diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7d6864c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/iproute2-4.18.0.tar.xz diff --git a/.iproute.metadata b/.iproute.metadata new file mode 100644 index 0000000..9a32132 --- /dev/null +++ b/.iproute.metadata @@ -0,0 +1 @@ +ff02c7352bae407a76d71b36558700bb489026fc SOURCES/iproute2-4.18.0.tar.xz diff --git a/SOURCES/0001-man-bridge.8-Document-oneline-option.patch b/SOURCES/0001-man-bridge.8-Document-oneline-option.patch new file mode 100644 index 0000000..964901d --- /dev/null +++ b/SOURCES/0001-man-bridge.8-Document-oneline-option.patch @@ -0,0 +1,58 @@ +From 7a9b3fa0fe560cb209f01642e6591ff0b5d42d12 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:36:09 +0200 +Subject: [PATCH] man: bridge.8: Document -oneline option + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1612704 +Upstream Status: iproute2.git commit 05758f5c7b357 + +commit 05758f5c7b357c53b53e16604bcdfb269fc68a13 +Author: Phil Sutter +Date: Thu Aug 16 12:27:53 2018 +0200 + + man: bridge.8: Document -oneline option + + Copied the description from ip.8. + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + man/man8/bridge.8 | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 +index e7f7148..95851e0 100644 +--- a/man/man8/bridge.8 ++++ b/man/man8/bridge.8 +@@ -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" +@@ -181,6 +182,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 + +-- +1.8.3.1 + diff --git a/SOURCES/0002-bridge-trivial-Make-help-text-consistent.patch b/SOURCES/0002-bridge-trivial-Make-help-text-consistent.patch new file mode 100644 index 0000000..fab3de3 --- /dev/null +++ b/SOURCES/0002-bridge-trivial-Make-help-text-consistent.patch @@ -0,0 +1,39 @@ +From 653ed98ba60d13b2c11338fe4d766eaf8eb5b364 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:36:09 +0200 +Subject: [PATCH] bridge: trivial: Make help text consistent + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1612704 +Upstream Status: iproute2.git commit f9ff0cd69c451 + +commit f9ff0cd69c4514bc78657d33459655248c9e1357 +Author: Phil Sutter +Date: Thu Aug 16 12:27:54 2018 +0200 + + bridge: trivial: Make help text consistent + + Change curly braces into brackets for -json option in help text to be + consistent with the rest. + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + bridge/bridge.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/bridge/bridge.c b/bridge/bridge.c +index 7fcfe11..28e1381 100644 +--- a/bridge/bridge.c ++++ b/bridge/bridge.c +@@ -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); + } + +-- +1.8.3.1 + diff --git a/SOURCES/0003-devlink-trivial-Make-help-text-consistent.patch b/SOURCES/0003-devlink-trivial-Make-help-text-consistent.patch new file mode 100644 index 0000000..6db3c0b --- /dev/null +++ b/SOURCES/0003-devlink-trivial-Make-help-text-consistent.patch @@ -0,0 +1,40 @@ +From fbcb1d0f1411bb21c9045a03188345e9c550624b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:36:09 +0200 +Subject: [PATCH] devlink: trivial: Make help text consistent + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1612704 +Upstream Status: iproute2.git commit bb75b9bf2f3fa +Conflicts: Context change due to missing 'region' support. + +commit bb75b9bf2f3fa392807bf09ed41eef25b89e1e82 +Author: Phil Sutter +Date: Thu Aug 16 12:27:55 2018 +0200 + + devlink: trivial: Make help text consistent + + Typically the part of the flag in brackets completes the leading part + instead of repeating it. + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + devlink/devlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/devlink/devlink.c b/devlink/devlink.c +index df2c66d..1142d16 100644 +--- a/devlink/devlink.c ++++ b/devlink/devlink.c +@@ -4492,7 +4492,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 }\n" +- " OPTIONS := { -V[ersion] | -n[no-nice-names] | -j[json] | -p[pretty] | -v[verbose] }\n"); ++ " OPTIONS := { -V[ersion] | -n[o-nice-names] | -j[json] | -p[pretty] | -v[verbose] }\n"); + } + + static int dl_cmd(struct dl *dl, int argc, char **argv) +-- +1.8.3.1 + diff --git a/SOURCES/0004-man-devlink.8-Document-verbose-option.patch b/SOURCES/0004-man-devlink.8-Document-verbose-option.patch new file mode 100644 index 0000000..460eb6c --- /dev/null +++ b/SOURCES/0004-man-devlink.8-Document-verbose-option.patch @@ -0,0 +1,40 @@ +From 6ab77b078026ed63e0234c1c1645b665723b0509 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:38:04 +0200 +Subject: [PATCH] man: devlink.8: Document -verbose option + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1612704 +Upstream Status: iproute2.git commit 29b1430ba9aa9 + +commit 29b1430ba9aa9bceb42b07232f5138e511034a5a +Author: Phil Sutter +Date: Thu Aug 16 12:27:56 2018 +0200 + + man: devlink.8: Document -verbose option + + This was the only bit missing in comparison to devlink help text. + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + man/man8/devlink.8 | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/man/man8/devlink.8 b/man/man8/devlink.8 +index efc6e62..92972b7 100644 +--- a/man/man8/devlink.8 ++++ b/man/man8/devlink.8 +@@ -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 + +-- +1.8.3.1 + diff --git a/SOURCES/0005-genl-Fix-help-text.patch b/SOURCES/0005-genl-Fix-help-text.patch new file mode 100644 index 0000000..81f271f --- /dev/null +++ b/SOURCES/0005-genl-Fix-help-text.patch @@ -0,0 +1,44 @@ +From 83af05569ffb9d607438f93d98c5ead84b1cc5ac Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:38:04 +0200 +Subject: [PATCH] genl: Fix help text + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1612704 +Upstream Status: iproute2.git commit d94974bc91eb2 + +commit d94974bc91eb2aa2df4592140e1aa3ea0d3cddba +Author: Phil Sutter +Date: Thu Aug 16 12:27:57 2018 +0200 + + genl: Fix help text + + The '| help' part was misleading: In fact, 'genl help' does not work but + 'genl help' does. Fix the help text to make that clear. + + In addition to that, list -Version and -help flags as well. + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + genl/genl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/genl/genl.c b/genl/genl.c +index 20ecb8b..1940a23 100644 +--- a/genl/genl.c ++++ b/genl/genl.c +@@ -98,9 +98,9 @@ static void usage(void) __attribute__((noreturn)); + + static void usage(void) + { +- fprintf(stderr, "Usage: genl [ OPTIONS ] OBJECT | help }\n" ++ fprintf(stderr, "Usage: genl [ OPTIONS ] OBJECT [help] }\n" + "where OBJECT := { ctrl etc }\n" +- " OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] }\n"); ++ " OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -V[ersion] | -h[elp] }\n"); + exit(-1); + } + +-- +1.8.3.1 + diff --git a/SOURCES/0006-man-ifstat.8-Document-json-and-pretty-options.patch b/SOURCES/0006-man-ifstat.8-Document-json-and-pretty-options.patch new file mode 100644 index 0000000..18142aa --- /dev/null +++ b/SOURCES/0006-man-ifstat.8-Document-json-and-pretty-options.patch @@ -0,0 +1,42 @@ +From a2e5a2d8f8c41fb4f87c66d827f3e22035a11dd7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:38:04 +0200 +Subject: [PATCH] man: ifstat.8: Document --json and --pretty options + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1612704 +Upstream Status: iproute2.git commit a486d25b9cbfc + +commit a486d25b9cbfc3469e30297495333d95a5576bdc +Author: Phil Sutter +Date: Thu Aug 16 12:27:58 2018 +0200 + + man: ifstat.8: Document --json and --pretty options + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + man/man8/ifstat.8 | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/man/man8/ifstat.8 b/man/man8/ifstat.8 +index 3ba0088..8cd164d 100644 +--- a/man/man8/ifstat.8 ++++ b/man/man8/ifstat.8 +@@ -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: + +-- +1.8.3.1 + diff --git a/SOURCES/0007-man-rtacct.8-Fix-nstat-options.patch b/SOURCES/0007-man-rtacct.8-Fix-nstat-options.patch new file mode 100644 index 0000000..84cc481 --- /dev/null +++ b/SOURCES/0007-man-rtacct.8-Fix-nstat-options.patch @@ -0,0 +1,69 @@ +From f586cb6ed5543621ec55ac07a6d2b72504c9c65b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:38:04 +0200 +Subject: [PATCH] man: rtacct.8: Fix nstat options + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1612704 +Upstream Status: iproute2.git commit 71170d854e96d + +commit 71170d854e96d2e7dff338f482cb23dfadbbd702 +Author: Phil Sutter +Date: Thu Aug 16 12:28:00 2018 +0200 + + man: rtacct.8: Fix nstat options + + Add missing --pretty and --json options, correct --zero to --zeros and + correct the mess around --scan/--interval including broken man page + formatting. + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + man/man8/rtacct.8 | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/man/man8/rtacct.8 b/man/man8/rtacct.8 +index 01321e6..ccdbf6c 100644 +--- a/man/man8/rtacct.8 ++++ b/man/man8/rtacct.8 +@@ -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 ++.B \-p, \-\-pretty ++When combined with ++.BR \-\-json , ++pretty print the output. ++.TP ++.B \-d, \-\-scan + Run in daemon mode collecting statistics. is interval between measurements in seconds. + .TP +- ++.B \-t, \-\-interval + Time interval to average rates. Default value is 60 seconds. +-.TP + + .SH SEE ALSO + lnstat(8) +-- +1.8.3.1 + diff --git a/SOURCES/0008-rtmon-List-options-in-help-text.patch b/SOURCES/0008-rtmon-List-options-in-help-text.patch new file mode 100644 index 0000000..4cdf9d8 --- /dev/null +++ b/SOURCES/0008-rtmon-List-options-in-help-text.patch @@ -0,0 +1,38 @@ +From b5ebd3fee37bc9d1832c545f605c639140b8d6f1 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:38:04 +0200 +Subject: [PATCH] rtmon: List options in help text + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1612704 +Upstream Status: iproute2.git commit 6417c06b59b07 + +commit 6417c06b59b0731bcff4c0999661b256be6f52cb +Author: Phil Sutter +Date: Thu Aug 16 12:28:01 2018 +0200 + + rtmon: List options in help text + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + ip/rtmon.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/ip/rtmon.c b/ip/rtmon.c +index acc11df..0e795f7 100644 +--- a/ip/rtmon.c ++++ b/ip/rtmon.c +@@ -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); + } +-- +1.8.3.1 + diff --git a/SOURCES/0009-man-ss.8-Describe-events-option.patch b/SOURCES/0009-man-ss.8-Describe-events-option.patch new file mode 100644 index 0000000..f6882f0 --- /dev/null +++ b/SOURCES/0009-man-ss.8-Describe-events-option.patch @@ -0,0 +1,37 @@ +From 222a4bb5ed730ff84a984a49d4f7fea39e930f97 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:38:04 +0200 +Subject: [PATCH] man: ss.8: Describe --events option + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1612704 +Upstream Status: iproute2.git commit d559db725cfe0 + +commit d559db725cfe033718d7bcfff01285c194a6e92d +Author: Phil Sutter +Date: Thu Aug 16 12:28:02 2018 +0200 + + man: ss.8: Describe --events option + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + man/man8/ss.8 | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/man/man8/ss.8 b/man/man8/ss.8 +index 28033d8..7a6572b 100644 +--- a/man/man8/ss.8 ++++ b/man/man8/ss.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 + 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 +-- +1.8.3.1 + diff --git a/SOURCES/0010-ip-Add-missing-M-flag-to-help-text.patch b/SOURCES/0010-ip-Add-missing-M-flag-to-help-text.patch new file mode 100644 index 0000000..7ee55c1 --- /dev/null +++ b/SOURCES/0010-ip-Add-missing-M-flag-to-help-text.patch @@ -0,0 +1,36 @@ +From 093a6272457a68f18bd992f3667051bcd31e32bc Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:38:04 +0200 +Subject: [PATCH] ip: Add missing -M flag to help text + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1612704 +Upstream Status: iproute2.git commit 644b9c238c2dd + +commit 644b9c238c2dde8b0b931d153fc6719e00ebfc6b +Author: Phil Sutter +Date: Thu Aug 16 12:27:59 2018 +0200 + + ip: Add missing -M flag to help text + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + ip/ip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/ip.c b/ip/ip.c +index 71d5170..bb964f3 100644 +--- a/ip/ip.c ++++ b/ip/ip.c +@@ -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"); +-- +1.8.3.1 + diff --git a/SOURCES/0011-iprule-Fix-destination-prefix-output.patch b/SOURCES/0011-iprule-Fix-destination-prefix-output.patch new file mode 100644 index 0000000..0ac6054 --- /dev/null +++ b/SOURCES/0011-iprule-Fix-destination-prefix-output.patch @@ -0,0 +1,47 @@ +From deef2321cf38ef0314bea307dbc27d376ad39624 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:45:38 +0200 +Subject: [PATCH] iprule: Fix destination prefix output + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1623503 +Upstream Status: iproute2.git commit 1a75322c5a8de + +commit 1a75322c5a8dee6e1ed0017d76c87ef85c505b98 +Author: Stefan Bader +Date: Tue Aug 28 16:27:29 2018 +0200 + + iprule: Fix destination prefix output + + When adding support for JSON output the new code for printing + the destination prefix adds a stray blank character before + the bitmask. This causes some user-space parsing to fail. + + Current output: + ...: from x.x.x.x/l to y.y.y.y /l + Previous output: + ...: from x.x.x.x/l to y.y.y.y/l + + Fixes: 0dd4ccc5 "iprule: add json support" + Signed-off-by: Stefan Bader + Acked-by: Luca Boccassi + Signed-off-by: Stephen Hemminger +--- + ip/iprule.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iprule.c b/ip/iprule.c +index 8b94214..744d6d8 100644 +--- a/ip/iprule.c ++++ b/ip/iprule.c +@@ -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 +-- +1.8.3.1 + diff --git a/SOURCES/0012-tc-act_tunnel_key-Enable-setup-of-tos-and-ttl.patch b/SOURCES/0012-tc-act_tunnel_key-Enable-setup-of-tos-and-ttl.patch new file mode 100644 index 0000000..9e38110 --- /dev/null +++ b/SOURCES/0012-tc-act_tunnel_key-Enable-setup-of-tos-and-ttl.patch @@ -0,0 +1,147 @@ +From b24c686f3e5bb0acbebf40c3e7f5a16f0582fd64 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:55:45 +0200 +Subject: [PATCH] tc/act_tunnel_key: Enable setup of tos and ttl + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1615915 +Upstream Status: iproute2.git commit 9f89b0cc0eda2 +Conflicts: Context change due to missing Geneve support. + +commit 9f89b0cc0eda2ef52d8850b0610f3e2e09fd7c1c +Author: Or Gerlitz +Date: Thu Jul 19 14:02:14 2018 +0300 + + tc/act_tunnel_key: Enable setup of tos and ttl + + Allow to set tos and ttl for the tunnel. + + For example, here's encap rule that sets tos to the tunnel: + + tc filter add dev eth0_0 protocol ip parent ffff: prio 10 flower \ + src_mac e4:11:22:33:44:50 dst_mac e4:11:22:33:44:70 \ + action tunnel_key set src_ip 192.168.10.1 dst_ip 192.168.10.2 id 100 dst_port 4789 tos 0x30 \ + action mirred egress redirect dev vxlan_sys_4789 + + Signed-off-by: Or Gerlitz + Reviewed-by: Roi Dayan + Acked-by: Jiri Pirko + Signed-off-by: David Ahern +--- + man/man8/tc-tunnel_key.8 | 8 ++++++++ + tc/m_tunnel_key.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 61 insertions(+) + +diff --git a/man/man8/tc-tunnel_key.8 b/man/man8/tc-tunnel_key.8 +index e979a74..71cee5b 100644 +--- a/man/man8/tc-tunnel_key.8 ++++ b/man/man8/tc-tunnel_key.8 +@@ -16,6 +16,8 @@ tunnel_key - Tunnel metadata manipulation + .IR ADDRESS + .BI id " KEY_ID" + .BI dst_port " UDP_PORT" ++.BI tos " TOS" ++.BI ttl " TTL" + .RB "[ " csum " | " nocsum " ]" + + .SH DESCRIPTION +@@ -79,6 +81,12 @@ Outer header destination IP address (IPv4 or IPv6) + .B dst_port + Outer header destination UDP port + .TP ++.B tos ++Outer header TOS ++.TP ++.B ttl ++Outer header TTL ++.TP + .RB [ no ] csum + Controlls outer UDP checksum. When set to + .B csum +diff --git a/tc/m_tunnel_key.c b/tc/m_tunnel_key.c +index 0fa4615..8d0a8d1 100644 +--- a/tc/m_tunnel_key.c ++++ b/tc/m_tunnel_key.c +@@ -81,6 +81,22 @@ static int tunnel_key_parse_dst_port(char *str, int type, struct nlmsghdr *n) + return 0; + } + ++static int tunnel_key_parse_tos_ttl(char *str, int type, struct nlmsghdr *n) ++{ ++ int ret; ++ __u8 val; ++ ++ ret = get_u8(&val, str, 10); ++ if (ret) ++ ret = get_u8(&val, str, 16); ++ if (ret) ++ return -1; ++ ++ addattr8(n, MAX_MSG, type, val); ++ ++ return 0; ++} ++ + static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p, + int tca_id, struct nlmsghdr *n) + { +@@ -157,6 +173,22 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p, + fprintf(stderr, "Illegal \"dst port\"\n"); + return -1; + } ++ } else if (matches(*argv, "tos") == 0) { ++ NEXT_ARG(); ++ ret = tunnel_key_parse_tos_ttl(*argv, ++ TCA_TUNNEL_KEY_ENC_TOS, n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"tos\"\n"); ++ return -1; ++ } ++ } else if (matches(*argv, "ttl") == 0) { ++ NEXT_ARG(); ++ ret = tunnel_key_parse_tos_ttl(*argv, ++ TCA_TUNNEL_KEY_ENC_TTL, n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"ttl\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "csum") == 0) { + csum = 1; + } else if (matches(*argv, "nocsum") == 0) { +@@ -260,6 +292,23 @@ static void tunnel_key_print_flag(FILE *f, const char *name_on, + rta_getattr_u8(attr) ? name_on : name_off); + } + ++static void tunnel_key_print_tos_ttl(FILE *f, char *name, ++ struct rtattr *attr) ++{ ++ if (!attr) ++ return; ++ ++ if (matches(name, "tos") == 0 && rta_getattr_u8(attr) != 0) { ++ print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_uint(PRINT_ANY, "tos", "\ttos 0x%x", ++ rta_getattr_u8(attr)); ++ } else if (matches(name, "ttl") == 0 && rta_getattr_u8(attr) != 0) { ++ print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_uint(PRINT_ANY, "ttl", "\tttl %u", ++ rta_getattr_u8(attr)); ++ } ++} ++ + static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg) + { + struct rtattr *tb[TCA_TUNNEL_KEY_MAX + 1]; +@@ -299,6 +348,10 @@ static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg) + tb[TCA_TUNNEL_KEY_ENC_DST_PORT]); + tunnel_key_print_flag(f, "nocsum", "csum", + tb[TCA_TUNNEL_KEY_NO_CSUM]); ++ tunnel_key_print_tos_ttl(f, "tos", ++ tb[TCA_TUNNEL_KEY_ENC_TOS]); ++ tunnel_key_print_tos_ttl(f, "ttl", ++ tb[TCA_TUNNEL_KEY_ENC_TTL]); + break; + } + print_action_control(f, " ", parm->action, ""); +-- +1.8.3.1 + diff --git a/SOURCES/0013-tc-flower-Add-match-on-encapsulating-tos-ttl.patch b/SOURCES/0013-tc-flower-Add-match-on-encapsulating-tos-ttl.patch new file mode 100644 index 0000000..f5424be --- /dev/null +++ b/SOURCES/0013-tc-flower-Add-match-on-encapsulating-tos-ttl.patch @@ -0,0 +1,127 @@ +From 23c57e53c5dfdaf113ecf1ebde8e04e8c7a10c50 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 20:56:18 +0200 +Subject: [PATCH] tc/flower: Add match on encapsulating tos/ttl + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1615915 +Upstream Status: iproute2.git commit 761ec9e29ff86 + +commit 761ec9e29ff867452057f59dc6ca430688b409ea +Author: Or Gerlitz +Date: Thu Jul 19 14:02:15 2018 +0300 + + tc/flower: Add match on encapsulating tos/ttl + + Add matching on tos/ttl of the IP tunnel headers. + + For example, here's decap rule that matches on the tunnel tos: + + tc filter add dev vxlan_sys_4789 protocol ip parent ffff: prio 10 flower \ + enc_src_ip 192.168.10.2 enc_dst_ip 192.168.10.1 enc_key_id 100 enc_dst_port 4789 enc_tos 0x30 \ + src_mac e4:11:22:33:44:70 dst_mac e4:11:22:33:44:50 \ + action tunnel_key unset \ + action mirred egress redirect dev eth0_0 + + Signed-off-by: Or Gerlitz + Reviewed-by: Roi Dayan + Acked-by: Jiri Pirko + Signed-off-by: David Ahern +--- + man/man8/tc-flower.8 | 14 +++++++++++++- + tc/f_flower.c | 27 +++++++++++++++++++++++++++ + 2 files changed, 40 insertions(+), 1 deletion(-) + +diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8 +index 4f3714b..f917f24 100644 +--- a/man/man8/tc-flower.8 ++++ b/man/man8/tc-flower.8 +@@ -70,6 +70,10 @@ flower \- flow based traffic control filter + .IR ipv4_address " | " ipv6_address " } | " + .B enc_dst_port + .IR port_number " | " ++.B enc_tos ++.IR TOS " | " ++.B enc_ttl ++.IR TTL " | " + .BR ip_flags + .IR IP_FLAGS + .SH DESCRIPTION +@@ -252,6 +256,10 @@ bits is assumed. + .BI enc_src_ip " PREFIX" + .TQ + .BI enc_dst_port " NUMBER" ++.TQ ++.BI enc_tos " NUMBER" ++.TQ ++.BI enc_ttl " NUMBER" + Match on IP tunnel metadata. Key id + .I NUMBER + is a 32 bit tunnel key id (e.g. VNI for VXLAN tunnel). +@@ -260,7 +268,11 @@ must be a valid IPv4 or IPv6 address optionally followed by a slash and the + prefix length. If the prefix is missing, \fBtc\fR assumes a full-length + host match. Dst port + .I NUMBER +-is a 16 bit UDP dst port. ++is a 16 bit UDP dst port. Tos ++.I NUMBER ++is an 8 bit tos (dscp+ecn) value, ttl ++.I NUMBER ++is an 8 bit time-to-live value. + .TP + .BI ip_flags " IP_FLAGS" + .I IP_FLAGS +diff --git a/tc/f_flower.c b/tc/f_flower.c +index 1dfd57d..cd102f2 100644 +--- a/tc/f_flower.c ++++ b/tc/f_flower.c +@@ -74,6 +74,8 @@ static void explain(void) + " enc_dst_ip [ IPV4-ADDR | IPV6-ADDR ] |\n" + " enc_src_ip [ IPV4-ADDR | IPV6-ADDR ] |\n" + " enc_key_id [ KEY-ID ] |\n" ++ " enc_tos MASKED-IP_TOS |\n" ++ " enc_ttl MASKED-IP_TTL |\n" + " ip_flags IP-FLAGS | \n" + " enc_dst_port [ port_number ] }\n" + " FILTERID := X:Y:Z\n" +@@ -972,6 +974,26 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + fprintf(stderr, "Illegal \"enc_dst_port\"\n"); + return -1; + } ++ } else if (matches(*argv, "enc_tos") == 0) { ++ NEXT_ARG(); ++ ret = flower_parse_ip_tos_ttl(*argv, ++ TCA_FLOWER_KEY_ENC_IP_TOS, ++ TCA_FLOWER_KEY_ENC_IP_TOS_MASK, ++ n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"enc_tos\"\n"); ++ return -1; ++ } ++ } else if (matches(*argv, "enc_ttl") == 0) { ++ NEXT_ARG(); ++ ret = flower_parse_ip_tos_ttl(*argv, ++ TCA_FLOWER_KEY_ENC_IP_TTL, ++ TCA_FLOWER_KEY_ENC_IP_TTL_MASK, ++ n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"enc_ttl\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "action") == 0) { + NEXT_ARG(); + ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n); +@@ -1463,6 +1485,11 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, + + flower_print_port("enc_dst_port", tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]); + ++ flower_print_ip_attr("enc_tos", tb[TCA_FLOWER_KEY_ENC_IP_TOS], ++ tb[TCA_FLOWER_KEY_ENC_IP_TOS_MASK]); ++ flower_print_ip_attr("enc_ttl", tb[TCA_FLOWER_KEY_ENC_IP_TTL], ++ tb[TCA_FLOWER_KEY_ENC_IP_TTL_MASK]); ++ + flower_print_matching_flags("ip_flags", FLOWER_IP_FLAGS, + tb[TCA_FLOWER_KEY_FLAGS], + tb[TCA_FLOWER_KEY_FLAGS_MASK]); +-- +1.8.3.1 + diff --git a/SOURCES/0014-Update-kernel-headers.patch b/SOURCES/0014-Update-kernel-headers.patch new file mode 100644 index 0000000..131b654 --- /dev/null +++ b/SOURCES/0014-Update-kernel-headers.patch @@ -0,0 +1,668 @@ +From 7bd1daafe80ecd7e7419616fabadfe41c6e4fe7a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 13 Sep 2018 21:29:59 +0200 +Subject: [PATCH] Update kernel headers + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1615915 +Upstream Status: RHEL-only + +This updates include/uapi/linux to the state of upstream commit +761ec9e29ff867452057f59dc6ca430688b409ea. +--- + include/uapi/linux/bpf.h | 9 +- + include/uapi/linux/btf.h | 113 +++++++++++++++++++++++++ + include/uapi/linux/devlink.h | 42 ++++++++++ + include/uapi/linux/if_link.h | 4 + + include/uapi/linux/ila.h | 1 + + include/uapi/linux/pkt_cls.h | 9 ++ + include/uapi/linux/pkt_sched.h | 135 ++++++++++++++++++++++++++++++ + include/uapi/linux/sctp.h | 5 ++ + include/uapi/linux/tc_act/tc_pedit.h | 9 +- + include/uapi/linux/tc_act/tc_skbedit.h | 2 + + include/uapi/linux/tc_act/tc_tunnel_key.h | 28 +++++++ + include/uapi/linux/tcp.h | 4 - + include/uapi/linux/tipc_netlink.h | 14 ++++ + 13 files changed, 365 insertions(+), 10 deletions(-) + create mode 100644 include/uapi/linux/btf.h + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 57e7390..b9a6367 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -1826,7 +1826,7 @@ union bpf_attr { + * A non-negative value equal to or less than *size* on success, + * or a negative error in case of failure. + * +- * int skb_load_bytes_relative(const struct sk_buff *skb, u32 offset, void *to, u32 len, u32 start_header) ++ * int bpf_skb_load_bytes_relative(const struct sk_buff *skb, u32 offset, void *to, u32 len, u32 start_header) + * Description + * This helper is similar to **bpf_skb_load_bytes**\ () in that + * it provides an easy way to load *len* bytes from *offset* +@@ -1877,7 +1877,7 @@ union bpf_attr { + * * < 0 if any input argument is invalid + * * 0 on success (packet is forwarded, nexthop neighbor exists) + * * > 0 one of **BPF_FIB_LKUP_RET_** codes explaining why the +- * * packet is not forwarded or needs assist from full stack ++ * packet is not forwarded or needs assist from full stack + * + * int bpf_sock_hash_update(struct bpf_sock_ops_kern *skops, struct bpf_map *map, void *key, u64 flags) + * Description +@@ -2033,7 +2033,6 @@ union bpf_attr { + * This helper is only available is the kernel was compiled with + * the **CONFIG_BPF_LIRC_MODE2** configuration option set to + * "**y**". +- * + * Return + * 0 + * +@@ -2053,7 +2052,6 @@ union bpf_attr { + * This helper is only available is the kernel was compiled with + * the **CONFIG_BPF_LIRC_MODE2** configuration option set to + * "**y**". +- * + * Return + * 0 + * +@@ -2557,6 +2555,9 @@ enum { + * Arg1: old_state + * Arg2: new_state + */ ++ BPF_SOCK_OPS_TCP_LISTEN_CB, /* Called on listen(2), right after ++ * socket transition to LISTEN state. ++ */ + }; + + /* List of TCP states. There is a build check in net/ipv4/tcp.c to detect +diff --git a/include/uapi/linux/btf.h b/include/uapi/linux/btf.h +new file mode 100644 +index 0000000..5dd580a +--- /dev/null ++++ b/include/uapi/linux/btf.h +@@ -0,0 +1,113 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* Copyright (c) 2018 Facebook */ ++#ifndef __LINUX_BTF_H__ ++#define __LINUX_BTF_H__ ++ ++#include ++ ++#define BTF_MAGIC 0xeB9F ++#define BTF_VERSION 1 ++ ++struct btf_header { ++ __u16 magic; ++ __u8 version; ++ __u8 flags; ++ __u32 hdr_len; ++ ++ /* All offsets are in bytes relative to the end of this header */ ++ __u32 type_off; /* offset of type section */ ++ __u32 type_len; /* length of type section */ ++ __u32 str_off; /* offset of string section */ ++ __u32 str_len; /* length of string section */ ++}; ++ ++/* Max # of type identifier */ ++#define BTF_MAX_TYPE 0x0000ffff ++/* Max offset into the string section */ ++#define BTF_MAX_NAME_OFFSET 0x0000ffff ++/* Max # of struct/union/enum members or func args */ ++#define BTF_MAX_VLEN 0xffff ++ ++struct btf_type { ++ __u32 name_off; ++ /* "info" bits arrangement ++ * bits 0-15: vlen (e.g. # of struct's members) ++ * bits 16-23: unused ++ * bits 24-27: kind (e.g. int, ptr, array...etc) ++ * bits 28-31: unused ++ */ ++ __u32 info; ++ /* "size" is used by INT, ENUM, STRUCT and UNION. ++ * "size" tells the size of the type it is describing. ++ * ++ * "type" is used by PTR, TYPEDEF, VOLATILE, CONST and RESTRICT. ++ * "type" is a type_id referring to another type. ++ */ ++ union { ++ __u32 size; ++ __u32 type; ++ }; ++}; ++ ++#define BTF_INFO_KIND(info) (((info) >> 24) & 0x0f) ++#define BTF_INFO_VLEN(info) ((info) & 0xffff) ++ ++#define BTF_KIND_UNKN 0 /* Unknown */ ++#define BTF_KIND_INT 1 /* Integer */ ++#define BTF_KIND_PTR 2 /* Pointer */ ++#define BTF_KIND_ARRAY 3 /* Array */ ++#define BTF_KIND_STRUCT 4 /* Struct */ ++#define BTF_KIND_UNION 5 /* Union */ ++#define BTF_KIND_ENUM 6 /* Enumeration */ ++#define BTF_KIND_FWD 7 /* Forward */ ++#define BTF_KIND_TYPEDEF 8 /* Typedef */ ++#define BTF_KIND_VOLATILE 9 /* Volatile */ ++#define BTF_KIND_CONST 10 /* Const */ ++#define BTF_KIND_RESTRICT 11 /* Restrict */ ++#define BTF_KIND_MAX 11 ++#define NR_BTF_KINDS 12 ++ ++/* For some specific BTF_KIND, "struct btf_type" is immediately ++ * followed by extra data. ++ */ ++ ++/* BTF_KIND_INT is followed by a u32 and the following ++ * is the 32 bits arrangement: ++ */ ++#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24) ++#define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16) ++#define BTF_INT_BITS(VAL) ((VAL) & 0x0000ffff) ++ ++/* Attributes stored in the BTF_INT_ENCODING */ ++#define BTF_INT_SIGNED (1 << 0) ++#define BTF_INT_CHAR (1 << 1) ++#define BTF_INT_BOOL (1 << 2) ++ ++/* BTF_KIND_ENUM is followed by multiple "struct btf_enum". ++ * The exact number of btf_enum is stored in the vlen (of the ++ * info in "struct btf_type"). ++ */ ++struct btf_enum { ++ __u32 name_off; ++ __s32 val; ++}; ++ ++/* BTF_KIND_ARRAY is followed by one "struct btf_array" */ ++struct btf_array { ++ __u32 type; ++ __u32 index_type; ++ __u32 nelems; ++}; ++ ++/* BTF_KIND_STRUCT and BTF_KIND_UNION are followed ++ * by multiple "struct btf_member". The exact number ++ * of btf_member is stored in the vlen (of the info in ++ * "struct btf_type"). ++ */ ++struct btf_member { ++ __u32 name_off; ++ __u32 type; ++ __u32 offset; /* offset in bits */ ++}; ++ ++#endif /* __LINUX_BTF_H__ */ +diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h +index 493f71f..5ee0e73 100644 +--- a/include/uapi/linux/devlink.h ++++ b/include/uapi/linux/devlink.h +@@ -78,6 +78,17 @@ enum devlink_command { + */ + DEVLINK_CMD_RELOAD, + ++ DEVLINK_CMD_PARAM_GET, /* can dump */ ++ DEVLINK_CMD_PARAM_SET, ++ DEVLINK_CMD_PARAM_NEW, ++ DEVLINK_CMD_PARAM_DEL, ++ ++ DEVLINK_CMD_REGION_GET, ++ DEVLINK_CMD_REGION_SET, ++ DEVLINK_CMD_REGION_NEW, ++ DEVLINK_CMD_REGION_DEL, ++ DEVLINK_CMD_REGION_READ, ++ + /* add new commands above here */ + __DEVLINK_CMD_MAX, + DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 +@@ -142,6 +153,16 @@ enum devlink_port_flavour { + */ + }; + ++enum devlink_param_cmode { ++ DEVLINK_PARAM_CMODE_RUNTIME, ++ DEVLINK_PARAM_CMODE_DRIVERINIT, ++ DEVLINK_PARAM_CMODE_PERMANENT, ++ ++ /* Add new configuration modes above */ ++ __DEVLINK_PARAM_CMODE_MAX, ++ DEVLINK_PARAM_CMODE_MAX = __DEVLINK_PARAM_CMODE_MAX - 1 ++}; ++ + enum devlink_attr { + /* don't change the order or add anything between, this is ABI! */ + DEVLINK_ATTR_UNSPEC, +@@ -238,6 +259,27 @@ enum devlink_attr { + DEVLINK_ATTR_PORT_NUMBER, /* u32 */ + DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, /* u32 */ + ++ DEVLINK_ATTR_PARAM, /* nested */ ++ DEVLINK_ATTR_PARAM_NAME, /* string */ ++ DEVLINK_ATTR_PARAM_GENERIC, /* flag */ ++ DEVLINK_ATTR_PARAM_TYPE, /* u8 */ ++ DEVLINK_ATTR_PARAM_VALUES_LIST, /* nested */ ++ DEVLINK_ATTR_PARAM_VALUE, /* nested */ ++ DEVLINK_ATTR_PARAM_VALUE_DATA, /* dynamic */ ++ DEVLINK_ATTR_PARAM_VALUE_CMODE, /* u8 */ ++ ++ DEVLINK_ATTR_REGION_NAME, /* string */ ++ DEVLINK_ATTR_REGION_SIZE, /* u64 */ ++ DEVLINK_ATTR_REGION_SNAPSHOTS, /* nested */ ++ DEVLINK_ATTR_REGION_SNAPSHOT, /* nested */ ++ DEVLINK_ATTR_REGION_SNAPSHOT_ID, /* u32 */ ++ ++ DEVLINK_ATTR_REGION_CHUNKS, /* nested */ ++ DEVLINK_ATTR_REGION_CHUNK, /* nested */ ++ DEVLINK_ATTR_REGION_CHUNK_DATA, /* binary */ ++ DEVLINK_ATTR_REGION_CHUNK_ADDR, /* u64 */ ++ DEVLINK_ATTR_REGION_CHUNK_LEN, /* u64 */ ++ + /* add new attributes above here, update the policy in devlink.c */ + + __DEVLINK_ATTR_MAX, +diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h +index 4eccc7f..1c64ed4 100644 +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -918,6 +918,7 @@ enum { + XDP_ATTACHED_DRV, + XDP_ATTACHED_SKB, + XDP_ATTACHED_HW, ++ XDP_ATTACHED_MULTI, + }; + + enum { +@@ -926,6 +927,9 @@ enum { + IFLA_XDP_ATTACHED, + IFLA_XDP_FLAGS, + IFLA_XDP_PROG_ID, ++ IFLA_XDP_DRV_PROG_ID, ++ IFLA_XDP_SKB_PROG_ID, ++ IFLA_XDP_HW_PROG_ID, + __IFLA_XDP_MAX, + }; + +diff --git a/include/uapi/linux/ila.h b/include/uapi/linux/ila.h +index 666292c..6a6c97c 100644 +--- a/include/uapi/linux/ila.h ++++ b/include/uapi/linux/ila.h +@@ -30,6 +30,7 @@ enum { + ILA_CMD_ADD, + ILA_CMD_DEL, + ILA_CMD_GET, ++ ILA_CMD_FLUSH, + + __ILA_CMD_MAX, + }; +diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h +index 84e4c1d..b451225 100644 +--- a/include/uapi/linux/pkt_cls.h ++++ b/include/uapi/linux/pkt_cls.h +@@ -469,6 +469,15 @@ enum { + TCA_FLOWER_KEY_IP_TTL, /* u8 */ + TCA_FLOWER_KEY_IP_TTL_MASK, /* u8 */ + ++ TCA_FLOWER_KEY_CVLAN_ID, /* be16 */ ++ TCA_FLOWER_KEY_CVLAN_PRIO, /* u8 */ ++ TCA_FLOWER_KEY_CVLAN_ETH_TYPE, /* be16 */ ++ ++ TCA_FLOWER_KEY_ENC_IP_TOS, /* u8 */ ++ TCA_FLOWER_KEY_ENC_IP_TOS_MASK, /* u8 */ ++ TCA_FLOWER_KEY_ENC_IP_TTL, /* u8 */ ++ TCA_FLOWER_KEY_ENC_IP_TTL_MASK, /* u8 */ ++ + __TCA_FLOWER_MAX, + }; + +diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h +index 37b5096..d9cc9dc 100644 +--- a/include/uapi/linux/pkt_sched.h ++++ b/include/uapi/linux/pkt_sched.h +@@ -539,6 +539,7 @@ enum { + TCA_NETEM_LATENCY64, + TCA_NETEM_JITTER64, + TCA_NETEM_SLOT, ++ TCA_NETEM_SLOT_DIST, + __TCA_NETEM_MAX, + }; + +@@ -581,6 +582,8 @@ struct tc_netem_slot { + __s64 max_delay; + __s32 max_packets; + __s32 max_bytes; ++ __s64 dist_delay; /* nsec */ ++ __s64 dist_jitter; /* nsec */ + }; + + enum { +@@ -934,4 +937,136 @@ enum { + + #define TCA_CBS_MAX (__TCA_CBS_MAX - 1) + ++ ++/* ETF */ ++struct tc_etf_qopt { ++ __s32 delta; ++ __s32 clockid; ++ __u32 flags; ++#define TC_ETF_DEADLINE_MODE_ON BIT(0) ++#define TC_ETF_OFFLOAD_ON BIT(1) ++}; ++ ++enum { ++ TCA_ETF_UNSPEC, ++ TCA_ETF_PARMS, ++ __TCA_ETF_MAX, ++}; ++ ++#define TCA_ETF_MAX (__TCA_ETF_MAX - 1) ++ ++ ++/* CAKE */ ++enum { ++ TCA_CAKE_UNSPEC, ++ TCA_CAKE_PAD, ++ TCA_CAKE_BASE_RATE64, ++ TCA_CAKE_DIFFSERV_MODE, ++ TCA_CAKE_ATM, ++ TCA_CAKE_FLOW_MODE, ++ TCA_CAKE_OVERHEAD, ++ TCA_CAKE_RTT, ++ TCA_CAKE_TARGET, ++ TCA_CAKE_AUTORATE, ++ TCA_CAKE_MEMORY, ++ TCA_CAKE_NAT, ++ TCA_CAKE_RAW, ++ TCA_CAKE_WASH, ++ TCA_CAKE_MPU, ++ TCA_CAKE_INGRESS, ++ TCA_CAKE_ACK_FILTER, ++ TCA_CAKE_SPLIT_GSO, ++ __TCA_CAKE_MAX ++}; ++#define TCA_CAKE_MAX (__TCA_CAKE_MAX - 1) ++ ++enum { ++ __TCA_CAKE_STATS_INVALID, ++ TCA_CAKE_STATS_PAD, ++ TCA_CAKE_STATS_CAPACITY_ESTIMATE64, ++ TCA_CAKE_STATS_MEMORY_LIMIT, ++ TCA_CAKE_STATS_MEMORY_USED, ++ TCA_CAKE_STATS_AVG_NETOFF, ++ TCA_CAKE_STATS_MIN_NETLEN, ++ TCA_CAKE_STATS_MAX_NETLEN, ++ TCA_CAKE_STATS_MIN_ADJLEN, ++ TCA_CAKE_STATS_MAX_ADJLEN, ++ TCA_CAKE_STATS_TIN_STATS, ++ TCA_CAKE_STATS_DEFICIT, ++ TCA_CAKE_STATS_COBALT_COUNT, ++ TCA_CAKE_STATS_DROPPING, ++ TCA_CAKE_STATS_DROP_NEXT_US, ++ TCA_CAKE_STATS_P_DROP, ++ TCA_CAKE_STATS_BLUE_TIMER_US, ++ __TCA_CAKE_STATS_MAX ++}; ++#define TCA_CAKE_STATS_MAX (__TCA_CAKE_STATS_MAX - 1) ++ ++enum { ++ __TCA_CAKE_TIN_STATS_INVALID, ++ TCA_CAKE_TIN_STATS_PAD, ++ TCA_CAKE_TIN_STATS_SENT_PACKETS, ++ TCA_CAKE_TIN_STATS_SENT_BYTES64, ++ TCA_CAKE_TIN_STATS_DROPPED_PACKETS, ++ TCA_CAKE_TIN_STATS_DROPPED_BYTES64, ++ TCA_CAKE_TIN_STATS_ACKS_DROPPED_PACKETS, ++ TCA_CAKE_TIN_STATS_ACKS_DROPPED_BYTES64, ++ TCA_CAKE_TIN_STATS_ECN_MARKED_PACKETS, ++ TCA_CAKE_TIN_STATS_ECN_MARKED_BYTES64, ++ TCA_CAKE_TIN_STATS_BACKLOG_PACKETS, ++ TCA_CAKE_TIN_STATS_BACKLOG_BYTES, ++ TCA_CAKE_TIN_STATS_THRESHOLD_RATE64, ++ TCA_CAKE_TIN_STATS_TARGET_US, ++ TCA_CAKE_TIN_STATS_INTERVAL_US, ++ TCA_CAKE_TIN_STATS_WAY_INDIRECT_HITS, ++ TCA_CAKE_TIN_STATS_WAY_MISSES, ++ TCA_CAKE_TIN_STATS_WAY_COLLISIONS, ++ TCA_CAKE_TIN_STATS_PEAK_DELAY_US, ++ TCA_CAKE_TIN_STATS_AVG_DELAY_US, ++ TCA_CAKE_TIN_STATS_BASE_DELAY_US, ++ TCA_CAKE_TIN_STATS_SPARSE_FLOWS, ++ TCA_CAKE_TIN_STATS_BULK_FLOWS, ++ TCA_CAKE_TIN_STATS_UNRESPONSIVE_FLOWS, ++ TCA_CAKE_TIN_STATS_MAX_SKBLEN, ++ TCA_CAKE_TIN_STATS_FLOW_QUANTUM, ++ __TCA_CAKE_TIN_STATS_MAX ++}; ++#define TCA_CAKE_TIN_STATS_MAX (__TCA_CAKE_TIN_STATS_MAX - 1) ++#define TC_CAKE_MAX_TINS (8) ++ ++enum { ++ CAKE_FLOW_NONE = 0, ++ CAKE_FLOW_SRC_IP, ++ CAKE_FLOW_DST_IP, ++ CAKE_FLOW_HOSTS, /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_DST_IP */ ++ CAKE_FLOW_FLOWS, ++ CAKE_FLOW_DUAL_SRC, /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_FLOWS */ ++ CAKE_FLOW_DUAL_DST, /* = CAKE_FLOW_DST_IP | CAKE_FLOW_FLOWS */ ++ CAKE_FLOW_TRIPLE, /* = CAKE_FLOW_HOSTS | CAKE_FLOW_FLOWS */ ++ CAKE_FLOW_MAX, ++}; ++ ++enum { ++ CAKE_DIFFSERV_DIFFSERV3 = 0, ++ CAKE_DIFFSERV_DIFFSERV4, ++ CAKE_DIFFSERV_DIFFSERV8, ++ CAKE_DIFFSERV_BESTEFFORT, ++ CAKE_DIFFSERV_PRECEDENCE, ++ CAKE_DIFFSERV_MAX ++}; ++ ++enum { ++ CAKE_ACK_NONE = 0, ++ CAKE_ACK_FILTER, ++ CAKE_ACK_AGGRESSIVE, ++ CAKE_ACK_MAX ++}; ++ ++enum { ++ CAKE_ATM_NONE = 0, ++ CAKE_ATM_ATM, ++ CAKE_ATM_PTM, ++ CAKE_ATM_MAX ++}; ++ + #endif +diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h +index 2d95ddc..dd164d7 100644 +--- a/include/uapi/linux/sctp.h ++++ b/include/uapi/linux/sctp.h +@@ -100,6 +100,7 @@ typedef __s32 sctp_assoc_t; + #define SCTP_RECVNXTINFO 33 + #define SCTP_DEFAULT_SNDINFO 34 + #define SCTP_AUTH_DEACTIVATE_KEY 35 ++#define SCTP_REUSE_PORT 36 + + /* Internal Socket Options. Some of the sctp library functions are + * implemented using these socket options. +@@ -762,6 +763,8 @@ enum sctp_spp_flags { + SPP_SACKDELAY_DISABLE = 1<<6, /*Disable SACK*/ + SPP_SACKDELAY = SPP_SACKDELAY_ENABLE | SPP_SACKDELAY_DISABLE, + SPP_HB_TIME_IS_ZERO = 1<<7, /* Set HB delay to 0 */ ++ SPP_IPV6_FLOWLABEL = 1<<8, ++ SPP_DSCP = 1<<9, + }; + + struct sctp_paddrparams { +@@ -772,6 +775,8 @@ struct sctp_paddrparams { + __u32 spp_pathmtu; + __u32 spp_sackdelay; + __u32 spp_flags; ++ __u32 spp_ipv6_flowlabel; ++ __u8 spp_dscp; + } __attribute__((packed, aligned(4))); + + /* +diff --git a/include/uapi/linux/tc_act/tc_pedit.h b/include/uapi/linux/tc_act/tc_pedit.h +index 162d109..24ec792 100644 +--- a/include/uapi/linux/tc_act/tc_pedit.h ++++ b/include/uapi/linux/tc_act/tc_pedit.h +@@ -17,13 +17,15 @@ enum { + TCA_PEDIT_KEY_EX, + __TCA_PEDIT_MAX + }; ++ + #define TCA_PEDIT_MAX (__TCA_PEDIT_MAX - 1) +- ++ + enum { + TCA_PEDIT_KEY_EX_HTYPE = 1, + TCA_PEDIT_KEY_EX_CMD = 2, + __TCA_PEDIT_KEY_EX_MAX + }; ++ + #define TCA_PEDIT_KEY_EX_MAX (__TCA_PEDIT_KEY_EX_MAX - 1) + + /* TCA_PEDIT_KEY_EX_HDR_TYPE_NETWROK is a special case for legacy users. It +@@ -38,6 +40,7 @@ enum pedit_header_type { + TCA_PEDIT_KEY_EX_HDR_TYPE_UDP = 5, + __PEDIT_HDR_TYPE_MAX, + }; ++ + #define TCA_PEDIT_HDR_TYPE_MAX (__PEDIT_HDR_TYPE_MAX - 1) + + enum pedit_cmd { +@@ -45,6 +48,7 @@ enum pedit_cmd { + TCA_PEDIT_KEY_EX_CMD_ADD = 1, + __PEDIT_CMD_MAX, + }; ++ + #define TCA_PEDIT_CMD_MAX (__PEDIT_CMD_MAX - 1) + + struct tc_pedit_key { +@@ -55,13 +59,14 @@ struct tc_pedit_key { + __u32 offmask; + __u32 shift; + }; +- ++ + struct tc_pedit_sel { + tc_gen; + unsigned char nkeys; + unsigned char flags; + struct tc_pedit_key keys[0]; + }; ++ + #define tc_pedit tc_pedit_sel + + #endif +diff --git a/include/uapi/linux/tc_act/tc_skbedit.h b/include/uapi/linux/tc_act/tc_skbedit.h +index fbcfe27..6de6071 100644 +--- a/include/uapi/linux/tc_act/tc_skbedit.h ++++ b/include/uapi/linux/tc_act/tc_skbedit.h +@@ -30,6 +30,7 @@ + #define SKBEDIT_F_MARK 0x4 + #define SKBEDIT_F_PTYPE 0x8 + #define SKBEDIT_F_MASK 0x10 ++#define SKBEDIT_F_INHERITDSFIELD 0x20 + + struct tc_skbedit { + tc_gen; +@@ -45,6 +46,7 @@ enum { + TCA_SKBEDIT_PAD, + TCA_SKBEDIT_PTYPE, + TCA_SKBEDIT_MASK, ++ TCA_SKBEDIT_FLAGS, + __TCA_SKBEDIT_MAX + }; + #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1) +diff --git a/include/uapi/linux/tc_act/tc_tunnel_key.h b/include/uapi/linux/tc_act/tc_tunnel_key.h +index 72bbefe..be384d6 100644 +--- a/include/uapi/linux/tc_act/tc_tunnel_key.h ++++ b/include/uapi/linux/tc_act/tc_tunnel_key.h +@@ -36,9 +36,37 @@ enum { + TCA_TUNNEL_KEY_PAD, + TCA_TUNNEL_KEY_ENC_DST_PORT, /* be16 */ + TCA_TUNNEL_KEY_NO_CSUM, /* u8 */ ++ TCA_TUNNEL_KEY_ENC_OPTS, /* Nested TCA_TUNNEL_KEY_ENC_OPTS_ ++ * attributes ++ */ ++ TCA_TUNNEL_KEY_ENC_TOS, /* u8 */ ++ TCA_TUNNEL_KEY_ENC_TTL, /* u8 */ + __TCA_TUNNEL_KEY_MAX, + }; + + #define TCA_TUNNEL_KEY_MAX (__TCA_TUNNEL_KEY_MAX - 1) + ++enum { ++ TCA_TUNNEL_KEY_ENC_OPTS_UNSPEC, ++ TCA_TUNNEL_KEY_ENC_OPTS_GENEVE, /* Nested ++ * TCA_TUNNEL_KEY_ENC_OPTS_ ++ * attributes ++ */ ++ __TCA_TUNNEL_KEY_ENC_OPTS_MAX, ++}; ++ ++#define TCA_TUNNEL_KEY_ENC_OPTS_MAX (__TCA_TUNNEL_KEY_ENC_OPTS_MAX - 1) ++ ++enum { ++ TCA_TUNNEL_KEY_ENC_OPT_GENEVE_UNSPEC, ++ TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS, /* be16 */ ++ TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE, /* u8 */ ++ TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA, /* 4 to 128 bytes */ ++ ++ __TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX, ++}; ++ ++#define TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX \ ++ (__TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX - 1) ++ + #endif +diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h +index 99e329b..2e766cf 100644 +--- a/include/uapi/linux/tcp.h ++++ b/include/uapi/linux/tcp.h +@@ -127,10 +127,6 @@ enum { + + #define TCP_CM_INQ TCP_INQ + +-#define TCP_REPAIR_ON 1 +-#define TCP_REPAIR_OFF 0 +-#define TCP_REPAIR_OFF_NO_WP -1 /* Turn off without window probes */ +- + struct tcp_repair_opt { + __u32 opt_code; + __u32 opt_val; +diff --git a/include/uapi/linux/tipc_netlink.h b/include/uapi/linux/tipc_netlink.h +index 85c1198..0ebe02e 100644 +--- a/include/uapi/linux/tipc_netlink.h ++++ b/include/uapi/linux/tipc_netlink.h +@@ -121,6 +121,7 @@ enum { + TIPC_NLA_SOCK_TIPC_STATE, /* u32 */ + TIPC_NLA_SOCK_COOKIE, /* u64 */ + TIPC_NLA_SOCK_PAD, /* flag */ ++ TIPC_NLA_SOCK_GROUP, /* nest */ + + __TIPC_NLA_SOCK_MAX, + TIPC_NLA_SOCK_MAX = __TIPC_NLA_SOCK_MAX - 1 +@@ -233,6 +234,19 @@ enum { + TIPC_NLA_MON_PEER_MAX = __TIPC_NLA_MON_PEER_MAX - 1 + }; + ++/* Nest, socket group info */ ++enum { ++ TIPC_NLA_SOCK_GROUP_ID, /* u32 */ ++ TIPC_NLA_SOCK_GROUP_OPEN, /* flag */ ++ TIPC_NLA_SOCK_GROUP_NODE_SCOPE, /* flag */ ++ TIPC_NLA_SOCK_GROUP_CLUSTER_SCOPE, /* flag */ ++ TIPC_NLA_SOCK_GROUP_INSTANCE, /* u32 */ ++ TIPC_NLA_SOCK_GROUP_BC_SEND_NEXT, /* u32 */ ++ ++ __TIPC_NLA_SOCK_GROUP_MAX, ++ TIPC_NLA_SOCK_GROUP_MAX = __TIPC_NLA_SOCK_GROUP_MAX - 1 ++}; ++ + /* Nest, connection info */ + enum { + TIPC_NLA_CON_UNSPEC, +-- +1.8.3.1 + diff --git a/SOURCES/0015-ip-route-Fix-segfault-with-many-nexthops.patch b/SOURCES/0015-ip-route-Fix-segfault-with-many-nexthops.patch new file mode 100644 index 0000000..d7458c4 --- /dev/null +++ b/SOURCES/0015-ip-route-Fix-segfault-with-many-nexthops.patch @@ -0,0 +1,529 @@ +From 4620f13fc0f0e344421c0b9a0b8747734d3caf00 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 19 Sep 2018 19:59:54 +0200 +Subject: [PATCH] ip-route: Fix segfault with many nexthops + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1625358 +Upstream Status: iproute2.git commit bd59e5b1517b0 + +commit bd59e5b1517b09b6f26d59f38fe6077d953c2396 +Author: Phil Sutter +Date: Thu Sep 6 15:31:51 2018 +0200 + + ip-route: Fix segfault with many nexthops + + It was possible to crash ip-route by adding an IPv6 route with 37 + nexthop statements. A simple reproducer is: + + | for i in `seq 37`; do + | nhs="nexthop via 1111::$i "$nhs + | done + | ip -6 route add 3333::/64 $nhs + + The related code was broken in multiple ways: + + * parse_one_nh() assumed that rta points to 4kB of storage but caller + provided just 1kB. Fixed by passing 'len' parameter with the correct + value. + + * Error checking of rta_addattr*() calls in parse_one_nh() and called + functions was completely absent, so with above fix in place output + flood would occur due to parser looping forever. + + While being at it, increase message buffer sizes to 4k. This allows for + at most 144 nexthops. + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + ip/iproute.c | 43 ++++++++++++-------- + ip/iproute_lwtunnel.c | 108 ++++++++++++++++++++++++++++++-------------------- + 2 files changed, 91 insertions(+), 60 deletions(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index 3083341..398322f 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -941,7 +941,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + } + + static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, +- struct rtattr *rta, struct rtnexthop *rtnh, ++ struct rtattr *rta, size_t len, struct rtnexthop *rtnh, + int *argcp, char ***argvp) + { + int argc = *argcp; +@@ -962,11 +962,16 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, + if (r->rtm_family == AF_UNSPEC) + r->rtm_family = addr.family; + if (addr.family == r->rtm_family) { +- rta_addattr_l(rta, 4096, RTA_GATEWAY, &addr.data, addr.bytelen); +- rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen; ++ if (rta_addattr_l(rta, len, RTA_GATEWAY, ++ &addr.data, addr.bytelen)) ++ return -1; ++ rtnh->rtnh_len += sizeof(struct rtattr) ++ + addr.bytelen; + } else { +- rta_addattr_l(rta, 4096, RTA_VIA, &addr.family, addr.bytelen+2); +- rtnh->rtnh_len += RTA_SPACE(addr.bytelen+2); ++ if (rta_addattr_l(rta, len, RTA_VIA, ++ &addr.family, addr.bytelen + 2)) ++ return -1; ++ rtnh->rtnh_len += RTA_SPACE(addr.bytelen + 2); + } + } else if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); +@@ -988,13 +993,15 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, + NEXT_ARG(); + if (get_rt_realms_or_raw(&realm, *argv)) + invarg("\"realm\" value is invalid\n", *argv); +- rta_addattr32(rta, 4096, RTA_FLOW, realm); ++ if (rta_addattr32(rta, len, RTA_FLOW, realm)) ++ return -1; + rtnh->rtnh_len += sizeof(struct rtattr) + 4; + } else if (strcmp(*argv, "encap") == 0) { +- int len = rta->rta_len; ++ int old_len = rta->rta_len; + +- lwt_parse_encap(rta, 4096, &argc, &argv); +- rtnh->rtnh_len += rta->rta_len - len; ++ if (lwt_parse_encap(rta, len, &argc, &argv)) ++ return -1; ++ rtnh->rtnh_len += rta->rta_len - old_len; + } else if (strcmp(*argv, "as") == 0) { + inet_prefix addr; + +@@ -1002,8 +1009,9 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, + if (strcmp(*argv, "to") == 0) + NEXT_ARG(); + get_addr(&addr, *argv, r->rtm_family); +- rta_addattr_l(rta, 4096, RTA_NEWDST, &addr.data, +- addr.bytelen); ++ if (rta_addattr_l(rta, len, RTA_NEWDST, ++ &addr.data, addr.bytelen)) ++ return -1; + rtnh->rtnh_len += sizeof(struct rtattr) + addr.bytelen; + } else + break; +@@ -1016,7 +1024,7 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r, + static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, + int argc, char **argv) + { +- char buf[1024]; ++ char buf[4096]; + struct rtattr *rta = (void *)buf; + struct rtnexthop *rtnh; + +@@ -1036,7 +1044,7 @@ static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, + memset(rtnh, 0, sizeof(*rtnh)); + rtnh->rtnh_len = sizeof(*rtnh); + rta->rta_len += rtnh->rtnh_len; +- if (parse_one_nh(n, r, rta, rtnh, &argc, &argv)) { ++ if (parse_one_nh(n, r, rta, 4096, rtnh, &argc, &argv)) { + fprintf(stderr, "Error: cannot parse nexthop\n"); + exit(-1); + } +@@ -1044,7 +1052,8 @@ static int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, + } + + if (rta->rta_len > RTA_LENGTH(0)) +- addattr_l(n, 1024, RTA_MULTIPATH, RTA_DATA(rta), RTA_PAYLOAD(rta)); ++ return addattr_l(n, 4096, RTA_MULTIPATH, ++ RTA_DATA(rta), RTA_PAYLOAD(rta)); + return 0; + } + +@@ -1053,7 +1062,7 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv) + struct { + struct nlmsghdr n; + struct rtmsg r; +- char buf[1024]; ++ char buf[4096]; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)), + .n.nlmsg_flags = NLM_F_REQUEST | flags, +@@ -1484,8 +1493,8 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv) + addattr_l(&req.n, sizeof(req), RTA_METRICS, RTA_DATA(mxrta), RTA_PAYLOAD(mxrta)); + } + +- if (nhs_ok) +- parse_nexthops(&req.n, &req.r, argc, argv); ++ if (nhs_ok && parse_nexthops(&req.n, &req.r, argc, argv)) ++ return -1; + + if (req.r.rtm_family == AF_UNSPEC) + req.r.rtm_family = AF_INET; +diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c +index e604481..969a476 100644 +--- a/ip/iproute_lwtunnel.c ++++ b/ip/iproute_lwtunnel.c +@@ -538,8 +538,9 @@ static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp, + + memcpy(tuninfo->srh, srh, srhlen); + +- rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo, +- sizeof(*tuninfo) + srhlen); ++ if (rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo, ++ sizeof(*tuninfo) + srhlen)) ++ return -1; + + free(tuninfo); + free(srh); +@@ -611,6 +612,7 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, + char segbuf[1024]; + inet_prefix addr; + __u32 hmac = 0; ++ int ret = 0; + + while (argc > 0) { + if (strcmp(*argv, "action") == 0) { +@@ -620,27 +622,28 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, + action = read_action_type(*argv); + if (!action) + invarg("\"action\" value is invalid\n", *argv); +- rta_addattr32(rta, len, SEG6_LOCAL_ACTION, action); ++ ret = rta_addattr32(rta, len, SEG6_LOCAL_ACTION, ++ action); + } else if (strcmp(*argv, "table") == 0) { + NEXT_ARG(); + if (table_ok++) + duparg2("table", *argv); + get_u32(&table, *argv, 0); +- rta_addattr32(rta, len, SEG6_LOCAL_TABLE, table); ++ ret = rta_addattr32(rta, len, SEG6_LOCAL_TABLE, table); + } else if (strcmp(*argv, "nh4") == 0) { + NEXT_ARG(); + if (nh4_ok++) + duparg2("nh4", *argv); + get_addr(&addr, *argv, AF_INET); +- rta_addattr_l(rta, len, SEG6_LOCAL_NH4, &addr.data, +- addr.bytelen); ++ ret = rta_addattr_l(rta, len, SEG6_LOCAL_NH4, ++ &addr.data, addr.bytelen); + } else if (strcmp(*argv, "nh6") == 0) { + NEXT_ARG(); + if (nh6_ok++) + duparg2("nh6", *argv); + get_addr(&addr, *argv, AF_INET6); +- rta_addattr_l(rta, len, SEG6_LOCAL_NH6, &addr.data, +- addr.bytelen); ++ ret = rta_addattr_l(rta, len, SEG6_LOCAL_NH6, ++ &addr.data, addr.bytelen); + } else if (strcmp(*argv, "iif") == 0) { + NEXT_ARG(); + if (iif_ok++) +@@ -648,7 +651,7 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, + iif = ll_name_to_index(*argv); + if (!iif) + exit(nodev(*argv)); +- rta_addattr32(rta, len, SEG6_LOCAL_IIF, iif); ++ ret = rta_addattr32(rta, len, SEG6_LOCAL_IIF, iif); + } else if (strcmp(*argv, "oif") == 0) { + NEXT_ARG(); + if (oif_ok++) +@@ -656,7 +659,7 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, + oif = ll_name_to_index(*argv); + if (!oif) + exit(nodev(*argv)); +- rta_addattr32(rta, len, SEG6_LOCAL_OIF, oif); ++ ret = rta_addattr32(rta, len, SEG6_LOCAL_OIF, oif); + } else if (strcmp(*argv, "srh") == 0) { + NEXT_ARG(); + if (srh_ok++) +@@ -691,6 +694,8 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, + } else { + break; + } ++ if (ret) ++ return ret; + argc--; argv++; + } + +@@ -705,14 +710,14 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, + srh = parse_srh(segbuf, hmac, + action == SEG6_LOCAL_ACTION_END_B6_ENCAP); + srhlen = (srh->hdrlen + 1) << 3; +- rta_addattr_l(rta, len, SEG6_LOCAL_SRH, srh, srhlen); ++ ret = rta_addattr_l(rta, len, SEG6_LOCAL_SRH, srh, srhlen); + free(srh); + } + + *argcp = argc + 1; + *argvp = argv - 1; + +- return 0; ++ return ret; + } + + static int parse_encap_mpls(struct rtattr *rta, size_t len, +@@ -730,8 +735,9 @@ static int parse_encap_mpls(struct rtattr *rta, size_t len, + exit(1); + } + +- rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST, &addr.data, +- addr.bytelen); ++ if (rta_addattr_l(rta, len, MPLS_IPTUNNEL_DST, ++ &addr.data, addr.bytelen)) ++ return -1; + + argc--; + argv++; +@@ -745,7 +751,8 @@ static int parse_encap_mpls(struct rtattr *rta, size_t len, + duparg2("ttl", *argv); + if (get_u8(&ttl, *argv, 0)) + invarg("\"ttl\" value is invalid\n", *argv); +- rta_addattr8(rta, len, MPLS_IPTUNNEL_TTL, ttl); ++ if (rta_addattr8(rta, len, MPLS_IPTUNNEL_TTL, ttl)) ++ return -1; + } else { + break; + } +@@ -768,6 +775,7 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, + int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0; + char **argv = *argvp; + int argc = *argcp; ++ int ret = 0; + + while (argc > 0) { + if (strcmp(*argv, "id") == 0) { +@@ -778,7 +786,7 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, + duparg2("id", *argv); + if (get_be64(&id, *argv, 0)) + invarg("\"id\" value is invalid\n", *argv); +- rta_addattr64(rta, len, LWTUNNEL_IP_ID, id); ++ ret = rta_addattr64(rta, len, LWTUNNEL_IP_ID, id); + } else if (strcmp(*argv, "dst") == 0) { + inet_prefix addr; + +@@ -786,8 +794,8 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, + if (dst_ok++) + duparg2("dst", *argv); + get_addr(&addr, *argv, AF_INET); +- rta_addattr_l(rta, len, LWTUNNEL_IP_DST, +- &addr.data, addr.bytelen); ++ ret = rta_addattr_l(rta, len, LWTUNNEL_IP_DST, ++ &addr.data, addr.bytelen); + } else if (strcmp(*argv, "tos") == 0) { + __u32 tos; + +@@ -796,7 +804,7 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, + duparg2("tos", *argv); + if (rtnl_dsfield_a2n(&tos, *argv)) + invarg("\"tos\" value is invalid\n", *argv); +- rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos); ++ ret = rta_addattr8(rta, len, LWTUNNEL_IP_TOS, tos); + } else if (strcmp(*argv, "ttl") == 0) { + __u8 ttl; + +@@ -805,10 +813,12 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, + duparg2("ttl", *argv); + if (get_u8(&ttl, *argv, 0)) + invarg("\"ttl\" value is invalid\n", *argv); +- rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl); ++ ret = rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl); + } else { + break; + } ++ if (ret) ++ break; + argc--; argv++; + } + +@@ -819,7 +829,7 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, + *argcp = argc + 1; + *argvp = argv - 1; + +- return 0; ++ return ret; + } + + static int parse_encap_ila(struct rtattr *rta, size_t len, +@@ -828,6 +838,7 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, + __u64 locator; + int argc = *argcp; + char **argv = *argvp; ++ int ret = 0; + + if (get_addr64(&locator, *argv) < 0) { + fprintf(stderr, "Bad locator: %s\n", *argv); +@@ -836,7 +847,8 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, + + argc--; argv++; + +- rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator); ++ if (rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator)) ++ return -1; + + while (argc > 0) { + if (strcmp(*argv, "csum-mode") == 0) { +@@ -849,8 +861,8 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, + invarg("\"csum-mode\" value is invalid\n", + *argv); + +- rta_addattr8(rta, 1024, ILA_ATTR_CSUM_MODE, +- (__u8)csum_mode); ++ ret = rta_addattr8(rta, 1024, ILA_ATTR_CSUM_MODE, ++ (__u8)csum_mode); + + argc--; argv++; + } else if (strcmp(*argv, "ident-type") == 0) { +@@ -863,8 +875,8 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, + invarg("\"ident-type\" value is invalid\n", + *argv); + +- rta_addattr8(rta, 1024, ILA_ATTR_IDENT_TYPE, +- (__u8)ident_type); ++ ret = rta_addattr8(rta, 1024, ILA_ATTR_IDENT_TYPE, ++ (__u8)ident_type); + + argc--; argv++; + } else if (strcmp(*argv, "hook-type") == 0) { +@@ -877,13 +889,15 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, + invarg("\"hook-type\" value is invalid\n", + *argv); + +- rta_addattr8(rta, 1024, ILA_ATTR_HOOK_TYPE, +- (__u8)hook_type); ++ ret = rta_addattr8(rta, 1024, ILA_ATTR_HOOK_TYPE, ++ (__u8)hook_type); + + argc--; argv++; + } else { + break; + } ++ if (ret) ++ break; + } + + /* argv is currently the first unparsed argument, +@@ -893,7 +907,7 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, + *argcp = argc + 1; + *argvp = argv - 1; + +- return 0; ++ return ret; + } + + static int parse_encap_ip6(struct rtattr *rta, size_t len, +@@ -902,6 +916,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + int id_ok = 0, dst_ok = 0, tos_ok = 0, ttl_ok = 0; + char **argv = *argvp; + int argc = *argcp; ++ int ret = 0; + + while (argc > 0) { + if (strcmp(*argv, "id") == 0) { +@@ -912,7 +927,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + duparg2("id", *argv); + if (get_be64(&id, *argv, 0)) + invarg("\"id\" value is invalid\n", *argv); +- rta_addattr64(rta, len, LWTUNNEL_IP6_ID, id); ++ ret = rta_addattr64(rta, len, LWTUNNEL_IP6_ID, id); + } else if (strcmp(*argv, "dst") == 0) { + inet_prefix addr; + +@@ -920,8 +935,8 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + if (dst_ok++) + duparg2("dst", *argv); + get_addr(&addr, *argv, AF_INET6); +- rta_addattr_l(rta, len, LWTUNNEL_IP6_DST, +- &addr.data, addr.bytelen); ++ ret = rta_addattr_l(rta, len, LWTUNNEL_IP6_DST, ++ &addr.data, addr.bytelen); + } else if (strcmp(*argv, "tc") == 0) { + __u32 tc; + +@@ -930,7 +945,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + duparg2("tc", *argv); + if (rtnl_dsfield_a2n(&tc, *argv)) + invarg("\"tc\" value is invalid\n", *argv); +- rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc); ++ ret = rta_addattr8(rta, len, LWTUNNEL_IP6_TC, tc); + } else if (strcmp(*argv, "hoplimit") == 0) { + __u8 hoplimit; + +@@ -940,10 +955,13 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + if (get_u8(&hoplimit, *argv, 0)) + invarg("\"hoplimit\" value is invalid\n", + *argv); +- rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT, hoplimit); ++ ret = rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT, ++ hoplimit); + } else { + break; + } ++ if (ret) ++ break; + argc--; argv++; + } + +@@ -954,7 +972,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + *argcp = argc + 1; + *argvp = argv - 1; + +- return 0; ++ return ret; + } + + static void lwt_bpf_usage(void) +@@ -1021,6 +1039,7 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) + int argc = *argcp; + char **argv = *argvp; + __u16 type; ++ int ret = 0; + + NEXT_ARG(); + type = read_encap_type(*argv); +@@ -1037,37 +1056,40 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) + nest = rta_nest(rta, 1024, RTA_ENCAP); + switch (type) { + case LWTUNNEL_ENCAP_MPLS: +- parse_encap_mpls(rta, len, &argc, &argv); ++ ret = parse_encap_mpls(rta, len, &argc, &argv); + break; + case LWTUNNEL_ENCAP_IP: +- parse_encap_ip(rta, len, &argc, &argv); ++ ret = parse_encap_ip(rta, len, &argc, &argv); + break; + case LWTUNNEL_ENCAP_ILA: +- parse_encap_ila(rta, len, &argc, &argv); ++ ret = parse_encap_ila(rta, len, &argc, &argv); + break; + case LWTUNNEL_ENCAP_IP6: +- parse_encap_ip6(rta, len, &argc, &argv); ++ ret = parse_encap_ip6(rta, len, &argc, &argv); + break; + case LWTUNNEL_ENCAP_BPF: + if (parse_encap_bpf(rta, len, &argc, &argv) < 0) + exit(-1); + break; + case LWTUNNEL_ENCAP_SEG6: +- parse_encap_seg6(rta, len, &argc, &argv); ++ ret = parse_encap_seg6(rta, len, &argc, &argv); + break; + case LWTUNNEL_ENCAP_SEG6_LOCAL: +- parse_encap_seg6local(rta, len, &argc, &argv); ++ ret = parse_encap_seg6local(rta, len, &argc, &argv); + break; + default: + fprintf(stderr, "Error: unsupported encap type\n"); + break; + } ++ if (ret) ++ return ret; ++ + rta_nest_end(rta, nest); + +- rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type); ++ ret = rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type); + + *argcp = argc; + *argvp = argv; + +- return 0; ++ return ret; + } +-- +1.8.3.1 + diff --git a/SOURCES/0016-bridge-mdb-fix-missing-new-line-when-show-bridge-mdb.patch b/SOURCES/0016-bridge-mdb-fix-missing-new-line-when-show-bridge-mdb.patch new file mode 100644 index 0000000..17003fa --- /dev/null +++ b/SOURCES/0016-bridge-mdb-fix-missing-new-line-when-show-bridge-mdb.patch @@ -0,0 +1,62 @@ +From e77e552d5814bf34ec65b8342875990c7f085edc Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 19 Sep 2018 20:00:42 +0200 +Subject: [PATCH] bridge/mdb: fix missing new line when show bridge mdb + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1625500 +Upstream Status: iproute2.git commit 92bba4ed4016a + +commit 92bba4ed4016af3ce7f7071d3c37f2cb34f240f5 +Author: Hangbin Liu +Date: Wed Sep 12 09:39:44 2018 +0800 + + bridge/mdb: fix missing new line when show bridge mdb + + The bridge mdb show is broken on current iproute2. e.g. + ]# bridge mdb show + 34: br0 veth0_br 224.1.1.2 temp 34: br0 veth0_br 224.1.1.1 temp + + After fix: + ]# bridge mdb show + 34: br0 veth0_br 224.1.1.2 temp + 34: br0 veth0_br 224.1.1.1 temp + + v2: Use json print lib as Stephen suggested. + v3: No need to use is_json_context() as print_string() could handle both cases. + v4: use new function print_nl() to print new line in non-json mode. + + Reported-by: Ying Xu + Fixes: c7c1a1ef51aea ("bridge: colorize output and use JSON print library") + Signed-off-by: Hangbin Liu + Signed-off-by: Stephen Hemminger +--- + bridge/mdb.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/bridge/mdb.c b/bridge/mdb.c +index f38dc67..a7b7979 100644 +--- a/bridge/mdb.c ++++ b/bridge/mdb.c +@@ -107,6 +107,10 @@ static void br_print_router_ports(FILE *f, struct rtattr *attr, + fprintf(f, "%s ", port_ifname); + } + } ++ ++ if (!show_stats) ++ print_nl(); ++ + close_json_array(PRINT_JSON, NULL); + } + +@@ -164,6 +168,8 @@ static void print_mdb_entry(FILE *f, int ifindex, const struct br_mdb_entry *e, + print_string(PRINT_ANY, "timer", " %s", + format_timer(timer)); + } ++ ++ print_nl(); + close_json_object(); + } + +-- +1.8.3.1 + diff --git a/SOURCES/0017-lib-introduce-print_nl.patch b/SOURCES/0017-lib-introduce-print_nl.patch new file mode 100644 index 0000000..4751bd9 --- /dev/null +++ b/SOURCES/0017-lib-introduce-print_nl.patch @@ -0,0 +1,357 @@ +From 1934af7ac7bbd967f56d0cf5fa12ec0423bd5683 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 19 Sep 2018 20:23:03 +0200 +Subject: [PATCH] lib: introduce print_nl + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1625500 +Upstream Status: iproute2.git commit b85076cd74e77 + +commit b85076cd74e77538918d35992b1a9cd17ff86af8 +Author: Stephen Hemminger +Date: Tue Sep 11 08:29:33 2018 -0700 + + lib: introduce print_nl + + Common pattern in iproute commands is to print a line seperator + in non-json mode. Make that a simple function. + + Signed-off-by: Stephen Hemminger +--- + bridge/bridge.c | 1 - + include/json_print.h | 2 ++ + ip/ip.c | 1 - + ip/ipaddress.c | 12 ++++++------ + ip/ipila.c | 2 +- + ip/ipl2tp.c | 14 +++++++------- + ip/ipmacsec.c | 2 +- + ip/ipmaddr.c | 2 +- + ip/ipmroute.c | 2 +- + ip/ipntable.c | 16 ++++++++-------- + lib/json_print.c | 7 +++++++ + lib/utils.c | 1 + + tc/tc.c | 1 - + 13 files changed, 35 insertions(+), 28 deletions(-) + +diff --git a/bridge/bridge.c b/bridge/bridge.c +index 28e1381..7221c0b 100644 +--- a/bridge/bridge.c ++++ b/bridge/bridge.c +@@ -30,7 +30,6 @@ int json; + int timestamp; + char *batch_file; + int force; +-const char *_SL_; + + static void usage(void) __attribute__((noreturn)); + +diff --git a/include/json_print.h b/include/json_print.h +index 218fedc..78a6c83 100644 +--- a/include/json_print.h ++++ b/include/json_print.h +@@ -41,6 +41,8 @@ void close_json_object(void); + void open_json_array(enum output_type type, const char *delim); + void close_json_array(enum output_type type, const char *delim); + ++void print_nl(void); ++ + #define _PRINT_FUNC(type_name, type) \ + void print_color_##type_name(enum output_type t, \ + enum color_attr color, \ +diff --git a/ip/ip.c b/ip/ip.c +index bb964f3..2ca55e3 100644 +--- a/ip/ip.c ++++ b/ip/ip.c +@@ -33,7 +33,6 @@ int oneline; + int brief; + int json; + int timestamp; +-const char *_SL_; + int force; + int max_flush_loops = 10; + int batch_mode; +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index b7b78f6..f315a81 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -240,7 +240,7 @@ static void print_linktype(FILE *fp, struct rtattr *tb) + const char *kind + = rta_getattr_str(linkinfo[IFLA_INFO_KIND]); + +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + print_string(PRINT_ANY, "info_kind", " %s ", kind); + + lu = get_link_kind(kind); +@@ -269,7 +269,7 @@ static void print_linktype(FILE *fp, struct rtattr *tb) + const char *slave_kind + = rta_getattr_str(linkinfo[IFLA_INFO_SLAVE_KIND]); + +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + print_string(PRINT_ANY, + "info_slave_kind", + " %s_slave ", +@@ -749,7 +749,7 @@ static void print_link_stats(FILE *fp, struct nlmsghdr *n) + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), + n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi))); + __print_link_stats(fp, tb); +- fprintf(fp, "%s", _SL_); ++ print_nl(); + } + + static int print_linkinfo_brief(FILE *fp, const char *name, +@@ -913,7 +913,7 @@ int print_linkinfo(const struct sockaddr_nl *who, + print_link_event(fp, rta_getattr_u32(tb[IFLA_EVENT])); + + if (!filter.family || filter.family == AF_PACKET || show_details) { +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + print_string(PRINT_ANY, + "link_type", + " link/%s ", +@@ -1064,7 +1064,7 @@ int print_linkinfo(const struct sockaddr_nl *who, + xdp_dump(fp, tb[IFLA_XDP], true, true); + + if (do_link && show_stats) { +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + __print_link_stats(fp, tb); + } + +@@ -1392,7 +1392,7 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, + if (rta_tb[IFA_CACHEINFO]) { + struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]); + +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + print_string(PRINT_FP, NULL, " valid_lft ", NULL); + + if (ci->ifa_valid == INFINITY_LIFE_TIME) { +diff --git a/ip/ipila.c b/ip/ipila.c +index 370385c..895fe0c 100644 +--- a/ip/ipila.c ++++ b/ip/ipila.c +@@ -128,7 +128,7 @@ static int print_ila_mapping(const struct sockaddr_nl *who, + else + print_string(PRINT_FP, NULL, "%s", "-"); + +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + close_json_object(); + + return 0; +diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c +index 05e9638..414a9eb 100644 +--- a/ip/ipl2tp.c ++++ b/ip/ipl2tp.c +@@ -228,7 +228,7 @@ static void print_tunnel(const struct l2tp_data *data) + print_string(PRINT_ANY, "encap", " encap %s", + p->encap == L2TP_ENCAPTYPE_UDP ? "UDP" : + p->encap == L2TP_ENCAPTYPE_IP ? "IP" : "??"); +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + + print_string(PRINT_ANY, "local", " From %s ", + inet_ntop(p->local_ip.family, p->local_ip.data, +@@ -236,11 +236,11 @@ static void print_tunnel(const struct l2tp_data *data) + print_string(PRINT_ANY, "peer", "to %s", + inet_ntop(p->peer_ip.family, p->peer_ip.data, + buf, sizeof(buf))); +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + + print_uint(PRINT_ANY, "peer_tunnel", " Peer tunnel %u", + p->peer_tunnel_id); +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + + if (p->encap == L2TP_ENCAPTYPE_UDP) { + print_string(PRINT_FP, NULL, +@@ -250,7 +250,7 @@ static void print_tunnel(const struct l2tp_data *data) + p->local_udp_port); + print_uint(PRINT_ANY, "peer_port", "/%hu", + p->peer_udp_port); +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + + switch (p->local_ip.family) { + case AF_INET: +@@ -292,18 +292,18 @@ static void print_session(struct l2tp_data *data) + + print_uint(PRINT_ANY, "session_id", "Session %u", p->session_id); + print_uint(PRINT_ANY, "tunnel_id", " in tunnel %u", p->tunnel_id); +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + + print_uint(PRINT_ANY, "peer_session_id", + " Peer session %u,", p->peer_session_id); + print_uint(PRINT_ANY, "peer_tunnel_id", + " tunnel %u", p->peer_tunnel_id); +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + + if (p->ifname != NULL) { + print_color_string(PRINT_ANY, COLOR_IFNAME, + "interface", " interface name: %s" , p->ifname); +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + } + + /* Show offsets only for plain console output (for legacy scripts) */ +diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c +index 4e4e158..fa56e0e 100644 +--- a/ip/ipmacsec.c ++++ b/ip/ipmacsec.c +@@ -627,7 +627,7 @@ static void print_attrs(struct rtattr *attrs[]) + if (attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]) { + __u64 cid = rta_getattr_u64(attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]); + +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + print_string(PRINT_ANY, "cipher_suite", + " cipher suite: %s,", cs_id_to_name(cid)); + } +diff --git a/ip/ipmaddr.c b/ip/ipmaddr.c +index a484990..992b212 100644 +--- a/ip/ipmaddr.c ++++ b/ip/ipmaddr.c +@@ -240,7 +240,7 @@ static void print_mlist(FILE *fp, struct ma_info *list) + print_uint(PRINT_ANY, "ifindex", "%d:", list->index); + print_color_string(PRINT_ANY, COLOR_IFNAME, + "ifname", "\t%s", list->name); +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + cur_index = list->index; + + open_json_array(PRINT_JSON, "maddr"); +diff --git a/ip/ipmroute.c b/ip/ipmroute.c +index cdb4d89..bc23cfe 100644 +--- a/ip/ipmroute.c ++++ b/ip/ipmroute.c +@@ -181,7 +181,7 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + if (show_stats && tb[RTA_MFC_STATS]) { + struct rta_mfc_stats *mfcs = RTA_DATA(tb[RTA_MFC_STATS]); + +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + print_u64(PRINT_ANY, "packets", " %"PRIu64" packets,", + mfcs->mfcs_packets); + print_u64(PRINT_ANY, "bytes", " %"PRIu64" bytes", mfcs->mfcs_bytes); +diff --git a/ip/ipntable.c b/ip/ipntable.c +index 4fae181..dd4f7c2 100644 +--- a/ip/ipntable.c ++++ b/ip/ipntable.c +@@ -346,7 +346,7 @@ static void print_ndtconfig(const struct ndt_config *ndtc) + "entry_size %u ", ndtc->ndtc_entry_size); + print_uint(PRINT_ANY, "entries", "entries %u ", ndtc->ndtc_entries); + +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + + print_string(PRINT_ANY, "last_flush", + " last_flush %s ", +@@ -355,7 +355,7 @@ static void print_ndtconfig(const struct ndt_config *ndtc) + "last_rand %s ", + ntable_strtime_delta(ndtc->ndtc_last_rand)); + +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + + print_uint(PRINT_ANY, "hash_rnd", + " hash_rnd %u ", ndtc->ndtc_hash_rnd); +@@ -367,7 +367,7 @@ static void print_ndtconfig(const struct ndt_config *ndtc) + print_uint(PRINT_ANY, "proxy_qlen", + "proxy_qlen %u ", ndtc->ndtc_proxy_qlen); + +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + } + + static void print_ndtparams(struct rtattr *tpb[]) +@@ -379,7 +379,7 @@ static void print_ndtparams(struct rtattr *tpb[]) + print_string(PRINT_FP, NULL, " dev ", NULL); + print_color_string(PRINT_ANY, COLOR_IFNAME, + "dev", "%s ", ll_index_to_name(ifindex)); +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + } + + print_string(PRINT_FP, NULL, " ", NULL); +@@ -482,7 +482,7 @@ static void print_ndtparams(struct rtattr *tpb[]) + print_u64(PRINT_ANY, "locktime", "locktime %llu ", locktime); + } + +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + } + + static void print_ndtstats(const struct ndt_stats *ndts) +@@ -517,7 +517,7 @@ static void print_ndtstats(const struct ndt_stats *ndts) + print_u64(PRINT_ANY, "forced_gc_runs", "forced_gc_runs %llu ", + ndts->ndts_forced_gc_runs); + +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + } + + static int print_ntable(const struct sockaddr_nl *who, +@@ -579,7 +579,7 @@ static int print_ntable(const struct sockaddr_nl *who, + print_string(PRINT_ANY, "name", "%s ", name); + } + +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + + ret = (tb[NDTA_THRESH1] || tb[NDTA_THRESH2] || tb[NDTA_THRESH3] || + tb[NDTA_GC_INTERVAL]); +@@ -611,7 +611,7 @@ static int print_ntable(const struct sockaddr_nl *who, + } + + if (ret) +- print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_nl(); + + if (tb[NDTA_CONFIG] && show_stats) + print_ndtconfig(RTA_DATA(tb[NDTA_CONFIG])); +diff --git a/lib/json_print.c b/lib/json_print.c +index 5dc41bf..09e51d0 100644 +--- a/lib/json_print.c ++++ b/lib/json_print.c +@@ -221,3 +221,10 @@ void print_color_null(enum output_type type, + color_fprintf(stdout, color, fmt, value); + } + } ++ ++/* Print line seperator (if not in JSON mode) */ ++void print_nl(void) ++{ ++ if (!_jw) ++ printf("%s", _SL_); ++} +diff --git a/lib/utils.c b/lib/utils.c +index 02ce677..e87ecf3 100644 +--- a/lib/utils.c ++++ b/lib/utils.c +@@ -42,6 +42,7 @@ + int resolve_hosts; + int timestamp_short; + int pretty; ++const char *_SL_ = "\n"; + + int read_prop(const char *dev, char *prop, long *value) + { +diff --git a/tc/tc.c b/tc/tc.c +index 3bb5910..2e97f2b 100644 +--- a/tc/tc.c ++++ b/tc/tc.c +@@ -43,7 +43,6 @@ bool use_names; + int json; + int color; + int oneline; +-const char *_SL_; + + static char *conf_file; + +-- +1.8.3.1 + diff --git a/SOURCES/0018-bridge-fdb-Fix-for-missing-keywords-in-non-JSON-outp.patch b/SOURCES/0018-bridge-fdb-Fix-for-missing-keywords-in-non-JSON-outp.patch new file mode 100644 index 0000000..a6c0a6e --- /dev/null +++ b/SOURCES/0018-bridge-fdb-Fix-for-missing-keywords-in-non-JSON-outp.patch @@ -0,0 +1,58 @@ +From 32c326673c4c2a5513d52898ebab453ccbb178a2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Oct 2018 10:52:09 +0200 +Subject: [PATCH] bridge: fdb: Fix for missing keywords in non-JSON output + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1636532 +Upstream Status: iproute2.git commit 4abb8c723a648 + +commit 4abb8c723a648ac9edc33741d2064e2507a6bae3 +Author: Phil Sutter +Date: Tue Oct 9 14:44:08 2018 +0200 + + bridge: fdb: Fix for missing keywords in non-JSON output + + While migrating to JSON print library, some keywords were dropped from + standard output by accident. Add them back to unbreak output parsers. + + Fixes: c7c1a1ef51aea ("bridge: colorize output and use JSON print library") + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + bridge/fdb.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/bridge/fdb.c b/bridge/fdb.c +index 4dbc894..6487fac 100644 +--- a/bridge/fdb.c ++++ b/bridge/fdb.c +@@ -182,7 +182,7 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + if (!is_json_context()) + fprintf(fp, "dev "); + print_color_string(PRINT_ANY, COLOR_IFNAME, +- "ifname", "%s ", ++ "ifname", "dev %s ", + ll_index_to_name(r->ndm_ifindex)); + } + +@@ -199,7 +199,7 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + + print_color_string(PRINT_ANY, + ifa_family_color(family), +- "dst", "%s ", dst); ++ "dst", "dst %s ", dst); + } + + if (vid) +@@ -246,7 +246,7 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + + + if (tb[NDA_MASTER]) +- print_string(PRINT_ANY, "master", "%s ", ++ print_string(PRINT_ANY, "master", "master %s ", + ll_index_to_name(rta_getattr_u32(tb[NDA_MASTER]))); + + print_string(PRINT_ANY, "state", "%s\n", +-- +1.8.3.1 + diff --git a/SOURCES/0019-ip-addrlabel-Fix-printing-of-label-value.patch b/SOURCES/0019-ip-addrlabel-Fix-printing-of-label-value.patch new file mode 100644 index 0000000..801d99c --- /dev/null +++ b/SOURCES/0019-ip-addrlabel-Fix-printing-of-label-value.patch @@ -0,0 +1,40 @@ +From fd07e443d264ddf25d4152af3a44144e1a9b3fd9 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Oct 2018 10:52:51 +0200 +Subject: [PATCH] ip-addrlabel: Fix printing of label value + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1639412 +Upstream Status: iproute2.git commit 0b9b0d08c29f9 + +commit 0b9b0d08c29f9aa6cc1b83c853964d9cc18dc6f2 +Author: Phil Sutter +Date: Mon Oct 15 22:20:58 2018 +0200 + + ip-addrlabel: Fix printing of label value + + Passing the return value of RTA_DATA() to rta_getattr_u32() is wrong + since that function will call RTA_DATA() by itself already. + + Fixes: a7ad1c8a6845d ("ipaddrlabel: add json support") + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + ip/ipaddrlabel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c +index 2f79c56..8abe572 100644 +--- a/ip/ipaddrlabel.c ++++ b/ip/ipaddrlabel.c +@@ -95,7 +95,7 @@ int print_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg + } + + if (tb[IFAL_LABEL] && RTA_PAYLOAD(tb[IFAL_LABEL]) == sizeof(uint32_t)) { +- uint32_t label = rta_getattr_u32(RTA_DATA(tb[IFAL_LABEL])); ++ uint32_t label = rta_getattr_u32(tb[IFAL_LABEL]); + + print_uint(PRINT_ANY, + "label", "label %u ", label); +-- +1.8.3.1 + diff --git a/SOURCES/0020-iplink_vxlan-take-into-account-preferred_family-crea.patch b/SOURCES/0020-iplink_vxlan-take-into-account-preferred_family-crea.patch new file mode 100644 index 0000000..ffae166 --- /dev/null +++ b/SOURCES/0020-iplink_vxlan-take-into-account-preferred_family-crea.patch @@ -0,0 +1,76 @@ +From f08a8608335d46bea1b2cb122823a4c538ce6e46 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Oct 2018 10:53:57 +0200 +Subject: [PATCH] iplink_vxlan: take into account preferred_family creating + vxlan device + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1626321 +Upstream Status: iproute2.git commit c1360e3b483e5 + +commit c1360e3b483e54a61a36bd2fdb3bfb91a4d2b32a +Author: Lorenzo Bianconi +Date: Fri Sep 21 15:34:25 2018 +0200 + + iplink_vxlan: take into account preferred_family creating vxlan device + + Take into account the configured preferred_family if neither saddr or + daddr are provided since otherwise vxlan kernel module will use IPv4 as + default remote inet family neglecting the one provided by userspace. + This behaviour was originally in commit 97d564b90ccb ("vxlan: use + preferred address family when neither group or remote is specified"). + The issue can be triggered with the following reproducer: + + $ip -6 link add vxlan1 type vxlan id 42 dev enp0s2 \ + proxy nolearning l2miss l3miss + $bridge fdb add 46:47:1f:a7:1c:25 dev vxlan1 dst 2000::2 + RTNETLINK answers: Address family not supported by protocol + + Fixes: 1e9b8072de2c ("iplink_vxlan: Get rid of inet_get_addr()") + Signed-off-by: Lorenzo Bianconi + Signed-off-by: Stephen Hemminger +--- + ip/iplink_vxlan.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c +index 2bc253f..831f39a 100644 +--- a/ip/iplink_vxlan.c ++++ b/ip/iplink_vxlan.c +@@ -82,6 +82,7 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, + __u64 attrs = 0; + bool set_op = (n->nlmsg_type == RTM_NEWLINK && + !(n->nlmsg_flags & NLM_F_CREATE)); ++ bool selected_family = false; + + saddr.family = daddr.family = AF_UNSPEC; + +@@ -356,12 +357,26 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, + int type = (saddr.family == AF_INET) ? IFLA_VXLAN_LOCAL + : IFLA_VXLAN_LOCAL6; + addattr_l(n, 1024, type, saddr.data, saddr.bytelen); ++ selected_family = true; + } + + if (is_addrtype_inet(&daddr)) { + int type = (daddr.family == AF_INET) ? IFLA_VXLAN_GROUP + : IFLA_VXLAN_GROUP6; + addattr_l(n, 1024, type, daddr.data, daddr.bytelen); ++ selected_family = true; ++ } ++ ++ if (!selected_family) { ++ if (preferred_family == AF_INET) { ++ get_addr(&daddr, "default", AF_INET); ++ addattr_l(n, 1024, IFLA_VXLAN_GROUP, ++ daddr.data, daddr.bytelen); ++ } else if (preferred_family == AF_INET6) { ++ get_addr(&daddr, "default", AF_INET6); ++ addattr_l(n, 1024, IFLA_VXLAN_GROUP6, ++ daddr.data, daddr.bytelen); ++ } + } + + if (!set_op || VXLAN_ATTRSET(attrs, IFLA_VXLAN_LEARNING)) +-- +1.8.3.1 + diff --git a/SOURCES/0021-json-make-0xhex-handle-u64.patch b/SOURCES/0021-json-make-0xhex-handle-u64.patch new file mode 100644 index 0000000..fbdeb8e --- /dev/null +++ b/SOURCES/0021-json-make-0xhex-handle-u64.patch @@ -0,0 +1,73 @@ +From 9822fef7a13eaec70be8e86c23bdb71569835bd0 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Oct 2018 12:49:51 +0200 +Subject: [PATCH] json: make 0xhex handle u64 + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1628428 +Upstream Status: iproute2.git commit 45ec4771d40cb + +commit 45ec4771d40cb367377e4148a2af22f25c20f3bf +Author: Sabrina Dubroca +Date: Fri Oct 12 17:34:32 2018 +0200 + + json: make 0xhex handle u64 + + Stephen converted macsec's sci to use 0xhex, but 0xhex handles + unsigned int's, not 64 bits ints. Thus, the output of the "ip macsec + show" command is mangled, with half of the SCI replaced with 0s: + + # ip macsec show + 11: macsec0: [...] + cipher suite: GCM-AES-128, using ICV length 16 + TXSC: 0000000001560001 on SA 0 + + # ip -d link show macsec0 + 11: macsec0@ens3: [...] + link/ether 52:54:00:12:01:56 brd ff:ff:ff:ff:ff:ff promiscuity 0 + macsec sci 5254001201560001 [...] + + where TXSC and sci should match. + + Fixes: c0b904de6211 ("macsec: support JSON") + Signed-off-by: Sabrina Dubroca + Signed-off-by: Stephen Hemminger +--- + include/json_print.h | 2 +- + lib/json_print.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/include/json_print.h b/include/json_print.h +index 78a6c83..218da31 100644 +--- a/include/json_print.h ++++ b/include/json_print.h +@@ -66,7 +66,7 @@ _PRINT_FUNC(uint, unsigned int); + _PRINT_FUNC(u64, uint64_t); + _PRINT_FUNC(hu, unsigned short); + _PRINT_FUNC(hex, unsigned int); +-_PRINT_FUNC(0xhex, unsigned int); ++_PRINT_FUNC(0xhex, unsigned long long int); + _PRINT_FUNC(luint, unsigned long int); + _PRINT_FUNC(lluint, unsigned long long int); + _PRINT_FUNC(float, double); +diff --git a/lib/json_print.c b/lib/json_print.c +index 09e51d0..cf13e9b 100644 +--- a/lib/json_print.c ++++ b/lib/json_print.c +@@ -171,12 +171,12 @@ void print_color_0xhex(enum output_type type, + enum color_attr color, + const char *key, + const char *fmt, +- unsigned int hex) ++ unsigned long long hex) + { + if (_IS_JSON_CONTEXT(type)) { + SPRINT_BUF(b1); + +- snprintf(b1, sizeof(b1), "%#x", hex); ++ snprintf(b1, sizeof(b1), "%#llx", hex); + print_string(PRINT_JSON, key, NULL, b1); + } else if (_IS_FP_CONTEXT(type)) { + color_fprintf(stdout, color, fmt, hex); +-- +1.8.3.1 + diff --git a/SOURCES/0022-macsec-fix-off-by-one-when-parsing-attributes.patch b/SOURCES/0022-macsec-fix-off-by-one-when-parsing-attributes.patch new file mode 100644 index 0000000..6b629be --- /dev/null +++ b/SOURCES/0022-macsec-fix-off-by-one-when-parsing-attributes.patch @@ -0,0 +1,114 @@ +From 03525ec63a5821a30461047da1dc8d907b3e3751 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Oct 2018 12:49:51 +0200 +Subject: [PATCH] macsec: fix off-by-one when parsing attributes + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1628428 +Upstream Status: iproute2.git commit 9b45f8ec13b0d + +commit 9b45f8ec13b0d338c70ef0758f751c249be6c7f0 +Author: Sabrina Dubroca +Date: Fri Oct 12 17:34:12 2018 +0200 + + macsec: fix off-by-one when parsing attributes + + I seem to have had a massive brainfart with uses of + parse_rtattr_nested(). The rtattr* array must have MAX+1 elements, and + the call to parse_rtattr_nested must have MAX as its bound. Let's fix + those. + + Fixes: b26fc590ce62 ("ip: add MACsec support") + Signed-off-by: Sabrina Dubroca + Signed-off-by: Stephen Hemminger +--- + ip/ipmacsec.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c +index fa56e0e..007ce54 100644 +--- a/ip/ipmacsec.c ++++ b/ip/ipmacsec.c +@@ -727,7 +727,7 @@ static void print_txsc_stats(const char *prefix, struct rtattr *attr) + if (!attr || show_stats == 0) + return; + +- parse_rtattr_nested(stats, MACSEC_TXSC_STATS_ATTR_MAX + 1, attr); ++ parse_rtattr_nested(stats, MACSEC_TXSC_STATS_ATTR_MAX, attr); + + print_stats(prefix, txsc_stats_names, NUM_MACSEC_TXSC_STATS_ATTR, + stats); +@@ -751,7 +751,7 @@ static void print_secy_stats(const char *prefix, struct rtattr *attr) + if (!attr || show_stats == 0) + return; + +- parse_rtattr_nested(stats, MACSEC_SECY_STATS_ATTR_MAX + 1, attr); ++ parse_rtattr_nested(stats, MACSEC_SECY_STATS_ATTR_MAX, attr); + + print_stats(prefix, secy_stats_names, + NUM_MACSEC_SECY_STATS_ATTR, stats); +@@ -772,7 +772,7 @@ static void print_rxsa_stats(const char *prefix, struct rtattr *attr) + if (!attr || show_stats == 0) + return; + +- parse_rtattr_nested(stats, MACSEC_SA_STATS_ATTR_MAX + 1, attr); ++ parse_rtattr_nested(stats, MACSEC_SA_STATS_ATTR_MAX, attr); + + print_stats(prefix, rxsa_stats_names, NUM_MACSEC_SA_STATS_ATTR, stats); + } +@@ -789,7 +789,7 @@ static void print_txsa_stats(const char *prefix, struct rtattr *attr) + if (!attr || show_stats == 0) + return; + +- parse_rtattr_nested(stats, MACSEC_SA_STATS_ATTR_MAX + 1, attr); ++ parse_rtattr_nested(stats, MACSEC_SA_STATS_ATTR_MAX, attr); + + print_stats(prefix, txsa_stats_names, NUM_MACSEC_SA_STATS_ATTR, stats); + } +@@ -817,7 +817,7 @@ static void print_tx_sc(const char *prefix, __u64 sci, __u8 encoding_sa, + bool state; + + open_json_object(NULL); +- parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX + 1, a); ++ parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX, a); + state = rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_ACTIVE]); + + print_string(PRINT_FP, NULL, "%s", prefix); +@@ -858,7 +858,7 @@ static void print_rxsc_stats(const char *prefix, struct rtattr *attr) + if (!attr || show_stats == 0) + return; + +- parse_rtattr_nested(stats, MACSEC_RXSC_STATS_ATTR_MAX + 1, attr); ++ parse_rtattr_nested(stats, MACSEC_RXSC_STATS_ATTR_MAX, attr); + + print_stats(prefix, rxsc_stats_names, + NUM_MACSEC_RXSC_STATS_ATTR, stats); +@@ -885,7 +885,7 @@ static void print_rx_sc(const char *prefix, __be64 sci, __u8 active, + bool state; + + open_json_object(NULL); +- parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX + 1, a); ++ parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX, a); + state = rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_ACTIVE]); + + print_string(PRINT_FP, NULL, "%s", prefix); +@@ -918,7 +918,7 @@ static void print_rxsc_list(struct rtattr *sc) + + open_json_object(NULL); + +- parse_rtattr_nested(sc_attr, MACSEC_RXSC_ATTR_MAX + 1, c); ++ parse_rtattr_nested(sc_attr, MACSEC_RXSC_ATTR_MAX, c); + print_rx_sc(" ", + rta_getattr_u64(sc_attr[MACSEC_RXSC_ATTR_SCI]), + rta_getattr_u32(sc_attr[MACSEC_RXSC_ATTR_ACTIVE]), +@@ -958,7 +958,7 @@ static int process(const struct sockaddr_nl *who, struct nlmsghdr *n, + } + + ifindex = rta_getattr_u32(attrs[MACSEC_ATTR_IFINDEX]); +- parse_rtattr_nested(attrs_secy, MACSEC_SECY_ATTR_MAX + 1, ++ parse_rtattr_nested(attrs_secy, MACSEC_SECY_ATTR_MAX, + attrs[MACSEC_ATTR_SECY]); + + if (!validate_secy_dump(attrs_secy)) { +-- +1.8.3.1 + diff --git a/SOURCES/0023-uapi-add-snmp-header-file.patch b/SOURCES/0023-uapi-add-snmp-header-file.patch new file mode 100644 index 0000000..c3e58d0 --- /dev/null +++ b/SOURCES/0023-uapi-add-snmp-header-file.patch @@ -0,0 +1,357 @@ +From 23bf1358295afa575227a41b5cd427cd1f3fdc0c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Oct 2018 12:51:12 +0200 +Subject: [PATCH] uapi: add snmp header file + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1626306 +Upstream Status: iproute2.git commit 9e030e77f20ab + +commit 9e030e77f20ab177e8717f054c9d53050b9a5d53 +Author: Lorenzo Bianconi +Date: Wed Oct 10 17:00:57 2018 +0200 + + uapi: add snmp header file + + Introduce snmp header file. It will be used in subsequent patch in + order to parse device statistics reported in + IFLA_INET6_STATS/IFLA_INET6_ICMP6STATS netlink attributes + + Signed-off-by: Lorenzo Bianconi + Signed-off-by: Stephen Hemminger +--- + include/uapi/linux/snmp.h | 323 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 323 insertions(+) + create mode 100644 include/uapi/linux/snmp.h + +diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h +new file mode 100644 +index 0000000..f80135e +--- /dev/null ++++ b/include/uapi/linux/snmp.h +@@ -0,0 +1,323 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++/* ++ * Definitions for MIBs ++ * ++ * Author: Hideaki YOSHIFUJI ++ */ ++ ++#ifndef _LINUX_SNMP_H ++#define _LINUX_SNMP_H ++ ++/* ipstats mib definitions */ ++/* ++ * RFC 1213: MIB-II ++ * RFC 2011 (updates 1213): SNMPv2-MIB-IP ++ * RFC 2863: Interfaces Group MIB ++ * RFC 2465: IPv6 MIB: General Group ++ * draft-ietf-ipv6-rfc2011-update-10.txt: MIB for IP: IP Statistics Tables ++ */ ++enum ++{ ++ IPSTATS_MIB_NUM = 0, ++/* frequently written fields in fast path, kept in same cache line */ ++ IPSTATS_MIB_INPKTS, /* InReceives */ ++ IPSTATS_MIB_INOCTETS, /* InOctets */ ++ IPSTATS_MIB_INDELIVERS, /* InDelivers */ ++ IPSTATS_MIB_OUTFORWDATAGRAMS, /* OutForwDatagrams */ ++ IPSTATS_MIB_OUTPKTS, /* OutRequests */ ++ IPSTATS_MIB_OUTOCTETS, /* OutOctets */ ++/* other fields */ ++ IPSTATS_MIB_INHDRERRORS, /* InHdrErrors */ ++ IPSTATS_MIB_INTOOBIGERRORS, /* InTooBigErrors */ ++ IPSTATS_MIB_INNOROUTES, /* InNoRoutes */ ++ IPSTATS_MIB_INADDRERRORS, /* InAddrErrors */ ++ IPSTATS_MIB_INUNKNOWNPROTOS, /* InUnknownProtos */ ++ IPSTATS_MIB_INTRUNCATEDPKTS, /* InTruncatedPkts */ ++ IPSTATS_MIB_INDISCARDS, /* InDiscards */ ++ IPSTATS_MIB_OUTDISCARDS, /* OutDiscards */ ++ IPSTATS_MIB_OUTNOROUTES, /* OutNoRoutes */ ++ IPSTATS_MIB_REASMTIMEOUT, /* ReasmTimeout */ ++ IPSTATS_MIB_REASMREQDS, /* ReasmReqds */ ++ IPSTATS_MIB_REASMOKS, /* ReasmOKs */ ++ IPSTATS_MIB_REASMFAILS, /* ReasmFails */ ++ IPSTATS_MIB_FRAGOKS, /* FragOKs */ ++ IPSTATS_MIB_FRAGFAILS, /* FragFails */ ++ IPSTATS_MIB_FRAGCREATES, /* FragCreates */ ++ IPSTATS_MIB_INMCASTPKTS, /* InMcastPkts */ ++ IPSTATS_MIB_OUTMCASTPKTS, /* OutMcastPkts */ ++ IPSTATS_MIB_INBCASTPKTS, /* InBcastPkts */ ++ IPSTATS_MIB_OUTBCASTPKTS, /* OutBcastPkts */ ++ IPSTATS_MIB_INMCASTOCTETS, /* InMcastOctets */ ++ IPSTATS_MIB_OUTMCASTOCTETS, /* OutMcastOctets */ ++ IPSTATS_MIB_INBCASTOCTETS, /* InBcastOctets */ ++ IPSTATS_MIB_OUTBCASTOCTETS, /* OutBcastOctets */ ++ IPSTATS_MIB_CSUMERRORS, /* InCsumErrors */ ++ IPSTATS_MIB_NOECTPKTS, /* InNoECTPkts */ ++ IPSTATS_MIB_ECT1PKTS, /* InECT1Pkts */ ++ IPSTATS_MIB_ECT0PKTS, /* InECT0Pkts */ ++ IPSTATS_MIB_CEPKTS, /* InCEPkts */ ++ IPSTATS_MIB_REASM_OVERLAPS, /* ReasmOverlaps */ ++ __IPSTATS_MIB_MAX ++}; ++ ++/* icmp mib definitions */ ++/* ++ * RFC 1213: MIB-II ICMP Group ++ * RFC 2011 (updates 1213): SNMPv2 MIB for IP: ICMP group ++ */ ++enum ++{ ++ ICMP_MIB_NUM = 0, ++ ICMP_MIB_INMSGS, /* InMsgs */ ++ ICMP_MIB_INERRORS, /* InErrors */ ++ ICMP_MIB_INDESTUNREACHS, /* InDestUnreachs */ ++ ICMP_MIB_INTIMEEXCDS, /* InTimeExcds */ ++ ICMP_MIB_INPARMPROBS, /* InParmProbs */ ++ ICMP_MIB_INSRCQUENCHS, /* InSrcQuenchs */ ++ ICMP_MIB_INREDIRECTS, /* InRedirects */ ++ ICMP_MIB_INECHOS, /* InEchos */ ++ ICMP_MIB_INECHOREPS, /* InEchoReps */ ++ ICMP_MIB_INTIMESTAMPS, /* InTimestamps */ ++ ICMP_MIB_INTIMESTAMPREPS, /* InTimestampReps */ ++ ICMP_MIB_INADDRMASKS, /* InAddrMasks */ ++ ICMP_MIB_INADDRMASKREPS, /* InAddrMaskReps */ ++ ICMP_MIB_OUTMSGS, /* OutMsgs */ ++ ICMP_MIB_OUTERRORS, /* OutErrors */ ++ ICMP_MIB_OUTDESTUNREACHS, /* OutDestUnreachs */ ++ ICMP_MIB_OUTTIMEEXCDS, /* OutTimeExcds */ ++ ICMP_MIB_OUTPARMPROBS, /* OutParmProbs */ ++ ICMP_MIB_OUTSRCQUENCHS, /* OutSrcQuenchs */ ++ ICMP_MIB_OUTREDIRECTS, /* OutRedirects */ ++ ICMP_MIB_OUTECHOS, /* OutEchos */ ++ ICMP_MIB_OUTECHOREPS, /* OutEchoReps */ ++ ICMP_MIB_OUTTIMESTAMPS, /* OutTimestamps */ ++ ICMP_MIB_OUTTIMESTAMPREPS, /* OutTimestampReps */ ++ ICMP_MIB_OUTADDRMASKS, /* OutAddrMasks */ ++ ICMP_MIB_OUTADDRMASKREPS, /* OutAddrMaskReps */ ++ ICMP_MIB_CSUMERRORS, /* InCsumErrors */ ++ __ICMP_MIB_MAX ++}; ++ ++#define __ICMPMSG_MIB_MAX 512 /* Out+In for all 8-bit ICMP types */ ++ ++/* icmp6 mib definitions */ ++/* ++ * RFC 2466: ICMPv6-MIB ++ */ ++enum ++{ ++ ICMP6_MIB_NUM = 0, ++ ICMP6_MIB_INMSGS, /* InMsgs */ ++ ICMP6_MIB_INERRORS, /* InErrors */ ++ ICMP6_MIB_OUTMSGS, /* OutMsgs */ ++ ICMP6_MIB_OUTERRORS, /* OutErrors */ ++ ICMP6_MIB_CSUMERRORS, /* InCsumErrors */ ++ __ICMP6_MIB_MAX ++}; ++ ++#define __ICMP6MSG_MIB_MAX 512 /* Out+In for all 8-bit ICMPv6 types */ ++ ++/* tcp mib definitions */ ++/* ++ * RFC 1213: MIB-II TCP group ++ * RFC 2012 (updates 1213): SNMPv2-MIB-TCP ++ */ ++enum ++{ ++ TCP_MIB_NUM = 0, ++ TCP_MIB_RTOALGORITHM, /* RtoAlgorithm */ ++ TCP_MIB_RTOMIN, /* RtoMin */ ++ TCP_MIB_RTOMAX, /* RtoMax */ ++ TCP_MIB_MAXCONN, /* MaxConn */ ++ TCP_MIB_ACTIVEOPENS, /* ActiveOpens */ ++ TCP_MIB_PASSIVEOPENS, /* PassiveOpens */ ++ TCP_MIB_ATTEMPTFAILS, /* AttemptFails */ ++ TCP_MIB_ESTABRESETS, /* EstabResets */ ++ TCP_MIB_CURRESTAB, /* CurrEstab */ ++ TCP_MIB_INSEGS, /* InSegs */ ++ TCP_MIB_OUTSEGS, /* OutSegs */ ++ TCP_MIB_RETRANSSEGS, /* RetransSegs */ ++ TCP_MIB_INERRS, /* InErrs */ ++ TCP_MIB_OUTRSTS, /* OutRsts */ ++ TCP_MIB_CSUMERRORS, /* InCsumErrors */ ++ __TCP_MIB_MAX ++}; ++ ++/* udp mib definitions */ ++/* ++ * RFC 1213: MIB-II UDP group ++ * RFC 2013 (updates 1213): SNMPv2-MIB-UDP ++ */ ++enum ++{ ++ UDP_MIB_NUM = 0, ++ UDP_MIB_INDATAGRAMS, /* InDatagrams */ ++ UDP_MIB_NOPORTS, /* NoPorts */ ++ UDP_MIB_INERRORS, /* InErrors */ ++ UDP_MIB_OUTDATAGRAMS, /* OutDatagrams */ ++ UDP_MIB_RCVBUFERRORS, /* RcvbufErrors */ ++ UDP_MIB_SNDBUFERRORS, /* SndbufErrors */ ++ UDP_MIB_CSUMERRORS, /* InCsumErrors */ ++ UDP_MIB_IGNOREDMULTI, /* IgnoredMulti */ ++ __UDP_MIB_MAX ++}; ++ ++/* linux mib definitions */ ++enum ++{ ++ LINUX_MIB_NUM = 0, ++ LINUX_MIB_SYNCOOKIESSENT, /* SyncookiesSent */ ++ LINUX_MIB_SYNCOOKIESRECV, /* SyncookiesRecv */ ++ LINUX_MIB_SYNCOOKIESFAILED, /* SyncookiesFailed */ ++ LINUX_MIB_EMBRYONICRSTS, /* EmbryonicRsts */ ++ LINUX_MIB_PRUNECALLED, /* PruneCalled */ ++ LINUX_MIB_RCVPRUNED, /* RcvPruned */ ++ LINUX_MIB_OFOPRUNED, /* OfoPruned */ ++ LINUX_MIB_OUTOFWINDOWICMPS, /* OutOfWindowIcmps */ ++ LINUX_MIB_LOCKDROPPEDICMPS, /* LockDroppedIcmps */ ++ LINUX_MIB_ARPFILTER, /* ArpFilter */ ++ LINUX_MIB_TIMEWAITED, /* TimeWaited */ ++ LINUX_MIB_TIMEWAITRECYCLED, /* TimeWaitRecycled */ ++ LINUX_MIB_TIMEWAITKILLED, /* TimeWaitKilled */ ++ LINUX_MIB_PAWSACTIVEREJECTED, /* PAWSActiveRejected */ ++ LINUX_MIB_PAWSESTABREJECTED, /* PAWSEstabRejected */ ++ LINUX_MIB_DELAYEDACKS, /* DelayedACKs */ ++ LINUX_MIB_DELAYEDACKLOCKED, /* DelayedACKLocked */ ++ LINUX_MIB_DELAYEDACKLOST, /* DelayedACKLost */ ++ LINUX_MIB_LISTENOVERFLOWS, /* ListenOverflows */ ++ LINUX_MIB_LISTENDROPS, /* ListenDrops */ ++ LINUX_MIB_TCPHPHITS, /* TCPHPHits */ ++ LINUX_MIB_TCPPUREACKS, /* TCPPureAcks */ ++ LINUX_MIB_TCPHPACKS, /* TCPHPAcks */ ++ LINUX_MIB_TCPRENORECOVERY, /* TCPRenoRecovery */ ++ LINUX_MIB_TCPSACKRECOVERY, /* TCPSackRecovery */ ++ LINUX_MIB_TCPSACKRENEGING, /* TCPSACKReneging */ ++ LINUX_MIB_TCPSACKREORDER, /* TCPSACKReorder */ ++ LINUX_MIB_TCPRENOREORDER, /* TCPRenoReorder */ ++ LINUX_MIB_TCPTSREORDER, /* TCPTSReorder */ ++ LINUX_MIB_TCPFULLUNDO, /* TCPFullUndo */ ++ LINUX_MIB_TCPPARTIALUNDO, /* TCPPartialUndo */ ++ LINUX_MIB_TCPDSACKUNDO, /* TCPDSACKUndo */ ++ LINUX_MIB_TCPLOSSUNDO, /* TCPLossUndo */ ++ LINUX_MIB_TCPLOSTRETRANSMIT, /* TCPLostRetransmit */ ++ LINUX_MIB_TCPRENOFAILURES, /* TCPRenoFailures */ ++ LINUX_MIB_TCPSACKFAILURES, /* TCPSackFailures */ ++ LINUX_MIB_TCPLOSSFAILURES, /* TCPLossFailures */ ++ LINUX_MIB_TCPFASTRETRANS, /* TCPFastRetrans */ ++ LINUX_MIB_TCPSLOWSTARTRETRANS, /* TCPSlowStartRetrans */ ++ LINUX_MIB_TCPTIMEOUTS, /* TCPTimeouts */ ++ LINUX_MIB_TCPLOSSPROBES, /* TCPLossProbes */ ++ LINUX_MIB_TCPLOSSPROBERECOVERY, /* TCPLossProbeRecovery */ ++ LINUX_MIB_TCPRENORECOVERYFAIL, /* TCPRenoRecoveryFail */ ++ LINUX_MIB_TCPSACKRECOVERYFAIL, /* TCPSackRecoveryFail */ ++ LINUX_MIB_TCPRCVCOLLAPSED, /* TCPRcvCollapsed */ ++ LINUX_MIB_TCPDSACKOLDSENT, /* TCPDSACKOldSent */ ++ LINUX_MIB_TCPDSACKOFOSENT, /* TCPDSACKOfoSent */ ++ LINUX_MIB_TCPDSACKRECV, /* TCPDSACKRecv */ ++ LINUX_MIB_TCPDSACKOFORECV, /* TCPDSACKOfoRecv */ ++ LINUX_MIB_TCPABORTONDATA, /* TCPAbortOnData */ ++ LINUX_MIB_TCPABORTONCLOSE, /* TCPAbortOnClose */ ++ LINUX_MIB_TCPABORTONMEMORY, /* TCPAbortOnMemory */ ++ LINUX_MIB_TCPABORTONTIMEOUT, /* TCPAbortOnTimeout */ ++ LINUX_MIB_TCPABORTONLINGER, /* TCPAbortOnLinger */ ++ LINUX_MIB_TCPABORTFAILED, /* TCPAbortFailed */ ++ LINUX_MIB_TCPMEMORYPRESSURES, /* TCPMemoryPressures */ ++ LINUX_MIB_TCPMEMORYPRESSURESCHRONO, /* TCPMemoryPressuresChrono */ ++ LINUX_MIB_TCPSACKDISCARD, /* TCPSACKDiscard */ ++ LINUX_MIB_TCPDSACKIGNOREDOLD, /* TCPSACKIgnoredOld */ ++ LINUX_MIB_TCPDSACKIGNOREDNOUNDO, /* TCPSACKIgnoredNoUndo */ ++ LINUX_MIB_TCPSPURIOUSRTOS, /* TCPSpuriousRTOs */ ++ LINUX_MIB_TCPMD5NOTFOUND, /* TCPMD5NotFound */ ++ LINUX_MIB_TCPMD5UNEXPECTED, /* TCPMD5Unexpected */ ++ LINUX_MIB_TCPMD5FAILURE, /* TCPMD5Failure */ ++ LINUX_MIB_SACKSHIFTED, ++ LINUX_MIB_SACKMERGED, ++ LINUX_MIB_SACKSHIFTFALLBACK, ++ LINUX_MIB_TCPBACKLOGDROP, ++ LINUX_MIB_PFMEMALLOCDROP, ++ LINUX_MIB_TCPMINTTLDROP, /* RFC 5082 */ ++ LINUX_MIB_TCPDEFERACCEPTDROP, ++ LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */ ++ LINUX_MIB_TCPTIMEWAITOVERFLOW, /* TCPTimeWaitOverflow */ ++ LINUX_MIB_TCPREQQFULLDOCOOKIES, /* TCPReqQFullDoCookies */ ++ LINUX_MIB_TCPREQQFULLDROP, /* TCPReqQFullDrop */ ++ LINUX_MIB_TCPRETRANSFAIL, /* TCPRetransFail */ ++ LINUX_MIB_TCPRCVCOALESCE, /* TCPRcvCoalesce */ ++ LINUX_MIB_TCPOFOQUEUE, /* TCPOFOQueue */ ++ LINUX_MIB_TCPOFODROP, /* TCPOFODrop */ ++ LINUX_MIB_TCPOFOMERGE, /* TCPOFOMerge */ ++ LINUX_MIB_TCPCHALLENGEACK, /* TCPChallengeACK */ ++ LINUX_MIB_TCPSYNCHALLENGE, /* TCPSYNChallenge */ ++ LINUX_MIB_TCPFASTOPENACTIVE, /* TCPFastOpenActive */ ++ LINUX_MIB_TCPFASTOPENACTIVEFAIL, /* TCPFastOpenActiveFail */ ++ LINUX_MIB_TCPFASTOPENPASSIVE, /* TCPFastOpenPassive*/ ++ LINUX_MIB_TCPFASTOPENPASSIVEFAIL, /* TCPFastOpenPassiveFail */ ++ LINUX_MIB_TCPFASTOPENLISTENOVERFLOW, /* TCPFastOpenListenOverflow */ ++ LINUX_MIB_TCPFASTOPENCOOKIEREQD, /* TCPFastOpenCookieReqd */ ++ LINUX_MIB_TCPFASTOPENBLACKHOLE, /* TCPFastOpenBlackholeDetect */ ++ LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES, /* TCPSpuriousRtxHostQueues */ ++ LINUX_MIB_BUSYPOLLRXPACKETS, /* BusyPollRxPackets */ ++ LINUX_MIB_TCPAUTOCORKING, /* TCPAutoCorking */ ++ LINUX_MIB_TCPFROMZEROWINDOWADV, /* TCPFromZeroWindowAdv */ ++ LINUX_MIB_TCPTOZEROWINDOWADV, /* TCPToZeroWindowAdv */ ++ LINUX_MIB_TCPWANTZEROWINDOWADV, /* TCPWantZeroWindowAdv */ ++ LINUX_MIB_TCPSYNRETRANS, /* TCPSynRetrans */ ++ LINUX_MIB_TCPORIGDATASENT, /* TCPOrigDataSent */ ++ LINUX_MIB_TCPHYSTARTTRAINDETECT, /* TCPHystartTrainDetect */ ++ LINUX_MIB_TCPHYSTARTTRAINCWND, /* TCPHystartTrainCwnd */ ++ LINUX_MIB_TCPHYSTARTDELAYDETECT, /* TCPHystartDelayDetect */ ++ LINUX_MIB_TCPHYSTARTDELAYCWND, /* TCPHystartDelayCwnd */ ++ LINUX_MIB_TCPACKSKIPPEDSYNRECV, /* TCPACKSkippedSynRecv */ ++ LINUX_MIB_TCPACKSKIPPEDPAWS, /* TCPACKSkippedPAWS */ ++ LINUX_MIB_TCPACKSKIPPEDSEQ, /* TCPACKSkippedSeq */ ++ LINUX_MIB_TCPACKSKIPPEDFINWAIT2, /* TCPACKSkippedFinWait2 */ ++ LINUX_MIB_TCPACKSKIPPEDTIMEWAIT, /* TCPACKSkippedTimeWait */ ++ LINUX_MIB_TCPACKSKIPPEDCHALLENGE, /* TCPACKSkippedChallenge */ ++ LINUX_MIB_TCPWINPROBE, /* TCPWinProbe */ ++ LINUX_MIB_TCPKEEPALIVE, /* TCPKeepAlive */ ++ LINUX_MIB_TCPMTUPFAIL, /* TCPMTUPFail */ ++ LINUX_MIB_TCPMTUPSUCCESS, /* TCPMTUPSuccess */ ++ LINUX_MIB_TCPDELIVERED, /* TCPDelivered */ ++ LINUX_MIB_TCPDELIVEREDCE, /* TCPDeliveredCE */ ++ LINUX_MIB_TCPACKCOMPRESSED, /* TCPAckCompressed */ ++ LINUX_MIB_TCPZEROWINDOWDROP, /* TCPZeroWindowDrop */ ++ LINUX_MIB_TCPRCVQDROP, /* TCPRcvQDrop */ ++ __LINUX_MIB_MAX ++}; ++ ++/* linux Xfrm mib definitions */ ++enum ++{ ++ LINUX_MIB_XFRMNUM = 0, ++ LINUX_MIB_XFRMINERROR, /* XfrmInError */ ++ LINUX_MIB_XFRMINBUFFERERROR, /* XfrmInBufferError */ ++ LINUX_MIB_XFRMINHDRERROR, /* XfrmInHdrError */ ++ LINUX_MIB_XFRMINNOSTATES, /* XfrmInNoStates */ ++ LINUX_MIB_XFRMINSTATEPROTOERROR, /* XfrmInStateProtoError */ ++ LINUX_MIB_XFRMINSTATEMODEERROR, /* XfrmInStateModeError */ ++ LINUX_MIB_XFRMINSTATESEQERROR, /* XfrmInStateSeqError */ ++ LINUX_MIB_XFRMINSTATEEXPIRED, /* XfrmInStateExpired */ ++ LINUX_MIB_XFRMINSTATEMISMATCH, /* XfrmInStateMismatch */ ++ LINUX_MIB_XFRMINSTATEINVALID, /* XfrmInStateInvalid */ ++ LINUX_MIB_XFRMINTMPLMISMATCH, /* XfrmInTmplMismatch */ ++ LINUX_MIB_XFRMINNOPOLS, /* XfrmInNoPols */ ++ LINUX_MIB_XFRMINPOLBLOCK, /* XfrmInPolBlock */ ++ LINUX_MIB_XFRMINPOLERROR, /* XfrmInPolError */ ++ LINUX_MIB_XFRMOUTERROR, /* XfrmOutError */ ++ LINUX_MIB_XFRMOUTBUNDLEGENERROR, /* XfrmOutBundleGenError */ ++ LINUX_MIB_XFRMOUTBUNDLECHECKERROR, /* XfrmOutBundleCheckError */ ++ LINUX_MIB_XFRMOUTNOSTATES, /* XfrmOutNoStates */ ++ LINUX_MIB_XFRMOUTSTATEPROTOERROR, /* XfrmOutStateProtoError */ ++ LINUX_MIB_XFRMOUTSTATEMODEERROR, /* XfrmOutStateModeError */ ++ LINUX_MIB_XFRMOUTSTATESEQERROR, /* XfrmOutStateSeqError */ ++ LINUX_MIB_XFRMOUTSTATEEXPIRED, /* XfrmOutStateExpired */ ++ LINUX_MIB_XFRMOUTPOLBLOCK, /* XfrmOutPolBlock */ ++ LINUX_MIB_XFRMOUTPOLDEAD, /* XfrmOutPolDead */ ++ LINUX_MIB_XFRMOUTPOLERROR, /* XfrmOutPolError */ ++ LINUX_MIB_XFRMFWDHDRERROR, /* XfrmFwdHdrError*/ ++ LINUX_MIB_XFRMOUTSTATEINVALID, /* XfrmOutStateInvalid */ ++ LINUX_MIB_XFRMACQUIREERROR, /* XfrmAcquireError */ ++ __LINUX_MIB_XFRMMAX ++}; ++ ++#endif /* _LINUX_SNMP_H */ +-- +1.8.3.1 + diff --git a/SOURCES/0024-utils-fix-get_rtnl_link_stats_rta-stats-parsing.patch b/SOURCES/0024-utils-fix-get_rtnl_link_stats_rta-stats-parsing.patch new file mode 100644 index 0000000..91b4ece --- /dev/null +++ b/SOURCES/0024-utils-fix-get_rtnl_link_stats_rta-stats-parsing.patch @@ -0,0 +1,93 @@ +From 2e4e707b662df2cf505147ca19da94ef97b6ea25 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Oct 2018 12:51:12 +0200 +Subject: [PATCH] utils: fix get_rtnl_link_stats_rta stats parsing + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1626306 +Upstream Status: iproute2.git commit c7a3b22961f52 + +commit c7a3b22961f528760766aa85095eb1ab04a39797 +Author: Lorenzo Bianconi +Date: Wed Oct 10 17:00:58 2018 +0200 + + utils: fix get_rtnl_link_stats_rta stats parsing + + iproute2 walks through the list of available tunnels using netlink + protocol in order to get device info instead of reading + them from proc filesystem. However the kernel reports device statistics + using IFLA_INET6_STATS/IFLA_INET6_ICMP6STATS attributes nested in + IFLA_PROTINFO one but iproutes expects these info in + IFLA_STATS64/IFLA_STATS attributes. + The issue can be triggered with the following reproducer: + + $ip link add ip6d0 type ip6tnl mode ip6ip6 local 1111::1 remote 2222::1 + $ip -6 -d -s tunnel show ip6d0 + ip6d0: ipv6/ipv6 remote 2222::1 local 1111::1 encaplimit 4 hoplimit 64 + tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000) + Dump terminated + + Fix the issue introducing IFLA_INET6_STATS attribute parsing + + Fixes: 3e953938717f ("iptunnel/ip6tunnel: Use netlink to walk through + tunnels list") + + Signed-off-by: Lorenzo Bianconi +--- + lib/utils.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/lib/utils.c b/lib/utils.c +index e87ecf3..7be2d6b 100644 +--- a/lib/utils.c ++++ b/lib/utils.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1549,6 +1550,24 @@ static void copy_rtnl_link_stats64(struct rtnl_link_stats64 *stats64, + *a++ = *b++; + } + ++#define IPSTATS_MIB_MAX_LEN (__IPSTATS_MIB_MAX * sizeof(__u64)) ++static void get_snmp_counters(struct rtnl_link_stats64 *stats64, ++ struct rtattr *s) ++{ ++ __u64 *mib = (__u64 *)RTA_DATA(s); ++ ++ memset(stats64, 0, sizeof(*stats64)); ++ ++ stats64->rx_packets = mib[IPSTATS_MIB_INPKTS]; ++ stats64->rx_bytes = mib[IPSTATS_MIB_INOCTETS]; ++ stats64->tx_packets = mib[IPSTATS_MIB_OUTPKTS]; ++ stats64->tx_bytes = mib[IPSTATS_MIB_OUTOCTETS]; ++ stats64->rx_errors = mib[IPSTATS_MIB_INDISCARDS]; ++ stats64->tx_errors = mib[IPSTATS_MIB_OUTDISCARDS]; ++ stats64->multicast = mib[IPSTATS_MIB_INMCASTPKTS]; ++ stats64->rx_frame_errors = mib[IPSTATS_MIB_CSUMERRORS]; ++} ++ + int get_rtnl_link_stats_rta(struct rtnl_link_stats64 *stats64, + struct rtattr *tb[]) + { +@@ -1565,6 +1584,14 @@ int get_rtnl_link_stats_rta(struct rtnl_link_stats64 *stats64, + rta = tb[IFLA_STATS]; + size = sizeof(struct rtnl_link_stats); + s = &stats; ++ } else if (tb[IFLA_PROTINFO]) { ++ struct rtattr *ptb[IPSTATS_MIB_MAX_LEN + 1]; ++ ++ parse_rtattr_nested(ptb, IPSTATS_MIB_MAX_LEN, ++ tb[IFLA_PROTINFO]); ++ if (ptb[IFLA_INET6_STATS]) ++ get_snmp_counters(stats64, ptb[IFLA_INET6_STATS]); ++ return sizeof(*stats64); + } else { + return -1; + } +-- +1.8.3.1 + diff --git a/SOURCES/0025-tc-htb-Print-default-value-in-hex.patch b/SOURCES/0025-tc-htb-Print-default-value-in-hex.patch new file mode 100644 index 0000000..7e9fc45 --- /dev/null +++ b/SOURCES/0025-tc-htb-Print-default-value-in-hex.patch @@ -0,0 +1,43 @@ +From 3e679f946a6313983ca544a28ce0ccf0072962e5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 12:22:23 +0200 +Subject: [PATCH] tc: htb: Print default value in hex + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1641053 +Upstream Status: iproute2.git commit 737b8258b35f4 + +commit 737b8258b35f4cc643a8153fdf955bfa0adec30f +Author: Phil Sutter +Date: Tue Oct 23 12:36:24 2018 +0200 + + tc: htb: Print default value in hex + + Value of 'default' is assumed to be hexadecimal when parsing, so + consequently it should be printed in hex as well. This is a regression + introduced when adding JSON output. + + As requested, also change JSON output to print the value as hex string. + + Fixes: f354fa6aa5ff0 ("tc: jsonify htb qdisc") + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + tc/q_htb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tc/q_htb.c b/tc/q_htb.c +index b93d31d..cce9ebc 100644 +--- a/tc/q_htb.c ++++ b/tc/q_htb.c +@@ -341,7 +341,7 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) + if (RTA_PAYLOAD(tb[TCA_HTB_INIT]) < sizeof(*gopt)) return -1; + + print_int(PRINT_ANY, "r2q", "r2q %d", gopt->rate2quantum); +- print_uint(PRINT_ANY, "default", " default %u", gopt->defcls); ++ print_0xhex(PRINT_ANY, "default", " default %x", gopt->defcls); + print_uint(PRINT_ANY, "direct_packets_stat", + " direct_packets_stat %u", gopt->direct_pkts); + if (show_details) { +-- +1.8.3.1 + diff --git a/SOURCES/0026-libnetlink-fix-leak-and-using-unused-memory-on-error.patch b/SOURCES/0026-libnetlink-fix-leak-and-using-unused-memory-on-error.patch new file mode 100644 index 0000000..9e355d1 --- /dev/null +++ b/SOURCES/0026-libnetlink-fix-leak-and-using-unused-memory-on-error.patch @@ -0,0 +1,81 @@ +From 3ec32595e21849de3165d52e1af48ca3bdf51fab Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 12:24:30 +0200 +Subject: [PATCH] libnetlink: fix leak and using unused memory on error + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1602555 +Upstream Status: iproute2.git commit c60389e4f9ea8 + +commit c60389e4f9ea88d7246dbb148d28791d577fe5b4 +Author: Stephen Hemminger +Date: Thu Sep 13 12:33:38 2018 -0700 + + libnetlink: fix leak and using unused memory on error + + If an error happens in multi-segment message (tc only) + then report the error and stop processing further responses. + This also fixes refering to the buffer after free. + + The sequence check is not necessary here because the + response message has already been validated to be in + the window of the sequence number of the iov. + + Reported-by: Mahesh Bandewar + Signed-off-by: Stephen Hemminger + Acked-by: Mahesh Bandewar +--- + lib/libnetlink.c | 23 +++++++++-------------- + 1 file changed, 9 insertions(+), 14 deletions(-) + +diff --git a/lib/libnetlink.c b/lib/libnetlink.c +index 928de1d..5868092 100644 +--- a/lib/libnetlink.c ++++ b/lib/libnetlink.c +@@ -617,7 +617,6 @@ static int __rtnl_talk_iov(struct rtnl_handle *rtnl, struct iovec *iov, + msg.msg_iovlen = 1; + i = 0; + while (1) { +-next: + status = rtnl_recvmsg(rtnl->fd, &msg, &buf); + ++i; + +@@ -660,27 +659,23 @@ next: + + if (l < sizeof(struct nlmsgerr)) { + fprintf(stderr, "ERROR truncated\n"); +- } else if (!err->error) { ++ free(buf); ++ return -1; ++ } ++ ++ if (!err->error) + /* check messages from kernel */ + nl_dump_ext_ack(h, errfn); + +- if (answer) +- *answer = (struct nlmsghdr *)buf; +- else +- free(buf); +- if (h->nlmsg_seq == seq) +- return 0; +- else if (i < iovlen) +- goto next; +- return 0; +- } +- + if (rtnl->proto != NETLINK_SOCK_DIAG && + show_rtnl_err) + rtnl_talk_error(h, err, errfn); + + errno = -err->error; +- free(buf); ++ if (answer) ++ *answer = (struct nlmsghdr *)buf; ++ else ++ free(buf); + return -i; + } + +-- +1.8.3.1 + diff --git a/SOURCES/0027-libnetlink-don-t-return-error-on-success.patch b/SOURCES/0027-libnetlink-don-t-return-error-on-success.patch new file mode 100644 index 0000000..99bb226 --- /dev/null +++ b/SOURCES/0027-libnetlink-don-t-return-error-on-success.patch @@ -0,0 +1,56 @@ +From 0a9e18d65228376c332d7ec0f87a19b8042e8a43 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 12:24:30 +0200 +Subject: [PATCH] libnetlink: don't return error on success + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1602555 +Upstream Status: iproute2.git commit b45e300024bb0 + +commit b45e300024bb0936a41821ad75117dc08b65669f +Author: Stephen Hemminger +Date: Tue Sep 25 10:08:48 2018 +0200 + + libnetlink: don't return error on success + + Change to error handling broke normal code. + + Fixes: c60389e4f9ea ("libnetlink: fix leak and using unused memory on error") + Reported-by: David Ahern + Signed-off-by: Stephen Hemminger +--- + lib/libnetlink.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/lib/libnetlink.c b/lib/libnetlink.c +index 5868092..f18dcea 100644 +--- a/lib/libnetlink.c ++++ b/lib/libnetlink.c +@@ -666,17 +666,20 @@ static int __rtnl_talk_iov(struct rtnl_handle *rtnl, struct iovec *iov, + if (!err->error) + /* check messages from kernel */ + nl_dump_ext_ack(h, errfn); ++ else { ++ errno = -err->error; + +- if (rtnl->proto != NETLINK_SOCK_DIAG && +- show_rtnl_err) +- rtnl_talk_error(h, err, errfn); ++ if (rtnl->proto != NETLINK_SOCK_DIAG && ++ show_rtnl_err) ++ rtnl_talk_error(h, err, errfn); ++ } + +- errno = -err->error; + if (answer) + *answer = (struct nlmsghdr *)buf; + else + free(buf); +- return -i; ++ ++ return err->error ? -i : 0; + } + + if (answer) { +-- +1.8.3.1 + diff --git a/SOURCES/0028-libnetlink-fix-use-after-free-of-message-buf.patch b/SOURCES/0028-libnetlink-fix-use-after-free-of-message-buf.patch new file mode 100644 index 0000000..48beb77 --- /dev/null +++ b/SOURCES/0028-libnetlink-fix-use-after-free-of-message-buf.patch @@ -0,0 +1,53 @@ +From e7c11266309ffa65143455ceefc17fe92d93511c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 12:24:30 +0200 +Subject: [PATCH] libnetlink: fix use-after-free of message buf + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1602555 +Upstream Status: iproute2.git commit 8c50b728b226f + +commit 8c50b728b226f6254251282697ce38a72639a6fc +Author: Vlad Buslov +Date: Mon Oct 8 23:52:26 2018 +0300 + + libnetlink: fix use-after-free of message buf + + In __rtnl_talk_iov() main loop, err is a pointer to memory in dynamically + allocated 'buf' that is used to store netlink messages. If netlink message + is an error message, buf is deallocated before returning with error code. + However, on return err->error code is checked one more time to generate + return value, after memory which err points to has already been + freed. Save error code in temporary variable and use the variable to + generate return value. + + Fixes: c60389e4f9ea ("libnetlink: fix leak and using unused memory on error") + Signed-off-by: Vlad Buslov + Signed-off-by: Stephen Hemminger +--- + lib/libnetlink.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lib/libnetlink.c b/lib/libnetlink.c +index f18dcea..a9932d4 100644 +--- a/lib/libnetlink.c ++++ b/lib/libnetlink.c +@@ -656,6 +656,7 @@ static int __rtnl_talk_iov(struct rtnl_handle *rtnl, struct iovec *iov, + + if (h->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(h); ++ int error = err->error; + + if (l < sizeof(struct nlmsgerr)) { + fprintf(stderr, "ERROR truncated\n"); +@@ -679,7 +680,7 @@ static int __rtnl_talk_iov(struct rtnl_handle *rtnl, struct iovec *iov, + else + free(buf); + +- return err->error ? -i : 0; ++ return error ? -i : 0; + } + + if (answer) { +-- +1.8.3.1 + diff --git a/SOURCES/0029-devlink-Fix-error-reporting-in-cmd_resource_set.patch b/SOURCES/0029-devlink-Fix-error-reporting-in-cmd_resource_set.patch new file mode 100644 index 0000000..ac59479 --- /dev/null +++ b/SOURCES/0029-devlink-Fix-error-reporting-in-cmd_resource_set.patch @@ -0,0 +1,41 @@ +From 8193c9eaecd5a9a5237424081c109df0d27770fd Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 12:24:30 +0200 +Subject: [PATCH] devlink: Fix error reporting in cmd_resource_set() + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1602555 +Upstream Status: iproute2.git commit b1ffc1f465928 + +commit b1ffc1f465928706e22d585932cead8d74f021de +Author: Phil Sutter +Date: Thu Oct 18 13:28:23 2018 +0200 + + devlink: Fix error reporting in cmd_resource_set() + + resource_path_parse() returns either zero or a negative error code, + hence the negated value must be passed to strerror(). + + Fixes: 8cd644095842a ("devlink: Add support for devlink resource abstraction") + Signed-off-by: Phil Sutter + Acked-by: Jiri Pirko + Signed-off-by: Stephen Hemminger +--- + devlink/devlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/devlink/devlink.c b/devlink/devlink.c +index 1142d16..7a5aef8 100644 +--- a/devlink/devlink.c ++++ b/devlink/devlink.c +@@ -4457,7 +4457,7 @@ static int cmd_resource_set(struct dl *dl) + &dl->opts.resource_id, + &dl->opts.resource_id_valid); + if (err) { +- pr_err("error parsing resource path %s\n", strerror(err)); ++ pr_err("error parsing resource path %s\n", strerror(-err)); + goto out; + } + +-- +1.8.3.1 + diff --git a/SOURCES/0030-rdma-Fix-for-ineffective-check-in-add_filter.patch b/SOURCES/0030-rdma-Fix-for-ineffective-check-in-add_filter.patch new file mode 100644 index 0000000..38b4687 --- /dev/null +++ b/SOURCES/0030-rdma-Fix-for-ineffective-check-in-add_filter.patch @@ -0,0 +1,42 @@ +From ad7f7e4a1fd4e0362a6d256c0d093d43b44e2c1d Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 12:24:30 +0200 +Subject: [PATCH] rdma: Fix for ineffective check in add_filter() + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1602555 +Upstream Status: iproute2.git commit 3b0070f6b1a31 + +commit 3b0070f6b1a319b7d6a431a39270a4804cb5927e +Author: Phil Sutter +Date: Thu Oct 18 13:41:54 2018 +0200 + + rdma: Fix for ineffective check in add_filter() + + With 'name' field defined as array in struct filters, it will always + contain a value irrespective of whether a name was assigned or not. + + Fix this by turning the field into a const char pointer. + + Fixes: 1174be72d1b4c ("rdma: Add filtering infrastructure") + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + rdma/rdma.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/rdma/rdma.h b/rdma/rdma.h +index d4b7ba1..c3b7530 100644 +--- a/rdma/rdma.h ++++ b/rdma/rdma.h +@@ -34,7 +34,7 @@ + + #define MAX_NUMBER_OF_FILTERS 64 + struct filters { +- char name[32]; ++ const char *name; + bool is_number; + }; + +-- +1.8.3.1 + diff --git a/SOURCES/0031-ip-route-Fix-for-memleak-in-error-path.patch b/SOURCES/0031-ip-route-Fix-for-memleak-in-error-path.patch new file mode 100644 index 0000000..9d3eea5 --- /dev/null +++ b/SOURCES/0031-ip-route-Fix-for-memleak-in-error-path.patch @@ -0,0 +1,65 @@ +From 0c762f107e6a5f6c56c42c0aba48f6aa9c6f1eef Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 12:24:30 +0200 +Subject: [PATCH] ip-route: Fix for memleak in error path + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1602555 +Upstream Status: iproute2.git commit e5da392ff8e39 + +commit e5da392ff8e3979b86cad04b238ffbbc8076e005 +Author: Phil Sutter +Date: Thu Oct 18 14:30:31 2018 +0200 + + ip-route: Fix for memleak in error path + + If call to rta_addattr_l() failed, parse_encap_seg6() would leak memory. + Fix this by making sure calls to free() are not skipped. + + Fixes: bd59e5b1517b0 ("ip-route: Fix segfault with many nexthops") + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + ip/iproute_lwtunnel.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c +index 969a476..85045d4 100644 +--- a/ip/iproute_lwtunnel.c ++++ b/ip/iproute_lwtunnel.c +@@ -498,6 +498,7 @@ static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp, + int argc = *argcp; + int encap = -1; + __u32 hmac = 0; ++ int ret = 0; + int srhlen; + + while (argc > 0) { +@@ -539,16 +540,19 @@ static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp, + memcpy(tuninfo->srh, srh, srhlen); + + if (rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo, +- sizeof(*tuninfo) + srhlen)) +- return -1; +- +- free(tuninfo); +- free(srh); ++ sizeof(*tuninfo) + srhlen)) { ++ ret = -1; ++ goto out; ++ } + + *argcp = argc + 1; + *argvp = argv - 1; + +- return 0; ++out: ++ free(tuninfo); ++ free(srh); ++ ++ return ret; + } + + struct lwt_x { +-- +1.8.3.1 + diff --git a/SOURCES/0032-rdma-Don-t-pass-garbage-to-rd_check_is_filtered.patch b/SOURCES/0032-rdma-Don-t-pass-garbage-to-rd_check_is_filtered.patch new file mode 100644 index 0000000..090b370 --- /dev/null +++ b/SOURCES/0032-rdma-Don-t-pass-garbage-to-rd_check_is_filtered.patch @@ -0,0 +1,59 @@ +From 97d754cf27798bc19ccdf8ce6d6b5b878e4d2c25 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 12:24:30 +0200 +Subject: [PATCH] rdma: Don't pass garbage to rd_check_is_filtered() + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1602555 +Upstream Status: iproute2.git commit cdefe1d8e472f + +commit cdefe1d8e472f3a69d5f54d90092b9b50961bf91 +Author: Phil Sutter +Date: Thu Oct 18 14:35:50 2018 +0200 + + rdma: Don't pass garbage to rd_check_is_filtered() + + Variables 'src_port' and 'dst_port' are initialized only if attributes + RDMA_NLDEV_ATTR_RES_SRC_ADDR or RDMA_NLDEV_ATTR_RES_DST_ADDR are + present. Make sure to pass them over to rd_check_is_filtered() only if + that is the case. + + Fixes: 9a362cc71a455 ("rdma: Add CM_ID resource tracking information") + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + rdma/res.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/rdma/res.c b/rdma/res.c +index 074b992..0d8c1c3 100644 +--- a/rdma/res.c ++++ b/rdma/res.c +@@ -621,6 +621,8 @@ static int res_cm_id_parse_cb(const struct nlmsghdr *nlh, void *data) + if (rd_check_is_string_filtered(rd, "src-addr", + src_addr_str)) + continue; ++ if (rd_check_is_filtered(rd, "src-port", src_port)) ++ continue; + } + + if (nla_line[RDMA_NLDEV_ATTR_RES_DST_ADDR]) { +@@ -630,14 +632,10 @@ static int res_cm_id_parse_cb(const struct nlmsghdr *nlh, void *data) + if (rd_check_is_string_filtered(rd, "dst-addr", + dst_addr_str)) + continue; ++ if (rd_check_is_filtered(rd, "dst-port", dst_port)) ++ continue; + } + +- if (rd_check_is_filtered(rd, "src-port", src_port)) +- continue; +- +- if (rd_check_is_filtered(rd, "dst-port", dst_port)) +- continue; +- + if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) { + pid = mnl_attr_get_u32( + nla_line[RDMA_NLDEV_ATTR_RES_PID]); +-- +1.8.3.1 + diff --git a/SOURCES/0033-ip-route-Fix-parse_encap_seg6-srh-parsing.patch b/SOURCES/0033-ip-route-Fix-parse_encap_seg6-srh-parsing.patch new file mode 100644 index 0000000..b30a47a --- /dev/null +++ b/SOURCES/0033-ip-route-Fix-parse_encap_seg6-srh-parsing.patch @@ -0,0 +1,41 @@ +From ffe33dd788af80a6645ab62b1df8e8f215b8902a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 12:24:30 +0200 +Subject: [PATCH] ip-route: Fix parse_encap_seg6() srh parsing + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1602555 +Upstream Status: iproute2.git commit 3b5c5ef0a75a9 + +commit 3b5c5ef0a75a9f685e78cd25da78706b5077bd83 +Author: Phil Sutter +Date: Thu Oct 18 15:44:14 2018 +0200 + + ip-route: Fix parse_encap_seg6() srh parsing + + In case caller did not specify 'segs' parameter, parse_srh() would read + garbage while iterating over 'segbuf'. Avoid this by initializing + 'segbuf' to an empty string. + + Fixes: e8493916a8ede ("iproute: add support for SR-IPv6 lwtunnel encapsulation") + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + ip/iproute_lwtunnel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c +index 85045d4..4ebfaa7 100644 +--- a/ip/iproute_lwtunnel.c ++++ b/ip/iproute_lwtunnel.c +@@ -494,7 +494,7 @@ static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp, + struct seg6_iptunnel_encap *tuninfo; + struct ipv6_sr_hdr *srh; + char **argv = *argvp; +- char segbuf[1024]; ++ char segbuf[1024] = ""; + int argc = *argcp; + int encap = -1; + __u32 hmac = 0; +-- +1.8.3.1 + diff --git a/SOURCES/0034-tipc-Drop-unused-variable-genl.patch b/SOURCES/0034-tipc-Drop-unused-variable-genl.patch new file mode 100644 index 0000000..78713c4 --- /dev/null +++ b/SOURCES/0034-tipc-Drop-unused-variable-genl.patch @@ -0,0 +1,76 @@ +From 03b579ec713d0a1062b16d0eab64d3189f6e325a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 12:24:30 +0200 +Subject: [PATCH] tipc: Drop unused variable 'genl' + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1602555 +Upstream Status: iproute2.git commit 8d05f33a381a2 + +commit 8d05f33a381a22572341204c667aafca02aabcca +Author: Phil Sutter +Date: Thu Oct 18 15:48:09 2018 +0200 + + tipc: Drop unused variable 'genl' + + Although initialized by call to libmnl, the variable is used only in a + call to sizeof(). Drop it and call sizeof with its type instead. + + Fixes: f043759dd4928 ("tipc: add new TIPC configuration tool") + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + tipc/node.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/tipc/node.c b/tipc/node.c +index 0fa1064..2fec675 100644 +--- a/tipc/node.c ++++ b/tipc/node.c +@@ -26,13 +26,12 @@ + + static int node_list_cb(const struct nlmsghdr *nlh, void *data) + { +- struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + struct nlattr *info[TIPC_NLA_MAX + 1] = {}; + struct nlattr *attrs[TIPC_NLA_NODE_MAX + 1] = {}; + char str[33] = {}; + uint32_t addr; + +- mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); ++ mnl_attr_parse(nlh, sizeof(struct genlmsghdr), parse_attrs, info); + if (!info[TIPC_NLA_NODE]) + return MNL_CB_ERROR; + +@@ -160,7 +159,6 @@ static int cmd_node_set_nodeid(struct nlmsghdr *nlh, const struct cmd *cmd, + + static int nodeid_get_cb(const struct nlmsghdr *nlh, void *data) + { +- struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + struct nlattr *info[TIPC_NLA_MAX + 1] = {}; + struct nlattr *attrs[TIPC_NLA_NET_MAX + 1] = {}; + char str[33] = {0,}; +@@ -168,7 +166,7 @@ static int nodeid_get_cb(const struct nlmsghdr *nlh, void *data) + uint64_t *w0 = (uint64_t *) &id[0]; + uint64_t *w1 = (uint64_t *) &id[8]; + +- mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); ++ mnl_attr_parse(nlh, sizeof(struct genlmsghdr), parse_attrs, info); + if (!info[TIPC_NLA_NET]) + return MNL_CB_ERROR; + +@@ -207,11 +205,10 @@ static int cmd_node_get_nodeid(struct nlmsghdr *nlh, const struct cmd *cmd, + + static int netid_get_cb(const struct nlmsghdr *nlh, void *data) + { +- struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + struct nlattr *info[TIPC_NLA_MAX + 1] = {}; + struct nlattr *attrs[TIPC_NLA_NET_MAX + 1] = {}; + +- mnl_attr_parse(nlh, sizeof(*genl), parse_attrs, info); ++ mnl_attr_parse(nlh, sizeof(struct genlmsghdr), parse_attrs, info); + if (!info[TIPC_NLA_NET]) + return MNL_CB_ERROR; + +-- +1.8.3.1 + diff --git a/SOURCES/0035-tc-Remove-pointless-assignments-in-batch.patch b/SOURCES/0035-tc-Remove-pointless-assignments-in-batch.patch new file mode 100644 index 0000000..b352d2e --- /dev/null +++ b/SOURCES/0035-tc-Remove-pointless-assignments-in-batch.patch @@ -0,0 +1,60 @@ +From 0b59d9f255a9b1c366fe5da3206d5089167277d4 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 12:24:30 +0200 +Subject: [PATCH] tc: Remove pointless assignments in batch() + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1602555 +Upstream Status: iproute2.git commit 6358bbc381c6e + +commit 6358bbc381c6e38465838370bcbbdeb77ec3565a +Author: Phil Sutter +Date: Thu Oct 18 15:48:48 2018 +0200 + + tc: Remove pointless assignments in batch() + + All these assignments are later overwritten without reading in between, + so just drop them. + + Fixes: 485d0c6001c4a ("tc: Add batchsize feature for filter and actions") + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + tc/tc.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/tc/tc.c b/tc/tc.c +index 2e97f2b..88e22ba 100644 +--- a/tc/tc.c ++++ b/tc/tc.c +@@ -322,11 +322,11 @@ static int batch(const char *name) + struct batch_buf *head = NULL, *tail = NULL, *buf_pool = NULL; + char *largv[100], *largv_next[100]; + char *line, *line_next = NULL; +- bool bs_enabled_next = false; + bool bs_enabled = false; + bool lastline = false; + int largc, largc_next; + bool bs_enabled_saved; ++ bool bs_enabled_next; + int batchsize = 0; + size_t len = 0; + int ret = 0; +@@ -355,7 +355,6 @@ static int batch(const char *name) + goto Exit; + largc = makeargs(line, largv, 100); + bs_enabled = batchsize_enabled(largc, largv); +- bs_enabled_saved = bs_enabled; + do { + if (getcmdline(&line_next, &len, stdin) == -1) + lastline = true; +@@ -391,7 +390,6 @@ static int batch(const char *name) + len = 0; + bs_enabled_saved = bs_enabled; + bs_enabled = bs_enabled_next; +- bs_enabled_next = false; + + if (largc == 0) { + largc = largc_next; +-- +1.8.3.1 + diff --git a/SOURCES/0036-tc_util-Add-support-for-showing-TCA_STATS_BASIC_HW-s.patch b/SOURCES/0036-tc_util-Add-support-for-showing-TCA_STATS_BASIC_HW-s.patch new file mode 100644 index 0000000..75d7d0c --- /dev/null +++ b/SOURCES/0036-tc_util-Add-support-for-showing-TCA_STATS_BASIC_HW-s.patch @@ -0,0 +1,103 @@ +From 1610b7b240601085ea42848e8d86469a091e560c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 17:01:52 +0200 +Subject: [PATCH] tc_util: Add support for showing TCA_STATS_BASIC_HW + statistics + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1637440 +Upstream Status: iproute2.git commit 5ac138324e31c + +commit 5ac138324e31c75edc65c69cedcf699fb624c113 +Author: Eelco Chaudron +Date: Tue Oct 2 03:27:18 2018 -0400 + + tc_util: Add support for showing TCA_STATS_BASIC_HW statistics + + Add support for showing hardware specific counters to easy + troubleshooting hardware offload. + + $ tc -s filter show dev enp3s0np0 parent ffff: + filter protocol ip pref 1 flower chain 0 + filter protocol ip pref 1 flower chain 0 handle 0x1 + eth_type ipv4 + dst_ip 2.0.0.0 + src_ip 1.0.0.0 + ip_flags nofrag + in_hw + action order 1: mirred (Egress Redirect to device eth1) stolen + index 1 ref 1 bind 1 installed 0 sec used 0 sec + Action statistics: + Sent 534884742 bytes 8915697 pkt (dropped 0, overlimits 0 requeues 0) + Sent software 187542 bytes 4077 pkt + Sent hardware 534697200 bytes 8911620 pkt + backlog 0b 0p requeues 0 + cookie 89173e6a44447001becfd486bda17e29 + + Signed-off-by: Eelco Chaudron + Signed-off-by: David Ahern +--- + tc/tc_util.c | 41 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 41 insertions(+) + +diff --git a/tc/tc_util.c b/tc/tc_util.c +index d757852..5a1bbf2 100644 +--- a/tc/tc_util.c ++++ b/tc/tc_util.c +@@ -800,6 +800,44 @@ void print_tm(FILE *f, const struct tcf_t *tm) + } + } + ++static void print_tcstats_basic_hw(struct rtattr **tbs, char *prefix) ++{ ++ struct gnet_stats_basic bs_hw; ++ ++ if (!tbs[TCA_STATS_BASIC_HW]) ++ return; ++ ++ memcpy(&bs_hw, RTA_DATA(tbs[TCA_STATS_BASIC_HW]), ++ MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC_HW]), sizeof(bs_hw))); ++ ++ if (bs_hw.bytes == 0 && bs_hw.packets == 0) ++ return; ++ ++ if (tbs[TCA_STATS_BASIC]) { ++ struct gnet_stats_basic bs; ++ ++ memcpy(&bs, RTA_DATA(tbs[TCA_STATS_BASIC]), ++ MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]), ++ sizeof(bs))); ++ ++ if (bs.bytes >= bs_hw.bytes && bs.packets >= bs_hw.packets) { ++ print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_string(PRINT_FP, NULL, "%s", prefix); ++ print_lluint(PRINT_ANY, "sw_bytes", ++ "Sent software %llu bytes", ++ bs.bytes - bs_hw.bytes); ++ print_uint(PRINT_ANY, "sw_packets", " %u pkt", ++ bs.packets - bs_hw.packets); ++ } ++ } ++ ++ print_string(PRINT_FP, NULL, "%s", _SL_); ++ print_string(PRINT_FP, NULL, "%s", prefix); ++ print_lluint(PRINT_ANY, "hw_bytes", "Sent hardware %llu bytes", ++ bs_hw.bytes); ++ print_uint(PRINT_ANY, "hw_packets", " %u pkt", bs_hw.packets); ++} ++ + void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtattr **xstats) + { + SPRINT_BUF(b1); +@@ -826,6 +864,9 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat + print_uint(PRINT_ANY, "requeues", " requeues %u) ", q.requeues); + } + ++ if (tbs[TCA_STATS_BASIC_HW]) ++ print_tcstats_basic_hw(tbs, prefix); ++ + if (tbs[TCA_STATS_RATE_EST64]) { + struct gnet_stats_rate_est64 re = {0}; + +-- +1.8.3.1 + diff --git a/SOURCES/0037-Update-kernel-headers.patch b/SOURCES/0037-Update-kernel-headers.patch new file mode 100644 index 0000000..783e937 --- /dev/null +++ b/SOURCES/0037-Update-kernel-headers.patch @@ -0,0 +1,664 @@ +From 94b44c8f431c8d159fee6c067aded7b9c4e71104 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 25 Oct 2018 17:00:00 +0200 +Subject: [PATCH] Update kernel headers + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1637440 +Upstream Status: RHEL-only + +This updates include/uapi/linux to the state of upstream commit +d9c0be4e9795473a73793058674c34d56cdb5eea. +--- + include/uapi/linux/bpf.h | 121 ++++++++++++++++++++++++++++++++++++++++- + include/uapi/linux/btf.h | 2 +- + include/uapi/linux/can.h | 2 +- + include/uapi/linux/gen_stats.h | 1 + + include/uapi/linux/if_addr.h | 1 + + include/uapi/linux/if_arp.h | 18 +++--- + include/uapi/linux/if_link.h | 15 +++++ + include/uapi/linux/if_packet.h | 1 + + include/uapi/linux/in6.h | 1 + + include/uapi/linux/ip.h | 1 + + include/uapi/linux/l2tp.h | 15 ++--- + include/uapi/linux/neighbour.h | 1 + + include/uapi/linux/netconf.h | 1 + + include/uapi/linux/pkt_cls.h | 34 +++++++++++- + include/uapi/linux/pkt_sched.h | 21 ++++++- + include/uapi/linux/rtnetlink.h | 7 +++ + include/uapi/linux/tcp.h | 14 ++++- + include/uapi/linux/xfrm.h | 5 +- + 18 files changed, 235 insertions(+), 26 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index b9a6367..abb7f77 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -75,6 +75,11 @@ struct bpf_lpm_trie_key { + __u8 data[0]; /* Arbitrary size */ + }; + ++struct bpf_cgroup_storage_key { ++ __u64 cgroup_inode_id; /* cgroup inode id */ ++ __u32 attach_type; /* program attach type */ ++}; ++ + /* BPF syscall commands, see bpf(2) man-page for details. */ + enum bpf_cmd { + BPF_MAP_CREATE, +@@ -120,6 +125,8 @@ enum bpf_map_type { + BPF_MAP_TYPE_CPUMAP, + BPF_MAP_TYPE_XSKMAP, + BPF_MAP_TYPE_SOCKHASH, ++ BPF_MAP_TYPE_CGROUP_STORAGE, ++ BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, + }; + + enum bpf_prog_type { +@@ -144,6 +151,8 @@ 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, ++ BPF_PROG_TYPE_FLOW_DISSECTOR, + }; + + enum bpf_attach_type { +@@ -164,6 +173,7 @@ enum bpf_attach_type { + BPF_CGROUP_UDP4_SENDMSG, + BPF_CGROUP_UDP6_SENDMSG, + BPF_LIRC_MODE2, ++ BPF_FLOW_DISSECTOR, + __MAX_BPF_ATTACH_TYPE + }; + +@@ -1371,6 +1381,20 @@ union bpf_attr { + * A 8-byte long non-decreasing number on success, or 0 if the + * socket field is missing inside *skb*. + * ++ * u64 bpf_get_socket_cookie(struct bpf_sock_addr *ctx) ++ * Description ++ * Equivalent to bpf_get_socket_cookie() helper that accepts ++ * *skb*, but gets socket from **struct bpf_sock_addr** contex. ++ * Return ++ * A 8-byte long non-decreasing number. ++ * ++ * u64 bpf_get_socket_cookie(struct bpf_sock_ops *ctx) ++ * Description ++ * Equivalent to bpf_get_socket_cookie() helper that accepts ++ * *skb*, but gets socket from **struct bpf_sock_ops** contex. ++ * Return ++ * A 8-byte long non-decreasing number. ++ * + * u32 bpf_get_socket_uid(struct sk_buff *skb) + * Return + * The owner UID of the socket associated to *skb*. If the socket +@@ -2071,10 +2095,54 @@ 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 + * on the cgroup within which the current task is running. ++ * ++ * void* get_local_storage(void *map, u64 flags) ++ * Description ++ * Get the pointer to the local storage area. ++ * The type and the size of the local storage is defined ++ * by the *map* argument. ++ * The *flags* meaning is specific for each map type, ++ * and has to be 0 for cgroup local storage. ++ * ++ * Depending on the bpf program type, a local storage area ++ * can be shared between multiple instances of the bpf program, ++ * running simultaneously. ++ * ++ * A user should care about the synchronization by himself. ++ * For example, by using the BPF_STX_XADD instruction to alter ++ * 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), \ +@@ -2157,7 +2225,10 @@ union bpf_attr { + FN(rc_repeat), \ + FN(rc_keydown), \ + FN(skb_cgroup_id), \ +- FN(get_current_cgroup_id), ++ FN(get_current_cgroup_id), \ ++ 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 +@@ -2264,6 +2335,7 @@ struct __sk_buff { + /* ... here. */ + + __u32 data_meta; ++ struct bpf_flow_keys *flow_keys; + }; + + struct bpf_tunnel_key { +@@ -2374,6 +2446,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 { +@@ -2685,4 +2781,27 @@ enum bpf_task_fd_type { + BPF_FD_TYPE_URETPROBE, /* filename + offset */ + }; + ++struct bpf_flow_keys { ++ __u16 nhoff; ++ __u16 thoff; ++ __u16 addr_proto; /* ETH_P_* of valid addrs */ ++ __u8 is_frag; ++ __u8 is_first_frag; ++ __u8 is_encap; ++ __u8 ip_proto; ++ __be16 n_proto; ++ __be16 sport; ++ __be16 dport; ++ union { ++ struct { ++ __be32 ipv4_src; ++ __be32 ipv4_dst; ++ }; ++ struct { ++ __u32 ipv6_src[4]; /* in6_addr; network order */ ++ __u32 ipv6_dst[4]; /* in6_addr; network order */ ++ }; ++ }; ++}; ++ + #endif /* __LINUX_BPF_H__ */ +diff --git a/include/uapi/linux/btf.h b/include/uapi/linux/btf.h +index 5dd580a..8d2a8ff 100644 +--- a/include/uapi/linux/btf.h ++++ b/include/uapi/linux/btf.h +@@ -76,7 +76,7 @@ struct btf_type { + */ + #define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24) + #define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16) +-#define BTF_INT_BITS(VAL) ((VAL) & 0x0000ffff) ++#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff) + + /* Attributes stored in the BTF_INT_ENCODING */ + #define BTF_INT_SIGNED (1 << 0) +diff --git a/include/uapi/linux/can.h b/include/uapi/linux/can.h +index 4d1ab8e..9009f0b 100644 +--- a/include/uapi/linux/can.h ++++ b/include/uapi/linux/can.h +@@ -77,7 +77,7 @@ typedef __u32 canid_t; + /* + * Controller Area Network Error Message Frame Mask structure + * +- * bit 0-28 : error class mask (see include/linux/can/error.h) ++ * bit 0-28 : error class mask (see include/uapi/linux/can/error.h) + * bit 29-31 : set to zero + */ + typedef __u32 can_err_mask_t; +diff --git a/include/uapi/linux/gen_stats.h b/include/uapi/linux/gen_stats.h +index 24a861c..065408e 100644 +--- a/include/uapi/linux/gen_stats.h ++++ b/include/uapi/linux/gen_stats.h +@@ -12,6 +12,7 @@ enum { + TCA_STATS_APP, + TCA_STATS_RATE_EST64, + TCA_STATS_PAD, ++ TCA_STATS_BASIC_HW, + __TCA_STATS_MAX, + }; + #define TCA_STATS_MAX (__TCA_STATS_MAX - 1) +diff --git a/include/uapi/linux/if_addr.h b/include/uapi/linux/if_addr.h +index a924606..c4dd87f 100644 +--- a/include/uapi/linux/if_addr.h ++++ b/include/uapi/linux/if_addr.h +@@ -34,6 +34,7 @@ enum { + IFA_MULTICAST, + IFA_FLAGS, + IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */ ++ IFA_TARGET_NETNSID, + __IFA_MAX, + }; + +diff --git a/include/uapi/linux/if_arp.h b/include/uapi/linux/if_arp.h +index cd136a6..dbfbc22 100644 +--- a/include/uapi/linux/if_arp.h ++++ b/include/uapi/linux/if_arp.h +@@ -114,18 +114,18 @@ + + /* ARP ioctl request. */ + struct arpreq { +- struct sockaddr arp_pa; /* protocol address */ +- struct sockaddr arp_ha; /* hardware address */ +- int arp_flags; /* flags */ +- struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ +- char arp_dev[16]; ++ struct sockaddr arp_pa; /* protocol address */ ++ struct sockaddr arp_ha; /* hardware address */ ++ int arp_flags; /* flags */ ++ struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ ++ char arp_dev[IFNAMSIZ]; + }; + + struct arpreq_old { +- struct sockaddr arp_pa; /* protocol address */ +- struct sockaddr arp_ha; /* hardware address */ +- int arp_flags; /* flags */ +- struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ ++ struct sockaddr arp_pa; /* protocol address */ ++ struct sockaddr arp_ha; /* hardware address */ ++ int arp_flags; /* flags */ ++ struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ + }; + + /* ARP Flag values. */ +diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h +index 1c64ed4..9c25460 100644 +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -161,9 +161,12 @@ enum { + IFLA_EVENT, + IFLA_NEW_NETNSID, + IFLA_IF_NETNSID, ++ IFLA_TARGET_NETNSID = IFLA_IF_NETNSID, /* new alias */ + IFLA_CARRIER_UP_COUNT, + IFLA_CARRIER_DOWN_COUNT, + IFLA_NEW_IFINDEX, ++ IFLA_MIN_MTU, ++ IFLA_MAX_MTU, + __IFLA_MAX + }; + +@@ -332,6 +335,7 @@ enum { + IFLA_BRPORT_GROUP_FWD_MASK, + IFLA_BRPORT_NEIGH_SUPPRESS, + IFLA_BRPORT_ISOLATED, ++ IFLA_BRPORT_BACKUP_PORT, + __IFLA_BRPORT_MAX + }; + #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) +@@ -457,6 +461,16 @@ enum { + + #define IFLA_MACSEC_MAX (__IFLA_MACSEC_MAX - 1) + ++/* XFRM section */ ++enum { ++ IFLA_XFRM_UNSPEC, ++ IFLA_XFRM_LINK, ++ IFLA_XFRM_IF_ID, ++ __IFLA_XFRM_MAX ++}; ++ ++#define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1) ++ + enum macsec_validation_type { + MACSEC_VALIDATE_DISABLED = 0, + MACSEC_VALIDATE_CHECK = 1, +@@ -539,6 +553,7 @@ enum { + IFLA_GENEVE_UDP_ZERO_CSUM6_TX, + IFLA_GENEVE_UDP_ZERO_CSUM6_RX, + IFLA_GENEVE_LABEL, ++ IFLA_GENEVE_TTL_INHERIT, + __IFLA_GENEVE_MAX + }; + #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) +diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h +index 67b61d9..467b654 100644 +--- a/include/uapi/linux/if_packet.h ++++ b/include/uapi/linux/if_packet.h +@@ -57,6 +57,7 @@ struct sockaddr_ll { + #define PACKET_QDISC_BYPASS 20 + #define PACKET_ROLLOVER_STATS 21 + #define PACKET_FANOUT_DATA 22 ++#define PACKET_IGNORE_OUTGOING 23 + + #define PACKET_FANOUT_HASH 0 + #define PACKET_FANOUT_LB 1 +diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h +index 409bb3f..2bb132a 100644 +--- a/include/uapi/linux/in6.h ++++ b/include/uapi/linux/in6.h +@@ -177,6 +177,7 @@ struct in6_flowlabel_req { + #define IPV6_V6ONLY 26 + #define IPV6_JOIN_ANYCAST 27 + #define IPV6_LEAVE_ANYCAST 28 ++#define IPV6_MULTICAST_ALL 29 + + /* IPV6_MTU_DISCOVER values */ + #define IPV6_PMTUDISC_DONT 0 +diff --git a/include/uapi/linux/ip.h b/include/uapi/linux/ip.h +index 883fd33..f4ecd2f 100644 +--- a/include/uapi/linux/ip.h ++++ b/include/uapi/linux/ip.h +@@ -168,6 +168,7 @@ enum + IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN, + IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, + IPV4_DEVCONF_DROP_GRATUITOUS_ARP, ++ IPV4_DEVCONF_BC_FORWARDING, + __IPV4_DEVCONF_MAX + }; + +diff --git a/include/uapi/linux/l2tp.h b/include/uapi/linux/l2tp.h +index 1fe52a7..131c3a2 100644 +--- a/include/uapi/linux/l2tp.h ++++ b/include/uapi/linux/l2tp.h +@@ -60,14 +60,14 @@ struct sockaddr_l2tpip6 { + /* + * Commands. + * Valid TLVs of each command are:- +- * TUNNEL_CREATE - CONN_ID, pw_type, netns, ifname, ipinfo, udpinfo, udpcsum, vlanid ++ * TUNNEL_CREATE - CONN_ID, pw_type, netns, ifname, ipinfo, udpinfo, udpcsum + * TUNNEL_DELETE - CONN_ID + * TUNNEL_MODIFY - CONN_ID, udpcsum + * TUNNEL_GETSTATS - CONN_ID, (stats) + * TUNNEL_GET - CONN_ID, (...) +- * SESSION_CREATE - SESSION_ID, PW_TYPE, data_seq, cookie, peer_cookie, l2spec ++ * SESSION_CREATE - SESSION_ID, PW_TYPE, cookie, peer_cookie, l2spec + * SESSION_DELETE - SESSION_ID +- * SESSION_MODIFY - SESSION_ID, data_seq ++ * SESSION_MODIFY - SESSION_ID + * SESSION_GET - SESSION_ID, (...) + * SESSION_GETSTATS - SESSION_ID, (stats) + * +@@ -95,7 +95,7 @@ enum { + L2TP_ATTR_PW_TYPE, /* u16, enum l2tp_pwtype */ + L2TP_ATTR_ENCAP_TYPE, /* u16, enum l2tp_encap_type */ + L2TP_ATTR_OFFSET, /* u16 (not used) */ +- L2TP_ATTR_DATA_SEQ, /* u16 */ ++ L2TP_ATTR_DATA_SEQ, /* u16 (not used) */ + L2TP_ATTR_L2SPEC_TYPE, /* u8, enum l2tp_l2spec_type */ + L2TP_ATTR_L2SPEC_LEN, /* u8 (not used) */ + L2TP_ATTR_PROTO_VERSION, /* u8 */ +@@ -105,7 +105,7 @@ enum { + L2TP_ATTR_SESSION_ID, /* u32 */ + L2TP_ATTR_PEER_SESSION_ID, /* u32 */ + L2TP_ATTR_UDP_CSUM, /* u8 */ +- L2TP_ATTR_VLAN_ID, /* u16 */ ++ L2TP_ATTR_VLAN_ID, /* u16 (not used) */ + L2TP_ATTR_COOKIE, /* 0, 4 or 8 bytes */ + L2TP_ATTR_PEER_COOKIE, /* 0, 4 or 8 bytes */ + L2TP_ATTR_DEBUG, /* u32, enum l2tp_debug_flags */ +@@ -119,8 +119,8 @@ enum { + L2TP_ATTR_IP_DADDR, /* u32 */ + L2TP_ATTR_UDP_SPORT, /* u16 */ + L2TP_ATTR_UDP_DPORT, /* u16 */ +- L2TP_ATTR_MTU, /* u16 */ +- L2TP_ATTR_MRU, /* u16 */ ++ L2TP_ATTR_MTU, /* u16 (not used) */ ++ L2TP_ATTR_MRU, /* u16 (not used) */ + L2TP_ATTR_STATS, /* nested */ + L2TP_ATTR_IP6_SADDR, /* struct in6_addr */ + L2TP_ATTR_IP6_DADDR, /* struct in6_addr */ +@@ -169,6 +169,7 @@ enum l2tp_encap_type { + L2TP_ENCAPTYPE_IP, + }; + ++/* For L2TP_ATTR_DATA_SEQ. Unused. */ + enum l2tp_seqmode { + L2TP_SEQ_NONE = 0, + L2TP_SEQ_IP = 1, +diff --git a/include/uapi/linux/neighbour.h b/include/uapi/linux/neighbour.h +index 904db61..9981554 100644 +--- a/include/uapi/linux/neighbour.h ++++ b/include/uapi/linux/neighbour.h +@@ -43,6 +43,7 @@ enum { + #define NTF_PROXY 0x08 /* == ATF_PUBL */ + #define NTF_EXT_LEARNED 0x10 + #define NTF_OFFLOADED 0x20 ++#define NTF_STICKY 0x40 + #define NTF_ROUTER 0x80 + + /* +diff --git a/include/uapi/linux/netconf.h b/include/uapi/linux/netconf.h +index 86ac1eb..229e885 100644 +--- a/include/uapi/linux/netconf.h ++++ b/include/uapi/linux/netconf.h +@@ -18,6 +18,7 @@ enum { + NETCONFA_PROXY_NEIGH, + NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN, + NETCONFA_INPUT, ++ NETCONFA_BC_FORWARDING, + __NETCONFA_MAX + }; + #define NETCONFA_MAX (__NETCONFA_MAX - 1) +diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h +index b451225..401d0c1 100644 +--- a/include/uapi/linux/pkt_cls.h ++++ b/include/uapi/linux/pkt_cls.h +@@ -45,6 +45,7 @@ enum { + * the skb and act like everything + * is alright. + */ ++#define TC_ACT_VALUE_MAX TC_ACT_TRAP + + /* There is a special kind of actions called "extended actions", + * which need a value parameter. These have a local opcode located in +@@ -55,11 +56,12 @@ enum { + #define __TC_ACT_EXT_SHIFT 28 + #define __TC_ACT_EXT(local) ((local) << __TC_ACT_EXT_SHIFT) + #define TC_ACT_EXT_VAL_MASK ((1 << __TC_ACT_EXT_SHIFT) - 1) +-#define TC_ACT_EXT_CMP(combined, opcode) \ +- (((combined) & (~TC_ACT_EXT_VAL_MASK)) == opcode) ++#define TC_ACT_EXT_OPCODE(combined) ((combined) & (~TC_ACT_EXT_VAL_MASK)) ++#define TC_ACT_EXT_CMP(combined, opcode) (TC_ACT_EXT_OPCODE(combined) == opcode) + + #define TC_ACT_JUMP __TC_ACT_EXT(1) + #define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2) ++#define TC_ACT_EXT_OPCODE_MAX TC_ACT_GOTO_CHAIN + + /* Action type identifiers*/ + enum { +@@ -478,12 +480,40 @@ enum { + TCA_FLOWER_KEY_ENC_IP_TTL, /* u8 */ + TCA_FLOWER_KEY_ENC_IP_TTL_MASK, /* u8 */ + ++ TCA_FLOWER_KEY_ENC_OPTS, ++ TCA_FLOWER_KEY_ENC_OPTS_MASK, ++ ++ TCA_FLOWER_IN_HW_COUNT, ++ + __TCA_FLOWER_MAX, + }; + + #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1) + + enum { ++ TCA_FLOWER_KEY_ENC_OPTS_UNSPEC, ++ TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested ++ * TCA_FLOWER_KEY_ENC_OPT_GENEVE_ ++ * attributes ++ */ ++ __TCA_FLOWER_KEY_ENC_OPTS_MAX, ++}; ++ ++#define TCA_FLOWER_KEY_ENC_OPTS_MAX (__TCA_FLOWER_KEY_ENC_OPTS_MAX - 1) ++ ++enum { ++ TCA_FLOWER_KEY_ENC_OPT_GENEVE_UNSPEC, ++ TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS, /* u16 */ ++ TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE, /* u8 */ ++ TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA, /* 4 to 128 bytes */ ++ ++ __TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX, ++}; ++ ++#define TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX \ ++ (__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1) ++ ++enum { + TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0), + TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1), + }; +diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h +index d9cc9dc..e9b7244 100644 +--- a/include/uapi/linux/pkt_sched.h ++++ b/include/uapi/linux/pkt_sched.h +@@ -124,6 +124,21 @@ struct tc_fifo_qopt { + __u32 limit; /* Queue length: bytes for bfifo, packets for pfifo */ + }; + ++/* SKBPRIO section */ ++ ++/* ++ * Priorities go from zero to (SKBPRIO_MAX_PRIORITY - 1). ++ * SKBPRIO_MAX_PRIORITY should be at least 64 in order for skbprio to be able ++ * to map one to one the DS field of IPV4 and IPV6 headers. ++ * Memory allocation grows linearly with SKBPRIO_MAX_PRIORITY. ++ */ ++ ++#define SKBPRIO_MAX_PRIORITY 64 ++ ++struct tc_skbprio_qopt { ++ __u32 limit; /* Queue length in packets. */ ++}; ++ + /* PRIO section */ + + #define TCQ_PRIO_BANDS 16 +@@ -380,9 +395,9 @@ enum { + struct tc_htb_xstats { + __u32 lends; + __u32 borrows; +- __u32 giants; /* too big packets (rate will not be accurate) */ +- __u32 tokens; +- __u32 ctokens; ++ __u32 giants; /* unused since 'Make HTB scheduler work with TSO.' */ ++ __s32 tokens; ++ __s32 ctokens; + }; + + /* HFSC section */ +diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h +index c3a7d8e..8c1d600 100644 +--- a/include/uapi/linux/rtnetlink.h ++++ b/include/uapi/linux/rtnetlink.h +@@ -150,6 +150,13 @@ enum { + RTM_NEWCACHEREPORT = 96, + #define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT + ++ RTM_NEWCHAIN = 100, ++#define RTM_NEWCHAIN RTM_NEWCHAIN ++ RTM_DELCHAIN, ++#define RTM_DELCHAIN RTM_DELCHAIN ++ RTM_GETCHAIN, ++#define RTM_GETCHAIN RTM_GETCHAIN ++ + __RTM_MAX, + #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) + }; +diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h +index 2e766cf..6ec7766 100644 +--- a/include/uapi/linux/tcp.h ++++ b/include/uapi/linux/tcp.h +@@ -127,6 +127,10 @@ enum { + + #define TCP_CM_INQ TCP_INQ + ++#define TCP_REPAIR_ON 1 ++#define TCP_REPAIR_OFF 0 ++#define TCP_REPAIR_OFF_NO_WP -1 /* Turn off without window probes */ ++ + struct tcp_repair_opt { + __u32 opt_code; + __u32 opt_val; +@@ -231,6 +235,11 @@ struct tcp_info { + + __u32 tcpi_delivered; + __u32 tcpi_delivered_ce; ++ ++ __u64 tcpi_bytes_sent; /* RFC4898 tcpEStatsPerfHCDataOctetsOut */ ++ __u64 tcpi_bytes_retrans; /* RFC4898 tcpEStatsPerfOctetsRetrans */ ++ __u32 tcpi_dsack_dups; /* RFC4898 tcpEStatsStackDSACKDups */ ++ __u32 tcpi_reord_seen; /* reordering events seen */ + }; + + /* netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */ +@@ -253,7 +262,10 @@ enum { + TCP_NLA_SND_SSTHRESH, /* Slow start size threshold */ + TCP_NLA_DELIVERED, /* Data pkts delivered incl. out-of-order */ + TCP_NLA_DELIVERED_CE, /* Like above but only ones w/ CE marks */ +- ++ TCP_NLA_BYTES_SENT, /* Data bytes sent including retransmission */ ++ TCP_NLA_BYTES_RETRANS, /* Data bytes retransmitted */ ++ TCP_NLA_DSACK_DUPS, /* DSACK blocks received */ ++ TCP_NLA_REORD_SEEN, /* reordering events seen */ + }; + + /* for TCP_MD5SIG socket option */ +diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h +index 93fb192..5cdda9d 100644 +--- a/include/uapi/linux/xfrm.h ++++ b/include/uapi/linux/xfrm.h +@@ -305,9 +305,12 @@ enum xfrm_attr_type_t { + XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */ + XFRMA_PAD, + XFRMA_OFFLOAD_DEV, /* struct xfrm_state_offload */ +- XFRMA_OUTPUT_MARK, /* __u32 */ ++ XFRMA_SET_MARK, /* __u32 */ ++ XFRMA_SET_MARK_MASK, /* __u32 */ ++ XFRMA_IF_ID, /* __u32 */ + __XFRMA_MAX + ++#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */ + #define XFRMA_MAX (__XFRMA_MAX - 1) + }; + +-- +1.8.3.1 + diff --git a/SOURCES/0038-man-ip-route.8-Document-nexthop-limit.patch b/SOURCES/0038-man-ip-route.8-Document-nexthop-limit.patch new file mode 100644 index 0000000..8c64720 --- /dev/null +++ b/SOURCES/0038-man-ip-route.8-Document-nexthop-limit.patch @@ -0,0 +1,46 @@ +From b99d3fd8b5a7dd140a2b4c7a7e70aea7478634f7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 26 Nov 2018 19:11:55 +0100 +Subject: [PATCH] man: ip-route.8: Document nexthop limit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1625358 +Upstream Status: iproute2.git commit 6cd959bb125c5 + +commit 6cd959bb125c50a04ab6671645fa38c5b07426f4 +Author: Phil Sutter +Date: Tue Nov 13 16:55:13 2018 +0100 + + man: ip-route.8: Document nexthop limit + + Add a note to 'nexthop' description stating the maximum number of + nexthops per command and pointing at 'append' command as a workaround. + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + man/man8/ip-route.8.in | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in +index b21a847..e464353 100644 +--- a/man/man8/ip-route.8.in ++++ b/man/man8/ip-route.8.in +@@ -589,6 +589,15 @@ argument lists: + route reflecting its relative bandwidth or quality. + .in -8 + ++The internal buffer used in iproute2 limits the maximum number of nexthops that ++may be specified in one go. If only ++.I ADDRESS ++is given, the current buffer size allows for 144 IPv6 nexthops and 253 IPv4 ++ones. For IPv4, this effectively limits the number of nexthops possible per ++route. With IPv6, further nexthops may be appended to the same route via ++.B "ip route append" ++command. ++ + .TP + .BI scope " SCOPE_VAL" + the scope of the destinations covered by the route prefix. +-- +1.8.3.1 + diff --git a/SOURCES/0039-ip-route-Fix-nexthop-encap-parsing.patch b/SOURCES/0039-ip-route-Fix-nexthop-encap-parsing.patch new file mode 100644 index 0000000..efe5f79 --- /dev/null +++ b/SOURCES/0039-ip-route-Fix-nexthop-encap-parsing.patch @@ -0,0 +1,101 @@ +From 06ce7afb4135de6ed92a286793cba5129f17f614 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 26 Nov 2018 19:11:55 +0100 +Subject: [PATCH] ip-route: Fix nexthop encap parsing + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1625358 +Upstream Status: iproute2.git commit 05d978e0850a6 + +commit 05d978e0850a6a3bae1e6c5392d82f7b1496f86a +Author: Phil Sutter +Date: Tue Nov 13 13:39:04 2018 +0100 + + ip-route: Fix nexthop encap parsing + + When parsing nexthop parameters, a buffer of 4k bytes is provided. Yet, + in lwt_parse_encap() and some functions called by it, buffer size was + assumed to be 1k despite the actual size was provided. This led to + spurious buffer size errors if the buffer was filled by previous nexthop + parameters to exceed that 1k boundary. + + Fixes: 1e5293056a02c ("lwtunnel: Add encapsulation support to ip route") + Fixes: 5866bddd9aa9e ("ila: Add support for ILA lwtunnels") + Fixes: ed67f83806538 ("ila: Support for checksum neutral translation") + Fixes: 86905c8f057c0 ("ila: support for configuring identifier and hook types") + Fixes: b15f440e78373 ("lwt: BPF support for LWT") + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + ip/iproute_lwtunnel.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c +index 4ebfaa7..388cd19 100644 +--- a/ip/iproute_lwtunnel.c ++++ b/ip/iproute_lwtunnel.c +@@ -851,7 +851,7 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, + + argc--; argv++; + +- if (rta_addattr64(rta, 1024, ILA_ATTR_LOCATOR, locator)) ++ if (rta_addattr64(rta, len, ILA_ATTR_LOCATOR, locator)) + return -1; + + while (argc > 0) { +@@ -865,7 +865,7 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, + invarg("\"csum-mode\" value is invalid\n", + *argv); + +- ret = rta_addattr8(rta, 1024, ILA_ATTR_CSUM_MODE, ++ ret = rta_addattr8(rta, len, ILA_ATTR_CSUM_MODE, + (__u8)csum_mode); + + argc--; argv++; +@@ -879,7 +879,7 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, + invarg("\"ident-type\" value is invalid\n", + *argv); + +- ret = rta_addattr8(rta, 1024, ILA_ATTR_IDENT_TYPE, ++ ret = rta_addattr8(rta, len, ILA_ATTR_IDENT_TYPE, + (__u8)ident_type); + + argc--; argv++; +@@ -893,7 +893,7 @@ static int parse_encap_ila(struct rtattr *rta, size_t len, + invarg("\"hook-type\" value is invalid\n", + *argv); + +- ret = rta_addattr8(rta, 1024, ILA_ATTR_HOOK_TYPE, ++ ret = rta_addattr8(rta, len, ILA_ATTR_HOOK_TYPE, + (__u8)hook_type); + + argc--; argv++; +@@ -1016,7 +1016,7 @@ static int parse_encap_bpf(struct rtattr *rta, size_t len, int *argcp, + if (get_unsigned(&headroom, *argv, 0) || headroom == 0) + invarg("headroom is invalid\n", *argv); + if (!headroom_set) +- rta_addattr32(rta, 1024, LWT_BPF_XMIT_HEADROOM, ++ rta_addattr32(rta, len, LWT_BPF_XMIT_HEADROOM, + headroom); + headroom_set = 1; + } else if (strcmp(*argv, "help") == 0) { +@@ -1057,7 +1057,7 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) + exit(-1); + } + +- nest = rta_nest(rta, 1024, RTA_ENCAP); ++ nest = rta_nest(rta, len, RTA_ENCAP); + switch (type) { + case LWTUNNEL_ENCAP_MPLS: + ret = parse_encap_mpls(rta, len, &argc, &argv); +@@ -1090,7 +1090,7 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) + + rta_nest_end(rta, nest); + +- ret = rta_addattr16(rta, 1024, RTA_ENCAP_TYPE, type); ++ ret = rta_addattr16(rta, len, RTA_ENCAP_TYPE, type); + + *argcp = argc; + *argvp = argv; +-- +1.8.3.1 + diff --git a/SOURCES/0040-man-rdma-Add-reference-to-rdma-resource.8.patch b/SOURCES/0040-man-rdma-Add-reference-to-rdma-resource.8.patch new file mode 100644 index 0000000..3b5b1f4 --- /dev/null +++ b/SOURCES/0040-man-rdma-Add-reference-to-rdma-resource.8.patch @@ -0,0 +1,64 @@ +From d2662aea40d63db11a38dc8bcbc354eafe280b8a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 11 Dec 2018 15:03:12 +0100 +Subject: [PATCH] man: rdma: Add reference to rdma-resource.8 + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1610334 +Upstream Status: iproute2.git commit b2ec8f431402f + +commit b2ec8f431402f621ed0a2435d895df55eb1354af +Author: Phil Sutter +Date: Mon Nov 26 18:58:31 2018 +0100 + + man: rdma: Add reference to rdma-resource.8 + + All rdma-related man pages list each other in SEE ALSO section, only + rdma-resource.8 is missing. Add it for the sake of consistency. + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + man/man8/rdma-dev.8 | 1 + + man/man8/rdma-link.8 | 1 + + man/man8/rdma.8 | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/man/man8/rdma-dev.8 b/man/man8/rdma-dev.8 +index 461681b..b7abfe1 100644 +--- a/man/man8/rdma-dev.8 ++++ b/man/man8/rdma-dev.8 +@@ -49,6 +49,7 @@ Shows the state of specified RDMA device. + .SH SEE ALSO + .BR rdma (8), + .BR rdma-link (8), ++.BR rdma-resource (8), + .br + + .SH AUTHOR +diff --git a/man/man8/rdma-link.8 b/man/man8/rdma-link.8 +index 97dd8bb..bddf347 100644 +--- a/man/man8/rdma-link.8 ++++ b/man/man8/rdma-link.8 +@@ -49,6 +49,7 @@ Shows the state of specified rdma link. + .SH SEE ALSO + .BR rdma (8), + .BR rdma-dev (8), ++.BR rdma-resource (8), + .br + + .SH AUTHOR +diff --git a/man/man8/rdma.8 b/man/man8/rdma.8 +index 12aa149..b2b5aef 100644 +--- a/man/man8/rdma.8 ++++ b/man/man8/rdma.8 +@@ -106,6 +106,7 @@ Exit status is 0 if command was successful or a positive integer upon failure. + .SH SEE ALSO + .BR rdma-dev (8), + .BR rdma-link (8), ++.BR rdma-resource (8), + .br + + .SH REPORTING BUGS +-- +1.8.3.1 + diff --git a/SOURCES/0041-iplink-fix-incorrect-any-address-handling-for-ip-tun.patch b/SOURCES/0041-iplink-fix-incorrect-any-address-handling-for-ip-tun.patch new file mode 100644 index 0000000..47684a7 --- /dev/null +++ b/SOURCES/0041-iplink-fix-incorrect-any-address-handling-for-ip-tun.patch @@ -0,0 +1,144 @@ +From 6549ac61c997af9a96d13cb4ae94d1a7b1993762 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 18 Dec 2018 17:34:35 +0100 +Subject: [PATCH] iplink: fix incorrect any address handling for ip tunnels + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1626304 +Upstream Status: iproute2.git commit fa1e658e84ab2 + +commit fa1e658e84ab267bb98955e44774831bb36f3861 +Author: Hangbin Liu +Date: Tue Sep 18 17:48:40 2018 +0800 + + iplink: fix incorrect any address handling for ip tunnels + + After commit d42c7891d26e4 ("utils: Do not reset family for default, any, + all addresses"), when call get_addr() for any/all addresses, we will set + addr->flags to ADDRTYPE_INET_UNSPEC if family is AF_INET/AF_INET6, which + makes is_addrtype_inet() checking passed and assigns incorrect address + to kernel. The ip link cmd will return error like: + + ]# ip link add ipip1 type ipip local any remote 1.1.1.1 + RTNETLINK answers: Numerical result out of range + + Fix it by using is_addrtype_inet_not_unspec() to avoid unspec addresses. + + geneve, vxlan are not affected as they use AF_UNSPEC family when call + get_addr() + + Reported-by: Jianlin Shi + Fixes: d42c7891d26e4 ("utils: Do not reset family for default, any, all addresses") + Signed-off-by: Hangbin Liu + Signed-off-by: Stephen Hemminger +--- + ip/link_gre.c | 4 ++-- + ip/link_gre6.c | 4 ++-- + ip/link_ip6tnl.c | 4 ++-- + ip/link_iptnl.c | 4 ++-- + ip/link_vti.c | 4 ++-- + ip/link_vti6.c | 4 ++-- + 6 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/ip/link_gre.c b/ip/link_gre.c +index ede761b..1ee7ee1 100644 +--- a/ip/link_gre.c ++++ b/ip/link_gre.c +@@ -395,9 +395,9 @@ get_failed: + addattr32(n, 1024, IFLA_GRE_OKEY, okey); + addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2); + addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2); +- if (is_addrtype_inet(&saddr)) ++ if (is_addrtype_inet_not_unspec(&saddr)) + addattr_l(n, 1024, IFLA_GRE_LOCAL, saddr.data, saddr.bytelen); +- if (is_addrtype_inet(&daddr)) ++ if (is_addrtype_inet_not_unspec(&daddr)) + addattr_l(n, 1024, IFLA_GRE_REMOTE, daddr.data, daddr.bytelen); + addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1); + if (ignore_df) +diff --git a/ip/link_gre6.c b/ip/link_gre6.c +index 181b2ea..20f9305 100644 +--- a/ip/link_gre6.c ++++ b/ip/link_gre6.c +@@ -424,9 +424,9 @@ get_failed: + addattr32(n, 1024, IFLA_GRE_OKEY, okey); + addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2); + addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2); +- if (is_addrtype_inet(&saddr)) ++ if (is_addrtype_inet_not_unspec(&saddr)) + addattr_l(n, 1024, IFLA_GRE_LOCAL, saddr.data, saddr.bytelen); +- if (is_addrtype_inet(&daddr)) ++ if (is_addrtype_inet_not_unspec(&daddr)) + addattr_l(n, 1024, IFLA_GRE_REMOTE, daddr.data, daddr.bytelen); + if (link) + addattr32(n, 1024, IFLA_GRE_LINK, link); +diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c +index c7fef2e..cfe2c5a 100644 +--- a/ip/link_ip6tnl.c ++++ b/ip/link_ip6tnl.c +@@ -320,11 +320,11 @@ get_failed: + return 0; + } + +- if (is_addrtype_inet(&saddr)) { ++ if (is_addrtype_inet_not_unspec(&saddr)) { + addattr_l(n, 1024, IFLA_IPTUN_LOCAL, + saddr.data, saddr.bytelen); + } +- if (is_addrtype_inet(&daddr)) { ++ if (is_addrtype_inet_not_unspec(&daddr)) { + addattr_l(n, 1024, IFLA_IPTUN_REMOTE, + daddr.data, daddr.bytelen); + } +diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c +index 57f4d0c..7ec1594 100644 +--- a/ip/link_iptnl.c ++++ b/ip/link_iptnl.c +@@ -325,11 +325,11 @@ get_failed: + return 0; + } + +- if (is_addrtype_inet(&saddr)) { ++ if (is_addrtype_inet_not_unspec(&saddr)) { + addattr_l(n, 1024, IFLA_IPTUN_LOCAL, + saddr.data, saddr.bytelen); + } +- if (is_addrtype_inet(&daddr)) { ++ if (is_addrtype_inet_not_unspec(&daddr)) { + addattr_l(n, 1024, IFLA_IPTUN_REMOTE, + daddr.data, daddr.bytelen); + } +diff --git a/ip/link_vti.c b/ip/link_vti.c +index 6196a1c..3fff441 100644 +--- a/ip/link_vti.c ++++ b/ip/link_vti.c +@@ -157,9 +157,9 @@ get_failed: + + addattr32(n, 1024, IFLA_VTI_IKEY, ikey); + addattr32(n, 1024, IFLA_VTI_OKEY, okey); +- if (is_addrtype_inet(&saddr)) ++ if (is_addrtype_inet_not_unspec(&saddr)) + addattr_l(n, 1024, IFLA_VTI_LOCAL, saddr.data, saddr.bytelen); +- if (is_addrtype_inet(&daddr)) ++ if (is_addrtype_inet_not_unspec(&daddr)) + addattr_l(n, 1024, IFLA_VTI_REMOTE, daddr.data, daddr.bytelen); + addattr32(n, 1024, IFLA_VTI_FWMARK, fwmark); + if (link) +diff --git a/ip/link_vti6.c b/ip/link_vti6.c +index 4263615..f5a267a 100644 +--- a/ip/link_vti6.c ++++ b/ip/link_vti6.c +@@ -159,9 +159,9 @@ get_failed: + + addattr32(n, 1024, IFLA_VTI_IKEY, ikey); + addattr32(n, 1024, IFLA_VTI_OKEY, okey); +- if (is_addrtype_inet(&saddr)) ++ if (is_addrtype_inet_not_unspec(&saddr)) + addattr_l(n, 1024, IFLA_VTI_LOCAL, saddr.data, saddr.bytelen); +- if (is_addrtype_inet(&daddr)) ++ if (is_addrtype_inet_not_unspec(&daddr)) + addattr_l(n, 1024, IFLA_VTI_REMOTE, daddr.data, daddr.bytelen); + addattr32(n, 1024, IFLA_VTI_FWMARK, fwmark); + if (link) +-- +1.8.3.1 + diff --git a/SOURCES/0042-l2tp-Fix-printing-of-cookie-and-peer_cookie-values.patch b/SOURCES/0042-l2tp-Fix-printing-of-cookie-and-peer_cookie-values.patch new file mode 100644 index 0000000..51f278d --- /dev/null +++ b/SOURCES/0042-l2tp-Fix-printing-of-cookie-and-peer_cookie-values.patch @@ -0,0 +1,45 @@ +From 7fa3df19e2b907e09b2de902a122daaff114ee0c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 31 Jan 2019 16:48:25 +0100 +Subject: [PATCH] l2tp: Fix printing of cookie and peer_cookie values + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1643805 +Upstream Status: iproute2.git commit b876b7e2b492f + +commit b876b7e2b492fa14ce1f3db6c18bf22b2df10132 +Author: Andrea Claudi +Date: Fri Nov 30 15:34:24 2018 +0100 + + l2tp: Fix printing of cookie and peer_cookie values + + print_cookie() invocations miss %s format specifier. + While at it, align printout to the previous lines. + + Fixes: 98453b65800f7 ("ip/l2tp: add JSON support") + Signed-off-by: Andrea Claudi + Signed-off-by: Stephen Hemminger +--- + ip/ipl2tp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c +index 414a9eb..87c13db 100644 +--- a/ip/ipl2tp.c ++++ b/ip/ipl2tp.c +@@ -311,10 +311,11 @@ static void print_session(struct l2tp_data *data) + print_uint(PRINT_FP, "peer_offset", " peer offset %u\n", 0); + + if (p->cookie_len > 0) +- print_cookie("cookie", "cookie", ++ print_cookie("cookie", " cookie %s", + p->cookie, p->cookie_len); ++ + if (p->peer_cookie_len > 0) +- print_cookie("peer_cookie", "peer cookie", ++ print_cookie("peer_cookie", " peer cookie %s", + p->peer_cookie, p->peer_cookie_len); + + if (p->reorder_timeout != 0) +-- +1.8.3.1 + diff --git a/SOURCES/0043-tc-f_flower-add-geneve-option-match-support-to-flowe.patch b/SOURCES/0043-tc-f_flower-add-geneve-option-match-support-to-flowe.patch new file mode 100644 index 0000000..9086978 --- /dev/null +++ b/SOURCES/0043-tc-f_flower-add-geneve-option-match-support-to-flowe.patch @@ -0,0 +1,403 @@ +From 9dd748cd49d15b7e90a7a65de53d431a2c515c86 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 31 Jan 2019 17:13:07 +0100 +Subject: [PATCH] tc: f_flower: add geneve option match support to flower + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1654761 +Upstream Status: iproute2.git commit 56155d4df86d4 + +commit 56155d4df86d489c4207444c8a90ce4e0e22e49f +Author: Pieter Jansen van Vuuren +Date: Fri Sep 28 16:03:39 2018 +0200 + + tc: f_flower: add geneve option match support to flower + + Allow matching on options in Geneve tunnel headers. + + The options can be described in the form + CLASS:TYPE:DATA/CLASS_MASK:TYPE_MASK:DATA_MASK, where CLASS is + represented as a 16bit hexadecimal value, TYPE as an 8bit + hexadecimal value and DATA as a variable length hexadecimal value. + + e.g. + # ip link add name geneve0 type geneve dstport 0 external + # tc qdisc add dev geneve0 ingress + # tc filter add dev geneve0 protocol ip parent ffff: \ + flower \ + enc_src_ip 10.0.99.192 \ + enc_dst_ip 10.0.99.193 \ + enc_key_id 11 \ + geneve_opts 0102:80:1122334421314151/ffff:ff:ffffffffffffffff \ + ip_proto udp \ + action mirred egress redirect dev eth1 + + Signed-off-by: Pieter Jansen van Vuuren + Signed-off-by: Simon Horman + Signed-off-by: David Ahern +--- + man/man8/tc-flower.8 | 13 ++- + tc/f_flower.c | 282 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 294 insertions(+), 1 deletion(-) + +diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8 +index f917f24..276b527 100644 +--- a/man/man8/tc-flower.8 ++++ b/man/man8/tc-flower.8 +@@ -74,6 +74,8 @@ flower \- flow based traffic control filter + .IR TOS " | " + .B enc_ttl + .IR TTL " | " ++.B geneve_opts ++.IR OPTIONS " | " + .BR ip_flags + .IR IP_FLAGS + .SH DESCRIPTION +@@ -260,6 +262,8 @@ bits is assumed. + .BI enc_tos " NUMBER" + .TQ + .BI enc_ttl " NUMBER" ++.TQ ++.BI geneve_opts " OPTIONS" + Match on IP tunnel metadata. Key id + .I NUMBER + is a 32 bit tunnel key id (e.g. VNI for VXLAN tunnel). +@@ -272,7 +276,14 @@ is a 16 bit UDP dst port. Tos + .I NUMBER + is an 8 bit tos (dscp+ecn) value, ttl + .I NUMBER +-is an 8 bit time-to-live value. ++is an 8 bit time-to-live value. geneve_opts ++.I OPTIONS ++must be a valid list of comma-separated geneve options where each option ++consists of a key optionally followed by a slash and corresponding mask. If ++the masks is missing, \fBtc\fR assumes a full-length match. The options can ++be described in the form CLASS:TYPE:DATA/CLASS_MASK:TYPE_MASK:DATA_MASK, ++where CLASS is represented as a 16bit hexadecimal value, TYPE as an 8bit ++hexadecimal value and DATA as a variable length hexadecimal value. + .TP + .BI ip_flags " IP_FLAGS" + .I IP_FLAGS +diff --git a/tc/f_flower.c b/tc/f_flower.c +index cd102f2..43102c8 100644 +--- a/tc/f_flower.c ++++ b/tc/f_flower.c +@@ -76,6 +76,7 @@ static void explain(void) + " enc_key_id [ KEY-ID ] |\n" + " enc_tos MASKED-IP_TOS |\n" + " enc_ttl MASKED-IP_TTL |\n" ++ " geneve_opts MASKED-OPTIONS |\n" + " ip_flags IP-FLAGS | \n" + " enc_dst_port [ port_number ] }\n" + " FILTERID := X:Y:Z\n" +@@ -580,6 +581,179 @@ static int flower_parse_enc_port(char *str, int type, struct nlmsghdr *n) + return 0; + } + ++static int flower_parse_geneve_opts(char *str, struct nlmsghdr *n) ++{ ++ struct rtattr *nest; ++ char *token; ++ int i, err; ++ ++ nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS_GENEVE); ++ ++ i = 1; ++ token = strsep(&str, ":"); ++ while (token) { ++ switch (i) { ++ case TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS: ++ { ++ __be16 opt_class; ++ ++ if (!strlen(token)) ++ break; ++ err = get_be16(&opt_class, token, 16); ++ if (err) ++ return err; ++ ++ addattr16(n, MAX_MSG, i, opt_class); ++ break; ++ } ++ case TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 16); ++ if (err) ++ return err; ++ ++ addattr8(n, MAX_MSG, i, opt_type); ++ break; ++ } ++ case TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA: ++ { ++ size_t token_len = strlen(token); ++ __u8 *opts; ++ ++ if (!token_len) ++ break; ++ opts = malloc(token_len / 2); ++ if (!opts) ++ return -1; ++ if (hex2mem(token, opts, token_len / 2) < 0) { ++ free(opts); ++ return -1; ++ } ++ addattr_l(n, MAX_MSG, i, opts, token_len / 2); ++ free(opts); ++ ++ break; ++ } ++ default: ++ fprintf(stderr, "Unknown \"geneve_opts\" type\n"); ++ return -1; ++ } ++ ++ token = strsep(&str, ":"); ++ i++; ++ } ++ addattr_nest_end(n, nest); ++ ++ return 0; ++} ++ ++static int flower_parse_enc_opt_part(char *str, struct nlmsghdr *n) ++{ ++ char *token; ++ int err; ++ ++ token = strsep(&str, ","); ++ while (token) { ++ err = flower_parse_geneve_opts(token, n); ++ if (err) ++ return err; ++ ++ token = strsep(&str, ","); ++ } ++ ++ return 0; ++} ++ ++static int flower_check_enc_opt_key(char *key) ++{ ++ int key_len, col_cnt = 0; ++ ++ key_len = strlen(key); ++ while ((key = strchr(key, ':'))) { ++ if (strlen(key) == key_len) ++ return -1; ++ ++ key_len = strlen(key) - 1; ++ col_cnt++; ++ key++; ++ } ++ ++ if (col_cnt != 2 || !key_len) ++ return -1; ++ ++ return 0; ++} ++ ++static int flower_parse_enc_opts(char *str, struct nlmsghdr *n) ++{ ++ char key[XATTR_SIZE_MAX], mask[XATTR_SIZE_MAX]; ++ int data_len, key_len, mask_len, err; ++ char *token, *slash; ++ struct rtattr *nest; ++ ++ key_len = 0; ++ mask_len = 0; ++ token = strsep(&str, ","); ++ while (token) { ++ slash = strchr(token, '/'); ++ if (slash) ++ *slash = '\0'; ++ ++ if ((key_len + strlen(token) > XATTR_SIZE_MAX) || ++ flower_check_enc_opt_key(token)) ++ return -1; ++ ++ strcpy(&key[key_len], token); ++ key_len += strlen(token) + 1; ++ key[key_len - 1] = ','; ++ ++ if (!slash) { ++ /* Pad out mask when not provided */ ++ if (mask_len + strlen(token) > XATTR_SIZE_MAX) ++ return -1; ++ ++ data_len = strlen(rindex(token, ':')); ++ sprintf(&mask[mask_len], "ffff:ff:"); ++ mask_len += 8; ++ memset(&mask[mask_len], 'f', data_len - 1); ++ mask_len += data_len; ++ mask[mask_len - 1] = ','; ++ token = strsep(&str, ","); ++ continue; ++ } ++ ++ if (mask_len + strlen(slash + 1) > XATTR_SIZE_MAX) ++ return -1; ++ ++ strcpy(&mask[mask_len], slash + 1); ++ mask_len += strlen(slash + 1) + 1; ++ mask[mask_len - 1] = ','; ++ ++ *slash = '/'; ++ token = strsep(&str, ","); ++ } ++ key[key_len - 1] = '\0'; ++ mask[mask_len - 1] = '\0'; ++ ++ nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS); ++ err = flower_parse_enc_opt_part(key, n); ++ if (err) ++ return err; ++ addattr_nest_end(n, nest); ++ ++ nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS_MASK); ++ err = flower_parse_enc_opt_part(mask, n); ++ if (err) ++ return err; ++ addattr_nest_end(n, nest); ++ ++ return 0; ++} ++ + static int flower_parse_opt(struct filter_util *qu, char *handle, + int argc, char **argv, struct nlmsghdr *n) + { +@@ -994,6 +1168,13 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + fprintf(stderr, "Illegal \"enc_ttl\"\n"); + return -1; + } ++ } else if (matches(*argv, "geneve_opts") == 0) { ++ NEXT_ARG(); ++ ret = flower_parse_enc_opts(*argv, n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"geneve_opts\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "action") == 0) { + NEXT_ARG(); + ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n); +@@ -1291,6 +1472,105 @@ static void flower_print_key_id(const char *name, struct rtattr *attr) + print_uint(PRINT_ANY, name, namefrm, rta_getattr_be32(attr)); + } + ++static void flower_print_geneve_opts(const char *name, struct rtattr *attr, ++ char *strbuf) ++{ ++ struct rtattr *tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX + 1]; ++ int ii, data_len, offset = 0, slen = 0; ++ struct rtattr *i = RTA_DATA(attr); ++ int rem = RTA_PAYLOAD(attr); ++ __u8 type, data_r[rem]; ++ char data[rem * 2 + 1]; ++ __u16 class; ++ ++ open_json_array(PRINT_JSON, name); ++ while (rem) { ++ parse_rtattr(tb, TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX, i, rem); ++ class = rta_getattr_be16(tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS]); ++ type = rta_getattr_u8(tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE]); ++ data_len = RTA_PAYLOAD(tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA]); ++ hexstring_n2a(RTA_DATA(tb[TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA]), ++ data_len, data, sizeof(data)); ++ hex2mem(data, data_r, data_len); ++ offset += data_len + 20; ++ rem -= data_len + 20; ++ i = RTA_DATA(attr) + offset; ++ ++ open_json_object(NULL); ++ print_uint(PRINT_JSON, "class", NULL, class); ++ print_uint(PRINT_JSON, "type", NULL, type); ++ open_json_array(PRINT_JSON, "data"); ++ for (ii = 0; ii < data_len; ii++) ++ print_uint(PRINT_JSON, NULL, NULL, data_r[ii]); ++ close_json_array(PRINT_JSON, "data"); ++ close_json_object(); ++ ++ slen += sprintf(strbuf + slen, "%04x:%02x:%s", ++ class, type, data); ++ if (rem) ++ slen += sprintf(strbuf + slen, ","); ++ } ++ close_json_array(PRINT_JSON, name); ++} ++ ++static void flower_print_geneve_parts(const char *name, struct rtattr *attr, ++ char *key, char *mask) ++{ ++ char *namefrm = "\n geneve_opt %s"; ++ char *key_token, *mask_token, *out; ++ int len; ++ ++ out = malloc(RTA_PAYLOAD(attr) * 4 + 3); ++ if (!out) ++ return; ++ ++ len = 0; ++ key_token = strsep(&key, ","); ++ mask_token = strsep(&mask, ","); ++ while (key_token) { ++ len += sprintf(&out[len], "%s/%s,", key_token, mask_token); ++ mask_token = strsep(&mask, ","); ++ key_token = strsep(&key, ","); ++ } ++ ++ out[len - 1] = '\0'; ++ print_string(PRINT_FP, name, namefrm, out); ++ free(out); ++} ++ ++static void flower_print_enc_opts(const char *name, struct rtattr *attr, ++ struct rtattr *mask_attr) ++{ ++ struct rtattr *key_tb[TCA_FLOWER_KEY_ENC_OPTS_MAX + 1]; ++ struct rtattr *msk_tb[TCA_FLOWER_KEY_ENC_OPTS_MAX + 1]; ++ char *key, *msk; ++ ++ if (!attr) ++ return; ++ ++ key = malloc(RTA_PAYLOAD(attr) * 2 + 1); ++ if (!key) ++ return; ++ ++ msk = malloc(RTA_PAYLOAD(attr) * 2 + 1); ++ if (!msk) ++ goto err_key_free; ++ ++ parse_rtattr_nested(key_tb, TCA_FLOWER_KEY_ENC_OPTS_MAX, attr); ++ flower_print_geneve_opts("geneve_opt_key", ++ key_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE], key); ++ ++ parse_rtattr_nested(msk_tb, TCA_FLOWER_KEY_ENC_OPTS_MAX, mask_attr); ++ flower_print_geneve_opts("geneve_opt_mask", ++ msk_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE], msk); ++ ++ flower_print_geneve_parts(name, attr, key, msk); ++ ++ free(msk); ++err_key_free: ++ free(key); ++} ++ + static void flower_print_masked_u8(const char *name, struct rtattr *attr, + struct rtattr *mask_attr, + const char *(*value_to_str)(__u8 value)) +@@ -1489,6 +1769,8 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, + tb[TCA_FLOWER_KEY_ENC_IP_TOS_MASK]); + flower_print_ip_attr("enc_ttl", tb[TCA_FLOWER_KEY_ENC_IP_TTL], + tb[TCA_FLOWER_KEY_ENC_IP_TTL_MASK]); ++ flower_print_enc_opts("enc_opt", tb[TCA_FLOWER_KEY_ENC_OPTS], ++ tb[TCA_FLOWER_KEY_ENC_OPTS_MASK]); + + flower_print_matching_flags("ip_flags", FLOWER_IP_FLAGS, + tb[TCA_FLOWER_KEY_FLAGS], +-- +1.8.3.1 + diff --git a/SOURCES/0044-tc-m_tunnel_key-Add-tunnel-option-support-to-act_tun.patch b/SOURCES/0044-tc-m_tunnel_key-Add-tunnel-option-support-to-act_tun.patch new file mode 100644 index 0000000..6bed3d5 --- /dev/null +++ b/SOURCES/0044-tc-m_tunnel_key-Add-tunnel-option-support-to-act_tun.patch @@ -0,0 +1,292 @@ +From d75736d332f6aa0fcd12352e2d2a5c1aa65c6464 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 31 Jan 2019 17:13:07 +0100 +Subject: [PATCH] tc: m_tunnel_key: Add tunnel option support to act_tunnel_key + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1654761 +Upstream Status: iproute2.git commit 6217917a38268 +Conflicts: Context change due to previous backport of tos and ttl + support. + +commit 6217917a382682d8e8a7ecdeb0c6626f701a0933 +Author: Simon Horman +Date: Thu Jul 5 17:12:00 2018 -0700 + + tc: m_tunnel_key: Add tunnel option support to act_tunnel_key + + Allow setting tunnel options using the act_tunnel_key action. + + Options are expressed as class:type:data and multiple options + may be listed using a comma delimiter. + + # ip link add name geneve0 type geneve dstport 0 external + # tc qdisc add dev eth0 ingress + # tc filter add dev eth0 protocol ip parent ffff: \ + flower indev eth0 \ + ip_proto udp \ + action tunnel_key \ + set src_ip 10.0.99.192 \ + dst_ip 10.0.99.193 \ + dst_port 6081 \ + id 11 \ + geneve_opts 0102:80:00800022,0102:80:00800022 \ + action mirred egress redirect dev geneve0 + + Signed-off-by: Simon Horman + Signed-off-by: Pieter Jansen van Vuuren + Reviewed-by: Jakub Kicinski + Signed-off-by: David Ahern +--- + man/man8/tc-tunnel_key.8 | 12 +++- + tc/m_tunnel_key.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 188 insertions(+), 1 deletion(-) + +diff --git a/man/man8/tc-tunnel_key.8 b/man/man8/tc-tunnel_key.8 +index 71cee5b..1e09362 100644 +--- a/man/man8/tc-tunnel_key.8 ++++ b/man/man8/tc-tunnel_key.8 +@@ -66,7 +66,9 @@ and + .B dst_ip + options. + .B dst_port +-is optional. ++and ++.B geneve_opts ++are optional. + .RS + .TP + .B id +@@ -81,6 +83,14 @@ Outer header destination IP address (IPv4 or IPv6) + .B dst_port + Outer header destination UDP port + .TP ++.B geneve_opts ++Geneve variable length options. ++.B geneve_opts ++is specified in the form CLASS:TYPE:DATA, where CLASS is represented as a ++16bit hexadecimal value, TYPE as an 8bit hexadecimal value and DATA as a ++variable length hexadecimal value. Additionally multiple options may be ++listed using a comma delimiter. ++.TP + .B tos + Outer header TOS + .TP +diff --git a/tc/m_tunnel_key.c b/tc/m_tunnel_key.c +index 8d0a8d1..e9e71e4 100644 +--- a/tc/m_tunnel_key.c ++++ b/tc/m_tunnel_key.c +@@ -29,6 +29,7 @@ static void explain(void) + "src_ip (mandatory)\n" + "dst_ip (mandatory)\n" + "dst_port \n" ++ "geneve_opts \n" + "csum | nocsum (default is \"csum\")\n"); + } + +@@ -81,6 +82,114 @@ static int tunnel_key_parse_dst_port(char *str, int type, struct nlmsghdr *n) + return 0; + } + ++static int tunnel_key_parse_be16(char *str, int base, int type, ++ struct nlmsghdr *n) ++{ ++ int ret; ++ __be16 value; ++ ++ ret = get_be16(&value, str, base); ++ if (ret) ++ return ret; ++ ++ addattr16(n, MAX_MSG, type, value); ++ ++ return 0; ++} ++ ++static int tunnel_key_parse_u8(char *str, int base, int type, ++ struct nlmsghdr *n) ++{ ++ int ret; ++ __u8 value; ++ ++ ret = get_u8(&value, str, base); ++ if (ret) ++ return ret; ++ ++ addattr8(n, MAX_MSG, type, value); ++ ++ return 0; ++} ++ ++static int tunnel_key_parse_geneve_opt(char *str, struct nlmsghdr *n) ++{ ++ char *token, *saveptr = NULL; ++ struct rtattr *nest; ++ int i, ret; ++ ++ nest = addattr_nest(n, MAX_MSG, TCA_TUNNEL_KEY_ENC_OPTS_GENEVE); ++ ++ token = strtok_r(str, ":", &saveptr); ++ i = 1; ++ while (token) { ++ switch (i) { ++ case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS: ++ { ++ ret = tunnel_key_parse_be16(token, 16, i, n); ++ if (ret) ++ return ret; ++ break; ++ } ++ case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE: ++ { ++ ret = tunnel_key_parse_u8(token, 16, i, n); ++ if (ret) ++ return ret; ++ break; ++ } ++ case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA: ++ { ++ size_t token_len = strlen(token); ++ uint8_t *opts; ++ ++ opts = malloc(token_len / 2); ++ if (!opts) ++ return -1; ++ if (hex2mem(token, opts, token_len / 2) < 0) { ++ free(opts); ++ return -1; ++ } ++ addattr_l(n, MAX_MSG, i, opts, token_len / 2); ++ free(opts); ++ ++ break; ++ } ++ default: ++ return -1; ++ } ++ ++ token = strtok_r(NULL, ":", &saveptr); ++ i++; ++ } ++ ++ addattr_nest_end(n, nest); ++ ++ return 0; ++} ++ ++static int tunnel_key_parse_geneve_opts(char *str, struct nlmsghdr *n) ++{ ++ char *token, *saveptr = NULL; ++ struct rtattr *nest; ++ int ret; ++ ++ nest = addattr_nest(n, MAX_MSG, TCA_TUNNEL_KEY_ENC_OPTS); ++ ++ token = strtok_r(str, ",", &saveptr); ++ while (token) { ++ ret = tunnel_key_parse_geneve_opt(token, n); ++ if (ret) ++ return ret; ++ ++ token = strtok_r(NULL, ",", &saveptr); ++ } ++ ++ addattr_nest_end(n, nest); ++ ++ return 0; ++} ++ + static int tunnel_key_parse_tos_ttl(char *str, int type, struct nlmsghdr *n) + { + int ret; +@@ -173,6 +282,13 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p, + fprintf(stderr, "Illegal \"dst port\"\n"); + return -1; + } ++ } else if (matches(*argv, "geneve_opts") == 0) { ++ NEXT_ARG(); ++ ++ if (tunnel_key_parse_geneve_opts(*argv, n)) { ++ fprintf(stderr, "Illegal \"geneve_opts\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "tos") == 0) { + NEXT_ARG(); + ret = tunnel_key_parse_tos_ttl(*argv, +@@ -292,6 +408,65 @@ static void tunnel_key_print_flag(FILE *f, const char *name_on, + rta_getattr_u8(attr) ? name_on : name_off); + } + ++static void tunnel_key_print_geneve_options(const char *name, ++ struct rtattr *attr) ++{ ++ struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ int ii, data_len = 0, offset = 0; ++ int rem = RTA_PAYLOAD(attr); ++ char strbuf[rem * 2 + 1]; ++ char data[rem * 2 + 1]; ++ uint8_t data_r[rem]; ++ uint16_t clss; ++ uint8_t type; ++ ++ open_json_array(PRINT_JSON, name); ++ print_string(PRINT_FP, name, "\n\t%s ", "geneve_opt"); ++ ++ while (rem) { ++ parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX, i, rem); ++ clss = rta_getattr_be16(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS]); ++ type = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE]); ++ data_len = RTA_PAYLOAD(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]); ++ hexstring_n2a(RTA_DATA(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]), ++ data_len, data, sizeof(data)); ++ hex2mem(data, data_r, data_len); ++ offset += data_len + 20; ++ rem -= data_len + 20; ++ i = RTA_DATA(attr) + offset; ++ ++ open_json_object(NULL); ++ print_uint(PRINT_JSON, "class", NULL, clss); ++ print_uint(PRINT_JSON, "type", NULL, type); ++ open_json_array(PRINT_JSON, "data"); ++ for (ii = 0; ii < data_len; ii++) ++ print_uint(PRINT_JSON, NULL, NULL, data_r[ii]); ++ close_json_array(PRINT_JSON, "data"); ++ close_json_object(); ++ ++ sprintf(strbuf, "%04x:%02x:%s", clss, type, data); ++ if (rem) ++ print_string(PRINT_FP, NULL, "%s,", strbuf); ++ else ++ print_string(PRINT_FP, NULL, "%s", strbuf); ++ } ++ ++ close_json_array(PRINT_JSON, name); ++} ++ ++static void tunnel_key_print_key_opt(const char *name, struct rtattr *attr) ++{ ++ struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1]; ++ ++ if (!attr) ++ return; ++ ++ parse_rtattr_nested(tb, TCA_TUNNEL_KEY_ENC_OPTS_MAX, attr); ++ tunnel_key_print_geneve_options(name, ++ tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE]); ++} ++ + static void tunnel_key_print_tos_ttl(FILE *f, char *name, + struct rtattr *attr) + { +@@ -346,6 +521,8 @@ static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg) + tb[TCA_TUNNEL_KEY_ENC_KEY_ID]); + tunnel_key_print_dst_port(f, "dst_port", + tb[TCA_TUNNEL_KEY_ENC_DST_PORT]); ++ tunnel_key_print_key_opt("geneve_opts", ++ tb[TCA_TUNNEL_KEY_ENC_OPTS]); + tunnel_key_print_flag(f, "nocsum", "csum", + tb[TCA_TUNNEL_KEY_NO_CSUM]); + tunnel_key_print_tos_ttl(f, "tos", +-- +1.8.3.1 + diff --git a/SOURCES/0045-ip-rule-Add-ipproto-and-port-range-to-filter-list.patch b/SOURCES/0045-ip-rule-Add-ipproto-and-port-range-to-filter-list.patch new file mode 100644 index 0000000..1d9ee49 --- /dev/null +++ b/SOURCES/0045-ip-rule-Add-ipproto-and-port-range-to-filter-list.patch @@ -0,0 +1,121 @@ +From ec8d7120bf3b8fd47937e9297468e0bb7c1f270c Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Wed, 29 May 2019 17:40:35 +0200 +Subject: [PATCH] ip rule: Add ipproto and port range to filter list + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1678111 +Upstream Status: iproute2.git commit b2e8bf1584605 + +commit b2e8bf158460568ec5b48cba69f657f95891c901 +Author: David Ahern +Date: Tue Oct 30 15:03:30 2018 -0700 + + ip rule: Add ipproto and port range to filter list + + Allow ip rule dumps and flushes to filter based on ipproto, sport + and dport. Example: + + $ ip ru ls ipproto udp + 99: from all to 8.8.8.8 ipproto udp dport 53 lookup 1001 + $ ip ru ls dport 53 + 99: from all to 8.8.8.8 ipproto udp dport 53 lookup 1001 + + Signed-off-by: David Ahern +--- + ip/iprule.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 66 insertions(+) + +diff --git a/ip/iprule.c b/ip/iprule.c +index 744d6d88e3433..33160eafa2b33 100644 +--- a/ip/iprule.c ++++ b/ip/iprule.c +@@ -78,6 +78,9 @@ static struct + inet_prefix dst; + int protocol; + int protocolmask; ++ struct fib_rule_port_range sport; ++ struct fib_rule_port_range dport; ++ __u8 ipproto; + } filter; + + static inline int frh_get_table(struct fib_rule_hdr *frh, struct rtattr **tb) +@@ -174,6 +177,39 @@ static bool filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len) + return false; + } + ++ if (filter.ipproto) { ++ __u8 ipproto = 0; ++ ++ if (tb[FRA_IP_PROTO]) ++ ipproto = rta_getattr_u8(tb[FRA_IP_PROTO]); ++ if (filter.ipproto != ipproto) ++ return false; ++ } ++ ++ if (filter.sport.start) { ++ const struct fib_rule_port_range *r; ++ ++ if (!tb[FRA_SPORT_RANGE]) ++ return false; ++ ++ r = RTA_DATA(tb[FRA_SPORT_RANGE]); ++ if (r->start != filter.sport.start || ++ r->end != filter.sport.end) ++ return false; ++ } ++ ++ if (filter.dport.start) { ++ const struct fib_rule_port_range *r; ++ ++ if (!tb[FRA_DPORT_RANGE]) ++ return false; ++ ++ r = RTA_DATA(tb[FRA_DPORT_RANGE]); ++ if (r->start != filter.dport.start || ++ r->end != filter.dport.end) ++ return false; ++ } ++ + table = frh_get_table(frh, tb); + if (filter.tb > 0 && filter.tb ^ table) + return false; +@@ -604,6 +640,36 @@ static int iprule_list_flush_or_save(int argc, char **argv, int action) + filter.protocolmask = 0; + } + filter.protocol = prot; ++ } else if (strcmp(*argv, "ipproto") == 0) { ++ int ipproto; ++ ++ NEXT_ARG(); ++ ipproto = inet_proto_a2n(*argv); ++ if (ipproto < 0) ++ invarg("Invalid \"ipproto\" value\n", *argv); ++ filter.ipproto = ipproto; ++ } else if (strcmp(*argv, "sport") == 0) { ++ struct fib_rule_port_range r; ++ int ret; ++ ++ NEXT_ARG(); ++ ret = sscanf(*argv, "%hu-%hu", &r.start, &r.end); ++ if (ret == 1) ++ r.end = r.start; ++ else if (ret != 2) ++ invarg("invalid port range\n", *argv); ++ filter.sport = r; ++ } else if (strcmp(*argv, "dport") == 0) { ++ struct fib_rule_port_range r; ++ int ret; ++ ++ NEXT_ARG(); ++ ret = sscanf(*argv, "%hu-%hu", &r.start, &r.end); ++ if (ret == 1) ++ r.end = r.start; ++ else if (ret != 2) ++ invarg("invalid dport range\n", *argv); ++ filter.dport = r; + } else{ + if (matches(*argv, "dst") == 0 || + matches(*argv, "to") == 0) { +-- +2.20.1 + diff --git a/SOURCES/0046-tc-flower-Add-support-for-QinQ.patch b/SOURCES/0046-tc-flower-Add-support-for-QinQ.patch new file mode 100644 index 0000000..2657235 --- /dev/null +++ b/SOURCES/0046-tc-flower-Add-support-for-QinQ.patch @@ -0,0 +1,273 @@ +From b485126fd0a84a09f3d61bb4d634011be92fb6a4 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Wed, 29 May 2019 18:28:17 +0200 +Subject: [PATCH] tc: flower: Add support for QinQ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1615928 +Upstream Status: iproute2.git commit 1f0a5dfd388cd + +commit 1f0a5dfd388cd5c25f6a24247667e04b2346e568 +Author: Jianbo Liu +Date: Sat Jun 30 10:01:33 2018 +0000 + + tc: flower: Add support for QinQ + + To support matching on both outer and inner vlan headers, + we add new cvlan_id/cvlan_prio/cvlan_ethtype for inner vlan header. + + Example: + # tc filter add dev eth0 protocol 802.1ad parent ffff: \ + flower vlan_id 1000 vlan_ethtype 802.1q \ + cvlan_id 100 cvlan_ethtype ipv4 \ + action vlan pop \ + action vlan pop \ + action mirred egress redirect dev eth1 + + # tc filter show dev eth0 ingress + filter protocol 802.1ad pref 1 flower chain 0 + filter protocol 802.1ad pref 1 flower chain 0 handle 0x1 +   vlan_id 1000 +   vlan_ethtype 802.1Q +   cvlan_id 100 +   cvlan_ethtype ip +   eth_type ipv4 +   in_hw + + Signed-off-by: Jianbo Liu + Acked-by: Jiri Pirko + Signed-off-by: David Ahern +--- + man/man8/tc-flower.8 | 23 ++++++++++ + tc/f_flower.c | 103 ++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 114 insertions(+), 12 deletions(-) + +diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8 +index 276b5271cf013..8be8882592eaa 100644 +--- a/man/man8/tc-flower.8 ++++ b/man/man8/tc-flower.8 +@@ -34,6 +34,12 @@ flower \- flow based traffic control filter + .IR PRIORITY " | " + .BR vlan_ethtype " { " ipv4 " | " ipv6 " | " + .IR ETH_TYPE " } | " ++.B cvlan_id ++.IR VID " | " ++.B cvlan_prio ++.IR PRIORITY " | " ++.BR cvlan_ethtype " { " ipv4 " | " ipv6 " | " ++.IR ETH_TYPE " } | " + .B mpls_label + .IR LABEL " | " + .B mpls_tc +@@ -145,6 +151,23 @@ Match on layer three protocol. + .I VLAN_ETH_TYPE + may be either + .BR ipv4 ", " ipv6 ++or an unsigned 16bit value in hexadecimal format. To match on QinQ packet, it must be 802.1Q or 802.1AD. ++.TP ++.BI cvlan_id " VID" ++Match on QinQ inner vlan tag id. ++.I VID ++is an unsigned 12bit value in decimal format. ++.TP ++.BI cvlan_prio " PRIORITY" ++Match on QinQ inner vlan tag priority. ++.I PRIORITY ++is an unsigned 3bit value in decimal format. ++.TP ++.BI cvlan_ethtype " VLAN_ETH_TYPE" ++Match on QinQ layer three protocol. ++.I VLAN_ETH_TYPE ++may be either ++.BR ipv4 ", " ipv6 + or an unsigned 16bit value in hexadecimal format. + .TP + .BI mpls_label " LABEL" +diff --git a/tc/f_flower.c b/tc/f_flower.c +index 43102c86d1597..634bb81af7dbb 100644 +--- a/tc/f_flower.c ++++ b/tc/f_flower.c +@@ -50,6 +50,9 @@ static void explain(void) + " vlan_id VID |\n" + " vlan_prio PRIORITY |\n" + " vlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n" ++ " cvlan_id VID |\n" ++ " cvlan_prio PRIORITY |\n" ++ " cvlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n" + " dst_mac MASKED-LLADDR |\n" + " src_mac MASKED-LLADDR |\n" + " ip_proto [tcp | udp | sctp | icmp | icmpv6 | IP-PROTO ] |\n" +@@ -131,15 +134,21 @@ err: + return err; + } + ++static bool eth_type_vlan(__be16 ethertype) ++{ ++ return ethertype == htons(ETH_P_8021Q) || ++ ethertype == htons(ETH_P_8021AD); ++} ++ + static int flower_parse_vlan_eth_type(char *str, __be16 eth_type, int type, + __be16 *p_vlan_eth_type, + struct nlmsghdr *n) + { + __be16 vlan_eth_type; + +- if (eth_type != htons(ETH_P_8021Q)) { +- fprintf(stderr, +- "Can't set \"vlan_ethtype\" if ethertype isn't 802.1Q\n"); ++ if (!eth_type_vlan(eth_type)) { ++ fprintf(stderr, "Can't set \"%s\" if ethertype isn't 802.1Q or 802.1AD\n", ++ type == TCA_FLOWER_KEY_VLAN_ETH_TYPE ? "vlan_ethtype" : "cvlan_ethtype"); + return -1; + } + +@@ -762,6 +771,7 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + struct rtattr *tail; + __be16 eth_type = TC_H_MIN(t->tcm_info); + __be16 vlan_ethtype = 0; ++ __be16 cvlan_ethtype = 0; + __u8 ip_proto = 0xff; + __u32 flags = 0; + __u32 mtf = 0; +@@ -839,9 +849,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + __u16 vid; + + NEXT_ARG(); +- if (eth_type != htons(ETH_P_8021Q)) { +- fprintf(stderr, +- "Can't set \"vlan_id\" if ethertype isn't 802.1Q\n"); ++ if (!eth_type_vlan(eth_type)) { ++ fprintf(stderr, "Can't set \"vlan_id\" if ethertype isn't 802.1Q or 802.1AD\n"); + return -1; + } + ret = get_u16(&vid, *argv, 10); +@@ -854,9 +863,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + __u8 vlan_prio; + + NEXT_ARG(); +- if (eth_type != htons(ETH_P_8021Q)) { +- fprintf(stderr, +- "Can't set \"vlan_prio\" if ethertype isn't 802.1Q\n"); ++ if (!eth_type_vlan(eth_type)) { ++ fprintf(stderr, "Can't set \"vlan_prio\" if ethertype isn't 802.1Q or 802.1AD\n"); + return -1; + } + ret = get_u8(&vlan_prio, *argv, 10); +@@ -873,6 +881,42 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + &vlan_ethtype, n); + if (ret < 0) + return -1; ++ } else if (matches(*argv, "cvlan_id") == 0) { ++ __u16 vid; ++ ++ NEXT_ARG(); ++ if (!eth_type_vlan(vlan_ethtype)) { ++ fprintf(stderr, "Can't set \"cvlan_id\" if inner vlan ethertype isn't 802.1Q or 802.1AD\n"); ++ return -1; ++ } ++ ret = get_u16(&vid, *argv, 10); ++ if (ret < 0 || vid & ~0xfff) { ++ fprintf(stderr, "Illegal \"cvlan_id\"\n"); ++ return -1; ++ } ++ addattr16(n, MAX_MSG, TCA_FLOWER_KEY_CVLAN_ID, vid); ++ } else if (matches(*argv, "cvlan_prio") == 0) { ++ __u8 cvlan_prio; ++ ++ NEXT_ARG(); ++ if (!eth_type_vlan(vlan_ethtype)) { ++ fprintf(stderr, "Can't set \"cvlan_prio\" if inner vlan ethertype isn't 802.1Q or 802.1AD\n"); ++ return -1; ++ } ++ ret = get_u8(&cvlan_prio, *argv, 10); ++ if (ret < 0 || cvlan_prio & ~0x7) { ++ fprintf(stderr, "Illegal \"cvlan_prio\"\n"); ++ return -1; ++ } ++ addattr8(n, MAX_MSG, ++ TCA_FLOWER_KEY_CVLAN_PRIO, cvlan_prio); ++ } else if (matches(*argv, "cvlan_ethtype") == 0) { ++ NEXT_ARG(); ++ ret = flower_parse_vlan_eth_type(*argv, vlan_ethtype, ++ TCA_FLOWER_KEY_CVLAN_ETH_TYPE, ++ &cvlan_ethtype, n); ++ if (ret < 0) ++ return -1; + } else if (matches(*argv, "mpls_label") == 0) { + __u32 label; + +@@ -959,7 +1003,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + } + } else if (matches(*argv, "ip_proto") == 0) { + NEXT_ARG(); +- ret = flower_parse_ip_proto(*argv, vlan_ethtype ? ++ ret = flower_parse_ip_proto(*argv, cvlan_ethtype ? ++ cvlan_ethtype : vlan_ethtype ? + vlan_ethtype : eth_type, + TCA_FLOWER_KEY_IP_PROTO, + &ip_proto, n); +@@ -989,7 +1034,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + } + } else if (matches(*argv, "dst_ip") == 0) { + NEXT_ARG(); +- ret = flower_parse_ip_addr(*argv, vlan_ethtype ? ++ ret = flower_parse_ip_addr(*argv, cvlan_ethtype ? ++ cvlan_ethtype : vlan_ethtype ? + vlan_ethtype : eth_type, + TCA_FLOWER_KEY_IPV4_DST, + TCA_FLOWER_KEY_IPV4_DST_MASK, +@@ -1002,7 +1048,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + } + } else if (matches(*argv, "src_ip") == 0) { + NEXT_ARG(); +- ret = flower_parse_ip_addr(*argv, vlan_ethtype ? ++ ret = flower_parse_ip_addr(*argv, cvlan_ethtype ? ++ cvlan_ethtype : vlan_ethtype ? + vlan_ethtype : eth_type, + TCA_FLOWER_KEY_IPV4_SRC, + TCA_FLOWER_KEY_IPV4_SRC_MASK, +@@ -1678,6 +1725,38 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, + rta_getattr_u8(attr)); + } + ++ if (tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]) { ++ SPRINT_BUF(buf); ++ struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]; ++ ++ print_string(PRINT_ANY, "vlan_ethtype", "\n vlan_ethtype %s", ++ ll_proto_n2a(rta_getattr_u16(attr), ++ buf, sizeof(buf))); ++ } ++ ++ if (tb[TCA_FLOWER_KEY_CVLAN_ID]) { ++ struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_ID]; ++ ++ print_uint(PRINT_ANY, "cvlan_id", "\n cvlan_id %u", ++ rta_getattr_u16(attr)); ++ } ++ ++ if (tb[TCA_FLOWER_KEY_CVLAN_PRIO]) { ++ struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_PRIO]; ++ ++ print_uint(PRINT_ANY, "cvlan_prio", "\n cvlan_prio %d", ++ rta_getattr_u8(attr)); ++ } ++ ++ if (tb[TCA_FLOWER_KEY_CVLAN_ETH_TYPE]) { ++ SPRINT_BUF(buf); ++ struct rtattr *attr = tb[TCA_FLOWER_KEY_CVLAN_ETH_TYPE]; ++ ++ print_string(PRINT_ANY, "cvlan_ethtype", "\n cvlan_ethtype %s", ++ ll_proto_n2a(rta_getattr_u16(attr), ++ buf, sizeof(buf))); ++ } ++ + flower_print_eth_addr("dst_mac", tb[TCA_FLOWER_KEY_ETH_DST], + tb[TCA_FLOWER_KEY_ETH_DST_MASK]); + flower_print_eth_addr("src_mac", tb[TCA_FLOWER_KEY_ETH_SRC], +-- +2.20.1 + diff --git a/SOURCES/0047-uapi-update-ib_verbs.patch b/SOURCES/0047-uapi-update-ib_verbs.patch new file mode 100644 index 0000000..36723cd --- /dev/null +++ b/SOURCES/0047-uapi-update-ib_verbs.patch @@ -0,0 +1,47 @@ +From bca44fb15b57a32a991780100171708e9e2e4960 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Wed, 29 May 2019 18:40:20 +0200 +Subject: [PATCH] uapi: update ib_verbs + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1664694 +Upstream Status: iproute2.git commit 27886a12416dd + +commit 27886a12416dd315cf386cfbfa93c2fb2aceca98 +Author: Stephen Hemminger +Date: Fri Aug 31 15:03:49 2018 -0700 + + uapi: update ib_verbs + + Merge current uapi from 4.19-rc1 + + Signed-off-by: Stephen Hemminger +--- + rdma/include/uapi/rdma/ib_user_verbs.h | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/rdma/include/uapi/rdma/ib_user_verbs.h b/rdma/include/uapi/rdma/ib_user_verbs.h +index 4f9991de8e3ad..25a16760de2ad 100644 +--- a/rdma/include/uapi/rdma/ib_user_verbs.h ++++ b/rdma/include/uapi/rdma/ib_user_verbs.h +@@ -279,7 +279,7 @@ struct ib_uverbs_query_port { + }; + + struct ib_uverbs_query_port_resp { +- __u32 port_cap_flags; ++ __u32 port_cap_flags; /* see ib_uverbs_query_port_cap_flags */ + __u32 max_msg_sz; + __u32 bad_pkey_cntr; + __u32 qkey_viol_cntr; +@@ -299,7 +299,8 @@ struct ib_uverbs_query_port_resp { + __u8 active_speed; + __u8 phys_state; + __u8 link_layer; +- __u8 reserved[2]; ++ __u8 flags; /* see ib_uverbs_query_port_flags */ ++ __u8 reserved; + }; + + struct ib_uverbs_alloc_pd { +-- +2.20.1 + diff --git a/SOURCES/0048-rdma-Fix-representation-of-PortInfo-CapabilityMask.patch b/SOURCES/0048-rdma-Fix-representation-of-PortInfo-CapabilityMask.patch new file mode 100644 index 0000000..159e26b --- /dev/null +++ b/SOURCES/0048-rdma-Fix-representation-of-PortInfo-CapabilityMask.patch @@ -0,0 +1,80 @@ +From e67f089156708052abeb9c67d77cb0cf966d89c6 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Wed, 29 May 2019 18:40:20 +0200 +Subject: [PATCH] rdma: Fix representation of PortInfo CapabilityMask + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1664694 +Upstream Status: iproute2.git commit d090fbf33bd15 + +commit d090fbf33bd15d82978596920b07616aa119ac2f +Author: Leon Romanovsky +Date: Sun Sep 16 20:28:13 2018 +0300 + + rdma: Fix representation of PortInfo CapabilityMask + + The port capability mask represents IBTA PortInfo specification, + but as it is written in description of kernel commit 2f944c0fbf58 + ("RDMA: Fix storage of PortInfo CapabilityMask in the kernel"), + the bit 26 was mistakenly overwritten. + + The rdmatool followed it too and mislead users by presenting wrong + value. Since it never showed proper value, we update the whole + port_cap_mask to comply with IBTA and show real HW values. + + Fixes: da990ab40a92 ("rdma: Add link object") + Signed-off-by: Leon Romanovsky + Signed-off-by: Stephen Hemminger +--- + rdma/link.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/rdma/link.c b/rdma/link.c +index 7e914c870994e..7a6d4b7e356d7 100644 +--- a/rdma/link.c ++++ b/rdma/link.c +@@ -20,6 +20,7 @@ static int link_help(struct rd *rd) + static const char *caps_to_str(uint32_t idx) + { + #define RDMA_PORT_FLAGS(x) \ ++ x(RESERVED, 0) \ + x(SM, 1) \ + x(NOTICE, 2) \ + x(TRAP, 3) \ +@@ -32,7 +33,9 @@ static const char *caps_to_str(uint32_t idx) + x(SM_DISABLED, 10) \ + x(SYS_IMAGE_GUID, 11) \ + x(PKEY_SW_EXT_PORT_TRAP, 12) \ ++ x(CABLE_INFO, 13) \ + x(EXTENDED_SPEEDS, 14) \ ++ x(CAP_MASK2, 15) \ + x(CM, 16) \ + x(SNMP_TUNNEL, 17) \ + x(REINIT, 18) \ +@@ -43,7 +46,12 @@ static const char *caps_to_str(uint32_t idx) + x(BOOT_MGMT, 23) \ + x(LINK_LATENCY, 24) \ + x(CLIENT_REG, 25) \ +- x(IP_BASED_GIDS, 26) ++ x(OTHER_LOCAL_CHANGES, 26) \ ++ x(LINK_SPPED_WIDTH, 27) \ ++ x(VENDOR_SPECIFIC_MADS, 28) \ ++ x(MULT_PKER_TRAP, 29) \ ++ x(MULT_FDB, 30) \ ++ x(HIERARCHY_INFO, 31) + + enum { RDMA_PORT_FLAGS(RDMA_BITMAP_ENUM) }; + +@@ -51,9 +59,7 @@ static const char *caps_to_str(uint32_t idx) + rdma_port_names[] = { RDMA_PORT_FLAGS(RDMA_BITMAP_NAMES) }; + #undef RDMA_PORT_FLAGS + +- if (idx < ARRAY_SIZE(rdma_port_names) && rdma_port_names[idx]) +- return rdma_port_names[idx]; +- return "UNKNOWN"; ++ return rdma_port_names[idx]; + } + + static void link_print_caps(struct rd *rd, struct nlattr **tb) +-- +2.20.1 + diff --git a/SOURCES/0049-devlink-Add-param-command-support.patch b/SOURCES/0049-devlink-Add-param-command-support.patch new file mode 100644 index 0000000..f512773 --- /dev/null +++ b/SOURCES/0049-devlink-Add-param-command-support.patch @@ -0,0 +1,702 @@ +From a126f6cc4f4d8f5f58758d673fbdb80894c5f05d Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Wed, 29 May 2019 18:55:33 +0200 +Subject: [PATCH] devlink: Add param command support + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1663199 +Upstream Status: iproute2.git commit 13925ae9eb38b + +commit 13925ae9eb38b99107be1d3fe21a1b73cf40bd97 +Author: Moshe Shemesh +Date: Wed Jul 4 17:12:06 2018 +0300 + + devlink: Add param command support + + Add support for configuration parameters set and show. + Each parameter can be either generic or driver-specific. + The user can retrieve data on these configuration parameters by devlink + param show command and can set new value to a configuration parameter + by devlink param set command. + The configuration parameters can be set in different configuration + modes: + runtime - set while driver is running, no reset required. + driverinit - applied while driver initializes, requires restart + driver by devlink reload command. + permanent - written to device's non-volatile memory, hard reset + required to apply. + + New commands added: + devlink dev param show [DEV name PARAMETER] + devlink dev param set DEV name PARAMETER value VALUE + cmode { permanent | driverinit | runtime } + + Signed-off-by: Moshe Shemesh + Signed-off-by: Jiri Pirko + Signed-off-by: David Ahern +--- + devlink/devlink.c | 454 +++++++++++++++++++++++++++++++++++++++++ + man/man8/devlink-dev.8 | 57 ++++++ + 2 files changed, 511 insertions(+) + +diff --git a/devlink/devlink.c b/devlink/devlink.c +index 7a5aef84f25dc..00a514f8ff666 100644 +--- a/devlink/devlink.c ++++ b/devlink/devlink.c +@@ -35,6 +35,10 @@ + #define ESWITCH_INLINE_MODE_NETWORK "network" + #define ESWITCH_INLINE_MODE_TRANSPORT "transport" + ++#define PARAM_CMODE_RUNTIME_STR "runtime" ++#define PARAM_CMODE_DRIVERINIT_STR "driverinit" ++#define PARAM_CMODE_PERMANENT_STR "permanent" ++ + static int g_new_line_count; + + #define pr_err(args...) fprintf(stderr, ##args) +@@ -187,6 +191,9 @@ static void ifname_map_free(struct ifname_map *ifname_map) + #define DL_OPT_ESWITCH_ENCAP_MODE BIT(15) + #define DL_OPT_RESOURCE_PATH BIT(16) + #define DL_OPT_RESOURCE_SIZE BIT(17) ++#define DL_OPT_PARAM_NAME BIT(18) ++#define DL_OPT_PARAM_VALUE BIT(19) ++#define DL_OPT_PARAM_CMODE BIT(20) + + struct dl_opts { + uint32_t present; /* flags of present items */ +@@ -211,6 +218,9 @@ struct dl_opts { + uint32_t resource_size; + uint32_t resource_id; + bool resource_id_valid; ++ const char *param_name; ++ const char *param_value; ++ enum devlink_param_cmode cmode; + }; + + struct dl { +@@ -348,6 +358,12 @@ static const enum mnl_attr_data_type devlink_policy[DEVLINK_ATTR_MAX + 1] = { + [DEVLINK_ATTR_DPIPE_FIELD_ID] = MNL_TYPE_U32, + [DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH] = MNL_TYPE_U32, + [DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE] = MNL_TYPE_U32, ++ [DEVLINK_ATTR_PARAM] = MNL_TYPE_NESTED, ++ [DEVLINK_ATTR_PARAM_NAME] = MNL_TYPE_STRING, ++ [DEVLINK_ATTR_PARAM_TYPE] = MNL_TYPE_U8, ++ [DEVLINK_ATTR_PARAM_VALUES_LIST] = MNL_TYPE_NESTED, ++ [DEVLINK_ATTR_PARAM_VALUE] = MNL_TYPE_NESTED, ++ [DEVLINK_ATTR_PARAM_VALUE_CMODE] = MNL_TYPE_U8, + }; + + static int attr_cb(const struct nlattr *attr, void *data) +@@ -514,6 +530,34 @@ static int strtouint16_t(const char *str, uint16_t *p_val) + return 0; + } + ++static int strtouint8_t(const char *str, uint8_t *p_val) ++{ ++ char *endptr; ++ unsigned long int val; ++ ++ val = strtoul(str, &endptr, 10); ++ if (endptr == str || *endptr != '\0') ++ return -EINVAL; ++ if (val > UCHAR_MAX) ++ return -ERANGE; ++ *p_val = val; ++ return 0; ++} ++ ++static int strtobool(const char *str, bool *p_val) ++{ ++ bool val; ++ ++ if (!strcmp(str, "true") || !strcmp(str, "1")) ++ val = true; ++ else if (!strcmp(str, "false") || !strcmp(str, "0")) ++ val = false; ++ else ++ return -EINVAL; ++ *p_val = val; ++ return 0; ++} ++ + static int __dl_argv_handle(char *str, char **p_bus_name, char **p_dev_name) + { + strslashrsplit(str, p_bus_name, p_dev_name); +@@ -792,6 +836,22 @@ static int eswitch_encap_mode_get(const char *typestr, bool *p_mode) + return 0; + } + ++static int param_cmode_get(const char *cmodestr, ++ enum devlink_param_cmode *cmode) ++{ ++ if (strcmp(cmodestr, PARAM_CMODE_RUNTIME_STR) == 0) { ++ *cmode = DEVLINK_PARAM_CMODE_RUNTIME; ++ } else if (strcmp(cmodestr, PARAM_CMODE_DRIVERINIT_STR) == 0) { ++ *cmode = DEVLINK_PARAM_CMODE_DRIVERINIT; ++ } else if (strcmp(cmodestr, PARAM_CMODE_PERMANENT_STR) == 0) { ++ *cmode = DEVLINK_PARAM_CMODE_PERMANENT; ++ } else { ++ pr_err("Unknown configuration mode \"%s\"\n", cmodestr); ++ return -EINVAL; ++ } ++ return 0; ++} ++ + static int dl_argv_parse(struct dl *dl, uint32_t o_required, + uint32_t o_optional) + { +@@ -973,6 +1033,32 @@ static int dl_argv_parse(struct dl *dl, uint32_t o_required, + if (err) + return err; + o_found |= DL_OPT_RESOURCE_SIZE; ++ } else if (dl_argv_match(dl, "name") && ++ (o_all & DL_OPT_PARAM_NAME)) { ++ dl_arg_inc(dl); ++ err = dl_argv_str(dl, &opts->param_name); ++ if (err) ++ return err; ++ o_found |= DL_OPT_PARAM_NAME; ++ } else if (dl_argv_match(dl, "value") && ++ (o_all & DL_OPT_PARAM_VALUE)) { ++ dl_arg_inc(dl); ++ err = dl_argv_str(dl, &opts->param_value); ++ if (err) ++ return err; ++ o_found |= DL_OPT_PARAM_VALUE; ++ } else if (dl_argv_match(dl, "cmode") && ++ (o_all & DL_OPT_PARAM_CMODE)) { ++ const char *cmodestr; ++ ++ dl_arg_inc(dl); ++ err = dl_argv_str(dl, &cmodestr); ++ if (err) ++ return err; ++ err = param_cmode_get(cmodestr, &opts->cmode); ++ if (err) ++ return err; ++ o_found |= DL_OPT_PARAM_CMODE; + } else { + pr_err("Unknown option \"%s\"\n", dl_argv(dl)); + return -EINVAL; +@@ -1057,6 +1143,24 @@ static int dl_argv_parse(struct dl *dl, uint32_t o_required, + return -EINVAL; + } + ++ if ((o_required & DL_OPT_PARAM_NAME) && ++ !(o_found & DL_OPT_PARAM_NAME)) { ++ pr_err("Parameter name expected.\n"); ++ return -EINVAL; ++ } ++ ++ if ((o_required & DL_OPT_PARAM_VALUE) && ++ !(o_found & DL_OPT_PARAM_VALUE)) { ++ pr_err("Value to set expected.\n"); ++ return -EINVAL; ++ } ++ ++ if ((o_required & DL_OPT_PARAM_CMODE) && ++ !(o_found & DL_OPT_PARAM_CMODE)) { ++ pr_err("Configuration mode expected.\n"); ++ return -EINVAL; ++ } ++ + return 0; + } + +@@ -1121,6 +1225,12 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl) + if (opts->present & DL_OPT_RESOURCE_SIZE) + mnl_attr_put_u64(nlh, DEVLINK_ATTR_RESOURCE_SIZE, + opts->resource_size); ++ if (opts->present & DL_OPT_PARAM_NAME) ++ mnl_attr_put_strz(nlh, DEVLINK_ATTR_PARAM_NAME, ++ opts->param_name); ++ if (opts->present & DL_OPT_PARAM_CMODE) ++ mnl_attr_put_u8(nlh, DEVLINK_ATTR_PARAM_VALUE_CMODE, ++ opts->cmode); + } + + static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl, +@@ -1179,6 +1289,8 @@ static void cmd_dev_help(void) + pr_err(" [ inline-mode { none | link | network | transport } ]\n"); + pr_err(" [ encap { disable | enable } ]\n"); + pr_err(" devlink dev eswitch show DEV\n"); ++ pr_err(" devlink dev param set DEV name PARAMETER value VALUE cmode { permanent | driverinit | runtime }\n"); ++ pr_err(" devlink dev param show [DEV name PARAMETER]\n"); + pr_err(" devlink dev reload DEV\n"); + } + +@@ -1393,6 +1505,14 @@ static void pr_out_str(struct dl *dl, const char *name, const char *val) + } + } + ++static void pr_out_bool(struct dl *dl, const char *name, bool val) ++{ ++ if (val) ++ pr_out_str(dl, name, "true"); ++ else ++ pr_out_str(dl, name, "false"); ++} ++ + static void pr_out_uint(struct dl *dl, const char *name, unsigned int val) + { + if (dl->json_output) { +@@ -1475,6 +1595,19 @@ static void pr_out_entry_end(struct dl *dl) + __pr_out_newline(); + } + ++static const char *param_cmode_name(uint8_t cmode) ++{ ++ switch (cmode) { ++ case DEVLINK_PARAM_CMODE_RUNTIME: ++ return PARAM_CMODE_RUNTIME_STR; ++ case DEVLINK_PARAM_CMODE_DRIVERINIT: ++ return PARAM_CMODE_DRIVERINIT_STR; ++ case DEVLINK_PARAM_CMODE_PERMANENT: ++ return PARAM_CMODE_PERMANENT_STR; ++ default: return ""; ++ } ++} ++ + static const char *eswitch_mode_name(uint32_t mode) + { + switch (mode) { +@@ -1593,6 +1726,304 @@ static int cmd_dev_eswitch(struct dl *dl) + return -ENOENT; + } + ++static void pr_out_param_value(struct dl *dl, int nla_type, struct nlattr *nl) ++{ ++ struct nlattr *nla_value[DEVLINK_ATTR_MAX + 1] = {}; ++ struct nlattr *val_attr; ++ int err; ++ ++ err = mnl_attr_parse_nested(nl, attr_cb, nla_value); ++ if (err != MNL_CB_OK) ++ return; ++ ++ if (!nla_value[DEVLINK_ATTR_PARAM_VALUE_CMODE] || ++ (nla_type != MNL_TYPE_FLAG && ++ !nla_value[DEVLINK_ATTR_PARAM_VALUE_DATA])) ++ return; ++ ++ pr_out_str(dl, "cmode", ++ param_cmode_name(mnl_attr_get_u8(nla_value[DEVLINK_ATTR_PARAM_VALUE_CMODE]))); ++ val_attr = nla_value[DEVLINK_ATTR_PARAM_VALUE_DATA]; ++ ++ switch (nla_type) { ++ case MNL_TYPE_U8: ++ pr_out_uint(dl, "value", mnl_attr_get_u8(val_attr)); ++ break; ++ case MNL_TYPE_U16: ++ pr_out_uint(dl, "value", mnl_attr_get_u16(val_attr)); ++ break; ++ case MNL_TYPE_U32: ++ pr_out_uint(dl, "value", mnl_attr_get_u32(val_attr)); ++ break; ++ case MNL_TYPE_STRING: ++ pr_out_str(dl, "value", mnl_attr_get_str(val_attr)); ++ break; ++ case MNL_TYPE_FLAG: ++ pr_out_bool(dl, "value", val_attr ? true : false); ++ break; ++ } ++} ++ ++static void pr_out_param(struct dl *dl, struct nlattr **tb, bool array) ++{ ++ struct nlattr *nla_param[DEVLINK_ATTR_MAX + 1] = {}; ++ struct nlattr *param_value_attr; ++ int nla_type; ++ int err; ++ ++ err = mnl_attr_parse_nested(tb[DEVLINK_ATTR_PARAM], attr_cb, nla_param); ++ if (err != MNL_CB_OK) ++ return; ++ if (!nla_param[DEVLINK_ATTR_PARAM_NAME] || ++ !nla_param[DEVLINK_ATTR_PARAM_TYPE] || ++ !nla_param[DEVLINK_ATTR_PARAM_VALUES_LIST]) ++ return; ++ ++ if (array) ++ pr_out_handle_start_arr(dl, tb); ++ else ++ __pr_out_handle_start(dl, tb, true, false); ++ ++ nla_type = mnl_attr_get_u8(nla_param[DEVLINK_ATTR_PARAM_TYPE]); ++ ++ pr_out_str(dl, "name", ++ mnl_attr_get_str(nla_param[DEVLINK_ATTR_PARAM_NAME])); ++ ++ if (!nla_param[DEVLINK_ATTR_PARAM_GENERIC]) ++ pr_out_str(dl, "type", "driver-specific"); ++ else ++ pr_out_str(dl, "type", "generic"); ++ ++ pr_out_array_start(dl, "values"); ++ mnl_attr_for_each_nested(param_value_attr, ++ nla_param[DEVLINK_ATTR_PARAM_VALUES_LIST]) { ++ pr_out_entry_start(dl); ++ pr_out_param_value(dl, nla_type, param_value_attr); ++ pr_out_entry_end(dl); ++ } ++ pr_out_array_end(dl); ++ pr_out_handle_end(dl); ++} ++ ++static int cmd_dev_param_show_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; ++ struct dl *dl = data; ++ ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_PARAM]) ++ return MNL_CB_ERROR; ++ pr_out_param(dl, tb, true); ++ return MNL_CB_OK; ++} ++ ++struct param_ctx { ++ struct dl *dl; ++ int nla_type; ++ union { ++ uint8_t vu8; ++ uint16_t vu16; ++ uint32_t vu32; ++ const char *vstr; ++ bool vbool; ++ } value; ++}; ++ ++static int cmd_dev_param_set_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ struct nlattr *nla_param[DEVLINK_ATTR_MAX + 1] = {}; ++ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; ++ struct nlattr *param_value_attr; ++ enum devlink_param_cmode cmode; ++ struct param_ctx *ctx = data; ++ struct dl *dl = ctx->dl; ++ int nla_type; ++ int err; ++ ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_PARAM]) ++ return MNL_CB_ERROR; ++ ++ err = mnl_attr_parse_nested(tb[DEVLINK_ATTR_PARAM], attr_cb, nla_param); ++ if (err != MNL_CB_OK) ++ return MNL_CB_ERROR; ++ ++ if (!nla_param[DEVLINK_ATTR_PARAM_TYPE] || ++ !nla_param[DEVLINK_ATTR_PARAM_VALUES_LIST]) ++ return MNL_CB_ERROR; ++ ++ nla_type = mnl_attr_get_u8(nla_param[DEVLINK_ATTR_PARAM_TYPE]); ++ mnl_attr_for_each_nested(param_value_attr, ++ nla_param[DEVLINK_ATTR_PARAM_VALUES_LIST]) { ++ struct nlattr *nla_value[DEVLINK_ATTR_MAX + 1] = {}; ++ struct nlattr *val_attr; ++ ++ err = mnl_attr_parse_nested(param_value_attr, ++ attr_cb, nla_value); ++ if (err != MNL_CB_OK) ++ return MNL_CB_ERROR; ++ ++ if (!nla_value[DEVLINK_ATTR_PARAM_VALUE_CMODE] || ++ (nla_type != MNL_TYPE_FLAG && ++ !nla_value[DEVLINK_ATTR_PARAM_VALUE_DATA])) ++ return MNL_CB_ERROR; ++ ++ cmode = mnl_attr_get_u8(nla_value[DEVLINK_ATTR_PARAM_VALUE_CMODE]); ++ if (cmode == dl->opts.cmode) { ++ val_attr = nla_value[DEVLINK_ATTR_PARAM_VALUE_DATA]; ++ switch (nla_type) { ++ case MNL_TYPE_U8: ++ ctx->value.vu8 = mnl_attr_get_u8(val_attr); ++ break; ++ case MNL_TYPE_U16: ++ ctx->value.vu16 = mnl_attr_get_u16(val_attr); ++ break; ++ case MNL_TYPE_U32: ++ ctx->value.vu32 = mnl_attr_get_u32(val_attr); ++ break; ++ case MNL_TYPE_STRING: ++ ctx->value.vstr = mnl_attr_get_str(val_attr); ++ break; ++ case MNL_TYPE_FLAG: ++ ctx->value.vbool = val_attr ? true : false; ++ break; ++ } ++ break; ++ } ++ } ++ ctx->nla_type = nla_type; ++ return MNL_CB_OK; ++} ++ ++static int cmd_dev_param_set(struct dl *dl) ++{ ++ struct param_ctx ctx = {}; ++ struct nlmsghdr *nlh; ++ uint32_t val_u32; ++ uint16_t val_u16; ++ uint8_t val_u8; ++ bool val_bool; ++ int err; ++ ++ err = dl_argv_parse(dl, DL_OPT_HANDLE | ++ DL_OPT_PARAM_NAME | ++ DL_OPT_PARAM_VALUE | ++ DL_OPT_PARAM_CMODE, 0); ++ if (err) ++ return err; ++ ++ /* Get value type */ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PARAM_GET, ++ NLM_F_REQUEST | NLM_F_ACK); ++ dl_opts_put(nlh, dl); ++ ++ ctx.dl = dl; ++ err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dev_param_set_cb, &ctx); ++ if (err) ++ return err; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PARAM_SET, ++ NLM_F_REQUEST | NLM_F_ACK); ++ dl_opts_put(nlh, dl); ++ ++ mnl_attr_put_u8(nlh, DEVLINK_ATTR_PARAM_TYPE, ctx.nla_type); ++ switch (ctx.nla_type) { ++ case MNL_TYPE_U8: ++ err = strtouint8_t(dl->opts.param_value, &val_u8); ++ if (err) ++ goto err_param_value_parse; ++ if (val_u8 == ctx.value.vu8) ++ return 0; ++ mnl_attr_put_u8(nlh, DEVLINK_ATTR_PARAM_VALUE_DATA, val_u8); ++ break; ++ case MNL_TYPE_U16: ++ err = strtouint16_t(dl->opts.param_value, &val_u16); ++ if (err) ++ goto err_param_value_parse; ++ if (val_u16 == ctx.value.vu16) ++ return 0; ++ mnl_attr_put_u16(nlh, DEVLINK_ATTR_PARAM_VALUE_DATA, val_u16); ++ break; ++ case MNL_TYPE_U32: ++ err = strtouint32_t(dl->opts.param_value, &val_u32); ++ if (err) ++ goto err_param_value_parse; ++ if (val_u32 == ctx.value.vu32) ++ return 0; ++ mnl_attr_put_u32(nlh, DEVLINK_ATTR_PARAM_VALUE_DATA, val_u32); ++ break; ++ case MNL_TYPE_FLAG: ++ err = strtobool(dl->opts.param_value, &val_bool); ++ if (err) ++ goto err_param_value_parse; ++ if (val_bool == ctx.value.vbool) ++ return 0; ++ if (val_bool) ++ mnl_attr_put(nlh, DEVLINK_ATTR_PARAM_VALUE_DATA, ++ 0, NULL); ++ break; ++ case MNL_TYPE_STRING: ++ mnl_attr_put_strz(nlh, DEVLINK_ATTR_PARAM_VALUE_DATA, ++ dl->opts.param_value); ++ if (!strcmp(dl->opts.param_value, ctx.value.vstr)) ++ return 0; ++ break; ++ default: ++ printf("Value type not supported\n"); ++ return -ENOTSUP; ++ } ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); ++ ++err_param_value_parse: ++ pr_err("Value \"%s\" is not a number or not within range\n", ++ dl->opts.param_value); ++ return err; ++} ++ ++static int cmd_dev_param_show(struct dl *dl) ++{ ++ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; ++ struct nlmsghdr *nlh; ++ int err; ++ ++ if (dl_argc(dl) == 0) ++ flags |= NLM_F_DUMP; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PARAM_GET, flags); ++ ++ if (dl_argc(dl) > 0) { ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | ++ DL_OPT_PARAM_NAME, 0); ++ if (err) ++ return err; ++ } ++ ++ pr_out_section_start(dl, "param"); ++ err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dev_param_show_cb, dl); ++ pr_out_section_end(dl); ++ return err; ++} ++ ++static int cmd_dev_param(struct dl *dl) ++{ ++ if (dl_argv_match(dl, "help")) { ++ cmd_dev_help(); ++ return 0; ++ } else if (dl_argv_match(dl, "show") || ++ dl_argv_match(dl, "list") || dl_no_arg(dl)) { ++ dl_arg_inc(dl); ++ return cmd_dev_param_show(dl); ++ } else if (dl_argv_match(dl, "set")) { ++ dl_arg_inc(dl); ++ return cmd_dev_param_set(dl); ++ } ++ pr_err("Command \"%s\" not found\n", dl_argv(dl)); ++ return -ENOENT; ++} + static int cmd_dev_show_cb(const struct nlmsghdr *nlh, void *data) + { + struct dl *dl = data; +@@ -1669,6 +2100,9 @@ static int cmd_dev(struct dl *dl) + } else if (dl_argv_match(dl, "reload")) { + dl_arg_inc(dl); + return cmd_dev_reload(dl); ++ } else if (dl_argv_match(dl, "param")) { ++ dl_arg_inc(dl); ++ return cmd_dev_param(dl); + } + pr_err("Command \"%s\" not found\n", dl_argv(dl)); + return -ENOENT; +@@ -2632,6 +3066,10 @@ static const char *cmd_name(uint8_t cmd) + case DEVLINK_CMD_PORT_SET: return "set"; + case DEVLINK_CMD_PORT_NEW: return "new"; + case DEVLINK_CMD_PORT_DEL: return "del"; ++ case DEVLINK_CMD_PARAM_GET: return "get"; ++ case DEVLINK_CMD_PARAM_SET: return "set"; ++ case DEVLINK_CMD_PARAM_NEW: return "new"; ++ case DEVLINK_CMD_PARAM_DEL: return "del"; + default: return ""; + } + } +@@ -2650,6 +3088,11 @@ static const char *cmd_obj(uint8_t cmd) + case DEVLINK_CMD_PORT_NEW: + case DEVLINK_CMD_PORT_DEL: + return "port"; ++ case DEVLINK_CMD_PARAM_GET: ++ case DEVLINK_CMD_PARAM_SET: ++ case DEVLINK_CMD_PARAM_NEW: ++ case DEVLINK_CMD_PARAM_DEL: ++ return "param"; + default: return ""; + } + } +@@ -2706,6 +3149,17 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) + pr_out_mon_header(genl->cmd); + pr_out_port(dl, tb); + break; ++ case DEVLINK_CMD_PARAM_GET: /* fall through */ ++ case DEVLINK_CMD_PARAM_SET: /* fall through */ ++ case DEVLINK_CMD_PARAM_NEW: /* fall through */ ++ case DEVLINK_CMD_PARAM_DEL: ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_PARAM]) ++ return MNL_CB_ERROR; ++ pr_out_mon_header(genl->cmd); ++ pr_out_param(dl, tb, false); ++ break; + } + return MNL_CB_OK; + } +diff --git a/man/man8/devlink-dev.8 b/man/man8/devlink-dev.8 +index 7c749ddabaeeb..d985da172aa05 100644 +--- a/man/man8/devlink-dev.8 ++++ b/man/man8/devlink-dev.8 +@@ -42,6 +42,23 @@ devlink-dev \- devlink device configuration + .BR "devlink dev eswitch show" + .IR DEV + ++.ti -8 ++.BR "devlink dev param set" ++.IR DEV ++.BR name ++.IR PARAMETER ++.BR value ++.IR VALUE ++.BR cmode " { " runtime " | " driverinit " | " permanent " } " ++ ++.ti -8 ++.BR "devlink dev param show" ++.RI "[ " ++.IR DEV ++.BR name ++.IR PARAMETER ++.RI "]" ++ + .ti -8 + .BR "devlink dev reload" + .IR DEV +@@ -98,6 +115,36 @@ Set eswitch encapsulation support + .I enable + - Enable encapsulation support + ++.SS devlink dev param set - set new value to devlink device configuration parameter ++ ++.TP ++.BI name " PARAMETER" ++Specify parameter name to set. ++ ++.TP ++.BI value " VALUE" ++New value to set. ++ ++.TP ++.BR cmode " { " runtime " | " driverinit " | " permanent " } " ++Configuration mode in which the new value is set. ++ ++.I runtime ++- Set new value while driver is running. This configuration mode doesn't require any reset to apply the new value. ++ ++.I driverinit ++- Set new value which will be applied during driver initialization. This configuration mode requires restart driver by devlink reload command to apply the new value. ++ ++.I permanent ++- New value is written to device's non-volatile memory. This configuration mode requires hard reset to apply the new value. ++ ++.SS devlink dev param show - display devlink device supported configuration parameters attributes ++ ++.BR name ++.IR PARAMETER ++Specify parameter name to show. ++If this argument is omitted all parameters supported by devlink devices are listed. ++ + .SS devlink dev reload - perform hot reload of the driver. + + .PP +@@ -126,6 +173,16 @@ devlink dev eswitch set pci/0000:01:00.0 mode switchdev + Sets the eswitch mode of specified devlink device to switchdev. + .RE + .PP ++devlink dev param show pci/0000:01:00.0 name max_macs ++.RS 4 ++Shows the parameter max_macs attributes. ++.RE ++.PP ++devlink dev param set pci/0000:01:00.0 name internal_error_reset value true cmode runtime ++.RS 4 ++Sets the parameter internal_error_reset of specified devlink device to true. ++.RE ++.PP + devlink dev reload pci/0000:01:00.0 + .RS 4 + Performs hot reload of specified devlink device. +-- +2.20.1 + diff --git a/SOURCES/0050-libnetlink-Convert-GETADDR-dumps-to-use-rtnl_addrdum.patch b/SOURCES/0050-libnetlink-Convert-GETADDR-dumps-to-use-rtnl_addrdum.patch new file mode 100644 index 0000000..340a376 --- /dev/null +++ b/SOURCES/0050-libnetlink-Convert-GETADDR-dumps-to-use-rtnl_addrdum.patch @@ -0,0 +1,100 @@ +From ae7cf70848d837d2ed85a21f6d7cbdf4c6ee6e4e Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Mon, 10 Jun 2019 14:25:21 +0200 +Subject: [PATCH] libnetlink: Convert GETADDR dumps to use rtnl_addrdump_req + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716772 +Upstream Status: iproute2.git commit 46917d0895fb0 + +commit 46917d0895fb0fb1df9b3c1575ccd467b4a1f860 +Author: David Ahern +Date: Sat Sep 29 08:41:46 2018 -0700 + + libnetlink: Convert GETADDR dumps to use rtnl_addrdump_req + + Add rtnl_addrdump_req for address dumps using the proper ifaddrmsg + as the header. Convert existing RTM_GETADDR dumps to use it. + + Signed-off-by: David Ahern +--- + include/libnetlink.h | 4 ++++ + ip/ipaddress.c | 6 +++--- + lib/libnetlink.c | 16 ++++++++++++++++ + 3 files changed, 23 insertions(+), 3 deletions(-) + +diff --git a/include/libnetlink.h b/include/libnetlink.h +index 9d9249e634dc3..2d9f6190230c1 100644 +--- a/include/libnetlink.h ++++ b/include/libnetlink.h +@@ -46,6 +46,10 @@ int rtnl_open_byproto(struct rtnl_handle *rth, unsigned int subscriptions, + __attribute__((warn_unused_result)); + + void rtnl_close(struct rtnl_handle *rth); ++ ++int rtnl_addrdump_req(struct rtnl_handle *rth, int family) ++ __attribute__((warn_unused_result)); ++ + int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type) + __attribute__((warn_unused_result)); + int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int fam, int type, +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index f315a815e945d..4714bce60db1b 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -1672,7 +1672,7 @@ static int ipaddr_flush(void) + filter.flushe = sizeof(flushb); + + while ((max_flush_loops == 0) || (round < max_flush_loops)) { +- if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { ++ if (rtnl_addrdump_req(&rth, filter.family) < 0) { + perror("Cannot send dump request"); + exit(1); + } +@@ -1764,7 +1764,7 @@ int ip_linkaddr_list(int family, req_filter_fn_t filter_fn, + } + + if (ainfo) { +- if (rtnl_wilddump_request(&rth, family, RTM_GETADDR) < 0) { ++ if (rtnl_addrdump_req(&rth, family) < 0) { + perror("Cannot send dump request"); + return 1; + } +@@ -1889,7 +1889,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) + if (ipadd_save_prep()) + exit(1); + +- if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETADDR) < 0) { ++ if (rtnl_addrdump_req(&rth, preferred_family) < 0) { + perror("Cannot send dump request"); + exit(1); + } +diff --git a/lib/libnetlink.c b/lib/libnetlink.c +index a9932d423126e..db625b9bd18ca 100644 +--- a/lib/libnetlink.c ++++ b/lib/libnetlink.c +@@ -199,6 +199,22 @@ int rtnl_open(struct rtnl_handle *rth, unsigned int subscriptions) + return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE); + } + ++int rtnl_addrdump_req(struct rtnl_handle *rth, int family) ++{ ++ struct { ++ struct nlmsghdr nlh; ++ struct ifaddrmsg ifm; ++ } req = { ++ .nlh.nlmsg_len = sizeof(req), ++ .nlh.nlmsg_type = RTM_GETADDR, ++ .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, ++ .nlh.nlmsg_seq = rth->dump = ++rth->seq, ++ .ifm.ifa_family = family, ++ }; ++ ++ return send(rth->fd, &req, sizeof(req), 0); ++} ++ + int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) + { + return rtnl_wilddump_req_filter(rth, family, type, RTEXT_FILTER_VF); +-- +2.20.1 + diff --git a/SOURCES/0051-rdma-Update-kernel-include-file-to-support-IB-device.patch b/SOURCES/0051-rdma-Update-kernel-include-file-to-support-IB-device.patch new file mode 100644 index 0000000..bebf939 --- /dev/null +++ b/SOURCES/0051-rdma-Update-kernel-include-file-to-support-IB-device.patch @@ -0,0 +1,43 @@ +From 0a919849a14e65e4ff4b2c71f02862598c79633b Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Mon, 10 Jun 2019 15:32:55 +0200 +Subject: [PATCH] rdma: Update kernel include file to support IB device + renaming + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1663228 +Upstream Status: iproute2.git commit 3fb00075d9043 + +commit 3fb00075d904389afce507fffe06ca3a8500ebf3 +Author: Leon Romanovsky +Date: Wed Oct 31 09:17:55 2018 +0200 + + rdma: Update kernel include file to support IB device renaming + + Bring kernel header file changes upto commit 05d940d3a3ec + ("RDMA/nldev: Allow IB device rename through RDMA netlink") + + Signed-off-by: Leon Romanovsky + Reviewed-by: Steve Wise + Signed-off-by: David Ahern +--- + rdma/include/uapi/rdma/rdma_netlink.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/rdma/include/uapi/rdma/rdma_netlink.h b/rdma/include/uapi/rdma/rdma_netlink.h +index 6513fb89abfa1..e2228c0917154 100644 +--- a/rdma/include/uapi/rdma/rdma_netlink.h ++++ b/rdma/include/uapi/rdma/rdma_netlink.h +@@ -227,8 +227,9 @@ enum rdma_nldev_command { + RDMA_NLDEV_CMD_UNSPEC, + + RDMA_NLDEV_CMD_GET, /* can dump */ ++ RDMA_NLDEV_CMD_SET, + +- /* 2 - 4 are free to use */ ++ /* 3 - 4 are free to use */ + + RDMA_NLDEV_CMD_PORT_GET = 5, /* can dump */ + +-- +2.20.1 + diff --git a/SOURCES/0052-rdma-Introduce-command-execution-helper-with-require.patch b/SOURCES/0052-rdma-Introduce-command-execution-helper-with-require.patch new file mode 100644 index 0000000..68919fb --- /dev/null +++ b/SOURCES/0052-rdma-Introduce-command-execution-helper-with-require.patch @@ -0,0 +1,63 @@ +From 349c43f99f876e0663fb0b00396ac3d387bc32e9 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Mon, 10 Jun 2019 15:32:55 +0200 +Subject: [PATCH] rdma: Introduce command execution helper with required device + name + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1663228 +Upstream Status: iproute2.git commit a14ceed32524c + +commit a14ceed32524c7f9c05572886cd63e921e4c0faf +Author: Leon Romanovsky +Date: Wed Oct 31 09:17:56 2018 +0200 + + rdma: Introduce command execution helper with required device name + + In contradiction to various show commands, the set command explicitly + requires to use device name as an argument. Provide new command + execution helper which enforces it. + + Signed-off-by: Leon Romanovsky + Reviewed-by: Steve Wise + Signed-off-by: David Ahern +--- + rdma/rdma.h | 1 + + rdma/utils.c | 10 ++++++++++ + 2 files changed, 11 insertions(+) + +diff --git a/rdma/rdma.h b/rdma/rdma.h +index c3b7530b6cc71..547bb5749a39f 100644 +--- a/rdma/rdma.h ++++ b/rdma/rdma.h +@@ -90,6 +90,7 @@ int cmd_link(struct rd *rd); + int cmd_res(struct rd *rd); + int rd_exec_cmd(struct rd *rd, const struct rd_cmd *c, const char *str); + int rd_exec_dev(struct rd *rd, int (*cb)(struct rd *rd)); ++int rd_exec_require_dev(struct rd *rd, int (*cb)(struct rd *rd)); + int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd), bool strict_port); + void rd_free(struct rd *rd); + int rd_set_arg_to_devname(struct rd *rd); +diff --git a/rdma/utils.c b/rdma/utils.c +index 4840bf226d54d..61f4aeb1bcf27 100644 +--- a/rdma/utils.c ++++ b/rdma/utils.c +@@ -577,6 +577,16 @@ out: + return ret; + } + ++int rd_exec_require_dev(struct rd *rd, int (*cb)(struct rd *rd)) ++{ ++ if (rd_no_arg(rd)) { ++ pr_err("Please provide device name.\n"); ++ return -EINVAL; ++ } ++ ++ return rd_exec_dev(rd, cb); ++} ++ + int rd_exec_cmd(struct rd *rd, const struct rd_cmd *cmds, const char *str) + { + const struct rd_cmd *c; +-- +2.20.1 + diff --git a/SOURCES/0053-rdma-Add-an-option-to-rename-IB-device-interface.patch b/SOURCES/0053-rdma-Add-an-option-to-rename-IB-device-interface.patch new file mode 100644 index 0000000..ab3a09e --- /dev/null +++ b/SOURCES/0053-rdma-Add-an-option-to-rename-IB-device-interface.patch @@ -0,0 +1,92 @@ +From 452611d090e456cf7b49bfbb2522df2928452e10 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Mon, 10 Jun 2019 15:32:55 +0200 +Subject: [PATCH] rdma: Add an option to rename IB device interface + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1663228 +Upstream Status: iproute2.git commit 4443c9c6a01ea + +commit 4443c9c6a01eac8c8f2743d4d185ceb9be4d1207 +Author: Leon Romanovsky +Date: Wed Oct 31 09:17:57 2018 +0200 + + rdma: Add an option to rename IB device interface + + Enrich rdmatool with an option to rename IB devices, + the command interface follows Iproute2 convention: + "rdma dev set [OLD-DEVNAME] name NEW-DEVNAME" + + Signed-off-by: Leon Romanovsky + Reviewed-by: Steve Wise + Signed-off-by: David Ahern +--- + rdma/dev.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/rdma/dev.c b/rdma/dev.c +index e2eafe47311b0..760b7fb3bb18f 100644 +--- a/rdma/dev.c ++++ b/rdma/dev.c +@@ -14,6 +14,7 @@ + static int dev_help(struct rd *rd) + { + pr_out("Usage: %s dev show [DEV]\n", rd->filename); ++ pr_out(" %s dev set [DEV] name DEVNAME\n", rd->filename); + return 0; + } + +@@ -240,17 +241,51 @@ static int dev_one_show(struct rd *rd) + return rd_exec_cmd(rd, cmds, "parameter"); + } + ++static int dev_set_name(struct rd *rd) ++{ ++ uint32_t seq; ++ ++ if (rd_no_arg(rd)) { ++ pr_err("Please provide device new name.\n"); ++ return -EINVAL; ++ } ++ ++ rd_prepare_msg(rd, RDMA_NLDEV_CMD_SET, ++ &seq, (NLM_F_REQUEST | NLM_F_ACK)); ++ mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx); ++ mnl_attr_put_strz(rd->nlh, RDMA_NLDEV_ATTR_DEV_NAME, rd_argv(rd)); ++ ++ return rd_send_msg(rd); ++} ++ ++static int dev_one_set(struct rd *rd) ++{ ++ const struct rd_cmd cmds[] = { ++ { NULL, dev_help}, ++ { "name", dev_set_name}, ++ { 0 } ++ }; ++ ++ return rd_exec_cmd(rd, cmds, "parameter"); ++} ++ + static int dev_show(struct rd *rd) + { + return rd_exec_dev(rd, dev_one_show); + } + ++static int dev_set(struct rd *rd) ++{ ++ return rd_exec_require_dev(rd, dev_one_set); ++} ++ + int cmd_dev(struct rd *rd) + { + const struct rd_cmd cmds[] = { + { NULL, dev_show }, + { "show", dev_show }, + { "list", dev_show }, ++ { "set", dev_set }, + { "help", dev_help }, + { 0 } + }; +-- +2.20.1 + diff --git a/SOURCES/0054-rdma-Document-IB-device-renaming-option.patch b/SOURCES/0054-rdma-Document-IB-device-renaming-option.patch new file mode 100644 index 0000000..8648fb8 --- /dev/null +++ b/SOURCES/0054-rdma-Document-IB-device-renaming-option.patch @@ -0,0 +1,77 @@ +From 1857f106b1fda133918456617efe74cd068c1a86 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Mon, 10 Jun 2019 15:32:55 +0200 +Subject: [PATCH] rdma: Document IB device renaming option + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1663228 +Upstream Status: iproute2.git commit e89feffae3626 + +commit e89feffae3626da5b5fda352ae73db132ac60a47 +Author: Leon Romanovsky +Date: Sun Nov 4 21:11:22 2018 +0200 + + rdma: Document IB device renaming option + + [leonro@server /]$ lspci |grep -i Ether + 00:08.0 Ethernet controller: Red Hat, Inc. Virtio network device + 00:09.0 Ethernet controller: Mellanox Technologies MT27700 Family [ConnectX-4] + [leonro@server /]$ sudo rdma dev + 1: mlx5_0: node_type ca fw 3.8.9999 node_guid 5254:00c0:fe12:3455 + sys_image_guid 5254:00c0:fe12:3455 + [leonro@server /]$ sudo rdma dev set mlx5_0 name hfi1_0 + [leonro@server /]$ sudo rdma dev + 1: hfi1_0: node_type ca fw 3.8.9999 node_guid 5254:00c0:fe12:3455 + sys_image_guid 5254:00c0:fe12:3455 + + Signed-off-by: Leon Romanovsky + Signed-off-by: David Ahern +--- + man/man8/rdma-dev.8 | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/man/man8/rdma-dev.8 b/man/man8/rdma-dev.8 +index b7abfe1088c2f..069f471791904 100644 +--- a/man/man8/rdma-dev.8 ++++ b/man/man8/rdma-dev.8 +@@ -1,6 +1,6 @@ + .TH RDMA\-DEV 8 "06 Jul 2017" "iproute2" "Linux" + .SH NAME +-rdmak-dev \- RDMA device configuration ++rdma-dev \- RDMA device configuration + .SH SYNOPSIS + .sp + .ad l +@@ -22,10 +22,18 @@ rdmak-dev \- RDMA device configuration + .B rdma dev show + .RI "[ " DEV " ]" + ++.ti -8 ++.B rdma dev set ++.RI "[ " DEV " ]" ++.BR name ++.BR NEWNAME ++ + .ti -8 + .B rdma dev help + + .SH "DESCRIPTION" ++.SS rdma dev set - rename rdma device ++ + .SS rdma dev show - display rdma device attributes + + .PP +@@ -45,6 +53,11 @@ rdma dev show mlx5_3 + Shows the state of specified RDMA device. + .RE + .PP ++rdma dev set mlx5_3 name rdma_0 ++.RS 4 ++Renames the mlx5_3 device to rdma_0. ++.RE ++.PP + + .SH SEE ALSO + .BR rdma (8), +-- +2.20.1 + diff --git a/SOURCES/0055-iplink-add-support-for-reporting-multiple-XDP-progra.patch b/SOURCES/0055-iplink-add-support-for-reporting-multiple-XDP-progra.patch new file mode 100644 index 0000000..4a49a42 --- /dev/null +++ b/SOURCES/0055-iplink-add-support-for-reporting-multiple-XDP-progra.patch @@ -0,0 +1,210 @@ +From 907e2adbcb6e02453972d5ada93de7bbaefedb2a Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:56 +0200 +Subject: [PATCH] iplink: add support for reporting multiple XDP programs + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit da083b5a483bf + +commit da083b5a483bfd52dfe72912f62a3bc16d775b87 +Author: Jakub Kicinski +Date: Fri Jul 13 15:54:51 2018 -0700 + + iplink: add support for reporting multiple XDP programs + + Kernel now supports attaching XDP programs in the driver + and hardware at the same time. Print that information + correctly. + + In case there are multiple programs attached kernel will + not provide IFLA_XDP_PROG_ID, so don't expect it to be + there (this also improves the printing for very old kernels + slightly, as it avoids unnecessary "prog/xdp" line). + + In short mode preserve the current outputs but don't print + IDs if there are multiple. + + 6: netdevsim0: mtu 1500 xdpoffload/id:11 qdisc [...] + + and: + + 6: netdevsim0: mtu 1500 xdpmulti qdisc [...] + + ip link output will keep using prog/xdp prefix if only one program + is attached, but can also print multiple program lines: + + prog/xdp id 8 tag fc7a51d1a693a99e jited + + vs: + + prog/xdpdrv id 8 tag fc7a51d1a693a99e jited + prog/xdpoffload id 9 tag fc7a51d1a693a99e + + JSON output gains a new array called "attached" which will + contain the full list of attached programs along with their + attachment modes: + + "xdp": { + "mode": 3, + "prog": { + "id": 11, + "tag": "fc7a51d1a693a99e", + "jited": 0 + }, + "attached": [ { + "mode": 3, + "prog": { + "id": 11, + "tag": "fc7a51d1a693a99e", + "jited": 0 + } + } ] + }, + + In case there are multiple programs attached the general "xdp" + section will not contain program information: + + "xdp": { + "mode": 4, + "attached": [ { + "mode": 1, + "prog": { + "id": 10, + "tag": "fc7a51d1a693a99e", + "jited": 1 + } + },{ + "mode": 3, + "prog": { + "id": 11, + "tag": "fc7a51d1a693a99e", + "jited": 0 + } + } ] + }, + + Signed-off-by: Jakub Kicinski + Reviewed-by: Quentin Monnet + Acked-by: Daniel Borkmann + Signed-off-by: David Ahern +--- + ip/iplink_xdp.c | 73 +++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 61 insertions(+), 12 deletions(-) + +diff --git a/ip/iplink_xdp.c b/ip/iplink_xdp.c +index dd4fd1fd3a3b1..4a490bc8fb66c 100644 +--- a/ip/iplink_xdp.c ++++ b/ip/iplink_xdp.c +@@ -91,6 +91,18 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, + return 0; + } + ++static void xdp_dump_json_one(struct rtattr *tb[IFLA_XDP_MAX + 1], __u32 attr, ++ __u8 mode) ++{ ++ if (!tb[attr]) ++ return; ++ ++ open_json_object(NULL); ++ print_uint(PRINT_JSON, "mode", NULL, mode); ++ bpf_dump_prog_info(NULL, rta_getattr_u32(tb[attr])); ++ close_json_object(); ++} ++ + static void xdp_dump_json(struct rtattr *tb[IFLA_XDP_MAX + 1]) + { + __u32 prog_id = 0; +@@ -104,13 +116,48 @@ static void xdp_dump_json(struct rtattr *tb[IFLA_XDP_MAX + 1]) + print_uint(PRINT_JSON, "mode", NULL, mode); + if (prog_id) + bpf_dump_prog_info(NULL, prog_id); ++ ++ open_json_array(PRINT_JSON, "attached"); ++ if (tb[IFLA_XDP_SKB_PROG_ID] || ++ tb[IFLA_XDP_DRV_PROG_ID] || ++ tb[IFLA_XDP_HW_PROG_ID]) { ++ xdp_dump_json_one(tb, IFLA_XDP_SKB_PROG_ID, XDP_ATTACHED_SKB); ++ xdp_dump_json_one(tb, IFLA_XDP_DRV_PROG_ID, XDP_ATTACHED_DRV); ++ xdp_dump_json_one(tb, IFLA_XDP_HW_PROG_ID, XDP_ATTACHED_HW); ++ } else if (tb[IFLA_XDP_PROG_ID]) { ++ /* Older kernel - use IFLA_XDP_PROG_ID */ ++ xdp_dump_json_one(tb, IFLA_XDP_PROG_ID, mode); ++ } ++ close_json_array(PRINT_JSON, NULL); ++ + close_json_object(); + } + ++static void xdp_dump_prog_one(FILE *fp, struct rtattr *tb[IFLA_XDP_MAX + 1], ++ __u32 attr, bool link, bool details, ++ const char *pfx) ++{ ++ __u32 prog_id; ++ ++ if (!tb[attr]) ++ return; ++ ++ prog_id = rta_getattr_u32(tb[attr]); ++ if (!details) { ++ if (prog_id && !link && attr == IFLA_XDP_PROG_ID) ++ fprintf(fp, "/id:%u", prog_id); ++ return; ++ } ++ ++ if (prog_id) { ++ fprintf(fp, "%s prog/xdp%s ", _SL_, pfx); ++ bpf_dump_prog_info(fp, prog_id); ++ } ++} ++ + void xdp_dump(FILE *fp, struct rtattr *xdp, bool link, bool details) + { + struct rtattr *tb[IFLA_XDP_MAX + 1]; +- __u32 prog_id = 0; + __u8 mode; + + parse_rtattr_nested(tb, IFLA_XDP_MAX, xdp); +@@ -124,27 +171,29 @@ void xdp_dump(FILE *fp, struct rtattr *xdp, bool link, bool details) + else if (is_json_context()) + return details ? (void)0 : xdp_dump_json(tb); + else if (details && link) +- fprintf(fp, "%s prog/xdp", _SL_); ++ /* don't print mode */; + else if (mode == XDP_ATTACHED_DRV) + fprintf(fp, "xdp"); + else if (mode == XDP_ATTACHED_SKB) + fprintf(fp, "xdpgeneric"); + else if (mode == XDP_ATTACHED_HW) + fprintf(fp, "xdpoffload"); ++ else if (mode == XDP_ATTACHED_MULTI) ++ fprintf(fp, "xdpmulti"); + else + fprintf(fp, "xdp[%u]", mode); + +- if (tb[IFLA_XDP_PROG_ID]) +- prog_id = rta_getattr_u32(tb[IFLA_XDP_PROG_ID]); +- if (!details) { +- if (prog_id && !link) +- fprintf(fp, "/id:%u", prog_id); +- fprintf(fp, " "); +- return; ++ xdp_dump_prog_one(fp, tb, IFLA_XDP_PROG_ID, link, details, ""); ++ ++ if (mode == XDP_ATTACHED_MULTI) { ++ xdp_dump_prog_one(fp, tb, IFLA_XDP_SKB_PROG_ID, link, details, ++ "generic"); ++ xdp_dump_prog_one(fp, tb, IFLA_XDP_DRV_PROG_ID, link, details, ++ "drv"); ++ xdp_dump_prog_one(fp, tb, IFLA_XDP_HW_PROG_ID, link, details, ++ "offload"); + } + +- if (prog_id) { ++ if (!details || !link) + fprintf(fp, " "); +- bpf_dump_prog_info(fp, prog_id); +- } + } +-- +2.20.1 + diff --git a/SOURCES/0056-bpf-move-bpf_elf_map-fixup-notification-under-verbos.patch b/SOURCES/0056-bpf-move-bpf_elf_map-fixup-notification-under-verbos.patch new file mode 100644 index 0000000..50c380c --- /dev/null +++ b/SOURCES/0056-bpf-move-bpf_elf_map-fixup-notification-under-verbos.patch @@ -0,0 +1,43 @@ +From f6fa6c4f178d2bbd3f33cfd4c32265692b91fe5d Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:56 +0200 +Subject: [PATCH] bpf: move bpf_elf_map fixup notification under verbose + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit 282a1fe1f8fc8 + +commit 282a1fe1f8fc87b1ebca4ca6f4440d2e69cf4b8f +Author: Daniel Borkmann +Date: Wed Jul 18 01:31:19 2018 +0200 + + bpf: move bpf_elf_map fixup notification under verbose + + No need to spam the user with this if it can be fixed gracefully + anyway. Therefore, move it under verbose option. + + Signed-off-by: Daniel Borkmann + Signed-off-by: David Ahern +--- + lib/bpf.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/bpf.c b/lib/bpf.c +index 65e26989a1f30..9dc37c787d907 100644 +--- a/lib/bpf.c ++++ b/lib/bpf.c +@@ -1898,9 +1898,9 @@ static int bpf_fetch_maps_end(struct bpf_elf_ctx *ctx) + } + + memcpy(ctx->maps, fixup, sizeof(fixup)); +- +- printf("Note: %zu bytes struct bpf_elf_map fixup performed due to size mismatch!\n", +- sizeof(struct bpf_elf_map) - ctx->map_len); ++ if (ctx->verbose) ++ printf("%zu bytes struct bpf_elf_map fixup performed due to size mismatch!\n", ++ sizeof(struct bpf_elf_map) - ctx->map_len); + return 0; + } + +-- +2.20.1 + diff --git a/SOURCES/0057-bpf-remove-strict-dependency-on-af_alg.patch b/SOURCES/0057-bpf-remove-strict-dependency-on-af_alg.patch new file mode 100644 index 0000000..7197210 --- /dev/null +++ b/SOURCES/0057-bpf-remove-strict-dependency-on-af_alg.patch @@ -0,0 +1,181 @@ +From 19729e1302017ef33e139903b28f9a778b2a8748 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:56 +0200 +Subject: [PATCH] bpf: remove strict dependency on af_alg + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit 6e5094dbb7c06 + +commit 6e5094dbb7c0682a9ca6eb2a64ec51f0a8a33a22 +Author: Daniel Borkmann +Date: Wed Jul 18 01:31:20 2018 +0200 + + bpf: remove strict dependency on af_alg + + Do not bail out when AF_ALG is not supported by the kernel and + only do so when a map is requested in object ns where we're + calculating the hash. Otherwise, the loader can operate just + fine, therefore lets not fail early when it's not needed. + + Signed-off-by: Daniel Borkmann + Signed-off-by: David Ahern +--- + lib/bpf.c | 74 +++++++++++++++++++++---------------------------------- + 1 file changed, 28 insertions(+), 46 deletions(-) + +diff --git a/lib/bpf.c b/lib/bpf.c +index 9dc37c787d907..ead8b5a7219f0 100644 +--- a/lib/bpf.c ++++ b/lib/bpf.c +@@ -1130,6 +1130,7 @@ struct bpf_elf_ctx { + GElf_Ehdr elf_hdr; + Elf_Data *sym_tab; + Elf_Data *str_tab; ++ char obj_uid[64]; + int obj_fd; + int map_fds[ELF_MAX_MAPS]; + struct bpf_elf_map maps[ELF_MAX_MAPS]; +@@ -1143,6 +1144,7 @@ struct bpf_elf_ctx { + enum bpf_prog_type type; + __u32 ifindex; + bool verbose; ++ bool noafalg; + struct bpf_elf_st stat; + struct bpf_hash_entry *ht[256]; + char *log; +@@ -1258,22 +1260,15 @@ static int bpf_obj_hash(const char *object, uint8_t *out, size_t len) + return -EINVAL; + + cfd = socket(AF_ALG, SOCK_SEQPACKET, 0); +- if (cfd < 0) { +- fprintf(stderr, "Cannot get AF_ALG socket: %s\n", +- strerror(errno)); ++ if (cfd < 0) + return cfd; +- } + + ret = bind(cfd, (struct sockaddr *)&alg, sizeof(alg)); +- if (ret < 0) { +- fprintf(stderr, "Error binding socket: %s\n", strerror(errno)); ++ if (ret < 0) + goto out_cfd; +- } + + ofd = accept(cfd, NULL, 0); + if (ofd < 0) { +- fprintf(stderr, "Error accepting socket: %s\n", +- strerror(errno)); + ret = ofd; + goto out_cfd; + } +@@ -1318,29 +1313,7 @@ out_cfd: + return ret; + } + +-static const char *bpf_get_obj_uid(const char *pathname) +-{ +- static bool bpf_uid_cached; +- static char bpf_uid[64]; +- uint8_t tmp[20]; +- int ret; +- +- if (bpf_uid_cached) +- goto done; +- +- ret = bpf_obj_hash(pathname, tmp, sizeof(tmp)); +- if (ret) { +- fprintf(stderr, "Object hashing failed!\n"); +- return NULL; +- } +- +- hexstring_n2a(tmp, sizeof(tmp), bpf_uid, sizeof(bpf_uid)); +- bpf_uid_cached = true; +-done: +- return bpf_uid; +-} +- +-static int bpf_init_env(const char *pathname) ++static void bpf_init_env(void) + { + struct rlimit limit = { + .rlim_cur = RLIM_INFINITY, +@@ -1350,15 +1323,8 @@ static int bpf_init_env(const char *pathname) + /* Don't bother in case we fail! */ + setrlimit(RLIMIT_MEMLOCK, &limit); + +- if (!bpf_get_work_dir(BPF_PROG_TYPE_UNSPEC)) { ++ if (!bpf_get_work_dir(BPF_PROG_TYPE_UNSPEC)) + fprintf(stderr, "Continuing without mounted eBPF fs. Too old kernel?\n"); +- return 0; +- } +- +- if (!bpf_get_obj_uid(pathname)) +- return -1; +- +- return 0; + } + + static const char *bpf_custom_pinning(const struct bpf_elf_ctx *ctx, +@@ -1394,7 +1360,7 @@ static void bpf_make_pathname(char *pathname, size_t len, const char *name, + case PIN_OBJECT_NS: + snprintf(pathname, len, "%s/%s/%s", + bpf_get_work_dir(ctx->type), +- bpf_get_obj_uid(NULL), name); ++ ctx->obj_uid, name); + break; + case PIN_GLOBAL_NS: + snprintf(pathname, len, "%s/%s/%s", +@@ -1427,7 +1393,7 @@ static int bpf_make_obj_path(const struct bpf_elf_ctx *ctx) + int ret; + + snprintf(tmp, sizeof(tmp), "%s/%s", bpf_get_work_dir(ctx->type), +- bpf_get_obj_uid(NULL)); ++ ctx->obj_uid); + + ret = mkdir(tmp, S_IRWXU); + if (ret && errno != EEXIST) { +@@ -1696,6 +1662,12 @@ static int bpf_maps_attach_all(struct bpf_elf_ctx *ctx) + const char *map_name; + + for (i = 0; i < ctx->map_num; i++) { ++ if (ctx->maps[i].pinning == PIN_OBJECT_NS && ++ ctx->noafalg) { ++ fprintf(stderr, "Missing kernel AF_ALG support for PIN_OBJECT_NS!\n"); ++ return -ENOTSUP; ++ } ++ + map_name = bpf_map_fetch_name(ctx, i); + if (!map_name) + return -EIO; +@@ -2451,14 +2423,24 @@ static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname, + enum bpf_prog_type type, __u32 ifindex, + bool verbose) + { +- int ret = -EINVAL; ++ uint8_t tmp[20]; ++ int ret; + +- if (elf_version(EV_CURRENT) == EV_NONE || +- bpf_init_env(pathname)) +- return ret; ++ if (elf_version(EV_CURRENT) == EV_NONE) ++ return -EINVAL; ++ ++ bpf_init_env(); + + memset(ctx, 0, sizeof(*ctx)); + bpf_get_cfg(ctx); ++ ++ ret = bpf_obj_hash(pathname, tmp, sizeof(tmp)); ++ if (ret) ++ ctx->noafalg = true; ++ else ++ hexstring_n2a(tmp, sizeof(tmp), ctx->obj_uid, ++ sizeof(ctx->obj_uid)); ++ + ctx->verbose = verbose; + ctx->type = type; + ctx->ifindex = ifindex; +-- +2.20.1 + diff --git a/SOURCES/0058-bpf-implement-bpf-to-bpf-calls-support.patch b/SOURCES/0058-bpf-implement-bpf-to-bpf-calls-support.patch new file mode 100644 index 0000000..18cc137 --- /dev/null +++ b/SOURCES/0058-bpf-implement-bpf-to-bpf-calls-support.patch @@ -0,0 +1,460 @@ +From 80dcb40f8442f79a043c520ae9eef067519ee7ca Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:56 +0200 +Subject: [PATCH] bpf: implement bpf to bpf calls support + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit b5cb33aec65cb + +commit b5cb33aec65cb77183abbdfa5b61ecc9877ec776 +Author: Daniel Borkmann +Date: Wed Jul 18 01:31:21 2018 +0200 + + bpf: implement bpf to bpf calls support + + Implement missing bpf to bpf calls support. The loader will + recognize .text section and handle relocation entries that + are emitted by LLVM. + + First step is processing of map related relocation entries + for .text section, and in a second step loader will copy .text + section into program section and adjust call instruction + offset accordingly. + + Example with test_xdp_noinline.o from kernel selftests: + + 1) Every function as __attribute__ ((always_inline)), rest + left unchanged: + + # ip -force link set dev lo xdp obj test_xdp_noinline.o sec xdp-test + # ip a + 1: lo: mtu 65536 xdpgeneric/id:233 qdisc noqueue state UNKNOWN group default qlen 1000 + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 + inet 127.0.0.1/8 scope host lo + valid_lft forever preferred_lft forever + inet6 ::1/128 scope host + valid_lft forever preferred_lft forever + [...] + # bpftool prog dump xlated id 233 + [...] + 1669: (2d) if r3 > r2 goto pc+4 + 1670: (79) r2 = *(u64 *)(r10 -136) + 1671: (61) r2 = *(u32 *)(r2 +0) + 1672: (63) *(u32 *)(r1 +0) = r2 + 1673: (b7) r0 = 1 + 1674: (95) exit <-- 1674 insns total + + 2) Every function as __attribute__ ((noinline)), rest + left unchanged: + + # ip -force link set dev lo xdp obj test_xdp_noinline.o sec xdp-test + # ip a + 1: lo: mtu 65536 xdpgeneric/id:236 qdisc noqueue state UNKNOWN group default qlen 1000 + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 + inet 127.0.0.1/8 scope host lo + valid_lft forever preferred_lft forever + inet6 ::1/128 scope host + valid_lft forever preferred_lft forever + [...] + # bpftool prog dump xlated id 236 + [...] + 1000: (bf) r1 = r6 + 1001: (b7) r2 = 24 + 1002: (85) call pc+3 <-- pc-relative call insns + 1003: (1f) r7 -= r0 + 1004: (bf) r0 = r7 + 1005: (95) exit + 1006: (bf) r0 = r1 + 1007: (bf) r1 = r2 + 1008: (67) r1 <<= 32 + 1009: (77) r1 >>= 32 + 1010: (bf) r3 = r0 + 1011: (6f) r3 <<= r1 + 1012: (87) r2 = -r2 + 1013: (57) r2 &= 31 + 1014: (67) r0 <<= 32 + 1015: (77) r0 >>= 32 + 1016: (7f) r0 >>= r2 + 1017: (4f) r0 |= r3 + 1018: (95) exit <-- 1018 insns total + + Signed-off-by: Daniel Borkmann + Signed-off-by: David Ahern +--- + lib/bpf.c | 233 ++++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 157 insertions(+), 76 deletions(-) + +diff --git a/lib/bpf.c b/lib/bpf.c +index ead8b5a7219f0..1b87490555050 100644 +--- a/lib/bpf.c ++++ b/lib/bpf.c +@@ -1109,7 +1109,8 @@ int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns, + #ifdef HAVE_ELF + struct bpf_elf_prog { + enum bpf_prog_type type; +- const struct bpf_insn *insns; ++ struct bpf_insn *insns; ++ unsigned int insns_num; + size_t size; + const char *license; + }; +@@ -1135,11 +1136,13 @@ struct bpf_elf_ctx { + int map_fds[ELF_MAX_MAPS]; + struct bpf_elf_map maps[ELF_MAX_MAPS]; + struct bpf_map_ext maps_ext[ELF_MAX_MAPS]; ++ struct bpf_elf_prog prog_text; + int sym_num; + int map_num; + int map_len; + bool *sec_done; + int sec_maps; ++ int sec_text; + char license[ELF_MAX_LICENSE_LEN]; + enum bpf_prog_type type; + __u32 ifindex; +@@ -1904,12 +1907,25 @@ static int bpf_fetch_strtab(struct bpf_elf_ctx *ctx, int section, + return 0; + } + ++static int bpf_fetch_text(struct bpf_elf_ctx *ctx, int section, ++ struct bpf_elf_sec_data *data) ++{ ++ ctx->sec_text = section; ++ ctx->sec_done[section] = true; ++ return 0; ++} ++ + static bool bpf_has_map_data(const struct bpf_elf_ctx *ctx) + { + return ctx->sym_tab && ctx->str_tab && ctx->sec_maps; + } + +-static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx) ++static bool bpf_has_call_data(const struct bpf_elf_ctx *ctx) ++{ ++ return ctx->sec_text; ++} ++ ++static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx, bool check_text_sec) + { + struct bpf_elf_sec_data data; + int i, ret = -1; +@@ -1925,6 +1941,11 @@ static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx) + else if (data.sec_hdr.sh_type == SHT_PROGBITS && + !strcmp(data.sec_name, ELF_SECTION_LICENSE)) + ret = bpf_fetch_license(ctx, i, &data); ++ else if (data.sec_hdr.sh_type == SHT_PROGBITS && ++ (data.sec_hdr.sh_flags & SHF_EXECINSTR) && ++ !strcmp(data.sec_name, ".text") && ++ check_text_sec) ++ ret = bpf_fetch_text(ctx, i, &data); + else if (data.sec_hdr.sh_type == SHT_SYMTAB && + !strcmp(data.sec_name, ".symtab")) + ret = bpf_fetch_symtab(ctx, i, &data); +@@ -1969,17 +1990,18 @@ static int bpf_fetch_prog(struct bpf_elf_ctx *ctx, const char *section, + ret = bpf_fill_section_data(ctx, i, &data); + if (ret < 0 || + !(data.sec_hdr.sh_type == SHT_PROGBITS && +- data.sec_hdr.sh_flags & SHF_EXECINSTR && ++ (data.sec_hdr.sh_flags & SHF_EXECINSTR) && + !strcmp(data.sec_name, section))) + continue; + + *sseen = true; + + memset(&prog, 0, sizeof(prog)); +- prog.type = ctx->type; +- prog.insns = data.sec_data->d_buf; +- prog.size = data.sec_data->d_size; +- prog.license = ctx->license; ++ prog.type = ctx->type; ++ prog.license = ctx->license; ++ prog.size = data.sec_data->d_size; ++ prog.insns_num = prog.size / sizeof(struct bpf_insn); ++ prog.insns = data.sec_data->d_buf; + + fd = bpf_prog_attach(section, &prog, ctx); + if (fd < 0) +@@ -1992,84 +2014,120 @@ static int bpf_fetch_prog(struct bpf_elf_ctx *ctx, const char *section, + return fd; + } + +-struct bpf_tail_call_props { +- unsigned int total; +- unsigned int jited; ++struct bpf_relo_props { ++ struct bpf_tail_call { ++ unsigned int total; ++ unsigned int jited; ++ } tc; ++ int main_num; + }; + ++static int bpf_apply_relo_map(struct bpf_elf_ctx *ctx, struct bpf_elf_prog *prog, ++ GElf_Rel *relo, GElf_Sym *sym, ++ struct bpf_relo_props *props) ++{ ++ unsigned int insn_off = relo->r_offset / sizeof(struct bpf_insn); ++ unsigned int map_idx = sym->st_value / ctx->map_len; ++ ++ if (insn_off >= prog->insns_num) ++ return -EINVAL; ++ if (prog->insns[insn_off].code != (BPF_LD | BPF_IMM | BPF_DW)) { ++ fprintf(stderr, "ELF contains relo data for non ld64 instruction at offset %u! Compiler bug?!\n", ++ insn_off); ++ return -EINVAL; ++ } ++ ++ if (map_idx >= ARRAY_SIZE(ctx->map_fds)) ++ return -EINVAL; ++ if (!ctx->map_fds[map_idx]) ++ return -EINVAL; ++ if (ctx->maps[map_idx].type == BPF_MAP_TYPE_PROG_ARRAY) { ++ props->tc.total++; ++ if (ctx->maps_ext[map_idx].owner.jited || ++ (ctx->maps_ext[map_idx].owner.type == 0 && ++ ctx->cfg.jit_enabled)) ++ props->tc.jited++; ++ } ++ ++ prog->insns[insn_off].src_reg = BPF_PSEUDO_MAP_FD; ++ prog->insns[insn_off].imm = ctx->map_fds[map_idx]; ++ return 0; ++} ++ ++static int bpf_apply_relo_call(struct bpf_elf_ctx *ctx, struct bpf_elf_prog *prog, ++ GElf_Rel *relo, GElf_Sym *sym, ++ struct bpf_relo_props *props) ++{ ++ unsigned int insn_off = relo->r_offset / sizeof(struct bpf_insn); ++ struct bpf_elf_prog *prog_text = &ctx->prog_text; ++ ++ if (insn_off >= prog->insns_num) ++ return -EINVAL; ++ if (prog->insns[insn_off].code != (BPF_JMP | BPF_CALL) && ++ prog->insns[insn_off].src_reg != BPF_PSEUDO_CALL) { ++ fprintf(stderr, "ELF contains relo data for non call instruction at offset %u! Compiler bug?!\n", ++ insn_off); ++ return -EINVAL; ++ } ++ ++ if (!props->main_num) { ++ struct bpf_insn *insns = realloc(prog->insns, ++ prog->size + prog_text->size); ++ if (!insns) ++ return -ENOMEM; ++ ++ memcpy(insns + prog->insns_num, prog_text->insns, ++ prog_text->size); ++ props->main_num = prog->insns_num; ++ prog->insns = insns; ++ prog->insns_num += prog_text->insns_num; ++ prog->size += prog_text->size; ++ } ++ ++ prog->insns[insn_off].imm += props->main_num - insn_off; ++ return 0; ++} ++ + static int bpf_apply_relo_data(struct bpf_elf_ctx *ctx, + struct bpf_elf_sec_data *data_relo, +- struct bpf_elf_sec_data *data_insn, +- struct bpf_tail_call_props *props) ++ struct bpf_elf_prog *prog, ++ struct bpf_relo_props *props) + { +- Elf_Data *idata = data_insn->sec_data; + GElf_Shdr *rhdr = &data_relo->sec_hdr; + int relo_ent, relo_num = rhdr->sh_size / rhdr->sh_entsize; +- struct bpf_insn *insns = idata->d_buf; +- unsigned int num_insns = idata->d_size / sizeof(*insns); + + for (relo_ent = 0; relo_ent < relo_num; relo_ent++) { +- unsigned int ioff, rmap; + GElf_Rel relo; + GElf_Sym sym; ++ int ret = -EIO; + + if (gelf_getrel(data_relo->sec_data, relo_ent, &relo) != &relo) + return -EIO; +- +- ioff = relo.r_offset / sizeof(struct bpf_insn); +- if (ioff >= num_insns || +- insns[ioff].code != (BPF_LD | BPF_IMM | BPF_DW)) { +- fprintf(stderr, "ELF contains relo data for non ld64 instruction at offset %u! Compiler bug?!\n", +- ioff); +- fprintf(stderr, " - Current section: %s\n", data_relo->sec_name); +- if (ioff < num_insns && +- insns[ioff].code == (BPF_JMP | BPF_CALL)) +- fprintf(stderr, " - Try to annotate functions with always_inline attribute!\n"); +- return -EINVAL; +- } +- + if (gelf_getsym(ctx->sym_tab, GELF_R_SYM(relo.r_info), &sym) != &sym) + return -EIO; +- if (sym.st_shndx != ctx->sec_maps) { +- fprintf(stderr, "ELF contains non-map related relo data in entry %u pointing to section %u! Compiler bug?!\n", +- relo_ent, sym.st_shndx); +- return -EIO; +- } + +- rmap = sym.st_value / ctx->map_len; +- if (rmap >= ARRAY_SIZE(ctx->map_fds)) +- return -EINVAL; +- if (!ctx->map_fds[rmap]) +- return -EINVAL; +- if (ctx->maps[rmap].type == BPF_MAP_TYPE_PROG_ARRAY) { +- props->total++; +- if (ctx->maps_ext[rmap].owner.jited || +- (ctx->maps_ext[rmap].owner.type == 0 && +- ctx->cfg.jit_enabled)) +- props->jited++; +- } +- +- if (ctx->verbose) +- fprintf(stderr, "Map \'%s\' (%d) injected into prog section \'%s\' at offset %u!\n", +- bpf_str_tab_name(ctx, &sym), ctx->map_fds[rmap], +- data_insn->sec_name, ioff); +- +- insns[ioff].src_reg = BPF_PSEUDO_MAP_FD; +- insns[ioff].imm = ctx->map_fds[rmap]; ++ if (sym.st_shndx == ctx->sec_maps) ++ ret = bpf_apply_relo_map(ctx, prog, &relo, &sym, props); ++ else if (sym.st_shndx == ctx->sec_text) ++ ret = bpf_apply_relo_call(ctx, prog, &relo, &sym, props); ++ else ++ fprintf(stderr, "ELF contains non-{map,call} related relo data in entry %u pointing to section %u! Compiler bug?!\n", ++ relo_ent, sym.st_shndx); ++ if (ret < 0) ++ return ret; + } + + return 0; + } + + static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section, +- bool *lderr, bool *sseen) ++ bool *lderr, bool *sseen, struct bpf_elf_prog *prog) + { + struct bpf_elf_sec_data data_relo, data_insn; +- struct bpf_elf_prog prog; + int ret, idx, i, fd = -1; + + for (i = 1; i < ctx->elf_hdr.e_shnum; i++) { +- struct bpf_tail_call_props props = {}; ++ struct bpf_relo_props props = {}; + + ret = bpf_fill_section_data(ctx, i, &data_relo); + if (ret < 0 || data_relo.sec_hdr.sh_type != SHT_REL) +@@ -2080,40 +2138,54 @@ static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section, + ret = bpf_fill_section_data(ctx, idx, &data_insn); + if (ret < 0 || + !(data_insn.sec_hdr.sh_type == SHT_PROGBITS && +- data_insn.sec_hdr.sh_flags & SHF_EXECINSTR && ++ (data_insn.sec_hdr.sh_flags & SHF_EXECINSTR) && + !strcmp(data_insn.sec_name, section))) + continue; ++ if (sseen) ++ *sseen = true; ++ ++ memset(prog, 0, sizeof(*prog)); ++ prog->type = ctx->type; ++ prog->license = ctx->license; ++ prog->size = data_insn.sec_data->d_size; ++ prog->insns_num = prog->size / sizeof(struct bpf_insn); ++ prog->insns = malloc(prog->size); ++ if (!prog->insns) { ++ *lderr = true; ++ return -ENOMEM; ++ } + +- *sseen = true; ++ memcpy(prog->insns, data_insn.sec_data->d_buf, prog->size); + +- ret = bpf_apply_relo_data(ctx, &data_relo, &data_insn, &props); ++ ret = bpf_apply_relo_data(ctx, &data_relo, prog, &props); + if (ret < 0) { + *lderr = true; ++ if (ctx->sec_text != idx) ++ free(prog->insns); + return ret; + } ++ if (ctx->sec_text == idx) { ++ fd = 0; ++ goto out; ++ } + +- memset(&prog, 0, sizeof(prog)); +- prog.type = ctx->type; +- prog.insns = data_insn.sec_data->d_buf; +- prog.size = data_insn.sec_data->d_size; +- prog.license = ctx->license; +- +- fd = bpf_prog_attach(section, &prog, ctx); ++ fd = bpf_prog_attach(section, prog, ctx); ++ free(prog->insns); + if (fd < 0) { + *lderr = true; +- if (props.total) { ++ if (props.tc.total) { + if (ctx->cfg.jit_enabled && +- props.total != props.jited) ++ props.tc.total != props.tc.jited) + fprintf(stderr, "JIT enabled, but only %u/%u tail call maps in the program have JITed owner!\n", +- props.jited, props.total); ++ props.tc.jited, props.tc.total); + if (!ctx->cfg.jit_enabled && +- props.jited) ++ props.tc.jited) + fprintf(stderr, "JIT disabled, but %u/%u tail call maps in the program have JITed owner!\n", +- props.jited, props.total); ++ props.tc.jited, props.tc.total); + } + return fd; + } +- ++out: + ctx->sec_done[i] = true; + ctx->sec_done[idx] = true; + break; +@@ -2125,10 +2197,18 @@ static int bpf_fetch_prog_relo(struct bpf_elf_ctx *ctx, const char *section, + static int bpf_fetch_prog_sec(struct bpf_elf_ctx *ctx, const char *section) + { + bool lderr = false, sseen = false; ++ struct bpf_elf_prog prog; + int ret = -1; + +- if (bpf_has_map_data(ctx)) +- ret = bpf_fetch_prog_relo(ctx, section, &lderr, &sseen); ++ if (bpf_has_call_data(ctx)) { ++ ret = bpf_fetch_prog_relo(ctx, ".text", &lderr, NULL, ++ &ctx->prog_text); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (bpf_has_map_data(ctx) || bpf_has_call_data(ctx)) ++ ret = bpf_fetch_prog_relo(ctx, section, &lderr, &sseen, &prog); + if (ret < 0 && !lderr) + ret = bpf_fetch_prog(ctx, section, &sseen); + if (ret < 0 && !sseen) +@@ -2525,6 +2605,7 @@ static void bpf_elf_ctx_destroy(struct bpf_elf_ctx *ctx, bool failure) + + bpf_hash_destroy(ctx); + ++ free(ctx->prog_text.insns); + free(ctx->sec_done); + free(ctx->log); + +@@ -2546,7 +2627,7 @@ static int bpf_obj_open(const char *pathname, enum bpf_prog_type type, + return ret; + } + +- ret = bpf_fetch_ancillary(ctx); ++ ret = bpf_fetch_ancillary(ctx, strcmp(section, ".text")); + if (ret < 0) { + fprintf(stderr, "Error fetching ELF ancillary data!\n"); + goto out; +-- +2.20.1 + diff --git a/SOURCES/0059-bpf-implement-btf-handling-and-map-annotation.patch b/SOURCES/0059-bpf-implement-btf-handling-and-map-annotation.patch new file mode 100644 index 0000000..d03774e --- /dev/null +++ b/SOURCES/0059-bpf-implement-btf-handling-and-map-annotation.patch @@ -0,0 +1,624 @@ +From e8386c4e1fa3b5486487fa4d6c350a0d5e300aaf Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:56 +0200 +Subject: [PATCH] bpf: implement btf handling and map annotation + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit f823f36012fb5 + +commit f823f36012fb5ab4ddfca6ed4ff56188730f281e +Author: Daniel Borkmann +Date: Wed Jul 18 01:31:22 2018 +0200 + + bpf: implement btf handling and map annotation + + Implement loading of .BTF section from object file and build up + internal table for retrieving key/value id related to maps in + the BPF program. Latter is done by setting up struct btf_type + table. + + One of the issues is that there's a disconnect between the data + types used in the map and struct bpf_elf_map, meaning the underlying + types are unknown from the map description. One way to overcome + this is to add a annotation such that the loader will recognize + the relation to both. BPF_ANNOTATE_KV_PAIR(map_foo, struct key, + struct val); has been added to the API that programs can use. + + The loader will then pick the corresponding key/value type ids and + attach it to the maps for creation. This can later on be dumped via + bpftool for introspection. + + Example with test_xdp_noinline.o from kernel selftests: + + [...] + + struct ctl_value { + union { + __u64 value; + __u32 ifindex; + __u8 mac[6]; + }; + }; + + struct bpf_map_def __attribute__ ((section("maps"), used)) ctl_array = { + .type = BPF_MAP_TYPE_ARRAY, + .key_size = sizeof(__u32), + .value_size = sizeof(struct ctl_value), + .max_entries = 16, + .map_flags = 0, + }; + BPF_ANNOTATE_KV_PAIR(ctl_array, __u32, struct ctl_value); + + [...] + + Above could also further be wrapped in a macro. Compiling through LLVM and + converting to BTF: + + # llc --version + LLVM (http://llvm.org/): + LLVM version 7.0.0svn + Optimized build. + Default target: x86_64-unknown-linux-gnu + Host CPU: skylake + + Registered Targets: + bpf - BPF (host endian) + bpfeb - BPF (big endian) + bpfel - BPF (little endian) + [...] + + # clang [...] -O2 -target bpf -g -emit-llvm -c test_xdp_noinline.c -o - | + llc -march=bpf -mcpu=probe -mattr=dwarfris -filetype=obj -o test_xdp_noinline.o + # pahole -J test_xdp_noinline.o + + Checking pahole dump of BPF object file: + + # file test_xdp_noinline.o + test_xdp_noinline.o: ELF 64-bit LSB relocatable, *unknown arch 0xf7* version 1 (SYSV), with debug_info, not stripped + # pahole test_xdp_noinline.o + [...] + struct ctl_value { + union { + __u64 value; /* 0 8 */ + __u32 ifindex; /* 0 4 */ + __u8 mac[0]; /* 0 0 */ + }; /* 0 8 */ + + /* size: 8, cachelines: 1, members: 1 */ + /* last cacheline: 8 bytes */ + }; + + Now loading into kernel and dumping the map via bpftool: + + # ip -force link set dev lo xdp obj test_xdp_noinline.o sec xdp-test + # ip a + 1: lo: mtu 65536 xdpgeneric/id:227 qdisc noqueue state UNKNOWN group default qlen 1000 + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 + inet 127.0.0.1/8 scope host lo + valid_lft forever preferred_lft forever + inet6 ::1/128 scope host + valid_lft forever preferred_lft forever + [...] + # bpftool prog show id 227 + 227: xdp tag a85e060c275c5616 gpl + loaded_at 2018-07-17T14:41:29+0000 uid 0 + xlated 8152B not jited memlock 12288B map_ids 381,385,386,382,384,383 + # bpftool map dump id 386 + [{ + "key": 0, + "value": { + "": { + "value": 0, + "ifindex": 0, + "mac": [] + } + } + },{ + "key": 1, + "value": { + "": { + "value": 0, + "ifindex": 0, + "mac": [] + } + } + },{ + [...] + + Signed-off-by: Daniel Borkmann + Signed-off-by: David Ahern +--- + include/bpf_elf.h | 9 ++ + include/bpf_util.h | 1 + + lib/bpf.c | 332 ++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 338 insertions(+), 4 deletions(-) + +diff --git a/include/bpf_elf.h b/include/bpf_elf.h +index a8e360f3bbb28..84e8ae00834c8 100644 +--- a/include/bpf_elf.h ++++ b/include/bpf_elf.h +@@ -41,4 +41,13 @@ struct bpf_elf_map { + __u32 inner_idx; + }; + ++#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \ ++ struct ____btf_map_##name { \ ++ type_key key; \ ++ type_val value; \ ++ }; \ ++ struct ____btf_map_##name \ ++ __attribute__ ((section(".maps." #name), used)) \ ++ ____btf_map_##name = { } ++ + #endif /* __BPF_ELF__ */ +diff --git a/include/bpf_util.h b/include/bpf_util.h +index 219beb40cd253..63837a04e56fe 100644 +--- a/include/bpf_util.h ++++ b/include/bpf_util.h +@@ -14,6 +14,7 @@ + #define __BPF_UTIL__ + + #include ++#include + #include + #include + #include +diff --git a/lib/bpf.c b/lib/bpf.c +index 1b87490555050..d093d0bd86eae 100644 +--- a/lib/bpf.c ++++ b/lib/bpf.c +@@ -393,6 +393,8 @@ struct bpf_prog_data { + + struct bpf_map_ext { + struct bpf_prog_data owner; ++ unsigned int btf_id_key; ++ unsigned int btf_id_val; + }; + + static int bpf_derive_elf_map_from_fdinfo(int fd, struct bpf_elf_map *map, +@@ -1125,24 +1127,36 @@ struct bpf_config { + unsigned int jit_enabled; + }; + ++struct bpf_btf { ++ const struct btf_header *hdr; ++ const void *raw; ++ const char *strings; ++ const struct btf_type **types; ++ int types_num; ++}; ++ + struct bpf_elf_ctx { + struct bpf_config cfg; + Elf *elf_fd; + GElf_Ehdr elf_hdr; + Elf_Data *sym_tab; + Elf_Data *str_tab; ++ Elf_Data *btf_data; + char obj_uid[64]; + int obj_fd; ++ int btf_fd; + int map_fds[ELF_MAX_MAPS]; + struct bpf_elf_map maps[ELF_MAX_MAPS]; + struct bpf_map_ext maps_ext[ELF_MAX_MAPS]; + struct bpf_elf_prog prog_text; ++ struct bpf_btf btf; + int sym_num; + int map_num; + int map_len; + bool *sec_done; + int sec_maps; + int sec_text; ++ int sec_btf; + char license[ELF_MAX_LICENSE_LEN]; + enum bpf_prog_type type; + __u32 ifindex; +@@ -1167,6 +1181,11 @@ struct bpf_map_data { + struct bpf_elf_map *ent; + }; + ++static bool bpf_log_has_data(struct bpf_elf_ctx *ctx) ++{ ++ return ctx->log && ctx->log[0]; ++} ++ + static __check_format_string(2, 3) void + bpf_dump_error(struct bpf_elf_ctx *ctx, const char *format, ...) + { +@@ -1176,7 +1195,7 @@ bpf_dump_error(struct bpf_elf_ctx *ctx, const char *format, ...) + vfprintf(stderr, format, vl); + va_end(vl); + +- if (ctx->log && ctx->log[0]) { ++ if (bpf_log_has_data(ctx)) { + if (ctx->verbose) { + fprintf(stderr, "%s\n", ctx->log); + } else { +@@ -1223,7 +1242,9 @@ static int bpf_log_realloc(struct bpf_elf_ctx *ctx) + + static int bpf_map_create(enum bpf_map_type type, uint32_t size_key, + uint32_t size_value, uint32_t max_elem, +- uint32_t flags, int inner_fd, uint32_t ifindex) ++ uint32_t flags, int inner_fd, int btf_fd, ++ uint32_t ifindex, uint32_t btf_id_key, ++ uint32_t btf_id_val) + { + union bpf_attr attr = {}; + +@@ -1234,10 +1255,30 @@ static int bpf_map_create(enum bpf_map_type type, uint32_t size_key, + attr.map_flags = flags; + attr.inner_map_fd = inner_fd; + attr.map_ifindex = ifindex; ++ attr.btf_fd = btf_fd; ++ attr.btf_key_type_id = btf_id_key; ++ attr.btf_value_type_id = btf_id_val; + + return bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); + } + ++static int bpf_btf_load(void *btf, size_t size_btf, ++ char *log, size_t size_log) ++{ ++ union bpf_attr attr = {}; ++ ++ attr.btf = bpf_ptr_to_u64(btf); ++ attr.btf_size = size_btf; ++ ++ if (size_log > 0) { ++ attr.btf_log_buf = bpf_ptr_to_u64(log); ++ attr.btf_log_size = size_log; ++ attr.btf_log_level = 1; ++ } ++ ++ return bpf(BPF_BTF_LOAD, &attr, sizeof(attr)); ++} ++ + static int bpf_obj_pin(int fd, const char *pathname) + { + union bpf_attr attr = {}; +@@ -1613,7 +1654,8 @@ static int bpf_map_attach(const char *name, struct bpf_elf_ctx *ctx, + ifindex = bpf_map_offload_neutral(map->type) ? 0 : ctx->ifindex; + errno = 0; + fd = bpf_map_create(map->type, map->size_key, map->size_value, +- map->max_elem, map->flags, map_inner_fd, ifindex); ++ map->max_elem, map->flags, map_inner_fd, ctx->btf_fd, ++ ifindex, ext->btf_id_key, ext->btf_id_val); + + if (fd < 0 || ctx->verbose) { + bpf_map_report(fd, name, map, ctx, map_inner_fd); +@@ -1638,8 +1680,80 @@ static const char *bpf_str_tab_name(const struct bpf_elf_ctx *ctx, + return ctx->str_tab->d_buf + sym->st_name; + } + ++static int bpf_btf_find(struct bpf_elf_ctx *ctx, const char *name) ++{ ++ const struct btf_type *type; ++ const char *res; ++ int id; ++ ++ for (id = 1; id < ctx->btf.types_num; id++) { ++ type = ctx->btf.types[id]; ++ if (type->name_off >= ctx->btf.hdr->str_len) ++ continue; ++ res = &ctx->btf.strings[type->name_off]; ++ if (!strcmp(res, name)) ++ return id; ++ } ++ ++ return -ENOENT; ++} ++ ++static int bpf_btf_find_kv(struct bpf_elf_ctx *ctx, const struct bpf_elf_map *map, ++ const char *name, uint32_t *id_key, uint32_t *id_val) ++{ ++ const struct btf_member *key, *val; ++ const struct btf_type *type; ++ char btf_name[512]; ++ const char *res; ++ int id; ++ ++ snprintf(btf_name, sizeof(btf_name), "____btf_map_%s", name); ++ id = bpf_btf_find(ctx, btf_name); ++ if (id < 0) ++ return id; ++ ++ type = ctx->btf.types[id]; ++ if (BTF_INFO_KIND(type->info) != BTF_KIND_STRUCT) ++ return -EINVAL; ++ if (BTF_INFO_VLEN(type->info) != 2) ++ return -EINVAL; ++ ++ key = ((void *) type) + sizeof(*type); ++ val = key + 1; ++ if (!key->type || key->type >= ctx->btf.types_num || ++ !val->type || val->type >= ctx->btf.types_num) ++ return -EINVAL; ++ ++ if (key->name_off >= ctx->btf.hdr->str_len || ++ val->name_off >= ctx->btf.hdr->str_len) ++ return -EINVAL; ++ ++ res = &ctx->btf.strings[key->name_off]; ++ if (strcmp(res, "key")) ++ return -EINVAL; ++ ++ res = &ctx->btf.strings[val->name_off]; ++ if (strcmp(res, "value")) ++ return -EINVAL; ++ ++ *id_key = key->type; ++ *id_val = val->type; ++ return 0; ++} ++ ++static void bpf_btf_annotate(struct bpf_elf_ctx *ctx, int which, const char *name) ++{ ++ uint32_t id_key = 0, id_val = 0; ++ ++ if (!bpf_btf_find_kv(ctx, &ctx->maps[which], name, &id_key, &id_val)) { ++ ctx->maps_ext[which].btf_id_key = id_key; ++ ctx->maps_ext[which].btf_id_val = id_val; ++ } ++} ++ + static const char *bpf_map_fetch_name(struct bpf_elf_ctx *ctx, int which) + { ++ const char *name; + GElf_Sym sym; + int i; + +@@ -1653,7 +1767,9 @@ static const char *bpf_map_fetch_name(struct bpf_elf_ctx *ctx, int which) + sym.st_value / ctx->map_len != which) + continue; + +- return bpf_str_tab_name(ctx, &sym); ++ name = bpf_str_tab_name(ctx, &sym); ++ bpf_btf_annotate(ctx, which, name); ++ return name; + } + + return NULL; +@@ -1915,11 +2031,210 @@ static int bpf_fetch_text(struct bpf_elf_ctx *ctx, int section, + return 0; + } + ++static void bpf_btf_report(int fd, struct bpf_elf_ctx *ctx) ++{ ++ fprintf(stderr, "\nBTF debug data section \'.BTF\' %s%s (%d)!\n", ++ fd < 0 ? "rejected: " : "loaded", ++ fd < 0 ? strerror(errno) : "", ++ fd < 0 ? errno : fd); ++ ++ fprintf(stderr, " - Length: %zu\n", ctx->btf_data->d_size); ++ ++ bpf_dump_error(ctx, "Verifier analysis:\n\n"); ++} ++ ++static int bpf_btf_attach(struct bpf_elf_ctx *ctx) ++{ ++ int tries = 0, fd; ++retry: ++ errno = 0; ++ fd = bpf_btf_load(ctx->btf_data->d_buf, ctx->btf_data->d_size, ++ ctx->log, ctx->log_size); ++ if (fd < 0 || ctx->verbose) { ++ if (fd < 0 && (errno == ENOSPC || !ctx->log_size)) { ++ if (tries++ < 10 && !bpf_log_realloc(ctx)) ++ goto retry; ++ ++ fprintf(stderr, "Log buffer too small to dump verifier log %zu bytes (%d tries)!\n", ++ ctx->log_size, tries); ++ return fd; ++ } ++ ++ if (bpf_log_has_data(ctx)) ++ bpf_btf_report(fd, ctx); ++ } ++ ++ return fd; ++} ++ ++static int bpf_fetch_btf_begin(struct bpf_elf_ctx *ctx, int section, ++ struct bpf_elf_sec_data *data) ++{ ++ ctx->btf_data = data->sec_data; ++ ctx->sec_btf = section; ++ ctx->sec_done[section] = true; ++ return 0; ++} ++ ++static int bpf_btf_check_header(struct bpf_elf_ctx *ctx) ++{ ++ const struct btf_header *hdr = ctx->btf_data->d_buf; ++ const char *str_start, *str_end; ++ unsigned int data_len; ++ ++ if (hdr->magic != BTF_MAGIC) { ++ fprintf(stderr, "Object has wrong BTF magic: %x, expected: %x!\n", ++ hdr->magic, BTF_MAGIC); ++ return -EINVAL; ++ } ++ ++ if (hdr->version != BTF_VERSION) { ++ fprintf(stderr, "Object has wrong BTF version: %u, expected: %u!\n", ++ hdr->version, BTF_VERSION); ++ return -EINVAL; ++ } ++ ++ if (hdr->flags) { ++ fprintf(stderr, "Object has unsupported BTF flags %x!\n", ++ hdr->flags); ++ return -EINVAL; ++ } ++ ++ data_len = ctx->btf_data->d_size - sizeof(*hdr); ++ if (data_len < hdr->type_off || ++ data_len < hdr->str_off || ++ data_len < hdr->type_len + hdr->str_len || ++ hdr->type_off >= hdr->str_off || ++ hdr->type_off + hdr->type_len != hdr->str_off || ++ hdr->str_off + hdr->str_len != data_len || ++ (hdr->type_off & (sizeof(uint32_t) - 1))) { ++ fprintf(stderr, "Object has malformed BTF data!\n"); ++ return -EINVAL; ++ } ++ ++ ctx->btf.hdr = hdr; ++ ctx->btf.raw = hdr + 1; ++ ++ str_start = ctx->btf.raw + hdr->str_off; ++ str_end = str_start + hdr->str_len; ++ if (!hdr->str_len || ++ hdr->str_len - 1 > BTF_MAX_NAME_OFFSET || ++ str_start[0] || str_end[-1]) { ++ fprintf(stderr, "Object has malformed BTF string data!\n"); ++ return -EINVAL; ++ } ++ ++ ctx->btf.strings = str_start; ++ return 0; ++} ++ ++static int bpf_btf_register_type(struct bpf_elf_ctx *ctx, ++ const struct btf_type *type) ++{ ++ int cur = ctx->btf.types_num, num = cur + 1; ++ const struct btf_type **types; ++ ++ types = realloc(ctx->btf.types, num * sizeof(type)); ++ if (!types) { ++ free(ctx->btf.types); ++ ctx->btf.types = NULL; ++ ctx->btf.types_num = 0; ++ return -ENOMEM; ++ } ++ ++ ctx->btf.types = types; ++ ctx->btf.types[cur] = type; ++ ctx->btf.types_num = num; ++ return 0; ++} ++ ++static struct btf_type btf_type_void; ++ ++static int bpf_btf_prep_type_data(struct bpf_elf_ctx *ctx) ++{ ++ const void *type_cur = ctx->btf.raw + ctx->btf.hdr->type_off; ++ const void *type_end = ctx->btf.raw + ctx->btf.hdr->str_off; ++ const struct btf_type *type; ++ uint16_t var_len; ++ int ret, kind; ++ ++ ret = bpf_btf_register_type(ctx, &btf_type_void); ++ if (ret < 0) ++ return ret; ++ ++ while (type_cur < type_end) { ++ type = type_cur; ++ type_cur += sizeof(*type); ++ ++ var_len = BTF_INFO_VLEN(type->info); ++ kind = BTF_INFO_KIND(type->info); ++ ++ switch (kind) { ++ case BTF_KIND_INT: ++ type_cur += sizeof(int); ++ break; ++ case BTF_KIND_ARRAY: ++ type_cur += sizeof(struct btf_array); ++ break; ++ case BTF_KIND_STRUCT: ++ case BTF_KIND_UNION: ++ type_cur += var_len * sizeof(struct btf_member); ++ break; ++ case BTF_KIND_ENUM: ++ type_cur += var_len * sizeof(struct btf_enum); ++ break; ++ case BTF_KIND_TYPEDEF: ++ case BTF_KIND_PTR: ++ case BTF_KIND_FWD: ++ case BTF_KIND_VOLATILE: ++ case BTF_KIND_CONST: ++ case BTF_KIND_RESTRICT: ++ break; ++ default: ++ fprintf(stderr, "Object has unknown BTF type: %u!\n", kind); ++ return -EINVAL; ++ } ++ ++ ret = bpf_btf_register_type(ctx, type); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int bpf_btf_prep_data(struct bpf_elf_ctx *ctx) ++{ ++ int ret = bpf_btf_check_header(ctx); ++ ++ if (!ret) ++ return bpf_btf_prep_type_data(ctx); ++ return ret; ++} ++ ++static void bpf_fetch_btf_end(struct bpf_elf_ctx *ctx) ++{ ++ int fd = bpf_btf_attach(ctx); ++ ++ if (fd < 0) ++ return; ++ ctx->btf_fd = fd; ++ if (bpf_btf_prep_data(ctx) < 0) { ++ close(ctx->btf_fd); ++ ctx->btf_fd = 0; ++ } ++} ++ + static bool bpf_has_map_data(const struct bpf_elf_ctx *ctx) + { + return ctx->sym_tab && ctx->str_tab && ctx->sec_maps; + } + ++static bool bpf_has_btf_data(const struct bpf_elf_ctx *ctx) ++{ ++ return ctx->sec_btf; ++} ++ + static bool bpf_has_call_data(const struct bpf_elf_ctx *ctx) + { + return ctx->sec_text; +@@ -1952,6 +2267,9 @@ static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx, bool check_text_sec) + else if (data.sec_hdr.sh_type == SHT_STRTAB && + !strcmp(data.sec_name, ".strtab")) + ret = bpf_fetch_strtab(ctx, i, &data); ++ else if (data.sec_hdr.sh_type == SHT_PROGBITS && ++ !strcmp(data.sec_name, ".BTF")) ++ ret = bpf_fetch_btf_begin(ctx, i, &data); + if (ret < 0) { + fprintf(stderr, "Error parsing section %d! Perhaps check with readelf -a?\n", + i); +@@ -1959,6 +2277,8 @@ static int bpf_fetch_ancillary(struct bpf_elf_ctx *ctx, bool check_text_sec) + } + } + ++ if (bpf_has_btf_data(ctx)) ++ bpf_fetch_btf_end(ctx); + if (bpf_has_map_data(ctx)) { + ret = bpf_fetch_maps_end(ctx); + if (ret < 0) { +@@ -2596,6 +2916,10 @@ static void bpf_maps_teardown(struct bpf_elf_ctx *ctx) + if (ctx->map_fds[i]) + close(ctx->map_fds[i]); + } ++ ++ if (ctx->btf_fd) ++ close(ctx->btf_fd); ++ free(ctx->btf.types); + } + + static void bpf_elf_ctx_destroy(struct bpf_elf_ctx *ctx, bool failure) +-- +2.20.1 + diff --git a/SOURCES/0060-bpf-check-map-symbol-type-properly-with-newer-llvm-c.patch b/SOURCES/0060-bpf-check-map-symbol-type-properly-with-newer-llvm-c.patch new file mode 100644 index 0000000..215fe51 --- /dev/null +++ b/SOURCES/0060-bpf-check-map-symbol-type-properly-with-newer-llvm-c.patch @@ -0,0 +1,113 @@ +From 9783e8b3de077c2e6399a9aa83f93237690bd744 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:57 +0200 +Subject: [PATCH] bpf: check map symbol type properly with newer llvm compiler + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit 7a04dd84a7f93 + +commit 7a04dd84a7f938f72fcef9efe8383314b0a66274 +Author: Yonghong Song +Date: Mon Oct 29 15:32:03 2018 -0700 + + bpf: check map symbol type properly with newer llvm compiler + + With llvm 7.0 or earlier, the map symbol type is STT_NOTYPE. + -bash-4.4$ cat t.c + __attribute__((section("maps"))) int g; + -bash-4.4$ clang -target bpf -O2 -c t.c + -bash-4.4$ readelf -s t.o + + Symbol table '.symtab' contains 2 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND + 1: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 3 g + + The following llvm commit enables BPF target to generate + proper symbol type and size. + commit bf6ec206615b9718869d48b4e5400d0c6e3638dd + Author: Yonghong Song + Date: Wed Sep 19 16:04:13 2018 +0000 + + [bpf] Symbol sizes and types in object file + + Clang-compiled object files currently don't include the symbol sizes and + types. Some tools however need that information. For example, ctfconvert + uses that information to generate FreeBSD's CTF representation from ELF + files. + With this patch, symbol sizes and types are included in object files. + + Signed-off-by: Paul Chaignon + Reported-by: Yutaro Hayakawa + + Hence, for llvm 8.0.0 (currently trunk), symbol type will be not NOTYPE, but OBJECT. + -bash-4.4$ clang -target bpf -O2 -c t.c + -bash-4.4$ readelf -s t.o + + Symbol table '.symtab' contains 3 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND + 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS t.c + 2: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 g + + This patch makes sure bpf library accepts both NOTYPE and OBJECT types + of global map symbols. + + Signed-off-by: Yonghong Song + Acked-by: Daniel Borkmann + Signed-off-by: Stephen Hemminger +--- + lib/bpf.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/lib/bpf.c b/lib/bpf.c +index d093d0bd86eae..45f279fa4a416 100644 +--- a/lib/bpf.c ++++ b/lib/bpf.c +@@ -1758,11 +1758,13 @@ static const char *bpf_map_fetch_name(struct bpf_elf_ctx *ctx, int which) + int i; + + for (i = 0; i < ctx->sym_num; i++) { ++ int type = GELF_ST_TYPE(sym.st_info); ++ + if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym) + continue; + + if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL || +- GELF_ST_TYPE(sym.st_info) != STT_NOTYPE || ++ (type != STT_NOTYPE && type != STT_OBJECT) || + sym.st_shndx != ctx->sec_maps || + sym.st_value / ctx->map_len != which) + continue; +@@ -1849,11 +1851,13 @@ static int bpf_map_num_sym(struct bpf_elf_ctx *ctx) + GElf_Sym sym; + + for (i = 0; i < ctx->sym_num; i++) { ++ int type = GELF_ST_TYPE(sym.st_info); ++ + if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym) + continue; + + if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL || +- GELF_ST_TYPE(sym.st_info) != STT_NOTYPE || ++ (type != STT_NOTYPE && type != STT_OBJECT) || + sym.st_shndx != ctx->sec_maps) + continue; + num++; +@@ -1927,10 +1931,12 @@ static int bpf_map_verify_all_offs(struct bpf_elf_ctx *ctx, int end) + * the table again. + */ + for (i = 0; i < ctx->sym_num; i++) { ++ int type = GELF_ST_TYPE(sym.st_info); ++ + if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym) + continue; + if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL || +- GELF_ST_TYPE(sym.st_info) != STT_NOTYPE || ++ (type != STT_NOTYPE && type != STT_OBJECT) || + sym.st_shndx != ctx->sec_maps) + continue; + if (sym.st_value == off) +-- +2.20.1 + diff --git a/SOURCES/0061-Use-libbsd-for-strlcpy-if-available.patch b/SOURCES/0061-Use-libbsd-for-strlcpy-if-available.patch new file mode 100644 index 0000000..6cb418c --- /dev/null +++ b/SOURCES/0061-Use-libbsd-for-strlcpy-if-available.patch @@ -0,0 +1,258 @@ +From d3153cc39f5dca57e2cfc2faaefc690f64af398f Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:57 +0200 +Subject: [PATCH] Use libbsd for strlcpy if available + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit 508f3c231efb1 + +commit 508f3c231efb179fb842d222e8151b395937b136 +Author: Luca Boccassi +Date: Wed Oct 31 18:00:11 2018 +0000 + + Use libbsd for strlcpy if available + + If libc does not provide strlcpy check for libbsd with pkg-config to + avoid relying on inline version. + + Signed-off-by: Luca Boccassi + Signed-off-by: Stephen Hemminger +--- + configure | 11 +++++++++-- + genl/ctrl.c | 3 +++ + ip/iplink.c | 3 +++ + ip/ipnetns.c | 3 +++ + ip/iproute_lwtunnel.c | 3 +++ + ip/ipvrf.c | 3 +++ + ip/ipxfrm.c | 3 +++ + ip/tunnel.c | 3 +++ + ip/xfrm_state.c | 3 +++ + lib/bpf.c | 3 +++ + lib/fs.c | 3 +++ + lib/inet_proto.c | 3 +++ + misc/ss.c | 3 +++ + tc/em_ipset.c | 3 +++ + tc/m_pedit.c | 3 +++ + 15 files changed, 51 insertions(+), 2 deletions(-) + +diff --git a/configure b/configure +index 5ef5cd4cf9cde..07c18f9bda4a2 100755 +--- a/configure ++++ b/configure +@@ -330,8 +330,15 @@ EOF + then + echo "no" + else +- echo 'CFLAGS += -DNEED_STRLCPY' >>$CONFIG +- echo "yes" ++ if ${PKG_CONFIG} libbsd --exists ++ then ++ echo 'CFLAGS += -DHAVE_LIBBSD' `${PKG_CONFIG} libbsd --cflags` >>$CONFIG ++ echo 'LDLIBS +=' `${PKG_CONFIG} libbsd --libs` >> $CONFIG ++ echo "no" ++ else ++ echo 'CFLAGS += -DNEED_STRLCPY' >>$CONFIG ++ echo "yes" ++ fi + fi + rm -f $TMPDIR/strtest.c $TMPDIR/strtest + } +diff --git a/genl/ctrl.c b/genl/ctrl.c +index 0d9c5f2517b78..4063ec0ba474b 100644 +--- a/genl/ctrl.c ++++ b/genl/ctrl.c +@@ -18,6 +18,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + + #include "utils.h" + #include "genl_utils.h" +diff --git a/ip/iplink.c b/ip/iplink.c +index 0ba5f1af76697..2f8f3bf1f84bb 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -24,6 +24,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + #include + #include + #include +diff --git a/ip/ipnetns.c b/ip/ipnetns.c +index 368be0cbc0a48..5991592e947b6 100644 +--- a/ip/ipnetns.c ++++ b/ip/ipnetns.c +@@ -8,6 +8,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + #include + #include + #include +diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c +index 388cd19a3ef0b..be9f60c3b2137 100644 +--- a/ip/iproute_lwtunnel.c ++++ b/ip/iproute_lwtunnel.c +@@ -16,6 +16,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + #include + #include + #include +diff --git a/ip/ipvrf.c b/ip/ipvrf.c +index 8a6b7f977b142..8572b4f23e3dc 100644 +--- a/ip/ipvrf.c ++++ b/ip/ipvrf.c +@@ -21,6 +21,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + #include + #include + #include +diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c +index 12c2f721571b6..5304dfc1af906 100644 +--- a/ip/ipxfrm.c ++++ b/ip/ipxfrm.c +@@ -28,6 +28,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + #include + #include + #include +diff --git a/ip/tunnel.c b/ip/tunnel.c +index 79de7f2406f0e..d54505d483d22 100644 +--- a/ip/tunnel.c ++++ b/ip/tunnel.c +@@ -24,6 +24,9 @@ + + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + #include + #include + #include +diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c +index 85d959cc4f44f..0c8df7e6e10cd 100644 +--- a/ip/xfrm_state.c ++++ b/ip/xfrm_state.c +@@ -27,6 +27,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + #include + #include "utils.h" + #include "xfrm.h" +diff --git a/lib/bpf.c b/lib/bpf.c +index 45f279fa4a416..35d7c45a2924d 100644 +--- a/lib/bpf.c ++++ b/lib/bpf.c +@@ -15,6 +15,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + #include + #include + #include +diff --git a/lib/fs.c b/lib/fs.c +index 86efd4ed2ed80..af36bea0987fa 100644 +--- a/lib/fs.c ++++ b/lib/fs.c +@@ -20,6 +20,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + #include + #include + +diff --git a/lib/inet_proto.c b/lib/inet_proto.c +index 0836a4c96a0b4..b379d8f8e720e 100644 +--- a/lib/inet_proto.c ++++ b/lib/inet_proto.c +@@ -18,6 +18,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + + #include "rt_names.h" + #include "utils.h" +diff --git a/misc/ss.c b/misc/ss.c +index 41e7762bb61f5..7e94f2c8d1baa 100644 +--- a/misc/ss.c ++++ b/misc/ss.c +@@ -18,6 +18,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + #include + #include + #include +diff --git a/tc/em_ipset.c b/tc/em_ipset.c +index 48b287f5ba3b2..550b2101a0579 100644 +--- a/tc/em_ipset.c ++++ b/tc/em_ipset.c +@@ -20,6 +20,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + #include + #include + +diff --git a/tc/m_pedit.c b/tc/m_pedit.c +index 2aeb56d9615f1..baacc80dd94b7 100644 +--- a/tc/m_pedit.c ++++ b/tc/m_pedit.c +@@ -23,6 +23,9 @@ + #include + #include + #include ++#ifdef HAVE_LIBBSD ++#include ++#endif + #include + #include "utils.h" + #include "tc_util.h" +-- +2.20.1 + diff --git a/SOURCES/0062-Include-bsd-string.h-only-in-include-utils.h.patch b/SOURCES/0062-Include-bsd-string.h-only-in-include-utils.h.patch new file mode 100644 index 0000000..245f113 --- /dev/null +++ b/SOURCES/0062-Include-bsd-string.h-only-in-include-utils.h.patch @@ -0,0 +1,255 @@ +From f416b73a7f47494cf6d18cdaad5e86709bc43a63 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:57 +0200 +Subject: [PATCH] Include bsd/string.h only in include/utils.h + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit 6d2fd4a53f63b + +commit 6d2fd4a53f63bd20667b1a8f2ec8fde1fc3a54d4 +Author: Luca Boccassi +Date: Thu Nov 1 22:25:27 2018 +0000 + + Include bsd/string.h only in include/utils.h + + This is simpler and cleaner, and avoids having to include the header + from every file where the functions are used. The prototypes of the + internal implementation are in this header, so utils.h will have to be + included anyway for those. + + Fixes: 508f3c231efb ("Use libbsd for strlcpy if available") + + Signed-off-by: Luca Boccassi + Signed-off-by: Stephen Hemminger +--- + genl/ctrl.c | 3 --- + include/utils.h | 4 ++++ + ip/iplink.c | 3 --- + ip/ipnetns.c | 3 --- + ip/iproute_lwtunnel.c | 3 --- + ip/ipvrf.c | 3 --- + ip/ipxfrm.c | 3 --- + ip/tunnel.c | 3 --- + ip/xfrm_state.c | 3 --- + lib/bpf.c | 3 --- + lib/fs.c | 3 --- + lib/inet_proto.c | 3 --- + misc/ss.c | 3 --- + tc/em_ipset.c | 3 --- + tc/m_pedit.c | 3 --- + 15 files changed, 4 insertions(+), 42 deletions(-) + +diff --git a/genl/ctrl.c b/genl/ctrl.c +index 4063ec0ba474b..0d9c5f2517b78 100644 +--- a/genl/ctrl.c ++++ b/genl/ctrl.c +@@ -18,9 +18,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + + #include "utils.h" + #include "genl_utils.h" +diff --git a/include/utils.h b/include/utils.h +index 8cb4349e8a89f..c32b37a1797d8 100644 +--- a/include/utils.h ++++ b/include/utils.h +@@ -9,6 +9,10 @@ + #include + #include + ++#ifdef HAVE_LIBBSD ++#include ++#endif ++ + #include "libnetlink.h" + #include "ll_map.h" + #include "rtm_map.h" +diff --git a/ip/iplink.c b/ip/iplink.c +index 2f8f3bf1f84bb..0ba5f1af76697 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -24,9 +24,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + #include + #include + #include +diff --git a/ip/ipnetns.c b/ip/ipnetns.c +index 5991592e947b6..368be0cbc0a48 100644 +--- a/ip/ipnetns.c ++++ b/ip/ipnetns.c +@@ -8,9 +8,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + #include + #include + #include +diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c +index be9f60c3b2137..388cd19a3ef0b 100644 +--- a/ip/iproute_lwtunnel.c ++++ b/ip/iproute_lwtunnel.c +@@ -16,9 +16,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + #include + #include + #include +diff --git a/ip/ipvrf.c b/ip/ipvrf.c +index 8572b4f23e3dc..8a6b7f977b142 100644 +--- a/ip/ipvrf.c ++++ b/ip/ipvrf.c +@@ -21,9 +21,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + #include + #include + #include +diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c +index 5304dfc1af906..12c2f721571b6 100644 +--- a/ip/ipxfrm.c ++++ b/ip/ipxfrm.c +@@ -28,9 +28,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + #include + #include + #include +diff --git a/ip/tunnel.c b/ip/tunnel.c +index d54505d483d22..79de7f2406f0e 100644 +--- a/ip/tunnel.c ++++ b/ip/tunnel.c +@@ -24,9 +24,6 @@ + + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + #include + #include + #include +diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c +index 0c8df7e6e10cd..85d959cc4f44f 100644 +--- a/ip/xfrm_state.c ++++ b/ip/xfrm_state.c +@@ -27,9 +27,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + #include + #include "utils.h" + #include "xfrm.h" +diff --git a/lib/bpf.c b/lib/bpf.c +index 35d7c45a2924d..45f279fa4a416 100644 +--- a/lib/bpf.c ++++ b/lib/bpf.c +@@ -15,9 +15,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + #include + #include + #include +diff --git a/lib/fs.c b/lib/fs.c +index af36bea0987fa..86efd4ed2ed80 100644 +--- a/lib/fs.c ++++ b/lib/fs.c +@@ -20,9 +20,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + #include + #include + +diff --git a/lib/inet_proto.c b/lib/inet_proto.c +index b379d8f8e720e..0836a4c96a0b4 100644 +--- a/lib/inet_proto.c ++++ b/lib/inet_proto.c +@@ -18,9 +18,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + + #include "rt_names.h" + #include "utils.h" +diff --git a/misc/ss.c b/misc/ss.c +index 7e94f2c8d1baa..41e7762bb61f5 100644 +--- a/misc/ss.c ++++ b/misc/ss.c +@@ -18,9 +18,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + #include + #include + #include +diff --git a/tc/em_ipset.c b/tc/em_ipset.c +index 550b2101a0579..48b287f5ba3b2 100644 +--- a/tc/em_ipset.c ++++ b/tc/em_ipset.c +@@ -20,9 +20,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + #include + #include + +diff --git a/tc/m_pedit.c b/tc/m_pedit.c +index baacc80dd94b7..2aeb56d9615f1 100644 +--- a/tc/m_pedit.c ++++ b/tc/m_pedit.c +@@ -23,9 +23,6 @@ + #include + #include + #include +-#ifdef HAVE_LIBBSD +-#include +-#endif + #include + #include "utils.h" + #include "tc_util.h" +-- +2.20.1 + diff --git a/SOURCES/0063-bpf-initialise-map-symbol-before-retrieving-and-comp.patch b/SOURCES/0063-bpf-initialise-map-symbol-before-retrieving-and-comp.patch new file mode 100644 index 0000000..62985b9 --- /dev/null +++ b/SOURCES/0063-bpf-initialise-map-symbol-before-retrieving-and-comp.patch @@ -0,0 +1,90 @@ +From 9348ded117d05ba1d54a748173db009d473c707c Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:57 +0200 +Subject: [PATCH] bpf: initialise map symbol before retrieving and comparing + its type + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit 1a7d3ad8a5862 + +commit 1a7d3ad8a5862ca9ce9dd19326faeea77e5e6142 +Author: Quentin Monnet +Date: Tue Nov 20 01:26:27 2018 +0000 + + bpf: initialise map symbol before retrieving and comparing its type + + In order to compare BPF map symbol type correctly in regard to the + latest LLVM, commit 7a04dd84a7f9 ("bpf: check map symbol type properly + with newer llvm compiler") compares map symbol type to both NOTYPE and + OBJECT. To do so, it first retrieves the type from "sym.st_info" and + stores it into a temporary variable. + + However, the type is collected from the symbol "sym" before this latter + symbol is actually updated. gelf_getsym() is called after that and + updates "sym", and when comparison with OBJECT or NOTYPE happens it is + done on the type of the symbol collected in the previous passage of the + loop (or on an uninitialised symbol on the first passage). This may + eventually break map collection from the ELF file. + + Fix this by assigning the type to the temporary variable only after the + call to gelf_getsym(). + + Fixes: 7a04dd84a7f9 ("bpf: check map symbol type properly with newer llvm compiler") + Reported-by: Ron Philip + Signed-off-by: Quentin Monnet + Reviewed-by: Jiong Wang + Acked-by: Yonghong Song + Signed-off-by: Stephen Hemminger +--- + lib/bpf.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/lib/bpf.c b/lib/bpf.c +index 45f279fa4a416..6aff8f7bad7fb 100644 +--- a/lib/bpf.c ++++ b/lib/bpf.c +@@ -1758,11 +1758,12 @@ static const char *bpf_map_fetch_name(struct bpf_elf_ctx *ctx, int which) + int i; + + for (i = 0; i < ctx->sym_num; i++) { +- int type = GELF_ST_TYPE(sym.st_info); ++ int type; + + if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym) + continue; + ++ type = GELF_ST_TYPE(sym.st_info); + if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL || + (type != STT_NOTYPE && type != STT_OBJECT) || + sym.st_shndx != ctx->sec_maps || +@@ -1851,11 +1852,12 @@ static int bpf_map_num_sym(struct bpf_elf_ctx *ctx) + GElf_Sym sym; + + for (i = 0; i < ctx->sym_num; i++) { +- int type = GELF_ST_TYPE(sym.st_info); ++ int type; + + if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym) + continue; + ++ type = GELF_ST_TYPE(sym.st_info); + if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL || + (type != STT_NOTYPE && type != STT_OBJECT) || + sym.st_shndx != ctx->sec_maps) +@@ -1931,10 +1933,12 @@ static int bpf_map_verify_all_offs(struct bpf_elf_ctx *ctx, int end) + * the table again. + */ + for (i = 0; i < ctx->sym_num; i++) { +- int type = GELF_ST_TYPE(sym.st_info); ++ int type; + + if (gelf_getsym(ctx->sym_tab, i, &sym) != &sym) + continue; ++ ++ type = GELF_ST_TYPE(sym.st_info); + if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL || + (type != STT_NOTYPE && type != STT_OBJECT) || + sym.st_shndx != ctx->sec_maps) +-- +2.20.1 + diff --git a/SOURCES/0064-lib-bpf-fix-build-warning-if-no-elf.patch b/SOURCES/0064-lib-bpf-fix-build-warning-if-no-elf.patch new file mode 100644 index 0000000..ea2e81e --- /dev/null +++ b/SOURCES/0064-lib-bpf-fix-build-warning-if-no-elf.patch @@ -0,0 +1,57 @@ +From ac8f163e0b2e14afdc8a1a1d449f1e5db07075ba Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:57 +0200 +Subject: [PATCH] lib/bpf: fix build warning if no elf +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit 33fde2b60081e + +commit 33fde2b60081ed9ac16f7dd81c48233803855689 +Author: Stephen Hemminger +Date: Mon Dec 10 13:50:17 2018 -0800 + + lib/bpf: fix build warning if no elf + + Function was not used unlesss HAVE_ELF causing: + + bpf.c:105:13: warning: ‘bpf_map_offload_neutral’ defined but not used [-Wunused-function] + + Signed-off-by: Stephen Hemminger +--- + lib/bpf.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/lib/bpf.c b/lib/bpf.c +index 6aff8f7bad7fb..5e85cfc0bdd5b 100644 +--- a/lib/bpf.c ++++ b/lib/bpf.c +@@ -102,11 +102,6 @@ static const struct bpf_prog_meta __bpf_prog_meta[] = { + }, + }; + +-static bool bpf_map_offload_neutral(enum bpf_map_type type) +-{ +- return type == BPF_MAP_TYPE_PERF_EVENT_ARRAY; +-} +- + static const char *bpf_prog_to_subdir(enum bpf_prog_type type) + { + assert(type < ARRAY_SIZE(__bpf_prog_meta) && +@@ -1610,6 +1605,11 @@ static bool bpf_is_map_in_map_type(const struct bpf_elf_map *map) + map->type == BPF_MAP_TYPE_HASH_OF_MAPS; + } + ++static bool bpf_map_offload_neutral(enum bpf_map_type type) ++{ ++ return type == BPF_MAP_TYPE_PERF_EVENT_ARRAY; ++} ++ + static int bpf_map_attach(const char *name, struct bpf_elf_ctx *ctx, + const struct bpf_elf_map *map, struct bpf_map_ext *ext, + int *have_map_in_map) +-- +2.20.1 + diff --git a/SOURCES/0065-bpf-add-btf-func-and-func_proto-kind-support.patch b/SOURCES/0065-bpf-add-btf-func-and-func_proto-kind-support.patch new file mode 100644 index 0000000..9f515c3 --- /dev/null +++ b/SOURCES/0065-bpf-add-btf-func-and-func_proto-kind-support.patch @@ -0,0 +1,61 @@ +From 5c940644dfc632f1270f39ee909e1abb877ff081 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:57 +0200 +Subject: [PATCH] bpf: add btf func and func_proto kind support + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit 3da6d055d93fe + +commit 3da6d055d93fefe40bf88a9bc37b4ce3433696ee +Author: Yonghong Song +Date: Thu Jan 24 16:41:07 2019 -0800 + + bpf: add btf func and func_proto kind support + + The issue is discovered for bpf selftest test_skb_cgroup.sh. + Currently we have, + $ ./test_skb_cgroup_id.sh + Wait for testing link-local IP to become available ... OK + Object has unknown BTF type: 13! + [PASS] + + In the above the BTF type 13 refers to BTF kind + BTF_KIND_FUNC_PROTO. + This patch added support of BTF_KIND_FUNC_PROTO and + BTF_KIND_FUNC during type parsing. + With this patch, I got + $ ./test_skb_cgroup_id.sh + Wait for testing link-local IP to become available ... OK + [PASS] + + Signed-off-by: Yonghong Song + Acked-by: Daniel Borkmann + Signed-off-by: Stephen Hemminger +--- + lib/bpf.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/bpf.c b/lib/bpf.c +index 5e85cfc0bdd5b..762f8857453ff 100644 +--- a/lib/bpf.c ++++ b/lib/bpf.c +@@ -2193,12 +2193,16 @@ static int bpf_btf_prep_type_data(struct bpf_elf_ctx *ctx) + case BTF_KIND_ENUM: + type_cur += var_len * sizeof(struct btf_enum); + break; ++ case BTF_KIND_FUNC_PROTO: ++ type_cur += var_len * sizeof(struct btf_param); ++ break; + case BTF_KIND_TYPEDEF: + case BTF_KIND_PTR: + case BTF_KIND_FWD: + case BTF_KIND_VOLATILE: + case BTF_KIND_CONST: + case BTF_KIND_RESTRICT: ++ case BTF_KIND_FUNC: + break; + default: + fprintf(stderr, "Object has unknown BTF type: %u!\n", kind); +-- +2.20.1 + diff --git a/SOURCES/0066-uapi-update-headers-to-4.20-rc1.patch b/SOURCES/0066-uapi-update-headers-to-4.20-rc1.patch new file mode 100644 index 0000000..9d67465 --- /dev/null +++ b/SOURCES/0066-uapi-update-headers-to-4.20-rc1.patch @@ -0,0 +1,282 @@ +From 3caa0fed6aa58a8f7a05486f98572878a8ad5b30 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:57 +0200 +Subject: [PATCH] uapi: update headers to 4.20-rc1 + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit 39776a8665f2d + +commit 39776a8665f2db1255ebed1f7cc992f69437bc36 +Author: Stephen Hemminger +Date: Mon Nov 5 08:37:41 2018 -0800 + + uapi: update headers to 4.20-rc1 + + Signed-off-by: Stephen Hemminger +--- + include/uapi/linux/bpf.h | 142 ++++++++++++++++++++++++++++++++++- + include/uapi/linux/elf-em.h | 1 + + include/uapi/linux/if_link.h | 1 + + include/uapi/linux/magic.h | 1 + + include/uapi/linux/netlink.h | 1 + + include/uapi/linux/sctp.h | 1 + + 6 files changed, 145 insertions(+), 2 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index abb7f7748c2de..2bbe33db8aefa 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -103,6 +103,7 @@ enum bpf_cmd { + BPF_BTF_LOAD, + BPF_BTF_GET_FD_BY_ID, + BPF_TASK_FD_QUERY, ++ BPF_MAP_LOOKUP_AND_DELETE_ELEM, + }; + + enum bpf_map_type { +@@ -127,6 +128,9 @@ enum bpf_map_type { + BPF_MAP_TYPE_SOCKHASH, + BPF_MAP_TYPE_CGROUP_STORAGE, + BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, ++ BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE, ++ BPF_MAP_TYPE_QUEUE, ++ BPF_MAP_TYPE_STACK, + }; + + enum bpf_prog_type { +@@ -461,6 +465,28 @@ union bpf_attr { + * Return + * 0 on success, or a negative error in case of failure. + * ++ * int bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags) ++ * Description ++ * Push an element *value* in *map*. *flags* is one of: ++ * ++ * **BPF_EXIST** ++ * If the queue/stack is full, the oldest element is removed to ++ * make room for this. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_map_pop_elem(struct bpf_map *map, void *value) ++ * Description ++ * Pop an element from *map*. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_map_peek_elem(struct bpf_map *map, void *value) ++ * Description ++ * Get an element from *map* without removing it. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * + * int bpf_probe_read(void *dst, u32 size, const void *src) + * Description + * For tracing programs, safely attempt to read *size* bytes from +@@ -1432,7 +1458,7 @@ union bpf_attr { + * Return + * 0 on success, or a negative error in case of failure. + * +- * int bpf_skb_adjust_room(struct sk_buff *skb, u32 len_diff, u32 mode, u64 flags) ++ * int bpf_skb_adjust_room(struct sk_buff *skb, s32 len_diff, u32 mode, u64 flags) + * Description + * Grow or shrink the room for data in the packet associated to + * *skb* by *len_diff*, and according to the selected *mode*. +@@ -2143,6 +2169,94 @@ union bpf_attr { + * request in the skb. + * Return + * 0 on success, or a negative error in case of failure. ++ * ++ * struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u32 netns, u64 flags) ++ * Description ++ * Look for TCP socket matching *tuple*, optionally in a child ++ * network namespace *netns*. The return value must be checked, ++ * and if non-NULL, released via **bpf_sk_release**\ (). ++ * ++ * The *ctx* should point to the context of the program, such as ++ * the skb or socket (depending on the hook in use). This is used ++ * to determine the base network namespace for the lookup. ++ * ++ * *tuple_size* must be one of: ++ * ++ * **sizeof**\ (*tuple*\ **->ipv4**) ++ * Look for an IPv4 socket. ++ * **sizeof**\ (*tuple*\ **->ipv6**) ++ * Look for an IPv6 socket. ++ * ++ * If the *netns* is zero, then the socket lookup table in the ++ * netns associated with the *ctx* will be used. For the TC hooks, ++ * this in the netns of the device in the skb. For socket hooks, ++ * this in the netns of the socket. If *netns* is non-zero, then ++ * it specifies the ID of the netns relative to the netns ++ * associated with the *ctx*. ++ * ++ * All values for *flags* are reserved for future usage, and must ++ * be left at zero. ++ * ++ * This helper is available only if the kernel was compiled with ++ * **CONFIG_NET** configuration option. ++ * Return ++ * Pointer to *struct bpf_sock*, or NULL in case of failure. ++ * ++ * struct bpf_sock *bpf_sk_lookup_udp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u32 netns, u64 flags) ++ * Description ++ * Look for UDP socket matching *tuple*, optionally in a child ++ * network namespace *netns*. The return value must be checked, ++ * and if non-NULL, released via **bpf_sk_release**\ (). ++ * ++ * The *ctx* should point to the context of the program, such as ++ * the skb or socket (depending on the hook in use). This is used ++ * to determine the base network namespace for the lookup. ++ * ++ * *tuple_size* must be one of: ++ * ++ * **sizeof**\ (*tuple*\ **->ipv4**) ++ * Look for an IPv4 socket. ++ * **sizeof**\ (*tuple*\ **->ipv6**) ++ * Look for an IPv6 socket. ++ * ++ * If the *netns* is zero, then the socket lookup table in the ++ * netns associated with the *ctx* will be used. For the TC hooks, ++ * this in the netns of the device in the skb. For socket hooks, ++ * this in the netns of the socket. If *netns* is non-zero, then ++ * it specifies the ID of the netns relative to the netns ++ * associated with the *ctx*. ++ * ++ * All values for *flags* are reserved for future usage, and must ++ * be left at zero. ++ * ++ * This helper is available only if the kernel was compiled with ++ * **CONFIG_NET** configuration option. ++ * Return ++ * Pointer to *struct bpf_sock*, or NULL in case of failure. ++ * ++ * int bpf_sk_release(struct bpf_sock *sk) ++ * Description ++ * Release the reference held by *sock*. *sock* must be a non-NULL ++ * pointer that was returned from bpf_sk_lookup_xxx\ (). ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_msg_push_data(struct sk_buff *skb, u32 start, u32 len, u64 flags) ++ * Description ++ * For socket policies, insert *len* bytes into msg at offset ++ * *start*. ++ * ++ * If a program of type **BPF_PROG_TYPE_SK_MSG** is run on a ++ * *msg* it may want to insert metadata or options into the msg. ++ * This can later be read and used by any of the lower layer BPF ++ * hooks. ++ * ++ * This helper may fail if under memory pressure (a malloc ++ * fails) in these cases BPF programs will get an appropriate ++ * error and BPF programs will need to handle them. ++ * ++ * Return ++ * 0 on success, or a negative error in case of failure. + */ + #define __BPF_FUNC_MAPPER(FN) \ + FN(unspec), \ +@@ -2228,7 +2342,14 @@ union bpf_attr { + FN(get_current_cgroup_id), \ + FN(get_local_storage), \ + FN(sk_select_reuseport), \ +- FN(skb_ancestor_cgroup_id), ++ FN(skb_ancestor_cgroup_id), \ ++ FN(sk_lookup_tcp), \ ++ FN(sk_lookup_udp), \ ++ FN(sk_release), \ ++ FN(map_push_elem), \ ++ FN(map_pop_elem), \ ++ FN(map_peek_elem), \ ++ FN(msg_push_data), + + /* integer value in 'imm' field of BPF_CALL instruction selects which helper + * function eBPF program intends to call +@@ -2398,6 +2519,23 @@ struct bpf_sock { + */ + }; + ++struct bpf_sock_tuple { ++ union { ++ struct { ++ __be32 saddr; ++ __be32 daddr; ++ __be16 sport; ++ __be16 dport; ++ } ipv4; ++ struct { ++ __be32 saddr[4]; ++ __be32 daddr[4]; ++ __be16 sport; ++ __be16 dport; ++ } ipv6; ++ }; ++}; ++ + #define XDP_PACKET_HEADROOM 256 + + /* User return codes for XDP prog type. +diff --git a/include/uapi/linux/elf-em.h b/include/uapi/linux/elf-em.h +index 31aa101783351..93722e60204c6 100644 +--- a/include/uapi/linux/elf-em.h ++++ b/include/uapi/linux/elf-em.h +@@ -41,6 +41,7 @@ + #define EM_TILEPRO 188 /* Tilera TILEPro */ + #define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */ + #define EM_TILEGX 191 /* Tilera TILE-Gx */ ++#define EM_RISCV 243 /* RISC-V */ + #define EM_BPF 247 /* Linux BPF - in-kernel virtual machine */ + #define EM_FRV 0x5441 /* Fujitsu FR-V */ + +diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h +index 9c254603ebdad..52e95197e0790 100644 +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -285,6 +285,7 @@ enum { + IFLA_BR_MCAST_STATS_ENABLED, + IFLA_BR_MCAST_IGMP_VERSION, + IFLA_BR_MCAST_MLD_VERSION, ++ IFLA_BR_VLAN_STATS_PER_PORT, + __IFLA_BR_MAX, + }; + +diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h +index 1a6fee974116a..96c24478d8ced 100644 +--- a/include/uapi/linux/magic.h ++++ b/include/uapi/linux/magic.h +@@ -29,6 +29,7 @@ + #define HPFS_SUPER_MAGIC 0xf995e849 + #define ISOFS_SUPER_MAGIC 0x9660 + #define JFFS2_SUPER_MAGIC 0x72b6 ++#define XFS_SUPER_MAGIC 0x58465342 /* "XFSB" */ + #define PSTOREFS_MAGIC 0x6165676C + #define EFIVARFS_MAGIC 0xde5e81e4 + #define HOSTFS_SUPER_MAGIC 0x00c0ffee +diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h +index 0b2c29bd081fa..2966171b9b95c 100644 +--- a/include/uapi/linux/netlink.h ++++ b/include/uapi/linux/netlink.h +@@ -153,6 +153,7 @@ enum nlmsgerr_attrs { + #define NETLINK_LIST_MEMBERSHIPS 9 + #define NETLINK_CAP_ACK 10 + #define NETLINK_EXT_ACK 11 ++#define NETLINK_DUMP_STRICT_CHK 12 + + struct nl_pktinfo { + __u32 group; +diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h +index dd164d7f4f41a..626480b68fb59 100644 +--- a/include/uapi/linux/sctp.h ++++ b/include/uapi/linux/sctp.h +@@ -301,6 +301,7 @@ enum sctp_sinfo_flags { + SCTP_SACK_IMMEDIATELY = (1 << 3), /* SACK should be sent without delay. */ + /* 2 bits here have been used by SCTP_PR_SCTP_MASK */ + SCTP_SENDALL = (1 << 6), ++ SCTP_PR_SCTP_ALL = (1 << 7), + SCTP_NOTIFICATION = MSG_NOTIFICATION, /* Next message is not user msg but notification. */ + SCTP_EOF = MSG_FIN, /* Initiate graceful shutdown process. */ + }; +-- +2.20.1 + diff --git a/SOURCES/0067-uapi-update-bpf-header.patch b/SOURCES/0067-uapi-update-bpf-header.patch new file mode 100644 index 0000000..22c447c --- /dev/null +++ b/SOURCES/0067-uapi-update-bpf-header.patch @@ -0,0 +1,155 @@ +From 415044d7e6f956daec990a7ae358f9f324bd2dcd Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:57 +0200 +Subject: [PATCH] uapi: update bpf header + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit 028766aed21a4 + +commit 028766aed21a4d8eb2e60c9ef667f75f9354a104 +Author: Stephen Hemminger +Date: Mon Dec 10 09:22:23 2018 -0800 + + uapi: update bpf header + + Changes from 4.20-rc6 + + Signed-off-by: Stephen Hemminger +--- + include/uapi/linux/bpf.h | 56 ++++++++++++++++++++++++++-------------- + 1 file changed, 37 insertions(+), 19 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 2bbe33db8aefa..ff651ca661308 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -2170,7 +2170,7 @@ union bpf_attr { + * Return + * 0 on success, or a negative error in case of failure. + * +- * struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u32 netns, u64 flags) ++ * struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags) + * Description + * Look for TCP socket matching *tuple*, optionally in a child + * network namespace *netns*. The return value must be checked, +@@ -2187,12 +2187,14 @@ union bpf_attr { + * **sizeof**\ (*tuple*\ **->ipv6**) + * Look for an IPv6 socket. + * +- * If the *netns* is zero, then the socket lookup table in the +- * netns associated with the *ctx* will be used. For the TC hooks, +- * this in the netns of the device in the skb. For socket hooks, +- * this in the netns of the socket. If *netns* is non-zero, then +- * it specifies the ID of the netns relative to the netns +- * associated with the *ctx*. ++ * If the *netns* is a negative signed 32-bit integer, then the ++ * socket lookup table in the netns associated with the *ctx* will ++ * will be used. For the TC hooks, this is the netns of the device ++ * in the skb. For socket hooks, this is the netns of the socket. ++ * If *netns* is any other signed 32-bit value greater than or ++ * equal to zero then it specifies the ID of the netns relative to ++ * the netns associated with the *ctx*. *netns* values beyond the ++ * range of 32-bit integers are reserved for future use. + * + * All values for *flags* are reserved for future usage, and must + * be left at zero. +@@ -2201,8 +2203,10 @@ union bpf_attr { + * **CONFIG_NET** configuration option. + * Return + * Pointer to *struct bpf_sock*, or NULL in case of failure. ++ * For sockets with reuseport option, the *struct bpf_sock* ++ * result is from reuse->socks[] using the hash of the tuple. + * +- * struct bpf_sock *bpf_sk_lookup_udp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u32 netns, u64 flags) ++ * struct bpf_sock *bpf_sk_lookup_udp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags) + * Description + * Look for UDP socket matching *tuple*, optionally in a child + * network namespace *netns*. The return value must be checked, +@@ -2219,12 +2223,14 @@ union bpf_attr { + * **sizeof**\ (*tuple*\ **->ipv6**) + * Look for an IPv6 socket. + * +- * If the *netns* is zero, then the socket lookup table in the +- * netns associated with the *ctx* will be used. For the TC hooks, +- * this in the netns of the device in the skb. For socket hooks, +- * this in the netns of the socket. If *netns* is non-zero, then +- * it specifies the ID of the netns relative to the netns +- * associated with the *ctx*. ++ * If the *netns* is a negative signed 32-bit integer, then the ++ * socket lookup table in the netns associated with the *ctx* will ++ * will be used. For the TC hooks, this is the netns of the device ++ * in the skb. For socket hooks, this is the netns of the socket. ++ * If *netns* is any other signed 32-bit value greater than or ++ * equal to zero then it specifies the ID of the netns relative to ++ * the netns associated with the *ctx*. *netns* values beyond the ++ * range of 32-bit integers are reserved for future use. + * + * All values for *flags* are reserved for future usage, and must + * be left at zero. +@@ -2233,6 +2239,8 @@ union bpf_attr { + * **CONFIG_NET** configuration option. + * Return + * Pointer to *struct bpf_sock*, or NULL in case of failure. ++ * For sockets with reuseport option, the *struct bpf_sock* ++ * result is from reuse->socks[] using the hash of the tuple. + * + * int bpf_sk_release(struct bpf_sock *sk) + * Description +@@ -2405,6 +2413,9 @@ enum bpf_func_id { + /* BPF_FUNC_perf_event_output for sk_buff input context. */ + #define BPF_F_CTXLEN_MASK (0xfffffULL << 32) + ++/* Current network namespace */ ++#define BPF_F_CURRENT_NETNS (-1L) ++ + /* Mode for BPF_FUNC_skb_adjust_room helper. */ + enum bpf_adj_room_mode { + BPF_ADJ_ROOM_NET, +@@ -2422,6 +2433,12 @@ enum bpf_lwt_encap_mode { + BPF_LWT_ENCAP_SEG6_INLINE + }; + ++#define __bpf_md_ptr(type, name) \ ++union { \ ++ type name; \ ++ __u64 :64; \ ++} __attribute__((aligned(8))) ++ + /* user accessible mirror of in-kernel sk_buff. + * new fields can only be added to the end of this structure + */ +@@ -2456,7 +2473,7 @@ struct __sk_buff { + /* ... here. */ + + __u32 data_meta; +- struct bpf_flow_keys *flow_keys; ++ __bpf_md_ptr(struct bpf_flow_keys *, flow_keys); + }; + + struct bpf_tunnel_key { +@@ -2572,8 +2589,8 @@ enum sk_action { + * be added to the end of this structure + */ + struct sk_msg_md { +- void *data; +- void *data_end; ++ __bpf_md_ptr(void *, data); ++ __bpf_md_ptr(void *, data_end); + + __u32 family; + __u32 remote_ip4; /* Stored in network byte order */ +@@ -2589,8 +2606,9 @@ 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 */ ++ __bpf_md_ptr(void *, data); ++ /* End of directly accessible data */ ++ __bpf_md_ptr(void *, data_end); + /* + * Total length of packet (starting from the tcp/udp header). + * Note that the directly accessible bytes (data_end - data) +-- +2.20.1 + diff --git a/SOURCES/0068-Update-kernel-headers.patch b/SOURCES/0068-Update-kernel-headers.patch new file mode 100644 index 0000000..741afb5 --- /dev/null +++ b/SOURCES/0068-Update-kernel-headers.patch @@ -0,0 +1,492 @@ +From 356758b3303ab24b6fe8dccf94ed98ed7cbad224 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 13 Jun 2019 14:37:57 +0200 +Subject: [PATCH] Update kernel headers + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1716361 +Upstream Status: iproute2.git commit 17689d3075c8b + +commit 17689d3075c8b9a29b8f398a57defb9dcabafe81 +Author: David Ahern +Date: Wed Dec 19 12:47:29 2018 -0800 + + Update kernel headers + + Update kernel headers to commit + 055722716c39 ("tipc: fix uninitialized value for broadcast retransmission") + + Signed-off-by: David Ahern +--- + include/uapi/linux/bpf.h | 175 +++++++++++++++++++++-------- + include/uapi/linux/btf.h | 18 ++- + include/uapi/linux/if_bridge.h | 21 ++++ + include/uapi/linux/if_link.h | 1 + + include/uapi/linux/if_tun.h | 1 + + include/uapi/linux/neighbour.h | 1 + + include/uapi/linux/net_namespace.h | 2 + + include/uapi/linux/snmp.h | 1 + + 8 files changed, 171 insertions(+), 49 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index ff651ca661308..960a7f0a4d99b 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -232,6 +232,20 @@ enum bpf_attach_type { + */ + #define BPF_F_STRICT_ALIGNMENT (1U << 0) + ++/* If BPF_F_ANY_ALIGNMENT is used in BPF_PROF_LOAD command, the ++ * verifier will allow any alignment whatsoever. On platforms ++ * with strict alignment requirements for loads ands stores (such ++ * as sparc and mips) the verifier validates that all loads and ++ * stores provably follow this requirement. This flag turns that ++ * checking and enforcement off. ++ * ++ * It is mostly used for testing when we want to validate the ++ * context and memory access aspects of the verifier, but because ++ * of an unaligned access the alignment check would trigger before ++ * the one we are interested in. ++ */ ++#define BPF_F_ANY_ALIGNMENT (1U << 1) ++ + /* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */ + #define BPF_PSEUDO_MAP_FD 1 + +@@ -257,9 +271,6 @@ enum bpf_attach_type { + /* Specify numa node during map creation */ + #define BPF_F_NUMA_NODE (1U << 2) + +-/* flags for BPF_PROG_QUERY */ +-#define BPF_F_QUERY_EFFECTIVE (1U << 0) +- + #define BPF_OBJ_NAME_LEN 16U + + /* Flags for accessing BPF object */ +@@ -269,6 +280,12 @@ enum bpf_attach_type { + /* Flag for stack_map, store build_id+offset instead of pointer */ + #define BPF_F_STACK_BUILD_ID (1U << 5) + ++/* Zero-initialize hash function seed. This should only be used for testing. */ ++#define BPF_F_ZERO_SEED (1U << 6) ++ ++/* flags for BPF_PROG_QUERY */ ++#define BPF_F_QUERY_EFFECTIVE (1U << 0) ++ + enum bpf_stack_build_id_status { + /* user space need an empty entry to identify end of a trace */ + BPF_STACK_BUILD_ID_EMPTY = 0, +@@ -335,6 +352,13 @@ union bpf_attr { + * (context accesses, allowed helpers, etc). + */ + __u32 expected_attach_type; ++ __u32 prog_btf_fd; /* fd pointing to BTF type data */ ++ __u32 func_info_rec_size; /* userspace bpf_func_info size */ ++ __aligned_u64 func_info; /* func info */ ++ __u32 func_info_cnt; /* number of bpf_func_info records */ ++ __u32 line_info_rec_size; /* userspace bpf_line_info size */ ++ __aligned_u64 line_info; /* line info */ ++ __u32 line_info_cnt; /* number of bpf_line_info records */ + }; + + struct { /* anonymous struct used by BPF_OBJ_* commands */ +@@ -353,8 +377,11 @@ union bpf_attr { + struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */ + __u32 prog_fd; + __u32 retval; +- __u32 data_size_in; +- __u32 data_size_out; ++ __u32 data_size_in; /* input: len of data_in */ ++ __u32 data_size_out; /* input/output: len of data_out ++ * returns ENOSPC if data_out ++ * is too small. ++ */ + __aligned_u64 data_in; + __aligned_u64 data_out; + __u32 repeat; +@@ -475,18 +502,6 @@ union bpf_attr { + * Return + * 0 on success, or a negative error in case of failure. + * +- * int bpf_map_pop_elem(struct bpf_map *map, void *value) +- * Description +- * Pop an element from *map*. +- * Return +- * 0 on success, or a negative error in case of failure. +- * +- * int bpf_map_peek_elem(struct bpf_map *map, void *value) +- * Description +- * Get an element from *map* without removing it. +- * Return +- * 0 on success, or a negative error in case of failure. +- * + * int bpf_probe_read(void *dst, u32 size, const void *src) + * Description + * For tracing programs, safely attempt to read *size* bytes from +@@ -1910,9 +1925,9 @@ union bpf_attr { + * is set to metric from route (IPv4/IPv6 only), and ifindex + * is set to the device index of the nexthop from the FIB lookup. + * +- * *plen* argument is the size of the passed in struct. +- * *flags* argument can be a combination of one or more of the +- * following values: ++ * *plen* argument is the size of the passed in struct. ++ * *flags* argument can be a combination of one or more of the ++ * following values: + * + * **BPF_FIB_LOOKUP_DIRECT** + * Do a direct table lookup vs full lookup using FIB +@@ -1921,9 +1936,9 @@ union bpf_attr { + * Perform lookup from an egress perspective (default is + * ingress). + * +- * *ctx* is either **struct xdp_md** for XDP programs or +- * **struct sk_buff** tc cls_act programs. +- * Return ++ * *ctx* is either **struct xdp_md** for XDP programs or ++ * **struct sk_buff** tc cls_act programs. ++ * Return + * * < 0 if any input argument is invalid + * * 0 on success (packet is forwarded, nexthop neighbor exists) + * * > 0 one of **BPF_FIB_LKUP_RET_** codes explaining why the +@@ -2068,8 +2083,8 @@ union bpf_attr { + * translated to a keycode using the rc keymap, and reported as + * an input key down event. After a period a key up event is + * generated. This period can be extended by calling either +- * **bpf_rc_keydown** () again with the same values, or calling +- * **bpf_rc_repeat** (). ++ * **bpf_rc_keydown**\ () again with the same values, or calling ++ * **bpf_rc_repeat**\ (). + * + * Some protocols include a toggle bit, in case the button was + * released and pressed again between consecutive scancodes. +@@ -2152,21 +2167,22 @@ union bpf_attr { + * The *flags* meaning is specific for each map type, + * and has to be 0 for cgroup local storage. + * +- * Depending on the bpf program type, a local storage area +- * can be shared between multiple instances of the bpf program, ++ * Depending on the BPF program type, a local storage area ++ * can be shared between multiple instances of the BPF program, + * running simultaneously. + * + * A user should care about the synchronization by himself. +- * For example, by using the BPF_STX_XADD instruction to alter ++ * For example, by using the **BPF_STX_XADD** instruction to alter + * the shared data. + * Return +- * Pointer to the local storage area. ++ * A 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. ++ * Select a **SO_REUSEPORT** socket from a ++ * **BPF_MAP_TYPE_REUSEPORT_ARRAY** *map*. ++ * It checks the selected socket is matching the incoming ++ * request in the socket buffer. + * Return + * 0 on success, or a negative error in case of failure. + * +@@ -2174,7 +2190,7 @@ union bpf_attr { + * Description + * Look for TCP socket matching *tuple*, optionally in a child + * network namespace *netns*. The return value must be checked, +- * and if non-NULL, released via **bpf_sk_release**\ (). ++ * and if non-**NULL**, released via **bpf_sk_release**\ (). + * + * The *ctx* should point to the context of the program, such as + * the skb or socket (depending on the hook in use). This is used +@@ -2202,15 +2218,15 @@ union bpf_attr { + * This helper is available only if the kernel was compiled with + * **CONFIG_NET** configuration option. + * Return +- * Pointer to *struct bpf_sock*, or NULL in case of failure. +- * For sockets with reuseport option, the *struct bpf_sock* +- * result is from reuse->socks[] using the hash of the tuple. ++ * Pointer to **struct bpf_sock**, or **NULL** in case of failure. ++ * For sockets with reuseport option, the **struct bpf_sock** ++ * result is from **reuse->socks**\ [] using the hash of the tuple. + * + * struct bpf_sock *bpf_sk_lookup_udp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags) + * Description + * Look for UDP socket matching *tuple*, optionally in a child + * network namespace *netns*. The return value must be checked, +- * and if non-NULL, released via **bpf_sk_release**\ (). ++ * and if non-**NULL**, released via **bpf_sk_release**\ (). + * + * The *ctx* should point to the context of the program, such as + * the skb or socket (depending on the hook in use). This is used +@@ -2238,33 +2254,71 @@ union bpf_attr { + * This helper is available only if the kernel was compiled with + * **CONFIG_NET** configuration option. + * Return +- * Pointer to *struct bpf_sock*, or NULL in case of failure. +- * For sockets with reuseport option, the *struct bpf_sock* +- * result is from reuse->socks[] using the hash of the tuple. ++ * Pointer to **struct bpf_sock**, or **NULL** in case of failure. ++ * For sockets with reuseport option, the **struct bpf_sock** ++ * result is from **reuse->socks**\ [] using the hash of the tuple. + * +- * int bpf_sk_release(struct bpf_sock *sk) ++ * int bpf_sk_release(struct bpf_sock *sock) + * Description +- * Release the reference held by *sock*. *sock* must be a non-NULL +- * pointer that was returned from bpf_sk_lookup_xxx\ (). ++ * Release the reference held by *sock*. *sock* must be a ++ * non-**NULL** pointer that was returned from ++ * **bpf_sk_lookup_xxx**\ (). + * Return + * 0 on success, or a negative error in case of failure. + * ++ * int bpf_map_pop_elem(struct bpf_map *map, void *value) ++ * Description ++ * Pop an element from *map*. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_map_peek_elem(struct bpf_map *map, void *value) ++ * Description ++ * Get an element from *map* without removing it. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * + * int bpf_msg_push_data(struct sk_buff *skb, u32 start, u32 len, u64 flags) + * Description +- * For socket policies, insert *len* bytes into msg at offset ++ * For socket policies, insert *len* bytes into *msg* at offset + * *start*. + * + * If a program of type **BPF_PROG_TYPE_SK_MSG** is run on a +- * *msg* it may want to insert metadata or options into the msg. ++ * *msg* it may want to insert metadata or options into the *msg*. + * This can later be read and used by any of the lower layer BPF + * hooks. + * + * This helper may fail if under memory pressure (a malloc + * fails) in these cases BPF programs will get an appropriate + * error and BPF programs will need to handle them. ++ * Return ++ * 0 on success, or a negative error in case of failure. + * ++ * int bpf_msg_pop_data(struct sk_msg_buff *msg, u32 start, u32 pop, u64 flags) ++ * Description ++ * Will remove *pop* bytes from a *msg* starting at byte *start*. ++ * This may result in **ENOMEM** errors under certain situations if ++ * an allocation and copy are required due to a full ring buffer. ++ * However, the helper will try to avoid doing the allocation ++ * if possible. Other errors can occur if input parameters are ++ * invalid either due to *start* byte not being valid part of *msg* ++ * payload and/or *pop* value being to large. + * Return + * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_rc_pointer_rel(void *ctx, s32 rel_x, s32 rel_y) ++ * Description ++ * This helper is used in programs implementing IR decoding, to ++ * report a successfully decoded pointer movement. ++ * ++ * The *ctx* should point to the lirc sample as passed into ++ * the program. ++ * ++ * This helper is only available is the kernel was compiled with ++ * the **CONFIG_BPF_LIRC_MODE2** configuration option set to ++ * "**y**". ++ * Return ++ * 0 + */ + #define __BPF_FUNC_MAPPER(FN) \ + FN(unspec), \ +@@ -2357,7 +2411,9 @@ union bpf_attr { + FN(map_push_elem), \ + FN(map_pop_elem), \ + FN(map_peek_elem), \ +- FN(msg_push_data), ++ FN(msg_push_data), \ ++ FN(msg_pop_data), \ ++ FN(rc_pointer_rel), + + /* integer value in 'imm' field of BPF_CALL instruction selects which helper + * function eBPF program intends to call +@@ -2474,6 +2530,8 @@ struct __sk_buff { + + __u32 data_meta; + __bpf_md_ptr(struct bpf_flow_keys *, flow_keys); ++ __u64 tstamp; ++ __u32 wire_len; + }; + + struct bpf_tunnel_key { +@@ -2649,6 +2707,16 @@ struct bpf_prog_info { + __u32 nr_jited_func_lens; + __aligned_u64 jited_ksyms; + __aligned_u64 jited_func_lens; ++ __u32 btf_id; ++ __u32 func_info_rec_size; ++ __aligned_u64 func_info; ++ __u32 nr_func_info; ++ __u32 nr_line_info; ++ __aligned_u64 line_info; ++ __aligned_u64 jited_line_info; ++ __u32 nr_jited_line_info; ++ __u32 line_info_rec_size; ++ __u32 jited_line_info_rec_size; + } __attribute__((aligned(8))); + + struct bpf_map_info { +@@ -2960,4 +3028,19 @@ struct bpf_flow_keys { + }; + }; + ++struct bpf_func_info { ++ __u32 insn_off; ++ __u32 type_id; ++}; ++ ++#define BPF_LINE_INFO_LINE_NUM(line_col) ((line_col) >> 10) ++#define BPF_LINE_INFO_LINE_COL(line_col) ((line_col) & 0x3ff) ++ ++struct bpf_line_info { ++ __u32 insn_off; ++ __u32 file_name_off; ++ __u32 line_off; ++ __u32 line_col; ++}; ++ + #endif /* __LINUX_BPF_H__ */ +diff --git a/include/uapi/linux/btf.h b/include/uapi/linux/btf.h +index 8d2a8ffad56f9..f43d5a8e13d31 100644 +--- a/include/uapi/linux/btf.h ++++ b/include/uapi/linux/btf.h +@@ -40,7 +40,8 @@ struct btf_type { + /* "size" is used by INT, ENUM, STRUCT and UNION. + * "size" tells the size of the type it is describing. + * +- * "type" is used by PTR, TYPEDEF, VOLATILE, CONST and RESTRICT. ++ * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, ++ * FUNC and FUNC_PROTO. + * "type" is a type_id referring to another type. + */ + union { +@@ -64,8 +65,10 @@ struct btf_type { + #define BTF_KIND_VOLATILE 9 /* Volatile */ + #define BTF_KIND_CONST 10 /* Const */ + #define BTF_KIND_RESTRICT 11 /* Restrict */ +-#define BTF_KIND_MAX 11 +-#define NR_BTF_KINDS 12 ++#define BTF_KIND_FUNC 12 /* Function */ ++#define BTF_KIND_FUNC_PROTO 13 /* Function Proto */ ++#define BTF_KIND_MAX 13 ++#define NR_BTF_KINDS 14 + + /* For some specific BTF_KIND, "struct btf_type" is immediately + * followed by extra data. +@@ -110,4 +113,13 @@ struct btf_member { + __u32 offset; /* offset in bits */ + }; + ++/* BTF_KIND_FUNC_PROTO is followed by multiple "struct btf_param". ++ * The exact number of btf_param is stored in the vlen (of the ++ * info in "struct btf_type"). ++ */ ++struct btf_param { ++ __u32 name_off; ++ __u32 type; ++}; ++ + #endif /* __LINUX_BTF_H__ */ +diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h +index bdfecf9411320..04f763cf53029 100644 +--- a/include/uapi/linux/if_bridge.h ++++ b/include/uapi/linux/if_bridge.h +@@ -292,4 +292,25 @@ struct br_mcast_stats { + __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; + __u64 mcast_packets[BR_MCAST_DIR_SIZE]; + }; ++ ++/* bridge boolean options ++ * BR_BOOLOPT_NO_LL_LEARN - disable learning from link-local packets ++ * ++ * IMPORTANT: if adding a new option do not forget to handle ++ * it in br_boolopt_toggle/get and bridge sysfs ++ */ ++enum br_boolopt_id { ++ BR_BOOLOPT_NO_LL_LEARN, ++ BR_BOOLOPT_MAX ++}; ++ ++/* struct br_boolopt_multi - change multiple bridge boolean options ++ * ++ * @optval: new option values (bit per option) ++ * @optmask: options to change (bit per option) ++ */ ++struct br_boolopt_multi { ++ __u32 optval; ++ __u32 optmask; ++}; + #endif /* _LINUX_IF_BRIDGE_H */ +diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h +index 52e95197e0790..8e6087aee2c29 100644 +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -286,6 +286,7 @@ enum { + IFLA_BR_MCAST_IGMP_VERSION, + IFLA_BR_MCAST_MLD_VERSION, + IFLA_BR_VLAN_STATS_PER_PORT, ++ IFLA_BR_MULTI_BOOLOPT, + __IFLA_BR_MAX, + }; + +diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h +index be9b744a16458..2f01165514a77 100644 +--- a/include/uapi/linux/if_tun.h ++++ b/include/uapi/linux/if_tun.h +@@ -59,6 +59,7 @@ + #define TUNGETVNETBE _IOR('T', 223, int) + #define TUNSETSTEERINGEBPF _IOR('T', 224, int) + #define TUNSETFILTEREBPF _IOR('T', 225, int) ++#define TUNSETCARRIER _IOW('T', 226, int) + + /* TUNSETIFF ifr flags */ + #define IFF_TUN 0x0001 +diff --git a/include/uapi/linux/neighbour.h b/include/uapi/linux/neighbour.h +index 998155444e0db..cd144e3099a3c 100644 +--- a/include/uapi/linux/neighbour.h ++++ b/include/uapi/linux/neighbour.h +@@ -28,6 +28,7 @@ enum { + NDA_MASTER, + NDA_LINK_NETNSID, + NDA_SRC_VNI, ++ NDA_PROTOCOL, /* Originator of entry */ + __NDA_MAX + }; + +diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h +index 6d64d0716800f..fa81f1e5ffa8f 100644 +--- a/include/uapi/linux/net_namespace.h ++++ b/include/uapi/linux/net_namespace.h +@@ -16,6 +16,8 @@ enum { + NETNSA_NSID, + NETNSA_PID, + NETNSA_FD, ++ NETNSA_TARGET_NSID, ++ NETNSA_CURRENT_NSID, + __NETNSA_MAX, + }; + +diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h +index f80135e5feaa8..86dc24a96c90a 100644 +--- a/include/uapi/linux/snmp.h ++++ b/include/uapi/linux/snmp.h +@@ -243,6 +243,7 @@ enum + LINUX_MIB_TCPREQQFULLDROP, /* TCPReqQFullDrop */ + LINUX_MIB_TCPRETRANSFAIL, /* TCPRetransFail */ + LINUX_MIB_TCPRCVCOALESCE, /* TCPRcvCoalesce */ ++ LINUX_MIB_TCPBACKLOGCOALESCE, /* TCPBacklogCoalesce */ + LINUX_MIB_TCPOFOQUEUE, /* TCPOFOQueue */ + LINUX_MIB_TCPOFODROP, /* TCPOFODrop */ + LINUX_MIB_TCPOFOMERGE, /* TCPOFOMerge */ +-- +2.20.1 + diff --git a/SOURCES/0069-ip-xfrm-Respect-family-in-deleteall-and-list-command.patch b/SOURCES/0069-ip-xfrm-Respect-family-in-deleteall-and-list-command.patch new file mode 100644 index 0000000..6871452 --- /dev/null +++ b/SOURCES/0069-ip-xfrm-Respect-family-in-deleteall-and-list-command.patch @@ -0,0 +1,104 @@ +From 2f95b860ca09f8dc798204514b06b69cdfa0bd61 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Fri, 14 Jun 2019 11:04:17 +0200 +Subject: [PATCH] ip-xfrm: Respect family in deleteall and list commands + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1656717 +Upstream Status: iproute2.git commit cd21ae40130b4 +Conflicts: on ip xfrm manpage due to missing commit a6af9f2e6195d + ("xfrm: add option to hide keys in state output") + +commit cd21ae40130b4d1ddb3ef500800840e35e7bfad1 +Author: Phil Sutter +Date: Mon May 6 19:09:56 2019 +0200 + + ip-xfrm: Respect family in deleteall and list commands + + Allow to limit 'ip xfrm {state|policy} list' output to a certain address + family and to delete all states/policies by family. + + Although preferred_family was already set in filters, the filter + function ignored it. To enable filtering despite the lack of other + selectors, filter.use has to be set if family is not AF_UNSPEC. + + Signed-off-by: Phil Sutter + Signed-off-by: Stephen Hemminger +--- + ip/xfrm_policy.c | 6 +++++- + ip/xfrm_state.c | 6 +++++- + man/man8/ip-xfrm.8 | 4 ++-- + 3 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c +index d54402691ca0a..5bb3e873d2e8c 100644 +--- a/ip/xfrm_policy.c ++++ b/ip/xfrm_policy.c +@@ -400,6 +400,10 @@ static int xfrm_policy_filter_match(struct xfrm_userpolicy_info *xpinfo, + if (!filter.use) + return 1; + ++ if (filter.xpinfo.sel.family != AF_UNSPEC && ++ filter.xpinfo.sel.family != xpinfo->sel.family) ++ return 0; ++ + if ((xpinfo->dir^filter.xpinfo.dir)&filter.dir_mask) + return 0; + +@@ -773,7 +777,7 @@ static int xfrm_policy_list_or_deleteall(int argc, char **argv, int deleteall) + char *selp = NULL; + struct rtnl_handle rth; + +- if (argc > 0) ++ if (argc > 0 || preferred_family != AF_UNSPEC) + filter.use = 1; + filter.xpinfo.sel.family = preferred_family; + +diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c +index 85d959cc4f44f..2441959e98992 100644 +--- a/ip/xfrm_state.c ++++ b/ip/xfrm_state.c +@@ -876,6 +876,10 @@ static int xfrm_state_filter_match(struct xfrm_usersa_info *xsinfo) + if (!filter.use) + return 1; + ++ if (filter.xsinfo.family != AF_UNSPEC && ++ filter.xsinfo.family != xsinfo->family) ++ return 0; ++ + if (filter.id_src_mask) + if (xfrm_addr_match(&xsinfo->saddr, &filter.xsinfo.saddr, + filter.id_src_mask)) +@@ -1140,7 +1144,7 @@ static int xfrm_state_list_or_deleteall(int argc, char **argv, int deleteall) + char *idp = NULL; + struct rtnl_handle rth; + +- if (argc > 0) ++ if (argc > 0 || preferred_family != AF_UNSPEC) + filter.use = 1; + filter.xsinfo.family = preferred_family; + +diff --git a/man/man8/ip-xfrm.8 b/man/man8/ip-xfrm.8 +index 988cc6aa61d14..d5b9f083147c4 100644 +--- a/man/man8/ip-xfrm.8 ++++ b/man/man8/ip-xfrm.8 +@@ -87,7 +87,7 @@ ip-xfrm \- transform configuration + .IR MASK " ] ]" + + .ti -8 +-.BR "ip xfrm state" " { " deleteall " | " list " } [" ++.BR ip " [ " -4 " | " -6 " ] " "xfrm state" " { " deleteall " | " list " } [" + .IR ID " ]" + .RB "[ " mode + .IR MODE " ]" +@@ -244,7 +244,7 @@ ip-xfrm \- transform configuration + .IR PTYPE " ]" + + .ti -8 +-.BR "ip xfrm policy" " { " deleteall " | " list " }" ++.BR ip " [ " -4 " | " -6 " ] " "xfrm policy" " { " deleteall " | " list " }" + .RB "[ " nosock " ]" + .RI "[ " SELECTOR " ]" + .RB "[ " dir +-- +2.20.1 + diff --git a/SOURCES/avpkt b/SOURCES/avpkt new file mode 100644 index 0000000..c362b94 --- /dev/null +++ b/SOURCES/avpkt @@ -0,0 +1 @@ +AVPKT=3000 diff --git a/SOURCES/cbq-0000.example b/SOURCES/cbq-0000.example new file mode 100644 index 0000000..5503374 --- /dev/null +++ b/SOURCES/cbq-0000.example @@ -0,0 +1,5 @@ +DEVICE=eth0,10Mbit,1Mbit +RATE=128Kbit +WEIGHT=10Kbit +PRIO=5 +RULE=192.168.1.0/24 diff --git a/SOURCES/rt_dsfield.deprecated b/SOURCES/rt_dsfield.deprecated new file mode 100644 index 0000000..c8eec63 --- /dev/null +++ b/SOURCES/rt_dsfield.deprecated @@ -0,0 +1,17 @@ + +# Deprecated values dropped upstream +# Kept in RHEL for backwards-compatibility +0x00 default +0x10 lowdelay +0x08 throughput +0x04 reliability +# This value overlap with ECT, do not use it! +0x02 mincost +# These values seems do not want to die, Cisco likes them by a strange reason. +0x20 priority +0x40 immediate +0x60 flash +0x80 flash-override +0xa0 critical +0xc0 internet +0xe0 network diff --git a/SPECS/iproute.spec b/SPECS/iproute.spec new file mode 100644 index 0000000..f634e0f --- /dev/null +++ b/SPECS/iproute.spec @@ -0,0 +1,1075 @@ +%global cbq_version v0.7.3 + +%define rpmversion 4.18.0 +%define specrelease 13%{?dist} +%define pkg_release %{specrelease}%{?buildid} + +Summary: Advanced IP routing and network device configuration tools +Name: iproute +Version: %{rpmversion} +Release: %{pkg_release} +Group: Applications/System +URL: http://kernel.org/pub/linux/utils/net/%{name}2/ +Source0: http://kernel.org/pub/linux/utils/net/%{name}2/%{name}2-%{version}.tar.xz +Source1: cbq-0000.example +Source2: avpkt +Source3: rt_dsfield.deprecated +Patch0: 0001-man-bridge.8-Document-oneline-option.patch +Patch1: 0002-bridge-trivial-Make-help-text-consistent.patch +Patch2: 0003-devlink-trivial-Make-help-text-consistent.patch +Patch3: 0004-man-devlink.8-Document-verbose-option.patch +Patch4: 0005-genl-Fix-help-text.patch +Patch5: 0006-man-ifstat.8-Document-json-and-pretty-options.patch +Patch6: 0007-man-rtacct.8-Fix-nstat-options.patch +Patch7: 0008-rtmon-List-options-in-help-text.patch +Patch8: 0009-man-ss.8-Describe-events-option.patch +Patch9: 0010-ip-Add-missing-M-flag-to-help-text.patch +Patch10: 0011-iprule-Fix-destination-prefix-output.patch +Patch11: 0012-tc-act_tunnel_key-Enable-setup-of-tos-and-ttl.patch +Patch12: 0013-tc-flower-Add-match-on-encapsulating-tos-ttl.patch +Patch13: 0014-Update-kernel-headers.patch +Patch14: 0015-ip-route-Fix-segfault-with-many-nexthops.patch +Patch15: 0016-bridge-mdb-fix-missing-new-line-when-show-bridge-mdb.patch +Patch16: 0017-lib-introduce-print_nl.patch +Patch17: 0018-bridge-fdb-Fix-for-missing-keywords-in-non-JSON-outp.patch +Patch18: 0019-ip-addrlabel-Fix-printing-of-label-value.patch +Patch19: 0020-iplink_vxlan-take-into-account-preferred_family-crea.patch +Patch20: 0021-json-make-0xhex-handle-u64.patch +Patch21: 0022-macsec-fix-off-by-one-when-parsing-attributes.patch +Patch22: 0023-uapi-add-snmp-header-file.patch +Patch23: 0024-utils-fix-get_rtnl_link_stats_rta-stats-parsing.patch +Patch24: 0025-tc-htb-Print-default-value-in-hex.patch +Patch25: 0026-libnetlink-fix-leak-and-using-unused-memory-on-error.patch +Patch26: 0027-libnetlink-don-t-return-error-on-success.patch +Patch27: 0028-libnetlink-fix-use-after-free-of-message-buf.patch +Patch28: 0029-devlink-Fix-error-reporting-in-cmd_resource_set.patch +Patch29: 0030-rdma-Fix-for-ineffective-check-in-add_filter.patch +Patch30: 0031-ip-route-Fix-for-memleak-in-error-path.patch +Patch31: 0032-rdma-Don-t-pass-garbage-to-rd_check_is_filtered.patch +Patch32: 0033-ip-route-Fix-parse_encap_seg6-srh-parsing.patch +Patch33: 0034-tipc-Drop-unused-variable-genl.patch +Patch34: 0035-tc-Remove-pointless-assignments-in-batch.patch +Patch35: 0036-tc_util-Add-support-for-showing-TCA_STATS_BASIC_HW-s.patch +Patch36: 0037-Update-kernel-headers.patch +Patch37: 0038-man-ip-route.8-Document-nexthop-limit.patch +Patch38: 0039-ip-route-Fix-nexthop-encap-parsing.patch +Patch39: 0040-man-rdma-Add-reference-to-rdma-resource.8.patch +Patch40: 0041-iplink-fix-incorrect-any-address-handling-for-ip-tun.patch +Patch41: 0042-l2tp-Fix-printing-of-cookie-and-peer_cookie-values.patch +Patch42: 0043-tc-f_flower-add-geneve-option-match-support-to-flowe.patch +Patch43: 0044-tc-m_tunnel_key-Add-tunnel-option-support-to-act_tun.patch +Patch44: 0045-ip-rule-Add-ipproto-and-port-range-to-filter-list.patch +Patch45: 0046-tc-flower-Add-support-for-QinQ.patch +Patch46: 0047-uapi-update-ib_verbs.patch +Patch47: 0048-rdma-Fix-representation-of-PortInfo-CapabilityMask.patch +Patch48: 0049-devlink-Add-param-command-support.patch +Patch49: 0050-libnetlink-Convert-GETADDR-dumps-to-use-rtnl_addrdum.patch +Patch50: 0051-rdma-Update-kernel-include-file-to-support-IB-device.patch +Patch51: 0052-rdma-Introduce-command-execution-helper-with-require.patch +Patch52: 0053-rdma-Add-an-option-to-rename-IB-device-interface.patch +Patch53: 0054-rdma-Document-IB-device-renaming-option.patch +Patch54: 0055-iplink-add-support-for-reporting-multiple-XDP-progra.patch +Patch55: 0056-bpf-move-bpf_elf_map-fixup-notification-under-verbos.patch +Patch56: 0057-bpf-remove-strict-dependency-on-af_alg.patch +Patch57: 0058-bpf-implement-bpf-to-bpf-calls-support.patch +Patch58: 0059-bpf-implement-btf-handling-and-map-annotation.patch +Patch59: 0060-bpf-check-map-symbol-type-properly-with-newer-llvm-c.patch +Patch60: 0061-Use-libbsd-for-strlcpy-if-available.patch +Patch61: 0062-Include-bsd-string.h-only-in-include-utils.h.patch +Patch62: 0063-bpf-initialise-map-symbol-before-retrieving-and-comp.patch +Patch63: 0064-lib-bpf-fix-build-warning-if-no-elf.patch +Patch64: 0065-bpf-add-btf-func-and-func_proto-kind-support.patch +Patch65: 0066-uapi-update-headers-to-4.20-rc1.patch +Patch66: 0067-uapi-update-bpf-header.patch +Patch67: 0068-Update-kernel-headers.patch +Patch68: 0069-ip-xfrm-Respect-family-in-deleteall-and-list-command.patch +License: GPLv2+ and Public Domain +BuildRequires: bison +BuildRequires: elfutils-libelf-devel +BuildRequires: flex +BuildRequires: iptables-devel >= 1.4.5 +BuildRequires: libdb-devel +BuildRequires: libmnl-devel +BuildRequires: libselinux-devel +BuildRequires: pkgconfig +%if ! 0%{?_module_build} +%if 0%{?fedora} +BuildRequires: linux-atm-libs-devel +%endif +%endif +# For the UsrMove transition period +Conflicts: filesystem < 3 +Provides: /sbin/ip +Obsoletes: %{name} < 4.5.0-3 + +%description +The iproute package contains networking utilities (ip and rtmon, for example) +which are designed to use the advanced networking capabilities of the Linux +kernel. + +%package tc +Summary: Linux Traffic Control utility +Group: Applications/System +License: GPLv2+ +Obsoletes: %{name} < 4.5.0-3 +Requires: %{name}%{?_isa} = %{version}-%{release} +Provides: tc + +%description tc +The Traffic Control utility manages queueing disciplines, their classes and +attached filters and actions. It is the standard tool to configure QoS in +Linux. + +%if ! 0%{?_module_build} +%package doc +Summary: Documentation for iproute2 utilities with examples +Group: Applications/System +License: GPLv2+ +Requires: %{name} = %{version}-%{release} + +%description doc +The iproute documentation contains howtos and examples of settings. +%endif + +%package devel +Summary: iproute development files +Group: Development/Libraries +License: GPLv2+ +Requires: %{name} = %{version}-%{release} +Provides: iproute-static = %{version}-%{release} + +%description devel +The libnetlink static library. + +%prep +%autosetup -p1 -n %{name}2-%{version} + +%build +export CFLAGS="%{optflags} -fno-exceptions" +export LDFLAGS="%{build_ldflags}" +export LIBDIR=/%{_libdir} +export IPT_LIB_DIR=/%{_lib}/xtables +./configure +make %{?_smp_mflags} + +%install +export DESTDIR='%{buildroot}' +export SBINDIR='%{_sbindir}' +export MANDIR='%{_mandir}' +export LIBDIR='%{_libdir}' +export CONFDIR='%{_sysconfdir}/iproute2' +export DOCDIR='%{_docdir}' +%make_install + +install -m755 examples/cbq.init-%{cbq_version} ${DESTDIR}/${SBINDIR}/cbq +echo '.so man8/tc-cbq.8' > %{buildroot}%{_mandir}/man8/cbq.8 + +install -d -m755 %{buildroot}%{_sysconfdir}/sysconfig/cbq +for config in \ + %{SOURCE1} \ + %{SOURCE2} + do install -m644 ${config} %{buildroot}%{_sysconfdir}/sysconfig/cbq +done + +# libnetlink +install -D -m644 include/libnetlink.h %{buildroot}%{_includedir}/libnetlink.h +install -D -m644 lib/libnetlink.a %{buildroot}%{_libdir}/libnetlink.a + +# drop these files, iproute-doc package extracts files directly from _builddir +rm -rf '%{buildroot}%{_docdir}' + +# Append deprecated values to rt_dsfield for compatibility reasons +cat %{SOURCE3} >>%{buildroot}%{_sysconfdir}/iproute2/rt_dsfield + +%files +%dir %{_sysconfdir}/iproute2 +%{!?_licensedir:%global license %%doc} +%license COPYING +%doc README README.decnet README.iproute2+tc README.distribution README.lnstat +%{_mandir}/man7/* +%exclude %{_mandir}/man7/tc-* +%{_mandir}/man8/* +%exclude %{_mandir}/man8/tc* +%exclude %{_mandir}/man8/cbq* +%attr(644,root,root) %config(noreplace) %{_sysconfdir}/iproute2/* +%{_sbindir}/* +%exclude %{_sbindir}/tc +%exclude %{_sbindir}/cbq + +%files tc +%{!?_licensedir:%global license %%doc} +%license COPYING +%doc README.iproute2+tc +%{_mandir}/man7/tc-* +%{_mandir}/man8/tc* +%{_mandir}/man8/cbq* +%dir %{_libdir}/tc/ +%{_libdir}/tc/* +%{_sbindir}/tc +%{_sbindir}/cbq +%dir %{_sysconfdir}/sysconfig/cbq +%config(noreplace) %{_sysconfdir}/sysconfig/cbq/* +%{_datadir}/bash-completion/completions/tc + +%if ! 0%{?_module_build} +%files doc +%{!?_licensedir:%global license %%doc} +%license COPYING +%doc examples +%endif + +%files devel +%{!?_licensedir:%global license %%doc} +%license COPYING +%{_mandir}/man3/* +%{_libdir}/libnetlink.a +%{_includedir}/libnetlink.h +%{_includedir}/iproute2/bpf_elf.h + +%changelog +* Fri Jun 14 2019 Andrea Claudi [4.18.0-13.el8] +- ip-xfrm: Respect family in deleteall and list commands (Andrea Claudi) [1656717] +- Update kernel headers (Andrea Claudi) [1716361] +- uapi: update bpf header (Andrea Claudi) [1716361] +- uapi: update headers to 4.20-rc1 (Andrea Claudi) [1716361] +- bpf: add btf func and func_proto kind support (Andrea Claudi) [1716361] +- lib/bpf: fix build warning if no elf (Andrea Claudi) [1716361] +- bpf: initialise map symbol before retrieving and comparing its type (Andrea Claudi) [1716361] +- Include bsd/string.h only in include/utils.h (Andrea Claudi) [1716361] +- Use libbsd for strlcpy if available (Andrea Claudi) [1716361] +- bpf: check map symbol type properly with newer llvm compiler (Andrea Claudi) [1716361] +- bpf: implement btf handling and map annotation (Andrea Claudi) [1716361] +- bpf: implement bpf to bpf calls support (Andrea Claudi) [1716361] +- bpf: remove strict dependency on af_alg (Andrea Claudi) [1716361] +- bpf: move bpf_elf_map fixup notification under verbose (Andrea Claudi) [1716361] +- iplink: add support for reporting multiple XDP programs (Andrea Claudi) [1716361] +- rdma: Document IB device renaming option (Andrea Claudi) [1663228] +- rdma: Add an option to rename IB device interface (Andrea Claudi) [1663228] +- rdma: Introduce command execution helper with required device name (Andrea Claudi) [1663228] +- rdma: Update kernel include file to support IB device renaming (Andrea Claudi) [1663228] +- libnetlink: Convert GETADDR dumps to use rtnl_addrdump_req (Andrea Claudi) [1716772] + +* Wed May 29 2019 Andrea Claudi [4.18.0-12.el8] +- devlink: Add param command support (Andrea Claudi) [1663199] +- rdma: Fix representation of PortInfo CapabilityMask (Andrea Claudi) [1664694] +- uapi: update ib_verbs (Andrea Claudi) [1664694] +- tc: flower: Add support for QinQ (Andrea Claudi) [1615928] +- ip rule: Add ipproto and port range to filter list (Andrea Claudi) [1678111] + +* Thu Jan 31 2019 Phil Sutter [4.18.0-11.el8] +- tc: m_tunnel_key: Add tunnel option support to act_tunnel_key (Phil Sutter) [1654761] +- tc: f_flower: add geneve option match support to flower (Phil Sutter) [1654761] +- l2tp: Fix printing of cookie and peer_cookie values (Phil Sutter) [1643805] + +* Tue Dec 18 2018 Phil Sutter [4.18.0-10.el8] +- iplink: fix incorrect any address handling for ip tunnels (Phil Sutter) [1626304] + +* Tue Dec 11 2018 Phil Sutter [4.18.0-9.el8] +- man: rdma: Add reference to rdma-resource.8 (Phil Sutter) [1610334] + +* Thu Nov 29 2018 Phil Sutter [4.18.0-8.el8] +- Bump release to run fresh CI tests. + +* Mon Nov 26 2018 Phil Sutter [4.18.0-7.el8] +- ip-route: Fix nexthop encap parsing (Phil Sutter) [1625358] +- man: ip-route.8: Document nexthop limit (Phil Sutter) [1625358] + +* Thu Oct 25 2018 Phil Sutter [4.18.0-6.el8] +- Update kernel headers (Phil Sutter) [1637440] +- tc_util: Add support for showing TCA_STATS_BASIC_HW statistics (Phil Sutter) [1637440] +- tc: Remove pointless assignments in batch() (Phil Sutter) [1602555] +- tipc: Drop unused variable 'genl' (Phil Sutter) [1602555] +- ip-route: Fix parse_encap_seg6() srh parsing (Phil Sutter) [1602555] +- rdma: Don't pass garbage to rd_check_is_filtered() (Phil Sutter) [1602555] +- ip-route: Fix for memleak in error path (Phil Sutter) [1602555] +- rdma: Fix for ineffective check in add_filter() (Phil Sutter) [1602555] +- devlink: Fix error reporting in cmd_resource_set() (Phil Sutter) [1602555] +- libnetlink: fix use-after-free of message buf (Phil Sutter) [1602555] +- libnetlink: don't return error on success (Phil Sutter) [1602555] +- libnetlink: fix leak and using unused memory on error (Phil Sutter) [1602555] +- tc: htb: Print default value in hex (Phil Sutter) [1641053] + +* Thu Oct 18 2018 Phil Sutter [4.18.0-5.el8] +- utils: fix get_rtnl_link_stats_rta stats parsing (Phil Sutter) [1626306] +- uapi: add snmp header file (Phil Sutter) [1626306] +- macsec: fix off-by-one when parsing attributes (Phil Sutter) [1628428] +- json: make 0xhex handle u64 (Phil Sutter) [1628428] + +* Thu Oct 18 2018 Phil Sutter [4.18.0-4.el8] +- iplink_vxlan: take into account preferred_family creating vxlan device (Phil Sutter) [1626321] +- ip-addrlabel: Fix printing of label value (Phil Sutter) [1639412] +- bridge: fdb: Fix for missing keywords in non-JSON output (Phil Sutter) [1636532] + +* Wed Sep 19 2018 Phil Sutter [4.18.0-3.el8] +- lib: introduce print_nl (Phil Sutter) [1625500] + +* Wed Sep 19 2018 Phil Sutter [4.18.0-2.el8] +- bridge/mdb: fix missing new line when show bridge mdb (Phil Sutter) [1625500] +- ip-route: Fix segfault with many nexthops (Phil Sutter) [1625358] +- Update kernel headers (Phil Sutter) [1615915] +- tc/flower: Add match on encapsulating tos/ttl (Phil Sutter) [1615915] +- tc/act_tunnel_key: Enable setup of tos and ttl (Phil Sutter) [1615915] +- iprule: Fix destination prefix output (Phil Sutter) [1623503] +- ip: Add missing -M flag to help text (Phil Sutter) [1612704] +- man: ss.8: Describe --events option (Phil Sutter) [1612704] +- rtmon: List options in help text (Phil Sutter) [1612704] +- man: rtacct.8: Fix nstat options (Phil Sutter) [1612704] +- man: ifstat.8: Document --json and --pretty options (Phil Sutter) [1612704] +- genl: Fix help text (Phil Sutter) [1612704] +- man: devlink.8: Document -verbose option (Phil Sutter) [1612704] +- devlink: trivial: Make help text consistent (Phil Sutter) [1612704] +- bridge: trivial: Make help text consistent (Phil Sutter) [1612704] +- man: bridge.8: Document -oneline option (Phil Sutter) [1612704] + +* Tue Aug 14 2018 Phil Sutter - 4.18.0-1 +- New version 4.18.0 + +* Thu Aug 09 2018 Phil Sutter [4.17.0-1.el8] +- rdma: print driver resource attributes (Phil Sutter) [1610334] +- rdma: update rdma_netlink.h to get new driver attributes (Phil Sutter) [1610334] +- rdma: Print net device name and index for RDMA device (Phil Sutter) [1610334] +- devlink: CTRL_ATTR_FAMILY_ID is a u16 (Phil Sutter) [1589317] +- tc: Do not use addattr_nest_compat on mqprio and netem (Phil Sutter) [1589317] +- ipaddress: Fix and make consistent label match handling (Phil Sutter) [1589317] +- rt_dsfield: Ship deprecated values for compatibility (Phil Sutter) [1595683] +- New version 4.17.0 including upstream-suggested fixes (Phil Sutter) [1589317] + +* Fri Feb 09 2018 Phil Sutter - 4.15.0-1 +- New version 4.15.0 + +* Fri Feb 9 2018 Florian Weimer - 4.14.1-6 +- Use LDFLAGS defaults from redhat-rpm-config + +* Wed Feb 07 2018 Fedora Release Engineering - 4.14.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Mon Dec 11 2017 Phil Sutter - 4.14.1-4 +- Add missing patch files. + +* Mon Dec 11 2017 Phil Sutter - 4.14.1-3 +- Add upstream suggested backports. +- Make use of %%autosetup macro. + +* Wed Nov 15 2017 Phil Sutter - 4.14.1-2 +- Drop unused build dependencies + +* Wed Nov 15 2017 Phil Sutter - 4.14.1-1 +- New version 4.14.1 + +* Tue Sep 19 2017 Phil Sutter - 4.13.0-1 +- New version 4.13.0 + +* Wed Aug 02 2017 Fedora Release Engineering - 4.12.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 4.12.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Fri Jul 21 2017 Phil Sutter - 4.12.0-1 +- New version 4.12.0 + +* Tue May 23 2017 Phil Sutter - 4.11.0-1 +- Add virtual capability to tc subpackage so it's easier found +- New version 4.11.0 + +* Thu May 11 2017 Karsten Hopp - 4.10.0-3 +- don't build docs for module builds to limit dependencies + +* Fri Mar 17 2017 Phil Sutter - 4.10.0-2 +- Add two fixes to 4.10.0 release from upstream. + +* Tue Mar 14 2017 Phil Sutter - 4.10.0-1 +- Ship new header iproute2/bpf_elf.h +- Document content of remaining docs fixup patch in spec file +- Drop patches already applied upstream +- New version 4.10.0 + +* Fri Feb 10 2017 Fedora Release Engineering - 4.9.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Feb 2 2017 Thomas Woerner - 4.9.0-3 +- Release bump for iptables-1.6.1 (libxtables.so.12) + +* Sat Jan 28 2017 Phil Sutter - 4.9.0-2 +- Fix for failing 'make install' + +* Sat Jan 28 2017 Phil Sutter - 4.9.0-1 +- New version 4.9.0 + +* Fri Jan 13 2017 Phil Sutter - 4.8.0-2 +- Fix segfault in xt action + +* Wed Nov 30 2016 Phil Sutter - 4.8.0-1 +- New version 4.8.0 + +* Wed Aug 10 2016 Phil Sutter - 4.7.0-1 +- New version 4.7.0 + +* Wed May 04 2016 Phil Sutter - 4.6.0-1 +- New version 4.6.0 + +* Wed Apr 13 2016 Thomas Woerner - 4.5.0-4 +- Rebuild for new iptables-1.6.0 with libxtables so bump + +* Fri Apr 08 2016 Phil Sutter - 4.5.0-3 +- Fix upgrade path by adding correct Requires/Obsoletes statements to spec file +- Move README.iproute2+tc into tc subpackage + +* Fri Mar 18 2016 Phil Sutter - 4.5.0-2 +- Split tc into it's own subpackage + +* Fri Mar 18 2016 Phil Sutter - 4.5.0-1 +- New version 4.5.0 + +* Thu Feb 04 2016 Fedora Release Engineering - 4.4.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Tue Jan 19 2016 Phil Sutter - 4.4.0-1 +- New version 4.4.0 + +* Sun Oct 04 2015 Phil Sutter - 4.2.0-4 +- Simplify RPM install stage by using package's install target + +* Sun Oct 04 2015 Phil Sutter - 4.2.0-3 +- Add missing build dependency to libmnl-devel +- Ship tipc utility + +* Thu Sep 24 2015 Phil Sutter - 4.2.0-2 +- Add missing build dependency to libselinux-devel + +* Wed Sep 02 2015 Pavel Šimerda - 4.2.0-1 +- new version 4.2.0 + +* Tue Jul 07 2015 Pavel Šimerda - 4.1.1-1 +- new version 4.1.1 + +* Wed Jun 17 2015 Fedora Release Engineering - 4.0.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Wed May 13 2015 Pavel Šimerda - 4.0.0-3 +- remove patch rejected by upstream + +* Mon May 11 2015 Pavel Šimerda - 4.0.0-2 +- Remove patch rejected by upstream + +* Tue Apr 14 2015 Pavel Šimerda - 4.0.0-1 +- new version 4.0.0 + +* Fri Mar 13 2015 Pavel Šimerda - 3.19.0-1 +- new version 3.19.0 + +* Sat Oct 04 2014 Lubomir Rintel - 3.16.0-3 +- Backport fix for ip link add name regression that broke libvirt + +* Sat Aug 16 2014 Fedora Release Engineering - 3.16.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Tue Aug 05 2014 Petr Šabata - 3.16.0-1 +- 3.16 bump + +* Sat Jul 12 2014 Tom Callaway - 3.15.0-2 +- fix license handling + +* Thu Jun 12 2014 Petr Šabata - 3.15.0-1 +- 3.15.0 bump + +* Sat Jun 07 2014 Fedora Release Engineering - 3.14.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue May 06 2014 Petr Šabata - 3.14.0-2 +- Fix incorrect references in ss(8), #1092653 + +* Tue Apr 15 2014 Petr Šabata - 3.14.0-1 +- 3.14 bump +- Drop out iplink_have_newlink() fix in favor of upstream's approach + +* Tue Nov 26 2013 Petr Šabata - 3.12.0-2 +- Drop libnl from dependencies (#1034454) + +* Mon Nov 25 2013 Petr Šabata - 3.12.0-1 +- 3.12.0 bump + +* Thu Nov 21 2013 Petr Šabata - 3.11.0-2 +- Fix the rtt time parsing again + +* Tue Oct 22 2013 Petr Šabata - 3.11.0-1 +- 3.11 bump + +* Tue Oct 01 2013 Petr Pisar - 3.10.0-8 +- Close file with bridge monitor file (bug #1011822) + +* Tue Sep 24 2013 Petr Pisar - 3.10.0-7 +- Add tc -OK option +- Document "bridge mdb" and "bridge monitor mdb" + +* Fri Aug 30 2013 Petr Šabata - 3.10.0-6 +- Fix lnstat -i properly this time + +* Thu Aug 29 2013 Petr Šabata - 3.10.0-5 +- Fix an 'ip link' hang (#996537) + +* Tue Aug 13 2013 Petr Šabata - 3.10.0-4 +- lnstat -i: Run indefinitely if the --count isn't specified (#977845) +- Switch to unversioned %%docdir + +* Sat Aug 03 2013 Fedora Release Engineering - 3.10.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Wed Jul 17 2013 Petr Šabata - 3.10.0-2 +- Fix the XFRM patch + +* Wed Jul 17 2013 Petr Šabata - 3.10.0-1 +- 3.10.0 bump +- Drop the SHAREDIR patch and revert to upstream ways (#966445) +- Fix an XFRM regression with FORTIFY_SOURCE + +* Tue Apr 30 2013 Petr Šabata - 3.9.0-1 +- 3.9.0 bump + +* Thu Apr 25 2013 Petr Šabata - 3.8.0-4 +- ATM is available in Fedora only + +* Tue Mar 12 2013 Petr Šabata - 3.8.0-3 +- Mention the "up" argument in documentation and help outputs (#907468) + +* Mon Mar 04 2013 Petr Šabata - 3.8.0-2 +- Bump for 1.4.18 rebuild + +* Tue Feb 26 2013 Petr Šabata - 3.8.0-1 +- 3.8.0 bump + +* Fri Feb 08 2013 Petr Šabata - 3.7.0-2 +- Don't propogate mounts out of ip (#882047) + +* Wed Dec 12 2012 Petr Šabata - 3.7.0-1 +- 3.7.0 bump + +* Mon Nov 19 2012 Petr Šabata - 3.6.0-3 +- Include section 7 manpages (#876857) +- Fix ancient bogus dates in the changelog (correction based upon commits) +- Explicitly require some TeX fonts no longer present in the base distribution + +* Thu Oct 04 2012 Petr Šabata - 3.6.0-2 +- List all interfaces by default + +* Wed Oct 03 2012 Petr Šabata - 3.6.0-1 +- 3.6.0 bump + +* Thu Aug 30 2012 Petr Šabata - 3.5.1-2 +- Remove the explicit iptables dependency (#852840) + +* Tue Aug 14 2012 Petr Šabata - 3.5.1-1 +- 3.5.1 bugfix release bump +- Rename 'br' to 'bridge' + +* Mon Aug 06 2012 Petr Šabata - 3.5.0-2 +- Install the new bridge utility + +* Thu Aug 02 2012 Petr Šabata - 3.5.0-1 +- 3.5.0 bump +- Move to db5. + +* Thu Jul 19 2012 Fedora Release Engineering - 3.4.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue May 22 2012 Petr Šabata - 3.4.0-1 +- 3.4.0 bump +- Drop the print route patch (included upstream) + +* Mon Apr 30 2012 Petr Šabata - 3.3.0-2 +- Let's install rtmon too... (#814819) + +* Thu Mar 22 2012 Petr Šabata - 3.3.0-1 +- 3.3.0 bump +- Update source URL + +* Mon Feb 27 2012 Petr Šabata - 3.2.0-3 +- Address dangerous /tmp files security issue (CVE-2012-1088, #797881, #797878) + +* Fri Jan 27 2012 Petr Šabata - 3.2.0-2 +- Simplify the spec a bit thanks to the UsrMove feature + +* Fri Jan 06 2012 Petr Šabata - 3.2.0-1 +- 3.2.0 bump +- Removing a useless, now conflicting patch (initcwnd already decumented) + +* Thu Nov 24 2011 Petr Šabata - 3.1.0-1 +- 3.1.0 bump +- Point URL and Source to the new location on kernel.org +- Remove now obsolete defattr +- Dropping various patches now included upstream +- Dropping iproute2-2.6.25-segfault.patch; I fail to understand the reason for + this hack + +* Tue Nov 15 2011 Petr Šabata - 2.6.39-6 +- ss -ul should display UDP CLOSED sockets (#691100) + +* Thu Oct 06 2011 Petr Sabata - 2.6.39-5 +- Fix ss, lnstat and arpd usage and manpages + +* Wed Sep 07 2011 Petr Sabata - 2.6.39-4 +- lnstat should dump (-d) to stdout instead of stderr (#736332) + +* Tue Jul 26 2011 Petr Sabata - 2.6.39-3 +- Rebuild for xtables7 + +* Tue Jul 12 2011 Petr Sabata - 2.6.39-2 +- Rebuild for xtables6 + +* Thu Jun 30 2011 Petr Sabata - 2.6.39-1 +- 2.6.39 bump + +* Wed Apr 27 2011 Petr Sabata - 2.6.38.1-4 +- Link [cr]tstat to lnstat + +* Wed Apr 27 2011 Petr Sabata - 2.6.38.1-3 +- Install ctstat, rtstat and routef manpage symlinks +- Install m_xt & m_ipt tc modules +- Creating devel and virtual static subpackages with libnetlink + +* Thu Apr 21 2011 Petr Sabata - 2.6.38.1-2 +- General cleanup +- Use global instead of define +- Buildroot removal +- Correcting URL and Source links +- Install genl, ifstat, routef, routel and rtpr (rhbz#697319) + +* Fri Mar 18 2011 Petr Sabata - 2.6.38.1-1 +- 2.6.38.1 bump + +* Wed Mar 16 2011 Petr Sabata - 2.6.38-1 +- 2.6.38 bump + +* Wed Feb 09 2011 Fedora Release Engineering - 2.6.37-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Mon Jan 31 2011 Petr Sabata - 2.6.37-2 +- man-pages.patch update, ip(8) TYPE whitespace + +* Mon Jan 10 2011 Petr Sabata - 2.6.37-1 +- 2.6.37 upstream release +- ss(8) improvements patch removed (included upstream) + +* Wed Dec 08 2010 Petr Sabata - 2.6.35-10 +- fix a typo in ss(8) improvements patch, rhbz#661267 + +* Tue Nov 30 2010 Petr Sabata - 2.6.35-9 +- ss(8) improvements patch by jpopelka; should be included in 2.6.36 + +* Tue Nov 09 2010 Petr Sabata - 2.6.35-8 +- rhbz#641599, use the versioned path, man-pages.patch update, prep update + +* Tue Oct 12 2010 Petr Sabata - 2.6.35-7 +- Do not segfault if peer name is omitted when creating a peer veth link, rhbz#642322 + +* Mon Oct 11 2010 Petr Sabata - 2.6.35-6 +- Man-pages update, rhbz#641599 + +* Wed Sep 29 2010 jkeating - 2.6.35-5 +- Rebuilt for gcc bug 634757 + +* Tue Sep 21 2010 Petr Sabata - 2.6.35-4 +- Modified man-pages.patch to fix cbq manpage, rhbz#635877 + +* Tue Sep 21 2010 Petr Sabata - 2.6.35-3 +- Don't print routes with negative metric fix, rhbz#628739 + +* Wed Aug 18 2010 Petr Sabata - 2.6.35-2 +- 'ip route get' fix, iproute2-2.6.35-print-route.patch +- rhbz#622782 + +* Thu Aug 05 2010 Petr Sabata - 2.6.35-1 +- 2.6.35 version bump +- iproute2-tc-priority.patch removed (included in upstream now) + +* Thu Jul 08 2010 Petr Sabata - 2.6.34-5 +- Licensing guidelines compliance fix + +* Wed Jul 07 2010 Petr Sabata - 2.6.34-4 +- Requires: iptables >= 1.4.5, BuildRequires: iptables-devel >= 1.4.5 + +* Thu Jul 01 2010 Petr Sabata - 2.6.34-3 +- Build now runs ./configure to regenerate Makefile for ipt/xt detection + +* Mon Jun 21 2010 Petr Sabata - 2.6.34-2 +- iproute-tc-priority.patch, rhbz#586112 + +* Mon Jun 21 2010 Petr Sabata - 2.6.34-1 +- 2.6.34 version bump + +* Tue Apr 20 2010 Marcela Mašláňová - 2.6.33-2 +- 578729 6rd tunnel correctly 3979ef91de9ed17d21672aaaefd6c228485135a2 +- change BR texlive to tex according to guidelines + +* Thu Feb 25 2010 Marcela Mašláňová - 2.6.33-1 +- update + +* Tue Jan 26 2010 Marcela Mašláňová - 2.6.32-2 +- add macvlan aka VESA support d63a9b2b1e4e3eab0d0577d0a0f412d50be1e0a7 +- kernel headers 2.6.33 ab322673298bd0b8927cdd9d11f3d36af5941b93 + are needed for macvlan features and probably for other added later. +- fix number of release which contains 2.6.32 kernel headers and features + but it was released as 2.6.31 + +* Mon Jan 4 2010 Marcela Mašláňová - 2.6.31-1 +- update to 2.6.31 + +* Fri Nov 27 2009 Marcela Mašláňová - 2.6.29-5.1.20091106gita7a9ddbb +- 539232 patch cbq initscript + +* Fri Nov 27 2009 Marcela Mašláňová - 2.6.29-5.0.20091106gita7a9ddbb +- snapshot with kernel headers for 2.6.32 + +* Fri Oct 9 2009 Marcela Mašláňová - 2.6.29-5.0.20091009gitdaf49fd6 +- new official version isn't available but it's needed -> switch to git snapshots + +* Thu Sep 24 2009 Marcela Mašláňová - 2.6.29-5 +- create missing man pages + +* Fri Jul 24 2009 Fedora Release Engineering - 2.6.29-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Thu Apr 23 2009 Marcela Mašláňová - 2.6.29-3 +- new iptables (xtables) bring problems to tc, when ipt is used. + rhbz#497344 still broken. tc_modules.patch brings correct paths to + xtables, but that doesn't fix whole issue. +- 497355 ip should allow creation of an IPsec SA with 'proto any' + and specified sport and dport as selectors + +* Tue Apr 14 2009 Marcela Mašláňová - 2.6.29-2 +- c3651bf4763d7247e3edd4e20526a85de459041b ip6tunnel: Fix no default + display of ip4ip6 tunnels +- e48f73d6a5e90d2f883e15ccedf4f53d26bb6e74 missing arpd directory + +* Wed Mar 25 2009 Marcela Mašláňová - 2.6.29-1 +- update to 2.6.29 +- remove DDR patch which became part of sourc +- add patch with correct headers 1957a322c9932e1a1d2ca1fd37ce4b335ceb7113 + +* Wed Feb 25 2009 Fedora Release Engineering - 2.6.28-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Wed Feb 4 2009 Marcela Mašláňová - 2.6.28-2 +- 483484 install distribution files into /usr/share and also fixed + install paths in spec +- add the latest change from git which add DRR support + c86f34942a0ce9f8203c0c38f9fe9604f96be706 + +* Mon Jan 19 2009 Marcela Mašláňová - 2.6.28-1 +- previous two patches were included into 2.6.28 release. +- update + +* Mon Jan 12 2009 Marcela Mašláňová - 2.6.27-2 +- 475130 - Negative preferred lifetimes of IPv6 prefixes/addresses + displayed incorrectly +- 472878 - “ip maddr show” in IB interface causes a stack corruption +- both patches will be probably in iproute v2.6.28 + +* Thu Dec 4 2008 Marcela Maslanova - 2.6.27-1 +- aead support was included into upstream version +- patch for moving libs is now deprecated +- update to 2.6.27 + +* Tue Aug 12 2008 Marcela Maslanova - 2.6.26-1 +- update to 2.6.26 +- clean patches + +* Tue Jul 22 2008 Marcela Maslanova - 2.6.25-5 +- fix iproute2-2.6.25-segfault.patch + +* Thu Jul 10 2008 Tom "spot" Callaway - 2.6.25-4 +- rebuild for new db4-4.7 + +* Thu Jul 3 2008 Marcela Maslanova - 2.6.25-3 +- 449933 instead of failing strncpy use copying byte after byte + +* Wed May 14 2008 Marcela Maslanova - 2.6.25-2 +- allow replay setting, solve also 444724 + +* Mon Apr 21 2008 Marcela Maslanova - 2.6.25-1 +- update +- remove patch for backward compatibility +- add patch for AEAD compatibility + +* Thu Feb 21 2008 Marcela Maslanova - 2.6.23-4 +- add creating ps file again. Fix was done in texlive + +* Wed Feb 6 2008 Marcela Maslanova - 2.6.23-3 +- rebuild without tetex files. It isn't working in rawhide yet. Added + new source for ps files. +- #431179 backward compatibility for previous iproute versions + +* Mon Jan 21 2008 Marcela Maslanova - 2.6.23-2 +- rebuild with fix tetex and linuxdoc-tools -> manual pdf +- clean unnecessary patches +- add into spec *.so objects, new BR linux-atm-libs-devel + +* Wed Oct 31 2007 Marcela Maslanova - 2.6.23-1 +- new version from upstrem 2.3.23 + +* Tue Oct 23 2007 Marcela Maslanova - 2.6.22-5 +- move files from /usr/lib/tc to /usr/share/tc +- remove listing files twice + +* Fri Aug 31 2007 Marcela Maslanova - 2.6.22-3 +- package review #225903 + +* Mon Aug 27 2007 Jeremy Katz - 2.6.22-2 +- rebuild for new db4 + +* Wed Jul 11 2007 Radek Vokál - 2.6.22-1 +- upgrade to 2.6.22 + +* Mon Mar 19 2007 Radek Vokál - 2.6.20-2 +- fix broken tc-pfifo man page (#232891) + +* Thu Mar 15 2007 Radek Vokál - 2.6.20-1 +- upgrade to 2.6.20 + +* Fri Dec 15 2006 Radek Vokál - 2.6.19-1 +- upgrade to 2.6.19 + +* Mon Dec 11 2006 Radek Vokál - 2.6.18-5 +- fix snapshot version + +* Fri Dec 1 2006 Radek Vokál - 2.6.18-4 +- spec file cleanup +- one more rebuilt against db4 + +* Thu Nov 16 2006 Radek Vokál - 2.6.18-3 +- fix defective manpage for tc-pfifo (#215399) + +* Mon Nov 13 2006 Radek Vokál - 2.6.18-2 +- rebuilt against new db4 + +* Tue Oct 3 2006 Radek Vokal - 2.6.18-1 +- upgrade to upstream 2.6.18 +- initcwnd patch merged +- bug fix for xfrm monitor +- alignment fixes for cris +- documentation corrections + +* Mon Oct 2 2006 Radek Vokal - 2.6.16-7 +- fix ip.8 man page, add initcwnd option + +* Sun Oct 01 2006 Jesse Keating - 2.6.16-6 +- rebuilt for unwind info generation, broken in gcc-4.1.1-21 + +* Tue Sep 19 2006 Radek Vokal - 2.6.16-5 +- fix crash when resolving ip address + +* Mon Aug 21 2006 Radek Vokál - 2.6.16-4 +- add LOWER_UP and DORMANT flags (#202199) +- use dist tag + +* Wed Jul 12 2006 Jesse Keating - 2.6.16-3.1 +- rebuild + +* Mon Jun 26 2006 Radek Vokál - 2.6.16-3 +- improve handling of initcwnd value (#179719) + +* Sun May 28 2006 Radek Vokál - 2.6.16-2 +- fix BuildRequires: flex (#193403) + +* Sun Mar 26 2006 Radek Vokál - 2.6.16-1 +- upgrade to 2.6.16-060323 +- don't hardcode /usr/lib in tc (#186607) + +* Wed Feb 22 2006 Radek Vokál - 2.6.15-2 +- own /usr/lib/tc (#181953) +- obsoletes shapecfg (#182284) + +* Fri Feb 10 2006 Jesse Keating - 2.6.15-1.2 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 2.6.15-1.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Tue Jan 17 2006 Radek Vokal 2.6.15-1 +- upgrade to 2.6.15-060110 + +* Mon Dec 12 2005 Radek Vokal 2.6.14-11 +- rebuilt + +* Fri Dec 09 2005 Radek Vokal 2.6.14-10 +- remove backup of config files (#175302) + +* Fri Nov 11 2005 Radek Vokal 2.6.14-9 +- use tc manpages and cbq.init from source tarball (#172851) + +* Thu Nov 10 2005 Radek Vokal 2.6.14-8 +- new upstream source + +* Mon Oct 31 2005 Radek Vokal 2.6.14-7 +- add warning to ip tunnel add command (#128107) + +* Fri Oct 07 2005 Bill Nottingham 2.6.14-6 +- update from upstream (appears to fix #170111) + +* Fri Oct 07 2005 Radek Vokal 2.6.14-5 +- update from upstream +- fixed host_len size for memcpy (#168903) + +* Fri Sep 23 2005 Radek Vokal 2.6.14-4 +- add RPM_OPT_FLAGS + +* Mon Sep 19 2005 Radek Vokal 2.6.14-3 +- forget to apply the patch :( + +* Mon Sep 19 2005 Radek Vokal 2.6.14-2 +- make ip help work again (#168449) + +* Wed Sep 14 2005 Radek Vokal 2.6.14-1 +- upgrade to ss050901 for 2.6.14 kernel headers + +* Fri Aug 26 2005 Radek Vokal 2.6.13-3 +- added /sbin/cbq script and sample configuration files (#166301) + +* Fri Aug 19 2005 Radek Vokal 2.6.13-2 +- upgrade to iproute2-050816 + +* Thu Aug 11 2005 Radek Vokal 2.6.13-1 +- update to snapshot for 2.6.13+ kernel + +* Tue May 24 2005 Radek Vokal 2.6.11-2 +- removed useless initvar patch (#150798) +- new upstream source + +* Tue Mar 15 2005 Radek Vokal 2.6.11-1 +- update to iproute-2.6.11 + +* Fri Mar 04 2005 Radek Vokal 2.6.10-2 +- gcc4 rebuilt + +* Wed Feb 16 2005 Radek Vokal 2.6.10-1 +- update to iproute-2.6.10 + +* Thu Dec 23 2004 Radek Vokal 2.6.9-6 +- added arpd into sbin + +* Mon Nov 29 2004 Radek Vokal 2.6.9-5 +- debug info removed from makefile and from spec (#140891) + +* Tue Nov 16 2004 Radek Vokal 2.6.9-4 +- source file updated from snapshot version +- endian patch adding + +* Sat Sep 18 2004 Joshua Blanton 2.6.9-3 +- added installation of netem module for tc + +* Mon Sep 06 2004 Radek Vokal 2.6.9-2 +- fixed possible buffer owerflow, path by Steve Grubb + +* Wed Sep 01 2004 Radek Vokal 2.6.9-1 +- updated to iproute-2.6.9, spec file change, patches cleared + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Wed May 26 2004 Phil Knirsch 2.4.7-16 +- Took tons of manpages from debian, much more complete (#123952). + +* Thu May 06 2004 Phil Knirsch 2.4.7-15 +- rebuilt + +* Thu May 06 2004 Phil Knirsch 2.4.7-13.2 +- Built security errata version for FC1. + +* Wed Apr 21 2004 Phil Knirsch 2.4.7-14 +- Fixed -f option for ss (#118355). +- Small description fix (#110997). +- Added initialization of some vars (#74961). +- Added patch to initialize "default" rule as well (#60693). + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Wed Nov 05 2003 Phil Knirsch 2.4.7-12 +- Security errata for netlink (CAN-2003-0856). + +* Thu Oct 23 2003 Phil Knirsch +- Updated to latest version. Used by other distros, so seems stable. ;-) +- Quite a few patches needed updating in that turn. +- Added ss (#107363) and several other new nifty tools. + +* Tue Jun 17 2003 Phil Knirsch +- rebuilt + +* Wed Jun 04 2003 Elliot Lee +- rebuilt + +* Wed Jan 22 2003 Tim Powers +- rebuilt + +* Thu Jan 16 2003 Phil Knirsch 2.4.7-7 +- Added htb3-tc patch from http://luxik.cdi.cz/~devik/qos/htb/ (#75486). + +* Fri Oct 11 2002 Bill Nottingham 2.4.7-6 +- remove flags patch at author's request + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Wed Jun 19 2002 Phil Knirsch 2.4.7-4 +- Don't forcibly strip binaries + +* Mon May 27 2002 Phil Knirsch 2.4.7-3 +- Fixed missing diffserv and atm support in config (#57278). +- Fixed inconsistent numeric base problem for command line (#65473). + +* Tue May 14 2002 Phil Knirsch 2.4.7-2 +- Added patch to fix crosscompiling by Adrian Linkins. + +* Fri Mar 15 2002 Phil Knirsch 2.4.7-1 +- Update to latest stable release 2.4.7-now-ss010824. +- Added simple man page for ip. + +* Wed Aug 8 2001 Bill Nottingham +- allow setting of allmulti & promisc flags (#48669) + +* Mon Jul 02 2001 Than Ngo +- fix build problem in beehive if kernel-sources is not installed + +* Fri May 25 2001 Helge Deller +- updated to iproute2-2.2.4-now-ss001007.tar.gz +- bzip2 source tar file +- "License" replaces "Copyright" +- added "BuildPrereq: tetex-latex tetex-dvips psutils" +- rebuilt for 7.2 + +* Tue May 1 2001 Bill Nottingham +- use the system headers - the included ones are broken +- ETH_P_ECHO went away + +* Sat Jan 6 2001 Jeff Johnson +- test for specific KERNEL_INCLUDE directories. + +* Thu Oct 12 2000 Than Ngo +- rebuild for 7.1 + +* Thu Oct 12 2000 Than Ngo +- add default configuration files for iproute (Bug #10549, #18887) + +* Tue Jul 25 2000 Jakub Jelinek +- fix include-glibc/ to cope with glibc 2.2 new resolver headers + +* Thu Jul 13 2000 Prospector +- automatic rebuild + +* Sun Jun 18 2000 Than Ngo +- rebuilt in the new build environment +- use RPM macros +- handle RPM_OPT_FLAGS + +* Sat Jun 03 2000 Than Ngo +- fix iproute to build with new glibc + +* Fri May 26 2000 Ngo Than +- update to 2.2.4-now-ss000305 +- add configuration files + +* Mon Sep 13 1999 Bill Nottingham +- strip binaries + +* Mon Aug 16 1999 Cristian Gafton +- first build