Blame SOURCES/open-lldp-v1.0.1-8-VDP-Support-for-OUI-infrastructure-in-vdptool.patch

df64a6
From 321bfe6c5cbad58e97fbb2df3c93564c89f1e09b Mon Sep 17 00:00:00 2001
df64a6
From: padkrish <padkrish@cisco.com>
df64a6
Date: Wed, 21 Jan 2015 03:38:53 +0000
df64a6
Subject: [PATCH] VDP: Support for OUI infrastructure in vdptool.
df64a6
df64a6
This patch contains the changes made in vdptool to support OUI fields
df64a6
in vdptool. This commit has only the infra-structure changes needed
df64a6
for supporting OUI. No specific OUI fields are added as a part of this
df64a6
commit. The man page for vdptool is also modified accordingly.
df64a6
df64a6
The OUI data can be given as input to vdptool in different ways. It
df64a6
could be
df64a6
df64a6
   vdptool .... -c oui=companyA,Data1 -c oui=companyB,Data2 -c oui=companyA,Data3
df64a6
df64a6
 Or
df64a6
df64a6
   vdptool .... -c oui=companyA,Data1Data3 -c oui=companyB,data2
df64a6
df64a6
where companyA and companyB are the name of the Organizations.
df64a6
Anything after the comma in OUI data field is Org specific and it's
df64a6
upto the respective organization specific handlers to encode it so
df64a6
that it could be decoded appropriately by the ORG specific handlers
df64a6
inside lldpad. That is, Data1 and Data3 is specific to Organization
df64a6
'companyA' and the OUI handlers of companyA in vdptool and lldpad is
df64a6
responsible for encoding/decoding the data. The common code in vdptool
df64a6
and lldpad just treats it as opaque data. 'companyA' or 'companyB'
df64a6
above is the key using which the right handlers will be called.
df64a6
df64a6
Irrespective of how the command line interface to vdptool is, the
df64a6
input to lldpad is always the same. i.e. KeywordlenKeywordDatalenData
df64a6
For OUI, the data field will have the complete OUI data starting with
df64a6
ORG name (e.g companyA). So, in order to call the right handler
df64a6
routine, the OUI data field is split as OUInamelenOUInameOUIData.
df64a6
df64a6
OUInamelen is 2B.
df64a6
df64a6
For example if the following is given:
df64a6
df64a6
vdptool -T -W -i eth2  -V assoc \
df64a6
    -c mode=assoc -c mgrid2=0 -c typeid=0 -c typeidver=0  \
df64a6
    -c uuid=18ea3452-b364-4e13-a1a2-9c6524deb685 -c hints=none \
df64a6
    -c filter=0-fa:16:3e:4c:2d:85-90001 -c oui=companyA,val1=data1
df64a6
df64a6
The data sent to lldpad by vdptool will be as follows assuming
df64a6
companyA encode handlers in vdptool encodes it the same way:
df64a6
df64a6
04mode0005assoc06mgrid20001006typeid0001009typeidver0001004uuid002418ea3452-b364-4e13-a1a2-9c6524deb68505hints0004none06filter00190-fa:16:3e:4c:2d:85-9000103oui001408companyAval1=data1
df64a6
df64a6
This commit will not insert the oui fields as given above because no OUI
df64a6
specific handlers are added.
df64a6
df64a6
Signed-off-by: padkrish <padkrish@cisco.com>
df64a6
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
df64a6
---
df64a6
 docs/vdptool.8          |  50 +++++++++++++++-
df64a6
 include/qbg_vdp22_oui.h |  11 ++++
df64a6
 vdptool.c               | 149 +++++++++++++++++++++++++++++++++++++++++++++---
df64a6
 3 files changed, 201 insertions(+), 9 deletions(-)
df64a6
df64a6
diff --git a/docs/vdptool.8 b/docs/vdptool.8
df64a6
index 0b50a13..4580c71 100644
df64a6
--- a/docs/vdptool.8
df64a6
+++ b/docs/vdptool.8
df64a6
@@ -182,6 +182,31 @@ delimited by two slashes ('--'),
df64a6
 also known as filter information format 3.
df64a6
 For vlan and group details see (1) and (4).
df64a6
 .RE
df64a6
+.TP
df64a6
+.B "oui (Organizationally Unique Identifier):"
df64a6
+This defines the optional Organizationally
df64a6
+defined information field. This contains the
df64a6
+specific sets of values for this entry. There
df64a6
+can be multiple organizational specific fields,
df64a6
+in which case there will be multiple keywords
df64a6
+.I oui=
df64a6
+followed by the values.
df64a6
+The value is of the following format:
df64a6
+.EX
df64a6
+oui=OUI,[Organization specific values ]
df64a6
+.EE
df64a6
+The OUI specifies the name of the Organization
df64a6
+that is responsible for defining
df64a6
+this content. A comma is mandatory after the OUI
df64a6
+field. The fields following this
df64a6
+ is specified by the organization and
df64a6
+hence will be decoded based on the value of this
df64a6
+OUI field. Currently, the following values for
df64a6
+OUI are supported.
df64a6
+.RS
df64a6
+.IP cisco -
df64a6
+Specifies Cisco defined OUI.
df64a6
+.TP
df64a6
 .SH COMMANDS
