Blame SOURCES/open-lldp-v1.0.1-11-VDP-Support-for-Cisco-specific-OUI-extensions-to-VDP.patch

74731f
From 409b8d4027d391a401b1d3c0f56569d6402679f7 Mon Sep 17 00:00:00 2001
74731f
From: padkrish <padkrish@cisco.com>
74731f
Date: Wed, 21 Jan 2015 03:40:09 +0000
74731f
Subject: [PATCH] VDP: Support for Cisco specific OUI extensions to VDP22
74731f
74731f
This commit has Cisco specific extensions to VDP22. vdptool is also
74731f
modified to carry Cisco's extensions for OUI.
74731f
The parameters to vdptool that are added for supporting Cisco OUI are:
74731f
"-c oui=cisco,vm_name=myname -c oui=cisco,ipv4_addr=a.b.c.d -c oui=cisco,vm_uuid=aaa"
74731f
74731f
The description of the files are:
74731f
74731f
vdp22cisco_oui.c:
74731f
-----------------
74731f
This file contain all the handler implementation.
74731f
vdp_cisco.h:
74731f
------------
74731f
Cisco specific OUI definitions and structures.
74731f
vdptool_cisco_oui.c:
74731f
--------------------
74731f
Cisco specific OUI extensions for user input.
74731f
74731f
Signed-off-by: padkrish <padkrish@cisco.com>
74731f
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
74731f
---
74731f
 Makefile.am          |   5 +-
74731f
 include/vdp_cisco.h  | 121 ++++++++++++++++++
74731f
 qbg/vdp22.c          |   2 +
74731f
 qbg/vdp22cisco_oui.c | 355 +++++++++++++++++++++++++++++++++++++++++++++++++++
74731f
 vdptool.c            |   2 +
74731f
 vdptool_cisco_oui.c  |  58 +++++++++
74731f
 6 files changed, 541 insertions(+), 2 deletions(-)
74731f
 create mode 100644 include/vdp_cisco.h
74731f
 create mode 100644 qbg/vdp22cisco_oui.c
74731f
 create mode 100644 vdptool_cisco_oui.c
74731f
74731f
diff --git a/Makefile.am b/Makefile.am
74731f
index f63311c..abc9348 100644
74731f
--- a/Makefile.am
74731f
+++ b/Makefile.am
74731f
@@ -70,14 +70,15 @@ include/lldp_evb22.h lldp_evb22.c lldp_evb22_cmds.c \
74731f
 include/qbg22.h include/qbg_ecp22.h qbg/ecp22.c \
74731f
 include/qbg_vdp22.h qbg/vdp22.c qbg/vdpnl.c qbg/vdp22sm.c qbg/vdp22br.c \
74731f
 include/qbg_vdp22def.h qbg/vdp22_cmds.c qbg/vdp_ascii.c \
74731f
-include/qbg_vdp22_oui.h qbg/vdp22_oui.c
74731f
+include/qbg_vdp22_oui.h qbg/vdp22_oui.c include/vdp_cisco.h \
74731f
+qbg/vdp22cisco_oui.c
74731f
 
74731f
 lib_LTLIBRARIES = liblldp_clif.la
74731f
 liblldp_clif_la_LDFLAGS = -version-info 1:0:0
74731f
 liblldp_clif_includedir = ${srcdir}/include
74731f
 liblldp_clif_la_SOURCES = clif.c
74731f
 
74731f
-vdptool_SOURCES = vdptool.c lldp_util.c qbg/vdp22_clif.c
74731f
+vdptool_SOURCES = vdptool.c lldp_util.c qbg/vdp22_clif.c vdptool_cisco_oui.c
74731f
 vdptool_LDADD = ${srcdir}/liblldp_clif.la
74731f
 vdptool_LDFLAGS = -llldp_clif $(LIBNL_LIBS)
74731f
 
