lldpad/lldpad-0.9.41-rework-EVB-TLV-code.patch
2011-04-21 09:10:21 +02:00

371 lines
12 KiB
Diff

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