df64a6
 .TP
df64a6
 .B license
df64a6
@@ -226,13 +251,33 @@ vdptool -i eth2 -T -V assoc -c mode=assoc -c mgrid2=blabla \\
df64a6
 	-c filter=2-52:00:00:11:22:33-200
df64a6
 .fi
df64a6
 .TP
df64a6
-Create a VSI association on interface eth2 and wait for the response from the bridge
df64a6
+Create a VSI association on interface eth2 and wait for the
df64a6
+response from the bridge
df64a6
 .br
df64a6
 .nf
df64a6
 vdptool -i eth2 -T -W -V assoc -c mode=assoc -c mgrid2=blabla \\
df64a6
 	-c typeid=5 -c uuid=1122 -c typeidver=4 -c hints=none \\
df64a6
 	-c filter=0-52:00:00:11:22:33-200
df64a6
 .fi
df64a6
+.TP
df64a6
+Create a VSI association on interface eth2 wth OUI parameters
df64a6
+and wait for the response from the bridge
df64a6
+.br
df64a6
+.nf
df64a6
+vdptool -i eth2 -T -W -V assoc -c mode=assoc -c mgrid2=blabla \\
df64a6
+	-c typeid=5 -c uuid=1122 -c typeidver=4 -c hints=none \\
df64a6
+	-c filter=0-52:00:00:11:22:33-200 -c oui=CompanyA,data
df64a6
+.fi
df64a6
+.TP
df64a6
+Create a VSI association on interface eth2 wth multiple OUI parameters
df64a6
+and wait for the response from the bridge
df64a6
+.br
df64a6
+.nf
df64a6
+vdptool -i eth2 -T -W -V assoc -c mode=assoc -c mgrid2=blabla \\
df64a6
+	-c typeid=5 -c uuid=1122 -c typeidver=4 -c hints=none \\
df64a6
+	-c filter=0-52:00:00:11:22:33-200 -c oui=CompanyA,data \\
df64a6
+	-c oui=CompanyB,data
df64a6
+.fi
df64a6
 
df64a6
 .TP
df64a6
 Query all VSI association on interface eth2
df64a6
@@ -240,7 +285,8 @@ Query all VSI association on interface eth2
df64a6
 vdptool -i eth2 -t -V assoc
df64a6
 
df64a6
 .TP
df64a6
-Query  VSI association on interface eth2 that matches specific VSI parameters. Any of the VSI parameters below can be omitted.
df64a6
+Query  VSI association on interface eth2 that matches specific
df64a6
+VSI parameters. Any of the VSI parameters below can be omitted.
df64a6
 .br
df64a6
 vdptool -i eth2 -t -V assoc -t -V assoc -c mode=assoc \\
df64a6
         -c mgrid2=blabla -c typeid=5 -c uuid=1122 \\
df64a6
diff --git a/include/qbg_vdp22_oui.h b/include/qbg_vdp22_oui.h
df64a6
index 0aeb7b9..d31c6ad 100644
df64a6
--- a/include/qbg_vdp22_oui.h
df64a6
+++ b/include/qbg_vdp22_oui.h
df64a6
@@ -33,6 +33,7 @@
df64a6
 enum vdp22_oui {
df64a6
 	VDP22_OUI_TYPE_LEN = 3,          /* Size of OUI Type field */
df64a6
 	VDP22_OUI_MAX_NAME = 20,
df64a6
+	MAX_OUI_DATA_LEN = 200
df64a6
 };
df64a6
 
