Merge branch 'net-next'
This commit is contained in:
commit
01e5409371
|
|
@ -1,6 +1,5 @@
|
|||
static-syms.h
|
||||
config.*
|
||||
Config
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
|
|
|||
8
Makefile
8
Makefile
|
|
@ -54,12 +54,12 @@ SUBDIRS=lib ip tc bridge misc netem genl tipc devlink rdma man
|
|||
LIBNETLINK=../lib/libnetlink.a ../lib/libutil.a
|
||||
LDLIBS += $(LIBNETLINK)
|
||||
|
||||
all: Config
|
||||
all: config.mk
|
||||
@set -e; \
|
||||
for i in $(SUBDIRS); \
|
||||
do echo; echo $$i; $(MAKE) $(MFLAGS) -C $$i; done
|
||||
|
||||
Config:
|
||||
config.mk:
|
||||
sh configure $(KERNEL_INCLUDE)
|
||||
|
||||
install: all
|
||||
|
|
@ -88,9 +88,9 @@ clean:
|
|||
do $(MAKE) $(MFLAGS) -C $$i clean; done
|
||||
|
||||
clobber:
|
||||
touch Config
|
||||
touch config.mk
|
||||
$(MAKE) $(MFLAGS) clean
|
||||
rm -f Config cscope.*
|
||||
rm -f config.mk cscope.*
|
||||
|
||||
distclean: clobber
|
||||
|
||||
|
|
|
|||
5
README
5
README
|
|
@ -21,8 +21,9 @@ database routines. Often this is in the db-devel package.
|
|||
|
||||
2. make
|
||||
|
||||
The makefile will automatically build a Config file which
|
||||
contains whether or not ATM is available, etc.
|
||||
The makefile will automatically build a config.mk file which
|
||||
contains definitions of libraries that may or may not be available
|
||||
on the system such as: ATM, ELF, MNL, and SELINUX.
|
||||
|
||||
3. To make documentation, cd to doc/ directory , then
|
||||
look at start of Makefile and set correct values for
|
||||
|
|
|
|||
|
|
@ -1,15 +1,6 @@
|
|||
BROBJ = bridge.o fdb.o monitor.o link.o mdb.o vlan.o
|
||||
|
||||
include ../Config
|
||||
|
||||
ifeq ($(IP_CONFIG_SETNS),y)
|
||||
CFLAGS += -DHAVE_SETNS
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_MNL),y)
|
||||
CFLAGS += -DHAVE_LIBMNL $(shell $(PKG_CONFIG) libmnl --cflags)
|
||||
LDLIBS += $(shell $(PKG_CONFIG) libmnl --libs)
|
||||
endif
|
||||
include ../config.mk
|
||||
|
||||
all: bridge
|
||||
|
||||
|
|
|
|||
218
bridge/mdb.c
218
bridge/mdb.c
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/if_ether.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <json_writer.h>
|
||||
|
||||
#include "libnetlink.h"
|
||||
#include "br_common.h"
|
||||
|
|
@ -25,6 +26,9 @@
|
|||
#endif
|
||||
|
||||
static unsigned int filter_index, filter_vlan;
|
||||
json_writer_t *jw_global;
|
||||
static bool print_mdb_entries = true;
|
||||
static bool print_mdb_router = true;
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
|
|
@ -49,13 +53,26 @@ static void __print_router_port_stats(FILE *f, struct rtattr *pattr)
|
|||
if (tb[MDBA_ROUTER_PATTR_TIMER]) {
|
||||
__jiffies_to_tv(&tv,
|
||||
rta_getattr_u32(tb[MDBA_ROUTER_PATTR_TIMER]));
|
||||
fprintf(f, " %4i.%.2i",
|
||||
(int)tv.tv_sec, (int)tv.tv_usec/10000);
|
||||
if (jw_global) {
|
||||
char formatted_time[9];
|
||||
|
||||
snprintf(formatted_time, sizeof(formatted_time),
|
||||
"%4i.%.2i", (int)tv.tv_sec,
|
||||
(int)tv.tv_usec/10000);
|
||||
jsonw_string_field(jw_global, "timer", formatted_time);
|
||||
} else {
|
||||
fprintf(f, " %4i.%.2i",
|
||||
(int)tv.tv_sec, (int)tv.tv_usec/10000);
|
||||
}
|
||||
}
|
||||
if (tb[MDBA_ROUTER_PATTR_TYPE]) {
|
||||
type = rta_getattr_u8(tb[MDBA_ROUTER_PATTR_TYPE]);
|
||||
fprintf(f, " %s",
|
||||
is_temp_mcast_rtr(type) ? "temp" : "permanent");
|
||||
if (jw_global)
|
||||
jsonw_string_field(jw_global, "type",
|
||||
is_temp_mcast_rtr(type) ? "temp" : "permanent");
|
||||
else
|
||||
fprintf(f, " %s",
|
||||
is_temp_mcast_rtr(type) ? "temp" : "permanent");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,24 +82,50 @@ static void br_print_router_ports(FILE *f, struct rtattr *attr, __u32 brifidx)
|
|||
struct rtattr *i;
|
||||
int rem;
|
||||
|
||||
if (!show_stats)
|
||||
fprintf(f, "router ports on %s: ", ll_index_to_name(brifidx));
|
||||
|
||||
rem = RTA_PAYLOAD(attr);
|
||||
for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
||||
port_ifindex = RTA_DATA(i);
|
||||
if (show_stats) {
|
||||
fprintf(f, "router ports on %s: %s",
|
||||
ll_index_to_name(brifidx),
|
||||
ll_index_to_name(*port_ifindex));
|
||||
__print_router_port_stats(f, i);
|
||||
fprintf(f, "\n");
|
||||
} else {
|
||||
fprintf(f, "%s ", ll_index_to_name(*port_ifindex));
|
||||
if (jw_global) {
|
||||
jsonw_name(jw_global, ll_index_to_name(brifidx));
|
||||
jsonw_start_array(jw_global);
|
||||
for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
||||
port_ifindex = RTA_DATA(i);
|
||||
jsonw_start_object(jw_global);
|
||||
jsonw_string_field(jw_global,
|
||||
"port",
|
||||
ll_index_to_name(*port_ifindex));
|
||||
if (show_stats)
|
||||
__print_router_port_stats(f, i);
|
||||
jsonw_end_object(jw_global);
|
||||
}
|
||||
jsonw_end_array(jw_global);
|
||||
} else {
|
||||
if (!show_stats)
|
||||
fprintf(f, "router ports on %s: ",
|
||||
ll_index_to_name(brifidx));
|
||||
for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
||||
port_ifindex = RTA_DATA(i);
|
||||
if (show_stats) {
|
||||
fprintf(f, "router ports on %s: %s",
|
||||
ll_index_to_name(brifidx),
|
||||
ll_index_to_name(*port_ifindex));
|
||||
__print_router_port_stats(f, i);
|
||||
fprintf(f, "\n");
|
||||
} else{
|
||||
fprintf(f, "%s ",
|
||||
ll_index_to_name(*port_ifindex));
|
||||
}
|
||||
}
|
||||
if (!show_stats)
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
if (!show_stats)
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
static void start_json_mdb_flags_array(bool *mdb_flags)
|
||||
{
|
||||
if (*mdb_flags)
|
||||
return;
|
||||
jsonw_name(jw_global, "flags");
|
||||
jsonw_start_array(jw_global);
|
||||
*mdb_flags = true;
|
||||
}
|
||||
|
||||
static void print_mdb_entry(FILE *f, int ifindex, struct br_mdb_entry *e,
|
||||
|
|
@ -91,28 +134,70 @@ static void print_mdb_entry(FILE *f, int ifindex, struct br_mdb_entry *e,
|
|||
SPRINT_BUF(abuf);
|
||||
const void *src;
|
||||
int af;
|
||||
bool mdb_flags = false;
|
||||
|
||||
if (filter_vlan && e->vid != filter_vlan)
|
||||
return;
|
||||
af = e->addr.proto == htons(ETH_P_IP) ? AF_INET : AF_INET6;
|
||||
src = af == AF_INET ? (const void *)&e->addr.u.ip4 :
|
||||
(const void *)&e->addr.u.ip6;
|
||||
if (n->nlmsg_type == RTM_DELMDB)
|
||||
fprintf(f, "Deleted ");
|
||||
fprintf(f, "dev %s port %s grp %s %s %s", ll_index_to_name(ifindex),
|
||||
ll_index_to_name(e->ifindex),
|
||||
inet_ntop(af, src, abuf, sizeof(abuf)),
|
||||
(e->state & MDB_PERMANENT) ? "permanent" : "temp",
|
||||
(e->flags & MDB_FLAGS_OFFLOAD) ? "offload" : "");
|
||||
if (e->vid)
|
||||
fprintf(f, " vid %hu", e->vid);
|
||||
if (jw_global)
|
||||
jsonw_start_object(jw_global);
|
||||
if (n->nlmsg_type == RTM_DELMDB) {
|
||||
if (jw_global)
|
||||
jsonw_string_field(jw_global, "opCode", "deleted");
|
||||
else
|
||||
fprintf(f, "Deleted ");
|
||||
}
|
||||
if (jw_global) {
|
||||
jsonw_string_field(jw_global, "dev", ll_index_to_name(ifindex));
|
||||
jsonw_string_field(jw_global,
|
||||
"port",
|
||||
ll_index_to_name(e->ifindex));
|
||||
jsonw_string_field(jw_global, "grp", inet_ntop(af, src,
|
||||
abuf, sizeof(abuf)));
|
||||
jsonw_string_field(jw_global, "state",
|
||||
(e->state & MDB_PERMANENT) ? "permanent" : "temp");
|
||||
if (e->flags & MDB_FLAGS_OFFLOAD) {
|
||||
start_json_mdb_flags_array(&mdb_flags);
|
||||
jsonw_string(jw_global, "offload");
|
||||
}
|
||||
if (mdb_flags)
|
||||
jsonw_end_array(jw_global);
|
||||
} else{
|
||||
fprintf(f, "dev %s port %s grp %s %s %s",
|
||||
ll_index_to_name(ifindex),
|
||||
ll_index_to_name(e->ifindex),
|
||||
inet_ntop(af, src, abuf, sizeof(abuf)),
|
||||
(e->state & MDB_PERMANENT) ? "permanent" : "temp",
|
||||
(e->flags & MDB_FLAGS_OFFLOAD) ? "offload" : "");
|
||||
}
|
||||
if (e->vid) {
|
||||
if (jw_global)
|
||||
jsonw_uint_field(jw_global, "vid", e->vid);
|
||||
else
|
||||
fprintf(f, " vid %hu", e->vid);
|
||||
}
|
||||
if (show_stats && tb && tb[MDBA_MDB_EATTR_TIMER]) {
|
||||
struct timeval tv;
|
||||
|
||||
__jiffies_to_tv(&tv, rta_getattr_u32(tb[MDBA_MDB_EATTR_TIMER]));
|
||||
fprintf(f, "%4i.%.2i", (int)tv.tv_sec, (int)tv.tv_usec/10000);
|
||||
if (jw_global) {
|
||||
char formatted_time[9];
|
||||
|
||||
snprintf(formatted_time, sizeof(formatted_time),
|
||||
"%4i.%.2i", (int)tv.tv_sec,
|
||||
(int)tv.tv_usec/10000);
|
||||
jsonw_string_field(jw_global, "timer", formatted_time);
|
||||
} else {
|
||||
fprintf(f, "%4i.%.2i", (int)tv.tv_sec,
|
||||
(int)tv.tv_usec/10000);
|
||||
}
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
if (jw_global)
|
||||
jsonw_end_object(jw_global);
|
||||
else
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
static void br_print_mdb_entry(FILE *f, int ifindex, struct rtattr *attr,
|
||||
|
|
@ -157,14 +242,14 @@ int print_mdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
|||
|
||||
parse_rtattr(tb, MDBA_MAX, MDBA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
|
||||
|
||||
if (tb[MDBA_MDB]) {
|
||||
if (tb[MDBA_MDB] && print_mdb_entries) {
|
||||
int rem = RTA_PAYLOAD(tb[MDBA_MDB]);
|
||||
|
||||
for (i = RTA_DATA(tb[MDBA_MDB]); RTA_OK(i, rem); i = RTA_NEXT(i, rem))
|
||||
br_print_mdb_entry(fp, r->ifindex, i, n);
|
||||
}
|
||||
|
||||
if (tb[MDBA_ROUTER]) {
|
||||
if (tb[MDBA_ROUTER] && print_mdb_router) {
|
||||
if (n->nlmsg_type == RTM_GETMDB) {
|
||||
if (show_details)
|
||||
br_print_router_ports(fp, tb[MDBA_ROUTER],
|
||||
|
|
@ -174,15 +259,33 @@ int print_mdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
|||
|
||||
i = RTA_DATA(tb[MDBA_ROUTER]);
|
||||
port_ifindex = RTA_DATA(i);
|
||||
if (n->nlmsg_type == RTM_DELMDB)
|
||||
fprintf(fp, "Deleted ");
|
||||
fprintf(fp, "router port dev %s master %s\n",
|
||||
ll_index_to_name(*port_ifindex),
|
||||
ll_index_to_name(r->ifindex));
|
||||
if (n->nlmsg_type == RTM_DELMDB) {
|
||||
if (jw_global)
|
||||
jsonw_string_field(jw_global,
|
||||
"opCode",
|
||||
"deleted");
|
||||
else
|
||||
fprintf(fp, "Deleted ");
|
||||
}
|
||||
if (jw_global) {
|
||||
jsonw_name(jw_global,
|
||||
ll_index_to_name(r->ifindex));
|
||||
jsonw_start_array(jw_global);
|
||||
jsonw_start_object(jw_global);
|
||||
jsonw_string_field(jw_global, "port",
|
||||
ll_index_to_name(*port_ifindex));
|
||||
jsonw_end_object(jw_global);
|
||||
jsonw_end_array(jw_global);
|
||||
} else {
|
||||
fprintf(fp, "router port dev %s master %s\n",
|
||||
ll_index_to_name(*port_ifindex),
|
||||
ll_index_to_name(r->ifindex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fflush(fp);
|
||||
if (!jw_global)
|
||||
fflush(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -215,15 +318,54 @@ static int mdb_show(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
/* get mdb entries*/
|
||||
if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETMDB) < 0) {
|
||||
perror("Cannot send dump request");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!json_output) {
|
||||
/* Normal output */
|
||||
if (rtnl_dump_filter(&rth, print_mdb, stdout) < 0) {
|
||||
fprintf(stderr, "Dump terminated\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Json output */
|
||||
jw_global = jsonw_new(stdout);
|
||||
jsonw_pretty(jw_global, 1);
|
||||
jsonw_start_object(jw_global);
|
||||
jsonw_name(jw_global, "mdb");
|
||||
jsonw_start_array(jw_global);
|
||||
|
||||
/* print mdb entries */
|
||||
print_mdb_entries = true;
|
||||
print_mdb_router = false;
|
||||
if (rtnl_dump_filter(&rth, print_mdb, stdout) < 0) {
|
||||
fprintf(stderr, "Dump terminated\n");
|
||||
return -1;
|
||||
}
|
||||
jsonw_end_array(jw_global);
|
||||
|
||||
/* get router ports */
|
||||
if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETMDB) < 0) {
|
||||
perror("Cannot send dump request");
|
||||
return -1;
|
||||
}
|
||||
jsonw_name(jw_global, "router");
|
||||
jsonw_start_object(jw_global);
|
||||
|
||||
/* print router ports */
|
||||
print_mdb_entries = false;
|
||||
print_mdb_router = true;
|
||||
if (rtnl_dump_filter(&rth, print_mdb, stdout) < 0) {
|
||||
fprintf(stderr, "Dump terminated\n");
|
||||
return -1;
|
||||
}
|
||||
jsonw_end_object(jw_global);
|
||||
jsonw_end_object(jw_global);
|
||||
jsonw_destroy(&jw_global);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
#
|
||||
INCLUDE=${1:-"$PWD/include"}
|
||||
|
||||
# Output file which is input to Makefile
|
||||
CONFIG=config.mk
|
||||
|
||||
# Make a temp directory in build tree.
|
||||
TMPDIR=$(mktemp -d config.XXXXXX)
|
||||
trap 'status=$?; rm -rf $TMPDIR; exit $status' EXIT HUP INT QUIT TERM
|
||||
|
|
@ -10,7 +13,7 @@ trap 'status=$?; rm -rf $TMPDIR; exit $status' EXIT HUP INT QUIT TERM
|
|||
check_prog()
|
||||
{
|
||||
echo -n "$2"
|
||||
command -v $1 >/dev/null 2>&1 && (echo "$3:=y" >> Config; echo "yes") || (echo "no"; return 1)
|
||||
command -v $1 >/dev/null 2>&1 && (echo "$3:=y" >> $CONFIG; echo "yes") || (echo "no"; return 1)
|
||||
}
|
||||
|
||||
check_docs()
|
||||
|
|
@ -30,9 +33,9 @@ check_toolchain()
|
|||
: ${PKG_CONFIG:=pkg-config}
|
||||
: ${AR=ar}
|
||||
: ${CC=gcc}
|
||||
echo "PKG_CONFIG:=${PKG_CONFIG}" >>Config
|
||||
echo "AR:=${AR}" >>Config
|
||||
echo "CC:=${CC}" >>Config
|
||||
echo "PKG_CONFIG:=${PKG_CONFIG}" >>$CONFIG
|
||||
echo "AR:=${AR}" >>$CONFIG
|
||||
echo "CC:=${CC}" >>$CONFIG
|
||||
}
|
||||
|
||||
check_atm()
|
||||
|
|
@ -49,7 +52,7 @@ EOF
|
|||
$CC -I$INCLUDE -o $TMPDIR/atmtest $TMPDIR/atmtest.c -latm >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
echo "TC_CONFIG_ATM:=y" >>Config
|
||||
echo "TC_CONFIG_ATM:=y" >>$CONFIG
|
||||
echo yes
|
||||
else
|
||||
echo no
|
||||
|
|
@ -61,7 +64,7 @@ check_xtables()
|
|||
{
|
||||
if ! ${PKG_CONFIG} xtables --exists
|
||||
then
|
||||
echo "TC_CONFIG_NO_XT:=y" >>Config
|
||||
echo "TC_CONFIG_NO_XT:=y" >>$CONFIG
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +93,7 @@ EOF
|
|||
if $CC -I$INCLUDE $IPTC -o $TMPDIR/ipttest $TMPDIR/ipttest.c $IPTL \
|
||||
$(${PKG_CONFIG} xtables --cflags --libs) -ldl >/dev/null 2>&1
|
||||
then
|
||||
echo "TC_CONFIG_XT:=y" >>Config
|
||||
echo "TC_CONFIG_XT:=y" >>$CONFIG
|
||||
echo "using xtables"
|
||||
fi
|
||||
rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest
|
||||
|
|
@ -99,7 +102,7 @@ EOF
|
|||
check_xt_old()
|
||||
{
|
||||
# bail if previous XT checks has already succeded.
|
||||
if grep -q TC_CONFIG_XT Config
|
||||
if grep -q TC_CONFIG_XT $CONFIG
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
|
@ -129,7 +132,7 @@ EOF
|
|||
$CC -I$INCLUDE $IPTC -o $TMPDIR/ipttest $TMPDIR/ipttest.c $IPTL -ldl >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
echo "TC_CONFIG_XT_OLD:=y" >>Config
|
||||
echo "TC_CONFIG_XT_OLD:=y" >>$CONFIG
|
||||
echo "using old xtables (no need for xt-internal.h)"
|
||||
fi
|
||||
rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest
|
||||
|
|
@ -138,7 +141,7 @@ EOF
|
|||
check_xt_old_internal_h()
|
||||
{
|
||||
# bail if previous XT checks has already succeded.
|
||||
if grep -q TC_CONFIG_XT Config
|
||||
if grep -q TC_CONFIG_XT $CONFIG
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
|
@ -170,14 +173,14 @@ EOF
|
|||
if [ $? -eq 0 ]
|
||||
then
|
||||
echo "using old xtables with xt-internal.h"
|
||||
echo "TC_CONFIG_XT_OLD_H:=y" >>Config
|
||||
echo "TC_CONFIG_XT_OLD_H:=y" >>$CONFIG
|
||||
fi
|
||||
rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest
|
||||
}
|
||||
|
||||
check_ipt()
|
||||
{
|
||||
if ! grep TC_CONFIG_XT Config > /dev/null
|
||||
if ! grep TC_CONFIG_XT $CONFIG > /dev/null
|
||||
then
|
||||
echo "using iptables"
|
||||
fi
|
||||
|
|
@ -188,7 +191,7 @@ check_ipt_lib_dir()
|
|||
IPT_LIB_DIR=$(${PKG_CONFIG} --variable=xtlibdir xtables)
|
||||
if [ -n "$IPT_LIB_DIR" ]; then
|
||||
echo $IPT_LIB_DIR
|
||||
echo "IPT_LIB_DIR:=$IPT_LIB_DIR" >> Config
|
||||
echo "IPT_LIB_DIR:=$IPT_LIB_DIR" >> $CONFIG
|
||||
return
|
||||
fi
|
||||
|
||||
|
|
@ -197,7 +200,7 @@ check_ipt_lib_dir()
|
|||
for file in $dir/{xtables,iptables}/lib*t_*so ; do
|
||||
if [ -f $file ]; then
|
||||
echo ${file%/*}
|
||||
echo "IPT_LIB_DIR:=${file%/*}" >> Config
|
||||
echo "IPT_LIB_DIR:=${file%/*}" >> $CONFIG
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
|
@ -218,8 +221,9 @@ EOF
|
|||
$CC -I$INCLUDE -o $TMPDIR/setnstest $TMPDIR/setnstest.c >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
echo "IP_CONFIG_SETNS:=y" >>Config
|
||||
echo "IP_CONFIG_SETNS:=y" >>$CONFIG
|
||||
echo "yes"
|
||||
echo "CFLAGS += -DHAVE_SETNS" >>$CONFIG
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
|
|
@ -249,7 +253,7 @@ EOF
|
|||
|
||||
if $CC -I$INCLUDE -o $TMPDIR/ipsettest $TMPDIR/ipsettest.c >/dev/null 2>&1
|
||||
then
|
||||
echo "TC_CONFIG_IPSET:=y" >>Config
|
||||
echo "TC_CONFIG_IPSET:=y" >>$CONFIG
|
||||
echo "yes"
|
||||
else
|
||||
echo "no"
|
||||
|
|
@ -259,25 +263,16 @@ EOF
|
|||
|
||||
check_elf()
|
||||
{
|
||||
cat >$TMPDIR/elftest.c <<EOF
|
||||
#include <libelf.h>
|
||||
#include <gelf.h>
|
||||
int main(void)
|
||||
{
|
||||
Elf_Scn *scn __attribute__((__unused__));
|
||||
GElf_Shdr shdr __attribute__((__unused__));;
|
||||
return elf_version(EV_CURRENT);
|
||||
}
|
||||
EOF
|
||||
|
||||
if $CC -I$INCLUDE -o $TMPDIR/elftest $TMPDIR/elftest.c -lelf >/dev/null 2>&1
|
||||
if ${PKG_CONFIG} libelf --exists
|
||||
then
|
||||
echo "HAVE_ELF:=y" >>Config
|
||||
echo "HAVE_ELF:=y" >>$CONFIG
|
||||
echo "yes"
|
||||
|
||||
echo 'CFLAGS += -DHAVE_ELF' `${PKG_CONFIG} libelf --cflags` >> $CONFIG
|
||||
echo 'LDLIBS += ' `${PKG_CONFIG} libelf --libs` >>$CONFIG
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
rm -f $TMPDIR/elftest.c $TMPDIR/elftest
|
||||
}
|
||||
|
||||
check_selinux()
|
||||
|
|
@ -285,8 +280,11 @@ check_selinux()
|
|||
{
|
||||
if ${PKG_CONFIG} libselinux --exists
|
||||
then
|
||||
echo "HAVE_SELINUX:=y" >>Config
|
||||
echo "HAVE_SELINUX:=y" >>$CONFIG
|
||||
echo "yes"
|
||||
|
||||
echo 'LDLIBS +=' `${PKG_CONFIG} --libs libselinux` >>$CONFIG
|
||||
echo 'CFLAGS += -DHAVE_SELINUX' `${PKG_CONFIG} --cflags libselinux` >>$CONFIG
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
|
|
@ -296,8 +294,11 @@ check_mnl()
|
|||
{
|
||||
if ${PKG_CONFIG} libmnl --exists
|
||||
then
|
||||
echo "HAVE_MNL:=y" >>Config
|
||||
echo "HAVE_MNL:=y" >>$CONFIG
|
||||
echo "yes"
|
||||
|
||||
echo 'CFLAGS += -DHAVE_LIBMNL' `${PKG_CONFIG} libmnl --cflags` >>$CONFIG
|
||||
echo 'LDLIBS +=' `${PKG_CONFIG} libmnl --libs` >> $CONFIG
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
|
|
@ -317,7 +318,7 @@ EOF
|
|||
$CC -I$INCLUDE -o $TMPDIR/dbtest $TMPDIR/dbtest.c -ldb >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
echo "HAVE_BERKELEY_DB:=y" >>Config
|
||||
echo "HAVE_BERKELEY_DB:=y" >>$CONFIG
|
||||
echo "yes"
|
||||
else
|
||||
echo "no"
|
||||
|
|
@ -351,8 +352,8 @@ endif
|
|||
EOF
|
||||
}
|
||||
|
||||
echo "# Generated config based on" $INCLUDE >Config
|
||||
quiet_config >> Config
|
||||
echo "# Generated config based on" $INCLUDE >$CONFIG
|
||||
quiet_config >> $CONFIG
|
||||
|
||||
check_toolchain
|
||||
|
||||
|
|
@ -362,7 +363,7 @@ echo -n " ATM "
|
|||
check_atm
|
||||
|
||||
check_xtables
|
||||
if ! grep -q TC_CONFIG_NO_XT Config
|
||||
if ! grep -q TC_CONFIG_NO_XT $CONFIG
|
||||
then
|
||||
echo -n " IPT "
|
||||
check_xt
|
||||
|
|
@ -375,7 +376,7 @@ then
|
|||
fi
|
||||
|
||||
echo
|
||||
if ! grep -q TC_CONFIG_NO_XT Config
|
||||
if ! grep -q TC_CONFIG_NO_XT $CONFIG
|
||||
then
|
||||
echo -n "iptables modules directory: "
|
||||
check_ipt_lib_dir
|
||||
|
|
@ -401,6 +402,6 @@ echo -n "docs:"
|
|||
check_docs
|
||||
echo
|
||||
|
||||
echo >> Config
|
||||
echo "%.o: %.c" >> Config
|
||||
echo ' $(QUIET_CC)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<' >> Config
|
||||
echo >> $CONFIG
|
||||
echo "%.o: %.c" >> $CONFIG
|
||||
echo ' $(QUIET_CC)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<' >> $CONFIG
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
include ../Config
|
||||
include ../config.mk
|
||||
|
||||
ifeq ($(HAVE_MNL),y)
|
||||
|
||||
DEVLINKOBJ = devlink.o mnlg.o
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
GENLOBJ=genl.o
|
||||
|
||||
include ../Config
|
||||
include ../config.mk
|
||||
SHARED_LIBS ?= y
|
||||
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
|
|
@ -17,11 +17,6 @@ LDFLAGS += -Wl,-export-dynamic
|
|||
LDLIBS += -lm -ldl
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_MNL),y)
|
||||
CFLAGS += -DHAVE_LIBMNL $(shell $(PKG_CONFIG) libmnl --cflags)
|
||||
LDLIBS += $(shell $(PKG_CONFIG) libmnl --libs)
|
||||
endif
|
||||
|
||||
all: genl
|
||||
|
||||
genl: $(GENLOBJ) $(LIBNETLINK) $(LIBUTIL) $(GENLLIB)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define __COLOR_H__ 1
|
||||
|
||||
enum color_attr {
|
||||
COLOR_NONE,
|
||||
COLOR_IFNAME,
|
||||
COLOR_MAC,
|
||||
COLOR_INET,
|
||||
|
|
@ -12,6 +13,7 @@ enum color_attr {
|
|||
};
|
||||
|
||||
void enable_color(void);
|
||||
void check_if_color_enabled(void);
|
||||
void set_color_palette(void);
|
||||
int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...);
|
||||
enum color_attr ifa_family_color(__u8 ifa_family);
|
||||
|
|
|
|||
|
|
@ -33,20 +33,29 @@ void jsonw_pretty(json_writer_t *self, bool on);
|
|||
void jsonw_name(json_writer_t *self, const char *name);
|
||||
|
||||
/* Add value */
|
||||
void jsonw_printf(json_writer_t *self, const char *fmt, ...);
|
||||
void jsonw_string(json_writer_t *self, const char *value);
|
||||
void jsonw_bool(json_writer_t *self, bool value);
|
||||
void jsonw_float(json_writer_t *self, double number);
|
||||
void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num);
|
||||
void jsonw_uint(json_writer_t *self, uint64_t number);
|
||||
void jsonw_hu(json_writer_t *self, unsigned short number);
|
||||
void jsonw_int(json_writer_t *self, int64_t number);
|
||||
void jsonw_null(json_writer_t *self);
|
||||
void jsonw_lluint(json_writer_t *self, unsigned long long int num);
|
||||
|
||||
/* Useful Combinations of name and value */
|
||||
void jsonw_string_field(json_writer_t *self, const char *prop, const char *val);
|
||||
void jsonw_bool_field(json_writer_t *self, const char *prop, bool value);
|
||||
void jsonw_float_field(json_writer_t *self, const char *prop, double num);
|
||||
void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num);
|
||||
void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num);
|
||||
void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num);
|
||||
void jsonw_null_field(json_writer_t *self, const char *prop);
|
||||
void jsonw_lluint_field(json_writer_t *self, const char *prop,
|
||||
unsigned long long int num);
|
||||
void jsonw_float_field_fmt(json_writer_t *self, const char *prop,
|
||||
const char *fmt, double val);
|
||||
|
||||
/* Collections */
|
||||
void jsonw_start_object(json_writer_t *self);
|
||||
|
|
|
|||
|
|
@ -30,9 +30,14 @@
|
|||
#define BPF_FROM_LE BPF_TO_LE
|
||||
#define BPF_FROM_BE BPF_TO_BE
|
||||
|
||||
/* jmp encodings */
|
||||
#define BPF_JNE 0x50 /* jump != */
|
||||
#define BPF_JLT 0xa0 /* LT is unsigned, '<' */
|
||||
#define BPF_JLE 0xb0 /* LE is unsigned, '<=' */
|
||||
#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */
|
||||
#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */
|
||||
#define BPF_JSLT 0xc0 /* SLT is signed, '<' */
|
||||
#define BPF_JSLE 0xd0 /* SLE is signed, '<=' */
|
||||
#define BPF_CALL 0x80 /* function call */
|
||||
#define BPF_EXIT 0x90 /* function return */
|
||||
|
||||
|
|
@ -104,6 +109,8 @@ enum bpf_map_type {
|
|||
BPF_MAP_TYPE_LPM_TRIE,
|
||||
BPF_MAP_TYPE_ARRAY_OF_MAPS,
|
||||
BPF_MAP_TYPE_HASH_OF_MAPS,
|
||||
BPF_MAP_TYPE_DEVMAP,
|
||||
BPF_MAP_TYPE_SOCKMAP,
|
||||
};
|
||||
|
||||
enum bpf_prog_type {
|
||||
|
|
@ -121,6 +128,7 @@ enum bpf_prog_type {
|
|||
BPF_PROG_TYPE_LWT_OUT,
|
||||
BPF_PROG_TYPE_LWT_XMIT,
|
||||
BPF_PROG_TYPE_SOCK_OPS,
|
||||
BPF_PROG_TYPE_SK_SKB,
|
||||
};
|
||||
|
||||
enum bpf_attach_type {
|
||||
|
|
@ -128,6 +136,8 @@ enum bpf_attach_type {
|
|||
BPF_CGROUP_INET_EGRESS,
|
||||
BPF_CGROUP_INET_SOCK_CREATE,
|
||||
BPF_CGROUP_SOCK_OPS,
|
||||
BPF_SK_SKB_STREAM_PARSER,
|
||||
BPF_SK_SKB_STREAM_VERDICT,
|
||||
__MAX_BPF_ATTACH_TYPE
|
||||
};
|
||||
|
||||
|
|
@ -153,6 +163,7 @@ enum bpf_attach_type {
|
|||
#define BPF_NOEXIST 1 /* create new element if it didn't exist */
|
||||
#define BPF_EXIST 2 /* update existing element */
|
||||
|
||||
/* flags for BPF_MAP_CREATE command */
|
||||
#define BPF_F_NO_PREALLOC (1U << 0)
|
||||
/* Instead of having one common LRU list in the
|
||||
* BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list
|
||||
|
|
@ -161,6 +172,8 @@ enum bpf_attach_type {
|
|||
* across different LRU lists.
|
||||
*/
|
||||
#define BPF_F_NO_COMMON_LRU (1U << 1)
|
||||
/* Specify numa node during map creation */
|
||||
#define BPF_F_NUMA_NODE (1U << 2)
|
||||
|
||||
union bpf_attr {
|
||||
struct { /* anonymous struct used by BPF_MAP_CREATE command */
|
||||
|
|
@ -168,8 +181,13 @@ union bpf_attr {
|
|||
__u32 key_size; /* size of key in bytes */
|
||||
__u32 value_size; /* size of value in bytes */
|
||||
__u32 max_entries; /* max number of entries in a map */
|
||||
__u32 map_flags; /* prealloc or not */
|
||||
__u32 map_flags; /* BPF_MAP_CREATE related
|
||||
* flags defined above.
|
||||
*/
|
||||
__u32 inner_map_fd; /* fd pointing to the inner map */
|
||||
__u32 numa_node; /* numa node (effective only if
|
||||
* BPF_F_NUMA_NODE is set).
|
||||
*/
|
||||
};
|
||||
|
||||
struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
|
||||
|
|
@ -344,9 +362,20 @@ union bpf_attr {
|
|||
* int bpf_redirect(ifindex, flags)
|
||||
* redirect to another netdev
|
||||
* @ifindex: ifindex of the net device
|
||||
* @flags: bit 0 - if set, redirect to ingress instead of egress
|
||||
* other bits - reserved
|
||||
* Return: TC_ACT_REDIRECT
|
||||
* @flags:
|
||||
* cls_bpf:
|
||||
* bit 0 - if set, redirect to ingress instead of egress
|
||||
* other bits - reserved
|
||||
* xdp_bpf:
|
||||
* all bits - reserved
|
||||
* Return: cls_bpf: TC_ACT_REDIRECT on success or TC_ACT_SHOT on error
|
||||
* xdp_bfp: XDP_REDIRECT on success or XDP_ABORT on error
|
||||
* int bpf_redirect_map(map, key, flags)
|
||||
* redirect to endpoint in map
|
||||
* @map: pointer to dev map
|
||||
* @key: index in map to lookup
|
||||
* @flags: --
|
||||
* Return: XDP_REDIRECT on success or XDP_ABORT on error
|
||||
*
|
||||
* u32 bpf_get_route_realm(skb)
|
||||
* retrieve a dst's tclassid
|
||||
|
|
@ -539,6 +568,20 @@ union bpf_attr {
|
|||
* @mode: operation mode (enum bpf_adj_room_mode)
|
||||
* @flags: reserved for future use
|
||||
* Return: 0 on success or negative error code
|
||||
*
|
||||
* int bpf_sk_redirect_map(map, key, flags)
|
||||
* Redirect skb to a sock in map using key as a lookup key for the
|
||||
* sock in map.
|
||||
* @map: pointer to sockmap
|
||||
* @key: key to lookup sock in map
|
||||
* @flags: reserved for future use
|
||||
* Return: SK_REDIRECT
|
||||
*
|
||||
* int bpf_sock_map_update(skops, map, key, flags)
|
||||
* @skops: pointer to bpf_sock_ops
|
||||
* @map: pointer to sockmap to update
|
||||
* @key: key to insert/update sock in map
|
||||
* @flags: same flags as map update elem
|
||||
*/
|
||||
#define __BPF_FUNC_MAPPER(FN) \
|
||||
FN(unspec), \
|
||||
|
|
@ -591,7 +634,10 @@ union bpf_attr {
|
|||
FN(get_socket_uid), \
|
||||
FN(set_hash), \
|
||||
FN(setsockopt), \
|
||||
FN(skb_adjust_room),
|
||||
FN(skb_adjust_room), \
|
||||
FN(redirect_map), \
|
||||
FN(sk_redirect_map), \
|
||||
FN(sock_map_update), \
|
||||
|
||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||
* function eBPF program intends to call
|
||||
|
|
@ -668,6 +714,15 @@ struct __sk_buff {
|
|||
__u32 data;
|
||||
__u32 data_end;
|
||||
__u32 napi_id;
|
||||
|
||||
/* accessed by BPF_PROG_TYPE_sk_skb types */
|
||||
__u32 family;
|
||||
__u32 remote_ip4; /* Stored in network byte order */
|
||||
__u32 local_ip4; /* Stored in network byte order */
|
||||
__u32 remote_ip6[4]; /* Stored in network byte order */
|
||||
__u32 local_ip6[4]; /* Stored in network byte order */
|
||||
__u32 remote_port; /* Stored in network byte order */
|
||||
__u32 local_port; /* stored in host byte order */
|
||||
};
|
||||
|
||||
struct bpf_tunnel_key {
|
||||
|
|
@ -703,6 +758,8 @@ struct bpf_sock {
|
|||
__u32 family;
|
||||
__u32 type;
|
||||
__u32 protocol;
|
||||
__u32 mark;
|
||||
__u32 priority;
|
||||
};
|
||||
|
||||
#define XDP_PACKET_HEADROOM 256
|
||||
|
|
@ -717,6 +774,7 @@ enum xdp_action {
|
|||
XDP_DROP,
|
||||
XDP_PASS,
|
||||
XDP_TX,
|
||||
XDP_REDIRECT,
|
||||
};
|
||||
|
||||
/* user accessible metadata for XDP packet hook
|
||||
|
|
@ -727,6 +785,12 @@ struct xdp_md {
|
|||
__u32 data_end;
|
||||
};
|
||||
|
||||
enum sk_action {
|
||||
SK_ABORTED = 0,
|
||||
SK_DROP,
|
||||
SK_REDIRECT,
|
||||
};
|
||||
|
||||
#define BPF_TAG_SIZE 8
|
||||
|
||||
struct bpf_prog_info {
|
||||
|
|
|
|||
|
|
@ -226,4 +226,22 @@ enum devlink_dpipe_action_type {
|
|||
DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY,
|
||||
};
|
||||
|
||||
enum devlink_dpipe_field_ethernet_id {
|
||||
DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC,
|
||||
};
|
||||
|
||||
enum devlink_dpipe_field_ipv4_id {
|
||||
DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
|
||||
};
|
||||
|
||||
enum devlink_dpipe_field_ipv6_id {
|
||||
DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
|
||||
};
|
||||
|
||||
enum devlink_dpipe_header_id {
|
||||
DEVLINK_DPIPE_HEADER_ETHERNET,
|
||||
DEVLINK_DPIPE_HEADER_IPV4,
|
||||
DEVLINK_DPIPE_HEADER_IPV6,
|
||||
};
|
||||
|
||||
#endif /* _LINUX_DEVLINK_H_ */
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
#define ARPHRD_LAPB 516 /* LAPB */
|
||||
#define ARPHRD_DDCMP 517 /* Digital's DDCMP protocol */
|
||||
#define ARPHRD_RAWHDLC 518 /* Raw HDLC */
|
||||
#define ARPHRD_RAWIP 519 /* Raw IP */
|
||||
|
||||
#define ARPHRD_TUNNEL 768 /* IPIP tunnel */
|
||||
#define ARPHRD_TUNNEL6 769 /* IP6IP6 tunnel */
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@
|
|||
#define ETH_P_ATALK 0x809B /* Appletalk DDP */
|
||||
#define ETH_P_AARP 0x80F3 /* Appletalk AARP */
|
||||
#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */
|
||||
#define ETH_P_ERSPAN 0x88BE /* ERSPAN type II */
|
||||
#define ETH_P_IPX 0x8137 /* IPX over DIX */
|
||||
#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */
|
||||
#define ETH_P_PAUSE 0x8808 /* IEEE Pause frames. See 802.3 31B */
|
||||
|
|
@ -98,11 +99,13 @@
|
|||
#define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */
|
||||
#define ETH_P_80221 0x8917 /* IEEE 802.21 Media Independent Handover Protocol */
|
||||
#define ETH_P_HSR 0x892F /* IEC 62439-3 HSRv1 */
|
||||
#define ETH_P_NSH 0x894F /* Network Service Header */
|
||||
#define ETH_P_LOOPBACK 0x9000 /* Ethernet loopback packet, per IEEE 802.3 */
|
||||
#define ETH_P_QINQ1 0x9100 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
|
||||
#define ETH_P_QINQ2 0x9200 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
|
||||
#define ETH_P_QINQ3 0x9300 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
|
||||
#define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
|
||||
#define ETH_P_IFE 0xED3E /* ForCES inter-FE LFB type */
|
||||
#define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
|
||||
|
||||
#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is less than this value
|
||||
|
|
@ -137,6 +140,9 @@
|
|||
#define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */
|
||||
#define ETH_P_CAIF 0x00F7 /* ST-Ericsson CAIF protocol */
|
||||
#define ETH_P_XDSA 0x00F8 /* Multiplexed DSA protocol */
|
||||
#define ETH_P_MAP 0x00F9 /* Qualcomm multiplexing and
|
||||
* aggregation protocol
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an Ethernet frame header.
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ enum {
|
|||
IFLA_GRE_COLLECT_METADATA,
|
||||
IFLA_GRE_IGNORE_DF,
|
||||
IFLA_GRE_FWMARK,
|
||||
IFLA_GRE_ERSPAN_INDEX,
|
||||
__IFLA_GRE_MAX,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -142,6 +142,8 @@ enum {
|
|||
INET_DIAG_PAD,
|
||||
INET_DIAG_MARK,
|
||||
INET_DIAG_BBRINFO,
|
||||
INET_DIAG_CLASS_ID,
|
||||
INET_DIAG_MD5SIG,
|
||||
__INET_DIAG_MAX,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,192 +0,0 @@
|
|||
#ifndef _IPV6_H
|
||||
#define _IPV6_H
|
||||
|
||||
#include <linux/libc-compat.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/in6.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
/* The latest drafts declared increase in minimal mtu up to 1280. */
|
||||
|
||||
#define IPV6_MIN_MTU 1280
|
||||
|
||||
/*
|
||||
* Advanced API
|
||||
* source interface/address selection, source routing, etc...
|
||||
* *under construction*
|
||||
*/
|
||||
|
||||
#if __UAPI_DEF_IN6_PKTINFO
|
||||
struct in6_pktinfo {
|
||||
struct in6_addr ipi6_addr;
|
||||
int ipi6_ifindex;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if __UAPI_DEF_IP6_MTUINFO
|
||||
struct ip6_mtuinfo {
|
||||
struct sockaddr_in6 ip6m_addr;
|
||||
__u32 ip6m_mtu;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct in6_ifreq {
|
||||
struct in6_addr ifr6_addr;
|
||||
__u32 ifr6_prefixlen;
|
||||
int ifr6_ifindex;
|
||||
};
|
||||
|
||||
#define IPV6_SRCRT_STRICT 0x01 /* Deprecated; will be removed */
|
||||
#define IPV6_SRCRT_TYPE_0 0 /* Deprecated; will be removed */
|
||||
#define IPV6_SRCRT_TYPE_2 2 /* IPv6 type 2 Routing Header */
|
||||
#define IPV6_SRCRT_TYPE_4 4 /* Segment Routing with IPv6 */
|
||||
|
||||
/*
|
||||
* routing header
|
||||
*/
|
||||
struct ipv6_rt_hdr {
|
||||
__u8 nexthdr;
|
||||
__u8 hdrlen;
|
||||
__u8 type;
|
||||
__u8 segments_left;
|
||||
|
||||
/*
|
||||
* type specific data
|
||||
* variable length field
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
struct ipv6_opt_hdr {
|
||||
__u8 nexthdr;
|
||||
__u8 hdrlen;
|
||||
/*
|
||||
* TLV encoded option data follows.
|
||||
*/
|
||||
} __attribute__((packed)); /* required for some archs */
|
||||
|
||||
#define ipv6_destopt_hdr ipv6_opt_hdr
|
||||
#define ipv6_hopopt_hdr ipv6_opt_hdr
|
||||
|
||||
/* Router Alert option values (RFC2711) */
|
||||
#define IPV6_OPT_ROUTERALERT_MLD 0x0000 /* MLD(RFC2710) */
|
||||
|
||||
/*
|
||||
* routing header type 0 (used in cmsghdr struct)
|
||||
*/
|
||||
|
||||
struct rt0_hdr {
|
||||
struct ipv6_rt_hdr rt_hdr;
|
||||
__u32 reserved;
|
||||
struct in6_addr addr[0];
|
||||
|
||||
#define rt0_type rt_hdr.type
|
||||
};
|
||||
|
||||
/*
|
||||
* routing header type 2
|
||||
*/
|
||||
|
||||
struct rt2_hdr {
|
||||
struct ipv6_rt_hdr rt_hdr;
|
||||
__u32 reserved;
|
||||
struct in6_addr addr;
|
||||
|
||||
#define rt2_type rt_hdr.type
|
||||
};
|
||||
|
||||
/*
|
||||
* home address option in destination options header
|
||||
*/
|
||||
|
||||
struct ipv6_destopt_hao {
|
||||
__u8 type;
|
||||
__u8 length;
|
||||
struct in6_addr addr;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* IPv6 fixed header
|
||||
*
|
||||
* BEWARE, it is incorrect. The first 4 bits of flow_lbl
|
||||
* are glued to priority now, forming "class".
|
||||
*/
|
||||
|
||||
struct ipv6hdr {
|
||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
__u8 priority:4,
|
||||
version:4;
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
__u8 version:4,
|
||||
priority:4;
|
||||
#else
|
||||
#error "Please fix <asm/byteorder.h>"
|
||||
#endif
|
||||
__u8 flow_lbl[3];
|
||||
|
||||
__be16 payload_len;
|
||||
__u8 nexthdr;
|
||||
__u8 hop_limit;
|
||||
|
||||
struct in6_addr saddr;
|
||||
struct in6_addr daddr;
|
||||
};
|
||||
|
||||
|
||||
/* index values for the variables in ipv6_devconf */
|
||||
enum {
|
||||
DEVCONF_FORWARDING = 0,
|
||||
DEVCONF_HOPLIMIT,
|
||||
DEVCONF_MTU6,
|
||||
DEVCONF_ACCEPT_RA,
|
||||
DEVCONF_ACCEPT_REDIRECTS,
|
||||
DEVCONF_AUTOCONF,
|
||||
DEVCONF_DAD_TRANSMITS,
|
||||
DEVCONF_RTR_SOLICITS,
|
||||
DEVCONF_RTR_SOLICIT_INTERVAL,
|
||||
DEVCONF_RTR_SOLICIT_DELAY,
|
||||
DEVCONF_USE_TEMPADDR,
|
||||
DEVCONF_TEMP_VALID_LFT,
|
||||
DEVCONF_TEMP_PREFERED_LFT,
|
||||
DEVCONF_REGEN_MAX_RETRY,
|
||||
DEVCONF_MAX_DESYNC_FACTOR,
|
||||
DEVCONF_MAX_ADDRESSES,
|
||||
DEVCONF_FORCE_MLD_VERSION,
|
||||
DEVCONF_ACCEPT_RA_DEFRTR,
|
||||
DEVCONF_ACCEPT_RA_PINFO,
|
||||
DEVCONF_ACCEPT_RA_RTR_PREF,
|
||||
DEVCONF_RTR_PROBE_INTERVAL,
|
||||
DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN,
|
||||
DEVCONF_PROXY_NDP,
|
||||
DEVCONF_OPTIMISTIC_DAD,
|
||||
DEVCONF_ACCEPT_SOURCE_ROUTE,
|
||||
DEVCONF_MC_FORWARDING,
|
||||
DEVCONF_DISABLE_IPV6,
|
||||
DEVCONF_ACCEPT_DAD,
|
||||
DEVCONF_FORCE_TLLAO,
|
||||
DEVCONF_NDISC_NOTIFY,
|
||||
DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL,
|
||||
DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL,
|
||||
DEVCONF_SUPPRESS_FRAG_NDISC,
|
||||
DEVCONF_ACCEPT_RA_FROM_LOCAL,
|
||||
DEVCONF_USE_OPTIMISTIC,
|
||||
DEVCONF_ACCEPT_RA_MTU,
|
||||
DEVCONF_STABLE_SECRET,
|
||||
DEVCONF_USE_OIF_ADDRS_ONLY,
|
||||
DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT,
|
||||
DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN,
|
||||
DEVCONF_DROP_UNICAST_IN_L2_MULTICAST,
|
||||
DEVCONF_DROP_UNSOLICITED_NA,
|
||||
DEVCONF_KEEP_ADDR_ON_DOWN,
|
||||
DEVCONF_RTR_SOLICIT_MAX_INTERVAL,
|
||||
DEVCONF_SEG6_ENABLED,
|
||||
DEVCONF_SEG6_REQUIRE_HMAC,
|
||||
DEVCONF_ENHANCED_DAD,
|
||||
DEVCONF_ADDR_GEN_MODE,
|
||||
DEVCONF_DISABLE_POLICY,
|
||||
DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN,
|
||||
DEVCONF_MAX
|
||||
};
|
||||
|
||||
|
||||
#endif /* _IPV6_H */
|
||||
|
|
@ -11,6 +11,7 @@ enum lwtunnel_encap_types {
|
|||
LWTUNNEL_ENCAP_IP6,
|
||||
LWTUNNEL_ENCAP_SEG6,
|
||||
LWTUNNEL_ENCAP_BPF,
|
||||
LWTUNNEL_ENCAP_SEG6_LOCAL,
|
||||
__LWTUNNEL_ENCAP_MAX,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,9 @@ struct nlmsghdr {
|
|||
#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
|
||||
#define NLM_F_APPEND 0x800 /* Add to end of list */
|
||||
|
||||
/* Modifiers to DELETE request */
|
||||
#define NLM_F_NONREC 0x100 /* Do not delete recursively */
|
||||
|
||||
/* Flags for ACK message */
|
||||
#define NLM_F_CAPPED 0x100 /* request was capped */
|
||||
#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */
|
||||
|
|
@ -222,5 +225,22 @@ struct nlattr {
|
|||
#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
|
||||
#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
|
||||
|
||||
/* Generic 32 bitflags attribute content sent to the kernel.
|
||||
*
|
||||
* The value is a bitmap that defines the values being set
|
||||
* The selector is a bitmask that defines which value is legit
|
||||
*
|
||||
* Examples:
|
||||
* value = 0x0, and selector = 0x1
|
||||
* implies we are selecting bit 1 and we want to set its value to 0.
|
||||
*
|
||||
* value = 0x2, and selector = 0x2
|
||||
* implies we are selecting bit 2 and we want to set its value to 1.
|
||||
*
|
||||
*/
|
||||
struct nla_bitfield32 {
|
||||
__u32 value;
|
||||
__u32 selector;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_NETLINK_H */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,383 @@
|
|||
/* PF_KEY user interface, this is defined by rfc2367 so
|
||||
* do not make arbitrary modifications or else this header
|
||||
* file will not be compliant.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_PFKEY2_H
|
||||
#define _LINUX_PFKEY2_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define PF_KEY_V2 2
|
||||
#define PFKEYV2_REVISION 199806L
|
||||
|
||||
struct sadb_msg {
|
||||
__u8 sadb_msg_version;
|
||||
__u8 sadb_msg_type;
|
||||
__u8 sadb_msg_errno;
|
||||
__u8 sadb_msg_satype;
|
||||
__u16 sadb_msg_len;
|
||||
__u16 sadb_msg_reserved;
|
||||
__u32 sadb_msg_seq;
|
||||
__u32 sadb_msg_pid;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_msg) == 16 */
|
||||
|
||||
struct sadb_ext {
|
||||
__u16 sadb_ext_len;
|
||||
__u16 sadb_ext_type;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_ext) == 4 */
|
||||
|
||||
struct sadb_sa {
|
||||
__u16 sadb_sa_len;
|
||||
__u16 sadb_sa_exttype;
|
||||
__be32 sadb_sa_spi;
|
||||
__u8 sadb_sa_replay;
|
||||
__u8 sadb_sa_state;
|
||||
__u8 sadb_sa_auth;
|
||||
__u8 sadb_sa_encrypt;
|
||||
__u32 sadb_sa_flags;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_sa) == 16 */
|
||||
|
||||
struct sadb_lifetime {
|
||||
__u16 sadb_lifetime_len;
|
||||
__u16 sadb_lifetime_exttype;
|
||||
__u32 sadb_lifetime_allocations;
|
||||
__u64 sadb_lifetime_bytes;
|
||||
__u64 sadb_lifetime_addtime;
|
||||
__u64 sadb_lifetime_usetime;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_lifetime) == 32 */
|
||||
|
||||
struct sadb_address {
|
||||
__u16 sadb_address_len;
|
||||
__u16 sadb_address_exttype;
|
||||
__u8 sadb_address_proto;
|
||||
__u8 sadb_address_prefixlen;
|
||||
__u16 sadb_address_reserved;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_address) == 8 */
|
||||
|
||||
struct sadb_key {
|
||||
__u16 sadb_key_len;
|
||||
__u16 sadb_key_exttype;
|
||||
__u16 sadb_key_bits;
|
||||
__u16 sadb_key_reserved;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_key) == 8 */
|
||||
|
||||
struct sadb_ident {
|
||||
__u16 sadb_ident_len;
|
||||
__u16 sadb_ident_exttype;
|
||||
__u16 sadb_ident_type;
|
||||
__u16 sadb_ident_reserved;
|
||||
__u64 sadb_ident_id;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_ident) == 16 */
|
||||
|
||||
struct sadb_sens {
|
||||
__u16 sadb_sens_len;
|
||||
__u16 sadb_sens_exttype;
|
||||
__u32 sadb_sens_dpd;
|
||||
__u8 sadb_sens_sens_level;
|
||||
__u8 sadb_sens_sens_len;
|
||||
__u8 sadb_sens_integ_level;
|
||||
__u8 sadb_sens_integ_len;
|
||||
__u32 sadb_sens_reserved;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_sens) == 16 */
|
||||
|
||||
/* followed by:
|
||||
__u64 sadb_sens_bitmap[sens_len];
|
||||
__u64 sadb_integ_bitmap[integ_len]; */
|
||||
|
||||
struct sadb_prop {
|
||||
__u16 sadb_prop_len;
|
||||
__u16 sadb_prop_exttype;
|
||||
__u8 sadb_prop_replay;
|
||||
__u8 sadb_prop_reserved[3];
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_prop) == 8 */
|
||||
|
||||
/* followed by:
|
||||
struct sadb_comb sadb_combs[(sadb_prop_len +
|
||||
sizeof(__u64) - sizeof(struct sadb_prop)) /
|
||||
sizeof(struct sadb_comb)]; */
|
||||
|
||||
struct sadb_comb {
|
||||
__u8 sadb_comb_auth;
|
||||
__u8 sadb_comb_encrypt;
|
||||
__u16 sadb_comb_flags;
|
||||
__u16 sadb_comb_auth_minbits;
|
||||
__u16 sadb_comb_auth_maxbits;
|
||||
__u16 sadb_comb_encrypt_minbits;
|
||||
__u16 sadb_comb_encrypt_maxbits;
|
||||
__u32 sadb_comb_reserved;
|
||||
__u32 sadb_comb_soft_allocations;
|
||||
__u32 sadb_comb_hard_allocations;
|
||||
__u64 sadb_comb_soft_bytes;
|
||||
__u64 sadb_comb_hard_bytes;
|
||||
__u64 sadb_comb_soft_addtime;
|
||||
__u64 sadb_comb_hard_addtime;
|
||||
__u64 sadb_comb_soft_usetime;
|
||||
__u64 sadb_comb_hard_usetime;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_comb) == 72 */
|
||||
|
||||
struct sadb_supported {
|
||||
__u16 sadb_supported_len;
|
||||
__u16 sadb_supported_exttype;
|
||||
__u32 sadb_supported_reserved;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_supported) == 8 */
|
||||
|
||||
/* followed by:
|
||||
struct sadb_alg sadb_algs[(sadb_supported_len +
|
||||
sizeof(__u64) - sizeof(struct sadb_supported)) /
|
||||
sizeof(struct sadb_alg)]; */
|
||||
|
||||
struct sadb_alg {
|
||||
__u8 sadb_alg_id;
|
||||
__u8 sadb_alg_ivlen;
|
||||
__u16 sadb_alg_minbits;
|
||||
__u16 sadb_alg_maxbits;
|
||||
__u16 sadb_alg_reserved;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_alg) == 8 */
|
||||
|
||||
struct sadb_spirange {
|
||||
__u16 sadb_spirange_len;
|
||||
__u16 sadb_spirange_exttype;
|
||||
__u32 sadb_spirange_min;
|
||||
__u32 sadb_spirange_max;
|
||||
__u32 sadb_spirange_reserved;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_spirange) == 16 */
|
||||
|
||||
struct sadb_x_kmprivate {
|
||||
__u16 sadb_x_kmprivate_len;
|
||||
__u16 sadb_x_kmprivate_exttype;
|
||||
__u32 sadb_x_kmprivate_reserved;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_x_kmprivate) == 8 */
|
||||
|
||||
struct sadb_x_sa2 {
|
||||
__u16 sadb_x_sa2_len;
|
||||
__u16 sadb_x_sa2_exttype;
|
||||
__u8 sadb_x_sa2_mode;
|
||||
__u8 sadb_x_sa2_reserved1;
|
||||
__u16 sadb_x_sa2_reserved2;
|
||||
__u32 sadb_x_sa2_sequence;
|
||||
__u32 sadb_x_sa2_reqid;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_x_sa2) == 16 */
|
||||
|
||||
struct sadb_x_policy {
|
||||
__u16 sadb_x_policy_len;
|
||||
__u16 sadb_x_policy_exttype;
|
||||
__u16 sadb_x_policy_type;
|
||||
__u8 sadb_x_policy_dir;
|
||||
__u8 sadb_x_policy_reserved;
|
||||
__u32 sadb_x_policy_id;
|
||||
__u32 sadb_x_policy_priority;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_x_policy) == 16 */
|
||||
|
||||
struct sadb_x_ipsecrequest {
|
||||
__u16 sadb_x_ipsecrequest_len;
|
||||
__u16 sadb_x_ipsecrequest_proto;
|
||||
__u8 sadb_x_ipsecrequest_mode;
|
||||
__u8 sadb_x_ipsecrequest_level;
|
||||
__u16 sadb_x_ipsecrequest_reserved1;
|
||||
__u32 sadb_x_ipsecrequest_reqid;
|
||||
__u32 sadb_x_ipsecrequest_reserved2;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_x_ipsecrequest) == 16 */
|
||||
|
||||
/* This defines the TYPE of Nat Traversal in use. Currently only one
|
||||
* type of NAT-T is supported, draft-ietf-ipsec-udp-encaps-06
|
||||
*/
|
||||
struct sadb_x_nat_t_type {
|
||||
__u16 sadb_x_nat_t_type_len;
|
||||
__u16 sadb_x_nat_t_type_exttype;
|
||||
__u8 sadb_x_nat_t_type_type;
|
||||
__u8 sadb_x_nat_t_type_reserved[3];
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_x_nat_t_type) == 8 */
|
||||
|
||||
/* Pass a NAT Traversal port (Source or Dest port) */
|
||||
struct sadb_x_nat_t_port {
|
||||
__u16 sadb_x_nat_t_port_len;
|
||||
__u16 sadb_x_nat_t_port_exttype;
|
||||
__be16 sadb_x_nat_t_port_port;
|
||||
__u16 sadb_x_nat_t_port_reserved;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_x_nat_t_port) == 8 */
|
||||
|
||||
/* Generic LSM security context */
|
||||
struct sadb_x_sec_ctx {
|
||||
__u16 sadb_x_sec_len;
|
||||
__u16 sadb_x_sec_exttype;
|
||||
__u8 sadb_x_ctx_alg; /* LSMs: e.g., selinux == 1 */
|
||||
__u8 sadb_x_ctx_doi;
|
||||
__u16 sadb_x_ctx_len;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_sec_ctx) = 8 */
|
||||
|
||||
/* Used by MIGRATE to pass addresses IKE will use to perform
|
||||
* negotiation with the peer */
|
||||
struct sadb_x_kmaddress {
|
||||
__u16 sadb_x_kmaddress_len;
|
||||
__u16 sadb_x_kmaddress_exttype;
|
||||
__u32 sadb_x_kmaddress_reserved;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_x_kmaddress) == 8 */
|
||||
|
||||
/* To specify the SA dump filter */
|
||||
struct sadb_x_filter {
|
||||
__u16 sadb_x_filter_len;
|
||||
__u16 sadb_x_filter_exttype;
|
||||
__u32 sadb_x_filter_saddr[4];
|
||||
__u32 sadb_x_filter_daddr[4];
|
||||
__u16 sadb_x_filter_family;
|
||||
__u8 sadb_x_filter_splen;
|
||||
__u8 sadb_x_filter_dplen;
|
||||
} __attribute__((packed));
|
||||
/* sizeof(struct sadb_x_filter) == 40 */
|
||||
|
||||
/* Message types */
|
||||
#define SADB_RESERVED 0
|
||||
#define SADB_GETSPI 1
|
||||
#define SADB_UPDATE 2
|
||||
#define SADB_ADD 3
|
||||
#define SADB_DELETE 4
|
||||
#define SADB_GET 5
|
||||
#define SADB_ACQUIRE 6
|
||||
#define SADB_REGISTER 7
|
||||
#define SADB_EXPIRE 8
|
||||
#define SADB_FLUSH 9
|
||||
#define SADB_DUMP 10
|
||||
#define SADB_X_PROMISC 11
|
||||
#define SADB_X_PCHANGE 12
|
||||
#define SADB_X_SPDUPDATE 13
|
||||
#define SADB_X_SPDADD 14
|
||||
#define SADB_X_SPDDELETE 15
|
||||
#define SADB_X_SPDGET 16
|
||||
#define SADB_X_SPDACQUIRE 17
|
||||
#define SADB_X_SPDDUMP 18
|
||||
#define SADB_X_SPDFLUSH 19
|
||||
#define SADB_X_SPDSETIDX 20
|
||||
#define SADB_X_SPDEXPIRE 21
|
||||
#define SADB_X_SPDDELETE2 22
|
||||
#define SADB_X_NAT_T_NEW_MAPPING 23
|
||||
#define SADB_X_MIGRATE 24
|
||||
#define SADB_MAX 24
|
||||
|
||||
/* Security Association flags */
|
||||
#define SADB_SAFLAGS_PFS 1
|
||||
#define SADB_SAFLAGS_NOPMTUDISC 0x20000000
|
||||
#define SADB_SAFLAGS_DECAP_DSCP 0x40000000
|
||||
#define SADB_SAFLAGS_NOECN 0x80000000
|
||||
|
||||
/* Security Association states */
|
||||
#define SADB_SASTATE_LARVAL 0
|
||||
#define SADB_SASTATE_MATURE 1
|
||||
#define SADB_SASTATE_DYING 2
|
||||
#define SADB_SASTATE_DEAD 3
|
||||
#define SADB_SASTATE_MAX 3
|
||||
|
||||
/* Security Association types */
|
||||
#define SADB_SATYPE_UNSPEC 0
|
||||
#define SADB_SATYPE_AH 2
|
||||
#define SADB_SATYPE_ESP 3
|
||||
#define SADB_SATYPE_RSVP 5
|
||||
#define SADB_SATYPE_OSPFV2 6
|
||||
#define SADB_SATYPE_RIPV2 7
|
||||
#define SADB_SATYPE_MIP 8
|
||||
#define SADB_X_SATYPE_IPCOMP 9
|
||||
#define SADB_SATYPE_MAX 9
|
||||
|
||||
/* Authentication algorithms */
|
||||
#define SADB_AALG_NONE 0
|
||||
#define SADB_AALG_MD5HMAC 2
|
||||
#define SADB_AALG_SHA1HMAC 3
|
||||
#define SADB_X_AALG_SHA2_256HMAC 5
|
||||
#define SADB_X_AALG_SHA2_384HMAC 6
|
||||
#define SADB_X_AALG_SHA2_512HMAC 7
|
||||
#define SADB_X_AALG_RIPEMD160HMAC 8
|
||||
#define SADB_X_AALG_AES_XCBC_MAC 9
|
||||
#define SADB_X_AALG_NULL 251 /* kame */
|
||||
#define SADB_AALG_MAX 251
|
||||
|
||||
/* Encryption algorithms */
|
||||
#define SADB_EALG_NONE 0
|
||||
#define SADB_EALG_DESCBC 2
|
||||
#define SADB_EALG_3DESCBC 3
|
||||
#define SADB_X_EALG_CASTCBC 6
|
||||
#define SADB_X_EALG_BLOWFISHCBC 7
|
||||
#define SADB_EALG_NULL 11
|
||||
#define SADB_X_EALG_AESCBC 12
|
||||
#define SADB_X_EALG_AESCTR 13
|
||||
#define SADB_X_EALG_AES_CCM_ICV8 14
|
||||
#define SADB_X_EALG_AES_CCM_ICV12 15
|
||||
#define SADB_X_EALG_AES_CCM_ICV16 16
|
||||
#define SADB_X_EALG_AES_GCM_ICV8 18
|
||||
#define SADB_X_EALG_AES_GCM_ICV12 19
|
||||
#define SADB_X_EALG_AES_GCM_ICV16 20
|
||||
#define SADB_X_EALG_CAMELLIACBC 22
|
||||
#define SADB_X_EALG_NULL_AES_GMAC 23
|
||||
#define SADB_EALG_MAX 253 /* last EALG */
|
||||
/* private allocations should use 249-255 (RFC2407) */
|
||||
#define SADB_X_EALG_SERPENTCBC 252 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
|
||||
#define SADB_X_EALG_TWOFISHCBC 253 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
|
||||
|
||||
/* Compression algorithms */
|
||||
#define SADB_X_CALG_NONE 0
|
||||
#define SADB_X_CALG_OUI 1
|
||||
#define SADB_X_CALG_DEFLATE 2
|
||||
#define SADB_X_CALG_LZS 3
|
||||
#define SADB_X_CALG_LZJH 4
|
||||
#define SADB_X_CALG_MAX 4
|
||||
|
||||
/* Extension Header values */
|
||||
#define SADB_EXT_RESERVED 0
|
||||
#define SADB_EXT_SA 1
|
||||
#define SADB_EXT_LIFETIME_CURRENT 2
|
||||
#define SADB_EXT_LIFETIME_HARD 3
|
||||
#define SADB_EXT_LIFETIME_SOFT 4
|
||||
#define SADB_EXT_ADDRESS_SRC 5
|
||||
#define SADB_EXT_ADDRESS_DST 6
|
||||
#define SADB_EXT_ADDRESS_PROXY 7
|
||||
#define SADB_EXT_KEY_AUTH 8
|
||||
#define SADB_EXT_KEY_ENCRYPT 9
|
||||
#define SADB_EXT_IDENTITY_SRC 10
|
||||
#define SADB_EXT_IDENTITY_DST 11
|
||||
#define SADB_EXT_SENSITIVITY 12
|
||||
#define SADB_EXT_PROPOSAL 13
|
||||
#define SADB_EXT_SUPPORTED_AUTH 14
|
||||
#define SADB_EXT_SUPPORTED_ENCRYPT 15
|
||||
#define SADB_EXT_SPIRANGE 16
|
||||
#define SADB_X_EXT_KMPRIVATE 17
|
||||
#define SADB_X_EXT_POLICY 18
|
||||
#define SADB_X_EXT_SA2 19
|
||||
/* The next four entries are for setting up NAT Traversal */
|
||||
#define SADB_X_EXT_NAT_T_TYPE 20
|
||||
#define SADB_X_EXT_NAT_T_SPORT 21
|
||||
#define SADB_X_EXT_NAT_T_DPORT 22
|
||||
#define SADB_X_EXT_NAT_T_OA 23
|
||||
#define SADB_X_EXT_SEC_CTX 24
|
||||
/* Used with MIGRATE to pass @ to IKE for negotiation */
|
||||
#define SADB_X_EXT_KMADDRESS 25
|
||||
#define SADB_X_EXT_FILTER 26
|
||||
#define SADB_EXT_MAX 26
|
||||
|
||||
/* Identity Extension values */
|
||||
#define SADB_IDENTTYPE_RESERVED 0
|
||||
#define SADB_IDENTTYPE_PREFIX 1
|
||||
#define SADB_IDENTTYPE_FQDN 2
|
||||
#define SADB_IDENTTYPE_USERFQDN 3
|
||||
#define SADB_IDENTTYPE_MAX 3
|
||||
|
||||
#endif /* !(_LINUX_PFKEY2_H) */
|
||||
|
|
@ -681,10 +681,29 @@ struct tcamsg {
|
|||
unsigned char tca__pad1;
|
||||
unsigned short tca__pad2;
|
||||
};
|
||||
|
||||
enum {
|
||||
TCA_ROOT_UNSPEC,
|
||||
TCA_ROOT_TAB,
|
||||
#define TCA_ACT_TAB TCA_ROOT_TAB
|
||||
#define TCAA_MAX TCA_ROOT_TAB
|
||||
TCA_ROOT_FLAGS,
|
||||
TCA_ROOT_COUNT,
|
||||
TCA_ROOT_TIME_DELTA, /* in msecs */
|
||||
__TCA_ROOT_MAX,
|
||||
#define TCA_ROOT_MAX (__TCA_ROOT_MAX - 1)
|
||||
};
|
||||
|
||||
#define TA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcamsg))))
|
||||
#define TA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcamsg))
|
||||
#define TCA_ACT_TAB 1 /* attr type must be >=1 */
|
||||
#define TCAA_MAX 1
|
||||
/* tcamsg flags stored in attribute TCA_ROOT_FLAGS
|
||||
*
|
||||
* TCA_FLAG_LARGE_DUMP_ON user->kernel to request for larger than TCA_ACT_MAX_PRIO
|
||||
* actions in a dump. All dump responses will contain the number of actions
|
||||
* being dumped stored in for user app's consumption in TCA_ROOT_COUNT
|
||||
*
|
||||
*/
|
||||
#define TCA_FLAG_LARGE_DUMP_ON (1 << 0)
|
||||
|
||||
/* New extended info filters for IFLA_EXT_MASK */
|
||||
#define RTEXT_FILTER_VF (1 << 0)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ struct seg6_iptunnel_encap {
|
|||
enum {
|
||||
SEG6_IPTUN_MODE_INLINE,
|
||||
SEG6_IPTUN_MODE_ENCAP,
|
||||
SEG6_IPTUN_MODE_L2ENCAP,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* SR-IPv6 implementation
|
||||
*
|
||||
* Author:
|
||||
* David Lebrun <david.lebrun@uclouvain.be>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_SEG6_LOCAL_H
|
||||
#define _LINUX_SEG6_LOCAL_H
|
||||
|
||||
#include <linux/seg6.h>
|
||||
|
||||
enum {
|
||||
SEG6_LOCAL_UNSPEC,
|
||||
SEG6_LOCAL_ACTION,
|
||||
SEG6_LOCAL_SRH,
|
||||
SEG6_LOCAL_TABLE,
|
||||
SEG6_LOCAL_NH4,
|
||||
SEG6_LOCAL_NH6,
|
||||
SEG6_LOCAL_IIF,
|
||||
SEG6_LOCAL_OIF,
|
||||
__SEG6_LOCAL_MAX,
|
||||
};
|
||||
#define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1)
|
||||
|
||||
enum {
|
||||
SEG6_LOCAL_ACTION_UNSPEC = 0,
|
||||
/* node segment */
|
||||
SEG6_LOCAL_ACTION_END = 1,
|
||||
/* adjacency segment (IPv6 cross-connect) */
|
||||
SEG6_LOCAL_ACTION_END_X = 2,
|
||||
/* lookup of next seg NH in table */
|
||||
SEG6_LOCAL_ACTION_END_T = 3,
|
||||
/* decap and L2 cross-connect */
|
||||
SEG6_LOCAL_ACTION_END_DX2 = 4,
|
||||
/* decap and IPv6 cross-connect */
|
||||
SEG6_LOCAL_ACTION_END_DX6 = 5,
|
||||
/* decap and IPv4 cross-connect */
|
||||
SEG6_LOCAL_ACTION_END_DX4 = 6,
|
||||
/* decap and lookup of DA in v6 table */
|
||||
SEG6_LOCAL_ACTION_END_DT6 = 7,
|
||||
/* decap and lookup of DA in v4 table */
|
||||
SEG6_LOCAL_ACTION_END_DT4 = 8,
|
||||
/* binding segment with insertion */
|
||||
SEG6_LOCAL_ACTION_END_B6 = 9,
|
||||
/* binding segment with encapsulation */
|
||||
SEG6_LOCAL_ACTION_END_B6_ENCAP = 10,
|
||||
/* binding segment with MPLS encap */
|
||||
SEG6_LOCAL_ACTION_END_BM = 11,
|
||||
/* lookup last seg in table */
|
||||
SEG6_LOCAL_ACTION_END_S = 12,
|
||||
/* forward to SR-unaware VNF with static proxy */
|
||||
SEG6_LOCAL_ACTION_END_AS = 13,
|
||||
/* forward to SR-unaware VNF with masquerading */
|
||||
SEG6_LOCAL_ACTION_END_AM = 14,
|
||||
|
||||
__SEG6_LOCAL_ACTION_MAX,
|
||||
};
|
||||
|
||||
#define SEG6_LOCAL_ACTION_MAX (__SEG6_LOCAL_ACTION_MAX - 1)
|
||||
|
||||
#endif
|
||||
|
|
@ -231,6 +231,14 @@ enum {
|
|||
TCP_NLA_SNDBUF_LIMITED, /* Time (usec) limited by send buffer */
|
||||
TCP_NLA_DATA_SEGS_OUT, /* Data pkts sent including retransmission */
|
||||
TCP_NLA_TOTAL_RETRANS, /* Data pkts retransmitted */
|
||||
TCP_NLA_PACING_RATE, /* Pacing rate in bytes per second */
|
||||
TCP_NLA_DELIVERY_RATE, /* Delivery rate in bytes per second */
|
||||
TCP_NLA_SND_CWND, /* Sending congestion window */
|
||||
TCP_NLA_REORDERING, /* Reordering metric */
|
||||
TCP_NLA_MIN_RTT, /* minimum RTT */
|
||||
TCP_NLA_RECUR_RETRANS, /* Recurring retransmits for the current pkt */
|
||||
TCP_NLA_DELIVERY_RATE_APP_LMT, /* delivery rate application limited ? */
|
||||
|
||||
};
|
||||
|
||||
/* for TCP_MD5SIG socket option */
|
||||
|
|
@ -248,4 +256,13 @@ struct tcp_md5sig {
|
|||
__u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
|
||||
};
|
||||
|
||||
/* INET_DIAG_MD5SIG */
|
||||
struct tcp_diag_md5sig {
|
||||
__u8 tcpm_family;
|
||||
__u8 tcpm_prefixlen;
|
||||
__u16 tcpm_keylen;
|
||||
__be32 tcpm_addr[4];
|
||||
__u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN];
|
||||
};
|
||||
|
||||
#endif /* _LINUX_TCP_H */
|
||||
|
|
|
|||
|
|
@ -304,6 +304,7 @@ enum xfrm_attr_type_t {
|
|||
XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */
|
||||
XFRMA_PAD,
|
||||
XFRMA_OFFLOAD_DEV, /* struct xfrm_state_offload */
|
||||
XFRMA_OUTPUT_MARK, /* __u32 */
|
||||
__XFRMA_MAX
|
||||
|
||||
#define XFRMA_MAX (__XFRMA_MAX - 1)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ extern int show_raw;
|
|||
extern int resolve_hosts;
|
||||
extern int oneline;
|
||||
extern int brief;
|
||||
extern int json;
|
||||
extern int timestamp;
|
||||
extern int timestamp_short;
|
||||
extern const char * _SL_;
|
||||
|
|
|
|||
17
ip/Makefile
17
ip/Makefile
|
|
@ -9,24 +9,11 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
|
|||
link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \
|
||||
iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \
|
||||
iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \
|
||||
ipvrf.o iplink_xstats.o ipseg6.o
|
||||
ipvrf.o iplink_xstats.o ipseg6.o ip_print.o
|
||||
|
||||
RTMONOBJ=rtmon.o
|
||||
|
||||
include ../Config
|
||||
|
||||
ifeq ($(IP_CONFIG_SETNS),y)
|
||||
CFLAGS += -DHAVE_SETNS
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_ELF),y)
|
||||
CFLAGS += -DHAVE_ELF
|
||||
LDLIBS += -lelf
|
||||
endif
|
||||
ifeq ($(HAVE_MNL),y)
|
||||
CFLAGS += -DHAVE_LIBMNL $(shell $(PKG_CONFIG) libmnl --cflags)
|
||||
LDLIBS += $(shell $(PKG_CONFIG) libmnl --libs)
|
||||
endif
|
||||
include ../config.mk
|
||||
|
||||
ALLOBJ=$(IPOBJ) $(RTMONOBJ)
|
||||
SCRIPTS=ifcfg rtpr routel routef
|
||||
|
|
|
|||
6
ip/ip.c
6
ip/ip.c
|
|
@ -33,6 +33,7 @@ int show_details;
|
|||
int resolve_hosts;
|
||||
int oneline;
|
||||
int brief;
|
||||
int json;
|
||||
int timestamp;
|
||||
const char *_SL_;
|
||||
int force;
|
||||
|
|
@ -258,6 +259,8 @@ int main(int argc, char **argv)
|
|||
batch_file = argv[1];
|
||||
} else if (matches(opt, "-brief") == 0) {
|
||||
++brief;
|
||||
} else if (matches(opt, "-json") == 0) {
|
||||
++json;
|
||||
} else if (matches(opt, "-rcvbuf") == 0) {
|
||||
unsigned int size;
|
||||
|
||||
|
|
@ -292,6 +295,9 @@ int main(int argc, char **argv)
|
|||
|
||||
_SL_ = oneline ? "\\" : "\n";
|
||||
|
||||
if (json)
|
||||
check_if_color_enabled();
|
||||
|
||||
if (batch_file)
|
||||
return batch(batch_file);
|
||||
|
||||
|
|
|
|||
|
|
@ -140,3 +140,59 @@ int name_is_vrf(const char *name);
|
|||
#endif
|
||||
|
||||
void print_num(FILE *fp, unsigned int width, uint64_t count);
|
||||
|
||||
#include "json_writer.h"
|
||||
|
||||
json_writer_t *get_json_writer(void);
|
||||
/*
|
||||
* use:
|
||||
* - PRINT_ANY for context based output
|
||||
* - PRINT_FP for non json specific output
|
||||
* - PRINT_JSON for json specific output
|
||||
*/
|
||||
enum output_type {
|
||||
PRINT_FP = 1,
|
||||
PRINT_JSON = 2,
|
||||
PRINT_ANY = 4,
|
||||
};
|
||||
|
||||
void new_json_obj(int json, FILE *fp);
|
||||
void delete_json_obj(void);
|
||||
|
||||
bool is_json_context(void);
|
||||
|
||||
void set_current_fp(FILE *fp);
|
||||
|
||||
void fflush_fp(void);
|
||||
|
||||
void open_json_object(const char *str);
|
||||
void close_json_object(void);
|
||||
void open_json_array(enum output_type type, const char *delim);
|
||||
void close_json_array(enum output_type type, const char *delim);
|
||||
|
||||
#include "color.h"
|
||||
|
||||
#define _PRINT_FUNC(type_name, type) \
|
||||
void print_color_##type_name(enum output_type t, \
|
||||
enum color_attr color, \
|
||||
const char *key, \
|
||||
const char *fmt, \
|
||||
type value); \
|
||||
\
|
||||
static inline void print_##type_name(enum output_type t, \
|
||||
const char *key, \
|
||||
const char *fmt, \
|
||||
type value) \
|
||||
{ \
|
||||
print_color_##type_name(t, -1, key, fmt, value); \
|
||||
}
|
||||
_PRINT_FUNC(int, int);
|
||||
_PRINT_FUNC(bool, bool);
|
||||
_PRINT_FUNC(null, const char*);
|
||||
_PRINT_FUNC(string, const char*);
|
||||
_PRINT_FUNC(uint, uint64_t);
|
||||
_PRINT_FUNC(hu, unsigned short);
|
||||
_PRINT_FUNC(hex, unsigned int);
|
||||
_PRINT_FUNC(0xhex, unsigned int);
|
||||
_PRINT_FUNC(lluint, unsigned long long int);
|
||||
#undef _PRINT_FUNC
|
||||
|
|
|
|||
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* ip_print.c "ip print regular or json output".
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Authors: Julien Fortin, <julien@cumulusnetworks.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "ip_common.h"
|
||||
#include "json_writer.h"
|
||||
|
||||
static json_writer_t *_jw;
|
||||
static FILE *_fp;
|
||||
|
||||
#define _IS_JSON_CONTEXT(type) ((type & PRINT_JSON || type & PRINT_ANY) && _jw)
|
||||
#define _IS_FP_CONTEXT(type) (!_jw && (type & PRINT_FP || type & PRINT_ANY))
|
||||
|
||||
void new_json_obj(int json, FILE *fp)
|
||||
{
|
||||
if (json) {
|
||||
_jw = jsonw_new(fp);
|
||||
if (!_jw) {
|
||||
perror("json object");
|
||||
exit(1);
|
||||
}
|
||||
jsonw_pretty(_jw, true);
|
||||
jsonw_start_array(_jw);
|
||||
}
|
||||
set_current_fp(fp);
|
||||
}
|
||||
|
||||
void delete_json_obj(void)
|
||||
{
|
||||
if (_jw) {
|
||||
jsonw_end_array(_jw);
|
||||
jsonw_destroy(&_jw);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_json_context(void)
|
||||
{
|
||||
return _jw != NULL;
|
||||
}
|
||||
|
||||
void set_current_fp(FILE *fp)
|
||||
{
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Error: invalid file pointer.\n");
|
||||
exit(1);
|
||||
}
|
||||
_fp = fp;
|
||||
}
|
||||
|
||||
json_writer_t *get_json_writer(void)
|
||||
{
|
||||
return _jw;
|
||||
}
|
||||
|
||||
void open_json_object(const char *str)
|
||||
{
|
||||
if (_IS_JSON_CONTEXT(PRINT_JSON)) {
|
||||
if (str)
|
||||
jsonw_name(_jw, str);
|
||||
jsonw_start_object(_jw);
|
||||
}
|
||||
}
|
||||
|
||||
void close_json_object(void)
|
||||
{
|
||||
if (_IS_JSON_CONTEXT(PRINT_JSON))
|
||||
jsonw_end_object(_jw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start json array or string array using
|
||||
* the provided string as json key (if not null)
|
||||
* or as array delimiter in non-json context.
|
||||
*/
|
||||
void open_json_array(enum output_type type, const char *str)
|
||||
{
|
||||
if (_IS_JSON_CONTEXT(type)) {
|
||||
if (str)
|
||||
jsonw_name(_jw, str);
|
||||
jsonw_start_array(_jw);
|
||||
} else if (_IS_FP_CONTEXT(type)) {
|
||||
fprintf(_fp, "%s", str);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* End json array or string array
|
||||
*/
|
||||
void close_json_array(enum output_type type, const char *str)
|
||||
{
|
||||
if (_IS_JSON_CONTEXT(type)) {
|
||||
jsonw_pretty(_jw, false);
|
||||
jsonw_end_array(_jw);
|
||||
jsonw_pretty(_jw, true);
|
||||
} else if (_IS_FP_CONTEXT(type)) {
|
||||
fprintf(_fp, "%s", str);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* pre-processor directive to generate similar
|
||||
* functions handling different types
|
||||
*/
|
||||
#define _PRINT_FUNC(type_name, type) \
|
||||
void print_color_##type_name(enum output_type t, \
|
||||
enum color_attr color, \
|
||||
const char *key, \
|
||||
const char *fmt, \
|
||||
type value) \
|
||||
{ \
|
||||
if (_IS_JSON_CONTEXT(t)) { \
|
||||
if (!key) \
|
||||
jsonw_##type_name(_jw, value); \
|
||||
else \
|
||||
jsonw_##type_name##_field(_jw, key, value); \
|
||||
} else if (_IS_FP_CONTEXT(t)) { \
|
||||
color_fprintf(_fp, color, fmt, value); \
|
||||
} \
|
||||
}
|
||||
_PRINT_FUNC(int, int);
|
||||
_PRINT_FUNC(hu, unsigned short);
|
||||
_PRINT_FUNC(uint, uint64_t);
|
||||
_PRINT_FUNC(lluint, unsigned long long int);
|
||||
#undef _PRINT_FUNC
|
||||
|
||||
void print_color_string(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
const char *value)
|
||||
{
|
||||
if (_IS_JSON_CONTEXT(type)) {
|
||||
if (key && !value)
|
||||
jsonw_name(_jw, key);
|
||||
else if (!key && value)
|
||||
jsonw_string(_jw, value);
|
||||
else
|
||||
jsonw_string_field(_jw, key, value);
|
||||
} else if (_IS_FP_CONTEXT(type)) {
|
||||
color_fprintf(_fp, color, fmt, value);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* value's type is bool. When using this function in FP context you can't pass
|
||||
* a value to it, you will need to use "is_json_context()" to have different
|
||||
* branch for json and regular output. grep -r "print_bool" for example
|
||||
*/
|
||||
void print_color_bool(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
bool value)
|
||||
{
|
||||
if (_IS_JSON_CONTEXT(type)) {
|
||||
if (key)
|
||||
jsonw_bool_field(_jw, key, value);
|
||||
else
|
||||
jsonw_bool(_jw, value);
|
||||
} else if (_IS_FP_CONTEXT(type)) {
|
||||
color_fprintf(_fp, color, fmt, value ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* In JSON context uses hardcode %#x format: 42 -> 0x2a
|
||||
*/
|
||||
void print_color_0xhex(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
unsigned int hex)
|
||||
{
|
||||
if (_IS_JSON_CONTEXT(type)) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1), "%#x", hex);
|
||||
print_string(PRINT_JSON, key, NULL, b1);
|
||||
} else if (_IS_FP_CONTEXT(type)) {
|
||||
color_fprintf(_fp, color, fmt, hex);
|
||||
}
|
||||
}
|
||||
|
||||
void print_color_hex(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
unsigned int hex)
|
||||
{
|
||||
if (_IS_JSON_CONTEXT(type)) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1), "%x", hex);
|
||||
if (key)
|
||||
jsonw_string_field(_jw, key, b1);
|
||||
else
|
||||
jsonw_string(_jw, b1);
|
||||
} else if (_IS_FP_CONTEXT(type)) {
|
||||
color_fprintf(_fp, color, fmt, hex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* In JSON context we don't use the argument "value" we simply call jsonw_null
|
||||
* whereas FP context can use "value" to output anything
|
||||
*/
|
||||
void print_color_null(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
const char *value)
|
||||
{
|
||||
if (_IS_JSON_CONTEXT(type)) {
|
||||
if (key)
|
||||
jsonw_null_field(_jw, key);
|
||||
else
|
||||
jsonw_null(_jw);
|
||||
} else if (_IS_FP_CONTEXT(type)) {
|
||||
color_fprintf(_fp, color, fmt, value);
|
||||
}
|
||||
}
|
||||
1048
ip/ipaddress.c
1048
ip/ipaddress.c
File diff suppressed because it is too large
Load Diff
|
|
@ -112,8 +112,9 @@ void iplink_usage(void)
|
|||
"\n"
|
||||
"TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n"
|
||||
" bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |\n"
|
||||
" gre | gretap | ip6gre | ip6gretap | vti | nlmon | team_slave |\n"
|
||||
" bond_slave | ipvlan | geneve | bridge_slave | vrf | macsec }\n");
|
||||
" gre | gretap | erspan | ip6gre | ip6gretap | vti | nlmon |\n"
|
||||
" team_slave | bond_slave | ipvlan | geneve | bridge_slave |\n"
|
||||
" vrf | macsec }\n");
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
|
@ -1046,10 +1047,12 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
|
|||
return -2;
|
||||
}
|
||||
|
||||
open_json_object(NULL);
|
||||
if (brief)
|
||||
print_linkinfo_brief(NULL, &answer.n, stdout, NULL);
|
||||
else
|
||||
print_linkinfo(NULL, &answer.n, stdout);
|
||||
close_json_object();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
231
ip/iplink_bond.c
231
ip/iplink_bond.c
|
|
@ -376,8 +376,8 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
|
||||
if (tb[IFLA_BOND_MODE]) {
|
||||
const char *mode = get_name(mode_tbl,
|
||||
rta_getattr_u8(tb[IFLA_BOND_MODE]));
|
||||
fprintf(f, "mode %s ", mode);
|
||||
rta_getattr_u8(tb[IFLA_BOND_MODE]));
|
||||
print_string(PRINT_ANY, "mode", "mode %s ", mode);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_ACTIVE_SLAVE] &&
|
||||
|
|
@ -386,61 +386,97 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
const char *n = if_indextoname(ifindex, buf);
|
||||
|
||||
if (n)
|
||||
fprintf(f, "active_slave %s ", n);
|
||||
print_string(PRINT_ANY,
|
||||
"active_slave",
|
||||
"active_slave %s ",
|
||||
n);
|
||||
else
|
||||
fprintf(f, "active_slave %u ", ifindex);
|
||||
print_uint(PRINT_ANY,
|
||||
"active_slave_index",
|
||||
"active_slave %u ",
|
||||
ifindex);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_MIIMON])
|
||||
fprintf(f, "miimon %u ", rta_getattr_u32(tb[IFLA_BOND_MIIMON]));
|
||||
print_uint(PRINT_ANY,
|
||||
"miimon",
|
||||
"miimon %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_MIIMON]));
|
||||
|
||||
if (tb[IFLA_BOND_UPDELAY])
|
||||
fprintf(f, "updelay %u ", rta_getattr_u32(tb[IFLA_BOND_UPDELAY]));
|
||||
print_uint(PRINT_ANY,
|
||||
"updelay",
|
||||
"updelay %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_UPDELAY]));
|
||||
|
||||
if (tb[IFLA_BOND_DOWNDELAY])
|
||||
fprintf(f, "downdelay %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY]));
|
||||
print_uint(PRINT_ANY,
|
||||
"downdelay",
|
||||
"downdelay %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY]));
|
||||
|
||||
if (tb[IFLA_BOND_USE_CARRIER])
|
||||
fprintf(f, "use_carrier %u ",
|
||||
rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER]));
|
||||
print_uint(PRINT_ANY,
|
||||
"use_carrier",
|
||||
"use_carrier %u ",
|
||||
rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER]));
|
||||
|
||||
if (tb[IFLA_BOND_ARP_INTERVAL])
|
||||
fprintf(f, "arp_interval %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL]));
|
||||
print_uint(PRINT_ANY,
|
||||
"arp_interval",
|
||||
"arp_interval %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL]));
|
||||
|
||||
if (tb[IFLA_BOND_ARP_IP_TARGET]) {
|
||||
struct rtattr *iptb[BOND_MAX_ARP_TARGETS + 1];
|
||||
int i;
|
||||
|
||||
parse_rtattr_nested(iptb, BOND_MAX_ARP_TARGETS,
|
||||
tb[IFLA_BOND_ARP_IP_TARGET]);
|
||||
tb[IFLA_BOND_ARP_IP_TARGET]);
|
||||
|
||||
if (iptb[0])
|
||||
fprintf(f, "arp_ip_target ");
|
||||
if (iptb[0]) {
|
||||
open_json_array(PRINT_JSON, "arp_ip_target");
|
||||
print_string(PRINT_FP, NULL, "arp_ip_target ", NULL);
|
||||
}
|
||||
|
||||
for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
|
||||
if (iptb[i])
|
||||
fprintf(f, "%s",
|
||||
rt_addr_n2a_rta(AF_INET, iptb[i]));
|
||||
if (i < BOND_MAX_ARP_TARGETS-1 && iptb[i+1])
|
||||
print_string(PRINT_ANY,
|
||||
NULL,
|
||||
"%s",
|
||||
rt_addr_n2a_rta(AF_INET, iptb[i]));
|
||||
if (!is_json_context()
|
||||
&& i < BOND_MAX_ARP_TARGETS-1
|
||||
&& iptb[i+1])
|
||||
fprintf(f, ",");
|
||||
}
|
||||
|
||||
if (iptb[0])
|
||||
fprintf(f, " ");
|
||||
if (iptb[0]) {
|
||||
print_string(PRINT_FP, NULL, " ", NULL);
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_ARP_VALIDATE]) {
|
||||
const char *arp_validate = get_name(arp_validate_tbl,
|
||||
rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE]));
|
||||
fprintf(f, "arp_validate %s ", arp_validate);
|
||||
__u32 arp_v = rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE]);
|
||||
const char *arp_validate = get_name(arp_validate_tbl, arp_v);
|
||||
|
||||
if (!arp_v && is_json_context())
|
||||
print_null(PRINT_JSON, "arp_validate", NULL, NULL);
|
||||
else
|
||||
print_string(PRINT_ANY,
|
||||
"arp_validate",
|
||||
"arp_validate %s ",
|
||||
arp_validate);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_ARP_ALL_TARGETS]) {
|
||||
const char *arp_all_targets = get_name(arp_all_targets_tbl,
|
||||
rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS]));
|
||||
fprintf(f, "arp_all_targets %s ", arp_all_targets);
|
||||
rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS]));
|
||||
print_string(PRINT_ANY,
|
||||
"arp_all_targets",
|
||||
"arp_all_targets %s ",
|
||||
arp_all_targets);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_PRIMARY] &&
|
||||
|
|
@ -449,123 +485,176 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
const char *n = if_indextoname(ifindex, buf);
|
||||
|
||||
if (n)
|
||||
fprintf(f, "primary %s ", n);
|
||||
print_string(PRINT_ANY, "primary", "primary %s ", n);
|
||||
else
|
||||
fprintf(f, "primary %u ", ifindex);
|
||||
print_uint(PRINT_ANY,
|
||||
"primary_index",
|
||||
"primary %u ",
|
||||
ifindex);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_PRIMARY_RESELECT]) {
|
||||
const char *primary_reselect = get_name(primary_reselect_tbl,
|
||||
rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT]));
|
||||
fprintf(f, "primary_reselect %s ", primary_reselect);
|
||||
rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT]));
|
||||
print_string(PRINT_ANY,
|
||||
"primary_reselect",
|
||||
"primary_reselect %s ",
|
||||
primary_reselect);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_FAIL_OVER_MAC]) {
|
||||
const char *fail_over_mac = get_name(fail_over_mac_tbl,
|
||||
rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC]));
|
||||
fprintf(f, "fail_over_mac %s ", fail_over_mac);
|
||||
rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC]));
|
||||
print_string(PRINT_ANY,
|
||||
"fail_over_mac",
|
||||
"fail_over_mac %s ",
|
||||
fail_over_mac);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_XMIT_HASH_POLICY]) {
|
||||
const char *xmit_hash_policy = get_name(xmit_hash_policy_tbl,
|
||||
rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY]));
|
||||
fprintf(f, "xmit_hash_policy %s ", xmit_hash_policy);
|
||||
rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY]));
|
||||
print_string(PRINT_ANY,
|
||||
"xmit_hash_policy",
|
||||
"xmit_hash_policy %s ",
|
||||
xmit_hash_policy);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_RESEND_IGMP])
|
||||
fprintf(f, "resend_igmp %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP]));
|
||||
print_uint(PRINT_ANY,
|
||||
"resend_igmp",
|
||||
"resend_igmp %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP]));
|
||||
|
||||
if (tb[IFLA_BOND_NUM_PEER_NOTIF])
|
||||
fprintf(f, "num_grat_arp %u ",
|
||||
rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF]));
|
||||
print_uint(PRINT_ANY,
|
||||
"num_peer_notif",
|
||||
"num_grat_arp %u ",
|
||||
rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF]));
|
||||
|
||||
if (tb[IFLA_BOND_ALL_SLAVES_ACTIVE])
|
||||
fprintf(f, "all_slaves_active %u ",
|
||||
rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE]));
|
||||
print_uint(PRINT_ANY,
|
||||
"all_slaves_active",
|
||||
"all_slaves_active %u ",
|
||||
rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE]));
|
||||
|
||||
if (tb[IFLA_BOND_MIN_LINKS])
|
||||
fprintf(f, "min_links %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS]));
|
||||
print_uint(PRINT_ANY,
|
||||
"min_links",
|
||||
"min_links %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS]));
|
||||
|
||||
if (tb[IFLA_BOND_LP_INTERVAL])
|
||||
fprintf(f, "lp_interval %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL]));
|
||||
print_uint(PRINT_ANY,
|
||||
"lp_interval",
|
||||
"lp_interval %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL]));
|
||||
|
||||
if (tb[IFLA_BOND_PACKETS_PER_SLAVE])
|
||||
fprintf(f, "packets_per_slave %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE]));
|
||||
print_uint(PRINT_ANY,
|
||||
"packets_per_slave",
|
||||
"packets_per_slave %u ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE]));
|
||||
|
||||
if (tb[IFLA_BOND_AD_LACP_RATE]) {
|
||||
const char *lacp_rate = get_name(lacp_rate_tbl,
|
||||
rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE]));
|
||||
fprintf(f, "lacp_rate %s ", lacp_rate);
|
||||
rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE]));
|
||||
print_string(PRINT_ANY,
|
||||
"ad_lacp_rate",
|
||||
"lacp_rate %s ",
|
||||
lacp_rate);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_AD_SELECT]) {
|
||||
const char *ad_select = get_name(ad_select_tbl,
|
||||
rta_getattr_u8(tb[IFLA_BOND_AD_SELECT]));
|
||||
fprintf(f, "ad_select %s ", ad_select);
|
||||
rta_getattr_u8(tb[IFLA_BOND_AD_SELECT]));
|
||||
print_string(PRINT_ANY,
|
||||
"ad_select",
|
||||
"ad_select %s ",
|
||||
ad_select);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_AD_INFO]) {
|
||||
struct rtattr *adtb[IFLA_BOND_AD_INFO_MAX + 1];
|
||||
|
||||
parse_rtattr_nested(adtb, IFLA_BOND_AD_INFO_MAX,
|
||||
tb[IFLA_BOND_AD_INFO]);
|
||||
tb[IFLA_BOND_AD_INFO]);
|
||||
|
||||
open_json_object("ad_info");
|
||||
|
||||
if (adtb[IFLA_BOND_AD_INFO_AGGREGATOR])
|
||||
fprintf(f, "ad_aggregator %d ",
|
||||
rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR]));
|
||||
print_int(PRINT_ANY,
|
||||
"aggregator",
|
||||
"ad_aggregator %d ",
|
||||
rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR]));
|
||||
|
||||
if (adtb[IFLA_BOND_AD_INFO_NUM_PORTS])
|
||||
fprintf(f, "ad_num_ports %d ",
|
||||
rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS]));
|
||||
print_int(PRINT_ANY,
|
||||
"num_ports",
|
||||
"ad_num_ports %d ",
|
||||
rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS]));
|
||||
|
||||
if (adtb[IFLA_BOND_AD_INFO_ACTOR_KEY])
|
||||
fprintf(f, "ad_actor_key %d ",
|
||||
rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]));
|
||||
print_int(PRINT_ANY,
|
||||
"actor_key",
|
||||
"ad_actor_key %d ",
|
||||
rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]));
|
||||
|
||||
if (adtb[IFLA_BOND_AD_INFO_PARTNER_KEY])
|
||||
fprintf(f, "ad_partner_key %d ",
|
||||
rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]));
|
||||
print_int(PRINT_ANY,
|
||||
"partner_key",
|
||||
"ad_partner_key %d ",
|
||||
rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]));
|
||||
|
||||
if (adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]) {
|
||||
unsigned char *p =
|
||||
RTA_DATA(adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]);
|
||||
SPRINT_BUF(b);
|
||||
fprintf(f, "ad_partner_mac %s ",
|
||||
ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b)));
|
||||
print_string(PRINT_ANY,
|
||||
"partner_mac",
|
||||
"ad_partner_mac %s ",
|
||||
ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b)));
|
||||
}
|
||||
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]) {
|
||||
fprintf(f, "ad_actor_sys_prio %u ",
|
||||
rta_getattr_u16(tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]));
|
||||
print_uint(PRINT_ANY,
|
||||
"ad_actor_sys_prio",
|
||||
"ad_actor_sys_prio %u ",
|
||||
rta_getattr_u16(tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]));
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_AD_USER_PORT_KEY]) {
|
||||
fprintf(f, "ad_user_port_key %u ",
|
||||
rta_getattr_u16(tb[IFLA_BOND_AD_USER_PORT_KEY]));
|
||||
print_uint(PRINT_ANY,
|
||||
"ad_user_port_key",
|
||||
"ad_user_port_key %u ",
|
||||
rta_getattr_u16(tb[IFLA_BOND_AD_USER_PORT_KEY]));
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_AD_ACTOR_SYSTEM]) {
|
||||
/* We assume the l2 address is an Ethernet MAC address */
|
||||
SPRINT_BUF(b1);
|
||||
fprintf(f, "ad_actor_system %s ",
|
||||
ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
|
||||
RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
|
||||
1 /*ARPHDR_ETHER*/, b1, sizeof(b1)));
|
||||
|
||||
print_string(PRINT_ANY,
|
||||
"ad_actor_system",
|
||||
"ad_actor_system %s ",
|
||||
ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
|
||||
RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
|
||||
1 /*ARPHDR_ETHER*/, b1, sizeof(b1)));
|
||||
}
|
||||
|
||||
if (tb[IFLA_BOND_TLB_DYNAMIC_LB]) {
|
||||
fprintf(f, "tlb_dynamic_lb %u ",
|
||||
rta_getattr_u8(tb[IFLA_BOND_TLB_DYNAMIC_LB]));
|
||||
print_uint(PRINT_ANY,
|
||||
"tlb_dynamic_lb",
|
||||
"tlb_dynamic_lb %u ",
|
||||
rta_getattr_u8(tb[IFLA_BOND_TLB_DYNAMIC_LB]));
|
||||
}
|
||||
}
|
||||
|
||||
static void bond_print_help(struct link_util *lu, int argc, char **argv,
|
||||
FILE *f)
|
||||
FILE *f)
|
||||
{
|
||||
print_explain(f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,9 +37,12 @@ static void print_slave_state(FILE *f, struct rtattr *tb)
|
|||
unsigned int state = rta_getattr_u8(tb);
|
||||
|
||||
if (state >= ARRAY_SIZE(slave_states))
|
||||
fprintf(f, "state %d ", state);
|
||||
print_int(PRINT_ANY, "state_index", "state %d ", state);
|
||||
else
|
||||
fprintf(f, "state %s ", slave_states[state]);
|
||||
print_string(PRINT_ANY,
|
||||
"state",
|
||||
"state %s ",
|
||||
slave_states[state]);
|
||||
}
|
||||
|
||||
static const char *slave_mii_status[] = {
|
||||
|
|
@ -54,9 +57,15 @@ static void print_slave_mii_status(FILE *f, struct rtattr *tb)
|
|||
unsigned int status = rta_getattr_u8(tb);
|
||||
|
||||
if (status >= ARRAY_SIZE(slave_mii_status))
|
||||
fprintf(f, "mii_status %d ", status);
|
||||
print_int(PRINT_ANY,
|
||||
"mii_status_index",
|
||||
"mii_status %d ",
|
||||
status);
|
||||
else
|
||||
fprintf(f, "mii_status %s ", slave_mii_status[status]);
|
||||
print_string(PRINT_ANY,
|
||||
"mii_status",
|
||||
"mii_status %s ",
|
||||
slave_mii_status[status]);
|
||||
}
|
||||
|
||||
static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
||||
|
|
@ -72,30 +81,42 @@ static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *t
|
|||
print_slave_mii_status(f, tb[IFLA_BOND_SLAVE_MII_STATUS]);
|
||||
|
||||
if (tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT])
|
||||
fprintf(f, "link_failure_count %d ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT]));
|
||||
print_int(PRINT_ANY,
|
||||
"link_failure_count",
|
||||
"link_failure_count %d ",
|
||||
rta_getattr_u32(tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT]));
|
||||
|
||||
if (tb[IFLA_BOND_SLAVE_PERM_HWADDR])
|
||||
fprintf(f, "perm_hwaddr %s ",
|
||||
ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_SLAVE_PERM_HWADDR]),
|
||||
RTA_PAYLOAD(tb[IFLA_BOND_SLAVE_PERM_HWADDR]),
|
||||
0, b1, sizeof(b1)));
|
||||
print_string(PRINT_ANY,
|
||||
"perm_hwaddr",
|
||||
"perm_hwaddr %s ",
|
||||
ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_SLAVE_PERM_HWADDR]),
|
||||
RTA_PAYLOAD(tb[IFLA_BOND_SLAVE_PERM_HWADDR]),
|
||||
0, b1, sizeof(b1)));
|
||||
|
||||
if (tb[IFLA_BOND_SLAVE_QUEUE_ID])
|
||||
fprintf(f, "queue_id %d ",
|
||||
rta_getattr_u16(tb[IFLA_BOND_SLAVE_QUEUE_ID]));
|
||||
print_int(PRINT_ANY,
|
||||
"queue_id",
|
||||
"queue_id %d ",
|
||||
rta_getattr_u16(tb[IFLA_BOND_SLAVE_QUEUE_ID]));
|
||||
|
||||
if (tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID])
|
||||
fprintf(f, "ad_aggregator_id %d ",
|
||||
rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID]));
|
||||
print_int(PRINT_ANY,
|
||||
"ad_aggregator_id",
|
||||
"ad_aggregator_id %d ",
|
||||
rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID]));
|
||||
|
||||
if (tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE])
|
||||
fprintf(f, "ad_actor_oper_port_state %d ",
|
||||
rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]));
|
||||
print_int(PRINT_ANY,
|
||||
"ad_actor_oper_port_state",
|
||||
"ad_actor_oper_port_state %d ",
|
||||
rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]));
|
||||
|
||||
if (tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE])
|
||||
fprintf(f, "ad_partner_oper_port_state %d ",
|
||||
rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]));
|
||||
print_int(PRINT_ANY,
|
||||
"ad_partner_oper_port_state",
|
||||
"ad_partner_oper_port_state %d ",
|
||||
rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]));
|
||||
}
|
||||
|
||||
static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||
|
|
|
|||
|
|
@ -373,45 +373,81 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void _bridge_print_timer(FILE *f,
|
||||
const char *attr,
|
||||
struct rtattr *timer)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
__jiffies_to_tv(&tv, rta_getattr_u64(timer));
|
||||
if (is_json_context()) {
|
||||
json_writer_t *jw = get_json_writer();
|
||||
|
||||
jsonw_name(jw, attr);
|
||||
jsonw_printf(jw, "%i.%.2i",
|
||||
(int)tv.tv_sec,
|
||||
(int)tv.tv_usec / 10000);
|
||||
} else {
|
||||
fprintf(f, "%s %4i.%.2i ", attr, (int)tv.tv_sec,
|
||||
(int)tv.tv_usec / 10000);
|
||||
}
|
||||
}
|
||||
|
||||
static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
||||
{
|
||||
if (!tb)
|
||||
return;
|
||||
|
||||
if (tb[IFLA_BR_FORWARD_DELAY])
|
||||
fprintf(f, "forward_delay %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_FORWARD_DELAY]));
|
||||
print_uint(PRINT_ANY,
|
||||
"forward_delay",
|
||||
"forward_delay %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_FORWARD_DELAY]));
|
||||
|
||||
if (tb[IFLA_BR_HELLO_TIME])
|
||||
fprintf(f, "hello_time %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_HELLO_TIME]));
|
||||
print_uint(PRINT_ANY,
|
||||
"hello_time",
|
||||
"hello_time %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_HELLO_TIME]));
|
||||
|
||||
if (tb[IFLA_BR_MAX_AGE])
|
||||
fprintf(f, "max_age %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_MAX_AGE]));
|
||||
print_uint(PRINT_ANY,
|
||||
"max_age",
|
||||
"max_age %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_MAX_AGE]));
|
||||
|
||||
if (tb[IFLA_BR_AGEING_TIME])
|
||||
fprintf(f, "ageing_time %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_AGEING_TIME]));
|
||||
print_uint(PRINT_ANY,
|
||||
"ageing_time",
|
||||
"ageing_time %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_AGEING_TIME]));
|
||||
|
||||
if (tb[IFLA_BR_STP_STATE])
|
||||
fprintf(f, "stp_state %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_STP_STATE]));
|
||||
print_uint(PRINT_ANY,
|
||||
"stp_state",
|
||||
"stp_state %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_STP_STATE]));
|
||||
|
||||
if (tb[IFLA_BR_PRIORITY])
|
||||
fprintf(f, "priority %u ",
|
||||
rta_getattr_u16(tb[IFLA_BR_PRIORITY]));
|
||||
print_uint(PRINT_ANY,
|
||||
"priority",
|
||||
"priority %u ",
|
||||
rta_getattr_u16(tb[IFLA_BR_PRIORITY]));
|
||||
|
||||
if (tb[IFLA_BR_VLAN_FILTERING])
|
||||
fprintf(f, "vlan_filtering %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_VLAN_FILTERING]));
|
||||
print_uint(PRINT_ANY,
|
||||
"vlan_filtering",
|
||||
"vlan_filtering %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_VLAN_FILTERING]));
|
||||
|
||||
if (tb[IFLA_BR_VLAN_PROTOCOL]) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
fprintf(f, "vlan_protocol %s ",
|
||||
ll_proto_n2a(rta_getattr_u16(tb[IFLA_BR_VLAN_PROTOCOL]),
|
||||
b1, sizeof(b1)));
|
||||
print_string(PRINT_ANY,
|
||||
"vlan_protocol",
|
||||
"vlan_protocol %s ",
|
||||
ll_proto_n2a(rta_getattr_u16(tb[IFLA_BR_VLAN_PROTOCOL]),
|
||||
b1, sizeof(b1)));
|
||||
}
|
||||
|
||||
if (tb[IFLA_BR_BRIDGE_ID]) {
|
||||
|
|
@ -419,7 +455,10 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
|
||||
br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), bridge_id,
|
||||
sizeof(bridge_id));
|
||||
fprintf(f, "bridge_id %s ", bridge_id);
|
||||
print_string(PRINT_ANY,
|
||||
"bridge_id",
|
||||
"bridge_id %s ",
|
||||
bridge_id);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BR_ROOT_ID]) {
|
||||
|
|
@ -427,163 +466,201 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
|
||||
br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), root_id,
|
||||
sizeof(root_id));
|
||||
fprintf(f, "designated_root %s ", root_id);
|
||||
print_string(PRINT_ANY,
|
||||
"root_id",
|
||||
"designated_root %s ",
|
||||
root_id);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BR_ROOT_PORT])
|
||||
fprintf(f, "root_port %u ",
|
||||
rta_getattr_u16(tb[IFLA_BR_ROOT_PORT]));
|
||||
print_uint(PRINT_ANY,
|
||||
"root_port",
|
||||
"root_port %u ",
|
||||
rta_getattr_u16(tb[IFLA_BR_ROOT_PORT]));
|
||||
|
||||
if (tb[IFLA_BR_ROOT_PATH_COST])
|
||||
fprintf(f, "root_path_cost %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_ROOT_PATH_COST]));
|
||||
print_uint(PRINT_ANY,
|
||||
"root_path_cost",
|
||||
"root_path_cost %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_ROOT_PATH_COST]));
|
||||
|
||||
if (tb[IFLA_BR_TOPOLOGY_CHANGE])
|
||||
fprintf(f, "topology_change %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE]));
|
||||
print_uint(PRINT_ANY,
|
||||
"topology_change",
|
||||
"topology_change %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE]));
|
||||
|
||||
if (tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED])
|
||||
fprintf(f, "topology_change_detected %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED]));
|
||||
print_uint(PRINT_ANY,
|
||||
"topology_change_detected",
|
||||
"topology_change_detected %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED]));
|
||||
|
||||
if (tb[IFLA_BR_HELLO_TIMER]) {
|
||||
struct timeval tv;
|
||||
if (tb[IFLA_BR_HELLO_TIMER])
|
||||
_bridge_print_timer(f, "hello_timer", tb[IFLA_BR_HELLO_TIMER]);
|
||||
|
||||
__jiffies_to_tv(&tv, rta_getattr_u64(tb[IFLA_BR_HELLO_TIMER]));
|
||||
fprintf(f, "hello_timer %4i.%.2i ", (int)tv.tv_sec,
|
||||
(int)tv.tv_usec/10000);
|
||||
}
|
||||
if (tb[IFLA_BR_TCN_TIMER])
|
||||
_bridge_print_timer(f, "tcn_timer", tb[IFLA_BR_TCN_TIMER]);
|
||||
|
||||
if (tb[IFLA_BR_TCN_TIMER]) {
|
||||
struct timeval tv;
|
||||
if (tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER])
|
||||
_bridge_print_timer(f, "topology_change_timer",
|
||||
tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]);
|
||||
|
||||
__jiffies_to_tv(&tv, rta_getattr_u64(tb[IFLA_BR_TCN_TIMER]));
|
||||
fprintf(f, "tcn_timer %4i.%.2i ", (int)tv.tv_sec,
|
||||
(int)tv.tv_usec/10000);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]) {
|
||||
unsigned long jiffies;
|
||||
struct timeval tv;
|
||||
|
||||
jiffies = rta_getattr_u64(tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]);
|
||||
__jiffies_to_tv(&tv, jiffies);
|
||||
fprintf(f, "topology_change_timer %4i.%.2i ", (int)tv.tv_sec,
|
||||
(int)tv.tv_usec/10000);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BR_GC_TIMER]) {
|
||||
struct timeval tv;
|
||||
|
||||
__jiffies_to_tv(&tv, rta_getattr_u64(tb[IFLA_BR_GC_TIMER]));
|
||||
fprintf(f, "gc_timer %4i.%.2i ", (int)tv.tv_sec,
|
||||
(int)tv.tv_usec/10000);
|
||||
}
|
||||
if (tb[IFLA_BR_GC_TIMER])
|
||||
_bridge_print_timer(f, "gc_timer", tb[IFLA_BR_GC_TIMER]);
|
||||
|
||||
if (tb[IFLA_BR_VLAN_DEFAULT_PVID])
|
||||
fprintf(f, "vlan_default_pvid %u ",
|
||||
rta_getattr_u16(tb[IFLA_BR_VLAN_DEFAULT_PVID]));
|
||||
print_uint(PRINT_ANY,
|
||||
"vlan_default_pvid",
|
||||
"vlan_default_pvid %u ",
|
||||
rta_getattr_u16(tb[IFLA_BR_VLAN_DEFAULT_PVID]));
|
||||
|
||||
if (tb[IFLA_BR_VLAN_STATS_ENABLED])
|
||||
fprintf(f, "vlan_stats_enabled %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]));
|
||||
print_uint(PRINT_ANY,
|
||||
"vlan_stats_enabled",
|
||||
"vlan_stats_enabled %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]));
|
||||
|
||||
if (tb[IFLA_BR_GROUP_FWD_MASK])
|
||||
fprintf(f, "group_fwd_mask %#x ",
|
||||
rta_getattr_u16(tb[IFLA_BR_GROUP_FWD_MASK]));
|
||||
print_0xhex(PRINT_ANY,
|
||||
"group_fwd_mask",
|
||||
"group_fwd_mask %#x ",
|
||||
rta_getattr_u16(tb[IFLA_BR_GROUP_FWD_MASK]));
|
||||
|
||||
if (tb[IFLA_BR_GROUP_ADDR]) {
|
||||
SPRINT_BUF(mac);
|
||||
|
||||
fprintf(f, "group_address %s ",
|
||||
ll_addr_n2a(RTA_DATA(tb[IFLA_BR_GROUP_ADDR]),
|
||||
RTA_PAYLOAD(tb[IFLA_BR_GROUP_ADDR]),
|
||||
1 /*ARPHDR_ETHER*/, mac, sizeof(mac)));
|
||||
print_string(PRINT_ANY,
|
||||
"group_addr",
|
||||
"group_address %s ",
|
||||
ll_addr_n2a(RTA_DATA(tb[IFLA_BR_GROUP_ADDR]),
|
||||
RTA_PAYLOAD(tb[IFLA_BR_GROUP_ADDR]),
|
||||
1 /*ARPHDR_ETHER*/, mac, sizeof(mac)));
|
||||
}
|
||||
|
||||
if (tb[IFLA_BR_MCAST_SNOOPING])
|
||||
fprintf(f, "mcast_snooping %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_SNOOPING]));
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_snooping",
|
||||
"mcast_snooping %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_SNOOPING]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_ROUTER])
|
||||
fprintf(f, "mcast_router %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_ROUTER]));
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_router",
|
||||
"mcast_router %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_ROUTER]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_QUERY_USE_IFADDR])
|
||||
fprintf(f, "mcast_query_use_ifaddr %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_QUERY_USE_IFADDR]));
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_query_use_ifaddr",
|
||||
"mcast_query_use_ifaddr %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_QUERY_USE_IFADDR]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_QUERIER])
|
||||
fprintf(f, "mcast_querier %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_QUERIER]));
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_querier",
|
||||
"mcast_querier %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_QUERIER]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_HASH_ELASTICITY])
|
||||
fprintf(f, "mcast_hash_elasticity %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_ELASTICITY]));
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_hash_elasticity",
|
||||
"mcast_hash_elasticity %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_ELASTICITY]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_HASH_MAX])
|
||||
fprintf(f, "mcast_hash_max %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_MAX]));
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_hash_max",
|
||||
"mcast_hash_max %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_MAX]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_LAST_MEMBER_CNT])
|
||||
fprintf(f, "mcast_last_member_count %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]));
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_last_member_cnt",
|
||||
"mcast_last_member_count %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT])
|
||||
fprintf(f, "mcast_startup_query_count %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]));
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_startup_query_cnt",
|
||||
"mcast_startup_query_count %u ",
|
||||
rta_getattr_u32(tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL])
|
||||
fprintf(f, "mcast_last_member_interval %llu ",
|
||||
rta_getattr_u64(tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]));
|
||||
print_lluint(PRINT_ANY,
|
||||
"mcast_last_member_intvl",
|
||||
"mcast_last_member_interval %llu ",
|
||||
rta_getattr_u64(tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL])
|
||||
fprintf(f, "mcast_membership_interval %llu ",
|
||||
rta_getattr_u64(tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]));
|
||||
print_lluint(PRINT_ANY,
|
||||
"mcast_membership_intvl",
|
||||
"mcast_membership_interval %llu ",
|
||||
rta_getattr_u64(tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_QUERIER_INTVL])
|
||||
fprintf(f, "mcast_querier_interval %llu ",
|
||||
rta_getattr_u64(tb[IFLA_BR_MCAST_QUERIER_INTVL]));
|
||||
print_lluint(PRINT_ANY,
|
||||
"mcast_querier_intvl",
|
||||
"mcast_querier_interval %llu ",
|
||||
rta_getattr_u64(tb[IFLA_BR_MCAST_QUERIER_INTVL]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_QUERY_INTVL])
|
||||
fprintf(f, "mcast_query_interval %llu ",
|
||||
rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_INTVL]));
|
||||
print_lluint(PRINT_ANY,
|
||||
"mcast_query_intvl",
|
||||
"mcast_query_interval %llu ",
|
||||
rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_INTVL]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL])
|
||||
fprintf(f, "mcast_query_response_interval %llu ",
|
||||
rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]));
|
||||
print_lluint(PRINT_ANY,
|
||||
"mcast_query_response_intvl",
|
||||
"mcast_query_response_interval %llu ",
|
||||
rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL])
|
||||
fprintf(f, "mcast_startup_query_interval %llu ",
|
||||
rta_getattr_u64(tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]));
|
||||
print_lluint(PRINT_ANY,
|
||||
"mcast_startup_query_intvl",
|
||||
"mcast_startup_query_interval %llu ",
|
||||
rta_getattr_u64(tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_STATS_ENABLED])
|
||||
fprintf(f, "mcast_stats_enabled %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_STATS_ENABLED]));
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_stats_enabled",
|
||||
"mcast_stats_enabled %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_STATS_ENABLED]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_IGMP_VERSION])
|
||||
fprintf(f, "mcast_igmp_version %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_IGMP_VERSION]));
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_igmp_version",
|
||||
"mcast_igmp_version %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_IGMP_VERSION]));
|
||||
|
||||
if (tb[IFLA_BR_MCAST_MLD_VERSION])
|
||||
fprintf(f, "mcast_mld_version %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_MLD_VERSION]));
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_mld_version",
|
||||
"mcast_mld_version %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_MLD_VERSION]));
|
||||
|
||||
if (tb[IFLA_BR_NF_CALL_IPTABLES])
|
||||
fprintf(f, "nf_call_iptables %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_NF_CALL_IPTABLES]));
|
||||
print_uint(PRINT_ANY,
|
||||
"nf_call_iptables",
|
||||
"nf_call_iptables %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_NF_CALL_IPTABLES]));
|
||||
|
||||
if (tb[IFLA_BR_NF_CALL_IP6TABLES])
|
||||
fprintf(f, "nf_call_ip6tables %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_NF_CALL_IP6TABLES]));
|
||||
print_uint(PRINT_ANY,
|
||||
"nf_call_ip6tables",
|
||||
"nf_call_ip6tables %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_NF_CALL_IP6TABLES]));
|
||||
|
||||
if (tb[IFLA_BR_NF_CALL_ARPTABLES])
|
||||
fprintf(f, "nf_call_arptables %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_NF_CALL_ARPTABLES]));
|
||||
print_uint(PRINT_ANY,
|
||||
"nf_call_arptables",
|
||||
"nf_call_arptables %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_NF_CALL_ARPTABLES]));
|
||||
}
|
||||
|
||||
static void bridge_print_help(struct link_util *lu, int argc, char **argv,
|
||||
FILE *f)
|
||||
FILE *f)
|
||||
{
|
||||
print_explain(f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,14 +56,52 @@ static const char *port_states[] = {
|
|||
static void print_portstate(FILE *f, __u8 state)
|
||||
{
|
||||
if (state <= BR_STATE_BLOCKING)
|
||||
fprintf(f, "state %s ", port_states[state]);
|
||||
print_string(PRINT_ANY,
|
||||
"state",
|
||||
"state %s ",
|
||||
port_states[state]);
|
||||
else
|
||||
fprintf(f, "state (%d) ", state);
|
||||
print_int(PRINT_ANY, "state_index", "state (%d) ", state);
|
||||
}
|
||||
|
||||
static void print_onoff(FILE *f, char *flag, __u8 val)
|
||||
static void _print_onoff(FILE *f, char *json_flag, char *flag, __u8 val)
|
||||
{
|
||||
fprintf(f, "%s %s ", flag, val ? "on" : "off");
|
||||
if (is_json_context())
|
||||
print_bool(PRINT_JSON, flag, NULL, val);
|
||||
else
|
||||
fprintf(f, "%s %s ", flag, val ? "on" : "off");
|
||||
}
|
||||
|
||||
static void _print_hex(FILE *f,
|
||||
const char *json_attr,
|
||||
const char *attr,
|
||||
__u16 val)
|
||||
{
|
||||
if (is_json_context()) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1), "0x%x", val);
|
||||
print_string(PRINT_JSON, json_attr, NULL, b1);
|
||||
} else {
|
||||
fprintf(f, "%s 0x%x ", attr, val);
|
||||
}
|
||||
}
|
||||
|
||||
static void _print_timer(FILE *f, const char *attr, struct rtattr *timer)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
__jiffies_to_tv(&tv, rta_getattr_u64(timer));
|
||||
if (is_json_context()) {
|
||||
json_writer_t *jw = get_json_writer();
|
||||
|
||||
jsonw_name(jw, attr);
|
||||
jsonw_printf(jw, "%i.%.2i",
|
||||
(int)tv.tv_sec, (int)tv.tv_usec / 10000);
|
||||
} else {
|
||||
fprintf(f, "%s %4i.%.2i ", attr, (int)tv.tv_sec,
|
||||
(int)tv.tv_usec / 10000);
|
||||
}
|
||||
}
|
||||
|
||||
static void bridge_slave_print_opt(struct link_util *lu, FILE *f,
|
||||
|
|
@ -76,59 +114,70 @@ static void bridge_slave_print_opt(struct link_util *lu, FILE *f,
|
|||
print_portstate(f, rta_getattr_u8(tb[IFLA_BRPORT_STATE]));
|
||||
|
||||
if (tb[IFLA_BRPORT_PRIORITY])
|
||||
fprintf(f, "priority %d ",
|
||||
rta_getattr_u16(tb[IFLA_BRPORT_PRIORITY]));
|
||||
print_int(PRINT_ANY,
|
||||
"priority",
|
||||
"priority %d ",
|
||||
rta_getattr_u16(tb[IFLA_BRPORT_PRIORITY]));
|
||||
|
||||
if (tb[IFLA_BRPORT_COST])
|
||||
fprintf(f, "cost %d ",
|
||||
rta_getattr_u32(tb[IFLA_BRPORT_COST]));
|
||||
print_int(PRINT_ANY,
|
||||
"cost",
|
||||
"cost %d ",
|
||||
rta_getattr_u32(tb[IFLA_BRPORT_COST]));
|
||||
|
||||
if (tb[IFLA_BRPORT_MODE])
|
||||
print_onoff(f, "hairpin",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_MODE]));
|
||||
_print_onoff(f, "mode", "hairpin",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_MODE]));
|
||||
|
||||
if (tb[IFLA_BRPORT_GUARD])
|
||||
print_onoff(f, "guard",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_GUARD]));
|
||||
_print_onoff(f, "guard", "guard",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_GUARD]));
|
||||
|
||||
if (tb[IFLA_BRPORT_PROTECT])
|
||||
print_onoff(f, "root_block",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_PROTECT]));
|
||||
_print_onoff(f, "protect", "root_block",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_PROTECT]));
|
||||
|
||||
if (tb[IFLA_BRPORT_FAST_LEAVE])
|
||||
print_onoff(f, "fastleave",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_FAST_LEAVE]));
|
||||
_print_onoff(f, "fast_leave", "fastleave",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_FAST_LEAVE]));
|
||||
|
||||
if (tb[IFLA_BRPORT_LEARNING])
|
||||
print_onoff(f, "learning",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_LEARNING]));
|
||||
_print_onoff(f, "learning", "learning",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_LEARNING]));
|
||||
|
||||
if (tb[IFLA_BRPORT_UNICAST_FLOOD])
|
||||
print_onoff(f, "flood",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_UNICAST_FLOOD]));
|
||||
_print_onoff(f, "unicast_flood", "flood",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_UNICAST_FLOOD]));
|
||||
|
||||
if (tb[IFLA_BRPORT_ID])
|
||||
fprintf(f, "port_id 0x%x ",
|
||||
rta_getattr_u16(tb[IFLA_BRPORT_ID]));
|
||||
_print_hex(f, "id", "port_id",
|
||||
rta_getattr_u16(tb[IFLA_BRPORT_ID]));
|
||||
|
||||
if (tb[IFLA_BRPORT_NO])
|
||||
fprintf(f, "port_no 0x%x ",
|
||||
rta_getattr_u16(tb[IFLA_BRPORT_NO]));
|
||||
_print_hex(f, "no", "port_no",
|
||||
rta_getattr_u16(tb[IFLA_BRPORT_NO]));
|
||||
|
||||
if (tb[IFLA_BRPORT_DESIGNATED_PORT])
|
||||
fprintf(f, "designated_port %u ",
|
||||
rta_getattr_u16(tb[IFLA_BRPORT_DESIGNATED_PORT]));
|
||||
print_uint(PRINT_ANY,
|
||||
"designated_port",
|
||||
"designated_port %u ",
|
||||
rta_getattr_u16(tb[IFLA_BRPORT_DESIGNATED_PORT]));
|
||||
|
||||
if (tb[IFLA_BRPORT_DESIGNATED_COST])
|
||||
fprintf(f, "designated_cost %u ",
|
||||
rta_getattr_u16(tb[IFLA_BRPORT_DESIGNATED_COST]));
|
||||
print_uint(PRINT_ANY,
|
||||
"designated_cost",
|
||||
"designated_cost %u ",
|
||||
rta_getattr_u16(tb[IFLA_BRPORT_DESIGNATED_COST]));
|
||||
|
||||
if (tb[IFLA_BRPORT_BRIDGE_ID]) {
|
||||
char bridge_id[32];
|
||||
|
||||
br_dump_bridge_id(RTA_DATA(tb[IFLA_BRPORT_BRIDGE_ID]),
|
||||
bridge_id, sizeof(bridge_id));
|
||||
fprintf(f, "designated_bridge %s ", bridge_id);
|
||||
print_string(PRINT_ANY,
|
||||
"bridge_id",
|
||||
"designated_bridge %s ",
|
||||
bridge_id);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BRPORT_ROOT_ID]) {
|
||||
|
|
@ -136,65 +185,59 @@ static void bridge_slave_print_opt(struct link_util *lu, FILE *f,
|
|||
|
||||
br_dump_bridge_id(RTA_DATA(tb[IFLA_BRPORT_ROOT_ID]),
|
||||
root_id, sizeof(root_id));
|
||||
fprintf(f, "designated_root %s ", root_id);
|
||||
print_string(PRINT_ANY,
|
||||
"root_id",
|
||||
"designated_root %s ", root_id);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BRPORT_HOLD_TIMER]) {
|
||||
struct timeval tv;
|
||||
__u64 htimer;
|
||||
if (tb[IFLA_BRPORT_HOLD_TIMER])
|
||||
_print_timer(f, "hold_timer", tb[IFLA_BRPORT_HOLD_TIMER]);
|
||||
|
||||
htimer = rta_getattr_u64(tb[IFLA_BRPORT_HOLD_TIMER]);
|
||||
__jiffies_to_tv(&tv, htimer);
|
||||
fprintf(f, "hold_timer %4i.%.2i ", (int)tv.tv_sec,
|
||||
(int)tv.tv_usec/10000);
|
||||
}
|
||||
if (tb[IFLA_BRPORT_MESSAGE_AGE_TIMER])
|
||||
_print_timer(f, "message_age_timer",
|
||||
tb[IFLA_BRPORT_MESSAGE_AGE_TIMER]);
|
||||
|
||||
if (tb[IFLA_BRPORT_MESSAGE_AGE_TIMER]) {
|
||||
struct timeval tv;
|
||||
__u64 agetimer;
|
||||
|
||||
agetimer = rta_getattr_u64(tb[IFLA_BRPORT_MESSAGE_AGE_TIMER]);
|
||||
__jiffies_to_tv(&tv, agetimer);
|
||||
fprintf(f, "message_age_timer %4i.%.2i ", (int)tv.tv_sec,
|
||||
(int)tv.tv_usec/10000);
|
||||
}
|
||||
|
||||
if (tb[IFLA_BRPORT_FORWARD_DELAY_TIMER]) {
|
||||
struct timeval tv;
|
||||
__u64 fwdtimer;
|
||||
|
||||
fwdtimer = rta_getattr_u64(tb[IFLA_BRPORT_FORWARD_DELAY_TIMER]);
|
||||
__jiffies_to_tv(&tv, fwdtimer);
|
||||
fprintf(f, "forward_delay_timer %4i.%.2i ", (int)tv.tv_sec,
|
||||
(int)tv.tv_usec/10000);
|
||||
}
|
||||
if (tb[IFLA_BRPORT_FORWARD_DELAY_TIMER])
|
||||
_print_timer(f, "forward_delay_timer",
|
||||
tb[IFLA_BRPORT_FORWARD_DELAY_TIMER]);
|
||||
|
||||
if (tb[IFLA_BRPORT_TOPOLOGY_CHANGE_ACK])
|
||||
fprintf(f, "topology_change_ack %u ",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_TOPOLOGY_CHANGE_ACK]));
|
||||
print_uint(PRINT_ANY,
|
||||
"topology_change_ack",
|
||||
"topology_change_ack %u ",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_TOPOLOGY_CHANGE_ACK]));
|
||||
|
||||
if (tb[IFLA_BRPORT_CONFIG_PENDING])
|
||||
fprintf(f, "config_pending %u ",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_CONFIG_PENDING]));
|
||||
print_uint(PRINT_ANY,
|
||||
"config_pending",
|
||||
"config_pending %u ",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_CONFIG_PENDING]));
|
||||
|
||||
if (tb[IFLA_BRPORT_PROXYARP])
|
||||
print_onoff(f, "proxy_arp",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_PROXYARP]));
|
||||
_print_onoff(f, "proxyarp", "proxy_arp",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_PROXYARP]));
|
||||
|
||||
if (tb[IFLA_BRPORT_PROXYARP_WIFI])
|
||||
print_onoff(f, "proxy_arp_wifi",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_PROXYARP_WIFI]));
|
||||
_print_onoff(f, "proxyarp_wifi", "proxy_arp_wifi",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_PROXYARP_WIFI]));
|
||||
|
||||
if (tb[IFLA_BRPORT_MULTICAST_ROUTER])
|
||||
fprintf(f, "mcast_router %u ",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_MULTICAST_ROUTER]));
|
||||
print_uint(PRINT_ANY,
|
||||
"multicast_router",
|
||||
"mcast_router %u ",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_MULTICAST_ROUTER]));
|
||||
|
||||
if (tb[IFLA_BRPORT_FAST_LEAVE])
|
||||
print_onoff(f, "mcast_fast_leave",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_FAST_LEAVE]));
|
||||
// not printing any json here because
|
||||
// we already printed fast_leave before
|
||||
print_string(PRINT_FP,
|
||||
NULL,
|
||||
"mcast_fast_leave %s ",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_FAST_LEAVE]) ? "on" : "off");
|
||||
|
||||
if (tb[IFLA_BRPORT_MCAST_FLOOD])
|
||||
print_onoff(f, "mcast_flood",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_MCAST_FLOOD]));
|
||||
_print_onoff(f, "mcast_flood", "mcast_flood",
|
||||
rta_getattr_u8(tb[IFLA_BRPORT_MCAST_FLOOD]));
|
||||
}
|
||||
|
||||
static void bridge_slave_parse_on_off(char *arg_name, char *arg_val,
|
||||
|
|
|
|||
275
ip/iplink_can.c
275
ip/iplink_can.c
|
|
@ -89,11 +89,11 @@ static void set_ctrlmode(char *name, char *arg,
|
|||
|
||||
static void print_ctrlmode(FILE *f, __u32 cm)
|
||||
{
|
||||
fprintf(f, "<");
|
||||
#define _PF(cmflag, cmname) \
|
||||
if (cm & cmflag) { \
|
||||
cm &= ~cmflag; \
|
||||
fprintf(f, "%s%s", cmname, cm ? "," : ""); \
|
||||
open_json_array(PRINT_ANY, is_json_context() ? "ctrlmode" : "<");
|
||||
#define _PF(cmflag, cmname) \
|
||||
if (cm & cmflag) { \
|
||||
cm &= ~cmflag; \
|
||||
print_string(PRINT_ANY, NULL, cm ? "%s," : "%s", cmname); \
|
||||
}
|
||||
_PF(CAN_CTRLMODE_LOOPBACK, "LOOPBACK");
|
||||
_PF(CAN_CTRLMODE_LISTENONLY, "LISTEN-ONLY");
|
||||
|
|
@ -105,8 +105,8 @@ static void print_ctrlmode(FILE *f, __u32 cm)
|
|||
_PF(CAN_CTRLMODE_PRESUME_ACK, "PRESUME-ACK");
|
||||
#undef _PF
|
||||
if (cm)
|
||||
fprintf(f, "%x", cm);
|
||||
fprintf(f, "> ");
|
||||
print_hex(PRINT_ANY, NULL, "%x", cm);
|
||||
close_json_array(PRINT_ANY, "> ");
|
||||
}
|
||||
|
||||
static int can_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||
|
|
@ -260,6 +260,14 @@ static const char *can_state_names[CAN_STATE_MAX] = {
|
|||
[CAN_STATE_SLEEPING] = "SLEEPING"
|
||||
};
|
||||
|
||||
static void can_print_json_timing_min_max(const char *attr, int min, int max)
|
||||
{
|
||||
open_json_object(attr);
|
||||
print_int(PRINT_JSON, "min", NULL, min);
|
||||
print_int(PRINT_JSON, "max", NULL, max);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
||||
{
|
||||
if (!tb)
|
||||
|
|
@ -283,24 +291,53 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
struct can_berr_counter *bc =
|
||||
RTA_DATA(tb[IFLA_CAN_BERR_COUNTER]);
|
||||
|
||||
fprintf(f, "(berr-counter tx %d rx %d) ", bc->txerr, bc->rxerr);
|
||||
if (is_json_context()) {
|
||||
open_json_object("berr_counter");
|
||||
print_int(PRINT_JSON, "tx", NULL, bc->txerr);
|
||||
print_int(PRINT_JSON, "rx", NULL, bc->rxerr);
|
||||
close_json_object();
|
||||
} else {
|
||||
fprintf(f, "(berr-counter tx %d rx %d) ",
|
||||
bc->txerr, bc->rxerr);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_RESTART_MS]) {
|
||||
__u32 *restart_ms = RTA_DATA(tb[IFLA_CAN_RESTART_MS]);
|
||||
|
||||
fprintf(f, "restart-ms %d ", *restart_ms);
|
||||
print_int(PRINT_ANY,
|
||||
"restart_ms",
|
||||
"restart-ms %d ",
|
||||
*restart_ms);
|
||||
}
|
||||
|
||||
/* bittiming is irrelevant if fixed bitrate is defined */
|
||||
if (tb[IFLA_CAN_BITTIMING] && !tb[IFLA_CAN_BITRATE_CONST]) {
|
||||
struct can_bittiming *bt = RTA_DATA(tb[IFLA_CAN_BITTIMING]);
|
||||
|
||||
fprintf(f, "\n bitrate %d sample-point %.3f ",
|
||||
bt->bitrate, (float)bt->sample_point / 1000.);
|
||||
fprintf(f, "\n tq %d prop-seg %d phase-seg1 %d phase-seg2 %d sjw %d",
|
||||
bt->tq, bt->prop_seg, bt->phase_seg1, bt->phase_seg2,
|
||||
bt->sjw);
|
||||
if (is_json_context()) {
|
||||
open_json_object("bittiming");
|
||||
print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate);
|
||||
jsonw_float_field_fmt(get_json_writer(),
|
||||
"sample_point", "%.3f",
|
||||
(float) bt->sample_point / 1000.);
|
||||
print_int(PRINT_ANY, "tq", NULL, bt->tq);
|
||||
print_int(PRINT_ANY, "prop_seg", NULL, bt->prop_seg);
|
||||
print_int(PRINT_ANY, "phase_seg1",
|
||||
NULL, bt->phase_seg1);
|
||||
print_int(PRINT_ANY, "phase_seg2",
|
||||
NULL, bt->phase_seg2);
|
||||
print_int(PRINT_ANY, "sjw", NULL, bt->sjw);
|
||||
close_json_object();
|
||||
} else {
|
||||
fprintf(f, "\n bitrate %d sample-point %.3f ",
|
||||
bt->bitrate, (float) bt->sample_point / 1000.);
|
||||
fprintf(f,
|
||||
"\n tq %d prop-seg %d phase-seg1 %d phase-seg2 %d sjw %d",
|
||||
bt->tq, bt->prop_seg,
|
||||
bt->phase_seg1, bt->phase_seg2,
|
||||
bt->sjw);
|
||||
}
|
||||
}
|
||||
|
||||
/* bittiming const is irrelevant if fixed bitrate is defined */
|
||||
|
|
@ -308,40 +345,68 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
struct can_bittiming_const *btc =
|
||||
RTA_DATA(tb[IFLA_CAN_BITTIMING_CONST]);
|
||||
|
||||
fprintf(f, "\n %s: tseg1 %d..%d tseg2 %d..%d "
|
||||
"sjw 1..%d brp %d..%d brp-inc %d",
|
||||
btc->name, btc->tseg1_min, btc->tseg1_max,
|
||||
btc->tseg2_min, btc->tseg2_max, btc->sjw_max,
|
||||
btc->brp_min, btc->brp_max, btc->brp_inc);
|
||||
if (is_json_context()) {
|
||||
open_json_object("bittiming_const");
|
||||
print_string(PRINT_JSON, "name", NULL, btc->name);
|
||||
can_print_json_timing_min_max("tseg1",
|
||||
btc->tseg1_min,
|
||||
btc->tseg1_max);
|
||||
can_print_json_timing_min_max("tseg2",
|
||||
btc->tseg2_min,
|
||||
btc->tseg2_max);
|
||||
can_print_json_timing_min_max("sjw", 1, btc->sjw_max);
|
||||
can_print_json_timing_min_max("brp",
|
||||
btc->brp_min,
|
||||
btc->brp_max);
|
||||
print_int(PRINT_JSON, "brp_inc", NULL, btc->brp_inc);
|
||||
close_json_object();
|
||||
} else {
|
||||
fprintf(f, "\n %s: tseg1 %d..%d tseg2 %d..%d "
|
||||
"sjw 1..%d brp %d..%d brp-inc %d",
|
||||
btc->name, btc->tseg1_min, btc->tseg1_max,
|
||||
btc->tseg2_min, btc->tseg2_max, btc->sjw_max,
|
||||
btc->brp_min, btc->brp_max, btc->brp_inc);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_BITRATE_CONST]) {
|
||||
__u32 *bitrate_const = RTA_DATA(tb[IFLA_CAN_BITRATE_CONST]);
|
||||
int bitrate_cnt = RTA_PAYLOAD(tb[IFLA_CAN_BITRATE_CONST]) /
|
||||
sizeof(*bitrate_const);
|
||||
sizeof(*bitrate_const);
|
||||
int i;
|
||||
__u32 bitrate = 0;
|
||||
|
||||
if (tb[IFLA_CAN_BITTIMING]) {
|
||||
struct can_bittiming *bt =
|
||||
RTA_DATA(tb[IFLA_CAN_BITTIMING]);
|
||||
RTA_DATA(tb[IFLA_CAN_BITTIMING]);
|
||||
bitrate = bt->bitrate;
|
||||
}
|
||||
|
||||
fprintf(f, "\n bitrate %u", bitrate);
|
||||
fprintf(f, "\n [");
|
||||
if (is_json_context()) {
|
||||
print_uint(PRINT_JSON,
|
||||
"bittiming_bitrate",
|
||||
NULL, bitrate);
|
||||
open_json_array(PRINT_JSON, "bitrate_const");
|
||||
for (i = 0; i < bitrate_cnt; ++i)
|
||||
print_uint(PRINT_JSON, NULL, NULL,
|
||||
bitrate_const[i]);
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
} else {
|
||||
fprintf(f, "\n bitrate %u", bitrate);
|
||||
fprintf(f, "\n [");
|
||||
|
||||
for (i = 0; i < bitrate_cnt - 1; ++i) {
|
||||
/* This will keep lines below 80 signs */
|
||||
if (!(i % 6) && i)
|
||||
fprintf(f, "\n ");
|
||||
|
||||
fprintf(f, "%8u, ", bitrate_const[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < bitrate_cnt - 1; ++i) {
|
||||
/* This will keep lines below 80 signs */
|
||||
if (!(i % 6) && i)
|
||||
fprintf(f, "\n ");
|
||||
|
||||
fprintf(f, "%8u, ", bitrate_const[i]);
|
||||
fprintf(f, "%8u ]", bitrate_const[i]);
|
||||
}
|
||||
|
||||
if (!(i % 6) && i)
|
||||
fprintf(f, "\n ");
|
||||
fprintf(f, "%8u ]", bitrate_const[i]);
|
||||
}
|
||||
|
||||
/* data bittiming is irrelevant if fixed bitrate is defined */
|
||||
|
|
@ -349,12 +414,30 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
struct can_bittiming *dbt =
|
||||
RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
|
||||
|
||||
fprintf(f, "\n dbitrate %d dsample-point %.3f ",
|
||||
dbt->bitrate, (float)dbt->sample_point / 1000.);
|
||||
fprintf(f, "\n dtq %d dprop-seg %d dphase-seg1 %d "
|
||||
"dphase-seg2 %d dsjw %d",
|
||||
dbt->tq, dbt->prop_seg, dbt->phase_seg1,
|
||||
dbt->phase_seg2, dbt->sjw);
|
||||
if (is_json_context()) {
|
||||
open_json_object("data_bittiming");
|
||||
print_int(PRINT_JSON, "bitrate", NULL, dbt->bitrate);
|
||||
jsonw_float_field_fmt(get_json_writer(),
|
||||
"sample_point",
|
||||
"%.3f",
|
||||
(float) dbt->sample_point / 1000.);
|
||||
print_int(PRINT_JSON, "tq", NULL, dbt->tq);
|
||||
print_int(PRINT_JSON, "prop_seg", NULL, dbt->prop_seg);
|
||||
print_int(PRINT_JSON, "phase_seg1",
|
||||
NULL, dbt->phase_seg1);
|
||||
print_int(PRINT_JSON, "phase_seg2",
|
||||
NULL, dbt->phase_seg2);
|
||||
print_int(PRINT_JSON, "sjw", NULL, dbt->sjw);
|
||||
close_json_object();
|
||||
} else {
|
||||
fprintf(f, "\n dbitrate %d dsample-point %.3f ",
|
||||
dbt->bitrate,
|
||||
(float) dbt->sample_point / 1000.);
|
||||
fprintf(f, "\n dtq %d dprop-seg %d dphase-seg1 %d "
|
||||
"dphase-seg2 %d dsjw %d",
|
||||
dbt->tq, dbt->prop_seg, dbt->phase_seg1,
|
||||
dbt->phase_seg2, dbt->sjw);
|
||||
}
|
||||
}
|
||||
|
||||
/* data bittiming const is irrelevant if fixed bitrate is defined */
|
||||
|
|
@ -363,63 +446,102 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
struct can_bittiming_const *dbtc =
|
||||
RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING_CONST]);
|
||||
|
||||
fprintf(f, "\n %s: dtseg1 %d..%d dtseg2 %d..%d "
|
||||
"dsjw 1..%d dbrp %d..%d dbrp-inc %d",
|
||||
dbtc->name, dbtc->tseg1_min, dbtc->tseg1_max,
|
||||
dbtc->tseg2_min, dbtc->tseg2_max, dbtc->sjw_max,
|
||||
dbtc->brp_min, dbtc->brp_max, dbtc->brp_inc);
|
||||
if (is_json_context()) {
|
||||
open_json_object("data_bittiming_const");
|
||||
print_string(PRINT_JSON, "name", NULL, dbtc->name);
|
||||
can_print_json_timing_min_max("tseg1",
|
||||
dbtc->tseg1_min,
|
||||
dbtc->tseg1_max);
|
||||
can_print_json_timing_min_max("tseg2",
|
||||
dbtc->tseg2_min,
|
||||
dbtc->tseg2_max);
|
||||
can_print_json_timing_min_max("sjw", 1, dbtc->sjw_max);
|
||||
can_print_json_timing_min_max("brp",
|
||||
dbtc->brp_min,
|
||||
dbtc->brp_max);
|
||||
|
||||
print_int(PRINT_JSON, "brp_inc", NULL, dbtc->brp_inc);
|
||||
close_json_object();
|
||||
} else {
|
||||
fprintf(f, "\n %s: dtseg1 %d..%d dtseg2 %d..%d "
|
||||
"dsjw 1..%d dbrp %d..%d dbrp-inc %d",
|
||||
dbtc->name, dbtc->tseg1_min, dbtc->tseg1_max,
|
||||
dbtc->tseg2_min, dbtc->tseg2_max, dbtc->sjw_max,
|
||||
dbtc->brp_min, dbtc->brp_max, dbtc->brp_inc);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_DATA_BITRATE_CONST]) {
|
||||
__u32 *dbitrate_const =
|
||||
RTA_DATA(tb[IFLA_CAN_DATA_BITRATE_CONST]);
|
||||
RTA_DATA(tb[IFLA_CAN_DATA_BITRATE_CONST]);
|
||||
int dbitrate_cnt =
|
||||
RTA_PAYLOAD(tb[IFLA_CAN_DATA_BITRATE_CONST]) /
|
||||
sizeof(*dbitrate_const);
|
||||
RTA_PAYLOAD(tb[IFLA_CAN_DATA_BITRATE_CONST]) /
|
||||
sizeof(*dbitrate_const);
|
||||
int i;
|
||||
__u32 dbitrate = 0;
|
||||
|
||||
if (tb[IFLA_CAN_DATA_BITTIMING]) {
|
||||
struct can_bittiming *dbt =
|
||||
RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
|
||||
RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
|
||||
dbitrate = dbt->bitrate;
|
||||
}
|
||||
|
||||
fprintf(f, "\n dbitrate %u", dbitrate);
|
||||
fprintf(f, "\n [");
|
||||
if (is_json_context()) {
|
||||
print_uint(PRINT_JSON, "data_bittiming_bitrate",
|
||||
NULL, dbitrate);
|
||||
open_json_array(PRINT_JSON, "data_bitrate_const");
|
||||
for (i = 0; i < dbitrate_cnt; ++i)
|
||||
print_uint(PRINT_JSON, NULL, NULL,
|
||||
dbitrate_const[i]);
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
} else {
|
||||
fprintf(f, "\n dbitrate %u", dbitrate);
|
||||
fprintf(f, "\n [");
|
||||
|
||||
for (i = 0; i < dbitrate_cnt - 1; ++i) {
|
||||
/* This will keep lines below 80 signs */
|
||||
if (!(i % 6) && i)
|
||||
fprintf(f, "\n ");
|
||||
|
||||
fprintf(f, "%8u, ", dbitrate_const[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < dbitrate_cnt - 1; ++i) {
|
||||
/* This will keep lines below 80 signs */
|
||||
if (!(i % 6) && i)
|
||||
fprintf(f, "\n ");
|
||||
|
||||
fprintf(f, "%8u, ", dbitrate_const[i]);
|
||||
fprintf(f, "%8u ]", dbitrate_const[i]);
|
||||
}
|
||||
|
||||
if (!(i % 6) && i)
|
||||
fprintf(f, "\n ");
|
||||
fprintf(f, "%8u ]", dbitrate_const[i]);
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_TERMINATION_CONST] && tb[IFLA_CAN_TERMINATION]) {
|
||||
__u16 *trm = RTA_DATA(tb[IFLA_CAN_TERMINATION]);
|
||||
__u16 *trm_const = RTA_DATA(tb[IFLA_CAN_TERMINATION_CONST]);
|
||||
int trm_cnt = RTA_PAYLOAD(tb[IFLA_CAN_TERMINATION_CONST]) /
|
||||
sizeof(*trm_const);
|
||||
sizeof(*trm_const);
|
||||
int i;
|
||||
|
||||
fprintf(f, "\n termination %hu [ ", *trm);
|
||||
if (is_json_context()) {
|
||||
print_hu(PRINT_JSON, "termination", NULL, *trm);
|
||||
open_json_array(PRINT_JSON, "termination_const");
|
||||
for (i = 0; i < trm_cnt; ++i)
|
||||
print_hu(PRINT_JSON, NULL, NULL, trm_const[i]);
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
} else {
|
||||
fprintf(f, "\n termination %hu [ ", *trm);
|
||||
|
||||
for (i = 0; i < trm_cnt - 1; ++i)
|
||||
fprintf(f, "%hu, ", trm_const[i]);
|
||||
for (i = 0; i < trm_cnt - 1; ++i)
|
||||
fprintf(f, "%hu, ", trm_const[i]);
|
||||
|
||||
fprintf(f, "%hu ]", trm_const[i]);
|
||||
fprintf(f, "%hu ]", trm_const[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_CLOCK]) {
|
||||
struct can_clock *clock = RTA_DATA(tb[IFLA_CAN_CLOCK]);
|
||||
|
||||
fprintf(f, "\n clock %d", clock->freq);
|
||||
print_int(PRINT_ANY,
|
||||
"clock",
|
||||
"\n clock %d",
|
||||
clock->freq);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -431,17 +553,32 @@ static void can_print_xstats(struct link_util *lu,
|
|||
|
||||
if (xstats && RTA_PAYLOAD(xstats) == sizeof(*stats)) {
|
||||
stats = RTA_DATA(xstats);
|
||||
fprintf(f, "\n re-started bus-errors arbit-lost "
|
||||
"error-warn error-pass bus-off");
|
||||
fprintf(f, "\n %-10d %-10d %-10d %-10d %-10d %-10d",
|
||||
stats->restarts, stats->bus_error,
|
||||
stats->arbitration_lost, stats->error_warning,
|
||||
stats->error_passive, stats->bus_off);
|
||||
|
||||
if (is_json_context()) {
|
||||
print_int(PRINT_JSON, "restarts",
|
||||
NULL, stats->restarts);
|
||||
print_int(PRINT_JSON, "bus_error",
|
||||
NULL, stats->bus_error);
|
||||
print_int(PRINT_JSON, "arbitration_lost",
|
||||
NULL, stats->arbitration_lost);
|
||||
print_int(PRINT_JSON, "error_warning",
|
||||
NULL, stats->error_warning);
|
||||
print_int(PRINT_JSON, "error_passive",
|
||||
NULL, stats->error_passive);
|
||||
print_int(PRINT_JSON, "bus_off", NULL, stats->bus_off);
|
||||
} else {
|
||||
fprintf(f, "\n re-started bus-errors arbit-lost "
|
||||
"error-warn error-pass bus-off");
|
||||
fprintf(f, "\n %-10d %-10d %-10d %-10d %-10d %-10d",
|
||||
stats->restarts, stats->bus_error,
|
||||
stats->arbitration_lost, stats->error_warning,
|
||||
stats->error_passive, stats->bus_off);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void can_print_help(struct link_util *lu, int argc, char **argv,
|
||||
FILE *f)
|
||||
FILE *f)
|
||||
{
|
||||
print_usage(f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -237,22 +237,28 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
return;
|
||||
|
||||
vni = rta_getattr_u32(tb[IFLA_GENEVE_ID]);
|
||||
fprintf(f, "id %u ", vni);
|
||||
print_uint(PRINT_ANY, "id", "id %u ", vni);
|
||||
|
||||
if (tb[IFLA_GENEVE_REMOTE]) {
|
||||
__be32 addr = rta_getattr_u32(tb[IFLA_GENEVE_REMOTE]);
|
||||
|
||||
if (addr)
|
||||
fprintf(f, "remote %s ",
|
||||
format_host(AF_INET, 4, &addr));
|
||||
print_string(PRINT_ANY,
|
||||
"remote",
|
||||
"remote %s ",
|
||||
format_host(AF_INET, 4, &addr));
|
||||
} else if (tb[IFLA_GENEVE_REMOTE6]) {
|
||||
struct in6_addr addr;
|
||||
|
||||
memcpy(&addr, RTA_DATA(tb[IFLA_GENEVE_REMOTE6]), sizeof(struct in6_addr));
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&addr)) {
|
||||
if (!IN6_IS_ADDR_MULTICAST(&addr))
|
||||
fprintf(f, "remote %s ",
|
||||
format_host(AF_INET6, sizeof(struct in6_addr), &addr));
|
||||
print_string(PRINT_ANY,
|
||||
"remote6",
|
||||
"remote %s ",
|
||||
format_host(AF_INET6,
|
||||
sizeof(struct in6_addr),
|
||||
&addr));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -260,47 +266,81 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
__u8 ttl = rta_getattr_u8(tb[IFLA_GENEVE_TTL]);
|
||||
|
||||
if (ttl)
|
||||
fprintf(f, "ttl %d ", ttl);
|
||||
print_int(PRINT_ANY, "ttl", "ttl %d ", ttl);
|
||||
}
|
||||
|
||||
if (tb[IFLA_GENEVE_TOS] &&
|
||||
(tos = rta_getattr_u8(tb[IFLA_GENEVE_TOS]))) {
|
||||
if (tos == 1)
|
||||
fprintf(f, "tos inherit ");
|
||||
else
|
||||
fprintf(f, "tos %#x ", tos);
|
||||
if (is_json_context()) {
|
||||
print_0xhex(PRINT_JSON, "tos", "%#x", tos);
|
||||
} else {
|
||||
if (tos == 1) {
|
||||
print_string(PRINT_FP,
|
||||
"tos",
|
||||
"tos %s ",
|
||||
"inherit");
|
||||
} else {
|
||||
fprintf(f, "tos %#x ", tos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_GENEVE_LABEL]) {
|
||||
__u32 label = rta_getattr_u32(tb[IFLA_GENEVE_LABEL]);
|
||||
|
||||
if (label)
|
||||
fprintf(f, "flowlabel %#x ", ntohl(label));
|
||||
print_0xhex(PRINT_ANY,
|
||||
"label",
|
||||
"flowlabel %#x ",
|
||||
ntohl(label));
|
||||
}
|
||||
|
||||
if (tb[IFLA_GENEVE_PORT])
|
||||
fprintf(f, "dstport %u ",
|
||||
rta_getattr_be16(tb[IFLA_GENEVE_PORT]));
|
||||
print_uint(PRINT_ANY,
|
||||
"port",
|
||||
"dstport %u ",
|
||||
rta_getattr_be16(tb[IFLA_GENEVE_PORT]));
|
||||
|
||||
if (tb[IFLA_GENEVE_COLLECT_METADATA])
|
||||
fputs("external ", f);
|
||||
print_bool(PRINT_ANY, "collect_metadata", "external ", true);
|
||||
|
||||
if (tb[IFLA_GENEVE_UDP_CSUM]) {
|
||||
if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_CSUM]))
|
||||
fputs("no", f);
|
||||
fputs("udpcsum ", f);
|
||||
if (is_json_context()) {
|
||||
print_bool(PRINT_JSON,
|
||||
"udp_csum",
|
||||
NULL,
|
||||
rta_getattr_u8(tb[IFLA_GENEVE_UDP_CSUM]));
|
||||
} else {
|
||||
if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_CSUM]))
|
||||
fputs("no", f);
|
||||
fputs("udpcsum ", f);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]) {
|
||||
if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]))
|
||||
fputs("no", f);
|
||||
fputs("udp6zerocsumtx ", f);
|
||||
if (is_json_context()) {
|
||||
print_bool(PRINT_JSON,
|
||||
"udp_zero_csum6_tx",
|
||||
NULL,
|
||||
rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]));
|
||||
} else {
|
||||
if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]))
|
||||
fputs("no", f);
|
||||
fputs("udp6zerocsumtx ", f);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]) {
|
||||
if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]))
|
||||
fputs("no", f);
|
||||
fputs("udp6zerocsumrx ", f);
|
||||
if (is_json_context()) {
|
||||
print_bool(PRINT_JSON,
|
||||
"udp_zero_csum6_rx",
|
||||
NULL,
|
||||
rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]));
|
||||
} else {
|
||||
if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]))
|
||||
fputs("no", f);
|
||||
fputs("udp6zerocsumrx ", f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -110,30 +110,36 @@ static void hsr_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]) < ETH_ALEN)
|
||||
return;
|
||||
|
||||
fprintf(f, "slave1 ");
|
||||
if (tb[IFLA_HSR_SLAVE1])
|
||||
fprintf(f, "%s ",
|
||||
ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE1])));
|
||||
print_string(PRINT_ANY,
|
||||
"slave1",
|
||||
"slave1 %s ",
|
||||
ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE1])));
|
||||
else
|
||||
fprintf(f, "<none> ");
|
||||
print_null(PRINT_ANY, "slave1", "slave1 %s ", "<none>");
|
||||
|
||||
fprintf(f, "slave2 ");
|
||||
if (tb[IFLA_HSR_SLAVE2])
|
||||
fprintf(f, "%s ",
|
||||
ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE2])));
|
||||
print_string(PRINT_ANY,
|
||||
"slave2",
|
||||
"slave2 %s ",
|
||||
ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE2])));
|
||||
else
|
||||
fprintf(f, "<none> ");
|
||||
print_null(PRINT_ANY, "slave2", "slave2 %s ", "<none>");
|
||||
|
||||
if (tb[IFLA_HSR_SEQ_NR])
|
||||
fprintf(f, "sequence %d ",
|
||||
rta_getattr_u16(tb[IFLA_HSR_SEQ_NR]));
|
||||
print_int(PRINT_ANY,
|
||||
"seq_nr",
|
||||
"sequence %d ",
|
||||
rta_getattr_u16(tb[IFLA_HSR_SEQ_NR]));
|
||||
|
||||
if (tb[IFLA_HSR_SUPERVISION_ADDR])
|
||||
fprintf(f, "supervision %s ",
|
||||
ll_addr_n2a(RTA_DATA(tb[IFLA_HSR_SUPERVISION_ADDR]),
|
||||
RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]),
|
||||
ARPHRD_VOID,
|
||||
b1, sizeof(b1)));
|
||||
print_string(PRINT_ANY,
|
||||
"supervision_addr",
|
||||
"supervision %s ",
|
||||
ll_addr_n2a(RTA_DATA(tb[IFLA_HSR_SUPERVISION_ADDR]),
|
||||
RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]),
|
||||
ARPHRD_VOID,
|
||||
b1, sizeof(b1)));
|
||||
}
|
||||
|
||||
static void hsr_print_help(struct link_util *lu, int argc, char **argv,
|
||||
|
|
|
|||
|
|
@ -91,23 +91,43 @@ static void ipoib_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
RTA_PAYLOAD(tb[IFLA_IPOIB_PKEY]) < sizeof(__u16))
|
||||
return;
|
||||
|
||||
fprintf(f, "pkey %#.4x ", rta_getattr_u16(tb[IFLA_IPOIB_PKEY]));
|
||||
__u16 pkey = rta_getattr_u16(tb[IFLA_IPOIB_PKEY]);
|
||||
|
||||
if (is_json_context()) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1), "%#.4x", pkey);
|
||||
print_string(PRINT_JSON, "key", NULL, b1);
|
||||
} else {
|
||||
fprintf(f, "pkey %#.4x ", pkey);
|
||||
}
|
||||
|
||||
if (!tb[IFLA_IPOIB_MODE] ||
|
||||
RTA_PAYLOAD(tb[IFLA_IPOIB_MODE]) < sizeof(__u16))
|
||||
return;
|
||||
|
||||
mode = rta_getattr_u16(tb[IFLA_IPOIB_MODE]);
|
||||
fprintf(f, "mode %s ",
|
||||
|
||||
const char *mode_str =
|
||||
mode == IPOIB_MODE_DATAGRAM ? "datagram" :
|
||||
mode == IPOIB_MODE_CONNECTED ? "connected" :
|
||||
"unknown");
|
||||
mode == IPOIB_MODE_CONNECTED ? "connected" : "unknown";
|
||||
|
||||
print_string(PRINT_ANY, "mode", "mode %s ", mode_str);
|
||||
|
||||
if (!tb[IFLA_IPOIB_UMCAST] ||
|
||||
RTA_PAYLOAD(tb[IFLA_IPOIB_UMCAST]) < sizeof(__u16))
|
||||
return;
|
||||
|
||||
fprintf(f, "umcast %.4x ", rta_getattr_u16(tb[IFLA_IPOIB_UMCAST]));
|
||||
__u16 umcast = rta_getattr_u16(tb[IFLA_IPOIB_UMCAST]);
|
||||
|
||||
if (is_json_context()) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1), "%.4x", umcast);
|
||||
print_string(PRINT_JSON, "umcast", NULL, b1);
|
||||
} else {
|
||||
fprintf(f, "umcast %.4x ", umcast);
|
||||
}
|
||||
}
|
||||
|
||||
static void ipoib_print_help(struct link_util *lu, int argc, char **argv,
|
||||
|
|
|
|||
|
|
@ -68,11 +68,11 @@ static void ipvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
if (tb[IFLA_IPVLAN_MODE]) {
|
||||
if (RTA_PAYLOAD(tb[IFLA_IPVLAN_MODE]) == sizeof(__u16)) {
|
||||
__u16 mode = rta_getattr_u16(tb[IFLA_IPVLAN_MODE]);
|
||||
|
||||
fprintf(f, " mode %s ",
|
||||
mode == IPVLAN_MODE_L2 ? "l2" :
|
||||
const char *mode_str = mode == IPVLAN_MODE_L2 ? "l2" :
|
||||
mode == IPVLAN_MODE_L3 ? "l3" :
|
||||
mode == IPVLAN_MODE_L3S ? "l3s" : "unknown");
|
||||
mode == IPVLAN_MODE_L3S ? "l3s" : "unknown";
|
||||
|
||||
print_string(PRINT_ANY, "mode", " mode %s ", mode_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,13 +193,15 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
|
|||
return;
|
||||
|
||||
mode = rta_getattr_u32(tb[IFLA_MACVLAN_MODE]);
|
||||
fprintf(f, "mode %s ",
|
||||
mode == MACVLAN_MODE_PRIVATE ? "private"
|
||||
: mode == MACVLAN_MODE_VEPA ? "vepa"
|
||||
: mode == MACVLAN_MODE_BRIDGE ? "bridge"
|
||||
: mode == MACVLAN_MODE_PASSTHRU ? "passthru"
|
||||
: mode == MACVLAN_MODE_SOURCE ? "source"
|
||||
: "unknown");
|
||||
print_string(PRINT_ANY,
|
||||
"mode",
|
||||
"mode %s ",
|
||||
mode == MACVLAN_MODE_PRIVATE ? "private"
|
||||
: mode == MACVLAN_MODE_VEPA ? "vepa"
|
||||
: mode == MACVLAN_MODE_BRIDGE ? "bridge"
|
||||
: mode == MACVLAN_MODE_PASSTHRU ? "passthru"
|
||||
: mode == MACVLAN_MODE_SOURCE ? "source"
|
||||
: "unknown");
|
||||
|
||||
if (!tb[IFLA_MACVLAN_FLAGS] ||
|
||||
RTA_PAYLOAD(tb[IFLA_MACVLAN_FLAGS]) < sizeof(__u16))
|
||||
|
|
@ -208,7 +210,7 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
|
|||
flags = rta_getattr_u16(tb[IFLA_MACVLAN_FLAGS]);
|
||||
|
||||
if (flags & MACVLAN_FLAG_NOPROMISC)
|
||||
fprintf(f, "nopromisc ");
|
||||
print_bool(PRINT_ANY, "nopromisc", "nopromisc ", true);
|
||||
|
||||
/* in source mode, there are more options to print */
|
||||
|
||||
|
|
@ -220,7 +222,7 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
|
|||
return;
|
||||
|
||||
count = rta_getattr_u32(tb[IFLA_MACVLAN_MACADDR_COUNT]);
|
||||
fprintf(f, "remotes (%d) ", count);
|
||||
print_int(PRINT_ANY, "macaddr_count", "remotes (%d) ", count);
|
||||
|
||||
if (!tb[IFLA_MACVLAN_MACADDR_DATA])
|
||||
return;
|
||||
|
|
@ -228,18 +230,29 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
|
|||
rta = RTA_DATA(tb[IFLA_MACVLAN_MACADDR_DATA]);
|
||||
len = RTA_PAYLOAD(tb[IFLA_MACVLAN_MACADDR_DATA]);
|
||||
|
||||
open_json_array(PRINT_JSON, "macaddr_data");
|
||||
for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
|
||||
if (rta->rta_type != IFLA_MACVLAN_MACADDR ||
|
||||
RTA_PAYLOAD(rta) < 6)
|
||||
continue;
|
||||
addr = RTA_DATA(rta);
|
||||
fprintf(f, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x ", addr[0],
|
||||
addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||
if (is_json_context()) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1),
|
||||
"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", addr[0],
|
||||
addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||
print_string(PRINT_JSON, NULL, NULL, b1);
|
||||
} else {
|
||||
fprintf(f, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x ", addr[0],
|
||||
addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||
}
|
||||
}
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
}
|
||||
|
||||
static void macvlan_print_help(struct link_util *lu, int argc, char **argv,
|
||||
FILE *f)
|
||||
FILE *f)
|
||||
{
|
||||
print_explain(lu, f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,37 +164,51 @@ static int vlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void vlan_print_map(FILE *f, char *name, struct rtattr *attr)
|
||||
static void vlan_print_map(FILE *f,
|
||||
const char *name_json,
|
||||
const char *name_fp,
|
||||
struct rtattr *attr)
|
||||
{
|
||||
struct ifla_vlan_qos_mapping *m;
|
||||
struct rtattr *i;
|
||||
int rem;
|
||||
|
||||
fprintf(f, "\n %s { ", name);
|
||||
open_json_array(PRINT_JSON, name_json);
|
||||
print_string(PRINT_FP, NULL, "\n %s { ", name_fp);
|
||||
|
||||
rem = RTA_PAYLOAD(attr);
|
||||
for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
||||
m = RTA_DATA(i);
|
||||
fprintf(f, "%u:%u ", m->from, m->to);
|
||||
|
||||
if (is_json_context()) {
|
||||
open_json_object(NULL);
|
||||
print_uint(PRINT_JSON, "from", NULL, m->from);
|
||||
print_uint(PRINT_JSON, "to", NULL, m->to);
|
||||
close_json_object();
|
||||
} else {
|
||||
fprintf(f, "%u:%u ", m->from, m->to);
|
||||
}
|
||||
}
|
||||
fprintf(f, "} ");
|
||||
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
print_string(PRINT_FP, NULL, "%s ", "}");
|
||||
}
|
||||
|
||||
static void vlan_print_flags(FILE *fp, __u32 flags)
|
||||
{
|
||||
fprintf(fp, "<");
|
||||
#define _PF(f) if (flags & VLAN_FLAG_##f) { \
|
||||
flags &= ~VLAN_FLAG_##f; \
|
||||
fprintf(fp, #f "%s", flags ? "," : ""); \
|
||||
}
|
||||
open_json_array(PRINT_ANY, is_json_context() ? "flags" : "<");
|
||||
#define _PF(f) if (flags & VLAN_FLAG_##f) { \
|
||||
flags &= ~VLAN_FLAG_##f; \
|
||||
print_string(PRINT_ANY, NULL, flags ? "%s," : "%s", #f); \
|
||||
}
|
||||
_PF(REORDER_HDR);
|
||||
_PF(GVRP);
|
||||
_PF(MVRP);
|
||||
_PF(LOOSE_BINDING);
|
||||
#undef _PF
|
||||
if (flags)
|
||||
fprintf(fp, "%x", flags);
|
||||
fprintf(fp, "> ");
|
||||
print_hex(PRINT_ANY, NULL, "%x", flags);
|
||||
close_json_array(PRINT_ANY, "> ");
|
||||
}
|
||||
|
||||
static void vlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
||||
|
|
@ -214,13 +228,19 @@ static void vlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
return;
|
||||
|
||||
if (tb[IFLA_VLAN_PROTOCOL])
|
||||
fprintf(f, "protocol %s ",
|
||||
ll_proto_n2a(rta_getattr_u16(tb[IFLA_VLAN_PROTOCOL]),
|
||||
print_string(PRINT_ANY,
|
||||
"protocol",
|
||||
"protocol %s ",
|
||||
ll_proto_n2a(
|
||||
rta_getattr_u16(tb[IFLA_VLAN_PROTOCOL]),
|
||||
b1, sizeof(b1)));
|
||||
else
|
||||
fprintf(f, "protocol 802.1q ");
|
||||
print_string(PRINT_ANY, "protocol", "protocol %s ", "802.1q");
|
||||
|
||||
fprintf(f, "id %u ", rta_getattr_u16(tb[IFLA_VLAN_ID]));
|
||||
print_uint(PRINT_ANY,
|
||||
"id",
|
||||
"id %u ",
|
||||
rta_getattr_u16(tb[IFLA_VLAN_ID]));
|
||||
|
||||
if (tb[IFLA_VLAN_FLAGS]) {
|
||||
if (RTA_PAYLOAD(tb[IFLA_VLAN_FLAGS]) < sizeof(*flags))
|
||||
|
|
@ -229,13 +249,19 @@ static void vlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
vlan_print_flags(f, flags->flags);
|
||||
}
|
||||
if (tb[IFLA_VLAN_INGRESS_QOS])
|
||||
vlan_print_map(f, "ingress-qos-map", tb[IFLA_VLAN_INGRESS_QOS]);
|
||||
vlan_print_map(f,
|
||||
"ingress_qos",
|
||||
"ingress-qos-map",
|
||||
tb[IFLA_VLAN_INGRESS_QOS]);
|
||||
if (tb[IFLA_VLAN_EGRESS_QOS])
|
||||
vlan_print_map(f, "egress-qos-map", tb[IFLA_VLAN_EGRESS_QOS]);
|
||||
vlan_print_map(f,
|
||||
"egress_qos",
|
||||
"egress-qos-map",
|
||||
tb[IFLA_VLAN_EGRESS_QOS]);
|
||||
}
|
||||
|
||||
static void vlan_print_help(struct link_util *lu, int argc, char **argv,
|
||||
FILE *f)
|
||||
FILE *f)
|
||||
{
|
||||
print_explain(f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,10 @@ static void vrf_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
return;
|
||||
|
||||
if (tb[IFLA_VRF_TABLE])
|
||||
fprintf(f, "table %u ", rta_getattr_u32(tb[IFLA_VRF_TABLE]));
|
||||
print_uint(PRINT_ANY,
|
||||
"table",
|
||||
"table %u ",
|
||||
rta_getattr_u32(tb[IFLA_VRF_TABLE]));
|
||||
}
|
||||
|
||||
static void vrf_slave_print_opt(struct link_util *lu, FILE *f,
|
||||
|
|
@ -72,13 +75,15 @@ static void vrf_slave_print_opt(struct link_util *lu, FILE *f,
|
|||
return;
|
||||
|
||||
if (tb[IFLA_VRF_PORT_TABLE]) {
|
||||
fprintf(f, "table %u ",
|
||||
rta_getattr_u32(tb[IFLA_VRF_PORT_TABLE]));
|
||||
print_uint(PRINT_ANY,
|
||||
"table",
|
||||
"table %u ",
|
||||
rta_getattr_u32(tb[IFLA_VRF_PORT_TABLE]));
|
||||
}
|
||||
}
|
||||
|
||||
static void vrf_print_help(struct link_util *lu, int argc, char **argv,
|
||||
FILE *f)
|
||||
FILE *f)
|
||||
{
|
||||
vrf_explain(f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -406,18 +406,22 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
return;
|
||||
|
||||
vni = rta_getattr_u32(tb[IFLA_VXLAN_ID]);
|
||||
fprintf(f, "id %u ", vni);
|
||||
print_uint(PRINT_ANY, "id", "id %u ", vni);
|
||||
|
||||
if (tb[IFLA_VXLAN_GROUP]) {
|
||||
__be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_GROUP]);
|
||||
|
||||
if (addr) {
|
||||
if (IN_MULTICAST(ntohl(addr)))
|
||||
fprintf(f, "group %s ",
|
||||
format_host(AF_INET, 4, &addr));
|
||||
print_string(PRINT_ANY,
|
||||
"group",
|
||||
"group %s ",
|
||||
format_host(AF_INET, 4, &addr));
|
||||
else
|
||||
fprintf(f, "remote %s ",
|
||||
format_host(AF_INET, 4, &addr));
|
||||
print_string(PRINT_ANY,
|
||||
"remote",
|
||||
"remote %s ",
|
||||
format_host(AF_INET, 4, &addr));
|
||||
}
|
||||
} else if (tb[IFLA_VXLAN_GROUP6]) {
|
||||
struct in6_addr addr;
|
||||
|
|
@ -425,11 +429,19 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_GROUP6]), sizeof(struct in6_addr));
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&addr)) {
|
||||
if (IN6_IS_ADDR_MULTICAST(&addr))
|
||||
fprintf(f, "group %s ",
|
||||
format_host(AF_INET6, sizeof(struct in6_addr), &addr));
|
||||
print_string(PRINT_ANY,
|
||||
"group6",
|
||||
"group %s ",
|
||||
format_host(AF_INET6,
|
||||
sizeof(struct in6_addr),
|
||||
&addr));
|
||||
else
|
||||
fprintf(f, "remote %s ",
|
||||
format_host(AF_INET6, sizeof(struct in6_addr), &addr));
|
||||
print_string(PRINT_ANY,
|
||||
"remote6",
|
||||
"remote %s ",
|
||||
format_host(AF_INET6,
|
||||
sizeof(struct in6_addr),
|
||||
&addr));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -437,15 +449,21 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
__be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_LOCAL]);
|
||||
|
||||
if (addr)
|
||||
fprintf(f, "local %s ",
|
||||
format_host(AF_INET, 4, &addr));
|
||||
print_string(PRINT_ANY,
|
||||
"local",
|
||||
"local %s ",
|
||||
format_host(AF_INET, 4, &addr));
|
||||
} else if (tb[IFLA_VXLAN_LOCAL6]) {
|
||||
struct in6_addr addr;
|
||||
|
||||
memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_LOCAL6]), sizeof(struct in6_addr));
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&addr))
|
||||
fprintf(f, "local %s ",
|
||||
format_host(AF_INET6, sizeof(struct in6_addr), &addr));
|
||||
print_string(PRINT_ANY,
|
||||
"local6",
|
||||
"local %s ",
|
||||
format_host(AF_INET6,
|
||||
sizeof(struct in6_addr),
|
||||
&addr));
|
||||
}
|
||||
|
||||
if (tb[IFLA_VXLAN_LINK] &&
|
||||
|
|
@ -453,110 +471,155 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
const char *n = if_indextoname(link, s2);
|
||||
|
||||
if (n)
|
||||
fprintf(f, "dev %s ", n);
|
||||
print_string(PRINT_ANY, "link", "dev %s ", n);
|
||||
else
|
||||
fprintf(f, "dev %u ", link);
|
||||
print_uint(PRINT_ANY, "link_index", "dev %u ", link);
|
||||
}
|
||||
|
||||
if (tb[IFLA_VXLAN_PORT_RANGE]) {
|
||||
const struct ifla_vxlan_port_range *r
|
||||
= RTA_DATA(tb[IFLA_VXLAN_PORT_RANGE]);
|
||||
fprintf(f, "srcport %u %u ", ntohs(r->low), ntohs(r->high));
|
||||
if (is_json_context()) {
|
||||
open_json_object("port_range");
|
||||
print_uint(PRINT_JSON, "low", NULL, ntohs(r->low));
|
||||
print_uint(PRINT_JSON, "high", NULL, ntohs(r->high));
|
||||
close_json_object();
|
||||
} else {
|
||||
fprintf(f, "srcport %u %u ",
|
||||
ntohs(r->low), ntohs(r->high));
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_VXLAN_PORT])
|
||||
fprintf(f, "dstport %u ",
|
||||
rta_getattr_be16(tb[IFLA_VXLAN_PORT]));
|
||||
print_uint(PRINT_ANY,
|
||||
"port",
|
||||
"dstport %u ",
|
||||
rta_getattr_be16(tb[IFLA_VXLAN_PORT]));
|
||||
|
||||
if (tb[IFLA_VXLAN_LEARNING] &&
|
||||
!rta_getattr_u8(tb[IFLA_VXLAN_LEARNING]))
|
||||
fputs("nolearning ", f);
|
||||
if (tb[IFLA_VXLAN_LEARNING]) {
|
||||
__u8 learning = rta_getattr_u8(tb[IFLA_VXLAN_LEARNING]);
|
||||
|
||||
print_bool(PRINT_JSON, "learning", NULL, learning);
|
||||
if (!learning)
|
||||
print_bool(PRINT_FP, NULL, "nolearning ", true);
|
||||
}
|
||||
|
||||
if (tb[IFLA_VXLAN_PROXY] && rta_getattr_u8(tb[IFLA_VXLAN_PROXY]))
|
||||
fputs("proxy ", f);
|
||||
print_bool(PRINT_ANY, "proxy", "proxy ", true);
|
||||
|
||||
if (tb[IFLA_VXLAN_RSC] && rta_getattr_u8(tb[IFLA_VXLAN_RSC]))
|
||||
fputs("rsc ", f);
|
||||
print_bool(PRINT_ANY, "rsc", "rsc ", true);
|
||||
|
||||
if (tb[IFLA_VXLAN_L2MISS] && rta_getattr_u8(tb[IFLA_VXLAN_L2MISS]))
|
||||
fputs("l2miss ", f);
|
||||
print_bool(PRINT_ANY, "l2miss", "l2miss ", true);
|
||||
|
||||
if (tb[IFLA_VXLAN_L3MISS] && rta_getattr_u8(tb[IFLA_VXLAN_L3MISS]))
|
||||
fputs("l3miss ", f);
|
||||
print_bool(PRINT_ANY, "l3miss", "l3miss ", true);
|
||||
|
||||
if (tb[IFLA_VXLAN_TOS] &&
|
||||
(tos = rta_getattr_u8(tb[IFLA_VXLAN_TOS]))) {
|
||||
if (tos == 1)
|
||||
fprintf(f, "tos inherit ");
|
||||
else
|
||||
fprintf(f, "tos %#x ", tos);
|
||||
if (is_json_context()) {
|
||||
print_0xhex(PRINT_JSON, "tos", "%#x", tos);
|
||||
} else {
|
||||
if (tos == 1)
|
||||
fprintf(f, "tos %s ", "inherit");
|
||||
else
|
||||
fprintf(f, "tos %#x ", tos);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_VXLAN_TTL]) {
|
||||
__u8 ttl = rta_getattr_u8(tb[IFLA_VXLAN_TTL]);
|
||||
|
||||
if (ttl)
|
||||
fprintf(f, "ttl %d ", ttl);
|
||||
print_int(PRINT_ANY, "ttl", "ttl %d ", ttl);
|
||||
else
|
||||
print_int(PRINT_JSON, "ttl", NULL, ttl);
|
||||
}
|
||||
|
||||
if (tb[IFLA_VXLAN_LABEL]) {
|
||||
__u32 label = rta_getattr_u32(tb[IFLA_VXLAN_LABEL]);
|
||||
|
||||
if (label)
|
||||
fprintf(f, "flowlabel %#x ", ntohl(label));
|
||||
print_0xhex(PRINT_ANY,
|
||||
"label",
|
||||
"flowlabel %#x ",
|
||||
ntohl(label));
|
||||
}
|
||||
|
||||
if (tb[IFLA_VXLAN_AGEING]) {
|
||||
__u32 age = rta_getattr_u32(tb[IFLA_VXLAN_AGEING]);
|
||||
|
||||
if (age == 0)
|
||||
fprintf(f, "ageing none ");
|
||||
print_uint(PRINT_ANY, "ageing", "ageing none ", 0);
|
||||
else
|
||||
fprintf(f, "ageing %u ", age);
|
||||
print_uint(PRINT_ANY, "ageing", "ageing %u ", age);
|
||||
}
|
||||
|
||||
if (tb[IFLA_VXLAN_LIMIT] &&
|
||||
((maxaddr = rta_getattr_u32(tb[IFLA_VXLAN_LIMIT])) != 0))
|
||||
fprintf(f, "maxaddr %u ", maxaddr);
|
||||
print_uint(PRINT_ANY, "limit", "maxaddr %u ", maxaddr);
|
||||
|
||||
if (tb[IFLA_VXLAN_UDP_CSUM]) {
|
||||
if (!rta_getattr_u8(tb[IFLA_VXLAN_UDP_CSUM]))
|
||||
fputs("no", f);
|
||||
fputs("udpcsum ", f);
|
||||
__u8 udp_csum = rta_getattr_u8(tb[IFLA_VXLAN_UDP_CSUM]);
|
||||
|
||||
if (is_json_context()) {
|
||||
print_bool(PRINT_ANY, "udp_csum", NULL, udp_csum);
|
||||
} else {
|
||||
if (!udp_csum)
|
||||
fputs("no", f);
|
||||
fputs("udpcsum ", f);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]) {
|
||||
if (!rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]))
|
||||
fputs("no", f);
|
||||
fputs("udp6zerocsumtx ", f);
|
||||
__u8 csum6 = rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]);
|
||||
|
||||
if (is_json_context()) {
|
||||
print_bool(PRINT_ANY,
|
||||
"udp_zero_csum6_tx", NULL, csum6);
|
||||
} else {
|
||||
if (!csum6)
|
||||
fputs("no", f);
|
||||
fputs("udp6zerocsumtx ", f);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]) {
|
||||
if (!rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]))
|
||||
fputs("no", f);
|
||||
fputs("udp6zerocsumrx ", f);
|
||||
__u8 csum6 = rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]);
|
||||
|
||||
if (is_json_context()) {
|
||||
print_bool(PRINT_ANY,
|
||||
"udp_zero_csum6_rx",
|
||||
NULL,
|
||||
csum6);
|
||||
} else {
|
||||
if (!csum6)
|
||||
fputs("no", f);
|
||||
fputs("udp6zerocsumrx ", f);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_VXLAN_REMCSUM_TX] &&
|
||||
rta_getattr_u8(tb[IFLA_VXLAN_REMCSUM_TX]))
|
||||
fputs("remcsumtx ", f);
|
||||
print_bool(PRINT_ANY, "remcsum_tx", "remcsumtx ", true);
|
||||
|
||||
if (tb[IFLA_VXLAN_REMCSUM_RX] &&
|
||||
rta_getattr_u8(tb[IFLA_VXLAN_REMCSUM_RX]))
|
||||
fputs("remcsumrx ", f);
|
||||
print_bool(PRINT_ANY, "remcsum_rx", "remcsumrx ", true);
|
||||
|
||||
if (tb[IFLA_VXLAN_COLLECT_METADATA] &&
|
||||
rta_getattr_u8(tb[IFLA_VXLAN_COLLECT_METADATA]))
|
||||
fputs("external ", f);
|
||||
print_bool(PRINT_ANY, "collect_metadata", "external ", true);
|
||||
|
||||
if (tb[IFLA_VXLAN_GBP])
|
||||
fputs("gbp ", f);
|
||||
print_bool(PRINT_ANY, "gbp", "gbp ", true);
|
||||
if (tb[IFLA_VXLAN_GPE])
|
||||
fputs("gpe ", f);
|
||||
print_bool(PRINT_ANY, "gpe", "gpe ", true);
|
||||
}
|
||||
|
||||
static void vxlan_print_help(struct link_util *lu, int argc, char **argv,
|
||||
FILE *f)
|
||||
FILE *f)
|
||||
{
|
||||
print_explain(f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "xdp.h"
|
||||
#include "bpf_util.h"
|
||||
#include "ip_common.h"
|
||||
|
||||
extern int force;
|
||||
|
||||
|
|
@ -93,30 +94,34 @@ void xdp_dump(FILE *fp, struct rtattr *xdp, bool link, bool details)
|
|||
return;
|
||||
|
||||
mode = rta_getattr_u8(tb[IFLA_XDP_ATTACHED]);
|
||||
if (mode == XDP_ATTACHED_NONE)
|
||||
return;
|
||||
else if (details && link)
|
||||
fprintf(fp, "%s prog/xdp", _SL_);
|
||||
else if (mode == XDP_ATTACHED_DRV)
|
||||
fprintf(fp, "xdp");
|
||||
else if (mode == XDP_ATTACHED_SKB)
|
||||
fprintf(fp, "xdpgeneric");
|
||||
else if (mode == XDP_ATTACHED_HW)
|
||||
fprintf(fp, "xdpoffload");
|
||||
else
|
||||
fprintf(fp, "xdp[%u]", mode);
|
||||
if (is_json_context()) {
|
||||
print_uint(PRINT_JSON, "attached", NULL, mode);
|
||||
} else {
|
||||
if (mode == XDP_ATTACHED_NONE)
|
||||
return;
|
||||
else if (details && link)
|
||||
fprintf(fp, "%s prog/xdp", _SL_);
|
||||
else if (mode == XDP_ATTACHED_DRV)
|
||||
fprintf(fp, "xdp");
|
||||
else if (mode == XDP_ATTACHED_SKB)
|
||||
fprintf(fp, "xdpgeneric");
|
||||
else if (mode == XDP_ATTACHED_HW)
|
||||
fprintf(fp, "xdpoffload");
|
||||
else
|
||||
fprintf(fp, "xdp[%u]", mode);
|
||||
|
||||
if (tb[IFLA_XDP_PROG_ID])
|
||||
prog_id = rta_getattr_u32(tb[IFLA_XDP_PROG_ID]);
|
||||
if (!details) {
|
||||
if (prog_id && !link)
|
||||
fprintf(fp, "/id:%u", prog_id);
|
||||
fprintf(fp, " ");
|
||||
return;
|
||||
}
|
||||
if (tb[IFLA_XDP_PROG_ID])
|
||||
prog_id = rta_getattr_u32(tb[IFLA_XDP_PROG_ID]);
|
||||
if (!details) {
|
||||
if (prog_id && !link)
|
||||
fprintf(fp, "/id:%u", prog_id);
|
||||
fprintf(fp, " ");
|
||||
return;
|
||||
}
|
||||
|
||||
if (prog_id) {
|
||||
fprintf(fp, " ");
|
||||
bpf_dump_prog_info(fp, prog_id);
|
||||
if (prog_id) {
|
||||
fprintf(fp, " ");
|
||||
bpf_dump_prog_info(fp, prog_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -561,9 +561,14 @@ static int validate_secy_dump(struct rtattr **attrs)
|
|||
static void print_flag(FILE *f, struct rtattr *attrs[], const char *desc,
|
||||
int field)
|
||||
{
|
||||
if (attrs[field])
|
||||
fprintf(f, "%s %s ", desc,
|
||||
values_on_off[!!rta_getattr_u8(attrs[field])]);
|
||||
if (attrs[field]) {
|
||||
const char *v = values_on_off[!!rta_getattr_u8(attrs[field])];
|
||||
|
||||
if (is_json_context())
|
||||
print_string(PRINT_JSON, desc, NULL, v);
|
||||
else
|
||||
fprintf(f, "%s %s ", desc, v);
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFAULT_CIPHER_NAME "GCM-AES-128"
|
||||
|
|
@ -1017,8 +1022,16 @@ static void macsec_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
return;
|
||||
|
||||
if (tb[IFLA_MACSEC_SCI]) {
|
||||
fprintf(f, "sci %016llx ",
|
||||
ntohll(rta_getattr_u64(tb[IFLA_MACSEC_SCI])));
|
||||
if (is_json_context()) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1), "%016llx",
|
||||
ntohll(rta_getattr_u64(tb[IFLA_MACSEC_SCI])));
|
||||
print_string(PRINT_JSON, "sci", NULL, b1);
|
||||
} else {
|
||||
fprintf(f, "sci %016llx ",
|
||||
ntohll(rta_getattr_u64(tb[IFLA_MACSEC_SCI])));
|
||||
}
|
||||
}
|
||||
|
||||
print_flag(f, tb, "protect", IFLA_MACSEC_PROTECT);
|
||||
|
|
@ -1026,35 +1039,70 @@ static void macsec_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
if (tb[IFLA_MACSEC_CIPHER_SUITE]) {
|
||||
__u64 csid = rta_getattr_u64(tb[IFLA_MACSEC_CIPHER_SUITE]);
|
||||
|
||||
fprintf(f, "cipher %s ", cs_id_to_name(csid));
|
||||
print_string(PRINT_ANY,
|
||||
"cipher_suite",
|
||||
"cipher %s ",
|
||||
cs_id_to_name(csid));
|
||||
}
|
||||
|
||||
if (tb[IFLA_MACSEC_ICV_LEN]) {
|
||||
fprintf(f, "icvlen %hhu ",
|
||||
rta_getattr_u8(tb[IFLA_MACSEC_ICV_LEN]));
|
||||
if (is_json_context()) {
|
||||
char b2[4];
|
||||
|
||||
snprintf(b2, sizeof(b2), "%hhu",
|
||||
rta_getattr_u8(tb[IFLA_MACSEC_ICV_LEN]));
|
||||
print_uint(PRINT_JSON, "icv_len", NULL, atoi(b2));
|
||||
} else {
|
||||
fprintf(f, "icvlen %hhu ",
|
||||
rta_getattr_u8(tb[IFLA_MACSEC_ICV_LEN]));
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_MACSEC_ENCODING_SA]) {
|
||||
fprintf(f, "encodingsa %hhu ",
|
||||
rta_getattr_u8(tb[IFLA_MACSEC_ENCODING_SA]));
|
||||
if (is_json_context()) {
|
||||
char b2[4];
|
||||
|
||||
snprintf(b2, sizeof(b2), "%hhu",
|
||||
rta_getattr_u8(tb[IFLA_MACSEC_ENCODING_SA]));
|
||||
print_uint(PRINT_JSON, "encoding_sa", NULL, atoi(b2));
|
||||
} else {
|
||||
fprintf(f, "encodingsa %hhu ",
|
||||
rta_getattr_u8(tb[IFLA_MACSEC_ENCODING_SA]));
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_MACSEC_VALIDATION]) {
|
||||
__u8 val = rta_getattr_u8(tb[IFLA_MACSEC_VALIDATION]);
|
||||
|
||||
fprintf(f, "validate %s ", VALIDATE_STR[val]);
|
||||
print_string(PRINT_ANY,
|
||||
"validation",
|
||||
"validate %s ",
|
||||
VALIDATE_STR[val]);
|
||||
}
|
||||
|
||||
const char *inc_sci, *es, *replay;
|
||||
|
||||
if (is_json_context()) {
|
||||
inc_sci = "inc_sci";
|
||||
replay = "replay_protect";
|
||||
es = "es";
|
||||
} else {
|
||||
inc_sci = "send_sci";
|
||||
es = "end_station";
|
||||
replay = "replay";
|
||||
}
|
||||
|
||||
print_flag(f, tb, "encrypt", IFLA_MACSEC_ENCRYPT);
|
||||
print_flag(f, tb, "send_sci", IFLA_MACSEC_INC_SCI);
|
||||
print_flag(f, tb, "end_station", IFLA_MACSEC_ES);
|
||||
print_flag(f, tb, inc_sci, IFLA_MACSEC_INC_SCI);
|
||||
print_flag(f, tb, es, IFLA_MACSEC_ES);
|
||||
print_flag(f, tb, "scb", IFLA_MACSEC_SCB);
|
||||
print_flag(f, tb, replay, IFLA_MACSEC_REPLAY_PROTECT);
|
||||
|
||||
print_flag(f, tb, "replay", IFLA_MACSEC_REPLAY_PROTECT);
|
||||
if (tb[IFLA_MACSEC_WINDOW]) {
|
||||
fprintf(f, "window %d ",
|
||||
rta_getattr_u32(tb[IFLA_MACSEC_WINDOW]));
|
||||
}
|
||||
if (tb[IFLA_MACSEC_WINDOW])
|
||||
print_int(PRINT_ANY,
|
||||
"window",
|
||||
"window %d ",
|
||||
rta_getattr_u32(tb[IFLA_MACSEC_WINDOW]));
|
||||
}
|
||||
|
||||
static bool check_txsc_flags(bool es, bool scb, bool sci)
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ static void usage(void)
|
|||
fprintf(stderr, "TIME := NUMBER[s|ms]\n");
|
||||
fprintf(stderr, "BOOL := [1|0]\n");
|
||||
fprintf(stderr, "FEATURES := ecn\n");
|
||||
fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 | seg6 ]\n");
|
||||
fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 | seg6 | seg6local ]\n");
|
||||
fprintf(stderr, "ENCAPHDR := [ MPLSLABEL | SEG6HDR ]\n");
|
||||
fprintf(stderr, "SEG6HDR := [ mode SEGMODE ] segs ADDR1,ADDRi,ADDRn [hmac HMACKEYID] [cleanup]\n");
|
||||
fprintf(stderr, "SEGMODE := [ encap | inline ]\n");
|
||||
|
|
@ -698,6 +698,8 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
|
|||
fprintf(fp, "onlink ");
|
||||
if (nh->rtnh_flags & RTNH_F_PERVASIVE)
|
||||
fprintf(fp, "pervasive ");
|
||||
if (nh->rtnh_flags & RTNH_F_OFFLOAD)
|
||||
fprintf(fp, "offload ");
|
||||
if (nh->rtnh_flags & RTNH_F_LINKDOWN)
|
||||
fprintf(fp, "linkdown ");
|
||||
len -= NLMSG_ALIGN(nh->rtnh_len);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include <linux/seg6.h>
|
||||
#include <linux/seg6_iptunnel.h>
|
||||
#include <linux/seg6_hmac.h>
|
||||
#include <linux/seg6_local.h>
|
||||
#include <net/if.h>
|
||||
|
||||
static const char *format_encap_type(int type)
|
||||
{
|
||||
|
|
@ -45,6 +47,8 @@ static const char *format_encap_type(int type)
|
|||
return "bpf";
|
||||
case LWTUNNEL_ENCAP_SEG6:
|
||||
return "seg6";
|
||||
case LWTUNNEL_ENCAP_SEG6_LOCAL:
|
||||
return "seg6local";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
|
|
@ -77,30 +81,18 @@ static int read_encap_type(const char *name)
|
|||
return LWTUNNEL_ENCAP_BPF;
|
||||
else if (strcmp(name, "seg6") == 0)
|
||||
return LWTUNNEL_ENCAP_SEG6;
|
||||
else if (strcmp(name, "seg6local") == 0)
|
||||
return LWTUNNEL_ENCAP_SEG6_LOCAL;
|
||||
else if (strcmp(name, "help") == 0)
|
||||
encap_type_usage();
|
||||
|
||||
return LWTUNNEL_ENCAP_NONE;
|
||||
}
|
||||
|
||||
static void print_encap_seg6(FILE *fp, struct rtattr *encap)
|
||||
static void print_srh(FILE *fp, struct ipv6_sr_hdr *srh)
|
||||
{
|
||||
struct rtattr *tb[SEG6_IPTUNNEL_MAX+1];
|
||||
struct seg6_iptunnel_encap *tuninfo;
|
||||
struct ipv6_sr_hdr *srh;
|
||||
int i;
|
||||
|
||||
parse_rtattr_nested(tb, SEG6_IPTUNNEL_MAX, encap);
|
||||
|
||||
if (!tb[SEG6_IPTUNNEL_SRH])
|
||||
return;
|
||||
|
||||
tuninfo = RTA_DATA(tb[SEG6_IPTUNNEL_SRH]);
|
||||
fprintf(fp, "mode %s ",
|
||||
(tuninfo->mode == SEG6_IPTUN_MODE_ENCAP) ? "encap" : "inline");
|
||||
|
||||
srh = tuninfo->srh;
|
||||
|
||||
fprintf(fp, "segs %d [ ", srh->first_segment + 1);
|
||||
|
||||
for (i = srh->first_segment; i >= 0; i--)
|
||||
|
|
@ -118,6 +110,136 @@ static void print_encap_seg6(FILE *fp, struct rtattr *encap)
|
|||
}
|
||||
}
|
||||
|
||||
static const char *seg6_mode_types[] = {
|
||||
[SEG6_IPTUN_MODE_INLINE] = "inline",
|
||||
[SEG6_IPTUN_MODE_ENCAP] = "encap",
|
||||
[SEG6_IPTUN_MODE_L2ENCAP] = "l2encap",
|
||||
};
|
||||
|
||||
static const char *format_seg6mode_type(int mode)
|
||||
{
|
||||
if (mode < 0 || mode > ARRAY_SIZE(seg6_mode_types))
|
||||
return "<unknown>";
|
||||
|
||||
return seg6_mode_types[mode];
|
||||
}
|
||||
|
||||
static int read_seg6mode_type(const char *mode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(seg6_mode_types); i++) {
|
||||
if (strcmp(mode, seg6_mode_types[i]) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void print_encap_seg6(FILE *fp, struct rtattr *encap)
|
||||
{
|
||||
struct rtattr *tb[SEG6_IPTUNNEL_MAX+1];
|
||||
struct seg6_iptunnel_encap *tuninfo;
|
||||
|
||||
parse_rtattr_nested(tb, SEG6_IPTUNNEL_MAX, encap);
|
||||
|
||||
if (!tb[SEG6_IPTUNNEL_SRH])
|
||||
return;
|
||||
|
||||
tuninfo = RTA_DATA(tb[SEG6_IPTUNNEL_SRH]);
|
||||
fprintf(fp, "mode %s ", format_seg6mode_type(tuninfo->mode));
|
||||
|
||||
print_srh(fp, tuninfo->srh);
|
||||
}
|
||||
|
||||
static const char *seg6_action_names[SEG6_LOCAL_ACTION_MAX + 1] = {
|
||||
[SEG6_LOCAL_ACTION_END] = "End",
|
||||
[SEG6_LOCAL_ACTION_END_X] = "End.X",
|
||||
[SEG6_LOCAL_ACTION_END_T] = "End.T",
|
||||
[SEG6_LOCAL_ACTION_END_DX2] = "End.DX2",
|
||||
[SEG6_LOCAL_ACTION_END_DX6] = "End.DX6",
|
||||
[SEG6_LOCAL_ACTION_END_DX4] = "End.DX4",
|
||||
[SEG6_LOCAL_ACTION_END_DT6] = "End.DT6",
|
||||
[SEG6_LOCAL_ACTION_END_DT4] = "End.DT4",
|
||||
[SEG6_LOCAL_ACTION_END_B6] = "End.B6",
|
||||
[SEG6_LOCAL_ACTION_END_B6_ENCAP] = "End.B6.Encaps",
|
||||
[SEG6_LOCAL_ACTION_END_BM] = "End.BM",
|
||||
[SEG6_LOCAL_ACTION_END_S] = "End.S",
|
||||
[SEG6_LOCAL_ACTION_END_AS] = "End.AS",
|
||||
[SEG6_LOCAL_ACTION_END_AM] = "End.AM",
|
||||
};
|
||||
|
||||
static const char *format_action_type(int action)
|
||||
{
|
||||
if (action < 0 || action > SEG6_LOCAL_ACTION_MAX)
|
||||
return "<invalid>";
|
||||
|
||||
return seg6_action_names[action] ?: "<unknown>";
|
||||
}
|
||||
|
||||
static int read_action_type(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SEG6_LOCAL_ACTION_MAX + 1; i++) {
|
||||
if (!seg6_action_names[i])
|
||||
continue;
|
||||
|
||||
if (strcmp(seg6_action_names[i], name) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return SEG6_LOCAL_ACTION_UNSPEC;
|
||||
}
|
||||
|
||||
static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
|
||||
{
|
||||
struct rtattr *tb[SEG6_LOCAL_MAX + 1];
|
||||
char ifbuf[IFNAMSIZ];
|
||||
int action;
|
||||
|
||||
parse_rtattr_nested(tb, SEG6_LOCAL_MAX, encap);
|
||||
|
||||
if (!tb[SEG6_LOCAL_ACTION])
|
||||
return;
|
||||
|
||||
action = rta_getattr_u32(tb[SEG6_LOCAL_ACTION]);
|
||||
|
||||
fprintf(fp, "action %s ", format_action_type(action));
|
||||
|
||||
if (tb[SEG6_LOCAL_SRH]) {
|
||||
fprintf(fp, "srh ");
|
||||
print_srh(fp, RTA_DATA(tb[SEG6_LOCAL_SRH]));
|
||||
}
|
||||
|
||||
if (tb[SEG6_LOCAL_TABLE])
|
||||
fprintf(fp, "table %u ", rta_getattr_u32(tb[SEG6_LOCAL_TABLE]));
|
||||
|
||||
if (tb[SEG6_LOCAL_NH4]) {
|
||||
fprintf(fp, "nh4 %s ",
|
||||
rt_addr_n2a_rta(AF_INET, tb[SEG6_LOCAL_NH4]));
|
||||
}
|
||||
|
||||
if (tb[SEG6_LOCAL_NH6]) {
|
||||
fprintf(fp, "nh6 %s ",
|
||||
rt_addr_n2a_rta(AF_INET6, tb[SEG6_LOCAL_NH6]));
|
||||
}
|
||||
|
||||
if (tb[SEG6_LOCAL_IIF]) {
|
||||
int iif = rta_getattr_u32(tb[SEG6_LOCAL_IIF]);
|
||||
|
||||
fprintf(fp, "iif %s ",
|
||||
if_indextoname(iif, ifbuf) ?: "<unknown>");
|
||||
}
|
||||
|
||||
if (tb[SEG6_LOCAL_OIF]) {
|
||||
int oif = rta_getattr_u32(tb[SEG6_LOCAL_OIF]);
|
||||
|
||||
fprintf(fp, "oif %s ",
|
||||
if_indextoname(oif, ifbuf) ?: "<unknown>");
|
||||
}
|
||||
}
|
||||
|
||||
static void print_encap_mpls(FILE *fp, struct rtattr *encap)
|
||||
{
|
||||
struct rtattr *tb[MPLS_IPTUNNEL_MAX+1];
|
||||
|
|
@ -287,56 +409,20 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
|
|||
case LWTUNNEL_ENCAP_SEG6:
|
||||
print_encap_seg6(fp, encap);
|
||||
break;
|
||||
case LWTUNNEL_ENCAP_SEG6_LOCAL:
|
||||
print_encap_seg6local(fp, encap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp,
|
||||
char ***argvp)
|
||||
static struct ipv6_sr_hdr *parse_srh(char *segbuf, int hmac, bool encap)
|
||||
{
|
||||
int mode_ok = 0, segs_ok = 0, hmac_ok = 0;
|
||||
struct seg6_iptunnel_encap *tuninfo;
|
||||
struct ipv6_sr_hdr *srh;
|
||||
char **argv = *argvp;
|
||||
char segbuf[1024];
|
||||
int argc = *argcp;
|
||||
int encap = -1;
|
||||
__u32 hmac = 0;
|
||||
int nsegs = 0;
|
||||
int srhlen;
|
||||
char *s;
|
||||
int i;
|
||||
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "mode") == 0) {
|
||||
NEXT_ARG();
|
||||
if (mode_ok++)
|
||||
duparg2("mode", *argv);
|
||||
if (strcmp(*argv, "encap") == 0)
|
||||
encap = 1;
|
||||
else if (strcmp(*argv, "inline") == 0)
|
||||
encap = 0;
|
||||
else
|
||||
invarg("\"mode\" value is invalid\n", *argv);
|
||||
} else if (strcmp(*argv, "segs") == 0) {
|
||||
NEXT_ARG();
|
||||
if (segs_ok++)
|
||||
duparg2("segs", *argv);
|
||||
if (encap == -1)
|
||||
invarg("\"segs\" provided before \"mode\"\n",
|
||||
*argv);
|
||||
|
||||
strlcpy(segbuf, *argv, 1024);
|
||||
} else if (strcmp(*argv, "hmac") == 0) {
|
||||
NEXT_ARG();
|
||||
if (hmac_ok++)
|
||||
duparg2("hmac", *argv);
|
||||
get_u32(&hmac, *argv, 0);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
s = segbuf;
|
||||
for (i = 0; *s; *s++ == ',' ? i++ : *s);
|
||||
nsegs = i + 1;
|
||||
|
|
@ -349,15 +435,9 @@ static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp,
|
|||
if (hmac)
|
||||
srhlen += 40;
|
||||
|
||||
tuninfo = malloc(sizeof(*tuninfo) + srhlen);
|
||||
memset(tuninfo, 0, sizeof(*tuninfo) + srhlen);
|
||||
srh = malloc(srhlen);
|
||||
memset(srh, 0, srhlen);
|
||||
|
||||
if (encap)
|
||||
tuninfo->mode = SEG6_IPTUN_MODE_ENCAP;
|
||||
else
|
||||
tuninfo->mode = SEG6_IPTUN_MODE_INLINE;
|
||||
|
||||
srh = tuninfo->srh;
|
||||
srh->hdrlen = (srhlen >> 3) - 1;
|
||||
srh->type = 4;
|
||||
srh->segments_left = nsegs - 1;
|
||||
|
|
@ -381,9 +461,173 @@ static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp,
|
|||
tlv->hmackeyid = htonl(hmac);
|
||||
}
|
||||
|
||||
return srh;
|
||||
}
|
||||
|
||||
static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp,
|
||||
char ***argvp)
|
||||
{
|
||||
int mode_ok = 0, segs_ok = 0, hmac_ok = 0;
|
||||
struct seg6_iptunnel_encap *tuninfo;
|
||||
struct ipv6_sr_hdr *srh;
|
||||
char **argv = *argvp;
|
||||
char segbuf[1024];
|
||||
int argc = *argcp;
|
||||
int encap = -1;
|
||||
__u32 hmac = 0;
|
||||
int srhlen;
|
||||
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "mode") == 0) {
|
||||
NEXT_ARG();
|
||||
if (mode_ok++)
|
||||
duparg2("mode", *argv);
|
||||
encap = read_seg6mode_type(*argv);
|
||||
if (encap < 0)
|
||||
invarg("\"mode\" value is invalid\n", *argv);
|
||||
} else if (strcmp(*argv, "segs") == 0) {
|
||||
NEXT_ARG();
|
||||
if (segs_ok++)
|
||||
duparg2("segs", *argv);
|
||||
if (encap == -1)
|
||||
invarg("\"segs\" provided before \"mode\"\n",
|
||||
*argv);
|
||||
|
||||
strlcpy(segbuf, *argv, 1024);
|
||||
} else if (strcmp(*argv, "hmac") == 0) {
|
||||
NEXT_ARG();
|
||||
if (hmac_ok++)
|
||||
duparg2("hmac", *argv);
|
||||
get_u32(&hmac, *argv, 0);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
srh = parse_srh(segbuf, hmac, encap);
|
||||
srhlen = (srh->hdrlen + 1) << 3;
|
||||
|
||||
tuninfo = malloc(sizeof(*tuninfo) + srhlen);
|
||||
memset(tuninfo, 0, sizeof(*tuninfo) + srhlen);
|
||||
|
||||
tuninfo->mode = encap;
|
||||
|
||||
memcpy(tuninfo->srh, srh, srhlen);
|
||||
|
||||
rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo,
|
||||
sizeof(*tuninfo) + srhlen);
|
||||
|
||||
free(tuninfo);
|
||||
free(srh);
|
||||
|
||||
*argcp = argc + 1;
|
||||
*argvp = argv - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
|
||||
char ***argvp)
|
||||
{
|
||||
int segs_ok = 0, hmac_ok = 0, table_ok = 0, nh4_ok = 0, nh6_ok = 0;
|
||||
int iif_ok = 0, oif_ok = 0, action_ok = 0, srh_ok = 0;
|
||||
__u32 action = 0, table, iif, oif;
|
||||
struct ipv6_sr_hdr *srh;
|
||||
char **argv = *argvp;
|
||||
int argc = *argcp;
|
||||
char segbuf[1024];
|
||||
inet_prefix addr;
|
||||
__u32 hmac = 0;
|
||||
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "action") == 0) {
|
||||
NEXT_ARG();
|
||||
if (action_ok++)
|
||||
duparg2("action", *argv);
|
||||
action = read_action_type(*argv);
|
||||
if (!action)
|
||||
invarg("\"action\" value is invalid\n", *argv);
|
||||
rta_addattr32(rta, len, SEG6_LOCAL_ACTION, action);
|
||||
} else if (strcmp(*argv, "table") == 0) {
|
||||
NEXT_ARG();
|
||||
if (table_ok++)
|
||||
duparg2("table", *argv);
|
||||
get_u32(&table, *argv, 0);
|
||||
rta_addattr32(rta, len, SEG6_LOCAL_TABLE, table);
|
||||
} else if (strcmp(*argv, "nh4") == 0) {
|
||||
NEXT_ARG();
|
||||
if (nh4_ok++)
|
||||
duparg2("nh4", *argv);
|
||||
get_addr(&addr, *argv, AF_INET);
|
||||
rta_addattr_l(rta, len, SEG6_LOCAL_NH4, &addr.data,
|
||||
addr.bytelen);
|
||||
} else if (strcmp(*argv, "nh6") == 0) {
|
||||
NEXT_ARG();
|
||||
if (nh6_ok++)
|
||||
duparg2("nh6", *argv);
|
||||
get_addr(&addr, *argv, AF_INET6);
|
||||
rta_addattr_l(rta, len, SEG6_LOCAL_NH6, &addr.data,
|
||||
addr.bytelen);
|
||||
} else if (strcmp(*argv, "iif") == 0) {
|
||||
NEXT_ARG();
|
||||
if (iif_ok++)
|
||||
duparg2("iif", *argv);
|
||||
iif = if_nametoindex(*argv);
|
||||
if (!iif)
|
||||
invarg("\"iif\" interface not found\n", *argv);
|
||||
rta_addattr32(rta, len, SEG6_LOCAL_IIF, iif);
|
||||
} else if (strcmp(*argv, "oif") == 0) {
|
||||
NEXT_ARG();
|
||||
if (oif_ok++)
|
||||
duparg2("oif", *argv);
|
||||
oif = if_nametoindex(*argv);
|
||||
if (!oif)
|
||||
invarg("\"oif\" interface not found\n", *argv);
|
||||
rta_addattr32(rta, len, SEG6_LOCAL_OIF, oif);
|
||||
} else if (strcmp(*argv, "srh") == 0) {
|
||||
NEXT_ARG();
|
||||
if (srh_ok++)
|
||||
duparg2("srh", *argv);
|
||||
if (strcmp(*argv, "segs") != 0)
|
||||
invarg("missing \"segs\" attribute for srh\n",
|
||||
*argv);
|
||||
NEXT_ARG();
|
||||
if (segs_ok++)
|
||||
duparg2("segs", *argv);
|
||||
strncpy(segbuf, *argv, 1024);
|
||||
segbuf[1023] = 0;
|
||||
if (!NEXT_ARG_OK())
|
||||
break;
|
||||
NEXT_ARG();
|
||||
if (strcmp(*argv, "hmac") == 0) {
|
||||
NEXT_ARG();
|
||||
if (hmac_ok++)
|
||||
duparg2("hmac", *argv);
|
||||
get_u32(&hmac, *argv, 0);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
if (!action) {
|
||||
fprintf(stderr, "Missing action type\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (srh_ok) {
|
||||
int srhlen;
|
||||
|
||||
srh = parse_srh(segbuf, hmac,
|
||||
action == SEG6_LOCAL_ACTION_END_B6_ENCAP);
|
||||
srhlen = (srh->hdrlen + 1) << 3;
|
||||
rta_addattr_l(rta, len, SEG6_LOCAL_SRH, srh, srhlen);
|
||||
free(srh);
|
||||
}
|
||||
|
||||
*argcp = argc + 1;
|
||||
*argvp = argv - 1;
|
||||
|
|
@ -751,6 +995,9 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
|
|||
case LWTUNNEL_ENCAP_SEG6:
|
||||
parse_encap_seg6(rta, len, &argc, &argv);
|
||||
break;
|
||||
case LWTUNNEL_ENCAP_SEG6_LOCAL:
|
||||
parse_encap_seg6local(rta, len, &argc, &argv);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: unsupported encap type\n");
|
||||
break;
|
||||
|
|
|
|||
176
ip/link_gre.c
176
ip/link_gre.c
|
|
@ -26,7 +26,7 @@
|
|||
static void print_usage(FILE *f)
|
||||
{
|
||||
fprintf(f,
|
||||
"Usage: ... { gre | gretap } [ remote ADDR ]\n"
|
||||
"Usage: ... { gre | gretap | erspan } [ remote ADDR ]\n"
|
||||
" [ local ADDR ]\n"
|
||||
" [ [i|o]seq ]\n"
|
||||
" [ [i|o]key KEY ]\n"
|
||||
|
|
@ -44,6 +44,7 @@ static void print_usage(FILE *f)
|
|||
" [ [no]encap-csum6 ]\n"
|
||||
" [ [no]encap-remcsum ]\n"
|
||||
" [ fwmark MARK ]\n"
|
||||
" [ erspan IDX ]\n"
|
||||
"\n"
|
||||
"Where: ADDR := { IP_ADDRESS | any }\n"
|
||||
" TOS := { NUMBER | inherit }\n"
|
||||
|
|
@ -96,6 +97,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
__u8 metadata = 0;
|
||||
__u8 ignore_df = 0;
|
||||
__u32 fwmark = 0;
|
||||
__u32 erspan_idx = 0;
|
||||
|
||||
if (!(n->nlmsg_flags & NLM_F_CREATE)) {
|
||||
if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
|
||||
|
|
@ -172,6 +174,9 @@ get_failed:
|
|||
|
||||
if (greinfo[IFLA_GRE_FWMARK])
|
||||
fwmark = rta_getattr_u32(greinfo[IFLA_GRE_FWMARK]);
|
||||
|
||||
if (greinfo[IFLA_GRE_ERSPAN_INDEX])
|
||||
erspan_idx = rta_getattr_u32(greinfo[IFLA_GRE_ERSPAN_INDEX]);
|
||||
}
|
||||
|
||||
while (argc > 0) {
|
||||
|
|
@ -328,6 +333,12 @@ get_failed:
|
|||
NEXT_ARG();
|
||||
if (get_u32(&fwmark, *argv, 0))
|
||||
invarg("invalid fwmark\n", *argv);
|
||||
} else if (strcmp(*argv, "erspan") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u32(&erspan_idx, *argv, 0))
|
||||
invarg("invalid erspan index\n", *argv);
|
||||
if (erspan_idx & ~((1<<20) - 1) || erspan_idx == 0)
|
||||
invarg("erspan index must be > 0 and <= 20-bit\n", *argv);
|
||||
} else
|
||||
usage();
|
||||
argc--; argv++;
|
||||
|
|
@ -359,6 +370,8 @@ get_failed:
|
|||
addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1);
|
||||
addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1);
|
||||
addattr32(n, 1024, IFLA_GRE_FWMARK, fwmark);
|
||||
if (erspan_idx != 0)
|
||||
addattr32(n, 1024, IFLA_GRE_ERSPAN_INDEX, erspan_idx);
|
||||
} else {
|
||||
addattr_l(n, 1024, IFLA_GRE_COLLECT_METADATA, NULL, 0);
|
||||
}
|
||||
|
|
@ -389,7 +402,7 @@ static void gre_print_direct_opt(FILE *f, struct rtattr *tb[])
|
|||
remote = format_host(AF_INET, 4, &addr);
|
||||
}
|
||||
|
||||
fprintf(f, "remote %s ", remote);
|
||||
print_string(PRINT_ANY, "remote", "remote %s ", remote);
|
||||
|
||||
if (tb[IFLA_GRE_LOCAL]) {
|
||||
unsigned int addr = rta_getattr_u32(tb[IFLA_GRE_LOCAL]);
|
||||
|
|
@ -398,36 +411,52 @@ static void gre_print_direct_opt(FILE *f, struct rtattr *tb[])
|
|||
local = format_host(AF_INET, 4, &addr);
|
||||
}
|
||||
|
||||
fprintf(f, "local %s ", local);
|
||||
print_string(PRINT_ANY, "local", "local %s ", local);
|
||||
|
||||
if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) {
|
||||
unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]);
|
||||
const char *n = if_indextoname(link, s2);
|
||||
|
||||
if (n)
|
||||
fprintf(f, "dev %s ", n);
|
||||
print_string(PRINT_ANY, "link", "dev %s ", n);
|
||||
else
|
||||
fprintf(f, "dev %u ", link);
|
||||
print_uint(PRINT_ANY, "link_index", "dev %u ", link);
|
||||
}
|
||||
|
||||
if (tb[IFLA_GRE_TTL] && rta_getattr_u8(tb[IFLA_GRE_TTL]))
|
||||
fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_GRE_TTL]));
|
||||
else
|
||||
fprintf(f, "ttl inherit ");
|
||||
if (tb[IFLA_GRE_TTL]) {
|
||||
__u8 ttl = rta_getattr_u8(tb[IFLA_GRE_TTL]);
|
||||
|
||||
if (ttl)
|
||||
print_int(PRINT_ANY, "ttl", "ttl %d ", ttl);
|
||||
else
|
||||
print_int(PRINT_JSON, "ttl", NULL, ttl);
|
||||
} else {
|
||||
print_string(PRINT_FP, NULL, "ttl %s ", "inherit");
|
||||
}
|
||||
|
||||
if (tb[IFLA_GRE_TOS] && rta_getattr_u8(tb[IFLA_GRE_TOS])) {
|
||||
int tos = rta_getattr_u8(tb[IFLA_GRE_TOS]);
|
||||
|
||||
fputs("tos ", f);
|
||||
if (tos == 1)
|
||||
fputs("inherit ", f);
|
||||
else
|
||||
fprintf(f, "0x%x ", tos);
|
||||
if (is_json_context()) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1), "0x%x", tos);
|
||||
print_string(PRINT_JSON, "tos", NULL, b1);
|
||||
} else {
|
||||
fputs("tos ", f);
|
||||
if (tos == 1)
|
||||
fputs("inherit ", f);
|
||||
else
|
||||
fprintf(f, "0x%x ", tos);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_GRE_PMTUDISC] &&
|
||||
!rta_getattr_u8(tb[IFLA_GRE_PMTUDISC]))
|
||||
fputs("nopmtudisc ", f);
|
||||
if (tb[IFLA_GRE_PMTUDISC]) {
|
||||
if (!rta_getattr_u8(tb[IFLA_GRE_PMTUDISC]))
|
||||
print_bool(PRINT_ANY, "pmtudisc", "nopmtudisc ", false);
|
||||
else
|
||||
print_bool(PRINT_JSON, "pmtudisc", NULL, true);
|
||||
}
|
||||
|
||||
if (tb[IFLA_GRE_IFLAGS])
|
||||
iflags = rta_getattr_u16(tb[IFLA_GRE_IFLAGS]);
|
||||
|
|
@ -437,26 +466,31 @@ static void gre_print_direct_opt(FILE *f, struct rtattr *tb[])
|
|||
|
||||
if ((iflags & GRE_KEY) && tb[IFLA_GRE_IKEY]) {
|
||||
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2));
|
||||
fprintf(f, "ikey %s ", s2);
|
||||
print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
|
||||
}
|
||||
|
||||
if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) {
|
||||
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2));
|
||||
fprintf(f, "okey %s ", s2);
|
||||
print_string(PRINT_ANY, "okey", "okey %s ", s2);
|
||||
}
|
||||
|
||||
if (iflags & GRE_SEQ)
|
||||
fputs("iseq ", f);
|
||||
print_bool(PRINT_ANY, "iseq", "iseq ", true);
|
||||
if (oflags & GRE_SEQ)
|
||||
fputs("oseq ", f);
|
||||
print_bool(PRINT_ANY, "oseq", "oseq ", true);
|
||||
if (iflags & GRE_CSUM)
|
||||
fputs("icsum ", f);
|
||||
print_bool(PRINT_ANY, "icsum", "icsum ", true);
|
||||
if (oflags & GRE_CSUM)
|
||||
fputs("ocsum ", f);
|
||||
print_bool(PRINT_ANY, "ocsum", "ocsum ", true);
|
||||
|
||||
if (tb[IFLA_GRE_FWMARK] && rta_getattr_u32(tb[IFLA_GRE_FWMARK])) {
|
||||
fprintf(f, "fwmark 0x%x ",
|
||||
rta_getattr_u32(tb[IFLA_GRE_FWMARK]));
|
||||
if (tb[IFLA_GRE_FWMARK]) {
|
||||
__u32 fwmark = rta_getattr_u32(tb[IFLA_GRE_FWMARK]);
|
||||
|
||||
if (fwmark) {
|
||||
snprintf(s2, sizeof(s2), "0x%x", fwmark);
|
||||
|
||||
print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -468,10 +502,16 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
if (!tb[IFLA_GRE_COLLECT_METADATA])
|
||||
gre_print_direct_opt(f, tb);
|
||||
else
|
||||
fputs("external ", f);
|
||||
print_bool(PRINT_ANY, "external", "external ", true);
|
||||
|
||||
if (tb[IFLA_GRE_IGNORE_DF] && rta_getattr_u8(tb[IFLA_GRE_IGNORE_DF]))
|
||||
fputs("ignore-df ", f);
|
||||
print_bool(PRINT_ANY, "ignore_df", "ignore-df ", true);
|
||||
|
||||
if (tb[IFLA_GRE_ERSPAN_INDEX]) {
|
||||
__u32 erspan_idx = rta_getattr_u32(tb[IFLA_GRE_ERSPAN_INDEX]);
|
||||
|
||||
fprintf(f, "erspan_index %u ", erspan_idx);
|
||||
}
|
||||
|
||||
if (tb[IFLA_GRE_ENCAP_TYPE] &&
|
||||
rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) {
|
||||
|
|
@ -480,45 +520,73 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
__u16 sport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_SPORT]);
|
||||
__u16 dport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_DPORT]);
|
||||
|
||||
fputs("encap ", f);
|
||||
|
||||
open_json_object("encap");
|
||||
print_string(PRINT_FP, NULL, "encap ", NULL);
|
||||
|
||||
switch (type) {
|
||||
case TUNNEL_ENCAP_FOU:
|
||||
fputs("fou ", f);
|
||||
print_string(PRINT_ANY, "type", "%s ", "fou");
|
||||
break;
|
||||
case TUNNEL_ENCAP_GUE:
|
||||
fputs("gue ", f);
|
||||
print_string(PRINT_ANY, "type", "%s ", "gue");
|
||||
break;
|
||||
default:
|
||||
fputs("unknown ", f);
|
||||
print_null(PRINT_ANY, "type", "%s ", "unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
if (sport == 0)
|
||||
fputs("encap-sport auto ", f);
|
||||
else
|
||||
fprintf(f, "encap-sport %u", ntohs(sport));
|
||||
if (is_json_context()) {
|
||||
print_uint(PRINT_JSON,
|
||||
"sport",
|
||||
NULL,
|
||||
sport ? ntohs(sport) : 0);
|
||||
print_uint(PRINT_JSON, "dport", NULL, ntohs(dport));
|
||||
|
||||
fprintf(f, "encap-dport %u ", ntohs(dport));
|
||||
print_bool(PRINT_JSON,
|
||||
"csum",
|
||||
NULL,
|
||||
flags & TUNNEL_ENCAP_FLAG_CSUM);
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM)
|
||||
fputs("encap-csum ", f);
|
||||
else
|
||||
fputs("noencap-csum ", f);
|
||||
print_bool(PRINT_JSON,
|
||||
"csum6",
|
||||
NULL,
|
||||
flags & TUNNEL_ENCAP_FLAG_CSUM6);
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
|
||||
fputs("encap-csum6 ", f);
|
||||
else
|
||||
fputs("noencap-csum6 ", f);
|
||||
print_bool(PRINT_JSON,
|
||||
"remcsum",
|
||||
NULL,
|
||||
flags & TUNNEL_ENCAP_FLAG_REMCSUM);
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
|
||||
fputs("encap-remcsum ", f);
|
||||
else
|
||||
fputs("noencap-remcsum ", f);
|
||||
close_json_object();
|
||||
} else {
|
||||
if (sport == 0)
|
||||
fputs("encap-sport auto ", f);
|
||||
else
|
||||
fprintf(f, "encap-sport %u", ntohs(sport));
|
||||
|
||||
fprintf(f, "encap-dport %u ", ntohs(dport));
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM)
|
||||
fputs("encap-csum ", f);
|
||||
else
|
||||
fputs("noencap-csum ", f);
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
|
||||
fputs("encap-csum6 ", f);
|
||||
else
|
||||
fputs("noencap-csum6 ", f);
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
|
||||
fputs("encap-remcsum ", f);
|
||||
else
|
||||
fputs("noencap-remcsum ", f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gre_print_help(struct link_util *lu, int argc, char **argv,
|
||||
FILE *f)
|
||||
FILE *f)
|
||||
{
|
||||
print_usage(f);
|
||||
}
|
||||
|
|
@ -538,3 +606,11 @@ struct link_util gretap_link_util = {
|
|||
.print_opt = gre_print_opt,
|
||||
.print_help = gre_print_help,
|
||||
};
|
||||
|
||||
struct link_util erspan_link_util = {
|
||||
.id = "erspan",
|
||||
.maxattr = IFLA_GRE_MAX,
|
||||
.parse_opt = gre_parse_opt,
|
||||
.print_opt = gre_print_opt,
|
||||
.print_help = gre_print_help,
|
||||
};
|
||||
|
|
|
|||
165
ip/link_gre6.c
165
ip/link_gre6.c
|
|
@ -425,7 +425,7 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
remote = format_host(AF_INET6, sizeof(addr), &addr);
|
||||
}
|
||||
|
||||
fprintf(f, "remote %s ", remote);
|
||||
print_string(PRINT_ANY, "remote", "remote %s ", remote);
|
||||
|
||||
if (tb[IFLA_GRE_LOCAL]) {
|
||||
struct in6_addr addr;
|
||||
|
|
@ -436,43 +436,83 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
local = format_host(AF_INET6, sizeof(addr), &addr);
|
||||
}
|
||||
|
||||
fprintf(f, "local %s ", local);
|
||||
print_string(PRINT_ANY, "local", "local %s ", local);
|
||||
|
||||
if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) {
|
||||
unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]);
|
||||
const char *n = if_indextoname(link, s2);
|
||||
|
||||
if (n)
|
||||
fprintf(f, "dev %s ", n);
|
||||
print_string(PRINT_ANY, "link", "dev %s ", n);
|
||||
else
|
||||
fprintf(f, "dev %u ", link);
|
||||
print_uint(PRINT_ANY, "link_index", "dev %u ", link);
|
||||
}
|
||||
|
||||
if (tb[IFLA_GRE_TTL] && rta_getattr_u8(tb[IFLA_GRE_TTL]))
|
||||
fprintf(f, "hoplimit %d ", rta_getattr_u8(tb[IFLA_GRE_TTL]));
|
||||
if (tb[IFLA_GRE_TTL]) {
|
||||
__u8 ttl = rta_getattr_u8(tb[IFLA_GRE_TTL]);
|
||||
|
||||
if (ttl)
|
||||
print_int(PRINT_ANY, "ttl", "hoplimit %d ", ttl);
|
||||
else
|
||||
print_int(PRINT_JSON, "ttl", NULL, ttl);
|
||||
}
|
||||
|
||||
if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT)
|
||||
fprintf(f, "encaplimit none ");
|
||||
print_bool(PRINT_ANY,
|
||||
"ip6_tnl_f_ign_encap_limit",
|
||||
"encaplimit none ",
|
||||
true);
|
||||
else if (tb[IFLA_GRE_ENCAP_LIMIT]) {
|
||||
int encap_limit = rta_getattr_u8(tb[IFLA_GRE_ENCAP_LIMIT]);
|
||||
|
||||
fprintf(f, "encaplimit %d ", encap_limit);
|
||||
print_int(PRINT_ANY,
|
||||
"encap_limit",
|
||||
"encaplimit %d ",
|
||||
encap_limit);
|
||||
}
|
||||
|
||||
if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
|
||||
fprintf(f, "flowlabel inherit ");
|
||||
else
|
||||
fprintf(f, "flowlabel 0x%05x ",
|
||||
ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
|
||||
if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) {
|
||||
print_bool(PRINT_ANY,
|
||||
"ip6_tnl_f_use_orig_flowlabel",
|
||||
"flowlabel inherit ",
|
||||
true);
|
||||
} else {
|
||||
if (is_json_context()) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
if (flags & IP6_TNL_F_USE_ORIG_TCLASS)
|
||||
fprintf(f, "tclass inherit ");
|
||||
else
|
||||
fprintf(f, "tclass 0x%02x ",
|
||||
ntohl(flowinfo & IP6_FLOWINFO_TCLASS) >> 20);
|
||||
snprintf(b1, sizeof(b1), "0x%05x",
|
||||
ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
|
||||
print_string(PRINT_JSON, "flowlabel", NULL, b1);
|
||||
|
||||
} else {
|
||||
fprintf(f, "flowlabel 0x%05x ",
|
||||
ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & IP6_TNL_F_USE_ORIG_TCLASS) {
|
||||
print_bool(PRINT_ANY,
|
||||
"ip6_tnl_f_use_orig_tclass",
|
||||
"tclass inherit ",
|
||||
true);
|
||||
} else {
|
||||
if (is_json_context()) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1), "0x%05x",
|
||||
ntohl(flowinfo & IP6_FLOWINFO_TCLASS) >> 20);
|
||||
print_string(PRINT_JSON, "tclass", NULL, b1);
|
||||
} else {
|
||||
fprintf(f, "tclass 0x%02x ",
|
||||
ntohl(flowinfo & IP6_FLOWINFO_TCLASS) >> 20);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & IP6_TNL_F_RCV_DSCP_COPY)
|
||||
fprintf(f, "dscp inherit ");
|
||||
print_bool(PRINT_ANY,
|
||||
"ip6_tnl_f_rcv_dscp_copy",
|
||||
"dscp inherit ",
|
||||
true);
|
||||
|
||||
if (tb[IFLA_GRE_IFLAGS])
|
||||
iflags = rta_getattr_u16(tb[IFLA_GRE_IFLAGS]);
|
||||
|
|
@ -482,27 +522,37 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
|
||||
if ((iflags & GRE_KEY) && tb[IFLA_GRE_IKEY]) {
|
||||
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2));
|
||||
fprintf(f, "ikey %s ", s2);
|
||||
print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
|
||||
}
|
||||
|
||||
if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) {
|
||||
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2));
|
||||
fprintf(f, "okey %s ", s2);
|
||||
print_string(PRINT_ANY, "okey", "okey %s ", s2);
|
||||
}
|
||||
|
||||
if (iflags & GRE_SEQ)
|
||||
fputs("iseq ", f);
|
||||
print_bool(PRINT_ANY, "iseq", "iseq ", true);
|
||||
if (oflags & GRE_SEQ)
|
||||
fputs("oseq ", f);
|
||||
print_bool(PRINT_ANY, "oseq", "oseq ", true);
|
||||
if (iflags & GRE_CSUM)
|
||||
fputs("icsum ", f);
|
||||
print_bool(PRINT_ANY, "icsum", "icsum ", true);
|
||||
if (oflags & GRE_CSUM)
|
||||
fputs("ocsum ", f);
|
||||
print_bool(PRINT_ANY, "ocsum", "ocsum ", true);
|
||||
|
||||
if (flags & IP6_TNL_F_USE_ORIG_FWMARK)
|
||||
fprintf(f, "fwmark inherit ");
|
||||
else if (tb[IFLA_GRE_FWMARK] && rta_getattr_u32(tb[IFLA_GRE_FWMARK]))
|
||||
fprintf(f, "fwmark 0x%x ", rta_getattr_u32(tb[IFLA_GRE_FWMARK]));
|
||||
print_bool(PRINT_ANY,
|
||||
"ip6_tnl_f_use_orig_fwmark",
|
||||
"fwmark inherit ",
|
||||
true);
|
||||
else if (tb[IFLA_GRE_FWMARK]) {
|
||||
__u32 fwmark = rta_getattr_u32(tb[IFLA_GRE_FWMARK]);
|
||||
|
||||
if (fwmark) {
|
||||
snprintf(s2, sizeof(s2), "0x%x", fwmark);
|
||||
|
||||
print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_GRE_ENCAP_TYPE] &&
|
||||
rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) {
|
||||
|
|
@ -511,40 +561,57 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
__u16 sport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_SPORT]);
|
||||
__u16 dport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_DPORT]);
|
||||
|
||||
fputs("encap ", f);
|
||||
open_json_object("encap");
|
||||
|
||||
print_string(PRINT_FP, NULL, "encap ", NULL);
|
||||
switch (type) {
|
||||
case TUNNEL_ENCAP_FOU:
|
||||
fputs("fou ", f);
|
||||
print_string(PRINT_ANY, "type", "%s ", "fou");
|
||||
break;
|
||||
case TUNNEL_ENCAP_GUE:
|
||||
fputs("gue ", f);
|
||||
print_string(PRINT_ANY, "type", "%s ", "gue");
|
||||
break;
|
||||
default:
|
||||
fputs("unknown ", f);
|
||||
print_null(PRINT_ANY, "type", "unknown ", NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sport == 0)
|
||||
fputs("encap-sport auto ", f);
|
||||
else
|
||||
fprintf(f, "encap-sport %u", ntohs(sport));
|
||||
if (is_json_context()) {
|
||||
print_uint(PRINT_JSON,
|
||||
"sport",
|
||||
NULL,
|
||||
sport ? ntohs(sport) : 0);
|
||||
print_uint(PRINT_JSON, "dport", NULL, ntohs(dport));
|
||||
print_bool(PRINT_JSON, "csum", NULL,
|
||||
flags & TUNNEL_ENCAP_FLAG_CSUM);
|
||||
print_bool(PRINT_JSON, "csum6", NULL,
|
||||
flags & TUNNEL_ENCAP_FLAG_CSUM6);
|
||||
print_bool(PRINT_JSON, "remcsum", NULL,
|
||||
flags & TUNNEL_ENCAP_FLAG_REMCSUM);
|
||||
close_json_object();
|
||||
} else {
|
||||
if (sport == 0)
|
||||
fputs("encap-sport auto ", f);
|
||||
else
|
||||
fprintf(f, "encap-sport %u", ntohs(sport));
|
||||
|
||||
fprintf(f, "encap-dport %u ", ntohs(dport));
|
||||
fprintf(f, "encap-dport %u ", ntohs(dport));
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM)
|
||||
fputs("encap-csum ", f);
|
||||
else
|
||||
fputs("noencap-csum ", f);
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM)
|
||||
fputs("encap-csum ", f);
|
||||
else
|
||||
fputs("noencap-csum ", f);
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
|
||||
fputs("encap-csum6 ", f);
|
||||
else
|
||||
fputs("noencap-csum6 ", f);
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
|
||||
fputs("encap-csum6 ", f);
|
||||
else
|
||||
fputs("noencap-csum6 ", f);
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
|
||||
fputs("encap-remcsum ", f);
|
||||
else
|
||||
fputs("noencap-remcsum ", f);
|
||||
if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
|
||||
fputs("encap-remcsum ", f);
|
||||
else
|
||||
fputs("noencap-remcsum ", f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
172
ip/link_ip6tnl.c
172
ip/link_ip6tnl.c
|
|
@ -346,25 +346,29 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb
|
|||
if (tb[IFLA_IPTUN_PROTO]) {
|
||||
switch (rta_getattr_u8(tb[IFLA_IPTUN_PROTO])) {
|
||||
case IPPROTO_IPIP:
|
||||
fprintf(f, "ipip6 ");
|
||||
print_string(PRINT_ANY, "proto", "%s ", "ipip6");
|
||||
break;
|
||||
case IPPROTO_IPV6:
|
||||
fprintf(f, "ip6ip6 ");
|
||||
print_string(PRINT_ANY, "proto", "%s ", "ip6ip6");
|
||||
break;
|
||||
case 0:
|
||||
fprintf(f, "any ");
|
||||
print_string(PRINT_ANY, "proto", "%s ", "any");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_IPTUN_REMOTE]) {
|
||||
fprintf(f, "remote %s ",
|
||||
rt_addr_n2a_rta(AF_INET6, tb[IFLA_IPTUN_REMOTE]));
|
||||
print_string(PRINT_ANY,
|
||||
"remote",
|
||||
"remote %s ",
|
||||
rt_addr_n2a_rta(AF_INET6, tb[IFLA_IPTUN_REMOTE]));
|
||||
}
|
||||
|
||||
if (tb[IFLA_IPTUN_LOCAL]) {
|
||||
fprintf(f, "local %s ",
|
||||
rt_addr_n2a_rta(AF_INET6, tb[IFLA_IPTUN_LOCAL]));
|
||||
print_string(PRINT_ANY,
|
||||
"local",
|
||||
"local %s ",
|
||||
rt_addr_n2a_rta(AF_INET6, tb[IFLA_IPTUN_LOCAL]));
|
||||
}
|
||||
|
||||
if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
|
||||
|
|
@ -372,93 +376,161 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb
|
|||
const char *n = if_indextoname(link, s2);
|
||||
|
||||
if (n)
|
||||
fprintf(f, "dev %s ", n);
|
||||
print_string(PRINT_ANY, "link", "dev %s ", n);
|
||||
else
|
||||
fprintf(f, "dev %u ", link);
|
||||
print_uint(PRINT_ANY, "link_index", "dev %u ", link);
|
||||
}
|
||||
|
||||
if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT)
|
||||
printf("encaplimit none ");
|
||||
print_bool(PRINT_ANY,
|
||||
"ip6_tnl_f_ign_encap_limit",
|
||||
"encaplimit none ",
|
||||
true);
|
||||
else if (tb[IFLA_IPTUN_ENCAP_LIMIT])
|
||||
fprintf(f, "encaplimit %u ",
|
||||
rta_getattr_u8(tb[IFLA_IPTUN_ENCAP_LIMIT]));
|
||||
print_uint(PRINT_ANY,
|
||||
"encap_limit",
|
||||
"encaplimit %u ",
|
||||
rta_getattr_u8(tb[IFLA_IPTUN_ENCAP_LIMIT]));
|
||||
|
||||
if (tb[IFLA_IPTUN_TTL])
|
||||
fprintf(f, "hoplimit %u ", rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
|
||||
print_uint(PRINT_ANY,
|
||||
"ttl",
|
||||
"hoplimit %u ",
|
||||
rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
|
||||
|
||||
if (flags & IP6_TNL_F_USE_ORIG_TCLASS)
|
||||
printf("tclass inherit ");
|
||||
print_bool(PRINT_ANY,
|
||||
"ip6_tnl_f_use_orig_tclass",
|
||||
"tclass inherit ",
|
||||
true);
|
||||
else if (tb[IFLA_IPTUN_FLOWINFO]) {
|
||||
__u32 val = ntohl(flowinfo & IP6_FLOWINFO_TCLASS);
|
||||
|
||||
printf("tclass 0x%02x ", (__u8)(val >> 20));
|
||||
if (is_json_context()) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1), "0x%02x", (__u8)(val >> 20));
|
||||
print_string(PRINT_JSON, "flowinfo_tclass", NULL, b1);
|
||||
} else {
|
||||
printf("tclass 0x%02x ", (__u8)(val >> 20));
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
|
||||
printf("flowlabel inherit ");
|
||||
else
|
||||
printf("flowlabel 0x%05x ", ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
|
||||
if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) {
|
||||
print_bool(PRINT_ANY,
|
||||
"ip6_tnl_f_use_orig_flowlabel",
|
||||
"flowlabel inherit ",
|
||||
true);
|
||||
} else {
|
||||
if (is_json_context()) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
printf("(flowinfo 0x%08x) ", ntohl(flowinfo));
|
||||
snprintf(b1, sizeof(b1), "0x%05x",
|
||||
ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
|
||||
print_string(PRINT_JSON, "flowlabel", NULL, b1);
|
||||
} else {
|
||||
printf("flowlabel 0x%05x ",
|
||||
ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
|
||||
}
|
||||
}
|
||||
|
||||
if (is_json_context()) {
|
||||
SPRINT_BUF(flwinfo);
|
||||
|
||||
snprintf(flwinfo, sizeof(flwinfo), "0x%08x", ntohl(flowinfo));
|
||||
print_string(PRINT_JSON, "flowinfo", NULL, flwinfo);
|
||||
} else {
|
||||
printf("(flowinfo 0x%08x) ", ntohl(flowinfo));
|
||||
|
||||
}
|
||||
|
||||
if (flags & IP6_TNL_F_RCV_DSCP_COPY)
|
||||
printf("dscp inherit ");
|
||||
print_bool(PRINT_ANY,
|
||||
"ip6_tnl_f_rcv_dscp_copy",
|
||||
"dscp inherit ",
|
||||
true);
|
||||
|
||||
if (flags & IP6_TNL_F_MIP6_DEV)
|
||||
fprintf(f, "mip6 ");
|
||||
print_bool(PRINT_ANY, "ip6_tnl_f_mip6_dev", "mip6 ", true);
|
||||
|
||||
if (flags & IP6_TNL_F_USE_ORIG_FWMARK)
|
||||
fprintf(f, "fwmark inherit ");
|
||||
else if (tb[IFLA_IPTUN_FWMARK] && rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]))
|
||||
fprintf(f, "fwmark 0x%x ", rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]));
|
||||
if (flags & IP6_TNL_F_USE_ORIG_FWMARK) {
|
||||
print_bool(PRINT_ANY,
|
||||
"ip6_tnl_f_use_orig_fwmark",
|
||||
"fwmark inherit ",
|
||||
true);
|
||||
} else if (tb[IFLA_IPTUN_FWMARK]) {
|
||||
__u32 fwmark = rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]);
|
||||
|
||||
if (fwmark) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1), "0x%x", fwmark);
|
||||
print_string(PRINT_ANY, "fwmark", "fwmark %s ", b1);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_IPTUN_ENCAP_TYPE] &&
|
||||
rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE]) !=
|
||||
TUNNEL_ENCAP_NONE) {
|
||||
rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) {
|
||||
__u16 type = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE]);
|
||||
__u16 flags = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_FLAGS]);
|
||||
__u16 sport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_SPORT]);
|
||||
__u16 dport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_DPORT]);
|
||||
|
||||
fputs("encap ", f);
|
||||
open_json_object("encap");
|
||||
print_string(PRINT_FP, NULL, "encap ", NULL);
|
||||
switch (type) {
|
||||
case TUNNEL_ENCAP_FOU:
|
||||
fputs("fou ", f);
|
||||
print_string(PRINT_ANY, "type", "%s ", "fou");
|
||||
break;
|
||||
case TUNNEL_ENCAP_GUE:
|
||||
fputs("gue ", f);
|
||||
print_string(PRINT_ANY, "type", "%s ", "gue");
|
||||
break;
|
||||
default:
|
||||
fputs("unknown ", f);
|
||||
print_null(PRINT_ANY, "type", "unknown ", NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sport == 0)
|
||||
fputs("encap-sport auto ", f);
|
||||
else
|
||||
fprintf(f, "encap-sport %u", ntohs(sport));
|
||||
if (is_json_context()) {
|
||||
print_uint(PRINT_JSON,
|
||||
"sport",
|
||||
NULL,
|
||||
sport ? ntohs(sport) : 0);
|
||||
print_uint(PRINT_JSON, "dport", NULL, ntohs(dport));
|
||||
print_bool(PRINT_JSON, "csum", NULL,
|
||||
flags & TUNNEL_ENCAP_FLAG_CSUM);
|
||||
print_bool(PRINT_JSON, "csum6", NULL,
|
||||
flags & TUNNEL_ENCAP_FLAG_CSUM6);
|
||||
print_bool(PRINT_JSON, "remcsum", NULL,
|
||||
flags & TUNNEL_ENCAP_FLAG_REMCSUM);
|
||||
close_json_object();
|
||||
} else {
|
||||
if (sport == 0)
|
||||
fputs("encap-sport auto ", f);
|
||||
else
|
||||
fprintf(f, "encap-sport %u", ntohs(sport));
|
||||
|
||||
fprintf(f, "encap-dport %u ", ntohs(dport));
|
||||
fprintf(f, "encap-dport %u ", ntohs(dport));
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM)
|
||||
fputs("encap-csum ", f);
|
||||
else
|
||||
fputs("noencap-csum ", f);
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM)
|
||||
fputs("encap-csum ", f);
|
||||
else
|
||||
fputs("noencap-csum ", f);
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
|
||||
fputs("encap-csum6 ", f);
|
||||
else
|
||||
fputs("noencap-csum6 ", f);
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
|
||||
fputs("encap-csum6 ", f);
|
||||
else
|
||||
fputs("noencap-csum6 ", f);
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
|
||||
fputs("encap-remcsum ", f);
|
||||
else
|
||||
fputs("noencap-remcsum ", f);
|
||||
if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
|
||||
fputs("encap-remcsum ", f);
|
||||
else
|
||||
fputs("noencap-remcsum ", f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ip6tunnel_print_help(struct link_util *lu, int argc, char **argv,
|
||||
FILE *f)
|
||||
FILE *f)
|
||||
{
|
||||
print_usage(f);
|
||||
}
|
||||
|
|
|
|||
155
ip/link_iptnl.c
155
ip/link_iptnl.c
|
|
@ -398,7 +398,7 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
|
|||
remote = format_host(AF_INET, 4, &addr);
|
||||
}
|
||||
|
||||
fprintf(f, "remote %s ", remote);
|
||||
print_string(PRINT_ANY, "remote", "remote %s ", remote);
|
||||
|
||||
if (tb[IFLA_IPTUN_LOCAL]) {
|
||||
unsigned int addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]);
|
||||
|
|
@ -407,43 +407,55 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
|
|||
local = format_host(AF_INET, 4, &addr);
|
||||
}
|
||||
|
||||
fprintf(f, "local %s ", local);
|
||||
print_string(PRINT_ANY, "local", "local %s ", local);
|
||||
|
||||
if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
|
||||
unsigned int link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
|
||||
const char *n = if_indextoname(link, s2);
|
||||
|
||||
if (n)
|
||||
fprintf(f, "dev %s ", n);
|
||||
print_string(PRINT_ANY, "link", "dev %s ", n);
|
||||
else
|
||||
fprintf(f, "dev %u ", link);
|
||||
print_int(PRINT_ANY, "link_index", "dev %u ", link);
|
||||
}
|
||||
|
||||
if (tb[IFLA_IPTUN_TTL] && rta_getattr_u8(tb[IFLA_IPTUN_TTL]))
|
||||
fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
|
||||
else
|
||||
fprintf(f, "ttl inherit ");
|
||||
if (tb[IFLA_IPTUN_TTL]) {
|
||||
__u8 ttl = rta_getattr_u8(tb[IFLA_IPTUN_TTL]);
|
||||
|
||||
if (tb[IFLA_IPTUN_TOS] && rta_getattr_u8(tb[IFLA_IPTUN_TOS])) {
|
||||
if (ttl)
|
||||
print_int(PRINT_ANY, "ttl", "ttl %d ", ttl);
|
||||
else
|
||||
print_int(PRINT_JSON, "ttl", NULL, ttl);
|
||||
} else {
|
||||
print_string(PRINT_FP, NULL, "ttl %s ", "inherit");
|
||||
}
|
||||
|
||||
if (tb[IFLA_IPTUN_TOS]) {
|
||||
int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]);
|
||||
|
||||
fputs("tos ", f);
|
||||
if (tos == 1)
|
||||
fputs("inherit ", f);
|
||||
else
|
||||
fprintf(f, "0x%x ", tos);
|
||||
if (tos) {
|
||||
if (is_json_context()) {
|
||||
print_0xhex(PRINT_JSON, "tos", "%#x", tos);
|
||||
} else {
|
||||
fputs("tos ", f);
|
||||
if (tos == 1)
|
||||
fputs("inherit ", f);
|
||||
else
|
||||
fprintf(f, "0x%x ", tos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC]))
|
||||
fprintf(f, "pmtudisc ");
|
||||
print_bool(PRINT_ANY, "pmtudisc", "pmtudisc ", true);
|
||||
else
|
||||
fprintf(f, "nopmtudisc ");
|
||||
print_bool(PRINT_ANY, "pmtudisc", "nopmtudisc ", false);
|
||||
|
||||
if (tb[IFLA_IPTUN_FLAGS]) {
|
||||
__u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]);
|
||||
|
||||
if (iflags & SIT_ISATAP)
|
||||
fprintf(f, "isatap ");
|
||||
print_bool(PRINT_ANY, "isatap", "isatap ", true);
|
||||
}
|
||||
|
||||
if (tb[IFLA_IPTUN_6RD_PREFIXLEN] &&
|
||||
|
|
@ -453,14 +465,32 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
|
|||
__u32 relayprefix =
|
||||
rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]);
|
||||
|
||||
printf("6rd-prefix %s/%u ",
|
||||
inet_ntop(AF_INET6, RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
|
||||
s1, sizeof(s1)),
|
||||
prefixlen);
|
||||
if (relayprefix) {
|
||||
printf("6rd-relay_prefix %s/%u ",
|
||||
format_host(AF_INET, 4, &relayprefix),
|
||||
relayprefixlen);
|
||||
const char *prefix = inet_ntop(AF_INET6,
|
||||
RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
|
||||
s1, sizeof(s1));
|
||||
|
||||
if (is_json_context()) {
|
||||
print_string(PRINT_JSON, "prefix", NULL, prefix);
|
||||
print_int(PRINT_JSON, "prefixlen", NULL, prefixlen);
|
||||
if (relayprefix) {
|
||||
print_string(PRINT_JSON,
|
||||
"relay_prefix",
|
||||
NULL,
|
||||
format_host(AF_INET,
|
||||
4,
|
||||
&relayprefix));
|
||||
print_int(PRINT_JSON,
|
||||
"relay_prefixlen",
|
||||
NULL,
|
||||
relayprefixlen);
|
||||
}
|
||||
} else {
|
||||
printf("6rd-prefix %s/%u ", prefix, prefixlen);
|
||||
if (relayprefix) {
|
||||
printf("6rd-relay_prefix %s/%u ",
|
||||
format_host(AF_INET, 4, &relayprefix),
|
||||
relayprefixlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -470,45 +500,72 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
|
|||
__u16 sport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_SPORT]);
|
||||
__u16 dport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_DPORT]);
|
||||
|
||||
fputs("encap ", f);
|
||||
print_string(PRINT_FP, NULL, "encap ", NULL);
|
||||
switch (type) {
|
||||
case TUNNEL_ENCAP_FOU:
|
||||
fputs("fou ", f);
|
||||
print_string(PRINT_ANY, "type", "%s ", "fou");
|
||||
break;
|
||||
case TUNNEL_ENCAP_GUE:
|
||||
fputs("gue ", f);
|
||||
print_string(PRINT_ANY, "type", "%s ", "gue");
|
||||
break;
|
||||
default:
|
||||
fputs("unknown ", f);
|
||||
print_null(PRINT_ANY, "type", "unknown ", NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sport == 0)
|
||||
fputs("encap-sport auto ", f);
|
||||
else
|
||||
fprintf(f, "encap-sport %u", ntohs(sport));
|
||||
if (is_json_context()) {
|
||||
print_uint(PRINT_JSON,
|
||||
"sport",
|
||||
NULL,
|
||||
sport ? ntohs(sport) : 0);
|
||||
print_uint(PRINT_JSON, "dport", NULL, ntohs(dport));
|
||||
print_bool(PRINT_JSON,
|
||||
"csum",
|
||||
NULL,
|
||||
flags & TUNNEL_ENCAP_FLAG_CSUM);
|
||||
print_bool(PRINT_JSON,
|
||||
"csum6",
|
||||
NULL,
|
||||
flags & TUNNEL_ENCAP_FLAG_CSUM6);
|
||||
print_bool(PRINT_JSON,
|
||||
"remcsum",
|
||||
NULL,
|
||||
flags & TUNNEL_ENCAP_FLAG_REMCSUM);
|
||||
close_json_object();
|
||||
} else {
|
||||
if (sport == 0)
|
||||
fputs("encap-sport auto ", f);
|
||||
else
|
||||
fprintf(f, "encap-sport %u", ntohs(sport));
|
||||
|
||||
fprintf(f, "encap-dport %u ", ntohs(dport));
|
||||
fprintf(f, "encap-dport %u ", ntohs(dport));
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM)
|
||||
fputs("encap-csum ", f);
|
||||
else
|
||||
fputs("noencap-csum ", f);
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM)
|
||||
fputs("encap-csum ", f);
|
||||
else
|
||||
fputs("noencap-csum ", f);
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
|
||||
fputs("encap-csum6 ", f);
|
||||
else
|
||||
fputs("noencap-csum6 ", f);
|
||||
if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
|
||||
fputs("encap-csum6 ", f);
|
||||
else
|
||||
fputs("noencap-csum6 ", f);
|
||||
|
||||
if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
|
||||
fputs("encap-remcsum ", f);
|
||||
else
|
||||
fputs("noencap-remcsum ", f);
|
||||
if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
|
||||
fputs("encap-remcsum ", f);
|
||||
else
|
||||
fputs("noencap-remcsum ", f);
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[IFLA_IPTUN_FWMARK] && rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]))
|
||||
fprintf(f, "fwmark 0x%x ",
|
||||
rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]));
|
||||
if (tb[IFLA_IPTUN_FWMARK]) {
|
||||
__u32 fwmark = rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]);
|
||||
|
||||
if (fwmark) {
|
||||
snprintf(s2, sizeof(s2), "0x%x", fwmark);
|
||||
|
||||
print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void iptunnel_print_help(struct link_util *lu, int argc, char **argv,
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
remote = format_host(AF_INET, 4, &addr);
|
||||
}
|
||||
|
||||
fprintf(f, "remote %s ", remote);
|
||||
print_string(PRINT_ANY, "remote", "remote %s ", remote);
|
||||
|
||||
if (tb[IFLA_VTI_LOCAL]) {
|
||||
unsigned int addr = rta_getattr_u32(tb[IFLA_VTI_LOCAL]);
|
||||
|
|
@ -233,30 +233,36 @@ static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
local = format_host(AF_INET, 4, &addr);
|
||||
}
|
||||
|
||||
fprintf(f, "local %s ", local);
|
||||
print_string(PRINT_ANY, "local", "local %s ", local);
|
||||
|
||||
if (tb[IFLA_VTI_LINK] &&
|
||||
(link = rta_getattr_u32(tb[IFLA_VTI_LINK]))) {
|
||||
const char *n = if_indextoname(link, s2);
|
||||
|
||||
if (n)
|
||||
fprintf(f, "dev %s ", n);
|
||||
print_string(PRINT_ANY, "link", "dev %s ", n);
|
||||
else
|
||||
fprintf(f, "dev %u ", link);
|
||||
print_uint(PRINT_ANY, "link_index", "dev %u ", link);
|
||||
}
|
||||
|
||||
if (tb[IFLA_VTI_IKEY] &&
|
||||
(key = rta_getattr_u32(tb[IFLA_VTI_IKEY])))
|
||||
fprintf(f, "ikey %#x ", ntohl(key));
|
||||
print_0xhex(PRINT_ANY, "ikey", "ikey %#x ", ntohl(key));
|
||||
|
||||
|
||||
if (tb[IFLA_VTI_OKEY] &&
|
||||
(key = rta_getattr_u32(tb[IFLA_VTI_OKEY])))
|
||||
fprintf(f, "okey %#x ", ntohl(key));
|
||||
print_0xhex(PRINT_ANY, "okey", "okey %#x ", ntohl(key));
|
||||
|
||||
if (tb[IFLA_VTI_FWMARK] && rta_getattr_u32(tb[IFLA_VTI_FWMARK])) {
|
||||
fprintf(f, "fwmark 0x%x ",
|
||||
rta_getattr_u32(tb[IFLA_VTI_FWMARK]));
|
||||
if (tb[IFLA_VTI_FWMARK]) {
|
||||
__u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]);
|
||||
|
||||
if (fwmark) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1), "0x%x", fwmark);
|
||||
print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
remote = format_host(AF_INET6, 16, &daddr);
|
||||
}
|
||||
|
||||
fprintf(f, "remote %s ", remote);
|
||||
print_string(PRINT_ANY, "remote", "remote %s ", remote);
|
||||
|
||||
if (tb[IFLA_VTI_LOCAL]) {
|
||||
memcpy(&saddr, RTA_DATA(tb[IFLA_VTI_LOCAL]), sizeof(saddr));
|
||||
|
|
@ -233,29 +233,35 @@ static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
local = format_host(AF_INET6, 16, &saddr);
|
||||
}
|
||||
|
||||
fprintf(f, "local %s ", local);
|
||||
print_string(PRINT_ANY, "local", "local %s ", local);
|
||||
|
||||
if (tb[IFLA_VTI_LINK] && (link = rta_getattr_u32(tb[IFLA_VTI_LINK]))) {
|
||||
const char *n = if_indextoname(link, s2);
|
||||
|
||||
if (n)
|
||||
fprintf(f, "dev %s ", n);
|
||||
print_string(PRINT_ANY, "link", "dev %s ", n);
|
||||
else
|
||||
fprintf(f, "dev %u ", link);
|
||||
print_uint(PRINT_ANY, "link_index", "dev %u ", link);
|
||||
}
|
||||
|
||||
if (tb[IFLA_VTI_IKEY]) {
|
||||
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_IKEY]), s2, sizeof(s2));
|
||||
fprintf(f, "ikey %s ", s2);
|
||||
print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
|
||||
}
|
||||
|
||||
if (tb[IFLA_VTI_OKEY]) {
|
||||
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_OKEY]), s2, sizeof(s2));
|
||||
fprintf(f, "okey %s ", s2);
|
||||
print_string(PRINT_ANY, "okey", "okey %s ", s2);
|
||||
}
|
||||
|
||||
if (tb[IFLA_VTI_FWMARK] && rta_getattr_u32(tb[IFLA_VTI_FWMARK])) {
|
||||
fprintf(f, "fwmark 0x%x ", rta_getattr_u32(tb[IFLA_VTI_FWMARK]));
|
||||
if (tb[IFLA_VTI_FWMARK]) {
|
||||
__u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]);
|
||||
|
||||
if (fwmark) {
|
||||
snprintf(s2, sizeof(s2), "0x%x", fwmark);
|
||||
|
||||
print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
14
lib/Makefile
14
lib/Makefile
|
|
@ -1,16 +1,4 @@
|
|||
include ../Config
|
||||
|
||||
ifeq ($(IP_CONFIG_SETNS),y)
|
||||
CFLAGS += -DHAVE_SETNS
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_ELF),y)
|
||||
CFLAGS += -DHAVE_ELF
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_MNL),y)
|
||||
CFLAGS += -DHAVE_LIBMNL $(shell $(PKG_CONFIG) libmnl --cflags)
|
||||
endif
|
||||
include ../config.mk
|
||||
|
||||
CFLAGS += -fPIC
|
||||
|
||||
|
|
|
|||
12
lib/color.c
12
lib/color.c
|
|
@ -89,6 +89,14 @@ void set_color_palette(void)
|
|||
is_dark_bg = 1;
|
||||
}
|
||||
|
||||
void check_if_color_enabled(void)
|
||||
{
|
||||
if (color_is_enabled) {
|
||||
fprintf(stderr, "Option \"-json\" conflicts with \"-color\".\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -96,13 +104,13 @@ int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...)
|
|||
|
||||
va_start(args, fmt);
|
||||
|
||||
if (!color_is_enabled) {
|
||||
if (!color_is_enabled || attr == COLOR_NONE) {
|
||||
ret = vfprintf(fp, fmt, args);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret += fprintf(fp, "%s",
|
||||
color_codes[attr_colors[is_dark_bg ? attr + 7 : attr]]);
|
||||
color_codes[attr_colors[is_dark_bg ? attr + 8 : attr]]);
|
||||
ret += vfprintf(fp, fmt, args);
|
||||
ret += fprintf(fp, "%s", color_codes[C_CLEAR]);
|
||||
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ void jsonw_name(json_writer_t *self, const char *name)
|
|||
putc(' ', self->out);
|
||||
}
|
||||
|
||||
static void jsonw_printf(json_writer_t *self, const char *fmt, ...)
|
||||
void jsonw_printf(json_writer_t *self, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
|
|
@ -199,23 +199,38 @@ void jsonw_bool(json_writer_t *self, bool val)
|
|||
jsonw_printf(self, "%s", val ? "true" : "false");
|
||||
}
|
||||
|
||||
#ifdef notused
|
||||
void jsonw_null(json_writer_t *self)
|
||||
{
|
||||
jsonw_printf(self, "null");
|
||||
}
|
||||
|
||||
void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num)
|
||||
{
|
||||
jsonw_printf(self, fmt, num);
|
||||
}
|
||||
|
||||
#ifdef notused
|
||||
void jsonw_float(json_writer_t *self, double num)
|
||||
{
|
||||
jsonw_printf(self, "%g", num);
|
||||
}
|
||||
#endif
|
||||
|
||||
void jsonw_hu(json_writer_t *self, unsigned short num)
|
||||
{
|
||||
jsonw_printf(self, "%hu", num);
|
||||
}
|
||||
|
||||
void jsonw_uint(json_writer_t *self, uint64_t num)
|
||||
{
|
||||
jsonw_printf(self, "%"PRIu64, num);
|
||||
}
|
||||
|
||||
void jsonw_lluint(json_writer_t *self, unsigned long long int num)
|
||||
{
|
||||
jsonw_printf(self, "%llu", num);
|
||||
}
|
||||
|
||||
void jsonw_int(json_writer_t *self, int64_t num)
|
||||
{
|
||||
jsonw_printf(self, "%"PRId64, num);
|
||||
|
|
@ -242,25 +257,46 @@ void jsonw_float_field(json_writer_t *self, const char *prop, double val)
|
|||
}
|
||||
#endif
|
||||
|
||||
void jsonw_float_field_fmt(json_writer_t *self,
|
||||
const char *prop,
|
||||
const char *fmt,
|
||||
double val)
|
||||
{
|
||||
jsonw_name(self, prop);
|
||||
jsonw_float_fmt(self, fmt, val);
|
||||
}
|
||||
|
||||
void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num)
|
||||
{
|
||||
jsonw_name(self, prop);
|
||||
jsonw_uint(self, num);
|
||||
}
|
||||
|
||||
void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num)
|
||||
{
|
||||
jsonw_name(self, prop);
|
||||
jsonw_hu(self, num);
|
||||
}
|
||||
|
||||
void jsonw_lluint_field(json_writer_t *self,
|
||||
const char *prop,
|
||||
unsigned long long int num)
|
||||
{
|
||||
jsonw_name(self, prop);
|
||||
jsonw_lluint(self, num);
|
||||
}
|
||||
|
||||
void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num)
|
||||
{
|
||||
jsonw_name(self, prop);
|
||||
jsonw_int(self, num);
|
||||
}
|
||||
|
||||
#ifdef notused
|
||||
void jsonw_null_field(json_writer_t *self, const char *prop)
|
||||
{
|
||||
jsonw_name(self, prop);
|
||||
jsonw_null(self);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST
|
||||
int main(int argc, char **argv)
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ ip-address \- protocol address management
|
|||
.BR sit " |"
|
||||
.BR gre " |"
|
||||
.BR gretap " |"
|
||||
.BR erspan " |"
|
||||
.BR ip6gre " |"
|
||||
.BR ip6gretap " |"
|
||||
.BR vti " |"
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ ip-link \- network device configuration
|
|||
.BR sit " |"
|
||||
.BR gre " |"
|
||||
.BR gretap " |"
|
||||
.BR erspan " |"
|
||||
.BR ip6gre " |"
|
||||
.BR ip6gretap " |"
|
||||
.BR vti " |"
|
||||
|
|
@ -297,6 +298,9 @@ Link types:
|
|||
.BR gretap
|
||||
- Virtual L2 tunnel interface GRE over IPv4
|
||||
.sp
|
||||
.BR erspan
|
||||
- Encapsulated Remote SPAN over GRE and IPv4
|
||||
.sp
|
||||
.BR ip6gre
|
||||
- Virtual tunnel interface GRE over IPv6
|
||||
.sp
|
||||
|
|
@ -643,13 +647,13 @@ keyword.
|
|||
.in -8
|
||||
|
||||
.TP
|
||||
GRE, IPIP, SIT Type Support
|
||||
GRE, IPIP, SIT, ERSPAN Type Support
|
||||
For a link of types
|
||||
.I GRE/IPIP/SIT
|
||||
.I GRE/IPIP/SIT/ERSPAN
|
||||
the following additional arguments are supported:
|
||||
|
||||
.BI "ip link add " DEVICE
|
||||
.BR type " { " gre " | " ipip " | " sit " }"
|
||||
.BR type " { " gre " | " ipip " | " sit " | " erspan " }"
|
||||
.BI " remote " ADDR " local " ADDR
|
||||
[
|
||||
.BR encap " { " fou " | " gue " | " none " }"
|
||||
|
|
@ -663,6 +667,8 @@ the following additional arguments are supported:
|
|||
.I " [no]encap-remcsum "
|
||||
] [
|
||||
.I " mode " { ip6ip | ipip | mplsip | any } "
|
||||
] [
|
||||
.BR erspan " \fIIDX "
|
||||
]
|
||||
|
||||
.in +8
|
||||
|
|
@ -707,6 +713,13 @@ MPLS-Over-IPv4, "any" indicates IPv6, IPv4 or MPLS Over IPv4. Supported for
|
|||
SIT where the default is "ip6ip" and IPIP where the default is "ipip".
|
||||
IPv6-Over-IPv4 is not supported for IPIP.
|
||||
|
||||
.sp
|
||||
.BR erspan " \fIIDX "
|
||||
- specifies the ERSPAN index field.
|
||||
.IR IDX
|
||||
indicates a 20 bit index/port number associated with the ERSPAN
|
||||
traffic's source port and direction.
|
||||
|
||||
.in -8
|
||||
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
|
|||
|
||||
.ti -8
|
||||
.IR ENCAP " := [ "
|
||||
.IR MPLS " | " IP " | " BPF " | " SEG6 " ] "
|
||||
.IR MPLS " | " IP " | " BPF " | " SEG6 " | " SEG6LOCAL " ] "
|
||||
|
||||
.ti -8
|
||||
.IR ENCAP_MPLS " := "
|
||||
|
|
@ -214,12 +214,19 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
|
|||
.IR ENCAP_SEG6 " := "
|
||||
.B seg6
|
||||
.BR mode " [ "
|
||||
.BR encap " | " inline " ] "
|
||||
.BR encap " | " inline " | " l2encap " ] "
|
||||
.B segs
|
||||
.IR SEGMENTS " [ "
|
||||
.B hmac
|
||||
.IR KEYID " ]"
|
||||
|
||||
.ti -8
|
||||
.IR ENCAP_SEG6LOCAL " := "
|
||||
.B seg6local
|
||||
.BR action
|
||||
.IR SEG6_ACTION " [ "
|
||||
.IR SEG6_ACTION_PARAM " ] "
|
||||
|
||||
.ti -8
|
||||
.IR ROUTE_GET_FLAGS " := "
|
||||
.BR " [ "
|
||||
|
|
@ -674,6 +681,9 @@ is a string specifying the supported encapsulation type. Namely:
|
|||
.sp
|
||||
.BI seg6
|
||||
- encapsulation type IPv6 Segment Routing
|
||||
.sp
|
||||
.BI seg6local
|
||||
- local SRv6 segment processing
|
||||
|
||||
.in -8
|
||||
.I ENCAPHDR
|
||||
|
|
@ -740,6 +750,10 @@ is a set of encapsulation attributes specific to the
|
|||
- Encapsulate packet in an outer IPv6 header with SRH
|
||||
.sp
|
||||
|
||||
.B mode l2encap
|
||||
- Encapsulate ingress L2 frame within an outer IPv6 header and SRH
|
||||
.sp
|
||||
|
||||
.I SEGMENTS
|
||||
- List of comma-separated IPv6 addresses
|
||||
.sp
|
||||
|
|
@ -749,6 +763,56 @@ is a set of encapsulation attributes specific to the
|
|||
.in -2
|
||||
.sp
|
||||
|
||||
.B seg6local
|
||||
.in +2
|
||||
.IR SEG6_ACTION " [ "
|
||||
.IR SEG6_ACTION_PARAM " ] "
|
||||
- Operation to perform on matching packets.
|
||||
The following actions are currently supported (\fB4.14+ only\fR).
|
||||
.in +2
|
||||
|
||||
.B End
|
||||
- Regular SRv6 processing as intermediate segment endpoint.
|
||||
This action only accepts packets with a non-zero Segments Left
|
||||
value. Other matching packets are dropped.
|
||||
|
||||
.B End.X nh6
|
||||
.I NEXTHOP
|
||||
- Regular SRv6 processing as intermediate segment endpoint.
|
||||
Additionally, forward processed packets to given next-hop.
|
||||
This action only accepts packets with a non-zero Segments Left
|
||||
value. Other matching packets are dropped.
|
||||
|
||||
.B End.DX6 nh6
|
||||
.I NEXTHOP
|
||||
- Decapsulate inner IPv6 packet and forward it to the
|
||||
specified next-hop. If the argument is set to ::, then
|
||||
the next-hop is selected according to the local selection
|
||||
rules. This action only accepts packets with either a zero Segments
|
||||
Left value or no SRH at all, and an inner IPv6 packet. Other
|
||||
matching packets are dropped.
|
||||
|
||||
.B End.B6 srh segs
|
||||
.IR SEGMENTS " [ "
|
||||
.B hmac
|
||||
.IR KEYID " ] "
|
||||
- Insert the specified SRH immediately after the IPv6 header,
|
||||
update the DA with the first segment of the newly inserted SRH,
|
||||
then forward the resulting packet. The original SRH is not
|
||||
modified. This action only accepts packets with a non-zero
|
||||
Segments Left value. Other matching packets are dropped.
|
||||
|
||||
.B End.B6.Encaps srh segs
|
||||
.IR SEGMENTS " [ "
|
||||
.B hmac
|
||||
.IR KEYID " ] "
|
||||
- Regular SRv6 processing as intermediate segment endpoint.
|
||||
Additionally, encapsulate the matching packet within an outer IPv6 header
|
||||
followed by the specified SRH. The destination address of the outer IPv6
|
||||
header is set to the first segment of the new SRH. The source
|
||||
address is set as described in \fBip-sr\fR(8).
|
||||
.in -4
|
||||
|
||||
.in -8
|
||||
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.TH "actions in tc" 8 "4 Jul 2017" "iproute2" "Linux"
|
||||
.TH "actions in tc" 8 "1 Aug 2017" "iproute2" "Linux"
|
||||
|
||||
.SH NAME
|
||||
actions \- independently defined actions in tc
|
||||
|
|
@ -33,6 +33,9 @@ actions \- independently defined actions in tc
|
|||
.B actions
|
||||
.BR ls " | " list
|
||||
.I ACTNAMESPEC
|
||||
[
|
||||
.I ACTFILTER
|
||||
]
|
||||
|
||||
.in +8
|
||||
.I ACTSPEC
|
||||
|
|
@ -60,6 +63,10 @@ ACTNAME
|
|||
:=
|
||||
.BI index " INDEX"
|
||||
|
||||
.I ACTFILTER
|
||||
:=
|
||||
.BI since " MSTIME"
|
||||
|
||||
.I COOKIESPEC
|
||||
:=
|
||||
.BI cookie " COOKIE"
|
||||
|
|
@ -71,9 +78,8 @@ ACTNAME
|
|||
.I ACTNAME
|
||||
may be any valid action type: gact, mirred, bpf, connmark, csum, police, etc.
|
||||
|
||||
.I ACTPARAMS
|
||||
are the action-specific parameters; see the man page for the specific action
|
||||
type to be used for details.
|
||||
.I MSTIME
|
||||
Time since last update.
|
||||
|
||||
.I CONTROL
|
||||
:= {
|
||||
|
|
@ -132,6 +138,10 @@ List all the actions in the specified table. When combined with the
|
|||
option for
|
||||
.BR tc ","
|
||||
display the statistics for all actions in the specified table.
|
||||
When combined with the option
|
||||
.B since
|
||||
allows doing a millisecond time-filter since the last time an
|
||||
action was used in the datapath.
|
||||
.TP
|
||||
.B flush
|
||||
Delete all actions stored in the specified table.
|
||||
|
|
@ -176,6 +186,19 @@ As such, it can be used as a correlating value for maintaining user state.
|
|||
The value to be stored is completely arbitrary and does not require a specific
|
||||
format. It is stored inside the action structure itself.
|
||||
|
||||
.TP
|
||||
.BI since " MSTIME"
|
||||
When dumping large number of actions, a millisecond time-filter can be
|
||||
specified
|
||||
.IR MSTIME "."
|
||||
The
|
||||
.I MSTIME
|
||||
is a millisecond count since last time a packet hit the action.
|
||||
As an example specifying "since 20000" implies to dump all actions
|
||||
that have seen packets in the last 20 seconds. This option is useful
|
||||
when the kernel has a large number of actions and you are only interested
|
||||
in recently used actions.
|
||||
|
||||
.TP
|
||||
.I CONTROL
|
||||
The
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ is required only when
|
|||
Optional six byte destination or source MAC address to encode.
|
||||
.TP
|
||||
.BI type " TYPE"
|
||||
Optional 16-bit ethertype to encode.
|
||||
Optional 16-bit ethertype to encode. If not specified value of 0xED3E will be used.
|
||||
.TP
|
||||
.BI CONTROL
|
||||
Action to take following an encode/decode.
|
||||
|
|
|
|||
|
|
@ -3,26 +3,12 @@ LNSTATOBJ=lnstat.o lnstat_util.o
|
|||
|
||||
TARGETS=ss nstat ifstat rtacct lnstat
|
||||
|
||||
include ../Config
|
||||
include ../config.mk
|
||||
|
||||
ifeq ($(HAVE_BERKELEY_DB),y)
|
||||
TARGETS += arpd
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SELINUX),y)
|
||||
LDLIBS += $(shell $(PKG_CONFIG) --libs libselinux)
|
||||
CFLAGS += $(shell $(PKG_CONFIG) --cflags libselinux) -DHAVE_SELINUX
|
||||
endif
|
||||
|
||||
ifeq ($(IP_CONFIG_SETNS),y)
|
||||
CFLAGS += -DHAVE_SETNS
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_MNL),y)
|
||||
CFLAGS += -DHAVE_LIBMNL $(shell $(PKG_CONFIG) libmnl --cflags)
|
||||
LDLIBS += $(shell $(PKG_CONFIG) libmnl --libs)
|
||||
endif
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
ss: $(SSOBJ)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
include ../Config
|
||||
include ../config.mk
|
||||
|
||||
DISTGEN = maketable normal pareto paretonormal
|
||||
DISTDATA = normal.dist pareto.dist paretonormal.dist experimental.dist
|
||||
|
|
@ -7,11 +7,6 @@ HOSTCC ?= $(CC)
|
|||
CCOPTS = $(CBUILD_CFLAGS)
|
||||
LDLIBS += -lm
|
||||
|
||||
ifeq ($(HAVE_MNL),y)
|
||||
CFLAGS += -DHAVE_LIBMNL $(shell $(PKG_CONFIG) libmnl --cflags)
|
||||
LDLIBS += $(shell $(PKG_CONFIG) libmnl --libs)
|
||||
endif
|
||||
|
||||
all: $(DISTGEN) $(DISTDATA)
|
||||
|
||||
$(DISTGEN):
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
include ../Config
|
||||
include ../config.mk
|
||||
|
||||
ifeq ($(HAVE_MNL),y)
|
||||
|
||||
RDMA_OBJ = rdma.o utils.o dev.o link.o
|
||||
|
||||
TARGETS=rdma
|
||||
CFLAGS += $(shell $(PKG_CONFIG) libmnl --cflags)
|
||||
LDLIBS += $(shell $(PKG_CONFIG) libmnl --libs)
|
||||
|
||||
endif
|
||||
|
||||
all: $(TARGETS) $(LIBS)
|
||||
|
|
|
|||
15
tc/Makefile
15
tc/Makefile
|
|
@ -2,11 +2,7 @@ TCOBJ= tc.o tc_qdisc.o tc_class.o tc_filter.o tc_util.o tc_monitor.o \
|
|||
tc_exec.o m_police.o m_estimator.o m_action.o m_ematch.o \
|
||||
emp_ematch.yacc.o emp_ematch.lex.o
|
||||
|
||||
include ../Config
|
||||
|
||||
ifeq ($(IP_CONFIG_SETNS),y)
|
||||
CFLAGS += -DHAVE_SETNS
|
||||
endif
|
||||
include ../config.mk
|
||||
|
||||
SHARED_LIBS ?= y
|
||||
|
||||
|
|
@ -102,15 +98,6 @@ endif
|
|||
TCOBJ += $(TCMODULES)
|
||||
LDLIBS += -L. -lm
|
||||
|
||||
ifeq ($(HAVE_ELF),y)
|
||||
CFLAGS += -DHAVE_ELF
|
||||
LDLIBS += -lelf
|
||||
endif
|
||||
ifeq ($(HAVE_MNL),y)
|
||||
CFLAGS += -DHAVE_LIBMNL $(shell $(PKG_CONFIG) libmnl --cflags)
|
||||
LDLIBS += $(shell $(PKG_CONFIG) libmnl --libs)
|
||||
endif
|
||||
|
||||
ifeq ($(SHARED_LIBS),y)
|
||||
LDLIBS += -ldl
|
||||
LDFLAGS += -Wl,-export-dynamic
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ static int basic_print_opt(struct filter_util *qu, FILE *f,
|
|||
}
|
||||
|
||||
if (tb[TCA_BASIC_ACT]) {
|
||||
tc_print_action(f, tb[TCA_BASIC_ACT]);
|
||||
tc_print_action(f, tb[TCA_BASIC_ACT], 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ static int bpf_print_opt(struct filter_util *qu, FILE *f,
|
|||
}
|
||||
|
||||
if (tb[TCA_BPF_ACT])
|
||||
tc_print_action(f, tb[TCA_BPF_ACT]);
|
||||
tc_print_action(f, tb[TCA_BPF_ACT], 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ static int cgroup_print_opt(struct filter_util *qu, FILE *f,
|
|||
}
|
||||
|
||||
if (tb[TCA_CGROUP_ACT])
|
||||
tc_print_action(f, tb[TCA_CGROUP_ACT]);
|
||||
tc_print_action(f, tb[TCA_CGROUP_ACT], 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ static int flow_print_opt(struct filter_util *fu, FILE *f, struct rtattr *opt,
|
|||
tc_print_police(f, tb[TCA_FLOW_POLICE]);
|
||||
if (tb[TCA_FLOW_ACT]) {
|
||||
fprintf(f, "\n");
|
||||
tc_print_action(f, tb[TCA_FLOW_ACT]);
|
||||
tc_print_action(f, tb[TCA_FLOW_ACT], 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1316,7 +1316,7 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
|
|||
}
|
||||
|
||||
if (tb[TCA_FLOWER_ACT])
|
||||
tc_print_action(f, tb[TCA_FLOWER_ACT]);
|
||||
tc_print_action(f, tb[TCA_FLOWER_ACT], 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ static int fw_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u
|
|||
|
||||
if (tb[TCA_FW_ACT]) {
|
||||
fprintf(f, "\n");
|
||||
tc_print_action(f, tb[TCA_FW_ACT]);
|
||||
tc_print_action(f, tb[TCA_FW_ACT], 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ static int matchall_print_opt(struct filter_util *qu, FILE *f,
|
|||
}
|
||||
|
||||
if (tb[TCA_MATCHALL_ACT])
|
||||
tc_print_action(f, tb[TCA_MATCHALL_ACT]);
|
||||
tc_print_action(f, tb[TCA_MATCHALL_ACT], 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ static int route_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
|
|||
if (tb[TCA_ROUTE4_POLICE])
|
||||
tc_print_police(f, tb[TCA_ROUTE4_POLICE]);
|
||||
if (tb[TCA_ROUTE4_ACT])
|
||||
tc_print_action(f, tb[TCA_ROUTE4_ACT]);
|
||||
tc_print_action(f, tb[TCA_ROUTE4_ACT], 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -402,7 +402,7 @@ static int rsvp_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, _
|
|||
}
|
||||
|
||||
if (tb[TCA_RSVP_ACT]) {
|
||||
tc_print_action(f, tb[TCA_RSVP_ACT]);
|
||||
tc_print_action(f, tb[TCA_RSVP_ACT], 0);
|
||||
}
|
||||
if (tb[TCA_RSVP_POLICE])
|
||||
tc_print_police(f, tb[TCA_RSVP_POLICE]);
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ static int tcindex_print_opt(struct filter_util *qu, FILE *f,
|
|||
}
|
||||
if (tb[TCA_TCINDEX_ACT]) {
|
||||
fprintf(f, "\n");
|
||||
tc_print_action(f, tb[TCA_TCINDEX_ACT]);
|
||||
tc_print_action(f, tb[TCA_TCINDEX_ACT], 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1337,7 +1337,7 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
|
|||
}
|
||||
|
||||
if (tb[TCA_U32_ACT])
|
||||
tc_print_action(f, tb[TCA_U32_ACT]);
|
||||
tc_print_action(f, tb[TCA_U32_ACT], 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -346,21 +346,25 @@ tc_print_action_flush(FILE *f, const struct rtattr *arg)
|
|||
}
|
||||
|
||||
int
|
||||
tc_print_action(FILE *f, const struct rtattr *arg)
|
||||
tc_print_action(FILE *f, const struct rtattr *arg, unsigned short tot_acts)
|
||||
{
|
||||
|
||||
int i;
|
||||
struct rtattr *tb[TCA_ACT_MAX_PRIO + 1];
|
||||
|
||||
if (arg == NULL)
|
||||
return 0;
|
||||
|
||||
parse_rtattr_nested(tb, TCA_ACT_MAX_PRIO, arg);
|
||||
if (!tot_acts)
|
||||
tot_acts = TCA_ACT_MAX_PRIO;
|
||||
|
||||
struct rtattr *tb[tot_acts + 1];
|
||||
|
||||
parse_rtattr_nested(tb, tot_acts, arg);
|
||||
|
||||
if (tab_flush && NULL != tb[0] && NULL == tb[1])
|
||||
return tc_print_action_flush(f, tb[0]);
|
||||
|
||||
for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
|
||||
for (i = 0; i < tot_acts; i++) {
|
||||
if (tb[i]) {
|
||||
fprintf(f, "\n\taction order %d: ", i);
|
||||
if (tc_print_one_action(f, tb[i]) < 0) {
|
||||
|
|
@ -380,7 +384,8 @@ int print_action(const struct sockaddr_nl *who,
|
|||
FILE *fp = (FILE *)arg;
|
||||
struct tcamsg *t = NLMSG_DATA(n);
|
||||
int len = n->nlmsg_len;
|
||||
struct rtattr *tb[TCAA_MAX+1];
|
||||
__u32 *tot_acts = NULL;
|
||||
struct rtattr *tb[TCA_ROOT_MAX+1];
|
||||
|
||||
len -= NLMSG_LENGTH(sizeof(*t));
|
||||
|
||||
|
|
@ -389,8 +394,12 @@ int print_action(const struct sockaddr_nl *who,
|
|||
return -1;
|
||||
}
|
||||
|
||||
parse_rtattr(tb, TCAA_MAX, TA_RTA(t), len);
|
||||
parse_rtattr(tb, TCA_ROOT_MAX, TA_RTA(t), len);
|
||||
|
||||
if (tb[TCA_ROOT_COUNT])
|
||||
tot_acts = RTA_DATA(tb[TCA_ROOT_COUNT]);
|
||||
|
||||
fprintf(fp, "total acts %d\n", tot_acts ? *tot_acts:0);
|
||||
if (tb[TCA_ACT_TAB] == NULL) {
|
||||
if (n->nlmsg_type != RTM_GETACTION)
|
||||
fprintf(stderr, "print_action: NULL kind\n");
|
||||
|
|
@ -414,7 +423,9 @@ int print_action(const struct sockaddr_nl *who,
|
|||
fprintf(fp, "Replaced action ");
|
||||
}
|
||||
}
|
||||
tc_print_action(fp, tb[TCA_ACT_TAB]);
|
||||
|
||||
|
||||
tc_print_action(fp, tb[TCA_ACT_TAB], tot_acts ? *tot_acts:0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -427,7 +438,7 @@ static int tc_action_gd(int cmd, unsigned int flags, int *argc_p, char ***argv_p
|
|||
char **argv = *argv_p;
|
||||
int prio = 0;
|
||||
int ret = 0;
|
||||
__u32 i;
|
||||
__u32 i = 0;
|
||||
struct rtattr *tail;
|
||||
struct rtattr *tail2;
|
||||
struct nlmsghdr *ans = NULL;
|
||||
|
|
@ -498,7 +509,8 @@ static int tc_action_gd(int cmd, unsigned int flags, int *argc_p, char ***argv_p
|
|||
tail2 = NLMSG_TAIL(&req.n);
|
||||
addattr_l(&req.n, MAX_MSG, ++prio, NULL, 0);
|
||||
addattr_l(&req.n, MAX_MSG, TCA_ACT_KIND, k, strlen(k) + 1);
|
||||
addattr32(&req.n, MAX_MSG, TCA_ACT_INDEX, i);
|
||||
if (i > 0)
|
||||
addattr32(&req.n, MAX_MSG, TCA_ACT_INDEX, i);
|
||||
tail2->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail2;
|
||||
|
||||
}
|
||||
|
|
@ -561,12 +573,16 @@ static int tc_action_modify(int cmd, unsigned int flags, int *argc_p, char ***ar
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int tc_act_list_or_flush(int argc, char **argv, int event)
|
||||
static int tc_act_list_or_flush(int *argc_p, char ***argv_p, int event)
|
||||
{
|
||||
struct rtattr *tail, *tail2, *tail3, *tail4;
|
||||
int ret = 0, prio = 0, msg_size = 0;
|
||||
char k[16];
|
||||
struct rtattr *tail, *tail2;
|
||||
struct action_util *a = NULL;
|
||||
struct nla_bitfield32 flag_select = { 0 };
|
||||
char **argv = *argv_p;
|
||||
__u32 msec_since = 0;
|
||||
int argc = *argc_p;
|
||||
char k[16];
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct tcamsg t;
|
||||
|
|
@ -597,11 +613,31 @@ static int tc_act_list_or_flush(int argc, char **argv, int event)
|
|||
}
|
||||
strncpy(k, *argv, sizeof(k) - 1);
|
||||
|
||||
argc -= 1;
|
||||
argv += 1;
|
||||
|
||||
if (argc && (strcmp(*argv, "since") == 0)) {
|
||||
NEXT_ARG();
|
||||
if (get_u32(&msec_since, *argv, 0))
|
||||
invarg("dump time \"since\" is invalid", *argv);
|
||||
}
|
||||
|
||||
addattr_l(&req.n, MAX_MSG, ++prio, NULL, 0);
|
||||
addattr_l(&req.n, MAX_MSG, TCA_ACT_KIND, k, strlen(k) + 1);
|
||||
tail2->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail2;
|
||||
tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail;
|
||||
|
||||
tail3 = NLMSG_TAIL(&req.n);
|
||||
flag_select.value |= TCA_FLAG_LARGE_DUMP_ON;
|
||||
flag_select.selector |= TCA_FLAG_LARGE_DUMP_ON;
|
||||
addattr_l(&req.n, MAX_MSG, TCA_ROOT_FLAGS, &flag_select,
|
||||
sizeof(struct nla_bitfield32));
|
||||
tail3->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail3;
|
||||
if (msec_since) {
|
||||
tail4 = NLMSG_TAIL(&req.n);
|
||||
addattr32(&req.n, MAX_MSG, TCA_ROOT_TIME_DELTA, msec_since);
|
||||
tail4->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail4;
|
||||
}
|
||||
msg_size = NLMSG_ALIGN(req.n.nlmsg_len) - NLMSG_ALIGN(sizeof(struct nlmsghdr));
|
||||
|
||||
if (event == RTM_GETACTION) {
|
||||
|
|
@ -626,6 +662,8 @@ static int tc_act_list_or_flush(int argc, char **argv, int event)
|
|||
|
||||
bad_val:
|
||||
|
||||
*argc_p = argc;
|
||||
*argv_p = argv;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -655,13 +693,21 @@ int do_action(int argc, char **argv)
|
|||
act_usage();
|
||||
return -1;
|
||||
}
|
||||
return tc_act_list_or_flush(argc-2, argv+2, RTM_GETACTION);
|
||||
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
return tc_act_list_or_flush(&argc, &argv,
|
||||
RTM_GETACTION);
|
||||
} else if (matches(*argv, "flush") == 0) {
|
||||
if (argc <= 2) {
|
||||
act_usage();
|
||||
return -1;
|
||||
}
|
||||
return tc_act_list_or_flush(argc-2, argv+2, RTM_DELACTION);
|
||||
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
return tc_act_list_or_flush(&argc, &argv,
|
||||
RTM_DELACTION);
|
||||
} else if (matches(*argv, "help") == 0) {
|
||||
act_usage();
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p,
|
|||
char dbuf[ETH_ALEN];
|
||||
char sbuf[ETH_ALEN];
|
||||
__u16 ife_type = 0;
|
||||
int user_type = 0;
|
||||
__u32 ife_prio = 0;
|
||||
__u32 ife_prio_v = 0;
|
||||
__u32 ife_mark = 0;
|
||||
|
|
@ -124,7 +125,8 @@ static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p,
|
|||
NEXT_ARG();
|
||||
if (get_u16(&ife_type, *argv, 0))
|
||||
invarg("ife type is invalid", *argv);
|
||||
fprintf(stderr, "IFE type 0x%x\n", ife_type);
|
||||
fprintf(stderr, "IFE type 0x%04X\n", ife_type);
|
||||
user_type = 1;
|
||||
} else if (matches(*argv, "dst") == 0) {
|
||||
NEXT_ARG();
|
||||
daddr = *argv;
|
||||
|
|
@ -185,8 +187,10 @@ static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p,
|
|||
|
||||
if (daddr)
|
||||
addattr_l(n, MAX_MSG, TCA_IFE_DMAC, dbuf, ETH_ALEN);
|
||||
if (ife_type)
|
||||
if (user_type)
|
||||
addattr_l(n, MAX_MSG, TCA_IFE_TYPE, &ife_type, 2);
|
||||
else
|
||||
fprintf(stderr, "IFE type 0x%04X\n", ETH_P_IFE);
|
||||
if (saddr)
|
||||
addattr_l(n, MAX_MSG, TCA_IFE_SMAC, sbuf, ETH_ALEN);
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ int act_parse_police(struct action_util *a, int *argc_p,
|
|||
char ***argv_p, int tca_id, struct nlmsghdr *n);
|
||||
int print_police(struct action_util *a, FILE *f, struct rtattr *tb);
|
||||
int police_print_xstats(struct action_util *a, FILE *f, struct rtattr *tb);
|
||||
int tc_print_action(FILE *f, const struct rtattr *tb);
|
||||
int tc_print_action(FILE *f, const struct rtattr *tb, unsigned short tot_acts);
|
||||
int tc_print_ipt(FILE *f, const struct rtattr *tb);
|
||||
int parse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n);
|
||||
void print_tm(FILE *f, const struct tcf_t *tm);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
include ../Config
|
||||
include ../config.mk
|
||||
|
||||
ifeq ($(HAVE_MNL),y)
|
||||
|
||||
TIPCOBJ=bearer.o \
|
||||
|
|
@ -8,8 +9,6 @@ TIPCOBJ=bearer.o \
|
|||
node.o socket.o \
|
||||
peer.o tipc.o
|
||||
|
||||
include ../Config
|
||||
|
||||
TARGETS=tipc
|
||||
CFLAGS += $(shell $(PKG_CONFIG) libmnl --cflags)
|
||||
LDLIBS += $(shell $(PKG_CONFIG) libmnl --libs)
|
||||
|
|
|
|||
Loading…
Reference in New Issue