Merge branch 'main' into next

Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
David Ahern 2020-07-14 23:52:43 +00:00
commit b78c480532
26 changed files with 714 additions and 149 deletions

View File

@ -678,7 +678,7 @@ _devlink_trap_set_action()
COMPREPLY=( $( compgen -W "action" -- "$cur" ) )
;;
$((7 + $i)))
COMPREPLY=( $( compgen -W "trap drop" -- "$cur" ) )
COMPREPLY=( $( compgen -W "trap drop mirror" -- "$cur" ) )
;;
esac
}
@ -708,7 +708,7 @@ _devlink_trap_group_set()
case $prev in
action)
COMPREPLY=( $( compgen -W "trap drop" -- "$cur" ) )
COMPREPLY=( $( compgen -W "trap drop mirror" -- "$cur" ) )
return
;;
policer)

View File

@ -635,10 +635,16 @@ static int fdb_get(int argc, char **argv)
if (rtnl_talk(&rth, &req.n, &answer) < 0)
return -2;
/*
* Initialize a json_writer and open an array object
* if -json was specified.
*/
new_json_obj(json);
if (print_fdb(answer, stdout) < 0) {
fprintf(stderr, "An error :-)\n");
return -1;
}
delete_json_obj();
return 0;
}

2
configure vendored
View File

