Merge branch 'iproute2-master' into iproute2-next
Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
commit
c4e0ea8e9b
2
Makefile
2
Makefile
|
|
@ -96,7 +96,7 @@ snapshot:
|
||||||
> include/SNAPSHOT.h
|
> include/SNAPSHOT.h
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@for i in $(SUBDIRS); \
|
@for i in $(SUBDIRS) testsuite; \
|
||||||
do $(MAKE) $(MFLAGS) -C $$i clean; done
|
do $(MAKE) $(MFLAGS) -C $$i clean; done
|
||||||
|
|
||||||
clobber:
|
clobber:
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,20 @@
|
||||||
#define MDB_RTR_RTA(r) \
|
#define MDB_RTR_RTA(r) \
|
||||||
((struct rtattr *)(((char *)(r)) + RTA_ALIGN(sizeof(__u32))))
|
((struct rtattr *)(((char *)(r)) + RTA_ALIGN(sizeof(__u32))))
|
||||||
|
|
||||||
extern void print_vlan_info(FILE *fp, struct rtattr *tb);
|
void print_vlan_info(FILE *fp, struct rtattr *tb);
|
||||||
extern int print_linkinfo(const struct sockaddr_nl *who,
|
int print_linkinfo(const struct sockaddr_nl *who,
|
||||||
struct nlmsghdr *n,
|
struct nlmsghdr *n,
|
||||||
void *arg);
|
void *arg);
|
||||||
extern int print_fdb(const struct sockaddr_nl *who,
|
int print_fdb(const struct sockaddr_nl *who,
|
||||||
struct nlmsghdr *n, void *arg);
|
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);
|
struct nlmsghdr *n, void *arg);
|
||||||
|
|
||||||
extern int do_fdb(int argc, char **argv);
|
int do_fdb(int argc, char **argv);
|
||||||
extern int do_mdb(int argc, char **argv);
|
int do_mdb(int argc, char **argv);
|
||||||
extern int do_monitor(int argc, char **argv);
|
int do_monitor(int argc, char **argv);
|
||||||
extern int do_vlan(int argc, char **argv);
|
int do_vlan(int argc, char **argv);
|
||||||
extern int do_link(int argc, char **argv);
|
int do_link(int argc, char **argv);
|
||||||
|
|
||||||
extern int preferred_family;
|
extern int preferred_family;
|
||||||
extern int show_stats;
|
extern int show_stats;
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ static void usage(void)
|
||||||
"where OBJECT := { link | fdb | mdb | vlan | monitor }\n"
|
"where OBJECT := { link | fdb | mdb | vlan | monitor }\n"
|
||||||
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n"
|
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n"
|
||||||
" -o[neline] | -t[imestamp] | -n[etns] name |\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);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,8 +173,7 @@ main(int argc, char **argv)
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (netns_switch(argv[1]))
|
if (netns_switch(argv[1]))
|
||||||
exit(-1);
|
exit(-1);
|
||||||
} else if (matches(opt, "-color") == 0) {
|
} else if (matches_color(opt, &color)) {
|
||||||
++color;
|
|
||||||
} else if (matches(opt, "-compressvlans") == 0) {
|
} else if (matches(opt, "-compressvlans") == 0) {
|
||||||
++compress_vlans;
|
++compress_vlans;
|
||||||
} else if (matches(opt, "-force") == 0) {
|
} else if (matches(opt, "-force") == 0) {
|
||||||
|
|
|
||||||
|
|
@ -5426,7 +5426,7 @@ static void help(void)
|
||||||
pr_err("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n"
|
pr_err("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n"
|
||||||
" devlink [ -f[orce] ] -b[atch] filename\n"
|
" devlink [ -f[orce] ] -b[atch] filename\n"
|
||||||
"where OBJECT := { dev | port | sb | monitor | dpipe | resource | region }\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)
|
static int dl_cmd(struct dl *dl, int argc, char **argv)
|
||||||
|
|
|
||||||
30
genl/genl.c
30
genl/genl.c
|
|
@ -26,12 +26,12 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "genl_utils.h"
|
#include "genl_utils.h"
|
||||||
|
|
||||||
int show_stats = 0;
|
int show_stats;
|
||||||
int show_details = 0;
|
int show_details;
|
||||||
int show_raw = 0;
|
int show_raw;
|
||||||
|
|
||||||
static void *BODY;
|
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,
|
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)
|
static int parse_nofopt(struct genl_util *f, int argc, char **argv)
|
||||||
{
|
{
|
||||||
if (argc) {
|
if (argc) {
|
||||||
fprintf(stderr, "Unknown genl \"%s\", hence option \"%s\" "
|
fprintf(stderr,
|
||||||
"is unparsable\n", f->name, *argv);
|
"Unknown genl \"%s\", hence option \"%s\" is unparsable\n",
|
||||||
|
f->name, *argv);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,9 +99,10 @@ static void usage(void) __attribute__((noreturn));
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: genl [ OPTIONS ] OBJECT | help }\n"
|
fprintf(stderr,
|
||||||
"where OBJECT := { ctrl etc }\n"
|
"Usage: genl [ OPTIONS ] OBJECT [help] }\n"
|
||||||
" OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] }\n");
|
"where OBJECT := { ctrl etc }\n"
|
||||||
|
" OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -V[ersion] | -h[elp] }\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,19 +124,21 @@ int main(int argc, char **argv)
|
||||||
} else if (matches(argv[1], "-help") == 0) {
|
} else if (matches(argv[1], "-help") == 0) {
|
||||||
usage();
|
usage();
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Option \"%s\" is unknown, try "
|
fprintf(stderr,
|
||||||
"\"genl -help\".\n", argv[1]);
|
"Option \"%s\" is unknown, try \"genl -help\".\n",
|
||||||
|
argv[1]);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
argc--; argv++;
|
argc--; argv++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
|
struct genl_util *a;
|
||||||
int ret;
|
int ret;
|
||||||
struct genl_util *a = NULL;
|
|
||||||
a = get_genl_kind(argv[1]);
|
a = get_genl_kind(argv[1]);
|
||||||
if (!a) {
|
if (!a) {
|
||||||
fprintf(stderr,"bad genl %s\n", argv[1]);
|
fprintf(stderr, "bad genl %s\n", argv[1]);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,10 @@ 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);
|
||||||
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
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#ifndef __COLOR_H__
|
#ifndef __COLOR_H__
|
||||||
#define __COLOR_H__ 1
|
#define __COLOR_H__ 1
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
enum color_attr {
|
enum color_attr {
|
||||||
COLOR_IFNAME,
|
COLOR_IFNAME,
|
||||||
COLOR_MAC,
|
COLOR_MAC,
|
||||||
|
|
@ -12,8 +14,15 @@ enum color_attr {
|
||||||
COLOR_NONE
|
COLOR_NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum color_opt {
|
||||||
|
COLOR_OPT_NEVER = 0,
|
||||||
|
COLOR_OPT_AUTO = 1,
|
||||||
|
COLOR_OPT_ALWAYS = 2
|
||||||
|
};
|
||||||
|
|
||||||
void enable_color(void);
|
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);
|
void set_color_palette(void);
|
||||||
int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...);
|
int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...);
|
||||||
enum color_attr ifa_family_color(__u8 ifa_family);
|
enum color_attr ifa_family_color(__u8 ifa_family);
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ void jsonw_pretty(json_writer_t *self, bool on);
|
||||||
void jsonw_name(json_writer_t *self, const char *name);
|
void jsonw_name(json_writer_t *self, const char *name);
|
||||||
|
|
||||||
/* Add value */
|
/* Add value */
|
||||||
|
__attribute__((format(printf, 2, 3)))
|
||||||
void jsonw_printf(json_writer_t *self, const char *fmt, ...);
|
void jsonw_printf(json_writer_t *self, const char *fmt, ...);
|
||||||
void jsonw_string(json_writer_t *self, const char *value);
|
void jsonw_string(json_writer_t *self, const char *value);
|
||||||
void jsonw_bool(json_writer_t *self, bool 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);
|
unsigned long int num);
|
||||||
void jsonw_lluint_field(json_writer_t *self, const char *prop,
|
void jsonw_lluint_field(json_writer_t *self, const char *prop,
|
||||||
unsigned long long int num);
|
unsigned long long int num);
|
||||||
void jsonw_float_field_fmt(json_writer_t *self, const char *prop,
|
|
||||||
const char *fmt, double val);
|
|
||||||
|
|
||||||
/* Collections */
|
/* Collections */
|
||||||
void jsonw_start_object(json_writer_t *self);
|
void jsonw_start_object(json_writer_t *self);
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,7 @@ enum bpf_map_type {
|
||||||
BPF_MAP_TYPE_XSKMAP,
|
BPF_MAP_TYPE_XSKMAP,
|
||||||
BPF_MAP_TYPE_SOCKHASH,
|
BPF_MAP_TYPE_SOCKHASH,
|
||||||
BPF_MAP_TYPE_CGROUP_STORAGE,
|
BPF_MAP_TYPE_CGROUP_STORAGE,
|
||||||
|
BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum bpf_prog_type {
|
enum bpf_prog_type {
|
||||||
|
|
@ -150,6 +151,7 @@ enum bpf_prog_type {
|
||||||
BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
|
BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
|
||||||
BPF_PROG_TYPE_LWT_SEG6LOCAL,
|
BPF_PROG_TYPE_LWT_SEG6LOCAL,
|
||||||
BPF_PROG_TYPE_LIRC_MODE2,
|
BPF_PROG_TYPE_LIRC_MODE2,
|
||||||
|
BPF_PROG_TYPE_SK_REUSEPORT,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum bpf_attach_type {
|
enum bpf_attach_type {
|
||||||
|
|
@ -2091,6 +2093,24 @@ union bpf_attr {
|
||||||
* Return
|
* Return
|
||||||
* The id is returned or 0 in case the id could not be retrieved.
|
* 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)
|
* u64 bpf_get_current_cgroup_id(void)
|
||||||
* Return
|
* Return
|
||||||
* A 64-bit integer containing the current cgroup id based
|
* A 64-bit integer containing the current cgroup id based
|
||||||
|
|
@ -2113,6 +2133,14 @@ union bpf_attr {
|
||||||
* the shared data.
|
* the shared data.
|
||||||
* Return
|
* Return
|
||||||
* Pointer to the local storage area.
|
* 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) \
|
#define __BPF_FUNC_MAPPER(FN) \
|
||||||
FN(unspec), \
|
FN(unspec), \
|
||||||
|
|
@ -2196,7 +2224,9 @@ union bpf_attr {
|
||||||
FN(rc_keydown), \
|
FN(rc_keydown), \
|
||||||
FN(skb_cgroup_id), \
|
FN(skb_cgroup_id), \
|
||||||
FN(get_current_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
|
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||||
* function eBPF program intends to call
|
* function eBPF program intends to call
|
||||||
|
|
@ -2413,6 +2443,30 @@ struct sk_msg_md {
|
||||||
__u32 local_port; /* stored in host byte order */
|
__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
|
#define BPF_TAG_SIZE 8
|
||||||
|
|
||||||
struct bpf_prog_info {
|
struct bpf_prog_info {
|
||||||
|
|
|
||||||
5
ip/ip.c
5
ip/ip.c
|
|
@ -55,7 +55,7 @@ static void usage(void)
|
||||||
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
|
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
|
||||||
" -h[uman-readable] | -iec | -j[son] | -p[retty] |\n"
|
" -h[uman-readable] | -iec | -j[son] | -p[retty] |\n"
|
||||||
" -f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |\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"
|
" -l[oops] { maximum-addr-flush-attempts } | -br[ief] |\n"
|
||||||
" -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n"
|
" -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n"
|
||||||
" -rc[vbuf] [size] | -n[etns] name | -a[ll] | -c[olor]}\n");
|
" -rc[vbuf] [size] | -n[etns] name | -a[ll] | -c[olor]}\n");
|
||||||
|
|
@ -283,8 +283,7 @@ int main(int argc, char **argv)
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
rcvbuf = size;
|
rcvbuf = size;
|
||||||
} else if (matches(opt, "-color") == 0) {
|
} else if (matches_color(opt, &color)) {
|
||||||
++color;
|
|
||||||
} else if (matches(opt, "-help") == 0) {
|
} else if (matches(opt, "-help") == 0) {
|
||||||
usage();
|
usage();
|
||||||
} else if (matches(opt, "-netns") == 0) {
|
} else if (matches(opt, "-netns") == 0) {
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ int do_netns(int argc, char **argv);
|
||||||
int do_xfrm(int argc, char **argv);
|
int do_xfrm(int argc, char **argv);
|
||||||
int do_ipl2tp(int argc, char **argv);
|
int do_ipl2tp(int argc, char **argv);
|
||||||
int do_ipfou(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_tcp_metrics(int argc, char **argv);
|
||||||
int do_ipnetconf(int argc, char **argv);
|
int do_ipnetconf(int argc, char **argv);
|
||||||
int do_iptoken(int argc, char **argv);
|
int do_iptoken(int argc, char **argv);
|
||||||
|
|
|
||||||
|
|
@ -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]);
|
struct can_bittiming *bt = RTA_DATA(tb[IFLA_CAN_BITTIMING]);
|
||||||
|
|
||||||
if (is_json_context()) {
|
if (is_json_context()) {
|
||||||
|
json_writer_t *jw;
|
||||||
|
|
||||||
open_json_object("bittiming");
|
open_json_object("bittiming");
|
||||||
print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate);
|
print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate);
|
||||||
jsonw_float_field_fmt(get_json_writer(),
|
jw = get_json_writer();
|
||||||
"sample_point", "%.3f",
|
jsonw_name(jw, "sample_point");
|
||||||
(float) bt->sample_point / 1000.);
|
jsonw_printf(jw, "%.3f",
|
||||||
|
(float) bt->sample_point / 1000);
|
||||||
print_int(PRINT_ANY, "tq", NULL, bt->tq);
|
print_int(PRINT_ANY, "tq", NULL, bt->tq);
|
||||||
print_int(PRINT_ANY, "prop_seg", NULL, bt->prop_seg);
|
print_int(PRINT_ANY, "prop_seg", NULL, bt->prop_seg);
|
||||||
print_int(PRINT_ANY, "phase_seg1",
|
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]);
|
RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
|
||||||
|
|
||||||
if (is_json_context()) {
|
if (is_json_context()) {
|
||||||
|
json_writer_t *jw;
|
||||||
|
|
||||||
open_json_object("data_bittiming");
|
open_json_object("data_bittiming");
|
||||||
print_int(PRINT_JSON, "bitrate", NULL, dbt->bitrate);
|
print_int(PRINT_JSON, "bitrate", NULL, dbt->bitrate);
|
||||||
jsonw_float_field_fmt(get_json_writer(),
|
jw = get_json_writer();
|
||||||
"sample_point",
|
jsonw_name(jw, "sample_point");
|
||||||
"%.3f",
|
jsonw_printf(jw, "%.3f",
|
||||||
(float) dbt->sample_point / 1000.);
|
(float) dbt->sample_point / 1000.);
|
||||||
print_int(PRINT_JSON, "tq", NULL, dbt->tq);
|
print_int(PRINT_JSON, "tq", NULL, dbt->tq);
|
||||||
print_int(PRINT_JSON, "prop_seg", NULL, dbt->prop_seg);
|
print_int(PRINT_JSON, "prop_seg", NULL, dbt->prop_seg);
|
||||||
print_int(PRINT_JSON, "phase_seg1",
|
print_int(PRINT_JSON, "phase_seg1",
|
||||||
|
|
|
||||||
13
ip/ipmaddr.c
13
ip/ipmaddr.c
|
|
@ -289,6 +289,7 @@ static int multiaddr_list(int argc, char **argv)
|
||||||
static int multiaddr_modify(int cmd, int argc, char **argv)
|
static int multiaddr_modify(int cmd, int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct ifreq ifr = {};
|
struct ifreq ifr = {};
|
||||||
|
int family;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (cmd == RTM_NEWADDR)
|
if (cmd == RTM_NEWADDR)
|
||||||
|
|
@ -324,7 +325,17 @@ static int multiaddr_modify(int cmd, int argc, char **argv)
|
||||||
exit(-1);
|
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) {
|
if (fd < 0) {
|
||||||
perror("Cannot create socket");
|
perror("Cannot create socket");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,9 @@ static int accept_msg(const struct sockaddr_nl *who,
|
||||||
{
|
{
|
||||||
FILE *fp = (FILE *)arg;
|
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);
|
struct rtmsg *r = NLMSG_DATA(n);
|
||||||
int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*r));
|
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);
|
ll_remember_index(who, n, NULL);
|
||||||
print_headers(fp, "[LINK]", ctrl);
|
print_headers(fp, "[LINK]", ctrl);
|
||||||
print_linkinfo(who, n, arg);
|
print_linkinfo(who, n, arg);
|
||||||
return 0;
|
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_headers(fp, "[ADDR]", ctrl);
|
||||||
print_addrinfo(who, n, arg);
|
print_addrinfo(who, n, arg);
|
||||||
return 0;
|
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_headers(fp, "[ADDRLABEL]", ctrl);
|
||||||
print_addrlabel(who, n, arg);
|
print_addrlabel(who, n, arg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH ||
|
case RTM_NEWNEIGH:
|
||||||
n->nlmsg_type == RTM_GETNEIGH) {
|
case RTM_DELNEIGH:
|
||||||
|
case RTM_GETNEIGH:
|
||||||
if (preferred_family) {
|
if (preferred_family) {
|
||||||
struct ndmsg *r = NLMSG_DATA(n);
|
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_headers(fp, "[NEIGH]", ctrl);
|
||||||
print_neigh(who, n, arg);
|
print_neigh(who, n, arg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
if (n->nlmsg_type == RTM_NEWPREFIX) {
|
case RTM_NEWPREFIX:
|
||||||
print_headers(fp, "[PREFIX]", ctrl);
|
print_headers(fp, "[PREFIX]", ctrl);
|
||||||
print_prefix(who, n, arg);
|
print_prefix(who, n, arg);
|
||||||
return 0;
|
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_headers(fp, "[RULE]", ctrl);
|
||||||
print_rule(who, n, arg);
|
print_rule(who, n, arg);
|
||||||
return 0;
|
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_headers(fp, "[NETCONF]", ctrl);
|
||||||
print_netconf(who, ctrl, n, arg);
|
print_netconf(who, ctrl, n, arg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
if (n->nlmsg_type == NLMSG_TSTAMP) {
|
case RTM_DELNSID:
|
||||||
print_nlmsg_timestamp(fp, n);
|
case RTM_NEWNSID:
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (n->nlmsg_type == RTM_NEWNSID || n->nlmsg_type == RTM_DELNSID) {
|
|
||||||
print_headers(fp, "[NSID]", ctrl);
|
print_headers(fp, "[NSID]", ctrl);
|
||||||
print_nsid(who, n, arg);
|
print_nsid(who, n, arg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP &&
|
case NLMSG_ERROR:
|
||||||
n->nlmsg_type != NLMSG_DONE) {
|
case NLMSG_NOOP:
|
||||||
fprintf(fp, "Unknown message: type=0x%08x(%d) flags=0x%08x(%d)len=0x%08x(%d)\n",
|
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_type, n->nlmsg_type,
|
||||||
n->nlmsg_flags, n->nlmsg_flags, n->nlmsg_len,
|
n->nlmsg_flags, n->nlmsg_flags, n->nlmsg_len,
|
||||||
n->nlmsg_len);
|
n->nlmsg_len);
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,10 @@ int print_netconf(const struct sockaddr_nl *who, struct rtnl_ctrl_data *ctrl,
|
||||||
|
|
||||||
if (n->nlmsg_type == NLMSG_ERROR)
|
if (n->nlmsg_type == NLMSG_ERROR)
|
||||||
return -1;
|
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);
|
n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -91,6 +93,9 @@ int print_netconf(const struct sockaddr_nl *who, struct rtnl_ctrl_data *ctrl,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
open_json_object(NULL);
|
open_json_object(NULL);
|
||||||
|
if (n->nlmsg_type == RTM_DELNETCONF)
|
||||||
|
print_bool(PRINT_ANY, "deleted", "Deleted ", true);
|
||||||
|
|
||||||
print_string(PRINT_ANY, "family",
|
print_string(PRINT_ANY, "family",
|
||||||
"%s ", family_name(ncm->ncm_family));
|
"%s ", family_name(ncm->ncm_family));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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_string(PRINT_FP, NULL, "to ", NULL);
|
||||||
print_color_string(PRINT_ANY, ifa_family_color(frh->family),
|
print_color_string(PRINT_ANY, ifa_family_color(frh->family),
|
||||||
"dst", "%s ", dst);
|
"dst", "%s", dst);
|
||||||
if (frh->dst_len != host_len)
|
if (frh->dst_len != host_len)
|
||||||
print_uint(PRINT_ANY, "dstlen", "/%u ", frh->dst_len);
|
print_uint(PRINT_ANY, "dstlen", "/%u ", frh->dst_len);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,9 @@ static int dump_msg2(const struct sockaddr_nl *who,
|
||||||
|
|
||||||
static void usage(void)
|
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");
|
fprintf(stderr, "LISTofOBJECTS := [ link ] [ address ] [ route ]\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
40
lib/color.c
40
lib/color.c
|
|
@ -3,11 +3,13 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
enum color {
|
enum color {
|
||||||
C_RED,
|
C_RED,
|
||||||
|
|
@ -77,13 +79,42 @@ void enable_color(void)
|
||||||
set_color_palette();
|
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();
|
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)
|
void set_color_palette(void)
|
||||||
|
|
@ -101,6 +132,7 @@ void set_color_palette(void)
|
||||||
is_dark_bg = 1;
|
is_dark_bg = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((format(printf, 3, 4)))
|
||||||
int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...)
|
int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,7 @@ void close_json_array(enum output_type type, const char *str)
|
||||||
* functions handling different types
|
* functions handling different types
|
||||||
*/
|
*/
|
||||||
#define _PRINT_FUNC(type_name, type) \
|
#define _PRINT_FUNC(type_name, type) \
|
||||||
|
__attribute__((format(printf, 4, 0))) \
|
||||||
void print_color_##type_name(enum output_type t, \
|
void print_color_##type_name(enum output_type t, \
|
||||||
enum color_attr color, \
|
enum color_attr color, \
|
||||||
const char *key, \
|
const char *key, \
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,7 @@ void jsonw_name(json_writer_t *self, const char *name)
|
||||||
putc(' ', self->out);
|
putc(' ', self->out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((format(printf, 2, 3)))
|
||||||
void jsonw_printf(json_writer_t *self, const char *fmt, ...)
|
void jsonw_printf(json_writer_t *self, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
@ -205,11 +206,6 @@ void jsonw_null(json_writer_t *self)
|
||||||
jsonw_printf(self, "null");
|
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)
|
void jsonw_float(json_writer_t *self, double num)
|
||||||
{
|
{
|
||||||
jsonw_printf(self, "%g", 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);
|
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)
|
void jsonw_uint_field(json_writer_t *self, const char *prop, unsigned int num)
|
||||||
{
|
{
|
||||||
jsonw_name(self, prop);
|
jsonw_name(self, prop);
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ bridge \- show / manipulate bridge addresses and devices
|
||||||
\fB\-b\fR[\fIatch\fR] filename |
|
\fB\-b\fR[\fIatch\fR] filename |
|
||||||
\fB\-c\fR[\folor\fR] |
|
\fB\-c\fR[\folor\fR] |
|
||||||
\fB\-p\fR[\fIretty\fR] |
|
\fB\-p\fR[\fIretty\fR] |
|
||||||
\fB\-j\fR[\fIson\fR] }
|
\fB\-j\fR[\fIson\fR] |
|
||||||
|
\fB\-o\fR[\fIneline\fr] }
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "bridge link set"
|
.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.
|
return code will be non zero.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR "\-c" , " -color"
|
.BR \-c [ color ][ = { always | auto | never }
|
||||||
Use color output.
|
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
|
.TP
|
||||||
.BR "\-j", " \-json"
|
.BR "\-j", " \-json"
|
||||||
|
|
@ -182,6 +192,18 @@ Output results in JavaScript Object Notation (JSON).
|
||||||
.BR "\-p", " \-pretty"
|
.BR "\-p", " \-pretty"
|
||||||
When combined with -j generate a pretty JSON output.
|
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
|
.SH BRIDGE - COMMAND SYNTAX
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,10 @@ Generate JSON output.
|
||||||
.BR "\-p" , " --pretty"
|
.BR "\-p" , " --pretty"
|
||||||
When combined with -j generate a pretty JSON output.
|
When combined with -j generate a pretty JSON output.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR "\-v" , " --verbose"
|
||||||
|
Turn on verbose output.
|
||||||
|
|
||||||
.SS
|
.SS
|
||||||
.I OBJECT
|
.I OBJECT
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,14 @@ Report average over the last SECS seconds.
|
||||||
.B \-z, \-\-zeros
|
.B \-z, \-\-zeros
|
||||||
Show entries with zero activity.
|
Show entries with zero activity.
|
||||||
.TP
|
.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
|
.B \-x, \-\-extended=TYPE
|
||||||
Show extended stats of TYPE. Supported types are:
|
Show extended stats of TYPE. Supported types are:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -187,8 +187,17 @@ to
|
||||||
executes specified command over all objects, it depends if command supports this option.
|
executes specified command over all objects, it depends if command supports this option.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR "\-c" , " -color"
|
.BR \-c [ color ][ = { always | auto | never }
|
||||||
Use color output.
|
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
|
.TP
|
||||||
.BR "\-t" , " \-timestamp"
|
.BR "\-t" , " \-timestamp"
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
nstat, rtacct - network statistics tools.
|
nstat, rtacct - network statistics tools.
|
||||||
|
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
Usage: nstat [ -h?vVzrnasd:t: ] [ PATTERN [ PATTERN ] ]
|
Usage: nstat [ -h?vVzrnasd:t:jp ] [ PATTERN [ PATTERN ] ]
|
||||||
.br
|
.br
|
||||||
Usage: rtacct [ -h?vVzrnasd:t: ] [ ListOfRealms ]
|
Usage: rtacct [ -h?vVzrnasd:t: ] [ ListOfRealms ]
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ Print help
|
||||||
.B \-V, \-\-version
|
.B \-V, \-\-version
|
||||||
Print version
|
Print version
|
||||||
.TP
|
.TP
|
||||||
.B \-z, \-\-zero
|
.B \-z, \-\-zeros
|
||||||
Dump zero counters too. By default they are not shown.
|
Dump zero counters too. By default they are not shown.
|
||||||
.TP
|
.TP
|
||||||
.B \-r, \-\-reset
|
.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
|
.B \-j, \-\-json
|
||||||
Display results in JSON format.
|
Display results in JSON format.
|
||||||
.TP
|
.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.
|
Run in daemon mode collecting statistics. <INTERVAL> is interval between measurements in seconds.
|
||||||
.TP
|
.TP
|
||||||
|
.B \-t, \-\-interval <INTERVAL>
|
||||||
Time interval to average rates. Default value is 60 seconds.
|
Time interval to average rates. Default value is 60 seconds.
|
||||||
.TP
|
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
lnstat(8)
|
lnstat(8)
|
||||||
|
|
|
||||||
|
|
@ -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
|
summary from various sources. It is useful when amount of sockets is so huge
|
||||||
that parsing /proc/net/tcp is painful.
|
that parsing /proc/net/tcp is painful.
|
||||||
.TP
|
.TP
|
||||||
|
.B \-E, \-\-events
|
||||||
|
Continually display sockets as they are destroyed
|
||||||
|
.TP
|
||||||
.B \-Z, \-\-context
|
.B \-Z, \-\-context
|
||||||
As the
|
As the
|
||||||
.B \-p
|
.B \-p
|
||||||
|
|
|
||||||
|
|
@ -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
|
no-split-gso parameter can increase the maximum achievable throughput by
|
||||||
retaining the full GSO packets.
|
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
|
.SH EXAMPLES
|
||||||
# tc qdisc delete root dev eth0
|
# tc qdisc delete root dev eth0
|
||||||
.br
|
.br
|
||||||
|
|
|
||||||
|
|
@ -755,8 +755,17 @@ option was specified. Classes can be filtered only by
|
||||||
option.
|
option.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR "\ -color"
|
.BR \-c [ color ][ = { always | auto | never }
|
||||||
Use color output.
|
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
|
.TP
|
||||||
.BR "\-j", " \-json"
|
.BR "\-j", " \-json"
|
||||||
|
|
|
||||||
21
misc/ss.c
21
misc/ss.c
|
|
@ -16,6 +16,7 @@
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
@ -976,6 +977,7 @@ static int buf_update(int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Append content to buffer as part of the current field */
|
/* Append content to buffer as part of the current field */
|
||||||
|
__attribute__((format(printf, 1, 2)))
|
||||||
static void out(const char *fmt, ...)
|
static void out(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
struct column *f = current_field;
|
struct column *f = current_field;
|
||||||
|
|
@ -1093,7 +1095,7 @@ static void print_header(void)
|
||||||
{
|
{
|
||||||
while (!field_is_last(current_field)) {
|
while (!field_is_last(current_field)) {
|
||||||
if (!current_field->disabled)
|
if (!current_field->disabled)
|
||||||
out(current_field->header);
|
out("%s", current_field->header);
|
||||||
field_next();
|
field_next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3604,6 +3606,21 @@ static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh,
|
||||||
out(" %c-%c",
|
out(" %c-%c",
|
||||||
mask & 1 ? '-' : '<', mask & 2 ? '-' : '>');
|
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;
|
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;
|
req.r.udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER | UDIAG_SHOW_RQLEN;
|
||||||
if (show_mem)
|
if (show_mem)
|
||||||
req.r.udiag_show |= UDIAG_SHOW_MEMINFO;
|
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);
|
return handle_netlink_request(f, &req.nlh, sizeof(req), unix_show_sock);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -277,6 +277,7 @@ static int flatten_tree(struct ematch *head, struct ematch *tree)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((format(printf, 5, 6)))
|
||||||
int em_parse_error(int err, struct bstr *args, struct bstr *carg,
|
int em_parse_error(int err, struct bstr *args, struct bstr *carg,
|
||||||
struct ematch_util *e, char *fmt, ...)
|
struct ematch_util *e, char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,17 +12,16 @@
|
||||||
|
|
||||||
#define EMATCHKINDSIZ 16
|
#define EMATCHKINDSIZ 16
|
||||||
|
|
||||||
struct bstr
|
struct bstr {
|
||||||
{
|
|
||||||
char *data;
|
char *data;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
int quoted;
|
int quoted;
|
||||||
struct bstr *next;
|
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));
|
struct bstr *b = calloc(1, sizeof(*b));
|
||||||
|
|
||||||
|
|
@ -35,7 +34,7 @@ static inline struct bstr * bstr_new(char *data, unsigned int len)
|
||||||
return b;
|
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 len = strlen(text);
|
||||||
int d = b->len - len;
|
int d = b->len - len;
|
||||||
|
|
@ -51,12 +50,10 @@ static inline struct bstr *bstr_next(struct bstr *b)
|
||||||
return b->next;
|
return b->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern unsigned long bstrtoul(const struct bstr *b);
|
unsigned long bstrtoul(const struct bstr *b);
|
||||||
extern void bstr_print(FILE *fd, const struct bstr *b, int ascii);
|
void bstr_print(FILE *fd, const struct bstr *b, int ascii);
|
||||||
|
|
||||||
|
struct ematch {
|
||||||
struct ematch
|
|
||||||
{
|
|
||||||
struct bstr *args;
|
struct bstr *args;
|
||||||
int index;
|
int index;
|
||||||
int inverted;
|
int inverted;
|
||||||
|
|
@ -66,7 +63,7 @@ struct ematch
|
||||||
struct ematch *next;
|
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));
|
struct ematch *e = calloc(1, sizeof(*e));
|
||||||
|
|
||||||
|
|
@ -79,14 +76,12 @@ static inline struct ematch * new_ematch(struct bstr *args, int inverted)
|
||||||
return e;
|
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];
|
char kind[EMATCHKINDSIZ];
|
||||||
int kind_num;
|
int kind_num;
|
||||||
int (*parse_eopt)(struct nlmsghdr *,struct tcf_ematch_hdr *,
|
int (*parse_eopt)(struct nlmsghdr *, struct tcf_ematch_hdr *,
|
||||||
struct bstr *);
|
struct bstr *);
|
||||||
int (*parse_eopt_argv)(struct nlmsghdr *, struct tcf_ematch_hdr *,
|
int (*parse_eopt_argv)(struct nlmsghdr *, struct tcf_ematch_hdr *,
|
||||||
int, char **);
|
int, char **);
|
||||||
|
|
@ -95,7 +90,7 @@ struct ematch_util
|
||||||
struct ematch_util *next;
|
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')
|
if (*((char *) b->data) == 'l')
|
||||||
return TCF_LAYER_LINK;
|
return TCF_LAYER_LINK;
|
||||||
|
|
@ -107,9 +102,10 @@ static inline int parse_layer(struct bstr *b)
|
||||||
return INT_MAX;
|
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, ...);
|
struct ematch_util *, char *fmt, ...);
|
||||||
extern int print_ematch(FILE *, const struct rtattr *);
|
int print_ematch(FILE *, const struct rtattr *);
|
||||||
extern int parse_ematch(int *, char ***, int, struct nlmsghdr *);
|
int parse_ematch(int *, char ***, int, struct nlmsghdr *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
31
tc/m_pedit.h
31
tc/m_pedit.h
|
|
@ -71,23 +71,22 @@ struct m_pedit_util {
|
||||||
struct m_pedit_key *tkey);
|
struct m_pedit_key *tkey);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int pack_key(struct m_pedit_sel *sel, struct m_pedit_key *tkey);
|
int pack_key(struct m_pedit_sel *sel, struct m_pedit_key *tkey);
|
||||||
extern int pack_key32(__u32 retain, struct m_pedit_sel *sel,
|
int pack_key32(__u32 retain, struct m_pedit_sel *sel,
|
||||||
struct m_pedit_key *tkey);
|
struct m_pedit_key *tkey);
|
||||||
extern int pack_key16(__u32 retain, struct m_pedit_sel *sel,
|
int pack_key16(__u32 retain, struct m_pedit_sel *sel,
|
||||||
struct m_pedit_key *tkey);
|
struct m_pedit_key *tkey);
|
||||||
extern int pack_key8(__u32 retain, struct m_pedit_sel *sel,
|
int pack_key8(__u32 retain, struct m_pedit_sel *sel,
|
||||||
struct m_pedit_key *tkey);
|
struct m_pedit_key *tkey);
|
||||||
extern int parse_val(int *argc_p, char ***argv_p, __u32 *val, int type);
|
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,
|
int parse_cmd(int *argc_p, char ***argv_p, __u32 len, int type,
|
||||||
__u32 retain,
|
__u32 retain,
|
||||||
struct m_pedit_sel *sel, struct m_pedit_key *tkey);
|
struct m_pedit_sel *sel, struct m_pedit_key *tkey);
|
||||||
extern int parse_offset(int *argc_p, char ***argv_p,
|
int parse_offset(int *argc_p, char ***argv_p,
|
||||||
struct m_pedit_sel *sel, struct m_pedit_key *tkey);
|
struct m_pedit_sel *sel, struct m_pedit_key *tkey);
|
||||||
int parse_pedit(struct action_util *a, int *argc_p, char ***argv_p,
|
int parse_pedit(struct action_util *a, int *argc_p, char ***argv_p,
|
||||||
int tca_id, struct nlmsghdr *n);
|
int tca_id, struct nlmsghdr *n);
|
||||||
extern int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg);
|
int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg);
|
||||||
extern int pedit_print_xstats(struct action_util *au, FILE *f,
|
int pedit_print_xstats(struct action_util *au, FILE *f,
|
||||||
struct rtattr *xstats);
|
struct rtattr *xstats);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -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)
|
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 = {};
|
struct tc_htb_opt opt = {};
|
||||||
__u32 rtab[256], ctab[256];
|
__u32 rtab[256], ctab[256];
|
||||||
unsigned buffer = 0, cbuffer = 0;
|
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)) {
|
if (get_u32(&opt.prio, *argv, 10)) {
|
||||||
explain1("prio"); return -1;
|
explain1("prio"); return -1;
|
||||||
}
|
}
|
||||||
ok++;
|
|
||||||
} else if (matches(*argv, "mtu") == 0) {
|
} else if (matches(*argv, "mtu") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (get_u32(&mtu, *argv, 10)) {
|
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");
|
explain1("buffer");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ok++;
|
|
||||||
} else if (matches(*argv, "cburst") == 0 ||
|
} else if (matches(*argv, "cburst") == 0 ||
|
||||||
strcmp(*argv, "cbuffer") == 0 ||
|
strcmp(*argv, "cbuffer") == 0 ||
|
||||||
strcmp(*argv, "cmaxburst") == 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");
|
explain1("cbuffer");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ok++;
|
|
||||||
} else if (strcmp(*argv, "ceil") == 0) {
|
} else if (strcmp(*argv, "ceil") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (ceil64) {
|
if (ceil64) {
|
||||||
|
|
@ -186,7 +182,6 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
|
||||||
explain1("ceil");
|
explain1("ceil");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ok++;
|
|
||||||
} else if (strcmp(*argv, "rate") == 0) {
|
} else if (strcmp(*argv, "rate") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (rate64) {
|
if (rate64) {
|
||||||
|
|
@ -202,7 +197,6 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
|
||||||
explain1("rate");
|
explain1("rate");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ok++;
|
|
||||||
} else if (strcmp(*argv, "help") == 0) {
|
} else if (strcmp(*argv, "help") == 0) {
|
||||||
explain();
|
explain();
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -214,9 +208,6 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str
|
||||||
argc--; argv++;
|
argc--; argv++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if (!ok)
|
|
||||||
return 0;*/
|
|
||||||
|
|
||||||
if (!rate64) {
|
if (!rate64) {
|
||||||
fprintf(stderr, "\"rate\" is required.\n");
|
fprintf(stderr, "\"rate\" is required.\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
3
tc/tc.c
3
tc/tc.c
|
|
@ -496,8 +496,7 @@ int main(int argc, char **argv)
|
||||||
matches(argv[1], "-conf") == 0) {
|
matches(argv[1], "-conf") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
conf_file = argv[1];
|
conf_file = argv[1];
|
||||||
} else if (matches(argv[1], "-color") == 0) {
|
} else if (matches_color(argv[1], &color)) {
|
||||||
++color;
|
|
||||||
} else if (matches(argv[1], "-timestamp") == 0) {
|
} else if (matches(argv[1], "-timestamp") == 0) {
|
||||||
timestamp++;
|
timestamp++;
|
||||||
} else if (matches(argv[1], "-tshort") == 0) {
|
} else if (matches(argv[1], "-tshort") == 0) {
|
||||||
|
|
|
||||||
|
|
@ -5,26 +5,26 @@
|
||||||
|
|
||||||
extern struct rtnl_handle rth;
|
extern struct rtnl_handle rth;
|
||||||
|
|
||||||
extern int do_qdisc(int argc, char **argv);
|
int do_qdisc(int argc, char **argv);
|
||||||
extern int do_class(int argc, char **argv);
|
int do_class(int argc, char **argv);
|
||||||
extern int do_filter(int argc, char **argv, void *buf, size_t buflen);
|
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);
|
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);
|
int do_action(int argc, char **argv, void *buf, size_t buflen);
|
||||||
extern int do_tcmonitor(int argc, char **argv);
|
int do_tcmonitor(int argc, char **argv);
|
||||||
extern int do_exec(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);
|
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);
|
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);
|
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);
|
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);
|
void print_size_table(FILE *fp, const char *prefix, struct rtattr *rta);
|
||||||
|
|
||||||
struct tc_estimator;
|
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;
|
struct tc_sizespec;
|
||||||
extern int parse_size_table(int *p_argc, char ***p_argv, struct tc_sizespec *s);
|
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 check_size_table_opts(struct tc_sizespec *s);
|
||||||
|
|
||||||
extern int show_graph;
|
extern int show_graph;
|
||||||
extern bool use_names;
|
extern bool use_names;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
#ifndef _TC_RED_H_
|
#ifndef _TC_RED_H_
|
||||||
#define _TC_RED_H_ 1
|
#define _TC_RED_H_ 1
|
||||||
|
|
||||||
extern int tc_red_eval_P(unsigned qmin, unsigned qmax, double prob);
|
int tc_red_eval_P(unsigned qmin, unsigned qmax, double prob);
|
||||||
extern int tc_red_eval_ewma(unsigned qmin, unsigned burst, unsigned avpkt);
|
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_idle_damping(int wlog, unsigned avpkt, unsigned bandwidth,
|
||||||
|
__u8 *sbuf);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -14,15 +14,13 @@ TESTS_DIR := $(dir $(TESTS))
|
||||||
|
|
||||||
IPVERS := $(filter-out iproute2/Makefile,$(wildcard iproute2/*))
|
IPVERS := $(filter-out iproute2/Makefile,$(wildcard iproute2/*))
|
||||||
|
|
||||||
|
KENVFN := $(shell mktemp /tmp/tc_testkenv.XXXXXX)
|
||||||
ifneq (,$(wildcard /proc/config.gz))
|
ifneq (,$(wildcard /proc/config.gz))
|
||||||
KENV := $(shell cat /proc/config.gz | gunzip | grep ^CONFIG)
|
KCPATH := /proc/config.gz
|
||||||
else
|
else
|
||||||
KVER := $(shell uname -r)
|
KVER := $(shell uname -r)
|
||||||
KCPATHS := /lib/modules/$(KVER)/config /boot/config-$(KVER)
|
KCPATHS := /lib/modules/$(KVER)/config /boot/config-$(KVER)
|
||||||
KCPATH := $(firstword $(wildcard $(KCPATHS)))
|
KCPATH := $(firstword $(wildcard $(KCPATHS)))
|
||||||
ifneq (,$(KCPATH))
|
|
||||||
KENV := $(shell cat ${KCPATH} | grep ^CONFIG)
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: compile listtests alltests configure $(TESTS)
|
.PHONY: compile listtests alltests configure $(TESTS)
|
||||||
|
|
@ -32,6 +30,7 @@ configure:
|
||||||
|
|
||||||
compile: configure
|
compile: configure
|
||||||
echo "Entering iproute2" && cd iproute2 && $(MAKE) && cd ..;
|
echo "Entering iproute2" && cd iproute2 && $(MAKE) && cd ..;
|
||||||
|
$(MAKE) -C tools
|
||||||
|
|
||||||
listtests:
|
listtests:
|
||||||
@for t in $(TESTS); do \
|
@for t in $(TESTS); do \
|
||||||
|
|
@ -43,6 +42,9 @@ alltests: $(TESTS)
|
||||||
clean:
|
clean:
|
||||||
@echo "Removing $(RESULTS_DIR) dir ..."
|
@echo "Removing $(RESULTS_DIR) dir ..."
|
||||||
@rm -rf $(RESULTS_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
|
distclean: clean
|
||||||
echo "Entering iproute2" && cd iproute2 && $(MAKE) distclean && cd ..;
|
echo "Entering iproute2" && cd iproute2 && $(MAKE) distclean && cd ..;
|
||||||
|
|
@ -59,14 +61,22 @@ endif
|
||||||
mkdir -p $(RESULTS_DIR)/$$d; \
|
mkdir -p $(RESULTS_DIR)/$$d; \
|
||||||
done
|
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 \
|
@for i in $(IPVERS); do \
|
||||||
o=`echo $$i | sed -e 's/iproute2\///'`; \
|
o=`echo $$i | sed -e 's/iproute2\///'`; \
|
||||||
echo -n "Running $@ [$$o/`uname -r`]: "; \
|
echo -n "Running $@ [$$o/`uname -r`]: "; \
|
||||||
TMP_ERR=`mktemp /tmp/tc_testsuite.XXXXXX`; \
|
TMP_ERR=`mktemp /tmp/tc_testsuite.XXXXXX`; \
|
||||||
TMP_OUT=`mktemp /tmp/tc_testsuite.XXXXXX`; \
|
TMP_OUT=`mktemp /tmp/tc_testsuite.XXXXXX`; \
|
||||||
|
. $(KENVFN); \
|
||||||
STD_ERR="$$TMP_ERR" STD_OUT="$$TMP_OUT" \
|
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" \
|
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 \
|
if [ "$$?" = "127" ]; then \
|
||||||
echo "SKIPPED"; \
|
echo "SKIPPED"; \
|
||||||
elif [ -e "$(RESULTS_DIR)/$@.$$o.err" ]; then \
|
elif [ -e "$(RESULTS_DIR)/$@.$$o.err" ]; then \
|
||||||
|
|
@ -75,5 +85,5 @@ endif
|
||||||
echo "PASS"; \
|
echo "PASS"; \
|
||||||
fi; \
|
fi; \
|
||||||
rm "$$TMP_ERR" "$$TMP_OUT"; \
|
rm "$$TMP_ERR" "$$TMP_OUT"; \
|
||||||
dmesg > $(RESULTS_DIR)/$@.$$o.dmesg; \
|
sudo dmesg > $(RESULTS_DIR)/$@.$$o.dmesg; \
|
||||||
done
|
done
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
include ../../config.mk
|
||||||
|
|
||||||
generate_nlmsg: generate_nlmsg.c ../../lib/libnetlink.c
|
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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue