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 | |
| 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>
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 44 | ||||
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.h | 2 | ||||
| -rw-r--r-- | drivers/infiniband/hw/nes/nes_hw.c | 42 |
3 files changed, 45 insertions, 43 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index c259ddc8dd88..f34fa6f77a81 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 | ||
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index 25e2493abc6a..3a20a7883976 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h | |||
| @@ -397,7 +397,7 @@ struct nes_cm_ops { | |||
| 397 | struct nes_cm_node *); | 397 | struct nes_cm_node *); |
| 398 | int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *, | 398 | int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *, |
| 399 | struct nes_cm_node *); | 399 | struct nes_cm_node *); |
| 400 | void (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *, | 400 | int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *, |
| 401 | struct sk_buff *); | 401 | struct sk_buff *); |
| 402 | int (*destroy_cm_core)(struct nes_cm_core *); | 402 | int (*destroy_cm_core)(struct nes_cm_core *); |
| 403 | int (*get)(struct nes_cm_core *); | 403 | int (*get)(struct nes_cm_core *); |
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 7c49cc882d75..8f70ff2dcc58 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
| @@ -2700,27 +2700,33 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) | |||
| 2700 | pkt_type, (pkt_type & NES_PKT_TYPE_APBVT_MASK)); */ | 2700 | pkt_type, (pkt_type & NES_PKT_TYPE_APBVT_MASK)); */ |
| 2701 | 2701 | ||
| 2702 | if ((pkt_type & NES_PKT_TYPE_APBVT_MASK) == NES_PKT_TYPE_APBVT_BITS) { | 2702 | if ((pkt_type & NES_PKT_TYPE_APBVT_MASK) == NES_PKT_TYPE_APBVT_BITS) { |
| 2703 | nes_cm_recv(rx_skb, nesvnic->netdev); | 2703 | if (nes_cm_recv(rx_skb, nesvnic->netdev)) |
| 2704 | rx_skb = NULL; | ||
| 2705 | } | ||
| 2706 | if (rx_skb == NULL) | ||
| 2707 | goto skip_rx_indicate0; | ||
| 2708 | |||
| 2709 | |||
| 2710 | if ((cqe_misc & NES_NIC_CQE_TAG_VALID) && | ||
| 2711 | (nesvnic->vlan_grp != NULL)) { | ||
| 2712 | vlan_tag = (u16)(le32_to_cpu( | ||
| 2713 | cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX]) | ||
| 2714 | >> 16); | ||
| 2715 | nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n", | ||
| 2716 | nesvnic->netdev->name, vlan_tag); | ||
| 2717 | if (nes_use_lro) | ||
| 2718 | lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb, | ||
| 2719 | nesvnic->vlan_grp, vlan_tag, NULL); | ||
| 2720 | else | ||
| 2721 | nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag); | ||
| 2704 | } else { | 2722 | } else { |
| 2705 | if ((cqe_misc & NES_NIC_CQE_TAG_VALID) && (nesvnic->vlan_grp != NULL)) { | 2723 | if (nes_use_lro) |
| 2706 | vlan_tag = (u16)(le32_to_cpu( | 2724 | lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL); |
| 2707 | cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX]) | 2725 | else |
| 2708 | >> 16); | 2726 | nes_netif_rx(rx_skb); |
| 2709 | nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n", | ||
| 2710 | nesvnic->netdev->name, vlan_tag); | ||
| 2711 | if (nes_use_lro) | ||
| 2712 | lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb, | ||
| 2713 | nesvnic->vlan_grp, vlan_tag, NULL); | ||
| 2714 | else | ||
| 2715 | nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag); | ||
| 2716 | } else { | ||
| 2717 | if (nes_use_lro) | ||
| 2718 | lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL); | ||
| 2719 | else | ||
| 2720 | nes_netif_rx(rx_skb); | ||
| 2721 | } | ||
| 2722 | } | 2727 | } |
| 2723 | 2728 | ||
| 2729 | skip_rx_indicate0: | ||
| 2724 | nesvnic->netdev->last_rx = jiffies; | 2730 | nesvnic->netdev->last_rx = jiffies; |
| 2725 | /* nesvnic->netstats.rx_packets++; */ | 2731 | /* nesvnic->netstats.rx_packets++; */ |
| 2726 | /* nesvnic->netstats.rx_bytes += rx_pkt_size; */ | 2732 | /* nesvnic->netstats.rx_bytes += rx_pkt_size; */ |
