Requires patches

This commit is contained in:
Petr Sabata 2011-04-21 09:10:21 +02:00
parent b63f87477c
commit c639191703
51 changed files with 5478 additions and 0 deletions

View File

@ -0,0 +1,25 @@
From 937d571370f2e2f2175d5910d2ca8a68a8d65920 Mon Sep 17 00:00:00 2001
From: Ross Brattain <ross.b.brattain@intel.com>
Date: Mon, 28 Feb 2011 17:07:58 -0800
Subject: [PATCH 09/51] Fix README mailing list address.
Signed-off-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
README | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/README b/README
index 5485518..2be674a 100644
--- a/README
+++ b/README
@@ -556,5 +556,5 @@ Support
=======
Contact Information:
- e1000-eedc Mailing List <e1000-eedc@lists.sourceforge.net>
+ LLDP-devel Mailing List <lldp-devel@open-lldp.org>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
--
1.7.4.4

View File

@ -0,0 +1,56 @@
From 91c351053a59846d7baac09af5a4c9fa3cc83f36 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Wed, 6 Apr 2011 08:33:53 -0700
Subject: [PATCH 28/51] add a vdp_vsi to count nr of VSIs
This adds a function to the VDP code which allows to query the number of
currently available VSIs for an interface.
This is used in the rework of the EVB TLV code to include the number of
configured VSIs in the TLV.
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_vdp.c | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/lldp_vdp.c b/lldp_vdp.c
index 9b1d222..d1adb66 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -149,6 +149,31 @@ void vdp_ack_profiles(struct vdp_data *vd, int seqnr)
}
+/* vdp_vsis - find out number of VSIs for this interface
+ * @ifname: interfac name
+ *
+ * returns the number of VSIs
+ *
+ * walk through the list of VSIs and return the count.
+ */
+int vdp_vsis(char *ifname)
+{
+ struct vdp_data *vd;
+ struct vsi_profile *p;
+ int count = 0;
+
+ vd = vdp_data(ifname);
+
+ if (!vd)
+ return 0;
+
+ LIST_FOREACH(p, &vd->profile_head, profile) {
+ count++;
+ }
+
+ return count;
+}
+
/* vdp_vsis_pending - check for pending VSIs
* @vd: vdp data for the interface
*
--
1.7.4.4

View File

@ -0,0 +1,42 @@
From 58ccc3beb723dd786cc74fe9236089fc9a9b6d15 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Wed, 6 Apr 2011 08:33:45 -0700
Subject: [PATCH 26/51] add configuration info for EVB and VDP to manpage
This patch adds basic commands to enable and configure EVB and VDP support
to the lldptool manpage.
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>
---
lldptool.8 | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/lldptool.8 b/lldptool.8
index 1ef5746..d3c9f33 100644
--- a/lldptool.8
+++ b/lldptool.8
@@ -201,6 +201,19 @@ Set a Management Address TLV on eth3 to carry IPv6 address ::192.168.10.10
Get the configured IPv4 address for the Management Address TLV on eth3
.B lldptool -t -eth3 -V mngAddr ipv4
+.TP
+Enable transmit of the Edge Virtual Bridging TLV for interface eth4
+.B lldptool -i eth4 -T -V evbCfg enableTx=yes
+
+.TP
+Configure EVB TLV to set reflective relay and RTE,ECP and VDP capabilities
+.B lldptool -T -i eth4 -V evbCfg fmode=reflectiverelay
+.br
+.B lldptool -T -i eth4 -V evbCfg capabilities=rte,ecp,vdp
+
+.TP
+Enable transmit of the VDP for interface eth4
+.B lldptool -i eth4 -T -V vdp enableTx=yes
.PP
Configurations per port have higher precedence than global configurations.
--
1.7.4.4

View File

@ -0,0 +1,44 @@
From 32e1d7fb3ab73374a628ee120dd3f6223cd729e3 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Wed, 6 Apr 2011 08:33:40 -0700
Subject: [PATCH 25/51] add pointer about EVB and VDP to manpage
This patch add pointers about EVB and VDP support to the lldpad manpage.
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>
---
lldpad.8 | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/lldpad.8 b/lldpad.8
index 71f6035..25b63bd 100644
--- a/lldpad.8
+++ b/lldpad.8
@@ -32,6 +32,9 @@ LLDP-MED Organizationally Specific TLVs
.TP
-
Data Center Bridging capabilities exchange protocol (DCBX) TLVs
+.TP
+-
+Edge Virtual Bridging (EVB) TLVs
.br
.PP
Capabilities of
@@ -81,6 +84,12 @@ for information on how to configure which version of DCBX
.B lldpad
executes.
+.B lldpad
+also supports edge virtual bridging as currently under specification in the
+IEEE 802.1Qb working group.
+<http://www.ieee802.org/1/pages/802.1bg.html>
+
+.PP
.SH OPTIONS
.B lldpad
has the following command line options:
--
1.7.4.4

View File

@ -0,0 +1,32 @@
From 899921f8db916c35dd684fdfab3b179ee60a4d55 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Wed, 6 Apr 2011 08:34:07 -0700
Subject: [PATCH 31/51] allow VSI sm state change from ASSOC to PREASSOC_P
This is a minor change in the VSI state machine to avoid an assertion if the
state changes from ASSOCIATED to PREASSOCIATE_PROCESSING.
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_vdp.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/lldp_vdp.c b/lldp_vdp.c
index d1adb66..c530c0d 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -409,7 +409,8 @@ void vdp_vsi_change_station_state(struct vsi_profile *profile, u8 newstate)
break;
case VSI_PREASSOC_PROCESSING:
assert((profile->state == VSI_PREASSOCIATED) ||
- profile->state == VSI_UNASSOCIATED);
+ (profile->state == VSI_ASSOCIATED) ||
+ (profile->state == VSI_UNASSOCIATED));
break;
case VSI_PREASSOCIATED:
assert((profile->state == VSI_PREASSOC_PROCESSING) ||
--
1.7.4.4

View File

@ -0,0 +1,33 @@
From 4db56779dea6479ce2a733525dc412346a48c675 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Wed, 6 Apr 2011 08:34:19 -0700
Subject: [PATCH 33/51] allow caching of deassociate requests via netlink
This patch changes the behaviour in case a new request is received from
libvirt via netlink while the affected port is down.
With a recent change, all requests would be rejected. This patch allows at
least deassociate requests again.
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>
---
event_iface.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/event_iface.c b/event_iface.c
index 815c84f..bdf9095 100644
--- a/event_iface.c
+++ b/event_iface.c
@@ -449,7 +449,7 @@ static int event_if_parse_setmsg(struct nlmsghdr *nlh)
}
/* If the link is down, reject request */
- if (!port->portEnabled) {
+ if ((!port->portEnabled) && (profile->mode != VDP_MODE_DEASSOCIATE)) {
LLDPAD_WARN("%s(%i): Unable to associate, port %s not enabled !\n", __func__,
__LINE__, ifname);
ret = -ENXIO;
--
1.7.4.4

View File

@ -0,0 +1,91 @@
From e63d88379622e98867c474b264ecc2473f0589b6 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:38:50 -0800
Subject: [PATCH 20/51] always flag changed profile in vdp_add_profile
This implies that we now have exactly the same behaviour both if the vsi
type is received over the netlink interface or manually from lldptool.
Also allocate bigger output buffer for profiles.
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>
---
event_iface.c | 2 --
lldp_vdp.c | 8 ++++++--
lldp_vdp_cmds.c | 6 ++----
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/event_iface.c b/event_iface.c
index 6841659..815c84f 100644
--- a/event_iface.c
+++ b/event_iface.c
@@ -463,8 +463,6 @@ static int event_if_parse_setmsg(struct nlmsghdr *nlh)
goto out_err;
}
- vdp_somethingChangedLocal(p, true);
-
return ret;
out_err:
diff --git a/lldp_vdp.c b/lldp_vdp.c
index b0855bd..d8e7c52 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -1135,19 +1135,23 @@ struct vsi_profile *vdp_add_profile(struct vsi_profile *profile)
if (p->mode == profile->mode) {
LLDPAD_DBG("%s(%i): profile already exists, ignoring !\n",
__func__, __LINE__);
- return p;
} else {
LLDPAD_DBG("%s(%i): taking new mode !\n", __func__,
__LINE__);
p->mode = profile->mode;
- return p;
}
+
+ vdp_somethingChangedLocal(p, true);
+
+ return p;
}
}
}
LIST_INSERT_HEAD(&vd->profile_head, profile, profile );
+ vdp_somethingChangedLocal(profile, true);
+
return profile;
}
diff --git a/lldp_vdp_cmds.c b/lldp_vdp_cmds.c
index 387aecd..b9399c6 100644
--- a/lldp_vdp_cmds.c
+++ b/lldp_vdp_cmds.c
@@ -160,10 +160,10 @@ static int get_arg_mode(struct cmd *cmd, char *arg, char *argvalue,
count++;
}
- s = t = malloc(count*VDP_BUF_SIZE+1);
+ s = t = malloc((count+1)*VDP_BUF_SIZE);
if (!s)
return cmd_invalid;
- memset(s, 0, count*VDP_BUF_SIZE+1);
+ memset(s, 0, (count+1)*VDP_BUF_SIZE);
LIST_FOREACH(np, &vd->profile_head, profile) {
PRINT_PROFILE(t, np);
@@ -322,8 +322,6 @@ static int set_arg_mode(struct cmd *cmd, char *arg, char *argvalue,
return cmd_invalid;
}
- vdp_somethingChangedLocal(profile, true);
-
return cmd_success;
}
--
1.7.4.4

View File

@ -0,0 +1,82 @@
From 626a6d414fe8292cf599777317a9347e813c7c01 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Wed, 6 Apr 2011 08:34:14 -0700
Subject: [PATCH 32/51] avoid duplicate deassociation
In case a deassociation is received, the VSI state machine should not send
out a duplicate deassociate. Deassociate should only be sent if requested
via netlink by libvirt, by commandline with lldptool or if a negative
response was received by the switch as response to a previous request.
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>
---
include/lldp_vdp.h | 1 +
lldp_vdp.c | 17 ++++++++++++-----
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/include/lldp_vdp.h b/include/lldp_vdp.h
index 60d87c9..4b7054b 100644
--- a/include/lldp_vdp.h
+++ b/include/lldp_vdp.h
@@ -128,6 +128,7 @@ struct vsi_profile {
int state;
int seqnr;
bool localChange;
+ bool remoteChange;
LIST_ENTRY(vsi_profile) profile;
};
diff --git a/lldp_vdp.c b/lldp_vdp.c
index c530c0d..7be0b1c 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -480,8 +480,10 @@ static bool vdp_vsi_set_station_state(struct vsi_profile *profile)
if (profile->mode == VDP_MODE_PREASSOCIATE) {
vdp_vsi_change_station_state(profile, VSI_PREASSOC_PROCESSING);
return true;
- } else if ((profile->mode == VDP_MODE_DEASSOCIATE) ||
- vdp_vsi_negative_response(profile)) {
+ } else if (profile->mode == VDP_MODE_DEASSOCIATE) {
+ vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING);
+ return true;
+ } else if (vdp_vsi_negative_response(profile)) {
vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING);
vdp_somethingChangedLocal(profile, true);
return true;
@@ -518,7 +520,8 @@ static bool vdp_vsi_set_station_state(struct vsi_profile *profile)
}
return false;
case VSI_DEASSOC_PROCESSING:
- if ((profile->ackReceived) || vdp_ackTimer_expired(profile)) {
+ if ((profile->ackReceived) || vdp_ackTimer_expired(profile) ||
+ profile->remoteChange) {
vdp_vsi_change_station_state(profile, VSI_EXIT);
return true;
}
@@ -590,7 +593,6 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
}
break;
case VSI_EXIT:
- /* TODO: send DEASSOC here ? */
vdp_stop_ackTimer(profile);
vdp_stop_keepaliveTimer(profile);
vdp_remove_profile(profile);
@@ -927,7 +929,12 @@ int vdp_indicate(struct vdp_data *vd, struct unpacked_tlv *tlv, int ecp_mode)
p->ackReceived = true;
p->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT;
- p->mode = vdp->mode;
+ if (vdp->mode != p->mode) {
+ p->mode = vdp->mode;
+ p->remoteChange = true;
+ LLDPAD_DBG("%s(%i): station: remoteChange %i !\n",
+ __func__, __LINE__, p->remoteChange);
+ }
p->response = vdp->response;
if (vdp_vsi_negative_response(p))
--
1.7.4.4

View File

@ -0,0 +1,32 @@
From 6a3754050cd6713a0466da5e219983f594ca441c Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:38:12 -0800
Subject: [PATCH 15/51] be sure to stop timers on VSI_EXIT
The VDP timers we are using have to be stopped for the profile on VSI_EXIT,
otherwise the timers may be kicked again on a profile that does no longer
exist.
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_vdp.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/lldp_vdp.c b/lldp_vdp.c
index 025cc8f..52768fe 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -547,6 +547,8 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
break;
case VSI_EXIT:
/* TODO: send DEASSOC here ? */
+ vdp_stop_ackTimer(profile);
+ vdp_stop_keepaliveTimer(profile);
vdp_remove_profile(profile);
break;
default:
--
1.7.4.4

View File

@ -0,0 +1,72 @@
From c834d11be209324b603dec54ec6e16784a077ce4 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Wed, 6 Apr 2011 08:34:03 -0700
Subject: [PATCH 30/51] bugfix: avoid failed query of vdp role
This patch corrects the query of the configured VDP role even if the role
has not been saved to lldpad config file.
Suggested-by: Zhifeng, Cai <bluewindow@h3c.com>
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_vdp_cmds.c | 27 +++++++++++++++++++--------
1 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/lldp_vdp_cmds.c b/lldp_vdp_cmds.c
index b9399c6..4d82b0b 100644
--- a/lldp_vdp_cmds.c
+++ b/lldp_vdp_cmds.c
@@ -328,20 +328,33 @@ static int set_arg_mode(struct cmd *cmd, char *arg, char *argvalue,
static int get_arg_role(struct cmd *cmd, char *arg, char *argvalue,
char *obuf)
{
- char *p;
char arg_path[VDP_BUF_SIZE];
+ struct vdp_data *vd;
if (cmd->cmd != cmd_gettlv)
return cmd_invalid;
+ vd = vdp_data(cmd->ifname);
+
+ if (!vd) {
+ LLDPAD_ERR("%s(%i): could not find vdp_data for %s !\n",
+ __FILE__, __LINE__, cmd->ifname);
+ return cmd_invalid;
+ }
+
switch (cmd->tlvid) {
case ((LLDP_MOD_VDP) << 8) | LLDP_VDP_SUBTYPE:
- snprintf(arg_path, sizeof(arg_path), "%s.%s",
- VDP_PREFIX, arg);
+ if (vd->role == VDP_ROLE_STATION) {
+ sprintf(obuf, "%02x%s%04x%s", (unsigned int) strlen(arg), arg,
+ (unsigned int) strlen("station"), "station");
+ } else if (vd->role == VDP_ROLE_BRIDGE) {
+ sprintf(obuf, "%02x%s%04x%s", (unsigned int) strlen(arg), arg,
+ (unsigned int) strlen("bridge"), "bridge");
+ } else {
+ return cmd_failed;
+ }
+
- if (get_cfg(cmd->ifname, arg_path, (void *)&p,
- CONFIG_TYPE_STRING))
- return cmd_failed;
break;
case INVALID_TLVID:
return cmd_invalid;
@@ -349,8 +362,6 @@ static int get_arg_role(struct cmd *cmd, char *arg, char *argvalue,
return cmd_not_applicable;
}
- sprintf(obuf, "%02x%s%04x%s", (unsigned int) strlen(arg), arg,
- (unsigned int) strlen(p), p);
return cmd_success;
}
--
1.7.4.4

View File

@ -0,0 +1,32 @@
From 3d5ac4bd5e07c574b387523863070f904657934b Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Wed, 6 Apr 2011 08:33:48 -0700
Subject: [PATCH 27/51] bugfix in bridge implementation
fixes a bug in the bridge state machine where still port->profile was used
instead of vdp_data (vd).
Reported-By: Zhifeng, Cai <bluewindow@h3c.com>
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_vdp.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lldp_vdp.c b/lldp_vdp.c
index b3c7726..9b1d222 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -740,7 +740,7 @@ static void vdp_vsi_sm_bridge(struct vsi_profile *profile)
LLDPAD_DBG("%s(%i)-%s: framein %p, sizein %i\n", __func__, __LINE__,
profile->port->ifname, vd->ecp.rx.framein,
vd->ecp.rx.sizein);
- ecp_rx_send_ack_frame(profile->port);
+ ecp_rx_send_ack_frame(vd);
break;
case VSI_PREASSOCIATED:
LLDPAD_DBG("%s(%i)-%s: \n", __func__, __LINE__, profile->port->ifname);
--
1.7.4.4

View File

@ -0,0 +1,49 @@
From 8ee44ed1df687e293a7eb0c86191219d2543105d Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Thu, 3 Feb 2011 23:00:03 +0000
Subject: [PATCH 02/51] bugfix: set configured capabilities as well
So far the configured capabilities have not been set during exchange of EVB
TLVs. This fixes it.
Signed-off-by: Jens Osterkamp <jens@linux.vnet.ibm.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
lldp_evb.c | 14 ++++++++++----
1 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/lldp_evb.c b/lldp_evb.c
index 4f50f31..8533b31 100644
--- a/lldp_evb.c
+++ b/lldp_evb.c
@@ -388,17 +388,23 @@ int evb_check_and_fill(struct evb_data *ed, struct tlv_info_evb *tie)
ed->tie->smode = LLDP_EVB_CAPABILITY_FORWARD_STANDARD;
}
- /* If both sides support RTE, set it */
- if ((tie->scap & ed->policy->scap) & LLDP_EVB_CAPABILITY_PROTOCOL_RTE)
+ /* If both sides support RTE, support and configure it */
+ if ((tie->scap & ed->policy->scap) & LLDP_EVB_CAPABILITY_PROTOCOL_RTE) {
ed->tie->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_RTE;
+ ed->tie->ccap |= LLDP_EVB_CAPABILITY_PROTOCOL_RTE;
+ }
/* If both sides support ECP, set it */
- if ((tie->scap & ed->policy->scap) & LLDP_EVB_CAPABILITY_PROTOCOL_ECP)
+ if ((tie->scap & ed->policy->scap) & LLDP_EVB_CAPABILITY_PROTOCOL_ECP) {
ed->tie->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_ECP;
+ ed->tie->ccap |= LLDP_EVB_CAPABILITY_PROTOCOL_ECP;
+ }
/* If both sides support VDP, set it */
- if ((tie->scap & ed->policy->scap) & LLDP_EVB_CAPABILITY_PROTOCOL_VDP)
+ if ((tie->scap & ed->policy->scap) & LLDP_EVB_CAPABILITY_PROTOCOL_VDP) {
ed->tie->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_VDP;
+ ed->tie->ccap |= LLDP_EVB_CAPABILITY_PROTOCOL_VDP;
+ }
/* If supported caps include VDP take over min value of both */
if (ed->tie->scap & LLDP_EVB_CAPABILITY_PROTOCOL_VDP)
--
1.7.4.4

View File

@ -0,0 +1,31 @@
From 22d4dd6b5f8612cf49da3ebe19cd0d6827be3e18 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Thu, 3 Feb 2011 23:00:04 +0000
Subject: [PATCH 03/51] bugfix: state ECP_TX_IDLE no longer exists
The ECP_TX_IDLE state in the state enum has been removed already some time
before, but the arry which maps the states to strings for printout has not
been adapted. This leads to wrong printouts with shifted states which makes
debugging confusing ;-)
Signed-off-by: Jens Osterkamp <jens@linux.vnet.ibm.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
ecp/ecp.h | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/ecp/ecp.h b/ecp/ecp.h
index 5f84992..2c0ea0f 100644
--- a/ecp/ecp.h
+++ b/ecp/ecp.h
@@ -71,7 +71,6 @@ enum {
};
static const char *ecp_tx_states[] = {
- "ECP_TX_IDLE",
"ECP_TX_INIT_TRANSMIT",
"ECP_TX_TRANSMIT_ECPDU",
"ECP_TX_WAIT_FOR_ACK",
--
1.7.4.4

View File

@ -0,0 +1,51 @@
From 96b9a70885f56f79c80400f9efbaa7598edec4d1 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:38:25 -0800
Subject: [PATCH 17/51] check if port is enabled for RxTx
In vdp_ifup, check in adminstatus if port is enabled for RxTx, and do
nothing, if not.
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_vdp.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/lldp_vdp.c b/lldp_vdp.c
index 980eaaf..b7c8f82 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -1235,6 +1235,7 @@ void vdp_ifup(char *ifname)
char *p;
struct vdp_data *vd;
struct vdp_user_data *ud;
+ struct port *port;
LLDPAD_DBG("%s(%i): starting VDP for if %s !\n", __func__, __LINE__, ifname);
@@ -1270,6 +1271,20 @@ void vdp_ifup(char *ifname)
ud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_VDP);
LIST_INSERT_HEAD(&ud->head, vd, entry);
+ port = port_find_by_name(ifname);
+
+ if (!port) {
+ LLDPAD_ERR("%s(%i): could not find port for %s!\n",
+ __func__, __LINE__, ifname);
+ goto out_err;
+ }
+
+ if (port->adminStatus != enabledRxTx) {
+ LLDPAD_WARN("%s(%i): port %s not enabled for RxTx (%i) !\n",
+ __func__, __LINE__, ifname, port->adminStatus);
+ return;
+ }
+
out_start_again:
if (ecp_init(ifname)) {
LLDPAD_ERR("%s:%s unable to init ecp !\n", __func__, ifname);
--
1.7.4.4

View File

@ -0,0 +1,110 @@
From e698bc3efe31e0807976eb9ff215379a7cde0ef6 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Thu, 3 Feb 2011 23:00:05 +0000
Subject: [PATCH 04/51] cleanup: change request from mode to boolean
Signed-off-by: Jens Osterkamp <jens@linux.vnet.ibm.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
ecp/ecp_tx.c | 10 +++++-----
event_iface.c | 2 +-
include/lldp_vdp.h | 7 -------
lldp_vdp_cmds.c | 2 +-
4 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/ecp/ecp_tx.c b/ecp/ecp_tx.c
index 69bca30..6dff8c7 100644
--- a/ecp/ecp_tx.c
+++ b/ecp/ecp_tx.c
@@ -53,7 +53,7 @@ void ecp_somethingChangedLocal(struct vdp_data *vd)
if (!vd)
return;
- vd->ecp.tx.localChange = 1;
+ vd->ecp.tx.localChange = true;
return;
}
@@ -216,7 +216,7 @@ void ecp_tx_Initialize(struct vdp_data *vd)
free(vd->ecp.tx.frameout);
vd->ecp.tx.frameout = NULL;
}
- vd->ecp.tx.localChange = VDP_PROFILE_REQ;
+ vd->ecp.tx.localChange = true;
vd->ecp.lastSequence = ECP_SEQUENCE_NR_START;
vd->ecp.stats.statsFramesOutTotal = 0;
vd->ecp.ackTimerExpired = false;
@@ -265,7 +265,7 @@ void ecp_tx_create_frame(struct vdp_data *vd)
ecp_txFrame(vd);
}
- vd->ecp.tx.localChange = 0;
+ vd->ecp.tx.localChange = false;
return;
}
@@ -431,7 +431,7 @@ static bool ecp_set_tx_state(struct vdp_data *vd)
}
return false;
case ECP_TX_REQUEST_PDU:
- if (vd->ecp.tx.localChange & VDP_PROFILE_REQ) {
+ if (vd->ecp.tx.localChange) {
ecp_tx_change_state(vd, ECP_TX_TRANSMIT_ECPDU);
return true;
}
@@ -470,7 +470,7 @@ void ecp_tx_run_sm(struct vdp_data *vd)
vd->ifname);
LLDPAD_DBG("%s(%i)-%s: seqECPDU %x lastSequence %x \n", __func__, __LINE__,
vd->ifname, vd->ecp.seqECPDU, vd->ecp.lastSequence);
- vd->ecp.tx.localChange = 0;
+ vd->ecp.tx.localChange = false;
ecp_tx_stop_ackTimer(vd);
}
break;
diff --git a/event_iface.c b/event_iface.c
index 70ff72f..5d447c6 100644
--- a/event_iface.c
+++ b/event_iface.c
@@ -454,7 +454,7 @@ static int event_if_parse_setmsg(struct nlmsghdr *nlh)
return -EINVAL;
}
- vdp_somethingChangedLocal(profile, VDP_PROFILE_REQ);
+ vdp_somethingChangedLocal(profile, true);
vdp_vsi_sm_station(p);
return 0;
diff --git a/include/lldp_vdp.h b/include/lldp_vdp.h
index 146e29d..2caf57a 100644
--- a/include/lldp_vdp.h
+++ b/include/lldp_vdp.h
@@ -62,13 +62,6 @@ static char *vsi_responses[] = {
"out of sync"
};
-enum {
- VDP_PROFILE_NOCHANGE = 0,
- VDP_PROFILE_REQ,
- VDP_PROFILE_ACK,
- VDP_PROFILE_NACK,
-};
-
#define VDP_MACVLAN_FORMAT_1 1
#define VDP_TIMER_GRANULARITY 10000 /* 10 ms in us */
diff --git a/lldp_vdp_cmds.c b/lldp_vdp_cmds.c
index d2e5b2f..9f67d7d 100644
--- a/lldp_vdp_cmds.c
+++ b/lldp_vdp_cmds.c
@@ -322,7 +322,7 @@ static int set_arg_mode(struct cmd *cmd, char *arg, char *argvalue,
return cmd_invalid;
}
- vdp_somethingChangedLocal(profile, VDP_PROFILE_REQ);
+ vdp_somethingChangedLocal(profile, true);
vdp_vsi_sm_station(p);
return cmd_success;
--
1.7.4.4

