Blame SOURCES/open-lldp-v1.0.1-5-VDP-Support-for-get-tlv-in-vdptool-and-VDP22.patch

74731f
From 0a21b0c0b9674f90cb9185e7fe097ae83657328f Mon Sep 17 00:00:00 2001
74731f
From: padkrish <padkrish@cisco.com>
74731f
Date: Wed, 21 Jan 2015 03:37:31 +0000
74731f
Subject: [PATCH] VDP: Support for get-tlv in vdptool and VDP22
74731f
74731f
This commit has the following changes:
74731f
a. Change in VDP22 and vdptool to support get-tlv. This actually refers to
74731f
get-vsi. Support for querying and printing all VSI's, partial VSI's is added.
74731f
The vdptool man page document is also modified accordingly.
74731f
b. The response from lldpad (VDP22) is modified to support to the
74731f
len, key, len, value format. Earlier, only the meessage to VDP22 has the
74731f
format. The response from VDP22 followed the comma separated format for VSI
74731f
parameters.
74731f
c. Fix some formatting issues
74731f
74731f
Signed-off-by: padkrish <padkrish@cisco.com>
74731f
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
74731f
---
74731f
 docs/vdptool.8         |  47 +++++++-----
74731f
 include/lldp_util.h    |   1 +
74731f
 include/qbg_vdp22.h    |   5 +-
74731f
 include/qbg_vdp22def.h |  11 ++-
74731f
 include/qbg_vdpnl.h    |   3 +
74731f
 lldp_util.c            |  52 ++++++++++----
74731f
 qbg/vdp22.c            |  28 ++++++--
74731f
 qbg/vdp22_cmds.c       | 135 +++++++++++++++++++++++++++++++----
74731f
 qbg/vdp22sm.c          |   5 +-
74731f
 qbg/vdp_ascii.c        | 190 +++++++++++++++++++++++++++++++------------------
74731f
 vdptool.c              | 152 +++++++++++----------------------------
74731f
 11 files changed, 395 insertions(+), 234 deletions(-)
74731f
74731f
diff --git a/docs/vdptool.8 b/docs/vdptool.8
74731f
index 5110bb9..02b4e8e 100644
74731f
--- a/docs/vdptool.8
74731f
+++ b/docs/vdptool.8
74731f
@@ -70,17 +70,17 @@ bridge.
74731f
 Specifies additional parameters for TLV queries and associations commands.
74731f
 The argument list varies, depending on the command option
74731f
 .B (-T)
74731f
-or 
74731f
+or
74731f
 .BR (-t) .
74731f
-To establish a VSI association use the command option 
74731f
+To establish a VSI association use the command option
74731f
 .B (-T)
74731f
 and specify additional information as arguments in the form
74731f
-of key=value. See the 
74731f
+of key=value. See the
74731f
 .I "VSI Parameter"
74731f
 subsection and
74731f
 .I Example
74731f
 section below.
74731f
-To query a VSI specific association use the command option 
74731f
+To query a VSI specific association use the command option
74731f
 .B (-t)
74731f
 and specify the value of the
