Compare commits

..

No commits in common. "main" and "v5.15.0" have entirely different histories.

87 changed files with 976 additions and 3293 deletions

View File

@ -1,8 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
# Top level Makefile for iproute2
-include config.mk
ifeq ("$(origin V)", "command line")
VERBOSE = $(V)
endif
@ -15,6 +13,7 @@ MAKEFLAGS += --no-print-directory
endif
PREFIX?=/usr
LIBDIR?=$(PREFIX)/lib
SBINDIR?=/sbin
CONFDIR?=/etc/iproute2
NETNS_RUN_DIR?=/var/run/netns
@ -41,18 +40,9 @@ 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
@ -70,7 +60,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.mk
all: config
@set -e; \
for i in $(SUBDIRS); \
do echo; echo $$i; $(MAKE) -C $$i; done
@ -90,7 +80,7 @@ help:
@echo "Make Arguments:"
@echo " V=[0|1] - set build verbosity level"
config.mk:
config:
@if [ ! -f config.mk -o configure -nt config.mk ]; then \
sh configure $(KERNEL_INCLUDE); \
fi

View File

@ -12,9 +12,7 @@ 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,
bool global_only);
void br_print_router_port_stats(struct rtattr *pattr);
int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor);
int do_fdb(int argc, char **argv);
int do_mdb(int argc, char **argv);

View File

@ -59,7 +59,7 @@ static const char *format_timer(__u32 ticks, int align)
return tbuf;
}
void br_print_router_port_stats(struct rtattr *pattr)
static void __print_router_port_stats(FILE *f, 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)
br_print_router_port_stats(i);
__print_router_port_stats(f, i);
close_json_object();
} else if (show_stats) {
fprintf(f, "router ports on %s: %s",
brifname, port_ifname);
br_print_router_port_stats(i);
__print_router_port_stats(f, i);
fprintf(f, "\n");
} else {
fprintf(f, "%s ", port_ifname);

View File

@ -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, false);
return print_vlan_rtm(n, arg, true);
default:
return 0;

View File

@ -9,7 +9,6 @@
#include <linux/if_bridge.h>
#include <linux/if_ether.h>
#include <string.h>
#include <errno.h>
#include "json_print.h"
#include "libnetlink.h"
@ -36,23 +35,8 @@ 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 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");
" bridge vlan { tunnelshow } [ dev DEV ] [ vid VLAN_ID ]\n");
exit(-1);
}
@ -273,24 +257,16 @@ 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();
@ -308,22 +284,8 @@ static int vlan_option_set(int argc, char **argv)
} 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);
@ -333,197 +295,42 @@ static int vlan_option_set(int argc, char **argv)
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)
req.bvm.ifindex = ll_name_to_index(d);
if (req.bvm.ifindex == 0) {
fprintf(stderr, "Cannot find network device \"%s\"\n", d);
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);
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;
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;
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;
}
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 (strcmp(*argv, "help") == 0)
NEXT_ARG();
}
argc--; argv++;
}
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 (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;
@ -814,224 +621,11 @@ static int print_vlan_stats(struct nlmsghdr *n, void *arg)
return 0;
}
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)
int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor)
{
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 &&
@ -1066,21 +660,66 @@ int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor, bool global_only
rem = len;
for (a = BRVLAN_RTA(bvm); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) {
unsigned short rta_type = a->rta_type & NLA_TYPE_MASK;
struct bridge_vlan_xstats vstats;
struct bridge_vlan_info *vinfo;
__u32 vrange = 0;
__u8 state = 0;
/* skip unknown attributes */
if (rta_type > BRIDGE_VLANDB_MAX ||
(global_only && rta_type != BRIDGE_VLANDB_GLOBAL_OPTIONS))
continue;
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]);
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;
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);
}
}
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;
@ -1088,12 +727,7 @@ int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor, bool global_only
static int print_vlan_rtm_filter(struct nlmsghdr *n, void *arg)
{
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);
return print_vlan_rtm(n, arg, false);
}
static int vlan_show(int argc, char **argv, int subject)
@ -1211,61 +845,6 @@ 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;
@ -1310,24 +889,6 @@ 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);
@ -1346,8 +907,6 @@ 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 {

78
configure vendored
View File

@ -3,8 +3,6 @@
# 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
@ -150,15 +148,6 @@ 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
@ -496,14 +485,12 @@ usage()
{
cat <<EOF
Usage: $0 [OPTIONS]
--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
--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
EOF
exit $1
}
@ -512,56 +499,30 @@ EOF
if [ $# -eq 1 ] && [ "$(echo $1 | cut -c 1)" != '-' ]; then
INCLUDE="$1"
else
while [ "$#" -gt 0 ]; do
while true; do
case "$1" in
--include_dir)
shift
INCLUDE="$1" ;;
--include_dir=*)
INCLUDE="${1#*=}" ;;
--libdir)
shift
LIBDIR="$1" ;;
--libdir=*)
LIBDIR="${1#*=}" ;;
INCLUDE=$2
shift 2 ;;
--libbpf_dir)
shift
LIBBPF_DIR="$1" ;;
--libbpf_dir=*)
LIBBPF_DIR="${1#*=}" ;;
LIBBPF_DIR="$2"
shift 2 ;;
--libbpf_force)
shift
LIBBPF_FORCE="$1" ;;
--libbpf_force=*)
LIBBPF_FORCE="${1#*=}" ;;
--prefix)
shift
PREFIX="$1" ;;
--prefix=*)
PREFIX="${1#*=}" ;;
if [ "$2" != 'on' ] && [ "$2" != 'off' ]; then
usage 1
fi
LIBBPF_FORCE=$2
shift 2 ;;
-h | --help)
usage 0 ;;
--*)
;;
"")
break ;;
*)
usage 1 ;;
shift 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
@ -585,7 +546,6 @@ 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

