Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4a14f6a7 authored by Faisal Latif's avatar Faisal Latif Committed by Roland Dreier
Browse files

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: default avatarFaisal Latif <faisal.latif@intel.com>
Signed-off-by: default avatarChien Tung <chien.tin.tung@intel.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 183ecfa3
Loading
Loading
Loading
Loading
+20 −24
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ static int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *,
	struct nes_cm_node *);
static int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *,
	struct nes_cm_node *);
static void mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
static int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *,
	struct sk_buff *);
static int mini_cm_dealloc_core(struct nes_cm_core *);
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
 * recv_pkt - recv an ETHERNET packet, and process it through CM
 * node state machine
 */
static void mini_cm_recv_pkt(struct nes_cm_core *cm_core,
static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
	struct nes_vnic *nesvnic, struct sk_buff *skb)
{
	struct nes_cm_node *cm_node = NULL;
@@ -2084,23 +2084,16 @@ static void mini_cm_recv_pkt(struct nes_cm_core *cm_core,
	struct iphdr *iph;
	struct tcphdr *tcph;
	struct nes_cm_info nfo;
	int skb_handled = 1;

	if (!skb)
		return;
		return 0;
	if (skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) {
		dev_kfree_skb_any(skb);
		return;
		return 0;
	}

	iph = (struct iphdr *)skb->data;
	tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr));
	skb_reset_network_header(skb);
	skb_set_transport_header(skb, sizeof(*tcph));
	if (!tcph) {
		dev_kfree_skb_any(skb);
		return;
	}
	skb->len = ntohs(iph->tot_len);

	nfo.loc_addr = ntohl(iph->daddr);
	nfo.loc_port = ntohs(tcph->dest);
@@ -2121,23 +2114,21 @@ static void mini_cm_recv_pkt(struct nes_cm_core *cm_core,
			/* Only type of packet accepted are for */
			/* the PASSIVE open (syn only) */
			if ((!tcph->syn) || (tcph->ack)) {
				cm_packets_dropped++;
				skb_handled = 0;
				break;
			}
			listener = find_listener(cm_core, nfo.loc_addr,
				nfo.loc_port,
				NES_CM_LISTENER_ACTIVE_STATE);
			if (listener) {
				nfo.cm_id = listener->cm_id;
				nfo.conn_type = listener->conn_type;
			} else {
				nes_debug(NES_DBG_CM, "Unable to find listener "
					"for the pkt\n");
				cm_packets_dropped++;
				dev_kfree_skb_any(skb);
			if (!listener) {
				nfo.cm_id = NULL;
				nfo.conn_type = 0;
				nes_debug(NES_DBG_CM, "Unable to find listener for the pkt\n");
				skb_handled = 0;
				break;
			}

			nfo.cm_id = listener->cm_id;
			nfo.conn_type = listener->conn_type;
			cm_node = make_cm_node(cm_core, nesvnic, &nfo,
				listener);
			if (!cm_node) {
@@ -2163,9 +2154,13 @@ static void mini_cm_recv_pkt(struct nes_cm_core *cm_core,
			dev_kfree_skb_any(skb);
			break;
		}
		skb_reset_network_header(skb);
		skb_set_transport_header(skb, sizeof(*tcph));
		skb->len = ntohs(iph->tot_len);
		process_packet(cm_node, skb, cm_core);
		rem_ref_cm_node(cm_core, cm_node);
	} while (0);
	return skb_handled;
}


@@ -2985,15 +2980,16 @@ int nes_destroy_listen(struct iw_cm_id *cm_id)
 */
int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice)
{
	int rc = 0;
	cm_packets_received++;
	if ((g_cm_core) && (g_cm_core->api)) {
		g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb);
		rc = g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb);
	} else {
		nes_debug(NES_DBG_CM, "Unable to process packet for CM,"
				" cm is not setup properly.\n");
	}

	return 0;
	return rc;
}


+1 −1
Original line number Diff line number Diff line
@@ -397,7 +397,7 @@ struct nes_cm_ops {
			struct nes_cm_node *);
	int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *,
			struct nes_cm_node *);
	void (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *,
	int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *,
			struct sk_buff *);
	int (*destroy_cm_core)(struct nes_cm_core *);
	int (*get)(struct nes_cm_core *);
+24 −18
Original line number Diff line number Diff line
@@ -2700,9 +2700,15 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
							pkt_type, (pkt_type & NES_PKT_TYPE_APBVT_MASK)); */

				if ((pkt_type & NES_PKT_TYPE_APBVT_MASK) == NES_PKT_TYPE_APBVT_BITS) {
					nes_cm_recv(rx_skb, nesvnic->netdev);
				} else {
					if ((cqe_misc & NES_NIC_CQE_TAG_VALID) && (nesvnic->vlan_grp != NULL)) {
					if (nes_cm_recv(rx_skb, nesvnic->netdev))
						rx_skb = NULL;
				}
				if (rx_skb == NULL)
					goto skip_rx_indicate0;


				if ((cqe_misc & NES_NIC_CQE_TAG_VALID) &&
				    (nesvnic->vlan_grp != NULL)) {
					vlan_tag = (u16)(le32_to_cpu(
							cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX])
							>> 16);
@@ -2719,8 +2725,8 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
					else
						nes_netif_rx(rx_skb);
				}
				}

skip_rx_indicate0:
				nesvnic->netdev->last_rx = jiffies;
				/* nesvnic->netstats.rx_packets++; */
				/* nesvnic->netstats.rx_bytes += rx_pkt_size; */