df64a6
 struct vdp22_oui_data_s {
df64a6
@@ -43,4 +44,14 @@ struct vdp22_oui_data_s {
df64a6
 	void *data;
df64a6
 };
df64a6
 
df64a6
+typedef struct vdptool_oui_data_s {
df64a6
+	char oui_name[VDP22_OUI_MAX_NAME];
df64a6
+	char data[MAX_OUI_DATA_LEN];
df64a6
+} vdptool_oui_data_t;
df64a6
+
df64a6
+typedef struct vdptool_oui_hndlr_tbl_s {
df64a6
+	char *oui_name;
df64a6
+	bool (*oui_cli_encode_hndlr)(char *dst, char *src, size_t len);
df64a6
+} vdptool_oui_hndlr_tbl_t;
df64a6
+
df64a6
 #endif /* __VDP22_OUI_H__ */
df64a6
diff --git a/vdptool.c b/vdptool.c
df64a6
index f7fd288..c857a85 100644
df64a6
--- a/vdptool.c
df64a6
+++ b/vdptool.c
df64a6
@@ -55,6 +55,22 @@
df64a6
 #include "qbg_vdp22_clif.h"
df64a6
 #include "lldp_util.h"
df64a6
 #include "qbg_vdp22def.h"
df64a6
+#include "qbg_vdp22_oui.h"
df64a6
+
df64a6
+#define OUI_ENCODE_HNDLR(name) name##_oui_encode_hndlr
df64a6
+#define EXTERN_OUI_FN(name) \
df64a6
+	extern bool name##_oui_encode_hndlr(char *, char *, size_t)
df64a6
+
df64a6
+/* The handler declaration  for encoding OUI specific information should be
df64a6
+ * here. The corresponding decoder handler should be in lldpad.
df64a6
+ */
df64a6
+
df64a6
+
df64a6
+/* The OUI specific handlers should be added here */
df64a6
+
df64a6
+vdptool_oui_hndlr_tbl_t oui_hndlr_tbl[] = {
df64a6
+};
df64a6
+
df64a6
 
df64a6
 static char *print_vdp_status(enum vdp22_cmd_status status)
df64a6
 {
df64a6
@@ -144,23 +160,137 @@ static void get_arg_value(char *str, char **arg, char **argval)
df64a6
 	*arg = str;
df64a6
 }
df64a6
 
df64a6
-static int render_cmd(struct cmd *cmd, int argc, char **args, char **argvals)
df64a6
+static char *get_oui_name(char *argvals)
df64a6
+{
df64a6
+	char *oui_loc;
df64a6
+
df64a6
+	oui_loc = strchr(argvals, ',');
df64a6
+	if (oui_loc == NULL)
df64a6
+		return NULL;
df64a6
+	*oui_loc = '\0';
df64a6
+	return oui_loc + 1;
df64a6
+}
df64a6
+
df64a6
+static void fill_oui_hdr(vdptool_oui_data_t *oui_data, char *oui_name)
df64a6
+{
df64a6
+	strncpy(oui_data->oui_name, oui_name, sizeof(oui_data->oui_name));
df64a6
+	snprintf(oui_data->data, sizeof(oui_data->data), "%02x%s",
df64a6
+		 (unsigned int)strlen(oui_data->oui_name), oui_data->oui_name);
df64a6
+}
df64a6
+
df64a6
+static bool run_vdptool_oui_hndlr(vdptool_oui_data_t *oui_data, char *argvals)
df64a6
+{
df64a6
+	int cnt = 0, tbl_size;
df64a6
+	char *dst;
df64a6
+	size_t len = 0;
df64a6
+
df64a6
+	tbl_size = sizeof(oui_hndlr_tbl) / sizeof(vdptool_oui_hndlr_tbl_t);
df64a6
+	for (cnt = 0; cnt < tbl_size; cnt++) {
df64a6
+		if (!strncmp(oui_hndlr_tbl[cnt].oui_name, oui_data->oui_name,
df64a6
+			     VDP22_OUI_MAX_NAME)) {
df64a6
+			len = strlen(oui_data->data);
df64a6
+			if (len >= sizeof(oui_data->data))
df64a6
+				return false;
df64a6
+			dst = oui_data->data + len;
df64a6
+			return oui_hndlr_tbl[cnt].oui_cli_encode_hndlr(dst,
df64a6
+								argvals, len);
df64a6
+		}
df64a6
+	}
df64a6
+	return false;
df64a6
+}
df64a6
+
df64a6
+/*
df64a6
+ * The OUI can be input in many ways.
df64a6
+ * It could be vdptool .... -c oui=companyA,Data1 -c oui=companyB,Data2 \
df64a6
+ *			    -c oui=companyA,Data3
df64a6
+ * Or
df64a6
+ * vdptool .... -c oui=companyA,Data1Data3 -c oui=companyB,data2
df64a6
+ * This function takes care of both the case cases
df64a6
+ *
df64a6
+ * Anything after the comma in OUI data field is Org specific and it's upto
df64a6
+ * the respective organization specific handlers to encode it so that it could
df64a6
+ * be decoded appropriately by the ORG specific handlers inside lldpad.
df64a6
+ * That is, Data1 and Data3 is ORG companyA specific and the OUI handlers
df64a6
+ * of ORG companyA in vdptool and lldpad is responsible for encoding/decoding.
df64a6
+ *
df64a6
+ * Irrespective of how the command line interface to vdptool is, the input to
df64a6
+ * lldpad is always the same. i.e. KeywordlenKeywordDatalenData
df64a6
+ * For OUI, the data field will have the complete OUI data starting with
df64a6
+ * ORG name (e.g companyA). So, in order to call the right handler routine,
df64a6
+ * the OUI data field is split as OUInamelenOUInameOUIData.
df64a6
+ * OUInamelen is 2B.
df64a6
+ */
df64a6
+
df64a6
+static bool rewrite_oui_argval(char *argvals, vdptool_oui_data_t **oui_data,
df64a6
+			       int total_oui)
df64a6
+{
df64a6
+	char *new_oui_argvals, *new_oui_name, *exist_oui_name;
df64a6
+	bool flag = true, ret = false;
df64a6
+	int cnt;
df64a6
+
df64a6
+	new_oui_argvals = get_oui_name(argvals);
df64a6
+	if (!new_oui_argvals) {
df64a6
+		printf("Incorrect OUI Value, missing comma as delimited for "
df64a6
+		       "OUI Type\n");
df64a6
+		return false;
df64a6
+	}
df64a6
+	new_oui_name = argvals;
df64a6
+	for (cnt = 0; cnt < total_oui; cnt++) {
df64a6
+		if (!oui_data[cnt])
df64a6
+			continue;
df64a6
+		exist_oui_name = oui_data[cnt]->oui_name;
df64a6
+		if (!strncmp(new_oui_name, exist_oui_name,
df64a6
+			     VDP22_OUI_MAX_NAME)) {
df64a6
+			flag = false;
df64a6
+			break;
df64a6
+		}
df64a6
+	}
df64a6
+	if (flag) {
df64a6
+		oui_data[total_oui] = calloc(1, sizeof(vdptool_oui_data_t));
df64a6
+		fill_oui_hdr(oui_data[total_oui], new_oui_name);
df64a6
+		ret = run_vdptool_oui_hndlr(oui_data[total_oui],
df64a6
+					    new_oui_argvals);
df64a6
+	} else
df64a6
+		ret = run_vdptool_oui_hndlr(oui_data[cnt], new_oui_argvals);
df64a6
+	if (!ret)
df64a6
+		return false;
df64a6
+	return flag;
df64a6
+}
df64a6
+
df64a6
+int render_cmd(struct cmd *cmd, int argc, char **args, char **argvals)
df64a6
 {
df64a6
 	int len;
df64a6
 	int i;
df64a6
 	int fid = 0, oui = 0;
df64a6
+	vdptool_oui_data_t **oui_data;
df64a6
+	bool is_new;
df64a6
 
df64a6
 	len = sizeof(cmd->obuf);
df64a6
 
df64a6
+	/* To avoid another loop to figure the number of OUI's */
df64a6
+	oui_data = calloc(argc, sizeof(vdptool_oui_data_t *));
df64a6
+	if (!oui_data) {
df64a6
+		printf("Not enough memory\n");
df64a6
+		return 0;
df64a6
+	}
df64a6
+
df64a6
 	if ((cmd->cmd == cmd_settlv) || (cmd->cmd == cmd_gettlv)) {
df64a6
 		for (i = 0; i < argc; i++) {
df64a6
-			if (args[i]) {
df64a6
-				if (!strncasecmp(args[i], "filter",
df64a6
-						strlen("filter")))
df64a6
-					fid++;
df64a6
-				else if (!strncasecmp(args[i], "oui",
df64a6
-						strlen("oui")))
df64a6
+			if (!args[i])
df64a6
+				continue;
df64a6
+			if (!strncasecmp(args[i], "filter", strlen("filter")))
df64a6
+				fid++;
df64a6
+			else if (!strncasecmp(args[i], "oui", strlen("oui"))) {
df64a6
+				is_new = rewrite_oui_argval(argvals[i],
df64a6
+							    oui_data,
df64a6
+							    oui);
df64a6
+				if (is_new) {
df64a6
+					argvals[i] = oui_data[oui]->data;
df64a6
 					oui++;
df64a6
+				} else {
df64a6
+					args[i] = NULL;
df64a6
+					argvals[i] = NULL;
df64a6
+				}
df64a6
 			}
df64a6
 		}
df64a6
 	}
df64a6
@@ -182,6 +312,11 @@ static int render_cmd(struct cmd *cmd, int argc, char **args, char **argvals)
df64a6
 				 len - strlen(cmd->obuf), "%04x%s",
df64a6
 				 (unsigned int)strlen(argvals[i]), argvals[i]);
df64a6
 	}
df64a6
+	for (i = 0; i < oui; i++) {
df64a6
+		if (oui_data[i])
df64a6
+			free(oui_data[i]);
df64a6
+	}
df64a6
+	free(oui_data);
df64a6
 	return strlen(cmd->obuf);
df64a6
 }
df64a6
 
df64a6
-- 
df64a6
2.1.0
df64a6