View File

@ -0,0 +1,192 @@
From 47ea2f2940025c23335f9c6182ccd6697a82364b Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:38:00 -0800
Subject: [PATCH 13/51] cleanup: only print profiles that are removed
- only print profiles that are removed, not all
- add more debug code in vdp_indicate
- correct some comments
- add profile to some debug statements
- remove duplicate stop_keepalive_Timer
- print VSI id in decimal and hex
- fix typo in vdp mode strings
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>
---
include/lldp_vdp.h | 4 +-
lldp_vdp.c | 61 +++++++++++++++++++++++++++++++--------------------
2 files changed, 39 insertions(+), 26 deletions(-)
diff --git a/include/lldp_vdp.h b/include/lldp_vdp.h
index 5fc1a22..031337d 100644
--- a/include/lldp_vdp.h
+++ b/include/lldp_vdp.h
@@ -40,7 +40,7 @@ static char *vsi_modes[] = {
"VDP_MODE_PREASSOCIATED",
"VDP_MODE_PREASSOCIATED_WITH_RR",
"VDP_MODE_ASSOCIATED",
- "VDP_MODE_DEASSOCITATED"
+ "VDP_MODE_DEASSOCIATED"
};
#define VDP_RESPONSE_SUCCESS 0x0
@@ -168,7 +168,7 @@ static int vdp_start_timer(struct vdp_data *vd);
c = sprintf(s, "state: %i", p->state); s += c; \
c = sprintf(s, " (%s)\n", vsi_states[p->state]); s+= c; \
c = sprintf(s, "mgrid: %i\n", p->mgrid); s += c; \
- c = sprintf(s, "id: %x\n", p->id); \
+ c = sprintf(s, "id: %i (0x%x)\n", p->id, p->id); \
s += c; \
c = sprintf(s, "version: %i\n", p->version); s += c; \
char instance[INSTANCE_STRLEN+2]; \
diff --git a/lldp_vdp.c b/lldp_vdp.c
index 73ca59f..9bd361e 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -168,7 +168,7 @@ void vdp_somethingChangedLocal(struct vsi_profile *profile, bool flag)
*
* returns true or false
*
- * returns value of profile->ackTimerExpired, true if ack timer has expired,
+ * returns value of profile->keepaliveTimerExpired, true if ack timer has expired,
* false otherwise.
*/
static bool vdp_keepaliveTimer_expired(struct vsi_profile *profile)
@@ -217,11 +217,14 @@ void vdp_timeout_handler(void *eloop_data, void *user_ctx)
if (vdp_ackTimer_expired(p) ||
vdp_keepaliveTimer_expired(p) ||
p->ackReceived) {
- 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__,
+ 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);
}
@@ -282,11 +285,12 @@ static void vdp_start_ackTimer(struct vsi_profile *profile)
{
profile->ackTimer = VDP_ACK_TIMER_DEFAULT;
- LLDPAD_DBG("%s(%i)-%s: starting ack timer (%i)\n", __func__, __LINE__,
- profile->port->ifname, profile->ackTimer);
+ LLDPAD_DBG("%s(%i)-%s: starting ack timer for 0x%02x (%i)\n",
+ __func__, __LINE__, profile->port->ifname,
+ profile->instance[15], profile->ackTimer);
}
-/* vdp_start_ackTimer - starts the VDP keepalive timer for a profile
+/* vdp_start_keepaliveTimer - starts the VDP keepalive timer for a profile
* @profile: profile to process
*
* starts the keepalive timer when a frame has been sent out.
@@ -295,8 +299,9 @@ static void vdp_start_keepaliveTimer(struct vsi_profile *profile)
{
profile->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT;
- LLDPAD_DBG("%s(%i)-%s: starting keepalive timer (%i)\n", __func__, __LINE__,
- profile->port->ifname, profile->keepaliveTimer);
+ LLDPAD_DBG("%s(%i)-%s: starting keepalive timer for 0x%02x (%i)\n",
+ __func__, __LINE__, profile->port->ifname,
+ profile->instance[15], profile->keepaliveTimer);
}
/* vdp_stop_ackTimer - stops the VDP ack timer
@@ -308,11 +313,12 @@ static void vdp_stop_ackTimer(struct vsi_profile *profile)
{
profile->ackTimer = VDP_ACK_TIMER_STOPPED;
- LLDPAD_DBG("%s(%i)-%s: stopping ack timer (%i)\n", __func__, __LINE__,
- profile->port->ifname, profile->ackTimer);
+ LLDPAD_DBG("%s(%i)-%s: stopping ack timer for 0x%02x (%i)\n",
+ __func__, __LINE__, profile->port->ifname,
+ profile->instance[15], profile->ackTimer);
}
-/* vdp_stop_ackTimer - stops the VDP keepalive timer for a profile
+/* vdp_stop_keepaliveTimer - stops the VDP keepalive timer for a profile
* @profile: profile to process
*
* stops the keepalive timer when a frame has been sent out.
@@ -321,8 +327,9 @@ static void vdp_stop_keepaliveTimer(struct vsi_profile *profile)
{
profile->keepaliveTimer = VDP_KEEPALIVE_TIMER_STOPPED;
- LLDPAD_DBG("%s(%i)-%s: stopping keepalive timer (%i)\n", __func__, __LINE__,
- profile->port->ifname, profile->keepaliveTimer);
+ LLDPAD_DBG("%s(%i)-%s: stopping keepalive timer for 0x%02x (%i)\n",
+ __func__, __LINE__, profile->port->ifname,
+ profile->instance[15], profile->keepaliveTimer);
}
/* vdp_vsi_change_station_state - changes the VDP station sm state
@@ -482,8 +489,9 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
vdp_vsi_set_station_state(profile);
do {
- LLDPAD_DBG("%s(%i)-%s: station - %s\n", __func__, __LINE__,
- profile->port->ifname, vsi_states[profile->state]);
+ LLDPAD_DBG("%s(%i)-%s: station for 0x%02x - %s\n",
+ __func__, __LINE__, profile->port->ifname,
+ profile->instance[15], vsi_states[profile->state]);
switch(profile->state) {
case VSI_UNASSOCIATED:
@@ -521,7 +529,6 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
case VSI_DEASSOC_PROCESSING:
vdp_stop_keepaliveTimer(profile);
profile->response = VDP_RESPONSE_NO_RESPONSE;
- vdp_stop_keepaliveTimer(profile);
if (profile->localChange) {
ecp_somethingChangedLocal(vd);
vdp_start_ackTimer(profile);
@@ -857,16 +864,22 @@ int vdp_indicate(struct vdp_data *vd, struct unpacked_tlv *tlv, int ecp_mode)
/* do we have the profile already ? */
LIST_FOREACH(p, &vd->profile_head, profile) {
if (vdp_profile_equal(p, profile)) {
- LLDPAD_DBG("%s(%i): station: profile found, localChange %i ackReceived %i!\n",
- __func__, __LINE__, p->localChange, p->ackReceived);
+ LLDPAD_DBG("%s(%i): station: profile found, "
+ "localChange %i ackReceived %i!\n",
+ __func__, __LINE__,
+ p->localChange, p->ackReceived);
p->ackReceived = true;
p->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT;
p->mode = vdp->mode;
p->response = vdp->response;
- LLDPAD_DBG("%s(%i): profile response: %s (%i).\n", __func__, __LINE__,
- vsi_responses[p->response], p->response);
+ LLDPAD_DBG("%s(%i): profile response: %s (%i) "
+ "for profile 0x%02x at state %s.\n",
+ __func__, __LINE__,
+ vsi_responses[p->response],
+ p->response, p->instance[15],
+ vsi_states[p->state]);
} else {
LLDPAD_DBG("%s(%i): station: profile not found !\n", __func__, __LINE__);
/* ignore profile */
@@ -1151,8 +1164,8 @@ int vdp_remove_profile(struct vsi_profile *profile)
* it exists. If yes, remove it. */
LIST_FOREACH(p, &vd->profile_head, profile) {
if (p) {
- vdp_print_profile(p);
if (vdp_profile_equal(p, profile)) {
+ vdp_print_profile(p);
LIST_REMOVE(p, profile);
free(p);
}
--
1.7.4.4

View File

@ -0,0 +1,122 @@
From 713b589fcb659bfdfe2b3ba283236d9a7932fe9d Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:38:54 -0800
Subject: [PATCH 21/51] consolidate ecp_somethingChangedlocal
This patch consolidates all modifications of vd->ecp.tx.localchange into
using ecp_somethingChangelocal like vdp_somethingChangedlocal for more
consistent interface and easier debugging.
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 | 17 ++++++++++-------
lldp_vdp.c | 7 ++++---
2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/ecp/ecp_tx.c b/ecp/ecp_tx.c
index 05c4818..99d5cae 100644
--- a/ecp/ecp_tx.c
+++ b/ecp/ecp_tx.c
@@ -48,12 +48,15 @@ void ecp_tx_run_sm(struct vdp_data *);
* used to signal an ecpdu needs to be sent out.
*/
-void ecp_somethingChangedLocal(struct vdp_data *vd)
+void ecp_somethingChangedLocal(struct vdp_data *vd, bool flag)
{
if (!vd)
return;
- vd->ecp.tx.localChange = true;
+ LLDPAD_DBG("%s(%i): setting vd->ecp.tx.localChange to %s.", __func__,
+ __LINE__, (flag == true) ? "true" : "false");
+
+ vd->ecp.tx.localChange = flag;
return;
}
@@ -218,7 +221,7 @@ void ecp_tx_Initialize(struct vdp_data *vd)
free(vd->ecp.tx.frameout);
vd->ecp.tx.frameout = NULL;
}
- vd->ecp.tx.localChange = true;
+ ecp_somethingChangedLocal(vd, true);
vd->ecp.lastSequence = ECP_SEQUENCE_NR_START;
vd->ecp.stats.statsFramesOutTotal = 0;
vd->ecp.ackTimer = ECP_ACK_TIMER_STOPPED;
@@ -267,7 +270,7 @@ void ecp_tx_create_frame(struct vdp_data *vd)
ecp_txFrame(vd);
}
- vd->ecp.tx.localChange = false;
+ ecp_somethingChangedLocal(vd, false);
return;
}
@@ -395,7 +398,7 @@ static bool ecp_set_tx_state(struct vdp_data *vd)
if (ecp_ackTimer_expired(vd)) {
vd->ecp.retries++;
if (vd->ecp.retries < ECP_MAX_RETRIES) {
- ecp_somethingChangedLocal(vd);
+ ecp_somethingChangedLocal(vd, true);
ecp_tx_change_state(vd, ECP_TX_TRANSMIT_ECPDU);
return true;
}
@@ -446,7 +449,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;
+ ecp_somethingChangedLocal(vd, false);
break;
case ECP_TX_WAIT_FOR_ACK:
if (vd->ecp.ackReceived) {
@@ -454,7 +457,7 @@ void ecp_tx_run_sm(struct vdp_data *vd)
vd->ifname);
LLDPAD_DBG("%s(%i)-%s: seqECPDU %x lastSequence %x \n", __func__, __LINE__,
vd->ifname, vd->ecp.seqECPDU, vd->ecp.lastSequence);
- vd->ecp.tx.localChange = false;
+ ecp_somethingChangedLocal(vd, false);
ecp_tx_stop_ackTimer(vd);
}
break;
diff --git a/lldp_vdp.c b/lldp_vdp.c
index d8e7c52..e6ee7e8 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -510,7 +510,7 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
vdp_stop_keepaliveTimer(profile);
profile->response = VDP_RESPONSE_NO_RESPONSE;
if (profile->localChange) {
- ecp_somethingChangedLocal(vd);
+ ecp_somethingChangedLocal(vd, true);
vdp_start_ackTimer(profile);
}
break;
@@ -524,7 +524,7 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
vdp_stop_keepaliveTimer(profile);
profile->response = VDP_RESPONSE_NO_RESPONSE;
if (profile->localChange) {
- ecp_somethingChangedLocal(vd);
+ ecp_somethingChangedLocal(vd, true);
vdp_start_ackTimer(profile);
}
break;
@@ -535,10 +535,11 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
vdp_start_keepaliveTimer(profile);
break;
case VSI_DEASSOC_PROCESSING:
+ profile->ackReceived = false;
vdp_stop_keepaliveTimer(profile);
profile->response = VDP_RESPONSE_NO_RESPONSE;
if (profile->localChange) {
- ecp_somethingChangedLocal(vd);
+ ecp_somethingChangedLocal(vd, true);
vdp_start_ackTimer(profile);
}
break;
--
1.7.4.4

View File

@ -0,0 +1,92 @@
From 17e37970a9d940dd53697147074674a9bb7e0874 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:37:45 -0800
Subject: [PATCH 10/51] event if: always reject request if link is down
If the link is down, reject all requests for de-/pre-/association.
And while we are at it, avoid the memory leak in event interface.
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>
---
event_iface.c | 39 ++++++++++++++++++++++++++-------------
1 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/event_iface.c b/event_iface.c
index 51ea951..6841659 100644
--- a/event_iface.c
+++ b/event_iface.c
@@ -294,6 +294,7 @@ static int event_if_parse_setmsg(struct nlmsghdr *nlh)
struct vdp_data *vd;
char *ifname;
int rem;
+ int ret = 0;
if (nlmsg_parse(nlh, sizeof(struct ifinfomsg),
(struct nlattr **)&tb, IFLA_MAX, NULL)) {
@@ -379,7 +380,8 @@ static int event_if_parse_setmsg(struct nlmsghdr *nlh)
if (nla_parse_nested(tb3, IFLA_PORT_MAX, tb_vf_ports,
ifla_port_policy)) {
LLDPAD_ERR("nested parsing on level 2 failed.\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_err;
}
if (tb3[IFLA_PORT_VF]) {
@@ -435,28 +437,39 @@ static int event_if_parse_setmsg(struct nlmsghdr *nlh)
}
}
- if (ifname) {
- struct port *port = port_find_by_name(ifname);
+ struct port *port = port_find_by_name(ifname);
- if (port) {
- profile->port = port;
- } else {
- LLDPAD_ERR("%s(%i): Could not find port for %s\n", __func__,
- __LINE__, ifname);
- return -EEXIST;
- }
+ if (port) {
+ profile->port = port;
+ } else {
+ LLDPAD_ERR("%s(%i): Could not find port for %s\n", __func__,
+ __LINE__, ifname);
+ ret = -EEXIST;
+ goto out_err;
+ }
+
+ /* If the link is down, reject request */
+ if (!port->portEnabled) {
+ LLDPAD_WARN("%s(%i): Unable to associate, port %s not enabled !\n", __func__,
+ __LINE__, ifname);
+ ret = -ENXIO;
+ goto out_err;
}
p = vdp_add_profile(profile);
if (!p) {
- free(profile);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_err;
}
vdp_somethingChangedLocal(p, true);
- return 0;
+ return ret;
+
+out_err:
+ free(profile);
+ return ret;
}
static void event_if_parseResponseMsg(struct nlmsghdr *nlh)
--
1.7.4.4

View File

@ -0,0 +1,32 @@
From bc2fec292417407a84b9c68b7b360236bb8120a8 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:38:42 -0800
Subject: [PATCH 19/51] fix memory leak in vdp_indicate
In function vdp_indicate, if (vd->role == VDP_ROLE_STATION) is true and
(vdp_profile_equal(p, profile)) is true, then pointer profile will leak.
This fixes it.
Reported-by: bluewindow <bluewindow@h3c.com>
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_vdp.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/lldp_vdp.c b/lldp_vdp.c
index efe9f64..b0855bd 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -892,6 +892,7 @@ int vdp_indicate(struct vdp_data *vd, struct unpacked_tlv *tlv, int ecp_mode)
vsi_responses[p->response],
p->response, p->instance[15],
vsi_states[p->state]);
+ free(profile);
} else {
LLDPAD_DBG("%s(%i): station: profile not found !\n",
__func__, __LINE__);
--
1.7.4.4

View File

@ -0,0 +1,32 @@
From 9b6f5c8b8a20d9c554ee0810be011c1c074adaf6 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:37:55 -0800
Subject: [PATCH 12/51] fix potential crash after link up
In case the interface goes down e.g. through a link down by the switch the
ECP rx state machine has to be reset to IDLE, otherwise it might crash.
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 | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/ecp/ecp.c b/ecp/ecp.c
index 1f46664..3f64292 100644
--- a/ecp/ecp.c
+++ b/ecp/ecp.c
@@ -71,8 +71,8 @@ int ecp_init(char *ifname)
goto fail;
}
- vd->ecp.ackTimerExpired = true;
ecp_tx_run_sm(vd);
+ ecp_rx_change_state(vd, ECP_RX_IDLE);
ecp_rx_run_sm(vd);
return 0;
--
1.7.4.4

View File

