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