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

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