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

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