Fix the frequent, power consuming wake-ups

This commit is contained in:
Petr Sabata 2011-05-04 17:49:39 +02:00
parent c639191703
commit e9225f8d60
4 changed files with 769 additions and 1 deletions

View File

@ -0,0 +1,256 @@
From aeb6d102f2b00c1799042cd02f079aa1f659d36c Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Wed, 4 May 2011 08:21:45 -0700
Subject: [PATCH 2/3] reduce number of select timeouts for ECP
A problem with the number of select timeouts has been reported in Redhat
bugzilla #694639 (https://bugzilla.redhat.com/show_bug.cgi?id=694639) and
by Will Cohen on the open-lldp mailing list.
The number of select timeouts for any running applications can be measured
with 'stap -c "sleep 10" timeout.stp'.
The high number of select timeouts was caused by the timers used in the ECP
code to control the timeout until when an ack has to be received and to
determine wether there is any work pending (e.g. changed profiles).
This patch changes the timers from calling them at a regular interval to a
demand based model. For this it is necessary to setup a short-running timer
whenever work has been scheduled. This way the execution path returns to the
event loop much more often leaving other modules a chance to get work done.
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.c | 104 ++++++++++++++++++++++++++++++++++++++++++++--------------
ecp/ecp.h | 7 +++-
ecp/ecp_tx.c | 8 ++++-
3 files changed, 91 insertions(+), 28 deletions(-)
diff --git a/ecp/ecp.c b/ecp/ecp.c
index ea3558d..b4d075e 100644
--- a/ecp/ecp.c
+++ b/ecp/ecp.c
@@ -37,9 +37,65 @@
#include "lldp/l2_packet.h"
#include "ecp/ecp.h"
-static int ecp_start_timer(struct vdp_data *vd);
+/* ecp_localchange_handler - triggers the processing of a local change
+ * @eloop_data: data structure of event loop
+ * @user_ctx: user context, vdp_data here
+ *
+ * no return value
+ *
+ * called from ecp_somethingchangedlocal when a change is pending. Calls
+ * the ECP tx station state machine. A oneshot handler. This detour is taken
+ * to not having to call the ecp code from the vdp state machine. Instead, we
+ * return to the event loop, giving other code a chance to do work.
+ */
+void ecp_localchange_handler(void *eloop_data, void *user_ctx)
+{
+ struct vdp_data *vd;
+
+ vd = (struct vdp_data *) user_ctx;
+
+ if (vd->ecp.tx.localChange) {
+ LLDPAD_DBG("%s(%i)-%s: ecp.tx.localChange %i!\n",
+ __func__, __LINE__,
+ vd->ifname, vd->ecp.tx.localChange);
+ ecp_tx_run_sm(vd);
+ }
+}
+
+/* ecp_start_localchange_timer - starts the ECP localchange timer
+ * @vd: vdp_data for the interface
+ *
+ * returns 0 on success, -1 on error
+ *
+ * starts the ECP localchange timer when a localchange has been signaled from
+ * the VDP state machine.
+ */
+int ecp_start_localchange_timer(struct vdp_data *vd)
+{
+ unsigned int usecs;
+
+ usecs = ECP_LOCALCHANGE_TIMEOUT;
+
+ return eloop_register_timeout(0, usecs, ecp_localchange_handler, NULL, (void *) vd);
+}
-/* ecp_timeout_handler - handles the timer expiry
+/* ecp_stop_localchange_timer - stop the ECP localchange timer
+ * @vd: vdp_data for the interface
+ *
+ * returns the number of removed handlers
+ *
+ * stops the ECP localchange timer. Used e.g. when the host interface goes down.
+ */
+static int ecp_stop_localchange_timer(struct vdp_data *vd)
+{
+ LLDPAD_DBG("%s(%i)-%s: stopping ecp localchange timer\n", __func__, __LINE__,
+ vd->ifname);
+
+ return eloop_cancel_timeout(ecp_localchange_handler, NULL, (void *) vd);
+}
+
+
+/* ecp_ack_timeout_handler - handles the ack timer expiry
* @eloop_data: data structure of event loop
* @user_ctx: user context, vdp_data here
*
@@ -47,58 +103,55 @@ static int ecp_start_timer(struct vdp_data *vd);
*
* called when the ECP timer has expired. Calls the ECP station state machine.
*/
-void ecp_timeout_handler(void *eloop_data, void *user_ctx)
+void ecp_ack_timeout_handler(void *eloop_data, void *user_ctx)
{
struct vdp_data *vd;
vd = (struct vdp_data *) user_ctx;
if (vd->ecp.ackTimer > 0)
- vd->ecp.ackTimer--;
+ vd->ecp.ackTimer -= ECP_ACK_TIMER_DEFAULT;
- if ((ecp_ackTimer_expired(vd) == true) ||
- vd->ecp.tx.localChange) {
+ if (ecp_ackTimer_expired(vd) == true) {
LLDPAD_DBG("%s(%i)-%s: ecp_ackTimer_expired (%i) !\n",
__func__, __LINE__, vd->ifname, vd->ecp.ackTimer);
- LLDPAD_DBG("%s(%i)-%s: ecp.tx.localChange %i!\n",
- __func__, __LINE__,
- vd->ifname, vd->ecp.tx.localChange);
ecp_tx_run_sm(vd);
+ } else {
+ LLDPAD_DBG("%s(%i)-%s: BUG ! handler called but"
+ "vdp->ecp.ackTimer not expired (%i) !\n",
+ __func__, __LINE__, vd->ecp.ackTimer);
}
-
- ecp_start_timer(vd);
}
-/* ecp_start_timer - starts the ECP timer
+/* ecp_start_ack_timer - starts the ECP ack timer
* @vd: vdp_data for the interface
*
* returns 0 on success, -1 on error
*
- * starts the ECP timer when the interface comes up.
+ * starts the ECP ack timer when a frame has been sent out.
*/
-static int ecp_start_timer(struct vdp_data *vd)
+int ecp_start_ack_timer(struct vdp_data *vd)
{
- unsigned int secs, usecs;
+ unsigned int usecs;
- secs = 0;
- usecs = ECP_TIMER_GRANULARITY;
+ usecs = ECP_ACK_TIMER_DEFAULT;
- return eloop_register_timeout(secs, usecs, ecp_timeout_handler, NULL, (void *) vd);
+ return eloop_register_timeout(0, usecs, ecp_ack_timeout_handler, NULL, (void *) vd);
}
-/* ecp_stop_timer - stop the ECP timer
+/* ecp_stop_ack_timer - stop the ECP ack timer
* @vd: vdp_data for the interface
*
* returns the number of removed handlers
*
- * stops the ECP timer. Used e.g. when the host interface goes down.
+ * stops the ECP ack timer. Used e.g. when the host interface goes down.
*/
-static int ecp_stop_timer(struct vdp_data *vd)
+int ecp_stop_ack_timer(struct vdp_data *vd)
{
- LLDPAD_DBG("%s(%i)-%s: stopping ecp timer\n", __func__, __LINE__,
+ LLDPAD_DBG("%s(%i)-%s: stopping ecp ack timer\n", __func__, __LINE__,
vd->ifname);
- return eloop_cancel_timeout(ecp_timeout_handler, NULL, (void *) vd);
+ return eloop_cancel_timeout(ecp_ack_timeout_handler, NULL, (void *) vd);
}
/* ecp_init - initialize ecp module
@@ -138,7 +191,7 @@ int ecp_init(char *ifname)
ecp_rx_change_state(vd, ECP_RX_IDLE);
ecp_rx_run_sm(vd);
- ecp_start_timer(vd);
+ ecp_somethingChangedLocal(vd, true);
return 0;
@@ -159,7 +212,8 @@ int ecp_deinit(char *ifname)
goto fail;
}
- ecp_stop_timer(vd);
+ ecp_stop_ack_timer(vd);
+ ecp_stop_localchange_timer(vd);
ecp_tx_stop_ackTimer(vd);
return 0;
diff --git a/ecp/ecp.h b/ecp/ecp.h
index c18b6d7..35fcf46 100644
--- a/ecp/ecp.h
+++ b/ecp/ecp.h
@@ -34,8 +34,11 @@
#define ECP_MAX_RETRIES 3
#define ECP_SEQUENCE_NR_START 0x0
-#define ECP_ACK_TIMER_DEFAULT 50 /* 500 ms in 10 ms chunks */
-#define ECP_TIMER_GRANULARITY 10000 /* 10 ms in us */
+#define MSECS 1000
+#define SECS 1000*MSECS
+
+#define ECP_ACK_TIMER_DEFAULT 500*MSECS /* 500 ms */
+#define ECP_LOCALCHANGE_TIMEOUT 1*MSECS /* 1 ms */
#define ECP_ACK_TIMER_STOPPED -1
diff --git a/ecp/ecp_tx.c b/ecp/ecp_tx.c
index ebf9e4b..ba96c6b 100644
--- a/ecp/ecp_tx.c
+++ b/ecp/ecp_tx.c
@@ -53,11 +53,13 @@ void ecp_somethingChangedLocal(struct vdp_data *vd, bool flag)
if (!vd)
return;
- LLDPAD_DBG("%s(%i): vd->ecp.tx.localChange to %s.", __func__,
+ LLDPAD_DBG("%s(%i): vd->ecp.tx.localChange to %s.\n", __func__,
__LINE__, (flag == true) ? "true" : "false");
vd->ecp.tx.localChange = flag;
+ ecp_start_localchange_timer(vd);
+
return;
}
@@ -288,6 +290,8 @@ void ecp_tx_stop_ackTimer(struct vdp_data *vd)
LLDPAD_DBG("%s(%i)-%s: stopped ecp ack timer\n", __func__, __LINE__,
vd->ifname);
+
+ ecp_stop_ack_timer(vd);
}
/* ecp_tx_start_ackTimer - starts the ECP ack timer
@@ -303,6 +307,8 @@ static void ecp_tx_start_ackTimer(struct vdp_data *vd)
LLDPAD_DBG("%s(%i)-%s: starting ecp ack timer\n", __func__, __LINE__,
vd->ifname);
+
+ ecp_start_ack_timer(vd);
}
/* ecp_ackTimer_expired - checks for expired ack timer
--
1.7.4.4

View File

@ -0,0 +1,432 @@
From 08a6ea57ef76248e439f94a77f74c80ab500d2db Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Wed, 4 May 2011 08:23:19 -0700
Subject: [PATCH 3/3] reduce number of select timeouts for VDP
A problem with the number of select timeouts has been reported in Redhat
bugzilla #694639 (https://bugzilla.redhat.com/show_bug.cgi?id=694639) and
by Will Cohen on the open-lldp mailing list.
The number of select timeouts for any running applications can be measured
with 'stap -c "sleep 10" timeout.stp'.
The high number of select timeouts was caused by the timers used in the VDP
code to control the ack and keepalive interval as well as to determine wether
there is any work pending (e.g. changed profiles or received acks).
This patch changes the timers from calling them at a regular interval to a
demand based model. For this it is necessary to setup a short-running timer
whenever work has been scheduled. This way the execution path returns to the
event loop much more often leaving other modules a chance to get work done.
Signed-off-by: Jens Osterkamp <jens@linux.vnet.ibm.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
include/lldp_vdp.h | 6 +-
lldp_vdp.c | 234 ++++++++++++++++++++++++++++++++-------------------
2 files changed, 150 insertions(+), 90 deletions(-)
diff --git a/include/lldp_vdp.h b/include/lldp_vdp.h
index 4b7054b..947ae31 100644
--- a/include/lldp_vdp.h
+++ b/include/lldp_vdp.h
@@ -64,11 +64,12 @@ static char *vsi_responses[] = {
#define VDP_MACVLAN_FORMAT_1 1
-#define VDP_TIMER_GRANULARITY 10000 /* 10 ms in us */
-#define VDP_KEEPALIVE_TIMER_DEFAULT 1000 /* 10s in 10ms chunks */
+#define VDP_TIMER_GRANULARITY 100*MSECS /* 100 ms */
+#define VDP_KEEPALIVE_TIMER_DEFAULT 10*SECS /* 10s */
#define VDP_ACK_TIMER_DEFAULT (2*ECP_ACK_TIMER_DEFAULT*ECP_MAX_RETRIES)
#define VDP_KEEPALIVE_TIMER_STOPPED -1
#define VDP_ACK_TIMER_STOPPED -1
+#define VDP_LOCALCHANGE_TIMEOUT 1*MSECS /* 1 ms */
#define VDP_ROLE_STATION 0
#define VDP_ROLE_BRIDGE 1
@@ -155,7 +156,6 @@ struct packed_tlv *vdp_gettlv(struct vdp_data *vd, struct vsi_profile *profile);
void vdp_vsi_sm_station(struct vsi_profile *profile);
struct vsi_profile *vdp_add_profile(struct vsi_profile *profile);
void vdp_somethingChangedLocal(struct vsi_profile *profile, bool mode);
-static int vdp_start_timer(struct vdp_data *vd);
#define MAC_ADDR_STRLEN 18
#define INSTANCE_STRLEN 36
diff --git a/lldp_vdp.c b/lldp_vdp.c
index 7be0b1c..4b2ce6a 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -143,8 +143,10 @@ void vdp_ack_profiles(struct vdp_data *vd, int seqnr)
struct vsi_profile *p;
LIST_FOREACH(p, &vd->profile_head, profile) {
- if (p->seqnr == seqnr)
+ if (p->seqnr == seqnr) {
p->ackReceived = true;
+ vdp_start_localchange_timer(p);
+ }
}
}
@@ -205,7 +207,13 @@ int vdp_vsis_pending(struct vdp_data *vd)
*/
void vdp_somethingChangedLocal(struct vsi_profile *profile, bool flag)
{
+ LLDPAD_DBG("%s(%i): setting profile->localChange to %s.\n",
+ __func__, __LINE__, (flag == true) ? "true" : "false");
+
profile->localChange = flag;
+
+ if (flag == true)
+ vdp_start_localchange_timer(profile);
}
/* vdp_keepaliveTimer_expired - checks for expired ack timer
@@ -234,147 +242,182 @@ static bool vdp_ackTimer_expired(struct vsi_profile *profile)
return (profile->ackTimer == 0);
}
-/* vdp_timeout_handler - handles the timer expiry
+/* vdp_localchange_handler - triggers in case of ackReceived or on vdp localchange
* @eloop_data: data structure of event loop
* @user_ctx: user context, vdp_data here
*
* no return value
*
- * called when the VDP timer has expired. Decrements ack and keepaliveTimer
- * and calls the VDP station state machine if necessary.
+ * called from vdp_somethingchangedlocal or vdp_ack_profiles when a change is
+ * pending. Calls the VDP station state machine. This detour is taken
+ * to not having to call the vdp code from the ecp state machine. Instead, we
+ * return to the event loop, giving other code a chance to do work.
*/
-void vdp_timeout_handler(void *eloop_data, void *user_ctx)
+void vdp_localchange_handler(void *eloop_data, void *user_ctx)
{
- struct vdp_data *vd;
struct vsi_profile *p;
- vd = (struct vdp_data *) user_ctx;
-
- vd->nroftimers--;
+ p = (struct vsi_profile *) user_ctx;
- LIST_FOREACH(p, &vd->profile_head, profile) {
- if (p->ackTimer > 0)
- p->ackTimer--;
-
- if (p->keepaliveTimer > 0)
- p->keepaliveTimer--;
-
- if (vdp_ackTimer_expired(p) ||
- vdp_keepaliveTimer_expired(p) ||
- p->ackReceived) {
- LLDPAD_DBG("%s(%i): profile 0x%02x\n",
- __func__, __LINE__, p->instance[15]);
- LLDPAD_DBG("%s(%i): vdp_ackTimer_expired %i\n",
- __func__, __LINE__, vdp_ackTimer_expired(p));
- LLDPAD_DBG("%s(%i): p->ackReceived %i\n",
- __func__, __LINE__, p->ackReceived);
- LLDPAD_DBG("%s(%i): vdp_keepaliveTimer_expired %i\n",
- __func__, __LINE__,
- vdp_keepaliveTimer_expired(p));
- vdp_vsi_sm_station(p);
- }
+ if ((p->ackReceived) || (p->localChange)) {
+ LLDPAD_DBG("%s(%i): p->localChange %i!\n",
+ __func__, __LINE__, p->localChange);
+ LLDPAD_DBG("%s(%i): p->ackReceived %i!\n",
+ __func__, __LINE__, p->ackReceived);
+ vdp_vsi_sm_station(p);
}
-
- vdp_start_timer(vd);
}
-/* vdp_stop_timer - stop the VDP timer
+/* vdp_start_localchange_timer - starts the VDP localchange timer
* @vd: vdp_data for the interface
*
- * returns the number of removed handlers
+ * returns 0 on success, -1 on error
*
- * stops the VDP timer. Used e.g. when the host interface goes down.
+ * starts the VPP localchange timer when a localchange has been signaled from
+ * the VDP state machine.
*/
-static int vdp_stop_timer(struct vdp_data *vd)
+int vdp_start_localchange_timer(struct vsi_profile *p)
{
- LLDPAD_DBG("%s(%i)-%s: stopping vdp timer\n", __func__, __LINE__,
- vd->ifname);
+ unsigned int usecs;
- vd->nroftimers--;
+ usecs = VDP_LOCALCHANGE_TIMEOUT;
- return eloop_cancel_timeout(vdp_timeout_handler, NULL, (void *) vd);
+ return eloop_register_timeout(0, usecs, vdp_localchange_handler, NULL, (void *) p);
}
-/* vdp_start_timer - starts the VDP timer
- * @vd: vdp_data for the interface
+/* vdp_ack_timeout_handler - handles the ack timer expiry
+ * @eloop_data: data structure of event loop
+ * @user_ctx: user context, vdp_data here
*
- * returns 0 on success, -1 on error
+ * no return value
*
- * starts the VDP timer when the interface comes up.
+ * called when the VDP ack timer for a profile has expired.
+ * Calls the VDP station state machine for the profile.
*/
-static int vdp_start_timer(struct vdp_data *vd)
+void vdp_ack_timeout_handler(void *eloop_data, void *user_ctx)
{
- unsigned int secs, usecs, rte;
-
- secs = 0;
- usecs = VDP_TIMER_GRANULARITY;
-
- vd->nroftimers++;
-
- if (vd->nroftimers > 1) {
- LLDPAD_WARN("%s(%i)-%s: nroftimers %i !\n", __func__, __LINE__,
- vd->ifname, vd->nroftimers);
- vd->nroftimers--;
- return 0;
+ struct vsi_profile *p = (struct vsi_profile *) user_ctx;
+
+ if (p->ackTimer > 0)
+ p->ackTimer -= VDP_ACK_TIMER_DEFAULT;
+
+ if (vdp_ackTimer_expired(p)) {
+ LLDPAD_DBG("%s(%i): profile 0x%02x\n",
+ __func__, __LINE__, p->instance[15]);
+ LLDPAD_DBG("%s(%i): vdp_ackTimer_expired %i\n",
+ __func__, __LINE__, vdp_ackTimer_expired(p));
+ LLDPAD_DBG("%s(%i): p->ackReceived %i\n",
+ __func__, __LINE__, p->ackReceived);
+ vdp_vsi_sm_station(p);
}
-
- return eloop_register_timeout(secs, usecs, vdp_timeout_handler, NULL, (void *) vd);
}
-/* vdp_start_ackTimer - starts the VDP ack timer
- * @profile: profile to process
+/* vdp_start_ack_timer - starts the VDP profile ack timer
+ * @profile: vsi_profile
+ *
+ * returns 0 on success, -1 on error
*
- * starts the ack timer when a frame has been sent out.
+ * starts the VDP profile ack timer when a profile has been handed to ecp for
+ * transmission.
*/
-static void vdp_start_ackTimer(struct vsi_profile *profile)
+static int vdp_start_ackTimer(struct vsi_profile *profile)
{
+ unsigned int usecs;
+
+ usecs = VDP_ACK_TIMER_DEFAULT;
+
profile->ackTimer = VDP_ACK_TIMER_DEFAULT;
LLDPAD_DBG("%s(%i)-%s: starting ack timer for 0x%02x (%i)\n",
__func__, __LINE__, profile->port->ifname,
profile->instance[15], profile->ackTimer);
+
+ return eloop_register_timeout(0, usecs, vdp_ack_timeout_handler, NULL, (void *) profile);
}
-/* vdp_start_keepaliveTimer - starts the VDP keepalive timer for a profile
- * @profile: profile to process
+/* vdp_stop_ackTimer - stops the VDP profile ack timer
+ * @vd: vdp_data for the interface
+ *
+ * returns the number of removed handlers
*
- * starts the keepalive timer when a frame has been sent out.
+ * stops the VDP tck imer. Used e.g. when the host interface goes down.
*/
-static void vdp_start_keepaliveTimer(struct vsi_profile *profile)
+static int vdp_stop_ackTimer(struct vsi_profile *profile)
{
- profile->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT;
-
- LLDPAD_DBG("%s(%i)-%s: starting keepalive timer for 0x%02x (%i)\n",
+ LLDPAD_DBG("%s(%i)-%s: stopping ack timer for 0x%02x (%i)\n",
__func__, __LINE__, profile->port->ifname,
- profile->instance[15], profile->keepaliveTimer);
+ profile->instance[15], profile->ackTimer);
+
+ return eloop_cancel_timeout(vdp_ack_timeout_handler, NULL, (void *) profile);
}
-/* vdp_stop_ackTimer - stops the VDP ack timer
- * @profile: profile to process
+/* vdp_keepalive_timeout_handler - handles the keepalive timer expiry
+ * @eloop_data: data structure of event loop
+ * @user_ctx: user context, vdp_data here
+ *
+ * no return value
*
- * stops the ack timer when a frame has been sent out.
+ * called when the VDP keepalive timer for a profile has expired.
+ * Calls the VDP station state machine for the profile.
*/
-static void vdp_stop_ackTimer(struct vsi_profile *profile)
+void vdp_keepalive_timeout_handler(void *eloop_data, void *user_ctx)
{
- profile->ackTimer = VDP_ACK_TIMER_STOPPED;
+ struct vsi_profile *p = (struct vsi_profile *) user_ctx;
+
+ if (p->keepaliveTimer > 0)
+ p->keepaliveTimer -= VDP_KEEPALIVE_TIMER_DEFAULT;
+
+ if (vdp_keepaliveTimer_expired(p)) {
+ LLDPAD_DBG("%s(%i): profile 0x%02x\n",
+ __func__, __LINE__, p->instance[15]);
+ LLDPAD_DBG("%s(%i): vdp_keepaliveTimer_expired %i\n",
+ __func__, __LINE__, vdp_keepaliveTimer_expired(p));
+ LLDPAD_DBG("%s(%i): p->ackReceived %i\n",
+ __func__, __LINE__, p->ackReceived);
+ vdp_vsi_sm_station(p);
+ }
+}
- LLDPAD_DBG("%s(%i)-%s: stopping ack timer for 0x%02x (%i)\n",
+/* vdp_start_keepalive_timer - starts the VDP profile keepalive timer
+ * @vd: vdp_data for the interface
+ *
+ * returns 0 on success, -1 on error
+ *
+ * starts the VDP profile keepalive timer when a profile has been handed to ecp for
+ * transmission.
+ */
+static int vdp_start_keepaliveTimer(struct vsi_profile *profile)
+{
+ unsigned int usecs;
+
+ usecs = VDP_KEEPALIVE_TIMER_DEFAULT;
+
+ profile->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT;
+
+ LLDPAD_DBG("%s(%i)-%s: starting keepalive timer for 0x%02x (%i)\n",
__func__, __LINE__, profile->port->ifname,
- profile->instance[15], profile->ackTimer);
+ profile->instance[15], profile->keepaliveTimer);
+
+ return eloop_register_timeout(0, usecs, vdp_keepalive_timeout_handler,
+ NULL, (void *) profile);
}
-/* vdp_stop_keepaliveTimer - stops the VDP keepalive timer for a profile
- * @profile: profile to process
+/* vdp_stop_keepalive_timer - stops the VDP profile keepalive timer
+ * @vd: vdp_data for the interface
+ *
+ * returns the number of removed handlers
*
- * stops the keepalive timer when a frame has been sent out.
+ * stops the VDP tck imer. Used e.g. when the host interface goes down.
*/
-static void vdp_stop_keepaliveTimer(struct vsi_profile *profile)
+static int vdp_stop_keepaliveTimer(struct vsi_profile *profile)
{
profile->keepaliveTimer = VDP_KEEPALIVE_TIMER_STOPPED;
LLDPAD_DBG("%s(%i)-%s: stopping keepalive timer for 0x%02x (%i)\n",
__func__, __LINE__, profile->port->ifname,
profile->instance[15], profile->keepaliveTimer);
+
+ return eloop_cancel_timeout(vdp_keepalive_timeout_handler, NULL, (void *) profile);
}
static bool vdp_vsi_negative_response(struct vsi_profile *profile)
@@ -560,6 +603,7 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
profile->response = VDP_RESPONSE_NO_RESPONSE;
if (profile->localChange) {
ecp_somethingChangedLocal(vd, true);
+ profile->ackReceived = false;
vdp_start_ackTimer(profile);
}
break;
@@ -573,6 +617,7 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
vdp_stop_keepaliveTimer(profile);
profile->response = VDP_RESPONSE_NO_RESPONSE;
if (profile->localChange) {
+ profile->ackReceived = false;
ecp_somethingChangedLocal(vd, true);
vdp_start_ackTimer(profile);
}
@@ -588,6 +633,7 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
vdp_stop_keepaliveTimer(profile);
profile->response = VDP_RESPONSE_NO_RESPONSE;
if (profile->localChange) {
+ profile->ackReceived = false;
ecp_somethingChangedLocal(vd, true);
vdp_start_ackTimer(profile);
}
@@ -1271,7 +1317,12 @@ void vdp_ifdown(char *ifname)
if (ecp_deinit(ifname))
goto out_err;
- vdp_stop_timer(vd);
+ LIST_FOREACH(p, &vd->profile_head, profile) {
+ if (p->ackTimer > 0)
+ vdp_stop_ackTimer(p);
+ if (p->keepaliveTimer > 0)
+ vdp_stop_keepaliveTimer(p);
+ }
LLDPAD_INFO("%s:%s vdp data removed\n", __func__, ifname);
return;
@@ -1291,10 +1342,11 @@ out_err:
*/
void vdp_ifup(char *ifname)
{
- char *p;
+ char *string;
struct vdp_data *vd;
struct vdp_user_data *ud;
struct port *port;
+ struct vsi_profile *p;
LLDPAD_DBG("%s(%i): starting VDP for if %s !\n", __func__, __LINE__, ifname);
@@ -1315,9 +1367,9 @@ void vdp_ifup(char *ifname)
vd->role = VDP_ROLE_STATION;
- if (!get_cfg(ifname, "vdp.role", (void *)&p,
+ if (!get_cfg(ifname, "vdp.role", (void *)&string,
CONFIG_TYPE_STRING)) {
- if (!strcasecmp(p, VAL_BRIDGE)) {
+ if (!strcasecmp(string, VAL_BRIDGE)) {
vd->role = VDP_ROLE_BRIDGE;
}
}
@@ -1356,7 +1408,15 @@ out_start_again:
LLDPAD_DBG("%s(%i)-%s: starting vdp timer (%i)\n", __func__, __LINE__,
vd->ifname, vd->nroftimers);
- vdp_start_timer(vd);
+
+ LIST_FOREACH(p, &vd->profile_head, profile) {
+ if (p->ackTimer > 0) {
+ vdp_somethingChangedLocal(p, true);
+ vdp_start_ackTimer(p);
+ }
+ if (p->keepaliveTimer > 0)
+ vdp_start_keepaliveTimer(p);
+ }
LLDPAD_DBG("%s:%s vdp added\n", __func__, ifname);
return;
--
1.7.4.4

View File

@ -0,0 +1,71 @@
From 76dbd2e24ff64fe7ae1503c658614e44a0a4e2e4 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Wed, 4 May 2011 08:21:42 -0700
Subject: [PATCH 1/3] support disabling of LLDP on switch side
In case LLDP is disabled on the switch side, the switch will send a LLDP
frame with chassis, port and TTL with TTL set to 0.
In this case evb_mibdelete is called to reset the previously negotiated EVB
data.
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>
---
lldp_evb.c | 33 +++++++++++++++++++++++++++++++++
1 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/lldp_evb.c b/lldp_evb.c
index 0839054..b3d756b 100644
--- a/lldp_evb.c
+++ b/lldp_evb.c
@@ -594,6 +594,38 @@ out_err:
return;
}
+u8 evb_mibdelete(struct port *port)
+{
+ struct evb_data *ed;
+
+ if (!is_tlv_txenabled(port->ifname, TLVID_8021Qbg(LLDP_EVB_SUBTYPE))) {
+ goto out_err;
+ }
+
+ LLDPAD_DBG("%s(%i): mibdelete triggered for port %s.\n", __func__,
+ __LINE__, port->ifname);
+
+ ed = evb_data(port->ifname);
+ if (!ed) {
+ LLDPAD_DBG("%s:%s does not exist.\n", __func__, port->ifname);
+ goto out_err;
+ }
+
+ free(ed->tie);
+ free(ed->last);
+ free(ed->policy);
+
+ if (evb_init_cfg_tlv(ed)) {
+ LLDPAD_ERR("%s:%s evb_init_cfg_tlv failed\n", __func__, port->ifname);
+ goto out_err;
+ }
+
+ evb_bld_tlv(ed);
+
+out_err:
+ return 0;
+}
+
static const struct lldp_mod_ops evb_ops = {
.lldp_mod_register = evb_register,
.lldp_mod_unregister = evb_unregister,
@@ -601,6 +633,7 @@ static const struct lldp_mod_ops evb_ops = {
.lldp_mod_rchange = evb_rchange,
.lldp_mod_ifup = evb_ifup,
.lldp_mod_ifdown = evb_ifdown,
+ .lldp_mod_mibdelete = evb_mibdelete,
.get_arg_handler = evb_get_arg_handlers,
};
--
1.7.4.4

View File

@ -1,6 +1,6 @@
Name: lldpad
Version: 0.9.41
Release: 2%{?dist}
Release: 3%{?dist}
Summary: Intel LLDP Agent
Group: System Environment/Daemons
@ -64,6 +64,9 @@ Patch148: lldpad-0.9.41-lldpad-dormantTimer-should-not-be-touched-by-modul
Patch149: lldpad-0.9.41-lldpad-dcbx-dropped-ifdown-messages-breaks-module.patch
Patch150: lldpad-0.9.41-lldpad-DCB-remove-iSCSI-tc-qdisc-and-filters.patch
Patch151: lldpad-0.9.41-lldpad-make-debug-messages-from-netlink-path-helpful.patch
Patch152: lldpad-0.9.41-support-disabling-of-LLDP-on-switch-side.patch
Patch153: lldpad-0.9.41-reduce-number-of-select-timeouts-for-ECP.patch
Patch154: lldpad-0.9.41-reduce-number-of-select-timeouts-for-VDP.patch
Requires: kernel >= 2.6.32
BuildRequires: libconfig-devel >= 1.3.2 kernel-headers >= 2.6.32
@ -145,6 +148,9 @@ that use %{name}.
%patch149 -p1
%patch150 -p1
%patch151 -p1
%patch152 -p1
%patch153 -p1
%patch154 -p1
# Fedora patches on top of that...
%patch0 -p1 -b .make
%patch1 -p1 -b .init
@ -211,6 +217,9 @@ fi
%changelog
* Wed May 4 2011 Petr Sabata <psabata@redhat.com> - 0.9.41-3
- Fix the frequent, power consuming lldpad wake-ups (rhbz#701943)
* Thu Apr 21 2011 Petr Sabata <psabata@redhat.com> - 0.9.41-2
- Bring in upstream 802.1Qbg bugfixes