@ -0,0 +1,194 @@
From 52d9fd16cb76cddd429f81a032098ae966fc4c4e Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:38:30 -0800
Subject: [PATCH 18/51] generic: renamed find_module_user_data_by_if
ifname was handed to find_module_user_data_by_if as parameter but never used
there. Therefore remove the parameter and rename the function to
find_module_user_data_by_id and change all the callers too.
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>
---
include/lldp_mod.h | 3 +--
lldp_8023.c | 4 ++--
lldp_basman.c | 4 ++--
lldp_dcbx.c | 4 ++--
lldp_evb.c | 4 ++--
lldp_mand.c | 4 ++--
lldp_med.c | 4 ++--
lldp_vdp.c | 4 ++--
8 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/include/lldp_mod.h b/include/lldp_mod.h
index 154fc99..c394fb9 100644
--- a/include/lldp_mod.h
+++ b/include/lldp_mod.h
@@ -108,8 +108,7 @@ static inline struct lldp_module *find_module_by_id(struct lldp_head *head, int
return NULL;
}
-static inline void *find_module_user_data_by_if(const char *ifname,
- struct lldp_head *head, int id)
+static inline void *find_module_user_data_by_id(struct lldp_head *head, int id)
{
struct lldp_module *mod;
diff --git a/lldp_8023.c b/lldp_8023.c
index 1e98aab..3a0bd4b 100644
--- a/lldp_8023.c
+++ b/lldp_8023.c
@@ -85,7 +85,7 @@ static struct ieee8023_data *ieee8023_data(const char *ifname)
struct ieee8023_user_data *ud;
struct ieee8023_data *bd = NULL;
- ud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_8023);
+ ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8023);
if (ud) {
LIST_FOREACH(bd, &ud->head, entry) {
if (!strncmp(ifname, bd->ifname, IFNAMSIZ))
@@ -447,7 +447,7 @@ void ieee8023_ifup(char *ifname)
goto out_err;
}
- ud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_8023);
+ ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8023);
LIST_INSERT_HEAD(&ud->head, bd, entry);
LLDPAD_INFO("%s:port %s added\n", __func__, ifname);
return;
diff --git a/lldp_basman.c b/lldp_basman.c
index 0011c8f..3129277 100644
--- a/lldp_basman.c
+++ b/lldp_basman.c
@@ -92,7 +92,7 @@ static struct basman_data *basman_data(const char *ifname)
struct basman_user_data *bud;
struct basman_data *bd = NULL;
- bud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_BASIC);
+ bud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_BASIC);
if (bud) {
LIST_FOREACH(bd, &bud->head, entry) {
if (!strncmp(ifname, bd->ifname, IFNAMSIZ))
@@ -676,7 +676,7 @@ void basman_ifup(char *ifname)
goto out_err;
}
- bud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_BASIC);
+ bud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_BASIC);
LIST_INSERT_HEAD(&bud->head, bd, entry);
LLDPAD_DBG("%s:port %s added\n", __func__, ifname);
return;
diff --git a/lldp_dcbx.c b/lldp_dcbx.c
index 8649df9..480c439 100644
--- a/lldp_dcbx.c
+++ b/lldp_dcbx.c
@@ -116,7 +116,7 @@ struct dcbx_tlvs *dcbx_data(const char *ifname)
struct dcbd_user_data *dud;
struct dcbx_tlvs *tlv = NULL;
- dud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_DCBX);
+ dud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_DCBX);
if (dud) {
LIST_FOREACH(tlv, &dud->head, entry) {
if (!strncmp(tlv->ifname, ifname, IFNAMSIZ))
@@ -443,7 +443,7 @@ void dcbx_ifup(char *ifname)
port = port->next;
}
- dud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_DCBX);
+ dud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_DCBX);
tlvs = dcbx_data(ifname);
if (!port || !check_port_dcb_mode(ifname))
diff --git a/lldp_evb.c b/lldp_evb.c
index 8533b31..a43f3e8 100644
--- a/lldp_evb.c
+++ b/lldp_evb.c
@@ -48,7 +48,7 @@ struct evb_data *evb_data(char *ifname)
struct evb_user_data *ud;
struct evb_data *ed = NULL;
- ud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_EVB);
+ ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB);
if (ud) {
LIST_FOREACH(ed, &ud->head, entry) {
if (!strncmp(ifname, ed->ifname, IFNAMSIZ))
@@ -597,7 +597,7 @@ void evb_ifup(char *ifname)
ed->state = EVB_OFFER_CAPABILITIES;
evb_bld_tlv(ed);
- ud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_EVB);
+ ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB);
LIST_INSERT_HEAD(&ud->head, ed, entry);
LLDPAD_DBG("%s:port %s added\n", __func__, ifname);
return;
diff --git a/lldp_mand.c b/lldp_mand.c
index 88efcd4..c755dfa 100644
--- a/lldp_mand.c
+++ b/lldp_mand.c
@@ -97,7 +97,7 @@ static struct mand_data *mand_data(const char *ifname)
struct mand_user_data *mud;
struct mand_data *md = NULL;
- mud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_MAND);
+ mud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_MAND);
if (mud) {
LIST_FOREACH(md, &mud->head, entry) {
if (!strncmp(ifname, md->ifname, IFNAMSIZ))
@@ -606,7 +606,7 @@ void mand_ifup(char *ifname)
md->rebuild_chassis = 1;
/* portid is built once and remains constant */
md->rebuild_portid = 1;
- mud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_MAND);
+ mud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_MAND);
LIST_INSERT_HEAD(&mud->head, md, entry);
LLDPAD_INFO("%s:port %s added\n", __func__, ifname);
return;
diff --git a/lldp_med.c b/lldp_med.c
index ce69536..7516f6d 100644
--- a/lldp_med.c
+++ b/lldp_med.c
@@ -96,7 +96,7 @@ static struct med_data *med_data(const char *ifname)
struct med_user_data *mud;
struct med_data *md = NULL;
- mud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_MED);
+ mud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_MED);
if (mud) {
LIST_FOREACH(md, &mud->head, entry) {
if (!strncmp(ifname, md->ifname, IFNAMSIZ))
@@ -902,7 +902,7 @@ void med_ifup(char *ifname)
free(md);
goto out_err;
}
- mud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_MED);
+ mud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_MED);
LIST_INSERT_HEAD(&mud->head, md, entry);
LLDPAD_INFO("%s:port %s added\n", __func__, ifname);
return;
diff --git a/lldp_vdp.c b/lldp_vdp.c
index b7c8f82..efe9f64 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -55,7 +55,7 @@ struct vdp_data *vdp_data(char *ifname)
struct vdp_user_data *ud;
struct vdp_data *vd = NULL;
- ud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_VDP);
+ ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP);
if (ud) {
LIST_FOREACH(vd, &ud->head, entry) {
if (!strncmp(ifname, vd->ifname, IFNAMSIZ))
@@ -1268,7 +1268,7 @@ void vdp_ifup(char *ifname)
LIST_INIT(&vd->profile_head);
- ud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_VDP);
+ ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP);
LIST_INSERT_HEAD(&ud->head, vd, entry);
port = port_find_by_name(ifname);
--
1.7.4.4

View File

@ -0,0 +1,69 @@
From 2784f4b9b91fea1690841f9284c11cac6cfe0e1f Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:38:06 -0800
Subject: [PATCH 14/51] handle negative response in VDP state machine
In case where we receive a negative response to a request from the switch,
handle it appropriately.
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_vdp.c | 18 ++++++++++++++++--
1 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/lldp_vdp.c b/lldp_vdp.c
index 9bd361e..025cc8f 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -332,6 +332,14 @@ static void vdp_stop_keepaliveTimer(struct vsi_profile *profile)
profile->instance[15], profile->keepaliveTimer);
}
+static bool vdp_vsi_negative_response(struct vsi_profile *profile)
+{
+ if ((profile->response > 0) && (profile->response < 255))
+ return true;
+ else
+ return false;
+}
+
/* vdp_vsi_change_station_state - changes the VDP station sm state
* @profile: profile to process
* @newstate: new state for the sm
@@ -426,8 +434,10 @@ static bool vdp_vsi_set_station_state(struct vsi_profile *profile)
if (profile->mode == VDP_MODE_PREASSOCIATE) {
vdp_vsi_change_station_state(profile, VSI_PREASSOC_PROCESSING);
return true;
- } else if (profile->mode == VDP_MODE_DEASSOCIATE) {
+ } else if ((profile->mode == VDP_MODE_DEASSOCIATE) ||
+ vdp_vsi_negative_response(profile)) {
vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING);
+ vdp_somethingChangedLocal(profile, true);
return true;
} else if (vdp_keepaliveTimer_expired(profile)) {
vdp_stop_keepaliveTimer(profile);
@@ -874,6 +884,9 @@ int vdp_indicate(struct vdp_data *vd, struct unpacked_tlv *tlv, int ecp_mode)
p->mode = vdp->mode;
p->response = vdp->response;
+ if (vdp_vsi_negative_response(p))
+ p->mode = VDP_MODE_DEASSOCIATE;
+
LLDPAD_DBG("%s(%i): profile response: %s (%i) "
"for profile 0x%02x at state %s.\n",
__func__, __LINE__,
@@ -881,7 +894,8 @@ int vdp_indicate(struct vdp_data *vd, struct unpacked_tlv *tlv, int ecp_mode)
p->response, p->instance[15],
vsi_states[p->state]);
} else {
- LLDPAD_DBG("%s(%i): station: profile not found !\n", __func__, __LINE__);
+ LLDPAD_DBG("%s(%i): station: profile not found !\n",
+ __func__, __LINE__);
/* ignore profile */
}
}
--
1.7.4.4

View File

