Merge branch 'master' into next
Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
commit
8c109059b5
|
|
@ -378,7 +378,7 @@ static int brlink_modify(int argc, char **argv)
|
|||
state = strtol(*argv, &endptr, 10);
|
||||
if (!(**argv != '\0' && *endptr == '\0')) {
|
||||
for (state = 0; state < nstates; state++)
|
||||
if (strcmp(port_states[state], *argv) == 0)
|
||||
if (strcasecmp(port_states[state], *argv) == 0)
|
||||
break;
|
||||
if (state == nstates) {
|
||||
fprintf(stderr,
|
||||
|
|
|
|||
111
bridge/vlan.c
111
bridge/vlan.c
|
|
@ -22,6 +22,11 @@ enum vlan_show_subject {
|
|||
VLAN_SHOW_TUNNELINFO,
|
||||
};
|
||||
|
||||
#define VLAN_ID_LEN 9
|
||||
|
||||
#define __stringify_1(x...) #x
|
||||
#define __stringify(x...) __stringify_1(x)
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
|
|
@ -256,11 +261,11 @@ static int filter_vlan_check(__u16 vid, __u16 flags)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void open_vlan_port(int ifi_index, const char *fmt,
|
||||
enum vlan_show_subject subject)
|
||||
static void open_vlan_port(int ifi_index, enum vlan_show_subject subject)
|
||||
{
|
||||
open_json_object(NULL);
|
||||
print_color_string(PRINT_ANY, COLOR_IFNAME, "ifname", fmt,
|
||||
print_color_string(PRINT_ANY, COLOR_IFNAME, "ifname",
|
||||
"%-" __stringify(IFNAMSIZ) "s ",
|
||||
ll_index_to_name(ifi_index));
|
||||
open_json_array(PRINT_JSON,
|
||||
subject == VLAN_SHOW_VLAN ? "vlans": "tunnels");
|
||||
|
|
@ -272,16 +277,18 @@ static void close_vlan_port(void)
|
|||
close_json_object();
|
||||
}
|
||||
|
||||
static void print_range(const char *name, __u32 start, __u32 id)
|
||||
static unsigned int print_range(const char *name, __u32 start, __u32 id)
|
||||
{
|
||||
char end[64];
|
||||
int width;
|
||||
|
||||
snprintf(end, sizeof(end), "%sEnd", name);
|
||||
|
||||
print_uint(PRINT_ANY, name, "\t %u", start);
|
||||
width = print_uint(PRINT_ANY, name, "%u", start);
|
||||
if (start != id)
|
||||
print_uint(PRINT_ANY, end, "-%u", id);
|
||||
width += print_uint(PRINT_ANY, end, "-%u", id);
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
static void print_vlan_tunnel_info(struct rtattr *tb, int ifindex)
|
||||
|
|
@ -290,14 +297,14 @@ static void print_vlan_tunnel_info(struct rtattr *tb, int ifindex)
|
|||
int rem = RTA_PAYLOAD(list);
|
||||
__u16 last_vid_start = 0;
|
||||
__u32 last_tunid_start = 0;
|
||||
|
||||
open_vlan_port(ifindex, "%s", VLAN_SHOW_TUNNELINFO);
|
||||
bool opened = false;
|
||||
|
||||
for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
||||
struct rtattr *ttb[IFLA_BRIDGE_VLAN_TUNNEL_MAX+1];
|
||||
__u32 tunnel_id = 0;
|
||||
__u16 tunnel_vid = 0;
|
||||
__u16 tunnel_flags = 0;
|
||||
unsigned int width;
|
||||
int vcheck_ret;
|
||||
|
||||
if (i->rta_type != IFLA_BRIDGE_VLAN_TUNNEL_INFO)
|
||||
|
|
@ -331,13 +338,33 @@ static void print_vlan_tunnel_info(struct rtattr *tb, int ifindex)
|
|||
else if (vcheck_ret == 0)
|
||||
continue;
|
||||
|
||||
if (!opened) {
|
||||
open_vlan_port(ifindex, VLAN_SHOW_TUNNELINFO);
|
||||
opened = true;
|
||||
} else {
|
||||
print_string(PRINT_FP, NULL,
|
||||
"%-" __stringify(IFNAMSIZ) "s ", "");
|
||||
}
|
||||
|
||||
open_json_object(NULL);
|
||||
print_range("vlan", last_vid_start, tunnel_vid);
|
||||
width = print_range("vlan", last_vid_start, tunnel_vid);
|
||||
if (width <= VLAN_ID_LEN) {
|
||||
char buf[VLAN_ID_LEN + 1];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%-*s",
|
||||
VLAN_ID_LEN - width, "");
|
||||
print_string(PRINT_FP, NULL, "%s ", buf);
|
||||
} else {
|
||||
fprintf(stderr, "BUG: vlan range too wide, %u\n",
|
||||
width);
|
||||
}
|
||||
print_range("tunid", last_tunid_start, tunnel_id);
|
||||
close_json_object();
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
}
|
||||
close_vlan_port();
|
||||
|
||||
if (opened)
|
||||
close_vlan_port();
|
||||
}
|
||||
|
||||
static int print_vlan(struct nlmsghdr *n, void *arg)
|
||||
|
|
@ -366,16 +393,8 @@ static int print_vlan(struct nlmsghdr *n, void *arg)
|
|||
return 0;
|
||||
|
||||
parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifm), len);
|
||||
|
||||
/* if AF_SPEC isn't there, vlan table is not preset for this port */
|
||||
if (!tb[IFLA_AF_SPEC]) {
|
||||
if (!filter_vlan && !is_json_context()) {
|
||||
color_fprintf(stdout, COLOR_IFNAME, "%s",
|
||||
ll_index_to_name(ifm->ifi_index));
|
||||
fprintf(stdout, "\tNone\n");
|
||||
}
|
||||
if (!tb[IFLA_AF_SPEC])
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (*subject) {
|
||||
case VLAN_SHOW_VLAN:
|
||||
|
|
@ -385,9 +404,7 @@ static int print_vlan(struct nlmsghdr *n, void *arg)
|
|||
print_vlan_tunnel_info(tb[IFLA_AF_SPEC], ifm->ifi_index);
|
||||
break;
|
||||
}
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -408,20 +425,23 @@ static void print_vlan_flags(__u16 flags)
|
|||
static void print_one_vlan_stats(const struct bridge_vlan_xstats *vstats)
|
||||
{
|
||||
open_json_object(NULL);
|
||||
print_hu(PRINT_ANY, "vid", " %hu", vstats->vid);
|
||||
|
||||
print_hu(PRINT_ANY, "vid", "%hu", vstats->vid);
|
||||
print_vlan_flags(vstats->flags);
|
||||
print_nl();
|
||||
|
||||
print_lluint(PRINT_ANY, "rx_bytes",
|
||||
"\n RX: %llu bytes",
|
||||
print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", "");
|
||||
print_lluint(PRINT_ANY, "rx_bytes", "RX: %llu bytes",
|
||||
vstats->rx_bytes);
|
||||
print_lluint(PRINT_ANY, "rx_packets", " %llu packets\n",
|
||||
vstats->rx_packets);
|
||||
print_lluint(PRINT_ANY, "tx_bytes",
|
||||
" TX: %llu bytes",
|
||||
vstats->rx_packets);
|
||||
|
||||
print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", "");
|
||||
print_lluint(PRINT_ANY, "tx_bytes", "TX: %llu bytes",
|
||||
vstats->tx_bytes);
|
||||
print_lluint(PRINT_ANY, "tx_packets", " %llu packets\n",
|
||||
vstats->tx_packets);
|
||||
vstats->tx_packets);
|
||||
|
||||
close_json_object();
|
||||
}
|
||||
|
||||
|
|
@ -456,10 +476,11 @@ static void print_vlan_stats_attr(struct rtattr *attr, int ifindex)
|
|||
|
||||
/* found vlan stats, first time print the interface name */
|
||||
if (!found_vlan) {
|
||||
open_vlan_port(ifindex, "%-16s", VLAN_SHOW_VLAN);
|
||||
open_vlan_port(ifindex, VLAN_SHOW_VLAN);
|
||||
found_vlan = true;
|
||||
} else {
|
||||
print_string(PRINT_FP, NULL, "%-16s", "");
|
||||
print_string(PRINT_FP, NULL,
|
||||
"%-" __stringify(IFNAMSIZ) "s ", "");
|
||||
}
|
||||
print_one_vlan_stats(vstats);
|
||||
}
|
||||
|
|
@ -538,15 +559,17 @@ static int vlan_show(int argc, char **argv, int subject)
|
|||
}
|
||||
|
||||
if (!is_json_context()) {
|
||||
printf("port\tvlan ids");
|
||||
printf("%-" __stringify(IFNAMSIZ) "s %-"
|
||||
__stringify(VLAN_ID_LEN) "s", "port",
|
||||
"vlan-id");
|
||||
if (subject == VLAN_SHOW_TUNNELINFO)
|
||||
printf("\ttunnel id");
|
||||
printf(" tunnel-id");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
ret = rtnl_dump_filter(&rth, print_vlan, &subject);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Dump ternminated\n");
|
||||
fprintf(stderr, "Dump terminated\n");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -559,7 +582,8 @@ static int vlan_show(int argc, char **argv, int subject)
|
|||
}
|
||||
|
||||
if (!is_json_context())
|
||||
printf("%-16s vlan id\n", "port");
|
||||
printf("%-" __stringify(IFNAMSIZ) "s vlan-id\n",
|
||||
"port");
|
||||
|
||||
if (rtnl_dump_filter(&rth, print_vlan_stats, stdout) < 0) {
|
||||
fprintf(stderr, "Dump terminated\n");
|
||||
|
|
@ -588,8 +612,7 @@ void print_vlan_info(struct rtattr *tb, int ifindex)
|
|||
struct rtattr *i, *list = tb;
|
||||
int rem = RTA_PAYLOAD(list);
|
||||
__u16 last_vid_start = 0;
|
||||
|
||||
open_vlan_port(ifindex, "%s", VLAN_SHOW_VLAN);
|
||||
bool opened = false;
|
||||
|
||||
for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
|
||||
struct bridge_vlan_info *vinfo;
|
||||
|
|
@ -608,14 +631,24 @@ void print_vlan_info(struct rtattr *tb, int ifindex)
|
|||
else if (vcheck_ret == 0)
|
||||
continue;
|
||||
|
||||
if (!opened) {
|
||||
open_vlan_port(ifindex, VLAN_SHOW_VLAN);
|
||||
opened = true;
|
||||
} else {
|
||||
print_string(PRINT_FP, NULL, "%-"
|
||||
__stringify(IFNAMSIZ) "s ", "");
|
||||
}
|
||||
|
||||
open_json_object(NULL);
|
||||
print_range("vlan", last_vid_start, vinfo->vid);
|
||||
|
||||
print_vlan_flags(vinfo->flags);
|
||||
close_json_object();
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
}
|
||||
close_vlan_port();
|
||||
|
||||
if (opened)
|
||||
close_vlan_port();
|
||||
}
|
||||
|
||||
int do_vlan(int argc, char **argv)
|
||||
|
|
|
|||
|
|
@ -6476,10 +6476,27 @@ static int cmd_region_read(struct dl *dl)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int cmd_region_snapshot_new(struct dl *dl)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
int err;
|
||||
|
||||
nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_REGION_NEW,
|
||||
NLM_F_REQUEST | NLM_F_ACK);
|
||||
|
||||
err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE_REGION |
|
||||
DL_OPT_REGION_SNAPSHOT_ID, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL);
|
||||
}
|
||||
|
||||
static void cmd_region_help(void)
|
||||
{
|
||||
pr_err("Usage: devlink region show [ DEV/REGION ]\n");
|
||||
pr_err(" devlink region del DEV/REGION snapshot SNAPSHOT_ID\n");
|
||||
pr_err(" devlink region new DEV/REGION snapshot SNAPSHOT_ID\n");
|
||||
pr_err(" devlink region dump DEV/REGION [ snapshot SNAPSHOT_ID ]\n");
|
||||
pr_err(" devlink region read DEV/REGION [ snapshot SNAPSHOT_ID ] address ADDRESS length LENGTH\n");
|
||||
}
|
||||
|
|
@ -6503,6 +6520,9 @@ static int cmd_region(struct dl *dl)
|
|||
} else if (dl_argv_match(dl, "read")) {
|
||||
dl_arg_inc(dl);
|
||||
return cmd_region_read(dl);
|
||||
} else if (dl_argv_match(dl, "new")) {
|
||||
dl_arg_inc(dl);
|
||||
return cmd_region_snapshot_new(dl);
|
||||
}
|
||||
pr_err("Command \"%s\" not found\n", dl_argv(dl));
|
||||
return -ENOENT;
|
||||
|
|
|
|||
|
|
@ -44,20 +44,24 @@ void close_json_array(enum output_type type, const char *delim);
|
|||
void print_nl(void);
|
||||
|
||||
#define _PRINT_FUNC(type_name, type) \
|
||||
void print_color_##type_name(enum output_type t, \
|
||||
enum color_attr color, \
|
||||
const char *key, \
|
||||
const char *fmt, \
|
||||
type value); \
|
||||
int print_color_##type_name(enum output_type t, \
|
||||
enum color_attr color, \
|
||||
const char *key, \
|
||||
const char *fmt, \
|
||||
type value); \
|
||||
\
|
||||
static inline void print_##type_name(enum output_type t, \
|
||||
const char *key, \
|
||||
const char *fmt, \
|
||||
type value) \
|
||||
static inline int print_##type_name(enum output_type t, \
|
||||
const char *key, \
|
||||
const char *fmt, \
|
||||
type value) \
|
||||
{ \
|
||||
print_color_##type_name(t, COLOR_NONE, key, fmt, value); \
|
||||
return print_color_##type_name(t, COLOR_NONE, key, fmt, \
|
||||
value); \
|
||||
}
|
||||
|
||||
/* These functions return 0 if printing to a JSON context, number of
|
||||
* characters printed otherwise (as calculated by printf(3)).
|
||||
*/
|
||||
_PRINT_FUNC(int, int)
|
||||
_PRINT_FUNC(s64, int64_t)
|
||||
_PRINT_FUNC(bool, bool)
|
||||
|
|
|
|||
|
|
@ -1131,7 +1131,8 @@ static int xfrm_state_keep(struct nlmsghdr *n, void *arg)
|
|||
if (!xfrm_state_filter_match(xsinfo))
|
||||
return 0;
|
||||
|
||||
if (xsinfo->id.proto == IPPROTO_IPIP)
|
||||
if (xsinfo->id.proto == IPPROTO_IPIP ||
|
||||
xsinfo->id.proto == IPPROTO_IPV6)
|
||||
return 0;
|
||||
|
||||
if (xb->offset > xb->size) {
|
||||
|
|
|
|||
|
|
@ -123,20 +123,22 @@ void close_json_array(enum output_type type, const char *str)
|
|||
*/
|
||||
#define _PRINT_FUNC(type_name, type) \
|
||||
__attribute__((format(printf, 4, 0))) \
|
||||
void print_color_##type_name(enum output_type t, \
|
||||
enum color_attr color, \
|
||||
const char *key, \
|
||||
const char *fmt, \
|
||||
type value) \
|
||||
int print_color_##type_name(enum output_type t, \
|
||||
enum color_attr color, \
|
||||
const char *key, \
|
||||
const char *fmt, \
|
||||
type value) \
|
||||
{ \
|
||||
int ret = 0; \
|
||||
if (_IS_JSON_CONTEXT(t)) { \
|
||||
if (!key) \
|
||||
jsonw_##type_name(_jw, value); \
|
||||
else \
|
||||
jsonw_##type_name##_field(_jw, key, value); \
|
||||
} else if (_IS_FP_CONTEXT(t)) { \
|
||||
color_fprintf(stdout, color, fmt, value); \
|
||||
ret = color_fprintf(stdout, color, fmt, value); \
|
||||
} \
|
||||
return ret; \
|
||||
}
|
||||
_PRINT_FUNC(int, int);
|
||||
_PRINT_FUNC(s64, int64_t);
|
||||
|
|
@ -162,12 +164,14 @@ _PRINT_NAME_VALUE_FUNC(uint, unsigned int, u);
|
|||
_PRINT_NAME_VALUE_FUNC(string, const char*, s);
|
||||
#undef _PRINT_NAME_VALUE_FUNC
|
||||
|
||||
void print_color_string(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
const char *value)
|
||||
int print_color_string(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
const char *value)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (_IS_JSON_CONTEXT(type)) {
|
||||
if (key && !value)
|
||||
jsonw_name(_jw, key);
|
||||
|
|
@ -176,8 +180,10 @@ void print_color_string(enum output_type type,
|
|||
else
|
||||
jsonw_string_field(_jw, key, value);
|
||||
} else if (_IS_FP_CONTEXT(type)) {
|
||||
color_fprintf(stdout, color, fmt, value);
|
||||
ret = color_fprintf(stdout, color, fmt, value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -185,47 +191,58 @@ void print_color_string(enum output_type type,
|
|||
* a value to it, you will need to use "is_json_context()" to have different
|
||||
* branch for json and regular output. grep -r "print_bool" for example
|
||||
*/
|
||||
void print_color_bool(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
bool value)
|
||||
int print_color_bool(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
bool value)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (_IS_JSON_CONTEXT(type)) {
|
||||
if (key)
|
||||
jsonw_bool_field(_jw, key, value);
|
||||
else
|
||||
jsonw_bool(_jw, value);
|
||||
} else if (_IS_FP_CONTEXT(type)) {
|
||||
color_fprintf(stdout, color, fmt, value ? "true" : "false");
|
||||
ret = color_fprintf(stdout, color, fmt,
|
||||
value ? "true" : "false");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* In JSON context uses hardcode %#x format: 42 -> 0x2a
|
||||
*/
|
||||
void print_color_0xhex(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
unsigned long long hex)
|
||||
int print_color_0xhex(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
unsigned long long hex)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (_IS_JSON_CONTEXT(type)) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
snprintf(b1, sizeof(b1), "%#llx", hex);
|
||||
print_string(PRINT_JSON, key, NULL, b1);
|
||||
} else if (_IS_FP_CONTEXT(type)) {
|
||||
color_fprintf(stdout, color, fmt, hex);
|
||||
ret = color_fprintf(stdout, color, fmt, hex);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void print_color_hex(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
unsigned int hex)
|
||||
int print_color_hex(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
unsigned int hex)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (_IS_JSON_CONTEXT(type)) {
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
|
|
@ -235,28 +252,34 @@ void print_color_hex(enum output_type type,
|
|||
else
|
||||
jsonw_string(_jw, b1);
|
||||
} else if (_IS_FP_CONTEXT(type)) {
|
||||
color_fprintf(stdout, color, fmt, hex);
|
||||
ret = color_fprintf(stdout, color, fmt, hex);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* In JSON context we don't use the argument "value" we simply call jsonw_null
|
||||
* whereas FP context can use "value" to output anything
|
||||
*/
|
||||
void print_color_null(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
const char *value)
|
||||
int print_color_null(enum output_type type,
|
||||
enum color_attr color,
|
||||
const char *key,
|
||||
const char *fmt,
|
||||
const char *value)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (_IS_JSON_CONTEXT(type)) {
|
||||
if (key)
|
||||
jsonw_null_field(_jw, key);
|
||||
else
|
||||
jsonw_null(_jw);
|
||||
} else if (_IS_FP_CONTEXT(type)) {
|
||||
color_fprintf(stdout, color, fmt, value);
|
||||
ret = color_fprintf(stdout, color, fmt, value);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Print line separator (if not in JSON mode) */
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
# these pages are built
|
||||
ip-address.8
|
||||
ip-link.8
|
||||
ip-netns.8
|
||||
ip-route.8
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
TARGETS = ip-address.8 ip-link.8 ip-route.8
|
||||
TARGETS = ip-address.8 ip-link.8 ip-netns.8 ip-route.8
|
||||
|
||||
MAN8PAGES = $(TARGETS) $(filter-out $(TARGETS),$(wildcard *.8))
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
ip-address.8: ip-address.8.in
|
||||
sed "s|@SYSCONFDIR@|$(CONFDIR)|g" $< > $@
|
||||
|
||||
ip-link.8: ip-link.8.in
|
||||
sed "s|@SYSCONFDIR@|$(CONFDIR)|g" $< > $@
|
||||
|
||||
ip-route.8: ip-route.8.in
|
||||
sed "s|@SYSCONFDIR@|$(CONFDIR)|g" $< > $@
|
||||
%: %.in
|
||||
sed \
|
||||
-e "s|@NETNS_ETC_DIR@|$(NETNS_ETC_DIR)|g" \
|
||||
-e "s|@NETNS_RUN_DIR@|$(NETNS_RUN_DIR)|g" \
|
||||
-e "s|@SYSCONFDIR@|$(CONFDIR)|g" \
|
||||
$< > $@
|
||||
|
||||
distclean: clean
|
||||
|
||||
|
|
|
|||
|
|
@ -289,36 +289,49 @@ the STP path cost of the specified port.
|
|||
.BI priority " PRIO "
|
||||
the STP port priority. The priority value is an unsigned 8-bit quantity
|
||||
(number between 0 and 255). This metric is used in the designated port an
|
||||
droot port selectio algorithms.
|
||||
droot port selection algorithms.
|
||||
|
||||
.TP
|
||||
.BI state " STATE "
|
||||
the operation state of the port. This is primarily used by user space STP/RSTP
|
||||
implementation. One may enter a lowercased port state name, or one of the
|
||||
the operation state of the port. Except state 0 (disable STP or BPDU filter feature),
|
||||
this is primarily used by user space STP/RSTP
|
||||
implementation. One may enter port state name (case insensitive), or one of the
|
||||
numbers below. Negative inputs are ignored, and unrecognized names return an
|
||||
error.
|
||||
|
||||
.B 0
|
||||
- port is DISABLED. Make this port completely inactive.
|
||||
- port is in STP
|
||||
.B DISABLED
|
||||
state. Make this port completely inactive for STP. This is also called
|
||||
BPDU filter and could be used to disable STP on an untrusted port, like
|
||||
a leaf virtual devices.
|
||||
.sp
|
||||
|
||||
.B 1
|
||||
- STP LISTENING state. Only valid if STP is enabled on the bridge. In this
|
||||
- port is in STP
|
||||
.B LISTENING
|
||||
state. Only valid if STP is enabled on the bridge. In this
|
||||
state the port listens for STP BPDUs and drops all other traffic frames.
|
||||
.sp
|
||||
|
||||
.B 2
|
||||
- STP LEARNING state. Only valid if STP is enabled on the bridge. In this
|
||||
- port is in STP
|
||||
.B LEARNING
|
||||
state. Only valid if STP is enabled on the bridge. In this
|
||||
state the port will accept traffic only for the purpose of updating MAC
|
||||
address tables.
|
||||
.sp
|
||||
|
||||
.B 3
|
||||
- STP FORWARDING state. Port is fully active.
|
||||
- port is in STP
|
||||
.B FORWARDING
|
||||
state. Port is fully active.
|
||||
.sp
|
||||
|
||||
.B 4
|
||||
- STP BLOCKING state. Only valid if STP is enabled on the bridge. This state
|
||||
- port is in STP
|
||||
.B BLOCKING
|
||||
state. Only valid if STP is enabled on the bridge. This state
|
||||
is used during the STP election process. In this state, port will only process
|
||||
STP BPDUs.
|
||||
.sp
|
||||
|
|
@ -327,12 +340,25 @@ STP BPDUs.
|
|||
.BR "guard on " or " guard off "
|
||||
Controls whether STP BPDUs will be processed by the bridge port. By default,
|
||||
the flag is turned off allowed BPDU processing. Turning this flag on will
|
||||
cause the port to stop processing STP BPDUs.
|
||||
disables
|
||||
the bridge port if a STP BPDU packet is received.
|
||||
|
||||
If running Spanning Tree on bridge, hostile devices on the network
|
||||
may send BPDU on a port and cause network failure. Setting
|
||||
.B guard on
|
||||
will detect and stop this by disabling the port.
|
||||
The port will be restarted if link is brought down, or
|
||||
removed and reattached. For example if guard is enable on
|
||||
eth0:
|
||||
|
||||
.B ip link set dev eth0 down; ip link set dev eth0 up
|
||||
|
||||
.TP
|
||||
.BR "hairpin on " or " hairpin off "
|
||||
Controls whether traffic may be send back out of the port on which it was
|
||||
received. By default, this flag is turned off and the bridge will not forward
|
||||
received. This option is also called reflective relay mode, and is used to support
|
||||
basic VEPA (Virtual Ethernet Port Aggregator) capabilities.
|
||||
By default, this flag is turned off and the bridge will not forward
|
||||
traffic back out of the receiving port.
|
||||
|
||||
.TP
|
||||
|
|
@ -346,6 +372,11 @@ enabled on the bridge. By default the flag is off.
|
|||
Controls whether a given port is allowed to become root port or not. Only used
|
||||
when STP is enabled on the bridge. By default the flag is off.
|
||||
|
||||
This feature is also called root port guard.
|
||||
If BPDU is received from a leaf (edge) port, it should not
|
||||
be elected as root port. This could be used if using STP on a bridge and the downstream bridges are not fully
|
||||
trusted; this prevents a hostile guest from rerouting traffic.
|
||||
|
||||
.TP
|
||||
.BR "learning on " or " learning off "
|
||||
Controls whether a given port will learn MAC addresses from received traffic or
|
||||
|
|
@ -383,6 +414,32 @@ there is no MDB entry. By default this flag is on.
|
|||
Controls whether a given port will replicate packets using unicast
|
||||
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
|
||||
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
|
||||
previously.
|
||||
|
||||
This feature is intended for interface types which have a more reliable
|
||||
and/or efficient way to deliver unicast packets than broadcast ones
|
||||
(e.g. WiFi).
|
||||
|
||||
However, it should only be enabled on interfaces where no IGMPv2/MLDv1
|
||||
report suppression takes place. IGMP/MLD report suppression issue is usually
|
||||
overcome by the network daemon (supplicant) enabling AP isolation and
|
||||
by that separating all STAs.
|
||||
|
||||
Delivery of STA-to-STA IP multicast is made possible again by
|
||||
enabling and utilizing the bridge hairpin mode, which considers the
|
||||
incoming port as a potential outgoing port, too (see
|
||||
.B hairpin
|
||||
option).
|
||||
Hairpin mode is performed after multicast snooping, therefore leading to
|
||||
only deliver reports to STAs running a multicast router.
|
||||
|
||||
.TP
|
||||
.BR "neigh_suppress on " or " neigh_suppress off "
|
||||
Controls whether neigh discovery (arp and nd) proxy and suppression is
|
||||
|
|
@ -472,7 +529,7 @@ the interface to which this address is associated.
|
|||
.B router
|
||||
- the destination address is associated with a router.
|
||||
Valid if the referenced device is a VXLAN type device and has
|
||||
route shortcircuit enabled.
|
||||
route short circuit enabled.
|
||||
.sp
|
||||
|
||||
.B use
|
||||
|
|
|
|||
|
|
@ -61,9 +61,9 @@ By default a process inherits its network namespace from its parent. Initially a
|
|||
the processes share the same default network namespace from the init process.
|
||||
|
||||
By convention a named network namespace is an object at
|
||||
.BR "/var/run/netns/" NAME
|
||||
.BR "@NETNS_RUN_DIR@/" NAME
|
||||
that can be opened. The file descriptor resulting from opening
|
||||
.BR "/var/run/netns/" NAME
|
||||
.BR "@NETNS_RUN_DIR@/" NAME
|
||||
refers to the specified network namespace. Holding that file
|
||||
descriptor open keeps the network namespace alive. The file
|
||||
descriptor can be used with the
|
||||
|
|
@ -72,13 +72,13 @@ system call to change the network namespace associated with a task.
|
|||
|
||||
For applications that are aware of network namespaces, the convention
|
||||
is to look for global network configuration files first in
|
||||
.BR "/etc/netns/" NAME "/"
|
||||
.BR "@NETNS_ETC_DIR@/" NAME "/"
|
||||
then in
|
||||
.BR "/etc/".
|
||||
For example, if you want a different version of
|
||||
.BR /etc/resolv.conf
|
||||
for a network namespace used to isolate your vpn you would name it
|
||||
.BR /etc/netns/myvpn/resolv.conf.
|
||||
.BR @NETNS_ETC_DIR@/myvpn/resolv.conf.
|
||||
|
||||
.B ip netns exec
|
||||
automates handling of this configuration, file convention for network
|
||||
|
|
@ -89,24 +89,24 @@ their traditional location in /etc.
|
|||
.TP
|
||||
.B ip netns list - show all of the named network namespaces
|
||||
.sp
|
||||
This command displays all of the network namespaces in /var/run/netns
|
||||
This command displays all of the network namespaces in @NETNS_RUN_DIR@
|
||||
|
||||
.TP
|
||||
.B ip netns add NAME - create a new named network namespace
|
||||
.sp
|
||||
If NAME is available in /var/run/netns/ this command creates a new
|
||||
If NAME is available in @NETNS_RUN_DIR@ this command creates a new
|
||||
network namespace and assigns NAME.
|
||||
|
||||
.TP
|
||||
.B ip netns attach NAME PID - create a new named network namespace
|
||||
.sp
|
||||
If NAME is available in /var/run/netns/ this command attaches the network
|
||||
If NAME is available in @NETNS_RUN_DIR@ this command attaches the network
|
||||
namespace of the process PID to NAME as if it were created with ip netns.
|
||||
|
||||
.TP
|
||||
.B ip [-all] netns delete [ NAME ] - delete the name of a network namespace(s)
|
||||
.sp
|
||||
If NAME is present in /var/run/netns it is umounted and the mount
|
||||
If NAME is present in @NETNS_RUN_DIR@ it is umounted and the mount
|
||||
point is removed. If this is the last user of the network namespace the
|
||||
network namespace will be freed and all physical devices will be moved to the
|
||||
default one, otherwise the network namespace persists until it has no more
|
||||
|
|
@ -160,7 +160,7 @@ Once it is assigned, it's not possible to change it.
|
|||
.TP
|
||||
.B ip netns identify [PID] - Report network namespaces names for process
|
||||
.sp
|
||||
This command walks through /var/run/netns and finds all the network
|
||||
This command walks through @NETNS_RUN_DIR@ and finds all the network
|
||||
namespace names for network namespace of the specified process, if PID is
|
||||
not specified then the current process will be used.
|
||||
|
||||
|
|
@ -201,7 +201,7 @@ and prints a line for each event it sees.
|
|||
.sp
|
||||
Network namespace ids are used to identify a peer network namespace. This
|
||||
command displays nsids of the current network namespace and provides the
|
||||
corresponding iproute2 netns name (from /var/run/netns) if any.
|
||||
corresponding iproute2 netns name (from @NETNS_RUN_DIR@) if any.
|
||||
|
||||
The
|
||||
.B target-nsid
|
||||
|
|
@ -177,7 +177,7 @@ static void print_hw_stats(const struct rtattr *arg, bool print_used)
|
|||
print_string(PRINT_ANY, NULL, " %s", item->str);
|
||||
}
|
||||
close_json_array(PRINT_JSON, NULL);
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
}
|
||||
|
||||
static int parse_hw_stats(const char *str, struct nlmsghdr *n)
|
||||
|
|
@ -291,7 +291,8 @@ done0:
|
|||
invarg(cookie_err_m, *argv);
|
||||
}
|
||||
|
||||
if (hex2mem(*argv, act_ck, slen / 2) < 0)
|
||||
if (slen % 2 ||
|
||||
hex2mem(*argv, act_ck, slen / 2) < 0)
|
||||
invarg("cookie must be a hex string\n",
|
||||
*argv);
|
||||
|
||||
|
|
@ -375,11 +376,11 @@ static int tc_print_one_action(FILE *f, struct rtattr *arg)
|
|||
|
||||
if (show_stats && tb[TCA_ACT_STATS]) {
|
||||
print_string(PRINT_FP, NULL, "\tAction statistics:", NULL);
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
open_json_object("stats");
|
||||
print_tcstats2_attr(f, tb[TCA_ACT_STATS], "\t", NULL);
|
||||
close_json_object();
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
}
|
||||
if (tb[TCA_ACT_COOKIE]) {
|
||||
int strsz = RTA_PAYLOAD(tb[TCA_ACT_COOKIE]);
|
||||
|
|
@ -388,7 +389,7 @@ static int tc_print_one_action(FILE *f, struct rtattr *arg)
|
|||
print_string(PRINT_ANY, "cookie", "\tcookie %s",
|
||||
hexstring_n2a(RTA_DATA(tb[TCA_ACT_COOKIE]),
|
||||
strsz, b1, sizeof(b1)));
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
}
|
||||
if (tb[TCA_ACT_FLAGS]) {
|
||||
struct nla_bitfield32 *flags = RTA_DATA(tb[TCA_ACT_FLAGS]);
|
||||
|
|
@ -397,7 +398,7 @@ static int tc_print_one_action(FILE *f, struct rtattr *arg)
|
|||
print_bool(PRINT_ANY, "no_percpu", "\tno_percpu",
|
||||
flags->value &
|
||||
TCA_ACT_FLAGS_NO_PERCPU_STATS);
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
}
|
||||
if (tb[TCA_ACT_HW_STATS])
|
||||
print_hw_stats(tb[TCA_ACT_HW_STATS], false);
|
||||
|
|
@ -457,7 +458,7 @@ tc_print_action(FILE *f, const struct rtattr *arg, unsigned short tot_acts)
|
|||
for (i = 0; i <= tot_acts; i++) {
|
||||
if (tb[i]) {
|
||||
open_json_object(NULL);
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "order",
|
||||
"\taction order %u: ", i);
|
||||
if (tc_print_one_action(f, tb[i]) < 0) {
|
||||
|
|
@ -496,7 +497,7 @@ int print_action(struct nlmsghdr *n, void *arg)
|
|||
open_json_object(NULL);
|
||||
print_uint(PRINT_ANY, "total acts", "total acts %u",
|
||||
tot_acts ? *tot_acts : 0);
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
close_json_object();
|
||||
if (tb[TCA_ACT_TAB] == NULL) {
|
||||
if (n->nlmsg_type != RTM_GETACTION)
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ static int print_connmark(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
print_uint(PRINT_ANY, "zone", "zone %u", ci->zone);
|
||||
print_action_control(f, " ", ci->action, "");
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "index", "\t index %u", ci->index);
|
||||
print_int(PRINT_ANY, "ref", " ref %d", ci->refcnt);
|
||||
print_int(PRINT_ANY, "bind", " bind %d", ci->bindcnt);
|
||||
|
|
@ -137,7 +137,7 @@ static int print_connmark(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
print_tm(f, tm);
|
||||
}
|
||||
}
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ static int print_ctinfo(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
print_hu(PRINT_ANY, "zone", "zone %u", zone);
|
||||
print_action_control(f, " ", ci->action, "");
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "index", "\t index %u", ci->index);
|
||||
print_int(PRINT_ANY, "ref", " ref %d", ci->refcnt);
|
||||
print_int(PRINT_ANY, "bind", " bind %d", ci->bindcnt);
|
||||
|
|
@ -256,7 +256,7 @@ static int print_ctinfo(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
if (show_stats)
|
||||
print_ctinfo_stats(f, tb);
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ static int print_ife(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
sizeof(b2)));
|
||||
}
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "index", "\t index %u", p->index);
|
||||
print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
|
||||
print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
|
||||
|
|
@ -324,7 +324,7 @@ static int print_ife(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
}
|
||||
}
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ static int print_mpls(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
}
|
||||
}
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ print_nat(struct action_util *au, FILE * f, struct rtattr *arg)
|
|||
format_host_r(AF_INET, 4, &sel->new_addr, buf1, sizeof(buf1)));
|
||||
|
||||
print_action_control(f, " ", sel->action, "");
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "index", "\t index %u", sel->index);
|
||||
print_int(PRINT_ANY, "ref", " ref %d", sel->refcnt);
|
||||
print_int(PRINT_ANY, "bind", " bind %d", sel->bindcnt);
|
||||
|
|
@ -185,7 +185,7 @@ print_nat(struct action_util *au, FILE * f, struct rtattr *arg)
|
|||
}
|
||||
}
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ static int print_sample(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
|
||||
print_action_control(f, " ", p->action, "");
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "index", "\t index %u", p->index);
|
||||
print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
|
||||
print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
|
||||
|
|
@ -179,7 +179,7 @@ static int print_sample(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
print_tm(f, tm);
|
||||
}
|
||||
}
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ static int print_skbedit(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
|
||||
print_action_control(f, " ", p->action, "");
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "index", "\t index %u", p->index);
|
||||
print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
|
||||
print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
|
||||
|
|
@ -267,7 +267,7 @@ static int print_skbedit(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
}
|
||||
}
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -489,7 +489,7 @@ static void tunnel_key_print_ip_addr(FILE *f, const char *name,
|
|||
else
|
||||
return;
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
if (matches(name, "src_ip") == 0)
|
||||
print_string(PRINT_ANY, "src_ip", "\tsrc_ip %s",
|
||||
rt_addr_n2a_rta(family, attr));
|
||||
|
|
@ -503,7 +503,7 @@ static void tunnel_key_print_key_id(FILE *f, const char *name,
|
|||
{
|
||||
if (!attr)
|
||||
return;
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "key_id", "\tkey_id %u", rta_getattr_be32(attr));
|
||||
}
|
||||
|
||||
|
|
@ -512,7 +512,7 @@ static void tunnel_key_print_dst_port(FILE *f, char *name,
|
|||
{
|
||||
if (!attr)
|
||||
return;
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "dst_port", "\tdst_port %u",
|
||||
rta_getattr_be16(attr));
|
||||
}
|
||||
|
|
@ -523,7 +523,7 @@ static void tunnel_key_print_flag(FILE *f, const char *name_on,
|
|||
{
|
||||
if (!attr)
|
||||
return;
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_string(PRINT_ANY, "flag", "\t%s",
|
||||
rta_getattr_u8(attr) ? name_on : name_off);
|
||||
}
|
||||
|
|
@ -655,11 +655,11 @@ static void tunnel_key_print_tos_ttl(FILE *f, char *name,
|
|||
return;
|
||||
|
||||
if (matches(name, "tos") == 0 && rta_getattr_u8(attr) != 0) {
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "tos", "\ttos 0x%x",
|
||||
rta_getattr_u8(attr));
|
||||
} else if (matches(name, "ttl") == 0 && rta_getattr_u8(attr) != 0) {
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "ttl", "\tttl %u",
|
||||
rta_getattr_u8(attr));
|
||||
}
|
||||
|
|
@ -712,7 +712,7 @@ static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
}
|
||||
print_action_control(f, " ", parm->action, "");
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_uint(PRINT_ANY, "index", "\t index %u", parm->index);
|
||||
print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
|
||||
print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);
|
||||
|
|
@ -725,7 +725,7 @@ static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg)
|
|||
}
|
||||
}
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
15
tc/q_cake.c
15
tc/q_cake.c
|
|
@ -97,6 +97,7 @@ static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
|||
unsigned int interval = 0;
|
||||
unsigned int diffserv = 0;
|
||||
unsigned int memlimit = 0;
|
||||
unsigned int fwmark = 0;
|
||||
unsigned int target = 0;
|
||||
__u64 bandwidth = 0;
|
||||
int ack_filter = -1;
|
||||
|
|
@ -107,7 +108,6 @@ static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
|||
int autorate = -1;
|
||||
int ingress = -1;
|
||||
int overhead = 0;
|
||||
int fwmark = -1;
|
||||
int wash = -1;
|
||||
int nat = -1;
|
||||
int atm = -1;
|
||||
|
|
@ -335,15 +335,12 @@ static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
|||
return -1;
|
||||
}
|
||||
} else if (strcmp(*argv, "fwmark") == 0) {
|
||||
unsigned int fwm;
|
||||
|
||||
NEXT_ARG();
|
||||
if (get_u32(&fwm, *argv, 0)) {
|
||||
if (get_u32(&fwmark, *argv, 0)) {
|
||||
fprintf(stderr,
|
||||
"Illegal value for \"fwmark\": \"%s\"\n", *argv);
|
||||
return -1;
|
||||
}
|
||||
fwmark = fwm;
|
||||
} else if (strcmp(*argv, "help") == 0) {
|
||||
explain();
|
||||
return -1;
|
||||
|
|
@ -388,7 +385,7 @@ static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
|||
if (memlimit)
|
||||
addattr_l(n, 1024, TCA_CAKE_MEMORY, &memlimit,
|
||||
sizeof(memlimit));
|
||||
if (fwmark != -1)
|
||||
if (fwmark)
|
||||
addattr_l(n, 1024, TCA_CAKE_FWMARK, &fwmark,
|
||||
sizeof(fwmark));
|
||||
if (nat != -1)
|
||||
|
|
@ -523,6 +520,10 @@ static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
|||
RTA_PAYLOAD(tb[TCA_CAKE_RTT]) >= sizeof(__u32)) {
|
||||
interval = rta_getattr_u32(tb[TCA_CAKE_RTT]);
|
||||
}
|
||||
if (tb[TCA_CAKE_MEMORY] &&
|
||||
RTA_PAYLOAD(tb[TCA_CAKE_MEMORY]) >= sizeof(__u32)) {
|
||||
memlimit = rta_getattr_u32(tb[TCA_CAKE_MEMORY]);
|
||||
}
|
||||
if (tb[TCA_CAKE_FWMARK] &&
|
||||
RTA_PAYLOAD(tb[TCA_CAKE_FWMARK]) >= sizeof(__u32)) {
|
||||
fwmark = rta_getattr_u32(tb[TCA_CAKE_FWMARK]);
|
||||
|
|
@ -575,7 +576,7 @@ static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
|||
|
||||
if (memlimit) {
|
||||
print_uint(PRINT_JSON, "memlimit", NULL, memlimit);
|
||||
print_string(PRINT_FP, NULL, "memlimit %s",
|
||||
print_string(PRINT_FP, NULL, "memlimit %s ",
|
||||
sprint_size(memlimit, b1));
|
||||
}
|
||||
|
||||
|
|
|
|||
27
tc/q_fq.c
27
tc/q_fq.c
|
|
@ -57,6 +57,7 @@ static void explain(void)
|
|||
" [ [no]pacing ] [ refill_delay TIME ]\n"
|
||||
" [ low_rate_threshold RATE ]\n"
|
||||
" [ orphan_mask MASK]\n"
|
||||
" [ timer_slack TIME]\n"
|
||||
" [ ce_threshold TIME ]\n");
|
||||
}
|
||||
|
||||
|
|
@ -86,6 +87,7 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
|||
unsigned int refill_delay;
|
||||
unsigned int orphan_mask;
|
||||
unsigned int ce_threshold;
|
||||
unsigned int timer_slack;
|
||||
bool set_plimit = false;
|
||||
bool set_flow_plimit = false;
|
||||
bool set_quantum = false;
|
||||
|
|
@ -96,6 +98,7 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
|||
bool set_orphan_mask = false;
|
||||
bool set_low_rate_threshold = false;
|
||||
bool set_ce_threshold = false;
|
||||
bool set_timer_slack = false;
|
||||
int pacing = -1;
|
||||
struct rtattr *tail;
|
||||
|
||||
|
|
@ -146,6 +149,20 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
|||
return -1;
|
||||
}
|
||||
set_ce_threshold = true;
|
||||
} else if (strcmp(*argv, "timer_slack") == 0) {
|
||||
__s64 t64;
|
||||
|
||||
NEXT_ARG();
|
||||
if (get_time64(&t64, *argv)) {
|
||||
fprintf(stderr, "Illegal \"timer_slack\"\n");
|
||||
return -1;
|
||||
}
|
||||
timer_slack = t64;
|
||||
if (timer_slack != t64) {
|
||||
fprintf(stderr, "Illegal (out of range) \"timer_slack\"\n");
|
||||
return -1;
|
||||
}
|
||||
set_timer_slack = true;
|
||||
} else if (strcmp(*argv, "defrate") == 0) {
|
||||
NEXT_ARG();
|
||||
if (strchr(*argv, '%')) {
|
||||
|
|
@ -240,6 +257,9 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
|||
if (set_ce_threshold)
|
||||
addattr_l(n, 1024, TCA_FQ_CE_THRESHOLD,
|
||||
&ce_threshold, sizeof(ce_threshold));
|
||||
if (set_timer_slack)
|
||||
addattr_l(n, 1024, TCA_FQ_TIMER_SLACK,
|
||||
&timer_slack, sizeof(timer_slack));
|
||||
addattr_nest_end(n, tail);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -254,6 +274,7 @@ static int fq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
|||
unsigned int refill_delay;
|
||||
unsigned int orphan_mask;
|
||||
unsigned int ce_threshold;
|
||||
unsigned int timer_slack;
|
||||
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
|
|
@ -355,6 +376,12 @@ static int fq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
|||
}
|
||||
}
|
||||
|
||||
if (tb[TCA_FQ_TIMER_SLACK] &&
|
||||
RTA_PAYLOAD(tb[TCA_FQ_TIMER_SLACK]) >= sizeof(__u32)) {
|
||||
timer_slack = rta_getattr_u32(tb[TCA_FQ_TIMER_SLACK]);
|
||||
fprintf(f, "timer_slack %s ", sprint_time64(timer_slack, b1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,12 +54,14 @@ static void explain(void)
|
|||
"[ memory_limit BYTES ]\n"
|
||||
"[ target TIME ] [ interval TIME ]\n"
|
||||
"[ quantum BYTES ] [ [no]ecn ]\n"
|
||||
"[ ce_threshold TIME ]\n");
|
||||
"[ ce_threshold TIME ]\n"
|
||||
"[ drop_batch SIZE ]\n");
|
||||
}
|
||||
|
||||
static int fq_codel_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
||||
struct nlmsghdr *n, const char *dev)
|
||||
{
|
||||
unsigned int drop_batch = 0;
|
||||
unsigned int limit = 0;
|
||||
unsigned int flows = 0;
|
||||
unsigned int target = 0;
|
||||
|
|
@ -89,6 +91,12 @@ static int fq_codel_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
|||
fprintf(stderr, "Illegal \"quantum\"\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp(*argv, "drop_batch") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_unsigned(&drop_batch, *argv, 0)) {
|
||||
fprintf(stderr, "Illegal \"drop_batch\"\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (strcmp(*argv, "target") == 0) {
|
||||
NEXT_ARG();
|
||||
if (get_time(&target, *argv)) {
|
||||
|
|
@ -147,6 +155,8 @@ static int fq_codel_parse_opt(struct qdisc_util *qu, int argc, char **argv,
|
|||
if (memory != ~0U)
|
||||
addattr_l(n, 1024, TCA_FQ_CODEL_MEMORY_LIMIT,
|
||||
&memory, sizeof(memory));
|
||||
if (drop_batch)
|
||||
addattr_l(n, 1024, TCA_FQ_CODEL_DROP_BATCH_SIZE, &drop_batch, sizeof(drop_batch));
|
||||
|
||||
addattr_nest_end(n, tail);
|
||||
return 0;
|
||||
|
|
@ -163,6 +173,7 @@ static int fq_codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt
|
|||
unsigned int quantum;
|
||||
unsigned int ce_threshold;
|
||||
unsigned int memory_limit;
|
||||
unsigned int drop_batch;
|
||||
|
||||
SPRINT_BUF(b1);
|
||||
|
||||
|
|
@ -220,6 +231,12 @@ static int fq_codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt
|
|||
if (ecn)
|
||||
print_bool(PRINT_ANY, "ecn", "ecn ", true);
|
||||
}
|
||||
if (tb[TCA_FQ_CODEL_DROP_BATCH_SIZE] &&
|
||||
RTA_PAYLOAD(tb[TCA_FQ_CODEL_DROP_BATCH_SIZE]) >= sizeof(__u32)) {
|
||||
drop_batch = rta_getattr_u32(tb[TCA_FQ_CODEL_DROP_BATCH_SIZE]);
|
||||
if (drop_batch)
|
||||
print_uint(PRINT_ANY, "drop_batch", "drop_batch %u ", drop_batch);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -264,7 +281,7 @@ static int fq_codel_print_xstats(struct qdisc_util *qu, FILE *f,
|
|||
st->qdisc_stats.old_flows_len);
|
||||
}
|
||||
if (st->type == TCA_FQ_CODEL_XSTATS_CLASS) {
|
||||
print_uint(PRINT_ANY, "deficit", " deficit %u",
|
||||
print_int(PRINT_ANY, "deficit", " deficit %d",
|
||||
st->class_stats.deficit);
|
||||
print_uint(PRINT_ANY, "count", " count %u",
|
||||
st->class_stats.count);
|
||||
|
|
|
|||
|
|
@ -368,7 +368,7 @@ static int print_sched_list(FILE *f, struct rtattr *list)
|
|||
|
||||
open_json_array(PRINT_JSON, "schedule");
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
|
||||
for (item = RTA_DATA(list); RTA_OK(item, rem); item = RTA_NEXT(item, rem)) {
|
||||
struct rtattr *tb[TCA_TAPRIO_SCHED_ENTRY_MAX + 1];
|
||||
|
|
@ -396,7 +396,7 @@ static int print_sched_list(FILE *f, struct rtattr *list)
|
|||
print_uint(PRINT_ANY, "interval", " interval %u", interval);
|
||||
close_json_object();
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
}
|
||||
|
||||
close_json_array(PRINT_ANY, "");
|
||||
|
|
@ -454,7 +454,7 @@ static int taprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
|||
print_uint(PRINT_ANY, NULL, " %u", qopt->prio_tc_map[i]);
|
||||
close_json_array(PRINT_ANY, "");
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
|
||||
open_json_array(PRINT_ANY, "queues");
|
||||
for (i = 0; i < qopt->num_tc; i++) {
|
||||
|
|
@ -465,7 +465,7 @@ static int taprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
|
|||
}
|
||||
close_json_array(PRINT_ANY, "");
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
|
||||
if (tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID])
|
||||
clockid = rta_getattr_s32(tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID]);
|
||||
|
|
|
|||
|
|
@ -385,6 +385,11 @@ int get_size(unsigned int *size, const char *str)
|
|||
}
|
||||
|
||||
*size = sz;
|
||||
|
||||
/* detect if an overflow happened */
|
||||
if (*size != floor(sz))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -783,7 +788,7 @@ static void print_tcstats_basic_hw(struct rtattr **tbs, char *prefix)
|
|||
sizeof(bs)));
|
||||
|
||||
if (bs.bytes >= bs_hw.bytes && bs.packets >= bs_hw.packets) {
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_string(PRINT_FP, NULL, "%s", prefix);
|
||||
print_lluint(PRINT_ANY, "sw_bytes",
|
||||
"Sent software %llu bytes",
|
||||
|
|
@ -793,7 +798,7 @@ static void print_tcstats_basic_hw(struct rtattr **tbs, char *prefix)
|
|||
}
|
||||
}
|
||||
|
||||
print_string(PRINT_FP, NULL, "%s", _SL_);
|
||||
print_nl();
|
||||
print_string(PRINT_FP, NULL, "%s", prefix);
|
||||
print_lluint(PRINT_ANY, "hw_bytes", "Sent hardware %llu bytes",
|
||||
bs_hw.bytes);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
#!/bin/sh
|
||||
|
||||
. lib/generic.sh
|
||||
|
||||
ts_log "[Testing vlan show]"
|
||||
|
||||
BR_DEV="$(rand_dev)"
|
||||
VX0_DEV="$(rand_dev)"
|
||||
VX1_DEV="$(rand_dev)"
|
||||
|
||||
ts_ip "$0" "Add $BR_DEV bridge interface" link add $BR_DEV type bridge
|
||||
|
||||
ts_ip "$0" "Add $VX0_DEV vxlan interface" \
|
||||
link add $VX0_DEV type vxlan dstport 4789 external
|
||||
ts_ip "$0" "Enslave $VX0_DEV under $BR_DEV" \
|
||||
link set dev $VX0_DEV master $BR_DEV
|
||||
ts_bridge "$0" "Delete default vlan from $VX0_DEV" \
|
||||
vlan del dev $VX0_DEV vid 1
|
||||
ts_ip "$0" "Add $VX1_DEV vxlan interface" \
|
||||
link add $VX1_DEV type vxlan dstport 4790 external
|
||||
ts_ip "$0" "Enslave $VX1_DEV under $BR_DEV" \
|
||||
link set dev $VX1_DEV master $BR_DEV
|
||||
|
||||
# Test that bridge ports without vlans do not appear in the output
|
||||
ts_bridge "$0" "Show vlan" vlan
|
||||
test_on_not "$VX0_DEV"
|
||||
|
||||
# Test that bridge ports without tunnels do not appear in the output
|
||||
ts_bridge "$0" "Show vlan tunnel info" vlan tunnelshow
|
||||
test_lines_count 1 # header only
|
||||
|
|
@ -28,6 +28,6 @@ ts_bridge "$0" "Add tunnel with vni > 16k" \
|
|||
|
||||
ts_bridge "$0" "Show tunnel info" vlan tunnelshow dev $VX_DEV
|
||||
test_on "1030\s+65556"
|
||||
test_lines_count 5
|
||||
test_lines_count 4
|
||||
|
||||
ts_bridge "$0" "Dump tunnel info" -j vlan tunnelshow dev $VX_DEV
|
||||
|
|
|
|||
Loading…
Reference in New Issue