From c369dc803bfc99540f88a583171b6c3394f5338b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 31 Jul 2017 20:55:14 -0700 Subject: [PATCH 1/7] Update headers from net-next Signed-off-by: Stephen Hemminger --- include/linux/bpf.h | 10 +++++++++- include/linux/netlink.h | 17 +++++++++++++++++ include/linux/rtnetlink.h | 23 +++++++++++++++++++++-- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index fb84d2c2..49e1def7 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -104,6 +104,7 @@ enum bpf_map_type { BPF_MAP_TYPE_LPM_TRIE, BPF_MAP_TYPE_ARRAY_OF_MAPS, BPF_MAP_TYPE_HASH_OF_MAPS, + BPF_MAP_TYPE_DEVMAP, }; enum bpf_prog_type { @@ -347,6 +348,11 @@ union bpf_attr { * @flags: bit 0 - if set, redirect to ingress instead of egress * other bits - reserved * Return: TC_ACT_REDIRECT + * int bpf_redirect_map(key, map, flags) + * redirect to endpoint in map + * @key: index in map to lookup + * @map: fd of map to do lookup in + * @flags: -- * * u32 bpf_get_route_realm(skb) * retrieve a dst's tclassid @@ -591,7 +597,8 @@ union bpf_attr { FN(get_socket_uid), \ FN(set_hash), \ FN(setsockopt), \ - FN(skb_adjust_room), + FN(skb_adjust_room), \ + FN(redirect_map), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call @@ -717,6 +724,7 @@ enum xdp_action { XDP_DROP, XDP_PASS, XDP_TX, + XDP_REDIRECT, }; /* user accessible metadata for XDP packet hook diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 3a53b9aa..654f08ad 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -222,5 +222,22 @@ struct nlattr { #define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) #define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) +/* Generic 32 bitflags attribute content sent to the kernel. + * + * The value is a bitmap that defines the values being set + * The selector is a bitmask that defines which value is legit + * + * Examples: + * value = 0x0, and selector = 0x1 + * implies we are selecting bit 1 and we want to set its value to 0. + * + * value = 0x2, and selector = 0x2 + * implies we are selecting bit 2 and we want to set its value to 1. + * + */ +struct nla_bitfield32 { + __u32 value; + __u32 selector; +}; #endif /* __LINUX_NETLINK_H */ diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 1d62dad0..813e9e07 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -681,10 +681,29 @@ struct tcamsg { unsigned char tca__pad1; unsigned short tca__pad2; }; + +enum { + TCA_ROOT_UNSPEC, + TCA_ROOT_TAB, +#define TCA_ACT_TAB TCA_ROOT_TAB +#define TCAA_MAX TCA_ROOT_TAB + TCA_ROOT_FLAGS, + TCA_ROOT_COUNT, + TCA_ROOT_TIME_DELTA, /* in msecs */ + __TCA_ROOT_MAX, +#define TCA_ROOT_MAX (__TCA_ROOT_MAX - 1) +}; + #define TA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcamsg)))) #define TA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcamsg)) -#define TCA_ACT_TAB 1 /* attr type must be >=1 */ -#define TCAA_MAX 1 +/* tcamsg flags stored in attribute TCA_ROOT_FLAGS + * + * TCA_FLAG_LARGE_DUMP_ON user->kernel to request for larger than TCA_ACT_MAX_PRIO + * actions in a dump. All dump responses will contain the number of actions + * being dumped stored in for user app's consumption in TCA_ROOT_COUNT + * + */ +#define TCA_FLAG_LARGE_DUMP_ON (1 << 0) /* New extended info filters for IFLA_EXT_MASK */ #define RTEXT_FILTER_VF (1 << 0) From f73ac674d0abf414c44b87bd5da3af01a6fb64f6 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 7 Jul 2017 08:37:19 -0700 Subject: [PATCH 2/7] ip: change flag names to an array For the most of the address flags, use a table of values rather than open coding every value. This allows for easier inevitable expansion of flags. This also fixes the missing stable-privacy flag. Signed-off-by: Stephen Hemminger --- ip/ipaddress.c | 184 ++++++++++++++++++++++++------------------------- 1 file changed, 89 insertions(+), 95 deletions(-) diff --git a/ip/ipaddress.c b/ip/ipaddress.c index cf8ef818..4d37c5e0 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -1012,14 +1012,95 @@ static unsigned int get_ifa_flags(struct ifaddrmsg *ifa, ifa->ifa_flags; } +/* Mapping from argument to address flag mask */ +struct { + const char *name; + unsigned long value; +} ifa_flag_names[] = { + { "secondary", IFA_F_SECONDARY }, + { "temporary", IFA_F_SECONDARY }, + { "nodad", IFA_F_NODAD }, + { "optimistic", IFA_F_OPTIMISTIC }, + { "dadfailed", IFA_F_DADFAILED }, + { "home", IFA_F_HOMEADDRESS }, + { "deprecated", IFA_F_DEPRECATED }, + { "tentative", IFA_F_TENTATIVE }, + { "permanent", IFA_F_PERMANENT }, + { "mngtmpaddr", IFA_F_MANAGETEMPADDR }, + { "noprefixroute", IFA_F_NOPREFIXROUTE }, + { "autojoin", IFA_F_MCAUTOJOIN }, + { "stable-privacy", IFA_F_STABLE_PRIVACY }, +}; + +static void print_ifa_flags(FILE *fp, const struct ifaddrmsg *ifa, + unsigned int flags) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) { + unsigned long mask = ifa_flag_names[i].value; + + if (mask == IFA_F_PERMANENT) { + if (!(flags & mask)) + fprintf(fp, "dynamic "); + } else if (flags & mask) { + if (mask == IFA_F_SECONDARY && + ifa->ifa_family == AF_INET6) + fprintf(fp, "temporary "); + else + fprintf(fp, "%s ", ifa_flag_names[i].name); + } + + flags &= ~mask; + } + + if (flags) + fprintf(fp, "flags %02x ", flags); + +} + +static int get_filter(const char *arg) +{ + unsigned int i; + + /* Special cases */ + if (strcmp(arg, "dynamic") == 0) { + filter.flags &= ~IFA_F_PERMANENT; + filter.flagmask |= IFA_F_PERMANENT; + } else if (strcmp(arg, "primary") == 0) { + filter.flags &= ~IFA_F_SECONDARY; + filter.flagmask |= IFA_F_SECONDARY; + } else if (*arg == '-') { + for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) { + if (strcmp(arg + 1, ifa_flag_names[i].name)) + continue; + + filter.flags &= ifa_flag_names[i].value; + filter.flagmask |= ifa_flag_names[i].value; + return 0; + } + + return -1; + } else { + for (i = 0; i < ARRAY_SIZE(ifa_flag_names); i++) { + if (strcmp(arg, ifa_flag_names[i].name)) + continue; + filter.flags |= ifa_flag_names[i].value; + filter.flagmask |= ifa_flag_names[i].value; + return 0; + } + return -1; + } + + return 0; +} + int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = arg; struct ifaddrmsg *ifa = NLMSG_DATA(n); int len = n->nlmsg_len; - int deprecated = 0; - /* Use local copy of ifa_flags to not interfere with filtering code */ unsigned int ifa_flags; struct rtattr *rta_tb[IFA_MAX+1]; @@ -1144,52 +1225,9 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, rta_tb[IFA_ANYCAST])); } fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1))); - if (ifa_flags & IFA_F_SECONDARY) { - ifa_flags &= ~IFA_F_SECONDARY; - if (ifa->ifa_family == AF_INET6) - fprintf(fp, "temporary "); - else - fprintf(fp, "secondary "); - } - if (ifa_flags & IFA_F_TENTATIVE) { - ifa_flags &= ~IFA_F_TENTATIVE; - fprintf(fp, "tentative "); - } - if (ifa_flags & IFA_F_DEPRECATED) { - ifa_flags &= ~IFA_F_DEPRECATED; - deprecated = 1; - fprintf(fp, "deprecated "); - } - if (ifa_flags & IFA_F_HOMEADDRESS) { - ifa_flags &= ~IFA_F_HOMEADDRESS; - fprintf(fp, "home "); - } - if (ifa_flags & IFA_F_NODAD) { - ifa_flags &= ~IFA_F_NODAD; - fprintf(fp, "nodad "); - } - if (ifa_flags & IFA_F_MANAGETEMPADDR) { - ifa_flags &= ~IFA_F_MANAGETEMPADDR; - fprintf(fp, "mngtmpaddr "); - } - if (ifa_flags & IFA_F_NOPREFIXROUTE) { - ifa_flags &= ~IFA_F_NOPREFIXROUTE; - fprintf(fp, "noprefixroute "); - } - if (ifa_flags & IFA_F_MCAUTOJOIN) { - ifa_flags &= ~IFA_F_MCAUTOJOIN; - fprintf(fp, "autojoin "); - } - if (!(ifa_flags & IFA_F_PERMANENT)) - fprintf(fp, "dynamic "); - else - ifa_flags &= ~IFA_F_PERMANENT; - if (ifa_flags & IFA_F_DADFAILED) { - ifa_flags &= ~IFA_F_DADFAILED; - fprintf(fp, "dadfailed "); - } - if (ifa_flags) - fprintf(fp, "flags %02x ", ifa_flags); + + print_ifa_flags(fp, ifa, ifa_flags); + if (rta_tb[IFA_LABEL]) fprintf(fp, "%s", rta_getattr_str(rta_tb[IFA_LABEL])); if (rta_tb[IFA_CACHEINFO]) { @@ -1205,7 +1243,7 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, if (ci->ifa_prefered == INFINITY_LIFE_TIME) fprintf(fp, "forever"); else { - if (deprecated) + if (ifa_flags & IFA_F_DEPRECATED) fprintf(fp, "%dsec", ci->ifa_prefered); else fprintf(fp, "%usec", ci->ifa_prefered); @@ -1608,52 +1646,8 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) filter.scope = scope; } else if (strcmp(*argv, "up") == 0) { filter.up = 1; - } else if (strcmp(*argv, "dynamic") == 0) { - filter.flags &= ~IFA_F_PERMANENT; - filter.flagmask |= IFA_F_PERMANENT; - } else if (strcmp(*argv, "permanent") == 0) { - filter.flags |= IFA_F_PERMANENT; - filter.flagmask |= IFA_F_PERMANENT; - } else if (strcmp(*argv, "secondary") == 0 || - strcmp(*argv, "temporary") == 0) { - filter.flags |= IFA_F_SECONDARY; - filter.flagmask |= IFA_F_SECONDARY; - } else if (strcmp(*argv, "primary") == 0) { - filter.flags &= ~IFA_F_SECONDARY; - filter.flagmask |= IFA_F_SECONDARY; - } else if (strcmp(*argv, "tentative") == 0) { - filter.flags |= IFA_F_TENTATIVE; - filter.flagmask |= IFA_F_TENTATIVE; - } else if (strcmp(*argv, "-tentative") == 0) { - filter.flags &= ~IFA_F_TENTATIVE; - filter.flagmask |= IFA_F_TENTATIVE; - } else if (strcmp(*argv, "deprecated") == 0) { - filter.flags |= IFA_F_DEPRECATED; - filter.flagmask |= IFA_F_DEPRECATED; - } else if (strcmp(*argv, "-deprecated") == 0) { - filter.flags &= ~IFA_F_DEPRECATED; - filter.flagmask |= IFA_F_DEPRECATED; - } else if (strcmp(*argv, "home") == 0) { - filter.flags |= IFA_F_HOMEADDRESS; - filter.flagmask |= IFA_F_HOMEADDRESS; - } else if (strcmp(*argv, "nodad") == 0) { - filter.flags |= IFA_F_NODAD; - filter.flagmask |= IFA_F_NODAD; - } else if (strcmp(*argv, "mngtmpaddr") == 0) { - filter.flags |= IFA_F_MANAGETEMPADDR; - filter.flagmask |= IFA_F_MANAGETEMPADDR; - } else if (strcmp(*argv, "noprefixroute") == 0) { - filter.flags |= IFA_F_NOPREFIXROUTE; - filter.flagmask |= IFA_F_NOPREFIXROUTE; - } else if (strcmp(*argv, "autojoin") == 0) { - filter.flags |= IFA_F_MCAUTOJOIN; - filter.flagmask |= IFA_F_MCAUTOJOIN; - } else if (strcmp(*argv, "dadfailed") == 0) { - filter.flags |= IFA_F_DADFAILED; - filter.flagmask |= IFA_F_DADFAILED; - } else if (strcmp(*argv, "-dadfailed") == 0) { - filter.flags &= ~IFA_F_DADFAILED; - filter.flagmask |= IFA_F_DADFAILED; + } else if (get_filter(*argv) == 0) { + } else if (strcmp(*argv, "label") == 0) { NEXT_ARG(); filter.label = *argv; From 3da3ebfca85b8f1e8252b898453d8cb383c5c398 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Wed, 2 Aug 2017 14:57:56 +0200 Subject: [PATCH 3/7] bpf: Make bytecode-file reading a little more robust bpf_parse_string() will now correctly handle: - Extraneous whitespace, - OPs on multiple lines and - overlong file names. The added feature of allowing to have OPs on multiple lines (like e.g. tcpdump prints them) is rather a side effect of fixing detection of malformed bytecode files having random content on a second line, like e.g.: | 4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0 | foobar Cc: Daniel Borkmann Signed-off-by: Phil Sutter Acked-by: Daniel Borkmann --- lib/bpf.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/lib/bpf.c b/lib/bpf.c index e7a4d12f..4f52ad4a 100644 --- a/lib/bpf.c +++ b/lib/bpf.c @@ -208,11 +208,11 @@ static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len, if (from_file) { size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,"); - char *tmp_string, *last; + char *tmp_string, *pos, c, c_prev = ' '; FILE *fp; tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len; - tmp_string = calloc(1, tmp_len); + tmp_string = pos = calloc(1, tmp_len); if (tmp_string == NULL) return -ENOMEM; @@ -223,17 +223,33 @@ static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len, return -ENOENT; } - if (!fgets(tmp_string, tmp_len, fp)) { + while ((c = fgetc(fp)) != EOF) { + switch (c) { + case '\n': + if (c_prev != ',') + *(pos++) = ','; + break; + case ' ': + case '\t': + if (c_prev != ' ') + *(pos++) = c; + break; + default: + *(pos++) = c; + } + if (pos - tmp_string == tmp_len) + break; + c_prev = c; + } + + if (!feof(fp)) { free(tmp_string); fclose(fp); - return -EIO; + return -E2BIG; } fclose(fp); - - last = &tmp_string[strlen(tmp_string) - 1]; - if (*last == '\n') - *last = 0; + *pos = 0; *need_release = true; *bpf_string = tmp_string; From cc21ebe8431477a40bc6fdfbd61cefd826aa7e8b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 3 Aug 2017 15:57:26 -0700 Subject: [PATCH 4/7] update headers from 4.13-rc4 Signed-off-by: Stephen Hemminger --- include/linux/bpf.h | 10 +--------- include/linux/netlink.h | 17 ----------------- include/linux/rtnetlink.h | 23 ++--------------------- 3 files changed, 3 insertions(+), 47 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 49e1def7..fb84d2c2 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -104,7 +104,6 @@ enum bpf_map_type { BPF_MAP_TYPE_LPM_TRIE, BPF_MAP_TYPE_ARRAY_OF_MAPS, BPF_MAP_TYPE_HASH_OF_MAPS, - BPF_MAP_TYPE_DEVMAP, }; enum bpf_prog_type { @@ -348,11 +347,6 @@ union bpf_attr { * @flags: bit 0 - if set, redirect to ingress instead of egress * other bits - reserved * Return: TC_ACT_REDIRECT - * int bpf_redirect_map(key, map, flags) - * redirect to endpoint in map - * @key: index in map to lookup - * @map: fd of map to do lookup in - * @flags: -- * * u32 bpf_get_route_realm(skb) * retrieve a dst's tclassid @@ -597,8 +591,7 @@ union bpf_attr { FN(get_socket_uid), \ FN(set_hash), \ FN(setsockopt), \ - FN(skb_adjust_room), \ - FN(redirect_map), + FN(skb_adjust_room), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call @@ -724,7 +717,6 @@ enum xdp_action { XDP_DROP, XDP_PASS, XDP_TX, - XDP_REDIRECT, }; /* user accessible metadata for XDP packet hook diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 654f08ad..3a53b9aa 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -222,22 +222,5 @@ struct nlattr { #define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) #define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) -/* Generic 32 bitflags attribute content sent to the kernel. - * - * The value is a bitmap that defines the values being set - * The selector is a bitmask that defines which value is legit - * - * Examples: - * value = 0x0, and selector = 0x1 - * implies we are selecting bit 1 and we want to set its value to 0. - * - * value = 0x2, and selector = 0x2 - * implies we are selecting bit 2 and we want to set its value to 1. - * - */ -struct nla_bitfield32 { - __u32 value; - __u32 selector; -}; #endif /* __LINUX_NETLINK_H */ diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 813e9e07..1d62dad0 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -681,29 +681,10 @@ struct tcamsg { unsigned char tca__pad1; unsigned short tca__pad2; }; - -enum { - TCA_ROOT_UNSPEC, - TCA_ROOT_TAB, -#define TCA_ACT_TAB TCA_ROOT_TAB -#define TCAA_MAX TCA_ROOT_TAB - TCA_ROOT_FLAGS, - TCA_ROOT_COUNT, - TCA_ROOT_TIME_DELTA, /* in msecs */ - __TCA_ROOT_MAX, -#define TCA_ROOT_MAX (__TCA_ROOT_MAX - 1) -}; - #define TA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcamsg)))) #define TA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcamsg)) -/* tcamsg flags stored in attribute TCA_ROOT_FLAGS - * - * TCA_FLAG_LARGE_DUMP_ON user->kernel to request for larger than TCA_ACT_MAX_PRIO - * actions in a dump. All dump responses will contain the number of actions - * being dumped stored in for user app's consumption in TCA_ROOT_COUNT - * - */ -#define TCA_FLAG_LARGE_DUMP_ON (1 << 0) +#define TCA_ACT_TAB 1 /* attr type must be >=1 */ +#define TCAA_MAX 1 /* New extended info filters for IFLA_EXT_MASK */ #define RTEXT_FILTER_VF (1 << 0) From 34705c807a38909247d1bb29ccdffe42e5c1dab3 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 1 Aug 2017 18:36:11 +0200 Subject: [PATCH 5/7] Really fix get_addr() and get_prefix() error messages Both functions take the desired address family as a parameter. So using that to notify the user what address family was expected is correct, unlike using dst->family which will tell the user only what address family was specified. The situation which commit 334af76143368 tried to fix was when 'ip' would accept addresses from multiple families. In that case, the family parameter is set to AF_UNSPEC so that get_addr_1() may accept any valid address. This patch introduces a wrapper around family_name() which returns the string "any valid" for AF_UNSPEC instead of the three question marks unsuitable for use in error messages. Tests for AF_UNSPEC: | # ip a a 256.10.166.1/24 dev d0 | Error: any valid prefix is expected rather than "256.10.166.1/24". | # ip neighbor add proxy 2001:db8::g dev d0 | Error: any valid address is expected rather than "2001:db8::g". Tests for explicit address family: | # ip -6 addrlabel add prefix 1.1.1.1/24 label 123 | Error: inet6 prefix is expected rather than "1.1.1.1/24". | # ip -4 addrlabel add prefix dead:beef::1/24 label 123 | Error: inet prefix is expected rather than "dead:beef::1/24". Reported-by: Jaroslav Aster Fixes: 334af76143368 ("fix get_addr() and get_prefix() error messages") Signed-off-by: Phil Sutter --- lib/utils.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/utils.c b/lib/utils.c index 9aa3219c..9143ed22 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -616,12 +616,19 @@ done: return err; } +static const char *family_name_verbose(int family) +{ + if (family == AF_UNSPEC) + return "any valid"; + return family_name(family); +} + int get_addr(inet_prefix *dst, const char *arg, int family) { if (get_addr_1(dst, arg, family)) { fprintf(stderr, "Error: %s address is expected rather than \"%s\".\n", - family_name(dst->family), arg); + family_name_verbose(family), arg); exit(1); } return 0; @@ -639,7 +646,7 @@ int get_prefix(inet_prefix *dst, char *arg, int family) if (get_prefix_1(dst, arg, family)) { fprintf(stderr, "Error: %s prefix is expected rather than \"%s\".\n", - family_name(dst->family), arg); + family_name_verbose(family), arg); exit(1); } return 0; From e2a055dd23f0e7527a987c24687cb6b0b86f0cde Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 3 Aug 2017 17:00:51 +0200 Subject: [PATCH 6/7] tc-simple: Fix documentation - CONTROL has to come last, otherwise 'index' applies to gact and not simple itself. - Man page wasn't updated to reflect syntax changes. Signed-off-by: Phil Sutter --- man/man8/tc-simple.8 | 29 ++++++++++++++++++++++++++--- tc/m_simple.c | 4 ++-- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/man/man8/tc-simple.8 b/man/man8/tc-simple.8 index 2206dc3b..7363ab56 100644 --- a/man/man8/tc-simple.8 +++ b/man/man8/tc-simple.8 @@ -6,15 +6,37 @@ simple - basic example action .in +8 .ti -8 .BR tc " ... " "action simple" -.I STRING +[ +.BI sdata " STRING" +] [ +.BI index " INDEX" +] [ +.I CONTROL +] + +.ti -8 +.IR CONTROL " := {" +.BR reclassify " | " pipe " | " drop " | " continue " | " ok " }" + .SH DESCRIPTION This is a pedagogical example rather than an actually useful action. Upon every access, it prints the given .I STRING which may be of arbitrary length. .SH OPTIONS .TP -.I STRING +.BI sdata " STRING" The actual string to print. +.TP +.BI index " INDEX" +Optional action index value. +.TP +.I CONTROL +Indicate how +.B tc +should proceed after executing the action. For a description of the possible +.I CONTROL +values, see +.BR tc-actions (8). .SH EXAMPLES The following example makes the kernel yell "Incoming ICMP!" every time it sees an incoming ICMP on eth0. Steps are: @@ -36,7 +58,7 @@ display stats again and observe increment by 1 .EX hadi@noma1:$ tc qdisc add dev eth0 ingress hadi@noma1:$tc filter add dev eth0 parent ffff: protocol ip prio 5 \\ - u32 match ip protocol 1 0xff flowid 1:1 action simple "Incoming ICMP" + u32 match ip protocol 1 0xff flowid 1:1 action simple sdata "Incoming ICMP" hadi@noma1:$ sudo tc -s filter ls dev eth0 parent ffff: filter protocol ip pref 5 u32 @@ -74,3 +96,4 @@ display stats again and observe increment by 1 .EE .SH SEE ALSO .BR tc (8) +.BR tc-actions (8) diff --git a/tc/m_simple.c b/tc/m_simple.c index a4457c70..800cf7d7 100644 --- a/tc/m_simple.c +++ b/tc/m_simple.c @@ -81,10 +81,10 @@ #endif static void explain(void) { - fprintf(stderr, "Usage:... simple [sdata STRING] [CONTROL] [index INDEX]\n"); + fprintf(stderr, "Usage:... simple [sdata STRING] [index INDEX] [CONTROL]\n"); fprintf(stderr, "\tSTRING being an arbitrary string\n" - "\tCONTROL := reclassify|pipe|drop|continue|ok\n" "\tINDEX := optional index value used\n"); + "\tCONTROL := reclassify|pipe|drop|continue|ok\n" } static void usage(void) From 620fc6696d4f4e9ad540a45892873b0382907739 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 3 Aug 2017 16:10:18 -0700 Subject: [PATCH 7/7] tc: fix m_simple usage Signed-off-by: Stephen Hemminger --- tc/m_simple.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tc/m_simple.c b/tc/m_simple.c index 800cf7d7..f8937bca 100644 --- a/tc/m_simple.c +++ b/tc/m_simple.c @@ -83,8 +83,8 @@ static void explain(void) { fprintf(stderr, "Usage:... simple [sdata STRING] [index INDEX] [CONTROL]\n"); fprintf(stderr, "\tSTRING being an arbitrary string\n" - "\tINDEX := optional index value used\n"); - "\tCONTROL := reclassify|pipe|drop|continue|ok\n" + "\tINDEX := optional index value used\n" + "\tCONTROL := reclassify|pipe|drop|continue|ok\n"); } static void usage(void)