@ -0,0 +1,127 @@
From 4bf0f2db41be0b282e63646fb6b31f0a938d3865 Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 09:16:22 -0700
Subject: [PATCH 50/51] lldpad: DCB, remove iSCSI tc qdisc and filters
This removes creating the multiq qdisc and iSCSI filter when
the iSCSI APP TLV is set. The multq qdisc was being created
and a filter to map iSCSI traffic to the queue number that is
being advertised as the app priority for iSCSI was setup.
But this implementation _only_ works on ixgbe drivers before
kernel 2.6.38 where this queue is actually mapped to the
correct traffic class. Probably worse is it breaks other
CNAs that use the kernel API select_queue() or skb->priority
to traffic class mappings to steer traffic.
Additionally, even if the host is not running iSCSI at all
the qdisc and filter are added if the switch advertises
the iSCSI APP TLV. By adding the qdisc we adversely effect
FCoE performance.
This patch removes the adding of the qdisc and filters
resolving the issues above.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
dcb_protocol.c | 5 ++---
include/dcb_driver_interface.h | 3 +--
lldp_dcbx_nl.c | 33 ++-------------------------------
3 files changed, 5 insertions(+), 36 deletions(-)
diff --git a/dcb_protocol.c b/dcb_protocol.c
index b841259..4596a5d 100644
--- a/dcb_protocol.c
+++ b/dcb_protocol.c
@@ -2772,7 +2772,7 @@ int set_configuration(char *device_name, u32 EventFlag)
app_data.dcb_app_idtype = DCB_APP_IDTYPE_ETHTYPE;
app_data.dcb_app_id = APP_FCOE_ETHTYPE;
app_data.dcb_app_priority = Oper->second->AppData[0];
- return set_hw_app0(device_name, &app_data);
+ return set_hw_app(device_name, &app_data);
} else if (DCB_TEST_FLAGS(EventFlag, DCB_LOCAL_CHANGE_APPTLV(APP_ISCSI_STYPE),
DCB_LOCAL_CHANGE_APPTLV(APP_ISCSI_STYPE)) ||
DCB_TEST_FLAGS(EventFlag, DCB_REMOTE_CHANGE_APPTLV(APP_ISCSI_STYPE),
@@ -2792,8 +2792,7 @@ int set_configuration(char *device_name, u32 EventFlag)
app_data.dcb_app_id = APP_ISCSI_PORT;
app_data.dcb_app_priority = Oper->second->AppData[0];
- return set_hw_app1(device_name, &app_data,
- Local->second->protocol.OperMode);
+ return set_hw_app(device_name, &app_data);
}
return dcb_success;
}
diff --git a/include/dcb_driver_interface.h b/include/dcb_driver_interface.h
index e4b5802..3e1c59f 100644
--- a/include/dcb_driver_interface.h
+++ b/include/dcb_driver_interface.h
@@ -42,8 +42,7 @@ typedef struct appgroup_attribs {
int set_hw_pg(char *device_name, pgroup_attribs *pg_data, bool Opermode);
int set_hw_pfc(char *device_name, dcb_pfc_list_type pfc_data, bool Opermode);
-int set_hw_app0(char *device_name, appgroup_attribs *app_data);
-int set_hw_app1(char *device_name, appgroup_attribs *app_data, int mode);
+int set_hw_app(char *device_name, appgroup_attribs *app_data);
int set_hw_all(char *device_name);
diff --git a/lldp_dcbx_nl.c b/lldp_dcbx_nl.c
index a860724..ce3d613 100644
--- a/lldp_dcbx_nl.c
+++ b/lldp_dcbx_nl.c
@@ -702,13 +702,13 @@ int set_hw_pfc(char *ifname, dcb_pfc_list_type pfc_data,
/* returns: 0 on success
* 1 on failure
*/
-int set_hw_app0(char *ifname, appgroup_attribs *app_data)
+int set_hw_app(char *ifname, appgroup_attribs *app_data)
{
struct nlmsghdr *nlh;
struct rtattr *rta_parent, *rta_child;
int seq;
- LLDPAD_DBG("set_hw_app0: %s\n", ifname);
+ LLDPAD_DBG("set_hw_app: %s\n", ifname);
nlh = start_msg(RTM_SETDCB, DCB_CMD_SAPP);
if (NULL == nlh)
@@ -748,35 +748,6 @@ void run_cmd(char *cmd, ...)
return;
}
-/* returns: 0 on success
- * 1 on failure
-*/
-int set_hw_app1(char *ifname, appgroup_attribs *app_data, int mode)
-{
- int queue;
-
- LLDPAD_INFO(" set_hw_app1: %s, %s, pri - %d\n", ifname,
- mode ? "Enabled" : "Disabled", mode);
-
- /* find first bit set in u8 bitmask for queue_mapping */
- queue = ffs(app_data->dcb_app_priority);
-
- run_cmd("tc qdisc del dev %s root 2>/dev/null", ifname, NULL, NULL);
- if (mode) {
- run_cmd("tc qdisc add dev %s root handle 1: multiq", ifname, NULL, NULL);
- run_cmd("tc filter add dev %s protocol ip parent 1: u32 match ip dport %d 0xffff action skbedit queue_mapping %d", ifname, 3260, queue);
- run_cmd("tc filter add dev %s protocol ip parent 1: u32 match ip sport %d 0xffff action skbedit queue_mapping %d", ifname, 3260, queue);
- run_cmd("tc filter add dev %s protocol ipv6 parent 1: u32 match ip6 dport %d 0xffff action skbedit queue_mapping %d", ifname, 3260, queue);
- run_cmd("tc filter add dev %s protocol ipv6 parent 1: u32 match ip6 sport %d 0xffff action skbedit queue_mapping %d", ifname, 3260, queue);
- }
-
- /* And push configuration to kernel */
- set_hw_app0(ifname, app_data);
-
- return(0);
-
-}
-
int set_hw_all(char *ifname)
{
struct nlmsghdr *nlh;
--
1.7.4.4

View File

@ -0,0 +1,48 @@
From 1c07cac7f456596bde81f20aa6f271f606814906 Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:47:09 -0700
Subject: [PATCH 34/51] lldpad: DCBx remove unused bchange value
bchange is no longer used in dcb_protocol remove variable.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
dcb_protocol.c | 7 ++-----
1 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/dcb_protocol.c b/dcb_protocol.c
index 21be011..ee07e5d 100644
--- a/dcb_protocol.c
+++ b/dcb_protocol.c
@@ -1612,7 +1612,6 @@ dcb_result put_pg(char *device_name, pg_attribs *pg_data)
full_dcb_attrib_ptrs attr_ptr;
u32 EventFlag = 0;
dcb_result result = dcb_success;
- bool bChange = false;
if (!pg_data)
return dcb_bad_params;
@@ -1634,7 +1633,6 @@ dcb_result put_pg(char *device_name, pg_attribs *pg_data)
result = dcb_bad_params;
goto Exit;
}
- bChange = true;
if (set_persistent(device_name, &attr_ptr) != dcb_success) {
LLDPAD_DBG("Set persistent failed put_pg()\n");
result = dcb_device_not_found;
@@ -1662,9 +1660,8 @@ dcb_result put_pg(char *device_name, pg_attribs *pg_data)
DCB_SET_FLAGS(EventFlag, DCB_LOCAL_CHANGE_PG);
/* Run the protocol */
- if (bChange)
- result = run_dcb_protocol(device_name, EventFlag,
- SUBTYPE_DEFAULT);
+ result = run_dcb_protocol(device_name, EventFlag,
+ SUBTYPE_DEFAULT);
} else {
/* Not in DCB data store, so store in persistent storage */
if (get_persistent(device_name, &attribs) == dcb_success) {
--
1.7.4.4

View File

@ -0,0 +1,54 @@
From ff7a21292914fe184a92e04eebdaea2ccadd4629 Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:47:53 -0700
Subject: [PATCH 41/51] lldpad: DCBx should not free TLV type 0
The DCBx module is free'ing the type 0 TLV. This is not
valid for two reasons. First the rchange() ops does
not return TLV_OK indicating the module has consumed
the TLV. And two the type 0 TLV should be handled by
all modules to indicate the end of a lldpdu.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
lldp_dcbx.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/lldp_dcbx.c b/lldp_dcbx.c
index 4227296..02c07f3 100644
--- a/lldp_dcbx.c
+++ b/lldp_dcbx.c
@@ -645,9 +645,11 @@ int dcbx_rchange(struct port *port, struct unpacked_tlv *tlv)
(tlv->info[DCB_OUI_LEN] == dcbx_subtype2)) {
port->lldpdu |= RCVD_LLDP_DCBX2_TLV;
dcbx->manifest->dcbx2 = tlv;
+ return TLV_OK;
} else if (tlv->info[DCB_OUI_LEN] == dcbx_subtype1) {
port->lldpdu |= RCVD_LLDP_DCBX1_TLV;
dcbx->manifest->dcbx1 = tlv;
+ return TLV_OK;
} else {
/* not a DCBX subtype we support */
return SUBTYPE_INVALID;
@@ -678,12 +680,14 @@ int dcbx_rchange(struct port *port, struct unpacked_tlv *tlv)
mibUpdateObjects(port);
}
- free_unpkd_tlv(tlv);
clear_dcbx_manifest(dcbx);
- dcbx->dcbdu = 0;
}
- return TLV_OK;
+ /* TLV is not handled by DCBx module return invalid to
+ * indicate lldpad core should continue to look for
+ * a module to handle this TLV
+ */
+ return SUBTYPE_INVALID;
}
u8 dcbx_mibDeleteObjects(struct port *port)
--
1.7.4.4

View File

@ -0,0 +1,112 @@
From 68c411e5a1638b4d38d9ea6c008b66bbad03d761 Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:47:35 -0700
Subject: [PATCH 38/51] lldpad: FCoE app data never sent to kernel
Remove ifdefs around netlink code. Because these defines were
never set the app data was not being sent to the kernel. After
removing the defines there were some compile errors that
needed to be fixed.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
dcb_protocol.c | 5 ++---
include/dcb_driver_interface.h | 4 ----
lldp_dcbx_nl.c | 4 ----
3 files changed, 2 insertions(+), 11 deletions(-)
diff --git a/dcb_protocol.c b/dcb_protocol.c
index ee07e5d..6a91574 100644
--- a/dcb_protocol.c
+++ b/dcb_protocol.c
@@ -42,6 +42,7 @@
#include "tlv_dcbx.h"
#include "lldp_rtnl.h"
#include "linux/if.h"
+#include "linux/dcbnl.h"
static void handle_opermode_true(char *device_name);
u8 gdcbx_subtype = dcbx_subtype2;
@@ -2754,13 +2755,13 @@ int set_configuration(char *device_name, u32 EventFlag)
DCB_TEST_FLAGS(EventFlag, DCB_REMOTE_CHANGE_LLINK,
DCB_REMOTE_CHANGE_LLINK)) {
return dcb_success;
-#ifdef DCB_APP_DRV_IF_SUPPORTED
} else if (DCB_TEST_FLAGS(EventFlag,
DCB_LOCAL_CHANGE_APPTLV(APP_FCOE_STYPE),
DCB_LOCAL_CHANGE_APPTLV(APP_FCOE_STYPE)) ||
DCB_TEST_FLAGS(EventFlag,
DCB_REMOTE_CHANGE_APPTLV(APP_FCOE_STYPE),
DCB_REMOTE_CHANGE_APPTLV(APP_FCOE_STYPE))) {
+ appgroup_attribs app_data;
/* Get Oper store */
app_it Oper = apptlv_find(&oper_apptlv, device_name,
@@ -2768,7 +2769,6 @@ int set_configuration(char *device_name, u32 EventFlag)
if (Oper == NULL)
return dcb_success;
- appgroup_attribs app_data;
app_data.dcb_app_idtype = DCB_APP_IDTYPE_ETHTYPE;
app_data.dcb_app_id = APP_FCOE_ETHTYPE;
app_data.dcb_app_priority = Oper->second->AppData[0];
@@ -2788,7 +2788,6 @@ int set_configuration(char *device_name, u32 EventFlag)
}
return set_hw_app1(device_name, Oper->second->AppData[0],
Local->second->protocol.OperMode);
-#endif /* DCB_APP_DRV_IF_SUPPORTED */
}
return dcb_success;
}
diff --git a/include/dcb_driver_interface.h b/include/dcb_driver_interface.h
index 0e681f8..17050fe 100644
--- a/include/dcb_driver_interface.h
+++ b/include/dcb_driver_interface.h
@@ -33,21 +33,17 @@ typedef struct pgroup_attribs {
dcb_traffic_attribs_type rx;
} pgroup_attribs;
-#ifdef DCB_APP_DRV_IF_SUPPORTED
typedef struct appgroup_attribs {
u8 dcb_app_idtype;
u16 dcb_app_id;
u8 dcb_app_priority;
} appgroup_attribs;
-#endif
int set_hw_pg(char *device_name, pgroup_attribs *pg_data, bool Opermode);
int set_hw_pfc(char *device_name, dcb_pfc_list_type pfc_data, bool Opermode);
-#ifdef DCB_APP_DRV_IF_SUPPORTED
int set_hw_app0(char *device_name, appgroup_attribs *app_data);
int set_hw_app1(char *device_name, u8 priority, int mode);
-#endif /* DCB_APP_DRV_IF_SUPPORTED */
int set_hw_all(char *device_name);
diff --git a/lldp_dcbx_nl.c b/lldp_dcbx_nl.c
index e5512df..e4b2830 100644
--- a/lldp_dcbx_nl.c
+++ b/lldp_dcbx_nl.c
@@ -699,9 +699,6 @@ int set_hw_pfc(char *ifname, dcb_pfc_list_type pfc_data,
return rval;
}
-
-#ifdef DCB_APP_DRV_IF_SUPPORTED
-
/* returns: 0 on success
* 1 on failure
*/
@@ -775,7 +772,6 @@ int set_hw_app1(char *ifname, u8 pri, int mode)
return(0);
}
-#endif /* DCB_APP_DRV_IF_SUPPORTED */
int set_hw_all(char *ifname)
{
--
1.7.4.4

View File

@ -0,0 +1,268 @@
From 81f201225a7865f3ce7560ca8eb29b92b81b345d Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:48:00 -0700
Subject: [PATCH 42/51] lldpad: add 802.1Qaz attributes to dcbnl.h
Update dcbnl.h with new 802.1Qaz kernel interface attributes.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
include/linux/dcbnl.h | 184 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 184 insertions(+), 0 deletions(-)
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h
index 8723491..66900e3 100644
--- a/include/linux/dcbnl.h
+++ b/include/linux/dcbnl.h
@@ -22,6 +22,89 @@
#include <linux/types.h>
+/* IEEE 802.1Qaz std supported values */
+#define IEEE_8021QAZ_MAX_TCS 8
+
+/* This structure contains the IEEE 802.1Qaz ETS managed object
+ *
+ * @willing: willing bit in ETS configuratin TLV
+ * @ets_cap: indicates supported capacity of ets feature
+ * @cbs: credit based shaper ets algorithm supported
+ * @tc_tx_bw: tc tx bandwidth indexed by traffic class
+ * @tc_rx_bw: tc rx bandwidth indexed by traffic class
+ * @tc_tsa: TSA Assignment table, indexed by traffic class
+ * @prio_tc: priority assignment table mapping 8021Qp to traffic class
+ * @tc_reco_bw: recommended tc bandwidth indexed by traffic class for TLV
+ * @tc_reco_tsa: recommended tc bandwidth indexed by traffic class for TLV
+ * @reco_prio_tc: recommended tc tx bandwidth indexed by traffic class for TLV
+ *
+ * Recommended values are used to set fields in the ETS recommendation TLV
+ * with hardware offloaded LLDP.
+ *
+ * ----
+ * TSA Assignment 8 bit identifiers
+ * 0 strict priority
+ * 1 credit-based shaper
+ * 2 enhanced transmission selection
+ * 3-254 reserved
+ * 255 vendor specific
+ */
+struct ieee_ets {
+ __u8 willing;
+ __u8 ets_cap;
+ __u8 cbs;
+ __u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS];
+ __u8 tc_rx_bw[IEEE_8021QAZ_MAX_TCS];
+ __u8 tc_tsa[IEEE_8021QAZ_MAX_TCS];
+ __u8 prio_tc[IEEE_8021QAZ_MAX_TCS];
+ __u8 tc_reco_bw[IEEE_8021QAZ_MAX_TCS];
+ __u8 tc_reco_tsa[IEEE_8021QAZ_MAX_TCS];
+ __u8 reco_prio_tc[IEEE_8021QAZ_MAX_TCS];
+};
+
+/* This structure contains the IEEE 802.1Qaz PFC managed object
+ *
+ * @pfc_cap: Indicates the number of traffic classes on the local device
+ * that may simultaneously have PFC enabled.
+ * @pfc_en: bitmap indicating pfc enabled traffic classes
+ * @mbc: enable macsec bypass capability
+ * @delay: the allowance made for a round-trip propagation delay of the
+ * link in bits.
+ * @requests: count of the sent pfc frames
+ * @indications: count of the received pfc frames
+ */
+struct ieee_pfc {
+ __u8 pfc_cap;
+ __u8 pfc_en;
+ __u8 mbc;
+ __u16 delay;
+ __u64 requests[IEEE_8021QAZ_MAX_TCS];
+ __u64 indications[IEEE_8021QAZ_MAX_TCS];
+};
+
+/* This structure contains the IEEE 802.1Qaz APP managed object. This
+ * object is also used for the CEE std as well. There is no difference
+ * between the objects.
+ *
+ * @selector: protocol identifier type
+ * @protocol: protocol of type indicated
+ * @priority: 3-bit unsigned integer indicating priority
+ *
+ * ----
+ * Selector field values
+ * 0 Reserved
+ * 1 Ethertype
+ * 2 Well known port number over TCP or SCTP
+ * 3 Well known port number over UDP or DCCP
+ * 4 Well known port number over TCP, SCTP, UDP, or DCCP
+ * 5-7 Reserved
+ */
+struct dcb_app {
+ __u8 selector;
+ __u8 priority;
+ __u16 protocol;
+};
+
struct dcbmsg {
__u8 dcb_family;
__u8 cmd;
@@ -50,6 +133,12 @@ struct dcbmsg {
* @DCB_CMD_SBCN: get backward congestion notification configration.
* @DCB_CMD_GAPP: get application protocol configuration
* @DCB_CMD_SAPP: set application protocol configuration
+ * @DCB_CMD_IEEE_SET: set IEEE 802.1Qaz configuration
+ * @DCB_CMD_IEEE_GET: get IEEE 802.1Qaz configuration
+ * @DCB_CMD_GDCBX: get DCBX engine configuration
+ * @DCB_CMD_SDCBX: set DCBX engine configuration
+ * @DCB_CMD_GFEATCFG: get DCBX features flags
+ * @DCB_CMD_SFEATCFG: set DCBX features negotiation flags
*/
enum dcbnl_commands {
DCB_CMD_UNDEFINED,
@@ -83,6 +172,15 @@ enum dcbnl_commands {
DCB_CMD_GAPP,
DCB_CMD_SAPP,
+ DCB_CMD_IEEE_SET,
+ DCB_CMD_IEEE_GET,
+
+ DCB_CMD_GDCBX,
+ DCB_CMD_SDCBX,
+
+ DCB_CMD_GFEATCFG,
+ DCB_CMD_SFEATCFG,
+
__DCB_CMD_ENUM_MAX,
DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1,
};
@@ -102,6 +200,9 @@ enum dcbnl_commands {
* @DCB_ATTR_CAP: DCB capabilities of the device (NLA_NESTED)
* @DCB_ATTR_NUMTCS: number of traffic classes supported (NLA_NESTED)
* @DCB_ATTR_BCN: backward congestion notification configuration (NLA_NESTED)
+ * @DCB_ATTR_IEEE: IEEE 802.1Qaz supported attributes (NLA_NESTED)
+ * @DCB_ATTR_DCBX: DCBX engine configuration in the device (NLA_U8)
+ * @DCB_ATTR_FEATCFG: DCBX features flags (NLA_NESTED)
*/
enum dcbnl_attrs {
DCB_ATTR_UNDEFINED,
@@ -119,10 +220,32 @@ enum dcbnl_attrs {
DCB_ATTR_BCN,
DCB_ATTR_APP,
+ /* IEEE std attributes */
+ DCB_ATTR_IEEE,
+
+ DCB_ATTR_DCBX,
+ DCB_ATTR_FEATCFG,
+
__DCB_ATTR_ENUM_MAX,
DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1,
};
+enum ieee_attrs {
+ DCB_ATTR_IEEE_UNSPEC,
+ DCB_ATTR_IEEE_ETS,
+ DCB_ATTR_IEEE_PFC,
+ DCB_ATTR_IEEE_APP_TABLE,
+ __DCB_ATTR_IEEE_MAX
+};
+#define DCB_ATTR_IEEE_MAX (__DCB_ATTR_IEEE_MAX - 1)
+
+enum ieee_attrs_app {
+ DCB_ATTR_IEEE_APP_UNSPEC,
+ DCB_ATTR_IEEE_APP,
+ __DCB_ATTR_IEEE_APP_MAX
+};
+#define DCB_ATTR_IEEE_APP_MAX (__DCB_ATTR_IEEE_APP_MAX - 1)
+
/**
* enum dcbnl_pfc_attrs - DCB Priority Flow Control user priority nested attrs
*
@@ -262,6 +385,8 @@ enum dcbnl_tc_attrs {
* @DCB_CAP_ATTR_GSP: (NLA_U8) device supports group strict priority
* @DCB_CAP_ATTR_BCN: (NLA_U8) device supports Backwards Congestion
* Notification
+ * @DCB_CAP_ATTR_DCBX: (NLA_U8) device supports DCBX engine
+ *
*/
enum dcbnl_cap_attrs {
DCB_CAP_ATTR_UNDEFINED,
@@ -273,12 +398,45 @@ enum dcbnl_cap_attrs {
DCB_CAP_ATTR_PFC_TCS,
DCB_CAP_ATTR_GSP,
DCB_CAP_ATTR_BCN,
+ DCB_CAP_ATTR_DCBX,
__DCB_CAP_ATTR_ENUM_MAX,
DCB_CAP_ATTR_MAX = __DCB_CAP_ATTR_ENUM_MAX - 1,
};
/**
+ * DCBX capability flags
+ *
+ * @DCB_CAP_DCBX_HOST: DCBX negotiation is performed by the host LLDP agent.
+ * 'set' routines are used to configure the device with
+ * the negotiated parameters
+ *
+ * @DCB_CAP_DCBX_LLD_MANAGED: DCBX negotiation is not performed in the host but
+ * by another entity
+ * 'get' routines are used to retrieve the
+ * negotiated parameters
+ * 'set' routines can be used to set the initial
+ * negotiation configuration
+ *
+ * @DCB_CAP_DCBX_VER_CEE: for a non-host DCBX engine, indicates the engine
+ * supports the CEE protocol flavor
+ *
+ * @DCB_CAP_DCBX_VER_IEEE: for a non-host DCBX engine, indicates the engine
+ * supports the IEEE protocol flavor
+ *
+ * @DCB_CAP_DCBX_STATIC: for a non-host DCBX engine, indicates the engine
+ * supports static configuration (i.e no actual
+ * negotiation is performed negotiated parameters equal
+ * the initial configuration)
+ *
+ */
+#define DCB_CAP_DCBX_HOST 0x01
+#define DCB_CAP_DCBX_LLD_MANAGED 0x02
+#define DCB_CAP_DCBX_VER_CEE 0x04
+#define DCB_CAP_DCBX_VER_IEEE 0x08
+#define DCB_CAP_DCBX_STATIC 0x10
+
+/**
* enum dcbnl_numtcs_attrs - number of traffic classes
*
* @DCB_NUMTCS_ATTR_UNDEFINED: unspecified attribute to catch errors
@@ -355,4 +513,30 @@ enum dcbnl_app_attrs {
DCB_APP_ATTR_MAX = __DCB_APP_ATTR_ENUM_MAX - 1,
};
+/**
+ * enum dcbnl_featcfg_attrs - features conifiguration flags
+ *
+ * @DCB_FEATCFG_ATTR_UNDEFINED: unspecified attribute to catch errors
+ * @DCB_FEATCFG_ATTR_ALL: (NLA_FLAG) all features configuration attributes
+ * @DCB_FEATCFG_ATTR_PG: (NLA_U8) configuration flags for priority groups
+ * @DCB_FEATCFG_ATTR_PFC: (NLA_U8) configuration flags for priority
+ * flow control
+ * @DCB_FEATCFG_ATTR_APP: (NLA_U8) configuration flags for application TLV
+ *
+ */
+#define DCB_FEATCFG_ERROR 0x01 /* error in feature resolution */
+#define DCB_FEATCFG_ENABLE 0x02 /* enable feature */
+#define DCB_FEATCFG_WILLING 0x04 /* feature is willing */
+#define DCB_FEATCFG_ADVERTISE 0x08 /* advertise feature */
+enum dcbnl_featcfg_attrs {
+ DCB_FEATCFG_ATTR_UNDEFINED,
+ DCB_FEATCFG_ATTR_ALL,
+ DCB_FEATCFG_ATTR_PG,
+ DCB_FEATCFG_ATTR_PFC,
+ DCB_FEATCFG_ATTR_APP,
+
+ __DCB_FEATCFG_ATTR_ENUM_MAX,
+ DCB_FEATCFG_ATTR_MAX = __DCB_FEATCFG_ATTR_ENUM_MAX - 1,
+};
+
#endif /* __LINUX_DCBNL_H__ */
--
1.7.4.4

View File

@ -0,0 +1,323 @@
From fa0230ed0e11d5a5a07dda1d4c882f1272e5c5b8 Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:48:06 -0700
Subject: [PATCH 43/51] lldpad: add 802.1Qaz nlmsg set/query support
This adds support to nltest for 8021Qaz set and query
of ETS, PFC, and APP.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
nltest.c | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 247 insertions(+), 2 deletions(-)
diff --git a/nltest.c b/nltest.c
index 6a00d74..d937064 100644
--- a/nltest.c
+++ b/nltest.c
@@ -48,10 +48,13 @@ static void hexprint(char *b, int len)
}
#endif
+#define NLMSG_TAIL(nmsg) \
+ ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+
static int init_socket(void)
{
int sd;
- int rcv_size;
+ int rcv_size = 8 * 1024;
struct sockaddr_nl snl;
sd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
@@ -116,6 +119,56 @@ static struct nlmsghdr *start_msg(__u16 msg_type, __u8 arg)
}
+int addattr_l(struct nlmsghdr *n, int type, const void *data,
+ int alen)
+{
+ int len = RTA_LENGTH(alen);
+ struct rtattr *rta;
+
+ if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > MAX_MSG_SIZE) {
+ fprintf(stderr, "addattr_l: message exceeded bound of %d\n",
+ MAX_MSG_SIZE);
+ return -1;
+ }
+ rta = NLMSG_TAIL(n);
+ rta->rta_type = type;
+ rta->rta_len = len;
+ memcpy(RTA_DATA(rta), data, alen);
+ n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
+ return 0;
+}
+
+struct rtattr *addattr_nest(struct nlmsghdr *n, int type)
+{
+ struct rtattr *nest = NLMSG_TAIL(n);
+
+ addattr_l(n, type, NULL, 0);
+ return nest;
+}
+
+int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest)
+{
+ nest->rta_len = (void *)NLMSG_TAIL(n) - (void *)nest;
+ return n->nlmsg_len;
+}
+
+int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+{
+ memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
+ while (RTA_OK(rta, len)) {
+ if ((rta->rta_type <= max) && (!tb[rta->rta_type]))
+ tb[rta->rta_type] = rta;
+ rta = RTA_NEXT(rta, len);
+ }
+ if (len)
+ fprintf(stderr, "!!!Deficit %d, rta_len=%d\n",
+ len, rta->rta_len);
+ return 0;
+}
+
+#define parse_rtattr_nested(tb, max, rta) \
+ (parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))
+
static struct rtattr *add_rta(struct nlmsghdr *nlh, __u16 rta_type,
void *attr, __u16 rta_len)
{
@@ -172,8 +225,8 @@ static struct nlmsghdr *get_msg(void)
if ((nlh->nlmsg_type == NLMSG_ERROR) || (len < 0) ||
!(NLMSG_OK(nlh, (unsigned int)len))) {
free(nlh);
-#ifdef HEXDUMP
printf("RECEIVE FAILED: %d\n", len);
+#ifdef HEXDUMP
if (len > 0)
hexprint((char *)nlh, len);
#endif
@@ -535,6 +588,7 @@ static int get_cap(char *ifname, __u8 *cap)
"would sure be nice.\n");
return -EIO;
}
+
rta_child = NLA_DATA(rta_parent);
rta_parent = (struct rtattr *)((char *)rta_parent +
NLMSG_ALIGN(rta_parent->rta_len));
@@ -570,6 +624,9 @@ static int get_cap(char *ifname, __u8 *cap)
case DCB_CAP_ATTR_BCN:
printf("bcn: ");
break;
+ case DCB_CAP_ATTR_DCBX:
+ printf("dcbx: ");
+ break;
default:
printf("unknown type: ");
break;
@@ -1081,6 +1138,178 @@ int set_hw_app0(char *ifname, appgroup_attribs *app_data)
}
#endif /* DCB_APP_DRV_IF_SUPPORTED */
+void print_app(struct rtattr *app_attr)
+{
+ struct dcb_app *data;
+
+ data = RTA_DATA(app_attr);
+ printf("selector %i protocol %i priority %i\n",
+ data->selector, data->protocol, data->priority);
+}
+
+void print_pfc(struct ieee_pfc *pfc)
+{
+ int i;
+ printf("PFC:\n");
+ printf("\t cap %2x en %2x\n", pfc->pfc_cap, pfc->pfc_en);
+ printf("\t mbc %2x delay %i\n", pfc->mbc, pfc->delay);
+
+ printf("\t requests: ");
+ for (i = 0; i < 8; i++)
+ printf("%i ", pfc->requests[i]);
+ printf("\n");
+
+ printf("\t requests: ");
+ for (i = 0; i < 8; i++)
+ printf("%i ", pfc->indications[i]);
+ printf("\n");
+}
+
+void print_ets(struct ieee_ets *ets)
+{
+ int i;
+ printf("ETS:\n");
+ printf("\tcap %2x cbs %2x\n", ets->ets_cap, ets->cbs);
+
+ printf("\tets tc_tx_bw: ");
+ for (i = 0; i < 8; i++)
+ printf("%i ", ets->tc_tx_bw[i]);
+ printf("\n");
+
+ printf("\tets tc_rx_bw: ");
+ for (i = 0; i < 8; i++)
+ printf("%i ", ets->tc_rx_bw[i]);
+ printf("\n");
+
+ printf("\tets tc_tsa: ");
+ for (i = 0; i < 8; i++)
+ printf("%i ", ets->tc_tsa[i]);
+ printf("\n");
+
+ printf("\tets prio_tc: ");
+ for (i = 0; i < 8; i++)
+ printf("%i ", ets->prio_tc[i]);
+ printf("\n");
+}
+
+int set_ieee(char *ifname, struct ieee_ets *ets_data, struct ieee_pfc *pfc_data,
+ struct dcb_app *app_data)
+{
+ struct nlmsghdr *nlh;
+ struct rtattr *ieee, *apptbl;
+
+ nlh = start_msg(RTM_SETDCB, DCB_CMD_IEEE_SET);
+ if (NULL == nlh)
+ return -EIO;
+
+ addattr_l(nlh, DCB_ATTR_IFNAME, ifname, strlen(ifname) + 1);
+ ieee = addattr_nest(nlh, DCB_ATTR_IEEE);
+ if (ets_data)
+ addattr_l(nlh, DCB_ATTR_IEEE_ETS, ets_data, sizeof(*ets_data));
+ if (pfc_data)
+ addattr_l(nlh, DCB_ATTR_IEEE_PFC, pfc_data, sizeof(*pfc_data));
+ if (app_data) {
+ apptbl = addattr_nest(nlh, DCB_ATTR_IEEE_APP_TABLE);
+ addattr_l(nlh, DCB_ATTR_IEEE_APP, app_data, sizeof(*app_data));
+#if 1
+ app_data->protocol++;
+ addattr_l(nlh, DCB_ATTR_IEEE_APP, app_data, sizeof(*app_data));
+#endif
+ addattr_nest_end(nlh, apptbl);
+ }
+ addattr_nest_end(nlh, ieee);
+
+ if (send_msg(nlh))
+ return -EIO;
+
+ return recv_msg(DCB_CMD_IEEE_SET, DCB_ATTR_IEEE);
+}
+
+#define DCB_RTA(r) \
+ ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct dcbmsg))))
+
+int get_ieee(char *ifname)
+{
+ struct nlmsghdr *nlh;
+ struct dcbmsg *d;
+ struct rtattr *dcb, *ieee[DCB_ATTR_IEEE_MAX+1];
+ struct rtattr *tb[DCB_ATTR_MAX + 1];
+ int len;
+
+ nlh = start_msg(RTM_GETDCB, DCB_CMD_IEEE_GET);
+ if (NULL == nlh) {
+ printf("start_msg failed\n");
+ return -EIO;
+ }
+
+ addattr_l(nlh, DCB_ATTR_IFNAME, ifname, strlen(ifname) + 1);
+ if (send_msg(nlh)) {
+ printf("send failure\n");
+ return -EIO;
+ }
+
+ /* Receive 802.1Qaz parameters */
+ memset(nlh, 0, MAX_MSG_SIZE);
+ len = recv(nl_sd, (void *)nlh, MAX_MSG_SIZE, 0);
+ if (len < 0) {
+ perror("ieee_get");
+ return -EIO;
+ }
+
+ if (nlh->nlmsg_type != RTM_GETDCB) {
+ struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA(nlh);
+ if (nlh->nlmsg_type == NLMSG_ERROR) {
+ printf("NLMSG_ERROR: err(%i): %s\n",
+ err->error, strerror(err->error * -1));
+ }
+ return -1;
+ }
+
+ d = NLMSG_DATA(nlh);
+ len -= NLMSG_LENGTH(sizeof(*d));
+ if (len < 0) {
+ printf("Broken message\n");
+ return -1;
+ }
+
+ parse_rtattr(tb, DCB_ATTR_MAX, DCB_RTA(d), len);
+ if (!tb[DCB_ATTR_IEEE]) {
+ printf("Missing DCB_ATTR_IEEE attribute!\n");
+ return -1;
+ }
+
+ if (tb[DCB_ATTR_IFNAME]) {
+ printf("\tifname %s\n", RTA_DATA(tb[DCB_ATTR_IFNAME]));
+ } else {
+ printf("Missing DCB_ATTR_IFNAME attribute!\n");
+ return -1;
+ }
+
+ dcb = tb[DCB_ATTR_IEEE];
+ parse_rtattr_nested(ieee, DCB_ATTR_IEEE_MAX, dcb);
+ if (ieee[DCB_ATTR_IEEE_ETS]) {
+ struct ieee_ets *ets = RTA_DATA(ieee[DCB_ATTR_IEEE_ETS]);
+ print_ets(ets);
+ }
+
+ if (ieee[DCB_ATTR_IEEE_PFC]) {
+ struct ieee_pfc *pfc = RTA_DATA(ieee[DCB_ATTR_IEEE_PFC]);
+ print_pfc(pfc);
+ }
+
+ if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
+ struct rtattr *i, *app_list = ieee[DCB_ATTR_IEEE_APP_TABLE];
+ int rem = RTA_PAYLOAD(app_list);
+ printf("APP: %i\n");
+ for (i = RTA_DATA(app_list);
+ RTA_OK(i, rem);
+ i = RTA_NEXT(i, rem))
+ print_app(i);
+ }
+
+ return 0;
+}
+
int main(int argc, char *argv[])
{
struct tc_config tc[8];
@@ -1285,6 +1514,22 @@ int main(int argc, char *argv[])
printf("GETTING APP FAILED!.\n");
}
#endif /* DCB_APP_DRV_IF_SUPPORTED */
+
+ if (1) {
+ printf("\nSETTING ETS:\n");
+ struct ieee_ets ets = { 0, 0x1, 0,
+ {25, 25, 25, 25, 0, 0, 0, 0},
+ {0, 0, 0, 0, 25, 25, 25, 25},
+ {1, 2, 3, 4, 1, 2, 3, 4},
+ {1, 2, 3, 4, 1, 2, 3, 4} };
+ struct ieee_pfc pfc = {0xf1, 0, 0, 0x32};
+ struct dcb_app app = {0, 0x8906, 4};
+
+ set_ieee(argv[1], &ets, &pfc, &app);
+ }
+
+ get_ieee(argv[1]);
+
err_main:
close(nl_sd);
return err;
--
1.7.4.4

View File