74731f
diff --git a/include/vdp_cisco.h b/include/vdp_cisco.h
74731f
new file mode 100644
74731f
index 0000000..339d479
74731f
--- /dev/null
74731f
+++ b/include/vdp_cisco.h
74731f
@@ -0,0 +1,121 @@
74731f
+/*******************************************************************************
74731f
+
74731f
+  Implementation of Cisco Specific OUI for VDP2.2
74731f
+  Copyright (c) 2012-2014 by Cisco Systems, Inc.
74731f
+
74731f
+  Author(s): Padmanabhan Krishnan <padkrish at cisco dot com>
74731f
+
74731f
+  This program is free software; you can redistribute it and/or modify it
74731f
+  under the terms and conditions of the GNU General Public License,
74731f
+  version 2, as published by the Free Software Foundation.
74731f
+
74731f
+  This program is distributed in the hope it will be useful, but WITHOUT
74731f
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
74731f
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
74731f
+  more details.
74731f
+
74731f
+  You should have received a copy of the GNU General Public License along with
74731f
+  this program; if not, write to the Free Software Foundation, Inc.,
74731f
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
74731f
+
74731f
+  The full GNU General Public License is included in this distribution in
74731f
+  the file called "COPYING".
74731f
+*******************************************************************************/
74731f
+
74731f
+#ifndef __VDP22_VISCO_H__
74731f
+#define __VDP22_VISCO_H__
74731f
+
74731f
+#include "lldp.h"
74731f
+#include <netinet/in.h>
74731f
+#include <arpa/inet.h>
74731f
+#include "qbg_vdp22_oui.h"
74731f
+
74731f
+#define MAX_VM_NAME 100
74731f
+#define CISCO_OUI_VAL "00000C"
74731f
+#define CISCO_OUI_HEX 0xC
74731f
+
74731f
+#define CISCO_OUI_NAME_ARG_STR "vm_name"
74731f
+#define CISCO_OUI_NAME_UUID_ARG_STR "vm_uuid"
74731f
+#define CISCO_OUI_L3V4ADDR_ARG_STR "ipv4_addr"
74731f
+#define MAX_VM_AF 3
74731f
+
74731f
+#define KEYLEN          16
74731f
+#define PORT_UUID_MAX 16
74731f
+
74731f
+enum oui_key_arg {
74731f
+	CISCO_OUI_NAME_ARG = 0,
74731f
+	CISCO_OUI_NAME_UUID_ARG,
74731f
+	CISCO_OUI_L3V4ADDR_ARG,
74731f
+	CISCO_OUI_INVALID_ARG
74731f
+};
74731f
+
74731f
+enum cisco_oui_subtype {
74731f
+	CISCO_OUI_NAME_SUBTYPE = 0xF1,
74731f
+	CISCO_OUI_L3ADDR_SUBTYPE = 0xF2,
74731f
+};
74731f
+
74731f
+/*
74731f
+ * Name SubTLV
74731f
+ *     OUI:        => 3B = 00-00-0C
74731f
+ *     subtype     => 1B = 0xF1
74731f
+ *     VSI ID Frmt => 1B
74731f
+ *     VSI ID      => 16B
74731f
+ *     VM ID Frmt  => 1B
74731f
+ *     VM ID       => 16B
74731f
+ *     VM Name     => Variable
74731f
+ *     Total       => 38 + VM name len
74731f
+ */
74731f
+
74731f
+/*
74731f
+ * L3 Addr SubTLV
74731f
+ *     OUI:        => 3B = 00-00-0C
74731f
+ *     subtype     => 1B = 0xF2
74731f
+ *     VSI ID Frmt => 1B
74731f
+ *     VSI ID      => 16B
74731f
+ *     AFI         => 2B
74731f
+ *     L3 Addr     => Variable
74731f
+ *     Total       => 23 + L3 Addr Len
74731f
+ */
74731f
+
74731f
+ /* Subtype Len w/o the 3B Cisco OUI Len */
74731f
+enum cisco_oui_subtype_len {
74731f
+	CISCO_VM_NAME_TLV_LEN = 35, /* minus the variable name len */
74731f
+	CISCO_VM_L3ADDR_TLV_LEN = 20 /* minus the variable addr len */
74731f
+};
74731f
+
74731f
+struct oui_keyword_handler {
74731f
+	char *keyword;
74731f
+	enum oui_key_arg val;
74731f
+};
74731f
+
74731f
+typedef union l3_addrtype_ {
74731f
+	struct in_addr   ipv4_address;
74731f
+	struct in6_addr ipv6_address;
74731f
+} l3_addr_t;
74731f
+
74731f
+typedef struct vdp_cisco_oui_s {
74731f
+	char key[KEYLEN];       /* Profile name */
74731f
+	u8 uuid[PORT_UUID_MAX]; /* Instance ID */
74731f
+	size_t vm_name_len;
74731f
+	char vm_name[MAX_VM_NAME];
74731f
+	u16 afi;
74731f
+	u8 vm_addr_len;
74731f
+	l3_addr_t l3_addr;
74731f
+} vdp_cisco_oui_t;
74731f
+
74731f
+bool cisco_str2vdpnl_hndlr(struct vdpnl_oui_data_s *, char *);
74731f
+bool cisco_vdp_free_oui(struct vdp22_oui_data_s *);
74731f
+bool cisco_vdpnl2vsi22_hndlr(void *, struct vdpnl_oui_data_s *,
74731f
+			     struct vdp22_oui_data_s *);
74731f
+size_t cisco_vdp_tx_hndlr(char unsigned *, struct vdp22_oui_data_s *, size_t);
74731f
+bool cisco_vdp_rx_hndlr();
74731f
+unsigned long cisco_vdp_oui_ptlvsize(void *);
74731f
+
74731f
+static inline void fill_cisco_oui_type(unsigned char *oui_type)
74731f
+{
74731f
+	oui_type[0] = 0x00;
74731f
+	oui_type[1] = 0x00;
74731f
+	oui_type[2] = 0x0c;
74731f
+}
74731f
+
74731f
+#endif /* __VDP22_VISCO_H__ */
74731f
diff --git a/qbg/vdp22.c b/qbg/vdp22.c
74731f
index 5cae83f..ab170ed 100644
74731f
--- a/qbg/vdp22.c
74731f
+++ b/qbg/vdp22.c
74731f
@@ -48,6 +48,7 @@
74731f
 #define EXTERN_FN(name)\
