lldpad/lldpad-0.9.41-rework-ecp-timer-code-towards-newer-drafts.patch
2011-04-21 09:10:21 +02:00

404 lines
12 KiB
Diff

From 1ce3f72873d392b55147d96cc38eda30b3e39de1 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:38:17 -0800
Subject: [PATCH 16/51] rework ecp timer code towards newer drafts
This reworks the timer code towards the using one single timer for
the ECP module which now counts down one timer, and may count down more
later like it was changed for the VDP module. It reduces the code path
before returning to the event loop and prepares us for extension of the
ECP code towards newer drafts.
Minor simplification: kick out one (almost empty) function.
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 | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++-
ecp/ecp.h | 7 ++++-
ecp/ecp_rx.c | 33 ++++++++----------------
ecp/ecp_tx.c | 60 ++++++++++++++++-----------------------------
include/lldp_vdp.h | 2 +-
lldp_vdp.c | 3 --
6 files changed, 106 insertions(+), 67 deletions(-)
diff --git a/ecp/ecp.c b/ecp/ecp.c
index 3f64292..ea3558d 100644
--- a/ecp/ecp.c
+++ b/ecp/ecp.c
@@ -37,6 +37,70 @@
#include "lldp/l2_packet.h"
#include "ecp/ecp.h"
+static int ecp_start_timer(struct vdp_data *vd);
+
+/* ecp_timeout_handler - handles the timer expiry
+ * @eloop_data: data structure of event loop
+ * @user_ctx: user context, vdp_data here
+ *
+ * no return value
+ *
+ * called when the ECP timer has expired. Calls the ECP station state machine.
+ */
+void ecp_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--;
+
+ if ((ecp_ackTimer_expired(vd) == true) ||
+ vd->ecp.tx.localChange) {
+ 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);
+ }
+
+ ecp_start_timer(vd);
+}
+
+/* ecp_start_timer - starts the ECP timer
+ * @vd: vdp_data for the interface
+ *
+ * returns 0 on success, -1 on error
+ *
+ * starts the ECP timer when the interface comes up.
+ */
+static int ecp_start_timer(struct vdp_data *vd)
+{
+ unsigned int secs, usecs;
+
+ secs = 0;
+ usecs = ECP_TIMER_GRANULARITY;
+
+ return eloop_register_timeout(secs, usecs, ecp_timeout_handler, NULL, (void *) vd);
+}
+
+/* ecp_stop_timer - stop the ECP 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.
+ */
+static int ecp_stop_timer(struct vdp_data *vd)
+{
+ LLDPAD_DBG("%s(%i)-%s: stopping ecp timer\n", __func__, __LINE__,
+ vd->ifname);
+
+ return eloop_cancel_timeout(ecp_timeout_handler, NULL, (void *) vd);
+}
+
/* ecp_init - initialize ecp module
* @ifname: interface for which the module is initialized
*
@@ -71,10 +135,11 @@ int ecp_init(char *ifname)
goto fail;
}
- ecp_tx_run_sm(vd);
ecp_rx_change_state(vd, ECP_RX_IDLE);
ecp_rx_run_sm(vd);
+ ecp_start_timer(vd);
+
return 0;
fail:
@@ -94,6 +159,7 @@ int ecp_deinit(char *ifname)
goto fail;
}
+ ecp_stop_timer(vd);
ecp_tx_stop_ackTimer(vd);
return 0;
diff --git a/ecp/ecp.h b/ecp/ecp.h
index 7fbfa58..c18b6d7 100644
--- a/ecp/ecp.h
+++ b/ecp/ecp.h
@@ -34,7 +34,10 @@
#define ECP_MAX_RETRIES 3
#define ECP_SEQUENCE_NR_START 0x0
-#define ECP_ACK_TIMER_DEFAULT 500000 /* 500 ms in us */
+#define ECP_ACK_TIMER_DEFAULT 50 /* 500 ms in 10 ms chunks */
+#define ECP_TIMER_GRANULARITY 10000 /* 10 ms in us */
+
+#define ECP_ACK_TIMER_STOPPED -1
typedef enum {
ECP_REQUEST = 0,
@@ -46,7 +49,7 @@ struct ecp {
int sequence;
int retries;
int ackReceived;
- int ackTimerExpired;
+ int ackTimer;
u16 lastSequence;
u16 seqECPDU;
struct portrx rx;
diff --git a/ecp/ecp_rx.c b/ecp/ecp_rx.c
index 6bd6237..ff391e5 100644
--- a/ecp/ecp_rx.c
+++ b/ecp/ecp_rx.c
@@ -50,7 +50,7 @@ void ecp_rx_Initialize(struct vdp_data *vd)
vd->ecp.rx.rcvFrame = false;
vd->ecp.rx.badFrame = false;
- vd->ecp.ackReceived = 0;
+ vd->ecp.ackReceived = false;
if (vd->ecp.rx.framein) {
free(vd->ecp.rx.framein);
@@ -258,16 +258,19 @@ void ecp_rx_ReceiveFrame(void *ctx, unsigned int ifindex, const u8 *buf, size_t
vd->ecp.seqECPDU = ntohs(ecp_hdr->seqnr);
+ ecp_print_framein(vd);
+
switch(ecp_hdr->mode) {
case ECP_REQUEST:
+ LLDPAD_DBG("%s(%i)-%s: received REQ frame \n",
+ __func__, __LINE__, vd->ifname);
vd->ecp.ackReceived = false;
- ecp_print_framein(vd);
ecp_rx_run_sm(vd);
break;
case ECP_ACK:
+ LLDPAD_DBG("%s(%i)-%s: received ACK frame \n",
+ __func__, __LINE__, vd->ifname);
vd->ecp.ackReceived = true;
- LLDPAD_DBG("%s(%i)-%s: received ack frame \n", __func__, __LINE__, vd->ifname);
- ecp_print_framein(vd);
vdp_ack_profiles(vd, vd->ecp.seqECPDU);
ecp_tx_run_sm(vd);
vd->ecp.ackReceived = false;
@@ -280,7 +283,7 @@ void ecp_rx_ReceiveFrame(void *ctx, unsigned int ifindex, const u8 *buf, size_t
ecp_rx_freeFrame(vd);
}
-/* ecp_rx_validateFrame - validates received frame
+/* ecp_rx_validate_frame - validates received frame
* @vd: vdp_data used by ecp
*
* no return value
@@ -288,7 +291,7 @@ void ecp_rx_ReceiveFrame(void *ctx, unsigned int ifindex, const u8 *buf, size_t
* checks wether received frame has correct subtype and mode
*/
-void ecp_rx_validateFrame(struct vdp_data *vd)
+void ecp_rx_validate_frame(struct vdp_data *vd)
{
u16 tlv_offset = 0;
struct ecp_hdr *ecp_hdr;
@@ -331,21 +334,6 @@ void ecp_rx_validateFrame(struct vdp_data *vd)
vd->ecp.seqECPDU = ntohs(ecp_hdr->seqnr);
}
-/* ecp_rx_validate_frame - wrapper around ecp_rx_validateFrame
- * @vd: currently used port
- *
- * no return value
- *
- * sets rcvFrame to false and validates frame. used in ECP_RX_RECEIVE_ECPDU
- * state of ecp_rx_run_sm
- */
-void ecp_rx_validate_frame(struct vdp_data *vd)
-{
- vd->ecp.rx.rcvFrame = false;
- ecp_rx_validateFrame(vd);
- return;
-}
-
/* ecp_rx_ProcessFrame - process received ecp frames
* @vd: currently used port
*
@@ -412,7 +400,7 @@ void ecp_rx_ProcessFrame(struct vdp_data *vd)
if (!tlv) {
LLDPAD_ERR("ERROR: Failed to malloc space for "
- "incoming TLV. \n");
+ "incoming TLV. \n");
goto out;
}
@@ -602,6 +590,7 @@ void ecp_rx_run_sm(struct vdp_data *vd)
case ECP_RX_RECEIVE_WAIT:
break;
case ECP_RX_RECEIVE_ECPDU:
+ vd->ecp.rx.rcvFrame = false;
ecp_rx_validate_frame(vd);
break;
case ECP_RX_SEND_ACK:
diff --git a/ecp/ecp_tx.c b/ecp/ecp_tx.c
index cc3cc51..05c4818 100644
--- a/ecp/ecp_tx.c
+++ b/ecp/ecp_tx.c
@@ -221,7 +221,7 @@ void ecp_tx_Initialize(struct vdp_data *vd)
vd->ecp.tx.localChange = true;
vd->ecp.lastSequence = ECP_SEQUENCE_NR_START;
vd->ecp.stats.statsFramesOutTotal = 0;
- vd->ecp.ackTimerExpired = false;
+ vd->ecp.ackTimer = ECP_ACK_TIMER_STOPPED;
vd->ecp.retries = 0;
struct port *port = port_find_by_name(vd->ifname);
@@ -271,29 +271,6 @@ void ecp_tx_create_frame(struct vdp_data *vd)
return;
}
-/* ecp_timeout_handler - handles the ack timer expiry
- * @eloop_data: data structure of event loop
- * @user_ctx: user context, port here
- *
- * no return value
- *
- * called when the ECP ack timer has expired. sets a flag and calls the ECP
- * state machine.
- */
-static void ecp_tx_timeout_handler(void *eloop_data, void *user_ctx)
-{
- struct vdp_data *vd;
-
- vd = (struct vdp_data *) user_ctx;
-
- vd->ecp.ackTimerExpired = true;
-
- LLDPAD_DBG("%s(%i)-%s: timer expired\n", __func__, __LINE__,
- vd->ifname);
-
- ecp_tx_run_sm(vd);
-}
-
/* ecp_tx_stop_ackTimer - stop the ECP ack timer
* @vd: currently used port
*
@@ -302,16 +279,16 @@ static void ecp_tx_timeout_handler(void *eloop_data, void *user_ctx)
* stops the ECP ack timer. used when a ack frame for the port has been
* received.
*/
-int ecp_tx_stop_ackTimer(struct vdp_data *vd)
+void ecp_tx_stop_ackTimer(struct vdp_data *vd)
{
- LLDPAD_DBG("%s(%i)-%s: stopping timer\n", __func__, __LINE__,
- vd->ifname);
+ vd->ecp.ackTimer = ECP_ACK_TIMER_STOPPED;
- return eloop_cancel_timeout(ecp_tx_timeout_handler, NULL, (void *) vd);
+ LLDPAD_DBG("%s(%i)-%s: stopped ecp ack timer\n", __func__, __LINE__,
+ vd->ifname);
}
/* ecp_tx_start_ackTimer - starts the ECP ack timer
- * @profile: profile to process
+ * @vd: vdp_data to process
*
* returns 0 on success, -1 on error
*
@@ -319,17 +296,22 @@ int ecp_tx_stop_ackTimer(struct vdp_data *vd)
*/
static void ecp_tx_start_ackTimer(struct vdp_data *vd)
{
- unsigned int secs, usecs, rte;
-
- vd->ecp.ackTimerExpired = false;
+ vd->ecp.ackTimer = ECP_ACK_TIMER_DEFAULT;
- secs = 0;
- usecs = ECP_ACK_TIMER_DEFAULT;
-
- LLDPAD_DBG("%s(%i)-%s: starting timer\n", __func__, __LINE__,
+ LLDPAD_DBG("%s(%i)-%s: starting ecp ack timer\n", __func__, __LINE__,
vd->ifname);
+}
- eloop_register_timeout(secs, usecs, ecp_tx_timeout_handler, NULL, (void *) vd);
+/* ecp_ackTimer_expired - checks for expired ack timer
+ * @vd: vdp_data for interface
+ *
+ * returns true or false
+ *
+ * returns true if ack timer has expired, false otherwise.
+ */
+bool ecp_ackTimer_expired(struct vdp_data *vd)
+{
+ return (vd->ecp.ackTimer == 0);
}
/* ecp_tx_change_state - changes the ecp tx sm state
@@ -410,7 +392,7 @@ static bool ecp_set_tx_state(struct vdp_data *vd)
ecp_tx_change_state(vd, ECP_TX_WAIT_FOR_ACK);
return false;
case ECP_TX_WAIT_FOR_ACK:
- if (vd->ecp.ackTimerExpired) {
+ if (ecp_ackTimer_expired(vd)) {
vd->ecp.retries++;
if (vd->ecp.retries < ECP_MAX_RETRIES) {
ecp_somethingChangedLocal(vd);
@@ -420,6 +402,7 @@ static bool ecp_set_tx_state(struct vdp_data *vd)
if (vd->ecp.retries == ECP_MAX_RETRIES) {
LLDPAD_DBG("%s(%i)-%s: 1 \n", __func__, __LINE__,
vd->ifname);
+ ecp_tx_stop_ackTimer(vd);
ecp_tx_change_state(vd, ECP_TX_REQUEST_PDU);
return true;
}
@@ -463,6 +446,7 @@ void ecp_tx_run_sm(struct vdp_data *vd)
case ECP_TX_TRANSMIT_ECPDU:
ecp_tx_create_frame(vd);
ecp_tx_start_ackTimer(vd);
+ vd->ecp.tx.localChange = false;
break;
case ECP_TX_WAIT_FOR_ACK:
if (vd->ecp.ackReceived) {
diff --git a/include/lldp_vdp.h b/include/lldp_vdp.h
index 031337d..60d87c9 100644
--- a/include/lldp_vdp.h
+++ b/include/lldp_vdp.h
@@ -66,7 +66,7 @@ static char *vsi_responses[] = {
#define VDP_TIMER_GRANULARITY 10000 /* 10 ms in us */
#define VDP_KEEPALIVE_TIMER_DEFAULT 1000 /* 10s in 10ms chunks */
-#define VDP_ACK_TIMER_DEFAULT 2*ECP_ACK_TIMER_DEFAULT*ECP_MAX_RETRIES/VDP_TIMER_GRANULARITY
+#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
diff --git a/lldp_vdp.c b/lldp_vdp.c
index 52768fe..980eaaf 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -512,7 +512,6 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
if (profile->localChange) {
ecp_somethingChangedLocal(vd);
vdp_start_ackTimer(profile);
- ecp_tx_run_sm(vd);
}
break;
case VSI_ASSOCIATED:
@@ -527,7 +526,6 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
if (profile->localChange) {
ecp_somethingChangedLocal(vd);
vdp_start_ackTimer(profile);
- ecp_tx_run_sm(vd);
}
break;
case VSI_PREASSOCIATED:
@@ -542,7 +540,6 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
if (profile->localChange) {
ecp_somethingChangedLocal(vd);
vdp_start_ackTimer(profile);
- ecp_tx_run_sm(vd);
}
break;
case VSI_EXIT:
--
1.7.4.4