diff options
author | Faisal Latif <faisal.latif@intel.com> | 2008-11-21 21:50:49 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-12-05 14:00:13 -0500 |
commit | 4a14f6a79f5110c6033f0c61d77d07c449c2d083 (patch) | |
tree | fe582f37fae182a2bec420e7af8312dfa8d01acb /drivers/infiniband/hw/nes/nes_cm.c | |
parent | 183ecfa3091cd4cdda329a7fe89d9544088f517d (diff) |
RDMA/nes: Forward packets for a new connection with stale APBVT entry
Under heavy traffic, there is a small windows when an APBVT entry is
not yet removed and a new connection is established. Packets for the
new connection are dropped until APBVT entry is removed. This patch
will forward the packets instead of dropping them.
Signed-off-by: Faisal Latif <faisal.latif@intel.com>
Signed-off-by: Chien Tung <chien.tin.tung@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/nes/nes_cm.c')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 44 |
1 files changed, 20 insertions, 24 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index c259ddc8dd8..f34fa6f77a8 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
@@ -86,7 +86,7 @@ static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *, | |||
86 | struct nes_cm_node *); | 86 | struct nes_cm_node *); |
87 | static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *, | 87 | static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *, |
88 | struct nes_cm_node *); | 88 | struct nes_cm_node *); |
89 | static void mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, | 89 | static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, |
90 | struct sk_buff *); | 90 | struct sk_buff *); |
91 | static int mini_cm_dealloc_core(struct nes_cm_core *); | 91 | static int mini_cm_dealloc_core(struct nes_cm_core *); |
92 | static int mini_cm_get(struct nes_cm_core *); | 92 | static int mini_cm_get(struct nes_cm_core *); |
@@ -2076,7 +2076,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod | |||
2076 | * recv_pkt - recv an ETHERNET packet, and process it through CM | 2076 | * recv_pkt - recv an ETHERNET packet, and process it through CM |
2077 | * node state machine | 2077 | * node state machine |
2078 | */ | 2078 | */ |
2079 | static void mini_cm_recv_pkt(struct nes_cm_core *cm_core, | 2079 | static int mini_cm_recv_pkt(struct nes_cm_core *cm_core, |
2080 | struct nes_vnic *nesvnic, struct sk_buff *skb) | 2080 | struct nes_vnic *nesvnic, struct sk_buff *skb) |
2081 | { | 2081 | { |
2082 | struct nes_cm_node *cm_node = NULL; | 2082 | struct nes_cm_node *cm_node = NULL; |
@@ -2084,23 +2084,16 @@ static void mini_cm_recv_pkt(struct nes_cm_core *cm_core, | |||
2084 | struct iphdr *iph; | 2084 | struct iphdr *iph; |
2085 | struct tcphdr *tcph; | 2085 | struct tcphdr *tcph; |
2086 | struct nes_cm_info nfo; | 2086 | struct nes_cm_info nfo; |
2087 | int skb_handled = 1; | ||
2087 | 2088 | ||
2088 | if (!skb) | 2089 | if (!skb) |
2089 | return; | 2090 | return 0; |
2090 | if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) { | 2091 | if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) { |
2091 | dev_kfree_skb_any(skb); | 2092 | return 0; |
2092 | return; | ||
2093 | } | 2093 | } |
2094 | 2094 | ||
2095 | iph = (struct iphdr *)skb->data; | 2095 | iph = (struct iphdr *)skb->data; |
2096 | tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr)); | 2096 | tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr)); |
2097 | skb_reset_network_header(skb); | ||
2098 | skb_set_transport_header(skb, sizeof(*tcph)); | ||
2099 | if (!tcph) { | ||
2100 | dev_kfree_skb_any(skb); | ||
2101 | return; | ||
2102 | } | ||
2103 | skb->len = ntohs(iph->tot_len); | ||
2104 | 2097 | ||
2105 | nfo.loc_addr = ntohl(iph->daddr); | 2098 | nfo.loc_addr = ntohl(iph->daddr); |
2106 | nfo.loc_port = ntohs(tcph->dest); | 2099 | nfo.loc_port = ntohs(tcph->dest); |
@@ -2121,23 +2114,21 @@ static void mini_cm_recv_pkt(struct nes_cm_core *cm_core, | |||
2121 | /* Only type of packet accepted are for */ | 2114 | /* Only type of packet accepted are for */ |
2122 | /* the PASSIVE open (syn only) */ | 2115 | /* the PASSIVE open (syn only) */ |
2123 | if ((!tcph->syn) || (tcph->ack)) { | 2116 | if ((!tcph->syn) || (tcph->ack)) { |
2124 | cm_packets_dropped++; | 2117 | skb_handled = 0; |
2125 | break; | 2118 | break; |
2126 | } | 2119 | } |
2127 | listener = find_listener(cm_core, nfo.loc_addr, | 2120 | listener = find_listener(cm_core, nfo.loc_addr, |
2128 | nfo.loc_port, | 2121 | nfo.loc_port, |
2129 | NES_CM_LISTENER_ACTIVE_STATE); | 2122 | NES_CM_LISTENER_ACTIVE_STATE); |
2130 | if (listener) { | 2123 | if (!listener) { |
2131 | nfo.cm_id = listener->cm_id; | 2124 | nfo.cm_id = NULL; |
2132 | nfo.conn_type = listener->conn_type; | 2125 | nfo.conn_type = 0; |
2133 | } else { | 2126 | nes_debug(NES_DBG_CM, "Unable to find listener for the pkt\n"); |
2134 | nes_debug(NES_DBG_CM, "Unable to find listener " | 2127 | skb_handled = 0; |
2135 | "for the pkt\n"); | ||
2136 | cm_packets_dropped++; | ||
2137 | dev_kfree_skb_any(skb); | ||
2138 | break; | 2128 | break; |
2139 | } | 2129 | } |
2140 | 2130 | nfo.cm_id = listener->cm_id; | |
2131 | nfo.conn_type = listener->conn_type; | ||
2141 | cm_node = make_cm_node(cm_core, nesvnic, &nfo, | 2132 | cm_node = make_cm_node(cm_core, nesvnic, &nfo, |
2142 | listener); | 2133 | listener); |
2143 | if (!cm_node) { | 2134 | if (!cm_node) { |
@@ -2163,9 +2154,13 @@ static void mini_cm_recv_pkt(struct nes_cm_core *cm_core, | |||
2163 | dev_kfree_skb_any(skb); | 2154 | dev_kfree_skb_any(skb); |
2164 | break; | 2155 | break; |
2165 | } | 2156 | } |
2157 | skb_reset_network_header(skb); | ||
2158 | skb_set_transport_header(skb, sizeof(*tcph)); | ||
2159 | skb->len = ntohs(iph->tot_len); | ||
2166 | process_packet(cm_node, skb, cm_core); | 2160 | process_packet(cm_node, skb, cm_core); |
2167 | rem_ref_cm_node(cm_core, cm_node); | 2161 | rem_ref_cm_node(cm_core, cm_node); |
2168 | } while (0); | 2162 | } while (0); |
2163 | return skb_handled; | ||
2169 | } | 2164 | } |
2170 | 2165 | ||
2171 | 2166 | ||
@@ -2985,15 +2980,16 @@ int nes_destroy_listen(struct iw_cm_id *cm_id) | |||
2985 | */ | 2980 | */ |
2986 | int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice) | 2981 | int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice) |
2987 | { | 2982 | { |
2983 | int rc = 0; | ||
2988 | cm_packets_received++; | 2984 | cm_packets_received++; |
2989 | if ((g_cm_core) && (g_cm_core->api)) { | 2985 | if ((g_cm_core) && (g_cm_core->api)) { |
2990 | g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb); | 2986 | rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb); |
2991 | } else { | 2987 | } else { |
2992 | nes_debug(NES_DBG_CM, "Unable to process packet for CM," | 2988 | nes_debug(NES_DBG_CM, "Unable to process packet for CM," |
2993 | " cm is not setup properly.\n"); | 2989 | " cm is not setup properly.\n"); |
2994 | } | 2990 | } |
2995 | 2991 | ||
2996 | return 0; | 2992 | return rc; |
2997 | } | 2993 | } |
2998 | 2994 | ||
2999 | 2995 | ||