Merge branch 'main' into next
Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
commit
b78c480532
|
|
@ -678,7 +678,7 @@ _devlink_trap_set_action()
|
||||||
COMPREPLY=( $( compgen -W "action" -- "$cur" ) )
|
COMPREPLY=( $( compgen -W "action" -- "$cur" ) )
|
||||||
;;
|
;;
|
||||||
$((7 + $i)))
|
$((7 + $i)))
|
||||||
COMPREPLY=( $( compgen -W "trap drop" -- "$cur" ) )
|
COMPREPLY=( $( compgen -W "trap drop mirror" -- "$cur" ) )
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
@ -708,7 +708,7 @@ _devlink_trap_group_set()
|
||||||
|
|
||||||
case $prev in
|
case $prev in
|
||||||
action)
|
action)
|
||||||
COMPREPLY=( $( compgen -W "trap drop" -- "$cur" ) )
|
COMPREPLY=( $( compgen -W "trap drop mirror" -- "$cur" ) )
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
policer)
|
policer)
|
||||||
|
|
|
||||||
|
|
@ -635,10 +635,16 @@ static int fdb_get(int argc, char **argv)
|
||||||
if (rtnl_talk(&rth, &req.n, &answer) < 0)
|
if (rtnl_talk(&rth, &req.n, &answer) < 0)
|
||||||
return -2;
|
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) {
|
if (print_fdb(answer, stdout) < 0) {
|
||||||
fprintf(stderr, "An error :-)\n");
|
fprintf(stderr, "An error :-)\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
delete_json_obj();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,7 @@ typedef unsigned short ip_set_id_t;
|
||||||
#include <linux/netfilter/xt_set.h>
|
#include <linux/netfilter/xt_set.h>
|
||||||
|
|
||||||
struct xt_set_info info;
|
struct xt_set_info info;
|
||||||
#if IPSET_PROTOCOL == 6
|
#if IPSET_PROTOCOL == 6 || IPSET_PROTOCOL == 7
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
return IPSET_MAXNAMELEN;
|
return IPSET_MAXNAMELEN;
|
||||||
|
|
|
||||||
|
|
@ -19,19 +19,26 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
#define _LINUX_SYSINFO_H /* avoid collision with musl header */
|
#define _LINUX_SYSINFO_H /* avoid collision with musl header */
|
||||||
#include <linux/genetlink.h>
|
#include <linux/genetlink.h>
|
||||||
#include <linux/devlink.h>
|
#include <linux/devlink.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
#include <libmnl/libmnl.h>
|
#include <libmnl/libmnl.h>
|
||||||
#include <netinet/ether.h>
|
#include <netinet/ether.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <rt_names.h>
|
#include <rt_names.h>
|
||||||
|
|
||||||
#include "SNAPSHOT.h"
|
#include "SNAPSHOT.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "mnlg.h"
|
#include "mnlg.h"
|
||||||
#include "json_writer.h"
|
#include "json_print.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "namespace.h"
|
#include "namespace.h"
|
||||||
|
|
||||||
|
|
@ -1298,6 +1305,8 @@ static int trap_action_get(const char *actionstr,
|
||||||
*p_action = DEVLINK_TRAP_ACTION_DROP;
|
*p_action = DEVLINK_TRAP_ACTION_DROP;
|
||||||
} else if (strcmp(actionstr, "trap") == 0) {
|
} else if (strcmp(actionstr, "trap") == 0) {
|
||||||
*p_action = DEVLINK_TRAP_ACTION_TRAP;
|
*p_action = DEVLINK_TRAP_ACTION_TRAP;
|
||||||
|
} else if (strcmp(actionstr, "mirror") == 0) {
|
||||||
|
*p_action = DEVLINK_TRAP_ACTION_MIRROR;
|
||||||
} else {
|
} else {
|
||||||
pr_err("Unknown trap action \"%s\"\n", actionstr);
|
pr_err("Unknown trap action \"%s\"\n", actionstr);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -2417,6 +2426,11 @@ static const struct param_val_conv param_val_conv[] = {
|
||||||
.vstr = "flash",
|
.vstr = "flash",
|
||||||
.vuint = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_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",
|
.name = "reset_dev_on_drv_probe",
|
||||||
.vstr = "unknown",
|
.vstr = "unknown",
|
||||||
|
|
@ -7209,6 +7223,8 @@ static const char *trap_type_name(uint8_t type)
|
||||||
return "drop";
|
return "drop";
|
||||||
case DEVLINK_TRAP_TYPE_EXCEPTION:
|
case DEVLINK_TRAP_TYPE_EXCEPTION:
|
||||||
return "exception";
|
return "exception";
|
||||||
|
case DEVLINK_TRAP_TYPE_CONTROL:
|
||||||
|
return "control";
|
||||||
default:
|
default:
|
||||||
return "<unknown type>";
|
return "<unknown type>";
|
||||||
}
|
}
|
||||||
|
|
@ -7221,6 +7237,8 @@ static const char *trap_action_name(uint8_t action)
|
||||||
return "drop";
|
return "drop";
|
||||||
case DEVLINK_TRAP_ACTION_TRAP:
|
case DEVLINK_TRAP_ACTION_TRAP:
|
||||||
return "trap";
|
return "trap";
|
||||||
|
case DEVLINK_TRAP_ACTION_MIRROR:
|
||||||
|
return "mirror";
|
||||||
default:
|
default:
|
||||||
return "<unknown action>";
|
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)
|
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 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(" [ policer POLICER ] [ nopolicer ]\n");
|
||||||
pr_err(" devlink trap group show [ DEV group GROUP ]\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");
|
pr_err(" devlink trap policer set DEV policer POLICER [ rate RATE ] [ burst BURST ]\n");
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,10 @@
|
||||||
#ifndef _TC_UTIL_H_
|
#ifndef _TC_UTIL_H_
|
||||||
#define _TC_UTIL_H_ 1
|
#define _TC_UTIL_H_ 1
|
||||||
|
|
||||||
|
#include <linux/genetlink.h>
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "linux/genetlink.h"
|
|
||||||
|
|
||||||
struct genl_util
|
struct genl_util {
|
||||||
{
|
|
||||||
struct genl_util *next;
|
struct genl_util *next;
|
||||||
char name[16];
|
char name[16];
|
||||||
int (*parse_genlopt)(struct genl_util *fu, int argc, char **argv);
|
int (*parse_genlopt)(struct genl_util *fu, int argc, char **argv);
|
||||||
|
|
|
||||||
|
|
@ -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_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \
|
||||||
iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.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 \
|
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
|
RTMONOBJ=rtmon.o
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@
|
||||||
#include <linux/sockios.h>
|
#include <linux/sockios.h>
|
||||||
#include <linux/net_namespace.h>
|
#include <linux/net_namespace.h>
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
#include "rt_names.h"
|
#include "rt_names.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "ll_map.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 */
|
/* 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) {
|
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)
|
if (strcmp(flag_name, ifa_flag_data[i].name) == 0)
|
||||||
return &ifa_flag_data[i];
|
return &ifa_flag_data[i];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
ip/ipfou.c
10
ip/ipfou.c
|
|
@ -27,10 +27,10 @@
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
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"
|
" [ local IFADDR ] [ peer IFADDR ]\n"
|
||||||
" [ peer_port PORT ] [ dev IFNAME ]\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"
|
" [ peer IFADDR ] [ peer_port PORT ]\n"
|
||||||
" [ dev IFNAME ]\n"
|
" [ dev IFNAME ]\n"
|
||||||
" ip fou show\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;
|
const char *local = NULL, *peer = NULL;
|
||||||
__u16 port, peer_port = 0;
|
__u16 port, peer_port = 0;
|
||||||
__u8 family = AF_INET;
|
__u8 family = preferred_family;
|
||||||
bool gue_set = false;
|
bool gue_set = false;
|
||||||
int ipproto_set = 0;
|
int ipproto_set = 0;
|
||||||
__u8 ipproto, type;
|
__u8 ipproto, type;
|
||||||
int port_set = 0;
|
int port_set = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
|
if (preferred_family == AF_UNSPEC) {
|
||||||
|
family = AF_INET;
|
||||||
|
}
|
||||||
|
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (!matches(*argv, "port")) {
|
if (!matches(*argv, "port")) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ void iplink_usage(void)
|
||||||
" bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |\n"
|
" bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |\n"
|
||||||
" gre | gretap | erspan | ip6gre | ip6gretap | ip6erspan |\n"
|
" gre | gretap | erspan | ip6gre | ip6gretap | ip6erspan |\n"
|
||||||
" vti | nlmon | team_slave | bond_slave | bridge_slave |\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");
|
" xfrm }\n");
|
||||||
}
|
}
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|
|
||||||
|
|
@ -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(ðertype, *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,
|
||||||
|
};
|
||||||
|
|
@ -59,6 +59,7 @@ static void usage(void)
|
||||||
" [ if_id IF_ID ] [ LIMIT-LIST ] [ TMPL-LIST ]\n"
|
" [ if_id IF_ID ] [ LIMIT-LIST ] [ TMPL-LIST ]\n"
|
||||||
"Usage: ip xfrm policy { delete | get } { SELECTOR | index INDEX } dir DIR\n"
|
"Usage: ip xfrm policy { delete | get } { SELECTOR | index INDEX } dir DIR\n"
|
||||||
" [ ctx CTX ] [ mark MARK [ mask MASK ] ] [ ptype PTYPE ]\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"
|
"Usage: ip xfrm policy { deleteall | list } [ nosock ] [ SELECTOR ] [ dir DIR ]\n"
|
||||||
" [ index INDEX ] [ ptype PTYPE ] [ action ACTION ] [ priority PRIORITY ]\n"
|
" [ index INDEX ] [ ptype PTYPE ] [ action ACTION ] [ priority PRIORITY ]\n"
|
||||||
" [ flag FLAG-LIST ]\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;
|
struct xfrm_user_sec_ctx sctx;
|
||||||
char str[CTX_BUF_SIZE];
|
char str[CTX_BUF_SIZE];
|
||||||
} ctx = {};
|
} ctx = {};
|
||||||
|
bool is_if_id_set = false;
|
||||||
|
__u32 if_id = 0;
|
||||||
|
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (strcmp(*argv, "dir") == 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();
|
NEXT_ARG();
|
||||||
xfrm_policy_ptype_parse(&upt.type, &argc, &argv);
|
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 {
|
} else {
|
||||||
if (selp)
|
if (selp)
|
||||||
invarg("unknown", *argv);
|
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);
|
(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)
|
if (rtnl_talk(&rth, &req.n, answer) < 0)
|
||||||
exit(2);
|
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->offset += new_n->nlmsg_len;
|
||||||
xb->nlmsg_count++;
|
xb->nlmsg_count++;
|
||||||
|
|
||||||
|
|
|
||||||
8
lib/fs.c
8
lib/fs.c
|
|
@ -148,10 +148,10 @@ __u64 get_cgroup2_id(const char *path)
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (fhp->handle_bytes != sizeof(__u64)) {
|
}
|
||||||
fprintf(stderr, "Invalid size of cgroup2 ID\n");
|
if (fhp->handle_bytes != sizeof(__u64)) {
|
||||||
goto out;
|
fprintf(stderr, "Invalid size of cgroup2 ID\n");
|
||||||
}
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(cg_id.bytes, fhp->f_handle, sizeof(__u64));
|
memcpy(cg_id.bytes, fhp->f_handle, sizeof(__u64));
|
||||||
|
|
|
||||||
|
|
@ -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)
|
int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen)
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
libnetlink provides a higher level interface to
|
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 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.
|
The send functions return the amount of data sent, or -1 on error.
|
||||||
.TP
|
.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
|
The following functions are useful to construct custom rtnetlink messages. For
|
||||||
simple database dumping with filtering it is better to use the higher level
|
simple database dumping with filtering it is better to use the higher level
|
||||||
functions above. See
|
functions above. See
|
||||||
.BR rtnetlink(3)
|
.BR rtnetlink (3)
|
||||||
and
|
and
|
||||||
.BR netlink(3)
|
.BR netlink (3)
|
||||||
on how to generate a rtnetlink message. The following utility functions
|
on how to generate a rtnetlink message. The following utility functions
|
||||||
require a continuous buffer that already contains a netlink message header
|
require a continuous buffer that already contains a netlink message header
|
||||||
and a rtnetlink request.
|
and a rtnetlink request.
|
||||||
|
|
@ -194,7 +194,7 @@ netlink/rtnetlink was designed and written by Alexey Kuznetsov.
|
||||||
Andi Kleen wrote the man page.
|
Andi Kleen wrote the man page.
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR netlink(7),
|
.BR netlink (7),
|
||||||
.BR rtnetlink(7)
|
.BR rtnetlink (7)
|
||||||
.br
|
.br
|
||||||
/usr/include/linux/rtnetlink.h
|
/usr/include/linux/rtnetlink.h
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,9 @@ bridge \- show / manipulate bridge addresses and devices
|
||||||
\fB\-o\fR[\fIneline\fr] }
|
\fB\-o\fR[\fIneline\fr] }
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "bridge link set"
|
.B "bridge link set"
|
||||||
.B dev
|
.B dev
|
||||||
.IR DEV
|
.IR DEV " [ "
|
||||||
.IR " [ "
|
|
||||||
.B cost
|
.B cost
|
||||||
.IR COST " ] [ "
|
.IR COST " ] [ "
|
||||||
.B priority
|
.B priority
|
||||||
|
|
@ -108,9 +107,9 @@ bridge \- show / manipulate bridge addresses and devices
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "bridge mdb" " { " add " | " del " } "
|
.BR "bridge mdb" " { " add " | " del " } "
|
||||||
.B dev
|
.B dev
|
||||||
.IR DEV
|
.I DEV
|
||||||
.B port
|
.B port
|
||||||
.IR PORT
|
.I PORT
|
||||||
.B grp
|
.B grp
|
||||||
.IR GROUP " [ "
|
.IR GROUP " [ "
|
||||||
.BR permanent " | " temp " ] [ "
|
.BR permanent " | " temp " ] [ "
|
||||||
|
|
@ -125,10 +124,10 @@ bridge \- show / manipulate bridge addresses and devices
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "bridge vlan" " { " add " | " del " } "
|
.BR "bridge vlan" " { " add " | " del " } "
|
||||||
.B dev
|
.B dev
|
||||||
.IR DEV
|
.I DEV
|
||||||
.B vid
|
.B vid
|
||||||
.IR VID " [ "
|
.IR VID " [ "
|
||||||
.BR tunnel_info
|
.B tunnel_info
|
||||||
.IR TUNNEL_ID " ] [ "
|
.IR TUNNEL_ID " ] [ "
|
||||||
.BR pvid " ] [ " untagged " ] [ "
|
.BR pvid " ] [ " untagged " ] [ "
|
||||||
.BR self " ] [ " master " ] "
|
.BR self " ] [ " master " ] "
|
||||||
|
|
@ -168,7 +167,7 @@ to the specified network namespace
|
||||||
Actually it just simplifies executing of:
|
Actually it just simplifies executing of:
|
||||||
|
|
||||||
.B ip netns exec
|
.B ip netns exec
|
||||||
.IR NETNS
|
.I NETNS
|
||||||
.B bridge
|
.B bridge
|
||||||
.RI "[ " OPTIONS " ] " OBJECT " { " COMMAND " | "
|
.RI "[ " OPTIONS " ] " OBJECT " { " COMMAND " | "
|
||||||
.BR help " }"
|
.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.
|
First failure will cause termination of bridge command.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR "\-force"
|
.B "\-force"
|
||||||
Don't terminate bridge command on errors in batch mode.
|
Don't terminate bridge command on errors in batch mode.
|
||||||
If there were any errors during execution of the commands, the application
|
If there were any errors during execution of the commands, the application
|
||||||
return code will be non zero.
|
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.
|
Controls whether a given port will flood unicast traffic for which there is no FDB entry. By default this flag is on.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI hwmode
|
.B hwmode
|
||||||
Some network interface cards support HW bridge functionality and they may be
|
Some network interface cards support HW bridge functionality and they may be
|
||||||
configured in different modes. Currently support modes are:
|
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
|
This is done by copying the packet per host and
|
||||||
changing the multicast destination MAC to a unicast one accordingly.
|
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
|
works on top of the multicast snooping feature of
|
||||||
the bridge. Which means unicast copies are only delivered to hosts which
|
the bridge. Which means unicast copies are only delivered to hosts which
|
||||||
are interested in it and signalized this via IGMP/MLD reports
|
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
|
configured backup port
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR nobackup_port
|
.B nobackup_port
|
||||||
Removes the currently configured backup port
|
Removes the currently configured backup port
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI self
|
.B self
|
||||||
link setting is configured on specified physical device
|
link setting is configured on specified physical device
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI master
|
.B master
|
||||||
link setting is configured on the software bridge (default)
|
link setting is configured on the software bridge (default)
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
|
|
@ -501,7 +500,7 @@ and delete old ones.
|
||||||
This command creates a new fdb entry.
|
This command creates a new fdb entry.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "LLADDR"
|
.B LLADDR
|
||||||
the Ethernet MAC address.
|
the Ethernet MAC address.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
|
|
@ -633,7 +632,7 @@ and last used time for each entry.
|
||||||
lookup a bridge forwarding table entry.
|
lookup a bridge forwarding table entry.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "LLADDR"
|
.B LLADDR
|
||||||
the Ethernet MAC address.
|
the Ethernet MAC address.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
|
|
@ -757,21 +756,21 @@ dst_metadata for every packet that belongs to this vlan (applicable to
|
||||||
bridge ports with vlan_tunnel flag set).
|
bridge ports with vlan_tunnel flag set).
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI pvid
|
.B pvid
|
||||||
the vlan specified is to be considered a PVID at ingress.
|
the vlan specified is to be considered a PVID at ingress.
|
||||||
Any untagged frames will be assigned to this VLAN.
|
Any untagged frames will be assigned to this VLAN.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI untagged
|
.B untagged
|
||||||
the vlan specified is to be treated as untagged on egress.
|
the vlan specified is to be treated as untagged on egress.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI self
|
.B self
|
||||||
the vlan is configured on the specified physical device. Required if the
|
the vlan is configured on the specified physical device. Required if the
|
||||||
device is the bridge device.
|
device is the bridge device.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI master
|
.B master
|
||||||
the vlan is configured on the software bridge (default).
|
the vlan is configured on the software bridge (default).
|
||||||
|
|
||||||
.SS bridge vlan delete - delete a vlan filter entry
|
.SS bridge vlan delete - delete a vlan filter entry
|
||||||
|
|
|
||||||
|
|
@ -26,61 +26,60 @@ devlink-dev \- devlink device configuration
|
||||||
.B devlink dev help
|
.B devlink dev help
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink dev eswitch set"
|
.B devlink dev eswitch set
|
||||||
.IR DEV
|
.I DEV
|
||||||
.RI "[ "
|
[
|
||||||
.BR mode " { " legacy " | " switchdev " } "
|
.BR mode " { " legacy " | " switchdev " } "
|
||||||
.RI "]"
|
] [
|
||||||
.RI "[ "
|
|
||||||
.BR inline-mode " { " none " | " link " | " network " | " transport " } "
|
.BR inline-mode " { " none " | " link " | " network " | " transport " } "
|
||||||
.RI "]"
|
] [
|
||||||
.RI "[ "
|
|
||||||
.BR encap-mode " { " none " | " basic " } "
|
.BR encap-mode " { " none " | " basic " } "
|
||||||
.RI "]"
|
]
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink dev eswitch show"
|
.B devlink dev eswitch show
|
||||||
.IR DEV
|
.I DEV
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink dev param set"
|
.B devlink dev param set
|
||||||
.IR DEV
|
.I DEV
|
||||||
.BR name
|
.B name
|
||||||
.IR PARAMETER
|
.I PARAMETER
|
||||||
.BR value
|
.B value
|
||||||
.IR VALUE
|
.I VALUE
|
||||||
.BR cmode " { " runtime " | " driverinit " | " permanent " } "
|
.BR cmode " { " runtime " | " driverinit " | " permanent " } "
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink dev param show"
|
.B devlink dev param show
|
||||||
.RI "[ "
|
[
|
||||||
.IR DEV
|
.I DEV
|
||||||
.BR name
|
.B name
|
||||||
.IR PARAMETER
|
.I PARAMETER
|
||||||
.RI "]"
|
]
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink dev reload"
|
.B devlink dev reload
|
||||||
.IR DEV
|
.I DEV
|
||||||
.RI "[ "
|
[
|
||||||
.BI "netns { " PID " | " NAME " | " ID " }
|
.B netns
|
||||||
.RI "]"
|
.RI "{ " PID " | " NAME " | " ID " }"
|
||||||
|
]
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink dev info"
|
.B devlink dev info
|
||||||
.RI "[ "
|
[
|
||||||
.IR DEV
|
.I DEV
|
||||||
.RI "]"
|
]
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink dev flash"
|
.B devlink dev flash
|
||||||
.IR DEV
|
.I DEV
|
||||||
.BR file
|
.B file
|
||||||
.IR PATH
|
.I PATH
|
||||||
.RI "["
|
[
|
||||||
.BR target
|
.B target
|
||||||
.IR ID
|
.I ID
|
||||||
.RI "]"
|
]
|
||||||
|
|
||||||
.SH "DESCRIPTION"
|
.SH "DESCRIPTION"
|
||||||
.SS devlink dev show - display devlink device attributes
|
.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
|
.SS devlink dev param show - display devlink device supported configuration parameters attributes
|
||||||
|
|
||||||
.BR name
|
.B name
|
||||||
.IR PARAMETER
|
.I PARAMETER
|
||||||
Specify parameter name to show.
|
Specify parameter name to show.
|
||||||
If this argument is omitted all parameters supported by devlink devices are listed.
|
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"
|
.I "DEV"
|
||||||
- Specifies the devlink device to reload.
|
- Specifies the devlink device to reload.
|
||||||
|
|
||||||
.BR netns
|
.B netns
|
||||||
.BI { " PID " | " NAME " | " ID " }
|
.RI { " PID " | " NAME " | " ID " }
|
||||||
- Specifies the network namespace to reload into, either by pid, name or id.
|
- Specifies the network namespace to reload into, either by pid, name or id.
|
||||||
|
|
||||||
.SS devlink dev info - display device information.
|
.SS devlink dev info - display device information.
|
||||||
|
|
@ -200,13 +199,13 @@ If this argument is omitted all devices are listed.
|
||||||
.I "DEV"
|
.I "DEV"
|
||||||
- specifies the devlink device to write to.
|
- specifies the devlink device to write to.
|
||||||
|
|
||||||
.BR file
|
.B file
|
||||||
.I PATH
|
.I PATH
|
||||||
- Path to the file which will be written into device's flash. The path needs
|
- 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,
|
to be relative to one of the directories searched by the kernel firmware loaded,
|
||||||
such as /lib/firmware.
|
such as /lib/firmware.
|
||||||
|
|
||||||
.BR component
|
.B component
|
||||||
.I NAME
|
.I NAME
|
||||||
- If device stores multiple firmware images in non-volatile memory, this
|
- If device stores multiple firmware images in non-volatile memory, this
|
||||||
parameter may be used to indicate which firmware image should be written.
|
parameter may be used to indicate which firmware image should be written.
|
||||||
|
|
|
||||||
|
|
@ -18,49 +18,47 @@ devlink-health \- devlink health reporting and recovery
|
||||||
\fB\-V\fR[\fIersion\fR] }
|
\fB\-V\fR[\fIersion\fR] }
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink health show"
|
.B devlink health show
|
||||||
.RI "[ " DEV ""
|
.RI "[ " DEV ""
|
||||||
.B reporter
|
.B reporter
|
||||||
.RI ""REPORTER " ] "
|
.RI ""REPORTER " ] "
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink health recover"
|
.B devlink health recover
|
||||||
.RI "" DEV ""
|
.RI "" DEV ""
|
||||||
.B reporter
|
.B reporter
|
||||||
.RI "" REPORTER ""
|
.RI "" REPORTER ""
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink health diagnose"
|
.B devlink health diagnose
|
||||||
.RI "" DEV ""
|
.RI "" DEV ""
|
||||||
.B reporter
|
.B reporter
|
||||||
.RI "" REPORTER ""
|
.RI "" REPORTER ""
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink health dump show"
|
.B devlink health dump show
|
||||||
.RI "" DEV ""
|
.RI "" DEV ""
|
||||||
.B reporter
|
.B reporter
|
||||||
.RI "" REPORTER ""
|
.RI "" REPORTER ""
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink health dump clear"
|
.B devlink health dump clear
|
||||||
.RI "" DEV ""
|
.RI "" DEV ""
|
||||||
.B reporter
|
.B reporter
|
||||||
.RI "" REPORTER ""
|
.RI "" REPORTER ""
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "devlink health set"
|
.B devlink health set
|
||||||
.RI "" DEV ""
|
.RI "" DEV ""
|
||||||
.B reporter
|
.B reporter
|
||||||
.RI "" REPORTER ""
|
.RI "" REPORTER ""
|
||||||
.RI "[ "
|
[
|
||||||
.BI "grace_period " MSEC "
|
.BI "grace_period " MSEC "
|
||||||
.RI "]"
|
] [
|
||||||
.RI "[ "
|
|
||||||
.BR auto_recover " { " true " | " false " } "
|
.BR auto_recover " { " true " | " false " } "
|
||||||
.RI "]"
|
] [
|
||||||
.RI "[ "
|
|
||||||
.BR auto_dump " { " true " | " false " } "
|
.BR auto_dump " { " true " | " false " } "
|
||||||
.RI "]"
|
]
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.B devlink health help
|
.B devlink health help
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ devlink-trap \- devlink trap configuration
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BI "devlink trap set " DEV " trap " TRAP
|
.BI "devlink trap set " DEV " trap " TRAP
|
||||||
.RB "[ " action " { " trap " | " drop " } ]"
|
.RB "[ " action " { " trap " | " drop " | " mirror " } ]"
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.B "devlink trap group show"
|
.B "devlink trap group show"
|
||||||
|
|
@ -36,7 +36,7 @@ devlink-trap \- devlink trap configuration
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BI "devlink trap group set " DEV " group " GROUP
|
.BI "devlink trap group set " DEV " group " GROUP
|
||||||
.RB "[ " action " { " trap " | " drop " } ]"
|
.RB "[ " action " { " trap " | " drop " | " mirror " } ]"
|
||||||
.br
|
.br
|
||||||
.RB "[ " policer
|
.RB "[ " policer
|
||||||
.IB "POLICER " ]
|
.IB "POLICER " ]
|
||||||
|
|
@ -76,7 +76,7 @@ Only applicable if a devlink device is also specified.
|
||||||
- specifies the packet trap.
|
- specifies the packet trap.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR action " { " trap " | " drop " } "
|
.BR action " { " trap " | " drop " | " mirror " } "
|
||||||
packet trap action.
|
packet trap action.
|
||||||
|
|
||||||
.I trap
|
.I trap
|
||||||
|
|
@ -85,6 +85,9 @@ packet trap action.
|
||||||
.I drop
|
.I drop
|
||||||
- the packet is dropped by the underlying device and a copy is not sent to the CPU.
|
- 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
|
.SS devlink trap group show - display available packet trap groups and their attributes
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
|
|
@ -108,14 +111,15 @@ Only applicable if a devlink device is also specified.
|
||||||
- specifies the packet trap group.
|
- specifies the packet trap group.
|
||||||
|
|
||||||
.TP
|
.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
|
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
|
trap group. The actions of non-drop traps cannot be changed and are thus
|
||||||
skipped.
|
skipped.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI policer " POLICER"
|
.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
|
.TP
|
||||||
.B nopolicer
|
.B nopolicer
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ Read commands from provided file or standard input and invoke them.
|
||||||
First failure will cause termination of devlink.
|
First failure will cause termination of devlink.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR "\-force"
|
.B \-force
|
||||||
Don't terminate devlink on errors in batch mode.
|
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.
|
If there were any errors during execution of the commands, the application return code will be non zero.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,7 @@ ip-link \- network device configuration
|
||||||
.BR ipvtap " |"
|
.BR ipvtap " |"
|
||||||
.BR lowpan " |"
|
.BR lowpan " |"
|
||||||
.BR geneve " |"
|
.BR geneve " |"
|
||||||
|
.BR bareudp " |"
|
||||||
.BR vrf " |"
|
.BR vrf " |"
|
||||||
.BR macsec " |"
|
.BR macsec " |"
|
||||||
.BR netdevsim " |"
|
.BR netdevsim " |"
|
||||||
|
|
@ -356,6 +357,9 @@ Link types:
|
||||||
.BR geneve
|
.BR geneve
|
||||||
- GEneric NEtwork Virtualization Encapsulation
|
- GEneric NEtwork Virtualization Encapsulation
|
||||||
.sp
|
.sp
|
||||||
|
.BR bareudp
|
||||||
|
- Bare UDP L3 encapsulation support
|
||||||
|
.sp
|
||||||
.BR macsec
|
.BR macsec
|
||||||
- Interface for IEEE 802.1AE MAC Security (MACsec)
|
- Interface for IEEE 802.1AE MAC Security (MACsec)
|
||||||
.sp
|
.sp
|
||||||
|
|
@ -1293,6 +1297,46 @@ options.
|
||||||
|
|
||||||
.in -8
|
.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
|
.TP
|
||||||
MACVLAN and MACVTAP Type Support
|
MACVLAN and MACVTAP Type Support
|
||||||
For a link of type
|
For a link of type
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,8 @@ ip-xfrm \- transform configuration
|
||||||
.IR EXTRA-FLAG-LIST " ]"
|
.IR EXTRA-FLAG-LIST " ]"
|
||||||
.RB "[ " output-mark
|
.RB "[ " output-mark
|
||||||
.IR OUTPUT-MARK " ]"
|
.IR OUTPUT-MARK " ]"
|
||||||
|
.RB "[ " if_id
|
||||||
|
.IR IF-ID " ]"
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.B "ip xfrm state allocspi"
|
.B "ip xfrm state allocspi"
|
||||||
|
|
@ -238,6 +240,8 @@ ip-xfrm \- transform configuration
|
||||||
.IR PRIORITY " ]"
|
.IR PRIORITY " ]"
|
||||||
.RB "[ " flag
|
.RB "[ " flag
|
||||||
.IR FLAG-LIST " ]"
|
.IR FLAG-LIST " ]"
|
||||||
|
.RB "[ " if_id
|
||||||
|
.IR IF-ID " ]"
|
||||||
.RI "[ " LIMIT-LIST " ] [ " TMPL-LIST " ]"
|
.RI "[ " LIMIT-LIST " ] [ " TMPL-LIST " ]"
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
|
|
@ -255,6 +259,8 @@ ip-xfrm \- transform configuration
|
||||||
.IR MASK " ] ]"
|
.IR MASK " ] ]"
|
||||||
.RB "[ " ptype
|
.RB "[ " ptype
|
||||||
.IR PTYPE " ]"
|
.IR PTYPE " ]"
|
||||||
|
.RB "[ " if_id
|
||||||
|
.IR IF-ID " ]"
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR ip " [ " -4 " | " -6 " ] " "xfrm policy" " { " deleteall " | " list " }"
|
.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
|
used to set the output mark to influence the routing
|
||||||
of the packets emitted by the state
|
of the packets emitted by the state
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.I IF-ID
|
||||||
|
xfrm interface identifier used to in both xfrm policies and states
|
||||||
|
|
||||||
.sp
|
.sp
|
||||||
.PP
|
.PP
|
||||||
.TS
|
.TS
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ flower \- flow based traffic control filter
|
||||||
.IR PRIORITY " | "
|
.IR PRIORITY " | "
|
||||||
.BR cvlan_ethtype " { " ipv4 " | " ipv6 " | "
|
.BR cvlan_ethtype " { " ipv4 " | " ipv6 " | "
|
||||||
.IR ETH_TYPE " } | "
|
.IR ETH_TYPE " } | "
|
||||||
|
.B mpls
|
||||||
|
.IR LSE_LIST " | "
|
||||||
.B mpls_label
|
.B mpls_label
|
||||||
.IR LABEL " | "
|
.IR LABEL " | "
|
||||||
.B mpls_tc
|
.B mpls_tc
|
||||||
|
|
@ -96,7 +98,24 @@ flower \- flow based traffic control filter
|
||||||
}
|
}
|
||||||
.IR OPTIONS " | "
|
.IR OPTIONS " | "
|
||||||
.BR ip_flags
|
.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
|
.SH DESCRIPTION
|
||||||
The
|
The
|
||||||
.B flower
|
.B flower
|
||||||
|
|
@ -182,6 +201,56 @@ Match on QinQ layer three protocol.
|
||||||
may be either
|
may be either
|
||||||
.BR ipv4 ", " ipv6
|
.BR ipv4 ", " ipv6
|
||||||
or an unsigned 16bit value in hexadecimal format.
|
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
|
.TP
|
||||||
.BI mpls_label " LABEL"
|
.BI mpls_label " LABEL"
|
||||||
Match the label id in the outermost MPLS label stack entry.
|
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)
|
(\fBindev\fR, \fBdst_mac\fR and \fBsrc_mac\fR)
|
||||||
have no dependency,
|
have no dependency,
|
||||||
MPLS and layer three matches
|
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,
|
\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)
|
\fBarp_op\fR, \fBarp_tha\fR, \fBarp_sha\fR and \fBip_flags\fR)
|
||||||
depend on the
|
depend on the
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,13 @@ tc \- show / manipulate traffic control settings
|
||||||
.B tc
|
.B tc
|
||||||
.RI "[ " OPTIONS " ]"
|
.RI "[ " OPTIONS " ]"
|
||||||
.RI "[ " FORMAT " ]"
|
.RI "[ " FORMAT " ]"
|
||||||
.B qdisc show [ dev
|
.B qdisc { show | list } [ dev
|
||||||
\fIDEV\fR
|
\fIDEV\fR
|
||||||
.B ]
|
.B ] [ root | ingress | handle
|
||||||
|
\fIQHANDLE\fR
|
||||||
|
.B | parent
|
||||||
|
\fICLASSID\fR
|
||||||
|
.B ] [ invisible ]
|
||||||
.P
|
.P
|
||||||
.B tc
|
.B tc
|
||||||
.RI "[ " OPTIONS " ]"
|
.RI "[ " OPTIONS " ]"
|
||||||
|
|
@ -473,7 +477,7 @@ qdiscs will use all three:
|
||||||
tc filters
|
tc filters
|
||||||
If tc filters are attached to a class, they are consulted first
|
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,
|
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
|
.TP
|
||||||
Type of Service
|
Type of Service
|
||||||
Some qdiscs have built in rules for classifying packets based on the TOS field.
|
Some qdiscs have built in rules for classifying packets based on the TOS field.
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <fnmatch.h>
|
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
|
|
||||||
221
tc/f_flower.c
221
tc/f_flower.c
|
|
@ -59,6 +59,7 @@ static void explain(void)
|
||||||
" ip_proto [tcp | udp | sctp | icmp | icmpv6 | IP-PROTO ] |\n"
|
" ip_proto [tcp | udp | sctp | icmp | icmpv6 | IP-PROTO ] |\n"
|
||||||
" ip_tos MASKED-IP_TOS |\n"
|
" ip_tos MASKED-IP_TOS |\n"
|
||||||
" ip_ttl MASKED-IP_TTL |\n"
|
" ip_ttl MASKED-IP_TTL |\n"
|
||||||
|
" mpls LSE-LIST |\n"
|
||||||
" mpls_label LABEL |\n"
|
" mpls_label LABEL |\n"
|
||||||
" mpls_tc TC |\n"
|
" mpls_tc TC |\n"
|
||||||
" mpls_bos BOS |\n"
|
" mpls_bos BOS |\n"
|
||||||
|
|
@ -89,6 +90,8 @@ static void explain(void)
|
||||||
" ct_label MASKED_CT_LABEL |\n"
|
" ct_label MASKED_CT_LABEL |\n"
|
||||||
" ct_mark MASKED_CT_MARK |\n"
|
" ct_mark MASKED_CT_MARK |\n"
|
||||||
" ct_zone MASKED_CT_ZONE }\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"
|
" FILTERID := X:Y:Z\n"
|
||||||
" MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS }\n"
|
" MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS }\n"
|
||||||
" MASKED_CT_STATE := combination of {+|-} and flags trk,est,new\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;
|
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,
|
static int flower_parse_opt(struct filter_util *qu, char *handle,
|
||||||
int argc, char **argv, struct nlmsghdr *n)
|
int argc, char **argv, struct nlmsghdr *n)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct tcmsg *t = NLMSG_DATA(n);
|
struct tcmsg *t = NLMSG_DATA(n);
|
||||||
|
bool mpls_format_old = false;
|
||||||
|
bool mpls_format_new = false;
|
||||||
struct rtattr *tail;
|
struct rtattr *tail;
|
||||||
__be16 eth_type = TC_H_MIN(t->tcm_info);
|
__be16 eth_type = TC_H_MIN(t->tcm_info);
|
||||||
__be16 vlan_ethtype = 0;
|
__be16 vlan_ethtype = 0;
|
||||||
|
|
@ -1381,6 +1500,23 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
||||||
&cvlan_ethtype, n);
|
&cvlan_ethtype, n);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -1;
|
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) {
|
} else if (matches(*argv, "mpls_label") == 0) {
|
||||||
__u32 label;
|
__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");
|
"Can't set \"mpls_label\" if ethertype isn't MPLS\n");
|
||||||
return -1;
|
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);
|
ret = get_u32(&label, *argv, 10);
|
||||||
if (ret < 0 || label & ~(MPLS_LS_LABEL_MASK >> MPLS_LS_LABEL_SHIFT)) {
|
if (ret < 0 || label & ~(MPLS_LS_LABEL_MASK >> MPLS_LS_LABEL_SHIFT)) {
|
||||||
fprintf(stderr, "Illegal \"mpls_label\"\n");
|
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");
|
"Can't set \"mpls_tc\" if ethertype isn't MPLS\n");
|
||||||
return -1;
|
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);
|
ret = get_u8(&tc, *argv, 10);
|
||||||
if (ret < 0 || tc & ~(MPLS_LS_TC_MASK >> MPLS_LS_TC_SHIFT)) {
|
if (ret < 0 || tc & ~(MPLS_LS_TC_MASK >> MPLS_LS_TC_SHIFT)) {
|
||||||
fprintf(stderr, "Illegal \"mpls_tc\"\n");
|
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");
|
"Can't set \"mpls_bos\" if ethertype isn't MPLS\n");
|
||||||
return -1;
|
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);
|
ret = get_u8(&bos, *argv, 10);
|
||||||
if (ret < 0 || bos & ~(MPLS_LS_S_MASK >> MPLS_LS_S_SHIFT)) {
|
if (ret < 0 || bos & ~(MPLS_LS_S_MASK >> MPLS_LS_S_SHIFT)) {
|
||||||
fprintf(stderr, "Illegal \"mpls_bos\"\n");
|
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");
|
"Can't set \"mpls_ttl\" if ethertype isn't MPLS\n");
|
||||||
return -1;
|
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);
|
ret = get_u8(&ttl, *argv, 10);
|
||||||
if (ret < 0 || ttl & ~(MPLS_LS_TTL_MASK >> MPLS_LS_TTL_SHIFT)) {
|
if (ret < 0 || ttl & ~(MPLS_LS_TTL_MASK >> MPLS_LS_TTL_SHIFT)) {
|
||||||
fprintf(stderr, "Illegal \"mpls_ttl\"\n");
|
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));
|
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,
|
static void flower_print_arp_op(const char *name,
|
||||||
struct rtattr *op_attr,
|
struct rtattr *op_attr,
|
||||||
struct rtattr *mask_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],
|
flower_print_ip_attr("ip_ttl", tb[TCA_FLOWER_KEY_IP_TTL],
|
||||||
tb[TCA_FLOWER_KEY_IP_TTL_MASK]);
|
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_u32("mpls_label", tb[TCA_FLOWER_KEY_MPLS_LABEL]);
|
||||||
flower_print_u8("mpls_tc", tb[TCA_FLOWER_KEY_MPLS_TC]);
|
flower_print_u8("mpls_tc", tb[TCA_FLOWER_KEY_MPLS_TC]);
|
||||||
flower_print_u8("mpls_bos", tb[TCA_FLOWER_KEY_MPLS_BOS]);
|
flower_print_u8("mpls_bos", tb[TCA_FLOWER_KEY_MPLS_BOS]);
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,12 @@ static int usage(void)
|
||||||
" [ ingress_block BLOCK_INDEX ] [ egress_block BLOCK_INDEX ]\n"
|
" [ ingress_block BLOCK_INDEX ] [ egress_block BLOCK_INDEX ]\n"
|
||||||
" [ [ QDISC_KIND ] [ help | OPTIONS ] ]\n"
|
" [ [ QDISC_KIND ] [ help | OPTIONS ] ]\n"
|
||||||
"\n"
|
"\n"
|
||||||
" tc qdisc show [ dev STRING ] [ ingress | clsact ] [ invisible ]\n"
|
" tc qdisc { show | list } [ dev STRING ] [ QDISC_ID ] [ invisible ]\n"
|
||||||
"Where:\n"
|
"Where:\n"
|
||||||
"QDISC_KIND := { [p|b]fifo | tbf | prio | cbq | red | etc. }\n"
|
"QDISC_KIND := { [p|b]fifo | tbf | prio | cbq | red | etc. }\n"
|
||||||
"OPTIONS := ... try tc qdisc add <desired QDISC_KIND> help\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;
|
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 int filter_ifindex;
|
||||||
|
static __u32 filter_parent;
|
||||||
|
static __u32 filter_handle;
|
||||||
|
|
||||||
int print_qdisc(struct nlmsghdr *n, void *arg)
|
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)
|
if (filter_ifindex && filter_ifindex != t->tcm_ifindex)
|
||||||
return 0;
|
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);
|
parse_rtattr_flags(tb, TCA_MAX, TCA_RTA(t), len, NLA_F_NESTED);
|
||||||
|
|
||||||
if (tb[TCA_KIND] == NULL) {
|
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)
|
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] = {};
|
char d[IFNAMSIZ] = {};
|
||||||
bool dump_invisible = false;
|
bool dump_invisible = false;
|
||||||
|
__u32 handle;
|
||||||
|
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (strcmp(*argv, "dev") == 0) {
|
if (strcmp(*argv, "dev") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
strncpy(d, *argv, sizeof(d)-1);
|
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 ||
|
} else if (strcmp(*argv, "ingress") == 0 ||
|
||||||
strcmp(*argv, "clsact") == 0) {
|
strcmp(*argv, "clsact") == 0) {
|
||||||
if (t.tcm_parent) {
|
if (filter_parent)
|
||||||
fprintf(stderr, "Duplicate parent ID\n");
|
invarg("parent is already specified", *argv);
|
||||||
usage();
|
else if (filter_handle)
|
||||||
}
|
invarg("handle is already specified", *argv);
|
||||||
t.tcm_parent = TC_H_INGRESS;
|
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) {
|
} else if (matches(*argv, "help") == 0) {
|
||||||
usage();
|
usage();
|
||||||
} else if (strcmp(*argv, "invisible") == 0) {
|
} else if (strcmp(*argv, "invisible") == 0) {
|
||||||
|
|
@ -374,32 +417,18 @@ static int tc_qdisc_list(int argc, char **argv)
|
||||||
ll_init_map(&rth);
|
ll_init_map(&rth);
|
||||||
|
|
||||||
if (d[0]) {
|
if (d[0]) {
|
||||||
t.tcm_ifindex = ll_name_to_index(d);
|
req.t.tcm_ifindex = ll_name_to_index(d);
|
||||||
if (!t.tcm_ifindex)
|
if (!req.t.tcm_ifindex)
|
||||||
return -nodev(d);
|
return -nodev(d);
|
||||||
filter_ifindex = t.tcm_ifindex;
|
filter_ifindex = req.t.tcm_ifindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dump_invisible) {
|
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);
|
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) {
|
if (rtnl_dump_request_n(&rth, &req.n) < 0) {
|
||||||
perror("Cannot send dump request");
|
perror("Cannot send request");
|
||||||
return 1;
|
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);
|
return tc_qdisc_modify(RTM_NEWQDISC, NLM_F_REPLACE, argc-1, argv+1);
|
||||||
if (matches(*argv, "delete") == 0)
|
if (matches(*argv, "delete") == 0)
|
||||||
return tc_qdisc_modify(RTM_DELQDISC, 0, argc-1, argv+1);
|
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
|
if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
|
||||||
|| matches(*argv, "lst") == 0)
|
|| matches(*argv, "lst") == 0)
|
||||||
return tc_qdisc_list(argc-1, argv+1);
|
return tc_qdisc_list(argc-1, argv+1);
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,7 @@ static int cmd_link_get_bcast_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
print_string(PRINT_ANY, "method", "%s", "AUTOSELECT");
|
print_string(PRINT_ANY, "method", "%s", "AUTOSELECT");
|
||||||
close_json_object();
|
close_json_object();
|
||||||
open_json_object(NULL);
|
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]));
|
mnl_attr_get_u32(props[prop_ratio]));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue