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

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