@ -0,0 +1,42 @@
From a6fb363020205d0c3d361bb10cf7df6ba8f28406 Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:48:24 -0700
Subject: [PATCH 46/51] lldpad: cleanup, fix check in gettlv for null ptr tlvs
Move check for null tlvs data structure in dcbx_gettlv()
above free tlvs. If there are no tlvs there is no reason
to try and free them.
Fortunantly, the free tlvs routines also check for a
null ptr so no harm is caused by doing this. But this
cleanup makes it read a bit better.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
lldp_dcbx.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/lldp_dcbx.c b/lldp_dcbx.c
index 02c07f3..567f04e 100644
--- a/lldp_dcbx.c
+++ b/lldp_dcbx.c
@@ -296,13 +296,12 @@ struct packed_tlv* dcbx_gettlv(struct port *port)
return NULL;
tlvs = dcbx_data(port->ifname);
-
- dcbx_free_tlv(tlvs);
if (!tlvs)
return NULL;
- dcbx_bld_tlv(port);
+ dcbx_free_tlv(tlvs);
+ dcbx_bld_tlv(port);
if (tlvs->dcbx_st == dcbx_subtype2) {
/* Load Type127 - dcbx subtype 2*/
if (tlv_ok(tlvs->dcbx2))
--
1.7.4.4

View File

@ -0,0 +1,43 @@
From 4aac303da6286d4bc08064e70369fb1493a480a2 Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:48:45 -0700
Subject: [PATCH 49/51] lldpad: dcbx, dropped ifdown messages breaks module
Because link events can occasionally be lost we have made
the lldpad core handle this case assuming the modules will
initialize correctly when the ifup() routine is called even
when the corresponding ifdown() was not. The dcbx module
however was broke in this case and the result was an
uninitialized port. This patch fixes this by moving the goto
up the routine to initialize the interface even if ifdown
was skipped.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
lldp_dcbx.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lldp_dcbx.c b/lldp_dcbx.c
index 3f6197b..8aa0000 100644
--- a/lldp_dcbx.c
+++ b/lldp_dcbx.c
@@ -503,6 +503,7 @@ void dcbx_ifup(char *ifname)
tlvs->dcbx_st = gdcbx_subtype;
LIST_INSERT_HEAD(&dud->head, tlvs, entry);
+initialized:
dcbx_add_adapter(ifname);
/* ensure advertise bits are set consistently with enabletx */
enabletx = is_tlv_txenabled(ifname, (OUI_CEE_DCBX << 8) |
@@ -511,7 +512,6 @@ void dcbx_ifup(char *ifname)
dont_advertise_dcbx_all(ifname);
dcbx_bld_tlv(port);
-initialized:
if (get_operstate(ifname) == IF_OPER_UP)
set_hw_all(ifname);
--
1.7.4.4

View File

@ -0,0 +1,42 @@
From e1dba77eb789c74ba4b5611a4270dc7ff44ed0a8 Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:47:17 -0700
Subject: [PATCH 35/51] lldpad: dcbx netlink cleanup
fix compile warnings in dcbx netlink.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
lldp_dcbx_nl.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lldp_dcbx_nl.c b/lldp_dcbx_nl.c
index 179f51d..e5512df 100644
--- a/lldp_dcbx_nl.c
+++ b/lldp_dcbx_nl.c
@@ -45,6 +45,7 @@
#include "lldp_dcbx_nl.h"
#include "messages.h"
#include "lldp_rtnl.h"
+#include "lldp/ports.h"
static int nl_sd = 0;
static int rtseq = 0;
@@ -418,12 +419,11 @@ int init_drv_if(void)
int deinit_drv_if(void)
{
- int err = 0;
-
if (nl_sd) {
shutdown(nl_sd, 2);
nl_sd = 0;
}
+ return 0;
}
--
1.7.4.4

View File

@ -0,0 +1,60 @@
From 4ead297738c0c9963ebfea2fb57edebf46bb8bba Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:48:38 -0700
Subject: [PATCH 48/51] lldpad: dormantTimer should not be touched by modules
CEE-DCBX modules is decrementing the dormantTimer this is
incorrect because it has implications for other modules.
Specifically they are dependent on lldp_dcbx.c handling
the dormantTimer mechanism in a way that their module
expects.
This moves the dormant timer handling into agent.c
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
lldp/agent.c | 3 +++
lldp_dcbx.c | 3 ---
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lldp/agent.c b/lldp/agent.c
index f5efdbe..2af8ce6 100644
--- a/lldp/agent.c
+++ b/lldp/agent.c
@@ -47,8 +47,11 @@ static void timer(void *eloop_data, void *user_ctx)
if (n->ops && n->ops->timer)
n->ops->timer(port);
}
+ if (port->timers.dormantDelay)
+ port->timers.dormantDelay--;
port = port->next;
};
+
/* Load new timer */
eloop_register_timeout(1, 0, timer, NULL, NULL);
}
diff --git a/lldp_dcbx.c b/lldp_dcbx.c
index 567f04e..3f6197b 100644
--- a/lldp_dcbx.c
+++ b/lldp_dcbx.c
@@ -79,8 +79,6 @@ static int dcbx_check_operstate(struct port *port)
if (!port->portEnabled || !port->timers.dormantDelay)
return 0;
- port->timers.dormantDelay--;
-
err = get_app(port->ifname, 0, &app_data);
if (err)
goto err_out;
@@ -101,7 +99,6 @@ static int dcbx_check_operstate(struct port *port)
__func__, port->ifname, port->timers.dormantDelay,
pfc_data.protocol.OperMode,
app_data.protocol.OperMode);
- port->timers.dormantDelay = 0;
set_operstate(port->ifname, IF_OPER_UP);
}
--
1.7.4.4

View File

@ -0,0 +1,92 @@
From 8b0e918921882fcf56d9b75acd3b39aa4a76169b Mon Sep 17 00:00:00 2001
From: Daruwalla, Sharookh P <sharookh.p.daruwalla@intel.com>
Date: Wed, 6 Apr 2011 08:48:13 -0700
Subject: [PATCH 44/51] lldpad: get() functions for Local and Remote MAC
addresses
Implements logic to extract the remote peer's MAC address from
the rx frame and store it in l2_packet_data's remote_mac_addr
field.
Removes get_san_mac_addr(). Instead uses l2_packet_get_own_src_addr()
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
lldp/l2_packet.h | 3 +++
lldp/l2_packet_linux.c | 18 +++++++++++++++++-
lldp/rx.c | 2 +-
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/lldp/l2_packet.h b/lldp/l2_packet.h
index 0bdacf1..7c88a5c 100644
--- a/lldp/l2_packet.h
+++ b/lldp/l2_packet.h
@@ -130,6 +130,9 @@ int l2_packet_get_own_src_addr(struct l2_packet_data *l2, u8 *addr);
*/
int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr);
+void get_remote_peer_mac_addr(struct port *port);
+void l2_packet_get_remote_addr(struct l2_packet_data *l2, u8 *addr);
+
/**
* l2_packet_send - Send a packet
* @l2: Pointer to internal l2_packet data from l2_packet_init()
diff --git a/lldp/l2_packet_linux.c b/lldp/l2_packet_linux.c
index 01e2b9c..b01d2c1 100644
--- a/lldp/l2_packet_linux.c
+++ b/lldp/l2_packet_linux.c
@@ -52,6 +52,7 @@ struct l2_packet_data {
u8 perm_mac_addr[ETH_ALEN];
u8 curr_mac_addr[ETH_ALEN];
u8 san_mac_addr[ETH_ALEN];
+ u8 remote_mac_addr[ETH_ALEN];
void (*rx_callback)(void *ctx, unsigned int ifindex,
const u8 *buf, size_t len);
void *rx_callback_ctx;
@@ -80,13 +81,28 @@ int l2_packet_get_own_src_addr(struct l2_packet_data *l2, u8 *addr)
return 0;
}
+
+/*
+ * Extracts the remote peer's MAC address from the rx frame and
+ * puts it in the l2_packet_data
+ */
+void get_remote_peer_mac_addr(struct port *port)
+{
+ int offset = ETH_ALEN; /* points to remote MAC address in RX frame */
+ memcpy(port->l2->remote_mac_addr, &port->rx.framein[offset], ETH_ALEN);
+}
+
+void l2_packet_get_remote_addr(struct l2_packet_data *l2, u8 *addr)
+{
+ memcpy(addr, l2->remote_mac_addr, ETH_ALEN);
+}
+
int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
{
memcpy(addr, l2->perm_mac_addr, ETH_ALEN);
return 0;
}
-
int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto,
const u8 *buf, size_t len)
{
diff --git a/lldp/rx.c b/lldp/rx.c
index 5dd40c3..2b904b7 100644
--- a/lldp/rx.c
+++ b/lldp/rx.c
@@ -153,7 +153,7 @@ void rxProcessFrame(struct port * port)
return;
}
memset(port->rx.manifest,0, sizeof(rxmanifest));
-
+ get_remote_peer_mac_addr(port);
tlv_offset = sizeof(struct l2_ethhdr); /* Points to 1st TLV */
do {
--
1.7.4.4

View File

@ -0,0 +1,112 @@
From fe8ccb1c84408690a42ce2c6134a0f0018ebd46a Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:47:41 -0700
Subject: [PATCH 39/51] lldpad: iSCSI subtype does not send kernel setapp
nlmsg
The iSCSI application data should be sent to the kernel
through the setapp netlink interface. This allows the
lower layer stack to query the application data and
also allows other application to use the generic getapp
interface.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
dcb_protocol.c | 10 ++++++++--
include/dcb_driver_interface.h | 2 +-
include/dcb_types.h | 3 +++
lldp_dcbx_nl.c | 8 ++++++--
4 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/dcb_protocol.c b/dcb_protocol.c
index 6a91574..b841259 100644
--- a/dcb_protocol.c
+++ b/dcb_protocol.c
@@ -2777,6 +2777,7 @@ int set_configuration(char *device_name, u32 EventFlag)
DCB_LOCAL_CHANGE_APPTLV(APP_ISCSI_STYPE)) ||
DCB_TEST_FLAGS(EventFlag, DCB_REMOTE_CHANGE_APPTLV(APP_ISCSI_STYPE),
DCB_REMOTE_CHANGE_APPTLV(APP_ISCSI_STYPE))) {
+ appgroup_attribs app_data;
/* Get Oper store */
app_it Oper = apptlv_find(&oper_apptlv, device_name,
@@ -2786,8 +2787,13 @@ int set_configuration(char *device_name, u32 EventFlag)
if (Oper == NULL || Local == NULL) {
return dcb_failed;
}
- return set_hw_app1(device_name, Oper->second->AppData[0],
- Local->second->protocol.OperMode);
+
+ app_data.dcb_app_idtype = DCB_APP_IDTYPE_PORTNUM;
+ app_data.dcb_app_id = APP_ISCSI_PORT;
+ app_data.dcb_app_priority = Oper->second->AppData[0];
+
+ return set_hw_app1(device_name, &app_data,
+ Local->second->protocol.OperMode);
}
return dcb_success;
}
diff --git a/include/dcb_driver_interface.h b/include/dcb_driver_interface.h
index 17050fe..e4b5802 100644
--- a/include/dcb_driver_interface.h
+++ b/include/dcb_driver_interface.h
@@ -43,7 +43,7 @@ int set_hw_pg(char *device_name, pgroup_attribs *pg_data, bool Opermode);
int set_hw_pfc(char *device_name, dcb_pfc_list_type pfc_data, bool Opermode);
int set_hw_app0(char *device_name, appgroup_attribs *app_data);
-int set_hw_app1(char *device_name, u8 priority, int mode);
+int set_hw_app1(char *device_name, appgroup_attribs *app_data, int mode);
int set_hw_all(char *device_name);
diff --git a/include/dcb_types.h b/include/dcb_types.h
index 5c21650..6a4b6a9 100644
--- a/include/dcb_types.h
+++ b/include/dcb_types.h
@@ -180,6 +180,9 @@ typedef struct dcb_traffic_attribs {
#define APP_FCOE_ETHTYPE 0x8906
#endif
+/* APP PROTOCOL TYPES */
+#define APP_ISCSI_PORT 3260
+
/* Flags */
#define DCB_SET_FLAGS(_FlagsVar, _BitsToSet) \
(_FlagsVar) = (_FlagsVar) | (_BitsToSet)
diff --git a/lldp_dcbx_nl.c b/lldp_dcbx_nl.c
index e4b2830..a860724 100644
--- a/lldp_dcbx_nl.c
+++ b/lldp_dcbx_nl.c
@@ -751,7 +751,7 @@ void run_cmd(char *cmd, ...)
/* returns: 0 on success
* 1 on failure
*/
-int set_hw_app1(char *ifname, u8 pri, int mode)
+int set_hw_app1(char *ifname, appgroup_attribs *app_data, int mode)
{
int queue;
@@ -759,7 +759,7 @@ int set_hw_app1(char *ifname, u8 pri, int mode)
mode ? "Enabled" : "Disabled", mode);
/* find first bit set in u8 bitmask for queue_mapping */
- queue = ffs(pri);
+ queue = ffs(app_data->dcb_app_priority);
run_cmd("tc qdisc del dev %s root 2>/dev/null", ifname, NULL, NULL);
if (mode) {
@@ -769,6 +769,10 @@ int set_hw_app1(char *ifname, u8 pri, int mode)
run_cmd("tc filter add dev %s protocol ipv6 parent 1: u32 match ip6 dport %d 0xffff action skbedit queue_mapping %d", ifname, 3260, queue);
run_cmd("tc filter add dev %s protocol ipv6 parent 1: u32 match ip6 sport %d 0xffff action skbedit queue_mapping %d", ifname, 3260, queue);
}
+
+ /* And push configuration to kernel */
+ set_hw_app0(ifname, app_data);
+
return(0);
}
--
1.7.4.4

View File

