Blob Blame History Raw
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