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

ee47b4
From 19bdcc3fe966dc7d6fc154d7d29addfe200c6afc Mon Sep 17 00:00:00 2001
ee47b4
From: padkrish <padkrish@cisco.com>
ee47b4
Date: Wed, 21 Jan 2015 03:39:19 +0000
ee47b4
Subject: [PATCH] VDP: Support for OUI infrastructure in vdp22.
ee47b4
ee47b4
This commit is a framework for supporting OUI fields
ee47b4
in VDP22. This specific patch has changes for converting
ee47b4
OUI input to vdpnl structure, vdpnl to VSI
ee47b4
 and place-holders for calling the OUI handlers.
ee47b4
The specific changes are:
ee47b4
ee47b4
vdp22.c:
ee47b4
-------
ee47b4
Currently, the OUI handler code is linked statically to the lldpad (vdp22).
ee47b4
Some more enhancements are needed to support the dynamic linking of OUI
ee47b4
handler code. This is the general flow:
ee47b4
All the OUI handlers specify their init function in vdp22_oui_init_list. When
ee47b4
VDP22 receives a command with the OUI fields, then based on the OUI value,
ee47b4
it calls the appropriate init function. The OUI specific init function
ee47b4
implemented in the OUI specific file (not in this file) then registers its
ee47b4
handlers with VDP22. The handlers prototype is in qbg_vdp22_oui.h and it
ee47b4
currently has:
ee47b4
1. Handler for converting the OUI string to OUI structure which is a member of vdpnl structure.
ee47b4
2. Handler for converting the OUI structure from vdpnl structure to a OUI structure which is a member of vsi22 structure
ee47b4
3. Handler for creating the OUI fields for Tx.
ee47b4
4.  handler for processing/Rx the OUI information
ee47b4
5. Handler for freeing the OUI structure
ee47b4
6. Handler to return the size of OUI PTLV
ee47b4
ee47b4
Then, accordingly the respective handlers are called.
ee47b4
Function 'vdp22_delete_oui' calls each of the registered handlers for freeing
ee47b4
its OUI specific fields.
ee47b4
Function 'vdpnl_alloc_vsi_oui' calls each of the registered handlers for
ee47b4
creating a OUI structure in vsi22 structure.
ee47b4
Function 'oui_vdp_hndlr_init' is called by OUI specific code to register
ee47b4
its handlers.
ee47b4
Function 'vdp22_oui_init' calls the OUI specific init function.
ee47b4
Comments are embedded in the other functions added.
ee47b4
ee47b4
vdp22sm.c:
ee47b4
----------
ee47b4
Function 'oui22_ptlv_sz' calls each of the handlers in its VSI structure
ee47b4
to get the size of the OUI specific PTLV size.
ee47b4
Function 'oui22_2tlv' calls the handler for generating the OUI data for Tx.
ee47b4
ee47b4
vdp22_cmds.c:
ee47b4
-------------
ee47b4
This file has a minor modification to get the number of OUI fields which is
ee47b4
encoded in the input to lldpad.
ee47b4
ee47b4
vdp_ascii.c:
ee47b4
------------
ee47b4
Function 'oui_str2vdpnl' calls the respective handler to convert the OUI input
ee47b4
string to the OUI structure stored in vdpnl structure.
ee47b4
ee47b4
Signed-off-by: padkrish <padkrish@cisco.com>
ee47b4
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
ee47b4
---
ee47b4
 include/qbg_vdp22_oui.h |  38 ++++++++++++
ee47b4
 qbg/vdp22.c             | 159 ++++++++++++++++++++++++++++++++++++++++++++++++
ee47b4
 qbg/vdp22_cmds.c        |  10 ++-
ee47b4
 qbg/vdp22sm.c           |  54 +++++++++++++++-
ee47b4
 qbg/vdp_ascii.c         |  37 ++++++++++-
ee47b4
 5 files changed, 293 insertions(+), 5 deletions(-)
ee47b4
ee47b4
diff --git a/include/qbg_vdp22_oui.h b/include/qbg_vdp22_oui.h
ee47b4
index d31c6ad..0cce31e 100644
ee47b4
--- a/include/qbg_vdp22_oui.h
ee47b4
+++ b/include/qbg_vdp22_oui.h
ee47b4
@@ -32,6 +32,7 @@
ee47b4
  */