@ -208,7 +208,7 @@ typedef unsigned short ip_set_id_t;
#include <linux/netfilter/xt_set.h>
struct xt_set_info info;
#if IPSET_PROTOCOL == 6
#if IPSET_PROTOCOL == 6 || IPSET_PROTOCOL == 7
int main(void)
{
return IPSET_MAXNAMELEN;

View File

@ -19,19 +19,26 @@
#include <limits.h>
#include <errno.h>
#include <inttypes.h>
#include <signal.h>
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/sysinfo.h>
#define _LINUX_SYSINFO_H /* avoid collision with musl header */
#include <linux/genetlink.h>
#include <linux/devlink.h>
#include <linux/netlink.h>
#include <libmnl/libmnl.h>
#include <netinet/ether.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <rt_names.h>
#include "SNAPSHOT.h"
#include "list.h"
#include "mnlg.h"
#include "json_writer.h"
#include "json_print.h"
#include "utils.h"
#include "namespace.h"
@ -1298,6 +1305,8 @@ static int trap_action_get(const char *actionstr,
*p_action = DEVLINK_TRAP_ACTION_DROP;
} else if (strcmp(actionstr, "trap") == 0) {
*p_action = DEVLINK_TRAP_ACTION_TRAP;
} else if (strcmp(actionstr, "mirror") == 0) {
*p_action = DEVLINK_TRAP_ACTION_MIRROR;
} else {
pr_err("Unknown trap action \"%s\"\n", actionstr);
return -EINVAL;
@ -2417,6 +2426,11 @@ static const struct param_val_conv param_val_conv[] = {
.vstr = "flash",
.vuint = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH,
},
{
.name = "fw_load_policy",
.vstr = "disk",
.vuint = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK,
},
{
.name = "reset_dev_on_drv_probe",
.vstr = "unknown",
@ -7209,6 +7223,8 @@ static const char *trap_type_name(uint8_t type)
return "drop";
case DEVLINK_TRAP_TYPE_EXCEPTION:
return "exception";
case DEVLINK_TRAP_TYPE_CONTROL:
return "control";
default:
return "<unknown type>";
}
@ -7221,6 +7237,8 @@ static const char *trap_action_name(uint8_t action)
return "drop";
case DEVLINK_TRAP_ACTION_TRAP:
return "trap";
case DEVLINK_TRAP_ACTION_MIRROR:
return "mirror";
default:
return "<unknown action>";
}
@ -7295,9 +7313,9 @@ static int cmd_trap_show_cb(const struct nlmsghdr *nlh, void *data)
static void cmd_trap_help(void)
{
pr_err("Usage: devlink trap set DEV trap TRAP [ action { trap | drop } ]\n");
pr_err("Usage: devlink trap set DEV trap TRAP [ action { trap | drop | mirror } ]\n");
pr_err(" devlink trap show [ DEV trap TRAP ]\n");
pr_err(" devlink trap group set DEV group GROUP [ action { trap | drop } ]\n");
pr_err(" devlink trap group set DEV group GROUP [ action { trap | drop | mirror } ]\n");
pr_err(" [ policer POLICER ] [ nopolicer ]\n");
pr_err(" devlink trap group show [ DEV group GROUP ]\n");
pr_err(" devlink trap policer set DEV policer POLICER [ rate RATE ] [ burst BURST ]\n");

View File

@ -2,11 +2,10 @@
#ifndef _TC_UTIL_H_
#define _TC_UTIL_H_ 1
#include <linux/genetlink.h>
#include "utils.h"
#include "linux/genetlink.h"
struct genl_util
{
struct genl_util {
struct genl_util *next;
char name[16];
int (*parse_genlopt)(struct genl_util *fu, int argc, char **argv);

View File

@ -11,7 +11,7 @@ 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
ipnexthop.o ipmptcp.o iplink_bareudp.o
RTMONOBJ=rtmon.o

View File

@ -30,7 +30,6 @@
#include <linux/sockios.h>
#include <linux/net_namespace.h>
#include "utils.h"
#include "rt_names.h"
#include "utils.h"
#include "ll_map.h"
@ -1257,7 +1256,9 @@ static const struct ifa_flag_data_t {
/* Returns a pointer to the data structure for a particular interface flag, or null if no flag could be found */
static const struct ifa_flag_data_t* lookup_flag_data_by_name(const char* flag_name) {
for (int i = 0; i < ARRAY_SIZE(ifa_flag_data); ++i) {
unsigned int i;
for (i = 0; i < ARRAY_SIZE(ifa_flag_data); ++i) {
if (strcmp(flag_name, ifa_flag_data[i].name) == 0)
return &ifa_flag_data[i];
}

View File

@ -27,10 +27,10 @@
static void usage(void)
{
fprintf(stderr,
"Usage: ip fou add port PORT { ipproto PROTO | gue } [ -6 ]\n"
"Usage: ip fou add port PORT { ipproto PROTO | gue }\n"
" [ local IFADDR ] [ peer IFADDR ]\n"
" [ peer_port PORT ] [ dev IFNAME ]\n"
" ip fou del port PORT [ -6 ] [ local IFADDR ]\n"
" ip fou del port PORT [ local IFADDR ]\n"
" [ peer IFADDR ] [ peer_port PORT ]\n"
" [ dev IFNAME ]\n"
" ip fou show\n"
@ -55,13 +55,17 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n,
{
const char *local = NULL, *peer = NULL;
__u16 port, peer_port = 0;
__u8 family = AF_INET;
__u8 family = preferred_family;
bool gue_set = false;
int ipproto_set = 0;
__u8 ipproto, type;
int port_set = 0;
int index = 0;
if (preferred_family == AF_UNSPEC) {
family = AF_INET;
}
while (argc > 0) {
if (!matches(*argv, "port")) {
NEXT_ARG();

View File

@ -124,7 +124,7 @@ void iplink_usage(void)
" bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |\n"
" gre | gretap | erspan | ip6gre | ip6gretap | ip6erspan |\n"
" vti | nlmon | team_slave | bond_slave | bridge_slave |\n"
" ipvlan | ipvtap | geneve | vrf | macsec | netdevsim | rmnet |\n"
" ipvlan | ipvtap | geneve | bareudp | vrf | macsec | netdevsim | rmnet |\n"
" xfrm }\n");
}
exit(-1);

150
ip/iplink_bareudp.c Normal file
View File

@ -0,0 +1,150 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <stdio.h>
#include <linux/if_ether.h>
#include <linux/if_link.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include "libnetlink.h"
#include "rt_names.h"
#include "utils.h"
#include "ip_common.h"
#include "json_print.h"
#define BAREUDP_ATTRSET(attrs, type) (((attrs) & (1L << (type))) != 0)
static void print_explain(FILE *f)
{
fprintf(f,
"Usage: ... bareudp dstport PORT\n"
" ethertype PROTO\n"
" [ srcportmin PORT ]\n"
" [ [no]multiproto ]\n"
"\n"
"Where: PORT := 0-65535\n"
" PROTO := NUMBER | ip | mpls\n"
" SRCPORTMIN := 0-65535\n"
);
}
static void explain(void)
{
print_explain(stderr);
}
static void check_duparg(__u64 *attrs, int type, const char *key,
const char *argv)
{
if (!BAREUDP_ATTRSET(*attrs, type)) {
*attrs |= (1L << type);
return;
}
duparg2(key, argv);
}
static int bareudp_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
bool multiproto = false;
__u16 srcportmin = 0;
__be16 ethertype = 0;
__be16 dstport = 0;
__u64 attrs = 0;
while (argc > 0) {
if (matches(*argv, "dstport") == 0) {
NEXT_ARG();
check_duparg(&attrs, IFLA_BAREUDP_PORT, "dstport",
*argv);
if (get_be16(&dstport, *argv, 0))
invarg("dstport", *argv);
} else if (matches(*argv, "ethertype") == 0) {
NEXT_ARG();
check_duparg(&attrs, IFLA_BAREUDP_ETHERTYPE,
"ethertype", *argv);
if (ll_proto_a2n(&ethertype, *argv))
invarg("ethertype", *argv);
} else if (matches(*argv, "srcportmin") == 0) {
NEXT_ARG();
check_duparg(&attrs, IFLA_BAREUDP_SRCPORT_MIN,
"srcportmin", *argv);
if (get_u16(&srcportmin, *argv, 0))
invarg("srcportmin", *argv);
} else if (matches(*argv, "multiproto") == 0) {
check_duparg(&attrs, IFLA_BAREUDP_MULTIPROTO_MODE,
*argv, *argv);
multiproto = true;
} else if (matches(*argv, "nomultiproto") == 0) {
check_duparg(&attrs, IFLA_BAREUDP_MULTIPROTO_MODE,
*argv, *argv);
multiproto = false;
} else if (matches(*argv, "help") == 0) {
explain();
return -1;
} else {
fprintf(stderr, "bareudp: unknown command \"%s\"?\n",
*argv);
explain();
return -1;
}
argc--, argv++;
}
if (!BAREUDP_ATTRSET(attrs, IFLA_BAREUDP_PORT))
missarg("dstport");
if (!BAREUDP_ATTRSET(attrs, IFLA_BAREUDP_ETHERTYPE))
missarg("ethertype");
addattr16(n, 1024, IFLA_BAREUDP_PORT, dstport);
addattr16(n, 1024, IFLA_BAREUDP_ETHERTYPE, ethertype);
if (BAREUDP_ATTRSET(attrs, IFLA_BAREUDP_SRCPORT_MIN))
addattr16(n, 1024, IFLA_BAREUDP_SRCPORT_MIN, srcportmin);
if (multiproto)
addattr(n, 1024, IFLA_BAREUDP_MULTIPROTO_MODE);
return 0;
}
static void bareudp_print_opt(struct link_util *lu, FILE *f,
struct rtattr *tb[])
{
if (!tb)
return;
if (tb[IFLA_BAREUDP_PORT])
print_uint(PRINT_ANY, "dstport", "dstport %u ",
rta_getattr_be16(tb[IFLA_BAREUDP_PORT]));
if (tb[IFLA_BAREUDP_ETHERTYPE]) {
struct rtattr *attr = tb[IFLA_BAREUDP_ETHERTYPE];
SPRINT_BUF(ethertype);
print_string(PRINT_ANY, "ethertype", "ethertype %s ",
ll_proto_n2a(rta_getattr_u16(attr),
ethertype, sizeof(ethertype)));
}
if (tb[IFLA_BAREUDP_SRCPORT_MIN])
print_uint(PRINT_ANY, "srcportmin", "srcportmin %u ",
rta_getattr_u16(tb[IFLA_BAREUDP_SRCPORT_MIN]));
if (tb[IFLA_BAREUDP_MULTIPROTO_MODE])
print_bool(PRINT_ANY, "multiproto", "multiproto ", true);
else
print_bool(PRINT_ANY, "multiproto", "nomultiproto ", false);
}
static void bareudp_print_help(struct link_util *lu, int argc, char **argv,
FILE *f)
{
print_explain(f);
}
struct link_util bareudp_link_util = {
.id = "bareudp",
.maxattr = IFLA_BAREUDP_MAX,
.parse_opt = bareudp_parse_opt,
.print_opt = bareudp_print_opt,
.print_help = bareudp_print_help,
};

View File

@ -59,6 +59,7 @@ static void usage(void)
" [ if_id IF_ID ] [ LIMIT-LIST ] [ TMPL-LIST ]\n"
"Usage: ip xfrm policy { delete | get } { SELECTOR | index INDEX } dir DIR\n"
" [ ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]\n"
" [ if_id IF_ID ]\n"
"Usage: ip xfrm policy { deleteall | list } [ nosock ] [ SELECTOR ] [ dir DIR ]\n"
" [ index INDEX ] [ ptype PTYPE ] [ action ACTION ] [ priority PRIORITY ]\n"
" [ flag FLAG-LIST ]\n"
@ -582,6 +583,8 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
struct xfrm_user_sec_ctx sctx;
char str[CTX_BUF_SIZE];
} ctx = {};
bool is_if_id_set = false;
__u32 if_id = 0;
while (argc > 0) {
if (strcmp(*argv, "dir") == 0) {
@ -619,7 +622,11 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
NEXT_ARG();
xfrm_policy_ptype_parse(&upt.type, &argc, &argv);
} else if (strcmp(*argv, "if_id") == 0) {
NEXT_ARG();
if (get_u32(&if_id, *argv, 0))
invarg("IF_ID value is invalid", *argv);
is_if_id_set = true;
} else {
if (selp)
invarg("unknown", *argv);
@ -669,6 +676,9 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete,
(void *)&ctx, ctx.sctx.len);
}
if (is_if_id_set)
addattr32(&req.n, sizeof(req.buf), XFRMA_IF_ID, if_id);
if (rtnl_talk(&rth, &req.n, answer) < 0)
exit(2);
@ -767,6 +777,11 @@ static int xfrm_policy_keep(struct nlmsghdr *n, void *arg)
}
}
if (tb[XFRMA_IF_ID]) {
addattr32(new_n, xb->size, XFRMA_IF_ID,
rta_getattr_u32(tb[XFRMA_IF_ID]));
}
xb->offset += new_n->nlmsg_len;
xb->nlmsg_count++;

View File

@ -148,10 +148,10 @@ __u64 get_cgroup2_id(const char *path)
strerror(errno));
goto out;
}
if (fhp->handle_bytes != sizeof(__u64)) {
fprintf(stderr, "Invalid size of cgroup2 ID\n");
goto out;
}
}
if (fhp->handle_bytes != sizeof(__u64)) {
fprintf(stderr, "Invalid size of cgroup2 ID\n");
goto out;
}
memcpy(cg_id.bytes, fhp->f_handle, sizeof(__u64));

View File

@ -50,7 +50,7 @@ int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data)
int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen)
.SH DESCRIPTION
libnetlink provides a higher level interface to
.BR rtnetlink(7).
.BR rtnetlink (7).
The read functions return 0 on success and a negative errno on failure.
The send functions return the amount of data sent, or -1 on error.
.TP
@ -129,9 +129,9 @@ for parsing. The file should contain raw data as received from a rtnetlink socke
The following functions are useful to construct custom rtnetlink messages. For
simple database dumping with filtering it is better to use the higher level
functions above. See
.BR rtnetlink(3)
.BR rtnetlink (3)
and
.BR netlink(3)
.BR netlink (3)
on how to generate a rtnetlink message. The following utility functions
require a continuous buffer that already contains a netlink message header
and a rtnetlink request.
@ -194,7 +194,7 @@ netlink/rtnetlink was designed and written by Alexey Kuznetsov.
Andi Kleen wrote the man page.
.SH SEE ALSO
.BR netlink(7),
.BR rtnetlink(7)
.BR netlink (7),
.BR rtnetlink (7)
.br
/usr/include/linux/rtnetlink.h

View File

@ -28,10 +28,9 @@ bridge \- show / manipulate bridge addresses and devices
\fB\-o\fR[\fIneline\fr] }
.ti -8
.BR "bridge link set"
.B "bridge link set"
.B dev
.IR DEV
.IR " [ "
.IR DEV " [ "
.B cost
.IR COST " ] [ "
.B priority
@ -108,9 +107,9 @@ bridge \- show / manipulate bridge addresses and devices
.ti -8
.BR "bridge mdb" " { " add " | " del " } "
.B dev
.IR DEV
.I DEV
.B port
.IR PORT
.I PORT
.B grp
.IR GROUP " [ "
.BR permanent " | " temp " ] [ "
@ -125,10 +124,10 @@ bridge \- show / manipulate bridge addresses and devices
.ti -8
.BR "bridge vlan" " { " add " | " del " } "
.B dev
.IR DEV
.I DEV
.B vid
.IR VID " [ "
.BR tunnel_info
.B tunnel_info
.IR TUNNEL_ID " ] [ "
.BR pvid " ] [ " untagged " ] [ "
.BR self " ] [ " master " ] "
@ -168,7 +167,7 @@ to the specified network namespace
Actually it just simplifies executing of:
.B ip netns exec
.IR NETNS
.I NETNS
.B bridge
.RI "[ " OPTIONS " ] " OBJECT " { " COMMAND " | "
.BR help " }"
@ -185,7 +184,7 @@ Read commands from provided file or standard input and invoke them.
First failure will cause termination of bridge command.
.TP
.BR "\-force"
.B "\-force"
Don't terminate bridge command on errors in batch mode.
If there were any errors during execution of the commands, the application
return code will be non zero.
@ -395,7 +394,7 @@ bridge FDB.
Controls whether a given port will flood unicast traffic for which there is no FDB entry. By default this flag is on.
.TP
.BI hwmode
.B hwmode
Some network interface cards support HW bridge functionality and they may be
configured in different modes. Currently support modes are:
@ -419,7 +418,7 @@ instead of multicast. By default this flag is off.
This is done by copying the packet per host and
changing the multicast destination MAC to a unicast one accordingly.
.BR mcast_to_unicast
.B mcast_to_unicast
works on top of the multicast snooping feature of
the bridge. Which means unicast copies are only delivered to hosts which
are interested in it and signalized this via IGMP/MLD reports
@ -464,15 +463,15 @@ If the port loses carrier all traffic will be redirected to the
configured backup port
.TP
.BR nobackup_port
.B nobackup_port
Removes the currently configured backup port
.TP
.BI self
.B self
link setting is configured on specified physical device
.TP
.BI master
.B master
link setting is configured on the software bridge (default)
.TP
@ -501,7 +500,7 @@ and delete old ones.
This command creates a new fdb entry.
.TP
.BI "LLADDR"
.B LLADDR
the Ethernet MAC address.
.TP
@ -633,7 +632,7 @@ and last used time for each entry.
lookup a bridge forwarding table entry.
.TP
.BI "LLADDR"
.B LLADDR
the Ethernet MAC address.
.TP
@ -757,21 +756,21 @@ dst_metadata for every packet that belongs to this vlan (applicable to
bridge ports with vlan_tunnel flag set).
.TP
.BI pvid
.B pvid
the vlan specified is to be considered a PVID at ingress.
Any untagged frames will be assigned to this VLAN.
.TP
.BI untagged
.B untagged
the vlan specified is to be treated as untagged on egress.
.TP
.BI self
.B self
the vlan is configured on the specified physical device. Required if the
device is the bridge device.
.TP
.BI master
.B master
the vlan is configured on the software bridge (default).
.SS bridge vlan delete - delete a vlan filter entry

