|
|
89f6b3 |
From 3b559d8d0b52e6a254dc3f59833de4308e18711e Mon Sep 17 00:00:00 2001
|
|
|
89f6b3 |
From: Thomas Richter <tmricht@linux.vnet.ibm.com>
|
|
|
89f6b3 |
Date: Wed, 21 Jan 2015 03:36:26 +0000
|
|
|
89f6b3 |
Subject: [PATCH] VDP: vdptool first version
|
|
|
89f6b3 |
|
|
|
89f6b3 |
This is the first version of a vdp command line interface
|
|
|
89f6b3 |
tool to send and retrieve data to the vdp22 module.
|
|
|
89f6b3 |
This tool follows similar concept as the lldptool.
|
|
|
89f6b3 |
The command line options are similar and some intended
|
|
|
89f6b3 |
functionality (such as -n to retrieve neighbor inforamtion,
|
|
|
89f6b3 |
that is tlv data send by bridges) is not yet implemented.
|
|
|
89f6b3 |
|
|
|
89f6b3 |
Signed-off-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
|
|
|
89f6b3 |
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
|
|
|
89f6b3 |
---
|
|
|
89f6b3 |
.gitignore | 1 +
|
|
|
89f6b3 |
Makefile.am | 8 +-
|
|
|
89f6b3 |
docs/vdptool.8 | 280 +++++++++++
|
|
|
89f6b3 |
include/qbg_vdp22_clif.h | 2 +
|
|
|
89f6b3 |
qbg/vdp22_clif.c | 141 ++++++
|
|
|
89f6b3 |
vdptool.c | 1149 ++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
89f6b3 |
6 files changed, 1579 insertions(+), 2 deletions(-)
|
|
|
89f6b3 |
create mode 100644 docs/vdptool.8
|
|
|
89f6b3 |
create mode 100644 qbg/vdp22_clif.c
|
|
|
89f6b3 |
create mode 100644 vdptool.c
|
|
|
89f6b3 |
|
|
|
89f6b3 |
diff --git a/.gitignore b/.gitignore
|
|
|
89f6b3 |
index c2ac5d7..e2230d9 100644
|
|
|
89f6b3 |
--- a/.gitignore
|
|
|
89f6b3 |
+++ b/.gitignore
|
|
|
89f6b3 |
@@ -31,6 +31,7 @@ missing
|
|
|
89f6b3 |
dcbtool
|
|
|
89f6b3 |
lldpad
|
|
|
89f6b3 |
lldptool
|
|
|
89f6b3 |
+vdptool
|
|
|
89f6b3 |
nltest
|
|
|
89f6b3 |
vdptest
|
|
|
89f6b3 |
qbg22sim
|
|
|
89f6b3 |
diff --git a/Makefile.am b/Makefile.am
|
|
|
89f6b3 |
index 4889d32..fc4f8d6 100644
|
|
|
89f6b3 |
--- a/Makefile.am
|
|
|
89f6b3 |
+++ b/Makefile.am
|
|
|
89f6b3 |
@@ -1,5 +1,5 @@
|
|
|
89f6b3 |
# target programs to be installed in ${sbindir}
|
|
|
89f6b3 |
-sbin_PROGRAMS = lldpad dcbtool lldptool
|
|
|
89f6b3 |
+sbin_PROGRAMS = lldpad dcbtool lldptool vdptool
|
|
|
89f6b3 |
|
|
|
89f6b3 |
# package nltest and vdptest, but do not install it anywhere
|
|
|
89f6b3 |
if BUILD_DEBUG
|
|
|
89f6b3 |
@@ -41,7 +41,7 @@ include/parse_cli.h include/version.h include/lldptool_cli.h include/list.h \
|
|
|
89f6b3 |
include/lldp_mand_clif.h include/lldp_basman_clif.h include/lldp_med_clif.h \
|
|
|
89f6b3 |
include/lldp_8023_clif.h include/lldp_dcbx_clif.h include/lldp_evb_clif.h \
|
|
|
89f6b3 |
include/lldp_evb22_clif.h include/qbg_vdp_clif.h include/qbg_vdpnl.h \
|
|
|
89f6b3 |
-include/lldp_8021qaz_clif.h \
|
|
|
89f6b3 |
+include/qbg_vdp22_clif.h include/lldp_8021qaz_clif.h \
|
|
|
89f6b3 |
include/lldp_orgspec_clif.h include/lldp_cisco_clif.h \
|
|
|
89f6b3 |
include/lldptool.h include/lldp_rtnl.h include/dcbtool.h include/lldp_dcbx_cfg.h
|
|
|
89f6b3 |
|
|
|
89f6b3 |
@@ -76,6 +76,10 @@ liblldp_clif_la_LDFLAGS = -version-info 1:0:0
|
|
|
89f6b3 |
liblldp_clif_includedir = ${srcdir}/include
|
|
|
89f6b3 |
liblldp_clif_la_SOURCES = clif.c
|
|
|
89f6b3 |
|
|
|
89f6b3 |
+vdptool_SOURCES = vdptool.c lldp_util.c qbg/vdp22_clif.c
|
|
|
89f6b3 |
+vdptool_LDADD = ${srcdir}/liblldp_clif.la
|
|
|
89f6b3 |
+vdptool_LDFLAGS = -llldp_clif $(LIBNL_LIBS)
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
dcbtool_SOURCES = dcbtool.c dcbtool_cmds.c parse_cli.l \
|
|
|
89f6b3 |
weak_readline.c $(lldpad_include_HEADERS) $(noinst_HEADERS)
|
|
|
89f6b3 |
dcbtool_LDADD = ${srcdir}/liblldp_clif.la
|
|
|
89f6b3 |
diff --git a/docs/vdptool.8 b/docs/vdptool.8
|
|
|
89f6b3 |
new file mode 100644
|
|
|
89f6b3 |
index 0000000..5110bb9
|
|
|
89f6b3 |
--- /dev/null
|
|
|
89f6b3 |
+++ b/docs/vdptool.8
|
|
|
89f6b3 |
@@ -0,0 +1,280 @@
|
|
|
89f6b3 |
+.\" LICENSE
|
|
|
89f6b3 |
+.\"
|
|
|
89f6b3 |
+.\" This software program is released under the terms of a license agreement
|
|
|
89f6b3 |
+.\" between you ('Licensee') and Intel. Do not use or load this software or
|
|
|
89f6b3 |
+.\" any associated materials (collectively, the 'Software') until you have
|
|
|
89f6b3 |
+.\" carefully read the full terms and conditions of the LICENSE located in this
|
|
|
89f6b3 |
+.\" software package. By loading or using the Software, you agree to the
|
|
|
89f6b3 |
+.\" terms of this Agreement. If you do not agree with the terms of this
|
|
|
89f6b3 |
+.\" Agreement, do not install or use the Software.
|
|
|
89f6b3 |
+.\"
|
|
|
89f6b3 |
+.\" * Other names and brands may be claimed as the property of others.
|
|
|
89f6b3 |
+.\"
|
|
|
89f6b3 |
+.TH vdptool 8 "April 2014" "open-lldp" "Linux"
|
|
|
89f6b3 |
+.SH NAME
|
|
|
89f6b3 |
+vdptool \- manage the VSI associations and status of lldpad
|
|
|
89f6b3 |
+.SH SYNOPSIS
|
|
|
89f6b3 |
+.B vdptool <command> [options] [argument]
|
|
|
89f6b3 |
+.br
|
|
|
89f6b3 |
+.SH DESCRIPTION
|
|
|
89f6b3 |
+.B vdptool
|
|
|
89f6b3 |
+is used to query and configure the VSI associations in
|
|
|
89f6b3 |
+.B lldpad.
|
|
|
89f6b3 |
+Only the ratified stardard version of the VDP protocol
|
|
|
89f6b3 |
+(also refered to as vdp22) is supported.
|
|
|
89f6b3 |
+It connects to the client interface of
|
|
|
89f6b3 |
+.B lldpad
|
|
|
89f6b3 |
+to perform these operations.
|
|
|
89f6b3 |
+.B vdptool
|
|
|
89f6b3 |
+will operate in interactive mode if it is executed without a \fIcommand\fR.
|
|
|
89f6b3 |
+In interactive mode,
|
|
|
89f6b3 |
+.B vdptool
|
|
|
89f6b3 |
+will also function as an event listener to print out events
|
|
|
89f6b3 |
+as they are received asynchronously from
|
|
|
89f6b3 |
+.BR lldpad "(still to be done)."
|
|
|
89f6b3 |
+It will use libreadline for interactive input when available
|
|
|
89f6b3 |
+(still to be done).
|
|
|
89f6b3 |
+.SH OPTIONS
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B \-i [ifname]
|
|
|
89f6b3 |
+specifies the network interface to which the command applies. Most
|
|
|
89f6b3 |
+.B vdptool
|
|
|
89f6b3 |
+commands require specifying a network interface.
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B -V [tlvid]
|
|
|
89f6b3 |
+specifies the VDP tlv identifier to be set or queried.
|
|
|
89f6b3 |
+.br
|
|
|
89f6b3 |
+The tlvid is an integer value used to identify specific
|
|
|
89f6b3 |
+VDP TLVs. The tlvid value is the type value for types not equal
|
|
|
89f6b3 |
+to 127 (the organizationally specific type).
|
|
|
89f6b3 |
+For organizationally specific
|
|
|
89f6b3 |
+TLVs, the tlvid is the value represented by the 3 byte OUI and 1 byte
|
|
|
89f6b3 |
+subtype - where the subtype is the lowest order byte of the tlvid.
|
|
|
89f6b3 |
+.br
|
|
|
89f6b3 |
+The tlvid can be entered as a numerical value (e.g. 10 or 0xa), or for
|
|
|
89f6b3 |
+supported TLVs, as a keyword (such as assoc, deassoc, preassoc,
|
|
|
89f6b3 |
+preassoc-rr, etc).
|
|
|
89f6b3 |
+Review the
|
|
|
89f6b3 |
+.B vdptool
|
|
|
89f6b3 |
+help output to see the list of supported TLV keywords.
|
|
|
89f6b3 |
+.sp 1
|
|
|
89f6b3 |
+Use option -c to specify the parameters and its values to be set or queried.
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B \-n
|
|
|
89f6b3 |
+"neighbor" option for commands which can use it (e.g. get-tlv).
|
|
|
89f6b3 |
+Use this flag to retrieve the last VDP22 data returned from the
|
|
|
89f6b3 |
+bridge.
|
|
|
89f6b3 |
+(not yet supported).
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B \-c <argument list>
|
|
|
89f6b3 |
+Specifies additional parameters for TLV queries and associations commands.
|
|
|
89f6b3 |
+The argument list varies, depending on the command option
|
|
|
89f6b3 |
+.B (-T)
|
|
|
89f6b3 |
+or
|
|
|
89f6b3 |
+.BR (-t) .
|
|
|
89f6b3 |
+To establish a VSI association use the command option
|
|
|
89f6b3 |
+.B (-T)
|
|
|
89f6b3 |
+and specify additional information as arguments in the form
|
|
|
89f6b3 |
+of key=value. See the
|
|
|
89f6b3 |
+.I "VSI Parameter"
|
|
|
89f6b3 |
+subsection and
|
|
|
89f6b3 |
+.I Example
|
|
|
89f6b3 |
+section below.
|
|
|
89f6b3 |
+To query a VSI specific association use the command option
|
|
|
89f6b3 |
+.B (-t)
|
|
|
89f6b3 |
+and specify the value of the
|
|
|
89f6b3 |
+VSI Instance Identifier (keywork uuid followed be the VSI
|
|
|
89f6b3 |
+UUID value)
|
|
|
89f6b3 |
+of the VSI association as configuration parameter.
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B \-r
|
|
|
89f6b3 |
+show raw client interface messages
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B \-R
|
|
|
89f6b3 |
+show only raw Client interface messages
|
|
|
89f6b3 |
+.SS VSI Parameter
|
|
|
89f6b3 |
+Each VDP22 TLVs contains a command mode, manager identifier,
|
|
|
89f6b3 |
+type identifier, type identifier version, VSI instance identifier,
|
|
|
89f6b3 |
+migiration hints and filter information.
|
|
|
89f6b3 |
+The fields are explained next:
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B "mode (Command Mode):"
|
|
|
89f6b3 |
+The command mode determines the type
|
|
|
89f6b3 |
+of the VSI association to be established.
|
|
|
89f6b3 |
+It is an ascii string can be one of:
|
|
|
89f6b3 |
+.RS
|
|
|
89f6b3 |
+.IP assoc:
|
|
|
89f6b3 |
+Create an VSI association.
|
|
|
89f6b3 |
+.IP preassoc:
|
|
|
89f6b3 |
+Create an VSI preassociation. The association
|
|
|
89f6b3 |
+is only announced to the switch.
|
|
|
89f6b3 |
+.IP preassoc-rr:
|
|
|
89f6b3 |
+Create an VSI preassociation. The association
|
|
|
89f6b3 |
+is only announced to the switch and the
|
|
|
89f6b3 |
+switch should reserve the resources.
|
|
|
89f6b3 |
+.IP deassoc:
|
|
|
89f6b3 |
+Delete an VSI association.
|
|
|
89f6b3 |
+.RE
|
|
|
89f6b3 |
+Other strings are not recognized and return an error.
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B "mgrid2 (Manager identifier):"
|
|
|
89f6b3 |
+The manager identifier is a string of up to 16
|
|
|
89f6b3 |
+alphanumeric characters.
|
|
|
89f6b3 |
+It can also be an UUID according to RFC 4122
|
|
|
89f6b3 |
+with optional dashes in between.
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B "typeid (Type Identifier):"
|
|
|
89f6b3 |
+The type identifier is a number in the range
|
|
|
89f6b3 |
+of 0 to 2^24 - 1.
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B "typeidver (Type Identifier Version):"
|
|
|
89f6b3 |
+The type identifer version is a number
|
|
|
89f6b3 |
+in the range of 0 to 255.
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B "uuid (VSI Instance Identifier):"
|
|
|
89f6b3 |
+The VSI instance identifier is
|
|
|
89f6b3 |
+an UUID according to RFC 4122
|
|
|
89f6b3 |
+with optional dashes in between.
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B "hints (Migration Hints):"
|
|
|
89f6b3 |
+The migiration hints is a string aiding in
|
|
|
89f6b3 |
+migration of virtual machines:
|
|
|
89f6b3 |
+.RS
|
|
|
89f6b3 |
+.IP none:
|
|
|
89f6b3 |
+No hints available.
|
|
|
89f6b3 |
+.IP from:
|
|
|
89f6b3 |
+The virtual machine is migrating away.
|
|
|
89f6b3 |
+.IP to:
|
|
|
89f6b3 |
+The virtual machine is migrating to.
|
|
|
89f6b3 |
+.RE
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B "fid (Filter Information Data):"
|
|
|
89f6b3 |
+The filter information data can be supplied in four
|
|
|
89f6b3 |
+different formats identified by numbers in parathesis.
|
|
|
89f6b3 |
+Multiple filter information fields can be supplied,
|
|
|
89f6b3 |
+but all have to be of the same format.
|
|
|
89f6b3 |
+.RS
|
|
|
89f6b3 |
+.IP "vlan (1)"
|
|
|
89f6b3 |
+A vlan number only, also known as filter information format 1.
|
|
|
89f6b3 |
+The vlan identifier is a number in the range of 1 to 2^16 - 1.
|
|
|
89f6b3 |
+The high order 4 bits are used as quality of service bits.
|
|
|
89f6b3 |
+The vlan identifier can be zero, a vlan identifier is then
|
|
|
89f6b3 |
+selected by the switch. Refer to IEEE 802.1 Qbg ratified
|
|
|
89f6b3 |
+standard for details.
|
|
|
89f6b3 |
+.IP "vlan-mac (2)"
|
|
|
89f6b3 |
+A vlan number and MAC address delimited by a slash ('-'),
|
|
|
89f6b3 |
+also known as filter information format 2.
|
|
|
89f6b3 |
+The MAC address is specified in the format xx:xx:xx:xx:xx:xx.
|
|
|
89f6b3 |
+The colons are mandatory.
|
|
|
89f6b3 |
+For vlan details see (1).
|
|
|
89f6b3 |
+.IP "vlan-mac-group (4)"
|
|
|
89f6b3 |
+A vlan number, MAC address and group identifier,
|
|
|
89f6b3 |
+each delimited by a slash ('-'),
|
|
|
89f6b3 |
+also known as filter information format 4.
|
|
|
89f6b3 |
+The group identifier is a 32 bit number.
|
|
|
89f6b3 |
+For vlan and MAC address details see (1) and (2).
|
|
|
89f6b3 |
+.IP "vlan--group (3)"
|
|
|
89f6b3 |
+A vlan number and group identifier,
|
|
|
89f6b3 |
+delimited by two slashes ('--'),
|
|
|
89f6b3 |
+also known as filter information format 3.
|
|
|
89f6b3 |
+For vlan and group details see (1) and (4).
|
|
|
89f6b3 |
+.RE
|
|
|
89f6b3 |
+.SH COMMANDS
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B license
|
|
|
89f6b3 |
+show license information
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B \-h, help
|
|
|
89f6b3 |
+show usage information
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B \-v, version
|
|
|
89f6b3 |
+show version information
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B \-t, get-tlv
|
|
|
89f6b3 |
+get TLV information for the specified interface
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B \-T, set-tlv
|
|
|
89f6b3 |
+set TLV information for the specified interface
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B \-p, ping
|
|
|
89f6b3 |
+display the process identifier of the running lldpad process
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+.B \-q, quit
|
|
|
89f6b3 |
+exit from interactive mode
|
|
|
89f6b3 |
+.PP
|
|
|
89f6b3 |
+.SH NOTES
|
|
|
89f6b3 |
+This tool is in its early design and development phase.
|
|
|
89f6b3 |
+It it buggy, incomplete and most of the ideas have not even
|
|
|
89f6b3 |
+been thought of....
|
|
|
89f6b3 |
+It reflects the current state of development when
|
|
|
89f6b3 |
+I had been given another work assignment.
|
|
|
89f6b3 |
+I append it so some else can continue to work on this.
|
|
|
89f6b3 |
+.SH EXAMPLES
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+Display process identifier of lldpad
|
|
|
89f6b3 |
+.br
|
|
|
89f6b3 |
+vdptool -p
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+Create a VSI association on interface eth2
|
|
|
89f6b3 |
+.br
|
|
|
89f6b3 |
+.nf
|
|
|
89f6b3 |
+Supported today: One config parameter and comma separated list
|
|
|
89f6b3 |
+vdptool -i eth2 -T -V assoc -c vsi=assoc,blabla,5, \\
|
|
|
89f6b3 |
+ 1122,4,none,2-52:00:00:11:22:33-200
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+Planned for the future:
|
|
|
89f6b3 |
+vdptool -i eth2 -T -V assoc -c mgrid2=blabla -c typeid=5 \\
|
|
|
89f6b3 |
+ -c uuid=1122 -c typeidver=4 -c hints=none -c fid=2-52:00:00:11:22:33-200
|
|
|
89f6b3 |
+.fi
|
|
|
89f6b3 |
+.TP
|
|
|
89f6b3 |
+Query all VSI association on interface eth2
|
|
|
89f6b3 |
+.br
|
|
|
89f6b3 |
+vdptool -i eth2 -t -V assoc
|
|
|
89f6b3 |
+.SH SEE ALSO
|
|
|
89f6b3 |
+.BR lldptool-dcbx (8),
|
|
|
89f6b3 |
+.BR lldptool-ets (8),
|
|
|
89f6b3 |
+.BR lldptool-pfc (8),
|
|
|
89f6b3 |
+.BR lldptool-app (8),
|
|
|
89f6b3 |
+.BR lldptool-med (8),
|
|
|
89f6b3 |
+.BR lldptool-vdp (8),
|
|
|
89f6b3 |
+.BR lldptool-evb (8),
|
|
|
89f6b3 |
+.BR lldptool-evb22 (8),
|
|
|
89f6b3 |
+.BR dcbtool (8),
|
|
|
89f6b3 |
+.BR lldpad (8)
|
|
|
89f6b3 |
+.br
|
|
|
89f6b3 |
+.SH COPYRIGHT
|
|
|
89f6b3 |
+vdptool - VSI configuration utility
|
|
|
89f6b3 |
+.br
|
|
|
89f6b3 |
+.IP Copyright(c)
|
|
|
89f6b3 |
+(c) 2014 IBM Corporation.
|
|
|
89f6b3 |
+.BR
|
|
|
89f6b3 |
+Portions of vdptool are based on:
|
|
|
89f6b3 |
+.IP open-lldp-0.96
|
|
|
89f6b3 |
+.IP "lldptool - LLDP agent configuration utility"
|
|
|
89f6b3 |
+.IP Copyright(c)
|
|
|
89f6b3 |
+2007-2012 Intel Corporation.
|
|
|
89f6b3 |
+.BR
|
|
|
89f6b3 |
+Portions of lldptool are based on:
|
|
|
89f6b3 |
+.IP hostapd-0.5.7
|
|
|
89f6b3 |
+.IP Copyright
|
|
|
89f6b3 |
+(c) 2004-2008, Jouni Malinen <j@w1.fi>
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+.SH LICENSE
|
|
|
89f6b3 |
+This program is free software; you can redistribute it and/or modify it
|
|
|
89f6b3 |
+under the terms and conditions of the GNU General Public License,
|
|
|
89f6b3 |
+version 2, as published by the Free Software Foundation.
|
|
|
89f6b3 |
+.LP
|
|
|
89f6b3 |
+This program is distributed in the hope it will be useful, but WITHOUT
|
|
|
89f6b3 |
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
89f6b3 |
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
89f6b3 |
+more details.
|
|
|
89f6b3 |
+.LP
|
|
|
89f6b3 |
+You should have received a copy of the GNU General Public License along with
|
|
|
89f6b3 |
+this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
89f6b3 |
+51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
89f6b3 |
+.LP
|
|
|
89f6b3 |
+The full GNU General Public License is included in this distribution in
|
|
|
89f6b3 |
+the file called "COPYING".
|
|
|
89f6b3 |
+.SH SUPPORT
|
|
|
89f6b3 |
+Contact Information:
|
|
|
89f6b3 |
+open-lldp Mailing List <lldp-devel@open-lldp.org>
|
|
|
89f6b3 |
diff --git a/include/qbg_vdp22_clif.h b/include/qbg_vdp22_clif.h
|
|
|
89f6b3 |
index 20330b8..008022a 100644
|
|
|
89f6b3 |
--- a/include/qbg_vdp22_clif.h
|
|
|
89f6b3 |
+++ b/include/qbg_vdp22_clif.h
|
|
|
89f6b3 |
@@ -52,4 +52,6 @@ typedef enum {
|
|
|
89f6b3 |
op_delete = 0x20,
|
|
|
89f6b3 |
op_key = 0x40
|
|
|
89f6b3 |
} vdp22_op;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+struct lldp_module *vdp22_cli_register(void);
|
|
|
89f6b3 |
#endif
|
|
|
89f6b3 |
diff --git a/qbg/vdp22_clif.c b/qbg/vdp22_clif.c
|
|
|
89f6b3 |
new file mode 100644
|
|
|
89f6b3 |
index 0000000..649305d
|
|
|
89f6b3 |
--- /dev/null
|
|
|
89f6b3 |
+++ b/qbg/vdp22_clif.c
|
|
|
89f6b3 |
@@ -0,0 +1,141 @@
|
|
|
89f6b3 |
+/*******************************************************************************
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ Implementation of VDP 22 (ratified standard) according to IEEE 802.1Qbg
|
|
|
89f6b3 |
+ (c) Copyright IBM Corp. 2014
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ Author(s): Thomas Richter <tmricht@linux.vnet.ibm.com>
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ This program is free software; you can redistribute it and/or modify it
|
|
|
89f6b3 |
+ under the terms and conditions of the GNU General Public License,
|
|
|
89f6b3 |
+ version 2, as published by the Free Software Foundation.
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ This program is distributed in the hope it will be useful, but WITHOUT
|
|
|
89f6b3 |
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
89f6b3 |
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
89f6b3 |
+ more details.
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ You should have received a copy of the GNU General Public License along with
|
|
|
89f6b3 |
+ this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
89f6b3 |
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ The full GNU General Public License is included in this distribution in
|
|
|
89f6b3 |
+ the file called "COPYING".
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+*******************************************************************************/
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+#include <stdio.h>
|
|
|
89f6b3 |
+#include <stdlib.h>
|
|
|
89f6b3 |
+#include <syslog.h>
|
|
|
89f6b3 |
+#include <sys/un.h>
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+#include "lldp_mod.h"
|
|
|
89f6b3 |
+#include "clif_msgs.h"
|
|
|
89f6b3 |
+#include "lldp.h"
|
|
|
89f6b3 |
+#include "qbg22.h"
|
|
|
89f6b3 |
+#include "qbg_vdp22def.h"
|
|
|
89f6b3 |
+#include "qbg_vdpnl.h"
|
|
|
89f6b3 |
+#include "qbg_vdp22_cmds.h"
|
|
|
89f6b3 |
+#include "qbg_vdp22_clif.h"
|
|
|
89f6b3 |
+#include "qbg_vdp22def.h"
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static struct type_name_info vdp22_tlv_names[] = {
|
|
|
89f6b3 |
+ {
|
|
|
89f6b3 |
+ .name = "VDP VSI Association",
|
|
|
89f6b3 |
+ .key = "assoc",
|
|
|
89f6b3 |
+ .type = VDP22_ASSOC
|
|
|
89f6b3 |
+ },
|
|
|
89f6b3 |
+ {
|
|
|
89f6b3 |
+ .name = "VDP VSI Deassociation",
|
|
|
89f6b3 |
+ .key = "deassoc",
|
|
|
89f6b3 |
+ .type = VDP22_DEASSOC
|
|
|
89f6b3 |
+ },
|
|
|
89f6b3 |
+ {
|
|
|
89f6b3 |
+ .name = "VDP VSI Preassociation",
|
|
|
89f6b3 |
+ .key = "preassoc",
|
|
|
89f6b3 |
+ .type = VDP22_PREASSOC
|
|
|
89f6b3 |
+ },
|
|
|
89f6b3 |
+ {
|
|
|
89f6b3 |
+ .name = "VDP VSI Preassociation with resource reservation",
|
|
|
89f6b3 |
+ .key = "preassoc-rr",
|
|
|
89f6b3 |
+ .type = VDP22_PREASSOC_WITH_RR
|
|
|
89f6b3 |
+ },
|
|
|
89f6b3 |
+ {
|
|
|
89f6b3 |
+ .type = INVALID_TLVID
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+};
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int vdp22_print_help(void)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ struct type_name_info *tn = &vdp22_tlv_names[0];
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ while (tn->type != INVALID_TLVID) {
|
|
|
89f6b3 |
+ if (tn->key && strlen(tn->key) && tn->name) {
|
|
|
89f6b3 |
+ printf(" %s", tn->key);
|
|
|
89f6b3 |
+ if (strlen(tn->key) + 3 < 8)
|
|
|
89f6b3 |
+ printf("\t");
|
|
|
89f6b3 |
+ printf("\t: %s\n", tn->name);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ tn++;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ return 0;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static u32 vdp22_lookup_tlv_name(char *tlvid_str)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ struct type_name_info *tn = &vdp22_tlv_names[0];
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ while (tn->type != INVALID_TLVID) {
|
|
|
89f6b3 |
+ if (!strcasecmp(tn->key, tlvid_str))
|
|
|
89f6b3 |
+ return tn->type;
|
|
|
89f6b3 |
+ tn++;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ return INVALID_TLVID;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void vdp22_cli_unregister(struct lldp_module *mod)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ free(mod);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+/* return 1: if it printed the TLV
|
|
|
89f6b3 |
+ * 0: if it did not
|
|
|
89f6b3 |
+ */
|
|
|
89f6b3 |
+static int vdp22_print_tlv(u32 tlvid, u16 len, char *info)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ struct type_name_info *tn = &vdp22_tlv_names[0];
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ while (tn->type != INVALID_TLVID) {
|
|
|
89f6b3 |
+ if (tlvid == tn->type) {
|
|
|
89f6b3 |
+ printf("%s\n", tn->name);
|
|
|
89f6b3 |
+ if (tn->print_info) {
|
|
|
89f6b3 |
+ printf("\t");
|
|
|
89f6b3 |
+ tn->print_info(len - 4, info);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ return 1;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ tn++;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ return 0;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static const struct lldp_mod_ops vdp22_ops_clif = {
|
|
|
89f6b3 |
+ .lldp_mod_register = vdp22_cli_register,
|
|
|
89f6b3 |
+ .lldp_mod_unregister = vdp22_cli_unregister,
|
|
|
89f6b3 |
+ .print_tlv = vdp22_print_tlv,
|
|
|
89f6b3 |
+ .lookup_tlv_name = vdp22_lookup_tlv_name,
|
|
|
89f6b3 |
+ .print_help = vdp22_print_help,
|
|
|
89f6b3 |
+};
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+struct lldp_module *vdp22_cli_register(void)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ struct lldp_module *mod;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ mod = malloc(sizeof(*mod));
|
|
|
89f6b3 |
+ if (!mod) {
|
|
|
89f6b3 |
+ fprintf(stderr, "failed to malloc module data\n");
|
|
|
89f6b3 |
+ return NULL;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ mod->id = LLDP_MOD_VDP22;
|
|
|
89f6b3 |
+ mod->ops = &vdp22_ops_clif;
|
|
|
89f6b3 |
+ return mod;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
diff --git a/vdptool.c b/vdptool.c
|
|
|
89f6b3 |
new file mode 100644
|
|
|
89f6b3 |
index 0000000..e7d384a
|
|
|
89f6b3 |
--- /dev/null
|
|
|
89f6b3 |
+++ b/vdptool.c
|
|
|
89f6b3 |
@@ -0,0 +1,1149 @@
|
|
|
89f6b3 |
+/*******************************************************************************
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ LLDP Agent Daemon (LLDPAD) Software
|
|
|
89f6b3 |
+ Copyright(c) IBM Corp. 2014
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ Substantially modified from:
|
|
|
89f6b3 |
+ hostapd-0.5.7
|
|
|
89f6b3 |
+ Copyright (c) 2002-2007, Jouni Malinen <jkmaline@cc.hut.fi> and
|
|
|
89f6b3 |
+ contributors
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ This program is free software; you can redistribute it and/or modify it
|
|
|
89f6b3 |
+ under the terms and conditions of the GNU General Public License,
|
|
|
89f6b3 |
+ version 2, as published by the Free Software Foundation.
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ This program is distributed in the hope it will be useful, but WITHOUT
|
|
|
89f6b3 |
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
89f6b3 |
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
89f6b3 |
+ more details.
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ You should have received a copy of the GNU General Public License along with
|
|
|
89f6b3 |
+ this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
89f6b3 |
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ The full GNU General Public License is included in this distribution in
|
|
|
89f6b3 |
+ the file called "COPYING".
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ Contact Information:
|
|
|
89f6b3 |
+ open-lldp Mailing List <lldp-devel@open-lldp.org>
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+*******************************************************************************/
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+/*
|
|
|
89f6b3 |
+ * Thomas Richter, IBM LTC Boeblingen, Germany, Feb 2014
|
|
|
89f6b3 |
+ *
|
|
|
89f6b3 |
+ * Command line interface tool to connect to vdp module of lldpad to
|
|
|
89f6b3 |
+ * set and query VSI profile settings.
|
|
|
89f6b3 |
+ */
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+#include <stdlib.h>
|
|
|
89f6b3 |
+#include <stdio.h>
|
|
|
89f6b3 |
+#include <unistd.h>
|
|
|
89f6b3 |
+#include <signal.h>
|
|
|
89f6b3 |
+#include <ctype.h>
|
|
|
89f6b3 |
+#include <errno.h>
|
|
|
89f6b3 |
+#include <getopt.h>
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+#include <sys/queue.h>
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+#include "version.h"
|
|
|
89f6b3 |
+#include "clif.h"
|
|
|
89f6b3 |
+#include "clif_msgs.h"
|
|
|
89f6b3 |
+#include "lldp_mod.h"
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+#include "qbg22.h"
|
|
|
89f6b3 |
+#include "qbg_vdp22_clif.h"
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static char *print_status(cmd_status status)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ char *str;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ switch (status) {
|
|
|
89f6b3 |
+ case cmd_success:
|
|
|
89f6b3 |
+ str = "Successful";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case cmd_failed:
|
|
|
89f6b3 |
+ str = "Failed";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case cmd_device_not_found:
|
|
|
89f6b3 |
+ str = "Device not found or inactive";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case cmd_agent_not_found:
|
|
|
89f6b3 |
+ str = "Agent instance for device not found";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case cmd_invalid:
|
|
|
89f6b3 |
+ str = "Invalid command";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case cmd_bad_params:
|
|
|
89f6b3 |
+ str = "Invalid parameters";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case cmd_peer_not_present:
|
|
|
89f6b3 |
+ str = "Peer feature not present";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case cmd_ctrl_vers_not_compatible:
|
|
|
89f6b3 |
+ str = "Version not compatible";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case cmd_not_capable:
|
|
|
89f6b3 |
+ str = "Device not capable";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case cmd_not_applicable:
|
|
|
89f6b3 |
+ str = "Command not applicable";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case cmd_no_access:
|
|
|
89f6b3 |
+ str = "Access denied";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case cmd_agent_not_supported:
|
|
|
89f6b3 |
+ str = "TLV does not support agent type";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ default:
|
|
|
89f6b3 |
+ str = "Unknown status";
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ return str;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void get_arg_value(char *str, char **arg, char **argval)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ unsigned int i;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ for (i = 0; i < strlen(str); i++)
|
|
|
89f6b3 |
+ if (!isprint(str[i]))
|
|
|
89f6b3 |
+ return;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ for (i = 0; i < strlen(str); i++)
|
|
|
89f6b3 |
+ if (str[i] == '=')
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (i < strlen(str)) {
|
|
|
89f6b3 |
+ str[i] = '\0';
|
|
|
89f6b3 |
+ *argval = &str[i+1];
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ *arg = str;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int render_cmd(struct cmd *cmd, int argc, char **args, char **argvals)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ int len;
|
|
|
89f6b3 |
+ int i;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ len = sizeof(cmd->obuf);
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ /* all command messages begin this way */
|
|
|
89f6b3 |
+ snprintf(cmd->obuf, len, "%c%08x%c%1x%02x%08x%02x%s%02x%08x",
|
|
|
89f6b3 |
+ MOD_CMD, cmd->module_id, CMD_REQUEST, CLIF_MSG_VERSION,
|
|
|
89f6b3 |
+ cmd->cmd, cmd->ops, (unsigned int) strlen(cmd->ifname),
|
|
|
89f6b3 |
+ cmd->ifname, cmd->type, cmd->tlvid);
|
|
|
89f6b3 |
+#if PADDU
|
|
|
89f6b3 |
+ if (cmd->cmd == cmd_settlv) {
|
|
|
89f6b3 |
+ size_t len2 = 0;
|
|
|
89f6b3 |
+ /*
|
|
|
89f6b3 |
+ * Get total length and append it plus any args and argvals
|
|
|
89f6b3 |
+ * to the command message
|
|
|
89f6b3 |
+ */
|
|
|
89f6b3 |
+ for (i = 0; i < argc; i++) {
|
|
|
89f6b3 |
+ if (args[i])
|
|
|
89f6b3 |
+ len2 += 2 + strlen(args[i]);
|
|
|
89f6b3 |
+ if (argvals[i])
|
|
|
89f6b3 |
+ len2 += 4 + strlen(argvals[i]);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ snprintf(cmd->obuf + strlen(cmd->obuf), len - strlen(cmd->obuf),
|
|
|
89f6b3 |
+ "%04zx", len2);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+#endif
|
|
|
89f6b3 |
+ /* Add any args and argvals to the command message */
|
|
|
89f6b3 |
+ for (i = 0; i < argc; i++) {
|
|
|
89f6b3 |
+ if (args[i])
|
|
|
89f6b3 |
+ snprintf(cmd->obuf + strlen(cmd->obuf),
|
|
|
89f6b3 |
+ len - strlen(cmd->obuf),
|
|
|
89f6b3 |
+ "%02x%s", (unsigned int)strlen(args[i]),
|
|
|
89f6b3 |
+ args[i]);
|
|
|
89f6b3 |
+ if (argvals[i])
|
|
|
89f6b3 |
+ snprintf(cmd->obuf + strlen(cmd->obuf),
|
|
|
89f6b3 |
+ len - strlen(cmd->obuf), "%04x%s",
|
|
|
89f6b3 |
+ (unsigned int)strlen(argvals[i]), argvals[i]);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ return strlen(cmd->obuf);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+int vdp_clif_command(struct clif *, char *, int);
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int vdp_cmd_gettlv(struct clif *clif, int argc, char *argv[],
|
|
|
89f6b3 |
+ struct cmd *cmd, int raw)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ int numargs = 0;
|
|
|
89f6b3 |
+ char **args;
|
|
|
89f6b3 |
+ char **argvals;
|
|
|
89f6b3 |
+ int i;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (cmd->cmd != cmd_gettlv)
|
|
|
89f6b3 |
+ return cmd_invalid;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ args = calloc(argc, sizeof(char *));
|
|
|
89f6b3 |
+ if (!args)
|
|
|
89f6b3 |
+ return cmd_failed;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ argvals = calloc(argc, sizeof(char *));
|
|
|
89f6b3 |
+ if (!argvals) {
|
|
|
89f6b3 |
+ free(args);
|
|
|
89f6b3 |
+ return cmd_failed;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ for (i = 0; i < argc; i++)
|
|
|
89f6b3 |
+ get_arg_value(argv[i], &args[i], &argvals[i]);
|
|
|
89f6b3 |
+ numargs = i;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ /* Default is local tlv query */
|
|
|
89f6b3 |
+ if (!(cmd->ops & op_neighbor))
|
|
|
89f6b3 |
+ cmd->ops |= op_local;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (numargs) {
|
|
|
89f6b3 |
+ /* Only commands with the config option should have arguments.*/
|
|
|
89f6b3 |
+ if (!(cmd->ops & op_config)) {
|
|
|
89f6b3 |
+ printf("%s\n", print_status(cmd_invalid));
|
|
|
89f6b3 |
+ goto out;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ /* Commands to get neighbor TLVs cannot have arguments. */
|
|
|
89f6b3 |
+ if (cmd->ops & op_neighbor) {
|
|
|
89f6b3 |
+ printf("%s\n", print_status(cmd_invalid));
|
|
|
89f6b3 |
+ goto out;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ cmd->ops |= op_arg;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ for (i = 0; i < numargs; i++) {
|
|
|
89f6b3 |
+ if (argvals[i]) {
|
|
|
89f6b3 |
+ printf("%s\n", print_status(cmd_invalid));
|
|
|
89f6b3 |
+ goto out;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ render_cmd(cmd, argc, args, argvals);
|
|
|
89f6b3 |
+ free(args);
|
|
|
89f6b3 |
+ free(argvals);
|
|
|
89f6b3 |
+ return vdp_clif_command(clif, cmd->obuf, raw);
|
|
|
89f6b3 |
+out:
|
|
|
89f6b3 |
+ free(args);
|
|
|
89f6b3 |
+ free(argvals);
|
|
|
89f6b3 |
+ return cmd_invalid;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int vdp_cmd_settlv(struct clif *clif, int argc, char *argv[],
|
|
|
89f6b3 |
+ struct cmd *cmd, int raw)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ int numargs = 0;
|
|
|
89f6b3 |
+ char **args;
|
|
|
89f6b3 |
+ char **argvals;
|
|
|
89f6b3 |
+ int i;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (cmd->cmd != cmd_settlv)
|
|
|
89f6b3 |
+ return cmd_invalid;
|
|
|
89f6b3 |
+ args = calloc(argc, sizeof(char *));
|
|
|
89f6b3 |
+ if (!args)
|
|
|
89f6b3 |
+ return cmd_failed;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ argvals = calloc(argc, sizeof(char *));
|
|
|
89f6b3 |
+ if (!argvals) {
|
|
|
89f6b3 |
+ free(args);
|
|
|
89f6b3 |
+ return cmd_failed;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ for (i = 0; i < argc; i++)
|
|
|
89f6b3 |
+ get_arg_value(argv[i], &args[i], &argvals[i]);
|
|
|
89f6b3 |
+ numargs = i;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ for (i = 0; i < numargs; i++) {
|
|
|
89f6b3 |
+ if (!argvals[i]) {
|
|
|
89f6b3 |
+ printf("%s\n", print_status(cmd_invalid));
|
|
|
89f6b3 |
+ goto out;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (numargs)
|
|
|
89f6b3 |
+ cmd->ops |= (op_arg | op_argval);
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ render_cmd(cmd, argc, args, argvals);
|
|
|
89f6b3 |
+ free(args);
|
|
|
89f6b3 |
+ free(argvals);
|
|
|
89f6b3 |
+ return vdp_clif_command(clif, cmd->obuf, raw);
|
|
|
89f6b3 |
+out:
|
|
|
89f6b3 |
+ free(args);
|
|
|
89f6b3 |
+ free(argvals);
|
|
|
89f6b3 |
+ return cmd_invalid;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int hex2u8(char *b)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ int hex = -1;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (isxdigit(*b) && isxdigit(*(b + 1)))
|
|
|
89f6b3 |
+ sscanf(b, "%02x", &hex;;
|
|
|
89f6b3 |
+ return hex;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int hex2u16(char *b)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ int hex = -1;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (isxdigit(*b) && isxdigit(*(b + 1)) && isxdigit(*(b + 2))
|
|
|
89f6b3 |
+ && isxdigit(*(b + 3)))
|
|
|
89f6b3 |
+ sscanf(b, "%04x", &hex;;
|
|
|
89f6b3 |
+ return hex;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int hex2u32(char *b)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ int hex;
|
|
|
89f6b3 |
+ char *b_old = b;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ for (hex = 0; hex < 8; ++hex)
|
|
|
89f6b3 |
+ if (!isxdigit(*b++))
|
|
|
89f6b3 |
+ return -1;
|
|
|
89f6b3 |
+ sscanf(b_old, "%08x", &hex;;
|
|
|
89f6b3 |
+ return hex;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int vdp_parse_response(char *buf)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ return hex2u8(buf + CLIF_STAT_OFF);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void print_pair(char *arg, size_t arglen, char *value, size_t valuelen)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ while (arglen--)
|
|
|
89f6b3 |
+ putchar(*arg++);
|
|
|
89f6b3 |
+ putchar('=');
|
|
|
89f6b3 |
+ while (valuelen--)
|
|
|
89f6b3 |
+ putchar(*value++);
|
|
|
89f6b3 |
+ putchar('\n');
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int print_arg_value(char *ibuf)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ int arglen, valuelen, offset = 0, ilen = strlen(ibuf);
|
|
|
89f6b3 |
+ char *arg, *value;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ while (offset < ilen) {
|
|
|
89f6b3 |
+ /* Length of argument */
|
|
|
89f6b3 |
+ arglen = hex2u8(ibuf + offset);
|
|
|
89f6b3 |
+ if (arglen < 0)
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ offset += 2;
|
|
|
89f6b3 |
+ arg = ibuf + offset;
|
|
|
89f6b3 |
+ offset += arglen;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ /* Length of argument value */
|
|
|
89f6b3 |
+ valuelen = hex2u16(ibuf + offset);
|
|
|
89f6b3 |
+ if (valuelen < 0)
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ offset += 4;
|
|
|
89f6b3 |
+ value = ibuf + offset;
|
|
|
89f6b3 |
+ offset += valuelen;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ print_pair(arg, arglen, value, valuelen);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ return offset;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int get_tlvid(char *ibuf)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ return hex2u32(ibuf);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+/*
|
|
|
89f6b3 |
+ * Print a TLV.
|
|
|
89f6b3 |
+ */
|
|
|
89f6b3 |
+static void print_tlv2(char *ibuf)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ size_t ilen = strlen(ibuf);
|
|
|
89f6b3 |
+ u16 tlv_type;
|
|
|
89f6b3 |
+ u16 tlv_len;
|
|
|
89f6b3 |
+ u32 tlvid;
|
|
|
89f6b3 |
+ int offset = 0;
|
|
|
89f6b3 |
+ int printed;
|
|
|
89f6b3 |
+ struct lldp_module *np;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ while (ilen > 0) {
|
|
|
89f6b3 |
+ tlv_len = 2 * sizeof(u16);
|
|
|
89f6b3 |
+ if (ilen < 2 * sizeof(u16)) {
|
|
|
89f6b3 |
+ printf("corrupted TLV ilen:%zd, tlv_len:%d\n",
|
|
|
89f6b3 |
+ ilen, tlv_len);
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ tlv_type = hex2u16(ibuf + offset);
|
|
|
89f6b3 |
+ tlv_len = tlv_type;
|
|
|
89f6b3 |
+ tlv_type >>= 9;
|
|
|
89f6b3 |
+ tlv_len &= 0x01ff;
|
|
|
89f6b3 |
+ offset += 2 * sizeof(u16);
|
|
|
89f6b3 |
+ ilen -= 2 * sizeof(u16);
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (ilen < (unsigned) 2 * tlv_len) {
|
|
|
89f6b3 |
+ printf("corrupted TLV ilen:%zd, tlv_len:%d\n",
|
|
|
89f6b3 |
+ ilen, tlv_len);
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ tlvid = tlv_type;
|
|
|
89f6b3 |
+ if (tlvid == INVALID_TLVID) {
|
|
|
89f6b3 |
+ tlvid = get_tlvid(ibuf + offset);
|
|
|
89f6b3 |
+ offset += 8;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ printed = 0;
|
|
|
89f6b3 |
+ LIST_FOREACH(np, &lldp_head, lldp) {
|
|
|
89f6b3 |
+ if (np->ops->print_tlv(tlvid, tlv_len, ibuf + offset)) {
|
|
|
89f6b3 |
+ printed = 1;
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (!printed) {
|
|
|
89f6b3 |
+ if (tlvid < INVALID_TLVID)
|
|
|
89f6b3 |
+ printf("Unidentified TLV\n\ttype:%d %*.*s\n",
|
|
|
89f6b3 |
+ tlv_type, tlv_len*2, tlv_len*2,
|
|
|
89f6b3 |
+ ibuf+offset);
|
|
|
89f6b3 |
+ else
|
|
|
89f6b3 |
+ printf("Unidentified Org Specific TLV\n\t"
|
|
|
89f6b3 |
+ "OUI: 0x%06x, Subtype: %d, Info: %*.*s\n",
|
|
|
89f6b3 |
+ tlvid >> 8, tlvid & 0x0ff,
|
|
|
89f6b3 |
+ tlv_len*2-8, tlv_len*2-8,
|
|
|
89f6b3 |
+ ibuf+offset);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ if (tlvid > INVALID_TLVID)
|
|
|
89f6b3 |
+ offset += (2 * tlv_len - 8);
|
|
|
89f6b3 |
+ else
|
|
|
89f6b3 |
+ offset += 2 * tlv_len;
|
|
|
89f6b3 |
+ ilen -= 2 * tlv_len;
|
|
|
89f6b3 |
+ if (tlvid == END_OF_LLDPDU_TLV)
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+/* Print reply from get command */
|
|
|
89f6b3 |
+static void print_tlvs(struct cmd *cmd, char *ibuf)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ if (cmd->ops & op_config) {
|
|
|
89f6b3 |
+ print_arg_value(ibuf);
|
|
|
89f6b3 |
+ return;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ print_tlv2(ibuf);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void print_cmd_response(char *ibuf, int status)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ struct cmd cmd;
|
|
|
89f6b3 |
+ unsigned char len;
|
|
|
89f6b3 |
+ int ioff;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (status != cmd_success) {
|
|
|
89f6b3 |
+ printf("%s\n", print_status(status));
|
|
|
89f6b3 |
+ return;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ cmd.cmd = hex2u8(ibuf + CMD_CODE);
|
|
|
89f6b3 |
+ cmd.ops = hex2u32(ibuf + CMD_OPS);
|
|
|
89f6b3 |
+ len = hex2u8(ibuf + CMD_IF_LEN);
|
|
|
89f6b3 |
+ ioff = CMD_IF;
|
|
|
89f6b3 |
+ if (len < sizeof(cmd.ifname)) {
|
|
|
89f6b3 |
+ memcpy(cmd.ifname, ibuf + CMD_IF, len);
|
|
|
89f6b3 |
+ } else {
|
|
|
89f6b3 |
+ printf("Response ifname too long: %*s\n", (int)len, cmd.ifname);
|
|
|
89f6b3 |
+ return;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ cmd.ifname[len] = '\0';
|
|
|
89f6b3 |
+ ioff += len;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (cmd.cmd == cmd_gettlv || cmd.cmd == cmd_settlv) {
|
|
|
89f6b3 |
+ cmd.tlvid = hex2u32(ibuf + ioff);
|
|
|
89f6b3 |
+ ioff += 2 * sizeof(cmd.tlvid);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ switch (cmd.cmd) {
|
|
|
89f6b3 |
+ case cmd_gettlv:
|
|
|
89f6b3 |
+ print_tlvs(&cmd, ibuf + ioff);
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case cmd_settlv:
|
|
|
89f6b3 |
+ printf("%s", ibuf + ioff);
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ default:
|
|
|
89f6b3 |
+ return;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void vdp_print_response(char *buf, int status)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ switch (buf[CLIF_RSP_OFF]) {
|
|
|
89f6b3 |
+ case PING_CMD:
|
|
|
89f6b3 |
+ if (status)
|
|
|
89f6b3 |
+ printf("FAILED:%s\n", print_status(status));
|
|
|
89f6b3 |
+ else
|
|
|
89f6b3 |
+ printf("%s\n", buf + CLIF_RSP_OFF + 5);
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case ATTACH_CMD:
|
|
|
89f6b3 |
+ case DETACH_CMD:
|
|
|
89f6b3 |
+ if (status)
|
|
|
89f6b3 |
+ printf("FAILED:%s\n", print_status(status));
|
|
|
89f6b3 |
+ else
|
|
|
89f6b3 |
+ printf("OK\n");
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case CMD_REQUEST:
|
|
|
89f6b3 |
+ print_cmd_response(buf + CLIF_RSP_OFF, status);
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ default:
|
|
|
89f6b3 |
+ printf("Unknown VDP command response: %s\n", buf);
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void vdp_print_event_msg(char *buf)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ printf("%s buf:%s\n", __func__, buf);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+/*
|
|
|
89f6b3 |
+ * Dummy function to avoid linkage of many sources
|
|
|
89f6b3 |
+ */
|
|
|
89f6b3 |
+int get_perm_hwaddr(UNUSED const char *ifname, UNUSED unsigned char *buf_perm,
|
|
|
89f6b3 |
+ UNUSED unsigned char *buf_san)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ return -EIO;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int show_raw;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static const char *cli_version =
|
|
|
89f6b3 |
+ "vdptool v" LLDPTOOL_VERSION "\n"
|
|
|
89f6b3 |
+ "Copyright (c) 2014, IBM Corporation\n";
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static const char *cli_license =
|
|
|
89f6b3 |
+"This program is free software. You can distribute it and/or modify it\n"
|
|
|
89f6b3 |
+"under the terms of the GNU General Public License version 2.\n"
|
|
|
89f6b3 |
+"\n";
|
|
|
89f6b3 |
+/*
|
|
|
89f6b3 |
+"Alternatively, this software may be distributed under the terms of the\n"
|
|
|
89f6b3 |
+"BSD license. See README and COPYING for more details.\n";
|
|
|
89f6b3 |
+*/
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static const char *cli_full_license =
|
|
|
89f6b3 |
+"This program is free software; you can redistribute it and/or modify\n"
|
|
|
89f6b3 |
+"it under the terms of the GNU General Public License version 2 as\n"
|
|
|
89f6b3 |
+"published by the Free Software Foundation.\n"
|
|
|
89f6b3 |
+"\n"
|
|
|
89f6b3 |
+"This program is distributed in the hope that it will be useful,\n"
|
|
|
89f6b3 |
+"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
|
|
89f6b3 |
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
|
|
89f6b3 |
+"GNU General Public License for more details.\n"
|
|
|
89f6b3 |
+"\n"
|
|
|
89f6b3 |
+"You should have received a copy of the GNU General Public License\n"
|
|
|
89f6b3 |
+"along with this program; if not, write to the Free Software\n"
|
|
|
89f6b3 |
+"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
|
|
|
89f6b3 |
+"\n"
|
|
|
89f6b3 |
+"Alternatively, this software may be distributed under the terms of the\n"
|
|
|
89f6b3 |
+"BSD license.\n"
|
|
|
89f6b3 |
+"\n"
|
|
|
89f6b3 |
+"Redistribution and use in source and binary forms, with or without\n"
|
|
|
89f6b3 |
+"modification, are permitted provided that the following conditions are\n"
|
|
|
89f6b3 |
+"met:\n"
|
|
|
89f6b3 |
+"\n"
|
|
|
89f6b3 |
+"1. Redistributions of source code must retain the above copyright\n"
|
|
|
89f6b3 |
+" notice, this list of conditions and the following disclaimer.\n"
|
|
|
89f6b3 |
+"\n"
|
|
|
89f6b3 |
+"2. Redistributions in binary form must reproduce the above copyright\n"
|
|
|
89f6b3 |
+" notice, this list of conditions and the following disclaimer in the\n"
|
|
|
89f6b3 |
+" documentation and/or other materials provided with the distribution.\n"
|
|
|
89f6b3 |
+"\n"
|
|
|
89f6b3 |
+"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
|
|
|
89f6b3 |
+" names of its contributors may be used to endorse or promote products\n"
|
|
|
89f6b3 |
+" derived from this software without specific prior written permission.\n"
|
|
|
89f6b3 |
+"\n"
|
|
|
89f6b3 |
+"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
|
|
|
89f6b3 |
+"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
|
|
|
89f6b3 |
+"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
|
|
|
89f6b3 |
+"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
|
|
|
89f6b3 |
+"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
|
|
|
89f6b3 |
+"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
|
|
|
89f6b3 |
+"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
|
|
|
89f6b3 |
+"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
|
|
|
89f6b3 |
+"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
|
|
|
89f6b3 |
+"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
|
|
|
89f6b3 |
+"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
|
|
|
89f6b3 |
+"\n";
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static const char *commands_usage =
|
|
|
89f6b3 |
+"Usage:\n"
|
|
|
89f6b3 |
+" vdptool <command> [options] [arg] general command line usage format\n"
|
|
|
89f6b3 |
+" vdptool go into interactive mode\n"
|
|
|
89f6b3 |
+" <command> [options] [arg] general interactive command format\n";
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static const char *commands_options =
|
|
|
89f6b3 |
+"Options:\n"
|
|
|
89f6b3 |
+" -i [ifname] network interface\n"
|
|
|
89f6b3 |
+" -V [tlvid] TLV identifier\n"
|
|
|
89f6b3 |
+" may be numeric or keyword (see below)\n"
|
|
|
89f6b3 |
+" -c <argument list> used with get TLV command to specify\n"
|
|
|
89f6b3 |
+" that the list of configuration elements\n"
|
|
|
89f6b3 |
+" -n \"neighbor\" option for command (To be done)\n"
|
|
|
89f6b3 |
+" -r show raw message\n"
|
|
|
89f6b3 |
+" -R show only raw messages\n";
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static const char *commands_help =
|
|
|
89f6b3 |
+"Commands:\n"
|
|
|
89f6b3 |
+" license show license information\n"
|
|
|
89f6b3 |
+" -h|help show command usage information\n"
|
|
|
89f6b3 |
+" -v|version show version\n"
|
|
|
89f6b3 |
+" -p|ping ping lldpad and query pid of lldpad\n"
|
|
|
89f6b3 |
+" -q|quit exit lldptool (interactive mode)\n"
|
|
|
89f6b3 |
+" -t|get-tlv get tlvid value\n"
|
|
|
89f6b3 |
+" -T|set-tlv set arg for tlvid to value\n";
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static struct clif *clif_conn;
|
|
|
89f6b3 |
+static int cli_quit;
|
|
|
89f6b3 |
+static int cli_attached;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+/*
|
|
|
89f6b3 |
+ * insert to head, so first one is last
|
|
|
89f6b3 |
+ */
|
|
|
89f6b3 |
+struct lldp_module *(*register_tlv_table[])(void) = {
|
|
|
89f6b3 |
+ vdp22_cli_register,
|
|
|
89f6b3 |
+ NULL,
|
|
|
89f6b3 |
+};
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void init_modules(void)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ struct lldp_module *module;
|
|
|
89f6b3 |
+ struct lldp_module *premod = NULL;
|
|
|
89f6b3 |
+ int i = 0;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ LIST_INIT(&lldp_head);
|
|
|
89f6b3 |
+ for (i = 0; register_tlv_table[i]; i++) {
|
|
|
89f6b3 |
+ module = register_tlv_table[i]();
|
|
|
89f6b3 |
+ if (premod)
|
|
|
89f6b3 |
+ LIST_INSERT_AFTER(premod, module, lldp);
|
|
|
89f6b3 |
+ else
|
|
|
89f6b3 |
+ LIST_INSERT_HEAD(&lldp_head, module, lldp);
|
|
|
89f6b3 |
+ premod = module;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+void deinit_modules(void)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ struct lldp_module *module;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ while (lldp_head.lh_first != NULL) {
|
|
|
89f6b3 |
+ module = lldp_head.lh_first;
|
|
|
89f6b3 |
+ LIST_REMOVE(lldp_head.lh_first, lldp);
|
|
|
89f6b3 |
+ module->ops->lldp_mod_unregister(module);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void usage(void)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ fprintf(stderr, "%s\n", cli_version);
|
|
|
89f6b3 |
+ fprintf(stderr, "\n%s\n%s\n%s\n",
|
|
|
89f6b3 |
+ commands_usage, commands_options, commands_help);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void print_raw_message(char *msg, int print)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ if (!print || !(print & SHOW_RAW))
|
|
|
89f6b3 |
+ return;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (!(print & SHOW_RAW_ONLY)) {
|
|
|
89f6b3 |
+ switch (msg[MSG_TYPE]) {
|
|
|
89f6b3 |
+ case EVENT_MSG:
|
|
|
89f6b3 |
+ printf("event: ");
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case CMD_RESPONSE:
|
|
|
89f6b3 |
+ printf("rsp: ");
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ default:
|
|
|
89f6b3 |
+ printf("cmd: ");
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ printf("%s\n", msg);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int parse_print_message(char *msg, int print)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ int status = 0;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ status = vdp_parse_response(msg);
|
|
|
89f6b3 |
+ print_raw_message(msg, print);
|
|
|
89f6b3 |
+ if (print & SHOW_RAW_ONLY)
|
|
|
89f6b3 |
+ return status;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (msg[MSG_TYPE] == CMD_RESPONSE)
|
|
|
89f6b3 |
+ vdp_print_response(msg, status);
|
|
|
89f6b3 |
+ else if (msg[MSG_TYPE] == MOD_CMD && msg[MOD_MSG_TYPE] == EVENT_MSG)
|
|
|
89f6b3 |
+ vdp_print_event_msg(&msg[MOD_MSG_TYPE]);
|
|
|
89f6b3 |
+ return status;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void cli_close_connection(void)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ if (clif_conn == NULL)
|
|
|
89f6b3 |
+ return;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (cli_attached) {
|
|
|
89f6b3 |
+ clif_detach(clif_conn);
|
|
|
89f6b3 |
+ cli_attached = 0;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ clif_close(clif_conn);
|
|
|
89f6b3 |
+ clif_conn = NULL;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void cli_msg_cb(char *msg, UNUSED size_t len)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ parse_print_message(msg, SHOW_OUTPUT | show_raw);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+/* structure of the print argument bitmap:
|
|
|
89f6b3 |
+ * SHOW_NO_OUTPUT (0x0) - don't print anything for the command
|
|
|
89f6b3 |
+ * SHOW_OUTPUT (0x01) - print output for the command
|
|
|
89f6b3 |
+ * SHOW_RAW (0x02) - print the raw clif command messages
|
|
|
89f6b3 |
+ * SHOW_RAW_ONLY (0x04) - print only the raw clif command messages
|
|
|
89f6b3 |
+*/
|
|
|
89f6b3 |
+static int _clif_command(struct clif *clif, char *cmd, int print)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ char buf[MAX_CLIF_MSGBUF];
|
|
|
89f6b3 |
+ size_t len;
|
|
|
89f6b3 |
+ int ret;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ print_raw_message(cmd, print);
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (clif_conn == NULL) {
|
|
|
89f6b3 |
+ printf("Not connected to lldpad - command dropped.\n");
|
|
|
89f6b3 |
+ return -1;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ len = sizeof(buf) - 1;
|
|
|
89f6b3 |
+ ret = clif_request(clif, cmd, strlen(cmd), buf, &len, cli_msg_cb);
|
|
|
89f6b3 |
+ if (ret == -2) {
|
|
|
89f6b3 |
+ printf("'%s' command timed out.\n", cmd);
|
|
|
89f6b3 |
+ return -2;
|
|
|
89f6b3 |
+ } else if (ret < 0) {
|
|
|
89f6b3 |
+ printf("'%s' command failed.\n", cmd);
|
|
|
89f6b3 |
+ return -1;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ if (print) {
|
|
|
89f6b3 |
+ buf[len] = '\0';
|
|
|
89f6b3 |
+ ret = parse_print_message(buf, print);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ return ret;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+int vdp_clif_command(struct clif *clif, char *cmd, int raw)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ return _clif_command(clif, cmd, SHOW_OUTPUT | raw);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int cli_cmd_ping(struct clif *clif, UNUSED int argc, UNUSED char *argv[],
|
|
|
89f6b3 |
+ UNUSED struct cmd *command, int raw)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ return vdp_clif_command(clif, "P", raw);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int
|
|
|
89f6b3 |
+cli_cmd_nop(UNUSED struct clif *clif, UNUSED int argc, UNUSED char *argv[],
|
|
|
89f6b3 |
+ UNUSED struct cmd *command, UNUSED int raw)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ return 0;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int
|
|
|
89f6b3 |
+cli_cmd_help(UNUSED struct clif *clif, UNUSED int argc, UNUSED char *argv[],
|
|
|
89f6b3 |
+ UNUSED struct cmd *command, UNUSED int raw)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ struct lldp_module *np;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ printf("%s\n%s\n%s", commands_usage, commands_options, commands_help);
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ printf("\nTLV identifiers:\n");
|
|
|
89f6b3 |
+ LIST_FOREACH(np, &lldp_head, lldp)
|
|
|
89f6b3 |
+ if (np->ops->print_help)
|
|
|
89f6b3 |
+ np->ops->print_help();
|
|
|
89f6b3 |
+ return 0;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int
|
|
|
89f6b3 |
+cli_cmd_version(UNUSED struct clif *clif, UNUSED int argc, UNUSED char *argv[],
|
|
|
89f6b3 |
+ UNUSED struct cmd *command, UNUSED int raw)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ printf("%s\n", cli_version);
|
|
|
89f6b3 |
+ return 0;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int
|
|
|
89f6b3 |
+cli_cmd_license(UNUSED struct clif *clif, UNUSED int argc, UNUSED char *argv[],
|
|
|
89f6b3 |
+ UNUSED struct cmd *command, UNUSED int raw)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ printf("%s\n", cli_full_license);
|
|
|
89f6b3 |
+ return 0;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int
|
|
|
89f6b3 |
+cli_cmd_quit(UNUSED struct clif *clif, UNUSED int argc, UNUSED char *argv[],
|
|
|
89f6b3 |
+ UNUSED struct cmd *command, UNUSED int raw)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ cli_quit = 1;
|
|
|
89f6b3 |
+ return 0;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static struct cli_cmd {
|
|
|
89f6b3 |
+ vdp22_cmd cmdcode;
|
|
|
89f6b3 |
+ const char *cmdstr;
|
|
|
89f6b3 |
+ int (*handler)(struct clif *clif, int argc, char *argv[],
|
|
|
89f6b3 |
+ struct cmd *cmd, int raw);
|
|
|
89f6b3 |
+} cli_commands[] = {
|
|
|
89f6b3 |
+ { cmd_ping, "ping", cli_cmd_ping },
|
|
|
89f6b3 |
+ { cmd_help, "help", cli_cmd_help },
|
|
|
89f6b3 |
+ { cmd_license, "license", cli_cmd_license },
|
|
|
89f6b3 |
+ { cmd_version, "version", cli_cmd_version },
|
|
|
89f6b3 |
+ { cmd_quit, "quit", cli_cmd_quit },
|
|
|
89f6b3 |
+ { cmd_gettlv, "gettlv", vdp_cmd_gettlv },
|
|
|
89f6b3 |
+ { cmd_gettlv, "get-tlv", vdp_cmd_gettlv },
|
|
|
89f6b3 |
+ { cmd_settlv, "settlv", vdp_cmd_settlv },
|
|
|
89f6b3 |
+ { cmd_settlv, "set-tlv", vdp_cmd_settlv },
|
|
|
89f6b3 |
+ { cmd_nop, NULL, cli_cmd_nop }
|
|
|
89f6b3 |
+};
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+u32 lookup_tlvid(char *tlvid_str)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ struct lldp_module *np;
|
|
|
89f6b3 |
+ u32 tlvid = INVALID_TLVID;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ LIST_FOREACH(np, &lldp_head, lldp) {
|
|
|
89f6b3 |
+ if (np->ops->lookup_tlv_name) {
|
|
|
89f6b3 |
+ tlvid = np->ops->lookup_tlv_name(tlvid_str);
|
|
|
89f6b3 |
+ if (tlvid != INVALID_TLVID)
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ return tlvid;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+void print_args(int argc, char *argv[])
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ int i;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ for (i = 0; i < argc; i++)
|
|
|
89f6b3 |
+ printf("\tremaining arg %d = %s\n", i, argv[i]);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static struct option lldptool_opts[] = {
|
|
|
89f6b3 |
+ {"help", 0, NULL, 'h'},
|
|
|
89f6b3 |
+ {"version", 0, NULL, 'v'},
|
|
|
89f6b3 |
+ {"stats", 0, NULL, 'S'},
|
|
|
89f6b3 |
+ {"get-tlv", 0, NULL, 't'},
|
|
|
89f6b3 |
+ {"set-tlv", 0, NULL, 'T'},
|
|
|
89f6b3 |
+ {"get-lldp", 0, NULL, 'l'},
|
|
|
89f6b3 |
+ {"set-lldp", 0, NULL, 'L'},
|
|
|
89f6b3 |
+ {0, 0, 0, 0}
|
|
|
89f6b3 |
+};
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static int request(struct clif *clif, int argc, char *argv[])
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ struct cli_cmd *cmd, *match = NULL;
|
|
|
89f6b3 |
+ struct cmd command;
|
|
|
89f6b3 |
+ int count;
|
|
|
89f6b3 |
+ int ret = 0;
|
|
|
89f6b3 |
+ int newraw = 0;
|
|
|
89f6b3 |
+ int numargs = 0;
|
|
|
89f6b3 |
+ char **argptr = &argv[0];
|
|
|
89f6b3 |
+ char *end;
|
|
|
89f6b3 |
+ int c;
|
|
|
89f6b3 |
+ int option_index;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ memset((void *)&command, 0, sizeof(command));
|
|
|
89f6b3 |
+ command.cmd = cmd_nop;
|
|
|
89f6b3 |
+ command.type = NEAREST_CUSTOMER_BRIDGE;
|
|
|
89f6b3 |
+ command.module_id = LLDP_MOD_VDP22;
|
|
|
89f6b3 |
+ command.tlvid = INVALID_TLVID;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ opterr = 0;
|
|
|
89f6b3 |
+ for (;;) {
|
|
|
89f6b3 |
+ c = getopt_long(argc, argv, "i:tThcnvrRpqV:",
|
|
|
89f6b3 |
+ lldptool_opts, &option_index);
|
|
|
89f6b3 |
+ if (c < 0)
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ switch (c) {
|
|
|
89f6b3 |
+ case '?':
|
|
|
89f6b3 |
+ printf("missing argument for option %s\n\n",
|
|
|
89f6b3 |
+ argv[optind-1]);
|
|
|
89f6b3 |
+ usage();
|
|
|
89f6b3 |
+ return -1;
|
|
|
89f6b3 |
+ case 'i':
|
|
|
89f6b3 |
+ strncpy(command.ifname, optarg, IFNAMSIZ);
|
|
|
89f6b3 |
+ command.ifname[IFNAMSIZ] = '\0';
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case 'V':
|
|
|
89f6b3 |
+ if (command.tlvid != INVALID_TLVID) {
|
|
|
89f6b3 |
+ printf("\nInvalid command: multiple TLV identifiers: %s\n",
|
|
|
89f6b3 |
+ optarg);
|
|
|
89f6b3 |
+ return -1;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ /* Currently tlvid unset lookup and verify parameter */
|
|
|
89f6b3 |
+ errno = 0;
|
|
|
89f6b3 |
+ command.tlvid = strtoul(optarg, &end, 0);
|
|
|
89f6b3 |
+ if (!command.tlvid || errno || *end != '\0' ||
|
|
|
89f6b3 |
+ end == optarg)
|
|
|
89f6b3 |
+ command.tlvid = lookup_tlvid(optarg);
|
|
|
89f6b3 |
+ if (command.tlvid == INVALID_TLVID) {
|
|
|
89f6b3 |
+ printf("\nInvalid TLV identifier: %s\n",
|
|
|
89f6b3 |
+ optarg);
|
|
|
89f6b3 |
+ return -1;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case 'p':
|
|
|
89f6b3 |
+ command.cmd = cmd_ping;
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case 'q':
|
|
|
89f6b3 |
+ command.cmd = cmd_quit;
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case 't':
|
|
|
89f6b3 |
+ command.cmd = cmd_gettlv;
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case 'T':
|
|
|
89f6b3 |
+ command.cmd = cmd_settlv;
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case 'c':
|
|
|
89f6b3 |
+ command.ops |= op_config;
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case 'n':
|
|
|
89f6b3 |
+ command.ops |= op_neighbor;
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case 'h':
|
|
|
89f6b3 |
+ command.cmd = cmd_help;
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case 'r':
|
|
|
89f6b3 |
+ if (newraw) {
|
|
|
89f6b3 |
+ usage();
|
|
|
89f6b3 |
+ return -1;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ newraw = SHOW_RAW;
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case 'R':
|
|
|
89f6b3 |
+ if (newraw) {
|
|
|
89f6b3 |
+ usage();
|
|
|
89f6b3 |
+ return -1;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ newraw = (SHOW_RAW | SHOW_RAW_ONLY);
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ case 'v':
|
|
|
89f6b3 |
+ command.cmd = cmd_version;
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ default:
|
|
|
89f6b3 |
+ usage();
|
|
|
89f6b3 |
+ ret = -1;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ /* if no command was supplied via an option flag, then
|
|
|
89f6b3 |
+ * the first remaining argument should be the command.
|
|
|
89f6b3 |
+ */
|
|
|
89f6b3 |
+ count = 0;
|
|
|
89f6b3 |
+ if (command.cmd == cmd_nop && optind < argc) {
|
|
|
89f6b3 |
+ cmd = cli_commands;
|
|
|
89f6b3 |
+ while (cmd->cmdcode != cmd_nop) {
|
|
|
89f6b3 |
+ if (strncasecmp(cmd->cmdstr, argv[optind],
|
|
|
89f6b3 |
+ strlen(argv[optind])) == 0) {
|
|
|
89f6b3 |
+ match = cmd;
|
|
|
89f6b3 |
+ command.cmd = match->cmdcode;
|
|
|
89f6b3 |
+ count++;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ cmd++;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (count > 1) {
|
|
|
89f6b3 |
+ printf("Ambiguous command '%s'; possible commands:",
|
|
|
89f6b3 |
+ argv[optind]);
|
|
|
89f6b3 |
+ cmd = cli_commands;
|
|
|
89f6b3 |
+ while (cmd->cmdstr) {
|
|
|
89f6b3 |
+ if (strncasecmp(cmd->cmdstr, argv[optind],
|
|
|
89f6b3 |
+ strlen(argv[optind])) == 0)
|
|
|
89f6b3 |
+ printf(" %s", cmd->cmdstr);
|
|
|
89f6b3 |
+ cmd++;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ printf("\n");
|
|
|
89f6b3 |
+ ret = -1;
|
|
|
89f6b3 |
+ } else {
|
|
|
89f6b3 |
+ if (!match) {
|
|
|
89f6b3 |
+ cmd = cli_commands;
|
|
|
89f6b3 |
+ while (cmd->cmdcode != command.cmd)
|
|
|
89f6b3 |
+ cmd++;
|
|
|
89f6b3 |
+ match = cmd;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ numargs = argc-optind - count;
|
|
|
89f6b3 |
+ if (numargs)
|
|
|
89f6b3 |
+ argptr = &argv[argc-numargs];
|
|
|
89f6b3 |
+ ret = match->handler(clif, numargs, argptr, &command, newraw);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ return ret;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void cli_recv_pending(struct clif *clif, int in_read)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ int first = 1;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (clif == NULL)
|
|
|
89f6b3 |
+ return;
|
|
|
89f6b3 |
+ while (clif_pending(clif)) {
|
|
|
89f6b3 |
+ char buf[256];
|
|
|
89f6b3 |
+ size_t len = sizeof(buf) - 1;
|
|
|
89f6b3 |
+ if (clif_recv(clif, buf, &len) == 0) {
|
|
|
89f6b3 |
+ buf[len] = '\0';
|
|
|
89f6b3 |
+ if (in_read && first)
|
|
|
89f6b3 |
+ printf("\n");
|
|
|
89f6b3 |
+ first = 0;
|
|
|
89f6b3 |
+ cli_msg_cb(buf, len);
|
|
|
89f6b3 |
+ } else {
|
|
|
89f6b3 |
+ printf("Could not read pending message.\n");
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static char *do_readline(const char *prompt)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ size_t size = 0;
|
|
|
89f6b3 |
+ ssize_t rc;
|
|
|
89f6b3 |
+ char *line = NULL;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ fputs(prompt, stdout);
|
|
|
89f6b3 |
+ fflush(stdout);
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ rc = getline(&line, &size, stdin);
|
|
|
89f6b3 |
+ if (rc <= 0)
|
|
|
89f6b3 |
+ return NULL;
|
|
|
89f6b3 |
+ if (line[rc - 1] == '\n')
|
|
|
89f6b3 |
+ line[rc - 1] = 0;
|
|
|
89f6b3 |
+ return line;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void cli_interactive(void)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ const int max_args = 20;
|
|
|
89f6b3 |
+ char *cmd, *argv[max_args], *pos;
|
|
|
89f6b3 |
+ int argc;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ setlinebuf(stdout);
|
|
|
89f6b3 |
+ printf("\nInteractive mode\n\n");
|
|
|
89f6b3 |
+ do {
|
|
|
89f6b3 |
+ cli_recv_pending(clif_conn, 0);
|
|
|
89f6b3 |
+ alarm(1);
|
|
|
89f6b3 |
+ cmd = do_readline("> ");
|
|
|
89f6b3 |
+ alarm(0);
|
|
|
89f6b3 |
+ if (!cmd)
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ argc = 1;
|
|
|
89f6b3 |
+ pos = cmd;
|
|
|
89f6b3 |
+ for (;;) {
|
|
|
89f6b3 |
+ while (*pos == ' ')
|
|
|
89f6b3 |
+ pos++;
|
|
|
89f6b3 |
+ if (*pos == '\0')
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ argv[argc] = pos;
|
|
|
89f6b3 |
+ argc++;
|
|
|
89f6b3 |
+ if (argc == max_args)
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ while (*pos != '\0' && *pos != ' ')
|
|
|
89f6b3 |
+ pos++;
|
|
|
89f6b3 |
+ if (*pos == ' ')
|
|
|
89f6b3 |
+ *pos++ = '\0';
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ if (argc) {
|
|
|
89f6b3 |
+ optind = 0;
|
|
|
89f6b3 |
+ request(clif_conn, argc, argv);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ free(cmd);
|
|
|
89f6b3 |
+ } while (!cli_quit);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void cli_terminate(UNUSED int sig)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ cli_close_connection();
|
|
|
89f6b3 |
+ exit(0);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+static void cli_alarm(UNUSED int sig)
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ if (clif_conn && _clif_command(clif_conn, "P", SHOW_NO_OUTPUT)) {
|
|
|
89f6b3 |
+ printf("Connection to lldpad lost - trying to reconnect\n");
|
|
|
89f6b3 |
+ cli_close_connection();
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ if (!clif_conn) {
|
|
|
89f6b3 |
+ clif_conn = clif_open();
|
|
|
89f6b3 |
+ if (clif_conn) {
|
|
|
89f6b3 |
+ char attach_str[9] = "";
|
|
|
89f6b3 |
+ u32 mod_id = LLDP_MOD_VDP22;
|
|
|
89f6b3 |
+ bin2hexstr((u8 *)&mod_id, 4, attach_str, 8);
|
|
|
89f6b3 |
+ printf("Connection to lldpad re-established\n");
|
|
|
89f6b3 |
+ if (clif_attach(clif_conn, attach_str) == 0)
|
|
|
89f6b3 |
+ cli_attached = 1;
|
|
|
89f6b3 |
+ else
|
|
|
89f6b3 |
+ printf("Warning: Failed to attach to lldpad.\n");
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ if (clif_conn)
|
|
|
89f6b3 |
+ cli_recv_pending(clif_conn, 1);
|
|
|
89f6b3 |
+ alarm(1);
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+int main(int argc, char *argv[])
|
|
|
89f6b3 |
+{
|
|
|
89f6b3 |
+ int interactive = 1;
|
|
|
89f6b3 |
+ int warning_displayed = 0;
|
|
|
89f6b3 |
+ int ret = 0;
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (argc > 1)
|
|
|
89f6b3 |
+ interactive = 0;
|
|
|
89f6b3 |
+ if (interactive)
|
|
|
89f6b3 |
+ printf("%s\n\n%s\n\n", cli_version, cli_license);
|
|
|
89f6b3 |
+ for (;;) {
|
|
|
89f6b3 |
+ clif_conn = clif_open();
|
|
|
89f6b3 |
+ if (clif_conn) {
|
|
|
89f6b3 |
+ if (warning_displayed)
|
|
|
89f6b3 |
+ printf("Connection established.\n");
|
|
|
89f6b3 |
+ break;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (!interactive) {
|
|
|
89f6b3 |
+ perror("Failed to connect to lldpad - clif_open");
|
|
|
89f6b3 |
+ return -1;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (!warning_displayed) {
|
|
|
89f6b3 |
+ printf("Could not connect to lldpad - re-trying\n");
|
|
|
89f6b3 |
+ warning_displayed = 1;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ sleep(1);
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ init_modules();
|
|
|
89f6b3 |
+ signal(SIGINT, cli_terminate);
|
|
|
89f6b3 |
+ signal(SIGTERM, cli_terminate);
|
|
|
89f6b3 |
+ signal(SIGALRM, cli_alarm);
|
|
|
89f6b3 |
+
|
|
|
89f6b3 |
+ if (interactive) {
|
|
|
89f6b3 |
+ char attach_str[9] = "";
|
|
|
89f6b3 |
+ u32 mod_id = LLDP_MOD_VDP22;
|
|
|
89f6b3 |
+ bin2hexstr((u8 *)&mod_id, 4, attach_str, 8);
|
|
|
89f6b3 |
+ if (clif_attach(clif_conn, attach_str) == 0)
|
|
|
89f6b3 |
+ cli_attached = 1;
|
|
|
89f6b3 |
+ else
|
|
|
89f6b3 |
+ printf("Warning: Failed to attach to lldpad.\n");
|
|
|
89f6b3 |
+ cli_interactive();
|
|
|
89f6b3 |
+ } else {
|
|
|
89f6b3 |
+ ret = request(clif_conn, argc, &argv[0]);
|
|
|
89f6b3 |
+ ret = !!ret;
|
|
|
89f6b3 |
+ }
|
|
|
89f6b3 |
+ cli_close_connection();
|
|
|
89f6b3 |
+ deinit_modules();
|
|
|
89f6b3 |
+ return ret;
|
|
|
89f6b3 |
+}
|
|
|
89f6b3 |
--
|
|
|
89f6b3 |
2.1.0
|
|
|
89f6b3 |
|