404 lines
12 KiB
Diff
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
|
|
|