View File

@ -26,61 +26,60 @@ devlink-dev \- devlink device configuration
.B devlink dev help
.ti -8
.BR "devlink dev eswitch set"
.IR DEV
.RI "[ "
.B devlink dev eswitch set
.I DEV
[
.BR mode " { " legacy " | " switchdev " } "
.RI "]"
.RI "[ "
] [
.BR inline-mode " { " none " | " link " | " network " | " transport " } "
.RI "]"
.RI "[ "
] [
.BR encap-mode " { " none " | " basic " } "
.RI "]"
]
.ti -8
.BR "devlink dev eswitch show"
.IR DEV
.B devlink dev eswitch show
.I DEV
.ti -8
.BR "devlink dev param set"
.IR DEV
.BR name
.IR PARAMETER
.BR value
.IR VALUE
.B devlink dev param set
.I DEV
.B name
.I PARAMETER
.B value
.I VALUE
.BR cmode " { " runtime " | " driverinit " | " permanent " } "
.ti -8
.BR "devlink dev param show"
.RI "[ "
.IR DEV
.BR name
.IR PARAMETER
.RI "]"
.B devlink dev param show
[
.I DEV
.B name
.I PARAMETER
]
.ti -8
.BR "devlink dev reload"
.IR DEV
.RI "[ "
.BI "netns { " PID " | " NAME " | " ID " }
.RI "]"
.B devlink dev reload
.I DEV
[
.B netns
.RI "{ " PID " | " NAME " | " ID " }"
]
.ti -8
.BR "devlink dev info"
.RI "[ "
.IR DEV
.RI "]"
.B devlink dev info
[
.I DEV
]
.ti -8
.BR "devlink dev flash"
.IR DEV
.BR file
.IR PATH
.RI "["
.BR target
.IR ID
.RI "]"
.B devlink dev flash
.I DEV
.B file
.I PATH
[
.B target
.I ID
]
.SH "DESCRIPTION"
.SS devlink dev show - display devlink device attributes
@ -159,8 +158,8 @@ Configuration mode in which the new value is set.
.SS devlink dev param show - display devlink device supported configuration parameters attributes
.BR name
.IR PARAMETER
.B name
.I PARAMETER
Specify parameter name to show.
If this argument is omitted all parameters supported by devlink devices are listed.
@ -170,8 +169,8 @@ If this argument is omitted all parameters supported by devlink devices are list
.I "DEV"
- Specifies the devlink device to reload.
.BR netns
.BI { " PID " | " NAME " | " ID " }
.B netns
.RI { " PID " | " NAME " | " ID " }
- Specifies the network namespace to reload into, either by pid, name or id.
.SS devlink dev info - display device information.
@ -200,13 +199,13 @@ If this argument is omitted all devices are listed.
.I "DEV"
- specifies the devlink device to write to.
.BR file
.B file
.I PATH
- Path to the file which will be written into device's flash. The path needs
to be relative to one of the directories searched by the kernel firmware loaded,
such as /lib/firmware.
.BR component
.B component
.I NAME
- If device stores multiple firmware images in non-volatile memory, this
parameter may be used to indicate which firmware image should be written.