View File

@ -3036,7 +3036,6 @@ 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;
@ -3089,7 +3088,6 @@ 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:
@ -3142,10 +3140,6 @@ 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);
@ -7851,10 +7845,6 @@ 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);
}

View File

@ -10,7 +10,7 @@ Where:
ACTION semantics
- pass and ok are equivalent to accept
- continue allows one to restart classification lookup
- continue allows to restart classification lookup
- drop drops packets
- reclassify implies continue classification where we left off

View File

@ -1,62 +0,0 @@
/* 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_ */

View File

@ -906,7 +906,6 @@ 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
@ -1275,13 +1274,6 @@ 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 */
@ -1637,7 +1629,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 migration disabled, which means that the
* all programs run with preemption disabled, which means that the
* SMP processor id is stable during all the execution of the
* program.
* Return
@ -4054,7 +4046,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 - must be a multiple of 8.
* The *data_len* is the size of *data* in bytes.
*
* Formats **%s**, **%p{i,I}{4,6}** requires to read kernel memory.
* Reading kernel memory may fail due to either invalid address or
@ -4759,8 +4751,7 @@ 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 - must be
* a multiple of 8.
* array. The *data_len* is the size of *data* in bytes.
*
* Formats **%s** and **%p{i,I}{4,6}** require to read kernel
* memory. Reading kernel memory may fail due to either invalid
@ -4886,58 +4877,6 @@ 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), \
@ -5116,10 +5055,6 @@ 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
@ -5349,8 +5284,6 @@ 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 {
@ -5644,7 +5577,6 @@ struct bpf_prog_info {
__u64 run_time_ns;
__u64 run_cnt;
__u64 recursion_misses;
__u32 verified_insns;
} __attribute__((aligned(8)));
struct bpf_map_info {
@ -5662,8 +5594,6 @@ 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 {

View File

@ -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, VAR and DECL_TAG.
* FUNC, FUNC_PROTO and VAR.
* "type" is a type_id referring to another type.
*/
union {
@ -56,29 +56,25 @@ struct btf_type {
#define BTF_INFO_VLEN(info) ((info) & 0xffff)
#define BTF_INFO_KFLAG(info) ((info) >> 31)
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,
};
#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)
/* For some specific BTF_KIND, "struct btf_type" is immediately
* followed by extra data.
@ -174,15 +170,4 @@ 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__ */

View File

@ -101,8 +101,6 @@ 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
@ -136,35 +134,10 @@ enum {
IFLA_CAN_BITRATE_CONST,
IFLA_CAN_DATA_BITRATE_CONST,
IFLA_CAN_BITRATE_MAX,
IFLA_CAN_TDC,
/* add new constants above here */
__IFLA_CAN_MAX,
IFLA_CAN_MAX = __IFLA_CAN_MAX - 1
__IFLA_CAN_MAX
};
/*
* 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
};
#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1)
/* u16 termination range: 1..65535 Ohms */
#define CAN_TERMINATION_DISABLED 0

View File

@ -551,8 +551,6 @@ 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,

View File

@ -86,7 +86,6 @@
* 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. */
@ -117,7 +116,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 more than this value
#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is less than this value
* then the frame is Ethernet II. Else it is 802.3 */
/*

View File

@ -9,38 +9,9 @@
#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,
};

View File

@ -169,7 +169,6 @@ 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
};

View File

@ -4,11 +4,6 @@
#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)
@ -198,32 +193,4 @@ 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 */

View File

@ -31,7 +31,6 @@ enum {
NDA_PROTOCOL, /* Originator of entry */
NDA_NH_ID,
NDA_FDB_EXT_ATTRS,
NDA_FLAGS_EXT,
__NDA_MAX
};
@ -41,16 +40,14 @@ enum {
* Neighbor Cache Entry Flags
*/
#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)
#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
/*
* Neighbor Cache Entry States.
@ -68,22 +65,12 @@ 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. 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).
*
/* 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.
* 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 {

View File

@ -49,7 +49,6 @@ enum nf_inet_hooks {
enum nf_dev_hooks {
NF_NETDEV_INGRESS,
NF_NETDEV_EGRESS,
NF_NETDEV_NUMHOOKS
};

View File

@ -840,8 +840,6 @@ 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
};

View File

@ -4,40 +4,3 @@
#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[]; \
}

View File

@ -84,20 +84,6 @@
#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
@ -138,22 +124,6 @@ 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,

40
include/uapi/linux/vdpa.h Normal file
View File

@ -0,0 +1,40 @@
/* 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

View File

@ -198,15 +198,9 @@ 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);

View File

@ -11,15 +11,14 @@ 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 \
iplink_amt.o
ipnexthop.o ipmptcp.o iplink_bareudp.o iplink_wwan.o ipioam6.o
RTMONOBJ=rtmon.o
include ../config.mk
ALLOBJ=$(IPOBJ) $(RTMONOBJ)
SCRIPTS=routel
SCRIPTS=ifcfg rtpr routel routef
TARGETS=ip rtmon
all: $(TARGETS) $(SCRIPTS)

150
ip/ifcfg Executable file
View File

@ -0,0 +1,150 @@
#! /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

View File

@ -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 | amt | fou | help | ila | ioam | l2tp |\n"
" link | macsec | maddress | monitor | mptcp | mroute | mrule |\n"
"where OBJECT := { address | addrlabel | fou | help | ila | ioam | l2tp | link |\n"
" 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"

View File

@ -53,6 +53,7 @@ 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);
@ -167,8 +168,7 @@ 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_ifidx(FILE *fp, __u32 ifidx, const char *prefix);
void __print_rta_gateway(FILE *fp, unsigned char family, const char *gateway);
void print_rta_if(FILE *fp, const struct rtattr *rta, const char *prefix);
void print_rta_gateway(FILE *fp, unsigned char family,
const struct rtattr *rta);
#endif /* _IP_COMMON_H_ */

View File

@ -60,7 +60,6 @@ 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"
@ -2124,8 +2123,6 @@ 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;

View File

@ -50,7 +50,7 @@ void iplink_types_usage(void)
{
/* Remember to add new entry here if new type is added. */
fprintf(stderr,
"TYPE := { amt | bareudp | bond | bond_slave | bridge | bridge_slave |\n"
"TYPE := { 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,7 +120,6 @@ 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"
@ -579,7 +578,6 @@ 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;
@ -685,7 +683,6 @@ 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;
@ -983,11 +980,9 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type)
}
}
if (index &&
(!(req->n.nlmsg_flags & NLM_F_CREATE) &&
!move_netns)) {
if (!(req->n.nlmsg_flags & NLM_F_CREATE) && index) {
fprintf(stderr,
"index can be used only when creating devices or when moving device to another netns.\n");
"index can be used only when creating devices.\n");
exit(-1);
}
@ -1024,9 +1019,6 @@ 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,

View File

@ -1,200 +0,0 @@
/*
* 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,
};

View File

@ -43,7 +43,6 @@ 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"
@ -84,7 +83,6 @@ 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) {
@ -202,18 +200,6 @@ 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;
@ -393,9 +379,6 @@ 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;
}
@ -576,18 +559,6 @@ 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",

View File

@ -28,7 +28,6 @@ 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"
@ -39,24 +38,20 @@ 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 := { NUMBER in bps }\n"
"\tWhere: BITRATE := { 1..1000000 }\n"
"\t SAMPLE-POINT := { 0.000..0.999 }\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"
"\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"
);
}
@ -93,47 +88,34 @@ static void set_ctrlmode(char *name, char *arg,
cm->mask |= flags;
}
static void print_flag(enum output_type t, __u32 *flags, __u32 flag,
const char* name)
static void print_ctrlmode(FILE *f, __u32 cm)
{
if (*flags & flag) {
*flags &= ~flag;
print_string(t, NULL, *flags ? "%s," : "%s", 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); \
}
}
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, "> ");
_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 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 };
struct rtattr *tdc;
__u32 tdcv = -1, tdco = -1, tdcf = -1;
struct can_ctrlmode cm = {0, 0};
while (argc > 0) {
if (matches(*argv, "bitrate") == 0) {
@ -199,18 +181,6 @@ 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,
@ -247,23 +217,6 @@ 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;
@ -301,17 +254,6 @@ 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;
}
@ -324,75 +266,11 @@ static const char *can_state_names[CAN_STATE_MAX] = {
[CAN_STATE_SLEEPING] = "SLEEPING"
};
static void can_print_nl_indent(void)
static void can_print_json_timing_min_max(const char *attr, int min, int 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);
}
open_json_object(attr);
print_int(PRINT_JSON, "min", NULL, min);
print_int(PRINT_JSON, "max", NULL, max);
close_json_object();
}
@ -404,7 +282,8 @@ 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]);
print_ctrlmode(PRINT_ANY, cm->flags, "ctrlmode");
if (cm->flags)
print_ctrlmode(f, cm->flags);
}
if (tb[IFLA_CAN_STATE]) {
@ -418,39 +297,56 @@ 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]);
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 (is_json_context()) {
open_json_object("berr_counter");
print_int(PRINT_JSON, "tx", NULL, bc->txerr);
print_int(PRINT_JSON, "rx", NULL, bc->rxerr);
close_json_object();
} else {
fprintf(f, "(berr-counter tx %d rx %d) ",
bc->txerr, bc->rxerr);
}
}
if (tb[IFLA_CAN_RESTART_MS]) {
__u32 *restart_ms = RTA_DATA(tb[IFLA_CAN_RESTART_MS]);
print_uint(PRINT_ANY, "restart_ms", "restart-ms %u ",
*restart_ms);
print_int(PRINT_ANY,
"restart_ms",
"restart-ms %d ",
*restart_ms);
}
/* bittiming is irrelevant if fixed bitrate is defined */
if (tb[IFLA_CAN_BITTIMING] && !tb[IFLA_CAN_BITRATE_CONST]) {
struct can_bittiming *bt = RTA_DATA(tb[IFLA_CAN_BITTIMING]);
char sp[6];
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();
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);
}
}
/* bittiming const is irrelevant if fixed bitrate is defined */
@ -458,18 +354,28 @@ 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]);
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 (is_json_context()) {
open_json_object("bittiming_const");
print_string(PRINT_JSON, "name", NULL, btc->name);
can_print_json_timing_min_max("tseg1",
btc->tseg1_min,
btc->tseg1_max);
can_print_json_timing_min_max("tseg2",
btc->tseg2_min,
btc->tseg2_max);
can_print_json_timing_min_max("sjw", 1, btc->sjw_max);
can_print_json_timing_min_max("brp",
btc->brp_min,
btc->brp_max);
print_int(PRINT_JSON, "brp_inc", NULL, btc->brp_inc);
close_json_object();
} else {
fprintf(f, "\n %s: tseg1 %d..%d tseg2 %d..%d "
"sjw 1..%d brp %d..%d brp-inc %d",
btc->name, btc->tseg1_min, btc->tseg1_max,
btc->tseg2_min, btc->tseg2_max, btc->sjw_max,
btc->brp_min, btc->brp_max, btc->brp_inc);
}
}
if (tb[IFLA_CAN_BITRATE_CONST]) {
@ -485,52 +391,64 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
bitrate = bt->bitrate;
}
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 (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]);
}
print_uint(PRINT_ANY, NULL,
i < bitrate_cnt - 1 ? "%8u, " : "%8u",
bitrate_const[i]);
if (!(i % 6) && i)
fprintf(f, "\n ");
fprintf(f, "%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];
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);
if (is_json_context()) {
json_writer_t *jw;
if (tb[IFLA_CAN_TDC])
can_print_tdc_opt(f, tb[IFLA_CAN_TDC]);
close_json_object();
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);
}
}
/* data bittiming const is irrelevant if fixed bitrate is defined */
@ -539,22 +457,29 @@ 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]);
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);
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);
if (tb[IFLA_CAN_TDC])
can_print_tdc_const_opt(f, tb[IFLA_CAN_TDC]);
close_json_object();
print_int(PRINT_JSON, "brp_inc", NULL, dbtc->brp_inc);
close_json_object();
} else {
fprintf(f, "\n %s: dtseg1 %d..%d dtseg2 %d..%d "
"dsjw 1..%d dbrp %d..%d dbrp-inc %d",
dbtc->name, dbtc->tseg1_min, dbtc->tseg1_max,
dbtc->tseg2_min, dbtc->tseg2_max, dbtc->sjw_max,
dbtc->brp_min, dbtc->brp_max, dbtc->brp_inc);
}
}
if (tb[IFLA_CAN_DATA_BITRATE_CONST]) {
@ -572,23 +497,30 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
dbitrate = dbt->bitrate;
}
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 (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]);
}
print_uint(PRINT_ANY, NULL,
i < dbitrate_cnt - 1 ? "%8u, " : "%8u",
dbitrate_const[i]);
if (!(i % 6) && i)
fprintf(f, "\n ");
fprintf(f, "%8u ]", dbitrate_const[i]);
}
close_json_array(PRINT_JSON, " ]");
}
if (tb[IFLA_CAN_TERMINATION_CONST] && tb[IFLA_CAN_TERMINATION]) {
@ -598,21 +530,29 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
sizeof(*trm_const);
int 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 (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]);
}
}
if (tb[IFLA_CAN_CLOCK]) {
struct can_clock *clock = RTA_DATA(tb[IFLA_CAN_CLOCK]);
can_print_nl_indent();
print_uint(PRINT_ANY, "clock", " clock %u ", clock->freq);
print_int(PRINT_ANY,
"clock",
"\n clock %d ",
clock->freq);
}
}
@ -625,23 +565,31 @@ static void can_print_xstats(struct link_util *lu,
if (xstats && RTA_PAYLOAD(xstats) == sizeof(*stats)) {
stats = RTA_DATA(xstats);
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);
if (is_json_context()) {
print_int(PRINT_JSON, "restarts",
NULL, stats->restarts);
print_int(PRINT_JSON, "bus_error",
NULL, stats->bus_error);
print_int(PRINT_JSON, "arbitration_lost",
NULL, stats->arbitration_lost);
print_int(PRINT_JSON, "error_warning",
NULL, stats->error_warning);
print_int(PRINT_JSON, "error_passive",
NULL, stats->error_passive);
print_int(PRINT_JSON, "bus_off", NULL, stats->bus_off);
} else {
fprintf(f, "\n re-started bus-errors arbit-lost "
"error-warn error-pass bus-off");
fprintf(f, "\n %-10d %-10d %-10d %-10d %-10d %-10d",
stats->restarts, stats->bus_error,
stats->arbitration_lost, stats->error_warning,
stats->error_passive, stats->bus_off);
}
}
}
static void can_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
static void can_print_help(struct link_util *lu, int argc, char **argv,
FILE *f)
{
print_usage(f);
}