ee47b4
 enum vdp22_oui {
ee47b4
 	VDP22_OUI_TYPE_LEN = 3,          /* Size of OUI Type field */
ee47b4
+	MAX_NUM_OUI = 10,
ee47b4
 	VDP22_OUI_MAX_NAME = 20,
ee47b4
 	MAX_OUI_DATA_LEN = 200
ee47b4
 };
ee47b4
@@ -54,4 +55,41 @@ typedef struct vdptool_oui_hndlr_tbl_s {
ee47b4
 	bool (*oui_cli_encode_hndlr)(char *dst, char *src, size_t len);
ee47b4
 } vdptool_oui_hndlr_tbl_t;
ee47b4
 
ee47b4
+struct vdpnl_oui_data_s {
ee47b4
+	unsigned char oui_type[VDP22_OUI_TYPE_LEN];
ee47b4
+	char oui_name[VDP22_OUI_MAX_NAME];
ee47b4
+	int len;
ee47b4
+	char data[MAX_OUI_DATA_LEN];
ee47b4
+	/* If vdpnl structure is used for IPC, then this cannot be a ptr as
ee47b4
+	 * otherwise it needs to be flattened out. If this is just used within
ee47b4
+	 * lldpad then this can be made a ptr instead of a static array.
ee47b4
+	 * May need to revisit later TODO
ee47b4
+	 */
ee47b4
+};
ee47b4
+
ee47b4
+struct vdp22_oui_init_s {
ee47b4
+	unsigned char oui_type[VDP22_OUI_TYPE_LEN];
ee47b4
+	char oui_name[VDP22_OUI_MAX_NAME];
ee47b4
+	bool (*oui_init)();
ee47b4
+};
ee47b4
+
ee47b4
+struct vdp22_oui_handler_s {
ee47b4
+	unsigned char oui_type[VDP22_OUI_TYPE_LEN];
ee47b4
+	char oui_name[VDP22_OUI_MAX_NAME];
ee47b4
+	/* This handler converts the OUI string to vdpnl structure */
ee47b4
+	bool (*str2vdpnl_hndlr)(struct vdpnl_oui_data_s *, char *);
ee47b4
+	/* This handler converts the vdpnl structure to vsi22 structure */
ee47b4
+	bool (*vdpnl2vsi22_hndlr)(void *, struct vdpnl_oui_data_s *,
ee47b4
+				   struct vdp22_oui_data_s *);
ee47b4
+	/* This handler creates the OUI fields for Tx */
ee47b4
+	size_t (*vdp_tx_hndlr)(char unsigned *,
ee47b4
+				struct vdp22_oui_data_s *, size_t);
ee47b4
+	/* This handler is called for processing/Rx the OUI information */
ee47b4
+	bool (*vdp_rx_hndlr)();
ee47b4
+	/* This handler frees the OUI structures */
ee47b4
+	bool (*vdp_free_oui_hndlr)(struct vdp22_oui_data_s *);
ee47b4
+	/* This handler returns the size of OUI PTLV */
ee47b4
+	unsigned long (*oui_ptlv_size_hndlr)(void *);
ee47b4
+};
ee47b4
+
ee47b4
 #endif /* __VDP22_OUI_H__ */
ee47b4
diff --git a/qbg/vdp22.c b/qbg/vdp22.c
ee47b4
index d7aa648..5cae83f 100644
ee47b4
--- a/qbg/vdp22.c
ee47b4
+++ b/qbg/vdp22.c
ee47b4
@@ -44,6 +44,22 @@
ee47b4
 #include "qbg_vdp22_cmds.h"
ee47b4
 #include "qbg_vdp22def.h"
ee47b4
 
ee47b4
+#define INIT_FN(name) name##_oui_init
ee47b4
+#define EXTERN_FN(name)\
ee47b4
+extern bool name##_oui_init()
ee47b4
+
ee47b4
+/* Init handlers for OUI. OUI handlers should be added in vdp22_oui_init_list.
ee47b4
+ * First argument specifies the OUI code assigned to the Organization.
ee47b4
+ * Second argument is the string which should match with the CLI and the third
ee47b4
+ * argument is the init handler.
ee47b4
+ */
ee47b4
+
ee47b4
+struct vdp22_oui_init_s vdp22_oui_init_list[] = {
ee47b4
+};
ee47b4
+
ee47b4
+struct vdp22_oui_handler_s vdp22_oui_list[MAX_NUM_OUI];
ee47b4
+unsigned char g_oui_index;
ee47b4
+
ee47b4
 /*
ee47b4
  * VDP22 helper functions
ee47b4
  */
