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

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