@ -0,0 +1,45 @@
From aa0294cd1a48ea34180be4d7235b4b13f9c6418b Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:48:31 -0700
Subject: [PATCH 47/51] lldpad: initialize ports after netlink interface is
created
Initialize netlink interface before ports are initialized. This
resolves an issue where an interface comes up after init_ports()
runs but before the netlinnk interface is up. In this case
we were missing a netlink ifup event. This can be seen on boot
occasionally.
Reported-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
lldpad.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/lldpad.c b/lldpad.c
index 8a5df5b..3a4a721 100644
--- a/lldpad.c
+++ b/lldpad.c
@@ -393,15 +393,15 @@ int main(int argc, char *argv[])
exit(1);
}
- /* Find available interfaces and add adapters */
- init_ports();
-
/* setup event RT netlink interface */
if (event_iface_init() < 0) {
LLDPAD_ERR("failed to register event interface\n");
exit(1);
}
+ /* Find available interfaces and add adapters */
+ init_ports();
+
if (ctrl_iface_register(clifd) < 0) {
if (!daemonize)
fprintf(stderr, "failed to register control interface\n");
--
1.7.4.4

View File

@ -0,0 +1,36 @@
From 1915deefe804639a90e93eeb39bfc68c0f084f3f Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:48:18 -0700
Subject: [PATCH 45/51] lldpad: invalidate peer rx frame after TTL
Invalidate peer RX frame after TTL because it is no
longer valid. If the frame is not cleared the user
interface displays the invalid TLV.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
lldp/rx.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/lldp/rx.c b/lldp/rx.c
index 2b904b7..78f2ad3 100644
--- a/lldp/rx.c
+++ b/lldp/rx.c
@@ -560,6 +560,13 @@ void process_rx_frame(struct port *port)
void process_delete_info(struct port *port)
{
mibDeleteObjects(port);
+
+ if (port->rx.framein) {
+ free(port->rx.framein);
+ port->rx.framein = NULL;
+ }
+
+ port->rx.sizein = 0;
port->rx.remoteChange = true;
return;
}
--
1.7.4.4

View File

@ -0,0 +1,160 @@
From e8c85404d362aa612b21159dc2b7281e37c6346f Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Thu, 7 Apr 2011 13:37:42 -0700
Subject: [PATCH 51/51] lldpad: make debug messages from netlink path helpful
The debug messages for received netlink messages e.g. for device changes
have been mostly empty so far.
This patch corrects this.
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>
---
event_iface.c | 96 +++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 77 insertions(+), 19 deletions(-)
diff --git a/event_iface.c b/event_iface.c
index bdf9095..99501c2 100644
--- a/event_iface.c
+++ b/event_iface.c
@@ -90,9 +90,6 @@ static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] =
static void event_if_decode_rta(int type, struct rtattr *rta, int *ls, char *d)
{
-
- LLDPAD_DBG(" rta_type =\n", rta->rta_len);
-
switch (type) {
case IFLA_ADDRESS:
LLDPAD_DBG(" IFLA_ADDRESS\n");
@@ -100,22 +97,83 @@ static void event_if_decode_rta(int type, struct rtattr *rta, int *ls, char *d)
case IFLA_BROADCAST:
LLDPAD_DBG(" IFLA_BROADCAST\n");
break;
+ case IFLA_IFNAME:
+ strncpy(d, (char *)RTA_DATA(rta), IFNAMSIZ);
+ LLDPAD_DBG(" IFLA_IFNAME\n");
+ LLDPAD_DBG(" device name is %s\n", d);
+ break;
+ case IFLA_MTU:
+ LLDPAD_DBG(" IFLA_MTU\n");
+ break;
+ case IFLA_LINK:
+ LLDPAD_DBG(" IFLA_LINK\n");
+ break;
+ case IFLA_QDISC:
+ LLDPAD_DBG(" IFLA_QDISC\n");
+ break;
+ case IFLA_STATS:
+ LLDPAD_DBG(" IFLA_STATS\n");
+ break;
+ case IFLA_COST:
+ LLDPAD_DBG(" IFLA_COST\n");
+ break;
+ case IFLA_PRIORITY:
+ LLDPAD_DBG(" IFLA_PRIORITY\n");
+ break;
+ case IFLA_MASTER:
+ LLDPAD_DBG(" IFLA_MASTER\n");
+ break;
+ case IFLA_WIRELESS:
+ LLDPAD_DBG(" IFLA_WIRELESS\n");
+ break;
+ case IFLA_PROTINFO:
+ LLDPAD_DBG(" IFLA_PROTINFO\n");
+ break;
+ case IFLA_TXQLEN:
+ LLDPAD_DBG(" IFLA_TXQLEN\n");
+ break;
+ case IFLA_MAP:
+ LLDPAD_DBG(" IFLA_MAP\n");
+ break;
+ case IFLA_WEIGHT:
+ LLDPAD_DBG(" IFLA_WEIGHT\n");
+ break;
case IFLA_OPERSTATE:
- LLDPAD_DBG(" IFLA_OPERSTATE \n", type);
+ LLDPAD_DBG(" IFLA_OPERSTATE\n");
*ls = (*((int *)RTA_DATA(rta)));
+ LLDPAD_DBG(" OPERSTATE = 0x%02x\n", *ls);
break;
case IFLA_LINKMODE:
- LLDPAD_DBG(" IFLA_LINKMODE \n", type);
- LLDPAD_DBG(" LINKMODE = \n", (*((int *)RTA_DATA(rta)))?
+ LLDPAD_DBG(" IFLA_LINKMODE\n");
+ LLDPAD_DBG(" LINKMODE = %s\n", (*((int *)RTA_DATA(rta)))?
"IF_LINK_MODE_DORMANT": "IF_LINK_MODE_DEFAULT");
break;
- case IFLA_IFNAME:
- strncpy(d, (char *)RTA_DATA(rta), IFNAMSIZ);
- LLDPAD_DBG(" IFLA_IFNAME\n");
- LLDPAD_DBG(" device name is \n", d);
+ case IFLA_LINKINFO:
+ LLDPAD_DBG(" IFLA_LINKINFO\n");
+ break;
+ case IFLA_NET_NS_PID:
+ LLDPAD_DBG(" IFLA_NET_NS_PID\n");
+ break;
+ case IFLA_IFALIAS:
+ LLDPAD_DBG(" IFLA_IFALIAS\n");
+ break;
+ case IFLA_NUM_VF:
+ LLDPAD_DBG(" IFLA_NUMVF\n");
+ break;
+ case IFLA_VFINFO_LIST:
+ LLDPAD_DBG(" IFLA_VFINFO_LIST\n");
+ break;
+ case IFLA_STATS64:
+ LLDPAD_DBG(" IFLA_STATS64\n");
+ break;
+ case IFLA_VF_PORTS:
+ LLDPAD_DBG(" IFLA_VF_PORTS\n");
+ break;
+ case IFLA_PORT_SELF:
+ LLDPAD_DBG(" IFLA_PORT_SELF\n");
break;
default:
- LLDPAD_DBG(" unknown type : \n", type);
+ LLDPAD_DBG(" unknown type : 0x%02x\n", type);
break;
}
}
@@ -175,16 +233,16 @@ static void event_if_decode_nlmsg(int route_type, void *data, int len)
case RTM_DELLINK:
case RTM_SETLINK:
case RTM_GETLINK:
- LLDPAD_DBG(" IFINFOMSG\n");
- LLDPAD_DBG(" ifi_family = \n",
+ LLDPAD_DBG(" IFINFOMSG\n");
+ LLDPAD_DBG(" ifi_family = 0x%02x\n",
((struct ifinfomsg *)data)->ifi_family);
- LLDPAD_DBG(" ifi_type = \n",
+ LLDPAD_DBG(" ifi_type = 0x%x\n",
((struct ifinfomsg *)data)->ifi_type);
- LLDPAD_DBG(" ifi_index = \n",
+ LLDPAD_DBG(" ifi_index = %i\n",
((struct ifinfomsg *)data)->ifi_index);
- LLDPAD_DBG(" ifi_flags = \n",
+ LLDPAD_DBG(" ifi_flags = 0x%04x\n",
((struct ifinfomsg *)data)->ifi_flags);
- LLDPAD_DBG(" ifi_change = \n",
+ LLDPAD_DBG(" ifi_change = 0x%04x\n",
((struct ifinfomsg *)data)->ifi_change);
/* print attributes */
@@ -197,8 +255,8 @@ static void event_if_decode_nlmsg(int route_type, void *data, int len)
rta = RTA_NEXT(rta, attrlen);
}
- LLDPAD_DBG("link status: \n", link_status);
- LLDPAD_DBG("device name: \n", device_name);
+ LLDPAD_DBG(" link status: %i\n", link_status);
+ LLDPAD_DBG(" device name: %s\n", device_name);
switch (link_status) {
case IF_OPER_DOWN:
--
1.7.4.4

View File

@ -0,0 +1,41 @@
From 748b44354889329f8c0ef0b9c86013a80f195be2 Mon Sep 17 00:00:00 2001
From: Zhifeng, Cai <bluewindow@h3c.com>
Date: Sun, 6 Mar 2011 21:39:10 -0800
Subject: [PATCH 23/51] lldpad: malloc could fail in clif_attach_helper()
malloc() may fail in clif_attach_helper() so return
values must be checked.
Suggested-By: Zhifeng, Cai <bluewindow@h3c.com>
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
clif.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/clif.c b/clif.c
index 20885f6..9e256f2 100644
--- a/clif.c
+++ b/clif.c
@@ -165,12 +165,18 @@ static int clif_attach_helper(struct clif *clif, char *tlvs_hex, int attach)
/* Allocate maximum buffer usage */
if (tlvs_hex && attach) {
buf = malloc(sizeof(char)*(strlen(tlvs_hex) + 1));
+ if (!buf)
+ return -1;
sprintf(buf, "%s%s","A",tlvs_hex);
} else if (attach) {
buf = malloc(sizeof(char) * 2);
+ if (!buf)
+ return -1;
sprintf(buf, "A");
} else {
buf = malloc(sizeof(char) * 2);
+ if (!buf)
+ return -1;
sprintf(buf, "D");
}
--
1.7.4.4

View File

@ -0,0 +1,299 @@
From 4a3e9c9bd7140d547b0deba41b52b014e5ab6225 Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:47:29 -0700
Subject: [PATCH 37/51] lldpad: remove cur_peer and last_peer from DCBx
cur_peer and last_peer are only used in the dcbx codepath
and worse their use in dcbx is buggy when dcbxv1 and dcbxv2
are present in the same lldp frame.
Rather than try to resolve these issues this patch strips
them out ocmpletely. And uses the stored tlv in the dcbx
struct when needed. This resolves the issues and removes
some unneeded code.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
include/tlv_dcbx.h | 2 --
lldp/ports.c | 10 ----------
lldp/ports.h | 8 --------
lldp/rx.c | 34 ----------------------------------
lldp_dcbx.c | 41 ++++++++++++++++-------------------------
tlv_dcbx.c | 49 -------------------------------------------------
6 files changed, 16 insertions(+), 128 deletions(-)
diff --git a/include/tlv_dcbx.h b/include/tlv_dcbx.h
index 209bf43..62cf568 100644
--- a/include/tlv_dcbx.h
+++ b/include/tlv_dcbx.h
@@ -228,8 +228,6 @@ struct dcb_control_info {
#ifdef __cplusplus
extern "C" {
#endif
-void process_dcbx_tlv(struct port *,struct unpacked_tlv *);
-
struct unpacked_tlv *bld_dcbx1_tlv(struct dcbx_tlvs *dcbx);
struct unpacked_tlv *bld_dcbx2_tlv(struct dcbx_tlvs *dcbx);
struct unpacked_tlv *bld_dcbx_ctrl_tlv(struct dcbx_tlvs *dcbx);
diff --git a/lldp/ports.c b/lldp/ports.c
index ae925c2..3372fb7 100644
--- a/lldp/ports.c
+++ b/lldp/ports.c
@@ -246,8 +246,6 @@ int reinit_port(const char *ifname)
/* init TX path */
txInitializeLLDP(port);
- port->tlvs.last_peer = NULL;
- port->tlvs.cur_peer = NULL;
return 0;
}
@@ -306,8 +304,6 @@ int add_port(const char *ifname)
/* init TX path */
txInitializeLLDP(newport);
- newport->tlvs.last_peer = NULL;
- newport->tlvs.cur_peer = NULL;
/* enable TX path */
if (porthead)
@@ -367,12 +363,6 @@ int remove_port(const char *ifname)
return -1;
/* Remove the tlvs */
- if (port->tlvs.cur_peer != NULL)
- port->tlvs.cur_peer = free_unpkd_tlv(port->tlvs.cur_peer);
-
- if (port->tlvs.last_peer != NULL)
- port->tlvs.last_peer = free_unpkd_tlv(port->tlvs.last_peer);
-
if (port->msap.msap1) {
free(port->msap.msap1);
port->msap.msap1 = NULL;
diff --git a/lldp/ports.h b/lldp/ports.h
index ef823f6..1de750d 100644
--- a/lldp/ports.h
+++ b/lldp/ports.h
@@ -132,11 +132,6 @@ enum portAdminStatus {
enabledRxTx,
};
-struct porttlvs{
- struct unpacked_tlv *cur_peer; /* Should be in manifest */
- struct unpacked_tlv *last_peer;
-};
-
struct port {
char *ifname;
u8 hw_resetting;
@@ -154,9 +149,6 @@ struct port {
u16 lldpdu;
struct msap msap;
- /* not sure */
- struct porttlvs tlvs;
-
struct port *next;
};
diff --git a/lldp/rx.c b/lldp/rx.c
index 114934f..5dd40c3 100644
--- a/lldp/rx.c
+++ b/lldp/rx.c
@@ -391,9 +391,6 @@ out:
}
port->lldpdu = 0;
- if (port->tlvs.cur_peer)
- port->tlvs.cur_peer =
- free_unpkd_tlv(port->tlvs.cur_peer);
clear_manifest(port);
return;
@@ -410,9 +407,6 @@ u8 mibDeleteObjects(struct port *port)
}
/* Clear history */
- if (port->tlvs.last_peer)
- port->tlvs.last_peer = free_unpkd_tlv(port->tlvs.last_peer);
-
port->msap.length1 = 0;
if (port->msap.msap1) {
free(port->msap.msap1);
@@ -642,34 +636,6 @@ void rx_change_state(struct port *port, u8 newstate) {
port->rx.state = newstate;
}
-
-void load_peer_tlvs(struct port *port,struct unpacked_tlv *tlv,int type)
-{
- struct unpacked_tlv *tmp = NULL;
-
- tmp = create_tlv();
- if (tmp) {
- tmp->type = tlv->type;
- tmp->length = tlv->length;
- tmp->info = (u8 *)malloc(tlv->length);
- if (tmp->info) {
- memset(tmp->info,0, tlv->length);
- memcpy(tmp->info,tlv->info,tlv->length);
- } else {
- LLDPAD_DBG("load_peer_tlvs: Failed to malloc info\n");
- }
-
- if (type == CURRENT_PEER) {
- assert(port->tlvs.cur_peer == NULL);
- port->tlvs.cur_peer = tmp;
- } else if (type == LAST_PEER) {
- assert(port->tlvs.last_peer == NULL);
- port->tlvs.last_peer = tmp;
- }
- }
- return;
-}
-
void clear_manifest(struct port *port) {
if (port->rx.manifest->mgmtadd)
port->rx.manifest->mgmtadd =
diff --git a/lldp_dcbx.c b/lldp_dcbx.c
index 480c439..4227296 100644
--- a/lldp_dcbx.c
+++ b/lldp_dcbx.c
@@ -599,6 +599,7 @@ int dcbx_rchange(struct port *port, struct unpacked_tlv *tlv)
u8 oui[DCB_OUI_LEN] = INIT_DCB_OUI;
struct dcbx_tlvs *dcbx;
struct dcbx_manifest *manifest;
+ int res;
dcbx = dcbx_data(port->ifname);
@@ -623,12 +624,9 @@ int dcbx_rchange(struct port *port, struct unpacked_tlv *tlv)
return TLV_ERR;
}
- /* expect oui_st to match tlv_info. */
- if ((memcmp(tlv->info, &oui, DCB_OUI_LEN) != 0)) {
- assert(port->tlvs.cur_peer == NULL);
- /* not a DCBX TLV */
+ /* Match DCB OUI */
+ if ((memcmp(tlv->info, &oui, DCB_OUI_LEN) != 0))
return SUBTYPE_INVALID;
- }
if (dcbx->dcbx_st == dcbx_subtype2) {
if ((tlv->info[DCB_OUI_LEN] == dcbx_subtype2)
@@ -657,37 +655,30 @@ int dcbx_rchange(struct port *port, struct unpacked_tlv *tlv)
}
if (tlv->type == TYPE_0) {
- /* unpack highest dcbx subtype first, to allow lower
- * subtype to store tlvs if higher was not present
+ /* Only process DCBXv2 or DCBXv1 but not both this
+ * is required because processing both could be
+ * problamatic. Specifically if the DCB attributes do
+ * not match across versions.
*/
- if ((dcbx->dcbx_st == dcbx_subtype2) &&
- dcbx->manifest->dcbx2) {
- load_peer_tlvs(port, dcbx->manifest->dcbx2,
- CURRENT_PEER);
- if (unpack_dcbx2_tlvs(port,
- dcbx->manifest->dcbx2) == false) {
+ if (dcbx->manifest->dcbx2) {
+ res = unpack_dcbx2_tlvs(port, dcbx->manifest->dcbx2);
+ if (!res) {
LLDPAD_DBG("Error unpacking the DCBX2"
"TLVs - Discarding LLDPDU\n");
return TLV_ERR;
}
- }
- if (dcbx->manifest->dcbx1) {
- if (!dcbx->manifest->dcbx2)
- load_peer_tlvs(port,
- dcbx->manifest->dcbx1,
- CURRENT_PEER);
- if (unpack_dcbx1_tlvs(port,
- dcbx->manifest->dcbx1) == false) {
+ mibUpdateObjects(port);
+ } else if (dcbx->manifest->dcbx1) {
+ res = unpack_dcbx1_tlvs(port, dcbx->manifest->dcbx1);
+ if (!res) {
LLDPAD_DBG("Error unpacking the DCBX1"
"TLVs - Discarding LLDPDU\n");
return TLV_ERR;
}
+ mibUpdateObjects(port);
}
- if (port->tlvs.cur_peer) {
- process_dcbx_tlv(port, port->tlvs.cur_peer);
- }
- free_unpkd_tlv(tlv);
+ free_unpkd_tlv(tlv);
clear_dcbx_manifest(dcbx);
dcbx->dcbdu = 0;
}
diff --git a/tlv_dcbx.c b/tlv_dcbx.c
index 93e48db..34028dc 100644
--- a/tlv_dcbx.c
+++ b/tlv_dcbx.c
@@ -1135,55 +1135,6 @@ void mibUpdateObjects(struct port *port)
return;
}
-
-void process_dcbx_tlv(struct port *port,struct unpacked_tlv *tlv)
-{
- if (port->rx.tooManyNghbrs){
- if(NULL != port->tlvs.last_peer) {
- if(NULL != port->tlvs.last_peer->info)
- free(port->tlvs.last_peer->info);
- free(port->tlvs.last_peer);
- port->tlvs.last_peer = NULL;
- }
- mibUpdateObjects(port);
- } else if (port->tlvs.last_peer == NULL) {
- /* First tlv. Create and load */
- load_peer_tlvs(port,tlv, LAST_PEER);
- mibUpdateObjects(port); /* Put 1st in peer mem */
- } else {
- if (tlv->length == port->tlvs.last_peer->length) {
- if (memcmp(tlv->info, port->tlvs.last_peer->info,
- tlv->length) != 0) {
- /* Strings are different unpack the tlvs and
- * store in peer mem
- * Load tlv in last_peer
- */
- mibUpdateObjects(port);
- port->tlvs.last_peer->type = tlv->type;
- port->tlvs.last_peer->length = tlv->length;
- if (port->tlvs.last_peer->info) {
- memcpy(port->tlvs.last_peer->info,
- tlv->info,tlv->length);
- }
- }
- } else {
- /* Lengths are different unpack the tlvs and store in
- * peer memory. Load tlv in last_peer
- */
- if(NULL != port->tlvs.last_peer) {
- if(NULL != port->tlvs.last_peer->info)
- free(port->tlvs.last_peer->info);
- free(port->tlvs.last_peer);
- port->tlvs.last_peer = NULL;
- }
- load_peer_tlvs(port,tlv, LAST_PEER);
- mibUpdateObjects(port);
- }
- }
- port->tlvs.cur_peer = free_unpkd_tlv(tlv);
- return;
-}
-
bool process_dcbx_ctrl_tlv(struct port *port)
{
struct dcbx_tlvs *tlvs;
--
1.7.4.4

View File

@ -0,0 +1,32 @@
From ce407dd26ca8cf61be75364e900c5ebcef3dd2cb Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:47:48 -0700
Subject: [PATCH 40/51] lldpad: remove print statements that are not helpful
Remove start/stop print statements from lldpad core. These
are not paticularly helpful for debugging and certainly
do not warrant being set at _WARN level.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
lldpad.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/lldpad.c b/lldpad.c
index 92de585..8a5df5b 100644
--- a/lldpad.c
+++ b/lldpad.c
@@ -410,9 +410,7 @@ int main(int argc, char *argv[])
exit(1);
}
- LLDPAD_WARN("%s is starting", argv[0]);
eloop_run();
- LLDPAD_WARN("%s is stopping", argv[0]);
clean_lldp_agent();
deinit_modules();
--
1.7.4.4

View File

@ -0,0 +1,45 @@
From 5d44f2fdd5f2074af2ec49fd89b8f1cfd0410879 Mon Sep 17 00:00:00 2001
From: Zhifeng, Cai <bluewindow@h3c.com>
Date: Sun, 6 Mar 2011 21:39:13 -0800
Subject: [PATCH 24/51] lldpad: remove unused cmd_buf variable in
clif_request()
cmd_buf is no longer used remove it.
Suggested-by: Zhifeng, Cai <bluewindow@h3c.com>
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
clif.c | 12 +++---------
1 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/clif.c b/clif.c
index 9e256f2..a6dc3d8 100644
--- a/clif.c
+++ b/clif.c
@@ -103,19 +103,13 @@ int clif_request(struct clif *clif, const char *cmd, size_t cmd_len,
int res;
fd_set rfds;
const char *_cmd;
- char *cmd_buf = NULL;
size_t _cmd_len;
- {
- _cmd = cmd;
- _cmd_len = cmd_len;
- }
+ _cmd = cmd;
+ _cmd_len = cmd_len;
- if (send(clif->s, _cmd, _cmd_len, 0) < 0) {
- free(cmd_buf);
+ if (send(clif->s, _cmd, _cmd_len, 0) < 0)
return -1;
- }
- free(cmd_buf);
for (;;) {
tv.tv_sec = CMD_RESPONSE_TIMEOUT;
--
1.7.4.4

View File

@ -0,0 +1,43 @@
From c18a94f5600d65f414e9ffe5579171c6700078fc Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:47:23 -0700
Subject: [PATCH 36/51] lldpad: rtnl_recv_operstate uses incorrect recv length
lldpad monitors the current operstate to stop repeated resets
from occurring while dcbx or other LLDP TLVs are being negotiated.
This can occur when the driver resets the device due to a LLDP
negotiated object.
In rtnl_recv_operstate() used to query the interface operstate the
recv message length was not being set correctly. This resulted in
netlink messages being truncated. Specifically, nlh is a pointer
to nlmsghdr and points to the head of the allocated memory block
used for the nlmsg. Taking the sizeof() of this only returns the
size of the nlsg header.
This was seen during DCB testing and resulted in repeated link resets
because the hardware was being reprogrammed multiple times during
link negotiation until the DCB negotiation reached a steady state.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
lldp_rtnl.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lldp_rtnl.c b/lldp_rtnl.c
index 77b013d..b966261 100644
--- a/lldp_rtnl.c
+++ b/lldp_rtnl.c
@@ -222,7 +222,7 @@ static ssize_t rtnl_recv_operstate(int s, int ifindex,
/* recv ifname reply */
memset(nlh, 0, NLMSG_SIZE);
- rc = recv(s, (void *) nlh, sizeof(*nlh), MSG_DONTWAIT);
+ rc = recv(s, (void *) nlh, NLMSG_SIZE, MSG_DONTWAIT);
if (rc < 0)
goto out;
ifi = NLMSG_DATA(nlh);
--
1.7.4.4

View File

@ -0,0 +1,109 @@
From 5b74605009a7d14bd93e5b068a55e28ff91dd02a Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Tue, 8 Feb 2011 00:51:58 -0800
Subject: [PATCH 07/51] new: call VDP station state machine on demand
With this patch the VDP station state machine is now only called if work is
pending. This reduces code paths and avoids problems e.g. with link up/down
events and VM operations in parallel.
Signed-off-by: Jens Osterkamp <jens@linux.vnet.ibm.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
event_iface.c | 3 +--
lldp_vdp.c | 24 ++++++++++++------------
lldp_vdp_cmds.c | 1 -
3 files changed, 13 insertions(+), 15 deletions(-)
diff --git a/event_iface.c b/event_iface.c
index 5d447c6..51ea951 100644
--- a/event_iface.c
+++ b/event_iface.c
@@ -454,8 +454,7 @@ static int event_if_parse_setmsg(struct nlmsghdr *nlh)
return -EINVAL;
}
- vdp_somethingChangedLocal(profile, true);
- vdp_vsi_sm_station(p);
+ vdp_somethingChangedLocal(p, true);
return 0;
}
diff --git a/lldp_vdp.c b/lldp_vdp.c
index 0cbf71e..6ebf171 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -131,16 +131,16 @@ void vdp_print_profile(struct vsi_profile *profile)
/* vdp_somethingChangedLocal - set flag if profile has changed
* @profile: profile to set the flag for
- * @mode: mode to set the flag to
+ * @flag: set the flag to true or false
*
* no return value
*
* set the localChange flag with a mode to indicate a profile has changed.
* used next time when a ecpdu with profiles is sent out.
*/
-void vdp_somethingChangedLocal(struct vsi_profile *profile, bool mode)
+void vdp_somethingChangedLocal(struct vsi_profile *profile, bool flag)
{
- profile->localChange = mode;
+ profile->localChange = flag;
}
/* vdp_keepaliveTimer_expired - checks for expired ack timer
@@ -192,10 +192,10 @@ void vdp_timeout_handler(void *eloop_data, void *user_ctx)
if (p->keepaliveTimer > 0)
p->keepaliveTimer--;
- if (vdp_ackTimer_expired(p))
- vdp_vsi_sm_station(p);
-
- if (vdp_keepaliveTimer_expired(p))
+ if (vdp_ackTimer_expired(p) ||
+ vdp_keepaliveTimer_expired(p) ||
+ p->ackReceived ||
+ p->localChange)
vdp_vsi_sm_station(p);
}
@@ -481,9 +481,11 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
case VSI_DEASSOC_PROCESSING:
profile->response = VDP_RESPONSE_NO_RESPONSE;
vdp_stop_keepaliveTimer(profile);
- vdp_somethingChangedLocal(profile, true);
- ecp_somethingChangedLocal(vd);
- ecp_tx_run_sm(vd);
+ if (profile->localChange) {
+ ecp_somethingChangedLocal(vd);
+ ecp_tx_run_sm(vd);
+ }
+ vdp_somethingChangedLocal(profile, false);
vdp_start_ackTimer(profile);
break;
case VSI_EXIT:
@@ -825,8 +827,6 @@ int vdp_indicate(struct vdp_data *vd, struct unpacked_tlv *tlv, int ecp_mode)
LLDPAD_DBG("%s(%i): profile response: %s (%i).\n", __func__, __LINE__,
vsi_responses[p->response], p->response);
-
- vdp_vsi_sm_station(p);
} else {
LLDPAD_DBG("%s(%i): station: profile not found !\n", __func__, __LINE__);
/* ignore profile */
diff --git a/lldp_vdp_cmds.c b/lldp_vdp_cmds.c
index 9f67d7d..387aecd 100644
--- a/lldp_vdp_cmds.c
+++ b/lldp_vdp_cmds.c
@@ -323,7 +323,6 @@ static int set_arg_mode(struct cmd *cmd, char *arg, char *argvalue,
}
vdp_somethingChangedLocal(profile, true);
- vdp_vsi_sm_station(p);
return cmd_success;
}
--
1.7.4.4

View File

@ -0,0 +1,32 @@
From 6bcb3c33134e72f7b0b474a1c058b9e629eb1056 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Tue, 8 Feb 2011 00:51:10 -0800
Subject: [PATCH 06/51] new: change VDP ACK timer value
This patch adapts the ACK timer value of the VDP state machine to be based
on ECP Ack timeout as this is described in the draft.
Signed-off-by: Jens Osterkamp <jens@linux.vnet.ibm.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
include/lldp_vdp.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/lldp_vdp.h b/include/lldp_vdp.h
index 2caf57a..3d1411d 100644
--- a/include/lldp_vdp.h
+++ b/include/lldp_vdp.h
@@ -65,8 +65,8 @@ 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
-#define VDP_ACK_TIMER_DEFAULT 150
+#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_KEEPALIVE_TIMER_STOPPED -1
#define VDP_ACK_TIMER_STOPPED -1
--
1.7.4.4

View File

@ -0,0 +1,49 @@
From 426a50e89645bde78c1ff7b286605105ddf5cc2a Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Tue, 8 Feb 2011 00:51:02 -0800
Subject: [PATCH 05/51] new: change the ECP ack timer from RTE based to fixed
This patch adapts the ECP ack timer value from the RTE based value to a
fixed one as described in newer drafts.
Signed-off-by: Jens Osterkamp <jens@linux.vnet.ibm.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
ecp/ecp.h | 3 +--
ecp/ecp_tx.c | 6 ++----
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/ecp/ecp.h b/ecp/ecp.h
index 2c0ea0f..7fbfa58 100644
--- a/ecp/ecp.h
+++ b/ecp/ecp.h
@@ -34,8 +34,7 @@
#define ECP_MAX_RETRIES 3
#define ECP_SEQUENCE_NR_START 0x0
-#define ECP_TRANSMISSION_TIMER(rte) EVB_RTM(rte)*EVB_RTG
-#define ECP_TRANSMISSION_DIVIDER 10000
+#define ECP_ACK_TIMER_DEFAULT 500000 /* 500 ms in us */
typedef enum {
ECP_REQUEST = 0,
diff --git a/ecp/ecp_tx.c b/ecp/ecp_tx.c
index 6dff8c7..54a278f 100644
--- a/ecp/ecp_tx.c
+++ b/ecp/ecp_tx.c
@@ -321,10 +321,8 @@ static void ecp_tx_start_ackTimer(struct vdp_data *vd)
vd->ecp.ackTimerExpired = false;
- rte = evb_get_rte(vd->ifname);
-
- secs = ECP_TRANSMISSION_TIMER(rte) / ECP_TRANSMISSION_DIVIDER;
- usecs = ECP_TRANSMISSION_TIMER(rte) % ECP_TRANSMISSION_DIVIDER;
+ secs = 0;
+ usecs = ECP_ACK_TIMER_DEFAULT;
LLDPAD_DBG("%s(%i)-%s: starting timer\n", __func__, __LINE__,
vd->ifname);
--
1.7.4.4

View File

@ -0,0 +1,477 @@
From a2b1745d86cce79b0e4f9aa01045f06218afc991 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Thu, 3 Feb 2011 23:00:02 +0000
Subject: [PATCH 01/51] new: rework of VDP code towards newer drafts
This is a first rework of the VDP towards the changes in newer drafts.
It contains the following changes:
- bugfix: prevent sending of duplicate keepalives
While checking ECP traffic on the wire a lot of ECP frames being
sent until an ack was received. This fixes it.
- allow transition from UNASSOCIATED to DEASSOCIATED
This is necessary in cases when lldpad has been terminated,
but VMs are still running, to allow these VMs to be deassociated.
- do not remove profile on ifdown
Up to now profiles were deleted and the vdp_data struct removed from the
list on "ifconfig eth? down".
Now profiles are retained during interface down. Processing of profiles will
continue after the interface comes up again. Keepalives are sent as before.
Signed-off-by: Jens Osterkamp <jens@linux.vnet.ibm.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
ecp/ecp.c | 2 -
include/lldp_vdp.h | 14 +++-
lldp_vdp.c | 218 +++++++++++++++++++++++++---------------------------
3 files changed, 116 insertions(+), 118 deletions(-)
diff --git a/ecp/ecp.c b/ecp/ecp.c
index 66e97a4..3798ae6 100644
--- a/ecp/ecp.c
+++ b/ecp/ecp.c
@@ -92,8 +92,6 @@ int ecp_deinit(char *ifname)
ecp_tx_stop_ackTimer(vd);
- l2_packet_deinit(vd->ecp.l2);
-
return 0;
fail:
diff --git a/include/lldp_vdp.h b/include/lldp_vdp.h
index 9906b52..146e29d 100644
--- a/include/lldp_vdp.h
+++ b/include/lldp_vdp.h
@@ -71,8 +71,11 @@ enum {
#define VDP_MACVLAN_FORMAT_1 1
-#define VDP_TRANSMISSION_TIMER(rte) 3*EVB_RTM(rte)*EVB_RTG
-#define VDP_TRANSMISSION_DIVIDER 10000
+#define VDP_TIMER_GRANULARITY 10000 /* 10 ms in us */
+#define VDP_KEEPALIVE_TIMER_DEFAULT 1000
+#define VDP_ACK_TIMER_DEFAULT 150
+#define VDP_KEEPALIVE_TIMER_STOPPED -1
+#define VDP_ACK_TIMER_STOPPED -1
#define VDP_ROLE_STATION 0
#define VDP_ROLE_BRIDGE 1
@@ -126,9 +129,9 @@ struct vsi_profile {
u8 mac[6]; /* TODO: currently only one MAC/VLAN pair supported, more later */
u16 vlan;
struct port *port;
- int ackTimerExpired;
+ int ackTimer;
int ackReceived;
- int keepaliveTimerExpired;
+ int keepaliveTimer;
int state;
bool localChange;
LIST_ENTRY(vsi_profile) profile;
@@ -139,6 +142,8 @@ struct vdp_data {
struct ecp ecp;
struct unpacked_tlv *vdp;
int role;
+ int keepaliveTimer;
+ int ackTimer;
LIST_HEAD(profile_head, vsi_profile) profile_head;
LIST_ENTRY(vdp_data) entry;
};
@@ -154,6 +159,7 @@ 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 b2cc594..0cbf71e 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -153,146 +153,137 @@ void vdp_somethingChangedLocal(struct vsi_profile *profile, bool mode)
*/
static bool vdp_keepaliveTimer_expired(struct vsi_profile *profile)
{
- return profile->keepaliveTimerExpired;
+ return (profile->keepaliveTimer == 0);
}
-/* vdp_acktimeout_handler - handles the ack timer expiry
+/* vdp_ackTimer_expired - checks for expired ack timer
+ * @profile: profile to be checked
+ *
+ * returns true or false
+ *
+ * returns value of profile->ackTimerExpired, true if ack timer has expired,
+ * false otherwise.
+ */
+static bool vdp_ackTimer_expired(struct vsi_profile *profile)
+{
+ return (profile->ackTimer == 0);
+}
+
+/* vdp_timeout_handler - handles the timer expiry
* @eloop_data: data structure of event loop
- * @user_ctx: user context, profile here
+ * @user_ctx: user context, vdp_data here
*
* no return value
*
- * called when the VDP ack timer has expired. sets a flag and calls the VDP
- * state machine.
+ * called when the VDP timer has expired. Decrements ack and keepaliveTimer
+ * and calls the VDP station state machine if necessary.
*/
-void vdp_keepalivetimeout_handler(void *eloop_data, void *user_ctx)
+void vdp_timeout_handler(void *eloop_data, void *user_ctx)
{
- struct vsi_profile *profile;
+ struct vdp_data *vd;
+ struct vsi_profile *p;
- profile = (struct vsi_profile *) user_ctx;
+ vd = (struct vdp_data *) user_ctx;
- profile->keepaliveTimerExpired = true;
+ LIST_FOREACH(p, &vd->profile_head, profile) {
+ if (p->ackTimer > 0)
+ p->ackTimer--;
- LLDPAD_DBG("%s(%i)-%s: keepalive timer expired\n", __func__, __LINE__,
- profile->port->ifname);
+ if (p->keepaliveTimer > 0)
+ p->keepaliveTimer--;
- vdp_vsi_sm_station(profile);
+ if (vdp_ackTimer_expired(p))
+ vdp_vsi_sm_station(p);
+
+ if (vdp_keepaliveTimer_expired(p))
+ vdp_vsi_sm_station(p);
+ }
+
+ vdp_start_timer(vd);
}
-/* vdp_stop_keepaliveTimer - stop the VDP keepalive timer
- * @profile: profile to process
+/* vdp_stop_timer - stop the VDP timer
+ * @vd: vdp_data for the interface
*
* returns the number of removed handlers
*
- * stops the VDP keepalive timer. Used when the profile changes state e.g. a deassoc
- * has been requested.
+ * stops the VDP timer. Used e.g. when the host interface goes down.
*/
-static int vdp_stop_keepaliveTimer(struct vsi_profile *profile)
+static int vdp_stop_timer(struct vdp_data *vd)
{
- LLDPAD_DBG("%s(%i)-%s: stopping keepalive timer\n", __func__, __LINE__,
- profile->port->ifname);
+ LLDPAD_DBG("%s(%i)-%s: stopping vdp timer\n", __func__, __LINE__,
+ vd->ifname);
- return eloop_cancel_timeout(vdp_keepalivetimeout_handler, NULL, (void *) profile);
+ return eloop_cancel_timeout(vdp_timeout_handler, NULL, (void *) vd);
}
-/* vdp_start_keepaliveTimer - starts the VDP keepalive timer
- * @profile: profile to process
+/* vdp_start_timer - starts the VDP timer
+ * @vd: vdp_data for the interface
*
* returns 0 on success, -1 on error
*
- * starts the keepalive timer after a ack frame has received.
+ * starts the VDP timer when the interface comes up.
*/
-static int vdp_start_keepaliveTimer(struct vsi_profile *profile)
+static int vdp_start_timer(struct vdp_data *vd)
{
unsigned int secs, usecs, rte;
- profile->keepaliveTimerExpired = false;
-
- rte = evb_get_rte(profile->port->ifname);
-
- secs = VDP_TRANSMISSION_TIMER(rte) / VDP_TRANSMISSION_DIVIDER;
- usecs = VDP_TRANSMISSION_TIMER(rte) % VDP_TRANSMISSION_DIVIDER;
+ secs = 0;
+ usecs = VDP_TIMER_GRANULARITY;
- LLDPAD_DBG("%s(%i)-%s: starting keepalive timer (%i secs, %i usecs) \n", __func__, __LINE__,
- profile->port->ifname, secs, usecs);
-
- return eloop_register_timeout(secs, usecs, vdp_keepalivetimeout_handler, NULL, (void *) profile);
+ return eloop_register_timeout(secs, usecs, vdp_timeout_handler, NULL, (void *) vd);
}
-/* vdp_ackTimer_expired - checks for expired ack timer
- * @profile: profile to be checked
- *
- * returns true or false
+/* vdp_start_ackTimer - starts the VDP ack timer
+ * @profile: profile to process
*
- * returns value of profile->ackTimerExpired, true if ack timer has expired,
- * false otherwise.
+ * starts the ack timer when a frame has been sent out.
*/
-static bool vdp_ackTimer_expired(struct vsi_profile *profile)
+static void vdp_start_ackTimer(struct vsi_profile *profile)
{
- return profile->ackTimerExpired;
+ profile->ackTimer = VDP_ACK_TIMER_DEFAULT;
+
+ LLDPAD_DBG("%s(%i)-%s: starting ack timer (%i)\n", __func__, __LINE__,
+ profile->port->ifname, profile->ackTimer);
}
-/* vdp_acktimeout_handler - handles the ack timer expiry
- * @eloop_data: data structure of event loop
- * @user_ctx: user context, profile here
- *
- * no return value
+/* vdp_start_ackTimer - starts the VDP keepalive timer for a profile
+ * @profile: profile to process
*
- * called when the VDP ack timer has expired. sets a flag and calls the VDP
- * state machine.
+ * starts the keepalive timer when a frame has been sent out.
*/
-void vdp_acktimeout_handler(void *eloop_data, void *user_ctx)
+static void vdp_start_keepaliveTimer(struct vsi_profile *profile)
{
- struct vsi_profile *profile;
-
- profile = (struct vsi_profile *) user_ctx;
+ profile->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT;
- profile->ackTimerExpired = true;
-
- LLDPAD_DBG("%s(%i)-%s: ack timer expired\n", __func__, __LINE__,
- profile->port->ifname);
-
- vdp_vsi_sm_station(profile);
+ LLDPAD_DBG("%s(%i)-%s: starting keepalive timer (%i)\n", __func__, __LINE__,
+ profile->port->ifname, profile->keepaliveTimer);
}
-/* vdp_stop_ackTimer - stop the VDP ack timer
+/* vdp_stop_ackTimer - stops the VDP ack timer
* @profile: profile to process
*
- * returns the number of removed handlers
- *
- * stops the VDP ack timer. used when a ack frame for the profile has been
- * received.
+ * stops the ack timer when a frame has been sent out.
*/
-static int vdp_stop_ackTimer(struct vsi_profile *profile)
+static void vdp_stop_ackTimer(struct vsi_profile *profile)
{
- LLDPAD_DBG("%s(%i)-%s: stopping ack timer\n", __func__, __LINE__,
- profile->port->ifname);
+ profile->ackTimer = VDP_ACK_TIMER_STOPPED;
- return eloop_cancel_timeout(vdp_acktimeout_handler, NULL, (void *) profile);
+ LLDPAD_DBG("%s(%i)-%s: stopping ack timer (%i)\n", __func__, __LINE__,
+ profile->port->ifname, profile->ackTimer);
}
-/* vdp_start_ackTimer - starts the VDP ack timer
+/* vdp_stop_ackTimer - stops the VDP keepalive timer for a profile
* @profile: profile to process
*
- * returns 0 on success, -1 on error
- *
- * starts the ack timer when a frame has been sent out.
+ * stops the keepalive timer when a frame has been sent out.
*/
-static int vdp_start_ackTimer(struct vsi_profile *profile)
+static void vdp_stop_keepaliveTimer(struct vsi_profile *profile)
{
- unsigned int secs, usecs, rte;
+ profile->keepaliveTimer = VDP_KEEPALIVE_TIMER_STOPPED;
- profile->ackTimerExpired = false;
-
- rte = evb_get_rte(profile->port->ifname);
-
- secs = VDP_TRANSMISSION_TIMER(rte) / VDP_TRANSMISSION_DIVIDER;
- usecs = VDP_TRANSMISSION_TIMER(rte) % VDP_TRANSMISSION_DIVIDER;
-
- LLDPAD_DBG("%s(%i)-%s: starting ack timer (%i secs, %i usecs)\n", __func__, __LINE__,
- profile->port->ifname, secs, usecs);
-
- return eloop_register_timeout(secs, usecs, vdp_acktimeout_handler, NULL, (void *) profile);
+ LLDPAD_DBG("%s(%i)-%s: stopping keepalive timer (%i)\n", __func__, __LINE__,
+ profile->port->ifname, profile->keepaliveTimer);
}
/* vdp_vsi_change_station_state - changes the VDP station sm state
@@ -325,6 +316,7 @@ void vdp_vsi_change_station_state(struct vsi_profile *profile, u8 newstate)
break;
case VSI_DEASSOC_PROCESSING:
assert((profile->state == VSI_PREASSOCIATED) ||
+ (profile->state == VSI_UNASSOCIATED) ||
(profile->state == VSI_ASSOCIATED));
break;
case VSI_EXIT:
@@ -361,13 +353,21 @@ static bool vdp_vsi_set_station_state(struct vsi_profile *profile)
if ((profile->mode == VDP_MODE_PREASSOCIATE) ||
(profile->mode == VDP_MODE_PREASSOCIATE_WITH_RR)) {
vdp_vsi_change_station_state(profile, VSI_PREASSOC_PROCESSING);
+ vdp_somethingChangedLocal(profile, true);
return true;
} else if (profile->mode == VDP_MODE_ASSOCIATE) {
vdp_vsi_change_station_state(profile, VSI_ASSOC_PROCESSING);
+ vdp_somethingChangedLocal(profile, true);
+ return true;
+ } else if (profile->mode == VDP_MODE_DEASSOCIATE) {
+ vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING);
+ vdp_somethingChangedLocal(profile, true);
return true;
}
return false;
case VSI_ASSOC_PROCESSING:
+ LLDPAD_DBG("profile->ackReceived %i, vdp_ackTimer %i\n",
+ profile->ackReceived, profile->ackTimer);
if (profile->ackReceived) {
vdp_vsi_change_station_state(profile, VSI_ASSOCIATED);
return true;
@@ -439,9 +439,10 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
break;
case VSI_ASSOC_PROCESSING:
profile->response = VDP_RESPONSE_NO_RESPONSE;
- vdp_somethingChangedLocal(profile, true);
- ecp_somethingChangedLocal(vd);
- ecp_tx_run_sm(vd);
+ if (profile->localChange) {
+ ecp_somethingChangedLocal(vd);
+ ecp_tx_run_sm(vd);
+ }
vdp_somethingChangedLocal(profile, false);
vdp_start_ackTimer(profile);
break;
@@ -449,36 +450,33 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
profile->ackReceived = false;
vdp_somethingChangedLocal(profile, false);
vdp_stop_ackTimer(profile);
- if (profile->keepaliveTimerExpired) {
+ if (vdp_keepaliveTimer_expired(profile)) {
vdp_somethingChangedLocal(profile, true);
ecp_somethingChangedLocal(vd);
ecp_tx_run_sm(vd);
+ vdp_start_keepaliveTimer(profile);
}
- vdp_start_keepaliveTimer(profile);
- /* TODO:
- * vsiError = ProcRxandSetCfg(remoteTLV, localtlv, vsistate);
- * if (!vsiError) vsistate=ASSOCIATED */
break;
case VSI_PREASSOC_PROCESSING:
/* send out profile */
profile->response = VDP_RESPONSE_NO_RESPONSE;
- vdp_somethingChangedLocal(profile, true);
- ecp_somethingChangedLocal(vd);
- ecp_tx_run_sm(vd);
+ if (profile->localChange) {
+ ecp_somethingChangedLocal(vd);
+ ecp_tx_run_sm(vd);
+ }
+ vdp_somethingChangedLocal(profile, false);
vdp_start_ackTimer(profile);
break;
case VSI_PREASSOCIATED:
profile->ackReceived = false;
vdp_somethingChangedLocal(profile, false);
vdp_stop_ackTimer(profile);
- if (profile->keepaliveTimerExpired) {
+ if (vdp_keepaliveTimer_expired(profile)) {
vdp_somethingChangedLocal(profile, true);
ecp_somethingChangedLocal(vd);
ecp_tx_run_sm(vd);
}
vdp_start_keepaliveTimer(profile);
- /* TODO vsiError = ProcRxandSetCfg(remoteTLV, localtlv, vsistate);
- * if (!vsiError) vsistate=PREASSOCIATED */
break;
case VSI_DEASSOC_PROCESSING:
profile->response = VDP_RESPONSE_NO_RESPONSE;
@@ -490,7 +488,6 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
break;
case VSI_EXIT:
/* TODO: send DEASSOC here ? */
- vdp_stop_ackTimer(profile);
vdp_remove_profile(profile);
break;
default:
@@ -822,7 +819,7 @@ int vdp_indicate(struct vdp_data *vd, struct unpacked_tlv *tlv, int ecp_mode)
__func__, __LINE__, p->localChange, p->ackReceived);
p->ackReceived = true;
- p->keepaliveTimerExpired = false;
+ p->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT;
p->mode = vdp->mode;
p->response = vdp->response;
@@ -1057,7 +1054,6 @@ struct vsi_profile *vdp_add_profile(struct vsi_profile *profile)
return NULL;
}
- profile->keepaliveTimerExpired = true;
profile->response = VDP_RESPONSE_NO_RESPONSE;
vdp_print_profile(profile);
@@ -1150,16 +1146,8 @@ void vdp_ifdown(char *ifname)
if (ecp_deinit(ifname))
goto out_err;
- LIST_REMOVE(vd, entry);
+ vdp_stop_timer(vd);
- LIST_FOREACH(p, &vd->profile_head, profile) {
- vdp_stop_ackTimer(p);
- vdp_stop_keepaliveTimer(p);
- LIST_REMOVE(p, profile);
- free(p);
- }
- vdp_free_tlv(vd);
- free(vd);
LLDPAD_INFO("%s:%s vdp data removed\n", __func__, ifname);
return;
out_err:
@@ -1187,7 +1175,7 @@ void vdp_ifup(char *ifname)
vd = vdp_data(ifname);
if (vd) {
LLDPAD_WARN("%s:%s vdp data already exists !\n", __func__, ifname);
- return;
+ goto out_start_timer;
}
/* not found, alloc/init per-port module data */
@@ -1222,6 +1210,12 @@ void vdp_ifup(char *ifname)
goto out_err;
}
+ vd->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT;
+ vd->ackTimer = VDP_ACK_TIMER_DEFAULT;
+
+out_start_timer:
+ vdp_start_timer(vd);
+
LLDPAD_DBG("%s:%s vdp added\n", __func__, ifname);
return;
--
1.7.4.4

View File

@ -0,0 +1,33 @@
From 44ce9bbdbf38e6d090016ef9fd8a8b9063f4821e Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Sun, 6 Mar 2011 21:37:50 -0800
Subject: [PATCH 11/51] no error if the profile already exists
In case we receive a profile for addition that already exists, there is no
need to return NULL to indicate an error. This may have just been a
duplicate request or the profile already existed e.g. if libvirt has been
restarted.
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_vdp.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lldp_vdp.c b/lldp_vdp.c
index a3781b0..73ca59f 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -1108,7 +1108,7 @@ struct vsi_profile *vdp_add_profile(struct vsi_profile *profile)
if (p->mode == profile->mode) {
LLDPAD_DBG("%s(%i): profile already exists, ignoring !\n",
__func__, __LINE__);
- return NULL;
+ return p;
} else {
LLDPAD_DBG("%s(%i): taking new mode !\n", __func__,
__LINE__);
--
1.7.4.4

View File

@ -0,0 +1,90 @@
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

View File

@ -0,0 +1,370 @@
From 0aeddf9df8fe679b22063550d941831b2644b3a0 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Wed, 6 Apr 2011 08:33:57 -0700
Subject: [PATCH 29/51] rework EVB TLV code
This patch reworks and simplifies the EVB handling code.
It includes
- EVB [cs]vsi endianness fixes.
- allow setting capabilities to none
- announce supported capabilities as in policy
- add sanity check for ed->last allocation
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>
---
include/lldp_evb.h | 2 +-
lldp_evb.c | 175 +++++++++++++++++++++++----------------------------
lldp_evb_cmds.c | 3 +
3 files changed, 83 insertions(+), 97 deletions(-)
diff --git a/include/lldp_evb.h b/include/lldp_evb.h
index f1f2121..e307e05 100644
--- a/include/lldp_evb.h
+++ b/include/lldp_evb.h
@@ -66,9 +66,9 @@ struct evb_data {
char ifname[IFNAMSIZ];
struct unpacked_tlv *evb;
struct tlv_info_evb *tie;
+ struct tlv_info_evb *last;
/* local policy */
struct tlv_info_evb *policy;
- int state;
LIST_ENTRY(evb_data) entry;
};
diff --git a/lldp_evb.c b/lldp_evb.c
index a43f3e8..0839054 100644
--- a/lldp_evb.c
+++ b/lldp_evb.c
@@ -64,8 +64,8 @@ static void evb_print_tlvinfo(struct tlv_info_evb *tie)
LLDPAD_INFO("%s(%i): configured forwarding mode: %02x\n", __FILE__, __LINE__, tie->cmode);
LLDPAD_INFO("%s(%i): supported capabilities: %02x\n", __FILE__, __LINE__, tie->scap);
LLDPAD_INFO("%s(%i): configured capabilities: %02x\n", __FILE__, __LINE__, tie->ccap);
- LLDPAD_INFO("%s(%i): supported no. of vsis: %04i\n", __FILE__, __LINE__, tie->svsi);
- LLDPAD_INFO("%s(%i): configured no. of vsis: %04i\n", __FILE__, __LINE__, tie->cvsi);
+ LLDPAD_INFO("%s(%i): supported no. of vsis: %04i\n", __FILE__, __LINE__, ntohs(tie->svsi));
+ LLDPAD_INFO("%s(%i): configured no. of vsis: %04i\n", __FILE__, __LINE__, ntohs(tie->cvsi));
LLDPAD_INFO("%s(%i): rte: %02i\n", __FILE__, __LINE__, tie->rte);
}
@@ -100,6 +100,30 @@ unsigned int evb_get_rte(char *ifname)
return (unsigned int) ed->tie->rte;
}
+/* evb_process_tlv - processes the tlv
+ * @ed: evb_data for the interface
+ * @tie: incoming tlv
+ *
+ * checks the received tlv and takes over values as needed.
+ *
+ */
+static void evb_update_tlv(struct evb_data *ed)
+{
+ /* waiting for valid packets to pour in
+ * if valid packet was received,
+ * - check parameters with what we have offered for this if,
+ * - fill structure with data,
+ * - enable local tx
+ */
+ if (evb_check_and_fill(ed, ed->last) != TLV_OK) {
+ LLDPAD_ERR("Invalid contents of EVB Cfg TLV !\n");
+ return;
+ }
+
+ somethingChangedLocal(ed->ifname); /* trigger tx with new values */
+ return;
+}
+
/*
* evb_bld_cfg_tlv - build the EVB TLV
* @ed: the evb data struct
@@ -124,9 +148,10 @@ static int evb_bld_cfg_tlv(struct evb_data *ed)
if (ed->tie->smode != ed->policy->smode) {
ed->tie->smode = ed->policy->smode;
- ed->state = EVB_OFFER_CAPABILITIES;
}
+ evb_update_tlv(ed);
+
tlv = create_tlv();
if (!tlv)
goto out_err;
@@ -142,7 +167,7 @@ static int evb_bld_cfg_tlv(struct evb_data *ed)
}
memcpy(tlv->info, ed->tie, tlv->length);
- LLDPAD_DBG("%s(%i): TLV about to be sent out:", __func__, __LINE__);
+ LLDPAD_DBG("%s(%i): TLV about to be sent out:\n", __func__, __LINE__);
evb_dump_tlv(tlv);
ed->evb = tlv;
@@ -178,7 +203,7 @@ static int evb_init_cfg_tlv(struct evb_data *ed)
LLDP_EVB_CAPABILITY_PROTOCOL_VDP;
ed->policy->cmode = 0;
ed->policy->ccap = 0;
- ed->policy->svsi = LLDP_EVB_DEFAULT_SVSI;
+ ed->policy->svsi = htons(LLDP_EVB_DEFAULT_SVSI);
ed->policy->rte = LLDP_EVB_DEFAULT_RTE;
/* pull forwarding mode into policy */
@@ -221,6 +246,10 @@ static int evb_init_cfg_tlv(struct evb_data *ed)
ed->policy->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_VDP;
}
+ if (strcasestr(param, VAL_EVB_CAPA_NONE)) {
+ ed->policy->scap = 0;
+ }
+
LLDPAD_DBG("%s:%s: policy param capabilities = %s.\n", __func__, ed->ifname, param);
LLDPAD_DBG("%s:%s: policy param scap = %x.\n", __func__, ed->ifname, ed->policy->scap);
}
@@ -247,10 +276,10 @@ static int evb_init_cfg_tlv(struct evb_data *ed)
LLDPAD_INFO("%s:%s: loading EVB policy for vsis failed, using default.\n",
__func__, ed->ifname);
} else {
- ed->policy->svsi = atoi(param);
+ ed->policy->svsi = htons(atoi(param));
LLDPAD_DBG("%s:%s: policy param vsis = %s.\n", __func__, ed->ifname, param);
- LLDPAD_DBG("%s:%s: policy param vsis = %i.\n", __func__, ed->ifname, ed->policy->svsi);
+ LLDPAD_DBG("%s:%s: policy param vsis = %i.\n", __func__, ed->ifname, ntohs(ed->policy->svsi));
}
/* load last used EVB TLV ... */
@@ -270,13 +299,23 @@ static int evb_init_cfg_tlv(struct evb_data *ed)
ed->tie->cmode = 0x0;
ed->tie->scap = ed->policy->scap;
ed->tie->ccap = 0x0;
- ed->tie->svsi = LLDP_EVB_DEFAULT_SVSI;
- ed->tie->cvsi = 0x0;
+ ed->tie->svsi = htons(LLDP_EVB_DEFAULT_SVSI);
+ ed->tie->cvsi = htons(0x0);
ed->tie->rte = LLDP_EVB_DEFAULT_RTE;
} else {
LLDPAD_INFO("%s(%i): loaded last used EVB TLV from file.\n", __FILE__, __LINE__);
}
+ ed->last = (struct tlv_info_evb *) calloc(1, sizeof(struct tlv_info_evb));
+
+ if (!ed->last) {
+ free(ed->policy);
+ free(ed->tie);
+ return ENOMEM;
+ }
+
+ ed->last->smode = LLDP_EVB_CAPABILITY_FORWARD_STANDARD;
+
return 0;
}
@@ -369,46 +408,62 @@ int evb_check_and_fill(struct evb_data *ed, struct tlv_info_evb *tie)
}
if ((tie->svsi < 0) || (tie->svsi > LLDP_EVB_DEFAULT_MAX_VSI)) {
- LLDPAD_ERR("nr of supported vsis (%i) exceeds allow value range !", tie->svsi);
+ LLDPAD_ERR("nr of supported vsis (%i) exceeds allow value range !", ntohs(tie->svsi));
return TLV_ERR;
}
if ((tie->cvsi < 0) || (tie->cvsi > LLDP_EVB_DEFAULT_MAX_VSI)) {
- LLDPAD_ERR("nr of configured vsis (%i) exceeds allow value range !", tie->cvsi);
+ LLDPAD_ERR("nr of configured vsis (%i) exceeds allow value range !", ntohs(tie->cvsi));
return TLV_ERR;
}
/* check bridge capabilities against local policy*/
/* if bridge supports RR and we support it as well, request it
* by setting smode in tlv to be sent out (ed->tie->smode) */
- if ( (tie->smode & ed->policy->smode) ==
- LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY ) {
+ if ((tie->smode & LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY) &&
+ (ed->policy->smode & LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY)) {
ed->tie->smode = LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY;
} else {
ed->tie->smode = LLDP_EVB_CAPABILITY_FORWARD_STANDARD;
}
+ /* maybe switch has already set the mode based on the saved info sent
+ * out on ifup */
+
+ if (tie->cmode == ed->tie->smode)
+ ed->tie->cmode = tie->cmode;
+
+ ed->tie->scap = ed->policy->scap;
+
/* If both sides support RTE, support and configure it */
if ((tie->scap & ed->policy->scap) & LLDP_EVB_CAPABILITY_PROTOCOL_RTE) {
- ed->tie->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_RTE;
ed->tie->ccap |= LLDP_EVB_CAPABILITY_PROTOCOL_RTE;
+ } else {
+ ed->tie->ccap &= ~LLDP_EVB_CAPABILITY_PROTOCOL_RTE;
}
/* If both sides support ECP, set it */
if ((tie->scap & ed->policy->scap) & LLDP_EVB_CAPABILITY_PROTOCOL_ECP) {
- ed->tie->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_ECP;
ed->tie->ccap |= LLDP_EVB_CAPABILITY_PROTOCOL_ECP;
+ } else {
+ ed->tie->ccap &= ~LLDP_EVB_CAPABILITY_PROTOCOL_ECP;
}
/* If both sides support VDP, set it */
if ((tie->scap & ed->policy->scap) & LLDP_EVB_CAPABILITY_PROTOCOL_VDP) {
- ed->tie->scap |= LLDP_EVB_CAPABILITY_PROTOCOL_VDP;
ed->tie->ccap |= LLDP_EVB_CAPABILITY_PROTOCOL_VDP;
+ } else {
+ ed->tie->ccap &= ~LLDP_EVB_CAPABILITY_PROTOCOL_VDP;
}
/* If supported caps include VDP take over min value of both */
- if (ed->tie->scap & LLDP_EVB_CAPABILITY_PROTOCOL_VDP)
- ed->tie->cvsi = MIN(ed->policy->svsi,tie->svsi);
+ if (ed->tie->scap & LLDP_EVB_CAPABILITY_PROTOCOL_VDP) {
+ ed->tie->svsi = tie->svsi;
+ ed->tie->cvsi = htons(vdp_vsis(ed->ifname));
+ } else {
+ ed->tie->svsi = 0;
+ ed->tie->cvsi = 0;
+ }
/* If both sides support RTE and value offer is > 0, set it */
if ((ed->tie->scap & LLDP_EVB_CAPABILITY_PROTOCOL_RTE) &&
@@ -422,80 +477,9 @@ int evb_check_and_fill(struct evb_data *ed, struct tlv_info_evb *tie)
LLDPAD_INFO("%s(%i): saved tlv_info_evb to config !\n", __FILE__, __LINE__);
}
- /* maybe switch has already set the mode based on the saved info sent
- * out on ifup */
-
- if (tie->cmode == ed->tie->smode)
- ed->tie->cmode = tie->cmode;
-
return TLV_OK;
}
-/* evb_compare
- *
- * compare our own and received tlv_info_evb
- */
-static int evb_compare(struct evb_data *ed, struct tlv_info_evb *tie)
-{
- LLDPAD_DBG("%s(%i): \n", __func__, __LINE__);
-
- if (ed->tie->cmode == tie->cmode)
- return 0;
- else
- return 1;
-}
-
-/* evb_statemachine:
- *
- * handle possible states during EVB capabilities exchange
- *
- * possible states: EVB_OFFER_CAPABILITIES
- * EVB_CONFIGURE
- * EVB_CONFIRMATION
- */
-static void evb_statemachine(struct evb_data *ed, struct tlv_info_evb *tie)
-{
- switch(ed->state) {
- case EVB_OFFER_CAPABILITIES:
- /* waiting for valid packets to pour in
- * if valid packet was received,
- * - check parameters with what we have offered for this if,
- * - fill structure with data,
- * - enable local tx
- * - switch to EVB_CONFIGURE
- */
- LLDPAD_DBG("%s: state -> EVB_OFFER_CAPABILITIES\n", __func__);
- if (evb_check_and_fill(ed, tie) != TLV_OK) {
- LLDPAD_ERR("Invalid contents of EVB Cfg TLV !\n");
- return;
- }
- somethingChangedLocal(ed->ifname); /* trigger tx with new values */
- ed->state = EVB_CONFIGURE;
- break;
- case EVB_CONFIGURE:
- /* we received a valid packet, if contents is same with our local settings
- * we can switch state to EVB_CONFIRMATION.*/
- LLDPAD_DBG("%s: state -> EVB_CONFIGURE\n", __func__);
- if (evb_compare(ed, tie)) {
- ed->state= EVB_OFFER_CAPABILITIES;
- } else {
- LLDPAD_ERR("tlv_info_evb now equal !\n");
- ed->state = EVB_CONFIRMATION;
- }
- somethingChangedLocal(ed->ifname);
- break;
- case EVB_CONFIRMATION:
- /* we are already in confirmation and received a new packet with
- * different parameters ? Check parameters. switch state back to
- * EVB_CONFIGURE ? */
- LLDPAD_DBG("%s: state -> EVB_CONFIRMATION\n", __func__);
- break;
- default:
- LLDPAD_ERR("EVB statemachine reached invalid state !\n");
- break;
- }
-}
-
/*
* evb_rchange: process RX TLV LLDPDU
*
@@ -531,15 +515,14 @@ static int evb_rchange(struct port *port, struct unpacked_tlv *tlv)
return TLV_OK;
}
- LLDPAD_DBG("%s(%i): received tlv:", __func__, __LINE__);
+ LLDPAD_DBG("%s(%i): received tlv:\n", __func__, __LINE__);
evb_dump_tlv(tlv);
- evb_print_tlvinfo(tie);
+ memcpy(ed->last, tlv->info, tlv->length);
+ evb_print_tlvinfo(ed->last);
- /* change state */
- evb_statemachine(ed, tie);
+ evb_update_tlv(ed);
- /* check which values have been taken over */
- LLDPAD_DBG("%s(%i): new tlv:", __func__, __LINE__);
+ LLDPAD_DBG("%s(%i): new tlv:\n", __func__, __LINE__);
evb_print_tlvinfo(ed->tie);
}
@@ -594,7 +577,6 @@ void evb_ifup(char *ifname)
goto out_free;
}
- ed->state = EVB_OFFER_CAPABILITIES;
evb_bld_tlv(ed);
ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB);
@@ -604,6 +586,7 @@ void evb_ifup(char *ifname)
out_free:
free(ed->tie);
+ free(ed->last);
free(ed->policy);
free(ed);
diff --git a/lldp_evb_cmds.c b/lldp_evb_cmds.c
index d04c012..454f638 100644
--- a/lldp_evb_cmds.c
+++ b/lldp_evb_cmds.c
@@ -325,6 +325,9 @@ static int set_arg_capabilities(struct cmd *cmd, char *arg, char *argvalue,
if (strcasestr(argvalue, VAL_EVB_CAPA_VDP))
scap |= LLDP_EVB_CAPABILITY_PROTOCOL_VDP;
+ if (strcasestr(argvalue, VAL_EVB_CAPA_NONE))
+ scap = 0;
+
ed->policy->scap = scap;
snprintf(arg_path, sizeof(arg_path), "%s%08x.capabilities",
--
1.7.4.4

View File

@ -0,0 +1,403 @@
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

View File

@ -0,0 +1,376 @@
From 1d747210d5248f4f4a7e38bb27b212b476d3b3b8 Mon Sep 17 00:00:00 2001
From: Jens Osterkamp <jens@linux.vnet.ibm.com>
Date: Thu, 3 Feb 2011 23:00:09 +0000
Subject: [PATCH 08/51] robustness: proper handling of LINK_DOWN/UP
This patch aims at more robustness in the VDP code, especially with regard
of error situations: link down/up, switch reboot, resends, ...
It contains the following changes:
- limit number of timers in VDP sm
Multiple link up netlink messages can cause more than one VDP
timer for one interface to be started. This causes multiple sendout of ECP
frames. This patch fixes it.
- stop keepalive timers while processing
Keepalive timers have to be stopped while the profile is in any processing.
- proper startup of VDP timer/ECP tx sm
After a LINK_DOWN/LINK_UP again, make sure that the VDP timer is properly
started again, even if multiple LINK_UP events are received.
Ensure that ECP tx state machine is in a proper state after LINK_UP.
- improved sequence nr handling
Given we send out multiple VDP TLVs in on ECP frame, we have to note the
sequence nr used to send it out. This enables us on reception of an ack
frame to identify all acked VSI types and mark them as ackReceived for
further processing.
- improved handling of timeouts and resends
implement a better control of timeouts and resends of ECP frames, if
necessary.
- stop ECP TX sm until ack was received
This should also save us some cycles.
Signed-off-by: Jens Osterkamp <jens@linux.vnet.ibm.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
ecp/ecp.c | 8 +++-
ecp/ecp_rx.c | 1 +
ecp/ecp_tx.c | 4 ++-
include/lldp_vdp.h | 2 +
lldp_vdp.c | 102 ++++++++++++++++++++++++++++++++++++---------------
5 files changed, 84 insertions(+), 33 deletions(-)
diff --git a/ecp/ecp.c b/ecp/ecp.c
index 3798ae6..1f46664 100644
--- a/ecp/ecp.c
+++ b/ecp/ecp.c
@@ -60,14 +60,18 @@ int ecp_init(char *ifname)
goto fail;
}
- vd->ecp.l2 = l2_packet_init(vd->ifname, NULL, ETH_P_ECP,
- ecp_rx_ReceiveFrame, vd, 1);
+ if (!vd->ecp.l2) {
+ vd->ecp.l2 = l2_packet_init(vd->ifname, NULL, ETH_P_ECP,
+ ecp_rx_ReceiveFrame, vd, 1);
+ }
+
if (!vd->ecp.l2) {
LLDPAD_ERR("ERROR: Failed to open register layer 2 access to "
"ETH_P_ECP\n");
goto fail;
}
+ vd->ecp.ackTimerExpired = true;
ecp_tx_run_sm(vd);
ecp_rx_run_sm(vd);
diff --git a/ecp/ecp_rx.c b/ecp/ecp_rx.c
index bfd51fa..6bd6237 100644
--- a/ecp/ecp_rx.c
+++ b/ecp/ecp_rx.c
@@ -268,6 +268,7 @@ void ecp_rx_ReceiveFrame(void *ctx, unsigned int ifindex, const u8 *buf, size_t
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;
break;
diff --git a/ecp/ecp_tx.c b/ecp/ecp_tx.c
index 54a278f..cc3cc51 100644
--- a/ecp/ecp_tx.c
+++ b/ecp/ecp_tx.c
@@ -172,6 +172,8 @@ bool ecp_build_ECPDU(struct vdp_data *vd)
fb_offset += ptlv->size;
}
+ p->seqnr = vd->ecp.lastSequence;
+
ptlv = free_pkd_tlv(ptlv);
}
@@ -406,7 +408,7 @@ static bool ecp_set_tx_state(struct vdp_data *vd)
return true;
}
ecp_tx_change_state(vd, ECP_TX_WAIT_FOR_ACK);
- return true;
+ return false;
case ECP_TX_WAIT_FOR_ACK:
if (vd->ecp.ackTimerExpired) {
vd->ecp.retries++;
diff --git a/include/lldp_vdp.h b/include/lldp_vdp.h
index 3d1411d..5fc1a22 100644
--- a/include/lldp_vdp.h
+++ b/include/lldp_vdp.h
@@ -126,6 +126,7 @@ struct vsi_profile {
int ackReceived;
int keepaliveTimer;
int state;
+ int seqnr;
bool localChange;
LIST_ENTRY(vsi_profile) profile;
};
@@ -137,6 +138,7 @@ struct vdp_data {
int role;
int keepaliveTimer;
int ackTimer;
+ int nroftimers;
LIST_HEAD(profile_head, vsi_profile) profile_head;
LIST_ENTRY(vdp_data) entry;
};
diff --git a/lldp_vdp.c b/lldp_vdp.c
index 6ebf171..a3781b0 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -129,6 +129,26 @@ void vdp_print_profile(struct vsi_profile *profile)
LLDPAD_DBG("vlan: %i\n", profile->vlan);
}
+/* vdp_ack_profiles - set ackReceived for all profiles with seqnr
+ * @vd: vd for the interface
+ * @seqnr: seqnr the ack has been received with
+ *
+ * no return value
+ *
+ * set the ackReceived for all profiles which have been sent out with
+ * the seqnr that we now have received the ack for.
+ */
+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)
+ p->ackReceived = true;
+ }
+
+}
+
/* vdp_somethingChangedLocal - set flag if profile has changed
* @profile: profile to set the flag for
* @flag: set the flag to true or false
@@ -185,6 +205,8 @@ void vdp_timeout_handler(void *eloop_data, void *user_ctx)
vd = (struct vdp_data *) user_ctx;
+ vd->nroftimers--;
+
LIST_FOREACH(p, &vd->profile_head, profile) {
if (p->ackTimer > 0)
p->ackTimer--;
@@ -194,9 +216,15 @@ void vdp_timeout_handler(void *eloop_data, void *user_ctx)
if (vdp_ackTimer_expired(p) ||
vdp_keepaliveTimer_expired(p) ||
- p->ackReceived ||
- p->localChange)
+ p->ackReceived) {
+ 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);
+ }
}
vdp_start_timer(vd);
@@ -214,6 +242,8 @@ static int vdp_stop_timer(struct vdp_data *vd)
LLDPAD_DBG("%s(%i)-%s: stopping vdp timer\n", __func__, __LINE__,
vd->ifname);
+ vd->nroftimers--;
+
return eloop_cancel_timeout(vdp_timeout_handler, NULL, (void *) vd);
}
@@ -231,6 +261,15 @@ static int vdp_start_timer(struct vdp_data *vd)
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;
+ }
+
return eloop_register_timeout(secs, usecs, vdp_timeout_handler, NULL, (void *) vd);
}
@@ -301,6 +340,7 @@ void vdp_vsi_change_station_state(struct vsi_profile *profile, u8 newstate)
break;
case VSI_ASSOC_PROCESSING:
assert((profile->state == VSI_PREASSOCIATED) ||
+ (profile->state == VSI_ASSOCIATED) ||
(profile->state == VSI_UNASSOCIATED));
break;
case VSI_ASSOCIATED:
@@ -308,7 +348,8 @@ void vdp_vsi_change_station_state(struct vsi_profile *profile, u8 newstate)
(profile->state == VSI_ASSOCIATED));
break;
case VSI_PREASSOC_PROCESSING:
- assert(profile->state == VSI_UNASSOCIATED);
+ assert((profile->state == VSI_PREASSOCIATED) ||
+ profile->state == VSI_UNASSOCIATED);
break;
case VSI_PREASSOCIATED:
assert((profile->state == VSI_PREASSOC_PROCESSING) ||
@@ -366,8 +407,6 @@ static bool vdp_vsi_set_station_state(struct vsi_profile *profile)
}
return false;
case VSI_ASSOC_PROCESSING:
- LLDPAD_DBG("profile->ackReceived %i, vdp_ackTimer %i\n",
- profile->ackReceived, profile->ackTimer);
if (profile->ackReceived) {
vdp_vsi_change_station_state(profile, VSI_ASSOCIATED);
return true;
@@ -383,24 +422,36 @@ static bool vdp_vsi_set_station_state(struct vsi_profile *profile)
} else if (profile->mode == VDP_MODE_DEASSOCIATE) {
vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING);
return true;
+ } else if (vdp_keepaliveTimer_expired(profile)) {
+ vdp_stop_keepaliveTimer(profile);
+ vdp_somethingChangedLocal(profile, true);
+ vdp_vsi_change_station_state(profile, VSI_ASSOC_PROCESSING);
+ return true;
}
return false;
case VSI_PREASSOC_PROCESSING:
+ LLDPAD_DBG("%s(%i): profile->ackReceived %i, vdp_ackTimer %i\n", __func__,
+ __LINE__, profile->ackReceived, profile->ackTimer);
if (profile->ackReceived) {
vdp_vsi_change_station_state(profile, VSI_PREASSOCIATED);
return true;
- } else if (vdp_ackTimer_expired(profile)) {
+ } else if (!profile->ackReceived && vdp_ackTimer_expired(profile)) {
vdp_vsi_change_station_state(profile, VSI_EXIT);
return true;
}
+ return false;
case VSI_PREASSOCIATED:
- if (profile->mode == VDP_MODE_DEASSOCIATE) {
- vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING);
- return true;
- }
if (profile->mode == VDP_MODE_ASSOCIATE) {
vdp_vsi_change_station_state(profile, VSI_ASSOC_PROCESSING);
return true;
+ } else if (profile->mode == VDP_MODE_DEASSOCIATE) {
+ vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING);
+ return true;
+ } else if (vdp_keepaliveTimer_expired(profile)) {
+ vdp_stop_keepaliveTimer(profile);
+ vdp_somethingChangedLocal(profile, true);
+ vdp_vsi_change_station_state(profile, VSI_PREASSOC_PROCESSING);
+ return true;
}
return false;
case VSI_DEASSOC_PROCESSING:
@@ -438,55 +489,44 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
case VSI_UNASSOCIATED:
break;
case VSI_ASSOC_PROCESSING:
+ vdp_stop_keepaliveTimer(profile);
profile->response = VDP_RESPONSE_NO_RESPONSE;
if (profile->localChange) {
ecp_somethingChangedLocal(vd);
+ vdp_start_ackTimer(profile);
ecp_tx_run_sm(vd);
}
- vdp_somethingChangedLocal(profile, false);
- vdp_start_ackTimer(profile);
break;
case VSI_ASSOCIATED:
profile->ackReceived = false;
vdp_somethingChangedLocal(profile, false);
vdp_stop_ackTimer(profile);
- if (vdp_keepaliveTimer_expired(profile)) {
- vdp_somethingChangedLocal(profile, true);
- ecp_somethingChangedLocal(vd);
- ecp_tx_run_sm(vd);
- vdp_start_keepaliveTimer(profile);
- }
+ vdp_start_keepaliveTimer(profile);
break;
case VSI_PREASSOC_PROCESSING:
- /* send out profile */
+ vdp_stop_keepaliveTimer(profile);
profile->response = VDP_RESPONSE_NO_RESPONSE;
if (profile->localChange) {
ecp_somethingChangedLocal(vd);
+ vdp_start_ackTimer(profile);
ecp_tx_run_sm(vd);
}
- vdp_somethingChangedLocal(profile, false);
- vdp_start_ackTimer(profile);
break;
case VSI_PREASSOCIATED:
profile->ackReceived = false;
vdp_somethingChangedLocal(profile, false);
vdp_stop_ackTimer(profile);
- if (vdp_keepaliveTimer_expired(profile)) {
- vdp_somethingChangedLocal(profile, true);
- ecp_somethingChangedLocal(vd);
- ecp_tx_run_sm(vd);
- }
vdp_start_keepaliveTimer(profile);
break;
case VSI_DEASSOC_PROCESSING:
+ vdp_stop_keepaliveTimer(profile);
profile->response = VDP_RESPONSE_NO_RESPONSE;
vdp_stop_keepaliveTimer(profile);
if (profile->localChange) {
ecp_somethingChangedLocal(vd);
+ vdp_start_ackTimer(profile);
ecp_tx_run_sm(vd);
}
- vdp_somethingChangedLocal(profile, false);
- vdp_start_ackTimer(profile);
break;
case VSI_EXIT:
/* TODO: send DEASSOC here ? */
@@ -1175,7 +1215,7 @@ void vdp_ifup(char *ifname)
vd = vdp_data(ifname);
if (vd) {
LLDPAD_WARN("%s:%s vdp data already exists !\n", __func__, ifname);
- goto out_start_timer;
+ goto out_start_again;
}
/* not found, alloc/init per-port module data */
@@ -1204,6 +1244,7 @@ void vdp_ifup(char *ifname)
ud = find_module_user_data_by_if(ifname, &lldp_head, LLDP_MOD_VDP);
LIST_INSERT_HEAD(&ud->head, vd, entry);
+out_start_again:
if (ecp_init(ifname)) {
LLDPAD_ERR("%s:%s unable to init ecp !\n", __func__, ifname);
vdp_ifdown(ifname);
@@ -1213,7 +1254,8 @@ void vdp_ifup(char *ifname)
vd->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT;
vd->ackTimer = VDP_ACK_TIMER_DEFAULT;
-out_start_timer:
+ LLDPAD_DBG("%s(%i)-%s: starting vdp timer (%i)\n", __func__, __LINE__,
+ vd->ifname, vd->nroftimers);
vdp_start_timer(vd);
LLDPAD_DBG("%s:%s vdp added\n", __func__, ifname);
--
1.7.4.4