ee47b4
@@ -218,6 +234,36 @@ void vdp22_showvsi(struct vsi22 *p)
ee47b4
 }
ee47b4
 
ee47b4
 /*
ee47b4
+ * Delete the OUI structures of VSI22
ee47b4
+ * This calls the respective OUI handlers which are responsible for freeing
ee47b4
+ * the OUI specific 'data' element of 'vdp22_oui_data_s' structure.
ee47b4
+ */
ee47b4
+
ee47b4
+static void vdp22_delete_oui(struct vsi22 *p)
ee47b4
+{
ee47b4
+	struct vdp22_oui_data_s *oui_str;
ee47b4
+	struct vdp22_oui_handler_s *oui_hndlr;
ee47b4
+	int idx;
ee47b4
+	bool ret;
ee47b4
+
ee47b4
+	if ((p->no_ouidata == 0) || (!p->oui_str_data))
ee47b4
+		return;
ee47b4
+	for (idx = 0; idx < p->no_ouidata; idx++) {
ee47b4
+		oui_str = &p->oui_str_data[idx];
ee47b4
+		oui_hndlr = vdp22_get_oui_hndlr(oui_str->oui_name);
ee47b4
+		if (!oui_hndlr)
ee47b4
+			LLDPAD_ERR("%s: Unknown OUI %s\n",
ee47b4
+				   __func__, oui_str->oui_name);
ee47b4
+		else {
ee47b4
+			ret = oui_hndlr->vdp_free_oui_hndlr(oui_str);
ee47b4
+			LLDPAD_DBG("%s: Free handler returned %d\n", __func__,
ee47b4
+				   ret);
ee47b4
+		}
ee47b4
+	}
ee47b4
+	free(p->oui_str_data);
ee47b4
+}
ee47b4
+
ee47b4
+/*
ee47b4
  * Delete a complete VSI node not on queue.
ee47b4
  */
ee47b4
 void vdp22_delete_vsi(struct vsi22 *p)
ee47b4
@@ -225,6 +271,7 @@ void vdp22_delete_vsi(struct vsi22 *p)
ee47b4
 	LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, p->vdp->ifname, p,
ee47b4
 		   p->vsi[0]);
ee47b4
 	free(p->fdata);
ee47b4
+	vdp22_delete_oui(p);
ee47b4
 	free(p);
ee47b4
 }
ee47b4
 
ee47b4
@@ -475,6 +522,38 @@ static bool filter_ok(unsigned char ffmt, struct fid22 *fp,
ee47b4
 	return rc;
ee47b4
 }
ee47b4
 
