Merge branch 'iproute2-master' into iproute2-next

Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
David Ahern 2018-08-30 11:04:05 -07:00
commit c4e0ea8e9b
38 changed files with 434 additions and 177 deletions

View File

@ -96,7 +96,7 @@ snapshot:
> include/SNAPSHOT.h
clean:
@for i in $(SUBDIRS); \
@for i in $(SUBDIRS) testsuite; \
do $(MAKE) $(MFLAGS) -C $$i clean; done
clobber:

View File

@ -6,20 +6,20 @@
#define MDB_RTR_RTA(r) \
((struct rtattr *)(((char *)(r)) + RTA_ALIGN(sizeof(__u32))))
extern void print_vlan_info(FILE *fp, struct rtattr *tb);
extern int print_linkinfo(const struct sockaddr_nl *who,
void print_vlan_info(FILE *fp, struct rtattr *tb);
int print_linkinfo(const struct sockaddr_nl *who,
struct nlmsghdr *n,
void *arg);
extern int print_fdb(const struct sockaddr_nl *who,
int print_fdb(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
extern int print_mdb(const struct sockaddr_nl *who,
int print_mdb(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
extern int do_fdb(int argc, char **argv);
extern int do_mdb(int argc, char **argv);
extern int do_monitor(int argc, char **argv);
extern int do_vlan(int argc, char **argv);
extern int do_link(int argc, char **argv);
int do_fdb(int argc, char **argv);
int do_mdb(int argc, char **argv);
int do_monitor(int argc, char **argv);
int do_vlan(int argc, char **argv);
int do_link(int argc, char **argv);
extern int preferred_family;
extern int show_stats;

View File

@ -42,7 +42,7 @@ static void usage(void)
"where OBJECT := { link | fdb | mdb | vlan | monitor }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n"
" -o[neline] | -t[imestamp] | -n[etns] name |\n"
" -c[ompressvlans] -color -p[retty] -j{son} }\n");
" -c[ompressvlans] -color -p[retty] -j[son] }\n");
exit(-1);
}
@ -173,8 +173,7 @@ main(int argc, char **argv)
NEXT_ARG();
if (netns_switch(argv[1]))
exit(-1);
} else if (matches(opt, "-color") == 0) {
++color;
} else if (matches_color(opt, &color)) {
} else if (matches(opt, "-compressvlans") == 0) {
++compress_vlans;
} else if (matches(opt, "-force") == 0) {

View File

@ -5426,7 +5426,7 @@ static void help(void)
pr_err("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n"
" devlink [ -f[orce] ] -b[atch] filename\n"
"where OBJECT := { dev | port | sb | monitor | dpipe | resource | region }\n"
" OPTIONS := { -V[ersion] | -n[no-nice-names] | -j[json] | -p[pretty] | -v[verbose] }\n");
" OPTIONS := { -V[ersion] | -n[o-nice-names] | -j[son] | -p[retty] | -v[erbose] }\n");
}
static int dl_cmd(struct dl *dl, int argc, char **argv)

View File