View File

@ -18,49 +18,47 @@ devlink-health \- devlink health reporting and recovery
\fB\-V\fR[\fIersion\fR] }
.ti -8
.BR "devlink health show"
.B devlink health show
.RI "[ " DEV ""
.B reporter
.RI ""REPORTER " ] "
.ti -8
.BR "devlink health recover"
.B devlink health recover
.RI "" DEV ""
.B reporter
.RI "" REPORTER ""
.ti -8
.BR "devlink health diagnose"
.B devlink health diagnose
.RI "" DEV ""
.B reporter
.RI "" REPORTER ""
.ti -8
.BR "devlink health dump show"
.B devlink health dump show
.RI "" DEV ""
.B reporter
.RI "" REPORTER ""
.ti -8
.BR "devlink health dump clear"
.B devlink health dump clear
.RI "" DEV ""
.B reporter
.RI "" REPORTER ""
.ti -8
.BR "devlink health set"
.B devlink health set
.RI "" DEV ""
.B reporter
.RI "" REPORTER ""
.RI "[ "
[
.BI "grace_period " MSEC "
.RI "]"
.RI "[ "
] [
.BR auto_recover " { " true " | " false " } "
.RI "]"
.RI "[ "
] [
.BR auto_dump " { " true " | " false " } "
.RI "]"
]
.ti -8
.B devlink health help

View File

@ -26,7 +26,7 @@ devlink-trap \- devlink trap configuration
.ti -8
.BI "devlink trap set " DEV " trap " TRAP
.RB "[ " action " { " trap " | " drop " } ]"
.RB "[ " action " { " trap " | " drop " | " mirror " } ]"
.ti -8
.B "devlink trap group show"
@ -36,7 +36,7 @@ devlink-trap \- devlink trap configuration
.ti -8
.BI "devlink trap group set " DEV " group " GROUP
.RB "[ " action " { " trap " | " drop " } ]"
.RB "[ " action " { " trap " | " drop " | " mirror " } ]"
.br
.RB "[ " policer
.IB "POLICER " ]
@ -76,7 +76,7 @@ Only applicable if a devlink device is also specified.
- specifies the packet trap.
.TP
.BR action " { " trap " | " drop " } "
.BR action " { " trap " | " drop " | " mirror " } "
packet trap action.
.I trap
@ -85,6 +85,9 @@ packet trap action.
.I drop
- the packet is dropped by the underlying device and a copy is not sent to the CPU.
.I mirror
- the packet is forwarded by the underlying device and a copy is sent to the CPU.
.SS devlink trap group show - display available packet trap groups and their attributes
.PP
@ -108,14 +111,15 @@ Only applicable if a devlink device is also specified.
- specifies the packet trap group.
.TP
.BR action " { " trap " | " drop " } "
.BR action " { " trap " | " drop " | " mirror " } "
packet trap action. The action is set for all the packet traps member in the
trap group. The actions of non-drop traps cannot be changed and are thus
skipped.
.TP
.BI policer " POLICER"
packet trap policer. The policer to bind to the packet trap group.
packet trap policer. The policer to bind to the packet trap group. A value of
"0" will unbind the currently bound policer.
.TP
.B nopolicer