View File

@ -22,7 +22,6 @@
#include "utils.h"
#include "ip_common.h"
#include "nh_common.h"
static void usage(void) __attribute__((noreturn));
static int prefix_banner;
@ -89,7 +88,7 @@ static int accept_msg(struct rtnl_ctrl_data *ctrl,
case RTM_NEWNEXTHOP:
case RTM_DELNEXTHOP:
print_headers(fp, "[NEXTHOP]", ctrl);
print_cache_nexthop(n, arg, true);
print_nexthop(n, arg);
return 0;
case RTM_NEWNEXTHOPBUCKET:

View File

@ -1,23 +1,17 @@
// 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 "json_print.h"
#include "libgenl.h"
#include "libnetlink.h"
#include "ll_map.h"
#include "json_print.h"
static void usage(void)
{
@ -305,11 +299,7 @@ static int mptcp_addr_show(int argc, char **argv)
if (rtnl_talk(&genl_rth, &req.n, &answer) < 0)
return -2;
new_json_obj(json);
ret = print_mptcp_addr(answer, stdout);
delete_json_obj();
fflush(stdout);
return ret;
return print_mptcp_addr(answer, stdout);
}
static int mptcp_addr_flush(int argc, char **argv)

View File

@ -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 ] [ use ] [ managed ] [ extern_learn ]\n"
" [ protocol PROTO ]\n"
" [ dev DEV ] [ router ] [ extern_learn ] [ protocol PROTO ]\n"
"\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"
" 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"
"\n"
"STATE := { delay | failed | incomplete | noarp | none |\n"
" permanent | probe | reachable | stale }\n");
@ -116,7 +116,6 @@ 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;
@ -150,11 +149,6 @@ 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) {
@ -190,10 +184,7 @@ 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;
@ -245,7 +236,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);
@ -313,7 +304,6 @@ 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 &&
@ -357,8 +347,6 @@ 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;
@ -436,26 +424,27 @@ 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");
if (ext_flags & NTF_EXT_MANAGED)
print_null(PRINT_ANY, "managed", "%s ", "managed");
print_null(PRINT_ANY, "proxy", " %s", "proxy");
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]));
}
@ -465,7 +454,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)));
}
@ -547,8 +536,6 @@ 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) {

View File

@ -6,7 +6,6 @@
*/
#include <linux/nexthop.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <rt_names.h>
@ -14,7 +13,6 @@
#include "utils.h"
#include "ip_common.h"
#include "nh_common.h"
static struct {
unsigned int flushed;
@ -35,9 +33,6 @@ 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)
@ -217,29 +212,28 @@ out:
return rc;
}
static bool __valid_nh_group_attr(const struct rtattr *g_attr)
{
int num = RTA_PAYLOAD(g_attr) / sizeof(struct nexthop_grp);
return num && num * sizeof(struct nexthop_grp) == RTA_PAYLOAD(g_attr);
}
static void print_nh_group(const struct nh_entry *nhe)
static void print_nh_group(FILE *fp, const struct rtattr *grps_attr)
{
struct nexthop_grp *nhg = RTA_DATA(grps_attr);
int num = RTA_PAYLOAD(grps_attr) / sizeof(*nhg);
int i;
if (!num || num * sizeof(*nhg) != RTA_PAYLOAD(grps_attr)) {
fprintf(fp, "<invalid nexthop group>");
return;
}
open_json_array(PRINT_JSON, "group");
print_string(PRINT_FP, NULL, "%s", "group ");
for (i = 0; i < nhe->nh_groups_cnt; ++i) {
for (i = 0; i < num; ++i) {
open_json_object(NULL);
if (i)
print_string(PRINT_FP, NULL, "%s", "/");
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);
print_uint(PRINT_ANY, "id", "%u", nhg[i].id);
if (nhg[i].weight)
print_uint(PRINT_ANY, "weight", ",%u", nhg[i].weight + 1);
close_json_object();
}
@ -259,59 +253,50 @@ static const char *nh_group_type_name(__u16 type)
}
}
static void print_nh_group_type(__u16 nh_grp_type)
static void print_nh_group_type(FILE *fp, const struct rtattr *grp_type_attr)
{
if (nh_grp_type == NEXTHOP_GRP_TYPE_MPATH)
__u16 type = rta_getattr_u16(grp_type_attr);
if (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(nh_grp_type));
print_string(PRINT_ANY, "type", "type %s ", nh_group_type_name(type));
}
static void parse_nh_res_group_rta(const struct rtattr *res_grp_attr,
struct nha_res_grp *res_grp)
static void print_nh_res_group(FILE *fp, const struct rtattr *res_grp_attr)
{
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])
res_grp->buckets = rta_getattr_u16(tb[NHA_RES_GROUP_BUCKETS]);
print_uint(PRINT_ANY, "buckets", "buckets %u ",
rta_getattr_u16(tb[NHA_RES_GROUP_BUCKETS]));
if (tb[NHA_RES_GROUP_IDLE_TIMER]) {
rta = tb[NHA_RES_GROUP_IDLE_TIMER];
res_grp->idle_timer = rta_getattr_u32(rta);
__jiffies_to_tv(&tv, rta_getattr_u32(rta));
print_tv(PRINT_ANY, "idle_timer", "idle_timer %g ", &tv);
}
if (tb[NHA_RES_GROUP_UNBALANCED_TIMER]) {
rta = tb[NHA_RES_GROUP_UNBALANCED_TIMER];
res_grp->unbalanced_timer = rta_getattr_u32(rta);
__jiffies_to_tv(&tv, rta_getattr_u32(rta));
print_tv(PRINT_ANY, "unbalanced_timer", "unbalanced_timer %g ",
&tv);
}
if (tb[NHA_RES_GROUP_UNBALANCED_TIME]) {
rta = tb[NHA_RES_GROUP_UNBALANCED_TIME];
res_grp->unbalanced_time = rta_getattr_u64(rta);
__jiffies_to_tv(&tv, rta_getattr_u32(rta));
print_tv(PRINT_ANY, "unbalanced_time", "unbalanced_time %g ",
&tv);
}
}
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();
}
@ -343,325 +328,14 @@ static void print_nh_res_bucket(FILE *fp, const struct rtattr *res_bucket_attr)
close_json_object();
}
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)
int print_nexthop(struct nlmsghdr *n, void *arg)
{
struct nhmsg *nhm = NLMSG_DATA(n);
struct rtattr *tb[NHA_MAX+1];
FILE *fp = (FILE *)arg;
struct nh_entry nhe;
int len, err;
int len;
SPRINT_BUF(b1);
if (n->nlmsg_type != RTM_DELNEXTHOP &&
n->nlmsg_type != RTM_NEWNEXTHOP) {
@ -680,29 +354,60 @@ int print_cache_nexthop(struct nlmsghdr *n, void *arg, bool process_cache)
if (filter.proto && filter.proto != nhm->nh_protocol)
return 0;
err = ipnh_parse_nhmsg(fp, nhm, len, &nhe);
if (err) {
close_json_object();
fprintf(stderr, "Error parsing nexthop: %s\n", strerror(-err));
return -1;
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)));
}
__print_nexthop_entry(fp, NULL, &nhe, n->nlmsg_type == RTM_DELNEXTHOP);
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_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);
@ -841,7 +546,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 >= UINT32_MAX / 100)
idle_timer >= ~0UL / 100)
invarg("invalid idle timer value", *argv);
addattr32(n, maxlen, NHA_RES_GROUP_IDLE_TIMER,
@ -851,7 +556,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 >= UINT32_MAX / 100)
unbalanced_timer >= ~0UL / 100)
invarg("invalid unbalanced timer value", *argv);
addattr32(n, maxlen, NHA_RES_GROUP_UNBALANCED_TIMER,
@ -1007,14 +712,26 @@ 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;
if (__ipnh_get_id(&rth, id, &answer) < 0)
addattr32(&req.n, sizeof(req), NHA_ID, id);
if (rtnl_talk(&rth, &req.n, &answer) < 0)
return -2;
new_json_obj(json);
if (print_nexthop_nocache(answer, (void *)stdout) < 0) {
if (print_nexthop(answer, (void *)stdout) < 0) {
free(answer);
return -1;
}
@ -1099,7 +816,7 @@ static int ipnh_list_flush(int argc, char **argv, int action)
new_json_obj(json);
if (rtnl_dump_filter(&rth, print_nexthop_nocache, stdout) < 0) {
if (rtnl_dump_filter(&rth, print_nexthop, stdout) < 0) {
fprintf(stderr, "Dump terminated\n");
return -2;
}

View File

@ -28,7 +28,6 @@
#include "rt_names.h"
#include "utils.h"
#include "ip_common.h"
#include "nh_common.h"
#ifndef RTAX_RTTVAR
#define RTAX_RTTVAR RTAX_HOPS
@ -411,13 +410,13 @@ static void print_rt_pref(FILE *fp, unsigned int pref)
}
}
void print_rta_ifidx(FILE *fp, __u32 ifidx, const char *prefix)
void print_rta_if(FILE *fp, const struct rtattr *rta, const char *prefix)
{
const char *ifname = ll_index_to_name(ifidx);
const char *ifname = ll_index_to_name(rta_getattr_u32(rta));
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);
}
@ -548,11 +547,13 @@ static void print_rta_newdst(FILE *fp, const struct rtmsg *r,
}
}
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)
{
if (is_json_context()) {
const char *gateway = format_host_rta(family, rta);
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),
@ -560,13 +561,6 @@ 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)
{
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;
@ -868,7 +862,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_ifidx(fp, rta_getattr_u32(tb[RTA_OIF]), "dev");
print_rta_if(fp, tb[RTA_OIF], "dev");
if (table && (table != RT_TABLE_MAIN || show_details > 0) && !filter.tb)
print_string(PRINT_ANY,
@ -952,7 +946,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_ifidx(fp, rta_getattr_u32(tb[RTA_IIF]), "iif");
print_rta_if(fp, tb[RTA_IIF], "iif");
if (tb[RTA_PREF])
print_rt_pref(fp, rta_getattr_u8(tb[RTA_PREF]));
@ -969,10 +963,6 @@ 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]);