74731f
 extern bool name##_oui_init()
74731f
 
74731f
+EXTERN_FN(cisco);
74731f
 /* Init handlers for OUI. OUI handlers should be added in vdp22_oui_init_list.
74731f
  * First argument specifies the OUI code assigned to the Organization.
74731f
  * Second argument is the string which should match with the CLI and the third
74731f
@@ -55,6 +56,7 @@ extern bool name##_oui_init()
74731f
  */
74731f
 
74731f
 struct vdp22_oui_init_s vdp22_oui_init_list[] = {
74731f
+	{{0x00, 0x00, 0x0c}, "cisco", INIT_FN(cisco)}
74731f
 };
74731f
 
74731f
 struct vdp22_oui_handler_s vdp22_oui_list[MAX_NUM_OUI];
74731f
diff --git a/qbg/vdp22cisco_oui.c b/qbg/vdp22cisco_oui.c
74731f
new file mode 100644
74731f
index 0000000..ef6c307
74731f
--- /dev/null
74731f
+++ b/qbg/vdp22cisco_oui.c
74731f
@@ -0,0 +1,355 @@
74731f
+/*******************************************************************************
74731f
+
74731f
+  Implementation of Cisco Specific OUI for VDP2.2
74731f
+  Copyright (c) 2012-2014 by Cisco Systems, Inc.
74731f
+
74731f
+  Author(s): Padmanabhan Krishnan <padkrish at cisco dot com>
74731f
+
74731f
+  This program is free software; you can redistribute it and/or modify it
74731f
+  under the terms and conditions of the GNU General Public License,
74731f
+  version 2, as published by the Free Software Foundation.
74731f
+
74731f
+  This program is distributed in the hope it will be useful, but WITHOUT
74731f
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
74731f
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
74731f
+  more details.
74731f
+
74731f
+  You should have received a copy of the GNU General Public License along with
74731f
+  this program; if not, write to the Free Software Foundation, Inc.,
74731f
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
74731f
+
74731f
+  The full GNU General Public License is included in this distribution in
74731f
+  the file called "COPYING".
74731f
+*******************************************************************************/
74731f
+
74731f
+#include <stdio.h>
74731f
+#include <stdlib.h>
74731f
+#include <string.h>
74731f
+#include <errno.h>
74731f
+#include <ctype.h>
74731f
+#include "messages.h"
74731f
+#include "qbg_vdp22def.h"
74731f
+#include "vdp_cisco.h"
74731f
+
74731f
+struct vdp22_oui_handler_s cisco_oui_hndlr = {
74731f
+		{0x00, 0x00, 0x0c}, "cisco", cisco_str2vdpnl_hndlr,
74731f
+		cisco_vdpnl2vsi22_hndlr,
74731f
+		cisco_vdp_tx_hndlr, cisco_vdp_rx_hndlr, cisco_vdp_free_oui,
74731f
+		cisco_vdp_oui_ptlvsize};
74731f
+
74731f
+struct oui_keyword_handler oui_key_handle[] = {
74731f
+	{CISCO_OUI_NAME_ARG_STR, CISCO_OUI_NAME_ARG},
74731f
+	{CISCO_OUI_NAME_UUID_ARG_STR, CISCO_OUI_NAME_UUID_ARG},
74731f
+	{CISCO_OUI_L3V4ADDR_ARG_STR, CISCO_OUI_L3V4ADDR_ARG} };
74731f
+
74731f
+enum oui_key_arg get_oui_key(char *token, u8 key_len)
74731f
+{
74731f
+	int count, key_str_size;
74731f
+
74731f
+	key_str_size = sizeof(oui_key_handle) / sizeof(oui_key_handle[0]);
74731f
+	for (count = 0; count < key_str_size; count++) {
74731f
+		if ((key_len <= strlen(token)) &&
74731f
+		     (!strncmp(token, oui_key_handle[count].keyword, key_len)))
74731f
+			return oui_key_handle[count].val;
74731f
+	}
74731f
+	return CISCO_OUI_INVALID_ARG;
74731f
+}
74731f
+
74731f
+/*
74731f
+ * This function fills the vdpnl structure of OUI from the command separated
74731f
+ * arguments containing the OUI information.
74731f
+ * The input to this function is right from the OUI data after the ORG specific
74731f
+ * OUI Type.
74731f
+ */
74731f
+
74731f
+bool cisco_str2vdpnl_hndlr(struct vdpnl_oui_data_s *vdp_oui_p, char *token)
74731f
+{
74731f
+	vdp_cisco_oui_t *vdp_cisco_oui_p;
74731f
+	char *uuid, *v4_addr_str;
74731f
+	int ret, offset = 0, len;
74731f
+	bool vm_name_flag = false, l3_addr_flag = false;
74731f
+	enum oui_key_arg oui_argtype;
74731f
+	u16 data_len;
74731f
+	u8 key_len;
74731f
+
74731f
+	if ((vdp_oui_p == NULL) || (token == NULL)) {
74731f
+		LLDPAD_ERR("%s: NULL arg\n", __func__);
74731f
+		return false;
74731f
+	}
74731f
+	fill_cisco_oui_type(vdp_oui_p->oui_type);
74731f
+	vdp_oui_p->len = sizeof(vdp_cisco_oui_t);
74731f
+	vdp_cisco_oui_p = (vdp_cisco_oui_t *)vdp_oui_p->data;
74731f
+	len = strlen(token);
74731f
+	while (offset < len) {
74731f
+		oui_vdp_hexstr2bin(token, &key_len, sizeof(key_len));
74731f
+		token += 2;
74731f
+		offset += 2;
74731f
+		oui_argtype = get_oui_key(token, key_len);
74731f
+		token += key_len;
74731f
+		offset += key_len;
74731f
+		oui_vdp_hexstr2bin(token, (u8 *)&data_len, sizeof(data_len));
74731f
+		data_len = htons(data_len);
74731f
+		token += 4;
74731f
+		offset += 4;
74731f
+		if ((offset + data_len) > len) {
74731f
+			LLDPAD_ERR("%s Incorrect len offset %d key %d data %d"
74731f
+					" Len %d\n", __func__, offset, key_len,
74731f
+					data_len, len);
74731f
+			return false;
74731f
+		}
74731f
+		switch (oui_argtype) {
74731f
+		case CISCO_OUI_NAME_ARG:
74731f
+			if (vm_name_flag) {
74731f
+				LLDPAD_ERR("%s: Incorrect arguments: Single VSI"
74731f
+					   " containing multiple VM Name\n",
74731f
+					   __func__);
74731f
+				return false;
74731f
+			}
74731f
+			vm_name_flag = true;
74731f
+			strncpy(vdp_cisco_oui_p->vm_name, token, data_len);
74731f
+			vdp_cisco_oui_p->vm_name[data_len] = '\0';
74731f
+			vdp_cisco_oui_p->vm_name_len = data_len;
74731f
+			LLDPAD_DBG("Name %s Len %ld\n",
74731f
+				   vdp_cisco_oui_p->vm_name,
74731f
+				   vdp_cisco_oui_p->vm_name_len);
74731f
+			break;
74731f
+		case CISCO_OUI_NAME_UUID_ARG:
74731f
+			uuid = calloc(data_len, sizeof(char));
74731f
+			if (uuid == NULL) {
74731f
+				LLDPAD_ERR("%s: NULL uuid\n", __func__);
74731f
+				return false;
74731f
+			}
74731f
+			strncpy(uuid, token, data_len);
74731f
+			if (oui_vdp_str2uuid(vdp_cisco_oui_p->uuid, uuid,
74731f
+					     sizeof(vdp_cisco_oui_p->uuid)))
74731f
+				memset(vdp_cisco_oui_p->uuid, 0,
74731f
+					sizeof(vdp_cisco_oui_p->uuid));
74731f
+			free(uuid);
74731f
+			break;
74731f
+		case CISCO_OUI_L3V4ADDR_ARG:
74731f
+			if (l3_addr_flag) {
74731f
+				LLDPAD_ERR("%s: Incorrect arguments: Single VSI"
74731f
+					   " containing multiple L3 Address\n",
74731f
+					   __func__);
74731f
+				return true;
74731f
+			}
74731f
+			l3_addr_flag = true;
74731f
+			vdp_cisco_oui_p->afi = MANADDR_IPV4;
74731f
+			vdp_cisco_oui_p->vm_addr_len =
74731f
+				sizeof(vdp_cisco_oui_p->l3_addr.ipv4_address);
74731f
+			v4_addr_str = calloc(data_len, sizeof(char));
74731f
+			if (v4_addr_str == NULL) {
74731f
+				LLDPAD_ERR("%s: NULL L3 Address\n", __func__);
74731f
+				return false;
74731f
+			}
74731f
+			strncpy(v4_addr_str, token, data_len);
74731f
+			ret = inet_aton(v4_addr_str,
74731f
+					&vdp_cisco_oui_p->l3_addr.ipv4_address);
74731f
+			LLDPAD_DBG("V4adr %s 0x%lx\n", v4_addr_str,
74731f
+				   (unsigned long)
74731f
+				  vdp_cisco_oui_p->l3_addr.ipv4_address.s_addr);
74731f
+			free(v4_addr_str);
74731f
+			if (!ret) {
74731f
+				LLDPAD_ERR("%s: Incorrect addr\n", __func__);
74731f
+				return false;
74731f
+			}
74731f
+			break;
74731f
+		default:
74731f
+			LLDPAD_ERR("%s: unknown subtype %d\n", __func__,
74731f
+				   oui_argtype);
74731f
+			return false;
74731f
+		}
74731f
+		token += data_len;
74731f
+		offset += data_len;
74731f
+	}
74731f
+	return true;
74731f
+}
74731f
+
74731f
+/*
74731f
+ * This function converts the OUI information from vdpnl struct to vdp22 struct
74731f
+ * vsi is not used here, but can be used for storing the pointer to the parent
74731f
+ * struct
74731f
+ */
74731f
+
74731f
+bool cisco_vdpnl2vsi22_hndlr(void *vsi_data, struct vdpnl_oui_data_s *from,
74731f
+			     struct vdp22_oui_data_s *to)
74731f
+{
74731f
+	if ((from == NULL) || (to == NULL)) {
74731f
+		LLDPAD_ERR("%s: NULL arg\n", __func__);
74731f
+		return false;
74731f
+	}
74731f
+	to->data = calloc(1, from->len);
74731f
+	if (to->data == NULL) {
74731f
+		LLDPAD_ERR("%s: calloc failure\n", __func__);
74731f
+		return false;
74731f
+	}
74731f
+	memcpy(to->oui_type, from->oui_type, sizeof(to->oui_type));
74731f
+	strncpy(to->oui_name, from->oui_name, sizeof(to->oui_name));
74731f
+	/* Parent Pointer */
74731f
+	to->vsi_data = vsi_data;
74731f
+	to->len = from->len;
74731f
+	memcpy(to->data, from->data, to->len);
74731f
+	return true;
74731f
+}
74731f
+
74731f
+/*
74731f
+ * This function deletes the OUI information associated with a VSI
74731f
+ */
74731f
+
74731f
+bool cisco_vdp_free_oui(struct vdp22_oui_data_s *vdp_oui_p)
74731f
+{
74731f
+	if ((vdp_oui_p == NULL) || (vdp_oui_p->data == NULL)) {
74731f
+		LLDPAD_ERR("%s: NULL arg\n", __func__);
74731f
+		return false;
74731f
+	}
74731f
+	free(vdp_oui_p->data);
74731f
+	vdp_oui_p->len = 0;
74731f
+	vdp_oui_p->data = NULL;
74731f
+	return true;
74731f
+}
74731f
+
74731f
+/*
74731f
+ * This gets called for any VDP specific response. Currently not implemented.
74731f
+ */
74731f
+
74731f
+bool cisco_vdp_rx_hndlr()
74731f
+{
74731f
+	return true;
74731f
+}
74731f
+
74731f
+static inline unsigned long cisco_vdp_name_subtlv_len(vdp_cisco_oui_t *ptr)
74731f
+{
74731f
+	return CISCO_VM_NAME_TLV_LEN + ptr->vm_name_len;
74731f
+}
74731f
+
74731f
+static inline unsigned long cisco_vdp_l3addr_subtlv_len(vdp_cisco_oui_t *ptr)
74731f
+{
74731f
+	return CISCO_VM_L3ADDR_TLV_LEN + ptr->vm_addr_len;
74731f
+}
74731f
+
74731f
+/*
74731f
+ * Returns the size
74731f
+ * ORG TLV's are sent separately for Name and IP, which is why the T,L of 2B
74731f
+ * and 3B for OUI_TYPE_LEN is added for both. This is done to be compatible
74731f
+ * with Cisco switch implementation.
74731f
+ */
74731f
+
74731f
+unsigned long cisco_vdp_oui_ptlvsize(void *arg_ptr)
74731f
+{
74731f
+	vdp_cisco_oui_t *ptr = (vdp_cisco_oui_t *)arg_ptr;
74731f
+	unsigned long cnt = 0;
74731f
+
74731f
+	if (ptr == NULL) {
74731f
+		LLDPAD_ERR("%s: Incorrect arg\n", __func__);
74731f
+		return 0;
74731f
+	}
74731f
+	if (ptr->vm_name_len != 0) {
74731f
+		cnt += 2 + VDP22_OUI_TYPE_LEN;
74731f
+		cnt += cisco_vdp_name_subtlv_len(ptr);
74731f
+	}
74731f
+	/* Only V4 or V6 is supported */
74731f
+	if ((ptr->afi == MANADDR_IPV4) || (ptr->afi == MANADDR_IPV6)) {
74731f
+		cnt += 2 + VDP22_OUI_TYPE_LEN;
74731f
+		cnt += cisco_vdp_l3addr_subtlv_len(ptr);
74731f
+	}
74731f
+	return cnt;
74731f
+}
74731f
+
74731f
+static inline size_t cisco_vdp22_gen_l3addr(char unsigned *cp, size_t offset,
74731f
+					    struct vdp22_oui_data_s *oui_ptr)
74731f
+{
74731f
+	vdp_cisco_oui_t *vdp_cisco_oui_str;
74731f
+	unsigned char *vsi = NULL;
74731f
+	unsigned short head;
74731f
+	unsigned char len = 0;
74731f
+	unsigned long net_l3_addr;
74731f
+
74731f
+	vdp_cisco_oui_str = (vdp_cisco_oui_t *)oui_ptr->data;
74731f
+	head = oui_get_tlv_head(VDP22_OUI, VDP22_OUI_TYPE_LEN +
74731f
+				cisco_vdp_l3addr_subtlv_len(oui_ptr->data));
74731f
+	offset += oui_append_2o(cp + offset, head);
74731f
+	offset += oui_append_3o(cp + offset, CISCO_OUI_HEX);
74731f
+	offset += oui_append_1o(cp + offset, CISCO_OUI_L3ADDR_SUBTYPE);
74731f
+	offset += oui_append_1o(cp + offset,
74731f
+				vdp22_oui_get_vsi22_fmt(oui_ptr->vsi_data));
74731f
+	vsi = vdp22_oui_get_vsi22_len(oui_ptr->vsi_data, &len;;
74731f
+	if (vsi != NULL)
74731f
+		offset += oui_append_nb(cp + offset, vsi, len);
74731f
+	else
74731f
+		LLDPAD_ERR("%s: get vsi22 return error\n", __func__);
74731f
+	offset += oui_append_2o(cp + offset, vdp_cisco_oui_str->afi);
74731f
+	if (vdp_cisco_oui_str->afi == MANADDR_IPV4) {
74731f
+		net_l3_addr = htonl(vdp_cisco_oui_str->l3_addr.
74731f
+				    ipv4_address.s_addr);
74731f
+		offset += oui_append_4o(cp + offset, net_l3_addr);
74731f
+	} else {
74731f
+		offset += oui_append_4o(cp + offset, 0);
74731f
+		LLDPAD_ERR("%s: Not supported for now\n", __func__);
74731f
+	}
74731f
+	LLDPAD_DBG("%s: Valid VM Addr offset %ld\n", __func__, offset);
74731f
+	return offset;
74731f
+}
74731f
+
74731f
+static inline size_t cisco_vdp22_gen_vmname(char unsigned *cp, size_t offset,
74731f
+					    struct vdp22_oui_data_s *oui_ptr)
74731f
+{
74731f
+	vdp_cisco_oui_t *vdp_cisco_oui_str;
74731f
+	unsigned char *vsi = NULL;
74731f
+	unsigned short head;
74731f
+	unsigned char len = 0;
74731f
+
74731f
+	vdp_cisco_oui_str = (vdp_cisco_oui_t *)oui_ptr->data;
74731f
+	head = oui_get_tlv_head(VDP22_OUI, VDP22_OUI_TYPE_LEN +
74731f
+				cisco_vdp_name_subtlv_len(oui_ptr->data));
74731f
+	offset += oui_append_2o(cp + offset, head);
74731f
+	offset += oui_append_3o(cp + offset, CISCO_OUI_HEX);
74731f
+	offset += oui_append_1o(cp + offset, CISCO_OUI_NAME_SUBTYPE);
74731f
+	offset += oui_append_1o(cp + offset,
74731f
+				vdp22_oui_get_vsi22_fmt(oui_ptr->vsi_data));
74731f
+	vsi = vdp22_oui_get_vsi22_len(oui_ptr->vsi_data, &len;;
74731f
+	if (vsi != NULL)
74731f
+		offset += oui_append_nb(cp + offset, vsi, len);
74731f
+	else
74731f
+		LLDPAD_ERR("%s: get vsi22 return error\n", __func__);
74731f
+	offset += oui_append_1o(cp + offset, VDP22_ID_UUID);
74731f
+	offset += oui_append_nb(cp + offset, vdp_cisco_oui_str->uuid,
74731f
+				sizeof(vdp_cisco_oui_str->uuid));
74731f
+	offset += oui_append_nb(cp + offset,
74731f
+				(char unsigned *)vdp_cisco_oui_str->vm_name,
74731f
+				vdp_cisco_oui_str->vm_name_len);
74731f
+	LLDPAD_DBG("%s: Valid VM Name offset %ld\n", __func__, offset);
74731f
+	return offset;
74731f
+}
74731f
+
74731f
+/*
74731f
+ * This function takes care of converting the OUI for Tx.
74731f
+ */
74731f
+
74731f
+size_t cisco_vdp_tx_hndlr(char unsigned *cp, struct vdp22_oui_data_s *oui_ptr,
74731f
+			  size_t offset)
74731f
+{
74731f
+	vdp_cisco_oui_t *vdp_cisco_oui_str;
74731f
+
74731f
+	if ((cp == NULL) || (oui_ptr == NULL) || (oui_ptr->data == NULL)) {
74731f
+		LLDPAD_ERR("%s: NULL Arguments\n", __func__);
74731f
+		return 0;
74731f
+	}
74731f
+	vdp_cisco_oui_str = (vdp_cisco_oui_t *)oui_ptr->data;
74731f
+	if (vdp_cisco_oui_str->vm_name_len != 0)
74731f
+		offset = cisco_vdp22_gen_vmname(cp, offset, oui_ptr);
74731f
+	if (vdp_cisco_oui_str->vm_addr_len != 0)
74731f
+		offset = cisco_vdp22_gen_l3addr(cp, offset, oui_ptr);
74731f
+	return offset;
74731f
+}
74731f
+
74731f
+bool cisco_oui_init()
74731f
+{
74731f
+	bool ret;
74731f
+
74731f
+	ret = oui_vdp_hndlr_init(&cisco_oui_hndlr);
74731f
+	if (!ret) {
74731f
+		LLDPAD_ERR("%s: handler init return err\n", __func__);
74731f
+		return false;
74731f
+	}
74731f
+	return true;
74731f
+}
74731f
diff --git a/vdptool.c b/vdptool.c
74731f
index c857a85..8edd6ca 100644
74731f
--- a/vdptool.c
74731f
+++ b/vdptool.c
74731f
@@ -65,10 +65,12 @@
74731f
  * here. The corresponding decoder handler should be in lldpad.
74731f
  */
74731f
 
74731f
+EXTERN_OUI_FN(cisco);
74731f
 
74731f
 /* The OUI specific handlers should be added here */
74731f
 
74731f
 vdptool_oui_hndlr_tbl_t oui_hndlr_tbl[] = {
74731f
+	{"cisco", OUI_ENCODE_HNDLR(cisco)}
74731f
 };
74731f
 
74731f
 
74731f
diff --git a/vdptool_cisco_oui.c b/vdptool_cisco_oui.c
74731f
new file mode 100644
74731f
index 0000000..4a846ad
74731f
--- /dev/null
74731f
+++ b/vdptool_cisco_oui.c
74731f
@@ -0,0 +1,58 @@
74731f
+/*******************************************************************************
74731f
+
74731f
+  Implementation of Cisco Specific OUI for vdptool
74731f
+  Copyright (c) 2012-2014 by Cisco Systems, Inc.
74731f
+
74731f
+  Author(s): Padmanabhan Krishnan <padkrish at cisco dot com>
74731f
+
74731f
+  This program is free software; you can redistribute it and/or modify it
74731f
+  under the terms and conditions of the GNU General Public License,
74731f
+  version 2, as published by the Free Software Foundation.
74731f
+
74731f
+  This program is distributed in the hope it will be useful, but WITHOUT
74731f
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
74731f
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
74731f
+  more details.
74731f
+
74731f
+  You should have received a copy of the GNU General Public License along with
74731f
+  this program; if not, write to the Free Software Foundation, Inc.,
74731f
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
74731f
+
74731f
+  The full GNU General Public License is included in this distribution in
74731f
+  the file called "COPYING".
74731f
+*******************************************************************************/
74731f
+
74731f
+#include <stdio.h>
74731f
+#include <stdlib.h>
74731f
+#include <string.h>
74731f
+#include "vdp_cisco.h"
74731f
+
74731f
+bool cisco_oui_encode_hndlr(char *dst, char *src, int len)
74731f
+{
74731f
+	char *src_temp = strdup(src);
74731f
+	char *key, *data;
74731f
+	bool flag = false;
74731f
+
74731f
+	if (!src_temp)
74731f
+		return false;
74731f
+	key = src_temp;
74731f
+	data = strchr(key, '=');
74731f
+	if (!data) {
74731f
+		free(src_temp);
74731f
+		return false;
74731f
+	}
74731f
+	*data = '\0';
74731f
+	data++;
74731f
+	if ((!strcmp(key, CISCO_OUI_NAME_ARG_STR)) ||
74731f
+	    (!strcmp(key, CISCO_OUI_L3V4ADDR_ARG_STR)) ||
74731f
+	    (!strcmp(key, CISCO_OUI_NAME_UUID_ARG_STR))) {
74731f
+		snprintf(dst, MAX_OUI_DATA_LEN - len, "%02x%s%04x%s",
74731f
+			 (unsigned int)strlen(key), key,
74731f
+			 (unsigned int)strlen(data), data);
74731f
+		flag = true;
74731f
+	} else
74731f
+		printf("Incorrect Cisco OUI %s\n", key);
74731f
+	free(src_temp);
74731f
+	return flag;
74731f
+}
74731f
+
74731f
-- 
74731f
2.1.0
74731f