74731f
 VSI Instance Identifier (keywork uuid followed be the VSI
74731f
@@ -92,6 +92,9 @@ show raw client interface messages
74731f
 .TP
74731f
 .B \-R
74731f
 show only raw Client interface messages
74731f
+.TP
74731f
+.B \-W
74731f
+Wait for the bridge response message
74731f
 .SS VSI Parameter
74731f
 Each VDP22 TLVs contains a command mode, manager identifier,
74731f
 type identifier, type identifier version, VSI instance identifier,
74731f
@@ -99,7 +102,7 @@ migiration hints and filter information.
74731f
 The fields are explained next:
74731f
 .TP
74731f
 .B "mode (Command Mode):"
74731f
-The command mode determines the type 
74731f
+The command mode determines the type
74731f
 of the VSI association to be established.
74731f
 It is an ascii string can be one of:
74731f
 .RS
74731f
@@ -110,7 +113,7 @@ Create an VSI preassociation. The association
74731f
 is only announced to the switch.
74731f
 .IP preassoc-rr:
74731f
 Create an VSI preassociation. The association
74731f
-is only announced to the switch and the 
74731f
+is only announced to the switch and the
74731f
 switch should reserve the resources.
74731f
 .IP deassoc:
74731f
 Delete an VSI association.
74731f
@@ -137,7 +140,7 @@ an UUID according to RFC 4122
74731f
 with optional dashes in between.
74731f
 .TP
74731f
 .B "hints (Migration Hints):"
74731f
-The migiration hints is a string aiding in 
74731f
+The migiration hints is a string aiding in
74731f
 migration of virtual machines:
74731f
 .RS
74731f
 .IP none:
74731f
@@ -168,13 +171,13 @@ The MAC address is specified in the format xx:xx:xx:xx:xx:xx.
74731f
 The colons are mandatory.
74731f
 For vlan details see (1).
74731f
 .IP "vlan-mac-group (4)"
74731f
-A vlan number, MAC address and group identifier, 
74731f
+A vlan number, MAC address and group identifier,
74731f
 each delimited by a slash ('-'),
74731f
 also known as filter information format 4.
74731f
 The group identifier is a 32 bit number.
74731f
 For vlan and MAC address details see (1) and (2).
74731f
 .IP "vlan--group (3)"
74731f
-A vlan number and group identifier, 
74731f
+A vlan number and group identifier,
74731f
 delimited by two slashes ('--'),
74731f
 also known as filter information format 3.
74731f
 For vlan and group details see (1) and (4).
74731f
@@ -218,18 +221,30 @@ vdptool -p
74731f
 Create a VSI association on interface eth2
74731f
 .br
74731f
 .nf
74731f
-Supported today: One config parameter and comma separated list
74731f
-vdptool -i eth2 -T -V assoc -c vsi=assoc,blabla,5, \\
74731f
-	1122,4,none,2-52:00:00:11:22:33-200
74731f
+vdptool -i eth2 -T -V assoc -c mode=assoc -c mgrid2=blabla \\
74731f
+	-c typeid=5 -c uuid=1122 -c typeidver=4 -c hints=none \\
74731f
+	-c filter=2-52:00:00:11:22:33-200
74731f
+.fi
74731f
+.TP
74731f
+Create a VSI association on interface eth2 and wait for the response from the bridge
74731f
+.br
74731f
+.nf
74731f
+vdptool -i eth2 -T -W -V assoc -c mode=assoc -c mgrid2=blabla \\
74731f
+	-c typeid=5 -c uuid=1122 -c typeidver=4 -c hints=none \\
74731f
+	-c filter=0-52:00:00:11:22:33-200
74731f
+.fi
74731f
 
74731f
-Planned for the future:
74731f
-vdptool -i eth2 -T -V assoc -c mgrid2=blabla -c typeid=5 \\
74731f
-	-c uuid=1122 -c typeidver=4 -c hints=none -c fid=2-52:00:00:11:22:33-200
74731f
-.fi
74731f
 .TP
74731f
 Query all VSI association on interface eth2
74731f
 .br
74731f
 vdptool -i eth2 -t -V assoc
74731f
+
74731f
+.TP
74731f
+Query  VSI association on interface eth2 that matches specific VSI parameters. Any of the VSI parameters below can be omitted.
74731f
+.br
74731f
+vdptool -i eth2 -t -V assoc -t -V assoc -c mode=assoc \\
74731f
+        -c mgrid2=blabla -c typeid=5 -c uuid=1122 \\
74731f
+        -c typeidver=4 -c hints=none
74731f
 .SH SEE ALSO
74731f
 .BR lldptool-dcbx (8),
74731f
 .BR lldptool-ets (8),
74731f
diff --git a/include/lldp_util.h b/include/lldp_util.h
74731f
index 5767d4e..878426b 100644
74731f
--- a/include/lldp_util.h
74731f
+++ b/include/lldp_util.h
74731f
@@ -170,6 +170,7 @@ int check_link_status(const char *ifname);
74731f
 int get_arg_val_list(char *ibuf, int ilen, int *ioff,
74731f
 			    char **args, char **argvals);
74731f
 int get_arg_list(char *ibuf, int ilen, int *ioff, char **args);
74731f
+int get_vsistr_arg_count(int ioff, int ilen);
74731f
 
74731f
 #define ntohll(x) be64_to_cpu(x)
74731f
 #define htonll(x) cpu_to_be64(x)
74731f
diff --git a/include/qbg_vdp22.h b/include/qbg_vdp22.h
74731f
index 45f44d5..af0aa15 100644
74731f
--- a/include/qbg_vdp22.h
74731f
+++ b/include/qbg_vdp22.h
74731f
@@ -165,7 +165,7 @@ struct vdp22_user_data {		/* Head for all VDP data */
74731f
 
74731f
 struct vsi_keyword_handler {
74731f
 	char *keyword;
74731f
-	enum vsi_mand_arg val;
74731f
+	enum vsi_key_arg val;
74731f
 };
74731f
 
74731f
 struct lldp_module *vdp22_register(void);
74731f
@@ -175,6 +175,7 @@ void vdp22_showvsi(struct vsi22 *p);
74731f
 void vdp22_stop(char *);
74731f
 int vdp22_from_ecp22(struct vdp22 *);
74731f
 int vdp22_query(const char *);
74731f
+struct vdp22 *vdp22_getvdp(const char *);
74731f
 int vdp22_addreq(struct vsi22 *, struct vdp22 *);
74731f
 int vdp22_nlback(struct vsi22 *);
74731f
 int vdp22_clntback(struct vsi22 *);
74731f
@@ -184,6 +185,8 @@ int vdp22br_resources(struct vsi22 *, int *);
74731f
 int vdp22_info(const char *);
74731f
 void vdp22_stop_timers(struct vsi22 *);
74731f
 int vdp22_start_localchange_timer(struct vsi22 *);
74731f
+bool vdp22_cmp_fdata(struct vsi22 *, struct vsi22 *);
74731f
+void vdp22_delete_vsi(struct vsi22 *);
74731f
 
74731f
 /*
74731f
  * Functions to get and set vlan identifier and qos.
74731f
diff --git a/include/qbg_vdp22def.h b/include/qbg_vdp22def.h
74731f
index 21ba15d..ff4270c 100644
74731f
--- a/include/qbg_vdp22def.h
74731f
+++ b/include/qbg_vdp22def.h
74731f
@@ -30,6 +30,15 @@
74731f
 #define QBG_VDP22DEF_H
74731f
 
74731f
 /*
74731f
+ * Define for length of vid-mac-gid
74731f
+ * VID in string cannot be more than 4B (Max is 4K)
74731f
+ * MAC when represented as 11:22:33:44:55:66 has 17B
74731f
+ * GID is 4B
74731f
+ * The below should be more than sufficient.
74731f
+ */
74731f
+#define MAX_GID_MAC_VID_STR 50
74731f
+
74731f
+/*
74731f
  * Define VDP22 filter formats.
74731f
  */
74731f
 enum vdp22_ffmt {			/* Format of filter information */
74731f
@@ -72,7 +81,7 @@ enum vdp22_migration_hints {
74731f
 	VDP22_MIGFROM = 32		/* S-bit migrate from hint */
74731f
 };
74731f
 
74731f
-enum vsi_mand_arg {
74731f
+enum vsi_key_arg {
74731f
 	VSI_MODE_ARG = 0,
74731f
 	VSI_MGRID2_ARG,
74731f
 	VSI_TYPEID_ARG,
74731f
diff --git a/include/qbg_vdpnl.h b/include/qbg_vdpnl.h
74731f
index 510a20c..c5c93ed 100644
74731f
--- a/include/qbg_vdpnl.h
74731f
+++ b/include/qbg_vdpnl.h
74731f
@@ -79,4 +79,7 @@ int vdp_str2vdpnl(char *, struct vdpnl_vsi *, char *);
74731f
 int vdp_vdpnl2str(struct vdpnl_vsi *, char *, size_t);
74731f
 int vdp22_sendevent(struct vdpnl_vsi *);
74731f
 void vdp22_freemaclist(struct vdpnl_vsi *);
74731f
+int vdp22_parse_str_vdpnl(struct vdpnl_vsi *, unsigned short *, char *);
74731f
+struct vsi22 *vdp22_alloc_vsi_ext(struct vdpnl_vsi *, int *);
74731f
+void copy_vsi_external(struct vdpnl_vsi *, struct vsi22 *, int);
74731f
 #endif
74731f
diff --git a/lldp_util.c b/lldp_util.c
74731f
index 754b0cd..f1fb7b9 100644
74731f
--- a/lldp_util.c
74731f
+++ b/lldp_util.c
74731f
@@ -199,7 +199,7 @@ int is_bond(const char *ifname)
74731f
  */
74731f
 int is_san_mac(u8 *addr)
74731f
 {
74731f
-	int i; 
74731f
+	int i;
74731f
 
74731f
 	for ( i = 0; i < ETH_ALEN; i++) {
74731f
 		if ( addr[i]!= 0xff )
74731f
@@ -215,7 +215,7 @@ int is_san_mac(u8 *addr)
74731f
  *	@addr: address of buffer in which to return the selected MAC address
74731f
  *
74731f
  *	Checks to see if ifname is a slave of the bond port.  If it is,
74731f
- *	then a 
74731f
+ *	then a
74731f
  *	Returns 0 if a source MAC from the bond could not be found. 1 is
74731f
  *	returned if the slave was found in the bond.  addr is updated with
74731f
  *	the source MAC that should be used.
74731f
@@ -287,7 +287,7 @@ int	get_src_mac_from_bond(struct port *bond_port, char *ifname, u8 *addr)
74731f
 
74731f
 	switch (ifb.bond_mode) {
74731f
 	case BOND_MODE_ACTIVEBACKUP:
74731f
-		/* If current port is not the active slave, then 
74731f
+		/* If current port is not the active slave, then
74731f
 		 * if the bond MAC is equal to the port's
74731f
 		 * permanent MAC, then find and return
74731f
 		 * the permanent MAC of the active
74731f
@@ -297,7 +297,7 @@ int	get_src_mac_from_bond(struct port *bond_port, char *ifname, u8 *addr)
74731f
 		if (strncmp(ifname, act_ifname, IFNAMSIZ))
74731f
 			if (get_perm_hwaddr(ifname, addr, san_mac) == 0)
74731f
 				if (!memcmp(bond_mac, addr, ETH_ALEN))
74731f
-					get_perm_hwaddr(act_ifname, addr, 
74731f
+					get_perm_hwaddr(act_ifname, addr,
74731f
 								san_mac);
74731f
 		break;
74731f
 	default:
74731f
@@ -346,7 +346,7 @@ int get_ifflags(const char *ifname)
74731f
 	int flags = 0;
74731f
 	struct ifreq ifr;
74731f
 
74731f
-	/* use ioctl */	
74731f
+	/* use ioctl */
74731f
 	fd = get_ioctl_socket();
74731f
 	if (fd >= 0) {
74731f
 		memset(&ifr, 0, sizeof(ifr));
74731f
@@ -382,7 +382,7 @@ int get_ifpflags(const char *ifname)
74731f
 	int flags = 0;
74731f
 	struct ifreq ifr;
74731f
 
74731f
-	/* use ioctl */	
74731f
+	/* use ioctl */
74731f
 	fd = get_ioctl_socket();
74731f
 	if (fd >= 0) {
74731f
 		memset(&ifr, 0, sizeof(ifr));
74731f
@@ -417,7 +417,7 @@ int get_iflink(const char *ifname)
74731f
 	snprintf(path, sizeof(path), "/sys/class/net/%s/iflink", ifname);
74731f
 	return read_int(path);
74731f
 }
74731f
-	
74731f
+
74731f
 int is_ether(const char *ifname)
74731f
 {
74731f
 	/* check for bridge in sysfs */
74731f
@@ -486,7 +486,7 @@ int is_slave(const char *ifmaster, const char *ifslave)
74731f
 			}
74731f
 		}
74731f
 	}
74731f
-	
74731f
+
74731f
 out_done:
74731f
 	return rc;
74731f
 }
74731f
@@ -562,13 +562,13 @@ int is_bridge(const char *ifname)
74731f
 	if (dirp) {
74731f
 		closedir(dirp);
74731f
 		rc = 1;
74731f
-	} else { 
74731f
-		/* use ioctl */	
74731f
+	} else {
74731f
+		/* use ioctl */
74731f
 		fd = get_ioctl_socket();
74731f
 		if (fd >= 0) {
74731f
 			struct ifreq ifr;
74731f
 			struct __bridge_info bi;
74731f
-			unsigned long args[4] = { BRCTL_GET_BRIDGE_INFO, 
74731f
+			unsigned long args[4] = { BRCTL_GET_BRIDGE_INFO,
74731f
 						 (unsigned long) &bi, 0, 0 };
74731f
 
74731f
 			ifr.ifr_data = (char *)args;
74731f
@@ -748,7 +748,7 @@ int is_autoneg_supported(const char *ifname)
74731f
 	int fd;
74731f
 	struct ifreq ifr;
74731f
 	struct ethtool_cmd cmd;
74731f
-	
74731f
+
74731f
 	fd = get_ioctl_socket();
74731f
 	if (fd >= 0) {
74731f
 		memset(&ifr, 0, sizeof(ifr));
74731f
@@ -769,7 +769,7 @@ int is_autoneg_enabled(const char *ifname)
74731f
 	int fd;
74731f
 	struct ifreq ifr;
74731f
 	struct ethtool_cmd cmd;
74731f
-	
74731f
+
74731f
 	fd = get_ioctl_socket();
74731f
 	if (fd >= 0) {
74731f
 		memset(&ifr, 0, sizeof(ifr));
74731f
@@ -806,7 +806,7 @@ int get_maucaps(const char *ifname)
74731f
 	u16 caps = MAUCAPADV_bOther;
74731f
 	struct ifreq ifr;
74731f
 	struct ethtool_cmd cmd;
74731f
-	
74731f
+
74731f
 	fd = get_ioctl_socket();
74731f
 	if (fd >= 0) {
74731f
 		memset(&ifr, 0, sizeof(ifr));
74731f
@@ -940,7 +940,7 @@ u16 get_caps(const char *ifname)
74731f
 
74731f
 	/* how to find TPID to determine C-VLAN vs. S-VLAN ? */
74731f
 	if (is_vlan(ifname))
74731f
-		caps |= SYSCAP_CVLAN; 
74731f
+		caps |= SYSCAP_CVLAN;
74731f
 
74731f
 	if (is_bridge(ifname))
74731f
 		caps |= SYSCAP_BRIDGE;
74731f
@@ -1282,3 +1282,25 @@ int get_arg_list(char *ibuf, int ilen, int *ioff, char **args)
74731f
 	free(arglens);
74731f
 	return numargs;
74731f
 }
74731f
+
74731f
+/*
74731f
+ * This functionality can be seen in many places to convert a LenData to a
74731f
+ * argument array.
74731f
+ */
74731f
+
74731f
+int get_vsistr_arg_count(int ioff, int ilen)
74731f
+{
74731f
+	int offset;
74731f
+	int numargs;
74731f
+
74731f
+	offset = ioff;
74731f
+	for (numargs = 0; (ilen - offset) > 2; numargs++) {
74731f
+		offset += 2;
74731f
+		if (ilen - offset > 0) {
74731f
+			offset++;
74731f
+			if (ilen - offset > 4)
74731f
+				offset += 4;
74731f
+		}
74731f
+	}
74731f
+	return numargs;
74731f
+}
74731f
diff --git a/qbg/vdp22.c b/qbg/vdp22.c
74731f
index a3cb7c9..af11af8 100644
74731f
--- a/qbg/vdp22.c
74731f
+++ b/qbg/vdp22.c
74731f
@@ -219,7 +219,7 @@ void vdp22_showvsi(struct vsi22 *p)
74731f
 /*
74731f
  * Delete a complete VSI node not on queue.
74731f
  */
74731f
-static void vdp22_delete_vsi(struct vsi22 *p)
74731f
+void vdp22_delete_vsi(struct vsi22 *p)
74731f
 {
74731f
 	LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, p->vdp->ifname, p,
74731f
 		   p->vsi[0]);
74731f
@@ -477,14 +477,15 @@ static bool filter_ok(unsigned char ffmt, struct fid22 *fp,
74731f
  * Allocate a VSI node with filter information data.
74731f
  * Check if input data is valid.
74731f
  */
74731f
-static struct vsi22 *vdp22_alloc_vsi(struct vdpnl_vsi *vsi, struct vdp22 *vdp,
74731f
-				     int *rc)
74731f
+static struct vsi22 *vdp22_alloc_vsi_int(struct vdpnl_vsi *vsi,
74731f
+					 struct vdp22 *vdp,
74731f
+					 int *rc, bool vsinl_chk)
74731f
 {
74731f
 	struct vsi22 *p;
74731f
 	int i;
74731f
 
74731f
 	*rc = -EINVAL;
74731f
-	if (!check_vsinl(vsi))
74731f
+	if (vsinl_chk && (!check_vsinl(vsi)))
74731f
 		return NULL;
74731f
 	p = calloc(1, sizeof(*p));
74731f
 	if (!p) {
74731f
@@ -546,6 +547,16 @@ error1:
74731f
 	return NULL;
74731f
 }
74731f
 
74731f
+struct vsi22 *vdp22_alloc_vsi_ext(struct vdpnl_vsi *vsinl, int *rc)
74731f
+{
74731f
+	struct vdp22 *vdp;
74731f
+
74731f
+	vdp = vdp22_getvdp(vsinl->ifname);
74731f
+	if (!vdp)
74731f
+		return NULL;
74731f
+	return vdp22_alloc_vsi_int(vsinl, vdp, rc, false);
74731f
+}
74731f
+
74731f
 /*
74731f
  * Allocate a VSI node with filter information data.
74731f
  * Check if input data is valid. Data was received by bridge from unknown
74731f
@@ -750,7 +761,7 @@ static struct vdp22 *vdp22_create(const char *ifname,
74731f
 /*
74731f
  * Query the supported VDP protocol on an interface.
74731f
  */
74731f
-static struct vdp22 *vdp22_getvdp(const char *ifname)
74731f
+struct vdp22 *vdp22_getvdp(const char *ifname)
74731f
 {
74731f
 	struct vdp22 *vdp;
74731f
 
74731f
@@ -820,7 +831,7 @@ int vdp22_request(struct vdpnl_vsi *vsi, int clif)
74731f
 		/* Adjust numbering for VDP 0.2 protocol from netlink */
74731f
 		if (!clif)
74731f
 			vsi->request += 1;
74731f
-		p = vdp22_alloc_vsi(vsi, vdp, &rc);
74731f
+		p = vdp22_alloc_vsi_int(vsi, vdp, &rc, true);
74731f
 		if (p) {
74731f
 			rc = vdp22_addreq(p, vdp);
74731f
 			if (rc)
74731f
@@ -1079,3 +1090,8 @@ int vdp22_info(const char *ifname)
74731f
 	return rc;
74731f
 
74731f
 }
74731f
+
74731f
+void copy_vsi_external(struct vdpnl_vsi *vsi, struct vsi22 *p, int clif)
74731f
+{
74731f
+	copy_vsi(vsi, p, clif);
74731f
+}
74731f
diff --git a/qbg/vdp22_cmds.c b/qbg/vdp22_cmds.c
74731f
index dde4669..409858d 100644
74731f
--- a/qbg/vdp22_cmds.c
74731f
+++ b/qbg/vdp22_cmds.c
74731f
@@ -237,7 +237,7 @@ int vdp22_clif_cmd(UNUSED void *data, UNUSED struct sockaddr_un *from,
74731f
 		return cmd_not_applicable;
74731f
 	}
74731f
 
74731f
-	if (!(cmd.ops & op_config))
74731f
+	if (!(cmd.ops & op_config) && (cmd.cmd != cmd_gettlv))
74731f
 		return cmd_invalid;
74731f
 
74731f
 	snprintf(rbuf, rlen, "%c%1x%02x%08x%02x%s",
74731f
@@ -254,10 +254,9 @@ int vdp22_clif_cmd(UNUSED void *data, UNUSED struct sockaddr_un *from,
74731f
 	snprintf(rbuf + roff, rlen - roff, "%08x", cmd.tlvid);
74731f
 	roff += 8;
74731f
 	if (cmd.cmd == cmd_gettlv) {
74731f
-		rstatus = handle_get_arg(&cmd, ARG_VDP22_VSI,
74731f
-						NULL,
74731f
-						rbuf + strlen(rbuf),
74731f
-						rlen - strlen(rbuf));
74731f
+		rstatus = handle_get_arg(&cmd, ARG_VDP22_VSI, ibuf + ioff,
74731f
+					 rbuf + strlen(rbuf),
74731f
+					 rlen - strlen(rbuf));
74731f
 	} else {
74731f
 		rstatus = handle_test_arg(&cmd, ARG_VDP22_VSI,
74731f
 						ibuf + ioff,
74731f
@@ -392,19 +391,25 @@ static int test_arg_vsi(struct cmd *cmd, UNUSED char *arg, char *argvalue,
74731f
  */
74731f
 static int catvsis(struct vdpnl_vsi *vsi, char *out, size_t out_len)
74731f
 {
74731f
-	int rc, i;
74731f
+	int rc, i, len, c;
74731f
 	size_t used = 0;
74731f
 	unsigned char wanted_req = vsi->request;
74731f
+	char tmp_buf[MAX_CLIF_MSGBUF];
74731f
 
74731f
+	memset(tmp_buf, 0, sizeof(tmp_buf));
74731f
 	for (i = 1; vdp22_status(i, vsi, 1) > 0; ++i) {
74731f
 		if (wanted_req != vsi->request) {
74731f
 			vdp22_freemaclist(vsi);
74731f
 			continue;
74731f
 		}
74731f
-		rc = vdp_vdpnl2str(vsi, out + used, out_len - used);
74731f
+		rc = vdp_vdpnl2str(vsi, tmp_buf, out_len - used);
74731f
+		len = strlen(tmp_buf);
74731f
+		c = snprintf(out + used, out_len - used, "%04x%s", len,
74731f
+			     tmp_buf);
74731f
+		if ((c < 0) || ((unsigned)c >= (out_len - used)))
74731f
+			return 0;
74731f
 		vdp22_freemaclist(vsi);
74731f
 		if (rc) {
74731f
-			strcat(out, ";");
74731f
 			used = strlen(out);
74731f
 		} else
74731f
 			return 0;
74731f
@@ -413,15 +418,113 @@ static int catvsis(struct vdpnl_vsi *vsi, char *out, size_t out_len)
74731f
 }
74731f
 
74731f
 /*
74731f
+ * Based on the VSI arguments specified, checks if it matches.
74731f
+ * This does't check for all VSI parameters.
74731f
+ */
74731f
+
74731f
+static bool vdp22_partial_vsi_equal(struct vsi22 *p1, struct vsi22 *p2,
74731f
+				    enum vsi_key_arg vsi_arg_key_flags)
74731f
+{
74731f
+	enum vsi_key_arg key_enum;
74731f
+
74731f
+	for (key_enum = VSI_MODE_ARG; key_enum < VSI_INVALID_ARG; key_enum++) {
74731f
+		if (!((1 << key_enum) & vsi_arg_key_flags))
74731f
+			continue;
74731f
+		switch (key_enum) {
74731f
+		case VSI_MODE_ARG:
74731f
+			break;
74731f
+		case VSI_MGRID2_ARG:
74731f
+			if (memcmp(p1->mgrid, p2->mgrid,
74731f
+				   sizeof(p2->mgrid)))
74731f
+				return false;
74731f
+		case VSI_TYPEID_ARG:
74731f
+			if (p1->type_id != p2->type_id)
74731f
+				return false;
74731f
+			break;
74731f
+		case VSI_TYPEIDVER_ARG:
74731f
+			if (p1->type_ver != p2->type_ver)
74731f
+				return false;
74731f
+			break;
74731f
+#ifdef LATER
74731f
+/* Currently not supported */
74731f
+		case VSI_VSIIDFRMT_ARG:
74731f
+			if (p1->vsi_fmt != p2->vsi_fmt)
74731f
+				return false;
74731f
+			break;
74731f
+#endif
74731f
+		case VSI_VSIID_ARG:
74731f
+			if (memcmp(p1->vsi, p2->vsi, sizeof(p1->vsi)))
74731f
+				return false;
74731f
+			break;
74731f
+		case VSI_FILTER_ARG:
74731f
+			if ((p1->fif != p2->fif) || (!vdp22_cmp_fdata(p1, p2)))
74731f
+				return false;
74731f
+			break;
74731f
+		case VSI_HINTS_ARG:
74731f
+			break;
74731f
+		default:
74731f
+			return false;
74731f
+		}
74731f
+	}
74731f
+	return true;
74731f
+}
74731f
+
74731f
+static int get_vsi_partial_arg(UNUSED char *arg, char *orig_argvalue,
74731f
+			       struct vdpnl_vsi *vsinl, char *out,
74731f
+			       size_t out_len)
74731f
+{
74731f
+	char tmp_buf[MAX_CLIF_MSGBUF];
74731f
+	struct vsi22 *p, *vsi;
74731f
+	struct vdp22 *vdp;
74731f
+	size_t used = 0;
74731f
+	int rc = -ENOMEM, len, c;
74731f
+	u16 vsi_arg_key_flags = 0;
74731f
+
74731f
+	if (vdp22_parse_str_vdpnl(vsinl, &vsi_arg_key_flags, orig_argvalue))
74731f
+		goto out;
74731f
+	vdp = vdp22_getvdp(vsinl->ifname);
74731f
+	if (!vdp)
74731f
+		goto out;
74731f
+
74731f
+	vsi = vdp22_alloc_vsi_ext(vsinl, &rc);
74731f
+	if (!vsi)
74731f
+		goto out;
74731f
+	LIST_FOREACH(p, &vdp->vsi22_que, node) {
74731f
+		if (p->vsi_mode != vsi->vsi_mode)
74731f
+			continue;
74731f
+		if (vdp22_partial_vsi_equal(p, vsi, vsi_arg_key_flags)) {
74731f
+			copy_vsi_external(vsinl, p, 1);
74731f
+			rc = vdp_vdpnl2str(vsinl, tmp_buf, out_len - used);
74731f
+			len = strlen(tmp_buf);
74731f
+			c = snprintf(out + used, out_len - used, "%04x%s",
74731f
+				     len, tmp_buf);
74731f
+			vdp22_freemaclist(vsinl);
74731f
+			if ((c < 0) || ((unsigned)c >= (out_len - used)))
74731f
+				goto out_delvsi;
74731f
+			if (rc)
74731f
+				used = strlen(out);
74731f
+			else
74731f
+				goto out_delvsi;
74731f
+		}
74731f
+	}
74731f
+out_delvsi:
74731f
+	vdp22_delete_vsi(vsi);
74731f
+out:
74731f
+	return rc;
74731f
+}
74731f
+
74731f
+/*
74731f
  * Return all VSIs on a particular interface into one string.
74731f
  */
74731f
-static int get_arg_vsi(struct cmd *cmd, char *arg, UNUSED char *argvalue,
74731f
+static int get_arg_vsi(struct cmd *cmd, char *arg, char *argvalue,
74731f
 		       char *obuf, int obuf_len)
74731f
 {
74731f
 	cmd_status good_cmd = vdp22_cmdok(cmd, cmd_gettlv);
74731f
 	struct vdpnl_vsi vsi;
74731f
 	char vsi_str[MAX_CLIF_MSGBUF];
74731f
 	int rc;
74731f
+	int fsize = (cmd->ops >> OP_FID_POS) & 0xff;
74731f
+	struct vdpnl_mac mac[fsize];
74731f
 
74731f
 	if (good_cmd != cmd_success)
74731f
 		return good_cmd;
74731f
@@ -433,14 +536,20 @@ static int get_arg_vsi(struct cmd *cmd, char *arg, UNUSED char *argvalue,
74731f
 
74731f
 	memset(obuf, 0, obuf_len);
74731f
 	memset(&vsi, 0, sizeof(vsi));
74731f
+	memset(vsi_str, 0, sizeof(vsi_str));
74731f
 	vsi.request = cmd->tlvid;
74731f
 	strncpy(vsi.ifname, cmd->ifname, sizeof(vsi.ifname) - 1);
74731f
 	good_cmd = cmd_failed;
74731f
-	if (!catvsis(&vsi, vsi_str, sizeof(vsi_str)))
74731f
+	if ((cmd->ops & op_config) && (cmd->ops & op_arg)) {
74731f
+		memset(&mac, 0, sizeof(mac));
74731f
+		vsi.macsz = fsize;
74731f
+		vsi.maclist = mac;
74731f
+		if (!get_vsi_partial_arg(arg, argvalue, &vsi, vsi_str,
74731f
+					 sizeof(vsi_str)))
74731f
+			goto out;
74731f
+	} else if (!catvsis(&vsi, vsi_str, sizeof(vsi_str)))
74731f
 		goto out;
74731f
-	rc = snprintf(obuf, obuf_len, "%02x%s%04x%s",
74731f
-		 (unsigned int)strlen(arg), arg, (unsigned int)strlen(vsi_str),
74731f
-		 vsi_str);
74731f
+	rc = snprintf(obuf, obuf_len, "%s", vsi_str);
74731f
 	if (rc > 0 || rc < obuf_len)
74731f
 		good_cmd = cmd_success;
74731f
 out:
74731f
diff --git a/qbg/vdp22sm.c b/qbg/vdp22sm.c
74731f
index d1f65b4..6264f74 100644
74731f
--- a/qbg/vdp22sm.c
74731f
+++ b/qbg/vdp22sm.c
74731f
@@ -944,7 +944,8 @@ static bool cmp_fdata1(struct fid22 *p1, struct fid22 *p2, unsigned char fif)
74731f
 
74731f
 	if (fif == VDP22_FFMT_MACVID || fif == VDP22_FFMT_GROUPMACVID)
74731f
 		is_good = !memcmp(p1->mac, p2->mac, sizeof(p1->mac));
74731f
-	if (fif == VDP22_FFMT_GROUPVID || fif == VDP22_FFMT_GROUPMACVID)
74731f
+	if (is_good &&
74731f
+		(fif == VDP22_FFMT_GROUPVID || fif == VDP22_FFMT_GROUPMACVID))
74731f
 		is_good = (p1->grpid == p2->grpid);
74731f
 	if (is_good) {
74731f
 		if (vdp22_get_vlanid(p1->vlan))
74731f
@@ -956,7 +957,7 @@ static bool cmp_fdata1(struct fid22 *p1, struct fid22 *p2, unsigned char fif)
74731f
 	return is_good;
74731f
 }
74731f
 
74731f
-static bool vdp22_cmp_fdata(struct vsi22 *p, struct vsi22 *vsip)
74731f
+bool vdp22_cmp_fdata(struct vsi22 *p, struct vsi22 *vsip)
74731f
 {
74731f
 	int i;
74731f
 
74731f
diff --git a/qbg/vdp_ascii.c b/qbg/vdp_ascii.c
74731f
index 09e53c6..76dde4a 100644
74731f
--- a/qbg/vdp_ascii.c
74731f
+++ b/qbg/vdp_ascii.c
74731f
@@ -110,6 +110,15 @@ static bool getnumber(char *s, unsigned int min, unsigned int max,
74731f
 }
74731f
 
74731f
 /*
74731f
+ * Returns the byte length of a given number
74731f
+ */
74731f
+
74731f
+static int get_strlen_num(unsigned long no)
74731f
+{
74731f
+	return snprintf(NULL, 0, "%lu", no);
74731f
+}
74731f
+
74731f
+/*
74731f
  * Read filter information data. The format is an ascii string:
74731f
  * filter-data		filter-format
74731f
  * vlan			1
74731f
@@ -264,7 +273,7 @@ static bool getmode(struct vdpnl_vsi *p, char *s)
74731f
 	return true;
74731f
 }
74731f
 
74731f
-enum vsi_mand_arg get_keywork_val(char *keyword)
74731f
+enum vsi_key_arg get_keywork_val(char *keyword)
74731f
 {
74731f
 	int count, key_str_size;
74731f
 
74731f
@@ -276,65 +285,36 @@ enum vsi_mand_arg get_keywork_val(char *keyword)
74731f
 	return VSI_INVALID_ARG;
74731f
 }
74731f
 
74731f
-/*
74731f
- * Parse the mode parameter to create/change an VSI assoication.
74731f
- * The format is a comma separated list of tokens:
74731f
- * cmd,mgrid,typeid,typeidversion,vsiid,hints,fid[,fid,fid,...]
74731f
- * with
74731f
- * cmd := "assoc" | "deassoc" | "preassoc" | "preassoc-rr"
74731f
- * mgrid :=  less or equal to 16 byte alphanumeric characters
74731f
- *		| UUID (with dashes in between)
74731f
- * typeid := number in range of 1 - 2^24 -1
74731f
- * typeidversion:= number in range of 1 - 255
74731f
- * vsiid := UUID (with dashes in between)
74731f
- * hints := varies between input (command) and output (event message)
74731f
- *          on input --> dash (-) | "none" | "from" | "to"
74731f
- *          on output --> response (number between 0..255)
74731f
- * fid := vlan
74731f
- *	| vlan-mac
74731f
- *	| vlan--group
74731f
- *	| vlan-mac-group
74731f
- * vlan := number in range of 1..2^16 -1
74731f
- * group := number in range of 1..2^32 - 1
74731f
- * mac := xx:xx:xx:xx:xx:xx
74731f
- */
74731f
-
74731f
-static int str2vdpnl(char *orig_argvalue, struct vdpnl_vsi *vsi)
74731f
+int vdp22_parse_str_vdpnl(struct vdpnl_vsi *vsi, u16 *key_flags,
74731f
+			  char *orig_argvalue)
74731f
 {
74731f
-	char **args;
74731f
 	char **argvals;
74731f
+	char **args;
74731f
 	char *argvalue;
74731f
+	enum vsi_key_arg vsi_key;
74731f
 	int rc = -ENOMEM;
74731f
+	int i, ioff = 0, numargs;
74731f
+	int ilen = strlen(orig_argvalue);
74731f
 	unsigned int no;
74731f
 	unsigned short idx = 0;
74731f
-	int i, ioff = 0, offset;
74731f
-	int ilen = strlen(orig_argvalue);
74731f
-	int numargs;
74731f
-	enum vsi_mand_arg vsi_key;
74731f
-	u16 vsi_mand_mask = (1 << VSI_MAND_NUM_ARG) - 1;
74731f
 	u16 num_arg_keys = 0;
74731f
 
74731f
 	argvalue = strdup(orig_argvalue);
74731f
 	if (!argvalue)
74731f
 		goto out;
74731f
 	/* Count args and argvalues */
74731f
-	offset = ioff;
74731f
-	for (numargs = 0; (ilen - offset) > 2; numargs++) {
74731f
-		offset += 2;
74731f
-		if (ilen - offset > 0) {
74731f
-			offset++;
74731f
-			if (ilen - offset > 4)
74731f
-				offset += 4;
74731f
-		}
74731f
-	}
74731f
+	numargs = get_vsistr_arg_count(ioff, ilen);
74731f
+	if (numargs == 0)
74731f
+		goto out_argvalue;
74731f
 	args = calloc(numargs, sizeof(char *));
74731f
 	if (!args)
74731f
 		goto out_argvalue;
74731f
-
74731f
 	argvals = calloc(numargs, sizeof(char *));
74731f
 	if (!argvals)
74731f
 		goto out_args;
74731f
 	numargs = get_arg_val_list(argvalue, ilen, &ioff, args, argvals);
74731f
+	if (numargs == 0)
74731f
+		goto out_free;
74731f
 	for (i = 0; i < numargs; i++) {
74731f
 		vsi_key = get_keywork_val(args[i]);
74731f
 		switch (vsi_key) {
74731f
@@ -378,9 +358,9 @@ static int str2vdpnl(char *orig_argvalue, struct vdpnl_vsi *vsi)
74731f
 		}
74731f
 		num_arg_keys |= (1 << vsi_key);
74731f
 	}
74731f
-	/* Return error if no filter information provided */
74731f
-	if ((num_arg_keys & vsi_mand_mask) == vsi_mand_mask)
74731f
-		rc = 0;
74731f
+	*key_flags = num_arg_keys;
74731f
+	rc = 0;
74731f
+
74731f
 out_free:
74731f
 	free(argvals);
74731f
 out_args:
74731f
@@ -392,6 +372,44 @@ out:
74731f
 }
74731f
 
74731f
 /*
74731f
+ * Parse the mode parameter to create/change an VSI assoication.
74731f
+ * The format is a comma separated list of tokens:
74731f
+ * cmd,mgrid,typeid,typeidversion,vsiid,hints,fid[,fid,fid,...]
74731f
+ * with
74731f
+ * cmd := "assoc" | "deassoc" | "preassoc" | "preassoc-rr"
74731f
+ * mgrid :=  less or equal to 16 byte alphanumeric characters
74731f
+ *		| UUID (with dashes in between)
74731f
+ * typeid := number in range of 1 - 2^24 -1
74731f
+ * typeidversion:= number in range of 1 - 255
74731f
+ * vsiid := UUID (with dashes in between)
74731f
+ * hints := varies between input (command) and output (event message)
74731f
+ *          on input --> dash (-) | "none" | "from" | "to"
74731f
+ *          on output --> response (number between 0..255)
74731f
+ * fid := vlan
74731f
+ *	| vlan-mac
74731f
+ *	| vlan--group
74731f
+ *	| vlan-mac-group
74731f
+ * vlan := number in range of 1..2^16 -1
74731f
+ * group := number in range of 1..2^32 - 1
74731f
+ * mac := xx:xx:xx:xx:xx:xx
74731f
+ */
74731f
+
74731f
+static int str2vdpnl(char *orig_argvalue, struct vdpnl_vsi *vsi)
74731f
+{
74731f
+	int rc = -ENOMEM;
74731f
+	u16 vsi_mand_mask = (1 << VSI_MAND_NUM_ARG) - 1;
74731f
+	u16 num_arg_keys = 0;
74731f
+
74731f
+	if (vdp22_parse_str_vdpnl(vsi, &num_arg_keys, orig_argvalue))
74731f
+		goto out;
74731f
+	/* Return error if no filter information provided */
74731f
+	if ((num_arg_keys & vsi_mand_mask) == vsi_mand_mask)
74731f
+		rc = 0;
74731f
+out:
74731f
+	return rc;
74731f
+}
74731f
+
74731f
+/*
74731f
  * Fill the vdpnl_vsi structure from the string.
74731f
  * Allocate the maclist. Must be free'ed by caller.
74731f
  */
74731f
@@ -426,6 +444,7 @@ static char *check_and_update(size_t *total, size_t *length, char *s, int c)
74731f
 /*
74731f
  * Convert VSI association to string.
74731f
  */
74731f
+#ifdef LATER_USE
74731f
 static const char *mode2str(unsigned char x)
74731f
 {
74731f
 	if (x == VDP22_ASSOC)
74731f
@@ -438,6 +457,7 @@ static const char *mode2str(unsigned char x)
74731f
 		return "deassoc";
74731f
 	return "unknown";
74731f
 }
74731f
+#endif
74731f
 
74731f
 /*
74731f
  * Convert filter information format into vlan[-mac][-group] string.
74731f
@@ -448,26 +468,50 @@ static int fid2str(char *s, size_t length, int fif, struct vdpnl_mac *p)
74731f
 {
74731f
 	int c;
74731f
 	size_t total = 0;
74731f
+	char tmp_buf[MAX_GID_MAC_VID_STR];
74731f
 
74731f
-	c = snprintf(s, length, "%d", vdp22_set_qos(p->qos) |
74731f
-		     vdp22_set_vlanid(p->vlan));
74731f
+	c = snprintf(s, length, "%02x%s",
74731f
+		     (unsigned int)strlen(VSI22_ARG_FILTER_STR),
74731f
+		     VSI22_ARG_FILTER_STR);
74731f
 	s = check_and_update(&total, &length, s, c);
74731f
 	if (!s)
74731f
 		goto out;
74731f
-	if (fif == VDP22_FFMT_MACVID || fif == VDP22_FFMT_GROUPMACVID) {
74731f
-		c = snprintf(s, length, "-%02x:%02x:%02x:%02x:%02x:%02x",
74731f
-			     p->mac[0], p->mac[1], p->mac[2], p->mac[3],
74731f
-			     p->mac[4], p->mac[5]);
74731f
-		s = check_and_update(&total, &length, s, c);
74731f
-		if (!s)
74731f
-			goto out;
74731f
-	}
74731f
-	if (fif == VDP22_FFMT_GROUPVID || fif == VDP22_FFMT_GROUPMACVID) {
74731f
-		c = snprintf(s, length, "-%ld", p->gpid);
74731f
-		s = check_and_update(&total, &length, s, c);
74731f
-		if (!s)
74731f
-			goto out;
74731f
+	memset(tmp_buf, 0, sizeof(tmp_buf));
74731f
+	switch (fif) {
74731f
+	case VDP22_FFMT_VID:
74731f
+		snprintf(tmp_buf, MAX_GID_MAC_VID_STR, "%d",
74731f
+			 vdp22_set_qos(p->qos) |
74731f
+			 vdp22_set_vlanid(p->vlan));
74731f
+		break;
74731f
+	case VDP22_FFMT_MACVID:
74731f
+		snprintf(tmp_buf, MAX_GID_MAC_VID_STR,
74731f
+			 "%d-%02x:%02x:%02x:%02x:%02x:%02x",
74731f
+			 vdp22_set_qos(p->qos) |
74731f
+			 vdp22_set_vlanid(p->vlan),
74731f
+			 p->mac[0], p->mac[1], p->mac[2], p->mac[3],
74731f
+			 p->mac[4], p->mac[5]);
74731f
+		break;
74731f
+	case VDP22_FFMT_GROUPVID:
74731f
+		snprintf(tmp_buf, MAX_GID_MAC_VID_STR,
74731f
+			 "%d-%ld",
74731f
+			 vdp22_set_qos(p->qos) | vdp22_set_vlanid(p->vlan),
74731f
+			 p->gpid);
74731f
+		break;
74731f
+	case VDP22_FFMT_GROUPMACVID:
74731f
+		snprintf(tmp_buf, MAX_GID_MAC_VID_STR,
74731f
+			 "%d-%02x:%02x:%02x:%02x:%02x:%02x-%ld",
74731f
+			 vdp22_set_qos(p->qos) | vdp22_set_vlanid(p->vlan),
74731f
+			 p->mac[0], p->mac[1], p->mac[2], p->mac[3],
74731f
+			 p->mac[4], p->mac[5], p->gpid);
74731f
+		break;
74731f
+	default:
74731f
+		break;
74731f
 	}
74731f
+	c = snprintf(s, length, "%04x%s", (unsigned int)strlen(tmp_buf),
74731f
+		     tmp_buf);
74731f
+	s = check_and_update(&total, &length, s, c);
74731f
+	if (!s)
74731f
+		goto out;
74731f
 out:
74731f
 	return s ? total : 0;
74731f
 }
74731f
@@ -500,15 +544,28 @@ int vdp_vdpnl2str(struct vdpnl_vsi *p, char *s, size_t length)
74731f
 	char instance[VDP_UUID_STRLEN + 2];
74731f
 
74731f
 	mgrid2str(instance, p, sizeof(instance));
74731f
-	c = snprintf(s, length, "%s,%s,%ld,%d,",
74731f
-		     mode2str(p->request), instance, p->vsi_typeid,
74731f
-		     p->vsi_typeversion);
74731f
+	c = snprintf(s, length, "%02x%s%04x%s%02x%s%04x%lu%02x%s%04x%d",
74731f
+		     (unsigned int)strlen(VSI22_ARG_MGRID_STR),
74731f
+		     VSI22_ARG_MGRID_STR,
74731f
+		     (unsigned int)strlen(instance), instance,
74731f
+		     (unsigned int)strlen(VSI22_ARG_TYPEID_STR),
74731f
+		     VSI22_ARG_TYPEID_STR, get_strlen_num(p->vsi_typeid),
74731f
+		     p->vsi_typeid,
74731f
+		     (unsigned int)strlen(VSI22_ARG_TYPEIDVER_STR),
74731f
+		     VSI22_ARG_TYPEIDVER_STR,
74731f
+		     get_strlen_num(p->vsi_typeversion), p->vsi_typeversion);
74731f
 	s = check_and_update(&total, &length, s, c);
74731f
 	if (!s)
74731f
 		goto out;
74731f
 
74731f
 	vdp_uuid2str(p->vsi_uuid, instance, sizeof(instance));
74731f
-	c = snprintf(s, length, "%s,%d,", instance, p->response);
74731f
+	c = snprintf(s, length, "%02x%s%04x%s%02x%s%04x%d",
74731f
+		     (unsigned int)strlen(VSI22_ARG_VSIID_STR),
74731f
+		     VSI22_ARG_VSIID_STR, (unsigned int)strlen(instance),
74731f
+		     instance,
74731f
+		     (unsigned int)strlen(VSI22_ARG_HINTS_STR),
74731f
+		     VSI22_ARG_HINTS_STR,
74731f
+		     get_strlen_num(p->response), p->response);
74731f
 	s = check_and_update(&total, &length, s, c);
74731f
 	if (!s)
74731f
 		goto out;
74731f
@@ -519,13 +576,8 @@ int vdp_vdpnl2str(struct vdpnl_vsi *p, char *s, size_t length)
74731f
 		s = check_and_update(&total, &length, s, c);
74731f
 		if (!c)
74731f
 			goto out;
74731f
-		if (p->macsz > 1 && i < p->macsz - 1) {
74731f
-			c = snprintf(s, length, ",");
74731f
-			s = check_and_update(&total, &length, s, c);
74731f
-			if (!s)
74731f
-				goto out;
74731f
-		}
74731f
 	}
74731f
+
74731f
 out:
74731f
 	return s ? total : 0;
74731f
 }
74731f
diff --git a/vdptool.c b/vdptool.c
74731f
index f506020..551e829 100644
74731f
--- a/vdptool.c
74731f
+++ b/vdptool.c
74731f
@@ -53,6 +53,7 @@
74731f
 
74731f
 #include "qbg22.h"
74731f
 #include "qbg_vdp22_clif.h"
74731f
+#include "lldp_util.h"
74731f
 
74731f
 static char *print_status(cmd_status status)
74731f
 {
74731f
@@ -129,7 +130,7 @@ static int render_cmd(struct cmd *cmd, int argc, char **args, char **argvals)
74731f
 
74731f
 	len = sizeof(cmd->obuf);
74731f
 
74731f
-	if (cmd->cmd == cmd_settlv) {
74731f
+	if ((cmd->cmd == cmd_settlv) || (cmd->cmd == cmd_gettlv)) {
74731f
 		for (i = 0; i < argc; i++) {
74731f
 			if (args[i]) {
74731f
 				if (!strncasecmp(args[i], "filter",
74731f
@@ -208,13 +209,6 @@ static int vdp_cmd_gettlv(struct clif *clif, int argc, char *argv[],
74731f
 		cmd->ops |= op_arg;
74731f
 	}
74731f
 
74731f
-	for (i = 0; i < numargs; i++) {
74731f
-		if (argvals[i]) {
74731f
-			printf("%s\n", print_status(cmd_invalid));
74731f
-			goto out;
74731f
-		}
74731f
-	}
74731f
-
74731f
 	render_cmd(cmd, argc, args, argvals);
74731f
 	free(args);
74731f
 	free(argvals);
74731f
@@ -305,125 +299,61 @@ static int vdp_parse_response(char *buf)
74731f
 	return hex2u8(buf + CLIF_STAT_OFF);
74731f
 }
74731f
 
74731f
-static void print_pair(char *arg, size_t arglen, char *value, size_t valuelen)
74731f
+int get_vsi_args(char *ibuf)
74731f
 {
74731f
-	while (arglen--)
74731f
-		putchar(*arg++);
74731f
-	putchar('=');
74731f
-	while (valuelen--)
74731f
-		putchar(*value++);
74731f
-	putchar('\n');
74731f
-}
74731f
+	int ioff = 0;
74731f
+	char **args;
74731f
+	char **argvals;
74731f
+	int numargs, i;
74731f
+	int ilen = strlen(ibuf);
74731f
 
74731f
-static int print_arg_value(char *ibuf)
74731f
-{
74731f
-	int arglen, valuelen, offset = 0, ilen = strlen(ibuf);
74731f
-	char *arg, *value;
74731f
+	/* count args and argvalus */
74731f
+	numargs = get_vsistr_arg_count(ioff, ilen);
74731f
 
74731f
-	while (offset < ilen) {
74731f
-		/* Length of argument */
74731f
-		arglen = hex2u8(ibuf + offset);
74731f
-		if (arglen < 0)
74731f
-			break;
74731f
-		offset += 2;
74731f
-		arg = ibuf + offset;
74731f
-		offset += arglen;
74731f
+	args = calloc(numargs, sizeof(char *));
74731f
+	if (!args)
74731f
+		return cmd_failed;
74731f
 
74731f
-		/* Length of argument value */
74731f
-		valuelen = hex2u16(ibuf + offset);
74731f
-		if (valuelen < 0)
74731f
-			break;
74731f
-		offset += 4;
74731f
-		value = ibuf + offset;
74731f
-		offset += valuelen;
74731f
+	argvals = calloc(numargs, sizeof(char *));
74731f
+	if (!argvals) {
74731f
+		free(args);
74731f
+		return cmd_failed;
74731f
+	}
74731f
 
74731f
-		print_pair(arg, arglen, value, valuelen);
74731f
+	numargs = get_arg_val_list(ibuf, ilen, &ioff, args, argvals);
74731f
+	for (i = 0; i < numargs; i++) {
74731f
+		printf("\t%s", args[i]);
74731f
+		printf(" = %s\n", argvals[i]);
74731f
 	}
74731f
-	return offset;
74731f
-}
74731f
 
74731f
-static int get_tlvid(char *ibuf)
74731f
-{
74731f
-	return hex2u32(ibuf);
74731f
+	free(args);
74731f
+	free(argvals);
74731f
+	return ioff;
74731f
 }
74731f
 
74731f
-/*
74731f
- * Print a TLV.
74731f
- */
74731f
-static void print_tlv2(char *ibuf)
74731f
+static void print_all_vsis(char *ibuf)
74731f
 {
74731f
 	size_t ilen = strlen(ibuf);
74731f
-	u16 tlv_type;
74731f
-	u16 tlv_len;
74731f
-	u32 tlvid;
74731f
-	int offset = 0;
74731f
-	int printed;
74731f
-	struct lldp_module *np;
74731f
+	u16 vsi_len;
74731f
+	int offset = 0, vsi_cnt = 0;
74731f
+	char tmp_ibuf[strlen(ibuf)];
74731f
 
74731f
 	while (ilen > 0) {
74731f
-		tlv_len = 2 * sizeof(u16);
74731f
-		if (ilen < 2 * sizeof(u16)) {
74731f
-			printf("corrupted TLV ilen:%zd, tlv_len:%d\n",
74731f
-				ilen, tlv_len);
74731f
-			break;
74731f
-		}
74731f
-		tlv_type = hex2u16(ibuf + offset);
74731f
-		tlv_len = tlv_type;
74731f
-		tlv_type >>= 9;
74731f
-		tlv_len &= 0x01ff;
74731f
+		vsi_len = hex2u16(ibuf + offset);
74731f
+		if (vsi_len > ilen)
74731f
+			return;
74731f
 		offset += 2 * sizeof(u16);
74731f
 		ilen -= 2 * sizeof(u16);
74731f
-
74731f
-		if (ilen < (unsigned) 2 * tlv_len) {
74731f
-			printf("corrupted TLV ilen:%zd, tlv_len:%d\n",
74731f
-				ilen, tlv_len);
74731f
-			break;
74731f
-		}
74731f
-		tlvid = tlv_type;
74731f
-		if (tlvid == INVALID_TLVID) {
74731f
-			tlvid = get_tlvid(ibuf + offset);
74731f
-			offset += 8;
74731f
-		}
74731f
-		printed = 0;
74731f
-		LIST_FOREACH(np, &lldp_head, lldp) {
74731f
-			if (np->ops->print_tlv(tlvid, tlv_len, ibuf + offset)) {
74731f
-				printed = 1;
74731f
-				break;
74731f
-			}
74731f
-		}
74731f
-
74731f
-		if (!printed) {
74731f
-			if (tlvid < INVALID_TLVID)
74731f
-				printf("Unidentified TLV\n\ttype:%d %*.*s\n",
74731f
-					tlv_type, tlv_len*2, tlv_len*2,
74731f
-					ibuf+offset);
74731f
-			else
74731f
-				printf("Unidentified Org Specific TLV\n\t"
74731f
-				      "OUI: 0x%06x, Subtype: %d, Info: %*.*s\n",
74731f
-					tlvid >> 8, tlvid & 0x0ff,
74731f
-					tlv_len*2-8, tlv_len*2-8,
74731f
-					ibuf+offset);
74731f
-		}
74731f
-		if (tlvid > INVALID_TLVID)
74731f
-			offset += (2 * tlv_len - 8);
74731f
-		else
74731f
-			offset += 2 * tlv_len;
74731f
-		ilen -= 2 * tlv_len;
74731f
-		if (tlvid == END_OF_LLDPDU_TLV)
74731f
-			break;
74731f
+		strncpy(tmp_ibuf, ibuf + offset, vsi_len);
74731f
+		tmp_ibuf[vsi_len] = '\0';
74731f
+		printf("%s %d:\n", "VSI ", vsi_cnt);
74731f
+		get_vsi_args(tmp_ibuf);
74731f
+		offset += vsi_len;
74731f
+		ilen -= vsi_len;
74731f
+		vsi_cnt++;
74731f
 	}
74731f
 }
74731f
 
74731f
-/* Print reply from get command */
74731f
-static void print_tlvs(struct cmd *cmd, char *ibuf)
74731f
-{
74731f
-	if (cmd->ops & op_config) {
74731f
-		print_arg_value(ibuf);
74731f
-		return;
74731f
-	}
74731f
-	print_tlv2(ibuf);
74731f
-}
74731f
-
74731f
 static void print_cmd_response(char *ibuf, int status)
74731f
 {
74731f
 	struct cmd cmd;
74731f
@@ -455,7 +385,7 @@ static void print_cmd_response(char *ibuf, int status)
74731f
 
74731f
 	switch (cmd.cmd) {
74731f
 	case cmd_gettlv:
74731f
-		print_tlvs(&cmd, ibuf + ioff);
74731f
+		print_all_vsis(ibuf + ioff);
74731f
 		break;
74731f
 	case cmd_settlv:
74731f
 		printf("%s", ibuf + ioff);
74731f
@@ -708,7 +638,7 @@ static int _clif_command(struct clif *clif, char *cmd, int print)
74731f
 	size_t len;
74731f
 	int ret;
74731f
 	int rc;
74731f
-	char reply[100];
74731f
+	char reply[200];
74731f
 	size_t reply_len2 = sizeof(reply);
74731f
 
74731f
 	print_raw_message(cmd, print);
74731f
-- 
74731f
2.1.0
74731f