View File

@ -210,54 +210,16 @@ 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_MODE] || !tb[IOAM6_IPTUNNEL_TRACE])
if (!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);
@ -922,48 +884,23 @@ 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;
__u32 trace_type = 0;
inet_prefix addr;
__u8 mode;
int argc = *argcp;
int ns_found = 0;
__u16 size = 0;
__u32 type = 0;
__u16 ns;
if (strcmp(*argv, "mode") != 0) {
mode = IOAM6_IPTUNNEL_MODE_INLINE;
} else {
NEXT_ARG();
trace = calloc(1, sizeof(*trace));
if (!trace)
return -1;
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)
if (strcmp(*argv, "trace"))
missarg("trace");
NEXT_ARG();
if (strcmp(*argv, "prealloc") != 0)
if (strcmp(*argv, "prealloc"))
missarg("prealloc");
while (NEXT_ARG_OK()) {
@ -972,58 +909,63 @@ static int parse_encap_ioam6(struct rtattr *rta, size_t len, int *argcp,
if (strcmp(*argv, "type") == 0) {
NEXT_ARG();
if (trace_type)
if (type)
duparg2("type", *argv);
if (get_u32(&trace_type, *argv, 0) || !trace_type)
invarg("Invalid trace type", *argv);
if (get_u32(&type, *argv, 0) || !type)
invarg("Invalid type", *argv);
trace->type_be32 = htonl(type << 8);
} else if (strcmp(*argv, "ns") == 0) {
NEXT_ARG();
if (ns_found++)
duparg2("ns", *argv);
if (get_u16(&trace_ns, *argv, 0))
if (!type)
missarg("type");
if (get_u16(&ns, *argv, 0))
invarg("Invalid namespace ID", *argv);
trace->namespace_id = htons(ns);
} else if (strcmp(*argv, "size") == 0) {
NEXT_ARG();
if (trace_size)
if (size)
duparg2("size", *argv);
if (get_u16(&trace_size, *argv, 0) || !trace_size)
invarg("Invalid trace size", *argv);
if (!type)
missarg("type");
if (!ns_found)
missarg("ns");
if (trace_size % 4)
invarg("Trace size must be a 4-octet multiple",
*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 > IOAM6_TRACE_DATA_SIZE_MAX)
invarg("Trace size is too big", *argv);
} else {
break;
}
}
if (!trace_type)
if (!type)
missarg("type");
if (!ns_found)
missarg("ns");
if (!trace_size)
if (!size)
missarg("size");
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))) {
if (rta_addattr_l(rta, len, IOAM6_IPTUNNEL_TRACE, trace,
sizeof(*trace))) {
free(trace);
return -1;
}

View File

@ -1,53 +0,0 @@
/* 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 Executable file
View File

@ -0,0 +1,10 @@
#! /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
View File

@ -1,62 +1,72 @@
#! /usr/bin/env python3
#!/bin/sh
# 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."""
import sys
import json
import getopt
import subprocess
test "X-h" = "X$1" && echo "Usage: $0 [tablenr [raw ip args...]]" && exit 64
test -z "$*" && set 0
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()
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);
}
'

5
ip/rtpr Executable file
View File

@ -0,0 +1,5 @@
#! /bin/sh
# SPDX-License-Identifier: GPL-2.0
exec tr "[\\\\]" "[
]"

View File

@ -132,7 +132,6 @@ 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);

View File

@ -323,9 +323,6 @@ 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;
}

View File

@ -66,8 +66,6 @@ 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"
@ -1126,133 +1124,6 @@ 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;
@ -1326,10 +1197,6 @@ 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);

View File

@ -1,82 +0,0 @@
/* 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;
}

View File

@ -203,30 +203,12 @@ 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;
}

View File

@ -39,12 +39,6 @@ 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)

View File

@ -1,23 +0,0 @@
/* 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;
}

View File

@ -1,56 +0,0 @@
/* 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;
}

View File

@ -145,53 +145,13 @@ bridge \- show / manipulate bridge addresses and devices
.B vid
.IR VID " [ "
.B state
.IR STP_STATE " ] [ "
.B mcast_router
.IR MULTICAST_ROUTER " ]"
.IR STP_STATE " ] "
.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 " ]"
@ -917,31 +877,6 @@ 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.
@ -960,98 +895,6 @@ 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

View File

@ -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 omitted in output, as well as parent
rate values means "unlimited" rates and ommited in output, as well as parent
node name.
.SS devlink port function rate set - set rate object parameters.

48
man/man8/ifcfg.8 Normal file
View File

@ -0,0 +1,48 @@
.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

View File

@ -49,8 +49,7 @@ ip-address \- protocol address management
.IR TYPE " ] [ "
.B vrf
.IR NAME " ] [ "
.BR up " ] ["
.BR nomaster " ] ]"
.BR up " ] ]"
.ti -8
.BR "ip address" " { " showdump " | " restore " }"
@ -341,10 +340,6 @@ 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

View File

@ -179,8 +179,7 @@ ip-link \- network device configuration
.B type
.IR ETYPE " ] ["
.B vrf
.IR NAME " ] ["
.BR nomaster " ]"
.IR NAME " ]"
.ti -8
.B ip link xstats
@ -198,7 +197,6 @@ ip-link \- network device configuration
.ti -8
.IR TYPE " := [ "
.BR amt " | "
.BR bridge " | "
.BR bond " | "
.BR can " | "
@ -365,9 +363,6 @@ 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
@ -462,7 +457,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 one to accelerate tagging on egress and to hide VLAN header on
allows 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.
@ -691,7 +686,7 @@ or the internal FDB should be used.
- enables the Group Policy extension (VXLAN-GBP).
.in +4
Allows one to transport group policy context across VXLAN network peers.
Allows 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.
@ -1348,48 +1343,6 @@ 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
@ -1539,8 +1492,6 @@ 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 "
@ -1663,12 +1614,6 @@ 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
@ -2093,7 +2038,7 @@ flag in the output of the
To change network namespace for wireless devices the
.B iw
tool can be used. But it allows one to change network namespace only for
tool can be used. But it allows to change network namespace only for
physical devices and by process
.IR PID .
@ -2583,10 +2528,6 @@ 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

View File

@ -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 " } ] ["

View File

@ -25,8 +25,6 @@ ip-neighbour \- neighbour/arp tables management.
.B dev
.IR DEV " ] [ "
.BR router " ] [ "
.BR use " ] [ "
.BR managed " ] [ "
.BR extern_learn " ]"
.ti -8
@ -37,8 +35,7 @@ ip-neighbour \- neighbour/arp tables management.
.B nud
.IR STATE " ] [ "
.B vrf
.IR NAME " ] ["
.BR nomaster " ]"
.IR NAME " ] "
.ti -8
.B ip neigh get
@ -94,21 +91,6 @@ 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
@ -209,10 +191,6 @@ 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.

View File

@ -246,17 +246,13 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]"
.ti -8
.IR ENCAP_IOAM6 " := "
.B ioam6
.BR mode " [ "
.BR inline " | " encap " | " auto " ] ["
.B tundst
.IR ADDRESS " ] "
.B trace
.B prealloc
.B type
.BR trace
.BR prealloc
.BR type
.IR IOAM6_TRACE_TYPE
.B ns
.BR ns
.IR IOAM6_NAMESPACE
.B size
.BR size
.IR IOAM6_TRACE_SIZE
.ti -8
@ -919,35 +915,14 @@ 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
@ -1274,9 +1249,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 mode encap tundst 2001:db8:42::1 trace prealloc type 0x800000 ns 1 size 12 dev eth0
ip -6 route add 2001:db8:1::/64 encap ioam6 trace prealloc type 0x800000 ns 1 size 12 dev eth0
.RS 4
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.
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.
.RE
.PP
ip route add 10.1.1.0/30 nhid 10

View File

@ -298,18 +298,6 @@ 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

View File

@ -58,28 +58,6 @@ 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 " }"
@ -122,17 +100,6 @@ 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
@ -219,26 +186,6 @@ 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),
@ -251,5 +198,3 @@ Disable all the optional counters on device mlx5_2 port 1.
Mark Zhang <markz@mellanox.com>
.br
Erez Alfasi <ereza@mellanox.com>
.br
Neta Ostrovsky <netao@nvidia.com>

1
man/man8/routef.8 Normal file
View File

@ -0,0 +1 @@
.so man8/routel.8

View File

@ -1,31 +1,25 @@
.TH ROUTEL 8 "1 Sept, 2021" "iproute2" "Linux"
.TH "ROUTEL" "8" "3 Jan, 2008" "iproute2" "Linux"
.SH "NAME"
.LP
routel \- list routes with pretty output format
.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 }
.br
routef \- flush routes
.SH "SYNTAX"
.LP
routel [\fItablenr\fP [\fIraw ip args...\fP]]
.br
routef
.SH "DESCRIPTION"
.LP
The routel script will list routes in a format that some might consider
easier to interpret then the
.B ip
route list equivalent.
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!
.SH "AUTHORS"
.LP
Rewritten by Stephen Hemminger <stephen@networkplumber.org>.
.br
Original script by Stephen R. van den Berg <srb@cuci.nl>.
The routel script was written by Stephen R. van den Berg <srb@cuci.nl>, 1999/04/18 and donated to the public domain.
.br
This manual page was written by Andreas Henriksson <andreas@fatal.se>, for the Debian GNU/Linux system.
.SH "SEE ALSO"

25
man/man8/rtpr.8 Normal file
View File

@ -0,0 +1,25 @@
.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>

View File

@ -409,7 +409,7 @@ Please take a look at the official documentation for details regarding filters.
.SH STATE-FILTER
.B STATE-FILTER
allows one to construct arbitrary set of states to match. Its syntax is
allows to construct arbitrary set of states to match. Its syntax is
sequence of keywords state and exclude followed by identifier of
state.
.TP

View File

@ -14,7 +14,7 @@ basic \- basic traffic control filter
.SH DESCRIPTION
The
.B basic
filter allows one to classify packets using the extended match infrastructure.
filter allows to classify packets using the extended match infrastructure.
.SH OPTIONS
.TP
.BI action " ACTION_SPEC"

View File

@ -12,13 +12,13 @@ fw \- fwmark traffic control filter
.SH DESCRIPTION
the
.B fw
filter allows one to classify packets based on a previously set
filter allows 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 one to mark single packets with the
allows to mark single packets with the
.B MARK
target, or whole connections using
.BR CONNMARK .

View File

@ -15,7 +15,7 @@ matchall \- traffic control filter that matches every packet
.SH DESCRIPTION
The
.B matchall
filter allows one to classify every packet that flows on the port and run a
filter allows to classify every packet that flows on the port and run a
action on it.
.SH OPTIONS
.TP

View File

@ -25,7 +25,7 @@ nat - stateless native address translation action
.SH DESCRIPTION
The
.B nat
action allows one to perform NAT without the overhead of conntrack, which is
action allows 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

View File

@ -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 one to introduce a delay variation and a correlation.
optional parameters allows 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 one to
alone corresponds to the Bernoulli model. The optional parameters allows 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.

View File

@ -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 one to have a variable
which allows 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 one to change data past the actual IP header itself. It assumes
Again, this allows 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 one to exclude bits from being changed. Supported only for 32 bits fields
allows to exclude bits from being changed. Supported only for 32 bits fields
or smaller.
.TP
.I CONTROL

View File

@ -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 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
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
integer greater than zero.
.SH EXAMPLES
Sample one of every 100 packets flowing into interface eth0 to psample group 12:

View File

@ -16,9 +16,9 @@ skbedit - SKB editing action
.SH DESCRIPTION
The
.B skbedit
action allows one to change a packet's associated meta data. It complements the
action allows to change a packet's associated meta data. It complements the
.B pedit
action, which in turn allows one to change parts of the packet data itself.
action, which in turn allows to change parts of the packet data itself.
The most unique feature of
.B skbedit

View File

@ -16,7 +16,7 @@ tcindex \- traffic control index filter
.B action
.BR ACTION_SPEC " ]"
.SH DESCRIPTION
This filter allows one to match packets based on their
This filter allows 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.

View File

@ -23,7 +23,7 @@ tunnel_key - Tunnel metadata manipulation
.SH DESCRIPTION
The
.B tunnel_key
action combined with a shared IP tunnel device, allows one to perform IP tunnel en-
action combined with a shared IP tunnel device, allows to perform IP tunnel en-
or decapsulation on a packet, reflected by
the operation modes
.IR UNSET " and " SET .

View File

@ -150,7 +150,7 @@ u32 \- universal 32bit traffic control filter
.BR at " [ " nexthdr+ " ] "
.IR int_value " ]"
.SH DESCRIPTION
The Universal/Ugly 32bit filter allows one to match arbitrary bitfields in the
The Universal/Ugly 32bit filter allows 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 one to match various header fields:
then allows 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 of a fragmented packet
the first fragment
.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 u16 0 1fff at 6 \\
match ip firstfrag \\
offset at 0 mask 0f00 shift 6 \\
link 1:
.EE

View File

@ -35,7 +35,7 @@ vlan - vlan manipulation module
.SH DESCRIPTION
The
.B vlan
action allows one to perform 802.1Q en- or decapsulation on a packet, reflected by
action allows to perform 802.1Q en- or decapsulation on a packet, reflected by
the operation modes
.IR POP ", " PUSH " and " MODIFY .
The

View File

@ -10,7 +10,7 @@ xt - tc iptables action
.SH DESCRIPTION
The
.B xt
action allows one to call arbitrary iptables targets for packets matching the filter
action allows to call arbitrary iptables targets for packets matching the filter
this action is attached to.
.SH OPTIONS
.TP

View File

@ -210,9 +210,8 @@ 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] = ' ';

View File

@ -457,17 +457,6 @@ 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;
@ -596,6 +585,20 @@ 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;

View File

@ -297,8 +297,6 @@ enum rdma_nldev_command {
RDMA_NLDEV_CMD_RES_SRQ_GET, /* can dump */
RDMA_NLDEV_CMD_STAT_GET_STATUS,
RDMA_NLDEV_NUM_OPS
};
@ -551,9 +549,6 @@ 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
*/

View File

@ -164,8 +164,6 @@ 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 {
@ -177,8 +175,6 @@ 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 {
@ -210,16 +206,10 @@ 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 {
@ -232,14 +222,12 @@ 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 reason;
__u8 reserved[2];
__u8 reserved[3];
__u8 private_data[RDMA_MAX_PRIVATE_DATA];
};
@ -299,7 +287,6 @@ struct rdma_ucm_event_resp {
struct rdma_ucm_ud_param ud;
} param;
__u32 reserved;
struct rdma_ucm_ece ece;
};
/* Option levels */

View File

@ -20,10 +20,6 @@ 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");
@ -41,12 +37,6 @@ 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;
}
@ -503,30 +493,6 @@ 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;
@ -749,310 +715,6 @@ 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] = {};
@ -1124,9 +786,6 @@ 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 }
};

View File

@ -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;
char out[128];
SPRINT_BUF(out);
char *p;
if (!attr)

View File

@ -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);

View File

@ -17,7 +17,6 @@ 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 {
@ -33,12 +32,6 @@ 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,

View File

@ -51,34 +51,8 @@
#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 */