ee47b4
+static void vdpnl_alloc_vsi_oui(struct vdpnl_vsi *vsi, struct vsi22 *p)
ee47b4
+{
ee47b4
+	struct vdp22_oui_handler_s *oui_hndlr;
ee47b4
+	bool ret;
ee47b4
+	int idx;
ee47b4
+
ee47b4
+	if (vsi->ouisz == 0)
ee47b4
+		return;
ee47b4
+	p->no_ouidata = vsi->ouisz;
ee47b4
+	p->oui_str_data = calloc(vsi->ouisz, sizeof(struct vdp22_oui_data_s));
ee47b4
+	if (!p->oui_str_data) {
ee47b4
+		LLDPAD_ERR("%s: calloc return failure\n", __func__);
ee47b4
+		return;
ee47b4
+	}
ee47b4
+	for (idx = 0; idx < vsi->ouisz; idx++) {
ee47b4
+		struct vdpnl_oui_data_s *from = &vsi->oui_list[idx];
ee47b4
+		struct vdp22_oui_data_s *to = &p->oui_str_data[idx];
ee47b4
+
ee47b4
+		oui_hndlr = vdp22_get_oui_hndlr(from->oui_name);
ee47b4
+		if (!oui_hndlr)
ee47b4
+			LLDPAD_ERR("%s: Unknown OUI Name %s\n",
ee47b4
+				   __func__, from->oui_name);
ee47b4
+		else {
ee47b4
+			ret = oui_hndlr->vdpnl2vsi22_hndlr(p, from, to);
ee47b4
+			if (!ret)
ee47b4
+				LLDPAD_ERR("%s: handler return error for "
ee47b4
+					   "oui %s\n", __func__,
ee47b4
+					   from->oui_name);
ee47b4
+		}
ee47b4
+	}
ee47b4
+}
ee47b4
+
ee47b4
 /*
ee47b4
  * Allocate a VSI node with filter information data.
ee47b4
  * Check if input data is valid.
ee47b4
@@ -540,6 +619,7 @@ static struct vsi22 *vdp22_alloc_vsi_int(struct vdpnl_vsi *vsi,
ee47b4
 		fp->requestor.req_pid = vsi->req_pid;
ee47b4
 		fp->requestor.req_seq = vsi->req_seq;
ee47b4
 	}
ee47b4
+	vdpnl_alloc_vsi_oui(vsi, p);
ee47b4
 	*rc = 0;
ee47b4
 	LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, vsi->ifname, p, p->vsi[0]);
ee47b4
 	return p;
ee47b4
@@ -1113,3 +1193,82 @@ void copy_vsi_external(struct vdpnl_vsi *vsi, struct vsi22 *p, int clif)
ee47b4
 {
ee47b4
 	copy_vsi(vsi, p, clif);
ee47b4
 }
ee47b4
+
ee47b4
+/*
ee47b4
+ * This is called by the ORG specific code to register its handlers.
ee47b4
+ */
ee47b4
+
ee47b4
+bool oui_vdp_hndlr_init(struct vdp22_oui_handler_s *handler_ptr)
ee47b4
+{
ee47b4
+	if (!handler_ptr) {
ee47b4
+		LLDPAD_DBG("%s: NULL handler\n", __func__);
ee47b4
+		return false;
ee47b4
+	}
ee47b4
+	memcpy(&(vdp22_oui_list[g_oui_index]), handler_ptr,
ee47b4
+		sizeof(vdp22_oui_list[g_oui_index]));
ee47b4
+	g_oui_index++;
ee47b4
+	return true;
ee47b4
+}
ee47b4
+
ee47b4
+/*
ee47b4
+ * This calls the ORG specific init function. Then the ORG specific init
ee47b4
+ * function registers its handlers.
ee47b4
+ */
ee47b4
+
ee47b4
+static void vdp22_oui_init(char *oui_name)
ee47b4
+{
ee47b4
+	int total;
ee47b4
+	int idx;
ee47b4
+
ee47b4
+	total = sizeof(vdp22_oui_init_list) / sizeof(vdp22_oui_init_list[0]);
ee47b4
+	for (idx = 0; idx < total; idx++) {
ee47b4
+		if (!strncmp(vdp22_oui_init_list[idx].oui_name, oui_name,
ee47b4
+			     sizeof(vdp22_oui_init_list[idx].oui_name))) {
ee47b4
+			if (!vdp22_oui_init_list[idx].oui_init())
ee47b4
+				LLDPAD_ERR("%s: oui init return error for OUI "
ee47b4
+					   "%s\n", __func__, oui_name);
ee47b4
+		}
ee47b4
+	}
ee47b4
+}
ee47b4
+
ee47b4
+static struct vdp22_oui_handler_s *get_oui_hndlr_internal(char *oui_name)
ee47b4
+{
ee47b4
+	int total;
ee47b4
+	int idx;
ee47b4
+
ee47b4
+	total = g_oui_index;
ee47b4
+	for (idx = 0; idx < total; idx++) {
ee47b4
+		if (!strncmp(vdp22_oui_list[idx].oui_name, oui_name,
ee47b4
+			     sizeof(vdp22_oui_list[idx].oui_name)))
ee47b4
+			return &vdp22_oui_list[idx];
ee47b4
+	}
ee47b4
+	return NULL;
ee47b4
+}
ee47b4
+
ee47b4
+/*
ee47b4
+ * Return the handler structure associated with this OUI.
ee47b4
+ * If the handler is already registered, then get_oui_hndlr_internal function
ee47b4
+ * will return it. Otherwise, vdp22_oui_init is called so that the handler
ee47b4
+ * init function is called which will register its handlers. This is done so
ee47b4
+ * that the ORG specific handlers are registered only on demand.
ee47b4
+ */
ee47b4
+
ee47b4
+struct vdp22_oui_handler_s *vdp22_get_oui_hndlr(char *oui_name)
ee47b4
+{
ee47b4
+	struct vdp22_oui_handler_s *hndlr;
ee47b4
+
ee47b4
+	if (oui_name == NULL) {
ee47b4
+		LLDPAD_ERR("%s: NULL arg\n", __func__);
ee47b4
+		return NULL;
ee47b4
+	}
ee47b4
+	/*
ee47b4
+	 * First check if the handler exists.
ee47b4
+	 * If not the OUI plugin is probably not initialized
ee47b4
+	 * Initialize the handlers
ee47b4
+	 */
ee47b4
+	hndlr = get_oui_hndlr_internal(oui_name);
ee47b4
+	if (hndlr != NULL)
ee47b4
+		return hndlr;
ee47b4
+	vdp22_oui_init(oui_name);
ee47b4
+	return get_oui_hndlr_internal(oui_name);
ee47b4
+}
ee47b4
diff --git a/qbg/vdp22_cmds.c b/qbg/vdp22_cmds.c
ee47b4
index 5d5ef6b..5b5788f 100644
ee47b4
--- a/qbg/vdp22_cmds.c
ee47b4
+++ b/qbg/vdp22_cmds.c
ee47b4
@@ -356,20 +356,25 @@ static int get_vdp22_retval(int rc)
ee47b4
 	}
