Blob Blame History Raw
From 4749b5abad3dabb802b34dddf6dbfb9ac6d180ff Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:39:05 -0800
Subject: [PATCH 22/51] prevent "forgotten" ECP frame for vsi type

We have seen cases where an ecp frame for a profile is "forgotten" to be
sent out if the ecp tx state machine is still waiting for an ack for a
previous frame.

The sequence which leads to this is as follows:

1) ecp frame for vsi type 1 is sent out
2) ecp tx state machine is switched to ECP_TX_WAIT_FOR_ACK_FRAME
3) keepalive timer for vsi type 2 times out, vsi type 2 is marked fo
4) ecp tx state machine switches to ECP_TX_REQUEST_PDU
5) ecp frame for vsi type 2 is not sent out
6) vdp ack timer for vsi type 2 times out
7) vsi type 2 is removed

It can take between hours and days until this behaviour can be observed.
This patch fixes it by checking for pending vsi type when switching to
ECP_TX_REQUEST_PDU.

Signed-off-by: Jens Osterkamp <jens@linux.vnet.ibm.com>
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
 ecp/ecp_tx.c |    7 ++++++-
 lldp_vdp.c   |   20 ++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/ecp/ecp_tx.c b/ecp/ecp_tx.c
index 99d5cae..ebf9e4b 100644
--- a/ecp/ecp_tx.c
+++ b/ecp/ecp_tx.c
@@ -53,7 +53,7 @@ void ecp_somethingChangedLocal(struct vdp_data *vd, bool flag)
 	if (!vd)
 		return;
 
-	LLDPAD_DBG("%s(%i): setting vd->ecp.tx.localChange to %s.", __func__,
+	LLDPAD_DBG("%s(%i): vd->ecp.tx.localChange to %s.", __func__,
 		   __LINE__, (flag == true) ? "true" : "false");
 
 	vd->ecp.tx.localChange = flag;
@@ -412,6 +412,11 @@ static bool ecp_set_tx_state(struct vdp_data *vd)
 		}
 		if (vd->ecp.ackReceived && vd->ecp.seqECPDU == vd->ecp.lastSequence) {
 			vd->ecp.ackReceived = false;
+			if (vdp_vsis_pending(vd)) {
+				LLDPAD_DBG("%s(%i)-%s: still work pending !\n",
+					   __func__, __LINE__, vd->ifname);
+				ecp_somethingChangedLocal(vd, true);
+			}
 			ecp_tx_change_state(vd, ECP_TX_REQUEST_PDU);
 			return true;
 		}
diff --git a/lldp_vdp.c b/lldp_vdp.c
index e6ee7e8..b3c7726 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -149,6 +149,26 @@ void vdp_ack_profiles(struct vdp_data *vd, int seqnr)
 
 }
 
+/* vdp_vsis_pending - check for pending VSIs
+ * @vd: vdp data for the interface
+ *
+ * returns the number of VSIs found
+ *
+ * walk through the list of VSIs and return the count.
+ */
+int vdp_vsis_pending(struct vdp_data *vd)
+{
+	struct vsi_profile *p;
+	int count = 0;
+
+	LIST_FOREACH(p, &vd->profile_head, profile) {
+		if (p->localChange && (p->ackReceived == false))
+			count++;
+	}
+
+	return count;
+}
+
 /* vdp_somethingChangedLocal - set flag if profile has changed
  * @profile: profile to set the flag for
  * @flag: set the flag to true or false
-- 
1.7.4.4