@ -26,12 +26,12 @@
#include "utils.h"
#include "genl_utils.h"
int show_stats = 0;
int show_details = 0;
int show_raw = 0;
int show_stats;
int show_details;
int show_raw;
static void *BODY;
static struct genl_util * genl_list;
static struct genl_util *genl_list;
static int print_nofopt(const struct sockaddr_nl *who, struct nlmsghdr *n,
@ -44,8 +44,9 @@ static int print_nofopt(const struct sockaddr_nl *who, struct nlmsghdr *n,
static int parse_nofopt(struct genl_util *f, int argc, char **argv)
{
if (argc) {
fprintf(stderr, "Unknown genl \"%s\", hence option \"%s\" "
"is unparsable\n", f->name, *argv);
fprintf(stderr,
"Unknown genl \"%s\", hence option \"%s\" is unparsable\n",
f->name, *argv);
return -1;
}
@ -98,9 +99,10 @@ static void usage(void) __attribute__((noreturn));
static void usage(void)
{
fprintf(stderr, "Usage: genl [ OPTIONS ] OBJECT | help }\n"
"where OBJECT := { ctrl etc }\n"
" OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] }\n");
fprintf(stderr,
"Usage: genl [ OPTIONS ] OBJECT [help] }\n"
"where OBJECT := { ctrl etc }\n"
" OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -V[ersion] | -h[elp] }\n");
exit(-1);
}
@ -122,19 +124,21 @@ int main(int argc, char **argv)
} else if (matches(argv[1], "-help") == 0) {
usage();
} else {
fprintf(stderr, "Option \"%s\" is unknown, try "
"\"genl -help\".\n", argv[1]);
fprintf(stderr,
"Option \"%s\" is unknown, try \"genl -help\".\n",
argv[1]);
exit(-1);
}
argc--; argv++;
}
if (argc > 1) {
struct genl_util *a;
int ret;
struct genl_util *a = NULL;
a = get_genl_kind(argv[1]);
if (!a) {
fprintf(stderr,"bad genl %s\n", argv[1]);
fprintf(stderr, "bad genl %s\n", argv[1]);
exit(-1);
}

View File

@ -10,9 +10,10 @@ struct genl_util
struct genl_util *next;
char name[16];
int (*parse_genlopt)(struct genl_util *fu, int argc, char **argv);
int (*print_genlopt)(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
int (*print_genlopt)(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg);
};
extern int genl_ctrl_resolve_family(const char *family);
int genl_ctrl_resolve_family(const char *family);
#endif

View File

@ -2,6 +2,8 @@
#ifndef __COLOR_H__
#define __COLOR_H__ 1
#include <stdbool.h>
enum color_attr {
COLOR_IFNAME,
COLOR_MAC,
@ -12,8 +14,15 @@ enum color_attr {
COLOR_NONE
};
enum color_opt {
COLOR_OPT_NEVER = 0,
COLOR_OPT_AUTO = 1,
COLOR_OPT_ALWAYS = 2
};
void enable_color(void);
int check_enable_color(int color, int json);
bool check_enable_color(int color, int json);
bool matches_color(const char *arg, int *val);
void set_color_palette(void);
int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...);
enum color_attr ifa_family_color(__u8 ifa_family);

View File

@ -29,6 +29,7 @@ void jsonw_pretty(json_writer_t *self, bool on);
void jsonw_name(json_writer_t *self, const char *name);
/* Add value */
__attribute__((format(printf, 2, 3)))
void jsonw_printf(json_writer_t *self, const char *fmt, ...);
void jsonw_string(json_writer_t *self, const char *value);
void jsonw_bool(json_writer_t *self, bool value);
@ -59,8 +60,6 @@ void jsonw_luint_field(json_writer_t *self, const char *prop,
unsigned long int num);
void jsonw_lluint_field(json_writer_t *self, const char *prop,
unsigned long long int num);
void jsonw_float_field_fmt(json_writer_t *self, const char *prop,
const char *fmt, double val);
/* Collections */
void jsonw_start_object(json_writer_t *self);

View File

@ -126,6 +126,7 @@ enum bpf_map_type {
BPF_MAP_TYPE_XSKMAP,
BPF_MAP_TYPE_SOCKHASH,
BPF_MAP_TYPE_CGROUP_STORAGE,
BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
};
enum bpf_prog_type {
@ -150,6 +151,7 @@ enum bpf_prog_type {
BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
BPF_PROG_TYPE_LWT_SEG6LOCAL,
BPF_PROG_TYPE_LIRC_MODE2,
BPF_PROG_TYPE_SK_REUSEPORT,
};
enum bpf_attach_type {
@ -2091,6 +2093,24 @@ union bpf_attr {
* Return
* The id is returned or 0 in case the id could not be retrieved.
*
* u64 bpf_skb_ancestor_cgroup_id(struct sk_buff *skb, int ancestor_level)
* Description
* Return id of cgroup v2 that is ancestor of cgroup associated
* with the *skb* at the *ancestor_level*. The root cgroup is at
* *ancestor_level* zero and each step down the hierarchy
* increments the level. If *ancestor_level* == level of cgroup
* associated with *skb*, then return value will be same as that
* of **bpf_skb_cgroup_id**\ ().
*
* The helper is useful to implement policies based on cgroups
* that are upper in hierarchy than immediate cgroup associated
* with *skb*.
*
* The format of returned id and helper limitations are same as in
* **bpf_skb_cgroup_id**\ ().
* Return
* The id is returned or 0 in case the id could not be retrieved.
*
* u64 bpf_get_current_cgroup_id(void)
* Return
* A 64-bit integer containing the current cgroup id based
@ -2113,6 +2133,14 @@ union bpf_attr {
* the shared data.
* Return
* Pointer to the local storage area.
*
* int bpf_sk_select_reuseport(struct sk_reuseport_md *reuse, struct bpf_map *map, void *key, u64 flags)
* Description
* Select a SO_REUSEPORT sk from a BPF_MAP_TYPE_REUSEPORT_ARRAY map
* It checks the selected sk is matching the incoming
* request in the skb.
* Return
* 0 on success, or a negative error in case of failure.
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@ -2196,7 +2224,9 @@ union bpf_attr {
FN(rc_keydown), \
FN(skb_cgroup_id), \
FN(get_current_cgroup_id), \
FN(get_local_storage),
FN(get_local_storage), \
FN(sk_select_reuseport), \
FN(skb_ancestor_cgroup_id),
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
* function eBPF program intends to call
@ -2413,6 +2443,30 @@ struct sk_msg_md {
__u32 local_port; /* stored in host byte order */
};
struct sk_reuseport_md {
/*
* Start of directly accessible data. It begins from
* the tcp/udp header.
*/
void *data;
void *data_end; /* End of directly accessible data */
/*
* Total length of packet (starting from the tcp/udp header).
* Note that the directly accessible bytes (data_end - data)
* could be less than this "len". Those bytes could be
* indirectly read by a helper "bpf_skb_load_bytes()".
*/
__u32 len;
/*
* Eth protocol in the mac header (network byte order). e.g.
* ETH_P_IP(0x0800) and ETH_P_IPV6(0x86DD)
*/
__u32 eth_protocol;
__u32 ip_protocol; /* IP protocol. e.g. IPPROTO_TCP, IPPROTO_UDP */
__u32 bind_inany; /* Is sock bound to an INANY address? */
__u32 hash; /* A hash of the packet 4 tuples */
};
#define BPF_TAG_SIZE 8
struct bpf_prog_info {

View File

@ -55,7 +55,7 @@ static void usage(void)
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
" -h[uman-readable] | -iec | -j[son] | -p[retty] |\n"
" -f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |\n"
" -4 | -6 | -I | -D | -B | -0 |\n"
" -4 | -6 | -I | -D | -M | -B | -0 |\n"
" -l[oops] { maximum-addr-flush-attempts } | -br[ief] |\n"
" -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n"
" -rc[vbuf] [size] | -n[etns] name | -a[ll] | -c[olor]}\n");
@ -283,8 +283,7 @@ int main(int argc, char **argv)
exit(-1);
}
rcvbuf = size;
} else if (matches(opt, "-color") == 0) {
++color;
} else if (matches_color(opt, &color)) {
} else if (matches(opt, "-help") == 0) {
usage();
} else if (matches(opt, "-netns") == 0) {

View File

@ -82,7 +82,7 @@ int do_netns(int argc, char **argv);
int do_xfrm(int argc, char **argv);
int do_ipl2tp(int argc, char **argv);
int do_ipfou(int argc, char **argv);
extern int do_ipila(int argc, char **argv);
int do_ipila(int argc, char **argv);
int do_tcp_metrics(int argc, char **argv);
int do_ipnetconf(int argc, char **argv);
int do_iptoken(int argc, char **argv);

View File

@ -316,11 +316,14 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
struct can_bittiming *bt = RTA_DATA(tb[IFLA_CAN_BITTIMING]);
if (is_json_context()) {
json_writer_t *jw;
open_json_object("bittiming");
print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate);
jsonw_float_field_fmt(get_json_writer(),
"sample_point", "%.3f",
(float) bt->sample_point / 1000.);
jw = get_json_writer();
jsonw_name(jw, "sample_point");
jsonw_printf(jw, "%.3f",
(float) bt->sample_point / 1000);
print_int(PRINT_ANY, "tq", NULL, bt->tq);
print_int(PRINT_ANY, "prop_seg", NULL, bt->prop_seg);
print_int(PRINT_ANY, "phase_seg1",
@ -415,12 +418,14 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
if (is_json_context()) {
json_writer_t *jw;
open_json_object("data_bittiming");
print_int(PRINT_JSON, "bitrate", NULL, dbt->bitrate);
jsonw_float_field_fmt(get_json_writer(),
"sample_point",
"%.3f",
(float) dbt->sample_point / 1000.);
jw = get_json_writer();
jsonw_name(jw, "sample_point");
jsonw_printf(jw, "%.3f",
(float) dbt->sample_point / 1000.);
print_int(PRINT_JSON, "tq", NULL, dbt->tq);
print_int(PRINT_JSON, "prop_seg", NULL, dbt->prop_seg);
print_int(PRINT_JSON, "phase_seg1",

View File

@ -289,6 +289,7 @@ static int multiaddr_list(int argc, char **argv)
static int multiaddr_modify(int cmd, int argc, char **argv)
{
struct ifreq ifr = {};
int family;
int fd;
if (cmd == RTM_NEWADDR)
@ -324,7 +325,17 @@ static int multiaddr_modify(int cmd, int argc, char **argv)
exit(-1);
}
fd = socket(AF_INET, SOCK_DGRAM, 0);
switch (preferred_family) {
case AF_INET6:
case AF_PACKET:
case AF_INET:
family = preferred_family;
break;
default:
family = AF_INET;
}
fd = socket(family, SOCK_DGRAM, 0);
if (fd < 0) {
perror("Cannot create socket");
exit(1);

View File

@ -58,7 +58,9 @@ static int accept_msg(const struct sockaddr_nl *who,
{
FILE *fp = (FILE *)arg;
if (n->nlmsg_type == RTM_NEWROUTE || n->nlmsg_type == RTM_DELROUTE) {
switch (n->nlmsg_type) {
case RTM_NEWROUTE:
case RTM_DELROUTE: {
struct rtmsg *r = NLMSG_DATA(n);
int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*r));
@ -82,24 +84,28 @@ static int accept_msg(const struct sockaddr_nl *who,
}
}
if (n->nlmsg_type == RTM_NEWLINK || n->nlmsg_type == RTM_DELLINK) {
case RTM_NEWLINK:
case RTM_DELLINK:
ll_remember_index(who, n, NULL);
print_headers(fp, "[LINK]", ctrl);
print_linkinfo(who, n, arg);
return 0;
}
if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {
case RTM_NEWADDR:
case RTM_DELADDR:
print_headers(fp, "[ADDR]", ctrl);
print_addrinfo(who, n, arg);
return 0;
}
if (n->nlmsg_type == RTM_NEWADDRLABEL || n->nlmsg_type == RTM_DELADDRLABEL) {
case RTM_NEWADDRLABEL:
case RTM_DELADDRLABEL:
print_headers(fp, "[ADDRLABEL]", ctrl);
print_addrlabel(who, n, arg);
return 0;
}
if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH ||
n->nlmsg_type == RTM_GETNEIGH) {
case RTM_NEWNEIGH:
case RTM_DELNEIGH:
case RTM_GETNEIGH:
if (preferred_family) {
struct ndmsg *r = NLMSG_DATA(n);
@ -110,34 +116,42 @@ static int accept_msg(const struct sockaddr_nl *who,
print_headers(fp, "[NEIGH]", ctrl);
print_neigh(who, n, arg);
return 0;
}
if (n->nlmsg_type == RTM_NEWPREFIX) {
case RTM_NEWPREFIX:
print_headers(fp, "[PREFIX]", ctrl);
print_prefix(who, n, arg);
return 0;
}
if (n->nlmsg_type == RTM_NEWRULE || n->nlmsg_type == RTM_DELRULE) {
case RTM_NEWRULE:
case RTM_DELRULE:
print_headers(fp, "[RULE]", ctrl);
print_rule(who, n, arg);
return 0;
}
if (n->nlmsg_type == RTM_NEWNETCONF) {
case NLMSG_TSTAMP:
print_nlmsg_timestamp(fp, n);
return 0;
case RTM_NEWNETCONF:
case RTM_DELNETCONF:
print_headers(fp, "[NETCONF]", ctrl);
print_netconf(who, ctrl, n, arg);
return 0;
}
if (n->nlmsg_type == NLMSG_TSTAMP) {
print_nlmsg_timestamp(fp, n);
return 0;
}
if (n->nlmsg_type == RTM_NEWNSID || n->nlmsg_type == RTM_DELNSID) {
case RTM_DELNSID:
case RTM_NEWNSID:
print_headers(fp, "[NSID]", ctrl);
print_nsid(who, n, arg);
return 0;
}
if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP &&
n->nlmsg_type != NLMSG_DONE) {
fprintf(fp, "Unknown message: type=0x%08x(%d) flags=0x%08x(%d)len=0x%08x(%d)\n",
case NLMSG_ERROR:
case NLMSG_NOOP:
case NLMSG_DONE:
break; /* ignore */
default:
fprintf(stderr,
"Unknown message: type=0x%08x(%d) flags=0x%08x(%d) len=0x%08x(%d)\n",
n->nlmsg_type, n->nlmsg_type,
n->nlmsg_flags, n->nlmsg_flags, n->nlmsg_len,
n->nlmsg_len);

View File

@ -66,8 +66,10 @@ int print_netconf(const struct sockaddr_nl *who, struct rtnl_ctrl_data *ctrl,
if (n->nlmsg_type == NLMSG_ERROR)
return -1;
if (n->nlmsg_type != RTM_NEWNETCONF) {
fprintf(stderr, "Not RTM_NEWNETCONF: %08x %08x %08x\n",
if (n->nlmsg_type != RTM_NEWNETCONF &&
n->nlmsg_type != RTM_DELNETCONF) {
fprintf(stderr, "Not a netconf message: %08x %08x %08x\n",
n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
return -1;
@ -91,6 +93,9 @@ int print_netconf(const struct sockaddr_nl *who, struct rtnl_ctrl_data *ctrl,
return 0;
open_json_object(NULL);
if (n->nlmsg_type == RTM_DELNETCONF)
print_bool(PRINT_ANY, "deleted", "Deleted ", true);
print_string(PRINT_ANY, "family",
"%s ", family_name(ncm->ncm_family));

View File

@ -239,7 +239,7 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
print_string(PRINT_FP, NULL, "to ", NULL);
print_color_string(PRINT_ANY, ifa_family_color(frh->family),
"dst", "%s ", dst);
"dst", "%s", dst);
if (frh->dst_len != host_len)
print_uint(PRINT_ANY, "dstlen", "/%u ", frh->dst_len);
else

View File

@ -63,7 +63,9 @@ static int dump_msg2(const struct sockaddr_nl *who,
static void usage(void)
{
fprintf(stderr, "Usage: rtmon file FILE [ all | LISTofOBJECTS]\n");
fprintf(stderr, "Usage: rtmon [ OPTIONS ] file FILE [ all | LISTofOBJECTS ]\n");
fprintf(stderr, "OPTIONS := { -f[amily] { inet | inet6 | link | help } |\n"
" -4 | -6 | -0 | -V[ersion] }\n");
fprintf(stderr, "LISTofOBJECTS := [ link ] [ address ] [ route ]\n");
exit(-1);
}

View File

@ -3,11 +3,13 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/if.h>
#include "color.h"
#include "utils.h"
enum color {
C_RED,
@ -77,13 +79,42 @@ void enable_color(void)
set_color_palette();
}
int check_enable_color(int color, int json)
bool check_enable_color(int color, int json)
{
if (color && !json) {
if (json || color == COLOR_OPT_NEVER)
return false;
if (color == COLOR_OPT_ALWAYS || isatty(fileno(stdout))) {
enable_color();
return 0;
return true;
}
return 1;
return false;
}
bool matches_color(const char *arg, int *val)
{
char *dup, *p;
if (!val)
return false;
dup = strdupa(arg);
p = strchrnul(dup, '=');
if (*p)
*(p++) = '\0';
if (matches(dup, "-color"))
return false;
if (*p == '\0' || !strcmp(p, "always"))
*val = COLOR_OPT_ALWAYS;
else if (!strcmp(p, "auto"))
*val = COLOR_OPT_AUTO;
else if (!strcmp(p, "never"))
*val = COLOR_OPT_NEVER;
else
return false;
return true;
}
void set_color_palette(void)
@ -101,6 +132,7 @@ void set_color_palette(void)
is_dark_bg = 1;
}
__attribute__((format(printf, 3, 4)))
int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...)
{
int ret = 0;

View File

@ -100,6 +100,7 @@ void close_json_array(enum output_type type, const char *str)
* functions handling different types
*/
#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, \

View File

@ -152,6 +152,7 @@ void jsonw_name(json_writer_t *self, const char *name)
putc(' ', self->out);
}
__attribute__((format(printf, 2, 3)))
void jsonw_printf(json_writer_t *self, const char *fmt, ...)
{
va_list ap;
@ -205,11 +206,6 @@ void jsonw_null(json_writer_t *self)
jsonw_printf(self, "null");
}
void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num)
{
jsonw_printf(self, fmt, num);
}
void jsonw_float(json_writer_t *self, double num)
{
jsonw_printf(self, "%g", num);
@ -274,15 +270,6 @@ void jsonw_float_field(json_writer_t *self, const char *prop, double val)
jsonw_float(self, val);
}
void jsonw_float_field_fmt(json_writer_t *self,
const char *prop,
const char *fmt,
double val)
{
jsonw_name(self, prop);
jsonw_float_fmt(self, fmt, val);
}
void jsonw_uint_field(json_writer_t *self, const char *prop, unsigned int num)
{
jsonw_name(self, prop);

View File

@ -24,7 +24,8 @@ bridge \- show / manipulate bridge addresses and devices
\fB\-b\fR[\fIatch\fR] filename |
\fB\-c\fR[\folor\fR] |
\fB\-p\fR[\fIretty\fR] |
\fB\-j\fR[\fIson\fR] }
\fB\-j\fR[\fIson\fR] |
\fB\-o\fR[\fIneline\fr] }
.ti -8
.BR "bridge link set"
@ -171,8 +172,17 @@ If there were any errors during execution of the commands, the application
return code will be non zero.
.TP
.BR "\-c" , " -color"
Use color output.
.BR \-c [ color ][ = { always | auto | never }
Configure color output. If parameter is omitted or
.BR always ,
color output is enabled regardless of stdout state. If parameter is
.BR auto ,
stdout is checked to be a terminal before enabling color output. If parameter is
.BR never ,
color output is disabled. If specified multiple times, the last one takes
precedence. This flag is ignored if
.B \-json
is also given.
.TP
.BR "\-j", " \-json"
@ -182,6 +192,18 @@ Output results in JavaScript Object Notation (JSON).
.BR "\-p", " \-pretty"
When combined with -j generate a pretty JSON output.
.TP
.BR "\-o", " \-oneline"
output each record on a single line, replacing line feeds
with the
.B '\e'
character. This is convenient when you want to count records
with
.BR wc (1)
or to
.BR grep (1)
the output.
.SH BRIDGE - COMMAND SYNTAX

View File

@ -47,6 +47,10 @@ Generate JSON output.
.BR "\-p" , " --pretty"
When combined with -j generate a pretty JSON output.
.TP
.BR "\-v" , " --verbose"
Turn on verbose output.
.SS
.I OBJECT

View File

@ -48,6 +48,14 @@ Report average over the last SECS seconds.
.B \-z, \-\-zeros
Show entries with zero activity.
.TP
.B \-j, \-\-json
Display results in JSON format
.TP
.B \-p, \-\-pretty
If combined with
.BR \-\-json ,
pretty print the output.
.TP
.B \-x, \-\-extended=TYPE
Show extended stats of TYPE. Supported types are:

View File

@ -187,8 +187,17 @@ to
executes specified command over all objects, it depends if command supports this option.
.TP
.BR "\-c" , " -color"
Use color output.
.BR \-c [ color ][ = { always | auto | never }
Configure color output. If parameter is omitted or
.BR always ,
color output is enabled regardless of stdout state. If parameter is
.BR auto ,
stdout is checked to be a terminal before enabling color output. If parameter is
.BR never ,
color output is disabled. If specified multiple times, the last one takes
precedence. This flag is ignored if
.B \-json
is also given.
.TP
.BR "\-t" , " \-timestamp"

View File

@ -4,7 +4,7 @@
nstat, rtacct - network statistics tools.
.SH SYNOPSIS
Usage: nstat [ -h?vVzrnasd:t: ] [ PATTERN [ PATTERN ] ]
Usage: nstat [ -h?vVzrnasd:t:jp ] [ PATTERN [ PATTERN ] ]
.br
Usage: rtacct [ -h?vVzrnasd:t: ] [ ListOfRealms ]
@ -21,7 +21,7 @@ Print help
.B \-V, \-\-version
Print version
.TP
.B \-z, \-\-zero
.B \-z, \-\-zeros
Dump zero counters too. By default they are not shown.
.TP
.B \-r, \-\-reset
@ -39,12 +39,16 @@ Do not update history, so that the next time you will see counters including val
.B \-j, \-\-json
Display results in JSON format.
.TP
.B \-d, \-\-interval <INTERVAL>
.B \-p, \-\-pretty
When combined with
.BR \-\-json ,
pretty print the output.
.TP
.B \-d, \-\-scan <INTERVAL>
Run in daemon mode collecting statistics. <INTERVAL> is interval between measurements in seconds.
.TP
.B \-t, \-\-interval <INTERVAL>
Time interval to average rates. Default value is 60 seconds.
.TP
.SH SEE ALSO
lnstat(8)

View File

@ -242,6 +242,9 @@ Print summary statistics. This option does not parse socket lists obtaining
summary from various sources. It is useful when amount of sockets is so huge
that parsing /proc/net/tcp is painful.
.TP
.B \-E, \-\-events
Continually display sockets as they are destroyed
.TP
.B \-Z, \-\-context
As the
.B \-p

View File

@ -569,6 +569,61 @@ possible latency. At link speeds higher than 10 Gbps, setting the
no-split-gso parameter can increase the maximum achievable throughput by
retaining the full GSO packets.
.SH OVERRIDING CLASSIFICATION WITH TC FILTERS
CAKE supports overriding of its internal classification of packets through the
tc filter mechanism. Packets can be assigned to different priority tins by
setting the
.B priority
field on the skb, and the flow hashing can be overridden by setting the
.B classid
parameter.
.PP
.B Tin override
.br
To assign a priority tin, the major number of the priority field needs
to match the qdisc handle of the cake instance; if it does, the minor number
will be interpreted as the tin index. For example, to classify all ICMP packets
as 'bulk', the following filter can be used:
.br
# tc qdisc replace dev eth0 handle 1: root cake diffserv3
# tc filter add dev eth0 parent 1: protocol ip prio 1 \\
u32 match icmp type 0 0 action skbedit priority 1:1
.PP
.B Flow hash override
.br
To override flow hashing, the classid can be set. CAKE will interpret
the major number of the classid as the host hash used in host isolation mode,
and the minor number as the flow hash used for flow-based queueing. One or both
of those can be set, and will be used if the relevant flow isolation parameter
is set (i.e., the major number will be ignored if CAKE is not configured in
hosts mode, and the minor number will be ignored if CAKE is not configured in
flows mode).
.br
This example will assign all ICMP packets to the first queue:
.br
# tc qdisc replace dev eth0 handle 1: root cake
# tc filter add dev eth0 parent 1: protocol ip prio 1 \\
u32 match icmp type 0 0 classid 0:1
.br
If only one of the host and flow overrides is set, CAKE will compute the other
hash from the packet as normal. Note, however, that the host isolation mode
works by assigning a host ID to the flow queue; so if overriding both host and
flow, the same flow cannot have more than one host assigned. In addition, it is
not possible to assign different source and destination host IDs through the
override mechanism; if a host ID is assigned, it will be used as both source and
destination host.
.SH EXAMPLES
# tc qdisc delete root dev eth0
.br

View File

@ -755,8 +755,17 @@ option was specified. Classes can be filtered only by
option.
.TP
.BR "\ -color"
Use color output.
.BR \-c [ color ][ = { always | auto | never }
Configure color output. If parameter is omitted or
.BR always ,
color output is enabled regardless of stdout state. If parameter is
.BR auto ,
stdout is checked to be a terminal before enabling color output. If parameter is
.BR never ,
color output is disabled. If specified multiple times, the last one takes
precedence. This flag is ignored if
.B \-json
is also given.
.TP
.BR "\-j", " \-json"

View File

@ -16,6 +16,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/sysmacros.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
@ -976,6 +977,7 @@ static int buf_update(int len)
}
/* Append content to buffer as part of the current field */
__attribute__((format(printf, 1, 2)))
static void out(const char *fmt, ...)
{
struct column *f = current_field;
@ -1093,7 +1095,7 @@ static void print_header(void)
{
while (!field_is_last(current_field)) {
if (!current_field->disabled)
out(current_field->header);
out("%s", current_field->header);
field_next();
}
}
@ -3604,6 +3606,21 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
out(" %c-%c",
mask & 1 ? '-' : '<', mask & 2 ? '-' : '>');
}
if (tb[UNIX_DIAG_VFS]) {
struct unix_diag_vfs *uv = RTA_DATA(tb[UNIX_DIAG_VFS]);
out(" ino:%u dev:%u/%u", uv->udiag_vfs_ino, major(uv->udiag_vfs_dev),
minor(uv->udiag_vfs_dev));
}
if (tb[UNIX_DIAG_ICONS]) {
int len = RTA_PAYLOAD(tb[UNIX_DIAG_ICONS]);
__u32 *peers = RTA_DATA(tb[UNIX_DIAG_ICONS]);
int i;
out(" peers:");
for (i = 0; i < len / sizeof(__u32); i++)
out(" %u", peers[i]);
}
}
return 0;
@ -3641,6 +3658,8 @@ static int unix_show_netlink(struct filter *f)
req.r.udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER | UDIAG_SHOW_RQLEN;
if (show_mem)
req.r.udiag_show |= UDIAG_SHOW_MEMINFO;
if (show_details)
req.r.udiag_show |= UDIAG_SHOW_VFS | UDIAG_SHOW_ICONS;
return handle_netlink_request(f, &req.nlh, sizeof(req), unix_show_sock);
}

View File

@ -277,6 +277,7 @@ static int flatten_tree(struct ematch *head, struct ematch *tree)
return count;
}
__attribute__((format(printf, 5, 6)))
int em_parse_error(int err, struct bstr *args, struct bstr *carg,
struct ematch_util *e, char *fmt, ...)
{

View File

@ -12,17 +12,16 @@
#define EMATCHKINDSIZ 16
struct bstr
{
struct bstr {
char *data;
unsigned int len;
int quoted;
struct bstr *next;
};
extern struct bstr * bstr_alloc(const char *text);
struct bstr *bstr_alloc(const char *text);
static inline struct bstr * bstr_new(char *data, unsigned int len)
static inline struct bstr *bstr_new(char *data, unsigned int len)
{
struct bstr *b = calloc(1, sizeof(*b));
@ -35,7 +34,7 @@ static inline struct bstr * bstr_new(char *data, unsigned int len)
return b;
}
static inline int bstrcmp(struct bstr *b, const char *text)
static inline int bstrcmp(const struct bstr *b, const char *text)
{
int len = strlen(text);
int d = b->len - len;
@ -51,12 +50,10 @@ static inline struct bstr *bstr_next(struct bstr *b)
return b->next;
}
extern unsigned long bstrtoul(const struct bstr *b);
extern void bstr_print(FILE *fd, const struct bstr *b, int ascii);
unsigned long bstrtoul(const struct bstr *b);
void bstr_print(FILE *fd, const struct bstr *b, int ascii);
struct ematch
{
struct ematch {
struct bstr *args;
int index;
int inverted;
@ -66,7 +63,7 @@ struct ematch
struct ematch *next;
};
static inline struct ematch * new_ematch(struct bstr *args, int inverted)
static inline struct ematch *new_ematch(struct bstr *args, int inverted)
{
struct ematch *e = calloc(1, sizeof(*e));
@ -79,14 +76,12 @@ static inline struct ematch * new_ematch(struct bstr *args, int inverted)
return e;
}
extern void print_ematch_tree(const struct ematch *tree);
void print_ematch_tree(const struct ematch *tree);
struct ematch_util
{
struct ematch_util {
char kind[EMATCHKINDSIZ];
int kind_num;
int (*parse_eopt)(struct nlmsghdr *,struct tcf_ematch_hdr *,
int (*parse_eopt)(struct nlmsghdr *, struct tcf_ematch_hdr *,
struct bstr *);
int (*parse_eopt_argv)(struct nlmsghdr *, struct tcf_ematch_hdr *,
int, char **);
@ -95,7 +90,7 @@ struct ematch_util
struct ematch_util *next;
};
static inline int parse_layer(struct bstr *b)
static inline int parse_layer(const struct bstr *b)
{
if (*((char *) b->data) == 'l')
return TCF_LAYER_LINK;
@ -107,9 +102,10 @@ static inline int parse_layer(struct bstr *b)
return INT_MAX;
}
extern int em_parse_error(int err, struct bstr *args, struct bstr *carg,
__attribute__((format(printf, 5, 6)))
int em_parse_error(int err, struct bstr *args, struct bstr *carg,
struct ematch_util *, char *fmt, ...);
extern int print_ematch(FILE *, const struct rtattr *);
extern int parse_ematch(int *, char ***, int, struct nlmsghdr *);
int print_ematch(FILE *, const struct rtattr *);
int parse_ematch(int *, char ***, int, struct nlmsghdr *);
#endif

View File

@ -71,23 +71,22 @@ struct m_pedit_util {
struct m_pedit_key *tkey);
};
extern int pack_key(struct m_pedit_sel *sel, struct m_pedit_key *tkey);
extern int pack_key32(__u32 retain, struct m_pedit_sel *sel,
struct m_pedit_key *tkey);
extern int pack_key16(__u32 retain, struct m_pedit_sel *sel,
struct m_pedit_key *tkey);
extern int pack_key8(__u32 retain, struct m_pedit_sel *sel,
int pack_key(struct m_pedit_sel *sel, struct m_pedit_key *tkey);
int pack_key32(__u32 retain, struct m_pedit_sel *sel,
struct m_pedit_key *tkey);
int pack_key16(__u32 retain, struct m_pedit_sel *sel,
struct m_pedit_key *tkey);
int pack_key8(__u32 retain, struct m_pedit_sel *sel,
struct m_pedit_key *tkey);
extern int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type);
extern int parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type,
__u32 retain,
struct m_pedit_sel *sel, struct m_pedit_key *tkey);
extern int parse_offset(int *argc_p, char ***argv_p,
struct m_pedit_sel *sel, struct m_pedit_key *tkey);
int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type);
int parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type,
__u32 retain,
struct m_pedit_sel *sel, struct m_pedit_key *tkey);
int parse_offset(int *argc_p, char ***argv_p,
struct m_pedit_sel *sel, struct m_pedit_key *tkey);
int parse_pedit(struct action_util *a, int *argc_p, char ***argv_p,
int tca_id, struct nlmsghdr *n);
extern int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg);
extern int pedit_print_xstats(struct action_util *au, FILE *f,
struct rtattr *xstats);
int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg);
int pedit_print_xstats(struct action_util *au, FILE *f,
struct rtattr *xstats);
#endif

View File

@ -109,7 +109,6 @@ static int htb_parse_opt(struct qdisc_util *qu, int argc,
static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev)
{
int ok = 0;
struct tc_htb_opt opt = {};
__u32 rtab[256], ctab[256];
unsigned buffer = 0, cbuffer = 0;
@ -127,7 +126,6 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
if (get_u32(&opt.prio, *argv, 10)) {
explain1("prio"); return -1;
}
ok++;
} else if (matches(*argv, "mtu") == 0) {
NEXT_ARG();
if (get_u32(&mtu, *argv, 10)) {
@ -161,7 +159,6 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
explain1("buffer");
return -1;
}
ok++;
} else if (matches(*argv, "cburst") == 0 ||
strcmp(*argv, "cbuffer") == 0 ||
strcmp(*argv, "cmaxburst") == 0) {
@ -170,7 +167,6 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
explain1("cbuffer");
return -1;
}
ok++;
} else if (strcmp(*argv, "ceil") == 0) {
NEXT_ARG();
if (ceil64) {
@ -186,7 +182,6 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
explain1("ceil");
return -1;
}
ok++;
} else if (strcmp(*argv, "rate") == 0) {
NEXT_ARG();
if (rate64) {
@ -202,7 +197,6 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
explain1("rate");
return -1;
}
ok++;
} else if (strcmp(*argv, "help") == 0) {
explain();
return -1;
@ -214,9 +208,6 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
argc--; argv++;
}
/* if (!ok)
return 0;*/
if (!rate64) {
fprintf(stderr, "\"rate\" is required.\n");
return -1;

View File

@ -496,8 +496,7 @@ int main(int argc, char **argv)
matches(argv[1], "-conf") == 0) {
NEXT_ARG();
conf_file = argv[1];
} else if (matches(argv[1], "-color") == 0) {
++color;
} else if (matches_color(argv[1], &color)) {
} else if (matches(argv[1], "-timestamp") == 0) {
timestamp++;
} else if (matches(argv[1], "-tshort") == 0) {

View File

@ -5,26 +5,26 @@
extern struct rtnl_handle rth;
extern int do_qdisc(int argc, char **argv);
extern int do_class(int argc, char **argv);
extern int do_filter(int argc, char **argv, void *buf, size_t buflen);
extern int do_chain(int argc, char **argv, void *buf, size_t buflen);
extern int do_action(int argc, char **argv, void *buf, size_t buflen);
extern int do_tcmonitor(int argc, char **argv);
extern int do_exec(int argc, char **argv);
int do_qdisc(int argc, char **argv);
int do_class(int argc, char **argv);
int do_filter(int argc, char **argv, void *buf, size_t buflen);
int do_chain(int argc, char **argv, void *buf, size_t buflen);
int do_action(int argc, char **argv, void *buf, size_t buflen);
int do_tcmonitor(int argc, char **argv);
int do_exec(int argc, char **argv);
extern int print_action(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
extern int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
extern int print_qdisc(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
extern int print_class(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
extern void print_size_table(FILE *fp, const char *prefix, struct rtattr *rta);
int print_action(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
int print_qdisc(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
int print_class(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg);
void print_size_table(FILE *fp, const char *prefix, struct rtattr *rta);
struct tc_estimator;
extern int parse_estimator(int *p_argc, char ***p_argv, struct tc_estimator *est);
int parse_estimator(int *p_argc, char ***p_argv, struct tc_estimator *est);
struct tc_sizespec;
extern int parse_size_table(int *p_argc, char ***p_argv, struct tc_sizespec *s);
extern int check_size_table_opts(struct tc_sizespec *s);
int parse_size_table(int *p_argc, char ***p_argv, struct tc_sizespec *s);
int check_size_table_opts(struct tc_sizespec *s);
extern int show_graph;
extern bool use_names;

View File

@ -2,8 +2,9 @@
#ifndef _TC_RED_H_
#define _TC_RED_H_ 1
extern int tc_red_eval_P(unsigned qmin, unsigned qmax, double prob);
extern int tc_red_eval_ewma(unsigned qmin, unsigned burst, unsigned avpkt);
extern int tc_red_eval_idle_damping(int wlog, unsigned avpkt, unsigned bandwidth, __u8 *sbuf);
int tc_red_eval_P(unsigned qmin, unsigned qmax, double prob);
int tc_red_eval_ewma(unsigned qmin, unsigned burst, unsigned avpkt);
int tc_red_eval_idle_damping(int wlog, unsigned avpkt, unsigned bandwidth,
__u8 *sbuf);
#endif

View File

@ -14,15 +14,13 @@ TESTS_DIR := $(dir $(TESTS))
IPVERS := $(filter-out iproute2/Makefile,$(wildcard iproute2/*))
KENVFN := $(shell mktemp /tmp/tc_testkenv.XXXXXX)
ifneq (,$(wildcard /proc/config.gz))
KENV := $(shell cat /proc/config.gz | gunzip | grep ^CONFIG)
KCPATH := /proc/config.gz
else
KVER := $(shell uname -r)
KCPATHS := /lib/modules/$(KVER)/config /boot/config-$(KVER)
KCPATH := $(firstword $(wildcard $(KCPATHS)))
ifneq (,$(KCPATH))
KENV := $(shell cat ${KCPATH} | grep ^CONFIG)
endif
endif
.PHONY: compile listtests alltests configure $(TESTS)
@ -32,6 +30,7 @@ configure:
compile: configure
echo "Entering iproute2" && cd iproute2 && $(MAKE) && cd ..;
$(MAKE) -C tools
listtests:
@for t in $(TESTS); do \
@ -43,6 +42,9 @@ alltests: $(TESTS)
clean:
@echo "Removing $(RESULTS_DIR) dir ..."
@rm -rf $(RESULTS_DIR)
@rm -f iproute2/iproute2-this
@rm -f tests/ip/link/dev_wo_vf_rate.nl
$(MAKE) -C tools clean
distclean: clean
echo "Entering iproute2" && cd iproute2 && $(MAKE) distclean && cd ..;
@ -59,14 +61,22 @@ endif
mkdir -p $(RESULTS_DIR)/$$d; \
done
@if [ "$(KCPATH)" = "/proc/config.gz" ]; then \
gunzip -c $(KCPATH) >$(KENVFN); \
elif [ "$(KCPATH)" != "" ]; then \
cat $(KCPATH) >$(KENVFN); \
fi
@sed -i -e 's/^CONFIG_/export CONFIG_/' $(KENVFN)
@for i in $(IPVERS); do \
o=`echo $$i | sed -e 's/iproute2\///'`; \
echo -n "Running $@ [$$o/`uname -r`]: "; \
TMP_ERR=`mktemp /tmp/tc_testsuite.XXXXXX`; \
TMP_OUT=`mktemp /tmp/tc_testsuite.XXXXXX`; \
. $(KENVFN); \
STD_ERR="$$TMP_ERR" STD_OUT="$$TMP_OUT" \
TC="$$i/tc/tc" IP="$$i/ip/ip" SS=$$i/misc/ss DEV="$(DEV)" IPVER="$@" SNAME="$$i" \
ERRF="$(RESULTS_DIR)/$@.$$o.err" $(KENV) $(PREFIX) tests/$@ > $(RESULTS_DIR)/$@.$$o.out; \
ERRF="$(RESULTS_DIR)/$@.$$o.err" $(PREFIX) tests/$@ > $(RESULTS_DIR)/$@.$$o.out; \
if [ "$$?" = "127" ]; then \
echo "SKIPPED"; \
elif [ -e "$(RESULTS_DIR)/$@.$$o.err" ]; then \
@ -75,5 +85,5 @@ endif
echo "PASS"; \
fi; \
rm "$$TMP_ERR" "$$TMP_OUT"; \
dmesg > $(RESULTS_DIR)/$@.$$o.dmesg; \
sudo dmesg > $(RESULTS_DIR)/$@.$$o.dmesg; \
done

View File

@ -1,3 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
include ../../config.mk
generate_nlmsg: generate_nlmsg.c ../../lib/libnetlink.c
$(CC) -o $@ $^
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDLIBS) $(EXTRA_CFLAGS) -I../../include -include../../include/uapi/linux/netlink.h -o $@ $^
clean:
rm -f generate_nlmsg