ee47b4
 }
ee47b4
 
ee47b4
-static int set_arg_vsi3(struct cmd *cmd, char *argvalue, bool test, int size)
ee47b4
+static int set_arg_vsi3(struct cmd *cmd, char *argvalue, bool test, int size,
ee47b4
+			int oui_size)
ee47b4
 {
ee47b4
 	cmd_status good_cmd = vdp22_cmdok(cmd, cmd_settlv);
ee47b4
 	int rc;
ee47b4
 	struct vdpnl_vsi vsi;
ee47b4
 	struct vdpnl_mac mac[size];
ee47b4
+	struct vdpnl_oui_data_s oui[oui_size];
ee47b4
 
ee47b4
 	if (good_cmd != cmd_success)
ee47b4
 		return good_cmd;
ee47b4
 
ee47b4
 	memset(&vsi, 0, sizeof(vsi));
ee47b4
 	memset(&mac, 0, sizeof(mac));
ee47b4
+	memset(&oui, 0, sizeof(oui));
ee47b4
 	vsi.maclist = mac;
ee47b4
 	vsi.macsz = size;
ee47b4
+	vsi.oui_list = (struct vdpnl_oui_data_s *)oui;
ee47b4
+	vsi.ouisz = oui_size;
ee47b4
 	rc = vdp_str2vdpnl(argvalue, &vsi, cmd->ifname);
ee47b4
 	if (rc) {
ee47b4
 		good_cmd = get_vdp22_retval(rc);
ee47b4
@@ -392,11 +397,12 @@ out:
ee47b4
 static int set_arg_vsi2(struct cmd *cmd, char *argvalue, bool test)
ee47b4
 {
ee47b4
 	int no = (cmd->ops >> OP_FID_POS) & 0xff;
ee47b4
+	int oui_no = (cmd->ops >> OP_OUI_POS) & 0xff;
ee47b4
 
ee47b4
 	if (no <= 0)
ee47b4
 		return -EINVAL;
ee47b4
 	if ((cmd->ops & op_arg) && (cmd->ops & op_argval))
ee47b4
-		return set_arg_vsi3(cmd, argvalue, test, no);
ee47b4
+		return set_arg_vsi3(cmd, argvalue, test, no, oui_no);
ee47b4
 	else /* Not supported for now */
ee47b4
 		return cmd_failed;
ee47b4
 }
ee47b4
diff --git a/qbg/vdp22sm.c b/qbg/vdp22sm.c
ee47b4
index 83a97fb..db0e413 100644
ee47b4
--- a/qbg/vdp22sm.c
ee47b4
+++ b/qbg/vdp22sm.c
ee47b4
@@ -184,6 +184,33 @@ static inline size_t vsi22_ptlv_sz(struct vsi22 *vp)
ee47b4
 }
ee47b4
 
ee47b4
 /*
ee47b4
+ * This function calls the registered OUI handlers that returns the size of
ee47b4
+ * the OUI data.
ee47b4
+ */
ee47b4
+
ee47b4
+static inline size_t oui22_ptlv_sz(struct vsi22 *vp)
ee47b4
+{
ee47b4
+	struct vdp22_oui_handler_s *oui_hndlr;
ee47b4
+	struct vdp22_oui_data_s *oui_str;
ee47b4
+	size_t size = 0;
ee47b4
+	int idx;
ee47b4
+
ee47b4
+	if (vp->no_ouidata == 0)
ee47b4
+		return 0;
ee47b4
+	for (idx = 0; idx < vp->no_ouidata; idx++) {
ee47b4
+		oui_str = &(vp->oui_str_data[idx]);
ee47b4
+		oui_hndlr = vdp22_get_oui_hndlr(oui_str->oui_name);
ee47b4
+		if (!oui_hndlr) {
ee47b4
+			LLDPAD_ERR("%s: No handler registered for OUI %s\n",
ee47b4
+				   __func__, oui_str->oui_name);
ee47b4
+			continue;
ee47b4
+		}
ee47b4
+		size += oui_hndlr->oui_ptlv_size_hndlr(oui_str->data);
ee47b4
+	}
ee47b4
+	return size;
ee47b4
+}
ee47b4
+
ee47b4
+/*
ee47b4
  * Extract 1, 2, 3, 4 byte integers in network byte format.
ee47b4
  * Extract n bytes.
ee47b4
  * Assume enough space available.
ee47b4
@@ -309,6 +336,29 @@ static size_t vsi22_2tlv_fdata(unsigned char *cp, struct fid22 *p,
ee47b4
 	return nbytes;
ee47b4
 }
ee47b4
 
ee47b4
+static void oui22_2tlv(struct vsi22 *vp, char unsigned *cp)
ee47b4
+{
ee47b4
+	struct vdp22_oui_handler_s *oui_hndlr;
ee47b4
+	struct vdp22_oui_data_s *oui_str;
ee47b4
+	size_t offset = 0;
ee47b4
+	size_t temp_offset = 0;
ee47b4
+	int idx;
ee47b4
+
ee47b4
+	if (vp->no_ouidata == 0)
ee47b4
+		return;
ee47b4
+	for (idx = 0; idx < vp->no_ouidata; idx++) {
ee47b4
+		oui_str = &(vp->oui_str_data[idx]);
ee47b4
+		oui_hndlr = vdp22_get_oui_hndlr(oui_str->oui_name);
ee47b4
+		if (!oui_hndlr) {
ee47b4
+			LLDPAD_ERR("%s: No handler registered for OUI %s\n",
ee47b4
+				   __func__, oui_str->oui_name);
ee47b4
+			continue;
ee47b4
+		}
ee47b4
+		temp_offset = oui_hndlr->vdp_tx_hndlr(cp, oui_str, offset);
ee47b4
+		offset += temp_offset;
ee47b4
+	}
ee47b4
+}
ee47b4
+
ee47b4
 static void vsi22_2tlv(struct vsi22 *vp, char unsigned *cp, unsigned char stat)
ee47b4
 {
ee47b4
 	size_t offset = 0, i;
ee47b4
@@ -478,7 +528,8 @@ static void vdp22st_wait_syscmd(struct vsi22 *vsip)
ee47b4
  */
ee47b4
 static void vdp22st_process(struct vsi22 *vsi)
ee47b4
 {
ee47b4
-	unsigned short len = mgr22_ptlv_sz() + vsi22_ptlv_sz(vsi);
ee47b4
+	unsigned short len = mgr22_ptlv_sz() + vsi22_ptlv_sz(vsi) +
ee47b4
+			      oui22_ptlv_sz(vsi);
ee47b4
 	unsigned char buf[len];
ee47b4
 	struct qbg22_imm qbg;
ee47b4
 
ee47b4
@@ -487,6 +538,7 @@ static void vdp22st_process(struct vsi22 *vsi)
ee47b4
 	qbg.u.c.data = buf;
ee47b4
 	mgr22_2tlv(vsi, buf);
ee47b4
 	vsi22_2tlv(vsi, buf + mgr22_ptlv_sz(), vsi->hints);
ee47b4
+	oui22_2tlv(vsi, buf + mgr22_ptlv_sz() + vsi22_ptlv_sz(vsi));
ee47b4
 	vsi->smi.txmit_error = modules_notify(LLDP_MOD_ECP22, LLDP_MOD_VDP22,
ee47b4
 					       vsi->vdp->ifname, &qbg);
ee47b4
 	if (!vsi->smi.txmit_error) {
ee47b4
diff --git a/qbg/vdp_ascii.c b/qbg/vdp_ascii.c
ee47b4
index 70ec79b..80a4419 100644
ee47b4
--- a/qbg/vdp_ascii.c
ee47b4
+++ b/qbg/vdp_ascii.c
ee47b4
@@ -54,7 +54,8 @@ struct vsi_keyword_handler vsi_key_handle[] = {
ee47b4
 /*	{VSI22_ARG_VSIIDFRMT_STR, VSI_VSIIDFRMT_ARG}, TODO*/
ee47b4
 	{VSI22_ARG_VSIID_STR, VSI_VSIID_ARG},
ee47b4
 	{VSI22_ARG_HINTS_STR, VSI_HINTS_ARG},
ee47b4
-	{VSI22_ARG_FILTER_STR, VSI_FILTER_ARG} };
ee47b4
+	{VSI22_ARG_FILTER_STR, VSI_FILTER_ARG},
ee47b4
+	{VSI22_ARG_OUI_STR, VSI_OUI_ARG} };
ee47b4
 
ee47b4
 /*
ee47b4
  * Check if it is a UUID and consists  of hexadecimal digits and dashes only.
ee47b4
@@ -225,6 +226,33 @@ static bool gethints(struct vdpnl_vsi *p, char *s)
ee47b4
 	return true;
ee47b4
 }
ee47b4
 
ee47b4
+static bool oui_str2vdpnl(struct vdpnl_vsi *vsi, char *p, unsigned short idx)
ee47b4
+{
ee47b4
+	struct vdp22_oui_handler_s *oui_hndlr;
ee47b4
+	char *temp_argval = p;
ee47b4
+	char *oui_val;
ee47b4
+	char oui_name[VDP22_OUI_MAX_NAME];
ee47b4
+	u8 oui_name_len;
ee47b4
+
ee47b4
+	hexstr2bin(p, &oui_name_len, sizeof(oui_name_len));
ee47b4
+	if (oui_name_len >= VDP22_OUI_MAX_NAME)
ee47b4
+		return false;
ee47b4
+	temp_argval = p + 2 * sizeof(oui_name_len);
ee47b4
+	oui_val = temp_argval + oui_name_len;
ee47b4
+	strncpy(oui_name, temp_argval, oui_name_len);
ee47b4
+	oui_name[oui_name_len] = '\0';
ee47b4
+	oui_hndlr = vdp22_get_oui_hndlr(oui_name);
ee47b4
+	if (!oui_hndlr)
ee47b4
+		return false;
ee47b4
+	strncpy(vsi->oui_list[idx].oui_name, oui_name,
ee47b4
+		sizeof(vsi->oui_list[idx].oui_name));
ee47b4
+	if (oui_hndlr->str2vdpnl_hndlr)
ee47b4
+		return oui_hndlr->str2vdpnl_hndlr(&(vsi->oui_list[idx]),
ee47b4
+						   oui_val);
ee47b4
+	else
ee47b4
+		return false;
ee47b4
+}
ee47b4
+
ee47b4
 /*
ee47b4
  * Read VSI association mode. If can be followed by an error code in brackets.
ee47b4
  * For vdp22 protocol the allowed words are assoc, preassoc, preassoc-rr and
ee47b4
@@ -315,7 +343,7 @@ int vdp22_parse_str_vdpnl(struct vdpnl_vsi *vsi, u16 *key_flags,
ee47b4
 	int i, ioff = 0, numargs;
ee47b4
 	int ilen = strlen(orig_argvalue);
ee47b4
 	unsigned int no;
ee47b4
-	unsigned short idx = 0;
ee47b4
+	unsigned short idx = 0, oui_idx = 0;
ee47b4
 	u16 num_arg_keys = 0;
ee47b4
 
ee47b4
 	argvalue = strdup(orig_argvalue);
ee47b4
@@ -373,6 +401,11 @@ int vdp22_parse_str_vdpnl(struct vdpnl_vsi *vsi, u16 *key_flags,
ee47b4
 			if (!argvals[i] || !gethints(vsi, argvals[i]))
ee47b4
 				goto out_err;
ee47b4
 			break;
ee47b4
+		case VSI_OUI_ARG:
ee47b4
+			if (!oui_str2vdpnl(vsi, argvals[i], oui_idx))
ee47b4
+				goto out_err;
ee47b4
+			oui_idx++;
ee47b4
+			break;
ee47b4
 		default:
ee47b4
 			goto out_err;
ee47b4
 		}
ee47b4
-- 
ee47b4
2.1.0
ee47b4