View File

@ -31,7 +31,7 @@ Read commands from provided file or standard input and invoke them.
First failure will cause termination of devlink.
.TP
.BR "\-force"
.B \-force
Don't terminate devlink on errors in batch mode.
If there were any errors during execution of the commands, the application return code will be non zero.

View File

@ -223,6 +223,7 @@ ip-link \- network device configuration
.BR ipvtap " |"
.BR lowpan " |"
.BR geneve " |"
.BR bareudp " |"
.BR vrf " |"
.BR macsec " |"
.BR netdevsim " |"
@ -356,6 +357,9 @@ Link types:
.BR geneve
- GEneric NEtwork Virtualization Encapsulation
.sp
.BR bareudp
- Bare UDP L3 encapsulation support
.sp
.BR macsec
- Interface for IEEE 802.1AE MAC Security (MACsec)
.sp
@ -1293,6 +1297,46 @@ options.
.in -8
.TP
Bareudp Type Support
For a link of type
.I Bareudp
the following additional arguments are supported:
.BI "ip link add " DEVICE
.BI type " bareudp " dstport " PORT " ethertype " ETHERTYPE"
[
.BI srcportmin " SRCPORTMIN "
] [
.RB [ no ] multiproto
]
.in +8
.sp
.BI dstport " PORT"
- specifies the destination port for the UDP tunnel.
.sp
.BI ethertype " ETHERTYPE"
- specifies the ethertype of the L3 protocol being tunnelled.
.sp
.BI srcportmin " SRCPORTMIN"
- selects the lowest value of the UDP tunnel source port range.
.sp
.RB [ no ] multiproto
- activates support for protocols similar to the one
.RB "specified by " ethertype .
When
.I ETHERTYPE
is "mpls_uc" (that is, unicast MPLS), this allows the tunnel to also handle
multicast MPLS.
When
.I ETHERTYPE
is "ipv4", this allows the tunnel to also handle IPv6. This option is disabled
by default.
.TP
MACVLAN and MACVTAP Type Support
For a link of type

View File

@ -61,6 +61,8 @@ ip-xfrm \- transform configuration
.IR EXTRA-FLAG-LIST " ]"
.RB "[ " output-mark
.IR OUTPUT-MARK " ]"
.RB "[ " if_id
.IR IF-ID " ]"
.ti -8
.B "ip xfrm state allocspi"
@ -238,6 +240,8 @@ ip-xfrm \- transform configuration
.IR PRIORITY " ]"
.RB "[ " flag
.IR FLAG-LIST " ]"
.RB "[ " if_id
.IR IF-ID " ]"
.RI "[ " LIMIT-LIST " ] [ " TMPL-LIST " ]"
.ti -8
@ -255,6 +259,8 @@ ip-xfrm \- transform configuration
.IR MASK " ] ]"
.RB "[ " ptype
.IR PTYPE " ]"
.RB "[ " if_id
.IR IF-ID " ]"
.ti -8
.BR ip " [ " -4 " | " -6 " ] " "xfrm policy" " { " deleteall " | " list " }"
@ -561,6 +567,10 @@ used to match xfrm policies and states
used to set the output mark to influence the routing
of the packets emitted by the state
.TP
.I IF-ID
xfrm interface identifier used to in both xfrm policies and states
.sp
.PP
.TS

View File

