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