diff --git a/SOURCES/0001-Update-kernel-headers.patch b/SOURCES/0001-Update-kernel-headers.patch index 5b5550f..4d6f5d2 100644 --- a/SOURCES/0001-Update-kernel-headers.patch +++ b/SOURCES/0001-Update-kernel-headers.patch @@ -1,5 +1,4 @@ From 4cd2ea662ae3255713a7de44e496e6ed32ade0c9 Mon Sep 17 00:00:00 2001 -Message-Id: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> From: Andrea Claudi Date: Thu, 16 Apr 2020 12:41:48 +0200 Subject: [PATCH] Update kernel headers @@ -223,5 +222,5 @@ index 04f763cf53029..31fc51bdedb3c 100644 __u16 vid; struct { -- -2.25.3 +2.25.4 diff --git a/SOURCES/0002-Update-kernel-headers.patch b/SOURCES/0002-Update-kernel-headers.patch index 77f6908..3ffe6a3 100644 --- a/SOURCES/0002-Update-kernel-headers.patch +++ b/SOURCES/0002-Update-kernel-headers.patch @@ -1,7 +1,4 @@ From 864c5a906ccfe205f886aa4bfb69f738a9a4fb45 Mon Sep 17 00:00:00 2001 -Message-Id: <864c5a906ccfe205f886aa4bfb69f738a9a4fb45.1587661326.git.aclaudi@redhat.com> -In-Reply-To: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> -References: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> From: Andrea Claudi Date: Thu, 16 Apr 2020 12:41:49 +0200 Subject: [PATCH] Update kernel headers @@ -139,5 +136,5 @@ index e16cb4e2af587..0f6f28b2e3010 100644 /* * Flag values -- -2.25.3 +2.25.4 diff --git a/SOURCES/0003-tc-implement-support-for-action-flags.patch b/SOURCES/0003-tc-implement-support-for-action-flags.patch index 6b4ff11..aef92b7 100644 --- a/SOURCES/0003-tc-implement-support-for-action-flags.patch +++ b/SOURCES/0003-tc-implement-support-for-action-flags.patch @@ -1,7 +1,4 @@ From a3d12445422afa12a67a7cd121b7add89f6c7d67 Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> -References: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> From: Andrea Claudi Date: Thu, 16 Apr 2020 12:41:49 +0200 Subject: [PATCH] tc: implement support for action flags @@ -115,5 +112,5 @@ index bdc62720879c1..c46aeaafa8ebf 100644 return 0; } -- -2.25.3 +2.25.4 diff --git a/SOURCES/0004-man-rdma-statistic-Add-filter-description.patch b/SOURCES/0004-man-rdma-statistic-Add-filter-description.patch index 8d60df3..9b805b9 100644 --- a/SOURCES/0004-man-rdma-statistic-Add-filter-description.patch +++ b/SOURCES/0004-man-rdma-statistic-Add-filter-description.patch @@ -1,7 +1,4 @@ From f0596659bb2ba71bbe6ec80df9d54ea02775f40f Mon Sep 17 00:00:00 2001 -Message-Id: -In-Reply-To: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> -References: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> From: Andrea Claudi Date: Thu, 23 Apr 2020 12:47:12 +0200 Subject: [PATCH] man: rdma-statistic: Add filter description @@ -109,5 +106,5 @@ index ef0bbcf147a70..cd99b7ace73fc 100644 pr_out(" %s statistic qp show\n", rd->filename); pr_out(" %s statistic qp show link mlx5_2/1\n", rd->filename); -- -2.25.3 +2.25.4 diff --git a/SOURCES/0005-man-rdma.8-Add-missing-resource-subcommand-descripti.patch b/SOURCES/0005-man-rdma.8-Add-missing-resource-subcommand-descripti.patch index d44931f..2a64a79 100644 --- a/SOURCES/0005-man-rdma.8-Add-missing-resource-subcommand-descripti.patch +++ b/SOURCES/0005-man-rdma.8-Add-missing-resource-subcommand-descripti.patch @@ -1,7 +1,4 @@ From 44362b42a40ed0f3a3598f55318ed4b0c9f8eb94 Mon Sep 17 00:00:00 2001 -Message-Id: <44362b42a40ed0f3a3598f55318ed4b0c9f8eb94.1587661326.git.aclaudi@redhat.com> -In-Reply-To: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> -References: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> From: Andrea Claudi Date: Thu, 23 Apr 2020 12:49:03 +0200 Subject: [PATCH] man: rdma.8: Add missing resource subcommand description @@ -50,5 +47,5 @@ index ef29b1c633644..221bf3343bf4c 100644 .B sys - RDMA subsystem related. -- -2.25.3 +2.25.4 diff --git a/SOURCES/0006-ip-xfrm-Fix-help-messages.patch b/SOURCES/0006-ip-xfrm-Fix-help-messages.patch index 066af77..11858c1 100644 --- a/SOURCES/0006-ip-xfrm-Fix-help-messages.patch +++ b/SOURCES/0006-ip-xfrm-Fix-help-messages.patch @@ -1,7 +1,4 @@ From 028ce3bafd9c8415a0cd72ff135f9498d833db21 Mon Sep 17 00:00:00 2001 -Message-Id: <028ce3bafd9c8415a0cd72ff135f9498d833db21.1587661326.git.aclaudi@redhat.com> -In-Reply-To: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> -References: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> From: Andrea Claudi Date: Wed, 15 Apr 2020 19:09:48 +0200 Subject: [PATCH] ip-xfrm: Fix help messages @@ -107,5 +104,5 @@ index b03ccc5807e90..7b413cd9b9a22 100644 "LIMIT := { time-soft | time-hard | time-use-soft | time-use-hard } SECONDS |\n" " { byte-soft | byte-hard } SIZE | { packet-soft | packet-hard } COUNT\n" -- -2.25.3 +2.25.4 diff --git a/SOURCES/0007-xfrm-not-try-to-delete-ipcomp-states-when-using-dele.patch b/SOURCES/0007-xfrm-not-try-to-delete-ipcomp-states-when-using-dele.patch index 87cbe8c..66d479f 100644 --- a/SOURCES/0007-xfrm-not-try-to-delete-ipcomp-states-when-using-dele.patch +++ b/SOURCES/0007-xfrm-not-try-to-delete-ipcomp-states-when-using-dele.patch @@ -1,7 +1,4 @@ From 7c1351ea866ec811ade4452b5f1791b34b0effe3 Mon Sep 17 00:00:00 2001 -Message-Id: <7c1351ea866ec811ade4452b5f1791b34b0effe3.1587661326.git.aclaudi@redhat.com> -In-Reply-To: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> -References: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> From: Andrea Claudi Date: Thu, 16 Apr 2020 12:10:23 +0200 Subject: [PATCH] xfrm: not try to delete ipcomp states when using deleteall @@ -54,5 +51,5 @@ index 7b413cd9b9a22..d014444e9af4f 100644 fprintf(stderr, "State buffer overflow\n"); return -1; -- -2.25.3 +2.25.4 diff --git a/SOURCES/0008-man-ip.8-Add-missing-vrf-subcommand-description.patch b/SOURCES/0008-man-ip.8-Add-missing-vrf-subcommand-description.patch index 7bc0e7b..0a36572 100644 --- a/SOURCES/0008-man-ip.8-Add-missing-vrf-subcommand-description.patch +++ b/SOURCES/0008-man-ip.8-Add-missing-vrf-subcommand-description.patch @@ -1,7 +1,4 @@ From 310becad3223411bc26e0401a838f2a7063406f3 Mon Sep 17 00:00:00 2001 -Message-Id: <310becad3223411bc26e0401a838f2a7063406f3.1587661326.git.aclaudi@redhat.com> -In-Reply-To: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> -References: <4cd2ea662ae3255713a7de44e496e6ed32ade0c9.1587661326.git.aclaudi@redhat.com> From: Andrea Claudi Date: Thu, 23 Apr 2020 18:56:14 +0200 Subject: [PATCH] man: ip.8: Add missing vrf subcommand description @@ -58,5 +55,5 @@ index e2bda2a2ea904..c425aaf1d506e 100644 .br .RB "IP Command reference " ip-cref.ps -- -2.25.3 +2.25.4 diff --git a/SOURCES/0009-nstat-print-useful-error-messages-in-abort-cases.patch b/SOURCES/0009-nstat-print-useful-error-messages-in-abort-cases.patch new file mode 100644 index 0000000..8e439d5 --- /dev/null +++ b/SOURCES/0009-nstat-print-useful-error-messages-in-abort-cases.patch @@ -0,0 +1,122 @@ +From 5723280683d940b33647b8dc92a3aa3b1a9a5466 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 30 Apr 2020 12:20:17 +0200 +Subject: [PATCH] nstat: print useful error messages in abort() cases +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1824896 +Upstream Status: iproute2.git commit 2c7056ac26412 + +commit 2c7056ac26412fe99443a283f0c1261cb81ccea2 +Author: Andrea Claudi +Date: Mon Feb 17 14:46:18 2020 +0100 + + nstat: print useful error messages in abort() cases + + When nstat temporary file is corrupted or in some other corner cases, + nstat use abort() to stop its execution. This can puzzle some users, + wondering what is the reason for the crash. + + This commit replaces abort() with some meaningful error messages and exit() + + Reported-by: Renaud Métrich + Signed-off-by: Andrea Claudi + Signed-off-by: Stephen Hemminger +--- + misc/nstat.c | 47 +++++++++++++++++++++++++++++++++-------------- + 1 file changed, 33 insertions(+), 14 deletions(-) + +diff --git a/misc/nstat.c b/misc/nstat.c +index 23113b223b22d..425e75ef461ec 100644 +--- a/misc/nstat.c ++++ b/misc/nstat.c +@@ -142,14 +142,19 @@ static void load_good_table(FILE *fp) + } + /* idbuf is as big as buf, so this is safe */ + nr = sscanf(buf, "%s%llu%lg", idbuf, &val, &rate); +- if (nr < 2) +- abort(); ++ if (nr < 2) { ++ fprintf(stderr, "%s:%d: error parsing history file\n", ++ __FILE__, __LINE__); ++ exit(-2); ++ } + if (nr < 3) + rate = 0; + if (useless_number(idbuf)) + continue; +- if ((n = malloc(sizeof(*n))) == NULL) +- abort(); ++ if ((n = malloc(sizeof(*n))) == NULL) { ++ perror("nstat: malloc"); ++ exit(-1); ++ } + n->id = strdup(idbuf); + n->val = val; + n->rate = rate; +@@ -190,8 +195,11 @@ static void load_ugly_table(FILE *fp) + int count1, count2, skip = 0; + + p = strchr(buf, ':'); +- if (!p) +- abort(); ++ if (!p) { ++ fprintf(stderr, "%s:%d: error parsing history file\n", ++ __FILE__, __LINE__); ++ exit(-2); ++ } + count1 = count_spaces(buf); + *p = 0; + idbuf[0] = 0; +@@ -211,8 +219,10 @@ static void load_ugly_table(FILE *fp) + strncat(idbuf, p, sizeof(idbuf) - off - 1); + } + n = malloc(sizeof(*n)); +- if (!n) +- abort(); ++ if (!n) { ++ perror("nstat: malloc"); ++ exit(-1); ++ } + n->id = strdup(idbuf); + n->rate = 0; + n->next = db; +@@ -221,18 +231,27 @@ static void load_ugly_table(FILE *fp) + } + n = db; + nread = getline(&buf, &buflen, fp); +- if (nread == -1) +- abort(); ++ if (nread == -1) { ++ fprintf(stderr, "%s:%d: error parsing history file\n", ++ __FILE__, __LINE__); ++ exit(-2); ++ } + count2 = count_spaces(buf); + if (count2 > count1) + skip = count2 - count1; + do { + p = strrchr(buf, ' '); +- if (!p) +- abort(); ++ if (!p) { ++ fprintf(stderr, "%s:%d: error parsing history file\n", ++ __FILE__, __LINE__); ++ exit(-2); ++ } + *p = 0; +- if (sscanf(p+1, "%llu", &n->val) != 1) +- abort(); ++ if (sscanf(p+1, "%llu", &n->val) != 1) { ++ fprintf(stderr, "%s:%d: error parsing history file\n", ++ __FILE__, __LINE__); ++ exit(-2); ++ } + /* Trick to skip "dummy" trailing ICMP MIB in 2.4 */ + if (skip) + skip--; +-- +2.25.4 + diff --git a/SOURCES/0010-ip-link-xstats-fix-TX-IGMP-reports-string.patch b/SOURCES/0010-ip-link-xstats-fix-TX-IGMP-reports-string.patch new file mode 100644 index 0000000..0ab0707 --- /dev/null +++ b/SOURCES/0010-ip-link-xstats-fix-TX-IGMP-reports-string.patch @@ -0,0 +1,40 @@ +From 28a6ef808bd5c196c2259f7841a97c1ba703479d Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 30 Apr 2020 12:32:41 +0200 +Subject: [PATCH] ip link: xstats: fix TX IGMP reports string + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1796041 +Upstream Status: iproute2.git commit 5cdeb77cd6ec2 + +commit 5cdeb77cd6ec26f0a7103dfb21494a6a43903206 +Author: Andrea Claudi +Date: Wed Jan 29 15:31:11 2020 +0100 + + ip link: xstats: fix TX IGMP reports string + + This restore the string format we have before jsonification, adding a + missing space between v2 and v3 on TX IGMP reports string. + + Fixes: a9bc23a79227a ("ip: bridge: add xstats json support") + Signed-off-by: Andrea Claudi + Signed-off-by: Stephen Hemminger +--- + ip/iplink_bridge.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c +index 06f736d4dc710..868ea6e266ebe 100644 +--- a/ip/iplink_bridge.c ++++ b/ip/iplink_bridge.c +@@ -742,7 +742,7 @@ static void bridge_print_stats_attr(struct rtattr *attr, int ifindex) + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", + mstats->igmp_v1reports[BR_MCAST_DIR_TX]); +- print_u64(PRINT_ANY, "tx_v2", "v2 %llu", ++ print_u64(PRINT_ANY, "tx_v2", "v2 %llu ", + mstats->igmp_v2reports[BR_MCAST_DIR_TX]); + print_u64(PRINT_ANY, "tx_v3", "v3 %llu\n", + mstats->igmp_v3reports[BR_MCAST_DIR_TX]); +-- +2.25.4 + diff --git a/SOURCES/0011-ip-fix-ip-route-show-json-output-for-multipath-nexth.patch b/SOURCES/0011-ip-fix-ip-route-show-json-output-for-multipath-nexth.patch new file mode 100644 index 0000000..c82b769 --- /dev/null +++ b/SOURCES/0011-ip-fix-ip-route-show-json-output-for-multipath-nexth.patch @@ -0,0 +1,148 @@ +From 65d5e933e5162c3464857ee233a2f20e778ee1b6 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 30 Apr 2020 12:35:47 +0200 +Subject: [PATCH] ip: fix ip route show json output for multipath nexthops + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1738633 +Upstream Status: iproute2.git commit 4ecefff3cf250 + +commit 4ecefff3cf250c1e4499dff14c80ed38bec6d7de +Author: Julien Fortin +Date: Thu Sep 26 17:29:34 2019 +0200 + + ip: fix ip route show json output for multipath nexthops + + print_rta_multipath doesn't support JSON output: + + { + "dst":"27.0.0.13", + "protocol":"bgp", + "metric":20, + "flags":[], + "gateway":"169.254.0.1"dev uplink-1 weight 1 , + "flags":["onlink"], + "gateway":"169.254.0.1"dev uplink-2 weight 1 , + "flags":["onlink"] + }, + + since RTA_MULTIPATH has nested objects we should print them + in a json array. + + With the path we have the following output: + + { + "flags": [], + "dst": "36.0.0.13", + "protocol": "bgp", + "metric": 20, + "nexthops": [ + { + "weight": 1, + "flags": [ + "onlink" + ], + "gateway": "169.254.0.1", + "dev": "uplink-1" + }, + { + "weight": 1, + "flags": [ + "onlink" + ], + "gateway": "169.254.0.1", + "dev": "uplink-2" + } + ] + } + + Fixes: 663c3cb23103f4 ("iproute: implement JSON and color output") + + Signed-off-by: Julien Fortin + Signed-off-by: David Ahern +--- + ip/iproute.c | 46 ++++++++++++++++++++++++++++------------------ + 1 file changed, 28 insertions(+), 18 deletions(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index a453385113cb9..32bb52df250c2 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -649,24 +649,26 @@ static void print_rta_multipath(FILE *fp, const struct rtmsg *r, + int len = RTA_PAYLOAD(rta); + int first = 1; + ++ open_json_array(PRINT_JSON, "nexthops"); ++ + while (len >= sizeof(*nh)) { + struct rtattr *tb[RTA_MAX + 1]; + + if (nh->rtnh_len > len) + break; + +- if (!is_json_context()) { +- if ((r->rtm_flags & RTM_F_CLONED) && +- r->rtm_type == RTN_MULTICAST) { +- if (first) { +- fprintf(fp, "Oifs: "); +- first = 0; +- } else { +- fprintf(fp, " "); +- } +- } else +- fprintf(fp, "%s\tnexthop ", _SL_); +- } ++ open_json_object(NULL); ++ ++ if ((r->rtm_flags & RTM_F_CLONED) && ++ r->rtm_type == RTN_MULTICAST) { ++ if (first) { ++ print_string(PRINT_FP, NULL, "Oifs: ", NULL); ++ first = 0; ++ } else { ++ print_string(PRINT_FP, NULL, " ", NULL); ++ } ++ } else ++ print_string(PRINT_FP, NULL, "%s\tnexthop ", _SL_); + + if (nh->rtnh_len > sizeof(*nh)) { + parse_rtattr(tb, RTA_MAX, RTNH_DATA(nh), +@@ -689,22 +691,30 @@ static void print_rta_multipath(FILE *fp, const struct rtmsg *r, + + if ((r->rtm_flags & RTM_F_CLONED) && + r->rtm_type == RTN_MULTICAST) { +- fprintf(fp, "%s", ll_index_to_name(nh->rtnh_ifindex)); ++ print_string(PRINT_ANY, "dev", ++ "%s", ll_index_to_name(nh->rtnh_ifindex)); ++ + if (nh->rtnh_hops != 1) +- fprintf(fp, "(ttl>%d)", nh->rtnh_hops); +- fprintf(fp, " "); ++ print_int(PRINT_ANY, "ttl", "(ttl>%d)", nh->rtnh_hops); ++ ++ print_string(PRINT_FP, NULL, " ", NULL); + } else { +- fprintf(fp, "dev %s ", ll_index_to_name(nh->rtnh_ifindex)); ++ print_string(PRINT_ANY, "dev", ++ "dev %s ", ll_index_to_name(nh->rtnh_ifindex)); ++ + if (r->rtm_family != AF_MPLS) +- fprintf(fp, "weight %d ", +- nh->rtnh_hops+1); ++ print_int(PRINT_ANY, "weight", ++ "weight %d ", nh->rtnh_hops + 1); + } + + print_rt_flags(fp, nh->rtnh_flags); + + len -= NLMSG_ALIGN(nh->rtnh_len); + nh = RTNH_NEXT(nh); ++ ++ close_json_object(); + } ++ close_json_array(PRINT_JSON, NULL); + } + + int print_route(struct nlmsghdr *n, void *arg) +-- +2.25.4 + diff --git a/SOURCES/0012-man-bridge.8-fix-bridge-link-show-description.patch b/SOURCES/0012-man-bridge.8-fix-bridge-link-show-description.patch new file mode 100644 index 0000000..7e0c378 --- /dev/null +++ b/SOURCES/0012-man-bridge.8-fix-bridge-link-show-description.patch @@ -0,0 +1,48 @@ +From 12bf930c542feeb9578d9320bc39a34365747127 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 30 Apr 2020 12:43:30 +0200 +Subject: [PATCH] man: bridge.8: fix bridge link show description + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1817571 +Upstream Status: iproute2.git commit 0641bed8a3c77 + +commit 0641bed8a3c779c37746c4d7be9e01a35e920841 +Author: Andrea Claudi +Date: Fri Mar 27 11:45:12 2020 +0100 + + man: bridge.8: fix bridge link show description + + When multiple bridges are present, 'bridge link show' diplays ports + for all bridges. Make this clear in the command description, and + point out the user to the ip command to display ports for a specific + bridge. + + Reported-by: Marc Muehlfeld + Signed-off-by: Andrea Claudi + Signed-off-by: Stephen Hemminger +--- + man/man8/bridge.8 | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 +index bb4fb521f8e57..d750e54a17b8b 100644 +--- a/man/man8/bridge.8 ++++ b/man/man8/bridge.8 +@@ -409,9 +409,12 @@ link setting is configured on the software bridge (default) + .BR "\-t" , " \-timestamp" + display current time when using monitor option. + +-.SS bridge link show - list bridge port configuration. ++.SS bridge link show - list ports configuration for all bridges. + +-This command displays the current bridge port configuration and flags. ++This command displays port configuration and flags for all bridges. ++ ++To display port configuration and flags for a specific bridge, use the ++"ip link show master " command. + + .SH bridge fdb - forwarding database management + +-- +2.25.4 + diff --git a/SOURCES/0013-xfrm-also-check-for-ipv6-state-in-xfrm_state_keep.patch b/SOURCES/0013-xfrm-also-check-for-ipv6-state-in-xfrm_state_keep.patch new file mode 100644 index 0000000..8d5b4b4 --- /dev/null +++ b/SOURCES/0013-xfrm-also-check-for-ipv6-state-in-xfrm_state_keep.patch @@ -0,0 +1,53 @@ +From 40dda2fc9fb2597996e443117df18995c58444a9 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 30 Apr 2020 12:46:30 +0200 +Subject: [PATCH] xfrm: also check for ipv6 state in xfrm_state_keep + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1828033 +Upstream Status: iproute2.git commit d27fc6390ce32 + +commit d27fc6390ce32ecdba6324e22b1c341791c5c63f +Author: Xin Long +Date: Mon Apr 27 15:14:24 2020 +0800 + + xfrm: also check for ipv6 state in xfrm_state_keep + + As commit f9d696cf414c ("xfrm: not try to delete ipcomp states when using + deleteall") does, this patch is to fix the same issue for ip6 state where + xsinfo->id.proto == IPPROTO_IPV6. + + # ip xfrm state add src 2000::1 dst 2000::2 spi 0x1000 \ + proto comp comp deflate mode tunnel sel src 2000::1 dst \ + 2000::2 proto gre + # ip xfrm sta deleteall + Failed to send delete-all request + : Operation not permitted + + Note that the xsinfo->proto in common states can never be IPPROTO_IPV6. + + Fixes: f9d696cf414c ("xfrm: not try to delete ipcomp states when using deleteall") + Reported-by: Xiumei Mu + Signed-off-by: Xin Long + Acked-by: Andrea Claudi + Signed-off-by: Stephen Hemminger +--- + ip/xfrm_state.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c +index d014444e9af4f..44f08ceed24dd 100644 +--- a/ip/xfrm_state.c ++++ b/ip/xfrm_state.c +@@ -1131,7 +1131,8 @@ static int xfrm_state_keep(struct nlmsghdr *n, void *arg) + if (!xfrm_state_filter_match(xsinfo)) + return 0; + +- if (xsinfo->id.proto == IPPROTO_IPIP) ++ if (xsinfo->id.proto == IPPROTO_IPIP || ++ xsinfo->id.proto == IPPROTO_IPV6) + return 0; + + if (xb->offset > xb->size) { +-- +2.25.4 + diff --git a/SOURCES/0014-Update-kernel-headers-and-import-udp.h.patch b/SOURCES/0014-Update-kernel-headers-and-import-udp.h.patch new file mode 100644 index 0000000..cef917b --- /dev/null +++ b/SOURCES/0014-Update-kernel-headers-and-import-udp.h.patch @@ -0,0 +1,115 @@ +From 90897540c719814eca34ce6b5b78b3bb76c4a43a Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Fri, 5 Jun 2020 15:42:49 +0200 +Subject: [PATCH] Update kernel headers and import udp.h + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1844045 +Upstream Status: iproute2.git commit 4df5ad933ca8c + +commit 4df5ad933ca8cebf23a4868061b28ab869e9b77a +Author: David Ahern +Date: Wed Jan 22 03:40:26 2020 +0000 + + Update kernel headers and import udp.h + + Update kernel headers to commit: + 4f2c17e0f332 ("Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next") + + and import udp.h for the next patch. + + Signed-off-by: David Ahern +--- + include/uapi/linux/hdlc/ioctl.h | 9 +++++++ + include/uapi/linux/if.h | 1 + + include/uapi/linux/udp.h | 47 +++++++++++++++++++++++++++++++++ + 3 files changed, 57 insertions(+) + create mode 100644 include/uapi/linux/udp.h + +diff --git a/include/uapi/linux/hdlc/ioctl.h b/include/uapi/linux/hdlc/ioctl.h +index 0fe4238e82462..b06341acab5ec 100644 +--- a/include/uapi/linux/hdlc/ioctl.h ++++ b/include/uapi/linux/hdlc/ioctl.h +@@ -79,6 +79,15 @@ typedef struct { + unsigned int timeout; + } cisco_proto; + ++typedef struct { ++ unsigned short dce; /* 1 for DCE (network side) operation */ ++ unsigned int modulo; /* modulo (8 = basic / 128 = extended) */ ++ unsigned int window; /* frame window size */ ++ unsigned int t1; /* timeout t1 */ ++ unsigned int t2; /* timeout t2 */ ++ unsigned int n2; /* frame retry counter */ ++} x25_hdlc_proto; ++ + /* PPP doesn't need any info now - supply length = 0 to ioctl */ + + #endif /* __ASSEMBLY__ */ +diff --git a/include/uapi/linux/if.h b/include/uapi/linux/if.h +index 495cdd2324428..626da393123b6 100644 +--- a/include/uapi/linux/if.h ++++ b/include/uapi/linux/if.h +@@ -210,6 +210,7 @@ struct if_settings { + fr_proto *fr; + fr_proto_pvc *fr_pvc; + fr_proto_pvc_info *fr_pvc_info; ++ x25_hdlc_proto *x25; + + /* interface settings */ + sync_serial_settings *sync; +diff --git a/include/uapi/linux/udp.h b/include/uapi/linux/udp.h +new file mode 100644 +index 0000000000000..d0a7223a0119c +--- /dev/null ++++ b/include/uapi/linux/udp.h +@@ -0,0 +1,47 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * INET An implementation of the TCP/IP protocol suite for the LINUX ++ * operating system. INET is implemented using the BSD Socket ++ * interface as the means of communication with the user level. ++ * ++ * Definitions for the UDP protocol. ++ * ++ * Version: @(#)udp.h 1.0.2 04/28/93 ++ * ++ * Author: Fred N. van Kempen, ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++#ifndef _LINUX_UDP_H ++#define _LINUX_UDP_H ++ ++#include ++ ++struct udphdr { ++ __be16 source; ++ __be16 dest; ++ __be16 len; ++ __sum16 check; ++}; ++ ++/* UDP socket options */ ++#define UDP_CORK 1 /* Never send partially complete segments */ ++#define UDP_ENCAP 100 /* Set the socket to accept encapsulated packets */ ++#define UDP_NO_CHECK6_TX 101 /* Disable sending checksum for UDP6X */ ++#define UDP_NO_CHECK6_RX 102 /* Disable accpeting checksum for UDP6 */ ++#define UDP_SEGMENT 103 /* Set GSO segmentation size */ ++#define UDP_GRO 104 /* This socket can receive UDP GRO packets */ ++ ++/* UDP encapsulation types */ ++#define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ ++#define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */ ++#define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */ ++#define UDP_ENCAP_GTP0 4 /* GSM TS 09.60 */ ++#define UDP_ENCAP_GTP1U 5 /* 3GPP TS 29.060 */ ++#define UDP_ENCAP_RXRPC 6 ++#define TCP_ENCAP_ESPINTCP 7 /* Yikes, this is really xfrm encap types. */ ++ ++#endif /* _LINUX_UDP_H */ +-- +2.26.2 + diff --git a/SOURCES/0015-ip-xfrm-add-espintcp-encapsulation.patch b/SOURCES/0015-ip-xfrm-add-espintcp-encapsulation.patch new file mode 100644 index 0000000..d19a729 --- /dev/null +++ b/SOURCES/0015-ip-xfrm-add-espintcp-encapsulation.patch @@ -0,0 +1,110 @@ +From b0312111114ed805f84b1e96d73f468e3a372025 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Fri, 5 Jun 2020 15:42:49 +0200 +Subject: [PATCH] ip: xfrm: add espintcp encapsulation + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1844045 +Upstream Status: iproute2.git commit 22aec42679d57 + +commit 22aec42679d57b8e0aef864c4d45feadb727c3ce +Author: Sabrina Dubroca +Date: Sun Jan 19 11:32:09 2020 +0100 + + ip: xfrm: add espintcp encapsulation + + While at it, convert xfrm_xfrma_print and xfrm_encap_type_parse to use + the UAPI macros for encap_type as suggested by David Ahern, and add the + UAPI udp.h header (sync'd from ipsec-next to get the TCP_ENCAP_ESPINTCP + definition). + + Co-developed-by: Herbert Xu + Signed-off-by: Sabrina Dubroca + Signed-off-by: David Ahern +--- + ip/ipxfrm.c | 14 ++++++++++---- + ip/xfrm_state.c | 2 +- + man/man8/ip-xfrm.8 | 4 ++-- + 3 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c +index 32f560933a477..fec206abc1f03 100644 +--- a/ip/ipxfrm.c ++++ b/ip/ipxfrm.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + #include "utils.h" + #include "xfrm.h" +@@ -753,12 +754,15 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family, + + fprintf(fp, "type "); + switch (e->encap_type) { +- case 1: ++ case UDP_ENCAP_ESPINUDP_NON_IKE: + fprintf(fp, "espinudp-nonike "); + break; +- case 2: ++ case UDP_ENCAP_ESPINUDP: + fprintf(fp, "espinudp "); + break; ++ case TCP_ENCAP_ESPINTCP: ++ fprintf(fp, "espintcp "); ++ break; + default: + fprintf(fp, "%u ", e->encap_type); + break; +@@ -1208,9 +1212,11 @@ int xfrm_encap_type_parse(__u16 *type, int *argcp, char ***argvp) + char **argv = *argvp; + + if (strcmp(*argv, "espinudp-nonike") == 0) +- *type = 1; ++ *type = UDP_ENCAP_ESPINUDP_NON_IKE; + else if (strcmp(*argv, "espinudp") == 0) +- *type = 2; ++ *type = UDP_ENCAP_ESPINUDP; ++ else if (strcmp(*argv, "espintcp") == 0) ++ *type = TCP_ENCAP_ESPINTCP; + else + invarg("ENCAP-TYPE value is invalid", *argv); + +diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c +index 44f08ceed24dd..f4bf3356bb01f 100644 +--- a/ip/xfrm_state.c ++++ b/ip/xfrm_state.c +@@ -112,7 +112,7 @@ static void usage(void) + "LIMIT-LIST := [ LIMIT-LIST ] limit LIMIT\n" + "LIMIT := { time-soft | time-hard | time-use-soft | time-use-hard } SECONDS |\n" + " { byte-soft | byte-hard } SIZE | { packet-soft | packet-hard } COUNT\n" +- "ENCAP := { espinudp | espinudp-nonike } SPORT DPORT OADDR\n" ++ "ENCAP := { espinudp | espinudp-nonike | espintcp } SPORT DPORT OADDR\n" + "DIR := in | out\n"); + + exit(-1); +diff --git a/man/man8/ip-xfrm.8 b/man/man8/ip-xfrm.8 +index cfce1e40b7f7d..f99f30bb448a6 100644 +--- a/man/man8/ip-xfrm.8 ++++ b/man/man8/ip-xfrm.8 +@@ -207,7 +207,7 @@ ip-xfrm \- transform configuration + + .ti -8 + .IR ENCAP " :=" +-.RB "{ " espinudp " | " espinudp-nonike " }" ++.RB "{ " espinudp " | " espinudp-nonike " | " espintcp " }" + .IR SPORT " " DPORT " " OADDR + + .ti -8 +@@ -548,7 +548,7 @@ sets limits in seconds, bytes, or numbers of packets. + .TP + .I ENCAP + encapsulates packets with protocol +-.BR espinudp " or " espinudp-nonike "," ++.BR espinudp ", " espinudp-nonike ", or " espintcp "," + .RI "using source port " SPORT ", destination port " DPORT + .RI ", and original address " OADDR "." + +-- +2.26.2 + diff --git a/SOURCES/0016-Update-kernel-headers-and-import-mptcp.h.patch b/SOURCES/0016-Update-kernel-headers-and-import-mptcp.h.patch new file mode 100644 index 0000000..2d709bd --- /dev/null +++ b/SOURCES/0016-Update-kernel-headers-and-import-mptcp.h.patch @@ -0,0 +1,177 @@ +From 93f77d1e57c84093b91bc9227929cfb4a24534e9 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:25:47 +0200 +Subject: [PATCH] Update kernel headers and import mptcp.h + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: iproute2.git commit 02ade5a8ea1c2 +Conflicts: on bpf uapi due to missing commit b5a77cf70116f ("uapi: update bpf.h") + and on if_bridge uapi due to several unrelated missing changes. + +commit 02ade5a8ea1c23201a99d8cdf7e02a6ba90d7718 +Author: David Ahern +Date: Wed Apr 29 16:41:39 2020 +0000 + + Update kernel headers and import mptcp.h + + Update kernel headers to commit + 790ab249b55d ("net: ethernet: fec: Prevent MII event after MII_SPEED write") + + and import mptcp.h + + Signed-off-by: David Ahern +--- + include/uapi/linux/if.h | 1 + + include/uapi/linux/if_bridge.h | 1 + + include/uapi/linux/if_ether.h | 1 + + include/uapi/linux/if_link.h | 1 + + include/uapi/linux/mptcp.h | 89 ++++++++++++++++++++++++++++++++++ + 5 files changed, 93 insertions(+) + create mode 100644 include/uapi/linux/mptcp.h + +diff --git a/include/uapi/linux/if.h b/include/uapi/linux/if.h +index 626da393123b6..9a3bc23d0235e 100644 +--- a/include/uapi/linux/if.h ++++ b/include/uapi/linux/if.h +@@ -175,6 +175,7 @@ enum { + enum { + IF_LINK_MODE_DEFAULT, + IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */ ++ IF_LINK_MODE_TESTING, /* limit upward transition to testing */ + }; + + /* +diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h +index 31fc51bdedb3c..53ba8385b022e 100644 +--- a/include/uapi/linux/if_bridge.h ++++ b/include/uapi/linux/if_bridge.h +@@ -120,6 +120,7 @@ enum { + IFLA_BRIDGE_MODE, + IFLA_BRIDGE_VLAN_INFO, + IFLA_BRIDGE_VLAN_TUNNEL_INFO, ++ IFLA_BRIDGE_MRP, + __IFLA_BRIDGE_MAX, + }; + #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) +diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h +index 728c42dfd59c1..1a0c7dfe8e38e 100644 +--- a/include/uapi/linux/if_ether.h ++++ b/include/uapi/linux/if_ether.h +@@ -92,6 +92,7 @@ + #define ETH_P_PREAUTH 0x88C7 /* 802.11 Preauthentication */ + #define ETH_P_TIPC 0x88CA /* TIPC */ + #define ETH_P_LLDP 0x88CC /* Link Layer Discovery Protocol */ ++#define ETH_P_MRP 0x88E3 /* Media Redundancy Protocol */ + #define ETH_P_MACSEC 0x88E5 /* 802.1ae MACsec */ + #define ETH_P_8021AH 0x88E7 /* 802.1ah Backbone Service Tag */ + #define ETH_P_MVRP 0x88F5 /* 802.1Q MVRP */ +diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h +index d36919fb4024a..4da0768d7a5a3 100644 +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -338,6 +338,7 @@ enum { + IFLA_BRPORT_NEIGH_SUPPRESS, + IFLA_BRPORT_ISOLATED, + IFLA_BRPORT_BACKUP_PORT, ++ IFLA_BRPORT_MRP_RING_OPEN, + __IFLA_BRPORT_MAX + }; + #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) +diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h +new file mode 100644 +index 0000000000000..009b8f0b0e8be +--- /dev/null ++++ b/include/uapi/linux/mptcp.h +@@ -0,0 +1,89 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++#ifndef _MPTCP_H ++#define _MPTCP_H ++ ++#include ++#include ++ ++#define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0) ++#define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1) ++#define MPTCP_SUBFLOW_FLAG_JOIN_REM _BITUL(2) ++#define MPTCP_SUBFLOW_FLAG_JOIN_LOC _BITUL(3) ++#define MPTCP_SUBFLOW_FLAG_BKUP_REM _BITUL(4) ++#define MPTCP_SUBFLOW_FLAG_BKUP_LOC _BITUL(5) ++#define MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED _BITUL(6) ++#define MPTCP_SUBFLOW_FLAG_CONNECTED _BITUL(7) ++#define MPTCP_SUBFLOW_FLAG_MAPVALID _BITUL(8) ++ ++enum { ++ MPTCP_SUBFLOW_ATTR_UNSPEC, ++ MPTCP_SUBFLOW_ATTR_TOKEN_REM, ++ MPTCP_SUBFLOW_ATTR_TOKEN_LOC, ++ MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ, ++ MPTCP_SUBFLOW_ATTR_MAP_SEQ, ++ MPTCP_SUBFLOW_ATTR_MAP_SFSEQ, ++ MPTCP_SUBFLOW_ATTR_SSN_OFFSET, ++ MPTCP_SUBFLOW_ATTR_MAP_DATALEN, ++ MPTCP_SUBFLOW_ATTR_FLAGS, ++ MPTCP_SUBFLOW_ATTR_ID_REM, ++ MPTCP_SUBFLOW_ATTR_ID_LOC, ++ MPTCP_SUBFLOW_ATTR_PAD, ++ __MPTCP_SUBFLOW_ATTR_MAX ++}; ++ ++#define MPTCP_SUBFLOW_ATTR_MAX (__MPTCP_SUBFLOW_ATTR_MAX - 1) ++ ++/* netlink interface */ ++#define MPTCP_PM_NAME "mptcp_pm" ++#define MPTCP_PM_CMD_GRP_NAME "mptcp_pm_cmds" ++#define MPTCP_PM_VER 0x1 ++ ++/* ++ * ATTR types defined for MPTCP ++ */ ++enum { ++ MPTCP_PM_ATTR_UNSPEC, ++ ++ MPTCP_PM_ATTR_ADDR, /* nested address */ ++ MPTCP_PM_ATTR_RCV_ADD_ADDRS, /* u32 */ ++ MPTCP_PM_ATTR_SUBFLOWS, /* u32 */ ++ ++ __MPTCP_PM_ATTR_MAX ++}; ++ ++#define MPTCP_PM_ATTR_MAX (__MPTCP_PM_ATTR_MAX - 1) ++ ++enum { ++ MPTCP_PM_ADDR_ATTR_UNSPEC, ++ ++ MPTCP_PM_ADDR_ATTR_FAMILY, /* u16 */ ++ MPTCP_PM_ADDR_ATTR_ID, /* u8 */ ++ MPTCP_PM_ADDR_ATTR_ADDR4, /* struct in_addr */ ++ MPTCP_PM_ADDR_ATTR_ADDR6, /* struct in6_addr */ ++ MPTCP_PM_ADDR_ATTR_PORT, /* u16 */ ++ MPTCP_PM_ADDR_ATTR_FLAGS, /* u32 */ ++ MPTCP_PM_ADDR_ATTR_IF_IDX, /* s32 */ ++ ++ __MPTCP_PM_ADDR_ATTR_MAX ++}; ++ ++#define MPTCP_PM_ADDR_ATTR_MAX (__MPTCP_PM_ADDR_ATTR_MAX - 1) ++ ++#define MPTCP_PM_ADDR_FLAG_SIGNAL (1 << 0) ++#define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1) ++#define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2) ++ ++enum { ++ MPTCP_PM_CMD_UNSPEC, ++ ++ MPTCP_PM_CMD_ADD_ADDR, ++ MPTCP_PM_CMD_DEL_ADDR, ++ MPTCP_PM_CMD_GET_ADDR, ++ MPTCP_PM_CMD_FLUSH_ADDRS, ++ MPTCP_PM_CMD_SET_LIMITS, ++ MPTCP_PM_CMD_GET_LIMITS, ++ ++ __MPTCP_PM_CMD_AFTER_LAST ++}; ++ ++#endif /* _MPTCP_H */ +-- +2.26.2 + diff --git a/SOURCES/0017-add-support-for-mptcp-netlink-interface.patch b/SOURCES/0017-add-support-for-mptcp-netlink-interface.patch new file mode 100644 index 0000000..47995fd --- /dev/null +++ b/SOURCES/0017-add-support-for-mptcp-netlink-interface.patch @@ -0,0 +1,532 @@ +From 1f25184a76227f8a7a1e425434e6e0f0bd13457d Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:26:50 +0200 +Subject: [PATCH] add support for mptcp netlink interface + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: unknown commit 7e0767cd862bb + +commit 7e0767cd862bb5dd2d41c41c5e6f55d633f953ea +Author: Paolo Abeni +Date: Thu Apr 23 15:37:08 2020 +0200 + + add support for mptcp netlink interface + + Implement basic commands to: + - manipulate MPTCP endpoints list + - manipulate MPTCP connection limits + + Examples: + 1. Allows multiple subflows per MPTCP connection + $ ip mptcp limits set subflows 2 + + 2. Accept ADD_ADDR announcement from the peer (server): + $ ip mptcp limits set add_addr_accepted 2 + + 3. Add a ipv4 address to be annunced for backup subflows: + $ ip mptcp endpoint add 10.99.1.2 signal backup + + 4. Add an ipv6 address used as source for additional subflows: + $ ip mptcp endpoint add 2001::2 subflow + + Signed-off-by: Paolo Abeni + Signed-off-by: David Ahern +--- + ip/Makefile | 2 +- + ip/ip.c | 3 +- + ip/ip_common.h | 1 + + ip/ipmptcp.c | 436 +++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 440 insertions(+), 2 deletions(-) + create mode 100644 ip/ipmptcp.c + +diff --git a/ip/Makefile b/ip/Makefile +index 5ab78d7d3b84e..8735b8e4706b3 100644 +--- a/ip/Makefile ++++ b/ip/Makefile +@@ -11,7 +11,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ + iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \ + iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \ + ipvrf.o iplink_xstats.o ipseg6.o iplink_netdevsim.o iplink_rmnet.o \ +- ipnexthop.o ++ ipnexthop.o ipmptcp.o + + RTMONOBJ=rtmon.o + +diff --git a/ip/ip.c b/ip/ip.c +index fed26f8d48279..8d62f4e312bdc 100644 +--- a/ip/ip.c ++++ b/ip/ip.c +@@ -51,7 +51,7 @@ static void usage(void) + "where OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |\n" + " tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |\n" + " netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |\n" +- " vrf | sr | nexthop }\n" ++ " vrf | sr | nexthop | mptcp }\n" + " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" + " -h[uman-readable] | -iec | -j[son] | -p[retty] |\n" + " -f[amily] { inet | inet6 | mpls | bridge | link } |\n" +@@ -103,6 +103,7 @@ static const struct cmd { + { "vrf", do_ipvrf}, + { "sr", do_seg6 }, + { "nexthop", do_ipnh }, ++ { "mptcp", do_mptcp }, + { "help", do_help }, + { 0 } + }; +diff --git a/ip/ip_common.h b/ip/ip_common.h +index cd916ec87c265..0dd4a53fc8333 100644 +--- a/ip/ip_common.h ++++ b/ip/ip_common.h +@@ -82,6 +82,7 @@ void vrf_reset(void); + int netns_identify_pid(const char *pidstr, char *name, int len); + int do_seg6(int argc, char **argv); + int do_ipnh(int argc, char **argv); ++int do_mptcp(int argc, char **argv); + + int iplink_get(char *name, __u32 filt_mask); + int iplink_ifla_xstats(int argc, char **argv); +diff --git a/ip/ipmptcp.c b/ip/ipmptcp.c +new file mode 100644 +index 0000000000000..bc12418bd39c6 +--- /dev/null ++++ b/ip/ipmptcp.c +@@ -0,0 +1,436 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "utils.h" ++#include "ip_common.h" ++#include "libgenl.h" ++#include "json_print.h" ++ ++static void usage(void) ++{ ++ fprintf(stderr, ++ "Usage: ip mptcp endpoint add ADDRESS [ dev NAME ] [ id ID ]\n" ++ " [ FLAG-LIST ]\n" ++ " ip mptcp endpoint delete id ID\n" ++ " ip mptcp endpoint show [ id ID ]\n" ++ " ip mptcp endpoint flush\n" ++ " ip mptcp limits set [ subflows NR ] [ add_addr_accepted NR ]\n" ++ " ip mptcp limits show\n" ++ "FLAG-LIST := [ FLAG-LIST ] FLAG\n" ++ "FLAG := [ signal | subflow | backup ]\n"); ++ ++ exit(-1); ++} ++ ++/* netlink socket */ ++static struct rtnl_handle genl_rth = { .fd = -1 }; ++static int genl_family = -1; ++ ++#define MPTCP_BUFLEN 4096 ++#define MPTCP_REQUEST(_req, _cmd, _flags) \ ++ GENL_REQUEST(_req, MPTCP_BUFLEN, genl_family, 0, \ ++ MPTCP_PM_VER, _cmd, _flags) ++ ++/* Mapping from argument to address flag mask */ ++static const struct { ++ const char *name; ++ unsigned long value; ++} mptcp_addr_flag_names[] = { ++ { "signal", MPTCP_PM_ADDR_FLAG_SIGNAL }, ++ { "subflow", MPTCP_PM_ADDR_FLAG_SUBFLOW }, ++ { "backup", MPTCP_PM_ADDR_FLAG_BACKUP }, ++}; ++ ++static void print_mptcp_addr_flags(unsigned int flags) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(mptcp_addr_flag_names); i++) { ++ unsigned long mask = mptcp_addr_flag_names[i].value; ++ ++ if (flags & mask) { ++ print_string(PRINT_FP, NULL, "%s ", ++ mptcp_addr_flag_names[i].name); ++ print_bool(PRINT_JSON, ++ mptcp_addr_flag_names[i].name, NULL, true); ++ } ++ ++ flags &= ~mask; ++ } ++ ++ if (flags) { ++ /* unknown flags */ ++ SPRINT_BUF(b1); ++ ++ snprintf(b1, sizeof(b1), "%02x", flags); ++ print_string(PRINT_ANY, "rawflags", "rawflags %s ", b1); ++ } ++} ++ ++static int get_flags(const char *arg, __u32 *flags) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(mptcp_addr_flag_names); i++) { ++ if (strcmp(arg, mptcp_addr_flag_names[i].name)) ++ continue; ++ ++ *flags |= mptcp_addr_flag_names[i].value; ++ return 0; ++ } ++ return -1; ++} ++ ++static int mptcp_parse_opt(int argc, char **argv, struct nlmsghdr *n, ++ bool adding) ++{ ++ struct rtattr *attr_addr; ++ bool addr_set = false; ++ inet_prefix address; ++ bool id_set = false; ++ __u32 index = 0; ++ __u32 flags = 0; ++ __u8 id = 0; ++ ++ ll_init_map(&rth); ++ while (argc > 0) { ++ if (get_flags(*argv, &flags) == 0) { ++ } else if (matches(*argv, "id") == 0) { ++ NEXT_ARG(); ++ ++ if (get_u8(&id, *argv, 0)) ++ invarg("invalid ID\n", *argv); ++ id_set = true; ++ } else if (matches(*argv, "dev") == 0) { ++ const char *ifname; ++ ++ NEXT_ARG(); ++ ++ ifname = *argv; ++ ++ if (check_ifname(ifname)) ++ invarg("invalid interface name\n", ifname); ++ ++ index = ll_name_to_index(ifname); ++ ++ if (!index) ++ invarg("device does not exist\n", ifname); ++ ++ } else if (get_addr(&address, *argv, AF_UNSPEC) == 0) { ++ addr_set = true; ++ } else { ++ invarg("unknown argument", *argv); ++ } ++ NEXT_ARG_FWD(); ++ } ++ ++ if (!addr_set && adding) ++ missarg("ADDRESS"); ++ ++ if (!id_set && !adding) ++ missarg("ID"); ++ ++ attr_addr = addattr_nest(n, MPTCP_BUFLEN, ++ MPTCP_PM_ATTR_ADDR | NLA_F_NESTED); ++ if (id_set) ++ addattr8(n, MPTCP_BUFLEN, MPTCP_PM_ADDR_ATTR_ID, id); ++ if (flags) ++ addattr32(n, MPTCP_BUFLEN, MPTCP_PM_ADDR_ATTR_FLAGS, flags); ++ if (index) ++ addattr32(n, MPTCP_BUFLEN, MPTCP_PM_ADDR_ATTR_IF_IDX, index); ++ if (addr_set) { ++ int type; ++ ++ addattr16(n, MPTCP_BUFLEN, MPTCP_PM_ADDR_ATTR_FAMILY, ++ address.family); ++ type = address.family == AF_INET ? MPTCP_PM_ADDR_ATTR_ADDR4 : ++ MPTCP_PM_ADDR_ATTR_ADDR6; ++ addattr_l(n, MPTCP_BUFLEN, type, &address.data, ++ address.bytelen); ++ } ++ ++ addattr_nest_end(n, attr_addr); ++ return 0; ++} ++ ++static int mptcp_addr_modify(int argc, char **argv, int cmd) ++{ ++ MPTCP_REQUEST(req, cmd, NLM_F_REQUEST); ++ int ret; ++ ++ ret = mptcp_parse_opt(argc, argv, &req.n, cmd == MPTCP_PM_CMD_ADD_ADDR); ++ if (ret) ++ return ret; ++ ++ if (rtnl_talk(&genl_rth, &req.n, NULL) < 0) ++ return -2; ++ ++ return 0; ++} ++ ++static int print_mptcp_addrinfo(struct rtattr *addrinfo) ++{ ++ struct rtattr *tb[MPTCP_PM_ADDR_ATTR_MAX + 1]; ++ __u8 family = AF_UNSPEC, addr_attr_type; ++ const char *ifname; ++ unsigned int flags; ++ int index; ++ __u16 id; ++ ++ parse_rtattr_nested(tb, MPTCP_PM_ADDR_ATTR_MAX, addrinfo); ++ ++ open_json_object(NULL); ++ if (tb[MPTCP_PM_ADDR_ATTR_FAMILY]) ++ family = rta_getattr_u8(tb[MPTCP_PM_ADDR_ATTR_FAMILY]); ++ ++ addr_attr_type = family == AF_INET ? MPTCP_PM_ADDR_ATTR_ADDR4 : ++ MPTCP_PM_ADDR_ATTR_ADDR6; ++ if (tb[addr_attr_type]) { ++ print_string(PRINT_ANY, "address", "%s ", ++ format_host_rta(family, tb[addr_attr_type])); ++ } ++ if (tb[MPTCP_PM_ADDR_ATTR_ID]) { ++ id = rta_getattr_u8(tb[MPTCP_PM_ADDR_ATTR_ID]); ++ print_uint(PRINT_ANY, "id", "id %u ", id); ++ } ++ if (tb[MPTCP_PM_ADDR_ATTR_FLAGS]) { ++ flags = rta_getattr_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]); ++ print_mptcp_addr_flags(flags); ++ } ++ if (tb[MPTCP_PM_ADDR_ATTR_IF_IDX]) { ++ index = rta_getattr_s32(tb[MPTCP_PM_ADDR_ATTR_IF_IDX]); ++ ifname = index ? ll_index_to_name(index) : NULL; ++ ++ if (ifname) ++ print_string(PRINT_ANY, "dev", "dev %s ", ifname); ++ } ++ ++ close_json_object(); ++ print_string(PRINT_FP, NULL, "\n", NULL); ++ fflush(stdout); ++ ++ return 0; ++} ++ ++static int print_mptcp_addr(struct nlmsghdr *n, void *arg) ++{ ++ struct rtattr *tb[MPTCP_PM_ATTR_MAX + 1]; ++ struct genlmsghdr *ghdr; ++ struct rtattr *addrinfo; ++ int len = n->nlmsg_len; ++ ++ if (n->nlmsg_type != genl_family) ++ return 0; ++ ++ len -= NLMSG_LENGTH(GENL_HDRLEN); ++ if (len < 0) ++ return -1; ++ ++ ghdr = NLMSG_DATA(n); ++ parse_rtattr_flags(tb, MPTCP_PM_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, ++ len, NLA_F_NESTED); ++ addrinfo = tb[MPTCP_PM_ATTR_ADDR]; ++ if (!addrinfo) ++ return -1; ++ ++ ll_init_map(&rth); ++ return print_mptcp_addrinfo(addrinfo); ++} ++ ++static int mptcp_addr_dump(void) ++{ ++ MPTCP_REQUEST(req, MPTCP_PM_CMD_GET_ADDR, NLM_F_REQUEST | NLM_F_DUMP); ++ ++ if (rtnl_send(&genl_rth, &req.n, req.n.nlmsg_len) < 0) { ++ perror("Cannot send show request"); ++ exit(1); ++ } ++ ++ new_json_obj(json); ++ ++ if (rtnl_dump_filter(&genl_rth, print_mptcp_addr, stdout) < 0) { ++ fprintf(stderr, "Dump terminated\n"); ++ delete_json_obj(); ++ fflush(stdout); ++ return -2; ++ } ++ ++ close_json_object(); ++ fflush(stdout); ++ return 0; ++} ++ ++static int mptcp_addr_show(int argc, char **argv) ++{ ++ MPTCP_REQUEST(req, MPTCP_PM_CMD_GET_ADDR, NLM_F_REQUEST); ++ struct nlmsghdr *answer; ++ int ret; ++ ++ if (!argv) ++ return mptcp_addr_dump(); ++ ++ ret = mptcp_parse_opt(argc, argv, &req.n, false); ++ if (ret) ++ return ret; ++ ++ if (rtnl_talk(&genl_rth, &req.n, &answer) < 0) ++ return -2; ++ ++ return print_mptcp_addr(answer, stdout); ++} ++ ++static int mptcp_addr_flush(int argc, char **argv) ++{ ++ MPTCP_REQUEST(req, MPTCP_PM_CMD_FLUSH_ADDRS, NLM_F_REQUEST); ++ ++ if (rtnl_talk(&genl_rth, &req.n, NULL) < 0) ++ return -2; ++ ++ return 0; ++} ++ ++static int mptcp_parse_limit(int argc, char **argv, struct nlmsghdr *n) ++{ ++ bool set_rcv_add_addrs = false; ++ bool set_subflows = false; ++ __u32 rcv_add_addrs = 0; ++ __u32 subflows = 0; ++ ++ while (argc > 0) { ++ if (matches(*argv, "subflows") == 0) { ++ NEXT_ARG(); ++ ++ if (get_u32(&subflows, *argv, 0)) ++ invarg("invalid subflows\n", *argv); ++ set_subflows = true; ++ } else if (matches(*argv, "add_addr_accepted") == 0) { ++ NEXT_ARG(); ++ ++ if (get_u32(&rcv_add_addrs, *argv, 0)) ++ invarg("invalid add_addr_accepted\n", *argv); ++ set_rcv_add_addrs = true; ++ } else { ++ invarg("unknown limit", *argv); ++ } ++ NEXT_ARG_FWD(); ++ } ++ ++ if (set_rcv_add_addrs) ++ addattr32(n, MPTCP_BUFLEN, MPTCP_PM_ATTR_RCV_ADD_ADDRS, ++ rcv_add_addrs); ++ if (set_subflows) ++ addattr32(n, MPTCP_BUFLEN, MPTCP_PM_ATTR_SUBFLOWS, subflows); ++ return set_rcv_add_addrs || set_subflows; ++} ++ ++static int print_mptcp_limit(struct nlmsghdr *n, void *arg) ++{ ++ struct rtattr *tb[MPTCP_PM_ATTR_MAX + 1]; ++ struct genlmsghdr *ghdr; ++ int len = n->nlmsg_len; ++ __u32 val; ++ ++ if (n->nlmsg_type != genl_family) ++ return 0; ++ ++ len -= NLMSG_LENGTH(GENL_HDRLEN); ++ if (len < 0) ++ return -1; ++ ++ ghdr = NLMSG_DATA(n); ++ parse_rtattr(tb, MPTCP_PM_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len); ++ ++ open_json_object(NULL); ++ if (tb[MPTCP_PM_ATTR_RCV_ADD_ADDRS]) { ++ val = rta_getattr_u32(tb[MPTCP_PM_ATTR_RCV_ADD_ADDRS]); ++ ++ print_uint(PRINT_ANY, "add_addr_accepted", ++ "add_addr_accepted %d ", val); ++ } ++ ++ if (tb[MPTCP_PM_ATTR_SUBFLOWS]) { ++ val = rta_getattr_u32(tb[MPTCP_PM_ATTR_SUBFLOWS]); ++ ++ print_uint(PRINT_ANY, "subflows", "subflows %d ", val); ++ } ++ print_string(PRINT_FP, NULL, "%s", "\n"); ++ fflush(stdout); ++ close_json_object(); ++ return 0; ++} ++ ++static int mptcp_limit_get_set(int argc, char **argv, int cmd) ++{ ++ bool do_get = cmd == MPTCP_PM_CMD_GET_LIMITS; ++ MPTCP_REQUEST(req, cmd, NLM_F_REQUEST); ++ struct nlmsghdr *answer; ++ int ret; ++ ++ ret = mptcp_parse_limit(argc, argv, &req.n); ++ if (ret < 0) ++ return -1; ++ ++ if (rtnl_talk(&genl_rth, &req.n, do_get ? &answer : NULL) < 0) ++ return -2; ++ ++ if (do_get) ++ return print_mptcp_limit(answer, stdout); ++ return 0; ++} ++ ++int do_mptcp(int argc, char **argv) ++{ ++ if (argc == 0) ++ usage(); ++ ++ if (matches(*argv, "help") == 0) ++ usage(); ++ ++ if (genl_init_handle(&genl_rth, MPTCP_PM_NAME, &genl_family)) ++ exit(1); ++ ++ if (matches(*argv, "endpoint") == 0) { ++ NEXT_ARG_FWD(); ++ if (argc == 0) ++ return mptcp_addr_show(0, NULL); ++ ++ if (matches(*argv, "add") == 0) ++ return mptcp_addr_modify(argc-1, argv+1, ++ MPTCP_PM_CMD_ADD_ADDR); ++ if (matches(*argv, "delete") == 0) ++ return mptcp_addr_modify(argc-1, argv+1, ++ MPTCP_PM_CMD_DEL_ADDR); ++ if (matches(*argv, "show") == 0) ++ return mptcp_addr_show(argc-1, argv+1); ++ if (matches(*argv, "flush") == 0) ++ return mptcp_addr_flush(argc-1, argv+1); ++ ++ goto unknown; ++ } ++ ++ if (matches(*argv, "limits") == 0) { ++ NEXT_ARG_FWD(); ++ if (argc == 0) ++ return mptcp_limit_get_set(0, NULL, ++ MPTCP_PM_CMD_GET_LIMITS); ++ ++ if (matches(*argv, "set") == 0) ++ return mptcp_limit_get_set(argc-1, argv+1, ++ MPTCP_PM_CMD_SET_LIMITS); ++ if (matches(*argv, "show") == 0) ++ return mptcp_limit_get_set(argc-1, argv+1, ++ MPTCP_PM_CMD_GET_LIMITS); ++ } ++ ++unknown: ++ fprintf(stderr, "Command \"%s\" is unknown, try \"ip mptcp help\".\n", ++ *argv); ++ exit(-1); ++} +-- +2.26.2 + diff --git a/SOURCES/0018-Update-kernel-headers.patch b/SOURCES/0018-Update-kernel-headers.patch new file mode 100644 index 0000000..9129be5 --- /dev/null +++ b/SOURCES/0018-Update-kernel-headers.patch @@ -0,0 +1,217 @@ +From 98f0c643a333ff630407828f4141131502edc6f9 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:26:50 +0200 +Subject: [PATCH] Update kernel headers + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: unknown commit 3d72f125c300d + +commit 3d72f125c300dd261a5151cf1cac7cfa152376b2 +Author: David Ahern +Date: Sun Sep 15 10:32:58 2019 -0700 + + Update kernel headers + + Update kernel headers to commit: + aa2eaa8c272a ("Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net") + + Signed-off-by: David Ahern +--- + include/uapi/linux/bpf.h | 15 ++++++++++++--- + include/uapi/linux/can.h | 20 +++++++++++++++++++- + include/uapi/linux/devlink.h | 11 +++++++++++ + include/uapi/linux/inet_diag.h | 9 +++++++++ + include/uapi/linux/pkt_cls.h | 2 ++ + include/uapi/linux/sctp.h | 3 +++ + 6 files changed, 56 insertions(+), 4 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 3e195ff43fa01..6d55239a4cc0f 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -106,6 +106,7 @@ enum bpf_cmd { + BPF_TASK_FD_QUERY, + BPF_MAP_LOOKUP_AND_DELETE_ELEM, + BPF_MAP_FREEZE, ++ BPF_BTF_GET_NEXT_ID, + }; + + enum bpf_map_type { +@@ -284,6 +285,9 @@ enum bpf_attach_type { + */ + #define BPF_F_TEST_RND_HI32 (1U << 2) + ++/* The verifier internal test flag. Behavior is undefined */ ++#define BPF_F_TEST_STATE_FREQ (1U << 3) ++ + /* When BPF ldimm64's insn[0].src_reg != 0 then this can have + * two extensions: + * +@@ -337,6 +341,9 @@ enum bpf_attach_type { + #define BPF_F_RDONLY_PROG (1U << 7) + #define BPF_F_WRONLY_PROG (1U << 8) + ++/* Clone map from listener for newly accepted socket */ ++#define BPF_F_CLONE (1U << 9) ++ + /* flags for BPF_PROG_QUERY */ + #define BPF_F_QUERY_EFFECTIVE (1U << 0) + +@@ -577,6 +584,8 @@ union bpf_attr { + * limited to five). + * + * Each time the helper is called, it appends a line to the trace. ++ * Lines are discarded while *\/sys/kernel/debug/tracing/trace* is ++ * open, use *\/sys/kernel/debug/tracing/trace_pipe* to avoid this. + * The format of the trace is customizable, and the exact output + * one will get depends on the options set in + * *\/sys/kernel/debug/tracing/trace_options* (see also the +@@ -1015,7 +1024,7 @@ union bpf_attr { + * The realm of the route for the packet associated to *skb*, or 0 + * if none was found. + * +- * int bpf_perf_event_output(struct pt_reg *ctx, struct bpf_map *map, u64 flags, void *data, u64 size) ++ * int bpf_perf_event_output(struct pt_regs *ctx, struct bpf_map *map, u64 flags, void *data, u64 size) + * Description + * Write raw *data* blob into a special BPF perf event held by + * *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf +@@ -1077,7 +1086,7 @@ union bpf_attr { + * Return + * 0 on success, or a negative error in case of failure. + * +- * int bpf_get_stackid(struct pt_reg *ctx, struct bpf_map *map, u64 flags) ++ * int bpf_get_stackid(struct pt_regs *ctx, struct bpf_map *map, u64 flags) + * Description + * Walk a user or a kernel stack and return its id. To achieve + * this, the helper needs *ctx*, which is a pointer to the context +@@ -1726,7 +1735,7 @@ union bpf_attr { + * Return + * 0 on success, or a negative error in case of failure. + * +- * int bpf_override_return(struct pt_reg *regs, u64 rc) ++ * int bpf_override_return(struct pt_regs *regs, u64 rc) + * Description + * Used for error injection, this helper uses kprobes to override + * the return value of the probed function, and to set it to *rc*. +diff --git a/include/uapi/linux/can.h b/include/uapi/linux/can.h +index 9009f0b6505cf..c61cdc7ad5cc6 100644 +--- a/include/uapi/linux/can.h ++++ b/include/uapi/linux/can.h +@@ -157,7 +157,8 @@ struct canfd_frame { + #define CAN_TP20 4 /* VAG Transport Protocol v2.0 */ + #define CAN_MCNET 5 /* Bosch MCNet */ + #define CAN_ISOTP 6 /* ISO 15765-2 Transport Protocol */ +-#define CAN_NPROTO 7 ++#define CAN_J1939 7 /* SAE J1939 */ ++#define CAN_NPROTO 8 + + #define SOL_CAN_BASE 100 + +@@ -174,6 +175,23 @@ struct sockaddr_can { + /* transport protocol class address information (e.g. ISOTP) */ + struct { canid_t rx_id, tx_id; } tp; + ++ /* J1939 address information */ ++ struct { ++ /* 8 byte name when using dynamic addressing */ ++ __u64 name; ++ ++ /* pgn: ++ * 8 bit: PS in PDU2 case, else 0 ++ * 8 bit: PF ++ * 1 bit: DP ++ * 1 bit: reserved ++ */ ++ __u32 pgn; ++ ++ /* 1 byte address */ ++ __u8 addr; ++ } j1939; ++ + /* reserved for future CAN protocols address information */ + } can_addr; + }; +diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h +index 3fb683bee6ba1..79e1405db67cc 100644 +--- a/include/uapi/linux/devlink.h ++++ b/include/uapi/linux/devlink.h +@@ -202,6 +202,15 @@ enum devlink_param_cmode { + enum devlink_param_fw_load_policy_value { + DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER, + DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH, ++ DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK, ++ DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_UNKNOWN, ++}; ++ ++enum devlink_param_reset_dev_on_drv_probe_value { ++ DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_UNKNOWN, ++ DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_ALWAYS, ++ DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_NEVER, ++ DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK, + }; + + enum { +@@ -410,6 +419,8 @@ enum devlink_attr { + DEVLINK_ATTR_TRAP_METADATA, /* nested */ + DEVLINK_ATTR_TRAP_GROUP_NAME, /* string */ + ++ DEVLINK_ATTR_RELOAD_FAILED, /* u8 0 or 1 */ ++ + /* add new attributes above here, update the policy in devlink.c */ + + __DEVLINK_ATTR_MAX, +diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h +index f3bcd7ee82771..3dff6841486a4 100644 +--- a/include/uapi/linux/inet_diag.h ++++ b/include/uapi/linux/inet_diag.h +@@ -153,11 +153,20 @@ enum { + INET_DIAG_BBRINFO, /* request as INET_DIAG_VEGASINFO */ + INET_DIAG_CLASS_ID, /* request as INET_DIAG_TCLASS */ + INET_DIAG_MD5SIG, ++ INET_DIAG_ULP_INFO, + __INET_DIAG_MAX, + }; + + #define INET_DIAG_MAX (__INET_DIAG_MAX - 1) + ++enum { ++ INET_ULP_INFO_UNSPEC, ++ INET_ULP_INFO_NAME, ++ INET_ULP_INFO_TLS, ++ __INET_ULP_INFO_MAX, ++}; ++#define INET_ULP_INFO_MAX (__INET_ULP_INFO_MAX - 1) ++ + /* INET_DIAG_MEM */ + + struct inet_diag_meminfo { +diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h +index 0a9ab625cba7b..c6ad22f76edee 100644 +--- a/include/uapi/linux/pkt_cls.h ++++ b/include/uapi/linux/pkt_cls.h +@@ -165,6 +165,8 @@ enum { + TCA_POLICE_RESULT, + TCA_POLICE_TM, + TCA_POLICE_PAD, ++ TCA_POLICE_RATE64, ++ TCA_POLICE_PEAKRATE64, + __TCA_POLICE_MAX + #define TCA_POLICE_RESULT TCA_POLICE_RESULT + }; +diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h +index c4bce0a2011c1..0d4c1507a169d 100644 +--- a/include/uapi/linux/sctp.h ++++ b/include/uapi/linux/sctp.h +@@ -134,6 +134,9 @@ typedef __s32 sctp_assoc_t; + #define SCTP_INTERLEAVING_SUPPORTED 125 + #define SCTP_SENDMSG_CONNECT 126 + #define SCTP_EVENT 127 ++#define SCTP_ASCONF_SUPPORTED 128 ++#define SCTP_AUTH_SUPPORTED 129 ++#define SCTP_ECN_SUPPORTED 130 + + /* PR-SCTP policies */ + #define SCTP_PR_SCTP_NONE 0x0000 +-- +2.26.2 + diff --git a/SOURCES/0019-Update-kernel-headers.patch b/SOURCES/0019-Update-kernel-headers.patch new file mode 100644 index 0000000..f6e47ee --- /dev/null +++ b/SOURCES/0019-Update-kernel-headers.patch @@ -0,0 +1,150 @@ +From 4dfaa0a3e4ea077d95d7355e73a8069b1c8af97b Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:26:50 +0200 +Subject: [PATCH] Update kernel headers + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: unknown commit ce9191ffee31d +Conflicts: several unrelated missing changes in uapi + +commit ce9191ffee31d440591bf49ef530b80ee9975dfb +Author: David Ahern +Date: Tue Mar 31 23:23:28 2020 +0000 + + Update kernel headers + + Update kernel headers to commit: + 7f80ccfe9968 ("net: ipv6: rpl_iptunnel: Fix potential memory leak in rpl_do_srh_inline") + + Signed-off-by: David Ahern +--- + include/uapi/linux/bpf.h | 20 +++++++++++++++++++- + include/uapi/linux/devlink.h | 6 ++++++ + include/uapi/linux/if_link.h | 5 ++++- + include/uapi/linux/inet_diag.h | 1 + + include/uapi/linux/lwtunnel.h | 1 + + 5 files changed, 31 insertions(+), 2 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 6d55239a4cc0f..94aa5a1d38215 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -483,7 +483,7 @@ union bpf_attr { + __u32 prog_cnt; + } query; + +- struct { ++ struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */ + __u64 name; + __u32 prog_fd; + } raw_tracepoint; +@@ -511,6 +511,24 @@ union bpf_attr { + __u64 probe_offset; /* output: probe_offset */ + __u64 probe_addr; /* output: probe_addr */ + } task_fd_query; ++ ++ struct { /* struct used by BPF_LINK_CREATE command */ ++ __u32 prog_fd; /* eBPF program to attach */ ++ __u32 target_fd; /* object to attach to */ ++ __u32 attach_type; /* attach type */ ++ __u32 flags; /* extra flags */ ++ } link_create; ++ ++ struct { /* struct used by BPF_LINK_UPDATE command */ ++ __u32 link_fd; /* link fd */ ++ /* new program fd to update link with */ ++ __u32 new_prog_fd; ++ __u32 flags; /* extra flags */ ++ /* expected link's program fd; is specified only if ++ * BPF_F_REPLACE flag is set in flags */ ++ __u32 old_prog_fd; ++ } link_update; ++ + } __attribute__((aligned(8))); + + /* The description below is an attempt at providing documentation to eBPF +diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h +index 79e1405db67cc..e63aeab76bcb8 100644 +--- a/include/uapi/linux/devlink.h ++++ b/include/uapi/linux/devlink.h +@@ -117,6 +117,11 @@ enum devlink_command { + DEVLINK_CMD_TRAP_GROUP_NEW, + DEVLINK_CMD_TRAP_GROUP_DEL, + ++ DEVLINK_CMD_TRAP_POLICER_GET, /* can dump */ ++ DEVLINK_CMD_TRAP_POLICER_SET, ++ DEVLINK_CMD_TRAP_POLICER_NEW, ++ DEVLINK_CMD_TRAP_POLICER_DEL, ++ + /* add new commands above here */ + __DEVLINK_CMD_MAX, + DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 +@@ -216,6 +221,7 @@ enum devlink_param_reset_dev_on_drv_probe_value { + enum { + DEVLINK_ATTR_STATS_RX_PACKETS, /* u64 */ + DEVLINK_ATTR_STATS_RX_BYTES, /* u64 */ ++ DEVLINK_ATTR_STATS_RX_DROPPED, /* u64 */ + + __DEVLINK_ATTR_STATS_MAX, + DEVLINK_ATTR_STATS_MAX = __DEVLINK_ATTR_STATS_MAX - 1 +diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h +index 4da0768d7a5a3..5d69479b8052d 100644 +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -459,6 +459,7 @@ enum { + IFLA_MACSEC_REPLAY_PROTECT, + IFLA_MACSEC_VALIDATION, + IFLA_MACSEC_PAD, ++ IFLA_MACSEC_OFFLOAD, + __IFLA_MACSEC_MAX, + }; + +@@ -949,11 +950,12 @@ enum { + #define XDP_FLAGS_SKB_MODE (1U << 1) + #define XDP_FLAGS_DRV_MODE (1U << 2) + #define XDP_FLAGS_HW_MODE (1U << 3) ++#define XDP_FLAGS_REPLACE (1U << 4) + #define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | \ + XDP_FLAGS_DRV_MODE | \ + XDP_FLAGS_HW_MODE) + #define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \ +- XDP_FLAGS_MODES) ++ XDP_FLAGS_MODES | XDP_FLAGS_REPLACE) + + /* These are stored into IFLA_XDP_ATTACHED on dump. */ + enum { +@@ -973,6 +975,7 @@ enum { + IFLA_XDP_DRV_PROG_ID, + IFLA_XDP_SKB_PROG_ID, + IFLA_XDP_HW_PROG_ID, ++ IFLA_XDP_EXPECTED_FD, + __IFLA_XDP_MAX, + }; + +diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h +index 3dff6841486a4..db45fc664a5fd 100644 +--- a/include/uapi/linux/inet_diag.h ++++ b/include/uapi/linux/inet_diag.h +@@ -163,6 +163,7 @@ enum { + INET_ULP_INFO_UNSPEC, + INET_ULP_INFO_NAME, + INET_ULP_INFO_TLS, ++ INET_ULP_INFO_MPTCP, + __INET_ULP_INFO_MAX, + }; + #define INET_ULP_INFO_MAX (__INET_ULP_INFO_MAX - 1) +diff --git a/include/uapi/linux/lwtunnel.h b/include/uapi/linux/lwtunnel.h +index 3f3fe6f30df0b..0ba94063c1809 100644 +--- a/include/uapi/linux/lwtunnel.h ++++ b/include/uapi/linux/lwtunnel.h +@@ -13,6 +13,7 @@ enum lwtunnel_encap_types { + LWTUNNEL_ENCAP_SEG6, + LWTUNNEL_ENCAP_BPF, + LWTUNNEL_ENCAP_SEG6_LOCAL, ++ LWTUNNEL_ENCAP_RPL, + __LWTUNNEL_ENCAP_MAX, + }; + +-- +2.26.2 + diff --git a/SOURCES/0020-ss-allow-dumping-MPTCP-subflow-information.patch b/SOURCES/0020-ss-allow-dumping-MPTCP-subflow-information.patch new file mode 100644 index 0000000..2189263 --- /dev/null +++ b/SOURCES/0020-ss-allow-dumping-MPTCP-subflow-information.patch @@ -0,0 +1,144 @@ +From afc9c910cc9c818180364860b04535def3c19b6e Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:27:41 +0200 +Subject: [PATCH] ss: allow dumping MPTCP subflow information + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: unknown commit 712fdd98c0839 +Conflicts: context changes and code slightly adapted in tcp_show_info() + due to missing commit 14cadc707b919 ("ss: allow dumping kTLS info") + +commit 712fdd98c0839540a50baca0fb858c7a72d18031 +Author: Davide Caratti +Date: Thu Apr 23 15:37:09 2020 +0200 + + ss: allow dumping MPTCP subflow information + + [root@f31 packetdrill]# ss -tni + + ESTAB 0 0 192.168.82.247:8080 192.0.2.1:35273 + cubic wscale:7,8 [...] tcp-ulp-mptcp flags:Mec token:0000(id:0)/5f856c60(id:0) seq:b810457db34209a5 sfseq:1 ssnoff:0 maplen:190 + + Additionally extends ss manpage to describe the new entry layout. + + Signed-off-by: Davide Caratti + Signed-off-by: Paolo Abeni + Signed-off-by: David Ahern +--- + man/man8/ss.8 | 5 ++++ + misc/ss.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 74 insertions(+) + +diff --git a/man/man8/ss.8 b/man/man8/ss.8 +index 023d771b17878..c80853f98c49a 100644 +--- a/man/man8/ss.8 ++++ b/man/man8/ss.8 +@@ -261,6 +261,11 @@ the pacing rate and max pacing rate + .TP + .B rcv_space: + a helper variable for TCP internal auto tuning socket receive buffer ++.P ++.TP ++.B tcp-ulp-mptcp flags:[MmBbJjecv] token: seq: sfseq: ssnoff: maplen: ++MPTCP subflow information ++.P + .RE + .TP + .B \-\-tos +diff --git a/misc/ss.c b/misc/ss.c +index 363b4c8d87cd3..3d565af86087c 100644 +--- a/misc/ss.c ++++ b/misc/ss.c +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + + /* AF_VSOCK/PF_VSOCK is only provided since glibc 2.18 */ + #ifndef PF_VSOCK +@@ -2751,6 +2752,59 @@ static void print_md5sig(struct tcp_diag_md5sig *sig) + print_escape_buf(sig->tcpm_key, sig->tcpm_keylen, " ,"); + } + ++static void mptcp_subflow_info(struct rtattr *tb[]) ++{ ++ u_int32_t flags = 0; ++ ++ if (tb[MPTCP_SUBFLOW_ATTR_FLAGS]) { ++ char caps[32 + 1] = { 0 }, *cap = &caps[0]; ++ ++ flags = rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_FLAGS]); ++ ++ if (flags & MPTCP_SUBFLOW_FLAG_MCAP_REM) ++ *cap++ = 'M'; ++ if (flags & MPTCP_SUBFLOW_FLAG_MCAP_LOC) ++ *cap++ = 'm'; ++ if (flags & MPTCP_SUBFLOW_FLAG_JOIN_REM) ++ *cap++ = 'J'; ++ if (flags & MPTCP_SUBFLOW_FLAG_JOIN_LOC) ++ *cap++ = 'j'; ++ if (flags & MPTCP_SUBFLOW_FLAG_BKUP_REM) ++ *cap++ = 'B'; ++ if (flags & MPTCP_SUBFLOW_FLAG_BKUP_LOC) ++ *cap++ = 'b'; ++ if (flags & MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED) ++ *cap++ = 'e'; ++ if (flags & MPTCP_SUBFLOW_FLAG_CONNECTED) ++ *cap++ = 'c'; ++ if (flags & MPTCP_SUBFLOW_FLAG_MAPVALID) ++ *cap++ = 'v'; ++ if (flags) ++ out(" flags:%s", caps); ++ } ++ if (tb[MPTCP_SUBFLOW_ATTR_TOKEN_REM] && ++ tb[MPTCP_SUBFLOW_ATTR_TOKEN_LOC] && ++ tb[MPTCP_SUBFLOW_ATTR_ID_REM] && ++ tb[MPTCP_SUBFLOW_ATTR_ID_LOC]) ++ out(" token:%04x(id:%hhu)/%04x(id:%hhu)", ++ rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_TOKEN_REM]), ++ rta_getattr_u8(tb[MPTCP_SUBFLOW_ATTR_ID_REM]), ++ rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_TOKEN_LOC]), ++ rta_getattr_u8(tb[MPTCP_SUBFLOW_ATTR_ID_LOC])); ++ if (tb[MPTCP_SUBFLOW_ATTR_MAP_SEQ]) ++ out(" seq:%llx", ++ rta_getattr_u64(tb[MPTCP_SUBFLOW_ATTR_MAP_SEQ])); ++ if (tb[MPTCP_SUBFLOW_ATTR_MAP_SFSEQ]) ++ out(" sfseq:%x", ++ rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_MAP_SFSEQ])); ++ if (tb[MPTCP_SUBFLOW_ATTR_SSN_OFFSET]) ++ out(" ssnoff:%x", ++ rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_SSN_OFFSET])); ++ if (tb[MPTCP_SUBFLOW_ATTR_MAP_DATALEN]) ++ out(" maplen:%x", ++ rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_MAP_DATALEN])); ++} ++ + #define TCPI_HAS_OPT(info, opt) !!(info->tcpi_options & (opt)) + + static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, +@@ -2906,6 +2960,21 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, + print_md5sig(sig++); + } + } ++ if (tb[INET_DIAG_ULP_INFO]) { ++ struct rtattr *ulpinfo[INET_ULP_INFO_MAX + 1] = { 0 }; ++ ++ parse_rtattr_nested(ulpinfo, INET_ULP_INFO_MAX, ++ tb[INET_DIAG_ULP_INFO]); ++ ++ if (ulpinfo[INET_ULP_INFO_MPTCP]) { ++ struct rtattr *sfinfo[MPTCP_SUBFLOW_ATTR_MAX + 1] = ++ { 0 }; ++ ++ parse_rtattr_nested(sfinfo, MPTCP_SUBFLOW_ATTR_MAX, ++ ulpinfo[INET_ULP_INFO_MPTCP]); ++ mptcp_subflow_info(sfinfo); ++ } ++ } + } + + static const char *format_host_sa(struct sockaddr_storage *sa) +-- +2.26.2 + diff --git a/SOURCES/0021-man-mptcp-man-page.patch b/SOURCES/0021-man-mptcp-man-page.patch new file mode 100644 index 0000000..f9aed62 --- /dev/null +++ b/SOURCES/0021-man-mptcp-man-page.patch @@ -0,0 +1,174 @@ +From af65892658d7c271d1fb328065a35f8017610418 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:28:45 +0200 +Subject: [PATCH] man: mptcp man page + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: unknown commit 2d8b5fe93e9de + +commit 2d8b5fe93e9decb56acc243905d82fb22d6c4cfd +Author: Paolo Abeni +Date: Thu Apr 23 15:37:10 2020 +0200 + + man: mptcp man page + + describe the mptcp subcommands implemented so far. + + Signed-off-by: Paolo Abeni + Signed-off-by: David Ahern +--- + man/man8/ip-mptcp.8 | 142 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 142 insertions(+) + create mode 100644 man/man8/ip-mptcp.8 + +diff --git a/man/man8/ip-mptcp.8 b/man/man8/ip-mptcp.8 +new file mode 100644 +index 0000000000000..f6457e97efbe8 +--- /dev/null ++++ b/man/man8/ip-mptcp.8 +@@ -0,0 +1,142 @@ ++.TH IP\-MPTCP 8 "4 Apr 2020" "iproute2" "Linux" ++.SH "NAME" ++ip-mptcp \- MPTCP path manager configuration ++.SH "SYNOPSIS" ++.sp ++.ad l ++.in +8 ++.ti -8 ++.B ip ++.RI "[ " OPTIONS " ]" ++.B mptcp ++.RB "{ " ++.B endpoint ++.RB " | " ++.B limits ++.RB " | " ++.B help ++.RB " }" ++.sp ++ ++.ti -8 ++.BR "ip mptcp endpoint add " ++.IR IFADDR ++.RB "[ " dev ++.IR IFNAME " ]" ++.RB "[ " id ++.I ID ++.RB "] [ " ++.I FLAG-LIST ++.RB "] " ++ ++.ti -8 ++.BR "ip mptcp endpoint del id " ++.I ID ++ ++.ti -8 ++.BR "ip mptcp endpoint show " ++.RB "[ " id ++.I ID ++.RB "]" ++ ++.ti -8 ++.BR "ip mptcp endpoint flush" ++ ++.ti -8 ++.IR FLAG-LIST " := [ " FLAG-LIST " ] " FLAG ++ ++.ti -8 ++.IR FLAG " := [" ++.B signal ++.RB "|" ++.B subflow ++.RB "|" ++.B backup ++.RB "]" ++ ++.ti -8 ++.BR "ip mptcp limits set " ++.RB "[ " ++.B subflow ++.IR SUBFLOW_NR " ]" ++.RB "[ " ++.B add_addr_accepted ++.IR ADD_ADDR_ACCEPTED_NR " ]" ++ ++.ti -8 ++.BR "ip mptcp limits show" ++ ++.SH DESCRIPTION ++ ++MPTCP is a transport protocol built on top of TCP that allows TCP ++connections to use multiple paths to maximize resource usage and increase ++redundancy. The ip-mptcp sub-commands allow configuring several aspects of the ++MPTCP path manager, which is in charge of subflows creation: ++ ++.P ++The ++.B endpoint ++object specifies the IP addresses that will be used and/or announced for ++additional subflows: ++ ++.TS ++l l. ++ip mptcp endpoint add add new MPTCP endpoint ++ip mptcp endpoint delete delete existing MPTCP endpoint ++ip mptcp endpoint show get existing MPTCP endpoint ++ip mptcp endpoint flush flush all existing MPTCP endpoints ++.TE ++ ++.TP ++.IR ID ++is a unique numeric identifier for the given endpoint ++ ++.TP ++.BR signal ++the endpoint will be announced/signalled to each peer via an ADD_ADDR MPTCP ++sub-option ++ ++.TP ++.BR subflow ++if additional subflow creation is allowed by MPTCP limits, the endpoint will ++be used as the source address to create an additional subflow after that ++the MPTCP connection is established. ++ ++.TP ++.BR backup ++the endpoint will be announced as a backup address, if this is a ++.BR signal ++endpoint, or the subflow will be created as a backup one if this is a ++.BR subflow ++endpoint ++ ++.sp ++.PP ++The ++.B limits ++object specifies the constraints for subflow creations: ++ ++.TS ++l l. ++ip mptcp limits show get current MPTCP subflow creation limits ++ip mptcp limits set change the MPTCP subflow creation limits ++.TE ++ ++.TP ++.IR SUBFLOW_NR ++specifies the maximum number of additional subflows allowed for each MPTCP ++connection. Additional subflows can be created due to: incoming accepted ++ADD_ADDR option, local ++.BR subflow ++endpoints, additional subflows started by the peer. ++ ++.TP ++.IR ADD_ADDR_ACCEPTED_NR ++specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP ++connection. The MPTCP path manager will try to create a new subflow for ++each accepted ADD_ADDR option, respecting the ++.IR SUBFLOW_NR ++limit. ++ ++.SH AUTHOR ++Original Manpage by Paolo Abeni +-- +2.26.2 + diff --git a/SOURCES/0022-man-ip.8-add-reference-to-mptcp-man-page.patch b/SOURCES/0022-man-ip.8-add-reference-to-mptcp-man-page.patch new file mode 100644 index 0000000..c38458f --- /dev/null +++ b/SOURCES/0022-man-ip.8-add-reference-to-mptcp-man-page.patch @@ -0,0 +1,70 @@ +From c2e8f8b4c1980c773b967953b795f81942e209fb Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:28:45 +0200 +Subject: [PATCH] man: ip.8: add reference to mptcp man-page + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: unknown commit 0c42c6b130196 + +commit 0c42c6b130196d1d7e87acc5122f8fd325e75c5b +Author: Paolo Abeni +Date: Wed Apr 29 19:17:22 2020 +0200 + + man: ip.8: add reference to mptcp man-page + + While at it, additionally fix a mandoc warning in mptcp.8 + + Signed-off-by: Paolo Abeni + Signed-off-by: David Ahern +--- + man/man8/ip-mptcp.8 | 1 - + man/man8/ip.8 | 7 ++++++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/man/man8/ip-mptcp.8 b/man/man8/ip-mptcp.8 +index f6457e97efbe8..ef8409ea4a24d 100644 +--- a/man/man8/ip-mptcp.8 ++++ b/man/man8/ip-mptcp.8 +@@ -2,7 +2,6 @@ + .SH "NAME" + ip-mptcp \- MPTCP path manager configuration + .SH "SYNOPSIS" +-.sp + .ad l + .in +8 + .ti -8 +diff --git a/man/man8/ip.8 b/man/man8/ip.8 +index c425aaf1d506e..f391237b4fcae 100644 +--- a/man/man8/ip.8 ++++ b/man/man8/ip.8 +@@ -22,7 +22,7 @@ ip \- show / manipulate routing, network devices, interfaces and tunnels + .BR link " | " address " | " addrlabel " | " route " | " rule " | " neigh " | "\ + ntable " | " tunnel " | " tuntap " | " maddress " | " mroute " | " mrule " | "\ + monitor " | " xfrm " | " netns " | " l2tp " | " tcp_metrics " | " token " | "\ +- macsec " | " vrf " }" ++ macsec " | " vrf " | " mptcp " }" + .sp + + .ti -8 +@@ -268,6 +268,10 @@ readability. + .B monitor + - watch for netlink messages. + ++.TP ++.B mptcp ++- manage MPTCP path manager. ++ + .TP + .B mroute + - multicast routing cache entry. +@@ -406,6 +410,7 @@ was written by Alexey N. Kuznetsov and added in Linux 2.2. + .BR ip-link (8), + .BR ip-maddress (8), + .BR ip-monitor (8), ++.BR ip-mptcp (8), + .BR ip-mroute (8), + .BR ip-neighbour (8), + .BR ip-netns (8), +-- +2.26.2 + diff --git a/SOURCES/0023-Update-kernel-headers.patch b/SOURCES/0023-Update-kernel-headers.patch new file mode 100644 index 0000000..7d329c4 --- /dev/null +++ b/SOURCES/0023-Update-kernel-headers.patch @@ -0,0 +1,568 @@ +From f0023a7d874697821516583c1b3be95e2f110668 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:41:59 +0200 +Subject: [PATCH] Update kernel headers + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: iproute2.git commit 7438afd2cc8d3 +Conflicts: on devlink uapi due to missing commit 9dcd8788fe6bc + ("Update kernel headers") + +commit 7438afd2cc8d37fd7f12e29963e1d926de53dda7 +Author: David Ahern +Date: Mon Nov 25 23:13:09 2019 +0000 + + Update kernel headers + + Update kernel headers to commit: + c431047c4efe ("enetc: add support Credit Based Shaper(CBS) for hardware offload") + + Signed-off-by: David Ahern +--- + include/uapi/linux/bpf.h | 130 ++++++++++++++------ + include/uapi/linux/gen_stats.h | 5 +- + include/uapi/linux/lwtunnel.h | 41 ++++++ + include/uapi/linux/netfilter/ipset/ip_set.h | 2 + + include/uapi/linux/pkt_cls.h | 29 +++++ + include/uapi/linux/pkt_sched.h | 22 ++-- + include/uapi/linux/sctp.h | 15 +++ + include/uapi/linux/tc_act/tc_tunnel_key.h | 29 +++++ + include/uapi/linux/tipc.h | 21 ++++ + include/uapi/linux/tipc_netlink.h | 4 + + 10 files changed, 246 insertions(+), 52 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 94aa5a1d38215..bf3475f915cf1 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -173,6 +173,7 @@ enum bpf_prog_type { + BPF_PROG_TYPE_CGROUP_SYSCTL, + BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, + BPF_PROG_TYPE_CGROUP_SOCKOPT, ++ BPF_PROG_TYPE_TRACING, + }; + + enum bpf_attach_type { +@@ -199,6 +200,9 @@ enum bpf_attach_type { + BPF_CGROUP_UDP6_RECVMSG, + BPF_CGROUP_GETSOCKOPT, + BPF_CGROUP_SETSOCKOPT, ++ BPF_TRACE_RAW_TP, ++ BPF_TRACE_FENTRY, ++ BPF_TRACE_FEXIT, + __MAX_BPF_ATTACH_TYPE + }; + +@@ -344,6 +348,9 @@ enum bpf_attach_type { + /* Clone map from listener for newly accepted socket */ + #define BPF_F_CLONE (1U << 9) + ++/* Enable memory-mapping BPF map */ ++#define BPF_F_MMAPABLE (1U << 10) ++ + /* flags for BPF_PROG_QUERY */ + #define BPF_F_QUERY_EFFECTIVE (1U << 0) + +@@ -421,6 +428,7 @@ union bpf_attr { + __aligned_u64 line_info; /* line info */ + __u32 line_info_cnt; /* number of bpf_line_info records */ + __u32 attach_btf_id; /* in-kernel BTF type id to attach to */ ++ __u32 attach_prog_fd; /* 0 to attach to vmlinux */ + }; + + struct { /* anonymous struct used by BPF_OBJ_* commands */ +@@ -579,10 +587,13 @@ union bpf_attr { + * Return + * 0 on success, or a negative error in case of failure. + * +- * int bpf_probe_read(void *dst, u32 size, const void *src) ++ * int bpf_probe_read(void *dst, u32 size, const void *unsafe_ptr) + * Description + * For tracing programs, safely attempt to read *size* bytes from +- * address *src* and store the data in *dst*. ++ * kernel space address *unsafe_ptr* and store the data in *dst*. ++ * ++ * Generally, use bpf_probe_read_user() or bpf_probe_read_kernel() ++ * instead. + * Return + * 0 on success, or a negative error in case of failure. + * +@@ -1444,45 +1455,14 @@ union bpf_attr { + * Return + * 0 on success, or a negative error in case of failure. + * +- * int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr) ++ * int bpf_probe_read_str(void *dst, u32 size, const void *unsafe_ptr) + * Description +- * Copy a NUL terminated string from an unsafe address +- * *unsafe_ptr* to *dst*. The *size* should include the +- * terminating NUL byte. In case the string length is smaller than +- * *size*, the target is not padded with further NUL bytes. If the +- * string length is larger than *size*, just *size*-1 bytes are +- * copied and the last byte is set to NUL. +- * +- * On success, the length of the copied string is returned. This +- * makes this helper useful in tracing programs for reading +- * strings, and more importantly to get its length at runtime. See +- * the following snippet: +- * +- * :: +- * +- * SEC("kprobe/sys_open") +- * void bpf_sys_open(struct pt_regs *ctx) +- * { +- * char buf[PATHLEN]; // PATHLEN is defined to 256 +- * int res = bpf_probe_read_str(buf, sizeof(buf), +- * ctx->di); +- * +- * // Consume buf, for example push it to +- * // userspace via bpf_perf_event_output(); we +- * // can use res (the string length) as event +- * // size, after checking its boundaries. +- * } ++ * Copy a NUL terminated string from an unsafe kernel address ++ * *unsafe_ptr* to *dst*. See bpf_probe_read_kernel_str() for ++ * more details. + * +- * In comparison, using **bpf_probe_read()** helper here instead +- * to read the string would require to estimate the length at +- * compile time, and would often result in copying more memory +- * than necessary. +- * +- * Another useful use case is when parsing individual process +- * arguments or individual environment variables navigating +- * *current*\ **->mm->arg_start** and *current*\ +- * **->mm->env_start**: using this helper and the return value, +- * one can quickly iterate at the right offset of the memory area. ++ * Generally, use bpf_probe_read_user_str() or bpf_probe_read_kernel_str() ++ * instead. + * Return + * On success, the strictly positive length of the string, + * including the trailing NUL character. On error, a negative +@@ -2793,6 +2773,72 @@ union bpf_attr { + * restricted to raw_tracepoint bpf programs. + * Return + * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_probe_read_user(void *dst, u32 size, const void *unsafe_ptr) ++ * Description ++ * Safely attempt to read *size* bytes from user space address ++ * *unsafe_ptr* and store the data in *dst*. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_probe_read_kernel(void *dst, u32 size, const void *unsafe_ptr) ++ * Description ++ * Safely attempt to read *size* bytes from kernel space address ++ * *unsafe_ptr* and store the data in *dst*. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_probe_read_user_str(void *dst, u32 size, const void *unsafe_ptr) ++ * Description ++ * Copy a NUL terminated string from an unsafe user address ++ * *unsafe_ptr* to *dst*. The *size* should include the ++ * terminating NUL byte. In case the string length is smaller than ++ * *size*, the target is not padded with further NUL bytes. If the ++ * string length is larger than *size*, just *size*-1 bytes are ++ * copied and the last byte is set to NUL. ++ * ++ * On success, the length of the copied string is returned. This ++ * makes this helper useful in tracing programs for reading ++ * strings, and more importantly to get its length at runtime. See ++ * the following snippet: ++ * ++ * :: ++ * ++ * SEC("kprobe/sys_open") ++ * void bpf_sys_open(struct pt_regs *ctx) ++ * { ++ * char buf[PATHLEN]; // PATHLEN is defined to 256 ++ * int res = bpf_probe_read_user_str(buf, sizeof(buf), ++ * ctx->di); ++ * ++ * // Consume buf, for example push it to ++ * // userspace via bpf_perf_event_output(); we ++ * // can use res (the string length) as event ++ * // size, after checking its boundaries. ++ * } ++ * ++ * In comparison, using **bpf_probe_read_user()** helper here ++ * instead to read the string would require to estimate the length ++ * at compile time, and would often result in copying more memory ++ * than necessary. ++ * ++ * Another useful use case is when parsing individual process ++ * arguments or individual environment variables navigating ++ * *current*\ **->mm->arg_start** and *current*\ ++ * **->mm->env_start**: using this helper and the return value, ++ * one can quickly iterate at the right offset of the memory area. ++ * Return ++ * On success, the strictly positive length of the string, ++ * including the trailing NUL character. On error, a negative ++ * value. ++ * ++ * int bpf_probe_read_kernel_str(void *dst, u32 size, const void *unsafe_ptr) ++ * Description ++ * Copy a NUL terminated string from an unsafe kernel address *unsafe_ptr* ++ * to *dst*. Same semantics as with bpf_probe_read_user_str() apply. ++ * Return ++ * On success, the strictly positive length of the string, including ++ * the trailing NUL character. On error, a negative value. + */ + #define __BPF_FUNC_MAPPER(FN) \ + FN(unspec), \ +@@ -2906,7 +2952,11 @@ union bpf_attr { + FN(sk_storage_delete), \ + FN(send_signal), \ + FN(tcp_gen_syncookie), \ +- FN(skb_output), ++ FN(skb_output), \ ++ FN(probe_read_user), \ ++ FN(probe_read_kernel), \ ++ FN(probe_read_user_str), \ ++ FN(probe_read_kernel_str), + + /* integer value in 'imm' field of BPF_CALL instruction selects which helper + * function eBPF program intends to call +diff --git a/include/uapi/linux/gen_stats.h b/include/uapi/linux/gen_stats.h +index 065408e16a807..852f234f1fd63 100644 +--- a/include/uapi/linux/gen_stats.h ++++ b/include/uapi/linux/gen_stats.h +@@ -13,6 +13,7 @@ enum { + TCA_STATS_RATE_EST64, + TCA_STATS_PAD, + TCA_STATS_BASIC_HW, ++ TCA_STATS_PKT64, + __TCA_STATS_MAX, + }; + #define TCA_STATS_MAX (__TCA_STATS_MAX - 1) +@@ -26,10 +27,6 @@ struct gnet_stats_basic { + __u64 bytes; + __u32 packets; + }; +-struct gnet_stats_basic_packed { +- __u64 bytes; +- __u32 packets; +-} __attribute__ ((packed)); + + /** + * struct gnet_stats_rate_est - rate estimator +diff --git a/include/uapi/linux/lwtunnel.h b/include/uapi/linux/lwtunnel.h +index 0ba94063c1809..b7c0191fd1b5f 100644 +--- a/include/uapi/linux/lwtunnel.h ++++ b/include/uapi/linux/lwtunnel.h +@@ -28,6 +28,7 @@ enum lwtunnel_ip_t { + LWTUNNEL_IP_TOS, + LWTUNNEL_IP_FLAGS, + LWTUNNEL_IP_PAD, ++ LWTUNNEL_IP_OPTS, + __LWTUNNEL_IP_MAX, + }; + +@@ -42,11 +43,51 @@ enum lwtunnel_ip6_t { + LWTUNNEL_IP6_TC, + LWTUNNEL_IP6_FLAGS, + LWTUNNEL_IP6_PAD, ++ LWTUNNEL_IP6_OPTS, + __LWTUNNEL_IP6_MAX, + }; + + #define LWTUNNEL_IP6_MAX (__LWTUNNEL_IP6_MAX - 1) + ++enum { ++ LWTUNNEL_IP_OPTS_UNSPEC, ++ LWTUNNEL_IP_OPTS_GENEVE, ++ LWTUNNEL_IP_OPTS_VXLAN, ++ LWTUNNEL_IP_OPTS_ERSPAN, ++ __LWTUNNEL_IP_OPTS_MAX, ++}; ++ ++#define LWTUNNEL_IP_OPTS_MAX (__LWTUNNEL_IP_OPTS_MAX - 1) ++ ++enum { ++ LWTUNNEL_IP_OPT_GENEVE_UNSPEC, ++ LWTUNNEL_IP_OPT_GENEVE_CLASS, ++ LWTUNNEL_IP_OPT_GENEVE_TYPE, ++ LWTUNNEL_IP_OPT_GENEVE_DATA, ++ __LWTUNNEL_IP_OPT_GENEVE_MAX, ++}; ++ ++#define LWTUNNEL_IP_OPT_GENEVE_MAX (__LWTUNNEL_IP_OPT_GENEVE_MAX - 1) ++ ++enum { ++ LWTUNNEL_IP_OPT_VXLAN_UNSPEC, ++ LWTUNNEL_IP_OPT_VXLAN_GBP, ++ __LWTUNNEL_IP_OPT_VXLAN_MAX, ++}; ++ ++#define LWTUNNEL_IP_OPT_VXLAN_MAX (__LWTUNNEL_IP_OPT_VXLAN_MAX - 1) ++ ++enum { ++ LWTUNNEL_IP_OPT_ERSPAN_UNSPEC, ++ LWTUNNEL_IP_OPT_ERSPAN_VER, ++ LWTUNNEL_IP_OPT_ERSPAN_INDEX, ++ LWTUNNEL_IP_OPT_ERSPAN_DIR, ++ LWTUNNEL_IP_OPT_ERSPAN_HWID, ++ __LWTUNNEL_IP_OPT_ERSPAN_MAX, ++}; ++ ++#define LWTUNNEL_IP_OPT_ERSPAN_MAX (__LWTUNNEL_IP_OPT_ERSPAN_MAX - 1) ++ + enum { + LWT_BPF_PROG_UNSPEC, + LWT_BPF_PROG_FD, +diff --git a/include/uapi/linux/netfilter/ipset/ip_set.h b/include/uapi/linux/netfilter/ipset/ip_set.h +index c512003dba6ba..4b372f46f0d04 100644 +--- a/include/uapi/linux/netfilter/ipset/ip_set.h ++++ b/include/uapi/linux/netfilter/ipset/ip_set.h +@@ -205,6 +205,8 @@ enum ipset_cadt_flags { + IPSET_FLAG_WITH_FORCEADD = (1 << IPSET_FLAG_BIT_WITH_FORCEADD), + IPSET_FLAG_BIT_WITH_SKBINFO = 6, + IPSET_FLAG_WITH_SKBINFO = (1 << IPSET_FLAG_BIT_WITH_SKBINFO), ++ IPSET_FLAG_BIT_IFACE_WILDCARD = 7, ++ IPSET_FLAG_IFACE_WILDCARD = (1 << IPSET_FLAG_BIT_IFACE_WILDCARD), + IPSET_FLAG_CADT_MAX = 15, + }; + +diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h +index c6ad22f76edee..449a63971451f 100644 +--- a/include/uapi/linux/pkt_cls.h ++++ b/include/uapi/linux/pkt_cls.h +@@ -571,6 +571,14 @@ enum { + * TCA_FLOWER_KEY_ENC_OPT_GENEVE_ + * attributes + */ ++ TCA_FLOWER_KEY_ENC_OPTS_VXLAN, /* Nested ++ * TCA_FLOWER_KEY_ENC_OPT_VXLAN_ ++ * attributes ++ */ ++ TCA_FLOWER_KEY_ENC_OPTS_ERSPAN, /* Nested ++ * TCA_FLOWER_KEY_ENC_OPT_ERSPAN_ ++ * attributes ++ */ + __TCA_FLOWER_KEY_ENC_OPTS_MAX, + }; + +@@ -588,6 +596,27 @@ enum { + #define TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX \ + (__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1) + ++enum { ++ TCA_FLOWER_KEY_ENC_OPT_VXLAN_UNSPEC, ++ TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP, /* u32 */ ++ __TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX, ++}; ++ ++#define TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX \ ++ (__TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX - 1) ++ ++enum { ++ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_UNSPEC, ++ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER, /* u8 */ ++ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX, /* be32 */ ++ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR, /* u8 */ ++ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID, /* u8 */ ++ __TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX, ++}; ++ ++#define TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX \ ++ (__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_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 18f185299f472..dab60bd8f0f4a 100644 +--- a/include/uapi/linux/pkt_sched.h ++++ b/include/uapi/linux/pkt_sched.h +@@ -950,19 +950,25 @@ enum { + TCA_PIE_BETA, + TCA_PIE_ECN, + TCA_PIE_BYTEMODE, ++ TCA_PIE_DQ_RATE_ESTIMATOR, + __TCA_PIE_MAX + }; + #define TCA_PIE_MAX (__TCA_PIE_MAX - 1) + + struct tc_pie_xstats { +- __u64 prob; /* current probability */ +- __u32 delay; /* current delay in ms */ +- __u32 avg_dq_rate; /* current average dq_rate in bits/pie_time */ +- __u32 packets_in; /* total number of packets enqueued */ +- __u32 dropped; /* packets dropped due to pie_action */ +- __u32 overlimit; /* dropped due to lack of space in queue */ +- __u32 maxq; /* maximum queue size */ +- __u32 ecn_mark; /* packets marked with ecn*/ ++ __u64 prob; /* current probability */ ++ __u32 delay; /* current delay in ms */ ++ __u32 avg_dq_rate; /* current average dq_rate in ++ * bits/pie_time ++ */ ++ __u32 dq_rate_estimating; /* is avg_dq_rate being calculated? */ ++ __u32 packets_in; /* total number of packets enqueued */ ++ __u32 dropped; /* packets dropped due to pie_action */ ++ __u32 overlimit; /* dropped due to lack of space ++ * in queue ++ */ ++ __u32 maxq; /* maximum queue size */ ++ __u32 ecn_mark; /* packets marked with ecn*/ + }; + + /* CBS */ +diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h +index 0d4c1507a169d..f8f218b16c280 100644 +--- a/include/uapi/linux/sctp.h ++++ b/include/uapi/linux/sctp.h +@@ -105,6 +105,7 @@ typedef __s32 sctp_assoc_t; + #define SCTP_DEFAULT_SNDINFO 34 + #define SCTP_AUTH_DEACTIVATE_KEY 35 + #define SCTP_REUSE_PORT 36 ++#define SCTP_PEER_ADDR_THLDS_V2 37 + + /* Internal Socket Options. Some of the sctp library functions are + * implemented using these socket options. +@@ -137,6 +138,8 @@ typedef __s32 sctp_assoc_t; + #define SCTP_ASCONF_SUPPORTED 128 + #define SCTP_AUTH_SUPPORTED 129 + #define SCTP_ECN_SUPPORTED 130 ++#define SCTP_EXPOSE_POTENTIALLY_FAILED_STATE 131 ++#define SCTP_EXPOSE_PF_STATE SCTP_EXPOSE_POTENTIALLY_FAILED_STATE + + /* PR-SCTP policies */ + #define SCTP_PR_SCTP_NONE 0x0000 +@@ -410,6 +413,8 @@ enum sctp_spc_state { + SCTP_ADDR_ADDED, + SCTP_ADDR_MADE_PRIM, + SCTP_ADDR_CONFIRMED, ++ SCTP_ADDR_POTENTIALLY_FAILED, ++#define SCTP_ADDR_PF SCTP_ADDR_POTENTIALLY_FAILED + }; + + +@@ -917,6 +922,7 @@ struct sctp_paddrinfo { + enum sctp_spinfo_state { + SCTP_INACTIVE, + SCTP_PF, ++#define SCTP_POTENTIALLY_FAILED SCTP_PF + SCTP_ACTIVE, + SCTP_UNCONFIRMED, + SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */ +@@ -1062,6 +1068,15 @@ struct sctp_paddrthlds { + __u16 spt_pathpfthld; + }; + ++/* Use a new structure with spt_pathcpthld for back compatibility */ ++struct sctp_paddrthlds_v2 { ++ sctp_assoc_t spt_assoc_id; ++ struct sockaddr_storage spt_address; ++ __u16 spt_pathmaxrxt; ++ __u16 spt_pathpfthld; ++ __u16 spt_pathcpthld; ++}; ++ + /* + * Socket Option for Getting the Association/Stream-Specific PR-SCTP Status + */ +diff --git a/include/uapi/linux/tc_act/tc_tunnel_key.h b/include/uapi/linux/tc_act/tc_tunnel_key.h +index 41c8b462c177c..3f10dc4e7a4bb 100644 +--- a/include/uapi/linux/tc_act/tc_tunnel_key.h ++++ b/include/uapi/linux/tc_act/tc_tunnel_key.h +@@ -50,6 +50,14 @@ enum { + * TCA_TUNNEL_KEY_ENC_OPTS_ + * attributes + */ ++ TCA_TUNNEL_KEY_ENC_OPTS_VXLAN, /* Nested ++ * TCA_TUNNEL_KEY_ENC_OPTS_ ++ * attributes ++ */ ++ TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN, /* Nested ++ * TCA_TUNNEL_KEY_ENC_OPTS_ ++ * attributes ++ */ + __TCA_TUNNEL_KEY_ENC_OPTS_MAX, + }; + +@@ -67,4 +75,25 @@ enum { + #define TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX \ + (__TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX - 1) + ++enum { ++ TCA_TUNNEL_KEY_ENC_OPT_VXLAN_UNSPEC, ++ TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP, /* u32 */ ++ __TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX, ++}; ++ ++#define TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX \ ++ (__TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX - 1) ++ ++enum { ++ TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_UNSPEC, ++ TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER, /* u8 */ ++ TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX, /* be32 */ ++ TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR, /* u8 */ ++ TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID, /* u8 */ ++ __TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX, ++}; ++ ++#define TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX \ ++ (__TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX - 1) ++ + #endif +diff --git a/include/uapi/linux/tipc.h b/include/uapi/linux/tipc.h +index 0f6f28b2e3010..de5bcd2a09fae 100644 +--- a/include/uapi/linux/tipc.h ++++ b/include/uapi/linux/tipc.h +@@ -233,6 +233,27 @@ struct tipc_sioc_nodeid_req { + char node_id[TIPC_NODEID_LEN]; + }; + ++/* ++ * TIPC Crypto, AEAD ++ */ ++#define TIPC_AEAD_ALG_NAME (32) ++ ++struct tipc_aead_key { ++ char alg_name[TIPC_AEAD_ALG_NAME]; ++ unsigned int keylen; /* in bytes */ ++ char key[]; ++}; ++ ++#define TIPC_AEAD_KEYLEN_MIN (16 + 4) ++#define TIPC_AEAD_KEYLEN_MAX (32 + 4) ++#define TIPC_AEAD_KEY_SIZE_MAX (sizeof(struct tipc_aead_key) + \ ++ TIPC_AEAD_KEYLEN_MAX) ++ ++static __inline__ int tipc_aead_key_size(struct tipc_aead_key *key) ++{ ++ return sizeof(*key) + key->keylen; ++} ++ + /* The macros and functions below are deprecated: + */ + +diff --git a/include/uapi/linux/tipc_netlink.h b/include/uapi/linux/tipc_netlink.h +index efb958fd167d0..6c2194ab745bd 100644 +--- a/include/uapi/linux/tipc_netlink.h ++++ b/include/uapi/linux/tipc_netlink.h +@@ -63,6 +63,8 @@ enum { + TIPC_NL_PEER_REMOVE, + TIPC_NL_BEARER_ADD, + TIPC_NL_UDP_GET_REMOTEIP, ++ TIPC_NL_KEY_SET, ++ TIPC_NL_KEY_FLUSH, + + __TIPC_NL_CMD_MAX, + TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1 +@@ -160,6 +162,8 @@ enum { + TIPC_NLA_NODE_UNSPEC, + TIPC_NLA_NODE_ADDR, /* u32 */ + TIPC_NLA_NODE_UP, /* flag */ ++ TIPC_NLA_NODE_ID, /* data */ ++ TIPC_NLA_NODE_KEY, /* data */ + + __TIPC_NLA_NODE_MAX, + TIPC_NLA_NODE_MAX = __TIPC_NLA_NODE_MAX - 1 +-- +2.26.2 + diff --git a/SOURCES/0024-iproute_lwtunnel-add-options-support-for-geneve-meta.patch b/SOURCES/0024-iproute_lwtunnel-add-options-support-for-geneve-meta.patch new file mode 100644 index 0000000..e093682 --- /dev/null +++ b/SOURCES/0024-iproute_lwtunnel-add-options-support-for-geneve-meta.patch @@ -0,0 +1,297 @@ +From c6f909bd0f40c58f39f857e1c57638cb41241fa2 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:43:01 +0200 +Subject: [PATCH] iproute_lwtunnel: add options support for geneve metadata + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit ca7614d4c6f45 + +commit ca7614d4c6f456187d831a8202bb4a8559a72f8b +Author: Xin Long +Date: Mon Apr 27 18:27:45 2020 +0800 + + iproute_lwtunnel: add options support for geneve metadata + + This patch is to add LWTUNNEL_IP(6)_OPTS and LWTUNNEL_IP_OPTS_GENEVE's + parse and print to implement geneve options support in iproute_lwtunnel. + + Options are expressed as class:type:data and multiple options may be + listed using a comma delimiter, class and type are numbers and data + is a hex string. + + With this patch, users can add and dump geneve options like: + + # ip netns add a + # ip netns add b + # ip -n a link add eth0 type veth peer name eth0 netns b + # ip -n a link set eth0 up; ip -n b link set eth0 up + # ip -n a addr add 10.1.0.1/24 dev eth0 + # ip -n b addr add 10.1.0.2/24 dev eth0 + # ip -n b link add geneve1 type geneve id 1 remote 10.1.0.1 ttl 64 + # ip -n b addr add 1.1.1.1/24 dev geneve1 + # ip -n b link set geneve1 up + # ip -n b route add 2.1.1.0/24 dev geneve1 + # ip -n a link add geneve1 type geneve external + # ip -n a addr add 2.1.1.1/24 dev geneve1 + # ip -n a link set geneve1 up + # ip -n a route add 1.1.1.0/24 encap ip id 1 geneve_opts \ + 1:1:1212121234567890,1:1:1212121234567890,1:1:1212121234567890 \ + dst 10.1.0.2 dev geneve1 + # ip -n a route show + # ip netns exec a ping 1.1.1.1 -c 1 + + 1.1.1.0/24 encap ip id 1 src 0.0.0.0 dst 10.1.0.2 ttl 0 tos 0 + geneve_opts 1:1:1212121234567890,1:1:1212121234567890 ... + + PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. + 64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=0.079 ms + + v1->v2: + - improve the changelog. + - use PRINT_ANY to support dumping with json format. + v2->v3: + - implement proper JSON array for opts instead of just bunch of strings. + v3->v4: + - keep the same format between input and output, json and non json. + - print class and type as uint and print data as hex string. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + ip/iproute_lwtunnel.c | 174 +++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 172 insertions(+), 2 deletions(-) + +diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c +index 60f34a32a6e5b..76d906c47c44f 100644 +--- a/ip/iproute_lwtunnel.c ++++ b/ip/iproute_lwtunnel.c +@@ -291,6 +291,54 @@ static void print_encap_mpls(FILE *fp, struct rtattr *encap) + rta_getattr_u8(tb[MPLS_IPTUNNEL_TTL])); + } + ++static void lwtunnel_print_geneve_opts(struct rtattr *attr) ++{ ++ struct rtattr *tb[LWTUNNEL_IP_OPT_GENEVE_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ int rem = RTA_PAYLOAD(attr); ++ char *name = "geneve_opts"; ++ int data_len, offset = 0; ++ char data[rem * 2 + 1]; ++ __u16 class; ++ __u8 type; ++ ++ print_nl(); ++ print_string(PRINT_FP, name, "\t%s ", name); ++ open_json_array(PRINT_JSON, name); ++ ++ while (rem) { ++ parse_rtattr(tb, LWTUNNEL_IP_OPT_GENEVE_MAX, i, rem); ++ class = rta_getattr_be16(tb[LWTUNNEL_IP_OPT_GENEVE_CLASS]); ++ type = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_GENEVE_TYPE]); ++ data_len = RTA_PAYLOAD(tb[LWTUNNEL_IP_OPT_GENEVE_DATA]); ++ hexstring_n2a(RTA_DATA(tb[LWTUNNEL_IP_OPT_GENEVE_DATA]), ++ data_len, data, sizeof(data)); ++ offset += data_len + 20; ++ rem -= data_len + 20; ++ i = RTA_DATA(attr) + offset; ++ ++ open_json_object(NULL); ++ print_uint(PRINT_ANY, "class", "%u", class); ++ print_uint(PRINT_ANY, "type", ":%u", type); ++ if (rem) ++ print_string(PRINT_ANY, "data", ":%s,", data); ++ else ++ print_string(PRINT_ANY, "data", ":%s ", data); ++ close_json_object(); ++ } ++ ++ close_json_array(PRINT_JSON, name); ++} ++ ++static void lwtunnel_print_opts(struct rtattr *attr) ++{ ++ struct rtattr *tb_opt[LWTUNNEL_IP_OPTS_MAX + 1]; ++ ++ parse_rtattr_nested(tb_opt, LWTUNNEL_IP_OPTS_MAX, attr); ++ if (tb_opt[LWTUNNEL_IP_OPTS_GENEVE]) ++ lwtunnel_print_geneve_opts(tb_opt[LWTUNNEL_IP_OPTS_GENEVE]); ++} ++ + static void print_encap_ip(FILE *fp, struct rtattr *encap) + { + struct rtattr *tb[LWTUNNEL_IP_MAX+1]; +@@ -329,6 +377,9 @@ static void print_encap_ip(FILE *fp, struct rtattr *encap) + if (flags & TUNNEL_SEQ) + print_bool(PRINT_ANY, "seq", "seq ", true); + } ++ ++ if (tb[LWTUNNEL_IP_OPTS]) ++ lwtunnel_print_opts(tb[LWTUNNEL_IP_OPTS]); + } + + static void print_encap_ila(FILE *fp, struct rtattr *encap) +@@ -401,6 +452,9 @@ static void print_encap_ip6(FILE *fp, struct rtattr *encap) + if (flags & TUNNEL_SEQ) + print_bool(PRINT_ANY, "seq", "seq ", true); + } ++ ++ if (tb[LWTUNNEL_IP6_OPTS]) ++ lwtunnel_print_opts(tb[LWTUNNEL_IP6_OPTS]); + } + + static void print_encap_bpf(FILE *fp, struct rtattr *encap) +@@ -795,11 +849,97 @@ static int parse_encap_mpls(struct rtattr *rta, size_t len, + return 0; + } + ++static int lwtunnel_parse_geneve_opt(char *str, size_t len, struct rtattr *rta) ++{ ++ struct rtattr *nest; ++ char *token; ++ int i, err; ++ ++ nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_GENEVE | NLA_F_NESTED); ++ i = 1; ++ token = strsep(&str, ":"); ++ while (token) { ++ switch (i) { ++ case LWTUNNEL_IP_OPT_GENEVE_CLASS: ++ { ++ __be16 opt_class; ++ ++ if (!strlen(token)) ++ break; ++ err = get_be16(&opt_class, token, 0); ++ if (err) ++ return err; ++ ++ rta_addattr16(rta, len, i, opt_class); ++ break; ++ } ++ case LWTUNNEL_IP_OPT_GENEVE_TYPE: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ rta_addattr8(rta, len, i, opt_type); ++ break; ++ } ++ case LWTUNNEL_IP_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; ++ } ++ rta_addattr_l(rta, len, i, opts, token_len / 2); ++ free(opts); ++ ++ break; ++ } ++ default: ++ fprintf(stderr, "Unknown \"geneve_opts\" type\n"); ++ return -1; ++ } ++ ++ token = strsep(&str, ":"); ++ i++; ++ } ++ rta_nest_end(rta, nest); ++ ++ return 0; ++} ++ ++static int lwtunnel_parse_geneve_opts(char *str, size_t len, struct rtattr *rta) ++{ ++ char *token; ++ int err; ++ ++ token = strsep(&str, ","); ++ while (token) { ++ err = lwtunnel_parse_geneve_opt(token, len, rta); ++ if (err) ++ return err; ++ ++ token = strsep(&str, ","); ++ } ++ ++ return 0; ++} ++ + static int parse_encap_ip(struct rtattr *rta, size_t len, + int *argcp, char ***argvp) + { + int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0; +- int key_ok = 0, csum_ok = 0, seq_ok = 0; ++ int key_ok = 0, csum_ok = 0, seq_ok = 0, opts_ok = 0; + char **argv = *argvp; + int argc = *argcp; + int ret = 0; +@@ -851,6 +991,21 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, + if (get_u8(&ttl, *argv, 0)) + invarg("\"ttl\" value is invalid\n", *argv); + ret = rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl); ++ } else if (strcmp(*argv, "geneve_opts") == 0) { ++ struct rtattr *nest; ++ ++ if (opts_ok++) ++ duparg2("opts", *argv); ++ ++ NEXT_ARG(); ++ ++ nest = rta_nest(rta, len, ++ LWTUNNEL_IP_OPTS | NLA_F_NESTED); ++ ret = lwtunnel_parse_geneve_opts(*argv, len, rta); ++ if (ret) ++ invarg("\"geneve_opts\" value is invalid\n", ++ *argv); ++ rta_nest_end(rta, nest); + } else if (strcmp(*argv, "key") == 0) { + if (key_ok++) + duparg2("key", *argv); +@@ -966,7 +1121,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + int *argcp, char ***argvp) + { + int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0; +- int key_ok = 0, csum_ok = 0, seq_ok = 0; ++ int key_ok = 0, csum_ok = 0, seq_ok = 0, opts_ok = 0; + char **argv = *argvp; + int argc = *argcp; + int ret = 0; +@@ -1020,6 +1175,21 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + *argv); + ret = rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT, + hoplimit); ++ } else if (strcmp(*argv, "geneve_opts") == 0) { ++ struct rtattr *nest; ++ ++ if (opts_ok++) ++ duparg2("opts", *argv); ++ ++ NEXT_ARG(); ++ ++ nest = rta_nest(rta, len, ++ LWTUNNEL_IP_OPTS | NLA_F_NESTED); ++ ret = lwtunnel_parse_geneve_opts(*argv, len, rta); ++ if (ret) ++ invarg("\"geneve_opts\" value is invalid\n", ++ *argv); ++ rta_nest_end(rta, nest); + } else if (strcmp(*argv, "key") == 0) { + if (key_ok++) + duparg2("key", *argv); +-- +2.26.2 + diff --git a/SOURCES/0025-iproute_lwtunnel-add-options-support-for-vxlan-metad.patch b/SOURCES/0025-iproute_lwtunnel-add-options-support-for-vxlan-metad.patch new file mode 100644 index 0000000..cc25df9 --- /dev/null +++ b/SOURCES/0025-iproute_lwtunnel-add-options-support-for-vxlan-metad.patch @@ -0,0 +1,175 @@ +From 873511fb86756c40631f80963356179627d69d49 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:43:01 +0200 +Subject: [PATCH] iproute_lwtunnel: add options support for vxlan metadata + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit b1bc0f3892222 + +commit b1bc0f38922220b379ed39552a5e2a7cf9dccd92 +Author: Xin Long +Date: Mon Apr 27 18:27:46 2020 +0800 + + iproute_lwtunnel: add options support for vxlan metadata + + This patch is to add LWTUNNEL_IP_OPTS_VXLAN's parse and print to implement + vxlan options support in iproute_lwtunnel. + + Option is expressed a number for gbp only, and vxlan doesn't support + multiple options. + + With this patch, users can add and dump vxlan options like: + + # ip netns add a + # ip netns add b + # ip -n a link add eth0 type veth peer name eth0 netns b + # ip -n a link set eth0 up + # ip -n b link set eth0 up + # ip -n a addr add 10.1.0.1/24 dev eth0 + # ip -n b addr add 10.1.0.2/24 dev eth0 + # ip -n b link add vxlan1 type vxlan id 1 local 10.1.0.2 \ + remote 10.1.0.1 dev eth0 ttl 64 gbp + # ip -n b addr add 1.1.1.1/24 dev vxlan1 + # ip -n b link set vxlan1 up + # ip -n b route add 2.1.1.0/24 dev vxlan1 + # ip -n a link add vxlan1 type vxlan local 10.1.0.1 dev eth0 ttl 64 \ + gbp external + # ip -n a addr add 2.1.1.1/24 dev vxlan1 + # ip -n a link set vxlan1 up + # ip -n a route add 1.1.1.0/24 encap ip id 1 \ + vxlan_opts 1110 dst 10.1.0.2 dev vxlan1 + # ip -n a route show + # ip netns exec a ping 1.1.1.1 -c 1 + + 1.1.1.0/24 encap ip id 1 src 0.0.0.0 dst 10.1.0.2 ttl 0 tos 0 + vxlan_opts 1110 dev vxlan1 scope link + + PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. + 64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=0.111 ms + + v1->v2: + - improve the changelog. + - get_u32 with base = 0 for gbp. + - use PRINT_ANY to support dumping with json format. + v2->v3: + - implement proper JSON array for opts. + v3->v4: + - keep the same format between input and output, json and non json. + - print gbp as uint. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + ip/iproute_lwtunnel.c | 68 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 68 insertions(+) + +diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c +index 76d906c47c44f..17514dcad9219 100644 +--- a/ip/iproute_lwtunnel.c ++++ b/ip/iproute_lwtunnel.c +@@ -330,6 +330,26 @@ static void lwtunnel_print_geneve_opts(struct rtattr *attr) + close_json_array(PRINT_JSON, name); + } + ++static void lwtunnel_print_vxlan_opts(struct rtattr *attr) ++{ ++ struct rtattr *tb[LWTUNNEL_IP_OPT_VXLAN_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ int rem = RTA_PAYLOAD(attr); ++ char *name = "vxlan_opts"; ++ __u32 gbp; ++ ++ parse_rtattr(tb, LWTUNNEL_IP_OPT_VXLAN_MAX, i, rem); ++ gbp = rta_getattr_u32(tb[LWTUNNEL_IP_OPT_VXLAN_GBP]); ++ ++ print_nl(); ++ print_string(PRINT_FP, name, "\t%s ", name); ++ open_json_array(PRINT_JSON, name); ++ open_json_object(NULL); ++ print_uint(PRINT_ANY, "gbp", "%u ", gbp); ++ close_json_object(); ++ close_json_array(PRINT_JSON, name); ++} ++ + static void lwtunnel_print_opts(struct rtattr *attr) + { + struct rtattr *tb_opt[LWTUNNEL_IP_OPTS_MAX + 1]; +@@ -337,6 +357,8 @@ static void lwtunnel_print_opts(struct rtattr *attr) + parse_rtattr_nested(tb_opt, LWTUNNEL_IP_OPTS_MAX, attr); + if (tb_opt[LWTUNNEL_IP_OPTS_GENEVE]) + lwtunnel_print_geneve_opts(tb_opt[LWTUNNEL_IP_OPTS_GENEVE]); ++ else if (tb_opt[LWTUNNEL_IP_OPTS_VXLAN]) ++ lwtunnel_print_vxlan_opts(tb_opt[LWTUNNEL_IP_OPTS_VXLAN]); + } + + static void print_encap_ip(FILE *fp, struct rtattr *encap) +@@ -935,6 +957,22 @@ static int lwtunnel_parse_geneve_opts(char *str, size_t len, struct rtattr *rta) + return 0; + } + ++static int lwtunnel_parse_vxlan_opts(char *str, size_t len, struct rtattr *rta) ++{ ++ struct rtattr *nest; ++ __u32 gbp; ++ int err; ++ ++ nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_VXLAN | NLA_F_NESTED); ++ err = get_u32(&gbp, str, 0); ++ if (err) ++ return err; ++ rta_addattr32(rta, len, LWTUNNEL_IP_OPT_VXLAN_GBP, gbp); ++ ++ rta_nest_end(rta, nest); ++ return 0; ++} ++ + static int parse_encap_ip(struct rtattr *rta, size_t len, + int *argcp, char ***argvp) + { +@@ -1006,6 +1044,21 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, + invarg("\"geneve_opts\" value is invalid\n", + *argv); + rta_nest_end(rta, nest); ++ } else if (strcmp(*argv, "vxlan_opts") == 0) { ++ struct rtattr *nest; ++ ++ if (opts_ok++) ++ duparg2("opts", *argv); ++ ++ NEXT_ARG(); ++ ++ nest = rta_nest(rta, len, ++ LWTUNNEL_IP_OPTS | NLA_F_NESTED); ++ ret = lwtunnel_parse_vxlan_opts(*argv, len, rta); ++ if (ret) ++ invarg("\"vxlan_opts\" value is invalid\n", ++ *argv); ++ rta_nest_end(rta, nest); + } else if (strcmp(*argv, "key") == 0) { + if (key_ok++) + duparg2("key", *argv); +@@ -1190,6 +1243,21 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + invarg("\"geneve_opts\" value is invalid\n", + *argv); + rta_nest_end(rta, nest); ++ } else if (strcmp(*argv, "vxlan_opts") == 0) { ++ struct rtattr *nest; ++ ++ if (opts_ok++) ++ duparg2("opts", *argv); ++ ++ NEXT_ARG(); ++ ++ nest = rta_nest(rta, len, ++ LWTUNNEL_IP_OPTS | NLA_F_NESTED); ++ ret = lwtunnel_parse_vxlan_opts(*argv, len, rta); ++ if (ret) ++ invarg("\"vxlan_opts\" value is invalid\n", ++ *argv); ++ rta_nest_end(rta, nest); + } else if (strcmp(*argv, "key") == 0) { + if (key_ok++) + duparg2("key", *argv); +-- +2.26.2 + diff --git a/SOURCES/0026-iproute_lwtunnel-add-options-support-for-erspan-meta.patch b/SOURCES/0026-iproute_lwtunnel-add-options-support-for-erspan-meta.patch new file mode 100644 index 0000000..d9f0bb6 --- /dev/null +++ b/SOURCES/0026-iproute_lwtunnel-add-options-support-for-erspan-meta.patch @@ -0,0 +1,246 @@ +From 3628115b53f7b693f623638fb5ec71bc292a3a00 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:43:01 +0200 +Subject: [PATCH] iproute_lwtunnel: add options support for erspan metadata + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit 39fa047938fbe + +commit 39fa047938fbef6cd08687b0daa4d86afbfdc61c +Author: Xin Long +Date: Mon Apr 27 18:27:47 2020 +0800 + + iproute_lwtunnel: add options support for erspan metadata + + This patch is to add LWTUNNEL_IP_OPTS_ERSPAN's parse and print to implement + erspan options support in iproute_lwtunnel. + + Option is expressed as version:index:dir:hwid, dir and hwid will be parsed + when version is 2, while index will be parsed when version is 1. All of + these are numbers. erspan doesn't support multiple options. + + With this patch, users can add and dump erspan options like: + + # ip netns add a + # ip netns add b + # ip -n a link add eth0 type veth peer name eth0 netns b + # ip -n a link set eth0 up + # ip -n b link set eth0 up + # ip -n a addr add 10.1.0.1/24 dev eth0 + # ip -n b addr add 10.1.0.2/24 dev eth0 + # ip -n b link add erspan1 type erspan key 1 seq erspan 123 \ + local 10.1.0.2 remote 10.1.0.1 + # ip -n b addr add 1.1.1.1/24 dev erspan1 + # ip -n b link set erspan1 up + # ip -n b route add 2.1.1.0/24 dev erspan1 + # ip -n a link add erspan1 type erspan key 1 seq local 10.1.0.1 external + # ip -n a addr add 2.1.1.1/24 dev erspan1 + # ip -n a link set erspan1 up + # ip -n a route add 1.1.1.0/24 encap ip id 1 \ + erspan_opts 2:123:1:2 dst 10.1.0.2 dev erspan1 + # ip -n a route show + # ip netns exec a ping 1.1.1.1 -c 1 + + 1.1.1.0/24 encap ip id 1 src 0.0.0.0 dst 10.1.0.2 ttl 0 tos 0 + erspan_opts 2:0:1:2 dev erspan1 scope link + + PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. + 64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=0.124 ms + + v1->v2: + - improve the changelog. + - use PRINT_ANY to support dumping with json format. + v2->v3: + - implement proper JSON object for opts instead of just bunch of strings. + v3->v4: + - keep the same format between input and output, json and non json. + - print version, index, dir and hwid as uint. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + ip/iproute_lwtunnel.c | 140 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 140 insertions(+) + +diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c +index 17514dcad9219..7e145768c111f 100644 +--- a/ip/iproute_lwtunnel.c ++++ b/ip/iproute_lwtunnel.c +@@ -350,6 +350,38 @@ static void lwtunnel_print_vxlan_opts(struct rtattr *attr) + close_json_array(PRINT_JSON, name); + } + ++static void lwtunnel_print_erspan_opts(struct rtattr *attr) ++{ ++ struct rtattr *tb[LWTUNNEL_IP_OPT_ERSPAN_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ char *name = "erspan_opts"; ++ __u8 ver, hwid, dir; ++ __u32 idx; ++ ++ parse_rtattr(tb, LWTUNNEL_IP_OPT_ERSPAN_MAX, i, RTA_PAYLOAD(attr)); ++ ver = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_ERSPAN_VER]); ++ if (ver == 1) { ++ idx = rta_getattr_be32(tb[LWTUNNEL_IP_OPT_ERSPAN_INDEX]); ++ dir = 0; ++ hwid = 0; ++ } else { ++ idx = 0; ++ dir = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_ERSPAN_DIR]); ++ hwid = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_ERSPAN_HWID]); ++ } ++ ++ print_nl(); ++ print_string(PRINT_FP, name, "\t%s ", name); ++ open_json_array(PRINT_JSON, name); ++ open_json_object(NULL); ++ print_uint(PRINT_ANY, "ver", "%u", ver); ++ print_uint(PRINT_ANY, "index", ":%u", idx); ++ print_uint(PRINT_ANY, "dir", ":%u", dir); ++ print_uint(PRINT_ANY, "hwid", ":%u ", hwid); ++ close_json_object(); ++ close_json_array(PRINT_JSON, name); ++} ++ + static void lwtunnel_print_opts(struct rtattr *attr) + { + struct rtattr *tb_opt[LWTUNNEL_IP_OPTS_MAX + 1]; +@@ -359,6 +391,8 @@ static void lwtunnel_print_opts(struct rtattr *attr) + lwtunnel_print_geneve_opts(tb_opt[LWTUNNEL_IP_OPTS_GENEVE]); + else if (tb_opt[LWTUNNEL_IP_OPTS_VXLAN]) + lwtunnel_print_vxlan_opts(tb_opt[LWTUNNEL_IP_OPTS_VXLAN]); ++ else if (tb_opt[LWTUNNEL_IP_OPTS_ERSPAN]) ++ lwtunnel_print_erspan_opts(tb_opt[LWTUNNEL_IP_OPTS_ERSPAN]); + } + + static void print_encap_ip(FILE *fp, struct rtattr *encap) +@@ -973,6 +1007,82 @@ static int lwtunnel_parse_vxlan_opts(char *str, size_t len, struct rtattr *rta) + return 0; + } + ++static int lwtunnel_parse_erspan_opts(char *str, size_t len, struct rtattr *rta) ++{ ++ struct rtattr *nest; ++ char *token; ++ int i, err; ++ ++ nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_ERSPAN | NLA_F_NESTED); ++ i = 1; ++ token = strsep(&str, ":"); ++ while (token) { ++ switch (i) { ++ case LWTUNNEL_IP_OPT_ERSPAN_VER: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ rta_addattr8(rta, len, i, opt_type); ++ break; ++ } ++ case LWTUNNEL_IP_OPT_ERSPAN_INDEX: ++ { ++ __be32 opt_class; ++ ++ if (!strlen(token)) ++ break; ++ err = get_be32(&opt_class, token, 0); ++ if (err) ++ return err; ++ ++ rta_addattr32(rta, len, i, opt_class); ++ break; ++ } ++ case LWTUNNEL_IP_OPT_ERSPAN_DIR: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ rta_addattr8(rta, len, i, opt_type); ++ break; ++ } ++ case LWTUNNEL_IP_OPT_ERSPAN_HWID: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ rta_addattr8(rta, len, i, opt_type); ++ break; ++ } ++ default: ++ fprintf(stderr, "Unknown \"geneve_opts\" type\n"); ++ return -1; ++ } ++ ++ token = strsep(&str, ":"); ++ i++; ++ } ++ ++ rta_nest_end(rta, nest); ++ return 0; ++} ++ + static int parse_encap_ip(struct rtattr *rta, size_t len, + int *argcp, char ***argvp) + { +@@ -1059,6 +1169,21 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, + invarg("\"vxlan_opts\" value is invalid\n", + *argv); + rta_nest_end(rta, nest); ++ } else if (strcmp(*argv, "erspan_opts") == 0) { ++ struct rtattr *nest; ++ ++ if (opts_ok++) ++ duparg2("opts", *argv); ++ ++ NEXT_ARG(); ++ ++ nest = rta_nest(rta, len, ++ LWTUNNEL_IP_OPTS | NLA_F_NESTED); ++ ret = lwtunnel_parse_erspan_opts(*argv, len, rta); ++ if (ret) ++ invarg("\"erspan_opts\" value is invalid\n", ++ *argv); ++ rta_nest_end(rta, nest); + } else if (strcmp(*argv, "key") == 0) { + if (key_ok++) + duparg2("key", *argv); +@@ -1258,6 +1383,21 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + invarg("\"vxlan_opts\" value is invalid\n", + *argv); + rta_nest_end(rta, nest); ++ } else if (strcmp(*argv, "erspan_opts") == 0) { ++ struct rtattr *nest; ++ ++ if (opts_ok++) ++ duparg2("opts", *argv); ++ ++ NEXT_ARG(); ++ ++ nest = rta_nest(rta, len, ++ LWTUNNEL_IP_OPTS | NLA_F_NESTED); ++ ret = lwtunnel_parse_erspan_opts(*argv, len, rta); ++ if (ret) ++ invarg("\"erspan_opts\" value is invalid\n", ++ *argv); ++ rta_nest_end(rta, nest); + } else if (strcmp(*argv, "key") == 0) { + if (key_ok++) + duparg2("key", *argv); +-- +2.26.2 + diff --git a/SOURCES/0027-tc-m_tunnel_key-add-options-support-for-vxlan.patch b/SOURCES/0027-tc-m_tunnel_key-add-options-support-for-vxlan.patch new file mode 100644 index 0000000..b86d0b3 --- /dev/null +++ b/SOURCES/0027-tc-m_tunnel_key-add-options-support-for-vxlan.patch @@ -0,0 +1,258 @@ +From f970b592af7421ce932a788a6a14161c351d75e0 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:43:01 +0200 +Subject: [PATCH] tc: m_tunnel_key: add options support for vxlan + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit f72c3ad00f3b7 +Conflicts: context change due to missing commit 7b0d424abef16 + ("tc: do not output newline in oneline mode") + +commit f72c3ad00f3b7869e90840d0098a83cb88224892 +Author: Xin Long +Date: Mon Apr 27 18:27:48 2020 +0800 + + tc: m_tunnel_key: add options support for vxlan + + This patch is to add TCA_TUNNEL_KEY_ENC_OPTS_VXLAN's parse and + print to implement vxlan options support in m_tunnel_key, like + Commit 6217917a3826 ("tc: m_tunnel_key: Add tunnel option support + to act_tunnel_key") for geneve options support. + + Option is expressed a 32bit number for gbp only, and vxlan + doesn't support multiple options. + + With this patch, users can add and dump vxlan options like: + + # ip link add name vxlan1 type vxlan 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 \ + vxlan_opts 65793 \ + action mirred egress redirect dev vxlan1 + # tc -s filter show dev eth0 parent ffff: + + filter protocol ip pref 49152 flower chain 0 handle 0x1 + indev eth0 + eth_type ipv4 + ip_proto udp + not_in_hw + action order 1: tunnel_key set + src_ip 10.0.99.192 + dst_ip 10.0.99.193 + key_id 11 + dst_port 6081 + vxlan_opts 65793 + ... + + v1->v2: + - get_u32 with base = 0 for gbp. + - use to print_unint("0x%x") to print gbp. + v2->v3: + - implement proper JSON array for opts. + v3->v4: + - keep the same format between input and output, json and non json. + - print gbp as uint. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + man/man8/tc-tunnel_key.8 | 10 ++++- + tc/m_tunnel_key.c | 85 +++++++++++++++++++++++++++++++++++----- + 2 files changed, 85 insertions(+), 10 deletions(-) + +diff --git a/man/man8/tc-tunnel_key.8 b/man/man8/tc-tunnel_key.8 +index 2145eb62e70e2..c208e2c82a181 100644 +--- a/man/man8/tc-tunnel_key.8 ++++ b/man/man8/tc-tunnel_key.8 +@@ -66,8 +66,10 @@ options. + .B id + , + .B dst_port +-and ++, + .B geneve_opts ++and ++.B vxlan_opts + are optional. + .RS + .TP +@@ -91,6 +93,12 @@ is specified in the form CLASS:TYPE:DATA, where CLASS is represented as a + variable length hexadecimal value. Additionally multiple options may be + listed using a comma delimiter. + .TP ++.B vxlan_opts ++Vxlan metatdata options. ++.B vxlan_opts ++is specified in the form GBP, as a 32bit number. Multiple options is not ++supported. ++.TP + .B tos + Outer header TOS + .TP +diff --git a/tc/m_tunnel_key.c b/tc/m_tunnel_key.c +index 4e65e444776a2..76391d6c85fb2 100644 +--- a/tc/m_tunnel_key.c ++++ b/tc/m_tunnel_key.c +@@ -29,7 +29,7 @@ static void explain(void) + "src_ip (mandatory)\n" + "dst_ip (mandatory)\n" + "dst_port \n" +- "geneve_opts \n" ++ "geneve_opts | vxlan_opts \n" + "csum | nocsum (default is \"csum\")\n"); + } + +@@ -112,6 +112,21 @@ static int tunnel_key_parse_u8(char *str, int base, int type, + return 0; + } + ++static int tunnel_key_parse_u32(char *str, int base, int type, ++ struct nlmsghdr *n) ++{ ++ __u32 value; ++ int ret; ++ ++ ret = get_u32(&value, str, base); ++ if (ret) ++ return ret; ++ ++ addattr32(n, MAX_MSG, type, value); ++ ++ return 0; ++} ++ + static int tunnel_key_parse_geneve_opt(char *str, struct nlmsghdr *n) + { + char *token, *saveptr = NULL; +@@ -190,6 +205,27 @@ static int tunnel_key_parse_geneve_opts(char *str, struct nlmsghdr *n) + return 0; + } + ++static int tunnel_key_parse_vxlan_opt(char *str, struct nlmsghdr *n) ++{ ++ struct rtattr *encap, *nest; ++ int ret; ++ ++ encap = addattr_nest(n, MAX_MSG, ++ TCA_TUNNEL_KEY_ENC_OPTS | NLA_F_NESTED); ++ nest = addattr_nest(n, MAX_MSG, ++ TCA_TUNNEL_KEY_ENC_OPTS_VXLAN | NLA_F_NESTED); ++ ++ ret = tunnel_key_parse_u32(str, 0, ++ TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP, n); ++ if (ret) ++ return ret; ++ ++ addattr_nest_end(n, nest); ++ addattr_nest_end(n, encap); ++ ++ return 0; ++} ++ + static int tunnel_key_parse_tos_ttl(char *str, int type, struct nlmsghdr *n) + { + int ret; +@@ -287,6 +323,13 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p, + fprintf(stderr, "Illegal \"geneve_opts\"\n"); + return -1; + } ++ } else if (matches(*argv, "vxlan_opts") == 0) { ++ NEXT_ARG(); ++ ++ if (tunnel_key_parse_vxlan_opt(*argv, n)) { ++ fprintf(stderr, "Illegal \"vxlan_opts\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "tos") == 0) { + NEXT_ARG(); + ret = tunnel_key_parse_tos_ttl(*argv, +@@ -406,13 +449,13 @@ 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) ++static void tunnel_key_print_geneve_options(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 *name = "geneve_opts"; + char strbuf[rem * 2 + 1]; + char data[rem * 2 + 1]; + uint8_t data_r[rem]; +@@ -420,7 +463,8 @@ static void tunnel_key_print_geneve_options(const char *name, + uint8_t type; + + open_json_array(PRINT_JSON, name); +- print_string(PRINT_FP, name, "\n\t%s ", "geneve_opt"); ++ print_nl(); ++ print_string(PRINT_FP, name, "\t%s ", name); + + while (rem) { + parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX, i, rem); +@@ -453,7 +497,27 @@ static void tunnel_key_print_geneve_options(const char *name, + close_json_array(PRINT_JSON, name); + } + +-static void tunnel_key_print_key_opt(const char *name, struct rtattr *attr) ++static void tunnel_key_print_vxlan_options(struct rtattr *attr) ++{ ++ struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ int rem = RTA_PAYLOAD(attr); ++ char *name = "vxlan_opts"; ++ __u32 gbp; ++ ++ parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX, i, rem); ++ gbp = rta_getattr_u32(tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP]); ++ ++ print_nl(); ++ print_string(PRINT_FP, name, "\t%s ", name); ++ open_json_array(PRINT_JSON, name); ++ open_json_object(NULL); ++ print_uint(PRINT_ANY, "gbp", "%u", gbp); ++ close_json_object(); ++ close_json_array(PRINT_JSON, name); ++} ++ ++static void tunnel_key_print_key_opt(struct rtattr *attr) + { + struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1]; + +@@ -461,8 +525,12 @@ static void tunnel_key_print_key_opt(const char *name, struct rtattr *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]); ++ if (tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE]) ++ tunnel_key_print_geneve_options( ++ tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE]); ++ else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]) ++ tunnel_key_print_vxlan_options( ++ tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]); + } + + static void tunnel_key_print_tos_ttl(FILE *f, char *name, +@@ -518,8 +586,7 @@ 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_key_opt(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", +-- +2.26.2 + diff --git a/SOURCES/0028-tc-m_tunnel_key-add-options-support-for-erpsan.patch b/SOURCES/0028-tc-m_tunnel_key-add-options-support-for-erpsan.patch new file mode 100644 index 0000000..5dfebf0 --- /dev/null +++ b/SOURCES/0028-tc-m_tunnel_key-add-options-support-for-erpsan.patch @@ -0,0 +1,265 @@ +From 2fb8c115a8031d893fff588181cc42764391e4d5 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:43:50 +0200 +Subject: [PATCH] tc: m_tunnel_key: add options support for erpsan + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit 668fd9b25d9ec + +commit 668fd9b25d9eca3067040273239f7825db95442b +Author: Xin Long +Date: Mon Apr 27 18:27:49 2020 +0800 + + tc: m_tunnel_key: add options support for erpsan + + This patch is to add TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN's parse and + print to implement erspan options support in m_tunnel_key, like + Commit 6217917a3826 ("tc: m_tunnel_key: Add tunnel option support + to act_tunnel_key") for geneve options support. + + Option is expressed as version:index:dir:hwid, dir and hwid will + be parsed when version is 2, while index will be parsed when + version is 1. erspan doesn't support multiple options. + + With this patch, users can add and dump erspan options like: + + # ip link add name erspan1 type erspan 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 \ + erspan_opts 1:2:0:0 \ + action mirred egress redirect dev erspan1 + # tc -s filter show dev eth0 parent ffff: + + filter protocol ip pref 49151 flower chain 0 handle 0x1 + indev eth0 + eth_type ipv4 + ip_proto udp + not_in_hw + action order 1: tunnel_key set + src_ip 10.0.99.192 + dst_ip 10.0.99.193 + key_id 11 + dst_port 6081 + erspan_opts 1:2:0:0 + csum pipe + index 2 ref 1 bind 1 + ... + v1->v2: + - no change. + v2->v3: + - no change. + v3->v4: + - keep the same format between input and output, json and non json. + - print version, index, dir and hwid as uint. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + man/man8/tc-tunnel_key.8 | 12 +++- + tc/m_tunnel_key.c | 117 ++++++++++++++++++++++++++++++++++++++- + 2 files changed, 127 insertions(+), 2 deletions(-) + +diff --git a/man/man8/tc-tunnel_key.8 b/man/man8/tc-tunnel_key.8 +index c208e2c82a181..ad9972402c0e5 100644 +--- a/man/man8/tc-tunnel_key.8 ++++ b/man/man8/tc-tunnel_key.8 +@@ -68,8 +68,10 @@ options. + .B dst_port + , + .B geneve_opts +-and ++, + .B vxlan_opts ++and ++.B erspan_opts + are optional. + .RS + .TP +@@ -99,6 +101,14 @@ Vxlan metatdata options. + is specified in the form GBP, as a 32bit number. Multiple options is not + supported. + .TP ++.B erspan_opts ++Erspan metatdata options. ++.B erspan_opts ++is specified in the form VERSION:INDEX:DIR:HWID, where VERSION is represented ++as a 8bit number, INDEX as an 32bit number, DIR and HWID as a 8bit number. ++Multiple options is not supported. Note INDEX is used when VERSION is 1, ++and DIR and HWID are used when VERSION is 2. ++.TP + .B tos + Outer header TOS + .TP +diff --git a/tc/m_tunnel_key.c b/tc/m_tunnel_key.c +index 76391d6c85fb2..a56fe24413fa0 100644 +--- a/tc/m_tunnel_key.c ++++ b/tc/m_tunnel_key.c +@@ -29,7 +29,7 @@ static void explain(void) + "src_ip (mandatory)\n" + "dst_ip (mandatory)\n" + "dst_port \n" +- "geneve_opts | vxlan_opts \n" ++ "geneve_opts | vxlan_opts | erspan_opts \n" + "csum | nocsum (default is \"csum\")\n"); + } + +@@ -97,6 +97,21 @@ static int tunnel_key_parse_be16(char *str, int base, int type, + return 0; + } + ++static int tunnel_key_parse_be32(char *str, int base, int type, ++ struct nlmsghdr *n) ++{ ++ __be32 value; ++ int ret; ++ ++ ret = get_be32(&value, str, base); ++ if (ret) ++ return ret; ++ ++ addattr32(n, MAX_MSG, type, value); ++ ++ return 0; ++} ++ + static int tunnel_key_parse_u8(char *str, int base, int type, + struct nlmsghdr *n) + { +@@ -226,6 +241,63 @@ static int tunnel_key_parse_vxlan_opt(char *str, struct nlmsghdr *n) + return 0; + } + ++static int tunnel_key_parse_erspan_opt(char *str, struct nlmsghdr *n) ++{ ++ char *token, *saveptr = NULL; ++ struct rtattr *encap, *nest; ++ int i, ret; ++ ++ encap = addattr_nest(n, MAX_MSG, ++ TCA_TUNNEL_KEY_ENC_OPTS | NLA_F_NESTED); ++ nest = addattr_nest(n, MAX_MSG, ++ TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN | NLA_F_NESTED); ++ ++ token = strtok_r(str, ":", &saveptr); ++ i = 1; ++ while (token) { ++ switch (i) { ++ case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER: ++ { ++ ret = tunnel_key_parse_u8(token, 0, i, n); ++ if (ret) ++ return ret; ++ break; ++ } ++ case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX: ++ { ++ ret = tunnel_key_parse_be32(token, 0, i, n); ++ if (ret) ++ return ret; ++ break; ++ } ++ case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR: ++ { ++ ret = tunnel_key_parse_u8(token, 0, i, n); ++ if (ret) ++ return ret; ++ break; ++ } ++ case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID: ++ { ++ ret = tunnel_key_parse_u8(token, 0, i, n); ++ if (ret) ++ return ret; ++ break; ++ } ++ default: ++ return -1; ++ } ++ ++ token = strtok_r(NULL, ":", &saveptr); ++ i++; ++ } ++ ++ addattr_nest_end(n, nest); ++ addattr_nest_end(n, encap); ++ ++ return 0; ++} ++ + static int tunnel_key_parse_tos_ttl(char *str, int type, struct nlmsghdr *n) + { + int ret; +@@ -330,6 +402,13 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p, + fprintf(stderr, "Illegal \"vxlan_opts\"\n"); + return -1; + } ++ } else if (matches(*argv, "erspan_opts") == 0) { ++ NEXT_ARG(); ++ ++ if (tunnel_key_parse_erspan_opt(*argv, n)) { ++ fprintf(stderr, "Illegal \"erspan_opts\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "tos") == 0) { + NEXT_ARG(); + ret = tunnel_key_parse_tos_ttl(*argv, +@@ -517,6 +596,39 @@ static void tunnel_key_print_vxlan_options(struct rtattr *attr) + close_json_array(PRINT_JSON, name); + } + ++static void tunnel_key_print_erspan_options(struct rtattr *attr) ++{ ++ struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ int rem = RTA_PAYLOAD(attr); ++ char *name = "erspan_opts"; ++ __u8 ver, hwid, dir; ++ __u32 idx; ++ ++ parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX, i, rem); ++ ver = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER]); ++ if (ver == 1) { ++ idx = rta_getattr_be32(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX]); ++ dir = 0; ++ hwid = 0; ++ } else { ++ idx = 0; ++ dir = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR]); ++ hwid = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID]); ++ } ++ ++ print_nl(); ++ print_string(PRINT_FP, name, "\t%s ", name); ++ open_json_array(PRINT_JSON, name); ++ open_json_object(NULL); ++ print_uint(PRINT_ANY, "ver", "%u", ver); ++ print_uint(PRINT_ANY, "index", ":%u", idx); ++ print_uint(PRINT_ANY, "dir", ":%u", dir); ++ print_uint(PRINT_ANY, "hwid", ":%u", hwid); ++ close_json_object(); ++ close_json_array(PRINT_JSON, name); ++} ++ + static void tunnel_key_print_key_opt(struct rtattr *attr) + { + struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1]; +@@ -531,6 +643,9 @@ static void tunnel_key_print_key_opt(struct rtattr *attr) + else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]) + tunnel_key_print_vxlan_options( + tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]); ++ else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN]) ++ tunnel_key_print_erspan_options( ++ tb[TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN]); + } + + static void tunnel_key_print_tos_ttl(FILE *f, char *name, +-- +2.26.2 + diff --git a/SOURCES/0029-tc-f_flower-add-options-support-for-vxlan.patch b/SOURCES/0029-tc-f_flower-add-options-support-for-vxlan.patch new file mode 100644 index 0000000..0de0f70 --- /dev/null +++ b/SOURCES/0029-tc-f_flower-add-options-support-for-vxlan.patch @@ -0,0 +1,316 @@ +From 4bd1eb80a195ce1a64e33f5fc9d5c58bf9f30c8d Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:43:50 +0200 +Subject: [PATCH] tc: f_flower: add options support for vxlan + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit 93c8d5f72f8ce +Conflicts: on a removed line due to missing commit 93c8d5f72f8ce + ("tc: f_flower: add options support for vxlan") + +commit 93c8d5f72f8ce4b98c68508e85457f83933302c0 +Author: Xin Long +Date: Mon Apr 27 18:27:50 2020 +0800 + + tc: f_flower: add options support for vxlan + + This patch is to add TCA_FLOWER_KEY_ENC_OPTS_VXLAN's parse and + print to implement vxlan options support in m_tunnel_key, like + Commit 56155d4df86d ("tc: f_flower: add geneve option match + support to flower") for geneve options support. + + Option is expressed a 32bit number for gbp only, and vxlan + doesn't support multiple options. + + With this patch, users can add and dump vxlan options like: + + # ip link add name vxlan1 type vxlan dstport 0 external + # tc qdisc add dev vxlan1 ingress + # tc filter add dev vxlan1 protocol ip parent ffff: \ + flower \ + enc_src_ip 10.0.99.192 \ + enc_dst_ip 10.0.99.193 \ + enc_key_id 11 \ + vxlan_opts 65793/4008635966 \ + ip_proto udp \ + action mirred egress redirect dev eth1 + # tc -s filter show dev vxlan1 parent ffff: + + filter protocol ip pref 49152 flower chain 0 handle 0x1 + eth_type ipv4 + ip_proto udp + enc_dst_ip 10.0.99.193 + enc_src_ip 10.0.99.192 + enc_key_id 11 + vxlan_opts 65793/4008635966 + not_in_hw + action order 1: mirred (Egress Redirect to device eth1) stolen + index 3 ref 1 bind 1 + Action statistics: + Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) + backlog 0b 0p requeues 0 + + v1->v2: + - get_u32 with base = 0 for gbp. + v2->v3: + - implement proper JSON array for opts. + v3->v4: + - keep the same format between input and output, json and non json. + - print gbp as uint. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + man/man8/tc-flower.8 | 12 ++++ + tc/f_flower.c | 130 +++++++++++++++++++++++++++++++++++++------ + 2 files changed, 126 insertions(+), 16 deletions(-) + +diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8 +index adff41e39b006..0efacbfdf9a95 100644 +--- a/man/man8/tc-flower.8 ++++ b/man/man8/tc-flower.8 +@@ -81,7 +81,11 @@ flower \- flow based traffic control filter + .IR TOS " | " + .B enc_ttl + .IR TTL " | " ++{ + .B geneve_opts ++| ++.B vxlan_opts ++} + .IR OPTIONS " | " + .BR ip_flags + .IR IP_FLAGS +@@ -290,6 +294,8 @@ bits is assumed. + .BI enc_ttl " NUMBER" + .TQ + .BI geneve_opts " OPTIONS" ++.TQ ++.BI vxlan_opts " OPTIONS" + Match on IP tunnel metadata. Key id + .I NUMBER + is a 32 bit tunnel key id (e.g. VNI for VXLAN tunnel). +@@ -310,6 +316,12 @@ 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. ++vxlan_opts ++.I OPTIONS ++doesn't support multiple options, and it consists of a key followed by a slash ++and corresponding mask. If the mask is missing, \fBtc\fR assumes a full-length ++match. The option can be described in the form GBP/GBP_MASK, where GBP is ++represented as a 32bit number. + .TP + .BI ip_flags " IP_FLAGS" + .I IP_FLAGS +diff --git a/tc/f_flower.c b/tc/f_flower.c +index 70d40d3b2f2bf..09079cd2c2280 100644 +--- a/tc/f_flower.c ++++ b/tc/f_flower.c +@@ -81,6 +81,7 @@ static void explain(void) + " enc_tos MASKED-IP_TOS |\n" + " enc_ttl MASKED-IP_TTL |\n" + " geneve_opts MASKED-OPTIONS |\n" ++ " vxlan_opts MASKED-OPTIONS |\n" + " ip_flags IP-FLAGS | \n" + " enc_dst_port [ port_number ] }\n" + " FILTERID := X:Y:Z\n" +@@ -648,7 +649,7 @@ 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) ++static int flower_parse_geneve_opt(char *str, struct nlmsghdr *n) + { + struct rtattr *nest; + char *token; +@@ -718,14 +719,33 @@ static int flower_parse_geneve_opts(char *str, struct nlmsghdr *n) + return 0; + } + +-static int flower_parse_enc_opt_part(char *str, struct nlmsghdr *n) ++static int flower_parse_vxlan_opt(char *str, struct nlmsghdr *n) ++{ ++ struct rtattr *nest; ++ __u32 gbp; ++ int err; ++ ++ nest = addattr_nest(n, MAX_MSG, ++ TCA_FLOWER_KEY_ENC_OPTS_VXLAN | NLA_F_NESTED); ++ ++ err = get_u32(&gbp, str, 0); ++ if (err) ++ return err; ++ addattr32(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP, gbp); ++ ++ addattr_nest_end(n, nest); ++ ++ return 0; ++} ++ ++static int flower_parse_geneve_opts(char *str, struct nlmsghdr *n) + { + char *token; + int err; + + token = strsep(&str, ","); + while (token) { +- err = flower_parse_geneve_opts(token, n); ++ err = flower_parse_geneve_opt(token, n); + if (err) + return err; + +@@ -755,7 +775,7 @@ static int flower_check_enc_opt_key(char *key) + return 0; + } + +-static int flower_parse_enc_opts(char *str, struct nlmsghdr *n) ++static int flower_parse_enc_opts_geneve(char *str, struct nlmsghdr *n) + { + char key[XATTR_SIZE_MAX], mask[XATTR_SIZE_MAX]; + int data_len, key_len, mask_len, err; +@@ -807,13 +827,50 @@ static int flower_parse_enc_opts(char *str, struct nlmsghdr *n) + mask[mask_len - 1] = '\0'; + + nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS); +- err = flower_parse_enc_opt_part(key, n); ++ err = flower_parse_geneve_opts(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); ++ err = flower_parse_geneve_opts(mask, n); ++ if (err) ++ return err; ++ addattr_nest_end(n, nest); ++ ++ return 0; ++} ++ ++static int flower_parse_enc_opts_vxlan(char *str, struct nlmsghdr *n) ++{ ++ char key[XATTR_SIZE_MAX], mask[XATTR_SIZE_MAX]; ++ struct rtattr *nest; ++ char *slash; ++ int err; ++ ++ slash = strchr(str, '/'); ++ if (slash) { ++ *slash++ = '\0'; ++ if (strlen(slash) > XATTR_SIZE_MAX) ++ return -1; ++ strcpy(mask, slash); ++ } else { ++ strcpy(mask, "0xffffffff"); ++ } ++ ++ if (strlen(str) > XATTR_SIZE_MAX) ++ return -1; ++ strcpy(key, str); ++ ++ nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS | NLA_F_NESTED); ++ err = flower_parse_vxlan_opt(str, n); ++ if (err) ++ return err; ++ addattr_nest_end(n, nest); ++ ++ nest = addattr_nest(n, MAX_MSG, ++ TCA_FLOWER_KEY_ENC_OPTS_MASK | NLA_F_NESTED); ++ err = flower_parse_vxlan_opt(mask, n); + if (err) + return err; + addattr_nest_end(n, nest); +@@ -1275,11 +1332,18 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + } + } else if (matches(*argv, "geneve_opts") == 0) { + NEXT_ARG(); +- ret = flower_parse_enc_opts(*argv, n); ++ ret = flower_parse_enc_opts_geneve(*argv, n); + if (ret < 0) { + fprintf(stderr, "Illegal \"geneve_opts\"\n"); + return -1; + } ++ } else if (matches(*argv, "vxlan_opts") == 0) { ++ NEXT_ARG(); ++ ret = flower_parse_enc_opts_vxlan(*argv, n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"vxlan_opts\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "action") == 0) { + NEXT_ARG(); + ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n); +@@ -1643,10 +1707,29 @@ static void flower_print_geneve_opts(const char *name, struct rtattr *attr, + close_json_array(PRINT_JSON, name); + } + +-static void flower_print_geneve_parts(const char *name, struct rtattr *attr, +- char *key, char *mask) ++static void flower_print_vxlan_opts(const char *name, struct rtattr *attr, ++ char *strbuf) ++{ ++ struct rtattr *tb[TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ int rem = RTA_PAYLOAD(attr); ++ __u32 gbp; ++ ++ parse_rtattr(tb, TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX, i, rem); ++ gbp = rta_getattr_u32(tb[TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP]); ++ ++ open_json_array(PRINT_JSON, name); ++ open_json_object(NULL); ++ print_uint(PRINT_JSON, "gbp", NULL, gbp); ++ close_json_object(); ++ close_json_array(PRINT_JSON, name); ++ ++ sprintf(strbuf, "%u", gbp); ++} ++ ++static void flower_print_enc_parts(const char *name, const char *namefrm, ++ struct rtattr *attr, char *key, char *mask) + { +- char *namefrm = "\n geneve_opt %s"; + char *key_token, *mask_token, *out; + int len; + +@@ -1687,14 +1770,29 @@ static void flower_print_enc_opts(const char *name, struct rtattr *attr, + 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); ++ if (key_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE]) { ++ flower_print_geneve_opts("geneve_opt_key", ++ key_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE], key); ++ ++ if (msk_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE]) ++ flower_print_geneve_opts("geneve_opt_mask", ++ msk_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE], msk); ++ ++ flower_print_enc_parts(name, " geneve_opts %s", attr, key, ++ msk); ++ } else if (key_tb[TCA_FLOWER_KEY_ENC_OPTS_VXLAN]) { ++ flower_print_vxlan_opts("vxlan_opt_key", ++ key_tb[TCA_FLOWER_KEY_ENC_OPTS_VXLAN], key); ++ ++ if (msk_tb[TCA_FLOWER_KEY_ENC_OPTS_VXLAN]) ++ flower_print_vxlan_opts("vxlan_opt_mask", ++ msk_tb[TCA_FLOWER_KEY_ENC_OPTS_VXLAN], msk); ++ ++ flower_print_enc_parts(name, " vxlan_opts %s", attr, key, ++ msk); ++ } + + free(msk); + err_key_free: +-- +2.26.2 + diff --git a/SOURCES/0030-tc-f_flower-add-options-support-for-erspan.patch b/SOURCES/0030-tc-f_flower-add-options-support-for-erspan.patch new file mode 100644 index 0000000..6c1469b --- /dev/null +++ b/SOURCES/0030-tc-f_flower-add-options-support-for-erspan.patch @@ -0,0 +1,324 @@ +From 6784a916b142c3bd5cf7c20a30b23e362bd4908a Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:44:22 +0200 +Subject: [PATCH] tc: f_flower: add options support for erspan + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit 4e578c78fedfe + +commit 4e578c78fedfe6ffa5fa5fde56778b264485829b +Author: Xin Long +Date: Mon Apr 27 18:27:51 2020 +0800 + + tc: f_flower: add options support for erspan + + This patch is to add TCA_FLOWER_KEY_ENC_OPTS_ERSPAN's parse and + print to implement erspan options support in m_tunnel_key, like + Commit 56155d4df86d ("tc: f_flower: add geneve option match + support to flower") for geneve options support. + + Option is expressed as version:index:dir:hwid, dir and hwid will + be parsed when version is 2, while index will be parsed when + version is 1. erspan doesn't support multiple options. + + With this patch, users can add and dump erspan options like: + + # ip link add name erspan1 type erspan external + # tc qdisc add dev erspan1 ingress + # tc filter add dev erspan1 protocol ip parent ffff: \ + flower \ + enc_src_ip 10.0.99.192 \ + enc_dst_ip 10.0.99.193 \ + enc_key_id 11 \ + erspan_opts 1:2:0:0/1:255:0:0 \ + ip_proto udp \ + action mirred egress redirect dev eth1 + # tc -s filter show dev erspan1 parent ffff: + + filter protocol ip pref 49152 flower chain 0 handle 0x1 + eth_type ipv4 + ip_proto udp + enc_dst_ip 10.0.99.193 + enc_src_ip 10.0.99.192 + enc_key_id 11 + erspan_opts 1:2:0:0/1:255:0:0 + not_in_hw + action order 1: mirred (Egress Redirect to device eth1) stolen + index 1 ref 1 bind 1 + Action statistics: + Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) + backlog 0b 0p requeues 0 + + v1->v2: + - no change. + v2->v3: + - no change. + v3->v4: + - keep the same format between input and output, json and non json. + - print version, index, dir and hwid as uint. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + man/man8/tc-flower.8 | 13 ++++ + tc/f_flower.c | 171 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 184 insertions(+) + +diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8 +index 0efacbfdf9a95..f41b0f7f1ef13 100644 +--- a/man/man8/tc-flower.8 ++++ b/man/man8/tc-flower.8 +@@ -85,6 +85,8 @@ flower \- flow based traffic control filter + .B geneve_opts + | + .B vxlan_opts ++| ++.B erspan_opts + } + .IR OPTIONS " | " + .BR ip_flags +@@ -296,6 +298,8 @@ bits is assumed. + .BI geneve_opts " OPTIONS" + .TQ + .BI vxlan_opts " OPTIONS" ++.TQ ++.BI erspan_opts " OPTIONS" + Match on IP tunnel metadata. Key id + .I NUMBER + is a 32 bit tunnel key id (e.g. VNI for VXLAN tunnel). +@@ -322,6 +326,15 @@ doesn't support multiple options, and it consists of a key followed by a slash + and corresponding mask. If the mask is missing, \fBtc\fR assumes a full-length + match. The option can be described in the form GBP/GBP_MASK, where GBP is + represented as a 32bit number. ++erspan_opts ++.I OPTIONS ++doesn't support multiple options, and it consists of a key followed by a slash ++and corresponding mask. If the mask is missing, \fBtc\fR assumes a full-length ++match. The option can be described in the form ++VERSION:INDEX:DIR:HWID/VERSION:INDEX_MASK:DIR_MASK:HWID_MASK, where VERSION is ++represented as a 8bit number, INDEX as an 32bit number, DIR and HWID as a 8bit ++number. Multiple options is not supported. Note INDEX/INDEX_MASK is used when ++VERSION is 1, and DIR/DIR_MASK and HWID/HWID_MASK are used when VERSION is 2. + .TP + .BI ip_flags " IP_FLAGS" + .I IP_FLAGS +diff --git a/tc/f_flower.c b/tc/f_flower.c +index 09079cd2c2280..691541ec59d4c 100644 +--- a/tc/f_flower.c ++++ b/tc/f_flower.c +@@ -82,6 +82,7 @@ static void explain(void) + " enc_ttl MASKED-IP_TTL |\n" + " geneve_opts MASKED-OPTIONS |\n" + " vxlan_opts MASKED-OPTIONS |\n" ++ " erspan_opts MASKED-OPTIONS |\n" + " ip_flags IP-FLAGS | \n" + " enc_dst_port [ port_number ] }\n" + " FILTERID := X:Y:Z\n" +@@ -738,6 +739,84 @@ static int flower_parse_vxlan_opt(char *str, struct nlmsghdr *n) + return 0; + } + ++static int flower_parse_erspan_opt(char *str, struct nlmsghdr *n) ++{ ++ struct rtattr *nest; ++ char *token; ++ int i, err; ++ ++ nest = addattr_nest(n, MAX_MSG, ++ TCA_FLOWER_KEY_ENC_OPTS_ERSPAN | NLA_F_NESTED); ++ ++ i = 1; ++ token = strsep(&str, ":"); ++ while (token) { ++ switch (i) { ++ case TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ addattr8(n, MAX_MSG, i, opt_type); ++ break; ++ } ++ case TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX: ++ { ++ __be32 opt_index; ++ ++ if (!strlen(token)) ++ break; ++ err = get_be32(&opt_index, token, 0); ++ if (err) ++ return err; ++ ++ addattr32(n, MAX_MSG, i, opt_index); ++ break; ++ } ++ case TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ addattr8(n, MAX_MSG, i, opt_type); ++ break; ++ } ++ case TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ addattr8(n, MAX_MSG, i, opt_type); ++ 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_geneve_opts(char *str, struct nlmsghdr *n) + { + char *token; +@@ -878,6 +957,49 @@ static int flower_parse_enc_opts_vxlan(char *str, struct nlmsghdr *n) + return 0; + } + ++static int flower_parse_enc_opts_erspan(char *str, struct nlmsghdr *n) ++{ ++ char key[XATTR_SIZE_MAX], mask[XATTR_SIZE_MAX]; ++ struct rtattr *nest; ++ char *slash; ++ int err; ++ ++ ++ slash = strchr(str, '/'); ++ if (slash) { ++ *slash++ = '\0'; ++ if (strlen(slash) > XATTR_SIZE_MAX) ++ return -1; ++ strcpy(mask, slash); ++ } else { ++ int index; ++ ++ slash = strchr(str, ':'); ++ index = (int)(slash - str); ++ memcpy(mask, str, index); ++ strcpy(mask + index, ":0xffffffff:0xff:0xff"); ++ } ++ ++ if (strlen(str) > XATTR_SIZE_MAX) ++ return -1; ++ strcpy(key, str); ++ ++ nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS | NLA_F_NESTED); ++ err = flower_parse_erspan_opt(key, n); ++ if (err) ++ return err; ++ addattr_nest_end(n, nest); ++ ++ nest = addattr_nest(n, MAX_MSG, ++ TCA_FLOWER_KEY_ENC_OPTS_MASK | NLA_F_NESTED); ++ err = flower_parse_erspan_opt(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) + { +@@ -1344,6 +1466,13 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + fprintf(stderr, "Illegal \"vxlan_opts\"\n"); + return -1; + } ++ } else if (matches(*argv, "erspan_opts") == 0) { ++ NEXT_ARG(); ++ ret = flower_parse_enc_opts_erspan(*argv, n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"erspan_opts\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "action") == 0) { + NEXT_ARG(); + ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n); +@@ -1727,6 +1856,38 @@ static void flower_print_vxlan_opts(const char *name, struct rtattr *attr, + sprintf(strbuf, "%u", gbp); + } + ++static void flower_print_erspan_opts(const char *name, struct rtattr *attr, ++ char *strbuf) ++{ ++ struct rtattr *tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX + 1]; ++ __u8 ver, hwid, dir; ++ __u32 idx; ++ ++ parse_rtattr(tb, TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX, RTA_DATA(attr), ++ RTA_PAYLOAD(attr)); ++ ver = rta_getattr_u8(tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER]); ++ if (ver == 1) { ++ idx = rta_getattr_be32(tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX]); ++ hwid = 0; ++ dir = 0; ++ } else { ++ idx = 0; ++ hwid = rta_getattr_u8(tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID]); ++ dir = rta_getattr_u8(tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR]); ++ } ++ ++ open_json_array(PRINT_JSON, name); ++ open_json_object(NULL); ++ print_uint(PRINT_JSON, "ver", NULL, ver); ++ print_uint(PRINT_JSON, "index", NULL, idx); ++ print_uint(PRINT_JSON, "dir", NULL, dir); ++ print_uint(PRINT_JSON, "hwid", NULL, hwid); ++ close_json_object(); ++ close_json_array(PRINT_JSON, name); ++ ++ sprintf(strbuf, "%u:%u:%u:%u", ver, idx, dir, hwid); ++} ++ + static void flower_print_enc_parts(const char *name, const char *namefrm, + struct rtattr *attr, char *key, char *mask) + { +@@ -1792,6 +1953,16 @@ static void flower_print_enc_opts(const char *name, struct rtattr *attr, + + flower_print_enc_parts(name, " vxlan_opts %s", attr, key, + msk); ++ } else if (key_tb[TCA_FLOWER_KEY_ENC_OPTS_ERSPAN]) { ++ flower_print_erspan_opts("erspan_opt_key", ++ key_tb[TCA_FLOWER_KEY_ENC_OPTS_ERSPAN], key); ++ ++ if (msk_tb[TCA_FLOWER_KEY_ENC_OPTS_ERSPAN]) ++ flower_print_erspan_opts("erspan_opt_mask", ++ msk_tb[TCA_FLOWER_KEY_ENC_OPTS_ERSPAN], msk); ++ ++ flower_print_enc_parts(name, " erspan_opts %s", attr, key, ++ msk); + } + + free(msk); +-- +2.26.2 + diff --git a/SPECS/iproute.spec b/SPECS/iproute.spec index 0c8241a..393d372 100644 --- a/SPECS/iproute.spec +++ b/SPECS/iproute.spec @@ -1,5 +1,5 @@ %define rpmversion 5.3.0 -%define specrelease 2%{?dist} +%define specrelease 4%{?dist} %define pkg_release %{specrelease}%{?buildid} Summary: Advanced IP routing and network device configuration tools @@ -20,6 +20,28 @@ Patch4: 0005-man-rdma.8-Add-missing-resource-subcommand-descripti.pa Patch5: 0006-ip-xfrm-Fix-help-messages.patch Patch6: 0007-xfrm-not-try-to-delete-ipcomp-states-when-using-dele.patch Patch7: 0008-man-ip.8-Add-missing-vrf-subcommand-description.patch +Patch8: 0009-nstat-print-useful-error-messages-in-abort-cases.patch +Patch9: 0010-ip-link-xstats-fix-TX-IGMP-reports-string.patch +Patch10: 0011-ip-fix-ip-route-show-json-output-for-multipath-nexth.patch +Patch11: 0012-man-bridge.8-fix-bridge-link-show-description.patch +Patch12: 0013-xfrm-also-check-for-ipv6-state-in-xfrm_state_keep.patch +Patch13: 0014-Update-kernel-headers-and-import-udp.h.patch +Patch14: 0015-ip-xfrm-add-espintcp-encapsulation.patch +Patch15: 0016-Update-kernel-headers-and-import-mptcp.h.patch +Patch16: 0017-add-support-for-mptcp-netlink-interface.patch +Patch17: 0018-Update-kernel-headers.patch +Patch18: 0019-Update-kernel-headers.patch +Patch19: 0020-ss-allow-dumping-MPTCP-subflow-information.patch +Patch20: 0021-man-mptcp-man-page.patch +Patch21: 0022-man-ip.8-add-reference-to-mptcp-man-page.patch +Patch22: 0023-Update-kernel-headers.patch +Patch23: 0024-iproute_lwtunnel-add-options-support-for-geneve-meta.patch +Patch24: 0025-iproute_lwtunnel-add-options-support-for-vxlan-metad.patch +Patch25: 0026-iproute_lwtunnel-add-options-support-for-erspan-meta.patch +Patch26: 0027-tc-m_tunnel_key-add-options-support-for-vxlan.patch +Patch27: 0028-tc-m_tunnel_key-add-options-support-for-erpsan.patch +Patch28: 0029-tc-f_flower-add-options-support-for-vxlan.patch +Patch29: 0030-tc-f_flower-add-options-support-for-erspan.patch License: GPLv2+ and Public Domain BuildRequires: bison BuildRequires: elfutils-libelf-devel @@ -164,6 +186,32 @@ cat %{SOURCE3} >>%{buildroot}%{_sysconfdir}/iproute2/rt_dsfield %{_includedir}/iproute2/bpf_elf.h %changelog +* Fri Jun 05 2020 Andrea Claudi [5.3.0-4.el8] +- tc: f_flower: add options support for erspan (Andrea Claudi) [1830485] +- tc: f_flower: add options support for vxlan (Andrea Claudi) [1830485] +- tc: m_tunnel_key: add options support for erpsan (Andrea Claudi) [1830485] +- tc: m_tunnel_key: add options support for vxlan (Andrea Claudi) [1830485] +- iproute_lwtunnel: add options support for erspan metadata (Andrea Claudi) [1830485] +- iproute_lwtunnel: add options support for vxlan metadata (Andrea Claudi) [1830485] +- iproute_lwtunnel: add options support for geneve metadata (Andrea Claudi) [1830485] +- Update kernel headers (Andrea Claudi) [1830485] +- man: ip.8: add reference to mptcp man-page (Andrea Claudi) [1812207] +- man: mptcp man page (Andrea Claudi) [1812207] +- ss: allow dumping MPTCP subflow information (Andrea Claudi) [1812207] +- Update kernel headers (Andrea Claudi) [1812207] +- Update kernel headers (Andrea Claudi) [1812207] +- add support for mptcp netlink interface (Andrea Claudi) [1812207] +- Update kernel headers and import mptcp.h (Andrea Claudi) [1812207] +- ip: xfrm: add espintcp encapsulation (Andrea Claudi) [1844045] +- Update kernel headers and import udp.h (Andrea Claudi) [1844045] + +* Thu Apr 30 2020 Andrea Claudi [5.3.0-3.el8] +- xfrm: also check for ipv6 state in xfrm_state_keep (Andrea Claudi) [1828033] +- man: bridge.8: fix bridge link show description (Andrea Claudi) [1817571] +- ip: fix ip route show json output for multipath nexthops (Andrea Claudi) [1738633] +- ip link: xstats: fix TX IGMP reports string (Andrea Claudi) [1796041] +- nstat: print useful error messages in abort() cases (Andrea Claudi) [1824896] + * Thu Apr 23 2020 Andrea Claudi [5.3.0-2.el8] - man: ip.8: Add missing vrf subcommand description (Andrea Claudi) [1780010] - xfrm: not try to delete ipcomp states when using deleteall (Andrea Claudi) [1808634]