@ -46,6 +46,8 @@ flower \- flow based traffic control filter
.IR PRIORITY " | "
.BR cvlan_ethtype " { " ipv4 " | " ipv6 " | "
.IR ETH_TYPE " } | "
.B mpls
.IR LSE_LIST " | "
.B mpls_label
.IR LABEL " | "
.B mpls_tc
@ -96,7 +98,24 @@ flower \- flow based traffic control filter
}
.IR OPTIONS " | "
.BR ip_flags
.IR IP_FLAGS
.IR IP_FLAGS " }"
.ti -8
.IR LSE_LIST " := [ " LSE_LIST " ] " LSE
.ti -8
.IR LSE " := "
.B lse depth
.IR DEPTH " { "
.B label
.IR LABEL " | "
.B tc
.IR TC " | "
.B bos
.IR BOS " | "
.B ttl
.IR TTL " }"
.SH DESCRIPTION
The
.B flower
@ -182,6 +201,56 @@ Match on QinQ layer three protocol.
may be either
.BR ipv4 ", " ipv6
or an unsigned 16bit value in hexadecimal format.
.TP
.BI mpls " LSE_LIST"
Match on the MPLS label stack.
.I LSE_LIST
is a list of Label Stack Entries, each introduced by the
.BR lse " keyword."
This option can't be used together with the standalone
.BR mpls_label ", " mpls_tc ", " mpls_bos " and " mpls_ttl " options."
.RS
.TP
.BI lse " LSE_OPTIONS"
Match on an MPLS Label Stack Entry.
.I LSE_OPTIONS
is a list of options that describe the properties of the LSE to match.
.RS
.TP
.BI depth " DEPTH"
The depth of the Label Stack Entry to consider. Depth starts at 1 (the
outermost Label Stack Entry). The maximum usable depth may be limited by the
kernel. This option is mandatory.
.I DEPTH
is an unsigned 8 bit value in decimal format.
.TP
.BI label " LABEL"
Match on the MPLS Label field at the specified
.BR depth .
.I LABEL
is an unsigned 20 bit value in decimal format.
.TP
.BI tc " TC"
Match on the MPLS Traffic Class field at the specified
.BR depth .
.I TC
is an unsigned 3 bit value in decimal format.
.TP
.BI bos " BOS"
Match on the MPLS Bottom Of Stack field at the specified
.BR depth .
.I BOS
is a 1 bit value in decimal format.
.TP
.BI ttl " TTL"
Match on the MPLS Time To Live field at the specified
.BR depth .
.I TTL
is an unsigned 8 bit value in decimal format.
.RE
.RE
.TP
.BI mpls_label " LABEL"
Match the label id in the outermost MPLS label stack entry.
@ -393,7 +462,7 @@ on the matches of the next lower layer. Precisely, layer one and two matches
(\fBindev\fR, \fBdst_mac\fR and \fBsrc_mac\fR)
have no dependency,
MPLS and layer three matches
(\fBmpls_label\fR, \fBmpls_tc\fR, \fBmpls_bos\fR, \fBmpls_ttl\fR,
(\fBmpls\fR, \fBmpls_label\fR, \fBmpls_tc\fR, \fBmpls_bos\fR, \fBmpls_ttl\fR,
\fBip_proto\fR, \fBdst_ip\fR, \fBsrc_ip\fR, \fBarp_tip\fR, \fBarp_sip\fR,
\fBarp_op\fR, \fBarp_tha\fR, \fBarp_sha\fR and \fBip_flags\fR)
depend on the

View File

@ -77,9 +77,13 @@ tc \- show / manipulate traffic control settings
.B tc
.RI "[ " OPTIONS " ]"
.RI "[ " FORMAT " ]"
.B qdisc show [ dev
.B qdisc { show | list } [ dev
\fIDEV\fR
.B ]
.B ] [ root | ingress | handle
\fIQHANDLE\fR
.B | parent
\fICLASSID\fR
.B ] [ invisible ]
.P
.B tc
.RI "[ " OPTIONS " ]"
@ -473,7 +477,7 @@ qdiscs will use all three:
tc filters
If tc filters are attached to a class, they are consulted first
for relevant instructions. Filters can match on all fields of a packet header,
as well as on the firewall mark applied by ipchains or iptables.
as well as on the firewall mark applied by iptables.
.TP
Type of Service
Some qdiscs have built in rules for classifying packets based on the TOS field.

View File

@ -18,7 +18,6 @@
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <fnmatch.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/un.h>

View File

@ -59,6 +59,7 @@ static void explain(void)
" ip_proto [tcp | udp | sctp | icmp | icmpv6 | IP-PROTO ] |\n"
" ip_tos MASKED-IP_TOS |\n"
" ip_ttl MASKED-IP_TTL |\n"
" mpls LSE-LIST |\n"
" mpls_label LABEL |\n"
" mpls_tc TC |\n"
" mpls_bos BOS |\n"
@ -89,6 +90,8 @@ static void explain(void)
" ct_label MASKED_CT_LABEL |\n"
" ct_mark MASKED_CT_MARK |\n"
" ct_zone MASKED_CT_ZONE }\n"
" LSE-LIST := [ LSE-LIST ] LSE\n"
" LSE := lse depth DEPTH { label LABEL | tc TC | bos BOS | ttl TTL }\n"
" FILTERID := X:Y:Z\n"
" MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS }\n"
" MASKED_CT_STATE := combination of {+|-} and flags trk,est,new\n"
@ -1199,11 +1202,127 @@ static int flower_parse_enc_opts_erspan(char *str, struct nlmsghdr *n)
return 0;
}
static int flower_parse_mpls_lse(int *argc_p, char ***argv_p,
struct nlmsghdr *nlh)
{
struct rtattr *lse_attr;
char **argv = *argv_p;
int argc = *argc_p;
__u8 depth = 0;
int ret;
lse_attr = addattr_nest(nlh, MAX_MSG,
TCA_FLOWER_KEY_MPLS_OPTS_LSE | NLA_F_NESTED);
while (argc > 0) {
if (matches(*argv, "depth") == 0) {
NEXT_ARG();
ret = get_u8(&depth, *argv, 10);
if (ret < 0 || depth < 1) {
fprintf(stderr, "Illegal \"depth\"\n");
return -1;
}
addattr8(nlh, MAX_MSG,
TCA_FLOWER_KEY_MPLS_OPT_LSE_DEPTH, depth);
} else if (matches(*argv, "label") == 0) {
__u32 label;
NEXT_ARG();
ret = get_u32(&label, *argv, 10);
if (ret < 0 ||
label & ~(MPLS_LS_LABEL_MASK >> MPLS_LS_LABEL_SHIFT)) {
fprintf(stderr, "Illegal \"label\"\n");
return -1;
}
addattr32(nlh, MAX_MSG,
TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL, label);
} else if (matches(*argv, "tc") == 0) {
__u8 tc;
NEXT_ARG();
ret = get_u8(&tc, *argv, 10);
if (ret < 0 ||
tc & ~(MPLS_LS_TC_MASK >> MPLS_LS_TC_SHIFT)) {
fprintf(stderr, "Illegal \"tc\"\n");
return -1;
}
addattr8(nlh, MAX_MSG, TCA_FLOWER_KEY_MPLS_OPT_LSE_TC,
tc);
} else if (matches(*argv, "bos") == 0) {
__u8 bos;
NEXT_ARG();
ret = get_u8(&bos, *argv, 10);
if (ret < 0 || bos & ~(MPLS_LS_S_MASK >> MPLS_LS_S_SHIFT)) {
fprintf(stderr, "Illegal \"bos\"\n");
return -1;
}
addattr8(nlh, MAX_MSG, TCA_FLOWER_KEY_MPLS_OPT_LSE_BOS,
bos);
} else if (matches(*argv, "ttl") == 0) {
__u8 ttl;
NEXT_ARG();
ret = get_u8(&ttl, *argv, 10);
if (ret < 0 || ttl & ~(MPLS_LS_TTL_MASK >> MPLS_LS_TTL_SHIFT)) {
fprintf(stderr, "Illegal \"ttl\"\n");
return -1;
}
addattr8(nlh, MAX_MSG, TCA_FLOWER_KEY_MPLS_OPT_LSE_TTL,
ttl);
} else {
break;
}
argc--; argv++;
}
if (!depth) {
missarg("depth");
return -1;
}
addattr_nest_end(nlh, lse_attr);
*argc_p = argc;
*argv_p = argv;
return 0;
}
static int flower_parse_mpls(int *argc_p, char ***argv_p, struct nlmsghdr *nlh)
{
struct rtattr *mpls_attr;
char **argv = *argv_p;
int argc = *argc_p;
mpls_attr = addattr_nest(nlh, MAX_MSG,
TCA_FLOWER_KEY_MPLS_OPTS | NLA_F_NESTED);
while (argc > 0) {
if (matches(*argv, "lse") == 0) {
NEXT_ARG();
if (flower_parse_mpls_lse(&argc, &argv, nlh) < 0)
return -1;
} else {
break;
}
}
addattr_nest_end(nlh, mpls_attr);
*argc_p = argc;
*argv_p = argv;
return 0;
}
static int flower_parse_opt(struct filter_util *qu, char *handle,
int argc, char **argv, struct nlmsghdr *n)
{
int ret;
struct tcmsg *t = NLMSG_DATA(n);
bool mpls_format_old = false;
bool mpls_format_new = false;
struct rtattr *tail;
__be16 eth_type = TC_H_MIN(t->tcm_info);
__be16 vlan_ethtype = 0;
@ -1381,6 +1500,23 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
&cvlan_ethtype, n);
if (ret < 0)
return -1;
} else if (matches(*argv, "mpls") == 0) {
NEXT_ARG();
if (eth_type != htons(ETH_P_MPLS_UC) &&
eth_type != htons(ETH_P_MPLS_MC)) {
fprintf(stderr,
"Can't set \"mpls\" if ethertype isn't MPLS\n");
return -1;
}
if (mpls_format_old) {
fprintf(stderr,
"Can't set \"mpls\" if \"mpls_label\", \"mpls_tc\", \"mpls_bos\" or \"mpls_ttl\" is set\n");
return -1;
}
mpls_format_new = true;
if (flower_parse_mpls(&argc, &argv, n) < 0)
return -1;
continue;
} else if (matches(*argv, "mpls_label") == 0) {
__u32 label;
@ -1391,6 +1527,12 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
"Can't set \"mpls_label\" if ethertype isn't MPLS\n");
return -1;
}
if (mpls_format_new) {
fprintf(stderr,
"Can't set \"mpls_label\" if \"mpls\" is set\n");
return -1;
}
mpls_format_old = true;
ret = get_u32(&label, *argv, 10);
if (ret < 0 || label & ~(MPLS_LS_LABEL_MASK >> MPLS_LS_LABEL_SHIFT)) {
fprintf(stderr, "Illegal \"mpls_label\"\n");
@ -1407,6 +1549,12 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
"Can't set \"mpls_tc\" if ethertype isn't MPLS\n");
return -1;
}
if (mpls_format_new) {
fprintf(stderr,
"Can't set \"mpls_tc\" if \"mpls\" is set\n");
return -1;
}
mpls_format_old = true;
ret = get_u8(&tc, *argv, 10);
if (ret < 0 || tc & ~(MPLS_LS_TC_MASK >> MPLS_LS_TC_SHIFT)) {
fprintf(stderr, "Illegal \"mpls_tc\"\n");
@ -1423,6 +1571,12 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
"Can't set \"mpls_bos\" if ethertype isn't MPLS\n");
return -1;
}
if (mpls_format_new) {
fprintf(stderr,
"Can't set \"mpls_bos\" if \"mpls\" is set\n");
return -1;
}
mpls_format_old = true;
ret = get_u8(&bos, *argv, 10);
if (ret < 0 || bos & ~(MPLS_LS_S_MASK >> MPLS_LS_S_SHIFT)) {
fprintf(stderr, "Illegal \"mpls_bos\"\n");
@ -1439,6 +1593,12 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
"Can't set \"mpls_ttl\" if ethertype isn't MPLS\n");
return -1;
}
if (mpls_format_new) {
fprintf(stderr,
"Can't set \"mpls_ttl\" if \"mpls\" is set\n");
return -1;
}
mpls_format_old = true;
ret = get_u8(&ttl, *argv, 10);
if (ret < 0 || ttl & ~(MPLS_LS_TTL_MASK >> MPLS_LS_TTL_SHIFT)) {
fprintf(stderr, "Illegal \"mpls_ttl\"\n");
@ -2316,6 +2476,66 @@ static void flower_print_u32(const char *name, struct rtattr *attr)
print_uint(PRINT_ANY, name, namefrm, rta_getattr_u32(attr));
}
static void flower_print_mpls_opt_lse(const char *name, struct rtattr *lse)
{
struct rtattr *tb[TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX + 1];
struct rtattr *attr;
if (lse->rta_type != (TCA_FLOWER_KEY_MPLS_OPTS_LSE | NLA_F_NESTED)) {
fprintf(stderr, "rta_type 0x%x, expecting 0x%x (0x%x & 0x%x)\n",
lse->rta_type,
TCA_FLOWER_KEY_MPLS_OPTS_LSE & NLA_F_NESTED,
TCA_FLOWER_KEY_MPLS_OPTS_LSE, NLA_F_NESTED);
return;
}
parse_rtattr(tb, TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX, RTA_DATA(lse),
RTA_PAYLOAD(lse));
print_nl();
open_json_array(PRINT_ANY, name);
attr = tb[TCA_FLOWER_KEY_MPLS_OPT_LSE_DEPTH];
if (attr)
print_hhu(PRINT_ANY, "depth", " depth %u",
rta_getattr_u8(attr));
attr = tb[TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL];
if (attr)
print_uint(PRINT_ANY, "label", " label %u",
rta_getattr_u32(attr));
attr = tb[TCA_FLOWER_KEY_MPLS_OPT_LSE_TC];
if (attr)
print_hhu(PRINT_ANY, "tc", " tc %u", rta_getattr_u8(attr));
attr = tb[TCA_FLOWER_KEY_MPLS_OPT_LSE_BOS];
if (attr)
print_hhu(PRINT_ANY, "bos", " bos %u", rta_getattr_u8(attr));
attr = tb[TCA_FLOWER_KEY_MPLS_OPT_LSE_TTL];
if (attr)
print_hhu(PRINT_ANY, "ttl", " ttl %u", rta_getattr_u8(attr));
close_json_array(PRINT_JSON, NULL);
}
static void flower_print_mpls_opts(const char *name, struct rtattr *attr)
{
struct rtattr *lse;
int rem;
if (!attr || !(attr->rta_type & NLA_F_NESTED))
return;
print_nl();
open_json_array(PRINT_ANY, name);
rem = RTA_PAYLOAD(attr);
lse = RTA_DATA(attr);
while (RTA_OK(lse, rem)) {
flower_print_mpls_opt_lse(" lse", lse);
lse = RTA_NEXT(lse, rem);
};
if (rem)
fprintf(stderr, "!!!Deficit %d, rta_len=%d\n",
rem, lse->rta_len);
close_json_array(PRINT_JSON, NULL);
}
static void flower_print_arp_op(const char *name,
struct rtattr *op_attr,
struct rtattr *mask_attr)
@ -2430,6 +2650,7 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
flower_print_ip_attr("ip_ttl", tb[TCA_FLOWER_KEY_IP_TTL],
tb[TCA_FLOWER_KEY_IP_TTL_MASK]);
flower_print_mpls_opts(" mpls", tb[TCA_FLOWER_KEY_MPLS_OPTS]);
flower_print_u32("mpls_label", tb[TCA_FLOWER_KEY_MPLS_LABEL]);
flower_print_u8("mpls_tc", tb[TCA_FLOWER_KEY_MPLS_TC]);
flower_print_u8("mpls_bos", tb[TCA_FLOWER_KEY_MPLS_BOS]);

