From c639191703488058b388036dd16624581f1d8138 Mon Sep 17 00:00:00 2001 From: Petr Sabata Date: Apr 21 2011 07:10:21 +0000 Subject: Requires patches --- diff --git a/lldpad-0.9.41-Fix-README-mailing-list-address.patch b/lldpad-0.9.41-Fix-README-mailing-list-address.patch new file mode 100644 index 0000000..8798078 --- /dev/null +++ b/lldpad-0.9.41-Fix-README-mailing-list-address.patch @@ -0,0 +1,25 @@ +From 937d571370f2e2f2175d5910d2ca8a68a8d65920 Mon Sep 17 00:00:00 2001 +From: Ross Brattain +Date: Mon, 28 Feb 2011 17:07:58 -0800 +Subject: [PATCH 09/51] Fix README mailing list address. + +Signed-off-by: Ross Brattain +Signed-off-by: Petr Sabata +--- + 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 ++ LLDP-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +-- +1.7.4.4 + diff --git a/lldpad-0.9.41-add-a-vdp_vsi-to-count-nr-of-VSIs.patch b/lldpad-0.9.41-add-a-vdp_vsi-to-count-nr-of-VSIs.patch new file mode 100644 index 0000000..5f07339 --- /dev/null +++ b/lldpad-0.9.41-add-a-vdp_vsi-to-count-nr-of-VSIs.patch @@ -0,0 +1,56 @@ +From 91c351053a59846d7baac09af5a4c9fa3cc83f36 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-add-configuration-info-for-EVB-and-VDP-to-manpage.patch b/lldpad-0.9.41-add-configuration-info-for-EVB-and-VDP-to-manpage.patch new file mode 100644 index 0000000..b9438e6 --- /dev/null +++ b/lldpad-0.9.41-add-configuration-info-for-EVB-and-VDP-to-manpage.patch @@ -0,0 +1,42 @@ +From 58ccc3beb723dd786cc74fe9236089fc9a9b6d15 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-add-pointer-about-EVB-and-VDP-to-manpage.patch b/lldpad-0.9.41-add-pointer-about-EVB-and-VDP-to-manpage.patch new file mode 100644 index 0000000..e2a16bf --- /dev/null +++ b/lldpad-0.9.41-add-pointer-about-EVB-and-VDP-to-manpage.patch @@ -0,0 +1,44 @@ +From 32e1d7fb3ab73374a628ee120dd3f6223cd729e3 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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. ++ ++ ++.PP + .SH OPTIONS + .B lldpad + has the following command line options: +-- +1.7.4.4 + diff --git a/lldpad-0.9.41-allow-VSI-sm-state-change-from-ASSOC-to-PREASSOC_P.patch b/lldpad-0.9.41-allow-VSI-sm-state-change-from-ASSOC-to-PREASSOC_P.patch new file mode 100644 index 0000000..1cdb527 --- /dev/null +++ b/lldpad-0.9.41-allow-VSI-sm-state-change-from-ASSOC-to-PREASSOC_P.patch @@ -0,0 +1,32 @@ +From 899921f8db916c35dd684fdfab3b179ee60a4d55 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-allow-caching-of-deassociate-requests-via-netlink.patch b/lldpad-0.9.41-allow-caching-of-deassociate-requests-via-netlink.patch new file mode 100644 index 0000000..3cceace --- /dev/null +++ b/lldpad-0.9.41-allow-caching-of-deassociate-requests-via-netlink.patch @@ -0,0 +1,33 @@ +From 4db56779dea6479ce2a733525dc412346a48c675 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-always-flag-changed-profile-in-vdp_add_profile.patch b/lldpad-0.9.41-always-flag-changed-profile-in-vdp_add_profile.patch new file mode 100644 index 0000000..bec79dd --- /dev/null +++ b/lldpad-0.9.41-always-flag-changed-profile-in-vdp_add_profile.patch @@ -0,0 +1,91 @@ +From e63d88379622e98867c474b264ecc2473f0589b6 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-avoid-duplicate-deassociation.patch b/lldpad-0.9.41-avoid-duplicate-deassociation.patch new file mode 100644 index 0000000..283086c --- /dev/null +++ b/lldpad-0.9.41-avoid-duplicate-deassociation.patch @@ -0,0 +1,82 @@ +From 626a6d414fe8292cf599777317a9347e813c7c01 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-be-sure-to-stop-timers-on-VSI_EXIT.patch b/lldpad-0.9.41-be-sure-to-stop-timers-on-VSI_EXIT.patch new file mode 100644 index 0000000..503a832 --- /dev/null +++ b/lldpad-0.9.41-be-sure-to-stop-timers-on-VSI_EXIT.patch @@ -0,0 +1,32 @@ +From 6a3754050cd6713a0466da5e219983f594ca441c Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-bugfix-avoid-failed-query-of-vdp-role.patch b/lldpad-0.9.41-bugfix-avoid-failed-query-of-vdp-role.patch new file mode 100644 index 0000000..83fa0d8 --- /dev/null +++ b/lldpad-0.9.41-bugfix-avoid-failed-query-of-vdp-role.patch @@ -0,0 +1,72 @@ +From c834d11be209324b603dec54ec6e16784a077ce4 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: Jens Osterkamp +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-bugfix-in-bridge-implementation.patch b/lldpad-0.9.41-bugfix-in-bridge-implementation.patch new file mode 100644 index 0000000..e2b2373 --- /dev/null +++ b/lldpad-0.9.41-bugfix-in-bridge-implementation.patch @@ -0,0 +1,32 @@ +From 3d5ac4bd5e07c574b387523863070f904657934b Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: Jens Osterkamp +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-bugfix-set-configured-capabilities-as-well.patch b/lldpad-0.9.41-bugfix-set-configured-capabilities-as-well.patch new file mode 100644 index 0000000..a193609 --- /dev/null +++ b/lldpad-0.9.41-bugfix-set-configured-capabilities-as-well.patch @@ -0,0 +1,49 @@ +From 8ee44ed1df687e293a7eb0c86191219d2543105d Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-bugfix-state-ECP_TX_IDLE-no-longer-exists.patch b/lldpad-0.9.41-bugfix-state-ECP_TX_IDLE-no-longer-exists.patch new file mode 100644 index 0000000..4bf0ad2 --- /dev/null +++ b/lldpad-0.9.41-bugfix-state-ECP_TX_IDLE-no-longer-exists.patch @@ -0,0 +1,31 @@ +From 22d4dd6b5f8612cf49da3ebe19cd0d6827be3e18 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-check-if-port-is-enabled-for-RxTx.patch b/lldpad-0.9.41-check-if-port-is-enabled-for-RxTx.patch new file mode 100644 index 0000000..8dc4624 --- /dev/null +++ b/lldpad-0.9.41-check-if-port-is-enabled-for-RxTx.patch @@ -0,0 +1,51 @@ +From 96b9a70885f56f79c80400f9efbaa7598edec4d1 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-cleanup-change-request-from-mode-to-boolean.patch b/lldpad-0.9.41-cleanup-change-request-from-mode-to-boolean.patch new file mode 100644 index 0000000..44e8ba9 --- /dev/null +++ b/lldpad-0.9.41-cleanup-change-request-from-mode-to-boolean.patch @@ -0,0 +1,110 @@ +From e698bc3efe31e0807976eb9ff215379a7cde0ef6 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-cleanup-only-print-profiles-that-are-removed.patch b/lldpad-0.9.41-cleanup-only-print-profiles-that-are-removed.patch new file mode 100644 index 0000000..bebfa78 --- /dev/null +++ b/lldpad-0.9.41-cleanup-only-print-profiles-that-are-removed.patch @@ -0,0 +1,192 @@ +From 47ea2f2940025c23335f9c6182ccd6697a82364b Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-consolidate-ecp_somethingChangedlocal.patch b/lldpad-0.9.41-consolidate-ecp_somethingChangedlocal.patch new file mode 100644 index 0000000..14aaf38 --- /dev/null +++ b/lldpad-0.9.41-consolidate-ecp_somethingChangedlocal.patch @@ -0,0 +1,122 @@ +From 713b589fcb659bfdfe2b3ba283236d9a7932fe9d Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-event-if-always-reject-request-if-link-is-down.patch b/lldpad-0.9.41-event-if-always-reject-request-if-link-is-down.patch new file mode 100644 index 0000000..480760e --- /dev/null +++ b/lldpad-0.9.41-event-if-always-reject-request-if-link-is-down.patch @@ -0,0 +1,92 @@ +From 17e37970a9d940dd53697147074674a9bb7e0874 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-fix-memory-leak-in-vdp_indicate.patch b/lldpad-0.9.41-fix-memory-leak-in-vdp_indicate.patch new file mode 100644 index 0000000..2a81535 --- /dev/null +++ b/lldpad-0.9.41-fix-memory-leak-in-vdp_indicate.patch @@ -0,0 +1,32 @@ +From bc2fec292417407a84b9c68b7b360236bb8120a8 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: Jens Osterkamp +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-fix-potential-crash-after-link-up.patch b/lldpad-0.9.41-fix-potential-crash-after-link-up.patch new file mode 100644 index 0000000..6e98b4a --- /dev/null +++ b/lldpad-0.9.41-fix-potential-crash-after-link-up.patch @@ -0,0 +1,32 @@ +From 9b6f5c8b8a20d9c554ee0810be011c1c074adaf6 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-generic-renamed-find_module_user_data_by_if.patch b/lldpad-0.9.41-generic-renamed-find_module_user_data_by_if.patch new file mode 100644 index 0000000..4f64a13 --- /dev/null +++ b/lldpad-0.9.41-generic-renamed-find_module_user_data_by_if.patch @@ -0,0 +1,194 @@ +From 52d9fd16cb76cddd429f81a032098ae966fc4c4e Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-handle-negative-response-in-VDP-state-machine.patch b/lldpad-0.9.41-handle-negative-response-in-VDP-state-machine.patch new file mode 100644 index 0000000..f79718b --- /dev/null +++ b/lldpad-0.9.41-handle-negative-response-in-VDP-state-machine.patch @@ -0,0 +1,69 @@ +From 2784f4b9b91fea1690841f9284c11cac6cfe0e1f Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-DCB-remove-iSCSI-tc-qdisc-and-filters.patch b/lldpad-0.9.41-lldpad-DCB-remove-iSCSI-tc-qdisc-and-filters.patch new file mode 100644 index 0000000..9980b06 --- /dev/null +++ b/lldpad-0.9.41-lldpad-DCB-remove-iSCSI-tc-qdisc-and-filters.patch @@ -0,0 +1,127 @@ +From 4bf0f2db41be0b282e63646fb6b31f0a938d3865 Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-DCBx-remove-unused-bchange-value.patch b/lldpad-0.9.41-lldpad-DCBx-remove-unused-bchange-value.patch new file mode 100644 index 0000000..faef677 --- /dev/null +++ b/lldpad-0.9.41-lldpad-DCBx-remove-unused-bchange-value.patch @@ -0,0 +1,48 @@ +From 1c07cac7f456596bde81f20aa6f271f606814906 Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-DCBx-should-not-free-TLV-type-0.patch b/lldpad-0.9.41-lldpad-DCBx-should-not-free-TLV-type-0.patch new file mode 100644 index 0000000..f302d07 --- /dev/null +++ b/lldpad-0.9.41-lldpad-DCBx-should-not-free-TLV-type-0.patch @@ -0,0 +1,54 @@ +From ff7a21292914fe184a92e04eebdaea2ccadd4629 Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-FCoE-app-data-never-sent-to-kernel.patch b/lldpad-0.9.41-lldpad-FCoE-app-data-never-sent-to-kernel.patch new file mode 100644 index 0000000..e9aa21d --- /dev/null +++ b/lldpad-0.9.41-lldpad-FCoE-app-data-never-sent-to-kernel.patch @@ -0,0 +1,112 @@ +From 68c411e5a1638b4d38d9ea6c008b66bbad03d761 Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-add-802.1Qaz-attributes-to-dcbnl.h.patch b/lldpad-0.9.41-lldpad-add-802.1Qaz-attributes-to-dcbnl.h.patch new file mode 100644 index 0000000..9e849aa --- /dev/null +++ b/lldpad-0.9.41-lldpad-add-802.1Qaz-attributes-to-dcbnl.h.patch @@ -0,0 +1,268 @@ +From 81f201225a7865f3ce7560ca8eb29b92b81b345d Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + ++/* 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 + diff --git a/lldpad-0.9.41-lldpad-add-802.1Qaz-nlmsg-set-query-support.patch b/lldpad-0.9.41-lldpad-add-802.1Qaz-nlmsg-set-query-support.patch new file mode 100644 index 0000000..b18eafb --- /dev/null +++ b/lldpad-0.9.41-lldpad-add-802.1Qaz-nlmsg-set-query-support.patch @@ -0,0 +1,323 @@ +From fa0230ed0e11d5a5a07dda1d4c882f1272e5c5b8 Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-cleanup-fix-check-in-gettlv-for-null-ptr-tlvs.patch b/lldpad-0.9.41-lldpad-cleanup-fix-check-in-gettlv-for-null-ptr-tlvs.patch new file mode 100644 index 0000000..c45dedb --- /dev/null +++ b/lldpad-0.9.41-lldpad-cleanup-fix-check-in-gettlv-for-null-ptr-tlvs.patch @@ -0,0 +1,42 @@ +From a6fb363020205d0c3d361bb10cf7df6ba8f28406 Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-dcbx-dropped-ifdown-messages-breaks-module.patch b/lldpad-0.9.41-lldpad-dcbx-dropped-ifdown-messages-breaks-module.patch new file mode 100644 index 0000000..29651fa --- /dev/null +++ b/lldpad-0.9.41-lldpad-dcbx-dropped-ifdown-messages-breaks-module.patch @@ -0,0 +1,43 @@ +From 4aac303da6286d4bc08064e70369fb1493a480a2 Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-dcbx-netlink-cleanup.patch b/lldpad-0.9.41-lldpad-dcbx-netlink-cleanup.patch new file mode 100644 index 0000000..dfae6bb --- /dev/null +++ b/lldpad-0.9.41-lldpad-dcbx-netlink-cleanup.patch @@ -0,0 +1,42 @@ +From e1dba77eb789c74ba4b5611a4270dc7ff44ed0a8 Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-dormantTimer-should-not-be-touched-by-modules.patch b/lldpad-0.9.41-lldpad-dormantTimer-should-not-be-touched-by-modules.patch new file mode 100644 index 0000000..a61ad6a --- /dev/null +++ b/lldpad-0.9.41-lldpad-dormantTimer-should-not-be-touched-by-modules.patch @@ -0,0 +1,60 @@ +From 4ead297738c0c9963ebfea2fb57edebf46bb8bba Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-get-functions-for-Local-and-Remote-MAC-addres.patch b/lldpad-0.9.41-lldpad-get-functions-for-Local-and-Remote-MAC-addres.patch new file mode 100644 index 0000000..68f8fe4 --- /dev/null +++ b/lldpad-0.9.41-lldpad-get-functions-for-Local-and-Remote-MAC-addres.patch @@ -0,0 +1,92 @@ +From 8b0e918921882fcf56d9b75acd3b39aa4a76169b Mon Sep 17 00:00:00 2001 +From: Daruwalla, Sharookh P +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-iSCSI-subtype-does-not-send-kernel-setapp-nlm.patch b/lldpad-0.9.41-lldpad-iSCSI-subtype-does-not-send-kernel-setapp-nlm.patch new file mode 100644 index 0000000..d25a299 --- /dev/null +++ b/lldpad-0.9.41-lldpad-iSCSI-subtype-does-not-send-kernel-setapp-nlm.patch @@ -0,0 +1,112 @@ +From fe8ccb1c84408690a42ce2c6134a0f0018ebd46a Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-initialize-ports-after-netlink-interface-is-c.patch b/lldpad-0.9.41-lldpad-initialize-ports-after-netlink-interface-is-c.patch new file mode 100644 index 0000000..873f918 --- /dev/null +++ b/lldpad-0.9.41-lldpad-initialize-ports-after-netlink-interface-is-c.patch @@ -0,0 +1,45 @@ +From aa0294cd1a48ea34180be4d7235b4b13f9c6418b Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-invalidate-peer-rx-frame-after-TTL.patch b/lldpad-0.9.41-lldpad-invalidate-peer-rx-frame-after-TTL.patch new file mode 100644 index 0000000..6a6c203 --- /dev/null +++ b/lldpad-0.9.41-lldpad-invalidate-peer-rx-frame-after-TTL.patch @@ -0,0 +1,36 @@ +From 1915deefe804639a90e93eeb39bfc68c0f084f3f Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-make-debug-messages-from-netlink-path-helpful.patch b/lldpad-0.9.41-lldpad-make-debug-messages-from-netlink-path-helpful.patch new file mode 100644 index 0000000..cb1d8ee --- /dev/null +++ b/lldpad-0.9.41-lldpad-make-debug-messages-from-netlink-path-helpful.patch @@ -0,0 +1,160 @@ +From e8c85404d362aa612b21159dc2b7281e37c6346f Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-malloc-could-fail-in-clif_attach_helper.patch b/lldpad-0.9.41-lldpad-malloc-could-fail-in-clif_attach_helper.patch new file mode 100644 index 0000000..f13b2b9 --- /dev/null +++ b/lldpad-0.9.41-lldpad-malloc-could-fail-in-clif_attach_helper.patch @@ -0,0 +1,41 @@ +From 748b44354889329f8c0ef0b9c86013a80f195be2 Mon Sep 17 00:00:00 2001 +From: Zhifeng, Cai +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-remove-cur_peer-and-last_peer-from-DCBx.patch b/lldpad-0.9.41-lldpad-remove-cur_peer-and-last_peer-from-DCBx.patch new file mode 100644 index 0000000..470dcd7 --- /dev/null +++ b/lldpad-0.9.41-lldpad-remove-cur_peer-and-last_peer-from-DCBx.patch @@ -0,0 +1,299 @@ +From 4a3e9c9bd7140d547b0deba41b52b014e5ab6225 Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-remove-print-statements-that-are-not-helpful.patch b/lldpad-0.9.41-lldpad-remove-print-statements-that-are-not-helpful.patch new file mode 100644 index 0000000..f7fecf0 --- /dev/null +++ b/lldpad-0.9.41-lldpad-remove-print-statements-that-are-not-helpful.patch @@ -0,0 +1,32 @@ +From ce407dd26ca8cf61be75364e900c5ebcef3dd2cb Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-remove-unused-cmd_buf-variable-in-clif_reques.patch b/lldpad-0.9.41-lldpad-remove-unused-cmd_buf-variable-in-clif_reques.patch new file mode 100644 index 0000000..5796d1d --- /dev/null +++ b/lldpad-0.9.41-lldpad-remove-unused-cmd_buf-variable-in-clif_reques.patch @@ -0,0 +1,45 @@ +From 5d44f2fdd5f2074af2ec49fd89b8f1cfd0410879 Mon Sep 17 00:00:00 2001 +From: Zhifeng, Cai +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-lldpad-rtnl_recv_operstate-uses-incorrect-recv-lengt.patch b/lldpad-0.9.41-lldpad-rtnl_recv_operstate-uses-incorrect-recv-lengt.patch new file mode 100644 index 0000000..dc302eb --- /dev/null +++ b/lldpad-0.9.41-lldpad-rtnl_recv_operstate-uses-incorrect-recv-lengt.patch @@ -0,0 +1,43 @@ +From c18a94f5600d65f414e9ffe5579171c6700078fc Mon Sep 17 00:00:00 2001 +From: John Fastabend +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-new-call-VDP-station-state-machine-on-demand.patch b/lldpad-0.9.41-new-call-VDP-station-state-machine-on-demand.patch new file mode 100644 index 0000000..9575511 --- /dev/null +++ b/lldpad-0.9.41-new-call-VDP-station-state-machine-on-demand.patch @@ -0,0 +1,109 @@ +From 5b74605009a7d14bd93e5b068a55e28ff91dd02a Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-new-change-VDP-ACK-timer-value.patch b/lldpad-0.9.41-new-change-VDP-ACK-timer-value.patch new file mode 100644 index 0000000..866ed55 --- /dev/null +++ b/lldpad-0.9.41-new-change-VDP-ACK-timer-value.patch @@ -0,0 +1,32 @@ +From 6bcb3c33134e72f7b0b474a1c058b9e629eb1056 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-new-change-the-ECP-ack-timer-from-RTE-based-to-fixed.patch b/lldpad-0.9.41-new-change-the-ECP-ack-timer-from-RTE-based-to-fixed.patch new file mode 100644 index 0000000..ab0199f --- /dev/null +++ b/lldpad-0.9.41-new-change-the-ECP-ack-timer-from-RTE-based-to-fixed.patch @@ -0,0 +1,49 @@ +From 426a50e89645bde78c1ff7b286605105ddf5cc2a Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-new-rework-of-VDP-code-towards-newer-drafts.patch b/lldpad-0.9.41-new-rework-of-VDP-code-towards-newer-drafts.patch new file mode 100644 index 0000000..3d57c2d --- /dev/null +++ b/lldpad-0.9.41-new-rework-of-VDP-code-towards-newer-drafts.patch @@ -0,0 +1,477 @@ +From a2b1745d86cce79b0e4f9aa01045f06218afc991 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-no-error-if-the-profile-already-exists.patch b/lldpad-0.9.41-no-error-if-the-profile-already-exists.patch new file mode 100644 index 0000000..641e774 --- /dev/null +++ b/lldpad-0.9.41-no-error-if-the-profile-already-exists.patch @@ -0,0 +1,33 @@ +From 44ce9bbdbf38e6d090016ef9fd8a8b9063f4821e Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-prevent-forgotten-ECP-frame-for-vsi-type.patch b/lldpad-0.9.41-prevent-forgotten-ECP-frame-for-vsi-type.patch new file mode 100644 index 0000000..fb36a07 --- /dev/null +++ b/lldpad-0.9.41-prevent-forgotten-ECP-frame-for-vsi-type.patch @@ -0,0 +1,90 @@ +From 4749b5abad3dabb802b34dddf6dbfb9ac6d180ff Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-rework-EVB-TLV-code.patch b/lldpad-0.9.41-rework-EVB-TLV-code.patch new file mode 100644 index 0000000..f6d88c8 --- /dev/null +++ b/lldpad-0.9.41-rework-EVB-TLV-code.patch @@ -0,0 +1,370 @@ +From 0aeddf9df8fe679b22063550d941831b2644b3a0 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-rework-ecp-timer-code-towards-newer-drafts.patch b/lldpad-0.9.41-rework-ecp-timer-code-towards-newer-drafts.patch new file mode 100644 index 0000000..5e062bf --- /dev/null +++ b/lldpad-0.9.41-rework-ecp-timer-code-towards-newer-drafts.patch @@ -0,0 +1,403 @@ +From 1ce3f72873d392b55147d96cc38eda30b3e39de1 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: John Fastabend +Signed-off-by: Petr Sabata +--- + 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 + diff --git a/lldpad-0.9.41-robustness-proper-handling-of-LINK_DOWN-UP.patch b/lldpad-0.9.41-robustness-proper-handling-of-LINK_DOWN-UP.patch new file mode 100644 index 0000000..41f989d --- /dev/null +++ b/lldpad-0.9.41-robustness-proper-handling-of-LINK_DOWN-UP.patch @@ -0,0 +1,376 @@ +From 1d747210d5248f4f4a7e38bb27b212b476d3b3b8 Mon Sep 17 00:00:00 2001 +From: Jens Osterkamp +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 +Signed-off-by: Petr Sabata +--- + 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 +