Compare commits
116 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
73590d9573 | |
|
|
3f77bc6253 | |
|
|
5f8bb902e1 | |
|
|
3184de3797 | |
|
|
79026c1262 | |
|
|
fa58de9b0c | |
|
|
be31c26484 | |
|
|
0e94972590 | |
|
|
9bd5ab0f09 | |
|
|
a787d9ae10 | |
|
|
af96c7b5dd | |
|
|
35c81b18c4 | |
|
|
50b668bdbf | |
|
|
9c56d693f6 | |
|
|
0c263d7c36 | |
|
|
0f7bb8d842 | |
|
|
67f3c7a5cc | |
|
|
fd5e958c49 | |
|
|
8316df6e6d | |
|
|
6e15d27aae | |
|
|
9cae1de564 | |
|
|
258e350ca9 | |
|
|
047e9ae516 | |
|
|
e2947f6fd8 | |
|
|
9e009e78e7 | |
|
|
040e52526c | |
|
|
c76a3849ec | |
|
|
76b30805f9 | |
|
|
2be7d99960 | |
|
|
95cd2a6204 | |
|
|
a936a73fc2 | |
|
|
cee0cf84bd | |
|
|
0ee1950b5c | |
|
|
4b8bca5f9e | |
|
|
99245d1741 | |
|
|
c330d09794 | |
|
|
48c379bc2a | |
|
|
1d819dcc74 | |
|
|
19ba785f16 | |
|
|
7d5cb70e94 | |
|
|
d480cb71f5 | |
|
|
e4ca6a4965 | |
|
|
a31e7b7967 | |
|
|
8cd517a805 | |
|
|
763fd793fe | |
|
|
41020eb0fd | |
|
|
8fb522cde3 | |
|
|
b840c620fe | |
|
|
b90174354d | |
|
|
6448ed373c | |
|
|
ec703e0629 | |
|
|
7ca868a7aa | |
|
|
5d5dc549ce | |
|
|
cb3d18c29e | |
|
|
60a9703032 | |
|
|
53d7c43bd3 | |
|
|
a2ca431215 | |
|
|
945c26db68 | |
|
|
7ec1cee630 | |
|
|
60a7515b89 | |
|
|
cfb0a8729e | |
|
|
371e889da7 | |
|
|
f72789965e | |
|
|
c8c9111a4c | |
|
|
e2cc9840ea | |
|
|
26c5782fab | |
|
|
fd4c1c8168 | |
|
|
c63b769ad4 | |
|
|
399ae00af5 | |
|
|
3a92669b3a | |
|
|
ebbb701714 | |
|
|
75c5054e7a | |
|
|
0431e1e724 | |
|
|
12b3d6a2ad | |
|
|
917d913b2e | |
|
|
d0cba0d1f6 | |
|
|
ae895504c6 | |
|
|
12fbe3e4eb | |
|
|
db28c944d8 | |
|
|
6d676ad934 | |
|
|
1eaebad2c5 | |
|
|
adddf30cd8 | |
|
|
2c8110881b | |
|
|
fb843668fb | |
|
|
72222cd467 | |
|
|
7ad5505bb5 | |
|
|
061da2e222 | |
|
|
60dcd5c318 | |
|
|
0e4cfa0370 | |
|
|
ebcee09ca1 | |
|
|
3ae784f589 | |
|
|
2b6cc38d52 | |
|
|
7cc7dbf447 | |
|
|
3399c0759f | |
|
|
a8d7212a4f | |
|
|
29fada0f41 | |
|
|
1f608d590c | |
|
|
dee5eb05e5 | |
|
|
ecf6d8b4a1 | |
|
|
720f8613bd | |
|
|
d3a961a9b1 | |
|
|
312e22fe79 | |
|
|
d2eecb9d1d | |
|
|
ebaa603b30 | |
|
|
8d6134b204 | |
|
|
51d8fc708c | |
|
|
71ba9c18e0 | |
|
|
e78411948d | |
|
|
09d8ce3db1 | |
|
|
e8763fc9ab | |
|
|
78832863ef | |
|
|
32f4969d44 | |
|
|
2909812583 | |
|
|
e53f4cd504 | |
|
|
236696e52c | |
|
|
cf866f0a5a |
16
Makefile
16
Makefile
|
|
@ -1,6 +1,8 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Top level Makefile for iproute2
|
||||
|
||||
-include config.mk
|
||||
|
||||
ifeq ("$(origin V)", "command line")
|
||||
VERBOSE = $(V)
|
||||
endif
|
||||
|
|
@ -13,7 +15,6 @@ MAKEFLAGS += --no-print-directory
|
|||
endif
|
||||
|
||||
PREFIX?=/usr
|
||||
LIBDIR?=$(PREFIX)/lib
|
||||
SBINDIR?=/sbin
|
||||
CONFDIR?=/etc/iproute2
|
||||
NETNS_RUN_DIR?=/var/run/netns
|
||||
|
|
@ -40,9 +41,18 @@ DEFINES+=-DCONFDIR=\"$(CONFDIR)\" \
|
|||
-DNETNS_RUN_DIR=\"$(NETNS_RUN_DIR)\" \
|
||||
-DNETNS_ETC_DIR=\"$(NETNS_ETC_DIR)\"
|
||||
|
||||
#options for AX.25
|
||||
ADDLIB+=ax25_ntop.o
|
||||
|
||||
#options for AX.25
|
||||
ADDLIB+=rose_ntop.o
|
||||
|
||||
#options for mpls
|
||||
ADDLIB+=mpls_ntop.o mpls_pton.o
|
||||
|
||||
#options for NETROM
|
||||
ADDLIB+=netrom_ntop.o
|
||||
|
||||
CC := gcc
|
||||
HOSTCC ?= $(CC)
|
||||
DEFINES += -D_GNU_SOURCE
|
||||
|
|
@ -60,7 +70,7 @@ SUBDIRS=lib ip tc bridge misc netem genl tipc devlink rdma dcb man vdpa
|
|||
LIBNETLINK=../lib/libutil.a ../lib/libnetlink.a
|
||||
LDLIBS += $(LIBNETLINK)
|
||||
|
||||
all: config
|
||||
all: config.mk
|
||||
@set -e; \
|
||||
for i in $(SUBDIRS); \
|
||||
do echo; echo $$i; $(MAKE) -C $$i; done
|
||||
|
|
@ -80,7 +90,7 @@ help:
|
|||
@echo "Make Arguments:"
|
||||
@echo " V=[0|1] - set build verbosity level"
|
||||
|
||||
config:
|
||||
config.mk:
|
||||
@if [ ! -f config.mk -o configure -nt config.mk ]; then \
|
||||
sh configure $(KERNEL_INCLUDE); \
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ int print_mdb_mon(struct nlmsghdr *n, void *arg);
|
|||
int print_fdb(struct nlmsghdr *n, void *arg);
|
||||
void print_stp_state(__u8 state);
|
||||
int parse_stp_state(const char *arg);
|
||||
int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor);
|
||||
int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor,
|
||||
bool global_only);
|
||||
void br_print_router_port_stats(struct rtattr *pattr);
|
||||
|
||||
int do_fdb(int argc, char **argv);
|
||||
int do_mdb(int argc, char **argv);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ static const char *format_timer(__u32 ticks, int align)
|
|||
return tbuf;
|
||||
}
|
||||
|
||||
static void __print_router_port_stats(FILE *f, struct rtattr *pattr)
|
||||
void br_print_router_port_stats(struct rtattr *pattr)
|
||||
{
|
||||
struct rtattr *tb[MDBA_ROUTER_PATTR_MAX + 1];
|
||||
|
||||
|
|
@ -101,13 +101,13 @@ static void br_print_router_ports(FILE *f, struct rtattr *attr,
|
|||
print_string(PRINT_JSON, "port", NULL, port_ifname);
|
||||
|
||||
if (show_stats)
|
||||
__print_router_port_stats(f, i);
|
||||
br_print_router_port_stats(i);
|
||||
close_json_object();
|
||||
} else if (show_stats) {
|
||||
fprintf(f, "router ports on %s: %s",
|
||||
brifname, port_ifname);
|
||||
|
||||
__print_router_port_stats(f, i);
|
||||
br_print_router_port_stats(i);
|
||||
fprintf(f, "\n");
|
||||
} else {
|
||||
fprintf(f, "%s ", port_ifname);
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ static int accept_msg(struct rtnl_ctrl_data *ctrl,
|
|||
case RTM_DELVLAN:
|
||||
if (prefix_banner)
|
||||
fprintf(fp, "[VLAN]");
|
||||
return print_vlan_rtm(n, arg, true);
|
||||
return print_vlan_rtm(n, arg, true, false);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
|
|
|||
635
bridge/vlan.c
635
bridge/vlan.c
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/if_bridge.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "json_print.h"
|
||||
#include "libnetlink.h"
|
||||
|
|
@ -35,8 +36,23 @@ static void usage(void)
|
|||
" [ pvid ] [ untagged ]\n"
|
||||
" [ self ] [ master ]\n"
|
||||
" bridge vlan { set } vid VLAN_ID dev DEV [ state STP_STATE ]\n"
|
||||
" [ mcast_router MULTICAST_ROUTER ]\n"
|
||||
" bridge vlan { show } [ dev DEV ] [ vid VLAN_ID ]\n"
|
||||
" bridge vlan { tunnelshow } [ dev DEV ] [ vid VLAN_ID ]\n");
|
||||
" bridge vlan { tunnelshow } [ dev DEV ] [ vid VLAN_ID ]\n"
|
||||
" bridge vlan global { set } vid VLAN_ID dev DEV\n"
|
||||
" [ mcast_snooping MULTICAST_SNOOPING ]\n"
|
||||
" [ mcast_querier MULTICAST_QUERIER ]\n"
|
||||
" [ mcast_igmp_version IGMP_VERSION ]\n"
|
||||
" [ mcast_mld_version MLD_VERSION ]\n"
|
||||
" [ mcast_last_member_count LAST_MEMBER_COUNT ]\n"
|
||||
" [ mcast_last_member_interval LAST_MEMBER_INTERVAL ]\n"
|
||||
" [ mcast_startup_query_count STARTUP_QUERY_COUNT ]\n"
|
||||
" [ mcast_startup_query_interval STARTUP_QUERY_INTERVAL ]\n"
|
||||
" [ mcast_membership_interval MEMBERSHIP_INTERVAL ]\n"
|
||||
" [ mcast_querier_interval QUERIER_INTERVAL ]\n"
|
||||
" [ mcast_query_interval QUERY_INTERVAL ]\n"
|
||||
" [ mcast_query_response_interval QUERY_RESPONSE_INTERVAL ]\n"
|
||||
" bridge vlan global { show } [ dev DEV ] [ vid VLAN_ID ]\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
|
@ -257,15 +273,129 @@ static int vlan_option_set(int argc, char **argv)
|
|||
};
|
||||
struct bridge_vlan_info vinfo = {};
|
||||
struct rtattr *afspec;
|
||||
short vid_end = -1;
|
||||
char *d = NULL;
|
||||
short vid = -1;
|
||||
int state = -1;
|
||||
|
||||
afspec = addattr_nest(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY);
|
||||
afspec->rta_type |= NLA_F_NESTED;
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "dev") == 0) {
|
||||
NEXT_ARG();
|
||||
d = *argv;
|
||||
req.bvm.ifindex = ll_name_to_index(d);
|
||||
if (req.bvm.ifindex == 0) {
|
||||
fprintf(stderr,
|
||||
"Cannot find network device \"%s\"\n",
|
||||
d);
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp(*argv, "vid") == 0) {
|
||||
short vid_end = -1;
|
||||
char *p;
|
||||
|
||||
NEXT_ARG();
|
||||
p = strchr(*argv, '-');
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
p++;
|
||||
vid = atoi(*argv);
|
||||
vid_end = atoi(p);
|
||||
if (vid >= vid_end || vid_end >= 4096) {
|
||||
fprintf(stderr, "Invalid VLAN range \"%hu-%hu\"\n",
|
||||
vid, vid_end);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
vid = atoi(*argv);
|
||||
}
|
||||
if (vid >= 4096) {
|
||||
fprintf(stderr, "Invalid VLAN ID \"%hu\"\n",
|
||||
vid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
vinfo.flags = BRIDGE_VLAN_INFO_ONLY_OPTS;
|
||||
vinfo.vid = vid;
|
||||
addattr_l(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY_INFO,
|
||||
&vinfo, sizeof(vinfo));
|
||||
if (vid_end != -1)
|
||||
addattr16(&req.n, sizeof(req),
|
||||
BRIDGE_VLANDB_ENTRY_RANGE, vid_end);
|
||||
} else if (strcmp(*argv, "state") == 0) {
|
||||
char *endptr;
|
||||
int state;
|
||||
|
||||
NEXT_ARG();
|
||||
state = strtol(*argv, &endptr, 10);
|
||||
if (!(**argv != '\0' && *endptr == '\0'))
|
||||
state = parse_stp_state(*argv);
|
||||
if (state == -1) {
|
||||
fprintf(stderr, "Error: invalid STP state\n");
|
||||
return -1;
|
||||
}
|
||||
addattr8(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY_STATE,
|
||||
state);
|
||||
} else if (strcmp(*argv, "mcast_router") == 0) {
|
||||
__u8 mcast_router;
|
||||
|
||||
NEXT_ARG();
|
||||
if (get_u8(&mcast_router, *argv, 0))
|
||||
invarg("invalid mcast_router", *argv);
|
||||
addattr8(&req.n, sizeof(req),
|
||||
BRIDGE_VLANDB_ENTRY_MCAST_ROUTER,
|
||||
mcast_router);
|
||||
} else {
|
||||
if (matches(*argv, "help") == 0)
|
||||
NEXT_ARG();
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
addattr_nest_end(&req.n, afspec);
|
||||
|
||||
if (d == NULL || vid == -1) {
|
||||
fprintf(stderr, "Device and VLAN ID are required arguments.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rtnl_talk(&rth, &req.n, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vlan_global_option_set(int argc, char **argv)
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct br_vlan_msg bvm;
|
||||
char buf[1024];
|
||||
} req = {
|
||||
.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct br_vlan_msg)),
|
||||
.n.nlmsg_flags = NLM_F_REQUEST,
|
||||
.n.nlmsg_type = RTM_NEWVLAN,
|
||||
.bvm.family = PF_BRIDGE,
|
||||
};
|
||||
struct rtattr *afspec;
|
||||
short vid_end = -1;
|
||||
char *d = NULL;
|
||||
short vid = -1;
|
||||
__u64 val64;
|
||||
__u32 val32;
|
||||
__u8 val8;
|
||||
|
||||
afspec = addattr_nest(&req.n, sizeof(req),
|
||||
BRIDGE_VLANDB_GLOBAL_OPTIONS);
|
||||
afspec->rta_type |= NLA_F_NESTED;
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "dev") == 0) {
|
||||
NEXT_ARG();
|
||||
d = *argv;
|
||||
req.bvm.ifindex = ll_name_to_index(d);
|
||||
if (req.bvm.ifindex == 0) {
|
||||
fprintf(stderr, "Cannot find network device \"%s\"\n",
|
||||
d);
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp(*argv, "vid") == 0) {
|
||||
char *p;
|
||||
|
||||
|
|
@ -284,53 +414,116 @@ static int vlan_option_set(int argc, char **argv)
|
|||
} else {
|
||||
vid = atoi(*argv);
|
||||
}
|
||||
} else if (strcmp(*argv, "state") == 0) {
|
||||
char *endptr;
|
||||
|
||||
NEXT_ARG();
|
||||
state = strtol(*argv, &endptr, 10);
|
||||
if (!(**argv != '\0' && *endptr == '\0'))
|
||||
state = parse_stp_state(*argv);
|
||||
if (state == -1) {
|
||||
fprintf(stderr, "Error: invalid STP state\n");
|
||||
if (vid >= 4096) {
|
||||
fprintf(stderr, "Invalid VLAN ID \"%hu\"\n",
|
||||
vid);
|
||||
return -1;
|
||||
}
|
||||
addattr16(&req.n, sizeof(req), BRIDGE_VLANDB_GOPTS_ID,
|
||||
vid);
|
||||
if (vid_end != -1)
|
||||
addattr16(&req.n, sizeof(req),
|
||||
BRIDGE_VLANDB_GOPTS_RANGE, vid_end);
|
||||
} else if (strcmp(*argv, "mcast_snooping") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u8(&val8, *argv, 0))
|
||||
invarg("invalid mcast_snooping", *argv);
|
||||
addattr8(&req.n, 1024,
|
||||
BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING, val8);
|
||||
} else if (strcmp(*argv, "mcast_querier") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u8(&val8, *argv, 0))
|
||||
invarg("invalid mcast_querier", *argv);
|
||||
addattr8(&req.n, 1024,
|
||||
BRIDGE_VLANDB_GOPTS_MCAST_QUERIER, val8);
|
||||
} else if (strcmp(*argv, "mcast_igmp_version") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u8(&val8, *argv, 0))
|
||||
invarg("invalid mcast_igmp_version", *argv);
|
||||
addattr8(&req.n, 1024,
|
||||
BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION, val8);
|
||||
} else if (strcmp(*argv, "mcast_mld_version") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u8(&val8, *argv, 0))
|
||||
invarg("invalid mcast_mld_version", *argv);
|
||||
addattr8(&req.n, 1024,
|
||||
BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION, val8);
|
||||
} else if (strcmp(*argv, "mcast_last_member_count") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u32(&val32, *argv, 0))
|
||||
invarg("invalid mcast_last_member_count", *argv);
|
||||
addattr32(&req.n, 1024,
|
||||
BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT,
|
||||
val32);
|
||||
} else if (strcmp(*argv, "mcast_startup_query_count") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u32(&val32, *argv, 0))
|
||||
invarg("invalid mcast_startup_query_count",
|
||||
*argv);
|
||||
addattr32(&req.n, 1024,
|
||||
BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT,
|
||||
val32);
|
||||
} else if (strcmp(*argv, "mcast_last_member_interval") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u64(&val64, *argv, 0))
|
||||
invarg("invalid mcast_last_member_interval",
|
||||
*argv);
|
||||
addattr64(&req.n, 1024,
|
||||
BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL,
|
||||
val64);
|
||||
} else if (strcmp(*argv, "mcast_membership_interval") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u64(&val64, *argv, 0))
|
||||
invarg("invalid mcast_membership_interval",
|
||||
*argv);
|
||||
addattr64(&req.n, 1024,
|
||||
BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL,
|
||||
val64);
|
||||
} else if (strcmp(*argv, "mcast_querier_interval") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u64(&val64, *argv, 0))
|
||||
invarg("invalid mcast_querier_interval",
|
||||
*argv);
|
||||
addattr64(&req.n, 1024,
|
||||
BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL,
|
||||
val64);
|
||||
} else if (strcmp(*argv, "mcast_query_interval") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u64(&val64, *argv, 0))
|
||||
invarg("invalid mcast_query_interval",
|
||||
*argv);
|
||||
addattr64(&req.n, 1024,
|
||||
BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL,
|
||||
val64);
|
||||
} else if (strcmp(*argv, "mcast_query_response_interval") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u64(&val64, *argv, 0))
|
||||
invarg("invalid mcast_query_response_interval",
|
||||
*argv);
|
||||
addattr64(&req.n, 1024,
|
||||
BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL,
|
||||
val64);
|
||||
} else if (strcmp(*argv, "mcast_startup_query_interval") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u64(&val64, *argv, 0))
|
||||
invarg("invalid mcast_startup_query_interval",
|
||||
*argv);
|
||||
addattr64(&req.n, 1024,
|
||||
BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL,
|
||||
val64);
|
||||
} else {
|
||||
if (matches(*argv, "help") == 0)
|
||||
if (strcmp(*argv, "help") == 0)
|
||||
NEXT_ARG();
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
addattr_nest_end(&req.n, afspec);
|
||||
|
||||
if (d == NULL || vid == -1) {
|
||||
fprintf(stderr, "Device and VLAN ID are required arguments.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
req.bvm.ifindex = ll_name_to_index(d);
|
||||
if (req.bvm.ifindex == 0) {
|
||||
fprintf(stderr, "Cannot find network device \"%s\"\n", d);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vid >= 4096) {
|
||||
fprintf(stderr, "Invalid VLAN ID \"%hu\"\n", vid);
|
||||
return -1;
|
||||
}
|
||||
afspec = addattr_nest(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY);
|
||||
afspec->rta_type |= NLA_F_NESTED;
|
||||
|
||||
vinfo.flags = BRIDGE_VLAN_INFO_ONLY_OPTS;
|
||||
vinfo.vid = vid;
|
||||
addattr_l(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY_INFO, &vinfo,
|
||||
sizeof(vinfo));
|
||||
if (vid_end != -1)
|
||||
addattr16(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY_RANGE,
|
||||
vid_end);
|
||||
if (state >= 0)
|
||||
addattr8(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY_STATE, state);
|
||||
addattr_nest_end(&req.n, afspec);
|
||||
|
||||
if (rtnl_talk(&rth, &req.n, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
|
|
@ -621,11 +814,224 @@ static int print_vlan_stats(struct nlmsghdr *n, void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor)
|
||||
static void print_vlan_router_ports(struct rtattr *rattr)
|
||||
{
|
||||
int rem = RTA_PAYLOAD(rattr);
|
||||
struct rtattr *i;
|
||||
|
||||
print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", "");
|
||||
open_json_array(PRINT_ANY, is_json_context() ? "router_ports" :
|
||||
"router ports: ");
|
||||
for (i = RTA_DATA(rattr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
||||
uint32_t *port_ifindex = RTA_DATA(i);
|
||||
const char *port_ifname = ll_index_to_name(*port_ifindex);
|
||||
|
||||
open_json_object(NULL);
|
||||
if (show_stats && i != RTA_DATA(rattr)) {
|
||||
print_nl();
|
||||
/* start: IFNAMSIZ + 4 + strlen("router ports: ") */
|
||||
print_string(PRINT_FP, NULL,
|
||||
"%-" __stringify(IFNAMSIZ) "s "
|
||||
" ",
|
||||
"");
|
||||
}
|
||||
print_string(PRINT_ANY, "port", "%s ", port_ifname);
|
||||
if (show_stats)
|
||||
br_print_router_port_stats(i);
|
||||
close_json_object();
|
||||
}
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
print_nl();
|
||||
}
|
||||
|
||||
static void print_vlan_global_opts(struct rtattr *a, int ifindex)
|
||||
{
|
||||
struct rtattr *vtb[BRIDGE_VLANDB_GOPTS_MAX + 1], *vattr;
|
||||
__u16 vid, vrange = 0;
|
||||
|
||||
if ((a->rta_type & NLA_TYPE_MASK) != BRIDGE_VLANDB_GLOBAL_OPTIONS)
|
||||
return;
|
||||
|
||||
parse_rtattr_flags(vtb, BRIDGE_VLANDB_GOPTS_MAX, RTA_DATA(a),
|
||||
RTA_PAYLOAD(a), NLA_F_NESTED);
|
||||
vid = rta_getattr_u16(vtb[BRIDGE_VLANDB_GOPTS_ID]);
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_RANGE])
|
||||
vrange = rta_getattr_u16(vtb[BRIDGE_VLANDB_GOPTS_RANGE]);
|
||||
else
|
||||
vrange = vid;
|
||||
|
||||
if (filter_vlan && (filter_vlan < vid || filter_vlan > vrange))
|
||||
return;
|
||||
|
||||
if (vlan_rtm_cur_ifidx != ifindex) {
|
||||
open_vlan_port(ifindex, VLAN_SHOW_VLAN);
|
||||
open_json_object(NULL);
|
||||
vlan_rtm_cur_ifidx = ifindex;
|
||||
} else {
|
||||
open_json_object(NULL);
|
||||
print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", "");
|
||||
}
|
||||
print_range("vlan", vid, vrange);
|
||||
print_nl();
|
||||
print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", "");
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING];
|
||||
print_uint(PRINT_ANY, "mcast_snooping", "mcast_snooping %u ",
|
||||
rta_getattr_u8(vattr));
|
||||
}
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER];
|
||||
print_uint(PRINT_ANY, "mcast_querier", "mcast_querier %u ",
|
||||
rta_getattr_u8(vattr));
|
||||
}
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION];
|
||||
print_uint(PRINT_ANY, "mcast_igmp_version",
|
||||
"mcast_igmp_version %u ", rta_getattr_u8(vattr));
|
||||
}
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION];
|
||||
print_uint(PRINT_ANY, "mcast_mld_version",
|
||||
"mcast_mld_version %u ", rta_getattr_u8(vattr));
|
||||
}
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT];
|
||||
print_uint(PRINT_ANY, "mcast_last_member_count",
|
||||
"mcast_last_member_count %u ",
|
||||
rta_getattr_u32(vattr));
|
||||
}
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL];
|
||||
print_lluint(PRINT_ANY, "mcast_last_member_interval",
|
||||
"mcast_last_member_interval %llu ",
|
||||
rta_getattr_u64(vattr));
|
||||
}
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT];
|
||||
print_uint(PRINT_ANY, "mcast_startup_query_count",
|
||||
"mcast_startup_query_count %u ",
|
||||
rta_getattr_u32(vattr));
|
||||
}
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL];
|
||||
print_lluint(PRINT_ANY, "mcast_startup_query_interval",
|
||||
"mcast_startup_query_interval %llu ",
|
||||
rta_getattr_u64(vattr));
|
||||
}
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL];
|
||||
print_lluint(PRINT_ANY, "mcast_membership_interval",
|
||||
"mcast_membership_interval %llu ",
|
||||
rta_getattr_u64(vattr));
|
||||
}
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL];
|
||||
print_lluint(PRINT_ANY, "mcast_querier_interval",
|
||||
"mcast_querier_interval %llu ",
|
||||
rta_getattr_u64(vattr));
|
||||
}
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL];
|
||||
print_lluint(PRINT_ANY, "mcast_query_interval",
|
||||
"mcast_query_interval %llu ",
|
||||
rta_getattr_u64(vattr));
|
||||
}
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL];
|
||||
print_lluint(PRINT_ANY, "mcast_query_response_interval",
|
||||
"mcast_query_response_interval %llu ",
|
||||
rta_getattr_u64(vattr));
|
||||
}
|
||||
print_nl();
|
||||
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS]) {
|
||||
vattr = RTA_DATA(vtb[BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS]);
|
||||
print_vlan_router_ports(vattr);
|
||||
}
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
static void print_vlan_opts(struct rtattr *a, int ifindex)
|
||||
{
|
||||
struct rtattr *vtb[BRIDGE_VLANDB_ENTRY_MAX + 1], *vattr;
|
||||
struct bridge_vlan_xstats vstats;
|
||||
struct bridge_vlan_info *vinfo;
|
||||
__u16 vrange = 0;
|
||||
__u8 state = 0;
|
||||
|
||||
if ((a->rta_type & NLA_TYPE_MASK) != BRIDGE_VLANDB_ENTRY)
|
||||
return;
|
||||
|
||||
parse_rtattr_flags(vtb, BRIDGE_VLANDB_ENTRY_MAX, RTA_DATA(a),
|
||||
RTA_PAYLOAD(a), NLA_F_NESTED);
|
||||
vinfo = RTA_DATA(vtb[BRIDGE_VLANDB_ENTRY_INFO]);
|
||||
|
||||
memset(&vstats, 0, sizeof(vstats));
|
||||
if (vtb[BRIDGE_VLANDB_ENTRY_RANGE])
|
||||
vrange = rta_getattr_u16(vtb[BRIDGE_VLANDB_ENTRY_RANGE]);
|
||||
else
|
||||
vrange = vinfo->vid;
|
||||
|
||||
if (filter_vlan && (filter_vlan < vinfo->vid || filter_vlan > vrange))
|
||||
return;
|
||||
|
||||
if (vtb[BRIDGE_VLANDB_ENTRY_STATE])
|
||||
state = rta_getattr_u8(vtb[BRIDGE_VLANDB_ENTRY_STATE]);
|
||||
|
||||
if (vtb[BRIDGE_VLANDB_ENTRY_STATS]) {
|
||||
struct rtattr *stb[BRIDGE_VLANDB_STATS_MAX+1];
|
||||
struct rtattr *attr;
|
||||
|
||||
attr = vtb[BRIDGE_VLANDB_ENTRY_STATS];
|
||||
parse_rtattr(stb, BRIDGE_VLANDB_STATS_MAX, RTA_DATA(attr),
|
||||
RTA_PAYLOAD(attr));
|
||||
|
||||
if (stb[BRIDGE_VLANDB_STATS_RX_BYTES]) {
|
||||
attr = stb[BRIDGE_VLANDB_STATS_RX_BYTES];
|
||||
vstats.rx_bytes = rta_getattr_u64(attr);
|
||||
}
|
||||
if (stb[BRIDGE_VLANDB_STATS_RX_PACKETS]) {
|
||||
attr = stb[BRIDGE_VLANDB_STATS_RX_PACKETS];
|
||||
vstats.rx_packets = rta_getattr_u64(attr);
|
||||
}
|
||||
if (stb[BRIDGE_VLANDB_STATS_TX_PACKETS]) {
|
||||
attr = stb[BRIDGE_VLANDB_STATS_TX_PACKETS];
|
||||
vstats.tx_packets = rta_getattr_u64(attr);
|
||||
}
|
||||
if (stb[BRIDGE_VLANDB_STATS_TX_BYTES]) {
|
||||
attr = stb[BRIDGE_VLANDB_STATS_TX_BYTES];
|
||||
vstats.tx_bytes = rta_getattr_u64(attr);
|
||||
}
|
||||
}
|
||||
|
||||
if (vlan_rtm_cur_ifidx != ifindex) {
|
||||
open_vlan_port(ifindex, VLAN_SHOW_VLAN);
|
||||
open_json_object(NULL);
|
||||
vlan_rtm_cur_ifidx = ifindex;
|
||||
} else {
|
||||
open_json_object(NULL);
|
||||
print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", "");
|
||||
}
|
||||
print_range("vlan", vinfo->vid, vrange);
|
||||
print_vlan_flags(vinfo->flags);
|
||||
print_nl();
|
||||
print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", "");
|
||||
print_stp_state(state);
|
||||
if (vtb[BRIDGE_VLANDB_ENTRY_MCAST_ROUTER]) {
|
||||
vattr = vtb[BRIDGE_VLANDB_ENTRY_MCAST_ROUTER];
|
||||
print_uint(PRINT_ANY, "mcast_router", "mcast_router %u ",
|
||||
rta_getattr_u8(vattr));
|
||||
}
|
||||
print_nl();
|
||||
if (show_stats)
|
||||
__print_one_vlan_stats(&vstats);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor, bool global_only)
|
||||
{
|
||||
struct rtattr *vtb[BRIDGE_VLANDB_ENTRY_MAX + 1], *a;
|
||||
struct br_vlan_msg *bvm = NLMSG_DATA(n);
|
||||
int len = n->nlmsg_len;
|
||||
struct rtattr *a;
|
||||
int rem;
|
||||
|
||||
if (n->nlmsg_type != RTM_NEWVLAN && n->nlmsg_type != RTM_DELVLAN &&
|
||||
|
|
@ -660,66 +1066,21 @@ int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor)
|
|||
|
||||
rem = len;
|
||||
for (a = BRVLAN_RTA(bvm); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) {
|
||||
struct bridge_vlan_xstats vstats;
|
||||
struct bridge_vlan_info *vinfo;
|
||||
__u32 vrange = 0;
|
||||
__u8 state = 0;
|
||||
unsigned short rta_type = a->rta_type & NLA_TYPE_MASK;
|
||||
|
||||
parse_rtattr_flags(vtb, BRIDGE_VLANDB_ENTRY_MAX, RTA_DATA(a),
|
||||
RTA_PAYLOAD(a), NLA_F_NESTED);
|
||||
vinfo = RTA_DATA(vtb[BRIDGE_VLANDB_ENTRY_INFO]);
|
||||
/* skip unknown attributes */
|
||||
if (rta_type > BRIDGE_VLANDB_MAX ||
|
||||
(global_only && rta_type != BRIDGE_VLANDB_GLOBAL_OPTIONS))
|
||||
continue;
|
||||
|
||||
memset(&vstats, 0, sizeof(vstats));
|
||||
if (vtb[BRIDGE_VLANDB_ENTRY_RANGE])
|
||||
vrange = rta_getattr_u16(vtb[BRIDGE_VLANDB_ENTRY_RANGE]);
|
||||
else
|
||||
vrange = vinfo->vid;
|
||||
|
||||
if (vtb[BRIDGE_VLANDB_ENTRY_STATE])
|
||||
state = rta_getattr_u8(vtb[BRIDGE_VLANDB_ENTRY_STATE]);
|
||||
|
||||
if (vtb[BRIDGE_VLANDB_ENTRY_STATS]) {
|
||||
struct rtattr *stb[BRIDGE_VLANDB_STATS_MAX+1];
|
||||
struct rtattr *attr;
|
||||
|
||||
attr = vtb[BRIDGE_VLANDB_ENTRY_STATS];
|
||||
parse_rtattr(stb, BRIDGE_VLANDB_STATS_MAX, RTA_DATA(attr),
|
||||
RTA_PAYLOAD(attr));
|
||||
|
||||
if (stb[BRIDGE_VLANDB_STATS_RX_BYTES]) {
|
||||
attr = stb[BRIDGE_VLANDB_STATS_RX_BYTES];
|
||||
vstats.rx_bytes = rta_getattr_u64(attr);
|
||||
}
|
||||
if (stb[BRIDGE_VLANDB_STATS_RX_PACKETS]) {
|
||||
attr = stb[BRIDGE_VLANDB_STATS_RX_PACKETS];
|
||||
vstats.rx_packets = rta_getattr_u64(attr);
|
||||
}
|
||||
if (stb[BRIDGE_VLANDB_STATS_TX_PACKETS]) {
|
||||
attr = stb[BRIDGE_VLANDB_STATS_TX_PACKETS];
|
||||
vstats.tx_packets = rta_getattr_u64(attr);
|
||||
}
|
||||
if (stb[BRIDGE_VLANDB_STATS_TX_BYTES]) {
|
||||
attr = stb[BRIDGE_VLANDB_STATS_TX_BYTES];
|
||||
vstats.tx_bytes = rta_getattr_u64(attr);
|
||||
}
|
||||
switch (rta_type) {
|
||||
case BRIDGE_VLANDB_ENTRY:
|
||||
print_vlan_opts(a, bvm->ifindex);
|
||||
break;
|
||||
case BRIDGE_VLANDB_GLOBAL_OPTIONS:
|
||||
print_vlan_global_opts(a, bvm->ifindex);
|
||||
break;
|
||||
}
|
||||
if (vlan_rtm_cur_ifidx != bvm->ifindex) {
|
||||
open_vlan_port(bvm->ifindex, VLAN_SHOW_VLAN);
|
||||
open_json_object(NULL);
|
||||
vlan_rtm_cur_ifidx = bvm->ifindex;
|
||||
} else {
|
||||
open_json_object(NULL);
|
||||
print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", "");
|
||||
}
|
||||
print_range("vlan", vinfo->vid, vrange);
|
||||
print_vlan_flags(vinfo->flags);
|
||||
print_nl();
|
||||
print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", "");
|
||||
print_stp_state(state);
|
||||
print_nl();
|
||||
if (show_stats)
|
||||
__print_one_vlan_stats(&vstats);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -727,7 +1088,12 @@ int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor)
|
|||
|
||||
static int print_vlan_rtm_filter(struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
return print_vlan_rtm(n, arg, false);
|
||||
return print_vlan_rtm(n, arg, false, false);
|
||||
}
|
||||
|
||||
static int print_vlan_rtm_global_filter(struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
return print_vlan_rtm(n, arg, false, true);
|
||||
}
|
||||
|
||||
static int vlan_show(int argc, char **argv, int subject)
|
||||
|
|
@ -845,6 +1211,61 @@ out:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vlan_global_show(int argc, char **argv)
|
||||
{
|
||||
__u32 dump_flags = BRIDGE_VLANDB_DUMPF_GLOBAL;
|
||||
int ret = 0, subject = VLAN_SHOW_VLAN;
|
||||
char *filter_dev = NULL;
|
||||
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "dev") == 0) {
|
||||
NEXT_ARG();
|
||||
if (filter_dev)
|
||||
duparg("dev", *argv);
|
||||
filter_dev = *argv;
|
||||
} else if (strcmp(*argv, "vid") == 0) {
|
||||
NEXT_ARG();
|
||||
if (filter_vlan)
|
||||
duparg("vid", *argv);
|
||||
filter_vlan = atoi(*argv);
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
if (filter_dev) {
|
||||
filter_index = ll_name_to_index(filter_dev);
|
||||
if (!filter_index)
|
||||
return nodev(filter_dev);
|
||||
}
|
||||
|
||||
new_json_obj(json);
|
||||
|
||||
if (rtnl_brvlandump_req(&rth, PF_BRIDGE, dump_flags) < 0) {
|
||||
perror("Cannot send dump request");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!is_json_context()) {
|
||||
printf("%-" __stringify(IFNAMSIZ) "s %-"
|
||||
__stringify(VLAN_ID_LEN) "s", "port",
|
||||
"vlan-id");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
ret = rtnl_dump_filter(&rth, print_vlan_rtm_global_filter, &subject);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Dump terminated\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (vlan_rtm_cur_ifidx != -1)
|
||||
close_vlan_port();
|
||||
|
||||
delete_json_obj();
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_vlan_info(struct rtattr *tb, int ifindex)
|
||||
{
|
||||
struct rtattr *i, *list = tb;
|
||||
|
|
@ -889,6 +1310,24 @@ void print_vlan_info(struct rtattr *tb, int ifindex)
|
|||
close_vlan_port();
|
||||
}
|
||||
|
||||
static int vlan_global(int argc, char **argv)
|
||||
{
|
||||
if (argc > 0) {
|
||||
if (strcmp(*argv, "show") == 0 ||
|
||||
strcmp(*argv, "lst") == 0 ||
|
||||
strcmp(*argv, "list") == 0)
|
||||
return vlan_global_show(argc-1, argv+1);
|
||||
else if (strcmp(*argv, "set") == 0)
|
||||
return vlan_global_option_set(argc-1, argv+1);
|
||||
else
|
||||
usage();
|
||||
} else {
|
||||
return vlan_global_show(0, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_vlan(int argc, char **argv)
|
||||
{
|
||||
ll_init_map(&rth);
|
||||
|
|
@ -907,6 +1346,8 @@ int do_vlan(int argc, char **argv)
|
|||
}
|
||||
if (matches(*argv, "set") == 0)
|
||||
return vlan_option_set(argc-1, argv+1);
|
||||
if (strcmp(*argv, "global") == 0)
|
||||
return vlan_global(argc-1, argv+1);
|
||||
if (matches(*argv, "help") == 0)
|
||||
usage();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
# This is not an autoconf generated configure
|
||||
|
||||
INCLUDE="$PWD/include"
|
||||
PREFIX="/usr"
|
||||
LIBDIR="\${prefix}/lib"
|
||||
|
||||
# Output file which is input to Makefile
|
||||
CONFIG=config.mk
|
||||
|
|
@ -148,6 +150,15 @@ EOF
|
|||
rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest
|
||||
}
|
||||
|
||||
check_lib_dir()
|
||||
{
|
||||
LIBDIR=$(echo $LIBDIR | sed "s|\${prefix}|$PREFIX|")
|
||||
|
||||
echo -n "lib directory: "
|
||||
echo "$LIBDIR"
|
||||
echo "LIBDIR:=$LIBDIR" >> $CONFIG
|
||||
}
|
||||
|
||||
check_ipt()
|
||||
{
|
||||
if ! grep TC_CONFIG_XT $CONFIG > /dev/null; then
|
||||
|
|
@ -485,12 +496,14 @@ usage()
|
|||
{
|
||||
cat <<EOF
|
||||
Usage: $0 [OPTIONS]
|
||||
--include_dir Path to iproute2 include dir
|
||||
--libbpf_dir Path to libbpf DESTDIR
|
||||
--libbpf_force Enable/disable libbpf by force. Available options:
|
||||
on: require link against libbpf, quit config if no libbpf support
|
||||
off: disable libbpf probing
|
||||
-h | --help Show this usage info
|
||||
--include_dir <dir> Path to iproute2 include dir
|
||||
--libdir <dir> Path to iproute2 lib dir
|
||||
--libbpf_dir <dir> Path to libbpf DESTDIR
|
||||
--libbpf_force <on|off> Enable/disable libbpf by force. Available options:
|
||||
on: require link against libbpf, quit config if no libbpf support
|
||||
off: disable libbpf probing
|
||||
--prefix <dir> Path prefix of the lib files to install
|
||||
-h | --help Show this usage info
|
||||
EOF
|
||||
exit $1
|
||||
}
|
||||
|
|
@ -499,30 +512,56 @@ EOF
|
|||
if [ $# -eq 1 ] && [ "$(echo $1 | cut -c 1)" != '-' ]; then
|
||||
INCLUDE="$1"
|
||||
else
|
||||
while true; do
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--include_dir)
|
||||
INCLUDE=$2
|
||||
shift 2 ;;
|
||||
shift
|
||||
INCLUDE="$1" ;;
|
||||
--include_dir=*)
|
||||
INCLUDE="${1#*=}" ;;
|
||||
--libdir)
|
||||
shift
|
||||
LIBDIR="$1" ;;
|
||||
--libdir=*)
|
||||
LIBDIR="${1#*=}" ;;
|
||||
--libbpf_dir)
|
||||
LIBBPF_DIR="$2"
|
||||
shift 2 ;;
|
||||
shift
|
||||
LIBBPF_DIR="$1" ;;
|
||||
--libbpf_dir=*)
|
||||
LIBBPF_DIR="${1#*=}" ;;
|
||||
--libbpf_force)
|
||||
if [ "$2" != 'on' ] && [ "$2" != 'off' ]; then
|
||||
usage 1
|
||||
fi
|
||||
LIBBPF_FORCE=$2
|
||||
shift 2 ;;
|
||||
shift
|
||||
LIBBPF_FORCE="$1" ;;
|
||||
--libbpf_force=*)
|
||||
LIBBPF_FORCE="${1#*=}" ;;
|
||||
--prefix)
|
||||
shift
|
||||
PREFIX="$1" ;;
|
||||
--prefix=*)
|
||||
PREFIX="${1#*=}" ;;
|
||||
-h | --help)
|
||||
usage 0 ;;
|
||||
"")
|
||||
break ;;
|
||||
--*)
|
||||
;;
|
||||
*)
|
||||
shift 1 ;;
|
||||
usage 1 ;;
|
||||
esac
|
||||
[ "$#" -gt 0 ] && shift
|
||||
done
|
||||
fi
|
||||
|
||||
[ -d "$INCLUDE" ] || usage 1
|
||||
if [ "${LIBBPF_DIR-unused}" != "unused" ]; then
|
||||
[ -d "$LIBBPF_DIR" ] || usage 1
|
||||
fi
|
||||
if [ "${LIBBPF_FORCE-unused}" != "unused" ]; then
|
||||
if [ "$LIBBPF_FORCE" != 'on' ] && [ "$LIBBPF_FORCE" != 'off' ]; then
|
||||
usage 1
|
||||
fi
|
||||
fi
|
||||
[ -z "$PREFIX" ] && usage 1
|
||||
[ -z "$LIBDIR" ] && usage 1
|
||||
|
||||
echo "# Generated config based on" $INCLUDE >$CONFIG
|
||||
quiet_config >> $CONFIG
|
||||
|
||||
|
|
@ -546,6 +585,7 @@ if ! grep -q TC_CONFIG_NO_XT $CONFIG; then
|
|||
fi
|
||||
|
||||
echo
|
||||
check_lib_dir
|
||||
if ! grep -q TC_CONFIG_NO_XT $CONFIG; then
|
||||
echo -n "iptables modules directory: "
|
||||
check_ipt_lib_dir
|
||||
|
|
|
|||
|
|
@ -3036,6 +3036,7 @@ static int cmd_dev_param_show_cb(const struct nlmsghdr *nlh, void *data)
|
|||
struct param_ctx {
|
||||
struct dl *dl;
|
||||
int nla_type;
|
||||
bool cmode_found;
|
||||
union {
|
||||
uint8_t vu8;
|
||||
uint16_t vu16;
|
||||
|
|
@ -3088,6 +3089,7 @@ static int cmd_dev_param_set_cb(const struct nlmsghdr *nlh, void *data)
|
|||
|
||||
cmode = mnl_attr_get_u8(nla_value[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
|
||||
if (cmode == dl->opts.cmode) {
|
||||
ctx->cmode_found = true;
|
||||
val_attr = nla_value[DEVLINK_ATTR_PARAM_VALUE_DATA];
|
||||
switch (nla_type) {
|
||||
case MNL_TYPE_U8:
|
||||
|
|
@ -3140,6 +3142,10 @@ static int cmd_dev_param_set(struct dl *dl)
|
|||
err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_dev_param_set_cb, &ctx);
|
||||
if (err)
|
||||
return err;
|
||||
if (!ctx.cmode_found) {
|
||||
pr_err("Configuration mode not supported\n");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PARAM_SET,
|
||||
NLM_F_REQUEST | NLM_F_ACK);
|
||||
|
|
@ -7845,6 +7851,10 @@ static void pr_out_region(struct dl *dl, struct nlattr **tb)
|
|||
if (tb[DEVLINK_ATTR_REGION_SNAPSHOT_ID])
|
||||
pr_out_snapshot(dl, tb);
|
||||
|
||||
if (tb[DEVLINK_ATTR_REGION_MAX_SNAPSHOTS])
|
||||
pr_out_u64(dl, "max",
|
||||
mnl_attr_get_u32(tb[DEVLINK_ATTR_REGION_MAX_SNAPSHOTS]));
|
||||
|
||||
pr_out_region_handle_end(dl);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ Where:
|
|||
|
||||
ACTION semantics
|
||||
- pass and ok are equivalent to accept
|
||||
- continue allows to restart classification lookup
|
||||
- continue allows one to restart classification lookup
|
||||
- drop drops packets
|
||||
- reclassify implies continue classification where we left off
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (c) 2021 Taehee Yoo <ap420073@gmail.com>
|
||||
*/
|
||||
#ifndef _AMT_H_
|
||||
#define _AMT_H_
|
||||
|
||||
enum ifla_amt_mode {
|
||||
/* AMT interface works as Gateway mode.
|
||||
* The Gateway mode encapsulates IGMP/MLD traffic and decapsulates
|
||||
* multicast traffic.
|
||||
*/
|
||||
AMT_MODE_GATEWAY = 0,
|
||||
/* AMT interface works as Relay mode.
|
||||
* The Relay mode encapsulates multicast traffic and decapsulates
|
||||
* IGMP/MLD traffic.
|
||||
*/
|
||||
AMT_MODE_RELAY,
|
||||
__AMT_MODE_MAX,
|
||||
};
|
||||
|
||||
#define AMT_MODE_MAX (__AMT_MODE_MAX - 1)
|
||||
|
||||
enum {
|
||||
IFLA_AMT_UNSPEC,
|
||||
/* This attribute specify mode etier Gateway or Relay. */
|
||||
IFLA_AMT_MODE,
|
||||
/* This attribute specify Relay port.
|
||||
* AMT interface is created as Gateway mode, this attribute is used
|
||||
* to specify relay(remote) port.
|
||||
* AMT interface is created as Relay mode, this attribute is used
|
||||
* as local port.
|
||||
*/
|
||||
IFLA_AMT_RELAY_PORT,
|
||||
/* This attribute specify Gateway port.
|
||||
* AMT interface is created as Gateway mode, this attribute is used
|
||||
* as local port.
|
||||
* AMT interface is created as Relay mode, this attribute is not used.
|
||||
*/
|
||||
IFLA_AMT_GATEWAY_PORT,
|
||||
/* This attribute specify physical device */
|
||||
IFLA_AMT_LINK,
|
||||
/* This attribute specify local ip address */
|
||||
IFLA_AMT_LOCAL_IP,
|
||||
/* This attribute specify Relay ip address.
|
||||
* So, this is not used by Relay.
|
||||
*/
|
||||
IFLA_AMT_REMOTE_IP,
|
||||
/* This attribute specify Discovery ip address.
|
||||
* When Gateway get started, it send discovery message to find the
|
||||
* Relay's ip address.
|
||||
* So, this is not used by Relay.
|
||||
*/
|
||||
IFLA_AMT_DISCOVERY_IP,
|
||||
/* This attribute specify number of maximum tunnel. */
|
||||
IFLA_AMT_MAX_TUNNELS,
|
||||
__IFLA_AMT_MAX,
|
||||
};
|
||||
|
||||
#define IFLA_AMT_MAX (__IFLA_AMT_MAX - 1)
|
||||
|
||||
#endif /* _AMT_H_ */
|
||||
|
|
@ -906,6 +906,7 @@ enum bpf_map_type {
|
|||
BPF_MAP_TYPE_RINGBUF,
|
||||
BPF_MAP_TYPE_INODE_STORAGE,
|
||||
BPF_MAP_TYPE_TASK_STORAGE,
|
||||
BPF_MAP_TYPE_BLOOM_FILTER,
|
||||
};
|
||||
|
||||
/* Note that tracing related programs such as
|
||||
|
|
@ -1274,6 +1275,13 @@ union bpf_attr {
|
|||
* struct stored as the
|
||||
* map value
|
||||
*/
|
||||
/* Any per-map-type extra fields
|
||||
*
|
||||
* BPF_MAP_TYPE_BLOOM_FILTER - the lowest 4 bits indicate the
|
||||
* number of hash functions (if 0, the bloom filter will default
|
||||
* to using 5 hash functions).
|
||||
*/
|
||||
__u64 map_extra;
|
||||
};
|
||||
|
||||
struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
|
||||
|
|
@ -1629,7 +1637,7 @@ union bpf_attr {
|
|||
* u32 bpf_get_smp_processor_id(void)
|
||||
* Description
|
||||
* Get the SMP (symmetric multiprocessing) processor id. Note that
|
||||
* all programs run with preemption disabled, which means that the
|
||||
* all programs run with migration disabled, which means that the
|
||||
* SMP processor id is stable during all the execution of the
|
||||
* program.
|
||||
* Return
|
||||
|
|
@ -4046,7 +4054,7 @@ union bpf_attr {
|
|||
* arguments. The *data* are a **u64** array and corresponding format string
|
||||
* values are stored in the array. For strings and pointers where pointees
|
||||
* are accessed, only the pointer values are stored in the *data* array.
|
||||
* The *data_len* is the size of *data* in bytes.
|
||||
* The *data_len* is the size of *data* in bytes - must be a multiple of 8.
|
||||
*
|
||||
* Formats **%s**, **%p{i,I}{4,6}** requires to read kernel memory.
|
||||
* Reading kernel memory may fail due to either invalid address or
|
||||
|
|
@ -4751,7 +4759,8 @@ union bpf_attr {
|
|||
* Each format specifier in **fmt** corresponds to one u64 element
|
||||
* in the **data** array. For strings and pointers where pointees
|
||||
* are accessed, only the pointer values are stored in the *data*
|
||||
* array. The *data_len* is the size of *data* in bytes.
|
||||
* array. The *data_len* is the size of *data* in bytes - must be
|
||||
* a multiple of 8.
|
||||
*
|
||||
* Formats **%s** and **%p{i,I}{4,6}** require to read kernel
|
||||
* memory. Reading kernel memory may fail due to either invalid
|
||||
|
|
@ -4877,6 +4886,58 @@ union bpf_attr {
|
|||
* Get the struct pt_regs associated with **task**.
|
||||
* Return
|
||||
* A pointer to struct pt_regs.
|
||||
*
|
||||
* long bpf_get_branch_snapshot(void *entries, u32 size, u64 flags)
|
||||
* Description
|
||||
* Get branch trace from hardware engines like Intel LBR. The
|
||||
* hardware engine is stopped shortly after the helper is
|
||||
* called. Therefore, the user need to filter branch entries
|
||||
* based on the actual use case. To capture branch trace
|
||||
* before the trigger point of the BPF program, the helper
|
||||
* should be called at the beginning of the BPF program.
|
||||
*
|
||||
* The data is stored as struct perf_branch_entry into output
|
||||
* buffer *entries*. *size* is the size of *entries* in bytes.
|
||||
* *flags* is reserved for now and must be zero.
|
||||
*
|
||||
* Return
|
||||
* On success, number of bytes written to *buf*. On error, a
|
||||
* negative value.
|
||||
*
|
||||
* **-EINVAL** if *flags* is not zero.
|
||||
*
|
||||
* **-ENOENT** if architecture does not support branch records.
|
||||
*
|
||||
* long bpf_trace_vprintk(const char *fmt, u32 fmt_size, const void *data, u32 data_len)
|
||||
* Description
|
||||
* Behaves like **bpf_trace_printk**\ () helper, but takes an array of u64
|
||||
* to format and can handle more format args as a result.
|
||||
*
|
||||
* Arguments are to be used as in **bpf_seq_printf**\ () helper.
|
||||
* Return
|
||||
* The number of bytes written to the buffer, or a negative error
|
||||
* in case of failure.
|
||||
*
|
||||
* struct unix_sock *bpf_skc_to_unix_sock(void *sk)
|
||||
* Description
|
||||
* Dynamically cast a *sk* pointer to a *unix_sock* pointer.
|
||||
* Return
|
||||
* *sk* if casting is valid, or **NULL** otherwise.
|
||||
*
|
||||
* long bpf_kallsyms_lookup_name(const char *name, int name_sz, int flags, u64 *res)
|
||||
* Description
|
||||
* Get the address of a kernel symbol, returned in *res*. *res* is
|
||||
* set to 0 if the symbol is not found.
|
||||
* Return
|
||||
* On success, zero. On error, a negative value.
|
||||
*
|
||||
* **-EINVAL** if *flags* is not zero.
|
||||
*
|
||||
* **-EINVAL** if string *name* is not the same size as *name_sz*.
|
||||
*
|
||||
* **-ENOENT** if symbol is not found.
|
||||
*
|
||||
* **-EPERM** if caller does not have permission to obtain kernel address.
|
||||
*/
|
||||
#define __BPF_FUNC_MAPPER(FN) \
|
||||
FN(unspec), \
|
||||
|
|
@ -5055,6 +5116,10 @@ union bpf_attr {
|
|||
FN(get_func_ip), \
|
||||
FN(get_attach_cookie), \
|
||||
FN(task_pt_regs), \
|
||||
FN(get_branch_snapshot), \
|
||||
FN(trace_vprintk), \
|
||||
FN(skc_to_unix_sock), \
|
||||
FN(kallsyms_lookup_name), \
|
||||
/* */
|
||||
|
||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||
|
|
@ -5284,6 +5349,8 @@ struct __sk_buff {
|
|||
__u32 gso_segs;
|
||||
__bpf_md_ptr(struct bpf_sock *, sk);
|
||||
__u32 gso_size;
|
||||
__u32 :32; /* Padding, future use. */
|
||||
__u64 hwtstamp;
|
||||
};
|
||||
|
||||
struct bpf_tunnel_key {
|
||||
|
|
@ -5577,6 +5644,7 @@ struct bpf_prog_info {
|
|||
__u64 run_time_ns;
|
||||
__u64 run_cnt;
|
||||
__u64 recursion_misses;
|
||||
__u32 verified_insns;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
struct bpf_map_info {
|
||||
|
|
@ -5594,6 +5662,8 @@ struct bpf_map_info {
|
|||
__u32 btf_id;
|
||||
__u32 btf_key_type_id;
|
||||
__u32 btf_value_type_id;
|
||||
__u32 :32; /* alignment pad */
|
||||
__u64 map_extra;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
struct bpf_btf_info {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ struct btf_type {
|
|||
* "size" tells the size of the type it is describing.
|
||||
*
|
||||
* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT,
|
||||
* FUNC, FUNC_PROTO and VAR.
|
||||
* FUNC, FUNC_PROTO, VAR and DECL_TAG.
|
||||
* "type" is a type_id referring to another type.
|
||||
*/
|
||||
union {
|
||||
|
|
@ -56,25 +56,29 @@ struct btf_type {
|
|||
#define BTF_INFO_VLEN(info) ((info) & 0xffff)
|
||||
#define BTF_INFO_KFLAG(info) ((info) >> 31)
|
||||
|
||||
#define BTF_KIND_UNKN 0 /* Unknown */
|
||||
#define BTF_KIND_INT 1 /* Integer */
|
||||
#define BTF_KIND_PTR 2 /* Pointer */
|
||||
#define BTF_KIND_ARRAY 3 /* Array */
|
||||
#define BTF_KIND_STRUCT 4 /* Struct */
|
||||
#define BTF_KIND_UNION 5 /* Union */
|
||||
#define BTF_KIND_ENUM 6 /* Enumeration */
|
||||
#define BTF_KIND_FWD 7 /* Forward */
|
||||
#define BTF_KIND_TYPEDEF 8 /* Typedef */
|
||||
#define BTF_KIND_VOLATILE 9 /* Volatile */
|
||||
#define BTF_KIND_CONST 10 /* Const */
|
||||
#define BTF_KIND_RESTRICT 11 /* Restrict */
|
||||
#define BTF_KIND_FUNC 12 /* Function */
|
||||
#define BTF_KIND_FUNC_PROTO 13 /* Function Proto */
|
||||
#define BTF_KIND_VAR 14 /* Variable */
|
||||
#define BTF_KIND_DATASEC 15 /* Section */
|
||||
#define BTF_KIND_FLOAT 16 /* Floating point */
|
||||
#define BTF_KIND_MAX BTF_KIND_FLOAT
|
||||
#define NR_BTF_KINDS (BTF_KIND_MAX + 1)
|
||||
enum {
|
||||
BTF_KIND_UNKN = 0, /* Unknown */
|
||||
BTF_KIND_INT = 1, /* Integer */
|
||||
BTF_KIND_PTR = 2, /* Pointer */
|
||||
BTF_KIND_ARRAY = 3, /* Array */
|
||||
BTF_KIND_STRUCT = 4, /* Struct */
|
||||
BTF_KIND_UNION = 5, /* Union */
|
||||
BTF_KIND_ENUM = 6, /* Enumeration */
|
||||
BTF_KIND_FWD = 7, /* Forward */
|
||||
BTF_KIND_TYPEDEF = 8, /* Typedef */
|
||||
BTF_KIND_VOLATILE = 9, /* Volatile */
|
||||
BTF_KIND_CONST = 10, /* Const */
|
||||
BTF_KIND_RESTRICT = 11, /* Restrict */
|
||||
BTF_KIND_FUNC = 12, /* Function */
|
||||
BTF_KIND_FUNC_PROTO = 13, /* Function Proto */
|
||||
BTF_KIND_VAR = 14, /* Variable */
|
||||
BTF_KIND_DATASEC = 15, /* Section */
|
||||
BTF_KIND_FLOAT = 16, /* Floating point */
|
||||
BTF_KIND_DECL_TAG = 17, /* Decl Tag */
|
||||
|
||||
NR_BTF_KINDS,
|
||||
BTF_KIND_MAX = NR_BTF_KINDS - 1,
|
||||
};
|
||||
|
||||
/* For some specific BTF_KIND, "struct btf_type" is immediately
|
||||
* followed by extra data.
|
||||
|
|
@ -170,4 +174,15 @@ struct btf_var_secinfo {
|
|||
__u32 size;
|
||||
};
|
||||
|
||||
/* BTF_KIND_DECL_TAG is followed by a single "struct btf_decl_tag" to describe
|
||||
* additional information related to the tag applied location.
|
||||
* If component_idx == -1, the tag is applied to a struct, union,
|
||||
* variable or function. Otherwise, it is applied to a struct/union
|
||||
* member or a func argument, and component_idx indicates which member
|
||||
* or argument (0 ... vlen-1).
|
||||
*/
|
||||
struct btf_decl_tag {
|
||||
__s32 component_idx;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_BTF_H__ */
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ struct can_ctrlmode {
|
|||
#define CAN_CTRLMODE_PRESUME_ACK 0x40 /* Ignore missing CAN ACKs */
|
||||
#define CAN_CTRLMODE_FD_NON_ISO 0x80 /* CAN FD in non-ISO mode */
|
||||
#define CAN_CTRLMODE_CC_LEN8_DLC 0x100 /* Classic CAN DLC option */
|
||||
#define CAN_CTRLMODE_TDC_AUTO 0x200 /* CAN transiver automatically calculates TDCV */
|
||||
#define CAN_CTRLMODE_TDC_MANUAL 0x400 /* TDCV is manually set up by user */
|
||||
|
||||
/*
|
||||
* CAN device statistics
|
||||
|
|
@ -134,10 +136,35 @@ enum {
|
|||
IFLA_CAN_BITRATE_CONST,
|
||||
IFLA_CAN_DATA_BITRATE_CONST,
|
||||
IFLA_CAN_BITRATE_MAX,
|
||||
__IFLA_CAN_MAX
|
||||
IFLA_CAN_TDC,
|
||||
|
||||
/* add new constants above here */
|
||||
__IFLA_CAN_MAX,
|
||||
IFLA_CAN_MAX = __IFLA_CAN_MAX - 1
|
||||
};
|
||||
|
||||
#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1)
|
||||
/*
|
||||
* CAN FD Transmitter Delay Compensation (TDC)
|
||||
*
|
||||
* Please refer to struct can_tdc_const and can_tdc in
|
||||
* include/linux/can/bittiming.h for further details.
|
||||
*/
|
||||
enum {
|
||||
IFLA_CAN_TDC_UNSPEC,
|
||||
IFLA_CAN_TDC_TDCV_MIN, /* u32 */
|
||||
IFLA_CAN_TDC_TDCV_MAX, /* u32 */
|
||||
IFLA_CAN_TDC_TDCO_MIN, /* u32 */
|
||||
IFLA_CAN_TDC_TDCO_MAX, /* u32 */
|
||||
IFLA_CAN_TDC_TDCF_MIN, /* u32 */
|
||||
IFLA_CAN_TDC_TDCF_MAX, /* u32 */
|
||||
IFLA_CAN_TDC_TDCV, /* u32 */
|
||||
IFLA_CAN_TDC_TDCO, /* u32 */
|
||||
IFLA_CAN_TDC_TDCF, /* u32 */
|
||||
|
||||
/* add new constants above here */
|
||||
__IFLA_CAN_TDC,
|
||||
IFLA_CAN_TDC_MAX = __IFLA_CAN_TDC - 1
|
||||
};
|
||||
|
||||
/* u16 termination range: 1..65535 Ohms */
|
||||
#define CAN_TERMINATION_DISABLED 0
|
||||
|
|
|
|||
|
|
@ -551,6 +551,8 @@ enum devlink_attr {
|
|||
DEVLINK_ATTR_RATE_NODE_NAME, /* string */
|
||||
DEVLINK_ATTR_RATE_PARENT_NODE_NAME, /* string */
|
||||
|
||||
DEVLINK_ATTR_REGION_MAX_SNAPSHOTS, /* u32 */
|
||||
|
||||
/* add new attributes above here, update the policy in devlink.c */
|
||||
|
||||
__DEVLINK_ATTR_MAX,
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@
|
|||
* over Ethernet
|
||||
*/
|
||||
#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
|
||||
#define ETH_P_REALTEK 0x8899 /* Multiple proprietary protocols */
|
||||
#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
|
||||
#define ETH_P_8021AD 0x88A8 /* 802.1ad Service VLAN */
|
||||
#define ETH_P_802_EX1 0x88B5 /* 802.1 Local Experimental 1. */
|
||||
|
|
@ -116,7 +117,7 @@
|
|||
#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
|
||||
#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is more than this value
|
||||
* then the frame is Ethernet II. Else it is 802.3 */
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -9,9 +9,38 @@
|
|||
#ifndef _LINUX_IOAM6_IPTUNNEL_H
|
||||
#define _LINUX_IOAM6_IPTUNNEL_H
|
||||
|
||||
/* Encap modes:
|
||||
* - inline: direct insertion
|
||||
* - encap: ip6ip6 encapsulation
|
||||
* - auto: __inline__ for local packets, encap for in-transit packets
|
||||
*/
|
||||
enum {
|
||||
__IOAM6_IPTUNNEL_MODE_MIN,
|
||||
|
||||
IOAM6_IPTUNNEL_MODE_INLINE,
|
||||
IOAM6_IPTUNNEL_MODE_ENCAP,
|
||||
IOAM6_IPTUNNEL_MODE_AUTO,
|
||||
|
||||
__IOAM6_IPTUNNEL_MODE_MAX,
|
||||
};
|
||||
|
||||
#define IOAM6_IPTUNNEL_MODE_MIN (__IOAM6_IPTUNNEL_MODE_MIN + 1)
|
||||
#define IOAM6_IPTUNNEL_MODE_MAX (__IOAM6_IPTUNNEL_MODE_MAX - 1)
|
||||
|
||||
enum {
|
||||
IOAM6_IPTUNNEL_UNSPEC,
|
||||
|
||||
/* Encap mode */
|
||||
IOAM6_IPTUNNEL_MODE, /* u8 */
|
||||
|
||||
/* Tunnel dst address.
|
||||
* For encap,auto modes.
|
||||
*/
|
||||
IOAM6_IPTUNNEL_DST, /* struct in6_addr */
|
||||
|
||||
/* IOAM Trace Header */
|
||||
IOAM6_IPTUNNEL_TRACE, /* struct ioam6_trace_hdr */
|
||||
|
||||
__IOAM6_IPTUNNEL_MAX,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ enum
|
|||
IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST,
|
||||
IPV4_DEVCONF_DROP_GRATUITOUS_ARP,
|
||||
IPV4_DEVCONF_BC_FORWARDING,
|
||||
IPV4_DEVCONF_ARP_EVICT_NOCARRIER,
|
||||
__IPV4_DEVCONF_MAX
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@
|
|||
|
||||
#include <linux/const.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/in.h> /* for sockaddr_in */
|
||||
#include <linux/in6.h> /* for sockaddr_in6 */
|
||||
#include <linux/socket.h> /* for sockaddr_storage and sa_family */
|
||||
|
||||
#include <sys/socket.h> /* for struct sockaddr */
|
||||
|
||||
#define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0)
|
||||
#define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1)
|
||||
|
|
@ -193,4 +198,32 @@ enum mptcp_event_attr {
|
|||
#define MPTCP_RST_EBADPERF 5
|
||||
#define MPTCP_RST_EMIDDLEBOX 6
|
||||
|
||||
struct mptcp_subflow_data {
|
||||
__u32 size_subflow_data; /* size of this structure in userspace */
|
||||
__u32 num_subflows; /* must be 0, set by kernel */
|
||||
__u32 size_kernel; /* must be 0, set by kernel */
|
||||
__u32 size_user; /* size of one element in data[] */
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
struct mptcp_subflow_addrs {
|
||||
union {
|
||||
__kernel_sa_family_t sa_family;
|
||||
struct sockaddr sa_local;
|
||||
struct sockaddr_in sin_local;
|
||||
struct sockaddr_in6 sin6_local;
|
||||
struct __kernel_sockaddr_storage ss_local;
|
||||
};
|
||||
union {
|
||||
struct sockaddr sa_remote;
|
||||
struct sockaddr_in sin_remote;
|
||||
struct sockaddr_in6 sin6_remote;
|
||||
struct __kernel_sockaddr_storage ss_remote;
|
||||
};
|
||||
};
|
||||
|
||||
/* MPTCP socket options */
|
||||
#define MPTCP_INFO 1
|
||||
#define MPTCP_TCPINFO 2
|
||||
#define MPTCP_SUBFLOW_ADDRS 3
|
||||
|
||||
#endif /* _MPTCP_H */
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ enum {
|
|||
NDA_PROTOCOL, /* Originator of entry */
|
||||
NDA_NH_ID,
|
||||
NDA_FDB_EXT_ATTRS,
|
||||
NDA_FLAGS_EXT,
|
||||
__NDA_MAX
|
||||
};
|
||||
|
||||
|
|
@ -40,14 +41,16 @@ enum {
|
|||
* Neighbor Cache Entry Flags
|
||||
*/
|
||||
|
||||
#define NTF_USE 0x01
|
||||
#define NTF_SELF 0x02
|
||||
#define NTF_MASTER 0x04
|
||||
#define NTF_PROXY 0x08 /* == ATF_PUBL */
|
||||
#define NTF_EXT_LEARNED 0x10
|
||||
#define NTF_OFFLOADED 0x20
|
||||
#define NTF_STICKY 0x40
|
||||
#define NTF_ROUTER 0x80
|
||||
#define NTF_USE (1 << 0)
|
||||
#define NTF_SELF (1 << 1)
|
||||
#define NTF_MASTER (1 << 2)
|
||||
#define NTF_PROXY (1 << 3) /* == ATF_PUBL */
|
||||
#define NTF_EXT_LEARNED (1 << 4)
|
||||
#define NTF_OFFLOADED (1 << 5)
|
||||
#define NTF_STICKY (1 << 6)
|
||||
#define NTF_ROUTER (1 << 7)
|
||||
/* Extended flags under NDA_FLAGS_EXT: */
|
||||
#define NTF_EXT_MANAGED (1 << 0)
|
||||
|
||||
/*
|
||||
* Neighbor Cache Entry States.
|
||||
|
|
@ -65,12 +68,22 @@ enum {
|
|||
#define NUD_PERMANENT 0x80
|
||||
#define NUD_NONE 0x00
|
||||
|
||||
/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change
|
||||
* and make no address resolution or NUD.
|
||||
* NUD_PERMANENT also cannot be deleted by garbage collectors.
|
||||
/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change and make no
|
||||
* address resolution or NUD.
|
||||
*
|
||||
* NUD_PERMANENT also cannot be deleted by garbage collectors. This holds true
|
||||
* for dynamic entries with NTF_EXT_LEARNED flag as well. However, upon carrier
|
||||
* down event, NUD_PERMANENT entries are not flushed whereas NTF_EXT_LEARNED
|
||||
* flagged entries explicitly are (which is also consistent with the routing
|
||||
* subsystem).
|
||||
*
|
||||
* When NTF_EXT_LEARNED is set for a bridge fdb entry the different cache entry
|
||||
* states don't make sense and thus are ignored. Such entries don't age and
|
||||
* can roam.
|
||||
*
|
||||
* NTF_EXT_MANAGED flagged neigbor entries are managed by the kernel on behalf
|
||||
* of a user space control plane, and automatically refreshed so that (if
|
||||
* possible) they remain in NUD_REACHABLE state.
|
||||
*/
|
||||
|
||||
struct nda_cacheinfo {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ enum nf_inet_hooks {
|
|||
|
||||
enum nf_dev_hooks {
|
||||
NF_NETDEV_INGRESS,
|
||||
NF_NETDEV_EGRESS,
|
||||
NF_NETDEV_NUMHOOKS
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -840,6 +840,8 @@ enum {
|
|||
TCA_FQ_CODEL_CE_THRESHOLD,
|
||||
TCA_FQ_CODEL_DROP_BATCH_SIZE,
|
||||
TCA_FQ_CODEL_MEMORY_LIMIT,
|
||||
TCA_FQ_CODEL_CE_THRESHOLD_SELECTOR,
|
||||
TCA_FQ_CODEL_CE_THRESHOLD_MASK,
|
||||
__TCA_FQ_CODEL_MAX
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,3 +4,40 @@
|
|||
#ifndef __always_inline
|
||||
#define __always_inline __inline__
|
||||
#endif
|
||||
|
||||
/**
|
||||
* __struct_group() - Create a mirrored named and anonyomous struct
|
||||
*
|
||||
* @TAG: The tag name for the named sub-struct (usually empty)
|
||||
* @NAME: The identifier name of the mirrored sub-struct
|
||||
* @ATTRS: Any struct attributes (usually empty)
|
||||
* @MEMBERS: The member declarations for the mirrored structs
|
||||
*
|
||||
* Used to create an anonymous union of two structs with identical layout
|
||||
* and size: one anonymous and one named. The former's members can be used
|
||||
* normally without sub-struct naming, and the latter can be used to
|
||||
* reason about the start, end, and size of the group of struct members.
|
||||
* The named struct can also be explicitly tagged for layer reuse, as well
|
||||
* as both having struct attributes appended.
|
||||
*/
|
||||
#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \
|
||||
union { \
|
||||
struct { MEMBERS } ATTRS; \
|
||||
struct TAG { MEMBERS } ATTRS NAME; \
|
||||
}
|
||||
|
||||
/**
|
||||
* __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
|
||||
*
|
||||
* @TYPE: The type of each flexible array element
|
||||
* @NAME: The name of the flexible array member
|
||||
*
|
||||
* In order to have a flexible array member in a union or alone in a
|
||||
* struct, it needs to be wrapped in an anonymous struct with at least 1
|
||||
* named member, but that member can be empty.
|
||||
*/
|
||||
#define __DECLARE_FLEX_ARRAY(TYPE, NAME) \
|
||||
struct { \
|
||||
struct { } __empty_ ## NAME; \
|
||||
TYPE NAME[]; \
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,20 @@
|
|||
#define TLS_CIPHER_CHACHA20_POLY1305_TAG_SIZE 16
|
||||
#define TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE 8
|
||||
|
||||
#define TLS_CIPHER_SM4_GCM 55
|
||||
#define TLS_CIPHER_SM4_GCM_IV_SIZE 8
|
||||
#define TLS_CIPHER_SM4_GCM_KEY_SIZE 16
|
||||
#define TLS_CIPHER_SM4_GCM_SALT_SIZE 4
|
||||
#define TLS_CIPHER_SM4_GCM_TAG_SIZE 16
|
||||
#define TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE 8
|
||||
|
||||
#define TLS_CIPHER_SM4_CCM 56
|
||||
#define TLS_CIPHER_SM4_CCM_IV_SIZE 8
|
||||
#define TLS_CIPHER_SM4_CCM_KEY_SIZE 16
|
||||
#define TLS_CIPHER_SM4_CCM_SALT_SIZE 4
|
||||
#define TLS_CIPHER_SM4_CCM_TAG_SIZE 16
|
||||
#define TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE 8
|
||||
|
||||
#define TLS_SET_RECORD_TYPE 1
|
||||
#define TLS_GET_RECORD_TYPE 2
|
||||
|
||||
|
|
@ -124,6 +138,22 @@ struct tls12_crypto_info_chacha20_poly1305 {
|
|||
unsigned char rec_seq[TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE];
|
||||
};
|
||||
|
||||
struct tls12_crypto_info_sm4_gcm {
|
||||
struct tls_crypto_info info;
|
||||
unsigned char iv[TLS_CIPHER_SM4_GCM_IV_SIZE];
|
||||
unsigned char key[TLS_CIPHER_SM4_GCM_KEY_SIZE];
|
||||
unsigned char salt[TLS_CIPHER_SM4_GCM_SALT_SIZE];
|
||||
unsigned char rec_seq[TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE];
|
||||
};
|
||||
|
||||
struct tls12_crypto_info_sm4_ccm {
|
||||
struct tls_crypto_info info;
|
||||
unsigned char iv[TLS_CIPHER_SM4_CCM_IV_SIZE];
|
||||
unsigned char key[TLS_CIPHER_SM4_CCM_KEY_SIZE];
|
||||
unsigned char salt[TLS_CIPHER_SM4_CCM_SALT_SIZE];
|
||||
unsigned char rec_seq[TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE];
|
||||
};
|
||||
|
||||
enum {
|
||||
TLS_INFO_UNSPEC,
|
||||
TLS_INFO_VERSION,
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
|
||||
/*
|
||||
* vdpa device management interface
|
||||
* Copyright (c) 2020 Mellanox Technologies Ltd. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_VDPA_H_
|
||||
#define _LINUX_VDPA_H_
|
||||
|
||||
#define VDPA_GENL_NAME "vdpa"
|
||||
#define VDPA_GENL_VERSION 0x1
|
||||
|
||||
enum vdpa_command {
|
||||
VDPA_CMD_UNSPEC,
|
||||
VDPA_CMD_MGMTDEV_NEW,
|
||||
VDPA_CMD_MGMTDEV_GET, /* can dump */
|
||||
VDPA_CMD_DEV_NEW,
|
||||
VDPA_CMD_DEV_DEL,
|
||||
VDPA_CMD_DEV_GET, /* can dump */
|
||||
};
|
||||
|
||||
enum vdpa_attr {
|
||||
VDPA_ATTR_UNSPEC,
|
||||
|
||||
/* bus name (optional) + dev name together make the parent device handle */
|
||||
VDPA_ATTR_MGMTDEV_BUS_NAME, /* string */
|
||||
VDPA_ATTR_MGMTDEV_DEV_NAME, /* string */
|
||||
VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES, /* u64 */
|
||||
|
||||
VDPA_ATTR_DEV_NAME, /* string */
|
||||
VDPA_ATTR_DEV_ID, /* u32 */
|
||||
VDPA_ATTR_DEV_VENDOR_ID, /* u32 */
|
||||
VDPA_ATTR_DEV_MAX_VQS, /* u32 */
|
||||
VDPA_ATTR_DEV_MAX_VQ_SIZE, /* u16 */
|
||||
|
||||
/* new attributes must be added above here */
|
||||
VDPA_ATTR_MAX,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -198,9 +198,15 @@ bool matches(const char *prefix, const char *string);
|
|||
int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits);
|
||||
int inet_addr_match_rta(const inet_prefix *m, const struct rtattr *rta);
|
||||
|
||||
const char *ax25_ntop(int af, const void *addr, char *str, socklen_t len);
|
||||
|
||||
const char *rose_ntop(int af, const void *addr, char *buf, socklen_t buflen);
|
||||
|
||||
const char *mpls_ntop(int af, const void *addr, char *str, size_t len);
|
||||
int mpls_pton(int af, const char *src, void *addr, size_t alen);
|
||||
|
||||
const char *netrom_ntop(int af, const void *addr, char *str, socklen_t len);
|
||||
|
||||
extern int __iproute2_hz_internal;
|
||||
int __get_hz(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,14 +11,15 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.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 iplink_netdevsim.o iplink_rmnet.o \
|
||||
ipnexthop.o ipmptcp.o iplink_bareudp.o iplink_wwan.o ipioam6.o
|
||||
ipnexthop.o ipmptcp.o iplink_bareudp.o iplink_wwan.o ipioam6.o \
|
||||
iplink_amt.o
|
||||
|
||||
RTMONOBJ=rtmon.o
|
||||
|
||||
include ../config.mk
|
||||
|
||||
ALLOBJ=$(IPOBJ) $(RTMONOBJ)
|
||||
SCRIPTS=ifcfg rtpr routel routef
|
||||
SCRIPTS=routel
|
||||
TARGETS=ip rtmon
|
||||
|
||||
all: $(TARGETS) $(SCRIPTS)
|
||||
|
|
|
|||
150
ip/ifcfg
150
ip/ifcfg
|
|
@ -1,150 +0,0 @@
|
|||
#! /bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
CheckForwarding () {
|
||||
local sbase fwd
|
||||
sbase=/proc/sys/net/ipv4/conf
|
||||
fwd=0
|
||||
if [ -d $sbase ]; then
|
||||
for dir in $sbase/*/forwarding; do
|
||||
fwd=$(( fwd + $(cat "$dir") ))
|
||||
done
|
||||
else
|
||||
fwd=2
|
||||
fi
|
||||
return $fwd
|
||||
}
|
||||
|
||||
RestartRDISC () {
|
||||
killall -HUP rdisc || rdisc -fs
|
||||
}
|
||||
|
||||
ABCMaskLen () {
|
||||
local class;
|
||||
|
||||
class=${1%%.*}
|
||||
if [ "$1" = "" -o $class -eq 0 -o $class -ge 224 ]; then return 0
|
||||
elif [ $class -ge 224 ]; then return 0
|
||||
elif [ $class -ge 192 ]; then return 24
|
||||
elif [ $class -ge 128 ]; then return 16
|
||||
else return 8; fi
|
||||
}
|
||||
|
||||
label="label $1"
|
||||
ldev="$1"
|
||||
dev=${1%:*}
|
||||
if [ "$dev" = "" -o "$1" = "help" ]; then
|
||||
echo "Usage: ifcfg DEV [[add|del [ADDR[/LEN]] [PEER] | stop]" 1>&2
|
||||
echo " add - add new address" 1>&2
|
||||
echo " del - delete address" 1>&2
|
||||
echo " stop - completely disable IP" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
|
||||
CheckForwarding
|
||||
fwd=$?
|
||||
if [ $fwd -ne 0 ]; then
|
||||
echo "Forwarding is ON or its state is unknown ($fwd). OK, No RDISC." 1>&2
|
||||
fi
|
||||
|
||||
|
||||
deleting=0
|
||||
case "$1" in
|
||||
add) shift ;;
|
||||
stop)
|
||||
if [ "$ldev" != "$dev" ]; then
|
||||
echo "Cannot stop alias $ldev" 1>&2
|
||||
exit 1;
|
||||
fi
|
||||
ip -4 addr flush dev $dev $label || exit 1
|
||||
if [ $fwd -eq 0 ]; then RestartRDISC; fi
|
||||
exit 0 ;;
|
||||
del*)
|
||||
deleting=1; shift ;;
|
||||
*)
|
||||
esac
|
||||
|
||||
ipaddr=
|
||||
pfxlen=
|
||||
if [ "$1" != "" ]; then
|
||||
ipaddr=${1%/*}
|
||||
if [ "$1" != "$ipaddr" ]; then
|
||||
pfxlen=${1#*/}
|
||||
fi
|
||||
if [ "$ipaddr" = "" ]; then
|
||||
echo "$1 is bad IP address." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
shift
|
||||
|
||||
peer=$1
|
||||
if [ "$peer" != "" ]; then
|
||||
if [ "$pfxlen" != "" -a "$pfxlen" != "32" ]; then
|
||||
echo "Peer address with non-trivial netmask." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
pfx="$ipaddr peer $peer"
|
||||
else
|
||||
if [ "$ipaddr" = "" ]; then
|
||||
echo "Missing IP address argument." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$pfxlen" = "" ]; then
|
||||
ABCMaskLen $ipaddr
|
||||
pfxlen=$?
|
||||
fi
|
||||
pfx="$ipaddr/$pfxlen"
|
||||
fi
|
||||
|
||||
if [ "$ldev" = "$dev" -a "$ipaddr" != "" ]; then
|
||||
label=
|
||||
fi
|
||||
|
||||
if [ $deleting -ne 0 ]; then
|
||||
ip addr del $pfx dev $dev $label || exit 1
|
||||
if [ $fwd -eq 0 ]; then RestartRDISC; fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
if ! ip link set up dev $dev ; then
|
||||
echo "Error: cannot enable interface $dev." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$ipaddr" = "" ]; then exit 0; fi
|
||||
|
||||
if ! arping -q -c 2 -w 3 -D -I $dev $ipaddr ; then
|
||||
echo "Error: some host already uses address $ipaddr on $dev." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! ip address add $pfx brd + dev $dev $label; then
|
||||
echo "Error: failed to add $pfx on $dev." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
arping -q -A -c 1 -I $dev $ipaddr
|
||||
noarp=$?
|
||||
( sleep 2 ;
|
||||
arping -q -U -c 1 -I $dev $ipaddr ) >/dev/null 2>&1 </dev/null &
|
||||
|
||||
ip route add unreachable 224.0.0.0/24 >/dev/null 2>&1
|
||||
ip route add unreachable 255.255.255.255 >/dev/null 2>&1
|
||||
if [ "`ip link ls $dev | grep -c MULTICAST`" -ge 1 ]; then
|
||||
ip route add 224.0.0.0/4 dev $dev scope global >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
if [ $fwd -eq 0 ]; then
|
||||
if [ $noarp -eq 0 ]; then
|
||||
ip ro append default dev $dev metric 30000 scope global
|
||||
elif [ "$peer" != "" ]; then
|
||||
if ping -q -c 2 -w 4 $peer ; then
|
||||
ip ro append default via $peer dev $dev metric 30001
|
||||
fi
|
||||
fi
|
||||
RestartRDISC
|
||||
fi
|
||||
|
||||
exit 0
|
||||
4
ip/ip.c
4
ip/ip.c
|
|
@ -64,8 +64,8 @@ static void usage(void)
|
|||
fprintf(stderr,
|
||||
"Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n"
|
||||
" ip [ -force ] -batch filename\n"
|
||||
"where OBJECT := { address | addrlabel | fou | help | ila | ioam | l2tp | link |\n"
|
||||
" macsec | maddress | monitor | mptcp | mroute | mrule |\n"
|
||||
"where OBJECT := { address | addrlabel | amt | fou | help | ila | ioam | l2tp |\n"
|
||||
" link | macsec | maddress | monitor | mptcp | mroute | mrule |\n"
|
||||
" neighbor | neighbour | netconf | netns | nexthop | ntable |\n"
|
||||
" ntbl | route | rule | sr | tap | tcpmetrics |\n"
|
||||
" token | tunnel | tuntap | vrf | xfrm }\n"
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ int print_prefix(struct nlmsghdr *n, void *arg);
|
|||
int print_rule(struct nlmsghdr *n, void *arg);
|
||||
int print_netconf(struct rtnl_ctrl_data *ctrl,
|
||||
struct nlmsghdr *n, void *arg);
|
||||
int print_nexthop(struct nlmsghdr *n, void *arg);
|
||||
int print_nexthop_bucket(struct nlmsghdr *n, void *arg);
|
||||
void netns_map_init(void);
|
||||
void netns_nsid_socket_init(void);
|
||||
|
|
@ -168,7 +167,8 @@ int name_is_vrf(const char *name);
|
|||
|
||||
void print_num(FILE *fp, unsigned int width, uint64_t count);
|
||||
void print_rt_flags(FILE *fp, unsigned int flags);
|
||||
void print_rta_if(FILE *fp, const struct rtattr *rta, const char *prefix);
|
||||
void print_rta_ifidx(FILE *fp, __u32 ifidx, const char *prefix);
|
||||
void __print_rta_gateway(FILE *fp, unsigned char family, const char *gateway);
|
||||
void print_rta_gateway(FILE *fp, unsigned char family,
|
||||
const struct rtattr *rta);
|
||||
#endif /* _IP_COMMON_H_ */
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ static void usage(void)
|
|||
" ip address {save|flush} [ dev IFNAME ] [ scope SCOPE-ID ]\n"
|
||||
" [ to PREFIX ] [ FLAG-LIST ] [ label LABEL ] [up]\n"
|
||||
" ip address [ show [ dev IFNAME ] [ scope SCOPE-ID ] [ master DEVICE ]\n"
|
||||
" [ nomaster ]\n"
|
||||
" [ type TYPE ] [ to PREFIX ] [ FLAG-LIST ]\n"
|
||||
" [ label LABEL ] [up] [ vrf NAME ] ]\n"
|
||||
" ip address {showdump|restore}\n"
|
||||
|
|
@ -2123,6 +2124,8 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
|
|||
if (!name_is_vrf(*argv))
|
||||
invarg("Not a valid VRF name\n", *argv);
|
||||
filter.master = ifindex;
|
||||
} else if (strcmp(*argv, "nomaster") == 0) {
|
||||
filter.master = -1;
|
||||
} else if (strcmp(*argv, "type") == 0) {
|
||||
int soff;
|
||||
|
||||
|
|
|
|||
14
ip/iplink.c
14
ip/iplink.c
|
|
@ -50,7 +50,7 @@ void iplink_types_usage(void)
|
|||
{
|
||||
/* Remember to add new entry here if new type is added. */
|
||||
fprintf(stderr,
|
||||
"TYPE := { bareudp | bond | bond_slave | bridge | bridge_slave |\n"
|
||||
"TYPE := { amt | bareudp | bond | bond_slave | bridge | bridge_slave |\n"
|
||||
" dummy | erspan | geneve | gre | gretap | ifb |\n"
|
||||
" ip6erspan | ip6gre | ip6gretap | ip6tnl |\n"
|
||||
" ipip | ipoib | ipvlan | ipvtap |\n"
|
||||
|
|
@ -120,6 +120,7 @@ void iplink_usage(void)
|
|||
" [ gso_max_size BYTES ] | [ gso_max_segs PACKETS ]\n"
|
||||
"\n"
|
||||
" ip link show [ DEVICE | group GROUP ] [up] [master DEV] [vrf NAME] [type TYPE]\n"
|
||||
" [nomaster]\n"
|
||||
"\n"
|
||||
" ip link xstats type TYPE [ ARGS ]\n"
|
||||
"\n"
|
||||
|
|
@ -578,6 +579,7 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
|
|||
|
||||
int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type)
|
||||
{
|
||||
bool move_netns = false;
|
||||
char *name = NULL;
|
||||
char *dev = NULL;
|
||||
char *link = NULL;
|
||||
|
|
@ -683,6 +685,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type)
|
|||
IFLA_NET_NS_PID, &netns, 4);
|
||||
else
|
||||
invarg("Invalid \"netns\" value\n", *argv);
|
||||
move_netns = true;
|
||||
} else if (strcmp(*argv, "multicast") == 0) {
|
||||
NEXT_ARG();
|
||||
req->i.ifi_change |= IFF_MULTICAST;
|
||||
|
|
@ -980,9 +983,11 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type)
|
|||
}
|
||||
}
|
||||
|
||||
if (!(req->n.nlmsg_flags & NLM_F_CREATE) && index) {
|
||||
if (index &&
|
||||
(!(req->n.nlmsg_flags & NLM_F_CREATE) &&
|
||||
!move_netns)) {
|
||||
fprintf(stderr,
|
||||
"index can be used only when creating devices.\n");
|
||||
"index can be used only when creating devices or when moving device to another netns.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
|
@ -1019,6 +1024,9 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type)
|
|||
/* Not renaming to the same name */
|
||||
if (name == dev)
|
||||
name = NULL;
|
||||
|
||||
if (index)
|
||||
addattr32(&req->n, sizeof(*req), IFLA_NEW_IFINDEX, index);
|
||||
} else {
|
||||
if (name != dev) {
|
||||
fprintf(stderr,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* iplink_amt.c AMT device support
|
||||
*
|
||||
* 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: Taehee Yoo <ap420073@gmail.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/amt.h>
|
||||
|
||||
#include "rt_names.h"
|
||||
#include "utils.h"
|
||||
#include "ip_common.h"
|
||||
|
||||
#define AMT_ATTRSET(attrs, type) (((attrs) & (1L << (type))) != 0)
|
||||
|
||||
static void print_usage(FILE *f)
|
||||
{
|
||||
fprintf(f,
|
||||
"Usage: ... amt\n"
|
||||
" [ discovery IP_ADDRESS ]\n"
|
||||
" [ mode MODE ]\n"
|
||||
" [ local ADDR ]\n"
|
||||
" [ dev PHYS_DEV ]\n"
|
||||
" [ relay_port PORT ]\n"
|
||||
" [ gateway_port PORT ]\n"
|
||||
" [ max_tunnels NUMBER ]\n"
|
||||
"\n"
|
||||
"Where: ADDR := { IP_ADDRESS }\n"
|
||||
" MODE := { gateway | relay }\n"
|
||||
);
|
||||
}
|
||||
|
||||
static char *modename[] = {"gateway", "relay"};
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
print_usage(stderr);
|
||||
}
|
||||
|
||||
static void check_duparg(__u64 *attrs, int type, const char *key,
|
||||
const char *argv)
|
||||
{
|
||||
if (!AMT_ATTRSET(*attrs, type)) {
|
||||
*attrs |= (1L << type);
|
||||
return;
|
||||
}
|
||||
duparg2(key, argv);
|
||||
}
|
||||
|
||||
static int amt_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||
struct nlmsghdr *n)
|
||||
{
|
||||
unsigned int mode, max_tunnels;
|
||||
inet_prefix saddr, daddr;
|
||||
__u64 attrs = 0;
|
||||
__u16 port;
|
||||
|
||||
saddr.family = daddr.family = AF_UNSPEC;
|
||||
|
||||
inet_prefix_reset(&saddr);
|
||||
inet_prefix_reset(&daddr);
|
||||
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "mode") == 0) {
|
||||
NEXT_ARG();
|
||||
if (strcmp(*argv, "gateway") == 0) {
|
||||
mode = 0;
|
||||
} else if (strcmp(*argv, "relay") == 0) {
|
||||
mode = 1;
|
||||
} else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
addattr32(n, 1024, IFLA_AMT_MODE, mode);
|
||||
} else if (strcmp(*argv, "relay_port") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u16(&port, *argv, 0))
|
||||
invarg("relay_port", *argv);
|
||||
addattr16(n, 1024, IFLA_AMT_RELAY_PORT, htons(port));
|
||||
} else if (strcmp(*argv, "gateway_port") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u16(&port, *argv, 0))
|
||||
invarg("gateway_port", *argv);
|
||||
addattr16(n, 1024, IFLA_AMT_GATEWAY_PORT, htons(port));
|
||||
} else if (strcmp(*argv, "max_tunnels") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u32(&max_tunnels, *argv, 0))
|
||||
invarg("max_tunnels", *argv);
|
||||
addattr32(n, 1024, IFLA_AMT_MAX_TUNNELS, max_tunnels);
|
||||
} else if (strcmp(*argv, "dev") == 0) {
|
||||
unsigned int link;
|
||||
|
||||
NEXT_ARG();
|
||||
link = ll_name_to_index(*argv);
|
||||
if (!link)
|
||||
exit(nodev(*argv));
|
||||
addattr32(n, 1024, IFLA_AMT_LINK, link);
|
||||
} else if (strcmp(*argv, "local") == 0) {
|
||||
NEXT_ARG();
|
||||
check_duparg(&attrs, IFLA_AMT_LOCAL_IP, "local", *argv);
|
||||
get_addr(&saddr, *argv, daddr.family);
|
||||
|
||||
if (is_addrtype_inet(&saddr))
|
||||
addattr_l(n, 1024, IFLA_AMT_LOCAL_IP,
|
||||
saddr.data, saddr.bytelen);
|
||||
} else if (strcmp(*argv, "discovery") == 0) {
|
||||
NEXT_ARG();
|
||||
check_duparg(&attrs, IFLA_AMT_DISCOVERY_IP,
|
||||
"discovery", *argv);
|
||||
get_addr(&daddr, *argv, daddr.family);
|
||||
if (is_addrtype_inet(&daddr))
|
||||
addattr_l(n, 1024, IFLA_AMT_DISCOVERY_IP,
|
||||
daddr.data, daddr.bytelen);
|
||||
} else if (strcmp(*argv, "help") == 0) {
|
||||
usage();
|
||||
return -1;
|
||||
} else {
|
||||
fprintf(stderr, "amt: unknown command \"%s\"?\n", *argv);
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
argc--, argv++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amt_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
||||
{
|
||||
if (!tb)
|
||||
return;
|
||||
|
||||
if (tb[IFLA_AMT_MODE])
|
||||
print_string(PRINT_ANY, "mode", "%s ",
|
||||
modename[rta_getattr_u32(tb[IFLA_AMT_MODE])]);
|
||||
|
||||
if (tb[IFLA_AMT_GATEWAY_PORT])
|
||||
print_uint(PRINT_ANY, "gateway_port", "gateway_port %u ",
|
||||
rta_getattr_be16(tb[IFLA_AMT_GATEWAY_PORT]));
|
||||
|
||||
if (tb[IFLA_AMT_RELAY_PORT])
|
||||
print_uint(PRINT_ANY, "relay_port", "relay_port %u ",
|
||||
rta_getattr_be16(tb[IFLA_AMT_RELAY_PORT]));
|
||||
|
||||
if (tb[IFLA_AMT_LOCAL_IP]) {
|
||||
__be32 addr = rta_getattr_u32(tb[IFLA_AMT_LOCAL_IP]);
|
||||
|
||||
print_string(PRINT_ANY, "local", "local %s ",
|
||||
format_host(AF_INET, 4, &addr));
|
||||
}
|
||||
|
||||
if (tb[IFLA_AMT_REMOTE_IP]) {
|
||||
__be32 addr = rta_getattr_u32(tb[IFLA_AMT_REMOTE_IP]);
|
||||
|
||||
print_string(PRINT_ANY, "remote", "remote %s ",
|
||||
format_host(AF_INET, 4, &addr));
|
||||
}
|
||||
|
||||
if (tb[IFLA_AMT_DISCOVERY_IP]) {
|
||||
__be32 addr = rta_getattr_u32(tb[IFLA_AMT_DISCOVERY_IP]);
|
||||
|
||||
print_string(PRINT_ANY, "discovery", "discovery %s ",
|
||||
format_host(AF_INET, 4, &addr));
|
||||
}
|
||||
|
||||
if (tb[IFLA_AMT_LINK]) {
|
||||
unsigned int link = rta_getattr_u32(tb[IFLA_AMT_LINK]);
|
||||
|
||||
print_string(PRINT_ANY, "link", "dev %s ",
|
||||
ll_index_to_name(link));
|
||||
}
|
||||
|
||||
if (tb[IFLA_AMT_MAX_TUNNELS])
|
||||
print_uint(PRINT_ANY, "max_tunnels", "max_tunnels %u ",
|
||||
rta_getattr_u32(tb[IFLA_AMT_MAX_TUNNELS]));
|
||||
}
|
||||
|
||||
static void amt_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
|
||||
{
|
||||
print_usage(f);
|
||||
}
|
||||
|
||||
struct link_util amt_link_util = {
|
||||
.id = "amt",
|
||||
.maxattr = IFLA_AMT_MAX,
|
||||
.parse_opt = amt_parse_opt,
|
||||
.print_opt = amt_print_opt,
|
||||
.print_help = amt_print_help,
|
||||
};
|
||||
|
|
@ -43,6 +43,7 @@ static void print_explain(FILE *f)
|
|||
" [ vlan_stats_enabled VLAN_STATS_ENABLED ]\n"
|
||||
" [ vlan_stats_per_port VLAN_STATS_PER_PORT ]\n"
|
||||
" [ mcast_snooping MULTICAST_SNOOPING ]\n"
|
||||
" [ mcast_vlan_snooping MULTICAST_VLAN_SNOOPING ]\n"
|
||||
" [ mcast_router MULTICAST_ROUTER ]\n"
|
||||
" [ mcast_query_use_ifaddr MCAST_QUERY_USE_IFADDR ]\n"
|
||||
" [ mcast_querier MULTICAST_QUERIER ]\n"
|
||||
|
|
@ -83,6 +84,7 @@ void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len)
|
|||
static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||
struct nlmsghdr *n)
|
||||
{
|
||||
struct br_boolopt_multi bm = {};
|
||||
__u32 val;
|
||||
|
||||
while (argc > 0) {
|
||||
|
|
@ -200,6 +202,18 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
invarg("invalid mcast_snooping", *argv);
|
||||
|
||||
addattr8(n, 1024, IFLA_BR_MCAST_SNOOPING, mcast_snoop);
|
||||
} else if (strcmp(*argv, "mcast_vlan_snooping") == 0) {
|
||||
__u32 mcvl_bit = 1 << BR_BOOLOPT_MCAST_VLAN_SNOOPING;
|
||||
__u8 mcast_vlan_snooping;
|
||||
|
||||
NEXT_ARG();
|
||||
if (get_u8(&mcast_vlan_snooping, *argv, 0))
|
||||
invarg("invalid mcast_vlan_snooping", *argv);
|
||||
bm.optmask |= 1 << BR_BOOLOPT_MCAST_VLAN_SNOOPING;
|
||||
if (mcast_vlan_snooping)
|
||||
bm.optval |= mcvl_bit;
|
||||
else
|
||||
bm.optval &= ~mcvl_bit;
|
||||
} else if (matches(*argv, "mcast_query_use_ifaddr") == 0) {
|
||||
__u8 mcast_qui;
|
||||
|
||||
|
|
@ -379,6 +393,9 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
argc--, argv++;
|
||||
}
|
||||
|
||||
if (bm.optmask)
|
||||
addattr_l(n, 1024, IFLA_BR_MULTI_BOOLOPT,
|
||||
&bm, sizeof(bm));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -559,6 +576,18 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
"mcast_snooping %u ",
|
||||
rta_getattr_u8(tb[IFLA_BR_MCAST_SNOOPING]));
|
||||
|
||||
if (tb[IFLA_BR_MULTI_BOOLOPT]) {
|
||||
__u32 mcvl_bit = 1 << BR_BOOLOPT_MCAST_VLAN_SNOOPING;
|
||||
struct br_boolopt_multi *bm;
|
||||
|
||||
bm = RTA_DATA(tb[IFLA_BR_MULTI_BOOLOPT]);
|
||||
if (bm->optmask & mcvl_bit)
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_vlan_snooping",
|
||||
"mcast_vlan_snooping %u ",
|
||||
!!(bm->optval & mcvl_bit));
|
||||
}
|
||||
|
||||
if (tb[IFLA_BR_MCAST_ROUTER])
|
||||
print_uint(PRINT_ANY,
|
||||
"mcast_router",
|
||||
|
|
|
|||
504
ip/iplink_can.c
504
ip/iplink_can.c
|
|
@ -28,6 +28,7 @@ static void print_usage(FILE *f)
|
|||
"\n"
|
||||
"\t[ dbitrate BITRATE [ dsample-point SAMPLE-POINT] ] |\n"
|
||||
"\t[ dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1\n \t dphase-seg2 PHASE-SEG2 [ dsjw SJW ] ]\n"
|
||||
"\t[ tdcv TDCV tdco TDCO tdcf TDCF ]\n"
|
||||
"\n"
|
||||
"\t[ loopback { on | off } ]\n"
|
||||
"\t[ listen-only { on | off } ]\n"
|
||||
|
|
@ -38,20 +39,24 @@ static void print_usage(FILE *f)
|
|||
"\t[ fd-non-iso { on | off } ]\n"
|
||||
"\t[ presume-ack { on | off } ]\n"
|
||||
"\t[ cc-len8-dlc { on | off } ]\n"
|
||||
"\t[ tdc-mode { auto | manual | off } ]\n"
|
||||
"\n"
|
||||
"\t[ restart-ms TIME-MS ]\n"
|
||||
"\t[ restart ]\n"
|
||||
"\n"
|
||||
"\t[ termination { 0..65535 } ]\n"
|
||||
"\n"
|
||||
"\tWhere: BITRATE := { 1..1000000 }\n"
|
||||
"\tWhere: BITRATE := { NUMBER in bps }\n"
|
||||
"\t SAMPLE-POINT := { 0.000..0.999 }\n"
|
||||
"\t TQ := { NUMBER }\n"
|
||||
"\t PROP-SEG := { 1..8 }\n"
|
||||
"\t PHASE-SEG1 := { 1..8 }\n"
|
||||
"\t PHASE-SEG2 := { 1..8 }\n"
|
||||
"\t SJW := { 1..4 }\n"
|
||||
"\t RESTART-MS := { 0 | NUMBER }\n"
|
||||
"\t TQ := { NUMBER in ns }\n"
|
||||
"\t PROP-SEG := { NUMBER in tq }\n"
|
||||
"\t PHASE-SEG1 := { NUMBER in tq }\n"
|
||||
"\t PHASE-SEG2 := { NUMBER in tq }\n"
|
||||
"\t SJW := { NUMBER in tq }\n"
|
||||
"\t TDCV := { NUMBER in tc}\n"
|
||||
"\t TDCO := { NUMBER in tc}\n"
|
||||
"\t TDCF := { NUMBER in tc}\n"
|
||||
"\t RESTART-MS := { 0 | NUMBER in ms }\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -88,34 +93,47 @@ static void set_ctrlmode(char *name, char *arg,
|
|||
cm->mask |= flags;
|
||||
}
|
||||
|
||||
static void print_ctrlmode(FILE *f, __u32 cm)
|
||||
static void print_flag(enum output_type t, __u32 *flags, __u32 flag,
|
||||
const char* name)
|
||||
{
|
||||
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); \
|
||||
if (*flags & flag) {
|
||||
*flags &= ~flag;
|
||||
print_string(t, NULL, *flags ? "%s," : "%s", name);
|
||||
}
|
||||
_PF(CAN_CTRLMODE_LOOPBACK, "LOOPBACK");
|
||||
_PF(CAN_CTRLMODE_LISTENONLY, "LISTEN-ONLY");
|
||||
_PF(CAN_CTRLMODE_3_SAMPLES, "TRIPLE-SAMPLING");
|
||||
_PF(CAN_CTRLMODE_ONE_SHOT, "ONE-SHOT");
|
||||
_PF(CAN_CTRLMODE_BERR_REPORTING, "BERR-REPORTING");
|
||||
_PF(CAN_CTRLMODE_FD, "FD");
|
||||
_PF(CAN_CTRLMODE_FD_NON_ISO, "FD-NON-ISO");
|
||||
_PF(CAN_CTRLMODE_PRESUME_ACK, "PRESUME-ACK");
|
||||
_PF(CAN_CTRLMODE_CC_LEN8_DLC, "CC-LEN8-DLC");
|
||||
#undef _PF
|
||||
if (cm)
|
||||
print_hex(PRINT_ANY, NULL, "%x", cm);
|
||||
close_json_array(PRINT_ANY, "> ");
|
||||
}
|
||||
|
||||
static void print_ctrlmode(enum output_type t, __u32 flags, const char* key)
|
||||
{
|
||||
if (!flags)
|
||||
return;
|
||||
|
||||
open_json_array(t, is_json_context() ? key : "<");
|
||||
|
||||
print_flag(t, &flags, CAN_CTRLMODE_LOOPBACK, "LOOPBACK");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_LISTENONLY, "LISTEN-ONLY");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_3_SAMPLES, "TRIPLE-SAMPLING");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_ONE_SHOT, "ONE-SHOT");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_BERR_REPORTING, "BERR-REPORTING");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_FD, "FD");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_FD_NON_ISO, "FD-NON-ISO");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_PRESUME_ACK, "PRESUME-ACK");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_CC_LEN8_DLC, "CC-LEN8-DLC");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_TDC_AUTO, "TDC-AUTO");
|
||||
print_flag(t, &flags, CAN_CTRLMODE_TDC_MANUAL, "TDC-MANUAL");
|
||||
|
||||
if (flags)
|
||||
print_hex(t, NULL, "%x", flags);
|
||||
|
||||
close_json_array(t, "> ");
|
||||
}
|
||||
|
||||
static int can_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||
struct nlmsghdr *n)
|
||||
{
|
||||
struct can_bittiming bt = {}, dbt = {};
|
||||
struct can_ctrlmode cm = {0, 0};
|
||||
struct can_ctrlmode cm = { 0 };
|
||||
struct rtattr *tdc;
|
||||
__u32 tdcv = -1, tdco = -1, tdcf = -1;
|
||||
|
||||
while (argc > 0) {
|
||||
if (matches(*argv, "bitrate") == 0) {
|
||||
|
|
@ -181,6 +199,18 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
NEXT_ARG();
|
||||
if (get_u32(&dbt.sjw, *argv, 0))
|
||||
invarg("invalid \"dsjw\" value\n", *argv);
|
||||
} else if (matches(*argv, "tdcv") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u32(&tdcv, *argv, 0))
|
||||
invarg("invalid \"tdcv\" value\n", *argv);
|
||||
} else if (matches(*argv, "tdco") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u32(&tdco, *argv, 0))
|
||||
invarg("invalid \"tdco\" value\n", *argv);
|
||||
} else if (matches(*argv, "tdcf") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_u32(&tdcf, *argv, 0))
|
||||
invarg("invalid \"tdcf\" value\n", *argv);
|
||||
} else if (matches(*argv, "loopback") == 0) {
|
||||
NEXT_ARG();
|
||||
set_ctrlmode("loopback", *argv, &cm,
|
||||
|
|
@ -217,6 +247,23 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
NEXT_ARG();
|
||||
set_ctrlmode("cc-len8-dlc", *argv, &cm,
|
||||
CAN_CTRLMODE_CC_LEN8_DLC);
|
||||
} else if (matches(*argv, "tdc-mode") == 0) {
|
||||
NEXT_ARG();
|
||||
if (strcmp(*argv, "auto") == 0) {
|
||||
cm.flags |= CAN_CTRLMODE_TDC_AUTO;
|
||||
cm.mask |= CAN_CTRLMODE_TDC_AUTO;
|
||||
} else if (strcmp(*argv, "manual") == 0) {
|
||||
cm.flags |= CAN_CTRLMODE_TDC_MANUAL;
|
||||
cm.mask |= CAN_CTRLMODE_TDC_MANUAL;
|
||||
} else if (strcmp(*argv, "off") == 0) {
|
||||
cm.mask |= CAN_CTRLMODE_TDC_AUTO |
|
||||
CAN_CTRLMODE_TDC_MANUAL;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Error: argument of \"tdc-mode\" must be \"auto\", \"manual\" or \"off\", not \"%s\"\n",
|
||||
*argv);
|
||||
exit (-1);
|
||||
}
|
||||
} else if (matches(*argv, "restart") == 0) {
|
||||
__u32 val = 1;
|
||||
|
||||
|
|
@ -254,6 +301,17 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
if (cm.mask)
|
||||
addattr_l(n, 1024, IFLA_CAN_CTRLMODE, &cm, sizeof(cm));
|
||||
|
||||
if (tdcv != -1 || tdco != -1 || tdcf != -1) {
|
||||
tdc = addattr_nest(n, 1024, IFLA_CAN_TDC | NLA_F_NESTED);
|
||||
if (tdcv != -1)
|
||||
addattr32(n, 1024, IFLA_CAN_TDC_TDCV, tdcv);
|
||||
if (tdco != -1)
|
||||
addattr32(n, 1024, IFLA_CAN_TDC_TDCO, tdco);
|
||||
if (tdcf != -1)
|
||||
addattr32(n, 1024, IFLA_CAN_TDC_TDCF, tdcf);
|
||||
addattr_nest_end(n, tdc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -266,11 +324,75 @@ 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)
|
||||
static void can_print_nl_indent(void)
|
||||
{
|
||||
open_json_object(attr);
|
||||
print_int(PRINT_JSON, "min", NULL, min);
|
||||
print_int(PRINT_JSON, "max", NULL, max);
|
||||
print_nl();
|
||||
print_string(PRINT_FP, NULL, "%s", "\t ");
|
||||
}
|
||||
|
||||
static void can_print_timing_min_max(const char *json_attr, const char *fp_attr,
|
||||
int min, int max)
|
||||
{
|
||||
print_null(PRINT_FP, NULL, fp_attr, NULL);
|
||||
open_json_object(json_attr);
|
||||
print_uint(PRINT_ANY, "min", " %d", min);
|
||||
print_uint(PRINT_ANY, "max", "..%d", max);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
static void can_print_tdc_opt(FILE *f, struct rtattr *tdc_attr)
|
||||
{
|
||||
struct rtattr *tb[IFLA_CAN_TDC_MAX + 1];
|
||||
|
||||
parse_rtattr_nested(tb, IFLA_CAN_TDC_MAX, tdc_attr);
|
||||
if (tb[IFLA_CAN_TDC_TDCV] || tb[IFLA_CAN_TDC_TDCO] ||
|
||||
tb[IFLA_CAN_TDC_TDCF]) {
|
||||
open_json_object("tdc");
|
||||
can_print_nl_indent();
|
||||
if (tb[IFLA_CAN_TDC_TDCV]) {
|
||||
__u32 *tdcv = RTA_DATA(tb[IFLA_CAN_TDC_TDCV]);
|
||||
|
||||
print_uint(PRINT_ANY, "tdcv", " tdcv %u", *tdcv);
|
||||
}
|
||||
if (tb[IFLA_CAN_TDC_TDCO]) {
|
||||
__u32 *tdco = RTA_DATA(tb[IFLA_CAN_TDC_TDCO]);
|
||||
|
||||
print_uint(PRINT_ANY, "tdco", " tdco %u", *tdco);
|
||||
}
|
||||
if (tb[IFLA_CAN_TDC_TDCF]) {
|
||||
__u32 *tdcf = RTA_DATA(tb[IFLA_CAN_TDC_TDCF]);
|
||||
|
||||
print_uint(PRINT_ANY, "tdcf", " tdcf %u", *tdcf);
|
||||
}
|
||||
close_json_object();
|
||||
}
|
||||
}
|
||||
|
||||
static void can_print_tdc_const_opt(FILE *f, struct rtattr *tdc_attr)
|
||||
{
|
||||
struct rtattr *tb[IFLA_CAN_TDC_MAX + 1];
|
||||
|
||||
parse_rtattr_nested(tb, IFLA_CAN_TDC_MAX, tdc_attr);
|
||||
open_json_object("tdc");
|
||||
can_print_nl_indent();
|
||||
if (tb[IFLA_CAN_TDC_TDCV_MIN] && tb[IFLA_CAN_TDC_TDCV_MAX]) {
|
||||
__u32 *tdcv_min = RTA_DATA(tb[IFLA_CAN_TDC_TDCV_MIN]);
|
||||
__u32 *tdcv_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCV_MAX]);
|
||||
|
||||
can_print_timing_min_max("tdcv", " tdcv", *tdcv_min, *tdcv_max);
|
||||
}
|
||||
if (tb[IFLA_CAN_TDC_TDCO_MIN] && tb[IFLA_CAN_TDC_TDCO_MAX]) {
|
||||
__u32 *tdco_min = RTA_DATA(tb[IFLA_CAN_TDC_TDCO_MIN]);
|
||||
__u32 *tdco_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCO_MAX]);
|
||||
|
||||
can_print_timing_min_max("tdco", " tdco", *tdco_min, *tdco_max);
|
||||
}
|
||||
if (tb[IFLA_CAN_TDC_TDCF_MIN] && tb[IFLA_CAN_TDC_TDCF_MAX]) {
|
||||
__u32 *tdcf_min = RTA_DATA(tb[IFLA_CAN_TDC_TDCF_MIN]);
|
||||
__u32 *tdcf_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCF_MAX]);
|
||||
|
||||
can_print_timing_min_max("tdcf", " tdcf", *tdcf_min, *tdcf_max);
|
||||
}
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
|
|
@ -282,8 +404,7 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
if (tb[IFLA_CAN_CTRLMODE]) {
|
||||
struct can_ctrlmode *cm = RTA_DATA(tb[IFLA_CAN_CTRLMODE]);
|
||||
|
||||
if (cm->flags)
|
||||
print_ctrlmode(f, cm->flags);
|
||||
print_ctrlmode(PRINT_ANY, cm->flags, "ctrlmode");
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_STATE]) {
|
||||
|
|
@ -297,56 +418,39 @@ 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]);
|
||||
|
||||
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);
|
||||
}
|
||||
open_json_object("berr_counter");
|
||||
print_uint(PRINT_ANY, "tx", "(berr-counter tx %u", bc->txerr);
|
||||
print_uint(PRINT_ANY, "rx", " rx %u) ", bc->rxerr);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_RESTART_MS]) {
|
||||
__u32 *restart_ms = RTA_DATA(tb[IFLA_CAN_RESTART_MS]);
|
||||
|
||||
print_int(PRINT_ANY,
|
||||
"restart_ms",
|
||||
"restart-ms %d ",
|
||||
*restart_ms);
|
||||
print_uint(PRINT_ANY, "restart_ms", "restart-ms %u ",
|
||||
*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]);
|
||||
char sp[6];
|
||||
|
||||
if (is_json_context()) {
|
||||
json_writer_t *jw;
|
||||
|
||||
open_json_object("bittiming");
|
||||
print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate);
|
||||
jw = get_json_writer();
|
||||
jsonw_name(jw, "sample_point");
|
||||
jsonw_printf(jw, "%.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);
|
||||
}
|
||||
open_json_object("bittiming");
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "bitrate", " bitrate %u", bt->bitrate);
|
||||
snprintf(sp, sizeof(sp), "%.3f", bt->sample_point / 1000.);
|
||||
print_string(PRINT_ANY, "sample_point", " sample-point %s", sp);
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "tq", " tq %u", bt->tq);
|
||||
print_uint(PRINT_ANY, "prop_seg", " prop-seg %u", bt->prop_seg);
|
||||
print_uint(PRINT_ANY, "phase_seg1", " phase-seg1 %u",
|
||||
bt->phase_seg1);
|
||||
print_uint(PRINT_ANY, "phase_seg2", " phase-seg2 %u",
|
||||
bt->phase_seg2);
|
||||
print_uint(PRINT_ANY, "sjw", " sjw %u", bt->sjw);
|
||||
print_uint(PRINT_ANY, "brp", " brp %u", bt->brp);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
/* bittiming const is irrelevant if fixed bitrate is defined */
|
||||
|
|
@ -354,28 +458,18 @@ 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]);
|
||||
|
||||
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);
|
||||
}
|
||||
open_json_object("bittiming_const");
|
||||
can_print_nl_indent();
|
||||
print_string(PRINT_ANY, "name", " %s:", btc->name);
|
||||
can_print_timing_min_max("tseg1", " tseg1",
|
||||
btc->tseg1_min, btc->tseg1_max);
|
||||
can_print_timing_min_max("tseg2", " tseg2",
|
||||
btc->tseg2_min, btc->tseg2_max);
|
||||
can_print_timing_min_max("sjw", " sjw", 1, btc->sjw_max);
|
||||
can_print_timing_min_max("brp", " brp",
|
||||
btc->brp_min, btc->brp_max);
|
||||
print_uint(PRINT_ANY, "brp_inc", " brp_inc %u", btc->brp_inc);
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_BITRATE_CONST]) {
|
||||
|
|
@ -391,64 +485,52 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
bitrate = bt->bitrate;
|
||||
}
|
||||
|
||||
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]);
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "bittiming_bitrate", " bitrate %u",
|
||||
bitrate);
|
||||
can_print_nl_indent();
|
||||
open_json_array(PRINT_ANY, is_json_context() ?
|
||||
"bitrate_const" : " [");
|
||||
for (i = 0; i < bitrate_cnt; ++i) {
|
||||
/* This will keep lines below 80 signs */
|
||||
if (!(i % 6) && i) {
|
||||
can_print_nl_indent();
|
||||
print_string(PRINT_FP, NULL, "%s", " ");
|
||||
}
|
||||
|
||||
if (!(i % 6) && i)
|
||||
fprintf(f, "\n ");
|
||||
fprintf(f, "%8u ]", bitrate_const[i]);
|
||||
print_uint(PRINT_ANY, NULL,
|
||||
i < bitrate_cnt - 1 ? "%8u, " : "%8u",
|
||||
bitrate_const[i]);
|
||||
}
|
||||
close_json_array(PRINT_JSON, " ]");
|
||||
}
|
||||
|
||||
/* data bittiming is irrelevant if fixed bitrate is defined */
|
||||
if (tb[IFLA_CAN_DATA_BITTIMING] && !tb[IFLA_CAN_DATA_BITRATE_CONST]) {
|
||||
struct can_bittiming *dbt =
|
||||
RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
|
||||
char dsp[6];
|
||||
|
||||
if (is_json_context()) {
|
||||
json_writer_t *jw;
|
||||
open_json_object("data_bittiming");
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "bitrate", " dbitrate %u", dbt->bitrate);
|
||||
snprintf(dsp, sizeof(dsp), "%.3f", dbt->sample_point / 1000.);
|
||||
print_string(PRINT_ANY, "sample_point", " dsample-point %s",
|
||||
dsp);
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "tq", " dtq %u", dbt->tq);
|
||||
print_uint(PRINT_ANY, "prop_seg", " dprop-seg %u",
|
||||
dbt->prop_seg);
|
||||
print_uint(PRINT_ANY, "phase_seg1", " dphase-seg1 %u",
|
||||
dbt->phase_seg1);
|
||||
print_uint(PRINT_ANY, "phase_seg2", " dphase-seg2 %u",
|
||||
dbt->phase_seg2);
|
||||
print_uint(PRINT_ANY, "sjw", " dsjw %u", dbt->sjw);
|
||||
print_uint(PRINT_ANY, "brp", " dbrp %u", dbt->brp);
|
||||
|
||||
open_json_object("data_bittiming");
|
||||
print_int(PRINT_JSON, "bitrate", NULL, dbt->bitrate);
|
||||
jw = get_json_writer();
|
||||
jsonw_name(jw, "sample_point");
|
||||
jsonw_printf(jw, "%.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);
|
||||
}
|
||||
if (tb[IFLA_CAN_TDC])
|
||||
can_print_tdc_opt(f, tb[IFLA_CAN_TDC]);
|
||||
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
/* data bittiming const is irrelevant if fixed bitrate is defined */
|
||||
|
|
@ -457,29 +539,22 @@ 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]);
|
||||
|
||||
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);
|
||||
open_json_object("data_bittiming_const");
|
||||
can_print_nl_indent();
|
||||
print_string(PRINT_ANY, "name", " %s:", dbtc->name);
|
||||
can_print_timing_min_max("tseg1", " dtseg1",
|
||||
dbtc->tseg1_min, dbtc->tseg1_max);
|
||||
can_print_timing_min_max("tseg2", " dtseg2",
|
||||
dbtc->tseg2_min, dbtc->tseg2_max);
|
||||
can_print_timing_min_max("sjw", " dsjw", 1, dbtc->sjw_max);
|
||||
can_print_timing_min_max("brp", " dbrp",
|
||||
dbtc->brp_min, dbtc->brp_max);
|
||||
print_uint(PRINT_ANY, "brp_inc", " dbrp_inc %u", dbtc->brp_inc);
|
||||
|
||||
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_TDC])
|
||||
can_print_tdc_const_opt(f, tb[IFLA_CAN_TDC]);
|
||||
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_DATA_BITRATE_CONST]) {
|
||||
|
|
@ -497,30 +572,23 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
dbitrate = dbt->bitrate;
|
||||
}
|
||||
|
||||
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]);
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "data_bittiming_bitrate", " dbitrate %u",
|
||||
dbitrate);
|
||||
can_print_nl_indent();
|
||||
open_json_array(PRINT_ANY, is_json_context() ?
|
||||
"data_bitrate_const" : " [");
|
||||
for (i = 0; i < dbitrate_cnt; ++i) {
|
||||
/* This will keep lines below 80 signs */
|
||||
if (!(i % 6) && i) {
|
||||
can_print_nl_indent();
|
||||
print_string(PRINT_FP, NULL, "%s", " ");
|
||||
}
|
||||
|
||||
if (!(i % 6) && i)
|
||||
fprintf(f, "\n ");
|
||||
fprintf(f, "%8u ]", dbitrate_const[i]);
|
||||
print_uint(PRINT_ANY, NULL,
|
||||
i < dbitrate_cnt - 1 ? "%8u, " : "%8u",
|
||||
dbitrate_const[i]);
|
||||
}
|
||||
close_json_array(PRINT_JSON, " ]");
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_TERMINATION_CONST] && tb[IFLA_CAN_TERMINATION]) {
|
||||
|
|
@ -530,29 +598,21 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
|
|||
sizeof(*trm_const);
|
||||
int i;
|
||||
|
||||
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]);
|
||||
|
||||
fprintf(f, "%hu ]", trm_const[i]);
|
||||
}
|
||||
can_print_nl_indent();
|
||||
print_hu(PRINT_ANY, "termination", " termination %hu [ ", *trm);
|
||||
open_json_array(PRINT_JSON, "termination_const");
|
||||
for (i = 0; i < trm_cnt; ++i)
|
||||
print_hu(PRINT_ANY, NULL,
|
||||
i < trm_cnt - 1 ? "%hu, " : "%hu",
|
||||
trm_const[i]);
|
||||
close_json_array(PRINT_JSON, " ]");
|
||||
}
|
||||
|
||||
if (tb[IFLA_CAN_CLOCK]) {
|
||||
struct can_clock *clock = RTA_DATA(tb[IFLA_CAN_CLOCK]);
|
||||
|
||||
print_int(PRINT_ANY,
|
||||
"clock",
|
||||
"\n clock %d ",
|
||||
clock->freq);
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "clock", " clock %u ", clock->freq);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -565,31 +625,23 @@ static void can_print_xstats(struct link_util *lu,
|
|||
if (xstats && RTA_PAYLOAD(xstats) == sizeof(*stats)) {
|
||||
stats = RTA_DATA(xstats);
|
||||
|
||||
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);
|
||||
}
|
||||
can_print_nl_indent();
|
||||
print_string(PRINT_FP, NULL, "%s",
|
||||
" re-started bus-errors arbit-lost error-warn error-pass bus-off");
|
||||
can_print_nl_indent();
|
||||
print_uint(PRINT_ANY, "restarts", " %-10u", stats->restarts);
|
||||
print_uint(PRINT_ANY, "bus_error", " %-10u", stats->bus_error);
|
||||
print_uint(PRINT_ANY, "arbitration_lost", " %-10u",
|
||||
stats->arbitration_lost);
|
||||
print_uint(PRINT_ANY, "error_warning", " %-10u",
|
||||
stats->error_warning);
|
||||
print_uint(PRINT_ANY, "error_passive", " %-10u",
|
||||
stats->error_passive);
|
||||
print_uint(PRINT_ANY, "bus_off", " %-10u", stats->bus_off);
|
||||
}
|
||||
}
|
||||
|
||||
static void can_print_help(struct link_util *lu, int argc, char **argv,
|
||||
FILE *f)
|
||||
static void can_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
|
||||
{
|
||||
print_usage(f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "utils.h"
|
||||
#include "ip_common.h"
|
||||
#include "nh_common.h"
|
||||
|
||||
static void usage(void) __attribute__((noreturn));
|
||||
static int prefix_banner;
|
||||
|
|
@ -88,7 +89,7 @@ static int accept_msg(struct rtnl_ctrl_data *ctrl,
|
|||
case RTM_NEWNEXTHOP:
|
||||
case RTM_DELNEXTHOP:
|
||||
print_headers(fp, "[NEXTHOP]", ctrl);
|
||||
print_nexthop(n, arg);
|
||||
print_cache_nexthop(n, arg, true);
|
||||
return 0;
|
||||
|
||||
case RTM_NEWNEXTHOPBUCKET:
|
||||
|
|
|
|||
18
ip/ipmptcp.c
18
ip/ipmptcp.c
|
|
@ -1,17 +1,23 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <rt_names.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/mptcp.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "ip_common.h"
|
||||
#include "libgenl.h"
|
||||
#include "json_print.h"
|
||||
#include "libgenl.h"
|
||||
#include "libnetlink.h"
|
||||
#include "ll_map.h"
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
|
|
@ -299,7 +305,11 @@ static int mptcp_addr_show(int argc, char **argv)
|
|||
if (rtnl_talk(&genl_rth, &req.n, &answer) < 0)
|
||||
return -2;
|
||||
|
||||
return print_mptcp_addr(answer, stdout);
|
||||
new_json_obj(json);
|
||||
ret = print_mptcp_addr(answer, stdout);
|
||||
delete_json_obj();
|
||||
fflush(stdout);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mptcp_addr_flush(int argc, char **argv)
|
||||
|
|
|
|||
47
ip/ipneigh.c
47
ip/ipneigh.c
|
|
@ -51,12 +51,12 @@ static void usage(void)
|
|||
fprintf(stderr,
|
||||
"Usage: ip neigh { add | del | change | replace }\n"
|
||||
" { ADDR [ lladdr LLADDR ] [ nud STATE ] proxy ADDR }\n"
|
||||
" [ dev DEV ] [ router ] [ extern_learn ] [ protocol PROTO ]\n"
|
||||
" [ dev DEV ] [ router ] [ use ] [ managed ] [ extern_learn ]\n"
|
||||
" [ protocol PROTO ]\n"
|
||||
"\n"
|
||||
" ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ]\n"
|
||||
" [ vrf NAME ]\n"
|
||||
"\n"
|
||||
" ip neigh get { ADDR | proxy ADDR } dev DEV\n"
|
||||
" ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ]\n"
|
||||
" [ vrf NAME ] [ nomaster ]\n"
|
||||
" ip neigh get { ADDR | proxy ADDR } dev DEV\n"
|
||||
"\n"
|
||||
"STATE := { delay | failed | incomplete | noarp | none |\n"
|
||||
" permanent | probe | reachable | stale }\n");
|
||||
|
|
@ -116,6 +116,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
|
|||
.ndm.ndm_family = preferred_family,
|
||||
.ndm.ndm_state = NUD_PERMANENT,
|
||||
};
|
||||
__u32 ext_flags = 0;
|
||||
char *dev = NULL;
|
||||
int dst_ok = 0;
|
||||
int dev_ok = 0;
|
||||
|
|
@ -149,6 +150,11 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
|
|||
req.ndm.ndm_flags |= NTF_PROXY;
|
||||
} else if (strcmp(*argv, "router") == 0) {
|
||||
req.ndm.ndm_flags |= NTF_ROUTER;
|
||||
} else if (strcmp(*argv, "use") == 0) {
|
||||
req.ndm.ndm_flags |= NTF_USE;
|
||||
} else if (strcmp(*argv, "managed") == 0) {
|
||||
ext_flags |= NTF_EXT_MANAGED;
|
||||
req.ndm.ndm_state = NUD_NONE;
|
||||
} else if (matches(*argv, "extern_learn") == 0) {
|
||||
req.ndm.ndm_flags |= NTF_EXT_LEARNED;
|
||||
} else if (strcmp(*argv, "dev") == 0) {
|
||||
|
|
@ -184,7 +190,10 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
|
|||
req.ndm.ndm_family = dst.family;
|
||||
if (addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen) < 0)
|
||||
return -1;
|
||||
|
||||
if (ext_flags &&
|
||||
addattr_l(&req.n, sizeof(req), NDA_FLAGS_EXT, &ext_flags,
|
||||
sizeof(ext_flags)) < 0)
|
||||
return -1;
|
||||
if (lla && strcmp(lla, "null")) {
|
||||
char llabuf[20];
|
||||
int l;
|
||||
|
|
@ -236,7 +245,7 @@ static void print_neigh_state(unsigned int nud)
|
|||
#define PRINT_FLAG(f) \
|
||||
if (nud & NUD_##f) { \
|
||||
nud &= ~NUD_##f; \
|
||||
print_string(PRINT_ANY, NULL, " %s", #f); \
|
||||
print_string(PRINT_ANY, NULL, "%s ", #f); \
|
||||
}
|
||||
|
||||
PRINT_FLAG(INCOMPLETE);
|
||||
|
|
@ -304,6 +313,7 @@ int print_neigh(struct nlmsghdr *n, void *arg)
|
|||
int len = n->nlmsg_len;
|
||||
struct rtattr *tb[NDA_MAX+1];
|
||||
static int logit = 1;
|
||||
__u32 ext_flags = 0;
|
||||
__u8 protocol = 0;
|
||||
|
||||
if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH &&
|
||||
|
|
@ -347,6 +357,8 @@ int print_neigh(struct nlmsghdr *n, void *arg)
|
|||
|
||||
if (tb[NDA_PROTOCOL])
|
||||
protocol = rta_getattr_u8(tb[NDA_PROTOCOL]);
|
||||
if (tb[NDA_FLAGS_EXT])
|
||||
ext_flags = rta_getattr_u32(tb[NDA_FLAGS_EXT]);
|
||||
|
||||
if (filter.protocol && filter.protocol != protocol)
|
||||
return 0;
|
||||
|
|
@ -424,27 +436,26 @@ int print_neigh(struct nlmsghdr *n, void *arg)
|
|||
fprintf(fp, "lladdr ");
|
||||
|
||||
print_color_string(PRINT_ANY, COLOR_MAC,
|
||||
"lladdr", "%s", lladdr);
|
||||
"lladdr", "%s ", lladdr);
|
||||
}
|
||||
|
||||
if (r->ndm_flags & NTF_ROUTER)
|
||||
print_null(PRINT_ANY, "router", " %s", "router");
|
||||
|
||||
print_null(PRINT_ANY, "router", "%s ", "router");
|
||||
if (r->ndm_flags & NTF_PROXY)
|
||||
print_null(PRINT_ANY, "proxy", " %s", "proxy");
|
||||
|
||||
print_null(PRINT_ANY, "proxy", "%s ", "proxy");
|
||||
if (ext_flags & NTF_EXT_MANAGED)
|
||||
print_null(PRINT_ANY, "managed", "%s ", "managed");
|
||||
if (r->ndm_flags & NTF_EXT_LEARNED)
|
||||
print_null(PRINT_ANY, "extern_learn", " %s ", "extern_learn");
|
||||
|
||||
print_null(PRINT_ANY, "extern_learn", "%s ", "extern_learn");
|
||||
if (r->ndm_flags & NTF_OFFLOADED)
|
||||
print_null(PRINT_ANY, "offload", " %s", "offload");
|
||||
print_null(PRINT_ANY, "offload", "%s ", "offload");
|
||||
|
||||
if (show_stats) {
|
||||
if (tb[NDA_CACHEINFO])
|
||||
print_cacheinfo(RTA_DATA(tb[NDA_CACHEINFO]));
|
||||
|
||||
if (tb[NDA_PROBES])
|
||||
print_uint(PRINT_ANY, "probes", " probes %u",
|
||||
print_uint(PRINT_ANY, "probes", "probes %u ",
|
||||
rta_getattr_u32(tb[NDA_PROBES]));
|
||||
}
|
||||
|
||||
|
|
@ -454,7 +465,7 @@ int print_neigh(struct nlmsghdr *n, void *arg)
|
|||
if (protocol) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
print_string(PRINT_ANY, "protocol", " proto %s ",
|
||||
print_string(PRINT_ANY, "protocol", "proto %s ",
|
||||
rtnl_rtprot_n2a(protocol, b1, sizeof(b1)));
|
||||
}
|
||||
|
||||
|
|
@ -536,6 +547,8 @@ static int do_show_or_flush(int argc, char **argv, int flush)
|
|||
if (!name_is_vrf(*argv))
|
||||
invarg("Not a valid VRF name\n", *argv);
|
||||
filter.master = ifindex;
|
||||
} else if (strcmp(*argv, "nomaster") == 0) {
|
||||
filter.master = -1;
|
||||
} else if (strcmp(*argv, "unused") == 0) {
|
||||
filter.unused_only = 1;
|
||||
} else if (strcmp(*argv, "nud") == 0) {
|
||||
|
|
|
|||
483
ip/ipnexthop.c
483
ip/ipnexthop.c
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/nexthop.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <rt_names.h>
|
||||
|
|
@ -13,6 +14,7 @@
|
|||
|
||||
#include "utils.h"
|
||||
#include "ip_common.h"
|
||||
#include "nh_common.h"
|
||||
|
||||
static struct {
|
||||
unsigned int flushed;
|
||||
|
|
@ -33,6 +35,9 @@ enum {
|
|||
#define RTM_NHA(h) ((struct rtattr *)(((char *)(h)) + \
|
||||
NLMSG_ALIGN(sizeof(struct nhmsg))))
|
||||
|
||||
static struct hlist_head nh_cache[NH_CACHE_SIZE];
|
||||
static struct rtnl_handle nh_cache_rth = { .fd = -1 };
|
||||
|
||||
static void usage(void) __attribute__((noreturn));
|
||||
|
||||
static void usage(void)
|
||||
|
|
@ -212,28 +217,29 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void print_nh_group(FILE *fp, const struct rtattr *grps_attr)
|
||||
static bool __valid_nh_group_attr(const struct rtattr *g_attr)
|
||||
{
|
||||
struct nexthop_grp *nhg = RTA_DATA(grps_attr);
|
||||
int num = RTA_PAYLOAD(grps_attr) / sizeof(*nhg);
|
||||
int i;
|
||||
int num = RTA_PAYLOAD(g_attr) / sizeof(struct nexthop_grp);
|
||||
|
||||
if (!num || num * sizeof(*nhg) != RTA_PAYLOAD(grps_attr)) {
|
||||
fprintf(fp, "<invalid nexthop group>");
|
||||
return;
|
||||
}
|
||||
return num && num * sizeof(struct nexthop_grp) == RTA_PAYLOAD(g_attr);
|
||||
}
|
||||
|
||||
static void print_nh_group(const struct nh_entry *nhe)
|
||||
{
|
||||
int i;
|
||||
|
||||
open_json_array(PRINT_JSON, "group");
|
||||
print_string(PRINT_FP, NULL, "%s", "group ");
|
||||
for (i = 0; i < num; ++i) {
|
||||
for (i = 0; i < nhe->nh_groups_cnt; ++i) {
|
||||
open_json_object(NULL);
|
||||
|
||||
if (i)
|
||||
print_string(PRINT_FP, NULL, "%s", "/");
|
||||
|
||||
print_uint(PRINT_ANY, "id", "%u", nhg[i].id);
|
||||
if (nhg[i].weight)
|
||||
print_uint(PRINT_ANY, "weight", ",%u", nhg[i].weight + 1);
|
||||
print_uint(PRINT_ANY, "id", "%u", nhe->nh_groups[i].id);
|
||||
if (nhe->nh_groups[i].weight)
|
||||
print_uint(PRINT_ANY, "weight", ",%u",
|
||||
nhe->nh_groups[i].weight + 1);
|
||||
|
||||
close_json_object();
|
||||
}
|
||||
|
|
@ -253,50 +259,59 @@ static const char *nh_group_type_name(__u16 type)
|
|||
}
|
||||
}
|
||||
|
||||
static void print_nh_group_type(FILE *fp, const struct rtattr *grp_type_attr)
|
||||
static void print_nh_group_type(__u16 nh_grp_type)
|
||||
{
|
||||
__u16 type = rta_getattr_u16(grp_type_attr);
|
||||
|
||||
if (type == NEXTHOP_GRP_TYPE_MPATH)
|
||||
if (nh_grp_type == NEXTHOP_GRP_TYPE_MPATH)
|
||||
/* Do not print type in order not to break existing output. */
|
||||
return;
|
||||
|
||||
print_string(PRINT_ANY, "type", "type %s ", nh_group_type_name(type));
|
||||
print_string(PRINT_ANY, "type", "type %s ", nh_group_type_name(nh_grp_type));
|
||||
}
|
||||
|
||||
static void print_nh_res_group(FILE *fp, const struct rtattr *res_grp_attr)
|
||||
static void parse_nh_res_group_rta(const struct rtattr *res_grp_attr,
|
||||
struct nha_res_grp *res_grp)
|
||||
{
|
||||
struct rtattr *tb[NHA_RES_GROUP_MAX + 1];
|
||||
struct rtattr *rta;
|
||||
struct timeval tv;
|
||||
|
||||
memset(res_grp, 0, sizeof(*res_grp));
|
||||
parse_rtattr_nested(tb, NHA_RES_GROUP_MAX, res_grp_attr);
|
||||
|
||||
open_json_object("resilient_args");
|
||||
|
||||
if (tb[NHA_RES_GROUP_BUCKETS])
|
||||
print_uint(PRINT_ANY, "buckets", "buckets %u ",
|
||||
rta_getattr_u16(tb[NHA_RES_GROUP_BUCKETS]));
|
||||
res_grp->buckets = rta_getattr_u16(tb[NHA_RES_GROUP_BUCKETS]);
|
||||
|
||||
if (tb[NHA_RES_GROUP_IDLE_TIMER]) {
|
||||
rta = tb[NHA_RES_GROUP_IDLE_TIMER];
|
||||
__jiffies_to_tv(&tv, rta_getattr_u32(rta));
|
||||
print_tv(PRINT_ANY, "idle_timer", "idle_timer %g ", &tv);
|
||||
res_grp->idle_timer = rta_getattr_u32(rta);
|
||||
}
|
||||
|
||||
if (tb[NHA_RES_GROUP_UNBALANCED_TIMER]) {
|
||||
rta = tb[NHA_RES_GROUP_UNBALANCED_TIMER];
|
||||
__jiffies_to_tv(&tv, rta_getattr_u32(rta));
|
||||
print_tv(PRINT_ANY, "unbalanced_timer", "unbalanced_timer %g ",
|
||||
&tv);
|
||||
res_grp->unbalanced_timer = rta_getattr_u32(rta);
|
||||
}
|
||||
|
||||
if (tb[NHA_RES_GROUP_UNBALANCED_TIME]) {
|
||||
rta = tb[NHA_RES_GROUP_UNBALANCED_TIME];
|
||||
__jiffies_to_tv(&tv, rta_getattr_u32(rta));
|
||||
print_tv(PRINT_ANY, "unbalanced_time", "unbalanced_time %g ",
|
||||
&tv);
|
||||
res_grp->unbalanced_time = rta_getattr_u64(rta);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_nh_res_group(const struct nha_res_grp *res_grp)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
open_json_object("resilient_args");
|
||||
|
||||
print_uint(PRINT_ANY, "buckets", "buckets %u ", res_grp->buckets);
|
||||
|
||||
__jiffies_to_tv(&tv, res_grp->idle_timer);
|
||||
print_tv(PRINT_ANY, "idle_timer", "idle_timer %g ", &tv);
|
||||
|
||||
__jiffies_to_tv(&tv, res_grp->unbalanced_timer);
|
||||
print_tv(PRINT_ANY, "unbalanced_timer", "unbalanced_timer %g ", &tv);
|
||||
|
||||
__jiffies_to_tv(&tv, res_grp->unbalanced_time);
|
||||
print_tv(PRINT_ANY, "unbalanced_time", "unbalanced_time %g ", &tv);
|
||||
|
||||
close_json_object();
|
||||
}
|
||||
|
|
@ -328,14 +343,325 @@ static void print_nh_res_bucket(FILE *fp, const struct rtattr *res_bucket_attr)
|
|||
close_json_object();
|
||||
}
|
||||
|
||||
int print_nexthop(struct nlmsghdr *n, void *arg)
|
||||
static void ipnh_destroy_entry(struct nh_entry *nhe)
|
||||
{
|
||||
if (nhe->nh_encap)
|
||||
free(nhe->nh_encap);
|
||||
if (nhe->nh_groups)
|
||||
free(nhe->nh_groups);
|
||||
}
|
||||
|
||||
/* parse nhmsg into nexthop entry struct which must be destroyed by
|
||||
* ipnh_destroy_enty when it's not needed anymore
|
||||
*/
|
||||
static int ipnh_parse_nhmsg(FILE *fp, const struct nhmsg *nhm, int len,
|
||||
struct nh_entry *nhe)
|
||||
{
|
||||
struct rtattr *tb[NHA_MAX+1];
|
||||
int err = 0;
|
||||
|
||||
memset(nhe, 0, sizeof(*nhe));
|
||||
parse_rtattr_flags(tb, NHA_MAX, RTM_NHA(nhm), len, NLA_F_NESTED);
|
||||
|
||||
if (tb[NHA_ID])
|
||||
nhe->nh_id = rta_getattr_u32(tb[NHA_ID]);
|
||||
|
||||
if (tb[NHA_OIF])
|
||||
nhe->nh_oif = rta_getattr_u32(tb[NHA_OIF]);
|
||||
|
||||
if (tb[NHA_GROUP_TYPE])
|
||||
nhe->nh_grp_type = rta_getattr_u16(tb[NHA_GROUP_TYPE]);
|
||||
|
||||
if (tb[NHA_GATEWAY]) {
|
||||
if (RTA_PAYLOAD(tb[NHA_GATEWAY]) > sizeof(nhe->nh_gateway)) {
|
||||
fprintf(fp, "<nexthop id %u invalid gateway length %lu>\n",
|
||||
nhe->nh_id, RTA_PAYLOAD(tb[NHA_GATEWAY]));
|
||||
err = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
nhe->nh_gateway_len = RTA_PAYLOAD(tb[NHA_GATEWAY]);
|
||||
memcpy(&nhe->nh_gateway, RTA_DATA(tb[NHA_GATEWAY]),
|
||||
RTA_PAYLOAD(tb[NHA_GATEWAY]));
|
||||
}
|
||||
|
||||
if (tb[NHA_ENCAP]) {
|
||||
nhe->nh_encap = malloc(RTA_LENGTH(RTA_PAYLOAD(tb[NHA_ENCAP])));
|
||||
if (!nhe->nh_encap) {
|
||||
err = -ENOMEM;
|
||||
goto out_err;
|
||||
}
|
||||
memcpy(nhe->nh_encap, tb[NHA_ENCAP],
|
||||
RTA_LENGTH(RTA_PAYLOAD(tb[NHA_ENCAP])));
|
||||
memcpy(&nhe->nh_encap_type, tb[NHA_ENCAP_TYPE],
|
||||
sizeof(nhe->nh_encap_type));
|
||||
}
|
||||
|
||||
if (tb[NHA_GROUP]) {
|
||||
if (!__valid_nh_group_attr(tb[NHA_GROUP])) {
|
||||
fprintf(fp, "<nexthop id %u invalid nexthop group>",
|
||||
nhe->nh_id);
|
||||
err = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
nhe->nh_groups = malloc(RTA_PAYLOAD(tb[NHA_GROUP]));
|
||||
if (!nhe->nh_groups) {
|
||||
err = -ENOMEM;
|
||||
goto out_err;
|
||||
}
|
||||
nhe->nh_groups_cnt = RTA_PAYLOAD(tb[NHA_GROUP]) /
|
||||
sizeof(struct nexthop_grp);
|
||||
memcpy(nhe->nh_groups, RTA_DATA(tb[NHA_GROUP]),
|
||||
RTA_PAYLOAD(tb[NHA_GROUP]));
|
||||
}
|
||||
|
||||
if (tb[NHA_RES_GROUP]) {
|
||||
parse_nh_res_group_rta(tb[NHA_RES_GROUP], &nhe->nh_res_grp);
|
||||
nhe->nh_has_res_grp = true;
|
||||
}
|
||||
|
||||
nhe->nh_blackhole = !!tb[NHA_BLACKHOLE];
|
||||
nhe->nh_fdb = !!tb[NHA_FDB];
|
||||
|
||||
nhe->nh_family = nhm->nh_family;
|
||||
nhe->nh_protocol = nhm->nh_protocol;
|
||||
nhe->nh_scope = nhm->nh_scope;
|
||||
nhe->nh_flags = nhm->nh_flags;
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
ipnh_destroy_entry(nhe);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __print_nexthop_entry(FILE *fp, const char *jsobj,
|
||||
struct nh_entry *nhe,
|
||||
bool deleted)
|
||||
{
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
open_json_object(jsobj);
|
||||
|
||||
if (deleted)
|
||||
print_bool(PRINT_ANY, "deleted", "Deleted ", true);
|
||||
|
||||
print_uint(PRINT_ANY, "id", "id %u ", nhe->nh_id);
|
||||
|
||||
if (nhe->nh_groups)
|
||||
print_nh_group(nhe);
|
||||
|
||||
print_nh_group_type(nhe->nh_grp_type);
|
||||
|
||||
if (nhe->nh_has_res_grp)
|
||||
print_nh_res_group(&nhe->nh_res_grp);
|
||||
|
||||
if (nhe->nh_encap)
|
||||
lwt_print_encap(fp, &nhe->nh_encap_type.rta, nhe->nh_encap);
|
||||
|
||||
if (nhe->nh_gateway_len)
|
||||
__print_rta_gateway(fp, nhe->nh_family,
|
||||
format_host(nhe->nh_family,
|
||||
nhe->nh_gateway_len,
|
||||
&nhe->nh_gateway));
|
||||
|
||||
if (nhe->nh_oif)
|
||||
print_rta_ifidx(fp, nhe->nh_oif, "dev");
|
||||
|
||||
if (nhe->nh_scope != RT_SCOPE_UNIVERSE || show_details > 0) {
|
||||
print_string(PRINT_ANY, "scope", "scope %s ",
|
||||
rtnl_rtscope_n2a(nhe->nh_scope, b1, sizeof(b1)));
|
||||
}
|
||||
|
||||
if (nhe->nh_blackhole)
|
||||
print_null(PRINT_ANY, "blackhole", "blackhole ", NULL);
|
||||
|
||||
if (nhe->nh_protocol != RTPROT_UNSPEC || show_details > 0) {
|
||||
print_string(PRINT_ANY, "protocol", "proto %s ",
|
||||
rtnl_rtprot_n2a(nhe->nh_protocol, b1, sizeof(b1)));
|
||||
}
|
||||
|
||||
print_rt_flags(fp, nhe->nh_flags);
|
||||
|
||||
if (nhe->nh_fdb)
|
||||
print_null(PRINT_ANY, "fdb", "fdb", NULL);
|
||||
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
static int __ipnh_get_id(struct rtnl_handle *rthp, __u32 nh_id,
|
||||
struct nlmsghdr **answer)
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct nhmsg nhm;
|
||||
char buf[1024];
|
||||
} req = {
|
||||
.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg)),
|
||||
.n.nlmsg_flags = NLM_F_REQUEST,
|
||||
.n.nlmsg_type = RTM_GETNEXTHOP,
|
||||
.nhm.nh_family = preferred_family,
|
||||
};
|
||||
|
||||
addattr32(&req.n, sizeof(req), NHA_ID, nh_id);
|
||||
|
||||
return rtnl_talk(rthp, &req.n, answer);
|
||||
}
|
||||
|
||||
static struct hlist_head *ipnh_cache_head(__u32 nh_id)
|
||||
{
|
||||
nh_id ^= nh_id >> 20;
|
||||
nh_id ^= nh_id >> 10;
|
||||
|
||||
return &nh_cache[nh_id % NH_CACHE_SIZE];
|
||||
}
|
||||
|
||||
static void ipnh_cache_link_entry(struct nh_entry *nhe)
|
||||
{
|
||||
struct hlist_head *head = ipnh_cache_head(nhe->nh_id);
|
||||
|
||||
hlist_add_head(&nhe->nh_hash, head);
|
||||
}
|
||||
|
||||
static void ipnh_cache_unlink_entry(struct nh_entry *nhe)
|
||||
{
|
||||
hlist_del(&nhe->nh_hash);
|
||||
}
|
||||
|
||||
static struct nh_entry *ipnh_cache_get(__u32 nh_id)
|
||||
{
|
||||
struct hlist_head *head = ipnh_cache_head(nh_id);
|
||||
struct nh_entry *nhe;
|
||||
struct hlist_node *n;
|
||||
|
||||
hlist_for_each(n, head) {
|
||||
nhe = container_of(n, struct nh_entry, nh_hash);
|
||||
if (nhe->nh_id == nh_id)
|
||||
return nhe;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __ipnh_cache_parse_nlmsg(const struct nlmsghdr *n,
|
||||
struct nh_entry *nhe)
|
||||
{
|
||||
int err, len;
|
||||
|
||||
len = n->nlmsg_len - NLMSG_SPACE(sizeof(struct nhmsg));
|
||||
if (len < 0) {
|
||||
fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = ipnh_parse_nhmsg(stderr, NLMSG_DATA(n), len, nhe);
|
||||
if (err) {
|
||||
fprintf(stderr, "Error parsing nexthop: %s\n", strerror(-err));
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct nh_entry *ipnh_cache_add(__u32 nh_id)
|
||||
{
|
||||
struct nlmsghdr *answer = NULL;
|
||||
struct nh_entry *nhe = NULL;
|
||||
|
||||
if (nh_cache_rth.fd < 0 && rtnl_open(&nh_cache_rth, 0) < 0) {
|
||||
nh_cache_rth.fd = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (__ipnh_get_id(&nh_cache_rth, nh_id, &answer) < 0)
|
||||
goto out;
|
||||
|
||||
nhe = malloc(sizeof(*nhe));
|
||||
if (!nhe)
|
||||
goto out;
|
||||
|
||||
if (__ipnh_cache_parse_nlmsg(answer, nhe))
|
||||
goto out_free_nhe;
|
||||
|
||||
ipnh_cache_link_entry(nhe);
|
||||
|
||||
out:
|
||||
if (answer)
|
||||
free(answer);
|
||||
|
||||
return nhe;
|
||||
|
||||
out_free_nhe:
|
||||
free(nhe);
|
||||
nhe = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void ipnh_cache_del(struct nh_entry *nhe)
|
||||
{
|
||||
ipnh_cache_unlink_entry(nhe);
|
||||
ipnh_destroy_entry(nhe);
|
||||
free(nhe);
|
||||
}
|
||||
|
||||
/* update, add or delete a nexthop entry based on nlmsghdr */
|
||||
static int ipnh_cache_process_nlmsg(const struct nlmsghdr *n,
|
||||
struct nh_entry *new_nhe)
|
||||
{
|
||||
struct nh_entry *nhe;
|
||||
|
||||
nhe = ipnh_cache_get(new_nhe->nh_id);
|
||||
switch (n->nlmsg_type) {
|
||||
case RTM_DELNEXTHOP:
|
||||
if (nhe)
|
||||
ipnh_cache_del(nhe);
|
||||
ipnh_destroy_entry(new_nhe);
|
||||
break;
|
||||
case RTM_NEWNEXTHOP:
|
||||
if (!nhe) {
|
||||
nhe = malloc(sizeof(*nhe));
|
||||
if (!nhe) {
|
||||
ipnh_destroy_entry(new_nhe);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* this allows us to save 1 allocation on updates by
|
||||
* reusing the old nh entry, but we need to cleanup its
|
||||
* internal storage
|
||||
*/
|
||||
ipnh_cache_unlink_entry(nhe);
|
||||
ipnh_destroy_entry(nhe);
|
||||
}
|
||||
memcpy(nhe, new_nhe, sizeof(*nhe));
|
||||
ipnh_cache_link_entry(nhe);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_cache_nexthop_id(FILE *fp, const char *fp_prefix, const char *jsobj,
|
||||
__u32 nh_id)
|
||||
{
|
||||
struct nh_entry *nhe = ipnh_cache_get(nh_id);
|
||||
|
||||
if (!nhe) {
|
||||
nhe = ipnh_cache_add(nh_id);
|
||||
if (!nhe)
|
||||
return;
|
||||
}
|
||||
|
||||
if (fp_prefix)
|
||||
print_string(PRINT_FP, NULL, "%s", fp_prefix);
|
||||
__print_nexthop_entry(fp, jsobj, nhe, false);
|
||||
}
|
||||
|
||||
int print_cache_nexthop(struct nlmsghdr *n, void *arg, bool process_cache)
|
||||
{
|
||||
struct nhmsg *nhm = NLMSG_DATA(n);
|
||||
struct rtattr *tb[NHA_MAX+1];
|
||||
FILE *fp = (FILE *)arg;
|
||||
int len;
|
||||
|
||||
SPRINT_BUF(b1);
|
||||
struct nh_entry nhe;
|
||||
int len, err;
|
||||
|
||||
if (n->nlmsg_type != RTM_DELNEXTHOP &&
|
||||
n->nlmsg_type != RTM_NEWNEXTHOP) {
|
||||
|
|
@ -354,60 +680,29 @@ int print_nexthop(struct nlmsghdr *n, void *arg)
|
|||
if (filter.proto && filter.proto != nhm->nh_protocol)
|
||||
return 0;
|
||||
|
||||
parse_rtattr_flags(tb, NHA_MAX, RTM_NHA(nhm), len, NLA_F_NESTED);
|
||||
|
||||
open_json_object(NULL);
|
||||
|
||||
if (n->nlmsg_type == RTM_DELNEXTHOP)
|
||||
print_bool(PRINT_ANY, "deleted", "Deleted ", true);
|
||||
|
||||
if (tb[NHA_ID])
|
||||
print_uint(PRINT_ANY, "id", "id %u ",
|
||||
rta_getattr_u32(tb[NHA_ID]));
|
||||
|
||||
if (tb[NHA_GROUP])
|
||||
print_nh_group(fp, tb[NHA_GROUP]);
|
||||
|
||||
if (tb[NHA_GROUP_TYPE])
|
||||
print_nh_group_type(fp, tb[NHA_GROUP_TYPE]);
|
||||
|
||||
if (tb[NHA_RES_GROUP])
|
||||
print_nh_res_group(fp, tb[NHA_RES_GROUP]);
|
||||
|
||||
if (tb[NHA_ENCAP])
|
||||
lwt_print_encap(fp, tb[NHA_ENCAP_TYPE], tb[NHA_ENCAP]);
|
||||
|
||||
if (tb[NHA_GATEWAY])
|
||||
print_rta_gateway(fp, nhm->nh_family, tb[NHA_GATEWAY]);
|
||||
|
||||
if (tb[NHA_OIF])
|
||||
print_rta_if(fp, tb[NHA_OIF], "dev");
|
||||
|
||||
if (nhm->nh_scope != RT_SCOPE_UNIVERSE || show_details > 0) {
|
||||
print_string(PRINT_ANY, "scope", "scope %s ",
|
||||
rtnl_rtscope_n2a(nhm->nh_scope, b1, sizeof(b1)));
|
||||
err = ipnh_parse_nhmsg(fp, nhm, len, &nhe);
|
||||
if (err) {
|
||||
close_json_object();
|
||||
fprintf(stderr, "Error parsing nexthop: %s\n", strerror(-err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tb[NHA_BLACKHOLE])
|
||||
print_null(PRINT_ANY, "blackhole", "blackhole ", NULL);
|
||||
|
||||
if (nhm->nh_protocol != RTPROT_UNSPEC || show_details > 0) {
|
||||
print_string(PRINT_ANY, "protocol", "proto %s ",
|
||||
rtnl_rtprot_n2a(nhm->nh_protocol, b1, sizeof(b1)));
|
||||
}
|
||||
|
||||
print_rt_flags(fp, nhm->nh_flags);
|
||||
|
||||
if (tb[NHA_FDB])
|
||||
print_null(PRINT_ANY, "fdb", "fdb", NULL);
|
||||
|
||||
__print_nexthop_entry(fp, NULL, &nhe, n->nlmsg_type == RTM_DELNEXTHOP);
|
||||
print_string(PRINT_FP, NULL, "%s", "\n");
|
||||
close_json_object();
|
||||
fflush(fp);
|
||||
|
||||
if (process_cache)
|
||||
ipnh_cache_process_nlmsg(n, &nhe);
|
||||
else
|
||||
ipnh_destroy_entry(&nhe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_nexthop_nocache(struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
return print_cache_nexthop(n, arg, false);
|
||||
}
|
||||
|
||||
int print_nexthop_bucket(struct nlmsghdr *n, void *arg)
|
||||
{
|
||||
struct nhmsg *nhm = NLMSG_DATA(n);
|
||||
|
|
@ -546,7 +841,7 @@ static void parse_nh_group_type_res(struct nlmsghdr *n, int maxlen, int *argcp,
|
|||
|
||||
NEXT_ARG();
|
||||
if (get_unsigned(&idle_timer, *argv, 0) ||
|
||||
idle_timer >= ~0UL / 100)
|
||||
idle_timer >= UINT32_MAX / 100)
|
||||
invarg("invalid idle timer value", *argv);
|
||||
|
||||
addattr32(n, maxlen, NHA_RES_GROUP_IDLE_TIMER,
|
||||
|
|
@ -556,7 +851,7 @@ static void parse_nh_group_type_res(struct nlmsghdr *n, int maxlen, int *argcp,
|
|||
|
||||
NEXT_ARG();
|
||||
if (get_unsigned(&unbalanced_timer, *argv, 0) ||
|
||||
unbalanced_timer >= ~0UL / 100)
|
||||
unbalanced_timer >= UINT32_MAX / 100)
|
||||
invarg("invalid unbalanced timer value", *argv);
|
||||
|
||||
addattr32(n, maxlen, NHA_RES_GROUP_UNBALANCED_TIMER,
|
||||
|
|
@ -712,26 +1007,14 @@ static int ipnh_modify(int cmd, unsigned int flags, int argc, char **argv)
|
|||
|
||||
static int ipnh_get_id(__u32 id)
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct nhmsg nhm;
|
||||
char buf[1024];
|
||||
} req = {
|
||||
.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg)),
|
||||
.n.nlmsg_flags = NLM_F_REQUEST,
|
||||
.n.nlmsg_type = RTM_GETNEXTHOP,
|
||||
.nhm.nh_family = preferred_family,
|
||||
};
|
||||
struct nlmsghdr *answer;
|
||||
|
||||
addattr32(&req.n, sizeof(req), NHA_ID, id);
|
||||
|
||||
if (rtnl_talk(&rth, &req.n, &answer) < 0)
|
||||
if (__ipnh_get_id(&rth, id, &answer) < 0)
|
||||
return -2;
|
||||
|
||||
new_json_obj(json);
|
||||
|
||||
if (print_nexthop(answer, (void *)stdout) < 0) {
|
||||
if (print_nexthop_nocache(answer, (void *)stdout) < 0) {
|
||||
free(answer);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -816,7 +1099,7 @@ static int ipnh_list_flush(int argc, char **argv, int action)
|
|||
|
||||
new_json_obj(json);
|
||||
|
||||
if (rtnl_dump_filter(&rth, print_nexthop, stdout) < 0) {
|
||||
if (rtnl_dump_filter(&rth, print_nexthop_nocache, stdout) < 0) {
|
||||
fprintf(stderr, "Dump terminated\n");
|
||||
return -2;
|
||||
}
|
||||
|
|
|
|||
32
ip/iproute.c
32
ip/iproute.c
|
|
@ -28,6 +28,7 @@
|
|||
#include "rt_names.h"
|
||||
#include "utils.h"
|
||||
#include "ip_common.h"
|
||||
#include "nh_common.h"
|
||||
|
||||
#ifndef RTAX_RTTVAR
|
||||
#define RTAX_RTTVAR RTAX_HOPS
|
||||
|
|
@ -410,13 +411,13 @@ static void print_rt_pref(FILE *fp, unsigned int pref)
|
|||
}
|
||||
}
|
||||
|
||||
void print_rta_if(FILE *fp, const struct rtattr *rta, const char *prefix)
|
||||
void print_rta_ifidx(FILE *fp, __u32 ifidx, const char *prefix)
|
||||
{
|
||||
const char *ifname = ll_index_to_name(rta_getattr_u32(rta));
|
||||
const char *ifname = ll_index_to_name(ifidx);
|
||||
|
||||
if (is_json_context())
|
||||
if (is_json_context()) {
|
||||
print_string(PRINT_JSON, prefix, NULL, ifname);
|
||||
else {
|
||||
} else {
|
||||
fprintf(fp, "%s ", prefix);
|
||||
color_fprintf(fp, COLOR_IFNAME, "%s ", ifname);
|
||||
}
|
||||
|
|
@ -547,13 +548,11 @@ static void print_rta_newdst(FILE *fp, const struct rtmsg *r,
|
|||
}
|
||||
}
|
||||
|
||||
void print_rta_gateway(FILE *fp, unsigned char family, const struct rtattr *rta)
|
||||
void __print_rta_gateway(FILE *fp, unsigned char family, const char *gateway)
|
||||
{
|
||||
const char *gateway = format_host_rta(family, rta);
|
||||
|
||||
if (is_json_context())
|
||||
if (is_json_context()) {
|
||||
print_string(PRINT_JSON, "gateway", NULL, gateway);
|
||||
else {
|
||||
} else {
|
||||
fprintf(fp, "via ");
|
||||
print_color_string(PRINT_FP,
|
||||
ifa_family_color(family),
|
||||
|
|
@ -561,6 +560,13 @@ void print_rta_gateway(FILE *fp, unsigned char family, const struct rtattr *rta)
|
|||
}
|
||||
}
|
||||
|
||||
void print_rta_gateway(FILE *fp, unsigned char family, const struct rtattr *rta)
|
||||
{
|
||||
const char *gateway = format_host_rta(family, rta);
|
||||
|
||||
__print_rta_gateway(fp, family, gateway);
|
||||
}
|
||||
|
||||
static void print_rta_via(FILE *fp, const struct rtattr *rta)
|
||||
{
|
||||
size_t len = RTA_PAYLOAD(rta) - 2;
|
||||
|
|
@ -862,7 +868,7 @@ int print_route(struct nlmsghdr *n, void *arg)
|
|||
print_rta_via(fp, tb[RTA_VIA]);
|
||||
|
||||
if (tb[RTA_OIF] && filter.oifmask != -1)
|
||||
print_rta_if(fp, tb[RTA_OIF], "dev");
|
||||
print_rta_ifidx(fp, rta_getattr_u32(tb[RTA_OIF]), "dev");
|
||||
|
||||
if (table && (table != RT_TABLE_MAIN || show_details > 0) && !filter.tb)
|
||||
print_string(PRINT_ANY,
|
||||
|
|
@ -946,7 +952,7 @@ int print_route(struct nlmsghdr *n, void *arg)
|
|||
print_rta_metrics(fp, tb[RTA_METRICS]);
|
||||
|
||||
if (tb[RTA_IIF] && filter.iifmask != -1)
|
||||
print_rta_if(fp, tb[RTA_IIF], "iif");
|
||||
print_rta_ifidx(fp, rta_getattr_u32(tb[RTA_IIF]), "iif");
|
||||
|
||||
if (tb[RTA_PREF])
|
||||
print_rt_pref(fp, rta_getattr_u8(tb[RTA_PREF]));
|
||||
|
|
@ -963,6 +969,10 @@ int print_route(struct nlmsghdr *n, void *arg)
|
|||
propagate ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
if (tb[RTA_NH_ID] && show_details)
|
||||
print_cache_nexthop_id(fp, "\n\tnh_info ", "nh_info",
|
||||
rta_getattr_u32(tb[RTA_NH_ID]));
|
||||
|
||||
if (tb[RTA_MULTIPATH])
|
||||
print_rta_multipath(fp, r, tb[RTA_MULTIPATH]);
|
||||
|
||||
|
|
|
|||
|
|
@ -210,16 +210,54 @@ static void print_encap_rpl(FILE *fp, struct rtattr *encap)
|
|||
print_rpl_srh(fp, srh);
|
||||
}
|
||||
|
||||
static const char *ioam6_mode_types[IOAM6_IPTUNNEL_MODE_MAX + 1] = {
|
||||
[IOAM6_IPTUNNEL_MODE_INLINE] = "inline",
|
||||
[IOAM6_IPTUNNEL_MODE_ENCAP] = "encap",
|
||||
[IOAM6_IPTUNNEL_MODE_AUTO] = "auto",
|
||||
};
|
||||
|
||||
static const char *format_ioam6mode_type(int mode)
|
||||
{
|
||||
if (mode < IOAM6_IPTUNNEL_MODE_MIN ||
|
||||
mode > IOAM6_IPTUNNEL_MODE_MAX ||
|
||||
!ioam6_mode_types[mode])
|
||||
return "<unknown>";
|
||||
|
||||
return ioam6_mode_types[mode];
|
||||
}
|
||||
|
||||
static __u8 read_ioam6mode_type(const char *mode)
|
||||
{
|
||||
__u8 i;
|
||||
|
||||
for (i = IOAM6_IPTUNNEL_MODE_MIN; i <= IOAM6_IPTUNNEL_MODE_MAX; i++) {
|
||||
if (ioam6_mode_types[i] && !strcmp(mode, ioam6_mode_types[i]))
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_encap_ioam6(FILE *fp, struct rtattr *encap)
|
||||
{
|
||||
struct rtattr *tb[IOAM6_IPTUNNEL_MAX + 1];
|
||||
struct ioam6_trace_hdr *trace;
|
||||
__u8 mode;
|
||||
|
||||
parse_rtattr_nested(tb, IOAM6_IPTUNNEL_MAX, encap);
|
||||
|
||||
if (!tb[IOAM6_IPTUNNEL_TRACE])
|
||||
if (!tb[IOAM6_IPTUNNEL_MODE] || !tb[IOAM6_IPTUNNEL_TRACE])
|
||||
return;
|
||||
|
||||
mode = rta_getattr_u8(tb[IOAM6_IPTUNNEL_MODE]);
|
||||
if (!tb[IOAM6_IPTUNNEL_DST] && mode != IOAM6_IPTUNNEL_MODE_INLINE)
|
||||
return;
|
||||
|
||||
print_string(PRINT_ANY, "mode", "mode %s ", format_ioam6mode_type(mode));
|
||||
|
||||
if (mode != IOAM6_IPTUNNEL_MODE_INLINE)
|
||||
print_string(PRINT_ANY, "tundst", "tundst %s ",
|
||||
rt_addr_n2a_rta(AF_INET6, tb[IOAM6_IPTUNNEL_DST]));
|
||||
|
||||
trace = RTA_DATA(tb[IOAM6_IPTUNNEL_TRACE]);
|
||||
|
||||
print_null(PRINT_ANY, "trace", "trace ", NULL);
|
||||
|
|
@ -884,23 +922,48 @@ out:
|
|||
static int parse_encap_ioam6(struct rtattr *rta, size_t len, int *argcp,
|
||||
char ***argvp)
|
||||
{
|
||||
int ns_found = 0, argc = *argcp;
|
||||
__u16 trace_ns, trace_size = 0;
|
||||
struct ioam6_trace_hdr *trace;
|
||||
char **argv = *argvp;
|
||||
int argc = *argcp;
|
||||
int ns_found = 0;
|
||||
__u16 size = 0;
|
||||
__u32 type = 0;
|
||||
__u16 ns;
|
||||
__u32 trace_type = 0;
|
||||
inet_prefix addr;
|
||||
__u8 mode;
|
||||
|
||||
trace = calloc(1, sizeof(*trace));
|
||||
if (!trace)
|
||||
return -1;
|
||||
if (strcmp(*argv, "mode") != 0) {
|
||||
mode = IOAM6_IPTUNNEL_MODE_INLINE;
|
||||
} else {
|
||||
NEXT_ARG();
|
||||
|
||||
if (strcmp(*argv, "trace"))
|
||||
mode = read_ioam6mode_type(*argv);
|
||||
if (!mode)
|
||||
invarg("Invalid mode", *argv);
|
||||
|
||||
NEXT_ARG();
|
||||
}
|
||||
|
||||
if (strcmp(*argv, "tundst") != 0) {
|
||||
if (mode != IOAM6_IPTUNNEL_MODE_INLINE)
|
||||
missarg("tundst");
|
||||
} else {
|
||||
if (mode == IOAM6_IPTUNNEL_MODE_INLINE)
|
||||
invarg("Inline mode does not need tundst", *argv);
|
||||
|
||||
NEXT_ARG();
|
||||
|
||||
get_addr(&addr, *argv, AF_INET6);
|
||||
if (addr.family != AF_INET6 || addr.bytelen != 16)
|
||||
invarg("Invalid IPv6 address for tundst", *argv);
|
||||
|
||||
NEXT_ARG();
|
||||
}
|
||||
|
||||
if (strcmp(*argv, "trace") != 0)
|
||||
missarg("trace");
|
||||
|
||||
NEXT_ARG();
|
||||
if (strcmp(*argv, "prealloc"))
|
||||
|
||||
if (strcmp(*argv, "prealloc") != 0)
|
||||
missarg("prealloc");
|
||||
|
||||
while (NEXT_ARG_OK()) {
|
||||
|
|
@ -909,63 +972,58 @@ static int parse_encap_ioam6(struct rtattr *rta, size_t len, int *argcp,
|
|||
if (strcmp(*argv, "type") == 0) {
|
||||
NEXT_ARG();
|
||||
|
||||
if (type)
|
||||
if (trace_type)
|
||||
duparg2("type", *argv);
|
||||
|
||||
if (get_u32(&type, *argv, 0) || !type)
|
||||
invarg("Invalid type", *argv);
|
||||
|
||||
trace->type_be32 = htonl(type << 8);
|
||||
|
||||
if (get_u32(&trace_type, *argv, 0) || !trace_type)
|
||||
invarg("Invalid trace type", *argv);
|
||||
} else if (strcmp(*argv, "ns") == 0) {
|
||||
NEXT_ARG();
|
||||
|
||||
if (ns_found++)
|
||||
duparg2("ns", *argv);
|
||||
|
||||
if (!type)
|
||||
missarg("type");
|
||||
|
||||
if (get_u16(&ns, *argv, 0))
|
||||
if (get_u16(&trace_ns, *argv, 0))
|
||||
invarg("Invalid namespace ID", *argv);
|
||||
|
||||
trace->namespace_id = htons(ns);
|
||||
|
||||
} else if (strcmp(*argv, "size") == 0) {
|
||||
NEXT_ARG();
|
||||
|
||||
if (size)
|
||||
if (trace_size)
|
||||
duparg2("size", *argv);
|
||||
|
||||
if (!type)
|
||||
missarg("type");
|
||||
if (!ns_found)
|
||||
missarg("ns");
|
||||
if (get_u16(&trace_size, *argv, 0) || !trace_size)
|
||||
invarg("Invalid trace size", *argv);
|
||||
|
||||
if (get_u16(&size, *argv, 0) || !size)
|
||||
invarg("Invalid size", *argv);
|
||||
|
||||
if (size % 4)
|
||||
invarg("Size must be a 4-octet multiple", *argv);
|
||||
if (size > IOAM6_TRACE_DATA_SIZE_MAX)
|
||||
invarg("Size too big", *argv);
|
||||
|
||||
trace->remlen = (__u8)(size / 4);
|
||||
if (trace_size % 4)
|
||||
invarg("Trace size must be a 4-octet multiple",
|
||||
*argv);
|
||||
|
||||
if (trace_size > IOAM6_TRACE_DATA_SIZE_MAX)
|
||||
invarg("Trace size is too big", *argv);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!type)
|
||||
if (!trace_type)
|
||||
missarg("type");
|
||||
if (!ns_found)
|
||||
missarg("ns");
|
||||
if (!size)
|
||||
if (!trace_size)
|
||||
missarg("size");
|
||||
|
||||
if (rta_addattr_l(rta, len, IOAM6_IPTUNNEL_TRACE, trace,
|
||||
sizeof(*trace))) {
|
||||
trace = calloc(1, sizeof(*trace));
|
||||
if (!trace)
|
||||
return -1;
|
||||
|
||||
trace->type_be32 = htonl(trace_type << 8);
|
||||
trace->namespace_id = htons(trace_ns);
|
||||
trace->remlen = (__u8)(trace_size / 4);
|
||||
|
||||
if (rta_addattr8(rta, len, IOAM6_IPTUNNEL_MODE, mode) ||
|
||||
(mode != IOAM6_IPTUNNEL_MODE_INLINE &&
|
||||
rta_addattr_l(rta, len, IOAM6_IPTUNNEL_DST, &addr.data, addr.bytelen)) ||
|
||||
rta_addattr_l(rta, len, IOAM6_IPTUNNEL_TRACE, trace, sizeof(*trace))) {
|
||||
free(trace);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __NH_COMMON_H__
|
||||
#define __NH_COMMON_H__ 1
|
||||
|
||||
#include <list.h>
|
||||
|
||||
#define NH_CACHE_SIZE 1024
|
||||
|
||||
struct nha_res_grp {
|
||||
__u16 buckets;
|
||||
__u32 idle_timer;
|
||||
__u32 unbalanced_timer;
|
||||
__u64 unbalanced_time;
|
||||
};
|
||||
|
||||
struct nh_entry {
|
||||
struct hlist_node nh_hash;
|
||||
|
||||
__u32 nh_id;
|
||||
__u32 nh_oif;
|
||||
__u32 nh_flags;
|
||||
__u16 nh_grp_type;
|
||||
__u8 nh_family;
|
||||
__u8 nh_scope;
|
||||
__u8 nh_protocol;
|
||||
|
||||
bool nh_blackhole;
|
||||
bool nh_fdb;
|
||||
|
||||
int nh_gateway_len;
|
||||
union {
|
||||
__be32 ipv4;
|
||||
struct in6_addr ipv6;
|
||||
} nh_gateway;
|
||||
|
||||
struct rtattr *nh_encap;
|
||||
union {
|
||||
struct rtattr rta;
|
||||
__u8 _buf[RTA_LENGTH(sizeof(__u16))];
|
||||
} nh_encap_type;
|
||||
|
||||
bool nh_has_res_grp;
|
||||
struct nha_res_grp nh_res_grp;
|
||||
|
||||
int nh_groups_cnt;
|
||||
struct nexthop_grp *nh_groups;
|
||||
};
|
||||
|
||||
void print_cache_nexthop_id(FILE *fp, const char *fp_prefix, const char *jsobj,
|
||||
__u32 nh_id);
|
||||
int print_cache_nexthop(struct nlmsghdr *n, void *arg, bool process_cache);
|
||||
|
||||
#endif /* __NH_COMMON_H__ */
|
||||
10
ip/routef
10
ip/routef
|
|
@ -1,10 +0,0 @@
|
|||
#! /bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
if [ -z "$*" ] ; then
|
||||
exec ip -4 ro flush scope global type unicast
|
||||
else
|
||||
echo "Usage: routef"
|
||||
echo
|
||||
echo "This script will flush the IPv4 routing table"
|
||||
fi
|
||||
124
ip/routel
124
ip/routel
|
|
@ -1,72 +1,62 @@
|
|||
#!/bin/sh
|
||||
#! /usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#
|
||||
# Script created by: Stephen R. van den Berg <srb@cuci.nl>, 1999/04/18
|
||||
# Donated to the public domain.
|
||||
#
|
||||
# This script transforms the output of "ip" into more readable text.
|
||||
# "ip" is the Linux-advanced-routing configuration tool part of the
|
||||
# iproute package.
|
||||
#
|
||||
# This is simple script to process JSON output from ip route
|
||||
# command and format it. Based on earlier shell script version.
|
||||
"""Script to parse ip route output into more readable text."""
|
||||
|
||||
test "X-h" = "X$1" && echo "Usage: $0 [tablenr [raw ip args...]]" && exit 64
|
||||
import sys
|
||||
import json
|
||||
import getopt
|
||||
import subprocess
|
||||
|
||||
test -z "$*" && set 0
|
||||
|
||||
ip route list table "$@" |
|
||||
while read network rest
|
||||
do set xx $rest
|
||||
shift
|
||||
proto=""
|
||||
via=""
|
||||
dev=""
|
||||
scope=""
|
||||
src=""
|
||||
table=""
|
||||
case $network in
|
||||
broadcast|local|unreachable) via=$network
|
||||
network=$1
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
while test $# != 0
|
||||
do
|
||||
case "$1" in
|
||||
proto|via|dev|scope|src|table)
|
||||
key=$1
|
||||
val=$2
|
||||
eval "$key='$val'"
|
||||
shift 2
|
||||
;;
|
||||
dead|onlink|pervasive|offload|notify|linkdown|unresolved)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
# avoid infinite loop on unknown keyword without value at line end
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
echo "$network $via $src $proto $scope $dev $table"
|
||||
done | awk -F ' ' '
|
||||
BEGIN {
|
||||
format="%15s%-3s %15s %15s %8s %8s%7s %s\n";
|
||||
printf(format,"target","","gateway","source","proto","scope","dev","tbl");
|
||||
}
|
||||
{ network=$1;
|
||||
mask="";
|
||||
if(match(network,"/"))
|
||||
{ mask=" "substr(network,RSTART+1);
|
||||
network=substr(network,0,RSTART);
|
||||
}
|
||||
via=$2;
|
||||
src=$3;
|
||||
proto=$4;
|
||||
scope=$5;
|
||||
dev=$6;
|
||||
table=$7;
|
||||
printf(format,network,mask,via,src,proto,scope,dev,table);
|
||||
}
|
||||
'
|
||||
def usage():
|
||||
'''Print usage and exit'''
|
||||
print("Usage: {} [tablenr [raw ip args...]]".format(sys.argv[0]))
|
||||
sys.exit(64)
|
||||
|
||||
|
||||
def main():
|
||||
'''Process the arguments'''
|
||||
family = 'inet'
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "h46f:", ["help", "family="])
|
||||
except getopt.GetoptError as err:
|
||||
print(err)
|
||||
usage()
|
||||
|
||||
for opt, arg in opts:
|
||||
if opt in ["-h", "--help"]:
|
||||
usage()
|
||||
elif opt == '-6':
|
||||
family = 'inet6'
|
||||
elif opt == "-4":
|
||||
family = 'inet'
|
||||
elif opt in ["-f", "--family"]:
|
||||
family = arg
|
||||
else:
|
||||
assert False, "unhandled option"
|
||||
|
||||
if not args:
|
||||
args = ['0']
|
||||
|
||||
cmd = ['ip', '-f', family, '-j', 'route', 'list', 'table'] + args
|
||||
process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
|
||||
tbl = json.load(process.stdout)
|
||||
if family == 'inet':
|
||||
fmt = '{:15} {:15} {:15} {:8} {:8}{:<16} {}'
|
||||
else:
|
||||
fmt = '{:32} {:32} {:32} {:8} {:8}{:<16} {}'
|
||||
|
||||
# ip route json keys
|
||||
keys = ['dst', 'gateway', 'prefsrc', 'protocol', 'scope', 'dev', 'table']
|
||||
print(fmt.format(*map(lambda x: x.capitalize(), keys)))
|
||||
|
||||
for record in tbl:
|
||||
fields = [record[k] if k in record else '' for k in keys]
|
||||
print(fmt.format(*fields))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
|||
5
ip/rtpr
5
ip/rtpr
|
|
@ -1,5 +0,0 @@
|
|||
#! /bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
exec tr "[\\\\]" "[
|
||||
]"
|
||||
|
|
@ -132,6 +132,7 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
|
|||
void xfrm_policy_info_print(struct xfrm_userpolicy_info *xpinfo,
|
||||
struct rtattr *tb[], FILE *fp, const char *prefix,
|
||||
const char *title);
|
||||
int xfrm_policy_default_print(struct nlmsghdr *n, FILE *fp);
|
||||
int xfrm_id_parse(xfrm_address_t *saddr, struct xfrm_id *id, __u16 *family,
|
||||
int loose, int *argcp, char ***argvp);
|
||||
int xfrm_mode_parse(__u8 *mode, int *argcp, char ***argvp);
|
||||
|
|
|
|||
|
|
@ -323,6 +323,9 @@ static int xfrm_accept_msg(struct rtnl_ctrl_data *ctrl,
|
|||
case XFRM_MSG_MAPPING:
|
||||
xfrm_mapping_print(n, arg);
|
||||
return 0;
|
||||
case XFRM_MSG_GETDEFAULT:
|
||||
xfrm_policy_default_print(n, arg);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
133
ip/xfrm_policy.c
133
ip/xfrm_policy.c
|
|
@ -66,6 +66,8 @@ static void usage(void)
|
|||
"Usage: ip xfrm policy flush [ ptype PTYPE ]\n"
|
||||
"Usage: ip xfrm policy count\n"
|
||||
"Usage: ip xfrm policy set [ hthresh4 LBITS RBITS ] [ hthresh6 LBITS RBITS ]\n"
|
||||
"Usage: ip xfrm policy setdefault DIR ACTION [ DIR ACTION ] [ DIR ACTION ]\n"
|
||||
"Usage: ip xfrm policy getdefault\n"
|
||||
"SELECTOR := [ src ADDR[/PLEN] ] [ dst ADDR[/PLEN] ] [ dev DEV ] [ UPSPEC ]\n"
|
||||
"UPSPEC := proto { { tcp | udp | sctp | dccp } [ sport PORT ] [ dport PORT ] |\n"
|
||||
" { icmp | ipv6-icmp | mobility-header } [ type NUMBER ] [ code NUMBER ] |\n"
|
||||
|
|
@ -1124,6 +1126,133 @@ static int xfrm_spd_getinfo(int argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int xfrm_str_to_policy(char *name, uint8_t *policy)
|
||||
{
|
||||
if (strcmp(name, "block") == 0) {
|
||||
*policy = XFRM_USERPOLICY_BLOCK;
|
||||
return 0;
|
||||
} else if (strcmp(name, "accept") == 0) {
|
||||
*policy = XFRM_USERPOLICY_ACCEPT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *xfrm_policy_to_str(uint8_t policy)
|
||||
{
|
||||
switch (policy) {
|
||||
case XFRM_USERPOLICY_UNSPEC:
|
||||
return "unspec";
|
||||
case XFRM_USERPOLICY_BLOCK:
|
||||
return "block";
|
||||
case XFRM_USERPOLICY_ACCEPT:
|
||||
return "accept";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static int xfrm_spd_setdefault(int argc, char **argv)
|
||||
{
|
||||
struct rtnl_handle rth;
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct xfrm_userpolicy_default up;
|
||||
} req = {
|
||||
.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_default)),
|
||||
.n.nlmsg_flags = NLM_F_REQUEST,
|
||||
.n.nlmsg_type = XFRM_MSG_SETDEFAULT,
|
||||
};
|
||||
|
||||
while (argc > 0) {
|
||||
if (strcmp(*argv, "in") == 0) {
|
||||
if (req.up.in)
|
||||
duparg("in", *argv);
|
||||
|
||||
NEXT_ARG();
|
||||
if (xfrm_str_to_policy(*argv, &req.up.in) < 0)
|
||||
invarg("in policy value is invalid", *argv);
|
||||
} else if (strcmp(*argv, "fwd") == 0) {
|
||||
if (req.up.fwd)
|
||||
duparg("fwd", *argv);
|
||||
|
||||
NEXT_ARG();
|
||||
if (xfrm_str_to_policy(*argv, &req.up.fwd) < 0)
|
||||
invarg("fwd policy value is invalid", *argv);
|
||||
} else if (strcmp(*argv, "out") == 0) {
|
||||
if (req.up.out)
|
||||
duparg("out", *argv);
|
||||
|
||||
NEXT_ARG();
|
||||
if (xfrm_str_to_policy(*argv, &req.up.out) < 0)
|
||||
invarg("out policy value is invalid", *argv);
|
||||
} else {
|
||||
invarg("unknown direction", *argv);
|
||||
}
|
||||
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
|
||||
exit(1);
|
||||
|
||||
if (rtnl_talk(&rth, &req.n, NULL) < 0)
|
||||
exit(2);
|
||||
|
||||
rtnl_close(&rth);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xfrm_policy_default_print(struct nlmsghdr *n, FILE *fp)
|
||||
{
|
||||
struct xfrm_userpolicy_default *up = NLMSG_DATA(n);
|
||||
int len = n->nlmsg_len - NLMSG_SPACE(sizeof(*up));
|
||||
|
||||
if (len < 0) {
|
||||
fprintf(stderr,
|
||||
"BUG: short nlmsg len %u (expect %lu) for XFRM_MSG_GETDEFAULT\n",
|
||||
n->nlmsg_len, NLMSG_SPACE(sizeof(*up)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(fp, "Default policies:\n");
|
||||
fprintf(fp, " in: %s\n", xfrm_policy_to_str(up->in));
|
||||
fprintf(fp, " fwd: %s\n", xfrm_policy_to_str(up->fwd));
|
||||
fprintf(fp, " out: %s\n", xfrm_policy_to_str(up->out));
|
||||
fflush(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xfrm_spd_getdefault(int argc, char **argv)
|
||||
{
|
||||
struct rtnl_handle rth;
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct xfrm_userpolicy_default up;
|
||||
} req = {
|
||||
.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_default)),
|
||||
.n.nlmsg_flags = NLM_F_REQUEST,
|
||||
.n.nlmsg_type = XFRM_MSG_GETDEFAULT,
|
||||
};
|
||||
struct nlmsghdr *answer;
|
||||
|
||||
if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
|
||||
exit(1);
|
||||
|
||||
if (rtnl_talk(&rth, &req.n, &answer) < 0)
|
||||
exit(2);
|
||||
|
||||
xfrm_policy_default_print(answer, (FILE *)stdout);
|
||||
|
||||
free(answer);
|
||||
rtnl_close(&rth);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xfrm_policy_flush(int argc, char **argv)
|
||||
{
|
||||
struct rtnl_handle rth;
|
||||
|
|
@ -1197,6 +1326,10 @@ int do_xfrm_policy(int argc, char **argv)
|
|||
return xfrm_spd_getinfo(argc, argv);
|
||||
if (matches(*argv, "set") == 0)
|
||||
return xfrm_spd_setinfo(argc-1, argv+1);
|
||||
if (matches(*argv, "setdefault") == 0)
|
||||
return xfrm_spd_setdefault(argc-1, argv+1);
|
||||
if (matches(*argv, "getdefault") == 0)
|
||||
return xfrm_spd_getdefault(argc-1, argv+1);
|
||||
if (matches(*argv, "help") == 0)
|
||||
usage();
|
||||
fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm policy help\".\n", *argv);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netax25/ax25.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
const char *ax25_ntop1(const ax25_address *src, char *dst, socklen_t size);
|
||||
|
||||
/*
|
||||
* AX.25 addresses are based on Amateur radio callsigns followed by an SSID
|
||||
* like XXXXXX-SS where the callsign consists of up to 6 ASCII characters
|
||||
* which are either letters or digits and the SSID is a decimal number in the
|
||||
* range 0..15.
|
||||
* Amateur radio callsigns are assigned by a country's relevant authorities
|
||||
* and are 3..6 characters though a few countries have assigned callsigns
|
||||
* longer than that. AX.25 is not able to handle such longer callsigns.
|
||||
* There are further restrictions on the format of valid callsigns by
|
||||
* applicable national and international law. Linux doesn't need to care and
|
||||
* will happily accept anything that consists of 6 ASCII characters in the
|
||||
* range of A-Z and 0-9 for a callsign such as the default AX.25 MAC address
|
||||
* LINUX-1 and the default broadcast address QST-0.
|
||||
* The SSID is just a number and not encoded in ASCII digits.
|
||||
*
|
||||
* Being based on HDLC AX.25 encodes addresses by shifting them one bit left
|
||||
* thus zeroing bit 0, the HDLC extension bit for all but the last bit of
|
||||
* a packet's address field but for our purposes here we're not considering
|
||||
* the HDLC extension bit that is it will always be zero.
|
||||
*
|
||||
* Linux' internal representation of AX.25 addresses in Linux is very similar
|
||||
* to this on the on-air or on-the-wire format. The callsign is padded to
|
||||
* 6 octets by adding spaces, followed by the SSID octet then all 7 octets
|
||||
* are left-shifted by one bit.
|
||||
*
|
||||
* For example, for the address "LINUX-1" the callsign is LINUX and SSID is 1
|
||||
* the internal format is 98:92:9c:aa:b0:40:02.
|
||||
*/
|
||||
|
||||
const char *ax25_ntop1(const ax25_address *src, char *dst, socklen_t size)
|
||||
{
|
||||
char c, *s;
|
||||
int n;
|
||||
|
||||
for (n = 0, s = dst; n < 6; n++) {
|
||||
c = (src->ax25_call[n] >> 1) & 0x7f;
|
||||
if (c != ' ')
|
||||
*s++ = c;
|
||||
}
|
||||
|
||||
*s++ = '-';
|
||||
|
||||
n = ((src->ax25_call[6] >> 1) & 0x0f);
|
||||
if (n > 9) {
|
||||
*s++ = '1';
|
||||
n -= 10;
|
||||
}
|
||||
|
||||
*s++ = n + '0';
|
||||
*s++ = '\0';
|
||||
|
||||
if (*dst == '\0' || *dst == '-') {
|
||||
dst[0] = '*';
|
||||
dst[1] = '\0';
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
const char *ax25_ntop(int af, const void *addr, char *buf, socklen_t buflen)
|
||||
{
|
||||
switch (af) {
|
||||
case AF_AX25:
|
||||
errno = 0;
|
||||
return ax25_ntop1((ax25_address *)addr, buf, buflen);
|
||||
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -203,12 +203,30 @@ int bpf_dump_prog_info(FILE *f, uint32_t id)
|
|||
if (!ret && len) {
|
||||
int jited = !!info.jited_prog_len;
|
||||
|
||||
print_string(PRINT_ANY, "name", "name %s ", info.name);
|
||||
print_string(PRINT_ANY, "tag", "tag %s ",
|
||||
hexstring_n2a(info.tag, sizeof(info.tag),
|
||||
tmp, sizeof(tmp)));
|
||||
print_uint(PRINT_JSON, "jited", NULL, jited);
|
||||
if (jited && !is_json_context())
|
||||
fprintf(f, "jited ");
|
||||
|
||||
if (show_details) {
|
||||
if (info.load_time) {
|
||||
/* ns since boottime */
|
||||
print_lluint(PRINT_ANY, "load_time",
|
||||
"load_time %llu ", info.load_time);
|
||||
|
||||
print_luint(PRINT_ANY, "created_by_uid",
|
||||
"created_by_uid %lu ",
|
||||
info.created_by_uid);
|
||||
}
|
||||
|
||||
if (info.btf_id)
|
||||
print_luint(PRINT_ANY, "btf_id", "btf_id %lu ",
|
||||
info.btf_id);
|
||||
}
|
||||
|
||||
dump_ok = 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@ const char *ll_addr_n2a(const unsigned char *addr, int alen, int type,
|
|||
|
||||
if (alen == 16 && (type == ARPHRD_TUNNEL6 || type == ARPHRD_IP6GRE))
|
||||
return inet_ntop(AF_INET6, addr, buf, blen);
|
||||
if (alen == 7 && type == ARPHRD_AX25)
|
||||
return ax25_ntop(AF_AX25, addr, buf, blen);
|
||||
if (alen == 7 && type == ARPHRD_NETROM)
|
||||
return netrom_ntop(AF_NETROM, addr, buf, blen);
|
||||
if (alen == 5 && type == ARPHRD_ROSE)
|
||||
return rose_ntop(AF_ROSE, addr, buf, blen);
|
||||
|
||||
snprintf(buf, blen, "%02x", addr[0]);
|
||||
for (i = 1, l = 2; i < alen && l < blen; i++, l += 3)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <linux/ax25.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
const char *ax25_ntop1(const ax25_address *src, char *dst, socklen_t size);
|
||||
|
||||
const char *netrom_ntop(int af, const void *addr, char *buf, socklen_t buflen)
|
||||
{
|
||||
switch (af) {
|
||||
case AF_NETROM:
|
||||
errno = 0;
|
||||
return ax25_ntop1((ax25_address *)addr, buf, buflen);
|
||||
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <linux/rose.h>
|
||||
|
||||
#include "rt_names.h"
|
||||
#include "utils.h"
|
||||
|
||||
static const char *rose_ntop1(const rose_address *src, char *dst,
|
||||
socklen_t size)
|
||||
{
|
||||
char *p = dst;
|
||||
int i;
|
||||
|
||||
if (size < 10)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
*p++ = '0' + ((src->rose_addr[i] >> 4) & 0xf);
|
||||
*p++ = '0' + ((src->rose_addr[i] ) & 0xf);
|
||||
}
|
||||
|
||||
if (size == 10)
|
||||
return dst;
|
||||
|
||||
*p = '\0';
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
const char *rose_ntop(int af, const void *addr, char *buf, socklen_t buflen)
|
||||
{
|
||||
switch (af) {
|
||||
case AF_ROSE:
|
||||
errno = 0;
|
||||
return rose_ntop1((rose_address *)addr, buf, buflen);
|
||||
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -145,13 +145,53 @@ bridge \- show / manipulate bridge addresses and devices
|
|||
.B vid
|
||||
.IR VID " [ "
|
||||
.B state
|
||||
.IR STP_STATE " ] "
|
||||
.IR STP_STATE " ] [ "
|
||||
.B mcast_router
|
||||
.IR MULTICAST_ROUTER " ]"
|
||||
|
||||
.ti -8
|
||||
.BR "bridge vlan" " [ " show " | " tunnelshow " ] [ "
|
||||
.B dev
|
||||
.IR DEV " ]"
|
||||
|
||||
.ti -8
|
||||
.BR "bridge vlan global set"
|
||||
.B dev
|
||||
.I DEV
|
||||
.B vid
|
||||
.IR VID " [ "
|
||||
.B mcast_snooping
|
||||
.IR MULTICAST_SNOOPING " ] [ "
|
||||
.B mcast_querier
|
||||
.IR MULTICAST_QUERIER " ] [ "
|
||||
.B mcast_igmp_version
|
||||
.IR IGMP_VERSION " ] [ "
|
||||
.B mcast_mld_version
|
||||
.IR MLD_VERSION " ] [ "
|
||||
.B mcast_last_member_count
|
||||
.IR LAST_MEMBER_COUNT " ] [ "
|
||||
.B mcast_last_member_interval
|
||||
.IR LAST_MEMBER_INTERVAL " ] [ "
|
||||
.B mcast_startup_query_count
|
||||
.IR STARTUP_QUERY_COUNT " ] [ "
|
||||
.B mcast_startup_query_interval
|
||||
.IR STARTUP_QUERY_INTERVAL " ] [ "
|
||||
.B mcast_membership_interval
|
||||
.IR MEMBERSHIP_INTERVAL " ] [ "
|
||||
.B mcast_querier_interval
|
||||
.IR QUERIER_INTERVAL " ] [ "
|
||||
.B mcast_query_interval
|
||||
.IR QUERY_INTERVAL " ] [ "
|
||||
.B mcast_query_response_interval
|
||||
.IR QUERY_RESPONSE_INTERVAL " ]"
|
||||
|
||||
.ti -8
|
||||
.BR "bridge vlan global" " [ " show " ] [ "
|
||||
.B dev
|
||||
.IR DEV " ] [ "
|
||||
.B vid
|
||||
.IR VID " ]"
|
||||
|
||||
.ti -8
|
||||
.BR "bridge monitor" " [ " all " | " neigh " | " link " | " mdb " | " vlan " ]"
|
||||
|
||||
|
|
@ -877,6 +917,31 @@ is used during the STP election process. In this state, the vlan will only proce
|
|||
STP BPDUs.
|
||||
.sp
|
||||
|
||||
.TP
|
||||
.BI mcast_router " MULTICAST_ROUTER "
|
||||
configure this vlan and interface's multicast router mode, note that only modes
|
||||
0 - 2 are available for bridge devices.
|
||||
A vlan and interface with a multicast router will receive all multicast traffic.
|
||||
.I MULTICAST_ROUTER
|
||||
may be either
|
||||
.sp
|
||||
.B 0
|
||||
- to disable multicast router.
|
||||
.sp
|
||||
|
||||
.B 1
|
||||
- to let the system detect the presence of routers (default).
|
||||
.sp
|
||||
|
||||
.B 2
|
||||
- to permanently enable multicast traffic forwarding on this vlan and interface.
|
||||
.sp
|
||||
|
||||
.B 3
|
||||
- to temporarily mark this vlan and port as having a multicast router, i.e.
|
||||
enable multicast traffic forwarding. This mode is available only for ports.
|
||||
.sp
|
||||
|
||||
.SS bridge vlan show - list vlan configuration.
|
||||
|
||||
This command displays the current VLAN filter table.
|
||||
|
|
@ -895,6 +960,98 @@ option, the command displays per-vlan traffic statistics.
|
|||
|
||||
This command displays the current vlan tunnel info mapping.
|
||||
|
||||
.SS bridge vlan global set - change vlan filter entry's global options
|
||||
|
||||
This command changes vlan filter entry's global options.
|
||||
|
||||
.TP
|
||||
.BI dev " NAME"
|
||||
the interface with which this vlan is associated. Only bridge devices are
|
||||
supported for global options.
|
||||
|
||||
.TP
|
||||
.BI vid " VID"
|
||||
the VLAN ID that identifies the vlan.
|
||||
|
||||
.TP
|
||||
.BI mcast_snooping " MULTICAST_SNOOPING "
|
||||
turn multicast snooping for VLAN entry with VLAN ID on
|
||||
.RI ( MULTICAST_SNOOPING " > 0) "
|
||||
or off
|
||||
.RI ( MULTICAST_SNOOPING " == 0). Default is on. "
|
||||
|
||||
.TP
|
||||
.BI mcast_querier " MULTICAST_QUERIER "
|
||||
enable
|
||||
.RI ( MULTICAST_QUERIER " > 0) "
|
||||
or disable
|
||||
.RI ( MULTICAST_QUERIER " == 0) "
|
||||
IGMP/MLD querier, ie sending of multicast queries by the bridge. Default is disabled.
|
||||
|
||||
.TP
|
||||
.BI mcast_igmp_version " IGMP_VERSION "
|
||||
set the IGMP version. Default is 2.
|
||||
|
||||
.TP
|
||||
.BI mcast_mld_version " MLD_VERSION "
|
||||
set the MLD version. Default is 1.
|
||||
|
||||
.TP
|
||||
.BI mcast_last_member_count " LAST_MEMBER_COUNT "
|
||||
set multicast last member count, ie the number of queries the bridge
|
||||
will send before stopping forwarding a multicast group after a "leave"
|
||||
message has been received. Default is 2.
|
||||
|
||||
.TP
|
||||
.BI mcast_last_member_interval " LAST_MEMBER_INTERVAL "
|
||||
interval between queries to find remaining members of a group,
|
||||
after a "leave" message is received.
|
||||
|
||||
.TP
|
||||
.BI mcast_startup_query_count " STARTUP_QUERY_COUNT "
|
||||
set the number of queries to send during startup phase. Default is 2.
|
||||
|
||||
.TP
|
||||
.BI mcast_startup_query_interval " STARTUP_QUERY_INTERVAL "
|
||||
interval between queries in the startup phase.
|
||||
|
||||
.TP
|
||||
.BI mcast_membership_interval " MEMBERSHIP_INTERVAL "
|
||||
delay after which the bridge will leave a group,
|
||||
if no membership reports for this group are received.
|
||||
|
||||
.TP
|
||||
.BI mcast_querier_interval " QUERIER_INTERVAL "
|
||||
interval between queries sent by other routers. If no queries are seen
|
||||
after this delay has passed, the bridge will start to send its own queries
|
||||
(as if
|
||||
.BI mcast_querier
|
||||
was enabled).
|
||||
|
||||
.TP
|
||||
.BI mcast_query_interval " QUERY_INTERVAL "
|
||||
interval between queries sent by the bridge after the end of the
|
||||
startup phase.
|
||||
|
||||
.TP
|
||||
.BI mcast_query_response_interval " QUERY_RESPONSE_INTERVAL "
|
||||
set the Max Response Time/Maximum Response Delay for IGMP/MLD
|
||||
queries sent by the bridge.
|
||||
|
||||
.SS bridge vlan global show - list global vlan options.
|
||||
|
||||
This command displays the global VLAN options for each VLAN entry.
|
||||
|
||||
.TP
|
||||
.BI dev " DEV"
|
||||
the interface only whose VLAN global options should be listed. Default is to list
|
||||
all bridge interfaces.
|
||||
|
||||
.TP
|
||||
.BI vid " VID"
|
||||
the VLAN ID only whose global options should be listed. Default is to list
|
||||
all vlans.
|
||||
|
||||
.SH bridge monitor - state monitoring
|
||||
|
||||
The
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ Command output show rate object identifier, it's type and rate values along with
|
|||
parent node name. Rate values printed in SI units which are more suitable to
|
||||
represent specific value. To print values in IEC units \fB-i\fR switch is
|
||||
used. JSON (\fB-j\fR) output always print rate values in bytes per second. Zero
|
||||
rate values means "unlimited" rates and ommited in output, as well as parent
|
||||
rate values means "unlimited" rates and omitted in output, as well as parent
|
||||
node name.
|
||||
|
||||
.SS devlink port function rate set - set rate object parameters.
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
.TH IFCFG 8 "September 24 2009" "iproute2" "Linux"
|
||||
.SH NAME
|
||||
ifcfg \- simplistic script which replaces ifconfig IP management
|
||||
.SH SYNOPSIS
|
||||
.ad l
|
||||
.in +8
|
||||
.ti -8
|
||||
.B ifcfg
|
||||
.RI "[ " DEVICE " ] [ " command " ] " ADDRESS " [ " PEER " ] "
|
||||
.sp
|
||||
|
||||
.SH DESCRIPTION
|
||||
This manual page documents briefly the
|
||||
.B ifcfg
|
||||
command.
|
||||
.PP
|
||||
This is a simplistic script replacing one option of
|
||||
.B ifconfig
|
||||
, namely, IP address management. It not only adds
|
||||
addresses, but also carries out Duplicate Address Detection RFC-DHCP,
|
||||
sends unsolicited ARP to update the caches of other hosts sharing
|
||||
the interface, adds some control routes and restarts Router Discovery
|
||||
when it is necessary.
|
||||
|
||||
.SH IFCONFIG - COMMAND SYNTAX
|
||||
|
||||
.SS
|
||||
.TP
|
||||
.B DEVICE
|
||||
- it may have alias, suffix, separated by colon.
|
||||
|
||||
.TP
|
||||
.B command
|
||||
- add, delete or stop.
|
||||
|
||||
.TP
|
||||
.B ADDRESS
|
||||
- optionally followed by prefix length.
|
||||
|
||||
.TP
|
||||
.B peer
|
||||
- optional peer address for pointpoint interfaces.
|
||||
|
||||
.SH NOTES
|
||||
This script is not suitable for use with IPv6.
|
||||
|
||||
.SH SEE ALSO
|
||||
.RB "IP Command reference " ip-cref.ps
|
||||
|
|
@ -49,7 +49,8 @@ ip-address \- protocol address management
|
|||
.IR TYPE " ] [ "
|
||||
.B vrf
|
||||
.IR NAME " ] [ "
|
||||
.BR up " ] ]"
|
||||
.BR up " ] ["
|
||||
.BR nomaster " ] ]"
|
||||
|
||||
.ti -8
|
||||
.BR "ip address" " { " showdump " | " restore " }"
|
||||
|
|
@ -340,6 +341,10 @@ output.
|
|||
.B up
|
||||
only list running interfaces.
|
||||
|
||||
.TP
|
||||
.B nomaster
|
||||
only list interfaces with no master.
|
||||
|
||||
.TP
|
||||
.BR dynamic " and " permanent
|
||||
(IPv6 only) only list addresses installed due to stateless
|
||||
|
|
|
|||
|
|
@ -179,7 +179,8 @@ ip-link \- network device configuration
|
|||
.B type
|
||||
.IR ETYPE " ] ["
|
||||
.B vrf
|
||||
.IR NAME " ]"
|
||||
.IR NAME " ] ["
|
||||
.BR nomaster " ]"
|
||||
|
||||
.ti -8
|
||||
.B ip link xstats
|
||||
|
|
@ -197,6 +198,7 @@ ip-link \- network device configuration
|
|||
|
||||
.ti -8
|
||||
.IR TYPE " := [ "
|
||||
.BR amt " | "
|
||||
.BR bridge " | "
|
||||
.BR bond " | "
|
||||
.BR can " | "
|
||||
|
|
@ -363,6 +365,9 @@ Link types:
|
|||
.BR bareudp
|
||||
- Bare UDP L3 encapsulation support
|
||||
.sp
|
||||
.BR amt
|
||||
- Automatic Multicast Tunneling (AMT)
|
||||
.sp
|
||||
.BR macsec
|
||||
- Interface for IEEE 802.1AE MAC Security (MACsec)
|
||||
.sp
|
||||
|
|
@ -457,7 +462,7 @@ then VLAN header will be not inserted immediately but only before
|
|||
passing to the physical device (if this device does not support VLAN
|
||||
offloading), the similar on the RX direction - by default the packet
|
||||
will be untagged before being received by VLAN device. Reordering
|
||||
allows to accelerate tagging on egress and to hide VLAN header on
|
||||
allows one to accelerate tagging on egress and to hide VLAN header on
|
||||
ingress so the packet looks like regular Ethernet packet, at the same
|
||||
time it might be confusing for packet capture as the VLAN header does
|
||||
not exist within the packet.
|
||||
|
|
@ -686,7 +691,7 @@ or the internal FDB should be used.
|
|||
- enables the Group Policy extension (VXLAN-GBP).
|
||||
|
||||
.in +4
|
||||
Allows to transport group policy context across VXLAN network peers.
|
||||
Allows one to transport group policy context across VXLAN network peers.
|
||||
If enabled, includes the mark of a packet in the VXLAN header for outgoing
|
||||
packets and fills the packet mark based on the information found in the
|
||||
VXLAN header for incoming packets.
|
||||
|
|
@ -1343,6 +1348,48 @@ When
|
|||
is "ipv4", this allows the tunnel to also handle IPv6. This option is disabled
|
||||
by default.
|
||||
|
||||
.TP
|
||||
AMT Type Support
|
||||
For a link of type
|
||||
.I AMT
|
||||
the following additional arguments are supported:
|
||||
|
||||
.BI "ip link add " DEVICE
|
||||
.BI type " AMT " discovery " IPADDR " mode " { " gateway " | " relay " } "
|
||||
.BI local " IPADDR " dev " PHYS_DEV " [
|
||||
.BI relay_port " PORT " ]
|
||||
[
|
||||
.BI gateway_port " PORT " ]
|
||||
[
|
||||
.BI max_tunnels " NUMBER "
|
||||
]
|
||||
|
||||
.in +8
|
||||
.sp
|
||||
.BI discovery " IPADDR"
|
||||
- specifies the unicast discovery IP address to use to find remote IP address.
|
||||
|
||||
.BR mode " { " gateway " | " relay " } "
|
||||
- specifies the role of AMT, Gateway or Relay
|
||||
|
||||
.BI local " IPADDR "
|
||||
- specifies the source IP address to use in outgoing packets.
|
||||
|
||||
.BI dev " PHYS_DEV "
|
||||
- specifies the underlying physical interface from which transform traffic
|
||||
is sent and received.
|
||||
|
||||
.BI relay_port " PORT "
|
||||
- specifies the UDP Relay port to communicate to the Relay.
|
||||
|
||||
.BI gateway_port " PORT "
|
||||
- specifies the UDP Gateway port to communicate to the Gateway.
|
||||
|
||||
.BI max_tunnels " NUMBER "
|
||||
- specifies the maximum number of tunnels.
|
||||
|
||||
.in -8
|
||||
|
||||
.TP
|
||||
MACVLAN and MACVTAP Type Support
|
||||
For a link of type
|
||||
|
|
@ -1492,6 +1539,8 @@ the following additional arguments are supported:
|
|||
] [
|
||||
.BI mcast_snooping " MULTICAST_SNOOPING "
|
||||
] [
|
||||
.BI mcast_vlan_snooping " MULTICAST_VLAN_SNOOPING "
|
||||
] [
|
||||
.BI mcast_router " MULTICAST_ROUTER "
|
||||
] [
|
||||
.BI mcast_query_use_ifaddr " MCAST_QUERY_USE_IFADDR "
|
||||
|
|
@ -1614,6 +1663,12 @@ per-VLAN per-port stats accounting. Can be changed only when there are no port V
|
|||
or off
|
||||
.RI ( MULTICAST_SNOOPING " == 0). "
|
||||
|
||||
.BI mcast_vlan_snooping " MULTICAST_VLAN_SNOOPING "
|
||||
- turn multicast VLAN snooping on
|
||||
.RI ( MULTICAST_VLAN_SNOOPING " > 0) "
|
||||
or off
|
||||
.RI ( MULTICAST_VLAN_SNOOPING " == 0). "
|
||||
|
||||
.BI mcast_router " MULTICAST_ROUTER "
|
||||
- set bridge's multicast router if IGMP snooping is enabled.
|
||||
.I MULTICAST_ROUTER
|
||||
|
|
@ -2038,7 +2093,7 @@ flag in the output of the
|
|||
|
||||
To change network namespace for wireless devices the
|
||||
.B iw
|
||||
tool can be used. But it allows to change network namespace only for
|
||||
tool can be used. But it allows one to change network namespace only for
|
||||
physical devices and by process
|
||||
.IR PID .
|
||||
|
||||
|
|
@ -2528,6 +2583,10 @@ interface list by comparing it with the relevant attribute in case the kernel
|
|||
didn't filter already. Therefore any string is accepted, but may lead to empty
|
||||
output.
|
||||
|
||||
.TP
|
||||
.B nomaster
|
||||
only show devices with no master
|
||||
|
||||
.SS ip link xstats - display extended statistics
|
||||
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ ip-macsec \- MACsec device configuration
|
|||
|
|
||||
.BI sci " <u64>"
|
||||
] [
|
||||
.BR cipher " { " default " | " gcm-aes-128 " | "gcm-aes-256" } ] ["
|
||||
.BR cipher " { " default " | " gcm-aes-128 " | " gcm-aes-256 " } ] ["
|
||||
.BI icvlen " ICVLEN"
|
||||
] [
|
||||
.BR encrypt " { " on " | " off " } ] ["
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ ip-neighbour \- neighbour/arp tables management.
|
|||
.B dev
|
||||
.IR DEV " ] [ "
|
||||
.BR router " ] [ "
|
||||
.BR use " ] [ "
|
||||
.BR managed " ] [ "
|
||||
.BR extern_learn " ]"
|
||||
|
||||
.ti -8
|
||||
|
|
@ -35,7 +37,8 @@ ip-neighbour \- neighbour/arp tables management.
|
|||
.B nud
|
||||
.IR STATE " ] [ "
|
||||
.B vrf
|
||||
.IR NAME " ] "
|
||||
.IR NAME " ] ["
|
||||
.BR nomaster " ]"
|
||||
|
||||
.ti -8
|
||||
.B ip neigh get
|
||||
|
|
@ -91,6 +94,21 @@ indicates whether we are proxying for this neighbour entry
|
|||
.BI router
|
||||
indicates whether neighbour is a router
|
||||
|
||||
.TP
|
||||
.BI use
|
||||
this neigh entry is in "use". This option can be used to indicate to
|
||||
the kernel that a controller is using this dynamic entry. If the entry
|
||||
does not exist, the kernel will resolve it. If it exists, an attempt
|
||||
to refresh the neighbor entry will be triggered.
|
||||
|
||||
.TP
|
||||
.BI managed
|
||||
this neigh entry is "managed". This option can be used to indicate to
|
||||
the kernel that a controller is using this dynamic entry. In contrast
|
||||
to "use", if the entry does not exist, the kernel will resolve it and
|
||||
periodically attempt to auto-refresh the neighbor entry such that it
|
||||
remains in resolved state when possible.
|
||||
|
||||
.TP
|
||||
.BI extern_learn
|
||||
this neigh entry was learned externally. This option can be used to
|
||||
|
|
@ -191,6 +209,10 @@ only list the neighbours attached to this device.
|
|||
.BI vrf " NAME"
|
||||
only list the neighbours for given VRF.
|
||||
|
||||
.TP
|
||||
.BI nomaster
|
||||
only list neighbours attached to an interface with no master.
|
||||
|
||||
.TP
|
||||
.BI proxy
|
||||
list neighbour proxies.
|
||||
|
|
|
|||
|
|
@ -246,13 +246,17 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
|
|||
.ti -8
|
||||
.IR ENCAP_IOAM6 " := "
|
||||
.B ioam6
|
||||
.BR trace
|
||||
.BR prealloc
|
||||
.BR type
|
||||
.BR mode " [ "
|
||||
.BR inline " | " encap " | " auto " ] ["
|
||||
.B tundst
|
||||
.IR ADDRESS " ] "
|
||||
.B trace
|
||||
.B prealloc
|
||||
.B type
|
||||
.IR IOAM6_TRACE_TYPE
|
||||
.BR ns
|
||||
.B ns
|
||||
.IR IOAM6_NAMESPACE
|
||||
.BR size
|
||||
.B size
|
||||
.IR IOAM6_TRACE_SIZE
|
||||
|
||||
.ti -8
|
||||
|
|
@ -915,14 +919,35 @@ address is set as described in \fBip-sr\fR(8).
|
|||
|
||||
.B ioam6
|
||||
.in +2
|
||||
.B mode inline
|
||||
- Directly insert IOAM after IPv6 header (default mode).
|
||||
.sp
|
||||
|
||||
.B mode encap
|
||||
- Encapsulate packet in an outer IPv6 header with IOAM.
|
||||
.sp
|
||||
|
||||
.B mode auto
|
||||
- Automatically use inline mode for local packets and encap mode for in-transit
|
||||
packets.
|
||||
.sp
|
||||
|
||||
.B tundst
|
||||
.I ADDRESS
|
||||
- IPv6 address of the tunnel destination (outer header), not used with inline
|
||||
mode.
|
||||
|
||||
.B type
|
||||
.I IOAM6_TRACE_TYPE
|
||||
- List of IOAM data required in the trace, represented by a bitfield (24 bits).
|
||||
.sp
|
||||
|
||||
.B ns
|
||||
.I IOAM6_NAMESPACE
|
||||
- Numerical value to represent an IOAM namespace. See \fBip-ioam\fR(8).
|
||||
.sp
|
||||
|
||||
.B size
|
||||
.I IOAM6_TRACE_SIZE
|
||||
- Size, in octets, of the pre-allocated trace data block.
|
||||
.in -4
|
||||
|
|
@ -1249,9 +1274,9 @@ ip -6 route add 2001:db8:1::/64 encap seg6local action End.DT46 vrftable 100 dev
|
|||
Adds an IPv6 route with SRv6 decapsulation and forward with lookup in VRF table.
|
||||
.RE
|
||||
.PP
|
||||
ip -6 route add 2001:db8:1::/64 encap ioam6 trace prealloc type 0x800000 ns 1 size 12 dev eth0
|
||||
ip -6 route add 2001:db8:1::/64 encap ioam6 mode encap tundst 2001:db8:42::1 trace prealloc type 0x800000 ns 1 size 12 dev eth0
|
||||
.RS 4
|
||||
Adds an IPv6 route with an IOAM Pre-allocated Trace encapsulation that only includes the hop limit and the node id, configured for the IOAM namespace 1 and a pre-allocated data block of 12 octets.
|
||||
Adds an IPv6 route with an IOAM Pre-allocated Trace encapsulation (ip6ip6) that only includes the hop limit and the node id, configured for the IOAM namespace 1 and a pre-allocated data block of 12 octets.
|
||||
.RE
|
||||
.PP
|
||||
ip route add 10.1.1.0/30 nhid 10
|
||||
|
|
|
|||
|
|
@ -298,6 +298,18 @@ ip-xfrm \- transform configuration
|
|||
.RB "[ " hthresh6
|
||||
.IR LBITS " " RBITS " ]"
|
||||
|
||||
.ti -8
|
||||
.B "ip xfrm policy setdefault"
|
||||
.IR DIR
|
||||
.IR ACTION " [ "
|
||||
.IR DIR
|
||||
.IR ACTION " ] [ "
|
||||
.IR DIR
|
||||
.IR ACTION " ]"
|
||||
|
||||
.ti -8
|
||||
.B "ip xfrm policy getdefault"
|
||||
|
||||
.ti -8
|
||||
.IR SELECTOR " :="
|
||||
.RB "[ " src
|
||||
|
|
|
|||
|
|
@ -58,6 +58,28 @@ rdma-statistic \- RDMA statistic counter configuration
|
|||
.RI "[ " COUNTER-ID " ]"
|
||||
.RI "[ " OBJECT-ID " ]"
|
||||
|
||||
.ti -8
|
||||
.B rdma statistic
|
||||
.B mode
|
||||
.B "[" supported "]"
|
||||
.B link
|
||||
.RI "[ " DEV/PORT_INDEX " ]"
|
||||
|
||||
.ti -8
|
||||
.B rdma statistic
|
||||
.B set
|
||||
.B link
|
||||
.RI "[ " DEV/PORT_INDEX " ]"
|
||||
.B optional-counters
|
||||
.RI "[ " OPTIONAL-COUNTERS " ]"
|
||||
|
||||
.ti -8
|
||||
.B rdma statistic
|
||||
.B unset
|
||||
.B link
|
||||
.RI "[ " DEV/PORT_INDEX " ]"
|
||||
.B optional-counters
|
||||
|
||||
.ti -8
|
||||
.IR COUNTER_SCOPE " := "
|
||||
.RB "{ " link " | " dev " }"
|
||||
|
|
@ -100,6 +122,17 @@ When unbound the statistics of this object are no longer available in this count
|
|||
- specifies the id of the counter to be bound.
|
||||
If this argument is omitted then a new counter will be allocated.
|
||||
|
||||
.SS rdma statistic mode - Display the enabled optional counters for each link.
|
||||
|
||||
.SS rdma statistic mode supported - Display the supported optional counters for each link.
|
||||
|
||||
.SS rdma statistic set - Enable a set of optional counters for a specific device/port.
|
||||
|
||||
.I "OPTIONAL-COUNTERS"
|
||||
- specifies the name of the optional counters to enable. Optional counters that are not specified will be disabled. Note that optional counters are driver-specific.
|
||||
|
||||
.SS rdma statistic unset - Disable all optional counters for a specific device/port.
|
||||
|
||||
.SH "EXAMPLES"
|
||||
.PP
|
||||
rdma statistic show
|
||||
|
|
@ -186,6 +219,26 @@ rdma statistic show mr mrn 6
|
|||
.RS 4
|
||||
Dump a specific MR statistics with mrn 6. Dumps nothing if does not exists.
|
||||
.RE
|
||||
.PP
|
||||
rdma statistic mode link mlx5_2/1
|
||||
.RS 4
|
||||
Display the optional counters that was enabled on mlx5_2/1.
|
||||
.RE
|
||||
.PP
|
||||
rdma statistic mode supported link mlx5_2/1
|
||||
.RS 4
|
||||
Display the optional counters that mlx5_2/1 supports.
|
||||
.RE
|
||||
.PP
|
||||
rdma statistic set link mlx5_2/1 optional-counters cc_rx_ce_pkts,cc_rx_cnp_pkts
|
||||
.RS 4
|
||||
Enable the cc_rx_ce_pkts,cc_rx_cnp_pkts counters on device mlx5_2 port 1.
|
||||
.RE
|
||||
.PP
|
||||
rdma statistic unset link mlx5_2/1 optional-counters
|
||||
.RS 4
|
||||
Disable all the optional counters on device mlx5_2 port 1.
|
||||
.RE
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR rdma (8),
|
||||
|
|
@ -198,3 +251,5 @@ Dump a specific MR statistics with mrn 6. Dumps nothing if does not exists.
|
|||
Mark Zhang <markz@mellanox.com>
|
||||
.br
|
||||
Erez Alfasi <ereza@mellanox.com>
|
||||
.br
|
||||
Neta Ostrovsky <netao@nvidia.com>
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
.so man8/routel.8
|
||||
|
|
@ -1,25 +1,31 @@
|
|||
.TH "ROUTEL" "8" "3 Jan, 2008" "iproute2" "Linux"
|
||||
.TH ROUTEL 8 "1 Sept, 2021" "iproute2" "Linux"
|
||||
.SH "NAME"
|
||||
.LP
|
||||
routel \- list routes with pretty output format
|
||||
.br
|
||||
routef \- flush routes
|
||||
.SH "SYNTAX"
|
||||
.LP
|
||||
routel [\fItablenr\fP [\fIraw ip args...\fP]]
|
||||
.br
|
||||
routef
|
||||
.SH SYNOPSIS
|
||||
.B routel
|
||||
.RI "[ " OPTIONS " ]"
|
||||
.RI "[ " tablenr
|
||||
[ \fIip route options...\fR ] ]
|
||||
.P
|
||||
.ti 8
|
||||
.IR OPTIONS " := {"
|
||||
\fB-h\fR | \fB--help\fR |
|
||||
[{\fB-f\fR | \fB--family\fR }
|
||||
{\fBinet\fR | \fBinet6\fR } |
|
||||
\fB-4\fR | \fB-6\fR }
|
||||
|
||||
.SH "DESCRIPTION"
|
||||
.LP
|
||||
These programs are a set of helper scripts you can use instead of raw iproute2 commands.
|
||||
.br
|
||||
The routel script will list routes in a format that some might consider easier to interpret then the ip route list equivalent.
|
||||
.br
|
||||
The routef script does not take any arguments and will simply flush the routing table down the drain. Beware! This means deleting all routes which will make your network unusable!
|
||||
The routel script will list routes in a format that some might consider
|
||||
easier to interpret then the
|
||||
.B ip
|
||||
route list equivalent.
|
||||
|
||||
.SH "AUTHORS"
|
||||
.LP
|
||||
The routel script was written by Stephen R. van den Berg <srb@cuci.nl>, 1999/04/18 and donated to the public domain.
|
||||
Rewritten by Stephen Hemminger <stephen@networkplumber.org>.
|
||||
.br
|
||||
Original script by Stephen R. van den Berg <srb@cuci.nl>.
|
||||
.br
|
||||
This manual page was written by Andreas Henriksson <andreas@fatal.se>, for the Debian GNU/Linux system.
|
||||
.SH "SEE ALSO"
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
.TH RTPR 8 "18 September, 2015"
|
||||
|
||||
.SH NAME
|
||||
rtpr \- replace backslashes with newlines.
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B rtpr
|
||||
is a trivial shell script which converts backslashes in standard input to newlines. It's sole purpose is to be fed with input from
|
||||
.B ip
|
||||
when executed with it's
|
||||
.B --oneline
|
||||
flag.
|
||||
|
||||
.SH EXAMPLES
|
||||
.TP
|
||||
ip --oneline address show | rtpr
|
||||
Undo oneline converted
|
||||
.B ip-address
|
||||
output.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR ip (8)
|
||||
|
||||
.SH AUTHORS
|
||||
Stephen Hemminger <shemming@brocade.com>
|
||||
|
|
@ -409,7 +409,7 @@ Please take a look at the official documentation for details regarding filters.
|
|||
.SH STATE-FILTER
|
||||
|
||||
.B STATE-FILTER
|
||||
allows to construct arbitrary set of states to match. Its syntax is
|
||||
allows one to construct arbitrary set of states to match. Its syntax is
|
||||
sequence of keywords state and exclude followed by identifier of
|
||||
state.
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ basic \- basic traffic control filter
|
|||
.SH DESCRIPTION
|
||||
The
|
||||
.B basic
|
||||
filter allows to classify packets using the extended match infrastructure.
|
||||
filter allows one to classify packets using the extended match infrastructure.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BI action " ACTION_SPEC"
|
||||
|
|
|
|||
|
|
@ -12,13 +12,13 @@ fw \- fwmark traffic control filter
|
|||
.SH DESCRIPTION
|
||||
the
|
||||
.B fw
|
||||
filter allows to classify packets based on a previously set
|
||||
filter allows one to classify packets based on a previously set
|
||||
.BR fwmark " by " iptables .
|
||||
If it is identical to the filter's
|
||||
.BR handle ,
|
||||
the filter matches.
|
||||
.B iptables
|
||||
allows to mark single packets with the
|
||||
allows one to mark single packets with the
|
||||
.B MARK
|
||||
target, or whole connections using
|
||||
.BR CONNMARK .
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ matchall \- traffic control filter that matches every packet
|
|||
.SH DESCRIPTION
|
||||
The
|
||||
.B matchall
|
||||
filter allows to classify every packet that flows on the port and run a
|
||||
filter allows one to classify every packet that flows on the port and run a
|
||||
action on it.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ nat - stateless native address translation action
|
|||
.SH DESCRIPTION
|
||||
The
|
||||
.B nat
|
||||
action allows to perform NAT without the overhead of conntrack, which is
|
||||
action allows one to perform NAT without the overhead of conntrack, which is
|
||||
desirable if the number of flows or addresses to perform NAT on is large. This
|
||||
action is best used in combination with the
|
||||
.B u32
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ maximum number of packets the qdisc may hold queued at a time.
|
|||
|
||||
.SS delay
|
||||
adds the chosen delay to the packets outgoing to chosen network interface. The
|
||||
optional parameters allows to introduce a delay variation and a correlation.
|
||||
optional parameters allows one to introduce a delay variation and a correlation.
|
||||
Delay and jitter values are expressed in ms while correlation is percentage.
|
||||
|
||||
.SS distribution
|
||||
|
|
@ -99,7 +99,7 @@ is now deprecated due to the noticed bad behavior.
|
|||
.SS loss state
|
||||
adds packet losses according to the 4-state Markov using the transition
|
||||
probabilities as input parameters. The parameter p13 is mandatory and if used
|
||||
alone corresponds to the Bernoulli model. The optional parameters allows to
|
||||
alone corresponds to the Bernoulli model. The optional parameters allows one to
|
||||
extend the model to 2-state (p31), 3-state (p23 and p32) and 4-state (p14).
|
||||
State 1 corresponds to good reception, State 4 to independent losses, State 3
|
||||
to burst losses and State 2 to good reception within a burst.
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ or a single byte
|
|||
.BI at " AT " offmask " MASK " shift " SHIFT"
|
||||
This is an optional part of
|
||||
.IR RAW_OP
|
||||
which allows to have a variable
|
||||
which allows one to have a variable
|
||||
.I OFFSET
|
||||
depending on packet data at offset
|
||||
.IR AT ,
|
||||
|
|
@ -202,7 +202,7 @@ unexpected things.
|
|||
.B icmp_type
|
||||
.TQ
|
||||
.B icmp_code
|
||||
Again, this allows to change data past the actual IP header itself. It assumes
|
||||
Again, this allows one to change data past the actual IP header itself. It assumes
|
||||
an ICMP header is present immediately following the (minimal sized) IP header.
|
||||
If it is not or the latter is bigger than the minimum of 20 bytes, this will do
|
||||
unexpected things. These fields are eight-bit values.
|
||||
|
|
@ -300,7 +300,7 @@ Keep the addressed data as is.
|
|||
.BI retain " RVAL"
|
||||
This optional extra part of
|
||||
.I CMD_SPEC
|
||||
allows to exclude bits from being changed. Supported only for 32 bits fields
|
||||
allows one to exclude bits from being changed. Supported only for 32 bits fields
|
||||
or smaller.
|
||||
.TP
|
||||
.I CONTROL
|
||||
|
|
|
|||
|
|
@ -92,8 +92,8 @@ packets that came from a specific rule.
|
|||
.TP
|
||||
.BI index " INDEX"
|
||||
Is a unique ID for an action. When creating new action instance, this parameter
|
||||
allows to set the new action index. When using existing action, this parameter
|
||||
allows to specify the existing action index. The index must 32bit unsigned
|
||||
allows one to set the new action index. When using existing action, this parameter
|
||||
allows one to specify the existing action index. The index must 32bit unsigned
|
||||
integer greater than zero.
|
||||
.SH EXAMPLES
|
||||
Sample one of every 100 packets flowing into interface eth0 to psample group 12:
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ skbedit - SKB editing action
|
|||
.SH DESCRIPTION
|
||||
The
|
||||
.B skbedit
|
||||
action allows to change a packet's associated meta data. It complements the
|
||||
action allows one to change a packet's associated meta data. It complements the
|
||||
.B pedit
|
||||
action, which in turn allows to change parts of the packet data itself.
|
||||
action, which in turn allows one to change parts of the packet data itself.
|
||||
|
||||
The most unique feature of
|
||||
.B skbedit
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ tcindex \- traffic control index filter
|
|||
.B action
|
||||
.BR ACTION_SPEC " ]"
|
||||
.SH DESCRIPTION
|
||||
This filter allows to match packets based on their
|
||||
This filter allows one to match packets based on their
|
||||
.B tcindex
|
||||
field value, i.e. the combination of the DSCP and ECN fields as present in IPv4
|
||||
and IPv6 headers.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ tunnel_key - Tunnel metadata manipulation
|
|||
.SH DESCRIPTION
|
||||
The
|
||||
.B tunnel_key
|
||||
action combined with a shared IP tunnel device, allows to perform IP tunnel en-
|
||||
action combined with a shared IP tunnel device, allows one to perform IP tunnel en-
|
||||
or decapsulation on a packet, reflected by
|
||||
the operation modes
|
||||
.IR UNSET " and " SET .
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ u32 \- universal 32bit traffic control filter
|
|||
.BR at " [ " nexthdr+ " ] "
|
||||
.IR int_value " ]"
|
||||
.SH DESCRIPTION
|
||||
The Universal/Ugly 32bit filter allows to match arbitrary bitfields in the
|
||||
The Universal/Ugly 32bit filter allows one to match arbitrary bitfields in the
|
||||
packet. Due to breaking everything down to values, masks and offsets, It is
|
||||
equally powerful and hard to use. Luckily many abstracting directives are
|
||||
present which allow defining rules on a higher level and therefore free the
|
||||
|
|
@ -375,7 +375,7 @@ or IPv6 (
|
|||
.BR ip6 )
|
||||
header.
|
||||
.IR IP / IP6
|
||||
then allows to match various header fields:
|
||||
then allows one to match various header fields:
|
||||
.RS
|
||||
.TP
|
||||
.BI src " ADDR"
|
||||
|
|
@ -427,7 +427,7 @@ Also minimal header size for IPv4 and lack of IPv6 extension headers is assumed.
|
|||
IPv4 only, check certain flags and fragment offset values. Match if the packet
|
||||
is not a fragment
|
||||
.RB ( nofrag ),
|
||||
the first fragment
|
||||
the first fragment of a fragmented packet
|
||||
.RB ( firstfrag ),
|
||||
if Don't Fragment
|
||||
.RB ( df )
|
||||
|
|
@ -644,7 +644,7 @@ tc filter add dev eth0 parent 1:0 protocol ip \\
|
|||
tc filter add dev eth0 parent 1:0 protocol ip \\
|
||||
u32 ht 800: \\
|
||||
match ip protocol 6 FF \\
|
||||
match ip firstfrag \\
|
||||
match u16 0 1fff at 6 \\
|
||||
offset at 0 mask 0f00 shift 6 \\
|
||||
link 1:
|
||||
.EE
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ vlan - vlan manipulation module
|
|||
.SH DESCRIPTION
|
||||
The
|
||||
.B vlan
|
||||
action allows to perform 802.1Q en- or decapsulation on a packet, reflected by
|
||||
action allows one to perform 802.1Q en- or decapsulation on a packet, reflected by
|
||||
the operation modes
|
||||
.IR POP ", " PUSH " and " MODIFY .
|
||||
The
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ xt - tc iptables action
|
|||
.SH DESCRIPTION
|
||||
The
|
||||
.B xt
|
||||
action allows to call arbitrary iptables targets for packets matching the filter
|
||||
action allows one to call arbitrary iptables targets for packets matching the filter
|
||||
this action is attached to.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -210,8 +210,9 @@ static struct table_hdr *build_hdr_string(struct lnstat_file *lnstat_files,
|
|||
}
|
||||
ofs += width+1;
|
||||
}
|
||||
|
||||
/* fill in spaces */
|
||||
for (h = 1; h <= th.num_lines; h++) {
|
||||
for (h = 1; h < th.num_lines; h++) {
|
||||
for (i = 0; i < ofs; i++) {
|
||||
if (th.hdr[h][i] == '\0')
|
||||
th.hdr[h][i] = ' ';
|
||||
|
|
|
|||
|
|
@ -457,6 +457,17 @@ struct ib_uverbs_poll_cq {
|
|||
__u32 ne;
|
||||
};
|
||||
|
||||
enum ib_uverbs_wc_opcode {
|
||||
IB_UVERBS_WC_SEND = 0,
|
||||
IB_UVERBS_WC_RDMA_WRITE = 1,
|
||||
IB_UVERBS_WC_RDMA_READ = 2,
|
||||
IB_UVERBS_WC_COMP_SWAP = 3,
|
||||
IB_UVERBS_WC_FETCH_ADD = 4,
|
||||
IB_UVERBS_WC_BIND_MW = 5,
|
||||
IB_UVERBS_WC_LOCAL_INV = 6,
|
||||
IB_UVERBS_WC_TSO = 7,
|
||||
};
|
||||
|
||||
struct ib_uverbs_wc {
|
||||
__aligned_u64 wr_id;
|
||||
__u32 status;
|
||||
|
|
@ -585,20 +596,6 @@ enum {
|
|||
IB_UVERBS_CREATE_QP_SUP_COMP_MASK = IB_UVERBS_CREATE_QP_MASK_IND_TABLE,
|
||||
};
|
||||
|
||||
enum {
|
||||
/*
|
||||
* This value is equal to IB_QP_DEST_QPN.
|
||||
*/
|
||||
IB_USER_LEGACY_LAST_QP_ATTR_MASK = 1ULL << 20,
|
||||
};
|
||||
|
||||
enum {
|
||||
/*
|
||||
* This value is equal to IB_QP_RATE_LIMIT.
|
||||
*/
|
||||
IB_USER_LAST_QP_ATTR_MASK = 1ULL << 25,
|
||||
};
|
||||
|
||||
struct ib_uverbs_ex_create_qp {
|
||||
__aligned_u64 user_handle;
|
||||
__u32 pd_handle;
|
||||
|
|
|
|||
|
|
@ -297,6 +297,8 @@ enum rdma_nldev_command {
|
|||
|
||||
RDMA_NLDEV_CMD_RES_SRQ_GET, /* can dump */
|
||||
|
||||
RDMA_NLDEV_CMD_STAT_GET_STATUS,
|
||||
|
||||
RDMA_NLDEV_NUM_OPS
|
||||
};
|
||||
|
||||
|
|
@ -549,6 +551,9 @@ enum rdma_nldev_attr {
|
|||
|
||||
RDMA_NLDEV_SYS_ATTR_COPY_ON_FORK, /* u8 */
|
||||
|
||||
RDMA_NLDEV_ATTR_STAT_HWCOUNTER_INDEX, /* u32 */
|
||||
RDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC, /* u8 */
|
||||
|
||||
/*
|
||||
* Always the end
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ struct rdma_ucm_query_route_resp {
|
|||
__u32 num_paths;
|
||||
__u8 port_num;
|
||||
__u8 reserved[3];
|
||||
__u32 ibdev_index;
|
||||
__u32 reserved1;
|
||||
};
|
||||
|
||||
struct rdma_ucm_query_addr_resp {
|
||||
|
|
@ -175,6 +177,8 @@ struct rdma_ucm_query_addr_resp {
|
|||
__u16 dst_size;
|
||||
struct __kernel_sockaddr_storage src_addr;
|
||||
struct __kernel_sockaddr_storage dst_addr;
|
||||
__u32 ibdev_index;
|
||||
__u32 reserved1;
|
||||
};
|
||||
|
||||
struct rdma_ucm_query_path_resp {
|
||||
|
|
@ -206,10 +210,16 @@ struct rdma_ucm_ud_param {
|
|||
__u8 reserved[7];
|
||||
};
|
||||
|
||||
struct rdma_ucm_ece {
|
||||
__u32 vendor_id;
|
||||
__u32 attr_mod;
|
||||
};
|
||||
|
||||
struct rdma_ucm_connect {
|
||||
struct rdma_ucm_conn_param conn_param;
|
||||
__u32 id;
|
||||
__u32 reserved;
|
||||
struct rdma_ucm_ece ece;
|
||||
};
|
||||
|
||||
struct rdma_ucm_listen {
|
||||
|
|
@ -222,12 +232,14 @@ struct rdma_ucm_accept {
|
|||
struct rdma_ucm_conn_param conn_param;
|
||||
__u32 id;
|
||||
__u32 reserved;
|
||||
struct rdma_ucm_ece ece;
|
||||
};
|
||||
|
||||
struct rdma_ucm_reject {
|
||||
__u32 id;
|
||||
__u8 private_data_len;
|
||||
__u8 reserved[3];
|
||||
__u8 reason;
|
||||
__u8 reserved[2];
|
||||
__u8 private_data[RDMA_MAX_PRIVATE_DATA];
|
||||
};
|
||||
|
||||
|
|
@ -287,6 +299,7 @@ struct rdma_ucm_event_resp {
|
|||
struct rdma_ucm_ud_param ud;
|
||||
} param;
|
||||
__u32 reserved;
|
||||
struct rdma_ucm_ece ece;
|
||||
};
|
||||
|
||||
/* Option levels */
|
||||
|
|
|
|||
341
rdma/stat.c
341
rdma/stat.c
|
|
@ -20,6 +20,10 @@ static int stat_help(struct rd *rd)
|
|||
pr_out(" %s statistic OBJECT unbind COUNTER_SCOPE [DEV/PORT_INDEX] [COUNTER-ID]\n", rd->filename);
|
||||
pr_out(" %s statistic show\n", rd->filename);
|
||||
pr_out(" %s statistic show link [ DEV/PORT_INDEX ]\n", rd->filename);
|
||||
pr_out(" %s statistic mode [ supported ]\n", rd->filename);
|
||||
pr_out(" %s statistic mode [ supported ] link [ DEV/PORT_INDEX ]\n", rd->filename);
|
||||
pr_out(" %s statistic set link [ DEV/PORT_INDEX ] optional-counters [ OPTIONAL-COUNTERS ]\n", rd->filename);
|
||||
pr_out(" %s statistic unset link [ DEV/PORT_INDEX ] optional-counters\n", rd->filename);
|
||||
pr_out("where OBJECT: = { qp }\n");
|
||||
pr_out(" CRITERIA : = { type }\n");
|
||||
pr_out(" COUNTER_SCOPE: = { link | dev }\n");
|
||||
|
|
@ -37,6 +41,12 @@ static int stat_help(struct rd *rd)
|
|||
pr_out(" %s statistic qp unbind link mlx5_2/1 cntn 4 lqpn 178\n", rd->filename);
|
||||
pr_out(" %s statistic show\n", rd->filename);
|
||||
pr_out(" %s statistic show link mlx5_2/1\n", rd->filename);
|
||||
pr_out(" %s statistic mode\n", rd->filename);
|
||||
pr_out(" %s statistic mode link mlx5_2/1\n", rd->filename);
|
||||
pr_out(" %s statistic mode supported\n", rd->filename);
|
||||
pr_out(" %s statistic mode supported link mlx5_2/1\n", rd->filename);
|
||||
pr_out(" %s statistic set link mlx5_2/1 optional-counters cc_rx_ce_pkts,cc_rx_cnp_pkts\n", rd->filename);
|
||||
pr_out(" %s statistic unset link mlx5_2/1 optional-counters\n", rd->filename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -493,6 +503,30 @@ static int stat_qp_set(struct rd *rd)
|
|||
return rd_exec_cmd(rd, cmds, "parameter");
|
||||
}
|
||||
|
||||
static int stat_get_arg_str(struct rd *rd, const char *arg, char **value, bool allow_empty)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (strcmpx(rd_argv(rd), arg) != 0) {
|
||||
pr_err("Unknown parameter '%s'.\n", rd_argv(rd));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rd_arg_inc(rd);
|
||||
if (!rd_no_arg(rd)) {
|
||||
*value = strdup(rd_argv(rd));
|
||||
len = strlen(*value);
|
||||
rd_arg_inc(rd);
|
||||
}
|
||||
|
||||
if ((allow_empty && len) || (!allow_empty && !len)) {
|
||||
stat_help(rd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stat_get_arg(struct rd *rd, const char *arg)
|
||||
{
|
||||
int value = 0;
|
||||
|
|
@ -715,6 +749,310 @@ static int stat_qp(struct rd *rd)
|
|||
return rd_exec_cmd(rd, cmds, "parameter");
|
||||
}
|
||||
|
||||
static int do_stat_mode_parse_cb(const struct nlmsghdr *nlh, void *data,
|
||||
bool supported)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct nlattr *nla_entry;
|
||||
const char *dev, *name;
|
||||
struct rd *rd = data;
|
||||
int enabled, err = 0;
|
||||
bool isfirst = true;
|
||||
uint32_t port;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
|
||||
!tb[RDMA_NLDEV_ATTR_PORT_INDEX] ||
|
||||
!tb[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
dev = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
|
||||
port = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_PORT_INDEX]);
|
||||
|
||||
mnl_attr_for_each_nested(nla_entry,
|
||||
tb[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS]) {
|
||||
struct nlattr *cnt[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
|
||||
err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, cnt);
|
||||
if ((err != MNL_CB_OK) ||
|
||||
(!cnt[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME]))
|
||||
return -EINVAL;
|
||||
|
||||
if (!cnt[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC])
|
||||
continue;
|
||||
|
||||
enabled = mnl_attr_get_u8(cnt[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC]);
|
||||
name = mnl_attr_get_str(cnt[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME]);
|
||||
if (supported || enabled) {
|
||||
if (isfirst) {
|
||||
open_json_object(NULL);
|
||||
print_color_string(PRINT_ANY, COLOR_NONE,
|
||||
"ifname", "link %s/", dev);
|
||||
print_color_uint(PRINT_ANY, COLOR_NONE, "port",
|
||||
"%u ", port);
|
||||
if (supported)
|
||||
open_json_array(PRINT_ANY,
|
||||
"supported optional-counters");
|
||||
else
|
||||
open_json_array(PRINT_ANY,
|
||||
"optional-counters");
|
||||
print_color_string(PRINT_FP, COLOR_NONE, NULL,
|
||||
" ", NULL);
|
||||
isfirst = false;
|
||||
} else {
|
||||
print_color_string(PRINT_FP, COLOR_NONE, NULL,
|
||||
",", NULL);
|
||||
}
|
||||
if (rd->pretty_output && !rd->json_output)
|
||||
newline_indent(rd);
|
||||
|
||||
print_color_string(PRINT_ANY, COLOR_NONE, NULL, "%s",
|
||||
name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isfirst) {
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
newline(rd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stat_mode_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
return do_stat_mode_parse_cb(nlh, data, false);
|
||||
}
|
||||
|
||||
static int stat_mode_parse_cb_supported(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
return do_stat_mode_parse_cb(nlh, data, true);
|
||||
}
|
||||
|
||||
static int stat_one_link_get_status_req(struct rd *rd, uint32_t *seq)
|
||||
{
|
||||
int flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
|
||||
rd_prepare_msg(rd, RDMA_NLDEV_CMD_STAT_GET_STATUS, seq, flags);
|
||||
mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
|
||||
mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_PORT_INDEX, rd->port_idx);
|
||||
|
||||
return rd_send_msg(rd);
|
||||
}
|
||||
|
||||
static int stat_one_link_get_mode(struct rd *rd)
|
||||
{
|
||||
uint32_t seq;
|
||||
int err;
|
||||
|
||||
if (!rd->port_idx)
|
||||
return 0;
|
||||
|
||||
err = stat_one_link_get_status_req(rd, &seq);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return rd_recv_msg(rd, stat_mode_parse_cb, rd, seq);
|
||||
}
|
||||
|
||||
static int stat_one_link_get_mode_supported(struct rd *rd)
|
||||
{
|
||||
uint32_t seq;
|
||||
int err;
|
||||
|
||||
if (!rd->port_idx)
|
||||
return 0;
|
||||
|
||||
err = stat_one_link_get_status_req(rd, &seq);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return rd_recv_msg(rd, stat_mode_parse_cb_supported, rd, seq);
|
||||
}
|
||||
|
||||
static int stat_link_get_mode(struct rd *rd)
|
||||
{
|
||||
return rd_exec_link(rd, stat_one_link_get_mode, false);
|
||||
}
|
||||
|
||||
static int stat_link_get_mode_supported(struct rd *rd)
|
||||
{
|
||||
return rd_exec_link(rd, stat_one_link_get_mode_supported, false);
|
||||
}
|
||||
|
||||
static int stat_mode_supported(struct rd *rd)
|
||||
{
|
||||
const struct rd_cmd cmds[] = {
|
||||
{ NULL, stat_link_get_mode_supported },
|
||||
{ "link", stat_link_get_mode_supported },
|
||||
{ "help", stat_help },
|
||||
{ 0 },
|
||||
};
|
||||
return rd_exec_cmd(rd, cmds, "parameter");
|
||||
}
|
||||
|
||||
static int stat_mode(struct rd *rd)
|
||||
{
|
||||
const struct rd_cmd cmds[] = {
|
||||
{ NULL, stat_link_get_mode },
|
||||
{ "link", stat_link_get_mode },
|
||||
{ "show", stat_link_get_mode },
|
||||
{ "supported", stat_mode_supported },
|
||||
{ "help", stat_help },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
return rd_exec_cmd(rd, cmds, "parameter");
|
||||
}
|
||||
|
||||
static int stat_one_set_link_opcounters(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
struct nlattr *nla_entry, *tb_set;
|
||||
int ret, flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
char *opcnt, *opcnts;
|
||||
struct rd *rd = data;
|
||||
uint32_t seq;
|
||||
bool found;
|
||||
|
||||
mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
|
||||
if (!tb[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS])
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
if (rd_no_arg(rd)) {
|
||||
stat_help(rd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = stat_get_arg_str(rd, "optional-counters", &opcnts, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rd_prepare_msg(rd, RDMA_NLDEV_CMD_STAT_SET, &seq, flags);
|
||||
mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX,
|
||||
rd->dev_idx);
|
||||
mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_PORT_INDEX,
|
||||
rd->port_idx);
|
||||
|
||||
tb_set = mnl_attr_nest_start(rd->nlh, RDMA_NLDEV_ATTR_STAT_HWCOUNTERS);
|
||||
|
||||
opcnt = strtok(opcnts, ",");
|
||||
while (opcnt) {
|
||||
found = false;
|
||||
mnl_attr_for_each_nested(nla_entry,
|
||||
tb[RDMA_NLDEV_ATTR_STAT_HWCOUNTERS]) {
|
||||
struct nlattr *cnt[RDMA_NLDEV_ATTR_MAX] = {}, *nm, *id;
|
||||
|
||||
if (mnl_attr_parse_nested(nla_entry, rd_attr_cb,
|
||||
cnt) != MNL_CB_OK)
|
||||
return -EINVAL;
|
||||
|
||||
nm = cnt[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME];
|
||||
id = cnt[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_INDEX];
|
||||
if (!nm || ! id)
|
||||
return -EINVAL;
|
||||
|
||||
if (!cnt[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC])
|
||||
continue;
|
||||
|
||||
if (strcmp(opcnt, mnl_attr_get_str(nm)) == 0) {
|
||||
mnl_attr_put_u32(rd->nlh,
|
||||
RDMA_NLDEV_ATTR_STAT_HWCOUNTER_INDEX,
|
||||
mnl_attr_get_u32(id));
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return -EINVAL;
|
||||
|
||||
opcnt = strtok(NULL, ",");
|
||||
}
|
||||
mnl_attr_nest_end(rd->nlh, tb_set);
|
||||
|
||||
return rd_sendrecv_msg(rd, seq);
|
||||
}
|
||||
|
||||
static int stat_one_set_link(struct rd *rd)
|
||||
{
|
||||
uint32_t seq;
|
||||
int err;
|
||||
|
||||
if (!rd->port_idx)
|
||||
return 0;
|
||||
|
||||
err = stat_one_link_get_status_req(rd, &seq);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return rd_recv_msg(rd, stat_one_set_link_opcounters, rd, seq);
|
||||
}
|
||||
|
||||
static int stat_set_link(struct rd *rd)
|
||||
{
|
||||
return rd_exec_link(rd, stat_one_set_link, true);
|
||||
}
|
||||
|
||||
static int stat_set(struct rd *rd)
|
||||
{
|
||||
const struct rd_cmd cmds[] = {
|
||||
{ NULL, stat_help },
|
||||
{ "link", stat_set_link },
|
||||
{ "help", stat_help },
|
||||
{ 0 },
|
||||
};
|
||||
return rd_exec_cmd(rd, cmds, "parameter");
|
||||
}
|
||||
|
||||
static int stat_one_unset_link_opcounters(struct rd *rd)
|
||||
{
|
||||
int ret, flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
struct nlattr *tbl;
|
||||
uint32_t seq;
|
||||
char *opcnts;
|
||||
|
||||
if (rd_no_arg(rd)) {
|
||||
stat_help(rd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = stat_get_arg_str(rd, "optional-counters", &opcnts, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rd_prepare_msg(rd, RDMA_NLDEV_CMD_STAT_SET, &seq, flags);
|
||||
mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX,
|
||||
rd->dev_idx);
|
||||
mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_PORT_INDEX,
|
||||
rd->port_idx);
|
||||
|
||||
tbl = mnl_attr_nest_start(rd->nlh, RDMA_NLDEV_ATTR_STAT_HWCOUNTERS);
|
||||
mnl_attr_nest_end(rd->nlh, tbl);
|
||||
|
||||
return rd_sendrecv_msg(rd, seq);
|
||||
}
|
||||
|
||||
static int stat_one_unset_link(struct rd *rd)
|
||||
{
|
||||
return stat_one_unset_link_opcounters(rd);
|
||||
}
|
||||
|
||||
static int stat_unset_link(struct rd *rd)
|
||||
{
|
||||
return rd_exec_link(rd, stat_one_unset_link, true);
|
||||
}
|
||||
|
||||
static int stat_unset(struct rd *rd)
|
||||
{
|
||||
const struct rd_cmd cmds[] = {
|
||||
{ NULL, stat_help },
|
||||
{ "link", stat_unset_link },
|
||||
{ "help", stat_help },
|
||||
{ 0 },
|
||||
};
|
||||
return rd_exec_cmd(rd, cmds, "parameter");
|
||||
}
|
||||
|
||||
static int stat_show_parse_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
|
||||
|
|
@ -786,6 +1124,9 @@ int cmd_stat(struct rd *rd)
|
|||
{ "help", stat_help },
|
||||
{ "qp", stat_qp },
|
||||
{ "mr", stat_mr },
|
||||
{ "mode", stat_mode },
|
||||
{ "set", stat_set },
|
||||
{ "unset", stat_unset },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2195,7 +2195,7 @@ static void flower_print_ct_label(struct rtattr *attr,
|
|||
const unsigned char *str;
|
||||
bool print_mask = false;
|
||||
int data_len, i;
|
||||
SPRINT_BUF(out);
|
||||
char out[128];
|
||||
char *p;
|
||||
|
||||
if (!attr)
|
||||
|
|
|
|||
|
|
@ -279,8 +279,8 @@ static int print_vlan(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
ETH_ALEN, 0, b1, sizeof(b1));
|
||||
print_string(PRINT_ANY, "dst_mac", " dst_mac %s", b1);
|
||||
}
|
||||
if (tb[TCA_VLAN_PUSH_ETH_SRC &&
|
||||
RTA_PAYLOAD(tb[TCA_VLAN_PUSH_ETH_SRC]) == ETH_ALEN]) {
|
||||
if (tb[TCA_VLAN_PUSH_ETH_SRC] &&
|
||||
RTA_PAYLOAD(tb[TCA_VLAN_PUSH_ETH_SRC]) == ETH_ALEN) {
|
||||
ll_addr_n2a(RTA_DATA(tb[TCA_VLAN_PUSH_ETH_SRC]),
|
||||
ETH_ALEN, 0, b1, sizeof(b1));
|
||||
print_string(PRINT_ANY, "src_mac", " src_mac %s", b1);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ enum vdpa_command {
|
|||
VDPA_CMD_DEV_NEW,
|
||||
VDPA_CMD_DEV_DEL,
|
||||
VDPA_CMD_DEV_GET, /* can dump */
|
||||
VDPA_CMD_DEV_CONFIG_GET, /* can dump */
|
||||
};
|
||||
|
||||
enum vdpa_attr {
|
||||
|
|
@ -32,6 +33,12 @@ enum vdpa_attr {
|
|||
VDPA_ATTR_DEV_VENDOR_ID, /* u32 */
|
||||
VDPA_ATTR_DEV_MAX_VQS, /* u32 */
|
||||
VDPA_ATTR_DEV_MAX_VQ_SIZE, /* u16 */
|
||||
VDPA_ATTR_DEV_MIN_VQ_SIZE, /* u16 */
|
||||
|
||||
VDPA_ATTR_DEV_NET_CFG_MACADDR, /* binary */
|
||||
VDPA_ATTR_DEV_NET_STATUS, /* u8 */
|
||||
VDPA_ATTR_DEV_NET_CFG_MAX_VQP, /* u16 */
|
||||
VDPA_ATTR_DEV_NET_CFG_MTU, /* u16 */
|
||||
|
||||
/* new attributes must be added above here */
|
||||
VDPA_ATTR_MAX,
|
||||
|
|
|
|||
|
|
@ -51,8 +51,34 @@
|
|||
#define VIRTIO_ID_PSTORE 22 /* virtio pstore device */
|
||||
#define VIRTIO_ID_IOMMU 23 /* virtio IOMMU */
|
||||
#define VIRTIO_ID_MEM 24 /* virtio mem */
|
||||
#define VIRTIO_ID_SOUND 25 /* virtio sound */
|
||||
#define VIRTIO_ID_FS 26 /* virtio filesystem */
|
||||
#define VIRTIO_ID_PMEM 27 /* virtio pmem */
|
||||
#define VIRTIO_ID_RPMB 28 /* virtio rpmb */
|
||||
#define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */
|
||||
#define VIRTIO_ID_VIDEO_ENCODER 30 /* virtio video encoder */
|
||||
#define VIRTIO_ID_VIDEO_DECODER 31 /* virtio video decoder */
|
||||
#define VIRTIO_ID_SCMI 32 /* virtio SCMI */
|
||||
#define VIRTIO_ID_NITRO_SEC_MOD 33 /* virtio nitro secure module*/
|
||||
#define VIRTIO_ID_I2C_ADAPTER 34 /* virtio i2c adapter */
|
||||
#define VIRTIO_ID_WATCHDOG 35 /* virtio watchdog */
|
||||
#define VIRTIO_ID_CAN 36 /* virtio can */
|
||||
#define VIRTIO_ID_DMABUF 37 /* virtio dmabuf */
|
||||
#define VIRTIO_ID_PARAM_SERV 38 /* virtio parameter server */
|
||||
#define VIRTIO_ID_AUDIO_POLICY 39 /* virtio audio policy */
|
||||
#define VIRTIO_ID_BT 40 /* virtio bluetooth */
|
||||
#define VIRTIO_ID_GPIO 41 /* virtio gpio */
|
||||
|
||||
/*
|
||||
* Virtio Transitional IDs
|
||||
*/
|
||||
|
||||
#define VIRTIO_TRANS_ID_NET 1000 /* transitional virtio net */
|
||||
#define VIRTIO_TRANS_ID_BLOCK 1001 /* transitional virtio block */
|
||||
#define VIRTIO_TRANS_ID_BALLOON 1002 /* transitional virtio balloon */
|
||||
#define VIRTIO_TRANS_ID_CONSOLE 1003 /* transitional virtio console */
|
||||
#define VIRTIO_TRANS_ID_SCSI 1004 /* transitional virtio SCSI */
|
||||
#define VIRTIO_TRANS_ID_RNG 1005 /* transitional virtio rng */
|
||||
#define VIRTIO_TRANS_ID_9P 1009 /* transitional virtio 9p console */
|
||||
|
||||
#endif /* _LINUX_VIRTIO_IDS_H */
|
||||
|
|
|
|||
Loading…
Reference in New Issue