View File

@ -35,11 +35,12 @@ static int usage(void)
" [ ingress_block BLOCK_INDEX ] [ egress_block BLOCK_INDEX ]\n"
" [ [ QDISC_KIND ] [ help | OPTIONS ] ]\n"
"\n"
" tc qdisc show [ dev STRING ] [ ingress | clsact ] [ invisible ]\n"
" tc qdisc { show | list } [ dev STRING ] [ QDISC_ID ] [ invisible ]\n"
"Where:\n"
"QDISC_KIND := { [p|b]fifo | tbf | prio | cbq | red | etc. }\n"
"OPTIONS := ... try tc qdisc add <desired QDISC_KIND> help\n"
"STAB_OPTIONS := ... try tc qdisc add stab help\n");
"STAB_OPTIONS := ... try tc qdisc add stab help\n"
"QDISC_ID := { root | ingress | handle QHANDLE | parent CLASSID }\n");
return -1;
}
@ -212,6 +213,8 @@ static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv)
}
static int filter_ifindex;
static __u32 filter_parent;
static __u32 filter_handle;
int print_qdisc(struct nlmsghdr *n, void *arg)
{
@ -235,6 +238,12 @@ int print_qdisc(struct nlmsghdr *n, void *arg)
if (filter_ifindex && filter_ifindex != t->tcm_ifindex)
return 0;
if (filter_handle && filter_handle != t->tcm_handle)
return 0;
if (filter_parent && filter_parent != t->tcm_parent)
return 0;
parse_rtattr_flags(tb, TCA_MAX, TCA_RTA(t), len, NLA_F_NESTED);
if (tb[TCA_KIND] == NULL) {
@ -344,21 +353,55 @@ int print_qdisc(struct nlmsghdr *n, void *arg)
static int tc_qdisc_list(int argc, char **argv)
{
struct tcmsg t = { .tcm_family = AF_UNSPEC };
struct {
struct nlmsghdr n;
struct tcmsg t;
char buf[256];
} req = {
.n.nlmsg_type = RTM_GETQDISC,
.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
.t.tcm_family = AF_UNSPEC,
};
char d[IFNAMSIZ] = {};
bool dump_invisible = false;
__u32 handle;
while (argc > 0) {
if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
strncpy(d, *argv, sizeof(d)-1);
} else if (strcmp(*argv, "root") == 0) {
if (filter_parent)
invarg("parent is already specified", *argv);
else if (filter_handle)
invarg("handle is already specified", *argv);
filter_parent = TC_H_ROOT;
} else if (strcmp(*argv, "ingress") == 0 ||
strcmp(*argv, "clsact") == 0) {
if (t.tcm_parent) {
fprintf(stderr, "Duplicate parent ID\n");
usage();
}
t.tcm_parent = TC_H_INGRESS;
strcmp(*argv, "clsact") == 0) {
if (filter_parent)
invarg("parent is already specified", *argv);
else if (filter_handle)
invarg("handle is already specified", *argv);
filter_parent = TC_H_INGRESS;
} else if (matches(*argv, "parent") == 0) {
if (filter_parent)
invarg("parent is already specified", *argv);
else if (filter_handle)
invarg("handle is already specified", *argv);
NEXT_ARG();
if (get_tc_classid(&handle, *argv))
invarg("invalid parent ID", *argv);
filter_parent = handle;
} else if (matches(*argv, "handle") == 0) {
if (filter_parent)
invarg("parent is already specified", *argv);
else if (filter_handle)
invarg("handle is already specified", *argv);
NEXT_ARG();
if (get_qdisc_handle(&handle, *argv))
invarg("invalid handle ID", *argv);
filter_handle = handle;
} else if (matches(*argv, "help") == 0) {
usage();
} else if (strcmp(*argv, "invisible") == 0) {
@ -374,32 +417,18 @@ static int tc_qdisc_list(int argc, char **argv)
ll_init_map(&rth);
if (d[0]) {
t.tcm_ifindex = ll_name_to_index(d);
if (!t.tcm_ifindex)
req.t.tcm_ifindex = ll_name_to_index(d);
if (!req.t.tcm_ifindex)
return -nodev(d);
filter_ifindex = t.tcm_ifindex;
filter_ifindex = req.t.tcm_ifindex;
}
if (dump_invisible) {
struct {
struct nlmsghdr n;
struct tcmsg t;
char buf[256];
} req = {
.n.nlmsg_type = RTM_GETQDISC,
.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
};
req.t.tcm_family = AF_UNSPEC;
addattr(&req.n, 256, TCA_DUMP_INVISIBLE);
if (rtnl_dump_request_n(&rth, &req.n) < 0) {
perror("Cannot send dump request");
return 1;
}
}
} else if (rtnl_dump_request(&rth, RTM_GETQDISC, &t, sizeof(t)) < 0) {
perror("Cannot send dump request");
if (rtnl_dump_request_n(&rth, &req.n) < 0) {
perror("Cannot send request");
return 1;
}
@ -427,10 +456,6 @@ int do_qdisc(int argc, char **argv)
return tc_qdisc_modify(RTM_NEWQDISC, NLM_F_REPLACE, argc-1, argv+1);
if (matches(*argv, "delete") == 0)
return tc_qdisc_modify(RTM_DELQDISC, 0, argc-1, argv+1);
#if 0
if (matches(*argv, "get") == 0)
return tc_qdisc_get(RTM_GETQDISC, 0, argc-1, argv+1);
#endif
if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
|| matches(*argv, "lst") == 0)
return tc_qdisc_list(argc-1, argv+1);

View File

@ -217,7 +217,7 @@ static int cmd_link_get_bcast_cb(const struct nlmsghdr *nlh, void *data)
print_string(PRINT_ANY, "method", "%s", "AUTOSELECT");
close_json_object();
open_json_object(NULL);
print_uint(PRINT_ANY, "ratio", " ratio:%u%\n",
print_uint(PRINT_ANY, "ratio", " ratio:%u\n",
mnl_attr_get_u32(props[prop_ratio]));
break;
default: