diff --git a/.gitignore b/.gitignore index d44cfaa..038d357 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/iproute2-3.10.0.tar.gz +SOURCES/iproute-3.10.0-55.el7.tar.xz diff --git a/.iproute.metadata b/.iproute.metadata index 384c662..75c6ec1 100644 --- a/.iproute.metadata +++ b/.iproute.metadata @@ -1 +1 @@ -a3cf3bacdd2cb6eb4eb580a2e7aa20bf7ca0ae6b SOURCES/iproute2-3.10.0.tar.gz +038cea3b78fd901da51be8718e3f41ae880644ea SOURCES/iproute-3.10.0-55.el7.tar.xz diff --git a/SOURCES/0001-man-lnstat-rewrite-manpage.patch b/SOURCES/0001-man-lnstat-rewrite-manpage.patch new file mode 100644 index 0000000..38eeca1 --- /dev/null +++ b/SOURCES/0001-man-lnstat-rewrite-manpage.patch @@ -0,0 +1,249 @@ +From b5c8d07b3e6c4c4b86636b6cb85f812eb634ea34 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 16 Feb 2016 20:03:30 +0100 +Subject: [PATCH] man: lnstat: rewrite manpage + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269133 +Upstream Status: commit f3737abf8ca5e + +commit f3737abf8ca5e446f71d99b4f8e77460ede6f7ef +Author: Phil Sutter +Date: Fri Sep 18 20:17:04 2015 +0200 + + man: lnstat: rewrite manpage + + Signed-off-by: Phil Sutter +--- + man/man8/lnstat.8 | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 192 insertions(+), 5 deletions(-) + +diff --git a/man/man8/lnstat.8 b/man/man8/lnstat.8 +index a76940b..b817bcf 100644 +--- a/man/man8/lnstat.8 ++++ b/man/man8/lnstat.8 +@@ -9,9 +9,21 @@ This manual page documents briefly the + .B lnstat + command. + .PP +-\fBlnstat\fP is a generalized and more feature-complete replacement for the old rtstat program. +-In addition to routing cache statistics, it supports any kind of statistics the linux kernel +-exports via a file in /proc/net/stat/. ++\fBlnstat\fP is a generalized and more feature-complete replacement for the old ++rtstat program. It is commonly used to periodically print a selection of ++statistical values exported by the kernel. ++In addition to routing cache statistics, it supports any kind of statistics the ++linux kernel exports via a file in /proc/net/stat/. ++.PP ++Each file in /proc/net/stat/ contains a header line listing the column names. ++These names are used by \fBlnstat\fP as keys for selecting which statistics to ++print. For every CPU present in the system, a line follows which lists the ++actual values for each column of the file. \fBlnstat\fP sums these values up ++(which in fact are counters) before printing them. After each interval, only ++the difference to the last value is printed. ++.PP ++Files and columns may be selected by using the \fB-f\fP and \fB-k\fP ++parameters. By default, all columns of all files are printed. + .SH OPTIONS + lnstat supports the following options. + .TP +@@ -28,13 +40,15 @@ Print number of intervals. + Dump list of available files/keys. + .TP + .B \-f, \-\-file +-Statistics file to use. ++Statistics file to use, may be specified multiple times. By default all files in /proc/net/stat are scanned. + .TP + .B \-i, \-\-interval + Set interval to 'intv' seconds. + .TP + .B \-k, \-\-keys k,k,k,... +-Display only keys specified. ++Display only keys specified. Each key \fBk\fP is of the form \fB[file:]key\fP. If \fB\fP ++is given, the search for the given key is limited to that file. Otherwise the first file containing ++the searched key is being used. + .TP + .B \-s, \-\-subject [0-2] + Specify display of subject/header. '0' means no header at all, '1' prints a header only at start of the program and '2' prints a header every 20 lines. +@@ -63,6 +77,179 @@ Print a header at start and every 20 lines. + .TP + .B # lnstat -c -1 -i 1 -f rt_cache -k entries,in_hit,in_slow_tot + Display statistics for keys entries, in_hit and in_slow_tot of field rt_cache every second. ++ ++.SH FILES ++.TP ++.B /proc/net/stat/arp_cache, /proc/net/stat/ndisc_cache ++Statistics around neighbor cache and ARP. \fBarp_cache\fP is for IPv4, \fBndisc_cache\fP is the same for IPv6. ++.sp ++.B entries ++Number of entries in the neighbor table. ++.sp ++.B allocs ++How many neighbor entries have been allocated. ++.sp ++.B destroys ++How many neighbor entries have been removed. ++.sp ++.B hash_grows ++How often the neighbor (hash) table was increased. ++.sp ++.B lookups ++How many lookups were performed. ++.sp ++.B hits ++How many \fBlookups\fP were successful. ++.sp ++.B res_failed ++How many neighbor lookups failed. ++.sp ++.B rcv_probes_mcast ++How many multicast neighbor solicitations were received. (IPv6 only.) ++.sp ++.B rcv_probes_ucast ++How many unicast neighbor solicitations were received. (IPv6 only.) ++.sp ++.B periodic_gc_runs ++How many garbage collection runs were executed. ++.sp ++.B forced_gc_runs ++How many forced garbage collection runs were executed. Happens when adding an ++entry and the table is too full. ++.sp ++.B unresolved_discards ++How many neighbor table entries were discarded due to lookup failure. ++.sp ++.B table_fulls ++Number of table overflows. Happens if table is full and forced GC run (see ++\fBforced_gc_runs\fP) has failed. ++ ++.TP ++.B /proc/net/stat/ip_conntrack, /proc/net/stat/nf_conntrack ++Conntrack related counters. \fBip_conntrack\fP is for backwards compatibility ++with older userspace only and shows the same data as \fBnf_conntrack\fP. ++.sp ++.B entries ++Number of entries in conntrack table. ++.sp ++.B searched ++Number of conntrack table lookups performed. ++.sp ++.B found ++Number of \fBsearched\fP entries which were successful. ++.sp ++.B new ++Number of conntrack entries added which were not expected before. ++.sp ++.B invalid ++Number of packets seen which can not be tracked. ++.sp ++.B ignore ++Number of packets seen which are already connected to a conntrack entry. ++.sp ++.B delete ++Number of conntrack entries which were removed. ++.sp ++.B delete_list ++Number of conntrack entries which were put to dying list. ++.sp ++.B insert ++Number of entries inserted into the list. ++.sp ++.B insert_failed ++Number of entries for which list insertion was attempted but failed (happens if ++the same entry is already present). ++.sp ++.B drop ++Number of packets dropped due to conntrack failure. Either new conntrack entry ++allocation failed, or protocol helper dropped the packet. ++.sp ++.B early_drop ++Number of dropped conntrack entries to make room for new ones, if maximum table ++size was reached. ++.sp ++.B icmp_error ++Number of packets wich could not be tracked due to error situation. This is a ++subset of \fBinvalid\fP. ++.sp ++.B expect_new ++Number of conntrack entries added after an expectation for them was already ++present. ++.sp ++.B expect_create ++Number of expectations added. ++.sp ++.B expect_delete ++Number of expectations deleted. ++.sp ++.B search_restart ++Number of conntrack table lookups which had to be restarted due to hashtable ++resizes. ++ ++.TP ++.B /proc/net/stat/rt_cache ++Routing cache statistics. ++.sp ++.B entries ++Number of entries in routing cache. ++.sp ++.B in_hit ++Number of route cache hits for incoming packets. Deprecated since IP route ++cache removal, therefore always zero. ++.sp ++.B in_slow_tot ++Number of routing cache entries added for input traffic. ++.sp ++.B in_slow_mc ++Number of multicast routing cache entries added for input traffic. ++.sp ++.B in_no_route ++Number of input packets for which no routing table entry was found. ++.sp ++.B in_brd ++Number of matched input broadcast packets. ++.sp ++.B in_martian_dst ++Number of incoming martian destination packets. ++.sp ++.B in_martian_src ++Number of incoming martian source packets. ++.sp ++.B out_hit ++Number of route cache hits for outgoing packets. Deprecated since IP route ++cache removal, therefore always zero. ++.sp ++.B out_slow_tot ++Number of routing cache entries added for output traffic. ++.sp ++.B out_slow_mc ++Number of multicast routing cache entries added for output traffic. ++.sp ++.B gc_total ++Total number of garbage collection runs. Deprecated since IP route cache ++removal, therefore always zero. ++.sp ++.B gc_ignored ++Number of ignored garbage collection runs due to minimum GC interval not ++reached and routing cache not full. Deprecated since IP route cache removal, ++therefore always zero. ++.sp ++.B gc_goal_miss ++Number of garbage collector goal misses. Deprecated since IP route cache ++removal, therefore always zero. ++.sp ++.B gc_dst_overflow ++Number of destination cache overflows. Deprecated since IP route cache removal, ++therefore always zero. ++.sp ++.B in_hlist_search ++Number of hash table list traversals for input traffic. Deprecated since IP ++route cache removal, therefore always zero. ++.sp ++.B out_hlist_search ++Number of hash table list traversals for output traffic. Deprecated since IP ++route cache removal, therefore always zero. ++ + .SH SEE ALSO + .BR ip (8), + and /usr/share/doc/iproute-doc/README.lnstat (package iproute-doc on Debian) +-- +1.8.3.1 + diff --git a/SOURCES/0002-lnstat-fix-header-displaying-mechanism.patch b/SOURCES/0002-lnstat-fix-header-displaying-mechanism.patch new file mode 100644 index 0000000..d4eaff9 --- /dev/null +++ b/SOURCES/0002-lnstat-fix-header-displaying-mechanism.patch @@ -0,0 +1,58 @@ +From 54a2e1a045adae87ccd7b3047c1ccc3b1eea1351 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 16 Feb 2016 20:48:44 +0100 +Subject: [PATCH] lnstat: fix header displaying mechanism + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1263392 +Upstream Status: commit fdb347f7fd6c3 +Conflicts: Patch practically rewritten due to missing commit + a4f9e8df37b23 ("lnstat: add json output format") and + follow-ups. + +commit fdb347f7fd6c36b270a8c571cbe9a124a281b2b5 +Author: Phil Sutter +Date: Wed Nov 18 16:57:47 2015 +0100 + + lnstat: fix header displaying mechanism + + The algorithm depends on the loop counter ('i') to increment by one in + each iteration. Though if running endlessly (count==0), the counter was + not incremented at all. + + Also change formatting of the header printing conditional a bit so it's + hopefully easier to read. + + Fixes: e7e2913 ("lnstat: run indefinitely by default") + Signed-off-by: Phil Sutter +--- + misc/lnstat.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/misc/lnstat.c b/misc/lnstat.c +index fcd7dd3..f2bb695 100644 +--- a/misc/lnstat.c ++++ b/misc/lnstat.c +@@ -332,16 +332,15 @@ int main(int argc, char **argv) + if (interval < 1 ) + interval=1; + +- for (i = 0; i < count || !count; ) { +- if ((hdr > 1 && (! (i % 20))) || (hdr == 1 && i == 0)) +- print_hdr(stdout, header); ++ for (i = 0; i < count || !count; i++) { + lnstat_update(lnstat_files); ++ if ((hdr > 1 && !(i % 20)) || ++ (hdr == 1 && i == 0)) ++ print_hdr(stdout, header); + print_line(stdout, lnstat_files, &fp); + fflush(stdout); + if (i < count - 1 || !count) + sleep(interval); +- if (count) +- ++i; + } + } + +-- +1.8.3.1 + diff --git a/SOURCES/0003-iproute2-Ignore-EADDRNOTAVAIL-errors-during-address-.patch b/SOURCES/0003-iproute2-Ignore-EADDRNOTAVAIL-errors-during-address-.patch new file mode 100644 index 0000000..6eecb61 --- /dev/null +++ b/SOURCES/0003-iproute2-Ignore-EADDRNOTAVAIL-errors-during-address-.patch @@ -0,0 +1,66 @@ +From fe077314f11f76536a7952e8b96951be104f89d1 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 17 Feb 2016 14:03:59 +0100 +Subject: [PATCH] iproute2: Ignore EADDRNOTAVAIL errors during address flush + operation + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291825 +Upstream Status: commit e149d4e84384f + +commit e149d4e84384f88965ce43a6390acf7ba356187c +Author: Neil Horman +Date: Thu Nov 5 14:54:17 2015 -0500 + + iproute2: Ignore EADDRNOTAVAIL errors during address flush operation + + I found recently that, if I disabled address promotion in the kernel, that + ip addr flush dev + + would fail with an EADDRNOTAVAIL errno (though the flush operation would in fact + flush all addresses from an interface properly) + + Whats happening is that, if I add a primary and multiple secondary addresses to + an interface, the flush operation first ennumerates them all with a GETADDR | + DUMP operation, then sends a delete request for each address. But the kernel, + having promotion disabled, deletes all secondary addresses when the primary is + removed. That means, that several delete requests may still be pending in the + netlink request for addresses that have been removed on our behalf, resulting in + EADDRNOTAVAIL return codes. + + It seems the simplest thing to do is to understand that EADDRUNAVAIL isn't a + fatal outcome on a flush operation, as it just indicates that an address which + you want to remove is already removed, so it can safely be ignored. + + Signed-off-by: Neil Horman + CC: Stephen Hemminger + CC: Alexey Kuznetsov +--- + ip/ipaddress.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 53c7001..f4537db 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -651,7 +651,17 @@ int print_linkinfo(const struct sockaddr_nl *who, + + static int flush_update(void) + { +- if (rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) { ++ ++ /* ++ * Note that the kernel may delete multiple addresses for one ++ * delete request (e.g. if ipv4 address promotion is disabled). ++ * Since a flush operation is really a series of delete requests ++ * its possible that we may request an address delete that has ++ * already been done by the kernel. Therefore, ignore EADDRNOTAVAIL ++ * errors returned from a flush request ++ */ ++ if ((rtnl_send_check(&rth, filter.flushb, filter.flushp) < 0) && ++ (errno != EADDRNOTAVAIL)) { + perror("Failed to send flush request"); + return -1; + } +-- +1.8.3.1 + diff --git a/SOURCES/0004-libnetlink-introduce-nc_flags.patch b/SOURCES/0004-libnetlink-introduce-nc_flags.patch new file mode 100644 index 0000000..40ffc16 --- /dev/null +++ b/SOURCES/0004-libnetlink-introduce-nc_flags.patch @@ -0,0 +1,81 @@ +From 81112a9fc77aa269f3fa7cde80facb9b9056854f Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 17 Feb 2016 14:03:59 +0100 +Subject: [PATCH] libnetlink: introduce nc_flags + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291825 +Upstream Status: commit 8e72880f6bfa3 +Conflicts: Changes in context and removed code due to missing commit + 892e21248cfdb ("remove unnecessary extern") + +commit 8e72880f6bfa39f439b9c4a88eb84b635b991687 +Author: Phil Sutter +Date: Tue Nov 24 15:31:01 2015 +0100 + + libnetlink: introduce nc_flags + + Allow for a filter to ignore certain nlmsg_flags. + + Signed-off-by: Phil Sutter +--- + include/libnetlink.h | 8 ++++++-- + lib/libnetlink.c | 10 ++++++---- + 2 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/include/libnetlink.h b/include/libnetlink.h +index bd9bde0..058dc64 100644 +--- a/include/libnetlink.h ++++ b/include/libnetlink.h +@@ -58,12 +58,16 @@ struct rtnl_dump_filter_arg + { + rtnl_filter_t filter; + void *arg1; ++ __u16 nc_flags; + }; + + extern int rtnl_dump_filter_l(struct rtnl_handle *rth, + const struct rtnl_dump_filter_arg *arg); +-extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter, +- void *arg); ++int rtnl_dump_filter_nc(struct rtnl_handle *rth, ++ rtnl_filter_t filter, ++ void *arg, __u16 nc_flags); ++#define rtnl_dump_filter(rth, filter, arg) \ ++ rtnl_dump_filter_nc(rth, filter, arg, 0) + extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + unsigned groups, struct nlmsghdr *answer) + __attribute__((warn_unused_result)); +diff --git a/lib/libnetlink.c b/lib/libnetlink.c +index 424a5b6..95675be 100644 +--- a/lib/libnetlink.c ++++ b/lib/libnetlink.c +@@ -234,6 +234,8 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth, + while (NLMSG_OK(h, msglen)) { + int err = 0; + ++ h->nlmsg_flags &= ~a->nc_flags; ++ + if (nladdr.nl_pid != 0 || + h->nlmsg_pid != rth->local.nl_pid || + h->nlmsg_seq != rth->dump) +@@ -292,13 +294,13 @@ skip_it: + } + } + +-int rtnl_dump_filter(struct rtnl_handle *rth, ++int rtnl_dump_filter_nc(struct rtnl_handle *rth, + rtnl_filter_t filter, +- void *arg1) ++ void *arg1, __u16 nc_flags) + { + const struct rtnl_dump_filter_arg a[2] = { +- { .filter = filter, .arg1 = arg1, }, +- { .filter = NULL, .arg1 = NULL, }, ++ { .filter = filter, .arg1 = arg1, .nc_flags = nc_flags, }, ++ { .filter = NULL, .arg1 = NULL, .nc_flags = 0, }, + }; + + return rtnl_dump_filter_l(rth, a); +-- +1.8.3.1 + diff --git a/SOURCES/0005-ipaddress-simplify-ipaddr_flush.patch b/SOURCES/0005-ipaddress-simplify-ipaddr_flush.patch new file mode 100644 index 0000000..966545a --- /dev/null +++ b/SOURCES/0005-ipaddress-simplify-ipaddr_flush.patch @@ -0,0 +1,86 @@ +From 6a865378a9e17df5ae352b3b41c96deb32a5b16d Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 17 Feb 2016 14:05:14 +0100 +Subject: [PATCH] ipaddress: simplify ipaddr_flush() + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291825 +Upstream Status: commit c6995c4802523 + +commit c6995c48025233902a5b0c5fe88654e17ea934f6 +Author: Phil Sutter +Date: Tue Nov 24 15:31:00 2015 +0100 + + ipaddress: simplify ipaddr_flush() + + Since it's no longer relevant whether an IP address is primary or + secondary when flushing, ipaddr_flush() can be simplified a bit. + + Signed-off-by: Phil Sutter +--- + ip/ipaddress.c | 38 +------------------------------------- + 1 file changed, 1 insertion(+), 37 deletions(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index f4537db..6f50354 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -885,28 +885,6 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, + return 0; + } + +-static int print_addrinfo_primary(const struct sockaddr_nl *who, +- struct nlmsghdr *n, void *arg) +-{ +- struct ifaddrmsg *ifa = NLMSG_DATA(n); +- +- if (ifa->ifa_flags & IFA_F_SECONDARY) +- return 0; +- +- return print_addrinfo(who, n, arg); +-} +- +-static int print_addrinfo_secondary(const struct sockaddr_nl *who, +- struct nlmsghdr *n, void *arg) +-{ +- struct ifaddrmsg *ifa = NLMSG_DATA(n); +- +- if (!(ifa->ifa_flags & IFA_F_SECONDARY)) +- return 0; +- +- return print_addrinfo(who, n, arg); +-} +- + struct nlmsg_list + { + struct nlmsg_list *next; +@@ -1149,26 +1127,12 @@ static int ipaddr_flush(void) + filter.flushe = sizeof(flushb); + + while ((max_flush_loops == 0) || (round < max_flush_loops)) { +- const struct rtnl_dump_filter_arg a[3] = { +- { +- .filter = print_addrinfo_secondary, +- .arg1 = stdout, +- }, +- { +- .filter = print_addrinfo_primary, +- .arg1 = stdout, +- }, +- { +- .filter = NULL, +- .arg1 = NULL, +- }, +- }; + if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { + perror("Cannot send dump request"); + exit(1); + } + filter.flushed = 0; +- if (rtnl_dump_filter_l(&rth, a) < 0) { ++ if (rtnl_dump_filter(&rth, print_addrinfo, stdout) < 0) { + fprintf(stderr, "Flush terminated\n"); + exit(1); + } +-- +1.8.3.1 + diff --git a/SOURCES/0006-ipaddress-fix-ipaddr_flush-for-Linux-3.1.patch b/SOURCES/0006-ipaddress-fix-ipaddr_flush-for-Linux-3.1.patch new file mode 100644 index 0000000..23914ac --- /dev/null +++ b/SOURCES/0006-ipaddress-fix-ipaddr_flush-for-Linux-3.1.patch @@ -0,0 +1,43 @@ +From 09bf564447edb4b024c0db0bd1c6b6aa43974a08 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 17 Feb 2016 14:05:14 +0100 +Subject: [PATCH] ipaddress: fix ipaddr_flush for Linux >= 3.1 + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291825 +Upstream Status: commit d25ec03e1dce4 + +commit d25ec03e1dce4cf22093a9f7106e9401ab5bf066 +Author: Phil Sutter +Date: Tue Nov 24 15:31:02 2015 +0100 + + ipaddress: fix ipaddr_flush for Linux >= 3.1 + + Linux version 3.1 introduced a consistency check for netlink dumps in + commit 670dc28 ("netlink: advertise incomplete dumps"). This bites + iproute2 when flushing more addresses than can fit into a single + RTM_GETADDR response. To silence the spurious error message "Dump was + interrupted and may be inconsistent.", advise rtnl_dump_filter_l() to + not care about NLM_F_DUMP_INTR. + + Signed-off-by: Phil Sutter +--- + ip/ipaddress.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 6f50354..197f5ae 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -1132,7 +1132,8 @@ static int ipaddr_flush(void) + exit(1); + } + filter.flushed = 0; +- if (rtnl_dump_filter(&rth, print_addrinfo, stdout) < 0) { ++ if (rtnl_dump_filter_nc(&rth, print_addrinfo, ++ stdout, NLM_F_DUMP_INTR) < 0) { + fprintf(stderr, "Flush terminated\n"); + exit(1); + } +-- +1.8.3.1 + diff --git a/SOURCES/0007-bridge-drop-reference-to-unused-option-embedded-from.patch b/SOURCES/0007-bridge-drop-reference-to-unused-option-embedded-from.patch new file mode 100644 index 0000000..e419cd5 --- /dev/null +++ b/SOURCES/0007-bridge-drop-reference-to-unused-option-embedded-from.patch @@ -0,0 +1,59 @@ +From e9ecb24fed993510096af3037139345b25fe2aa1 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 12:37:52 +0100 +Subject: [PATCH] bridge: drop reference to unused option embedded from manpage + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1075692 +Upstream Status: iproute2.git commit 822e9609e7ae8 + +commit 822e9609e7ae8e7dee27355d89d778f14cc27a2d +Author: Andy Gospodarek +Date: Tue Mar 17 11:34:10 2015 -0400 + + bridge: drop reference to unused option embedded from manpage + + While looking at the manpage, I noticed a reference to 'embedded' that was + added by this commit: + + commit d611682a8c8f28205158e6d3a7d5e2d01db022cc + Author: John Fastabend + Date: Thu Sep 13 23:50:36 2012 -0700 + + iproute2: bridge: finish removing replace option in man pages + + I no longer see any reference to the 'embedded' option in any c- or h-files, so + it seems worthwhile to remove. + + Signed-off-by: Andy Gospodarek + CC: John Fastabend +--- + man/man8/bridge.8 | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 +index 96312da..519640e 100644 +--- a/man/man8/bridge.8 ++++ b/man/man8/bridge.8 +@@ -50,7 +50,7 @@ bridge \- show / manipulate bridge addresses and devices + .B dev + .IR DEV " { " + .BR local " | " temp " } { " +-.BR self " } { " embedded " } { " router " } [ " ++.BR self " } { " router " } [ " + .B dst + .IR IPADDR " ] [ " + .B vni +@@ -296,10 +296,6 @@ the interface to which this address is associated. + - the address is associated with a software fdb (default) + .sp + +-.B embedded +-- the address is associated with an offloaded fdb +-.sp +- + .B router + - the destination address is associated with a router. + Valid if the referenced device is a VXLAN type device and has +-- +1.8.3.1 + diff --git a/SOURCES/0008-bridge-drop-man-page-fragment.patch b/SOURCES/0008-bridge-drop-man-page-fragment.patch new file mode 100644 index 0000000..8a3952b --- /dev/null +++ b/SOURCES/0008-bridge-drop-man-page-fragment.patch @@ -0,0 +1,36 @@ +From 54c907ac41637ccf40c1997b20066129230331d8 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 12:37:52 +0100 +Subject: [PATCH] bridge: drop man page fragment + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1075692 +Upstream Status: iproute2.git commit efb169717e4e6 + +commit efb169717e4e6e4eaebbb65da29b64e076942759 +Author: Stephen Hemminger +Date: Tue Jul 28 16:50:19 2015 -0700 + + bridge: drop man page fragment + + Left over copy/paste from ip monitor man page. +--- + man/man8/bridge.8 | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 +index 519640e..7f67867 100644 +--- a/man/man8/bridge.8 ++++ b/man/man8/bridge.8 +@@ -505,8 +505,7 @@ described in previous sections. + .P + If a file name is given, it does not listen on RTNETLINK, + but opens the file containing RTNETLINK messages saved in binary format +-and dumps them. Such a history file can be generated with the +- ++and dumps them. + + .SH NOTES + This command uses facilities added in Linux 3.0. +-- +1.8.3.1 + diff --git a/SOURCES/0009-bridge-fdb-add-use-option-to-set-NTF_USE-flag-in-fdb.patch b/SOURCES/0009-bridge-fdb-add-use-option-to-set-NTF_USE-flag-in-fdb.patch new file mode 100644 index 0000000..aab205b --- /dev/null +++ b/SOURCES/0009-bridge-fdb-add-use-option-to-set-NTF_USE-flag-in-fdb.patch @@ -0,0 +1,96 @@ +From 56fcd25048b851772694f870b7eeb78ea5e147a7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 12:38:18 +0100 +Subject: [PATCH] bridge fdb: add 'use' option to set NTF_USE flag in fdb add + requests + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1075692 +Upstream Status: iproute2.git commit cd8df30b7c64d + +commit cd8df30b7c64da0cf0e3653490a9545f77b59e85 +Author: Roopa Prabhu +Date: Thu Jul 30 14:37:02 2015 -0700 + + bridge fdb: add 'use' option to set NTF_USE flag in fdb add requests + + This is similar to command options corresponding to other NTF_* flags + already exposed to the user space (examples self/master). + + Also updates bridge man page (The man page patch also includes + a fix to the 'self' entry and documents 'master' for fdb entries) + + Signed-off-by: Roopa Prabhu + Reviewed-by: Nikolay Aleksandrov +--- + bridge/fdb.c | 7 +++++-- + man/man8/bridge.8 | 15 ++++++++++++--- + 2 files changed, 17 insertions(+), 5 deletions(-) + +diff --git a/bridge/fdb.c b/bridge/fdb.c +index 615541e..513b3f9 100644 +--- a/bridge/fdb.c ++++ b/bridge/fdb.c +@@ -30,8 +30,9 @@ int filter_index; + + static void usage(void) + { +- fprintf(stderr, "Usage: bridge fdb { add | append | del | replace } ADDR dev DEV {self|master} [ temp ]\n" +- " [router] [ dst IPADDR] [ vlan VID ]\n" ++ fprintf(stderr, "Usage: bridge fdb { add | append | del | replace ADDR dev DEV\n" ++ " [ self ] [ master ] [ use ] [ router ]\n" ++ " [ local | temp ] [ dst IPADDR ] [ vlan VID ]\n" + " [ port PORT] [ vni VNI ] [via DEV]\n"); + fprintf(stderr, " bridge fdb {show} [ dev DEV ]\n"); + exit(-1); +@@ -269,6 +270,8 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv) + duparg2("vlan", *argv); + NEXT_ARG(); + vid = atoi(*argv); ++ } else if (matches(*argv, "use") == 0) { ++ req.ndm.ndm_flags |= NTF_USE; + } else { + if (strcmp(*argv, "to") == 0) { + NEXT_ARG(); +diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 +index 7f67867..68a86e5 100644 +--- a/man/man8/bridge.8 ++++ b/man/man8/bridge.8 +@@ -49,8 +49,8 @@ bridge \- show / manipulate bridge addresses and devices + .I LLADDR + .B dev + .IR DEV " { " +-.BR local " | " temp " } { " +-.BR self " } { " router " } [ " ++.BR local " | " temp " } [ " ++.BR self " ] [ " master " ] [ " router " ] [ " use " ] [ " + .B dst + .IR IPADDR " ] [ " + .B vni +@@ -293,7 +293,11 @@ the Ethernet MAC address. + the interface to which this address is associated. + + .B self +-- the address is associated with a software fdb (default) ++- the address is associated with the port drivers fdb. Usually hardware. ++.sp ++ ++.B master ++- the address is associated with master devices fdb. Usually software (default). + .sp + + .B router +@@ -302,6 +306,11 @@ Valid if the referenced device is a VXLAN type device and has + route shortcircuit enabled. + .sp + ++.B use ++- the address is in use. User space can use this option to ++indicate to the kernel that the fdb entry is in use. ++.sp ++ + .in -8 + The next command line parameters apply only + when the specified device +-- +1.8.3.1 + diff --git a/SOURCES/0010-ip-allow-ip-address-show-to-list-addresses-with-cert.patch b/SOURCES/0010-ip-allow-ip-address-show-to-list-addresses-with-cert.patch new file mode 100644 index 0000000..b399c98 --- /dev/null +++ b/SOURCES/0010-ip-allow-ip-address-show-to-list-addresses-with-cert.patch @@ -0,0 +1,70 @@ +From beadd143d5adde6e482bb088255f9bba7a8d850a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 13:21:45 +0100 +Subject: [PATCH] ip: allow ip address show to list addresses with certain + flags not being set + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1231898 +Upstream Status: iproute2.git commit b5f39b2588a6b + +commit b5f39b2588a6b0312f11ac6d0fab9391b105b83c +Author: Heiner Kallweit +Date: Mon Dec 22 20:18:43 2014 +0100 + + ip: allow ip address show to list addresses with certain flags not being set + + Sometimes it's needed to have "ip address show" list only addresses + with certain flags not being set, e.g. in network scripts. + As an example one might want to exclude addresses in "tentative" + or "deprecated" state. + + Support listing addresses with flags tentative, deprecated, dadfailed + not being set by prefixing the respective flag with a minus. + + Signed-off-by: Heiner Kallweit +--- + ip/ipaddress.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 197f5ae..1e0728c 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -80,7 +80,7 @@ static void usage(void) + fprintf(stderr, "SCOPE-ID := [ host | link | global | NUMBER ]\n"); + fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n"); + fprintf(stderr, "FLAG := [ permanent | dynamic | secondary | primary |\n"); +- fprintf(stderr, " tentative | deprecated | dadfailed | temporary |\n"); ++ fprintf(stderr, " [-]tentative | [-]deprecated | [-]dadfailed | temporary |\n"); + fprintf(stderr, " CONFFLAG-LIST ]\n"); + fprintf(stderr, "CONFFLAG-LIST := [ CONFFLAG-LIST ] CONFFLAG\n"); + fprintf(stderr, "CONFFLAG := [ home | nodad | mngtmpaddr | noprefixroute ]\n"); +@@ -1233,9 +1233,15 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) + } else if (strcmp(*argv, "tentative") == 0) { + filter.flags |= IFA_F_TENTATIVE; + filter.flagmask |= IFA_F_TENTATIVE; ++ } else if (strcmp(*argv, "-tentative") == 0) { ++ filter.flags &= ~IFA_F_TENTATIVE; ++ filter.flagmask |= IFA_F_TENTATIVE; + } else if (strcmp(*argv, "deprecated") == 0) { + filter.flags |= IFA_F_DEPRECATED; + filter.flagmask |= IFA_F_DEPRECATED; ++ } else if (strcmp(*argv, "-deprecated") == 0) { ++ filter.flags &= ~IFA_F_DEPRECATED; ++ filter.flagmask |= IFA_F_DEPRECATED; + } else if (strcmp(*argv, "home") == 0) { + filter.flags |= IFA_F_HOMEADDRESS; + filter.flagmask |= IFA_F_HOMEADDRESS; +@@ -1251,6 +1257,9 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) + } else if (strcmp(*argv, "dadfailed") == 0) { + filter.flags |= IFA_F_DADFAILED; + filter.flagmask |= IFA_F_DADFAILED; ++ } else if (strcmp(*argv, "-dadfailed") == 0) { ++ filter.flags &= ~IFA_F_DADFAILED; ++ filter.flagmask |= IFA_F_DADFAILED; + } else if (strcmp(*argv, "label") == 0) { + NEXT_ARG(); + filter.label = *argv; +-- +1.8.3.1 + diff --git a/SOURCES/0011-ip-extend-ip-address-man-page-to-reflect-the-recent-.patch b/SOURCES/0011-ip-extend-ip-address-man-page-to-reflect-the-recent-.patch new file mode 100644 index 0000000..0e24507 --- /dev/null +++ b/SOURCES/0011-ip-extend-ip-address-man-page-to-reflect-the-recent-.patch @@ -0,0 +1,73 @@ +From 93d677d83f7c0b6152746ecd03b7a0619c75fabd Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 13:21:45 +0100 +Subject: [PATCH] ip: extend "ip-address" man page to reflect the recent flag + extensions + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1231898 +Upstream Status: iproute2.git commit 18c8bbe3dbe11 + +commit 18c8bbe3dbe118ccf4c8da4c9b2e4fc52f7a8aaf +Author: Heiner Kallweit +Date: Wed Dec 24 23:11:50 2014 +0100 + + ip: extend "ip-address" man page to reflect the recent flag extensions + + Extend "ip-address" man page to reflect the recent extension of + allowing to list addresses with flags tentative, deprecated, dadfailed + not being set. + + Signed-off-by: Heiner Kallweit +--- + man/man8/ip-address.8.in | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in +index c6f25ea..6e46af8 100644 +--- a/man/man8/ip-address.8.in ++++ b/man/man8/ip-address.8.in +@@ -50,8 +50,9 @@ ip-address \- protocol address management + + .ti -8 + .IR FLAG " := " +-.RB "[ " permanent " | " dynamic " | " secondary " | " primary " | "\ +-tentative " | " deprecated " | " dadfailed " | " temporary " ]" ++.RB "[ " permanent " | " dynamic " | " secondary " | " primary " | \ ++[ - ] " tentative " | [ - ] " deprecated " | [ - ] " dadfailed " | "\ ++temporary " ]" + + .SH "DESCRIPTION" + The +@@ -178,15 +179,29 @@ addresses. + address detection. + + .TP ++.B -tentative ++(IPv6 only) only list addresses which are not in the process of ++duplicate address detection currently. ++ ++.TP + .B deprecated + (IPv6 only) only list deprecated addresses. + + .TP ++.B -deprecated ++(IPv6 only) only list addresses not being deprecated. ++ ++.TP + .B dadfailed + (IPv6 only) only list addresses which have failed duplicate + address detection. + + .TP ++.B -dadfailed ++(IPv6 only) only list addresses which have not failed duplicate ++address detection. ++ ++.TP + .B temporary + (IPv6 only) only list temporary addresses. + +-- +1.8.3.1 + diff --git a/SOURCES/0012-ip-address-fix-and-extend-documentation.patch b/SOURCES/0012-ip-address-fix-and-extend-documentation.patch new file mode 100644 index 0000000..5cb63dd --- /dev/null +++ b/SOURCES/0012-ip-address-fix-and-extend-documentation.patch @@ -0,0 +1,296 @@ +From de15ee438be780578c0dec2ece6f96cd511b43e5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 13:21:45 +0100 +Subject: [PATCH] ip-address: fix and extend documentation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1231898 +Upstream Status: iproute2.git commit 4e972d5ef41b2 + +commit 4e972d5ef41b28679a8125ed5289496284a9157f +Author: Pavel Šimerda +Date: Wed Aug 12 22:04:08 2015 +0200 + + ip-address: fix and extend documentation + + * Improve manual page synopsis and built-it help + * Use full subcommand names (e.g. 'address' and 'maddress') + * Specify when IPv4, IPv6 or both are affected + * Add lifetimes, home and nodad + * Remove any remaining excess spaces + + Commit 43d29f7 substantially improves generated ip-address.8 instead of + ip-address.8.in and commit e419f2d removes the generated one losing the + improvements entirely. This commit recovers the lost changes, adapts + them to the current manual page and adds more man page and help + improvements. + + Original commit by: Kenyon Ralph +--- + ip/ipaddress.c | 16 +++---- + man/man8/ip-address.8.in | 117 +++++++++++++++++++++++++++++++++++++---------- + 2 files changed, 100 insertions(+), 33 deletions(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 1e0728c..e4da5b1 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -68,15 +68,15 @@ static void usage(void) + if (do_link) { + iplink_usage(); + } +- fprintf(stderr, "Usage: ip addr {add|change|replace} IFADDR dev STRING [ LIFETIME ]\n"); ++ fprintf(stderr, "Usage: ip address {add|change|replace} IFADDR dev IFNAME [ LIFETIME ]\n"); + fprintf(stderr, " [ CONFFLAG-LIST ]\n"); +- fprintf(stderr, " ip addr del IFADDR dev STRING [mngtmpaddr]\n"); +- fprintf(stderr, " ip addr {show|save|flush} [ dev STRING ] [ scope SCOPE-ID ]\n"); +- fprintf(stderr, " [ to PREFIX ] [ FLAG-LIST ] [ label PATTERN ] [up]\n"); +- fprintf(stderr, " ip addr {showdump|restore}\n"); ++ fprintf(stderr, " ip address del IFADDR dev IFNAME [mngtmpaddr]\n"); ++ fprintf(stderr, " ip address {show|save|flush} [ dev IFNAME ] [ scope SCOPE-ID ]\n"); ++ fprintf(stderr, " [ to PREFIX ] [ FLAG-LIST ] [ label LABEL ] [up]\n"); ++ fprintf(stderr, " ip address {showdump|restore}\n"); + fprintf(stderr, "IFADDR := PREFIX | ADDR peer PREFIX\n"); + fprintf(stderr, " [ broadcast ADDR ] [ anycast ADDR ]\n"); +- fprintf(stderr, " [ label STRING ] [ scope SCOPE-ID ]\n"); ++ fprintf(stderr, " [ label IFNAME ] [ scope SCOPE-ID ]\n"); + fprintf(stderr, "SCOPE-ID := [ host | link | global | NUMBER ]\n"); + fprintf(stderr, "FLAG-LIST := [ FLAG-LIST ] FLAG\n"); + fprintf(stderr, "FLAG := [ permanent | dynamic | secondary | primary |\n"); +@@ -968,7 +968,7 @@ static int ipadd_dump_check_magic(void) + __u32 magic = 0; + + if (isatty(STDIN_FILENO)) { +- fprintf(stderr, "Can't restore addr dump from a terminal\n"); ++ fprintf(stderr, "Can't restore address dump from a terminal\n"); + return -1; + } + +@@ -1606,6 +1606,6 @@ int do_ipaddr(int argc, char **argv) + return ipaddr_restore(); + if (matches(*argv, "help") == 0) + usage(); +- fprintf(stderr, "Command \"%s\" is unknown, try \"ip addr help\".\n", *argv); ++ fprintf(stderr, "Command \"%s\" is unknown, try \"ip address help\".\n", *argv); + exit(-1); + } +diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in +index 6e46af8..2ea3e67 100644 +--- a/man/man8/ip-address.8.in ++++ b/man/man8/ip-address.8.in +@@ -14,18 +14,26 @@ ip-address \- protocol address management + .sp + + .ti -8 +-.BR "ip address" " { " add " | " del " } " +-.IB IFADDR " dev " STRING ++.BR "ip address" " { " add " | " change " | " replace " } " ++.IB IFADDR " dev " IFNAME ++.RI "[ " LIFETIME " ] [ " CONFFLAG-LIST " ]" + + .ti -8 +-.BR "ip address" " { " show " | " flush " } [ " dev +-.IR STRING " ] [ " ++.BR "ip address del" ++.IB IFADDR " dev " IFNAME " [ " mngtmpaddr " ]" ++ ++.ti -8 ++.BR "ip address" " { " show " | " save " | " flush " } [ " dev ++.IR IFNAME " ] [ " + .B scope + .IR SCOPE-ID " ] [ " + .B to + .IR PREFIX " ] [ " FLAG-LIST " ] [ " + .B label +-.IR PATTERN " ]" ++.IR PATTERN " ] [ " up " ]" ++ ++.ti -8 ++.BR "ip address" " { " showdump " | " restore " }" + + .ti -8 + .IR IFADDR " := " PREFIX " | " ADDR +@@ -36,7 +44,7 @@ ip-address \- protocol address management + .B anycast + .IR ADDR " ] [ " + .B label +-.IR STRING " ] [ " ++.IR LABEL " ] [ " + .B scope + .IR SCOPE-ID " ]" + +@@ -52,15 +60,33 @@ ip-address \- protocol address management + .IR FLAG " := " + .RB "[ " permanent " | " dynamic " | " secondary " | " primary " | \ + [ - ] " tentative " | [ - ] " deprecated " | [ - ] " dadfailed " | "\ +-temporary " ]" ++temporary " ] " CONFFLAG-LIST " ]" ++ ++.ti -8 ++.IR CONFFLAG-LIST " := [ " CONFFLAG-LIST " ] " CONFFLAG ++ ++.ti -8 ++.IR CONFFLAG " := " ++.RB "[ " home " | " nodad " ]" ++ ++.ti -8 ++.IR LIFETIME " := [ " ++.BI valid_lft " LFT" ++.RB "| " preferred_lft ++.IR LFT " ]" ++ ++.ti -8 ++.IR LFT " := [ " ++.BR forever " |" ++.IR SECONDS " ]" + + .SH "DESCRIPTION" + The + .B address +-is a protocol (IP or IPv6) address attached +-to a network device. Each device must have at least one address +-to use the corresponding protocol. It is possible to have several +-different addresses attached to one device. These addresses are not ++is a protocol (IPv4 or IPv6) address attached ++to a network device. Each device must have at least one address ++to use the corresponding protocol. It is possible to have several ++different addresses attached to one device. These addresses are not + discriminated, so that the term + .B alias + is not quite appropriate for them and we do not use it in this document. +@@ -73,7 +99,7 @@ and deletes old ones. + .SS ip address add - add new protocol address. + + .TP +-.BI dev " NAME" ++.BI dev " IFNAME " + the name of the device to add the address to. + + .TP +@@ -107,7 +133,7 @@ instead of the broadcast address. In this case, the broadcast address + is derived by setting/resetting the host bits of the interface prefix. + + .TP +-.BI label " NAME" ++.BI label " LABEL" + Each address may be tagged with a label string. + In order to preserve compatibility with Linux-2.0 net aliases, + this string must coincide with the name of the device or must be prefixed +@@ -125,7 +151,7 @@ Predefined scope values are: + - the address is globally valid. + .sp + .B site +-- (IPv6 only) the address is site local, i.e. it is ++- (IPv6 only, deprecated) the address is site local, i.e. it is + valid inside this site. + .sp + .B link +@@ -135,6 +161,30 @@ valid inside this site. + - the address is valid only inside this host. + .in -8 + ++.TP ++.BI valid_lft " LFT" ++the valid lifetime of this address; see section 5.5.4 of ++RFC 4862. When it expires, the address is removed by the kernel. ++Defaults to ++.BR "forever" . ++ ++.TP ++.BI preferred_lft " LFT" ++the preferred lifetime of this address; see section 5.5.4 ++of RFC 4862. When it expires, the address is no longer used for new ++outgoing connections. Defaults to ++.BR "forever" . ++ ++.TP ++.B home ++(IPv6 only) designates this address the "home address" as defined in ++RFC 6275. ++ ++.TP ++.B nodad ++(IPv6 only) do not perform Duplicate Address Detection (RFC 4862) when ++adding this address. ++ + .SS ip address delete - delete protocol address + .B Arguments: + coincide with the arguments of +@@ -145,7 +195,7 @@ If no arguments are given, the first address is deleted. + .SS ip address show - look at protocol addresses + + .TP +-.BI dev " NAME " (default) ++.BI dev " IFNAME " (default) + name of device. + + .TP +@@ -219,36 +269,53 @@ The difference is that it does not run when no arguments are given. + + .PP + .B Warning: +-This command (and other ++This command and other + .B flush +-commands described below) is pretty dangerous. If you make a mistake, +-it will not forgive it, but will cruelly purge all the addresses. ++commands are unforgiving. They will cruelly purge all the addresses. + + .PP + With the + .B -statistics + option, the command becomes verbose. It prints out the number of deleted +-addresses and the number of rounds made to flush the address list. If +-this option is given twice, ++addresses and the number of rounds made to flush the address list. ++If this option is given twice, + .B ip address flush + also dumps all the deleted addresses in the format described in the + previous subsection. + + .SH "EXAMPLES" + .PP ++ip address show ++.RS 4 ++Shows IPv4 and IPv6 addresses assigned to all network interfaces. The 'show' ++subcommand can be omitted. ++.RE ++.PP ++ip address show up ++.RS 4 ++Same as above except that only addresses assigned to active network interfaces ++are shown. ++.RE ++.PP + ip address show dev eth0 + .RS 4 +-Shows the addresses assigned to network interface eth0 ++Shows IPv4 and IPv6 addresses assigned to network interface eth0. ++.RE ++.PP ++ip address add 2001:0db8:85a3::0370:7334/64 dev eth1 ++.RS 4 ++Adds an IPv6 address to network interface eth1. + .RE + .PP +-ip addr add 2001:0db8:85a3::0370:7334/64 dev eth1 ++ip address delete 2001:0db8:85a3::0370:7334/64 dev eth1 + .RS 4 +-Adds an IPv6 address to network interface eth1 ++Delete the IPv6 address added above. + .RE + .PP +-ip addr flush dev eth4 ++ip address flush dev eth4 scope global + .RS 4 +-Removes all addresses from device eth4 ++Removes all global IPv4 and IPv6 addresses from device eth4. Without 'scope ++global' it would remove all addresses including IPv6 link-local ones. + .RE + + .SH SEE ALSO +-- +1.8.3.1 + diff --git a/SOURCES/0013-ip-address.8.in-fix-BNF-syntax-error.patch b/SOURCES/0013-ip-address.8.in-fix-BNF-syntax-error.patch new file mode 100644 index 0000000..e3ea03b --- /dev/null +++ b/SOURCES/0013-ip-address.8.in-fix-BNF-syntax-error.patch @@ -0,0 +1,39 @@ +From 5461dd2bc08dc1036b655c8aa9f8acf306b092fd Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 13:21:59 +0100 +Subject: [PATCH] ip-address.8.in: fix BNF syntax error + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1231898 +Upstream Status: iproute2.git commit 715296b85a0ec + +commit 715296b85a0ecece7cdc60d42b026d66ac21a55e +Author: Phil Sutter +Date: Tue Aug 18 18:11:12 2015 +0200 + + ip-address.8.in: fix BNF syntax error + + The previous man page fixup introduced a syntax error due to missing + opening bracket, which might crash some humanoid BNF parsers. + + Fixes: 4e972d5 ("ip-address: fix and extend documentation") + Signed-off-by: Phil Sutter +--- + man/man8/ip-address.8.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in +index 2ea3e67..f1efc43 100644 +--- a/man/man8/ip-address.8.in ++++ b/man/man8/ip-address.8.in +@@ -60,7 +60,7 @@ ip-address \- protocol address management + .IR FLAG " := " + .RB "[ " permanent " | " dynamic " | " secondary " | " primary " | \ + [ - ] " tentative " | [ - ] " deprecated " | [ - ] " dadfailed " | "\ +-temporary " ] " CONFFLAG-LIST " ]" ++temporary " ] [ " CONFFLAG-LIST " ]" + + .ti -8 + .IR CONFFLAG-LIST " := [ " CONFFLAG-LIST " ] " CONFFLAG +-- +1.8.3.1 + diff --git a/SOURCES/0014-man-ip-address-align-synopsis-with-help-output.patch b/SOURCES/0014-man-ip-address-align-synopsis-with-help-output.patch new file mode 100644 index 0000000..2e95e3f --- /dev/null +++ b/SOURCES/0014-man-ip-address-align-synopsis-with-help-output.patch @@ -0,0 +1,39 @@ +From 8447b36e09fd2b4a420892267c91993e77299f4b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 13:21:59 +0100 +Subject: [PATCH] man: ip-address: align synopsis with help output + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1231898 +Upstream Status: iproute2.git commit 0b17394087a2c + +commit 0b17394087a2c1b5564353bd21eb59f468130553 +Author: Phil Sutter +Date: Fri Sep 18 20:17:00 2015 +0200 + + man: ip-address: align synopsis with help output + + When fixing the BNF syntax error, I overlooked that 'ip address help' + prints a more correct synopsis. This patch aligns them. + + Fixes: 715296b ("ip-address.8.in: fix BNF syntax error") + Signed-off-by: Phil Sutter +--- + man/man8/ip-address.8.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in +index f1efc43..43611b9 100644 +--- a/man/man8/ip-address.8.in ++++ b/man/man8/ip-address.8.in +@@ -60,7 +60,7 @@ ip-address \- protocol address management + .IR FLAG " := " + .RB "[ " permanent " | " dynamic " | " secondary " | " primary " | \ + [ - ] " tentative " | [ - ] " deprecated " | [ - ] " dadfailed " | "\ +-temporary " ] [ " CONFFLAG-LIST " ]" ++temporary " | " CONFFLAG-LIST " ]" + + .ti -8 + .IR CONFFLAG-LIST " := [ " CONFFLAG-LIST " ] " CONFFLAG +-- +1.8.3.1 + diff --git a/SOURCES/0015-man-ip-address-document-mngtmpaddr-and-noprefixroute.patch b/SOURCES/0015-man-ip-address-document-mngtmpaddr-and-noprefixroute.patch new file mode 100644 index 0000000..9e84ab8 --- /dev/null +++ b/SOURCES/0015-man-ip-address-document-mngtmpaddr-and-noprefixroute.patch @@ -0,0 +1,62 @@ +From f54df6d82b9ee4986d3746c8fe767b11d59a53eb Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 13:21:59 +0100 +Subject: [PATCH] man: ip-address: document mngtmpaddr and noprefixroute flags + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1231898 +Upstream Status: iproute2.git commit f7afa999520d3 + +commit f7afa999520d3f93114c296e37e4ccea84d2c6de +Author: Phil Sutter +Date: Fri Sep 18 20:17:03 2015 +0200 + + man: ip-address: document mngtmpaddr and noprefixroute flags + + Signed-off-by: Phil Sutter +--- + man/man8/ip-address.8.in | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in +index 43611b9..159d906 100644 +--- a/man/man8/ip-address.8.in ++++ b/man/man8/ip-address.8.in +@@ -67,7 +67,7 @@ temporary " | " CONFFLAG-LIST " ]" + + .ti -8 + .IR CONFFLAG " := " +-.RB "[ " home " | " nodad " ]" ++.RB "[ " home " | " mngtmpaddr " | " nodad " | " noprefixroute " ]" + + .ti -8 + .IR LIFETIME " := [ " +@@ -181,10 +181,26 @@ outgoing connections. Defaults to + RFC 6275. + + .TP ++.B mngtmpaddr ++(IPv6 only) make the kernel manage temporary addresses created from this one as ++template on behalf of Privacy Extensions (RFC3041). For this to become active, ++the \fBuse_tempaddr\fP sysctl setting has to be set to a value greater than ++zero. The given address needs to have a prefix length of 64. This flag allows ++to use privacy extensions in a manually configured network, just like if ++stateless auto-configuration was active. ++ ++.TP + .B nodad + (IPv6 only) do not perform Duplicate Address Detection (RFC 4862) when + adding this address. + ++.TP ++.B noprefixroute ++Do not automatically create a route for the network prefix of the added ++address, and don't search for one to delete when removing the address. Changing ++an address to add this flag will remove the automatically added prefix route, ++changing it to remove this flag will create the prefix route automatically. ++ + .SS ip address delete - delete protocol address + .B Arguments: + coincide with the arguments of +-- +1.8.3.1 + diff --git a/SOURCES/0016-ss-return-1-if-an-unrecognized-option-was-given.patch b/SOURCES/0016-ss-return-1-if-an-unrecognized-option-was-given.patch new file mode 100644 index 0000000..5a5436d --- /dev/null +++ b/SOURCES/0016-ss-return-1-if-an-unrecognized-option-was-given.patch @@ -0,0 +1,40 @@ +From c74eb4b7e9ca7cade47d0c3b23876cc6527b8774 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 13:33:36 +0100 +Subject: [PATCH] ss: return -1 if an unrecognized option was given + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1265238 +Upstream Status: iproute2.git commit f73105ab42795 + +commit f73105ab42795422f131fb711712e3c860df982f +Author: Phil Sutter +Date: Thu Oct 15 21:01:16 2015 +0200 + + ss: return -1 if an unrecognized option was given + + When getopt_long encounters an option which has not been registered, it + returns '?'. React upon that and call usage() instead of help() so ss + returns with a non-zero exit status. + + Signed-off-by: Phil Sutter +--- + misc/ss.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/misc/ss.c b/misc/ss.c +index fd9a1f9..b9b2081 100644 +--- a/misc/ss.c ++++ b/misc/ss.c +@@ -3605,8 +3605,8 @@ int main(int argc, char *argv[]) + exit(1); + break; + case 'h': +- case '?': + help(); ++ case '?': + default: + usage(); + } +-- +1.8.3.1 + diff --git a/SOURCES/0017-ss-add-support-for-bytes_acked-bytes_received.patch b/SOURCES/0017-ss-add-support-for-bytes_acked-bytes_received.patch new file mode 100644 index 0000000..0aed83b --- /dev/null +++ b/SOURCES/0017-ss-add-support-for-bytes_acked-bytes_received.patch @@ -0,0 +1,65 @@ +From a4f7690739cb14ef83adfccebf32a628c9718ce0 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 13:36:34 +0100 +Subject: [PATCH] ss: add support for bytes_acked & bytes_received + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269114 +Upstream Status: iproute2.git commit 1a4dda7103bcd + +commit 1a4dda7103bcd5efcca72ffe03eef43318897dae +Author: Eric Dumazet +Date: Mon May 11 10:03:49 2015 -0700 + + ss: add support for bytes_acked & bytes_received + + tcp_info has 2 new fields : bytes_acked & bytes_received + + $ ss -ti src :22 + ... + cubic wscale:7,6 rto:234 rtt:33.199/17.225 ato:17.225 mss:1418 cwnd:9 + ssthresh:9 send 3.1Mbps lastsnd:3 lastrcv:4 lastack:193 + bytes_acked:188396 bytes_received:13639 pacing_rate 6.2Mbps unacked:1 + retrans:0/4 reordering:4 rcv_rtt:47.25 rcv_space:28960 + + Signed-off-by: Eric Dumazet +--- + misc/ss.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/misc/ss.c b/misc/ss.c +index b9b2081..b1e8a8c 100644 +--- a/misc/ss.c ++++ b/misc/ss.c +@@ -761,6 +761,8 @@ struct tcpstat + unsigned int lastack; + double pacing_rate; + double pacing_rate_max; ++ unsigned long long bytes_acked; ++ unsigned long long bytes_received; + unsigned int unacked; + unsigned int retrans; + unsigned int retrans_total; +@@ -1683,6 +1685,11 @@ static void tcp_stats_print(struct tcpstat *s) + if (s->ssthresh) + printf(" ssthresh:%d", s->ssthresh); + ++ if (s->bytes_acked) ++ printf(" bytes_acked:%llu", s->bytes_acked); ++ if (s->bytes_received) ++ printf(" bytes_received:%llu", s->bytes_received); ++ + if (s->dctcp && s->dctcp->enabled) { + struct dctcpstat *dctcp = s->dctcp; + +@@ -1974,6 +1981,8 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, + info->tcpi_max_pacing_rate != ~0ULL) + s.pacing_rate_max = info->tcpi_max_pacing_rate * 8.; + } ++ s.bytes_acked = info->tcpi_bytes_acked; ++ s.bytes_received = info->tcpi_bytes_received; + tcp_stats_print(&s); + if (s.dctcp) + free(s.dctcp); +-- +1.8.3.1 + diff --git a/SOURCES/0018-ss-add-support-for-segs_in-and-segs_out.patch b/SOURCES/0018-ss-add-support-for-segs_in-and-segs_out.patch new file mode 100644 index 0000000..20e882c --- /dev/null +++ b/SOURCES/0018-ss-add-support-for-segs_in-and-segs_out.patch @@ -0,0 +1,62 @@ +From bf3cb083a64373edcad8ef43fe1fdf7ebdd27cb4 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 13:36:34 +0100 +Subject: [PATCH] ss: add support for segs_in and segs_out + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269114 +Upstream Status: iproute2.git commit ecb435eacd501 + +commit ecb435eacd50161d2a7cce5731a269ef916c0dd4 +Author: Craig Gallek +Date: Tue May 26 14:54:41 2015 -0400 + + ss: add support for segs_in and segs_out + + Two new tcp_info fields: tcpi_segs_in and tcpi_segs_out. + (2efd055c53c06b7e89c167c98069bab9afce7e59) + + ~: ss -ti src :22 + cubic wscale:7,6 rto:201 rtt:0.244/0.012 ato:40 mss:1418 cwnd:21 bytes_acked:80605 bytes_received:20491 segs_out:414 segs_in:600 send 976.3Mbps lastsnd:23 lastrcv:23 lastack:22 pacing_rate 1952.7Mbps rcv_rtt:98 rcv_space:28960 + + Signed-off-by: Craig Gallek + Reviewed-by: Marcelo Ricardo Leitner +--- + misc/ss.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/misc/ss.c b/misc/ss.c +index b1e8a8c..7750887 100644 +--- a/misc/ss.c ++++ b/misc/ss.c +@@ -763,6 +763,8 @@ struct tcpstat + double pacing_rate_max; + unsigned long long bytes_acked; + unsigned long long bytes_received; ++ unsigned int segs_out; ++ unsigned int segs_in; + unsigned int unacked; + unsigned int retrans; + unsigned int retrans_total; +@@ -1689,6 +1691,10 @@ static void tcp_stats_print(struct tcpstat *s) + printf(" bytes_acked:%llu", s->bytes_acked); + if (s->bytes_received) + printf(" bytes_received:%llu", s->bytes_received); ++ if (s->segs_out) ++ printf(" segs_out:%u", s->segs_out); ++ if (s->segs_in) ++ printf(" segs_in:%u", s->segs_in); + + if (s->dctcp && s->dctcp->enabled) { + struct dctcpstat *dctcp = s->dctcp; +@@ -1983,6 +1989,8 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, + } + s.bytes_acked = info->tcpi_bytes_acked; + s.bytes_received = info->tcpi_bytes_received; ++ s.segs_out = info->tcpi_segs_out; ++ s.segs_in = info->tcpi_segs_in; + tcp_stats_print(&s); + if (s.dctcp) + free(s.dctcp); +-- +1.8.3.1 + diff --git a/SOURCES/0019-ip-address-fix-oneline-mode-for-interfaces-with-VF.patch b/SOURCES/0019-ip-address-fix-oneline-mode-for-interfaces-with-VF.patch new file mode 100644 index 0000000..dfdc31b --- /dev/null +++ b/SOURCES/0019-ip-address-fix-oneline-mode-for-interfaces-with-VF.patch @@ -0,0 +1,35 @@ +From 266d5bfc819457371abd69309fae4c16b776fef1 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 13:37:23 +0100 +Subject: [PATCH] ip-address: fix oneline mode for interfaces with VF + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1272405 +Upstream Status: iproute2.git commit 6f07f3dc41545 + +commit 6f07f3dc41545657c0364eb17850b946f41861bf +Author: Phil Sutter +Date: Fri Oct 16 12:38:33 2015 +0200 + + ip-address: fix oneline mode for interfaces with VF + + Signed-off-by: Phil Sutter +--- + ip/ipaddress.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index e4da5b1..07242d3 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -294,7 +294,7 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo) + } else + vf_linkstate = NULL; + +- fprintf(fp, "\n vf %d MAC %s", vf_mac->vf, ++ fprintf(fp, "%s vf %d MAC %s", _SL_, vf_mac->vf, + ll_addr_n2a((unsigned char *)&vf_mac->mac, + ETH_ALEN, 0, b1, sizeof(b1))); + if (vf_vlan->vlan) +-- +1.8.3.1 + diff --git a/SOURCES/0020-neighbor-check-return-values.patch b/SOURCES/0020-neighbor-check-return-values.patch new file mode 100644 index 0000000..f392994 --- /dev/null +++ b/SOURCES/0020-neighbor-check-return-values.patch @@ -0,0 +1,49 @@ +From e12035a23d3f12154f4d4034ee88157b86f3b5e3 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 13:38:12 +0100 +Subject: [PATCH] neighbor: check return values + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1277094 +Upstream Status: iproute2.git commit 542b0cc759c6d + +commit 542b0cc759c6d3456d16c05c886b367e1b2f1e73 +Author: Stephen Hemminger +Date: Tue Jan 13 18:06:16 2015 -0800 + + neighbor: check return values + + Need to check for invalid address and buffer overrun in ip neigh + command with invalid paramters. +--- + ip/ipneigh.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/ip/ipneigh.c b/ip/ipneigh.c +index 71a4100..c47f005 100644 +--- a/ip/ipneigh.c ++++ b/ip/ipneigh.c +@@ -157,14 +157,19 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv) + exit(-1); + } + req.ndm.ndm_family = dst.family; +- addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen); ++ if (addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen) < 0) ++ return -1; + + if (lla && strcmp(lla, "null")) { + char llabuf[20]; + int l; + + l = ll_addr_a2n(llabuf, sizeof(llabuf), lla); +- addattr_l(&req.n, sizeof(req), NDA_LLADDR, llabuf, l); ++ if (l < 0) ++ return -1; ++ ++ if (addattr_l(&req.n, sizeof(req), NDA_LLADDR, llabuf, l) < 0) ++ return -1; + } + + ll_init_map(&rth); +-- +1.8.3.1 + diff --git a/SOURCES/0021-gre-raising-the-size-of-the-buffer-holding-nl-messag.patch b/SOURCES/0021-gre-raising-the-size-of-the-buffer-holding-nl-messag.patch new file mode 100644 index 0000000..e9095f3 --- /dev/null +++ b/SOURCES/0021-gre-raising-the-size-of-the-buffer-holding-nl-messag.patch @@ -0,0 +1,36 @@ +From bfc39db4ab381162c4be2d7e3de8d315d0445082 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:03:47 +0100 +Subject: [PATCH] gre: raising the size of the buffer holding nl messages. + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 +Upstream Status: iproute2.git commit bde5baa5476cd + +commit bde5baa5476cd8d7d33afc42170dc984f3717e14 +Author: Jetchko Jekov +Date: Thu May 21 16:32:24 2015 +0200 + + gre: raising the size of the buffer holding nl messages. + + Now it matches the size for the answer defined in rtnl_talk() + and prevents stack corruption with answer > 1024 bytes. +--- + ip/link_gre.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/link_gre.c b/ip/link_gre.c +index 83653d0..ddbd6cc 100644 +--- a/ip/link_gre.c ++++ b/ip/link_gre.c +@@ -50,7 +50,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, + struct { + struct nlmsghdr n; + struct ifinfomsg i; +- char buf[1024]; ++ char buf[16384]; + } req; + struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); + struct rtattr *tb[IFLA_MAX + 1]; +-- +1.8.3.1 + diff --git a/SOURCES/0022-Allow-specifying-bridge-port-STP-state-by-name-rathe.patch b/SOURCES/0022-Allow-specifying-bridge-port-STP-state-by-name-rathe.patch new file mode 100644 index 0000000..4b48bf5 --- /dev/null +++ b/SOURCES/0022-Allow-specifying-bridge-port-STP-state-by-name-rathe.patch @@ -0,0 +1,77 @@ +From a5087426d103b65fcfd85dc0f71c5bedc3a23148 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:04:01 +0100 +Subject: [PATCH] Allow specifying bridge port STP state by name rather than + number. + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 +Upstream Status: iproute2.git commit 6b8c871dc1045 +Conflicts: Whitespace change due to already applied commit + a89d5329d414c ("docs: make spacing consistent") + +commit 6b8c871dc104576c9f55d87937d6dd445d77f34f +Author: Alex Pilon +Date: Thu Feb 19 14:27:46 2015 -0500 + + Allow specifying bridge port STP state by name rather than number. + + The existing behaviour forces one to memorize the integer constants for + STP port states. + + # bridge link set dev dummy0 state 3 + + This patch makes it possible to use the lowercased port state name. + + # bridge link set dev dummy0 state forwarding + + Invalid non-integer inputs now cause exit with status -1. + + Signed-off-by: Alex Pilon +--- + bridge/link.c | 14 +++++++++++++- + man/man8/bridge.8 | 4 +++- + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/bridge/link.c b/bridge/link.c +index 38dfaea..48be938 100644 +--- a/bridge/link.c ++++ b/bridge/link.c +@@ -289,7 +289,19 @@ static int brlink_modify(int argc, char **argv) + priority = atoi(*argv); + } else if (strcmp(*argv, "state") == 0) { + NEXT_ARG(); +- state = atoi(*argv); ++ char *endptr; ++ size_t nstates = sizeof(port_states) / sizeof(*port_states); ++ state = strtol(*argv, &endptr, 10); ++ if (!(**argv != '\0' && *endptr == '\0')) { ++ for (state = 0; state < nstates; state++) ++ if (strcmp(port_states[state], *argv) == 0) ++ break; ++ if (state == nstates) { ++ fprintf(stderr, ++ "Error: invalid STP port state\n"); ++ exit(-1); ++ } ++ } + } else if (strcmp(*argv, "hwmode") == 0) { + NEXT_ARG(); + flags = BRIDGE_FLAGS_SELF; +diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 +index 68a86e5..2c9f90c 100644 +--- a/man/man8/bridge.8 ++++ b/man/man8/bridge.8 +@@ -204,7 +204,9 @@ droot port selectio algorithms. + .TP + .BI state " STATE " + the operation state of the port. This is primarily used by user space STP/RSTP +-implementation. The following is a list of valid values: ++implementation. One may enter a lowercased port state name, or one of the ++numbers below. Negative inputs are ignored, and unrecognized names return an ++error. + + .B 0 + - port is DISABLED. Make this port completely inactive. +-- +1.8.3.1 + diff --git a/SOURCES/0023-fix-ip-force-batch-to-continue-on-errors.patch b/SOURCES/0023-fix-ip-force-batch-to-continue-on-errors.patch new file mode 100644 index 0000000..cb459f6 --- /dev/null +++ b/SOURCES/0023-fix-ip-force-batch-to-continue-on-errors.patch @@ -0,0 +1,220 @@ +From 03f8f5811ebc0f8fac1c3ccb76c14007d250bd38 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:05:04 +0100 +Subject: [PATCH] fix ip -force -batch to continue on errors + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 +Upstream Status: iproute2.git commit 42ecedd4bae53 +Conflicts: Context changed due to missing other commits adding policy + flags (e.g. learning_sync). + +commit 42ecedd4bae534fc688194a795eb4548c6530cda +Author: Roopa Prabhu +Date: Tue Mar 17 19:26:32 2015 -0700 + + fix ip -force -batch to continue on errors + + This patch replaces exits with returns in several + iproute2 commands. This fixes `ip -batch -force` + to not exit but continue on errors. + + $cat c.txt + route del 1.2.3.0/24 dev eth0 + route del 1.2.4.0/24 dev eth0 + route del 1.2.5.0/24 dev eth0 + route add 1.2.3.0/24 dev eth0 + + $ip -force -batch c.txt + RTNETLINK answers: No such process + Command failed c.txt:2 + RTNETLINK answers: No such process + Command failed c.txt:3 + + Reported-by: Sven-Haegar Koch + Signed-off-by: Roopa Prabhu +--- + bridge/fdb.c | 6 +++--- + bridge/link.c | 18 +++++++++--------- + bridge/mdb.c | 8 ++++---- + bridge/vlan.c | 4 ++-- + ip/iproute.c | 2 +- + 5 files changed, 19 insertions(+), 19 deletions(-) + +diff --git a/bridge/fdb.c b/bridge/fdb.c +index 513b3f9..b8138cb 100644 +--- a/bridge/fdb.c ++++ b/bridge/fdb.c +@@ -287,7 +287,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv) + + if (d == NULL || addr == NULL) { + fprintf(stderr, "Device and address are required arguments.\n"); +- exit(-1); ++ return -1; + } + + /* Assume self */ +@@ -302,7 +302,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv) + abuf, abuf+1, abuf+2, + abuf+3, abuf+4, abuf+5) != 6) { + fprintf(stderr, "Invalid mac address %s\n", addr); +- exit(-1); ++ return -1; + } + + addattr_l(&req.n, sizeof(req), NDA_LLADDR, abuf, ETH_ALEN); +@@ -330,7 +330,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv) + } + + if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) +- exit(2); ++ return -1; + + return 0; + } +diff --git a/bridge/link.c b/bridge/link.c +index 48be938..c5e7ae5 100644 +--- a/bridge/link.c ++++ b/bridge/link.c +@@ -268,19 +268,19 @@ static int brlink_modify(int argc, char **argv) + } else if (strcmp(*argv, "guard") == 0) { + NEXT_ARG(); + if (!on_off("guard", &bpdu_guard, *argv)) +- exit(-1); ++ return -1; + } else if (strcmp(*argv, "hairpin") == 0) { + NEXT_ARG(); + if (!on_off("hairping", &hairpin, *argv)) +- exit(-1); ++ return -1; + } else if (strcmp(*argv, "fastleave") == 0) { + NEXT_ARG(); + if (!on_off("fastleave", &fast_leave, *argv)) +- exit(-1); ++ return -1; + } else if (strcmp(*argv, "root_block") == 0) { + NEXT_ARG(); + if (!on_off("root_block", &root_block, *argv)) +- exit(-1); ++ return -1; + } else if (strcmp(*argv, "cost") == 0) { + NEXT_ARG(); + cost = atoi(*argv); +@@ -299,7 +299,7 @@ static int brlink_modify(int argc, char **argv) + if (state == nstates) { + fprintf(stderr, + "Error: invalid STP port state\n"); +- exit(-1); ++ return -1; + } + } + } else if (strcmp(*argv, "hwmode") == 0) { +@@ -313,7 +313,7 @@ static int brlink_modify(int argc, char **argv) + fprintf(stderr, + "Mode argument must be \"vepa\" or " + "\"veb\".\n"); +- exit(-1); ++ return -1; + } + } else { + usage(); +@@ -322,14 +322,14 @@ static int brlink_modify(int argc, char **argv) + } + if (d == NULL) { + fprintf(stderr, "Device is a required argument.\n"); +- exit(-1); ++ return -1; + } + + + req.ifm.ifi_index = ll_name_to_index(d); + if (req.ifm.ifi_index == 0) { + fprintf(stderr, "Cannot find bridge device \"%s\"\n", d); +- exit(-1); ++ return -1; + } + + /* Nested PROTINFO attribute. Contains: port flags, cost, priority and +@@ -377,7 +377,7 @@ static int brlink_modify(int argc, char **argv) + } + + if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) +- exit(2); ++ return -1; + + return 0; + } +diff --git a/bridge/mdb.c b/bridge/mdb.c +index 81d479b..ab3a792 100644 +--- a/bridge/mdb.c ++++ b/bridge/mdb.c +@@ -145,12 +145,12 @@ static int mdb_show(int argc, char **argv) + + if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETMDB) < 0) { + perror("Cannot send dump request"); +- exit(1); ++ return -1; + } + + if (rtnl_dump_filter(&rth, print_mdb, stdout) < 0) { + fprintf(stderr, "Dump terminated\n"); +- exit(1); ++ return -1; + } + + return 0; +@@ -198,7 +198,7 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv) + + if (d == NULL || grp == NULL || p == NULL) { + fprintf(stderr, "Device, group address and port name are required arguments.\n"); +- exit(-1); ++ return -1; + } + + req.bpm.ifindex = ll_name_to_index(d); +@@ -225,7 +225,7 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv) + addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry)); + + if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) +- exit(2); ++ return -1; + + return 0; + } +diff --git a/bridge/vlan.c b/bridge/vlan.c +index 83c4088..ba54b0e 100644 +--- a/bridge/vlan.c ++++ b/bridge/vlan.c +@@ -69,7 +69,7 @@ static int vlan_modify(int cmd, int argc, char **argv) + + if (d == NULL || vid == -1) { + fprintf(stderr, "Device and VLAN ID are required arguments.\n"); +- exit(-1); ++ return -1; + } + + req.ifm.ifi_index = ll_name_to_index(d); +@@ -96,7 +96,7 @@ static int vlan_modify(int cmd, int argc, char **argv) + addattr_nest_end(&req.n, afspec); + + if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) +- exit(2); ++ return -1; + + return 0; + } +diff --git a/ip/iproute.c b/ip/iproute.c +index 586039d..fbe5268 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -1030,7 +1030,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) + req.r.rtm_family = AF_INET; + + if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) +- exit(2); ++ return -1; + + return 0; + } +-- +1.8.3.1 + diff --git a/SOURCES/0024-ip-fix-exit-code-for-addrlabel.patch b/SOURCES/0024-ip-fix-exit-code-for-addrlabel.patch new file mode 100644 index 0000000..6839365 --- /dev/null +++ b/SOURCES/0024-ip-fix-exit-code-for-addrlabel.patch @@ -0,0 +1,52 @@ +From 205034e561dbc0e1fa380970130b28188870c265 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:05:42 +0100 +Subject: [PATCH] ip: fix exit code for addrlabel + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 +Upstream Status: iproute2.git commit 906cafe3ff7a3 + +commit 906cafe3ff7a3e285e59f95e7b58c91610d5d16f +Author: Stephen Hemminger +Date: Wed May 6 09:55:07 2015 -0700 + + ip: fix exit code for addrlabel + + The exit code for ip label was not correct. + The return from the command function is negated and turned into + the exit code on failure. +--- + ip/ipaddrlabel.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c +index 8a4afbc..5b1f6e4 100644 +--- a/ip/ipaddrlabel.c ++++ b/ip/ipaddrlabel.c +@@ -184,7 +184,7 @@ static int ipaddrlabel_modify(int cmd, int argc, char **argv) + req.ifal.ifal_family = AF_INET6; + + if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) +- return 2; ++ return -2; + + return 0; + } +@@ -233,12 +233,12 @@ static int ipaddrlabel_flush(int argc, char **argv) + + if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) { + perror("Cannot send dump request"); +- return 1; ++ return -1; + } + + if (rtnl_dump_filter(&rth, flush_addrlabel, NULL) < 0) { + fprintf(stderr, "Flush terminated\n"); +- return 1; ++ return -1; + } + + return 0; +-- +1.8.3.1 + diff --git a/SOURCES/0025-Consolidated-tunnel-support-fixes-for-ip6-gre-and-ip.patch b/SOURCES/0025-Consolidated-tunnel-support-fixes-for-ip6-gre-and-ip.patch deleted file mode 100644 index cac6882..0000000 --- a/SOURCES/0025-Consolidated-tunnel-support-fixes-for-ip6-gre-and-ip.patch +++ /dev/null @@ -1,1067 +0,0 @@ -From 0148deddeee0682884fe95b2ee4f58790498bf0a Mon Sep 17 00:00:00 2001 -From: Phil Sutter -Date: Mon, 3 Aug 2015 09:38:43 -0400 -Subject: [PATCH] Consolidated tunnel support/fixes for ip6/gre and ip6_vti - -The original patches are: -- iproute2: GRE over IPv6 tunnel support. -- Whitespace and indentation cleanup -- iproute2: Add support for IPv6 VTI tunnels to ip6tunnel -- ip tunnel: fix 'ip -oneline tunnel show' for some GRE tunnels -- iproute2: ip6_tunnel mode bugfixes: any,vti6 -- iproute2: VTI6 support for ip -6 link command. - -Conflicts: - ip/ipaddress.c -- due to previous backport of 07fa9c1529 ("Add VF link state control") -- and missing 30b55792 ("iproute2: show counter of carrier on<->off transitions") ---- - ip/Makefile | 5 +- - ip/ip6tunnel.c | 138 ++++++++++++++++---- - ip/iplink.c | 19 ++- - ip/iptunnel.c | 2 +- - ip/link_gre6.c | 398 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - ip/link_vti6.c | 250 ++++++++++++++++++++++++++++++++++++ - 6 files changed, 776 insertions(+), 36 deletions(-) - create mode 100644 ip/link_gre6.c - create mode 100644 ip/link_vti6.c - -diff --git a/ip/Makefile b/ip/Makefile -index 48bd4a1..f377c37 100644 ---- a/ip/Makefile -+++ b/ip/Makefile -@@ -3,9 +3,9 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ - ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o iptoken.o \ - ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \ - iplink_vlan.o link_veth.o link_gre.o iplink_can.o \ -- iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \ -+ iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o link_vti6.o \ - iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \ -- link_iptnl.o -+ link_iptnl.o link_gre6.o - - RTMONOBJ=rtmon.o - -@@ -23,7 +23,6 @@ all: $(TARGETS) $(SCRIPTS) - - ip: $(IPOBJ) $(LIBNETLINK) - -- - rtmon: $(RTMONOBJ) - - install: all -diff --git a/ip/ip6tunnel.c b/ip/ip6tunnel.c -index 216e982..f37042e 100644 ---- a/ip/ip6tunnel.c -+++ b/ip/ip6tunnel.c -@@ -48,11 +48,12 @@ static void usage(void) __attribute__((noreturn)); - static void usage(void) - { - fprintf(stderr, "Usage: ip -f inet6 tunnel { add | change | del | show } [ NAME ]\n"); -- fprintf(stderr, " [ mode { ip6ip6 | ipip6 | any } ]\n"); -+ fprintf(stderr, " [ mode { ip6ip6 | ipip6 | ip6gre | vti6 | any } ]\n"); - fprintf(stderr, " [ remote ADDR local ADDR ] [ dev PHYS_DEV ]\n"); - fprintf(stderr, " [ encaplimit ELIM ]\n"); - fprintf(stderr ," [ hoplimit TTL ] [ tclass TCLASS ] [ flowlabel FLOWLABEL ]\n"); - fprintf(stderr, " [ dscp inherit ]\n"); -+ fprintf(stderr, " [ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "Where: NAME := STRING\n"); - fprintf(stderr, " ADDR := IPV6_ADDRESS\n"); -@@ -62,10 +63,11 @@ static void usage(void) - DEFAULT_TNL_HOP_LIMIT); - fprintf(stderr, " TCLASS := { 0x0..0xff | inherit }\n"); - fprintf(stderr, " FLOWLABEL := { 0x0..0xfffff | inherit }\n"); -+ fprintf(stderr, " KEY := { DOTTED_QUAD | NUMBER }\n"); - exit(-1); - } - --static void print_tunnel(struct ip6_tnl_parm *p) -+static void print_tunnel(struct ip6_tnl_parm2 *p) - { - char remote[64]; - char local[64]; -@@ -104,9 +106,29 @@ static void print_tunnel(struct ip6_tnl_parm *p) - - if (p->flags & IP6_TNL_F_RCV_DSCP_COPY) - printf(" dscp inherit"); -+ -+ if (p->proto == IPPROTO_GRE) { -+ if ((p->i_flags&GRE_KEY) && (p->o_flags&GRE_KEY) && p->o_key == p->i_key) -+ printf(" key %u", ntohl(p->i_key)); -+ else if ((p->i_flags|p->o_flags)&GRE_KEY) { -+ if (p->i_flags&GRE_KEY) -+ printf(" ikey %u ", ntohl(p->i_key)); -+ if (p->o_flags&GRE_KEY) -+ printf(" okey %u ", ntohl(p->o_key)); -+ } -+ -+ if (p->i_flags&GRE_SEQ) -+ printf("%s Drop packets out of sequence.", _SL_); -+ if (p->i_flags&GRE_CSUM) -+ printf("%s Checksum in received packet is required.", _SL_); -+ if (p->o_flags&GRE_SEQ) -+ printf("%s Sequence packets on output.", _SL_); -+ if (p->o_flags&GRE_CSUM) -+ printf("%s Checksum output packets.", _SL_); -+ } - } - --static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm *p) -+static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm2 *p) - { - int count = 0; - char medium[IFNAMSIZ]; -@@ -119,19 +141,25 @@ static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm *p) - if (strcmp(*argv, "ipv6/ipv6") == 0 || - strcmp(*argv, "ip6ip6") == 0) - p->proto = IPPROTO_IPV6; -- else if (strcmp(*argv, "ip/ipv6") == 0 || -+ else if (strcmp(*argv, "vti6") == 0) { -+ p->proto = IPPROTO_IPV6; -+ p->i_flags |= VTI_ISVTI; -+ } else if (strcmp(*argv, "ip/ipv6") == 0 || - strcmp(*argv, "ipv4/ipv6") == 0 || - strcmp(*argv, "ipip6") == 0 || - strcmp(*argv, "ip4ip6") == 0) - p->proto = IPPROTO_IPIP; -+ else if (strcmp(*argv, "ip6gre") == 0 || -+ strcmp(*argv, "gre/ipv6") == 0) -+ p->proto = IPPROTO_GRE; - else if (strcmp(*argv, "any/ipv6") == 0 || - strcmp(*argv, "any") == 0) - p->proto = 0; - else { -- fprintf(stderr,"Unknown tunnel mode \"%s\"\n", *argv); -- exit(-1); -- } -- } else if (strcmp(*argv, "remote") == 0) { -+ fprintf(stderr,"Unknown tunnel mode \"%s\"\n", *argv); -+ exit(-1); -+ } -+ } else if (strcmp(*argv, "remote") == 0) { - inet_prefix raddr; - NEXT_ARG(); - get_prefix(&raddr, *argv, preferred_family); -@@ -202,6 +230,60 @@ static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm *p) - if (strcmp(*argv, "inherit") != 0) - invarg("not inherit", *argv); - p->flags |= IP6_TNL_F_RCV_DSCP_COPY; -+ } else if (strcmp(*argv, "key") == 0) { -+ unsigned uval; -+ NEXT_ARG(); -+ p->i_flags |= GRE_KEY; -+ p->o_flags |= GRE_KEY; -+ if (strchr(*argv, '.')) -+ p->i_key = p->o_key = get_addr32(*argv); -+ else { -+ if (get_unsigned(&uval, *argv, 0) < 0) { -+ fprintf(stderr, "invalid value of \"key\"\n"); -+ exit(-1); -+ } -+ p->i_key = p->o_key = htonl(uval); -+ } -+ } else if (strcmp(*argv, "ikey") == 0) { -+ unsigned uval; -+ NEXT_ARG(); -+ p->i_flags |= GRE_KEY; -+ if (strchr(*argv, '.')) -+ p->i_key = get_addr32(*argv); -+ else { -+ if (get_unsigned(&uval, *argv, 0)<0) { -+ fprintf(stderr, "invalid value of \"ikey\"\n"); -+ exit(-1); -+ } -+ p->i_key = htonl(uval); -+ } -+ } else if (strcmp(*argv, "okey") == 0) { -+ unsigned uval; -+ NEXT_ARG(); -+ p->o_flags |= GRE_KEY; -+ if (strchr(*argv, '.')) -+ p->o_key = get_addr32(*argv); -+ else { -+ if (get_unsigned(&uval, *argv, 0)<0) { -+ fprintf(stderr, "invalid value of \"okey\"\n"); -+ exit(-1); -+ } -+ p->o_key = htonl(uval); -+ } -+ } else if (strcmp(*argv, "seq") == 0) { -+ p->i_flags |= GRE_SEQ; -+ p->o_flags |= GRE_SEQ; -+ } else if (strcmp(*argv, "iseq") == 0) { -+ p->i_flags |= GRE_SEQ; -+ } else if (strcmp(*argv, "oseq") == 0) { -+ p->o_flags |= GRE_SEQ; -+ } else if (strcmp(*argv, "csum") == 0) { -+ p->i_flags |= GRE_CSUM; -+ p->o_flags |= GRE_CSUM; -+ } else if (strcmp(*argv, "icsum") == 0) { -+ p->i_flags |= GRE_CSUM; -+ } else if (strcmp(*argv, "ocsum") == 0) { -+ p->o_flags |= GRE_CSUM; - } else { - if (strcmp(*argv, "name") == 0) { - NEXT_ARG(); -@@ -212,7 +294,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm *p) - duparg2("name", *argv); - strncpy(p->name, *argv, IFNAMSIZ - 1); - if (cmd == SIOCCHGTUNNEL && count == 0) { -- struct ip6_tnl_parm old_p; -+ struct ip6_tnl_parm2 old_p; - memset(&old_p, 0, sizeof(old_p)); - if (tnl_get_ioctl(*argv, &old_p)) - return -1; -@@ -230,7 +312,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm *p) - return 0; - } - --static void ip6_tnl_parm_init(struct ip6_tnl_parm *p, int apply_default) -+static void ip6_tnl_parm_init(struct ip6_tnl_parm2 *p, int apply_default) - { - memset(p, 0, sizeof(*p)); - p->proto = IPPROTO_IPV6; -@@ -244,8 +326,8 @@ static void ip6_tnl_parm_init(struct ip6_tnl_parm *p, int apply_default) - * @p1: user specified parameter - * @p2: database entry - */ --static int ip6_tnl_parm_match(const struct ip6_tnl_parm *p1, -- const struct ip6_tnl_parm *p2) -+static int ip6_tnl_parm_match(const struct ip6_tnl_parm2 *p1, -+ const struct ip6_tnl_parm2 *p2) - { - return ((!p1->link || p1->link == p2->link) && - (!p1->name[0] || strcmp(p1->name, p2->name) == 0) && -@@ -263,7 +345,7 @@ static int ip6_tnl_parm_match(const struct ip6_tnl_parm *p1, - (!p1->flags || (p1->flags & p2->flags))); - } - --static int do_tunnels_list(struct ip6_tnl_parm *p) -+static int do_tunnels_list(struct ip6_tnl_parm2 *p) - { - char buf[512]; - int err = -1; -@@ -287,7 +369,7 @@ static int do_tunnels_list(struct ip6_tnl_parm *p) - rx_fifo, rx_frame, - tx_bytes, tx_packets, tx_errs, tx_drops, - tx_fifo, tx_colls, tx_carrier, rx_multi; -- struct ip6_tnl_parm p1; -+ struct ip6_tnl_parm2 p1; - char *ptr; - - buf[sizeof(buf) - 1] = '\0'; -@@ -312,10 +394,12 @@ static int do_tunnels_list(struct ip6_tnl_parm *p) - fprintf(stderr, "Failed to get type of \"%s\"\n", name); - continue; - } -- if (type != ARPHRD_TUNNEL6) -+ if (type != ARPHRD_TUNNEL6 && type != ARPHRD_IP6GRE) - continue; - memset(&p1, 0, sizeof(p1)); - ip6_tnl_parm_init(&p1, 0); -+ if (type == ARPHRD_IP6GRE) -+ p1.proto = IPPROTO_GRE; - strcpy(p1.name, name); - p1.link = ll_name_to_index(p1.name); - if (p1.link == 0) -@@ -346,7 +430,7 @@ static int do_tunnels_list(struct ip6_tnl_parm *p) - - static int do_show(int argc, char **argv) - { -- struct ip6_tnl_parm p; -+ struct ip6_tnl_parm2 p; - - ll_init_map(&rth); - ip6_tnl_parm_init(&p, 0); -@@ -369,28 +453,38 @@ static int do_show(int argc, char **argv) - - static int do_add(int cmd, int argc, char **argv) - { -- struct ip6_tnl_parm p; -+ struct ip6_tnl_parm2 p; -+ const char *basedev = "ip6tnl0"; - - ip6_tnl_parm_init(&p, 1); - - if (parse_args(argc, argv, cmd, &p) < 0) - return -1; - -- return tnl_add_ioctl(cmd, -- cmd == SIOCCHGTUNNEL && p.name[0] ? -- p.name : "ip6tnl0", p.name, &p); -+ if (p.proto == IPPROTO_GRE) -+ basedev = "ip6gre0"; -+ else if (p.i_flags & VTI_ISVTI) -+ basedev = "ip6_vti0"; -+ -+ return tnl_add_ioctl(cmd, basedev, p.name, &p); - } - - static int do_del(int argc, char **argv) - { -- struct ip6_tnl_parm p; -+ struct ip6_tnl_parm2 p; -+ const char *basedev = "ip6tnl0"; - - ip6_tnl_parm_init(&p, 1); - - if (parse_args(argc, argv, SIOCDELTUNNEL, &p) < 0) - return -1; - -- return tnl_del_ioctl(p.name[0] ? p.name : "ip6tnl0", p.name, &p); -+ if (p.proto == IPPROTO_GRE) -+ basedev = "ip6gre0"; -+ else if (p.i_flags & VTI_ISVTI) -+ basedev = "ip6_vti0"; -+ -+ return tnl_del_ioctl(basedev, p.name, &p); - } - - int do_ip6tunnel(int argc, char **argv) -diff --git a/ip/iplink.c b/ip/iplink.c -index dc98019..deef14b 100644 ---- a/ip/iplink.c -+++ b/ip/iplink.c -@@ -84,7 +84,8 @@ void iplink_usage(void) - if (iplink_have_newlink()) { - fprintf(stderr, "\n"); - fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |\n"); -- fprintf(stderr, " bridge | ipoib | ip6tnl | ipip | sit | vxlan }\n"); -+ fprintf(stderr, " bridge | ipoib | ip6tnl | ipip | sit | vxlan |\n"); -+ fprintf(stderr, " gre | gretap | ip6gre | ip6gretap }\n"); - } - exit(-1); - } -@@ -242,7 +243,7 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, - } - ivt.vf = vf; - addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE, &ivt, sizeof(ivt)); -- -+ - } else if (matches(*argv, "spoofchk") == 0) { - struct ifla_vf_spoofchk ivs; - NEXT_ARG(); -@@ -272,7 +273,6 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, - return 0; - } - -- - int iplink_parse(int argc, char **argv, struct iplink_req *req, - char **name, char **type, char **link, char **dev, int *group) - { -@@ -330,16 +330,16 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, - if (get_integer(&mtu, *argv, 0)) - invarg("Invalid \"mtu\" value\n", *argv); - addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4); -- } else if (strcmp(*argv, "netns") == 0) { -- NEXT_ARG(); -- if (netns != -1) -- duparg("netns", *argv); -+ } else if (strcmp(*argv, "netns") == 0) { -+ NEXT_ARG(); -+ if (netns != -1) -+ duparg("netns", *argv); - if ((netns = get_netns_fd(*argv)) >= 0) - addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4); - else if (get_integer(&netns, *argv, 0) == 0) - addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4); - else -- invarg("Invalid \"netns\" value\n", *argv); -+ invarg("Invalid \"netns\" value\n", *argv); - } else if (strcmp(*argv, "multicast") == 0) { - NEXT_ARG(); - req->i.ifi_change |= IFF_MULTICAST; -@@ -797,7 +797,6 @@ static int set_address(struct ifreq *ifr, int brd) - return 0; - } - -- - static int do_set(int argc, char **argv) - { - char *dev = NULL; -@@ -897,7 +896,7 @@ static int do_set(int argc, char **argv) - } else - return on_off("dynamic", *argv); - } else { -- if (strcmp(*argv, "dev") == 0) { -+ if (strcmp(*argv, "dev") == 0) { - NEXT_ARG(); - } - if (matches(*argv, "help") == 0) -diff --git a/ip/iptunnel.c b/ip/iptunnel.c -index 43f8585..9099503 100644 ---- a/ip/iptunnel.c -+++ b/ip/iptunnel.c -@@ -405,7 +405,7 @@ static void print_tunnel(struct ip_tunnel_parm *p) - } - - if (p->i_flags&GRE_SEQ) -- printf("%s Drop packets out of sequence.\n", _SL_); -+ printf("%s Drop packets out of sequence.", _SL_); - if (p->i_flags&GRE_CSUM) - printf("%s Checksum in received packet is required.", _SL_); - if (p->o_flags&GRE_SEQ) -diff --git a/ip/link_gre6.c b/ip/link_gre6.c -new file mode 100644 -index 0000000..4c9c536 ---- /dev/null -+++ b/ip/link_gre6.c -@@ -0,0 +1,398 @@ -+/* -+ * link_gre6.c gre driver module -+ * -+ * 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. -+ * -+ * Authors: Dmitry Kozlov -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "rt_names.h" -+#include "utils.h" -+#include "ip_common.h" -+#include "tunnel.h" -+ -+#define IP6_FLOWINFO_TCLASS htonl(0x0FF00000) -+#define IP6_FLOWINFO_FLOWLABEL htonl(0x000FFFFF) -+ -+#define DEFAULT_TNL_HOP_LIMIT (64) -+ -+static void usage(void) __attribute__((noreturn)); -+static void usage(void) -+{ -+ fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n"); -+ fprintf(stderr, " type { ip6gre | ip6gretap } [ remote ADDR ] [ local ADDR ]\n"); -+ fprintf(stderr, " [ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]\n"); -+ fprintf(stderr, " [ hoplimit TTL ] [ encaplimit ELIM ]\n"); -+ fprintf(stderr, " [ tclass TCLASS ] [ flowlabel FLOWLABEL ]\n"); -+ fprintf(stderr, " [ dscp inherit ] [ dev PHYS_DEV ]\n"); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, "Where: NAME := STRING\n"); -+ fprintf(stderr, " ADDR := IPV6_ADDRESS\n"); -+ fprintf(stderr, " TTL := { 0..255 } (default=%d)\n", -+ DEFAULT_TNL_HOP_LIMIT); -+ fprintf(stderr, " KEY := { DOTTED_QUAD | NUMBER }\n"); -+ fprintf(stderr, " ELIM := { none | 0..255 }(default=%d)\n", -+ IPV6_DEFAULT_TNL_ENCAP_LIMIT); -+ fprintf(stderr, " TCLASS := { 0x0..0xff | inherit }\n"); -+ fprintf(stderr, " FLOWLABEL := { 0x0..0xfffff | inherit }\n"); -+ exit(-1); -+} -+ -+static int gre_parse_opt(struct link_util *lu, int argc, char **argv, -+ struct nlmsghdr *n) -+{ -+ struct { -+ struct nlmsghdr n; -+ struct ifinfomsg i; -+ char buf[1024]; -+ } req; -+ struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); -+ struct rtattr *tb[IFLA_MAX + 1]; -+ struct rtattr *linkinfo[IFLA_INFO_MAX+1]; -+ struct rtattr *greinfo[IFLA_GRE_MAX + 1]; -+ __u16 iflags = 0; -+ __u16 oflags = 0; -+ unsigned ikey = 0; -+ unsigned okey = 0; -+ struct in6_addr raddr = IN6ADDR_ANY_INIT; -+ struct in6_addr laddr = IN6ADDR_ANY_INIT; -+ unsigned link = 0; -+ unsigned flowinfo = 0; -+ unsigned flags = 0; -+ __u8 hop_limit = DEFAULT_TNL_HOP_LIMIT; -+ __u8 encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT; -+ int len; -+ -+ if (!(n->nlmsg_flags & NLM_F_CREATE)) { -+ memset(&req, 0, sizeof(req)); -+ -+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)); -+ req.n.nlmsg_flags = NLM_F_REQUEST; -+ req.n.nlmsg_type = RTM_GETLINK; -+ req.i.ifi_family = preferred_family; -+ req.i.ifi_index = ifi->ifi_index; -+ -+ if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { -+get_failed: -+ fprintf(stderr, -+ "Failed to get existing tunnel info.\n"); -+ return -1; -+ } -+ -+ len = req.n.nlmsg_len; -+ len -= NLMSG_LENGTH(sizeof(*ifi)); -+ if (len < 0) -+ goto get_failed; -+ -+ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len); -+ -+ if (!tb[IFLA_LINKINFO]) -+ goto get_failed; -+ -+ parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); -+ -+ if (!linkinfo[IFLA_INFO_DATA]) -+ goto get_failed; -+ -+ parse_rtattr_nested(greinfo, IFLA_GRE_MAX, -+ linkinfo[IFLA_INFO_DATA]); -+ -+ if (greinfo[IFLA_GRE_IKEY]) -+ ikey = rta_getattr_u32(greinfo[IFLA_GRE_IKEY]); -+ -+ if (greinfo[IFLA_GRE_OKEY]) -+ okey = rta_getattr_u32(greinfo[IFLA_GRE_OKEY]); -+ -+ if (greinfo[IFLA_GRE_IFLAGS]) -+ iflags = rta_getattr_u16(greinfo[IFLA_GRE_IFLAGS]); -+ -+ if (greinfo[IFLA_GRE_OFLAGS]) -+ oflags = rta_getattr_u16(greinfo[IFLA_GRE_OFLAGS]); -+ -+ if (greinfo[IFLA_GRE_LOCAL]) -+ memcpy(&laddr, RTA_DATA(greinfo[IFLA_GRE_LOCAL]), sizeof(laddr)); -+ -+ if (greinfo[IFLA_GRE_REMOTE]) -+ memcpy(&raddr, RTA_DATA(greinfo[IFLA_GRE_REMOTE]), sizeof(raddr)); -+ -+ if (greinfo[IFLA_GRE_TTL]) -+ hop_limit = rta_getattr_u8(greinfo[IFLA_GRE_TTL]); -+ -+ if (greinfo[IFLA_GRE_LINK]) -+ link = rta_getattr_u32(greinfo[IFLA_GRE_LINK]); -+ -+ if (greinfo[IFLA_GRE_ENCAP_LIMIT]) -+ encap_limit = rta_getattr_u8(greinfo[IFLA_GRE_ENCAP_LIMIT]); -+ -+ if (greinfo[IFLA_GRE_FLOWINFO]) -+ flowinfo = rta_getattr_u32(greinfo[IFLA_GRE_FLOWINFO]); -+ -+ if (greinfo[IFLA_GRE_FLAGS]) -+ flags = rta_getattr_u32(greinfo[IFLA_GRE_FLAGS]); -+ } -+ -+ while (argc > 0) { -+ if (!matches(*argv, "key")) { -+ unsigned uval; -+ -+ NEXT_ARG(); -+ iflags |= GRE_KEY; -+ oflags |= GRE_KEY; -+ if (strchr(*argv, '.')) -+ uval = get_addr32(*argv); -+ else { -+ if (get_unsigned(&uval, *argv, 0) < 0) { -+ fprintf(stderr, -+ "Invalid value for \"key\"\n"); -+ exit(-1); -+ } -+ uval = htonl(uval); -+ } -+ -+ ikey = okey = uval; -+ } else if (!matches(*argv, "ikey")) { -+ unsigned uval; -+ -+ NEXT_ARG(); -+ iflags |= GRE_KEY; -+ if (strchr(*argv, '.')) -+ uval = get_addr32(*argv); -+ else { -+ if (get_unsigned(&uval, *argv, 0)<0) { -+ fprintf(stderr, "invalid value of \"ikey\"\n"); -+ exit(-1); -+ } -+ uval = htonl(uval); -+ } -+ ikey = uval; -+ } else if (!matches(*argv, "okey")) { -+ unsigned uval; -+ -+ NEXT_ARG(); -+ oflags |= GRE_KEY; -+ if (strchr(*argv, '.')) -+ uval = get_addr32(*argv); -+ else { -+ if (get_unsigned(&uval, *argv, 0)<0) { -+ fprintf(stderr, "invalid value of \"okey\"\n"); -+ exit(-1); -+ } -+ uval = htonl(uval); -+ } -+ okey = uval; -+ } else if (!matches(*argv, "seq")) { -+ iflags |= GRE_SEQ; -+ oflags |= GRE_SEQ; -+ } else if (!matches(*argv, "iseq")) { -+ iflags |= GRE_SEQ; -+ } else if (!matches(*argv, "oseq")) { -+ oflags |= GRE_SEQ; -+ } else if (!matches(*argv, "csum")) { -+ iflags |= GRE_CSUM; -+ oflags |= GRE_CSUM; -+ } else if (!matches(*argv, "icsum")) { -+ iflags |= GRE_CSUM; -+ } else if (!matches(*argv, "ocsum")) { -+ oflags |= GRE_CSUM; -+ } else if (!matches(*argv, "remote")) { -+ inet_prefix addr; -+ NEXT_ARG(); -+ get_prefix(&addr, *argv, preferred_family); -+ if (addr.family == AF_UNSPEC) -+ invarg("\"remote\" address family is AF_UNSPEC", *argv); -+ memcpy(&raddr, &addr.data, sizeof(raddr)); -+ } else if (!matches(*argv, "local")) { -+ inet_prefix addr; -+ NEXT_ARG(); -+ get_prefix(&addr, *argv, preferred_family); -+ if (addr.family == AF_UNSPEC) -+ invarg("\"local\" address family is AF_UNSPEC", *argv); -+ memcpy(&laddr, &addr.data, sizeof(laddr)); -+ } else if (!matches(*argv, "dev")) { -+ NEXT_ARG(); -+ link = if_nametoindex(*argv); -+ if (link == 0) -+ exit(-1); -+ } else if (!matches(*argv, "ttl") || -+ !matches(*argv, "hoplimit")) { -+ __u8 uval; -+ NEXT_ARG(); -+ if (get_u8(&uval, *argv, 0)) -+ invarg("invalid TTL", *argv); -+ hop_limit = uval; -+ } else if (!matches(*argv, "tos") || -+ !matches(*argv, "tclass") || -+ !matches(*argv, "dsfield")) { -+ __u8 uval; -+ NEXT_ARG(); -+ if (strcmp(*argv, "inherit") == 0) -+ flags |= IP6_TNL_F_USE_ORIG_TCLASS; -+ else { -+ if (get_u8(&uval, *argv, 16)) -+ invarg("invalid TClass", *argv); -+ flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS; -+ flags &= ~IP6_TNL_F_USE_ORIG_TCLASS; -+ } -+ } else if (strcmp(*argv, "flowlabel") == 0 || -+ strcmp(*argv, "fl") == 0) { -+ __u32 uval; -+ NEXT_ARG(); -+ if (strcmp(*argv, "inherit") == 0) -+ flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL; -+ else { -+ if (get_u32(&uval, *argv, 16)) -+ invarg("invalid Flowlabel", *argv); -+ if (uval > 0xFFFFF) -+ invarg("invalid Flowlabel", *argv); -+ flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL; -+ flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL; -+ } -+ } else if (strcmp(*argv, "dscp") == 0) { -+ NEXT_ARG(); -+ if (strcmp(*argv, "inherit") != 0) -+ invarg("not inherit", *argv); -+ flags |= IP6_TNL_F_RCV_DSCP_COPY; -+ } else -+ usage(); -+ argc--; argv++; -+ } -+ -+ addattr32(n, 1024, IFLA_GRE_IKEY, ikey); -+ addattr32(n, 1024, IFLA_GRE_OKEY, okey); -+ addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2); -+ addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2); -+ addattr_l(n, 1024, IFLA_GRE_LOCAL, &laddr, sizeof(laddr)); -+ addattr_l(n, 1024, IFLA_GRE_REMOTE, &raddr, sizeof(raddr)); -+ if (link) -+ addattr32(n, 1024, IFLA_GRE_LINK, link); -+ addattr_l(n, 1024, IFLA_GRE_TTL, &hop_limit, 1); -+ addattr_l(n, 1024, IFLA_GRE_ENCAP_LIMIT, &encap_limit, 1); -+ addattr_l(n, 1024, IFLA_GRE_FLOWINFO, &flowinfo, 4); -+ addattr_l(n, 1024, IFLA_GRE_FLAGS, &flowinfo, 4); -+ -+ return 0; -+} -+ -+static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) -+{ -+ char s1[1024]; -+ char s2[64]; -+ const char *local = "any"; -+ const char *remote = "any"; -+ unsigned iflags = 0; -+ unsigned oflags = 0; -+ unsigned flags = 0; -+ unsigned flowinfo = 0; -+ struct in6_addr in6_addr_any = IN6ADDR_ANY_INIT; -+ -+ if (!tb) -+ return; -+ -+ if (tb[IFLA_GRE_FLAGS]) -+ flags = rta_getattr_u32(tb[IFLA_GRE_FLAGS]); -+ -+ if (tb[IFLA_GRE_FLOWINFO]) -+ flags = rta_getattr_u32(tb[IFLA_GRE_FLOWINFO]); -+ -+ if (tb[IFLA_GRE_REMOTE]) { -+ struct in6_addr addr; -+ memcpy(&addr, RTA_DATA(tb[IFLA_GRE_REMOTE]), sizeof(addr)); -+ -+ if (memcmp(&addr, &in6_addr_any, sizeof(addr))) -+ remote = format_host(AF_INET6, sizeof(addr), &addr, s1, sizeof(s1)); -+ } -+ -+ fprintf(f, "remote %s ", remote); -+ -+ if (tb[IFLA_GRE_LOCAL]) { -+ struct in6_addr addr; -+ memcpy(&addr, RTA_DATA(tb[IFLA_GRE_LOCAL]), sizeof(addr)); -+ -+ if (memcmp(&addr, &in6_addr_any, sizeof(addr))) -+ local = format_host(AF_INET6, sizeof(addr), &addr, s1, sizeof(s1)); -+ } -+ -+ fprintf(f, "local %s ", local); -+ -+ if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) { -+ unsigned link = rta_getattr_u32(tb[IFLA_GRE_LINK]); -+ const char *n = if_indextoname(link, s2); -+ -+ if (n) -+ fprintf(f, "dev %s ", n); -+ else -+ fprintf(f, "dev %u ", link); -+ } -+ -+ if (tb[IFLA_GRE_TTL] && rta_getattr_u8(tb[IFLA_GRE_TTL])) -+ fprintf(f, "hoplimit %d ", rta_getattr_u8(tb[IFLA_GRE_TTL])); -+ -+ if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT) -+ fprintf(f, "encaplimit none "); -+ else if (tb[IFLA_GRE_ENCAP_LIMIT]) { -+ int encap_limit = rta_getattr_u8(tb[IFLA_GRE_ENCAP_LIMIT]); -+ -+ fprintf(f, "encaplimit %d ", encap_limit); -+ } -+ -+ if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) -+ fprintf(f, "flowlabel inherit "); -+ else -+ fprintf(f, "flowlabel 0x%05x ", ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL)); -+ -+ if (flags & IP6_TNL_F_RCV_DSCP_COPY) -+ fprintf(f, "dscp inherit "); -+ -+ if (tb[IFLA_GRE_IFLAGS]) -+ iflags = rta_getattr_u16(tb[IFLA_GRE_IFLAGS]); -+ -+ if (tb[IFLA_GRE_OFLAGS]) -+ oflags = rta_getattr_u16(tb[IFLA_GRE_OFLAGS]); -+ -+ if ((iflags & GRE_KEY) && tb[IFLA_GRE_IKEY]) { -+ inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2)); -+ fprintf(f, "ikey %s ", s2); -+ } -+ -+ if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) { -+ inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2)); -+ fprintf(f, "okey %s ", s2); -+ } -+ -+ if (iflags & GRE_SEQ) -+ fputs("iseq ", f); -+ if (oflags & GRE_SEQ) -+ fputs("oseq ", f); -+ if (iflags & GRE_CSUM) -+ fputs("icsum ", f); -+ if (oflags & GRE_CSUM) -+ fputs("ocsum ", f); -+} -+ -+struct link_util ip6gre_link_util = { -+ .id = "ip6gre", -+ .maxattr = IFLA_GRE_MAX, -+ .parse_opt = gre_parse_opt, -+ .print_opt = gre_print_opt, -+}; -+ -+struct link_util ip6gretap_link_util = { -+ .id = "ip6gretap", -+ .maxattr = IFLA_GRE_MAX, -+ .parse_opt = gre_parse_opt, -+ .print_opt = gre_print_opt, -+}; -diff --git a/ip/link_vti6.c b/ip/link_vti6.c -new file mode 100644 -index 0000000..282896d ---- /dev/null -+++ b/ip/link_vti6.c -@@ -0,0 +1,250 @@ -+/* -+ * link_vti6.c VTI driver module -+ * -+ * 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. -+ * -+ * Authors: Herbert Xu -+ * Saurabh Mohan Modified link_gre.c for VTI -+ * Steffen Klassert Modified link_vti.c for IPv6 -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include "rt_names.h" -+#include "utils.h" -+#include "ip_common.h" -+#include "tunnel.h" -+ -+ -+static void usage(void) __attribute__((noreturn)); -+static void usage(void) -+{ -+ fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n"); -+ fprintf(stderr, " type { vti6 } [ remote ADDR ] [ local ADDR ]\n"); -+ fprintf(stderr, " [ [i|o]key KEY ]\n"); -+ fprintf(stderr, " [ dev PHYS_DEV ]\n"); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, "Where: NAME := STRING\n"); -+ fprintf(stderr, " ADDR := { IPV6_ADDRESS }\n"); -+ fprintf(stderr, " KEY := { DOTTED_QUAD | NUMBER }\n"); -+ exit(-1); -+} -+ -+static int vti6_parse_opt(struct link_util *lu, int argc, char **argv, -+ struct nlmsghdr *n) -+{ -+ struct { -+ struct nlmsghdr n; -+ struct ifinfomsg i; -+ char buf[1024]; -+ } req; -+ struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); -+ struct rtattr *tb[IFLA_MAX + 1]; -+ struct rtattr *linkinfo[IFLA_INFO_MAX+1]; -+ struct rtattr *vtiinfo[IFLA_VTI_MAX + 1]; -+ struct in6_addr saddr; -+ struct in6_addr daddr; -+ unsigned ikey = 0; -+ unsigned okey = 0; -+ unsigned link = 0; -+ int len; -+ -+ if (!(n->nlmsg_flags & NLM_F_CREATE)) { -+ memset(&req, 0, sizeof(req)); -+ -+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)); -+ req.n.nlmsg_flags = NLM_F_REQUEST; -+ req.n.nlmsg_type = RTM_GETLINK; -+ req.i.ifi_family = preferred_family; -+ req.i.ifi_index = ifi->ifi_index; -+ -+ if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { -+get_failed: -+ fprintf(stderr, -+ "Failed to get existing tunnel info.\n"); -+ return -1; -+ } -+ -+ len = req.n.nlmsg_len; -+ len -= NLMSG_LENGTH(sizeof(*ifi)); -+ if (len < 0) -+ goto get_failed; -+ -+ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len); -+ -+ if (!tb[IFLA_LINKINFO]) -+ goto get_failed; -+ -+ parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); -+ -+ if (!linkinfo[IFLA_INFO_DATA]) -+ goto get_failed; -+ -+ parse_rtattr_nested(vtiinfo, IFLA_VTI_MAX, -+ linkinfo[IFLA_INFO_DATA]); -+ -+ if (vtiinfo[IFLA_VTI_IKEY]) -+ ikey = rta_getattr_u32(vtiinfo[IFLA_VTI_IKEY]); -+ -+ if (vtiinfo[IFLA_VTI_OKEY]) -+ okey = rta_getattr_u32(vtiinfo[IFLA_VTI_OKEY]); -+ -+ if (vtiinfo[IFLA_VTI_LOCAL]) -+ memcpy(&saddr, RTA_DATA(vtiinfo[IFLA_VTI_LOCAL]), sizeof(saddr)); -+ -+ if (vtiinfo[IFLA_VTI_REMOTE]) -+ memcpy(&daddr, RTA_DATA(vtiinfo[IFLA_VTI_REMOTE]), sizeof(daddr)); -+ -+ if (vtiinfo[IFLA_VTI_LINK]) -+ link = rta_getattr_u8(vtiinfo[IFLA_VTI_LINK]); -+ } -+ -+ while (argc > 0) { -+ if (!matches(*argv, "key")) { -+ unsigned uval; -+ -+ NEXT_ARG(); -+ if (strchr(*argv, '.')) -+ uval = get_addr32(*argv); -+ else { -+ if (get_unsigned(&uval, *argv, 0) < 0) { -+ fprintf(stderr, -+ "Invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv); -+ exit(-1); -+ } -+ uval = htonl(uval); -+ } -+ -+ ikey = okey = uval; -+ } else if (!matches(*argv, "ikey")) { -+ unsigned uval; -+ -+ NEXT_ARG(); -+ if (strchr(*argv, '.')) -+ uval = get_addr32(*argv); -+ else { -+ if (get_unsigned(&uval, *argv, 0) < 0) { -+ fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv); -+ exit(-1); -+ } -+ uval = htonl(uval); -+ } -+ ikey = uval; -+ } else if (!matches(*argv, "okey")) { -+ unsigned uval; -+ -+ NEXT_ARG(); -+ if (strchr(*argv, '.')) -+ uval = get_addr32(*argv); -+ else { -+ if (get_unsigned(&uval, *argv, 0) < 0) { -+ fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv); -+ exit(-1); -+ } -+ uval = htonl(uval); -+ } -+ okey = uval; -+ } else if (!matches(*argv, "remote")) { -+ NEXT_ARG(); -+ if (!strcmp(*argv, "any")) { -+ fprintf(stderr, "invalid value for \"remote\": \"%s\"\n", *argv); -+ exit(-1); -+ } else { -+ inet_prefix addr; -+ get_prefix(&addr, *argv, AF_INET6); -+ memcpy(&daddr, addr.data, addr.bytelen); -+ } -+ } else if (!matches(*argv, "local")) { -+ NEXT_ARG(); -+ if (!strcmp(*argv, "any")) { -+ fprintf(stderr, "invalid value for \"local\": \"%s\"\n", *argv); -+ exit(-1); -+ } else { -+ inet_prefix addr; -+ get_prefix(&addr, *argv, AF_INET6); -+ memcpy(&saddr, addr.data, addr.bytelen); -+ } -+ } else if (!matches(*argv, "dev")) { -+ NEXT_ARG(); -+ link = if_nametoindex(*argv); -+ if (link == 0) -+ exit(-1); -+ } else -+ usage(); -+ argc--; argv++; -+ } -+ -+ addattr32(n, 1024, IFLA_VTI_IKEY, ikey); -+ addattr32(n, 1024, IFLA_VTI_OKEY, okey); -+ addattr_l(n, 1024, IFLA_VTI_LOCAL, &saddr, sizeof(saddr)); -+ addattr_l(n, 1024, IFLA_VTI_REMOTE, &daddr, sizeof(daddr)); -+ if (link) -+ addattr32(n, 1024, IFLA_VTI_LINK, link); -+ -+ return 0; -+} -+ -+static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) -+{ -+ char s1[1024]; -+ char s2[64]; -+ const char *local = "any"; -+ const char *remote = "any"; -+ struct in6_addr saddr; -+ struct in6_addr daddr; -+ -+ if (!tb) -+ return; -+ -+ if (tb[IFLA_VTI_REMOTE]) { -+ memcpy(&daddr, RTA_DATA(tb[IFLA_VTI_REMOTE]), sizeof(daddr)); -+ -+ remote = format_host(AF_INET6, 16, &daddr, s1, sizeof(s1)); -+ } -+ -+ fprintf(f, "remote %s ", remote); -+ -+ if (tb[IFLA_VTI_LOCAL]) { -+ memcpy(&saddr, RTA_DATA(tb[IFLA_VTI_LOCAL]), sizeof(saddr)); -+ -+ local = format_host(AF_INET6, 16, &saddr, s1, sizeof(s1)); -+ } -+ -+ fprintf(f, "local %s ", local); -+ -+ if (tb[IFLA_VTI_LINK] && *(__u32 *)RTA_DATA(tb[IFLA_VTI_LINK])) { -+ unsigned link = *(__u32 *)RTA_DATA(tb[IFLA_VTI_LINK]); -+ const char *n = if_indextoname(link, s2); -+ -+ if (n) -+ fprintf(f, "dev %s ", n); -+ else -+ fprintf(f, "dev %u ", link); -+ } -+ -+ if (tb[IFLA_VTI_IKEY]) { -+ inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_IKEY]), s2, sizeof(s2)); -+ fprintf(f, "ikey %s ", s2); -+ } -+ -+ if (tb[IFLA_VTI_OKEY]) { -+ inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_OKEY]), s2, sizeof(s2)); -+ fprintf(f, "okey %s ", s2); -+ } -+} -+ -+struct link_util vti6_link_util = { -+ .id = "vti6", -+ .maxattr = IFLA_VTI_MAX, -+ .parse_opt = vti6_parse_opt, -+ .print_opt = vti6_print_opt, -+}; --- -1.8.3.1 - diff --git a/SOURCES/0025-link-dump-filter.patch b/SOURCES/0025-link-dump-filter.patch new file mode 100644 index 0000000..7175f45 --- /dev/null +++ b/SOURCES/0025-link-dump-filter.patch @@ -0,0 +1,122 @@ +From 83e4e4b09ca5ca91ab54fe983c1786e04b7ba41b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:05:51 +0100 +Subject: [PATCH] link dump filter + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 +Upstream Status: iproute2.git commit 50b9950dd9011 + +commit 50b9950dd90114609e10298c0fa32a9371250687 +Author: Roopa Prabhu +Date: Wed Jul 16 07:13:25 2014 -0700 + + link dump filter + + This patch avoids a full link wildump request when the user has specified + a single link. Uses RTM_GETLINK without the NLM_F_DUMP flag. + + This helps on a system with large number of interfaces. + + This patch currently only uses the link ifindex in the filter. + Hoping to provide a subsequent kernel patch to do link dump filtering on + other attributes in the kernel. + + In iplink_get, to be safe, this patch currently sets the answer buffer + size to the max size that libnetlink rtnl_talk can copy. The current api + does not seem to provide a way to indicate the answer buf size. + + changelog from RFC to v1: + - incorporated comments from stephen (fixed comment and fixed if/else block) + + changelog from v1 to v2: + - fix whitespaces error + + Signed-off-by: Roopa Prabhu +--- + ip/ip_common.h | 1 + + ip/ipaddress.c | 13 +++++++++++++ + ip/iplink.c | 32 ++++++++++++++++++++++++++++++++ + 3 files changed, 46 insertions(+) + +diff --git a/ip/ip_common.h b/ip/ip_common.h +index e7aaa7f..274d12a 100644 +--- a/ip/ip_common.h ++++ b/ip/ip_common.h +@@ -54,6 +54,7 @@ extern int do_ipl2tp(int argc, char **argv); + extern int do_tcp_metrics(int argc, char **argv); + extern int do_ipnetconf(int argc, char **argv); + extern int do_iptoken(int argc, char **argv); ++extern int iplink_get(unsigned int flags, char *name, __u32 filt_mask); + + static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb) + { +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 07242d3..f5a47db 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -1308,6 +1308,19 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) + exit(0); + } + ++ /* ++ * If only filter_dev present and none of the other ++ * link filters are present, use RTM_GETLINK to get ++ * the link device ++ */ ++ if (filter_dev && filter.group == -1 && do_link == 1) { ++ if (iplink_get(0, filter_dev, RTEXT_FILTER_VF) < 0) { ++ perror("Cannot send link get request"); ++ exit(1); ++ } ++ exit(0); ++ } ++ + if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) { + perror("Cannot send dump request"); + exit(1); +diff --git a/ip/iplink.c b/ip/iplink.c +index cacb589..9362e83 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -673,6 +673,38 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) + return 0; + } + ++int iplink_get(unsigned int flags, char *name, __u32 filt_mask) ++{ ++ int len; ++ struct iplink_req req; ++ char answer[16384]; ++ ++ memset(&req, 0, sizeof(req)); ++ ++ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); ++ req.n.nlmsg_flags = NLM_F_REQUEST|flags; ++ req.n.nlmsg_type = RTM_GETLINK; ++ req.i.ifi_family = preferred_family; ++ ++ if (name) { ++ len = strlen(name) + 1; ++ if (len == 1) ++ invarg("\"\" is not a valid device identifier\n", ++ "name"); ++ if (len > IFNAMSIZ) ++ invarg("\"name\" too long\n", name); ++ addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, len); ++ } ++ addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask); ++ ++ if (rtnl_talk(&rth, &req.n, 0, 0, (struct nlmsghdr *)answer) < 0) ++ return -2; ++ ++ print_linkinfo(NULL, (struct nlmsghdr *)answer, stdout); ++ ++ return 0; ++} ++ + #if IPLINK_IOCTL_COMPAT + static int get_ctl_fd(void) + { +-- +1.8.3.1 + diff --git a/SOURCES/0026-ip-return-correct-exit-code-on-route-failure.patch b/SOURCES/0026-ip-return-correct-exit-code-on-route-failure.patch new file mode 100644 index 0000000..b1b14a8 --- /dev/null +++ b/SOURCES/0026-ip-return-correct-exit-code-on-route-failure.patch @@ -0,0 +1,43 @@ +From daba15cd1437d136cfd3f09bd42d7c79ffa3d517 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:05:52 +0100 +Subject: [PATCH] ip: return correct exit code on route failure + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 +Upstream Status: iproute2.git commit d58ba4ba2a532 + +commit d58ba4ba2a532f3ebfa640c42ec2622b54740cdf +Author: Stephen Hemminger +Date: Wed May 6 09:48:06 2015 -0700 + + ip: return correct exit code on route failure + + If kernel complains about ip route request, exit status should be + 2 not 1. + + This fixes regression introduced by: + commit 42ecedd4bae534fc688194a795eb4548c6530cda + Author: Roopa Prabhu + Date: Tue Mar 17 19:26:32 2015 -0700 + + fix ip -force -batch to continue on errors +--- + ip/iproute.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index fbe5268..4f7cd9b 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -1030,7 +1030,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) + req.r.rtm_family = AF_INET; + + if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) +- return -1; ++ return -2; + + return 0; + } +-- +1.8.3.1 + diff --git a/SOURCES/0027-ip-fix-exit-code-for-rule-failures.patch b/SOURCES/0027-ip-fix-exit-code-for-rule-failures.patch new file mode 100644 index 0000000..8edcdfa --- /dev/null +++ b/SOURCES/0027-ip-fix-exit-code-for-rule-failures.patch @@ -0,0 +1,37 @@ +From edc209d4479b6b89aed9cb5b661002cf27031bea Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:05:58 +0100 +Subject: [PATCH] ip: fix exit code for rule failures + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 +Upstream Status: iproute2.git commit 076ae7089a4b4 + +commit 076ae7089a4b4874a1aedd4c5f84bb889dcda34e +Author: Stephen Hemminger +Date: Wed May 6 09:53:41 2015 -0700 + + ip: fix exit code for rule failures + + If ip rule command fails talking to kernel, exit code should be 2. + The sub-command is called by cmd loop and the exit code is negative + of return value from the command callback. +--- + ip/iprule.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iprule.c b/ip/iprule.c +index d80b125..eebcda2 100644 +--- a/ip/iprule.c ++++ b/ip/iprule.c +@@ -355,7 +355,7 @@ static int iprule_modify(int cmd, int argc, char **argv) + req.r.rtm_table = RT_TABLE_MAIN; + + if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) +- return 2; ++ return -2; + + return 0; + } +-- +1.8.3.1 + diff --git a/SOURCES/0028-libnetlink-add-size-argument-to-rtnl_talk.patch b/SOURCES/0028-libnetlink-add-size-argument-to-rtnl_talk.patch new file mode 100644 index 0000000..e4849de --- /dev/null +++ b/SOURCES/0028-libnetlink-add-size-argument-to-rtnl_talk.patch @@ -0,0 +1,819 @@ +From fc6ef05c8579a313461139e1c31130e0893c56f0 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:06:06 +0100 +Subject: [PATCH] libnetlink: add size argument to rtnl_talk + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 +Upstream Status: iproute2.git commit c079e121a73af +Conflicts: +- Already applied commit d25ec03e1dce4 + ("ipaddress: fix ipaddr_flush for Linux >= 3.1"). +- Missing commit 025fa9dc7a4fe + ("xfrm: add command for configuring SPD hash table"). +- Upstream conflict merge at 03371c7d98d16. + +commit c079e121a73af5eb49e003b13607e8a690331df6 +Author: Stephen Hemminger +Date: Wed May 27 12:26:14 2015 -0700 + + libnetlink: add size argument to rtnl_talk + + There have been several instances where response from kernel + has overrun the stack buffer from the caller. Avoid future problems + by passing a size argument. + + Also drop the unused peer and group arguments to rtnl_talk. +--- + bridge/fdb.c | 2 +- + bridge/link.c | 2 +- + bridge/mdb.c | 2 +- + bridge/vlan.c | 2 +- + genl/ctrl.c | 4 ++-- + include/libnetlink.h | 4 ++-- + ip/ipaddress.c | 4 ++-- + ip/ipaddrlabel.c | 4 ++-- + ip/ipl2tp.c | 8 ++++---- + ip/iplink.c | 13 ++++++++----- + ip/ipneigh.c | 2 +- + ip/ipnetns.c | 4 ++-- + ip/ipntable.c | 2 +- + ip/iproute.c | 8 ++++---- + ip/iprule.c | 4 ++-- + ip/iptoken.c | 2 +- + ip/link_gre.c | 2 +- + ip/link_gre6.c | 2 +- + ip/link_ip6tnl.c | 2 +- + ip/link_iptnl.c | 2 +- + ip/link_vti.c | 2 +- + ip/link_vti6.c | 2 +- + ip/tcp_metrics.c | 4 ++-- + ip/xfrm_policy.c | 14 +++++++------- + ip/xfrm_state.c | 12 ++++++------ + lib/libgenl.c | 2 +- + lib/libnetlink.c | 40 ++++++++++++++++++++++------------------ + tc/m_action.c | 6 +++--- + tc/tc_class.c | 2 +- + tc/tc_filter.c | 2 +- + tc/tc_qdisc.c | 2 +- + 31 files changed, 85 insertions(+), 78 deletions(-) + +diff --git a/bridge/fdb.c b/bridge/fdb.c +index b8138cb..6dc3153 100644 +--- a/bridge/fdb.c ++++ b/bridge/fdb.c +@@ -329,7 +329,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv) + return -1; + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return -1; + + return 0; +diff --git a/bridge/link.c b/bridge/link.c +index c5e7ae5..02777d6 100644 +--- a/bridge/link.c ++++ b/bridge/link.c +@@ -376,7 +376,7 @@ static int brlink_modify(int argc, char **argv) + addattr_nest_end(&req.n, nest); + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return -1; + + return 0; +diff --git a/bridge/mdb.c b/bridge/mdb.c +index ab3a792..821f575 100644 +--- a/bridge/mdb.c ++++ b/bridge/mdb.c +@@ -224,7 +224,7 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv) + + addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry)); + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return -1; + + return 0; +diff --git a/bridge/vlan.c b/bridge/vlan.c +index ba54b0e..b471bf7 100644 +--- a/bridge/vlan.c ++++ b/bridge/vlan.c +@@ -95,7 +95,7 @@ static int vlan_modify(int cmd, int argc, char **argv) + + addattr_nest_end(&req.n, afspec); + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return -1; + + return 0; +diff --git a/genl/ctrl.c b/genl/ctrl.c +index 48cbc35..2596883 100644 +--- a/genl/ctrl.c ++++ b/genl/ctrl.c +@@ -67,7 +67,7 @@ int genl_ctrl_resolve_family(const char *family) + + addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME, family, strlen(family) + 1); + +- if (rtnl_talk(&rth, nlh, 0, 0, nlh) < 0) { ++ if (rtnl_talk(&rth, nlh, nlh, sizeof(req)) < 0) { + fprintf(stderr, "Error talking to the kernel\n"); + goto errout; + } +@@ -341,7 +341,7 @@ static int ctrl_list(int cmd, int argc, char **argv) + goto ctrl_done; + } + +- if (rtnl_talk(&rth, nlh, 0, 0, nlh) < 0) { ++ if (rtnl_talk(&rth, nlh, nlh, sizeof(req)) < 0) { + fprintf(stderr, "Error talking to the kernel\n"); + goto ctrl_done; + } +diff --git a/include/libnetlink.h b/include/libnetlink.h +index 058dc64..8c90873 100644 +--- a/include/libnetlink.h ++++ b/include/libnetlink.h +@@ -68,8 +68,8 @@ int rtnl_dump_filter_nc(struct rtnl_handle *rth, + void *arg, __u16 nc_flags); + #define rtnl_dump_filter(rth, filter, arg) \ + rtnl_dump_filter_nc(rth, filter, arg, 0) +-extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, +- unsigned groups, struct nlmsghdr *answer) ++extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, ++ struct nlmsghdr *answer, size_t len) + __attribute__((warn_unused_result)); + extern int rtnl_send(struct rtnl_handle *rth, const void *buf, int) + __attribute__((warn_unused_result)); +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index f5a47db..700c40f 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -1024,7 +1024,7 @@ static int restore_handler(const struct sockaddr_nl *nl, + + ll_init_map(&rth); + +- ret = rtnl_talk(&rth, n, 0, 0, n); ++ ret = rtnl_talk(&rth, n, n, sizeof(*n)); + if ((ret < 0) && (errno == EEXIST)) + ret = 0; + +@@ -1587,7 +1587,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv) + sizeof(cinfo)); + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c +index 5b1f6e4..c5d69f4 100644 +--- a/ip/ipaddrlabel.c ++++ b/ip/ipaddrlabel.c +@@ -183,7 +183,7 @@ static int ipaddrlabel_modify(int cmd, int argc, char **argv) + if (req.ifal.ifal_family == AF_UNSPEC) + req.ifal.ifal_family = AF_INET6; + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +@@ -210,7 +210,7 @@ static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, vo + if (rtnl_open(&rth2, 0) < 0) + return -1; + +- if (rtnl_talk(&rth2, n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth2, n, NULL, 0) < 0) + return -2; + + rtnl_close(&rth2); +diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c +index 5cd8632..2f7c9bf 100644 +--- a/ip/ipl2tp.c ++++ b/ip/ipl2tp.c +@@ -119,7 +119,7 @@ static int create_tunnel(struct l2tp_parm *p) + addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port); + } + +- if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +@@ -132,7 +132,7 @@ static int delete_tunnel(struct l2tp_parm *p) + + addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id); + +- if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +@@ -166,7 +166,7 @@ static int create_session(struct l2tp_parm *p) + if (p->ifname && p->ifname[0]) + addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname); + +- if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +@@ -179,7 +179,7 @@ static int delete_session(struct l2tp_parm *p) + + addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id); + addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id); +- if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +diff --git a/ip/iplink.c b/ip/iplink.c +index 9362e83..048d4f3 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -592,7 +592,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) + + req.i.ifi_index = 0; + addattr32(&req.n, sizeof(req), IFLA_GROUP, group); +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + return 0; + } +@@ -667,7 +667,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) + return -1; + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + return 0; +@@ -677,7 +677,10 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask) + { + int len; + struct iplink_req req; +- char answer[16384]; ++ struct { ++ struct nlmsghdr n; ++ char buf[16384]; ++ } answer; + + memset(&req, 0, sizeof(req)); + +@@ -697,10 +700,10 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask) + } + addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask); + +- if (rtnl_talk(&rth, &req.n, 0, 0, (struct nlmsghdr *)answer) < 0) ++ if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0) + return -2; + +- print_linkinfo(NULL, (struct nlmsghdr *)answer, stdout); ++ print_linkinfo(NULL, &answer.n, stdout); + + return 0; + } +diff --git a/ip/ipneigh.c b/ip/ipneigh.c +index c47f005..19fd8e2 100644 +--- a/ip/ipneigh.c ++++ b/ip/ipneigh.c +@@ -179,7 +179,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv) + return -1; + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + return 0; +diff --git a/ip/ipnetns.c b/ip/ipnetns.c +index 00b6cc4..2c848bc 100644 +--- a/ip/ipnetns.c ++++ b/ip/ipnetns.c +@@ -113,7 +113,7 @@ static int get_netnsid_from_name(const char *name) + return fd; + + addattr32(&req.n, 1024, NETNSA_FD, fd); +- if (rtnl_talk(&rtnsh, &req.n, 0, 0, &answer.n) < 0) { ++ if (rtnl_talk(&rtnsh, &req.n, &answer.n, sizeof(answer)) < 0) { + close(fd); + return -2; + } +@@ -698,7 +698,7 @@ static int set_netnsid_from_name(const char *name, int nsid) + + addattr32(&req.n, 1024, NETNSA_FD, fd); + addattr32(&req.n, 1024, NETNSA_NSID, nsid); +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + err = -2; + + close(fd); +diff --git a/ip/ipntable.c b/ip/ipntable.c +index 4d4eece..ca5d935 100644 +--- a/ip/ipntable.c ++++ b/ip/ipntable.c +@@ -314,7 +314,7 @@ static int ipntable_modify(int cmd, int flags, int argc, char **argv) + RTA_PAYLOAD(parms_rta)); + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + return 0; +diff --git a/ip/iproute.c b/ip/iproute.c +index 4f7cd9b..367b922 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -1029,7 +1029,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) + if (req.r.rtm_family == AF_UNSPEC) + req.r.rtm_family = AF_INET; + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +@@ -1486,7 +1486,7 @@ static int iproute_get(int argc, char **argv) + if (req.r.rtm_family == AF_UNSPEC) + req.r.rtm_family = AF_INET; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) + exit(2); + + if (connected && !from_ok) { +@@ -1527,7 +1527,7 @@ static int iproute_get(int argc, char **argv) + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_GETROUTE; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) + exit(2); + } + +@@ -1549,7 +1549,7 @@ static int restore_handler(const struct sockaddr_nl *nl, + + ll_init_map(&rth); + +- ret = rtnl_talk(&rth, n, 0, 0, n); ++ ret = rtnl_talk(&rth, n, n, sizeof(*n)); + if ((ret < 0) && (errno == EEXIST)) + ret = 0; + +diff --git a/ip/iprule.c b/ip/iprule.c +index eebcda2..89fa7ef 100644 +--- a/ip/iprule.c ++++ b/ip/iprule.c +@@ -354,7 +354,7 @@ static int iprule_modify(int cmd, int argc, char **argv) + if (!table_ok && cmd == RTM_NEWRULE) + req.r.rtm_table = RT_TABLE_MAIN; + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +@@ -381,7 +381,7 @@ static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *a + if (rtnl_open(&rth2, 0) < 0) + return -1; + +- if (rtnl_talk(&rth2, n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth2, n, NULL, 0) < 0) + return -2; + + rtnl_close(&rth2); +diff --git a/ip/iptoken.c b/ip/iptoken.c +index 5689c2e..0d265e6 100644 +--- a/ip/iptoken.c ++++ b/ip/iptoken.c +@@ -182,7 +182,7 @@ static int iptoken_set(int argc, char **argv) + return -1; + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return -2; + + return 0; +diff --git a/ip/link_gre.c b/ip/link_gre.c +index ddbd6cc..62acf46 100644 +--- a/ip/link_gre.c ++++ b/ip/link_gre.c +@@ -77,7 +77,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { + get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); +diff --git a/ip/link_gre6.c b/ip/link_gre6.c +index f18919c..e00ea09 100644 +--- a/ip/link_gre6.c ++++ b/ip/link_gre6.c +@@ -91,7 +91,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { + get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); +diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c +index cf59a93..f771c75 100644 +--- a/ip/link_ip6tnl.c ++++ b/ip/link_ip6tnl.c +@@ -89,7 +89,7 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv, + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { + get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); +diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c +index 2ac2604..4d5422b 100644 +--- a/ip/link_iptnl.c ++++ b/ip/link_iptnl.c +@@ -81,7 +81,7 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv, + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { + get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); +diff --git a/ip/link_vti.c b/ip/link_vti.c +index 59ac4c4..f3fea33 100644 +--- a/ip/link_vti.c ++++ b/ip/link_vti.c +@@ -71,7 +71,7 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv, + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { + get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); +diff --git a/ip/link_vti6.c b/ip/link_vti6.c +index 282896d..c146f79 100644 +--- a/ip/link_vti6.c ++++ b/ip/link_vti6.c +@@ -67,7 +67,7 @@ static int vti6_parse_opt(struct link_util *lu, int argc, char **argv, + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { + get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); +diff --git a/ip/tcp_metrics.c b/ip/tcp_metrics.c +index c6be3c9..8fa4b26 100644 +--- a/ip/tcp_metrics.c ++++ b/ip/tcp_metrics.c +@@ -386,10 +386,10 @@ static int tcpm_do_cmd(int cmd, int argc, char **argv) + } + + if (ack) { +- if (rtnl_talk(&grth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&grth, &req.n, NULL, 0) < 0) + return -2; + } else if (atype >= 0) { +- if (rtnl_talk(&grth, &req.n, 0, 0, &req.n) < 0) ++ if (rtnl_talk(&grth, &req.n, &req.n, sizeof(req)) < 0) + return -2; + if (process_msg(NULL, &req.n, stdout) < 0) { + fprintf(stderr, "Dump terminated\n"); +diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c +index f7f2c5c..3ff734e 100644 +--- a/ip/xfrm_policy.c ++++ b/ip/xfrm_policy.c +@@ -393,7 +393,7 @@ static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv) + if (req.xpinfo.sel.family == AF_UNSPEC) + req.xpinfo.sel.family = AF_INET; + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + rtnl_close(&rth); +@@ -555,7 +555,7 @@ int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n, + } + + static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, +- void *res_nlbuf) ++ void *res_nlbuf, size_t res_size) + { + struct rtnl_handle rth; + struct { +@@ -670,7 +670,7 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, + (void *)&ctx, ctx.sctx.len); + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, res_nlbuf) < 0) ++ if (rtnl_talk(&rth, &req.n, res_nlbuf, res_size) < 0) + exit(2); + + rtnl_close(&rth); +@@ -680,7 +680,7 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, + + static int xfrm_policy_delete(int argc, char **argv) + { +- return xfrm_policy_get_or_delete(argc, argv, 1, NULL); ++ return xfrm_policy_get_or_delete(argc, argv, 1, NULL, 0); + } + + static int xfrm_policy_get(int argc, char **argv) +@@ -690,7 +690,7 @@ static int xfrm_policy_get(int argc, char **argv) + + memset(buf, 0, sizeof(buf)); + +- xfrm_policy_get_or_delete(argc, argv, 0, n); ++ xfrm_policy_get_or_delete(argc, argv, 0, n, sizeof(buf)); + + if (xfrm_policy_print(NULL, n, (void*)stdout) < 0) { + fprintf(stderr, "An error :-)\n"); +@@ -975,7 +975,7 @@ static int xfrm_spd_getinfo(int argc, char **argv) + if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) + exit(1); + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) + exit(2); + + print_spdinfo(&req.n, (void*)stdout); +@@ -1027,7 +1027,7 @@ static int xfrm_policy_flush(int argc, char **argv) + if (show_stats > 1) + fprintf(stderr, "Flush policy\n"); + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + rtnl_close(&rth); +diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c +index 0f6b10d..20d7a7e 100644 +--- a/ip/xfrm_state.c ++++ b/ip/xfrm_state.c +@@ -644,7 +644,7 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) + if (req.xsinfo.family == AF_UNSPEC) + req.xsinfo.family = AF_INET; + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + rtnl_close(&rth); +@@ -781,7 +781,7 @@ static int xfrm_state_allocspi(int argc, char **argv) + req.xspi.info.family = AF_INET; + + +- if (rtnl_talk(&rth, &req.n, 0, 0, res_n) < 0) ++ if (rtnl_talk(&rth, &req.n, res_n, sizeof(res_buf)) < 0) + exit(2); + + if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) { +@@ -971,7 +971,7 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete) + req.xsid.family = AF_INET; + + if (delete) { +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + } else { + char buf[NLMSG_BUF_SIZE]; +@@ -979,7 +979,7 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete) + + memset(buf, 0, sizeof(buf)); + +- if (rtnl_talk(&rth, &req.n, 0, 0, res_n) < 0) ++ if (rtnl_talk(&rth, &req.n, res_n, sizeof(req)) < 0) + exit(2); + + if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) { +@@ -1220,7 +1220,7 @@ static int xfrm_sad_getinfo(int argc, char **argv) + if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) + exit(1); + +- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) + exit(2); + + print_sadinfo(&req.n, (void*)stdout); +@@ -1274,7 +1274,7 @@ static int xfrm_state_flush(int argc, char **argv) + fprintf(stderr, "Flush state with XFRM-PROTO value \"%s\"\n", + strxf_xfrmproto(req.xsf.proto)); + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + exit(2); + + rtnl_close(&rth); +diff --git a/lib/libgenl.c b/lib/libgenl.c +index ef3e5db..acb1478 100644 +--- a/lib/libgenl.c ++++ b/lib/libgenl.c +@@ -53,7 +53,7 @@ int genl_resolve_family(struct rtnl_handle *grth, const char *family) + addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME, + family, strlen(family) + 1); + +- if (rtnl_talk(grth, &req.n, 0, 0, &req.n) < 0) { ++ if (rtnl_talk(grth, &req.n, &req.n, sizeof(req)) < 0) { + fprintf(stderr, "Error talking to the kernel\n"); + return -2; + } +diff --git a/lib/libnetlink.c b/lib/libnetlink.c +index 95675be..97b79fd 100644 +--- a/lib/libnetlink.c ++++ b/lib/libnetlink.c +@@ -29,6 +29,10 @@ + #define SOL_NETLINK 270 + #endif + ++#ifndef MIN ++#define MIN(a, b) ((a) < (b) ? (a) : (b)) ++#endif ++ + int rcvbuf = 1024 * 1024; + + void rtnl_close(struct rtnl_handle *rth) +@@ -306,8 +310,8 @@ int rtnl_dump_filter_nc(struct rtnl_handle *rth, + return rtnl_dump_filter_l(rth, a); + } + +-int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, +- unsigned groups, struct nlmsghdr *answer) ++int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, ++ struct nlmsghdr *answer, size_t len) + { + int status; + unsigned seq; +@@ -323,12 +327,10 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + .msg_iov = &iov, + .msg_iovlen = 1, + }; +- char buf[16384]; ++ char buf[32768]; + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; +- nladdr.nl_pid = peer; +- nladdr.nl_groups = groups; + + n->nlmsg_seq = seq = ++rtnl->seq; + +@@ -336,7 +338,6 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + n->nlmsg_flags |= NLM_F_ACK; + + status = sendmsg(rtnl->fd, &msg, 0); +- + if (status < 0) { + perror("Cannot talk to rtnetlink"); + return -1; +@@ -345,7 +346,6 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + memset(buf,0,sizeof(buf)); + + iov.iov_base = buf; +- + while (1) { + iov.iov_len = sizeof(buf); + status = recvmsg(rtnl->fd, &msg, 0); +@@ -378,7 +378,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + exit(1); + } + +- if (nladdr.nl_pid != peer || ++ if (nladdr.nl_pid != 0 || + h->nlmsg_pid != rtnl->local.nl_pid || + h->nlmsg_seq != seq) { + /* Don't forget to skip that message. */ +@@ -391,20 +391,22 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); + if (l < sizeof(struct nlmsgerr)) { + fprintf(stderr, "ERROR truncated\n"); +- } else { +- if (!err->error) { +- if (answer) +- memcpy(answer, h, h->nlmsg_len); +- return 0; +- } +- +- fprintf(stderr, "RTNETLINK answers: %s\n", strerror(-err->error)); +- errno = -err->error; ++ } else if (!err->error) { ++ if (answer) ++ memcpy(answer, h, ++ MIN(len, h->nlmsg_len)); ++ return 0; + } ++ ++ fprintf(stderr, "RTNETLINK answers: %s\n", ++ strerror(-err->error)); ++ errno = -err->error; + return -1; + } ++ + if (answer) { +- memcpy(answer, h, h->nlmsg_len); ++ memcpy(answer, h, ++ MIN(len, h->nlmsg_len)); + return 0; + } + +@@ -413,10 +415,12 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + status -= NLMSG_ALIGN(len); + h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); + } ++ + if (msg.msg_flags & MSG_TRUNC) { + fprintf(stderr, "Message truncated\n"); + continue; + } ++ + if (status) { + fprintf(stderr, "!!!Remnant of size %d\n", status); + exit(1); +diff --git a/tc/m_action.c b/tc/m_action.c +index 4acabef..7cbf377 100644 +--- a/tc/m_action.c ++++ b/tc/m_action.c +@@ -451,7 +451,7 @@ static int tc_action_gd(int cmd, unsigned flags, int *argc_p, char ***argv_p) + if (cmd == RTM_GETACTION) + ans = &req.n; + +- if (rtnl_talk(&rth, &req.n, 0, 0, ans) < 0) { ++ if (rtnl_talk(&rth, &req.n, ans, MAX_MSG) < 0) { + fprintf(stderr, "We have an error talking to the kernel\n"); + return 1; + } +@@ -496,7 +496,7 @@ static int tc_action_modify(int cmd, unsigned flags, int *argc_p, char ***argv_p + } + tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail; + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) { ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) { + fprintf(stderr, "We have an error talking to the kernel\n"); + ret = -1; + } +@@ -566,7 +566,7 @@ static int tc_act_list_or_flush(int argc, char **argv, int event) + req.n.nlmsg_type = RTM_DELACTION; + req.n.nlmsg_flags |= NLM_F_ROOT; + req.n.nlmsg_flags |= NLM_F_REQUEST; +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) { ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) { + fprintf(stderr, "We have an error flushing\n"); + return 1; + } +diff --git a/tc/tc_class.c b/tc/tc_class.c +index b8767bc..4f35346 100644 +--- a/tc/tc_class.c ++++ b/tc/tc_class.c +@@ -138,7 +138,7 @@ static int tc_class_modify(int cmd, unsigned flags, int argc, char **argv) + } + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return 2; + + return 0; +diff --git a/tc/tc_filter.c b/tc/tc_filter.c +index 609fbe9..e76d616 100644 +--- a/tc/tc_filter.c ++++ b/tc/tc_filter.c +@@ -167,7 +167,7 @@ static int tc_filter_modify(int cmd, unsigned flags, int argc, char **argv) + } + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) { ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) { + fprintf(stderr, "We have an error talking to the kernel\n"); + return 2; + } +diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c +index c71937d..c31ae8d 100644 +--- a/tc/tc_qdisc.c ++++ b/tc/tc_qdisc.c +@@ -187,7 +187,7 @@ static int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv) + req.t.tcm_ifindex = idx; + } + +- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return 2; + + return 0; +-- +1.8.3.1 + diff --git a/SOURCES/0029-libnetlink-don-t-confuse-variables-in-rtnl_talk.patch b/SOURCES/0029-libnetlink-don-t-confuse-variables-in-rtnl_talk.patch new file mode 100644 index 0000000..3f0c2c5 --- /dev/null +++ b/SOURCES/0029-libnetlink-don-t-confuse-variables-in-rtnl_talk.patch @@ -0,0 +1,62 @@ +From 5b5cbaf1e54a9c0fb169465913c1250c560b487a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:07:42 +0100 +Subject: [PATCH] libnetlink: don't confuse variables in rtnl_talk() + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 +Upstream Status: iproute2.git commit ed108cfc0260b + +commit ed108cfc0260b6b751647982b77d6363b1defb15 +Author: Nicolas Dichtel +Date: Thu Dec 3 17:13:48 2015 +0100 + + libnetlink: don't confuse variables in rtnl_talk() + + There is two variables named 'len' in rtnl_talk. In fact, commit + c079e121a73a didn't work. For example, it was possible to trigger + a seg fault with this command: + $ ip link set gre2 type ip6gre hoplimit 32 + + Let's rename the argument len to maxlen. + + Fixes: c079e121a73a ("libnetlink: add size argument to rtnl_talk") + Reported-by: Thomas Faivre + Signed-off-by: Nicolas Dichtel +--- + lib/libnetlink.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/libnetlink.c b/lib/libnetlink.c +index 97b79fd..b2a300e 100644 +--- a/lib/libnetlink.c ++++ b/lib/libnetlink.c +@@ -311,7 +311,7 @@ int rtnl_dump_filter_nc(struct rtnl_handle *rth, + } + + int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, +- struct nlmsghdr *answer, size_t len) ++ struct nlmsghdr *answer, size_t maxlen) + { + int status; + unsigned seq; +@@ -394,7 +394,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, + } else if (!err->error) { + if (answer) + memcpy(answer, h, +- MIN(len, h->nlmsg_len)); ++ MIN(maxlen, h->nlmsg_len)); + return 0; + } + +@@ -406,7 +406,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, + + if (answer) { + memcpy(answer, h, +- MIN(len, h->nlmsg_len)); ++ MIN(maxlen, h->nlmsg_len)); + return 0; + } + +-- +1.8.3.1 + diff --git a/SOURCES/0030-man-ss-Fix-explanation-when-no-options-specified.patch b/SOURCES/0030-man-ss-Fix-explanation-when-no-options-specified.patch new file mode 100644 index 0000000..35aa6d4 --- /dev/null +++ b/SOURCES/0030-man-ss-Fix-explanation-when-no-options-specified.patch @@ -0,0 +1,39 @@ +From 04ec23bf2b69254b9a92bf9ac2d720e1d6480ebc Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:08:34 +0100 +Subject: [PATCH] man ss: Fix explanation when no options specified + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291818 +Upstream Status: iproute2.git commit 814f9b9919b5f + +commit 814f9b9919b5f0eab6b9746b15e2cf91b087bc9a +Author: Vadim Kochan +Date: Tue Jul 21 16:46:28 2015 +0300 + + man ss: Fix explanation when no options specified + + Really by default ss dumps not only TCP sockets but any kind of socket + which is in ESTABLISHED state (TCP/UDP/UNIX). + + Signed-off-by: Vadim Kochan + Reported-by: Miha Marolt +--- + man/man8/ss.8 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/man8/ss.8 b/man/man8/ss.8 +index bd1f2a9..62c6ad8 100644 +--- a/man/man8/ss.8 ++++ b/man/man8/ss.8 +@@ -13,7 +13,7 @@ It can display more TCP and state informations than other tools. + + .SH OPTIONS + When no option is used ss displays a list of +-open non-listening TCP sockets that have established connection. ++open non-listening sockets (e.g. TCP/UNIX/UDP) that have established connection. + .TP + .B \-h, \-\-help + Show summary of options. +-- +1.8.3.1 + diff --git a/SOURCES/0031-iproute-restrict-hoplimit-values-to-be-in-range-0-25.patch b/SOURCES/0031-iproute-restrict-hoplimit-values-to-be-in-range-0-25.patch new file mode 100644 index 0000000..f737d90 --- /dev/null +++ b/SOURCES/0031-iproute-restrict-hoplimit-values-to-be-in-range-0-25.patch @@ -0,0 +1,46 @@ +From 5498e4f0b6d4fe1955c1719c54932fb9812f1dab Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:19:36 +0100 +Subject: [PATCH] iproute: restrict hoplimit values to be in range [0; 255] + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291832 +Upstream Status: iproute2.git commit ea6cbab792f7b + +commit ea6cbab792f7bb8813f1b24cc1f4bd4caad8ccbe +Author: Phil Sutter +Date: Tue Nov 24 15:45:31 2015 +0100 + + iproute: restrict hoplimit values to be in range [0; 255] + + Technically, the range of possible hoplimit values are defined by IPv4 + and IPv6 header formats. Both define the field to be eight bits in size, + which leads to a value range of [0;255]. Setting a packet's hoplimit + field to 0 though makes not much sense, as the next hop would + immediately drop the packet. Therefore Linux uses 0 as a special value + indicating to use the system's default hoplimit (configurable via + sysctl). In iproute, setting the hoplimit of a route to 0 is equivalent + to omitting the hoplimit parameter alltogether, so it is actually not + necessary to allow that value to be specified, but keep it anyway for + backwards compatibility. + + Signed-off-by: Phil Sutter +--- + ip/iproute.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index 367b922..78b288a 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -805,7 +805,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) + mxlock |= (1< 255) + invarg("\"hoplimit\" value is invalid\n", *argv); + rta_addattr32(mxrta, sizeof(mxbuf), RTAX_HOPLIMIT, hoplimit); + } else if (strcmp(*argv, "advmss") == 0) { +-- +1.8.3.1 + diff --git a/SOURCES/0032-iproute2-ip-route.8.in-minor-fixes.patch b/SOURCES/0032-iproute2-ip-route.8.in-minor-fixes.patch new file mode 100644 index 0000000..d588ddc --- /dev/null +++ b/SOURCES/0032-iproute2-ip-route.8.in-minor-fixes.patch @@ -0,0 +1,49 @@ +From 09a56dfad65188e4055cde50c0c15e10746205c7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:19:36 +0100 +Subject: [PATCH] iproute2: ip-route.8.in: minor fixes + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291832 +Upstream Status: iproute2.git commit 4b8000f37ad5e + +commit 4b8000f37ad5efe65c5dec0a1ea37192a9e05ae2 +Author: Richard Godbee +Date: Sun Aug 25 22:40:19 2013 -0400 + + iproute2: ip-route.8.in: minor fixes + + In SYNOPSIS section: + + - Add 'reordering' + - Add missing '[' before 'quickack' + + Signed-off-by: Richard Godbee +--- + man/man8/ip-route.8.in | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in +index 24306bc..1275306 100644 +--- a/man/man8/ip-route.8.in ++++ b/man/man8/ip-route.8.in +@@ -97,6 +97,8 @@ replace " } " + .IR TIME " ] [ " + .B rttvar + .IR TIME " ] [ " ++.B reordering ++.IR NUMBER " ] [ " + .B window + .IR NUMBER " ] [ " + .B cwnd +@@ -110,7 +112,7 @@ replace " } " + .B initcwnd + .IR NUMBER " ] [ " + .B initrwnd +-.IR NUMBER " ]" ++.IR NUMBER " ] [ " + .B quickack + .IR BOOL " ]" + +-- +1.8.3.1 + diff --git a/SOURCES/0033-ip-route-enable-per-route-ecn-settings-via-features-.patch b/SOURCES/0033-ip-route-enable-per-route-ecn-settings-via-features-.patch new file mode 100644 index 0000000..fa402b4 --- /dev/null +++ b/SOURCES/0033-ip-route-enable-per-route-ecn-settings-via-features-.patch @@ -0,0 +1,150 @@ +From 5ce779716791bd07324bc6141e31336aa2f9c31e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:19:36 +0100 +Subject: [PATCH] ip route: enable per-route ecn settings via 'features' option + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291832 +Upstream Status: iproute2.git commit 29d1f730b8757 + +commit 29d1f730b87572a4e8165859dc04b0c89533ea4e +Author: Florian Westphal +Date: Thu Nov 6 22:15:32 2014 +0100 + + ip route: enable per-route ecn settings via 'features' option + + This permits to selectively enable explicit congestion notification via + the routing table. + + If this ecn feature is not set, the kernel will use the tcp_ecn sysctl + to decide wheter to use ECN when establising a TCP connection. + + At the time of this writing, the kernel supports ecn and allfrags, but + allfrags is of dubious value and not implemented here. + + Example: + + ip route change 192.168.2.0/24 dev eth0 features ecn + + Signed-off-by: Florian Westphal +--- + ip/iproute.c | 32 ++++++++++++++++++++++++++++++++ + man/man8/ip-route.8.in | 18 ++++++++++++++++++ + 2 files changed, 50 insertions(+) + +diff --git a/ip/iproute.c b/ip/iproute.c +index 78b288a..ea69aa3 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -80,6 +80,7 @@ static void usage(void) + fprintf(stderr, " [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n"); + fprintf(stderr, " [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n"); + fprintf(stderr, " [ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]\n"); ++ fprintf(stderr, " [ features FEATURES ]\n"); + fprintf(stderr, " [ quickack BOOL ]\n"); + fprintf(stderr, "TYPE := [ unicast | local | broadcast | multicast | throw |\n"); + fprintf(stderr, " unreachable | prohibit | blackhole | nat ]\n"); +@@ -89,6 +90,7 @@ static void usage(void) + fprintf(stderr, "RTPROTO := [ kernel | boot | static | NUMBER ]\n"); + fprintf(stderr, "TIME := NUMBER[s|ms]\n"); + fprintf(stderr, "BOOL := [1|0]\n"); ++ fprintf(stderr, "FEATURES := ecn\n"); + exit(-1); + } + +@@ -280,6 +282,19 @@ static int calc_host_len(const struct rtmsg *r) + return -1; + } + ++static void print_rtax_features(FILE *fp, unsigned int features) ++{ ++ unsigned int of = features; ++ ++ if (features & RTAX_FEATURE_ECN) { ++ fprintf(fp, " ecn"); ++ features &= ~RTAX_FEATURE_ECN; ++ } ++ ++ if (features) ++ fprintf(fp, " 0x%x", of); ++} ++ + int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + { + FILE *fp = (FILE*)arg; +@@ -538,6 +553,9 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + + val = *(unsigned*)RTA_DATA(mxrta[i]); + switch (i) { ++ case RTAX_FEATURES: ++ print_rtax_features(fp, val); ++ break; + case RTAX_HOPLIMIT: + if ((int)val == -1) + val = 0; +@@ -888,6 +906,20 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) + if (get_unsigned(&win, *argv, 0)) + invarg("\"initrwnd\" value is invalid\n", *argv); + rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITRWND, win); ++ } else if (matches(*argv, "features") == 0) { ++ unsigned int features = 0; ++ ++ while (argc > 0) { ++ NEXT_ARG(); ++ ++ if (strcmp(*argv, "ecn") == 0) ++ features |= RTAX_FEATURE_ECN; ++ else ++ invarg("\"features\" value not valid\n", *argv); ++ break; ++ } ++ ++ rta_addattr32(mxrta, sizeof(mxbuf), RTAX_FEATURES, features); + } else if (matches(*argv, "quickack") == 0) { + unsigned quickack; + NEXT_ARG(); +diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in +index 1275306..05fd879 100644 +--- a/man/man8/ip-route.8.in ++++ b/man/man8/ip-route.8.in +@@ -113,6 +113,8 @@ replace " } " + .IR NUMBER " ] [ " + .B initrwnd + .IR NUMBER " ] [ " ++.B features ++.IR FEATURES " ] [ " + .B quickack + .IR BOOL " ]" + +@@ -140,6 +142,10 @@ throw " | " unreachable " | " prohibit " | " blackhole " | " nat " ]" + .BR kernel " | " boot " | " static " |" + .IR NUMBER " ]" + ++.ti -8 ++.IR FEATURES " := [ " ++.BR ecn " | ]" ++ + + .SH DESCRIPTION + .B ip route +@@ -411,6 +417,18 @@ Actual window size is this value multiplied by the MSS of the connection. + The default value is zero, meaning to use Slow Start value. + + .TP ++.BI features " FEATURES " (3.18+ only) ++Enable or disable per-route features. Only available feature at this ++time is ++.B ecn ++to enable explicit congestion notification when initiating connections to the ++given destination network. ++When responding to a connection request from the given network, ecn will ++also be used even if the ++.B net.ipv4.tcp_ecn ++sysctl is set to 0. ++ ++.TP + .BI quickack " BOOL " "(3.11+ only)" + Enable or disable quick ack for connections to this destination. + +-- +1.8.3.1 + diff --git a/SOURCES/0034-ip-route-add-congestion-control-metric.patch b/SOURCES/0034-ip-route-add-congestion-control-metric.patch new file mode 100644 index 0000000..310bf81 --- /dev/null +++ b/SOURCES/0034-ip-route-add-congestion-control-metric.patch @@ -0,0 +1,137 @@ +From 863f0cafefd9293451fe4682b02c8186a68ad30a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:19:36 +0100 +Subject: [PATCH] ip: route: add congestion control metric + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291832 +Upstream Status: iproute2.git commit 6ef87f9cce213 + +commit 6ef87f9cce213cae66098d08e0abc36d67b95244 +Author: Daniel Borkmann +Date: Fri Jan 9 00:13:06 2015 +0100 + + ip: route: add congestion control metric + + This patch adds configuration and dumping of congestion control metric + for ip route, for example: + + ip route add dev foo congctl [lock] dctcp + + Reference: http://thread.gmane.org/gmane.linux.network/344733 + Signed-off-by: Daniel Borkmann +--- + ip/iproute.c | 22 ++++++++++++++++++---- + man/man8/ip-route.8.in | 19 ++++++++++++++++++- + 2 files changed, 36 insertions(+), 5 deletions(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index ea69aa3..d3a5e1c 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -53,6 +53,7 @@ static const char *mx_names[RTAX_MAX+1] = { + [RTAX_RTO_MIN] = "rto_min", + [RTAX_INITRWND] = "initrwnd", + [RTAX_QUICKACK] = "quickack", ++ [RTAX_CC_ALGO] = "congctl", + }; + static void usage(void) __attribute__((noreturn)); + +@@ -80,8 +81,7 @@ static void usage(void) + fprintf(stderr, " [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n"); + fprintf(stderr, " [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n"); + fprintf(stderr, " [ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]\n"); +- fprintf(stderr, " [ features FEATURES ]\n"); +- fprintf(stderr, " [ quickack BOOL ]\n"); ++ fprintf(stderr, " [ features FEATURES ] [ quickack BOOL ] [ congctl NAME ]\n"); + fprintf(stderr, "TYPE := [ unicast | local | broadcast | multicast | throw |\n"); + fprintf(stderr, " unreachable | prohibit | blackhole | nat ]\n"); + fprintf(stderr, "TABLE_ID := [ local | main | default | all | NUMBER ]\n"); +@@ -539,7 +539,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + mxlock = *(unsigned*)RTA_DATA(mxrta[RTAX_LOCK]); + + for (i=2; i<= RTAX_MAX; i++) { +- unsigned val; ++ __u32 val; + + if (mxrta[i] == NULL) + continue; +@@ -548,10 +548,12 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + fprintf(fp, " %s", mx_names[i]); + else + fprintf(fp, " metric %d", i); ++ + if (mxlock & (1< +Date: Thu, 18 Feb 2016 14:34:13 +0100 +Subject: [PATCH] ip-link: remove warning message + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291832 +Upstream Status: iproute2.git commit eb85526923d1d + +This fixes a warning generated by the previous backport. + +commit eb85526923d1de1857c2b1e6860a471f2a0ae1b9 +Author: Zhang Shengju +Date: Thu Jan 21 02:23:49 2016 +0000 + + ip-link: remove warning message + + the warning was: + iproute.c:301:12: warning: 'val' may be used uninitialized in this + function [-Wmaybe-uninitialized] + features &= ~RTAX_FEATURE_ECN; + ^ + iproute.c:575:10: note: 'val' was declared here + __u32 val; + ^ + + Signed-off-by: Zhang Shengju +--- + ip/iproute.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index d3a5e1c..99d93c8 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -539,7 +539,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + mxlock = *(unsigned*)RTA_DATA(mxrta[RTAX_LOCK]); + + for (i=2; i<= RTAX_MAX; i++) { +- __u32 val; ++ __u32 val = 0U; + + if (mxrta[i] == NULL) + continue; +-- +1.8.3.1 + diff --git a/SOURCES/0036-route-ignore-RTAX_HOPLIMIT-of-value-1.patch b/SOURCES/0036-route-ignore-RTAX_HOPLIMIT-of-value-1.patch new file mode 100644 index 0000000..907e94f --- /dev/null +++ b/SOURCES/0036-route-ignore-RTAX_HOPLIMIT-of-value-1.patch @@ -0,0 +1,65 @@ +From 49ec02d14079797fe7290190d13f89ce5c3b57f3 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 14:19:36 +0100 +Subject: [PATCH] route: ignore RTAX_HOPLIMIT of value -1 + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291832 +Upstream Status: iproute2.git commit 0f7543322c5fd + +commit 0f7543322c5fd64d70672578979cf74226f54b64 +Author: Phil Sutter +Date: Wed Dec 2 13:50:22 2015 +0100 + + route: ignore RTAX_HOPLIMIT of value -1 + + Older kernels use -1 internally as indicator to use the sysctl default, + but they still export the setting. Newer kernels use 0 to indicate that + (which is why the conversion from -1 to 0 was done here), but they also + stopped exporting the value. Since the meaning of -1 is clear, treat it + equally like default on newer kernels (which is to not print anything). + + Signed-off-by: Phil Sutter +--- + ip/iproute.c | 17 ++++++++--------- + 1 file changed, 8 insertions(+), 9 deletions(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index 99d93c8..d87a099 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -544,24 +544,23 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + if (mxrta[i] == NULL) + continue; + +- if (i < sizeof(mx_names)/sizeof(char*) && mx_names[i]) +- fprintf(fp, " %s", mx_names[i]); +- else +- fprintf(fp, " metric %d", i); +- + if (mxlock & (1< +Date: Thu, 18 Feb 2016 14:19:36 +0100 +Subject: [PATCH] route: Fix printing of locked entries + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1291832 +Upstream Status: iproute2.git commit ed6b8652f7d54 + +commit ed6b8652f7d5470cac7fd763b4a47d07a3a0bfb6 +Author: Phil Sutter +Date: Sat Dec 12 14:09:48 2015 +0100 + + route: Fix printing of locked entries + + Commit 0f7543322c5fd ("route: ignore RTAX_HOPLIMIT of value -1") + accidentally reordered fprintf statements. This patch restores the + original ordering. + + Fixes: 0f7543322c5fd ("route: ignore RTAX_HOPLIMIT of value -1") + Signed-off-by: Phil Sutter +--- + ip/iproute.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index d87a099..27e04a8 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -544,8 +544,6 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + if (mxrta[i] == NULL) + continue; + +- if (mxlock & (1< +Date: Thu, 18 Feb 2016 15:29:02 +0100 +Subject: [PATCH] man: tc: add man page for fq pacer + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1261520 +Upstream Status: iproute2.git commit 484b3f922cfd5 +Conflicts: Changed context due to other missing man pages in RHEL7. + +commit 484b3f922cfd5a38a73de5981e471f99ecfe3e8b +Author: Florian Westphal +Date: Thu Sep 24 02:10:28 2015 +0200 + + man: tc: add man page for fq pacer + + Partially based on kernel Kconfig help text, code comments and + git commit messages from Eric Dumazet. + + Joint work with Phil Sutter. + + Signed-off-by: Phil Sutter + Signed-off-by: Florian Westphal +--- + man/man8/Makefile | 1 + + man/man8/tc-fq.8 | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + man/man8/tc.8 | 1 + + 3 files changed, 94 insertions(+) + create mode 100644 man/man8/tc-fq.8 + +diff --git a/man/man8/Makefile b/man/man8/Makefile +index ff80c98..23ac83e 100644 +--- a/man/man8/Makefile ++++ b/man/man8/Makefile +@@ -2,6 +2,7 @@ TARGETS = ip-address.8 ip-link.8 ip-route.8 + + MAN8PAGES = $(TARGETS) ip.8 arpd.8 lnstat.8 routel.8 rtacct.8 rtmon.8 ss.8 \ + tc.8 tc-bfifo.8 tc-cbq.8 tc-cbq-details.8 tc-choke.8 tc-codel.8 \ ++ tc-fq.8 \ + tc-drr.8 tc-ematch.8 tc-fq_codel.8 tc-hfsc.8 tc-htb.8 \ + tc-netem.8 tc-pfifo.8 tc-pfifo_fast.8 tc-prio.8 tc-red.8 \ + tc-sfb.8 tc-sfq.8 tc-stab.8 tc-tbf.8 \ +diff --git a/man/man8/tc-fq.8 b/man/man8/tc-fq.8 +new file mode 100644 +index 0000000..993beb6 +--- /dev/null ++++ b/man/man8/tc-fq.8 +@@ -0,0 +1,92 @@ ++.TH FQ 8 "10 Sept 2015" "iproute2" "Linux" ++.SH NAME ++Fair Queuing (FQ) \- Traffic Pacing ++.SH SYNOPSIS ++.B tc qdisc ... fq ++[ ++.B limit ++PACKETS ] [ ++.B flow_limit ++PACKETS ] [ ++.B quantum ++BYTES ] [ ++.B initial_quantum ++BYTES ] [ ++.B maxrate ++RATE ] [ ++.B buckets ++NUMBER ] [ ++.B pacing ++| ++.B nopacing ++] ++ ++.SH DESCRIPTION ++FQ (Fair Queue) is a classless packet scheduler meant to be mostly ++used for locally generated traffic. It is designed to achieve per flow pacing. ++FQ does flow separation, and is able to respect pacing requirements set by TCP stack. ++All packets belonging to a socket are considered as a 'flow'. ++For non local packets (router workload), packet rxhash is used as fallback. ++ ++An application can specify a maximum pacing rate using the ++.B SO_MAX_PACING_RATE ++setsockopt call. This packet scheduler adds delay between packets to ++respect rate limitation set by TCP stack. ++ ++Dequeueing happens in a round-robin fashion. ++A special FIFO queue is reserved for high priority packets ( ++.B TC_PRIO_CONTROL ++priority), such packets are always dequeued first. ++ ++FQ is non-work-conserving. ++ ++TCP pacing is good for flows having idle times, as the congestion ++window permits TCP stack to queue a possibly large number of packets. ++This removes the 'slow start after idle' choice, badly hitting ++large BDP flows and applications delivering chunks of data such as video streams. ++ ++.SH PARAMETERS ++.SS limit ++Hard limit on the real queue size. When this limit is reached, new packets ++are dropped. If the value is lowered, packets are dropped so that the new limit is ++met. Default is 10000 packets. ++.SS flow_limit ++Hard limit on the maximum number of packets queued per flow. ++Default value is 100. ++.SS quantum ++The credit per dequeue RR round, i.e. the amount of bytes a flow is allowed to ++dequeue at once. A larger value means a longer time period before the next flow ++will be served. ++Default is 2 * interface MTU bytes. ++.SS initial_quantum ++The initial sending rate credit, i.e. the amount of bytes a new flow is allowed ++to dequeue initially. ++This is specifically meant to allow using IW10 without added delay. ++Default is 10 * interface MTU, i.e. 15140 for 'standard' ethernet. ++.SS maxrate ++Maximum sending rate of a flow. Default is unlimited. ++Application specific setting via ++.B SO_MAX_PACING_RATE ++is ignored only if it is larger than this value. ++.SS buckets ++The size of the hash table used for flow lookups. Each bucket is assigned a ++red-black tree for efficient collision sorting. ++Default: 1024. ++.SS [no]pacing ++Enable or disable flow pacing. Default is enabled. ++.SH EXAMPLES ++#tc qdisc add dev eth0 root fq ++.br ++#tc -s -d qdisc ++.br ++qdisc fq 8003: dev eth0 root refcnt 2 limit 10000p flow_limit 100p buckets 1024 quantum 3028 initial_quantum 15140 ++ Sent 503727981 bytes 1146972 pkt (dropped 0, overlimits 0 requeues 54452) ++ backlog 0b 0p requeues 54452 ++ 1289 flows (1289 inactive, 0 throttled) ++ 0 gc, 31 highprio, 27411 throttled ++.br ++.SH SEE ALSO ++.BR tc (8), ++.BR socket (7) ++.SH AUTHORS ++FQ was written by Eric Dumazet. +diff --git a/man/man8/tc.8 b/man/man8/tc.8 +index dfb6e20..80eaa3b 100644 +--- a/man/man8/tc.8 ++++ b/man/man8/tc.8 +@@ -589,6 +589,7 @@ was written by Alexey N. Kuznetsov and added in Linux 2.2. + .BR tc-codel (8), + .BR tc-drr (8), + .BR tc-ematch (8), ++.BR tc-fq (8), + .BR tc-fq_codel (8), + .BR tc-hfsc (7), + .BR tc-hfsc (8), +-- +1.8.3.1 + diff --git a/SOURCES/0039-man-fix-whatis-for-fq.patch b/SOURCES/0039-man-fix-whatis-for-fq.patch new file mode 100644 index 0000000..3c0f8a9 --- /dev/null +++ b/SOURCES/0039-man-fix-whatis-for-fq.patch @@ -0,0 +1,34 @@ +From 15d41b84bca17d554053c4726ff57b1a16ead28b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 15:29:58 +0100 +Subject: [PATCH] man: fix whatis for fq + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1261520 +Upstream Status: iproute2.git commit e947d8947d341 + +commit e947d8947d34114e2ea7c5508dfbb9b10b4611c2 +Author: Stephen Hemminger +Date: Wed Jan 6 10:29:06 2016 -0800 + + man: fix whatis for fq + + The FQ man page was not following whatis formatting rules. +--- + man/man8/tc-fq.8 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/man8/tc-fq.8 b/man/man8/tc-fq.8 +index 993beb6..f058a05 100644 +--- a/man/man8/tc-fq.8 ++++ b/man/man8/tc-fq.8 +@@ -1,6 +1,6 @@ + .TH FQ 8 "10 Sept 2015" "iproute2" "Linux" + .SH NAME +-Fair Queuing (FQ) \- Traffic Pacing ++FQ \- Fair Queue traffic policing + .SH SYNOPSIS + .B tc qdisc ... fq + [ +-- +1.8.3.1 + diff --git a/SOURCES/0040-batch-support-quoted-strings.patch b/SOURCES/0040-batch-support-quoted-strings.patch new file mode 100644 index 0000000..1d0a578 --- /dev/null +++ b/SOURCES/0040-batch-support-quoted-strings.patch @@ -0,0 +1,70 @@ +From a8e630258cafd1e93e85fd8ee7227583a28fb7cd Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 15:31:08 +0100 +Subject: [PATCH] batch: support quoted strings + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1272593 +Upstream Status: iproute2.git commit 39e3d3836c138 + +commit 39e3d3836c1384506d0a76a496133c5361940770 +Author: Christophe Gouault +Date: Fri Oct 2 11:59:37 2015 +0200 + + batch: support quoted strings + + Support quoting strings with " or ' in an iproute2 batch file. + + Enables to configure empty crypto keys (for ESP-null) or keys with + spaces: + + xfrm state add src 1.1.1.1 dst 2.2.2.2 proto ah spi 0x1 \ + mode tunnel auth hmac(sha1) "r4ezR/@kd6'749f2 6zf$" + + xfrm state add src 5.5.5.5 dst 2.2.2.2 proto esp spi 0x2 \ + mode tunnel enc cipher_null "" + + Signed-off-by: Christophe Gouault +--- + lib/utils.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +diff --git a/lib/utils.c b/lib/utils.c +index 8c5cd46..1cd4fdd 100644 +--- a/lib/utils.c ++++ b/lib/utils.c +@@ -907,12 +907,31 @@ int makeargs(char *line, char *argv[], int maxargs) + char *cp; + int argc = 0; + +- for (cp = strtok(line, ws); cp; cp = strtok(NULL, ws)) { ++ for (cp = line + strspn(line, ws); *cp; cp += strspn(cp, ws)) { + if (argc >= (maxargs - 1)) { + fprintf(stderr, "Too many arguments to command\n"); + exit(1); + } ++ ++ /* word begins with quote */ ++ if (*cp == '\'' || *cp == '"') { ++ char quote = *cp++; ++ ++ argv[argc++] = cp; ++ /* find ending quote */ ++ cp = strchr(cp, quote); ++ if (cp == NULL) { ++ fprintf(stderr, "Unterminated quoted string\n"); ++ exit(1); ++ } ++ *cp++ = 0; ++ continue; ++ } ++ + argv[argc++] = cp; ++ /* find end of word */ ++ cp += strcspn(cp, ws); ++ *cp++ = 0; + } + argv[argc] = NULL; + +-- +1.8.3.1 + diff --git a/SOURCES/0041-tc-add-a-man-page-for-basic-filter.patch b/SOURCES/0041-tc-add-a-man-page-for-basic-filter.patch new file mode 100644 index 0000000..4d65fb3 --- /dev/null +++ b/SOURCES/0041-tc-add-a-man-page-for-basic-filter.patch @@ -0,0 +1,64 @@ +From 952fd52029d937cf5ea2b9b79c3afdb810d6f88b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 15:45:21 +0100 +Subject: [PATCH] tc: add a man page for basic filter + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1286711 +Upstream Status: iproute2.git commit 55b35567ad05d + +commit 55b35567ad05d926c1a73828cef2d4370d928b54 +Author: Phil Sutter +Date: Fri Oct 23 19:47:08 2015 +0200 + + tc: add a man page for basic filter + + Cc: Thomas Graf + Signed-off-by: Phil Sutter +--- + man/man8/tc-basic.8 | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + create mode 100644 man/man8/tc-basic.8 + +diff --git a/man/man8/tc-basic.8 b/man/man8/tc-basic.8 +new file mode 100644 +index 0000000..fb39eaa +--- /dev/null ++++ b/man/man8/tc-basic.8 +@@ -0,0 +1,34 @@ ++.TH "Basic classifier in tc" 8 "21 Oct 2015" "iproute2" "Linux" ++ ++.SH NAME ++basic \- basic traffic control filter ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " " filter " ... " basic " [ " match ++.IR EMATCH_TREE " ] [ " ++.B action ++.IR ACTION_SPEC " ] [ " ++.B classid ++.IR CLASSID " ]" ++.SH DESCRIPTION ++The ++.B basic ++filter allows to classify packets using the extended match infrastructure. ++.SH OPTIONS ++.TP ++.BI action " ACTION_SPEC" ++Apply an action from the generic actions framework on matching packets. ++.TP ++.BI classid " CLASSID" ++Push matching packets into the class identified by ++.IR CLASSID . ++.TP ++.BI match " EMATCH_TREE" ++Match packets using the extended match infrastructure. See ++.BR tc-ematch (8) ++for a detailed description of the allowed syntax in ++.IR EMATCH_TREE . ++.SH SEE ALSO ++.BR tc (8), ++.BR tc-ematch (8) +-- +1.8.3.1 + diff --git a/SOURCES/0042-tc-add-a-man-page-for-cgroup-filter.patch b/SOURCES/0042-tc-add-a-man-page-for-cgroup-filter.patch new file mode 100644 index 0000000..931f727 --- /dev/null +++ b/SOURCES/0042-tc-add-a-man-page-for-cgroup-filter.patch @@ -0,0 +1,110 @@ +From 5479cdfe6cede09f61a3bf890d55dab651669a13 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 15:45:21 +0100 +Subject: [PATCH] tc: add a man page for cgroup filter + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1286711 +Upstream Status: iproute2.git commit 5774f09ee8c6d + +commit 5774f09ee8c6d36c34986bacea423b5b4dd1cb48 +Author: Phil Sutter +Date: Fri Oct 23 19:47:09 2015 +0200 + + tc: add a man page for cgroup filter + + Cc: Thomas Graf + Signed-off-by: Phil Sutter +--- + man/man8/tc-cgroup.8 | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 80 insertions(+) + create mode 100644 man/man8/tc-cgroup.8 + +diff --git a/man/man8/tc-cgroup.8 b/man/man8/tc-cgroup.8 +new file mode 100644 +index 0000000..2bea7d4 +--- /dev/null ++++ b/man/man8/tc-cgroup.8 +@@ -0,0 +1,80 @@ ++.TH "Cgroup classifier in tc" 8 " 21 Oct 2015" "iproute2" "Linux" ++ ++.SH NAME ++cgroup \- control group based traffic control filter ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " " filter " ... " cgroup " [ " match ++.IR EMATCH_TREE " ] [ " ++.B action ++.IR ACTION_SPEC " ]" ++.SH DESCRIPTION ++This filter serves as a hint to ++.B tc ++that the assigned class ID of the net_cls control group the process the packet ++originates from belongs to should be used for classification. Obviously, it is ++useful for locally generated packets only. ++.SH OPTIONS ++.TP ++.BI action " ACTION_SPEC" ++Apply an action from the generic actions framework on matching packets. ++.TP ++.BI match " EMATCH_TREE" ++Match packets using the extended match infrastructure. See ++.BR tc-ematch (8) ++for a detailed description of the allowed syntax in ++.IR EMATCH_TREE . ++.SH EXAMPLES ++In order to use this filter, a net_cls control group has to be created first and ++class as well as process ID(s) assigned to it. The following creates a net_cls ++cgroup named "foobar": ++ ++.RS ++.EX ++modprobe cls_cgroup ++mkdir /sys/fs/cgroup/net_cls ++mount -t cgroup -onet_cls net_cls /sys/fs/cgroup/net_cls ++mkdir /sys/fs/cgroup/net_cls/foobar ++.EE ++.RE ++ ++To assign a class ID to the created cgroup, a file named ++.I net_cls.classid ++has to be created which contains the class ID to be assigned as a hexadecimal, ++64bit wide number. The upper 32bits are reserved for the major handle, the ++remaining hold the minor. So a class ID of e.g. ++.B ff:be ++has to be written like so: ++.B 0xff00be ++(leading zeroes may be omitted). To continue the above example, the following ++assigns class ID 1:2 to foobar cgroup: ++ ++.RS ++.EX ++echo 0x10002 > /sys/fs/cgroup/net_cls/foobar/net_cls.classid ++.EE ++.RE ++ ++Finally some PIDs can be assigned to the given cgroup: ++ ++.RS ++.EX ++echo 1234 > /sys/fs/cgroup/net_cls/foobar/tasks ++echo 5678 > /sys/fs/cgroup/net_cls/foobar/tasks ++.EE ++.RE ++ ++Now by simply attaching a ++.B cgroup ++filter to a ++.B qdisc ++makes packets from PIDs 1234 and 5678 be pushed into class 1:2. ++ ++.SH SEE ALSO ++.BR tc (8), ++.BR tc-ematch (8), ++.br ++the file ++.I Documentation/cgroups/net_cls.txt ++of the Linux kernel tree +-- +1.8.3.1 + diff --git a/SOURCES/0043-tc-add-a-man-page-for-flow-filter.patch b/SOURCES/0043-tc-add-a-man-page-for-flow-filter.patch new file mode 100644 index 0000000..ed1e2bd --- /dev/null +++ b/SOURCES/0043-tc-add-a-man-page-for-flow-filter.patch @@ -0,0 +1,295 @@ +From 5703331fbb7957ff959aeda921b7aa28a78d2eb8 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 15:45:21 +0100 +Subject: [PATCH] tc: add a man page for flow filter + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1286711 +Upstream Status: iproute2.git commit 334ddc9b4d526 + +commit 334ddc9b4d526d0fe4487464c1c4e0c0fcb35a30 +Author: Phil Sutter +Date: Fri Oct 23 19:47:10 2015 +0200 + + tc: add a man page for flow filter + + Cc: Patrick McHardy + Signed-off-by: Phil Sutter +--- + man/man8/tc-flow.8 | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 265 insertions(+) + create mode 100644 man/man8/tc-flow.8 + +diff --git a/man/man8/tc-flow.8 b/man/man8/tc-flow.8 +new file mode 100644 +index 0000000..f1b7e2a +--- /dev/null ++++ b/man/man8/tc-flow.8 +@@ -0,0 +1,265 @@ ++.TH "Flow filter in tc" 8 "20 Oct 2015" "iproute2" "Linux" ++ ++.SH NAME ++flow \- flow based traffic control filter ++.SH SYNOPSIS ++.TP ++Mapping mode: ++ ++.RS ++.in +8 ++.ti -8 ++.BR tc " " filter " ... " "flow map key " ++.IR KEY " [ " OPS " ] [ " OPTIONS " ] " ++.RE ++.TP ++Hashing mode: ++ ++.RS ++.in +8 ++.ti -8 ++.BR tc " " filter " ... " "flow hash keys " ++.IR KEY_LIST " [ " ++.B perturb ++.IR secs " ] [ " OPTIONS " ] " ++.RE ++ ++.in +8 ++.ti -8 ++.IR OPS " := [ " OPS " ] " OP ++ ++.ti -8 ++.IR OPTIONS " := [ " ++.B divisor ++.IR NUM " ] [ " ++.B baseclass ++.IR ID " ] [ " ++.B match ++.IR EMATCH_TREE " ] [ " ++.B action ++.IR ACTION_SPEC " ]" ++ ++.ti -8 ++.IR KEY_LIST " := [ " KEY_LIST " ] " KEY ++ ++.ti -8 ++.IR OP " := { " ++.BR or " | " and " | " xor " | " rshift " | " addend " } " ++.I NUM ++ ++.ti -8 ++.IR ID " := " X : Y ++ ++.ti -8 ++.IR KEY " := { " ++.BR src " | " dst " | " proto " | " proto-src " | " proto-dst " | " iif " | " ++.BR priority " | " mark " | " nfct " | " nfct-src " | " nfct-dst " | " ++.BR nfct-proto-src " | " nfct-proto-dst " | " rt-classid " | " sk-uid " | " ++.BR sk-gid " | " vlan-tag " | " rxhash " }" ++.SH DESCRIPTION ++The ++.B flow ++classifier is meant to extend the ++.B SFQ ++hashing capabilities without hard-coding new hash functions. It also allows ++deterministic mappings of keys to classes. ++.SH OPTIONS ++.TP ++.BI action " ACTION_SPEC" ++Apply an action from the generic actions framework on matching packets. ++.TP ++.BI baseclass " ID" ++An offset for the resulting class ID. ++.I ID ++may be ++.BR root ", " none ++or a hexadecimal class ID in the form [\fIX\fB:\fR]\fIY\fR. If \fIX\fR is ++omitted, it is assumed to be zero. ++.TP ++.BI divisor " NUM" ++Number of buckets to use for sorting into. Keys are calculated modulo ++.IR NUM . ++.TP ++.BI "hash keys " KEY-LIST ++Perform a ++.B jhash2 ++operation over the keys in ++.IR KEY-LIST , ++the result (modulo the ++.B divisor ++if given) is taken as class ID, optionally offset by the value of ++.BR baseclass . ++It is possible to specify an interval (in seconds) after which ++.BR jhash2 's ++entropy source is recreated using the ++.B perturb ++parameter. ++.TP ++.BI "map key " KEY ++Packet data identified by ++.I KEY ++is translated into class IDs to push the packet into. The value may be mangled by ++.I OPS ++before using it for the mapping. They are applied in the order listed here: ++.RS ++.TP 4 ++.BI and " NUM" ++Perform bitwise ++.B AND ++operation with numeric value ++.IR NUM . ++.TP ++.BI or " NUM" ++Perform bitwise ++.B OR ++operation with numeric value ++.IR NUM . ++.TP ++.BI xor " NUM" ++Perform bitwise ++.B XOR ++operation with numeric value ++.IR NUM . ++.TP ++.BI rshift " NUM" ++Shift the value of ++.I KEY ++to the right by ++.I NUM ++bits. ++.TP ++.BI addend " NUM" ++Add ++.I NUM ++to the value of ++.IR KEY . ++ ++.RE ++.RS ++For the ++.BR or ", " and ", " xor " and " rshift ++operations, ++.I NUM ++is assumed to be an unsigned, 32bit integer value. For the ++.B addend ++operation, ++.I NUM ++may be much more complex: It may be prefixed by a minus ('-') sign to cause ++subtraction instead of addition and for keys of ++.BR src ", " dst ", " nfct-src " and " nfct-dst ++it may be given in IP address notation. See below for an illustrating example. ++.RE ++.TP ++.BI match " EMATCH_TREE" ++Match packets using the extended match infrastructure. See ++.BR tc-ematch (8) ++for a detailed description of the allowed syntax in ++.IR EMATCH_TREE . ++.SH KEYS ++In mapping mode, a single key is used (after optional permutation) to build a ++class ID. The resulting ID is deducible in most cases. In hashing more, a number ++of keys may be specified which are then hashed and the output used as class ID. ++This ID is not deducible in beforehand, and may even change over time for a ++given flow if a ++.B perturb ++interval has been given. ++ ++The range of class IDs can be limited by the ++.B divisor ++option, which is used for a modulus. ++.TP ++.BR src ", " dst ++Use source or destination address as key. In case of IPv4 and TIPC, this is the ++actual address value. For IPv6, the 128bit address is folded into a 32bit value ++by XOR'ing the four 32bit words. In all other cases, the kernel-internal socket ++address is used (after folding into 32bits on 64bit systems). ++.TP ++.B proto ++Use the layer four protocol number as key. ++.TP ++.B proto-src ++Use the layer four source port as key. If not available, the kernel-internal ++socket address is used instead. ++.TP ++.B proto-dst ++Use the layer four destination port as key. If not available, the associated ++kernel-internal dst_entry address is used after XOR'ing with the packet's ++layer three protocol number. ++.TP ++.B iif ++Use the incoming interface index as key. ++.TP ++.B priority ++Use the packet's priority as key. Usually this is the IP header's DSCP/ECN ++value. ++.TP ++.B mark ++Use the netfilter ++.B fwmark ++as key. ++.TP ++.B nfct ++Use the associated conntrack entry address as key. ++.TP ++.BR nfct-src ", " nfct-dst ", " nfct-proto-src ", " nfct-proto-dst ++These are conntrack-aware variants of ++.BR src ", " dst ", " proto-src " and " proto-dst . ++In case of NAT, these are basically the packet header's values before NAT was ++applied. ++.TP ++.B rt-classid ++Use the packet's destination routing table entry's realm as key. ++.TP ++.B sk-uid ++.TQ ++.B sk-gid ++For locally generated packets, use the user or group ID the originating socket ++belongs to as key. ++.TP ++.B vlan-tag ++Use the packet's vlan ID as key. ++.TP ++.B rxhash ++Use the flow hash as key. ++ ++.SH EXAMPLES ++.TP ++Classic SFQ hash: ++ ++.EX ++tc filter add ... flow hash \\ ++ keys src,dst,proto,proto-src,proto-dst divisor 1024 ++.EE ++.TP ++Classic SFQ hash, but using information from conntrack to work properly in combination with NAT: ++ ++.EX ++tc filter add ... flow hash \\ ++ keys nfct-src,nfct-dst,proto,nfct-proto-src,nfct-proto-dst \\ ++ divisor 1024 ++.EE ++.TP ++Map destination IPs of 192.168.0.0/24 to classids 1-257: ++ ++.EX ++tc filter add ... flow map \\ ++ key dst addend -192.168.0.0 divisor 256 ++.EE ++.TP ++Alternative to the above: ++ ++.EX ++tc filter add ... flow map \\ ++ key dst and 0xff ++.EE ++.TP ++The same, but in reverse order: ++ ++.EX ++tc filter add ... flow map \\ ++ key dst and 0xff xor 0xff ++.EE ++.SH SEE ALSO ++.BR tc (8), ++.BR tc-ematch (8), ++.BR tc-sfq (8) +-- +1.8.3.1 + diff --git a/SOURCES/0044-tc-add-a-man-page-for-fw-filter.patch b/SOURCES/0044-tc-add-a-man-page-for-fw-filter.patch new file mode 100644 index 0000000..faa8c22 --- /dev/null +++ b/SOURCES/0044-tc-add-a-man-page-for-fw-filter.patch @@ -0,0 +1,96 @@ +From c2d169ccc97a4eca2755b9e54977634654277798 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 15:45:21 +0100 +Subject: [PATCH] tc: add a man page for fw filter + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1286711 +Upstream Status: iproute2.git commit 49891ba177283 + +commit 49891ba177283d3bece364c50e7c9909e2b733b5 +Author: Phil Sutter +Date: Fri Oct 23 19:47:12 2015 +0200 + + tc: add a man page for fw filter + + Cc: Alexey Kuznetsov + Signed-off-by: Phil Sutter +--- + man/man8/tc-fw.8 | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 66 insertions(+) + create mode 100644 man/man8/tc-fw.8 + +diff --git a/man/man8/tc-fw.8 b/man/man8/tc-fw.8 +new file mode 100644 +index 0000000..d742b47 +--- /dev/null ++++ b/man/man8/tc-fw.8 +@@ -0,0 +1,66 @@ ++.TH "Firewall mark classifier in tc" 8 "21 Oct 2015" "iproute2" "Linux" ++ ++.SH NAME ++fw \- fwmark traffic control filter ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " " filter " ... " fw " [ " classid ++.IR CLASSID " ] [ " ++.B action ++.IR ACTION_SPEC " ]" ++.SH DESCRIPTION ++the ++.B fw ++filter allows to classify packets based on a previously set ++.BR fwmark " by " iptables . ++If it is identical to the filter's ++.BR handle , ++the filter matches. ++.B iptables ++allows to mark single packets with the ++.B MARK ++target, or whole connections using ++.BR CONNMARK . ++The benefit of using this filter instead of doing the ++heavy-lifting with ++.B tc ++itself is that on one hand it might be convenient to keep packet filtering and ++classification in one place, possibly having to match a packet just once, and on ++the other users familiar with ++.BR iptables " but not " tc ++will have a less hard time adding QoS to their setups. ++.SH OPTIONS ++.TP ++.BI classid " CLASSID" ++Push matching packets to the class identified by ++.IR CLASSID . ++.TP ++.BI action " ACTION_SPEC" ++Apply an action from the generic actions framework on matching packets. ++.SH EXAMPLES ++Take e.g. the following tc filter statement: ++ ++.RS ++.EX ++tc filter add ... handle 6 fw classid 1:1 ++.EE ++.RE ++ ++will match if the packet's ++.B fwmark ++value is ++.BR 6 . ++This is a sample ++.B iptables ++statement marking packets coming in on eth0: ++ ++.RS ++.EX ++iptables -t mangle -A PREROUTING -i eth0 -j MARK --set-mark 6 ++.EE ++.RE ++.SH SEE ALSO ++.BR tc (8), ++.BR iptables (8), ++.BR iptables-extensions (8) +-- +1.8.3.1 + diff --git a/SOURCES/0045-tc-add-a-man-page-for-route-filter.patch b/SOURCES/0045-tc-add-a-man-page-for-route-filter.patch new file mode 100644 index 0000000..63a4318 --- /dev/null +++ b/SOURCES/0045-tc-add-a-man-page-for-route-filter.patch @@ -0,0 +1,104 @@ +From 0ea28e2d5095b69850f1ac2ebe49880f8b0f81f8 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 15:45:21 +0100 +Subject: [PATCH] tc: add a man page for route filter + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1286711 +Upstream Status: iproute2.git commit 02dddd6110309 + +commit 02dddd6110309ac37e72c418cfd96684dc763f3e +Author: Phil Sutter +Date: Fri Oct 23 19:47:13 2015 +0200 + + tc: add a man page for route filter + + Cc: Alexey Kuznetsov + Signed-off-by: Phil Sutter +--- + man/man8/tc-route.8 | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 74 insertions(+) + create mode 100644 man/man8/tc-route.8 + +diff --git a/man/man8/tc-route.8 b/man/man8/tc-route.8 +new file mode 100644 +index 0000000..b865cd1 +--- /dev/null ++++ b/man/man8/tc-route.8 +@@ -0,0 +1,74 @@ ++.TH "Route classifier in tc" 8 "21 Oct 2015" "iproute2" "Linux" ++ ++.SH NAME ++route \- route traffic control filter ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " " filter " ... " route " [ " from ++.IR REALM " | " ++.B fromif ++.IR TAG " ] [ " ++.B to ++.IR REALM " ] [ " ++.B classid ++.IR CLASSID " ] [ " ++.B action ++.IR ACTION_SPEC " ]" ++.SH DESCRIPTION ++Match packets based on routing table entries. This filter centers around the ++possibility to assign a ++.B realm ++to routing table entries. For any packet to be classified by this filter, a ++routing table lookup is performed and the returned ++.B realm ++is used to decide on whether the packet is a match or not. ++.SH OPTIONS ++.TP ++.BI action " ACTION_SPEC" ++Apply an action from the generic actions framework on matching packets. ++.TP ++.BI classid " CLASSID" ++Push matching packets into the class identified by ++.IR CLASSID . ++.TP ++.BI from " REALM" ++.TQ ++.BI fromif " TAG" ++Perform source route lookups. ++.I TAG ++is the name of an interface which must be present on the system at the time of ++.B tc ++invocation. ++.TP ++.BI to " REALM" ++Match if normal (i.e., destination) routing returns the given ++.IR REALM . ++.SH EXAMPLES ++Consider the subnet 192.168.2.0/24 being attached to eth0: ++ ++.RS ++.EX ++ip route add 192.168.2.0/24 dev eth0 realm 2 ++.EE ++.RE ++ ++The following ++.B route ++filter will then match packets from that subnet: ++ ++.RS ++.EX ++tc filter add ... route from 2 classid 1:2 ++.EE ++.RE ++ ++and pass packets on to class 1:2. ++.SH NOTES ++Due to implementation details, ++.B realm ++values must be in a range from 0 to 255, inclusive. Alternatively, a verbose ++name defined in /etc/iproute2/rt_realms may be given instead. ++.SH SEE ALSO ++.BR tc (8), ++.BR ip-route (8) +-- +1.8.3.1 + diff --git a/SOURCES/0046-tc-add-a-man-page-for-tcindex-filter.patch b/SOURCES/0046-tc-add-a-man-page-for-tcindex-filter.patch new file mode 100644 index 0000000..4b41f21 --- /dev/null +++ b/SOURCES/0046-tc-add-a-man-page-for-tcindex-filter.patch @@ -0,0 +1,88 @@ +From 86454e53f668896356e7ab1eaa8a687fdc266e2b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 15:45:21 +0100 +Subject: [PATCH] tc: add a man page for tcindex filter + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1286711 +Upstream Status: iproute2.git commit fc7a72f1ebcd8 + +commit fc7a72f1ebcd8eeba8788a68f83b0454a1bc7730 +Author: Phil Sutter +Date: Fri Oct 23 19:47:14 2015 +0200 + + tc: add a man page for tcindex filter + + Cc: Werner Almesberger + Signed-off-by: Phil Sutter +--- + man/man8/tc-tcindex.8 | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 58 insertions(+) + create mode 100644 man/man8/tc-tcindex.8 + +diff --git a/man/man8/tc-tcindex.8 b/man/man8/tc-tcindex.8 +new file mode 100644 +index 0000000..7fcf825 +--- /dev/null ++++ b/man/man8/tc-tcindex.8 +@@ -0,0 +1,58 @@ ++.TH "Traffic control index filter" 8 "21 Oct 2015" "iproute2" "Linux" ++ ++.SH NAME ++tcindex \- traffic control index filter ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " " filter " ... " tcindex " [ " hash ++.IR SIZE " ] [ " ++.B mask ++.IR MASK " ] [ " ++.B shift ++.IR SHIFT " ] [ " ++.BR pas_on " | " fall_through " ] [ " classid ++.IR CLASSID " ] [ " ++.B action ++.BR ACTION_SPEC " ]" ++.SH DESCRIPTION ++This filter allows to match packets based on their ++.B tcindex ++field value, i.e. the combination of the DSCP and ECN fields as present in IPv4 ++and IPv6 headers. ++.SH OPTIONS ++.TP ++.BI action " ACTION_SPEC" ++Apply an action from the generic actions framework on matching packets. ++.TP ++.BI classid " CLASSID" ++Push matching packets into the class identified by ++.IR CLASSID . ++.TP ++.BI hash " SIZE" ++Hash table size in entries to use. Defaults to 64. ++.TP ++.BI mask " MASK" ++An optional bitmask to binary ++.BR AND " to the packet's " tcindex ++field before use. ++.TP ++.BI shift " SHIFT" ++The number of bits to right-shift a packet's ++.B tcindex ++value before use. If a ++.B mask ++has been set, masking is done before shifting. ++.TP ++.B pass_on ++If this flag is set, failure to find a class for the resulting ID will make the ++filter fail and lead to the next filter being consulted. ++.TP ++.B fall_through ++This is the opposite of ++.B pass_on ++and the default. The filter will classify the packet even if there is no class ++present for the resulting class ID. ++ ++.SH SEE ALSO ++.BR tc (8) +-- +1.8.3.1 + diff --git a/SOURCES/0047-tc-add-a-man-page-for-u32-filter.patch b/SOURCES/0047-tc-add-a-man-page-for-u32-filter.patch new file mode 100644 index 0000000..32d3aea --- /dev/null +++ b/SOURCES/0047-tc-add-a-man-page-for-u32-filter.patch @@ -0,0 +1,693 @@ +From ccf0d2713af94b388d8220d30d8ca82be3c913fc Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 15:45:21 +0100 +Subject: [PATCH] tc: add a man page for u32 filter + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1286711 +Upstream Status: iproute2.git commit f15a23966fff3 + +commit f15a23966fff35e484812ec1d733d9438f658644 +Author: Phil Sutter +Date: Fri Oct 23 19:47:15 2015 +0200 + + tc: add a man page for u32 filter + + Cc: Alexey Kuznetsov + Signed-off-by: Phil Sutter +--- + man/man8/tc-u32.8 | 663 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 663 insertions(+) + create mode 100644 man/man8/tc-u32.8 + +diff --git a/man/man8/tc-u32.8 b/man/man8/tc-u32.8 +new file mode 100644 +index 0000000..47c8f2d +--- /dev/null ++++ b/man/man8/tc-u32.8 +@@ -0,0 +1,663 @@ ++.TH "Universal 32bit classifier in tc" 8 "25 Sep 2015" "iproute2" "Linux" ++ ++.SH NAME ++u32 \- universal 32bit traffic control filter ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " " filter " ... [ " handle ++.IR HANDLE " ] " ++.B u32 ++.IR OPTION_LIST " [ " ++.B offset ++.IR OFFSET " ] [ " ++.B hashkey ++.IR HASHKEY " ] [ " ++.B classid ++.IR CLASSID " ] [ " ++.B divisor ++.IR uint_value " ] [ " ++.B order ++.IR u32_value " ] [ " ++.B ht ++.IR HANDLE " ] [ " ++.B sample ++.IR SELECTOR " [ " ++.B divisor ++.IR uint_value " ] ] [ " ++.B link ++.IR HANDLE " ] [ " ++.B indev ++.IR ifname " ] [ " ++.BR help " ]" ++ ++.ti -8 ++.IR HANDLE " := { " ++\fIu12_hex_htid\fB:\fR[\fIu8_hex_hash\fB:\fR[\fIu12_hex_nodeid\fR] | \fB0x\fIu32_hex_value\fR } ++ ++.ti -8 ++.IR OPTION_LIST " := [ " OPTION_LIST " ] " OPTION ++ ++.ti -8 ++.IR HASHKEY " := [ " ++.B mask ++.IR u32_hex_value " ] [ " ++.B at ++.IR 4*int_value " ]" ++ ++.ti -8 ++.IR CLASSID " := { " ++.BR root " | " ++.BR none " | " ++[\fIu16_major\fR]\fB:\fIu16_minor\fR | \fIu32_hex_value\fR } ++ ++.ti -8 ++.IR OFFSET " := [ " ++.B plus ++.IR int_value " ] [ " ++.B at ++.IR 2*int_value " ] [ " ++.B mask ++.IR u16_hex_value " ] [ " ++.B shift ++.IR int_value " ] [ " ++.BR eat " ]" ++ ++.ti -8 ++.IR OPTION " := { " ++.B match ++.IR SELECTOR " | " ++.B action ++.IR ACTION " } " ++ ++.ti -8 ++.IR SELECTOR " := { " ++.B u32 ++.IR VAL_MASK_32 " | " ++.B u16 ++.IR VAL_MASK_16 " | " ++.B u8 ++.IR VAL_MASK_8 " | " ++.B ip ++.IR IP " | " ++.B ip6 ++.IR IP6 " | { " ++.BR tcp " | " udp " } " ++.IR TCPUDP " | " ++.B icmp ++.IR ICMP " | " ++.B mark ++.IR VAL_MASK_32 " | " ++.B ether ++.IR ETHER " }" ++ ++.ti -8 ++.IR IP " := { { " ++.BR src " | " dst " } { " default " | " any " | " all " | " ++.IR ip_address " [ " ++.BR / " { " ++.IR prefixlen " | " netmask " } ] } " AT " | { " ++.BR dsfield " | " ihl " | " protocol " | " precedence " | " ++.BR icmp_type " | " icmp_code " } " ++.IR VAL_MASK_8 " | { " ++.BR sport " | " dport " } " ++.IR VAL_MASK_16 " | " ++.BR nofrag " | " firstfrag " | " df " | " mf " }" ++ ++.ti -8 ++.IR IP6 " := { { " ++.BR src " | " dst " } { " default " | " any " | " all " | " ++.IR ip6_address " [/" prefixlen " ] } " AT " | " ++.B priority ++.IR VAL_MASK_8 " | { " ++.BR protocol " | " icmp_type " | " icmp_code " } " ++.IR VAL_MASK_8 " | " ++.B flowlabel ++.IR VAL_MASK_32 " | { " ++.BR sport " | " dport " } " ++.IR VAL_MASK_16 " }" ++ ++.ti -8 ++.IR TCPUDP " := { " ++.BR src " | " dst " } " ++.I VAL_MASK_16 ++ ++.ti -8 ++.IR ICMP " := { " ++.B type ++.IR VAL_MASK_8 " | " ++.B code ++.IR VAL_MASK_8 " }" ++ ++.ti -8 ++.IR ETHER " := { " ++.BR src " | " dst " } " ++.IR ether_address " " AT ++ ++.ti -8 ++.IR VAL_MASK_32 " := " u32_value " " u32_hex_mask " [ " AT " ]" ++ ++.ti -8 ++.IR VAL_MASK_16 " := " u16_value " " u16_hex_mask " [ " AT " ]" ++ ++.ti -8 ++.IR VAL_MASK_8 " := " u8_value " " u8_hex_mask " [ " AT " ]" ++ ++.ti -8 ++.IR AT " := [ " ++.BR at " [ " nexthdr+ " ] " ++.IR int_value " ]" ++.SH DESCRIPTION ++The Universal/Ugly 32bit filter allows to match arbitrary bitfields in the ++packet. Due to breaking everything down to values, masks and offsets, It is ++equally powerful and hard to use. Luckily many abstracting directives are ++present which allow defining rules on a higher level and therefore free the ++user from having to fiddle with bits and masks in many cases. ++ ++There are two general modes of invocation: The first mode creates a new filter ++to delegate packets to different destinations. Apart from the obvious ones, ++namely classifying the packet by specifying a ++.I CLASSID ++or calling an ++.BR action , ++one may ++.B link ++one filter to another one (or even a list of them), effectively organizing ++filters into a tree-like hierarchy. ++ ++Typically filter delegation is done by means of a hash table, which leads to the ++second mode of invocation: it merely serves to set up these hash tables. Filters ++can select a hash table and provide a key selector from which a hash is to be ++computed and used as key to lookup the table's bucket which contains filters for ++further processing. This is useful if a high number of filters is in use, as the ++overhead of performing the hash operation and table lookup becomes negligible in ++that case. Using hashtables with ++.B u32 ++basically involves the following pattern: ++.IP (1) 4 ++Creating a new hash table, specifying it's size using the ++.B divisor ++parameter and ideally a handle by which the table can be identified. If the ++latter is not given, the kernel chooses one on it's own, which has to be ++guessed later. ++.IP (2) 4 ++Creating filters which link to the created table in ++.I (1) ++using the ++.B link ++parameter and defining the packet data which the kernel will use to calculate ++the ++.BR hashkey . ++.IP (3) 4 ++Adding filters to buckets in the hash table from ++.IR (1) . ++In order to avoid having to know how exactly the kernel creates the hash key, ++there is the ++.B sample ++parameter, which gives sample data to hash and thereby define the table bucket ++the filter should be added to. ++ ++.RE ++In fact, even if not explicitly requested ++.B u32 ++creates a hash table for every ++.B priority ++a filter is being added with. The table's size is 1 though, so it is in fact ++merely a linked list. ++.SH VALUES ++Options and selectors require values to be specified in a specific format, which ++is often non-intuitive. Therefore the terminals in ++.I SYNOPSIS ++have been given descriptive names to indicate the required format and/or maximum ++allowed numeric value: Prefixes ++.IR u32 ", " u16 " and " u8 ++indicate four, two and single byte unsigned values. E.g. ++.I u16 ++indicates a two byte-sized value in range between 0 and 65535 (0xFFFF) ++inclusive. A prefix of ++.I int ++indicates a four byte signed value. A middle part of ++.I _hex_ ++indicates that the value is parsed in hexadecimal format. Otherwise, the ++value's base is automatically detected, i.e. values prefixed with ++.I 0x ++are considered hexadecimal, a leading ++.I 0 ++indicates octal format and decimal format otherwise. There are some values with ++special formatting as well: ++.IR ip_address " and " netmask ++are in dotted-quad formatting as usual for IPv4 addresses. An ++.I ip6_address ++is specified in common, colon-separated hexadecimal format. Finally, ++.I prefixlen ++is an unsigned, decimal integer value in range from 0 to the address width in ++bits (32 for IPv4 and 128 for IPv6). ++ ++Sometimes values need to be dividable by a certain number. In that case a name ++of the form ++.I N*val ++was chosen, indicating that ++.I val ++must be dividable by ++.IR N . ++Or the other way around: the resulting value must be a multiple of ++.IR N . ++.SH OPTIONS ++.B U32 ++recognizes the following options: ++.TP ++.BI handle " HANDLE" ++The handle is used to reference a filter and therefore must be unique. It ++consists of a hash table identifier ++.B htid ++and optional ++.B hash ++(which identifies the hash table's bucket) and ++.BR nodeid . ++All these values are parsed as unsigned, hexadecimal numbers with length 12bits ++( ++.BR htid " and " nodeid ) ++or 8bits ( ++.BR hash ). ++Alternatively one may specify a single, 32bit long hex number which contains ++the three fields bits in concatenated form. Other than the fields themselves, it ++has to be prefixed by ++.BR 0x . ++.TP ++.BI offset " OFFSET" ++Set an offset which defines where matches of subsequent filters are applied to. ++Therefore this option is useful only when combined with ++.BR link " or a combination of " ht " and " sample . ++The offset may be given explicitly by using the ++.B plus ++keyword, or extracted from the packet data with ++.BR at . ++It is possible to mangle the latter using ++.BR mask " and/or " shift ++keywords. By default, this offset is recorded but not implicitly applied. It is ++used only to substitute the ++.B nexthdr+ ++statement. Using the keyword ++.B eat ++though inverses this behaviour: the offset is applied always, and ++.B nexthdr+ ++will fall back to zero. ++.TP ++.BI hashkey " HASHKEY" ++Spefify what packet data to use to calculate a hash key for bucket lookup. The ++kernel adjusts the value according to the hash table's size. For this to work, ++the option ++.B link ++must be given. ++.TP ++.BI classid " CLASSID" ++Classify matching packets into the given ++.IR CLASSID , ++which consists of either 16bit ++.BR major " and " minor ++numbers or a single 32bit value combining both. ++.TP ++.BI divisor " u32_value" ++Specify a modulo value. Used when creating hash tables to define their size or ++for declaring a ++.B sample ++to calculate hash table keys from. Must be a power of two with exponent not ++exceeding eight. ++.TP ++.BI order " u32_value" ++A value to order filters by, ascending. Conflicts with ++.B handle ++which serves the same purpose. ++.TP ++.BI sample " SELECTOR" ++Used together with ++.B ht ++to specify which bucket to add this filter to. This allows one to avoid having ++to know how exactly the kernel calculates hashes. The additional ++.B divisor ++defaults to 256, so must be given for hash tables of different size. ++.TP ++.BI link " HANDLE" ++Delegate matching packets to filters in a hash table. ++.I HANDLE ++is used to only specify the hash table, so only ++.BR htid " may be given, " hash " and " nodeid ++have to be omitted. By default, bucket number 0 will be used and can be ++overridden by the ++.B hashkey ++option. ++.TP ++.BI indev " ifname" ++Filter on the incoming interface of the packet. Obviously works only for ++forwarded traffic. ++.TP ++.BI help ++Print a brief help text about possible options. ++.SH SELECTORS ++Basically the only real selector is ++.B u32 . ++All others merely provide a higher level syntax and are internally translated ++into ++.B u32 . ++.TP ++.BI u32 " VAL_MASK_32" ++.TQ ++.BI u16 " VAL_MASK_16" ++.TQ ++.BI u8 " VAL_MASK_8" ++Match packet data to a given value. The selector name defines the sample length ++to extract (32bits for ++.BR u32 , ++16bits for ++.B u16 ++and 8bits for ++.BR u8 ). ++Before comparing, the sample is binary AND'ed with the given mask. This way ++uninteresting bits can be cleared before comparison. The position of the sample ++is defined by the offset specified in ++.IR AT . ++.TP ++.BI ip " IP" ++.TQ ++.BI ip6 " IP6" ++Assume packet starts with an IPv4 ( ++.BR ip ) ++or IPv6 ( ++.BR ip6 ) ++header. ++.IR IP / IP6 ++then allows to match various header fields: ++.RS ++.TP ++.BI src " ADDR" ++.BI dst " ADDR" ++Compare Source or Destination Address fields against the value of ++.IR ADDR . ++The reserved words ++.BR default ", " any " and " all ++effectively match any address. Otherwise an IP address of the particular ++protocol is expected, optionally suffixed by a prefix length to match whole ++subnets. In case of IPv4 a netmask may also be given. ++.TP ++.BI dsfield " VAL_MASK_8" ++IPv4 only. Match the packet header's DSCP/ECN field. Synonyms to this are ++.BR tos " and " precedence . ++.TP ++.BI ihl " VAL_MASK_8" ++IPv4 only. Match the Internet Header Length field. Note that the value's unit is ++32bits, so to match a packet with 24byte header length ++.I u8_value ++has to be 6. ++.TP ++.BI protocol " VAL_MASK_8" ++Match the Protocol (IPv4) or Next Header (IPv6) field value, e.g. 6 for TCP. ++.TP ++.BI icmp_type " VAL_MASK_8" ++.TQ ++.BI icmp_code " VAL_MASK_8" ++Assume a next-header protocol of icmp or ipv6-icmp and match Type or Code ++field values. This is dangerous, as the code assumes minimal header size for ++IPv4 and lack of extension headers for IPv6. ++.TP ++.BI sport " VAL_MASK_16" ++.TQ ++.BI dport " VAL_MASK_16" ++Match layer four source or destination ports. This is dangerous as well, as it ++assumes a suitable layer four protocol is present (which has Source and ++Destination Port fields right at the start of the header and 16bit in size). ++Also minimal header size for IPv4 and lack of IPv6 extension headers is assumed. ++.TP ++.B nofrag ++.TQ ++.B firstfrag ++.TQ ++.B df ++.TQ ++.B mf ++IPv4 only, check certain flags and fragment offset values. Match if the packet ++is not a fragment ++.RB ( nofrag ), ++the first fragment ++.RB ( firstfrag ), ++if Don't Fragment ++.RB ( df ) ++or More Fragments ++.RB ( mf ) ++bits are set. ++.TP ++.BI priority " VAL_MASK_8" ++IPv6 only. Match the header's Traffic Class field, which has the same purpose ++and semantics of IPv4's ToS field since RFC 3168: upper six bits are DSCP, the ++lower two ECN. ++.TP ++.BI flowlabel " VAL_MASK_32" ++IPv6 only. Match the Flow Label field's value. Note that Flow Label itself is ++only 20bytes long, which are the least significant ones here. The remaining ++upper 12bytes match Version and Traffic Class fields. ++.RE ++.TP ++.BI tcp " TCPUDP" ++.TQ ++.BI udp " TCPUDP" ++Match fields of next header of protocol TCP or UDP. The possible values for ++.I TCPDUP ++are: ++.RS ++.TP ++.BI src " VAL_MASK_16" ++Match on Source Port field value. ++.TP ++.BI dst " VALMASK_16" ++Match on Destination Port field value. ++.RE ++.TP ++.BI icmp " ICMP" ++Match fields of next header of protocol ICMP. The possible values for ++.I ICMP ++are: ++.RS ++.TP ++.BI type " VAL_MASK_8" ++Match on ICMP Type field. ++.TP ++.BI code " VAL_MASK_8" ++Match on ICMP Code field. ++.RE ++.TP ++.BI mark " VAL_MASK_32" ++Match on netfilter fwmark value. ++.TP ++.BI ether " ETHER" ++Match on ethernet header fields. Possible values for ++.I ETHER ++are: ++.RS ++.TP ++.BI src " ether_address" " " AT ++.TQ ++.BI dst " ether_address" " " AT ++Match on source or destination ethernet address. This is dangerous: It assumes ++an ethernet header is present at the start of the packet. This will probably ++lead to unexpected things if used with layer three interfaces like e.g. tun or ++ppp. ++.SH EXAMPLES ++.RS ++.EX ++tc filter add dev eth0 parent 999:0 prio 99 protocol ip u32 \\ ++ match ip src 192.168.8.0/24 classid 1:1 ++.EE ++.RE ++ ++This attaches a filter to the qdisc identified by ++.BR 999:0. ++It's priority is ++.BR 99 , ++which affects in which order multiple filters attached to the same ++.B parent ++are consulted (the lower the earlier). The filter handles packets of ++.B protocol ++type ++.BR ip , ++and ++.BR match es ++if the IP header's source address is within the ++.B 192.168.8.0/24 ++subnet. Matching packets are classified into class ++.BR 1.1 . ++The effect of this command might be surprising at first glance: ++ ++.RS ++.EX ++filter parent 1: protocol ip pref 99 u32 ++filter parent 1: protocol ip pref 99 u32 \\ ++ fh 800: ht divisor 1 ++filter parent 1: protocol ip pref 99 u32 \\ ++ fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 \\ ++ match c0a80800/ffffff00 at 12 ++.EE ++.RE ++ ++So parent ++.B 1: ++is assigned a new ++.B u32 ++filter, which contains a hash table of size 1 (as the ++.B divisor ++indicates). The table ID is ++.BR 800 . ++The third line then shows the actual filter which was added above: it sits in ++table ++.B 800 ++and bucket ++.BR 0 , ++classifies packets into class ID ++.B 1:1 ++and matches the upper three bytes of the four byte value at offset ++.B 12 ++to be ++.BR 0xc0a808 , ++which is 192, 168 and 8. ++ ++Now for something more complicated, namely creating a custom hash table: ++ ++.RS ++.EX ++tc filter add dev eth0 prio 99 handle 1: u32 divisor 256 ++.EE ++.RE ++ ++This creates a table of size 256 with handle ++.B 1: ++in priority ++.BR 99 . ++The effect is as follows: ++ ++.RS ++.EX ++filter parent 1: protocol all pref 99 u32 ++filter parent 1: protocol all pref 99 u32 fh 1: ht divisor 256 ++filter parent 1: protocol all pref 99 u32 fh 800: ht divisor 1 ++.EE ++.RE ++ ++So along with the requested hash table (handle ++.BR 1: ), ++the kernel has created his own table of size 1 to hold other filters of the same ++priority. ++ ++The next step is to create a filter which links to the created hash table: ++ ++.RS ++.EX ++tc filter add dev eth0 parent 1: prio 1 u32 \\ ++ link 1: hashkey mask 0x0000ff00 at 12 \\ ++ match ip src 192.168.0.0/16 ++.EE ++.RE ++ ++The filter is given a lower priority than the hash table itself so ++.B u32 ++consults it before manually traversing the hash table. The options ++.BR link " and " hashkey ++determine which table and bucket to redirect to. In this case the hash key ++should be constructed out of the second byte at offset 12, which corresponds to ++an IP packet's third byte of the source address field. Along with the ++.B match ++statement, this effectively maps all class C networks below 192.168.0.0/16 to ++different buckets of the hash table. ++ ++Filters for certain subnets can be created like so: ++ ++.RS ++.EX ++tc filter add dev eth0 parent 1: prio 99 u32 \\ ++ ht 1: sample u32 0x00000800 0x0000ff00 at 12 \\ ++ match ip src 192.168.8.0/24 classid 1:1 ++.EE ++.RE ++ ++The bucket is defined using the ++.B sample ++option: In this case, the second byte at offset 12 must be 0x08, exactly. In ++this case, the resulting bucket ID is obviously 8, but as soon as ++.B sample ++selects an amount of data which could exceed the ++.BR divisor , ++one would have to know the kernel-internal algorithm to deduce the destination ++bucket. This filter's ++.B match ++statement is redundant in this case, as the entropy for the hash key does not ++exceed the table size and therefore no collisions can occur. Otherwise it's ++necessary to prevent matching unwanted packets. ++ ++Matching upper layer fields is problematic since IPv4 header length is variable ++and IPv6 supports extension headers which affect upper layer header offset. To ++overcome this, there is the possibility to specify ++.B nexthdr+ ++when giving an offset, and to make things easier there are the ++.BR tcp " and " udp ++matches which use ++.B nexthdr+ ++implicitly. This offset has to be calculated in beforehand though, and the only ++way to achieve that is by doing it in a separate filter which then links to the ++filter which wants to use it. Here is an example of doing so: ++ ++.RS ++.EX ++tc filter add dev eth0 parent 1:0 protocol ip handle 1: \\ ++ u32 divisor 1 ++tc filter add dev eth0 parent 1:0 protocol ip \\ ++ u32 ht 1: \\ ++ match tcp src 22 FFFF \\ ++ classid 1:2 ++tc filter add dev eth0 parent 1:0 protocol ip \\ ++ u32 ht 800: \\ ++ match ip protocol 6 FF \\ ++ match ip firstfrag \\ ++ offset at 0 mask 0f00 shift 6 \\ ++ link 1: ++.EE ++.RE ++ ++This is what is being done: In the first call, a single element sized hash table ++is created so there is a place to hold the linked to filter and a known handle ++.RB ( 1: ) ++to reference to it. The second call then adds the actual filter, which pushes ++packets with TCP source port 22 into class ++.BR 1:2 . ++Using ++.BR ht , ++it is moved into the hash table created by the first call. The third call then ++does the actual magic: It matches IPv4 packets with next layer protocol 6 (TCP), ++only if it's the first fragment (usually TCP sets DF bit, but if it doesn't and ++the packet is fragmented, only the first one contains the TCP header), and then ++sets the offset based on the IP header's IHL field (right-shifting by 6 ++eliminates the offset of the field and at the same time converts the value into ++byte unit). Finally, using ++.BR link , ++the hash table from first call is referenced which holds the filter from second ++call. ++.SH SEE ALSO ++.BR tc (8), ++.br ++.BR cls_u32.txt " at " http://linux-tc-notes.sourceforge.net/ +-- +1.8.3.1 + diff --git a/SOURCES/0048-tc-ship-filter-man-pages-and-refer-to-them-in-tc.8.patch b/SOURCES/0048-tc-ship-filter-man-pages-and-refer-to-them-in-tc.8.patch new file mode 100644 index 0000000..bd5b68b --- /dev/null +++ b/SOURCES/0048-tc-ship-filter-man-pages-and-refer-to-them-in-tc.8.patch @@ -0,0 +1,133 @@ +From 984233b59ae6025b6aef029b85a8ced53741f6a3 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 18 Feb 2016 15:45:21 +0100 +Subject: [PATCH] tc: ship filter man pages and refer to them in tc.8 + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1286711 +Upstream Status: iproute2.git commit a257bc7b4c481 +Conflicts: +- Context change due to other missing man pages in RHEL7. +- Dropped all references to flower filter as that does not exist in + RHEL7. + +commit a257bc7b4c481d4b2871508edfccc198d1e56c8a +Author: Phil Sutter +Date: Fri Oct 23 19:47:16 2015 +0200 + + tc: ship filter man pages and refer to them in tc.8 + + Cc: Thomas Graf + Cc: Alexey Kuznetsov + Cc: Jiri Pirko + Cc: Patrick McHardy + Cc: Werner Almesberger + Signed-off-by: Phil Sutter +--- + man/man8/Makefile | 4 +++- + man/man8/tc.8 | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 53 insertions(+), 1 deletion(-) + +diff --git a/man/man8/Makefile b/man/man8/Makefile +index 23ac83e..248ecfd 100644 +--- a/man/man8/Makefile ++++ b/man/man8/Makefile +@@ -10,7 +10,9 @@ MAN8PAGES = $(TARGETS) ip.8 arpd.8 lnstat.8 routel.8 rtacct.8 rtmon.8 ss.8 \ + ip-addrlabel.8 ip-l2tp.8 \ + ip-maddress.8 ip-monitor.8 ip-mroute.8 ip-neighbour.8 \ + ip-netns.8 ip-ntable.8 ip-rule.8 ip-tunnel.8 ip-xfrm.8 \ +- ip-tcp_metrics.8 ip-netconf.8 ip-token.8 ++ ip-tcp_metrics.8 ip-netconf.8 ip-token.8 \ ++ tc-basic.8 tc-cgroup.8 tc-flow.8 tc-fw.8 tc-route.8 \ ++ tc-tcindex.8 tc-u32.8 + + all: $(TARGETS) + +diff --git a/man/man8/tc.8 b/man/man8/tc.8 +index 80eaa3b..fb4efd9 100644 +--- a/man/man8/tc.8 ++++ b/man/man8/tc.8 +@@ -141,6 +141,49 @@ It is important to notice that filters reside + .B within + qdiscs - they are not masters of what happens. + ++The available filters are: ++.TP ++basic ++Filter packets based on an ematch expression. See ++.BR tc-ematch (8) ++for details. ++.TP ++bpf ++Filter packets using (e)BPF, see ++.BR tc-bpf (8) ++for details. ++.TP ++cgroup ++Filter packets based on the control group of their process. See ++. BR tc-cgroup (8) ++for details. ++.TP ++flow ++Flow-based classifier, filtering packets based on their flow (identified by selectable keys). See ++.BR tc-flow (8) ++for details. ++.TP ++fw ++Filter based on fwmark. Directly maps fwmark value to traffic class. See ++.BR tc-fw (8). ++.TP ++route ++Filter packets based on routing table. See ++.BR tc-route (8) ++for details. ++.TP ++rsvp ++Match Resource Reservation Protocol (RSVP) packets. ++.TP ++tcindex ++Filter packets based on traffic control index. See ++.BR tc-index (8). ++.TP ++u32 ++Generic filtering on arbitrary packet data, assisted by syntax to abstract common operations. See ++.BR tc-u32 (8) ++for details. ++ + .SH CLASSLESS QDISCS + The classless qdiscs are: + .TP +@@ -583,24 +626,31 @@ print rates in IEC units (ie. 1K = 1024). + .B tc + was written by Alexey N. Kuznetsov and added in Linux 2.2. + .SH SEE ALSO ++.BR tc-basic (8), + .BR tc-bfifo (8), + .BR tc-cbq (8), ++.BR tc-cgroup (8), + .BR tc-choke (8), + .BR tc-codel (8), + .BR tc-drr (8), + .BR tc-ematch (8), ++.BR tc-flow (8), + .BR tc-fq (8), + .BR tc-fq_codel (8), ++.BR tc-fw (8), + .BR tc-hfsc (7), + .BR tc-hfsc (8), + .BR tc-htb (8), + .BR tc-pfifo (8), + .BR tc-pfifo_fast (8), + .BR tc-red (8), ++.BR tc-route (8), + .BR tc-sfb (8), + .BR tc-sfq (8), + .BR tc-stab (8), + .BR tc-tbf (8), ++.BR tc-tcindex (8), ++.BR tc-u32 (8), + .br + .RB "User documentation at " http://lartc.org/ ", but please direct bugreports and patches to: " + +-- +1.8.3.1 + diff --git a/SOURCES/0049-xfrm-add-command-for-configuring-SPD-hash-table.patch b/SOURCES/0049-xfrm-add-command-for-configuring-SPD-hash-table.patch new file mode 100644 index 0000000..5d1050d --- /dev/null +++ b/SOURCES/0049-xfrm-add-command-for-configuring-SPD-hash-table.patch @@ -0,0 +1,198 @@ +From 03fe9d9ea9d8bf2635d12669d6cc7a80c2c8db1e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 16 Feb 2016 22:14:05 +0100 +Subject: [PATCH] xfrm: add command for configuring SPD hash table + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1212026 +Upstream Status: commit 025fa9dc7a4fe +Conflicts: Adjusted call to rtnl_talk due to previously backported + c079e121a73af ("libnetlink: add size argument to rtnl_talk") + +commit 025fa9dc7a4fee971c7040aeb84b4dac2ae08b3b +Author: Christophe Gouault +Date: Thu Apr 9 17:39:32 2015 +0200 + + xfrm: add command for configuring SPD hash table + + add a new command to configure the SPD hash table: + ip xfrm policy set [ hthresh4 LBITS RBITS ] [ hthresh6 LBITS RBITS ] + + and code to display the SPD hash configuration: + ip -s -s xfrm policy count + + hthresh4: defines minimum local and remote IPv4 prefix lengths of + selectors to hash a policy. If prefix lengths are greater or equal + to the thresholds, then the policy is hashed, otherwise it falls back + in the policy_inexact chained list. + + hthresh6: defines minimum local and remote IPv6 prefix lengths of + selectors to hash a policy, otherwise it falls back + in the policy_inexact chained list. + + Example: + + % ip -s -s xfrm policy count + SPD IN 0 OUT 0 FWD 0 (Sock: IN 0 OUT 0 FWD 0) + SPD buckets: count 7 Max 1048576 + SPD IPv4 thresholds: local 32 remote 32 + SPD IPv6 thresholds: local 128 remote 128 + + % ip xfrm pol set hthresh4 24 16 hthresh6 64 56 + + % ip -s -s xfrm policy count + SPD IN 0 OUT 0 FWD 0 (Sock: IN 0 OUT 0 FWD 0) + SPD buckets: count 7 Max 1048576 + SPD IPv4 thresholds: local 24 remote 16 + SPD IPv6 thresholds: local 64 remote 56 + + Signed-off-by: Christophe Gouault +--- + ip/xfrm_policy.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 102 insertions(+), 3 deletions(-) + +diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c +index 3ff734e..e66a4fa 100644 +--- a/ip/xfrm_policy.c ++++ b/ip/xfrm_policy.c +@@ -64,7 +64,8 @@ static void usage(void) + fprintf(stderr, " [ index INDEX ] [ ptype PTYPE ] [ action ACTION ] [ priority PRIORITY ]\n"); + fprintf(stderr, " [ flag FLAG-LIST ]\n"); + fprintf(stderr, "Usage: ip xfrm policy flush [ ptype PTYPE ]\n"); +- fprintf(stderr, "Usage: ip xfrm count\n"); ++ fprintf(stderr, "Usage: ip xfrm policy count\n"); ++ fprintf(stderr, "Usage: ip xfrm policy set [ hthresh4 LBITS RBITS ] [ hthresh6 LBITS RBITS ]\n"); + fprintf(stderr, "SELECTOR := [ src ADDR[/PLEN] ] [ dst ADDR[/PLEN] ] [ dev DEV ] [ UPSPEC ]\n"); + fprintf(stderr, "UPSPEC := proto { { "); + fprintf(stderr, "%s | ", strxf_proto(IPPROTO_TCP)); +@@ -935,7 +936,7 @@ static int print_spdinfo( struct nlmsghdr *n, void *arg) + fprintf(fp,")"); + } + +- fprintf(fp,"\n"); ++ fprintf(fp, "%s", _SL_); + } + if (show_stats > 1) { + struct xfrmu_spdhinfo *sh; +@@ -949,13 +950,109 @@ static int print_spdinfo( struct nlmsghdr *n, void *arg) + fprintf(fp,"\t SPD buckets:"); + fprintf(fp," count %d", sh->spdhcnt); + fprintf(fp," Max %d", sh->spdhmcnt); ++ fprintf(fp, "%s", _SL_); ++ } ++ if (tb[XFRMA_SPD_IPV4_HTHRESH]) { ++ struct xfrmu_spdhthresh *th; ++ if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV4_HTHRESH]) < sizeof(*th)) { ++ fprintf(stderr, "SPDinfo: Wrong len %d\n", len); ++ return -1; ++ } ++ th = RTA_DATA(tb[XFRMA_SPD_IPV4_HTHRESH]); ++ fprintf(fp,"\t SPD IPv4 thresholds:"); ++ fprintf(fp," local %d", th->lbits); ++ fprintf(fp," remote %d", th->rbits); ++ fprintf(fp, "%s", _SL_); ++ ++ } ++ if (tb[XFRMA_SPD_IPV6_HTHRESH]) { ++ struct xfrmu_spdhthresh *th; ++ if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV6_HTHRESH]) < sizeof(*th)) { ++ fprintf(stderr, "SPDinfo: Wrong len %d\n", len); ++ return -1; ++ } ++ th = RTA_DATA(tb[XFRMA_SPD_IPV6_HTHRESH]); ++ fprintf(fp,"\t SPD IPv6 thresholds:"); ++ fprintf(fp," local %d", th->lbits); ++ fprintf(fp," remote %d", th->rbits); ++ fprintf(fp, "%s", _SL_); + } + } +- fprintf(fp,"\n"); ++ ++ if (oneline) ++ fprintf(fp, "\n"); + + return 0; + } + ++static int xfrm_spd_setinfo(int argc, char **argv) ++{ ++ struct rtnl_handle rth; ++ struct { ++ struct nlmsghdr n; ++ __u32 flags; ++ char buf[RTA_BUF_SIZE]; ++ } req; ++ ++ char *thr4 = NULL; ++ char *thr6 = NULL; ++ ++ memset(&req, 0, sizeof(req)); ++ ++ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(__u32)); ++ req.n.nlmsg_flags = NLM_F_REQUEST; ++ req.n.nlmsg_type = XFRM_MSG_NEWSPDINFO; ++ req.flags = 0XFFFFFFFF; ++ ++ while (argc > 0) { ++ if (strcmp(*argv, "hthresh4") == 0) { ++ struct xfrmu_spdhthresh thr; ++ ++ if (thr4) ++ duparg("hthresh4", *argv); ++ thr4 = *argv; ++ NEXT_ARG(); ++ if (get_u8(&thr.lbits, *argv, 0) || thr.lbits > 32) ++ invarg("hthresh4 LBITS value is invalid", *argv); ++ NEXT_ARG(); ++ if (get_u8(&thr.rbits, *argv, 0) || thr.rbits > 32) ++ invarg("hthresh4 RBITS value is invalid", *argv); ++ ++ addattr_l(&req.n, sizeof(req), XFRMA_SPD_IPV4_HTHRESH, ++ (void *)&thr, sizeof(thr)); ++ } else if (strcmp(*argv, "hthresh6") == 0) { ++ struct xfrmu_spdhthresh thr; ++ ++ if (thr6) ++ duparg("hthresh6", *argv); ++ thr6 = *argv; ++ NEXT_ARG(); ++ if (get_u8(&thr.lbits, *argv, 0) || thr.lbits > 128) ++ invarg("hthresh6 LBITS value is invalid", *argv); ++ NEXT_ARG(); ++ if (get_u8(&thr.rbits, *argv, 0) || thr.rbits > 128) ++ invarg("hthresh6 RBITS value is invalid", *argv); ++ ++ addattr_l(&req.n, sizeof(req), XFRMA_SPD_IPV6_HTHRESH, ++ (void *)&thr, sizeof(thr)); ++ } else { ++ invarg("unknown", *argv); ++ } ++ ++ argc--; argv++; ++ } ++ ++ if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) ++ exit(1); ++ ++ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) ++ exit(2); ++ ++ rtnl_close(&rth); ++ ++ return 0; ++} ++ + static int xfrm_spd_getinfo(int argc, char **argv) + { + struct rtnl_handle rth; +@@ -1059,6 +1156,8 @@ int do_xfrm_policy(int argc, char **argv) + return xfrm_policy_flush(argc-1, argv+1); + if (matches(*argv, "count") == 0) + return xfrm_spd_getinfo(argc, argv); ++ if (matches(*argv, "set") == 0) ++ return xfrm_spd_setinfo(argc-1, argv+1); + if (matches(*argv, "help") == 0) + usage(); + fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm policy help\".\n", *argv); +-- +1.8.3.1 + diff --git a/SOURCES/0050-xfrm-revise-man-page-and-document-ip-xfrm-policy-set.patch b/SOURCES/0050-xfrm-revise-man-page-and-document-ip-xfrm-policy-set.patch new file mode 100644 index 0000000..551f224 --- /dev/null +++ b/SOURCES/0050-xfrm-revise-man-page-and-document-ip-xfrm-policy-set.patch @@ -0,0 +1,141 @@ +From b213961bb74c8de4d713504a7b4c9b20900f8f99 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:24:36 +0100 +Subject: [PATCH] xfrm: revise man page and document ip xfrm policy set + + Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1212026 + Upstream Status: commit 811aca044859a + Conflicts: Context changed due to already applied commit b6ec53e3008aa + ("xfrmmonitor: allows to monitor in several netns") + + commit 811aca044859aed2802f4449023fcb4d30275625 + Author: Christophe Gouault + Date: Thu Apr 9 17:39:33 2015 +0200 + + xfrm: revise man page and document ip xfrm policy set + + - document ip xfrm policy set + - update ip xfrm monitor documentation + - in DESCRIPTION section, reorganize grouping of commands + + Signed-off-by: Christophe Gouault +--- + man/man8/ip-xfrm.8 | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 59 insertions(+), 2 deletions(-) + +diff --git a/man/man8/ip-xfrm.8 b/man/man8/ip-xfrm.8 +index 3752c7e..aea4fda 100644 +--- a/man/man8/ip-xfrm.8 ++++ b/man/man8/ip-xfrm.8 +@@ -252,6 +252,13 @@ ip-xfrm \- transform configuration + .B "ip xfrm policy count" + + .ti -8 ++.B "ip xfrm policy set" ++.RB "[ " hthresh4 ++.IR LBITS " " RBITS " ]" ++.RB "[ " hthresh6 ++.IR LBITS " " RBITS " ]" ++ ++.ti -8 + .IR SELECTOR " :=" + .RB "[ " src + .IR ADDR "[/" PLEN "] ]" +@@ -359,6 +366,13 @@ ip-xfrm \- transform configuration + | + .IR LISTofXFRM-OBJECTS " ]" + ++.ti -8 ++.IR LISTofXFRM-OBJECTS " := [ " LISTofXFRM-OBJECTS " ] " XFRM-OBJECT ++ ++.ti -8 ++.IR XFRM-OBJECT " := " ++.BR acquire " | " expire " | " SA " | " policy " | " aevent " | " report ++ + .in -8 + .ad b + +@@ -384,7 +398,6 @@ ip xfrm state deleteall delete all existing state in xfrm + ip xfrm state list print out the list of existing state in xfrm + ip xfrm state flush flush all state in xfrm + ip xfrm state count count all existing state in xfrm +-ip xfrm monitor state monitoring for xfrm objects + .TE + + .TP +@@ -506,7 +519,9 @@ encapsulates packets with protocol + .BR espinudp " or " espinudp-nonike "," + .RI "using source port " SPORT ", destination port " DPORT + .RI ", and original address " OADDR "." ++ + .sp ++.PP + .TS + l l. + ip xfrm policy add add a new policy +@@ -516,7 +531,6 @@ ip xfrm policy get get an existing policy + ip xfrm policy deleteall delete all existing xfrm policies + ip xfrm policy list print out the list of xfrm policies + ip xfrm policy flush flush policies +-ip xfrm policy count count existing policies + .TE + + .TP +@@ -611,6 +625,47 @@ and inbound trigger + can be + .BR required " (default) or " use "." + ++.sp ++.PP ++.TS ++l l. ++ip xfrm policy count count existing policies ++.TE ++ ++.PP ++Use one or more -s options to display more details, including policy hash table ++information. ++ ++.sp ++.PP ++.TS ++l l. ++ip xfrm policy set configure the policy hash table ++.TE ++ ++.PP ++Security policies whose address prefix lengths are greater than or equal ++policy hash table thresholds are hashed. Others are stored in the ++policy_inexact chained list. ++ ++.TP ++.I LBITS ++specifies the minimum local address prefix length of policies that are ++stored in the Security Policy Database hash table. ++ ++.TP ++.I RBITS ++specifies the minimum remote address prefix length of policies that are ++stored in the Security Policy Database hash table. ++ ++.sp ++.PP ++.TS ++l l. ++ip xfrm monitor state monitoring for xfrm objects ++.TE ++ ++.PP + The xfrm objects to monitor can be optionally specified. + + .P +@@ -629,4 +684,6 @@ originates. Example: + .SH AUTHOR + Manpage revised by David Ward + .br ++Manpage revised by Christophe Gouault ++.br + Manpage revised by Nicolas Dichtel +-- +1.8.3.1 + diff --git a/SOURCES/0051-iplink-update-available-type-list.patch b/SOURCES/0051-iplink-update-available-type-list.patch new file mode 100644 index 0000000..bd0f219 --- /dev/null +++ b/SOURCES/0051-iplink-update-available-type-list.patch @@ -0,0 +1,41 @@ +From 36af5dff831900abaa38c6c906a2c9ac8ca4d201 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:24:50 +0100 +Subject: [PATCH] iplink: update available type list + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 1253a10a63e41 + +commit 1253a10a63e417c5a7774c127aea1a3b0dd09e88 +Author: Nicolas Dichtel +Date: Tue Oct 8 07:59:45 2013 -0700 + + iplink: update available type list + + macvtap and vti were missing. + + Signed-off-by: Nicolas Dichtel +--- + ip/iplink.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index 048d4f3..5a9ed57 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -89,9 +89,9 @@ void iplink_usage(void) + if (iplink_have_newlink()) { + fprintf(stderr, " ip link help [ TYPE ]\n"); + fprintf(stderr, "\n"); +- fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |\n"); +- fprintf(stderr, " bridge | ipoib | ip6tnl | ipip | sit | vxlan |\n"); +- fprintf(stderr, " gre | gretap | ip6gre | ip6gretap }\n"); ++ fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n"); ++ fprintf(stderr, " can | bridge | ipoib | ip6tnl | ipip | sit | vxlan |\n"); ++ fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti }\n"); + } + exit(-1); + } +-- +1.8.3.1 + diff --git a/SOURCES/0052-iplink-add-support-for-bonding-netlink.patch b/SOURCES/0052-iplink-add-support-for-bonding-netlink.patch new file mode 100644 index 0000000..2273ab0 --- /dev/null +++ b/SOURCES/0052-iplink-add-support-for-bonding-netlink.patch @@ -0,0 +1,174 @@ +From c8b98b78222a1eef506d3e3e9e7dc7da9db0984c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:24:51 +0100 +Subject: [PATCH] iplink: add support for bonding netlink + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit cc26a8909ff31 + +commit cc26a8909ff31388ca0b3703b08605e116e490bb +Author: Jiri Pirko +Date: Fri Oct 18 17:50:01 2013 +0200 + + iplink: add support for bonding netlink + + Signed-off-by: Jiri Pirko +--- + ip/Makefile | 2 +- + ip/iplink.c | 4 +-- + ip/iplink_bond.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++ + man/man8/ip-link.8.in | 4 +++ + 4 files changed, 99 insertions(+), 3 deletions(-) + create mode 100644 ip/iplink_bond.c + +diff --git a/ip/Makefile b/ip/Makefile +index f377c37..76878fb 100644 +--- a/ip/Makefile ++++ b/ip/Makefile +@@ -5,7 +5,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ + iplink_vlan.o link_veth.o link_gre.o iplink_can.o \ + iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o link_vti6.o \ + iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \ +- link_iptnl.o link_gre6.o ++ link_iptnl.o link_gre6.o iplink_bond.o + + RTMONOBJ=rtmon.o + +diff --git a/ip/iplink.c b/ip/iplink.c +index 5a9ed57..3024e99 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -90,8 +90,8 @@ void iplink_usage(void) + fprintf(stderr, " ip link help [ TYPE ]\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n"); +- fprintf(stderr, " can | bridge | ipoib | ip6tnl | ipip | sit | vxlan |\n"); +- fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti }\n"); ++ fprintf(stderr, " can | bridge | bond | ipoib | ip6tnl | ipip | sit |\n"); ++ fprintf(stderr, " vxlan | gre | gretap | ip6gre | ip6gretap | vti }\n"); + } + exit(-1); + } +diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c +new file mode 100644 +index 0000000..3fb7f4f +--- /dev/null ++++ b/ip/iplink_bond.c +@@ -0,0 +1,92 @@ ++/* ++ * iplink_bond.c Bonding device support ++ * ++ * 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. ++ * ++ * Authors: Jiri Pirko ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "rt_names.h" ++#include "utils.h" ++#include "ip_common.h" ++ ++static void explain(void) ++{ ++ fprintf(stderr, ++ "Usage: ... bond [ mode BONDMODE ] [ active_slave SLAVE_DEV ]\n" ++ " [ clear_active_slave ]\n" ++ "\n" ++ "BONDMODE := 0-6\n" ++ ); ++} ++ ++static int bond_parse_opt(struct link_util *lu, int argc, char **argv, ++ struct nlmsghdr *n) ++{ ++ __u8 mode; ++ unsigned ifindex; ++ ++ while (argc > 0) { ++ if (matches(*argv, "mode") == 0) { ++ NEXT_ARG(); ++ if (get_u8(&mode, *argv, 0)) { ++ invarg("mode %s is invalid", *argv); ++ return -1; ++ } ++ addattr8(n, 1024, IFLA_BOND_MODE, mode); ++ } else if (matches(*argv, "active_slave") == 0) { ++ NEXT_ARG(); ++ ifindex = if_nametoindex(*argv); ++ if (!ifindex) ++ return -1; ++ addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, ifindex); ++ } else if (matches(*argv, "clear_active_slave") == 0) { ++ addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, 0); ++ } else { ++ fprintf(stderr, "bond: unknown command \"%s\"?\n", *argv); ++ explain(); ++ return -1; ++ } ++ argc--, argv++; ++ } ++ ++ return 0; ++} ++ ++static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) ++{ ++ unsigned ifindex; ++ ++ if (!tb) ++ return; ++ ++ if (tb[IFLA_BOND_MODE]) ++ fprintf(f, "mode %u ", rta_getattr_u8(tb[IFLA_BOND_MODE])); ++ ++ if (tb[IFLA_BOND_ACTIVE_SLAVE] && ++ (ifindex = rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]))) { ++ char buf[IFNAMSIZ]; ++ const char *n = if_indextoname(ifindex, buf); ++ ++ if (n) ++ fprintf(f, "active_slave %s ", n); ++ else ++ fprintf(f, "active_slave %u ", ifindex); ++ } ++} ++ ++struct link_util bond_link_util = { ++ .id = "bond", ++ .maxattr = IFLA_BOND_MAX, ++ .parse_opt = bond_parse_opt, ++ .print_opt = bond_print_opt, ++}; +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index ef90738..d69c930 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -52,6 +52,7 @@ ip-link \- network device configuration + .ti -8 + .IR TYPE " := [ " + .BR bridge " | " ++.BR bond " ]" + .BR can " | " + .BR dummy " | " + .BR ifb " | " +@@ -160,6 +161,9 @@ Link types: + .B bridge + - Ethernet Bridge device + .sp ++.B bond ++- Bonding device ++.sp + .B can + - Controller Area Network interface + .sp +-- +1.8.3.1 + diff --git a/SOURCES/0053-iproute2-finish-support-for-bonding-attributes.patch b/SOURCES/0053-iproute2-finish-support-for-bonding-attributes.patch new file mode 100644 index 0000000..632aa74 --- /dev/null +++ b/SOURCES/0053-iproute2-finish-support-for-bonding-attributes.patch @@ -0,0 +1,546 @@ +From 94fcad34a1305c2851b759b6acb3903c7227580f Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:24:51 +0100 +Subject: [PATCH] iproute2: finish support for bonding attributes + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 63d127b05dff4 + +commit 63d127b05dff4d21e8748b2ba9e0e6372897c383 +Author: sfeldma@cumulusnetworks.com +Date: Fri Jan 3 18:45:38 2014 -0800 + + iproute2: finish support for bonding attributes + + Add support for bonding attributes just added to net-next. + On set, allow string or number value for enumerated attributes. + On show, use always use string value for attribute. + + Signed-off-by: Scott Feldman +--- + ip/iplink_bond.c | 458 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 451 insertions(+), 7 deletions(-) + +diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c +index 3fb7f4f..f0e5ab1 100644 +--- a/ip/iplink_bond.c ++++ b/ip/iplink_bond.c +@@ -7,41 +7,165 @@ + * 2 of the License, or (at your option) any later version. + * + * Authors: Jiri Pirko ++ * Scott Feldman + */ + + #include + #include + #include + #include ++#include + #include + + #include "rt_names.h" + #include "utils.h" + #include "ip_common.h" + ++#define BOND_MAX_ARP_TARGETS 16 ++ ++static const char *mode_tbl[] = { ++ "balance-rr", ++ "active-backup", ++ "balance-xor", ++ "broadcast", ++ "802.3ad", ++ "balance-tlb", ++ "balance-alb", ++ NULL, ++}; ++ ++static const char *arp_validate_tbl[] = { ++ "none", ++ "active", ++ "backup", ++ "all", ++ NULL, ++}; ++ ++static const char *arp_all_targets_tbl[] = { ++ "any", ++ "all", ++ NULL, ++}; ++ ++static const char *primary_reselect_tbl[] = { ++ "always", ++ "better", ++ "failure", ++ NULL, ++}; ++ ++static const char *fail_over_mac_tbl[] = { ++ "none", ++ "active", ++ "follow", ++ NULL, ++}; ++ ++static const char *xmit_hash_policy_tbl[] = { ++ "layer2", ++ "layer3+4", ++ "layer2+3", ++ "encap2+3", ++ "encap3+4", ++ NULL, ++}; ++ ++static const char *lacp_rate_tbl[] = { ++ "slow", ++ "fast", ++ NULL, ++}; ++ ++static const char *ad_select_tbl[] = { ++ "stable", ++ "bandwidth", ++ "count", ++ NULL, ++}; ++ ++static const char *get_name(const char **tbl, int index) ++{ ++ int i; ++ ++ for (i = 0; tbl[i]; i++) ++ if (i == index) ++ return tbl[i]; ++ ++ return "UNKNOWN"; ++} ++ ++static int get_index(const char **tbl, char *name) ++{ ++ int i, index; ++ ++ /* check for integer index passed in instead of name */ ++ if (get_integer(&index, name, 10) == 0) ++ for (i = 0; tbl[i]; i++) ++ if (i == index) ++ return i; ++ ++ for (i = 0; tbl[i]; i++) ++ if (strncmp(tbl[i], name, strlen(tbl[i])) == 0) ++ return i; ++ ++ return -1; ++} ++ + static void explain(void) + { + fprintf(stderr, + "Usage: ... bond [ mode BONDMODE ] [ active_slave SLAVE_DEV ]\n" +- " [ clear_active_slave ]\n" ++ " [ clear_active_slave ] [ miimon MIIMON ]\n" ++ " [ updelay UPDELAY ] [ downdelay DOWNDELAY ]\n" ++ " [ use_carrier USE_CARRIER ]\n" ++ " [ arp_interval ARP_INTERVAL ]\n" ++ " [ arp_validate ARP_VALIDATE ]\n" ++ " [ arp_all_targets ARP_ALL_TARGETS ]\n" ++ " [ arp_ip_target [ ARP_IP_TARGET, ... ] ]\n" ++ " [ primary SLAVE_DEV ]\n" ++ " [ primary_reselect PRIMARY_RESELECT ]\n" ++ " [ fail_over_mac FAIL_OVER_MAC ]\n" ++ " [ xmit_hash_policy XMIT_HASH_POLICY ]\n" ++ " [ resend_igmp RESEND_IGMP ]\n" ++ " [ num_grat_arp|num_unsol_na NUM_GRAT_ARP|NUM_UNSOL_NA ]\n" ++ " [ all_slaves_active ALL_SLAVES_ACTIVE ]\n" ++ " [ min_links MIN_LINKS ]\n" ++ " [ lp_interval LP_INTERVAL ]\n" ++ " [ packets_per_slave PACKETS_PER_SLAVE ]\n" ++ " [ lacp_rate LACP_RATE ]\n" ++ " [ ad_select AD_SELECT ]\n" + "\n" +- "BONDMODE := 0-6\n" ++ "BONDMODE := balance-rr|active-backup|balance-xor|broadcast|802.3ad|balance-tlb|balance-alb\n" ++ "ARP_VALIDATE := none|active|backup|all\n" ++ "ARP_ALL_TARGETS := any|all\n" ++ "PRIMARY_RESELECT := always|better|failure\n" ++ "FAIL_OVER_MAC := none|active|follow\n" ++ "XMIT_HASH_POLICY := layer2|layer2+3|layer3+4\n" ++ "LACP_RATE := slow|fast\n" ++ "AD_SELECT := stable|bandwidth|count\n" + ); + } + + static int bond_parse_opt(struct link_util *lu, int argc, char **argv, + struct nlmsghdr *n) + { +- __u8 mode; ++ __u8 mode, use_carrier, primary_reselect, fail_over_mac; ++ __u8 xmit_hash_policy, num_peer_notif, all_slaves_active; ++ __u8 lacp_rate, ad_select; ++ __u32 miimon, updelay, downdelay, arp_interval, arp_validate; ++ __u32 arp_all_targets, resend_igmp, min_links, lp_interval; ++ __u32 packets_per_slave; + unsigned ifindex; + + while (argc > 0) { + if (matches(*argv, "mode") == 0) { + NEXT_ARG(); +- if (get_u8(&mode, *argv, 0)) { +- invarg("mode %s is invalid", *argv); ++ if (get_index(mode_tbl, *argv) < 0) { ++ invarg("invalid mode", *argv); + return -1; + } ++ mode = get_index(mode_tbl, *argv); + addattr8(n, 1024, IFLA_BOND_MODE, mode); + } else if (matches(*argv, "active_slave") == 0) { + NEXT_ARG(); +@@ -51,6 +175,170 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv, + addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, ifindex); + } else if (matches(*argv, "clear_active_slave") == 0) { + addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, 0); ++ } else if (matches(*argv, "miimon") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&miimon, *argv, 0)) { ++ invarg("invalid miimon", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BOND_MIIMON, miimon); ++ } else if (matches(*argv, "updelay") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&updelay, *argv, 0)) { ++ invarg("invalid updelay", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BOND_UPDELAY, updelay); ++ } else if (matches(*argv, "downdelay") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&downdelay, *argv, 0)) { ++ invarg("invalid downdelay", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BOND_DOWNDELAY, downdelay); ++ } else if (matches(*argv, "use_carrier") == 0) { ++ NEXT_ARG(); ++ if (get_u8(&use_carrier, *argv, 0)) { ++ invarg("invalid use_carrier", *argv); ++ return -1; ++ } ++ addattr8(n, 1024, IFLA_BOND_USE_CARRIER, use_carrier); ++ } else if (matches(*argv, "arp_interval") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&arp_interval, *argv, 0)) { ++ invarg("invalid arp_interval", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BOND_ARP_INTERVAL, arp_interval); ++ } else if (matches(*argv, "arp_ip_target") == 0) { ++ struct rtattr * nest = addattr_nest(n, 1024, ++ IFLA_BOND_ARP_IP_TARGET); ++ if (NEXT_ARG_OK()) { ++ NEXT_ARG(); ++ char *targets = strdupa(*argv); ++ char *target = strtok(targets, ","); ++ int i; ++ ++ for(i = 0; target && i < BOND_MAX_ARP_TARGETS; i++) { ++ __u32 addr = get_addr32(target); ++ addattr32(n, 1024, i, addr); ++ target = strtok(NULL, ","); ++ } ++ addattr_nest_end(n, nest); ++ } ++ addattr_nest_end(n, nest); ++ } else if (matches(*argv, "arp_validate") == 0) { ++ NEXT_ARG(); ++ if (get_index(arp_validate_tbl, *argv) < 0) { ++ invarg("invalid arp_validate", *argv); ++ return -1; ++ } ++ arp_validate = get_index(arp_validate_tbl, *argv); ++ addattr32(n, 1024, IFLA_BOND_ARP_VALIDATE, arp_validate); ++ } else if (matches(*argv, "arp_all_targets") == 0) { ++ NEXT_ARG(); ++ if (get_index(arp_all_targets_tbl, *argv) < 0) { ++ invarg("invalid arp_all_targets", *argv); ++ return -1; ++ } ++ arp_all_targets = get_index(arp_all_targets_tbl, *argv); ++ addattr32(n, 1024, IFLA_BOND_ARP_ALL_TARGETS, arp_all_targets); ++ } else if (matches(*argv, "primary") == 0) { ++ NEXT_ARG(); ++ ifindex = if_nametoindex(*argv); ++ if (!ifindex) ++ return -1; ++ addattr32(n, 1024, IFLA_BOND_PRIMARY, ifindex); ++ } else if (matches(*argv, "primary_reselect") == 0) { ++ NEXT_ARG(); ++ if (get_index(primary_reselect_tbl, *argv) < 0) { ++ invarg("invalid primary_reselect", *argv); ++ return -1; ++ } ++ primary_reselect = get_index(primary_reselect_tbl, *argv); ++ addattr8(n, 1024, IFLA_BOND_PRIMARY_RESELECT, ++ primary_reselect); ++ } else if (matches(*argv, "fail_over_mac") == 0) { ++ NEXT_ARG(); ++ if (get_index(fail_over_mac_tbl, *argv) < 0) { ++ invarg("invalid fail_over_mac", *argv); ++ return -1; ++ } ++ fail_over_mac = get_index(fail_over_mac_tbl, *argv); ++ addattr8(n, 1024, IFLA_BOND_FAIL_OVER_MAC, ++ fail_over_mac); ++ } else if (matches(*argv, "xmit_hash_policy") == 0) { ++ NEXT_ARG(); ++ if (get_index(xmit_hash_policy_tbl, *argv) < 0) { ++ invarg("invalid xmit_hash_policy", *argv); ++ return -1; ++ } ++ xmit_hash_policy = get_index(xmit_hash_policy_tbl, *argv); ++ addattr8(n, 1024, IFLA_BOND_XMIT_HASH_POLICY, ++ xmit_hash_policy); ++ } else if (matches(*argv, "resend_igmp") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&resend_igmp, *argv, 0)) { ++ invarg("invalid resend_igmp", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BOND_RESEND_IGMP, resend_igmp); ++ } else if (matches(*argv, "num_grat_arp") == 0 || ++ matches(*argv, "num_unsol_na") == 0) { ++ NEXT_ARG(); ++ if (get_u8(&num_peer_notif, *argv, 0)) { ++ invarg("invalid num_grat_arp|num_unsol_na", ++ *argv); ++ return -1; ++ } ++ addattr8(n, 1024, IFLA_BOND_NUM_PEER_NOTIF, ++ num_peer_notif); ++ } else if (matches(*argv, "all_slaves_active") == 0) { ++ NEXT_ARG(); ++ if (get_u8(&all_slaves_active, *argv, 0)) { ++ invarg("invalid all_slaves_active", *argv); ++ return -1; ++ } ++ addattr8(n, 1024, IFLA_BOND_ALL_SLAVES_ACTIVE, ++ all_slaves_active); ++ } else if (matches(*argv, "min_links") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&min_links, *argv, 0)) { ++ invarg("invalid min_links", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BOND_MIN_LINKS, min_links); ++ } else if (matches(*argv, "lp_interval") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&lp_interval, *argv, 0)) { ++ invarg("invalid lp_interval", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BOND_LP_INTERVAL, lp_interval); ++ } else if (matches(*argv, "packets_per_slave") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&packets_per_slave, *argv, 0)) { ++ invarg("invalid packets_per_slave", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BOND_PACKETS_PER_SLAVE, ++ packets_per_slave); ++ } else if (matches(*argv, "lacp_rate") == 0) { ++ NEXT_ARG(); ++ if (get_index(lacp_rate_tbl, *argv) < 0) { ++ invarg("invalid lacp_rate", *argv); ++ return -1; ++ } ++ lacp_rate = get_index(lacp_rate_tbl, *argv); ++ addattr8(n, 1024, IFLA_BOND_AD_LACP_RATE, lacp_rate); ++ } else if (matches(*argv, "ad_select") == 0) { ++ NEXT_ARG(); ++ if (get_index(ad_select_tbl, *argv) < 0) { ++ invarg("invalid ad_select", *argv); ++ return -1; ++ } ++ ad_select = get_index(ad_select_tbl, *argv); ++ addattr8(n, 1024, IFLA_BOND_AD_SELECT, ad_select); + } else { + fprintf(stderr, "bond: unknown command \"%s\"?\n", *argv); + explain(); +@@ -69,8 +357,11 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + if (!tb) + return; + +- if (tb[IFLA_BOND_MODE]) +- fprintf(f, "mode %u ", rta_getattr_u8(tb[IFLA_BOND_MODE])); ++ if (tb[IFLA_BOND_MODE]) { ++ const char *mode = get_name(mode_tbl, ++ rta_getattr_u8(tb[IFLA_BOND_MODE])); ++ fprintf(f, "mode %s ", mode); ++ } + + if (tb[IFLA_BOND_ACTIVE_SLAVE] && + (ifindex = rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]))) { +@@ -82,6 +373,159 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + else + fprintf(f, "active_slave %u ", ifindex); + } ++ ++ if (tb[IFLA_BOND_MIIMON]) ++ fprintf(f, "miimon %u ", rta_getattr_u32(tb[IFLA_BOND_MIIMON])); ++ ++ if (tb[IFLA_BOND_UPDELAY]) ++ fprintf(f, "updelay %u ", rta_getattr_u32(tb[IFLA_BOND_UPDELAY])); ++ ++ if (tb[IFLA_BOND_DOWNDELAY]) ++ fprintf(f, "downdelay %u ", ++ rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY])); ++ ++ if (tb[IFLA_BOND_USE_CARRIER]) ++ fprintf(f, "use_carrier %u ", ++ rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER])); ++ ++ if (tb[IFLA_BOND_ARP_INTERVAL]) ++ fprintf(f, "arp_interval %u ", ++ rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL])); ++ ++ if (tb[IFLA_BOND_ARP_IP_TARGET]) { ++ struct rtattr *iptb[BOND_MAX_ARP_TARGETS + 1]; ++ char buf[INET_ADDRSTRLEN]; ++ int i; ++ ++ parse_rtattr_nested(iptb, BOND_MAX_ARP_TARGETS, ++ tb[IFLA_BOND_ARP_IP_TARGET]); ++ ++ if (iptb[0]) ++ fprintf(f, "arp_ip_target "); ++ ++ for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) { ++ if (iptb[i]) ++ fprintf(f, "%s", ++ rt_addr_n2a(AF_INET, ++ RTA_PAYLOAD(iptb[i]), ++ RTA_DATA(iptb[i]), ++ buf, ++ INET_ADDRSTRLEN)); ++ if (i < BOND_MAX_ARP_TARGETS-1 && iptb[i+1]) ++ fprintf(f, ","); ++ } ++ ++ if (iptb[0]) ++ fprintf(f, " "); ++ } ++ ++ if (tb[IFLA_BOND_ARP_VALIDATE]) { ++ const char *arp_validate = get_name(arp_validate_tbl, ++ rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE])); ++ fprintf(f, "arp_validate %s ", arp_validate); ++ } ++ ++ if (tb[IFLA_BOND_ARP_ALL_TARGETS]) { ++ const char *arp_all_targets = get_name(arp_all_targets_tbl, ++ rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS])); ++ fprintf(f, "arp_all_target %s ", arp_all_targets); ++ } ++ ++ if (tb[IFLA_BOND_PRIMARY] && ++ (ifindex = rta_getattr_u32(tb[IFLA_BOND_PRIMARY]))) { ++ char buf[IFNAMSIZ]; ++ const char *n = if_indextoname(ifindex, buf); ++ ++ if (n) ++ fprintf(f, "primary %s ", n); ++ else ++ fprintf(f, "primary %u ", ifindex); ++ } ++ ++ if (tb[IFLA_BOND_PRIMARY_RESELECT]) { ++ const char *primary_reselect = get_name(primary_reselect_tbl, ++ rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT])); ++ fprintf(f, "primary_reselect %s ", primary_reselect); ++ } ++ ++ if (tb[IFLA_BOND_FAIL_OVER_MAC]) { ++ const char *fail_over_mac = get_name(fail_over_mac_tbl, ++ rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC])); ++ fprintf(f, "fail_over_mac %s ", fail_over_mac); ++ } ++ ++ if (tb[IFLA_BOND_XMIT_HASH_POLICY]) { ++ const char *xmit_hash_policy = get_name(xmit_hash_policy_tbl, ++ rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY])); ++ fprintf(f, "xmit_hash_policy %s ", xmit_hash_policy); ++ } ++ ++ if (tb[IFLA_BOND_RESEND_IGMP]) ++ fprintf(f, "resend_igmp %u ", ++ rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP])); ++ ++ if (tb[IFLA_BOND_NUM_PEER_NOTIF]) ++ fprintf(f, "num_grat_arp %u ", ++ rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF])); ++ ++ if (tb[IFLA_BOND_ALL_SLAVES_ACTIVE]) ++ fprintf(f, "all_slaves_active %u ", ++ rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE])); ++ ++ if (tb[IFLA_BOND_MIN_LINKS]) ++ fprintf(f, "min_links %u ", ++ rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS])); ++ ++ if (tb[IFLA_BOND_LP_INTERVAL]) ++ fprintf(f, "lp_interval %u ", ++ rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL])); ++ ++ if (tb[IFLA_BOND_PACKETS_PER_SLAVE]) ++ fprintf(f, "packets_per_slave %u ", ++ rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE])); ++ ++ if (tb[IFLA_BOND_AD_LACP_RATE]) { ++ const char *lacp_rate = get_name(lacp_rate_tbl, ++ rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE])); ++ fprintf(f, "lacp_rate %s ", lacp_rate); ++ } ++ ++ if (tb[IFLA_BOND_AD_SELECT]) { ++ const char *ad_select = get_name(ad_select_tbl, ++ rta_getattr_u8(tb[IFLA_BOND_AD_SELECT])); ++ fprintf(f, "ad_select %s ", ad_select); ++ } ++ ++ if (tb[IFLA_BOND_AD_INFO]) { ++ struct rtattr *adtb[IFLA_BOND_AD_INFO_MAX + 1]; ++ ++ parse_rtattr_nested(adtb, IFLA_BOND_AD_INFO_MAX, ++ tb[IFLA_BOND_AD_INFO]); ++ ++ if (adtb[IFLA_BOND_AD_INFO_AGGREGATOR]) ++ fprintf(f, "ad_aggregator %d ", ++ rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR])); ++ ++ if (adtb[IFLA_BOND_AD_INFO_NUM_PORTS]) ++ fprintf(f, "ad_num_ports %d ", ++ rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS])); ++ ++ if (adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]) ++ fprintf(f, "ad_actor_key %d ", ++ rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY])); ++ ++ if (adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]) ++ fprintf(f, "ad_partner_key %d ", ++ rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY])); ++ ++ if (adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]) { ++ unsigned char *p = ++ RTA_DATA(adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]); ++ SPRINT_BUF(b); ++ fprintf(f, "ad_partner_mac %s ", ++ ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b))); ++ } ++ } + } + + struct link_util bond_link_util = { +-- +1.8.3.1 + diff --git a/SOURCES/0054-introduce-support-for-slave-info-data.patch b/SOURCES/0054-introduce-support-for-slave-info-data.patch new file mode 100644 index 0000000..38edc74 --- /dev/null +++ b/SOURCES/0054-introduce-support-for-slave-info-data.patch @@ -0,0 +1,185 @@ +From 4e0ecde498d450b10a3bb44ca95816dd2a479f40 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:24:51 +0100 +Subject: [PATCH] introduce support for slave info data + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit fbea6115645a1 +Conflicts: Changed context due to already applied commit 561e650eff679 + ("ip link: Shortify printing the usage of link type") + +commit fbea6115645a126de87bbcf51371050dde1a5b39 +Author: Jiri Pirko +Date: Thu Jan 23 17:52:53 2014 +0100 + + introduce support for slave info data + + Signed-off-by: Jiri Pirko +--- + ip/ip_common.h | 4 ++++ + ip/ipaddress.c | 54 ++++++++++++++++++++++++++++++++++++------------------ + ip/iplink.c | 21 ++++++++++++++++++--- + 3 files changed, 58 insertions(+), 21 deletions(-) + +diff --git a/ip/ip_common.h b/ip/ip_common.h +index 274d12a..917fcf8 100644 +--- a/ip/ip_common.h ++++ b/ip/ip_common.h +@@ -66,6 +66,8 @@ static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb) + + extern struct rtnl_handle rth; + ++#include ++ + struct link_util + { + struct link_util *next; +@@ -79,9 +81,11 @@ struct link_util + struct rtattr *); + void (*print_help)(struct link_util *, int, char **, + FILE *); ++ bool slave; + }; + + struct link_util *get_link_kind(const char *kind); ++struct link_util *get_link_slave_kind(const char *slave_kind); + + #ifndef INFINITY_LIFE_TIME + #define INFINITY_LIFE_TIME 0xFFFFFFFFU +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 700c40f..8681bf9 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -193,34 +193,52 @@ static void print_linktype(FILE *fp, struct rtattr *tb) + { + struct rtattr *linkinfo[IFLA_INFO_MAX+1]; + struct link_util *lu; ++ struct link_util *slave_lu; + char *kind; ++ char *slave_kind; + + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); + +- if (!linkinfo[IFLA_INFO_KIND]) +- return; +- kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); ++ if (linkinfo[IFLA_INFO_KIND]) { ++ kind = RTA_DATA(linkinfo[IFLA_INFO_KIND]); + +- fprintf(fp, "%s", _SL_); +- fprintf(fp, " %s ", kind); ++ fprintf(fp, "%s", _SL_); ++ fprintf(fp, " %s ", kind); + +- lu = get_link_kind(kind); +- if (!lu || !lu->print_opt) +- return; ++ lu = get_link_kind(kind); ++ if (lu && lu->print_opt) { ++ struct rtattr *attr[lu->maxattr+1], **data = NULL; + +- if (1) { +- struct rtattr *attr[lu->maxattr+1], **data = NULL; ++ if (linkinfo[IFLA_INFO_DATA]) { ++ parse_rtattr_nested(attr, lu->maxattr, ++ linkinfo[IFLA_INFO_DATA]); ++ data = attr; ++ } ++ lu->print_opt(lu, fp, data); + +- if (linkinfo[IFLA_INFO_DATA]) { +- parse_rtattr_nested(attr, lu->maxattr, +- linkinfo[IFLA_INFO_DATA]); +- data = attr; ++ if (linkinfo[IFLA_INFO_XSTATS] && show_stats && ++ lu->print_xstats) ++ lu->print_xstats(lu, fp, linkinfo[IFLA_INFO_XSTATS]); + } +- lu->print_opt(lu, fp, data); ++ } + +- if (linkinfo[IFLA_INFO_XSTATS] && show_stats && +- lu->print_xstats) +- lu->print_xstats(lu, fp, linkinfo[IFLA_INFO_XSTATS]); ++ if (linkinfo[IFLA_INFO_SLAVE_KIND]) { ++ slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]); ++ ++ fprintf(fp, "%s", _SL_); ++ fprintf(fp, " %s_slave ", slave_kind); ++ ++ slave_lu = get_link_slave_kind(slave_kind); ++ if (slave_lu && slave_lu->print_opt) { ++ struct rtattr *attr[slave_lu->maxattr+1], **data = NULL; ++ ++ if (linkinfo[IFLA_INFO_SLAVE_DATA]) { ++ parse_rtattr_nested(attr, slave_lu->maxattr, ++ linkinfo[IFLA_INFO_SLAVE_DATA]); ++ data = attr; ++ } ++ slave_lu->print_opt(slave_lu, fp, data); ++ } + } + } + +diff --git a/ip/iplink.c b/ip/iplink.c +index 3024e99..8d6a2b3 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "rt_names.h" + #include "utils.h" +@@ -110,14 +111,15 @@ static int on_off(const char *msg, const char *realval) + static void *BODY; /* cached dlopen(NULL) handle */ + static struct link_util *linkutil_list; + +-struct link_util *get_link_kind(const char *id) ++static struct link_util *__get_link_kind(const char *id, bool slave) + { + void *dlh; + char buf[256]; + struct link_util *l; + + for (l = linkutil_list; l; l = l->next) +- if (strcmp(l->id, id) == 0) ++ if (strcmp(l->id, id) == 0 && ++ l->slave == slave) + return l; + + snprintf(buf, sizeof(buf), LIBDIR "/ip/link_%s.so", id); +@@ -132,7 +134,10 @@ struct link_util *get_link_kind(const char *id) + } + } + +- snprintf(buf, sizeof(buf), "%s_link_util", id); ++ if (slave) ++ snprintf(buf, sizeof(buf), "%s_slave_link_util", id); ++ else ++ snprintf(buf, sizeof(buf), "%s_link_util", id); + l = dlsym(dlh, buf); + if (l == NULL) + return NULL; +@@ -142,6 +147,16 @@ struct link_util *get_link_kind(const char *id) + return l; + } + ++struct link_util *get_link_kind(const char *id) ++{ ++ return __get_link_kind(id, false); ++} ++ ++struct link_util *get_link_slave_kind(const char *id) ++{ ++ return __get_link_kind(id, true); ++} ++ + static int get_link_mode(const char *mode) + { + if (strcasecmp(mode, "default") == 0) +-- +1.8.3.1 + diff --git a/SOURCES/0055-iplink-add-support-for-bonding-slave.patch b/SOURCES/0055-iplink-add-support-for-bonding-slave.patch new file mode 100644 index 0000000..becc4c3 --- /dev/null +++ b/SOURCES/0055-iplink-add-support-for-bonding-slave.patch @@ -0,0 +1,134 @@ +From 95014c8dbd2a76b735fed48bd2985d9b51f5f48a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:25:58 +0100 +Subject: [PATCH] iplink: add support for bonding slave + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 730d3f61d91ff +Conflicts: Patch adjusted for missing HSR device support in RHEL7 + +commit 730d3f61d91ffefd58adcae6d2765e94a14fa3af +Author: Jiri Pirko +Date: Thu Jan 23 17:52:54 2014 +0100 + + iplink: add support for bonding slave + + Signed-off-by: Jiri Pirko +--- + ip/Makefile | 2 +- + ip/iplink_bond_slave.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 91 insertions(+), 1 deletion(-) + create mode 100644 ip/iplink_bond_slave.c + +diff --git a/ip/Makefile b/ip/Makefile +index 76878fb..080b079 100644 +--- a/ip/Makefile ++++ b/ip/Makefile +@@ -5,7 +5,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ + iplink_vlan.o link_veth.o link_gre.o iplink_can.o \ + iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o link_vti6.o \ + iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \ +- link_iptnl.o link_gre6.o iplink_bond.o ++ link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o + + RTMONOBJ=rtmon.o + +diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c +new file mode 100644 +index 0000000..bb4e1d6 +--- /dev/null ++++ b/ip/iplink_bond_slave.c +@@ -0,0 +1,90 @@ ++/* ++ * iplink_bond_slave.c Bonding slave device support ++ * ++ * 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. ++ * ++ * Authors: Jiri Pirko ++ */ ++ ++#include ++#include ++#include ++ ++#include "rt_names.h" ++#include "utils.h" ++#include "ip_common.h" ++ ++static const char *slave_states[] = { ++ [BOND_STATE_ACTIVE] = "ACTIVE", ++ [BOND_STATE_BACKUP] = "BACKUP", ++}; ++ ++static void print_slave_state(FILE *f, struct rtattr *tb) ++{ ++ unsigned int state = rta_getattr_u8(tb); ++ ++ if (state >= sizeof(slave_states) / sizeof(slave_states[0])) ++ fprintf(f, "state %d ", state); ++ else ++ fprintf(f, "state %s ", slave_states[state]); ++} ++ ++static const char *slave_mii_status[] = { ++ [BOND_LINK_UP] = "UP", ++ [BOND_LINK_FAIL] = "GOING_DOWN", ++ [BOND_LINK_DOWN] = "DOWN", ++ [BOND_LINK_BACK] = "GOING_BACK", ++}; ++ ++static void print_slave_mii_status(FILE *f, struct rtattr *tb) ++{ ++ unsigned int status = rta_getattr_u8(tb); ++ ++ fprintf(f, "mii_status %d ", status); ++ if (status >= sizeof(slave_mii_status) / sizeof(slave_mii_status[0])) ++ fprintf(f, "mii_status %d ", status); ++ else ++ fprintf(f, "mii_status %s ", slave_mii_status[status]); ++} ++ ++static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) ++{ ++ SPRINT_BUF(b1); ++ if (!tb) ++ return; ++ ++ if (tb[IFLA_BOND_SLAVE_STATE]) ++ print_slave_state(f, tb[IFLA_BOND_SLAVE_STATE]); ++ ++ if (tb[IFLA_BOND_SLAVE_MII_STATUS]) ++ print_slave_mii_status(f, tb[IFLA_BOND_SLAVE_MII_STATUS]); ++ ++ if (tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT]) ++ fprintf(f, "link_failure_count %d ", ++ rta_getattr_u32(tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT])); ++ ++ if (tb[IFLA_BOND_SLAVE_PERM_HWADDR]) ++ fprintf(f, "perm_hwaddr %s ", ++ ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_SLAVE_PERM_HWADDR]), ++ RTA_PAYLOAD(tb[IFLA_BOND_SLAVE_PERM_HWADDR]), ++ 0, b1, sizeof(b1))); ++ ++ if (tb[IFLA_BOND_SLAVE_QUEUE_ID]) ++ fprintf(f, "queue_id %d ", ++ rta_getattr_u16(tb[IFLA_BOND_SLAVE_QUEUE_ID])); ++ ++ if (tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID]) ++ fprintf(f, "ad_aggregator_id %d ", ++ rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID])); ++} ++ ++struct link_util bond_slave_link_util = { ++ .id = "bond", ++ .maxattr = IFLA_BOND_SLAVE_MAX, ++ .print_opt = bond_slave_print_opt, ++ .slave = true, ++}; ++ +-- +1.8.3.1 + diff --git a/SOURCES/0056-iplink_bond-fix-arp_all_targets-parameter-name-in-ou.patch b/SOURCES/0056-iplink_bond-fix-arp_all_targets-parameter-name-in-ou.patch new file mode 100644 index 0000000..ff49e68 --- /dev/null +++ b/SOURCES/0056-iplink_bond-fix-arp_all_targets-parameter-name-in-ou.patch @@ -0,0 +1,42 @@ +From 2335458a36b8e8450f3d97720d78edffb540c91f Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:26:25 +0100 +Subject: [PATCH] iplink_bond: fix arp_all_targets parameter name in output +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 32ad31fba1a88 + +commit 32ad31fba1a88df278b6f268e1849782a90bd702 +Author: Michal Kubeček +Date: Thu Feb 6 12:47:33 2014 +0100 + + iplink_bond: fix arp_all_targets parameter name in output + + Name of arp_all_targets parameter in output of "ip -d link show" + is missing trailing "s". + + Fixes: 63d127b0 ("iproute2: finish support for bonding attributes") + Signed-off-by: Michal Kubecek +--- + ip/iplink_bond.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c +index f0e5ab1..f22151e 100644 +--- a/ip/iplink_bond.c ++++ b/ip/iplink_bond.c +@@ -428,7 +428,7 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + if (tb[IFLA_BOND_ARP_ALL_TARGETS]) { + const char *arp_all_targets = get_name(arp_all_targets_tbl, + rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS])); +- fprintf(f, "arp_all_target %s ", arp_all_targets); ++ fprintf(f, "arp_all_targets %s ", arp_all_targets); + } + + if (tb[IFLA_BOND_PRIMARY] && +-- +1.8.3.1 + diff --git a/SOURCES/0057-iplink_bond-fix-parameter-value-matching.patch b/SOURCES/0057-iplink_bond-fix-parameter-value-matching.patch new file mode 100644 index 0000000..96147fe --- /dev/null +++ b/SOURCES/0057-iplink_bond-fix-parameter-value-matching.patch @@ -0,0 +1,52 @@ +From 16c4a3d6c4892e6b24ccb0f63cec449823b82ef2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:26:25 +0100 +Subject: [PATCH] iplink_bond: fix parameter value matching +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit f7a45e0955514 + +commit f7a45e09555145378bdcdb5d074472ae716803ca +Author: Michal Kubeček +Date: Thu Feb 13 17:31:59 2014 +0100 + + iplink_bond: fix parameter value matching + + Lookup function get_index() compares argument with table entries + only up to the length of the table entry so that if an entry + with lower index is a substring of a later one, earlier entry is + used even if the argument is equal to the other. For example, + + ip link set bond0 type bond xmit_hash_policy layer2+3 + + sets xmit_hash_policy to 0 (layer2) as this is found before + "layer2+3" can be checked. + + Use strcmp() to compare whole strings instead. + + v2: look for an exact match only + + Signed-off-by: Michal Kubecek +--- + ip/iplink_bond.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c +index f22151e..7a950df 100644 +--- a/ip/iplink_bond.c ++++ b/ip/iplink_bond.c +@@ -106,7 +106,7 @@ static int get_index(const char **tbl, char *name) + return i; + + for (i = 0; tbl[i]; i++) +- if (strncmp(tbl[i], name, strlen(tbl[i])) == 0) ++ if (strcmp(tbl[i], name) == 0) + return i; + + return -1; +-- +1.8.3.1 + diff --git a/SOURCES/0058-iplink_bond_slave-show-mii_status-only-once.patch b/SOURCES/0058-iplink_bond_slave-show-mii_status-only-once.patch new file mode 100644 index 0000000..69fe012 --- /dev/null +++ b/SOURCES/0058-iplink_bond_slave-show-mii_status-only-once.patch @@ -0,0 +1,41 @@ +From 49d156bff02820e919f594fb6b95b19fc6fce87d Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:26:25 +0100 +Subject: [PATCH] iplink_bond_slave: show mii_status only once +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 574e7488060ff + +commit 574e7488060ff3fb1ca65f3ee05bf34e718dbb1a +Author: Michal Kubeček +Date: Fri Feb 28 14:58:15 2014 +0100 + + iplink_bond_slave: show mii_status only once + + With "ip -d link show", bonding slave mii status is displayed + twice, once as a number and once as a name. + + Fixes: 730d3f61 ("iplink: add support for bonding slave") + Signed-off-by: Michal Kubecek +--- + ip/iplink_bond_slave.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c +index bb4e1d6..8f3fc6c 100644 +--- a/ip/iplink_bond_slave.c ++++ b/ip/iplink_bond_slave.c +@@ -43,7 +43,6 @@ static void print_slave_mii_status(FILE *f, struct rtattr *tb) + { + unsigned int status = rta_getattr_u8(tb); + +- fprintf(f, "mii_status %d ", status); + if (status >= sizeof(slave_mii_status) / sizeof(slave_mii_status[0])) + fprintf(f, "mii_status %d ", status); + else +-- +1.8.3.1 + diff --git a/SOURCES/0059-iplink-can-fix-help-text-and-man-page.patch b/SOURCES/0059-iplink-can-fix-help-text-and-man-page.patch new file mode 100644 index 0000000..bd43c94 --- /dev/null +++ b/SOURCES/0059-iplink-can-fix-help-text-and-man-page.patch @@ -0,0 +1,64 @@ +From fe40921238c1acaa322de13c7fd3ebb0cb8f2c9c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:26:25 +0100 +Subject: [PATCH] iplink: can: fix help text and man page + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 2b70fe156b719 + +commit 2b70fe156b7198ee1cbe34610025c3a86461ed02 +Author: Oliver Hartkopp +Date: Thu May 15 19:52:19 2014 +0200 + + iplink: can: fix help text and man page + + Controller Area Network (CAN) interfaces are physical network interfaces. + They can't be 'created' like software devices by 'ip link add type can'. + + Signed-off-by: Oliver Hartkopp +--- + ip/iplink.c | 4 ++-- + man/man8/ip-link.8.in | 5 +---- + 2 files changed, 3 insertions(+), 6 deletions(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index 8d6a2b3..7e6d992 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -91,8 +91,8 @@ void iplink_usage(void) + fprintf(stderr, " ip link help [ TYPE ]\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n"); +- fprintf(stderr, " can | bridge | bond | ipoib | ip6tnl | ipip | sit |\n"); +- fprintf(stderr, " vxlan | gre | gretap | ip6gre | ip6gretap | vti }\n"); ++ fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n"); ++ fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti }\n"); + } + exit(-1); + } +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index d69c930..82ae316 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -164,9 +164,6 @@ Link types: + .B bond + - Bonding device + .sp +-.B can +-- Controller Area Network interface +-.sp + .B dummy + - Dummy network interface + .sp +@@ -180,7 +177,7 @@ Link types: + - Virtual interface base on link layer address (MAC) + .sp + .B vcan +-- Virtual Local CAN interface ++- Virtual Controller Area Network interface + .sp + .B veth + - Virtual ethernet interface +-- +1.8.3.1 + diff --git a/SOURCES/0060-ip-add-nlmon-as-a-device-type-to-help-message.patch b/SOURCES/0060-ip-add-nlmon-as-a-device-type-to-help-message.patch new file mode 100644 index 0000000..3d00c45 --- /dev/null +++ b/SOURCES/0060-ip-add-nlmon-as-a-device-type-to-help-message.patch @@ -0,0 +1,39 @@ +From ee76da8edee35ab8c6b69dbb2376a93ee736e7ed Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:26:25 +0100 +Subject: [PATCH] ip: add nlmon as a device type to help message + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 7968262df6fe7 + +commit 7968262df6fe7103352105e222bc98ac1ba7a821 +Author: Masatake YAMATO +Date: Thu Jun 12 04:08:38 2014 +0900 + + ip: add nlmon as a device type to help message + + Though nlmon device can be added, it was not listed + in the output of "ip link help". + + Signed-off-by: Masatake YAMATO + Acked-by: Daniel Borkmann +--- + ip/iplink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index 7e6d992..2f8bbf9 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -92,7 +92,7 @@ void iplink_usage(void) + fprintf(stderr, "\n"); + fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n"); + fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n"); +- fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti }\n"); ++ fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon }\n"); + } + exit(-1); + } +-- +1.8.3.1 + diff --git a/SOURCES/0061-iproute2-allow-to-change-slave-options-via-type_slav.patch b/SOURCES/0061-iproute2-allow-to-change-slave-options-via-type_slav.patch new file mode 100644 index 0000000..890dc84 --- /dev/null +++ b/SOURCES/0061-iproute2-allow-to-change-slave-options-via-type_slav.patch @@ -0,0 +1,111 @@ +From c05b809a58c55860dabb5930ba19dbf8f71f137f Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:26:25 +0100 +Subject: [PATCH] iproute2: allow to change slave options via type_slave + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 620ddedada7fd + +commit 620ddedada7fddd0d1d04a3da0145535423bc237 +Author: Nikolay Aleksandrov +Date: Wed Sep 3 17:57:30 2014 +0200 + + iproute2: allow to change slave options via type_slave + + This patch adds the necessary changes to allow altering a slave device's + options via ip link set type _slave specific-option. + It also adds support to set the bonding slaves' queue_id. + + Example: + ip link set eth0 type bond_slave queue_id 10 + + Signed-off-by: Nikolay Aleksandrov + Acked-by: Jiri Pirko +--- + ip/iplink.c | 22 +++++++++++++++++++--- + ip/iplink_bond_slave.c | 19 +++++++++++++++++++ + 2 files changed, 38 insertions(+), 3 deletions(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index 2f8bbf9..f444bef 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -92,7 +92,8 @@ void iplink_usage(void) + fprintf(stderr, "\n"); + fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n"); + fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n"); +- fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon }\n"); ++ fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n"); ++ fprintf(stderr, " bond_slave }\n"); + } + exit(-1); + } +@@ -654,14 +655,29 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) + + if (type) { + struct rtattr *linkinfo = NLMSG_TAIL(&req.n); ++ char slavebuf[128], *ulinep = strchr(type, '_'); ++ int iflatype; ++ + addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); + addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type, + strlen(type)); + +- lu = get_link_kind(type); ++ if (ulinep && !strcmp(ulinep, "_slave")) { ++ strncpy(slavebuf, type, sizeof(slavebuf)); ++ slavebuf[sizeof(slavebuf) - 1] = '\0'; ++ ulinep = strchr(slavebuf, '_'); ++ /* check in case it was after sizeof(slavebuf) - 1*/ ++ if (ulinep) ++ *ulinep = '\0'; ++ lu = get_link_slave_kind(slavebuf); ++ iflatype = IFLA_INFO_SLAVE_DATA; ++ } else { ++ lu = get_link_kind(type); ++ iflatype = IFLA_INFO_DATA; ++ } + if (lu && argc) { + struct rtattr * data = NLMSG_TAIL(&req.n); +- addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0); ++ addattr_l(&req.n, sizeof(req), iflatype, NULL, 0); + + if (lu->parse_opt && + lu->parse_opt(lu, argc, argv, &req.n)) +diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c +index 8f3fc6c..aacba14 100644 +--- a/ip/iplink_bond_slave.c ++++ b/ip/iplink_bond_slave.c +@@ -80,10 +80,29 @@ static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *t + rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID])); + } + ++static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv, ++ struct nlmsghdr *n) ++{ ++ __u16 queue_id; ++ ++ while (argc > 0) { ++ if (matches(*argv, "queue_id") == 0) { ++ NEXT_ARG(); ++ if (get_u16(&queue_id, *argv, 0)) ++ invarg("queue_id is invalid", *argv); ++ addattr16(n, 1024, IFLA_BOND_SLAVE_QUEUE_ID, queue_id); ++ } ++ argc--, argv++; ++ } ++ ++ return 0; ++} ++ + struct link_util bond_slave_link_util = { + .id = "bond", + .maxattr = IFLA_BOND_SLAVE_MAX, + .print_opt = bond_slave_print_opt, ++ .parse_opt = bond_slave_parse_opt, + .slave = true, + }; + +-- +1.8.3.1 + diff --git a/SOURCES/0062-add-help-command-to-bonding-master.patch b/SOURCES/0062-add-help-command-to-bonding-master.patch new file mode 100644 index 0000000..b3a0174 --- /dev/null +++ b/SOURCES/0062-add-help-command-to-bonding-master.patch @@ -0,0 +1,36 @@ +From 93cd31f4ccc36ef387667fb0dbf6d78b493fa5b9 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:26:25 +0100 +Subject: [PATCH] add help command to bonding master + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 7feb76ce98edf + +commit 7feb76ce98edfeeffc51e3ec4deab0910df1edf4 +Author: Jiri Pirko +Date: Fri Sep 5 15:24:16 2014 +0200 + + add help command to bonding master + + Signed-off-by: Jiri Pirko +--- + ip/iplink_bond.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c +index 7a950df..539a2e6 100644 +--- a/ip/iplink_bond.c ++++ b/ip/iplink_bond.c +@@ -339,6 +339,9 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv, + } + ad_select = get_index(ad_select_tbl, *argv); + addattr8(n, 1024, IFLA_BOND_AD_SELECT, ad_select); ++ } else if (matches(*argv, "help") == 0) { ++ explain(); ++ return -1; + } else { + fprintf(stderr, "bond: unknown command \"%s\"?\n", *argv); + explain(); +-- +1.8.3.1 + diff --git a/SOURCES/0063-ip-link-Shortify-printing-the-usage-of-link-type.patch b/SOURCES/0063-ip-link-Shortify-printing-the-usage-of-link-type.patch new file mode 100644 index 0000000..db03cc5 --- /dev/null +++ b/SOURCES/0063-ip-link-Shortify-printing-the-usage-of-link-type.patch @@ -0,0 +1,78 @@ +From eb7bc8d12d4b763c3938086b9a7aa7ae45a40a5d Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:26:25 +0100 +Subject: [PATCH] ip link: Shortify printing the usage of link type + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 561e650eff679 +Conflicts: Reapplying an already backported commit, just applying + it's changes to ip/iplink_bond.c. + +commit 561e650eff679296d3f4c12657721ae769cbc187 +Author: vadimk +Date: Tue Sep 30 08:17:31 2014 +0300 + + ip link: Shortify printing the usage of link type + + Allow to print particular link type usage by: + + ip link help [TYPE] + + Currently to print usage for some link type it is needed + to use the following way: + + ip link { add | del | set } type TYPE help + + Signed-off-by: Vadim Kochan +--- + ip/iplink_bond.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c +index 539a2e6..a573f92 100644 +--- a/ip/iplink_bond.c ++++ b/ip/iplink_bond.c +@@ -112,9 +112,9 @@ static int get_index(const char **tbl, char *name) + return -1; + } + +-static void explain(void) ++static void print_explain(FILE *f) + { +- fprintf(stderr, ++ fprintf(f, + "Usage: ... bond [ mode BONDMODE ] [ active_slave SLAVE_DEV ]\n" + " [ clear_active_slave ] [ miimon MIIMON ]\n" + " [ updelay UPDELAY ] [ downdelay DOWNDELAY ]\n" +@@ -147,6 +147,11 @@ static void explain(void) + ); + } + ++static void explain(void) ++{ ++ print_explain(stderr); ++} ++ + static int bond_parse_opt(struct link_util *lu, int argc, char **argv, + struct nlmsghdr *n) + { +@@ -531,9 +536,16 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + } + } + ++static void bond_print_help(struct link_util *lu, int argc, char **argv, ++ FILE *f) ++{ ++ print_explain(f); ++} ++ + struct link_util bond_link_util = { + .id = "bond", + .maxattr = IFLA_BOND_MAX, + .parse_opt = bond_parse_opt, + .print_opt = bond_print_opt, ++ .print_help = bond_print_help, + }; +-- +1.8.3.1 + diff --git a/SOURCES/0064-iplink_bond-add-support-for-ad_actor-and-port_key-op.patch b/SOURCES/0064-iplink_bond-add-support-for-ad_actor-and-port_key-op.patch new file mode 100644 index 0000000..edb0570 --- /dev/null +++ b/SOURCES/0064-iplink_bond-add-support-for-ad_actor-and-port_key-op.patch @@ -0,0 +1,109 @@ +From e4fb787ac29b773e8d754f78f643dc9eb7445dce Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:27:20 +0100 +Subject: [PATCH] iplink_bond: add support for ad_actor and port_key options + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 6fc1f8add30b3 + +commit 6fc1f8add30b3c4387e675d0b7c1787b737f8777 +Author: Jonathan Toppins +Date: Sat May 9 00:01:59 2015 -0700 + + iplink_bond: add support for ad_actor and port_key options + + This adds support for setting and displaying the following bonding + options: + * ad_user_port_key + * ad_actor_sys_prio + * ad_actor_system + + Signed-off-by: Jonathan Toppins +--- + ip/iplink_bond.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c +index a573f92..2a9783e 100644 +--- a/ip/iplink_bond.c ++++ b/ip/iplink_bond.c +@@ -135,6 +135,9 @@ static void print_explain(FILE *f) + " [ packets_per_slave PACKETS_PER_SLAVE ]\n" + " [ lacp_rate LACP_RATE ]\n" + " [ ad_select AD_SELECT ]\n" ++ " [ ad_user_port_key PORTKEY ]\n" ++ " [ ad_actor_sys_prio SYSPRIO ]\n" ++ " [ ad_actor_system LLADDR ]\n" + "\n" + "BONDMODE := balance-rr|active-backup|balance-xor|broadcast|802.3ad|balance-tlb|balance-alb\n" + "ARP_VALIDATE := none|active|backup|all\n" +@@ -158,6 +161,7 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv, + __u8 mode, use_carrier, primary_reselect, fail_over_mac; + __u8 xmit_hash_policy, num_peer_notif, all_slaves_active; + __u8 lacp_rate, ad_select; ++ __u16 ad_user_port_key, ad_actor_sys_prio; + __u32 miimon, updelay, downdelay, arp_interval, arp_validate; + __u32 arp_all_targets, resend_igmp, min_links, lp_interval; + __u32 packets_per_slave; +@@ -344,6 +348,32 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv, + } + ad_select = get_index(ad_select_tbl, *argv); + addattr8(n, 1024, IFLA_BOND_AD_SELECT, ad_select); ++ } else if (matches(*argv, "ad_user_port_key") == 0) { ++ NEXT_ARG(); ++ if (get_u16(&ad_user_port_key, *argv, 0)) { ++ invarg("invalid ad_user_port_key", *argv); ++ return -1; ++ } ++ addattr16(n, 1024, IFLA_BOND_AD_USER_PORT_KEY, ++ ad_user_port_key); ++ } else if (matches(*argv, "ad_actor_sys_prio") == 0) { ++ NEXT_ARG(); ++ if (get_u16(&ad_actor_sys_prio, *argv, 0)) { ++ invarg("invalid ad_actor_sys_prio", *argv); ++ return -1; ++ } ++ addattr16(n, 1024, IFLA_BOND_AD_ACTOR_SYS_PRIO, ++ ad_actor_sys_prio); ++ } else if (matches(*argv, "ad_actor_system") == 0) { ++ int len; ++ char abuf[32]; ++ ++ NEXT_ARG(); ++ len = ll_addr_a2n(abuf, sizeof(abuf), *argv); ++ if (len < 0) ++ return -1; ++ addattr_l(n, 1024, IFLA_BOND_AD_ACTOR_SYSTEM, ++ abuf, len); + } else if (matches(*argv, "help") == 0) { + explain(); + return -1; +@@ -534,6 +564,25 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b))); + } + } ++ ++ if (tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]) { ++ fprintf(f, "ad_actor_sys_prio %u ", ++ rta_getattr_u16(tb[IFLA_BOND_AD_ACTOR_SYS_PRIO])); ++ } ++ ++ if (tb[IFLA_BOND_AD_USER_PORT_KEY]) { ++ fprintf(f, "ad_user_port_key %u ", ++ rta_getattr_u16(tb[IFLA_BOND_AD_USER_PORT_KEY])); ++ } ++ ++ if (tb[IFLA_BOND_AD_ACTOR_SYSTEM]) { ++ /* We assume the l2 address is an Ethernet MAC address */ ++ SPRINT_BUF(b1); ++ fprintf(f, "ad_actor_system %s ", ++ ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_AD_ACTOR_SYSTEM]), ++ RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]), ++ 1 /*ARPHDR_ETHER*/, b1, sizeof(b1))); ++ } + } + + static void bond_print_help(struct link_util *lu, int argc, char **argv, +-- +1.8.3.1 + diff --git a/SOURCES/0065-bonding-export-3ad-actor-and-partner-port-state.patch b/SOURCES/0065-bonding-export-3ad-actor-and-partner-port-state.patch new file mode 100644 index 0000000..0870c63 --- /dev/null +++ b/SOURCES/0065-bonding-export-3ad-actor-and-partner-port-state.patch @@ -0,0 +1,48 @@ +From 773a7f959b38eae8f01301b3fafaa0392759404b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:27:20 +0100 +Subject: [PATCH] bonding: export 3ad actor and partner port state + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 7d6bc3b87abad + +commit 7d6bc3b87abadddaf2e0a92c113e6ef83c226ed5 +Author: Nikolay Aleksandrov +Date: Tue Jun 16 12:26:57 2015 +0300 + + bonding: export 3ad actor and partner port state + + This patch adds support to retrieve the new bond slave attributes: + IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE + IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE + which are read-only. + + (Removed if_link.h changes already updated in net-next) + + Signed-off-by: Nikolay Aleksandrov +--- + ip/iplink_bond_slave.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c +index aacba14..33bea91 100644 +--- a/ip/iplink_bond_slave.c ++++ b/ip/iplink_bond_slave.c +@@ -78,6 +78,14 @@ static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *t + if (tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID]) + fprintf(f, "ad_aggregator_id %d ", + rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID])); ++ ++ if (tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]) ++ fprintf(f, "ad_actor_oper_port_state %d\n", ++ rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE])); ++ ++ if (tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]) ++ fprintf(f, "ad_partner_oper_port_state %d\n", ++ rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE])); + } + + static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv, +-- +1.8.3.1 + diff --git a/SOURCES/0066-iplink-bonding-add-support-for-IFLA_BOND_TLB_DYNAMIC.patch b/SOURCES/0066-iplink-bonding-add-support-for-IFLA_BOND_TLB_DYNAMIC.patch new file mode 100644 index 0000000..bdffa80 --- /dev/null +++ b/SOURCES/0066-iplink-bonding-add-support-for-IFLA_BOND_TLB_DYNAMIC.patch @@ -0,0 +1,96 @@ +From 3e07fbb9852e7d395f5fef89ee10365802df559a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:27:20 +0100 +Subject: [PATCH] iplink: bonding: add support for IFLA_BOND_TLB_DYNAMIC_LB + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit d02e46627f29b + +commit d02e46627f29b6bc761e6b6afd9198da001b13f1 +Author: Nikolay Aleksandrov +Date: Mon Aug 3 12:19:55 2015 +0200 + + iplink: bonding: add support for IFLA_BOND_TLB_DYNAMIC_LB + + Add support to be able to set and show the value of tlb_dynamic_lb + (IFLA_BOND_TLB_DYNAMIC_LB). + Example: + $ ip -d link show dev bond0 type bond + 7: bond0: mtu 1500 qdisc noop state DOWN + mode DEFAULT group default + link/ether ce:2f:e1:6e:d7:e0 brd ff:ff:ff:ff:ff:ff promiscuity 0 + bond mode balance-tlb miimon 100 updelay 0 downdelay 0 use_carrier 1 + arp_interval 0 arp_validate none arp_all_targets any primary_reselect + always fail_over_mac none xmit_hash_policy layer2 resend_igmp 1 + num_grat_arp 1 all_slaves_active 0 min_links 0 lp_interval 1 + packets_per_slave 1 lacp_rate slow ad_select stable tlb_dynamic_lb 1 + addrgenmode eui64 + + $ ip -d l set dev bond0 type bond tlb_dynamic_lb 0 + $ ip -d link show dev bond0 type bond + 7: bond0: mtu 1500 qdisc noop state DOWN + mode DEFAULT group default + link/ether ce:2f:e1:6e:d7:e0 brd ff:ff:ff:ff:ff:ff promiscuity 0 + bond mode balance-tlb miimon 100 updelay 0 downdelay 0 use_carrier 1 + arp_interval 0 arp_validate none arp_all_targets any primary_reselect + always fail_over_mac none xmit_hash_policy layer2 resend_igmp 1 + num_grat_arp 1 all_slaves_active 0 min_links 0 lp_interval 1 + packets_per_slave 1 lacp_rate slow ad_select stable tlb_dynamic_lb 0 + addrgenmode eui64 + + Signed-off-by: Nikolay Aleksandrov +--- + ip/iplink_bond.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c +index 2a9783e..1b50de9 100644 +--- a/ip/iplink_bond.c ++++ b/ip/iplink_bond.c +@@ -133,6 +133,7 @@ static void print_explain(FILE *f) + " [ min_links MIN_LINKS ]\n" + " [ lp_interval LP_INTERVAL ]\n" + " [ packets_per_slave PACKETS_PER_SLAVE ]\n" ++ " [ tlb_dynamic_lb TLB_DYNAMIC_LB ]\n" + " [ lacp_rate LACP_RATE ]\n" + " [ ad_select AD_SELECT ]\n" + " [ ad_user_port_key PORTKEY ]\n" +@@ -160,7 +161,7 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv, + { + __u8 mode, use_carrier, primary_reselect, fail_over_mac; + __u8 xmit_hash_policy, num_peer_notif, all_slaves_active; +- __u8 lacp_rate, ad_select; ++ __u8 lacp_rate, ad_select, tlb_dynamic_lb; + __u16 ad_user_port_key, ad_actor_sys_prio; + __u32 miimon, updelay, downdelay, arp_interval, arp_validate; + __u32 arp_all_targets, resend_igmp, min_links, lp_interval; +@@ -374,6 +375,14 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv, + return -1; + addattr_l(n, 1024, IFLA_BOND_AD_ACTOR_SYSTEM, + abuf, len); ++ } else if (matches(*argv, "tlb_dynamic_lb") == 0) { ++ NEXT_ARG(); ++ if (get_u8(&tlb_dynamic_lb, *argv, 0)) { ++ invarg("invalid tlb_dynamic_lb", *argv); ++ return -1; ++ } ++ addattr8(n, 1024, IFLA_BOND_TLB_DYNAMIC_LB, ++ tlb_dynamic_lb); + } else if (matches(*argv, "help") == 0) { + explain(); + return -1; +@@ -583,6 +592,11 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]), + 1 /*ARPHDR_ETHER*/, b1, sizeof(b1))); + } ++ ++ if (tb[IFLA_BOND_TLB_DYNAMIC_LB]) { ++ fprintf(f, "tlb_dynamic_lb %u ", ++ rta_getattr_u8(tb[IFLA_BOND_TLB_DYNAMIC_LB])); ++ } + } + + static void bond_print_help(struct link_util *lu, int argc, char **argv, +-- +1.8.3.1 + diff --git a/SOURCES/0067-bond-fix-return-after-invarg.patch b/SOURCES/0067-bond-fix-return-after-invarg.patch new file mode 100644 index 0000000..e36ba60 --- /dev/null +++ b/SOURCES/0067-bond-fix-return-after-invarg.patch @@ -0,0 +1,234 @@ +From 83016b9c3734c833ea2c329b371369a1de8bdc09 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:27:20 +0100 +Subject: [PATCH] bond: fix return after invarg + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit e0f229fb75349 + +commit e0f229fb7534991f7f1b4ca16a4fcc091a8d50af +Author: Stephen Hemminger +Date: Thu Aug 13 14:20:54 2015 -0700 + + bond: fix return after invarg +--- + ip/iplink_bond.c | 95 +++++++++++++++++++------------------------------------- + 1 file changed, 32 insertions(+), 63 deletions(-) + +diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c +index 1b50de9..9d96cfe 100644 +--- a/ip/iplink_bond.c ++++ b/ip/iplink_bond.c +@@ -171,10 +171,8 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv, + while (argc > 0) { + if (matches(*argv, "mode") == 0) { + NEXT_ARG(); +- if (get_index(mode_tbl, *argv) < 0) { ++ if (get_index(mode_tbl, *argv) < 0) + invarg("invalid mode", *argv); +- return -1; +- } + mode = get_index(mode_tbl, *argv); + addattr8(n, 1024, IFLA_BOND_MODE, mode); + } else if (matches(*argv, "active_slave") == 0) { +@@ -187,38 +185,28 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv, + addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, 0); + } else if (matches(*argv, "miimon") == 0) { + NEXT_ARG(); +- if (get_u32(&miimon, *argv, 0)) { ++ if (get_u32(&miimon, *argv, 0)) + invarg("invalid miimon", *argv); +- return -1; +- } + addattr32(n, 1024, IFLA_BOND_MIIMON, miimon); + } else if (matches(*argv, "updelay") == 0) { + NEXT_ARG(); +- if (get_u32(&updelay, *argv, 0)) { ++ if (get_u32(&updelay, *argv, 0)) + invarg("invalid updelay", *argv); +- return -1; +- } + addattr32(n, 1024, IFLA_BOND_UPDELAY, updelay); + } else if (matches(*argv, "downdelay") == 0) { + NEXT_ARG(); +- if (get_u32(&downdelay, *argv, 0)) { ++ if (get_u32(&downdelay, *argv, 0)) + invarg("invalid downdelay", *argv); +- return -1; +- } + addattr32(n, 1024, IFLA_BOND_DOWNDELAY, downdelay); + } else if (matches(*argv, "use_carrier") == 0) { + NEXT_ARG(); +- if (get_u8(&use_carrier, *argv, 0)) { ++ if (get_u8(&use_carrier, *argv, 0)) + invarg("invalid use_carrier", *argv); +- return -1; +- } + addattr8(n, 1024, IFLA_BOND_USE_CARRIER, use_carrier); + } else if (matches(*argv, "arp_interval") == 0) { + NEXT_ARG(); +- if (get_u32(&arp_interval, *argv, 0)) { ++ if (get_u32(&arp_interval, *argv, 0)) + invarg("invalid arp_interval", *argv); +- return -1; +- } + addattr32(n, 1024, IFLA_BOND_ARP_INTERVAL, arp_interval); + } else if (matches(*argv, "arp_ip_target") == 0) { + struct rtattr * nest = addattr_nest(n, 1024, +@@ -239,18 +227,14 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv, + addattr_nest_end(n, nest); + } else if (matches(*argv, "arp_validate") == 0) { + NEXT_ARG(); +- if (get_index(arp_validate_tbl, *argv) < 0) { ++ if (get_index(arp_validate_tbl, *argv) < 0) + invarg("invalid arp_validate", *argv); +- return -1; +- } + arp_validate = get_index(arp_validate_tbl, *argv); + addattr32(n, 1024, IFLA_BOND_ARP_VALIDATE, arp_validate); + } else if (matches(*argv, "arp_all_targets") == 0) { + NEXT_ARG(); +- if (get_index(arp_all_targets_tbl, *argv) < 0) { ++ if (get_index(arp_all_targets_tbl, *argv) < 0) + invarg("invalid arp_all_targets", *argv); +- return -1; +- } + arp_all_targets = get_index(arp_all_targets_tbl, *argv); + addattr32(n, 1024, IFLA_BOND_ARP_ALL_TARGETS, arp_all_targets); + } else if (matches(*argv, "primary") == 0) { +@@ -261,108 +245,93 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv, + addattr32(n, 1024, IFLA_BOND_PRIMARY, ifindex); + } else if (matches(*argv, "primary_reselect") == 0) { + NEXT_ARG(); +- if (get_index(primary_reselect_tbl, *argv) < 0) { ++ if (get_index(primary_reselect_tbl, *argv) < 0) + invarg("invalid primary_reselect", *argv); +- return -1; +- } + primary_reselect = get_index(primary_reselect_tbl, *argv); + addattr8(n, 1024, IFLA_BOND_PRIMARY_RESELECT, + primary_reselect); + } else if (matches(*argv, "fail_over_mac") == 0) { + NEXT_ARG(); +- if (get_index(fail_over_mac_tbl, *argv) < 0) { ++ if (get_index(fail_over_mac_tbl, *argv) < 0) + invarg("invalid fail_over_mac", *argv); +- return -1; +- } + fail_over_mac = get_index(fail_over_mac_tbl, *argv); + addattr8(n, 1024, IFLA_BOND_FAIL_OVER_MAC, + fail_over_mac); + } else if (matches(*argv, "xmit_hash_policy") == 0) { + NEXT_ARG(); +- if (get_index(xmit_hash_policy_tbl, *argv) < 0) { ++ if (get_index(xmit_hash_policy_tbl, *argv) < 0) + invarg("invalid xmit_hash_policy", *argv); +- return -1; +- } ++ + xmit_hash_policy = get_index(xmit_hash_policy_tbl, *argv); + addattr8(n, 1024, IFLA_BOND_XMIT_HASH_POLICY, + xmit_hash_policy); + } else if (matches(*argv, "resend_igmp") == 0) { + NEXT_ARG(); +- if (get_u32(&resend_igmp, *argv, 0)) { ++ if (get_u32(&resend_igmp, *argv, 0)) + invarg("invalid resend_igmp", *argv); +- return -1; +- } ++ + addattr32(n, 1024, IFLA_BOND_RESEND_IGMP, resend_igmp); + } else if (matches(*argv, "num_grat_arp") == 0 || + matches(*argv, "num_unsol_na") == 0) { + NEXT_ARG(); +- if (get_u8(&num_peer_notif, *argv, 0)) { ++ if (get_u8(&num_peer_notif, *argv, 0)) + invarg("invalid num_grat_arp|num_unsol_na", + *argv); +- return -1; +- } ++ + addattr8(n, 1024, IFLA_BOND_NUM_PEER_NOTIF, + num_peer_notif); + } else if (matches(*argv, "all_slaves_active") == 0) { + NEXT_ARG(); +- if (get_u8(&all_slaves_active, *argv, 0)) { ++ if (get_u8(&all_slaves_active, *argv, 0)) + invarg("invalid all_slaves_active", *argv); +- return -1; +- } ++ + addattr8(n, 1024, IFLA_BOND_ALL_SLAVES_ACTIVE, + all_slaves_active); + } else if (matches(*argv, "min_links") == 0) { + NEXT_ARG(); +- if (get_u32(&min_links, *argv, 0)) { ++ if (get_u32(&min_links, *argv, 0)) + invarg("invalid min_links", *argv); +- return -1; +- } ++ + addattr32(n, 1024, IFLA_BOND_MIN_LINKS, min_links); + } else if (matches(*argv, "lp_interval") == 0) { + NEXT_ARG(); +- if (get_u32(&lp_interval, *argv, 0)) { ++ if (get_u32(&lp_interval, *argv, 0)) + invarg("invalid lp_interval", *argv); +- return -1; +- } ++ + addattr32(n, 1024, IFLA_BOND_LP_INTERVAL, lp_interval); + } else if (matches(*argv, "packets_per_slave") == 0) { + NEXT_ARG(); +- if (get_u32(&packets_per_slave, *argv, 0)) { ++ if (get_u32(&packets_per_slave, *argv, 0)) + invarg("invalid packets_per_slave", *argv); +- return -1; +- } ++ + addattr32(n, 1024, IFLA_BOND_PACKETS_PER_SLAVE, + packets_per_slave); + } else if (matches(*argv, "lacp_rate") == 0) { + NEXT_ARG(); +- if (get_index(lacp_rate_tbl, *argv) < 0) { ++ if (get_index(lacp_rate_tbl, *argv) < 0) + invarg("invalid lacp_rate", *argv); +- return -1; +- } ++ + lacp_rate = get_index(lacp_rate_tbl, *argv); + addattr8(n, 1024, IFLA_BOND_AD_LACP_RATE, lacp_rate); + } else if (matches(*argv, "ad_select") == 0) { + NEXT_ARG(); +- if (get_index(ad_select_tbl, *argv) < 0) { ++ if (get_index(ad_select_tbl, *argv) < 0) + invarg("invalid ad_select", *argv); +- return -1; +- } ++ + ad_select = get_index(ad_select_tbl, *argv); + addattr8(n, 1024, IFLA_BOND_AD_SELECT, ad_select); + } else if (matches(*argv, "ad_user_port_key") == 0) { + NEXT_ARG(); +- if (get_u16(&ad_user_port_key, *argv, 0)) { ++ if (get_u16(&ad_user_port_key, *argv, 0)) + invarg("invalid ad_user_port_key", *argv); +- return -1; +- } ++ + addattr16(n, 1024, IFLA_BOND_AD_USER_PORT_KEY, + ad_user_port_key); + } else if (matches(*argv, "ad_actor_sys_prio") == 0) { + NEXT_ARG(); +- if (get_u16(&ad_actor_sys_prio, *argv, 0)) { ++ if (get_u16(&ad_actor_sys_prio, *argv, 0)) + invarg("invalid ad_actor_sys_prio", *argv); +- return -1; +- } ++ + addattr16(n, 1024, IFLA_BOND_AD_ACTOR_SYS_PRIO, + ad_actor_sys_prio); + } else if (matches(*argv, "ad_actor_system") == 0) { +-- +1.8.3.1 + diff --git a/SOURCES/0068-ip-link-missing-options-in-bond-usage.patch b/SOURCES/0068-ip-link-missing-options-in-bond-usage.patch new file mode 100644 index 0000000..7bd2e26 --- /dev/null +++ b/SOURCES/0068-ip-link-missing-options-in-bond-usage.patch @@ -0,0 +1,35 @@ +From 66db03bb795390998c935f05bcfe5d379853c46e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:27:28 +0100 +Subject: [PATCH] ip link: missing options in bond usage + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit a197883432896 + +commit a197883432896d52c8f3b0ef34c2c4887a61473e +Author: Arthur Gautier +Date: Fri Sep 11 12:48:28 2015 +0000 + + ip link: missing options in bond usage + + Signed-off-by: Arthur Gautier +--- + ip/iplink_bond.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c +index 9d96cfe..cb2f045 100644 +--- a/ip/iplink_bond.c ++++ b/ip/iplink_bond.c +@@ -145,7 +145,7 @@ static void print_explain(FILE *f) + "ARP_ALL_TARGETS := any|all\n" + "PRIMARY_RESELECT := always|better|failure\n" + "FAIL_OVER_MAC := none|active|follow\n" +- "XMIT_HASH_POLICY := layer2|layer2+3|layer3+4\n" ++ "XMIT_HASH_POLICY := layer2|layer2+3|layer3+4|encap2+3|encap3+4\n" + "LACP_RATE := slow|fast\n" + "AD_SELECT := stable|bandwidth|count\n" + ); +-- +1.8.3.1 + diff --git a/SOURCES/0069-ip-remove-extra-newlines-at-end-of-file.patch b/SOURCES/0069-ip-remove-extra-newlines-at-end-of-file.patch new file mode 100644 index 0000000..817301b --- /dev/null +++ b/SOURCES/0069-ip-remove-extra-newlines-at-end-of-file.patch @@ -0,0 +1,73 @@ +From f681ef8608cd2d4addf701d1773d5e01afcbde95 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:27:28 +0100 +Subject: [PATCH] ip: remove extra newlines at end-of-file + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit f7520a1998995 +Conflicts: Dropped changes to ip/ipfou.c since RHEL7 does not support + that. + +commit f7520a1998995f29730692212c1c87a39064e168 +Author: Stephen Hemminger +Date: Fri Oct 23 15:41:58 2015 -0700 + + ip: remove extra newlines at end-of-file + + Shouldn't have extra blank lines. +--- + ip/ipaddrlabel.c | 1 - + ip/iplink_bond_slave.c | 1 - + ip/ipprefix.c | 1 - + ip/iproute.c | 1 - + ip/tcp_metrics.c | 1 - + 5 files changed, 5 deletions(-) + +diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c +index c5d69f4..1158b33 100644 +--- a/ip/ipaddrlabel.c ++++ b/ip/ipaddrlabel.c +@@ -263,4 +263,3 @@ int do_ipaddrlabel(int argc, char **argv) + fprintf(stderr, "Command \"%s\" is unknown, try \"ip addrlabel help\".\n", *argv); + exit(-1); + } +- +diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c +index 33bea91..9b569b1 100644 +--- a/ip/iplink_bond_slave.c ++++ b/ip/iplink_bond_slave.c +@@ -113,4 +113,3 @@ struct link_util bond_slave_link_util = { + .parse_opt = bond_slave_parse_opt, + .slave = true, + }; +- +diff --git a/ip/ipprefix.c b/ip/ipprefix.c +index 42f51e7..286c09b 100644 +--- a/ip/ipprefix.c ++++ b/ip/ipprefix.c +@@ -108,4 +108,3 @@ int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) + + return 0; + } +- +diff --git a/ip/iproute.c b/ip/iproute.c +index 27e04a8..b7e0b15 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -1696,4 +1696,3 @@ int do_iproute(int argc, char **argv) + fprintf(stderr, "Command \"%s\" is unknown, try \"ip route help\".\n", *argv); + exit(-1); + } +- +diff --git a/ip/tcp_metrics.c b/ip/tcp_metrics.c +index 8fa4b26..7e7cf27 100644 +--- a/ip/tcp_metrics.c ++++ b/ip/tcp_metrics.c +@@ -427,4 +427,3 @@ int do_tcp_metrics(int argc, char **argv) + "try \"ip tcp_metrics help\".\n", *argv); + exit(-1); + } +- +-- +1.8.3.1 + diff --git a/SOURCES/0070-iplink-bond_slave-fix-ad_actor-partner_oper_port_sta.patch b/SOURCES/0070-iplink-bond_slave-fix-ad_actor-partner_oper_port_sta.patch new file mode 100644 index 0000000..90b00f3 --- /dev/null +++ b/SOURCES/0070-iplink-bond_slave-fix-ad_actor-partner_oper_port_sta.patch @@ -0,0 +1,47 @@ +From 35fdf5a241f8111eba6b81e9f736ac9df1e07bc4 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Feb 2016 18:28:00 +0100 +Subject: [PATCH] iplink: bond_slave: fix ad_actor/partner_oper_port_state + output + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit e6c38e2c59c92 + +commit e6c38e2c59c922229ca615b6f913523dd6ee7c24 +Author: Nikolay Aleksandrov +Date: Mon Feb 8 17:13:58 2016 +0100 + + iplink: bond_slave: fix ad_actor/partner_oper_port_state output + + It seems that I've made a mistake when I exported these, instead of a + space in the end I've put a newline character which is wrong and breaks + the single line output. + + Fixes: 7d6bc3b87abad ("bonding: export 3ad actor and partner port state") + Reported-by: Sam Tannous + Signed-off-by: Nikolay Aleksandrov +--- + ip/iplink_bond_slave.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c +index 9b569b1..2f3364e 100644 +--- a/ip/iplink_bond_slave.c ++++ b/ip/iplink_bond_slave.c +@@ -80,11 +80,11 @@ static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *t + rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID])); + + if (tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]) +- fprintf(f, "ad_actor_oper_port_state %d\n", ++ fprintf(f, "ad_actor_oper_port_state %d ", + rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE])); + + if (tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]) +- fprintf(f, "ad_partner_oper_port_state %d\n", ++ fprintf(f, "ad_partner_oper_port_state %d ", + rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE])); + } + +-- +1.8.3.1 + diff --git a/SOURCES/0071-add-bridge_slave-device-support.patch b/SOURCES/0071-add-bridge_slave-device-support.patch new file mode 100644 index 0000000..d97b0c3 --- /dev/null +++ b/SOURCES/0071-add-bridge_slave-device-support.patch @@ -0,0 +1,227 @@ +From 6ec8ce797ff664a31494a1b9693465f1c545fb91 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 24 Feb 2016 10:48:07 +0100 +Subject: [PATCH] add bridge_slave device support + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1270759 +Upstream Status: iproute2.git commit 8c39db391d21a +Conflicts: Context conflict due to missing HSR device support. + +commit 8c39db391d21ad118e9f2fd6d35f097dea01cdf4 +Author: Jiri Pirko +Date: Sun Sep 28 16:31:04 2014 -0700 + + add bridge_slave device support + + Note this depends on "iproute2: allow to change slave options via + type_slave" +--- + ip/Makefile | 3 +- + ip/iplink_bridge_slave.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 183 insertions(+), 1 deletion(-) + create mode 100644 ip/iplink_bridge_slave.c + +diff --git a/ip/Makefile b/ip/Makefile +index 080b079..8d4f128 100644 +--- a/ip/Makefile ++++ b/ip/Makefile +@@ -5,7 +5,8 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ + iplink_vlan.o link_veth.o link_gre.o iplink_can.o \ + iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o link_vti6.o \ + iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \ +- link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o ++ link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o \ ++ iplink_bridge_slave.o + + RTMONOBJ=rtmon.o + +diff --git a/ip/iplink_bridge_slave.c b/ip/iplink_bridge_slave.c +new file mode 100644 +index 0000000..a285185 +--- /dev/null ++++ b/ip/iplink_bridge_slave.c +@@ -0,0 +1,181 @@ ++/* ++ * iplink_bridge_slave.c Bridge slave device support ++ * ++ * 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. ++ * ++ * Authors: Jiri Pirko ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "rt_names.h" ++#include "utils.h" ++#include "ip_common.h" ++ ++static void explain(void) ++{ ++ fprintf(stderr, ++ "Usage: ... bridge_slave [ state STATE ] [ priority PRIO ] [cost COST ]\n" ++ " [ guard {on | off} ]\n" ++ " [ hairpin {on | off} ] \n" ++ " [ fastleave {on | off} ]\n" ++ " [ root_block {on | off} ]\n" ++ " [ learning {on | off} ]\n" ++ " [ flood {on | off} ]\n" ++ ); ++} ++ ++static const char *port_states[] = { ++ [BR_STATE_DISABLED] = "disabled", ++ [BR_STATE_LISTENING] = "listening", ++ [BR_STATE_LEARNING] = "learning", ++ [BR_STATE_FORWARDING] = "forwarding", ++ [BR_STATE_BLOCKING] = "blocking", ++}; ++ ++static void print_portstate(FILE *f, __u8 state) ++{ ++ if (state <= BR_STATE_BLOCKING) ++ fprintf(f, "state %s ", port_states[state]); ++ else ++ fprintf(f, "state (%d) ", state); ++} ++ ++static void print_onoff(FILE *f, char *flag, __u8 val) ++{ ++ fprintf(f, "%s %s ", flag, val ? "on" : "off"); ++} ++ ++static void bridge_slave_print_opt(struct link_util *lu, FILE *f, ++ struct rtattr *tb[]) ++{ ++ if (!tb) ++ return; ++ ++ if (tb[IFLA_BRPORT_STATE]) ++ print_portstate(f, rta_getattr_u8(tb[IFLA_BRPORT_STATE])); ++ ++ if (tb[IFLA_BRPORT_PRIORITY]) ++ fprintf(f, "priority %d ", ++ rta_getattr_u16(tb[IFLA_BRPORT_PRIORITY])); ++ ++ if (tb[IFLA_BRPORT_COST]) ++ fprintf(f, "cost %d ", ++ rta_getattr_u32(tb[IFLA_BRPORT_COST])); ++ ++ if (tb[IFLA_BRPORT_MODE]) ++ print_onoff(f, "hairpin", ++ rta_getattr_u8(tb[IFLA_BRPORT_MODE])); ++ ++ if (tb[IFLA_BRPORT_GUARD]) ++ print_onoff(f, "guard", ++ rta_getattr_u8(tb[IFLA_BRPORT_GUARD])); ++ ++ if (tb[IFLA_BRPORT_PROTECT]) ++ print_onoff(f, "root_block", ++ rta_getattr_u8(tb[IFLA_BRPORT_PROTECT])); ++ ++ if (tb[IFLA_BRPORT_FAST_LEAVE]) ++ print_onoff(f, "fastleave", ++ rta_getattr_u8(tb[IFLA_BRPORT_FAST_LEAVE])); ++ ++ if (tb[IFLA_BRPORT_LEARNING]) ++ print_onoff(f, "learning", ++ rta_getattr_u8(tb[IFLA_BRPORT_LEARNING])); ++ ++ if (tb[IFLA_BRPORT_UNICAST_FLOOD]) ++ print_onoff(f, "flood", ++ rta_getattr_u8(tb[IFLA_BRPORT_UNICAST_FLOOD])); ++} ++ ++static void bridge_slave_parse_on_off(char *arg_name, char *arg_val, ++ struct nlmsghdr *n, int type) ++{ ++ __u8 val; ++ ++ if (strcmp(arg_val, "on") == 0) ++ val = 1; ++ else if (strcmp(arg_val, "off") == 0) ++ val = 0; ++ else ++ invarg("should be \"on\" or \"off\"", arg_name); ++ ++ addattr8(n, 1024, type, val); ++} ++ ++static int bridge_slave_parse_opt(struct link_util *lu, int argc, char **argv, ++ struct nlmsghdr *n) ++{ ++ __u8 state; ++ __u16 priority; ++ __u32 cost; ++ ++ while (argc > 0) { ++ if (matches(*argv, "state") == 0) { ++ NEXT_ARG(); ++ if (get_u8(&state, *argv, 0)) ++ invarg("state is invalid", *argv); ++ addattr8(n, 1024, IFLA_BRPORT_STATE, state); ++ } else if (matches(*argv, "priority") == 0) { ++ NEXT_ARG(); ++ if (get_u16(&priority, *argv, 0)) ++ invarg("priority is invalid", *argv); ++ addattr16(n, 1024, IFLA_BRPORT_PRIORITY, priority); ++ } else if (matches(*argv, "cost") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&cost, *argv, 0)) ++ invarg("cost is invalid", *argv); ++ addattr32(n, 1024, IFLA_BRPORT_COST, cost); ++ } else if (matches(*argv, "hairpin") == 0) { ++ NEXT_ARG(); ++ bridge_slave_parse_on_off("hairpin", *argv, n, ++ IFLA_BRPORT_MODE); ++ } else if (matches(*argv, "guard") == 0) { ++ NEXT_ARG(); ++ bridge_slave_parse_on_off("guard", *argv, n, ++ IFLA_BRPORT_GUARD); ++ } else if (matches(*argv, "root_block") == 0) { ++ NEXT_ARG(); ++ bridge_slave_parse_on_off("root_block", *argv, n, ++ IFLA_BRPORT_PROTECT); ++ } else if (matches(*argv, "fastleave") == 0) { ++ NEXT_ARG(); ++ bridge_slave_parse_on_off("fastleave", *argv, n, ++ IFLA_BRPORT_FAST_LEAVE); ++ } else if (matches(*argv, "learning") == 0) { ++ NEXT_ARG(); ++ bridge_slave_parse_on_off("learning", *argv, n, ++ IFLA_BRPORT_LEARNING); ++ } else if (matches(*argv, "flood") == 0) { ++ NEXT_ARG(); ++ bridge_slave_parse_on_off("flood", *argv, n, ++ IFLA_BRPORT_UNICAST_FLOOD); ++ } else if (matches(*argv, "help") == 0) { ++ explain(); ++ return -1; ++ } else { ++ fprintf(stderr, "bridge_slave: unknown option \"%s\"?\n", ++ *argv); ++ explain(); ++ return -1; ++ } ++ argc--, argv++; ++ } ++ ++ return 0; ++} ++ ++struct link_util bridge_slave_link_util = { ++ .id = "bridge", ++ .maxattr = IFLA_BRPORT_MAX, ++ .print_opt = bridge_slave_print_opt, ++ .parse_opt = bridge_slave_parse_opt, ++ .slave = true, ++}; +-- +1.8.3.1 + diff --git a/SOURCES/0072-add-bridge-master-device-support.patch b/SOURCES/0072-add-bridge-master-device-support.patch new file mode 100644 index 0000000..cc04000 --- /dev/null +++ b/SOURCES/0072-add-bridge-master-device-support.patch @@ -0,0 +1,137 @@ +From 9c8e31c1555b5d06b90a4a0c64ffd4254a1ae28a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 24 Feb 2016 10:48:44 +0100 +Subject: [PATCH] add bridge master device support + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1270759 +Upstream Status: iproute2.git commit 28d84b429e4e2 +Conflicts: Context changed due to missing HSR device support. + +commit 28d84b429e4e20e63f6e4746285ccfdb72eac92f +Author: Jiri Pirko +Date: Sun Sep 28 16:33:29 2014 -0700 + + add bridge master device support + + Signed-off-by: Jiri Pirko +--- + ip/Makefile | 2 +- + ip/iplink_bridge.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 94 insertions(+), 1 deletion(-) + create mode 100644 ip/iplink_bridge.c + +diff --git a/ip/Makefile b/ip/Makefile +index 8d4f128..35065d6 100644 +--- a/ip/Makefile ++++ b/ip/Makefile +@@ -6,7 +6,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ + iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o link_vti6.o \ + iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \ + link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o \ +- iplink_bridge_slave.o ++ iplink_bridge.o iplink_bridge_slave.o + + RTMONOBJ=rtmon.o + +diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c +new file mode 100644 +index 0000000..0cea7d1 +--- /dev/null ++++ b/ip/iplink_bridge.c +@@ -0,0 +1,93 @@ ++/* ++ * iplink_bridge.c Bridge device support ++ * ++ * 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. ++ * ++ * Authors: Jiri Pirko ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "utils.h" ++#include "ip_common.h" ++ ++static void explain(void) ++{ ++ fprintf(stderr, ++ "Usage: ... bridge [ forward_delay FORWARD_DELAY ]\n" ++ " [ hello_time HELLO_TIME ]\n" ++ " [ max_age MAX_AGE ]\n" ++ ); ++} ++ ++static int bridge_parse_opt(struct link_util *lu, int argc, char **argv, ++ struct nlmsghdr *n) ++{ ++ __u32 val; ++ ++ while (argc > 0) { ++ if (matches(*argv, "forward_delay") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&val, *argv, 0)) { ++ invarg("invalid forward_delay", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BR_FORWARD_DELAY, val); ++ } else if (matches(*argv, "hello_time") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&val, *argv, 0)) { ++ invarg("invalid hello_time", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BR_HELLO_TIME, val); ++ } else if (matches(*argv, "max_age") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&val, *argv, 0)) { ++ invarg("invalid max_age", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BR_MAX_AGE, val); ++ } else if (matches(*argv, "help") == 0) { ++ explain(); ++ return -1; ++ } else { ++ fprintf(stderr, "bridge: unknown command \"%s\"?\n", *argv); ++ explain(); ++ return -1; ++ } ++ argc--, argv++; ++ } ++ ++ return 0; ++} ++ ++static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) ++{ ++ if (!tb) ++ return; ++ ++ if (tb[IFLA_BR_FORWARD_DELAY]) ++ fprintf(f, "forward_delay %u ", ++ rta_getattr_u32(tb[IFLA_BR_FORWARD_DELAY])); ++ ++ if (tb[IFLA_BR_HELLO_TIME]) ++ fprintf(f, "hello_time %u ", ++ rta_getattr_u32(tb[IFLA_BR_HELLO_TIME])); ++ ++ if (tb[IFLA_BR_MAX_AGE]) ++ fprintf(f, "max_age %u ", ++ rta_getattr_u32(tb[IFLA_BR_MAX_AGE])); ++} ++ ++struct link_util bridge_link_util = { ++ .id = "bridge", ++ .maxattr = IFLA_BR_MAX, ++ .parse_opt = bridge_parse_opt, ++ .print_opt = bridge_print_opt, ++}; +-- +1.8.3.1 + diff --git a/SOURCES/0073-iplink_bridge-add-support-for-ageing_time.patch b/SOURCES/0073-iplink_bridge-add-support-for-ageing_time.patch new file mode 100644 index 0000000..732f062 --- /dev/null +++ b/SOURCES/0073-iplink_bridge-add-support-for-ageing_time.patch @@ -0,0 +1,50 @@ +From 7e957986a9ff1832aed84cc8f0b77e540f36c4af Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 24 Feb 2016 10:49:04 +0100 +Subject: [PATCH] iplink_bridge: add support for ageing_time + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1270759 +Upstream Status: iproute2.git commit 6c99fb60765b7 + +commit 6c99fb60765b7a18c760f2357f6ca4da54505d9d +Author: Nikolay Aleksandrov +Date: Tue Jun 16 13:38:47 2015 +0300 + + iplink_bridge: add support for ageing_time + + This patch adds support to set ageing_time via IFLA_BR_AGEING_TIME. + + Signed-off-by: Nikolay Aleksandrov +--- + ip/iplink_bridge.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c +index 0cea7d1..2726a36 100644 +--- a/ip/iplink_bridge.c ++++ b/ip/iplink_bridge.c +@@ -23,6 +23,7 @@ static void explain(void) + "Usage: ... bridge [ forward_delay FORWARD_DELAY ]\n" + " [ hello_time HELLO_TIME ]\n" + " [ max_age MAX_AGE ]\n" ++ " [ ageing_time AGEING_TIME ]\n" + ); + } + +@@ -53,6 +54,13 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv, + return -1; + } + addattr32(n, 1024, IFLA_BR_MAX_AGE, val); ++ } else if (matches(*argv, "ageing_time") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&val, *argv, 0)) { ++ invarg("invalid ageing_time", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BR_AGEING_TIME, val); + } else if (matches(*argv, "help") == 0) { + explain(); + return -1; +-- +1.8.3.1 + diff --git a/SOURCES/0074-iplink_bridge-add-support-for-stp_state.patch b/SOURCES/0074-iplink_bridge-add-support-for-stp_state.patch new file mode 100644 index 0000000..0bc1b9b --- /dev/null +++ b/SOURCES/0074-iplink_bridge-add-support-for-stp_state.patch @@ -0,0 +1,50 @@ +From a86ae0b0475aef00435b503628b3bf4faeb4a599 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 24 Feb 2016 10:49:04 +0100 +Subject: [PATCH] iplink_bridge: add support for stp_state + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1270759 +Upstream Status: iproute2.git commit dab049628a8e5 + +commit dab049628a8e5e962ecc9edf9e37ac858ce3200b +Author: Nikolay Aleksandrov +Date: Tue Jun 16 13:38:48 2015 +0300 + + iplink_bridge: add support for stp_state + + This patch adds support to set stp_state via IFLA_BR_STP_STATE. + + Signed-off-by: Nikolay Aleksandrov +--- + ip/iplink_bridge.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c +index 2726a36..79b9e04 100644 +--- a/ip/iplink_bridge.c ++++ b/ip/iplink_bridge.c +@@ -24,6 +24,7 @@ static void explain(void) + " [ hello_time HELLO_TIME ]\n" + " [ max_age MAX_AGE ]\n" + " [ ageing_time AGEING_TIME ]\n" ++ " [ stp_state STP_STATE ]\n" + ); + } + +@@ -61,6 +62,13 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv, + return -1; + } + addattr32(n, 1024, IFLA_BR_AGEING_TIME, val); ++ } else if (matches(*argv, "stp_state") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&val, *argv, 0)) { ++ invarg("invalid stp_state", *argv); ++ return -1; ++ } ++ addattr32(n, 1024, IFLA_BR_STP_STATE, val); + } else if (matches(*argv, "help") == 0) { + explain(); + return -1; +-- +1.8.3.1 + diff --git a/SOURCES/0075-iplink_bridge-add-support-for-priority.patch b/SOURCES/0075-iplink_bridge-add-support-for-priority.patch new file mode 100644 index 0000000..c388dfe --- /dev/null +++ b/SOURCES/0075-iplink_bridge-add-support-for-priority.patch @@ -0,0 +1,52 @@ +From 8b3aa8fa4f5e02ba2f49b4030299e6f75fdf1072 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 24 Feb 2016 10:49:04 +0100 +Subject: [PATCH] iplink_bridge: add support for priority + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1270759 +Upstream Status: iproute2.git commit b0197a047e5c4 + +commit b0197a047e5c41a37d5dd724290eadd5b9353558 +Author: Nikolay Aleksandrov +Date: Tue Jun 16 13:38:49 2015 +0300 + + iplink_bridge: add support for priority + + This patch adds support to set bridge stp priority via IFLA_BR_PRIORITY. + + Signed-off-by: Nikolay Aleksandrov +--- + ip/iplink_bridge.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c +index 79b9e04..297160c 100644 +--- a/ip/iplink_bridge.c ++++ b/ip/iplink_bridge.c +@@ -25,6 +25,7 @@ static void explain(void) + " [ max_age MAX_AGE ]\n" + " [ ageing_time AGEING_TIME ]\n" + " [ stp_state STP_STATE ]\n" ++ " [ priority PRIORITY ]\n" + ); + } + +@@ -69,6 +70,15 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv, + return -1; + } + addattr32(n, 1024, IFLA_BR_STP_STATE, val); ++ } else if (matches(*argv, "priority") == 0) { ++ __u16 prio; ++ ++ NEXT_ARG(); ++ if (get_u16(&prio, *argv, 0)) { ++ invarg("invalid priority", *argv); ++ return -1; ++ } ++ addattr16(n, 1024, IFLA_BR_PRIORITY, prio); + } else if (matches(*argv, "help") == 0) { + explain(); + return -1; +-- +1.8.3.1 + diff --git a/SOURCES/0076-iplink-use-the-short-format-to-print-help-info.patch b/SOURCES/0076-iplink-use-the-short-format-to-print-help-info.patch new file mode 100644 index 0000000..13c5a1a --- /dev/null +++ b/SOURCES/0076-iplink-use-the-short-format-to-print-help-info.patch @@ -0,0 +1,69 @@ +From a36e0ae05b37cb2055bd2a4304d43b486888d5a7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 24 Feb 2016 10:49:04 +0100 +Subject: [PATCH] iplink: use the short format to print help info + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1270759 +Upstream Status: iproute2.git commit 43367ef7eb047 + +commit 43367ef7eb0473ea4ecdc3925f076107f05873a0 +Author: Zhang Shengju +Date: Wed Aug 12 06:03:23 2015 +0000 + + iplink: use the short format to print help info + + Allow to print link type usage by: ip link help bridge + + Signed-off-by: Zhang Shengju +--- + ip/iplink_bridge.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c +index 297160c..1e69960 100644 +--- a/ip/iplink_bridge.c ++++ b/ip/iplink_bridge.c +@@ -17,9 +17,9 @@ + #include "utils.h" + #include "ip_common.h" + +-static void explain(void) ++static void print_explain(FILE *f) + { +- fprintf(stderr, ++ fprintf(f, + "Usage: ... bridge [ forward_delay FORWARD_DELAY ]\n" + " [ hello_time HELLO_TIME ]\n" + " [ max_age MAX_AGE ]\n" +@@ -29,6 +29,11 @@ static void explain(void) + ); + } + ++static void explain(void) ++{ ++ print_explain(stderr); ++} ++ + static int bridge_parse_opt(struct link_util *lu, int argc, char **argv, + struct nlmsghdr *n) + { +@@ -111,9 +116,16 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + rta_getattr_u32(tb[IFLA_BR_MAX_AGE])); + } + ++static void bridge_print_help(struct link_util *lu, int argc, char **argv, ++ FILE *f) ++{ ++ print_explain(f); ++} ++ + struct link_util bridge_link_util = { + .id = "bridge", + .maxattr = IFLA_BR_MAX, + .parse_opt = bridge_parse_opt, + .print_opt = bridge_print_opt, ++ .print_help = bridge_print_help, + }; +-- +1.8.3.1 + diff --git a/SOURCES/0077-iplink-shortify-printing-the-usage-of-link-type.patch b/SOURCES/0077-iplink-shortify-printing-the-usage-of-link-type.patch new file mode 100644 index 0000000..d7ff8af --- /dev/null +++ b/SOURCES/0077-iplink-shortify-printing-the-usage-of-link-type.patch @@ -0,0 +1,70 @@ +From f1041556927a428d05b7349a1abe5eaf6af50575 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 24 Feb 2016 10:49:05 +0100 +Subject: [PATCH] iplink: shortify printing the usage of link type + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1270759 +Upstream Status: iproute2.git commit a560d850d9cd2 + +commit a560d850d9cd24b06281897c97eb6afef3f00d8b +Author: Zhang Shengju +Date: Wed Aug 12 06:03:24 2015 +0000 + + iplink: shortify printing the usage of link type + + Allow to print link type usage by: ip link help bridge_slave + + Signed-off-by: Zhang Shengju +--- + ip/iplink_bridge_slave.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/ip/iplink_bridge_slave.c b/ip/iplink_bridge_slave.c +index a285185..4593872 100644 +--- a/ip/iplink_bridge_slave.c ++++ b/ip/iplink_bridge_slave.c +@@ -19,9 +19,9 @@ + #include "utils.h" + #include "ip_common.h" + +-static void explain(void) ++static void print_explain(FILE *f) + { +- fprintf(stderr, ++ fprintf(f, + "Usage: ... bridge_slave [ state STATE ] [ priority PRIO ] [cost COST ]\n" + " [ guard {on | off} ]\n" + " [ hairpin {on | off} ] \n" +@@ -32,6 +32,11 @@ static void explain(void) + ); + } + ++static void explain(void) ++{ ++ print_explain(stderr); ++} ++ + static const char *port_states[] = { + [BR_STATE_DISABLED] = "disabled", + [BR_STATE_LISTENING] = "listening", +@@ -172,10 +177,17 @@ static int bridge_slave_parse_opt(struct link_util *lu, int argc, char **argv, + return 0; + } + ++static void bridge_slave_print_help(struct link_util *lu, int argc, char **argv, ++ FILE *f) ++{ ++ print_explain(f); ++} ++ + struct link_util bridge_slave_link_util = { + .id = "bridge", + .maxattr = IFLA_BRPORT_MAX, + .print_opt = bridge_slave_print_opt, + .parse_opt = bridge_slave_parse_opt, ++ .print_help = bridge_slave_print_help, + .slave = true, + }; +-- +1.8.3.1 + diff --git a/SOURCES/0078-iplink-add-ageing_time-stp_state-and-priority-for-br.patch b/SOURCES/0078-iplink-add-ageing_time-stp_state-and-priority-for-br.patch new file mode 100644 index 0000000..69174d7 --- /dev/null +++ b/SOURCES/0078-iplink-add-ageing_time-stp_state-and-priority-for-br.patch @@ -0,0 +1,48 @@ +From eed74d8f509bda634bb310dcf054da09319a308b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 24 Feb 2016 10:49:05 +0100 +Subject: [PATCH] iplink: add ageing_time, stp_state and priority for bridge + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1270759 +Upstream Status: iproute2.git commit fdba05155c700 + +commit fdba05155c7008d18b5760624c99978ba0d369d4 +Author: Nikolay Aleksandrov +Date: Wed Aug 12 09:11:30 2015 -0700 + + iplink: add ageing_time, stp_state and priority for bridge + + When showing bridge attributes, show also ageing_time, stp_state and + priority if available. + + Signed-off-by: Nikolay Aleksandrov +--- + ip/iplink_bridge.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c +index 1e69960..e704e29 100644 +--- a/ip/iplink_bridge.c ++++ b/ip/iplink_bridge.c +@@ -114,6 +114,18 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + if (tb[IFLA_BR_MAX_AGE]) + fprintf(f, "max_age %u ", + rta_getattr_u32(tb[IFLA_BR_MAX_AGE])); ++ ++ if (tb[IFLA_BR_AGEING_TIME]) ++ fprintf(f, "ageing_time %u ", ++ rta_getattr_u32(tb[IFLA_BR_AGEING_TIME])); ++ ++ if (tb[IFLA_BR_STP_STATE]) ++ fprintf(f, "stp_state %u ", ++ rta_getattr_u32(tb[IFLA_BR_STP_STATE])); ++ ++ if (tb[IFLA_BR_PRIORITY]) ++ fprintf(f, "priority %u ", ++ rta_getattr_u16(tb[IFLA_BR_PRIORITY])); + } + + static void bridge_print_help(struct link_util *lu, int argc, char **argv, +-- +1.8.3.1 + diff --git a/SOURCES/0079-ip-link-consolidate-macvlan-and-macvtap.patch b/SOURCES/0079-ip-link-consolidate-macvlan-and-macvtap.patch new file mode 100644 index 0000000..59d625e --- /dev/null +++ b/SOURCES/0079-ip-link-consolidate-macvlan-and-macvtap.patch @@ -0,0 +1,246 @@ +From ecbf839299f6156ebcc159a39b5fcb01b1273e42 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 4 Mar 2016 17:46:07 +0100 +Subject: [PATCH] ip: link: consolidate macvlan and macvtap + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1013584 +Upstream Status: iproute2.git commit 541f1b3e1d101 + +commit 541f1b3e1d1011718cbef85adb284a72b183c676 +Author: Phil Sutter +Date: Fri Sep 25 14:09:49 2015 +0200 + + ip: link: consolidate macvlan and macvtap + + After eliminating the minor differences in both files which existed + solely because features/fixes were applied to only one of them and not + the other, the remaining differences were in function naming and error + messages. The latter is addressed by using the 'id' field of struct + link_util. + + Fold both files into one in order to share common code and eliminate the + chance of having fixes/enhancements applied to only one of them. + + Signed-off-by: Phil Sutter +--- + ip/Makefile | 2 +- + ip/iplink_macvlan.c | 40 +++++++++++++------- + ip/iplink_macvtap.c | 105 ---------------------------------------------------- + 3 files changed, 28 insertions(+), 119 deletions(-) + delete mode 100644 ip/iplink_macvtap.c + +diff --git a/ip/Makefile b/ip/Makefile +index 35065d6..e4f0507 100644 +--- a/ip/Makefile ++++ b/ip/Makefile +@@ -3,7 +3,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ + ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o iptoken.o \ + ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \ + iplink_vlan.o link_veth.o link_gre.o iplink_can.o \ +- iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o link_vti6.o \ ++ iplink_macvlan.o ipl2tp.o link_vti.o link_vti6.o \ + iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \ + link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o \ + iplink_bridge.o iplink_bridge_slave.o +diff --git a/ip/iplink_macvlan.c b/ip/iplink_macvlan.c +index e080157..b972d0e 100644 +--- a/ip/iplink_macvlan.c ++++ b/ip/iplink_macvlan.c +@@ -1,5 +1,5 @@ + /* +- * iplink_vlan.c VLAN device support ++ * iplink_macvlan.c macvlan/macvtap device support + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License +@@ -20,22 +20,29 @@ + #include "utils.h" + #include "ip_common.h" + +-static void print_explain(FILE *f) ++#define pfx_err(lu, ...) { \ ++ fprintf(stderr, "%s: ", lu->id); \ ++ fprintf(stderr, __VA_ARGS__); \ ++ fprintf(stderr, "\n"); \ ++} ++ ++static void print_explain(struct link_util *lu, FILE *f) + { + fprintf(f, +- "Usage: ... macvlan mode { private | vepa | bridge | passthru }\n" ++ "Usage: ... %s mode { private | vepa | bridge | passthru }\n", ++ lu->id + ); + } + +-static void explain(void) ++static void explain(struct link_util *lu) + { +- print_explain(stderr); ++ print_explain(lu, stderr); + } + +-static int mode_arg(void) ++static int mode_arg(const char *arg) + { + fprintf(stderr, "Error: argument of \"mode\" must be \"private\", " +- "\"vepa\", \"bridge\" or \"passthru\" \n"); ++ "\"vepa\", \"bridge\" or \"passthru\", not \"%s\"\n", arg); + return -1; + } + +@@ -56,15 +63,14 @@ static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv, + else if (strcmp(*argv, "passthru") == 0) + mode = MACVLAN_MODE_PASSTHRU; + else +- return mode_arg(); +- ++ return mode_arg(*argv); + addattr32(n, 1024, IFLA_MACVLAN_MODE, mode); + } else if (matches(*argv, "help") == 0) { +- explain(); ++ explain(lu); + return -1; + } else { +- fprintf(stderr, "macvlan: unknown option \"%s\"?\n", *argv); +- explain(); ++ pfx_err(lu, "unknown option \"%s\"?", *argv); ++ explain(lu); + return -1; + } + argc--, argv++; +@@ -96,7 +102,7 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[] + static void macvlan_print_help(struct link_util *lu, int argc, char **argv, + FILE *f) + { +- print_explain(f); ++ print_explain(lu, f); + } + + struct link_util macvlan_link_util = { +@@ -106,3 +112,11 @@ struct link_util macvlan_link_util = { + .print_opt = macvlan_print_opt, + .print_help = macvlan_print_help, + }; ++ ++struct link_util macvtap_link_util = { ++ .id = "macvtap", ++ .maxattr = IFLA_MACVLAN_MAX, ++ .parse_opt = macvlan_parse_opt, ++ .print_opt = macvlan_print_opt, ++ .print_help = macvlan_print_help, ++}; +diff --git a/ip/iplink_macvtap.c b/ip/iplink_macvtap.c +deleted file mode 100644 +index 9c2cd74..0000000 +--- a/ip/iplink_macvtap.c ++++ /dev/null +@@ -1,105 +0,0 @@ +-/* +- * iplink_macvtap.c macvtap device support +- * +- * 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. +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include "rt_names.h" +-#include "utils.h" +-#include "ip_common.h" +- +-static void print_explain(FILE *f) +-{ +- fprintf(stderr, +- "Usage: ... macvtap mode { private | vepa | bridge | passthru }\n" +- ); +-} +- +-static void explain(void) +-{ +- print_explain(stderr); +-} +- +-static int mode_arg(const char *arg) +-{ +- fprintf(stderr, "Error: argument of \"mode\" must be \"private\", " +- "\"vepa\", \"bridge\" or \"passthru\", not \"%s\"\n", arg); +- return -1; +-} +- +-static int macvtap_parse_opt(struct link_util *lu, int argc, char **argv, +- struct nlmsghdr *n) +-{ +- while (argc > 0) { +- if (matches(*argv, "mode") == 0) { +- __u32 mode = 0; +- NEXT_ARG(); +- +- if (strcmp(*argv, "private") == 0) +- mode = MACVLAN_MODE_PRIVATE; +- else if (strcmp(*argv, "vepa") == 0) +- mode = MACVLAN_MODE_VEPA; +- else if (strcmp(*argv, "bridge") == 0) +- mode = MACVLAN_MODE_BRIDGE; +- else if (strcmp(*argv, "passthru") == 0) +- mode = MACVLAN_MODE_PASSTHRU; +- else +- return mode_arg(*argv); +- +- addattr32(n, 1024, IFLA_MACVLAN_MODE, mode); +- } else if (matches(*argv, "help") == 0) { +- explain(); +- return -1; +- } else { +- fprintf(stderr, "macvtap: unknown command \"%s\"?\n", *argv); +- explain(); +- return -1; +- } +- argc--, argv++; +- } +- +- return 0; +-} +- +-static void macvtap_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) +-{ +- __u32 mode; +- +- if (!tb) +- return; +- +- if (!tb[IFLA_MACVLAN_MODE] || +- RTA_PAYLOAD(tb[IFLA_MACVLAN_MODE]) < sizeof(__u32)) +- return; +- +- mode = rta_getattr_u32(tb[IFLA_VLAN_ID]); +- fprintf(f, " mode %s ", +- mode == MACVLAN_MODE_PRIVATE ? "private" +- : mode == MACVLAN_MODE_VEPA ? "vepa" +- : mode == MACVLAN_MODE_BRIDGE ? "bridge" +- : mode == MACVLAN_MODE_PASSTHRU ? "passthru" +- : "unknown"); +-} +- +-static void macvtap_print_help(struct link_util *lu, int argc, char **argv, +- FILE *f) +-{ +- print_explain(f); +-} +- +-struct link_util macvtap_link_util = { +- .id = "macvtap", +- .maxattr = IFLA_MACVLAN_MAX, +- .parse_opt = macvtap_parse_opt, +- .print_opt = macvtap_print_opt, +- .print_help = macvtap_print_help, +-}; +-- +1.8.3.1 + diff --git a/SOURCES/0080-ip-macvlan-support-MACVLAN_FLAG_NOPROMISC-flag.patch b/SOURCES/0080-ip-macvlan-support-MACVLAN_FLAG_NOPROMISC-flag.patch new file mode 100644 index 0000000..7b3b36e --- /dev/null +++ b/SOURCES/0080-ip-macvlan-support-MACVLAN_FLAG_NOPROMISC-flag.patch @@ -0,0 +1,102 @@ +From 65d44f53fc70fa57b76a4eb5dadb1eeda5996924 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 4 Mar 2016 17:46:07 +0100 +Subject: [PATCH] ip: macvlan: support MACVLAN_FLAG_NOPROMISC flag + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1013584 +Upstream Status: iproute2.git commit 3cf8ba596026b + +commit 3cf8ba596026b61f58e674fa28f3a310597e8d36 +Author: Phil Sutter +Date: Fri Sep 25 14:09:50 2015 +0200 + + ip: macvlan: support MACVLAN_FLAG_NOPROMISC flag + + This flag is allowed for devices in passthru mode to prevent forcing the + underlying interface into promiscuous mode. + + Signed-off-by: Phil Sutter +--- + ip/iplink_macvlan.c | 30 +++++++++++++++++++++++++++--- + 1 file changed, 27 insertions(+), 3 deletions(-) + +diff --git a/ip/iplink_macvlan.c b/ip/iplink_macvlan.c +index b972d0e..f2677e1 100644 +--- a/ip/iplink_macvlan.c ++++ b/ip/iplink_macvlan.c +@@ -29,7 +29,7 @@ + static void print_explain(struct link_util *lu, FILE *f) + { + fprintf(f, +- "Usage: ... %s mode { private | vepa | bridge | passthru }\n", ++ "Usage: ... %s mode { private | vepa | bridge | passthru [nopromisc] }\n", + lu->id + ); + } +@@ -49,9 +49,11 @@ static int mode_arg(const char *arg) + static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv, + struct nlmsghdr *n) + { ++ __u32 mode = 0; ++ __u16 flags = 0; ++ + while (argc > 0) { + if (matches(*argv, "mode") == 0) { +- __u32 mode = 0; + NEXT_ARG(); + + if (strcmp(*argv, "private") == 0) +@@ -64,7 +66,8 @@ static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv, + mode = MACVLAN_MODE_PASSTHRU; + else + return mode_arg(*argv); +- addattr32(n, 1024, IFLA_MACVLAN_MODE, mode); ++ } else if (matches(*argv, "nopromisc") == 0) { ++ flags |= MACVLAN_FLAG_NOPROMISC; + } else if (matches(*argv, "help") == 0) { + explain(lu); + return -1; +@@ -76,12 +79,25 @@ static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv, + argc--, argv++; + } + ++ if (mode) ++ addattr32(n, 1024, IFLA_MACVLAN_MODE, mode); ++ ++ if (flags) { ++ if (flags & MACVLAN_FLAG_NOPROMISC && ++ mode != MACVLAN_MODE_PASSTHRU) { ++ pfx_err(lu, "nopromisc flag only valid in passthru mode"); ++ explain(lu); ++ return -1; ++ } ++ addattr16(n, 1024, IFLA_MACVLAN_FLAGS, flags); ++ } + return 0; + } + + static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + { + __u32 mode; ++ __u16 flags; + + if (!tb) + return; +@@ -97,6 +113,14 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[] + : mode == MACVLAN_MODE_BRIDGE ? "bridge" + : mode == MACVLAN_MODE_PASSTHRU ? "passthru" + : "unknown"); ++ ++ if (!tb[IFLA_MACVLAN_FLAGS] || ++ RTA_PAYLOAD(tb[IFLA_MACVLAN_FLAGS]) < sizeof(__u16)) ++ return; ++ ++ flags = rta_getattr_u16(tb[IFLA_MACVLAN_FLAGS]); ++ if (flags & MACVLAN_FLAG_NOPROMISC) ++ fprintf(f, "nopromisc "); + } + + static void macvlan_print_help(struct link_util *lu, int argc, char **argv, +-- +1.8.3.1 + diff --git a/SOURCES/0081-iproute2-ip6gre-update-man-pages.patch b/SOURCES/0081-iproute2-ip6gre-update-man-pages.patch new file mode 100644 index 0000000..75a65d7 --- /dev/null +++ b/SOURCES/0081-iproute2-ip6gre-update-man-pages.patch @@ -0,0 +1,196 @@ +From 7ec0dbe4a48ad0231fbc3b0962e822a530adb985 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 15:57:00 +0100 +Subject: [PATCH] iproute2: ip6gre: update man pages + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1013584 +Upstream Status: iproute2.git commit 9abde37cde92e + +commit 9abde37cde92e9b84f2f72aad9a03635972ffdf3 +Author: xeb@mail.ru +Date: Tue Oct 1 11:18:34 2013 +0400 + + iproute2: ip6gre: update man pages + + Update man pages with ip6gre info. + + Signed-off-by: Dmitry Kozlov +--- + man/man8/ip-link.8.in | 124 +++++++++++++++++++++++++++++++++++++++++++++++++- + man/man8/ip-tunnel.8 | 4 +- + 2 files changed, 125 insertions(+), 3 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 82ae316..81ef4bb 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -64,7 +64,11 @@ ip-link \- network device configuration + .BR vxlan " |" + .BR ip6tnl " |" + .BR ipip " |" +-.BR sit " ]" ++.BR sit " |" ++.BR gre " |" ++.BR gretap " |" ++.BR ip6gre " |" ++.BR ip6gretap " ]" + + .ti -8 + .BI "ip link delete " DEVICE +@@ -196,6 +200,18 @@ Link types: + .sp + .BR sit + - Virtual tunnel interface IPv6 over IPv4 ++.sp ++.BR gre ++- Virtual tunnel interface GRE over IPv4 ++.sp ++.BR gretap ++- Virtual L2 tuunel interface GRE over IPv4 ++.sp ++.BR ip6gre ++- Virtual tuunel interface GRE over IPv6 ++.sp ++.BR ip6gretap ++- Virtual L2 tuunel interface GRE over IPv6 + .in -8 + + .TP +@@ -443,6 +459,112 @@ Example: + + .in -8 + ++.TP ++IP6GRE/IP6GRETAP Type Support ++For a link of type ++.I IP6GRE/IP6GRETAP ++the following additional arguments are supported: ++ ++.BI "ip link add " DEVICE ++.BI type " { ip6gre | ip6gretap } " remote " ADDR " local " ADDR ++.R " [ " ++.I "[i|o]seq]" ++.R " ] [ " ++.I "[i|o]key" KEY ++.R " ] [ " ++.I " [i|o]csum " ++.R " ] [ " ++.BI hoplimit " TTL " ++.R " ] [ " ++.BI encaplimit " ELIM " ++.R " ] [ " ++.BI tclass " TCLASS " ++.R " ] [ " ++.BI flowlabel " FLOWLABEL " ++.R " ] [ " ++.BI "dscp inherit" ++.R " ] [ " ++.BI dev " PHYS_DEV " ++.R " ]" ++ ++.in +8 ++.sp ++.BI remote " ADDR " ++- specifies the remote IPv6 address of the tunnel. ++ ++.sp ++.BI local " ADDR " ++- specifies the fixed local IPv6 address for tunneled packets. ++It must be and address on another interface on this host. ++ ++.sp ++.BI [i|o]seq ++- serialize packets. ++The ++.B oseq ++flag enables sequencing of outgoing packets. ++The ++.B iseq ++flag requires that all input packets are serialized. ++ ++.sp ++.BI [i|o]key " KEY" ++- use keyed GRE with key ++.IR KEY ". "KEY ++is either a number or an IPv4 address-like dotted quad. ++The ++.B key ++parameter specifies the same key to use in both directions. ++The ++.BR ikey " and " okey ++parameters specify different keys for input and output. ++ ++.sp ++.BI [i|o]csum ++- generate/require checksums for tunneled packets. ++The ++.B ocsum ++flag calculates checksums for outgoing packets. ++The ++.B icsum ++flag requires that all input packets have the correct ++checksum. The ++.B csum ++flag is equivalent to the combination ++.BR "icsum ocsum" . ++ ++.sp ++.BI hoplimit " TTL" ++- specifies Hop Limit value to use in outgoing packets. ++ ++.sp ++.BI encaplimit " ELIM" ++- specifies a fixed encapsulation limit. Default is 4. ++ ++.sp ++.BI flowlabel " FLOWLABEL" ++- specifies a fixed flowlabel. ++ ++.sp ++.BI tclass " TCLASS" ++- specifies the traffic class field on ++tunneled packets, which can be specified as either a two-digit ++hex value (e.g. c0) or a predefined string (e.g. internet). ++The value ++.B inherit ++causes the field to be copied from the original IP header. The ++values ++.BI "inherit/" STRING ++or ++.BI "inherit/" 00 ".." ff ++will set the field to ++.I STRING ++or ++.IR 00 ".." ff ++when tunneling non-IP packets. The default value is 00. ++ ++.in -8 ++ + .SS ip link delete - delete virtual link + .I DEVICE + specifies the virtual device to act operate on. +diff --git a/man/man8/ip-tunnel.8 b/man/man8/ip-tunnel.8 +index f697b4f..c97c28c 100644 +--- a/man/man8/ip-tunnel.8 ++++ b/man/man8/ip-tunnel.8 +@@ -50,7 +50,7 @@ ip-tunnel - tunnel configuration + + .ti -8 + .IR MODE " := " +-.RB " { " ipip " | " gre " | " sit " | " isatap " | " ip6ip6 " | " ipip6 " | " any " }" ++.RB " { " ipip " | " gre " | " sit " | " isatap " | " ip6ip6 " | " ipip6 " | " ip6gre " | " any " }" + + .ti -8 + .IR ADDR " := { " IP_ADDRESS " |" +@@ -110,7 +110,7 @@ Modes for IPv4 encapsulation available: + .BR ipip ", " sit ", " isatap " and " gre "." + .br + Modes for IPv6 encapsulation available: +-.BR ip6ip6 ", " ipip6 " and " any "." ++.BR ip6ip6 ", " ipip6 ", " ip6gre ", and " any "." + + .TP + .BI remote " ADDRESS" +-- +1.8.3.1 + diff --git a/SOURCES/0082-iproute-Descriptions-of-fou-and-gue-options-in-ip-li.patch b/SOURCES/0082-iproute-Descriptions-of-fou-and-gue-options-in-ip-li.patch new file mode 100644 index 0000000..d12a4a2 --- /dev/null +++ b/SOURCES/0082-iproute-Descriptions-of-fou-and-gue-options-in-ip-li.patch @@ -0,0 +1,120 @@ +From 6d19d559d29c1060c0d472f4d6a5daf2c5e608a9 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 15:57:00 +0100 +Subject: [PATCH] iproute: Descriptions of fou and gue options in ip-link man + pages + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1013584 +Upstream Status: iproute2.git commit 90f1df715eb38 + +commit 90f1df715eb38bbbb4554ebbad783d67690a38b2 +Author: Tom Herbert +Date: Thu Jan 29 08:52:01 2015 -0800 + + iproute: Descriptions of fou and gue options in ip-link man pages + + Add section for additional arguments to GRE, IPIP, and SIT types + that are related to Foo-over-UDP and Generic UDP Encapsulation. + Also, added an example GUE configuration in the examples section. + + Signed-off-by: Tom Herbert +--- + man/man8/ip-link.8.in | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 67 insertions(+), 1 deletion(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 81ef4bb..9e667a2 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -460,6 +460,63 @@ Example: + .in -8 + + .TP ++GRE, IPIP, SIT Type Support ++For a link of types ++.I GRE/IPIP/SIT ++the following additional arguments are supported: ++ ++.BI "ip link add " DEVICE ++.BR type " { gre | ipip | sit } " ++.BI " remote " ADDR " local " ADDR ++.R " [ " ++.BR encap " { fou | gue | none } " ++.R " ] [ " ++.BI "encap-sport { " PORT " | auto } " ++.R " ] [ " ++.BI "encap-dport " PORT ++.R " ] [ " ++.I " [no]encap-csum " ++.R " ] [ " ++.I " [no]encap-remcsum " ++.R " ]" ++ ++.in +8 ++.sp ++.BI remote " ADDR " ++- specifies the remote address of the tunnel. ++ ++.sp ++.BI local " ADDR " ++- specifies the fixed local address for tunneled packets. ++It must be an address on another interface on this host. ++ ++.sp ++.BR encap " { fou | gue | none } " ++- specifies type of secondary UDP encapsulation. "fou" indicates ++Foo-Over-UDP, "gue" indicates Generic UDP Encapsulation. ++ ++.sp ++.BI "encap-sport { " PORT " | auto } " ++- specifies the source port in UDP encapsulation. ++.IR PORT ++indicates the port by number, "auto" ++indicates that the port number should be chosen automatically ++(the kernel picks a flow based on the flow hash of the ++encapsulated packet). ++ ++.sp ++.I [no]encap-csum ++- specifies if UDP checksums are enabled in the secondary ++encapsulation. ++ ++.sp ++.I [no]encap-remcsum ++- specifies if Remote Checksum Offload is enabled. This is only ++applicable for Generic UDP Encapsulation. ++ ++.in -8 ++ ++.TP + IP6GRE/IP6GRETAP Type Support + For a link of type + .I IP6GRE/IP6GRETAP +@@ -495,7 +552,7 @@ the following additional arguments are supported: + .sp + .BI local " ADDR " + - specifies the fixed local IPv6 address for tunneled packets. +-It must be and address on another interface on this host. ++It must be an address on another interface on this host. + + .sp + .BI [i|o]seq +@@ -831,6 +888,15 @@ ip link help gre + .RS 4 + Display help for the gre link type. + .RE ++.PP ++ip link add name tun1 type ipip remote 192.168.1.1 ++local 192.168.1.2 ttl 225 encap gue encap-sport auto ++encap-dport 5555 encap-csum encap-remcsum ++.RS 4 ++Creates an IPIP that is encapsulated with Generic UDP Encapsulation, ++and the outer UDP checksum and remote checksum offload are enabled. ++ ++.RE + + .SH SEE ALSO + .br +-- +1.8.3.1 + diff --git a/SOURCES/0083-ip-link-Document-IPoIB-link-type-in-the-man-page.patch b/SOURCES/0083-ip-link-Document-IPoIB-link-type-in-the-man-page.patch new file mode 100644 index 0000000..60b36c1 --- /dev/null +++ b/SOURCES/0083-ip-link-Document-IPoIB-link-type-in-the-man-page.patch @@ -0,0 +1,53 @@ +From 00618aeedb8287dc27609ff80ba077710ddeca25 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 15:57:00 +0100 +Subject: [PATCH] ip-link: Document IPoIB link type in the man page + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1013584 +Upstream Status: iproute2.git commit 8ca8fac7aaf61 + +commit 8ca8fac7aaf61a05ee074fe1f1daee4acabf8588 +Author: Or Gerlitz +Date: Sun Nov 16 09:43:34 2014 +0200 + + ip-link: Document IPoIB link type in the man page + + Add documentation on how to create devices of type IP-over-Infiniband + in the man page. + + Signed-off-by: Or Gerlitz +--- + man/man8/ip-link.8.in | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 9e667a2..dffa25b 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -622,6 +622,23 @@ when tunneling non-IP packets. The default value is 00. + + .in -8 + ++.TP ++IPoIB Type Support ++For a link of type ++.I IPoIB ++the following additional arguments are supported: ++ ++.BI "ip link add " DEVICE " name " NAME ++.BI type " ipoib [ " pkey " PKEY ] [" mode " MODE " ] ++ ++.in +8 ++.sp ++.BI pkey " PKEY " ++- specifies the IB P-Key to use. ++ ++.BI mode " MODE " ++- specifies the mode (datagram or connected) to use. ++ + .SS ip link delete - delete virtual link + .I DEVICE + specifies the virtual device to act operate on. +-- +1.8.3.1 + diff --git a/SOURCES/0084-iproute2-ip-link.8.in-Spelling-fixes.patch b/SOURCES/0084-iproute2-ip-link.8.in-Spelling-fixes.patch new file mode 100644 index 0000000..5b75942 --- /dev/null +++ b/SOURCES/0084-iproute2-ip-link.8.in-Spelling-fixes.patch @@ -0,0 +1,46 @@ +From 977e3cbb92fe7f4d8fcd1332c347bfe1391a4d0e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 15:57:00 +0100 +Subject: [PATCH] iproute2: ip-link.8.in: Spelling fixes + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1013584 +Upstream Status: iproute2.git commit d36d9d41d6e66 + +commit d36d9d41d6e66c130b0632b82ea74c3ae4d0fbe3 +Author: Reese Moore +Date: Wed Feb 4 14:04:48 2015 -0500 + + iproute2: ip-link.8.in: Spelling fixes + + In the ip-link(8) man page, for the gretap, ip6gre, and ip6gretap types, the + word tunnel was incorrectly spelled 'tuunel'. + + Signed-off-by: Reese Moore +--- + man/man8/ip-link.8.in | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index dffa25b..d8fca23 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -205,13 +205,13 @@ Link types: + - Virtual tunnel interface GRE over IPv4 + .sp + .BR gretap +-- Virtual L2 tuunel interface GRE over IPv4 ++- Virtual L2 tunnel interface GRE over IPv4 + .sp + .BR ip6gre +-- Virtual tuunel interface GRE over IPv6 ++- Virtual tunnel interface GRE over IPv6 + .sp + .BR ip6gretap +-- Virtual L2 tuunel interface GRE over IPv6 ++- Virtual L2 tunnel interface GRE over IPv6 + .in -8 + + .TP +-- +1.8.3.1 + diff --git a/SOURCES/0085-man-ip-link-Add-missing-link-types-vti-ipvlan-nlmon.patch b/SOURCES/0085-man-ip-link-Add-missing-link-types-vti-ipvlan-nlmon.patch new file mode 100644 index 0000000..ecae525 --- /dev/null +++ b/SOURCES/0085-man-ip-link-Add-missing-link-types-vti-ipvlan-nlmon.patch @@ -0,0 +1,54 @@ +From 2f5dccc695c146101b4fc796e0f31fc71e97aaff Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 15:57:01 +0100 +Subject: [PATCH] man ip-link: Add missing link types - vti,ipvlan,nlmon + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1013584 +Upstream Status: iproute2.git commit b6d6b5a1cdd91 + +commit b6d6b5a1cdd91c878ab2541f38402a44ffb75ee7 +Author: Vadim Kochan +Date: Sat Apr 4 19:00:55 2015 +0300 + + man ip-link: Add missing link types - vti,ipvlan,nlmon + + Signed-off-by: Vadim Kochan +--- + man/man8/ip-link.8.in | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index d8fca23..339b5c5 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -68,7 +68,10 @@ ip-link \- network device configuration + .BR gre " |" + .BR gretap " |" + .BR ip6gre " |" +-.BR ip6gretap " ]" ++.BR ip6gretap " |" ++.BR vti " |" ++.BR nlmon " |" ++.BR ipvlan " ]" + + .ti -8 + .BI "ip link delete " DEVICE +@@ -212,6 +215,15 @@ Link types: + .sp + .BR ip6gretap + - Virtual L2 tunnel interface GRE over IPv6 ++.sp ++.BR vti ++- Virtual tunnel interface ++.sp ++.BR nlmon ++- Netlink monitoring device ++.sp ++.BR ipvlan ++- Interface for L3 (IPv6/IPv4) based VLANs + .in -8 + + .TP +-- +1.8.3.1 + diff --git a/SOURCES/0086-man-ip-link-fix-a-typo.patch b/SOURCES/0086-man-ip-link-fix-a-typo.patch new file mode 100644 index 0000000..31fcb43 --- /dev/null +++ b/SOURCES/0086-man-ip-link-fix-a-typo.patch @@ -0,0 +1,35 @@ +From 4b2882df80788b9740cce915d2ac5ca8b263cfa0 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 15:57:01 +0100 +Subject: [PATCH] man: ip-link: fix a typo + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1013584 +Upstream Status: iproute2.git commit e37a9c73d2e0b + +commit e37a9c73d2e0bbf1288eb16e9b47028012db2bf8 +Author: Masatake YAMATO +Date: Fri Nov 7 03:57:05 2014 +0900 + + man: ip-link: fix a typo + + Signed-off-by: Masatake YAMATO +--- + man/man8/ip-link.8.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 339b5c5..88e014b 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -52,7 +52,7 @@ ip-link \- network device configuration + .ti -8 + .IR TYPE " := [ " + .BR bridge " | " +-.BR bond " ]" ++.BR bond " | " + .BR can " | " + .BR dummy " | " + .BR ifb " | " +-- +1.8.3.1 + diff --git a/SOURCES/0087-man-ip-link-document-MACVLAN-MACVTAP-interface-types.patch b/SOURCES/0087-man-ip-link-document-MACVLAN-MACVTAP-interface-types.patch new file mode 100644 index 0000000..1f60800 --- /dev/null +++ b/SOURCES/0087-man-ip-link-document-MACVLAN-MACVTAP-interface-types.patch @@ -0,0 +1,84 @@ +From 2d76f7483d2bf0857d325883fe22c924d1dfcb53 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 15:57:01 +0100 +Subject: [PATCH] man: ip-link: document MACVLAN/MACVTAP interface types + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1013584 +Upstream Status: iproute2.git commit a60223bc1c10d +Conflicts: Changed context due to missing GENEVE support + +commit a60223bc1c10d4b172caa966acebb5a1620d0d6f +Author: Phil Sutter +Date: Fri Sep 25 14:09:51 2015 +0200 + + man: ip-link: document MACVLAN/MACVTAP interface types + + Signed-off-by: Phil Sutter +--- + man/man8/ip-link.8.in | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 50 insertions(+) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 88e014b..4614ba3 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -651,6 +651,56 @@ the following additional arguments are supported: + .BI mode " MODE " + - specifies the mode (datagram or connected) to use. + ++.TP ++MACVLAN and MACVTAP Type Support ++For a link of type ++.I MACVLAN ++or ++.I MACVTAP ++the following additional arguments are supported: ++ ++.BI "ip link add link " DEVICE " name " NAME ++.BR type " { " macvlan " | " macvtap " } " ++.BR mode " { " private " | " vepa " | " bridge " | " passthru ++.BR " [ " nopromisc " ] } " ++ ++.in +8 ++.sp ++.BR type " { " macvlan " | " macvtap " } " ++- specifies the link type to use. ++.BR macvlan " creates just a virtual interface, while " ++.BR macvtap " in addition creates a character device " ++.BR /dev/tapX " to be used just like a " tuntap " device." ++ ++.B mode private ++- Do not allow communication between ++.B macvlan ++instances on the same physical interface, even if the external switch supports ++hairpin mode. ++ ++.B mode vepa ++- Virtual Ethernet Port Aggregator mode. Data from one ++.B macvlan ++instance to the other on the same physical interface is transmitted over the ++physical interface. Either the attached switch needs to support hairpin mode, ++or there must be a TCP/IP router forwarding the packets in order to allow ++communication. This is the default mode. ++ ++.B mode bridge ++- In bridge mode, all endpoints are directly connected to each other, ++communication is not redirected through the physical interface's peer. ++ ++.BR mode " " passthru " [ " nopromisc " ] " ++- This mode gives more power to a single endpoint, usually in ++.BR macvtap " mode. It is not allowed for more than one endpoint on the same " ++physical interface. All traffic will be forwarded to this endpoint, allowing ++virtio guests to change MAC address or set promiscuous mode in order to bridge ++the interface or create vlan interfaces on top of it. By default, this mode ++forces the underlying interface into promiscuous mode. Passing the ++.BR nopromisc " flag prevents this, so the promisc flag may be controlled " ++using standard tools. ++.in -8 ++ + .SS ip link delete - delete virtual link + .I DEVICE + specifies the virtual device to act operate on. +-- +1.8.3.1 + diff --git a/SOURCES/0088-iplink-macvtap-fix-man-page.patch b/SOURCES/0088-iplink-macvtap-fix-man-page.patch new file mode 100644 index 0000000..35f4dfd --- /dev/null +++ b/SOURCES/0088-iplink-macvtap-fix-man-page.patch @@ -0,0 +1,46 @@ +From 360aec0603f2dc23eea1e2ec80497f5f4ef673ac Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 16:11:30 +0100 +Subject: [PATCH] iplink: macvtap: fix man page + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1013584 +Upstream Status: iproute2.git commit e4c356827acc6 + +commit e4c356827acc661e33b6a6bdffc5ededf7beb659 +Author: Rami Rosen +Date: Sat Jul 19 12:00:25 2014 +0300 + + iplink: macvtap: fix man page + + This patch adds description about macvtap to ip-link.8 man page. + + Signed-off-by: Rami Rosen +--- + man/man8/ip-link.8.in | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 4614ba3..4982268 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -58,6 +58,7 @@ ip-link \- network device configuration + .BR ifb " | " + .BR ipoib " |" + .BR macvlan " | " ++.BR macvtap " | " + .BR vcan " | " + .BR veth " | " + .BR vlan " | " +@@ -183,6 +184,9 @@ Link types: + .B macvlan + - Virtual interface base on link layer address (MAC) + .sp ++.B macvtap ++- Virtual interface based on link layer address (MAC) and TAP. ++.sp + .B vcan + - Virtual Controller Area Network interface + .sp +-- +1.8.3.1 + diff --git a/SOURCES/0089-iprule-Align-help-text-with-man-page-synopsis.patch b/SOURCES/0089-iprule-Align-help-text-with-man-page-synopsis.patch new file mode 100644 index 0000000..332f350 --- /dev/null +++ b/SOURCES/0089-iprule-Align-help-text-with-man-page-synopsis.patch @@ -0,0 +1,43 @@ +From a1655d17463e2a71af8d43381333c14661ad1e50 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:32:48 +0100 +Subject: [PATCH] iprule: Align help text with man page synopsis + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 67eedcd9a145f +Conflicts: Patch adjusted to missing save/restore support. + +commit 67eedcd9a145f30aa0a185b7235f01b66349effe +Author: Phil Sutter +Date: Thu Feb 25 13:07:35 2016 +0100 + + iprule: Align help text with man page synopsis + + The help text was misleading: One could think it is possible to list + rules by selector, which would be nice but isn't. This change also + clarifies that 'ip rule' defaults to 'list' if no further arguments are + given. + + Signed-off-by: Phil Sutter +--- + ip/iprule.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/ip/iprule.c b/ip/iprule.c +index 89fa7ef..059b50b 100644 +--- a/ip/iprule.c ++++ b/ip/iprule.c +@@ -32,7 +32,9 @@ static void usage(void) __attribute__((noreturn)); + + static void usage(void) + { +- fprintf(stderr, "Usage: ip rule [ list | add | del | flush ] SELECTOR ACTION\n"); ++ fprintf(stderr, "Usage: ip rule { add | del } SELECTOR ACTION\n"); ++ fprintf(stderr, " ip rule { flush }\n"); ++ fprintf(stderr, " ip rule [ list ]\n"); + fprintf(stderr, "SELECTOR := [ not ] [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK[/MASK] ]\n"); + fprintf(stderr, " [ iif STRING ] [ oif STRING ] [ pref NUMBER ]\n"); + fprintf(stderr, "ACTION := [ table TABLE_ID ]\n"); +-- +1.8.3.1 + diff --git a/SOURCES/0090-ipl2tp-Print-help-even-on-systems-without-l2tp-suppo.patch b/SOURCES/0090-ipl2tp-Print-help-even-on-systems-without-l2tp-suppo.patch new file mode 100644 index 0000000..69f49a1 --- /dev/null +++ b/SOURCES/0090-ipl2tp-Print-help-even-on-systems-without-l2tp-suppo.patch @@ -0,0 +1,55 @@ +From 4112b882e90a2338ecc9ad83a8b01d77725ab52d Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:33:46 +0100 +Subject: [PATCH] ipl2tp: Print help even on systems without l2tp support + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit e897776690aec + +commit e897776690aec728f9033eef146783d3a3d48033 +Author: Phil Sutter +Date: Wed Feb 24 09:12:47 2016 +0100 + + ipl2tp: Print help even on systems without l2tp support + + Signed-off-by: Phil Sutter +--- + ip/ipl2tp.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c +index 2f7c9bf..92e15c5 100644 +--- a/ip/ipl2tp.c ++++ b/ip/ipl2tp.c +@@ -719,6 +719,9 @@ static int do_show(int argc, char **argv) + + int do_ipl2tp(int argc, char **argv) + { ++ if (argc < 1 || !matches(*argv, "help")) ++ usage(); ++ + if (genl_family < 0) { + if (rtnl_open_byproto(&genl_rth, 0, NETLINK_GENERIC) < 0) { + fprintf(stderr, "Cannot open generic netlink socket\n"); +@@ -730,9 +733,6 @@ int do_ipl2tp(int argc, char **argv) + exit(1); + } + +- if (argc < 1) +- usage(); +- + if (matches(*argv, "add") == 0) + return do_add(argc-1, argv+1); + if (matches(*argv, "delete") == 0) +@@ -741,8 +741,6 @@ int do_ipl2tp(int argc, char **argv) + matches(*argv, "lst") == 0 || + matches(*argv, "list") == 0) + return do_show(argc-1, argv+1); +- if (matches(*argv, "help") == 0) +- usage(); + + fprintf(stderr, "Command \"%s\" is unknown, try \"ip l2tp help\".\n", *argv); + exit(-1); +-- +1.8.3.1 + diff --git a/SOURCES/0091-ip-align-help-text-with-manpage.patch b/SOURCES/0091-ip-align-help-text-with-manpage.patch new file mode 100644 index 0000000..dc4cad6 --- /dev/null +++ b/SOURCES/0091-ip-align-help-text-with-manpage.patch @@ -0,0 +1,39 @@ +From 6f07a04604fada54d38c78c51b174931c2e42a35 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:33:46 +0100 +Subject: [PATCH] ip: align help text with manpage + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 7a53aa592fffb + +commit 7a53aa592fffbe5984aa8adbe76f5b370b247f05 +Author: Phil Sutter +Date: Wed Mar 2 19:19:49 2016 +0100 + + ip: align help text with manpage + + Although the ip command accepts both "neighbor" and "neighbour" as + subcommand, I assume it's sufficient to list it in help text as just + "neigh" like ip.8 does. + + Signed-off-by: Phil Sutter +--- + ip/ip.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/ip.c b/ip/ip.c +index 361daf4..8b9b9c0 100644 +--- a/ip/ip.c ++++ b/ip/ip.c +@@ -47,7 +47,7 @@ static void usage(void) + fprintf(stderr, + "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n" + " ip [ -force ] -batch filename\n" +-"where OBJECT := { link | address | addrlabel | route | rule | neighbor | ntable |\n" ++"where OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |\n" + " tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |\n" + " netns | l2tp | tcp_metrics | token }\n" + " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" +-- +1.8.3.1 + diff --git a/SOURCES/0092-ipaddrlabel-Improve-help-text-precision.patch b/SOURCES/0092-ipaddrlabel-Improve-help-text-precision.patch new file mode 100644 index 0000000..d31aea3 --- /dev/null +++ b/SOURCES/0092-ipaddrlabel-Improve-help-text-precision.patch @@ -0,0 +1,39 @@ +From 42bab91fdeafcbbc1766ccc348b7a57082a7fbb4 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:33:46 +0100 +Subject: [PATCH] ipaddrlabel: Improve help text precision + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 27ff1a564bb20 + +commit 27ff1a564bb20f80dca1023b29d5d22fe196e727 +Author: Phil Sutter +Date: Wed Mar 2 19:19:50 2016 +0100 + + ipaddrlabel: Improve help text precision + + Neither 'list' nor 'flush' actions accept parameters, and with given + prefix the action keyword is not optional anymore. + + Signed-off-by: Phil Sutter +--- + ip/ipaddrlabel.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c +index 1158b33..7f25f0b 100644 +--- a/ip/ipaddrlabel.c ++++ b/ip/ipaddrlabel.c +@@ -50,7 +50,8 @@ static void usage(void) __attribute__((noreturn)); + + static void usage(void) + { +- fprintf(stderr, "Usage: ip addrlabel [ list | add | del | flush ] prefix PREFIX [ dev DEV ] [ label LABEL ]\n"); ++ fprintf(stderr, "Usage: ip addrlabel { add | del } prefix PREFIX [ dev DEV ] [ label LABEL ]\n"); ++ fprintf(stderr, " ip addrlabel [ list | flush | help ]\n"); + exit(-1); + } + +-- +1.8.3.1 + diff --git a/SOURCES/0093-iplink-fix-help-text-syntax.patch b/SOURCES/0093-iplink-fix-help-text-syntax.patch new file mode 100644 index 0000000..1c3016a --- /dev/null +++ b/SOURCES/0093-iplink-fix-help-text-syntax.patch @@ -0,0 +1,54 @@ +From 99bd608a259c2ef0cafdbb96aa38c8e934c63955 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:33:46 +0100 +Subject: [PATCH] iplink: fix help text syntax + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 5c2ea5b8c001f +Conflicts: Missing commit 6c5ffb9a2c3db ("iplink: cleanup whitespace and + checkpatch issues"), which introduces worse conflicts. + Relevant changes therefore incorporated here. + +commit 5c2ea5b8c001fe3e7c85f2c93b9b05bcb035bafa +Author: Phil Sutter +Date: Wed Mar 2 19:19:51 2016 +0100 + + iplink: fix help text syntax + + Get rid of extraneous closing brackets and while here, merge the double + netns parameter. + + Signed-off-by: Phil Sutter +--- + ip/iplink.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index f444bef..787d743 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -70,17 +70,16 @@ void iplink_usage(void) + fprintf(stderr, " [ address LLADDR ]\n"); + fprintf(stderr, " [ broadcast LLADDR ]\n"); + fprintf(stderr, " [ mtu MTU ]\n"); +- fprintf(stderr, " [ netns PID ]\n"); +- fprintf(stderr, " [ netns NAME ]\n"); ++ fprintf(stderr, " [ netns { PID | NAME } ]\n"); + fprintf(stderr, " [ link-netnsid ID ]\n"); + fprintf(stderr, " [ alias NAME ]\n"); + fprintf(stderr, " [ vf NUM [ mac LLADDR ]\n"); + fprintf(stderr, " [ vlan VLANID [ qos VLAN-QOS ] ]\n"); + +- fprintf(stderr, " [ rate TXRATE ] ] \n"); ++ fprintf(stderr, " [ rate TXRATE ]\n"); + +- fprintf(stderr, " [ spoofchk { on | off} ] ] \n"); +- fprintf(stderr, " [ query_rss { on | off} ] ] \n"); ++ fprintf(stderr, " [ spoofchk { on | off} ]\n"); ++ fprintf(stderr, " [ query_rss { on | off} ]\n"); + fprintf(stderr, " [ state { auto | enable | disable} ] ]\n"); + fprintf(stderr, " [ master DEVICE ]\n"); + fprintf(stderr, " [ nomaster ]\n"); +-- +1.8.3.1 + diff --git a/SOURCES/0094-ipneigh-add-missing-proxy-keyword-to-help-text.patch b/SOURCES/0094-ipneigh-add-missing-proxy-keyword-to-help-text.patch new file mode 100644 index 0000000..eb6c2d1 --- /dev/null +++ b/SOURCES/0094-ipneigh-add-missing-proxy-keyword-to-help-text.patch @@ -0,0 +1,37 @@ +From bef1cf702a74c0c15a5b763ab95bc22ad34ecca9 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:36:42 +0100 +Subject: [PATCH] ipneigh: add missing proxy keyword to help text + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit c339b4cc53f64 + +commit c339b4cc53f64b79b384524ce0e124965d341579 +Author: Phil Sutter +Date: Wed Mar 2 19:19:52 2016 +0100 + + ipneigh: add missing proxy keyword to help text + + And while we're at it, add whitespace around braces and pipe symbol. + + Signed-off-by: Phil Sutter +--- + ip/ipneigh.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/ipneigh.c b/ip/ipneigh.c +index 19fd8e2..2dbd537 100644 +--- a/ip/ipneigh.c ++++ b/ip/ipneigh.c +@@ -48,7 +48,7 @@ static void usage(void) + fprintf(stderr, "Usage: ip neigh { add | del | change | replace } { ADDR [ lladdr LLADDR ]\n" + " [ nud { permanent | noarp | stale | reachable } ]\n" + " | proxy ADDR } [ dev DEV ]\n"); +- fprintf(stderr, " ip neigh {show|flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]\n"); ++ fprintf(stderr, " ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ]\n"); + exit(-1); + } + +-- +1.8.3.1 + diff --git a/SOURCES/0095-ipntable-Fix-typo-in-help-text.patch b/SOURCES/0095-ipntable-Fix-typo-in-help-text.patch new file mode 100644 index 0000000..173f12c --- /dev/null +++ b/SOURCES/0095-ipntable-Fix-typo-in-help-text.patch @@ -0,0 +1,35 @@ +From 0c03f463e786c6c597590cbc57b2bad29ab4fd42 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:36:42 +0100 +Subject: [PATCH] ipntable: Fix typo in help text + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit f1fdcfe66a8e1 + +commit f1fdcfe66a8e197a5015cb81c789061c03629108 +Author: Phil Sutter +Date: Wed Mar 2 19:19:53 2016 +0100 + + ipntable: Fix typo in help text + + Signed-off-by: Phil Sutter +--- + ip/ipntable.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/ipntable.c b/ip/ipntable.c +index ca5d935..3ff5e65 100644 +--- a/ip/ipntable.c ++++ b/ip/ipntable.c +@@ -53,7 +53,7 @@ static void usage(void) + + "PARMS := [ base_reachable MSEC ] [ retrans MSEC ] [ gc_stale MSEC ]\n" + " [ delay_probe MSEC ] [ queue LEN ]\n" +- " [ app_probs VAL ] [ ucast_probes VAL ] [ mcast_probes VAL ]\n" ++ " [ app_probes VAL ] [ ucast_probes VAL ] [ mcast_probes VAL ]\n" + " [ anycast_delay MSEC ] [ proxy_delay MSEC ] [ proxy_queue LEN ]\n" + " [ locktime MSEC ]\n" + ); +-- +1.8.3.1 + diff --git a/SOURCES/0096-iproute-TYPE-keyword-is-not-optional-fix-help-text-a.patch b/SOURCES/0096-iproute-TYPE-keyword-is-not-optional-fix-help-text-a.patch new file mode 100644 index 0000000..7033942 --- /dev/null +++ b/SOURCES/0096-iproute-TYPE-keyword-is-not-optional-fix-help-text-a.patch @@ -0,0 +1,50 @@ +From 42dcbf8a80e4d9ccdf9b777674656db26fc9eb4c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:36:42 +0100 +Subject: [PATCH] iproute: TYPE keyword is not optional, fix help text + accordingly + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 070ebbdf754b0 +Conflicts: Patch applied manually due to multiple missing features. + +commit 070ebbdf754b02e1d7f9e9dbd84e1499332d9063 +Author: Phil Sutter +Date: Wed Mar 2 19:19:54 2016 +0100 + + iproute: TYPE keyword is not optional, fix help text accordingly + + This is a bit pedantic, but brackets ([]) show optional values and since + TYPE must not become empty, they're not suited to surround the type + keyword choices. Use curly braces instead. + + Also add some missing whitespace to the parameter list above. + + Signed-off-by: Phil Sutter +--- + ip/iproute.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index b7e0b15..74599e4 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -78,12 +78,12 @@ static void usage(void) + fprintf(stderr, "NH := [ via ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n"); + fprintf(stderr, "OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]\n"); + fprintf(stderr, " [ rtt TIME ] [ rttvar TIME ] [reordering NUMBER ]\n"); +- fprintf(stderr, " [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n"); ++ fprintf(stderr, " [ window NUMBER ] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n"); + fprintf(stderr, " [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n"); + fprintf(stderr, " [ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]\n"); + fprintf(stderr, " [ features FEATURES ] [ quickack BOOL ] [ congctl NAME ]\n"); +- fprintf(stderr, "TYPE := [ unicast | local | broadcast | multicast | throw |\n"); +- fprintf(stderr, " unreachable | prohibit | blackhole | nat ]\n"); ++ fprintf(stderr, "TYPE := { unicast | local | broadcast | multicast | throw |\n"); ++ fprintf(stderr, " unreachable | prohibit | blackhole | nat }\n"); + fprintf(stderr, "TABLE_ID := [ local | main | default | all | NUMBER ]\n"); + fprintf(stderr, "SCOPE := [ host | link | global | NUMBER ]\n"); + fprintf(stderr, "NHFLAGS := [ onlink | pervasive ]\n"); +-- +1.8.3.1 + diff --git a/SOURCES/0097-iprule-add-missing-nat-keyword-to-help-text.patch b/SOURCES/0097-iprule-add-missing-nat-keyword-to-help-text.patch new file mode 100644 index 0000000..09418e6 --- /dev/null +++ b/SOURCES/0097-iprule-add-missing-nat-keyword-to-help-text.patch @@ -0,0 +1,34 @@ +From 0c053afb5900cb6f4b91a700d595c49fc41b2005 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:41:29 +0100 +Subject: [PATCH] iprule: add missing nat keyword to help text + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 20f2af78fb85e + +commit 20f2af78fb85e53c6d41e73f010607b8d0edbd6e +Author: Phil Sutter +Date: Wed Mar 2 19:19:55 2016 +0100 + + iprule: add missing nat keyword to help text + + Signed-off-by: Phil Sutter +--- + ip/iprule.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ip/iprule.c b/ip/iprule.c +index 059b50b..2a153f5 100644 +--- a/ip/iprule.c ++++ b/ip/iprule.c +@@ -38,6 +38,7 @@ static void usage(void) + fprintf(stderr, "SELECTOR := [ not ] [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK[/MASK] ]\n"); + fprintf(stderr, " [ iif STRING ] [ oif STRING ] [ pref NUMBER ]\n"); + fprintf(stderr, "ACTION := [ table TABLE_ID ]\n"); ++ fprintf(stderr, " [ nat ADDRESS ]\n"); + fprintf(stderr, " [ realms [SRCREALM/]DSTREALM ]\n"); + fprintf(stderr, " [ goto NUMBER ]\n"); + fprintf(stderr, "TABLE_ID := [ local | main | default | NUMBER ]\n"); +-- +1.8.3.1 + diff --git a/SOURCES/0098-man-ip-address.8-Minor-syntax-fixes.patch b/SOURCES/0098-man-ip-address.8-Minor-syntax-fixes.patch new file mode 100644 index 0000000..2727399 --- /dev/null +++ b/SOURCES/0098-man-ip-address.8-Minor-syntax-fixes.patch @@ -0,0 +1,55 @@ +From 715a353a639ae91ca8dfd6c09492ed6426b060bc Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:41:30 +0100 +Subject: [PATCH] man: ip-address.8: Minor syntax fixes + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 37fdeb585d773 + +commit 37fdeb585d773b22a193c07b0beef8994c2b741f +Author: Phil Sutter +Date: Wed Mar 2 19:19:56 2016 +0100 + + man: ip-address.8: Minor syntax fixes + + Clarify that the optional '-' prefix of the 'tentative', 'deprecated' + and 'dadfailed' keywords has to be put right in front of them, no + whitespace is allowed in between. + + In addition to that, clarify that it is valid to pass both 'valid_lft' + and 'preferred_lft' at the same time to 'ip address'. + + Signed-off-by: Phil Sutter +--- + man/man8/ip-address.8.in | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in +index 159d906..ff3fe0b 100644 +--- a/man/man8/ip-address.8.in ++++ b/man/man8/ip-address.8.in +@@ -58,9 +58,9 @@ ip-address \- protocol address management + + .ti -8 + .IR FLAG " := " +-.RB "[ " permanent " | " dynamic " | " secondary " | " primary " | \ +-[ - ] " tentative " | [ - ] " deprecated " | [ - ] " dadfailed " | "\ +-temporary " | " CONFFLAG-LIST " ]" ++.RB "[ " permanent " | " dynamic " | " secondary " | " primary " |" ++.RB [ - ] tentative " | [" - ] deprecated " | [" - ] dadfailed " |" ++.BR temporary " | " CONFFLAG-LIST " ]" + + .ti -8 + .IR CONFFLAG-LIST " := [ " CONFFLAG-LIST " ] " CONFFLAG +@@ -72,7 +72,7 @@ temporary " | " CONFFLAG-LIST " ]" + .ti -8 + .IR LIFETIME " := [ " + .BI valid_lft " LFT" +-.RB "| " preferred_lft ++.RB "] [ " preferred_lft + .IR LFT " ]" + + .ti -8 +-- +1.8.3.1 + diff --git a/SOURCES/0099-man-ip-link.8-minor-font-fix.patch b/SOURCES/0099-man-ip-link.8-minor-font-fix.patch new file mode 100644 index 0000000..5bf3e9b --- /dev/null +++ b/SOURCES/0099-man-ip-link.8-minor-font-fix.patch @@ -0,0 +1,37 @@ +From 4fdf53298b2ab445960d5ce2ee26208752f5b2a8 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:41:30 +0100 +Subject: [PATCH] man: ip-link.8: minor font fix + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit d890144ecf750 + +commit d890144ecf7501c9117355d14d013dd5c98936ef +Author: Phil Sutter +Date: Wed Mar 2 19:19:57 2016 +0100 + + man: ip-link.8: minor font fix + + We commonly use bold font for terminals and italic for non-terminals. + + Signed-off-by: Phil Sutter +--- + man/man8/ip-link.8.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 4982268..d369598 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -46,7 +46,7 @@ ip-link \- network device configuration + .RB "[ " numrxqueues + .IR QUEUE_COUNT " ]" + .br +-.BR type " TYPE" ++.BI type " TYPE" + .RI "[ " ARGS " ]" + + .ti -8 +-- +1.8.3.1 + diff --git a/SOURCES/0100-man-ip-link.8-Fix-and-improve-synopsis.patch b/SOURCES/0100-man-ip-link.8-Fix-and-improve-synopsis.patch new file mode 100644 index 0000000..5373d5b --- /dev/null +++ b/SOURCES/0100-man-ip-link.8-Fix-and-improve-synopsis.patch @@ -0,0 +1,145 @@ +From 1cdfff2f66b7f733dc424c933e91546fae6eac4a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:41:30 +0100 +Subject: [PATCH] man: ip-link.8: Fix and improve synopsis + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit ca611d6408c9b +Conflicts: Patch adjusted to missing features. + +commit ca611d6408c9bf17d122923c72d27d032e054cd8 +Author: Phil Sutter +Date: Wed Mar 2 19:19:58 2016 +0100 + + man: ip-link.8: Fix and improve synopsis + + Reflect that it is possible to pass multiple parameters at the same + time, also use the same trick the help text uses to emphasize vf + specific parameters. + + Signed-off-by: Phil Sutter +--- + man/man8/ip-link.8.in | 81 ++++++++++++++++++++++++++++----------------------- + 1 file changed, 45 insertions(+), 36 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index d369598..6ce2cc8 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -83,68 +83,77 @@ ip-link \- network device configuration + .BR "ip link set " { + .IR DEVICE " | " + .BI "group " GROUP +-.RB "} { " up " | " down " | " arp " { " on " | " off " } |" ++.RB "} [ { " up " | " down " } ]" + .br +-.BR promisc " { " on " | " off " } |" ++.RB "[ " arp " { " on " | " off " } ]" + .br +-.BR allmulticast " { " on " | " off " } |" ++.RB "[ " dynamic " { " on " | " off " } ]" + .br +-.BR dynamic " { " on " | " off " } |" ++.RB "[ " multicast " { " on " | " off " } ]" + .br +-.BR multicast " { " on " | " off " } |" ++.RB "[ " allmulticast " { " on " | " off " } ]" + .br +-.B txqueuelen +-.IR PACKETS " |" ++.RB "[ " promisc " { " on " | " off " } ]" + .br +-.B name +-.IR NEWNAME " |" ++.RB "[ " trailers " { " on " | " off " } ]" + .br +-.B address +-.IR LLADDR " |" +-.B broadcast +-.IR LLADDR " |" ++.RB "[ " txqueuelen ++.IR PACKETS " ]" + .br +-.B mtu +-.IR MTU " |" ++.RB "[ " name ++.IR NEWNAME " ]" + .br +-.B netns +-.IR PID " |" ++.RB "[ " address ++.IR LLADDR " ]" + .br +-.B netns +-.IR NETNSNAME " |" ++.RB "[ " broadcast ++.IR LLADDR " ]" + .br +-.B alias +-.IR NAME " |" ++.RB "[ " mtu ++.IR MTU " ]" + .br +-.B vf ++.RB "[ " netns " {" ++.IR PID " | " NETNSNAME " } ]" ++.br ++.RB "[ " link-netnsid ++.IR ID " ]" ++.br ++.RB "[ " alias ++.IR NAME " ]" ++.br ++.RB "[ " vf + .IR NUM " [" + .B mac +-.IR LLADDR " ] [" +-.B vlan ++.IR LLADDR " ]" ++.br ++.in +9 ++.RB "[ " vlan + .IR VLANID " [ " + .B qos +-.IR VLAN-QOS " ] ] [" +-.B rate +-.IR TXRATE " ] [" +-.B spoofchk { on | off } +-] | ++.IR VLAN-QOS " ] ]" ++.br ++.RB "[ " rate ++.IR TXRATE " ]" + .br +-.B master +-.IR DEVICE " |" ++.RB "[ " spoofchk " { " on " | " off " } ]" + .br +-.B nomaster " |" ++.RB "[ " state " { " auto " | " enable " | " disable " } ] ]" ++.br ++.in -9 ++.RB "[ " master ++.IR DEVICE " ]" + .br +-.B addrgenmode { eui64 | none } ++.RB "[ " nomaster " ]" + .br +-.B link-netnsid ID +-.BR " }" ++.RB "[ " addrgenmode " { " eui64 " | " none " } ]" + + + .ti -8 + .B ip link show + .RI "[ " DEVICE " | " + .B group +-.IR GROUP " ]" ++.IR GROUP " ] [" ++.BR up " ]" + + .ti -8 + .B ip link help +-- +1.8.3.1 + diff --git a/SOURCES/0101-man-ip-neighbour-Fix-for-missing-NUD_STATE-descripti.patch b/SOURCES/0101-man-ip-neighbour-Fix-for-missing-NUD_STATE-descripti.patch new file mode 100644 index 0000000..b5d6b4a --- /dev/null +++ b/SOURCES/0101-man-ip-neighbour-Fix-for-missing-NUD_STATE-descripti.patch @@ -0,0 +1,65 @@ +From bd8b3c3337511956fd6a34e7f0071a717f238ab9 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:41:49 +0100 +Subject: [PATCH] man: ip-neighbour: Fix for missing NUD_STATE description + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 03cb9d58bc828 + +commit 03cb9d58bc8282d156ff644ad5af15217855af54 +Author: Phil Sutter +Date: Wed Mar 2 19:19:59 2016 +0100 + + man: ip-neighbour: Fix for missing NUD_STATE description + + Signed-off-by: Phil Sutter +--- + man/man8/ip-neighbour.8 | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/man/man8/ip-neighbour.8 b/man/man8/ip-neighbour.8 +index 631b4c0..f3068f4 100644 +--- a/man/man8/ip-neighbour.8 ++++ b/man/man8/ip-neighbour.8 +@@ -18,7 +18,9 @@ ip-neighbour \- neighbour/arp tables management. + .IR ADDR " [ " + .B lladdr + .IR LLADDR " ] [ " +-.BR nud " { " permanent " | " noarp " | " stale " | " reachable " } ] | " proxy ++.B nud ++.IR STATE " ] |" ++.B proxy + .IR ADDR " } [ " + .B dev + .IR DEV " ]" +@@ -31,6 +33,9 @@ ip-neighbour \- neighbour/arp tables management. + .B nud + .IR STATE " ]" + ++.ti -8 ++.IR STATE " := {" ++.BR permanent " | " noarp " | " stale " | " reachable " }" + + .SH DESCRIPTION + The +@@ -75,7 +80,7 @@ can also be + .BR "null" . + + .TP +-.BI nud " NUD_STATE" ++.BI nud " STATE" + the state of the neighbour entry. + .B nud + is an abbreviation for 'Neighbour Unreachability Detection'. +@@ -147,7 +152,7 @@ list neighbour proxies. + only list neighbours which are not currently in use. + + .TP +-.BI nud " NUD_STATE" ++.BI nud " STATE" + only list neighbour entries in this state. + .I NUD_STATE + takes values listed below or the special value +-- +1.8.3.1 + diff --git a/SOURCES/0102-man-ip-netns.8-Clarify-synopsis-a-bit.patch b/SOURCES/0102-man-ip-netns.8-Clarify-synopsis-a-bit.patch new file mode 100644 index 0000000..b9e840b --- /dev/null +++ b/SOURCES/0102-man-ip-netns.8-Clarify-synopsis-a-bit.patch @@ -0,0 +1,47 @@ +From ade70fd224787a92c881156d9f097876558e9523 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:41:49 +0100 +Subject: [PATCH] man: ip-netns.8: Clarify synopsis a bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 57e1ace02a3e3 + +commit 57e1ace02a3e3d212c2d8809d63b729ea59d7427 +Author: Phil Sutter +Date: Wed Mar 2 19:20:00 2016 +0100 + + man: ip-netns.8: Clarify synopsis a bit + + Use brackets to show that 'ip netns' defaults to action 'list', drop + superfluous curly braces around 'set' action keyword. + + Signed-off-by: Phil Sutter +--- + man/man8/ip-netns.8 | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8 +index c9b0fbc..c5310e2 100644 +--- a/man/man8/ip-netns.8 ++++ b/man/man8/ip-netns.8 +@@ -13,7 +13,7 @@ ip-netns \- process network namespace management + .BR help " }" + .sp + .ti -8 +-.BR "ip netns" " { " list " } " ++.BR "ip netns" " [ " list " ]" + + .ti -8 + .B ip netns add +@@ -24,7 +24,7 @@ ip-netns \- process network namespace management + .RI "[ " NETNSNAME " ]" + + .ti -8 +-.BR "ip netns" " { " set " } " ++.B ip netns set + .I NETNSNAME NETNSID + + .ti -8 +-- +1.8.3.1 + diff --git a/SOURCES/0103-man-ip-ntable.8-Review-synopsis-section.patch b/SOURCES/0103-man-ip-ntable.8-Review-synopsis-section.patch new file mode 100644 index 0000000..cb3533e --- /dev/null +++ b/SOURCES/0103-man-ip-ntable.8-Review-synopsis-section.patch @@ -0,0 +1,96 @@ +From 3482c7efe9f08c25761d27aa94a5acba69090c91 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:41:49 +0100 +Subject: [PATCH] man: ip-ntable.8: Review synopsis section + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 54beacc33464d + +commit 54beacc33464d51db6c44f606d1be6cd75591c0d +Author: Phil Sutter +Date: Wed Mar 2 19:20:01 2016 +0100 + + man: ip-ntable.8: Review synopsis section + + The first line contained a c'n'p error, incorrectly listing 'ip address' + syntax. Since PARAMS is used just once and there are not many other + parameters to 'ip ntable change', state them inline and in addition to + that clarify the possibility to pass multiple parameters at once. + + Signed-off-by: Phil Sutter +--- + man/man8/ip-ntable.8 | 39 ++++++++++++++++++++++----------------- + 1 file changed, 22 insertions(+), 17 deletions(-) + +diff --git a/man/man8/ip-ntable.8 b/man/man8/ip-ntable.8 +index d903a17..2b95632 100644 +--- a/man/man8/ip-ntable.8 ++++ b/man/man8/ip-ntable.8 +@@ -8,7 +8,7 @@ ip-ntable - neighbour table configuration + .ti -8 + .B ip + .RI "[ " OPTIONS " ]" +-.B address ++.B ntable + .RI " { " COMMAND " | " + .BR help " }" + .sp +@@ -17,34 +17,39 @@ ip-ntable - neighbour table configuration + .BR "ip ntable change name" + .IR NAME " [ " + .B dev +-.IR DEV " ] " PARMS +- +-.ti -8 +-.IR PARMS " := { " ++.IR DEV " ] [" + .B thresh1 +-.IR VAL " | " ++.IR VAL " ] [" + .B thresh2 +-.IR VAL " | " ++.IR VAL " ] [" + .B thresh3 +-.IR VAL " | " ++.IR VAL " ] [" + .B gc_int +-.IR MSEC " | " ++.IR MSEC " ] [" + .B base_reachable +-.IR MSEC " | " ++.IR MSEC " ] [" + .B retrans +-.IR MSEC " | " "gc_stale MSEC " " | " ++.IR MSEC " ] [" ++.B gc_stale ++.IR MSEC " ] [" + .B delay_probe +-.IR MSEC " | " "queue LEN " " | " ++.IR MSEC " ] [" ++.B queue ++.IR LEN " ] [" + .B app_probs +-.IR VAL " | " ++.IR VAL " ] [" + .B ucast_probes +-.IR VAL " | " "mcast_probes VAL " " | " ++.IR VAL " ] [" ++.B mcast_probes ++.IR VAL " ] [" + .B anycast_delay +-.IR MSEC " | " ++.IR MSEC " ] [" + .B proxy_delay +-.IR MSEC " | " "proxy_queue LEN " " | " ++.IR MSEC " ] [" ++.B proxy_queue ++.IR LEN " ] [" + .B locktime +-.IR MSEC " }" ++.IR MSEC " ]" + + .ti -8 + .BR "ip ntable show" " [ " +-- +1.8.3.1 + diff --git a/SOURCES/0104-man-ip-rule.8-Review-synopsis-section.patch b/SOURCES/0104-man-ip-rule.8-Review-synopsis-section.patch new file mode 100644 index 0000000..adb245b --- /dev/null +++ b/SOURCES/0104-man-ip-rule.8-Review-synopsis-section.patch @@ -0,0 +1,81 @@ +From f50767955c0f8e45fc13b5756bed7bb5bce12bca Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:41:49 +0100 +Subject: [PATCH] man: ip-rule.8: Review synopsis section + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 582b0fc6cb443 +Conflicts: Adjusted to missing save/restore feature and suppressor flag. + +commit 582b0fc6cb443ebe71b82654aa6307d55cd1fc1a +Author: Phil Sutter +Date: Wed Mar 2 19:20:02 2016 +0100 + + man: ip-rule.8: Review synopsis section + + Clarify that 'ip rule' defaults to action 'list', that 'flush' and + 'save' actions don't accept additional parameters, add missing 'not' and + 'goto' keywords and finally fix fonts used in 'fwmark' and 'realms' + parameters. + + Signed-off-by: Phil Sutter +--- + man/man8/ip-rule.8 | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/man/man8/ip-rule.8 b/man/man8/ip-rule.8 +index 16414c5..2594ff3 100644 +--- a/man/man8/ip-rule.8 ++++ b/man/man8/ip-rule.8 +@@ -9,17 +9,26 @@ ip-rule \- routing policy database management + .B ip + .RI "[ " OPTIONS " ]" + .B rule +-.RI " { " COMMAND " | " ++.RI "{ " COMMAND " | " + .BR help " }" + .sp + + .ti -8 + .B ip rule +-.RB " [ " list " | " add " | " del " | " flush " ]" ++.RB "[ " list " ]" ++ ++.ti -8 ++.B ip rule ++.RB "{ " add " | " del " }" + .I SELECTOR ACTION + + .ti -8 ++.B ip rule ++.RB "{ " flush " }" ++ ++.ti -8 + .IR SELECTOR " := [ " ++.BR not " ] [" + .B from + .IR PREFIX " ] [ " + .B to +@@ -27,7 +36,7 @@ ip-rule \- routing policy database management + .B tos + .IR TOS " ] [ " + .B fwmark +-.IR FWMARK[/MASK] " ] [ " ++.IR FWMARK\fR[\fB/\fIMASK "] ] [ " + .B iif + .IR STRING " ] [ " + .B oif +@@ -42,7 +51,9 @@ ip-rule \- routing policy database management + .B nat + .IR ADDRESS " ] [ " + .B realms +-.RI "[" SRCREALM "/]" DSTREALM " ]" ++.RI "[" SRCREALM "\fB/\fR]" DSTREALM " ] [" ++.B goto ++.IR NUMBER " ]" + + .ti -8 + .IR TABLE_ID " := [ " +-- +1.8.3.1 + diff --git a/SOURCES/0105-man-ip-token.8-Review-synopsis-section.patch b/SOURCES/0105-man-ip-token.8-Review-synopsis-section.patch new file mode 100644 index 0000000..5365fef --- /dev/null +++ b/SOURCES/0105-man-ip-token.8-Review-synopsis-section.patch @@ -0,0 +1,60 @@ +From 4ec32c42f38a0df94e138fff65eb292cc5e31b4b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:44:16 +0100 +Subject: [PATCH] man: ip-token.8: Review synopsis section + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 16a124ea2dac1 + +commit 16a124ea2dac186d4c54f3bc166a7be4882855ba +Author: Phil Sutter +Date: Wed Mar 2 19:20:03 2016 +0100 + + man: ip-token.8: Review synopsis section + + Drop unnecessary curly braces around single action keywords, point out + that 'dev' parameter to 'ip token get' is optional and clarify that 'ip + token' defaults to 'list' action. + + Signed-off-by: Phil Sutter +--- + man/man8/ip-token.8 | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/man/man8/ip-token.8 b/man/man8/ip-token.8 +index 521596f..1303bbb 100644 +--- a/man/man8/ip-token.8 ++++ b/man/man8/ip-token.8 +@@ -7,23 +7,23 @@ ip-token \- tokenized interface identifer support + .in +8 + .ti -8 + .B ip token +-.RI " { " COMMAND " | " ++.RI "{ " COMMAND " | " + .BR help " }" + .sp + + .ti -8 +-.BR "ip token" " { " set " } " ++.B ip token set + .IR TOKEN + .B dev + .IR DEV + + .ti -8 +-.BR "ip token" " { " get " } " +-.B dev +-.IR DEV ++.B ip token get ++.RB "[ " dev ++.IR DEV " ]" + + .ti -8 +-.BR "ip token" " { " list " }" ++.BR "ip token" " [ " list " ]" + + .SH "DESCRIPTION" + IPv6 tokenized interface identifer support is used for assigning well-known +-- +1.8.3.1 + diff --git a/SOURCES/0106-add-vti-vti6-tunnel-modes-to-ip-tunnel-manual-page.patch b/SOURCES/0106-add-vti-vti6-tunnel-modes-to-ip-tunnel-manual-page.patch new file mode 100644 index 0000000..1fe147b --- /dev/null +++ b/SOURCES/0106-add-vti-vti6-tunnel-modes-to-ip-tunnel-manual-page.patch @@ -0,0 +1,99 @@ +From 8db75397532ab61150a4c889337cdbacd0072d58 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:44:16 +0100 +Subject: [PATCH] add 'vti'/'vti6' tunnel modes to ip-tunnel manual page + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 6eca32ec6fa68 + +commit 6eca32ec6fa682491bece81b91fd44de3de4afc4 +Author: Konstantin Shemyak +Date: Sat Aug 29 21:36:32 2015 +0300 + + add 'vti'/'vti6' tunnel modes to ip-tunnel manual page + + * "vti" and "vti6" tunnel modes added to ip-tunnel.8 manual page + * Added "hoplimit" terminology for IPv6 + * Corrected usage line + * Minor language fix +--- + man/man8/ip-tunnel.8 | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/man/man8/ip-tunnel.8 b/man/man8/ip-tunnel.8 +index c97c28c..8b746cb 100644 +--- a/man/man8/ip-tunnel.8 ++++ b/man/man8/ip-tunnel.8 +@@ -6,14 +6,12 @@ ip-tunnel - tunnel configuration + .ad l + .in +8 + .ti -8 +-.B ip +-.RI "[ " OPTIONS " ]" +-.B tunnel +-.RI " { " COMMAND " | " +-.BR help " }" ++.B ip tunnel help + .sp + .ti -8 +-.BR "ip tunnel" " { " add " | " change " | " del " | " show " | " prl " }" ++.BR "ip " ++.RI "[ " OPTIONS " ]" ++.BR "tunnel" " { " add " | " change " | " del " | " show " | " prl " }" + .RI "[ " NAME " ]" + .br + .RB "[ " mode +@@ -29,7 +27,7 @@ ip-tunnel - tunnel configuration + .br + .RB "[ " encaplimit + .IR ELIM " ]" +-.RB "[ " ttl ++.RB "[ " ttl "|" hoplimit + .IR TTL " ]" + .br + .RB "[ " tos +@@ -50,7 +48,7 @@ ip-tunnel - tunnel configuration + + .ti -8 + .IR MODE " := " +-.RB " { " ipip " | " gre " | " sit " | " isatap " | " ip6ip6 " | " ipip6 " | " ip6gre " | " any " }" ++.RB " { " ipip " | " gre " | " sit " | " isatap " | " vti " | " ip6ip6 " | " ipip6 " | " ip6gre " | " vti6 " | " any " }" + + .ti -8 + .IR ADDR " := { " IP_ADDRESS " |" +@@ -107,10 +105,10 @@ select the tunnel device name. + set the tunnel mode. Available modes depend on the encapsulating address family. + .br + Modes for IPv4 encapsulation available: +-.BR ipip ", " sit ", " isatap " and " gre "." ++.BR ipip ", " sit ", " isatap ", " vti ", and " gre "." + .br + Modes for IPv6 encapsulation available: +-.BR ip6ip6 ", " ipip6 ", " ip6gre ", and " any "." ++.BR ip6ip6 ", " ipip6 ", " ip6gre ", " vti6 ", and " any "." + + .TP + .BI remote " ADDRESS" +@@ -123,7 +121,9 @@ It must be an address on another interface of this host. + + .TP + .BI ttl " N" +-set a fixed TTL ++.TP ++.BI hoplimit " N" ++set a fixed TTL (IPv4) or hoplimit (IPv6) + .I N + on tunneled packets. + .I N +@@ -218,7 +218,7 @@ The + .B seq + flag is equivalent to the combination + .BR "iseq oseq" . +-.B It isn't work. Don't use it. ++.B It doesn't work. Don't use it. + + .TP + .BI encaplim " ELIM" +-- +1.8.3.1 + diff --git a/SOURCES/0107-man-ip-tunnel.8-Document-missing-6rd-action.patch b/SOURCES/0107-man-ip-tunnel.8-Document-missing-6rd-action.patch new file mode 100644 index 0000000..8d129e2 --- /dev/null +++ b/SOURCES/0107-man-ip-tunnel.8-Document-missing-6rd-action.patch @@ -0,0 +1,61 @@ +From 369be35cccd7c3cfba8bd76f06b98936a0ec6ffb Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:44:25 +0100 +Subject: [PATCH] man: ip-tunnel.8: Document missing 6rd action + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 5d8cb0900e9fd + +commit 5d8cb0900e9fd927a81a91c79434cbf847463078 +Author: Phil Sutter +Date: Wed Mar 2 19:20:04 2016 +0100 + + man: ip-tunnel.8: Document missing 6rd action + + Also drop the non-terminal 'TIME' description as it is not referenced + anywhere. + + Signed-off-by: Phil Sutter +--- + man/man8/ip-tunnel.8 | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/man/man8/ip-tunnel.8 b/man/man8/ip-tunnel.8 +index 8b746cb..4938c74 100644 +--- a/man/man8/ip-tunnel.8 ++++ b/man/man8/ip-tunnel.8 +@@ -11,7 +11,7 @@ ip-tunnel - tunnel configuration + .ti -8 + .BR "ip " + .RI "[ " OPTIONS " ]" +-.BR "tunnel" " { " add " | " change " | " del " | " show " | " prl " }" ++.BR "tunnel" " { " add " | " change " | " del " | " show " | " prl " | " 6rd " }" + .RI "[ " NAME " ]" + .br + .RB "[ " mode +@@ -42,6 +42,12 @@ ip-tunnel - tunnel configuration + .B prl-delete + .IR ADDR " ]" + .br ++.RB "[ " 6rd-prefix ++.IR ADDR " ] [" ++.B 6rd-relay_prefix ++.IR ADDR " ] [ ++.BR 6rd-reset " ]" ++.br + .RB "[ [" no "]" pmtudisc " ]" + .RB "[ " dev + .IR PHYS_DEV " ]" +@@ -75,9 +81,6 @@ ip-tunnel - tunnel configuration + .ti -8 + .IR KEY " := { " DOTTED_QUAD " | " NUMBER " }" + +-.ti -8 +-.IR TIME " := " NUMBER "[s|ms]" +- + .SH DESCRIPTION + .B tunnel + objects are tunnels, encapsulating packets in IP packets and then +-- +1.8.3.1 + diff --git a/SOURCES/0108-man-ip-xfrm.8-Document-missing-parameters.patch b/SOURCES/0108-man-ip-xfrm.8-Document-missing-parameters.patch new file mode 100644 index 0000000..6bc8c34 --- /dev/null +++ b/SOURCES/0108-man-ip-xfrm.8-Document-missing-parameters.patch @@ -0,0 +1,60 @@ +From f163e1dede72014608226a718ade142634e28458 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:44:25 +0100 +Subject: [PATCH] man: ip-xfrm.8: Document missing parameters + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit a7eef7aa70b2d + +commit a7eef7aa70b2d7ea2a78841e1cc188fa416e0f7f +Author: Phil Sutter +Date: Wed Mar 2 19:20:05 2016 +0100 + + man: ip-xfrm.8: Document missing parameters + + Namely, 'extra-flag' of 'ip xfrm state' and 'flag' of 'ip xfrm policy'. + + Signed-off-by: Phil Sutter +--- + man/man8/ip-xfrm.8 | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/man/man8/ip-xfrm.8 b/man/man8/ip-xfrm.8 +index aea4fda..a9c5890 100644 +--- a/man/man8/ip-xfrm.8 ++++ b/man/man8/ip-xfrm.8 +@@ -53,6 +53,8 @@ ip-xfrm \- transform configuration + .IR ADDR "[/" PLEN "] ]" + .RB "[ " ctx + .IR CTX " ]" ++.RB "[ " extra-flag ++.IR EXTRA-FLAG-LIST " ]" + + .ti -8 + .B "ip xfrm state allocspi" +@@ -191,6 +193,13 @@ ip-xfrm \- transform configuration + .IR SPORT " " DPORT " " OADDR + + .ti -8 ++.IR EXTRA-FLAG-LIST " := [ " EXTRA-FLAG-LIST " ] " EXTRA-FLAG ++ ++.ti -8 ++.IR EXTRA-FLAG " := " ++.B dont-encap-dscp ++ ++.ti -8 + .BR "ip xfrm policy" " { " add " | " update " }" + .I SELECTOR + .B dir +@@ -242,6 +251,8 @@ ip-xfrm \- transform configuration + .IR ACTION " ]" + .RB "[ " priority + .IR PRIORITY " ]" ++.RB "[ " flag ++.IR FLAG-LIST "]" + + .ti -8 + .B "ip xfrm policy flush" +-- +1.8.3.1 + diff --git a/SOURCES/0109-man-ip-add-h-uman-readable-option.patch b/SOURCES/0109-man-ip-add-h-uman-readable-option.patch new file mode 100644 index 0000000..2706dc2 --- /dev/null +++ b/SOURCES/0109-man-ip-add-h-uman-readable-option.patch @@ -0,0 +1,47 @@ +From af27a9b48061501e033de4f28b66f3dadcbddfd7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:44:25 +0100 +Subject: [PATCH] man: ip: add -h[uman-readable] option + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 9b2e9f4a8c4bf + +commit 9b2e9f4a8c4bf802b20a37ddb4d07f04c2e8e770 +Author: Phil Sutter +Date: Fri Sep 18 20:17:01 2015 +0200 + + man: ip: add -h[uman-readable] option + + Since 'ip help' lists it, it should be described in ip.8 as well. + + Signed-off-by: Phil Sutter +--- + man/man8/ip.8 | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/man/man8/ip.8 b/man/man8/ip.8 +index b772c4c..0b30d4a 100644 +--- a/man/man8/ip.8 ++++ b/man/man8/ip.8 +@@ -27,6 +27,7 @@ ip \- show / manipulate routing, devices, policy routing and tunnels + .ti -8 + .IR OPTIONS " := { " + \fB\-V\fR[\fIersion\fR] | ++\fB\-h\fR[\fIuman-readable\fR] | + \fB\-s\fR[\fItatistics\fR] | + \fB\-r\fR[\fIesolve\fR] | + \fB\-f\fR[\fIamily\fR] { +@@ -45,6 +46,10 @@ Print the version of the + utility and exit. + + .TP ++.BR "\-h", " \-human", " \-human-readable" ++output statistics with human readable values followed by suffix. ++ ++.TP + .BR "\-b", " \-batch " + Read commands from provided file or standard input and invoke them. + First failure will cause termination of ip. +-- +1.8.3.1 + diff --git a/SOURCES/0110-man-ip.8-Add-missing-flags-and-token-subcommand-desc.patch b/SOURCES/0110-man-ip.8-Add-missing-flags-and-token-subcommand-desc.patch new file mode 100644 index 0000000..4539a9d --- /dev/null +++ b/SOURCES/0110-man-ip.8-Add-missing-flags-and-token-subcommand-desc.patch @@ -0,0 +1,99 @@ +From 06a16be3a229f7c37d9fd03d2e6108bf39840fcc Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:44:25 +0100 +Subject: [PATCH] man: ip.8: Add missing flags and token subcommand description + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit ac0eff58fd826 +Conflicts: Missing color output support. + +commit ac0eff58fd826683107e47c9df085b4b4e92ec66 +Author: Phil Sutter +Date: Wed Mar 2 19:20:06 2016 +0100 + + man: ip.8: Add missing flags and token subcommand description + + Signed-off-by: Phil Sutter +--- + man/man8/ip.8 | 33 ++++++++++++++++++++++++++++++++- + 1 file changed, 32 insertions(+), 1 deletion(-) + +diff --git a/man/man8/ip.8 b/man/man8/ip.8 +index 0b30d4a..c28cee0 100644 +--- a/man/man8/ip.8 ++++ b/man/man8/ip.8 +@@ -21,7 +21,7 @@ ip \- show / manipulate routing, devices, policy routing and tunnels + .IR OBJECT " := { " + .BR link " | " address " | " addrlabel " | " route " | " rule " | " neigh " | "\ + ntable " | " tunnel " | " tuntap " | " maddress " | " mroute " | " mrule " | "\ +- monitor " | " xfrm " | " netns " | " l2tp " | " tcp_metrics " }" ++ monitor " | " xfrm " | " netns " | " l2tp " | " tcp_metrics " | " token " }" + .sp + + .ti -8 +@@ -29,10 +29,22 @@ ip \- show / manipulate routing, devices, policy routing and tunnels + \fB\-V\fR[\fIersion\fR] | + \fB\-h\fR[\fIuman-readable\fR] | + \fB\-s\fR[\fItatistics\fR] | ++\fB\-d\fR[\fIetails\fR] | + \fB\-r\fR[\fIesolve\fR] | ++\fB\-iec\fR | + \fB\-f\fR[\fIamily\fR] { + .BR inet " | " inet6 " | " ipx " | " dnet " | " link " } | " ++\fB-4\fR | ++\fB-6\fR | ++\fB-I\fR | ++\fB-D\fR | ++\fB-B\fR | ++\fB-0\fR | ++\fB-l\fR[\fIoops\fR] { \fBmaximum-addr-flush-attempts\fR } | + \fB\-o\fR[\fIneline\fR] | ++\fB\-rc\fR[\fIvbuf\fR] [\fBsize\fR] | ++\fB\-t\fR[\fIimestamp\fR] | ++\fB\-ts\fR[\fIhort\fR] | + \fB\-n\fR[\fIetns\fR] name | + \fB\-a\fR[\fIll\fR] } + +@@ -165,6 +177,20 @@ to + .BR "\-a" , " \-all" + executes specified command over all objects, it depends if command supports this option. + ++.TP ++.BR "\-t" , " \-timestamp" ++display current time when using monitor option. ++ ++.TP ++.BR "\-ts" , " \-tshort" ++Like ++.BR \-timestamp , ++but use shorter format. ++ ++.TP ++.BR "\-rc" , " \-rcvbuf" ++Set the netlink socket receive buffer size, defaults to 1MB. ++ + .SH IP - COMMAND SYNTAX + + .SS +@@ -227,6 +253,10 @@ executes specified command over all objects, it depends if command supports this + - manage TCP Metrics + + .TP ++.B token ++- manage tokenized interface identifiers. ++ ++.TP + .B tunnel + - tunnel over IP. + +@@ -287,6 +317,7 @@ was written by Alexey N. Kuznetsov and added in Linux 2.2. + .BR ip-route (8), + .BR ip-rule (8), + .BR ip-tcp_metrics (8), ++.BR ip-token (8), + .BR ip-tunnel (8), + .BR ip-xfrm (8) + .br +-- +1.8.3.1 + diff --git a/SOURCES/0111-man-ip-l2tp.8-Fix-BNF-syntax.patch b/SOURCES/0111-man-ip-l2tp.8-Fix-BNF-syntax.patch new file mode 100644 index 0000000..4025b41 --- /dev/null +++ b/SOURCES/0111-man-ip-l2tp.8-Fix-BNF-syntax.patch @@ -0,0 +1,75 @@ +From 0fc679a36a881de486a86d16b847c8ded58ca765 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:44:42 +0100 +Subject: [PATCH] man: ip-l2tp.8: Fix BNF syntax + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 2227f2a5a28fa + +commit 2227f2a5a28fa0fc3cc4257ccc9528cdc81996ac +Author: Phil Sutter +Date: Wed Mar 2 19:20:07 2016 +0100 + + man: ip-l2tp.8: Fix BNF syntax + + The 'ADDR' part of 'local' and 'remote' parameters is not optional, but + may also consist of the word 'any'. While at it, add missing whitespace + and fix fonts. + + Signed-off-by: Phil Sutter +--- + man/man8/ip-l2tp.8 | 24 +++++++++--------------- + 1 file changed, 9 insertions(+), 15 deletions(-) + +diff --git a/man/man8/ip-l2tp.8 b/man/man8/ip-l2tp.8 +index 2efda9f..9bc9116 100644 +--- a/man/man8/ip-l2tp.8 ++++ b/man/man8/ip-l2tp.8 +@@ -15,10 +15,7 @@ ip-l2tp - L2TPv3 static unmanaged tunnel configuration + .ti -8 + .BR "ip l2tp add tunnel" + .br +-.B remote +-.RI "[ " ADDR " ]" +-.B local +-.RI "[ " ADDR " ]" ++.BI remote " ADDR " local " ADDR " + .br + .B tunnel_id + .IR ID +@@ -73,24 +70,21 @@ ip-l2tp - L2TPv3 static unmanaged tunnel configuration + .IR ID + .br + .ti -8 +-.BR "ip l2tp show tunnel" +-.B "[" tunnel_id +-.IR ID +-.B "]" ++.BR "ip l2tp show tunnel" " [ " tunnel_id ++.IR ID " ]" + .br + .ti -8 +-.BR "ip l2tp show session" +-.B "[" tunnel_id +-.IR ID +-.B "] [" session_id +-.IR ID +-.B "]" ++.BR "ip l2tp show session" " [ " tunnel_id ++.IR ID .B " ] [" ++.B session_id ++.IR ID " ]" + .br + .ti -8 + .IR NAME " := " + .IR STRING + .ti -8 +-.IR ADDR " := { " IP_ADDRESS " }" ++.IR ADDR " := { " IP_ADDRESS " |" ++.BR any " }" + .ti -8 + .IR PORT " := { " NUMBER " }" + .ti -8 +-- +1.8.3.1 + diff --git a/SOURCES/0112-fix-spelling-of-Kuznetsov.patch b/SOURCES/0112-fix-spelling-of-Kuznetsov.patch new file mode 100644 index 0000000..1322e04 --- /dev/null +++ b/SOURCES/0112-fix-spelling-of-Kuznetsov.patch @@ -0,0 +1,63 @@ +From 0fe5b27ea6bfc6b17404940a5730fe5107c72d74 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 7 Mar 2016 20:44:43 +0100 +Subject: [PATCH] fix spelling of Kuznetsov + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit dd8fac8cee409 + +commit dd8fac8cee4093f766eb0e53a00bafb156ec71db +Author: Stephen Hemminger +Date: Sat Jan 3 09:58:41 2015 -0800 + + fix spelling of Kuznetsov + + Suggested by Vadim Kochan +--- + doc/nstat.sgml | 2 +- + doc/ss.sgml | 2 +- + man/man8/ss.8 | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/doc/nstat.sgml b/doc/nstat.sgml +index be9d8bc..48cacc6 100644 +--- a/doc/nstat.sgml ++++ b/doc/nstat.sgml +@@ -3,7 +3,7 @@ +
+ + NSTAT, IFSTAT and RTACCT Utilities +-<author>Alexey Kuznetosv, <tt/kuznet@ms2.inr.ac.ru/ ++<author>Alexey Kuznetsov, <tt/kuznet@ms2.inr.ac.ru/ + <date>some_negative_number, 20 Sep 2001 + <abstract> + <tt/nstat/, <tt/ifstat/ and <tt/rtacct/ are simple tools helping +diff --git a/doc/ss.sgml b/doc/ss.sgml +index 0b1b533..3024b57 100644 +--- a/doc/ss.sgml ++++ b/doc/ss.sgml +@@ -3,7 +3,7 @@ + <article> + + <title>SS Utility: Quick Intro +-<author>Alexey Kuznetosv, <tt/kuznet@ms2.inr.ac.ru/ ++<author>Alexey Kuznetsov, <tt/kuznet@ms2.inr.ac.ru/ + <date>some_negative_number, 20 Sep 2001 + <abstract> + <tt/ss/ is one another utility to investigate sockets. +diff --git a/man/man8/ss.8 b/man/man8/ss.8 +index 62c6ad8..6afbabb 100644 +--- a/man/man8/ss.8 ++++ b/man/man8/ss.8 +@@ -193,7 +193,7 @@ List all the tcp sockets in state FIN-WAIT-1 for our apache to network 193.233.7 + + .SH AUTHOR + .I ss +-was written by Alexey Kuznetosv, <kuznet@ms2.inr.ac.ru>. ++was written by Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>. + .PP + This manual page was written by Michael Prokop <mika@grml.org> + for the Debian project (but may be used by others). +-- +1.8.3.1 + diff --git a/SOURCES/0113-man-Spelling-fixes.patch b/SOURCES/0113-man-Spelling-fixes.patch new file mode 100644 index 0000000..d5a7c20 --- /dev/null +++ b/SOURCES/0113-man-Spelling-fixes.patch @@ -0,0 +1,82 @@ +From b05a7002c77459b8f4b20966404f36b2a52a0307 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Mon, 7 Mar 2016 20:44:54 +0100 +Subject: [PATCH] man: Spelling fixes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit ac0817ef6612a +Conflicts: + * Missing man pages in RHEL7 (tc-bpf.8 and tc-mqprio.8). + * Missing support for -conf option in tc. + +commit ac0817ef6612a0ffb7d2b99891d6f7db48d33a72 +Author: Ville Skyttä <ville.skytta@iki.fi> +Date: Sat Nov 7 11:53:00 2015 +0200 + + man: Spelling fixes + + Signed-off-by: Ville Skyttä <ville.skytta@iki.fi> +--- + man/man8/bridge.8 | 2 +- + man/man8/ifcfg.8 | 2 +- + man/man8/lnstat.8 | 2 +- + man/man8/tc-cbq-details.8 | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 +index 2c9f90c..4fcf2e8 100644 +--- a/man/man8/bridge.8 ++++ b/man/man8/bridge.8 +@@ -220,7 +220,7 @@ state the port for list for STP BPDUs and drop all other traffic. + .B 2 + - STP LEARNING state. Only valid if STP is enabled on the bridge. In this + state the port will accept traffic only for the purpose of updating MAC +-adress tables. ++address tables. + .sp + + .B 3 +diff --git a/man/man8/ifcfg.8 b/man/man8/ifcfg.8 +index 79033bd..1a3786c 100644 +--- a/man/man8/ifcfg.8 ++++ b/man/man8/ifcfg.8 +@@ -1,6 +1,6 @@ + .TH IFCFG 8 "September 24 2009" "iproute2" "Linux" + .SH NAME +-ifcfg \- simplistic script which replaces ifconfig IP managment ++ifcfg \- simplistic script which replaces ifconfig IP management + .SH SYNOPSIS + .ad l + .in +8 +diff --git a/man/man8/lnstat.8 b/man/man8/lnstat.8 +index b817bcf..d509649 100644 +--- a/man/man8/lnstat.8 ++++ b/man/man8/lnstat.8 +@@ -169,7 +169,7 @@ Number of dropped conntrack entries to make room for new ones, if maximum table + size was reached. + .sp + .B icmp_error +-Number of packets wich could not be tracked due to error situation. This is a ++Number of packets which could not be tracked due to error situation. This is a + subset of \fBinvalid\fP. + .sp + .B expect_new +diff --git a/man/man8/tc-cbq-details.8 b/man/man8/tc-cbq-details.8 +index ddaf3ca..86353b5 100644 +--- a/man/man8/tc-cbq-details.8 ++++ b/man/man8/tc-cbq-details.8 +@@ -197,7 +197,7 @@ priority yielded a class, enter the fallback algorithm. + The fallback algorithm resides outside of the loop and is as follows. + .TP + (i) +-Consult the defmap of the class at which the jump to fallback occured. If ++Consult the defmap of the class at which the jump to fallback occurred. If + the defmap contains a class for the + .B + priority +-- +1.8.3.1 + diff --git a/SOURCES/0114-man-tc-htb-Fix-HRB-HTB-typo.patch b/SOURCES/0114-man-tc-htb-Fix-HRB-HTB-typo.patch new file mode 100644 index 0000000..4806e5e --- /dev/null +++ b/SOURCES/0114-man-tc-htb-Fix-HRB-HTB-typo.patch @@ -0,0 +1,37 @@ +From 7ebb76a1066a17bb7dcd06c685e9751032c47d9a Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Mon, 7 Mar 2016 20:45:51 +0100 +Subject: [PATCH] man tc-htb: Fix HRB -> HTB typo + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 6c19ff10b5bdf + +commit 6c19ff10b5bdf2f2f20e340d2cba4115da4eb7ef +Author: Vadim Kochan <vadim4j@gmail.com> +Date: Tue Sep 22 20:01:13 2015 +0300 + + man tc-htb: Fix HRB -> HTB typo + + Changed HRB -> HTB. + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> +--- + man/man8/tc-htb.8 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/man8/tc-htb.8 b/man/man8/tc-htb.8 +index d196ecd..95f25de 100644 +--- a/man/man8/tc-htb.8 ++++ b/man/man8/tc-htb.8 +@@ -48,7 +48,7 @@ Shaping works as documented in + .B tc-tbf (8). + + .SH CLASSIFICATION +-Within the one HRB instance many classes may exist. Each of these classes ++Within the one HTB instance many classes may exist. Each of these classes + contains another qdisc, by default + .BR tc-pfifo (8). + +-- +1.8.3.1 + diff --git a/SOURCES/0115-TBF-man-page-fix-tbf-is-not-classless.patch b/SOURCES/0115-TBF-man-page-fix-tbf-is-not-classless.patch new file mode 100644 index 0000000..799d1e4 --- /dev/null +++ b/SOURCES/0115-TBF-man-page-fix-tbf-is-not-classless.patch @@ -0,0 +1,57 @@ +From 9d1e99695d9c39432a66ec20f36928bf053410a4 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Mon, 7 Mar 2016 20:45:51 +0100 +Subject: [PATCH] TBF man page fix (tbf is not classless) + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 7bc7fcaadbd2d + +commit 7bc7fcaadbd2db1aef1f9b15216a97f63d826493 +Author: Sergey V. Lobanov <sergey@lobanov.in> +Date: Fri May 9 22:12:54 2014 +0400 + + TBF man page fix (tbf is not classless) + + TBF is not classless qdisc. man page corrected, added example + describing the use of inner qdisc + + Signed-off-by: Sergey V. Lobanov <sergey@lobanov.in> +--- + man/man8/tc-tbf.8 | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/man/man8/tc-tbf.8 b/man/man8/tc-tbf.8 +index 51310f1..fc2c837 100644 +--- a/man/man8/tc-tbf.8 ++++ b/man/man8/tc-tbf.8 +@@ -21,7 +21,7 @@ bytes/cell + burst is also known as buffer and maxburst. mtu is also known as minburst. + .SH DESCRIPTION + +-The Token Bucket Filter is a classless queueing discipline available for ++The Token Bucket Filter is a classful queueing discipline available for + traffic control with the + .BR tc (8) + command. +@@ -121,9 +121,17 @@ To attach a TBF with a sustained maximum rate of 0.5mbit/s, a peakrate of 1.0mbi + a 5kilobyte buffer, with a pre-bucket queue size limit calculated so the TBF causes + at most 70ms of latency, with perfect peakrate behaviour, issue: + .P +-# tc qdisc add dev eth0 root tbf rate 0.5mbit \\ ++# tc qdisc add dev eth0 handle 10: root tbf rate 0.5mbit \\ + burst 5kb latency 70ms peakrate 1mbit \\ + minburst 1540 ++.P ++To attach an inner qdisc, for example sfq, issue: ++.P ++# tc qdisc add dev eth0 parent 10:1 handle 100: sfq ++.P ++Without inner qdisc TBF queue acts as bfifo. If the inner qdisc is changed ++the limit/latency is not effective anymore. ++.P + + .SH SEE ALSO + .BR tc (8) +-- +1.8.3.1 + diff --git a/SOURCES/0116-man8-scrub-trailing-whitespace.patch b/SOURCES/0116-man8-scrub-trailing-whitespace.patch new file mode 100644 index 0000000..d11b7c6 --- /dev/null +++ b/SOURCES/0116-man8-scrub-trailing-whitespace.patch @@ -0,0 +1,2022 @@ +From ec65031c65c10110cbbefbeb222984813782ebb3 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Mon, 7 Mar 2016 20:45:51 +0100 +Subject: [PATCH] man8: scrub trailing whitespace + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 5699275b424c6 + +commit 5699275b424c637edc60f46c89071d4e8f4edde3 +Author: Stephen Hemminger <shemming@brocade.com> +Date: Mon Nov 23 15:41:37 2015 -0800 + + man8: scrub trailing whitespace + + Remove extraneous whitespace +--- + man/man8/bridge.8 | 6 +- + man/man8/ip-addrlabel.8 | 5 +- + man/man8/ip-neighbour.8 | 4 +- + man/man8/ip-ntable.8 | 4 +- + man/man8/ip-rule.8 | 2 +- + man/man8/ip-xfrm.8 | 2 +- + man/man8/ip.8 | 2 +- + man/man8/routel.8 | 20 +++--- + man/man8/rtacct.8 | 1 - + man/man8/rtmon.8 | 8 +-- + man/man8/ss.8 | 6 +- + man/man8/tc-bfifo.8 | 32 ++++----- + man/man8/tc-cbq-details.8 | 178 +++++++++++++++++++++++----------------------- + man/man8/tc-cbq.8 | 158 ++++++++++++++++++++-------------------- + man/man8/tc-drr.8 | 1 - + man/man8/tc-htb.8 | 80 ++++++++++----------- + man/man8/tc-netem.8 | 22 +++--- + man/man8/tc-pfifo_fast.8 | 14 ++-- + man/man8/tc-prio.8 | 28 ++++---- + man/man8/tc-red.8 | 62 ++++++++-------- + man/man8/tc-sfq.8 | 40 +++++------ + man/man8/tc-tbf.8 | 48 ++++++------- + man/man8/tc.8 | 1 - + 23 files changed, 351 insertions(+), 373 deletions(-) + +diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 +index 4fcf2e8..3cda7d6 100644 +--- a/man/man8/bridge.8 ++++ b/man/man8/bridge.8 +@@ -84,7 +84,7 @@ bridge \- show / manipulate bridge addresses and devices + .BR "bridge vlan" " { " add " | " del " } " + .B dev + .IR DEV +-.B vid ++.B vid + .IR VID " [ " + .BR pvid " ] [ " untagged " ] [ " + .BR self " ] [ " master " ] " +@@ -142,7 +142,7 @@ to + - Bridge port. + + .TP +-.B fdb ++.B fdb + - Forwarding Database entry. + + .TP +@@ -340,7 +340,7 @@ If omitted the default value is used. + .BI via " DEVICE" + device name of the outgoing interface for the + VXLAN device driver to reach the +-remote VXLAN tunnel endpoint. ++remote VXLAN tunnel endpoint. + + .SS bridge fdb append - append a forwarding database entry + This command adds a new fdb entry with an already known +diff --git a/man/man8/ip-addrlabel.8 b/man/man8/ip-addrlabel.8 +index 5fc18fe..51ef572 100644 +--- a/man/man8/ip-addrlabel.8 ++++ b/man/man8/ip-addrlabel.8 +@@ -7,8 +7,8 @@ ip-addrlabel \- protocol address label management + .in +8 + .ti -8 + .B ip +-.RI "[ " OPTIONS " ]" +-.B addrlabel ++.RI "[ " OPTIONS " ]" ++.B addrlabel + .RI " { " COMMAND " | " + .BR help " }" + .sp +@@ -66,4 +66,3 @@ flush all address labels in the kernel. This does not restore any default settin + + .SH AUTHOR + Manpage by Yoshifuji Hideaki / 吉藤英明 +- +diff --git a/man/man8/ip-neighbour.8 b/man/man8/ip-neighbour.8 +index f3068f4..c94c654 100644 +--- a/man/man8/ip-neighbour.8 ++++ b/man/man8/ip-neighbour.8 +@@ -38,9 +38,9 @@ ip-neighbour \- neighbour/arp tables management. + .BR permanent " | " noarp " | " stale " | " reachable " }" + + .SH DESCRIPTION +-The ++The + .B ip neigh +-command manipulates ++command manipulates + .I neighbour + objects that establish bindings between protocol addresses and + link layer addresses for hosts sharing the same link. +diff --git a/man/man8/ip-ntable.8 b/man/man8/ip-ntable.8 +index 2b95632..4f0f2e5 100644 +--- a/man/man8/ip-ntable.8 ++++ b/man/man8/ip-ntable.8 +@@ -60,7 +60,7 @@ ip-ntable - neighbour table configuration + + .SH DESCRIPTION + .I ip ntable +-controls the parameters for the neighbour tables. ++controls the parameters for the neighbour tables. + + .SS ip ntable show - list the ip neighbour tables + +@@ -103,4 +103,4 @@ default value (3) to 8 packets. + .BR ip (8) + + .SH AUTHOR +-Manpage by Stephen Hemminger ++Manpage by Stephen Hemminger +diff --git a/man/man8/ip-rule.8 b/man/man8/ip-rule.8 +index 2594ff3..0661061 100644 +--- a/man/man8/ip-rule.8 ++++ b/man/man8/ip-rule.8 +@@ -62,7 +62,7 @@ ip-rule \- routing policy database management + + .SH DESCRIPTION + .I ip rule +-manipulates rules ++manipulates rules + in the routing policy database control the route selection algorithm. + + .P +diff --git a/man/man8/ip-xfrm.8 b/man/man8/ip-xfrm.8 +index a9c5890..aa04804 100644 +--- a/man/man8/ip-xfrm.8 ++++ b/man/man8/ip-xfrm.8 +@@ -119,7 +119,7 @@ ip-xfrm \- transform configuration + + .ti -8 + .IR ALGO " :=" +-.RB "{ " enc " | " auth " } " ++.RB "{ " enc " | " auth " } " + .IR ALGO-NAME " " ALGO-KEYMAT " |" + .br + .B auth-trunc +diff --git a/man/man8/ip.8 b/man/man8/ip.8 +index c28cee0..a95264d 100644 +--- a/man/man8/ip.8 ++++ b/man/man8/ip.8 +@@ -12,7 +12,7 @@ ip \- show / manipulate routing, devices, policy routing and tunnels + .sp + + .ti -8 +-.B ip ++.B ip + .RB "[ " -force " ] " + .BI "-batch " filename + .sp +diff --git a/man/man8/routel.8 b/man/man8/routel.8 +index cdf8f55..82d580f 100644 +--- a/man/man8/routel.8 ++++ b/man/man8/routel.8 +@@ -1,16 +1,16 @@ + .TH "ROUTEL" "8" "3 Jan, 2008" "iproute2" "Linux" + .SH "NAME" +-.LP ++.LP + routel \- list routes with pretty output format + .br + routef \- flush routes + .SH "SYNTAX" +-.LP ++.LP + routel [\fItablenr\fP [\fIraw ip args...\fP]] +-.br ++.br + routef + .SH "DESCRIPTION" +-.LP ++.LP + These programs are a set of helper scripts you can use instead of raw iproute2 commands. + .br + The routel script will list routes in a format that some might consider easier to interpret then the ip route list equivalent. +@@ -18,15 +18,15 @@ The routel script will list routes in a format that some might consider easier t + The routef script does not take any arguments and will simply flush the routing table down the drain. Beware! This means deleting all routes which will make your network unusable! + + .SH "FILES" +-.LP +-\fI/usr/bin/routef\fP +-.br +-\fI/usr/bin/routel\fP ++.LP ++\fI/usr/bin/routef\fP ++.br ++\fI/usr/bin/routel\fP + .SH "AUTHORS" +-.LP ++.LP + The routel script was written by Stephen R. van den Berg <srb@cuci.nl>, 1999/04/18 and donated to the public domain. + .br + This manual page was written by Andreas Henriksson <andreas@fatal.se>, for the Debian GNU/Linux system. + .SH "SEE ALSO" +-.LP ++.LP + ip(8) +diff --git a/man/man8/rtacct.8 b/man/man8/rtacct.8 +index fb9afe8..b10839f 100644 +--- a/man/man8/rtacct.8 ++++ b/man/man8/rtacct.8 +@@ -45,4 +45,3 @@ Time interval to average rates. Default value is 60 seconds. + + .SH SEE ALSO + lnstat(8) +- +diff --git a/man/man8/rtmon.8 b/man/man8/rtmon.8 +index 0538752..38a2b77 100644 +--- a/man/man8/rtmon.8 ++++ b/man/man8/rtmon.8 +@@ -10,11 +10,11 @@ This manual page documents briefly the + command. + .PP + .B rtmon +-listens on +-.I netlink ++listens on ++.I netlink + socket and monitors routing table changes. + +-.I rtmon ++.I rtmon + can be started before the first network configuration command is issued. + For example if you insert: + +@@ -61,7 +61,7 @@ to display logged output from file. + .SH SEE ALSO + .BR ip (8) + .SH AUTHOR +-.B rtmon ++.B rtmon + was written by Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>. + .PP + This manual page was written by Michael Prokop <mika@grml.org>, +diff --git a/man/man8/ss.8 b/man/man8/ss.8 +index 6afbabb..f4d5264 100644 +--- a/man/man8/ss.8 ++++ b/man/man8/ss.8 +@@ -12,7 +12,7 @@ to + It can display more TCP and state informations than other tools. + + .SH OPTIONS +-When no option is used ss displays a list of ++When no option is used ss displays a list of + open non-listening sockets (e.g. TCP/UNIX/UDP) that have established connection. + .TP + .B \-h, \-\-help +@@ -189,10 +189,10 @@ List all the tcp sockets in state FIN-WAIT-1 for our apache to network 193.233.7 + .BR /usr/share/doc/iproute-doc/ss.html " (package iproute�doc)", + .br + .BR RFC " 793 " +-- https://tools.ietf.org/rfc/rfc793.txt (TCP states) ++- https://tools.ietf.org/rfc/rfc793.txt (TCP states) + + .SH AUTHOR +-.I ss ++.I ss + was written by Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>. + .PP + This manual page was written by Michael Prokop <mika@grml.org> +diff --git a/man/man8/tc-bfifo.8 b/man/man8/tc-bfifo.8 +index f04090c..3e29032 100644 +--- a/man/man8/tc-bfifo.8 ++++ b/man/man8/tc-bfifo.8 +@@ -6,37 +6,37 @@ bfifo \- Byte limited First In, First Out queue + + .SH SYNOPSIS + .B tc qdisc ... add pfifo +-.B [ limit ++.B [ limit + packets + .B ] + .P + .B tc qdisc ... add bfifo +-.B [ limit ++.B [ limit + bytes + .B ] + + .SH DESCRIPTION + The pfifo and bfifo qdiscs are unadorned First In, First Out queues. They are the +-simplest queues possible and therefore have no overhead. ++simplest queues possible and therefore have no overhead. + .B pfifo +-constrains the queue size as measured in packets. ++constrains the queue size as measured in packets. + .B bfifo + does so as measured in bytes. + +-Like all non-default qdiscs, they maintain statistics. This might be a reason to prefer ++Like all non-default qdiscs, they maintain statistics. This might be a reason to prefer + pfifo or bfifo over the default. + + .SH ALGORITHM + A list of packets is maintained, when a packet is enqueued it gets inserted at the tail of +-a list. When a packet needs to be sent out to the network, it is taken from the head of the list. ++a list. When a packet needs to be sent out to the network, it is taken from the head of the list. + + If the list is too long, no further packets are allowed on. This is called 'tail drop'. + + .SH PARAMETERS +-.TP ++.TP + limit +-Maximum queue size. Specified in bytes for bfifo, in packets for pfifo. For pfifo, defaults +-to the interface txqueuelen, as specified with ++Maximum queue size. Specified in bytes for bfifo, in packets for pfifo. For pfifo, defaults ++to the interface txqueuelen, as specified with + .BR ifconfig (8) + or + .BR ip (8). +@@ -48,20 +48,20 @@ The range for this parameter is [0, UINT32_MAX] bytes. + Note: The link layer header was considered when counting packets length. + + .SH OUTPUT +-The output of ++The output of + .B tc -s qdisc ls +-contains the limit, either in packets or in bytes, and the number of bytes +-and packets actually sent. An unsent and dropped packet only appears between braces ++contains the limit, either in packets or in bytes, and the number of bytes ++and packets actually sent. An unsent and dropped packet only appears between braces + and is not counted as 'Sent'. + +-In this example, the queue length is 100 packets, 45894 bytes were sent over 681 packets. ++In this example, the queue length is 100 packets, 45894 bytes were sent over 681 packets. + No packets were dropped, and as the pfifo queue does not slow down packets, there were also no + overlimits: + .P + .nf +-# tc -s qdisc ls dev eth0 ++# tc -s qdisc ls dev eth0 + qdisc pfifo 8001: dev eth0 limit 100p +- Sent 45894 bytes 681 pkts (dropped 0, overlimits 0) ++ Sent 45894 bytes 681 pkts (dropped 0, overlimits 0) + .fi + + If a backlog occurs, this is displayed as well. +@@ -72,5 +72,3 @@ If a backlog occurs, this is displayed as well. + Alexey N. Kuznetsov, <kuznet@ms2.inr.ac.ru> + + This manpage maintained by bert hubert <ahu@ds9a.nl> +- +- +diff --git a/man/man8/tc-cbq-details.8 b/man/man8/tc-cbq-details.8 +index 86353b5..9368103 100644 +--- a/man/man8/tc-cbq-details.8 ++++ b/man/man8/tc-cbq-details.8 +@@ -5,54 +5,54 @@ CBQ \- Class Based Queueing + .B tc qdisc ... dev + dev + .B ( parent +-classid +-.B | root) [ handle +-major: ++classid ++.B | root) [ handle ++major: + .B ] cbq avpkt + bytes + .B bandwidth + rate +-.B [ cell ++.B [ cell + bytes + .B ] [ ewma + log + .B ] [ mpu + bytes +-.B ] ++.B ] + + .B tc class ... dev + dev +-.B parent ++.B parent + major:[minor] +-.B [ classid ++.B [ classid + major:minor + .B ] cbq allot + bytes +-.B [ bandwidth +-rate +-.B ] [ rate ++.B [ bandwidth ++rate ++.B ] [ rate + rate + .B ] prio + priority + .B [ weight + weight +-.B ] [ minburst ++.B ] [ minburst ++packets ++.B ] [ maxburst + packets +-.B ] [ maxburst +-packets +-.B ] [ ewma ++.B ] [ ewma + log + .B ] [ cell + bytes + .B ] avpkt + bytes + .B [ mpu +-bytes ++bytes + .B ] [ bounded isolated ] [ split + handle + .B & defmap + defmap +-.B ] [ estimator ++.B ] [ estimator + interval timeconstant + .B ] + +@@ -60,7 +60,7 @@ interval timeconstant + Class Based Queueing is a classful qdisc that implements a rich + linksharing hierarchy of classes. It contains shaping elements as + well as prioritizing capabilities. Shaping is performed using link +-idle time calculations based on the timing of dequeue events and ++idle time calculations based on the timing of dequeue events and + underlying link bandwidth. + + .SH SHAPING ALGORITHM +@@ -71,10 +71,10 @@ When shaping a 10mbit/s connection to 1mbit/s, the link will + be idle 90% of the time. If it isn't, it needs to be throttled so that it + IS idle 90% of the time. + +-From the kernel's perspective, this is hard to measure, so CBQ instead +-derives the idle time from the number of microseconds (in fact, jiffies) +-that elapse between requests from the device driver for more data. Combined +-with the knowledge of packet sizes, this is used to approximate how full or ++From the kernel's perspective, this is hard to measure, so CBQ instead ++derives the idle time from the number of microseconds (in fact, jiffies) ++that elapse between requests from the device driver for more data. Combined ++with the knowledge of packet sizes, this is used to approximate how full or + empty the link is. + + This is rather circumspect and doesn't always arrive at proper +@@ -84,9 +84,9 @@ perhaps because of a badly implemented driver? A PCMCIA network card + will also never achieve 100mbit/s because of the way the bus is + designed - again, how do we calculate the idle time? + +-The physical link bandwidth may be ill defined in case of not-quite-real +-network devices like PPP over Ethernet or PPTP over TCP/IP. The effective +-bandwidth in that case is probably determined by the efficiency of pipes ++The physical link bandwidth may be ill defined in case of not-quite-real ++network devices like PPP over Ethernet or PPTP over TCP/IP. The effective ++bandwidth in that case is probably determined by the efficiency of pipes + to userspace - which not defined. + + During operations, the effective idletime is measured using an +@@ -104,59 +104,59 @@ CBQ throttles and is then 'overlimit'. + + Conversely, an idle link might amass a huge avgidle, which would then + allow infinite bandwidths after a few hours of silence. To prevent +-this, avgidle is capped at ++this, avgidle is capped at + .B maxidle. + + If overlimit, in theory, the CBQ could throttle itself for exactly the + amount of time that was calculated to pass between packets, and then + pass one packet, and throttle again. Due to timer resolution constraints, +-this may not be feasible, see the ++this may not be feasible, see the + .B minburst + parameter below. + + .SH CLASSIFICATION + Within the one CBQ instance many classes may exist. Each of these classes +-contains another qdisc, by default ++contains another qdisc, by default + .BR tc-pfifo (8). + +-When enqueueing a packet, CBQ starts at the root and uses various methods to ++When enqueueing a packet, CBQ starts at the root and uses various methods to + determine which class should receive the data. If a verdict is reached, this + process is repeated for the recipient class which might have further + means of classifying traffic to its children, if any. + +-CBQ has the following methods available to classify a packet to any child ++CBQ has the following methods available to classify a packet to any child + classes. + .TP + (i) + .B skb->priority class encoding. +-Can be set from userspace by an application with the ++Can be set from userspace by an application with the + .B SO_PRIORITY + setsockopt. +-The ++The + .B skb->priority class encoding +-only applies if the skb->priority holds a major:minor handle of an existing ++only applies if the skb->priority holds a major:minor handle of an existing + class within this qdisc. + .TP + (ii) + tc filters attached to the class. + .TP + (iii) +-The defmap of a class, as set with the ++The defmap of a class, as set with the + .B split & defmap + parameters. The defmap may contain instructions for each possible Linux packet + priority. + + .P +-Each class also has a ++Each class also has a + .B level. + Leaf nodes, attached to the bottom of the class hierarchy, have a level of 0. + .SH CLASSIFICATION ALGORITHM + +-Classification is a loop, which terminates when a leaf class is found. At any ++Classification is a loop, which terminates when a leaf class is found. At any + point the loop may jump to the fallback algorithm. + + The loop consists of the following steps: +-.TP ++.TP + (i) + If the packet is generated locally and has a valid classid encoded within its + .B skb->priority, +@@ -169,40 +169,40 @@ a class which is not a leaf class, restart loop from the class returned. + If it is a leaf, choose it and terminate. + .TP + (iii) +-If the tc filters did not return a class, but did return a classid, +-try to find a class with that id within this qdisc. ++If the tc filters did not return a class, but did return a classid, ++try to find a class with that id within this qdisc. + Check if the found class is of a lower + .B level + than the current class. If so, and the returned class is not a leaf node, + restart the loop at the found class. If it is a leaf node, terminate. +-If we found an upward reference to a higher level, enter the fallback ++If we found an upward reference to a higher level, enter the fallback + algorithm. + .TP + (iv) + If the tc filters did not return a class, nor a valid reference to one, + consider the minor number of the reference to be the priority. Retrieve + a class from the defmap of this class for the priority. If this did not +-contain a class, consult the defmap of this class for the ++contain a class, consult the defmap of this class for the ++.B BEST_EFFORT ++class. If this is an upward reference, or no + .B BEST_EFFORT +-class. If this is an upward reference, or no +-.B BEST_EFFORT + class was defined, + enter the fallback algorithm. If a valid class was found, and it is not a +-leaf node, restart the loop at this class. If it is a leaf, choose it and ++leaf node, restart the loop at this class. If it is a leaf, choose it and + terminate. If +-neither the priority distilled from the classid, nor the +-.B BEST_EFFORT ++neither the priority distilled from the classid, nor the ++.B BEST_EFFORT + priority yielded a class, enter the fallback algorithm. + .P + The fallback algorithm resides outside of the loop and is as follows. + .TP + (i) +-Consult the defmap of the class at which the jump to fallback occurred. If +-the defmap contains a class for the ++Consult the defmap of the class at which the jump to fallback occurred. If ++the defmap contains a class for the + .B + priority +-of the class (which is related to the TOS field), choose this class and +-terminate. ++of the class (which is related to the TOS field), choose this class and ++terminate. + .TP + (ii) + Consult the map for a class for the +@@ -212,28 +212,28 @@ priority. If found, choose it, and terminate. + (iii) + Choose the class at which break out to the fallback algorithm occurred. Terminate. + .P +-The packet is enqueued to the class which was chosen when either algorithm ++The packet is enqueued to the class which was chosen when either algorithm + terminated. It is therefore possible for a packet to be enqueued *not* at a + leaf node, but in the middle of the hierarchy. + + .SH LINK SHARING ALGORITHM +-When dequeuing for sending to the network device, CBQ decides which of its ++When dequeuing for sending to the network device, CBQ decides which of its + classes will be allowed to send. It does so with a Weighted Round Robin process + in which each class with packets gets a chance to send in turn. The WRR process +-starts by asking the highest priority classes (lowest numerically - ++starts by asking the highest priority classes (lowest numerically - + highest semantically) for packets, and will continue to do so until they +-have no more data to offer, in which case the process repeats for lower ++have no more data to offer, in which case the process repeats for lower + priorities. + + .B CERTAINTY ENDS HERE, ANK PLEASE HELP + + Each class is not allowed to send at length though - they can only dequeue a +-configurable amount of data during each round. ++configurable amount of data during each round. + + If a class is about to go overlimit, and it is not + .B bounded + it will try to borrow avgidle from siblings that are not +-.B isolated. ++.B isolated. + This process is repeated from the bottom upwards. If a class is unable + to borrow enough avgidle to send a packet, it is throttled and not asked + for a packet for enough time for the avgidle to increase above zero. +@@ -244,7 +244,7 @@ for a packet for enough time for the avgidle to increase above zero. + .SH QDISC + The root qdisc of a CBQ class tree has the following parameters: + +-.TP ++.TP + parent major:minor | root + This mandatory parameter determines the place of the CBQ instance, either at the + .B root +@@ -259,22 +259,22 @@ For calculations, the average packet size must be known. It is silently capped + at a minimum of 2/3 of the interface MTU. Mandatory. + .TP + bandwidth rate +-To determine the idle time, CBQ must know the bandwidth of your underlying ++To determine the idle time, CBQ must know the bandwidth of your underlying + physical interface, or parent qdisc. This is a vital parameter, more about it + later. Mandatory. + .TP + cell + The cell size determines he granularity of packet transmission time calculations. Has a sensible default. +-.TP ++.TP + mpu + A zero sized packet may still take time to transmit. This value is the lower + cap for packet transmission time calculations - packets smaller than this value + are still deemed to have this size. Defaults to zero. + .TP + ewma log +-When CBQ needs to measure the average idle time, it does so using an ++When CBQ needs to measure the average idle time, it does so using an + Exponentially Weighted Moving Average which smooths out measurements into +-a moving average. The EWMA LOG determines how much smoothing occurs. Defaults ++a moving average. The EWMA LOG determines how much smoothing occurs. Defaults + to 5. Lower values imply greater sensitivity. Must be between 0 and 31. + .P + A CBQ qdisc does not shape out of its own accord. It only needs to know certain +@@ -283,35 +283,35 @@ parameters about the underlying link. Actual shaping is done in classes. + .SH CLASSES + Classes have a host of parameters to configure their operation. + +-.TP ++.TP + parent major:minor +-Place of this class within the hierarchy. If attached directly to a qdisc ++Place of this class within the hierarchy. If attached directly to a qdisc + and not to another class, minor can be omitted. Mandatory. +-.TP ++.TP + classid major:minor + Like qdiscs, classes can be named. The major number must be equal to the +-major number of the qdisc to which it belongs. Optional, but needed if this ++major number of the qdisc to which it belongs. Optional, but needed if this + class is going to have children. +-.TP ++.TP + weight weight +-When dequeuing to the interface, classes are tried for traffic in a ++When dequeuing to the interface, classes are tried for traffic in a + round-robin fashion. Classes with a higher configured qdisc will generally + have more traffic to offer during each round, so it makes sense to allow + it to dequeue more traffic. All weights under a class are normalized, so +-only the ratios matter. Defaults to the configured rate, unless the priority ++only the ratios matter. Defaults to the configured rate, unless the priority + of this class is maximal, in which case it is set to 1. +-.TP ++.TP + allot bytes + Allot specifies how many bytes a qdisc can dequeue +-during each round of the process. This parameter is weighted using the ++during each round of the process. This parameter is weighted using the + renormalized class weight described above. + +-.TP ++.TP + priority priority +-In the round-robin process, classes with the lowest priority field are tried ++In the round-robin process, classes with the lowest priority field are tried + for packets first. Mandatory. + +-.TP ++.TP + rate rate + Maximum rate this class and all its children combined can send at. Mandatory. + +@@ -321,7 +321,7 @@ This is different from the bandwidth specified when creating a CBQ disc. Only + used to determine maxidle and offtime, which are only calculated when + specifying maxburst or minburst. Mandatory if specifying maxburst or minburst. + +-.TP ++.TP + maxburst + This number of packets is used to calculate maxidle so that when + avgidle is at maxidle, this number of average packets can be burst +@@ -329,7 +329,7 @@ before avgidle drops to 0. Set it higher to be more tolerant of + bursts. You can't set maxidle directly, only via this parameter. + + .TP +-minburst ++minburst + As mentioned before, CBQ needs to throttle in case of + overlimit. The ideal solution is to do so for exactly the calculated + idle time, and pass 1 packet. However, Unix kernels generally have a +@@ -352,21 +352,21 @@ Minidle is specified in negative microseconds, so 10 means that + avgidle is capped at -10us. + + .TP +-bounded ++bounded + Signifies that this class will not borrow bandwidth from its siblings. +-.TP ++.TP + isolated + Means that this class will not borrow bandwidth to its siblings + +-.TP ++.TP + split major:minor & defmap bitmap[/bitmap] +-If consulting filters attached to a class did not give a verdict, ++If consulting filters attached to a class did not give a verdict, + CBQ can also classify based on the packet's priority. There are 16 +-priorities available, numbered from 0 to 15. ++priorities available, numbered from 0 to 15. + +-The defmap specifies which priorities this class wants to receive, +-specified as a bitmap. The Least Significant Bit corresponds to priority +-zero. The ++The defmap specifies which priorities this class wants to receive, ++specified as a bitmap. The Least Significant Bit corresponds to priority ++zero. The + .B split + parameter tells CBQ at which class the decision must be made, which should + be a (grand)parent of the class you are adding. +@@ -374,7 +374,7 @@ be a (grand)parent of the class you are adding. + As an example, 'tc class add ... classid 10:1 cbq .. split 10:0 defmap c0' + configures class 10:0 to send packets with priorities 6 and 7 to 10:1. + +-The complimentary configuration would then ++The complimentary configuration would then + be: 'tc class add ... classid 10:2 cbq ... split 10:0 defmap 3f' + Which would send all packets 0, 1, 2, 3, 4 and 5 to 10:1. + .TP +@@ -384,11 +384,11 @@ can use to classify packets with. In order to determine the bandwidth + it uses a very simple estimator that measures once every + .B interval + microseconds how much traffic has passed. This again is a EWMA, for which +-the time constant can be specified, also in microseconds. The ++the time constant can be specified, also in microseconds. The + .B time constant +-corresponds to the sluggishness of the measurement or, conversely, to the ++corresponds to the sluggishness of the measurement or, conversely, to the + sensitivity of the average to short bursts. Higher values mean less +-sensitivity. ++sensitivity. + + + +@@ -399,7 +399,7 @@ Sally Floyd and Van Jacobson, "Link-sharing and Resource + Management Models for Packet Networks", + IEEE/ACM Transactions on Networking, Vol.3, No.4, 1995 + +-.TP ++.TP + o + Sally Floyd, "Notes on CBQ and Guarantee Service", 1995 + +@@ -408,7 +408,7 @@ o + Sally Floyd, "Notes on Class-Based Queueing: Setting + Parameters", 1996 + +-.TP ++.TP + o + Sally Floyd and Michael Speer, "Experimental Results + for Class-Based Queueing", 1998, not published. +@@ -421,5 +421,3 @@ for Class-Based Queueing", 1998, not published. + .SH AUTHOR + Alexey N. Kuznetsov, <kuznet@ms2.inr.ac.ru>. This manpage maintained by + bert hubert <ahu@ds9a.nl> +- +- +diff --git a/man/man8/tc-cbq.8 b/man/man8/tc-cbq.8 +index b900e1c..301265d 100644 +--- a/man/man8/tc-cbq.8 ++++ b/man/man8/tc-cbq.8 +@@ -5,56 +5,56 @@ CBQ \- Class Based Queueing + .B tc qdisc ... dev + dev + .B ( parent +-classid +-.B | root) [ handle +-major: +-.B ] cbq [ allot ++classid ++.B | root) [ handle ++major: ++.B ] cbq [ allot + bytes + .B ] avpkt + bytes + .B bandwidth + rate +-.B [ cell ++.B [ cell + bytes + .B ] [ ewma + log + .B ] [ mpu + bytes +-.B ] ++.B ] + + .B tc class ... dev + dev +-.B parent ++.B parent + major:[minor] +-.B [ classid ++.B [ classid + major:minor + .B ] cbq allot + bytes +-.B [ bandwidth +-rate +-.B ] [ rate ++.B [ bandwidth ++rate ++.B ] [ rate + rate + .B ] prio + priority + .B [ weight + weight +-.B ] [ minburst ++.B ] [ minburst ++packets ++.B ] [ maxburst + packets +-.B ] [ maxburst +-packets +-.B ] [ ewma ++.B ] [ ewma + log + .B ] [ cell + bytes + .B ] avpkt + bytes + .B [ mpu +-bytes ++bytes + .B ] [ bounded isolated ] [ split + handle + .B & defmap + defmap +-.B ] [ estimator ++.B ] [ estimator + interval timeconstant + .B ] + +@@ -62,7 +62,7 @@ interval timeconstant + Class Based Queueing is a classful qdisc that implements a rich + linksharing hierarchy of classes. It contains shaping elements as + well as prioritizing capabilities. Shaping is performed using link +-idle time calculations based on the timing of dequeue events and ++idle time calculations based on the timing of dequeue events and + underlying link bandwidth. + + .SH SHAPING ALGORITHM +@@ -85,71 +85,71 @@ CBQ throttles and is then 'overlimit'. + + Conversely, an idle link might amass a huge avgidle, which would then + allow infinite bandwidths after a few hours of silence. To prevent +-this, avgidle is capped at ++this, avgidle is capped at + .B maxidle. + + If overlimit, in theory, the CBQ could throttle itself for exactly the + amount of time that was calculated to pass between packets, and then + pass one packet, and throttle again. Due to timer resolution constraints, +-this may not be feasible, see the ++this may not be feasible, see the + .B minburst + parameter below. + + .SH CLASSIFICATION + Within the one CBQ instance many classes may exist. Each of these classes +-contains another qdisc, by default ++contains another qdisc, by default + .BR tc-pfifo (8). + +-When enqueueing a packet, CBQ starts at the root and uses various methods to +-determine which class should receive the data. ++When enqueueing a packet, CBQ starts at the root and uses various methods to ++determine which class should receive the data. + +-In the absence of uncommon configuration options, the process is rather easy. +-At each node we look for an instruction, and then go to the class the +-instruction refers us to. If the class found is a barren leaf-node (without +-children), we enqueue the packet there. If it is not yet a leaf node, we do +-the whole thing over again starting from that node. ++In the absence of uncommon configuration options, the process is rather easy. ++At each node we look for an instruction, and then go to the class the ++instruction refers us to. If the class found is a barren leaf-node (without ++children), we enqueue the packet there. If it is not yet a leaf node, we do ++the whole thing over again starting from that node. + +-The following actions are performed, in order at each node we visit, until one ++The following actions are performed, in order at each node we visit, until one + sends us to another node, or terminates the process. + .TP + (i) +-Consult filters attached to the class. If sent to a leafnode, we are done. ++Consult filters attached to the class. If sent to a leafnode, we are done. + Otherwise, restart. + .TP + (ii) +-Consult the defmap for the priority assigned to this packet, which depends ++Consult the defmap for the priority assigned to this packet, which depends + on the TOS bits. Check if the referral is leafless, otherwise restart. + .TP + (iii) +-Ask the defmap for instructions for the 'best effort' priority. Check the ++Ask the defmap for instructions for the 'best effort' priority. Check the + answer for leafness, otherwise restart. + .TP + (iv) + If none of the above returned with an instruction, enqueue at this node. + .P + This algorithm makes sure that a packet always ends up somewhere, even while +-you are busy building your configuration. ++you are busy building your configuration. + + For more details, see + .BR tc-cbq-details(8). + + .SH LINK SHARING ALGORITHM +-When dequeuing for sending to the network device, CBQ decides which of its ++When dequeuing for sending to the network device, CBQ decides which of its + classes will be allowed to send. It does so with a Weighted Round Robin process + in which each class with packets gets a chance to send in turn. The WRR process +-starts by asking the highest priority classes (lowest numerically - ++starts by asking the highest priority classes (lowest numerically - + highest semantically) for packets, and will continue to do so until they +-have no more data to offer, in which case the process repeats for lower ++have no more data to offer, in which case the process repeats for lower + priorities. + +-Classes by default borrow bandwidth from their siblings. A class can be +-prevented from doing so by declaring it 'bounded'. A class can also indicate ++Classes by default borrow bandwidth from their siblings. A class can be ++prevented from doing so by declaring it 'bounded'. A class can also indicate + its unwillingness to lend out bandwidth by being 'isolated'. + + .SH QDISC + The root of a CBQ qdisc class tree has the following parameters: + +-.TP ++.TP + parent major:minor | root + This mandatory parameter determines the place of the CBQ instance, either at the + .B root +@@ -159,7 +159,7 @@ handle major: + Like all other qdiscs, the CBQ can be assigned a handle. Should consist only + of a major number, followed by a colon. Optional, but very useful if classes + will be generated within this qdisc. +-.TP ++.TP + allot bytes + This allotment is the 'chunkiness' of link sharing and is used for determining packet + transmission time tables. The qdisc allot differs slightly from the class allot discussed +@@ -170,23 +170,23 @@ The average size of a packet is needed for calculating maxidle, and is also used + for making sure 'allot' has a safe value. Mandatory. + .TP + bandwidth rate +-To determine the idle time, CBQ must know the bandwidth of your underlying ++To determine the idle time, CBQ must know the bandwidth of your underlying + physical interface, or parent qdisc. This is a vital parameter, more about it + later. Mandatory. + .TP + cell + The cell size determines he granularity of packet transmission time calculations. Has a sensible default. +-.TP ++.TP + mpu + A zero sized packet may still take time to transmit. This value is the lower + cap for packet transmission time calculations - packets smaller than this value + are still deemed to have this size. Defaults to zero. + .TP + ewma log +-When CBQ needs to measure the average idle time, it does so using an ++When CBQ needs to measure the average idle time, it does so using an + Exponentially Weighted Moving Average which smooths out measurements into +-a moving average. The EWMA LOG determines how much smoothing occurs. Lower +-values imply greater sensitivity. Must be between 0 and 31. Defaults ++a moving average. The EWMA LOG determines how much smoothing occurs. Lower ++values imply greater sensitivity. Must be between 0 and 31. Defaults + to 5. + .P + A CBQ qdisc does not shape out of its own accord. It only needs to know certain +@@ -195,40 +195,40 @@ parameters about the underlying link. Actual shaping is done in classes. + .SH CLASSES + Classes have a host of parameters to configure their operation. + +-.TP ++.TP + parent major:minor +-Place of this class within the hierarchy. If attached directly to a qdisc ++Place of this class within the hierarchy. If attached directly to a qdisc + and not to another class, minor can be omitted. Mandatory. +-.TP ++.TP + classid major:minor + Like qdiscs, classes can be named. The major number must be equal to the +-major number of the qdisc to which it belongs. Optional, but needed if this ++major number of the qdisc to which it belongs. Optional, but needed if this + class is going to have children. +-.TP ++.TP + weight weight +-When dequeuing to the interface, classes are tried for traffic in a ++When dequeuing to the interface, classes are tried for traffic in a + round-robin fashion. Classes with a higher configured qdisc will generally + have more traffic to offer during each round, so it makes sense to allow + it to dequeue more traffic. All weights under a class are normalized, so +-only the ratios matter. Defaults to the configured rate, unless the priority ++only the ratios matter. Defaults to the configured rate, unless the priority + of this class is maximal, in which case it is set to 1. +-.TP ++.TP + allot bytes + Allot specifies how many bytes a qdisc can dequeue +-during each round of the process. This parameter is weighted using the ++during each round of the process. This parameter is weighted using the + renormalized class weight described above. Silently capped at a minimum of + 3/2 avpkt. Mandatory. + +-.TP ++.TP + prio priority +-In the round-robin process, classes with the lowest priority field are tried ++In the round-robin process, classes with the lowest priority field are tried + for packets first. Mandatory. + +-.TP ++.TP + avpkt + See the QDISC section. + +-.TP ++.TP + rate rate + Maximum rate this class and all its children combined can send at. Mandatory. + +@@ -238,7 +238,7 @@ This is different from the bandwidth specified when creating a CBQ disc! Only + used to determine maxidle and offtime, which are only calculated when + specifying maxburst or minburst. Mandatory if specifying maxburst or minburst. + +-.TP ++.TP + maxburst + This number of packets is used to calculate maxidle so that when + avgidle is at maxidle, this number of average packets can be burst +@@ -246,7 +246,7 @@ before avgidle drops to 0. Set it higher to be more tolerant of + bursts. You can't set maxidle directly, only via this parameter. + + .TP +-minburst ++minburst + As mentioned before, CBQ needs to throttle in case of + overlimit. The ideal solution is to do so for exactly the calculated + idle time, and pass 1 packet. However, Unix kernels generally have a +@@ -269,21 +269,21 @@ Minidle is specified in negative microseconds, so 10 means that + avgidle is capped at -10us. Optional. + + .TP +-bounded ++bounded + Signifies that this class will not borrow bandwidth from its siblings. +-.TP ++.TP + isolated + Means that this class will not borrow bandwidth to its siblings + +-.TP ++.TP + split major:minor & defmap bitmap[/bitmap] +-If consulting filters attached to a class did not give a verdict, ++If consulting filters attached to a class did not give a verdict, + CBQ can also classify based on the packet's priority. There are 16 +-priorities available, numbered from 0 to 15. ++priorities available, numbered from 0 to 15. + +-The defmap specifies which priorities this class wants to receive, +-specified as a bitmap. The Least Significant Bit corresponds to priority +-zero. The ++The defmap specifies which priorities this class wants to receive, ++specified as a bitmap. The Least Significant Bit corresponds to priority ++zero. The + .B split + parameter tells CBQ at which class the decision must be made, which should + be a (grand)parent of the class you are adding. +@@ -291,7 +291,7 @@ be a (grand)parent of the class you are adding. + As an example, 'tc class add ... classid 10:1 cbq .. split 10:0 defmap c0' + configures class 10:0 to send packets with priorities 6 and 7 to 10:1. + +-The complimentary configuration would then ++The complimentary configuration would then + be: 'tc class add ... classid 10:2 cbq ... split 10:0 defmap 3f' + Which would send all packets 0, 1, 2, 3, 4 and 5 to 10:1. + .TP +@@ -301,22 +301,22 @@ can use to classify packets with. In order to determine the bandwidth + it uses a very simple estimator that measures once every + .B interval + microseconds how much traffic has passed. This again is a EWMA, for which +-the time constant can be specified, also in microseconds. The ++the time constant can be specified, also in microseconds. The + .B time constant +-corresponds to the sluggishness of the measurement or, conversely, to the ++corresponds to the sluggishness of the measurement or, conversely, to the + sensitivity of the average to short bursts. Higher values mean less +-sensitivity. ++sensitivity. + + .SH BUGS +-The actual bandwidth of the underlying link may not be known, for example +-in the case of PPoE or PPTP connections which in fact may send over a ++The actual bandwidth of the underlying link may not be known, for example ++in the case of PPoE or PPTP connections which in fact may send over a + pipe, instead of over a physical device. CBQ is quite resilient to major + errors in the configured bandwidth, probably a the cost of coarser shaping. + +-Default kernels rely on coarse timing information for making decisions. These ++Default kernels rely on coarse timing information for making decisions. These + may make shaping precise in the long term, but inaccurate on second long scales. + +-See ++See + .BR tc-cbq-details(8) + for hints on how to improve this. + +@@ -327,7 +327,7 @@ Sally Floyd and Van Jacobson, "Link-sharing and Resource + Management Models for Packet Networks", + IEEE/ACM Transactions on Networking, Vol.3, No.4, 1995 + +-.TP ++.TP + o + Sally Floyd, "Notes on CBQ and Guaranteed Service", 1995 + +@@ -336,7 +336,7 @@ o + Sally Floyd, "Notes on Class-Based Queueing: Setting + Parameters", 1996 + +-.TP ++.TP + o + Sally Floyd and Michael Speer, "Experimental Results + for Class-Based Queueing", 1998, not published. +@@ -349,5 +349,3 @@ for Class-Based Queueing", 1998, not published. + .SH AUTHOR + Alexey N. Kuznetsov, <kuznet@ms2.inr.ac.ru>. This manpage maintained by + bert hubert <ahu@ds9a.nl> +- +- +diff --git a/man/man8/tc-drr.8 b/man/man8/tc-drr.8 +index f550a35..2fea4ee 100644 +--- a/man/man8/tc-drr.8 ++++ b/man/man8/tc-drr.8 +@@ -92,4 +92,3 @@ as limits are handled by the individual child qdiscs. + + .SH AUTHOR + sched_drr was written by Patrick McHardy. +- +diff --git a/man/man8/tc-htb.8 b/man/man8/tc-htb.8 +index 95f25de..ae310f4 100644 +--- a/man/man8/tc-htb.8 ++++ b/man/man8/tc-htb.8 +@@ -5,30 +5,30 @@ HTB \- Hierarchy Token Bucket + .B tc qdisc ... dev + dev + .B ( parent +-classid +-.B | root) [ handle +-major: +-.B ] htb [ default ++classid ++.B | root) [ handle ++major: ++.B ] htb [ default + minor-id +-.B ] ++.B ] + + .B tc class ... dev + dev +-.B parent ++.B parent + major:[minor] +-.B [ classid ++.B [ classid + major:minor + .B ] htb rate + rate + .B [ ceil +-rate +-.B ] burst ++rate ++.B ] burst + bytes + .B [ cburst + bytes + .B ] [ prio + priority +-.B ] ++.B ] + + .SH DESCRIPTION + HTB is meant as a more understandable and intuitive replacement for +@@ -37,9 +37,9 @@ of the outbound bandwidth on a given link. Both allow you to use one + physical link to simulate several slower links and to send different + kinds of traffic on different simulated links. In both cases, you have + to specify how to divide the physical link into simulated links and +-how to decide which simulated link to use for a given packet to be sent. ++how to decide which simulated link to use for a given packet to be sent. + +-Unlike CBQ, HTB shapes traffic based on the Token Bucket Filter algorithm ++Unlike CBQ, HTB shapes traffic based on the Token Bucket Filter algorithm + which does not depend on interface characteristics and so does not need to + know the underlying bandwidth of the outgoing interface. + +@@ -49,30 +49,30 @@ Shaping works as documented in + + .SH CLASSIFICATION + Within the one HTB instance many classes may exist. Each of these classes +-contains another qdisc, by default ++contains another qdisc, by default + .BR tc-pfifo (8). + +-When enqueueing a packet, HTB starts at the root and uses various methods to +-determine which class should receive the data. ++When enqueueing a packet, HTB starts at the root and uses various methods to ++determine which class should receive the data. + +-In the absence of uncommon configuration options, the process is rather easy. +-At each node we look for an instruction, and then go to the class the +-instruction refers us to. If the class found is a barren leaf-node (without +-children), we enqueue the packet there. If it is not yet a leaf node, we do +-the whole thing over again starting from that node. ++In the absence of uncommon configuration options, the process is rather easy. ++At each node we look for an instruction, and then go to the class the ++instruction refers us to. If the class found is a barren leaf-node (without ++children), we enqueue the packet there. If it is not yet a leaf node, we do ++the whole thing over again starting from that node. + +-The following actions are performed, in order at each node we visit, until one ++The following actions are performed, in order at each node we visit, until one + sends us to another node, or terminates the process. + .TP + (i) +-Consult filters attached to the class. If sent to a leafnode, we are done. ++Consult filters attached to the class. If sent to a leafnode, we are done. + Otherwise, restart. + .TP + (ii) + If none of the above returned with an instruction, enqueue at this node. + .P + This algorithm makes sure that a packet always ends up somewhere, even while +-you are busy building your configuration. ++you are busy building your configuration. + + .SH LINK SHARING ALGORITHM + FIXME +@@ -80,7 +80,7 @@ FIXME + .SH QDISC + The root of a HTB qdisc class tree has the following parameters: + +-.TP ++.TP + parent major:minor | root + This mandatory parameter determines the place of the HTB instance, either at the + .B root +@@ -90,54 +90,54 @@ handle major: + Like all other qdiscs, the HTB can be assigned a handle. Should consist only + of a major number, followed by a colon. Optional, but very useful if classes + will be generated within this qdisc. +-.TP ++.TP + default minor-id + Unclassified traffic gets sent to the class with this minor-id. + + .SH CLASSES + Classes have a host of parameters to configure their operation. + +-.TP ++.TP + parent major:minor +-Place of this class within the hierarchy. If attached directly to a qdisc ++Place of this class within the hierarchy. If attached directly to a qdisc + and not to another class, minor can be omitted. Mandatory. +-.TP ++.TP + classid major:minor + Like qdiscs, classes can be named. The major number must be equal to the +-major number of the qdisc to which it belongs. Optional, but needed if this ++major number of the qdisc to which it belongs. Optional, but needed if this + class is going to have children. +-.TP ++.TP + prio priority +-In the round-robin process, classes with the lowest priority field are tried ++In the round-robin process, classes with the lowest priority field are tried + for packets first. Mandatory. + +-.TP ++.TP + rate rate + Maximum rate this class and all its children are guaranteed. Mandatory. + + .TP + ceil rate +-Maximum rate at which a class can send, if its parent has bandwidth to spare. ++Maximum rate at which a class can send, if its parent has bandwidth to spare. + Defaults to the configured rate, which implies no borrowing + +-.TP ++.TP + burst bytes +-Amount of bytes that can be burst at ++Amount of bytes that can be burst at + .B ceil + speed, in excess of the configured +-.B rate. ++.B rate. + Should be at least as high as the highest burst of all children. + +-.TP ++.TP + cburst bytes + Amount of bytes that can be burst at 'infinite' speed, in other words, as fast + as the interface can transmit them. For perfect evening out, should be equal to at most one average + packet. Should be at least as high as the highest cburst of all children. + + .SH NOTES +-Due to Unix timing constraints, the maximum ceil rate is not infinite and may in fact be quite low. On Intel, ++Due to Unix timing constraints, the maximum ceil rate is not infinite and may in fact be quite low. On Intel, + there are 100 timer events per second, the maximum rate is that rate at which 'burst' bytes are sent each timer tick. +-From this, the minimum burst size for a specified rate can be calculated. For i386, a 10mbit rate requires a 12 kilobyte ++From this, the minimum burst size for a specified rate can be calculated. For i386, a 10mbit rate requires a 12 kilobyte + burst as 100*12kb*8 equals 10mbit. + + .SH SEE ALSO +@@ -146,5 +146,3 @@ burst as 100*12kb*8 equals 10mbit. + HTB website: http://luxik.cdi.cz/~devik/qos/htb/ + .SH AUTHOR + Martin Devera <devik@cdi.cz>. This manpage maintained by bert hubert <ahu@ds9a.nl> +- +- +diff --git a/man/man8/tc-netem.8 b/man/man8/tc-netem.8 +index 53c4de9..b31384f 100644 +--- a/man/man8/tc-netem.8 ++++ b/man/man8/tc-netem.8 +@@ -2,9 +2,9 @@ + .SH NAME + NetEm \- Network Emulator + .SH SYNOPSIS +-.B "tc qdisc ... dev" ++.B "tc qdisc ... dev" + .IR DEVICE " ] " +-.BR "add netem" ++.BR "add netem" + .I OPTIONS + + .IR OPTIONS " := [ " LIMIT " ] [ " DELAY " ] [ " LOSS \ +@@ -15,15 +15,15 @@ NetEm \- Network Emulator + .I packets + + .IR DELAY " := " +-.BI delay ++.BI delay + .IR TIME " [ " JITTER " [ " CORRELATION " ]]]" + .br +- [ ++ [ + .BR distribution " { "uniform " | " normal " | " pareto " | " paretonormal " } ]" + + .IR LOSS " := " + .BR loss " { " +-.BI random ++.BI random + .IR PERCENT " [ " CORRELATION " ] |" + .br + .RB " " state +@@ -44,13 +44,13 @@ NetEm \- Network Emulator + .IR REORDERING " := " + .B reorder + .IR PERCENT " [ " CORRELATION " ] [ " +-.B gap ++.B gap + .IR DISTANCE " ]" + + .IR RATE " := " + .B rate + .IR RATE " [ " PACKETOVERHEAD " [ " CELLSIZE " [ " CELLOVERHEAD " ]]]]" +- ++ + + .SH DESCRIPTION + NetEm is an enhancement of the Linux traffic control facilities +@@ -139,11 +139,11 @@ in this second example 25% of packets are sent immediately (with correlation of + 50%) while the others are delayed by 10 ms. + + .SS rate +-delay packets based on packet size and is a replacement for ++delay packets based on packet size and is a replacement for + .IR TBF . + Rate can be +-specified in common units (e.g. 100kbit). Optional +-.I PACKETOVERHEAD ++specified in common units (e.g. 100kbit). Optional ++.I PACKETOVERHEAD + (in bytes) specify an per packet overhead and can be negative. A positive value can be + used to simulate additional link layer headers. A negative value can be used to + artificial strip the Ethernet header (e.g. -14) and/or simulate a link layer +@@ -152,7 +152,7 @@ the cellsize. Cellsize can be used to simulate link layer schemes. ATM for + example has an payload cellsize of 48 bytes and 5 byte per cell header. If a + packet is 50 byte then ATM must use two cells: 2 * 48 bytes payload including 2 + * 5 byte header, thus consume 106 byte on the wire. The last optional value +-.I CELLOVERHEAD ++.I CELLOVERHEAD + can be used to specify per cell overhead - for our ATM example 5. + .I CELLOVERHEAD + can be negative, but use negative values with caution. +diff --git a/man/man8/tc-pfifo_fast.8 b/man/man8/tc-pfifo_fast.8 +index 43ab166..baf34b1 100644 +--- a/man/man8/tc-pfifo_fast.8 ++++ b/man/man8/tc-pfifo_fast.8 +@@ -13,14 +13,14 @@ is detached. + In this sense this qdisc is magic, and unlike other qdiscs. + + .SH ALGORITHM +-The algorithm is very similar to that of the classful ++The algorithm is very similar to that of the classful + .BR tc-prio (8) +-qdisc. ++qdisc. + .B pfifo_fast + is like three + .BR tc-pfifo (8) + queues side by side, where packets can be enqueued in any of the three bands +-based on their Type of Service bits or assigned priority. ++based on their Type of Service bits or assigned priority. + + Not all three bands are dequeued simultaneously - as long as lower bands + have traffic, higher bands are never dequeued. This can be used to +@@ -28,7 +28,7 @@ prioritize interactive traffic or penalize 'lowest cost' traffic. + + Each band can be txqueuelen packets long, as configured with + .BR ifconfig (8) +-or ++or + .BR ip (8). + Additional packets coming in are not enqueued but are instead dropped. + +@@ -36,7 +36,7 @@ See + .BR tc-prio (8) + for complete details on how TOS bits are translated into bands. + .SH PARAMETERS +-.TP ++.TP + txqueuelen + The length of the three bands depends on the interface txqueuelen, as + specified with +@@ -46,7 +46,7 @@ or + + .SH BUGS + Does not maintain statistics and does not show up in tc qdisc ls. This is because +-it is the automatic default in the absence of a configured qdisc. ++it is the automatic default in the absence of a configured qdisc. + + .SH SEE ALSO + .BR tc (8) +@@ -55,5 +55,3 @@ it is the automatic default in the absence of a configured qdisc. + Alexey N. Kuznetsov, <kuznet@ms2.inr.ac.ru> + + This manpage maintained by bert hubert <ahu@ds9a.nl> +- +- +diff --git a/man/man8/tc-prio.8 b/man/man8/tc-prio.8 +index 8c8cb54..0b4ba8b 100644 +--- a/man/man8/tc-prio.8 ++++ b/man/man8/tc-prio.8 +@@ -5,21 +5,21 @@ PRIO \- Priority qdisc + .B tc qdisc ... dev + dev + .B ( parent +-classid +-.B | root) [ handle +-major: +-.B ] prio [ bands ++classid ++.B | root) [ handle ++major: ++.B ] prio [ bands + bands + .B ] [ priomap + band band band... +-.B ] [ estimator ++.B ] [ estimator + interval timeconstant + .B ] + + .SH DESCRIPTION + The PRIO qdisc is a simple classful queueing discipline that contains + an arbitrary number of classes of differing priority. The classes are +-dequeued in numerical descending order of priority. PRIO is a scheduler ++dequeued in numerical descending order of priority. PRIO is a scheduler + and never delays packets - it is a work-conserving qdisc, though the qdiscs + contained in the classes may not be. + +@@ -51,22 +51,22 @@ From userspace + A process with sufficient privileges can encode the destination class + directly with SO_PRIORITY, see + .BR socket(7). +-.TP ++.TP + with a tc filter + A tc filter attached to the root qdisc can point traffic directly to a class +-.TP ++.TP + with the priomap + Based on the packet priority, which in turn is derived from the Type of + Service assigned to the packet. + .P +-Only the priomap is specific to this qdisc. ++Only the priomap is specific to this qdisc. + .SH QDISC PARAMETERS + .TP + bands + Number of bands. If changed from the default of 3, + .B priomap + must be updated as well. +-.TP ++.TP + priomap + The priomap maps the priority of + a packet to a class. The priority can either be set directly from userspace, +@@ -126,7 +126,7 @@ TOS Bits Means Linux Priority Band + The second column contains the value of the relevant + four TOS bits, followed by their translated meaning. For example, 15 stands + for a packet wanting Minimal Monetary Cost, Maximum Reliability, Maximum +-Throughput AND Minimum Delay. ++Throughput AND Minimum Delay. + + The fourth column lists the way the Linux kernel interprets the TOS bits, by + showing to which Priority they are mapped. +@@ -151,7 +151,7 @@ FTP + + TFTP 1000 (minimize delay) + +-SMTP ++SMTP + Command phase 1000 (minimize delay) + DATA phase 0100 (maximize throughput) + +@@ -176,12 +176,10 @@ further qdisc. + + .SH BUGS + Large amounts of traffic in the lower bands can cause starvation of higher +-bands. Can be prevented by attaching a shaper (for example, ++bands. Can be prevented by attaching a shaper (for example, + .BR tc-tbf(8) + to these bands to make sure they cannot dominate the link. + + .SH AUTHORS + Alexey N. Kuznetsov, <kuznet@ms2.inr.ac.ru>, J Hadi Salim + <hadi@cyberus.ca>. This manpage maintained by bert hubert <ahu@ds9a.nl> +- +- +diff --git a/man/man8/tc-red.8 b/man/man8/tc-red.8 +index d001c49..dd1ab74 100644 +--- a/man/man8/tc-red.8 ++++ b/man/man8/tc-red.8 +@@ -1,17 +1,17 @@ + .TH RED 8 "13 December 2001" "iproute2" "Linux" + .SH NAME +-red \- Random Early Detection ++red \- Random Early Detection + .SH SYNOPSIS + .B tc qdisc ... red +-.B limit ++.B limit ++bytes ++.B [ min ++bytes ++.B ] [ max + bytes +-.B [ min +-bytes +-.B ] [ max +-bytes + .B ] avpkt + bytes +-.B [ burst ++.B [ burst + packets + .B ] [ ecn ] [ harddrop] [ bandwidth + rate +@@ -46,51 +46,51 @@ The average queue size is used for determining the marking + probability. This is calculated using an Exponential Weighted Moving + Average, which can be more or less sensitive to bursts. + +-When the average queue size is below ++When the average queue size is below + .B min +-bytes, no packet will ever be marked. When it exceeds +-.B min, ++bytes, no packet will ever be marked. When it exceeds ++.B min, + the probability of doing so climbs linearly up +-to +-.B probability, ++to ++.B probability, + until the average queue size hits + .B max +-bytes. Because +-.B probability ++bytes. Because ++.B probability + is normally not set to 100%, the queue size might +-conceivably rise above ++conceivably rise above + .B max +-bytes, so the ++bytes, so the + .B limit + parameter is provided to set a hard maximum for the size of the queue. + + .SH PARAMETERS +-.TP ++.TP + min + Average queue size at which marking becomes a possibility. Defaults to + .B max + /3 + +-.TP ++.TP + max + At this average queue size, the marking probability is maximal. Should be at + least twice + .B min +-to prevent synchronous retransmits, higher for low ++to prevent synchronous retransmits, higher for low + .B min. +-Default to ++Default to + .B limit + /4 +-.TP ++.TP + probability + Maximum probability for marking, specified as a floating point + number from 0.0 to 1.0. Suggested values are 0.01 or 0.02 (1 or 2%, + respectively). Default : 0.02 +-.TP ++.TP + limit + Hard limit on the real (not average) queue size in bytes. Further packets + are dropped. Should be set higher than max+burst. It is advised to set this +-a few times higher than ++a few times higher than + .B max. + .TP + burst +@@ -98,7 +98,7 @@ Used for determining how fast the average queue size is influenced by the + real queue size. Larger values make the calculation more sluggish, allowing + longer bursts of traffic before marking starts. Real life experiments + support the following guideline: (min+min+max)/(3*avpkt). +-.TP ++.TP + avpkt + Specified in bytes. Used with burst to determine the time constant for + average queue size calculations. 1000 is a good value. +@@ -126,15 +126,15 @@ bytes, this parameter forces a drop instead of ecn marking. + adaptive + (Added in linux-3.3) Sets RED in adaptive mode as described in http://icir.org/floyd/papers/adaptiveRed.pdf + .nf +-Goal of Adaptive RED is to make 'probability' dynamic value between 1% and 50% to reach the target average queue : ++Goal of Adaptive RED is to make 'probability' dynamic value between 1% and 50% to reach the target average queue : + .B (max - min) / 2 + .fi + + .SH EXAMPLE + + .P +-# tc qdisc add dev eth0 parent 1:1 handle 10: red +- limit 400000 min 30000 max 90000 avpkt 1000 ++# tc qdisc add dev eth0 parent 1:1 handle 10: red ++ limit 400000 min 30000 max 90000 avpkt 1000 + burst 55 ecn adaptive bandwidth 10Mbit + + .SH SEE ALSO +@@ -142,11 +142,11 @@ Goal of Adaptive RED is to make 'probability' dynamic value between 1% and 50% t + .BR tc-choke (8) + + .SH SOURCES +-.TP ++.TP + o + Floyd, S., and Jacobson, V., Random Early Detection gateways for + Congestion Avoidance. http://www.aciri.org/floyd/papers/red/red.html +-.TP ++.TP + o + Some changes to the algorithm by Alexey N. Kuznetsov. + .TP +@@ -156,7 +156,5 @@ Adaptive RED : http://icir.org/floyd/papers/adaptiveRed.pdf + .SH AUTHORS + Alexey N. Kuznetsov, <kuznet@ms2.inr.ac.ru>, Alexey Makarenko + <makar@phoenix.kharkov.ua>, J Hadi Salim <hadi@nortelnetworks.com>, +-Eric Dumazet <eric.dumazet@gmail.com>. ++Eric Dumazet <eric.dumazet@gmail.com>. + This manpage maintained by bert hubert <ahu@ds9a.nl> +- +- +diff --git a/man/man8/tc-sfq.8 b/man/man8/tc-sfq.8 +index 9afb5b2..ec4d8b8 100644 +--- a/man/man8/tc-sfq.8 ++++ b/man/man8/tc-sfq.8 +@@ -33,11 +33,11 @@ P + .SH DESCRIPTION + + Stochastic Fairness Queueing is a classless queueing discipline available for +-traffic control with the ++traffic control with the + .BR tc (8) + command. + +-SFQ does not shape traffic but only schedules the transmission of packets, based on 'flows'. ++SFQ does not shape traffic but only schedules the transmission of packets, based on 'flows'. + The goal is to ensure fairness so that each flow is able to send data in turn, thus preventing + any single flow from drowning out the rest. + +@@ -62,13 +62,13 @@ Destination address + (iii) + Source and Destination port + .P +-If these are available. SFQ knows about ipv4 and ipv6 and also UDP, TCP and ESP. +-Packets with other protocols are hashed based on the 32bits representation of their ++If these are available. SFQ knows about ipv4 and ipv6 and also UDP, TCP and ESP. ++Packets with other protocols are hashed based on the 32bits representation of their + destination and source. A flow corresponds mostly to a TCP/IP connection. + + Each of these buckets should represent a unique flow. Because multiple flows may +-get hashed to the same bucket, sfqs internal hashing algorithm may be perturbed at configurable +-intervals so that the unfairness lasts only for a short while. Perturbation may ++get hashed to the same bucket, sfqs internal hashing algorithm may be perturbed at configurable ++intervals so that the unfairness lasts only for a short while. Perturbation may + however cause some inadvertent packet reordering to occur. After linux-3.3, there is + no packet reordering problem, but possible packet drops if rehashing hits one limit + (number of flows or packets per flow) +@@ -88,7 +88,7 @@ divisor + Can be used to set a different hash table size, available from kernel 2.6.39 onwards. + The specified divisor must be a power of two and cannot be larger than 65536. + Default value: 1024. +-.TP ++.TP + limit + Upper limit of the SFQ. Can be used to reduce the default length of 127 packets. + After linux-3.3, it can be raised. +@@ -97,12 +97,12 @@ depth + Limit of packets per flow (after linux-3.3). Default to 127 and can be lowered. + .TP + perturb +-Interval in seconds for queue algorithm perturbation. Defaults to 0, which means that ++Interval in seconds for queue algorithm perturbation. Defaults to 0, which means that + no perturbation occurs. Do not set too low for each perturbation may cause some packet + reordering or losses. Advised value: 60 + This value has no effect when external flow classification is used. + Its better to increase divisor value to lower risk of hash collisions. +-.TP ++.TP + quantum + Amount of bytes a flow is allowed to dequeue during a round of the round robin process. + Defaults to the MTU of the interface which is also the advised value and the minimum value. +@@ -142,7 +142,7 @@ Specified in bytes. Used with burst to determine the time constant for average q + burst + Used for determining how fast the average queue size is influenced by the real queue size. + .nf +-Default value is : ++Default value is : + .B (2 * min + max) / (3 * avpkt) + .fi + .TP +@@ -166,16 +166,16 @@ To attach to device ppp0: + .P + # tc qdisc add dev ppp0 root sfq + .P +-Please note that SFQ, like all non-shaping (work-conserving) qdiscs, is only useful ++Please note that SFQ, like all non-shaping (work-conserving) qdiscs, is only useful + if it owns the queue. +-This is the case when the link speed equals the actually available bandwidth. This holds +-for regular phone modems, ISDN connections and direct non-switched ethernet links. ++This is the case when the link speed equals the actually available bandwidth. This holds ++for regular phone modems, ISDN connections and direct non-switched ethernet links. + .P +-Most often, cable modems and DSL devices do not fall into this category. The same holds +-for when connected to a switch and trying to send data to a congested segment also ++Most often, cable modems and DSL devices do not fall into this category. The same holds ++for when connected to a switch and trying to send data to a congested segment also + connected to the switch. + .P +-In this case, the effective queue does not reside within Linux and is therefore not ++In this case, the effective queue does not reside within Linux and is therefore not + available for scheduling. + .P + Embed SFQ in a classful qdisc to make sure it owns the queue. +@@ -191,11 +191,11 @@ changed the sfq default of 1024, use the same value for the flow hash filter, to + .P + Example of sfq with optional RED mode : + .P +-# tc qdisc add dev eth0 parent 1:1 handle 10: sfq limit 3000 flows 512 divisor 16384 ++# tc qdisc add dev eth0 parent 1:1 handle 10: sfq limit 3000 flows 512 divisor 16384 + redflowlimit 100000 min 8000 max 60000 probability 0.20 ecn headdrop + + .SH SOURCE +-.TP ++.TP + o + Paul E. McKenney "Stochastic Fairness Queuing", + IEEE INFOCOMM'90 Proceedings, San Francisco, 1990. +@@ -205,7 +205,7 @@ o + Paul E. McKenney "Stochastic Fairness Queuing", + "Interworking: Research and Experience", v.2, 1991, p.113-131. + +-.TP ++.TP + o + See also: + M. Shreedhar and George Varghese "Efficient Fair +@@ -220,5 +220,3 @@ Alexey N. Kuznetsov, <kuznet@ms2.inr.ac.ru>, + Eric Dumazet <eric.dumazet@gmail.com>. + .P + This manpage maintained by bert hubert <ahu@ds9a.nl> +- +- +diff --git a/man/man8/tc-tbf.8 b/man/man8/tc-tbf.8 +index fc2c837..d721b5d 100644 +--- a/man/man8/tc-tbf.8 ++++ b/man/man8/tc-tbf.8 +@@ -6,11 +6,11 @@ tbf \- Token Bucket Filter + rate + .B burst + bytes/cell +-.B ( latency +-ms ++.B ( latency ++ms + .B | limit + bytes +-.B ) [ mpu ++.B ) [ mpu + bytes + .B [ peakrate + rate +@@ -22,46 +22,46 @@ burst is also known as buffer and maxburst. mtu is also known as minburst. + .SH DESCRIPTION + + The Token Bucket Filter is a classful queueing discipline available for +-traffic control with the ++traffic control with the + .BR tc (8) + command. + + TBF is a pure shaper and never schedules traffic. It is non-work-conserving and may throttle +-itself, although packets are available, to ensure that the configured rate is not exceeded. +-It is able to shape up to 1mbit/s of normal traffic with ideal minimal burstiness, ++itself, although packets are available, to ensure that the configured rate is not exceeded. ++It is able to shape up to 1mbit/s of normal traffic with ideal minimal burstiness, + sending out data exactly at the configured rates. + + Much higher rates are possible but at the cost of losing the minimal burstiness. In that +-case, data is on average dequeued at the configured rate but may be sent much faster at millisecond ++case, data is on average dequeued at the configured rate but may be sent much faster at millisecond + timescales. Because of further queues living in network adaptors, this is often not a problem. + + .SH ALGORITHM +-As the name implies, traffic is filtered based on the expenditure of ++As the name implies, traffic is filtered based on the expenditure of + .B tokens. + Tokens roughly correspond to bytes, with the additional constraint + that each packet consumes some tokens, no matter how small it is. This + reflects the fact that even a zero-sized packet occupies the link for + some time. + +-On creation, the TBF is stocked with tokens which correspond to the amount of traffic that can be burst ++On creation, the TBF is stocked with tokens which correspond to the amount of traffic that can be burst + in one go. Tokens arrive at a steady rate, until the bucket is full. + +-If no tokens are available, packets are queued, up to a configured limit. The TBF now ++If no tokens are available, packets are queued, up to a configured limit. The TBF now + calculates the token deficit, and throttles until the first packet in the queue can be sent. + +-If it is not acceptable to burst out packets at maximum speed, a peakrate can be configured ++If it is not acceptable to burst out packets at maximum speed, a peakrate can be configured + to limit the speed at which the bucket empties. This peakrate is implemented as a second TBF + with a very small bucket, so that it doesn't burst. + +-To achieve perfection, the second bucket may contain only a single packet, which leads to +-the earlier mentioned 1mbit/s limit. ++To achieve perfection, the second bucket may contain only a single packet, which leads to ++the earlier mentioned 1mbit/s limit. + + This limit is caused by the fact that the kernel can only throttle for at minimum 1 'jiffy', which depends +-on HZ as 1/HZ. For perfect shaping, only a single packet can get sent per jiffy - for HZ=100, this means 100 ++on HZ as 1/HZ. For perfect shaping, only a single packet can get sent per jiffy - for HZ=100, this means 100 + packets of on average 1000 bytes each, which roughly corresponds to 1mbit/s. + + .SH PARAMETERS +-See ++See + .BR tc (8) + for how to specify the units of these values. + .TP +@@ -71,30 +71,30 @@ available. You can also specify this the other way around by setting the + latency parameter, which specifies the maximum amount of time a packet can + sit in the TBF. The latter calculation takes into account the size of the + bucket, the rate and possibly the peakrate (if set). These two parameters +-are mutually exclusive. ++are mutually exclusive. + .TP + burst + Also known as buffer or maxburst. +-Size of the bucket, in bytes. This is the maximum amount of bytes that tokens can be available for instantaneously. +-In general, larger shaping rates require a larger buffer. For 10mbit/s on Intel, you need at least 10kbyte buffer ++Size of the bucket, in bytes. This is the maximum amount of bytes that tokens can be available for instantaneously. ++In general, larger shaping rates require a larger buffer. For 10mbit/s on Intel, you need at least 10kbyte buffer + if you want to reach your configured rate! + + If your buffer is too small, packets may be dropped because more tokens arrive per timer tick than fit in your bucket. + The minimum buffer size can be calculated by dividing the rate by HZ. + +-Token usage calculations are performed using a table which by default has a resolution of 8 packets. +-This resolution can be changed by specifying the ++Token usage calculations are performed using a table which by default has a resolution of 8 packets. ++This resolution can be changed by specifying the + .B cell + size with the burst. For example, to specify a 6000 byte buffer with a 16 + byte cell size, set a burst of 6000/16. You will probably never have to set + this. Must be an integral power of 2. + .TP + mpu +-A zero-sized packet does not use zero bandwidth. For ethernet, no packet uses less than 64 bytes. The Minimum Packet Unit ++A zero-sized packet does not use zero bandwidth. For ethernet, no packet uses less than 64 bytes. The Minimum Packet Unit + determines the minimal token usage (specified in bytes) for a packet. Defaults to zero. + .TP + rate +-The speed knob. See remarks above about limits! See ++The speed knob. See remarks above about limits! See + .BR tc (8) + for units. + .PP +@@ -112,7 +112,7 @@ Specifies the size of the peakrate bucket. For perfect accuracy, should be set t + If a peakrate is needed, but some burstiness is acceptable, this size can be raised. A 3000 byte minburst + allows around 3mbit/s of peakrate, given 1000 byte packets. + +-Like the regular burstsize you can also specify a ++Like the regular burstsize you can also specify a + .B cell + size. + .SH EXAMPLE & USAGE +@@ -139,5 +139,3 @@ the limit/latency is not effective anymore. + .SH AUTHOR + Alexey N. Kuznetsov, <kuznet@ms2.inr.ac.ru>. This manpage maintained by + bert hubert <ahu@ds9a.nl> +- +- +diff --git a/man/man8/tc.8 b/man/man8/tc.8 +index fb4efd9..391d7c7 100644 +--- a/man/man8/tc.8 ++++ b/man/man8/tc.8 +@@ -656,4 +656,3 @@ was written by Alexey N. Kuznetsov and added in Linux 2.2. + + .SH AUTHOR + Manpage maintained by bert hubert (ahu@ds9a.nl) +- +-- +1.8.3.1 + diff --git a/SOURCES/0117-man-ip-.8-drop-any-reference-to-generic-ip-options.patch b/SOURCES/0117-man-ip-.8-drop-any-reference-to-generic-ip-options.patch new file mode 100644 index 0000000..c73e0b3 --- /dev/null +++ b/SOURCES/0117-man-ip-.8-drop-any-reference-to-generic-ip-options.patch @@ -0,0 +1,116 @@ +From b8c5594d2702d7df9dd291b6e06253ad5f4fc17e Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Mon, 7 Mar 2016 20:46:03 +0100 +Subject: [PATCH] man: ip-*.8: drop any reference to generic ip options + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit e895ae0b31864 +Conflicts: Missing support for -brief option. + +commit e895ae0b31864df9f7dc16254d6dd2084f7bd523 +Author: Phil Sutter <phil@nwl.cc> +Date: Wed Mar 2 19:20:08 2016 +0100 + + man: ip-*.8: drop any reference to generic ip options + + Listing generic 'ip' options in subcommand man pages is redundant and + error-prone, as they won't be kept in sync anyway. Since many other man + pages don't list them either, drop references to them in the remaining + ones. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/ip-addrlabel.8 | 14 +------------- + man/man8/ip-link.8.in | 14 +------------- + man/man8/ip-monitor.8 | 4 +--- + man/man8/ip-mroute.8 | 2 +- + 4 files changed, 4 insertions(+), 30 deletions(-) + +diff --git a/man/man8/ip-addrlabel.8 b/man/man8/ip-addrlabel.8 +index 51ef572..233d606 100644 +--- a/man/man8/ip-addrlabel.8 ++++ b/man/man8/ip-addrlabel.8 +@@ -6,21 +6,9 @@ ip-addrlabel \- protocol address label management + .ad l + .in +8 + .ti -8 +-.B ip +-.RI "[ " OPTIONS " ]" +-.B addrlabel ++.B ip addrlabel + .RI " { " COMMAND " | " + .BR help " }" +-.sp +- +-.ti -8 +-.IR OPTIONS " := { " +-\fB\-V\fR[\fIersion\fR] | +-\fB\-s\fR[\fItatistics\fR] | +-\fB\-r\fR[\fIesolve\fR] | +-\fB\-f\fR[\fIamily\fR] { +-.BR inet " | " inet6 " | " ipx " | " dnet " | " link " } | " +-\fB\-o\fR[\fIneline\fR] } + + .ti -8 + .BR "ip addrlabel" " { " add " | " del " } " prefix +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 6ce2cc8..62fc340 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -6,24 +6,12 @@ ip-link \- network device configuration + .ad l + .in +8 + .ti -8 +-.B ip +-.RI "[ " OPTIONS " ]" +-.B link ++.B ip link + .RI " { " COMMAND " | " + .BR help " }" + .sp + + .ti -8 +-.IR OPTIONS " := { " +-\fB\-V\fR[\fIersion\fR] | +-\fB\-h\fR[\fIuman-readable\fR] | +-\fB\-s\fR[\fItatistics\fR] | +-\fB\-r\fR[\fIesolve\fR] | +-\fB\-f\fR[\fIamily\fR] { +-.BR inet " | " inet6 " | " ipx " | " dnet " | " link " } | " +-\fB\-o\fR[\fIneline\fR] } +- +-.ti -8 + .BI "ip link add" + .RB "[ " link + .IR DEVICE " ]" +diff --git a/man/man8/ip-monitor.8 b/man/man8/ip-monitor.8 +index 2d4fd4f..5d99a09 100644 +--- a/man/man8/ip-monitor.8 ++++ b/man/man8/ip-monitor.8 +@@ -6,9 +6,7 @@ ip-monitor, rtmon \- state monitoring + .ad l + .in +8 + .ti -8 +-.BR "ip " " [ " +-.IR ip-OPTIONS " ]" +-.BR "monitor" " [ " all " |" ++.BR "ip monitor" " [ " all " |" + .IR OBJECT-LIST " ] [" + .BI file " FILENAME " + ] [ +diff --git a/man/man8/ip-mroute.8 b/man/man8/ip-mroute.8 +index e89b6b2..b64e30d 100644 +--- a/man/man8/ip-mroute.8 ++++ b/man/man8/ip-mroute.8 +@@ -6,7 +6,7 @@ ip-mroute \- multicast routing cache management + .ad l + .in +8 + .ti -8 +-.BR "ip " " [ ip-OPTIONS ] " "mroute show" " [ [ " ++.BR "ip mroute show" " [ [ " + .BR " to " " ] " + .IR PREFIX " ] [ " + .B from +-- +1.8.3.1 + diff --git a/SOURCES/0118-fix-indentation-of-ip-neighbour-man-page.patch b/SOURCES/0118-fix-indentation-of-ip-neighbour-man-page.patch new file mode 100644 index 0000000..c895870 --- /dev/null +++ b/SOURCES/0118-fix-indentation-of-ip-neighbour-man-page.patch @@ -0,0 +1,97 @@ +From 080e795a1ae29f78cbec9f18837a9b6f84fea55f Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 25 Feb 2016 12:53:31 +0100 +Subject: [PATCH] fix indentation of ip neighbour man page + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1276661 +Upstream Status: iproute2.git commit 882e754cd4b3f + +commit 882e754cd4b3f302714bae777ee674fe6c61d04b +Author: Stephen Hemminger <stephen@networkplumber.org> +Date: Mon Mar 31 20:23:40 2014 -0700 + + fix indentation of ip neighbour man page + + Formatting was awful and unclear on ip neighbour +--- + man/man8/ip-neighbour.8 | 30 ++++++++++++++---------------- + 1 file changed, 14 insertions(+), 16 deletions(-) + +diff --git a/man/man8/ip-neighbour.8 b/man/man8/ip-neighbour.8 +index c94c654..19c6d9d 100644 +--- a/man/man8/ip-neighbour.8 ++++ b/man/man8/ip-neighbour.8 +@@ -60,7 +60,7 @@ change an existing entry + .TP + ip neighbour replace + add a new entry or change an existing one +- ++.RS + .PP + These commands create new neighbour records or update existing ones. + +@@ -105,11 +105,12 @@ This option to + .B ip neigh + does not change the neighbour state if it was valid and the address + is not changed by this command. +-.RS +-ip neighbour delete - delete a neighbour entry + .RE +-This command invalidates a neighbour entry. + ++.TP ++ip neighbour delete ++delete a neighbour entry ++.RS + .PP + The arguments are the same as with + .BR "ip neigh add" , +@@ -128,13 +129,12 @@ Particularly, the kernel may try to resolve this address even + on a + .B NOARP + interface or if the address is multicast or broadcast. +- +-.RS +-ip neighbour show - list neighbour entries + .RE + +-This command displays neighbour tables. +- ++.TP ++ip neighbour show ++list neighbour entries ++.RS + .TP + .BI to " ADDRESS " (default) + the prefix selecting the neighbours to list. +@@ -164,15 +164,12 @@ lists all entries except for + .B none + and + .BR "noarp" . +- +-.RS +-ip neighbour flush - flush neighbour entries + .RE + +-This command flushes neighbour tables, selecting +-entries to flush by some criteria. +- +-.PP ++.TP ++ip neighbour flush ++flush neighbour entries ++.RS + This command has the same arguments as + .B show. + The differences are that it does not run when no arguments are given, +@@ -190,6 +187,7 @@ neighbour table. If the option is given + twice, + .B ip neigh flush + also dumps all the deleted neighbours. ++.RE + + .SH EXAMPLES + .PP +-- +1.8.3.1 + diff --git a/SOURCES/0119-man-ip-neighbour.8-Document-all-known-nud-states.patch b/SOURCES/0119-man-ip-neighbour.8-Document-all-known-nud-states.patch new file mode 100644 index 0000000..7e4ccd9 --- /dev/null +++ b/SOURCES/0119-man-ip-neighbour.8-Document-all-known-nud-states.patch @@ -0,0 +1,75 @@ +From c97c96a77b54729f31a5e7b0209d87f314d1d8fe Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Mon, 7 Mar 2016 20:56:07 +0100 +Subject: [PATCH] man: ip-neighbour.8: Document all known nud states + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1276661 +Upstream Status: iproute2.git commit 948acfed23e5e + +commit 948acfed23e5e314fe0f4f863da0368f56645d32 +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 20:07:20 2016 +0100 + + man: ip-neighbour.8: Document all known nud states + + Not sure how useful they are in practice, but as 'ip neigh' supports + setting them all, they deserve to be described as well. + + While at it, also add a missing layer of indentation to the subordinate + nud state list. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/ip-neighbour.8 | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +diff --git a/man/man8/ip-neighbour.8 b/man/man8/ip-neighbour.8 +index 19c6d9d..b292e18 100644 +--- a/man/man8/ip-neighbour.8 ++++ b/man/man8/ip-neighbour.8 +@@ -35,7 +35,8 @@ ip-neighbour \- neighbour/arp tables management. + + .ti -8 + .IR STATE " := {" +-.BR permanent " | " noarp " | " stale " | " reachable " }" ++.BR permanent " | " noarp " | " stale " | " reachable " | " none " |" ++.BR incomplete " | " delay " | " probe " | " failed " }" + + .SH DESCRIPTION + The +@@ -86,6 +87,7 @@ the state of the neighbour entry. + is an abbreviation for 'Neighbour Unreachability Detection'. + The state can take one of the following values: + ++.RS + .TP + .B permanent + the neighbour entry is valid forever and can be only +@@ -105,6 +107,24 @@ This option to + .B ip neigh + does not change the neighbour state if it was valid and the address + is not changed by this command. ++.TP ++.B none ++this is a pseudo state used when initially creating a neighbour entry or after ++trying to remove it before it becomes free to do so. ++.TP ++.B incomplete ++the neighbour entry has not (yet) been validated/resolved. ++.TP ++.B delay ++neighbor entry validation is currently delayed. ++.TP ++.B probe ++neighbor is being probed. ++.TP ++.B failed ++max number of probes exceeded without success, neighbor validation has ++ultimately failed. ++.RE + .RE + + .TP +-- +1.8.3.1 + diff --git a/SOURCES/0120-libnetlink-Double-the-dump-buffer-size.patch b/SOURCES/0120-libnetlink-Double-the-dump-buffer-size.patch new file mode 100644 index 0000000..7df0dab --- /dev/null +++ b/SOURCES/0120-libnetlink-Double-the-dump-buffer-size.patch @@ -0,0 +1,45 @@ +From 3cfb170def0cfa4b4048ee1e153b29b460ff54f1 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Tue, 8 Mar 2016 18:35:16 +0100 +Subject: [PATCH] libnetlink: Double the dump buffer size + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1304840 +Upstream Status: iproute2.git commit 72b365e8e0fd5 + +commit 72b365e8e0fd5efe1d5c05d04c25950736635cfb +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 19:57:28 2016 +0100 + + libnetlink: Double the dump buffer size + + There have been reports about 'ip addr' printing "Message truncated" on + systems with large numbers of VFs. Although I haven't been able to get + my hands on hardware suitable to reproduce this, increasing the dump + buffer has been reported to resolve the issue. For want of a better + idea, just double the buffer size to 32k. + + Feels like this opportunistic buffer size selection is rather + workarounding a design flaw in libnetlink or maybe even the netlink + protocol itself. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + lib/libnetlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/libnetlink.c b/lib/libnetlink.c +index b2a300e..96bde59 100644 +--- a/lib/libnetlink.c ++++ b/lib/libnetlink.c +@@ -202,7 +202,7 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth, + .msg_iov = &iov, + .msg_iovlen = 1, + }; +- char buf[16384]; ++ char buf[32768]; + int dump_intr = 0; + + iov.iov_base = buf; +-- +1.8.3.1 + diff --git a/SOURCES/0121-man-ip-link-Beef-up-VXLAN-csum-options-a-bit.patch b/SOURCES/0121-man-ip-link-Beef-up-VXLAN-csum-options-a-bit.patch new file mode 100644 index 0000000..e26719d --- /dev/null +++ b/SOURCES/0121-man-ip-link-Beef-up-VXLAN-csum-options-a-bit.patch @@ -0,0 +1,45 @@ +From f49095ecb1b78ea7020e52cc53a0337d0b6df466 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Tue, 8 Mar 2016 18:36:08 +0100 +Subject: [PATCH] man: ip-link: Beef up VXLAN csum options a bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1254625 +Upstream Status: iproute2.git commit 4853ee528110f + +commit 4853ee528110f61f4d1c1606cfd5dd276bb39cbd +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 12:52:38 2016 +0100 + + man: ip-link: Beef up VXLAN csum options a bit + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/ip-link.8.in | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 62fc340..e8dccbd 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -409,15 +409,15 @@ are entered into the VXLAN device forwarding database. + + .sp + .I [no]udpcsum +-- specifies if UDP checksum is filled in ++- specifies if UDP checksum is calculated for transmitted packets over IPv4. + + .sp + .I [no]udp6zerocsumtx +-- specifies if UDP checksum is filled in ++- skip UDP checksum calculation for transmitted packets over IPv6. + + .sp + .I [no]udp6zerocsumrx +-- specifies if UDP checksum is received ++- allow incoming UDP packets over IPv6 with zero checksum field. + + .sp + .BI ageing " SECONDS" +-- +1.8.3.1 + diff --git a/SOURCES/0122-fix-print_ipt-segfault-if-more-then-one-filter-with-.patch b/SOURCES/0122-fix-print_ipt-segfault-if-more-then-one-filter-with-.patch new file mode 100644 index 0000000..42ded44 --- /dev/null +++ b/SOURCES/0122-fix-print_ipt-segfault-if-more-then-one-filter-with-.patch @@ -0,0 +1,80 @@ +From 732cf95fe96f859d40afb1bd3251b2cada683220 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Tue, 8 Mar 2016 18:38:17 +0100 +Subject: [PATCH] fix print_ipt: segfault if more then one filter with action + -j MARK. + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1314403 +Upstream Status: iproute2.git commit 6e2e5ec28bad4 + +commit 6e2e5ec28bad4561c534adf4f22b2706e385c71d +Author: Andreas Greve <andreas.greve@a-greve.de> +Date: Sat May 10 11:19:18 2014 +0200 + + fix print_ipt: segfault if more then one filter with action -j MARK. + + BUG: tc filter show ... produce a segmentation fault if more than one + filter rule with action -j MARK exists. + + Reason: In print_ipt(...) xtables will be initialzed with a + pointer to the static struct tcipt_globals at xtables_init_all(). + Later on the fields .opts and .options_offset of tcipt_globals are + modified. The call of xtables_free_opts(1) at the end of print(...) + does not restore the original values of tcipt_globals for the + modified fields. It only frees some allocated memory and sets + .opts to NULL. This leads to a segmentation fault when print_ipt() + is called for the next filter rule with action -j MARK. + + Fix: Cloneing tcipt_globals on the stack as tmp_tcipt_globals and + use it instead of tcipt_globals, so tcipt_globals will be not + modified. + + Signed-off-by: Andreas Greve <andreas.greve@a-greve.de> +--- + tc/m_xt.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/tc/m_xt.c b/tc/m_xt.c +index dd5fd48..48aac90 100644 +--- a/tc/m_xt.c ++++ b/tc/m_xt.c +@@ -298,7 +298,10 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg) + if (arg == NULL) + return -1; + +- xtables_init_all(&tcipt_globals, NFPROTO_IPV4); ++ /* copy tcipt_globals because .opts will be modified by iptables */ ++ struct xtables_globals tmp_tcipt_globals = tcipt_globals; ++ ++ xtables_init_all(&tmp_tcipt_globals, NFPROTO_IPV4); + set_lib_dir(); + + parse_rtattr_nested(tb, TCA_IPT_MAX, arg); +@@ -333,12 +336,12 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg) + } + + #if (XTABLES_VERSION_CODE >= 6) +- opts = xtables_options_xfrm(tcipt_globals.orig_opts, +- tcipt_globals.opts, ++ opts = xtables_options_xfrm(tmp_tcipt_globals.orig_opts, ++ tmp_tcipt_globals.opts, + m->x6_options, + &m->option_offset); + #else +- opts = xtables_merge_options(tcipt_globals.opts, ++ opts = xtables_merge_options(tmp_tcipt_globals.opts, + m->extra_opts, + &m->option_offset); + #endif +@@ -346,7 +349,7 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg) + fprintf(stderr, " failed to find aditional options for target %s\n\n", optarg); + return -1; + } else +- tcipt_globals.opts = opts; ++ tmp_tcipt_globals.opts = opts; + } else { + fprintf(stderr, " failed to find target %s\n\n", + t->u.user.name); +-- +1.8.3.1 + diff --git a/SOURCES/0123-man-rtpr-add-minimal-manpage.patch b/SOURCES/0123-man-rtpr-add-minimal-manpage.patch new file mode 100644 index 0000000..c2f23aa --- /dev/null +++ b/SOURCES/0123-man-rtpr-add-minimal-manpage.patch @@ -0,0 +1,72 @@ +From 6f97690bb3a37d701a67fdd8e0dbd4d8911c4d7c Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Fri, 11 Mar 2016 15:33:47 +0100 +Subject: [PATCH] man: rtpr: add minimal manpage + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1316059 +Upstream Status: iproute2.git commit e4ef49a465969 +Conflicts: Context changes in Makefile due to missing other man pages. + +commit e4ef49a465969a68704dbcfec43baa7f874f59ff +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Sep 18 20:17:05 2015 +0200 + + man: rtpr: add minimal manpage + + While there is not much to explain about this rather trivial shell + script, having a manpage for it serves as good point of reference for + users wondering what it might be for. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/Makefile | 2 +- + man/man8/rtpr.8 | 25 +++++++++++++++++++++++++ + 2 files changed, 26 insertions(+), 1 deletion(-) + create mode 100644 man/man8/rtpr.8 + +diff --git a/man/man8/Makefile b/man/man8/Makefile +index 248ecfd..c60c773 100644 +--- a/man/man8/Makefile ++++ b/man/man8/Makefile +@@ -1,6 +1,6 @@ + TARGETS = ip-address.8 ip-link.8 ip-route.8 + +-MAN8PAGES = $(TARGETS) ip.8 arpd.8 lnstat.8 routel.8 rtacct.8 rtmon.8 ss.8 \ ++MAN8PAGES = $(TARGETS) ip.8 arpd.8 lnstat.8 routel.8 rtacct.8 rtmon.8 rtpr.8 ss.8 \ + tc.8 tc-bfifo.8 tc-cbq.8 tc-cbq-details.8 tc-choke.8 tc-codel.8 \ + tc-fq.8 \ + tc-drr.8 tc-ematch.8 tc-fq_codel.8 tc-hfsc.8 tc-htb.8 \ +diff --git a/man/man8/rtpr.8 b/man/man8/rtpr.8 +new file mode 100644 +index 0000000..5e32b2e +--- /dev/null ++++ b/man/man8/rtpr.8 +@@ -0,0 +1,25 @@ ++.TH RTPR 8 "18 September, 2015" ++ ++.SH NAME ++rtpr \- replace backslashes with newlines. ++ ++.SH DESCRIPTION ++.B rtpr ++is a trivial bash script which converts backslashes in standard input to newlines. It's sole purpose is to be fed with input from ++.B ip ++when executed with it's ++.B --oneline ++flag. ++ ++.SH EXAMPLES ++.TP ++ip --onenline address show | rtpr ++Undo oneline converted ++.B ip-address ++output. ++ ++.SH SEE ALSO ++.BR ip (8) ++ ++.SH AUTHORS ++Stephen Hemminger <shemming@brocade.com> +-- +1.8.3.1 + diff --git a/SOURCES/0124-tc-introduce-simple-action.patch b/SOURCES/0124-tc-introduce-simple-action.patch new file mode 100644 index 0000000..354c3f1 --- /dev/null +++ b/SOURCES/0124-tc-introduce-simple-action.patch @@ -0,0 +1,247 @@ +From 1ce74bc27f9b766ed42fc23b3a3754bbef6a1a3c Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Fri, 11 Mar 2016 15:37:57 +0100 +Subject: [PATCH] tc: introduce simple action + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1315930 +Upstream Status: iproute2.git commit 087f46ee4ebd1 + +commit 087f46ee4ebd178a2a8562989fd9a4e02c93f406 +Author: Jamal Hadi Salim <jhs@mojatatu.com> +Date: Sun Sep 29 07:33:42 2013 -0400 + + tc: introduce simple action + + Simple action is already in the kernel for years now as an + example. This complements it with user space control. + + Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> +--- + tc/Makefile | 1 + + tc/m_simple.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 203 insertions(+) + create mode 100644 tc/m_simple.c + +diff --git a/tc/Makefile b/tc/Makefile +index 79116f3..59ee1dd 100644 +--- a/tc/Makefile ++++ b/tc/Makefile +@@ -44,6 +44,7 @@ TCMODULES += m_nat.o + TCMODULES += m_pedit.o + TCMODULES += m_skbedit.o + TCMODULES += m_csum.o ++TCMODULES += m_simple.o + TCMODULES += p_ip.o + TCMODULES += p_icmp.o + TCMODULES += p_tcp.o +diff --git a/tc/m_simple.c b/tc/m_simple.c +new file mode 100644 +index 0000000..0224440 +--- /dev/null ++++ b/tc/m_simple.c +@@ -0,0 +1,202 @@ ++/* ++ * m_simple.c simple action ++ * ++ * This program is free software; you can distribute 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. ++ * ++ * Authors: J Hadi Salim <jhs@mojatatu.com> ++ * ++ * Pedagogical example. Adds a string that will be printed everytime ++ * the simple instance is hit. ++ * Use this as a skeleton action and keep modifying it to meet your needs. ++ * Look at linux/tc_act/tc_defact.h for the different components ids and ++ * definitions used in this actions ++ * ++ * example use, yell "Incoming ICMP!" every time you see an incoming ICMP on ++ * eth0. Steps are: ++ * 1) Add an ingress qdisc point to eth0 ++ * 2) Start a chain on ingress of eth0 that first matches ICMP then invokes ++ * the simple action to shout. ++ * 3) display stats and show that no packet has been seen by the action ++ * 4) Send one ping packet to google (expect to receive a response back) ++ * 5) grep the logs to see the logged message ++ * 6) display stats again and observe increment by 1 ++ * ++ hadi@noma1:$ tc qdisc add dev eth0 ingress ++ hadi@noma1:$tc filter add dev eth0 parent ffff: protocol ip prio 5 \ ++ u32 match ip protocol 1 0xff flowid 1:1 action simple "Incoming ICMP" ++ ++ hadi@noma1:$ sudo tc -s filter ls dev eth0 parent ffff: ++ filter protocol ip pref 5 u32 ++ filter protocol ip pref 5 u32 fh 800: ht divisor 1 ++ filter protocol ip pref 5 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 ++ match 00010000/00ff0000 at 8 ++ action order 1: Simple <Incoming ICMP> ++ index 4 ref 1 bind 1 installed 29 sec used 29 sec ++ Action statistics: ++ Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) ++ backlog 0b 0p requeues 0 ++ ++ ++ hadi@noma1$ ping -c 1 www.google.ca ++ PING www.google.ca (74.125.225.120) 56(84) bytes of data. ++ 64 bytes from ord08s08-in-f24.1e100.net (74.125.225.120): icmp_req=1 ttl=53 time=31.3 ms ++ ++ --- www.google.ca ping statistics --- ++ 1 packets transmitted, 1 received, 0% packet loss, time 0ms ++ rtt min/avg/max/mdev = 31.316/31.316/31.316/0.000 ms ++ ++ hadi@noma1$ dmesg | grep simple ++ [135354.473951] simple: Incoming ICMP_1 ++ ++ hadi@noma1$ sudo tc/tc -s filter ls dev eth0 parent ffff: ++ filter protocol ip pref 5 u32 ++ filter protocol ip pref 5 u32 fh 800: ht divisor 1 ++ filter protocol ip pref 5 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 ++ match 00010000/00ff0000 at 8 ++ action order 1: Simple <Incoming ICMP> ++ index 4 ref 1 bind 1 installed 206 sec used 67 sec ++ Action statistics: ++ Sent 84 bytes 1 pkt (dropped 0, overlimits 0 requeues 0) ++ backlog 0b 0p requeues 0 ++*/ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include <syslog.h> ++#include <fcntl.h> ++#include <sys/socket.h> ++#include <netinet/in.h> ++#include <arpa/inet.h> ++#include <string.h> ++#include "utils.h" ++#include "tc_util.h" ++#include <linux/tc_act/tc_defact.h> ++ ++#ifndef SIMP_MAX_DATA ++#define SIMP_MAX_DATA 32 ++#endif ++static void explain(void) ++{ ++ fprintf(stderr, "Usage: ... simple STRING\n" ++ "STRING being an arbitrary string\n" ++ "example: \"simple blah\"\n"); ++} ++ ++static void usage(void) ++{ ++ explain(); ++ exit(-1); ++} ++ ++static int ++parse_simple(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, ++ struct nlmsghdr *n) ++{ ++ struct tc_defact sel = {}; ++ int argc = *argc_p; ++ char **argv = *argv_p; ++ int ok = 0; ++ struct rtattr *tail; ++ char *simpdata = NULL; ++ ++ ++ while (argc > 0) { ++ if (matches(*argv, "simple") == 0) { ++ NEXT_ARG(); ++ simpdata = *argv; ++ ok = 1; ++ argc--; ++ argv++; ++ break; ++ } else if (matches(*argv, "help") == 0) { ++ usage(); ++ } else { ++ break; ++ } ++ ++ } ++ ++ if (!ok) { ++ explain(); ++ return -1; ++ } ++ ++ if (argc) { ++ if (matches(*argv, "index") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&sel.index, *argv, 10)) { ++ fprintf(stderr, "simple: Illegal \"index\"\n"); ++ return -1; ++ } ++ argc--; ++ argv++; ++ } ++ } ++ ++ if (strlen(simpdata) > (SIMP_MAX_DATA - 1)) { ++ fprintf(stderr, "simple: Illegal string len %ld <%s> \n", ++ strlen(simpdata), simpdata); ++ return -1; ++ } ++ ++ sel.action = TC_ACT_PIPE; ++ ++ tail = NLMSG_TAIL(n); ++ addattr_l(n, MAX_MSG, tca_id, NULL, 0); ++ addattr_l(n, MAX_MSG, TCA_DEF_PARMS, &sel, sizeof(sel)); ++ addattr_l(n, MAX_MSG, TCA_DEF_DATA, simpdata, SIMP_MAX_DATA); ++ tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail; ++ ++ *argc_p = argc; ++ *argv_p = argv; ++ return 0; ++} ++ ++static int print_simple(struct action_util *au, FILE * f, struct rtattr *arg) ++{ ++ struct tc_defact *sel; ++ struct rtattr *tb[TCA_DEF_MAX + 1]; ++ char *simpdata; ++ ++ if (arg == NULL) ++ return -1; ++ ++ parse_rtattr_nested(tb, TCA_DEF_MAX, arg); ++ ++ if (tb[TCA_DEF_PARMS] == NULL) { ++ fprintf(f, "[NULL simple parameters]"); ++ return -1; ++ } ++ sel = RTA_DATA(tb[TCA_DEF_PARMS]); ++ ++ if (tb[TCA_DEF_DATA] == NULL) { ++ fprintf(f, "[missing simple string]"); ++ return -1; ++ } ++ ++ simpdata = RTA_DATA(tb[TCA_DEF_DATA]); ++ ++ fprintf(f, "Simple <%s>\n", simpdata); ++ fprintf(f, "\t index %d ref %d bind %d", sel->index, ++ sel->refcnt, sel->bindcnt); ++ ++ if (show_stats) { ++ if (tb[TCA_DEF_TM]) { ++ struct tcf_t *tm = RTA_DATA(tb[TCA_DEF_TM]); ++ print_tm(f, tm); ++ fprintf(f, "\n"); ++ } ++ } ++ ++ return 0; ++} ++ ++struct action_util simple_action_util = { ++ .id = "simple", ++ .parse_aopt = parse_simple, ++ .print_aopt = print_simple, ++}; +-- +1.8.3.1 + diff --git a/SOURCES/0125-simple-print-newline.patch b/SOURCES/0125-simple-print-newline.patch new file mode 100644 index 0000000..fd00636 --- /dev/null +++ b/SOURCES/0125-simple-print-newline.patch @@ -0,0 +1,47 @@ +From 2928f0b53aa26bf304a5ecc0b0339213c0046f7f Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Fri, 11 Mar 2016 15:37:57 +0100 +Subject: [PATCH] simple print newline + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1315930 +Upstream Status: iproute2.git commit 352f6f97bef6b + +commit 352f6f97bef6baefa21d973b914a67e7feac3d8f +Author: Jamal Hadi Salim <jhs@mojatatu.com> +Date: Sun Dec 22 07:50:09 2013 -0500 + + simple print newline + + attached. + + cheers, + jamal + commit d7869e6167c3553e93e254940b0647032b40fed8 + Author: Jamal Hadi Salim <jhs@mojatatu.com> + Date: Sun Dec 22 07:46:28 2013 -0500 + + print new line at the end for aesthetics + + Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com> +--- + tc/m_simple.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tc/m_simple.c b/tc/m_simple.c +index 0224440..a8e1d6b 100644 +--- a/tc/m_simple.c ++++ b/tc/m_simple.c +@@ -188,9 +188,9 @@ static int print_simple(struct action_util *au, FILE * f, struct rtattr *arg) + if (tb[TCA_DEF_TM]) { + struct tcf_t *tm = RTA_DATA(tb[TCA_DEF_TM]); + print_tm(f, tm); +- fprintf(f, "\n"); + } + } ++ fprintf(f, "\n"); + + return 0; + } +-- +1.8.3.1 + diff --git a/SOURCES/0126-tc-minor-spelling-fixes.patch b/SOURCES/0126-tc-minor-spelling-fixes.patch new file mode 100644 index 0000000..f25c1d2 --- /dev/null +++ b/SOURCES/0126-tc-minor-spelling-fixes.patch @@ -0,0 +1,56 @@ +From 360643aed5b1cc553dbcfb34276ef1ad5589e7bf Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Fri, 11 Mar 2016 15:38:09 +0100 +Subject: [PATCH] tc: minor spelling fixes + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1315930 +Upstream Status: iproute2.git commit b2e116d6c395a + +commit b2e116d6c395ad079c0c488f22a7be06efad0102 +Author: Stephen Hemminger <shemming@brocade.com> +Date: Wed Dec 3 19:28:34 2014 -0800 + + tc: minor spelling fixes +--- + tc/m_simple.c | 2 +- + tc/m_xt.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tc/m_simple.c b/tc/m_simple.c +index a8e1d6b..b61aca7 100644 +--- a/tc/m_simple.c ++++ b/tc/m_simple.c +@@ -8,7 +8,7 @@ + * + * Authors: J Hadi Salim <jhs@mojatatu.com> + * +- * Pedagogical example. Adds a string that will be printed everytime ++ * Pedagogical example. Adds a string that will be printed every time + * the simple instance is hit. + * Use this as a skeleton action and keep modifying it to meet your needs. + * Look at linux/tc_act/tc_defact.h for the different components ids and +diff --git a/tc/m_xt.c b/tc/m_xt.c +index 48aac90..537daf8 100644 +--- a/tc/m_xt.c ++++ b/tc/m_xt.c +@@ -175,7 +175,7 @@ static int parse_ipt(struct action_util *a,int *argc_p, + &m->option_offset); + #endif + if (opts == NULL) { +- fprintf(stderr, " failed to find aditional options for target %s\n\n", optarg); ++ fprintf(stderr, " failed to find additional options for target %s\n\n", optarg); + return -1; + } else + tcipt_globals.opts = opts; +@@ -346,7 +346,7 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg) + &m->option_offset); + #endif + if (opts == NULL) { +- fprintf(stderr, " failed to find aditional options for target %s\n\n", optarg); ++ fprintf(stderr, " failed to find additional options for target %s\n\n", optarg); + return -1; + } else + tmp_tcipt_globals.opts = opts; +-- +1.8.3.1 + diff --git a/SOURCES/0127-whitespace-cleanup.patch b/SOURCES/0127-whitespace-cleanup.patch new file mode 100644 index 0000000..5932007 --- /dev/null +++ b/SOURCES/0127-whitespace-cleanup.patch @@ -0,0 +1,99 @@ +From efa905c6b20db4486e9ee6ab991ecfcd7a04ce63 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Fri, 11 Mar 2016 15:38:15 +0100 +Subject: [PATCH] whitespace cleanup + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1315930 +Upstream Status: iproute2.git commit 3d0b7439dfac9 +Conflicts: Just picking changes to tc/m_simple.c + +commit 3d0b7439dfac96d93386295a4c961b89bd3d8463 +Author: Stephen Hemminger <shemming@brocade.com> +Date: Sat Dec 20 15:47:17 2014 -0800 + + whitespace cleanup + + Remove all trailing whitespace and space before tabs. +--- + tc/m_simple.c | 38 +++++++++++++++++++------------------- + 1 file changed, 19 insertions(+), 19 deletions(-) + +diff --git a/tc/m_simple.c b/tc/m_simple.c +index b61aca7..866552f 100644 +--- a/tc/m_simple.c ++++ b/tc/m_simple.c +@@ -9,7 +9,7 @@ + * Authors: J Hadi Salim <jhs@mojatatu.com> + * + * Pedagogical example. Adds a string that will be printed every time +- * the simple instance is hit. ++ * the simple instance is hit. + * Use this as a skeleton action and keep modifying it to meet your needs. + * Look at linux/tc_act/tc_defact.h for the different components ids and + * definitions used in this actions +@@ -26,20 +26,20 @@ + * + hadi@noma1:$ tc qdisc add dev eth0 ingress + hadi@noma1:$tc filter add dev eth0 parent ffff: protocol ip prio 5 \ +- u32 match ip protocol 1 0xff flowid 1:1 action simple "Incoming ICMP" +- ++ u32 match ip protocol 1 0xff flowid 1:1 action simple "Incoming ICMP" ++ + hadi@noma1:$ sudo tc -s filter ls dev eth0 parent ffff: +- filter protocol ip pref 5 u32 +- filter protocol ip pref 5 u32 fh 800: ht divisor 1 +- filter protocol ip pref 5 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 ++ filter protocol ip pref 5 u32 ++ filter protocol ip pref 5 u32 fh 800: ht divisor 1 ++ filter protocol ip pref 5 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 + match 00010000/00ff0000 at 8 +- action order 1: Simple <Incoming ICMP> +- index 4 ref 1 bind 1 installed 29 sec used 29 sec +- Action statistics: +- Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) +- backlog 0b 0p requeues 0 +- +- ++ action order 1: Simple <Incoming ICMP> ++ index 4 ref 1 bind 1 installed 29 sec used 29 sec ++ Action statistics: ++ Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) ++ backlog 0b 0p requeues 0 ++ ++ + hadi@noma1$ ping -c 1 www.google.ca + PING www.google.ca (74.125.225.120) 56(84) bytes of data. + 64 bytes from ord08s08-in-f24.1e100.net (74.125.225.120): icmp_req=1 ttl=53 time=31.3 ms +@@ -52,15 +52,15 @@ + [135354.473951] simple: Incoming ICMP_1 + + hadi@noma1$ sudo tc/tc -s filter ls dev eth0 parent ffff: +- filter protocol ip pref 5 u32 +- filter protocol ip pref 5 u32 fh 800: ht divisor 1 +- filter protocol ip pref 5 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 ++ filter protocol ip pref 5 u32 ++ filter protocol ip pref 5 u32 fh 800: ht divisor 1 ++ filter protocol ip pref 5 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 + match 00010000/00ff0000 at 8 + action order 1: Simple <Incoming ICMP> + index 4 ref 1 bind 1 installed 206 sec used 67 sec + Action statistics: +- Sent 84 bytes 1 pkt (dropped 0, overlimits 0 requeues 0) +- backlog 0b 0p requeues 0 ++ Sent 84 bytes 1 pkt (dropped 0, overlimits 0 requeues 0) ++ backlog 0b 0p requeues 0 + */ + + #include <stdio.h> +@@ -82,7 +82,7 @@ + static void explain(void) + { + fprintf(stderr, "Usage: ... simple STRING\n" +- "STRING being an arbitrary string\n" ++ "STRING being an arbitrary string\n" + "example: \"simple blah\"\n"); + } + +-- +1.8.3.1 + diff --git a/SOURCES/0128-tc-fix-compilation-warning-on-32bits-arch.patch b/SOURCES/0128-tc-fix-compilation-warning-on-32bits-arch.patch new file mode 100644 index 0000000..9aa8553 --- /dev/null +++ b/SOURCES/0128-tc-fix-compilation-warning-on-32bits-arch.patch @@ -0,0 +1,44 @@ +From 9733ef83d303d0bbc45b96fa22c4f22d990fdcd0 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Fri, 11 Mar 2016 15:38:41 +0100 +Subject: [PATCH] tc: fix compilation warning on 32bits arch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1315930 +Upstream Status: iproute2.git commit afa5158f02024 + +commit afa5158f02024ea9ac71a4bb262670bba17aebcd +Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> +Date: Wed Apr 22 10:27:05 2015 +0200 + + tc: fix compilation warning on 32bits arch + + The warning was: + m_simple.c: In function ‘parse_simple’: + m_simple.c:142:4: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 3 has type ‘size_t’ [-Wformat] + + Useful to be able to compile with -Werror. + + Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> +--- + tc/m_simple.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tc/m_simple.c b/tc/m_simple.c +index 866552f..1ad5526 100644 +--- a/tc/m_simple.c ++++ b/tc/m_simple.c +@@ -138,7 +138,7 @@ parse_simple(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, + } + + if (strlen(simpdata) > (SIMP_MAX_DATA - 1)) { +- fprintf(stderr, "simple: Illegal string len %ld <%s> \n", ++ fprintf(stderr, "simple: Illegal string len %zu <%s> \n", + strlen(simpdata), simpdata); + return -1; + } +-- +1.8.3.1 + diff --git a/SOURCES/0129-man-Add-a-man-page-for-the-csum-action.patch b/SOURCES/0129-man-Add-a-man-page-for-the-csum-action.patch new file mode 100644 index 0000000..71e4cea --- /dev/null +++ b/SOURCES/0129-man-Add-a-man-page-for-the-csum-action.patch @@ -0,0 +1,84 @@ +From e7ba7a30f2e02c4666d7d41366e6a2077df1938d Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:43:19 +0200 +Subject: [PATCH] man: Add a man page for the csum action. + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit 438dd1d49d71b + +commit 438dd1d49d71b5d19f51637c50005f11755558dc +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 13:11:37 2016 +0100 + + man: Add a man page for the csum action. + + Cc: Gregoire Baron <baronchon@n7mm.org> + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/tc-csum.8 | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 54 insertions(+) + create mode 100644 man/man8/tc-csum.8 + +diff --git a/man/man8/tc-csum.8 b/man/man8/tc-csum.8 +new file mode 100644 +index 0000000..9d00aae +--- /dev/null ++++ b/man/man8/tc-csum.8 +@@ -0,0 +1,54 @@ ++.TH "Checksum action in tc" 8 "11 Jan 2015" "iproute2" "Linux" ++ ++.SH NAME ++csum - checksum update action ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " ... " "action csum" ++.I UPDATE ++ ++.ti -8 ++.IR UPDATE " := " TARGET " [ " UPDATE " ]" ++ ++.ti -8 ++.IR TARGET " := { " ++.BR ip4h " |" ++.BR icmp " |" ++.BR igmp " |" ++.BR tcp " |" ++.BR udp " |" ++.BR udplite " |" ++.IR SWEETS " }" ++ ++.ti -8 ++.IR SWEETS " := { " ++.BR and " | " or " | " + " }" ++.SH DESCRIPTION ++The ++.B csum ++action triggers checksum recalculation of specified packet headers. It is ++commonly used after packet editing using the ++.B pedit ++action to fix for then incorrect checksums. ++.SH OPTIONS ++.TP ++.I TARGET ++Specify which headers to update: IPv4 header ++.RB ( ip4h ), ++ICMP header ++.RB ( icmp ), ++IGMP header ++.RB ( igmp ), ++TCP header ++.RB ( tcp ), ++UDP header ++.RB ( udp ") or" ++UDPLite header ++.RB ( udplite ). ++.TP ++.B SWEETS ++These are merely syntactic sugar and ignored internally. ++.SH SEE ALSO ++.BR tc (8), ++.BR tc-pedit (8) +-- +1.8.3.1 + diff --git a/SOURCES/0130-man-Add-a-man-page-for-the-mirred-action.patch b/SOURCES/0130-man-Add-a-man-page-for-the-mirred-action.patch new file mode 100644 index 0000000..4145351 --- /dev/null +++ b/SOURCES/0130-man-Add-a-man-page-for-the-mirred-action.patch @@ -0,0 +1,118 @@ +From c38162b8ca4f45f08a99d4aaa44a0e43eb5da54f Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:43:19 +0200 +Subject: [PATCH] man: Add a man page for the mirred action + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit 61d74eed701f8 + +commit 61d74eed701f8a54c9f0c549cbad0722e53482ff +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 13:11:38 2016 +0100 + + man: Add a man page for the mirred action + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/tc-mirred.8 | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 89 insertions(+) + create mode 100644 man/man8/tc-mirred.8 + +diff --git a/man/man8/tc-mirred.8 b/man/man8/tc-mirred.8 +new file mode 100644 +index 0000000..52d98bc +--- /dev/null ++++ b/man/man8/tc-mirred.8 +@@ -0,0 +1,89 @@ ++.TH "Mirror/redirect action in tc" 8 "11 Jan 2015" "iproute2" "Linux" ++ ++.SH NAME ++mirred - mirror/redirect action ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " ... " "action mirred" ++.I DIRECTION ACTION ++.RB "[ " index ++.IR INDEX " ] " ++.BI dev " DEVICENAME" ++ ++.ti -8 ++.IR DIRECTION " := { " ++.BR ingress " | " egress " }" ++ ++.ti -8 ++.IR ACTION " := { " ++.BR mirror " | " redirect " }" ++.SH DESCRIPTION ++The ++.B mirred ++action allows to redirect or mirror packets to another network interface on the ++same system. It is typically used in combination with the ++.B ifb ++pseudo device to create a shrared instance where QoS happens, but serves well ++for debugging or monitoring purposes, too. ++.SH OPTIONS ++.TP ++.B ingress ++.TQ ++.B egress ++Specify the direction in which the packet shall appear on the destination ++interface. Currently only ++.B egress ++is implemented. ++.TP ++.B mirror ++.TQ ++.B redirect ++Define whether the packet should be copied ++.RB ( mirror ) ++or moved ++.RB ( redirect ) ++to the destination interface. ++.TP ++.BI index " INDEX" ++Assign a unique ID to this action instead of letting the kernel choose one ++automatically. ++.I INDEX ++is a 32bit unsigned integer greater than zero. ++.TP ++.BI dev " DEVICENAME" ++Specify the network interface to redirect or mirror to. ++.SH EXAMPLES ++Limit ingress bandwidth on eth0 to 1mbit/s, redirect exceeding traffic to lo for ++debugging purposes: ++ ++.RS ++.EX ++# tc qdisc add dev eth0 handle ffff: ingress ++# tc filter add dev eth0 parent ffff: u32 \\ ++ match u32 0 0 \\ ++ action police rate 1mbit burst 100k conform-exceed pipe \\ ++ action mirred egress redirect dev lo ++.EE ++.RE ++ ++Use an ++.B ifb ++interface to send ingress traffic on eth0 through an instance of ++.BR sfq : ++ ++.RS ++.EX ++# modprobe ifb ++# ip link set ifb0 up ++# tc qdisc add dev ifb0 root sfq ++# tc qdisc add dev eth0 handle ffff: ingress ++# tc filter add dev eth0 parent ffff: u32 \\ ++ match u32 0 0 \\ ++ action mirred egress redirect dev ifb0 ++.EE ++.RE ++ ++.SH SEE ALSO ++.BR tc (8), ++.BR tc-u32 (8) +-- +1.8.3.1 + diff --git a/SOURCES/0131-man-Add-a-man-page-for-the-nat-action.patch b/SOURCES/0131-man-Add-a-man-page-for-the-nat-action.patch new file mode 100644 index 0000000..b9cccc1 --- /dev/null +++ b/SOURCES/0131-man-Add-a-man-page-for-the-nat-action.patch @@ -0,0 +1,108 @@ +From 4670c581d7173b300d30eedfc6a4ddbf504011bd Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:43:19 +0200 +Subject: [PATCH] man: Add a man page for the nat action + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit ec0bab1e028a9 + +commit ec0bab1e028a9a8178ae18c4fa6ca600dcf167ba +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 13:11:39 2016 +0100 + + man: Add a man page for the nat action + + Cc: Herbert Xu <herbert@gondor.apana.org.au> + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/tc-nat.8 | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 78 insertions(+) + create mode 100644 man/man8/tc-nat.8 + +diff --git a/man/man8/tc-nat.8 b/man/man8/tc-nat.8 +new file mode 100644 +index 0000000..fdcc052 +--- /dev/null ++++ b/man/man8/tc-nat.8 +@@ -0,0 +1,78 @@ ++.TH "NAT action in tc" 8 "12 Jan 2015" "iproute2" "Linux" ++ ++.SH NAME ++nat - stateless native address translation action ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " ... " "action nat" ++.I DIRECTION OLD NEW ++ ++.ti -8 ++.IR DIRECTION " := { " ++.BR ingress " | " egress " }" ++ ++.ti -8 ++.IR OLD " := " IPV4_ADDR_SPEC ++ ++.ti -8 ++.IR NEW " := " IPV4_ADDR_SPEC ++ ++.ti -8 ++.IR IPV4_ADDR_SPEC " := { " ++.BR default " | " any " | " all " | " ++\fIin_addr\fR[\fB/\fR{\fIprefix\fR|\fInetmask\fR}] ++.SH DESCRIPTION ++The ++.B nat ++action allows to perform NAT without the overhead of conntrack, which is ++desirable if the number of flows or addresses to perform NAT on is large. This ++action is best used in combination with the ++.B u32 ++filter to allow for efficient lookups of a large number of stateless NAT rules ++in constant time. ++.SH OPTIONS ++.TP ++.B ingress ++Translate destination addresses, i.e. perform DNAT. ++.TP ++.B egress ++Translate source addresses, i.e. perform SNAT. ++.TP ++.I OLD ++Specifies addresses which should be translated. ++.TP ++.I NEW ++Specifies addresses which ++.I OLD ++should be translated into. ++.SH NOTES ++The accepted address format in ++.IR OLD " and " NEW ++is quite flexible. It may either consist of one of the keywords ++.BR default ", " any " or " all , ++representing the all-zero IP address or a combination of IP address and netmask ++or prefix length separated by a slash ++.RB ( / ) ++sign. In any case, the mask (or prefix length) value of ++.I OLD ++is used for ++.I NEW ++as well so that a one-to-one mapping of addresses is assured. ++ ++Address translation is done using a combination of binary operations. First, the ++original (source or destination) address is matched against the value of ++.IR OLD . ++If the original address fits, the new address is created by taking the leading ++bits from ++.I NEW ++(defined by the netmask of ++.IR OLD ) ++and taking the remaining bits from the original address. ++ ++There is rudimental support for upper layer protocols, namely TCP, UDP and ICMP. ++While for the first two only checksum recalculation is performed, the action ++also takes care of embedded IP headers in ICMP packets by translating the ++respective address therein, too. ++.SH SEE ALSO ++.BR tc (8) +-- +1.8.3.1 + diff --git a/SOURCES/0132-man-Add-a-man-page-for-the-pedit-action.patch b/SOURCES/0132-man-Add-a-man-page-for-the-pedit-action.patch new file mode 100644 index 0000000..ac4171f --- /dev/null +++ b/SOURCES/0132-man-Add-a-man-page-for-the-pedit-action.patch @@ -0,0 +1,259 @@ +From be321a9a9608a4e9b85b5d1ab6606687a8a90cb0 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:43:19 +0200 +Subject: [PATCH] man: Add a man page for the pedit action + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit 448800026ff71 + +commit 448800026ff7189f297233c6588457a7e9770183 +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 13:11:40 2016 +0100 + + man: Add a man page for the pedit action + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/tc-pedit.8 | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 230 insertions(+) + create mode 100644 man/man8/tc-pedit.8 + +diff --git a/man/man8/tc-pedit.8 b/man/man8/tc-pedit.8 +new file mode 100644 +index 0000000..c30927e +--- /dev/null ++++ b/man/man8/tc-pedit.8 +@@ -0,0 +1,230 @@ ++.TH "Generic packet editor action in tc" 8 "12 Jan 2015" "iproute2" "Linux" ++ ++.SH NAME ++pedit - generic packet editor action ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " ... " "action pedit munge " { ++.IR RAW_OP " | " LAYERED_OP " } [ " BRANCH " ]" ++ ++.ti -8 ++.IR RAW_OP " := " ++.BI offset " OFFSET" ++.RB "{ " u8 " | " u16 " | " u32 " } [" ++.IR AT_SPEC " ] " CMD_SPEC ++ ++.ti -8 ++.IR AT_SPEC " := " ++.BI at " AT " offmask " MASK " shift " SHIFT" ++ ++.ti -8 ++.IR LAYERED_OP " := { " ++.BI ip " IPHDR_FIELD" ++| ++.BI ip6 " IP6HDR_FIELD" ++| ++.BI udp " UDPHDR_FIELD" ++| ++.BI tcp " TCPHDR_FIELD" ++| ++.BI icmp " ICMPHDR_FIELD" ++.RI } " CMD_SPEC" ++ ++.ti -8 ++.IR IPHDR_FIELD " := { " ++.BR src " | " dst " | " tos " | " dsfield " | " ihl " | " protocol " |" ++.BR precedence " | " nofrag " | " firstfrag " | " ce " | " df " |" ++.BR mf " | " dport " | " sport " | " icmp_type " | " icmp_code " }" ++ ++.ti -8 ++.IR CMD_SPEC " := {" ++.BR clear " | " invert " | " set ++.IR VAL " | " ++.BR preserve " } [ " retain ++.IR RVAL " ]" ++ ++.ti -8 ++.IR BRANCH " := {" ++.BR reclassify " | " pipe " | " drop " | " shot " | " continue " | " pass " }" ++.SH DESCRIPTION ++The ++.B pedit ++action can be used to change arbitrary packet data. The location of data to ++change can either be specified by giving an offset and size as in ++.IR RAW_OP , ++or for header values by naming the header and field to edit the size is then ++chosen automatically based on the header field size. Currently this is supported ++only for IPv4 headers. ++.SH OPTIONS ++.TP ++.BI offset " OFFSET " "\fR{ \fBu32 \fR| \fBu16 \fR| \fBu8 \fR}" ++Specify the offset at which to change data. ++.I OFFSET ++is a signed integer, it's base is automatically chosen (e.g. hex if prefixed by ++.B 0x ++or octal if prefixed by ++.BR 0 ). ++The second argument specifies the length of data to change, that is four bytes ++.RB ( u32 ), ++two bytes ++.RB ( u16 ) ++or a single byte ++.RB ( u8 ). ++.TP ++.BI at " AT " offmask " MASK " shift " SHIFT" ++This is an optional part of ++.IR RAW_OP ++which allows to have a variable ++.I OFFSET ++depending on packet data at offset ++.IR AT , ++which is binary ANDed with ++.I MASK ++and right-shifted by ++.I SHIFT ++before adding it to ++.IR OFFSET . ++.TP ++.BI ip " IPHDR_FIELD" ++Change an IPv4 header field. The supported keywords for ++.I IPHDR_FIELD ++are: ++.RS ++.TP ++.B src ++.TQ ++.B dst ++Source or destination IP address, a four-byte value. ++.TP ++.B tos ++.TQ ++.B dsfield ++.TQ ++.B precedence ++Type Of Service field, an eight-bit value. ++.TP ++.B ihl ++Change the IP Header Length field, a four-bit value. ++.TP ++.B protocol ++Next-layer Protocol field, an eight-bit value. ++.TP ++.B nofrag ++.TQ ++.B firstfrag ++.TQ ++.B ce ++.TQ ++.B df ++.TQ ++.B mf ++Change IP header flags. Note that the value to pass to the ++.B set ++command is not just a bit value, but the full byte including the flags field. ++Though only the relevant bits of that value are respected, the rest ignored. ++.TP ++.B dport ++.TQ ++.B sport ++Destination or source port numbers, a 16-bit value. Indeed, IPv4 headers don't ++contain this information. Instead, this will set an offset which suits at least ++TCP and UDP if the IP header is of minimum size (20 bytes). If not, this will do ++unexpected things. ++.TP ++.B icmp_type ++.TQ ++.B icmp_code ++Again, this allows to change data past the actual IP header itself. It assumes ++an ICMP header is present immediately following the (minimal sized) IP header. ++If it is not or the latter is bigger than the minimum of 20 bytes, this will do ++unexpected things. These fields are eight-bit values. ++.RE ++.TP ++.B clear ++Clear the addressed data (i.e., set it to zero). ++.TP ++.B invert ++Swap every bit in the addressed data. ++.TP ++.BI set " VAL" ++Set the addressed data to a specific value. The size of ++.I VAL ++is defined by either one of the ++.BR u32 ", " u16 " or " u8 ++keywords in ++.IR RAW_OP , ++or the size of the addressed header field in ++.IR LAYERED_OP . ++.TP ++.B preserve ++Keep the addressed data as is. ++.TP ++.BI retain " RVAL" ++This optional extra part of ++.I CMD_SPEC ++allows to exclude bits from being changed. ++.TP ++.I BRANCH ++The following keywords allow to control how the tree of qdisc, classes, ++filters and actions is further traversed after this action. ++.RS ++.TP ++.B reclassify ++Restart with the first filter in the current list. ++.TP ++.B pipe ++Continue with the next action attached to the same filter. ++.TP ++.B drop ++.TQ ++.B shot ++Drop the packet. ++.TP ++.B continue ++Continue classification with the next filter in line. ++.TP ++.B pass ++Finish classification process and return to calling qdisc for further packet ++processing. This is the default. ++.RE ++.SH EXAMPLES ++Being able to edit packet data, one could do all kinds of things, such as e.g. ++implementing port redirection. Certainly not the most useful application, but ++as an example it should do: ++ ++First, qdiscs need to be set up to attach filters to. For the receive path, a simple ++.B ingress ++qdisc will do, for transmit path a classful qdisc ++.RB ( HTB ++in this case) is necessary: ++ ++.RS ++.EX ++tc qdisc replace dev eth0 root handle 1: htb ++tc qdisc add dev eth0 ingress handle ffff: ++.EE ++.RE ++ ++Finally, a filter with ++.B pedit ++action can be added for each direction. In this case, ++.B u32 ++is used matching on the port number to redirect from, while ++.B pedit ++then does the actual rewriting: ++ ++.RS ++.EX ++tc filter add dev eth0 parent 1: u32 \\ ++ match ip dport 23 0xffff \\ ++ action pedit pedit munge ip dport set 22 ++tc filter add dev eth0 parent ffff: u32 \\ ++ match ip sport 22 0xffff \\ ++ action pedit pedit munge ip sport set 23 ++.EE ++.RE ++.SH SEE ALSO ++.BR tc (8), ++.BR tc-htb (8), ++.BR tc-u32 (8) +-- +1.8.3.1 + diff --git a/SOURCES/0133-man-Add-a-man-page-for-the-police-action.patch b/SOURCES/0133-man-Add-a-man-page-for-the-police-action.patch new file mode 100644 index 0000000..c441951 --- /dev/null +++ b/SOURCES/0133-man-Add-a-man-page-for-the-police-action.patch @@ -0,0 +1,157 @@ +From dbe2324f84ce589c8fbef01af614cfd80c650483 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:43:19 +0200 +Subject: [PATCH] man: Add a man page for the police action + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit d477eea5a6dcb + +commit d477eea5a6dcb1fe42f8106f2172eaced379eabc +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 13:11:41 2016 +0100 + + man: Add a man page for the police action + + Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/tc-police.8 | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 127 insertions(+) + create mode 100644 man/man8/tc-police.8 + +diff --git a/man/man8/tc-police.8 b/man/man8/tc-police.8 +new file mode 100644 +index 0000000..2b1537e +--- /dev/null ++++ b/man/man8/tc-police.8 +@@ -0,0 +1,127 @@ ++.TH "Policing action in tc" 8 "20 Jan 2015" "iproute2" "Linux" ++ ++.SH NAME ++police - policing action ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " ... " "action police" ++.BI rate " RATE " burst ++.IR BYTES [\fB/ BYTES "] [" ++.B mtu ++.IR BYTES [\fB/ BYTES "] ] [" ++.BI peakrate " RATE" ++] [ ++.BI avrate " RATE" ++] [ ++.BI overhead " BYTES" ++] [ ++.BI linklayer " TYPE" ++] [ ++.BI conform-exceed " EXCEEDACT\fR[\fB/\fIEXCEEDACT\fR]" ++ ++.ti -8 ++.IR EXCEEDACT " := { " ++.BR pipe " | " ok " | " reclassify " | " drop " | " continue " }" ++.SH DESCRIPTION ++The ++.B police ++action allows to limit bandwidth of traffic matched by the filter it is ++attached to. ++.SH OPTIONS ++.TP ++.BI rate " RATE" ++The maximum traffic rate of packets passing this action. Those exceeding it will ++be treated as defined by the ++.B conform-exceed ++option. ++.TP ++.BI burst " BYTES\fR[\fB/\fIBYTES\fR]" ++Set the maximum allowed burst in bytes, optionally followed by a slash ('/') ++sign and cell size which must be a power of 2. ++.TP ++.BI mtu " BYTES\fR[\fB/\fIBYTES\fR]" ++This is the maximum packet size handled by the policer (larger ones will be ++handled like they exceeded the configured rate). Setting this value correctly ++will improve the scheduler's precision. ++Value formatting is identical to ++.B burst ++above. Defaults to unlimited. ++.TP ++.BI peakrate " RATE" ++Set the maximum bucket depletion rate, exceeding ++.BR rate . ++.TP ++.BI avrate " RATE" ++Make use of an in-kernel bandwidth rate estimator and match the given ++.I RATE ++against it. ++.TP ++.BI overhead " BYTES" ++Account for protocol overhead of encapsulating output devices when computing ++.BR rate " and " peakrate . ++.TP ++.BI linklayer " TYPE" ++Specify the link layer type. ++.I TYPE ++may be one of ++.B ethernet ++(the default), ++.BR atm " or " adsl ++(which are synonyms). It is used to align the precomputed rate tables to ATM ++cell sizes, for ++.B ethernet ++no action is taken. ++.TP ++.BI conform-exceed " EXCEEDACT\fR[\fB/\fIEXCEEDACT\fR]" ++Define how to handle packets which exceed (and, if the second ++.I EXCEEDACT ++is given, also those who don't), the configured bandwidth limit. Possible values ++are: ++.RS ++.IP continue ++Don't do anything, just continue with the next action in line. ++.IP drop ++Drop the packet immediately. ++.IP shot ++This is a synonym to ++.BR drop . ++.IP ok ++Accept the packet. This is the default for conforming packets. ++.IP pass ++This is a synonym to ++.BR ok . ++.IP reclassify ++Treat the packet as non-matching to the filter this action is attached to and ++continue with the next filter in line (if any). This is the default for ++exceeding packets. ++.IP pipe ++Pass the packet to the next action in line. ++.SH EXAMPLES ++A typical application of the police action is to enforce ingress traffic rate ++by dropping exceeding packets. Although better done on the sender's side, ++especially in scenarios with lack of peer control (e.g. with dial-up providers) ++this is often the best one can do in order to keep latencies low under high ++load. The following establishes input bandwidth policing to 1mbit/s using the ++.B ingress ++qdisc and ++.B u32 ++filter: ++ ++.RS ++.EX ++# tc qdisc add dev eth0 handle ffff: ingress ++# tc filter add dev eth0 parent ffff: u32 \\ ++ match u32 0 0 \\ ++ police rate 1mbit burst 100k ++.EE ++.RE ++ ++As an action can not live on it's own, there always has to be a filter involved as link between qdisc and action. The example above uses ++.B u32 ++for that, which is configured to effectively match any packet (passing it to the ++.B police ++action thereby). ++ ++.SH SEE ALSO ++.BR tc (8) +-- +1.8.3.1 + diff --git a/SOURCES/0134-man-Add-a-man-page-for-the-simple-action.patch b/SOURCES/0134-man-Add-a-man-page-for-the-simple-action.patch new file mode 100644 index 0000000..6bb931c --- /dev/null +++ b/SOURCES/0134-man-Add-a-man-page-for-the-simple-action.patch @@ -0,0 +1,105 @@ +From a97f29e69b11276cc18793cd696614c367ffc806 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:43:19 +0200 +Subject: [PATCH] man: Add a man page for the simple action + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit ebf9933bb3d5c + +commit ebf9933bb3d5c6a869edb7405f7a4759862409ab +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 13:11:42 2016 +0100 + + man: Add a man page for the simple action + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/tc-simple.8 | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 76 insertions(+) + create mode 100644 man/man8/tc-simple.8 + +diff --git a/man/man8/tc-simple.8 b/man/man8/tc-simple.8 +new file mode 100644 +index 0000000..2206dc3 +--- /dev/null ++++ b/man/man8/tc-simple.8 +@@ -0,0 +1,76 @@ ++.TH "Simple action in tc" 8 "12 Jan 2015" "iproute2" "Linux" ++ ++.SH NAME ++simple - basic example action ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " ... " "action simple" ++.I STRING ++.SH DESCRIPTION ++This is a pedagogical example rather than an actually useful action. Upon every access, it prints the given ++.I STRING ++which may be of arbitrary length. ++.SH OPTIONS ++.TP ++.I STRING ++The actual string to print. ++.SH EXAMPLES ++The following example makes the kernel yell "Incoming ICMP!" every time it sees ++an incoming ICMP on eth0. Steps are: ++.IP 1) 4 ++Add an ingress qdisc point to eth0 ++.IP 2) 4 ++Start a chain on ingress of eth0 that first matches ICMP then invokes the ++simple action to shout. ++.IP 3) 4 ++display stats and show that no packet has been seen by the action ++.IP 4) 4 ++Send one ping packet to google (expect to receive a response back) ++.IP 5) 4 ++grep the logs to see the logged message ++.IP 6) 4 ++display stats again and observe increment by 1 ++ ++.RE ++.EX ++ hadi@noma1:$ tc qdisc add dev eth0 ingress ++ hadi@noma1:$tc filter add dev eth0 parent ffff: protocol ip prio 5 \\ ++ u32 match ip protocol 1 0xff flowid 1:1 action simple "Incoming ICMP" ++ ++ hadi@noma1:$ sudo tc -s filter ls dev eth0 parent ffff: ++ filter protocol ip pref 5 u32 ++ filter protocol ip pref 5 u32 fh 800: ht divisor 1 ++ filter protocol ip pref 5 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 ++ match 00010000/00ff0000 at 8 ++ action order 1: Simple <Incoming ICMP> ++ index 4 ref 1 bind 1 installed 29 sec used 29 sec ++ Action statistics: ++ Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) ++ backlog 0b 0p requeues 0 ++ ++ ++ hadi@noma1$ ping -c 1 www.google.ca ++ PING www.google.ca (74.125.225.120) 56(84) bytes of data. ++ 64 bytes from ord08s08-in-f24.1e100.net (74.125.225.120): icmp_req=1 ttl=53 time=31.3 ms ++ ++ --- www.google.ca ping statistics --- ++ 1 packets transmitted, 1 received, 0% packet loss, time 0ms ++ rtt min/avg/max/mdev = 31.316/31.316/31.316/0.000 ms ++ ++ hadi@noma1$ dmesg | grep simple ++ [135354.473951] simple: Incoming ICMP_1 ++ ++ hadi@noma1$ sudo tc/tc -s filter ls dev eth0 parent ffff: ++ filter protocol ip pref 5 u32 ++ filter protocol ip pref 5 u32 fh 800: ht divisor 1 ++ filter protocol ip pref 5 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 ++ match 00010000/00ff0000 at 8 ++ action order 1: Simple <Incoming ICMP> ++ index 4 ref 1 bind 1 installed 206 sec used 67 sec ++ Action statistics: ++ Sent 84 bytes 1 pkt (dropped 0, overlimits 0 requeues 0) ++ backlog 0b 0p requeues 0 ++.EE ++.SH SEE ALSO ++.BR tc (8) +-- +1.8.3.1 + diff --git a/SOURCES/0135-man-Add-a-man-page-for-the-skbedit-action.patch b/SOURCES/0135-man-Add-a-man-page-for-the-skbedit-action.patch new file mode 100644 index 0000000..7982962 --- /dev/null +++ b/SOURCES/0135-man-Add-a-man-page-for-the-skbedit-action.patch @@ -0,0 +1,75 @@ +From 8d3f6c504bcfe6483ab9fb78359b57fc41e0a4ee Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:43:19 +0200 +Subject: [PATCH] man: Add a man page for the skbedit action + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit ae6cf29be0dc6 + +commit ae6cf29be0dc6e1ce237bfe97c12329638c6edac +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 13:11:43 2016 +0100 + + man: Add a man page for the skbedit action + + Cc: Alexander Duyck <alexander.duyck@gmail.com> + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/tc-skbedit.8 | 45 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + create mode 100644 man/man8/tc-skbedit.8 + +diff --git a/man/man8/tc-skbedit.8 b/man/man8/tc-skbedit.8 +new file mode 100644 +index 0000000..b585a4d +--- /dev/null ++++ b/man/man8/tc-skbedit.8 +@@ -0,0 +1,45 @@ ++.TH "SKB editing action in tc" 8 "12 Jan 2015" "iproute2" "Linux" ++ ++.SH NAME ++skbedit - SKB editing action ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " ... " "action skbedit " [ " queue_mapping ++.IR QUEUE_MAPPING " ] [" ++.B priority ++.IR PRIORITY " ] [" ++.B mark ++.IR MARK " ]" ++.SH DESCRIPTION ++The ++.B skbedit ++action allows to change a packet's associated meta data. It complements the ++.B pedit ++action, which in turn allows to change parts of the packet data itself. ++.SH OPTIONS ++.TP ++.BI queue_mapping " QUEUE_MAPPING" ++Override the packet's transmit queue. Useful when applied to packets transmitted ++over MQ-capable network interfaces. ++.I QUEUE_MAPPING ++is an unsigned 16bit value in decimal format. ++.TP ++.BI priority " PRIORITY" ++Override the packet classification decision. ++.I PRIORITY ++is either ++.BR root ", " none ++or a hexadecimal major class ID optionally followed by a colon ++.RB ( : ) ++and a hexadecimal minor class ID. ++.TP ++.BI mark " MARK" ++Change the packet's firewall mark value. ++.I MARK ++is an unsigned 32bit value in automatically detected format (i.e., prefix with ++.RB ' 0x ' ++for hexadecimal interpretation, etc.). ++.SH SEE ALSO ++.BR tc (8), ++.BR tc-pedit (8) +-- +1.8.3.1 + diff --git a/SOURCES/0136-man-Add-a-man-page-for-the-xt-action.patch b/SOURCES/0136-man-Add-a-man-page-for-the-xt-action.patch new file mode 100644 index 0000000..8520e23 --- /dev/null +++ b/SOURCES/0136-man-Add-a-man-page-for-the-xt-action.patch @@ -0,0 +1,72 @@ +From 6d3c3c31c6dae72d87bf2e5a0138291cf4b787cd Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:43:19 +0200 +Subject: [PATCH] man: Add a man page for the xt action + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit fa2c34eff1b89 + +commit fa2c34eff1b89b55b1cdb3c0ed3b29bf8b3d5b40 +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 13:11:45 2016 +0100 + + man: Add a man page for the xt action + + Cc: Jiri Pirko <jiri@resnulli.us> + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/tc-xt.8 | 42 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + create mode 100644 man/man8/tc-xt.8 + +diff --git a/man/man8/tc-xt.8 b/man/man8/tc-xt.8 +new file mode 100644 +index 0000000..4fd800c +--- /dev/null ++++ b/man/man8/tc-xt.8 +@@ -0,0 +1,42 @@ ++.TH "iptables action in tc" 8 "3 Mar 2016" "iproute2" "Linux" ++ ++.SH NAME ++xt - tc iptables action ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR tc " ... " "action xt \-j" ++.IR TARGET " [ " TARGET_OPTS " ]" ++.SH DESCRIPTION ++The ++.B xt ++action allows to call arbitrary iptables targets for packets matching the filter ++this action is attached to. ++.SH OPTIONS ++.TP ++.BI -j " TARGET \fR[\fI TARGET_OPTS \fR]" ++Perform a jump to the given iptables target, optionally passing any target ++specific options in ++.IR TARGET_OPTS . ++.SH EXAMPLES ++The following will attach a ++.B u32 ++filter to the ++.B ingress ++qdisc matching ICMP replies and using the ++.B xt ++action to make the kernel yell 'PONG' each time: ++ ++.RS ++.EX ++tc qdisc add dev eth0 ingress ++tc filter add dev eth0 parent ffff: proto ip u32 \\ ++ match ip protocol 1 0xff \\ ++ match ip icmp_type 0 0xff \\ ++ action xt -j LOG --log-prefix PONG ++.EE ++.RE ++.SH SEE ALSO ++.BR tc (8), ++.BR tc-u32 (8), ++.BR iptables-extensions (8) +-- +1.8.3.1 + diff --git a/SOURCES/0137-man-tc-u32-Minor-syntax-fix.patch b/SOURCES/0137-man-tc-u32-Minor-syntax-fix.patch new file mode 100644 index 0000000..fd30806 --- /dev/null +++ b/SOURCES/0137-man-tc-u32-Minor-syntax-fix.patch @@ -0,0 +1,34 @@ +From e46aa21cf20f6ef05ebe3ef3d95b662a7973f8d6 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:43:19 +0200 +Subject: [PATCH] man: tc-u32: Minor syntax fix + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit b487954d5baf9 + +commit b487954d5baf95b4402456964eaad76dcb54db82 +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 12:52:39 2016 +0100 + + man: tc-u32: Minor syntax fix + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/tc-u32.8 | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/man/man8/tc-u32.8 b/man/man8/tc-u32.8 +index 47c8f2d..691f53c 100644 +--- a/man/man8/tc-u32.8 ++++ b/man/man8/tc-u32.8 +@@ -370,6 +370,7 @@ then allows to match various header fields: + .RS + .TP + .BI src " ADDR" ++.TQ + .BI dst " ADDR" + Compare Source or Destination Address fields against the value of + .IR ADDR . +-- +1.8.3.1 + diff --git a/SOURCES/0138-tc-pedit-document-branch-control-in-help-output.patch b/SOURCES/0138-tc-pedit-document-branch-control-in-help-output.patch new file mode 100644 index 0000000..e785035 --- /dev/null +++ b/SOURCES/0138-tc-pedit-document-branch-control-in-help-output.patch @@ -0,0 +1,46 @@ +From 390c23937283fa848f867481ee60ea96899d4dc8 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:43:20 +0200 +Subject: [PATCH] tc: pedit: document branch control in help output + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit c024acc641428 + +commit c024acc6414285a09107648c9c21a377404b9d45 +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 12:52:37 2016 +0100 + + tc: pedit: document branch control in help output + + This seems to have been a hidden feature, though it's very useful and + necessary at least when combining multiple pedit actions. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + tc/m_pedit.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tc/m_pedit.c b/tc/m_pedit.c +index e89d932..64a3eae 100644 +--- a/tc/m_pedit.c ++++ b/tc/m_pedit.c +@@ -35,7 +35,7 @@ int pedit_debug = 1; + static void + explain(void) + { +- fprintf(stderr, "Usage: ... pedit munge <MUNGE>\n"); ++ fprintf(stderr, "Usage: ... pedit munge <MUNGE> [<BRANCH>]\n"); + fprintf(stderr, + "Where: MUNGE := <RAW>|<LAYERED>\n" + "\t<RAW>:= <OFFSETC>[ATC]<CMD>\n " +@@ -47,6 +47,7 @@ explain(void) + "\t\tCMD:= clear | invert | set <setval>| retain\n " + "\t<LAYERED>:= ip <ipdata> | ip6 <ip6data> \n " + " \t\t| udp <udpdata> | tcp <tcpdata> | icmp <icmpdata> \n" ++ "\t<BRANCH>:= reclassify | pipe | drop | continue | pass\n" + "For Example usage look at the examples directory\n"); + + } +-- +1.8.3.1 + diff --git a/SOURCES/0139-tc-connmark-pedit-Rename-BRANCH-to-CONTROL.patch b/SOURCES/0139-tc-connmark-pedit-Rename-BRANCH-to-CONTROL.patch new file mode 100644 index 0000000..0466933 --- /dev/null +++ b/SOURCES/0139-tc-connmark-pedit-Rename-BRANCH-to-CONTROL.patch @@ -0,0 +1,86 @@ +From edb4ae8d586a471c389d0a5e6a4b42cb5ce2f1a9 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:43:20 +0200 +Subject: [PATCH] tc: connmark, pedit: Rename BRANCH to CONTROL + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit 1672f42195406 +Conflicts: + - Connmark action does not exist in RHEL7. + - Missing commit 32a121cba2579 ("tc: code cleanup") which itself causes + many conflicts. + +commit 1672f42195406d2d4d8fb014b8ea2a59e59f2d6a +Author: Phil Sutter <phil@nwl.cc> +Date: Tue Mar 22 15:48:33 2016 +0100 + + tc: connmark, pedit: Rename BRANCH to CONTROL + + As Jamal suggested, BRANCH is the wrong name, as these keywords go + beyond simple branch control - e.g. loops are possible, too. Therefore + rename the non-terminal to CONTROL instead which should be more + appropriate. + + Signed-off-by: Phil Sutter <phil@nwl.cc> + Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> +--- + man/man8/tc-pedit.8 | 6 +++--- + tc/m_pedit.c | 4 ++-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/man/man8/tc-pedit.8 b/man/man8/tc-pedit.8 +index c30927e..c34520c 100644 +--- a/man/man8/tc-pedit.8 ++++ b/man/man8/tc-pedit.8 +@@ -6,7 +6,7 @@ pedit - generic packet editor action + .in +8 + .ti -8 + .BR tc " ... " "action pedit munge " { +-.IR RAW_OP " | " LAYERED_OP " } [ " BRANCH " ]" ++.IR RAW_OP " | " LAYERED_OP " } [ " CONTROL " ]" + + .ti -8 + .IR RAW_OP " := " +@@ -45,7 +45,7 @@ pedit - generic packet editor action + .IR RVAL " ]" + + .ti -8 +-.IR BRANCH " := {" ++.IR CONTROL " := {" + .BR reclassify " | " pipe " | " drop " | " shot " | " continue " | " pass " }" + .SH DESCRIPTION + The +@@ -165,7 +165,7 @@ This optional extra part of + .I CMD_SPEC + allows to exclude bits from being changed. + .TP +-.I BRANCH ++.I CONTROL + The following keywords allow to control how the tree of qdisc, classes, + filters and actions is further traversed after this action. + .RS +diff --git a/tc/m_pedit.c b/tc/m_pedit.c +index 64a3eae..c8c0264 100644 +--- a/tc/m_pedit.c ++++ b/tc/m_pedit.c +@@ -35,7 +35,7 @@ int pedit_debug = 1; + static void + explain(void) + { +- fprintf(stderr, "Usage: ... pedit munge <MUNGE> [<BRANCH>]\n"); ++ fprintf(stderr, "Usage: ... pedit munge <MUNGE> [CONTROL]\n"); + fprintf(stderr, + "Where: MUNGE := <RAW>|<LAYERED>\n" + "\t<RAW>:= <OFFSETC>[ATC]<CMD>\n " +@@ -47,7 +47,7 @@ explain(void) + "\t\tCMD:= clear | invert | set <setval>| retain\n " + "\t<LAYERED>:= ip <ipdata> | ip6 <ip6data> \n " + " \t\t| udp <udpdata> | tcp <tcpdata> | icmp <icmpdata> \n" +- "\t<BRANCH>:= reclassify | pipe | drop | continue | pass\n" ++ "\tCONTROL:= reclassify | pipe | drop | continue | pass\n" + "For Example usage look at the examples directory\n"); + + } +-- +1.8.3.1 + diff --git a/SOURCES/0140-man-tc-csum.8-Add-an-example.patch b/SOURCES/0140-man-tc-csum.8-Add-an-example.patch new file mode 100644 index 0000000..4636a59 --- /dev/null +++ b/SOURCES/0140-man-tc-csum.8-Add-an-example.patch @@ -0,0 +1,49 @@ +From 40dbf26f8c9369ec6a7be6702cfb54d3d9c198d5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:51:09 +0200 +Subject: [PATCH] man: tc-csum.8: Add an example + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit dbfb17a67f9c7 + +commit dbfb17a67f9c7cf64a38ca734ef638a3f613546c +Author: Phil Sutter <phil@nwl.cc> +Date: Tue Mar 22 15:48:34 2016 +0100 + + man: tc-csum.8: Add an example + + Signed-off-by: Phil Sutter <phil@nwl.cc> + Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> +--- + man/man8/tc-csum.8 | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/man/man8/tc-csum.8 b/man/man8/tc-csum.8 +index 9d00aae..3a64c82 100644 +--- a/man/man8/tc-csum.8 ++++ b/man/man8/tc-csum.8 +@@ -49,6 +49,21 @@ UDPLite header + .TP + .B SWEETS + These are merely syntactic sugar and ignored internally. ++.SH EXAMPLES ++The following performs stateless NAT for incoming packets from 192.168.1.100 to ++new destination 18.52.86.120 (0x12345678 in hex). Assuming these are UDP ++packets, both IP and UDP checksums have to be recalculated: ++ ++.RS ++.EX ++# tc qdisc add dev eth0 ingress handle ffff: ++# tc filter add eth0 prio 1 protocol ip parent ffff: \\ ++ u32 match ip src 192.168.1.100/32 flowid :1 \\ ++ action pedit munge ip dst set 0x12345678 pipe \\ ++ csum ip and udp ++.EE ++.RE ++ + .SH SEE ALSO + .BR tc (8), + .BR tc-pedit (8) +-- +1.8.3.1 + diff --git a/SOURCES/0141-man-tc-mirred.8-Reword-man-page-a-bit-add-generic-mi.patch b/SOURCES/0141-man-tc-mirred.8-Reword-man-page-a-bit-add-generic-mi.patch new file mode 100644 index 0000000..a577a52 --- /dev/null +++ b/SOURCES/0141-man-tc-mirred.8-Reword-man-page-a-bit-add-generic-mi.patch @@ -0,0 +1,69 @@ +From a7a39f89b58da3eb939f7233c23f8eb225826d48 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:51:09 +0200 +Subject: [PATCH] man: tc-mirred.8: Reword man page a bit, add generic mirror + example + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit 26df2953a5c34 + +commit 26df2953a5c34fe03986cbf3466321fd8a3af1c5 +Author: Phil Sutter <phil@nwl.cc> +Date: Tue Mar 22 15:48:35 2016 +0100 + + man: tc-mirred.8: Reword man page a bit, add generic mirror example + + Signed-off-by: Phil Sutter <phil@nwl.cc> + Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> +--- + man/man8/tc-mirred.8 | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/man/man8/tc-mirred.8 b/man/man8/tc-mirred.8 +index 52d98bc..bba96e0 100644 +--- a/man/man8/tc-mirred.8 ++++ b/man/man8/tc-mirred.8 +@@ -21,11 +21,9 @@ mirred - mirror/redirect action + .SH DESCRIPTION + The + .B mirred +-action allows to redirect or mirror packets to another network interface on the +-same system. It is typically used in combination with the +-.B ifb +-pseudo device to create a shrared instance where QoS happens, but serves well +-for debugging or monitoring purposes, too. ++action allows packet mirroring (copying) or redirecting (stealing) the packet it ++receives. Mirroring is what is sometimes referred to as Switch Port Analyzer ++(SPAN) and is commonly used to analyze and/or debug flows. + .SH OPTIONS + .TP + .B ingress +@@ -67,9 +65,23 @@ debugging purposes: + .EE + .RE + +-Use an ++Mirror all incoming ICMP packets on eth0 to a dummy interface for examination ++with e.g. tcpdump: ++ ++.RS ++.EX ++# ip link add dummy0 type dummy ++# ip link set dummy0 up ++# tc qdisc add dev eth0 handle ffff: ingress ++# tc filter add dev eth0 parent ffff: protocol ip \\ ++ u32 match ip protocol 1 0xff \\ ++ action mirred egress mirror dev dummy0 ++.EE ++.RE ++ ++Using an + .B ifb +-interface to send ingress traffic on eth0 through an instance of ++interface, it is possible to send ingress traffic through an instance of + .BR sfq : + + .RS +-- +1.8.3.1 + diff --git a/SOURCES/0142-man-tc-police.8-Emphasize-on-the-two-rate-control-me.patch b/SOURCES/0142-man-tc-police.8-Emphasize-on-the-two-rate-control-me.patch new file mode 100644 index 0000000..711ace1 --- /dev/null +++ b/SOURCES/0142-man-tc-police.8-Emphasize-on-the-two-rate-control-me.patch @@ -0,0 +1,86 @@ +From 6bfb1788b2986d5d2dde9bc6dd941234c2076ae5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:51:09 +0200 +Subject: [PATCH] man: tc-police.8: Emphasize on the two rate control + mechanisms + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit 8409abd59bbc8 + +commit 8409abd59bbc8a79689be25ab3a385c65d1334bd +Author: Phil Sutter <phil@nwl.cc> +Date: Tue Mar 22 15:48:36 2016 +0100 + + man: tc-police.8: Emphasize on the two rate control mechanisms + + As Jamal pointed out, there are two different approaches to bandwidth + measurement. Try to make this clear by separating them in synopsis and + also documenting the way to fine-tune avrate. + + Signed-off-by: Phil Sutter <phil@nwl.cc> + Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> +--- + man/man8/tc-police.8 | 29 +++++++++++++++++++++++++---- + 1 file changed, 25 insertions(+), 4 deletions(-) + +diff --git a/man/man8/tc-police.8 b/man/man8/tc-police.8 +index 2b1537e..5c5a632 100644 +--- a/man/man8/tc-police.8 ++++ b/man/man8/tc-police.8 +@@ -12,13 +12,21 @@ police - policing action + .IR BYTES [\fB/ BYTES "] ] [" + .BI peakrate " RATE" + ] [ +-.BI avrate " RATE" +-] [ + .BI overhead " BYTES" + ] [ + .BI linklayer " TYPE" + ] [ +-.BI conform-exceed " EXCEEDACT\fR[\fB/\fIEXCEEDACT\fR]" ++.IR CONTROL " ]" ++ ++.ti -8 ++.BR tc " ... " filter " ... [ " estimator ++.IR "SAMPLE AVERAGE " ] ++.BR "action police avrate" ++.IR RATE " [ " CONTROL " ]" ++ ++.ti -8 ++.IR CONTROL " :=" ++.BI conform-exceed " EXCEEDACT\fR[\fB/\fIEXCEEDACT" + + .ti -8 + .IR EXCEEDACT " := { " +@@ -27,7 +35,14 @@ police - policing action + The + .B police + action allows to limit bandwidth of traffic matched by the filter it is +-attached to. ++attached to. Basically there are two different algorithms available to measure ++the packet rate: The first one uses an internal dual token bucket and is ++configured using the ++.BR rate ", " burst ", " mtu ", " peakrate ", " overhead " and " linklayer ++parameters. The second one uses an in-kernel sampling mechanism. It can be ++fine-tuned using the ++.B estimator ++filter parameter. + .SH OPTIONS + .TP + .BI rate " RATE" +@@ -73,6 +88,12 @@ cell sizes, for + .B ethernet + no action is taken. + .TP ++.BI estimator " SAMPLE AVERAGE" ++Fine-tune the in-kernel packet rate estimator. ++.IR SAMPLE " and " AVERAGE ++are time values and control the frequency in which samples are taken and over ++what timespan an average is built. ++.TP + .BI conform-exceed " EXCEEDACT\fR[\fB/\fIEXCEEDACT\fR]" + Define how to handle packets which exceed (and, if the second + .I EXCEEDACT +-- +1.8.3.1 + diff --git a/SOURCES/0143-man-tc-skbedit.8-Elaborate-a-bit-on-TX-queues.patch b/SOURCES/0143-man-tc-skbedit.8-Elaborate-a-bit-on-TX-queues.patch new file mode 100644 index 0000000..9bfc14f --- /dev/null +++ b/SOURCES/0143-man-tc-skbedit.8-Elaborate-a-bit-on-TX-queues.patch @@ -0,0 +1,46 @@ +From 067dc31603717259cfc09b859ffccbe1178553a5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:51:09 +0200 +Subject: [PATCH] man: tc-skbedit.8: Elaborate a bit on TX queues + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit c73b621cfa480 + +commit c73b621cfa480b039bf09dc732d7e224e14684ba +Author: Phil Sutter <phil@nwl.cc> +Date: Tue Mar 22 15:48:37 2016 +0100 + + man: tc-skbedit.8: Elaborate a bit on TX queues + + Signed-off-by: Phil Sutter <phil@nwl.cc> + Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> +--- + man/man8/tc-skbedit.8 | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/man/man8/tc-skbedit.8 b/man/man8/tc-skbedit.8 +index b585a4d..e690296 100644 +--- a/man/man8/tc-skbedit.8 ++++ b/man/man8/tc-skbedit.8 +@@ -17,6 +17,18 @@ The + action allows to change a packet's associated meta data. It complements the + .B pedit + action, which in turn allows to change parts of the packet data itself. ++ ++The most unique feature of ++.B skbedit ++is it's ability to decide over which queue of an interface with multiple ++transmit queues the packet is to be sent out. The number of available transmit ++queues is reflected by sysfs entries within ++.I /sys/class/net/<interface>/queues ++with name ++.I tx-N ++(where ++.I N ++is the actual queue number). + .SH OPTIONS + .TP + .BI queue_mapping " QUEUE_MAPPING" +-- +1.8.3.1 + diff --git a/SOURCES/0144-man-ship-action-man-pages.patch b/SOURCES/0144-man-ship-action-man-pages.patch new file mode 100644 index 0000000..c79a339 --- /dev/null +++ b/SOURCES/0144-man-ship-action-man-pages.patch @@ -0,0 +1,38 @@ +From 7a3afbd3a258eb8fad8d4c4fc0d2cc0b4989d09c Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:51:09 +0200 +Subject: [PATCH] man: ship action man pages + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit bcdd39c5880f3 +Conflicts: Only relevant changes applied manually. + +commit bcdd39c5880f39190a63325f1f93e6c9e87c5feb +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 13:11:46 2016 +0100 + + man: ship action man pages + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/Makefile | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/man/man8/Makefile b/man/man8/Makefile +index c60c773..8389fce 100644 +--- a/man/man8/Makefile ++++ b/man/man8/Makefile +@@ -12,7 +12,9 @@ MAN8PAGES = $(TARGETS) ip.8 arpd.8 lnstat.8 routel.8 rtacct.8 rtmon.8 rtpr.8 ss. + ip-netns.8 ip-ntable.8 ip-rule.8 ip-tunnel.8 ip-xfrm.8 \ + ip-tcp_metrics.8 ip-netconf.8 ip-token.8 \ + tc-basic.8 tc-cgroup.8 tc-flow.8 tc-fw.8 tc-route.8 \ +- tc-tcindex.8 tc-u32.8 ++ tc-tcindex.8 tc-u32.8 \ ++ tc-csum.8 tc-mirred.8 tc-nat.8 tc-pedit.8 tc-police.8 \ ++ tc-simple.8 tc-skbedit.8 tc-xt.8 + + all: $(TARGETS) + +-- +1.8.3.1 + diff --git a/SOURCES/0145-doc-Add-my-article-about-tc-filters-and-actions.patch b/SOURCES/0145-doc-Add-my-article-about-tc-filters-and-actions.patch new file mode 100644 index 0000000..e4670f8 --- /dev/null +++ b/SOURCES/0145-doc-Add-my-article-about-tc-filters-and-actions.patch @@ -0,0 +1,569 @@ +From bcccddebc0476f32a4cc725f7f9f20a85c7db47b Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:51:38 +0200 +Subject: [PATCH] doc: Add my article about tc, filters and actions + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit 5f4d27d533917 + +commit 5f4d27d533917ccce4249c1d367aabf606167c47 +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 13:11:47 2016 +0100 + + doc: Add my article about tc, filters and actions + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + doc/Makefile | 2 +- + doc/tc-filters.tex | 529 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 530 insertions(+), 1 deletion(-) + create mode 100644 doc/tc-filters.tex + +diff --git a/doc/Makefile b/doc/Makefile +index b92957e..5e9da17 100644 +--- a/doc/Makefile ++++ b/doc/Makefile +@@ -1,4 +1,4 @@ +-PSFILES=ip-cref.ps ip-tunnels.ps api-ip6-flowlabels.ps ss.ps nstat.ps arpd.ps rtstat.ps ++PSFILES=ip-cref.ps ip-tunnels.ps api-ip6-flowlabels.ps ss.ps nstat.ps arpd.ps rtstat.ps tc-filters.ps + # tc-cref.ps + # api-rtnl.tex api-pmtudisc.tex api-news.tex + # iki-netdev.ps iki-neighdst.ps +diff --git a/doc/tc-filters.tex b/doc/tc-filters.tex +new file mode 100644 +index 0000000..59127d6 +--- /dev/null ++++ b/doc/tc-filters.tex +@@ -0,0 +1,529 @@ ++\documentclass[12pt,twoside]{article} ++ ++\usepackage[hidelinks]{hyperref} % \url ++\usepackage{booktabs} % nicer tabulars ++\usepackage{fancyvrb} ++\usepackage{fullpage} ++\usepackage{float} ++ ++\newcommand{\iface}{\textit} ++\newcommand{\cmd}{\texttt} ++\newcommand{\man}{\textit} ++\newcommand{\qdisc}{\texttt} ++\newcommand{\filter}{\texttt} ++ ++\begin{document} ++\title{QoS in Linux with TC and Filters} ++\author{Phil Sutter (phil@nwl.cc)} ++\date{January 2016} ++\maketitle ++ ++TC, the Traffic Control utility, has been there for a very long time - forever ++in my humble perception. It is still (and has ever been if I'm not mistaken) the ++only tool to configure QoS in Linux. ++ ++Standard practice when transmitting packets over a medium which may block (due ++to congestion, e.g.) is to use a queue which temporarily holds these packets. In ++Linux, this queueing approach is where QoS happens: A Queueing Discipline ++(qdisc) holds multiple packet queues with different priorities for dequeueing to ++the network driver. The classification (i.e. deciding which queue a packet ++should go into) is typically done based on Type Of Service (IPv4) or Traffic ++Class (IPv6) header fields but depending on qdisc implementation, might be ++controlled by the user as well. ++ ++Qdiscs come in two flavors, classful or classless. While classless qdiscs are ++not as flexible as classful ones, they also require much less customizing. Often ++it is enough to just attach them to an interface, without exact knowledge of ++what is done internally. Classful qdiscs are the exact opposite: flexible in ++application, they are often not even usable without insightful configuration. ++ ++As the name implies, classful qdiscs provide configurable classes to sort ++traffic into. In it's basic form, this is not much different than, say, the ++classless \qdisc{pfifo\_fast} which holds three queues and classifies per ++packet upon priority field. Though typically classes go beyond that by ++supporting nesting and additional characteristics like e.g. maximum traffic ++rate or quantum. ++ ++When it comes to controlling the classification process, filters come into play. ++They attach to the parent of a set of classes (i.e. either the qdisc itself or ++a parent class) and specify how a packet (or it's associated flow) has to look ++like in order to suit a given class. To overcome this simplification, it is ++possible to attach multiple filters to the same parent, which then consults each ++of them in row until the first one accepts the packet. ++ ++Before getting into detail about what filters there are and how to use them, a ++simple setup of a qdisc with classes is necessary: ++\begin{figure}[H] ++\begin{Verbatim} ++ .-------------------------------------------------------. ++ | | ++ | HTB | ++ | | ++ | .----------------------------------------------------.| ++ | | || ++ | | Class 1:1 || ++ | | || ++ | | .---------------..---------------..---------------.|| ++ | | | || || ||| ++ | | | Class 1:10 || Class 1:20 || Class 1:30 ||| ++ | | | || || ||| ++ | | | .------------.|| .------------.|| .------------.||| ++ | | | | ||| | ||| | |||| ++ | | | | fq_codel ||| | fq_codel ||| | fq_codel |||| ++ | | | | ||| | ||| | |||| ++ | | | '------------'|| '------------'|| '------------'||| ++ | | '---------------''---------------''---------------'|| ++ | '----------------------------------------------------'| ++ '-------------------------------------------------------' ++\end{Verbatim} ++\end{figure} ++\noindent ++The following commands establish the basic setup shown: ++\begin{Verbatim} ++(1) # tc qdisc replace dev eth0 root handle 1: htb default 30 ++(2) # tc class add dev eth0 parent 1: classid 1:1 htb rate 95mbit ++(3) # alias tclass='tc class add dev eth0 parent 1:1' ++(4) # tclass classid 1:10 htb rate 1mbit ceil 20mbit prio 1 ++(4) # tclass classid 1:20 htb rate 90mbit ceil 95mbit prio 2 ++(4) # tclass classid 1:30 htb rate 1mbit ceil 95mbit prio 3 ++(5) # tc qdisc add dev eth0 parent 1:10 fq_codel ++(5) # tc qdisc add dev eth0 parent 1:20 fq_codel ++(5) # tc qdisc add dev eth0 parent 1:30 fq_codel ++\end{Verbatim} ++A little explanation for the unfamiliar reader: ++\begin{enumerate} ++\item Replace the root qdisc of \iface{eth0} by an instance of \qdisc{HTB}. ++ Specifying the handle is necessary so it can be referenced in consecutive ++ calls to \cmd{tc}. The default class for unclassified traffic is set to ++ 30. ++\item Create a single top-level class with handle 1:1 which limits the total ++ bandwidth allowed to 95mbit/s. It is assumed that \iface{eth0} is a 100mbit/s link, ++ staying a little below that helps to keep the main point of enqueueing in ++ the qdisc layer instead of the interface hardware queue or at another ++ bottleneck in the network. ++\item Define an alias for the common part of the remaining three calls in order ++ to improve readability. This means all remaining classes are attached to the ++ common parent class from (2). ++\item Create three child classes for different uses: Class 1:10 has highest ++ priority but is tightly limited in bandwidth - fine for interactive ++ connections. Class 1:20 has mid priority and high guaranteed bandwidth, for ++ high priority bulk traffic. Finally, there's the default class 1:30 with ++ lowest priority, low guaranteed bandwidth and the ability to use the full ++ link in case it's unused otherwise. This should be fine for uninteresting ++ traffic not explicitly taken care of. ++\item Attach a leaf qdisc to each of the child classes created in (4). Since ++ \qdisc{HTB} by default attaches \qdisc{pfifo} as leaf qdisc, this step is optional. Still, ++ the fairness between different flows provided by the classless \qdisc{fq\_codel} is ++ worth the effort. ++\end{enumerate} ++More information about the qdiscs and fine-tuning parameters can be found in ++\man{tc-htb(8)} and \man{tc-fq\_codel(8)}. ++ ++Without any additional setup done, now all traffic leaving \iface{eth0} is shaped to ++95mbit/s and directed through class 1:30. This can be verified by looking at the ++\texttt{Sent} field of the class statistics printed via \cmd{tc -s class show dev eth0}: ++Only the root class 1:1 and it's child 1:30 should show any traffic. ++ ++ ++\section*{Finally time to start filtering!} ++ ++Let's begin with a simple one, i.e. reestablishing what \qdisc{pfifo\_fast} did ++automatically based on TOS/Priority field. Linux internally translates the ++header field into the priority field of struct skbuff, which ++\qdisc{pfifo\_fast} uses for ++classification. \man{tc-prio(8)} contains a table listing the priority (and ++ultimately, \qdisc{pfifo\_fast} queue index) each TOS value is being translated into. ++Here is a shorter version: ++\begin{center} ++\begin{tabular}{lll} ++TOS Values & Linux Priority (Number) & Queue Index \\ ++\midrule ++0x0 - 0x6 & Best Effort (0) & 1 \\ ++0x8 - 0xe & Bulk (2) & 2 \\ ++0x10 - 0x16 & Interactive (6) & 0 \\ ++0x18 - 0x1e & Interactive Bulk (4) & 1 \\ ++\end{tabular} ++\end{center} ++Using the \filter{basic} filter, it is possible to match packets based on that skbuff ++field, which has the added benefit of being IP version agnostic. Since the ++\qdisc{HTB} setup above defaults to class ID 1:30, the Bulk priority can be ++ignored. The \filter{basic} filter allows to combine matches, therefore we get along ++with only two filters: ++\begin{Verbatim} ++# tc filter add dev eth0 parent 1: basic \ ++ match 'meta(priority eq 6)' classid 1:10 ++# tc filter add dev eth0 parent 1: basic \ ++ match 'meta(priority eq 0)' \ ++ or 'meta(priority eq 4)' classid 1:20 ++\end{Verbatim} ++A detailed description of the \filter{basic} filter and the ematch syntax it uses can be ++found in \man{tc-basic(8)} and \man{tc-ematch(8)}. ++ ++Obviously, this first example cries for optimization. A simple one would be to ++just change the default class from 1:30 to 1:20, so filters are only needed for ++Bulk and Interactive priorities: ++\begin{Verbatim} ++# tc filter add dev eth0 parent 1: basic \ ++ match 'meta(priority eq 6)' classid 1:10 ++# tc filter add dev eth0 parent 1: basic \ ++ match 'meta(priority eq 2)' classid 1:20 ++\end{Verbatim} ++Given that class IDs are random, choosing them wisely allows for a direct ++mapping. So first, recreate the qdisc and classes configuration: ++\begin{Verbatim} ++# tc qdisc replace dev eth0 root handle 1: htb default 10 ++# tc class add dev eth0 parent 1: classid 1:1 htb rate 95mbit ++# alias tclass='tc class add dev eth0 parent 1:1' ++# tclass classid 1:16 htb rate 1mbit ceil 20mbit prio 1 ++# tclass classid 1:10 htb rate 90mbit ceil 95mbit prio 2 ++# tclass classid 1:12 htb rate 1mbit ceil 95mbit prio 3 ++# tc qdisc add dev eth0 parent 1:16 fq_codel ++# tc qdisc add dev eth0 parent 1:10 fq_codel ++# tc qdisc add dev eth0 parent 1:12 fq_codel ++\end{Verbatim} ++This is basically identical to above, but with changed leaf class IDs and the ++second priority class being the default. Using the \filter{flow} filter with it's \texttt{map} ++functionality, a single filter command is enough: ++\begin{Verbatim} ++# tc filter add dev eth0 parent 1: handle 0x1337 flow \ ++ map key priority baseclass 1:10 ++\end{Verbatim} ++The \filter{flow} filter now uses the priority value to construct a destination class ID ++by adding it to the value of \texttt{baseclass}. While this works for priority values of ++0, 2 and 6, it will result in non-existent class ID 1:14 for Interactive Bulk ++traffic. In that case, the \qdisc{HTB} default applies so that traffic goes into class ++ID 1:10 just as intended. Please note that specifying a handle is a mandatory ++requirement by the \filter{flow} filter, although I didn't see where one would use that ++later. For more information about \filter{flow}, see \man{tc-flow(8)}. ++ ++While \filter{flow} and \filter{basic} filters are relatively easy to apply and understand, they ++are as well quite limited to their intended purpose. A more flexible option is ++the \filter{u32} filter, which allows to match on arbitrary parts of the packet data - ++yet only on that, not any meta data associated to it by the kernel (with the ++exception of firewall mark value). So in order to continue this little ++exercise with \filter{u32}, we have to base classification directly upon the actual TOS ++value. An intuitive attempt might look like this: ++\begin{Verbatim} ++# alias tcfilter='tc filter add dev eth0 parent 1:' ++# tcfilter u32 match ip dsfield 0x10 0x1e classid 1:16 ++# tcfilter u32 match ip dsfield 0x12 0x1e classid 1:16 ++# tcfilter u32 match ip dsfield 0x14 0x1e classid 1:16 ++# tcfilter u32 match ip dsfield 0x16 0x1e classid 1:16 ++# tcfilter u32 match ip dsfield 0x8 0x1e classid 1:12 ++# tcfilter u32 match ip dsfield 0xa 0x1e classid 1:12 ++# tcfilter u32 match ip dsfield 0xc 0x1e classid 1:12 ++# tcfilter u32 match ip dsfield 0xe 0x1e classid 1:12 ++\end{Verbatim} ++The obvious drawback here is the amount of filters needed. And without the ++default class, eight more filters would be necessary. This also has performance ++implications: A packet with TOS value 0xe will be checked eight times in total ++in order to determine it's destination class. While there's not much to be done ++about the number of filters, at least the performance problem can be eliminated ++by using \filter{u32}'s hash table support: ++\begin{Verbatim} ++# tc filter add dev eth0 parent 1: prio 99 handle 1: u32 divisor 16 ++\end{Verbatim} ++This creates a hash table with 16 buckets. The table size is arbitrary, but not ++random: Since the first bit of the TOS field is not interesting, it can be ++ignored and therefore the range of values to consider is just [0;15], i.e. a ++number of 16 different values. The next step is to populate the hash table: ++\begin{Verbatim} ++# alias tcfilter='tc filter add dev eth0 parent 1: prio 99' ++# tcfilter u32 match u8 0 0 ht 1:0: classid 1:16 ++# tcfilter u32 match u8 0 0 ht 1:1: classid 1:16 ++# tcfilter u32 match u8 0 0 ht 1:2: classid 1:16 ++# tcfilter u32 match u8 0 0 ht 1:3: classid 1:16 ++# tcfilter u32 match u8 0 0 ht 1:4: classid 1:12 ++# tcfilter u32 match u8 0 0 ht 1:5: classid 1:12 ++# tcfilter u32 match u8 0 0 ht 1:6: classid 1:12 ++# tcfilter u32 match u8 0 0 ht 1:7: classid 1:12 ++# tcfilter u32 match u8 0 0 ht 1:8: classid 1:16 ++# tcfilter u32 match u8 0 0 ht 1:9: classid 1:16 ++# tcfilter u32 match u8 0 0 ht 1:a: classid 1:16 ++# tcfilter u32 match u8 0 0 ht 1:b: classid 1:16 ++# tcfilter u32 match u8 0 0 ht 1:c: classid 1:10 ++# tcfilter u32 match u8 0 0 ht 1:d: classid 1:10 ++# tcfilter u32 match u8 0 0 ht 1:e: classid 1:10 ++# tcfilter u32 match u8 0 0 ht 1:f: classid 1:10 ++\end{Verbatim} ++The parameter \texttt{ht} denotes the hash table and bucket the filter should be added ++to. Since the first TOS bit is ignored, it's value has to be divided by two in ++order to get to the bucket it maps to. E.g. a TOS value of 0x10 will therefore ++map to bucket 0x8. For the sake of completeness, all possible values are mapped ++and therefore a configurable default class is not required. Note that the used ++match expression is not necessary, but mandatory. Therefore anything that ++matches any packet will suffice. Finally, a filter which links to the defined ++hash table is needed: ++\begin{Verbatim} ++# tc filter add dev eth0 parent 1: prio 1 protocol ip u32 \ ++ link 1: hashkey mask 0x001e0000 match u8 0 0 ++\end{Verbatim} ++Here again, the actual match statement is not necessary, but syntactically ++required. All the magic lies within the \texttt{hashkey} parameter, which defines which ++part of the packet should be used directly as hash key. Here's a drawing of the ++first four bytes of the IPv4 header, with the area selected by \texttt{hashkey mask} ++highlighted: ++\begin{figure}[H] ++\begin{Verbatim} ++ 0 1 2 3 ++ .-----------------------------------------------------------------. ++ | | | ######## | | | ++ | Version| IHL | #DSCP### | ECN| Total Length | ++ | | | ######## | | | ++ '-----------------------------------------------------------------' ++\end{Verbatim} ++\end{figure} ++\noindent ++This may look confusing at first, but keep in mind that bit- as well as ++byte-ordering here is LSB while the mask value is written in MSB we humans use. ++Therefore reading the mask is done like so, starting from left: ++\begin{enumerate} ++\item Skip the first byte (which contains Version and IHL fields). ++\item Skip the lowest bit of the second byte (0x1e is even). ++\item Mark the four following bits (0x1e is 11110 in binary). ++\item Skip the remaining three bits of the second byte as well as the remaining two ++ bytes. ++\end{enumerate} ++Before doing the lookup, the kernel right-shifts the masked value by the amount ++of zero-bits in \texttt{mask}, which implicitly also does the division by two which the ++hash table depends on. With this setup, every packet has to pass exactly two ++filters to be classified. Note that this filter is limited to IPv4 packets: Due ++to the related Traffic Class field being at a different offset in the packet, it ++would not work for IPv6. To use the same setup for IPv6 as well, a second ++entry-level filter is necessary: ++\begin{Verbatim} ++# tc filter add dev eth0 parent 1: prio 2 protocol ipv6 u32 \ ++ link 1: hashkey mask 0x01e00000 match u8 0 0 ++\end{Verbatim} ++For illustration purposes, here again is a drawing of the first four bytes of ++the IPv6 header, again with masked area highlighted: ++\begin{figure}[H] ++\begin{Verbatim} ++ 0 1 2 3 ++ .-----------------------------------------------------------------. ++ | | ######## | | ++ | Version| #Traffic Class| Flow Label | ++ | | ######## | | ++ '-----------------------------------------------------------------' ++\end{Verbatim} ++\end{figure} ++\noindent ++Reading the mask value is analogous to IPv4 with the added complexity that ++Traffic Class spans over two bytes. Yet, for comparison there's a simple trick: ++IPv6 has the interesting field shifted by four bits to the left, and the new ++mask's value is shifted by the same amount. For further information about ++\filter{u32} and what can be done with it, consult it's man page ++\man{tc-u32(8)}. ++ ++Of course, the kernel provides many more filters than just \filter{basic}, ++\filter{flow} and \filter{u32} which have been presented above. As of now, the ++remaining ones are: ++\begin{description} ++\item[bpf] ++ Filtering using Berkeley Packet Filter programs. The program's return ++ code determines the packet's destination class ID. ++ ++\item[cgroup] ++ Filter packets based on control groups. This is only useful for packets ++ originating from the local host, as control groups only exist in that ++ scope. ++ ++\item[flower] ++ An extended variant of the flow filter. ++ ++\item[fw] ++ Matches on firewall mark values previously assigned to the packet by ++ netfilter (or a filter action, see below for details). This allows to ++ export the classification algorithm into netfilter, which is very ++ convenient if appropriate rules exist on the same system in there ++ already. ++ ++\item[route] ++ Filter packets based on matching routing table entry. Basically ++ equivalent to the \texttt{fw} filter above, to make use of an already existing ++ extensive routing table setup. ++ ++\item[rsvp, rsvp6] ++ Implementation of the Resource Reservation Protocol in Linux, to react ++ upon requests sent by an RSVP daemon. ++ ++\item[tcindex] ++ Match packets based on tcindex value, which is usually set by the dsmark ++ qdisc. This is part of an approach to support Differentiated Services in ++ Linux, which is another topic on it's own. ++\end{description} ++ ++ ++\section*{Filter Actions} ++ ++The tc filter framework provides the infrastructure to another extensible set of ++tools as well, namely tc actions. As the name suggests, they allow to do things ++with packets (or associated data). (The list of) Actions are part of a given ++filter. If it matches, each action it contains is executed in order before ++returning the classification result. Since the action has direct access to the ++latter, it is in theory possible for an action to react upon or even change the ++filtering result - as long as the packet matched, of course. Yet none of the ++currently in-tree actions make use of this. ++ ++The Generic Actions framework originally evolved out of the filters' ability to ++police traffic to a given maximum bandwidth. One common use case for that is to ++limit ingress traffic, dropping packets which exceed the threshold. A classic ++setup example is like so: ++\begin{Verbatim} ++# tc qdisc add dev eth0 handle ffff: ingress ++# tc filter add dev eth0 parent ffff: u32 \ ++ match u32 0 0 ++ police rate 1mbit burst 100k ++\end{Verbatim} ++The ingress qdisc is not a real one, but merely a point of reference for filters ++to attach to which should get applied to incoming traffic. The \filter{u32} filter added ++above matches on any packet and therefore limits the total incoming bandwidth to ++1mbit/s, allowing bursts of up to 100kbytes. Using the new syntax, the filter ++command changes slightly: ++\begin{Verbatim} ++# tc filter add dev eth0 parent ffff: u32 \ ++ match u32 0 0 \ ++ action police rate 1mbit burst 100k ++\end{Verbatim} ++The important detail is that this syntax allows to define multiple actions. ++E.g. for testing purposes, it is possible to redirect exceeding traffic to the ++loopback interface instead of dropping it: ++\begin{Verbatim} ++# tc filter add dev eth0 parent ffff: u32 \ ++ match u32 0 0 \ ++ action police rate 1mbit burst 100k conform-exceed pipe \ ++ action mirred egress redirect dev lo ++\end{Verbatim} ++The added parameter \texttt{conform-exceed pipe} tells the police action to allow for ++further actions to handle the exceeding packet. ++ ++Apart from \texttt{police} and \texttt{mirred} actions, there are a few more. Here's a full ++list of the currently implemented ones: ++\begin{description} ++\item[bpf] ++ Apply a Berkeley Packet Filter program to the packet. ++ ++\item[connmark] ++ Set the packet's firewall mark to that of it's connection. This works by ++ searching the conntrack table for a matching entry. If found, the mark ++ is restored. ++ ++\item[csum] ++ Trigger recalculation of packet checksums. The supported protocols are: ++ IPv4, ICMP, IGMP, TCP, UDP and UDPLite. ++ ++\item[ipt] ++ Pass the packet to an iptables target. This allows to use iptables ++ extensions directly instead of having to go the extra mile via setting ++ an arbitrary firewall mark and matching on that from within netfilter. ++ ++\item[mirred] ++ Mirror or redirect packets. This is often combined with the ifb pseudo ++ device to share a common QoS setup between multiple interfaces or even ++ ingress traffic. ++ ++\item[nat] ++ Perform stateless Native Address Translation. This is certainly not ++ complete and therefore inferior to NAT using iptables: Although the ++ kernel module decides between TCP, UDP and ICMP traffic, it does not ++ handle typical problematic protocols such as active FTP or SIP. ++ ++\item[pedit] ++ Generic packet editing. This allows to alter arbitrary bytes of the ++ packet, either by specifying an offset into the packet or by naming a ++ packet header and field name to change. Currently, the latter is ++ implemented only for IPv4 yet. ++ ++\item[police] ++ Apply a bandwidth rate limiting policy. Packets exceeding it are dropped ++ by default, but may optionally be handled differently. ++ ++\item[simple] ++ This is rather an example than real action. All it does is print a ++ user-defined string together with a packet counter. Useful maybe for ++ debugging when filter statistics are not available or too complicated. ++ ++\item[skbedit] ++ Edit associated packet data, supports changing queue mapping, priority ++ field and firewall mark value. ++ ++\item[vlan] ++ Add/remove a VLAN header to/from the packet. This might serve as ++ alternative to using 802.1Q pseudo-interfaces in combination with ++ routing rules when e.g. packets for a given destination need to be ++ encapsulated. ++\end{description} ++ ++ ++\section*{Intermediate Functional Block} ++ ++The Intermediate Functional Block (\texttt{ifb}) pseudo network interface acts as a QoS ++concentrator for multiple different sources of traffic. Packets from or to other ++interfaces have to be redirected to it using the \texttt{mirred} action in order to be ++handled, regularly routed traffic will be dropped. This way, a single stack of ++qdiscs, classes and filters can be shared between multiple interfaces. ++ ++Here's a simple example to feed incoming traffic from multiple interfaces ++through a Stochastic Fairness Queue (\qdisc{sfq}): ++\begin{Verbatim} ++(1) # modprobe ifb ++(2) # ip link set ifb0 up ++(3) # tc qdisc add dev ifb0 root sfq ++\end{Verbatim} ++The first step is to load the \texttt{ifb} kernel module (1). By default, this will ++create two ifb devices: \iface{ifb0} and \iface{ifb1}. After setting ++\iface{ifb0} up in (2), the root ++qdisc is replaced by \qdisc{sfq} in (3). Finally, one can start redirecting ingress ++traffic to \iface{ifb0}, e.g. from \iface{eth0}: ++\begin{Verbatim} ++# tc qdisc add dev eth0 handle ffff: ingress ++# tc filter add dev eth0 parent ffff: u32 \ ++ match u32 0 0 \ ++ action mirred egress redirect dev ifb0 ++\end{Verbatim} ++The same can be done for other interfaces, just replacing \iface{eth0} in the two ++commands above. One thing to keep in mind here is the asymmetrical routing this ++creates within the host doing the QoS: Incoming packets enter the system via ++\iface{ifb0}, while corresponding replies leave directly via \iface{eth0}. This can be observed ++using \cmd{tcpdump} on \iface{ifb0}, which shows the input part of the traffic only. What's ++more confusing is that \cmd{tcpdump} on \iface{eth0} shows both incoming and outgoing traffic, ++but the redirection is still effective - a simple prove is setting ++\iface{ifb0} down, ++which will interrupt the communication. Obviously \cmd{tcpdump} catches the packets to ++dump before they enter the ingress qdisc, which is why it sees them while the ++kernel itself doesn't. ++ ++ ++\section*{Conclusion} ++ ++My personal impression is that although the \cmd{tc} utility is an absolute ++necessity for anyone aiming at doing QoS in Linux professionally, there are way ++too many loose ends and trip wires present in it's environment. Contributing to ++this is the fact, that much of the non-essential functionality is redundantly ++available in netfilter. Another problem which adds weight to the first one is a ++general lack of documentation. Of course, there are many HOWTOs and guides in ++the internet, but since it's often not clear how up to date these are, I prefer ++the usual resources such as man or info pages. Surely nothing one couldn't fix ++in hindsight, but quality certainly suffers if the original author of the code ++does not or can not contribute to that. ++ ++All that being said, once the steep learning curve has been mastered, the ++conglomerate of (classful) qdiscs, filters and actions provides a highly ++sophisticated and flexible infrastructure to perform QoS, which plays nicely ++along with routing and firewalling setups. ++ ++ ++\section*{Further Reading} ++ ++A good starting point for novice users and experienced ones diving into unknown ++areas is the extensive HOWTO at \url{http://lartc.org}. The iproute2 package ships ++some examples (usually in /usr/share/doc/, depending on distribution) as well as ++man pages for \cmd{tc} in general, qdiscs and filters. The latter have been added ++just recently though, so if your distribution does not ship iproute2 version ++4.3.0 yet, these are not in there. Apart from that, the internet is a spring of ++HOWTOs and scripts people wrote - though these should be taken with a grain of ++salt: The complexity of the matter often leads to copying others' solutions ++without much validation, which allows for less optimal or even obsolete ++implementations to survive much longer than desired. ++ ++\end{document} +-- +1.8.3.1 + diff --git a/SOURCES/0146-doc-tc-filters.tex-Drop-overly-subjective-paragraphs.patch b/SOURCES/0146-doc-tc-filters.tex-Drop-overly-subjective-paragraphs.patch new file mode 100644 index 0000000..b5a9e0c --- /dev/null +++ b/SOURCES/0146-doc-tc-filters.tex-Drop-overly-subjective-paragraphs.patch @@ -0,0 +1,65 @@ +From 099c84e5b772f0fc5ec2f0176e74330a4e4ec0cb Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 30 Mar 2016 16:51:38 +0200 +Subject: [PATCH] doc/tc-filters.tex: Drop overly subjective paragraphs + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1275426 +Upstream Status: iproute2.git commit edf35b88248f6 + +commit edf35b88248f667c0b4f1502ccd35ce423d12451 +Author: Phil Sutter <phil@nwl.cc> +Date: Tue Mar 22 15:48:32 2016 +0100 + + doc/tc-filters.tex: Drop overly subjective paragraphs + + Cc: Alexei Starovoitov <alexei.starovoitov@gmail.com> + Signed-off-by: Phil Sutter <phil@nwl.cc> + Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> +--- + doc/tc-filters.tex | 23 ++++------------------- + 1 file changed, 4 insertions(+), 19 deletions(-) + +diff --git a/doc/tc-filters.tex b/doc/tc-filters.tex +index 59127d6..54cc0c9 100644 +--- a/doc/tc-filters.tex ++++ b/doc/tc-filters.tex +@@ -18,10 +18,6 @@ + \date{January 2016} + \maketitle + +-TC, the Traffic Control utility, has been there for a very long time - forever +-in my humble perception. It is still (and has ever been if I'm not mistaken) the +-only tool to configure QoS in Linux. +- + Standard practice when transmitting packets over a medium which may block (due + to congestion, e.g.) is to use a queue which temporarily holds these packets. In + Linux, this queueing approach is where QoS happens: A Queueing Discipline +@@ -496,21 +492,10 @@ kernel itself doesn't. + + \section*{Conclusion} + +-My personal impression is that although the \cmd{tc} utility is an absolute +-necessity for anyone aiming at doing QoS in Linux professionally, there are way +-too many loose ends and trip wires present in it's environment. Contributing to +-this is the fact, that much of the non-essential functionality is redundantly +-available in netfilter. Another problem which adds weight to the first one is a +-general lack of documentation. Of course, there are many HOWTOs and guides in +-the internet, but since it's often not clear how up to date these are, I prefer +-the usual resources such as man or info pages. Surely nothing one couldn't fix +-in hindsight, but quality certainly suffers if the original author of the code +-does not or can not contribute to that. +- +-All that being said, once the steep learning curve has been mastered, the +-conglomerate of (classful) qdiscs, filters and actions provides a highly +-sophisticated and flexible infrastructure to perform QoS, which plays nicely +-along with routing and firewalling setups. ++Once the steep learning curve has been mastered, the conglomerate of (classful) ++qdiscs, filters and actions provides a highly sophisticated and flexible ++infrastructure to perform QoS, which plays nicely along with routing and ++firewalling setups. + + + \section*{Further Reading} +-- +1.8.3.1 + diff --git a/SOURCES/0147-ss-Fix-wrong-filter-behaviour.patch b/SOURCES/0147-ss-Fix-wrong-filter-behaviour.patch new file mode 100644 index 0000000..2a9b7b0 --- /dev/null +++ b/SOURCES/0147-ss-Fix-wrong-filter-behaviour.patch @@ -0,0 +1,210 @@ +From d57e50c6402fb84b9fb21617a9e4e69551af50f2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Mon, 30 May 2016 16:46:58 +0200 +Subject: [PATCH] ss: Fix wrong filter behaviour + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1318005 +Upstream Status: iproute2.git commit 57ff5a1096cab + +commit 57ff5a1096cab63107d7e85bcd0d822614e33d73 +Author: Vadim Kochan <vadim4j@gmail.com> +Date: Thu Apr 30 07:30:24 2015 +0300 + + ss: Fix wrong filter behaviour + + Fixed applying family & socket type filters. + It was not possible to select UDP & UNIX sockets together. + + Now selected families are ORed. + + The problem was that filters were combined by AND. + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> + Reported-By: Mihai Moldovan <ionic@ionic.de> +--- + misc/ss.c | 91 ++++++++++++++++++++++++++++++++++----------------------------- + 1 file changed, 49 insertions(+), 42 deletions(-) + +diff --git a/misc/ss.c b/misc/ss.c +index 7750887..95f3c31 100644 +--- a/misc/ss.c ++++ b/misc/ss.c +@@ -233,14 +233,12 @@ static struct filter current_filter; + static void filter_db_set(struct filter *f, int db) + { + f->states |= default_dbs[db].states; +- f->families |= default_dbs[db].families; + f->dbs |= 1 << db; + do_default = 0; + } + + static void filter_af_set(struct filter *f, int af) + { +- f->dbs |= default_afs[af].dbs; + f->states |= default_afs[af].states; + f->families |= 1 << af; + do_default = 0; +@@ -266,21 +264,31 @@ static void filter_default_dbs(struct filter *f) + filter_db_set(f, NETLINK_DB); + } + +-static void filter_merge(struct filter *af, struct filter *dbf, int states) ++static void filter_states_set(struct filter *f, int states) + { +- if (af->families) +- af->families = (af->families | dbf->families) & af->families; +- else +- af->families = dbf->families; ++ if (states) ++ f->states = (f->states | states) & states; ++} + +- if (dbf->dbs) +- af->dbs = (af->dbs | dbf->dbs) & dbf->dbs; ++static void filter_merge_defaults(struct filter *f) ++{ ++ int db; ++ int af; + +- if (dbf->states) +- af->states = (af->states | dbf->states) & dbf->states; ++ for (db = 0; db < MAX_DB; db++) { ++ if (!(f->dbs & (1 << db))) ++ continue; + +- if (states) +- af->states = (af->states | states) & states; ++ if (!(default_dbs[db].families & f->families)) ++ f->families |= default_dbs[db].families; ++ } ++ for (af = 0; af < AF_MAX; af++) { ++ if (!(f->families & (1 << af))) ++ continue; ++ ++ if (!(default_afs[af].dbs & f->dbs)) ++ f->dbs |= default_afs[af].dbs; ++ } + } + + static FILE *generic_proc_open(const char *env, const char *name) +@@ -1540,7 +1548,7 @@ out: + if (fam != AF_UNSPEC) { + f->families = 0; + filter_af_set(f, fam); +- filter_merge(f, f, 0); ++ filter_states_set(f, 0); + } + + res = malloc(sizeof(*res)); +@@ -3440,7 +3448,6 @@ int main(int argc, char *argv[]) + const char *dump_tcpdiag = NULL; + FILE *filter_fp = NULL; + int ch; +- struct filter dbs_filter = {}; + int state_filter = 0; + + while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbf:miA:D:F:vVzZN:", +@@ -3474,16 +3481,16 @@ int main(int argc, char *argv[]) + show_bpf++; + break; + case 'd': +- filter_db_set(&dbs_filter, DCCP_DB); ++ filter_db_set(¤t_filter, DCCP_DB); + break; + case 't': +- filter_db_set(&dbs_filter, TCP_DB); ++ filter_db_set(¤t_filter, TCP_DB); + break; + case 'u': +- filter_db_set(&dbs_filter, UDP_DB); ++ filter_db_set(¤t_filter, UDP_DB); + break; + case 'w': +- filter_db_set(&dbs_filter, RAW_DB); ++ filter_db_set(¤t_filter, RAW_DB); + break; + case 'x': + filter_af_set(¤t_filter, AF_UNIX); +@@ -3537,44 +3544,44 @@ int main(int argc, char *argv[]) + if ((p1 = strchr(p, ',')) != NULL) + *p1 = 0; + if (strcmp(p, "all") == 0) { +- filter_default_dbs(&dbs_filter); ++ filter_default_dbs(¤t_filter); + } else if (strcmp(p, "inet") == 0) { +- filter_db_set(&dbs_filter, UDP_DB); +- filter_db_set(&dbs_filter, DCCP_DB); +- filter_db_set(&dbs_filter, TCP_DB); +- filter_db_set(&dbs_filter, RAW_DB); ++ filter_db_set(¤t_filter, UDP_DB); ++ filter_db_set(¤t_filter, DCCP_DB); ++ filter_db_set(¤t_filter, TCP_DB); ++ filter_db_set(¤t_filter, RAW_DB); + } else if (strcmp(p, "udp") == 0) { +- filter_db_set(&dbs_filter, UDP_DB); ++ filter_db_set(¤t_filter, UDP_DB); + } else if (strcmp(p, "dccp") == 0) { +- filter_db_set(&dbs_filter, DCCP_DB); ++ filter_db_set(¤t_filter, DCCP_DB); + } else if (strcmp(p, "tcp") == 0) { +- filter_db_set(&dbs_filter, TCP_DB); ++ filter_db_set(¤t_filter, TCP_DB); + } else if (strcmp(p, "raw") == 0) { +- filter_db_set(&dbs_filter, RAW_DB); ++ filter_db_set(¤t_filter, RAW_DB); + } else if (strcmp(p, "unix") == 0) { +- filter_db_set(&dbs_filter, UNIX_ST_DB); +- filter_db_set(&dbs_filter, UNIX_DG_DB); +- filter_db_set(&dbs_filter, UNIX_SQ_DB); ++ filter_db_set(¤t_filter, UNIX_ST_DB); ++ filter_db_set(¤t_filter, UNIX_DG_DB); ++ filter_db_set(¤t_filter, UNIX_SQ_DB); + } else if (strcasecmp(p, "unix_stream") == 0 || + strcmp(p, "u_str") == 0) { +- filter_db_set(&dbs_filter, UNIX_ST_DB); ++ filter_db_set(¤t_filter, UNIX_ST_DB); + } else if (strcasecmp(p, "unix_dgram") == 0 || + strcmp(p, "u_dgr") == 0) { +- filter_db_set(&dbs_filter, UNIX_DG_DB); ++ filter_db_set(¤t_filter, UNIX_DG_DB); + } else if (strcasecmp(p, "unix_seqpacket") == 0 || + strcmp(p, "u_seq") == 0) { +- filter_db_set(&dbs_filter, UNIX_SQ_DB); ++ filter_db_set(¤t_filter, UNIX_SQ_DB); + } else if (strcmp(p, "packet") == 0) { +- filter_db_set(&dbs_filter, PACKET_R_DB); +- filter_db_set(&dbs_filter, PACKET_DG_DB); ++ filter_db_set(¤t_filter, PACKET_R_DB); ++ filter_db_set(¤t_filter, PACKET_DG_DB); + } else if (strcmp(p, "packet_raw") == 0 || + strcmp(p, "p_raw") == 0) { +- filter_db_set(&dbs_filter, PACKET_R_DB); ++ filter_db_set(¤t_filter, PACKET_R_DB); + } else if (strcmp(p, "packet_dgram") == 0 || + strcmp(p, "p_dgr") == 0) { +- filter_db_set(&dbs_filter, PACKET_DG_DB); ++ filter_db_set(¤t_filter, PACKET_DG_DB); + } else if (strcmp(p, "netlink") == 0) { +- filter_db_set(&dbs_filter, NETLINK_DB); ++ filter_db_set(¤t_filter, NETLINK_DB); + } else { + fprintf(stderr, "ss: \"%s\" is illegal socket table id\n", p); + usage(); +@@ -3667,11 +3674,11 @@ int main(int argc, char *argv[]) + if (do_default) { + state_filter = state_filter ? state_filter : SS_CONN; + filter_default_dbs(¤t_filter); +- filter_merge(¤t_filter, ¤t_filter, state_filter); +- } else { +- filter_merge(¤t_filter, &dbs_filter, state_filter); + } + ++ filter_states_set(¤t_filter, state_filter); ++ filter_merge_defaults(¤t_filter); ++ + if (resolve_services && resolve_hosts && + (current_filter.dbs&(UNIX_DBM|(1<<TCP_DB)|(1<<UDP_DB)|(1<<DCCP_DB)))) + init_service_resolver(); +-- +1.8.3.1 + diff --git a/SOURCES/0148-ss-Drop-silly-assignment.patch b/SOURCES/0148-ss-Drop-silly-assignment.patch new file mode 100644 index 0000000..7b5d53d --- /dev/null +++ b/SOURCES/0148-ss-Drop-silly-assignment.patch @@ -0,0 +1,38 @@ +From 26763f0545c14630b1af31fbd9550a38356dad31 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Mon, 30 May 2016 16:46:58 +0200 +Subject: [PATCH] ss: Drop silly assignment + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1318005 +Upstream Status: iproute2.git commit 9d320e1e92863 + +commit 9d320e1e928630d8b2b83d5e4ef4e10a117352bc +Author: Phil Sutter <phil@nwl.cc> +Date: Wed Apr 13 22:07:04 2016 +0200 + + ss: Drop silly assignment + + An expression of the form '(a | b) & b' will evaluate to the value of b + for any value of a or b. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + misc/ss.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/misc/ss.c b/misc/ss.c +index 95f3c31..ce7fa82 100644 +--- a/misc/ss.c ++++ b/misc/ss.c +@@ -267,7 +267,7 @@ static void filter_default_dbs(struct filter *f) + static void filter_states_set(struct filter *f, int states) + { + if (states) +- f->states = (f->states | states) & states; ++ f->states = states; + } + + static void filter_merge_defaults(struct filter *f) +-- +1.8.3.1 + diff --git a/SOURCES/0149-ss-Fix-accidental-state-filter-override.patch b/SOURCES/0149-ss-Fix-accidental-state-filter-override.patch new file mode 100644 index 0000000..ecac69a --- /dev/null +++ b/SOURCES/0149-ss-Fix-accidental-state-filter-override.patch @@ -0,0 +1,48 @@ +From 603d0ffb9ec9200de2395200dbc50ba762de6038 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Mon, 30 May 2016 16:46:58 +0200 +Subject: [PATCH] ss: Fix accidental state filter override + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1318005 +Upstream Status: iproute2.git commit e56a959e550f4 + +commit e56a959e550f424023ebf3ebb8437f214944a245 +Author: Phil Sutter <phil@nwl.cc> +Date: Wed Apr 13 22:07:05 2016 +0200 + + ss: Fix accidental state filter override + + Passing a filter expression and selecting an address family using the + '-f' flag would overwrite the state filter by accident. Therefore + calling e.g. 'ss -nl -f inet '(sport = :22)' would not only print + listening sockets (as requested by '-l' flag) but connected ones, as + well. + + Fix this by reusing the formerly ineffective call to filter_states_set() + to restore the state filter as it was before the call to + filter_af_set(). + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + misc/ss.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/misc/ss.c b/misc/ss.c +index ce7fa82..c385d47 100644 +--- a/misc/ss.c ++++ b/misc/ss.c +@@ -1546,9 +1546,10 @@ void *parse_hostcond(char *addr, bool is_port) + + out: + if (fam != AF_UNSPEC) { ++ int states = f->states; + f->families = 0; + filter_af_set(f, fam); +- filter_states_set(f, 0); ++ filter_states_set(f, states); + } + + res = malloc(sizeof(*res)); +-- +1.8.3.1 + diff --git a/SOURCES/0150-ip-enable-configuring-multicast-group-autojoin.patch b/SOURCES/0150-ip-enable-configuring-multicast-group-autojoin.patch new file mode 100644 index 0000000..f03b863 --- /dev/null +++ b/SOURCES/0150-ip-enable-configuring-multicast-group-autojoin.patch @@ -0,0 +1,110 @@ +From 24aff639b62b443b15281c5fc44e28483c22236b Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Mon, 30 May 2016 18:37:49 +0200 +Subject: [PATCH] ip: enable configuring multicast group autojoin + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1333513 +Upstream Status: iproute2.git commit e31867ac30cf9 +Conflicts: Minor context conflict due to previously applied commit + c079e121a73af ("libnetlink: add size argument to rtnl_talk"). + +commit e31867ac30cf95155d113bbfaedf6b99f98a677f +Author: Madhu Challa <challa@noironetworks.com> +Date: Wed Mar 4 10:30:10 2015 -0800 + + ip: enable configuring multicast group autojoin + + Joining multicast group on ethernet level via "ip maddr" command would + not work if we have an Ethernet switch that does igmp snooping since + the switch would not replicate multicast packets on ports that did not + have IGMP reports for the multicast addresses. + + Linux vxlan interfaces created via "ip link add vxlan" have the group option + that enables then to do the required join. + + By extending ip address command with option "autojoin" we can get similar + functionality for openvswitch vxlan interfaces as well as other tunneling + mechanisms that need to receive multicast traffic. + + example: + ip address add 224.1.1.10/24 dev eth5 autojoin + ip address del 224.1.1.10/24 dev eth5 +--- + ip/ipaddress.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 8681bf9..ffcc076 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -83,7 +83,7 @@ static void usage(void) + fprintf(stderr, " [-]tentative | [-]deprecated | [-]dadfailed | temporary |\n"); + fprintf(stderr, " CONFFLAG-LIST ]\n"); + fprintf(stderr, "CONFFLAG-LIST := [ CONFFLAG-LIST ] CONFFLAG\n"); +- fprintf(stderr, "CONFFLAG := [ home | nodad | mngtmpaddr | noprefixroute ]\n"); ++ fprintf(stderr, "CONFFLAG := [ home | nodad | mngtmpaddr | noprefixroute | autojoin ]\n"); + fprintf(stderr, "LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]\n"); + fprintf(stderr, "LFT := forever | SECONDS\n"); + +@@ -868,6 +868,10 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, + ifa_flags &= ~IFA_F_NOPREFIXROUTE; + fprintf(fp, "noprefixroute "); + } ++ if (ifa_flags & IFA_F_MCAUTOJOIN) { ++ ifa_flags &= ~IFA_F_MCAUTOJOIN; ++ fprintf(fp, "autojoin "); ++ } + if (!(ifa_flags & IFA_F_PERMANENT)) { + fprintf(fp, "dynamic "); + } else +@@ -1272,6 +1276,9 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) + } else if (strcmp(*argv, "noprefixroute") == 0) { + filter.flags |= IFA_F_NOPREFIXROUTE; + filter.flagmask |= IFA_F_NOPREFIXROUTE; ++ } else if (strcmp(*argv, "autojoin") == 0) { ++ filter.flags |= IFA_F_MCAUTOJOIN; ++ filter.flagmask |= IFA_F_MCAUTOJOIN; + } else if (strcmp(*argv, "dadfailed") == 0) { + filter.flags |= IFA_F_DADFAILED; + filter.flagmask |= IFA_F_DADFAILED; +@@ -1408,6 +1415,16 @@ static int default_scope(inet_prefix *lcl) + return 0; + } + ++static bool ipaddr_is_multicast(inet_prefix *a) ++{ ++ if (a->family == AF_INET) ++ return IN_MULTICAST(ntohl(a->data[0])); ++ else if (a->family == AF_INET6) ++ return IN6_IS_ADDR_MULTICAST(a->data); ++ else ++ return false; ++} ++ + static int ipaddr_modify(int cmd, int flags, int argc, char **argv) + { + struct { +@@ -1515,6 +1532,8 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv) + ifa_flags |= IFA_F_MANAGETEMPADDR; + } else if (strcmp(*argv, "noprefixroute") == 0) { + ifa_flags |= IFA_F_NOPREFIXROUTE; ++ } else if (strcmp(*argv, "autojoin") == 0) { ++ ifa_flags |= IFA_F_MCAUTOJOIN; + } else { + if (strcmp(*argv, "local") == 0) { + NEXT_ARG(); +@@ -1605,6 +1624,11 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv) + sizeof(cinfo)); + } + ++ if ((ifa_flags & IFA_F_MCAUTOJOIN) && !ipaddr_is_multicast(&lcl)) { ++ fprintf(stderr, "autojoin needs multicast address\n"); ++ return -1; ++ } ++ + if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) + return -2; + +-- +1.8.3.1 + diff --git a/SOURCES/0151-man-ip-ip-link-Fix-ip-option-location.patch b/SOURCES/0151-man-ip-ip-link-Fix-ip-option-location.patch new file mode 100644 index 0000000..be6349a --- /dev/null +++ b/SOURCES/0151-man-ip-ip-link-Fix-ip-option-location.patch @@ -0,0 +1,76 @@ +From be5c5dc145c7e7f4e8e8e3731c9cb9cc43cbb52c Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 1 Jun 2016 00:49:32 +0200 +Subject: [PATCH] man: ip, ip-link: Fix ip option location + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1251186 +Upstream Status: iproute2.git commit 134080cff35e3 +Conflicts: Context changes in ip-link.8.in due to missing other + features. + +commit 134080cff35e379cac81d47ec669d265c56d528d +Author: Phil Sutter <phil@nwl.cc> +Date: Mon May 30 20:46:27 2016 +0200 + + man: ip, ip-link: Fix ip option location + + This patch drops the redundant description of some of ip's options in + ip-link.8's description of the 'show' subcommand, preserving the + description of -iec (but appending it to the list in ip.8 with minor + fixes). + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/ip-link.8.in | 20 -------------------- + man/man8/ip.8 | 4 ++++ + 2 files changed, 4 insertions(+), 20 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index e8dccbd..744a8af 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -915,26 +915,6 @@ specifies what group of devices to show. + .B up + only display running interfaces. + +-.TP +-The show command has additional formatting options: +- +-.RS +-.TP +-.BR "\-s" , " \-stats", " \-statistics" +-output more statistics about packet usage. +- +-.TP +-.BR "\-d", " \-details" +-output more detailed information. +- +-.TP +-.BR "\-h", " \-human", " \-human-readable" +-output statistics with human readable values number followed by suffix +- +-.TP +-.BR "\-iec" +-print human readable rates in IEC units (ie. 1K = 1024). +-.RE + + .SS ip link help - display help + +diff --git a/man/man8/ip.8 b/man/man8/ip.8 +index a95264d..b1c0bc0 100644 +--- a/man/man8/ip.8 ++++ b/man/man8/ip.8 +@@ -191,6 +191,10 @@ but use shorter format. + .BR "\-rc" , " \-rcvbuf" <SIZE> + Set the netlink socket receive buffer size, defaults to 1MB. + ++.TP ++.BR "\-iec" ++print human readable rates in IEC units (e.g. 1Ki = 1024). ++ + .SH IP - COMMAND SYNTAX + + .SS +-- +1.8.3.1 + diff --git a/SOURCES/0152-ip-link-Allow-to-filter-devices-by-master-dev.patch b/SOURCES/0152-ip-link-Allow-to-filter-devices-by-master-dev.patch new file mode 100644 index 0000000..d89f1d6 --- /dev/null +++ b/SOURCES/0152-ip-link-Allow-to-filter-devices-by-master-dev.patch @@ -0,0 +1,111 @@ +From 07d29a9b4fff9486c4d4077c714086c895951e02 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 16 Jun 2016 16:40:15 +0200 +Subject: [PATCH] ip link: Allow to filter devices by master dev + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1341343 +Upstream Status: iproute2.git commit 1b94414854d71 +Conflicts: Changes in ip-link.8.in due to previously applied patches + 134080cff35e3 ("man: ip, ip-link: Fix ip option location") + and ca611d6408c9b ("man: ip-link.8: Fix and improve + synopsis"). + +commit 1b94414854d71a6b6df367644ae9b06a54278daf +Author: Vadim Kochan <vadim4j@gmail.com> +Date: Sat Nov 29 11:27:41 2014 -0800 + + ip link: Allow to filter devices by master dev + + Added 'master' option to 'ip link show' command + to filter devices by master dev. + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> +--- + ip/ipaddress.c | 16 ++++++++++++++++ + ip/iplink.c | 2 +- + man/man8/ip-link.8.in | 8 +++++++- + 3 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index ffcc076..3d9e47f 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -57,6 +57,7 @@ static struct + int flushp; + int flushe; + int group; ++ int master; + } filter; + + static int do_link; +@@ -560,6 +561,14 @@ int print_linkinfo(const struct sockaddr_nl *who, + return -1; + } + ++ if (tb[IFLA_MASTER]) { ++ int master = *(int*)RTA_DATA(tb[IFLA_MASTER]); ++ if (filter.master > 0 && master != filter.master) ++ return -1; ++ } ++ else if (filter.master > 0) ++ return -1; ++ + if (n->nlmsg_type == RTM_DELLINK) + fprintf(fp, "Deleted "); + +@@ -1292,6 +1301,13 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) + NEXT_ARG(); + if (rtnl_group_a2n(&filter.group, *argv)) + invarg("Invalid \"group\" value\n", *argv); ++ } else if (strcmp(*argv, "master") == 0) { ++ int ifindex; ++ NEXT_ARG(); ++ ifindex = ll_name_to_index(*argv); ++ if (!ifindex) ++ invarg("Device does not exist\n", *argv); ++ filter.master = ifindex; + } else { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); +diff --git a/ip/iplink.c b/ip/iplink.c +index 787d743..1d93229 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -84,7 +84,7 @@ void iplink_usage(void) + fprintf(stderr, " [ master DEVICE ]\n"); + fprintf(stderr, " [ nomaster ]\n"); + fprintf(stderr, " [ addrgenmode { eui64 | none } ]\n"); +- fprintf(stderr, " ip link show [ DEVICE | group GROUP ] [up]\n"); ++ fprintf(stderr, " ip link show [ DEVICE | group GROUP ] [up] [master DEV]\n"); + + if (iplink_have_newlink()) { + fprintf(stderr, " ip link help [ TYPE ]\n"); +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 744a8af..09ea2f7 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -141,7 +141,9 @@ ip-link \- network device configuration + .RI "[ " DEVICE " | " + .B group + .IR GROUP " ] [" +-.BR up " ]" ++.BR up " ] [" ++.B master ++.IR DEVICE " ]" + + .ti -8 + .B ip link help +@@ -915,6 +917,10 @@ specifies what group of devices to show. + .B up + only display running interfaces. + ++.TP ++.BI master " DEVICE " ++.I DEVICE ++specifies the master device which enslaves devices to show. + + .SS ip link help - display help + +-- +1.8.3.1 + diff --git a/SOURCES/0153-ip-link-Show-devices-by-type.patch b/SOURCES/0153-ip-link-Show-devices-by-type.patch new file mode 100644 index 0000000..14962bf --- /dev/null +++ b/SOURCES/0153-ip-link-Show-devices-by-type.patch @@ -0,0 +1,150 @@ +From 1483dbd11fe093100866a1bad822941e12d10c6a Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 16 Jun 2016 16:41:37 +0200 +Subject: [PATCH] ip link: Show devices by type + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1341343 +Upstream Status: iproute2.git commit 712249d8fac88 +Conflicts: Changes in ip-link.8.in due to previously applied patches + 134080cff35e3 ("man: ip, ip-link: Fix ip option location") + and ca611d6408c9b ("man: ip-link.8: Fix and improve + synopsis"). + +commit 712249d8fac88bcf3a9fd0b1de2263074075873b +Author: Vadim Kochan <vadim4j@gmail.com> +Date: Wed Dec 10 10:11:29 2014 +0200 + + ip link: Show devices by type + + Added new option 'type' to 'ip link show' + command which allows to filter devices by type: + + ip link show type bridge + ip link show type vlan + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> +--- + ip/ipaddress.c | 27 +++++++++++++++++++++++++++ + ip/iplink.c | 2 +- + man/man8/ip-link.8.in | 19 ++++++++++++++++++- + 3 files changed, 46 insertions(+), 2 deletions(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 3d9e47f..4720de0 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -58,6 +58,7 @@ static struct + int flushe; + int group; + int master; ++ char *kind; + } filter; + + static int do_link; +@@ -190,6 +191,18 @@ static void print_linkmode(FILE *f, struct rtattr *tb) + fprintf(f, "mode %s ", link_modes[mode]); + } + ++static char *parse_link_kind(struct rtattr *tb) ++{ ++ struct rtattr *linkinfo[IFLA_INFO_MAX+1]; ++ ++ parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb); ++ ++ if (linkinfo[IFLA_INFO_KIND]) ++ return RTA_DATA(linkinfo[IFLA_INFO_KIND]); ++ ++ return ""; ++} ++ + static void print_linktype(FILE *fp, struct rtattr *tb) + { + struct rtattr *linkinfo[IFLA_INFO_MAX+1]; +@@ -569,6 +582,17 @@ int print_linkinfo(const struct sockaddr_nl *who, + else if (filter.master > 0) + return -1; + ++ if (filter.kind) { ++ if (tb[IFLA_LINKINFO]) { ++ char *kind = parse_link_kind(tb[IFLA_LINKINFO]); ++ ++ if (strcmp(kind, filter.kind)) ++ return -1; ++ } else { ++ return -1; ++ } ++ } ++ + if (n->nlmsg_type == RTM_DELLINK) + fprintf(fp, "Deleted "); + +@@ -1308,6 +1332,9 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) + if (!ifindex) + invarg("Device does not exist\n", *argv); + filter.master = ifindex; ++ } else if (do_link && strcmp(*argv, "type") == 0) { ++ NEXT_ARG(); ++ filter.kind = *argv; + } else { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); +diff --git a/ip/iplink.c b/ip/iplink.c +index 1d93229..0f91043 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -84,7 +84,7 @@ void iplink_usage(void) + fprintf(stderr, " [ master DEVICE ]\n"); + fprintf(stderr, " [ nomaster ]\n"); + fprintf(stderr, " [ addrgenmode { eui64 | none } ]\n"); +- fprintf(stderr, " ip link show [ DEVICE | group GROUP ] [up] [master DEV]\n"); ++ fprintf(stderr, " ip link show [ DEVICE | group GROUP ] [up] [master DEV] [type TYPE]\n"); + + if (iplink_have_newlink()) { + fprintf(stderr, " ip link help [ TYPE ]\n"); +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 09ea2f7..f968e49 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -143,7 +143,9 @@ ip-link \- network device configuration + .IR GROUP " ] [" + .BR up " ] [" + .B master +-.IR DEVICE " ]" ++.IR DEVICE " ] [" ++.B type ++.IR TYPE " ]" + + .ti -8 + .B ip link help +@@ -922,6 +924,11 @@ only display running interfaces. + .I DEVICE + specifies the master device which enslaves devices to show. + ++.TP ++.BI type " TYPE " ++.I TYPE ++specifies the type of devices to show. ++ + .SS ip link help - display help + + .PP +@@ -935,6 +942,16 @@ ip link show + Shows the state of all network interfaces on the system. + .RE + .PP ++ip link show type bridge ++.RS 4 ++Shows the bridge devices. ++.RE ++.PP ++ip link show type vlan ++.RS 4 ++Shows the vlan devices. ++.RE ++.PP + ip link set dev ppp0 mtu 1400 + .RS 4 + Change the MTU the ppp0 device. +-- +1.8.3.1 + diff --git a/SOURCES/0154-man-ip-link-Small-example-of-ip-link-show-master.patch b/SOURCES/0154-man-ip-link-Small-example-of-ip-link-show-master.patch new file mode 100644 index 0000000..6917287 --- /dev/null +++ b/SOURCES/0154-man-ip-link-Small-example-of-ip-link-show-master.patch @@ -0,0 +1,38 @@ +From f74901523533aee13be145d36877d93a8163536d Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 16 Jun 2016 16:41:52 +0200 +Subject: [PATCH] man ip-link: Small example of 'ip link show master' + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1341343 +Upstream Status: iproute2.git commit 417b2180a57b0 + +commit 417b2180a57b0335981bdaaaaa017a48d1a84b72 +Author: Vadim Kochan <vadim4j@gmail.com> +Date: Fri Dec 26 04:46:20 2014 +0200 + + man ip-link: Small example of 'ip link show master' + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> +--- + man/man8/ip-link.8.in | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index f968e49..312be6b 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -952,6 +952,11 @@ ip link show type vlan + Shows the vlan devices. + .RE + .PP ++ip link show master br0 ++.RS 4 ++Shows devices enslaved by br0 ++.RE ++.PP + ip link set dev ppp0 mtu 1400 + .RS 4 + Change the MTU the ppp0 device. +-- +1.8.3.1 + diff --git a/SOURCES/0155-ipaddress-Allow-listing-addresses-by-type.patch b/SOURCES/0155-ipaddress-Allow-listing-addresses-by-type.patch new file mode 100644 index 0000000..dbc194d --- /dev/null +++ b/SOURCES/0155-ipaddress-Allow-listing-addresses-by-type.patch @@ -0,0 +1,163 @@ +From 836bc8fd1c04199a9a2b40fc8c2cf07debb7fd0b Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 16 Jun 2016 16:41:52 +0200 +Subject: [PATCH] ipaddress: Allow listing addresses by type + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1341343 +Upstream Status: iproute2.git commit 24604eb2877a3 + +commit 24604eb2877a3be3f3167ca329b37cba178537f2 +Author: Phil Sutter <phil@nwl.cc> +Date: Thu Jun 9 19:20:36 2016 +0200 + + ipaddress: Allow listing addresses by type + + Not sure why this was limited to ip-link before. It is semantically + equal to the 'master' keyword, which is not restricted at all. + + The man page and help text adjustments include the 'master' keyword as + well since that is also supported but wasn't documented before. + + Cc: Vadim Kochan <vadim4j@gmail.com> + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + ip/ipaddress.c | 11 ++++++++-- + man/man8/ip-address.8.in | 57 +++++++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 63 insertions(+), 5 deletions(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 4720de0..f10f58a 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -73,8 +73,11 @@ static void usage(void) + fprintf(stderr, "Usage: ip address {add|change|replace} IFADDR dev IFNAME [ LIFETIME ]\n"); + fprintf(stderr, " [ CONFFLAG-LIST ]\n"); + fprintf(stderr, " ip address del IFADDR dev IFNAME [mngtmpaddr]\n"); +- fprintf(stderr, " ip address {show|save|flush} [ dev IFNAME ] [ scope SCOPE-ID ]\n"); ++ fprintf(stderr, " ip address {save|flush} [ dev IFNAME ] [ scope SCOPE-ID ]\n"); + fprintf(stderr, " [ to PREFIX ] [ FLAG-LIST ] [ label LABEL ] [up]\n"); ++ fprintf(stderr, " ip address [ show [ dev IFNAME ] [ scope SCOPE-ID ] [ master DEVICE ]\n"); ++ fprintf(stderr, " [ type TYPE ] [ to PREFIX ] [ FLAG-LIST ]\n"); ++ fprintf(stderr, " [ label LABEL ] [up] ]\n"); + fprintf(stderr, " ip address {showdump|restore}\n"); + fprintf(stderr, "IFADDR := PREFIX | ADDR peer PREFIX\n"); + fprintf(stderr, " [ broadcast ADDR ] [ anycast ADDR ]\n"); +@@ -88,6 +91,10 @@ static void usage(void) + fprintf(stderr, "CONFFLAG := [ home | nodad | mngtmpaddr | noprefixroute | autojoin ]\n"); + fprintf(stderr, "LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]\n"); + fprintf(stderr, "LFT := forever | SECONDS\n"); ++ fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n"); ++ fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n"); ++ fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n"); ++ fprintf(stderr, " bond_slave | ipvlan | geneve | bridge_slave | vrf }\n"); + + exit(-1); + } +@@ -1332,7 +1339,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) + if (!ifindex) + invarg("Device does not exist\n", *argv); + filter.master = ifindex; +- } else if (do_link && strcmp(*argv, "type") == 0) { ++ } else if (strcmp(*argv, "type") == 0) { + NEXT_ARG(); + filter.kind = *argv; + } else { +diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in +index ff3fe0b..ab0942d 100644 +--- a/man/man8/ip-address.8.in ++++ b/man/man8/ip-address.8.in +@@ -23,7 +23,7 @@ ip-address \- protocol address management + .IB IFADDR " dev " IFNAME " [ " mngtmpaddr " ]" + + .ti -8 +-.BR "ip address" " { " show " | " save " | " flush " } [ " dev ++.BR "ip address" " { " save " | " flush " } [ " dev + .IR IFNAME " ] [ " + .B scope + .IR SCOPE-ID " ] [ " +@@ -33,6 +33,21 @@ ip-address \- protocol address management + .IR PATTERN " ] [ " up " ]" + + .ti -8 ++.BR "ip address" " [ " show " [ " dev ++.IR IFNAME " ] [ " ++.B scope ++.IR SCOPE-ID " ] [ " ++.B to ++.IR PREFIX " ] [ " FLAG-LIST " ] [ " ++.B label ++.IR PATTERN " ] [ " ++.B master ++.IR DEVICE " ] [ " ++.B type ++.IR TYPE " ] [ " ++.BR up " ] ]" ++ ++.ti -8 + .BR "ip address" " { " showdump " | " restore " }" + + .ti -8 +@@ -80,6 +95,34 @@ ip-address \- protocol address management + .BR forever " |" + .IR SECONDS " ]" + ++.ti -8 ++.IR TYPE " := [ " ++.BR bridge " | " ++.BR bond " | " ++.BR can " | " ++.BR dummy " | " ++.BR hsr " | " ++.BR ifb " | " ++.BR ipoib " |" ++.BR macvlan " | " ++.BR macvtap " | " ++.BR vcan " | " ++.BR veth " | " ++.BR vlan " | " ++.BR vxlan " |" ++.BR ip6tnl " |" ++.BR ipip " |" ++.BR sit " |" ++.BR gre " |" ++.BR gretap " |" ++.BR ip6gre " |" ++.BR ip6gretap " |" ++.BR vti " |" ++.BR nlmon " |" ++.BR ipvlan " |" ++.BR lowpan " |" ++.BR geneve " ]" ++ + .SH "DESCRIPTION" + The + .B address +@@ -230,6 +273,14 @@ only list addresses with labels matching the + is a usual shell style pattern. + + .TP ++.BI master " DEVICE" ++only list interfaces enslaved to this master device. ++ ++.TP ++.BI type " TYPE" ++only list interfaces of the given type. ++ ++.TP + .B up + only list running interfaces. + +@@ -280,8 +331,8 @@ This command flushes the protocol addresses selected by some criteria. + + .PP + This command has the same arguments as +-.B show. +-The difference is that it does not run when no arguments are given. ++.BR show " except that " type " and " master " selectors are not supported." ++Another difference is that it does not run when no arguments are given. + + .PP + .B Warning: +-- +1.8.3.1 + diff --git a/SOURCES/0156-add-new-IFLA_VF_TRUST-netlink-attribute.patch b/SOURCES/0156-add-new-IFLA_VF_TRUST-netlink-attribute.patch new file mode 100644 index 0000000..613f8f5 --- /dev/null +++ b/SOURCES/0156-add-new-IFLA_VF_TRUST-netlink-attribute.patch @@ -0,0 +1,44 @@ +From 57400a02cdfa4332a927d0dbeed97d4e969fd070 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 16 Jun 2016 16:50:43 +0200 +Subject: [PATCH] add new IFLA_VF_TRUST netlink attribute + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1302119 +Upstream Status: iproute2.git commit dddf1b44126ea + +commit dddf1b44126eaa25c6698be618fb452fc7b9bed3 +Author: Stephen Hemminger <shemming@brocade.com> +Date: Fri Oct 23 15:47:07 2015 -0700 + + add new IFLA_VF_TRUST netlink attribute +--- + include/linux/if_link.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/include/linux/if_link.h b/include/linux/if_link.h +index 1934566..ca9a681 100644 +--- a/include/linux/if_link.h ++++ b/include/linux/if_link.h +@@ -499,6 +499,7 @@ enum { + * on/off switch + */ + IFLA_VF_STATS, /* network device statistics */ ++ IFLA_VF_TRUST, /* Trust VF */ + __IFLA_VF_MAX, + }; + +@@ -560,6 +561,11 @@ enum { + + #define IFLA_VF_STATS_MAX (__IFLA_VF_STATS_MAX - 1) + ++struct ifla_vf_trust { ++ __u32 vf; ++ __u32 setting; ++}; ++ + /* VF ports management section + * + * Nested layout of set/get msg is: +-- +1.8.3.1 + diff --git a/SOURCES/0157-iplink-Support-VF-Trust.patch b/SOURCES/0157-iplink-Support-VF-Trust.patch new file mode 100644 index 0000000..8020fa0 --- /dev/null +++ b/SOURCES/0157-iplink-Support-VF-Trust.patch @@ -0,0 +1,92 @@ +From 090af3d3a7fe36caa6eceb6bed51491425045ce9 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 16 Jun 2016 16:50:59 +0200 +Subject: [PATCH] iplink: Support VF Trust + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1302119 +Upstream Status: iproute2.git commit b6d77d9ee3122 +Conflicts: Context changes due to missing other features. + +commit b6d77d9ee312246146e9b5ca70a8a1426898b484 +Author: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com> +Date: Fri Feb 26 02:40:18 2016 +0000 + + iplink: Support VF Trust + + Add IFLA_VF_TRUST message to trust the VF. + PF can accept some privileged operation from the trusted VF. + For example, ixgbe PF doesn't allow to enable VF promiscuous mode until + the VF is trusted because it may hurt performance. + + To trust VF. + # ip link set dev eth0 vf 1 trust on + + To untrust VF. + # ip link set dev eth0 vf 1 trust off + + Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com> +--- + ip/iplink.c | 13 +++++++++++++ + man/man8/ip-link.8.in | 8 +++++++- + 2 files changed, 20 insertions(+), 1 deletion(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index 0f91043..84bdc56 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -81,6 +81,7 @@ void iplink_usage(void) + fprintf(stderr, " [ spoofchk { on | off} ]\n"); + fprintf(stderr, " [ query_rss { on | off} ]\n"); + fprintf(stderr, " [ state { auto | enable | disable} ] ]\n"); ++ fprintf(stderr, " [ trust { on | off} ] ]\n"); + fprintf(stderr, " [ master DEVICE ]\n"); + fprintf(stderr, " [ nomaster ]\n"); + fprintf(stderr, " [ addrgenmode { eui64 | none } ]\n"); +@@ -302,6 +303,18 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, + ivs.vf = vf; + addattr_l(&req->n, sizeof(*req), IFLA_VF_RSS_QUERY_EN, &ivs, sizeof(ivs)); + ++ } else if (matches(*argv, "trust") == 0) { ++ struct ifla_vf_trust ivt; ++ NEXT_ARG(); ++ if (matches(*argv, "on") == 0) ++ ivt.setting = 1; ++ else if (matches(*argv, "off") == 0) ++ ivt.setting = 0; ++ else ++ invarg("Invalid \"trust\" value\n", *argv); ++ ivt.vf = vf; ++ addattr_l(&req->n, sizeof(*req), IFLA_VF_TRUST, &ivt, sizeof(ivt)); ++ + } else if (matches(*argv, "state") == 0) { + struct ifla_vf_link_state ivl; + NEXT_ARG(); +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 312be6b..1d052ef 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -118,7 +118,9 @@ ip-link \- network device configuration + .RB "[ " vlan + .IR VLANID " [ " + .B qos +-.IR VLAN-QOS " ] ]" ++.IR VLAN-QOS " ] ] [" ++.B trust { on | off } ++] | + .br + .RB "[ " rate + .IR TXRATE " ]" +@@ -872,6 +874,10 @@ parameter must be specified. + .sp + .BI spoofchk " on|off" + - turn packet spoof checking on or off for the specified VF. ++.sp ++.BI trust " on|off" ++- trust the specified VF user. This enables that VF user can set a specific feature ++which may impact security and/or performance. (e.g. VF multicast promiscuous mode) + .in -8 + + .TP +-- +1.8.3.1 + diff --git a/SOURCES/0158-ip-link-Support-printing-VF-trust-setting.patch b/SOURCES/0158-ip-link-Support-printing-VF-trust-setting.patch new file mode 100644 index 0000000..ee4bd0d --- /dev/null +++ b/SOURCES/0158-ip-link-Support-printing-VF-trust-setting.patch @@ -0,0 +1,45 @@ +From 9318ed3fad1320bbe3ca61e5ed5f317331ec38d7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 16 Jun 2016 16:51:20 +0200 +Subject: [PATCH] ip-link: Support printing VF trust setting + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1302119 +Upstream Status: iproute2.git commit fe9322781e635 +Conflicts: Context changes due to missing commit a1b99717c7cd7 + ("Add displaying VF traffic statistics"). + +commit fe9322781e6351b5572cbaa8df4dd0e5ec96398a +Author: Phil Sutter <phil@nwl.cc> +Date: Thu Mar 31 14:43:32 2016 +0200 + + ip-link: Support printing VF trust setting + + This adds a new item to VF lines of a PF, stating whether the VF is + trusted or not. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + ip/ipaddress.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index f10f58a..05e0da9 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -356,6 +356,13 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo) + else + fprintf(fp, ", link-state disable"); + } ++ if (vf[IFLA_VF_TRUST]) { ++ struct ifla_vf_trust *vf_trust = RTA_DATA(vf[IFLA_VF_TRUST]); ++ ++ if (vf_trust->setting != -1) ++ fprintf(fp, ", trust %s", ++ vf_trust->setting ? "on" : "off"); ++ } + } + + static void print_num(FILE *fp, unsigned width, uint64_t count) +-- +1.8.3.1 + diff --git a/SOURCES/0159-man-ip-link.8-Fix-ip-link-delete-description.patch b/SOURCES/0159-man-ip-link.8-Fix-ip-link-delete-description.patch new file mode 100644 index 0000000..9228b0d --- /dev/null +++ b/SOURCES/0159-man-ip-link.8-Fix-ip-link-delete-description.patch @@ -0,0 +1,43 @@ +From 5b52a263b3e8b9b86100f3e69923401cb5be1cbd Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 23 Jun 2016 22:33:18 +0200 +Subject: [PATCH] man: ip-link.8: Fix 'ip link delete' description + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1341343 +Upstream Status: Side effect of iproute2.git commit 7f74cf6de03a3 + +This is not a backport as the above mentioned upstream commit does +something completely different and we only want the man page fix it +contains. +--- + man/man8/ip-link.8.in | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 1d052ef..c9ccf23 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -709,15 +709,14 @@ using standard tools. + .in -8 + + .SS ip link delete - delete virtual link +-.I DEVICE +-specifies the virtual device to act operate on. +-.I TYPE +-specifies the type of the device. +- + + .TP + .BI dev " DEVICE " +-specifies the physical device to act operate on. ++specifies the virtual device to act operate on. ++ ++.TP ++.BI type " TYPE " ++specifies the type of the device. + + .SS ip link set - change device attributes + +-- +1.8.3.1 + diff --git a/SOURCES/0160-man-ip-address-ip-link-Document-type-quirk.patch b/SOURCES/0160-man-ip-address-ip-link-Document-type-quirk.patch new file mode 100644 index 0000000..c4bd43a --- /dev/null +++ b/SOURCES/0160-man-ip-address-ip-link-Document-type-quirk.patch @@ -0,0 +1,60 @@ +From 7384fd2e31a9284f2ded443666fb91eabc15b75b Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Fri, 1 Jul 2016 20:36:52 +0200 +Subject: [PATCH] man: ip-address, ip-link: Document 'type' quirk + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1341343 +Upstream Status: iproute2.git commit 3462c116f8dd5 + +commit 3462c116f8dd578591f5f41d249d7542ea476ca4 +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Jun 24 12:14:23 2016 +0200 + + man: ip-address, ip-link: Document 'type' quirk + + This covers the fact that calling 'ip {link|addr} show type foobar' does + not return an error. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/ip-address.8.in | 6 ++++++ + man/man8/ip-link.8.in | 6 ++++++ + 2 files changed, 12 insertions(+) + +diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in +index ab0942d..8d34adb 100644 +--- a/man/man8/ip-address.8.in ++++ b/man/man8/ip-address.8.in +@@ -280,6 +280,12 @@ only list interfaces enslaved to this master device. + .BI type " TYPE" + only list interfaces of the given type. + ++Note that the type name is not checked against the list of supported types - ++instead it is sent as-is to the kernel. Later it is used to filter the returned ++interface list by comparing it with the relevant attribute in case the kernel ++didn't filter already. Therefore any string is accepted, but may lead to empty ++output. ++ + .TP + .B up + only list running interfaces. +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index c9ccf23..5e4862f 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -934,6 +934,12 @@ specifies the master device which enslaves devices to show. + .I TYPE + specifies the type of devices to show. + ++Note that the type name is not checked against the list of supported types - ++instead it is sent as-is to the kernel. Later it is used to filter the returned ++interface list by comparing it with the relevant attribute in case the kernel ++didn't filter already. Therefore any string is accepted, but may lead to empty ++output. ++ + .SS ip link help - display help + + .PP +-- +1.8.3.1 + diff --git a/SOURCES/0161-iproute2-GENEVE-support.patch b/SOURCES/0161-iproute2-GENEVE-support.patch new file mode 100644 index 0000000..a6985c4 --- /dev/null +++ b/SOURCES/0161-iproute2-GENEVE-support.patch @@ -0,0 +1,201 @@ +From 66373cc86a92570198bc282fde92782d8a256966 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 2 Jul 2016 12:42:24 +0200 +Subject: [PATCH] iproute2: GENEVE support + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1339178 +Upstream Status: iproute2.git commit 908755dc49df0 +Conflicts: + - Context changes due to missing interface type support for hsr, fou + and ipvlan. + - Added missing IFLA_GENEVE_* defines. + +commit 908755dc49df0beffd12c8cad91e425e5be76888 +Author: John W. Linville <linville@tuxdriver.com> +Date: Fri May 8 13:27:08 2015 -0400 + + iproute2: GENEVE support + + Signed-off-by: John W. Linville <linville@tuxdriver.com> +--- + include/linux/if_link.h | 5 ++ + ip/Makefile | 3 +- + ip/iplink.c | 2 +- + ip/iplink_geneve.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 130 insertions(+), 2 deletions(-) + create mode 100644 ip/iplink_geneve.c + +diff --git a/include/linux/if_link.h b/include/linux/if_link.h +index ca9a681..73b5556 100644 +--- a/include/linux/if_link.h ++++ b/include/linux/if_link.h +@@ -410,6 +410,11 @@ enum { + IFLA_GENEVE_TOS, + IFLA_GENEVE_PORT, /* destination port */ + IFLA_GENEVE_COLLECT_METADATA, ++ IFLA_GENEVE_REMOTE6, ++ IFLA_GENEVE_UDP_CSUM, ++ IFLA_GENEVE_UDP_ZERO_CSUM6_TX, ++ IFLA_GENEVE_UDP_ZERO_CSUM6_RX, ++ IFLA_GENEVE_LABEL, + __IFLA_GENEVE_MAX + }; + #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) +diff --git a/ip/Makefile b/ip/Makefile +index e4f0507..5aad224 100644 +--- a/ip/Makefile ++++ b/ip/Makefile +@@ -6,7 +6,8 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ + iplink_macvlan.o ipl2tp.o link_vti.o link_vti6.o \ + iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \ + link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o \ +- iplink_bridge.o iplink_bridge_slave.o ++ iplink_bridge.o iplink_bridge_slave.o \ ++ iplink_geneve.o + + RTMONOBJ=rtmon.o + +diff --git a/ip/iplink.c b/ip/iplink.c +index 84bdc56..0e2390d 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -93,7 +93,7 @@ void iplink_usage(void) + fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n"); + fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n"); + fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n"); +- fprintf(stderr, " bond_slave }\n"); ++ fprintf(stderr, " bond_slave | geneve }\n"); + } + exit(-1); + } +diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c +new file mode 100644 +index 0000000..74703e1 +--- /dev/null ++++ b/ip/iplink_geneve.c +@@ -0,0 +1,122 @@ ++/* ++ * iplink_geneve.c GENEVE device support ++ * ++ * 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. ++ * ++ * Authors: John W. Linville <linville@tuxdriver.com> ++ */ ++ ++#include <stdio.h> ++ ++#include "utils.h" ++#include "ip_common.h" ++ ++static void print_explain(FILE *f) ++{ ++ fprintf(f, "Usage: ... geneve id VNI remote ADDR\n"); ++ fprintf(f, "\n"); ++ fprintf(f, "Where: VNI := 0-16777215\n"); ++ fprintf(f, " ADDR := IP_ADDRESS\n"); ++} ++ ++static void explain(void) ++{ ++ print_explain(stderr); ++} ++ ++static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, ++ struct nlmsghdr *n) ++{ ++ __u32 vni = 0; ++ int vni_set = 0; ++ __u32 daddr = 0; ++ struct in6_addr daddr6 = IN6ADDR_ANY_INIT; ++ ++ ++ while (argc > 0) { ++ if (!matches(*argv, "id") || ++ !matches(*argv, "vni")) { ++ NEXT_ARG(); ++ if (get_u32(&vni, *argv, 0) || ++ vni >= 1u << 24) ++ invarg("invalid id", *argv); ++ vni_set = 1; ++ } else if (!matches(*argv, "remote")) { ++ NEXT_ARG(); ++ if (!inet_get_addr(*argv, &daddr, &daddr6)) { ++ fprintf(stderr, "Invalid address \"%s\"\n", *argv); ++ return -1; ++ } ++ if (IN_MULTICAST(ntohl(daddr))) ++ invarg("invalid remote address", *argv); ++ } else if (matches(*argv, "help") == 0) { ++ explain(); ++ return -1; ++ } else { ++ fprintf(stderr, "geneve: unknown command \"%s\"?\n", *argv); ++ explain(); ++ return -1; ++ } ++ argc--, argv++; ++ } ++ ++ if (!vni_set) { ++ fprintf(stderr, "geneve: missing virtual network identifier\n"); ++ return -1; ++ } ++ ++ if (!daddr) { ++ fprintf(stderr, "geneve: remove link partner not specified\n"); ++ return -1; ++ } ++ if (memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) != 0) { ++ fprintf(stderr, "geneve: remove link over IPv6 not supported\n"); ++ return -1; ++ } ++ ++ addattr32(n, 1024, IFLA_GENEVE_ID, vni); ++ if (daddr) ++ addattr_l(n, 1024, IFLA_GENEVE_REMOTE, &daddr, 4); ++ ++ return 0; ++} ++ ++static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) ++{ ++ __u32 vni; ++ char s1[1024]; ++ ++ if (!tb) ++ return; ++ ++ if (!tb[IFLA_GENEVE_ID] || ++ RTA_PAYLOAD(tb[IFLA_GENEVE_ID]) < sizeof(__u32)) ++ return; ++ ++ vni = rta_getattr_u32(tb[IFLA_GENEVE_ID]); ++ fprintf(f, "id %u ", vni); ++ ++ if (tb[IFLA_GENEVE_REMOTE]) { ++ __be32 addr = rta_getattr_u32(tb[IFLA_GENEVE_REMOTE]); ++ if (addr) ++ fprintf(f, "remote %s ", ++ format_host(AF_INET, 4, &addr, s1, sizeof(s1))); ++ } ++} ++ ++static void geneve_print_help(struct link_util *lu, int argc, char **argv, ++ FILE *f) ++{ ++ print_explain(f); ++} ++ ++struct link_util geneve_link_util = { ++ .id = "geneve", ++ .maxattr = IFLA_GENEVE_MAX, ++ .parse_opt = geneve_parse_opt, ++ .print_opt = geneve_print_opt, ++ .print_help = geneve_print_help, ++}; +-- +1.8.3.1 + diff --git a/SOURCES/0162-iproute2-update-ip-link.8-for-geneve-tunnels.patch b/SOURCES/0162-iproute2-update-ip-link.8-for-geneve-tunnels.patch new file mode 100644 index 0000000..0e90b85 --- /dev/null +++ b/SOURCES/0162-iproute2-update-ip-link.8-for-geneve-tunnels.patch @@ -0,0 +1,75 @@ +From 99659a911616298190930b2bf370bd2794973723 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 2 Jul 2016 12:43:58 +0200 +Subject: [PATCH] iproute2: update ip-link.8 for geneve tunnels + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1339178 +Upstream Status: iproute2.git commit c1a1d8bc4c2f1 +Conflicts: Context changes due to missing lowpan interface type support + and previously added MACVLAN/MACVTAP support. + +commit c1a1d8bc4c2f1da2f4ed5f11e3d9edc276c0c8d1 +Author: John W. Linville <linville@tuxdriver.com> +Date: Fri May 22 14:46:46 2015 -0400 + + iproute2: update ip-link.8 for geneve tunnels + + Signed-off-by: John W. Linville <linville@tuxdriver.com> +--- + man/man8/ip-link.8.in | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 5e4862f..21503ff 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -60,7 +60,8 @@ ip-link \- network device configuration + .BR ip6gretap " |" + .BR vti " |" + .BR nlmon " |" +-.BR ipvlan " ]" ++.BR ipvlan " |" ++.BR geneve " ]" + + .ti -8 + .BI "ip link delete " DEVICE +@@ -231,6 +232,9 @@ Link types: + .sp + .BR ipvlan + - Interface for L3 (IPv6/IPv4) based VLANs ++.sp ++.BR geneve ++- GEneric NEtwork Virtualization Encapsulation + .in -8 + + .TP +@@ -659,6 +663,26 @@ the following additional arguments are supported: + - specifies the mode (datagram or connected) to use. + + .TP ++GENEVE Type Support ++For a link of type ++.I GENEVE ++the following additional arguments are supported: ++ ++.BI "ip link add " DEVICE ++.BI type " geneve " id " ID " remote " IPADDR" ++ ++.in +8 ++.sp ++.BI id " VNI " ++- specifies the Virtual Network Identifer to use. ++ ++.sp ++.BI remote " IPADDR" ++- specifies the unicast destination IP address to use in outgoing packets. ++ ++.in -8 ++ ++.TP + MACVLAN and MACVTAP Type Support + For a link of type + .I MACVLAN +-- +1.8.3.1 + diff --git a/SOURCES/0163-iplink_geneve-add-ttl-configuration-at-link-creation.patch b/SOURCES/0163-iplink_geneve-add-ttl-configuration-at-link-creation.patch new file mode 100644 index 0000000..49f7f50 --- /dev/null +++ b/SOURCES/0163-iplink_geneve-add-ttl-configuration-at-link-creation.patch @@ -0,0 +1,114 @@ +From 9e871fce2cd86c1e7ee7db0b7f658b63c6b70c84 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 2 Jul 2016 12:45:04 +0200 +Subject: [PATCH] iplink_geneve: add ttl configuration at link creation + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1339178 +Upstream Status: iproute2.git commit f4c05c2e99538 +Conflicts: Context changes due to already updated kernel headers. + +commit f4c05c2e9953810c42e37ae21f6970c1f024fa46 +Author: John W. Linville <linville@tuxdriver.com> +Date: Mon Jun 15 14:37:15 2015 -0400 + + iplink_geneve: add ttl configuration at link creation + + Signed-off-by: John W. Linville <linville@tuxdriver.com> +--- + ip/iplink_geneve.c | 23 ++++++++++++++++++++++- + man/man8/ip-link.8.in | 7 +++++++ + 2 files changed, 29 insertions(+), 1 deletion(-) + +diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c +index 74703e1..dff08a6 100644 +--- a/ip/iplink_geneve.c ++++ b/ip/iplink_geneve.c +@@ -17,9 +17,11 @@ + static void print_explain(FILE *f) + { + fprintf(f, "Usage: ... geneve id VNI remote ADDR\n"); ++ fprintf(f, " [ ttl TTL ]\n"); + fprintf(f, "\n"); + fprintf(f, "Where: VNI := 0-16777215\n"); + fprintf(f, " ADDR := IP_ADDRESS\n"); ++ fprintf(f, " TTL := { 1..255 | inherit }\n"); + } + + static void explain(void) +@@ -34,7 +36,7 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + int vni_set = 0; + __u32 daddr = 0; + struct in6_addr daddr6 = IN6ADDR_ANY_INIT; +- ++ __u8 ttl = 0; + + while (argc > 0) { + if (!matches(*argv, "id") || +@@ -52,6 +54,18 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + } + if (IN_MULTICAST(ntohl(daddr))) + invarg("invalid remote address", *argv); ++ } else if (!matches(*argv, "ttl") || ++ !matches(*argv, "hoplimit")) { ++ unsigned uval; ++ ++ NEXT_ARG(); ++ if (strcmp(*argv, "inherit") != 0) { ++ if (get_unsigned(&uval, *argv, 0)) ++ invarg("invalid TTL", *argv); ++ if (uval > 255) ++ invarg("TTL must be <= 255", *argv); ++ ttl = uval; ++ } + } else if (matches(*argv, "help") == 0) { + explain(); + return -1; +@@ -80,6 +94,7 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + addattr32(n, 1024, IFLA_GENEVE_ID, vni); + if (daddr) + addattr_l(n, 1024, IFLA_GENEVE_REMOTE, &daddr, 4); ++ addattr8(n, 1024, IFLA_GENEVE_TTL, ttl); + + return 0; + } +@@ -105,6 +120,12 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + fprintf(f, "remote %s ", + format_host(AF_INET, 4, &addr, s1, sizeof(s1))); + } ++ ++ if (tb[IFLA_GENEVE_TTL]) { ++ __u8 ttl = rta_getattr_u8(tb[IFLA_GENEVE_TTL]); ++ if (ttl) ++ fprintf(f, "ttl %d ", ttl); ++ } + } + + static void geneve_print_help(struct link_util *lu, int argc, char **argv, +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 21503ff..284ee13 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -670,6 +670,9 @@ the following additional arguments are supported: + + .BI "ip link add " DEVICE + .BI type " geneve " id " ID " remote " IPADDR" ++.R " [ " ++.BI ttl " TTL " ++.R " ]" + + .in +8 + .sp +@@ -680,6 +683,10 @@ the following additional arguments are supported: + .BI remote " IPADDR" + - specifies the unicast destination IP address to use in outgoing packets. + ++.sp ++.BI ttl " TTL" ++- specifies the TTL value to use in outgoing packets. ++ + .in -8 + + .TP +-- +1.8.3.1 + diff --git a/SOURCES/0164-iplink_geneve-add-tos-configuration-at-link-creation.patch b/SOURCES/0164-iplink_geneve-add-tos-configuration-at-link-creation.patch new file mode 100644 index 0000000..37f02ca --- /dev/null +++ b/SOURCES/0164-iplink_geneve-add-tos-configuration-at-link-creation.patch @@ -0,0 +1,129 @@ +From a57db8e46974abc5b942ba2f617761da90a13eff Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 2 Jul 2016 12:45:39 +0200 +Subject: [PATCH] iplink_geneve: add tos configuration at link creation + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1339178 +Upstream Status: iproute2.git commit f4739b2ee780e +Conflicts: Context changes due to already updated kernel headers. + +commit f4739b2ee780e8bba51945bf9f37d3459b67102f +Author: John W. Linville <linville@tuxdriver.com> +Date: Mon Jun 15 14:37:16 2015 -0400 + + iplink_geneve: add tos configuration at link creation + + Signed-off-by: John W. Linville <linville@tuxdriver.com> +--- + ip/iplink_geneve.c | 26 +++++++++++++++++++++++++- + man/man8/ip-link.8.in | 6 ++++++ + 2 files changed, 31 insertions(+), 1 deletion(-) + +diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c +index dff08a6..331240a 100644 +--- a/ip/iplink_geneve.c ++++ b/ip/iplink_geneve.c +@@ -11,16 +11,18 @@ + + #include <stdio.h> + ++#include "rt_names.h" + #include "utils.h" + #include "ip_common.h" + + static void print_explain(FILE *f) + { + fprintf(f, "Usage: ... geneve id VNI remote ADDR\n"); +- fprintf(f, " [ ttl TTL ]\n"); ++ fprintf(f, " [ ttl TTL ] [ tos TOS ]\n"); + fprintf(f, "\n"); + fprintf(f, "Where: VNI := 0-16777215\n"); + fprintf(f, " ADDR := IP_ADDRESS\n"); ++ fprintf(f, " TOS := { NUMBER | inherit }\n"); + fprintf(f, " TTL := { 1..255 | inherit }\n"); + } + +@@ -37,6 +39,7 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + __u32 daddr = 0; + struct in6_addr daddr6 = IN6ADDR_ANY_INIT; + __u8 ttl = 0; ++ __u8 tos = 0; + + while (argc > 0) { + if (!matches(*argv, "id") || +@@ -66,6 +69,17 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + invarg("TTL must be <= 255", *argv); + ttl = uval; + } ++ } else if (!matches(*argv, "tos") || ++ !matches(*argv, "dsfield")) { ++ __u32 uval; ++ ++ NEXT_ARG(); ++ if (strcmp(*argv, "inherit") != 0) { ++ if (rtnl_dsfield_a2n(&uval, *argv)) ++ invarg("bad TOS value", *argv); ++ tos = uval; ++ } else ++ tos = 1; + } else if (matches(*argv, "help") == 0) { + explain(); + return -1; +@@ -95,6 +109,7 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + if (daddr) + addattr_l(n, 1024, IFLA_GENEVE_REMOTE, &daddr, 4); + addattr8(n, 1024, IFLA_GENEVE_TTL, ttl); ++ addattr8(n, 1024, IFLA_GENEVE_TOS, tos); + + return 0; + } +@@ -103,6 +118,7 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + { + __u32 vni; + char s1[1024]; ++ __u8 tos; + + if (!tb) + return; +@@ -126,6 +142,14 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + if (ttl) + fprintf(f, "ttl %d ", ttl); + } ++ ++ if (tb[IFLA_GENEVE_TOS] && ++ (tos = rta_getattr_u8(tb[IFLA_GENEVE_TOS]))) { ++ if (tos == 1) ++ fprintf(f, "tos inherit "); ++ else ++ fprintf(f, "tos %#x ", tos); ++ } + } + + static void geneve_print_help(struct link_util *lu, int argc, char **argv, +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 284ee13..31a6190 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -672,6 +672,8 @@ the following additional arguments are supported: + .BI type " geneve " id " ID " remote " IPADDR" + .R " [ " + .BI ttl " TTL " ++.R " ] [ " ++.BI tos " TOS " + .R " ]" + + .in +8 +@@ -687,6 +689,10 @@ the following additional arguments are supported: + .BI ttl " TTL" + - specifies the TTL value to use in outgoing packets. + ++.sp ++.BI tos " TOS" ++- specifies the TOS value to use in outgoing packets. ++ + .in -8 + + .TP +-- +1.8.3.1 + diff --git a/SOURCES/0165-geneve-add-support-for-IPv6-link-partners.patch b/SOURCES/0165-geneve-add-support-for-IPv6-link-partners.patch new file mode 100644 index 0000000..621b317 --- /dev/null +++ b/SOURCES/0165-geneve-add-support-for-IPv6-link-partners.patch @@ -0,0 +1,73 @@ +From 0d9e19857745be8b49d5bca762bf4bdeaa977b08 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 2 Jul 2016 12:46:03 +0200 +Subject: [PATCH] geneve: add support for IPv6 link partners + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1339178 +Upstream Status: iproute2.git commit 906ac5437ab8e + +commit 906ac5437ab8e1e5f8514afe62bf01e1ff3906af +Author: John W. Linville <linville@tuxdriver.com> +Date: Thu Sep 24 14:39:39 2015 -0400 + + geneve: add support for IPv6 link partners + + Signed-off-by: John W. Linville <linville@tuxdriver.com> +--- + ip/iplink_geneve.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c +index 331240a..1345479 100644 +--- a/ip/iplink_geneve.c ++++ b/ip/iplink_geneve.c +@@ -55,7 +55,7 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + fprintf(stderr, "Invalid address \"%s\"\n", *argv); + return -1; + } +- if (IN_MULTICAST(ntohl(daddr))) ++ if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr))) + invarg("invalid remote address", *argv); + } else if (!matches(*argv, "ttl") || + !matches(*argv, "hoplimit")) { +@@ -96,18 +96,16 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + return -1; + } + +- if (!daddr) { +- fprintf(stderr, "geneve: remove link partner not specified\n"); +- return -1; +- } +- if (memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) != 0) { +- fprintf(stderr, "geneve: remove link over IPv6 not supported\n"); ++ if (!daddr && memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) == 0) { ++ fprintf(stderr, "geneve: remote link partner not specified\n"); + return -1; + } + + addattr32(n, 1024, IFLA_GENEVE_ID, vni); + if (daddr) + addattr_l(n, 1024, IFLA_GENEVE_REMOTE, &daddr, 4); ++ if (memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) != 0) ++ addattr_l(n, 1024, IFLA_GENEVE_REMOTE6, &daddr6, sizeof(struct in6_addr)); + addattr8(n, 1024, IFLA_GENEVE_TTL, ttl); + addattr8(n, 1024, IFLA_GENEVE_TOS, tos); + +@@ -135,6 +133,14 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + if (addr) + fprintf(f, "remote %s ", + format_host(AF_INET, 4, &addr, s1, sizeof(s1))); ++ } else if (tb[IFLA_GENEVE_REMOTE6]) { ++ struct in6_addr addr; ++ memcpy(&addr, RTA_DATA(tb[IFLA_GENEVE_REMOTE6]), sizeof(struct in6_addr)); ++ if (memcmp(&addr, &in6addr_any, sizeof(addr)) != 0) { ++ if (IN6_IS_ADDR_MULTICAST(&addr)) ++ fprintf(f, "remote %s ", ++ format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1))); ++ } + } + + if (tb[IFLA_GENEVE_TTL]) { +-- +1.8.3.1 + diff --git a/SOURCES/0166-geneve-add-support-for-lwt-tunnel-creation-and-dst-p.patch b/SOURCES/0166-geneve-add-support-for-lwt-tunnel-creation-and-dst-p.patch new file mode 100644 index 0000000..0f2b33c --- /dev/null +++ b/SOURCES/0166-geneve-add-support-for-lwt-tunnel-creation-and-dst-p.patch @@ -0,0 +1,117 @@ +From ce4a302b676ce7e47237c4c20b3c1c3b3721ed3e Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 2 Jul 2016 12:46:03 +0200 +Subject: [PATCH] geneve: add support for lwt tunnel creation and dst port + selection + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1339178 +Upstream Status: iproute2.git commit 9450c5ec63b0c + +commit 9450c5ec63b0cc4068b363eae7c71b024fc25121 +Author: Paolo Abeni <pabeni@redhat.com> +Date: Thu Jan 28 14:48:55 2016 +0100 + + geneve: add support for lwt tunnel creation and dst port selection + + This change add the ability to create lwt/flow based/externally + controlled geneve device and to select the udp destination port used + by a full geneve tunnel. + + Signed-off-by: Paolo Abeni <pabeni@redhat.com> +--- + ip/iplink_geneve.c | 41 ++++++++++++++++++++++++++++++++++++----- + 1 file changed, 36 insertions(+), 5 deletions(-) + +diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c +index 1345479..30b16b9 100644 +--- a/ip/iplink_geneve.c ++++ b/ip/iplink_geneve.c +@@ -19,6 +19,7 @@ static void print_explain(FILE *f) + { + fprintf(f, "Usage: ... geneve id VNI remote ADDR\n"); + fprintf(f, " [ ttl TTL ] [ tos TOS ]\n"); ++ fprintf(f, " [ dstport PORT ] [ [no]external ]\n"); + fprintf(f, "\n"); + fprintf(f, "Where: VNI := 0-16777215\n"); + fprintf(f, " ADDR := IP_ADDRESS\n"); +@@ -40,6 +41,8 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + struct in6_addr daddr6 = IN6ADDR_ANY_INIT; + __u8 ttl = 0; + __u8 tos = 0; ++ __u16 dstport = 0; ++ bool metadata = 0; + + while (argc > 0) { + if (!matches(*argv, "id") || +@@ -80,6 +83,14 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + tos = uval; + } else + tos = 1; ++ } else if (!matches(*argv, "dstport")) { ++ NEXT_ARG(); ++ if (get_u16(&dstport, *argv, 0)) ++ invarg("dstport", *argv); ++ } else if (!matches(*argv, "external")) { ++ metadata = true; ++ } else if (!matches(*argv, "noexternal")) { ++ metadata = false; + } else if (matches(*argv, "help") == 0) { + explain(); + return -1; +@@ -91,14 +102,22 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + argc--, argv++; + } + +- if (!vni_set) { +- fprintf(stderr, "geneve: missing virtual network identifier\n"); ++ if (metadata && vni_set) { ++ fprintf(stderr, "geneve: both 'external' and vni cannot be specified\n"); + return -1; + } + +- if (!daddr && memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) == 0) { +- fprintf(stderr, "geneve: remote link partner not specified\n"); +- return -1; ++ if (!metadata) { ++ /* parameter checking make sense only for full geneve tunnels */ ++ if (!vni_set) { ++ fprintf(stderr, "geneve: missing virtual network identifier\n"); ++ return -1; ++ } ++ ++ if (!daddr && memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) == 0) { ++ fprintf(stderr, "geneve: remote link partner not specified\n"); ++ return -1; ++ } + } + + addattr32(n, 1024, IFLA_GENEVE_ID, vni); +@@ -108,6 +127,10 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + addattr_l(n, 1024, IFLA_GENEVE_REMOTE6, &daddr6, sizeof(struct in6_addr)); + addattr8(n, 1024, IFLA_GENEVE_TTL, ttl); + addattr8(n, 1024, IFLA_GENEVE_TOS, tos); ++ if (dstport) ++ addattr16(n, 1024, IFLA_GENEVE_PORT, htons(dstport)); ++ if (metadata) ++ addattr(n, 1024, IFLA_GENEVE_COLLECT_METADATA); + + return 0; + } +@@ -156,6 +179,14 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + else + fprintf(f, "tos %#x ", tos); + } ++ ++ if (tb[IFLA_GENEVE_PORT]) ++ fprintf(f, "dstport %u ", ++ ntohs(rta_getattr_u16(tb[IFLA_GENEVE_PORT]))); ++ ++ if (tb[IFLA_GENEVE_COLLECT_METADATA]) ++ fputs("external ", f); ++ + } + + static void geneve_print_help(struct link_util *lu, int argc, char **argv, +-- +1.8.3.1 + diff --git a/SOURCES/0167-geneve-Add-support-for-configuring-UDP-checksums.patch b/SOURCES/0167-geneve-Add-support-for-configuring-UDP-checksums.patch new file mode 100644 index 0000000..7183ec4 --- /dev/null +++ b/SOURCES/0167-geneve-Add-support-for-configuring-UDP-checksums.patch @@ -0,0 +1,113 @@ +From 95f2a6b5b5d0065cd08cf23bb0ad6dda510454cf Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 2 Jul 2016 12:46:04 +0200 +Subject: [PATCH] geneve: Add support for configuring UDP checksums. + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1339178 +Upstream Status: iproute2.git commit 325d02b44ce31 + +commit 325d02b44ce3194a6d7a57e6a46b5ed767b61025 +Author: Jesse Gross <jesse@kernel.org> +Date: Fri Mar 18 17:51:09 2016 -0700 + + geneve: Add support for configuring UDP checksums. + + Enable support for configuring outer UDP checksums on Geneve tunnels: + + ip link add type geneve id 10 remote 10.0.0.2 udpcsum + + Signed-off-by: Jesse Gross <jesse@kernel.org> +--- + ip/iplink_geneve.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 48 insertions(+) + +diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c +index 30b16b9..13a6d80 100644 +--- a/ip/iplink_geneve.c ++++ b/ip/iplink_geneve.c +@@ -20,6 +20,7 @@ static void print_explain(FILE *f) + fprintf(f, "Usage: ... geneve id VNI remote ADDR\n"); + fprintf(f, " [ ttl TTL ] [ tos TOS ]\n"); + fprintf(f, " [ dstport PORT ] [ [no]external ]\n"); ++ fprintf(f, " [ [no]udpcsum ] [ [no]udp6zerocsumtx ] [ [no]udp6zerocsumrx ]\n"); + fprintf(f, "\n"); + fprintf(f, "Where: VNI := 0-16777215\n"); + fprintf(f, " ADDR := IP_ADDRESS\n"); +@@ -43,6 +44,12 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + __u8 tos = 0; + __u16 dstport = 0; + bool metadata = 0; ++ __u8 udpcsum = 0; ++ bool udpcsum_set = false; ++ __u8 udp6zerocsumtx = 0; ++ bool udp6zerocsumtx_set = false; ++ __u8 udp6zerocsumrx = 0; ++ bool udp6zerocsumrx_set = false; + + while (argc > 0) { + if (!matches(*argv, "id") || +@@ -91,6 +98,24 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + metadata = true; + } else if (!matches(*argv, "noexternal")) { + metadata = false; ++ } else if (!matches(*argv, "udpcsum")) { ++ udpcsum = 1; ++ udpcsum_set = true; ++ } else if (!matches(*argv, "noudpcsum")) { ++ udpcsum = 0; ++ udpcsum_set = true; ++ } else if (!matches(*argv, "udp6zerocsumtx")) { ++ udp6zerocsumtx = 1; ++ udp6zerocsumtx_set = true; ++ } else if (!matches(*argv, "noudp6zerocsumtx")) { ++ udp6zerocsumtx = 0; ++ udp6zerocsumtx_set = true; ++ } else if (!matches(*argv, "udp6zerocsumrx")) { ++ udp6zerocsumrx = 1; ++ udp6zerocsumrx_set = true; ++ } else if (!matches(*argv, "noudp6zerocsumrx")) { ++ udp6zerocsumrx = 0; ++ udp6zerocsumrx_set = true; + } else if (matches(*argv, "help") == 0) { + explain(); + return -1; +@@ -131,6 +156,12 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + addattr16(n, 1024, IFLA_GENEVE_PORT, htons(dstport)); + if (metadata) + addattr(n, 1024, IFLA_GENEVE_COLLECT_METADATA); ++ if (udpcsum_set) ++ addattr8(n, 1024, IFLA_GENEVE_UDP_CSUM, udpcsum); ++ if (udp6zerocsumtx_set) ++ addattr8(n, 1024, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, udp6zerocsumtx); ++ if (udp6zerocsumrx_set) ++ addattr8(n, 1024, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, udp6zerocsumrx); + + return 0; + } +@@ -187,6 +218,23 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + if (tb[IFLA_GENEVE_COLLECT_METADATA]) + fputs("external ", f); + ++ if (tb[IFLA_GENEVE_UDP_CSUM]) { ++ if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_CSUM])) ++ fputs("no", f); ++ fputs("udpcsum ", f); ++ } ++ ++ if (tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]) { ++ if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX])) ++ fputs("no", f); ++ fputs("udp6zerocsumtx ", f); ++ } ++ ++ if (tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]) { ++ if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX])) ++ fputs("no", f); ++ fputs("udp6zerocsumrx ", f); ++ } + } + + static void geneve_print_help(struct link_util *lu, int argc, char **argv, +-- +1.8.3.1 + diff --git a/SOURCES/0168-geneve-add-support-to-set-flow-label.patch b/SOURCES/0168-geneve-add-support-to-set-flow-label.patch new file mode 100644 index 0000000..ffd1d8f --- /dev/null +++ b/SOURCES/0168-geneve-add-support-to-set-flow-label.patch @@ -0,0 +1,137 @@ +From 20d649d4bb017d5c8280205db545a274b15ae21c Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 2 Jul 2016 12:46:04 +0200 +Subject: [PATCH] geneve: add support to set flow label + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1339178 +Upstream Status: iproute2.git commit 29bb2373a8777 +Conflicts: + - Missing formatting cleanup changes. + - Added missing LABEL_MAX_MASK define. + +commit 29bb2373a8777d0c8b8c68450a872c19bc7f245c +Author: Daniel Borkmann <daniel@iogearbox.net> +Date: Thu Mar 24 16:49:56 2016 +0100 + + geneve: add support to set flow label + + Follow-up for kernel commit 8eb3b99554b8 ("geneve: support setting + IPv6 flow label") to allow setting the label for the device config. + + Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> +--- + ip/ip_common.h | 4 ++++ + ip/iplink_geneve.c | 29 ++++++++++++++++++++++++----- + man/man8/ip-link.8.in | 6 ++++++ + 3 files changed, 34 insertions(+), 5 deletions(-) + +diff --git a/ip/ip_common.h b/ip/ip_common.h +index 917fcf8..880890e 100644 +--- a/ip/ip_common.h ++++ b/ip/ip_common.h +@@ -90,3 +90,7 @@ struct link_util *get_link_slave_kind(const char *slave_kind); + #ifndef INFINITY_LIFE_TIME + #define INFINITY_LIFE_TIME 0xFFFFFFFFU + #endif ++ ++#ifndef LABEL_MAX_MASK ++#define LABEL_MAX_MASK 0xFFFFFU ++#endif +diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c +index 13a6d80..fb0c6b1 100644 +--- a/ip/iplink_geneve.c ++++ b/ip/iplink_geneve.c +@@ -18,14 +18,15 @@ + static void print_explain(FILE *f) + { + fprintf(f, "Usage: ... geneve id VNI remote ADDR\n"); +- fprintf(f, " [ ttl TTL ] [ tos TOS ]\n"); ++ fprintf(f, " [ ttl TTL ] [ tos TOS ] [ flowlabel LABEL ]\n"); + fprintf(f, " [ dstport PORT ] [ [no]external ]\n"); + fprintf(f, " [ [no]udpcsum ] [ [no]udp6zerocsumtx ] [ [no]udp6zerocsumrx ]\n"); + fprintf(f, "\n"); +- fprintf(f, "Where: VNI := 0-16777215\n"); +- fprintf(f, " ADDR := IP_ADDRESS\n"); +- fprintf(f, " TOS := { NUMBER | inherit }\n"); +- fprintf(f, " TTL := { 1..255 | inherit }\n"); ++ fprintf(f, "Where: VNI := 0-16777215\n"); ++ fprintf(f, " ADDR := IP_ADDRESS\n"); ++ fprintf(f, " TOS := { NUMBER | inherit }\n"); ++ fprintf(f, " TTL := { 1..255 | inherit }\n"); ++ fprintf(f, " LABEL := 0-1048575\n"); + } + + static void explain(void) +@@ -40,6 +41,7 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + int vni_set = 0; + __u32 daddr = 0; + struct in6_addr daddr6 = IN6ADDR_ANY_INIT; ++ __u32 label = 0; + __u8 ttl = 0; + __u8 tos = 0; + __u16 dstport = 0; +@@ -90,6 +92,15 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + tos = uval; + } else + tos = 1; ++ } else if (!matches(*argv, "label") || ++ !matches(*argv, "flowlabel")) { ++ __u32 uval; ++ ++ NEXT_ARG(); ++ if (get_u32(&uval, *argv, 0) || ++ (uval & ~LABEL_MAX_MASK)) ++ invarg("invalid flowlabel", *argv); ++ label = htonl(uval); + } else if (!matches(*argv, "dstport")) { + NEXT_ARG(); + if (get_u16(&dstport, *argv, 0)) +@@ -150,6 +161,7 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, + addattr_l(n, 1024, IFLA_GENEVE_REMOTE, &daddr, 4); + if (memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) != 0) + addattr_l(n, 1024, IFLA_GENEVE_REMOTE6, &daddr6, sizeof(struct in6_addr)); ++ addattr32(n, 1024, IFLA_GENEVE_LABEL, label); + addattr8(n, 1024, IFLA_GENEVE_TTL, ttl); + addattr8(n, 1024, IFLA_GENEVE_TOS, tos); + if (dstport) +@@ -211,6 +223,13 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + fprintf(f, "tos %#x ", tos); + } + ++ if (tb[IFLA_GENEVE_LABEL]) { ++ __u32 label = rta_getattr_u32(tb[IFLA_GENEVE_LABEL]); ++ ++ if (label) ++ fprintf(f, "flowlabel %#x ", ntohl(label)); ++ } ++ + if (tb[IFLA_GENEVE_PORT]) + fprintf(f, "dstport %u ", + ntohs(rta_getattr_u16(tb[IFLA_GENEVE_PORT]))); +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 31a6190..3002e47 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -674,6 +674,8 @@ the following additional arguments are supported: + .BI ttl " TTL " + .R " ] [ " + .BI tos " TOS " ++.R " ] [ " ++.BI flowlabel " FLOWLABEL " + .R " ]" + + .in +8 +@@ -693,6 +695,10 @@ the following additional arguments are supported: + .BI tos " TOS" + - specifies the TOS value to use in outgoing packets. + ++.sp ++.BI flowlabel " FLOWLABEL" ++- specifies the flow label to use in outgoing packets. ++ + .in -8 + + .TP +-- +1.8.3.1 + diff --git a/SOURCES/0169-geneve-fix-IPv6-remote-address-reporting.patch b/SOURCES/0169-geneve-fix-IPv6-remote-address-reporting.patch new file mode 100644 index 0000000..27ca499 --- /dev/null +++ b/SOURCES/0169-geneve-fix-IPv6-remote-address-reporting.patch @@ -0,0 +1,39 @@ +From 4290eadae6233b5d7bc7d92821dbdc0f8fee07a5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 2 Jul 2016 12:46:47 +0200 +Subject: [PATCH] geneve: fix IPv6 remote address reporting + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1339178 +Upstream Status: iproute2.git commit 2642b6b03e546 + +commit 2642b6b03e546b04e163a7cb2585ece791324a05 +Author: Edward Cree <ecree@solarflare.com> +Date: Fri May 6 15:28:25 2016 +0100 + + geneve: fix IPv6 remote address reporting + + Since we can only configure unicast, we probably want to be able to + display unicast, rather than multicast. + + Fixes: 906ac5437ab8 ("geneve: add support for IPv6 link partners") + Signed-off-by: Edward Cree <ecree@solarflare.com> +--- + ip/iplink_geneve.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c +index fb0c6b1..905c537 100644 +--- a/ip/iplink_geneve.c ++++ b/ip/iplink_geneve.c +@@ -203,7 +203,7 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + struct in6_addr addr; + memcpy(&addr, RTA_DATA(tb[IFLA_GENEVE_REMOTE6]), sizeof(struct in6_addr)); + if (memcmp(&addr, &in6addr_any, sizeof(addr)) != 0) { +- if (IN6_IS_ADDR_MULTICAST(&addr)) ++ if (!IN6_IS_ADDR_MULTICAST(&addr)) + fprintf(f, "remote %s ", + format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1))); + } +-- +1.8.3.1 + diff --git a/SOURCES/0170-iproute2-utils-change-hexstring_n2a-and-hexstring_a2.patch b/SOURCES/0170-iproute2-utils-change-hexstring_n2a-and-hexstring_a2.patch new file mode 100644 index 0000000..6c59b20 --- /dev/null +++ b/SOURCES/0170-iproute2-utils-change-hexstring_n2a-and-hexstring_a2.patch @@ -0,0 +1,92 @@ +From 60969cb2bd1782f232d1c74871642c03b429d676 Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 6 Jul 2016 18:41:30 +0200 +Subject: [PATCH] iproute2: utils: change hexstring_n2a and hexstring_a2n to do + not work with ":" + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1300765 +Upstream Status: iproute2.git commit 316c2346f7f3 + +commit 316c2346f7f3e337be9a56e7ad5fc8e04cd26d63 +Author: Jiri Pirko <jiri@resnulli.us> +Date: Thu May 15 15:10:21 2014 +0200 + + iproute2: utils: change hexstring_n2a and hexstring_a2n to do not work with ":" + + Signed-off-by: Jiri Pirko <jiri@resnulli.us> + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + lib/utils.c | 46 +++++++++++++--------------------------------- + 1 file changed, 13 insertions(+), 33 deletions(-) + +diff --git a/lib/utils.c b/lib/utils.c +index 1cd4fdd..7f842ae 100644 +--- a/lib/utils.c ++++ b/lib/utils.c +@@ -783,10 +783,6 @@ char *hexstring_n2a(const __u8 *str, int len, char *buf, int blen) + sprintf(ptr, "%02x", str[i]); + ptr += 2; + blen -= 2; +- if (i != len-1 && blen > 1) { +- *ptr++ = ':'; +- blen--; +- } + } + return buf; + } +@@ -794,38 +790,22 @@ char *hexstring_n2a(const __u8 *str, int len, char *buf, int blen) + __u8* hexstring_a2n(const char *str, __u8 *buf, int blen) + { + int cnt = 0; ++ char *endptr; + +- for (;;) { +- unsigned acc; +- char ch; +- +- acc = 0; +- +- while ((ch = *str) != ':' && ch != 0) { +- if (ch >= '0' && ch <= '9') +- ch -= '0'; +- else if (ch >= 'a' && ch <= 'f') +- ch -= 'a'-10; +- else if (ch >= 'A' && ch <= 'F') +- ch -= 'A'-10; +- else +- return NULL; +- acc = (acc<<4) + ch; +- str++; +- } +- +- if (acc > 255) ++ if (strlen(str) % 2) ++ return NULL; ++ while (cnt < blen && strlen(str) > 1) { ++ unsigned int tmp; ++ char tmpstr[3]; ++ ++ strncpy(tmpstr, str, 2); ++ tmpstr[2] = '\0'; ++ tmp = strtoul(tmpstr, &endptr, 16); ++ if (errno != 0 || tmp > 0xFF || *endptr != '\0') + return NULL; +- if (cnt < blen) { +- buf[cnt] = acc; +- cnt++; +- } +- if (ch == 0) +- break; +- ++str; ++ buf[cnt++] = tmp; ++ str += 2; + } +- if (cnt < blen) +- memset(buf+cnt, 0, blen-cnt); + return buf; + } + +-- +1.8.3.1 + diff --git a/SOURCES/0171-iproute2-arpd-use-ll_addr_a2n-and-ll_addr_n2a.patch b/SOURCES/0171-iproute2-arpd-use-ll_addr_a2n-and-ll_addr_n2a.patch new file mode 100644 index 0000000..8b3dc43 --- /dev/null +++ b/SOURCES/0171-iproute2-arpd-use-ll_addr_a2n-and-ll_addr_n2a.patch @@ -0,0 +1,55 @@ +From a3c9bb79b1f03896d09df67a7095cd545e495ab0 Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 6 Jul 2016 18:41:31 +0200 +Subject: [PATCH] iproute2: arpd: use ll_addr_a2n and ll_addr_n2a + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1300765 +Upstream Status: iproute2.git commit dd50247dba85 + +commit dd50247dba85255538d659551305b4bb75bcae62 +Author: Jiri Pirko <jiri@resnulli.us> +Date: Thu May 15 15:10:20 2014 +0200 + + iproute2: arpd: use ll_addr_a2n and ll_addr_n2a + + Signed-off-by: Jiri Pirko <jiri@resnulli.us> + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + misc/arpd.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/misc/arpd.c b/misc/arpd.c +index cc5e1ca..7919eb8 100644 +--- a/misc/arpd.c ++++ b/misc/arpd.c +@@ -36,6 +36,7 @@ + + #include "libnetlink.h" + #include "utils.h" ++#include "rt_names.h" + + int resolve_hosts; + +@@ -721,8 +722,7 @@ int main(int argc, char **argv) + goto do_abort; + } + +- dbdat.data = hexstring_a2n(macbuf, b1, 6); +- if (dbdat.data == NULL) ++ if (ll_addr_a2n((char *) b1, 6, macbuf) != 6) + goto do_abort; + dbdat.size = 6; + +@@ -747,7 +747,7 @@ int main(int argc, char **argv) + printf("%-8d %-15s %s\n", + key->iface, + inet_ntoa(*(struct in_addr*)&key->addr), +- hexstring_n2a(dbdat.data, 6, b1, 18)); ++ ll_addr_n2a(dbdat.data, 6, ARPHRD_ETHER, b1, 18)); + } else { + printf("%-8d %-15s FAILED: %dsec ago\n", + key->iface, +-- +1.8.3.1 + diff --git a/SOURCES/0172-lib-ll_addr-improve-ll_addr_n2a-a-bit.patch b/SOURCES/0172-lib-ll_addr-improve-ll_addr_n2a-a-bit.patch new file mode 100644 index 0000000..98a8e1a --- /dev/null +++ b/SOURCES/0172-lib-ll_addr-improve-ll_addr_n2a-a-bit.patch @@ -0,0 +1,56 @@ +From 6b0e32fa35dbb002e7b6d2b6529cd3543b07bdef Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 6 Jul 2016 18:41:32 +0200 +Subject: [PATCH] lib/ll_addr: improve ll_addr_n2a() a bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1300765 +Upstream Status: iproute2.git commit f63ed3e62989 + +commit f63ed3e629893046aca58a3bb409a3ff909a8fae +Author: Phil Sutter <phil@nwl.cc> +Date: Tue Mar 22 19:35:19 2016 +0100 + + lib/ll_addr: improve ll_addr_n2a() a bit + + Apart from making the code a bit more compact and efficient, this also + prevents a potential buffer overflow if the passed buffer is really too + small: Although correctly decrementing the size parameter passed to + snprintf, it could become negative which would then wrap since snprintf + uses (unsigned) size_t for the parameter. + + Signed-off-by: Phil Sutter <phil@nwl.cc> + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + lib/ll_addr.c | 15 +++------------ + 1 file changed, 3 insertions(+), 12 deletions(-) + +diff --git a/lib/ll_addr.c b/lib/ll_addr.c +index c12ab07..d38bc31 100644 +--- a/lib/ll_addr.c ++++ b/lib/ll_addr.c +@@ -41,18 +41,9 @@ const char *ll_addr_n2a(unsigned char *addr, int alen, int type, char *buf, int + if (alen == 16 && type == ARPHRD_TUNNEL6) { + return inet_ntop(AF_INET6, addr, buf, blen); + } +- l = 0; +- for (i=0; i<alen; i++) { +- if (i==0) { +- snprintf(buf+l, blen, "%02x", addr[i]); +- blen -= 2; +- l += 2; +- } else { +- snprintf(buf+l, blen, ":%02x", addr[i]); +- blen -= 3; +- l += 3; +- } +- } ++ snprintf(buf, blen, "%02x", addr[0]); ++ for (i = 1, l = 2; i < alen && l < blen; i++, l += 3) ++ snprintf(buf + l, blen - l, ":%02x", addr[i]); + return buf; + } + +-- +1.8.3.1 + diff --git a/SOURCES/0173-utils-make-hexstring_a2n-provide-the-number-of-hex-d.patch b/SOURCES/0173-utils-make-hexstring_a2n-provide-the-number-of-hex-d.patch new file mode 100644 index 0000000..c2049bd --- /dev/null +++ b/SOURCES/0173-utils-make-hexstring_a2n-provide-the-number-of-hex-d.patch @@ -0,0 +1,72 @@ +From da4ac3dc839ed968d4701534344a597df97b0cf0 Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 6 Jul 2016 18:41:33 +0200 +Subject: [PATCH] utils: make hexstring_a2n provide the number of hex digits + parsed + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1300765 +Upstream Status: iproute2.git commit 89ae502056f5 + +Conflicts: context conflicts around decalaration of hexstring_{n2a,a2n} +due to missing code cleanup (lack of upstream commit 892e21248cfd) + +commit 89ae502056f58a0177b9970f1f79a9683ac7fdd0 +Author: Sabrina Dubroca <sd@queasysnail.net> +Date: Fri Jun 3 16:45:45 2016 +0200 + + utils: make hexstring_a2n provide the number of hex digits parsed + + Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> + Acked-by: Phil Sutter <phil@nwl.cc> + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + include/utils.h | 4 ++-- + lib/utils.c | 8 ++++++-- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/include/utils.h b/include/utils.h +index 0234277..86af63b 100644 +--- a/include/utils.h ++++ b/include/utils.h +@@ -98,8 +98,8 @@ extern int get_s16(__s16 *val, const char *arg, int base); + extern int get_u8(__u8 *val, const char *arg, int base); + extern int get_s8(__s8 *val, const char *arg, int base); + +-extern char* hexstring_n2a(const __u8 *str, int len, char *buf, int blen); +-extern __u8* hexstring_a2n(const char *str, __u8 *buf, int blen); ++char *hexstring_n2a(const __u8 *str, int len, char *buf, int blen); ++__u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len); + + extern const char *format_host(int af, int len, const void *addr, + char *buf, int buflen); +diff --git a/lib/utils.c b/lib/utils.c +index 7f842ae..5337084 100644 +--- a/lib/utils.c ++++ b/lib/utils.c +@@ -787,9 +787,9 @@ char *hexstring_n2a(const __u8 *str, int len, char *buf, int blen) + return buf; + } + +-__u8* hexstring_a2n(const char *str, __u8 *buf, int blen) ++__u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len) + { +- int cnt = 0; ++ unsigned int cnt = 0; + char *endptr; + + if (strlen(str) % 2) +@@ -806,6 +806,10 @@ __u8* hexstring_a2n(const char *str, __u8 *buf, int blen) + buf[cnt++] = tmp; + str += 2; + } ++ ++ if (len) ++ *len = cnt; ++ + return buf; + } + +-- +1.8.3.1 + diff --git a/SOURCES/0174-utils-add-get_be-16-32-64-use-them-where-possible.patch b/SOURCES/0174-utils-add-get_be-16-32-64-use-them-where-possible.patch new file mode 100644 index 0000000..15b804d --- /dev/null +++ b/SOURCES/0174-utils-add-get_be-16-32-64-use-them-where-possible.patch @@ -0,0 +1,232 @@ +From 25b35417c2ea49d31289177a81cb988369e138db Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 6 Jul 2016 18:41:34 +0200 +Subject: [PATCH] utils: add get_be{16, 32, 64}, use them where possible + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1300765 +Upstream Status: iproute2.git commit 9f7401fa4967 + +Conflicts: +- context conflicts due to missing code cleanups (lack of upstream commit +892e21248cfd and 56f5daac98da) +- hunks not merged: +get_be64() implementation in utils.{c,h} due to missing support for +lwtunnel (lack of upstream commit 1e5293056a02 implementing htonll()) +ip/ipfou.c due to missing support for foo-over-udp (lack of upstream commit +6928747b6e79) +tc/f_flower.c due to missing support for Flower classifier (lack of upstream +commit 30eb304ecd1d) +ip/iproute_lwtunnel.c due to missing support for lwtunnel (lack of upstream +commit 1e5293056a02) + +commit 9f7401fa4967178a071c53498f6bdc460c7cc4ea +Author: Sabrina Dubroca <sd@queasysnail.net> +Date: Fri Jun 3 16:45:46 2016 +0200 + + utils: add get_be{16, 32, 64}, use them where possible + + Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> + Acked-by: Phil Sutter <phil@nwl.cc> + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + include/utils.h | 2 ++ + ip/iplink_vxlan.c | 7 ++----- + ip/ipxfrm.c | 13 +++---------- + ip/xfrm_state.c | 10 +++------- + lib/ll_proto.c | 3 +-- + lib/utils.c | 22 ++++++++++++++++++++++ + tc/f_u32.c | 8 ++------ + 7 files changed, 35 insertions(+), 30 deletions(-) + +diff --git a/include/utils.h b/include/utils.h +index 86af63b..4fd48b6 100644 +--- a/include/utils.h ++++ b/include/utils.h +@@ -97,6 +97,8 @@ extern int get_u16(__u16 *val, const char *arg, int base); + extern int get_s16(__s16 *val, const char *arg, int base); + extern int get_u8(__u8 *val, const char *arg, int base); + extern int get_s8(__s8 *val, const char *arg, int base); ++int get_be32(__be32 *val, const char *arg, int base); ++int get_be16(__be16 *val, const char *arg, int base); + + char *hexstring_n2a(const __u8 *str, int len, char *buf, int blen); + __u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len); +diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c +index a4cf924..2ca97a4 100644 +--- a/ip/iplink_vxlan.c ++++ b/ip/iplink_vxlan.c +@@ -153,15 +153,12 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, + invarg("max addresses", *argv); + } else if (!matches(*argv, "port") || + !matches(*argv, "srcport")) { +- __u16 minport, maxport; + NEXT_ARG(); +- if (get_u16(&minport, *argv, 0)) ++ if (get_be16(&range.low, *argv, 0)) + invarg("min port", *argv); + NEXT_ARG(); +- if (get_u16(&maxport, *argv, 0)) ++ if (get_be16(&range.high, *argv, 0)) + invarg("max port", *argv); +- range.low = htons(minport); +- range.high = htons(maxport); + } else if (!matches(*argv, "dstport")){ + NEXT_ARG(); + if (get_u16(&dstport, *argv, 0)) +diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c +index feff09a..0344355 100644 +--- a/ip/ipxfrm.c ++++ b/ip/ipxfrm.c +@@ -1057,15 +1057,10 @@ int xfrm_id_parse(xfrm_address_t *saddr, struct xfrm_id *id, __u16 *family, + filter.id_proto_mask = XFRM_FILTER_MASK_FULL; + + } else if (strcmp(*argv, "spi") == 0) { +- __u32 spi; +- + NEXT_ARG(); +- if (get_u32(&spi, *argv, 0)) ++ if (get_be32(&id->spi, *argv, 0)) + invarg("SPI value is invalid", *argv); + +- spi = htonl(spi); +- id->spi = spi; +- + filter.id_spi_mask = XFRM_FILTER_MASK_FULL; + + } else { +@@ -1199,9 +1194,8 @@ static int xfrm_selector_upspec_parse(struct xfrm_selector *sel, + + NEXT_ARG(); + +- if (get_u16(&sel->sport, *argv, 0)) ++ if (get_be16(&sel->sport, *argv, 0)) + invarg("value after \"sport\" is invalid", *argv); +- sel->sport = htons(sel->sport); + if (sel->sport) + sel->sport_mask = ~((__u16)0); + +@@ -1212,9 +1206,8 @@ static int xfrm_selector_upspec_parse(struct xfrm_selector *sel, + + NEXT_ARG(); + +- if (get_u16(&sel->dport, *argv, 0)) ++ if (get_be16(&sel->dport, *argv, 0)) + invarg("value after \"dport\" is invalid", *argv); +- sel->dport = htons(sel->dport); + if (sel->dport) + sel->dport_mask = ~((__u16)0); + +diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c +index 20d7a7e..4dfddbc 100644 +--- a/ip/xfrm_state.c ++++ b/ip/xfrm_state.c +@@ -176,11 +176,9 @@ static int xfrm_seq_parse(__u32 *seq, int *argcp, char ***argvp) + int argc = *argcp; + char **argv = *argvp; + +- if (get_u32(seq, *argv, 0)) ++ if (get_be32(seq, *argv, 0)) + invarg("SEQ value is invalid", *argv); + +- *seq = htonl(*seq); +- + *argcp = argc; + *argvp = argv; + +@@ -346,13 +344,11 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) + NEXT_ARG(); + xfrm_encap_type_parse(&encap.encap_type, &argc, &argv); + NEXT_ARG(); +- if (get_u16(&encap.encap_sport, *argv, 0)) ++ if (get_be16(&encap.encap_sport, *argv, 0)) + invarg("SPORT value after \"encap\" is invalid", *argv); +- encap.encap_sport = htons(encap.encap_sport); + NEXT_ARG(); +- if (get_u16(&encap.encap_dport, *argv, 0)) ++ if (get_be16(&encap.encap_dport, *argv, 0)) + invarg("DPORT value after \"encap\" is invalid", *argv); +- encap.encap_dport = htons(encap.encap_dport); + NEXT_ARG(); + get_addr(&oa, *argv, AF_UNSPEC); + memcpy(&encap.encap_oa, &oa.data, sizeof(encap.encap_oa)); +diff --git a/lib/ll_proto.c b/lib/ll_proto.c +index d8df68c..e094d9f 100644 +--- a/lib/ll_proto.c ++++ b/lib/ll_proto.c +@@ -111,8 +111,7 @@ int ll_proto_a2n(unsigned short *id, const char *buf) + return 0; + } + } +- if (get_u16(id, buf, 0)) ++ if (get_be16(id, buf, 0)) + return -1; +- *id = htons(*id); + return 0; + } +diff --git a/lib/utils.c b/lib/utils.c +index 5337084..687c188 100644 +--- a/lib/utils.c ++++ b/lib/utils.c +@@ -351,6 +351,28 @@ int get_s8(__s8 *val, const char *arg, int base) + return 0; + } + ++int get_be32(__be32 *val, const char *arg, int base) ++{ ++ __u32 v; ++ int ret = get_u32(&v, arg, base); ++ ++ if (!ret) ++ *val = htonl(v); ++ ++ return ret; ++} ++ ++int get_be16(__be16 *val, const char *arg, int base) ++{ ++ __u16 v; ++ int ret = get_u16(&v, arg, base); ++ ++ if (!ret) ++ *val = htons(v); ++ ++ return ret; ++} ++ + /* This uses a non-standard parsing (ie not inet_aton, or inet_pton) + * because of legacy choice to parse 10.8 as 10.8.0.0 not 10.0.0.8 + */ +diff --git a/tc/f_u32.c b/tc/f_u32.c +index 8bc9a17..134925e 100644 +--- a/tc/f_u32.c ++++ b/tc/f_u32.c +@@ -765,11 +765,9 @@ static int parse_offset(int *argc_p, char ***argv_p, struct tc_u32_sel *sel) + } + sel->flags |= TC_U32_VAROFFSET; + } else if (matches(*argv, "mask") == 0) { +- __u16 mask; + NEXT_ARG(); +- if (get_u16(&mask, *argv, 16)) ++ if (get_be16(&sel->offmask, *argv, 16)) + return -1; +- sel->offmask = htons(mask); + sel->flags |= TC_U32_VAROFFSET; + } else if (matches(*argv, "shift") == 0) { + int shift; +@@ -798,11 +796,9 @@ static int parse_hashkey(int *argc_p, char ***argv_p, struct tc_u32_sel *sel) + + while (argc > 0) { + if (matches(*argv, "mask") == 0) { +- __u32 mask; + NEXT_ARG(); +- if (get_u32(&mask, *argv, 16)) ++ if (get_be32(&sel->hmask, *argv, 16)) + return -1; +- sel->hmask = htonl(mask); + } else if (matches(*argv, "at") == 0) { + int num; + NEXT_ARG(); +-- +1.8.3.1 + diff --git a/SOURCES/0175-utils-provide-get_hex-to-read-a-hex-digit-from-a-cha.patch b/SOURCES/0175-utils-provide-get_hex-to-read-a-hex-digit-from-a-cha.patch new file mode 100644 index 0000000..71d702c --- /dev/null +++ b/SOURCES/0175-utils-provide-get_hex-to-read-a-hex-digit-from-a-cha.patch @@ -0,0 +1,149 @@ +From 1880eb1a9cd934736ed4b41b247664760bc7b69c Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 6 Jul 2016 18:41:35 +0200 +Subject: [PATCH] utils: provide get_hex to read a hex digit from a char + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1300765 +Upstream Status: iproute2.git commit 609640f5f0fe + +Conflicts: context conflict due to missing code cleanup (lack of upstream +commit 892e21248cfd) + +commit 609640f5f0feda8099b04452297d81dd1a8a1777 +Author: Sabrina Dubroca <sd@queasysnail.net> +Date: Fri Jun 3 16:45:47 2016 +0200 + + utils: provide get_hex to read a hex digit from a char + + Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> + Acked-by: Phil Sutter <phil@nwl.cc> + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + include/utils.h | 1 + + ip/ipl2tp.c | 15 ++------------- + lib/ipx_pton.c | 18 +++--------------- + lib/utils.c | 12 ++++++++++++ + 4 files changed, 18 insertions(+), 28 deletions(-) + +diff --git a/include/utils.h b/include/utils.h +index 4fd48b6..fad82dc 100644 +--- a/include/utils.h ++++ b/include/utils.h +@@ -84,6 +84,7 @@ extern int get_addr(inet_prefix *dst, const char *arg, int family); + extern int get_prefix(inet_prefix *dst, char *arg, int family); + extern int mask2bits(__u32 netmask); + ++int get_hex(char c); + extern int get_integer(int *val, const char *arg, int base); + extern int get_unsigned(unsigned *val, const char *arg, int base); + extern int get_time_rtt(unsigned *val, const char *arg, int *raw); +diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c +index 92e15c5..d2c8979 100644 +--- a/ip/ipl2tp.c ++++ b/ip/ipl2tp.c +@@ -424,30 +424,19 @@ static int get_tunnel(struct l2tp_data *p) + * Command parser + *****************************************************************************/ + +-static int hex(char ch) +-{ +- if ((ch >= 'a') && (ch <= 'f')) +- return ch - 'a' + 10; +- if ((ch >= '0') && (ch <= '9')) +- return ch - '0'; +- if ((ch >= 'A') && (ch <= 'F')) +- return ch - 'A' + 10; +- return -1; +-} +- + static int hex2mem(const char *buf, uint8_t *mem, int count) + { + int i, j; + int c; + + for (i = 0, j = 0; i < count; i++, j += 2) { +- c = hex(buf[j]); ++ c = get_hex(buf[j]); + if (c < 0) + goto err; + + mem[i] = c << 4; + +- c = hex(buf[j + 1]); ++ c = get_hex(buf[j + 1]); + if (c < 0) + goto err; + +diff --git a/lib/ipx_pton.c b/lib/ipx_pton.c +index 3dca271..071a775 100644 +--- a/lib/ipx_pton.c ++++ b/lib/ipx_pton.c +@@ -6,18 +6,6 @@ + + #include "utils.h" + +-static u_int32_t hexget(char c) +-{ +- if (c >= 'A' && c <= 'F') +- return c - 'A' + 10; +- if (c >= 'a' && c <= 'f') +- return c - 'a' + 10; +- if (c >= '0' && c <= '9') +- return c - '0'; +- +- return 0xf0; +-} +- + static int ipx_getnet(u_int32_t *net, const char *str) + { + int i; +@@ -25,7 +13,7 @@ static int ipx_getnet(u_int32_t *net, const char *str) + + for(i = 0; *str && (i < 8); i++) { + +- if ((tmp = hexget(*str)) & 0xf0) { ++ if ((tmp = get_hex(*str)) == -1) { + if (*str == '.') + return 0; + else +@@ -49,11 +37,11 @@ static int ipx_getnode(u_int8_t *node, const char *str) + u_int32_t tmp; + + for(i = 0; i < 6; i++) { +- if ((tmp = hexget(*str++)) & 0xf0) ++ if ((tmp = get_hex(*str++)) == -1) + return -1; + node[i] = (u_int8_t)tmp; + node[i] <<= 4; +- if ((tmp = hexget(*str++)) & 0xf0) ++ if ((tmp = get_hex(*str++)) == -1) + return -1; + node[i] |= (u_int8_t)tmp; + if (*str == ':') +diff --git a/lib/utils.c b/lib/utils.c +index 687c188..dedadff 100644 +--- a/lib/utils.c ++++ b/lib/utils.c +@@ -35,6 +35,18 @@ + + int timestamp_short = 0; + ++int get_hex(char c) ++{ ++ if (c >= 'A' && c <= 'F') ++ return c - 'A' + 10; ++ if (c >= 'a' && c <= 'f') ++ return c - 'a' + 10; ++ if (c >= '0' && c <= '9') ++ return c - '0'; ++ ++ return -1; ++} ++ + int get_integer(int *val, const char *arg, int base) + { + long res; +-- +1.8.3.1 + diff --git a/SOURCES/0176-ip-add-MACsec-support.patch b/SOURCES/0176-ip-add-MACsec-support.patch new file mode 100644 index 0000000..c50248f --- /dev/null +++ b/SOURCES/0176-ip-add-MACsec-support.patch @@ -0,0 +1,1619 @@ +From 2eacdef42c7194133be00b2de64cabd72b88aef1 Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 6 Jul 2016 18:41:36 +0200 +Subject: [PATCH] ip: add MACsec support + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1300765 +Upstream Status: iproute2.git commit b26fc590ce62 + +Conflicts: +- context conflict due to missing code cleanup (lack of upstream commit +892e21248cfd) +- context conflict due to missing support for foo-over-udp (lack of upstream +commit 6928747b6e79) + +commit b26fc590ce6272835da35c016f6a99f5f43d6a88 +Author: Sabrina Dubroca <sd@queasysnail.net> +Date: Wed Jun 8 09:34:21 2016 -0700 + + ip: add MACsec support + + Extend ip-link to create MACsec devices + + ip link add link <master> <macsec> type macsec [options] + + Add `ip macsec` command to configure receive-side secure channels and + secure associations within a macsec netdevice. + + Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> + Acked-by: Phil Sutter <phil@nwl.cc> + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + ip/Makefile | 2 +- + ip/ip.c | 3 +- + ip/ip_common.h | 1 + + ip/ipmacsec.c | 1301 +++++++++++++++++++++++++++++++++++++++++++++++++ + man/man8/Makefile | 2 +- + man/man8/ip-link.8.in | 85 ++++ + man/man8/ip-macsec.8 | 98 ++++ + 7 files changed, 1489 insertions(+), 3 deletions(-) + create mode 100644 ip/ipmacsec.c + create mode 100644 man/man8/ip-macsec.8 + +diff --git a/ip/Makefile b/ip/Makefile +index 5aad224..f6de690 100644 +--- a/ip/Makefile ++++ b/ip/Makefile +@@ -6,7 +6,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ + iplink_macvlan.o ipl2tp.o link_vti.o link_vti6.o \ + iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \ + link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o \ +- iplink_bridge.o iplink_bridge_slave.o \ ++ iplink_bridge.o iplink_bridge_slave.o ipmacsec.o \ + iplink_geneve.o + + RTMONOBJ=rtmon.o +diff --git a/ip/ip.c b/ip/ip.c +index 8b9b9c0..d6f1391 100644 +--- a/ip/ip.c ++++ b/ip/ip.c +@@ -49,7 +49,7 @@ static void usage(void) + " ip [ -force ] -batch filename\n" + "where OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |\n" + " tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |\n" +-" netns | l2tp | tcp_metrics | token }\n" ++" netns | l2tp | macsec | tcp_metrics | token }\n" + " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" + " -h[uman-readable] | -iec |\n" + " -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n" +@@ -81,6 +81,7 @@ static const struct cmd { + { "ntbl", do_ipntable }, + { "link", do_iplink }, + { "l2tp", do_ipl2tp }, ++ { "macsec", do_ipmacsec }, + { "tunnel", do_iptunnel }, + { "tunl", do_iptunnel }, + { "tuntap", do_iptuntap }, +diff --git a/ip/ip_common.h b/ip/ip_common.h +index 880890e..c3e7fda 100644 +--- a/ip/ip_common.h ++++ b/ip/ip_common.h +@@ -44,6 +44,7 @@ extern int do_iptunnel(int argc, char **argv); + extern int do_ip6tunnel(int argc, char **argv); + extern int do_iptuntap(int argc, char **argv); + extern int do_iplink(int argc, char **argv); ++int do_ipmacsec(int argc, char **argv); + extern int do_ipmonitor(int argc, char **argv); + extern int do_multiaddr(int argc, char **argv); + extern int do_multiroute(int argc, char **argv); +diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c +new file mode 100644 +index 0000000..34ba341 +--- /dev/null ++++ b/ip/ipmacsec.c +@@ -0,0 +1,1301 @@ ++/* ++ * ipmacsec.c "ip macsec". ++ * ++ * 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. ++ * ++ * Authors: Sabrina Dubroca <sd@queasysnail.net> ++ */ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <errno.h> ++#include <linux/genetlink.h> ++#include <linux/if_ether.h> ++#include <linux/if_macsec.h> ++ ++#include "rt_names.h" ++#include "utils.h" ++#include "ip_common.h" ++#include "ll_map.h" ++#include "libgenl.h" ++ ++static const char *values_on_off[] = { "off", "on" }; ++ ++static const char *VALIDATE_STR[] = { ++ [MACSEC_VALIDATE_DISABLED] = "disabled", ++ [MACSEC_VALIDATE_CHECK] = "check", ++ [MACSEC_VALIDATE_STRICT] = "strict", ++}; ++ ++struct sci { ++ __u64 sci; ++ __u16 port; ++ char abuf[6]; ++}; ++ ++struct sa_desc { ++ __u8 an; ++ __u32 pn; ++ __u8 key_id[MACSEC_KEYID_LEN]; ++ __u32 key_len; ++ __u8 key[MACSEC_MAX_KEY_LEN]; ++ __u8 active; ++}; ++ ++struct cipher_args { ++ __u64 id; ++ __u8 icv_len; ++}; ++ ++struct txsc_desc { ++ int ifindex; ++ __u64 sci; ++ __be16 port; ++ struct cipher_args cipher; ++ __u32 window; ++ enum macsec_validation_type validate; ++ __u8 encoding_sa; ++}; ++ ++struct rxsc_desc { ++ int ifindex; ++ __u64 sci; ++ __u8 active; ++}; ++ ++#define MACSEC_BUFLEN 1024 ++ ++ ++/* netlink socket */ ++static struct rtnl_handle genl_rth; ++static int genl_family = -1; ++ ++#define MACSEC_GENL_REQ(_req, _bufsiz, _cmd, _flags) \ ++ GENL_REQUEST(_req, _bufsiz, genl_family, 0, MACSEC_GENL_VERSION, \ ++ _cmd, _flags) ++ ++ ++static void init_genl(void) ++{ ++ if (genl_family >= 0) ++ return; ++ ++ if (rtnl_open_byproto(&genl_rth, 0, NETLINK_GENERIC) < 0) { ++ fprintf(stderr, "Cannot open generic netlink socket\n"); ++ exit(1); ++ } ++ ++ genl_family = genl_resolve_family(&genl_rth, MACSEC_GENL_NAME); ++ if (genl_family < 0) ++ exit(1); ++} ++ ++static void ipmacsec_usage(void) ++{ ++ fprintf(stderr, "Usage: ip macsec add DEV tx sa { 0..3 } [ OPTS ] key ID KEY\n"); ++ fprintf(stderr, " ip macsec set DEV tx sa { 0..3 } [ OPTS ]\n"); ++ fprintf(stderr, " ip macsec del DEV tx sa { 0..3 }\n"); ++ fprintf(stderr, " ip macsec add DEV rx SCI [ on | off ]\n"); ++ fprintf(stderr, " ip macsec set DEV rx SCI [ on | off ]\n"); ++ fprintf(stderr, " ip macsec del DEV rx SCI\n"); ++ fprintf(stderr, " ip macsec add DEV rx SCI sa { 0..3 } [ OPTS ] key ID KEY\n"); ++ fprintf(stderr, " ip macsec set DEV rx SCI sa { 0..3 } [ OPTS ]\n"); ++ fprintf(stderr, " ip macsec del DEV rx SCI sa { 0..3 }\n"); ++ fprintf(stderr, " ip macsec show\n"); ++ fprintf(stderr, " ip macsec show DEV\n"); ++ fprintf(stderr, "where OPTS := [ pn <u32> ] [ on | off ]\n"); ++ fprintf(stderr, " ID := 128-bit hex string\n"); ++ fprintf(stderr, " KEY := 128-bit hex string\n"); ++ fprintf(stderr, " SCI := { sci <u64> | port <u16> address <lladdr> }\n"); ++ ++ exit(-1); ++} ++ ++static int one_of(const char *msg, const char *realval, const char **list, ++ size_t len, int *index) ++{ ++ int i; ++ ++ for (i = 0; i < len; i++) { ++ if (matches(realval, list[i]) == 0) { ++ *index = i; ++ return 0; ++ } ++ } ++ ++ fprintf(stderr, "Error: argument of \"%s\" must be one of ", msg); ++ for (i = 0; i < len; i++) ++ fprintf(stderr, "\"%s\", ", list[i]); ++ fprintf(stderr, "not \"%s\"\n", realval); ++ return -1; ++} ++ ++static int get_an(__u8 *val, const char *arg) ++{ ++ int ret = get_u8(val, arg, 0); ++ ++ if (ret) ++ return ret; ++ ++ if (*val > 3) ++ return -1; ++ ++ return 0; ++} ++ ++static int get_sci(__u64 *sci, const char *arg) ++{ ++ return get_u64(sci, arg, 16); ++} ++ ++static int get_port(__be16 *port, const char *arg) ++{ ++ return get_be16(port, arg, 10); ++} ++ ++#define _STR(a) #a ++#define STR(a) _STR(a) ++ ++static void get_icvlen(__u8 *icvlen, char *arg) ++{ ++ int ret = get_u8(icvlen, arg, 10); ++ ++ if (ret) ++ invarg("expected ICV length", arg); ++ ++ if (*icvlen < MACSEC_MIN_ICV_LEN || *icvlen > MACSEC_MAX_ICV_LEN) ++ invarg("ICV length must be in the range {" ++ STR(MACSEC_MIN_ICV_LEN) ".." STR(MACSEC_MAX_ICV_LEN) ++ "}", arg); ++} ++ ++static bool get_sa(int *argcp, char ***argvp, __u8 *an) ++{ ++ int argc = *argcp; ++ char **argv = *argvp; ++ int ret; ++ ++ if (argc <= 0 || strcmp(*argv, "sa") != 0) ++ return false; ++ ++ NEXT_ARG(); ++ ret = get_an(an, *argv); ++ if (ret) ++ invarg("expected an { 0..3 }", *argv); ++ argc--; argv++; ++ ++ *argvp = argv; ++ *argcp = argc; ++ return true; ++} ++ ++static int parse_sa_args(int *argcp, char ***argvp, struct sa_desc *sa) ++{ ++ int argc = *argcp; ++ char **argv = *argvp; ++ int ret; ++ bool active_set = false; ++ ++ while (argc > 0) { ++ if (strcmp(*argv, "pn") == 0) { ++ if (sa->pn != 0) ++ duparg2("pn", "pn"); ++ NEXT_ARG(); ++ ret = get_u32(&sa->pn, *argv, 0); ++ if (ret) ++ invarg("expected pn", *argv); ++ if (sa->pn == 0) ++ invarg("expected pn != 0", *argv); ++ } else if (strcmp(*argv, "key") == 0) { ++ unsigned int len; ++ ++ NEXT_ARG(); ++ if (!hexstring_a2n(*argv, sa->key_id, MACSEC_KEYID_LEN, ++ &len)) ++ invarg("expected key id", *argv); ++ NEXT_ARG(); ++ if (!hexstring_a2n(*argv, sa->key, MACSEC_MAX_KEY_LEN, ++ &sa->key_len)) ++ invarg("expected key", *argv); ++ } else if (strcmp(*argv, "on") == 0) { ++ if (active_set) ++ duparg2("on/off", "on"); ++ sa->active = true; ++ active_set = true; ++ } else if (strcmp(*argv, "off") == 0) { ++ if (active_set) ++ duparg2("on/off", "off"); ++ sa->active = false; ++ active_set = true; ++ } else { ++ fprintf(stderr, "macsec: unknown command \"%s\"?\n", ++ *argv); ++ ipmacsec_usage(); ++ } ++ ++ argv++; argc--; ++ } ++ ++ *argvp = argv; ++ *argcp = argc; ++ return 0; ++} ++ ++static __u64 make_sci(char *addr, __be16 port) ++{ ++ __u64 sci; ++ ++ memcpy(&sci, addr, ETH_ALEN); ++ memcpy(((char *)&sci) + ETH_ALEN, &port, sizeof(port)); ++ ++ return sci; ++} ++ ++static bool sci_complete(bool sci, bool port, bool addr, bool port_only) ++{ ++ return sci || (port && (addr || port_only)); ++} ++ ++static int get_sci_portaddr(struct sci *sci, int *argcp, char ***argvp, ++ bool port_only, bool optional) ++{ ++ int argc = *argcp; ++ char **argv = *argvp; ++ int ret; ++ bool p = false, a = false, s = false; ++ ++ while (argc > 0) { ++ if (strcmp(*argv, "sci") == 0) { ++ if (p) ++ invarg("expected address", *argv); ++ if (a) ++ invarg("expected port", *argv); ++ NEXT_ARG(); ++ ret = get_sci(&sci->sci, *argv); ++ if (ret) ++ invarg("expected sci", *argv); ++ s = true; ++ } else if (strcmp(*argv, "port") == 0) { ++ NEXT_ARG(); ++ ret = get_port(&sci->port, *argv); ++ if (ret) ++ invarg("expected port", *argv); ++ if (sci->port == 0) ++ invarg("expected port != 0", *argv); ++ p = true; ++ } else if (strcmp(*argv, "address") == 0) { ++ NEXT_ARG(); ++ ret = ll_addr_a2n(sci->abuf, sizeof(sci->abuf), *argv); ++ if (ret < 0) ++ invarg("expected lladdr", *argv); ++ a = true; ++ } else if (optional) { ++ break; ++ } else { ++ invarg("expected sci, port, or address", *argv); ++ } ++ ++ argv++; argc--; ++ ++ if (sci_complete(s, p, a, port_only)) ++ break; ++ } ++ ++ if (!optional && !sci_complete(s, p, a, port_only)) ++ return -1; ++ ++ if (p && a) ++ sci->sci = make_sci(sci->abuf, sci->port); ++ ++ *argvp = argv; ++ *argcp = argc; ++ ++ return p || a || s; ++} ++ ++static bool parse_rxsci(int *argcp, char ***argvp, struct rxsc_desc *rxsc, ++ struct sa_desc *rxsa) ++{ ++ struct sci sci = { 0 }; ++ ++ if (*argcp == 0 || ++ get_sci_portaddr(&sci, argcp, argvp, false, false) < 0) { ++ fprintf(stderr, "expected sci\n"); ++ ipmacsec_usage(); ++ } ++ ++ rxsc->sci = sci.sci; ++ ++ return get_sa(argcp, argvp, &rxsa->an); ++} ++ ++static int parse_rxsci_args(int *argcp, char ***argvp, struct rxsc_desc *rxsc) ++{ ++ int argc = *argcp; ++ char **argv = *argvp; ++ bool active_set = false; ++ ++ while (argc > 0) { ++ if (strcmp(*argv, "on") == 0) { ++ if (active_set) ++ duparg2("on/off", "on"); ++ rxsc->active = true; ++ active_set = true; ++ } else if (strcmp(*argv, "off") == 0) { ++ if (active_set) ++ duparg2("on/off", "off"); ++ rxsc->active = false; ++ active_set = true; ++ } else { ++ fprintf(stderr, "macsec: unknown command \"%s\"?\n", ++ *argv); ++ ipmacsec_usage(); ++ } ++ ++ argv++; argc--; ++ } ++ ++ *argvp = argv; ++ *argcp = argc; ++ return 0; ++} ++ ++enum cmd { ++ CMD_ADD, ++ CMD_DEL, ++ CMD_UPD, ++ __CMD_MAX ++}; ++ ++static const enum macsec_nl_commands macsec_commands[__CMD_MAX][2][2] = { ++ [CMD_ADD] = { ++ [0] = {-1, MACSEC_CMD_ADD_RXSC}, ++ [1] = {MACSEC_CMD_ADD_TXSA, MACSEC_CMD_ADD_RXSA}, ++ }, ++ [CMD_UPD] = { ++ [0] = {-1, MACSEC_CMD_UPD_RXSC}, ++ [1] = {MACSEC_CMD_UPD_TXSA, MACSEC_CMD_UPD_RXSA}, ++ }, ++ [CMD_DEL] = { ++ [0] = {-1, MACSEC_CMD_DEL_RXSC}, ++ [1] = {MACSEC_CMD_DEL_TXSA, MACSEC_CMD_DEL_RXSA}, ++ }, ++}; ++ ++static int do_modify_nl(enum cmd c, enum macsec_nl_commands cmd, int ifindex, ++ struct rxsc_desc *rxsc, struct sa_desc *sa) ++{ ++ struct rtattr *attr_sa; ++ ++ MACSEC_GENL_REQ(req, MACSEC_BUFLEN, cmd, NLM_F_REQUEST); ++ ++ addattr32(&req.n, MACSEC_BUFLEN, MACSEC_ATTR_IFINDEX, ifindex); ++ if (rxsc) { ++ struct rtattr *attr_rxsc; ++ ++ attr_rxsc = addattr_nest(&req.n, MACSEC_BUFLEN, ++ MACSEC_ATTR_RXSC_CONFIG); ++ addattr64(&req.n, MACSEC_BUFLEN, ++ MACSEC_RXSC_ATTR_SCI, rxsc->sci); ++ if (c != CMD_DEL && rxsc->active != 0xff) ++ addattr8(&req.n, MACSEC_BUFLEN, ++ MACSEC_RXSC_ATTR_ACTIVE, rxsc->active); ++ ++ addattr_nest_end(&req.n, attr_rxsc); ++ } ++ ++ if (sa->an == 0xff) ++ goto talk; ++ ++ attr_sa = addattr_nest(&req.n, MACSEC_BUFLEN, MACSEC_ATTR_SA_CONFIG); ++ ++ addattr8(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_AN, sa->an); ++ ++ if (c != CMD_DEL) { ++ if (sa->pn) ++ addattr32(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_PN, ++ sa->pn); ++ ++ if (sa->key_len) { ++ addattr_l(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_KEYID, ++ sa->key_id, MACSEC_KEYID_LEN); ++ addattr_l(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_KEY, ++ sa->key, sa->key_len); ++ } ++ ++ if (sa->active != 0xff) { ++ addattr8(&req.n, MACSEC_BUFLEN, ++ MACSEC_SA_ATTR_ACTIVE, sa->active); ++ } ++ } ++ ++ addattr_nest_end(&req.n, attr_sa); ++ ++talk: ++ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) ++ return -2; ++ ++ return 0; ++} ++ ++static bool check_sa_args(enum cmd c, struct sa_desc *sa) ++{ ++ if (c == CMD_ADD) { ++ if (!sa->key_len) { ++ fprintf(stderr, "cannot create SA without key\n"); ++ return -1; ++ } ++ ++ if (sa->pn == 0) { ++ fprintf(stderr, "must specify a packet number != 0\n"); ++ return -1; ++ } ++ } else if (c == CMD_UPD) { ++ if (sa->key_len) { ++ fprintf(stderr, "cannot change key on SA\n"); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int do_modify_txsa(enum cmd c, int argc, char **argv, int ifindex) ++{ ++ struct sa_desc txsa = {0}; ++ enum macsec_nl_commands cmd; ++ ++ txsa.an = 0xff; ++ txsa.active = 0xff; ++ ++ if (argc == 0 || !get_sa(&argc, &argv, &txsa.an)) ++ ipmacsec_usage(); ++ ++ if (c == CMD_DEL) ++ goto modify; ++ ++ if (parse_sa_args(&argc, &argv, &txsa)) ++ return -1; ++ ++ if (check_sa_args(c, &txsa)) ++ return -1; ++ ++modify: ++ cmd = macsec_commands[c][1][0]; ++ return do_modify_nl(c, cmd, ifindex, NULL, &txsa); ++} ++ ++static int do_modify_rxsci(enum cmd c, int argc, char **argv, int ifindex) ++{ ++ struct rxsc_desc rxsc = {0}; ++ struct sa_desc rxsa = {0}; ++ bool sa_set; ++ enum macsec_nl_commands cmd; ++ ++ rxsc.ifindex = ifindex; ++ rxsc.active = 0xff; ++ rxsa.an = 0xff; ++ rxsa.active = 0xff; ++ ++ sa_set = parse_rxsci(&argc, &argv, &rxsc, &rxsa); ++ ++ if (c == CMD_DEL) ++ goto modify; ++ ++ if (sa_set && (parse_sa_args(&argc, &argv, &rxsa) || ++ check_sa_args(c, &rxsa))) ++ return -1; ++ if (!sa_set && parse_rxsci_args(&argc, &argv, &rxsc)) ++ return -1; ++ ++modify: ++ cmd = macsec_commands[c][sa_set][1]; ++ return do_modify_nl(c, cmd, rxsc.ifindex, &rxsc, &rxsa); ++} ++ ++static int do_modify(enum cmd c, int argc, char **argv) ++{ ++ int ifindex; ++ ++ if (argc == 0) ++ ipmacsec_usage(); ++ ++ ifindex = ll_name_to_index(*argv); ++ if (!ifindex) { ++ fprintf(stderr, "Device \"%s\" does not exist.\n", *argv); ++ return -1; ++ } ++ argc--; argv++; ++ ++ if (argc == 0) ++ ipmacsec_usage(); ++ ++ if (strcmp(*argv, "tx") == 0) ++ return do_modify_txsa(c, argc-1, argv+1, ifindex); ++ if (strcmp(*argv, "rx") == 0) ++ return do_modify_rxsci(c, argc-1, argv+1, ifindex); ++ ++ ipmacsec_usage(); ++ return -1; ++} ++ ++/* dump/show */ ++static struct { ++ int ifindex; ++ __u64 sci; ++} filter; ++ ++static int validate_dump(struct rtattr **attrs) ++{ ++ return attrs[MACSEC_ATTR_IFINDEX] && attrs[MACSEC_ATTR_SECY] && ++ attrs[MACSEC_ATTR_TXSA_LIST] && attrs[MACSEC_ATTR_RXSC_LIST] && ++ attrs[MACSEC_ATTR_TXSC_STATS] && attrs[MACSEC_ATTR_SECY_STATS]; ++ ++} ++ ++static int validate_secy_dump(struct rtattr **attrs) ++{ ++ return attrs[MACSEC_SECY_ATTR_SCI] && ++ attrs[MACSEC_SECY_ATTR_ENCODING_SA] && ++ attrs[MACSEC_SECY_ATTR_CIPHER_SUITE] && ++ attrs[MACSEC_SECY_ATTR_ICV_LEN] && ++ attrs[MACSEC_SECY_ATTR_PROTECT] && ++ attrs[MACSEC_SECY_ATTR_REPLAY] && ++ attrs[MACSEC_SECY_ATTR_OPER] && ++ attrs[MACSEC_SECY_ATTR_VALIDATE] && ++ attrs[MACSEC_SECY_ATTR_ENCRYPT] && ++ attrs[MACSEC_SECY_ATTR_INC_SCI] && ++ attrs[MACSEC_SECY_ATTR_ES] && ++ attrs[MACSEC_SECY_ATTR_SCB]; ++} ++ ++static void print_flag(FILE *f, struct rtattr *attrs[], const char *desc, ++ int field) ++{ ++ if (attrs[field]) ++ fprintf(f, "%s %s ", desc, ++ values_on_off[!!rta_getattr_u8(attrs[field])]); ++} ++ ++#define DEFAULT_CIPHER_NAME "GCM-AES-128" ++ ++static const char *cs_id_to_name(__u64 cid) ++{ ++ switch (cid) { ++ case MACSEC_DEFAULT_CIPHER_ID: ++ case MACSEC_DEFAULT_CIPHER_ALT: ++ return DEFAULT_CIPHER_NAME; ++ default: ++ return "(unknown)"; ++ } ++} ++ ++static void print_cipher_suite(const char *prefix, __u64 cid, __u8 icv_len) ++{ ++ printf("%scipher suite: %s, using ICV length %d\n", prefix, ++ cs_id_to_name(cid), icv_len); ++} ++ ++static void print_attrs(const char *prefix, struct rtattr *attrs[]) ++{ ++ print_flag(stdout, attrs, "protect", MACSEC_SECY_ATTR_PROTECT); ++ ++ if (attrs[MACSEC_SECY_ATTR_VALIDATE]) { ++ __u8 val = rta_getattr_u8(attrs[MACSEC_SECY_ATTR_VALIDATE]); ++ ++ printf("validate %s ", VALIDATE_STR[val]); ++ } ++ ++ print_flag(stdout, attrs, "sc", MACSEC_RXSC_ATTR_ACTIVE); ++ print_flag(stdout, attrs, "sa", MACSEC_SA_ATTR_ACTIVE); ++ print_flag(stdout, attrs, "encrypt", MACSEC_SECY_ATTR_ENCRYPT); ++ print_flag(stdout, attrs, "send_sci", MACSEC_SECY_ATTR_INC_SCI); ++ print_flag(stdout, attrs, "end_station", MACSEC_SECY_ATTR_ES); ++ print_flag(stdout, attrs, "scb", MACSEC_SECY_ATTR_SCB); ++ ++ print_flag(stdout, attrs, "replay", MACSEC_SECY_ATTR_REPLAY); ++ if (attrs[MACSEC_SECY_ATTR_WINDOW]) { ++ printf("window %d ", ++ rta_getattr_u32(attrs[MACSEC_SECY_ATTR_WINDOW])); ++ } ++ ++ if (attrs[MACSEC_SECY_ATTR_CIPHER_SUITE] && ++ attrs[MACSEC_SECY_ATTR_ICV_LEN]) { ++ printf("\n"); ++ print_cipher_suite(prefix, ++ rta_getattr_u64(attrs[MACSEC_SECY_ATTR_CIPHER_SUITE]), ++ rta_getattr_u8(attrs[MACSEC_SECY_ATTR_ICV_LEN])); ++ } ++ ++} ++ ++static void print_one_stat(const char **names, struct rtattr **attr, int idx, ++ bool long_stat) ++{ ++ int pad = strlen(names[idx]) + 1; ++ ++ if (attr[idx]) { ++ if (long_stat) ++ printf("%*llu", pad, rta_getattr_u64(attr[idx])); ++ else ++ printf("%*u", pad, rta_getattr_u32(attr[idx])); ++ } else { ++ printf("%*c", pad, '-'); ++ } ++} ++ ++static const char *txsc_stats_names[NUM_MACSEC_TXSC_STATS_ATTR] = { ++ [MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED] = "OutOctetsProtected", ++ [MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED] = "OutOctetsEncrypted", ++ [MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_PROTECTED] = "OutPktsProtected", ++ [MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_ENCRYPTED] = "OutPktsEncrypted", ++}; ++ ++static void print_txsc_stats(const char *prefix, struct rtattr *attr) ++{ ++ struct rtattr *stats[MACSEC_TXSC_STATS_ATTR_MAX + 1]; ++ int i; ++ ++ if (!attr || show_stats == 0) ++ return; ++ ++ parse_rtattr_nested(stats, MACSEC_TXSC_STATS_ATTR_MAX + 1, attr); ++ printf("%sstats:", prefix); ++ ++ for (i = 1; i < NUM_MACSEC_TXSC_STATS_ATTR; i++) { ++ if (!txsc_stats_names[i]) ++ continue; ++ printf(" %s", txsc_stats_names[i]); ++ } ++ ++ printf("\n%s ", prefix); ++ ++ for (i = 1; i < NUM_MACSEC_TXSC_STATS_ATTR; i++) { ++ if (!txsc_stats_names[i]) ++ continue; ++ print_one_stat(txsc_stats_names, stats, i, true); ++ } ++ ++ printf("\n"); ++} ++ ++static const char *secy_stats_names[NUM_MACSEC_SECY_STATS_ATTR] = { ++ [MACSEC_SECY_STATS_ATTR_OUT_PKTS_UNTAGGED] = "OutPktsUntagged", ++ [MACSEC_SECY_STATS_ATTR_IN_PKTS_UNTAGGED] = "InPktsUntagged", ++ [MACSEC_SECY_STATS_ATTR_OUT_PKTS_TOO_LONG] = "OutPktsTooLong", ++ [MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_TAG] = "InPktsNoTag", ++ [MACSEC_SECY_STATS_ATTR_IN_PKTS_BAD_TAG] = "InPktsBadTag", ++ [MACSEC_SECY_STATS_ATTR_IN_PKTS_UNKNOWN_SCI] = "InPktsUnknownSCI", ++ [MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_SCI] = "InPktsNoSCI", ++ [MACSEC_SECY_STATS_ATTR_IN_PKTS_OVERRUN] = "InPktsOverrun", ++}; ++ ++static void print_secy_stats(const char *prefix, struct rtattr *attr) ++{ ++ struct rtattr *stats[MACSEC_SECY_STATS_ATTR_MAX + 1]; ++ int i; ++ ++ if (!attr || show_stats == 0) ++ return; ++ ++ parse_rtattr_nested(stats, MACSEC_SECY_STATS_ATTR_MAX + 1, attr); ++ printf("%sstats:", prefix); ++ ++ for (i = 1; i < NUM_MACSEC_SECY_STATS_ATTR; i++) { ++ if (!secy_stats_names[i]) ++ continue; ++ printf(" %s", secy_stats_names[i]); ++ } ++ ++ printf("\n%s ", prefix); ++ ++ for (i = 1; i < NUM_MACSEC_SECY_STATS_ATTR; i++) { ++ if (!secy_stats_names[i]) ++ continue; ++ print_one_stat(secy_stats_names, stats, i, true); ++ } ++ ++ printf("\n"); ++} ++ ++static const char *rxsa_stats_names[NUM_MACSEC_SA_STATS_ATTR] = { ++ [MACSEC_SA_STATS_ATTR_IN_PKTS_OK] = "InPktsOK", ++ [MACSEC_SA_STATS_ATTR_IN_PKTS_INVALID] = "InPktsInvalid", ++ [MACSEC_SA_STATS_ATTR_IN_PKTS_NOT_VALID] = "InPktsNotValid", ++ [MACSEC_SA_STATS_ATTR_IN_PKTS_NOT_USING_SA] = "InPktsNotUsingSA", ++ [MACSEC_SA_STATS_ATTR_IN_PKTS_UNUSED_SA] = "InPktsUnusedSA", ++}; ++ ++static void print_rxsa_stats(const char *prefix, struct rtattr *attr) ++{ ++ struct rtattr *stats[MACSEC_SA_STATS_ATTR_MAX + 1]; ++ int i; ++ ++ if (!attr || show_stats == 0) ++ return; ++ ++ parse_rtattr_nested(stats, MACSEC_SA_STATS_ATTR_MAX + 1, attr); ++ printf("%s%s ", prefix, prefix); ++ ++ for (i = 1; i < NUM_MACSEC_SA_STATS_ATTR; i++) { ++ if (!rxsa_stats_names[i]) ++ continue; ++ printf(" %s", rxsa_stats_names[i]); ++ } ++ ++ printf("\n%s%s ", prefix, prefix); ++ ++ for (i = 1; i < NUM_MACSEC_SA_STATS_ATTR; i++) { ++ if (!rxsa_stats_names[i]) ++ continue; ++ print_one_stat(rxsa_stats_names, stats, i, false); ++ } ++ ++ printf("\n"); ++} ++ ++static const char *txsa_stats_names[NUM_MACSEC_SA_STATS_ATTR] = { ++ [MACSEC_SA_STATS_ATTR_OUT_PKTS_PROTECTED] = "OutPktsProtected", ++ [MACSEC_SA_STATS_ATTR_OUT_PKTS_ENCRYPTED] = "OutPktsEncrypted", ++}; ++ ++static void print_txsa_stats(const char *prefix, struct rtattr *attr) ++{ ++ struct rtattr *stats[MACSEC_SA_STATS_ATTR_MAX + 1]; ++ ++ if (!attr || show_stats == 0) ++ return; ++ ++ parse_rtattr_nested(stats, MACSEC_SA_STATS_ATTR_MAX + 1, attr); ++ printf("%s%s %s %s\n", prefix, prefix, ++ txsa_stats_names[MACSEC_SA_STATS_ATTR_OUT_PKTS_PROTECTED], ++ txsa_stats_names[MACSEC_SA_STATS_ATTR_OUT_PKTS_ENCRYPTED]); ++ printf("%s%s ", prefix, prefix); ++ ++ print_one_stat(txsa_stats_names, stats, ++ MACSEC_SA_STATS_ATTR_OUT_PKTS_PROTECTED, false); ++ print_one_stat(txsa_stats_names, stats, ++ MACSEC_SA_STATS_ATTR_OUT_PKTS_ENCRYPTED, false); ++ printf("\n"); ++} ++ ++static void print_tx_sc(const char *prefix, __u64 sci, __u8 encoding_sa, ++ struct rtattr *txsc_stats, struct rtattr *secy_stats, ++ struct rtattr *sa) ++{ ++ struct rtattr *sa_attr[MACSEC_SA_ATTR_MAX + 1]; ++ struct rtattr *a; ++ int rem; ++ ++ printf("%sTXSC: %016llx on SA %d\n", prefix, sci, encoding_sa); ++ print_secy_stats(prefix, secy_stats); ++ print_txsc_stats(prefix, txsc_stats); ++ ++ rem = RTA_PAYLOAD(sa); ++ for (a = RTA_DATA(sa); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) { ++ SPRINT_BUF(keyid); ++ bool state; ++ ++ parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX + 1, a); ++ state = rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_ACTIVE]); ++ printf("%s%s%d: PN %u, state %s, key %s\n", prefix, prefix, ++ rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_AN]), ++ rta_getattr_u32(sa_attr[MACSEC_SA_ATTR_PN]), ++ values_on_off[state], ++ hexstring_n2a(RTA_DATA(sa_attr[MACSEC_SA_ATTR_KEYID]), ++ RTA_PAYLOAD(sa_attr[MACSEC_SA_ATTR_KEYID]), ++ keyid, sizeof(keyid))); ++ print_txsa_stats(prefix, sa_attr[MACSEC_SA_ATTR_STATS]); ++ } ++} ++ ++static const char *rxsc_stats_names[NUM_MACSEC_RXSC_STATS_ATTR] = { ++ [MACSEC_RXSC_STATS_ATTR_IN_OCTETS_VALIDATED] = "InOctetsValidated", ++ [MACSEC_RXSC_STATS_ATTR_IN_OCTETS_DECRYPTED] = "InOctetsDecrypted", ++ [MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNCHECKED] = "InPktsUnchecked", ++ [MACSEC_RXSC_STATS_ATTR_IN_PKTS_DELAYED] = "InPktsDelayed", ++ [MACSEC_RXSC_STATS_ATTR_IN_PKTS_OK] = "InPktsOK", ++ [MACSEC_RXSC_STATS_ATTR_IN_PKTS_INVALID] = "InPktsInvalid", ++ [MACSEC_RXSC_STATS_ATTR_IN_PKTS_LATE] = "InPktsLate", ++ [MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_VALID] = "InPktsNotValid", ++ [MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_USING_SA] = "InPktsNotUsingSA", ++ [MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNUSED_SA] = "InPktsUnusedSA", ++}; ++ ++static void print_rxsc_stats(const char *prefix, struct rtattr *attr) ++{ ++ struct rtattr *stats[MACSEC_RXSC_STATS_ATTR_MAX + 1]; ++ int i; ++ ++ if (!attr || show_stats == 0) ++ return; ++ ++ parse_rtattr_nested(stats, MACSEC_RXSC_STATS_ATTR_MAX + 1, attr); ++ printf("%sstats:", prefix); ++ for (i = 1; i < NUM_MACSEC_RXSC_STATS_ATTR; i++) { ++ if (!rxsc_stats_names[i]) ++ continue; ++ printf(" %s", rxsc_stats_names[i]); ++ } ++ ++ printf("\n%s ", prefix); ++ ++ for (i = 1; i < NUM_MACSEC_RXSC_STATS_ATTR; i++) { ++ if (!rxsc_stats_names[i]) ++ continue; ++ print_one_stat(rxsc_stats_names, stats, i, true); ++ } ++ ++ printf("\n"); ++} ++ ++static void print_rx_sc(const char *prefix, __u64 sci, __u8 active, ++ struct rtattr *rxsc_stats, struct rtattr *sa) ++{ ++ struct rtattr *sa_attr[MACSEC_SA_ATTR_MAX + 1]; ++ struct rtattr *a; ++ int rem; ++ ++ printf("%sRXSC: %016llx, state %s\n", prefix, sci, ++ values_on_off[!!active]); ++ print_rxsc_stats(prefix, rxsc_stats); ++ ++ rem = RTA_PAYLOAD(sa); ++ for (a = RTA_DATA(sa); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) { ++ SPRINT_BUF(keyid); ++ bool state; ++ ++ parse_rtattr_nested(sa_attr, MACSEC_SA_ATTR_MAX + 1, a); ++ state = rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_ACTIVE]); ++ printf("%s%s%d: PN %u, state %s, key %s\n", prefix, prefix, ++ rta_getattr_u8(sa_attr[MACSEC_SA_ATTR_AN]), ++ rta_getattr_u32(sa_attr[MACSEC_SA_ATTR_PN]), ++ values_on_off[state], ++ hexstring_n2a(RTA_DATA(sa_attr[MACSEC_SA_ATTR_KEYID]), ++ RTA_PAYLOAD(sa_attr[MACSEC_SA_ATTR_KEYID]), ++ keyid, sizeof(keyid))); ++ print_rxsa_stats(prefix, sa_attr[MACSEC_SA_ATTR_STATS]); ++ } ++} ++ ++static int process(const struct sockaddr_nl *who, struct nlmsghdr *n, ++ void *arg) ++{ ++ struct genlmsghdr *ghdr; ++ struct rtattr *attrs[MACSEC_ATTR_MAX + 1], *sc, *c; ++ struct rtattr *attrs_secy[MACSEC_SECY_ATTR_MAX + 1]; ++ int len = n->nlmsg_len; ++ int ifindex; ++ __u64 sci; ++ __u8 encoding_sa; ++ int rem; ++ ++ if (n->nlmsg_type != genl_family) ++ return -1; ++ ++ len -= NLMSG_LENGTH(GENL_HDRLEN); ++ if (len < 0) ++ return -1; ++ ++ ghdr = NLMSG_DATA(n); ++ if (ghdr->cmd != MACSEC_CMD_GET_TXSC) ++ return 0; ++ ++ parse_rtattr(attrs, MACSEC_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len); ++ if (!validate_dump(attrs)) { ++ printf("incomplete dump message\n"); ++ return -1; ++ } ++ ++ ifindex = rta_getattr_u32(attrs[MACSEC_ATTR_IFINDEX]); ++ parse_rtattr_nested(attrs_secy, MACSEC_SECY_ATTR_MAX + 1, ++ attrs[MACSEC_ATTR_SECY]); ++ ++ if (!validate_secy_dump(attrs_secy)) { ++ printf("incomplete dump message\n"); ++ return -1; ++ } ++ ++ sci = rta_getattr_u64(attrs_secy[MACSEC_SECY_ATTR_SCI]); ++ encoding_sa = rta_getattr_u8(attrs_secy[MACSEC_SECY_ATTR_ENCODING_SA]); ++ ++ if (filter.ifindex && ifindex != filter.ifindex) ++ return 0; ++ ++ if (filter.sci && sci != filter.sci) ++ return 0; ++ ++ printf("%d: %s: ", ifindex, ll_index_to_name(ifindex)); ++ print_attrs(" ", attrs_secy); ++ ++ print_tx_sc(" ", sci, encoding_sa, ++ attrs[MACSEC_ATTR_TXSC_STATS], ++ attrs[MACSEC_ATTR_SECY_STATS], ++ attrs[MACSEC_ATTR_TXSA_LIST]); ++ ++ if (!attrs[MACSEC_ATTR_RXSC_LIST]) ++ return 0; ++ ++ sc = attrs[MACSEC_ATTR_RXSC_LIST]; ++ rem = RTA_PAYLOAD(sc); ++ for (c = RTA_DATA(sc); RTA_OK(c, rem); c = RTA_NEXT(c, rem)) { ++ struct rtattr *sc_attr[MACSEC_RXSC_ATTR_MAX + 1]; ++ ++ parse_rtattr_nested(sc_attr, MACSEC_RXSC_ATTR_MAX + 1, c); ++ print_rx_sc(" ", ++ rta_getattr_u64(sc_attr[MACSEC_RXSC_ATTR_SCI]), ++ rta_getattr_u32(sc_attr[MACSEC_RXSC_ATTR_ACTIVE]), ++ sc_attr[MACSEC_RXSC_ATTR_STATS], ++ sc_attr[MACSEC_RXSC_ATTR_SA_LIST]); ++ } ++ ++ return 0; ++} ++ ++static int do_dump(int ifindex) ++{ ++ MACSEC_GENL_REQ(req, MACSEC_BUFLEN, MACSEC_CMD_GET_TXSC, ++ NLM_F_REQUEST | NLM_F_DUMP); ++ ++ memset(&filter, 0, sizeof(filter)); ++ filter.ifindex = ifindex; ++ ++ req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq; ++ if (rtnl_send(&genl_rth, &req, req.n.nlmsg_len) < 0) { ++ perror("Failed to send dump request"); ++ exit(1); ++ } ++ ++ if (rtnl_dump_filter(&genl_rth, process, stdout) < 0) { ++ fprintf(stderr, "Dump terminated\n"); ++ exit(1); ++ } ++ ++ return 0; ++} ++ ++static int do_show(int argc, char **argv) ++{ ++ int ifindex; ++ ++ if (argc == 0) ++ return do_dump(0); ++ ++ ifindex = ll_name_to_index(*argv); ++ if (ifindex == 0) { ++ fprintf(stderr, "Device \"%s\" does not exist.\n", *argv); ++ return -1; ++ } ++ ++ argc--, argv++; ++ if (argc == 0) ++ return do_dump(ifindex); ++ ++ ipmacsec_usage(); ++ return -1; ++} ++ ++int do_ipmacsec(int argc, char **argv) ++{ ++ init_genl(); ++ ++ if (argc < 1) ++ ipmacsec_usage(); ++ ++ if (matches(*argv, "help") == 0) ++ ipmacsec_usage(); ++ ++ if (matches(*argv, "show") == 0) ++ return do_show(argc-1, argv+1); ++ ++ if (matches(*argv, "add") == 0) ++ return do_modify(CMD_ADD, argc-1, argv+1); ++ if (matches(*argv, "set") == 0) ++ return do_modify(CMD_UPD, argc-1, argv+1); ++ if (matches(*argv, "delete") == 0) ++ return do_modify(CMD_DEL, argc-1, argv+1); ++ ++ fprintf(stderr, "Command \"%s\" is unknown, try \"ip macsec help\".\n", ++ *argv); ++ exit(-1); ++} ++ ++/* device creation */ ++static void macsec_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) ++{ ++ if (!tb) ++ return; ++ ++ if (tb[IFLA_MACSEC_SCI]) { ++ fprintf(f, "sci %016llx ", ++ rta_getattr_u64(tb[IFLA_MACSEC_SCI])); ++ } ++ ++ print_flag(f, tb, "protect", IFLA_MACSEC_PROTECT); ++ ++ if (tb[IFLA_MACSEC_CIPHER_SUITE]) { ++ __u64 csid = rta_getattr_u64(tb[IFLA_MACSEC_CIPHER_SUITE]); ++ ++ fprintf(f, "cipher %s ", cs_id_to_name(csid)); ++ } ++ ++ if (tb[IFLA_MACSEC_ICV_LEN]) { ++ fprintf(f, "icvlen %hhu ", ++ rta_getattr_u8(tb[IFLA_MACSEC_ICV_LEN])); ++ } ++ ++ if (tb[IFLA_MACSEC_ENCODING_SA]) { ++ fprintf(f, "encodingsa %hhu ", ++ rta_getattr_u8(tb[IFLA_MACSEC_ENCODING_SA])); ++ } ++ ++ if (tb[IFLA_MACSEC_VALIDATION]) { ++ __u8 val = rta_getattr_u8(tb[IFLA_MACSEC_VALIDATION]); ++ ++ fprintf(f, "validate %s ", VALIDATE_STR[val]); ++ } ++ ++ print_flag(f, tb, "encrypt", IFLA_MACSEC_ENCRYPT); ++ print_flag(f, tb, "send_sci", IFLA_MACSEC_INC_SCI); ++ print_flag(f, tb, "end_station", IFLA_MACSEC_ES); ++ print_flag(f, tb, "scb", IFLA_MACSEC_SCB); ++ ++ print_flag(f, tb, "replay", IFLA_MACSEC_REPLAY_PROTECT); ++ if (tb[IFLA_MACSEC_WINDOW]) { ++ fprintf(f, "window %d ", ++ rta_getattr_u32(tb[IFLA_MACSEC_WINDOW])); ++ } ++} ++ ++ ++static int do_cipher_suite(struct cipher_args *cipher, int *argcp, ++ char ***argvp) ++{ ++ char **argv = *argvp; ++ int argc = *argcp; ++ ++ if (argc == 0) ++ return -1; ++ ++ if (strcmp(*argv, "default") == 0 || ++ strcmp(*argv, "gcm-aes-128") == 0 || ++ strcmp(*argv, "GCM-AES-128") == 0) ++ cipher->id = MACSEC_DEFAULT_CIPHER_ID; ++ NEXT_ARG(); ++ ++ if (strcmp(*argv, "icvlen") == 0) { ++ NEXT_ARG(); ++ if (cipher->icv_len != 0) ++ duparg2("icvlen", "icvlen"); ++ get_icvlen(&cipher->icv_len, *argv); ++ } ++ *argcp = argc; ++ *argvp = argv; ++ ++ return 0; ++} ++ ++static bool check_txsc_flags(bool es, bool scb, bool sci) ++{ ++ if (sci && (es || scb)) ++ return false; ++ if (es && scb) ++ return false; ++ return true; ++} ++ ++static void usage(FILE *f) ++{ ++ fprintf(f, ++ "Usage: ... macsec [ port PORT | sci SCI ]\n" ++ " [ cipher CIPHER_SUITE ]\n" ++ " [ encrypt { on | off } ]\n" ++ " [ send_sci { on | off } ]\n" ++ " [ end_station { on | off } ]\n" ++ " [ scb { on | off } ]\n" ++ " [ protect { on | off } ]\n" ++ " [ replay { on | off} window { 0..2^32-1 } ]\n" ++ " [ validate { strict | check | disabled } ]\n" ++ " [ encodingsa { 0..3 } ]\n" ++ ); ++ fprintf(f, "CIPHER_SUITE := [ default = gcm-aes-128 ] icvlen { 8..32 }\n"); ++} ++ ++static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, ++ struct nlmsghdr *hdr) ++{ ++ int ret; ++ __u8 encoding_sa = 0xff; ++ __u32 window = -1; ++ struct cipher_args cipher = {0}; ++ enum macsec_validation_type validate; ++ bool es = false, scb = false, send_sci = false; ++ int replay_protect = -1; ++ struct sci sci = { 0 }; ++ ++ ret = get_sci_portaddr(&sci, &argc, &argv, true, true); ++ if (ret < 0) { ++ fprintf(stderr, "expected sci\n"); ++ return -1; ++ } ++ ++ if (ret > 0) { ++ if (sci.sci) ++ addattr_l(hdr, MACSEC_BUFLEN, IFLA_MACSEC_SCI, ++ &sci.sci, sizeof(sci.sci)); ++ else ++ addattr_l(hdr, MACSEC_BUFLEN, IFLA_MACSEC_PORT, ++ &sci.port, sizeof(sci.port)); ++ } ++ ++ while (argc > 0) { ++ if (strcmp(*argv, "cipher") == 0) { ++ if (cipher.id) ++ duparg2("cipher", "cipher"); ++ NEXT_ARG(); ++ if (do_cipher_suite(&cipher, &argc, &argv)) ++ return -1; ++ } else if (strcmp(*argv, "encrypt") == 0) { ++ NEXT_ARG(); ++ int i; ++ ++ ret = one_of("encrypt", *argv, values_on_off, ++ ARRAY_SIZE(values_on_off), &i); ++ if (ret != 0) ++ return ret; ++ addattr8(hdr, MACSEC_BUFLEN, IFLA_MACSEC_ENCRYPT, i); ++ } else if (strcmp(*argv, "send_sci") == 0) { ++ NEXT_ARG(); ++ int i; ++ ++ ret = one_of("send_sci", *argv, values_on_off, ++ ARRAY_SIZE(values_on_off), &i); ++ if (ret != 0) ++ return ret; ++ send_sci = i; ++ addattr8(hdr, MACSEC_BUFLEN, ++ IFLA_MACSEC_INC_SCI, send_sci); ++ } else if (strcmp(*argv, "end_station") == 0) { ++ NEXT_ARG(); ++ int i; ++ ++ ret = one_of("end_station", *argv, values_on_off, ++ ARRAY_SIZE(values_on_off), &i); ++ if (ret != 0) ++ return ret; ++ es = i; ++ addattr8(hdr, MACSEC_BUFLEN, IFLA_MACSEC_ES, es); ++ } else if (strcmp(*argv, "scb") == 0) { ++ NEXT_ARG(); ++ int i; ++ ++ ret = one_of("scb", *argv, values_on_off, ++ ARRAY_SIZE(values_on_off), &i); ++ if (ret != 0) ++ return ret; ++ scb = i; ++ addattr8(hdr, MACSEC_BUFLEN, IFLA_MACSEC_SCB, scb); ++ } else if (strcmp(*argv, "protect") == 0) { ++ NEXT_ARG(); ++ int i; ++ ++ ret = one_of("protect", *argv, values_on_off, ++ ARRAY_SIZE(values_on_off), &i); ++ if (ret != 0) ++ return ret; ++ addattr8(hdr, MACSEC_BUFLEN, IFLA_MACSEC_PROTECT, i); ++ } else if (strcmp(*argv, "replay") == 0) { ++ NEXT_ARG(); ++ int i; ++ ++ ret = one_of("replay", *argv, values_on_off, ++ ARRAY_SIZE(values_on_off), &i); ++ if (ret != 0) ++ return ret; ++ replay_protect = !!i; ++ } else if (strcmp(*argv, "window") == 0) { ++ NEXT_ARG(); ++ ret = get_u32(&window, *argv, 0); ++ if (ret) ++ invarg("expected replay window size", *argv); ++ } else if (strcmp(*argv, "validate") == 0) { ++ NEXT_ARG(); ++ ret = one_of("validate", *argv, ++ VALIDATE_STR, ARRAY_SIZE(VALIDATE_STR), ++ (int *)&validate); ++ if (ret != 0) ++ return ret; ++ addattr8(hdr, MACSEC_BUFLEN, ++ IFLA_MACSEC_VALIDATION, validate); ++ } else if (strcmp(*argv, "encodingsa") == 0) { ++ if (encoding_sa != 0xff) ++ duparg2("encodingsa", "encodingsa"); ++ NEXT_ARG(); ++ ret = get_an(&encoding_sa, *argv); ++ if (ret) ++ invarg("expected an { 0..3 }", *argv); ++ } else { ++ fprintf(stderr, "macsec: unknown command \"%s\"?\n", ++ *argv); ++ usage(stderr); ++ return -1; ++ } ++ ++ argv++; argc--; ++ } ++ ++ if (!check_txsc_flags(es, scb, send_sci)) { ++ fprintf(stderr, "invalid combination of send_sci/end_station/scb\n"); ++ return -1; ++ } ++ ++ if (window != -1 && replay_protect == -1) { ++ fprintf(stderr, ++ "replay window set, but replay protection not enabled. did you mean 'replay on window %u'?\n", ++ window); ++ return -1; ++ } else if (window == -1 && replay_protect == 1) { ++ fprintf(stderr, ++ "replay protection enabled, but no window set. did you mean 'replay on window VALUE'?\n"); ++ return -1; ++ } ++ ++ if (cipher.id) { ++ addattr_l(hdr, MACSEC_BUFLEN, IFLA_MACSEC_CIPHER_SUITE, ++ &cipher.id, sizeof(cipher.id)); ++ addattr_l(hdr, MACSEC_BUFLEN, IFLA_MACSEC_ICV_LEN, ++ &cipher.icv_len, sizeof(cipher.icv_len)); ++ } ++ ++ if (replay_protect != -1) { ++ addattr32(hdr, MACSEC_BUFLEN, IFLA_MACSEC_WINDOW, window); ++ addattr8(hdr, MACSEC_BUFLEN, IFLA_MACSEC_REPLAY_PROTECT, ++ replay_protect); ++ } ++ ++ if (encoding_sa != 0xff) { ++ addattr_l(hdr, MACSEC_BUFLEN, IFLA_MACSEC_ENCODING_SA, ++ &encoding_sa, sizeof(encoding_sa)); ++ } ++ ++ return 0; ++} ++ ++static void macsec_print_help(struct link_util *lu, int argc, char **argv, ++ FILE *f) ++{ ++ usage(f); ++} ++ ++struct link_util macsec_link_util = { ++ .id = "macsec", ++ .maxattr = IFLA_MACSEC_MAX, ++ .parse_opt = macsec_parse_opt, ++ .print_help = macsec_print_help, ++ .print_opt = macsec_print_opt, ++ .slave = false, ++}; +diff --git a/man/man8/Makefile b/man/man8/Makefile +index 8389fce..f3a3fa5 100644 +--- a/man/man8/Makefile ++++ b/man/man8/Makefile +@@ -7,7 +7,7 @@ MAN8PAGES = $(TARGETS) ip.8 arpd.8 lnstat.8 routel.8 rtacct.8 rtmon.8 rtpr.8 ss. + tc-netem.8 tc-pfifo.8 tc-pfifo_fast.8 tc-prio.8 tc-red.8 \ + tc-sfb.8 tc-sfq.8 tc-stab.8 tc-tbf.8 \ + bridge.8 rtstat.8 ctstat.8 nstat.8 routef.8 \ +- ip-addrlabel.8 ip-l2tp.8 \ ++ ip-addrlabel.8 ip-l2tp.8 ip-macsec.8 \ + ip-maddress.8 ip-monitor.8 ip-mroute.8 ip-neighbour.8 \ + ip-netns.8 ip-ntable.8 ip-rule.8 ip-tunnel.8 ip-xfrm.8 \ + ip-tcp_metrics.8 ip-netconf.8 ip-token.8 \ +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 3002e47..ac3bb77 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -235,6 +235,9 @@ Link types: + .sp + .BR geneve + - GEneric NEtwork Virtualization Encapsulation ++.sp ++.BR macsec ++- Interface for IEEE 802.1AE MAC Security (MACsec) + .in -8 + + .TP +@@ -751,6 +754,88 @@ forces the underlying interface into promiscuous mode. Passing the + using standard tools. + .in -8 + ++.TP ++MACsec Type Support ++For a link of type ++.I MACsec ++the following additional arguments are supported: ++ ++.BI "ip link add link " DEVICE " name " NAME " type macsec" ++[ ++.BI port " PORT" ++| ++.BI sci " SCI" ++] [ ++.BI cipher " CIPHER_SUITE" ++] [ ++.BR encrypt " {" ++.BR on " | " off " } ] [ " ++.BR send_sci " { " on " | " off " } ] [" ++.BR es " { " on " | " off " } ] [" ++.BR scb " { " on " | " off " } ] [" ++.BR protect " { " on " | " off " } ] [" ++.BR replay " { " on " | " off " }" ++.BR window " { " ++.IR 0..2^32-1 " } ] [" ++.BR validate " { " strict " | " check " | " disabled " } ] [" ++.BR encoding " { " ++.IR 0..3 " } ]" ++ ++.in +8 ++.sp ++.BI port " PORT " ++- sets the port number for this MACsec device. ++ ++.sp ++.BI sci " SCI " ++- sets the SCI for this MACsec device. ++ ++.sp ++.BI cipher " CIPHER_SUITE " ++- defines the cipher suite to use. ++ ++.sp ++.BR "encrypt on " or " encrypt off" ++- switches between authenticated encryption, or authenticity mode only. ++ ++.sp ++.BR "send_sci on " or " send_sci off" ++- specifies whether the SCI is included in every packet, or only when it is necessary. ++ ++.sp ++.BR "es on " or " es off" ++- sets the End Station bit. ++ ++.sp ++.BR "scb on " or " scb off" ++- sets the Single Copy Broadcast bit. ++ ++.sp ++.BR "protect on " or " protect off" ++- enables MACsec protection on the device. ++ ++.sp ++.BR "replay on " or " replay off" ++- enables replay protection on the device. ++ ++.in +8 ++ ++.sp ++.BI window " SIZE " ++- sets the size of the replay window. ++ ++.in -8 ++ ++.sp ++.BR "validate strict " or " validate check " or " validate disabled" ++- sets the validation mode on the device. ++ ++.sp ++.BI encoding " AN " ++- sets the active secure association for transmission. ++ ++.in -8 ++ + .SS ip link delete - delete virtual link + + .TP +diff --git a/man/man8/ip-macsec.8 b/man/man8/ip-macsec.8 +new file mode 100644 +index 0000000..e8455d7 +--- /dev/null ++++ b/man/man8/ip-macsec.8 +@@ -0,0 +1,98 @@ ++.TH IP\-MACSEC 8 "07 Mar 2016" "iproute" "Linux" ++.SH NAME ++ip-macsec \- MACsec device configuration ++.SH "SYNOPSIS" ++.BI "ip link add link " DEVICE " name " NAME " type macsec " ++[ [ ++.BR cipher " { " default " | " gcm-aes-128 " } ] " ++.BI icvlen " ICVLEN" ++] [ [ ++.BR encrypt " { " on " | " off " } ] [" ++.BR send_sci " { " on " | " off " } ] [" ++.BR end_station " { " on " | " off " } ] [" ++.BR scb " { " on " | " off " } ] [" ++.BR protect " { " on " | " off " } ] [" ++.BR replay " { " on " | " off " } ] [" ++.BI window " WINDOW" ++] [ ++.BI encodingsa " SA" ++] ++ ++.BI "ip macsec add " DEV " tx sa" ++.RI "{ " 0..3 " } [ " OPTS " ]" ++.BI key " ID KEY" ++.br ++.BI "ip macsec set " DEV " tx sa" ++.RI "{ " 0..3 " } [ " OPTS " ]" ++.br ++.BI "ip macsec del " DEV " tx sa" ++.RI "{ " 0..3 " }" ++ ++.BI "ip macsec add " DEV " rx " SCI ++.RB [ " on " | " off " ] ++.br ++.BI "ip macsec set " DEV " rx " SCI ++.RB [ " on " | " off " ] ++.br ++.BI "ip macsec del " DEV " rx " SCI ++ ++.BI "ip macsec add " DEV " rx " SCI " sa" ++.RI "{ " 0..3 " } [ " OPTS " ]" ++.BI key " ID KEY" ++.br ++.BI "ip macsec set " DEV " rx " SCI " sa" ++.RI "{ " 0..3 " } [ " OPTS " ]" ++.br ++.BI "ip macsec del " DEV " rx " SCI " sa" ++.RI "{ " 0..3 " }" ++ ++.B ip macsec show ++.RI [ " DEV " ] ++ ++.IR OPTS " := [ " ++.BR pn " { " ++.IR 1..2^32-1 " } ] [" ++.BR on " | " off " ]" ++.br ++.IR SCI " := { " ++.B sci ++.IR <u64> " | " ++.BI port " <u16> " address " <lladdr> " ++} ++ ++ ++.SH DESCRIPTION ++The ++.B ip macsec ++commands are used to configure transmit secure associations and receive secure channels and their secure associations on a MACsec device created with the ++.B ip link add ++command using the ++.I macsec ++type. ++ ++.SH EXAMPLES ++.PP ++.SS Create a MACsec device on link eth0 ++.nf ++# ip link add device eth0 macsec0 type macsec port 11 encrypt on ++.PP ++.SS Configure a secure association on that device ++.nf ++# ip macsec add macsec0 tx sa 0 pn 1024 on key 01 81818181818181818181818181818181 ++.PP ++.SS Configure a receive channel ++.nf ++# ip macsec add macsec0 rx port 1234 address c6:19:52:8f:e6:a0 ++.PP ++.SS Configure a receive association ++.nf ++# ip macsec add macsec0 rx port 1234 address c6:19:52:8f:e6:a0 sa 0 pn 1 on key 00 82828282828282828282828282828282 ++.PP ++.SS Display MACsec configuration ++.nf ++# ip macsec show ++.SH SEE ALSO ++.br ++.BR ip-link (8) ++.SH AUTHOR ++Sabrina Dubroca <sd@queasysnail.net> +-- +1.8.3.1 + diff --git a/SOURCES/0177-utils-fix-hex-digits-parsing-in-hexstring_a2n.patch b/SOURCES/0177-utils-fix-hex-digits-parsing-in-hexstring_a2n.patch new file mode 100644 index 0000000..47fa534 --- /dev/null +++ b/SOURCES/0177-utils-fix-hex-digits-parsing-in-hexstring_a2n.patch @@ -0,0 +1,40 @@ +From 91c9a1f1f26b1800e1d1d1cd7d814d3e2d14f822 Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 6 Jul 2016 18:41:37 +0200 +Subject: [PATCH] utils: fix hex digits parsing in hexstring_a2n() + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1300765 +Upstream Status: iproute2.git commit 9ba4126dc4d6 + +commit 9ba4126dc4d6abb8dc5c8c8d52177849e764a14e +Author: Beniamino Galvani <bgalvani@redhat.com> +Date: Tue Jun 14 22:55:17 2016 +0200 + + utils: fix hex digits parsing in hexstring_a2n() + + strtoul() only modifies errno on overflow, so if errno is not zero + before calling the function its value is preserved and makes the + function fail for valid inputs; initialize it. + + Signed-off-by: Beniamino Galvani <bgalvani@redhat.com> + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + lib/utils.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/utils.c b/lib/utils.c +index dedadff..b310166 100644 +--- a/lib/utils.c ++++ b/lib/utils.c +@@ -834,6 +834,7 @@ __u8 *hexstring_a2n(const char *str, __u8 *buf, int blen, unsigned int *len) + + strncpy(tmpstr, str, 2); + tmpstr[2] = '\0'; ++ errno = 0; + tmp = strtoul(tmpstr, &endptr, 16); + if (errno != 0 || tmp > 0xFF || *endptr != '\0') + return NULL; +-- +1.8.3.1 + diff --git a/SOURCES/0178-RH-INTERNAL-update-kernel-headers-to-v4.6.0.patch b/SOURCES/0178-RH-INTERNAL-update-kernel-headers-to-v4.6.0.patch new file mode 100644 index 0000000..3d5c03d --- /dev/null +++ b/SOURCES/0178-RH-INTERNAL-update-kernel-headers-to-v4.6.0.patch @@ -0,0 +1,1152 @@ +From aefa5a575081f3ce848944ab4150918b41bc1268 Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 6 Jul 2016 18:41:38 +0200 +Subject: [PATCH] RH-INTERNAL: update kernel headers to v4.6.0 + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1300765 + +4.6.0 is the latest iproute2 tag including support for MACsec. +Obtained using the following command: + +$ git checkout v4.6.0 -- include/linux + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + include/linux/bpf.h | 155 +++++++++++++++++++++++-------- + include/linux/devlink.h | 72 ++++++++++++++ + include/linux/genetlink.h | 1 + + include/linux/if.h | 30 +++++- + include/linux/if_bridge.h | 38 +++++++- + include/linux/if_ether.h | 1 + + include/linux/if_link.h | 101 ++++++++++++++++++++ + include/linux/ila.h | 37 ++++++++ + include/linux/in6.h | 1 + + include/linux/libc-compat.h | 44 +++++++++ + include/linux/lwtunnel.h | 43 +++++++++ + include/linux/mpls_iptunnel.h | 28 ++++++ + include/linux/netconf.h | 1 + + include/linux/netfilter_ipv4/ip_tables.h | 1 + + include/linux/netlink.h | 1 + + include/linux/pkt_cls.h | 7 ++ + include/linux/pkt_sched.h | 4 + + include/linux/rtnetlink.h | 3 + + include/linux/sock_diag.h | 1 + + include/linux/tc_act/tc_ife.h | 38 ++++++++ + include/linux/tcp.h | 5 + + 21 files changed, 571 insertions(+), 41 deletions(-) + create mode 100644 include/linux/devlink.h + create mode 100644 include/linux/ila.h + create mode 100644 include/linux/lwtunnel.h + create mode 100644 include/linux/mpls_iptunnel.h + create mode 100644 include/linux/tc_act/tc_ife.h + +diff --git a/include/linux/bpf.h b/include/linux/bpf.h +index 3d6d00b..0f5d6f5 100644 +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -63,50 +63,16 @@ struct bpf_insn { + __s32 imm; /* signed immediate constant */ + }; + +-/* BPF syscall commands */ ++/* BPF syscall commands, see bpf(2) man-page for details. */ + enum bpf_cmd { +- /* create a map with given type and attributes +- * fd = bpf(BPF_MAP_CREATE, union bpf_attr *, u32 size) +- * returns fd or negative error +- * map is deleted when fd is closed +- */ + BPF_MAP_CREATE, +- +- /* lookup key in a given map +- * err = bpf(BPF_MAP_LOOKUP_ELEM, union bpf_attr *attr, u32 size) +- * Using attr->map_fd, attr->key, attr->value +- * returns zero and stores found elem into value +- * or negative error +- */ + BPF_MAP_LOOKUP_ELEM, +- +- /* create or update key/value pair in a given map +- * err = bpf(BPF_MAP_UPDATE_ELEM, union bpf_attr *attr, u32 size) +- * Using attr->map_fd, attr->key, attr->value, attr->flags +- * returns zero or negative error +- */ + BPF_MAP_UPDATE_ELEM, +- +- /* find and delete elem by key in a given map +- * err = bpf(BPF_MAP_DELETE_ELEM, union bpf_attr *attr, u32 size) +- * Using attr->map_fd, attr->key +- * returns zero or negative error +- */ + BPF_MAP_DELETE_ELEM, +- +- /* lookup key in a given map and return next key +- * err = bpf(BPF_MAP_GET_NEXT_KEY, union bpf_attr *attr, u32 size) +- * Using attr->map_fd, attr->key, attr->next_key +- * returns zero and stores next key or negative error +- */ + BPF_MAP_GET_NEXT_KEY, +- +- /* verify and load eBPF program +- * prog_fd = bpf(BPF_PROG_LOAD, union bpf_attr *attr, u32 size) +- * Using attr->prog_type, attr->insns, attr->license +- * returns fd or negative error +- */ + BPF_PROG_LOAD, ++ BPF_OBJ_PIN, ++ BPF_OBJ_GET, + }; + + enum bpf_map_type { +@@ -115,6 +81,9 @@ enum bpf_map_type { + BPF_MAP_TYPE_ARRAY, + BPF_MAP_TYPE_PROG_ARRAY, + BPF_MAP_TYPE_PERF_EVENT_ARRAY, ++ BPF_MAP_TYPE_PERCPU_HASH, ++ BPF_MAP_TYPE_PERCPU_ARRAY, ++ BPF_MAP_TYPE_STACK_TRACE, + }; + + enum bpf_prog_type { +@@ -132,12 +101,15 @@ enum bpf_prog_type { + #define BPF_NOEXIST 1 /* create new element if it didn't exist */ + #define BPF_EXIST 2 /* update existing element */ + ++#define BPF_F_NO_PREALLOC (1U << 0) ++ + union bpf_attr { + struct { /* anonymous struct used by BPF_MAP_CREATE command */ + __u32 map_type; /* one of enum bpf_map_type */ + __u32 key_size; /* size of key in bytes */ + __u32 value_size; /* size of value in bytes */ + __u32 max_entries; /* max number of entries in a map */ ++ __u32 map_flags; /* prealloc or not */ + }; + + struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ +@@ -160,6 +132,11 @@ union bpf_attr { + __aligned_u64 log_buf; /* user supplied buffer */ + __u32 kern_version; /* checked when prog_type=kprobe */ + }; ++ ++ struct { /* anonymous struct used by BPF_OBJ_* commands */ ++ __aligned_u64 pathname; ++ __u32 bpf_fd; ++ }; + } __attribute__((aligned(8))); + + /* integer value in 'imm' field of BPF_CALL instruction selects which helper +@@ -272,9 +249,103 @@ enum bpf_func_id { + BPF_FUNC_skb_get_tunnel_key, + BPF_FUNC_skb_set_tunnel_key, + BPF_FUNC_perf_event_read, /* u64 bpf_perf_event_read(&map, index) */ ++ /** ++ * bpf_redirect(ifindex, flags) - redirect to another netdev ++ * @ifindex: ifindex of the net device ++ * @flags: bit 0 - if set, redirect to ingress instead of egress ++ * other bits - reserved ++ * Return: TC_ACT_REDIRECT ++ */ ++ BPF_FUNC_redirect, ++ ++ /** ++ * bpf_get_route_realm(skb) - retrieve a dst's tclassid ++ * @skb: pointer to skb ++ * Return: realm if != 0 ++ */ ++ BPF_FUNC_get_route_realm, ++ ++ /** ++ * bpf_perf_event_output(ctx, map, index, data, size) - output perf raw sample ++ * @ctx: struct pt_regs* ++ * @map: pointer to perf_event_array map ++ * @index: index of event in the map ++ * @data: data on stack to be output as raw data ++ * @size: size of data ++ * Return: 0 on success ++ */ ++ BPF_FUNC_perf_event_output, ++ BPF_FUNC_skb_load_bytes, ++ ++ /** ++ * bpf_get_stackid(ctx, map, flags) - walk user or kernel stack and return id ++ * @ctx: struct pt_regs* ++ * @map: pointer to stack_trace map ++ * @flags: bits 0-7 - numer of stack frames to skip ++ * bit 8 - collect user stack instead of kernel ++ * bit 9 - compare stacks by hash only ++ * bit 10 - if two different stacks hash into the same stackid ++ * discard old ++ * other bits - reserved ++ * Return: >= 0 stackid on success or negative error ++ */ ++ BPF_FUNC_get_stackid, ++ ++ /** ++ * bpf_csum_diff(from, from_size, to, to_size, seed) - calculate csum diff ++ * @from: raw from buffer ++ * @from_size: length of from buffer ++ * @to: raw to buffer ++ * @to_size: length of to buffer ++ * @seed: optional seed ++ * Return: csum result ++ */ ++ BPF_FUNC_csum_diff, ++ ++ /** ++ * bpf_skb_[gs]et_tunnel_opt(skb, opt, size) ++ * retrieve or populate tunnel options metadata ++ * @skb: pointer to skb ++ * @opt: pointer to raw tunnel option data ++ * @size: size of @opt ++ * Return: 0 on success for set, option size for get ++ */ ++ BPF_FUNC_skb_get_tunnel_opt, ++ BPF_FUNC_skb_set_tunnel_opt, + __BPF_FUNC_MAX_ID, + }; + ++/* All flags used by eBPF helper functions, placed here. */ ++ ++/* BPF_FUNC_skb_store_bytes flags. */ ++#define BPF_F_RECOMPUTE_CSUM (1ULL << 0) ++#define BPF_F_INVALIDATE_HASH (1ULL << 1) ++ ++/* BPF_FUNC_l3_csum_replace and BPF_FUNC_l4_csum_replace flags. ++ * First 4 bits are for passing the header field size. ++ */ ++#define BPF_F_HDR_FIELD_MASK 0xfULL ++ ++/* BPF_FUNC_l4_csum_replace flags. */ ++#define BPF_F_PSEUDO_HDR (1ULL << 4) ++#define BPF_F_MARK_MANGLED_0 (1ULL << 5) ++ ++/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */ ++#define BPF_F_INGRESS (1ULL << 0) ++ ++/* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */ ++#define BPF_F_TUNINFO_IPV6 (1ULL << 0) ++ ++/* BPF_FUNC_get_stackid flags. */ ++#define BPF_F_SKIP_FIELD_MASK 0xffULL ++#define BPF_F_USER_STACK (1ULL << 8) ++#define BPF_F_FAST_STACK_CMP (1ULL << 9) ++#define BPF_F_REUSE_STACKID (1ULL << 10) ++ ++/* BPF_FUNC_skb_set_tunnel_key flags. */ ++#define BPF_F_ZERO_CSUM_TX (1ULL << 1) ++#define BPF_F_DONT_FRAGMENT (1ULL << 2) ++ + /* user accessible mirror of in-kernel sk_buff. + * new fields can only be added to the end of this structure + */ +@@ -293,11 +364,19 @@ struct __sk_buff { + __u32 tc_index; + __u32 cb[5]; + __u32 hash; ++ __u32 tc_classid; + }; + + struct bpf_tunnel_key { + __u32 tunnel_id; +- __u32 remote_ipv4; ++ union { ++ __u32 remote_ipv4; ++ __u32 remote_ipv6[4]; ++ }; ++ __u8 tunnel_tos; ++ __u8 tunnel_ttl; ++ __u16 tunnel_ext; ++ __u32 tunnel_label; + }; + + #endif /* __LINUX_BPF_H__ */ +diff --git a/include/linux/devlink.h b/include/linux/devlink.h +new file mode 100644 +index 0000000..a96e1a0 +--- /dev/null ++++ b/include/linux/devlink.h +@@ -0,0 +1,72 @@ ++/* ++ * include/uapi/linux/devlink.h - Network physical device Netlink interface ++ * Copyright (c) 2016 Mellanox Technologies. All rights reserved. ++ * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> ++ * ++ * 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_DEVLINK_H_ ++#define _LINUX_DEVLINK_H_ ++ ++#define DEVLINK_GENL_NAME "devlink" ++#define DEVLINK_GENL_VERSION 0x1 ++#define DEVLINK_GENL_MCGRP_CONFIG_NAME "config" ++ ++enum devlink_command { ++ /* don't change the order or add anything between, this is ABI! */ ++ DEVLINK_CMD_UNSPEC, ++ ++ DEVLINK_CMD_GET, /* can dump */ ++ DEVLINK_CMD_SET, ++ DEVLINK_CMD_NEW, ++ DEVLINK_CMD_DEL, ++ ++ DEVLINK_CMD_PORT_GET, /* can dump */ ++ DEVLINK_CMD_PORT_SET, ++ DEVLINK_CMD_PORT_NEW, ++ DEVLINK_CMD_PORT_DEL, ++ ++ DEVLINK_CMD_PORT_SPLIT, ++ DEVLINK_CMD_PORT_UNSPLIT, ++ ++ /* add new commands above here */ ++ ++ __DEVLINK_CMD_MAX, ++ DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 ++}; ++ ++enum devlink_port_type { ++ DEVLINK_PORT_TYPE_NOTSET, ++ DEVLINK_PORT_TYPE_AUTO, ++ DEVLINK_PORT_TYPE_ETH, ++ DEVLINK_PORT_TYPE_IB, ++}; ++ ++enum devlink_attr { ++ /* don't change the order or add anything between, this is ABI! */ ++ DEVLINK_ATTR_UNSPEC, ++ ++ /* bus name + dev name together are a handle for devlink entity */ ++ DEVLINK_ATTR_BUS_NAME, /* string */ ++ DEVLINK_ATTR_DEV_NAME, /* string */ ++ ++ DEVLINK_ATTR_PORT_INDEX, /* u32 */ ++ DEVLINK_ATTR_PORT_TYPE, /* u16 */ ++ DEVLINK_ATTR_PORT_DESIRED_TYPE, /* u16 */ ++ DEVLINK_ATTR_PORT_NETDEV_IFINDEX, /* u32 */ ++ DEVLINK_ATTR_PORT_NETDEV_NAME, /* string */ ++ DEVLINK_ATTR_PORT_IBDEV_NAME, /* string */ ++ DEVLINK_ATTR_PORT_SPLIT_COUNT, /* u32 */ ++ DEVLINK_ATTR_PORT_SPLIT_GROUP, /* u32 */ ++ ++ /* add new attributes above here, update the policy in devlink.c */ ++ ++ __DEVLINK_ATTR_MAX, ++ DEVLINK_ATTR_MAX = __DEVLINK_ATTR_MAX - 1 ++}; ++ ++#endif /* _LINUX_DEVLINK_H_ */ +diff --git a/include/linux/genetlink.h b/include/linux/genetlink.h +index 8a1d500..e792092 100644 +--- a/include/linux/genetlink.h ++++ b/include/linux/genetlink.h +@@ -21,6 +21,7 @@ struct genlmsghdr { + #define GENL_CMD_CAP_DO 0x02 + #define GENL_CMD_CAP_DUMP 0x04 + #define GENL_CMD_CAP_HASPOL 0x08 ++#define GENL_UNS_ADMIN_PERM 0x10 + + /* + * List of reserved static generic netlink identifiers: +diff --git a/include/linux/if.h b/include/linux/if.h +index a55a9e0..5b84948 100644 +--- a/include/linux/if.h ++++ b/include/linux/if.h +@@ -19,14 +19,20 @@ + #ifndef _LINUX_IF_H + #define _LINUX_IF_H + ++#include <linux/libc-compat.h> /* for compatibility with glibc */ + #include <linux/types.h> /* for "__kernel_caddr_t" et al */ + #include <linux/socket.h> /* for "struct sockaddr" et al */ + /* for "__user" et al */ + ++#if __UAPI_DEF_IF_IFNAMSIZ + #define IFNAMSIZ 16 ++#endif /* __UAPI_DEF_IF_IFNAMSIZ */ + #define IFALIASZ 256 + #include <linux/hdlc/ioctl.h> + ++/* For glibc compatibility. An empty enum does not compile. */ ++#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 && \ ++ __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 + /** + * enum net_device_flags - &struct net_device flags + * +@@ -37,7 +43,7 @@ + * are shared for all types of net_devices. The sysfs entries are available + * via /sys/class/net/<dev>/flags. Flags which can be toggled through sysfs + * are annotated below, note that only a few flags can be toggled and some +- * other flags are always always preserved from the original net_device flags ++ * other flags are always preserved from the original net_device flags + * even if you try to set them via sysfs. Flags which are always preserved + * are kept under the flag grouping @IFF_VOLATILE. Flags which are __volatile__ + * are annotated below as such. +@@ -68,6 +74,8 @@ + * @IFF_ECHO: echo sent packets. Volatile. + */ + enum net_device_flags { ++/* for compatibility with glibc net/if.h */ ++#if __UAPI_DEF_IF_NET_DEVICE_FLAGS + IFF_UP = 1<<0, /* sysfs */ + IFF_BROADCAST = 1<<1, /* __volatile__ */ + IFF_DEBUG = 1<<2, /* sysfs */ +@@ -84,11 +92,17 @@ enum net_device_flags { + IFF_PORTSEL = 1<<13, /* sysfs */ + IFF_AUTOMEDIA = 1<<14, /* sysfs */ + IFF_DYNAMIC = 1<<15, /* sysfs */ ++#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */ ++#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO + IFF_LOWER_UP = 1<<16, /* __volatile__ */ + IFF_DORMANT = 1<<17, /* __volatile__ */ + IFF_ECHO = 1<<18, /* __volatile__ */ ++#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ + }; ++#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 && __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 */ + ++/* for compatibility with glibc net/if.h */ ++#if __UAPI_DEF_IF_NET_DEVICE_FLAGS + #define IFF_UP IFF_UP + #define IFF_BROADCAST IFF_BROADCAST + #define IFF_DEBUG IFF_DEBUG +@@ -105,9 +119,13 @@ enum net_device_flags { + #define IFF_PORTSEL IFF_PORTSEL + #define IFF_AUTOMEDIA IFF_AUTOMEDIA + #define IFF_DYNAMIC IFF_DYNAMIC ++#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */ ++ ++#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO + #define IFF_LOWER_UP IFF_LOWER_UP + #define IFF_DORMANT IFF_DORMANT + #define IFF_ECHO IFF_ECHO ++#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ + + #define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\ + IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT) +@@ -166,6 +184,8 @@ enum { + * being very small might be worth keeping for clean configuration. + */ + ++/* for compatibility with glibc net/if.h */ ++#if __UAPI_DEF_IF_IFMAP + struct ifmap { + unsigned long mem_start; + unsigned long mem_end; +@@ -175,6 +195,7 @@ struct ifmap { + unsigned char port; + /* 3 bytes spare */ + }; ++#endif /* __UAPI_DEF_IF_IFMAP */ + + struct if_settings { + unsigned int type; /* Type of physical device or protocol */ +@@ -200,6 +221,8 @@ struct if_settings { + * remainder may be interface specific. + */ + ++/* for compatibility with glibc net/if.h */ ++#if __UAPI_DEF_IF_IFREQ + struct ifreq { + #define IFHWADDRLEN 6 + union +@@ -223,6 +246,7 @@ struct ifreq { + struct if_settings ifru_settings; + } ifr_ifru; + }; ++#endif /* __UAPI_DEF_IF_IFREQ */ + + #define ifr_name ifr_ifrn.ifrn_name /* interface name */ + #define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +@@ -249,6 +273,8 @@ struct ifreq { + * must know all networks accessible). + */ + ++/* for compatibility with glibc net/if.h */ ++#if __UAPI_DEF_IF_IFCONF + struct ifconf { + int ifc_len; /* size of buffer */ + union { +@@ -256,6 +282,8 @@ struct ifconf { + struct ifreq *ifcu_req; + } ifc_ifcu; + }; ++#endif /* __UAPI_DEF_IF_IFCONF */ ++ + #define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ + #define ifc_req ifc_ifcu.ifcu_req /* array of structures */ + +diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h +index f24050b..8de96b7 100644 +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -127,6 +127,7 @@ enum { + #define BRIDGE_VLAN_INFO_UNTAGGED (1<<2) /* VLAN egresses untagged */ + #define BRIDGE_VLAN_INFO_RANGE_BEGIN (1<<3) /* VLAN is start of vlan range */ + #define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */ ++#define BRIDGE_VLAN_INFO_BRENTRY (1<<5) /* Global bridge VLAN entry */ + + struct bridge_vlan_info { + __u16 flags; +@@ -136,11 +137,17 @@ struct bridge_vlan_info { + /* Bridge multicast database attributes + * [MDBA_MDB] = { + * [MDBA_MDB_ENTRY] = { +- * [MDBA_MDB_ENTRY_INFO] ++ * [MDBA_MDB_ENTRY_INFO] { ++ * struct br_mdb_entry ++ * [MDBA_MDB_EATTR attributes] ++ * } + * } + * } + * [MDBA_ROUTER] = { +- * [MDBA_ROUTER_PORT] ++ * [MDBA_ROUTER_PORT] = { ++ * u32 ifindex ++ * [MDBA_ROUTER_PATTR attributes] ++ * } + * } + */ + enum { +@@ -165,6 +172,22 @@ enum { + }; + #define MDBA_MDB_ENTRY_MAX (__MDBA_MDB_ENTRY_MAX - 1) + ++/* per mdb entry additional attributes */ ++enum { ++ MDBA_MDB_EATTR_UNSPEC, ++ MDBA_MDB_EATTR_TIMER, ++ __MDBA_MDB_EATTR_MAX ++}; ++#define MDBA_MDB_EATTR_MAX (__MDBA_MDB_EATTR_MAX - 1) ++ ++/* multicast router types */ ++enum { ++ MDB_RTR_TYPE_DISABLED, ++ MDB_RTR_TYPE_TEMP_QUERY, ++ MDB_RTR_TYPE_PERM, ++ MDB_RTR_TYPE_TEMP ++}; ++ + enum { + MDBA_ROUTER_UNSPEC, + MDBA_ROUTER_PORT, +@@ -172,6 +195,15 @@ enum { + }; + #define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1) + ++/* router port attributes */ ++enum { ++ MDBA_ROUTER_PATTR_UNSPEC, ++ MDBA_ROUTER_PATTR_TIMER, ++ MDBA_ROUTER_PATTR_TYPE, ++ __MDBA_ROUTER_PATTR_MAX ++}; ++#define MDBA_ROUTER_PATTR_MAX (__MDBA_ROUTER_PATTR_MAX - 1) ++ + struct br_port_msg { + __u8 family; + __u32 ifindex; +@@ -182,6 +214,8 @@ struct br_mdb_entry { + #define MDB_TEMPORARY 0 + #define MDB_PERMANENT 1 + __u8 state; ++#define MDB_FLAGS_OFFLOAD (1 << 0) ++ __u8 flags; + __u16 vid; + struct { + union { +diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h +index bf278d6..8f3b0f4 100644 +--- a/include/linux/if_ether.h ++++ b/include/linux/if_ether.h +@@ -83,6 +83,7 @@ + #define ETH_P_8021AD 0x88A8 /* 802.1ad Service VLAN */ + #define ETH_P_802_EX1 0x88B5 /* 802.1 Local Experimental 1. */ + #define ETH_P_TIPC 0x88CA /* TIPC */ ++#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 */ + #define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */ +diff --git a/include/linux/if_link.h b/include/linux/if_link.h +index 73b5556..6a688e8 100644 +--- a/include/linux/if_link.h ++++ b/include/linux/if_link.h +@@ -35,6 +35,8 @@ struct rtnl_link_stats { + /* for cslip etc */ + __u32 rx_compressed; + __u32 tx_compressed; ++ ++ __u32 rx_nohandler; /* dropped, no handler found */ + }; + + /* The main device statistics structure */ +@@ -68,6 +70,8 @@ struct rtnl_link_stats64 { + /* for cslip etc */ + __u64 rx_compressed; + __u64 tx_compressed; ++ ++ __u64 rx_nohandler; /* dropped, no handler found */ + }; + + /* The struct should be in sync with struct ifmap */ +@@ -149,6 +153,8 @@ enum { + IFLA_LINK_NETNSID, + IFLA_PHYS_PORT_NAME, + IFLA_PROTO_DOWN, ++ IFLA_GSO_MAX_SEGS, ++ IFLA_GSO_MAX_SIZE, + __IFLA_MAX + }; + +@@ -216,6 +222,7 @@ enum in6_addr_gen_mode { + IN6_ADDR_GEN_MODE_EUI64, + IN6_ADDR_GEN_MODE_NONE, + IN6_ADDR_GEN_MODE_STABLE_PRIVACY, ++ IN6_ADDR_GEN_MODE_RANDOM, + }; + + /* Bridge section */ +@@ -230,11 +237,47 @@ enum { + IFLA_BR_PRIORITY, + IFLA_BR_VLAN_FILTERING, + IFLA_BR_VLAN_PROTOCOL, ++ IFLA_BR_GROUP_FWD_MASK, ++ IFLA_BR_ROOT_ID, ++ IFLA_BR_BRIDGE_ID, ++ IFLA_BR_ROOT_PORT, ++ IFLA_BR_ROOT_PATH_COST, ++ IFLA_BR_TOPOLOGY_CHANGE, ++ IFLA_BR_TOPOLOGY_CHANGE_DETECTED, ++ IFLA_BR_HELLO_TIMER, ++ IFLA_BR_TCN_TIMER, ++ IFLA_BR_TOPOLOGY_CHANGE_TIMER, ++ IFLA_BR_GC_TIMER, ++ IFLA_BR_GROUP_ADDR, ++ IFLA_BR_FDB_FLUSH, ++ IFLA_BR_MCAST_ROUTER, ++ IFLA_BR_MCAST_SNOOPING, ++ IFLA_BR_MCAST_QUERY_USE_IFADDR, ++ IFLA_BR_MCAST_QUERIER, ++ IFLA_BR_MCAST_HASH_ELASTICITY, ++ IFLA_BR_MCAST_HASH_MAX, ++ IFLA_BR_MCAST_LAST_MEMBER_CNT, ++ IFLA_BR_MCAST_STARTUP_QUERY_CNT, ++ IFLA_BR_MCAST_LAST_MEMBER_INTVL, ++ IFLA_BR_MCAST_MEMBERSHIP_INTVL, ++ IFLA_BR_MCAST_QUERIER_INTVL, ++ IFLA_BR_MCAST_QUERY_INTVL, ++ IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, ++ IFLA_BR_MCAST_STARTUP_QUERY_INTVL, ++ IFLA_BR_NF_CALL_IPTABLES, ++ IFLA_BR_NF_CALL_IP6TABLES, ++ IFLA_BR_NF_CALL_ARPTABLES, ++ IFLA_BR_VLAN_DEFAULT_PVID, + __IFLA_BR_MAX, + }; + + #define IFLA_BR_MAX (__IFLA_BR_MAX - 1) + ++struct ifla_bridge_id { ++ __u8 prio[2]; ++ __u8 addr[6]; /* ETH_ALEN */ ++}; ++ + enum { + BRIDGE_MODE_UNSPEC, + BRIDGE_MODE_HAIRPIN, +@@ -254,6 +297,19 @@ enum { + IFLA_BRPORT_PROXYARP, /* proxy ARP */ + IFLA_BRPORT_LEARNING_SYNC, /* mac learning sync from device */ + IFLA_BRPORT_PROXYARP_WIFI, /* proxy ARP for Wi-Fi */ ++ IFLA_BRPORT_ROOT_ID, /* designated root */ ++ IFLA_BRPORT_BRIDGE_ID, /* designated bridge */ ++ IFLA_BRPORT_DESIGNATED_PORT, ++ IFLA_BRPORT_DESIGNATED_COST, ++ IFLA_BRPORT_ID, ++ IFLA_BRPORT_NO, ++ IFLA_BRPORT_TOPOLOGY_CHANGE_ACK, ++ IFLA_BRPORT_CONFIG_PENDING, ++ IFLA_BRPORT_MESSAGE_AGE_TIMER, ++ IFLA_BRPORT_FORWARD_DELAY_TIMER, ++ IFLA_BRPORT_HOLD_TIMER, ++ IFLA_BRPORT_FLUSH, ++ IFLA_BRPORT_MULTICAST_ROUTER, + __IFLA_BRPORT_MAX + }; + #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) +@@ -349,6 +405,43 @@ enum { + + #define IFLA_VRF_MAX (__IFLA_VRF_MAX - 1) + ++enum { ++ IFLA_VRF_PORT_UNSPEC, ++ IFLA_VRF_PORT_TABLE, ++ __IFLA_VRF_PORT_MAX ++}; ++ ++#define IFLA_VRF_PORT_MAX (__IFLA_VRF_PORT_MAX - 1) ++ ++/* MACSEC section */ ++enum { ++ IFLA_MACSEC_UNSPEC, ++ IFLA_MACSEC_SCI, ++ IFLA_MACSEC_PORT, ++ IFLA_MACSEC_ICV_LEN, ++ IFLA_MACSEC_CIPHER_SUITE, ++ IFLA_MACSEC_WINDOW, ++ IFLA_MACSEC_ENCODING_SA, ++ IFLA_MACSEC_ENCRYPT, ++ IFLA_MACSEC_PROTECT, ++ IFLA_MACSEC_INC_SCI, ++ IFLA_MACSEC_ES, ++ IFLA_MACSEC_SCB, ++ IFLA_MACSEC_REPLAY_PROTECT, ++ IFLA_MACSEC_VALIDATION, ++ __IFLA_MACSEC_MAX, ++}; ++ ++#define IFLA_MACSEC_MAX (__IFLA_MACSEC_MAX - 1) ++ ++enum macsec_validation_type { ++ MACSEC_VALIDATE_DISABLED = 0, ++ MACSEC_VALIDATE_CHECK = 1, ++ MACSEC_VALIDATE_STRICT = 2, ++ __MACSEC_VALIDATE_END, ++ MACSEC_VALIDATE_MAX = __MACSEC_VALIDATE_END - 1, ++}; ++ + /* IPVLAN section */ + enum { + IFLA_IPVLAN_UNSPEC, +@@ -392,6 +485,7 @@ enum { + IFLA_VXLAN_GBP, + IFLA_VXLAN_REMCSUM_NOPARTIAL, + IFLA_VXLAN_COLLECT_METADATA, ++ IFLA_VXLAN_LABEL, + __IFLA_VXLAN_MAX + }; + #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) +@@ -505,6 +599,8 @@ enum { + */ + IFLA_VF_STATS, /* network device statistics */ + IFLA_VF_TRUST, /* Trust VF */ ++ IFLA_VF_IB_NODE_GUID, /* VF Infiniband node GUID */ ++ IFLA_VF_IB_PORT_GUID, /* VF Infiniband port GUID */ + __IFLA_VF_MAX, + }; + +@@ -537,6 +633,11 @@ struct ifla_vf_spoofchk { + __u32 setting; + }; + ++struct ifla_vf_guid { ++ __u32 vf; ++ __u64 guid; ++}; ++ + enum { + IFLA_VF_LINK_STATE_AUTO, /* link state of the uplink */ + IFLA_VF_LINK_STATE_ENABLE, /* link always up */ +diff --git a/include/linux/ila.h b/include/linux/ila.h +new file mode 100644 +index 0000000..4f9e1de +--- /dev/null ++++ b/include/linux/ila.h +@@ -0,0 +1,37 @@ ++/* ila.h - ILA Interface */ ++ ++#ifndef _LINUX_ILA_H ++#define _LINUX_ILA_H ++ ++/* NETLINK_GENERIC related info */ ++#define ILA_GENL_NAME "ila" ++#define ILA_GENL_VERSION 0x1 ++ ++enum { ++ ILA_ATTR_UNSPEC, ++ ILA_ATTR_LOCATOR, /* u64 */ ++ ILA_ATTR_IDENTIFIER, /* u64 */ ++ ILA_ATTR_LOCATOR_MATCH, /* u64 */ ++ ILA_ATTR_IFINDEX, /* s32 */ ++ ILA_ATTR_DIR, /* u32 */ ++ ++ __ILA_ATTR_MAX, ++}; ++ ++#define ILA_ATTR_MAX (__ILA_ATTR_MAX - 1) ++ ++enum { ++ ILA_CMD_UNSPEC, ++ ILA_CMD_ADD, ++ ILA_CMD_DEL, ++ ILA_CMD_GET, ++ ++ __ILA_CMD_MAX, ++}; ++ ++#define ILA_CMD_MAX (__ILA_CMD_MAX - 1) ++ ++#define ILA_DIR_IN (1 << 0) ++#define ILA_DIR_OUT (1 << 1) ++ ++#endif /* _LINUX_ILA_H */ +diff --git a/include/linux/in6.h b/include/linux/in6.h +index 994f4c2..aa5b66d 100644 +--- a/include/linux/in6.h ++++ b/include/linux/in6.h +@@ -196,6 +196,7 @@ struct in6_flowlabel_req { + + #define IPV6_IPSEC_POLICY 34 + #define IPV6_XFRM_POLICY 35 ++#define IPV6_HDRINCL 36 + #endif + + /* +diff --git a/include/linux/libc-compat.h b/include/linux/libc-compat.h +index 9bed5b6..b3c2085 100644 +--- a/include/linux/libc-compat.h ++++ b/include/linux/libc-compat.h +@@ -51,6 +51,40 @@ + /* We have included glibc headers... */ + #if defined(__GLIBC__) + ++/* Coordinate with glibc net/if.h header. */ ++#if defined(_NET_IF_H) ++ ++/* GLIBC headers included first so don't define anything ++ * that would already be defined. */ ++ ++#define __UAPI_DEF_IF_IFCONF 0 ++#define __UAPI_DEF_IF_IFMAP 0 ++#define __UAPI_DEF_IF_IFNAMSIZ 0 ++#define __UAPI_DEF_IF_IFREQ 0 ++/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0 ++/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ ++#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 ++#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ ++ ++#else /* _NET_IF_H */ ++ ++/* Linux headers included first, and we must define everything ++ * we need. The expectation is that glibc will check the ++ * __UAPI_DEF_* defines and adjust appropriately. */ ++ ++#define __UAPI_DEF_IF_IFCONF 1 ++#define __UAPI_DEF_IF_IFMAP 1 ++#define __UAPI_DEF_IF_IFNAMSIZ 1 ++#define __UAPI_DEF_IF_IFREQ 1 ++/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1 ++/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 ++ ++#endif /* _NET_IF_H */ ++ + /* Coordinate with glibc netinet/in.h header. */ + #if defined(_NETINET_IN_H) + +@@ -117,6 +151,16 @@ + * that we need. */ + #else /* !defined(__GLIBC__) */ + ++/* Definitions for if.h */ ++#define __UAPI_DEF_IF_IFCONF 1 ++#define __UAPI_DEF_IF_IFMAP 1 ++#define __UAPI_DEF_IF_IFNAMSIZ 1 ++#define __UAPI_DEF_IF_IFREQ 1 ++/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1 ++/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ ++#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 ++ + /* Definitions for in.h */ + #define __UAPI_DEF_IN_ADDR 1 + #define __UAPI_DEF_IN_IPPROTO 1 +diff --git a/include/linux/lwtunnel.h b/include/linux/lwtunnel.h +new file mode 100644 +index 0000000..1d2f4f6 +--- /dev/null ++++ b/include/linux/lwtunnel.h +@@ -0,0 +1,43 @@ ++#ifndef _LWTUNNEL_H_ ++#define _LWTUNNEL_H_ ++ ++#include <linux/types.h> ++ ++enum lwtunnel_encap_types { ++ LWTUNNEL_ENCAP_NONE, ++ LWTUNNEL_ENCAP_MPLS, ++ LWTUNNEL_ENCAP_IP, ++ LWTUNNEL_ENCAP_ILA, ++ LWTUNNEL_ENCAP_IP6, ++ __LWTUNNEL_ENCAP_MAX, ++}; ++ ++#define LWTUNNEL_ENCAP_MAX (__LWTUNNEL_ENCAP_MAX - 1) ++ ++enum lwtunnel_ip_t { ++ LWTUNNEL_IP_UNSPEC, ++ LWTUNNEL_IP_ID, ++ LWTUNNEL_IP_DST, ++ LWTUNNEL_IP_SRC, ++ LWTUNNEL_IP_TTL, ++ LWTUNNEL_IP_TOS, ++ LWTUNNEL_IP_FLAGS, ++ __LWTUNNEL_IP_MAX, ++}; ++ ++#define LWTUNNEL_IP_MAX (__LWTUNNEL_IP_MAX - 1) ++ ++enum lwtunnel_ip6_t { ++ LWTUNNEL_IP6_UNSPEC, ++ LWTUNNEL_IP6_ID, ++ LWTUNNEL_IP6_DST, ++ LWTUNNEL_IP6_SRC, ++ LWTUNNEL_IP6_HOPLIMIT, ++ LWTUNNEL_IP6_TC, ++ LWTUNNEL_IP6_FLAGS, ++ __LWTUNNEL_IP6_MAX, ++}; ++ ++#define LWTUNNEL_IP6_MAX (__LWTUNNEL_IP6_MAX - 1) ++ ++#endif /* _LWTUNNEL_H_ */ +diff --git a/include/linux/mpls_iptunnel.h b/include/linux/mpls_iptunnel.h +new file mode 100644 +index 0000000..4132c3c +--- /dev/null ++++ b/include/linux/mpls_iptunnel.h +@@ -0,0 +1,28 @@ ++/* ++ * mpls tunnel api ++ * ++ * Authors: ++ * Roopa Prabhu <roopa@cumulusnetworks.com> ++ * ++ * 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_MPLS_IPTUNNEL_H ++#define _LINUX_MPLS_IPTUNNEL_H ++ ++/* MPLS tunnel attributes ++ * [RTA_ENCAP] = { ++ * [MPLS_IPTUNNEL_DST] ++ * } ++ */ ++enum { ++ MPLS_IPTUNNEL_UNSPEC, ++ MPLS_IPTUNNEL_DST, ++ __MPLS_IPTUNNEL_MAX, ++}; ++#define MPLS_IPTUNNEL_MAX (__MPLS_IPTUNNEL_MAX - 1) ++ ++#endif /* _LINUX_MPLS_IPTUNNEL_H */ +diff --git a/include/linux/netconf.h b/include/linux/netconf.h +index 7210fe4..70306a8 100644 +--- a/include/linux/netconf.h ++++ b/include/linux/netconf.h +@@ -19,6 +19,7 @@ enum { + __NETCONFA_MAX + }; + #define NETCONFA_MAX (__NETCONFA_MAX - 1) ++#define NETCONFA_ALL -1 + + #define NETCONFA_IFINDEX_ALL -1 + #define NETCONFA_IFINDEX_DEFAULT -2 +diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h +index 38542b4..456fb86 100644 +--- a/include/linux/netfilter_ipv4/ip_tables.h ++++ b/include/linux/netfilter_ipv4/ip_tables.h +@@ -17,6 +17,7 @@ + + #include <linux/types.h> + ++#include <linux/if.h> + #include <linux/netfilter_ipv4.h> + + #include <linux/netfilter/x_tables.h> +diff --git a/include/linux/netlink.h b/include/linux/netlink.h +index 352b5b8..8a7ca5c 100644 +--- a/include/linux/netlink.h ++++ b/include/linux/netlink.h +@@ -54,6 +54,7 @@ struct nlmsghdr { + #define NLM_F_ACK 4 /* Reply with ack, with zero or error code */ + #define NLM_F_ECHO 8 /* Echo this request */ + #define NLM_F_DUMP_INTR 16 /* Dump was inconsistent due to sequence change */ ++#define NLM_F_DUMP_FILTERED 32 /* Dump was filtered as requested */ + + /* Modifiers to GET request */ + #define NLM_F_ROOT 0x100 /* specify tree root */ +diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h +index 25af89f..b69358b 100644 +--- a/include/linux/pkt_cls.h ++++ b/include/linux/pkt_cls.h +@@ -33,6 +33,7 @@ enum { + #define TC_ACT_STOLEN 4 + #define TC_ACT_QUEUED 5 + #define TC_ACT_REPEAT 6 ++#define TC_ACT_REDIRECT 7 + #define TC_ACT_JUMP 0x10000000 + + /* Action type identifiers*/ +@@ -117,6 +118,7 @@ enum { + TCA_U32_INDEV, + TCA_U32_PCNT, + TCA_U32_MARK, ++ TCA_U32_FLAGS, + __TCA_U32_MAX + }; + +@@ -319,6 +321,8 @@ enum { + + /* BPF classifier */ + ++#define TCA_BPF_FLAG_ACT_DIRECT (1 << 0) ++ + enum { + TCA_BPF_UNSPEC, + TCA_BPF_ACT, +@@ -328,6 +332,7 @@ enum { + TCA_BPF_OPS, + TCA_BPF_FD, + TCA_BPF_NAME, ++ TCA_BPF_FLAGS, + __TCA_BPF_MAX, + }; + +@@ -358,6 +363,8 @@ enum { + TCA_FLOWER_KEY_TCP_DST, /* be16 */ + TCA_FLOWER_KEY_UDP_SRC, /* be16 */ + TCA_FLOWER_KEY_UDP_DST, /* be16 */ ++ ++ TCA_FLOWER_FLAGS, + __TCA_FLOWER_MAX, + }; + +diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h +index 8d2530d..8cb18b4 100644 +--- a/include/linux/pkt_sched.h ++++ b/include/linux/pkt_sched.h +@@ -72,6 +72,10 @@ struct tc_estimator { + #define TC_H_UNSPEC (0U) + #define TC_H_ROOT (0xFFFFFFFFU) + #define TC_H_INGRESS (0xFFFFFFF1U) ++#define TC_H_CLSACT TC_H_INGRESS ++ ++#define TC_H_MIN_INGRESS 0xFFF2U ++#define TC_H_MIN_EGRESS 0xFFF3U + + /* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */ + enum tc_link_layer { +diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h +index 3244947..6aaa2a3 100644 +--- a/include/linux/rtnetlink.h ++++ b/include/linux/rtnetlink.h +@@ -270,6 +270,7 @@ enum rt_scope_t { + #define RTM_F_CLONED 0x200 /* This route is cloned */ + #define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */ + #define RTM_F_PREFIX 0x800 /* Prefix addresses */ ++#define RTM_F_LOOKUP_TABLE 0x1000 /* set rtm_table to FIB lookup result */ + + /* Reserved table identifiers */ + +@@ -310,6 +311,7 @@ enum rtattr_type_t { + RTA_PREF, + RTA_ENCAP_TYPE, + RTA_ENCAP, ++ RTA_EXPIRES, + __RTA_MAX + }; + +@@ -664,6 +666,7 @@ struct tcamsg { + #define RTEXT_FILTER_VF (1 << 0) + #define RTEXT_FILTER_BRVLAN (1 << 1) + #define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2) ++#define RTEXT_FILTER_SKIP_STATS (1 << 3) + + /* End of information exported to user level */ + +diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h +index 024e1f4..dafcb89 100644 +--- a/include/linux/sock_diag.h ++++ b/include/linux/sock_diag.h +@@ -4,6 +4,7 @@ + #include <linux/types.h> + + #define SOCK_DIAG_BY_FAMILY 20 ++#define SOCK_DESTROY 21 + + struct sock_diag_req { + __u8 sdiag_family; +diff --git a/include/linux/tc_act/tc_ife.h b/include/linux/tc_act/tc_ife.h +new file mode 100644 +index 0000000..d648ff6 +--- /dev/null ++++ b/include/linux/tc_act/tc_ife.h +@@ -0,0 +1,38 @@ ++#ifndef __UAPI_TC_IFE_H ++#define __UAPI_TC_IFE_H ++ ++#include <linux/types.h> ++#include <linux/pkt_cls.h> ++ ++#define TCA_ACT_IFE 25 ++/* Flag bits for now just encoding/decoding; mutually exclusive */ ++#define IFE_ENCODE 1 ++#define IFE_DECODE 0 ++ ++struct tc_ife { ++ tc_gen; ++ __u16 flags; ++}; ++ ++/*XXX: We need to encode the total number of bytes consumed */ ++enum { ++ TCA_IFE_UNSPEC, ++ TCA_IFE_PARMS, ++ TCA_IFE_TM, ++ TCA_IFE_DMAC, ++ TCA_IFE_SMAC, ++ TCA_IFE_TYPE, ++ TCA_IFE_METALST, ++ __TCA_IFE_MAX ++}; ++#define TCA_IFE_MAX (__TCA_IFE_MAX - 1) ++ ++#define IFE_META_SKBMARK 1 ++#define IFE_META_HASHID 2 ++#define IFE_META_PRIO 3 ++#define IFE_META_QMAP 4 ++/*Can be overridden at runtime by module option*/ ++#define __IFE_META_MAX 5 ++#define IFE_META_MAX (__IFE_META_MAX - 1) ++ ++#endif +diff --git a/include/linux/tcp.h b/include/linux/tcp.h +index 1e9b4a6..7f21db9 100644 +--- a/include/linux/tcp.h ++++ b/include/linux/tcp.h +@@ -196,6 +196,11 @@ struct tcp_info { + __u64 tcpi_bytes_received; /* RFC4898 tcpEStatsAppHCThruOctetsReceived */ + __u32 tcpi_segs_out; /* RFC4898 tcpEStatsPerfSegsOut */ + __u32 tcpi_segs_in; /* RFC4898 tcpEStatsPerfSegsIn */ ++ ++ __u32 tcpi_notsent_bytes; ++ __u32 tcpi_min_rtt; ++ __u32 tcpi_data_segs_in; /* RFC4898 tcpEStatsDataSegsIn */ ++ __u32 tcpi_data_segs_out; /* RFC4898 tcpEStatsDataSegsOut */ + }; + + /* for TCP_MD5SIG socket option */ +-- +1.8.3.1 + diff --git a/SOURCES/0179-add-if_macsec-header.patch b/SOURCES/0179-add-if_macsec-header.patch new file mode 100644 index 0000000..c0236b0 --- /dev/null +++ b/SOURCES/0179-add-if_macsec-header.patch @@ -0,0 +1,200 @@ +From a55fc510ebab810aa67dcf62191eec4c4b83b472 Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 6 Jul 2016 18:41:39 +0200 +Subject: [PATCH] add if_macsec header + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1300765 +Upstream Status: iproute2.git commit 5c33c9592412 + +commit 5c33c9592412216eec32d3a8b1c21c03311c79fc +Author: Stephen Hemminger <shemming@brocade.com> +Date: Mon May 23 16:10:43 2016 -0700 + + add if_macsec header + + Current version from 4.7-pre-rc1 + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + include/linux/if_macsec.h | 169 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 169 insertions(+) + create mode 100644 include/linux/if_macsec.h + +diff --git a/include/linux/if_macsec.h b/include/linux/if_macsec.h +new file mode 100644 +index 0000000..cbd4faa +--- /dev/null ++++ b/include/linux/if_macsec.h +@@ -0,0 +1,169 @@ ++/* ++ * include/uapi/linux/if_macsec.h - MACsec device ++ * ++ * Copyright (c) 2015 Sabrina Dubroca <sd@queasysnail.net> ++ * ++ * 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 _MACSEC_H ++#define _MACSEC_H ++ ++#include <linux/types.h> ++ ++#define MACSEC_GENL_NAME "macsec" ++#define MACSEC_GENL_VERSION 1 ++ ++#define MACSEC_MAX_KEY_LEN 128 ++ ++#define MACSEC_KEYID_LEN 16 ++ ++#define MACSEC_DEFAULT_CIPHER_ID 0x0080020001000001ULL ++#define MACSEC_DEFAULT_CIPHER_ALT 0x0080C20001000001ULL ++ ++#define MACSEC_MIN_ICV_LEN 8 ++#define MACSEC_MAX_ICV_LEN 32 ++ ++enum macsec_attrs { ++ MACSEC_ATTR_UNSPEC, ++ MACSEC_ATTR_IFINDEX, /* u32, ifindex of the MACsec netdevice */ ++ MACSEC_ATTR_RXSC_CONFIG, /* config, nested macsec_rxsc_attrs */ ++ MACSEC_ATTR_SA_CONFIG, /* config, nested macsec_sa_attrs */ ++ MACSEC_ATTR_SECY, /* dump, nested macsec_secy_attrs */ ++ MACSEC_ATTR_TXSA_LIST, /* dump, nested, macsec_sa_attrs for each TXSA */ ++ MACSEC_ATTR_RXSC_LIST, /* dump, nested, macsec_rxsc_attrs for each RXSC */ ++ MACSEC_ATTR_TXSC_STATS, /* dump, nested, macsec_txsc_stats_attr */ ++ MACSEC_ATTR_SECY_STATS, /* dump, nested, macsec_secy_stats_attr */ ++ __MACSEC_ATTR_END, ++ NUM_MACSEC_ATTR = __MACSEC_ATTR_END, ++ MACSEC_ATTR_MAX = __MACSEC_ATTR_END - 1, ++}; ++ ++enum macsec_secy_attrs { ++ MACSEC_SECY_ATTR_UNSPEC, ++ MACSEC_SECY_ATTR_SCI, ++ MACSEC_SECY_ATTR_ENCODING_SA, ++ MACSEC_SECY_ATTR_WINDOW, ++ MACSEC_SECY_ATTR_CIPHER_SUITE, ++ MACSEC_SECY_ATTR_ICV_LEN, ++ MACSEC_SECY_ATTR_PROTECT, ++ MACSEC_SECY_ATTR_REPLAY, ++ MACSEC_SECY_ATTR_OPER, ++ MACSEC_SECY_ATTR_VALIDATE, ++ MACSEC_SECY_ATTR_ENCRYPT, ++ MACSEC_SECY_ATTR_INC_SCI, ++ MACSEC_SECY_ATTR_ES, ++ MACSEC_SECY_ATTR_SCB, ++ MACSEC_SECY_ATTR_PAD, ++ __MACSEC_SECY_ATTR_END, ++ NUM_MACSEC_SECY_ATTR = __MACSEC_SECY_ATTR_END, ++ MACSEC_SECY_ATTR_MAX = __MACSEC_SECY_ATTR_END - 1, ++}; ++ ++enum macsec_rxsc_attrs { ++ MACSEC_RXSC_ATTR_UNSPEC, ++ MACSEC_RXSC_ATTR_SCI, /* config/dump, u64 */ ++ MACSEC_RXSC_ATTR_ACTIVE, /* config/dump, u8 0..1 */ ++ MACSEC_RXSC_ATTR_SA_LIST, /* dump, nested */ ++ MACSEC_RXSC_ATTR_STATS, /* dump, nested, macsec_rxsc_stats_attr */ ++ MACSEC_RXSC_ATTR_PAD, ++ __MACSEC_RXSC_ATTR_END, ++ NUM_MACSEC_RXSC_ATTR = __MACSEC_RXSC_ATTR_END, ++ MACSEC_RXSC_ATTR_MAX = __MACSEC_RXSC_ATTR_END - 1, ++}; ++ ++enum macsec_sa_attrs { ++ MACSEC_SA_ATTR_UNSPEC, ++ MACSEC_SA_ATTR_AN, /* config/dump, u8 0..3 */ ++ MACSEC_SA_ATTR_ACTIVE, /* config/dump, u8 0..1 */ ++ MACSEC_SA_ATTR_PN, /* config/dump, u32 */ ++ MACSEC_SA_ATTR_KEY, /* config, data */ ++ MACSEC_SA_ATTR_KEYID, /* config/dump, 128-bit */ ++ MACSEC_SA_ATTR_STATS, /* dump, nested, macsec_sa_stats_attr */ ++ MACSEC_SA_ATTR_PAD, ++ __MACSEC_SA_ATTR_END, ++ NUM_MACSEC_SA_ATTR = __MACSEC_SA_ATTR_END, ++ MACSEC_SA_ATTR_MAX = __MACSEC_SA_ATTR_END - 1, ++}; ++ ++enum macsec_nl_commands { ++ MACSEC_CMD_GET_TXSC, ++ MACSEC_CMD_ADD_RXSC, ++ MACSEC_CMD_DEL_RXSC, ++ MACSEC_CMD_UPD_RXSC, ++ MACSEC_CMD_ADD_TXSA, ++ MACSEC_CMD_DEL_TXSA, ++ MACSEC_CMD_UPD_TXSA, ++ MACSEC_CMD_ADD_RXSA, ++ MACSEC_CMD_DEL_RXSA, ++ MACSEC_CMD_UPD_RXSA, ++}; ++ ++/* u64 per-RXSC stats */ ++enum macsec_rxsc_stats_attr { ++ MACSEC_RXSC_STATS_ATTR_UNSPEC, ++ MACSEC_RXSC_STATS_ATTR_IN_OCTETS_VALIDATED, ++ MACSEC_RXSC_STATS_ATTR_IN_OCTETS_DECRYPTED, ++ MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNCHECKED, ++ MACSEC_RXSC_STATS_ATTR_IN_PKTS_DELAYED, ++ MACSEC_RXSC_STATS_ATTR_IN_PKTS_OK, ++ MACSEC_RXSC_STATS_ATTR_IN_PKTS_INVALID, ++ MACSEC_RXSC_STATS_ATTR_IN_PKTS_LATE, ++ MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_VALID, ++ MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_USING_SA, ++ MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNUSED_SA, ++ MACSEC_RXSC_STATS_ATTR_PAD, ++ __MACSEC_RXSC_STATS_ATTR_END, ++ NUM_MACSEC_RXSC_STATS_ATTR = __MACSEC_RXSC_STATS_ATTR_END, ++ MACSEC_RXSC_STATS_ATTR_MAX = __MACSEC_RXSC_STATS_ATTR_END - 1, ++}; ++ ++/* u32 per-{RX,TX}SA stats */ ++enum macsec_sa_stats_attr { ++ MACSEC_SA_STATS_ATTR_UNSPEC, ++ MACSEC_SA_STATS_ATTR_IN_PKTS_OK, ++ MACSEC_SA_STATS_ATTR_IN_PKTS_INVALID, ++ MACSEC_SA_STATS_ATTR_IN_PKTS_NOT_VALID, ++ MACSEC_SA_STATS_ATTR_IN_PKTS_NOT_USING_SA, ++ MACSEC_SA_STATS_ATTR_IN_PKTS_UNUSED_SA, ++ MACSEC_SA_STATS_ATTR_OUT_PKTS_PROTECTED, ++ MACSEC_SA_STATS_ATTR_OUT_PKTS_ENCRYPTED, ++ __MACSEC_SA_STATS_ATTR_END, ++ NUM_MACSEC_SA_STATS_ATTR = __MACSEC_SA_STATS_ATTR_END, ++ MACSEC_SA_STATS_ATTR_MAX = __MACSEC_SA_STATS_ATTR_END - 1, ++}; ++ ++/* u64 per-TXSC stats */ ++enum macsec_txsc_stats_attr { ++ MACSEC_TXSC_STATS_ATTR_UNSPEC, ++ MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED, ++ MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED, ++ MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_PROTECTED, ++ MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_ENCRYPTED, ++ MACSEC_TXSC_STATS_ATTR_PAD, ++ __MACSEC_TXSC_STATS_ATTR_END, ++ NUM_MACSEC_TXSC_STATS_ATTR = __MACSEC_TXSC_STATS_ATTR_END, ++ MACSEC_TXSC_STATS_ATTR_MAX = __MACSEC_TXSC_STATS_ATTR_END - 1, ++}; ++ ++/* u64 per-SecY stats */ ++enum macsec_secy_stats_attr { ++ MACSEC_SECY_STATS_ATTR_UNSPEC, ++ MACSEC_SECY_STATS_ATTR_OUT_PKTS_UNTAGGED, ++ MACSEC_SECY_STATS_ATTR_IN_PKTS_UNTAGGED, ++ MACSEC_SECY_STATS_ATTR_OUT_PKTS_TOO_LONG, ++ MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_TAG, ++ MACSEC_SECY_STATS_ATTR_IN_PKTS_BAD_TAG, ++ MACSEC_SECY_STATS_ATTR_IN_PKTS_UNKNOWN_SCI, ++ MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_SCI, ++ MACSEC_SECY_STATS_ATTR_IN_PKTS_OVERRUN, ++ MACSEC_SECY_STATS_ATTR_PAD, ++ __MACSEC_SECY_STATS_ATTR_END, ++ NUM_MACSEC_SECY_STATS_ATTR = __MACSEC_SECY_STATS_ATTR_END, ++ MACSEC_SECY_STATS_ATTR_MAX = __MACSEC_SECY_STATS_ATTR_END - 1, ++}; ++ ++#endif /* _MACSEC_H */ +-- +1.8.3.1 + diff --git a/SOURCES/0180-configure-Add-check-for-the-doc-tools.patch b/SOURCES/0180-configure-Add-check-for-the-doc-tools.patch new file mode 100644 index 0000000..8a3c390 --- /dev/null +++ b/SOURCES/0180-configure-Add-check-for-the-doc-tools.patch @@ -0,0 +1,85 @@ +From 1ded94f66819e69ddf8a3e68924d978873ac400e Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:29:56 +0200 +Subject: [PATCH] configure: Add check for the doc tools + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit 10ed8b7f67513 + +commit 10ed8b7f6751305c78596bd5b8732bfccbd69e21 +Author: vadimk <vadim4j@gmail.com> +Date: Sun Nov 30 18:08:25 2014 +0200 + + configure: Add check for the doc tools + + Added checking existence of the doc files converters. + If the XXX tool exists then HAVE_XXX:=y will be written + to the Config file. Example of the configure script output: + + TC schedulers + ATM no + IPT using xtables + IPSET yes + + iptables modules directory: /usr/lib/iptables + libc has setns: yes + SELinux support: no + + Docs + latex: no + WARNING: no docs can be built from LaTeX files + sgml2html: yes + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> +--- + configure | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/configure b/configure +index d5170f0..c3dacdb 100755 +--- a/configure ++++ b/configure +@@ -7,6 +7,24 @@ INCLUDE=${1:-"$PWD/include"} + TMPDIR=$(mktemp -d config.XXXXXX) + trap 'status=$?; rm -rf $TMPDIR; exit $status' EXIT HUP INT QUIT TERM + ++check_prog() ++{ ++ echo -n "$2" ++ command -v $1 >/dev/null 2>&1 && (echo "$3:=y" >> Config; echo "yes") || (echo "no"; return 1) ++} ++ ++check_docs() ++{ ++ if check_prog latex " latex: " HAVE_LATEX; then ++ check_prog pdflatex " pdflatex: " HAVE_PDFLATEX || echo " WARNING: no PDF docs can be built from LaTeX files" ++ check_prog sgml2latex " sgml2latex: " HAVE_SGML2LATEX || echo " WARNING: no LaTeX files can be build from SGML files" ++ else ++ echo " WARNING: no docs can be built from LaTeX files" ++ fi ++ ++ check_prog sgml2html " sgml2html: " HAVE_SGML2HTML || echo " WARNING: no HTML docs can be built from SGML" ++} ++ + check_toolchain() + { + : ${PKG_CONFIG:=pkg-config} +@@ -260,7 +278,7 @@ check_ipt + echo -n " IPSET " + check_ipset + +-echo -n "iptables modules directory: " ++echo -n -e "\niptables modules directory: " + check_ipt_lib_dir + + echo -n "libc has setns: " +@@ -268,3 +286,6 @@ check_setns + + echo -n "SELinux support: " + check_selinux ++ ++echo -e "\nDocs" ++check_docs +-- +1.8.3.1 + diff --git a/SOURCES/0181-configure-Check-for-libmnl.patch b/SOURCES/0181-configure-Check-for-libmnl.patch new file mode 100644 index 0000000..340e574 --- /dev/null +++ b/SOURCES/0181-configure-Check-for-libmnl.patch @@ -0,0 +1,59 @@ +From f827299674966fbd0cbc13a243323f8ea7fbcc8d Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:29:56 +0200 +Subject: [PATCH] configure: Check for libmnl + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit b6907403efd9d +Conflicts: Context changes due to missing commit + 11c39b5e98a16 ("tc: add eBPF support to f_bpf"). + +commit b6907403efd9d64ed5a140d3bc6e23773452bef9 +Author: Vadim Kochan <vadim4j@gmail.com> +Date: Fri May 29 13:27:41 2015 +0300 + + configure: Check for libmnl + + Indicate existence of libmnl which is required by tipc. + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> +--- + configure | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/configure b/configure +index c3dacdb..b270ace 100755 +--- a/configure ++++ b/configure +@@ -261,6 +261,17 @@ check_selinux() + fi + } + ++check_mnl() ++{ ++ if ${PKG_CONFIG} libmnl --exists ++ then ++ echo "HAVE_MNL:=y" >>Config ++ echo -n "yes" ++ else ++ echo -n "no" ++ fi ++} ++ + echo "# Generated config based on" $INCLUDE >Config + check_toolchain + +@@ -287,5 +298,10 @@ check_setns + echo -n "SELinux support: " + check_selinux + ++echo -n "libmnl support: " ++check_mnl ++echo " (required by tipc)" ++ + echo -e "\nDocs" + check_docs ++echo "" +-- +1.8.3.1 + diff --git a/SOURCES/0182-configure-cleanup.patch b/SOURCES/0182-configure-cleanup.patch new file mode 100644 index 0000000..5a80b89 --- /dev/null +++ b/SOURCES/0182-configure-cleanup.patch @@ -0,0 +1,48 @@ +From b0c8d9f05f7241b3c8ea8ecc92853109a4fa9762 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:30:52 +0200 +Subject: [PATCH] configure: cleanup + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit aaf70458028a2 + +commit aaf70458028a243f0d60bbe82b787bdb1f3b9a31 +Author: Stephen Hemminger <shemming@brocade.com> +Date: Thu Jun 25 15:10:22 2015 -0400 + + configure: cleanup + + Don't echo "-e" when using builtin echo in bash. +--- + configure | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/configure b/configure +index b270ace..6672277 100755 +--- a/configure ++++ b/configure +@@ -289,7 +289,8 @@ check_ipt + echo -n " IPSET " + check_ipset + +-echo -n -e "\niptables modules directory: " ++echo ++echo -n "iptables modules directory: " + check_ipt_lib_dir + + echo -n "libc has setns: " +@@ -300,8 +301,8 @@ check_selinux + + echo -n "libmnl support: " + check_mnl +-echo " (required by tipc)" + +-echo -e "\nDocs" ++echo ++echo -n "docs:" + check_docs +-echo "" ++echo +-- +1.8.3.1 + diff --git a/SOURCES/0183-include-add-linked-list-implementation-from-kernel.patch b/SOURCES/0183-include-add-linked-list-implementation-from-kernel.patch new file mode 100644 index 0000000..89981f1 --- /dev/null +++ b/SOURCES/0183-include-add-linked-list-implementation-from-kernel.patch @@ -0,0 +1,237 @@ +From 48a71ae76f5b7535f787a34b34162c2235550261 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:31:01 +0200 +Subject: [PATCH] include: add linked list implementation from kernel + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit 4952b45946d73 +Conflicts: Dropped changes in tc/tc_class.c since commit d954b34a1f8d8 + ("tc class: Show classes as ASCII graph") is missing. + +commit 4952b45946d73a4e5dd673928cf50327251de1de +Author: Jiri Pirko <jiri@mellanox.com> +Date: Tue Mar 22 10:02:20 2016 +0100 + + include: add linked list implementation from kernel + + Rename hlist.h to list.h while adding it to be aligned with kernel + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + include/hlist.h | 56 ---------------------------- + include/list.h | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ip/ipnetns.c | 2 +- + lib/ll_map.c | 2 +- + 4 files changed, 114 insertions(+), 58 deletions(-) + delete mode 100644 include/hlist.h + create mode 100644 include/list.h + +diff --git a/include/hlist.h b/include/hlist.h +deleted file mode 100644 +index 4e8de9e..0000000 +--- a/include/hlist.h ++++ /dev/null +@@ -1,56 +0,0 @@ +-#ifndef __HLIST_H__ +-#define __HLIST_H__ 1 +-/* Hash list stuff from kernel */ +- +-#include <stddef.h> +- +-#define container_of(ptr, type, member) ({ \ +- const typeof( ((type *)0)->member ) *__mptr = (ptr); \ +- (type *)( (char *)__mptr - offsetof(type,member) );}) +- +-struct hlist_head { +- struct hlist_node *first; +-}; +- +-struct hlist_node { +- struct hlist_node *next, **pprev; +-}; +- +-static inline void hlist_del(struct hlist_node *n) +-{ +- struct hlist_node *next = n->next; +- struct hlist_node **pprev = n->pprev; +- *pprev = next; +- if (next) +- next->pprev = pprev; +-} +- +-static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +-{ +- struct hlist_node *first = h->first; +- n->next = first; +- if (first) +- first->pprev = &n->next; +- h->first = n; +- n->pprev = &h->first; +-} +- +-#define hlist_for_each(pos, head) \ +- for (pos = (head)->first; pos ; pos = pos->next) +- +- +-#define hlist_for_each_safe(pos, n, head) \ +- for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ +- pos = n) +- +-#define hlist_entry_safe(ptr, type, member) \ +- ({ typeof(ptr) ____ptr = (ptr); \ +- ____ptr ? hlist_entry(____ptr, type, member) : NULL; \ +- }) +- +-#define hlist_for_each_entry(pos, head, member) \ +- for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\ +- pos; \ +- pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) +- +-#endif /* __HLIST_H__ */ +diff --git a/include/list.h b/include/list.h +new file mode 100644 +index 0000000..cdebe4d +--- /dev/null ++++ b/include/list.h +@@ -0,0 +1,112 @@ ++#ifndef __LIST_H__ ++#define __LIST_H__ 1 ++/* List and hash list stuff from kernel */ ++ ++#include <stddef.h> ++ ++#define container_of(ptr, type, member) ({ \ ++ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ ++ (type *)( (char *)__mptr - offsetof(type,member) );}) ++ ++struct list_head { ++ struct list_head *next, *prev; ++}; ++ ++static inline void INIT_LIST_HEAD(struct list_head *list) ++{ ++ list->next = list; ++ list->prev = list; ++} ++ ++static inline void __list_add(struct list_head *new, ++ struct list_head *prev, ++ struct list_head *next) ++{ ++ next->prev = new; ++ new->next = next; ++ new->prev = prev; ++ prev->next = new; ++} ++ ++static inline void list_add(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head, head->next); ++} ++ ++static inline void __list_del(struct list_head *prev, struct list_head *next) ++{ ++ next->prev = prev; ++ prev->next = next; ++} ++ ++static inline void list_del(struct list_head *entry) ++{ ++ __list_del(entry->prev, entry->next); ++} ++ ++#define list_entry(ptr, type, member) \ ++ container_of(ptr, type, member) ++ ++#define list_first_entry(ptr, type, member) \ ++ list_entry((ptr)->next, type, member) ++ ++#define list_next_entry(pos, member) \ ++ list_entry((pos)->member.next, typeof(*(pos)), member) ++ ++#define list_for_each_entry(pos, head, member) \ ++ for (pos = list_first_entry(head, typeof(*pos), member); \ ++ &pos->member != (head); \ ++ pos = list_next_entry(pos, member)) ++ ++#define list_for_each_entry_safe(pos, n, head, member) \ ++ for (pos = list_first_entry(head, typeof(*pos), member), \ ++ n = list_next_entry(pos, member); \ ++ &pos->member != (head); \ ++ pos = n, n = list_next_entry(n, member)) ++ ++struct hlist_head { ++ struct hlist_node *first; ++}; ++ ++struct hlist_node { ++ struct hlist_node *next, **pprev; ++}; ++ ++static inline void hlist_del(struct hlist_node *n) ++{ ++ struct hlist_node *next = n->next; ++ struct hlist_node **pprev = n->pprev; ++ *pprev = next; ++ if (next) ++ next->pprev = pprev; ++} ++ ++static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) ++{ ++ struct hlist_node *first = h->first; ++ n->next = first; ++ if (first) ++ first->pprev = &n->next; ++ h->first = n; ++ n->pprev = &h->first; ++} ++ ++#define hlist_for_each(pos, head) \ ++ for (pos = (head)->first; pos ; pos = pos->next) ++ ++ ++#define hlist_for_each_safe(pos, n, head) \ ++ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ ++ pos = n) ++ ++#define hlist_entry_safe(ptr, type, member) \ ++ ({ typeof(ptr) ____ptr = (ptr); \ ++ ____ptr ? hlist_entry(____ptr, type, member) : NULL; \ ++ }) ++ ++#define hlist_for_each_entry(pos, head, member) \ ++ for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\ ++ pos; \ ++ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) ++ ++#endif /* __LIST_H__ */ +diff --git a/ip/ipnetns.c b/ip/ipnetns.c +index 2c848bc..ef05ff3 100644 +--- a/ip/ipnetns.c ++++ b/ip/ipnetns.c +@@ -19,7 +19,7 @@ + #include <linux/net_namespace.h> + + #include "utils.h" +-#include "hlist.h" ++#include "list.h" + #include "ip_common.h" + #include "namespace.h" + +diff --git a/lib/ll_map.c b/lib/ll_map.c +index c6f7027..fa14a77 100644 +--- a/lib/ll_map.c ++++ b/lib/ll_map.c +@@ -22,7 +22,7 @@ + + #include "libnetlink.h" + #include "ll_map.h" +-#include "hlist.h" ++#include "list.h" + + struct ll_cache { + struct hlist_node idx_hash; +-- +1.8.3.1 + diff --git a/SOURCES/0184-add-devlink-tool.patch b/SOURCES/0184-add-devlink-tool.patch new file mode 100644 index 0000000..9a6dbda --- /dev/null +++ b/SOURCES/0184-add-devlink-tool.patch @@ -0,0 +1,1713 @@ +From f6e5ebe6d481c6785c7b6b8b9888620087669a1c Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:32:36 +0200 +Subject: [PATCH] add devlink tool + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit a3c4b484a1edd +Conflicts: Context changed due to missing tipc utility. + +commit a3c4b484a1eddc87fbb66812a2453d840bc89f35 +Author: Jiri Pirko <jiri@mellanox.com> +Date: Tue Mar 22 10:02:21 2016 +0100 + + add devlink tool + + Add new tool called devlink which is userspace counterpart of devlink + Netlink socket. + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + Makefile | 2 +- + devlink/Makefile | 20 + + devlink/devlink.c | 986 +++++++++++++++++++++++++++++++++++++++++++++ + devlink/mnlg.c | 274 +++++++++++++ + devlink/mnlg.h | 27 ++ + man/man8/devlink-dev.8 | 58 +++ + man/man8/devlink-monitor.8 | 36 ++ + man/man8/devlink-port.8 | 126 ++++++ + man/man8/devlink.8 | 83 ++++ + 9 files changed, 1611 insertions(+), 1 deletion(-) + create mode 100644 devlink/Makefile + create mode 100644 devlink/devlink.c + create mode 100644 devlink/mnlg.c + create mode 100644 devlink/mnlg.h + create mode 100644 man/man8/devlink-dev.8 + create mode 100644 man/man8/devlink-monitor.8 + create mode 100644 man/man8/devlink-port.8 + create mode 100644 man/man8/devlink.8 + +diff --git a/Makefile b/Makefile +index 18faee4..d50512f 100644 +--- a/Makefile ++++ b/Makefile +@@ -36,7 +36,7 @@ WFLAGS += -Wmissing-declarations -Wold-style-definition -Wformat=2 + CFLAGS := $(WFLAGS) $(CCOPTS) -I../include $(DEFINES) $(CFLAGS) + YACCFLAGS = -d -t -v + +-SUBDIRS=lib ip tc bridge misc netem genl man ++SUBDIRS=lib ip tc bridge misc netem genl devlink man + + LIBNETLINK=../lib/libnetlink.a ../lib/libutil.a + LDLIBS += $(LIBNETLINK) +diff --git a/devlink/Makefile b/devlink/Makefile +new file mode 100644 +index 0000000..3fdaa69 +--- /dev/null ++++ b/devlink/Makefile +@@ -0,0 +1,20 @@ ++include ../Config ++ifeq ($(HAVE_MNL),y) ++ ++DEVLINKOBJ = devlink.o mnlg.o ++TARGETS=devlink ++ ++CFLAGS += $(shell $(PKG_CONFIG) libmnl --cflags) ++LDLIBS += $(shell $(PKG_CONFIG) libmnl --libs) ++ ++endif ++ ++all: $(TARGETS) $(LIBS) ++ ++devlink: $(DEVLINKOBJ) ++ ++install: all ++ install -m 0755 $(TARGETS) $(DESTDIR)$(SBINDIR) ++ ++clean: ++ rm -f $(DEVLINKOBJ) $(TARGETS) +diff --git a/devlink/devlink.c b/devlink/devlink.c +new file mode 100644 +index 0000000..c2da850 +--- /dev/null ++++ b/devlink/devlink.c +@@ -0,0 +1,986 @@ ++/* ++ * devlink.c Devlink tool ++ * ++ * 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. ++ * ++ * Authors: Jiri Pirko <jiri@mellanox.com> ++ */ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <stdbool.h> ++#include <unistd.h> ++#include <getopt.h> ++#include <limits.h> ++#include <errno.h> ++#include <linux/genetlink.h> ++#include <linux/devlink.h> ++#include <libmnl/libmnl.h> ++ ++#include "SNAPSHOT.h" ++#include "list.h" ++#include "mnlg.h" ++ ++#define pr_err(args...) fprintf(stderr, ##args) ++#define pr_out(args...) fprintf(stdout, ##args) ++ ++static int _mnlg_socket_recv_run(struct mnlg_socket *nlg, ++ mnl_cb_t data_cb, void *data) ++{ ++ int err; ++ ++ err = mnlg_socket_recv_run(nlg, data_cb, data); ++ if (err < 0) { ++ pr_err("devlink answers: %s\n", strerror(errno)); ++ return -errno; ++ } ++ return 0; ++} ++ ++static int _mnlg_socket_sndrcv(struct mnlg_socket *nlg, ++ const struct nlmsghdr *nlh, ++ mnl_cb_t data_cb, void *data) ++{ ++ int err; ++ ++ err = mnlg_socket_send(nlg, nlh); ++ if (err < 0) { ++ pr_err("Failed to call mnlg_socket_send\n"); ++ return -errno; ++ } ++ return _mnlg_socket_recv_run(nlg, data_cb, data); ++} ++ ++static int _mnlg_socket_group_add(struct mnlg_socket *nlg, ++ const char *group_name) ++{ ++ int err; ++ ++ err = mnlg_socket_group_add(nlg, group_name); ++ if (err < 0) { ++ pr_err("Failed to call mnlg_socket_group_add\n"); ++ return -errno; ++ } ++ return 0; ++} ++ ++struct ifname_map { ++ struct list_head list; ++ char *bus_name; ++ char *dev_name; ++ uint32_t port_index; ++ char *ifname; ++}; ++ ++static struct ifname_map *ifname_map_alloc(const char *bus_name, ++ const char *dev_name, ++ uint32_t port_index, ++ const char *ifname) ++{ ++ struct ifname_map *ifname_map; ++ ++ ifname_map = calloc(1, sizeof(*ifname_map)); ++ if (!ifname_map) ++ return NULL; ++ ifname_map->bus_name = strdup(bus_name); ++ ifname_map->dev_name = strdup(dev_name); ++ ifname_map->port_index = port_index; ++ ifname_map->ifname = strdup(ifname); ++ if (!ifname_map->bus_name || !ifname_map->dev_name || ++ !ifname_map->ifname) { ++ free(ifname_map->ifname); ++ free(ifname_map->dev_name); ++ free(ifname_map->bus_name); ++ free(ifname_map); ++ return NULL; ++ } ++ return ifname_map; ++} ++ ++static void ifname_map_free(struct ifname_map *ifname_map) ++{ ++ free(ifname_map->ifname); ++ free(ifname_map->dev_name); ++ free(ifname_map->bus_name); ++ free(ifname_map); ++} ++ ++struct dl { ++ struct mnlg_socket *nlg; ++ struct list_head ifname_map_list; ++ int argc; ++ char **argv; ++}; ++ ++static int dl_argc(struct dl *dl) ++{ ++ return dl->argc; ++} ++ ++static char *dl_argv(struct dl *dl) ++{ ++ if (dl_argc(dl) == 0) ++ return NULL; ++ return *dl->argv; ++} ++ ++static void dl_arg_inc(struct dl *dl) ++{ ++ if (dl_argc(dl) == 0) ++ return; ++ dl->argc--; ++ dl->argv++; ++} ++ ++static char *dl_argv_next(struct dl *dl) ++{ ++ char *ret; ++ ++ if (dl_argc(dl) == 0) ++ return NULL; ++ ++ ret = *dl->argv; ++ dl_arg_inc(dl); ++ return ret; ++} ++ ++static char *dl_argv_index(struct dl *dl, unsigned int index) ++{ ++ if (index >= dl_argc(dl)) ++ return NULL; ++ return dl->argv[index]; ++} ++ ++static int strcmpx(const char *str1, const char *str2) ++{ ++ if (strlen(str1) > strlen(str2)) ++ return -1; ++ return strncmp(str1, str2, strlen(str1)); ++} ++ ++static bool dl_argv_match(struct dl *dl, const char *pattern) ++{ ++ if (dl_argc(dl) == 0) ++ return false; ++ return strcmpx(dl_argv(dl), pattern) == 0; ++} ++ ++static bool dl_no_arg(struct dl *dl) ++{ ++ return dl_argc(dl) == 0; ++} ++ ++static int attr_cb(const struct nlattr *attr, void *data) ++{ ++ const struct nlattr **tb = data; ++ int type; ++ ++ type = mnl_attr_get_type(attr); ++ ++ if (mnl_attr_type_valid(attr, DEVLINK_ATTR_MAX) < 0) ++ return MNL_CB_ERROR; ++ ++ if (type == DEVLINK_ATTR_BUS_NAME && ++ mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_DEV_NAME && ++ mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_PORT_INDEX && ++ mnl_attr_validate(attr, MNL_TYPE_U32) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_PORT_TYPE && ++ mnl_attr_validate(attr, MNL_TYPE_U16) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_PORT_DESIRED_TYPE && ++ mnl_attr_validate(attr, MNL_TYPE_U16) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_PORT_NETDEV_IFINDEX && ++ mnl_attr_validate(attr, MNL_TYPE_U32) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_PORT_NETDEV_NAME && ++ mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_PORT_IBDEV_NAME && ++ mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0) ++ return MNL_CB_ERROR; ++ tb[type] = attr; ++ return MNL_CB_OK; ++} ++ ++static int ifname_map_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ struct dl *dl = data; ++ struct ifname_map *ifname_map; ++ const char *bus_name; ++ const char *dev_name; ++ uint32_t port_ifindex; ++ const char *port_ifname; ++ ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_PORT_INDEX]) ++ return MNL_CB_ERROR; ++ ++ if (!tb[DEVLINK_ATTR_PORT_NETDEV_NAME]) ++ return MNL_CB_OK; ++ ++ bus_name = mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]); ++ dev_name = mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME]); ++ port_ifindex = mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_INDEX]); ++ port_ifname = mnl_attr_get_str(tb[DEVLINK_ATTR_PORT_NETDEV_NAME]); ++ ifname_map = ifname_map_alloc(bus_name, dev_name, ++ port_ifindex, port_ifname); ++ if (!ifname_map) ++ return MNL_CB_ERROR; ++ list_add(&ifname_map->list, &dl->ifname_map_list); ++ ++ return MNL_CB_OK; ++} ++ ++static void ifname_map_fini(struct dl *dl) ++{ ++ struct ifname_map *ifname_map, *tmp; ++ ++ list_for_each_entry_safe(ifname_map, tmp, ++ &dl->ifname_map_list, list) { ++ list_del(&ifname_map->list); ++ ifname_map_free(ifname_map); ++ } ++} ++ ++static int ifname_map_init(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ int err; ++ ++ INIT_LIST_HEAD(&dl->ifname_map_list); ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_GET, ++ NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); ++ ++ err = _mnlg_socket_sndrcv(dl->nlg, nlh, ifname_map_cb, dl); ++ if (err) { ++ ifname_map_fini(dl); ++ return err; ++ } ++ return 0; ++} ++ ++static int ifname_map_lookup(struct dl *dl, const char *ifname, ++ char **p_bus_name, char **p_dev_name, ++ uint32_t *p_port_index) ++{ ++ struct ifname_map *ifname_map; ++ ++ list_for_each_entry(ifname_map, &dl->ifname_map_list, list) { ++ if (strcmp(ifname, ifname_map->ifname) == 0) { ++ *p_bus_name = ifname_map->bus_name; ++ *p_dev_name = ifname_map->dev_name; ++ *p_port_index = ifname_map->port_index; ++ return 0; ++ } ++ } ++ return -ENOENT; ++} ++ ++static unsigned int strslashcount(char *str) ++{ ++ unsigned int count = 0; ++ char *pos = str; ++ ++ while ((pos = strchr(pos, '/'))) { ++ count++; ++ pos++; ++ } ++ return count; ++} ++ ++static int strslashrsplit(char *str, char **before, char **after) ++{ ++ char *slash; ++ ++ slash = strrchr(str, '/'); ++ if (!slash) ++ return -EINVAL; ++ *slash = '\0'; ++ *before = str; ++ *after = slash + 1; ++ return 0; ++} ++ ++static int strtouint32_t(const char *str, uint32_t *p_val) ++{ ++ char *endptr; ++ unsigned long int val; ++ ++ val = strtoul(str, &endptr, 10); ++ if (endptr == str || *endptr != '\0') ++ return -EINVAL; ++ if (val > UINT_MAX) ++ return -ERANGE; ++ *p_val = val; ++ return 0; ++} ++ ++static int dl_argv_put_handle(struct nlmsghdr *nlh, struct dl *dl) ++{ ++ char *str = dl_argv_next(dl); ++ char *bus_name = bus_name; ++ char *dev_name = dev_name; ++ ++ if (!str) { ++ pr_err("Devlink identification (\"bus_name/dev_name\") expected\n"); ++ return -EINVAL; ++ } ++ if (strslashcount(str) != 1) { ++ pr_err("Wrong devlink identification string format.\n"); ++ pr_err("Expected \"bus_name/dev_name\".\n"); ++ return -EINVAL; ++ } ++ ++ strslashrsplit(str, &bus_name, &dev_name); ++ mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, bus_name); ++ mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, dev_name); ++ return 0; ++} ++ ++static int dl_argv_put_handle_port(struct nlmsghdr *nlh, struct dl *dl) ++{ ++ char *str = dl_argv_next(dl); ++ unsigned int slash_count; ++ char *bus_name = bus_name; ++ char *dev_name = dev_name; ++ uint32_t port_index = port_index; ++ int err; ++ ++ if (!str) { ++ pr_err("Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\") expected.\n"); ++ return -EINVAL; ++ } ++ slash_count = strslashcount(str); ++ if (slash_count != 2 && slash_count != 0) { ++ pr_err("Wrong port identification string format.\n"); ++ pr_err("Expected \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n"); ++ return -EINVAL; ++ } ++ ++ if (slash_count == 2) { ++ char *handlestr = handlestr; ++ char *portstr = portstr; ++ ++ err = strslashrsplit(str, &handlestr, &portstr); ++ err = strtouint32_t(portstr, &port_index); ++ if (err) { ++ pr_err("Port index \"%s\" is not a number or not within range\n", ++ portstr); ++ return err; ++ } ++ strslashrsplit(handlestr, &bus_name, &dev_name); ++ } else if (slash_count == 0) { ++ err = ifname_map_lookup(dl, str, &bus_name, &dev_name, ++ &port_index); ++ if (err) { ++ pr_err("Netdevice \"%s\" not found\n", str); ++ return err; ++ } ++ } ++ mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, bus_name); ++ mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, dev_name); ++ mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, port_index); ++ return 0; ++} ++ ++static int dl_argv_uint32_t(struct dl *dl, uint32_t *p_val) ++{ ++ char *str = dl_argv_next(dl); ++ int err; ++ ++ if (!str) { ++ pr_err("Unsigned number argument expected\n"); ++ return -EINVAL; ++ } ++ ++ err = strtouint32_t(str, p_val); ++ if (err) { ++ pr_err("\"%s\" is not a number or not within range\n", str); ++ return err; ++ } ++ return 0; ++} ++ ++static int dl_argv_str(struct dl *dl, const char **p_str) ++{ ++ const char *str = dl_argv_next(dl); ++ ++ if (!str) { ++ pr_err("String parameter expected\n"); ++ return -EINVAL; ++ } ++ *p_str = str; ++ return 0; ++} ++ ++static int port_type_get(const char *typestr, enum devlink_port_type *p_type) ++{ ++ if (strcmp(typestr, "auto") == 0) { ++ *p_type = DEVLINK_PORT_TYPE_AUTO; ++ } else if (strcmp(typestr, "eth") == 0) { ++ *p_type = DEVLINK_PORT_TYPE_ETH; ++ } else if (strcmp(typestr, "ib") == 0) { ++ *p_type = DEVLINK_PORT_TYPE_IB; ++ } else { ++ pr_err("Unknown port type \"%s\"\n", typestr); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++#define BIT(nr) (1UL << (nr)) ++#define DL_OPT_HANDLE BIT(0) ++#define DL_OPT_HANDLEP BIT(1) ++#define DL_OPT_PORT_TYPE BIT(2) ++#define DL_OPT_PORT_COUNT BIT(3) ++ ++static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl, ++ uint32_t o_required, uint32_t o_optional) ++{ ++ uint32_t o_all = o_required | o_optional; ++ uint32_t o_found = 0; ++ int err; ++ ++ if (o_required & DL_OPT_HANDLE) { ++ err = dl_argv_put_handle(nlh, dl); ++ if (err) ++ return err; ++ } else if (o_required & DL_OPT_HANDLEP) { ++ err = dl_argv_put_handle_port(nlh, dl); ++ if (err) ++ return err; ++ } ++ ++ while (dl_argc(dl)) { ++ if (dl_argv_match(dl, "type") && ++ (o_all & DL_OPT_PORT_TYPE)) { ++ enum devlink_port_type port_type; ++ const char *typestr; ++ ++ dl_arg_inc(dl); ++ err = dl_argv_str(dl, &typestr); ++ if (err) ++ return err; ++ err = port_type_get(typestr, &port_type); ++ if (err) ++ return err; ++ mnl_attr_put_u16(nlh, DEVLINK_ATTR_PORT_TYPE, ++ port_type); ++ o_found |= DL_OPT_PORT_TYPE; ++ } else if (dl_argv_match(dl, "count") && ++ (o_all & DL_OPT_PORT_COUNT)) { ++ uint32_t count; ++ ++ dl_arg_inc(dl); ++ err = dl_argv_uint32_t(dl, &count); ++ if (err) ++ return err; ++ mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_SPLIT_COUNT, ++ count); ++ o_found |= DL_OPT_PORT_COUNT; ++ } else { ++ pr_err("Unknown option \"%s\"\n", dl_argv(dl)); ++ return -EINVAL; ++ } ++ } ++ ++ if ((o_required & DL_OPT_PORT_TYPE) && !(o_found & DL_OPT_PORT_TYPE)) { ++ pr_err("Port type option expected.\n"); ++ return -EINVAL; ++ } ++ ++ if ((o_required & DL_OPT_PORT_COUNT) && ++ !(o_found & DL_OPT_PORT_COUNT)) { ++ pr_err("Port split count option expected.\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static void cmd_dev_help(void) ++{ ++ pr_out("Usage: devlink dev show [ DEV ]\n"); ++} ++ ++static void pr_out_handle(struct nlattr **tb) ++{ ++ pr_out("%s/%s", mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]), ++ mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME])); ++} ++ ++static void pr_out_dev(struct nlattr **tb) ++{ ++ pr_out_handle(tb); ++ pr_out("\n"); ++} ++ ++static int cmd_dev_show_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME]) ++ return MNL_CB_ERROR; ++ pr_out_dev(tb); ++ return MNL_CB_OK; ++} ++ ++static int cmd_dev_show(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; ++ int err; ++ ++ if (dl_argc(dl) == 0) ++ flags |= NLM_F_DUMP; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_GET, flags); ++ ++ if (dl_argc(dl) > 0) { ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, 0); ++ if (err) ++ return err; ++ } ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dev_show_cb, NULL); ++} ++ ++static int cmd_dev(struct dl *dl) ++{ ++ if (dl_argv_match(dl, "help")) { ++ cmd_dev_help(); ++ return 0; ++ } else if (dl_argv_match(dl, "show") || ++ dl_argv_match(dl, "list") || dl_no_arg(dl)) { ++ dl_arg_inc(dl); ++ return cmd_dev_show(dl); ++ } ++ pr_err("Command \"%s\" not found\n", dl_argv(dl)); ++ return -ENOENT; ++} ++ ++static void cmd_port_help(void) ++{ ++ pr_out("Usage: devlink port show [ DEV/PORT_INDEX ]\n"); ++ pr_out(" dl port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n"); ++ pr_out(" dl port split DEV/PORT_INDEX count COUNT\n"); ++ pr_out(" dl port unsplit DEV/PORT_INDEX\n"); ++} ++ ++static const char *port_type_name(uint32_t type) ++{ ++ switch (type) { ++ case DEVLINK_PORT_TYPE_NOTSET: return "notset"; ++ case DEVLINK_PORT_TYPE_AUTO: return "auto"; ++ case DEVLINK_PORT_TYPE_ETH: return "eth"; ++ case DEVLINK_PORT_TYPE_IB: return "ib"; ++ default: return "<unknown type>"; ++ } ++} ++ ++static void pr_out_port(struct nlattr **tb) ++{ ++ struct nlattr *pt_attr = tb[DEVLINK_ATTR_PORT_TYPE]; ++ struct nlattr *dpt_attr = tb[DEVLINK_ATTR_PORT_DESIRED_TYPE]; ++ ++ pr_out_handle(tb); ++ pr_out("/%d:", mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_INDEX])); ++ if (pt_attr) { ++ uint16_t port_type = mnl_attr_get_u16(pt_attr); ++ ++ pr_out(" type %s", port_type_name(port_type)); ++ if (dpt_attr) { ++ uint16_t des_port_type = mnl_attr_get_u16(dpt_attr); ++ ++ if (port_type != des_port_type) ++ pr_out("(%s)", port_type_name(des_port_type)); ++ } ++ } ++ if (tb[DEVLINK_ATTR_PORT_NETDEV_NAME]) ++ pr_out(" netdev %s", ++ mnl_attr_get_str(tb[DEVLINK_ATTR_PORT_NETDEV_NAME])); ++ if (tb[DEVLINK_ATTR_PORT_IBDEV_NAME]) ++ pr_out(" ibdev %s", ++ mnl_attr_get_str(tb[DEVLINK_ATTR_PORT_IBDEV_NAME])); ++ if (tb[DEVLINK_ATTR_PORT_SPLIT_GROUP]) ++ pr_out(" split_group %u", ++ mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_SPLIT_GROUP])); ++ pr_out("\n"); ++} ++ ++static int cmd_port_show_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_PORT_INDEX]) ++ return MNL_CB_ERROR; ++ pr_out_port(tb); ++ return MNL_CB_OK; ++} ++ ++static int cmd_port_show(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; ++ int err; ++ ++ if (dl_argc(dl) == 0) ++ flags |= NLM_F_DUMP; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_GET, flags); ++ ++ if (dl_argc(dl) > 0) { ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP, 0); ++ if (err) ++ return err; ++ } ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_port_show_cb, NULL); ++} ++ ++static int cmd_port_set(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ int err; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_SET, ++ NLM_F_REQUEST | NLM_F_ACK); ++ ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_PORT_TYPE, 0); ++ if (err) ++ return err; ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); ++} ++ ++static int cmd_port_split(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ int err; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_SPLIT, ++ NLM_F_REQUEST | NLM_F_ACK); ++ ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_PORT_COUNT, 0); ++ if (err) ++ return err; ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); ++} ++ ++static int cmd_port_unsplit(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ int err; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_UNSPLIT, ++ NLM_F_REQUEST | NLM_F_ACK); ++ ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP, 0); ++ if (err) ++ return err; ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); ++} ++ ++static int cmd_port(struct dl *dl) ++{ ++ if (dl_argv_match(dl, "help")) { ++ cmd_port_help(); ++ return 0; ++ } else if (dl_argv_match(dl, "show") || ++ dl_argv_match(dl, "list") || dl_no_arg(dl)) { ++ dl_arg_inc(dl); ++ return cmd_port_show(dl); ++ } else if (dl_argv_match(dl, "set")) { ++ dl_arg_inc(dl); ++ return cmd_port_set(dl); ++ } else if (dl_argv_match(dl, "split")) { ++ dl_arg_inc(dl); ++ return cmd_port_split(dl); ++ } else if (dl_argv_match(dl, "unsplit")) { ++ dl_arg_inc(dl); ++ return cmd_port_unsplit(dl); ++ } ++ pr_err("Command \"%s\" not found\n", dl_argv(dl)); ++ return -ENOENT; ++} ++ ++static const char *cmd_name(uint8_t cmd) ++{ ++ switch (cmd) { ++ case DEVLINK_CMD_UNSPEC: return "unspec"; ++ case DEVLINK_CMD_GET: return "get"; ++ case DEVLINK_CMD_SET: return "set"; ++ case DEVLINK_CMD_NEW: return "new"; ++ case DEVLINK_CMD_DEL: return "del"; ++ case DEVLINK_CMD_PORT_GET: return "get"; ++ case DEVLINK_CMD_PORT_SET: return "set"; ++ case DEVLINK_CMD_PORT_NEW: return "net"; ++ case DEVLINK_CMD_PORT_DEL: return "del"; ++ default: return "<unknown cmd>"; ++ } ++} ++ ++static const char *cmd_obj(uint8_t cmd) ++{ ++ switch (cmd) { ++ case DEVLINK_CMD_UNSPEC: return "unspec"; ++ case DEVLINK_CMD_GET: ++ case DEVLINK_CMD_SET: ++ case DEVLINK_CMD_NEW: ++ case DEVLINK_CMD_DEL: ++ return "dev"; ++ case DEVLINK_CMD_PORT_GET: ++ case DEVLINK_CMD_PORT_SET: ++ case DEVLINK_CMD_PORT_NEW: ++ case DEVLINK_CMD_PORT_DEL: ++ return "port"; ++ default: return "<unknown obj>"; ++ } ++} ++ ++static void pr_out_mon_header(uint8_t cmd) ++{ ++ pr_out("[%s,%s] ", cmd_obj(cmd), cmd_name(cmd)); ++} ++ ++static bool cmd_filter_check(struct dl *dl, uint8_t cmd) ++{ ++ const char *obj = cmd_obj(cmd); ++ unsigned int index = 0; ++ const char *cur_obj; ++ ++ if (dl_no_arg(dl)) ++ return true; ++ while ((cur_obj = dl_argv_index(dl, index++))) { ++ if (strcmp(cur_obj, obj) == 0 || strcmp(cur_obj, "all") == 0) ++ return true; ++ } ++ return false; ++} ++ ++static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct dl *dl = data; ++ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ uint8_t cmd = genl->cmd; ++ ++ if (!cmd_filter_check(dl, cmd)) ++ return MNL_CB_OK; ++ ++ switch (cmd) { ++ case DEVLINK_CMD_GET: /* fall through */ ++ case DEVLINK_CMD_SET: /* fall through */ ++ case DEVLINK_CMD_NEW: /* fall through */ ++ case DEVLINK_CMD_DEL: ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME]) ++ return MNL_CB_ERROR; ++ pr_out_mon_header(genl->cmd); ++ pr_out_dev(tb); ++ break; ++ case DEVLINK_CMD_PORT_GET: /* fall through */ ++ case DEVLINK_CMD_PORT_SET: /* fall through */ ++ case DEVLINK_CMD_PORT_NEW: /* fall through */ ++ case DEVLINK_CMD_PORT_DEL: ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_PORT_INDEX]) ++ return MNL_CB_ERROR; ++ pr_out_mon_header(genl->cmd); ++ pr_out_port(tb); ++ break; ++ } ++ return MNL_CB_OK; ++} ++ ++static int cmd_mon_show(struct dl *dl) ++{ ++ int err; ++ unsigned int index = 0; ++ const char *cur_obj; ++ ++ while ((cur_obj = dl_argv_index(dl, index++))) { ++ if (strcmp(cur_obj, "all") != 0 && ++ strcmp(cur_obj, "dev") != 0 && ++ strcmp(cur_obj, "port") != 0) { ++ pr_err("Unknown object \"%s\"\n", cur_obj); ++ return -EINVAL; ++ } ++ } ++ err = _mnlg_socket_group_add(dl->nlg, DEVLINK_GENL_MCGRP_CONFIG_NAME); ++ if (err) ++ return err; ++ err = _mnlg_socket_recv_run(dl->nlg, cmd_mon_show_cb, dl); ++ if (err) ++ return err; ++ return 0; ++} ++ ++static void cmd_mon_help(void) ++{ ++ pr_out("Usage: devlink monitor [ all | OBJECT-LIST ]\n" ++ "where OBJECT-LIST := { dev | port }\n"); ++} ++ ++static int cmd_mon(struct dl *dl) ++{ ++ if (dl_argv_match(dl, "help")) { ++ cmd_mon_help(); ++ return 0; ++ } else if (dl_no_arg(dl)) { ++ dl_arg_inc(dl); ++ return cmd_mon_show(dl); ++ } ++ pr_err("Command \"%s\" not found\n", dl_argv(dl)); ++ return -ENOENT; ++} ++ ++static void help(void) ++{ ++ pr_out("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n" ++ "where OBJECT := { dev | port | monitor }\n" ++ " OPTIONS := { -V[ersion] }\n"); ++} ++ ++static int dl_cmd(struct dl *dl) ++{ ++ if (dl_argv_match(dl, "help") || dl_no_arg(dl)) { ++ help(); ++ return 0; ++ } else if (dl_argv_match(dl, "dev")) { ++ dl_arg_inc(dl); ++ return cmd_dev(dl); ++ } else if (dl_argv_match(dl, "port")) { ++ dl_arg_inc(dl); ++ return cmd_port(dl); ++ } else if (dl_argv_match(dl, "monitor")) { ++ dl_arg_inc(dl); ++ return cmd_mon(dl); ++ } ++ pr_err("Object \"%s\" not found\n", dl_argv(dl)); ++ return -ENOENT; ++} ++ ++static int dl_init(struct dl *dl, int argc, char **argv) ++{ ++ int err; ++ ++ dl->argc = argc; ++ dl->argv = argv; ++ ++ dl->nlg = mnlg_socket_open(DEVLINK_GENL_NAME, DEVLINK_GENL_VERSION); ++ if (!dl->nlg) { ++ pr_err("Failed to connect to devlink Netlink\n"); ++ return -errno; ++ } ++ ++ err = ifname_map_init(dl); ++ if (err) { ++ pr_err("Failed to create index map\n"); ++ goto err_ifname_map_create; ++ } ++ return 0; ++ ++err_ifname_map_create: ++ mnlg_socket_close(dl->nlg); ++ return err; ++} ++ ++static void dl_fini(struct dl *dl) ++{ ++ ifname_map_fini(dl); ++ mnlg_socket_close(dl->nlg); ++} ++ ++static struct dl *dl_alloc(void) ++{ ++ struct dl *dl; ++ ++ dl = calloc(1, sizeof(*dl)); ++ if (!dl) ++ return NULL; ++ return dl; ++} ++ ++static void dl_free(struct dl *dl) ++{ ++ free(dl); ++} ++ ++int main(int argc, char **argv) ++{ ++ static const struct option long_options[] = { ++ { "Version", no_argument, NULL, 'V' }, ++ { NULL, 0, NULL, 0 } ++ }; ++ struct dl *dl; ++ int opt; ++ int err; ++ int ret; ++ ++ while ((opt = getopt_long(argc, argv, "V", ++ long_options, NULL)) >= 0) { ++ ++ switch (opt) { ++ case 'V': ++ printf("devlink utility, iproute2-ss%s\n", SNAPSHOT); ++ return EXIT_SUCCESS; ++ default: ++ pr_err("Unknown option.\n"); ++ help(); ++ return EXIT_FAILURE; ++ } ++ } ++ ++ argc -= optind; ++ argv += optind; ++ ++ dl = dl_alloc(); ++ if (!dl) { ++ pr_err("Failed to allocate memory for devlink\n"); ++ return EXIT_FAILURE; ++ } ++ ++ err = dl_init(dl, argc, argv); ++ if (err) { ++ ret = EXIT_FAILURE; ++ goto dl_free; ++ } ++ ++ err = dl_cmd(dl); ++ if (err) { ++ ret = EXIT_FAILURE; ++ goto dl_fini; ++ } ++ ++ ret = EXIT_SUCCESS; ++ ++dl_fini: ++ dl_fini(dl); ++dl_free: ++ dl_free(dl); ++ ++ return ret; ++} +diff --git a/devlink/mnlg.c b/devlink/mnlg.c +new file mode 100644 +index 0000000..9e27de2 +--- /dev/null ++++ b/devlink/mnlg.c +@@ -0,0 +1,274 @@ ++/* ++ * mnlg.c Generic Netlink helpers for libmnl ++ * ++ * 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. ++ * ++ * Authors: Jiri Pirko <jiri@mellanox.com> ++ */ ++ ++#include <stdlib.h> ++#include <stdbool.h> ++#include <string.h> ++#include <errno.h> ++#include <unistd.h> ++#include <time.h> ++#include <libmnl/libmnl.h> ++#include <linux/genetlink.h> ++ ++#include "mnlg.h" ++ ++struct mnlg_socket { ++ struct mnl_socket *nl; ++ char *buf; ++ uint32_t id; ++ uint8_t version; ++ unsigned int seq; ++ unsigned int portid; ++}; ++ ++static struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd, ++ uint16_t flags, uint32_t id, ++ uint8_t version) ++{ ++ struct nlmsghdr *nlh; ++ struct genlmsghdr *genl; ++ ++ nlh = mnl_nlmsg_put_header(nlg->buf); ++ nlh->nlmsg_type = id; ++ nlh->nlmsg_flags = flags; ++ nlg->seq = time(NULL); ++ nlh->nlmsg_seq = nlg->seq; ++ ++ genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); ++ genl->cmd = cmd; ++ genl->version = version; ++ ++ return nlh; ++} ++ ++struct nlmsghdr *mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd, ++ uint16_t flags) ++{ ++ return __mnlg_msg_prepare(nlg, cmd, flags, nlg->id, nlg->version); ++} ++ ++int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh) ++{ ++ return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len); ++} ++ ++int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data) ++{ ++ int err; ++ ++ do { ++ err = mnl_socket_recvfrom(nlg->nl, nlg->buf, ++ MNL_SOCKET_BUFFER_SIZE); ++ if (err <= 0) ++ break; ++ err = mnl_cb_run(nlg->buf, err, nlg->seq, nlg->portid, ++ data_cb, data); ++ } while (err > 0); ++ ++ return err; ++} ++ ++struct group_info { ++ bool found; ++ uint32_t id; ++ const char *name; ++}; ++ ++static int parse_mc_grps_cb(const struct nlattr *attr, void *data) ++{ ++ const struct nlattr **tb = data; ++ int type = mnl_attr_get_type(attr); ++ ++ if (mnl_attr_type_valid(attr, CTRL_ATTR_MCAST_GRP_MAX) < 0) ++ return MNL_CB_OK; ++ ++ switch (type) { ++ case CTRL_ATTR_MCAST_GRP_ID: ++ if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) ++ return MNL_CB_ERROR; ++ break; ++ case CTRL_ATTR_MCAST_GRP_NAME: ++ if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) ++ return MNL_CB_ERROR; ++ break; ++ } ++ tb[type] = attr; ++ return MNL_CB_OK; ++} ++ ++static void parse_genl_mc_grps(struct nlattr *nested, ++ struct group_info *group_info) ++{ ++ struct nlattr *pos; ++ const char *name; ++ ++ mnl_attr_for_each_nested(pos, nested) { ++ struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX + 1] = {}; ++ ++ mnl_attr_parse_nested(pos, parse_mc_grps_cb, tb); ++ if (!tb[CTRL_ATTR_MCAST_GRP_NAME] || ++ !tb[CTRL_ATTR_MCAST_GRP_ID]) ++ continue; ++ ++ name = mnl_attr_get_str(tb[CTRL_ATTR_MCAST_GRP_NAME]); ++ if (strcmp(name, group_info->name) != 0) ++ continue; ++ ++ group_info->id = mnl_attr_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]); ++ group_info->found = true; ++ } ++} ++ ++static int get_group_id_attr_cb(const struct nlattr *attr, void *data) ++{ ++ const struct nlattr **tb = data; ++ int type = mnl_attr_get_type(attr); ++ ++ if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0) ++ return MNL_CB_ERROR; ++ ++ if (type == CTRL_ATTR_MCAST_GROUPS && ++ mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) ++ return MNL_CB_ERROR; ++ tb[type] = attr; ++ return MNL_CB_OK; ++} ++ ++static int get_group_id_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct group_info *group_info = data; ++ struct nlattr *tb[CTRL_ATTR_MAX + 1] = {}; ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ ++ mnl_attr_parse(nlh, sizeof(*genl), get_group_id_attr_cb, tb); ++ if (!tb[CTRL_ATTR_MCAST_GROUPS]) ++ return MNL_CB_ERROR; ++ parse_genl_mc_grps(tb[CTRL_ATTR_MCAST_GROUPS], group_info); ++ return MNL_CB_OK; ++} ++ ++int mnlg_socket_group_add(struct mnlg_socket *nlg, const char *group_name) ++{ ++ struct nlmsghdr *nlh; ++ struct group_info group_info; ++ int err; ++ ++ nlh = __mnlg_msg_prepare(nlg, CTRL_CMD_GETFAMILY, ++ NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1); ++ mnl_attr_put_u32(nlh, CTRL_ATTR_FAMILY_ID, nlg->id); ++ ++ err = mnlg_socket_send(nlg, nlh); ++ if (err < 0) ++ return err; ++ ++ group_info.found = false; ++ group_info.name = group_name; ++ err = mnlg_socket_recv_run(nlg, get_group_id_cb, &group_info); ++ if (err < 0) ++ return err; ++ ++ if (!group_info.found) { ++ errno = ENOENT; ++ return -1; ++ } ++ ++ err = mnl_socket_setsockopt(nlg->nl, NETLINK_ADD_MEMBERSHIP, ++ &group_info.id, sizeof(group_info.id)); ++ if (err < 0) ++ return err; ++ ++ return 0; ++} ++ ++static int get_family_id_attr_cb(const struct nlattr *attr, void *data) ++{ ++ const struct nlattr **tb = data; ++ int type = mnl_attr_get_type(attr); ++ ++ if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0) ++ return MNL_CB_ERROR; ++ ++ if (type == CTRL_ATTR_FAMILY_ID && ++ mnl_attr_validate(attr, MNL_TYPE_U16) < 0) ++ return MNL_CB_ERROR; ++ tb[type] = attr; ++ return MNL_CB_OK; ++} ++ ++static int get_family_id_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ uint32_t *p_id = data; ++ struct nlattr *tb[CTRL_ATTR_MAX + 1] = {}; ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ ++ mnl_attr_parse(nlh, sizeof(*genl), get_family_id_attr_cb, tb); ++ if (!tb[CTRL_ATTR_FAMILY_ID]) ++ return MNL_CB_ERROR; ++ *p_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]); ++ return MNL_CB_OK; ++} ++ ++struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version) ++{ ++ struct mnlg_socket *nlg; ++ struct nlmsghdr *nlh; ++ int err; ++ ++ nlg = malloc(sizeof(*nlg)); ++ if (!nlg) ++ return NULL; ++ ++ nlg->buf = malloc(MNL_SOCKET_BUFFER_SIZE); ++ if (!nlg->buf) ++ goto err_buf_alloc; ++ ++ nlg->nl = mnl_socket_open(NETLINK_GENERIC); ++ if (!nlg->nl) ++ goto err_mnl_socket_open; ++ ++ err = mnl_socket_bind(nlg->nl, 0, MNL_SOCKET_AUTOPID); ++ if (err < 0) ++ goto err_mnl_socket_bind; ++ ++ nlg->portid = mnl_socket_get_portid(nlg->nl); ++ ++ nlh = __mnlg_msg_prepare(nlg, CTRL_CMD_GETFAMILY, ++ NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1); ++ mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, family_name); ++ ++ err = mnlg_socket_send(nlg, nlh); ++ if (err < 0) ++ goto err_mnlg_socket_send; ++ ++ err = mnlg_socket_recv_run(nlg, get_family_id_cb, &nlg->id); ++ if (err < 0) ++ goto err_mnlg_socket_recv_run; ++ ++ nlg->version = version; ++ return nlg; ++ ++err_mnlg_socket_recv_run: ++err_mnlg_socket_send: ++err_mnl_socket_bind: ++ mnl_socket_close(nlg->nl); ++err_mnl_socket_open: ++ free(nlg->buf); ++err_buf_alloc: ++ free(nlg); ++ return NULL; ++} ++ ++void mnlg_socket_close(struct mnlg_socket *nlg) ++{ ++ mnl_socket_close(nlg->nl); ++ free(nlg->buf); ++ free(nlg); ++} +diff --git a/devlink/mnlg.h b/devlink/mnlg.h +new file mode 100644 +index 0000000..4d1babf +--- /dev/null ++++ b/devlink/mnlg.h +@@ -0,0 +1,27 @@ ++/* ++ * mnlg.h Generic Netlink helpers for libmnl ++ * ++ * 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. ++ * ++ * Authors: Jiri Pirko <jiri@mellanox.com> ++ */ ++ ++#ifndef _MNLG_H_ ++#define _MNLG_H_ ++ ++#include <libmnl/libmnl.h> ++ ++struct mnlg_socket; ++ ++struct nlmsghdr *mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd, ++ uint16_t flags); ++int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh); ++int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data); ++int mnlg_socket_group_add(struct mnlg_socket *nlg, const char *group_name); ++struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version); ++void mnlg_socket_close(struct mnlg_socket *nlg); ++ ++#endif /* _MNLG_H_ */ +diff --git a/man/man8/devlink-dev.8 b/man/man8/devlink-dev.8 +new file mode 100644 +index 0000000..7878d89 +--- /dev/null ++++ b/man/man8/devlink-dev.8 +@@ -0,0 +1,58 @@ ++.TH DEVLINK\-DEV 8 "14 Mar 2016" "iproute2" "Linux" ++.SH NAME ++devlink-dev \- devlink device configuration ++.SH SYNOPSIS ++.sp ++.ad l ++.in +8 ++.ti -8 ++.B devlink ++.RI "[ " OPTIONS " ]" ++.B dev ++.RI " { " COMMAND " | " ++.BR help " }" ++.sp ++ ++.ti -8 ++.IR OPTIONS " := { " ++\fB\-V\fR[\fIersion\fR] | ++ ++.ti -8 ++.B devlink dev show ++.RI "[ " DEV " ]" ++ ++.ti -8 ++.B devlink dev help ++ ++.SH "DESCRIPTION" ++.SS devlink dev show - display devlink device attributes ++ ++.PP ++.I "DEV" ++- specifies the devlink device to show. ++If this argument is omitted all devices are listed. ++ ++.in +4 ++Format is: ++.in +2 ++BUS_NAME/BUS_ADDRESS ++ ++.SH "EXAMPLES" ++.PP ++devlink dev show ++.RS 4 ++Shows the state of all devlink devices on the system. ++.RE ++.PP ++devlink dev show pci/0000:01:00.0 ++.RS 4 ++Shows the state of specified devlink device. ++ ++.SH SEE ALSO ++.BR devlink (8), ++.BR devlink-port (8), ++.BR devlink-monitor (8), ++.br ++ ++.SH AUTHOR ++Jiri Pirko <jiri@mellanox.com> +diff --git a/man/man8/devlink-monitor.8 b/man/man8/devlink-monitor.8 +new file mode 100644 +index 0000000..98134c3 +--- /dev/null ++++ b/man/man8/devlink-monitor.8 +@@ -0,0 +1,36 @@ ++.TH DEVLINK\-MONITOR 8 "14 Mar 2016" "iproute2" "Linux" ++.SH "NAME" ++devlink-monitor \- state monitoring ++.SH SYNOPSIS ++.sp ++.ad l ++.in +8 ++.ti -8 ++.BR "devlink monitor" " [ " all " |" ++.IR OBJECT-LIST " ]" ++.sp ++ ++.SH DESCRIPTION ++The ++.B devlink ++utility can monitor the state of devlink devices and ports ++continuously. This option has a slightly different format. Namely, the ++.B monitor ++command is the first in the command line and then the object list. ++ ++.I OBJECT-LIST ++is the list of object types that we want to monitor. ++It may contain ++.BR dev ", " port ". ++ ++.B devlink ++opens Devlink Netlink socket, listens on it and dumps state changes. ++ ++.SH SEE ALSO ++.BR devlink (8), ++.BR devlink-dev (8), ++.BR devlink-port (8), ++.br ++ ++.SH AUTHOR ++Jiri Pirko <jiri@mellanox.com> +diff --git a/man/man8/devlink-port.8 b/man/man8/devlink-port.8 +new file mode 100644 +index 0000000..e6ae686 +--- /dev/null ++++ b/man/man8/devlink-port.8 +@@ -0,0 +1,126 @@ ++.TH DEVLINK\-PORT 8 "14 Mar 2016" "iproute2" "Linux" ++.SH NAME ++devlink-port \- devlink port configuration ++.SH SYNOPSIS ++.sp ++.ad l ++.in +8 ++.ti -8 ++.B devlink ++.RI "[ " OPTIONS " ]" ++.B port ++.RI " { " COMMAND " | " ++.BR help " }" ++.sp ++ ++.ti -8 ++.IR OPTIONS " := { " ++\fB\-V\fR[\fIersion\fR] | ++ ++.ti -8 ++.BR "devlink port set " ++.IR DEV/PORT_INDEX ++.RI "[ " ++.BR type " { " eth " | " ib " | " auto " }" ++.RI "]" ++ ++.ti -8 ++.BR "devlink port split " ++.IR DEV/PORT_INDEX ++.BR count ++.IR COUNT ++ ++.ti -8 ++.BR "devlink port unsplit " ++.IR DEV/PORT_INDEX ++ ++.ti -8 ++.B devlink port show ++.RI "[ " DEV/PORT_INDEX " ]" ++ ++.ti -8 ++.B devlink port help ++ ++.SH "DESCRIPTION" ++.SS devlink port set - change devlink port attributes ++ ++.PP ++.B "DEV/PORT_INDEX" ++- specifies the devlink port to operate on. ++ ++.in +4 ++Format is: ++.in +2 ++BUS_NAME/BUS_ADDRESS/PORT_INDEX ++ ++.TP ++.BR type " { " eth " | " ib " | " auto " } " ++set port type ++ ++.I eth ++- Ethernet ++ ++.I ib ++- Infiniband ++ ++.I auto ++- autoselect ++ ++.SS devlink port split - split devlink port into more ++ ++.PP ++.B "DEV/PORT_INDEX" ++- specifies the devlink port to operate on. ++ ++.TP ++.BI count " COUNT" ++number of ports to split to. ++ ++.SS devlink port unsplit - unsplit previously split devlink port ++Could be performed on any split port of the same split group. ++ ++.PP ++.B "DEV/PORT_INDEX" ++- specifies the devlink port to operate on. ++ ++.SS devlink port show - display devlink port attributes ++ ++.PP ++.I "DEV/PORT_INDEX" ++- specifies the devlink port to show. ++If this argument is omitted all ports are listed. ++ ++.SH "EXAMPLES" ++.PP ++devlink port show ++.RS 4 ++Shows the state of all devlink ports on the system. ++.RE ++.PP ++devlink port show pci/0000:01:00.0/1 ++.RS 4 ++Shows the state of specified devlink port. ++.RE ++.PP ++devlink port set pci/0000:01:00.0/1 type eth ++.RS 4 ++Set type of specified devlink port to Ethernet. ++.RE ++.PP ++devlink port split pci/0000:01:00.0/1 count 4 ++.RS 4 ++Split the specified devlink port into four ports. ++.RE ++.PP ++devlink port unsplit pci/0000:01:00.0/1 ++.RS 4 ++Unplit the specified previously split devlink port. ++ ++.SH SEE ALSO ++.BR devlink (8), ++.BR devlink-dev (8), ++.BR devlink-monitor (8), ++.br ++ ++.SH AUTHOR ++Jiri Pirko <jiri@mellanox.com> +diff --git a/man/man8/devlink.8 b/man/man8/devlink.8 +new file mode 100644 +index 0000000..f608ccc +--- /dev/null ++++ b/man/man8/devlink.8 +@@ -0,0 +1,83 @@ ++.TH DEVLINK 8 "14 Mar 2016" "iproute2" "Linux" ++.SH NAME ++devlink \- Devlink tool ++.SH SYNOPSIS ++.sp ++.ad l ++.in +8 ++.ti -8 ++.B devlink ++.RI "[ " OPTIONS " ] " OBJECT " { " COMMAND " | " ++.BR help " }" ++.sp ++ ++.ti -8 ++.IR OBJECT " := { " ++.BR dev " | " port " | " monitor " }" ++.sp ++ ++.ti -8 ++.IR OPTIONS " := { " ++\fB\-V\fR[\fIersion\fR] | ++ ++.SH OPTIONS ++ ++.TP ++.BR "\-V" , " -Version" ++Print the version of the ++.B devlink ++utility and exit. ++ ++.SS ++.I OBJECT ++ ++.TP ++.B dev ++- devlink device. ++ ++.TP ++.B port ++- devlink port. ++ ++.TP ++.B monitor ++- watch for netlink messages. ++ ++.SS ++.I COMMAND ++ ++Specifies the action to perform on the object. ++The set of possible actions depends on the object type. ++As a rule, it is possible to ++.B show ++(or ++.B list ++) objects, but some objects do not allow all of these operations ++or have some additional commands. The ++.B help ++command is available for all objects. It prints ++out a list of available commands and argument syntax conventions. ++.sp ++If no command is given, some default command is assumed. ++Usually it is ++.B list ++or, if the objects of this class cannot be listed, ++.BR "help" . ++ ++.SH EXIT STATUS ++Exit status is 0 if command was successful or a positive integer upon failure. ++ ++.SH SEE ALSO ++.BR devlink-dev (8), ++.BR devlink-port (8), ++.BR devlink-monitor (8), ++.br ++ ++.SH REPORTING BUGS ++Report any bugs to the Network Developers mailing list ++.B <netdev@vger.kernel.org> ++where the development and maintenance is primarily done. ++You do not have to be subscribed to the list to send a message there. ++ ++.SH AUTHOR ++Jiri Pirko <jiri@mellanox.com> +-- +1.8.3.1 + diff --git a/SOURCES/0185-devlink-ignore-build-result.patch b/SOURCES/0185-devlink-ignore-build-result.patch new file mode 100644 index 0000000..72ea9b4 --- /dev/null +++ b/SOURCES/0185-devlink-ignore-build-result.patch @@ -0,0 +1,30 @@ +From 2fed35a92358b7c1e068c191867b34c47911bd63 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:33:01 +0200 +Subject: [PATCH] devlink: ignore build result + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit 3273e3c13258a + +commit 3273e3c13258a1845d1bc7eaa012c4824f4b47cb +Author: Stephen Hemminger <stephen@networkplumber.org> +Date: Mon Apr 11 13:32:22 2016 -0700 + + devlink: ignore build result + + devlink binary is built +--- + devlink/.gitignore | 1 + + 1 file changed, 1 insertion(+) + create mode 100644 devlink/.gitignore + +diff --git a/devlink/.gitignore b/devlink/.gitignore +new file mode 100644 +index 0000000..08d175f +--- /dev/null ++++ b/devlink/.gitignore +@@ -0,0 +1 @@ ++devlink +-- +1.8.3.1 + diff --git a/SOURCES/0186-devlink-fix-devlink-port-help-message.patch b/SOURCES/0186-devlink-fix-devlink-port-help-message.patch new file mode 100644 index 0000000..f31be02 --- /dev/null +++ b/SOURCES/0186-devlink-fix-devlink-port-help-message.patch @@ -0,0 +1,41 @@ +From affa0ba82aa12faf331686866f8a95f9dbc1b9fb Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:33:14 +0200 +Subject: [PATCH] devlink: fix "devlink port" help message + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit ec7513faa9598 + +commit ec7513faa959811e3a68aed0836d949dd924afca +Author: Jiri Pirko <jiri@mellanox.com> +Date: Fri Apr 15 09:51:43 2016 +0200 + + devlink: fix "devlink port" help message + + "dl" -> "devlink" + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + devlink/devlink.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/devlink/devlink.c b/devlink/devlink.c +index c2da850..39f423a 100644 +--- a/devlink/devlink.c ++++ b/devlink/devlink.c +@@ -578,9 +578,9 @@ static int cmd_dev(struct dl *dl) + static void cmd_port_help(void) + { + pr_out("Usage: devlink port show [ DEV/PORT_INDEX ]\n"); +- pr_out(" dl port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n"); +- pr_out(" dl port split DEV/PORT_INDEX count COUNT\n"); +- pr_out(" dl port unsplit DEV/PORT_INDEX\n"); ++ pr_out(" devlink port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n"); ++ pr_out(" devlink port split DEV/PORT_INDEX count COUNT\n"); ++ pr_out(" devlink port unsplit DEV/PORT_INDEX\n"); + } + + static const char *port_type_name(uint32_t type) +-- +1.8.3.1 + diff --git a/SOURCES/0187-list-add-list_for_each_entry_reverse-macro.patch b/SOURCES/0187-list-add-list_for_each_entry_reverse-macro.patch new file mode 100644 index 0000000..44527f2 --- /dev/null +++ b/SOURCES/0187-list-add-list_for_each_entry_reverse-macro.patch @@ -0,0 +1,54 @@ +From 04bba6707f56d8b5dd53d6b452240a634f823003 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:33:14 +0200 +Subject: [PATCH] list: add list_for_each_entry_reverse macro + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit f1239ca1f96c7 + +commit f1239ca1f96c76fbc0742ca0d0c7e87b9b15d437 +Author: Jiri Pirko <jiri@mellanox.com> +Date: Fri Apr 15 09:51:44 2016 +0200 + + list: add list_for_each_entry_reverse macro + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + include/list.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/include/list.h b/include/list.h +index cdebe4d..b549c3e 100644 +--- a/include/list.h ++++ b/include/list.h +@@ -50,9 +50,15 @@ static inline void list_del(struct list_head *entry) + #define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + ++#define list_last_entry(ptr, type, member) \ ++ list_entry((ptr)->prev, type, member) ++ + #define list_next_entry(pos, member) \ + list_entry((pos)->member.next, typeof(*(pos)), member) + ++#define list_prev_entry(pos, member) \ ++ list_entry((pos)->member.prev, typeof(*(pos)), member) ++ + #define list_for_each_entry(pos, head, member) \ + for (pos = list_first_entry(head, typeof(*pos), member); \ + &pos->member != (head); \ +@@ -64,6 +70,11 @@ static inline void list_del(struct list_head *entry) + &pos->member != (head); \ + pos = n, n = list_next_entry(n, member)) + ++#define list_for_each_entry_reverse(pos, head, member) \ ++ for (pos = list_last_entry(head, typeof(*pos), member); \ ++ &pos->member != (head); \ ++ pos = list_prev_entry(pos, member)) ++ + struct hlist_head { + struct hlist_node *first; + }; +-- +1.8.3.1 + diff --git a/SOURCES/0188-list-add-list_add_tail-helper.patch b/SOURCES/0188-list-add-list_add_tail-helper.patch new file mode 100644 index 0000000..13a40ed --- /dev/null +++ b/SOURCES/0188-list-add-list_add_tail-helper.patch @@ -0,0 +1,38 @@ +From 1fb2dabb962200cb88b5ab9d22ebe89cdfab22c4 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:33:14 +0200 +Subject: [PATCH] list: add list_add_tail helper + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit ebaf76b55ea50 + +commit ebaf76b55ea509bcfb8845e4c40a9ecd3e8377f5 +Author: Jiri Pirko <jiri@mellanox.com> +Date: Fri Apr 15 09:51:45 2016 +0200 + + list: add list_add_tail helper + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + include/list.h | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/include/list.h b/include/list.h +index b549c3e..5b529dc 100644 +--- a/include/list.h ++++ b/include/list.h +@@ -33,6 +33,11 @@ static inline void list_add(struct list_head *new, struct list_head *head) + __list_add(new, head, head->next); + } + ++static inline void list_add_tail(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head->prev, head); ++} ++ + static inline void __list_del(struct list_head *prev, struct list_head *next) + { + next->prev = prev; +-- +1.8.3.1 + diff --git a/SOURCES/0189-devlink-introduce-pr_out_port_handle-helper.patch b/SOURCES/0189-devlink-introduce-pr_out_port_handle-helper.patch new file mode 100644 index 0000000..c3e2601 --- /dev/null +++ b/SOURCES/0189-devlink-introduce-pr_out_port_handle-helper.patch @@ -0,0 +1,50 @@ +From 8a2d81a5e49d22ee486c16864ae3462bd037e8ed Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:33:14 +0200 +Subject: [PATCH] devlink: introduce pr_out_port_handle helper + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit 68cab0ba763f9 + +commit 68cab0ba763f9d80740d171e1882ad4f262ca6e1 +Author: Jiri Pirko <jiri@mellanox.com> +Date: Fri Apr 15 09:51:46 2016 +0200 + + devlink: introduce pr_out_port_handle helper + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + devlink/devlink.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/devlink/devlink.c b/devlink/devlink.c +index 39f423a..0904e07 100644 +--- a/devlink/devlink.c ++++ b/devlink/devlink.c +@@ -523,6 +523,12 @@ static void pr_out_handle(struct nlattr **tb) + mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME])); + } + ++static void pr_out_port_handle(struct nlattr **tb) ++{ ++ pr_out_handle(tb); ++ pr_out("/%d", mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_INDEX])); ++} ++ + static void pr_out_dev(struct nlattr **tb) + { + pr_out_handle(tb); +@@ -599,8 +605,8 @@ static void pr_out_port(struct nlattr **tb) + struct nlattr *pt_attr = tb[DEVLINK_ATTR_PORT_TYPE]; + struct nlattr *dpt_attr = tb[DEVLINK_ATTR_PORT_DESIRED_TYPE]; + +- pr_out_handle(tb); +- pr_out("/%d:", mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_INDEX])); ++ pr_out_port_handle(tb); ++ pr_out(":"); + if (pt_attr) { + uint16_t port_type = mnl_attr_get_u16(pt_attr); + +-- +1.8.3.1 + diff --git a/SOURCES/0190-devlink-introduce-helper-to-print-out-nice-names-ifn.patch b/SOURCES/0190-devlink-introduce-helper-to-print-out-nice-names-ifn.patch new file mode 100644 index 0000000..740c111 --- /dev/null +++ b/SOURCES/0190-devlink-introduce-helper-to-print-out-nice-names-ifn.patch @@ -0,0 +1,231 @@ +From 8dfa9a148b54fb2c7d58a5a391c8477fc75d9061 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:33:14 +0200 +Subject: [PATCH] devlink: introduce helper to print out nice names (ifnames) + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit 43f35be4ebb63 + +commit 43f35be4ebb63bf5dea9cc0570ba8d15458d2457 +Author: Jiri Pirko <jiri@mellanox.com> +Date: Fri Apr 15 09:51:47 2016 +0200 + + devlink: introduce helper to print out nice names (ifnames) + + By default, ifnames will be printed out. User can turn that off using + "-n" option on the command line. + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + devlink/devlink.c | 90 +++++++++++++++++++++++++++++++++++++++++++------ + man/man8/devlink-dev.8 | 1 + + man/man8/devlink-port.8 | 1 + + man/man8/devlink.8 | 5 +++ + 4 files changed, 86 insertions(+), 11 deletions(-) + +diff --git a/devlink/devlink.c b/devlink/devlink.c +index 0904e07..5e08666 100644 +--- a/devlink/devlink.c ++++ b/devlink/devlink.c +@@ -114,6 +114,7 @@ struct dl { + struct list_head ifname_map_list; + int argc; + char **argv; ++ bool no_nice_names; + }; + + static int dl_argc(struct dl *dl) +@@ -290,6 +291,23 @@ static int ifname_map_lookup(struct dl *dl, const char *ifname, + return -ENOENT; + } + ++static int ifname_map_rev_lookup(struct dl *dl, const char *bus_name, ++ const char *dev_name, uint32_t port_index, ++ char **p_ifname) ++{ ++ struct ifname_map *ifname_map; ++ ++ list_for_each_entry(ifname_map, &dl->ifname_map_list, list) { ++ if (strcmp(bus_name, ifname_map->bus_name) == 0 && ++ strcmp(dev_name, ifname_map->dev_name) == 0 && ++ port_index == ifname_map->port_index) { ++ *p_ifname = ifname_map->ifname; ++ return 0; ++ } ++ } ++ return -ENOENT; ++} ++ + static unsigned int strslashcount(char *str) + { + unsigned int count = 0; +@@ -517,16 +535,62 @@ static void cmd_dev_help(void) + pr_out("Usage: devlink dev show [ DEV ]\n"); + } + ++static void __pr_out_handle(const char *bus_name, const char *dev_name) ++{ ++ pr_out("%s/%s", bus_name, dev_name); ++} ++ + static void pr_out_handle(struct nlattr **tb) + { +- pr_out("%s/%s", mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]), ++ __pr_out_handle(mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]), + mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME])); + } + ++static void __pr_out_port_handle(const char *bus_name, const char *dev_name, ++ uint32_t port_index) ++{ ++ __pr_out_handle(bus_name, dev_name); ++ pr_out("/%d", port_index); ++} ++ + static void pr_out_port_handle(struct nlattr **tb) + { +- pr_out_handle(tb); +- pr_out("/%d", mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_INDEX])); ++ __pr_out_port_handle(mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]), ++ mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME]), ++ mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_INDEX])); ++} ++ ++static void __pr_out_port_handle_nice(struct dl *dl, const char *bus_name, ++ const char *dev_name, uint32_t port_index) ++{ ++ char *ifname; ++ int err; ++ ++ if (dl->no_nice_names) ++ goto no_nice_names; ++ ++ err = ifname_map_rev_lookup(dl, bus_name, dev_name, ++ port_index, &ifname); ++ if (err) ++ goto no_nice_names; ++ pr_out("%s", ifname); ++ return; ++ ++no_nice_names: ++ __pr_out_port_handle(bus_name, dev_name, port_index); ++} ++ ++static void pr_out_port_handle_nice(struct dl *dl, struct nlattr **tb) ++{ ++ const char *bus_name; ++ const char *dev_name; ++ uint32_t port_index; ++ ++ bus_name = mnl_attr_get_str(tb[DEVLINK_ATTR_BUS_NAME]); ++ dev_name = mnl_attr_get_str(tb[DEVLINK_ATTR_DEV_NAME]); ++ port_index = mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_INDEX]); ++ ++ __pr_out_port_handle_nice(dl, bus_name, dev_name, port_index); + } + + static void pr_out_dev(struct nlattr **tb) +@@ -867,7 +931,7 @@ static void help(void) + { + pr_out("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n" + "where OBJECT := { dev | port | monitor }\n" +- " OPTIONS := { -V[ersion] }\n"); ++ " OPTIONS := { -V[ersion] | -n[no-nice-names] }\n"); + } + + static int dl_cmd(struct dl *dl) +@@ -939,6 +1003,7 @@ int main(int argc, char **argv) + { + static const struct option long_options[] = { + { "Version", no_argument, NULL, 'V' }, ++ { "no-nice-names", no_argument, NULL, 'n' }, + { NULL, 0, NULL, 0 } + }; + struct dl *dl; +@@ -946,13 +1011,22 @@ int main(int argc, char **argv) + int err; + int ret; + +- while ((opt = getopt_long(argc, argv, "V", ++ dl = dl_alloc(); ++ if (!dl) { ++ pr_err("Failed to allocate memory for devlink\n"); ++ return EXIT_FAILURE; ++ } ++ ++ while ((opt = getopt_long(argc, argv, "Vn", + long_options, NULL)) >= 0) { + + switch (opt) { + case 'V': + printf("devlink utility, iproute2-ss%s\n", SNAPSHOT); + return EXIT_SUCCESS; ++ case 'n': ++ dl->no_nice_names = true; ++ break; + default: + pr_err("Unknown option.\n"); + help(); +@@ -963,12 +1037,6 @@ int main(int argc, char **argv) + argc -= optind; + argv += optind; + +- dl = dl_alloc(); +- if (!dl) { +- pr_err("Failed to allocate memory for devlink\n"); +- return EXIT_FAILURE; +- } +- + err = dl_init(dl, argc, argv); + if (err) { + ret = EXIT_FAILURE; +diff --git a/man/man8/devlink-dev.8 b/man/man8/devlink-dev.8 +index 7878d89..af96a29 100644 +--- a/man/man8/devlink-dev.8 ++++ b/man/man8/devlink-dev.8 +@@ -16,6 +16,7 @@ devlink-dev \- devlink device configuration + .ti -8 + .IR OPTIONS " := { " + \fB\-V\fR[\fIersion\fR] | ++\fB\-n\fR[\fIno-nice-names\fR] } + + .ti -8 + .B devlink dev show +diff --git a/man/man8/devlink-port.8 b/man/man8/devlink-port.8 +index e6ae686..d78837c 100644 +--- a/man/man8/devlink-port.8 ++++ b/man/man8/devlink-port.8 +@@ -16,6 +16,7 @@ devlink-port \- devlink port configuration + .ti -8 + .IR OPTIONS " := { " + \fB\-V\fR[\fIersion\fR] | ++\fB\-n\fR[\fIno-nice-names\fR] } + + .ti -8 + .BR "devlink port set " +diff --git a/man/man8/devlink.8 b/man/man8/devlink.8 +index f608ccc..df00f4f 100644 +--- a/man/man8/devlink.8 ++++ b/man/man8/devlink.8 +@@ -19,6 +19,7 @@ devlink \- Devlink tool + .ti -8 + .IR OPTIONS " := { " + \fB\-V\fR[\fIersion\fR] | ++\fB\-n\fR[\fIno-nice-names\fR] } + + .SH OPTIONS + +@@ -28,6 +29,10 @@ Print the version of the + .B devlink + utility and exit. + ++.TP ++.BR "\-n" , " -no-nice-names" ++Turn off printing out nice names, for example netdevice ifnames instead of devlink port identification. ++ + .SS + .I OBJECT + +-- +1.8.3.1 + diff --git a/SOURCES/0191-devlink-split-dl_argv_parse_put-to-parse-and-put-par.patch b/SOURCES/0191-devlink-split-dl_argv_parse_put-to-parse-and-put-par.patch new file mode 100644 index 0000000..5993eec --- /dev/null +++ b/SOURCES/0191-devlink-split-dl_argv_parse_put-to-parse-and-put-par.patch @@ -0,0 +1,239 @@ +From 4b03d06db283f11e3301e22e75b714abb7c446df Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:33:14 +0200 +Subject: [PATCH] devlink: split dl_argv_parse_put to parse and put parts + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit 6563a6eb539ba + +commit 6563a6eb539ba5c3f9fa262bc302190abb7e5f39 +Author: Jiri Pirko <jiri@mellanox.com> +Date: Fri Apr 15 09:51:48 2016 +0200 + + devlink: split dl_argv_parse_put to parse and put parts + + It is handy to have parsed cmdline data stored so they can be used for + dumps filtering. So split original dl_argv_parse_put into parse and put + parts. + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + devlink/devlink.c | 105 +++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 69 insertions(+), 36 deletions(-) + +diff --git a/devlink/devlink.c b/devlink/devlink.c +index 5e08666..0c2132f 100644 +--- a/devlink/devlink.c ++++ b/devlink/devlink.c +@@ -109,12 +109,28 @@ static void ifname_map_free(struct ifname_map *ifname_map) + free(ifname_map); + } + ++#define BIT(nr) (1UL << (nr)) ++#define DL_OPT_HANDLE BIT(0) ++#define DL_OPT_HANDLEP BIT(1) ++#define DL_OPT_PORT_TYPE BIT(2) ++#define DL_OPT_PORT_COUNT BIT(3) ++ ++struct dl_opts { ++ uint32_t present; /* flags of present items */ ++ char *bus_name; ++ char *dev_name; ++ uint32_t port_index; ++ enum devlink_port_type port_type; ++ uint32_t port_count; ++}; ++ + struct dl { + struct mnlg_socket *nlg; + struct list_head ifname_map_list; + int argc; + char **argv; + bool no_nice_names; ++ struct dl_opts opts; + }; + + static int dl_argc(struct dl *dl) +@@ -347,11 +363,9 @@ static int strtouint32_t(const char *str, uint32_t *p_val) + return 0; + } + +-static int dl_argv_put_handle(struct nlmsghdr *nlh, struct dl *dl) ++static int dl_argv_handle(struct dl *dl, char **p_bus_name, char **p_dev_name) + { + char *str = dl_argv_next(dl); +- char *bus_name = bus_name; +- char *dev_name = dev_name; + + if (!str) { + pr_err("Devlink identification (\"bus_name/dev_name\") expected\n"); +@@ -363,19 +377,15 @@ static int dl_argv_put_handle(struct nlmsghdr *nlh, struct dl *dl) + return -EINVAL; + } + +- strslashrsplit(str, &bus_name, &dev_name); +- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, bus_name); +- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, dev_name); ++ strslashrsplit(str, p_bus_name, p_dev_name); + return 0; + } + +-static int dl_argv_put_handle_port(struct nlmsghdr *nlh, struct dl *dl) ++static int dl_argv_handle_port(struct dl *dl, char **p_bus_name, ++ char **p_dev_name, uint32_t *p_port_index) + { + char *str = dl_argv_next(dl); + unsigned int slash_count; +- char *bus_name = bus_name; +- char *dev_name = dev_name; +- uint32_t port_index = port_index; + int err; + + if (!str) { +@@ -394,24 +404,21 @@ static int dl_argv_put_handle_port(struct nlmsghdr *nlh, struct dl *dl) + char *portstr = portstr; + + err = strslashrsplit(str, &handlestr, &portstr); +- err = strtouint32_t(portstr, &port_index); ++ err = strtouint32_t(portstr, p_port_index); + if (err) { + pr_err("Port index \"%s\" is not a number or not within range\n", + portstr); + return err; + } +- strslashrsplit(handlestr, &bus_name, &dev_name); ++ strslashrsplit(handlestr, p_bus_name, p_dev_name); + } else if (slash_count == 0) { +- err = ifname_map_lookup(dl, str, &bus_name, &dev_name, +- &port_index); ++ err = ifname_map_lookup(dl, str, p_bus_name, p_dev_name, ++ p_port_index); + if (err) { + pr_err("Netdevice \"%s\" not found\n", str); + return err; + } + } +- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, bus_name); +- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, dev_name); +- mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, port_index); + return 0; + } + +@@ -460,55 +467,46 @@ static int port_type_get(const char *typestr, enum devlink_port_type *p_type) + return 0; + } + +-#define BIT(nr) (1UL << (nr)) +-#define DL_OPT_HANDLE BIT(0) +-#define DL_OPT_HANDLEP BIT(1) +-#define DL_OPT_PORT_TYPE BIT(2) +-#define DL_OPT_PORT_COUNT BIT(3) +- +-static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl, +- uint32_t o_required, uint32_t o_optional) ++static int dl_argv_parse(struct dl *dl, uint32_t o_required, ++ uint32_t o_optional) + { ++ struct dl_opts *opts = &dl->opts; + uint32_t o_all = o_required | o_optional; + uint32_t o_found = 0; + int err; + + if (o_required & DL_OPT_HANDLE) { +- err = dl_argv_put_handle(nlh, dl); ++ err = dl_argv_handle(dl, &opts->bus_name, &opts->dev_name); + if (err) + return err; ++ o_found |= DL_OPT_HANDLE; + } else if (o_required & DL_OPT_HANDLEP) { +- err = dl_argv_put_handle_port(nlh, dl); ++ err = dl_argv_handle_port(dl, &opts->bus_name, &opts->dev_name, ++ &opts->port_index); + if (err) + return err; ++ o_found |= DL_OPT_HANDLEP; + } + + while (dl_argc(dl)) { + if (dl_argv_match(dl, "type") && + (o_all & DL_OPT_PORT_TYPE)) { +- enum devlink_port_type port_type; + const char *typestr; + + dl_arg_inc(dl); + err = dl_argv_str(dl, &typestr); + if (err) + return err; +- err = port_type_get(typestr, &port_type); ++ err = port_type_get(typestr, &opts->port_type); + if (err) + return err; +- mnl_attr_put_u16(nlh, DEVLINK_ATTR_PORT_TYPE, +- port_type); + o_found |= DL_OPT_PORT_TYPE; + } else if (dl_argv_match(dl, "count") && + (o_all & DL_OPT_PORT_COUNT)) { +- uint32_t count; +- + dl_arg_inc(dl); +- err = dl_argv_uint32_t(dl, &count); ++ err = dl_argv_uint32_t(dl, &opts->port_count); + if (err) + return err; +- mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_SPLIT_COUNT, +- count); + o_found |= DL_OPT_PORT_COUNT; + } else { + pr_err("Unknown option \"%s\"\n", dl_argv(dl)); +@@ -516,6 +514,8 @@ static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl, + } + } + ++ opts->present = o_found; ++ + if ((o_required & DL_OPT_PORT_TYPE) && !(o_found & DL_OPT_PORT_TYPE)) { + pr_err("Port type option expected.\n"); + return -EINVAL; +@@ -530,6 +530,39 @@ static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl, + return 0; + } + ++static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl) ++{ ++ struct dl_opts *opts = &dl->opts; ++ ++ if (opts->present & DL_OPT_HANDLE) { ++ mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, opts->bus_name); ++ mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, opts->dev_name); ++ } else if (opts->present & DL_OPT_HANDLEP) { ++ mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, opts->bus_name); ++ mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, opts->dev_name); ++ mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, ++ opts->port_index); ++ } ++ if (opts->present & DL_OPT_PORT_TYPE) ++ mnl_attr_put_u16(nlh, DEVLINK_ATTR_PORT_TYPE, ++ opts->port_type); ++ if (opts->present & DL_OPT_PORT_COUNT) ++ mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_SPLIT_COUNT, ++ opts->port_count); ++} ++ ++static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl, ++ uint32_t o_required, uint32_t o_optional) ++{ ++ int err; ++ ++ err = dl_argv_parse(dl, o_required, o_optional); ++ if (err) ++ return err; ++ dl_opts_put(nlh, dl); ++ return 0; ++} ++ + static void cmd_dev_help(void) + { + pr_out("Usage: devlink dev show [ DEV ]\n"); +-- +1.8.3.1 + diff --git a/SOURCES/0192-devlink-introduce-dump-filtering-function.patch b/SOURCES/0192-devlink-introduce-dump-filtering-function.patch new file mode 100644 index 0000000..22398a4 --- /dev/null +++ b/SOURCES/0192-devlink-introduce-dump-filtering-function.patch @@ -0,0 +1,67 @@ +From 548573fb441d1b7752cb54065841c3d30aff8cc2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:33:14 +0200 +Subject: [PATCH] devlink: introduce dump filtering function + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit 707a91c549496 + +commit 707a91c5494962e3f5b358fc866ebb79dc28c3e3 +Author: Jiri Pirko <jiri@mellanox.com> +Date: Fri Apr 15 09:51:49 2016 +0200 + + devlink: introduce dump filtering function + + This function is to be used from dump callbacks to decide if the output + currect output should be filtered off or not. Filtering is based on + previously parsed and stored command line options. + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + devlink/devlink.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/devlink/devlink.c b/devlink/devlink.c +index 0c2132f..d436bbf 100644 +--- a/devlink/devlink.c ++++ b/devlink/devlink.c +@@ -563,6 +563,36 @@ static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl, + return 0; + } + ++static bool dl_dump_filter(struct dl *dl, struct nlattr **tb) ++{ ++ struct dl_opts *opts = &dl->opts; ++ struct nlattr *attr_bus_name = tb[DEVLINK_ATTR_BUS_NAME]; ++ struct nlattr *attr_dev_name = tb[DEVLINK_ATTR_DEV_NAME]; ++ struct nlattr *attr_port_index = tb[DEVLINK_ATTR_PORT_INDEX]; ++ ++ if (opts->present & DL_OPT_HANDLE && ++ attr_bus_name && attr_dev_name) { ++ const char *bus_name = mnl_attr_get_str(attr_bus_name); ++ const char *dev_name = mnl_attr_get_str(attr_dev_name); ++ ++ if (strcmp(bus_name, opts->bus_name) != 0 || ++ strcmp(dev_name, opts->dev_name) != 0) ++ return false; ++ } ++ if (opts->present & DL_OPT_HANDLEP && ++ attr_bus_name && attr_dev_name && attr_port_index) { ++ const char *bus_name = mnl_attr_get_str(attr_bus_name); ++ const char *dev_name = mnl_attr_get_str(attr_dev_name); ++ uint32_t port_index = mnl_attr_get_u32(attr_port_index); ++ ++ if (strcmp(bus_name, opts->bus_name) != 0 || ++ strcmp(dev_name, opts->dev_name) != 0 || ++ port_index != opts->port_index) ++ return false; ++ } ++ return true; ++} ++ + static void cmd_dev_help(void) + { + pr_out("Usage: devlink dev show [ DEV ]\n"); +-- +1.8.3.1 + diff --git a/SOURCES/0193-devlink-allow-to-parse-both-devlink-and-port-handle-.patch b/SOURCES/0193-devlink-allow-to-parse-both-devlink-and-port-handle-.patch new file mode 100644 index 0000000..ecaac1c --- /dev/null +++ b/SOURCES/0193-devlink-allow-to-parse-both-devlink-and-port-handle-.patch @@ -0,0 +1,179 @@ +From 01194858b0ee630c56b7988b3e911ccf008b89ff Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:33:14 +0200 +Subject: [PATCH] devlink: allow to parse both devlink and port handle in the + same time + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit 2f85a9c535874 + +commit 2f85a9c535874e721cfc8b8743325afc93a8b1fa +Author: Jiri Pirko <jiri@mellanox.com> +Date: Fri Apr 15 09:51:50 2016 +0200 + + devlink: allow to parse both devlink and port handle in the same time + + For filtering purposes, it makes sense for used to either specify + devlink handle of port handle. + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + devlink/devlink.c | 109 ++++++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 90 insertions(+), 19 deletions(-) + +diff --git a/devlink/devlink.c b/devlink/devlink.c +index d436bbf..e2e0413 100644 +--- a/devlink/devlink.c ++++ b/devlink/devlink.c +@@ -363,6 +363,12 @@ static int strtouint32_t(const char *str, uint32_t *p_val) + return 0; + } + ++static int __dl_argv_handle(char *str, char **p_bus_name, char **p_dev_name) ++{ ++ strslashrsplit(str, p_bus_name, p_dev_name); ++ return 0; ++} ++ + static int dl_argv_handle(struct dl *dl, char **p_bus_name, char **p_dev_name) + { + char *str = dl_argv_next(dl); +@@ -376,8 +382,40 @@ static int dl_argv_handle(struct dl *dl, char **p_bus_name, char **p_dev_name) + pr_err("Expected \"bus_name/dev_name\".\n"); + return -EINVAL; + } ++ return __dl_argv_handle(str, p_bus_name, p_dev_name); ++} + +- strslashrsplit(str, p_bus_name, p_dev_name); ++static int __dl_argv_handle_port(char *str, ++ char **p_bus_name, char **p_dev_name, ++ uint32_t *p_port_index) ++{ ++ char *handlestr = handlestr; ++ char *portstr = portstr; ++ int err; ++ ++ strslashrsplit(str, &handlestr, &portstr); ++ err = strtouint32_t(portstr, p_port_index); ++ if (err) { ++ pr_err("Port index \"%s\" is not a number or not within range\n", ++ portstr); ++ return err; ++ } ++ strslashrsplit(handlestr, p_bus_name, p_dev_name); ++ return 0; ++} ++ ++static int __dl_argv_handle_port_ifname(struct dl *dl, char *str, ++ char **p_bus_name, char **p_dev_name, ++ uint32_t *p_port_index) ++{ ++ int err; ++ ++ err = ifname_map_lookup(dl, str, p_bus_name, p_dev_name, ++ p_port_index); ++ if (err) { ++ pr_err("Netdevice \"%s\" not found\n", str); ++ return err; ++ } + return 0; + } + +@@ -386,7 +424,6 @@ static int dl_argv_handle_port(struct dl *dl, char **p_bus_name, + { + char *str = dl_argv_next(dl); + unsigned int slash_count; +- int err; + + if (!str) { + pr_err("Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\") expected.\n"); +@@ -398,26 +435,52 @@ static int dl_argv_handle_port(struct dl *dl, char **p_bus_name, + pr_err("Expected \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n"); + return -EINVAL; + } +- + if (slash_count == 2) { +- char *handlestr = handlestr; +- char *portstr = portstr; +- +- err = strslashrsplit(str, &handlestr, &portstr); +- err = strtouint32_t(portstr, p_port_index); +- if (err) { +- pr_err("Port index \"%s\" is not a number or not within range\n", +- portstr); ++ return __dl_argv_handle_port(str, p_bus_name, ++ p_dev_name, p_port_index); ++ } else if (slash_count == 0) { ++ return __dl_argv_handle_port_ifname(dl, str, p_bus_name, ++ p_dev_name, p_port_index); ++ } ++ return 0; ++} ++ ++static int dl_argv_handle_both(struct dl *dl, char **p_bus_name, ++ char **p_dev_name, uint32_t *p_port_index, ++ uint32_t *p_handle_bit) ++{ ++ char *str = dl_argv_next(dl); ++ unsigned int slash_count; ++ int err; ++ ++ if (!str) { ++ pr_err("One of following identifications expected:\n" ++ "Devlink identification (\"bus_name/dev_name\")\n" ++ "Port identification (\"bus_name/dev_name/port_index\" or \"netdev ifname\")\n"); ++ return -EINVAL; ++ } ++ slash_count = strslashcount(str); ++ if (slash_count == 1) { ++ err = __dl_argv_handle(str, p_bus_name, p_dev_name); ++ if (err) + return err; +- } +- strslashrsplit(handlestr, p_bus_name, p_dev_name); ++ *p_handle_bit = DL_OPT_HANDLE; ++ } else if (slash_count == 2) { ++ err = __dl_argv_handle_port(str, p_bus_name, ++ p_dev_name, p_port_index); ++ if (err) ++ return err; ++ *p_handle_bit = DL_OPT_HANDLEP; + } else if (slash_count == 0) { +- err = ifname_map_lookup(dl, str, p_bus_name, p_dev_name, +- p_port_index); +- if (err) { +- pr_err("Netdevice \"%s\" not found\n", str); ++ err = __dl_argv_handle_port_ifname(dl, str, p_bus_name, ++ p_dev_name, p_port_index); ++ if (err) + return err; +- } ++ *p_handle_bit = DL_OPT_HANDLEP; ++ } else { ++ pr_err("Wrong port identification string format.\n"); ++ pr_err("Expected \"bus_name/dev_name\" or \"bus_name/dev_name/port_index\" or \"netdev_ifname\".\n"); ++ return -EINVAL; + } + return 0; + } +@@ -475,7 +538,15 @@ static int dl_argv_parse(struct dl *dl, uint32_t o_required, + uint32_t o_found = 0; + int err; + +- if (o_required & DL_OPT_HANDLE) { ++ if (o_required & DL_OPT_HANDLE && o_required & DL_OPT_HANDLEP) { ++ uint32_t handle_bit = handle_bit; ++ ++ err = dl_argv_handle_both(dl, &opts->bus_name, &opts->dev_name, ++ &opts->port_index, &handle_bit); ++ if (err) ++ return err; ++ o_found |= handle_bit; ++ } else if (o_required & DL_OPT_HANDLE) { + err = dl_argv_handle(dl, &opts->bus_name, &opts->dev_name); + if (err) + return err; +-- +1.8.3.1 + diff --git a/SOURCES/0194-devlink-implement-shared-buffer-support.patch b/SOURCES/0194-devlink-implement-shared-buffer-support.patch new file mode 100644 index 0000000..d75e27e --- /dev/null +++ b/SOURCES/0194-devlink-implement-shared-buffer-support.patch @@ -0,0 +1,807 @@ +From ae919a21446e668c06b5abb440b412487e60ece6 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:33:14 +0200 +Subject: [PATCH] devlink: implement shared buffer support + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit b56700bf8add4 + +commit b56700bf8add4ebb2fe451c85f50602b58a886a2 +Author: Jiri Pirko <jiri@mellanox.com> +Date: Fri Apr 15 09:51:51 2016 +0200 + + devlink: implement shared buffer support + + Implement kernel devlink shared buffer interface. Introduce new object + "sb" and allow to browse the shared buffer parameters and also change + configuration. + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + devlink/devlink.c | 603 +++++++++++++++++++++++++++++++++++++++++++++++- + include/linux/devlink.h | 57 +++++ + 2 files changed, 659 insertions(+), 1 deletion(-) + +diff --git a/devlink/devlink.c b/devlink/devlink.c +index e2e0413..228807f 100644 +--- a/devlink/devlink.c ++++ b/devlink/devlink.c +@@ -114,6 +114,13 @@ static void ifname_map_free(struct ifname_map *ifname_map) + #define DL_OPT_HANDLEP BIT(1) + #define DL_OPT_PORT_TYPE BIT(2) + #define DL_OPT_PORT_COUNT BIT(3) ++#define DL_OPT_SB BIT(4) ++#define DL_OPT_SB_POOL BIT(5) ++#define DL_OPT_SB_SIZE BIT(6) ++#define DL_OPT_SB_TYPE BIT(7) ++#define DL_OPT_SB_THTYPE BIT(8) ++#define DL_OPT_SB_TH BIT(9) ++#define DL_OPT_SB_TC BIT(10) + + struct dl_opts { + uint32_t present; /* flags of present items */ +@@ -122,6 +129,13 @@ struct dl_opts { + uint32_t port_index; + enum devlink_port_type port_type; + uint32_t port_count; ++ uint32_t sb_index; ++ uint16_t sb_pool_index; ++ uint32_t sb_pool_size; ++ enum devlink_sb_pool_type sb_pool_type; ++ enum devlink_sb_threshold_type sb_pool_thtype; ++ uint32_t sb_threshold; ++ uint16_t sb_tc_index; + }; + + struct dl { +@@ -225,6 +239,42 @@ static int attr_cb(const struct nlattr *attr, void *data) + if (type == DEVLINK_ATTR_PORT_IBDEV_NAME && + mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0) + return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_INDEX && ++ mnl_attr_validate(attr, MNL_TYPE_U32) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_SIZE && ++ mnl_attr_validate(attr, MNL_TYPE_U32) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_INGRESS_POOL_COUNT && ++ mnl_attr_validate(attr, MNL_TYPE_U16) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_EGRESS_POOL_COUNT && ++ mnl_attr_validate(attr, MNL_TYPE_U16) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_INGRESS_TC_COUNT && ++ mnl_attr_validate(attr, MNL_TYPE_U16) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_EGRESS_TC_COUNT && ++ mnl_attr_validate(attr, MNL_TYPE_U16) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_POOL_INDEX && ++ mnl_attr_validate(attr, MNL_TYPE_U16) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_POOL_TYPE && ++ mnl_attr_validate(attr, MNL_TYPE_U8) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_POOL_SIZE && ++ mnl_attr_validate(attr, MNL_TYPE_U32) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE && ++ mnl_attr_validate(attr, MNL_TYPE_U8) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_THRESHOLD && ++ mnl_attr_validate(attr, MNL_TYPE_U32) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_TC_INDEX && ++ mnl_attr_validate(attr, MNL_TYPE_U16) < 0) ++ return MNL_CB_ERROR; + tb[type] = attr; + return MNL_CB_OK; + } +@@ -363,6 +413,20 @@ static int strtouint32_t(const char *str, uint32_t *p_val) + return 0; + } + ++static int strtouint16_t(const char *str, uint16_t *p_val) ++{ ++ char *endptr; ++ unsigned long int val; ++ ++ val = strtoul(str, &endptr, 10); ++ if (endptr == str || *endptr != '\0') ++ return -EINVAL; ++ if (val > USHRT_MAX) ++ return -ERANGE; ++ *p_val = val; ++ return 0; ++} ++ + static int __dl_argv_handle(char *str, char **p_bus_name, char **p_dev_name) + { + strslashrsplit(str, p_bus_name, p_dev_name); +@@ -503,6 +567,24 @@ static int dl_argv_uint32_t(struct dl *dl, uint32_t *p_val) + return 0; + } + ++static int dl_argv_uint16_t(struct dl *dl, uint16_t *p_val) ++{ ++ char *str = dl_argv_next(dl); ++ int err; ++ ++ if (!str) { ++ pr_err("Unsigned number argument expected\n"); ++ return -EINVAL; ++ } ++ ++ err = strtouint16_t(str, p_val); ++ if (err) { ++ pr_err("\"%s\" is not a number or not within range\n", str); ++ return err; ++ } ++ return 0; ++} ++ + static int dl_argv_str(struct dl *dl, const char **p_str) + { + const char *str = dl_argv_next(dl); +@@ -530,6 +612,33 @@ static int port_type_get(const char *typestr, enum devlink_port_type *p_type) + return 0; + } + ++static int pool_type_get(const char *typestr, enum devlink_sb_pool_type *p_type) ++{ ++ if (strcmp(typestr, "ingress") == 0) { ++ *p_type = DEVLINK_SB_POOL_TYPE_INGRESS; ++ } else if (strcmp(typestr, "egress") == 0) { ++ *p_type = DEVLINK_SB_POOL_TYPE_EGRESS; ++ } else { ++ pr_err("Unknown pool type \"%s\"\n", typestr); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int threshold_type_get(const char *typestr, ++ enum devlink_sb_threshold_type *p_type) ++{ ++ if (strcmp(typestr, "static") == 0) { ++ *p_type = DEVLINK_SB_THRESHOLD_TYPE_STATIC; ++ } else if (strcmp(typestr, "dynamic") == 0) { ++ *p_type = DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC; ++ } else { ++ pr_err("Unknown threshold type \"%s\"\n", typestr); ++ return -EINVAL; ++ } ++ return 0; ++} ++ + static int dl_argv_parse(struct dl *dl, uint32_t o_required, + uint32_t o_optional) + { +@@ -579,6 +688,66 @@ static int dl_argv_parse(struct dl *dl, uint32_t o_required, + if (err) + return err; + o_found |= DL_OPT_PORT_COUNT; ++ } else if (dl_argv_match(dl, "sb") && ++ (o_all & DL_OPT_SB)) { ++ dl_arg_inc(dl); ++ err = dl_argv_uint32_t(dl, &opts->sb_index); ++ if (err) ++ return err; ++ o_found |= DL_OPT_SB; ++ } else if (dl_argv_match(dl, "pool") && ++ (o_all & DL_OPT_SB_POOL)) { ++ dl_arg_inc(dl); ++ err = dl_argv_uint16_t(dl, &opts->sb_pool_index); ++ if (err) ++ return err; ++ o_found |= DL_OPT_SB_POOL; ++ } else if (dl_argv_match(dl, "size") && ++ (o_all & DL_OPT_SB_SIZE)) { ++ dl_arg_inc(dl); ++ err = dl_argv_uint32_t(dl, &opts->sb_pool_size); ++ if (err) ++ return err; ++ o_found |= DL_OPT_SB_SIZE; ++ } else if (dl_argv_match(dl, "type") && ++ (o_all & DL_OPT_SB_TYPE)) { ++ const char *typestr; ++ ++ dl_arg_inc(dl); ++ err = dl_argv_str(dl, &typestr); ++ if (err) ++ return err; ++ err = pool_type_get(typestr, &opts->sb_pool_type); ++ if (err) ++ return err; ++ o_found |= DL_OPT_SB_TYPE; ++ } else if (dl_argv_match(dl, "thtype") && ++ (o_all & DL_OPT_SB_THTYPE)) { ++ const char *typestr; ++ ++ dl_arg_inc(dl); ++ err = dl_argv_str(dl, &typestr); ++ if (err) ++ return err; ++ err = threshold_type_get(typestr, ++ &opts->sb_pool_thtype); ++ if (err) ++ return err; ++ o_found |= DL_OPT_SB_THTYPE; ++ } else if (dl_argv_match(dl, "th") && ++ (o_all & DL_OPT_SB_TH)) { ++ dl_arg_inc(dl); ++ err = dl_argv_uint32_t(dl, &opts->sb_threshold); ++ if (err) ++ return err; ++ o_found |= DL_OPT_SB_TH; ++ } else if (dl_argv_match(dl, "tc") && ++ (o_all & DL_OPT_SB_TC)) { ++ dl_arg_inc(dl); ++ err = dl_argv_uint16_t(dl, &opts->sb_tc_index); ++ if (err) ++ return err; ++ o_found |= DL_OPT_SB_TC; + } else { + pr_err("Unknown option \"%s\"\n", dl_argv(dl)); + return -EINVAL; +@@ -587,6 +756,11 @@ static int dl_argv_parse(struct dl *dl, uint32_t o_required, + + opts->present = o_found; + ++ if ((o_optional & DL_OPT_SB) && !(o_found & DL_OPT_SB)) { ++ opts->sb_index = 0; ++ opts->present |= DL_OPT_SB; ++ } ++ + if ((o_required & DL_OPT_PORT_TYPE) && !(o_found & DL_OPT_PORT_TYPE)) { + pr_err("Port type option expected.\n"); + return -EINVAL; +@@ -598,6 +772,35 @@ static int dl_argv_parse(struct dl *dl, uint32_t o_required, + return -EINVAL; + } + ++ if ((o_required & DL_OPT_SB_POOL) && !(o_found & DL_OPT_SB_POOL)) { ++ pr_err("Pool index option expected.\n"); ++ return -EINVAL; ++ } ++ ++ if ((o_required & DL_OPT_SB_SIZE) && !(o_found & DL_OPT_SB_SIZE)) { ++ pr_err("Pool size option expected.\n"); ++ return -EINVAL; ++ } ++ ++ if ((o_required & DL_OPT_SB_TYPE) && !(o_found & DL_OPT_SB_TYPE)) { ++ pr_err("Pool type option expected.\n"); ++ return -EINVAL; ++ } ++ ++ if ((o_required & DL_OPT_SB_THTYPE) && !(o_found & DL_OPT_SB_THTYPE)) { ++ pr_err("Pool threshold type option expected.\n"); ++ return -EINVAL; ++ } ++ ++ if ((o_required & DL_OPT_SB_TH) && !(o_found & DL_OPT_SB_TH)) { ++ pr_err("Threshold option expected.\n"); ++ return -EINVAL; ++ } ++ ++ if ((o_required & DL_OPT_SB_TC) && !(o_found & DL_OPT_SB_TC)) { ++ pr_err("TC index option expected.\n"); ++ return -EINVAL; ++ } + return 0; + } + +@@ -620,6 +823,27 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl) + if (opts->present & DL_OPT_PORT_COUNT) + mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_SPLIT_COUNT, + opts->port_count); ++ if (opts->present & DL_OPT_SB) ++ mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_INDEX, ++ opts->sb_index); ++ if (opts->present & DL_OPT_SB_POOL) ++ mnl_attr_put_u16(nlh, DEVLINK_ATTR_SB_POOL_INDEX, ++ opts->sb_pool_index); ++ if (opts->present & DL_OPT_SB_SIZE) ++ mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_POOL_SIZE, ++ opts->sb_pool_size); ++ if (opts->present & DL_OPT_SB_TYPE) ++ mnl_attr_put_u8(nlh, DEVLINK_ATTR_SB_POOL_TYPE, ++ opts->sb_pool_type); ++ if (opts->present & DL_OPT_SB_THTYPE) ++ mnl_attr_put_u8(nlh, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, ++ opts->sb_pool_thtype); ++ if (opts->present & DL_OPT_SB_TH) ++ mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_THRESHOLD, ++ opts->sb_threshold); ++ if (opts->present & DL_OPT_SB_TC) ++ mnl_attr_put_u16(nlh, DEVLINK_ATTR_SB_TC_INDEX, ++ opts->sb_tc_index); + } + + static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl, +@@ -929,6 +1153,380 @@ static int cmd_port(struct dl *dl) + return -ENOENT; + } + ++static void cmd_sb_help(void) ++{ ++ pr_out("Usage: devlink sb show [ DEV [ sb SB_INDEX ] ]\n"); ++ pr_out(" devlink sb pool show [ DEV [ sb SB_INDEX ] pool POOL_INDEX ]\n"); ++ pr_out(" devlink sb pool set DEV [ sb SB_INDEX ] pool POOL_INDEX\n"); ++ pr_out(" size POOL_SIZE thtype { static | dynamic }\n"); ++ pr_out(" devlink sb port pool show [ DEV/PORT_INDEX [ sb SB_INDEX ]\n"); ++ pr_out(" pool POOL_INDEX ]\n"); ++ pr_out(" devlink sb port pool set DEV/PORT_INDEX [ sb SB_INDEX ]\n"); ++ pr_out(" pool POOL_INDEX th THRESHOLD\n"); ++ pr_out(" devlink sb tc bind show [ DEV/PORT_INDEX [ sb SB_INDEX ] tc TC_INDEX\n"); ++ pr_out(" type { ingress | egress } ]\n"); ++ pr_out(" devlink sb tc bind set DEV/PORT_INDEX [ sb SB_INDEX ] tc TC_INDEX\n"); ++ pr_out(" type { ingress | egress } pool POOL_INDEX\n"); ++ pr_out(" th THRESHOLD\n"); ++} ++ ++static void pr_out_sb(struct nlattr **tb) ++{ ++ pr_out_handle(tb); ++ pr_out(": sb %u size %u ing_pools %u eg_pools %u ing_tcs %u eg_tcs %u\n", ++ mnl_attr_get_u32(tb[DEVLINK_ATTR_SB_INDEX]), ++ mnl_attr_get_u32(tb[DEVLINK_ATTR_SB_SIZE]), ++ mnl_attr_get_u16(tb[DEVLINK_ATTR_SB_INGRESS_POOL_COUNT]), ++ mnl_attr_get_u16(tb[DEVLINK_ATTR_SB_EGRESS_POOL_COUNT]), ++ mnl_attr_get_u16(tb[DEVLINK_ATTR_SB_INGRESS_TC_COUNT]), ++ mnl_attr_get_u16(tb[DEVLINK_ATTR_SB_EGRESS_TC_COUNT])); ++} ++ ++static int cmd_sb_show_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_SB_INDEX] || !tb[DEVLINK_ATTR_SB_SIZE] || ++ !tb[DEVLINK_ATTR_SB_INGRESS_POOL_COUNT] || ++ !tb[DEVLINK_ATTR_SB_EGRESS_POOL_COUNT] || ++ !tb[DEVLINK_ATTR_SB_INGRESS_TC_COUNT] || ++ !tb[DEVLINK_ATTR_SB_EGRESS_TC_COUNT]) ++ return MNL_CB_ERROR; ++ pr_out_sb(tb); ++ return MNL_CB_OK; ++} ++ ++static int cmd_sb_show(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; ++ int err; ++ ++ if (dl_argc(dl) == 0) ++ flags |= NLM_F_DUMP; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_SB_GET, flags); ++ ++ if (dl_argc(dl) > 0) { ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, DL_OPT_SB); ++ if (err) ++ return err; ++ } ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_sb_show_cb, NULL); ++} ++ ++static const char *pool_type_name(uint8_t type) ++{ ++ switch (type) { ++ case DEVLINK_SB_POOL_TYPE_INGRESS: return "ingress"; ++ case DEVLINK_SB_POOL_TYPE_EGRESS: return "egress"; ++ default: return "<unknown type>"; ++ } ++} ++ ++static const char *threshold_type_name(uint8_t type) ++{ ++ switch (type) { ++ case DEVLINK_SB_THRESHOLD_TYPE_STATIC: return "static"; ++ case DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC: return "dynamic"; ++ default: return "<unknown type>"; ++ } ++} ++ ++static void pr_out_sb_pool(struct nlattr **tb) ++{ ++ pr_out_handle(tb); ++ pr_out(": sb %u pool %u type %s size %u thtype %s\n", ++ mnl_attr_get_u32(tb[DEVLINK_ATTR_SB_INDEX]), ++ mnl_attr_get_u16(tb[DEVLINK_ATTR_SB_POOL_INDEX]), ++ pool_type_name(mnl_attr_get_u8(tb[DEVLINK_ATTR_SB_POOL_TYPE])), ++ mnl_attr_get_u32(tb[DEVLINK_ATTR_SB_POOL_SIZE]), ++ threshold_type_name(mnl_attr_get_u8(tb[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]))); ++} ++ ++static int cmd_sb_pool_show_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_SB_INDEX] || !tb[DEVLINK_ATTR_SB_POOL_INDEX] || ++ !tb[DEVLINK_ATTR_SB_POOL_TYPE] || !tb[DEVLINK_ATTR_SB_POOL_SIZE] || ++ !tb[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]) ++ return MNL_CB_ERROR; ++ pr_out_sb_pool(tb); ++ return MNL_CB_OK; ++} ++ ++static int cmd_sb_pool_show(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; ++ int err; ++ ++ if (dl_argc(dl) == 0) ++ flags |= NLM_F_DUMP; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_SB_POOL_GET, flags); ++ ++ if (dl_argc(dl) > 0) { ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_SB_POOL, ++ DL_OPT_SB); ++ if (err) ++ return err; ++ } ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_sb_pool_show_cb, NULL); ++} ++ ++static int cmd_sb_pool_set(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ int err; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_SB_POOL_SET, ++ NLM_F_REQUEST | NLM_F_ACK); ++ ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_SB_POOL | ++ DL_OPT_SB_SIZE | DL_OPT_SB_THTYPE, DL_OPT_SB); ++ if (err) ++ return err; ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); ++} ++ ++static int cmd_sb_pool(struct dl *dl) ++{ ++ if (dl_argv_match(dl, "help")) { ++ cmd_sb_help(); ++ return 0; ++ } else if (dl_argv_match(dl, "show") || ++ dl_argv_match(dl, "list") || dl_no_arg(dl)) { ++ dl_arg_inc(dl); ++ return cmd_sb_pool_show(dl); ++ } else if (dl_argv_match(dl, "set")) { ++ dl_arg_inc(dl); ++ return cmd_sb_pool_set(dl); ++ } ++ pr_err("Command \"%s\" not found\n", dl_argv(dl)); ++ return -ENOENT; ++} ++ ++static void pr_out_sb_port_pool(struct dl *dl, struct nlattr **tb) ++{ ++ pr_out_port_handle_nice(dl, tb); ++ pr_out(": sb %u pool %u threshold %u\n", ++ mnl_attr_get_u32(tb[DEVLINK_ATTR_SB_INDEX]), ++ mnl_attr_get_u16(tb[DEVLINK_ATTR_SB_POOL_INDEX]), ++ mnl_attr_get_u32(tb[DEVLINK_ATTR_SB_THRESHOLD])); ++} ++ ++static int cmd_sb_port_pool_show_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct dl *dl = data; ++ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_PORT_INDEX] || !tb[DEVLINK_ATTR_SB_INDEX] || ++ !tb[DEVLINK_ATTR_SB_POOL_INDEX] || !tb[DEVLINK_ATTR_SB_THRESHOLD]) ++ return MNL_CB_ERROR; ++ pr_out_sb_port_pool(dl, tb); ++ return MNL_CB_OK; ++} ++ ++static int cmd_sb_port_pool_show(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; ++ int err; ++ ++ if (dl_argc(dl) == 0) ++ flags |= NLM_F_DUMP; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_SB_PORT_POOL_GET, flags); ++ ++ if (dl_argc(dl) > 0) { ++ err = dl_argv_parse_put(nlh, dl, ++ DL_OPT_HANDLEP | DL_OPT_SB_POOL, ++ DL_OPT_SB); ++ if (err) ++ return err; ++ } ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_sb_port_pool_show_cb, dl); ++} ++ ++static int cmd_sb_port_pool_set(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ int err; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_SB_PORT_POOL_SET, ++ NLM_F_REQUEST | NLM_F_ACK); ++ ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_SB_POOL | ++ DL_OPT_SB_TH, DL_OPT_SB); ++ if (err) ++ return err; ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); ++} ++ ++static int cmd_sb_port_pool(struct dl *dl) ++{ ++ if (dl_argv_match(dl, "help")) { ++ cmd_sb_help(); ++ return 0; ++ } else if (dl_argv_match(dl, "show") || ++ dl_argv_match(dl, "list") || dl_no_arg(dl)) { ++ dl_arg_inc(dl); ++ return cmd_sb_port_pool_show(dl); ++ } else if (dl_argv_match(dl, "set")) { ++ dl_arg_inc(dl); ++ return cmd_sb_port_pool_set(dl); ++ } ++ pr_err("Command \"%s\" not found\n", dl_argv(dl)); ++ return -ENOENT; ++} ++ ++static int cmd_sb_port(struct dl *dl) ++{ ++ if (dl_argv_match(dl, "help") || dl_no_arg(dl)) { ++ cmd_sb_help(); ++ return 0; ++ } else if (dl_argv_match(dl, "pool")) { ++ dl_arg_inc(dl); ++ return cmd_sb_port_pool(dl); ++ } ++ pr_err("Command \"%s\" not found\n", dl_argv(dl)); ++ return -ENOENT; ++} ++ ++static void pr_out_sb_tc_bind(struct dl *dl, struct nlattr **tb) ++{ ++ pr_out_port_handle_nice(dl, tb); ++ pr_out(": sb %u tc %u type %s pool %u threshold %u\n", ++ mnl_attr_get_u32(tb[DEVLINK_ATTR_SB_INDEX]), ++ mnl_attr_get_u16(tb[DEVLINK_ATTR_SB_TC_INDEX]), ++ pool_type_name(mnl_attr_get_u8(tb[DEVLINK_ATTR_SB_POOL_TYPE])), ++ mnl_attr_get_u16(tb[DEVLINK_ATTR_SB_POOL_INDEX]), ++ mnl_attr_get_u32(tb[DEVLINK_ATTR_SB_THRESHOLD])); ++} ++ ++static int cmd_sb_tc_bind_show_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct dl *dl = data; ++ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_PORT_INDEX] || !tb[DEVLINK_ATTR_SB_INDEX] || ++ !tb[DEVLINK_ATTR_SB_TC_INDEX] || !tb[DEVLINK_ATTR_SB_POOL_TYPE] || ++ !tb[DEVLINK_ATTR_SB_POOL_INDEX] || !tb[DEVLINK_ATTR_SB_THRESHOLD]) ++ return MNL_CB_ERROR; ++ pr_out_sb_tc_bind(dl, tb); ++ return MNL_CB_OK; ++} ++ ++static int cmd_sb_tc_bind_show(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; ++ int err; ++ ++ if (dl_argc(dl) == 0) ++ flags |= NLM_F_DUMP; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_SB_TC_POOL_BIND_GET, flags); ++ ++ if (dl_argc(dl) > 0) { ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_SB_TC | ++ DL_OPT_SB_TYPE, DL_OPT_SB); ++ if (err) ++ return err; ++ } ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_sb_tc_bind_show_cb, dl); ++} ++ ++static int cmd_sb_tc_bind_set(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ int err; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_SB_TC_POOL_BIND_SET, ++ NLM_F_REQUEST | NLM_F_ACK); ++ ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_SB_TC | ++ DL_OPT_SB_TYPE | DL_OPT_SB_POOL | DL_OPT_SB_TH, ++ DL_OPT_SB); ++ if (err) ++ return err; ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); ++} ++ ++static int cmd_sb_tc_bind(struct dl *dl) ++{ ++ if (dl_argv_match(dl, "help")) { ++ cmd_sb_help(); ++ return 0; ++ } else if (dl_argv_match(dl, "show") || ++ dl_argv_match(dl, "list") || dl_no_arg(dl)) { ++ dl_arg_inc(dl); ++ return cmd_sb_tc_bind_show(dl); ++ } else if (dl_argv_match(dl, "set")) { ++ dl_arg_inc(dl); ++ return cmd_sb_tc_bind_set(dl); ++ } ++ pr_err("Command \"%s\" not found\n", dl_argv(dl)); ++ return -ENOENT; ++} ++ ++static int cmd_sb_tc(struct dl *dl) ++{ ++ if (dl_argv_match(dl, "help") || dl_no_arg(dl)) { ++ cmd_sb_help(); ++ return 0; ++ } else if (dl_argv_match(dl, "bind")) { ++ dl_arg_inc(dl); ++ return cmd_sb_tc_bind(dl); ++ } ++ pr_err("Command \"%s\" not found\n", dl_argv(dl)); ++ return -ENOENT; ++} ++ ++static int cmd_sb(struct dl *dl) ++{ ++ if (dl_argv_match(dl, "help")) { ++ cmd_sb_help(); ++ return 0; ++ } else if (dl_argv_match(dl, "show") || ++ dl_argv_match(dl, "list") || dl_no_arg(dl)) { ++ dl_arg_inc(dl); ++ return cmd_sb_show(dl); ++ } else if (dl_argv_match(dl, "pool")) { ++ dl_arg_inc(dl); ++ return cmd_sb_pool(dl); ++ } else if (dl_argv_match(dl, "port")) { ++ dl_arg_inc(dl); ++ return cmd_sb_port(dl); ++ } else if (dl_argv_match(dl, "tc")) { ++ dl_arg_inc(dl); ++ return cmd_sb_tc(dl); ++ } ++ pr_err("Command \"%s\" not found\n", dl_argv(dl)); ++ return -ENOENT; ++} ++ + static const char *cmd_name(uint8_t cmd) + { + switch (cmd) { +@@ -1064,7 +1662,7 @@ static int cmd_mon(struct dl *dl) + static void help(void) + { + pr_out("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n" +- "where OBJECT := { dev | port | monitor }\n" ++ "where OBJECT := { dev | port | sb | monitor }\n" + " OPTIONS := { -V[ersion] | -n[no-nice-names] }\n"); + } + +@@ -1079,6 +1677,9 @@ static int dl_cmd(struct dl *dl) + } else if (dl_argv_match(dl, "port")) { + dl_arg_inc(dl); + return cmd_port(dl); ++ } else if (dl_argv_match(dl, "sb")) { ++ dl_arg_inc(dl); ++ return cmd_sb(dl); + } else if (dl_argv_match(dl, "monitor")) { + dl_arg_inc(dl); + return cmd_mon(dl); +diff --git a/include/linux/devlink.h b/include/linux/devlink.h +index a96e1a0..d40699f 100644 +--- a/include/linux/devlink.h ++++ b/include/linux/devlink.h +@@ -33,6 +33,26 @@ enum devlink_command { + DEVLINK_CMD_PORT_SPLIT, + DEVLINK_CMD_PORT_UNSPLIT, + ++ DEVLINK_CMD_SB_GET, /* can dump */ ++ DEVLINK_CMD_SB_SET, ++ DEVLINK_CMD_SB_NEW, ++ DEVLINK_CMD_SB_DEL, ++ ++ DEVLINK_CMD_SB_POOL_GET, /* can dump */ ++ DEVLINK_CMD_SB_POOL_SET, ++ DEVLINK_CMD_SB_POOL_NEW, ++ DEVLINK_CMD_SB_POOL_DEL, ++ ++ DEVLINK_CMD_SB_PORT_POOL_GET, /* can dump */ ++ DEVLINK_CMD_SB_PORT_POOL_SET, ++ DEVLINK_CMD_SB_PORT_POOL_NEW, ++ DEVLINK_CMD_SB_PORT_POOL_DEL, ++ ++ DEVLINK_CMD_SB_TC_POOL_BIND_GET, /* can dump */ ++ DEVLINK_CMD_SB_TC_POOL_BIND_SET, ++ DEVLINK_CMD_SB_TC_POOL_BIND_NEW, ++ DEVLINK_CMD_SB_TC_POOL_BIND_DEL, ++ + /* add new commands above here */ + + __DEVLINK_CMD_MAX, +@@ -46,6 +66,31 @@ enum devlink_port_type { + DEVLINK_PORT_TYPE_IB, + }; + ++enum devlink_sb_pool_type { ++ DEVLINK_SB_POOL_TYPE_INGRESS, ++ DEVLINK_SB_POOL_TYPE_EGRESS, ++}; ++ ++/* static threshold - limiting the maximum number of bytes. ++ * dynamic threshold - limiting the maximum number of bytes ++ * based on the currently available free space in the shared buffer pool. ++ * In this mode, the maximum quota is calculated based ++ * on the following formula: ++ * max_quota = alpha / (1 + alpha) * Free_Buffer ++ * While Free_Buffer is the amount of none-occupied buffer associated to ++ * the relevant pool. ++ * The value range which can be passed is 0-20 and serves ++ * for computation of alpha by following formula: ++ * alpha = 2 ^ (passed_value - 10) ++ */ ++ ++enum devlink_sb_threshold_type { ++ DEVLINK_SB_THRESHOLD_TYPE_STATIC, ++ DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC, ++}; ++ ++#define DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX 20 ++ + enum devlink_attr { + /* don't change the order or add anything between, this is ABI! */ + DEVLINK_ATTR_UNSPEC, +@@ -62,6 +107,18 @@ enum devlink_attr { + DEVLINK_ATTR_PORT_IBDEV_NAME, /* string */ + DEVLINK_ATTR_PORT_SPLIT_COUNT, /* u32 */ + DEVLINK_ATTR_PORT_SPLIT_GROUP, /* u32 */ ++ DEVLINK_ATTR_SB_INDEX, /* u32 */ ++ DEVLINK_ATTR_SB_SIZE, /* u32 */ ++ DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, /* u16 */ ++ DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, /* u16 */ ++ DEVLINK_ATTR_SB_INGRESS_TC_COUNT, /* u16 */ ++ DEVLINK_ATTR_SB_EGRESS_TC_COUNT, /* u16 */ ++ DEVLINK_ATTR_SB_POOL_INDEX, /* u16 */ ++ DEVLINK_ATTR_SB_POOL_TYPE, /* u8 */ ++ DEVLINK_ATTR_SB_POOL_SIZE, /* u32 */ ++ DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, /* u8 */ ++ DEVLINK_ATTR_SB_THRESHOLD, /* u32 */ ++ DEVLINK_ATTR_SB_TC_INDEX, /* u16 */ + + /* add new attributes above here, update the policy in devlink.c */ + +-- +1.8.3.1 + diff --git a/SOURCES/0195-devlink-implement-shared-buffer-occupancy-control.patch b/SOURCES/0195-devlink-implement-shared-buffer-occupancy-control.patch new file mode 100644 index 0000000..103e564 --- /dev/null +++ b/SOURCES/0195-devlink-implement-shared-buffer-occupancy-control.patch @@ -0,0 +1,453 @@ +From fbd89ab4f4ffdcbda971a3a4ea6096cc4971d04e Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:33:14 +0200 +Subject: [PATCH] devlink: implement shared buffer occupancy control + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit a60ebcb6f34f4 + +commit a60ebcb6f34f4c43cba092f52b1150d7fb1deec5 +Author: Jiri Pirko <jiri@mellanox.com> +Date: Fri Apr 15 09:51:52 2016 +0200 + + devlink: implement shared buffer occupancy control + + Use kernel shared buffer occupancy control commands to make snapshot and + clear occupancy watermarks. Also, allow to show occupancy values in a + nice way. + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + devlink/devlink.c | 349 ++++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/devlink.h | 6 + + 2 files changed, 355 insertions(+) + +diff --git a/devlink/devlink.c b/devlink/devlink.c +index 228807f..ffefa86 100644 +--- a/devlink/devlink.c ++++ b/devlink/devlink.c +@@ -27,6 +27,12 @@ + + #define pr_err(args...) fprintf(stderr, ##args) + #define pr_out(args...) fprintf(stdout, ##args) ++#define pr_out_sp(num, args...) \ ++ do { \ ++ int ret = fprintf(stdout, ##args); \ ++ if (ret < num) \ ++ fprintf(stdout, "%*s", num - ret, ""); \ ++ } while (0) + + static int _mnlg_socket_recv_run(struct mnlg_socket *nlg, + mnl_cb_t data_cb, void *data) +@@ -275,6 +281,12 @@ static int attr_cb(const struct nlattr *attr, void *data) + if (type == DEVLINK_ATTR_SB_TC_INDEX && + mnl_attr_validate(attr, MNL_TYPE_U16) < 0) + return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_OCC_CUR && ++ mnl_attr_validate(attr, MNL_TYPE_U32) < 0) ++ return MNL_CB_ERROR; ++ if (type == DEVLINK_ATTR_SB_OCC_MAX && ++ mnl_attr_validate(attr, MNL_TYPE_U32) < 0) ++ return MNL_CB_ERROR; + tb[type] = attr; + return MNL_CB_OK; + } +@@ -864,6 +876,7 @@ static bool dl_dump_filter(struct dl *dl, struct nlattr **tb) + struct nlattr *attr_bus_name = tb[DEVLINK_ATTR_BUS_NAME]; + struct nlattr *attr_dev_name = tb[DEVLINK_ATTR_DEV_NAME]; + struct nlattr *attr_port_index = tb[DEVLINK_ATTR_PORT_INDEX]; ++ struct nlattr *attr_sb_index = tb[DEVLINK_ATTR_SB_INDEX]; + + if (opts->present & DL_OPT_HANDLE && + attr_bus_name && attr_dev_name) { +@@ -885,6 +898,12 @@ static bool dl_dump_filter(struct dl *dl, struct nlattr **tb) + port_index != opts->port_index) + return false; + } ++ if (opts->present & DL_OPT_SB && attr_sb_index) { ++ uint32_t sb_index = mnl_attr_get_u32(attr_sb_index); ++ ++ if (sb_index != opts->sb_index) ++ return false; ++ } + return true; + } + +@@ -1168,6 +1187,9 @@ static void cmd_sb_help(void) + pr_out(" devlink sb tc bind set DEV/PORT_INDEX [ sb SB_INDEX ] tc TC_INDEX\n"); + pr_out(" type { ingress | egress } pool POOL_INDEX\n"); + pr_out(" th THRESHOLD\n"); ++ pr_out(" devlink sb occupancy show { DEV | DEV/PORT_INDEX } [ sb SB_INDEX ]\n"); ++ pr_out(" devlink sb occupancy snapshot DEV [ sb SB_INDEX ]\n"); ++ pr_out(" devlink sb occupancy clearmax DEV [ sb SB_INDEX ]\n"); + } + + static void pr_out_sb(struct nlattr **tb) +@@ -1504,6 +1526,330 @@ static int cmd_sb_tc(struct dl *dl) + return -ENOENT; + } + ++struct occ_item { ++ struct list_head list; ++ uint32_t index; ++ uint32_t cur; ++ uint32_t max; ++ uint32_t bound_pool_index; ++}; ++ ++struct occ_port { ++ struct list_head list; ++ char *bus_name; ++ char *dev_name; ++ uint32_t port_index; ++ uint32_t sb_index; ++ struct list_head pool_list; ++ struct list_head ing_tc_list; ++ struct list_head eg_tc_list; ++}; ++ ++struct occ_show { ++ struct dl *dl; ++ int err; ++ struct list_head port_list; ++}; ++ ++static struct occ_item *occ_item_alloc(void) ++{ ++ return calloc(1, sizeof(struct occ_item)); ++} ++ ++static void occ_item_free(struct occ_item *occ_item) ++{ ++ free(occ_item); ++} ++ ++static struct occ_port *occ_port_alloc(uint32_t port_index) ++{ ++ struct occ_port *occ_port; ++ ++ occ_port = calloc(1, sizeof(*occ_port)); ++ if (!occ_port) ++ return NULL; ++ occ_port->port_index = port_index; ++ INIT_LIST_HEAD(&occ_port->pool_list); ++ INIT_LIST_HEAD(&occ_port->ing_tc_list); ++ INIT_LIST_HEAD(&occ_port->eg_tc_list); ++ return occ_port; ++} ++ ++static void occ_port_free(struct occ_port *occ_port) ++{ ++ struct occ_item *occ_item, *tmp; ++ ++ list_for_each_entry_safe(occ_item, tmp, &occ_port->pool_list, list) ++ occ_item_free(occ_item); ++ list_for_each_entry_safe(occ_item, tmp, &occ_port->ing_tc_list, list) ++ occ_item_free(occ_item); ++ list_for_each_entry_safe(occ_item, tmp, &occ_port->eg_tc_list, list) ++ occ_item_free(occ_item); ++} ++ ++static struct occ_show *occ_show_alloc(struct dl *dl) ++{ ++ struct occ_show *occ_show; ++ ++ occ_show = calloc(1, sizeof(*occ_show)); ++ if (!occ_show) ++ return NULL; ++ occ_show->dl = dl; ++ INIT_LIST_HEAD(&occ_show->port_list); ++ return occ_show; ++} ++ ++static void occ_show_free(struct occ_show *occ_show) ++{ ++ struct occ_port *occ_port, *tmp; ++ ++ list_for_each_entry_safe(occ_port, tmp, &occ_show->port_list, list) ++ occ_port_free(occ_port); ++} ++ ++static struct occ_port *occ_port_get(struct occ_show *occ_show, ++ struct nlattr **tb) ++{ ++ struct occ_port *occ_port; ++ uint32_t port_index; ++ ++ port_index = mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_INDEX]); ++ ++ list_for_each_entry_reverse(occ_port, &occ_show->port_list, list) { ++ if (occ_port->port_index == port_index) ++ return occ_port; ++ } ++ occ_port = occ_port_alloc(port_index); ++ if (!occ_port) ++ return NULL; ++ list_add_tail(&occ_port->list, &occ_show->port_list); ++ return occ_port; ++} ++ ++static void pr_out_occ_show_item_list(const char *label, struct list_head *list, ++ bool bound_pool) ++{ ++ struct occ_item *occ_item; ++ int i = 1; ++ ++ pr_out_sp(7, " %s:", label); ++ list_for_each_entry(occ_item, list, list) { ++ if ((i - 1) % 4 == 0 && i != 1) ++ pr_out_sp(7, " "); ++ if (bound_pool) ++ pr_out_sp(7, "%2u(%u):", occ_item->index, ++ occ_item->bound_pool_index); ++ else ++ pr_out_sp(7, "%2u:", occ_item->index); ++ pr_out_sp(15, "%7u/%u", occ_item->cur, occ_item->max); ++ if (i++ % 4 == 0) ++ pr_out("\n"); ++ } ++ if ((i - 1) % 4 != 0) ++ pr_out("\n"); ++} ++ ++static void pr_out_occ_show_port(struct occ_port *occ_port) ++{ ++ pr_out_occ_show_item_list("pool", &occ_port->pool_list, false); ++ pr_out_occ_show_item_list("itc", &occ_port->ing_tc_list, true); ++ pr_out_occ_show_item_list("etc", &occ_port->eg_tc_list, true); ++} ++ ++static void pr_out_occ_show(struct occ_show *occ_show) ++{ ++ struct dl *dl = occ_show->dl; ++ struct dl_opts *opts = &dl->opts; ++ struct occ_port *occ_port; ++ ++ list_for_each_entry(occ_port, &occ_show->port_list, list) { ++ __pr_out_port_handle_nice(dl, opts->bus_name, opts->dev_name, ++ occ_port->port_index); ++ pr_out(":\n"); ++ pr_out_occ_show_port(occ_port); ++ } ++} ++ ++static void cmd_sb_occ_port_pool_process(struct occ_show *occ_show, ++ struct nlattr **tb) ++{ ++ struct occ_port *occ_port; ++ struct occ_item *occ_item; ++ ++ if (occ_show->err || !dl_dump_filter(occ_show->dl, tb)) ++ return; ++ ++ occ_port = occ_port_get(occ_show, tb); ++ if (!occ_port) { ++ occ_show->err = -ENOMEM; ++ return; ++ } ++ ++ occ_item = occ_item_alloc(); ++ if (!occ_item) { ++ occ_show->err = -ENOMEM; ++ return; ++ } ++ occ_item->index = mnl_attr_get_u16(tb[DEVLINK_ATTR_SB_POOL_INDEX]); ++ occ_item->cur = mnl_attr_get_u32(tb[DEVLINK_ATTR_SB_OCC_CUR]); ++ occ_item->max = mnl_attr_get_u32(tb[DEVLINK_ATTR_SB_OCC_MAX]); ++ list_add_tail(&occ_item->list, &occ_port->pool_list); ++} ++ ++static int cmd_sb_occ_port_pool_process_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct occ_show *occ_show = data; ++ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_PORT_INDEX] || !tb[DEVLINK_ATTR_SB_INDEX] || ++ !tb[DEVLINK_ATTR_SB_POOL_INDEX] || ++ !tb[DEVLINK_ATTR_SB_OCC_CUR] || !tb[DEVLINK_ATTR_SB_OCC_MAX]) ++ return MNL_CB_ERROR; ++ cmd_sb_occ_port_pool_process(occ_show, tb); ++ return MNL_CB_OK; ++} ++ ++static void cmd_sb_occ_tc_pool_process(struct occ_show *occ_show, ++ struct nlattr **tb) ++{ ++ struct occ_port *occ_port; ++ struct occ_item *occ_item; ++ uint8_t pool_type; ++ ++ if (occ_show->err || !dl_dump_filter(occ_show->dl, tb)) ++ return; ++ ++ occ_port = occ_port_get(occ_show, tb); ++ if (!occ_port) { ++ occ_show->err = -ENOMEM; ++ return; ++ } ++ ++ occ_item = occ_item_alloc(); ++ if (!occ_item) { ++ occ_show->err = -ENOMEM; ++ return; ++ } ++ occ_item->index = mnl_attr_get_u16(tb[DEVLINK_ATTR_SB_TC_INDEX]); ++ occ_item->cur = mnl_attr_get_u32(tb[DEVLINK_ATTR_SB_OCC_CUR]); ++ occ_item->max = mnl_attr_get_u32(tb[DEVLINK_ATTR_SB_OCC_MAX]); ++ occ_item->bound_pool_index = ++ mnl_attr_get_u16(tb[DEVLINK_ATTR_SB_POOL_INDEX]); ++ pool_type = mnl_attr_get_u8(tb[DEVLINK_ATTR_SB_POOL_TYPE]); ++ if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS) ++ list_add_tail(&occ_item->list, &occ_port->ing_tc_list); ++ else if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS) ++ list_add_tail(&occ_item->list, &occ_port->eg_tc_list); ++ else ++ occ_item_free(occ_item); ++} ++ ++static int cmd_sb_occ_tc_pool_process_cb(const struct nlmsghdr *nlh, void *data) ++{ ++ struct occ_show *occ_show = data; ++ struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {}; ++ struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); ++ ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_PORT_INDEX] || !tb[DEVLINK_ATTR_SB_INDEX] || ++ !tb[DEVLINK_ATTR_SB_TC_INDEX] || !tb[DEVLINK_ATTR_SB_POOL_TYPE] || ++ !tb[DEVLINK_ATTR_SB_POOL_INDEX] || ++ !tb[DEVLINK_ATTR_SB_OCC_CUR] || !tb[DEVLINK_ATTR_SB_OCC_MAX]) ++ return MNL_CB_ERROR; ++ cmd_sb_occ_tc_pool_process(occ_show, tb); ++ return MNL_CB_OK; ++} ++ ++static int cmd_sb_occ_show(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ struct occ_show *occ_show; ++ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP; ++ int err; ++ ++ err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_HANDLEP, DL_OPT_SB); ++ if (err) ++ return err; ++ ++ occ_show = occ_show_alloc(dl); ++ if (!occ_show) ++ return -ENOMEM; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_SB_PORT_POOL_GET, flags); ++ ++ err = _mnlg_socket_sndrcv(dl->nlg, nlh, ++ cmd_sb_occ_port_pool_process_cb, occ_show); ++ if (err) ++ goto out; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_SB_TC_POOL_BIND_GET, flags); ++ ++ err = _mnlg_socket_sndrcv(dl->nlg, nlh, ++ cmd_sb_occ_tc_pool_process_cb, occ_show); ++ if (err) ++ goto out; ++ ++ pr_out_occ_show(occ_show); ++ ++out: ++ occ_show_free(occ_show); ++ return err; ++} ++ ++static int cmd_sb_occ_snapshot(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ int err; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_SB_OCC_SNAPSHOT, ++ NLM_F_REQUEST | NLM_F_ACK); ++ ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, DL_OPT_SB); ++ if (err) ++ return err; ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); ++} ++ ++static int cmd_sb_occ_clearmax(struct dl *dl) ++{ ++ struct nlmsghdr *nlh; ++ int err; ++ ++ nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_SB_OCC_MAX_CLEAR, ++ NLM_F_REQUEST | NLM_F_ACK); ++ ++ err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, DL_OPT_SB); ++ if (err) ++ return err; ++ ++ return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); ++} ++ ++static int cmd_sb_occ(struct dl *dl) ++{ ++ if (dl_argv_match(dl, "help") || dl_no_arg(dl)) { ++ cmd_sb_help(); ++ return 0; ++ } else if (dl_argv_match(dl, "show") || ++ dl_argv_match(dl, "list")) { ++ dl_arg_inc(dl); ++ return cmd_sb_occ_show(dl); ++ } else if (dl_argv_match(dl, "snapshot")) { ++ dl_arg_inc(dl); ++ return cmd_sb_occ_snapshot(dl); ++ } else if (dl_argv_match(dl, "clearmax")) { ++ dl_arg_inc(dl); ++ return cmd_sb_occ_clearmax(dl); ++ } ++ pr_err("Command \"%s\" not found\n", dl_argv(dl)); ++ return -ENOENT; ++} ++ + static int cmd_sb(struct dl *dl) + { + if (dl_argv_match(dl, "help")) { +@@ -1522,6 +1868,9 @@ static int cmd_sb(struct dl *dl) + } else if (dl_argv_match(dl, "tc")) { + dl_arg_inc(dl); + return cmd_sb_tc(dl); ++ } else if (dl_argv_match(dl, "occupancy")) { ++ dl_arg_inc(dl); ++ return cmd_sb_occ(dl); + } + pr_err("Command \"%s\" not found\n", dl_argv(dl)); + return -ENOENT; +diff --git a/include/linux/devlink.h b/include/linux/devlink.h +index d40699f..0e21d00 100644 +--- a/include/linux/devlink.h ++++ b/include/linux/devlink.h +@@ -53,6 +53,10 @@ enum devlink_command { + DEVLINK_CMD_SB_TC_POOL_BIND_NEW, + DEVLINK_CMD_SB_TC_POOL_BIND_DEL, + ++ /* Shared buffer occupancy monitoring commands */ ++ DEVLINK_CMD_SB_OCC_SNAPSHOT, ++ DEVLINK_CMD_SB_OCC_MAX_CLEAR, ++ + /* add new commands above here */ + + __DEVLINK_CMD_MAX, +@@ -119,6 +123,8 @@ enum devlink_attr { + DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, /* u8 */ + DEVLINK_ATTR_SB_THRESHOLD, /* u32 */ + DEVLINK_ATTR_SB_TC_INDEX, /* u16 */ ++ DEVLINK_ATTR_SB_OCC_CUR, /* u32 */ ++ DEVLINK_ATTR_SB_OCC_MAX, /* u32 */ + + /* add new attributes above here, update the policy in devlink.c */ + +-- +1.8.3.1 + diff --git a/SOURCES/0196-devlink-add-manpage-for-shared-buffer.patch b/SOURCES/0196-devlink-add-manpage-for-shared-buffer.patch new file mode 100644 index 0000000..9f364a1 --- /dev/null +++ b/SOURCES/0196-devlink-add-manpage-for-shared-buffer.patch @@ -0,0 +1,383 @@ +From 8a5444de3226e5acb78307b79146f0456b4244cf Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Sat, 9 Jul 2016 11:33:14 +0200 +Subject: [PATCH] devlink: add manpage for shared buffer + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1342515 +Upstream Status: iproute2.git commit 4bf138d6d2747 + +commit 4bf138d6d2747b198fc0a78f5fe4e1c9287e9e90 +Author: Jiri Pirko <jiri@mellanox.com> +Date: Fri Apr 15 09:51:53 2016 +0200 + + devlink: add manpage for shared buffer + + Manpage for devlink "sb" object. + + Signed-off-by: Jiri Pirko <jiri@mellanox.com> +--- + man/man8/devlink-dev.8 | 1 + + man/man8/devlink-monitor.8 | 1 + + man/man8/devlink-port.8 | 1 + + man/man8/devlink-sb.8 | 313 +++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 316 insertions(+) + create mode 100644 man/man8/devlink-sb.8 + +diff --git a/man/man8/devlink-dev.8 b/man/man8/devlink-dev.8 +index af96a29..62bcead 100644 +--- a/man/man8/devlink-dev.8 ++++ b/man/man8/devlink-dev.8 +@@ -52,6 +52,7 @@ Shows the state of specified devlink device. + .SH SEE ALSO + .BR devlink (8), + .BR devlink-port (8), ++.BR devlink-sb (8), + .BR devlink-monitor (8), + .br + +diff --git a/man/man8/devlink-monitor.8 b/man/man8/devlink-monitor.8 +index 98134c3..13fe641 100644 +--- a/man/man8/devlink-monitor.8 ++++ b/man/man8/devlink-monitor.8 +@@ -29,6 +29,7 @@ opens Devlink Netlink socket, listens on it and dumps state changes. + .SH SEE ALSO + .BR devlink (8), + .BR devlink-dev (8), ++.BR devlink-sb (8), + .BR devlink-port (8), + .br + +diff --git a/man/man8/devlink-port.8 b/man/man8/devlink-port.8 +index d78837c..a639d01 100644 +--- a/man/man8/devlink-port.8 ++++ b/man/man8/devlink-port.8 +@@ -120,6 +120,7 @@ Unplit the specified previously split devlink port. + .SH SEE ALSO + .BR devlink (8), + .BR devlink-dev (8), ++.BR devlink-sb (8), + .BR devlink-monitor (8), + .br + +diff --git a/man/man8/devlink-sb.8 b/man/man8/devlink-sb.8 +new file mode 100644 +index 0000000..ffb5553 +--- /dev/null ++++ b/man/man8/devlink-sb.8 +@@ -0,0 +1,313 @@ ++.TH DEVLINK\-SB 8 "14 Apr 2016" "iproute2" "Linux" ++.SH NAME ++devlink-sb \- devlink shared buffer configuration ++.SH SYNOPSIS ++.sp ++.ad l ++.in +8 ++.ti -8 ++.B devlink ++.RI "[ " OPTIONS " ]" ++.B sb ++.RI " { " COMMAND " | " ++.BR help " }" ++.sp ++ ++.ti -8 ++.IR OPTIONS " := { " ++\fB\-V\fR[\fIersion\fR] | ++\fB\-n\fR[\fIno-nice-names\fR] } ++ ++.ti -8 ++.BR "devlink sb show " ++.RI "[ " DEV " [ " ++.B sb ++.IR SB_INDEX " ] ]" ++ ++.ti -8 ++.BR "devlink sb pool show " ++.RI "[ " DEV " [ " ++.B sb ++.IR SB_INDEX " ] " ++.br ++.B pool ++.IR POOL_INDEX " ]" ++ ++.ti -8 ++.BI "devlink sb pool set " DEV " ++.RB "[ " sb ++.IR SB_INDEX " ] " ++.br ++.BI pool " POOL_INDEX " ++.br ++.BI size " POOL_SIZE " ++.br ++.BR thtype " { " static " | " dynamic " }" ++ ++.ti -8 ++.BR "devlink sb port pool show " ++.RI "[ " DEV/PORT_INDEX " [ " ++.B sb ++.IR SB_INDEX " ] " ++.br ++.B pool ++.IR POOL_INDEX " ]" ++ ++.ti -8 ++.BI "devlink sb port pool set " DEV/PORT_INDEX " ++.RB "[ " sb ++.IR SB_INDEX " ] " ++.br ++.BI pool " POOL_INDEX " ++.br ++.BI th " THRESHOLD " ++ ++.ti -8 ++.BR "devlink sb tc bind show " ++.RI "[ " DEV/PORT_INDEX " [ " ++.B sb ++.IR SB_INDEX " ] " ++.br ++.BI tc " TC_INDEX " ++.br ++.B type ++.RB "{ " ingress " | " egress " } ]" ++ ++.ti -8 ++.BI "devlink sb tc bind set " DEV/PORT_INDEX " ++.RB "[ " sb ++.IR SB_INDEX " ] " ++.br ++.BI tc " TC_INDEX " ++.br ++.BR type " { " ingress " | " egress " }" ++.br ++.BI pool " POOL_INDEX " ++.br ++.BI th " THRESHOLD " ++ ++.ti -8 ++.BR "devlink sb occupancy show " ++.RI "{ " DEV " | " DEV/PORT_INDEX " } [ " ++.B sb ++.IR SB_INDEX " ] " ++ ++.ti -8 ++.BR "devlink sb occupancy snapshot " ++.IR DEV " [ " ++.B sb ++.IR SB_INDEX " ]" ++ ++.ti -8 ++.BR "devlink sb occupancy clearmax " ++.IR DEV " [ " ++.B sb ++.IR SB_INDEX " ]" ++ ++.ti -8 ++.B devlink sb help ++ ++.SH "DESCRIPTION" ++.SS devlink sb show - display available shared buffers and their attributes ++ ++.PP ++.I "DEV" ++- specifies the devlink device to show shared buffers. ++If this argument is omitted all shared buffers of all devices are listed. ++ ++.PP ++.I "SB_INDEX" ++- specifies the shared buffer. ++If this argument is omitted shared buffer with index 0 is selected. ++Behaviour of this argument it the same for every command. ++ ++.SS devlink sb pool show - display available pools and their attributes ++ ++.PP ++.I "DEV" ++- specifies the devlink device to show pools. ++If this argument is omitted all pools of all devices are listed. ++ ++.SS devlink sb pool set - set attributes of pool ++ ++.PP ++.I "DEV" ++- specifies the devlink device to set pool. ++ ++.TP ++.BI size " POOL_SIZE" ++size of the pool in Bytes. ++ ++.TP ++.BR thtype " { " static " | " dynamic " } " ++pool threshold type. ++ ++.I static ++- Threshold values for the pool will be passed in Bytes. ++ ++.I dynamic ++- Threshold values ("to_alpha") for the pool will be used to compute alpha parameter according to formula: ++.br ++.in +16 ++alpha = 2 ^ (to_alpha - 10) ++.in -16 ++ ++.in +10 ++The range of the passed value is between 0 to 20. The computed alpha is used to determine the maximum usage of the flow: ++.in -10 ++.br ++.in +16 ++max_usage = alpha / (1 + alpha) * Free_Buffer ++.in -16 ++ ++.SS devlink sb port pool show - display port-pool combinations and threshold for each ++.I "DEV/PORT_INDEX" ++- specifies the devlink port. ++ ++.TP ++.BI pool " POOL_INDEX" ++pool index. ++ ++.SS devlink sb port pool set - set port-pool threshold ++.I "DEV/PORT_INDEX" ++- specifies the devlink port. ++ ++.TP ++.BI pool " POOL_INDEX" ++pool index. ++ ++.TP ++.BI th " THRESHOLD" ++threshold value. Type of the value is either Bytes or "to_alpha", depends on ++.B thtype ++set for the pool. ++ ++.SS devlink sb tc bind show - display port-TC to pool bindings and threshold for each ++ ++.I "DEV/PORT_INDEX" ++- specifies the devlink port. ++ ++.TP ++.BI tc " TC_INDEX" ++index of either ingress or egress TC, usually in range 0 to 8 (depends on device). ++ ++.TP ++.BR type " { " ingress " | " egress " } " ++TC type. ++ ++.SS devlink sb tc bind set - set port-TC to pool binding with specified threshold ++ ++.I "DEV/PORT_INDEX" ++- specifies the devlink port. ++ ++.TP ++.BI tc " TC_INDEX" ++index of either ingress or egress TC, usually in range 0 to 8 (depends on device). ++ ++.TP ++.BR type " { " ingress " | " egress " } " ++TC type. ++ ++.TP ++.BI pool " POOL_INDEX" ++index of pool to bind this to. ++ ++.TP ++.BI th " THRESHOLD" ++threshold value. Type of the value is either Bytes or "to_alpha", depends on ++.B thtype ++set for the pool. ++ ++.SS devlink sb occupancy show - display shared buffer occupancy values for device or port ++ ++.PP ++This command is used to browse shared buffer occupancy values. Values are showed for every port-pool combination as well as for all port-TC combinations (with pool this port-TC is bound to). Format of value is: ++.br ++.in +16 ++current_value/max_value ++.in -16 ++Note that before showing values, one has to issue ++.b occupancy snapshot ++command first. ++ ++.PP ++.I "DEV" ++- specifies the devlink device to show occupancy values for. ++ ++.I "DEV/PORT_INDEX" ++- specifies the devlink port to show occupancy values for. ++ ++.SS devlink sb occupancy snapshot - take occupancy snapshot of shared buffer for device ++This command is used to take a snapshot of shared buffer occupancy values. After that, the values can be showed using ++.B occupancy show ++command. ++ ++.PP ++.I "DEV" ++- specifies the devlink device to take occupancy snapshot on. ++ ++.SS devlink sb occupancy clearmax - clear occupancy watermarks of shared buffer for device ++This command is used to reset maximal occupancy values reached for whole device. Note that before browsing reset values, one has to issue ++.B occupancy snapshot ++command. ++ ++.PP ++.I "DEV" ++- specifies the devlink device to clear occupancy watermarks on. ++ ++.SH "EXAMPLES" ++.PP ++devlink sb show ++.RS 4 ++List available share buffers. ++.RE ++.PP ++devlink sb pool show ++.RS 4 ++List available pools and their config. ++.RE ++.PP ++devlink sb port pool show pci/0000:03:00.0/1 pool 0 ++.RS 4 ++Show port-pool setup for specified port and pool. ++.RE ++.PP ++sudo devlink sb port pool set pci/0000:03:00.0/1 pool 0 th 15 ++.RS 4 ++Change threshold for port specified port and pool. ++.RE ++.PP ++devlink sb tc bind show pci/0000:03:00.0/1 tc 0 type ingress ++.RS 4 ++Show pool binding and threshold for specified port and TC. ++.RE ++.PP ++sudo devlink sb tc bind set pci/0000:03:00.0/1 tc 0 type ingress pool 0 th 9 ++.RS 4 ++Set pool binding and threshold for specified port and TC. ++.RE ++.PP ++sudo devlink sb occupancy snapshot pci/0000:03:00.0 ++.RS 4 ++Make a snapshot of occupancy of shared buffer for specified devlink device. ++.RE ++.PP ++devlink sb occupancy show pci/0000:03:00.0/1 ++.RS 4 ++Show occupancy for specified port from the snapshot. ++.RE ++.PP ++sudo devlink sb occupancy clearmax pci/0000:03:00.0 ++.RS 4 ++Clear watermarks for shared buffer of specified devlink device. ++ ++ ++.SH SEE ALSO ++.BR devlink (8), ++.BR devlink-dev (8), ++.BR devlink-port (8), ++.BR devlink-monitor (8), ++.br ++ ++.SH AUTHOR ++Jiri Pirko <jiri@mellanox.com> +-- +1.8.3.1 + diff --git a/SOURCES/0197-ip-route-restore-route-entries-in-correct-order.patch b/SOURCES/0197-ip-route-restore-route-entries-in-correct-order.patch new file mode 100644 index 0000000..aa8f935 --- /dev/null +++ b/SOURCES/0197-ip-route-restore-route-entries-in-correct-order.patch @@ -0,0 +1,128 @@ +From 3cdde59a38727b58edb9e165fcbb9befa5025f43 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 21:31:37 +0200 +Subject: [PATCH] ip route: restore route entries in correct order + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1348133 +Upstream Status: iproute2.git commit 74af8dd9620e4 + +commit 74af8dd9620e4322babf9d2a936b1d333a4e37e0 +Author: Xin Long <lucien.xin@gmail.com> +Date: Tue Jul 12 21:37:58 2016 +0800 + + ip route: restore route entries in correct order + + Sometimes we cannot restore route entries, because in kernel + [1] fib_check_nh() + [2] fib_valid_prefsrc() + cause some routes to depend on existence of others while adding. + + For example, we saved all the routes, and flushed all tables + [a] default via 192.168.122.1 dev eth0 + [b] 192.168.122.0/24 dev eth0 src 192.168.122.21 + [c] broadcast 127.0.0.0 dev lo table local src 127.0.0.1 + [d] local 127.0.0.0/8 dev lo table local src 127.0.0.1 + [e] local 127.0.0.1 dev lo table local src 127.0.0.1 + [f] broadcast 127.255.255.255 dev lo table local src 127.0.0.1 + [g] broadcast 192.168.122.0 dev eth0 table local src 192.168.122.21 + [h] local 192.168.122.21 dev eth0 table local src 192.168.122.21 + [i] broadcast 192.168.122.255 dev eth0 table local src 192.168.122.21 + + Now start to restore them: + If we want to add [a], we have to add [b] first, as [1] and + 'via 192.168.122.1' in [a]. + If we want to add [b], we have to add [h] first, as [2] and + 'src 192.168.122.21' in [b]. + + So the correct order to restore should be like: + [e][h] -> [b][c][d][f][g][i] -> [a] + + This patch fixes it by traversing the file 3 times, it only restores + part of them in each run according to the following conditions, to + make sure every entry can be restored successfully. + 1. !gw && (!fib_prefsrc || fib_prefsrc == cfg->fc_dst) + 2. !gw && (fib_prefsrc != cfg->fc_dst) + 3. gw + + Signed-off-by: Xin Long <lucien.xin@gmail.com> + Acked-by: Phil Sutter <phil@nwl.cc> +--- + ip/iproute.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 45 insertions(+), 2 deletions(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index 74599e4..fca5802 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -1585,12 +1585,42 @@ static int iproute_get(int argc, char **argv) + exit(0); + } + ++static int rtattr_cmp(struct rtattr *rta1, struct rtattr *rta2) ++{ ++ if (!rta1 || !rta2 || rta1->rta_len != rta2->rta_len) ++ return 1; ++ ++ return memcmp(RTA_DATA(rta1), RTA_DATA(rta2), RTA_PAYLOAD(rta1)); ++} ++ + static int restore_handler(const struct sockaddr_nl *nl, + struct rtnl_ctrl_data *ctrl, + struct nlmsghdr *n, void *arg) + { +- int ret; ++ struct rtmsg *r = NLMSG_DATA(n); ++ struct rtattr *tb[RTA_MAX+1]; ++ int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)); ++ int ret, prio = *(int *)arg; ++ ++ parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); + ++ /* Restore routes in correct order: ++ * 0. ones for local addresses, ++ * 1. ones for local networks, ++ * 2. others (remote networks/hosts). ++ */ ++ if (!prio && !tb[RTA_GATEWAY] && (!tb[RTA_PREFSRC] || ++ !rtattr_cmp(tb[RTA_PREFSRC], tb[RTA_DST]))) ++ goto restore; ++ else if (prio == 1 && !tb[RTA_GATEWAY] && ++ rtattr_cmp(tb[RTA_PREFSRC], tb[RTA_DST])) ++ goto restore; ++ else if (prio == 2 && tb[RTA_GATEWAY]) ++ goto restore; ++ ++ return 0; ++ ++restore: + n->nlmsg_flags |= NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK; + + ll_init_map(&rth); +@@ -1623,10 +1653,23 @@ static int route_dump_check_magic(void) + + static int iproute_restore(void) + { ++ int pos, prio; ++ + if (route_dump_check_magic()) + exit(-1); + +- exit(rtnl_from_file(stdin, &restore_handler, NULL)); ++ pos = ftell(stdin); ++ for (prio = 0; prio < 3; prio++) { ++ int err; ++ ++ err = rtnl_from_file(stdin, &restore_handler, &prio); ++ if (err) ++ exit(err); ++ ++ fseek(stdin, pos, SEEK_SET); ++ } ++ ++ exit(0); + } + + static int show_handler(const struct sockaddr_nl *nl, +-- +1.8.3.1 + diff --git a/SOURCES/0198-iproute-constify-rtattr_cmp.patch b/SOURCES/0198-iproute-constify-rtattr_cmp.patch new file mode 100644 index 0000000..37f21d7 --- /dev/null +++ b/SOURCES/0198-iproute-constify-rtattr_cmp.patch @@ -0,0 +1,33 @@ +From cdfa6872b71e63e4b2fe0ae6fd9b87be06d9ed53 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 21:31:37 +0200 +Subject: [PATCH] iproute: constify rtattr_cmp + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1348133 +Upstream Status: iproute2.git commit 79f4a39365361 + +commit 79f4a39365361732622e114dbc86bc90ed32d25f +Author: Stephen Hemminger <shemming@brocade.com> +Date: Fri Jul 15 11:34:45 2016 -0700 + + iproute: constify rtattr_cmp +--- + ip/iproute.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index fca5802..94dacbb 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -1585,7 +1585,7 @@ static int iproute_get(int argc, char **argv) + exit(0); + } + +-static int rtattr_cmp(struct rtattr *rta1, struct rtattr *rta2) ++static int rtattr_cmp(const struct rtattr *rta1, const struct rtattr *rta2) + { + if (!rta1 || !rta2 || rta1->rta_len != rta2->rta_len) + return 1; +-- +1.8.3.1 + diff --git a/SOURCES/0199-ip-link-Add-group-in-usage-for-ip-link-delete.patch b/SOURCES/0199-ip-link-Add-group-in-usage-for-ip-link-delete.patch new file mode 100644 index 0000000..dbf0c4d --- /dev/null +++ b/SOURCES/0199-ip-link-Add-group-in-usage-for-ip-link-delete.patch @@ -0,0 +1,46 @@ +From 9502dd16d7623bd5c40b34a38dae7c8118bba9e6 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:54:33 +0200 +Subject: [PATCH] ip link: Add group in usage() for 'ip link delete' + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 8916ccf66cec5 + +commit 8916ccf66cec59e4e1c1bd4d79a9342b0569d89c +Author: Vadim Kochan <vadim4j@gmail.com> +Date: Fri May 1 22:26:52 2015 +0300 + + ip link: Add group in usage() for 'ip link delete' + + Show deleting by group in 'ip link help' output: + + ... + ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ] + ... + + Also show separately DEVICE option in { } list. + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> +--- + ip/iplink.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index 0e2390d..619556c 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -53,9 +53,9 @@ void iplink_usage(void) + fprintf(stderr, " [ numtxqueues QUEUE_COUNT ]\n"); + fprintf(stderr, " [ numrxqueues QUEUE_COUNT ]\n"); + fprintf(stderr, " type TYPE [ ARGS ]\n"); +- fprintf(stderr, " ip link delete DEV type TYPE [ ARGS ]\n"); ++ fprintf(stderr, " ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]\n"); + fprintf(stderr, "\n"); +- fprintf(stderr, " ip link set { dev DEVICE | group DEVGROUP } [ { up | down } ]\n"); ++ fprintf(stderr, " ip link set { DEVICE | dev DEVICE | group DEVGROUP } [ { up | down } ]\n"); + } else + fprintf(stderr, "Usage: ip link set DEVICE [ { up | down } ]\n"); + +-- +1.8.3.1 + diff --git a/SOURCES/0200-iplink-List-valid-type-argument-in-ip-link-help-text.patch b/SOURCES/0200-iplink-List-valid-type-argument-in-ip-link-help-text.patch new file mode 100644 index 0000000..7d6d0e5 --- /dev/null +++ b/SOURCES/0200-iplink-List-valid-type-argument-in-ip-link-help-text.patch @@ -0,0 +1,37 @@ +From cb18b1973836de6baf786912af560d1f7086cea9 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:54:33 +0200 +Subject: [PATCH] iplink: List valid 'type' argument in ip link help text + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 771a24289044c + +commit 771a24289044c264cfe7b83040c2b35459b4227d +Author: Phil Sutter <phil@nwl.cc> +Date: Sat Jul 9 11:22:45 2016 +0200 + + iplink: List valid 'type' argument in ip link help text + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + ip/iplink.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index 619556c..0098443 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -55,7 +55,9 @@ void iplink_usage(void) + fprintf(stderr, " type TYPE [ ARGS ]\n"); + fprintf(stderr, " ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]\n"); + fprintf(stderr, "\n"); +- fprintf(stderr, " ip link set { DEVICE | dev DEVICE | group DEVGROUP } [ { up | down } ]\n"); ++ fprintf(stderr, " ip link set { DEVICE | dev DEVICE | group DEVGROUP }\n"); ++ fprintf(stderr, " [ { up | down } ]\n"); ++ fprintf(stderr, " [ type TYPE ARGS ]\n"); + } else + fprintf(stderr, "Usage: ip link set DEVICE [ { up | down } ]\n"); + +-- +1.8.3.1 + diff --git a/SOURCES/0201-iplink-bond_slave-Add-missing-help-functions.patch b/SOURCES/0201-iplink-bond_slave-Add-missing-help-functions.patch new file mode 100644 index 0000000..45e5ddd --- /dev/null +++ b/SOURCES/0201-iplink-bond_slave-Add-missing-help-functions.patch @@ -0,0 +1,75 @@ +From b2958475a62de444f8bf0e756406f7097a415a4b Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:54:33 +0200 +Subject: [PATCH] iplink: bond_slave: Add missing help functions + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 25c93faa58806 + +commit 25c93faa58806479ea73bc2d5ceb545e5e932867 +Author: Phil Sutter <phil@nwl.cc> +Date: Sat Jul 9 11:22:46 2016 +0200 + + iplink: bond_slave: Add missing help functions + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + ip/iplink_bond_slave.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c +index 2f3364e..5a802b1 100644 +--- a/ip/iplink_bond_slave.c ++++ b/ip/iplink_bond_slave.c +@@ -17,6 +17,16 @@ + #include "utils.h" + #include "ip_common.h" + ++static void print_explain(FILE *f) ++{ ++ fprintf(f, "Usage: ... bond_slave [ queue_id ID ]\n"); ++} ++ ++static void explain(void) ++{ ++ print_explain(stderr); ++} ++ + static const char *slave_states[] = { + [BOND_STATE_ACTIVE] = "ACTIVE", + [BOND_STATE_BACKUP] = "BACKUP", +@@ -99,6 +109,13 @@ static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv, + if (get_u16(&queue_id, *argv, 0)) + invarg("queue_id is invalid", *argv); + addattr16(n, 1024, IFLA_BOND_SLAVE_QUEUE_ID, queue_id); ++ } else { ++ if (matches(*argv, "help") != 0) ++ fprintf(stderr, ++ "bond_slave: unknown option \"%s\"?\n", ++ *argv); ++ explain(); ++ return -1; + } + argc--, argv++; + } +@@ -106,10 +123,17 @@ static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv, + return 0; + } + ++static void bond_slave_print_help(struct link_util *lu, int argc, char **argv, ++ FILE *f) ++{ ++ print_explain(f); ++} ++ + struct link_util bond_slave_link_util = { + .id = "bond", + .maxattr = IFLA_BOND_SLAVE_MAX, + .print_opt = bond_slave_print_opt, + .parse_opt = bond_slave_parse_opt, ++ .print_help = bond_slave_print_help, + .slave = true, + }; +-- +1.8.3.1 + diff --git a/SOURCES/0202-man-ip-link-Add-deleting-links-by-group.patch b/SOURCES/0202-man-ip-link-Add-deleting-links-by-group.patch new file mode 100644 index 0000000..03822b1 --- /dev/null +++ b/SOURCES/0202-man-ip-link-Add-deleting-links-by-group.patch @@ -0,0 +1,56 @@ +From 3c5f4d7b71df13bdbb11733a4969274ffaa965fd Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:54:33 +0200 +Subject: [PATCH] man ip-link: Add deleting links by group + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 7f74cf6de03a3 +Conflicts: Context changes due to previously added GENEVE support. + +commit 7f74cf6de03a35cb15761d5b507a4d37bc1af64e +Author: Vadim Kochan <vadim4j@gmail.com> +Date: Fri May 1 21:46:41 2015 +0300 + + man ip-link: Add deleting links by group + + Indicate possibility deleting virtual links by group. + + Also changed the alignment of 'ip link delete' args + descriptions, to look like similary to 'ip link set'. + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> +--- + man/man8/ip-link.8.in | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index ac3bb77..59a5699 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -64,7 +64,10 @@ ip-link \- network device configuration + .BR geneve " ]" + + .ti -8 +-.BI "ip link delete " DEVICE ++.BR "ip link delete " { ++.IR DEVICE " | " ++.BI "group " GROUP ++} + .BI type " TYPE" + .RI "[ " ARGS " ]" + +@@ -843,6 +846,11 @@ the following additional arguments are supported: + specifies the virtual device to act operate on. + + .TP ++.BI group " GROUP " ++specifies the group of virtual links to delete. Group 0 is not allowed to be ++deleted since it is the default group. ++ ++.TP + .BI type " TYPE " + specifies the type of the device. + +-- +1.8.3.1 + diff --git a/SOURCES/0203-man-ip-link-Add-short-description-about-group.patch b/SOURCES/0203-man-ip-link-Add-short-description-about-group.patch new file mode 100644 index 0000000..aafd1a3 --- /dev/null +++ b/SOURCES/0203-man-ip-link-Add-short-description-about-group.patch @@ -0,0 +1,39 @@ +From 68ba1fcc05e8ee70267ae967b83d6236b9d2c5f5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:55:48 +0200 +Subject: [PATCH] man ip-link: Add short description about 'group' + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 032b4f4d19e1d + +commit 032b4f4d19e1d0880f800a0becfd05025206bb7d +Author: Vadim Kochan <vadim4j@gmail.com> +Date: Sat Mar 7 15:43:37 2015 +0200 + + man ip-link: Add short description about 'group' + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> +--- + man/man8/ip-link.8.in | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 59a5699..d820e69 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -1082,6 +1082,12 @@ output. + .I "TYPE" + specifies which help of link type to dislpay. + ++.SS ++.I GROUP ++may be a number or a string from the file ++.B /etc/iproute2/group ++which can be manually filled. ++ + .SH "EXAMPLES" + .PP + ip link show +-- +1.8.3.1 + diff --git a/SOURCES/0204-man-ip-link-Remove-extra-GROUP-explanation.patch b/SOURCES/0204-man-ip-link-Remove-extra-GROUP-explanation.patch new file mode 100644 index 0000000..d936882 --- /dev/null +++ b/SOURCES/0204-man-ip-link-Remove-extra-GROUP-explanation.patch @@ -0,0 +1,50 @@ +From baceb17b65e029f473d3df3215d9a3d5f035b63f Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:55:49 +0200 +Subject: [PATCH] man ip-link: Remove extra GROUP explanation + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 699589f6df02a + +commit 699589f6df02a6173e09202887a692967bb4e7d1 +Author: Vadim Kochan <vadim4j@gmail.com> +Date: Wed May 13 18:03:51 2015 +0300 + + man ip-link: Remove extra GROUP explanation + + Remove double explanation of GROUP option from 'ip link set' section. + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> +--- + man/man8/ip-link.8.in | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index d820e69..ca0d955 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -957,12 +957,6 @@ tool can be used. But it allows to change network namespace only for physical de + give the device a symbolic name for easy reference. + + .TP +-.BI group " GROUP" +-specify the group the device belongs to. +-The available groups are listed in file +-.BR "@SYSCONFDIR@/group" . +- +-.TP + .BI vf " NUM" + specify a Virtual Function device to be configured. The associated PF device + must be specified using the +@@ -1085,7 +1079,7 @@ specifies which help of link type to dislpay. + .SS + .I GROUP + may be a number or a string from the file +-.B /etc/iproute2/group ++.B @SYSCONFDIR@/group + which can be manually filled. + + .SH "EXAMPLES" +-- +1.8.3.1 + diff --git a/SOURCES/0205-ip-link.8-Extend-type-list-in-synopsis.patch b/SOURCES/0205-ip-link.8-Extend-type-list-in-synopsis.patch new file mode 100644 index 0000000..704290d --- /dev/null +++ b/SOURCES/0205-ip-link.8-Extend-type-list-in-synopsis.patch @@ -0,0 +1,121 @@ +From 2e254c04052152cb014d83ce9175f31916da07f2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:55:49 +0200 +Subject: [PATCH] ip-link.8: Extend type list in synopsis + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 657426c5060ac +Conflicts: Patch adjusted to missing HSR, lowpan and VRF support. + +commit 657426c5060ace22197397fbcaa6ac2c60d2ebec +Author: Phil Sutter <phil@nwl.cc> +Date: Sat Jul 9 11:22:47 2016 +0200 + + ip-link.8: Extend type list in synopsis + + 'ip link set' supports passing a type to set type-specific parameters. + Add this missing piece of information to the synopsis section. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/ip-link.8.in | 65 +++++++++++++++++++++++++++++---------------------- + 1 file changed, 37 insertions(+), 28 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index ca0d955..7bf3d47 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -38,32 +38,6 @@ ip-link \- network device configuration + .RI "[ " ARGS " ]" + + .ti -8 +-.IR TYPE " := [ " +-.BR bridge " | " +-.BR bond " | " +-.BR can " | " +-.BR dummy " | " +-.BR ifb " | " +-.BR ipoib " |" +-.BR macvlan " | " +-.BR macvtap " | " +-.BR vcan " | " +-.BR veth " | " +-.BR vlan " | " +-.BR vxlan " |" +-.BR ip6tnl " |" +-.BR ipip " |" +-.BR sit " |" +-.BR gre " |" +-.BR gretap " |" +-.BR ip6gre " |" +-.BR ip6gretap " |" +-.BR vti " |" +-.BR nlmon " |" +-.BR ipvlan " |" +-.BR geneve " ]" +- +-.ti -8 + .BR "ip link delete " { + .IR DEVICE " | " + .BI "group " GROUP +@@ -75,7 +49,12 @@ ip-link \- network device configuration + .BR "ip link set " { + .IR DEVICE " | " + .BI "group " GROUP +-.RB "} [ { " up " | " down " } ]" ++} ++.br ++.RB "[ { " up " | " down " } ]" ++.br ++.RB "[ " type ++.IR "ETYPE TYPE_ARGS" " ]" + .br + .RB "[ " arp " { " on " | " off " } ]" + .br +@@ -151,12 +130,42 @@ ip-link \- network device configuration + .B master + .IR DEVICE " ] [" + .B type +-.IR TYPE " ]" ++.IR ETYPE " ]" + + .ti -8 + .B ip link help + .RI "[ " TYPE " ]" + ++.ti -8 ++.IR TYPE " := [ " ++.BR bridge " | " ++.BR bond " | " ++.BR can " | " ++.BR dummy " | " ++.BR ifb " | " ++.BR ipoib " |" ++.BR macvlan " | " ++.BR macvtap " | " ++.BR vcan " | " ++.BR veth " | " ++.BR vlan " | " ++.BR vxlan " |" ++.BR ip6tnl " |" ++.BR ipip " |" ++.BR sit " |" ++.BR gre " |" ++.BR gretap " |" ++.BR ip6gre " |" ++.BR ip6gretap " |" ++.BR vti " |" ++.BR nlmon " |" ++.BR ipvlan " |" ++.BR geneve " ]" ++ ++.ti -8 ++.IR ETYPE " := [ " TYPE " |" ++.BR bridge_slave " | " bond_slave " ]" ++ + .SH "DESCRIPTION" + .SS ip link add - add virtual link + +-- +1.8.3.1 + diff --git a/SOURCES/0206-ip-link.8-Place-ip-link-set-warning-more-prominently.patch b/SOURCES/0206-ip-link.8-Place-ip-link-set-warning-more-prominently.patch new file mode 100644 index 0000000..47db533 --- /dev/null +++ b/SOURCES/0206-ip-link.8-Place-ip-link-set-warning-more-prominently.patch @@ -0,0 +1,67 @@ +From 38d81434a8b2f6354936ea3c9cb787cef002e3f1 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:56:22 +0200 +Subject: [PATCH] ip-link.8: Place 'ip link set' warning more prominently + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit f9e9f92881fcd + +commit f9e9f92881fcd8e2241e2f5c6afcdbfb9398bf89 +Author: Phil Sutter <phil@nwl.cc> +Date: Sat Jul 9 11:22:48 2016 +0200 + + ip-link.8: Place 'ip link set' warning more prominently + + This moves the warning to the beginning of the section about 'ip link + set' which makes it still stand out after adding more text to it's end. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/ip-link.8.in | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 7bf3d47..53d287a 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -865,6 +865,18 @@ specifies the type of the device. + + .SS ip link set - change device attributes + ++.PP ++.B Warning: ++If multiple parameter changes are requested, ++.B ip ++aborts immediately after any of the changes have failed. ++This is the only case when ++.B ip ++can move the system to an unpredictable state. The solution ++is to avoid changing several parameters with one ++.B ip link set ++call. ++ + .TP + .BI dev " DEVICE " + .I DEVICE +@@ -1034,18 +1046,6 @@ set IPv6 address generation mode + .BR "link-netnsid " + set peer netnsid for a cross-netns interface + +-.PP +-.B Warning: +-If multiple parameter changes are requested, +-.B ip +-aborts immediately after any of the changes have failed. +-This is the only case when +-.B ip +-can move the system to an unpredictable state. The solution +-is to avoid changing several parameters with one +-.B ip link set +-call. +- + .SS ip link show - display device attributes + + .TP +-- +1.8.3.1 + diff --git a/SOURCES/0207-ip-link.8-Add-slave-type-option-descriptions.patch b/SOURCES/0207-ip-link.8-Add-slave-type-option-descriptions.patch new file mode 100644 index 0000000..a27c813 --- /dev/null +++ b/SOURCES/0207-ip-link.8-Add-slave-type-option-descriptions.patch @@ -0,0 +1,162 @@ +From 9535f2ada08243db6212d5a19664afafb640b151 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:56:23 +0200 +Subject: [PATCH] ip-link.8: Add slave type option descriptions + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 3dd4b8936bd8c + +commit 3dd4b8936bd8c07eaf0f9e410a1b0cebaef77e40 +Author: Phil Sutter <phil@nwl.cc> +Date: Sat Jul 9 11:22:49 2016 +0200 + + ip-link.8: Add slave type option descriptions + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/ip-link.8.in | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 129 insertions(+) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 53d287a..25faebc 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -1046,6 +1046,135 @@ set IPv6 address generation mode + .BR "link-netnsid " + set peer netnsid for a cross-netns interface + ++.TP ++.BI type " ETYPE TYPE_ARGS" ++Change type-specific settings. For a list of supported types and arguments refer ++to the description of ++.B "ip link add" ++above. In addition to that, it is possible to manipulate settings to slave ++devices: ++ ++.TP ++Bridge Slave Support ++For a link with master ++.B bridge ++the following additional arguments are supported: ++ ++.B "ip link set type bridge_slave" ++[ ++.BI state " STATE" ++] [ ++.BI priority " PRIO" ++] [ ++.BI cost " COST" ++] [ ++.BR guard " { " on " | " off " }" ++] [ ++.BR hairpin " { " on " | " off " }" ++] [ ++.BR fastleave " { " on " | " off " }" ++] [ ++.BR root_block " { " on " | " off " }" ++] [ ++.BR learning " { " on " | " off " }" ++] [ ++.BR flood " { " on " | " off " }" ++] [ ++.BR proxy_arp " { " on " | " off " }" ++] [ ++.BR proxy_arp_wifi " { " on " | " off " }" ++] [ ++.BI mcast_router " MULTICAST_ROUTER" ++] [ ++.BR mcast_fast_leave " { " on " | " off "} ]" ++ ++.in +8 ++.sp ++.BI state " STATE" ++- Set port state. ++.I STATE ++is a number representing the following states: ++.BR 0 " (disabled)," ++.BR 1 " (listening)," ++.BR 2 " (learning)," ++.BR 3 " (forwarding)," ++.BR 4 " (blocking)." ++ ++.BI priority " PRIO" ++- set port priority (a 16bit unsigned value). ++ ++.BI cost " COST" ++- set port cost (a 32bit unsigned value). ++ ++.BR guard " { " on " | " off " }" ++- block incoming BPDU packets on this port. ++ ++.BR hairpin " { " on " | " off " }" ++- enable hairpin mode on this port. This will allow incoming packets on this ++port to be reflected back. ++ ++.BR fastleave " { " on " | " off " }" ++- enable multicast fast leave on this port. ++ ++.BR root_block " { " on " | " off " }" ++- block this port from becoming the bridge's root port. ++ ++.BR learning " { " on " | " off " }" ++- allow MAC address learning on this port. ++ ++.BR flood " { " on " | " off " }" ++- open the flood gates on this port, i.e. forward all unicast frames to this ++port also. Requires ++.BR proxy_arp " and " proxy_arp_wifi ++to be turned off. ++ ++.BR proxy_arp " { " on " | " off " }" ++- enable proxy ARP on this port. ++ ++.BR proxy_arp_wifi " { " on " | " off " }" ++- enable proxy ARP on this port which meets extended requirements by IEEE ++802.11 and Hotspot 2.0 specifications. ++ ++.BI mcast_router " MULTICAST_ROUTER" ++- configure this port for having multicast routers attached. A port with a ++multicast router will receive all multicast traffic. ++.I MULTICAST_ROUTER ++may be either ++.B 0 ++to disable multicast routers on this port, ++.B 1 ++to let the system detect the presence of of routers (this is the default), ++.B 2 ++to permanently enable multicast traffic forwarding on this port or ++.B 3 ++to enable multicast routers temporarily on this port, not depending on incoming ++queries. ++ ++.BR mcast_fast_leave " { " on " | " off " }" ++- this is a synonym to the ++.B fastleave ++option above. ++ ++.in -8 ++ ++.TP ++Bonding Slave Support ++For a link with master ++.B bond ++the following additional arguments are supported: ++ ++.B "ip link set type bond_slave" ++[ ++.BI queue_id " ID" ++] ++ ++.in +8 ++.sp ++.BI queue_id " ID" ++- set the slave's queue ID (a 16bit unsigned value). ++ ++.in -8 ++ + .SS ip link show - display device attributes + + .TP +-- +1.8.3.1 + diff --git a/SOURCES/0208-ip-link-fix-unterminated-string-in-manpage.patch b/SOURCES/0208-ip-link-fix-unterminated-string-in-manpage.patch new file mode 100644 index 0000000..cb74379 --- /dev/null +++ b/SOURCES/0208-ip-link-fix-unterminated-string-in-manpage.patch @@ -0,0 +1,35 @@ +From 696a9399c6782dfda428c5160df9decd64820153 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:56:23 +0200 +Subject: [PATCH] ip-link: fix unterminated string in manpage + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit f66611d823465 + +commit f66611d8234657a6ddebb98e8596a1ac866d0047 +Author: Stephen Hemminger <shemming@brocade.com> +Date: Wed Dec 3 19:35:36 2014 -0800 + + ip-link: fix unterminated string in manpage + + Missing " +--- + man/man8/ip-link.8.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 25faebc..b764019 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -327,7 +327,7 @@ For a link of type + the following additional arguments are supported: + + .BI "ip link add " DEVICE +-.BI type " vxlan " id " ID ++.BI type " vxlan " id " ID" + .R " [ " + .BI dev " PHYS_DEV " + .RB " ] [ { " group " | " remote " } " +-- +1.8.3.1 + diff --git a/SOURCES/0209-vxlan-fix-help-and-man-text.patch b/SOURCES/0209-vxlan-fix-help-and-man-text.patch new file mode 100644 index 0000000..aaa4769 --- /dev/null +++ b/SOURCES/0209-vxlan-fix-help-and-man-text.patch @@ -0,0 +1,53 @@ +From 00739d4e137e1a8aa637666ba0c6dbfdb308fcc2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:56:33 +0200 +Subject: [PATCH] vxlan: fix help and man text + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 5cd64c979f97a + +commit 5cd64c979f97ac1590e7bf28ae9b1adbd7673d3a +Author: Thomas Faivre <thomas.faivre@6wind.com> +Date: Thu Jan 14 18:10:19 2016 +0100 + + vxlan: fix help and man text + + Options 'group' and 'remote' cannot take 'any' as value but 'local' can. + + Signed-off-by: Thomas Faivre <thomas.faivre@6wind.com> + Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> +--- + ip/iplink_vxlan.c | 2 +- + man/man8/ip-link.8.in | 3 ++- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c +index 2ca97a4..015d7d9 100644 +--- a/ip/iplink_vxlan.c ++++ b/ip/iplink_vxlan.c +@@ -23,7 +23,7 @@ + + static void print_explain(FILE *f) + { +- fprintf(f, "Usage: ... vxlan id VNI [ { group | remote } ADDR ] [ local ADDR ]\n"); ++ fprintf(f, "Usage: ... vxlan id VNI [ { group | remote } IP_ADDRESS ] [ local ADDR ]\n"); + fprintf(f, " [ ttl TTL ] [ tos TOS ] [ dev PHYS_DEV ]\n"); + fprintf(f, " [ dstport PORT ] [ srcport MIN MAX ]\n"); + fprintf(f, " [ [no]learning ] [ [no]proxy ] [ [no]rsc ]\n"); +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index b764019..3ee1ad6 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -333,7 +333,8 @@ the following additional arguments are supported: + .RB " ] [ { " group " | " remote " } " + .I IPADDR + .R " ] [ " +-.BI local " IPADDR " ++.B local ++.RI "{ "IPADDR " | "any " } " + .R " ] [ " + .BI ttl " TTL " + .R " ] [ " +-- +1.8.3.1 + diff --git a/SOURCES/0210-ip-link-fix-man-page-warnings.patch b/SOURCES/0210-ip-link-fix-man-page-warnings.patch new file mode 100644 index 0000000..b00d696 --- /dev/null +++ b/SOURCES/0210-ip-link-fix-man-page-warnings.patch @@ -0,0 +1,220 @@ +From cca57c0deaee5dd9ac0a4dac4e8ed89bf8b57945 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:56:33 +0200 +Subject: [PATCH] ip-link: fix man page warnings + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 1ab0f02f465b7 +Conflicts: Context changes due to previously applied patch 29bb2373a8777 + ("geneve: add support to set flow label"). + +commit 1ab0f02f465b7bcc09798645d19236a500742e90 +Author: Thomas Faivre <thomas.faivre@6wind.com> +Date: Thu Jan 14 18:10:20 2016 +0100 + + ip-link: fix man page warnings + + grff wrapper returns warnings when parsing the ip-link.8.in file. + + How to reproduce: + $ man --warnings ip-link > /dev/null + `R' is a string (producing the registered sign), not a macro. + [...] + + Signed-off-by: Thomas Faivre <thomas.faivre@6wind.com> + Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> +--- + man/man8/ip-link.8.in | 104 +++++++++++++++++++++++++------------------------- + 1 file changed, 52 insertions(+), 52 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 3ee1ad6..be572f6 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -270,28 +270,28 @@ the following additional arguments are supported: + .BI link " DEVICE " + .BI name " NAME " + .BI type " vlan " +-.R " [ " ++[ + .BI protocol " VLAN_PROTO " +-.R " ] " ++] + .BI id " VLANID " +-.R " [ " ++[ + .BR reorder_hdr " { " on " | " off " } " +-.R " ] " +-.R " [ " ++] ++[ + .BR gvrp " { " on " | " off " } " +-.R " ] " +-.R " [ " ++] ++[ + .BR mvrp " { " on " | " off " } " +-.R " ] " +-.R " [ " ++] ++[ + .BR loose_binding " { " on " | " off " } " +-.R " ] " +-.R " [ " ++] ++[ + .BI ingress-qos-map " QOS-MAP " +-.R " ] " +-.R " [ " ++] ++[ + .BI egress-qos-map " QOS-MAP " +-.R " ] " ++] + + .in +8 + .sp +@@ -328,44 +328,44 @@ the following additional arguments are supported: + + .BI "ip link add " DEVICE + .BI type " vxlan " id " ID" +-.R " [ " ++[ + .BI dev " PHYS_DEV " + .RB " ] [ { " group " | " remote " } " + .I IPADDR +-.R " ] [ " ++] [ + .B local + .RI "{ "IPADDR " | "any " } " +-.R " ] [ " ++] [ + .BI ttl " TTL " +-.R " ] [ " ++] [ + .BI tos " TOS " +-.R " ] [ " ++] [ + .BI dstport " PORT " +-.R " ] [ " ++] [ + .BI srcport " MIN MAX " +-.R " ] [ " ++] [ + .I "[no]learning " +-.R " ] [ " ++] [ + .I "[no]proxy " +-.R " ] [ " ++] [ + .I "[no]rsc " +-.R " ] [ " ++] [ + .I "[no]l2miss " +-.R " ] [ " ++] [ + .I "[no]l3miss " +-.R " ] [ " ++] [ + .I "[no]udpcsum " +-.R " ] [ " ++] [ + .I "[no]udp6zerocsumtx " +-.R " ] [ " ++] [ + .I "[no]udp6zerocsumrx " +-.R " ] [ " ++] [ + .BI ageing " SECONDS " +-.R " ] [ " ++] [ + .BI maxaddress " NUMBER " +-.R " ] [ " ++] [ + .B gbp +-.R " ]" ++] + + .in +8 + .sp +@@ -507,17 +507,17 @@ the following additional arguments are supported: + .BI "ip link add " DEVICE + .BR type " { gre | ipip | sit } " + .BI " remote " ADDR " local " ADDR +-.R " [ " ++[ + .BR encap " { fou | gue | none } " +-.R " ] [ " ++] [ + .BI "encap-sport { " PORT " | auto } " +-.R " ] [ " ++] [ + .BI "encap-dport " PORT +-.R " ] [ " ++] [ + .I " [no]encap-csum " +-.R " ] [ " ++] [ + .I " [no]encap-remcsum " +-.R " ]" ++] + + .in +8 + .sp +@@ -563,25 +563,25 @@ the following additional arguments are supported: + + .BI "ip link add " DEVICE + .BI type " { ip6gre | ip6gretap } " remote " ADDR " local " ADDR +-.R " [ " ++[ + .I "[i|o]seq]" +-.R " ] [ " ++] [ + .I "[i|o]key" KEY +-.R " ] [ " ++] [ + .I " [i|o]csum " +-.R " ] [ " ++] [ + .BI hoplimit " TTL " +-.R " ] [ " ++] [ + .BI encaplimit " ELIM " +-.R " ] [ " ++] [ + .BI tclass " TCLASS " +-.R " ] [ " ++] [ + .BI flowlabel " FLOWLABEL " +-.R " ] [ " ++] [ + .BI "dscp inherit" +-.R " ] [ " ++] [ + .BI dev " PHYS_DEV " +-.R " ]" ++] + + .in +8 + .sp +@@ -686,13 +686,13 @@ the following additional arguments are supported: + + .BI "ip link add " DEVICE + .BI type " geneve " id " ID " remote " IPADDR" +-.R " [ " ++[ + .BI ttl " TTL " +-.R " ] [ " ++] [ + .BI tos " TOS " +-.R " ] [ " ++] [ + .BI flowlabel " FLOWLABEL " +-.R " ]" ++] + + .in +8 + .sp +-- +1.8.3.1 + diff --git a/SOURCES/0211-ip-link.8-Fix-font-choices.patch b/SOURCES/0211-ip-link.8-Fix-font-choices.patch new file mode 100644 index 0000000..ef1ebcc --- /dev/null +++ b/SOURCES/0211-ip-link.8-Fix-font-choices.patch @@ -0,0 +1,249 @@ +From cc76a807b3215f06674cc613a8d492111eea949a Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:57:10 +0200 +Subject: [PATCH] ip-link.8: Fix font choices + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1269528 +Upstream Status: iproute2.git commit 52a5986980527 +Conflicts: Context changes due to missing support for 'external' VXLAN + flag and missing HSR support. + +commit 52a598698052773857a2ca590b81940367774fce +Author: Phil Sutter <phil@nwl.cc> +Date: Sat Jul 9 11:22:50 2016 +0200 + + ip-link.8: Fix font choices + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/ip-link.8.in | 76 ++++++++++++++++++++++++++------------------------- + 1 file changed, 39 insertions(+), 37 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index be572f6..1d2fcb0 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -269,7 +269,7 @@ the following additional arguments are supported: + .BI "ip link add + .BI link " DEVICE " + .BI name " NAME " +-.BI type " vlan " ++.B "type vlan" + [ + .BI protocol " VLAN_PROTO " + ] +@@ -327,7 +327,7 @@ For a link of type + the following additional arguments are supported: + + .BI "ip link add " DEVICE +-.BI type " vxlan " id " ID" ++.BI type " vxlan " id " VNI" + [ + .BI dev " PHYS_DEV " + .RB " ] [ { " group " | " remote " } " +@@ -344,21 +344,21 @@ the following additional arguments are supported: + ] [ + .BI srcport " MIN MAX " + ] [ +-.I "[no]learning " ++.RB [ no ] learning + ] [ +-.I "[no]proxy " ++.RB [ no ] proxy + ] [ +-.I "[no]rsc " ++.RB [ no ] rsc + ] [ +-.I "[no]l2miss " ++.RB [ no ] l2miss + ] [ +-.I "[no]l3miss " ++.RB [ no ] l3miss + ] [ +-.I "[no]udpcsum " ++.RB [ no ] udpcsum + ] [ +-.I "[no]udp6zerocsumtx " ++.RB [ no ] udp6zerocsumtx + ] [ +-.I "[no]udp6zerocsumrx " ++.RB [ no ] udp6zerocsumrx + ] [ + .BI ageing " SECONDS " + ] [ +@@ -413,36 +413,36 @@ parameter. + source ports to communicate to the remote VXLAN tunnel endpoint. + + .sp +-.I [no]learning ++.RB [ no ] learning + - specifies if unknown source link layer addresses and IP addresses + are entered into the VXLAN device forwarding database. + + .sp +-.I [no]rsc ++.RB [ no ] rsc + - specifies if route short circuit is turned on. + + .sp +-.I [no]proxy ++.RB [ no ] proxy + - specifies ARP proxy is turned on. + + .sp +-.I [no]l2miss ++.RB [ no ] l2miss + - specifies if netlink LLADDR miss notifications are generated. + + .sp +-.I [no]l3miss ++.RB [ no ] l3miss + - specifies if netlink IP ADDR miss notifications are generated. + + .sp +-.I [no]udpcsum ++.RB [ no ] udpcsum + - specifies if UDP checksum is calculated for transmitted packets over IPv4. + + .sp +-.I [no]udp6zerocsumtx ++.RB [ no ] udp6zerocsumtx + - skip UDP checksum calculation for transmitted packets over IPv6. + + .sp +-.I [no]udp6zerocsumrx ++.RB [ no ] udp6zerocsumrx + - allow incoming UDP packets over IPv6 with zero checksum field. + + .sp +@@ -505,18 +505,18 @@ For a link of types + the following additional arguments are supported: + + .BI "ip link add " DEVICE +-.BR type " { gre | ipip | sit } " ++.BR type " { " gre " | " ipip " | " sit " }" + .BI " remote " ADDR " local " ADDR + [ +-.BR encap " { fou | gue | none } " ++.BR encap " { " fou " | " gue " | " none " }" + ] [ +-.BI "encap-sport { " PORT " | auto } " ++.BR encap-sport " { " \fIPORT " | " auto " }" + ] [ + .BI "encap-dport " PORT + ] [ +-.I " [no]encap-csum " ++.RB [ no ] encap-csum + ] [ +-.I " [no]encap-remcsum " ++.RB [ no ] encap-remcsum + ] + + .in +8 +@@ -530,12 +530,12 @@ the following additional arguments are supported: + It must be an address on another interface on this host. + + .sp +-.BR encap " { fou | gue | none } " ++.BR encap " { " fou " | " gue " | " none " }" + - specifies type of secondary UDP encapsulation. "fou" indicates + Foo-Over-UDP, "gue" indicates Generic UDP Encapsulation. + + .sp +-.BI "encap-sport { " PORT " | auto } " ++.BR encap-sport " { " \fIPORT " | " auto " }" + - specifies the source port in UDP encapsulation. + .IR PORT + indicates the port by number, "auto" +@@ -544,12 +544,12 @@ indicates that the port number should be chosen automatically + encapsulated packet). + + .sp +-.I [no]encap-csum ++.RB [ no ] encap-csum + - specifies if UDP checksums are enabled in the secondary + encapsulation. + + .sp +-.I [no]encap-remcsum ++.RB [ no ] encap-remcsum + - specifies if Remote Checksum Offload is enabled. This is only + applicable for Generic UDP Encapsulation. + +@@ -562,13 +562,15 @@ For a link of type + the following additional arguments are supported: + + .BI "ip link add " DEVICE +-.BI type " { ip6gre | ip6gretap } " remote " ADDR " local " ADDR ++.BR type " { " ip6gre " | " ip6gretap " }" ++.BI remote " ADDR " local " ADDR" + [ +-.I "[i|o]seq]" ++.RB [ i | o ] seq + ] [ +-.I "[i|o]key" KEY ++.RB [ i | o ] key ++.I KEY + ] [ +-.I " [i|o]csum " ++.RB [ i | o ] csum + ] [ + .BI hoplimit " TTL " + ] [ +@@ -594,7 +596,7 @@ the following additional arguments are supported: + It must be an address on another interface on this host. + + .sp +-.BI [i|o]seq ++.RB [ i | o ] seq + - serialize packets. + The + .B oseq +@@ -604,7 +606,7 @@ The + flag requires that all input packets are serialized. + + .sp +-.BI [i|o]key " KEY" ++.RB [ i | o ] key " \fIKEY" + - use keyed GRE with key + .IR KEY ". "KEY + is either a number or an IPv4 address-like dotted quad. +@@ -616,7 +618,7 @@ The + parameters specify different keys for input and output. + + .sp +-.BI [i|o]csum ++.RB [ i | o ] csum + - generate/require checksums for tunneled packets. + The + .B ocsum +@@ -668,7 +670,7 @@ For a link of type + the following additional arguments are supported: + + .BI "ip link add " DEVICE " name " NAME +-.BI type " ipoib [ " pkey " PKEY ] [" mode " MODE " ] ++.BR "type ipoib " [ " pkey \fIPKEY" " ] [ " mode " \fIMODE \fR]" + + .in +8 + .sp +@@ -685,7 +687,7 @@ For a link of type + the following additional arguments are supported: + + .BI "ip link add " DEVICE +-.BI type " geneve " id " ID " remote " IPADDR" ++.BI type " geneve " id " VNI " remote " IPADDR" + [ + .BI ttl " TTL " + ] [ +@@ -728,7 +730,7 @@ the following additional arguments are supported: + .BI "ip link add link " DEVICE " name " NAME + .BR type " { " macvlan " | " macvtap " } " + .BR mode " { " private " | " vepa " | " bridge " | " passthru +-.BR " [ " nopromisc " ] } " ++.RB " [ " nopromisc " ] } " + + .in +8 + .sp +-- +1.8.3.1 + diff --git a/SOURCES/0212-ip-address.8-Document-autojoin-flag.patch b/SOURCES/0212-ip-address.8-Document-autojoin-flag.patch new file mode 100644 index 0000000..d91b0e4 --- /dev/null +++ b/SOURCES/0212-ip-address.8-Document-autojoin-flag.patch @@ -0,0 +1,76 @@ +From 88f9c8ccf815fdc170e0f160335acdaacadc669e Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 22:59:33 +0200 +Subject: [PATCH] ip-address.8: Document autojoin flag + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1333513 +Upstream Status: iproute2.git commit 6acf086c2bf3e + +commit 6acf086c2bf3e94ceed984acd39936e216342e16 +Author: Phil Sutter <phil@nwl.cc> +Date: Tue Jul 12 09:56:16 2016 +0200 + + ip-address.8: Document autojoin flag + + Description copied from related kernel support commit message with a + little tailoring to fit. + + While at it, fix font of non-terminal CONFFLAG-LIST in synopsis. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/ip-address.8.in | 25 +++++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in +index 8d34adb..c954ab3 100644 +--- a/man/man8/ip-address.8.in ++++ b/man/man8/ip-address.8.in +@@ -75,14 +75,15 @@ ip-address \- protocol address management + .IR FLAG " := " + .RB "[ " permanent " | " dynamic " | " secondary " | " primary " |" + .RB [ - ] tentative " | [" - ] deprecated " | [" - ] dadfailed " |" +-.BR temporary " | " CONFFLAG-LIST " ]" ++.BR temporary " |" ++.IR CONFFLAG-LIST " ]" + + .ti -8 + .IR CONFFLAG-LIST " := [ " CONFFLAG-LIST " ] " CONFFLAG + + .ti -8 + .IR CONFFLAG " := " +-.RB "[ " home " | " mngtmpaddr " | " nodad " | " noprefixroute " ]" ++.RB "[ " home " | " mngtmpaddr " | " nodad " | " noprefixroute " | " autojoin " ]" + + .ti -8 + .IR LIFETIME " := [ " +@@ -244,6 +245,26 @@ address, and don't search for one to delete when removing the address. Changing + an address to add this flag will remove the automatically added prefix route, + changing it to remove this flag will create the prefix route automatically. + ++.TP ++.B autojoin ++Joining multicast groups on Ethernet level via ++.B "ip maddr" ++command does not work if connected to an Ethernet switch that does IGMP ++snooping since the switch would not replicate multicast packets on ports that ++did not have IGMP reports for the multicast addresses. ++ ++Linux VXLAN interfaces created via ++.B "ip link add vxlan" ++have the ++.B group ++option that enables them to do the required join. ++ ++Using the ++.B autojoin ++flag when adding a multicast address enables similar functionality for ++Openvswitch VXLAN interfaces as well as other tunneling mechanisms that need to ++receive multicast traffic. ++ + .SS ip address delete - delete protocol address + .B Arguments: + coincide with the arguments of +-- +1.8.3.1 + diff --git a/SOURCES/0213-route-allow-routes-to-be-configured-with-expire-valu.patch b/SOURCES/0213-route-allow-routes-to-be-configured-with-expire-valu.patch new file mode 100644 index 0000000..88f7949 --- /dev/null +++ b/SOURCES/0213-route-allow-routes-to-be-configured-with-expire-valu.patch @@ -0,0 +1,61 @@ +From 9c5c3d0a9c58d8385424193fbd3467c29483d3d2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 20:45:56 +0200 +Subject: [PATCH] route: allow routes to be configured with expire values + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1357020 +Upstream Status: iproute2.git commit 68eede2505005 +Conflicts: Context changes due to missing commits: + * 194e9b855d053 ("ip: support RFC4191 router preference") + * f638e9f7c8718 ("mpls: always set type RTN_UNICAST and scope + RT_SCOPE_UNIVERSE for") + +commit 68eede2505005ea919e2fb43afc91bad0601faea +Author: Hangbin Liu <liuhangbin@gmail.com> +Date: Mon Dec 21 16:29:36 2015 +0800 + + route: allow routes to be configured with expire values + + Signed-off-by: Hangbin Liu <liuhangbin@gmail.com> +--- + ip/iproute.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/ip/iproute.c b/ip/iproute.c +index 94dacbb..a13e6f3 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -82,6 +82,7 @@ static void usage(void) + fprintf(stderr, " [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n"); + fprintf(stderr, " [ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]\n"); + fprintf(stderr, " [ features FEATURES ] [ quickack BOOL ] [ congctl NAME ]\n"); ++ fprintf(stderr, " [ expires TIME ]\n"); + fprintf(stderr, "TYPE := { unicast | local | broadcast | multicast | throw |\n"); + fprintf(stderr, " unreachable | prohibit | blackhole | nat }\n"); + fprintf(stderr, "TABLE_ID := [ local | main | default | all | NUMBER ]\n"); +@@ -746,6 +747,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) + int scope_ok = 0; + int table_ok = 0; + int raw = 0; ++ static int hz; + + memset(&req, 0, sizeof(req)); + +@@ -797,6 +799,14 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) + if (rtnl_dsfield_a2n(&tos, *argv)) + invarg("\"tos\" value is invalid\n", *argv); + req.r.rtm_tos = tos; ++ } else if (strcmp(*argv, "expires") == 0 ) { ++ __u32 expires; ++ NEXT_ARG(); ++ if (get_u32(&expires, *argv, 0)) ++ invarg("\"expires\" value is invalid\n", *argv); ++ if (!hz) ++ hz = get_user_hz(); ++ addattr32(&req.n, sizeof(req), RTA_EXPIRES, expires*hz); + } else if (matches(*argv, "metric") == 0 || + matches(*argv, "priority") == 0 || + matches(*argv, "preference") == 0) { +-- +1.8.3.1 + diff --git a/SOURCES/0214-ip-route-timeout-for-routes-has-to-be-set-in-seconds.patch b/SOURCES/0214-ip-route-timeout-for-routes-has-to-be-set-in-seconds.patch new file mode 100644 index 0000000..7b03340 --- /dev/null +++ b/SOURCES/0214-ip-route-timeout-for-routes-has-to-be-set-in-seconds.patch @@ -0,0 +1,59 @@ +From fcb76a6f2bd281e956dc736fb63dc1fa238ce220 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 20 Jul 2016 20:48:14 +0200 +Subject: [PATCH] ip route: timeout for routes has to be set in seconds + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1357020 +Upstream Status: iproute2.git commit eecc006952d6f +Conflicts: Changed context due to missing commit f638e9f7c8718 + ("mpls: always set type RTN_UNICAST and scope + RT_SCOPE_UNIVERSE for") + +commit eecc006952d6f3992b632974d0f04f995d2a176e +Author: Andrew Vagin <avagin@virtuozzo.com> +Date: Wed Jun 29 02:27:14 2016 +0300 + + ip route: timeout for routes has to be set in seconds + + Currently a timeout is multiplied by HZ in user-space and + then it multiplied by HZ in kernel-space. + + $ ./ip/ip r add 2002::0/64 dev veth1 expires 10 + $ ./ip/ip -6 r + 2002::/64 dev veth1 metric 1024 linkdown expires 996sec pref medium + + Cc: Xin Long <lucien.xin@gmail.com> + Cc: Hangbin Liu <liuhangbin@gmail.com> + Cc: Stephen Hemminger <shemming@brocade.com> + Fixes: 68eede250500 ("route: allow routes to be configured with expire values") + Signed-off-by: Andrew Vagin <avagin@virtuozzo.com> +--- + ip/iproute.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index a13e6f3..094566a 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -747,7 +747,6 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) + int scope_ok = 0; + int table_ok = 0; + int raw = 0; +- static int hz; + + memset(&req, 0, sizeof(req)); + +@@ -804,9 +803,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) + NEXT_ARG(); + if (get_u32(&expires, *argv, 0)) + invarg("\"expires\" value is invalid\n", *argv); +- if (!hz) +- hz = get_user_hz(); +- addattr32(&req.n, sizeof(req), RTA_EXPIRES, expires*hz); ++ addattr32(&req.n, sizeof(req), RTA_EXPIRES, expires); + } else if (matches(*argv, "metric") == 0 || + matches(*argv, "priority") == 0 || + matches(*argv, "preference") == 0) { +-- +1.8.3.1 + diff --git a/SOURCES/0215-iproute2-ip-route.8.in-Add-expires-option-for-ip-rou.patch b/SOURCES/0215-iproute2-ip-route.8.in-Add-expires-option-for-ip-rou.patch new file mode 100644 index 0000000..b66de89 --- /dev/null +++ b/SOURCES/0215-iproute2-ip-route.8.in-Add-expires-option-for-ip-rou.patch @@ -0,0 +1,52 @@ +From b1a374e69efdde93f7c64ccbfb53415a9d344ec4 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Fri, 22 Jul 2016 15:15:58 +0200 +Subject: [PATCH] iproute2: ip-route.8.in: Add expires option for ip route + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1357020 +Upstream Status: iproute2.git commit 3fbe7ca847367 +Conflicts: Patch adjusted for missing commit 194e9b855d053 + ("ip: support RFC4191 router preference") + +commit 3fbe7ca847367d0f9c3861283767ae702c2a19ab +Author: Hangbin Liu <liuhangbin@gmail.com> +Date: Fri Dec 25 11:12:16 2015 +0800 + + iproute2: ip-route.8.in: Add expires option for ip route + + Signed-off-by: Hangbin Liu <liuhangbin@gmail.com> +--- + man/man8/ip-route.8.in | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in +index ec4a5b2..dcaca2b 100644 +--- a/man/man8/ip-route.8.in ++++ b/man/man8/ip-route.8.in +@@ -118,7 +118,9 @@ replace " } " + .B quickack + .IR BOOL " ] [ " + .B congctl +-.IR NAME " ]" ++.IR NAME " ] [ " ++.B expires ++.IR TIME " ]" + + .ti -8 + .IR TYPE " := [ " +@@ -554,6 +556,12 @@ even if it does not match any interface prefix. + .RE + + .TP ++.BI expires " TIME " "(4.4+ only)" ++the route will be deleted after the expires time. ++.B Only ++support IPv6 at present. ++ ++.TP + ip route delete + delete route + .RS +-- +1.8.3.1 + diff --git a/SOURCES/0216-ipneigh-List-all-nud-states-in-help-output.patch b/SOURCES/0216-ipneigh-List-all-nud-states-in-help-output.patch new file mode 100644 index 0000000..76ccd72 --- /dev/null +++ b/SOURCES/0216-ipneigh-List-all-nud-states-in-help-output.patch @@ -0,0 +1,46 @@ +From b5c4868b391cac0956205526223bbd34fb40dffc Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 21 Jul 2016 17:01:09 +0200 +Subject: [PATCH] ipneigh: List all nud states in help output + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1276661 +Upstream Status: iproute2.git commit 03a0cf20b4511 + +commit 03a0cf20b451105ab13f0593fe57144bd6b25c3b +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 20:07:21 2016 +0100 + + ipneigh: List all nud states in help output + + To not make the output overly confusing, list them in a definition of + the STATE placeholder which is already used in the show/flush syntax but + wasn't explained before. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + ip/ipneigh.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/ip/ipneigh.c b/ip/ipneigh.c +index 2dbd537..472555d 100644 +--- a/ip/ipneigh.c ++++ b/ip/ipneigh.c +@@ -45,10 +45,11 @@ static void usage(void) __attribute__((noreturn)); + + static void usage(void) + { +- fprintf(stderr, "Usage: ip neigh { add | del | change | replace } { ADDR [ lladdr LLADDR ]\n" +- " [ nud { permanent | noarp | stale | reachable } ]\n" +- " | proxy ADDR } [ dev DEV ]\n"); +- fprintf(stderr, " ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ]\n"); ++ fprintf(stderr, "Usage: ip neigh { add | del | change | replace }\n" ++ " { ADDR [ lladdr LLADDR ] [ nud STATE ] | proxy ADDR } [ dev DEV ]\n"); ++ fprintf(stderr, " ip neigh { show | flush } [ proxy ] [ to PREFIX ] [ dev DEV ] [ nud STATE ]\n\n"); ++ fprintf(stderr, "STATE := { permanent | noarp | stale | reachable | none |\n" ++ " incomplete | delay | probe | failed }\n"); + exit(-1); + } + +-- +1.8.3.1 + diff --git a/SOURCES/0217-Document-VF-link-state-control-in-the-ip-link-man-pa.patch b/SOURCES/0217-Document-VF-link-state-control-in-the-ip-link-man-pa.patch new file mode 100644 index 0000000..cbd8e72 --- /dev/null +++ b/SOURCES/0217-Document-VF-link-state-control-in-the-ip-link-man-pa.patch @@ -0,0 +1,98 @@ +From a858036c46f6887ac0dc5211f5884876913fb432 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Fri, 22 Jul 2016 12:08:03 +0200 +Subject: [PATCH] Document VF link state control in the ip-link man page + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1264146 +Upstream Status: iproute2.git commit 63f60e3ab3655 +Conflicts: Multiple due to mistakes when resolving conflicts while + backporting commit ca611d6408c9b ("man: ip-link.8: Fix and + improve synopsis"). + +This commit is strictly speaking not related to bz#1264146, but it helps +preventing conflicts with the real fix for that BZ. Also it was +forgotten when backporting for bz#1061593 so it adds missing +documentation bits about a feature we already have. + +commit 63f60e3ab3655b5d1b62d3a9f641ef7b638d2361 +Author: Or Gerlitz <ogerlitz@mellanox.com> +Date: Sun May 11 09:22:19 2014 +0300 + + Document VF link state control in the ip-link man page + + Document the support added by commit 07fa9c1 "Add VF link state + control" in the ip-link man page. + + Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> +--- + man/man8/ip-link.8.in | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 1d2fcb0..d98fe91 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -101,16 +101,16 @@ ip-link \- network device configuration + .RB "[ " vlan + .IR VLANID " [ " + .B qos +-.IR VLAN-QOS " ] ] [" +-.B trust { on | off } +-] | ++.IR VLAN-QOS " ] ]" + .br + .RB "[ " rate + .IR TXRATE " ]" + .br + .RB "[ " spoofchk " { " on " | " off " } ]" + .br +-.RB "[ " state " { " auto " | " enable " | " disable " } ] ]" ++.RB "[ " state " { " auto " | " enable " | " disable " } ]" ++.br ++.RB "[ " trust " { " on " | " off " } ] ]" + .br + .in -9 + .RB "[ " master +@@ -322,7 +322,7 @@ the following additional arguments are supported: + + .TP + VXLAN Type Support +-For a link of type ++For a link of type + .I VXLAN + the following additional arguments are supported: + +@@ -557,7 +557,7 @@ applicable for Generic UDP Encapsulation. + + .TP + IP6GRE/IP6GRETAP Type Support +-For a link of type ++For a link of type + .I IP6GRE/IP6GRETAP + the following additional arguments are supported: + +@@ -641,7 +641,7 @@ flag is equivalent to the combination + + .sp + .BI flowlabel " FLOWLABEL" +-- specifies a fixed flowlabel. ++- specifies a fixed flowlabel. + + .sp + .BI tclass " TCLASS" +@@ -1028,6 +1028,12 @@ parameter must be specified. + .BI spoofchk " on|off" + - turn packet spoof checking on or off for the specified VF. + .sp ++.BI state " auto|enable|disable" ++- set the virtual link state as seen by the specified VF. Setting to auto means a ++reflection of the PF link state, enable lets the VF to communicate with other VFs on ++this host even if the PF link state is down, disable causes the HW to drop any packets ++sent by the VF. ++.sp + .BI trust " on|off" + - trust the specified VF user. This enables that VF user can set a specific feature + which may impact security and/or performance. (e.g. VF multicast promiscuous mode) +-- +1.8.3.1 + diff --git a/SOURCES/0218-man-ip-link-Document-query_rss-option.patch b/SOURCES/0218-man-ip-link-Document-query_rss-option.patch new file mode 100644 index 0000000..e219da2 --- /dev/null +++ b/SOURCES/0218-man-ip-link-Document-query_rss-option.patch @@ -0,0 +1,48 @@ +From 648dee9a042d08c669537d72b5bdcd31b99f6c74 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Fri, 22 Jul 2016 14:53:00 +0200 +Subject: [PATCH] man: ip-link: Document query_rss option + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1264146 +Upstream Status: iproute2.git commit 8e45e44b7923a + +commit 8e45e44b7923a30c97ea50e43f72db6688c6175e +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Jun 10 16:39:50 2016 +0200 + + man: ip-link: Document query_rss option + + Doc text shamelessly stolen from the introducing commit's message + (6c55c8c4617c5 ['ip link set vf: Added "query_rss" command']). + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/ip-link.8.in | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index d98fe91..33172e5 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -108,6 +108,8 @@ ip-link \- network device configuration + .br + .RB "[ " spoofchk " { " on " | " off " } ]" + .br ++.RB "[ " query_rss " { " on " | " off " } ]" ++.br + .RB "[ " state " { " auto " | " enable " | " disable " } ]" + .br + .RB "[ " trust " { " on " | " off " } ] ]" +@@ -1028,6 +1030,9 @@ parameter must be specified. + .BI spoofchk " on|off" + - turn packet spoof checking on or off for the specified VF. + .sp ++.BI query_rss " on|off" ++- toggle the ability of querying the RSS configuration of a specific VF. VF RSS information like RSS hash key may be considered sensitive on some devices where this information is shared between VF and PF and thus its querying may be prohibited by default. ++.sp + .BI state " auto|enable|disable" + - set the virtual link state as seen by the specified VF. Setting to auto means a + reflection of the PF link state, enable lets the VF to communicate with other VFs on +-- +1.8.3.1 + diff --git a/SOURCES/0219-Add-support-to-configure-SR-IOV-VF-minimum-and-maxim.patch b/SOURCES/0219-Add-support-to-configure-SR-IOV-VF-minimum-and-maxim.patch new file mode 100644 index 0000000..8a2403b --- /dev/null +++ b/SOURCES/0219-Add-support-to-configure-SR-IOV-VF-minimum-and-maxim.patch @@ -0,0 +1,327 @@ +From ed60b38f294c5f950d125384af8e430388929c51 Mon Sep 17 00:00:00 2001 +From: Jakub Sitnicki <jkbs@redhat.com> +Date: Wed, 27 Jul 2016 15:56:14 +0200 +Subject: [PATCH] Add support to configure SR-IOV VF minimum and maximum Tx + rate through ip tool + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1340914 +Upstream Status: iproute2.git commit f89a2a0 +Conflicts: +* context in iplink_parse() because we already have + ccdcbf35f120 ("iplink: add support of IFLA_LINK_NETNSID attribute") +* we already have a partial backport of ca611d6408c9 ("man: ip-link.8: + Fix and improve synopsis"), so fast-forward the synopsis to it's + current form + +commit f89a2a05ffa94ac5bec9f50751f761215356092b +Author: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com> +Date: Thu May 22 09:59:37 2014 -0400 + + Add support to configure SR-IOV VF minimum and maximum Tx rate through ip tool + + o "min_tx_rate" option has been added for minimum Tx rate. Hence, for + consistent naming, "max_tx_rate" option has been introduced for maximum + Tx rate. + + o Change in v2: "rate" can be used along with "max_tx_rate". + When both are specified, "max_tx_rate" should override. + + o Change in v3: + * IFLA_VF_RATE: When IFLA_VF_RATE is used, and user has given only one of + min_tx_rate or max_tx_rate, reading of previous rate limits is done in + userspace instead of in kernel space before ndo_set_vf_rate. + + * IFLA_VF_TX_RATE: When IFLA_VF_TX_RATE is used, min_tx_rate is always read + in kernel space. This takes care of below scenarios: + (1) when old tool sends "rate" but kernel is new (expects min and max) + (2) when new tool sends only "rate" but kernel is old (expects only "rate") + + o Change in v4 as suggested by Stephen Hemminger: + * As per iproute policy, input and output formats should match. Changing display + of max_tx_rate and min_tx_rate options accordingly. + ./ip/ip link show p3p1 + 8: p3p1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000 + link/ether 00:0e:1e:16:ce:40 brd ff:ff:ff:ff:ff:ff + vf 0 MAC 2a:18:8f:4d:3d:d4, tx rate 700 (Mbps), max_tx_rate 700Mbps, min_tx_rate 200Mbps + vf 1 MAC 72:dc:ba:f9:df:fd + + Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com> +--- + ip/ip_common.h | 1 + + ip/ipaddress.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ + ip/iplink.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++--- + man/man8/ip-link.8.in | 26 +++++++++++++++++++-- + 4 files changed, 148 insertions(+), 5 deletions(-) + +diff --git a/ip/ip_common.h b/ip/ip_common.h +index c3e7fda..286f61f 100644 +--- a/ip/ip_common.h ++++ b/ip/ip_common.h +@@ -17,6 +17,7 @@ extern int iproute_monitor(int argc, char **argv); + extern void iplink_usage(void) __attribute__((noreturn)); + extern void iproute_reset_filter(void); + extern void ipmroute_reset_filter(void); ++void ipaddr_get_vf_rate(int, int *, int *, int); + extern void ipaddr_reset_filter(int); + extern void ipneigh_reset_filter(void); + extern void ipntable_reset_filter(void); +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 05e0da9..11ff34d 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -290,6 +290,7 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo) + { + struct ifla_vf_mac *vf_mac; + struct ifla_vf_vlan *vf_vlan; ++ struct ifla_vf_rate *vf_rate; + struct ifla_vf_tx_rate *vf_tx_rate; + struct ifla_vf_spoofchk *vf_spoofchk; + struct ifla_vf_link_state *vf_linkstate; +@@ -307,6 +308,7 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo) + vf_mac = RTA_DATA(vf[IFLA_VF_MAC]); + vf_vlan = RTA_DATA(vf[IFLA_VF_VLAN]); + vf_tx_rate = RTA_DATA(vf[IFLA_VF_TX_RATE]); ++ vf_rate = RTA_DATA(vf[IFLA_VF_RATE]); + + /* Check if the spoof checking vf info type is supported by + * this kernel. +@@ -342,6 +344,10 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo) + fprintf(fp, ", qos %d", vf_vlan->qos); + if (vf_tx_rate->rate) + fprintf(fp, ", tx rate %d (Mbps)", vf_tx_rate->rate); ++ if (vf_rate->max_tx_rate) ++ fprintf(fp, ", max_tx_rate %dMbps", vf_rate->max_tx_rate); ++ if (vf_rate->min_tx_rate) ++ fprintf(fp, ", min_tx_rate %dMbps", vf_rate->min_tx_rate); + if (vf_spoofchk && vf_spoofchk->setting != -1) { + if (vf_spoofchk->setting) + fprintf(fp, ", spoof checking on"); +@@ -1450,6 +1456,63 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) + return 0; + } + ++static void ++ipaddr_loop_each_vf(struct rtattr *tb[], int vfnum, int *min, int *max) ++{ ++ struct rtattr *vflist = tb[IFLA_VFINFO_LIST]; ++ struct rtattr *i, *vf[IFLA_VF_MAX+1]; ++ struct ifla_vf_rate *vf_rate; ++ int rem; ++ ++ rem = RTA_PAYLOAD(vflist); ++ ++ for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { ++ parse_rtattr_nested(vf, IFLA_VF_MAX, i); ++ vf_rate = RTA_DATA(vf[IFLA_VF_RATE]); ++ if (vf_rate->vf == vfnum) { ++ *min = vf_rate->min_tx_rate; ++ *max = vf_rate->max_tx_rate; ++ return; ++ } ++ } ++ fprintf(stderr, "Cannot find VF %d\n", vfnum); ++ exit(1); ++} ++ ++void ipaddr_get_vf_rate(int vfnum, int *min, int *max, int idx) ++{ ++ struct nlmsg_chain linfo = { NULL, NULL}; ++ struct rtattr *tb[IFLA_MAX+1]; ++ struct ifinfomsg *ifi; ++ struct nlmsg_list *l; ++ struct nlmsghdr *n; ++ int len; ++ ++ if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETLINK) < 0) { ++ perror("Cannot send dump request"); ++ exit(1); ++ } ++ if (rtnl_dump_filter(&rth, store_nlmsg, &linfo) < 0) { ++ fprintf(stderr, "Dump terminated\n"); ++ exit(1); ++ } ++ for (l = linfo.head; l; l = l->next) { ++ n = &l->h; ++ ifi = NLMSG_DATA(n); ++ ++ len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)); ++ if (len < 0 || idx && idx != ifi->ifi_index) ++ continue; ++ ++ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); ++ ++ if ((tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF])) { ++ ipaddr_loop_each_vf(tb, vfnum, min, max); ++ return; ++ } ++ } ++} ++ + int ipaddr_list_link(int argc, char **argv) + { + preferred_family = AF_PACKET; +diff --git a/ip/iplink.c b/ip/iplink.c +index 0098443..bce5ba0 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -233,16 +233,40 @@ struct iplink_req { + }; + + static int iplink_parse_vf(int vf, int *argcp, char ***argvp, +- struct iplink_req *req) ++ struct iplink_req *req, int dev_index) + { ++ char new_rate_api = 0, count = 0, override_legacy_rate = 0; ++ struct ifla_vf_rate tivt; + int len, argc = *argcp; + char **argv = *argvp; + struct rtattr *vfinfo; + ++ tivt.min_tx_rate = -1; ++ tivt.max_tx_rate = -1; ++ + vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO); + + while (NEXT_ARG_OK()) { + NEXT_ARG(); ++ count++; ++ if (!matches(*argv, "max_tx_rate")) { ++ /* new API in use */ ++ new_rate_api = 1; ++ /* override legacy rate */ ++ override_legacy_rate = 1; ++ } else if (!matches(*argv, "min_tx_rate")) { ++ /* new API in use */ ++ new_rate_api = 1; ++ } ++ } ++ ++ while (count--) { ++ /* rewind arg */ ++ PREV_ARG(); ++ } ++ ++ while (NEXT_ARG_OK()) { ++ NEXT_ARG(); + if (matches(*argv, "mac") == 0) { + struct ifla_vf_mac ivm; + NEXT_ARG(); +@@ -279,7 +303,25 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, + invarg("Invalid \"rate\" value\n", *argv); + } + ivt.vf = vf; +- addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE, &ivt, sizeof(ivt)); ++ if (!new_rate_api) ++ addattr_l(&req->n, sizeof(*req), ++ IFLA_VF_TX_RATE, &ivt, sizeof(ivt)); ++ else if (!override_legacy_rate) ++ tivt.max_tx_rate = ivt.rate; ++ ++ } else if (matches(*argv, "max_tx_rate") == 0) { ++ NEXT_ARG(); ++ if (get_unsigned(&tivt.max_tx_rate, *argv, 0)) ++ invarg("Invalid \"max tx rate\" value\n", ++ *argv); ++ tivt.vf = vf; ++ ++ } else if (matches(*argv, "min_tx_rate") == 0) { ++ NEXT_ARG(); ++ if (get_unsigned(&tivt.min_tx_rate, *argv, 0)) ++ invarg("Invalid \"min tx rate\" value\n", ++ *argv); ++ tivt.vf = vf; + + } else if (matches(*argv, "spoofchk") == 0) { + struct ifla_vf_spoofchk ivs; +@@ -337,6 +379,19 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, + } + } + ++ if (new_rate_api) { ++ int tmin, tmax; ++ if (tivt.min_tx_rate == -1 || tivt.max_tx_rate == -1) { ++ ipaddr_get_vf_rate(tivt.vf, &tmin, &tmax, dev_index); ++ if (tivt.min_tx_rate == -1) ++ tivt.min_tx_rate = tmin; ++ if (tivt.max_tx_rate == -1) ++ tivt.max_tx_rate = tmax; ++ } ++ addattr_l(&req->n, sizeof(*req), IFLA_VF_RATE, &tivt, ++ sizeof(tivt)); ++ } ++ + if (argc == *argcp) + incomplete_command(); + +@@ -358,6 +413,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, + int vf = -1; + int numtxqueues = -1; + int numrxqueues = -1; ++ int dev_index; + int link_netnsid = -1; + + *group = -1; +@@ -468,7 +524,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, + } + vflist = addattr_nest(&req->n, sizeof(*req), + IFLA_VFINFO_LIST); +- len = iplink_parse_vf(vf, &argc, &argv, req); ++ len = iplink_parse_vf(vf, &argc, &argv, req, dev_index); + if (len < 0) + return -1; + addattr_nest_end(&req->n, vflist); +@@ -570,6 +626,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, + if (*dev) + duparg2("dev", *argv); + *dev = *argv; ++ dev_index = ll_name_to_index(*dev); + } + argc--; argv++; + } +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 33172e5..741922f 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -106,6 +106,12 @@ ip-link \- network device configuration + .RB "[ " rate + .IR TXRATE " ]" + .br ++.RB "[ " max_tx_rate ++.IR TXRATE " ]" ++.br ++.RB "[ " min_tx_rate ++.IR TXRATE " ]" ++.br + .RB "[ " spoofchk " { " on " | " off " } ]" + .br + .RB "[ " query_rss " { " on " | " off " } ]" +@@ -1021,8 +1027,24 @@ as 0 disables VLAN tagging and filtering for the VF. + + .sp + .BI rate " TXRATE" +-- change the allowed transmit bandwidth, in Mbps, for the specified VF. +-Setting this parameter to 0 disables rate limiting. The ++-- change the allowed transmit bandwidth, in Mbps, for the specified VF. ++Setting this parameter to 0 disables rate limiting. ++.B vf ++parameter must be specified. ++Please use new API ++.B "max_tx_rate" ++option instead. ++ ++.sp ++.BI max_tx_rate " TXRATE" ++- change the allowed maximum transmit bandwidth, in Mbps, for the specified VF. ++.B vf ++parameter must be specified. ++ ++.sp ++.BI min_tx_rate " TXRATE" ++- change the allowed minimum transmit bandwidth, in Mbps, for the specified VF. ++Minimum TXRATE should be always <= Maximum TXRATE. + .B vf + parameter must be specified. + +-- +1.8.3.1 + diff --git a/SOURCES/0220-ip-check-for-missing-dev-arg-when-doing-VF-rate.patch b/SOURCES/0220-ip-check-for-missing-dev-arg-when-doing-VF-rate.patch new file mode 100644 index 0000000..3d25dd8 --- /dev/null +++ b/SOURCES/0220-ip-check-for-missing-dev-arg-when-doing-VF-rate.patch @@ -0,0 +1,66 @@ +From e9c1b5f32fd39ee8a29035fd49e4aea8daa59cf3 Mon Sep 17 00:00:00 2001 +From: Jakub Sitnicki <jkbs@redhat.com> +Date: Wed, 27 Jul 2016 15:56:15 +0200 +Subject: [PATCH] ip: check for missing dev arg when doing VF rate + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1340914 +Upstream Status: iproute2.git commit 9a02651 +Conflicts: +* context in iplink_parse() because we already have + ccdcbf35f120 ("iplink: add support of IFLA_LINK_NETNSID attribute") + +commit 9a02651a87d0fd56e2e7eedd63921a050a42b3ec +Author: Stephen Hemminger <stephen@networkplumber.org> +Date: Mon Jul 14 12:08:05 2014 -0700 + + ip: check for missing dev arg when doing VF rate + + New VF rate code was not handling case where device not specified. + Caught by GCC warning about uninitialized variable. +--- + ip/iplink.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index bce5ba0..7ee015c 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -381,6 +381,7 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, + + if (new_rate_api) { + int tmin, tmax; ++ + if (tivt.min_tx_rate == -1 || tivt.max_tx_rate == -1) { + ipaddr_get_vf_rate(tivt.vf, &tmin, &tmax, dev_index); + if (tivt.min_tx_rate == -1) +@@ -413,7 +414,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, + int vf = -1; + int numtxqueues = -1; + int numrxqueues = -1; +- int dev_index; ++ int dev_index = 0; + int link_netnsid = -1; + + *group = -1; +@@ -524,6 +525,9 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, + } + vflist = addattr_nest(&req->n, sizeof(*req), + IFLA_VFINFO_LIST); ++ if (dev_index == 0) ++ missarg("dev"); ++ + len = iplink_parse_vf(vf, &argc, &argv, req, dev_index); + if (len < 0) + return -1; +@@ -627,6 +631,8 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, + duparg2("dev", *argv); + *dev = *argv; + dev_index = ll_name_to_index(*dev); ++ if (dev_index == 0) ++ invarg("Unknown device", *argv); + } + argc--; argv++; + } +-- +1.8.3.1 + diff --git a/SOURCES/0221-ip-link-Remove-unnecessary-device-checking.patch b/SOURCES/0221-ip-link-Remove-unnecessary-device-checking.patch new file mode 100644 index 0000000..66e9928 --- /dev/null +++ b/SOURCES/0221-ip-link-Remove-unnecessary-device-checking.patch @@ -0,0 +1,44 @@ +From 95a0e54cd3b045b9cd1128c0c8ad00e78f1d61c4 Mon Sep 17 00:00:00 2001 +From: Jakub Sitnicki <jkbs@redhat.com> +Date: Wed, 27 Jul 2016 15:56:16 +0200 +Subject: [PATCH] ip link: Remove unnecessary device checking + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1340914 +Upstream Status: iproute2.git commit f1b66ff + +commit f1b66ff83a0babbe99fef81b3a960d7a4ce8dbc6 +Author: vadimk <vadim4j@gmail.com> +Date: Sat Aug 30 15:06:00 2014 +0300 + + ip link: Remove unnecessary device checking + + The real checking is performed later in iplink_modify(..) func which + checks device existence if NLM_F_CREATE flag is set. + + Also it fixes the case when impossible to add veth link which was + caused by 9a02651a87 (ip: check for missing dev arg when doing VF rate) + because these devices are not exist yet. + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> + Acked-by: Oliver Hartkopp <socketcan@hartkopp.net> + Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> +--- + ip/iplink.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index 7ee015c..461dc95 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -631,8 +631,6 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, + duparg2("dev", *argv); + *dev = *argv; + dev_index = ll_name_to_index(*dev); +- if (dev_index == 0) +- invarg("Unknown device", *argv); + } + argc--; argv++; + } +-- +1.8.3.1 + diff --git a/SOURCES/0222-ip-link-Fix-crash-on-older-kernels-when-show-VF-dev.patch b/SOURCES/0222-ip-link-Fix-crash-on-older-kernels-when-show-VF-dev.patch new file mode 100644 index 0000000..64d47d6 --- /dev/null +++ b/SOURCES/0222-ip-link-Fix-crash-on-older-kernels-when-show-VF-dev.patch @@ -0,0 +1,73 @@ +From ef78dba44078e9e3f4d995bd04faecacc7dd045e Mon Sep 17 00:00:00 2001 +From: Jakub Sitnicki <jkbs@redhat.com> +Date: Wed, 27 Jul 2016 15:56:17 +0200 +Subject: [PATCH] ip link: Fix crash on older kernels when show VF dev + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1340914 +Upstream Status: iproute2.git commit 8c29ae7 + +commit 8c29ae7cc2494e251520584e83698c1a9f1912e5 +Author: Vadim Kochan <vadim4j@gmail.com> +Date: Fri Jan 9 21:24:31 2015 +0200 + + ip link: Fix crash on older kernels when show VF dev + + The issue was caused that ifla_vf_rate does not exist on + older kernels and should be checked if it exists as nested attr. + + Signed-off-by: Vadim Kochan <vadim4j@gmail.com> + Reported-by: William Dauchy <william@gandi.net> + Tested-by: William Dauchy <william@gandi.net> +--- + ip/ipaddress.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 11ff34d..45e747b 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -290,11 +290,10 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo) + { + struct ifla_vf_mac *vf_mac; + struct ifla_vf_vlan *vf_vlan; +- struct ifla_vf_rate *vf_rate; + struct ifla_vf_tx_rate *vf_tx_rate; + struct ifla_vf_spoofchk *vf_spoofchk; + struct ifla_vf_link_state *vf_linkstate; +- struct rtattr *vf[IFLA_VF_MAX+1]; ++ struct rtattr *vf[IFLA_VF_MAX + 1] = {}; + struct rtattr *tmp; + SPRINT_BUF(b1); + +@@ -308,7 +307,6 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo) + vf_mac = RTA_DATA(vf[IFLA_VF_MAC]); + vf_vlan = RTA_DATA(vf[IFLA_VF_VLAN]); + vf_tx_rate = RTA_DATA(vf[IFLA_VF_TX_RATE]); +- vf_rate = RTA_DATA(vf[IFLA_VF_RATE]); + + /* Check if the spoof checking vf info type is supported by + * this kernel. +@@ -344,10 +342,16 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo) + fprintf(fp, ", qos %d", vf_vlan->qos); + if (vf_tx_rate->rate) + fprintf(fp, ", tx rate %d (Mbps)", vf_tx_rate->rate); +- if (vf_rate->max_tx_rate) +- fprintf(fp, ", max_tx_rate %dMbps", vf_rate->max_tx_rate); +- if (vf_rate->min_tx_rate) +- fprintf(fp, ", min_tx_rate %dMbps", vf_rate->min_tx_rate); ++ ++ if (vf[IFLA_VF_RATE]) { ++ struct ifla_vf_rate *vf_rate = RTA_DATA(vf[IFLA_VF_RATE]); ++ ++ if (vf_rate->max_tx_rate) ++ fprintf(fp, ", max_tx_rate %dMbps", vf_rate->max_tx_rate); ++ if (vf_rate->min_tx_rate) ++ fprintf(fp, ", min_tx_rate %dMbps", vf_rate->min_tx_rate); ++ } ++ + if (vf_spoofchk && vf_spoofchk->setting != -1) { + if (vf_spoofchk->setting) + fprintf(fp, ", spoof checking on"); +-- +1.8.3.1 + diff --git a/SOURCES/0223-iplink-Add-missing-variable-initialization.patch b/SOURCES/0223-iplink-Add-missing-variable-initialization.patch new file mode 100644 index 0000000..41ad031 --- /dev/null +++ b/SOURCES/0223-iplink-Add-missing-variable-initialization.patch @@ -0,0 +1,42 @@ +From d3f086bcbaf690e311df10f867005c2b97231231 Mon Sep 17 00:00:00 2001 +From: Jakub Sitnicki <jkbs@redhat.com> +Date: Wed, 27 Jul 2016 15:56:18 +0200 +Subject: [PATCH] iplink: Add missing variable initialization + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1253767 + https://bugzilla.redhat.com/show_bug.cgi?id=1271580 +Upstream Status: iproute2.git commit a89193a +Conflicts: +* context in iplink_parse_vf() because we don't have + 6c5ffb9a2c3d ("iplink: cleanup whitespace and checkpatch issues") + +commit a89193a7d68f59c1ce3bf47a32ff7b73661f1c54 +Author: Phil Sutter <phil@nwl.cc> +Date: Thu Jun 16 16:19:39 2016 +0200 + + iplink: Add missing variable initialization + + Without this, we might feed garbage to the kernel when the address is + shorter than expected. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + ip/iplink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index 461dc95..7b070f4 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -268,7 +268,7 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, + while (NEXT_ARG_OK()) { + NEXT_ARG(); + if (matches(*argv, "mac") == 0) { +- struct ifla_vf_mac ivm; ++ struct ifla_vf_mac ivm = { 0 }; + NEXT_ARG(); + ivm.vf = vf; + len = ll_addr_a2n((char *)ivm.mac, 32, *argv); +-- +1.8.3.1 + diff --git a/SOURCES/0224-iplink-Check-address-length-via-netlink.patch b/SOURCES/0224-iplink-Check-address-length-via-netlink.patch new file mode 100644 index 0000000..2418a59 --- /dev/null +++ b/SOURCES/0224-iplink-Check-address-length-via-netlink.patch @@ -0,0 +1,136 @@ +From 7bfe1d25875b2fef1cfd679fdd8c4a999928bb80 Mon Sep 17 00:00:00 2001 +From: Jakub Sitnicki <jkbs@redhat.com> +Date: Wed, 27 Jul 2016 15:56:19 +0200 +Subject: [PATCH] iplink: Check address length via netlink + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1253767 + https://bugzilla.redhat.com/show_bug.cgi?id=1271580 +Upstream Status: iproute2.git commit 8fe58d5 +Conflicts: +* context in iplink_parse_vf() because we don't have + 6c5ffb9a2c3d ("iplink: cleanup whitespace and checkpatch issues") + +commit 8fe58d58941f440140986f444c3d040b5e350c87 +Author: Phil Sutter <phil@nwl.cc> +Date: Thu Jun 16 16:19:40 2016 +0200 + + iplink: Check address length via netlink + + This is a feature which was lost during the conversion to netlink + interface: If the device exists and a user tries to change the link + layer address, query the kernel for the old address first and reject the + new one if sizes differ. + + This patch adds the same check when setting VF address by assuming same + length as PF device. + + Note that at least for VFs the check can't be done in kernel space since + struct ifla_vf_mac lacks a length field and due to netlink padding the + exact size can't be communicated to the kernel. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + ip/iplink.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 50 insertions(+), 2 deletions(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index 7b070f4..a8bcc09 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -232,6 +232,36 @@ struct iplink_req { + char buf[1024]; + }; + ++static int nl_get_ll_addr_len(unsigned int dev_index) ++{ ++ int len; ++ struct iplink_req req = { ++ .n = { ++ .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), ++ .nlmsg_type = RTM_GETLINK, ++ .nlmsg_flags = NLM_F_REQUEST ++ }, ++ .i = { ++ .ifi_family = preferred_family, ++ .ifi_index = dev_index, ++ } ++ }; ++ struct rtattr *tb[IFLA_MAX+1]; ++ ++ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) ++ return -1; ++ ++ len = req.n.nlmsg_len - NLMSG_LENGTH(sizeof(req.i)); ++ if (len < 0) ++ return -1; ++ ++ parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(&req.i), len, NLA_F_NESTED); ++ if (!tb[IFLA_ADDRESS]) ++ return -1; ++ ++ return RTA_PAYLOAD(tb[IFLA_ADDRESS]); ++} ++ + static int iplink_parse_vf(int vf, int *argcp, char ***argvp, + struct iplink_req *req, int dev_index) + { +@@ -269,11 +299,18 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, + NEXT_ARG(); + if (matches(*argv, "mac") == 0) { + struct ifla_vf_mac ivm = { 0 }; ++ int halen = nl_get_ll_addr_len(dev_index); + NEXT_ARG(); + ivm.vf = vf; + len = ll_addr_a2n((char *)ivm.mac, 32, *argv); + if (len < 0) + return -1; ++ if (halen > 0 && len != halen) { ++ fprintf(stderr, ++ "Invalid address length %d - must be %d bytes\n", ++ len, halen); ++ return -1; ++ } + addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm, sizeof(ivm)); + } else if (matches(*argv, "vlan") == 0) { + struct ifla_vf_vlan ivv; +@@ -416,6 +453,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, + int numrxqueues = -1; + int dev_index = 0; + int link_netnsid = -1; ++ int addr_len = 0; + + *group = -1; + ret = argc; +@@ -435,10 +473,10 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, + *link = *argv; + } else if (matches(*argv, "address") == 0) { + NEXT_ARG(); +- len = ll_addr_a2n(abuf, sizeof(abuf), *argv); ++ addr_len = ll_addr_a2n(abuf, sizeof(abuf), *argv); + if (len < 0) + return -1; +- addattr_l(&req->n, sizeof(*req), IFLA_ADDRESS, abuf, len); ++ addattr_l(&req->n, sizeof(*req), IFLA_ADDRESS, abuf, addr_len); + } else if (matches(*argv, "broadcast") == 0 || + strcmp(*argv, "brd") == 0) { + NEXT_ARG(); +@@ -635,6 +673,16 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, + argc--; argv++; + } + ++ if (dev_index && addr_len) { ++ int halen = nl_get_ll_addr_len(dev_index); ++ if (halen >= 0 && halen != addr_len) { ++ fprintf(stderr, ++ "Invalid address length %d - must be %d bytes\n", ++ addr_len, halen); ++ return -1; ++ } ++ } ++ + return ret - argc; + } + +-- +1.8.3.1 + diff --git a/SOURCES/0225-Fix-MAC-address-length-check.patch b/SOURCES/0225-Fix-MAC-address-length-check.patch new file mode 100644 index 0000000..740f8fb --- /dev/null +++ b/SOURCES/0225-Fix-MAC-address-length-check.patch @@ -0,0 +1,39 @@ +From b6e8abac9c09c000f0b3f20ec3855f30aa1a4135 Mon Sep 17 00:00:00 2001 +From: Jakub Sitnicki <jkbs@redhat.com> +Date: Wed, 27 Jul 2016 15:56:20 +0200 +Subject: [PATCH] Fix MAC address length check + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1253767 + https://bugzilla.redhat.com/show_bug.cgi?id=1271580 +Upstream Status: iproute2.git commit 0aae234 + +commit 0aae23468ac57924c040ef4588ecd6b6dcb33075 +Author: Phil Sutter <phil@nwl.cc> +Date: Wed Jun 22 12:05:38 2016 +0200 + + Fix MAC address length check + + I forgot to change the variable in the conditional, too. + + Fixes: 8fe58d58941f4 ("iplink: Check address length via netlink") + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + ip/iplink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iplink.c b/ip/iplink.c +index a8bcc09..f49b32e 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -474,7 +474,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, + } else if (matches(*argv, "address") == 0) { + NEXT_ARG(); + addr_len = ll_addr_a2n(abuf, sizeof(abuf), *argv); +- if (len < 0) ++ if (addr_len < 0) + return -1; + addattr_l(&req->n, sizeof(*req), IFLA_ADDRESS, abuf, addr_len); + } else if (matches(*argv, "broadcast") == 0 || +-- +1.8.3.1 + diff --git a/SOURCES/0226-ip-add-paren-to-silence-warning.patch b/SOURCES/0226-ip-add-paren-to-silence-warning.patch new file mode 100644 index 0000000..1eb2976 --- /dev/null +++ b/SOURCES/0226-ip-add-paren-to-silence-warning.patch @@ -0,0 +1,35 @@ +From e711f1b53b6d8cb7d067935d3bddccf289fe486e Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 27 Jul 2016 17:26:55 +0200 +Subject: [PATCH] ip: add paren to silence warning + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1340914 +Upstream Status: iproute2.git commit 1199c4f569175 + +commit 1199c4f569175e09a33bf6b1af3a8faadbf9dc04 +Author: Stephen Hemminger <stephen@networkplumber.org> +Date: Mon Jul 14 12:06:52 2014 -0700 + + ip: add paren to silence warning + + Gcc doesn't like mixed || and && in same conditional. +--- + ip/ipaddress.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 45e747b..112c34b 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -1505,7 +1505,7 @@ void ipaddr_get_vf_rate(int vfnum, int *min, int *max, int idx) + ifi = NLMSG_DATA(n); + + len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)); +- if (len < 0 || idx && idx != ifi->ifi_index) ++ if (len < 0 || (idx && idx != ifi->ifi_index)) + continue; + + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); +-- +1.8.3.1 + diff --git a/SOURCES/0227-doc-man-ip-rule-Remove-incorrect-statement-about-rul.patch b/SOURCES/0227-doc-man-ip-rule-Remove-incorrect-statement-about-rul.patch new file mode 100644 index 0000000..e4568d1 --- /dev/null +++ b/SOURCES/0227-doc-man-ip-rule-Remove-incorrect-statement-about-rul.patch @@ -0,0 +1,53 @@ +From 8d15023372324cddbb517976e57a7cee76ab9bbb Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Tue, 2 Aug 2016 18:08:20 +0200 +Subject: [PATCH] doc, man: ip-rule: Remove incorrect statement about rule 0 + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1362561 +Upstream Status: iproute2.git commit 0ce05841d58b4 + +commit 0ce05841d58b42ef39ce7144dc31e77970e5d2e0 +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Mar 4 12:52:41 2016 +0100 + + doc, man: ip-rule: Remove incorrect statement about rule 0 + + The documentation is wrong here: it is indeed possible to remove policy + rule 0 and recreate it afterwards. Therefore remove these statements. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + doc/ip-cref.tex | 3 --- + man/man8/ip-rule.8 | 2 -- + 2 files changed, 5 deletions(-) + +diff --git a/doc/ip-cref.tex b/doc/ip-cref.tex +index d8fed66..bdd3010 100644 +--- a/doc/ip-cref.tex ++++ b/doc/ip-cref.tex +@@ -2003,9 +2003,6 @@ table \verb|local| (ID 255). + The \verb|local| table is a special routing table containing + high priority control routes for local and broadcast addresses. + +-Rule 0 is special. It cannot be deleted or overridden. +- +- + \item Priority: 32766, Selector: match anything, Action: lookup routing + table \verb|main| (ID 254). + The \verb|main| table is the normal routing table containing all non-policy +diff --git a/man/man8/ip-rule.8 b/man/man8/ip-rule.8 +index 0661061..5274ef0 100644 +--- a/man/man8/ip-rule.8 ++++ b/man/man8/ip-rule.8 +@@ -111,8 +111,6 @@ The + .B local + table is a special routing table containing + high priority control routes for local and broadcast addresses. +-.sp +-Rule 0 is special. It cannot be deleted or overridden. + + .TP + 2. +-- +1.8.3.1 + diff --git a/SOURCES/0228-man-ip-link-ip-address-Drop-references-to-ipvlan.patch b/SOURCES/0228-man-ip-link-ip-address-Drop-references-to-ipvlan.patch new file mode 100644 index 0000000..dcd9d07 --- /dev/null +++ b/SOURCES/0228-man-ip-link-ip-address-Drop-references-to-ipvlan.patch @@ -0,0 +1,52 @@ +From 216b8610970df1369d4459105fcc15658d1bf029 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 3 Aug 2016 13:12:05 +0200 +Subject: [PATCH] man: ip-link, ip-address: Drop references to ipvlan + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1013584 +Upstream Status: RHEL only + +Since we don't support ipvlan in RHEL, remove all references to this +interface type which were added by accident. +--- + man/man8/ip-address.8.in | 1 - + man/man8/ip-link.8.in | 4 ---- + 2 files changed, 5 deletions(-) + +diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in +index c954ab3..08a79ec 100644 +--- a/man/man8/ip-address.8.in ++++ b/man/man8/ip-address.8.in +@@ -120,7 +120,6 @@ ip-address \- protocol address management + .BR ip6gretap " |" + .BR vti " |" + .BR nlmon " |" +-.BR ipvlan " |" + .BR lowpan " |" + .BR geneve " ]" + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 741922f..dc9728c 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -167,7 +167,6 @@ ip-link \- network device configuration + .BR ip6gretap " |" + .BR vti " |" + .BR nlmon " |" +-.BR ipvlan " |" + .BR geneve " ]" + + .ti -8 +@@ -250,9 +249,6 @@ Link types: + .BR nlmon + - Netlink monitoring device + .sp +-.BR ipvlan +-- Interface for L3 (IPv6/IPv4) based VLANs +-.sp + .BR geneve + - GEneric NEtwork Virtualization Encapsulation + .sp +-- +1.8.3.1 + diff --git a/SOURCES/0229-man-ip-link-Drop-fou-and-gue-related-documentation.patch b/SOURCES/0229-man-ip-link-Drop-fou-and-gue-related-documentation.patch new file mode 100644 index 0000000..057a061 --- /dev/null +++ b/SOURCES/0229-man-ip-link-Drop-fou-and-gue-related-documentation.patch @@ -0,0 +1,88 @@ +From 53c41b7d2b6e2a37065e7963fa9c0938b9d936d2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 3 Aug 2016 13:19:05 +0200 +Subject: [PATCH] man: ip-link: Drop fou and gue related documentation + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1013584 +Upstream Status: RHEL only + +This is a partial revert of commit 90f1df715eb38 ("iproute: Descriptions +of fou and gue options in ip-link man pages") which, besides useful +additions, also documents options not supported in iproute as shipped +with RHEL7. +--- + man/man8/ip-link.8.in | 44 -------------------------------------------- + 1 file changed, 44 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index dc9728c..b9d9933 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -511,17 +511,6 @@ the following additional arguments are supported: + .BI "ip link add " DEVICE + .BR type " { " gre " | " ipip " | " sit " }" + .BI " remote " ADDR " local " ADDR +-[ +-.BR encap " { " fou " | " gue " | " none " }" +-] [ +-.BR encap-sport " { " \fIPORT " | " auto " }" +-] [ +-.BI "encap-dport " PORT +-] [ +-.RB [ no ] encap-csum +-] [ +-.RB [ no ] encap-remcsum +-] + + .in +8 + .sp +@@ -533,30 +522,6 @@ the following additional arguments are supported: + - specifies the fixed local address for tunneled packets. + It must be an address on another interface on this host. + +-.sp +-.BR encap " { " fou " | " gue " | " none " }" +-- specifies type of secondary UDP encapsulation. "fou" indicates +-Foo-Over-UDP, "gue" indicates Generic UDP Encapsulation. +- +-.sp +-.BR encap-sport " { " \fIPORT " | " auto " }" +-- specifies the source port in UDP encapsulation. +-.IR PORT +-indicates the port by number, "auto" +-indicates that the port number should be chosen automatically +-(the kernel picks a flow based on the flow hash of the +-encapsulated packet). +- +-.sp +-.RB [ no ] encap-csum +-- specifies if UDP checksums are enabled in the secondary +-encapsulation. +- +-.sp +-.RB [ no ] encap-remcsum +-- specifies if Remote Checksum Offload is enabled. This is only +-applicable for Generic UDP Encapsulation. +- + .in -8 + + .TP +@@ -1293,15 +1258,6 @@ ip link help gre + .RS 4 + Display help for the gre link type. + .RE +-.PP +-ip link add name tun1 type ipip remote 192.168.1.1 +-local 192.168.1.2 ttl 225 encap gue encap-sport auto +-encap-dport 5555 encap-csum encap-remcsum +-.RS 4 +-Creates an IPIP that is encapsulated with Generic UDP Encapsulation, +-and the outer UDP checksum and remote checksum offload are enabled. +- +-.RE + + .SH SEE ALSO + .br +-- +1.8.3.1 + diff --git a/SOURCES/0230-Revert-ip-fix-exit-code-for-rule-failures.patch b/SOURCES/0230-Revert-ip-fix-exit-code-for-rule-failures.patch new file mode 100644 index 0000000..701570c --- /dev/null +++ b/SOURCES/0230-Revert-ip-fix-exit-code-for-rule-failures.patch @@ -0,0 +1,28 @@ +From 97a3579120732908e937505fa91966e9fc5098a6 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 3 Aug 2016 13:25:08 +0200 +Subject: [PATCH] Revert "ip: fix exit code for rule failures" + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 + +This reverts commit edc209d4479b6b89aed9cb5b661002cf27031bea. +--- + ip/iprule.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iprule.c b/ip/iprule.c +index 2a153f5..63d7fcc 100644 +--- a/ip/iprule.c ++++ b/ip/iprule.c +@@ -358,7 +358,7 @@ static int iprule_modify(int cmd, int argc, char **argv) + req.r.rtm_table = RT_TABLE_MAIN; + + if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) +- return -2; ++ return 2; + + return 0; + } +-- +1.8.3.1 + diff --git a/SOURCES/0231-Revert-ip-return-correct-exit-code-on-route-failure.patch b/SOURCES/0231-Revert-ip-return-correct-exit-code-on-route-failure.patch new file mode 100644 index 0000000..41bfe19 --- /dev/null +++ b/SOURCES/0231-Revert-ip-return-correct-exit-code-on-route-failure.patch @@ -0,0 +1,28 @@ +From 6bcd2f4cc935039d7360fba0cb5a55de5131199d Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 3 Aug 2016 13:26:25 +0200 +Subject: [PATCH] Revert "ip: return correct exit code on route failure" + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 + +This reverts commit daba15cd1437d136cfd3f09bd42d7c79ffa3d517. +--- + ip/iproute.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index 094566a..378bdba 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -1083,7 +1083,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) + req.r.rtm_family = AF_INET; + + if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) +- return -2; ++ return -1; + + return 0; + } +-- +1.8.3.1 + diff --git a/SOURCES/0232-Revert-link-dump-filter.patch b/SOURCES/0232-Revert-link-dump-filter.patch new file mode 100644 index 0000000..440353e --- /dev/null +++ b/SOURCES/0232-Revert-link-dump-filter.patch @@ -0,0 +1,99 @@ +From 79b2060582ed044feb9d703e9f13c620fb64c389 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 3 Aug 2016 13:28:09 +0200 +Subject: [PATCH] Revert "link dump filter" + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 + +This reverts commit 83e4e4b09ca5ca91ab54fe983c1786e04b7ba41b. +--- + ip/ip_common.h | 1 - + ip/ipaddress.c | 13 ------------- + ip/iplink.c | 35 ----------------------------------- + 3 files changed, 49 deletions(-) + +diff --git a/ip/ip_common.h b/ip/ip_common.h +index 286f61f..42eda66 100644 +--- a/ip/ip_common.h ++++ b/ip/ip_common.h +@@ -56,7 +56,6 @@ extern int do_ipl2tp(int argc, char **argv); + extern int do_tcp_metrics(int argc, char **argv); + extern int do_ipnetconf(int argc, char **argv); + extern int do_iptoken(int argc, char **argv); +-extern int iplink_get(unsigned int flags, char *name, __u32 filt_mask); + + static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb) + { +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 112c34b..97a8f2f 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -1400,19 +1400,6 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) + exit(0); + } + +- /* +- * If only filter_dev present and none of the other +- * link filters are present, use RTM_GETLINK to get +- * the link device +- */ +- if (filter_dev && filter.group == -1 && do_link == 1) { +- if (iplink_get(0, filter_dev, RTEXT_FILTER_VF) < 0) { +- perror("Cannot send link get request"); +- exit(1); +- } +- exit(0); +- } +- + if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) { + perror("Cannot send dump request"); + exit(1); +diff --git a/ip/iplink.c b/ip/iplink.c +index f49b32e..3dac893 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -827,41 +827,6 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) + return 0; + } + +-int iplink_get(unsigned int flags, char *name, __u32 filt_mask) +-{ +- int len; +- struct iplink_req req; +- struct { +- struct nlmsghdr n; +- char buf[16384]; +- } answer; +- +- memset(&req, 0, sizeof(req)); +- +- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); +- req.n.nlmsg_flags = NLM_F_REQUEST|flags; +- req.n.nlmsg_type = RTM_GETLINK; +- req.i.ifi_family = preferred_family; +- +- if (name) { +- len = strlen(name) + 1; +- if (len == 1) +- invarg("\"\" is not a valid device identifier\n", +- "name"); +- if (len > IFNAMSIZ) +- invarg("\"name\" too long\n", name); +- addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, len); +- } +- addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask); +- +- if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0) +- return -2; +- +- print_linkinfo(NULL, &answer.n, stdout); +- +- return 0; +-} +- + #if IPLINK_IOCTL_COMPAT + static int get_ctl_fd(void) + { +-- +1.8.3.1 + diff --git a/SOURCES/0233-Revert-ip-fix-exit-code-for-addrlabel.patch b/SOURCES/0233-Revert-ip-fix-exit-code-for-addrlabel.patch new file mode 100644 index 0000000..5271b62 --- /dev/null +++ b/SOURCES/0233-Revert-ip-fix-exit-code-for-addrlabel.patch @@ -0,0 +1,43 @@ +From d1481d4882f12d786afb9eb78a255ea78ea3a7c5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 3 Aug 2016 13:29:11 +0200 +Subject: [PATCH] Revert "ip: fix exit code for addrlabel" + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 + +This reverts commit 205034e561dbc0e1fa380970130b28188870c265. +--- + ip/ipaddrlabel.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c +index 7f25f0b..a0b6e6f 100644 +--- a/ip/ipaddrlabel.c ++++ b/ip/ipaddrlabel.c +@@ -185,7 +185,7 @@ static int ipaddrlabel_modify(int cmd, int argc, char **argv) + req.ifal.ifal_family = AF_INET6; + + if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) +- return -2; ++ return 2; + + return 0; + } +@@ -234,12 +234,12 @@ static int ipaddrlabel_flush(int argc, char **argv) + + if (rtnl_wilddump_request(&rth, af, RTM_GETADDRLABEL) < 0) { + perror("Cannot send dump request"); +- return -1; ++ return 1; + } + + if (rtnl_dump_filter(&rth, flush_addrlabel, NULL) < 0) { + fprintf(stderr, "Flush terminated\n"); +- return -1; ++ return 1; + } + + return 0; +-- +1.8.3.1 + diff --git a/SOURCES/0234-Revert-fix-ip-force-batch-to-continue-on-errors.patch b/SOURCES/0234-Revert-fix-ip-force-batch-to-continue-on-errors.patch new file mode 100644 index 0000000..a195ee6 --- /dev/null +++ b/SOURCES/0234-Revert-fix-ip-force-batch-to-continue-on-errors.patch @@ -0,0 +1,194 @@ +From bfc6f79b96a6ce78c9ab57454d94ba983adb81a8 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 3 Aug 2016 13:31:13 +0200 +Subject: [PATCH] Revert "fix ip -force -batch to continue on errors" + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 + +This reverts commit 03f8f5811ebc0f8fac1c3ccb76c14007d250bd38. +--- + bridge/fdb.c | 6 +++--- + bridge/link.c | 18 +++++++++--------- + bridge/mdb.c | 8 ++++---- + bridge/vlan.c | 4 ++-- + ip/iproute.c | 2 +- + 5 files changed, 19 insertions(+), 19 deletions(-) + +diff --git a/bridge/fdb.c b/bridge/fdb.c +index 6dc3153..0191c76 100644 +--- a/bridge/fdb.c ++++ b/bridge/fdb.c +@@ -287,7 +287,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv) + + if (d == NULL || addr == NULL) { + fprintf(stderr, "Device and address are required arguments.\n"); +- return -1; ++ exit(-1); + } + + /* Assume self */ +@@ -302,7 +302,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv) + abuf, abuf+1, abuf+2, + abuf+3, abuf+4, abuf+5) != 6) { + fprintf(stderr, "Invalid mac address %s\n", addr); +- return -1; ++ exit(-1); + } + + addattr_l(&req.n, sizeof(req), NDA_LLADDR, abuf, ETH_ALEN); +@@ -330,7 +330,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv) + } + + if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) +- return -1; ++ exit(2); + + return 0; + } +diff --git a/bridge/link.c b/bridge/link.c +index 02777d6..861100d 100644 +--- a/bridge/link.c ++++ b/bridge/link.c +@@ -268,19 +268,19 @@ static int brlink_modify(int argc, char **argv) + } else if (strcmp(*argv, "guard") == 0) { + NEXT_ARG(); + if (!on_off("guard", &bpdu_guard, *argv)) +- return -1; ++ exit(-1); + } else if (strcmp(*argv, "hairpin") == 0) { + NEXT_ARG(); + if (!on_off("hairping", &hairpin, *argv)) +- return -1; ++ exit(-1); + } else if (strcmp(*argv, "fastleave") == 0) { + NEXT_ARG(); + if (!on_off("fastleave", &fast_leave, *argv)) +- return -1; ++ exit(-1); + } else if (strcmp(*argv, "root_block") == 0) { + NEXT_ARG(); + if (!on_off("root_block", &root_block, *argv)) +- return -1; ++ exit(-1); + } else if (strcmp(*argv, "cost") == 0) { + NEXT_ARG(); + cost = atoi(*argv); +@@ -299,7 +299,7 @@ static int brlink_modify(int argc, char **argv) + if (state == nstates) { + fprintf(stderr, + "Error: invalid STP port state\n"); +- return -1; ++ exit(-1); + } + } + } else if (strcmp(*argv, "hwmode") == 0) { +@@ -313,7 +313,7 @@ static int brlink_modify(int argc, char **argv) + fprintf(stderr, + "Mode argument must be \"vepa\" or " + "\"veb\".\n"); +- return -1; ++ exit(-1); + } + } else { + usage(); +@@ -322,14 +322,14 @@ static int brlink_modify(int argc, char **argv) + } + if (d == NULL) { + fprintf(stderr, "Device is a required argument.\n"); +- return -1; ++ exit(-1); + } + + + req.ifm.ifi_index = ll_name_to_index(d); + if (req.ifm.ifi_index == 0) { + fprintf(stderr, "Cannot find bridge device \"%s\"\n", d); +- return -1; ++ exit(-1); + } + + /* Nested PROTINFO attribute. Contains: port flags, cost, priority and +@@ -377,7 +377,7 @@ static int brlink_modify(int argc, char **argv) + } + + if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) +- return -1; ++ exit(2); + + return 0; + } +diff --git a/bridge/mdb.c b/bridge/mdb.c +index 821f575..1cd03e0 100644 +--- a/bridge/mdb.c ++++ b/bridge/mdb.c +@@ -145,12 +145,12 @@ static int mdb_show(int argc, char **argv) + + if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETMDB) < 0) { + perror("Cannot send dump request"); +- return -1; ++ exit(1); + } + + if (rtnl_dump_filter(&rth, print_mdb, stdout) < 0) { + fprintf(stderr, "Dump terminated\n"); +- return -1; ++ exit(1); + } + + return 0; +@@ -198,7 +198,7 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv) + + if (d == NULL || grp == NULL || p == NULL) { + fprintf(stderr, "Device, group address and port name are required arguments.\n"); +- return -1; ++ exit(-1); + } + + req.bpm.ifindex = ll_name_to_index(d); +@@ -225,7 +225,7 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv) + addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry)); + + if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) +- return -1; ++ exit(2); + + return 0; + } +diff --git a/bridge/vlan.c b/bridge/vlan.c +index b471bf7..54e10d0 100644 +--- a/bridge/vlan.c ++++ b/bridge/vlan.c +@@ -69,7 +69,7 @@ static int vlan_modify(int cmd, int argc, char **argv) + + if (d == NULL || vid == -1) { + fprintf(stderr, "Device and VLAN ID are required arguments.\n"); +- return -1; ++ exit(-1); + } + + req.ifm.ifi_index = ll_name_to_index(d); +@@ -96,7 +96,7 @@ static int vlan_modify(int cmd, int argc, char **argv) + addattr_nest_end(&req.n, afspec); + + if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) +- return -1; ++ exit(2); + + return 0; + } +diff --git a/ip/iproute.c b/ip/iproute.c +index 378bdba..b7057b3 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -1083,7 +1083,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) + req.r.rtm_family = AF_INET; + + if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) +- return -1; ++ exit(2); + + return 0; + } +-- +1.8.3.1 + diff --git a/SOURCES/0235-Revert-Allow-specifying-bridge-port-STP-state-by-nam.patch b/SOURCES/0235-Revert-Allow-specifying-bridge-port-STP-state-by-nam.patch new file mode 100644 index 0000000..16a32b8 --- /dev/null +++ b/SOURCES/0235-Revert-Allow-specifying-bridge-port-STP-state-by-nam.patch @@ -0,0 +1,57 @@ +From 1ae6a8011c996122c66a9ea791a7540e8f541b1c Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Wed, 3 Aug 2016 13:31:51 +0200 +Subject: [PATCH] Revert "Allow specifying bridge port STP state by name rather + than number." + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1288042 + +This reverts commit a5087426d103b65fcfd85dc0f71c5bedc3a23148. +--- + bridge/link.c | 14 +------------- + man/man8/bridge.8 | 4 +--- + 2 files changed, 2 insertions(+), 16 deletions(-) + +diff --git a/bridge/link.c b/bridge/link.c +index 861100d..19d0642 100644 +--- a/bridge/link.c ++++ b/bridge/link.c +@@ -289,19 +289,7 @@ static int brlink_modify(int argc, char **argv) + priority = atoi(*argv); + } else if (strcmp(*argv, "state") == 0) { + NEXT_ARG(); +- char *endptr; +- size_t nstates = sizeof(port_states) / sizeof(*port_states); +- state = strtol(*argv, &endptr, 10); +- if (!(**argv != '\0' && *endptr == '\0')) { +- for (state = 0; state < nstates; state++) +- if (strcmp(port_states[state], *argv) == 0) +- break; +- if (state == nstates) { +- fprintf(stderr, +- "Error: invalid STP port state\n"); +- exit(-1); +- } +- } ++ state = atoi(*argv); + } else if (strcmp(*argv, "hwmode") == 0) { + NEXT_ARG(); + flags = BRIDGE_FLAGS_SELF; +diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 +index 3cda7d6..4f48546 100644 +--- a/man/man8/bridge.8 ++++ b/man/man8/bridge.8 +@@ -204,9 +204,7 @@ droot port selectio algorithms. + .TP + .BI state " STATE " + the operation state of the port. This is primarily used by user space STP/RSTP +-implementation. One may enter a lowercased port state name, or one of the +-numbers below. Negative inputs are ignored, and unrecognized names return an +-error. ++implementation. The following is a list of valid values: + + .B 0 + - port is DISABLED. Make this port completely inactive. +-- +1.8.3.1 + diff --git a/SOURCES/0236-man-macsec-fix-macsec-related-typos.patch b/SOURCES/0236-man-macsec-fix-macsec-related-typos.patch new file mode 100644 index 0000000..42e28a7 --- /dev/null +++ b/SOURCES/0236-man-macsec-fix-macsec-related-typos.patch @@ -0,0 +1,109 @@ +From 6e7aaccce27c114aad2ef88aa2bf11844ad0282c Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 3 Aug 2016 17:22:09 +0200 +Subject: [PATCH] man: macsec: fix macsec related typos + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1354702 +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1354319 +Upstream Status: iproute2.git commit c0ab80a4907a + +commit c0ab80a4907a102e48b3a8f4150e77671e5af81d +Author: Davide Caratti <dcaratti@redhat.com> +Date: Tue Jul 26 11:03:18 2016 +0200 + + man: macsec: fix macsec related typos + + - ip-macsec.8: fix wrong 'device' keyword in 'ip link add device eth0'; + add missing description of 'validate' keyword; remove spurious bracket + near 'encrypt' keyword; add missing reference to configuration of 'port' + and 'sci' + - ip-link.8 fix wrong 'es' and 'encoding' keywords in MACsec section + + Signed-off-by: Davide Caratti <dcaratti@redhat.com> + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + man/man8/ip-link.8.in | 8 ++++---- + man/man8/ip-macsec.8 | 11 ++++++++--- + 2 files changed, 12 insertions(+), 7 deletions(-) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index b9d9933..9acb6b2 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -755,14 +755,14 @@ the following additional arguments are supported: + .BR encrypt " {" + .BR on " | " off " } ] [ " + .BR send_sci " { " on " | " off " } ] [" +-.BR es " { " on " | " off " } ] [" ++.BR end_station " { " on " | " off " } ] [" + .BR scb " { " on " | " off " } ] [" + .BR protect " { " on " | " off " } ] [" + .BR replay " { " on " | " off " }" + .BR window " { " + .IR 0..2^32-1 " } ] [" + .BR validate " { " strict " | " check " | " disabled " } ] [" +-.BR encoding " { " ++.BR encodingsa " { " + .IR 0..3 " } ]" + + .in +8 +@@ -787,7 +787,7 @@ the following additional arguments are supported: + - specifies whether the SCI is included in every packet, or only when it is necessary. + + .sp +-.BR "es on " or " es off" ++.BR "end_station on " or " end_station off" + - sets the End Station bit. + + .sp +@@ -815,7 +815,7 @@ the following additional arguments are supported: + - sets the validation mode on the device. + + .sp +-.BI encoding " AN " ++.BI encodingsa " AN " + - sets the active secure association for transmission. + + .in -8 +diff --git a/man/man8/ip-macsec.8 b/man/man8/ip-macsec.8 +index e8455d7..f928c43 100644 +--- a/man/man8/ip-macsec.8 ++++ b/man/man8/ip-macsec.8 +@@ -3,10 +3,14 @@ + ip-macsec \- MACsec device configuration + .SH "SYNOPSIS" + .BI "ip link add link " DEVICE " name " NAME " type macsec " +-[ [ ++[ ++.BI port " PORT" ++| ++.BI sci " SCI" ++] [ [ + .BR cipher " { " default " | " gcm-aes-128 " } ] " + .BI icvlen " ICVLEN" +-] [ [ ++] [ + .BR encrypt " { " on " | " off " } ] [" + .BR send_sci " { " on " | " off " } ] [" + .BR end_station " { " on " | " off " } ] [" +@@ -15,6 +19,7 @@ ip-macsec \- MACsec device configuration + .BR replay " { " on " | " off " } ] [" + .BI window " WINDOW" + ] [ ++.BR validate " { " strict " | " check " | " disabled " } ] [" + .BI encodingsa " SA" + ] + +@@ -74,7 +79,7 @@ type. + .PP + .SS Create a MACsec device on link eth0 + .nf +-# ip link add device eth0 macsec0 type macsec port 11 encrypt on ++# ip link add link eth0 macsec0 type macsec port 11 encrypt on + .PP + .SS Configure a secure association on that device + .nf +-- +1.8.3.1 + diff --git a/SOURCES/0237-ip-link-address-add-macsec-item-to-TYPE-list.patch b/SOURCES/0237-ip-link-address-add-macsec-item-to-TYPE-list.patch new file mode 100644 index 0000000..1a577af --- /dev/null +++ b/SOURCES/0237-ip-link-address-add-macsec-item-to-TYPE-list.patch @@ -0,0 +1,87 @@ +From 594bd9247ca5f02d46a8a94bc25f9edf2e82f6d3 Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 3 Aug 2016 17:22:10 +0200 +Subject: [PATCH] ip {link,address}: add 'macsec' item to TYPE list + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1354702 +Upstream Status: iproute2.git commit fd4df5b21180 +Conflicts: context conflicts in TYPE lists due to missing HSR, lowpan +and VRF support, and because of upstream commit 577cfe0b677e not yet +merged. + +commit fd4df5b21180f9b32259d859e6fcbbb08d0e03c4 +Author: Davide Caratti <dcaratti@redhat.com> +Date: Tue Jul 26 11:03:19 2016 +0200 + + ip {link,address}: add 'macsec' item to TYPE list + + fix output of "ip address help" and "ip link help". Update TYPE list in man + pages ip-address.8 and ip-link.8 as well. + + Signed-off-by: Davide Caratti <dcaratti@redhat.com> + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + ip/ipaddress.c | 2 +- + ip/iplink.c | 2 +- + man/man8/ip-address.8.in | 3 ++- + man/man8/ip-link.8.in | 3 ++- + 4 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/ip/ipaddress.c b/ip/ipaddress.c +index 97a8f2f..62a25bc 100644 +--- a/ip/ipaddress.c ++++ b/ip/ipaddress.c +@@ -94,7 +94,7 @@ static void usage(void) + fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n"); + fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n"); + fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n"); +- fprintf(stderr, " bond_slave | ipvlan | geneve | bridge_slave | vrf }\n"); ++ fprintf(stderr, " bond_slave | ipvlan | geneve | bridge_slave | vrf | macsec }\n"); + + exit(-1); + } +diff --git a/ip/iplink.c b/ip/iplink.c +index 3dac893..e9c2874 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -95,7 +95,7 @@ void iplink_usage(void) + fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |\n"); + fprintf(stderr, " bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |\n"); + fprintf(stderr, " gre | gretap | ip6gre | ip6gretap | vti | nlmon |\n"); +- fprintf(stderr, " bond_slave | geneve }\n"); ++ fprintf(stderr, " bond_slave | geneve | macsec }\n"); + } + exit(-1); + } +diff --git a/man/man8/ip-address.8.in b/man/man8/ip-address.8.in +index 08a79ec..be514ca 100644 +--- a/man/man8/ip-address.8.in ++++ b/man/man8/ip-address.8.in +@@ -121,7 +121,8 @@ ip-address \- protocol address management + .BR vti " |" + .BR nlmon " |" + .BR lowpan " |" +-.BR geneve " ]" ++.BR geneve " |" ++.BR macsec " ]" + + .SH "DESCRIPTION" + The +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 9acb6b2..2633521 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -167,7 +167,8 @@ ip-link \- network device configuration + .BR ip6gretap " |" + .BR vti " |" + .BR nlmon " |" +-.BR geneve " ]" ++.BR geneve " |" ++.BR macsec " ]" + + .ti -8 + .IR ETYPE " := [ " TYPE " |" +-- +1.8.3.1 + diff --git a/SOURCES/0238-macsec-cipher-and-icvlen-can-be-set-separately.patch b/SOURCES/0238-macsec-cipher-and-icvlen-can-be-set-separately.patch new file mode 100644 index 0000000..d7ff890 --- /dev/null +++ b/SOURCES/0238-macsec-cipher-and-icvlen-can-be-set-separately.patch @@ -0,0 +1,167 @@ +From b669a186dc9a68efb82595d991726bb5e3cb51b6 Mon Sep 17 00:00:00 2001 +From: Davide Caratti <dcaratti@redhat.com> +Date: Wed, 3 Aug 2016 17:22:11 +0200 +Subject: [PATCH] macsec: cipher and icvlen can be set separately + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1354408 +Upstream Status: iproute2.git commit 89bb6e673a6a + +commit 89bb6e673a6ae9dd9b6845ed95358dd6653c167e +Author: Davide Caratti <dcaratti@redhat.com> +Date: Tue Jul 26 11:03:20 2016 +0200 + + macsec: cipher and icvlen can be set separately + + since kernel driver has valid default values for 'cipher' and 'icvlen', + there is no need for requiring users to specify both of them when a new + link is added. Also, prompt an error message and exit with appropriate + exit status in case of unsupported cipher suite. + + Signed-off-by: Davide Caratti <dcaratti@redhat.com> + +Signed-off-by: Davide Caratti <dcaratti@redhat.com> +--- + ip/ipmacsec.c | 52 +++++++++++++++++---------------------------------- + man/man8/ip-link.8.in | 6 ++++++ + man/man8/ip-macsec.8 | 4 ++-- + 3 files changed, 25 insertions(+), 37 deletions(-) + +diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c +index 34ba341..329be00 100644 +--- a/ip/ipmacsec.c ++++ b/ip/ipmacsec.c +@@ -1071,34 +1071,6 @@ static void macsec_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) + } + } + +- +-static int do_cipher_suite(struct cipher_args *cipher, int *argcp, +- char ***argvp) +-{ +- char **argv = *argvp; +- int argc = *argcp; +- +- if (argc == 0) +- return -1; +- +- if (strcmp(*argv, "default") == 0 || +- strcmp(*argv, "gcm-aes-128") == 0 || +- strcmp(*argv, "GCM-AES-128") == 0) +- cipher->id = MACSEC_DEFAULT_CIPHER_ID; +- NEXT_ARG(); +- +- if (strcmp(*argv, "icvlen") == 0) { +- NEXT_ARG(); +- if (cipher->icv_len != 0) +- duparg2("icvlen", "icvlen"); +- get_icvlen(&cipher->icv_len, *argv); +- } +- *argcp = argc; +- *argvp = argv; +- +- return 0; +-} +- + static bool check_txsc_flags(bool es, bool scb, bool sci) + { + if (sci && (es || scb)) +@@ -1112,7 +1084,8 @@ static void usage(FILE *f) + { + fprintf(f, + "Usage: ... macsec [ port PORT | sci SCI ]\n" +- " [ cipher CIPHER_SUITE ]\n" ++ " [ cipher { default | gcm-aes-128 } ]\n" ++ " [ icvlen { 8..16 } ]\n" + " [ encrypt { on | off } ]\n" + " [ send_sci { on | off } ]\n" + " [ end_station { on | off } ]\n" +@@ -1122,7 +1095,6 @@ static void usage(FILE *f) + " [ validate { strict | check | disabled } ]\n" + " [ encodingsa { 0..3 } ]\n" + ); +- fprintf(f, "CIPHER_SUITE := [ default = gcm-aes-128 ] icvlen { 8..32 }\n"); + } + + static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, +@@ -1154,11 +1126,21 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, + + while (argc > 0) { + if (strcmp(*argv, "cipher") == 0) { ++ NEXT_ARG(); + if (cipher.id) +- duparg2("cipher", "cipher"); ++ duparg("cipher", *argv); ++ if (strcmp(*argv, "default") == 0 || ++ strcmp(*argv, "gcm-aes-128") == 0 || ++ strcmp(*argv, "GCM-AES-128") == 0) ++ cipher.id = MACSEC_DEFAULT_CIPHER_ID; ++ else ++ invarg("expected: default or gcm-aes-128", ++ *argv); ++ } else if (strcmp(*argv, "icvlen") == 0) { + NEXT_ARG(); +- if (do_cipher_suite(&cipher, &argc, &argv)) +- return -1; ++ if (cipher.icv_len) ++ duparg("icvlen", *argv); ++ get_icvlen(&cipher.icv_len, *argv); + } else if (strcmp(*argv, "encrypt") == 0) { + NEXT_ARG(); + int i; +@@ -1264,12 +1246,12 @@ static int macsec_parse_opt(struct link_util *lu, int argc, char **argv, + return -1; + } + +- if (cipher.id) { ++ if (cipher.id) + addattr_l(hdr, MACSEC_BUFLEN, IFLA_MACSEC_CIPHER_SUITE, + &cipher.id, sizeof(cipher.id)); ++ if (cipher.icv_len) + addattr_l(hdr, MACSEC_BUFLEN, IFLA_MACSEC_ICV_LEN, + &cipher.icv_len, sizeof(cipher.icv_len)); +- } + + if (replay_protect != -1) { + addattr32(hdr, MACSEC_BUFLEN, IFLA_MACSEC_WINDOW, window); +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 2633521..18c7040 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -753,6 +753,8 @@ the following additional arguments are supported: + ] [ + .BI cipher " CIPHER_SUITE" + ] [ ++.BR icvlen " { " ++.IR 8..16 " } ] [" + .BR encrypt " {" + .BR on " | " off " } ] [ " + .BR send_sci " { " on " | " off " } ] [" +@@ -780,6 +782,10 @@ the following additional arguments are supported: + - defines the cipher suite to use. + + .sp ++.BI icvlen " LENGTH " ++- sets the length of the Integrity Check Value (ICV). ++ ++.sp + .BR "encrypt on " or " encrypt off" + - switches between authenticated encryption, or authenticity mode only. + +diff --git a/man/man8/ip-macsec.8 b/man/man8/ip-macsec.8 +index f928c43..105aeec 100644 +--- a/man/man8/ip-macsec.8 ++++ b/man/man8/ip-macsec.8 +@@ -7,8 +7,8 @@ ip-macsec \- MACsec device configuration + .BI port " PORT" + | + .BI sci " SCI" +-] [ [ +-.BR cipher " { " default " | " gcm-aes-128 " } ] " ++] [ ++.BR cipher " { " default " | " gcm-aes-128 " } ] [" + .BI icvlen " ICVLEN" + ] [ + .BR encrypt " { " on " | " off " } ] [" +-- +1.8.3.1 + diff --git a/SOURCES/0239-man-ip-link.8-Document-missing-geneve-options.patch b/SOURCES/0239-man-ip-link.8-Document-missing-geneve-options.patch new file mode 100644 index 0000000..6191966 --- /dev/null +++ b/SOURCES/0239-man-ip-link.8-Document-missing-geneve-options.patch @@ -0,0 +1,86 @@ +From f5daf2e2fa8afe3adb7eb9bb04fb41828144e562 Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 18 Aug 2016 20:54:31 +0200 +Subject: [PATCH] man: ip-link.8: Document missing geneve options + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1339178 +Upstream Status: iproute2.git commit 7e33b093318cd + +commit 7e33b093318cd9281e3df3572ed64b57e12ba642 +Author: Phil Sutter <phil@nwl.cc> +Date: Fri Aug 12 01:17:12 2016 +0200 + + man: ip-link.8: Document missing geneve options + + This adds missing documentation of geneve type options: + + - dstport + - external + - udpcsum + - udp6zerocsumtx + - udp6zerocsumrx + + The bits for the last three was just copy and pasted from vxlan section. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + man/man8/ip-link.8.in | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in +index 18c7040..8968cf2 100644 +--- a/man/man8/ip-link.8.in ++++ b/man/man8/ip-link.8.in +@@ -664,6 +664,16 @@ the following additional arguments are supported: + .BI tos " TOS " + ] [ + .BI flowlabel " FLOWLABEL " ++] [ ++.BI dstport " PORT" ++] [ ++.RB [ no ] external ++] [ ++.RB [ no ] udpcsum ++] [ ++.RB [ no ] udp6zerocsumtx ++] [ ++.RB [ no ] udp6zerocsumrx + ] + + .in +8 +@@ -687,6 +697,32 @@ the following additional arguments are supported: + .BI flowlabel " FLOWLABEL" + - specifies the flow label to use in outgoing packets. + ++.sp ++.BI dstport " PORT" ++- select a destination port other than the default of 6081. ++ ++.sp ++.RB [ no ] external ++- make this tunnel externally controlled (or not, which is the default). This ++flag is mutually exclusive with the ++.BR id , ++.BR remote , ++.BR ttl , ++.BR tos " and " flowlabel ++options. ++ ++.sp ++.RB [ no ] udpcsum ++- specifies if UDP checksum is calculated for transmitted packets over IPv4. ++ ++.sp ++.RB [ no ] udp6zerocsumtx ++- skip UDP checksum calculation for transmitted packets over IPv6. ++ ++.sp ++.RB [ no ] udp6zerocsumrx ++- allow incoming UDP packets over IPv6 with zero checksum field. ++ + .in -8 + + .TP +-- +1.8.3.1 + diff --git a/SOURCES/0240-ip-link-add-missing-min-max-_tx_rate-to-help-text.patch b/SOURCES/0240-ip-link-add-missing-min-max-_tx_rate-to-help-text.patch new file mode 100644 index 0000000..a87a5e6 --- /dev/null +++ b/SOURCES/0240-ip-link-add-missing-min-max-_tx_rate-to-help-text.patch @@ -0,0 +1,38 @@ +From 5eac57fa0734790c5905dc1e0eb8fcab03fbfd3f Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 18 Aug 2016 20:56:09 +0200 +Subject: [PATCH] ip-link: add missing {min,max}_tx_rate to help text + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1340914 +Upstream Status: iproute2.git commit 08c0466b11b79 + +commit 08c0466b11b79107740226052a27279034eb3768 +Author: Phil Sutter <phil@nwl.cc> +Date: Tue Aug 16 16:08:38 2016 +0200 + + ip-link: add missing {min,max}_tx_rate to help text + + These vf options are described in man page already, they're just missing + in help output. + + Signed-off-by: Phil Sutter <phil@nwl.cc> +--- + ip/iplink.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/ip/iplink.c b/ip/iplink.c +index e9c2874..e0e0fe9 100644 +--- a/ip/iplink.c ++++ b/ip/iplink.c +@@ -79,6 +79,8 @@ void iplink_usage(void) + fprintf(stderr, " [ vlan VLANID [ qos VLAN-QOS ] ]\n"); + + fprintf(stderr, " [ rate TXRATE ]\n"); ++ fprintf(stderr, " [ max_tx_rate TXRATE ]\n"); ++ fprintf(stderr, " [ min_tx_rate TXRATE ]\n"); + + fprintf(stderr, " [ spoofchk { on | off} ]\n"); + fprintf(stderr, " [ query_rss { on | off} ]\n"); +-- +1.8.3.1 + diff --git a/SOURCES/0241-ip-route-restore_handler-should-check-tb-RTA_PREFSRC.patch b/SOURCES/0241-ip-route-restore_handler-should-check-tb-RTA_PREFSRC.patch new file mode 100644 index 0000000..e35b86c --- /dev/null +++ b/SOURCES/0241-ip-route-restore_handler-should-check-tb-RTA_PREFSRC.patch @@ -0,0 +1,47 @@ +From 3bcd42253a598fe19892e418e15edea6cb87149e Mon Sep 17 00:00:00 2001 +From: Phil Sutter <psutter@redhat.com> +Date: Thu, 25 Aug 2016 16:47:35 +0200 +Subject: [PATCH] ip route: restore_handler should check tb[RTA_PREFSRC] for + local networks + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1362728 +Upstream Status: iproute2.git commit c85703bb9fb77 + +commit c85703bb9fb778ca94a3f84343406a251d23f9ba +Author: Xin Long <lucien.xin@gmail.com> +Date: Sun Aug 7 17:12:30 2016 +0800 + + ip route: restore_handler should check tb[RTA_PREFSRC] for local networks + + Prior to this patch, If one route entry's RTA_PREFSRC and RTA_GATEWAY + both were NULL, it was supposed to be restored ONLY as a local address. + + But as it didn't check tb[RTA_PREFSRC] when restoring local networks, + rtattr_cmp would return a success if it was NULL, this route entry would + be restored again as a local network. + + This patch is to add tb[RTA_PREFSRC] check when restoring local networks. + + Fixes: 74af8dd9620e ("ip route: restore route entries in correct order") + Signed-off-by: Xin Long <lucien.xin@gmail.com> + Tested-by: Phil Sutter <phil@nwl.cc> +--- + ip/iproute.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index b7057b3..15e1a51 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -1619,7 +1619,7 @@ static int restore_handler(const struct sockaddr_nl *nl, + if (!prio && !tb[RTA_GATEWAY] && (!tb[RTA_PREFSRC] || + !rtattr_cmp(tb[RTA_PREFSRC], tb[RTA_DST]))) + goto restore; +- else if (prio == 1 && !tb[RTA_GATEWAY] && ++ else if (prio == 1 && !tb[RTA_GATEWAY] && tb[RTA_PREFSRC] && + rtattr_cmp(tb[RTA_PREFSRC], tb[RTA_DST])) + goto restore; + else if (prio == 2 && tb[RTA_GATEWAY]) +-- +1.8.3.1 + diff --git a/SOURCES/iproute-3.10.0-man-tc.8-mention-Fair-Queue-scheduler.patch b/SOURCES/iproute-3.10.0-man-tc.8-mention-Fair-Queue-scheduler.patch deleted file mode 100644 index b405656..0000000 --- a/SOURCES/iproute-3.10.0-man-tc.8-mention-Fair-Queue-scheduler.patch +++ /dev/null @@ -1,31 +0,0 @@ -From e4341c2d317de1d30deb1672af1e43fc04ac4f0d Mon Sep 17 00:00:00 2001 -From: Phil Sutter <psutter@redhat.com> -Date: Wed, 9 Sep 2015 15:33:36 +0200 -Subject: [PATCH] man: tc.8: mention Fair Queue scheduler - -This is rather a placeholder to let users know fq exists at all. ---- -This patch has not been accepted upstream yet, but since it's the last blocker -for RHEL7.2 I'll condone the consequences. ---- - man/man8/tc.8 | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/man/man8/tc.8 b/man/man8/tc.8 -index cc839d9..b8ef52a 100644 ---- a/man/man8/tc.8 -+++ b/man/man8/tc.8 -@@ -148,6 +148,10 @@ The classless qdiscs are: - Simplest usable qdisc, pure First In, First Out behaviour. Limited in - packets or in bytes. - .TP -+fq -+Fair Queue Scheduler realises TCP pacing and scales to millions of concurrent -+flows per qdisc. -+.TP - pfifo_fast - Standard qdisc for 'Advanced Router' enabled kernels. Consists of a three-band - queue which honors Type of Service flags, as well as the priority that may be --- -1.8.3.1 - diff --git a/SOURCES/iproute2-2.6.35-print-route.patch b/SOURCES/iproute2-2.6.35-print-route.patch deleted file mode 100644 index 04f3cf7..0000000 --- a/SOURCES/iproute2-2.6.35-print-route.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/ip/iproute.c b/ip/iproute.c -index 711576e..86c7ab7 100644 ---- a/ip/iproute.c -+++ b/ip/iproute.c -@@ -160,7 +160,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) - if (r->rtm_family == AF_INET6 && table != RT_TABLE_MAIN) - ip6_multiple_tables = 1; - -- if (filter.cloned == !(r->rtm_flags&RTM_F_CLONED)) -+ if (filter.cloned && !(r->rtm_flags&RTM_F_CLONED)) - return 0; - - if (r->rtm_family == AF_INET6 && !ip6_multiple_tables) { diff --git a/SOURCES/iproute2-2.6.39-create-peer-veth-without-a-name.patch b/SOURCES/iproute2-2.6.39-create-peer-veth-without-a-name.patch deleted file mode 100644 index b0ae4da..0000000 --- a/SOURCES/iproute2-2.6.39-create-peer-veth-without-a-name.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/ip/link_veth.c b/ip/link_veth.c -index 3d19b01..eb0f41e 100644 ---- a/ip/link_veth.c -+++ b/ip/link_veth.c -@@ -27,7 +27,7 @@ static void usage(void) - static int veth_parse_opt(struct link_util *lu, int argc, char **argv, - struct nlmsghdr *hdr) - { -- char *name, *type, *link, *dev; -+ char *name = NULL, *type = NULL, *link = NULL, *dev = NULL; - int err, len; - struct rtattr * data; - int group; diff --git a/SOURCES/iproute2-2.6.39-lnstat-dump-to-stdout.patch b/SOURCES/iproute2-2.6.39-lnstat-dump-to-stdout.patch deleted file mode 100644 index a5b7b62..0000000 --- a/SOURCES/iproute2-2.6.39-lnstat-dump-to-stdout.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/misc/lnstat.c b/misc/lnstat.c -index 32ab6a4..431bfc7 100644 ---- a/misc/lnstat.c -+++ b/misc/lnstat.c -@@ -322,7 +322,7 @@ int main(int argc, char **argv) - int i; - struct table_hdr *header; - case MODE_DUMP: -- lnstat_dump(stderr, lnstat_files); -+ lnstat_dump(stdout, lnstat_files); - break; - case MODE_NORMAL: - diff --git a/SOURCES/iproute2-3.10.0-1139173.patch b/SOURCES/iproute2-3.10.0-1139173.patch deleted file mode 100644 index b5f9d7d..0000000 --- a/SOURCES/iproute2-3.10.0-1139173.patch +++ /dev/null @@ -1,27 +0,0 @@ -commit 1ed509bb522225050edfa1ed7ddc7255e9a18bd5 -Author: Thomas Egerer <thomas.egerer@secunet.com> -Date: Thu Aug 29 14:00:36 2013 +0200 - - ip/xfrm: Fix potential SIGSEGV when printing extra flags - - The git-commit dc8867d0, that added support for displaying the - extra-flags of a state, introduced a potential segfault. - Trying to show a state without the extra-flag attribute and show_stats - enabled, would cause the NULL pointer in tb[XFRMA_SA_EXTRA_FLAGS] to be - dereferenced. - - Signed-off-by: Thomas Egerer <thomas.egerer@secunet.com> - -diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c -index 0a3a9fb..411d9d5 100644 ---- a/ip/ipxfrm.c -+++ b/ip/ipxfrm.c -@@ -856,7 +856,7 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo, - if (flags) - fprintf(fp, "%x", flags); - } -- if (show_stats > 0 || tb[XFRMA_SA_EXTRA_FLAGS]) { -+ if (show_stats > 0 && tb[XFRMA_SA_EXTRA_FLAGS]) { - __u32 extra_flags = *(__u32 *)RTA_DATA(tb[XFRMA_SA_EXTRA_FLAGS]); - - fprintf(fp, "extra_flag "); diff --git a/SOURCES/iproute2-3.10.0-Fix-changing-tunnel-remote-and-local-address-to-any.patch b/SOURCES/iproute2-3.10.0-Fix-changing-tunnel-remote-and-local-address-to-any.patch deleted file mode 100644 index 755a924..0000000 --- a/SOURCES/iproute2-3.10.0-Fix-changing-tunnel-remote-and-local-address-to-any.patch +++ /dev/null @@ -1,51 +0,0 @@ -From b45db2060837990b05d2f8da28c1ba0217011439 Mon Sep 17 00:00:00 2001 -From: Thadeu Lima de Souza Cascardo <cascardo@redhat.com> -Date: Thu, 4 Jun 2015 09:01:18 -0300 -Subject: [PATCH] Fix changing tunnel remote and local address to any - -If a tunnel is created with a local address, you can't change it to any. - - # ip tunnel add tunl1 mode ipip remote 10.16.42.37 local 10.16.42.214 ttl 64 - # ip tunnel show tunl1 - tunl1: ip/ip remote 10.16.42.37 local 10.16.42.214 ttl 64 - # ip tunnel change tunl1 local any - # echo $? - 0 - # ip tunnel show tunl1 - tunl1: ip/ip remote 10.16.42.37 local 10.16.42.214 ttl 64 - -It happens that parse_args zeroes ip_tunnel_parm, and when creating the -tunnel, it is OK to leave it as is if the address is any. However, when -changing the tunnel, the current parameters will be read from -ip_tunnel_parm, and local and remote address won't be zeroes anymore, so -it needs to be explicitly set to any. - -Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@redhat.com> -Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> -(cherry picked from commit 4e4b78324f1dbcee590c01a7ac3e5ebaf20daa27) ---- - ip/iptunnel.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/ip/iptunnel.c b/ip/iptunnel.c -index 43f8585..4c9c429 100644 ---- a/ip/iptunnel.c -+++ b/ip/iptunnel.c -@@ -167,10 +167,14 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) - NEXT_ARG(); - if (strcmp(*argv, "any")) - p->iph.daddr = get_addr32(*argv); -+ else -+ p->iph.daddr = htonl(INADDR_ANY); - } else if (strcmp(*argv, "local") == 0) { - NEXT_ARG(); - if (strcmp(*argv, "any")) - p->iph.saddr = get_addr32(*argv); -+ else -+ p->iph.saddr = htonl(INADDR_ANY); - } else if (strcmp(*argv, "dev") == 0) { - NEXT_ARG(); - strncpy(medium, *argv, IFNAMSIZ-1); --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-Fix-multiple-programming-errors.patch b/SOURCES/iproute2-3.10.0-Fix-multiple-programming-errors.patch deleted file mode 100644 index fb24eee..0000000 --- a/SOURCES/iproute2-3.10.0-Fix-multiple-programming-errors.patch +++ /dev/null @@ -1,229 +0,0 @@ -From 453eee90927d1c28951af40c3fd2c40365b07055 Mon Sep 17 00:00:00 2001 -From: Stephen Hemminger <shemming@brocade.com> -Date: Wed, 12 Aug 2015 08:35:54 -0700 -Subject: [PATCH] Fix multiple programming errors -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This is a combination of 8 commits: - -commit 2f29d6bb5089271988a820d1f9596f9973ee2e4d -Author: Stephen Hemminger <shemming@brocade.com> -Date: Wed Aug 12 08:35:54 2015 -0700 - - ipnetns: make net namespace cache variable size - - Save some space by using variable size for nsid cache elements. - - Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> - -commit e0dce0e5dc363b7e307984706c130f6ee769259b -Author: Phil Sutter <phil@nwl.cc> -Date: Thu Aug 6 14:24:32 2015 +0200 - - misc/ss: avoid NULL pointer dereference - - This was working before, but only if realloc a) succeeded and b) did not - move the buffer to a different location. ''**buf = **new_buf' then - writes the value of *new_buf's first field into that of *buf. - - Signed-off-by: Phil Sutter <phil@nwl.cc> - -commit 532ca40a52d4103816f2e50690a02e9dd6c1abe5 -Author: Phil Sutter <phil@nwl.cc> -Date: Thu Aug 6 14:24:33 2015 +0200 - - misc/ss: simplify buffer realloc, fix checking realloc failure - - Signed-off-by: Phil Sutter <phil@nwl.cc> - -commit b95d28c380c945ac760b128403dc82279cb9cc39 -Author: Phil Sutter <phil@nwl.cc> -Date: Thu Aug 6 14:24:34 2015 +0200 - - misc/ss: add missing fclose() calls - - Signed-off-by: Phil Sutter <phil@nwl.cc> - -commit 5950ba914e12b9c942e45e2dda6b1732a3efa058 -Author: Phil Sutter <phil@nwl.cc> -Date: Thu Aug 6 14:24:35 2015 +0200 - - lib/namespace: don't leak fd in error case - - Signed-off-by: Phil Sutter <phil@nwl.cc> - -commit a02371fb3831c8d3d9d53209f2389b250a1fb804 -Author: Phil Sutter <phil@nwl.cc> -Date: Thu Aug 6 14:24:36 2015 +0200 - - misc/ss: fix memory leak in user_ent_hash_build() - - Signed-off-by: Phil Sutter <phil@nwl.cc> - -commit 9e5ba07f491037f51472915477575d3e3fe0adcb -Author: Phil Sutter <phil@nwl.cc> -Date: Tue Aug 18 18:11:08 2015 +0200 - - lib/namespace: fix fd leakage in non-error case - - My previous patch 5950ba9 ("lib/namespace: don't leak fd in error case") - was a step in the wrong direction. Instead of closing the opened file - descriptor in error case only, follow a better approach here and close - the fd as soon as it is not used anymore. This way the inelegant goto - statements can be dropped, and the fd leak in non-error case is fixed as - well. - - Fixes: 5950ba9 ("lib/namespace: don't leak fd in error case") - Signed-off-by: Phil Sutter <phil@nwl.cc> - -commit b765eda924363caec99b760d8cff815ecf4a8de6 -Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> -Date: Wed Apr 22 10:27:06 2015 +0200 - - libnamespaces: fix warning about syscall() - - The warning was: - In file included from namespace.c:14:0: - ../include/namespace.h: In function ‘setns’: - ../include/namespace.h:37:2: warning: implicit declaration of function ‘syscall’ [-Wimplicit-function-declaration] - - Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> ---- - include/namespace.h | 1 + - ip/ipnetns.c | 6 +++--- - lib/namespace.c | 2 ++ - misc/ss.c | 17 +++++++++++------ - 4 files changed, 17 insertions(+), 9 deletions(-) - -diff --git a/include/namespace.h b/include/namespace.h -index a2ac7dc..5add9d2 100644 ---- a/include/namespace.h -+++ b/include/namespace.h -@@ -3,6 +3,7 @@ - - #include <sched.h> - #include <sys/mount.h> -+#include <unistd.h> - #include <sys/syscall.h> - #include <errno.h> - -diff --git a/ip/ipnetns.c b/ip/ipnetns.c -index 019f954..00b6cc4 100644 ---- a/ip/ipnetns.c -+++ b/ip/ipnetns.c -@@ -140,7 +140,7 @@ struct nsid_cache { - struct hlist_node nsid_hash; - struct hlist_node name_hash; - int nsid; -- char name[NAME_MAX]; -+ char name[0]; - }; - - #define NSIDMAP_SIZE 128 -@@ -165,7 +165,7 @@ static struct nsid_cache *netns_map_get_by_nsid(int nsid) - return NULL; - } - --static int netns_map_add(int nsid, char *name) -+static int netns_map_add(int nsid, const char *name) - { - struct nsid_cache *c; - uint32_t h; -@@ -173,7 +173,7 @@ static int netns_map_add(int nsid, char *name) - if (netns_map_get_by_nsid(nsid) != NULL) - return -EEXIST; - -- c = malloc(sizeof(*c)); -+ c = malloc(sizeof(*c) + strlen(name)); - if (c == NULL) { - perror("malloc"); - return -ENOMEM; -diff --git a/lib/namespace.c b/lib/namespace.c -index c03a103..0549916 100644 ---- a/lib/namespace.c -+++ b/lib/namespace.c -@@ -57,8 +57,10 @@ int netns_switch(char *name) - if (setns(netns, CLONE_NEWNET) < 0) { - fprintf(stderr, "setting the network namespace \"%s\" failed: %s\n", - name, strerror(errno)); -+ close(netns); - return -1; - } -+ close(netns); - - if (unshare(CLONE_NEWNS) < 0) { - fprintf(stderr, "unshare failed: %s\n", strerror(errno)); -diff --git a/misc/ss.c b/misc/ss.c -index 951e1eb..5d0cc36 100644 ---- a/misc/ss.c -+++ b/misc/ss.c -@@ -474,8 +474,10 @@ static void user_ent_hash_build(void) - - sprintf(name + nameoff, "%d/fd/", pid); - pos = strlen(name); -- if ((dir1 = opendir(name)) == NULL) -+ if ((dir1 = opendir(name)) == NULL) { -+ free(pid_context); - continue; -+ } - - process[0] = '\0'; - p = process; -@@ -541,7 +543,7 @@ static int find_entry(unsigned ino, char **buf, int type) - struct user_ent *p; - int cnt = 0; - char *ptr; -- char **new_buf = buf; -+ char *new_buf; - int len, new_buf_len; - int buf_used = 0; - int buf_len = 0; -@@ -583,12 +585,12 @@ static int find_entry(unsigned ino, char **buf, int type) - - if (len < 0 || len >= buf_len - buf_used) { - new_buf_len = buf_len + ENTRY_BUF_SIZE; -- *new_buf = realloc(*buf, new_buf_len); -+ new_buf = realloc(*buf, new_buf_len); - if (!new_buf) { - fprintf(stderr, "ss: failed to malloc buffer\n"); - abort(); - } -- **buf = **new_buf; -+ *buf = new_buf; - buf_len = new_buf_len; - continue; - } else { -@@ -2928,6 +2930,7 @@ static int packet_show_line(char *buf, const struct filter *f, int fam) - static int packet_show(struct filter *f) - { - FILE *fp; -+ int rc = 0; - - if (!filter_af_get(f, AF_PACKET) || !(f->states & (1 << SS_CLOSE))) - return 0; -@@ -2939,9 +2942,10 @@ static int packet_show(struct filter *f) - if ((fp = net_packet_open()) == NULL) - return -1; - if (generic_record_read(fp, packet_show_line, f, AF_PACKET)) -- return -1; -+ rc = -1; - -- return 0; -+ fclose(fp); -+ return rc; - } - - static int netlink_show_one(struct filter *f, -@@ -3118,6 +3122,7 @@ static int netlink_show(struct filter *f) - netlink_show_one(f, prot, pid, groups, 0, 0, 0, rq, wq, sk, cb); - } - -+ fclose(fp); - return 0; - } - --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-Revert-Changes-for-BZ-1212026.patch b/SOURCES/iproute2-3.10.0-Revert-Changes-for-BZ-1212026.patch deleted file mode 100644 index 4825a88..0000000 --- a/SOURCES/iproute2-3.10.0-Revert-Changes-for-BZ-1212026.patch +++ /dev/null @@ -1,275 +0,0 @@ -From ae646501d67a3c6e5078529f92339ffc87277cea Mon Sep 17 00:00:00 2001 -From: Phil Sutter <psutter@redhat.com> -Date: Thu, 3 Sep 2015 13:02:02 +0200 -Subject: [PATCH] Revert Changes for BZ#1212026 - -Kernel lacks support for it in RHEL7.2, delivering this would be inconsistent. - -This is a combination of 2 reverts: - -Revert "xfrm: add command for configuring SPD hash table" -Revert "xfrm: revise man page and document ip xfrm policy set" ---- - ip/xfrm_policy.c | 105 ++--------------------------------------------------- - man/man8/ip-xfrm.8 | 61 +------------------------------ - 2 files changed, 5 insertions(+), 161 deletions(-) - -diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c -index 9ac4a89..36e33c9 100644 ---- a/ip/xfrm_policy.c -+++ b/ip/xfrm_policy.c -@@ -64,8 +64,7 @@ static void usage(void) - fprintf(stderr, " [ index INDEX ] [ ptype PTYPE ] [ action ACTION ] [ priority PRIORITY ]\n"); - fprintf(stderr, " [ flag FLAG-LIST ]\n"); - fprintf(stderr, "Usage: ip xfrm policy flush [ ptype PTYPE ]\n"); -- fprintf(stderr, "Usage: ip xfrm policy count\n"); -- fprintf(stderr, "Usage: ip xfrm policy set [ hthresh4 LBITS RBITS ] [ hthresh6 LBITS RBITS ]\n"); -+ fprintf(stderr, "Usage: ip xfrm count\n"); - fprintf(stderr, "SELECTOR := [ src ADDR[/PLEN] ] [ dst ADDR[/PLEN] ] [ dev DEV ] [ UPSPEC ]\n"); - fprintf(stderr, "UPSPEC := proto { { "); - fprintf(stderr, "%s | ", strxf_proto(IPPROTO_TCP)); -@@ -936,7 +935,7 @@ static int print_spdinfo( struct nlmsghdr *n, void *arg) - fprintf(fp,")"); - } - -- fprintf(fp, "%s", _SL_); -+ fprintf(fp,"\n"); - } - if (show_stats > 1) { - struct xfrmu_spdhinfo *sh; -@@ -950,109 +949,13 @@ static int print_spdinfo( struct nlmsghdr *n, void *arg) - fprintf(fp,"\t SPD buckets:"); - fprintf(fp," count %d", sh->spdhcnt); - fprintf(fp," Max %d", sh->spdhmcnt); -- fprintf(fp, "%s", _SL_); -- } -- if (tb[XFRMA_SPD_IPV4_HTHRESH]) { -- struct xfrmu_spdhthresh *th; -- if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV4_HTHRESH]) < sizeof(*th)) { -- fprintf(stderr, "SPDinfo: Wrong len %d\n", len); -- return -1; -- } -- th = RTA_DATA(tb[XFRMA_SPD_IPV4_HTHRESH]); -- fprintf(fp,"\t SPD IPv4 thresholds:"); -- fprintf(fp," local %d", th->lbits); -- fprintf(fp," remote %d", th->rbits); -- fprintf(fp, "%s", _SL_); -- -- } -- if (tb[XFRMA_SPD_IPV6_HTHRESH]) { -- struct xfrmu_spdhthresh *th; -- if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV6_HTHRESH]) < sizeof(*th)) { -- fprintf(stderr, "SPDinfo: Wrong len %d\n", len); -- return -1; -- } -- th = RTA_DATA(tb[XFRMA_SPD_IPV6_HTHRESH]); -- fprintf(fp,"\t SPD IPv6 thresholds:"); -- fprintf(fp," local %d", th->lbits); -- fprintf(fp," remote %d", th->rbits); -- fprintf(fp, "%s", _SL_); - } - } -- -- if (oneline) -- fprintf(fp, "\n"); -+ fprintf(fp,"\n"); - - return 0; - } - --static int xfrm_spd_setinfo(int argc, char **argv) --{ -- struct rtnl_handle rth; -- struct { -- struct nlmsghdr n; -- __u32 flags; -- char buf[RTA_BUF_SIZE]; -- } req; -- -- char *thr4 = NULL; -- char *thr6 = NULL; -- -- memset(&req, 0, sizeof(req)); -- -- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(__u32)); -- req.n.nlmsg_flags = NLM_F_REQUEST; -- req.n.nlmsg_type = XFRM_MSG_NEWSPDINFO; -- req.flags = 0XFFFFFFFF; -- -- while (argc > 0) { -- if (strcmp(*argv, "hthresh4") == 0) { -- struct xfrmu_spdhthresh thr; -- -- if (thr4) -- duparg("hthresh4", *argv); -- thr4 = *argv; -- NEXT_ARG(); -- if (get_u8(&thr.lbits, *argv, 0) || thr.lbits > 32) -- invarg("hthresh4 LBITS value is invalid", *argv); -- NEXT_ARG(); -- if (get_u8(&thr.rbits, *argv, 0) || thr.rbits > 32) -- invarg("hthresh4 RBITS value is invalid", *argv); -- -- addattr_l(&req.n, sizeof(req), XFRMA_SPD_IPV4_HTHRESH, -- (void *)&thr, sizeof(thr)); -- } else if (strcmp(*argv, "hthresh6") == 0) { -- struct xfrmu_spdhthresh thr; -- -- if (thr6) -- duparg("hthresh6", *argv); -- thr6 = *argv; -- NEXT_ARG(); -- if (get_u8(&thr.lbits, *argv, 0) || thr.lbits > 128) -- invarg("hthresh6 LBITS value is invalid", *argv); -- NEXT_ARG(); -- if (get_u8(&thr.rbits, *argv, 0) || thr.rbits > 128) -- invarg("hthresh6 RBITS value is invalid", *argv); -- -- addattr_l(&req.n, sizeof(req), XFRMA_SPD_IPV6_HTHRESH, -- (void *)&thr, sizeof(thr)); -- } else { -- invarg("unknown", *argv); -- } -- -- argc--; argv++; -- } -- -- if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) -- exit(1); -- -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -- exit(2); -- -- rtnl_close(&rth); -- -- return 0; --} -- - static int xfrm_spd_getinfo(int argc, char **argv) - { - struct rtnl_handle rth; -@@ -1156,8 +1059,6 @@ int do_xfrm_policy(int argc, char **argv) - return xfrm_policy_flush(argc-1, argv+1); - if (matches(*argv, "count") == 0) - return xfrm_spd_getinfo(argc, argv); -- if (matches(*argv, "set") == 0) -- return xfrm_spd_setinfo(argc-1, argv+1); - if (matches(*argv, "help") == 0) - usage(); - fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm policy help\".\n", *argv); -diff --git a/man/man8/ip-xfrm.8 b/man/man8/ip-xfrm.8 -index aea4fda..3752c7e 100644 ---- a/man/man8/ip-xfrm.8 -+++ b/man/man8/ip-xfrm.8 -@@ -252,13 +252,6 @@ ip-xfrm \- transform configuration - .B "ip xfrm policy count" - - .ti -8 --.B "ip xfrm policy set" --.RB "[ " hthresh4 --.IR LBITS " " RBITS " ]" --.RB "[ " hthresh6 --.IR LBITS " " RBITS " ]" -- --.ti -8 - .IR SELECTOR " :=" - .RB "[ " src - .IR ADDR "[/" PLEN "] ]" -@@ -366,13 +359,6 @@ ip-xfrm \- transform configuration - | - .IR LISTofXFRM-OBJECTS " ]" - --.ti -8 --.IR LISTofXFRM-OBJECTS " := [ " LISTofXFRM-OBJECTS " ] " XFRM-OBJECT -- --.ti -8 --.IR XFRM-OBJECT " := " --.BR acquire " | " expire " | " SA " | " policy " | " aevent " | " report -- - .in -8 - .ad b - -@@ -398,6 +384,7 @@ ip xfrm state deleteall delete all existing state in xfrm - ip xfrm state list print out the list of existing state in xfrm - ip xfrm state flush flush all state in xfrm - ip xfrm state count count all existing state in xfrm -+ip xfrm monitor state monitoring for xfrm objects - .TE - - .TP -@@ -519,9 +506,7 @@ encapsulates packets with protocol - .BR espinudp " or " espinudp-nonike "," - .RI "using source port " SPORT ", destination port " DPORT - .RI ", and original address " OADDR "." -- - .sp --.PP - .TS - l l. - ip xfrm policy add add a new policy -@@ -531,6 +516,7 @@ ip xfrm policy get get an existing policy - ip xfrm policy deleteall delete all existing xfrm policies - ip xfrm policy list print out the list of xfrm policies - ip xfrm policy flush flush policies -+ip xfrm policy count count existing policies - .TE - - .TP -@@ -625,47 +611,6 @@ and inbound trigger - can be - .BR required " (default) or " use "." - --.sp --.PP --.TS --l l. --ip xfrm policy count count existing policies --.TE -- --.PP --Use one or more -s options to display more details, including policy hash table --information. -- --.sp --.PP --.TS --l l. --ip xfrm policy set configure the policy hash table --.TE -- --.PP --Security policies whose address prefix lengths are greater than or equal --policy hash table thresholds are hashed. Others are stored in the --policy_inexact chained list. -- --.TP --.I LBITS --specifies the minimum local address prefix length of policies that are --stored in the Security Policy Database hash table. -- --.TP --.I RBITS --specifies the minimum remote address prefix length of policies that are --stored in the Security Policy Database hash table. -- --.sp --.PP --.TS --l l. --ip xfrm monitor state monitoring for xfrm objects --.TE -- --.PP - The xfrm objects to monitor can be optionally specified. - - .P -@@ -684,6 +629,4 @@ originates. Example: - .SH AUTHOR - Manpage revised by David Ward <david.ward@ll.mit.edu> - .br --Manpage revised by Christophe Gouault <christophe.gouault@6wind.com> --.br - Manpage revised by Nicolas Dichtel <nicolas.dichtel@6wind.com> --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-address.patch b/SOURCES/iproute2-3.10.0-address.patch deleted file mode 100644 index ed97476..0000000 --- a/SOURCES/iproute2-3.10.0-address.patch +++ /dev/null @@ -1,1443 +0,0 @@ -commit 9764c8d5063de9d76326f028fce66f6e4e49bb5a -Author: Pavel Šimerda <psimerda@redhat.com> -Date: Thu May 28 12:17:39 2015 +0200 - - backport selected ip-link/ip-address features and documentation - -diff --git a/ip/ip.c b/ip/ip.c -index 86f8b45..7f2c206 100644 ---- a/ip/ip.c -+++ b/ip/ip.c -@@ -22,8 +22,11 @@ - #include "SNAPSHOT.h" - #include "utils.h" - #include "ip_common.h" -+#include "namespace.h" - - int preferred_family = AF_UNSPEC; -+int human_readable = 0; -+int use_iec = 0; - int show_stats = 0; - int show_details = 0; - int resolve_hosts = 0; -@@ -33,6 +36,7 @@ char * _SL_ = NULL; - int force = 0; - int max_flush_loops = 10; - int batch_mode = 0; -+bool do_all = false; - - struct rtnl_handle rth = { .fd = -1 }; - -@@ -47,11 +51,12 @@ static void usage(void) - " tunnel | tuntap | maddr | mroute | mrule | monitor | xfrm |\n" - " netns | l2tp | tcp_metrics | token }\n" - " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" -+" -h[uman-readable] | -iec |\n" - " -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n" - " -4 | -6 | -I | -D | -B | -0 |\n" - " -l[oops] { maximum-addr-flush-attempts } |\n" - " -o[neline] | -t[imestamp] | -b[atch] [filename] |\n" --" -rc[vbuf] [size]}\n"); -+" -rc[vbuf] [size] | -n[etns] name | -a[ll] }\n"); - exit(-1); - } - -@@ -65,7 +70,7 @@ static const struct cmd { - const char *cmd; - int (*func)(int argc, char **argv); - } cmds[] = { -- { "address", do_ipaddr }, -+ { "address", do_ipaddr }, - { "addrlabel", do_ipaddrlabel }, - { "maddress", do_multiaddr }, - { "route", do_iproute }, -@@ -212,6 +217,11 @@ int main(int argc, char **argv) - preferred_family = AF_DECnet; - } else if (strcmp(opt, "-B") == 0) { - preferred_family = AF_BRIDGE; -+ } else if (matches(opt, "-human") == 0 || -+ matches(opt, "-human-readable") == 0) { -+ ++human_readable; -+ } else if (matches(opt, "-iec") == 0) { -+ ++use_iec; - } else if (matches(opt, "-stats") == 0 || - matches(opt, "-statistics") == 0) { - ++show_stats; -@@ -253,6 +263,12 @@ int main(int argc, char **argv) - rcvbuf = size; - } else if (matches(opt, "-help") == 0) { - usage(); -+ } else if (matches(opt, "-netns") == 0) { -+ NEXT_ARG(); -+ if (netns_switch(argv[1])) -+ exit(-1); -+ } else if (matches(opt, "-all") == 0) { -+ do_all = true; - } else { - fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n", opt); - exit(-1); -diff --git a/ip/ipaddress.c b/ip/ipaddress.c -index 5b9a438..c99a078 100644 ---- a/ip/ipaddress.c -+++ b/ip/ipaddress.c -@@ -28,6 +28,7 @@ - #include <linux/netdevice.h> - #include <linux/if_arp.h> - #include <linux/sockios.h> -+#include <linux/net_namespace.h> - - #include "rt_names.h" - #include "utils.h" -@@ -69,7 +70,7 @@ static void usage(void) - } - fprintf(stderr, "Usage: ip addr {add|change|replace} IFADDR dev STRING [ LIFETIME ]\n"); - fprintf(stderr, " [ CONFFLAG-LIST ]\n"); -- fprintf(stderr, " ip addr del IFADDR dev STRING\n"); -+ fprintf(stderr, " ip addr del IFADDR dev STRING [mngtmpaddr]\n"); - fprintf(stderr, " ip addr {show|save|flush} [ dev STRING ] [ scope SCOPE-ID ]\n"); - fprintf(stderr, " [ to PREFIX ] [ FLAG-LIST ] [ label PATTERN ] [up]\n"); - fprintf(stderr, " ip addr {showdump|restore}\n"); -@@ -82,7 +83,7 @@ static void usage(void) - fprintf(stderr, " tentative | deprecated | dadfailed | temporary |\n"); - fprintf(stderr, " CONFFLAG-LIST ]\n"); - fprintf(stderr, "CONFFLAG-LIST := [ CONFFLAG-LIST ] CONFFLAG\n"); -- fprintf(stderr, "CONFFLAG := [ home | nodad ]\n"); -+ fprintf(stderr, "CONFFLAG := [ home | nodad | mngtmpaddr | noprefixroute ]\n"); - fprintf(stderr, "LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]\n"); - fprintf(stderr, "LFT := forever | SECONDS\n"); - -@@ -223,12 +224,36 @@ static void print_linktype(FILE *fp, struct rtattr *tb) - } - } - -+static void print_af_spec(FILE *fp, struct rtattr *af_spec_attr) -+{ -+ struct rtattr *inet6_attr; -+ struct rtattr *tb[IFLA_INET6_MAX + 1]; -+ -+ inet6_attr = parse_rtattr_one_nested(AF_INET6, af_spec_attr); -+ if (!inet6_attr) -+ return; -+ -+ parse_rtattr_nested(tb, IFLA_INET6_MAX, inet6_attr); -+ -+ if (tb[IFLA_INET6_ADDR_GEN_MODE]) { -+ switch (rta_getattr_u8(tb[IFLA_INET6_ADDR_GEN_MODE])) { -+ case IN6_ADDR_GEN_MODE_EUI64: -+ fprintf(fp, "addrgenmode eui64 "); -+ break; -+ case IN6_ADDR_GEN_MODE_NONE: -+ fprintf(fp, "addrgenmode none "); -+ break; -+ } -+ } -+} -+ - static void print_vfinfo(FILE *fp, struct rtattr *vfinfo) - { - struct ifla_vf_mac *vf_mac; - struct ifla_vf_vlan *vf_vlan; - struct ifla_vf_tx_rate *vf_tx_rate; - struct ifla_vf_spoofchk *vf_spoofchk; -+ struct ifla_vf_link_state *vf_linkstate; - struct rtattr *vf[IFLA_VF_MAX+1]; - struct rtattr *tmp; - SPRINT_BUF(b1); -@@ -255,6 +280,20 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo) - else - vf_spoofchk = RTA_DATA(vf[IFLA_VF_SPOOFCHK]); - -+ if (vf_spoofchk) { -+ /* Check if the link state vf info type is supported by -+ * this kernel. -+ */ -+ tmp = (struct rtattr *)((char *)vf[IFLA_VF_SPOOFCHK] + -+ vf[IFLA_VF_SPOOFCHK]->rta_len); -+ -+ if (tmp->rta_type != IFLA_VF_LINK_STATE) -+ vf_linkstate = NULL; -+ else -+ vf_linkstate = RTA_DATA(vf[IFLA_VF_LINK_STATE]); -+ } else -+ vf_linkstate = NULL; -+ - fprintf(fp, "\n vf %d MAC %s", vf_mac->vf, - ll_addr_n2a((unsigned char *)&vf_mac->mac, - ETH_ALEN, 0, b1, sizeof(b1))); -@@ -270,99 +309,203 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo) - else - fprintf(fp, ", spoof checking off"); - } -+ if (vf_linkstate) { -+ if (vf_linkstate->link_state == IFLA_VF_LINK_STATE_AUTO) -+ fprintf(fp, ", link-state auto"); -+ else if (vf_linkstate->link_state == IFLA_VF_LINK_STATE_ENABLE) -+ fprintf(fp, ", link-state enable"); -+ else -+ fprintf(fp, ", link-state disable"); -+ } - } - --static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s) { -- fprintf(fp, "%s", _SL_); -+static void print_num(FILE *fp, unsigned width, uint64_t count) -+{ -+ const char *prefix = "kMGTPE"; -+ const unsigned int base = use_iec ? 1024 : 1000; -+ uint64_t powi = 1; -+ uint16_t powj = 1; -+ uint8_t precision = 2; -+ char buf[64]; -+ -+ if (!human_readable || count < base) { -+ fprintf(fp, "%-*"PRIu64" ", width, count); -+ return; -+ } -+ -+ /* increase value by a factor of 1000/1024 and print -+ * if result is something a human can read */ -+ for(;;) { -+ powi *= base; -+ if (count / base < powi) -+ break; -+ -+ if (!prefix[1]) -+ break; -+ ++prefix; -+ } -+ -+ /* try to guess a good number of digits for precision */ -+ for (; precision > 0; precision--) { -+ powj *= 10; -+ if (count / powi < powj) -+ break; -+ } -+ -+ snprintf(buf, sizeof(buf), "%.*f%c%s", precision, -+ (double) count / powi, *prefix, use_iec ? "i" : ""); -+ -+ fprintf(fp, "%-*s ", width, buf); -+} -+ -+static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s, -+ const struct rtattr *carrier_changes) -+{ -+ /* RX stats */ - fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s", - s->rx_compressed ? "compressed" : "", _SL_); -- fprintf(fp, " %-10"PRIu64" %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"", -- (uint64_t)s->rx_bytes, -- (uint64_t)s->rx_packets, -- (uint64_t)s->rx_errors, -- (uint64_t)s->rx_dropped, -- (uint64_t)s->rx_over_errors, -- (uint64_t)s->multicast); -+ -+ fprintf(fp, " "); -+ print_num(fp, 10, s->rx_bytes); -+ print_num(fp, 8, s->rx_packets); -+ print_num(fp, 7, s->rx_errors); -+ print_num(fp, 7, s->rx_dropped); -+ print_num(fp, 7, s->rx_over_errors); -+ print_num(fp, 7, s->multicast); - if (s->rx_compressed) -- fprintf(fp, " %-7"PRIu64"", -- (uint64_t)s->rx_compressed); -+ print_num(fp, 7, s->rx_compressed); -+ -+ /* RX error stats */ - if (show_stats > 1) { - fprintf(fp, "%s", _SL_); -- fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_); -- fprintf(fp, " %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"", -- (uint64_t)s->rx_length_errors, -- (uint64_t)s->rx_crc_errors, -- (uint64_t)s->rx_frame_errors, -- (uint64_t)s->rx_fifo_errors, -- (uint64_t)s->rx_missed_errors); -+ fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_); -+ -+ fprintf(fp, " "); -+ print_num(fp, 8, s->rx_length_errors); -+ print_num(fp, 7, s->rx_crc_errors); -+ print_num(fp, 7, s->rx_frame_errors); -+ print_num(fp, 7, s->rx_fifo_errors); -+ print_num(fp, 7, s->rx_missed_errors); - } - fprintf(fp, "%s", _SL_); -+ -+ /* TX stats */ - fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s", -- (uint64_t)s->tx_compressed ? "compressed" : "", _SL_); -- fprintf(fp, " %-10"PRIu64" %-8"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"", -- (uint64_t)s->tx_bytes, -- (uint64_t)s->tx_packets, -- (uint64_t)s->tx_errors, -- (uint64_t)s->tx_dropped, -- (uint64_t)s->tx_carrier_errors, -- (uint64_t)s->collisions); -+ s->tx_compressed ? "compressed" : "", _SL_); -+ -+ -+ fprintf(fp, " "); -+ print_num(fp, 10, s->tx_bytes); -+ print_num(fp, 8, s->tx_packets); -+ print_num(fp, 7, s->tx_errors); -+ print_num(fp, 7, s->tx_dropped); -+ print_num(fp, 7, s->tx_carrier_errors); -+ print_num(fp, 7, s->collisions); - if (s->tx_compressed) -- fprintf(fp, " %-7"PRIu64"", -- (uint64_t)s->tx_compressed); -+ print_num(fp, 7, s->tx_compressed); -+ -+ /* TX error stats */ - if (show_stats > 1) { - fprintf(fp, "%s", _SL_); -- fprintf(fp, " TX errors: aborted fifo window heartbeat%s", _SL_); -- fprintf(fp, " %-7"PRIu64" %-7"PRIu64" %-7"PRIu64" %-7"PRIu64"", -- (uint64_t)s->tx_aborted_errors, -- (uint64_t)s->tx_fifo_errors, -- (uint64_t)s->tx_window_errors, -- (uint64_t)s->tx_heartbeat_errors); -+ fprintf(fp, " TX errors: aborted fifo window heartbeat"); -+ if (carrier_changes) -+ fprintf(fp, " transns"); -+ fprintf(fp, "%s", _SL_); -+ -+ fprintf(fp, " "); -+ print_num(fp, 8, s->tx_aborted_errors); -+ print_num(fp, 7, s->tx_fifo_errors); -+ print_num(fp, 7, s->tx_window_errors); -+ print_num(fp, 7, s->tx_heartbeat_errors); -+ if (carrier_changes) -+ print_num(fp, 7, *(uint32_t*)RTA_DATA(carrier_changes)); - } - } - --static void print_link_stats(FILE *fp, const struct rtnl_link_stats *s) -+static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s, -+ const struct rtattr *carrier_changes) - { -- fprintf(fp, "%s", _SL_); -+ /* RX stats */ - fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s", - s->rx_compressed ? "compressed" : "", _SL_); -- fprintf(fp, " %-10u %-8u %-7u %-7u %-7u %-7u", -- s->rx_bytes, s->rx_packets, s->rx_errors, -- s->rx_dropped, s->rx_over_errors, -- s->multicast -- ); -+ -+ -+ fprintf(fp, " "); -+ print_num(fp, 10, s->rx_bytes); -+ print_num(fp, 8, s->rx_packets); -+ print_num(fp, 7, s->rx_errors); -+ print_num(fp, 7, s->rx_dropped); -+ print_num(fp, 7, s->rx_over_errors); -+ print_num(fp, 7, s->multicast); - if (s->rx_compressed) -- fprintf(fp, " %-7u", s->rx_compressed); -+ print_num(fp, 7, s->rx_compressed); -+ -+ /* RX error stats */ - if (show_stats > 1) { - fprintf(fp, "%s", _SL_); -- fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_); -- fprintf(fp, " %-7u %-7u %-7u %-7u %-7u", -- s->rx_length_errors, -- s->rx_crc_errors, -- s->rx_frame_errors, -- s->rx_fifo_errors, -- s->rx_missed_errors -- ); -+ fprintf(fp, " RX errors: length crc frame fifo missed%s", _SL_); -+ fprintf(fp, " "); -+ print_num(fp, 8, s->rx_length_errors); -+ print_num(fp, 7, s->rx_crc_errors); -+ print_num(fp, 7, s->rx_frame_errors); -+ print_num(fp, 7, s->rx_fifo_errors); -+ print_num(fp, 7, s->rx_missed_errors); - } - fprintf(fp, "%s", _SL_); -+ -+ /* TX stats */ - fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s", - s->tx_compressed ? "compressed" : "", _SL_); -- fprintf(fp, " %-10u %-8u %-7u %-7u %-7u %-7u", -- s->tx_bytes, s->tx_packets, s->tx_errors, -- s->tx_dropped, s->tx_carrier_errors, s->collisions); -+ -+ fprintf(fp, " "); -+ print_num(fp, 10, s->tx_bytes); -+ print_num(fp, 8, s->tx_packets); -+ print_num(fp, 7, s->tx_errors); -+ print_num(fp, 7, s->tx_dropped); -+ print_num(fp, 7, s->tx_carrier_errors); -+ print_num(fp, 7, s->collisions); - if (s->tx_compressed) -- fprintf(fp, " %-7u", s->tx_compressed); -+ print_num(fp, 7, s->tx_compressed); -+ -+ /* TX error stats */ - if (show_stats > 1) { - fprintf(fp, "%s", _SL_); -- fprintf(fp, " TX errors: aborted fifo window heartbeat%s", _SL_); -- fprintf(fp, " %-7u %-7u %-7u %-7u", -- s->tx_aborted_errors, -- s->tx_fifo_errors, -- s->tx_window_errors, -- s->tx_heartbeat_errors -- ); -+ fprintf(fp, " TX errors: aborted fifo window heartbeat"); -+ if (carrier_changes) -+ fprintf(fp, " transns"); -+ fprintf(fp, "%s", _SL_); -+ -+ fprintf(fp, " "); -+ print_num(fp, 8, s->tx_aborted_errors); -+ print_num(fp, 7, s->tx_fifo_errors); -+ print_num(fp, 7, s->tx_window_errors); -+ print_num(fp, 7, s->tx_heartbeat_errors); -+ if (carrier_changes) -+ print_num(fp, 7, *(uint32_t*)RTA_DATA(carrier_changes)); - } - } - -+static void __print_link_stats(FILE *fp, struct rtattr **tb) -+{ -+ if (tb[IFLA_STATS64]) -+ print_link_stats64(fp, RTA_DATA(tb[IFLA_STATS64]), -+ tb[IFLA_CARRIER_CHANGES]); -+ else if (tb[IFLA_STATS]) -+ print_link_stats32(fp, RTA_DATA(tb[IFLA_STATS]), -+ tb[IFLA_CARRIER_CHANGES]); -+} -+ -+static void print_link_stats(FILE *fp, struct nlmsghdr *n) -+{ -+ struct ifinfomsg *ifi = NLMSG_DATA(n); -+ struct rtattr * tb[IFLA_MAX+1]; -+ -+ parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), -+ n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi))); -+ __print_link_stats(fp, tb); -+ fprintf(fp, "%s", _SL_); -+} -+ - int print_linkinfo(const struct sockaddr_nl *who, - struct nlmsghdr *n, void *arg) - { -@@ -411,9 +554,13 @@ int print_linkinfo(const struct sockaddr_nl *who, - if (iflink == 0) - fprintf(fp, "@NONE: "); - else { -- fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1)); -- m_flag = ll_index_to_flags(iflink); -- m_flag = !(m_flag & IFF_UP); -+ if (tb[IFLA_LINK_NETNSID]) -+ fprintf(fp, "@if%d: ", iflink); -+ else { -+ fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1)); -+ m_flag = ll_index_to_flags(iflink); -+ m_flag = !(m_flag & IFF_UP); -+ } - } - } else { - fprintf(fp, ": "); -@@ -461,26 +608,36 @@ int print_linkinfo(const struct sockaddr_nl *who, - } - } - -- if (do_link && tb[IFLA_PROMISCUITY] && show_details) -+ if (tb[IFLA_LINK_NETNSID]) { -+ int id = *(int*)RTA_DATA(tb[IFLA_LINK_NETNSID]); -+ -+ if (id >= 0) -+ fprintf(fp, " link-netnsid %d", id); -+ else -+ fprintf(fp, " link-netnsid unknown"); -+ } -+ -+ if (tb[IFLA_PROMISCUITY] && show_details) - fprintf(fp, " promiscuity %u ", - *(int*)RTA_DATA(tb[IFLA_PROMISCUITY])); - -- if (do_link && tb[IFLA_LINKINFO] && show_details) -+ if (tb[IFLA_LINKINFO] && show_details) - print_linktype(fp, tb[IFLA_LINKINFO]); - -- if (do_link && tb[IFLA_IFALIAS]) { -+ if (do_link && tb[IFLA_AF_SPEC] && show_details) -+ print_af_spec(fp, tb[IFLA_AF_SPEC]); -+ -+ if ((do_link || show_details) && tb[IFLA_IFALIAS]) { - fprintf(fp, "%s alias %s", _SL_, - rta_getattr_str(tb[IFLA_IFALIAS])); - } - - if (do_link && show_stats) { -- if (tb[IFLA_STATS64]) -- print_link_stats64(fp, RTA_DATA(tb[IFLA_STATS64])); -- else if (tb[IFLA_STATS]) -- print_link_stats(fp, RTA_DATA(tb[IFLA_STATS])); -+ fprintf(fp, "%s", _SL_); -+ __print_link_stats(fp, tb); - } - -- if (do_link && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) { -+ if ((do_link || show_details) && tb[IFLA_VFINFO_LIST] && tb[IFLA_NUM_VF]) { - struct rtattr *i, *vflist = tb[IFLA_VFINFO_LIST]; - int rem = RTA_PAYLOAD(vflist); - for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) -@@ -489,7 +646,7 @@ int print_linkinfo(const struct sockaddr_nl *who, - - fprintf(fp, "\n"); - fflush(fp); -- return 0; -+ return 1; - } - - static int flush_update(void) -@@ -512,10 +669,17 @@ static int set_lifetime(unsigned int *lifetime, char *argv) - return 0; - } - -+static unsigned int get_ifa_flags(struct ifaddrmsg *ifa, -+ struct rtattr *ifa_flags_attr) -+{ -+ return ifa_flags_attr ? rta_getattr_u32(ifa_flags_attr) : -+ ifa->ifa_flags; -+} -+ - int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, - void *arg) - { -- FILE *fp = (FILE*)arg; -+ FILE *fp = arg; - struct ifaddrmsg *ifa = NLMSG_DATA(n); - int len = n->nlmsg_len; - int deprecated = 0; -@@ -536,7 +700,10 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, - if (filter.flushb && n->nlmsg_type != RTM_NEWADDR) - return 0; - -- parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa))); -+ parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), -+ n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa))); -+ -+ ifa_flags = get_ifa_flags(ifa, rta_tb[IFA_FLAGS]); - - if (!rta_tb[IFA_LOCAL]) - rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS]; -@@ -547,7 +714,7 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, - return 0; - if ((filter.scope^ifa->ifa_scope)&filter.scopemask) - return 0; -- if ((filter.flags^ifa->ifa_flags)&filter.flagmask) -+ if ((filter.flags ^ ifa_flags) & filter.flagmask) - return 0; - if (filter.label) { - SPRINT_BUF(b1); -@@ -613,7 +780,8 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, - abuf, sizeof(abuf))); - - if (rta_tb[IFA_ADDRESS] == NULL || -- memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), 4) == 0) { -+ memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]), RTA_DATA(rta_tb[IFA_LOCAL]), -+ ifa->ifa_family == AF_INET ? 4 : 16) == 0) { - fprintf(fp, "/%d ", ifa->ifa_prefixlen); - } else { - fprintf(fp, " peer %s/%d ", -@@ -640,36 +808,43 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, - abuf, sizeof(abuf))); - } - fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1))); -- ifa_flags = ifa->ifa_flags; -- if (ifa->ifa_flags&IFA_F_SECONDARY) { -+ if (ifa_flags & IFA_F_SECONDARY) { - ifa_flags &= ~IFA_F_SECONDARY; - if (ifa->ifa_family == AF_INET6) - fprintf(fp, "temporary "); - else - fprintf(fp, "secondary "); - } -- if (ifa->ifa_flags&IFA_F_TENTATIVE) { -+ if (ifa_flags & IFA_F_TENTATIVE) { - ifa_flags &= ~IFA_F_TENTATIVE; - fprintf(fp, "tentative "); - } -- if (ifa->ifa_flags&IFA_F_DEPRECATED) { -+ if (ifa_flags & IFA_F_DEPRECATED) { - ifa_flags &= ~IFA_F_DEPRECATED; - deprecated = 1; - fprintf(fp, "deprecated "); - } -- if (ifa->ifa_flags&IFA_F_HOMEADDRESS) { -+ if (ifa_flags & IFA_F_HOMEADDRESS) { - ifa_flags &= ~IFA_F_HOMEADDRESS; - fprintf(fp, "home "); - } -- if (ifa->ifa_flags&IFA_F_NODAD) { -+ if (ifa_flags & IFA_F_NODAD) { - ifa_flags &= ~IFA_F_NODAD; - fprintf(fp, "nodad "); - } -- if (!(ifa->ifa_flags&IFA_F_PERMANENT)) { -+ if (ifa_flags & IFA_F_MANAGETEMPADDR) { -+ ifa_flags &= ~IFA_F_MANAGETEMPADDR; -+ fprintf(fp, "mngtmpaddr "); -+ } -+ if (ifa_flags & IFA_F_NOPREFIXROUTE) { -+ ifa_flags &= ~IFA_F_NOPREFIXROUTE; -+ fprintf(fp, "noprefixroute "); -+ } -+ if (!(ifa_flags & IFA_F_PERMANENT)) { - fprintf(fp, "dynamic "); - } else - ifa_flags &= ~IFA_F_PERMANENT; -- if (ifa->ifa_flags&IFA_F_DADFAILED) { -+ if (ifa_flags & IFA_F_DADFAILED) { - ifa_flags &= ~IFA_F_DADFAILED; - fprintf(fp, "dadfailed "); - } -@@ -896,6 +1071,8 @@ static void ipaddr_filter(struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo) - for (a = ainfo->head; a; a = a->next) { - struct nlmsghdr *n = &a->h; - struct ifaddrmsg *ifa = NLMSG_DATA(n); -+ struct rtattr *tb[IFA_MAX + 1]; -+ unsigned int ifa_flags; - - if (ifa->ifa_index != ifi->ifi_index) - continue; -@@ -904,11 +1081,13 @@ static void ipaddr_filter(struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo) - continue; - if ((filter.scope^ifa->ifa_scope)&filter.scopemask) - continue; -- if ((filter.flags^ifa->ifa_flags)&filter.flagmask) -+ -+ parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n)); -+ ifa_flags = get_ifa_flags(ifa, tb[IFA_FLAGS]); -+ -+ if ((filter.flags ^ ifa_flags) & filter.flagmask) - continue; - if (filter.pfx.family || filter.label) { -- struct rtattr *tb[IFA_MAX+1]; -- parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n)); - if (!tb[IFA_LOCAL]) - tb[IFA_LOCAL] = tb[IFA_ADDRESS]; - -@@ -1084,6 +1263,12 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) - } else if (strcmp(*argv, "nodad") == 0) { - filter.flags |= IFA_F_NODAD; - filter.flagmask |= IFA_F_NODAD; -+ } else if (strcmp(*argv, "mngtmpaddr") == 0) { -+ filter.flags |= IFA_F_MANAGETEMPADDR; -+ filter.flagmask |= IFA_F_MANAGETEMPADDR; -+ } else if (strcmp(*argv, "noprefixroute") == 0) { -+ filter.flags |= IFA_F_NOPREFIXROUTE; -+ filter.flagmask |= IFA_F_NOPREFIXROUTE; - } else if (strcmp(*argv, "dadfailed") == 0) { - filter.flags |= IFA_F_DADFAILED; - filter.flagmask |= IFA_F_DADFAILED; -@@ -1163,11 +1348,15 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action) - } - - for (l = linfo.head; l; l = l->next) { -- if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) { -+ int res = 0; -+ -+ if (no_link || (res = print_linkinfo(NULL, &l->h, stdout)) >= 0) { - struct ifinfomsg *ifi = NLMSG_DATA(&l->h); - if (filter.family != AF_PACKET) - print_selected_addrinfo(ifi->ifi_index, - ainfo.head, stdout); -+ if (res > 0 && !do_link && show_stats) -+ print_link_stats(stdout, &l->h); - } - } - fflush(stdout); -@@ -1222,6 +1411,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv) - __u32 preferred_lft = INFINITY_LIFE_TIME; - __u32 valid_lft = INFINITY_LIFE_TIME; - struct ifa_cacheinfo cinfo; -+ unsigned int ifa_flags = 0; - - memset(&req, 0, sizeof(req)); - -@@ -1299,9 +1489,13 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv) - if (set_lifetime(&preferred_lft, *argv)) - invarg("preferred_lft value", *argv); - } else if (strcmp(*argv, "home") == 0) { -- req.ifa.ifa_flags |= IFA_F_HOMEADDRESS; -+ ifa_flags |= IFA_F_HOMEADDRESS; - } else if (strcmp(*argv, "nodad") == 0) { -- req.ifa.ifa_flags |= IFA_F_NODAD; -+ ifa_flags |= IFA_F_NODAD; -+ } else if (strcmp(*argv, "mngtmpaddr") == 0) { -+ ifa_flags |= IFA_F_MANAGETEMPADDR; -+ } else if (strcmp(*argv, "noprefixroute") == 0) { -+ ifa_flags |= IFA_F_NOPREFIXROUTE; - } else { - if (strcmp(*argv, "local") == 0) { - NEXT_ARG(); -@@ -1319,6 +1513,11 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv) - } - argc--; argv++; - } -+ if (ifa_flags <= 0xff) -+ req.ifa.ifa_flags = ifa_flags; -+ else -+ addattr32(&req.n, sizeof(req), IFA_FLAGS, ifa_flags); -+ - if (d == NULL) { - fprintf(stderr, "Not enough information: \"dev\" argument is required.\n"); - return -1; -diff --git a/ip/iplink.c b/ip/iplink.c -index dc98019..e17d5df 100644 ---- a/ip/iplink.c -+++ b/ip/iplink.c -@@ -31,6 +31,7 @@ - #include "rt_names.h" - #include "utils.h" - #include "ip_common.h" -+#include "namespace.h" - - #define IPLINK_IOCTL_COMPAT 1 - #ifndef LIBDIR -@@ -70,6 +71,7 @@ void iplink_usage(void) - fprintf(stderr, " [ mtu MTU ]\n"); - fprintf(stderr, " [ netns PID ]\n"); - fprintf(stderr, " [ netns NAME ]\n"); -+ fprintf(stderr, " [ link-netnsid ID ]\n"); - fprintf(stderr, " [ alias NAME ]\n"); - fprintf(stderr, " [ vf NUM [ mac LLADDR ]\n"); - fprintf(stderr, " [ vlan VLANID [ qos VLAN-QOS ] ]\n"); -@@ -77,8 +79,11 @@ void iplink_usage(void) - fprintf(stderr, " [ rate TXRATE ] ] \n"); - - fprintf(stderr, " [ spoofchk { on | off} ] ] \n"); -+ fprintf(stderr, " [ query_rss { on | off} ] ] \n"); -+ fprintf(stderr, " [ state { auto | enable | disable} ] ]\n"); - fprintf(stderr, " [ master DEVICE ]\n"); - fprintf(stderr, " [ nomaster ]\n"); -+ fprintf(stderr, " [ addrgenmode { eui64 | none } ]\n"); - fprintf(stderr, " ip link show [ DEVICE | group GROUP ] [up]\n"); - - if (iplink_have_newlink()) { -@@ -144,6 +149,15 @@ static int get_link_mode(const char *mode) - return -1; - } - -+static int get_addr_gen_mode(const char *mode) -+{ -+ if (strcasecmp(mode, "eui64") == 0) -+ return IN6_ADDR_GEN_MODE_EUI64; -+ if (strcasecmp(mode, "none") == 0) -+ return IN6_ADDR_GEN_MODE_NONE; -+ return -1; -+} -+ - #if IPLINK_IOCTL_COMPAT - static int have_rtnl_newlink = -1; - -@@ -176,8 +190,13 @@ static int iplink_have_newlink(void) - req.n.nlmsg_type = RTM_NEWLINK; - req.i.ifi_family = AF_UNSPEC; - -- rtnl_send(&rth, &req.n, req.n.nlmsg_len); -- rtnl_listen(&rth, accept_msg, NULL); -+ if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) { -+ perror("Could not check for " -+ "link configuration over netlink support"); -+ have_rtnl_newlink = 0; -+ } else { -+ rtnl_listen(&rth, accept_msg, NULL); -+ } - } - return have_rtnl_newlink; - } -@@ -254,7 +273,44 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp, - invarg("Invalid \"spoofchk\" value\n", *argv); - ivs.vf = vf; - addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK, &ivs, sizeof(ivs)); -+ } else if (matches(*argv, "state") == 0) { -+ struct ifla_vf_link_state ivl; -+ NEXT_ARG(); -+ if (matches(*argv, "auto") == 0) -+ ivl.link_state = IFLA_VF_LINK_STATE_AUTO; -+ else if (matches(*argv, "enable") == 0) -+ ivl.link_state = IFLA_VF_LINK_STATE_ENABLE; -+ else if (matches(*argv, "disable") == 0) -+ ivl.link_state = IFLA_VF_LINK_STATE_DISABLE; -+ else -+ invarg("Invalid \"state\" value\n", *argv); -+ ivl.vf = vf; -+ addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE, &ivl, sizeof(ivl)); -+ } else if (matches(*argv, "query_rss") == 0) { -+ struct ifla_vf_rss_query_en ivs; -+ NEXT_ARG(); -+ if (matches(*argv, "on") == 0) -+ ivs.setting = 1; -+ else if (matches(*argv, "off") == 0) -+ ivs.setting = 0; -+ else -+ invarg("Invalid \"query_rss\" value\n", *argv); -+ ivs.vf = vf; -+ addattr_l(&req->n, sizeof(*req), IFLA_VF_RSS_QUERY_EN, &ivs, sizeof(ivs)); - -+ } else if (matches(*argv, "state") == 0) { -+ struct ifla_vf_link_state ivl; -+ NEXT_ARG(); -+ if (matches(*argv, "auto") == 0) -+ ivl.link_state = IFLA_VF_LINK_STATE_AUTO; -+ else if (matches(*argv, "enable") == 0) -+ ivl.link_state = IFLA_VF_LINK_STATE_ENABLE; -+ else if (matches(*argv, "disable") == 0) -+ ivl.link_state = IFLA_VF_LINK_STATE_DISABLE; -+ else -+ invarg("Invalid \"state\" value\n", *argv); -+ ivl.vf = vf; -+ addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE, &ivl, sizeof(ivl)); - } else { - /* rewind arg */ - PREV_ARG(); -@@ -284,6 +340,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, - int vf = -1; - int numtxqueues = -1; - int numrxqueues = -1; -+ int link_netnsid = -1; - - *group = -1; - ret = argc; -@@ -334,7 +391,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, - NEXT_ARG(); - if (netns != -1) - duparg("netns", *argv); -- if ((netns = get_netns_fd(*argv)) >= 0) -+ if ((netns = netns_get_fd(*argv)) >= 0) - addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_FD, &netns, 4); - else if (get_integer(&netns, *argv, 0) == 0) - addattr_l(&req->n, sizeof(*req), IFLA_NET_NS_PID, &netns, 4); -@@ -466,6 +523,26 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, - invarg("Invalid \"numrxqueues\" value\n", *argv); - addattr_l(&req->n, sizeof(*req), IFLA_NUM_RX_QUEUES, - &numrxqueues, 4); -+ } else if (matches(*argv, "addrgenmode") == 0) { -+ struct rtattr *afs, *afs6; -+ int mode; -+ NEXT_ARG(); -+ mode = get_addr_gen_mode(*argv); -+ if (mode < 0) -+ invarg("Invalid address generation mode\n", *argv); -+ afs = addattr_nest(&req->n, sizeof(*req), IFLA_AF_SPEC); -+ afs6 = addattr_nest(&req->n, sizeof(*req), AF_INET6); -+ addattr8(&req->n, sizeof(*req), IFLA_INET6_ADDR_GEN_MODE, mode); -+ addattr_nest_end(&req->n, afs6); -+ addattr_nest_end(&req->n, afs); -+ } else if (matches(*argv, "link-netnsid") == 0) { -+ NEXT_ARG(); -+ if (link_netnsid != -1) -+ duparg("link-netnsid", *argv); -+ if (get_integer(&link_netnsid, *argv, 0)) -+ invarg("Invalid \"link-netnsid\" value\n", *argv); -+ addattr32(&req->n, sizeof(*req), IFLA_LINK_NETNSID, -+ link_netnsid); - } else { - if (strcmp(*argv, "dev") == 0) { - NEXT_ARG(); -diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c -index 1025326..43b8abc 100644 ---- a/ip/iplink_vxlan.c -+++ b/ip/iplink_vxlan.c -@@ -23,11 +23,12 @@ - - static void explain(void) - { -- fprintf(stderr, "Usage: ... vxlan id VNI [ group ADDR ] [ local ADDR ]\n"); -+ fprintf(stderr, "Usage: ... vxlan id VNI [ { group | remote } ADDR ] [ local ADDR ]\n"); - fprintf(stderr, " [ ttl TTL ] [ tos TOS ] [ dev PHYS_DEV ]\n"); -- fprintf(stderr, " [ port MIN MAX ] [ [no]learning ]\n"); -- fprintf(stderr, " [ [no]proxy ] [ [no]rsc ]\n"); -+ fprintf(stderr, " [ dstport PORT ] [ srcport MIN MAX ]\n"); -+ fprintf(stderr, " [ [no]learning ] [ [no]proxy ] [ [no]rsc ]\n"); - fprintf(stderr, " [ [no]l2miss ] [ [no]l3miss ]\n"); -+ fprintf(stderr, " [ gbp ]\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "Where: VNI := 0-16777215\n"); - fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n"); -@@ -42,6 +43,10 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, - int vni_set = 0; - __u32 saddr = 0; - __u32 gaddr = 0; -+ __u32 daddr = 0; -+ struct in6_addr saddr6 = IN6ADDR_ANY_INIT; -+ struct in6_addr gaddr6 = IN6ADDR_ANY_INIT; -+ struct in6_addr daddr6 = IN6ADDR_ANY_INIT; - unsigned link = 0; - __u8 tos = 0; - __u8 ttl = 0; -@@ -53,6 +58,12 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, - __u8 noage = 0; - __u32 age = 0; - __u32 maxaddr = 0; -+ __u16 dstport = 0; -+ __u8 gbp = 0; -+ __u8 udpcsum = 0; -+ __u8 udp6zerocsumtx = 0; -+ __u8 udp6zerocsumrx = 0; -+ int dst_port_set = 0; - struct ifla_vxlan_port_range range = { 0, 0 }; - - while (argc > 0) { -@@ -65,15 +76,30 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, - vni_set = 1; - } else if (!matches(*argv, "group")) { - NEXT_ARG(); -- gaddr = get_addr32(*argv); -- -- if (!IN_MULTICAST(ntohl(gaddr))) -- invarg("invald group address", *argv); -+ if (!inet_get_addr(*argv, &gaddr, &gaddr6)) { -+ fprintf(stderr, "Invalid address \"%s\"\n", *argv); -+ return -1; -+ } -+ if (!IN6_IS_ADDR_MULTICAST(&gaddr6) && !IN_MULTICAST(ntohl(gaddr))) -+ invarg("invalid group address", *argv); -+ } else if (!matches(*argv, "remote")) { -+ NEXT_ARG(); -+ if (!inet_get_addr(*argv, &daddr, &daddr6)) { -+ fprintf(stderr, "Invalid address \"%s\"\n", *argv); -+ return -1; -+ } -+ if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr))) -+ invarg("invalid remote address", *argv); - } else if (!matches(*argv, "local")) { - NEXT_ARG(); -- if (strcmp(*argv, "any")) -- saddr = get_addr32(*argv); -- if (IN_MULTICAST(ntohl(saddr))) -+ if (strcmp(*argv, "any")) { -+ if (!inet_get_addr(*argv, &saddr, &saddr6)) { -+ fprintf(stderr, "Invalid address \"%s\"\n", *argv); -+ return -1; -+ } -+ } -+ -+ if (IN_MULTICAST(ntohl(saddr)) || IN6_IS_ADDR_MULTICAST(&saddr6)) - invarg("invalid local address", *argv); - } else if (!matches(*argv, "dev")) { - NEXT_ARG(); -@@ -115,7 +141,8 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, - maxaddr = 0; - else if (get_u32(&maxaddr, *argv, 0)) - invarg("max addresses", *argv); -- } else if (!matches(*argv, "port")) { -+ } else if (!matches(*argv, "port") || -+ !matches(*argv, "srcport")) { - __u16 minport, maxport; - NEXT_ARG(); - if (get_u16(&minport, *argv, 0)) -@@ -125,6 +152,11 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, - invarg("max port", *argv); - range.low = htons(minport); - range.high = htons(maxport); -+ } else if (!matches(*argv, "dstport")){ -+ NEXT_ARG(); -+ if (get_u16(&dstport, *argv, 0)) -+ invarg("dst port", *argv); -+ dst_port_set = 1; - } else if (!matches(*argv, "nolearning")) { - learning = 0; - } else if (!matches(*argv, "learning")) { -@@ -145,6 +177,20 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, - l3miss = 0; - } else if (!matches(*argv, "l3miss")) { - l3miss = 1; -+ } else if (!matches(*argv, "gbp")) { -+ gbp = 1; -+ } else if (!matches(*argv, "udpcsum")) { -+ udpcsum = 1; -+ } else if (!matches(*argv, "noudpcsum")) { -+ udpcsum = 0; -+ } else if (!matches(*argv, "udp6zerocsumtx")) { -+ udp6zerocsumtx = 1; -+ } else if (!matches(*argv, "noudp6zerocsumtx")) { -+ udp6zerocsumtx = 0; -+ } else if (!matches(*argv, "udp6zerocsumrx")) { -+ udp6zerocsumrx = 1; -+ } else if (!matches(*argv, "noudp6zerocsumrx")) { -+ udp6zerocsumrx = 0; - } else if (matches(*argv, "help") == 0) { - explain(); - return -1; -@@ -160,11 +206,35 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, - fprintf(stderr, "vxlan: missing virtual network identifier\n"); - return -1; - } -+ -+ if (!dst_port_set) { -+ fprintf(stderr, "vxlan: destination port not specified\n" -+ "Will use Linux kernel default (non-standard value)\n"); -+ fprintf(stderr, -+ "Use 'dstport 4789' to get the IANA assigned value\n" -+ "Use 'dstport 0' to get default and quiet this message\n"); -+ } -+ if ((gaddr && daddr) || -+ (memcmp(&gaddr6, &in6addr_any, sizeof(gaddr6)) && -+ memcmp(&daddr6, &in6addr_any, sizeof(daddr6)))) { -+ fprintf(stderr, "vxlan: both group and remote cannot be specified\n"); -+ return -1; -+ } - addattr32(n, 1024, IFLA_VXLAN_ID, vni); - if (gaddr) - addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4); -+ else if (daddr) -+ addattr_l(n, 1024, IFLA_VXLAN_GROUP, &daddr, 4); -+ if (memcmp(&gaddr6, &in6addr_any, sizeof(gaddr6)) != 0) -+ addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &gaddr6, sizeof(struct in6_addr)); -+ else if (memcmp(&daddr6, &in6addr_any, sizeof(daddr6)) != 0) -+ addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &daddr6, sizeof(struct in6_addr)); -+ - if (saddr) - addattr_l(n, 1024, IFLA_VXLAN_LOCAL, &saddr, 4); -+ else if (memcmp(&saddr6, &in6addr_any, sizeof(saddr6)) != 0) -+ addattr_l(n, 1024, IFLA_VXLAN_LOCAL6, &saddr6, sizeof(struct in6_addr)); -+ - if (link) - addattr32(n, 1024, IFLA_VXLAN_LINK, link); - addattr8(n, 1024, IFLA_VXLAN_TTL, ttl); -@@ -174,6 +244,10 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, - addattr8(n, 1024, IFLA_VXLAN_RSC, rsc); - addattr8(n, 1024, IFLA_VXLAN_L2MISS, l2miss); - addattr8(n, 1024, IFLA_VXLAN_L3MISS, l3miss); -+ addattr8(n, 1024, IFLA_VXLAN_UDP_CSUM, udpcsum); -+ addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, udp6zerocsumtx); -+ addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, udp6zerocsumrx); -+ - if (noage) - addattr32(n, 1024, IFLA_VXLAN_AGEING, 0); - else if (age) -@@ -184,6 +258,13 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, - addattr_l(n, 1024, IFLA_VXLAN_PORT_RANGE, - &range, sizeof(range)); - -+ if (dstport) -+ addattr16(n, 1024, IFLA_VXLAN_PORT, htons(dstport)); -+ -+ if (gbp) -+ addattr_l(n, 1024, IFLA_VXLAN_GBP, NULL, 0); -+ -+ - return 0; - } - -@@ -208,9 +289,25 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) - - if (tb[IFLA_VXLAN_GROUP]) { - __be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_GROUP]); -- if (addr) -- fprintf(f, "group %s ", -- format_host(AF_INET, 4, &addr, s1, sizeof(s1))); -+ if (addr) { -+ if (IN_MULTICAST(ntohl(addr))) -+ fprintf(f, "group %s ", -+ format_host(AF_INET, 4, &addr, s1, sizeof(s1))); -+ else -+ fprintf(f, "remote %s ", -+ format_host(AF_INET, 4, &addr, s1, sizeof(s1))); -+ } -+ } else if (tb[IFLA_VXLAN_GROUP6]) { -+ struct in6_addr addr; -+ memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_GROUP6]), sizeof(struct in6_addr)); -+ if (memcmp(&addr, &in6addr_any, sizeof(addr)) != 0) { -+ if (IN6_IS_ADDR_MULTICAST(&addr)) -+ fprintf(f, "group %s ", -+ format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1))); -+ else -+ fprintf(f, "remote %s ", -+ format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1))); -+ } - } - - if (tb[IFLA_VXLAN_LOCAL]) { -@@ -218,6 +315,12 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) - if (addr) - fprintf(f, "local %s ", - format_host(AF_INET, 4, &addr, s1, sizeof(s1))); -+ } else if (tb[IFLA_VXLAN_LOCAL6]) { -+ struct in6_addr addr; -+ memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_LOCAL6]), sizeof(struct in6_addr)); -+ if (memcmp(&addr, &in6addr_any, sizeof(addr)) != 0) -+ fprintf(f, "local %s ", -+ format_host(AF_INET6, sizeof(struct in6_addr), &addr, s1, sizeof(s1))); - } - - if (tb[IFLA_VXLAN_LINK] && -@@ -233,9 +336,13 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) - if (tb[IFLA_VXLAN_PORT_RANGE]) { - const struct ifla_vxlan_port_range *r - = RTA_DATA(tb[IFLA_VXLAN_PORT_RANGE]); -- fprintf(f, "port %u %u ", ntohs(r->low), ntohs(r->high)); -+ fprintf(f, "srcport %u %u ", ntohs(r->low), ntohs(r->high)); - } - -+ if (tb[IFLA_VXLAN_PORT]) -+ fprintf(f, "dstport %u ", -+ ntohs(rta_getattr_u16(tb[IFLA_VXLAN_PORT]))); -+ - if (tb[IFLA_VXLAN_LEARNING] && - !rta_getattr_u8(tb[IFLA_VXLAN_LEARNING])) - fputs("nolearning ", f); -@@ -277,6 +384,20 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) - if (tb[IFLA_VXLAN_LIMIT] && - (maxaddr = rta_getattr_u32(tb[IFLA_VXLAN_LIMIT]) != 0)) - fprintf(f, "maxaddr %u ", maxaddr); -+ -+ if (tb[IFLA_VXLAN_UDP_CSUM] && rta_getattr_u8(tb[IFLA_VXLAN_UDP_CSUM])) -+ fputs("udpcsum ", f); -+ -+ if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX] && -+ rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX])) -+ fputs("udp6zerocsumtx ", f); -+ -+ if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX] && -+ rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX])) -+ fputs("udp6zerocsumrx ", f); -+ -+ if (tb[IFLA_VXLAN_GBP]) -+ fputs("gbp ", f); - } - - struct link_util vxlan_link_util = { -diff --git a/lib/libnetlink.c b/lib/libnetlink.c -index 9e2a795..baac6ae 100644 ---- a/lib/libnetlink.c -+++ b/lib/libnetlink.c -@@ -701,6 +701,18 @@ int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int l - return i; - } - -+struct rtattr *parse_rtattr_one(int type, struct rtattr *rta, int len) -+{ -+ while (RTA_OK(rta, len)) { -+ if (rta->rta_type == type) -+ return rta; -+ rta = RTA_NEXT(rta, len); -+ } -+ if (len) -+ fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); -+ return NULL; -+} -+ - int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, - int len) - { -diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in -index 86e0bc9..a015b82 100644 ---- a/man/man8/ip-link.8.in -+++ b/man/man8/ip-link.8.in -@@ -16,6 +16,7 @@ ip-link \- network device configuration - .ti -8 - .IR OPTIONS " := { " - \fB\-V\fR[\fIersion\fR] | -+\fB\-h\fR[\fIuman-readable\fR] | - \fB\-s\fR[\fItatistics\fR] | - \fB\-r\fR[\fIesolve\fR] | - \fB\-f\fR[\fIamily\fR] { -@@ -120,9 +121,11 @@ ip-link \- network device configuration - ] | - .br - .B master --.IR DEVICE -+.IR DEVICE " |" - .br --.B nomaster -+.B nomaster " |" -+.br -+.B addrgenmode { eui64 | none } - .BR " }" - - -@@ -197,6 +200,65 @@ specifies the number of transmit queues for new device. - specifies the number of receive queues for new device. - - .TP -+VLAN Type Support -+For a link of type -+.I VLAN -+the following additional arguments are supported: -+ -+.BI "ip link add link " DEVICE -+.BI name " NAME " -+.BI type " vlan " -+.R " [ " -+.BI protocol " VLAN_PROTO " -+.R " ] " -+.BI id " VLANID " -+.R " [ " -+.BR reorder_hdr " { " on " | " off " } " -+.R " ] " -+.R " [ " -+.BR gvrp " { " on " | " off " } " -+.R " ] " -+.R " [ " -+.BR mvrp " { " on " | " off " } " -+.R " ] " -+.R " [ " -+.BR loose_binding " { " on " | " off " } " -+.R " ] " -+.R " [ " -+.BI ingress-qos-map " QOS-MAP " -+.R " ] " -+.R " [ " -+.BI egress-qos-map " QOS-MAP " -+.R " ] " -+ -+.in +8 -+.sp -+.BI protocol " VLAN_PROTO " -+- either 802.1Q or 802.1ad. -+ -+.BI id " VLANID " -+- specifies the VID. -+ -+.BR reorder_hdr " { " on " | " off " } " -+- specifies whether ethernet headers are reordered or not. -+ -+.BR gvrp " { " on " | " off " } " -+- specifies whether this VLAN should be registered using GARP VLAN Registration Protocol. -+ -+.BR mvrp " { " on " | " off " } " -+- specifies whether this VLAN should be registered using Multiple VLAN Registration Protocol. -+ -+.BR loose_binding " { " on " | " off " } " -+- specifies whether the VLAN device state is bound to the physical device state. -+ -+.BI ingress-qos-map " QOS-MAP " -+- defines a mapping between priority code points on incoming frames. The format is FROM:TO with multiple mappings separated by spaces. -+ -+.BI egress-qos-map " QOS-MAP " -+- the same as ingress-qos-map but for outgoing frames. -+.in -8 -+ -+.TP - VXLAN Type Support - For a link of type - .I VXLAN -@@ -206,8 +268,8 @@ the following additional arguments are supported: - .BI type " vxlan " id " ID - .R " [ " - .BI dev " PHYS_DEV " --.R " ] [ " --.BI group " IPADDR " -+.RB " ] [ { " group " | " remote " } " -+.I IPADDR - .R " ] [ " - .BI local " IPADDR " - .R " ] [ " -@@ -226,6 +288,8 @@ the following additional arguments are supported: - .I "[no]l2miss " - .R " ] [ " - .I "[no]l3miss " -+.R " ] [ " -+.B gbp - .R " ]" - - .in +8 -@@ -240,6 +304,17 @@ Identifier) to use. - .sp - .BI group " IPADDR" - - specifies the multicast IP address to join. -+This parameter cannot be specified with the -+.B remote -+parameter. -+ -+.sp -+.BI remote " IPADDR" -+- specifies the unicast destination IP address to use in outgoing packets -+when the destination link layer address is not known in the VXLAN device -+forwarding database. This parameter cannot be specified with the -+.B group -+parameter. - - .sp - .BI local " IPADDR" -@@ -279,6 +354,49 @@ are entered into the VXLAN device forwarding database. - .I [no]l3miss - - specifies if netlink IP ADDR miss notifications are generated. - -+.sp -+.B gbp -+- enables the Group Policy extension (VXLAN-GBP). -+ -+.in +4 -+Allows to transport group policy context across VXLAN network peers. -+If enabled, includes the mark of a packet in the VXLAN header for outgoing -+packets and fills the packet mark based on the information found in the -+VXLAN header for incomming packets. -+ -+Format of upper 16 bits of packet mark (flags); -+ -+.in +2 -++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+.br -+|-|-|-|-|-|-|-|-|-|D|-|-|A|-|-|-| -+.br -++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+ -+.B D := -+Don't Learn bit. When set, this bit indicates that the egress -+VTEP MUST NOT learn the source address of the encapsulated frame. -+ -+.B A := -+Indicates that the group policy has already been applied to -+this packet. Policies MUST NOT be applied by devices when the A bit is set. -+.in -2 -+ -+Format of lower 16 bits of packet mark (policy ID): -+ -+.in +2 -++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+.br -+| Group Policy ID | -+.br -++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+.in -2 -+ -+Example: -+ iptables -A OUTPUT [...] -j MARK --set-mark 0x800FF -+ -+.in -4 -+ - .in -8 - - .SS ip link delete - delete virtual link -@@ -366,14 +484,29 @@ the interface is - .IR "POINTOPOINT" . - - .TP --.BI netns " PID" --move the device to the network namespace associated with the process --.IR "PID". -- --.TP --.BI netns " NETNSNAME" -+.BI netns " NETNSNAME " \fR| " PID" - move the device to the network namespace associated with name --.IR "NETNSNAME". -+.IR "NETNSNAME " or -+.RI process " PID". -+ -+Some devices are not allowed to change network namespace: loopback, bridge, -+ppp, wireless. These are network namespace local devices. In such case -+.B ip -+tool will return "Invalid argument" error. It is possible to find out if device is local -+to a single network namespace by checking -+.B netns-local -+flag in the output of the -+.BR ethtool ":" -+ -+.in +8 -+.B ethtool -k -+.I DEVICE -+.in -8 -+ -+To change network namespace for wireless devices the -+.B iw -+tool can be used. But it allows to change network namespace only for physical devices and by process -+.IR PID . - - .TP - .BI alias " NAME" -@@ -442,6 +575,10 @@ set master device of the device (enslave device). - .BI nomaster - unset master device of the device (release device). - -+.TP -+.BR "addrgenmode eui64 " or " addrgenmode none" -+allow to ipv6 set address generation mode -+ - .PP - .B Warning: - If multiple parameter changes are requested, -@@ -471,6 +608,27 @@ specifies what group of devices to show. - .B up - only display running interfaces. - -+.TP -+The show command has additional formatting options: -+ -+.RS -+.TP -+.BR "\-s" , " \-stats", " \-statistics" -+output more statistics about packet usage. -+ -+.TP -+.BR "\-d", " \-details" -+output more detailed information. -+ -+.TP -+.BR "\-h", " \-human", " \-human-readble" -+output statistics with human readable values number followed by suffix -+ -+.TP -+.BR "\-iec" -+print human readable rates in IEC units (ie. 1K = 1024). -+.RE -+ - .SH "EXAMPLES" - .PP - ip link show -@@ -495,7 +653,8 @@ Removes vlan device. - - .SH SEE ALSO - .br --.BR ip (8) -+.BR ip (8), -+.BR ip-netns (8) - - .SH AUTHOR - Original Manpage by Michail Litvak <mci@owl.openwall.com> -diff --git a/man/man8/ip.8 b/man/man8/ip.8 -index 9065b3a..0713756 100644 ---- a/man/man8/ip.8 -+++ b/man/man8/ip.8 -@@ -31,7 +31,8 @@ ip \- show / manipulate routing, devices, policy routing and tunnels - \fB\-r\fR[\fIesolve\fR] | - \fB\-f\fR[\fIamily\fR] { - .BR inet " | " inet6 " | " ipx " | " dnet " | " link " } | " --\fB\-o\fR[\fIneline\fR] } -+\fB\-o\fR[\fIneline\fR] | -+\fB\-n\fR[\fIetns\fR] name } - - - .SH OPTIONS -@@ -130,6 +131,26 @@ the output. - use the system's name resolver to print DNS names instead of - host addresses. - -+.TP -+.BR "\-n" , " \-net" , " \-netns " <NETNS> -+switches -+.B ip -+to the specified network namespace -+.IR NETNS . -+Actually it just simplifies executing of: -+ -+.B ip netns exec -+.IR NETNS -+.B ip -+.RI "[ " OPTIONS " ] " OBJECT " { " COMMAND " | " -+.BR help " }" -+ -+to -+ -+.B ip -+.RI "-n[etns] " NETNS " [ " OPTIONS " ] " OBJECT " { " COMMAND " | " -+.BR help " }" -+ - .SH IP - COMMAND SYNTAX - - .SS diff --git a/SOURCES/iproute2-3.10.0-backport-additional-INET_DIAG-flags-in-inet_diag.h.patch b/SOURCES/iproute2-3.10.0-backport-additional-INET_DIAG-flags-in-inet_diag.h.patch deleted file mode 100644 index 3cee455..0000000 --- a/SOURCES/iproute2-3.10.0-backport-additional-INET_DIAG-flags-in-inet_diag.h.patch +++ /dev/null @@ -1,29 +0,0 @@ -From da2469f770c19421ed5bbc575f76abd7f3affc10 Mon Sep 17 00:00:00 2001 -From: Phil Sutter <psutter@redhat.com> -Date: Sun, 2 Aug 2015 07:29:09 -0400 -Subject: [PATCH 1/2] backport additional INET_DIAG flags in inet_diag.h - ---- - include/linux/inet_diag.h | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h -index 7438dad..f1d4b59 100644 ---- a/include/linux/inet_diag.h -+++ b/include/linux/inet_diag.h -@@ -111,9 +111,11 @@ enum { - INET_DIAG_SKMEMINFO, - INET_DIAG_SHUTDOWN, - INET_DIAG_DCTCPINFO, -+ INET_DIAG_PROTOCOL, /* response attribute only */ -+ INET_DIAG_SKV6ONLY, - }; - --#define INET_DIAG_MAX INET_DIAG_DCTCPINFO -+#define INET_DIAG_MAX INET_DIAG_SKV6ONLY - - /* INET_DIAG_MEM */ - --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-bridge-Add-master-device-name-to-bridge-fdb-show.patch b/SOURCES/iproute2-3.10.0-bridge-Add-master-device-name-to-bridge-fdb-show.patch deleted file mode 100644 index e3b55b5..0000000 --- a/SOURCES/iproute2-3.10.0-bridge-Add-master-device-name-to-bridge-fdb-show.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 52296b5871435812cb2a05bcc3166968e170d783 Mon Sep 17 00:00:00 2001 -From: Roopa Prabhu <roopa@cumulusnetworks.com> -Date: Sat, 7 Jun 2014 22:23:42 -0700 -Subject: [PATCH] bridge: Add master device name to bridge fdb show - -This patch adds master dev name from NDA_MASTER netlink attribute - to bridge fdb show output - -current iproute2 tries to print 'master' in the output if NTF_MASTER -is present. But, kernel today does not set NTF_MASTER during dump -requests. Which means I have not seen iproute2 bridge cmd print 'master' atall. -This patch overrides the NTF_MASTER flag if NDA_MASTER attribute is present. - -Example output: - -before this patch: -# bridge fdb show -44:38:39:00:27:ba dev bond2.2003 permanent -44:38:39:00:27:bb dev bond4.2003 permanent -44:38:39:00:27:bc dev bond2.2004 permanent - -After this patch: -# bridge fdb show -44:38:39:00:27:ba dev bond2.2003 master br-2003 permanent -44:38:39:00:27:bb dev bond4.2003 master br-2003 permanent -44:38:39:00:27:bc dev bond2.2004 master br-2004 permanent - -For comparision with the above, below is the output for NTF_SELF today, -# bridge fdb show -33:33:00:00:00:01 dev eth0 self permanent -01:00:5e:00:00:01 dev eth0 self permanent -33:33:ff:00:01:cc dev eth0 self permanent - -If change in output is a concern, 'master' can be put at the end of the fdb -output line or made optional with -d[etails] option. - -change from v1 to v2: - use 'bridge' instead of 'master' in fdb show output - -change from v2 to v3: - use 'master' instead of 'bridge' in fdb show output - (master could also be a vxlan device) - -Signed-off-by: Wilson Kok <wkok@cumulusnetworks.com> -Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com> ---- - bridge/fdb.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/bridge/fdb.c b/bridge/fdb.c -index f725012..615541e 100644 ---- a/bridge/fdb.c -+++ b/bridge/fdb.c -@@ -145,7 +145,10 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) - } - if (r->ndm_flags & NTF_SELF) - fprintf(fp, "self "); -- if (r->ndm_flags & NTF_MASTER) -+ if (tb[NDA_MASTER]) -+ fprintf(fp, "master %s ", -+ ll_index_to_name(rta_getattr_u32(tb[NDA_MASTER]))); -+ else if (r->ndm_flags & NTF_MASTER) - fprintf(fp, "master "); - if (r->ndm_flags & NTF_ROUTER) - fprintf(fp, "router "); --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-bridge.patch b/SOURCES/iproute2-3.10.0-bridge.patch deleted file mode 100644 index 7d04738..0000000 --- a/SOURCES/iproute2-3.10.0-bridge.patch +++ /dev/null @@ -1,323 +0,0 @@ -commit 2a9f06affaf089608a8137decaa17c5aee71ed6f -Author: Pavel Šimerda <psimerda@redhat.com> -Date: Thu May 28 12:17:38 2015 +0200 - - backport selected bridge features and documentation - -diff --git a/bridge/Makefile b/bridge/Makefile -index 1fb8320..9800753 100644 ---- a/bridge/Makefile -+++ b/bridge/Makefile -@@ -2,6 +2,10 @@ BROBJ = bridge.o fdb.o monitor.o link.o mdb.o vlan.o - - include ../Config - -+ifeq ($(IP_CONFIG_SETNS),y) -+ CFLAGS += -DHAVE_SETNS -+endif -+ - all: bridge - - bridge: $(BROBJ) $(LIBNETLINK) -diff --git a/bridge/bridge.c b/bridge/bridge.c -index ee08f90..5fcc552 100644 ---- a/bridge/bridge.c -+++ b/bridge/bridge.c -@@ -13,6 +13,7 @@ - #include "SNAPSHOT.h" - #include "utils.h" - #include "br_common.h" -+#include "namespace.h" - - struct rtnl_handle rth = { .fd = -1 }; - int preferred_family = AF_UNSPEC; -@@ -31,7 +32,7 @@ static void usage(void) - "Usage: bridge [ OPTIONS ] OBJECT { COMMAND | help }\n" - "where OBJECT := { link | fdb | mdb | vlan | monitor }\n" - " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n" --" -o[neline] | -t[imestamp] \n"); -+" -o[neline] | -t[imestamp] | -n[etns] name }\n"); - exit(-1); - } - -@@ -112,6 +113,10 @@ main(int argc, char **argv) - preferred_family = AF_INET; - } else if (strcmp(opt, "-6") == 0) { - preferred_family = AF_INET6; -+ } else if (matches(opt, "-netns") == 0) { -+ NEXT_ARG(); -+ if (netns_switch(argv[1])) -+ exit(-1); - } else { - fprintf(stderr, "Option \"%s\" is unknown, try \"bridge help\".\n", opt); - exit(-1); -diff --git a/bridge/fdb.c b/bridge/fdb.c -index 591fbbe..f725012 100644 ---- a/bridge/fdb.c -+++ b/bridge/fdb.c -@@ -30,7 +30,7 @@ int filter_index; - - static void usage(void) - { -- fprintf(stderr, "Usage: bridge fdb { add | append | del } ADDR dev DEV {self|master} [ temp ]\n" -+ fprintf(stderr, "Usage: bridge fdb { add | append | del | replace } ADDR dev DEV {self|master} [ temp ]\n" - " [router] [ dst IPADDR] [ vlan VID ]\n" - " [ port PORT] [ vni VNI ] [via DEV]\n"); - fprintf(stderr, " bridge fdb {show} [ dev DEV ]\n"); -@@ -125,12 +125,16 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) - if (ifindex) { - char ifname[IF_NAMESIZE]; - -- if (if_indextoname(ifindex, ifname)) -+ if (!tb[NDA_LINK_NETNSID] && -+ if_indextoname(ifindex, ifname)) - fprintf(fp, "via %s ", ifname); - else - fprintf(fp, "via ifindex %u ", ifindex); - } - } -+ if (tb[NDA_LINK_NETNSID]) -+ fprintf(fp, "link-netnsid %d ", -+ rta_getattr_u32(tb[NDA_LINK_NETNSID])); - - if (show_stats && tb[NDA_CACHEINFO]) { - struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]); -@@ -334,6 +338,8 @@ int do_fdb(int argc, char **argv) - return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_EXCL, argc-1, argv+1); - if (matches(*argv, "append") == 0) - return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_APPEND, argc-1, argv+1); -+ if (matches(*argv, "replace") == 0) -+ return fdb_modify(RTM_NEWNEIGH, NLM_F_CREATE|NLM_F_REPLACE, argc-1, argv+1); - if (matches(*argv, "delete") == 0) - return fdb_modify(RTM_DELNEIGH, 0, argc-1, argv+1); - if (matches(*argv, "show") == 0 || -diff --git a/bridge/monitor.c b/bridge/monitor.c -index e96fcaf..76e7d47 100644 ---- a/bridge/monitor.c -+++ b/bridge/monitor.c -@@ -132,12 +132,15 @@ int do_monitor(int argc, char **argv) - - if (file) { - FILE *fp; -+ int err; - fp = fopen(file, "r"); - if (fp == NULL) { - perror("Cannot fopen"); - exit(-1); - } -- return rtnl_from_file(fp, accept_msg, stdout); -+ err = rtnl_from_file(fp, accept_msg, stdout); -+ fclose(fp); -+ return err; - } - - if (rtnl_open(&rth, groups) < 0) -diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 -index 66678b5..9db2aec 100644 ---- a/man/man8/bridge.8 -+++ b/man/man8/bridge.8 -@@ -13,13 +13,14 @@ bridge \- show / manipulate bridge addresses and devices - - .ti -8 - .IR OBJECT " := { " --.BR link " | " fdb " | " vlan " | " monitor " }" -+.BR link " | " fdb " | " mdb " | " vlan " | " monitor " }" - .sp - - .ti -8 - .IR OPTIONS " := { " - \fB\-V\fR[\fIersion\fR] | --\fB\-s\fR[\fItatistics\fR] } -+\fB\-s\fR[\fItatistics\fR] | -+\fB\-n\fR[\fIetns\fR] name } - - .ti -8 - .BR "bridge link set" -@@ -44,12 +45,12 @@ bridge \- show / manipulate bridge addresses and devices - .IR DEV " ]" - - .ti -8 --.BR "bridge fdb" " { " add " | " append " | " del " } " -+.BR "bridge fdb" " { " add " | " append " | " del " | " replace " } " - .I LLADDR - .B dev - .IR DEV " { " - .BR local " | " temp " } { " --.BR self " } { " embedded " } { " router " } [ " -+.BR self " } { " router " } [ " - .B dst - .IR IPADDR " ] [ " - .B vni -@@ -65,6 +66,21 @@ bridge \- show / manipulate bridge addresses and devices - .IR DEV " ]" - - .ti -8 -+.BR "bridge mdb" " { " add " | " del " } " -+.B dev -+.IR DEV -+.B port -+.IR PORT -+.B grp -+.IR GROUP " [ " -+.BR permanent " | " temp " ]" -+ -+.ti -8 -+.BR "bridge mdb show " [ " -+.B dev -+.IR DEV " ]" -+ -+.ti -8 - .BR "bridge vlan" " { " add " | " del " } " - .B dev - .IR DEV -@@ -79,7 +95,7 @@ bridge \- show / manipulate bridge addresses and devices - .IR DEV " ]" - - .ti -8 --.BR "bridge monitor" " [ " all " | " neigh " | " link " ]" -+.BR "bridge monitor" " [ " all " | " neigh " | " link " | " mdb " ]" - - .SH OPTIONS - -@@ -95,6 +111,26 @@ output more information. If this option - is given multiple times, the amount of information increases. - As a rule, the information is statistics or some time values. - -+.TP -+.BR "\-n" , " \-net" , " \-netns " <NETNS> -+switches -+.B bridge -+to the specified network namespace -+.IR NETNS . -+Actually it just simplifies executing of: -+ -+.B ip netns exec -+.IR NETNS -+.B bridge -+.RI "[ " OPTIONS " ] " OBJECT " { " COMMAND " | " -+.BR help " }" -+ -+to -+ -+.B bridge -+.RI "-n[etns] " NETNS " [ " OPTIONS " ] " OBJECT " { " COMMAND " | " -+.BR help " }" -+ - - .SH BRIDGE - COMMAND SYNTAX - -@@ -110,6 +146,10 @@ As a rule, the information is statistics or some time values. - - Forwarding Database entry. - - .TP -+.B mdb -+- Multicast group database entry. -+ -+.TP - .B vlan - - VLAN filter list. - -@@ -256,10 +296,6 @@ the interface to which this address is associated. - - the address is associated with a software fdb (default) - .sp - --.B embedded --- the address is associated with an offloaded fdb --.sp -- - .B router - - the destination address is associated with a router. - Valid if the referenced device is a VXLAN type device and has -@@ -314,6 +350,13 @@ This command removes an existing fdb entry. - - .PP - The arguments are the same as with -+.BR "bridge fdb add" . -+ -+.SS bridge fdb replace - replace a forwarding database entry -+This command replaces an already present fdb entry. -+ -+.PP -+The arguments are the same as with - .BR "bridge fdb add" , - - .SS bridge fdb show - list forwarding entries. -@@ -326,6 +369,69 @@ With the - option, the command becomes verbose. It prints out the last updated - and last used time for each entry. - -+.SH bridge mdb - multicast group database management -+ -+.B mdb -+objects contain known IP multicast group addresses on a link. -+ -+.P -+The corresponding commands display mdb entries, add new entries, -+and delete old ones. -+ -+.SS bridge mdb add - add a new multicast group database entry -+ -+This command creates a new mdb entry. -+ -+.TP -+.BI dev " DEV" -+the interface where this group address is associated. -+ -+.TP -+.BI port " PORT" -+the port whose link is known to have members of this multicast group. -+ -+.TP -+.BI grp " GROUP" -+the IP multicast group address whose members reside on the link connected to -+the port. -+ -+.B permanent -+- the mdb entry is permanent -+.sp -+ -+.B temp -+- the mdb entry is temporary (default) -+.sp -+ -+.in -8 -+.SS bridge mdb delete - delete a multicast group database entry -+This command removes an existing mdb entry. -+ -+.PP -+The arguments are the same as with -+.BR "bridge mdb add" . -+ -+.SS bridge mdb show - list multicast group database entries -+ -+This command displays the current multicast group membership table. The table -+is populated by IGMP and MLD snooping in the bridge driver automatically. It -+can be altered by -+.B bridge mdb add -+and -+.B bridge mdb del -+commands manually too. -+ -+.TP -+.BI dev " DEV" -+the interface only whose entries should be listed. Default is to list all -+bridge interfaces. -+ -+.PP -+With the -+.B -details -+option, the command becomes verbose. It prints out the ports known to have -+a connected router. -+ - .SH bridge vlan - VLAN filter list - - .B vlan -@@ -395,7 +501,7 @@ command is the first in the command line and then the object list follows: - .I OBJECT-LIST - is the list of object types that we want to monitor. - It may contain --.BR link ", and " fdb "." -+.BR link ", " fdb ", and " mdb "." - If no - .B file - argument is given, diff --git a/SOURCES/iproute2-3.10.0-fix-ip-tunnel-command-for-vti-tunnels-with-io-key-gi.patch b/SOURCES/iproute2-3.10.0-fix-ip-tunnel-command-for-vti-tunnels-with-io-key-gi.patch deleted file mode 100644 index a48f70b..0000000 --- a/SOURCES/iproute2-3.10.0-fix-ip-tunnel-command-for-vti-tunnels-with-io-key-gi.patch +++ /dev/null @@ -1,304 +0,0 @@ -From ac525bc5be98547620bc8d9df9e040438f60f2a8 Mon Sep 17 00:00:00 2001 -From: Phil Sutter <psutter@redhat.com> -Date: Fri, 7 Aug 2015 13:18:13 +0200 -Subject: [PATCH] fix ip tunnel command for vti tunnels with [io]key given - -This patch folds five upstream commits: -- 30d07e9 iproute2: spelling: noptmudisc -> nopmtudisc -- 1c28bd5 iptunnel: Allow GRE_KEY for vti interface -- 0612519 Remove trailing whitespace -- 0cb6bb5 do not exit silently when link is not found -- 23d526c fix ip tunnel for vti tunnels with ikey ---- - ip/ipaddress.c | 2 +- - ip/ipaddrlabel.c | 2 +- - ip/iplink_vxlan.c | 5 ++++- - ip/iproute.c | 2 +- - ip/iptunnel.c | 36 ++++++++++++++++++++---------------- - ip/ipxfrm.c | 4 ++-- - ip/link_gre.c | 7 +++++-- - ip/link_gre6.c | 5 ++++- - ip/link_iptnl.c | 2 +- - ip/link_vti.c | 5 ++++- - ip/tunnel.c | 2 +- - ip/xfrm_state.c | 2 +- - 12 files changed, 45 insertions(+), 29 deletions(-) - -diff --git a/ip/ipaddress.c b/ip/ipaddress.c -index c99a078..4650a2e 100644 ---- a/ip/ipaddress.c -+++ b/ip/ipaddress.c -@@ -126,7 +126,7 @@ static void print_link_flags(FILE *fp, unsigned flags, unsigned mdown) - } - - static const char *oper_states[] = { -- "UNKNOWN", "NOTPRESENT", "DOWN", "LOWERLAYERDOWN", -+ "UNKNOWN", "NOTPRESENT", "DOWN", "LOWERLAYERDOWN", - "TESTING", "DORMANT", "UP" - }; - -diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c -index 1789d9c..301074b 100644 ---- a/ip/ipaddrlabel.c -+++ b/ip/ipaddrlabel.c -@@ -134,7 +134,7 @@ static int ipaddrlabel_modify(int cmd, int argc, char **argv) - inet_prefix prefix; - uint32_t label = 0xffffffffUL; - char *p = NULL; -- char *l = NULL; -+ char *l = NULL; - - memset(&req, 0, sizeof(req)); - memset(&prefix, 0, sizeof(prefix)); -diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c -index 43b8abc..2f3a84c 100644 ---- a/ip/iplink_vxlan.c -+++ b/ip/iplink_vxlan.c -@@ -104,8 +104,11 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, - } else if (!matches(*argv, "dev")) { - NEXT_ARG(); - link = if_nametoindex(*argv); -- if (link == 0) -+ if (link == 0) { -+ fprintf(stderr, "Cannot find device \"%s\"\n", -+ *argv); - exit(-1); -+ } - } else if (!matches(*argv, "ttl") || - !matches(*argv, "hoplimit")) { - unsigned uval; -diff --git a/ip/iproute.c b/ip/iproute.c -index 984d970..207301c 100644 ---- a/ip/iproute.c -+++ b/ip/iproute.c -@@ -837,7 +837,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) - } - if (get_time_rtt(&rtt, *argv, &raw)) - invarg("\"rtt\" value is invalid\n", *argv); -- rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTT, -+ rta_addattr32(mxrta, sizeof(mxbuf), RTAX_RTT, - (raw) ? rtt : rtt * 8); - } else if (strcmp(*argv, "rto_min") == 0) { - unsigned rto_min; -diff --git a/ip/iptunnel.c b/ip/iptunnel.c -index 9099503..29188c4 100644 ---- a/ip/iptunnel.c -+++ b/ip/iptunnel.c -@@ -240,8 +240,9 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) - } - } - -- if (p->iph.protocol == IPPROTO_IPIP || p->iph.protocol == IPPROTO_IPV6) { -- if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) { -+ if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) { -+ if (!(p->i_flags & VTI_ISVTI) && -+ (p->iph.protocol != IPPROTO_GRE)) { - fprintf(stderr, "Keys are not allowed with ipip and sit tunnels\n"); - return -1; - } -@@ -249,8 +250,11 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) - - if (medium[0]) { - p->link = if_nametoindex(medium); -- if (p->link == 0) -+ if (p->link == 0) { -+ fprintf(stderr, "Cannot find device \"%s\"\n", -+ medium); - return -1; -+ } - } - - if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { -@@ -280,16 +284,16 @@ static int do_add(int cmd, int argc, char **argv) - return -1; - - if (p.iph.ttl && p.iph.frag_off == 0) { -- fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n"); -+ fprintf(stderr, "ttl != 0 and nopmtudisc are incompatible\n"); - return -1; - } - - switch (p.iph.protocol) { - case IPPROTO_IPIP: -- if (p.i_flags != VTI_ISVTI) -- return tnl_add_ioctl(cmd, "tunl0", p.name, &p); -- else -+ if (p.i_flags & VTI_ISVTI) - return tnl_add_ioctl(cmd, "ip_vti0", p.name, &p); -+ else -+ return tnl_add_ioctl(cmd, "tunl0", p.name, &p); - case IPPROTO_GRE: - return tnl_add_ioctl(cmd, "gre0", p.name, &p); - case IPPROTO_IPV6: -@@ -310,10 +314,10 @@ static int do_del(int argc, char **argv) - - switch (p.iph.protocol) { - case IPPROTO_IPIP: -- if (p.i_flags != VTI_ISVTI) -- return tnl_del_ioctl("tunl0", p.name, &p); -- else -+ if (p.i_flags & VTI_ISVTI) - return tnl_del_ioctl("ip_vti0", p.name, &p); -+ else -+ return tnl_del_ioctl("tunl0", p.name, &p); - case IPPROTO_GRE: - return tnl_del_ioctl("gre0", p.name, &p); - case IPPROTO_IPV6: -@@ -344,16 +348,16 @@ static void print_tunnel(struct ip_tunnel_parm *p) - if (p->iph.protocol == IPPROTO_IPV6 && (p->i_flags & SIT_ISATAP)) { - struct ip_tunnel_prl prl[16]; - int i; -- -+ - memset(prl, 0, sizeof(prl)); - prl[0].datalen = sizeof(prl) - sizeof(prl[0]); - prl[0].addr = htonl(INADDR_ANY); -- -+ - if (!tnl_prl_ioctl(SIOCGETPRL, p->name, prl)) - for (i = 1; i < sizeof(prl) / sizeof(prl[0]); i++) - { - if (prl[i].addr != htonl(INADDR_ANY)) { -- printf(" %s %s ", -+ printf(" %s %s ", - (prl[i].flags & PRL_DEFAULT) ? "pdr" : "pr", - format_host(AF_INET, 4, &prl[i].addr, s1, sizeof(s1))); - } -@@ -502,10 +506,10 @@ static int do_show(int argc, char **argv) - - switch (p.iph.protocol) { - case IPPROTO_IPIP: -- if (p.i_flags != VTI_ISVTI) -- err = tnl_get_ioctl(p.name[0] ? p.name : "tunl0", &p); -- else -+ if (p.i_flags & VTI_ISVTI) - err = tnl_get_ioctl(p.name[0] ? p.name : "ip_vti0", &p); -+ else -+ err = tnl_get_ioctl(p.name[0] ? p.name : "tunl0", &p); - break; - case IPPROTO_GRE: - err = tnl_get_ioctl(p.name[0] ? p.name : "gre0", &p); -diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c -index 020159c..a6ec4cf 100644 ---- a/ip/ipxfrm.c -+++ b/ip/ipxfrm.c -@@ -358,7 +358,7 @@ void xfrm_stats_print(struct xfrm_stats *s, FILE *fp, const char *prefix) - - if (prefix) - fputs(prefix, fp); -- fprintf(fp, " replay-window %u replay %u failed %u%s", -+ fprintf(fp, " replay-window %u replay %u failed %u%s", - s->replay_window, s->replay, s->integrity_failed, _SL_); - } - -@@ -409,7 +409,7 @@ void xfrm_lifetime_print(struct xfrm_lifetime_cfg *cfg, - - if (prefix) - fputs(prefix, fp); -- fprintf(fp, " expire add: soft %llu(sec), hard %llu(sec)%s", -+ fprintf(fp, " expire add: soft %llu(sec), hard %llu(sec)%s", - (unsigned long long) cfg->soft_add_expires_seconds, - (unsigned long long) cfg->hard_add_expires_seconds, - _SL_); -diff --git a/ip/link_gre.c b/ip/link_gre.c -index 7e0b896..fda84d8 100644 ---- a/ip/link_gre.c -+++ b/ip/link_gre.c -@@ -207,8 +207,11 @@ get_failed: - } else if (!matches(*argv, "dev")) { - NEXT_ARG(); - link = if_nametoindex(*argv); -- if (link == 0) -+ if (link == 0) { -+ fprintf(stderr, "Cannot find device \"%s\"\n", -+ *argv); - exit(-1); -+ } - } else if (!matches(*argv, "ttl") || - !matches(*argv, "hoplimit")) { - unsigned uval; -@@ -233,7 +236,7 @@ get_failed: - tos = uval; - } else - tos = 1; -- } else -+ } else - usage(); - argc--; argv++; - } -diff --git a/ip/link_gre6.c b/ip/link_gre6.c -index 4c9c536..c7183e2 100644 ---- a/ip/link_gre6.c -+++ b/ip/link_gre6.c -@@ -225,8 +225,11 @@ get_failed: - } else if (!matches(*argv, "dev")) { - NEXT_ARG(); - link = if_nametoindex(*argv); -- if (link == 0) -+ if (link == 0) { -+ fprintf(stderr, "Cannot find device \"%s\"\n", -+ *argv); - exit(-1); -+ } - } else if (!matches(*argv, "ttl") || - !matches(*argv, "hoplimit")) { - __u8 uval; -diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c -index b00d8d9..768c4ef 100644 ---- a/ip/link_iptnl.c -+++ b/ip/link_iptnl.c -@@ -212,7 +212,7 @@ get_failed: - } - - if (ttl && pmtudisc == 0) { -- fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n"); -+ fprintf(stderr, "ttl != 0 and nopmtudisc are incompatible\n"); - exit(-1); - } - -diff --git a/ip/link_vti.c b/ip/link_vti.c -index 77a7482..6274c83 100644 ---- a/ip/link_vti.c -+++ b/ip/link_vti.c -@@ -171,8 +171,11 @@ get_failed: - } else if (!matches(*argv, "dev")) { - NEXT_ARG(); - link = if_nametoindex(*argv); -- if (link == 0) -+ if (link == 0) { -+ fprintf(stderr, "Cannot find device \"%s\"\n", -+ *argv); - exit(-1); -+ } - } else - usage(); - argc--; argv++; -diff --git a/ip/tunnel.c b/ip/tunnel.c -index a6a2846..a1a7660 100644 ---- a/ip/tunnel.c -+++ b/ip/tunnel.c -@@ -122,7 +122,7 @@ int tnl_del_ioctl(const char *basedev, const char *name, void *p) - return err; - } - --static int tnl_gen_ioctl(int cmd, const char *name, -+static int tnl_gen_ioctl(int cmd, const char *name, - void *p, int skiperr) - { - struct ifreq ifr; -diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c -index 160ab32..208c49c 100644 ---- a/ip/xfrm_state.c -+++ b/ip/xfrm_state.c -@@ -1193,7 +1193,7 @@ static int print_sadinfo(struct nlmsghdr *n, void *arg) - fprintf(fp,"BAD SAD length returned\n"); - return -1; - } -- -+ - si = RTA_DATA(tb[XFRMA_SAD_HINFO]); - fprintf(fp," (buckets "); - fprintf(fp,"count %d", si->sadhcnt); --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-fq-allow-options-of-fair-queue-set-to-0U.patch b/SOURCES/iproute2-3.10.0-fq-allow-options-of-fair-queue-set-to-0U.patch deleted file mode 100644 index 4e5344c..0000000 --- a/SOURCES/iproute2-3.10.0-fq-allow-options-of-fair-queue-set-to-0U.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 2adc0d473370b683726e2ea019c6d1cc302823ce Mon Sep 17 00:00:00 2001 -From: Yang Yingliang <yangyingliang@huawei.com> -Date: Thu, 29 May 2014 12:04:34 +0800 -Subject: [PATCH 2/2] fq: allow options of fair queue set to ~0U - -Some options of fair queue cannot be (~0U). It leads to maxrate -cannot be reset to unlimited because it cannot be (~0U). Allow -the options being ~0U. - -Tested by the following command: - # tc qdisc add dev eth4 root handle 1: fq limit 2000 flow_limit 200 maxrate 100mbit quantum 2000 initial_quantum 1600 - # tc -s -d qdisc show -qdisc fq 1: dev eth4 root refcnt 2 limit 2000p flow_limit 200p buckets 1024 quantum 2000 initial_quantum 1600 maxrate 100Mbit - Sent 1492 bytes 10 pkt (dropped 0, overlimits 0 requeues 0) - backlog 0b 0p requeues 0 - 1 flows (0 inactive, 0 throttled) - 0 gc, 0 highprio, 0 throttled - - # tc qdisc change dev eth4 root handle 1: fq limit 4294967295 flow_limit 4294967295 maxrate 34359738360 quantum 4294967295 initial_quantum 4294967295 - # tc -s -d qdisc show -qdisc fq 1: dev eth4 root refcnt 2 limit 4294967295p flow_limit 4294967295p buckets 1024 quantum 4294967295 initial_quantum 4294967295 - Sent 38372 bytes 216 pkt (dropped 0, overlimits 0 requeues 0) - backlog 0b 0p requeues 0 - 2 flows (1 inactive, 0 throttled) - 0 gc, 2 highprio, 7 throttled - -Suggested-by: Eric Dumazet <edumazet@google.com> -Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> ---- - tc/q_fq.c | 37 +++++++++++++++++++++++++------------ - 1 file changed, 25 insertions(+), 12 deletions(-) - -diff --git a/tc/q_fq.c b/tc/q_fq.c -index c1f658e..e7288c2 100644 ---- a/tc/q_fq.c -+++ b/tc/q_fq.c -@@ -44,6 +44,7 @@ - #include <netinet/in.h> - #include <arpa/inet.h> - #include <string.h> -+#include <stdbool.h> - - #include "utils.h" - #include "tc_util.h" -@@ -71,13 +72,19 @@ static unsigned int ilog2(unsigned int val) - static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) - { -- unsigned int plimit = ~0U; -- unsigned int flow_plimit = ~0U; -- unsigned int quantum = ~0U; -- unsigned int initial_quantum = ~0U; -+ unsigned int plimit; -+ unsigned int flow_plimit; -+ unsigned int quantum; -+ unsigned int initial_quantum; - unsigned int buckets = 0; -- unsigned int maxrate = ~0U; -- unsigned int defrate = ~0U; -+ unsigned int maxrate; -+ unsigned int defrate; -+ bool set_plimit = false; -+ bool set_flow_plimit = false; -+ bool set_quantum = false; -+ bool set_initial_quantum = false; -+ bool set_maxrate = false; -+ bool set_defrate = false; - int pacing = -1; - struct rtattr *tail; - -@@ -88,12 +95,14 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, - fprintf(stderr, "Illegal \"limit\"\n"); - return -1; - } -+ set_plimit = true; - } else if (strcmp(*argv, "flow_limit") == 0) { - NEXT_ARG(); - if (get_unsigned(&flow_plimit, *argv, 0)) { - fprintf(stderr, "Illegal \"flow_limit\"\n"); - return -1; - } -+ set_flow_plimit = true; - } else if (strcmp(*argv, "buckets") == 0) { - NEXT_ARG(); - if (get_unsigned(&buckets, *argv, 0)) { -@@ -106,24 +115,28 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, - fprintf(stderr, "Illegal \"maxrate\"\n"); - return -1; - } -+ set_maxrate = true; - } else if (strcmp(*argv, "defrate") == 0) { - NEXT_ARG(); - if (get_rate(&defrate, *argv)) { - fprintf(stderr, "Illegal \"defrate\"\n"); - return -1; - } -+ set_defrate = true; - } else if (strcmp(*argv, "quantum") == 0) { - NEXT_ARG(); - if (get_unsigned(&quantum, *argv, 0)) { - fprintf(stderr, "Illegal \"quantum\"\n"); - return -1; - } -+ set_quantum = true; - } else if (strcmp(*argv, "initial_quantum") == 0) { - NEXT_ARG(); - if (get_unsigned(&initial_quantum, *argv, 0)) { - fprintf(stderr, "Illegal \"initial_quantum\"\n"); - return -1; - } -+ set_initial_quantum = true; - } else if (strcmp(*argv, "pacing") == 0) { - pacing = 1; - } else if (strcmp(*argv, "nopacing") == 0) { -@@ -147,24 +160,24 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, - addattr_l(n, 1024, TCA_FQ_BUCKETS_LOG, - &log, sizeof(log)); - } -- if (plimit != ~0U) -+ if (set_plimit) - addattr_l(n, 1024, TCA_FQ_PLIMIT, - &plimit, sizeof(plimit)); -- if (flow_plimit != ~0U) -+ if (set_flow_plimit) - addattr_l(n, 1024, TCA_FQ_FLOW_PLIMIT, - &flow_plimit, sizeof(flow_plimit)); -- if (quantum != ~0U) -+ if (set_quantum) - addattr_l(n, 1024, TCA_FQ_QUANTUM, &quantum, sizeof(quantum)); -- if (initial_quantum != ~0U) -+ if (set_initial_quantum) - addattr_l(n, 1024, TCA_FQ_INITIAL_QUANTUM, - &initial_quantum, sizeof(initial_quantum)); - if (pacing != -1) - addattr_l(n, 1024, TCA_FQ_RATE_ENABLE, - &pacing, sizeof(pacing)); -- if (maxrate != ~0U) -+ if (set_maxrate) - addattr_l(n, 1024, TCA_FQ_FLOW_MAX_RATE, - &maxrate, sizeof(maxrate)); -- if (defrate != ~0U) -+ if (set_defrate) - addattr_l(n, 1024, TCA_FQ_FLOW_DEFAULT_RATE, - &defrate, sizeof(defrate)); - tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-ip-link-fix-and-extend-documentation.patch b/SOURCES/iproute2-3.10.0-ip-link-fix-and-extend-documentation.patch deleted file mode 100644 index 5b9bb39..0000000 --- a/SOURCES/iproute2-3.10.0-ip-link-fix-and-extend-documentation.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 8951dc99dc6a881e95420d0591bcb374f0c373d7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20=C5=A0imerda?= <psimerda@redhat.com> -Date: Wed, 12 Aug 2015 22:04:07 +0200 -Subject: [PATCH] ip-link: fix and extend documentation - - * Add `can` to list of supported link types - * Document `addrgenmode` - * Document `link-netnsid` - * Document VLAN link type - * Improve VXLAN link type documentation - - Fix VXLAN srcport/dstport docs - - Document `udpcsum`, `udp6zerocsumtx` and `udp6zerocsumrx` ---- - man/man8/ip-link.8.in | 96 +++++++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 93 insertions(+), 3 deletions(-) - -diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in -index 844127d..a45bc05 100644 ---- a/man/man8/ip-link.8.in -+++ b/man/man8/ip-link.8.in -@@ -126,6 +126,8 @@ ip-link \- network device configuration - .B nomaster " |" - .br - .B addrgenmode { eui64 | none } -+.br -+.B link-netnsid ID - .BR " }" - - -@@ -259,6 +261,66 @@ the following additional arguments are supported: - .in -8 - - .TP -+VLAN Type Support -+For a link of type -+.I VLAN -+the following additional arguments are supported: -+ -+.BI "ip link add -+.BI link " DEVICE " -+.BI name " NAME " -+.BI type " vlan " -+.R " [ " -+.BI protocol " VLAN_PROTO " -+.R " ] " -+.BI id " VLANID " -+.R " [ " -+.BR reorder_hdr " { " on " | " off " } " -+.R " ] " -+.R " [ " -+.BR gvrp " { " on " | " off " } " -+.R " ] " -+.R " [ " -+.BR mvrp " { " on " | " off " } " -+.R " ] " -+.R " [ " -+.BR loose_binding " { " on " | " off " } " -+.R " ] " -+.R " [ " -+.BI ingress-qos-map " QOS-MAP " -+.R " ] " -+.R " [ " -+.BI egress-qos-map " QOS-MAP " -+.R " ] " -+ -+.in +8 -+.sp -+.BI protocol " VLAN_PROTO " -+- either 802.1Q or 802.1ad. -+ -+.BI id " VLANID " -+- specifies the VLAN Identifer to use. Note that numbers with a leading " 0 " or " 0x " are interpreted as octal or hexadeimal, respectively. -+ -+.BR reorder_hdr " { " on " | " off " } " -+- specifies whether ethernet headers are reordered or not. -+ -+.BR gvrp " { " on " | " off " } " -+- specifies whether this VLAN should be registered using GARP VLAN Registration Protocol. -+ -+.BR mvrp " { " on " | " off " } " -+- specifies whether this VLAN should be registered using Multiple VLAN Registration Protocol. -+ -+.BR loose_binding " { " on " | " off " } " -+- specifies whether the VLAN device state is bound to the physical device state. -+ -+.BI ingress-qos-map " QOS-MAP " -+- defines a mapping between priority code points on incoming frames. The format is FROM:TO with multiple mappings separated by spaces. -+ -+.BI egress-qos-map " QOS-MAP " -+- the same as ingress-qos-map but for outgoing frames. -+.in -8 -+ -+.TP - VXLAN Type Support - For a link of type - .I VXLAN -@@ -277,7 +339,9 @@ the following additional arguments are supported: - .R " ] [ " - .BI tos " TOS " - .R " ] [ " --.BI port " MIN MAX " -+.BI dstport " PORT " -+.R " ] [ " -+.BI srcport " MIN MAX " - .R " ] [ " - .I "[no]learning " - .R " ] [ " -@@ -289,6 +353,12 @@ the following additional arguments are supported: - .R " ] [ " - .I "[no]l3miss " - .R " ] [ " -+.I "[no]udpcsum " -+.R " ] [ " -+.I "[no]udp6zerocsumtx " -+.R " ] [ " -+.I "[no]udp6zerocsumrx " -+.R " ] [ " - .B gbp - .R " ]" - -@@ -329,7 +399,11 @@ parameter. - - specifies the TOS value to use in outgoing packets. - - .sp --.BI port " MIN MAX" -+.BI dstport " PORT" -+- specifies the UDP destination port to communicate to the remote VXLAN tunnel endpoint. -+ -+.sp -+.BI srcport " MIN MAX" - - specifies the range of port numbers to use as UDP - source ports to communicate to the remote VXLAN tunnel endpoint. - -@@ -355,6 +429,18 @@ are entered into the VXLAN device forwarding database. - - specifies if netlink IP ADDR miss notifications are generated. - - .sp -+.I [no]udpcsum -+- specifies if UDP checksum is filled in -+ -+.sp -+.I [no]udp6zerocsumtx -+- specifies if UDP checksum is filled in -+ -+.sp -+.I [no]udp6zerocsumrx -+- specifies if UDP checksum is received -+ -+.sp - .B gbp - - enables the Group Policy extension (VXLAN-GBP). - -@@ -577,7 +663,11 @@ unset master device of the device (release device). - - .TP - .BR "addrgenmode eui64 " or " addrgenmode none" --allow to ipv6 set address generation mode -+set IPv6 address generation mode -+ -+.TP -+.BR "link-netnsid " -+set peer netnsid for a cross-netns interface - - .PP - .B Warning: --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-ip-link-fix-minor-typo-in-manpage.patch b/SOURCES/iproute2-3.10.0-ip-link-fix-minor-typo-in-manpage.patch deleted file mode 100644 index 53166c4..0000000 --- a/SOURCES/iproute2-3.10.0-ip-link-fix-minor-typo-in-manpage.patch +++ /dev/null @@ -1,28 +0,0 @@ -From e9693b8ac04691c603a6ccbe3f5fb996fd804eb9 Mon Sep 17 00:00:00 2001 -From: Phil Sutter <phil@nwl.cc> -Date: Tue, 11 Aug 2015 19:14:11 +0200 -Subject: [PATCH] ip-link: fix minor typo in manpage - -Change '-human-readble' to '-human-readable'. - -Signed-off-by: Phil Sutter <phil@nwl.cc> ---- - man/man8/ip-link.8.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in -index a015b82..844127d 100644 ---- a/man/man8/ip-link.8.in -+++ b/man/man8/ip-link.8.in -@@ -621,7 +621,7 @@ output more statistics about packet usage. - output more detailed information. - - .TP --.BR "\-h", " \-human", " \-human-readble" -+.BR "\-h", " \-human", " \-human-readable" - output statistics with human readable values number followed by suffix - - .TP --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-ip-rule.patch b/SOURCES/iproute2-3.10.0-ip-rule.patch deleted file mode 100644 index d86597a..0000000 --- a/SOURCES/iproute2-3.10.0-ip-rule.patch +++ /dev/null @@ -1,35 +0,0 @@ -diff --git a/man/man8/ip-rule.8 b/man/man8/ip-rule.8 -index dd925be..0c45a6f 100644 ---- a/man/man8/ip-rule.8 -+++ b/man/man8/ip-rule.8 -@@ -108,8 +108,6 @@ The - .B local - table is a special routing table containing - high priority control routes for local and broadcast addresses. --.sp --Rule 0 is special. It cannot be deleted or overridden. - - .TP - 2. ---- iproute2-3.10.0/man/man8/ip-rule.8.orig 2015-07-08 18:04:55.918190531 +0200 -+++ iproute2-3.10.0/man/man8/ip-rule.8 2015-07-08 18:05:46.778190024 +0200 -@@ -41,7 +41,7 @@ - .IR TABLE_ID " ] [ " - .B nat - .IR ADDRESS " ] [ " --.BR prohibit " | " reject " | " unreachable " ] [ " realms -+.BR prohibit " | " unreachable " ] [ " realms - .RI "[" SRCREALM "/]" DSTREALM " ]" - - .ti -8 ---- iproute2-3.10.0/ip/iprule.c.orig 2015-07-08 18:07:17.018189125 +0200 -+++ iproute2-3.10.0/ip/iprule.c 2015-07-08 18:07:32.448188972 +0200 -@@ -36,7 +36,7 @@ - fprintf(stderr, "SELECTOR := [ not ] [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK[/MASK] ]\n"); - fprintf(stderr, " [ iif STRING ] [ oif STRING ] [ pref NUMBER ]\n"); - fprintf(stderr, "ACTION := [ table TABLE_ID ]\n"); -- fprintf(stderr, " [ prohibit | reject | unreachable ]\n"); -+ fprintf(stderr, " [ prohibit | unreachable ]\n"); - fprintf(stderr, " [ realms [SRCREALM/]DSTREALM ]\n"); - fprintf(stderr, " [ goto NUMBER ]\n"); - fprintf(stderr, "TABLE_ID := [ local | main | default | NUMBER ]\n"); diff --git a/SOURCES/iproute2-3.10.0-ip-xfrm-monitor-allows-to-monitor-in-several-netns.patch b/SOURCES/iproute2-3.10.0-ip-xfrm-monitor-allows-to-monitor-in-several-netns.patch deleted file mode 100644 index 885397a..0000000 --- a/SOURCES/iproute2-3.10.0-ip-xfrm-monitor-allows-to-monitor-in-several-netns.patch +++ /dev/null @@ -1,834 +0,0 @@ -From 3873ff54417f7e514197d069bcad187ca2ec3b86 Mon Sep 17 00:00:00 2001 -From: Phil Sutter <psutter@redhat.com> -Date: Mon, 10 Aug 2015 17:26:16 +0200 -Subject: [PATCH] {ip,xfrm}monitor: allows to monitor in several netns - -This is a combination of six commits: - -commit c1f4d1640efa2ba2219861852b351d5c369c3715 -Author: Phil Sutter <psutter@redhat.com> -Date: Mon Aug 10 17:26:16 2015 +0200 - - include/linux/netlink.h: add NETLINK_LISTEN_ALL_NSID - - This is a selective backport for the following patches and will be replaced by - full linux header update backports soon. - -commit 2503247d58c36f9197144790455626bae105342a -Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> -Date: Wed May 20 16:19:57 2015 +0200 - - man: update ip monitor page - - Add label option. - - Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> - -commit 0628cddd9d5c0cb9ed0e0aba136e50de93487150 -Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> -Date: Wed May 20 16:19:58 2015 +0200 - - libnetlink: introduce rtnl_listen_filter_t - - There is no functional change with this commit. It only prepares the next one. - - Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> - -commit 3b0006f8183e09eda5f2f11667f2b9d36fcd8c16 -Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> -Date: Wed May 20 16:19:59 2015 +0200 - - ipmonitor: introduce print_headers - - The goal of this patch is to avoid code duplication. - - Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> - -commit 449b824ad19679f66164e1e97513f36eee0d004e -Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> -Date: Wed May 20 16:20:00 2015 +0200 - - ipmonitor: allows to monitor in several netns - - With this patch, it's now possible to listen in all netns that have an nsid - assigned into the netns where the socket is opened. - - Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> - -commit b6ec53e3008aaf2acc3db146e24bc9a365e4b6c2 -Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> -Date: Wed May 20 16:20:01 2015 +0200 - - xfrmmonitor: allows to monitor in several netns - - With this patch, it's now possible to listen in all netns that have an nsid - assigned into the netns where is socket is opened. - - Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> - -There were multiple conflicts to resolve due to the following missing commits: -- c16298b ip xfrm mon: Add objects list to the usage output -- 2271779 ip monitor: Dont print timestamp or banner-label for cloned routes -- 0018565 add ability to filter neighbour discovery by protocol -- 488c41d ip: Add label option to ip monitor -- e557212 netlink: extend buffers to 16K -- 093b764 ip monitor: Allow to filter events by dev ---- - bridge/monitor.c | 1 + - genl/ctrl.c | 17 ++++++++++----- - include/libnetlink.h | 15 +++++++++++-- - include/linux/netlink.h | 1 + - ip/ip_common.h | 1 + - ip/ipaddress.c | 8 +++++-- - ip/iplink.c | 1 + - ip/ipmonitor.c | 58 ++++++++++++++++++++++++++++++------------------- - ip/ipnetconf.c | 11 ++++++++-- - ip/ipnetns.c | 1 + - ip/iproute.c | 9 +++++--- - ip/rtmon.c | 12 +++++++--- - ip/xfrm_monitor.c | 15 ++++++++++++- - lib/libnetlink.c | 49 +++++++++++++++++++++++++++++++++++++---- - man/man3/libnetlink.3 | 7 +++--- - man/man8/ip-monitor.8 | 36 ++++++++++++++++++++++++++++++ - man/man8/ip-xfrm.8 | 21 +++++++++++++++++- - tc/tc_monitor.c | 1 + - 18 files changed, 216 insertions(+), 48 deletions(-) - -diff --git a/bridge/monitor.c b/bridge/monitor.c -index 76e7d47..82cdff0 100644 ---- a/bridge/monitor.c -+++ b/bridge/monitor.c -@@ -47,6 +47,7 @@ static int show_mark(FILE *fp, const struct nlmsghdr *n) - } - - static int accept_msg(const struct sockaddr_nl *who, -+ struct rtnl_ctrl_data *ctrl, - struct nlmsghdr *n, void *arg) - { - FILE *fp = arg; -diff --git a/genl/ctrl.c b/genl/ctrl.c -index 7c42578..48cbc35 100644 ---- a/genl/ctrl.c -+++ b/genl/ctrl.c -@@ -177,8 +177,9 @@ static int print_ctrl_grp(FILE *fp, struct rtattr *arg, __u32 ctrl_ver) - /* - * The controller sends one nlmsg per family - */ --static int print_ctrl(const struct sockaddr_nl *who, struct nlmsghdr *n, -- void *arg) -+static int print_ctrl(const struct sockaddr_nl *who, -+ struct rtnl_ctrl_data *ctrl, -+ struct nlmsghdr *n, void *arg) - { - struct rtattr *tb[CTRL_ATTR_MAX + 1]; - struct genlmsghdr *ghdr = NLMSG_DATA(n); -@@ -281,6 +282,12 @@ static int print_ctrl(const struct sockaddr_nl *who, struct nlmsghdr *n, - return 0; - } - -+static int print_ctrl2(const struct sockaddr_nl *who, -+ struct nlmsghdr *n, void *arg) -+{ -+ return print_ctrl(who, NULL, n, arg); -+} -+ - static int ctrl_list(int cmd, int argc, char **argv) - { - struct rtnl_handle rth; -@@ -339,7 +346,7 @@ static int ctrl_list(int cmd, int argc, char **argv) - goto ctrl_done; - } - -- if (print_ctrl(NULL, nlh, (void *) stdout) < 0) { -+ if (print_ctrl2(NULL, nlh, (void *) stdout) < 0) { - fprintf(stderr, "Dump terminated\n"); - goto ctrl_done; - } -@@ -355,7 +362,7 @@ static int ctrl_list(int cmd, int argc, char **argv) - goto ctrl_done; - } - -- rtnl_dump_filter(&rth, print_ctrl, stdout); -+ rtnl_dump_filter(&rth, print_ctrl2, stdout); - - } - -@@ -408,5 +415,5 @@ static int parse_ctrl(struct genl_util *a, int argc, char **argv) - struct genl_util ctrl_genl_util = { - .name = "ctrl", - .parse_genlopt = parse_ctrl, -- .print_genlopt = print_ctrl, -+ .print_genlopt = print_ctrl2, - }; -diff --git a/include/libnetlink.h b/include/libnetlink.h -index 5dcc0c3..ae93336 100644 ---- a/include/libnetlink.h -+++ b/include/libnetlink.h -@@ -19,6 +19,8 @@ struct rtnl_handle - __u32 seq; - __u32 dump; - FILE *dump_fp; -+#define RTNL_HANDLE_F_LISTEN_ALL_NSID 0x01 -+ int flags; - }; - - extern int rcvbuf; -@@ -31,9 +33,17 @@ extern int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int fam, int type, - __u32 filt_mask); - extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len); - -+struct rtnl_ctrl_data { -+ int nsid; -+}; -+ - typedef int (*rtnl_filter_t)(const struct sockaddr_nl *, - struct nlmsghdr *n, void *); - -+typedef int (*rtnl_listen_filter_t)(const struct sockaddr_nl *, -+ struct rtnl_ctrl_data *, -+ struct nlmsghdr *n, void *); -+ - struct rtnl_dump_filter_arg - { - rtnl_filter_t filter; -@@ -105,9 +115,10 @@ static inline const char *rta_getattr_str(const struct rtattr *rta) - return (const char *)RTA_DATA(rta); - } - --extern int rtnl_listen(struct rtnl_handle *, rtnl_filter_t handler, -+extern int rtnl_listen_all_nsid(struct rtnl_handle *); -+extern int rtnl_listen(struct rtnl_handle *, rtnl_listen_filter_t handler, - void *jarg); --extern int rtnl_from_file(FILE *, rtnl_filter_t handler, -+extern int rtnl_from_file(FILE *, rtnl_listen_filter_t handler, - void *jarg); - - #define NLMSG_TAIL(nmsg) \ -diff --git a/include/linux/netlink.h b/include/linux/netlink.h -index e0a09df..0c89ddd 100644 ---- a/include/linux/netlink.h -+++ b/include/linux/netlink.h -@@ -108,6 +108,7 @@ struct nlmsgerr { - #define NETLINK_NO_ENOBUFS 5 - #define NETLINK_RX_RING 6 - #define NETLINK_TX_RING 7 -+#define NETLINK_LISTEN_ALL_NSID 8 - - struct nl_pktinfo { - __u32 group; -diff --git a/ip/ip_common.h b/ip/ip_common.h -index 85529f0..bd36924 100644 ---- a/ip/ip_common.h -+++ b/ip/ip_common.h -@@ -29,6 +29,7 @@ extern int print_prefix(const struct sockaddr_nl *who, - extern int print_rule(const struct sockaddr_nl *who, - struct nlmsghdr *n, void *arg); - extern int print_netconf(const struct sockaddr_nl *who, -+ struct rtnl_ctrl_data *ctrl, - struct nlmsghdr *n, void *arg); - extern void netns_map_init(void); - extern int print_nsid(const struct sockaddr_nl *who, -diff --git a/ip/ipaddress.c b/ip/ipaddress.c -index 4650a2e..30fda4f 100644 ---- a/ip/ipaddress.c -+++ b/ip/ipaddress.c -@@ -1007,7 +1007,9 @@ static int save_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, - return ret == n->nlmsg_len ? 0 : ret; - } - --static int show_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg) -+static int show_handler(const struct sockaddr_nl *nl, -+ struct rtnl_ctrl_data *ctrl, -+ struct nlmsghdr *n, void *arg) - { - struct ifaddrmsg *ifa = NLMSG_DATA(n); - -@@ -1024,7 +1026,9 @@ static int ipaddr_showdump(void) - exit(rtnl_from_file(stdin, &show_handler, NULL)); - } - --static int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg) -+static int restore_handler(const struct sockaddr_nl *nl, -+ struct rtnl_ctrl_data *ctrl, -+ struct nlmsghdr *n, void *arg) - { - int ret; - -diff --git a/ip/iplink.c b/ip/iplink.c -index e47cbdd..86ea23e 100644 ---- a/ip/iplink.c -+++ b/ip/iplink.c -@@ -163,6 +163,7 @@ static int get_addr_gen_mode(const char *mode) - static int have_rtnl_newlink = -1; - - static int accept_msg(const struct sockaddr_nl *who, -+ struct rtnl_ctrl_data *ctrl, - struct nlmsghdr *n, void *arg) - { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n); -diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c -index 148cf1e..131b6ac 100644 ---- a/ip/ipmonitor.c -+++ b/ip/ipmonitor.c -@@ -26,18 +26,36 @@ - - static void usage(void) __attribute__((noreturn)); - int prefix_banner; -+int listen_all_nsid; - - static void usage(void) - { -- fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ]\n"); -+ fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ] " -+ "[all-nsid] [dev DEVICE]\n"); - fprintf(stderr, "LISTofOBJECTS := link | address | route | mroute | prefix |\n"); - fprintf(stderr, " neigh | netconf | nsid\n"); - fprintf(stderr, "FILE := file FILENAME\n"); - exit(-1); - } - -+static void print_headers(FILE *fp, char *label, struct rtnl_ctrl_data *ctrl) -+{ -+ if (timestamp) -+ print_timestamp(fp); -+ -+ if (listen_all_nsid) { -+ if (ctrl == NULL || ctrl->nsid < 0) -+ fprintf(fp, "[nsid current]"); -+ else -+ fprintf(fp, "[nsid %d]", ctrl->nsid); -+ } -+ -+ if (prefix_banner) -+ fprintf(fp, "%s", label); -+} - - static int accept_msg(const struct sockaddr_nl *who, -+ struct rtnl_ctrl_data *ctrl, - struct nlmsghdr *n, void *arg) - { - FILE *fp = (FILE*)arg; -@@ -56,59 +74,51 @@ static int accept_msg(const struct sockaddr_nl *who, - - if (r->rtm_family == RTNL_FAMILY_IPMR || - r->rtm_family == RTNL_FAMILY_IP6MR) { -- if (prefix_banner) -- fprintf(fp, "[MROUTE]"); -+ print_headers(fp, "[MROUTE]", ctrl); - print_mroute(who, n, arg); - return 0; - } else { -- if (prefix_banner) -- fprintf(fp, "[ROUTE]"); -+ print_headers(fp, "[ROUTE]", ctrl); - print_route(who, n, arg); - return 0; - } - } -+ - if (n->nlmsg_type == RTM_NEWLINK || n->nlmsg_type == RTM_DELLINK) { - ll_remember_index(who, n, NULL); -- if (prefix_banner) -- fprintf(fp, "[LINK]"); -+ print_headers(fp, "[LINK]", ctrl); - print_linkinfo(who, n, arg); - return 0; - } - if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) { -- if (prefix_banner) -- fprintf(fp, "[ADDR]"); -+ print_headers(fp, "[ADDR]", ctrl); - print_addrinfo(who, n, arg); - return 0; - } - if (n->nlmsg_type == RTM_NEWADDRLABEL || n->nlmsg_type == RTM_DELADDRLABEL) { -- if (prefix_banner) -- fprintf(fp, "[ADDRLABEL]"); -+ print_headers(fp, "[ADDRLABEL]", ctrl); - print_addrlabel(who, n, arg); - return 0; - } - if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH || - n->nlmsg_type == RTM_GETNEIGH) { -- if (prefix_banner) -- fprintf(fp, "[NEIGH]"); -+ print_headers(fp, "[NEIGH]", ctrl); - print_neigh(who, n, arg); - return 0; - } - if (n->nlmsg_type == RTM_NEWPREFIX) { -- if (prefix_banner) -- fprintf(fp, "[PREFIX]"); -+ print_headers(fp, "[PREFIX]", ctrl); - print_prefix(who, n, arg); - return 0; - } - if (n->nlmsg_type == RTM_NEWRULE || n->nlmsg_type == RTM_DELRULE) { -- if (prefix_banner) -- fprintf(fp, "[RULE]"); -+ print_headers(fp, "[RULE]", ctrl); - print_rule(who, n, arg); - return 0; - } - if (n->nlmsg_type == RTM_NEWNETCONF) { -- if (prefix_banner) -- fprintf(fp, "[NETCONF]"); -- print_netconf(who, n, arg); -+ print_headers(fp, "[NETCONF]", ctrl); -+ print_netconf(who, ctrl, n, arg); - return 0; - } - if (n->nlmsg_type == 15) { -@@ -128,8 +138,7 @@ static int accept_msg(const struct sockaddr_nl *who, - n->nlmsg_type == RTM_DELTFILTER) - return 0; - if (n->nlmsg_type == RTM_NEWNSID || n->nlmsg_type == RTM_DELNSID) { -- if (prefix_banner) -- fprintf(fp, "[NSID]"); -+ print_headers(fp, "[NSID]", ctrl); - print_nsid(who, n, arg); - return 0; - } -@@ -166,6 +175,8 @@ int do_ipmonitor(int argc, char **argv) - if (matches(*argv, "file") == 0) { - NEXT_ARG(); - file = *argv; -+ } else if (matches(*argv, "all-nsid") == 0) { -+ listen_all_nsid = 1; - } else if (matches(*argv, "link") == 0) { - llink=1; - groups = 0; -@@ -250,6 +261,9 @@ int do_ipmonitor(int argc, char **argv) - - if (rtnl_open(&rth, groups) < 0) - exit(1); -+ if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0) -+ exit(1); -+ - ll_init_map(&rth); - netns_map_init(); - -diff --git a/ip/ipnetconf.c b/ip/ipnetconf.c -index 9a77ecb..8e42132 100644 ---- a/ip/ipnetconf.c -+++ b/ip/ipnetconf.c -@@ -40,7 +40,8 @@ static void usage(void) - - #define NETCONF_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct netconfmsg)))) - --int print_netconf(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) -+int print_netconf(const struct sockaddr_nl *who, struct rtnl_ctrl_data *ctrl, -+ struct nlmsghdr *n, void *arg) - { - FILE *fp = (FILE*)arg; - struct netconfmsg *ncm = NLMSG_DATA(n); -@@ -119,6 +120,12 @@ int print_netconf(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) - return 0; - } - -+static int print_netconf2(const struct sockaddr_nl *who, -+ struct nlmsghdr *n, void *arg) -+{ -+ return print_netconf(who, NULL, n, arg); -+} -+ - static void ipnetconf_reset_filter(void) - { - memset(&filter, 0, sizeof(filter)); -@@ -169,7 +176,7 @@ dump: - perror("Cannot send dump request"); - exit(1); - } -- if (rtnl_dump_filter(&rth, print_netconf, stdout) < 0) { -+ if (rtnl_dump_filter(&rth, print_netconf2, stdout) < 0) { - fprintf(stderr, "Dump terminated\n"); - exit(1); - } -diff --git a/ip/ipnetns.c b/ip/ipnetns.c -index 438d59b..019f954 100644 ---- a/ip/ipnetns.c -+++ b/ip/ipnetns.c -@@ -43,6 +43,7 @@ static struct rtnl_handle rtnsh = { .fd = -1 }; - static int have_rtnl_getnsid = -1; - - static int ipnetns_accept_msg(const struct sockaddr_nl *who, -+ struct rtnl_ctrl_data *ctrl, - struct nlmsghdr *n, void *arg) - { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n); -diff --git a/ip/iproute.c b/ip/iproute.c -index 207301c..20980ab 100644 ---- a/ip/iproute.c -+++ b/ip/iproute.c -@@ -1539,8 +1539,9 @@ static int iproute_get(int argc, char **argv) - exit(0); - } - --static int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, -- void *arg) -+static int restore_handler(const struct sockaddr_nl *nl, -+ struct rtnl_ctrl_data *ctrl, -+ struct nlmsghdr *n, void *arg) - { - int ret; - -@@ -1582,7 +1583,9 @@ static int iproute_restore(void) - exit(rtnl_from_file(stdin, &restore_handler, NULL)); - } - --static int show_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg) -+static int show_handler(const struct sockaddr_nl *nl, -+ struct rtnl_ctrl_data *ctrl, -+ struct nlmsghdr *n, void *arg) - { - print_route(nl, n, stdout); - return 0; -diff --git a/ip/rtmon.c b/ip/rtmon.c -index 9227eac..5094d22 100644 ---- a/ip/rtmon.c -+++ b/ip/rtmon.c -@@ -45,8 +45,8 @@ static void write_stamp(FILE *fp) - fwrite((void*)n1, 1, NLMSG_ALIGN(n1->nlmsg_len), fp); - } - --static int dump_msg(const struct sockaddr_nl *who, struct nlmsghdr *n, -- void *arg) -+static int dump_msg(const struct sockaddr_nl *who, struct rtnl_ctrl_data *ctrl, -+ struct nlmsghdr *n, void *arg) - { - FILE *fp = (FILE*)arg; - if (!init_phase) -@@ -56,6 +56,12 @@ static int dump_msg(const struct sockaddr_nl *who, struct nlmsghdr *n, - return 0; - } - -+static int dump_msg2(const struct sockaddr_nl *who, -+ struct nlmsghdr *n, void *arg) -+{ -+ return dump_msg(who, NULL, n, arg); -+} -+ - static void usage(void) - { - fprintf(stderr, "Usage: rtmon file FILE [ all | LISTofOBJECTS]\n"); -@@ -163,7 +169,7 @@ main(int argc, char **argv) - - write_stamp(fp); - -- if (rtnl_dump_filter(&rth, dump_msg, fp) < 0) { -+ if (rtnl_dump_filter(&rth, dump_msg2, fp) < 0) { - fprintf(stderr, "Dump terminated\n"); - return 1; - } -diff --git a/ip/xfrm_monitor.c b/ip/xfrm_monitor.c -index 292193e..228aaf2 100644 ---- a/ip/xfrm_monitor.c -+++ b/ip/xfrm_monitor.c -@@ -36,10 +36,11 @@ - #include "ip_common.h" - - static void usage(void) __attribute__((noreturn)); -+int listen_all_nsid; - - static void usage(void) - { -- fprintf(stderr, "Usage: ip xfrm monitor [ all | LISTofXFRM-OBJECTS ]\n"); -+ fprintf(stderr, "Usage: ip xfrm monitor [all-nsid] [ all | LISTofXFRM-OBJECTS ]\n"); - exit(-1); - } - -@@ -291,6 +292,7 @@ static int xfrm_mapping_print(const struct sockaddr_nl *who, - } - - static int xfrm_accept_msg(const struct sockaddr_nl *who, -+ struct rtnl_ctrl_data *ctrl, - struct nlmsghdr *n, void *arg) - { - FILE *fp = (FILE*)arg; -@@ -298,6 +300,13 @@ static int xfrm_accept_msg(const struct sockaddr_nl *who, - if (timestamp) - print_timestamp(fp); - -+ if (listen_all_nsid) { -+ if (ctrl == NULL || ctrl->nsid < 0) -+ fprintf(fp, "[nsid current]"); -+ else -+ fprintf(fp, "[nsid %d]", ctrl->nsid); -+ } -+ - switch (n->nlmsg_type) { - case XFRM_MSG_NEWSA: - case XFRM_MSG_DELSA: -@@ -360,6 +369,8 @@ int do_xfrm_monitor(int argc, char **argv) - if (matches(*argv, "file") == 0) { - NEXT_ARG(); - file = *argv; -+ } else if (matches(*argv, "all-nsid") == 0) { -+ listen_all_nsid = 1; - } else if (matches(*argv, "acquire") == 0) { - lacquire=1; - groups = 0; -@@ -412,6 +423,8 @@ int do_xfrm_monitor(int argc, char **argv) - - if (rtnl_open_byproto(&rth, groups, NETLINK_XFRM) < 0) - exit(1); -+ if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0) -+ exit(1); - - if (rtnl_listen(&rth, xfrm_accept_msg, (void*)stdout) < 0) - exit(2); -diff --git a/lib/libnetlink.c b/lib/libnetlink.c -index baac6ae..0a989f4 100644 ---- a/lib/libnetlink.c -+++ b/lib/libnetlink.c -@@ -25,6 +25,10 @@ - - #include "libnetlink.h" - -+#ifndef SOL_NETLINK -+#define SOL_NETLINK 270 -+#endif -+ - int rcvbuf = 1024 * 1024; - - void rtnl_close(struct rtnl_handle *rth) -@@ -406,8 +410,21 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, - } - } - -+int rtnl_listen_all_nsid(struct rtnl_handle *rth) -+{ -+ unsigned int on = 1; -+ -+ if (setsockopt(rth->fd, SOL_NETLINK, NETLINK_LISTEN_ALL_NSID, &on, -+ sizeof(on)) < 0) { -+ perror("NETLINK_LISTEN_ALL_NSID"); -+ return -1; -+ } -+ rth->flags |= RTNL_HANDLE_F_LISTEN_ALL_NSID; -+ return 0; -+} -+ - int rtnl_listen(struct rtnl_handle *rtnl, -- rtnl_filter_t handler, -+ rtnl_listen_filter_t handler, - void *jarg) - { - int status; -@@ -421,6 +438,12 @@ int rtnl_listen(struct rtnl_handle *rtnl, - .msg_iovlen = 1, - }; - char buf[8192]; -+ char cmsgbuf[BUFSIZ]; -+ -+ if (rtnl->flags & RTNL_HANDLE_F_LISTEN_ALL_NSID) { -+ msg.msg_control = &cmsgbuf; -+ msg.msg_controllen = sizeof(cmsgbuf); -+ } - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; -@@ -429,6 +452,9 @@ int rtnl_listen(struct rtnl_handle *rtnl, - - iov.iov_base = buf; - while (1) { -+ struct rtnl_ctrl_data ctrl; -+ struct cmsghdr *cmsg; -+ - iov.iov_len = sizeof(buf); - status = recvmsg(rtnl->fd, &msg, 0); - -@@ -449,6 +475,21 @@ int rtnl_listen(struct rtnl_handle *rtnl, - fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen); - exit(1); - } -+ -+ if (rtnl->flags & RTNL_HANDLE_F_LISTEN_ALL_NSID) { -+ memset(&ctrl, 0, sizeof(ctrl)); -+ ctrl.nsid = -1; -+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; -+ cmsg = CMSG_NXTHDR(&msg, cmsg)) -+ if (cmsg->cmsg_level == SOL_NETLINK && -+ cmsg->cmsg_type == NETLINK_LISTEN_ALL_NSID && -+ cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { -+ int *data = (int *)CMSG_DATA(cmsg); -+ -+ ctrl.nsid = *data; -+ } -+ } -+ - for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { - int err; - int len = h->nlmsg_len; -@@ -463,7 +504,7 @@ int rtnl_listen(struct rtnl_handle *rtnl, - exit(1); - } - -- err = handler(&nladdr, h, jarg); -+ err = handler(&nladdr, &ctrl, h, jarg); - if (err < 0) - return err; - -@@ -481,7 +522,7 @@ int rtnl_listen(struct rtnl_handle *rtnl, - } - } - --int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler, -+int rtnl_from_file(FILE *rtnl, rtnl_listen_filter_t handler, - void *jarg) - { - int status; -@@ -529,7 +570,7 @@ int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler, - return -1; - } - -- err = handler(&nladdr, h, jarg); -+ err = handler(&nladdr, NULL, h, jarg); - if (err < 0) - return err; - } -diff --git a/man/man3/libnetlink.3 b/man/man3/libnetlink.3 -index e999bd6..99be9cc 100644 ---- a/man/man3/libnetlink.3 -+++ b/man/man3/libnetlink.3 -@@ -33,7 +33,8 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, - void *jarg) - .sp - int rtnl_listen(struct rtnl_handle *rtnl, -- int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *), -+ int (*handler)(struct sockaddr_nl *, struct rtnl_ctrl_data *, -+ struct nlmsghdr *n, void *), - void *jarg) - .sp - int rtnl_from_file(FILE *rtnl, -@@ -108,8 +109,8 @@ rtnl_listen - Receive netlink data after a request and pass it to - .I handler. - .B handler --is a callback that gets the message source address, the message itself, --and the -+is a callback that gets the message source address, anscillary data, the message -+itself, and the - .B jarg - cookie as arguments. It will get called for all received messages. - Only one message bundle is received. If there is a message -diff --git a/man/man8/ip-monitor.8 b/man/man8/ip-monitor.8 -index a710b34..91099f8 100644 ---- a/man/man8/ip-monitor.8 -+++ b/man/man8/ip-monitor.8 -@@ -11,6 +11,10 @@ ip-monitor, rtmon \- state monitoring - .BR "monitor" " [ " all " |" - .IR OBJECT-LIST " ] [" - .BI file " FILENAME " -+] [ -+.BI label -+] [ -+.BI all-nsid - ] - .sp - -@@ -26,6 +30,10 @@ command is the first in the command line and then the object list follows: - .BR "ip monitor" " [ " all " |" - .IR OBJECT-LIST " ] [" - .BI file " FILENAME " -+] [ -+.BI label -+] [ -+.BI all-nsid - ] - - .I OBJECT-LIST -@@ -42,6 +50,32 @@ described in previous sections. - - .P - If the -+.BI label -+option is set, a prefix is displayed before each message to -+show the family of the message. For example: -+.sp -+.in +2 -+[NEIGH]10.16.0.112 dev eth0 lladdr 00:04:23:df:2f:d0 REACHABLE -+[LINK]3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN group default -+ link/ether 52:54:00:12:34:57 brd ff:ff:ff:ff:ff:ff -+.in -2 -+.sp -+ -+.P -+If the -+.BI all-nsid -+option is set, the program listens to all network namespaces that have a -+nsid assigned into the network namespace were the program is running. -+A prefix is displayed to show the network namespace where the message -+originates. Example: -+.sp -+.in +2 -+[nsid 0]10.16.0.112 dev eth0 lladdr 00:04:23:df:2f:d0 REACHABLE -+.in -2 -+.sp -+ -+.P -+If the - .BI file - option is given, the program does not listen on RTNETLINK, - but opens the given file, and dumps its contents. The file -@@ -75,3 +109,5 @@ of starting. - - .SH AUTHOR - Original Manpage by Michail Litvak <mci@owl.openwall.com> -+.br -+Manpage revised by Nicolas Dichtel <nicolas.dichtel@6wind.com> -diff --git a/man/man8/ip-xfrm.8 b/man/man8/ip-xfrm.8 -index e305c0b..aea4fda 100644 ---- a/man/man8/ip-xfrm.8 -+++ b/man/man8/ip-xfrm.8 -@@ -359,7 +359,11 @@ ip-xfrm \- transform configuration - .BR required " | " use - - .ti -8 --.BR "ip xfrm monitor" " [ " all " |" -+.BR "ip xfrm monitor" " [" -+.BI all-nsid -+] [ -+.BI all -+ | - .IR LISTofXFRM-OBJECTS " ]" - - .ti -8 -@@ -664,7 +668,22 @@ ip xfrm monitor state monitoring for xfrm objects - .PP - The xfrm objects to monitor can be optionally specified. - -+.P -+If the -+.BI all-nsid -+option is set, the program listens to all network namespaces that have a -+nsid assigned into the network namespace were the program is running. -+A prefix is displayed to show the network namespace where the message -+originates. Example: -+.sp -+.in +2 -+[nsid 1]Flushed state proto 0 -+.in -2 -+.sp -+ - .SH AUTHOR - Manpage revised by David Ward <david.ward@ll.mit.edu> - .br - Manpage revised by Christophe Gouault <christophe.gouault@6wind.com> -+.br -+Manpage revised by Nicolas Dichtel <nicolas.dichtel@6wind.com> -diff --git a/tc/tc_monitor.c b/tc/tc_monitor.c -index 0efe034..cae3616 100644 ---- a/tc/tc_monitor.c -+++ b/tc/tc_monitor.c -@@ -36,6 +36,7 @@ static void usage(void) - - - static int accept_tcmsg(const struct sockaddr_nl *who, -+ struct rtnl_ctrl_data *ctrl, - struct nlmsghdr *n, void *arg) - { - FILE *fp = (FILE*)arg; --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-lib.patch b/SOURCES/iproute2-3.10.0-lib.patch deleted file mode 100644 index 2c97fe9..0000000 --- a/SOURCES/iproute2-3.10.0-lib.patch +++ /dev/null @@ -1,505 +0,0 @@ -commit f389090cd1dc2f9945c19f837ade98bd733015cb -Author: Pavel Šimerda <psimerda@redhat.com> -Date: Thu May 28 23:39:22 2015 +0200 - - backport selected library functions - -diff --git a/include/libnetlink.h b/include/libnetlink.h -index ec3d657..5dcc0c3 100644 ---- a/include/libnetlink.h -+++ b/include/libnetlink.h -@@ -18,6 +18,7 @@ struct rtnl_handle - struct sockaddr_nl peer; - __u32 seq; - __u32 dump; -+ FILE *dump_fp; - }; - - extern int rcvbuf; -@@ -68,11 +69,15 @@ extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int le - extern int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta, - int len, unsigned short flags); - extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len); -+extern struct rtattr *parse_rtattr_one(int type, struct rtattr *rta, int len); - extern int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, int len); - - #define parse_rtattr_nested(tb, max, rta) \ - (parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta))) - -+#define parse_rtattr_one_nested(type, rta) \ -+ (parse_rtattr_one(type, RTA_DATA(rta), RTA_PAYLOAD(rta))) -+ - #define parse_rtattr_nested_compat(tb, max, rta, data, len) \ - ({ data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \ - __parse_rtattr_nested_compat(tb, max, rta, len); }) -@@ -140,5 +145,17 @@ extern int rtnl_from_file(FILE *, rtnl_filter_t handler, - #define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg)) - #endif - -+#ifndef NETNS_RTA -+#define NETNS_RTA(r) \ -+ ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtgenmsg)))) -+#endif -+#ifndef NETNS_PAYLOAD -+#define NETNS_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtgenmsg)) -+#endif -+ -+/* User defined nlmsg_type which is used mostly for logging netlink -+ * messages from dump file */ -+#define NLMSG_TSTAMP 15 -+ - #endif /* __LIBNETLINK_H__ */ - -diff --git a/include/namespace.h b/include/namespace.h -new file mode 100644 -index 0000000..a2ac7dc ---- /dev/null -+++ b/include/namespace.h -@@ -0,0 +1,54 @@ -+#ifndef __NAMESPACE_H__ -+#define __NAMESPACE_H__ 1 -+ -+#include <sched.h> -+#include <sys/mount.h> -+#include <sys/syscall.h> -+#include <errno.h> -+ -+#define NETNS_RUN_DIR "/var/run/netns" -+#define NETNS_ETC_DIR "/etc/netns" -+ -+#ifndef CLONE_NEWNET -+#define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */ -+#endif -+ -+#ifndef MNT_DETACH -+#define MNT_DETACH 0x00000002 /* Just detach from the tree */ -+#endif /* MNT_DETACH */ -+ -+/* sys/mount.h may be out too old to have these */ -+#ifndef MS_REC -+#define MS_REC 16384 -+#endif -+ -+#ifndef MS_SLAVE -+#define MS_SLAVE (1 << 19) -+#endif -+ -+#ifndef MS_SHARED -+#define MS_SHARED (1 << 20) -+#endif -+ -+#ifndef HAVE_SETNS -+static inline int setns(int fd, int nstype) -+{ -+#ifdef __NR_setns -+ return syscall(__NR_setns, fd, nstype); -+#else -+ errno = ENOSYS; -+ return -1; -+#endif -+} -+#endif /* HAVE_SETNS */ -+ -+extern int netns_switch(char *netns); -+extern int netns_get_fd(const char *netns); -+extern int netns_foreach(int (*func)(char *nsname, void *arg), void *arg); -+ -+struct netns_func { -+ int (*func)(char *nsname, void *arg); -+ void *arg; -+}; -+ -+#endif /* __NAMESPACE_H__ */ -diff --git a/include/rt_names.h b/include/rt_names.h -index 37adbd3..c0ea4f9 100644 ---- a/include/rt_names.h -+++ b/include/rt_names.h -@@ -8,6 +8,7 @@ const char *rtnl_rtscope_n2a(int id, char *buf, int len); - const char *rtnl_rttable_n2a(__u32 id, char *buf, int len); - const char *rtnl_rtrealm_n2a(int id, char *buf, int len); - const char *rtnl_dsfield_n2a(int id, char *buf, int len); -+const char *rtnl_group_n2a(int id, char *buf, int len); - - int rtnl_rtprot_a2n(__u32 *id, const char *arg); - int rtnl_rtscope_a2n(__u32 *id, const char *arg); -@@ -28,5 +29,7 @@ int ll_addr_a2n(char *lladdr, int len, const char *arg); - const char * ll_proto_n2a(unsigned short id, char *buf, int len); - int ll_proto_a2n(unsigned short *id, const char *buf); - -+const char *nl_proto_n2a(int id, char *buf, int len); -+int nl_proto_a2n(__u32 *id, const char *arg); - - #endif -diff --git a/include/utils.h b/include/utils.h -index 24ff19f..ca05b02 100644 ---- a/include/utils.h -+++ b/include/utils.h -@@ -5,12 +5,15 @@ - #include <asm/types.h> - #include <resolv.h> - #include <stdlib.h> -+#include <stdbool.h> - - #include "libnetlink.h" - #include "ll_map.h" - #include "rtm_map.h" - - extern int preferred_family; -+extern int human_readable; -+extern int use_iec; - extern int show_stats; - extern int show_details; - extern int show_raw; -@@ -20,6 +23,7 @@ extern int timestamp; - extern char * _SL_; - extern int max_flush_loops; - extern int batch_mode; -+extern bool do_all; - - #ifndef IPPROTO_ESP - #define IPPROTO_ESP 50 -@@ -151,9 +155,16 @@ int print_timestamp(FILE *fp); - extern int cmdlineno; - extern ssize_t getcmdline(char **line, size_t *len, FILE *in); - extern int makeargs(char *line, char *argv[], int maxargs); -+extern int inet_get_addr(const char *src, __u32 *dst, struct in6_addr *dst6); - - struct iplink_req; - int iplink_parse(int argc, char **argv, struct iplink_req *req, - char **name, char **type, char **link, char **dev, - int *group); -+ -+extern int do_each_netns(int (*func)(char *nsname, void *arg), void *arg, -+ bool show_label); -+ -+char *int_to_str(int val, char *buf); -+ - #endif /* __UTILS_H__ */ -diff --git a/lib/Makefile b/lib/Makefile -index a42b885..66f89f1 100644 ---- a/lib/Makefile -+++ b/lib/Makefile -@@ -1,8 +1,12 @@ - include ../Config - -+ifeq ($(IP_CONFIG_SETNS),y) -+ CFLAGS += -DHAVE_SETNS -+endif -+ - CFLAGS += -fPIC - --UTILOBJ=utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o inet_proto.o -+UTILOBJ=utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o inet_proto.o namespace.o - - NLOBJ=libgenl.o ll_map.o libnetlink.o - -diff --git a/lib/namespace.c b/lib/namespace.c -new file mode 100644 -index 0000000..c03a103 ---- /dev/null -+++ b/lib/namespace.c -@@ -0,0 +1,123 @@ -+/* -+ * namespace.c -+ * -+ * 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. -+ */ -+ -+#include <fcntl.h> -+#include <dirent.h> -+ -+#include "utils.h" -+#include "namespace.h" -+ -+static void bind_etc(const char *name) -+{ -+ char etc_netns_path[MAXPATHLEN]; -+ char netns_name[MAXPATHLEN]; -+ char etc_name[MAXPATHLEN]; -+ struct dirent *entry; -+ DIR *dir; -+ -+ snprintf(etc_netns_path, sizeof(etc_netns_path), "%s/%s", NETNS_ETC_DIR, name); -+ dir = opendir(etc_netns_path); -+ if (!dir) -+ return; -+ -+ while ((entry = readdir(dir)) != NULL) { -+ if (strcmp(entry->d_name, ".") == 0) -+ continue; -+ if (strcmp(entry->d_name, "..") == 0) -+ continue; -+ snprintf(netns_name, sizeof(netns_name), "%s/%s", etc_netns_path, entry->d_name); -+ snprintf(etc_name, sizeof(etc_name), "/etc/%s", entry->d_name); -+ if (mount(netns_name, etc_name, "none", MS_BIND, NULL) < 0) { -+ fprintf(stderr, "Bind %s -> %s failed: %s\n", -+ netns_name, etc_name, strerror(errno)); -+ } -+ } -+ closedir(dir); -+} -+ -+int netns_switch(char *name) -+{ -+ char net_path[MAXPATHLEN]; -+ int netns; -+ -+ snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name); -+ netns = open(net_path, O_RDONLY | O_CLOEXEC); -+ if (netns < 0) { -+ fprintf(stderr, "Cannot open network namespace \"%s\": %s\n", -+ name, strerror(errno)); -+ return -1; -+ } -+ -+ if (setns(netns, CLONE_NEWNET) < 0) { -+ fprintf(stderr, "setting the network namespace \"%s\" failed: %s\n", -+ name, strerror(errno)); -+ return -1; -+ } -+ -+ if (unshare(CLONE_NEWNS) < 0) { -+ fprintf(stderr, "unshare failed: %s\n", strerror(errno)); -+ return -1; -+ } -+ /* Don't let any mounts propagate back to the parent */ -+ if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL)) { -+ fprintf(stderr, "\"mount --make-rslave /\" failed: %s\n", -+ strerror(errno)); -+ return -1; -+ } -+ /* Mount a version of /sys that describes the network namespace */ -+ if (umount2("/sys", MNT_DETACH) < 0) { -+ fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno)); -+ return -1; -+ } -+ if (mount(name, "/sys", "sysfs", 0, NULL) < 0) { -+ fprintf(stderr, "mount of /sys failed: %s\n",strerror(errno)); -+ return -1; -+ } -+ -+ /* Setup bind mounts for config files in /etc */ -+ bind_etc(name); -+ return 0; -+} -+ -+int netns_get_fd(const char *name) -+{ -+ char pathbuf[MAXPATHLEN]; -+ const char *path, *ptr; -+ -+ path = name; -+ ptr = strchr(name, '/'); -+ if (!ptr) { -+ snprintf(pathbuf, sizeof(pathbuf), "%s/%s", -+ NETNS_RUN_DIR, name ); -+ path = pathbuf; -+ } -+ return open(path, O_RDONLY); -+} -+ -+int netns_foreach(int (*func)(char *nsname, void *arg), void *arg) -+{ -+ DIR *dir; -+ struct dirent *entry; -+ -+ dir = opendir(NETNS_RUN_DIR); -+ if (!dir) -+ return -1; -+ -+ while ((entry = readdir(dir)) != NULL) { -+ if (strcmp(entry->d_name, ".") == 0) -+ continue; -+ if (strcmp(entry->d_name, "..") == 0) -+ continue; -+ if (func(entry->d_name, arg)) -+ break; -+ } -+ -+ closedir(dir); -+ return 0; -+} -diff --git a/lib/rt_names.c b/lib/rt_names.c -index 02f1417..c2e60de 100644 ---- a/lib/rt_names.c -+++ b/lib/rt_names.c -@@ -500,3 +500,104 @@ int rtnl_group_a2n(int *id, const char *arg) - *id = i; - return 0; - } -+ -+const char *rtnl_group_n2a(int id, char *buf, int len) -+{ -+ struct rtnl_hash_entry *entry; -+ int i; -+ -+ if (!rtnl_group_init) -+ rtnl_group_initialize(); -+ -+ for (i=0; i<256; i++) { -+ entry = rtnl_group_hash[i]; -+ if (entry && entry->id == id) { -+ return entry->name; -+ } -+ } -+ -+ snprintf(buf, len, "%d", id); -+ return buf; -+} -+ -+static char *nl_proto_tab[256] = { -+ [NETLINK_ROUTE] = "rtnl", -+ [NETLINK_UNUSED] = "unused", -+ [NETLINK_USERSOCK] = "usersock", -+ [NETLINK_FIREWALL] = "fw", -+ [NETLINK_SOCK_DIAG] = "tcpdiag", -+ [NETLINK_NFLOG] = "nflog", -+ [NETLINK_XFRM] = "xfrm", -+ [NETLINK_SELINUX] = "selinux", -+ [NETLINK_ISCSI] = "iscsi", -+ [NETLINK_AUDIT] = "audit", -+ [NETLINK_FIB_LOOKUP] = "fiblookup", -+ [NETLINK_CONNECTOR] = "connector", -+ [NETLINK_NETFILTER] = "nft", -+ [NETLINK_IP6_FW] = "ip6fw", -+ [NETLINK_DNRTMSG] = "dec-rt", -+ [NETLINK_KOBJECT_UEVENT] = "uevent", -+ [NETLINK_GENERIC] = "genl", -+ [NETLINK_SCSITRANSPORT] = "scsi-trans", -+ [NETLINK_ECRYPTFS] = "ecryptfs", -+ [NETLINK_RDMA] = "rdma", -+ [NETLINK_CRYPTO] = "crypto", -+}; -+ -+static int nl_proto_init; -+ -+static void nl_proto_initialize(void) -+{ -+ nl_proto_init = 1; -+ rtnl_tab_initialize(CONFDIR "/nl_protos", -+ nl_proto_tab, 256); -+} -+ -+const char *nl_proto_n2a(int id, char *buf, int len) -+{ -+ if (id < 0 || id >= 256) { -+ snprintf(buf, len, "%u", id); -+ return buf; -+ } -+ -+ if (!nl_proto_init) -+ nl_proto_initialize(); -+ -+ if (nl_proto_tab[id]) -+ return nl_proto_tab[id]; -+ -+ snprintf(buf, len, "%u", id); -+ return buf; -+} -+ -+int nl_proto_a2n(__u32 *id, const char *arg) -+{ -+ static char *cache = NULL; -+ static unsigned long res; -+ char *end; -+ int i; -+ -+ if (cache && strcmp(cache, arg) == 0) { -+ *id = res; -+ return 0; -+ } -+ -+ if (!nl_proto_init) -+ nl_proto_initialize(); -+ -+ for (i = 0; i < 256; i++) { -+ if (nl_proto_tab[i] && -+ strcmp(nl_proto_tab[i], arg) == 0) { -+ cache = nl_proto_tab[i]; -+ res = i; -+ *id = res; -+ return 0; -+ } -+ } -+ -+ res = strtoul(arg, &end, 0); -+ if (!end || end == arg || *end || res > 255) -+ return -1; -+ *id = res; -+ return 0; -+} -diff --git a/lib/utils.c b/lib/utils.c -index 0f9de02..299b485 100644 ---- a/lib/utils.c -+++ b/lib/utils.c -@@ -31,6 +31,7 @@ - - - #include "utils.h" -+#include "namespace.h" - - int get_integer(int *val, const char *arg, int base) - { -@@ -864,3 +865,44 @@ int makeargs(char *line, char *argv[], int maxargs) - - return argc; - } -+ -+int inet_get_addr(const char *src, __u32 *dst, struct in6_addr *dst6) -+{ -+ if (strchr(src, ':')) -+ return inet_pton(AF_INET6, src, dst6); -+ else -+ return inet_pton(AF_INET, src, dst); -+} -+ -+static int on_netns(char *nsname, void *arg) -+{ -+ struct netns_func *f = arg; -+ -+ if (netns_switch(nsname)) -+ return -1; -+ -+ return f->func(nsname, f->arg); -+} -+ -+static int on_netns_label(char *nsname, void *arg) -+{ -+ printf("\nnetns: %s\n", nsname); -+ return on_netns(nsname, arg); -+} -+ -+int do_each_netns(int (*func)(char *nsname, void *arg), void *arg, -+ bool show_label) -+{ -+ struct netns_func nsf = { .func = func, .arg = arg }; -+ -+ if (show_label) -+ return netns_foreach(on_netns_label, &nsf); -+ -+ return netns_foreach(on_netns, &nsf); -+} -+ -+char *int_to_str(int val, char *buf) -+{ -+ sprintf(buf, "%d", val); -+ return buf; -+} -diff --git a/misc/Makefile b/misc/Makefile -index a59ff87..a516bd8 100644 ---- a/misc/Makefile -+++ b/misc/Makefile -@@ -5,6 +5,10 @@ TARGETS=ss nstat ifstat rtacct arpd lnstat - - include ../Config - -+ifeq ($(IP_CONFIG_SETNS),y) -+ CFLAGS += -DHAVE_SETNS -+endif -+ - all: $(TARGETS) - - ss: $(SSOBJ) diff --git a/SOURCES/iproute2-3.10.0-linux.patch b/SOURCES/iproute2-3.10.0-linux.patch deleted file mode 100644 index 8b840df..0000000 --- a/SOURCES/iproute2-3.10.0-linux.patch +++ /dev/null @@ -1,2459 +0,0 @@ -diff --git a/include/linux/bpf.h b/include/linux/bpf.h -new file mode 100644 -index 0000000..08aab3a ---- /dev/null -+++ b/include/linux/bpf.h -@@ -0,0 +1,226 @@ -+/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of version 2 of the GNU General Public -+ * License as published by the Free Software Foundation. -+ */ -+#ifndef __LINUX_BPF_H__ -+#define __LINUX_BPF_H__ -+ -+#include <linux/types.h> -+#include <linux/bpf_common.h> -+ -+/* Extended instruction set based on top of classic BPF */ -+ -+/* instruction classes */ -+#define BPF_ALU64 0x07 /* alu mode in double word width */ -+ -+/* ld/ldx fields */ -+#define BPF_DW 0x18 /* double word */ -+#define BPF_XADD 0xc0 /* exclusive add */ -+ -+/* alu/jmp fields */ -+#define BPF_MOV 0xb0 /* mov reg to reg */ -+#define BPF_ARSH 0xc0 /* sign extending arithmetic shift right */ -+ -+/* change endianness of a register */ -+#define BPF_END 0xd0 /* flags for endianness conversion: */ -+#define BPF_TO_LE 0x00 /* convert to little-endian */ -+#define BPF_TO_BE 0x08 /* convert to big-endian */ -+#define BPF_FROM_LE BPF_TO_LE -+#define BPF_FROM_BE BPF_TO_BE -+ -+#define BPF_JNE 0x50 /* jump != */ -+#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */ -+#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */ -+#define BPF_CALL 0x80 /* function call */ -+#define BPF_EXIT 0x90 /* function return */ -+ -+/* Register numbers */ -+enum { -+ BPF_REG_0 = 0, -+ BPF_REG_1, -+ BPF_REG_2, -+ BPF_REG_3, -+ BPF_REG_4, -+ BPF_REG_5, -+ BPF_REG_6, -+ BPF_REG_7, -+ BPF_REG_8, -+ BPF_REG_9, -+ BPF_REG_10, -+ __MAX_BPF_REG, -+}; -+ -+/* BPF has 10 general purpose 64-bit registers and stack frame. */ -+#define MAX_BPF_REG __MAX_BPF_REG -+ -+struct bpf_insn { -+ __u8 code; /* opcode */ -+ __u8 dst_reg:4; /* dest register */ -+ __u8 src_reg:4; /* source register */ -+ __s16 off; /* signed offset */ -+ __s32 imm; /* signed immediate constant */ -+}; -+ -+/* BPF syscall commands */ -+enum bpf_cmd { -+ /* create a map with given type and attributes -+ * fd = bpf(BPF_MAP_CREATE, union bpf_attr *, u32 size) -+ * returns fd or negative error -+ * map is deleted when fd is closed -+ */ -+ BPF_MAP_CREATE, -+ -+ /* lookup key in a given map -+ * err = bpf(BPF_MAP_LOOKUP_ELEM, union bpf_attr *attr, u32 size) -+ * Using attr->map_fd, attr->key, attr->value -+ * returns zero and stores found elem into value -+ * or negative error -+ */ -+ BPF_MAP_LOOKUP_ELEM, -+ -+ /* create or update key/value pair in a given map -+ * err = bpf(BPF_MAP_UPDATE_ELEM, union bpf_attr *attr, u32 size) -+ * Using attr->map_fd, attr->key, attr->value, attr->flags -+ * returns zero or negative error -+ */ -+ BPF_MAP_UPDATE_ELEM, -+ -+ /* find and delete elem by key in a given map -+ * err = bpf(BPF_MAP_DELETE_ELEM, union bpf_attr *attr, u32 size) -+ * Using attr->map_fd, attr->key -+ * returns zero or negative error -+ */ -+ BPF_MAP_DELETE_ELEM, -+ -+ /* lookup key in a given map and return next key -+ * err = bpf(BPF_MAP_GET_NEXT_KEY, union bpf_attr *attr, u32 size) -+ * Using attr->map_fd, attr->key, attr->next_key -+ * returns zero and stores next key or negative error -+ */ -+ BPF_MAP_GET_NEXT_KEY, -+ -+ /* verify and load eBPF program -+ * prog_fd = bpf(BPF_PROG_LOAD, union bpf_attr *attr, u32 size) -+ * Using attr->prog_type, attr->insns, attr->license -+ * returns fd or negative error -+ */ -+ BPF_PROG_LOAD, -+}; -+ -+enum bpf_map_type { -+ BPF_MAP_TYPE_UNSPEC, -+ BPF_MAP_TYPE_HASH, -+ BPF_MAP_TYPE_ARRAY, -+}; -+ -+enum bpf_prog_type { -+ BPF_PROG_TYPE_UNSPEC, -+ BPF_PROG_TYPE_SOCKET_FILTER, -+ BPF_PROG_TYPE_SCHED_CLS, -+ BPF_PROG_TYPE_SCHED_ACT, -+}; -+ -+#define BPF_PSEUDO_MAP_FD 1 -+ -+/* flags for BPF_MAP_UPDATE_ELEM command */ -+#define BPF_ANY 0 /* create new element or update existing */ -+#define BPF_NOEXIST 1 /* create new element if it didn't exist */ -+#define BPF_EXIST 2 /* update existing element */ -+ -+union bpf_attr { -+ struct { /* anonymous struct used by BPF_MAP_CREATE command */ -+ __u32 map_type; /* one of enum bpf_map_type */ -+ __u32 key_size; /* size of key in bytes */ -+ __u32 value_size; /* size of value in bytes */ -+ __u32 max_entries; /* max number of entries in a map */ -+ }; -+ -+ struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ -+ __u32 map_fd; -+ __aligned_u64 key; -+ union { -+ __aligned_u64 value; -+ __aligned_u64 next_key; -+ }; -+ __u64 flags; -+ }; -+ -+ struct { /* anonymous struct used by BPF_PROG_LOAD command */ -+ __u32 prog_type; /* one of enum bpf_prog_type */ -+ __u32 insn_cnt; -+ __aligned_u64 insns; -+ __aligned_u64 license; -+ __u32 log_level; /* verbosity level of verifier */ -+ __u32 log_size; /* size of user buffer */ -+ __aligned_u64 log_buf; /* user supplied buffer */ -+ }; -+} __attribute__((aligned(8))); -+ -+/* integer value in 'imm' field of BPF_CALL instruction selects which helper -+ * function eBPF program intends to call -+ */ -+enum bpf_func_id { -+ BPF_FUNC_unspec, -+ BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */ -+ BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */ -+ BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */ -+ BPF_FUNC_get_prandom_u32, /* u32 prandom_u32(void) */ -+ BPF_FUNC_get_smp_processor_id, /* u32 raw_smp_processor_id(void) */ -+ -+ /** -+ * skb_store_bytes(skb, offset, from, len, flags) - store bytes into packet -+ * @skb: pointer to skb -+ * @offset: offset within packet from skb->data -+ * @from: pointer where to copy bytes from -+ * @len: number of bytes to store into packet -+ * @flags: bit 0 - if true, recompute skb->csum -+ * other bits - reserved -+ * Return: 0 on success -+ */ -+ BPF_FUNC_skb_store_bytes, -+ -+ /** -+ * l3_csum_replace(skb, offset, from, to, flags) - recompute IP checksum -+ * @skb: pointer to skb -+ * @offset: offset within packet where IP checksum is located -+ * @from: old value of header field -+ * @to: new value of header field -+ * @flags: bits 0-3 - size of header field -+ * other bits - reserved -+ * Return: 0 on success -+ */ -+ BPF_FUNC_l3_csum_replace, -+ -+ /** -+ * l4_csum_replace(skb, offset, from, to, flags) - recompute TCP/UDP checksum -+ * @skb: pointer to skb -+ * @offset: offset within packet where TCP/UDP checksum is located -+ * @from: old value of header field -+ * @to: new value of header field -+ * @flags: bits 0-3 - size of header field -+ * bit 4 - is pseudo header -+ * other bits - reserved -+ * Return: 0 on success -+ */ -+ BPF_FUNC_l4_csum_replace, -+ __BPF_FUNC_MAX_ID, -+}; -+ -+/* user accessible mirror of in-kernel sk_buff. -+ * new fields can only be added to the end of this structure -+ */ -+struct __sk_buff { -+ __u32 len; -+ __u32 pkt_type; -+ __u32 mark; -+ __u32 queue_mapping; -+ __u32 protocol; -+ __u32 vlan_present; -+ __u32 vlan_tci; -+ __u32 vlan_proto; -+ __u32 priority; -+}; -+ -+#endif /* __LINUX_BPF_H__ */ -diff --git a/include/linux/bpf_common.h b/include/linux/bpf_common.h -new file mode 100644 -index 0000000..afe7433 ---- /dev/null -+++ b/include/linux/bpf_common.h -@@ -0,0 +1,55 @@ -+#ifndef __LINUX_BPF_COMMON_H__ -+#define __LINUX_BPF_COMMON_H__ -+ -+/* Instruction classes */ -+#define BPF_CLASS(code) ((code) & 0x07) -+#define BPF_LD 0x00 -+#define BPF_LDX 0x01 -+#define BPF_ST 0x02 -+#define BPF_STX 0x03 -+#define BPF_ALU 0x04 -+#define BPF_JMP 0x05 -+#define BPF_RET 0x06 -+#define BPF_MISC 0x07 -+ -+/* ld/ldx fields */ -+#define BPF_SIZE(code) ((code) & 0x18) -+#define BPF_W 0x00 -+#define BPF_H 0x08 -+#define BPF_B 0x10 -+#define BPF_MODE(code) ((code) & 0xe0) -+#define BPF_IMM 0x00 -+#define BPF_ABS 0x20 -+#define BPF_IND 0x40 -+#define BPF_MEM 0x60 -+#define BPF_LEN 0x80 -+#define BPF_MSH 0xa0 -+ -+/* alu/jmp fields */ -+#define BPF_OP(code) ((code) & 0xf0) -+#define BPF_ADD 0x00 -+#define BPF_SUB 0x10 -+#define BPF_MUL 0x20 -+#define BPF_DIV 0x30 -+#define BPF_OR 0x40 -+#define BPF_AND 0x50 -+#define BPF_LSH 0x60 -+#define BPF_RSH 0x70 -+#define BPF_NEG 0x80 -+#define BPF_MOD 0x90 -+#define BPF_XOR 0xa0 -+ -+#define BPF_JA 0x00 -+#define BPF_JEQ 0x10 -+#define BPF_JGT 0x20 -+#define BPF_JGE 0x30 -+#define BPF_JSET 0x40 -+#define BPF_SRC(code) ((code) & 0x08) -+#define BPF_K 0x00 -+#define BPF_X 0x08 -+ -+#ifndef BPF_MAXINSNS -+#define BPF_MAXINSNS 4096 -+#endif -+ -+#endif /* __LINUX_BPF_COMMON_H__ */ -diff --git a/include/linux/can.h b/include/linux/can.h -index e52958d..d9ba97f 100644 ---- a/include/linux/can.h -+++ b/include/linux/can.h -@@ -8,10 +8,42 @@ - * Copyright (c) 2002-2007 Volkswagen Group Electronic Research - * All rights reserved. - * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. Neither the name of Volkswagen nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * Alternatively, provided that this notice is retained in full, this -+ * software may be distributed under the terms of the GNU General -+ * Public License ("GPL") version 2, in which case the provisions of the -+ * GPL apply INSTEAD OF those given above. -+ * -+ * The provided data structures and external interfaces from this code -+ * are not restricted to be used by modules with a GPL compatible license. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. - */ - --#ifndef CAN_H --#define CAN_H -+#ifndef _CAN_H -+#define _CAN_H - - #include <linux/types.h> - #include <linux/socket.h> -@@ -159,4 +191,4 @@ struct can_filter { - - #define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */ - --#endif /* CAN_H */ -+#endif /* !_UAPI_CAN_H */ -diff --git a/include/linux/can/netlink.h b/include/linux/can/netlink.h -index 14966dd..6d4ec2a 100644 ---- a/include/linux/can/netlink.h -+++ b/include/linux/can/netlink.h -@@ -5,10 +5,18 @@ - * - * Copyright (c) 2009 Wolfgang Grandegger <wg@grandegger.com> - * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the version 2 of the GNU General Public License -+ * as published by the Free Software Foundation -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. - */ - --#ifndef CAN_NETLINK_H --#define CAN_NETLINK_H -+#ifndef _CAN_NETLINK_H -+#define _CAN_NETLINK_H - - #include <linux/types.h> - -@@ -84,10 +92,13 @@ struct can_ctrlmode { - }; - - #define CAN_CTRLMODE_LOOPBACK 0x01 /* Loopback mode */ --#define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */ -+#define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */ - #define CAN_CTRLMODE_3_SAMPLES 0x04 /* Triple sampling mode */ - #define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */ - #define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */ -+#define CAN_CTRLMODE_FD 0x20 /* CAN FD mode */ -+#define CAN_CTRLMODE_PRESUME_ACK 0x40 /* Ignore missing CAN ACKs */ -+#define CAN_CTRLMODE_FD_NON_ISO 0x80 /* CAN FD in non-ISO mode */ - - /* - * CAN device statistics -@@ -114,9 +125,11 @@ enum { - IFLA_CAN_RESTART_MS, - IFLA_CAN_RESTART, - IFLA_CAN_BERR_COUNTER, -+ IFLA_CAN_DATA_BITTIMING, -+ IFLA_CAN_DATA_BITTIMING_CONST, - __IFLA_CAN_MAX - }; - - #define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1) - --#endif /* CAN_NETLINK_H */ -+#endif /* !_UAPI_CAN_NETLINK_H */ -diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h -index 51da65b..2b82d7e 100644 ---- a/include/linux/fib_rules.h -+++ b/include/linux/fib_rules.h -@@ -44,8 +44,8 @@ enum { - FRA_FWMARK, /* mark */ - FRA_FLOW, /* flow/class id */ - FRA_UNUSED6, -- FRA_UNUSED7, -- FRA_UNUSED8, -+ FRA_SUPPRESS_IFGROUP, -+ FRA_SUPPRESS_PREFIXLEN, - FRA_TABLE, /* Extended table id */ - FRA_FWMASK, /* mask for netfilter mark */ - FRA_OIFNAME, -diff --git a/include/linux/filter.h b/include/linux/filter.h -index 9a46cb6..344781d 100644 ---- a/include/linux/filter.h -+++ b/include/linux/filter.h -@@ -7,7 +7,7 @@ - - - #include <linux/types.h> -- -+#include <linux/bpf_common.h> - - /* - * Current version of the filter code architecture. -@@ -32,56 +32,6 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */ - struct sock_filter *filter; - }; - --/* -- * Instruction classes -- */ -- --#define BPF_CLASS(code) ((code) & 0x07) --#define BPF_LD 0x00 --#define BPF_LDX 0x01 --#define BPF_ST 0x02 --#define BPF_STX 0x03 --#define BPF_ALU 0x04 --#define BPF_JMP 0x05 --#define BPF_RET 0x06 --#define BPF_MISC 0x07 -- --/* ld/ldx fields */ --#define BPF_SIZE(code) ((code) & 0x18) --#define BPF_W 0x00 --#define BPF_H 0x08 --#define BPF_B 0x10 --#define BPF_MODE(code) ((code) & 0xe0) --#define BPF_IMM 0x00 --#define BPF_ABS 0x20 --#define BPF_IND 0x40 --#define BPF_MEM 0x60 --#define BPF_LEN 0x80 --#define BPF_MSH 0xa0 -- --/* alu/jmp fields */ --#define BPF_OP(code) ((code) & 0xf0) --#define BPF_ADD 0x00 --#define BPF_SUB 0x10 --#define BPF_MUL 0x20 --#define BPF_DIV 0x30 --#define BPF_OR 0x40 --#define BPF_AND 0x50 --#define BPF_LSH 0x60 --#define BPF_RSH 0x70 --#define BPF_NEG 0x80 --#define BPF_MOD 0x90 --#define BPF_XOR 0xa0 -- --#define BPF_JA 0x00 --#define BPF_JEQ 0x10 --#define BPF_JGT 0x20 --#define BPF_JGE 0x30 --#define BPF_JSET 0x40 --#define BPF_SRC(code) ((code) & 0x08) --#define BPF_K 0x00 --#define BPF_X 0x08 -- - /* ret - BPF_K and BPF_X also apply */ - #define BPF_RVAL(code) ((code) & 0x18) - #define BPF_A 0x10 -@@ -91,10 +41,6 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */ - #define BPF_TAX 0x00 - #define BPF_TXA 0x80 - --#ifndef BPF_MAXINSNS --#define BPF_MAXINSNS 4096 --#endif -- - /* - * Macros for filter block array initializers. - */ -@@ -130,7 +76,9 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */ - #define SKF_AD_VLAN_TAG 44 - #define SKF_AD_VLAN_TAG_PRESENT 48 - #define SKF_AD_PAY_OFFSET 52 --#define SKF_AD_MAX 56 -+#define SKF_AD_RANDOM 56 -+#define SKF_AD_VLAN_TPID 60 -+#define SKF_AD_MAX 64 - #define SKF_NET_OFF (-0x100000) - #define SKF_LL_OFF (-0x200000) - -diff --git a/include/linux/fou.h b/include/linux/fou.h -new file mode 100644 -index 0000000..744c323 ---- /dev/null -+++ b/include/linux/fou.h -@@ -0,0 +1,41 @@ -+/* fou.h - FOU Interface */ -+ -+#ifndef _LINUX_FOU_H -+#define _LINUX_FOU_H -+ -+/* NETLINK_GENERIC related info -+ */ -+#define FOU_GENL_NAME "fou" -+#define FOU_GENL_VERSION 0x1 -+ -+enum { -+ FOU_ATTR_UNSPEC, -+ FOU_ATTR_PORT, /* u16 */ -+ FOU_ATTR_AF, /* u8 */ -+ FOU_ATTR_IPPROTO, /* u8 */ -+ FOU_ATTR_TYPE, /* u8 */ -+ FOU_ATTR_REMCSUM_NOPARTIAL, /* flag */ -+ -+ __FOU_ATTR_MAX, -+}; -+ -+#define FOU_ATTR_MAX (__FOU_ATTR_MAX - 1) -+ -+enum { -+ FOU_CMD_UNSPEC, -+ FOU_CMD_ADD, -+ FOU_CMD_DEL, -+ FOU_CMD_GET, -+ -+ __FOU_CMD_MAX, -+}; -+ -+enum { -+ FOU_ENCAP_UNSPEC, -+ FOU_ENCAP_DIRECT, -+ FOU_ENCAP_GUE, -+}; -+ -+#define FOU_CMD_MAX (__FOU_CMD_MAX - 1) -+ -+#endif /* _LINUX_FOU_H */ -diff --git a/include/linux/gen_stats.h b/include/linux/gen_stats.h -index 552c8a0..6487317 100644 ---- a/include/linux/gen_stats.h -+++ b/include/linux/gen_stats.h -@@ -9,6 +9,7 @@ enum { - TCA_STATS_RATE_EST, - TCA_STATS_QUEUE, - TCA_STATS_APP, -+ TCA_STATS_RATE_EST64, - __TCA_STATS_MAX, - }; - #define TCA_STATS_MAX (__TCA_STATS_MAX - 1) -@@ -38,6 +39,16 @@ struct gnet_stats_rate_est { - }; - - /** -+ * struct gnet_stats_rate_est64 - rate estimator -+ * @bps: current byte rate -+ * @pps: current packet rate -+ */ -+struct gnet_stats_rate_est64 { -+ __u64 bps; -+ __u64 pps; -+}; -+ -+/** - * struct gnet_stats_queue - queuing statistics - * @qlen: queue length - * @backlog: backlog size of queue -diff --git a/include/linux/genetlink.h b/include/linux/genetlink.h -index 1f85a27..8a1d500 100644 ---- a/include/linux/genetlink.h -+++ b/include/linux/genetlink.h -@@ -27,6 +27,8 @@ struct genlmsghdr { - */ - #define GENL_ID_GENERATE 0 - #define GENL_ID_CTRL NLMSG_MIN_TYPE -+#define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1) -+#define GENL_ID_PMCRAID (NLMSG_MIN_TYPE + 2) - - /************************************************************************** - * Controller -diff --git a/include/linux/if.h b/include/linux/if.h -index 7f261c0..a55a9e0 100644 ---- a/include/linux/if.h -+++ b/include/linux/if.h -@@ -27,64 +27,91 @@ - #define IFALIASZ 256 - #include <linux/hdlc/ioctl.h> - --/* Standard interface flags (netdevice->flags). */ --#define IFF_UP 0x1 /* interface is up */ --#define IFF_BROADCAST 0x2 /* broadcast address valid */ --#define IFF_DEBUG 0x4 /* turn on debugging */ --#define IFF_LOOPBACK 0x8 /* is a loopback net */ --#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */ --#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ --#define IFF_RUNNING 0x40 /* interface RFC2863 OPER_UP */ --#define IFF_NOARP 0x80 /* no ARP protocol */ --#define IFF_PROMISC 0x100 /* receive all packets */ --#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/ -- --#define IFF_MASTER 0x400 /* master of a load balancer */ --#define IFF_SLAVE 0x800 /* slave of a load balancer */ -- --#define IFF_MULTICAST 0x1000 /* Supports multicast */ -- --#define IFF_PORTSEL 0x2000 /* can set media type */ --#define IFF_AUTOMEDIA 0x4000 /* auto media select active */ --#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/ -- --#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ --#define IFF_DORMANT 0x20000 /* driver signals dormant */ -+/** -+ * enum net_device_flags - &struct net_device flags -+ * -+ * These are the &struct net_device flags, they can be set by drivers, the -+ * kernel and some can be triggered by userspace. Userspace can query and -+ * set these flags using userspace utilities but there is also a sysfs -+ * entry available for all dev flags which can be queried and set. These flags -+ * are shared for all types of net_devices. The sysfs entries are available -+ * via /sys/class/net/<dev>/flags. Flags which can be toggled through sysfs -+ * are annotated below, note that only a few flags can be toggled and some -+ * other flags are always always preserved from the original net_device flags -+ * even if you try to set them via sysfs. Flags which are always preserved -+ * are kept under the flag grouping @IFF_VOLATILE. Flags which are __volatile__ -+ * are annotated below as such. -+ * -+ * You should have a pretty good reason to be extending these flags. -+ * -+ * @IFF_UP: interface is up. Can be toggled through sysfs. -+ * @IFF_BROADCAST: broadcast address valid. Volatile. -+ * @IFF_DEBUG: turn on debugging. Can be toggled through sysfs. -+ * @IFF_LOOPBACK: is a loopback net. Volatile. -+ * @IFF_POINTOPOINT: interface is has p-p link. Volatile. -+ * @IFF_NOTRAILERS: avoid use of trailers. Can be toggled through sysfs. -+ * Volatile. -+ * @IFF_RUNNING: interface RFC2863 OPER_UP. Volatile. -+ * @IFF_NOARP: no ARP protocol. Can be toggled through sysfs. Volatile. -+ * @IFF_PROMISC: receive all packets. Can be toggled through sysfs. -+ * @IFF_ALLMULTI: receive all multicast packets. Can be toggled through -+ * sysfs. -+ * @IFF_MASTER: master of a load balancer. Volatile. -+ * @IFF_SLAVE: slave of a load balancer. Volatile. -+ * @IFF_MULTICAST: Supports multicast. Can be toggled through sysfs. -+ * @IFF_PORTSEL: can set media type. Can be toggled through sysfs. -+ * @IFF_AUTOMEDIA: auto media select active. Can be toggled through sysfs. -+ * @IFF_DYNAMIC: dialup device with changing addresses. Can be toggled -+ * through sysfs. -+ * @IFF_LOWER_UP: driver signals L1 up. Volatile. -+ * @IFF_DORMANT: driver signals dormant. Volatile. -+ * @IFF_ECHO: echo sent packets. Volatile. -+ */ -+enum net_device_flags { -+ IFF_UP = 1<<0, /* sysfs */ -+ IFF_BROADCAST = 1<<1, /* __volatile__ */ -+ IFF_DEBUG = 1<<2, /* sysfs */ -+ IFF_LOOPBACK = 1<<3, /* __volatile__ */ -+ IFF_POINTOPOINT = 1<<4, /* __volatile__ */ -+ IFF_NOTRAILERS = 1<<5, /* sysfs */ -+ IFF_RUNNING = 1<<6, /* __volatile__ */ -+ IFF_NOARP = 1<<7, /* sysfs */ -+ IFF_PROMISC = 1<<8, /* sysfs */ -+ IFF_ALLMULTI = 1<<9, /* sysfs */ -+ IFF_MASTER = 1<<10, /* __volatile__ */ -+ IFF_SLAVE = 1<<11, /* __volatile__ */ -+ IFF_MULTICAST = 1<<12, /* sysfs */ -+ IFF_PORTSEL = 1<<13, /* sysfs */ -+ IFF_AUTOMEDIA = 1<<14, /* sysfs */ -+ IFF_DYNAMIC = 1<<15, /* sysfs */ -+ IFF_LOWER_UP = 1<<16, /* __volatile__ */ -+ IFF_DORMANT = 1<<17, /* __volatile__ */ -+ IFF_ECHO = 1<<18, /* __volatile__ */ -+}; - --#define IFF_ECHO 0x40000 /* echo sent packets */ -+#define IFF_UP IFF_UP -+#define IFF_BROADCAST IFF_BROADCAST -+#define IFF_DEBUG IFF_DEBUG -+#define IFF_LOOPBACK IFF_LOOPBACK -+#define IFF_POINTOPOINT IFF_POINTOPOINT -+#define IFF_NOTRAILERS IFF_NOTRAILERS -+#define IFF_RUNNING IFF_RUNNING -+#define IFF_NOARP IFF_NOARP -+#define IFF_PROMISC IFF_PROMISC -+#define IFF_ALLMULTI IFF_ALLMULTI -+#define IFF_MASTER IFF_MASTER -+#define IFF_SLAVE IFF_SLAVE -+#define IFF_MULTICAST IFF_MULTICAST -+#define IFF_PORTSEL IFF_PORTSEL -+#define IFF_AUTOMEDIA IFF_AUTOMEDIA -+#define IFF_DYNAMIC IFF_DYNAMIC -+#define IFF_LOWER_UP IFF_LOWER_UP -+#define IFF_DORMANT IFF_DORMANT -+#define IFF_ECHO IFF_ECHO - - #define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\ - IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT) - --/* Private (from user) interface flags (netdevice->priv_flags). */ --#define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */ --#define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */ --#define IFF_SLAVE_INACTIVE 0x4 /* bonding slave not the curr. active */ --#define IFF_MASTER_8023AD 0x8 /* bonding master, 802.3ad. */ --#define IFF_MASTER_ALB 0x10 /* bonding master, balance-alb. */ --#define IFF_BONDING 0x20 /* bonding master or slave */ --#define IFF_SLAVE_NEEDARP 0x40 /* need ARPs for validation */ --#define IFF_ISATAP 0x80 /* ISATAP interface (RFC4214) */ --#define IFF_MASTER_ARPMON 0x100 /* bonding master, ARP mon in use */ --#define IFF_WAN_HDLC 0x200 /* WAN HDLC device */ --#define IFF_XMIT_DST_RELEASE 0x400 /* dev_hard_start_xmit() is allowed to -- * release skb->dst -- */ --#define IFF_DONT_BRIDGE 0x800 /* disallow bridging this ether dev */ --#define IFF_DISABLE_NETPOLL 0x1000 /* disable netpoll at run-time */ --#define IFF_MACVLAN_PORT 0x2000 /* device used as macvlan port */ --#define IFF_BRIDGE_PORT 0x4000 /* device used as bridge port */ --#define IFF_OVS_DATAPATH 0x8000 /* device used as Open vSwitch -- * datapath port */ --#define IFF_TX_SKB_SHARING 0x10000 /* The interface supports sharing -- * skbs on transmit */ --#define IFF_UNICAST_FLT 0x20000 /* Supports unicast filtering */ --#define IFF_TEAM_PORT 0x40000 /* device used as team port */ --#define IFF_SUPP_NOFCS 0x80000 /* device supports sending custom FCS */ --#define IFF_LIVE_ADDR_CHANGE 0x100000 /* device supports hardware address -- * change when it's running */ -- -- - #define IF_GET_IFACE 0x0001 /* for querying only */ - #define IF_GET_PROTO 0x0002 - -diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h -index 58b39f4..26f0ecf 100644 ---- a/include/linux/if_addr.h -+++ b/include/linux/if_addr.h -@@ -18,6 +18,9 @@ struct ifaddrmsg { - * It makes no difference for normally configured broadcast interfaces, - * but for point-to-point IFA_ADDRESS is DESTINATION address, - * local address is supplied in IFA_LOCAL attribute. -+ * -+ * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags. -+ * If present, the value from struct ifaddrmsg will be ignored. - */ - enum { - IFA_UNSPEC, -@@ -28,6 +31,7 @@ enum { - IFA_ANYCAST, - IFA_CACHEINFO, - IFA_MULTICAST, -+ IFA_FLAGS, - __IFA_MAX, - }; - -@@ -44,6 +48,10 @@ enum { - #define IFA_F_DEPRECATED 0x20 - #define IFA_F_TENTATIVE 0x40 - #define IFA_F_PERMANENT 0x80 -+#define IFA_F_MANAGETEMPADDR 0x100 -+#define IFA_F_NOPREFIXROUTE 0x200 -+#define IFA_F_MCAUTOJOIN 0x400 -+#define IFA_F_STABLE_PRIVACY 0x800 - - struct ifa_cacheinfo { - __u32 ifa_prefered; -diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h -index 6a48d55..d001bdb 100644 ---- a/include/linux/if_arp.h -+++ b/include/linux/if_arp.h -@@ -93,6 +93,8 @@ - #define ARPHRD_PHONET_PIPE 821 /* PhoNet pipe header */ - #define ARPHRD_CAIF 822 /* CAIF media type */ - #define ARPHRD_IP6GRE 823 /* GRE over IPv6 */ -+#define ARPHRD_NETLINK 824 /* Netlink header */ -+#define ARPHRD_6LOWPAN 825 /* IPv6 over LoWPAN */ - - #define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */ - #define ARPHRD_NONE 0xFFFE /* zero header length */ -diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h -index d37e53c..913bd8e 100644 ---- a/include/linux/if_bridge.h -+++ b/include/linux/if_bridge.h -@@ -14,6 +14,8 @@ - #define _LINUX_IF_BRIDGE_H - - #include <linux/types.h> -+#include <linux/if_ether.h> -+#include <linux/in6.h> - - #define SYSFS_BRIDGE_ATTR "bridge" - #define SYSFS_BRIDGE_FDB "brforward" -@@ -88,7 +90,7 @@ struct __port_info { - }; - - struct __fdb_entry { -- __u8 mac_addr[6]; -+ __u8 mac_addr[ETH_ALEN]; - __u8 port_no; - __u8 is_local; - __u32 ageing_timer_value; -@@ -103,6 +105,7 @@ struct __fdb_entry { - - #define BRIDGE_MODE_VEB 0 /* Default loopback mode */ - #define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */ -+#define BRIDGE_MODE_UNDEF 0xFFFF /* mode undefined */ - - /* Bridge management nested attributes - * [IFLA_AF_SPEC] = { -@@ -122,6 +125,8 @@ enum { - #define BRIDGE_VLAN_INFO_MASTER (1<<0) /* Operate on Bridge device as well */ - #define BRIDGE_VLAN_INFO_PVID (1<<1) /* VLAN is PVID, ingress untagged */ - #define BRIDGE_VLAN_INFO_UNTAGGED (1<<2) /* VLAN egresses untagged */ -+#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1<<3) /* VLAN is start of vlan range */ -+#define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */ - - struct bridge_vlan_info { - __u16 flags; -diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h -index 2fc760a..4678e49 100644 ---- a/include/linux/if_ether.h -+++ b/include/linux/if_ether.h -@@ -68,11 +68,11 @@ - #define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ - #define ETH_P_WCCP 0x883E /* Web-cache coordination protocol - * defined in draft-wilson-wrec-wccp-v2-00.txt */ --#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ --#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ - #define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */ - #define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */ - #define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */ -+#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ -+#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ - #define ETH_P_LINK_CTL 0x886c /* HPNA, wlan link local tunnel */ - #define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport - * over Ethernet -@@ -85,9 +85,12 @@ - #define ETH_P_8021AH 0x88E7 /* 802.1ah Backbone Service Tag */ - #define ETH_P_MVRP 0x88F5 /* 802.1Q MVRP */ - #define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */ -+#define ETH_P_PRP 0x88FB /* IEC 62439-3 PRP/HSRv0 */ - #define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ - #define ETH_P_TDLS 0x890D /* TDLS */ - #define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ -+#define ETH_P_80221 0x8917 /* IEEE 802.21 Media Independent Handover Protocol */ -+#define ETH_P_LOOPBACK 0x9000 /* Ethernet loopback packet, per IEEE 802.3 */ - #define ETH_P_QINQ1 0x9100 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ - #define ETH_P_QINQ2 0x9200 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ - #define ETH_P_QINQ3 0x9300 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ -@@ -125,6 +128,7 @@ - #define ETH_P_PHONET 0x00F5 /* Nokia Phonet frames */ - #define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */ - #define ETH_P_CAIF 0x00F7 /* ST-Ericsson CAIF protocol */ -+#define ETH_P_XDSA 0x00F8 /* Multiplexed DSA protocol */ - - /* - * This is an Ethernet frame header. -diff --git a/include/linux/if_link.h b/include/linux/if_link.h -index 965dc9f..3d0d613 100644 ---- a/include/linux/if_link.h -+++ b/include/linux/if_link.h -@@ -143,6 +143,11 @@ enum { - IFLA_NUM_TX_QUEUES, - IFLA_NUM_RX_QUEUES, - IFLA_CARRIER, -+ IFLA_PHYS_PORT_ID, -+ IFLA_CARRIER_CHANGES, -+ IFLA_PHYS_SWITCH_ID, -+ IFLA_LINK_NETNSID, -+ IFLA_PHYS_PORT_NAME, - __IFLA_MAX - }; - -@@ -200,11 +205,33 @@ enum { - IFLA_INET6_CACHEINFO, /* time values and max reasm size */ - IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */ - IFLA_INET6_TOKEN, /* device token */ -+ IFLA_INET6_ADDR_GEN_MODE, /* implicit address generator mode */ - __IFLA_INET6_MAX - }; - - #define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) - -+enum in6_addr_gen_mode { -+ IN6_ADDR_GEN_MODE_EUI64, -+ IN6_ADDR_GEN_MODE_NONE, -+ IN6_ADDR_GEN_MODE_STABLE_PRIVACY, -+}; -+ -+/* Bridge section */ -+ -+enum { -+ IFLA_BR_UNSPEC, -+ IFLA_BR_FORWARD_DELAY, -+ IFLA_BR_HELLO_TIME, -+ IFLA_BR_MAX_AGE, -+ IFLA_BR_AGEING_TIME, -+ IFLA_BR_STP_STATE, -+ IFLA_BR_PRIORITY, -+ __IFLA_BR_MAX, -+}; -+ -+#define IFLA_BR_MAX (__IFLA_BR_MAX - 1) -+ - enum { - BRIDGE_MODE_UNSPEC, - BRIDGE_MODE_HAIRPIN, -@@ -219,6 +246,11 @@ enum { - IFLA_BRPORT_GUARD, /* bpdu guard */ - IFLA_BRPORT_PROTECT, /* root port protection */ - IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ -+ IFLA_BRPORT_LEARNING, /* mac learning */ -+ IFLA_BRPORT_UNICAST_FLOOD, /* flood unicast traffic */ -+ IFLA_BRPORT_PROXYARP, /* proxy ARP */ -+ IFLA_BRPORT_LEARNING_SYNC, /* mac learning sync from device */ -+ IFLA_BRPORT_PROXYARP_WIFI, /* proxy ARP for Wi-Fi */ - __IFLA_BRPORT_MAX - }; - #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) -@@ -235,6 +267,8 @@ enum { - IFLA_INFO_KIND, - IFLA_INFO_DATA, - IFLA_INFO_XSTATS, -+ IFLA_INFO_SLAVE_KIND, -+ IFLA_INFO_SLAVE_DATA, - __IFLA_INFO_MAX, - }; - -@@ -277,6 +311,10 @@ enum { - IFLA_MACVLAN_UNSPEC, - IFLA_MACVLAN_MODE, - IFLA_MACVLAN_FLAGS, -+ IFLA_MACVLAN_MACADDR_MODE, -+ IFLA_MACVLAN_MACADDR, -+ IFLA_MACVLAN_MACADDR_DATA, -+ IFLA_MACVLAN_MACADDR_COUNT, - __IFLA_MACVLAN_MAX, - }; - -@@ -287,10 +325,33 @@ enum macvlan_mode { - MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */ - MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */ - MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */ -+ MACVLAN_MODE_SOURCE = 16,/* use source MAC address list to assign */ -+}; -+ -+enum macvlan_macaddr_mode { -+ MACVLAN_MACADDR_ADD, -+ MACVLAN_MACADDR_DEL, -+ MACVLAN_MACADDR_FLUSH, -+ MACVLAN_MACADDR_SET, - }; - - #define MACVLAN_FLAG_NOPROMISC 1 - -+/* IPVLAN section */ -+enum { -+ IFLA_IPVLAN_UNSPEC, -+ IFLA_IPVLAN_MODE, -+ __IFLA_IPVLAN_MAX -+}; -+ -+#define IFLA_IPVLAN_MAX (__IFLA_IPVLAN_MAX - 1) -+ -+enum ipvlan_mode { -+ IPVLAN_MODE_L2 = 0, -+ IPVLAN_MODE_L3, -+ IPVLAN_MODE_MAX -+}; -+ - /* VXLAN section */ - enum { - IFLA_VXLAN_UNSPEC, -@@ -309,6 +370,15 @@ enum { - IFLA_VXLAN_L2MISS, - IFLA_VXLAN_L3MISS, - IFLA_VXLAN_PORT, /* destination port */ -+ IFLA_VXLAN_GROUP6, -+ IFLA_VXLAN_LOCAL6, -+ IFLA_VXLAN_UDP_CSUM, -+ IFLA_VXLAN_UDP_ZERO_CSUM6_TX, -+ IFLA_VXLAN_UDP_ZERO_CSUM6_RX, -+ IFLA_VXLAN_REMCSUM_TX, -+ IFLA_VXLAN_REMCSUM_RX, -+ IFLA_VXLAN_GBP, -+ IFLA_VXLAN_REMCSUM_NOPARTIAL, - __IFLA_VXLAN_MAX - }; - #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) -@@ -318,6 +388,63 @@ struct ifla_vxlan_port_range { - __be16 high; - }; - -+/* Bonding section */ -+ -+enum { -+ IFLA_BOND_UNSPEC, -+ IFLA_BOND_MODE, -+ IFLA_BOND_ACTIVE_SLAVE, -+ IFLA_BOND_MIIMON, -+ IFLA_BOND_UPDELAY, -+ IFLA_BOND_DOWNDELAY, -+ IFLA_BOND_USE_CARRIER, -+ IFLA_BOND_ARP_INTERVAL, -+ IFLA_BOND_ARP_IP_TARGET, -+ IFLA_BOND_ARP_VALIDATE, -+ IFLA_BOND_ARP_ALL_TARGETS, -+ IFLA_BOND_PRIMARY, -+ IFLA_BOND_PRIMARY_RESELECT, -+ IFLA_BOND_FAIL_OVER_MAC, -+ IFLA_BOND_XMIT_HASH_POLICY, -+ IFLA_BOND_RESEND_IGMP, -+ IFLA_BOND_NUM_PEER_NOTIF, -+ IFLA_BOND_ALL_SLAVES_ACTIVE, -+ IFLA_BOND_MIN_LINKS, -+ IFLA_BOND_LP_INTERVAL, -+ IFLA_BOND_PACKETS_PER_SLAVE, -+ IFLA_BOND_AD_LACP_RATE, -+ IFLA_BOND_AD_SELECT, -+ IFLA_BOND_AD_INFO, -+ __IFLA_BOND_MAX, -+}; -+ -+#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1) -+ -+enum { -+ IFLA_BOND_AD_INFO_UNSPEC, -+ IFLA_BOND_AD_INFO_AGGREGATOR, -+ IFLA_BOND_AD_INFO_NUM_PORTS, -+ IFLA_BOND_AD_INFO_ACTOR_KEY, -+ IFLA_BOND_AD_INFO_PARTNER_KEY, -+ IFLA_BOND_AD_INFO_PARTNER_MAC, -+ __IFLA_BOND_AD_INFO_MAX, -+}; -+ -+#define IFLA_BOND_AD_INFO_MAX (__IFLA_BOND_AD_INFO_MAX - 1) -+ -+enum { -+ IFLA_BOND_SLAVE_UNSPEC, -+ IFLA_BOND_SLAVE_STATE, -+ IFLA_BOND_SLAVE_MII_STATUS, -+ IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, -+ IFLA_BOND_SLAVE_PERM_HWADDR, -+ IFLA_BOND_SLAVE_QUEUE_ID, -+ IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, -+ __IFLA_BOND_SLAVE_MAX, -+}; -+ -+#define IFLA_BOND_SLAVE_MAX (__IFLA_BOND_SLAVE_MAX - 1) -+ - /* SR-IOV virtual function management section */ - - enum { -@@ -332,8 +459,13 @@ enum { - IFLA_VF_UNSPEC, - IFLA_VF_MAC, /* Hardware queue specific attributes */ - IFLA_VF_VLAN, -- IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */ -+ IFLA_VF_TX_RATE, /* Max TX Bandwidth Allocation */ - IFLA_VF_SPOOFCHK, /* Spoof Checking on/off switch */ -+ IFLA_VF_LINK_STATE, /* link state enable/disable/auto switch */ -+ IFLA_VF_RATE, /* Min and Max TX Bandwidth Allocation */ -+ IFLA_VF_RSS_QUERY_EN, /* RSS Redirection Table and Hash Key query -+ * on/off switch -+ */ - __IFLA_VF_MAX, - }; - -@@ -355,11 +487,34 @@ struct ifla_vf_tx_rate { - __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ - }; - -+struct ifla_vf_rate { -+ __u32 vf; -+ __u32 min_tx_rate; /* Min Bandwidth in Mbps */ -+ __u32 max_tx_rate; /* Max Bandwidth in Mbps */ -+}; -+ - struct ifla_vf_spoofchk { - __u32 vf; - __u32 setting; - }; - -+enum { -+ IFLA_VF_LINK_STATE_AUTO, /* link state of the uplink */ -+ IFLA_VF_LINK_STATE_ENABLE, /* link always up */ -+ IFLA_VF_LINK_STATE_DISABLE, /* link always down */ -+ __IFLA_VF_LINK_STATE_MAX, -+}; -+ -+struct ifla_vf_link_state { -+ __u32 vf; -+ __u32 link_state; -+}; -+ -+struct ifla_vf_rss_query_en { -+ __u32 vf; -+ __u32 setting; -+}; -+ - /* VF ports management section - * - * Nested layout of set/get msg is: -@@ -450,4 +605,19 @@ enum { - - #define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) - -+ -+/* HSR section */ -+ -+enum { -+ IFLA_HSR_UNSPEC, -+ IFLA_HSR_SLAVE1, -+ IFLA_HSR_SLAVE2, -+ IFLA_HSR_MULTICAST_SPEC, /* Last byte of supervision addr */ -+ IFLA_HSR_SUPERVISION_ADDR, /* Supervision frame multicast addr */ -+ IFLA_HSR_SEQ_NR, -+ __IFLA_HSR_MAX, -+}; -+ -+#define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1) -+ - #endif /* _LINUX_IF_LINK_H */ -diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h -index dffb192..ffee583 100644 ---- a/include/linux/if_tun.h -+++ b/include/linux/if_tun.h -@@ -22,21 +22,11 @@ - - /* Read queue size */ - #define TUN_READQ_SIZE 500 -- --/* TUN device flags */ --#define TUN_TUN_DEV 0x0001 --#define TUN_TAP_DEV 0x0002 -+/* TUN device type flags: deprecated. Use IFF_TUN/IFF_TAP instead. */ -+#define TUN_TUN_DEV IFF_TUN -+#define TUN_TAP_DEV IFF_TAP - #define TUN_TYPE_MASK 0x000f - --#define TUN_FASYNC 0x0010 --#define TUN_NOCHECKSUM 0x0020 --#define TUN_NO_PI 0x0040 --/* This flag has no real effect */ --#define TUN_ONE_QUEUE 0x0080 --#define TUN_PERSIST 0x0100 --#define TUN_VNET_HDR 0x0200 --#define TUN_TAP_MQ 0x0400 -- - /* Ioctl defines */ - #define TUNSETNOCSUM _IOW('T', 200, int) - #define TUNSETDEBUG _IOW('T', 201, int) -@@ -56,6 +46,10 @@ - #define TUNGETVNETHDRSZ _IOR('T', 215, int) - #define TUNSETVNETHDRSZ _IOW('T', 216, int) - #define TUNSETQUEUE _IOW('T', 217, int) -+#define TUNSETIFINDEX _IOW('T', 218, unsigned int) -+#define TUNGETFILTER _IOR('T', 219, struct sock_fprog) -+#define TUNSETVNETLE _IOW('T', 220, int) -+#define TUNGETVNETLE _IOR('T', 221, int) - - /* TUNSETIFF ifr flags */ - #define IFF_TUN 0x0001 -@@ -68,6 +62,12 @@ - #define IFF_MULTI_QUEUE 0x0100 - #define IFF_ATTACH_QUEUE 0x0200 - #define IFF_DETACH_QUEUE 0x0400 -+/* read-only flag */ -+#define IFF_PERSIST 0x0800 -+#define IFF_NOFILTER 0x1000 -+ -+/* Socket options */ -+#define TUN_TX_TIMESTAMP 1 - - /* Features for GSO (TUNSETOFFLOAD). */ - #define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */ -diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h -index 9f471ca..102ce7a 100644 ---- a/include/linux/if_tunnel.h -+++ b/include/linux/if_tunnel.h -@@ -53,10 +53,24 @@ enum { - IFLA_IPTUN_6RD_RELAY_PREFIX, - IFLA_IPTUN_6RD_PREFIXLEN, - IFLA_IPTUN_6RD_RELAY_PREFIXLEN, -+ IFLA_IPTUN_ENCAP_TYPE, -+ IFLA_IPTUN_ENCAP_FLAGS, -+ IFLA_IPTUN_ENCAP_SPORT, -+ IFLA_IPTUN_ENCAP_DPORT, - __IFLA_IPTUN_MAX, - }; - #define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) - -+enum tunnel_encap_types { -+ TUNNEL_ENCAP_NONE, -+ TUNNEL_ENCAP_FOU, -+ TUNNEL_ENCAP_GUE, -+}; -+ -+#define TUNNEL_ENCAP_FLAG_CSUM (1<<0) -+#define TUNNEL_ENCAP_FLAG_CSUM6 (1<<1) -+#define TUNNEL_ENCAP_FLAG_REMCSUM (1<<2) -+ - /* SIT-mode i_flags */ - #define SIT_ISATAP 0x0001 - -@@ -94,13 +108,17 @@ enum { - IFLA_GRE_ENCAP_LIMIT, - IFLA_GRE_FLOWINFO, - IFLA_GRE_FLAGS, -+ IFLA_GRE_ENCAP_TYPE, -+ IFLA_GRE_ENCAP_FLAGS, -+ IFLA_GRE_ENCAP_SPORT, -+ IFLA_GRE_ENCAP_DPORT, - __IFLA_GRE_MAX, - }; - - #define IFLA_GRE_MAX (__IFLA_GRE_MAX - 1) - - /* VTI-mode i_flags */ --#define VTI_ISVTI 0x0001 -+#define VTI_ISVTI ((__be16)0x0001) - - enum { - IFLA_VTI_UNSPEC, -diff --git a/include/linux/in6.h b/include/linux/in6.h -new file mode 100644 -index 0000000..994f4c2 ---- /dev/null -+++ b/include/linux/in6.h -@@ -0,0 +1,293 @@ -+/* -+ * Types and definitions for AF_INET6 -+ * Linux INET6 implementation -+ * -+ * Authors: -+ * Pedro Roque <roque@di.fc.ul.pt> -+ * -+ * Sources: -+ * IPv6 Program Interfaces for BSD Systems -+ * <draft-ietf-ipngwg-bsd-api-05.txt> -+ * -+ * Advanced Sockets API for IPv6 -+ * <draft-stevens-advanced-api-00.txt> -+ * -+ * 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_IN6_H -+#define _LINUX_IN6_H -+ -+#include <linux/types.h> -+#include <linux/libc-compat.h> -+ -+/* -+ * IPv6 address structure -+ */ -+ -+#if __UAPI_DEF_IN6_ADDR -+struct in6_addr { -+ union { -+ __u8 u6_addr8[16]; -+#if __UAPI_DEF_IN6_ADDR_ALT -+ __be16 u6_addr16[8]; -+ __be32 u6_addr32[4]; -+#endif -+ } in6_u; -+#define s6_addr in6_u.u6_addr8 -+#if __UAPI_DEF_IN6_ADDR_ALT -+#define s6_addr16 in6_u.u6_addr16 -+#define s6_addr32 in6_u.u6_addr32 -+#endif -+}; -+#endif /* __UAPI_DEF_IN6_ADDR */ -+ -+#if __UAPI_DEF_SOCKADDR_IN6 -+struct sockaddr_in6 { -+ unsigned short int sin6_family; /* AF_INET6 */ -+ __be16 sin6_port; /* Transport layer port # */ -+ __be32 sin6_flowinfo; /* IPv6 flow information */ -+ struct in6_addr sin6_addr; /* IPv6 address */ -+ __u32 sin6_scope_id; /* scope id (new in RFC2553) */ -+}; -+#endif /* __UAPI_DEF_SOCKADDR_IN6 */ -+ -+#if __UAPI_DEF_IPV6_MREQ -+struct ipv6_mreq { -+ /* IPv6 multicast address of group */ -+ struct in6_addr ipv6mr_multiaddr; -+ -+ /* local IPv6 address of interface */ -+ int ipv6mr_ifindex; -+}; -+#endif /* __UAPI_DEF_IVP6_MREQ */ -+ -+#define ipv6mr_acaddr ipv6mr_multiaddr -+ -+struct in6_flowlabel_req { -+ struct in6_addr flr_dst; -+ __be32 flr_label; -+ __u8 flr_action; -+ __u8 flr_share; -+ __u16 flr_flags; -+ __u16 flr_expires; -+ __u16 flr_linger; -+ __u32 __flr_pad; -+ /* Options in format of IPV6_PKTOPTIONS */ -+}; -+ -+#define IPV6_FL_A_GET 0 -+#define IPV6_FL_A_PUT 1 -+#define IPV6_FL_A_RENEW 2 -+ -+#define IPV6_FL_F_CREATE 1 -+#define IPV6_FL_F_EXCL 2 -+#define IPV6_FL_F_REFLECT 4 -+#define IPV6_FL_F_REMOTE 8 -+ -+#define IPV6_FL_S_NONE 0 -+#define IPV6_FL_S_EXCL 1 -+#define IPV6_FL_S_PROCESS 2 -+#define IPV6_FL_S_USER 3 -+#define IPV6_FL_S_ANY 255 -+ -+ -+/* -+ * Bitmask constant declarations to help applications select out the -+ * flow label and priority fields. -+ * -+ * Note that this are in host byte order while the flowinfo field of -+ * sockaddr_in6 is in network byte order. -+ */ -+ -+#define IPV6_FLOWINFO_FLOWLABEL 0x000fffff -+#define IPV6_FLOWINFO_PRIORITY 0x0ff00000 -+ -+/* These definitions are obsolete */ -+#define IPV6_PRIORITY_UNCHARACTERIZED 0x0000 -+#define IPV6_PRIORITY_FILLER 0x0100 -+#define IPV6_PRIORITY_UNATTENDED 0x0200 -+#define IPV6_PRIORITY_RESERVED1 0x0300 -+#define IPV6_PRIORITY_BULK 0x0400 -+#define IPV6_PRIORITY_RESERVED2 0x0500 -+#define IPV6_PRIORITY_INTERACTIVE 0x0600 -+#define IPV6_PRIORITY_CONTROL 0x0700 -+#define IPV6_PRIORITY_8 0x0800 -+#define IPV6_PRIORITY_9 0x0900 -+#define IPV6_PRIORITY_10 0x0a00 -+#define IPV6_PRIORITY_11 0x0b00 -+#define IPV6_PRIORITY_12 0x0c00 -+#define IPV6_PRIORITY_13 0x0d00 -+#define IPV6_PRIORITY_14 0x0e00 -+#define IPV6_PRIORITY_15 0x0f00 -+ -+/* -+ * IPV6 extension headers -+ */ -+#if __UAPI_DEF_IPPROTO_V6 -+#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */ -+#define IPPROTO_ROUTING 43 /* IPv6 routing header */ -+#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */ -+#define IPPROTO_ICMPV6 58 /* ICMPv6 */ -+#define IPPROTO_NONE 59 /* IPv6 no next header */ -+#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ -+#define IPPROTO_MH 135 /* IPv6 mobility header */ -+#endif /* __UAPI_DEF_IPPROTO_V6 */ -+ -+/* -+ * IPv6 TLV options. -+ */ -+#define IPV6_TLV_PAD1 0 -+#define IPV6_TLV_PADN 1 -+#define IPV6_TLV_ROUTERALERT 5 -+#define IPV6_TLV_JUMBO 194 -+#define IPV6_TLV_HAO 201 /* home address option */ -+ -+/* -+ * IPV6 socket options -+ */ -+#if __UAPI_DEF_IPV6_OPTIONS -+#define IPV6_ADDRFORM 1 -+#define IPV6_2292PKTINFO 2 -+#define IPV6_2292HOPOPTS 3 -+#define IPV6_2292DSTOPTS 4 -+#define IPV6_2292RTHDR 5 -+#define IPV6_2292PKTOPTIONS 6 -+#define IPV6_CHECKSUM 7 -+#define IPV6_2292HOPLIMIT 8 -+#define IPV6_NEXTHOP 9 -+#define IPV6_AUTHHDR 10 /* obsolete */ -+#define IPV6_FLOWINFO 11 -+ -+#define IPV6_UNICAST_HOPS 16 -+#define IPV6_MULTICAST_IF 17 -+#define IPV6_MULTICAST_HOPS 18 -+#define IPV6_MULTICAST_LOOP 19 -+#define IPV6_ADD_MEMBERSHIP 20 -+#define IPV6_DROP_MEMBERSHIP 21 -+#define IPV6_ROUTER_ALERT 22 -+#define IPV6_MTU_DISCOVER 23 -+#define IPV6_MTU 24 -+#define IPV6_RECVERR 25 -+#define IPV6_V6ONLY 26 -+#define IPV6_JOIN_ANYCAST 27 -+#define IPV6_LEAVE_ANYCAST 28 -+ -+/* IPV6_MTU_DISCOVER values */ -+#define IPV6_PMTUDISC_DONT 0 -+#define IPV6_PMTUDISC_WANT 1 -+#define IPV6_PMTUDISC_DO 2 -+#define IPV6_PMTUDISC_PROBE 3 -+/* same as IPV6_PMTUDISC_PROBE, provided for symetry with IPv4 -+ * also see comments on IP_PMTUDISC_INTERFACE -+ */ -+#define IPV6_PMTUDISC_INTERFACE 4 -+/* weaker version of IPV6_PMTUDISC_INTERFACE, which allows packets to -+ * get fragmented if they exceed the interface mtu -+ */ -+#define IPV6_PMTUDISC_OMIT 5 -+ -+/* Flowlabel */ -+#define IPV6_FLOWLABEL_MGR 32 -+#define IPV6_FLOWINFO_SEND 33 -+ -+#define IPV6_IPSEC_POLICY 34 -+#define IPV6_XFRM_POLICY 35 -+#endif -+ -+/* -+ * Multicast: -+ * Following socket options are shared between IPv4 and IPv6. -+ * -+ * MCAST_JOIN_GROUP 42 -+ * MCAST_BLOCK_SOURCE 43 -+ * MCAST_UNBLOCK_SOURCE 44 -+ * MCAST_LEAVE_GROUP 45 -+ * MCAST_JOIN_SOURCE_GROUP 46 -+ * MCAST_LEAVE_SOURCE_GROUP 47 -+ * MCAST_MSFILTER 48 -+ */ -+ -+/* -+ * Advanced API (RFC3542) (1) -+ * -+ * Note: IPV6_RECVRTHDRDSTOPTS does not exist. see net/ipv6/datagram.c. -+ */ -+ -+#define IPV6_RECVPKTINFO 49 -+#define IPV6_PKTINFO 50 -+#define IPV6_RECVHOPLIMIT 51 -+#define IPV6_HOPLIMIT 52 -+#define IPV6_RECVHOPOPTS 53 -+#define IPV6_HOPOPTS 54 -+#define IPV6_RTHDRDSTOPTS 55 -+#define IPV6_RECVRTHDR 56 -+#define IPV6_RTHDR 57 -+#define IPV6_RECVDSTOPTS 58 -+#define IPV6_DSTOPTS 59 -+#define IPV6_RECVPATHMTU 60 -+#define IPV6_PATHMTU 61 -+#define IPV6_DONTFRAG 62 -+#if 0 /* not yet */ -+#define IPV6_USE_MIN_MTU 63 -+#endif -+ -+/* -+ * Netfilter (1) -+ * -+ * Following socket options are used in ip6_tables; -+ * see include/linux/netfilter_ipv6/ip6_tables.h. -+ * -+ * IP6T_SO_SET_REPLACE / IP6T_SO_GET_INFO 64 -+ * IP6T_SO_SET_ADD_COUNTERS / IP6T_SO_GET_ENTRIES 65 -+ */ -+ -+/* -+ * Advanced API (RFC3542) (2) -+ */ -+#define IPV6_RECVTCLASS 66 -+#define IPV6_TCLASS 67 -+ -+/* -+ * Netfilter (2) -+ * -+ * Following socket options are used in ip6_tables; -+ * see include/linux/netfilter_ipv6/ip6_tables.h. -+ * -+ * IP6T_SO_GET_REVISION_MATCH 68 -+ * IP6T_SO_GET_REVISION_TARGET 69 -+ * IP6T_SO_ORIGINAL_DST 80 -+ */ -+ -+#define IPV6_AUTOFLOWLABEL 70 -+/* RFC5014: Source address selection */ -+#define IPV6_ADDR_PREFERENCES 72 -+ -+#define IPV6_PREFER_SRC_TMP 0x0001 -+#define IPV6_PREFER_SRC_PUBLIC 0x0002 -+#define IPV6_PREFER_SRC_PUBTMP_DEFAULT 0x0100 -+#define IPV6_PREFER_SRC_COA 0x0004 -+#define IPV6_PREFER_SRC_HOME 0x0400 -+#define IPV6_PREFER_SRC_CGA 0x0008 -+#define IPV6_PREFER_SRC_NONCGA 0x0800 -+ -+/* RFC5082: Generalized Ttl Security Mechanism */ -+#define IPV6_MINHOPCOUNT 73 -+ -+#define IPV6_ORIGDSTADDR 74 -+#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR -+#define IPV6_TRANSPARENT 75 -+#define IPV6_UNICAST_IF 76 -+ -+/* -+ * Multicast Routing: -+ * see include/uapi/linux/mroute6.h. -+ * -+ * MRT6_BASE 200 -+ * ... -+ * MRT6_MAX -+ */ -+#endif /* _LINUX_IN6_H */ -diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h -index e34f247..7438dad 100644 ---- a/include/linux/inet_diag.h -+++ b/include/linux/inet_diag.h -@@ -110,10 +110,10 @@ enum { - INET_DIAG_TCLASS, - INET_DIAG_SKMEMINFO, - INET_DIAG_SHUTDOWN, -+ INET_DIAG_DCTCPINFO, - }; - --#define INET_DIAG_MAX INET_DIAG_SHUTDOWN -- -+#define INET_DIAG_MAX INET_DIAG_DCTCPINFO - - /* INET_DIAG_MEM */ - -@@ -133,5 +133,14 @@ struct tcpvegas_info { - __u32 tcpv_minrtt; - }; - -+/* INET_DIAG_DCTCPINFO */ -+ -+struct tcp_dctcp_info { -+ __u16 dctcp_enabled; -+ __u16 dctcp_ce_state; -+ __u32 dctcp_alpha; -+ __u32 dctcp_ab_ecn; -+ __u32 dctcp_ab_tot; -+}; - - #endif /* _INET_DIAG_H_ */ -diff --git a/include/linux/l2tp.h b/include/linux/l2tp.h -index c4bec82..5b0e36d 100644 ---- a/include/linux/l2tp.h -+++ b/include/linux/l2tp.h -@@ -122,6 +122,8 @@ enum { - L2TP_ATTR_STATS, /* nested */ - L2TP_ATTR_IP6_SADDR, /* struct in6_addr */ - L2TP_ATTR_IP6_DADDR, /* struct in6_addr */ -+ L2TP_ATTR_UDP_ZERO_CSUM6_TX, /* u8 */ -+ L2TP_ATTR_UDP_ZERO_CSUM6_RX, /* u8 */ - __L2TP_ATTR_MAX, - }; - -@@ -174,5 +176,6 @@ enum l2tp_seqmode { - */ - #define L2TP_GENL_NAME "l2tp" - #define L2TP_GENL_VERSION 0x1 -+#define L2TP_GENL_MCGROUP "l2tp" - - #endif /* _LINUX_L2TP_H_ */ -diff --git a/include/linux/libc-compat.h b/include/linux/libc-compat.h -new file mode 100644 -index 0000000..990332e ---- /dev/null -+++ b/include/linux/libc-compat.h -@@ -0,0 +1,121 @@ -+/* -+ * Compatibility interface for userspace libc header coordination: -+ * -+ * Define compatibility macros that are used to control the inclusion or -+ * exclusion of UAPI structures and definitions in coordination with another -+ * userspace C library. -+ * -+ * This header is intended to solve the problem of UAPI definitions that -+ * conflict with userspace definitions. If a UAPI header has such conflicting -+ * definitions then the solution is as follows: -+ * -+ * * Synchronize the UAPI header and the libc headers so either one can be -+ * used and such that the ABI is preserved. If this is not possible then -+ * no simple compatibility interface exists (you need to write translating -+ * wrappers and rename things) and you can't use this interface. -+ * -+ * Then follow this process: -+ * -+ * (a) Include libc-compat.h in the UAPI header. -+ * e.g. #include <linux/libc-compat.h> -+ * This include must be as early as possible. -+ * -+ * (b) In libc-compat.h add enough code to detect that the comflicting -+ * userspace libc header has been included first. -+ * -+ * (c) If the userspace libc header has been included first define a set of -+ * guard macros of the form __UAPI_DEF_FOO and set their values to 1, else -+ * set their values to 0. -+ * -+ * (d) Back in the UAPI header with the conflicting definitions, guard the -+ * definitions with: -+ * #if __UAPI_DEF_FOO -+ * ... -+ * #endif -+ * -+ * This fixes the situation where the linux headers are included *after* the -+ * libc headers. To fix the problem with the inclusion in the other order the -+ * userspace libc headers must be fixed like this: -+ * -+ * * For all definitions that conflict with kernel definitions wrap those -+ * defines in the following: -+ * #if !__UAPI_DEF_FOO -+ * ... -+ * #endif -+ * -+ * This prevents the redefinition of a construct already defined by the kernel. -+ */ -+#ifndef _LIBC_COMPAT_H -+#define _LIBC_COMPAT_H -+ -+/* We have included glibc headers... */ -+#if defined(__GLIBC__) -+ -+/* Coordinate with glibc netinet/in.h header. */ -+#if defined(_NETINET_IN_H) -+ -+/* GLIBC headers included first so don't define anything -+ * that would already be defined. */ -+#define __UAPI_DEF_IN6_ADDR 0 -+/* The exception is the in6_addr macros which must be defined -+ * if the glibc code didn't define them. This guard matches -+ * the guard in glibc/inet/netinet/in.h which defines the -+ * additional in6_addr macros e.g. s6_addr16, and s6_addr32. */ -+#if defined(__USE_MISC) || defined (__USE_GNU) -+#define __UAPI_DEF_IN6_ADDR_ALT 0 -+#else -+#define __UAPI_DEF_IN6_ADDR_ALT 1 -+#endif -+#define __UAPI_DEF_SOCKADDR_IN6 0 -+#define __UAPI_DEF_IPV6_MREQ 0 -+#define __UAPI_DEF_IPPROTO_V6 0 -+#define __UAPI_DEF_IPV6_OPTIONS 0 -+#define __UAPI_DEF_IN6_PKTINFO 0 -+#define __UAPI_DEF_IP6_MTUINFO 0 -+ -+#else -+ -+/* Linux headers included first, and we must define everything -+ * we need. The expectation is that glibc will check the -+ * __UAPI_DEF_* defines and adjust appropriately. */ -+#define __UAPI_DEF_IN6_ADDR 1 -+/* We unconditionally define the in6_addr macros and glibc must -+ * coordinate. */ -+#define __UAPI_DEF_IN6_ADDR_ALT 1 -+#define __UAPI_DEF_SOCKADDR_IN6 1 -+#define __UAPI_DEF_IPV6_MREQ 1 -+#define __UAPI_DEF_IPPROTO_V6 1 -+#define __UAPI_DEF_IPV6_OPTIONS 1 -+#define __UAPI_DEF_IN6_PKTINFO 1 -+#define __UAPI_DEF_IP6_MTUINFO 1 -+ -+#endif /* _NETINET_IN_H */ -+ -+/* Definitions for xattr.h */ -+#if defined(_SYS_XATTR_H) -+#define __UAPI_DEF_XATTR 0 -+#else -+#define __UAPI_DEF_XATTR 1 -+#endif -+ -+/* If we did not see any headers from any supported C libraries, -+ * or we are being included in the kernel, then define everything -+ * that we need. */ -+#else /* !defined(__GLIBC__) */ -+ -+/* Definitions for in6.h */ -+#define __UAPI_DEF_IN6_ADDR 1 -+#define __UAPI_DEF_IN6_ADDR_ALT 1 -+#define __UAPI_DEF_SOCKADDR_IN6 1 -+#define __UAPI_DEF_IPV6_MREQ 1 -+#define __UAPI_DEF_IPPROTO_V6 1 -+#define __UAPI_DEF_IPV6_OPTIONS 1 -+#define __UAPI_DEF_IN6_PKTINFO 1 -+#define __UAPI_DEF_IP6_MTUINFO 1 -+ -+/* Definitions for xattr.h */ -+#define __UAPI_DEF_XATTR 1 -+ -+#endif /* __GLIBC__ */ -+ -+#endif /* _LIBC_COMPAT_H */ -diff --git a/include/linux/mpls.h b/include/linux/mpls.h -new file mode 100644 -index 0000000..0893902 ---- /dev/null -+++ b/include/linux/mpls.h -@@ -0,0 +1,34 @@ -+#ifndef _MPLS_H -+#define _MPLS_H -+ -+#include <linux/types.h> -+#include <asm/byteorder.h> -+ -+/* Reference: RFC 5462, RFC 3032 -+ * -+ * 0 1 2 3 -+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+ * | Label | TC |S| TTL | -+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+ * -+ * Label: Label Value, 20 bits -+ * TC: Traffic Class field, 3 bits -+ * S: Bottom of Stack, 1 bit -+ * TTL: Time to Live, 8 bits -+ */ -+ -+struct mpls_label { -+ __be32 entry; -+}; -+ -+#define MPLS_LS_LABEL_MASK 0xFFFFF000 -+#define MPLS_LS_LABEL_SHIFT 12 -+#define MPLS_LS_TC_MASK 0x00000E00 -+#define MPLS_LS_TC_SHIFT 9 -+#define MPLS_LS_S_MASK 0x00000100 -+#define MPLS_LS_S_SHIFT 8 -+#define MPLS_LS_TTL_MASK 0x000000FF -+#define MPLS_LS_TTL_SHIFT 0 -+ -+#endif /* _MPLS_H */ -diff --git a/include/linux/neighbour.h b/include/linux/neighbour.h -index f175212..2e35c61 100644 ---- a/include/linux/neighbour.h -+++ b/include/linux/neighbour.h -@@ -24,6 +24,8 @@ enum { - NDA_PORT, - NDA_VNI, - NDA_IFINDEX, -+ NDA_MASTER, -+ NDA_LINK_NETNSID, - __NDA_MAX - }; - -@@ -34,11 +36,11 @@ enum { - */ - - #define NTF_USE 0x01 --#define NTF_PROXY 0x08 /* == ATF_PUBL */ --#define NTF_ROUTER 0x80 -- - #define NTF_SELF 0x02 - #define NTF_MASTER 0x04 -+#define NTF_PROXY 0x08 /* == ATF_PUBL */ -+#define NTF_EXT_LEARNED 0x10 -+#define NTF_ROUTER 0x80 - - /* - * Neighbor Cache Entry States. -@@ -58,7 +60,7 @@ enum { - - /* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change - and make no address resolution or NUD. -- NUD_PERMANENT is also cannot be deleted by garbage collectors. -+ NUD_PERMANENT also cannot be deleted by garbage collectors. - */ - - struct nda_cacheinfo { -@@ -124,6 +126,7 @@ enum { - NDTPA_PROXY_QLEN, /* u32 */ - NDTPA_LOCKTIME, /* u64, msecs */ - NDTPA_QUEUE_LENBYTES, /* u32 */ -+ NDTPA_MCAST_REPROBES, /* u32 */ - __NDTPA_MAX - }; - #define NDTPA_MAX (__NDTPA_MAX - 1) -diff --git a/include/linux/net_namespace.h b/include/linux/net_namespace.h -new file mode 100644 -index 0000000..9a92b7e ---- /dev/null -+++ b/include/linux/net_namespace.h -@@ -0,0 +1,23 @@ -+/* Copyright (c) 2015 6WIND S.A. -+ * Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ */ -+#ifndef _LINUX_NET_NAMESPACE_H_ -+#define _LINUX_NET_NAMESPACE_H_ -+ -+/* Attributes of RTM_NEWNSID/RTM_GETNSID messages */ -+enum { -+ NETNSA_NONE, -+#define NETNSA_NSID_NOT_ASSIGNED -1 -+ NETNSA_NSID, -+ NETNSA_PID, -+ NETNSA_FD, -+ __NETNSA_MAX, -+}; -+ -+#define NETNSA_MAX (__NETNSA_MAX - 1) -+ -+#endif /* _LINUX_NET_NAMESPACE_H_ */ -diff --git a/include/linux/netconf.h b/include/linux/netconf.h -index 52c4424..6ceb170 100644 ---- a/include/linux/netconf.h -+++ b/include/linux/netconf.h -@@ -14,6 +14,7 @@ enum { - NETCONFA_FORWARDING, - NETCONFA_RP_FILTER, - NETCONFA_MC_FORWARDING, -+ NETCONFA_PROXY_NEIGH, - __NETCONFA_MAX - }; - #define NETCONFA_MAX (__NETCONFA_MAX - 1) -diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h -index adc7260..66fceb4 100644 ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -37,6 +37,12 @@ - #define INIT_NETDEV_GROUP 0 - - -+/* interface name assignment types (sysfs name_assign_type attribute) */ -+#define NET_NAME_UNKNOWN 0 /* unknown origin (not exposed to userspace) */ -+#define NET_NAME_ENUM 1 /* enumerated by kernel */ -+#define NET_NAME_PREDICTABLE 2 /* predictably named by the kernel */ -+#define NET_NAME_USER 3 /* provided by user-space */ -+#define NET_NAME_RENAMED 4 /* renamed by user-space */ - - /* Media selection options. */ - enum { -@@ -49,5 +55,11 @@ enum { - IF_PORT_100BASEFX - }; - -+/* hardware address assignment types */ -+#define NET_ADDR_PERM 0 /* address is permanent (default) */ -+#define NET_ADDR_RANDOM 1 /* address is generated randomly */ -+#define NET_ADDR_STOLEN 2 /* address is stolen from other device */ -+#define NET_ADDR_SET 3 /* address is set using -+ * dev_set_mac_address() */ - - #endif /* _LINUX_NETDEVICE_H */ -diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h -index f05c3d9..be0bc18 100644 ---- a/include/linux/netfilter.h -+++ b/include/linux/netfilter.h -@@ -51,6 +51,7 @@ enum nf_inet_hooks { - - enum { - NFPROTO_UNSPEC = 0, -+ NFPROTO_INET = 1, - NFPROTO_IPV4 = 2, - NFPROTO_ARP = 3, - NFPROTO_BRIDGE = 7, -diff --git a/include/linux/netlink_diag.h b/include/linux/netlink_diag.h -index 4e31db4..f2159d3 100644 ---- a/include/linux/netlink_diag.h -+++ b/include/linux/netlink_diag.h -@@ -33,6 +33,7 @@ struct netlink_diag_ring { - }; - - enum { -+ /* NETLINK_DIAG_NONE, standard nl API requires this attribute! */ - NETLINK_DIAG_MEMINFO, - NETLINK_DIAG_GROUPS, - NETLINK_DIAG_RX_RING, -diff --git a/include/linux/packet_diag.h b/include/linux/packet_diag.h -index b2cc0cd..d08c63f 100644 ---- a/include/linux/packet_diag.h -+++ b/include/linux/packet_diag.h -@@ -29,6 +29,7 @@ struct packet_diag_msg { - }; - - enum { -+ /* PACKET_DIAG_NONE, standard nl API requires this attribute! */ - PACKET_DIAG_INFO, - PACKET_DIAG_MCLIST, - PACKET_DIAG_RX_RING, -diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h -index 082eafa..bf08e76 100644 ---- a/include/linux/pkt_cls.h -+++ b/include/linux/pkt_cls.h -@@ -388,6 +388,22 @@ enum { - - #define TCA_CGROUP_MAX (__TCA_CGROUP_MAX - 1) - -+/* BPF classifier */ -+ -+enum { -+ TCA_BPF_UNSPEC, -+ TCA_BPF_ACT, -+ TCA_BPF_POLICE, -+ TCA_BPF_CLASSID, -+ TCA_BPF_OPS_LEN, -+ TCA_BPF_OPS, -+ TCA_BPF_FD, -+ TCA_BPF_NAME, -+ __TCA_BPF_MAX, -+}; -+ -+#define TCA_BPF_MAX (__TCA_BPF_MAX - 1) -+ - /* Extended Matches */ - - struct tcf_ematch_tree_hdr { -diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h -index dbd71b0..534b847 100644 ---- a/include/linux/pkt_sched.h -+++ b/include/linux/pkt_sched.h -@@ -73,9 +73,17 @@ struct tc_estimator { - #define TC_H_ROOT (0xFFFFFFFFU) - #define TC_H_INGRESS (0xFFFFFFF1U) - -+/* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */ -+enum tc_link_layer { -+ TC_LINKLAYER_UNAWARE, /* Indicate unaware old iproute2 util */ -+ TC_LINKLAYER_ETHERNET, -+ TC_LINKLAYER_ATM, -+}; -+#define TC_LINKLAYER_MASK 0x0F /* limit use to lower 4 bits */ -+ - struct tc_ratespec { - unsigned char cell_log; -- unsigned char __reserved; -+ __u8 linklayer; /* lower 4 bits */ - unsigned short overhead; - short cell_align; - unsigned short mpu; -@@ -163,6 +171,10 @@ enum { - TCA_TBF_PARMS, - TCA_TBF_RTAB, - TCA_TBF_PTAB, -+ TCA_TBF_RATE64, -+ TCA_TBF_PRATE64, -+ TCA_TBF_BURST, -+ TCA_TBF_PBURST, - __TCA_TBF_MAX, - }; - -@@ -349,6 +361,8 @@ enum { - TCA_HTB_CTAB, - TCA_HTB_RTAB, - TCA_HTB_DIRECT_QLEN, -+ TCA_HTB_RATE64, -+ TCA_HTB_CEIL64, - __TCA_HTB_MAX, - }; - -@@ -511,6 +525,7 @@ enum { - TCA_NETEM_LOSS, - TCA_NETEM_RATE, - TCA_NETEM_ECN, -+ TCA_NETEM_RATE64, - __TCA_NETEM_MAX, - }; - -@@ -736,4 +751,98 @@ struct tc_fq_codel_xstats { - }; - }; - -+/* FQ */ -+ -+enum { -+ TCA_FQ_UNSPEC, -+ -+ TCA_FQ_PLIMIT, /* limit of total number of packets in queue */ -+ -+ TCA_FQ_FLOW_PLIMIT, /* limit of packets per flow */ -+ -+ TCA_FQ_QUANTUM, /* RR quantum */ -+ -+ TCA_FQ_INITIAL_QUANTUM, /* RR quantum for new flow */ -+ -+ TCA_FQ_RATE_ENABLE, /* enable/disable rate limiting */ -+ -+ TCA_FQ_FLOW_DEFAULT_RATE,/* obsolete, do not use */ -+ -+ TCA_FQ_FLOW_MAX_RATE, /* per flow max rate */ -+ -+ TCA_FQ_BUCKETS_LOG, /* log2(number of buckets) */ -+ -+ TCA_FQ_FLOW_REFILL_DELAY, /* flow credit refill delay in usec */ -+ -+ TCA_FQ_ORPHAN_MASK, /* mask applied to orphaned skb hashes */ -+ -+ __TCA_FQ_MAX -+}; -+ -+#define TCA_FQ_MAX (__TCA_FQ_MAX - 1) -+ -+struct tc_fq_qd_stats { -+ __u64 gc_flows; -+ __u64 highprio_packets; -+ __u64 tcp_retrans; -+ __u64 throttled; -+ __u64 flows_plimit; -+ __u64 pkts_too_long; -+ __u64 allocation_errors; -+ __s64 time_next_delayed_flow; -+ __u32 flows; -+ __u32 inactive_flows; -+ __u32 throttled_flows; -+ __u32 pad; -+}; -+ -+/* Heavy-Hitter Filter */ -+ -+enum { -+ TCA_HHF_UNSPEC, -+ TCA_HHF_BACKLOG_LIMIT, -+ TCA_HHF_QUANTUM, -+ TCA_HHF_HH_FLOWS_LIMIT, -+ TCA_HHF_RESET_TIMEOUT, -+ TCA_HHF_ADMIT_BYTES, -+ TCA_HHF_EVICT_TIMEOUT, -+ TCA_HHF_NON_HH_WEIGHT, -+ __TCA_HHF_MAX -+}; -+ -+#define TCA_HHF_MAX (__TCA_HHF_MAX - 1) -+ -+struct tc_hhf_xstats { -+ __u32 drop_overlimit; /* number of times max qdisc packet limit -+ * was hit -+ */ -+ __u32 hh_overlimit; /* number of times max heavy-hitters was hit */ -+ __u32 hh_tot_count; /* number of captured heavy-hitters so far */ -+ __u32 hh_cur_count; /* number of current heavy-hitters */ -+}; -+ -+/* PIE */ -+enum { -+ TCA_PIE_UNSPEC, -+ TCA_PIE_TARGET, -+ TCA_PIE_LIMIT, -+ TCA_PIE_TUPDATE, -+ TCA_PIE_ALPHA, -+ TCA_PIE_BETA, -+ TCA_PIE_ECN, -+ TCA_PIE_BYTEMODE, -+ __TCA_PIE_MAX -+}; -+#define TCA_PIE_MAX (__TCA_PIE_MAX - 1) -+ -+struct tc_pie_xstats { -+ __u32 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*/ -+}; - #endif -diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h -index 93370bd..702b19b 100644 ---- a/include/linux/rtnetlink.h -+++ b/include/linux/rtnetlink.h -@@ -132,6 +132,13 @@ enum { - RTM_GETMDB = 86, - #define RTM_GETMDB RTM_GETMDB - -+ RTM_NEWNSID = 88, -+#define RTM_NEWNSID RTM_NEWNSID -+ RTM_DELNSID = 89, -+#define RTM_DELNSID RTM_DELNSID -+ RTM_GETNSID = 90, -+#define RTM_GETNSID RTM_GETNSID -+ - __RTM_MAX, - #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) - }; -@@ -235,6 +242,7 @@ enum { - #define RTPROT_NTK 15 /* Netsukuku */ - #define RTPROT_DHCP 16 /* DHCP client */ - #define RTPROT_MROUTED 17 /* Multicast daemon */ -+#define RTPROT_BABEL 42 /* Babel daemon */ - - /* rtm_scope - -@@ -297,6 +305,9 @@ enum rtattr_type_t { - RTA_TABLE, - RTA_MARK, - RTA_MFC_STATS, -+ RTA_VIA, -+ RTA_NEWDST, -+ RTA_PREF, - __RTA_MAX - }; - -@@ -326,6 +337,7 @@ struct rtnexthop { - #define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */ - #define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */ - #define RTNH_F_ONLINK 4 /* Gateway is forced on link */ -+#define RTNH_F_EXTERNAL 8 /* Route installed externally */ - - /* Macros to handle hexthops */ - -@@ -338,6 +350,12 @@ struct rtnexthop { - #define RTNH_SPACE(len) RTNH_ALIGN(RTNH_LENGTH(len)) - #define RTNH_DATA(rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0))) - -+/* RTA_VIA */ -+struct rtvia { -+ __kernel_sa_family_t rtvia_family; -+ __u8 rtvia_addr[0]; -+}; -+ - /* RTM_CACHEINFO */ - - struct rta_cacheinfo { -@@ -386,6 +404,10 @@ enum { - #define RTAX_RTO_MIN RTAX_RTO_MIN - RTAX_INITRWND, - #define RTAX_INITRWND RTAX_INITRWND -+ RTAX_QUICKACK, -+#define RTAX_QUICKACK RTAX_QUICKACK -+ RTAX_CC_ALGO, -+#define RTAX_CC_ALGO RTAX_CC_ALGO - __RTAX_MAX - }; - -@@ -611,6 +633,10 @@ enum rtnetlink_groups { - #define RTNLGRP_IPV6_NETCONF RTNLGRP_IPV6_NETCONF - RTNLGRP_MDB, - #define RTNLGRP_MDB RTNLGRP_MDB -+ RTNLGRP_MPLS_ROUTE, -+#define RTNLGRP_MPLS_ROUTE RTNLGRP_MPLS_ROUTE -+ RTNLGRP_NSID, -+#define RTNLGRP_NSID RTNLGRP_NSID - __RTNLGRP_MAX - }; - #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) -@@ -629,6 +655,7 @@ struct tcamsg { - /* New extended info filters for IFLA_EXT_MASK */ - #define RTEXT_FILTER_VF (1 << 0) - #define RTEXT_FILTER_BRVLAN (1 << 1) -+#define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2) - - /* End of information exported to user level */ - -diff --git a/include/linux/tc_act/tc_bpf.h b/include/linux/tc_act/tc_bpf.h -new file mode 100644 -index 0000000..07f17cc ---- /dev/null -+++ b/include/linux/tc_act/tc_bpf.h -@@ -0,0 +1,33 @@ -+/* -+ * Copyright (c) 2015 Jiri Pirko <jiri@resnulli.us> -+ * -+ * 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_TC_BPF_H -+#define __LINUX_TC_BPF_H -+ -+#include <linux/pkt_cls.h> -+ -+#define TCA_ACT_BPF 13 -+ -+struct tc_act_bpf { -+ tc_gen; -+}; -+ -+enum { -+ TCA_ACT_BPF_UNSPEC, -+ TCA_ACT_BPF_TM, -+ TCA_ACT_BPF_PARMS, -+ TCA_ACT_BPF_OPS_LEN, -+ TCA_ACT_BPF_OPS, -+ TCA_ACT_BPF_FD, -+ TCA_ACT_BPF_NAME, -+ __TCA_ACT_BPF_MAX, -+}; -+#define TCA_ACT_BPF_MAX (__TCA_ACT_BPF_MAX - 1) -+ -+#endif -diff --git a/include/linux/tc_act/tc_connmark.h b/include/linux/tc_act/tc_connmark.h -new file mode 100644 -index 0000000..994b097 ---- /dev/null -+++ b/include/linux/tc_act/tc_connmark.h -@@ -0,0 +1,22 @@ -+#ifndef __UAPI_TC_CONNMARK_H -+#define __UAPI_TC_CONNMARK_H -+ -+#include <linux/types.h> -+#include <linux/pkt_cls.h> -+ -+#define TCA_ACT_CONNMARK 14 -+ -+struct tc_connmark { -+ tc_gen; -+ __u16 zone; -+}; -+ -+enum { -+ TCA_CONNMARK_UNSPEC, -+ TCA_CONNMARK_PARMS, -+ TCA_CONNMARK_TM, -+ __TCA_CONNMARK_MAX -+}; -+#define TCA_CONNMARK_MAX (__TCA_CONNMARK_MAX - 1) -+ -+#endif -diff --git a/include/linux/tc_act/tc_defact.h b/include/linux/tc_act/tc_defact.h -new file mode 100644 -index 0000000..17dddb4 ---- /dev/null -+++ b/include/linux/tc_act/tc_defact.h -@@ -0,0 +1,19 @@ -+#ifndef __LINUX_TC_DEF_H -+#define __LINUX_TC_DEF_H -+ -+#include <linux/pkt_cls.h> -+ -+struct tc_defact { -+ tc_gen; -+}; -+ -+enum { -+ TCA_DEF_UNSPEC, -+ TCA_DEF_TM, -+ TCA_DEF_PARMS, -+ TCA_DEF_DATA, -+ __TCA_DEF_MAX -+}; -+#define TCA_DEF_MAX (__TCA_DEF_MAX - 1) -+ -+#endif -diff --git a/include/linux/tc_act/tc_ipt.h b/include/linux/tc_act/tc_ipt.h -index a233556..130aaad 100644 ---- a/include/linux/tc_act/tc_ipt.h -+++ b/include/linux/tc_act/tc_ipt.h -@@ -4,6 +4,7 @@ - #include <linux/pkt_cls.h> - - #define TCA_ACT_IPT 6 -+#define TCA_ACT_XT 10 - - enum { - TCA_IPT_UNSPEC, -diff --git a/include/linux/tc_act/tc_vlan.h b/include/linux/tc_act/tc_vlan.h -new file mode 100644 -index 0000000..f7b8d44 ---- /dev/null -+++ b/include/linux/tc_act/tc_vlan.h -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us> -+ * -+ * 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_TC_VLAN_H -+#define __LINUX_TC_VLAN_H -+ -+#include <linux/pkt_cls.h> -+ -+#define TCA_ACT_VLAN 12 -+ -+#define TCA_VLAN_ACT_POP 1 -+#define TCA_VLAN_ACT_PUSH 2 -+ -+struct tc_vlan { -+ tc_gen; -+ int v_action; -+}; -+ -+enum { -+ TCA_VLAN_UNSPEC, -+ TCA_VLAN_TM, -+ TCA_VLAN_PARMS, -+ TCA_VLAN_PUSH_VLAN_ID, -+ TCA_VLAN_PUSH_VLAN_PROTOCOL, -+ __TCA_VLAN_MAX, -+}; -+#define TCA_VLAN_MAX (__TCA_VLAN_MAX - 1) -+ -+#endif -diff --git a/include/linux/tcp.h b/include/linux/tcp.h -index 1eb04d3..f96e015 100644 ---- a/include/linux/tcp.h -+++ b/include/linux/tcp.h -@@ -111,6 +111,7 @@ enum { - #define TCP_REPAIR_OPTIONS 22 - #define TCP_FASTOPEN 23 /* Enable FastOpen on listeners */ - #define TCP_TIMESTAMP 24 -+#define TCP_NOTSENT_LOWAT 25 /* limit number of unsent bytes in write queue */ - - struct tcp_repair_opt { - __u32 opt_code; -@@ -185,6 +186,9 @@ struct tcp_info { - __u32 tcpi_rcv_space; - - __u32 tcpi_total_retrans; -+ -+ __u64 tcpi_pacing_rate; -+ __u64 tcpi_max_pacing_rate; - }; - - /* for TCP_MD5SIG socket option */ -diff --git a/include/linux/tcp_metrics.h b/include/linux/tcp_metrics.h -index cb5157b..9353392 100644 ---- a/include/linux/tcp_metrics.h -+++ b/include/linux/tcp_metrics.h -@@ -11,12 +11,15 @@ - #define TCP_METRICS_GENL_VERSION 0x1 - - enum tcp_metric_index { -- TCP_METRIC_RTT, -- TCP_METRIC_RTTVAR, -+ TCP_METRIC_RTT, /* in ms units */ -+ TCP_METRIC_RTTVAR, /* in ms units */ - TCP_METRIC_SSTHRESH, - TCP_METRIC_CWND, - TCP_METRIC_REORDERING, - -+ TCP_METRIC_RTT_US, /* in usec units */ -+ TCP_METRIC_RTTVAR_US, /* in usec units */ -+ - /* Always last. */ - __TCP_METRIC_MAX, - }; -@@ -35,6 +38,8 @@ enum { - TCP_METRICS_ATTR_FOPEN_SYN_DROPS, /* u16, count of drops */ - TCP_METRICS_ATTR_FOPEN_SYN_DROP_TS, /* msecs age */ - TCP_METRICS_ATTR_FOPEN_COOKIE, /* binary */ -+ TCP_METRICS_ATTR_SADDR_IPV4, /* u32 */ -+ TCP_METRICS_ATTR_SADDR_IPV6, /* binary */ - - __TCP_METRICS_ATTR_MAX, - }; -diff --git a/include/linux/unix_diag.h b/include/linux/unix_diag.h -index b9e2a6a..1eb0b8d 100644 ---- a/include/linux/unix_diag.h -+++ b/include/linux/unix_diag.h -@@ -31,6 +31,7 @@ struct unix_diag_msg { - }; - - enum { -+ /* UNIX_DIAG_NONE, standard nl API requires this attribute! */ - UNIX_DIAG_NAME, - UNIX_DIAG_VFS, - UNIX_DIAG_PEER, -diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h -index 341c3c9..b8f5451 100644 ---- a/include/linux/xfrm.h -+++ b/include/linux/xfrm.h -@@ -1,6 +1,7 @@ - #ifndef _LINUX_XFRM_H - #define _LINUX_XFRM_H - -+#include <linux/in6.h> - #include <linux/types.h> - - /* All of the structures in this file may not change size as they are -@@ -13,6 +14,7 @@ - typedef union { - __be32 a4; - __be32 a6[4]; -+ struct in6_addr in6; - } xfrm_address_t; - - /* Ident of a specific xfrm_state. It is used on input to lookup -@@ -298,6 +300,8 @@ enum xfrm_attr_type_t { - XFRMA_TFCPAD, /* __u32 */ - XFRMA_REPLAY_ESN_VAL, /* struct xfrm_replay_esn */ - XFRMA_SA_EXTRA_FLAGS, /* __u32 */ -+ XFRMA_PROTO, /* __u8 */ -+ XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */ - __XFRMA_MAX - - #define XFRMA_MAX (__XFRMA_MAX - 1) -@@ -326,6 +330,8 @@ enum xfrm_spdattr_type_t { - XFRMA_SPD_UNSPEC, - XFRMA_SPD_INFO, - XFRMA_SPD_HINFO, -+ XFRMA_SPD_IPV4_HTHRESH, -+ XFRMA_SPD_IPV6_HTHRESH, - __XFRMA_SPD_MAX - - #define XFRMA_SPD_MAX (__XFRMA_SPD_MAX - 1) -@@ -345,6 +351,11 @@ struct xfrmu_spdhinfo { - __u32 spdhmcnt; - }; - -+struct xfrmu_spdhthresh { -+ __u8 lbits; -+ __u8 rbits; -+}; -+ - struct xfrm_usersa_info { - struct xfrm_selector sel; - struct xfrm_id id; -@@ -474,6 +485,14 @@ struct xfrm_user_mapping { - __be16 new_sport; - }; - -+struct xfrm_address_filter { -+ xfrm_address_t saddr; -+ xfrm_address_t daddr; -+ __u16 family; -+ __u8 splen; -+ __u8 dplen; -+}; -+ - /* backwards compatibility for userspace */ - #define XFRMGRP_ACQUIRE 1 - #define XFRMGRP_EXPIRE 2 -diff --git a/ip/xfrm_monitor.c b/ip/xfrm_monitor.c -index 50116a7..773b143 100644 ---- a/ip/xfrm_monitor.c -+++ b/ip/xfrm_monitor.c -@@ -27,7 +27,9 @@ - #include <stdio.h> - #include <stdlib.h> - #include <string.h> -+#include <netinet/in.h> - #include <linux/xfrm.h> -+ - #include "utils.h" - #include "xfrm.h" - #include "ip_common.h" diff --git a/SOURCES/iproute2-3.10.0-lnstat-interval.patch b/SOURCES/iproute2-3.10.0-lnstat-interval.patch deleted file mode 100644 index 656f1cc..0000000 --- a/SOURCES/iproute2-3.10.0-lnstat-interval.patch +++ /dev/null @@ -1,29 +0,0 @@ -diff --git a/misc/lnstat.c b/misc/lnstat.c -index dca10ad..847e33f 100644 ---- a/misc/lnstat.c -+++ b/misc/lnstat.c -@@ -226,7 +226,7 @@ int main(int argc, char **argv) - MODE_NORMAL, - } mode = MODE_NORMAL; - -- unsigned long count = 1; -+ unsigned long count = 0; - static struct field_params fp; - int num_req_files = 0; - char *req_files[LNSTAT_MAX_FILES]; -@@ -336,13 +336,14 @@ int main(int argc, char **argv) - if (interval < 1 ) - interval=1; - -- for (i = 0; i < count; i++) { -+ for (i = 0; !count || i < count; ) { - if ((hdr > 1 && (! (i % 20))) || (hdr == 1 && i == 0)) - print_hdr(stdout, header); - lnstat_update(lnstat_files); - print_line(stdout, lnstat_files, &fp); - fflush(stdout); - sleep(interval); -+ if (count) ++i; - } - } - diff --git a/SOURCES/iproute2-3.10.0-man-ip-Add-missing-details-option.patch b/SOURCES/iproute2-3.10.0-man-ip-Add-missing-details-option.patch deleted file mode 100644 index 308a85b..0000000 --- a/SOURCES/iproute2-3.10.0-man-ip-Add-missing-details-option.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 4634f27c656a5fad22f6ed93963b78947450907f Mon Sep 17 00:00:00 2001 -From: vadimk <vadim4j@gmail.com> -Date: Mon, 27 Oct 2014 17:22:58 +0200 -Subject: [PATCH] man ip: Add missing '-details' option - -Signed-off-by: Vadim Kochan <vadim4j@gmail.com> ---- - man/man8/ip.8 | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/man/man8/ip.8 b/man/man8/ip.8 -index 0713756..0bae59e 100644 ---- a/man/man8/ip.8 -+++ b/man/man8/ip.8 -@@ -60,6 +60,10 @@ appears twice or more, the amount of information increases. - As a rule, the information is statistics or some time values. - - .TP -+.BR "\-d" , " \-details" -+Output more detailed information. -+ -+.TP - .BR "\-l" , " \-loops " <COUNT> - Specify maximum number of loops the 'ip addr flush' logic - will attempt before giving up. The default is 10. --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-misc-ss-don-t-imply-a-when-A-was-specified.patch b/SOURCES/iproute2-3.10.0-misc-ss-don-t-imply-a-when-A-was-specified.patch deleted file mode 100644 index 0caf474..0000000 --- a/SOURCES/iproute2-3.10.0-misc-ss-don-t-imply-a-when-A-was-specified.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 9aeb98263755ab24bd000da8ebf256dea5f21e1f Mon Sep 17 00:00:00 2001 -From: Phil Sutter <phil@nwl.cc> -Date: Fri, 7 Aug 2015 15:31:27 +0200 -Subject: [PATCH] misc/ss: don't imply -a when -A was specified - -Signed-off-by: Phil Sutter <phil@nwl.cc> ---- - misc/ss.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/misc/ss.c b/misc/ss.c -index c443c35..951e1eb 100644 ---- a/misc/ss.c -+++ b/misc/ss.c -@@ -3505,6 +3505,8 @@ int main(int argc, char *argv[]) - char *p, *p1; - if (!saw_query) { - current_filter.dbs = 0; -+ state_filter = state_filter ? -+ state_filter : SS_CONN; - saw_query = 1; - do_default = 0; - } --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-netns.patch b/SOURCES/iproute2-3.10.0-netns.patch deleted file mode 100644 index 7589f44..0000000 --- a/SOURCES/iproute2-3.10.0-netns.patch +++ /dev/null @@ -1,730 +0,0 @@ -commit 99ea60996425f1baa6bcb07d01323b80129c2141 -Author: Pavel Šimerda <psimerda@redhat.com> -Date: Mon Jun 1 18:56:09 2015 +0200 - - backport selected ip-netns features - -diff --git a/ip/ipnetns.c b/ip/ipnetns.c -index 794a498..24df167 100644 ---- a/ip/ipnetns.c -+++ b/ip/ipnetns.c -@@ -15,180 +15,151 @@ - #include <unistd.h> - #include <ctype.h> - -+#include <linux/net_namespace.h> -+ - #include "utils.h" - #include "ip_common.h" -- --#define NETNS_RUN_DIR "/var/run/netns" --#define NETNS_ETC_DIR "/etc/netns" -- --#ifndef CLONE_NEWNET --#define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */ --#endif -- --#ifndef MNT_DETACH --#define MNT_DETACH 0x00000002 /* Just detach from the tree */ --#endif /* MNT_DETACH */ -- --/* sys/mount.h may be out too old to have these */ --#ifndef MS_REC --#define MS_REC 16384 --#endif -- --#ifndef MS_SLAVE --#define MS_SLAVE (1 << 19) --#endif -- --#ifndef MS_SHARED --#define MS_SHARED (1 << 20) --#endif -- --#ifndef HAVE_SETNS --static int setns(int fd, int nstype) --{ --#ifdef __NR_setns -- return syscall(__NR_setns, fd, nstype); --#else -- errno = ENOSYS; -- return -1; --#endif --} --#endif /* HAVE_SETNS */ -+#include "namespace.h" - - static int usage(void) - { - fprintf(stderr, "Usage: ip netns list\n"); - fprintf(stderr, " ip netns add NAME\n"); -- fprintf(stderr, " ip netns delete NAME\n"); -- fprintf(stderr, " ip netns identify PID\n"); -+ fprintf(stderr, " ip netns set NAME NETNSID\n"); -+ fprintf(stderr, " ip [-all] netns delete [NAME]\n"); -+ fprintf(stderr, " ip netns identify [PID]\n"); - fprintf(stderr, " ip netns pids NAME\n"); -- fprintf(stderr, " ip netns exec NAME cmd ...\n"); -+ fprintf(stderr, " ip [-all] netns exec [NAME] cmd ...\n"); - fprintf(stderr, " ip netns monitor\n"); - exit(-1); - } - --int get_netns_fd(const char *name) -+static int have_rtnl_getnsid = -1; -+ -+static int ipnetns_accept_msg(const struct sockaddr_nl *who, -+ struct nlmsghdr *n, void *arg) - { -- char pathbuf[MAXPATHLEN]; -- const char *path, *ptr; -+ struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n); - -- path = name; -- ptr = strchr(name, '/'); -- if (!ptr) { -- snprintf(pathbuf, sizeof(pathbuf), "%s/%s", -- NETNS_RUN_DIR, name ); -- path = pathbuf; -- } -- return open(path, O_RDONLY); -+ if (n->nlmsg_type == NLMSG_ERROR && -+ (err->error == -EOPNOTSUPP || err->error == -EINVAL)) -+ have_rtnl_getnsid = 0; -+ else -+ have_rtnl_getnsid = 1; -+ return -1; - } - --static int netns_list(int argc, char **argv) -+static int ipnetns_have_nsid(void) - { -- struct dirent *entry; -- DIR *dir; -+ struct { -+ struct nlmsghdr n; -+ struct rtgenmsg g; -+ char buf[1024]; -+ } req; -+ int fd; - -- dir = opendir(NETNS_RUN_DIR); -- if (!dir) -- return 0; -+ if (have_rtnl_getnsid < 0) { -+ memset(&req, 0, sizeof(req)); -+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); -+ req.n.nlmsg_flags = NLM_F_REQUEST; -+ req.n.nlmsg_type = RTM_GETNSID; -+ req.g.rtgen_family = AF_UNSPEC; - -- while ((entry = readdir(dir)) != NULL) { -- if (strcmp(entry->d_name, ".") == 0) -- continue; -- if (strcmp(entry->d_name, "..") == 0) -- continue; -- printf("%s\n", entry->d_name); -+ fd = open("/proc/self/ns/net", O_RDONLY); -+ if (fd < 0) { -+ perror("open(\"/proc/self/ns/net\")"); -+ exit(1); -+ } -+ -+ addattr32(&req.n, 1024, NETNSA_FD, fd); -+ -+ if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) { -+ perror("request send failed"); -+ exit(1); -+ } -+ rtnl_listen(&rth, ipnetns_accept_msg, NULL); -+ close(fd); - } -- closedir(dir); -- return 0; -+ -+ return have_rtnl_getnsid; - } - --static void bind_etc(const char *name) -+static int get_netnsid_from_name(const char *name) -+{ -+ struct { -+ struct nlmsghdr n; -+ struct rtgenmsg g; -+ char buf[1024]; -+ } req, answer; -+ struct rtattr *tb[NETNSA_MAX + 1]; -+ struct rtgenmsg *rthdr; -+ int len, fd; -+ -+ memset(&req, 0, sizeof(req)); -+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); -+ req.n.nlmsg_flags = NLM_F_REQUEST; -+ req.n.nlmsg_type = RTM_GETNSID; -+ req.g.rtgen_family = AF_UNSPEC; -+ -+ fd = netns_get_fd(name); -+ if (fd < 0) -+ return fd; -+ -+ addattr32(&req.n, 1024, NETNSA_FD, fd); -+ if (rtnl_talk(&rth, &req.n, 0, 0, &answer.n) < 0) { -+ close(fd); -+ return -2; -+ } -+ close(fd); -+ -+ /* Validate message and parse attributes */ -+ if (answer.n.nlmsg_type == NLMSG_ERROR) -+ return -1; -+ -+ rthdr = NLMSG_DATA(&answer.n); -+ len = answer.n.nlmsg_len - NLMSG_SPACE(sizeof(*rthdr)); -+ if (len < 0) -+ return -1; -+ -+ parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len); -+ -+ if (tb[NETNSA_NSID]) -+ return rta_getattr_u32(tb[NETNSA_NSID]); -+ -+ return -1; -+} -+ -+static int netns_list(int argc, char **argv) - { -- char etc_netns_path[MAXPATHLEN]; -- char netns_name[MAXPATHLEN]; -- char etc_name[MAXPATHLEN]; - struct dirent *entry; - DIR *dir; -+ int id; - -- snprintf(etc_netns_path, sizeof(etc_netns_path), "%s/%s", NETNS_ETC_DIR, name); -- dir = opendir(etc_netns_path); -+ dir = opendir(NETNS_RUN_DIR); - if (!dir) -- return; -+ return 0; - - while ((entry = readdir(dir)) != NULL) { - if (strcmp(entry->d_name, ".") == 0) - continue; - if (strcmp(entry->d_name, "..") == 0) - continue; -- snprintf(netns_name, sizeof(netns_name), "%s/%s", etc_netns_path, entry->d_name); -- snprintf(etc_name, sizeof(etc_name), "/etc/%s", entry->d_name); -- if (mount(netns_name, etc_name, "none", MS_BIND, NULL) < 0) { -- fprintf(stderr, "Bind %s -> %s failed: %s\n", -- netns_name, etc_name, strerror(errno)); -+ printf("%s", entry->d_name); -+ if (ipnetns_have_nsid()) { -+ id = get_netnsid_from_name(entry->d_name); -+ if (id >= 0) -+ printf(" (id: %d)", id); - } -+ printf("\n"); - } - closedir(dir); -+ return 0; - } - --static int netns_exec(int argc, char **argv) -+static int cmd_exec(const char *cmd, char **argv, bool do_fork) - { -- /* Setup the proper environment for apps that are not netns -- * aware, and execute a program in that environment. -- */ -- const char *name, *cmd; -- char net_path[MAXPATHLEN]; -- int netns; -- -- if (argc < 1) { -- fprintf(stderr, "No netns name specified\n"); -- return -1; -- } -- if (argc < 2) { -- fprintf(stderr, "No command specified\n"); -- return -1; -- } -- -- name = argv[0]; -- cmd = argv[1]; -- snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name); -- netns = open(net_path, O_RDONLY | O_CLOEXEC); -- if (netns < 0) { -- fprintf(stderr, "Cannot open network namespace \"%s\": %s\n", -- name, strerror(errno)); -- return -1; -- } -- -- if (setns(netns, CLONE_NEWNET) < 0) { -- fprintf(stderr, "seting the network namespace \"%s\" failed: %s\n", -- name, strerror(errno)); -- return -1; -- } -- -- if (unshare(CLONE_NEWNS) < 0) { -- fprintf(stderr, "unshare failed: %s\n", strerror(errno)); -- return -1; -- } -- /* Don't let any mounts propogate back to the parent */ -- if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL)) { -- fprintf(stderr, "\"mount --make-rslave /\" failed: %s\n", -- strerror(errno)); -- return -1; -- } -- /* Mount a version of /sys that describes the network namespace */ -- if (umount2("/sys", MNT_DETACH) < 0) { -- fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno)); -- return -1; -- } -- if (mount(name, "/sys", "sysfs", 0, NULL) < 0) { -- fprintf(stderr, "mount of /sys failed: %s\n",strerror(errno)); -- return -1; -- } -- -- /* Setup bind mounts for config files in /etc */ -- bind_etc(name); -- - fflush(stdout); -- -- if (batch_mode) { -+ if (do_fork) { - int status; - pid_t pid; - -@@ -205,20 +176,57 @@ static int netns_exec(int argc, char **argv) - exit(1); - } - -- /* If child failed, propogate status */ -- if (WIFEXITED(status)) -- exit(WEXITSTATUS(status)); -+ if (WIFEXITED(status)) { -+ return WEXITSTATUS(status); -+ } - -- return 0; -+ exit(1); - } - } - -- if (execvp(cmd, argv + 1) < 0) -+ if (execvp(cmd, argv) < 0) - fprintf(stderr, "exec of \"%s\" failed: %s\n", -- cmd, strerror(errno)); -+ cmd, strerror(errno)); - _exit(1); - } - -+static int on_netns_exec(char *nsname, void *arg) -+{ -+ char **argv = arg; -+ cmd_exec(argv[1], argv + 1, true); -+ return 0; -+} -+ -+static int netns_exec(int argc, char **argv) -+{ -+ /* Setup the proper environment for apps that are not netns -+ * aware, and execute a program in that environment. -+ */ -+ const char *cmd; -+ -+ if (argc < 1 && !do_all) { -+ fprintf(stderr, "No netns name specified\n"); -+ return -1; -+ } -+ if ((argc < 2 && !do_all) || (argc < 1 && do_all)) { -+ fprintf(stderr, "No command specified\n"); -+ return -1; -+ } -+ -+ if (do_all) -+ return do_each_netns(on_netns_exec, --argv, 1); -+ -+ if (netns_switch(argv[0])) -+ return -1; -+ -+ /* ip must return the status of the child, -+ * but do_cmd() will add a minus to this, -+ * so let's add another one here to cancel it. -+ */ -+ cmd = argv[1]; -+ return -cmd_exec(cmd, argv + 1, !!batch_mode); -+} -+ - static int is_pid(const char *str) - { - int ch; -@@ -282,7 +290,7 @@ static int netns_pids(int argc, char **argv) - } - closedir(dir); - return 0; -- -+ - } - - static int netns_identify(int argc, char **argv) -@@ -295,19 +303,17 @@ static int netns_identify(int argc, char **argv) - struct dirent *entry; - - if (argc < 1) { -- fprintf(stderr, "No pid specified\n"); -- return -1; -- } -- if (argc > 1) { -+ pidstr = "self"; -+ } else if (argc > 1) { - fprintf(stderr, "extra arguments specified\n"); - return -1; -- } -- pidstr = argv[0]; -- -- if (!is_pid(pidstr)) { -- fprintf(stderr, "Specified string '%s' is not a pid\n", -- pidstr); -- return -1; -+ } else { -+ pidstr = argv[0]; -+ if (!is_pid(pidstr)) { -+ fprintf(stderr, "Specified string '%s' is not a pid\n", -+ pidstr); -+ return -1; -+ } - } - - snprintf(net_path, sizeof(net_path), "/proc/%s/ns/net", pidstr); -@@ -355,21 +361,14 @@ static int netns_identify(int argc, char **argv) - } - closedir(dir); - return 0; -- -+ - } - --static int netns_delete(int argc, char **argv) -+static int on_netns_del(char *nsname, void *arg) - { -- const char *name; - char netns_path[MAXPATHLEN]; - -- if (argc < 1) { -- fprintf(stderr, "No netns name specified\n"); -- return -1; -- } -- -- name = argv[0]; -- snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name); -+ snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, nsname); - umount2(netns_path, MNT_DETACH); - if (unlink(netns_path) < 0) { - fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n", -@@ -379,6 +378,33 @@ static int netns_delete(int argc, char **argv) - return 0; - } - -+static int netns_delete(int argc, char **argv) -+{ -+ if (argc < 1 && !do_all) { -+ fprintf(stderr, "No netns name specified\n"); -+ return -1; -+ } -+ -+ if (do_all) -+ return netns_foreach(on_netns_del, NULL); -+ -+ return on_netns_del(argv[0], NULL); -+} -+ -+static int create_netns_dir(void) -+{ -+ /* Create the base netns directory if it doesn't exist */ -+ if (mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) { -+ if (errno != EEXIST) { -+ fprintf(stderr, "mkdir %s failed: %s\n", -+ NETNS_RUN_DIR, strerror(errno)); -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ - static int netns_add(int argc, char **argv) - { - /* This function creates a new network namespace and -@@ -402,10 +428,10 @@ static int netns_add(int argc, char **argv) - - snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name); - -- /* Create the base netns directory if it doesn't exist */ -- mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); -+ if (create_netns_dir()) -+ return -1; - -- /* Make it possible for network namespace mounts to propogate between -+ /* Make it possible for network namespace mounts to propagate between - * mount namespaces. This makes it likely that a unmounting a network - * namespace file in one namespace will unmount the network namespace - * file in all namespaces allowing the network namespace to be freed -@@ -431,7 +457,7 @@ static int netns_add(int argc, char **argv) - /* Create the filesystem state */ - fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0); - if (fd < 0) { -- fprintf(stderr, "Cannot not create namespace file \"%s\": %s\n", -+ fprintf(stderr, "Cannot create namespace file \"%s\": %s\n", - netns_path, strerror(errno)); - return -1; - } -@@ -454,6 +480,61 @@ out_delete: - return -1; - } - -+static int set_netnsid_from_name(const char *name, int nsid) -+{ -+ struct { -+ struct nlmsghdr n; -+ struct rtgenmsg g; -+ char buf[1024]; -+ } req; -+ int fd, err = 0; -+ -+ memset(&req, 0, sizeof(req)); -+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); -+ req.n.nlmsg_flags = NLM_F_REQUEST; -+ req.n.nlmsg_type = RTM_NEWNSID; -+ req.g.rtgen_family = AF_UNSPEC; -+ -+ fd = netns_get_fd(name); -+ if (fd < 0) -+ return fd; -+ -+ addattr32(&req.n, 1024, NETNSA_FD, fd); -+ addattr32(&req.n, 1024, NETNSA_NSID, nsid); -+ if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ err = -2; -+ -+ close(fd); -+ return err; -+} -+ -+static int netns_set(int argc, char **argv) -+{ -+ char netns_path[MAXPATHLEN]; -+ const char *name; -+ int netns, nsid; -+ -+ if (argc < 1) { -+ fprintf(stderr, "No netns name specified\n"); -+ return -1; -+ } -+ if (argc < 2) { -+ fprintf(stderr, "No nsid specified\n"); -+ return -1; -+ } -+ name = argv[0]; -+ nsid = atoi(argv[1]); -+ -+ snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name); -+ netns = open(netns_path, O_RDONLY | O_CLOEXEC); -+ if (netns < 0) { -+ fprintf(stderr, "Cannot open network namespace \"%s\": %s\n", -+ name, strerror(errno)); -+ return -1; -+ } -+ -+ return set_netnsid_from_name(name, nsid); -+} - - static int netns_monitor(int argc, char **argv) - { -@@ -466,6 +547,10 @@ static int netns_monitor(int argc, char **argv) - strerror(errno)); - return -1; - } -+ -+ if (create_netns_dir()) -+ return -1; -+ - if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_CREATE | IN_DELETE) < 0) { - fprintf(stderr, "inotify_add_watch failed: %s\n", - strerror(errno)); -@@ -505,6 +590,9 @@ int do_netns(int argc, char **argv) - if (matches(*argv, "add") == 0) - return netns_add(argc-1, argv+1); - -+ if (matches(*argv, "set") == 0) -+ return netns_set(argc-1, argv+1); -+ - if (matches(*argv, "delete") == 0) - return netns_delete(argc-1, argv+1); - -diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8 -index 6aa6e93..80a4ad1 100644 ---- a/man/man8/ip-netns.8 -+++ b/man/man8/ip-netns.8 -@@ -16,20 +16,28 @@ ip-netns \- process network namespace management - .BR "ip netns" " { " list " } " - - .ti -8 --.BR "ip netns" " { " add " | " delete " } " -+.B ip netns add - .I NETNSNAME - - .ti -8 -+.B ip [-all] netns del -+.RI "[ " NETNSNAME " ]" -+ -+.ti -8 -+.BR "ip netns" " { " set " } " -+.I NETNSNAME NETNSID -+ -+.ti -8 - .BR "ip netns identify" --.I PID -+.RI "[ " PID " ]" - - .ti -8 - .BR "ip netns pids" - .I NETNSNAME - - .ti -8 --.BR "ip netns exec " --.I NETNSNAME command ... -+.BR "ip [-all] netns exec " -+.RI "[ " NETNSNAME " ] " command ... - - .ti -8 - .BR "ip netns monitor" -@@ -38,12 +46,15 @@ ip-netns \- process network namespace management - A network namespace is logically another copy of the network stack, - with its own routes, firewall rules, and network devices. - -+By default a process inherits its network namespace from its parent. Initially all -+the processes share the same default network namespace from the init process. -+ - By convention a named network namespace is an object at - .BR "/var/run/netns/" NAME --that can be opened. The file descriptor resulting from opening -+that can be opened. The file descriptor resulting from opening - .BR "/var/run/netns/" NAME --refers to the specified network namespace. Holding that file --descriptor open keeps the network namespace alive. The file -+refers to the specified network namespace. Holding that file -+descriptor open keeps the network namespace alive. The file - descriptor can be used with the - .B setns(2) - system call to change the network namespace associated with a task. -@@ -76,19 +87,64 @@ If NAME is available in /var/run/netns/ this command creates a new - network namespace and assigns NAME. - - .TP --.B ip netns delete NAME - delete the name of a network namespace -+.B ip [-all] netns delete [ NAME ] - delete the name of a network namespace(s) - .sp - If NAME is present in /var/run/netns it is umounted and the mount --point is removed. If this is the last user of the network namespace the --network namespace will be freed, otherwise the network namespace --persists until it has no more users. ip netns delete may fail if --the mount point is in use in another mount namespace. -+point is removed. If this is the last user of the network namespace the -+network namespace will be freed and all physical devices will be moved to the -+default one, otherwise the network namespace persists until it has no more -+users. ip netns delete may fail if the mount point is in use in another mount -+namespace. -+ -+If -+.B -all -+option was specified then all the network namespace names will be removed. -+ -+It is possible to lose the physical device when it was moved to netns and -+then this netns was deleted with a running process: -+ -+.RS 10 -+$ ip netns add net0 -+.RE -+.RS 10 -+$ ip link set dev eth0 netns net0 -+.RE -+.RS 10 -+$ ip netns exec net0 SOME_PROCESS_IN_BACKGROUND -+.RE -+.RS 10 -+$ ip netns del net0 -+.RE -+ -+.RS -+and eth0 will appear in the default netns only after SOME_PROCESS_IN_BACKGROUND -+will exit or will be killed. To prevent this the processes running in net0 -+should be killed before deleting the netns: -+ -+.RE -+.RS 10 -+$ ip netns pids net0 | xargs kill -+.RE -+.RS 10 -+$ ip netns del net0 -+.RE - - .TP --.B ip netns identify PID - Report network namespaces names for process -+.B ip netns set NAME NETNSID - assign an id to a peer network namespace -+.sp -+This command assigns a id to a peer network namespace. This id is valid -+only in the current network namespace. -+This id will be used by the kernel in some netlink messages. If no id is -+assigned when the kernel needs it, it will be automatically assigned by -+the kernel. -+Once it is assigned, it's not possible to change it. -+ -+.TP -+.B ip netns identify [PID] - Report network namespaces names for process - .sp - This command walks through /var/run/netns and finds all the network --namespace names for network namespace of the specified process. -+namespace names for network namespace of the specified process, if PID is -+not specified then the current process will be used. - - .TP - .B ip netns pids NAME - Report processes in the named network namespace -@@ -97,15 +153,25 @@ This command walks through proc and finds all of the process who have - the named network namespace as their primary network namespace. - - .TP --.B ip netns exec NAME cmd ... - Run cmd in the named network namespace -+.B ip [-all] netns exec [ NAME ] cmd ... - Run cmd in the named network namespace - .sp - This command allows applications that are network namespace unaware - to be run in something other than the default network namespace with - all of the configuration for the specified network namespace appearing --in the customary global locations. A network namespace and bind mounts -+in the customary global locations. A network namespace and bind mounts - are used to move files from their network namespace specific location - to their default locations without affecting other processes. - -+If -+.B -all -+option was specified then -+.B cmd -+will be executed synchronously on the each named network namespace even if -+.B cmd -+fails on some of them. Network namespace name is printed on each -+.B cmd -+executing. -+ - .TP - .B ip netns monitor - Report as network namespace names are added and deleted - .sp ---- iproute2-3.10.0/man/man8/ip.8.orig 2015-07-08 19:15:58.468148060 +0200 -+++ iproute2-3.10.0/man/man8/ip.8 2015-07-08 19:16:38.078147665 +0200 -@@ -132,7 +132,7 @@ - host addresses. - - .TP --.BR "\-n" , " \-net" , " \-netns " <NETNS> -+.BR "\-n" , " \-netns " <NETNS> - switches - .B ip - to the specified network namespace diff --git a/SOURCES/iproute2-3.10.0-pkt_sched-fq-Fair-Queue-packet-scheduler.patch b/SOURCES/iproute2-3.10.0-pkt_sched-fq-Fair-Queue-packet-scheduler.patch deleted file mode 100644 index 3403906..0000000 --- a/SOURCES/iproute2-3.10.0-pkt_sched-fq-Fair-Queue-packet-scheduler.patch +++ /dev/null @@ -1,354 +0,0 @@ -From 837c38c3365b63ba486d0b0eb8a963621d8f0ac2 Mon Sep 17 00:00:00 2001 -From: Eric Dumazet <edumazet@google.com> -Date: Thu, 29 Aug 2013 19:30:36 -0700 -Subject: [PATCH 1/2] pkt_sched: fq: Fair Queue packet scheduler - -Support for FQ packet scheduler - -$ tc qd add dev eth0 root fq help -Usage: ... fq [ limit PACKETS ] [ flow_limit PACKETS ] - [ quantum BYTES ] [ initial_quantum BYTES ] - [ maxrate RATE ] [ buckets NUMBER ] - [ [no]pacing ] - -$ tc -s -d qd -qdisc fq 8002: dev eth0 root refcnt 32 limit 10000p flow_limit 100p -buckets 256 quantum 3028 initial_quantum 15140 - Sent 216532416 bytes 148395 pkt (dropped 0, overlimits 0 requeues 14) - backlog 0b 0p requeues 14 - 511 flows (511 inactive, 0 throttled) - 110 gc, 0 highprio, 0 retrans, 1143 throttled, 0 flows_plimit - -limit : max number of packets on whole Qdisc (default 10000) - -flow_limit : max number of packets per flow (default 100) - -quantum : the max deficit per RR round (default is 2 MTU) - -initial_quantum : initial credit for new flows (default is 10 MTU) - -maxrate : max per flow rate (default : unlimited) - -buckets : number of RB trees (default : 1024) in hash table. - (consumes 8 bytes per bucket) - -[no]pacing : disable/enable pacing (default is enable) - -Usage : - -tc qdisc add dev $ETH root fq - -tc qdisc del dev $ETH root 2>/dev/null -tc qdisc add dev $ETH root handle 1: mq -for i in `seq 1 4` -do - tc qdisc add dev $ETH parent 1:$i est 1sec 4sec fq -done - -Signed-off-by: Eric Dumazet <edumazet@google.com> ---- - tc/Makefile | 1 + - tc/q_fq.c | 279 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 280 insertions(+) - create mode 100644 tc/q_fq.c - -diff --git a/tc/Makefile b/tc/Makefile -index af6a277..79116f3 100644 ---- a/tc/Makefile -+++ b/tc/Makefile -@@ -56,6 +56,7 @@ TCMODULES += em_meta.o - TCMODULES += q_mqprio.o - TCMODULES += q_codel.o - TCMODULES += q_fq_codel.o -+TCMODULES += q_fq.o - - ifeq ($(TC_CONFIG_IPSET), y) - ifeq ($(TC_CONFIG_XT), y) -diff --git a/tc/q_fq.c b/tc/q_fq.c -new file mode 100644 -index 0000000..c1f658e ---- /dev/null -+++ b/tc/q_fq.c -@@ -0,0 +1,279 @@ -+/* -+ * Fair Queue -+ * -+ * Copyright (C) 2013 Eric Dumazet <edumazet@google.com> -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the authors may not be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * Alternatively, provided that this notice is retained in full, this -+ * software may be distributed under the terms of the GNU General -+ * Public License ("GPL") version 2, in which case the provisions of the -+ * GPL apply INSTEAD OF those given above. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <syslog.h> -+#include <fcntl.h> -+#include <sys/socket.h> -+#include <netinet/in.h> -+#include <arpa/inet.h> -+#include <string.h> -+ -+#include "utils.h" -+#include "tc_util.h" -+ -+static void explain(void) -+{ -+ fprintf(stderr, "Usage: ... fq [ limit PACKETS ] [ flow_limit PACKETS ]\n"); -+ fprintf(stderr, " [ quantum BYTES ] [ initial_quantum BYTES ]\n"); -+ fprintf(stderr, " [ maxrate RATE ] [ buckets NUMBER ]\n"); -+ fprintf(stderr, " [ [no]pacing ]\n"); -+} -+ -+static unsigned int ilog2(unsigned int val) -+{ -+ unsigned int res = 0; -+ -+ val--; -+ while (val) { -+ res++; -+ val >>= 1; -+ } -+ return res; -+} -+ -+static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, -+ struct nlmsghdr *n) -+{ -+ unsigned int plimit = ~0U; -+ unsigned int flow_plimit = ~0U; -+ unsigned int quantum = ~0U; -+ unsigned int initial_quantum = ~0U; -+ unsigned int buckets = 0; -+ unsigned int maxrate = ~0U; -+ unsigned int defrate = ~0U; -+ int pacing = -1; -+ struct rtattr *tail; -+ -+ while (argc > 0) { -+ if (strcmp(*argv, "limit") == 0) { -+ NEXT_ARG(); -+ if (get_unsigned(&plimit, *argv, 0)) { -+ fprintf(stderr, "Illegal \"limit\"\n"); -+ return -1; -+ } -+ } else if (strcmp(*argv, "flow_limit") == 0) { -+ NEXT_ARG(); -+ if (get_unsigned(&flow_plimit, *argv, 0)) { -+ fprintf(stderr, "Illegal \"flow_limit\"\n"); -+ return -1; -+ } -+ } else if (strcmp(*argv, "buckets") == 0) { -+ NEXT_ARG(); -+ if (get_unsigned(&buckets, *argv, 0)) { -+ fprintf(stderr, "Illegal \"buckets\"\n"); -+ return -1; -+ } -+ } else if (strcmp(*argv, "maxrate") == 0) { -+ NEXT_ARG(); -+ if (get_rate(&maxrate, *argv)) { -+ fprintf(stderr, "Illegal \"maxrate\"\n"); -+ return -1; -+ } -+ } else if (strcmp(*argv, "defrate") == 0) { -+ NEXT_ARG(); -+ if (get_rate(&defrate, *argv)) { -+ fprintf(stderr, "Illegal \"defrate\"\n"); -+ return -1; -+ } -+ } else if (strcmp(*argv, "quantum") == 0) { -+ NEXT_ARG(); -+ if (get_unsigned(&quantum, *argv, 0)) { -+ fprintf(stderr, "Illegal \"quantum\"\n"); -+ return -1; -+ } -+ } else if (strcmp(*argv, "initial_quantum") == 0) { -+ NEXT_ARG(); -+ if (get_unsigned(&initial_quantum, *argv, 0)) { -+ fprintf(stderr, "Illegal \"initial_quantum\"\n"); -+ return -1; -+ } -+ } else if (strcmp(*argv, "pacing") == 0) { -+ pacing = 1; -+ } else if (strcmp(*argv, "nopacing") == 0) { -+ pacing = 0; -+ } else if (strcmp(*argv, "help") == 0) { -+ explain(); -+ return -1; -+ } else { -+ fprintf(stderr, "What is \"%s\"?\n", *argv); -+ explain(); -+ return -1; -+ } -+ argc--; argv++; -+ } -+ -+ tail = NLMSG_TAIL(n); -+ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); -+ if (buckets) { -+ unsigned int log = ilog2(buckets); -+ -+ addattr_l(n, 1024, TCA_FQ_BUCKETS_LOG, -+ &log, sizeof(log)); -+ } -+ if (plimit != ~0U) -+ addattr_l(n, 1024, TCA_FQ_PLIMIT, -+ &plimit, sizeof(plimit)); -+ if (flow_plimit != ~0U) -+ addattr_l(n, 1024, TCA_FQ_FLOW_PLIMIT, -+ &flow_plimit, sizeof(flow_plimit)); -+ if (quantum != ~0U) -+ addattr_l(n, 1024, TCA_FQ_QUANTUM, &quantum, sizeof(quantum)); -+ if (initial_quantum != ~0U) -+ addattr_l(n, 1024, TCA_FQ_INITIAL_QUANTUM, -+ &initial_quantum, sizeof(initial_quantum)); -+ if (pacing != -1) -+ addattr_l(n, 1024, TCA_FQ_RATE_ENABLE, -+ &pacing, sizeof(pacing)); -+ if (maxrate != ~0U) -+ addattr_l(n, 1024, TCA_FQ_FLOW_MAX_RATE, -+ &maxrate, sizeof(maxrate)); -+ if (defrate != ~0U) -+ addattr_l(n, 1024, TCA_FQ_FLOW_DEFAULT_RATE, -+ &defrate, sizeof(defrate)); -+ tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; -+ return 0; -+} -+ -+static int fq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) -+{ -+ struct rtattr *tb[TCA_FQ_MAX + 1]; -+ unsigned int plimit, flow_plimit; -+ unsigned int buckets_log; -+ int pacing; -+ unsigned int rate, quantum; -+ SPRINT_BUF(b1); -+ -+ if (opt == NULL) -+ return 0; -+ -+ parse_rtattr_nested(tb, TCA_FQ_MAX, opt); -+ -+ if (tb[TCA_FQ_PLIMIT] && -+ RTA_PAYLOAD(tb[TCA_FQ_PLIMIT]) >= sizeof(__u32)) { -+ plimit = rta_getattr_u32(tb[TCA_FQ_PLIMIT]); -+ fprintf(f, "limit %up ", plimit); -+ } -+ if (tb[TCA_FQ_FLOW_PLIMIT] && -+ RTA_PAYLOAD(tb[TCA_FQ_FLOW_PLIMIT]) >= sizeof(__u32)) { -+ flow_plimit = rta_getattr_u32(tb[TCA_FQ_FLOW_PLIMIT]); -+ fprintf(f, "flow_limit %up ", flow_plimit); -+ } -+ if (tb[TCA_FQ_BUCKETS_LOG] && -+ RTA_PAYLOAD(tb[TCA_FQ_BUCKETS_LOG]) >= sizeof(__u32)) { -+ buckets_log = rta_getattr_u32(tb[TCA_FQ_BUCKETS_LOG]); -+ fprintf(f, "buckets %u ", 1U << buckets_log); -+ } -+ if (tb[TCA_FQ_RATE_ENABLE] && -+ RTA_PAYLOAD(tb[TCA_FQ_RATE_ENABLE]) >= sizeof(int)) { -+ pacing = rta_getattr_u32(tb[TCA_FQ_RATE_ENABLE]); -+ if (pacing == 0) -+ fprintf(f, "nopacing "); -+ } -+ if (tb[TCA_FQ_QUANTUM] && -+ RTA_PAYLOAD(tb[TCA_FQ_QUANTUM]) >= sizeof(__u32)) { -+ quantum = rta_getattr_u32(tb[TCA_FQ_QUANTUM]); -+ fprintf(f, "quantum %u ", quantum); -+ } -+ if (tb[TCA_FQ_INITIAL_QUANTUM] && -+ RTA_PAYLOAD(tb[TCA_FQ_INITIAL_QUANTUM]) >= sizeof(__u32)) { -+ quantum = rta_getattr_u32(tb[TCA_FQ_INITIAL_QUANTUM]); -+ fprintf(f, "initial_quantum %u ", quantum); -+ } -+ if (tb[TCA_FQ_FLOW_MAX_RATE] && -+ RTA_PAYLOAD(tb[TCA_FQ_FLOW_MAX_RATE]) >= sizeof(__u32)) { -+ rate = rta_getattr_u32(tb[TCA_FQ_FLOW_MAX_RATE]); -+ -+ if (rate != ~0U) -+ fprintf(f, "maxrate %s ", sprint_rate(rate, b1)); -+ } -+ if (tb[TCA_FQ_FLOW_DEFAULT_RATE] && -+ RTA_PAYLOAD(tb[TCA_FQ_FLOW_DEFAULT_RATE]) >= sizeof(__u32)) { -+ rate = rta_getattr_u32(tb[TCA_FQ_FLOW_DEFAULT_RATE]); -+ -+ if (rate != 0) -+ fprintf(f, "defrate %s ", sprint_rate(rate, b1)); -+ } -+ -+ return 0; -+} -+ -+static int fq_print_xstats(struct qdisc_util *qu, FILE *f, -+ struct rtattr *xstats) -+{ -+ struct tc_fq_qd_stats *st; -+ -+ if (xstats == NULL) -+ return 0; -+ -+ if (RTA_PAYLOAD(xstats) < sizeof(*st)) -+ return -1; -+ -+ st = RTA_DATA(xstats); -+ -+ fprintf(f, " %u flows (%u inactive, %u throttled)", -+ st->flows, st->inactive_flows, st->throttled_flows); -+ -+ if (st->time_next_delayed_flow > 0) -+ fprintf(f, ", next packet delay %llu ns", st->time_next_delayed_flow); -+ -+ fprintf(f, "\n %llu gc, %llu highprio", -+ st->gc_flows, st->highprio_packets); -+ -+ if (st->tcp_retrans) -+ fprintf(f, ", %llu retrans", st->tcp_retrans); -+ -+ fprintf(f, ", %llu throttled", st->throttled); -+ -+ if (st->flows_plimit) -+ fprintf(f, ", %llu flows_plimit", st->flows_plimit); -+ -+ if (st->pkts_too_long || st->allocation_errors) -+ fprintf(f, "\n %llu too long pkts, %llu alloc errors\n", -+ st->pkts_too_long, st->allocation_errors); -+ -+ return 0; -+} -+ -+struct qdisc_util fq_qdisc_util = { -+ .id = "fq", -+ .parse_qopt = fq_parse_opt, -+ .print_qopt = fq_print_opt, -+ .print_xstats = fq_print_xstats, -+}; --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-route.patch b/SOURCES/iproute2-3.10.0-route.patch deleted file mode 100644 index f455da1..0000000 --- a/SOURCES/iproute2-3.10.0-route.patch +++ /dev/null @@ -1,29 +0,0 @@ -commit 922b4822043726dedee2b8e5c3729f7b1e856139 -Author: Pavel Simerda <psimerda@redhat.com> -Date: Tue Dec 2 17:45:10 2014 +0100 - - ip route: don't assume default route - - Just print the help when "ip route del" is called without any other - arguments. - - Resolves: - - * https://bugzilla.redhat.com/show_bug.cgi?id=997965 - - Signed-off-by: Pavel Šimerda <psimerda@redhat.com> - -diff --git a/ip/iproute.c b/ip/iproute.c -index c9cf5d6..32847c6 100644 ---- a/ip/iproute.c -+++ b/ip/iproute.c -@@ -975,6 +975,9 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) - argc--; argv++; - } - -+ if (!dst_ok) -+ usage(); -+ - if (d || nhs_ok) { - int idx; - diff --git a/SOURCES/iproute2-3.10.0-rtt.patch b/SOURCES/iproute2-3.10.0-rtt.patch deleted file mode 100644 index d6307c0..0000000 --- a/SOURCES/iproute2-3.10.0-rtt.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff --git a/lib/utils.c b/lib/utils.c -index dae1b51..55fea18 100644 ---- a/lib/utils.c -+++ b/lib/utils.c -@@ -144,8 +144,7 @@ int get_time_rtt(unsigned *val, const char *arg, int *raw) - if (t < 0.0) - return -1; - -- /* extra non-digits */ -- if (!p || p == arg || *p) -+ if (!p || p == arg) - return -1; - - /* over/underflow */ -@@ -154,8 +153,7 @@ int get_time_rtt(unsigned *val, const char *arg, int *raw) - } else { - res = strtoul(arg, &p, 0); - -- /* empty string or trailing non-digits */ -- if (!p || p == arg || *p) -+ if (!p || p == arg) - return -1; - - /* overflow */ -@@ -165,8 +163,6 @@ int get_time_rtt(unsigned *val, const char *arg, int *raw) - t = (double)res; - } - -- if (p == arg) -- return -1; - *raw = 1; - - if (*p) { diff --git a/SOURCES/iproute2-3.10.0-ss-print-value-of-IPV6_V6ONLY-socket-option-if-set.patch b/SOURCES/iproute2-3.10.0-ss-print-value-of-IPV6_V6ONLY-socket-option-if-set.patch deleted file mode 100644 index 6a8a85d..0000000 --- a/SOURCES/iproute2-3.10.0-ss-print-value-of-IPV6_V6ONLY-socket-option-if-set.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 14809558dba9fe8c9ff2943fbea8cb05f6a1bfbf Mon Sep 17 00:00:00 2001 -From: Phil Sutter <phil@nwl.cc> -Date: Wed, 24 Jun 2015 13:07:20 +0200 -Subject: [PATCH 2/2] ss: print value of IPV6_V6ONLY socket option if set - -If available and set, print 'v6only:1' for AF_INET6 sockets upon request -of extended information. For IPv6 sockets bound to in6addr_any, this is -the only way to determine if they will also accept IPv4 requests or not. - -Signed-off-by: Phil Sutter <phil@nwl.cc> ---- - misc/ss.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/misc/ss.c b/misc/ss.c -index 954a30b..ec08e03 100644 ---- a/misc/ss.c -+++ b/misc/ss.c -@@ -2026,6 +2026,11 @@ static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol) - - if (show_details) { - sock_details_print(&s); -+ if (s.local.family == AF_INET6 && tb[INET_DIAG_SKV6ONLY]) { -+ unsigned char v6only; -+ v6only = *(__u8 *)RTA_DATA(tb[INET_DIAG_SKV6ONLY]); -+ printf(" v6only:%u", v6only); -+ } - if (tb[INET_DIAG_SHUTDOWN]) { - unsigned char mask; - mask = *(__u8 *)RTA_DATA(tb[INET_DIAG_SHUTDOWN]); --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-ss.patch b/SOURCES/iproute2-3.10.0-ss.patch deleted file mode 100644 index 938928f..0000000 --- a/SOURCES/iproute2-3.10.0-ss.patch +++ /dev/null @@ -1,3644 +0,0 @@ -From 86f398ded8260a68b52de1f6669f5c3ccc69b350 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20=C5=A0imerda?= <psimerda@redhat.com> -Date: Mon, 27 Apr 2015 14:56:19 +0200 -Subject: [PATCH iproute2 3/4] backport 'ss' command from 4.0.0 - -Patch obtained using the following command. - -git diff v3.10.0..v4.0.0 misc/ss* man/man8/ss.8 doc/ss.sgml - -Plus added missing hooks to check for SELinux and the following fixup: -- d2055ea ss: Fix allocation of cong control alg name ---- - configure | 15 + - doc/ss.sgml | 2 +- - man/man8/ss.8 | 82 +- - misc/Makefile | 5 + - misc/ss.c | 2321 +++++++++++++++++++++++++++++++------------------------ - misc/ssfilter.h | 4 +- - misc/ssfilter.y | 23 +- - 7 files changed, 1419 insertions(+), 1033 deletions(-) - -diff --git a/configure b/configure -index da01c19..d5170f0 100755 ---- a/configure -+++ b/configure -@@ -231,6 +231,18 @@ EOF - rm -f $TMPDIR/ipsettest.c $TMPDIR/ipsettest - } - -+check_selinux() -+# SELinux is a compile time option in the ss utility -+{ -+ if ${PKG_CONFIG} libselinux --exists -+ then -+ echo "HAVE_SELINUX:=y" >>Config -+ echo "yes" -+ else -+ echo "no" -+ fi -+} -+ - echo "# Generated config based on" $INCLUDE >Config - check_toolchain - -@@ -253,3 +265,6 @@ check_ipt_lib_dir - - echo -n "libc has setns: " - check_setns -+ -+echo -n "SELinux support: " -+check_selinux -diff --git a/doc/ss.sgml b/doc/ss.sgml -index 0b1b533..3024b57 100644 ---- a/doc/ss.sgml -+++ b/doc/ss.sgml -@@ -3,7 +3,7 @@ - <article> - - <title>SS Utility: Quick Intro --<author>Alexey Kuznetosv, <tt/kuznet@ms2.inr.ac.ru/ -+<author>Alexey Kuznetsov, <tt/kuznet@ms2.inr.ac.ru/ - <date>some_negative_number, 20 Sep 2001 - <abstract> - <tt/ss/ is one another utility to investigate sockets. -diff --git a/man/man8/ss.8 b/man/man8/ss.8 -index e55dd0c..b7fbaef 100644 ---- a/man/man8/ss.8 -+++ b/man/man8/ss.8 -@@ -53,6 +53,40 @@ Print summary statistics. This option does not parse socket lists obtaining - summary from various sources. It is useful when amount of sockets is so huge - that parsing /proc/net/tcp is painful. - .TP -+.B \-Z, \-\-context -+As the -+.B \-p -+option but also shows process security context. -+.sp -+For -+.BR netlink (7) -+sockets the initiating process context is displayed as follows: -+.RS -+.RS -+.IP "1." 4 -+If valid pid show the process context. -+.IP "2." 4 -+If destination is kernel (pid = 0) show kernel initial context. -+.IP "3." 4 -+If a unique identifier has been allocated by the kernel or netlink user, -+show context as "unavailable". This will generally indicate that a -+process has more than one netlink socket active. -+.RE -+.RE -+.TP -+.B \-z, \-\-contexts -+As the -+.B \-Z -+option but also shows the socket context. The socket context is -+taken from the associated inode and is not the actual socket -+context held by the kernel. Sockets are typically labeled with the -+context of the creating process, however the context shown will reflect -+any policy role, type and/or range transition rules applied, -+and is therefore a useful reference. -+.TP -+.B \-N NSNAME, \-\-net=NSNAME -+Switch to the specified network namespace name. -+.TP - .B \-b, \-\-bpf - Show socket BPF filters (only administrators are allowed to get these information). - .TP -@@ -87,7 +121,7 @@ Currently the following families are supported: unix, inet, inet6, link, netlink - .B \-A QUERY, \-\-query=QUERY, \-\-socket=QUERY - List of socket tables to dump, separated by commas. The following identifiers - are understood: all, inet, tcp, udp, raw, unix, packet, netlink, unix_dgram, --unix_stream, packet_raw, packet_dgram. -+unix_stream, unix_seqpacket, packet_raw, packet_dgram. - .TP - .B \-D FILE, \-\-diag=FILE - Do not display anything, just dump raw information about TCP sockets to FILE after applying filters. If FILE is - stdout is used. -@@ -96,13 +130,49 @@ Do not display anything, just dump raw information about TCP sockets to FILE aft - Read filter information from FILE. - Each line of FILE is interpreted like single command line option. If FILE is - stdin is used. - .TP --.B FILTER := [ state TCP-STATE ] [ EXPRESSION ] -+.B FILTER := [ state STATE-FILTER ] [ EXPRESSION ] - Please take a look at the official documentation (Debian package iproute-doc) for details regarding filters. -+ -+.SH STATE-FILTER -+ -+.B STATE-FILTER -+allows to construct arbitrary set of states to match. Its syntax is sequence of keywords state and exclude followed by identifier of state. -+.TP -+Available identifiers are: -+ -+All standard TCP states: -+.BR established ", " syn-sent ", " syn-recv ", " fin-wait-1 ", " fin-wait-2 ", " time-wait ", " closed ", " close-wait ", " last-ack ", " -+.BR listen " and " closing. -+ -+.B all -+- for all the states -+ -+.B connected -+- all the states except for -+.BR listen " and " closed -+ -+.B synchronized -+- all the -+.B connected -+states except for -+.B syn-sent -+ -+.B bucket -+- states, which are maintained as minisockets, i.e. -+.BR time-wait " and " syn-recv -+ -+.B big -+- opposite to -+.B bucket -+ - .SH USAGE EXAMPLES - .TP - .B ss -t -a - Display all TCP sockets. - .TP -+.B ss -t -a -Z -+Display all TCP sockets with process SELinux security contexts. -+.TP - .B ss -u -a - Display all UDP sockets. - .TP -@@ -116,10 +186,14 @@ Find all local processes connected to X server. - List all the tcp sockets in state FIN-WAIT-1 for our apache to network 193.233.7/24 and look at their timers. - .SH SEE ALSO - .BR ip (8), --.BR /usr/share/doc/iproute-doc/ss.html " (package iproute�doc)" -+.BR /usr/share/doc/iproute-doc/ss.html " (package iproute�doc)", -+.br -+.BR RFC " 793 " -+- https://tools.ietf.org/rfc/rfc793.txt (TCP states) -+ - .SH AUTHOR - .I ss --was written by Alexey Kuznetosv, <kuznet@ms2.inr.ac.ru>. -+was written by Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>. - .PP - This manual page was written by Michael Prokop <mika@grml.org> - for the Debian project (but may be used by others). -diff --git a/misc/Makefile b/misc/Makefile -index a516bd8..b7ecba9 100644 ---- a/misc/Makefile -+++ b/misc/Makefile -@@ -5,6 +5,11 @@ TARGETS=ss nstat ifstat rtacct arpd lnstat - - include ../Config - -+ifeq ($(HAVE_SELINUX),y) -+ LDLIBS += $(shell pkg-config --libs libselinux) -+ CFLAGS += $(shell pkg-config --cflags libselinux) -DHAVE_SELINUX -+endif -+ - ifeq ($(IP_CONFIG_SETNS),y) - CFLAGS += -DHAVE_SETNS - endif -diff --git a/misc/ss.c b/misc/ss.c -index c0369f1..954a30b 100644 ---- a/misc/ss.c -+++ b/misc/ss.c -@@ -25,11 +25,13 @@ - #include <dirent.h> - #include <fnmatch.h> - #include <getopt.h> -+#include <stdbool.h> - - #include "utils.h" - #include "rt_names.h" - #include "ll_map.h" - #include "libnetlink.h" -+#include "namespace.h" - #include "SNAPSHOT.h" - - #include <linux/tcp.h> -@@ -41,6 +43,49 @@ - #include <linux/packet_diag.h> - #include <linux/netlink_diag.h> - -+#define MAGIC_SEQ 123456 -+ -+#define DIAG_REQUEST(_req, _r) \ -+ struct { \ -+ struct nlmsghdr nlh; \ -+ _r; \ -+ } _req = { \ -+ .nlh = { \ -+ .nlmsg_type = SOCK_DIAG_BY_FAMILY, \ -+ .nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST,\ -+ .nlmsg_seq = MAGIC_SEQ, \ -+ .nlmsg_len = sizeof(_req), \ -+ }, \ -+ } -+ -+#if HAVE_SELINUX -+#include <selinux/selinux.h> -+#else -+/* Stubs for SELinux functions */ -+static int is_selinux_enabled(void) -+{ -+ return -1; -+} -+ -+static int getpidcon(pid_t pid, char **context) -+{ -+ *context = NULL; -+ return -1; -+} -+ -+static int getfilecon(char *path, char **context) -+{ -+ *context = NULL; -+ return -1; -+} -+ -+static int security_get_initial_context(char *name, char **context) -+{ -+ *context = NULL; -+ return -1; -+} -+#endif -+ - int resolve_hosts = 0; - int resolve_services = 1; - int preferred_family = AF_UNSPEC; -@@ -50,6 +95,10 @@ int show_users = 0; - int show_mem = 0; - int show_tcpinfo = 0; - int show_bpf = 0; -+int show_proc_ctx = 0; -+int show_sock_ctx = 0; -+/* If show_users & show_proc_ctx only do user_ent_hash_build() once */ -+int user_ent_hash_build_init = 0; - - int netid_width; - int state_width; -@@ -71,6 +120,7 @@ enum - RAW_DB, - UNIX_DG_DB, - UNIX_ST_DB, -+ UNIX_SQ_DB, - PACKET_DG_DB, - PACKET_R_DB, - NETLINK_DB, -@@ -78,8 +128,9 @@ enum - }; - - #define PACKET_DBM ((1<<PACKET_DG_DB)|(1<<PACKET_R_DB)) --#define UNIX_DBM ((1<<UNIX_DG_DB)|(1<<UNIX_ST_DB)) -+#define UNIX_DBM ((1<<UNIX_DG_DB)|(1<<UNIX_ST_DB)|(1<<UNIX_SQ_DB)) - #define ALL_DB ((1<<MAX_DB)-1) -+#define INET_DBM ((1<<TCP_DB)|(1<<UDP_DB)|(1<<DCCP_DB)|(1<<RAW_DB)) - - enum { - SS_UNKNOWN, -@@ -97,7 +148,8 @@ enum { - SS_MAX - }; - --#define SS_ALL ((1<<SS_MAX)-1) -+#define SS_ALL ((1 << SS_MAX) - 1) -+#define SS_CONN (SS_ALL & ~((1<<SS_LISTEN)|(1<<SS_CLOSE)|(1<<SS_TIME_WAIT)|(1<<SS_SYN_RECV))) - - #include "ssfilter.h" - -@@ -109,13 +161,127 @@ struct filter - struct ssfilter *f; - }; - --struct filter default_filter = { -- .dbs = ~0, -- .states = SS_ALL & ~((1<<SS_LISTEN)|(1<<SS_CLOSE)|(1<<SS_TIME_WAIT)|(1<<SS_SYN_RECV)), -- .families= (1<<AF_INET)|(1<<AF_INET6), -+static const struct filter default_dbs[MAX_DB] = { -+ [TCP_DB] = { -+ .states = SS_CONN, -+ .families = (1 << AF_INET) | (1 << AF_INET6), -+ }, -+ [DCCP_DB] = { -+ .states = SS_CONN, -+ .families = (1 << AF_INET) | (1 << AF_INET6), -+ }, -+ [UDP_DB] = { -+ .states = (1 << SS_ESTABLISHED), -+ .families = (1 << AF_INET) | (1 << AF_INET6), -+ }, -+ [RAW_DB] = { -+ .states = (1 << SS_ESTABLISHED), -+ .families = (1 << AF_INET) | (1 << AF_INET6), -+ }, -+ [UNIX_DG_DB] = { -+ .states = (1 << SS_CLOSE), -+ .families = (1 << AF_UNIX), -+ }, -+ [UNIX_ST_DB] = { -+ .states = SS_CONN, -+ .families = (1 << AF_UNIX), -+ }, -+ [UNIX_SQ_DB] = { -+ .states = SS_CONN, -+ .families = (1 << AF_UNIX), -+ }, -+ [PACKET_DG_DB] = { -+ .states = (1 << SS_CLOSE), -+ .families = (1 << AF_PACKET), -+ }, -+ [PACKET_R_DB] = { -+ .states = (1 << SS_CLOSE), -+ .families = (1 << AF_PACKET), -+ }, -+ [NETLINK_DB] = { -+ .states = (1 << SS_CLOSE), -+ .families = (1 << AF_NETLINK), -+ }, -+}; -+ -+static const struct filter default_afs[AF_MAX] = { -+ [AF_INET] = { -+ .dbs = INET_DBM, -+ .states = SS_CONN, -+ }, -+ [AF_INET6] = { -+ .dbs = INET_DBM, -+ .states = SS_CONN, -+ }, -+ [AF_UNIX] = { -+ .dbs = UNIX_DBM, -+ .states = SS_CONN, -+ }, -+ [AF_PACKET] = { -+ .dbs = PACKET_DBM, -+ .states = (1 << SS_CLOSE), -+ }, -+ [AF_NETLINK] = { -+ .dbs = (1 << NETLINK_DB), -+ .states = (1 << SS_CLOSE), -+ }, - }; - --struct filter current_filter; -+static int do_default = 1; -+static struct filter current_filter; -+ -+static void filter_db_set(struct filter *f, int db) -+{ -+ f->states |= default_dbs[db].states; -+ f->families |= default_dbs[db].families; -+ f->dbs |= 1 << db; -+ do_default = 0; -+} -+ -+static void filter_af_set(struct filter *f, int af) -+{ -+ f->dbs |= default_afs[af].dbs; -+ f->states |= default_afs[af].states; -+ f->families |= 1 << af; -+ do_default = 0; -+ preferred_family = af; -+} -+ -+static int filter_af_get(struct filter *f, int af) -+{ -+ return f->families & (1 << af); -+} -+ -+static void filter_default_dbs(struct filter *f) -+{ -+ filter_db_set(f, UDP_DB); -+ filter_db_set(f, DCCP_DB); -+ filter_db_set(f, TCP_DB); -+ filter_db_set(f, RAW_DB); -+ filter_db_set(f, UNIX_ST_DB); -+ filter_db_set(f, UNIX_DG_DB); -+ filter_db_set(f, UNIX_SQ_DB); -+ filter_db_set(f, PACKET_R_DB); -+ filter_db_set(f, PACKET_DG_DB); -+ filter_db_set(f, NETLINK_DB); -+} -+ -+static void filter_merge(struct filter *af, struct filter *dbf, int states) -+{ -+ if (af->families) -+ af->families = (af->families | dbf->families) & af->families; -+ else -+ af->families = dbf->families; -+ -+ if (dbf->dbs) -+ af->dbs = (af->dbs | dbf->dbs) & dbf->dbs; -+ -+ if (dbf->states) -+ af->states = (af->states | dbf->states) & dbf->states; -+ -+ if (states) -+ af->states = (af->states | states) & states; -+} - - static FILE *generic_proc_open(const char *env, const char *name) - { -@@ -206,7 +372,9 @@ struct user_ent { - unsigned int ino; - int pid; - int fd; -- char process[0]; -+ char *process; -+ char *process_ctx; -+ char *socket_ctx; - }; - - #define USER_ENT_HASH_SIZE 256 -@@ -219,26 +387,50 @@ static int user_ent_hashfn(unsigned int ino) - return val & (USER_ENT_HASH_SIZE - 1); - } - --static void user_ent_add(unsigned int ino, const char *process, int pid, int fd) -+static void user_ent_add(unsigned int ino, char *process, -+ int pid, int fd, -+ char *proc_ctx, -+ char *sock_ctx) - { - struct user_ent *p, **pp; -- int str_len; - -- str_len = strlen(process) + 1; -- p = malloc(sizeof(struct user_ent) + str_len); -- if (!p) -+ p = malloc(sizeof(struct user_ent)); -+ if (!p) { -+ fprintf(stderr, "ss: failed to malloc buffer\n"); - abort(); -+ } - p->next = NULL; - p->ino = ino; - p->pid = pid; - p->fd = fd; -- strcpy(p->process, process); -+ p->process = strdup(process); -+ p->process_ctx = strdup(proc_ctx); -+ p->socket_ctx = strdup(sock_ctx); - - pp = &user_ent_hash[user_ent_hashfn(ino)]; - p->next = *pp; - *pp = p; - } - -+static void user_ent_destroy(void) -+{ -+ struct user_ent *p, *p_next; -+ int cnt = 0; -+ -+ while (cnt != USER_ENT_HASH_SIZE) { -+ p = user_ent_hash[cnt]; -+ while (p) { -+ free(p->process); -+ free(p->process_ctx); -+ free(p->socket_ctx); -+ p_next = p->next; -+ free(p); -+ p = p_next; -+ } -+ cnt++; -+ } -+} -+ - static void user_ent_hash_build(void) - { - const char *root = getenv("PROC_ROOT") ? : "/proc/"; -@@ -246,6 +438,15 @@ static void user_ent_hash_build(void) - char name[1024]; - int nameoff; - DIR *dir; -+ char *pid_context; -+ char *sock_context; -+ const char *no_ctx = "unavailable"; -+ -+ /* If show_users & show_proc_ctx set only do this once */ -+ if (user_ent_hash_build_init != 0) -+ return; -+ -+ user_ent_hash_build_init = 1; - - strcpy(name, root); - if (strlen(name) == 0 || name[strlen(name)-1] != '/') -@@ -260,6 +461,7 @@ static void user_ent_hash_build(void) - while ((d = readdir(dir)) != NULL) { - struct dirent *d1; - char process[16]; -+ char *p; - int pid, pos; - DIR *dir1; - char crap; -@@ -267,12 +469,16 @@ static void user_ent_hash_build(void) - if (sscanf(d->d_name, "%d%c", &pid, &crap) != 1) - continue; - -+ if (getpidcon(pid, &pid_context) != 0) -+ pid_context = strdup(no_ctx); -+ - sprintf(name + nameoff, "%d/fd/", pid); - pos = strlen(name); - if ((dir1 = opendir(name)) == NULL) - continue; - - process[0] = '\0'; -+ p = process; - - while ((d1 = readdir(dir1)) != NULL) { - const char *pattern = "socket:["; -@@ -280,6 +486,7 @@ static void user_ent_hash_build(void) - char lnk[64]; - int fd; - ssize_t link_len; -+ char tmp[1024]; - - if (sscanf(d1->d_name, "%d%c", &fd, &crap) != 1) - continue; -@@ -296,55 +503,107 @@ static void user_ent_hash_build(void) - - sscanf(lnk, "socket:[%u]", &ino); - -- if (process[0] == '\0') { -- char tmp[1024]; -+ snprintf(tmp, sizeof(tmp), "%s/%d/fd/%s", -+ root, pid, d1->d_name); -+ -+ if (getfilecon(tmp, &sock_context) <= 0) -+ sock_context = strdup(no_ctx); -+ -+ if (*p == '\0') { - FILE *fp; - -- snprintf(tmp, sizeof(tmp), "%s/%d/stat", root, pid); -+ snprintf(tmp, sizeof(tmp), "%s/%d/stat", -+ root, pid); - if ((fp = fopen(tmp, "r")) != NULL) { -- fscanf(fp, "%*d (%[^)])", process); -+ fscanf(fp, "%*d (%[^)])", p); - fclose(fp); - } - } -- -- user_ent_add(ino, process, pid, fd); -+ user_ent_add(ino, p, pid, fd, -+ pid_context, sock_context); -+ free(sock_context); - } -+ free(pid_context); - closedir(dir1); - } - closedir(dir); - } - --static int find_users(unsigned ino, char *buf, int buflen) -+enum entry_types { -+ USERS, -+ PROC_CTX, -+ PROC_SOCK_CTX -+}; -+ -+#define ENTRY_BUF_SIZE 512 -+static int find_entry(unsigned ino, char **buf, int type) - { - struct user_ent *p; - int cnt = 0; - char *ptr; -+ char **new_buf = buf; -+ int len, new_buf_len; -+ int buf_used = 0; -+ int buf_len = 0; - - if (!ino) - return 0; - - p = user_ent_hash[user_ent_hashfn(ino)]; -- ptr = buf; -+ ptr = *buf = NULL; - while (p) { - if (p->ino != ino) - goto next; - -- if (ptr - buf >= buflen - 1) -- break; -+ while (1) { -+ ptr = *buf + buf_used; -+ switch (type) { -+ case USERS: -+ len = snprintf(ptr, buf_len - buf_used, -+ "(\"%s\",pid=%d,fd=%d),", -+ p->process, p->pid, p->fd); -+ break; -+ case PROC_CTX: -+ len = snprintf(ptr, buf_len - buf_used, -+ "(\"%s\",pid=%d,proc_ctx=%s,fd=%d),", -+ p->process, p->pid, -+ p->process_ctx, p->fd); -+ break; -+ case PROC_SOCK_CTX: -+ len = snprintf(ptr, buf_len - buf_used, -+ "(\"%s\",pid=%d,proc_ctx=%s,fd=%d,sock_ctx=%s),", -+ p->process, p->pid, -+ p->process_ctx, p->fd, -+ p->socket_ctx); -+ break; -+ default: -+ fprintf(stderr, "ss: invalid type: %d\n", type); -+ abort(); -+ } - -- snprintf(ptr, buflen - (ptr - buf), -- "(\"%s\",%d,%d),", -- p->process, p->pid, p->fd); -- ptr += strlen(ptr); -+ if (len < 0 || len >= buf_len - buf_used) { -+ new_buf_len = buf_len + ENTRY_BUF_SIZE; -+ *new_buf = realloc(*buf, new_buf_len); -+ if (!new_buf) { -+ fprintf(stderr, "ss: failed to malloc buffer\n"); -+ abort(); -+ } -+ **buf = **new_buf; -+ buf_len = new_buf_len; -+ continue; -+ } else { -+ buf_used += len; -+ break; -+ } -+ } - cnt++; -- -- next: -+next: - p = p->next; - } -- -- if (ptr != buf) -+ if (buf_used) { -+ ptr = *buf + buf_used; - ptr[-1] = '\0'; -- -+ } - return cnt; - } - -@@ -359,7 +618,7 @@ struct slabstat - int skbs; - }; - --struct slabstat slabstat; -+static struct slabstat slabstat; - - static const char *slabstat_ids[] = - { -@@ -375,6 +634,10 @@ static int get_slabstat(struct slabstat *s) - char buf[256]; - FILE *fp; - int cnt; -+ static int slabstat_valid; -+ -+ if (slabstat_valid) -+ return 0; - - memset(s, 0, sizeof(*s)); - -@@ -398,10 +661,29 @@ static int get_slabstat(struct slabstat *s) - break; - } - -+ slabstat_valid = 1; -+ - fclose(fp); - return 0; - } - -+static inline void sock_addr_set_str(inet_prefix *prefix, char **ptr) -+{ -+ memcpy(prefix->data, ptr, sizeof(char *)); -+} -+ -+static inline char *sock_addr_get_str(const inet_prefix *prefix) -+{ -+ char *tmp ; -+ memcpy(&tmp, prefix->data, sizeof(char *)); -+ return tmp; -+} -+ -+static unsigned long long cookie_sk_get(const uint32_t *cookie) -+{ -+ return (((unsigned long long)cookie[1] << 31) << 1) | cookie[0]; -+} -+ - static const char *sstate_name[] = { - "UNKNOWN", - [SS_ESTABLISHED] = "ESTAB", -@@ -432,25 +714,106 @@ static const char *sstate_namel[] = { - [SS_CLOSING] = "closing", - }; - -+struct sockstat -+{ -+ struct sockstat *next; -+ unsigned int type; -+ uint16_t prot; -+ inet_prefix local; -+ inet_prefix remote; -+ int lport; -+ int rport; -+ int state; -+ int rq, wq; -+ unsigned ino; -+ unsigned uid; -+ int refcnt; -+ unsigned int iface; -+ unsigned long long sk; -+}; -+ -+struct dctcpstat -+{ -+ unsigned int ce_state; -+ unsigned int alpha; -+ unsigned int ab_ecn; -+ unsigned int ab_tot; -+ bool enabled; -+}; -+ - struct tcpstat - { -- inet_prefix local; -- inet_prefix remote; -- int lport; -- int rport; -- int state; -- int rq, wq; -- int timer; -- int timeout; -- int retrs; -- unsigned ino; -- int probes; -- unsigned uid; -- int refcnt; -- unsigned long long sk; -- int rto, ato, qack, cwnd, ssthresh; -+ struct sockstat ss; -+ int timer; -+ int timeout; -+ int probes; -+ char cong_alg[16]; -+ double rto, ato, rtt, rttvar; -+ int qack, cwnd, ssthresh, backoff; -+ double send_bps; -+ int snd_wscale; -+ int rcv_wscale; -+ int mss; -+ unsigned int lastsnd; -+ unsigned int lastrcv; -+ unsigned int lastack; -+ double pacing_rate; -+ double pacing_rate_max; -+ unsigned int unacked; -+ unsigned int retrans; -+ unsigned int retrans_total; -+ unsigned int lost; -+ unsigned int sacked; -+ unsigned int fackets; -+ unsigned int reordering; -+ double rcv_rtt; -+ int rcv_space; -+ bool has_ts_opt; -+ bool has_sack_opt; -+ bool has_ecn_opt; -+ bool has_ecnseen_opt; -+ bool has_fastopen_opt; -+ bool has_wscale_opt; -+ struct dctcpstat *dctcp; - }; - -+static void sock_state_print(struct sockstat *s, const char *sock_name) -+{ -+ if (netid_width) -+ printf("%-*s ", netid_width, sock_name); -+ if (state_width) -+ printf("%-*s ", state_width, sstate_name[s->state]); -+ -+ printf("%-6d %-6d ", s->rq, s->wq); -+} -+ -+static void sock_details_print(struct sockstat *s) -+{ -+ if (s->uid) -+ printf(" uid:%u", s->uid); -+ -+ printf(" ino:%u", s->ino); -+ printf(" sk:%llx", s->sk); -+} -+ -+static void sock_addr_print_width(int addr_len, const char *addr, char *delim, -+ int port_len, const char *port, const char *ifname) -+{ -+ if (ifname) { -+ printf("%*s%%%s%s%-*s ", addr_len, addr, ifname, delim, -+ port_len, port); -+ } -+ else { -+ printf("%*s%s%-*s ", addr_len, addr, delim, port_len, port); -+ } -+} -+ -+static void sock_addr_print(const char *addr, char *delim, const char *port, -+ const char *ifname) -+{ -+ sock_addr_print_width(addr_width, addr, delim, serv_width, port, ifname); -+} -+ - static const char *tmr_name[] = { - "off", - "on", -@@ -487,12 +850,6 @@ static const char *print_ms_timer(int timeout) - return buf; - } - --static const char *print_hz_timer(int timeout) --{ -- int hz = get_user_hz(); -- return print_ms_timer(((timeout*1000) + hz-1)/hz); --} -- - struct scache - { - struct scache *next; -@@ -639,13 +996,12 @@ static const char *resolve_service(int port) - return buf; - } - --static void formatted_print(const inet_prefix *a, int port) -+static void inet_addr_print(const inet_prefix *a, int port, unsigned int ifindex) - { - char buf[1024]; - const char *ap = buf; -- int est_len; -- -- est_len = addr_width; -+ int est_len = addr_width; -+ const char *ifname = NULL; - - if (a->family == AF_INET) { - if (a->data[0] == 0) { -@@ -662,7 +1018,14 @@ static void formatted_print(const inet_prefix *a, int port) - else - est_len = addr_width + ((est_len-addr_width+3)/4)*4; - } -- printf("%*s:%-*s ", est_len, ap, serv_width, resolve_service(port)); -+ -+ if (ifindex) { -+ ifname = ll_index_to_name(ifindex); -+ est_len -= strlen(ifname) + 1; /* +1 for percent char */ -+ } -+ -+ sock_addr_print_width(est_len, ap, ":", serv_width, resolve_service(port), -+ ifname); - } - - struct aafilter -@@ -694,9 +1057,9 @@ static int inet2_addr_match(const inet_prefix *a, const inet_prefix *p, - - static int unix_match(const inet_prefix *a, const inet_prefix *p) - { -- char *addr, *pattern; -- memcpy(&addr, a->data, sizeof(addr)); -- memcpy(&pattern, p->data, sizeof(pattern)); -+ char *addr = sock_addr_get_str(a); -+ char *pattern = sock_addr_get_str(p); -+ - if (pattern == NULL) - return 1; - if (addr == NULL) -@@ -704,7 +1067,7 @@ static int unix_match(const inet_prefix *a, const inet_prefix *p) - return !fnmatch(pattern, addr, 0); - } - --static int run_ssfilter(struct ssfilter *f, struct tcpstat *s) -+static int run_ssfilter(struct ssfilter *f, struct sockstat *s) - { - switch (f->type) { - case SSF_S_AUTO: -@@ -712,8 +1075,7 @@ static int run_ssfilter(struct ssfilter *f, struct tcpstat *s) - static int low, high=65535; - - if (s->local.family == AF_UNIX) { -- char *p; -- memcpy(&p, s->local.data, sizeof(p)); -+ char *p = sock_addr_get_str(&s->local); - return p == NULL || (p[0] == '@' && strlen(p) == 6 && - strspn(p+1, "0123456789abcdef") == 5); - } -@@ -894,7 +1256,8 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode) - - case SSF_AND: - { -- char *a1, *a2, *a, l1, l2; -+ char *a1, *a2, *a; -+ int l1, l2; - l1 = ssfilter_bytecompile(f->pred, &a1); - l2 = ssfilter_bytecompile(f->post, &a2); - if (!(a = malloc(l1+l2))) abort(); -@@ -907,7 +1270,8 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode) - } - case SSF_OR: - { -- char *a1, *a2, *a, l1, l2; -+ char *a1, *a2, *a; -+ int l1, l2; - l1 = ssfilter_bytecompile(f->pred, &a1); - l2 = ssfilter_bytecompile(f->post, &a2); - if (!(a = malloc(l1+l2+4))) abort(); -@@ -920,7 +1284,8 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode) - } - case SSF_NOT: - { -- char *a1, *a, l1; -+ char *a1, *a; -+ int l1; - l1 = ssfilter_bytecompile(f->pred, &a1); - if (!(a = malloc(l1+4))) abort(); - memcpy(a, a1, l1); -@@ -993,7 +1358,9 @@ static int xll_initted = 0; - static void xll_init(void) - { - struct rtnl_handle rth; -- rtnl_open(&rth, 0); -+ if (rtnl_open(&rth, 0) < 0) -+ exit(1); -+ - ll_init_map(&rth); - rtnl_close(&rth); - xll_initted = 1; -@@ -1013,15 +1380,13 @@ static int xll_name_to_index(const char *dev) - return ll_name_to_index(dev); - } - --void *parse_hostcond(char *addr) -+void *parse_hostcond(char *addr, bool is_port) - { - char *port = NULL; -- struct aafilter a; -+ struct aafilter a = { .port = -1 }; - struct aafilter *res; - int fam = preferred_family; -- -- memset(&a, 0, sizeof(a)); -- a.port = -1; -+ struct filter *f = ¤t_filter; - - if (fam == AF_UNIX || strncmp(addr, "unix:", 5) == 0) { - char *p; -@@ -1030,7 +1395,8 @@ void *parse_hostcond(char *addr) - addr+=5; - p = strdup(addr); - a.addr.bitlen = 8*strlen(p); -- memcpy(a.addr.data, &p, sizeof(p)); -+ sock_addr_set_str(&a.addr, &p); -+ fam = AF_UNIX; - goto out; - } - -@@ -1056,6 +1422,7 @@ void *parse_hostcond(char *addr) - return NULL; - a.addr.data[0] = ntohs(tmp); - } -+ fam = AF_PACKET; - goto out; - } - -@@ -1078,26 +1445,21 @@ void *parse_hostcond(char *addr) - } - if (addr[0] && strcmp(addr, "*")) { - a.addr.bitlen = 32; -- if (get_u32(a.addr.data, addr, 0)) { -- if (strcmp(addr, "rtnl") == 0) -- a.addr.data[0] = 0; -- else if (strcmp(addr, "fw") == 0) -- a.addr.data[0] = 3; -- else if (strcmp(addr, "tcpdiag") == 0) -- a.addr.data[0] = 4; -- else -- return NULL; -- } -+ if (nl_proto_a2n(&a.addr.data[0], addr) == -1) -+ return NULL; - } -+ fam = AF_NETLINK; - goto out; - } - -- if (strncmp(addr, "inet:", 5) == 0) { -- addr += 5; -+ if (fam == AF_INET || !strncmp(addr, "inet:", 5)) { - fam = AF_INET; -- } else if (strncmp(addr, "inet6:", 6) == 0) { -- addr += 6; -+ if (!strncmp(addr, "inet:", 5)) -+ addr += 5; -+ } else if (fam == AF_INET6 || !strncmp(addr, "inet6:", 6)) { - fam = AF_INET6; -+ if (!strncmp(addr, "inet6:", 6)) -+ addr += 6; - } - - /* URL-like literal [] */ -@@ -1111,10 +1473,14 @@ void *parse_hostcond(char *addr) - } else { - port = strrchr(strchr(addr, '/') ? : addr, ':'); - } -+ -+ if (is_port) -+ port = addr; -+ - if (port && *port) { -- if (*port != ':') -- return NULL; -- *port++ = 0; -+ if (*port == ':') -+ *port++ = 0; -+ - if (*port && *port != '*') { - if (get_integer(&a.port, port, 0)) { - struct servent *se1 = NULL; -@@ -1155,7 +1521,7 @@ void *parse_hostcond(char *addr) - } - } - } -- if (addr && *addr && *addr != '*') { -+ if (!is_port && addr && *addr && *addr != '*') { - if (get_prefix_1(&a.addr, addr, fam)) { - if (get_dns_host(&a, addr, fam)) { - fprintf(stderr, "Error: an inet prefix is expected rather than \"%s\".\n", addr); -@@ -1164,133 +1530,274 @@ void *parse_hostcond(char *addr) - } - } - -- out: -+out: -+ if (fam != AF_UNSPEC) { -+ f->families = 0; -+ filter_af_set(f, fam); -+ filter_merge(f, f, 0); -+ } -+ - res = malloc(sizeof(*res)); - if (res) - memcpy(res, &a, sizeof(a)); - return res; - } - --static int tcp_show_line(char *line, const struct filter *f, int family) -+static char *proto_name(int protocol) -+{ -+ switch (protocol) { -+ case IPPROTO_UDP: -+ return "udp"; -+ case IPPROTO_TCP: -+ return "tcp"; -+ case IPPROTO_DCCP: -+ return "dccp"; -+ } -+ -+ return "???"; -+} -+ -+static void inet_stats_print(struct sockstat *s, int protocol) -+{ -+ char *buf = NULL; -+ -+ sock_state_print(s, proto_name(protocol)); -+ -+ inet_addr_print(&s->local, s->lport, s->iface); -+ inet_addr_print(&s->remote, s->rport, 0); -+ -+ if (show_proc_ctx || show_sock_ctx) { -+ if (find_entry(s->ino, &buf, -+ (show_proc_ctx & show_sock_ctx) ? -+ PROC_SOCK_CTX : PROC_CTX) > 0) { -+ printf(" users:(%s)", buf); -+ free(buf); -+ } -+ } else if (show_users) { -+ if (find_entry(s->ino, &buf, USERS) > 0) { -+ printf(" users:(%s)", buf); -+ free(buf); -+ } -+ } -+} -+ -+static int proc_parse_inet_addr(char *loc, char *rem, int family, struct -+ sockstat *s) -+{ -+ s->local.family = s->remote.family = family; -+ if (family == AF_INET) { -+ sscanf(loc, "%x:%x", s->local.data, (unsigned*)&s->lport); -+ sscanf(rem, "%x:%x", s->remote.data, (unsigned*)&s->rport); -+ s->local.bytelen = s->remote.bytelen = 4; -+ return 0; -+ } else { -+ sscanf(loc, "%08x%08x%08x%08x:%x", -+ s->local.data, -+ s->local.data + 1, -+ s->local.data + 2, -+ s->local.data + 3, -+ &s->lport); -+ sscanf(rem, "%08x%08x%08x%08x:%x", -+ s->remote.data, -+ s->remote.data + 1, -+ s->remote.data + 2, -+ s->remote.data + 3, -+ &s->rport); -+ s->local.bytelen = s->remote.bytelen = 16; -+ return 0; -+ } -+ return -1; -+} -+ -+static int proc_inet_split_line(char *line, char **loc, char **rem, char **data) - { -- struct tcpstat s; -- char *loc, *rem, *data; -- char opt[256]; -- int n; - char *p; - - if ((p = strchr(line, ':')) == NULL) - return -1; -- loc = p+2; - -- if ((p = strchr(loc, ':')) == NULL) -+ *loc = p+2; -+ if ((p = strchr(*loc, ':')) == NULL) - return -1; -- p[5] = 0; -- rem = p+6; - -- if ((p = strchr(rem, ':')) == NULL) -+ p[5] = 0; -+ *rem = p+6; -+ if ((p = strchr(*rem, ':')) == NULL) - return -1; -+ - p[5] = 0; -- data = p+6; -+ *data = p+6; -+ return 0; -+} - -- do { -- int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0'); -+static char *sprint_bw(char *buf, double bw) -+{ -+ if (bw > 1000000.) -+ sprintf(buf,"%.1fM", bw / 1000000.); -+ else if (bw > 1000.) -+ sprintf(buf,"%.1fK", bw / 1000.); -+ else -+ sprintf(buf, "%g", bw); - -- if (!(f->states & (1<<state))) -- return 0; -- } while (0); -+ return buf; -+} - -- s.local.family = s.remote.family = family; -- if (family == AF_INET) { -- sscanf(loc, "%x:%x", s.local.data, (unsigned*)&s.lport); -- sscanf(rem, "%x:%x", s.remote.data, (unsigned*)&s.rport); -- s.local.bytelen = s.remote.bytelen = 4; -- } else { -- sscanf(loc, "%08x%08x%08x%08x:%x", -- s.local.data, -- s.local.data+1, -- s.local.data+2, -- s.local.data+3, -- &s.lport); -- sscanf(rem, "%08x%08x%08x%08x:%x", -- s.remote.data, -- s.remote.data+1, -- s.remote.data+2, -- s.remote.data+3, -- &s.rport); -- s.local.bytelen = s.remote.bytelen = 16; -+static void tcp_stats_print(struct tcpstat *s) -+{ -+ char b1[64]; -+ -+ if (s->has_ts_opt) -+ printf(" ts"); -+ if (s->has_sack_opt) -+ printf(" sack"); -+ if (s->has_ecn_opt) -+ printf(" ecn"); -+ if (s->has_ecnseen_opt) -+ printf(" ecnseen"); -+ if (s->has_fastopen_opt) -+ printf(" fastopen"); -+ if (s->cong_alg[0]) -+ printf(" %s", s->cong_alg); -+ if (s->has_wscale_opt) -+ printf(" wscale:%d,%d", s->snd_wscale, s->rcv_wscale); -+ if (s->rto) -+ printf(" rto:%g", s->rto); -+ if (s->backoff) -+ printf(" backoff:%u", s->backoff); -+ if (s->rtt) -+ printf(" rtt:%g/%g", s->rtt, s->rttvar); -+ if (s->ato) -+ printf(" ato:%g", s->ato); -+ -+ if (s->qack) -+ printf(" qack:%d", s->qack); -+ if (s->qack & 1) -+ printf(" bidir"); -+ -+ if (s->mss) -+ printf(" mss:%d", s->mss); -+ if (s->cwnd && s->cwnd != 2) -+ printf(" cwnd:%d", s->cwnd); -+ if (s->ssthresh) -+ printf(" ssthresh:%d", s->ssthresh); -+ -+ if (s->dctcp && s->dctcp->enabled) { -+ struct dctcpstat *dctcp = s->dctcp; -+ -+ printf(" dctcp:(ce_state:%u,alpha:%u,ab_ecn:%u,ab_tot:%u)", -+ dctcp->ce_state, dctcp->alpha, dctcp->ab_ecn, -+ dctcp->ab_tot); -+ } else if (s->dctcp) { -+ printf(" dctcp:fallback_mode"); -+ } -+ -+ if (s->send_bps) -+ printf(" send %sbps", sprint_bw(b1, s->send_bps)); -+ if (s->lastsnd) -+ printf(" lastsnd:%u", s->lastsnd); -+ if (s->lastrcv) -+ printf(" lastrcv:%u", s->lastrcv); -+ if (s->lastack) -+ printf(" lastack:%u", s->lastack); -+ -+ if (s->pacing_rate) { -+ printf(" pacing_rate %sbps", sprint_bw(b1, s->pacing_rate)); -+ if (s->pacing_rate_max) -+ printf("/%sbps", sprint_bw(b1, -+ s->pacing_rate_max)); -+ } -+ -+ if (s->unacked) -+ printf(" unacked:%u", s->unacked); -+ if (s->retrans || s->retrans_total) -+ printf(" retrans:%u/%u", s->retrans, s->retrans_total); -+ if (s->lost) -+ printf(" lost:%u", s->lost); -+ if (s->sacked && s->ss.state != SS_LISTEN) -+ printf(" sacked:%u", s->sacked); -+ if (s->fackets) -+ printf(" fackets:%u", s->fackets); -+ if (s->reordering != 3) -+ printf(" reordering:%d", s->reordering); -+ if (s->rcv_rtt) -+ printf(" rcv_rtt:%g", s->rcv_rtt); -+ if (s->rcv_space) -+ printf(" rcv_space:%d", s->rcv_space); -+} -+ -+static void tcp_timer_print(struct tcpstat *s) -+{ -+ if (s->timer) { -+ if (s->timer > 4) -+ s->timer = 5; -+ printf(" timer:(%s,%s,%d)", -+ tmr_name[s->timer], -+ print_ms_timer(s->timeout), -+ s->retrans); - } -+} - -- if (f->f && run_ssfilter(f->f, &s) == 0) -+static int tcp_show_line(char *line, const struct filter *f, int family) -+{ -+ int rto = 0, ato = 0; -+ struct tcpstat s = {}; -+ char *loc, *rem, *data; -+ char opt[256]; -+ int n; -+ int hz = get_user_hz(); -+ -+ if (proc_inet_split_line(line, &loc, &rem, &data)) -+ return -1; -+ -+ int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0'); -+ if (!(f->states & (1 << state))) -+ return 0; -+ -+ proc_parse_inet_addr(loc, rem, family, &s.ss); -+ -+ if (f->f && run_ssfilter(f->f, &s.ss) == 0) - return 0; - - opt[0] = 0; - n = sscanf(data, "%x %x:%x %x:%x %x %d %d %u %d %llx %d %d %d %d %d %[^\n]\n", -- &s.state, &s.wq, &s.rq, -- &s.timer, &s.timeout, &s.retrs, &s.uid, &s.probes, &s.ino, -- &s.refcnt, &s.sk, &s.rto, &s.ato, &s.qack, -- &s.cwnd, &s.ssthresh, opt); -+ &s.ss.state, &s.ss.wq, &s.ss.rq, -+ &s.timer, &s.timeout, &s.retrans, &s.ss.uid, &s.probes, -+ &s.ss.ino, &s.ss.refcnt, &s.ss.sk, &rto, &ato, &s.qack, &s.cwnd, -+ &s.ssthresh, opt); - - if (n < 17) - opt[0] = 0; - - if (n < 12) { -- s.rto = 0; -+ rto = 0; - s.cwnd = 2; - s.ssthresh = -1; -- s.ato = s.qack = 0; -+ ato = s.qack = 0; - } - -- if (netid_width) -- printf("%-*s ", netid_width, "tcp"); -- if (state_width) -- printf("%-*s ", state_width, sstate_name[s.state]); -+ s.retrans = s.timer != 1 ? s.probes : s.retrans; -+ s.timeout = (s.timeout * 1000 + hz - 1) / hz; -+ s.ato = (double)ato / hz; -+ s.qack /= 2; -+ s.rto = (double)rto; -+ s.ssthresh = s.ssthresh == -1 ? 0 : s.ssthresh; -+ s.rto = s.rto != 3 * hz ? s.rto / hz : 0; - -- printf("%-6d %-6d ", s.rq, s.wq); -+ inet_stats_print(&s.ss, IPPROTO_TCP); - -- formatted_print(&s.local, s.lport); -- formatted_print(&s.remote, s.rport); -+ if (show_options) -+ tcp_timer_print(&s); - -- if (show_options) { -- if (s.timer) { -- if (s.timer > 4) -- s.timer = 5; -- printf(" timer:(%s,%s,%d)", -- tmr_name[s.timer], -- print_hz_timer(s.timeout), -- s.timer != 1 ? s.probes : s.retrs); -- } -- } -- if (show_tcpinfo) { -- int hz = get_user_hz(); -- if (s.rto && s.rto != 3*hz) -- printf(" rto:%g", (double)s.rto/hz); -- if (s.ato) -- printf(" ato:%g", (double)s.ato/hz); -- if (s.cwnd != 2) -- printf(" cwnd:%d", s.cwnd); -- if (s.ssthresh != -1) -- printf(" ssthresh:%d", s.ssthresh); -- if (s.qack/2) -- printf(" qack:%d", s.qack/2); -- if (s.qack&1) -- printf(" bidir"); -- } -- if (show_users) { -- char ubuf[4096]; -- if (find_users(s.ino, ubuf, sizeof(ubuf)) > 0) -- printf(" users:(%s)", ubuf); -- } - if (show_details) { -- if (s.uid) -- printf(" uid:%u", (unsigned)s.uid); -- printf(" ino:%u", s.ino); -- printf(" sk:%llx", s.sk); -+ sock_details_print(&s.ss); - if (opt[0]) - printf(" opt:\"%s\"", opt); - } -- printf("\n"); - -+ if (show_tcpinfo) -+ tcp_stats_print(&s); -+ -+ printf("\n"); - return 0; - } - -@@ -1320,23 +1827,27 @@ outerr: - return ferror(fp) ? -1 : 0; - } - --static char *sprint_bw(char *buf, double bw) --{ -- if (bw > 1000000.) -- sprintf(buf,"%.1fM", bw / 1000000.); -- else if (bw > 1000.) -- sprintf(buf,"%.1fK", bw / 1000.); -- else -- sprintf(buf, "%g", bw); -- -- return buf; --} -- - static void print_skmeminfo(struct rtattr *tb[], int attrtype) - { - const __u32 *skmeminfo; -- if (!tb[attrtype]) -+ -+ if (!tb[attrtype]) { -+ if (attrtype == INET_DIAG_SKMEMINFO) { -+ if (!tb[INET_DIAG_MEMINFO]) -+ return; -+ -+ const struct inet_diag_meminfo *minfo = -+ RTA_DATA(tb[INET_DIAG_MEMINFO]); -+ -+ printf(" mem:(r%u,w%u,f%u,t%u)", -+ minfo->idiag_rmem, -+ minfo->idiag_wmem, -+ minfo->idiag_fmem, -+ minfo->idiag_tmem); -+ } - return; -+ } -+ - skmeminfo = RTA_DATA(tb[attrtype]); - - printf(" skmem:(r%u,rb%u,t%u,tb%u,f%u,w%u,o%u", -@@ -1355,23 +1866,17 @@ static void print_skmeminfo(struct rtattr *tb[], int attrtype) - printf(")"); - } - -+#define TCPI_HAS_OPT(info, opt) !!(info->tcpi_options & (opt)) -+ - static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, - struct rtattr *tb[]) - { -- char b1[64]; - double rtt = 0; -+ struct tcpstat s = {}; - -- if (tb[INET_DIAG_SKMEMINFO]) { -- print_skmeminfo(tb, INET_DIAG_SKMEMINFO); -- } else if (tb[INET_DIAG_MEMINFO]) { -- const struct inet_diag_meminfo *minfo -- = RTA_DATA(tb[INET_DIAG_MEMINFO]); -- printf(" mem:(r%u,w%u,f%u,t%u)", -- minfo->idiag_rmem, -- minfo->idiag_wmem, -- minfo->idiag_fmem, -- minfo->idiag_tmem); -- } -+ s.ss.state = r->idiag_state; -+ -+ print_skmeminfo(tb, INET_DIAG_SKMEMINFO); - - if (tb[INET_DIAG_INFO]) { - struct tcp_info *info; -@@ -1386,37 +1891,48 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, - info = RTA_DATA(tb[INET_DIAG_INFO]); - - if (show_options) { -- if (info->tcpi_options & TCPI_OPT_TIMESTAMPS) -- printf(" ts"); -- if (info->tcpi_options & TCPI_OPT_SACK) -- printf(" sack"); -- if (info->tcpi_options & TCPI_OPT_ECN) -- printf(" ecn"); -- if (info->tcpi_options & TCPI_OPT_ECN_SEEN) -- printf(" ecnseen"); -- if (info->tcpi_options & TCPI_OPT_SYN_DATA) -- printf(" fastopen"); -+ s.has_ts_opt = TCPI_HAS_OPT(info, TCPI_OPT_TIMESTAMPS); -+ s.has_sack_opt = TCPI_HAS_OPT(info, TCPI_OPT_SACK); -+ s.has_ecn_opt = TCPI_HAS_OPT(info, TCPI_OPT_ECN); -+ s.has_ecnseen_opt = TCPI_HAS_OPT(info, TCPI_OPT_ECN_SEEN); -+ s.has_fastopen_opt = TCPI_HAS_OPT(info, TCPI_OPT_SYN_DATA); - } - - if (tb[INET_DIAG_CONG]) -- printf(" %s", rta_getattr_str(tb[INET_DIAG_CONG])); -+ strncpy(s.cong_alg, -+ rta_getattr_str(tb[INET_DIAG_CONG]), -+ sizeof(s.cong_alg) - 1); -+ -+ if (TCPI_HAS_OPT(info, TCPI_OPT_WSCALE)) { -+ s.has_wscale_opt = true; -+ s.snd_wscale = info->tcpi_snd_wscale; -+ s.rcv_wscale = info->tcpi_rcv_wscale; -+ } - -- if (info->tcpi_options & TCPI_OPT_WSCALE) -- printf(" wscale:%d,%d", info->tcpi_snd_wscale, -- info->tcpi_rcv_wscale); - if (info->tcpi_rto && info->tcpi_rto != 3000000) -- printf(" rto:%g", (double)info->tcpi_rto/1000); -- if (info->tcpi_rtt) -- printf(" rtt:%g/%g", (double)info->tcpi_rtt/1000, -- (double)info->tcpi_rttvar/1000); -- if (info->tcpi_ato) -- printf(" ato:%g", (double)info->tcpi_ato/1000); -- if (info->tcpi_snd_mss) -- printf(" mss:%d", info->tcpi_snd_mss); -- if (info->tcpi_snd_cwnd != 2) -- printf(" cwnd:%d", info->tcpi_snd_cwnd); -+ s.rto = (double)info->tcpi_rto / 1000; -+ -+ s.backoff = info->tcpi_backoff; -+ s.rtt = (double)info->tcpi_rtt / 1000; -+ s.rttvar = (double)info->tcpi_rttvar / 1000; -+ s.ato = (double)info->tcpi_ato / 1000; -+ s.mss = info->tcpi_snd_mss; -+ s.rcv_space = info->tcpi_rcv_space; -+ s.rcv_rtt = (double)info->tcpi_rcv_rtt / 1000; -+ s.lastsnd = info->tcpi_last_data_sent; -+ s.lastrcv = info->tcpi_last_data_recv; -+ s.lastack = info->tcpi_last_ack_recv; -+ s.unacked = info->tcpi_unacked; -+ s.retrans = info->tcpi_retrans; -+ s.retrans_total = info->tcpi_total_retrans; -+ s.lost = info->tcpi_lost; -+ s.sacked = info->tcpi_sacked; -+ s.reordering = info->tcpi_reordering; -+ s.rcv_space = info->tcpi_rcv_space; -+ s.cwnd = info->tcpi_snd_cwnd; -+ - if (info->tcpi_snd_ssthresh < 0xFFFF) -- printf(" ssthresh:%d", info->tcpi_snd_ssthresh); -+ s.ssthresh = info->tcpi_snd_ssthresh; - - rtt = (double) info->tcpi_rtt; - if (tb[INET_DIAG_VEGASINFO]) { -@@ -1424,108 +1940,102 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, - = RTA_DATA(tb[INET_DIAG_VEGASINFO]); - - if (vinfo->tcpv_enabled && -- vinfo->tcpv_rtt && vinfo->tcpv_rtt != 0x7fffffff) -+ vinfo->tcpv_rtt && vinfo->tcpv_rtt != 0x7fffffff) - rtt = vinfo->tcpv_rtt; - } - -+ if (tb[INET_DIAG_DCTCPINFO]) { -+ struct dctcpstat *dctcp = malloc(sizeof(struct -+ dctcpstat)); -+ -+ const struct tcp_dctcp_info *dinfo -+ = RTA_DATA(tb[INET_DIAG_DCTCPINFO]); -+ -+ dctcp->enabled = !!dinfo->dctcp_enabled; -+ dctcp->ce_state = dinfo->dctcp_ce_state; -+ dctcp->alpha = dinfo->dctcp_alpha; -+ dctcp->ab_ecn = dinfo->dctcp_ab_ecn; -+ dctcp->ab_tot = dinfo->dctcp_ab_tot; -+ s.dctcp = dctcp; -+ } -+ - if (rtt > 0 && info->tcpi_snd_mss && info->tcpi_snd_cwnd) { -- printf(" send %sbps", -- sprint_bw(b1, (double) info->tcpi_snd_cwnd * -- (double) info->tcpi_snd_mss * 8000000. -- / rtt)); -+ s.send_bps = (double) info->tcpi_snd_cwnd * -+ (double)info->tcpi_snd_mss * 8000000. / rtt; - } - -- if (info->tcpi_unacked) -- printf(" unacked:%u", info->tcpi_unacked); -- if (info->tcpi_retrans || info->tcpi_total_retrans) -- printf(" retrans:%u/%u", info->tcpi_retrans, -- info->tcpi_total_retrans); -- if (info->tcpi_lost) -- printf(" lost:%u", info->tcpi_lost); -- if (info->tcpi_sacked && r->idiag_state != SS_LISTEN) -- printf(" sacked:%u", info->tcpi_sacked); -- if (info->tcpi_fackets) -- printf(" fackets:%u", info->tcpi_fackets); -- if (info->tcpi_reordering != 3) -- printf(" reordering:%d", info->tcpi_reordering); -- if (info->tcpi_rcv_rtt) -- printf(" rcv_rtt:%g", (double) info->tcpi_rcv_rtt/1000); -- if (info->tcpi_rcv_space) -- printf(" rcv_space:%d", info->tcpi_rcv_space); -+ if (info->tcpi_pacing_rate && -+ info->tcpi_pacing_rate != ~0ULL) { -+ s.pacing_rate = info->tcpi_pacing_rate * 8.; - -+ if (info->tcpi_max_pacing_rate && -+ info->tcpi_max_pacing_rate != ~0ULL) -+ s.pacing_rate_max = info->tcpi_max_pacing_rate * 8.; -+ } -+ tcp_stats_print(&s); -+ if (s.dctcp) -+ free(s.dctcp); - } - } - --static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f) -+static int inet_show_sock(struct nlmsghdr *nlh, struct filter *f, int protocol) - { - struct rtattr * tb[INET_DIAG_MAX+1]; - struct inet_diag_msg *r = NLMSG_DATA(nlh); -- struct tcpstat s; -+ struct sockstat s = {}; - - parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr*)(r+1), - nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); - -- s.state = r->idiag_state; -- s.local.family = s.remote.family = r->idiag_family; -- s.lport = ntohs(r->id.idiag_sport); -- s.rport = ntohs(r->id.idiag_dport); -+ s.state = r->idiag_state; -+ s.local.family = s.remote.family = r->idiag_family; -+ s.lport = ntohs(r->id.idiag_sport); -+ s.rport = ntohs(r->id.idiag_dport); -+ s.wq = r->idiag_wqueue; -+ s.rq = r->idiag_rqueue; -+ s.ino = r->idiag_inode; -+ s.uid = r->idiag_uid; -+ s.iface = r->id.idiag_if; -+ s.sk = cookie_sk_get(&r->id.idiag_cookie[0]); -+ - if (s.local.family == AF_INET) { - s.local.bytelen = s.remote.bytelen = 4; - } else { - s.local.bytelen = s.remote.bytelen = 16; - } -+ - memcpy(s.local.data, r->id.idiag_src, s.local.bytelen); - memcpy(s.remote.data, r->id.idiag_dst, s.local.bytelen); - - if (f && f->f && run_ssfilter(f->f, &s) == 0) - return 0; - -- if (netid_width) -- printf("%-*s ", netid_width, "tcp"); -- if (state_width) -- printf("%-*s ", state_width, sstate_name[s.state]); -- -- printf("%-6d %-6d ", r->idiag_rqueue, r->idiag_wqueue); -- -- formatted_print(&s.local, s.lport); -- formatted_print(&s.remote, s.rport); -+ inet_stats_print(&s, protocol); - - if (show_options) { -- if (r->idiag_timer) { -- if (r->idiag_timer > 4) -- r->idiag_timer = 5; -- printf(" timer:(%s,%s,%d)", -- tmr_name[r->idiag_timer], -- print_ms_timer(r->idiag_expires), -- r->idiag_retrans); -- } -- } -- if (show_users) { -- char ubuf[4096]; -- if (find_users(r->idiag_inode, ubuf, sizeof(ubuf)) > 0) -- printf(" users:(%s)", ubuf); -+ struct tcpstat t = {}; -+ -+ t.timer = r->idiag_timer; -+ t.timeout = r->idiag_expires; -+ t.retrans = r->idiag_retrans; -+ tcp_timer_print(&t); - } -+ - if (show_details) { -- if (r->idiag_uid) -- printf(" uid:%u", (unsigned)r->idiag_uid); -- printf(" ino:%u", r->idiag_inode); -- printf(" sk:"); -- if (r->id.idiag_cookie[1] != 0) -- printf("%08x", r->id.idiag_cookie[1]); -- printf("%08x", r->id.idiag_cookie[0]); -+ sock_details_print(&s); - if (tb[INET_DIAG_SHUTDOWN]) { - unsigned char mask; - mask = *(__u8 *)RTA_DATA(tb[INET_DIAG_SHUTDOWN]); - printf(" %c-%c", mask & 1 ? '-' : '<', mask & 2 ? '-' : '>'); - } - } -+ - if (show_mem || show_tcpinfo) { - printf("\n\t"); - tcp_show_info(nlh, r, tb); - } - - printf("\n"); -- - return 0; - } - -@@ -1555,7 +2065,7 @@ static int tcpdiag_send(int fd, int protocol, struct filter *f) - req.nlh.nlmsg_type = DCCPDIAG_GETSOCK; - req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; - req.nlh.nlmsg_pid = 0; -- req.nlh.nlmsg_seq = 123456; -+ req.nlh.nlmsg_seq = MAGIC_SEQ; - memset(&req.r, 0, sizeof(req.r)); - req.r.idiag_family = AF_INET; - req.r.idiag_states = f->states; -@@ -1601,10 +2111,7 @@ static int tcpdiag_send(int fd, int protocol, struct filter *f) - static int sockdiag_send(int family, int fd, int protocol, struct filter *f) - { - struct sockaddr_nl nladdr; -- struct { -- struct nlmsghdr nlh; -- struct inet_diag_req_v2 r; -- } req; -+ DIAG_REQUEST(req, struct inet_diag_req_v2 r); - char *bc = NULL; - int bclen; - struct msghdr msg; -@@ -1617,11 +2124,6 @@ static int sockdiag_send(int family, int fd, int protocol, struct filter *f) - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - -- req.nlh.nlmsg_len = sizeof(req); -- req.nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY; -- req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; -- req.nlh.nlmsg_pid = 0; -- req.nlh.nlmsg_seq = 123456; - memset(&req.r, 0, sizeof(req.r)); - req.r.sdiag_family = family; - req.r.sdiag_protocol = protocol; -@@ -1665,128 +2167,63 @@ static int sockdiag_send(int family, int fd, int protocol, struct filter *f) - return 0; - } - --static int inet_show_netlink(struct filter *f, FILE *dump_fp, int protocol) --{ -- int fd, family; -- struct sockaddr_nl nladdr; -- struct msghdr msg; -- char buf[8192]; -- struct iovec iov[3]; -- -- if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0) -- return -1; -- -- family = PF_INET; --again: -- if (sockdiag_send(family, fd, protocol, f)) -- return -1; -- -- memset(&nladdr, 0, sizeof(nladdr)); -- nladdr.nl_family = AF_NETLINK; -- -- iov[0] = (struct iovec){ -- .iov_base = buf, -- .iov_len = sizeof(buf) -- }; -- -- while (1) { -- int status; -- struct nlmsghdr *h; -- -- msg = (struct msghdr) { -- (void*)&nladdr, sizeof(nladdr), -- iov, 1, -- NULL, 0, -- 0 -- }; -- -- status = recvmsg(fd, &msg, 0); -- -- if (status < 0) { -- if (errno == EINTR) -- continue; -- perror("OVERRUN"); -- continue; -- } -- if (status == 0) { -- fprintf(stderr, "EOF on netlink\n"); -- close(fd); -- return 0; -- } -- -- if (dump_fp) -- fwrite(buf, 1, NLMSG_ALIGN(status), dump_fp); -+struct inet_diag_arg { -+ struct filter *f; -+ int protocol; -+}; - -- h = (struct nlmsghdr*)buf; -- while (NLMSG_OK(h, status)) { -- int err; -- struct inet_diag_msg *r = NLMSG_DATA(h); -+static int show_one_inet_sock(const struct sockaddr_nl *addr, -+ struct nlmsghdr *h, void *arg) -+{ -+ int err; -+ struct inet_diag_arg *diag_arg = arg; -+ struct inet_diag_msg *r = NLMSG_DATA(h); - -- if (/*h->nlmsg_pid != rth->local.nl_pid ||*/ -- h->nlmsg_seq != 123456) -- goto skip_it; -+ if (!(diag_arg->f->families & (1 << r->idiag_family))) -+ return 0; -+ if ((err = inet_show_sock(h, NULL, diag_arg->protocol)) < 0) -+ return err; - -- if (h->nlmsg_type == NLMSG_DONE) -- goto done; -+ return 0; -+} - -- if (h->nlmsg_type == NLMSG_ERROR) { -- struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); -- if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { -- fprintf(stderr, "ERROR truncated\n"); -- } else { -- if (family != PF_UNSPEC) { -- family = PF_UNSPEC; -- goto again; -- } -+static int inet_show_netlink(struct filter *f, FILE *dump_fp, int protocol) -+{ -+ int err = 0; -+ struct rtnl_handle rth; -+ int family = PF_INET; -+ struct inet_diag_arg arg = { .f = f, .protocol = protocol }; - -- errno = -err->error; -- if (errno == EOPNOTSUPP) { -- close(fd); -- return -1; -- } -- perror("TCPDIAG answers"); -- } -+ if (rtnl_open_byproto(&rth, 0, NETLINK_SOCK_DIAG)) -+ return -1; -+ rth.dump = MAGIC_SEQ; -+ rth.dump_fp = dump_fp; - -- goto done; -- } -- if (!dump_fp) { -- if (!(f->families & (1<<r->idiag_family))) { -- h = NLMSG_NEXT(h, status); -- continue; -- } -- err = inet_show_sock(h, NULL); -- if (err < 0) { -- close(fd); -- return err; -- } -- } -+again: -+ if ((err = sockdiag_send(family, rth.fd, protocol, f))) -+ goto Exit; - --skip_it: -- h = NLMSG_NEXT(h, status); -- } -- if (msg.msg_flags & MSG_TRUNC) { -- fprintf(stderr, "Message truncated\n"); -- continue; -- } -- if (status) { -- fprintf(stderr, "!!!Remnant of size %d\n", status); -- exit(1); -+ if ((err = rtnl_dump_filter(&rth, show_one_inet_sock, &arg))) { -+ if (family != PF_UNSPEC) { -+ family = PF_UNSPEC; -+ goto again; - } -+ goto Exit; - } --done: - if (family == PF_INET) { - family = PF_INET6; - goto again; - } - -- close(fd); -- return 0; -+Exit: -+ rtnl_close(&rth); -+ return err; - } - - static int tcp_show_netlink_file(struct filter *f) - { - FILE *fp; -- char buf[8192]; -+ char buf[16384]; - - if ((fp = fopen(getenv("TCPDIAG_FILE"), "r")) == NULL) { - perror("fopen($TCPDIAG_FILE)"); -@@ -1833,7 +2270,7 @@ static int tcp_show_netlink_file(struct filter *f) - return -1; - } - -- err = inet_show_sock(h, f); -+ err = inet_show_sock(h, f, IPPROTO_TCP); - if (err < 0) - return err; - } -@@ -1845,6 +2282,9 @@ static int tcp_show(struct filter *f, int socktype) - char *buf = NULL; - int bufsize = 64*1024; - -+ if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6)) -+ return 0; -+ - dg_proto = TCP_PROTO; - - if (getenv("TCPDIAG_FILE")) -@@ -1864,6 +2304,8 @@ static int tcp_show(struct filter *f, int socktype) - * it is able to give us some memory for snapshot. - */ - if (1) { -+ get_slabstat(&slabstat); -+ - int guess = slabstat.socks+slabstat.tcp_syns; - if (f->states&(1<<SS_TIME_WAIT)) - guess += slabstat.tcp_tws; -@@ -1919,53 +2361,19 @@ outerr: - - static int dgram_show_line(char *line, const struct filter *f, int family) - { -- struct tcpstat s; -+ struct sockstat s = {}; - char *loc, *rem, *data; - char opt[256]; - int n; -- char *p; - -- if ((p = strchr(line, ':')) == NULL) -+ if (proc_inet_split_line(line, &loc, &rem, &data)) - return -1; -- loc = p+2; -- -- if ((p = strchr(loc, ':')) == NULL) -- return -1; -- p[5] = 0; -- rem = p+6; - -- if ((p = strchr(rem, ':')) == NULL) -- return -1; -- p[5] = 0; -- data = p+6; -- -- do { -- int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0'); -- -- if (!(f->states & (1<<state))) -- return 0; -- } while (0); -+ int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0'); -+ if (!(f->states & (1 << state))) -+ return 0; - -- s.local.family = s.remote.family = family; -- if (family == AF_INET) { -- sscanf(loc, "%x:%x", s.local.data, (unsigned*)&s.lport); -- sscanf(rem, "%x:%x", s.remote.data, (unsigned*)&s.rport); -- s.local.bytelen = s.remote.bytelen = 4; -- } else { -- sscanf(loc, "%08x%08x%08x%08x:%x", -- s.local.data, -- s.local.data+1, -- s.local.data+2, -- s.local.data+3, -- &s.lport); -- sscanf(rem, "%08x%08x%08x%08x:%x", -- s.remote.data, -- s.remote.data+1, -- s.remote.data+2, -- s.remote.data+3, -- &s.rport); -- s.local.bytelen = s.remote.bytelen = 16; -- } -+ proc_parse_inet_addr(loc, rem, family, &s); - - if (f->f && run_ssfilter(f->f, &s) == 0) - return 0; -@@ -1979,46 +2387,28 @@ static int dgram_show_line(char *line, const struct filter *f, int family) - if (n < 9) - opt[0] = 0; - -- if (netid_width) -- printf("%-*s ", netid_width, dg_proto); -- if (state_width) -- printf("%-*s ", state_width, sstate_name[s.state]); -+ inet_stats_print(&s, IPPROTO_UDP); - -- printf("%-6d %-6d ", s.rq, s.wq); -+ if (show_details && opt[0]) -+ printf(" opt:\"%s\"", opt); - -- formatted_print(&s.local, s.lport); -- formatted_print(&s.remote, s.rport); -- -- if (show_users) { -- char ubuf[4096]; -- if (find_users(s.ino, ubuf, sizeof(ubuf)) > 0) -- printf(" users:(%s)", ubuf); -- } -- -- if (show_details) { -- if (s.uid) -- printf(" uid=%u", (unsigned)s.uid); -- printf(" ino=%u", s.ino); -- printf(" sk=%llx", s.sk); -- if (opt[0]) -- printf(" opt:\"%s\"", opt); -- } - printf("\n"); -- - return 0; - } - -- - static int udp_show(struct filter *f) - { - FILE *fp = NULL; - -- if (!getenv("PROC_NET_UDP") && !getenv("PROC_ROOT") -- && inet_show_netlink(f, NULL, IPPROTO_UDP) == 0) -+ if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6)) - return 0; - - dg_proto = UDP_PROTO; - -+ if (!getenv("PROC_NET_UDP") && !getenv("PROC_ROOT") -+ && inet_show_netlink(f, NULL, IPPROTO_UDP) == 0) -+ return 0; -+ - if (f->families&(1<<AF_INET)) { - if ((fp = net_udp_open()) == NULL) - goto outerr; -@@ -2049,6 +2439,9 @@ static int raw_show(struct filter *f) - { - FILE *fp = NULL; - -+ if (!filter_af_get(f, AF_INET) && !filter_af_get(f, AF_INET6)) -+ return 0; -+ - dg_proto = RAW_PROTO; - - if (f->families&(1<<AF_INET)) { -@@ -2077,156 +2470,174 @@ outerr: - } while (0); - } - -- --struct unixstat --{ -- struct unixstat *next; -- int ino; -- int peer; -- int rq; -- int wq; -- int state; -- int type; -- char *name; --}; -- -- -- - int unix_state_map[] = { SS_CLOSE, SS_SYN_SENT, - SS_ESTABLISHED, SS_CLOSING }; - -+#define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct sockstat)) - --#define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct unixstat)) -- --static void unix_list_free(struct unixstat *list) -+static void unix_list_free(struct sockstat *list) - { - while (list) { -- struct unixstat *s = list; -+ struct sockstat *s = list; -+ char *name = sock_addr_get_str(&s->local); -+ - list = list->next; -- if (s->name) -- free(s->name); -+ -+ if (name) -+ free(name); - free(s); - } - } - --static void unix_list_print(struct unixstat *list, struct filter *f) -+static const char *unix_netid_name(int type) - { -- struct unixstat *s; -- char *peer; -+ const char *netid; -+ -+ switch (type) { -+ case SOCK_STREAM: -+ netid = "u_str"; -+ break; -+ case SOCK_SEQPACKET: -+ netid = "u_seq"; -+ break; -+ case SOCK_DGRAM: -+ default: -+ netid = "u_dgr"; -+ break; -+ } -+ return netid; -+} -+ -+static bool unix_type_skip(struct sockstat *s, struct filter *f) -+{ -+ if (s->type == SOCK_STREAM && !(f->dbs&(1<<UNIX_ST_DB))) -+ return true; -+ if (s->type == SOCK_DGRAM && !(f->dbs&(1<<UNIX_DG_DB))) -+ return true; -+ if (s->type == SOCK_SEQPACKET && !(f->dbs&(1<<UNIX_SQ_DB))) -+ return true; -+ return false; -+} -+ -+static bool unix_use_proc(void) -+{ -+ return getenv("PROC_NET_UNIX") || getenv("PROC_ROOT"); -+} -+ -+static void unix_stats_print(struct sockstat *list, struct filter *f) -+{ -+ struct sockstat *s; -+ char *local, *peer; -+ char *ctx_buf = NULL; -+ bool use_proc = unix_use_proc(); -+ char port_name[30] = {}; - - for (s = list; s; s = s->next) { -- if (!(f->states & (1<<s->state))) -- continue; -- if (s->type == SOCK_STREAM && !(f->dbs&(1<<UNIX_ST_DB))) -+ if (!(f->states & (1 << s->state))) - continue; -- if (s->type == SOCK_DGRAM && !(f->dbs&(1<<UNIX_DG_DB))) -+ if (unix_type_skip(s, f)) - continue; - -- peer = "*"; -- if (s->peer) { -- struct unixstat *p; -+ local = sock_addr_get_str(&s->local); -+ peer = "*"; -+ -+ if (s->rport && use_proc) { -+ struct sockstat *p; -+ - for (p = list; p; p = p->next) { -- if (s->peer == p->ino) -+ if (s->rport == p->lport) - break; - } -+ - if (!p) { - peer = "?"; - } else { -- peer = p->name ? : "*"; -+ peer = sock_addr_get_str(&p->local); -+ peer = peer ? : "*"; - } - } - -- if (f->f) { -- struct tcpstat tst; -- tst.local.family = AF_UNIX; -- tst.remote.family = AF_UNIX; -- memcpy(tst.local.data, &s->name, sizeof(s->name)); -+ if (use_proc && f->f) { - if (strcmp(peer, "*") == 0) -- memset(tst.remote.data, 0, sizeof(peer)); -+ memset(s->remote.data, 0, sizeof(char *)); - else -- memcpy(tst.remote.data, &peer, sizeof(peer)); -- if (run_ssfilter(f->f, &tst) == 0) -+ sock_addr_set_str(&s->remote, &peer); -+ -+ if (run_ssfilter(f->f, s) == 0) - continue; - } - -- if (netid_width) -- printf("%-*s ", netid_width, -- s->type == SOCK_STREAM ? "u_str" : "u_dgr"); -- if (state_width) -- printf("%-*s ", state_width, sstate_name[s->state]); -- printf("%-6d %-6d ", s->rq, s->wq); -- printf("%*s %-*d %*s %-*d", -- addr_width, s->name ? : "*", serv_width, s->ino, -- addr_width, peer, serv_width, s->peer); -- if (show_users) { -- char ubuf[4096]; -- if (find_users(s->ino, ubuf, sizeof(ubuf)) > 0) -- printf(" users:(%s)", ubuf); -+ sock_state_print(s, unix_netid_name(s->type)); -+ -+ sock_addr_print(local ?: "*", " ", -+ int_to_str(s->lport, port_name), NULL); -+ sock_addr_print(peer, " ", int_to_str(s->rport, port_name), -+ NULL); -+ -+ if (show_proc_ctx || show_sock_ctx) { -+ if (find_entry(s->ino, &ctx_buf, -+ (show_proc_ctx & show_sock_ctx) ? -+ PROC_SOCK_CTX : PROC_CTX) > 0) { -+ printf(" users:(%s)", ctx_buf); -+ free(ctx_buf); -+ } -+ } else if (show_users) { -+ if (find_entry(s->ino, &ctx_buf, USERS) > 0) { -+ printf(" users:(%s)", ctx_buf); -+ free(ctx_buf); -+ } - } - printf("\n"); - } - } - --static int unix_show_sock(struct nlmsghdr *nlh, struct filter *f) -+static int unix_show_sock(const struct sockaddr_nl *addr, struct nlmsghdr *nlh, -+ void *arg) - { -+ struct filter *f = (struct filter *)arg; - struct unix_diag_msg *r = NLMSG_DATA(nlh); - struct rtattr *tb[UNIX_DIAG_MAX+1]; -- char name[128]; -- int peer_ino; -- __u32 rqlen, wqlen; -+ char *name = NULL; -+ struct sockstat stat = {}; - - parse_rtattr(tb, UNIX_DIAG_MAX, (struct rtattr*)(r+1), - nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); - -- if (netid_width) -- printf("%-*s ", netid_width, -- r->udiag_type == SOCK_STREAM ? "u_str" : "u_dgr"); -- if (state_width) -- printf("%-*s ", state_width, sstate_name[r->udiag_state]); -+ stat.type = r->udiag_type; -+ stat.state = r->udiag_state; -+ stat.ino = stat.lport = r->udiag_ino; -+ stat.local.family = stat.remote.family = AF_UNIX; -+ -+ if (unix_type_skip(&stat, f)) -+ return 0; - - if (tb[UNIX_DIAG_RQLEN]) { - struct unix_diag_rqlen *rql = RTA_DATA(tb[UNIX_DIAG_RQLEN]); -- rqlen = rql->udiag_rqueue; -- wqlen = rql->udiag_wqueue; -- } else { -- rqlen = 0; -- wqlen = 0; -+ stat.rq = rql->udiag_rqueue; -+ stat.wq = rql->udiag_wqueue; - } -- -- printf("%-6u %-6u ", rqlen, wqlen); -- - if (tb[UNIX_DIAG_NAME]) { - int len = RTA_PAYLOAD(tb[UNIX_DIAG_NAME]); - -+ name = malloc(len + 1); - memcpy(name, RTA_DATA(tb[UNIX_DIAG_NAME]), len); - name[len] = '\0'; - if (name[0] == '\0') - name[0] = '@'; -- } else -- sprintf(name, "*"); -- -+ sock_addr_set_str(&stat.local, &name); -+ } - if (tb[UNIX_DIAG_PEER]) -- peer_ino = rta_getattr_u32(tb[UNIX_DIAG_PEER]); -- else -- peer_ino = 0; -+ stat.rport = rta_getattr_u32(tb[UNIX_DIAG_PEER]); - -- printf("%*s %-*d %*s %-*d", -- addr_width, name, -- serv_width, r->udiag_ino, -- addr_width, "*", /* FIXME */ -- serv_width, peer_ino); -+ if (f->f && run_ssfilter(f->f, &stat) == 0) -+ return 0; - -- if (show_users) { -- char ubuf[4096]; -- if (find_users(r->udiag_ino, ubuf, sizeof(ubuf)) > 0) -- printf(" users:(%s)", ubuf); -- } -+ unix_stats_print(&stat, f); - - if (show_mem) { -- printf("\n\t"); -+ printf("\t"); - print_skmeminfo(tb, UNIX_DIAG_MEMINFO); - } -- - if (show_details) { - if (tb[UNIX_DIAG_SHUTDOWN]) { - unsigned char mask; -@@ -2234,107 +2645,40 @@ static int unix_show_sock(struct nlmsghdr *nlh, struct filter *f) - printf(" %c-%c", mask & 1 ? '-' : '<', mask & 2 ? '-' : '>'); - } - } -+ if (show_mem || show_details) -+ printf("\n"); - -- printf("\n"); -- -+ if (name) -+ free(name); - return 0; - } - --static int handle_netlink_request(struct filter *f, FILE *dump_fp, -- struct nlmsghdr *req, size_t size, -- int (* show_one_sock)(struct nlmsghdr *nlh, struct filter *f)) -+static int handle_netlink_request(struct filter *f, struct nlmsghdr *req, -+ size_t size, rtnl_filter_t show_one_sock) - { -- int fd; -- char buf[8192]; -+ int ret = -1; -+ struct rtnl_handle rth; - -- if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0) -+ if (rtnl_open_byproto(&rth, 0, NETLINK_SOCK_DIAG)) - return -1; - -- if (send(fd, req, size, 0) < 0) { -- close(fd); -- return -1; -- } -- -- while (1) { -- ssize_t status; -- struct nlmsghdr *h; -- struct sockaddr_nl nladdr; -- socklen_t slen = sizeof(nladdr); -- -- status = recvfrom(fd, buf, sizeof(buf), 0, -- (struct sockaddr *) &nladdr, &slen); -- if (status < 0) { -- if (errno == EINTR) -- continue; -- perror("OVERRUN"); -- continue; -- } -- if (status == 0) { -- fprintf(stderr, "EOF on netlink\n"); -- goto close_it; -- } -- -- if (dump_fp) -- fwrite(buf, 1, NLMSG_ALIGN(status), dump_fp); -- -- h = (struct nlmsghdr*)buf; -- while (NLMSG_OK(h, status)) { -- int err; -- -- if (/*h->nlmsg_pid != rth->local.nl_pid ||*/ -- h->nlmsg_seq != 123456) -- goto skip_it; -- -- if (h->nlmsg_type == NLMSG_DONE) -- goto close_it; -+ rth.dump = MAGIC_SEQ; - -- if (h->nlmsg_type == NLMSG_ERROR) { -- struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); -- if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { -- fprintf(stderr, "ERROR truncated\n"); -- } else { -- errno = -err->error; -- if (errno != ENOENT) -- fprintf(stderr, "DIAG answers %d\n", errno); -- } -- close(fd); -- return -1; -- } -- if (!dump_fp) { -- err = show_one_sock(h, f); -- if (err < 0) { -- close(fd); -- return err; -- } -- } -+ if (rtnl_send(&rth, req, size) < 0) -+ goto Exit; - --skip_it: -- h = NLMSG_NEXT(h, status); -- } -+ if (rtnl_dump_filter(&rth, show_one_sock, f)) -+ goto Exit; - -- if (status) { -- fprintf(stderr, "!!!Remnant of size %zd\n", status); -- exit(1); -- } -- } -- --close_it: -- close(fd); -- return 0; -+ ret = 0; -+Exit: -+ rtnl_close(&rth); -+ return ret; - } - --static int unix_show_netlink(struct filter *f, FILE *dump_fp) -+static int unix_show_netlink(struct filter *f) - { -- struct { -- struct nlmsghdr nlh; -- struct unix_diag_req r; -- } req; -- -- memset(&req, 0, sizeof(req)); -- req.nlh.nlmsg_len = sizeof(req); -- req.nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY; -- req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; -- req.nlh.nlmsg_seq = 123456; -+ DIAG_REQUEST(req, struct unix_diag_req r); - - req.r.sdiag_family = AF_UNIX; - req.r.udiag_states = f->states; -@@ -2342,8 +2686,7 @@ static int unix_show_netlink(struct filter *f, FILE *dump_fp) - if (show_mem) - req.r.udiag_show |= UDIAG_SHOW_MEMINFO; - -- return handle_netlink_request(f, dump_fp, &req.nlh, -- sizeof(req), unix_show_sock); -+ return handle_netlink_request(f, &req.nlh, sizeof(req), unix_show_sock); - } - - static int unix_show(struct filter *f) -@@ -2353,10 +2696,12 @@ static int unix_show(struct filter *f) - char name[128]; - int newformat = 0; - int cnt; -- struct unixstat *list = NULL; -+ struct sockstat *list = NULL; - -- if (!getenv("PROC_NET_UNIX") && !getenv("PROC_ROOT") -- && unix_show_netlink(f, NULL) == 0) -+ if (!filter_af_get(f, AF_UNIX)) -+ return 0; -+ -+ if (!unix_use_proc() && unix_show_netlink(f) == 0) - return 0; - - if ((fp = net_unix_open()) == NULL) -@@ -2368,30 +2713,30 @@ static int unix_show(struct filter *f) - cnt = 0; - - while (fgets(buf, sizeof(buf)-1, fp)) { -- struct unixstat *u, **insp; -+ struct sockstat *u, **insp; - int flags; - - if (!(u = malloc(sizeof(*u)))) - break; -- u->name = NULL; - - if (sscanf(buf, "%x: %x %x %x %x %x %d %s", -- &u->peer, &u->rq, &u->wq, &flags, &u->type, -+ &u->rport, &u->rq, &u->wq, &flags, &u->type, - &u->state, &u->ino, name) < 8) - name[0] = 0; - -- if (flags&(1<<16)) { -+ u->lport = u->ino; -+ u->local.family = u->remote.family = AF_UNIX; -+ -+ if (flags & (1 << 16)) { - u->state = SS_LISTEN; - } else { - u->state = unix_state_map[u->state-1]; -- if (u->type == SOCK_DGRAM && -- u->state == SS_CLOSE && -- u->peer) -+ if (u->type == SOCK_DGRAM && u->state == SS_CLOSE && u->rport) - u->state = SS_ESTABLISHED; - } - - if (!newformat) { -- u->peer = 0; -+ u->rport = 0; - u->rq = 0; - u->wq = 0; - } -@@ -2408,12 +2753,11 @@ static int unix_show(struct filter *f) - *insp = u; - - if (name[0]) { -- if ((u->name = malloc(strlen(name)+1)) == NULL) -- break; -- strcpy(u->name, name); -+ char *tmp = strdup(name); -+ sock_addr_set_str(&u->local, &tmp); - } - if (++cnt > MAX_UNIX_REMEMBER) { -- unix_list_print(list, f); -+ unix_stats_print(list, f); - unix_list_free(list); - list = NULL; - cnt = 0; -@@ -2421,7 +2765,7 @@ static int unix_show(struct filter *f) - } - fclose(fp); - if (list) { -- unix_list_print(list, f); -+ unix_stats_print(list, f); - unix_list_free(list); - list = NULL; - cnt = 0; -@@ -2430,11 +2774,62 @@ static int unix_show(struct filter *f) - return 0; - } - --static int packet_show_sock(struct nlmsghdr *nlh, struct filter *f) -+static int packet_stats_print(struct sockstat *s, const struct filter *f) - { -+ char *buf = NULL; -+ const char *addr, *port; -+ char ll_name[16]; -+ -+ if (f->f) { -+ s->local.family = AF_PACKET; -+ s->remote.family = AF_PACKET; -+ s->local.data[0] = s->prot; -+ if (run_ssfilter(f->f, s) == 0) -+ return 1; -+ } -+ -+ sock_state_print(s, s->type == SOCK_RAW ? "p_raw" : "p_dgr"); -+ -+ if (s->prot == 3) -+ addr = "*"; -+ else -+ addr = ll_proto_n2a(htons(s->prot), ll_name, sizeof(ll_name)); -+ -+ if (s->iface == 0) -+ port = "*"; -+ else -+ port = xll_index_to_name(s->iface); -+ -+ sock_addr_print(addr, ":", port, NULL); -+ sock_addr_print("", "*", "", NULL); -+ -+ if (show_proc_ctx || show_sock_ctx) { -+ if (find_entry(s->ino, &buf, -+ (show_proc_ctx & show_sock_ctx) ? -+ PROC_SOCK_CTX : PROC_CTX) > 0) { -+ printf(" users:(%s)", buf); -+ free(buf); -+ } -+ } else if (show_users) { -+ if (find_entry(s->ino, &buf, USERS) > 0) { -+ printf(" users:(%s)", buf); -+ free(buf); -+ } -+ } -+ -+ if (show_details) -+ sock_details_print(s); -+ -+ return 0; -+} -+ -+static int packet_show_sock(const struct sockaddr_nl *addr, -+ struct nlmsghdr *nlh, void *arg) -+{ -+ const struct filter *f = arg; - struct packet_diag_msg *r = NLMSG_DATA(nlh); - struct rtattr *tb[PACKET_DIAG_MAX+1]; -- __u32 rq; -+ struct sockstat stat = {}; - - parse_rtattr(tb, PACKET_DIAG_MAX, (struct rtattr*)(r+1), - nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); -@@ -2443,56 +2838,27 @@ static int packet_show_sock(struct nlmsghdr *nlh, struct filter *f) - if (!tb[PACKET_DIAG_MEMINFO]) - return -1; - -- if (netid_width) -- printf("%-*s ", netid_width, -- r->pdiag_type == SOCK_RAW ? "p_raw" : "p_dgr"); -- if (state_width) -- printf("%-*s ", state_width, "UNCONN"); -+ stat.type = r->pdiag_type; -+ stat.prot = r->pdiag_num; -+ stat.ino = r->pdiag_ino; -+ stat.state = SS_CLOSE; -+ stat.sk = cookie_sk_get(&r->pdiag_cookie[0]); - - if (tb[PACKET_DIAG_MEMINFO]) { - __u32 *skmeminfo = RTA_DATA(tb[PACKET_DIAG_MEMINFO]); -- -- rq = skmeminfo[SK_MEMINFO_RMEM_ALLOC]; -- } else -- rq = 0; -- printf("%-6d %-6d ", rq, 0); -- -- if (r->pdiag_num == 3) { -- printf("%*s:", addr_width, "*"); -- } else { -- char tb2[16]; -- printf("%*s:", addr_width, -- ll_proto_n2a(htons(r->pdiag_num), tb2, sizeof(tb2))); -+ stat.rq = skmeminfo[SK_MEMINFO_RMEM_ALLOC]; - } -+ - if (tb[PACKET_DIAG_INFO]) { - struct packet_diag_info *pinfo = RTA_DATA(tb[PACKET_DIAG_INFO]); -- -- if (pinfo->pdi_index == 0) -- printf("%-*s ", serv_width, "*"); -- else -- printf("%-*s ", serv_width, xll_index_to_name(pinfo->pdi_index)); -- } else -- printf("%-*s ", serv_width, "*"); -- -- printf("%*s*%-*s", -- addr_width, "", serv_width, ""); -- -- if (show_users) { -- char ubuf[4096]; -- if (find_users(r->pdiag_ino, ubuf, sizeof(ubuf)) > 0) -- printf(" users:(%s)", ubuf); -+ stat.lport = stat.iface = pinfo->pdi_index; - } -- if (show_details) { -- __u32 uid = 0; - -- if (tb[PACKET_DIAG_UID]) -- uid = *(__u32 *)RTA_DATA(tb[PACKET_DIAG_UID]); -+ if (tb[PACKET_DIAG_UID]) -+ stat.uid = *(__u32 *)RTA_DATA(tb[PACKET_DIAG_UID]); - -- printf(" ino=%u uid=%u sk=", r->pdiag_ino, uid); -- if (r->pdiag_cookie[1] != 0) -- printf("%08x", r->pdiag_cookie[1]); -- printf("%08x", r->pdiag_cookie[0]); -- } -+ if (packet_stats_print(&stat, f)) -+ return 0; - - if (show_bpf && tb[PACKET_DIAG_FILTER]) { - struct sock_filter *fil = -@@ -2512,244 +2878,154 @@ static int packet_show_sock(struct nlmsghdr *nlh, struct filter *f) - return 0; - } - --static int packet_show_netlink(struct filter *f, FILE *dump_fp) -+static int packet_show_netlink(struct filter *f) - { -- int fd; -- struct { -- struct nlmsghdr nlh; -- struct packet_diag_req r; -- } req; -- char buf[8192]; -- -- if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0) -- return -1; -- -- memset(&req, 0, sizeof(req)); -- req.nlh.nlmsg_len = sizeof(req); -- req.nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY; -- req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; -- req.nlh.nlmsg_seq = 123456; -+ DIAG_REQUEST(req, struct packet_diag_req r); - - req.r.sdiag_family = AF_PACKET; - req.r.pdiag_show = PACKET_SHOW_INFO | PACKET_SHOW_MEMINFO | PACKET_SHOW_FILTER; - -- if (send(fd, &req, sizeof(req), 0) < 0) { -- close(fd); -- return -1; -- } -- -- while (1) { -- ssize_t status; -- struct nlmsghdr *h; -- struct sockaddr_nl nladdr; -- socklen_t slen = sizeof(nladdr); -- -- status = recvfrom(fd, buf, sizeof(buf), 0, -- (struct sockaddr *) &nladdr, &slen); -- if (status < 0) { -- if (errno == EINTR) -- continue; -- perror("OVERRUN"); -- continue; -- } -- if (status == 0) { -- fprintf(stderr, "EOF on netlink\n"); -- goto close_it; -- } -- -- if (dump_fp) -- fwrite(buf, 1, NLMSG_ALIGN(status), dump_fp); -- -- h = (struct nlmsghdr*)buf; -- while (NLMSG_OK(h, status)) { -- int err; -+ return handle_netlink_request(f, &req.nlh, sizeof(req), packet_show_sock); -+} - -- if (h->nlmsg_seq != 123456) -- goto skip_it; -+static int packet_show_line(char *buf, const struct filter *f, int fam) -+{ -+ unsigned long long sk; -+ struct sockstat stat = {}; -+ int type, prot, iface, state, rq, uid, ino; - -- if (h->nlmsg_type == NLMSG_DONE) -- goto close_it; -+ sscanf(buf, "%llx %*d %d %x %d %d %u %u %u", -+ &sk, -+ &type, &prot, &iface, &state, -+ &rq, &uid, &ino); - -- if (h->nlmsg_type == NLMSG_ERROR) { -- struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); -- if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { -- fprintf(stderr, "ERROR truncated\n"); -- } else { -- errno = -err->error; -- if (errno != ENOENT) -- fprintf(stderr, "UDIAG answers %d\n", errno); -- } -- close(fd); -- return -1; -- } -- if (!dump_fp) { -- err = packet_show_sock(h, f); -- if (err < 0) { -- close(fd); -- return err; -- } -- } -+ if (stat.type == SOCK_RAW && !(f->dbs&(1<<PACKET_R_DB))) -+ return 0; -+ if (stat.type == SOCK_DGRAM && !(f->dbs&(1<<PACKET_DG_DB))) -+ return 0; - --skip_it: -- h = NLMSG_NEXT(h, status); -- } -+ stat.type = type; -+ stat.prot = prot; -+ stat.lport = stat.iface = iface; -+ stat.state = state; -+ stat.rq = rq; -+ stat.uid = uid; -+ stat.ino = ino; -+ stat.state = SS_CLOSE; - -- if (status) { -- fprintf(stderr, "!!!Remnant of size %zd\n", status); -- exit(1); -- } -- } -+ if (packet_stats_print(&stat, f)) -+ return 0; - --close_it: -- close(fd); -+ printf("\n"); - return 0; - } - -- - static int packet_show(struct filter *f) - { - FILE *fp; -- char buf[256]; -- int type; -- int prot; -- int iface; -- int state; -- int rq; -- int uid; -- int ino; -- unsigned long long sk; - -- if (!(f->states & (1<<SS_CLOSE))) -+ if (!filter_af_get(f, AF_PACKET) || !(f->states & (1 << SS_CLOSE))) - return 0; - -- if (packet_show_netlink(f, NULL) == 0) -+ if (!getenv("PROC_NET_PACKET") && !getenv("PROC_ROOT") && -+ packet_show_netlink(f) == 0) - return 0; - - if ((fp = net_packet_open()) == NULL) - return -1; -- fgets(buf, sizeof(buf)-1, fp); -- -- while (fgets(buf, sizeof(buf)-1, fp)) { -- sscanf(buf, "%llx %*d %d %x %d %d %u %u %u", -- &sk, -- &type, &prot, &iface, &state, -- &rq, &uid, &ino); -- -- if (type == SOCK_RAW && !(f->dbs&(1<<PACKET_R_DB))) -- continue; -- if (type == SOCK_DGRAM && !(f->dbs&(1<<PACKET_DG_DB))) -- continue; -- if (f->f) { -- struct tcpstat tst; -- tst.local.family = AF_PACKET; -- tst.remote.family = AF_PACKET; -- tst.rport = 0; -- tst.lport = iface; -- tst.local.data[0] = prot; -- tst.remote.data[0] = 0; -- if (run_ssfilter(f->f, &tst) == 0) -- continue; -- } -- -- if (netid_width) -- printf("%-*s ", netid_width, -- type == SOCK_RAW ? "p_raw" : "p_dgr"); -- if (state_width) -- printf("%-*s ", state_width, "UNCONN"); -- printf("%-6d %-6d ", rq, 0); -- if (prot == 3) { -- printf("%*s:", addr_width, "*"); -- } else { -- char tb[16]; -- printf("%*s:", addr_width, -- ll_proto_n2a(htons(prot), tb, sizeof(tb))); -- } -- if (iface == 0) { -- printf("%-*s ", serv_width, "*"); -- } else { -- printf("%-*s ", serv_width, xll_index_to_name(iface)); -- } -- printf("%*s*%-*s", -- addr_width, "", serv_width, ""); -- -- if (show_users) { -- char ubuf[4096]; -- if (find_users(ino, ubuf, sizeof(ubuf)) > 0) -- printf(" users:(%s)", ubuf); -- } -- if (show_details) { -- printf(" ino=%u uid=%u sk=%llx", ino, uid, sk); -- } -- printf("\n"); -- } -+ if (generic_record_read(fp, packet_show_line, f, AF_PACKET)) -+ return -1; - - return 0; - } - --static void netlink_show_one(struct filter *f, -+static int netlink_show_one(struct filter *f, - int prot, int pid, unsigned groups, - int state, int dst_pid, unsigned dst_group, - int rq, int wq, - unsigned long long sk, unsigned long long cb) - { -+ struct sockstat st; -+ SPRINT_BUF(prot_buf) = {}; -+ const char *prot_name; -+ char procname[64] = {}; -+ -+ st.state = SS_CLOSE; -+ st.rq = rq; -+ st.wq = wq; -+ - if (f->f) { -- struct tcpstat tst; -- tst.local.family = AF_NETLINK; -- tst.remote.family = AF_NETLINK; -- tst.rport = -1; -- tst.lport = pid; -- tst.local.data[0] = prot; -- tst.remote.data[0] = 0; -- if (run_ssfilter(f->f, &tst) == 0) -- return; -+ st.local.family = AF_NETLINK; -+ st.remote.family = AF_NETLINK; -+ st.rport = -1; -+ st.lport = pid; -+ st.local.data[0] = prot; -+ if (run_ssfilter(f->f, &st) == 0) -+ return 1; - } - -- if (netid_width) -- printf("%-*s ", netid_width, "nl"); -- if (state_width) -- printf("%-*s ", state_width, "UNCONN"); -- printf("%-6d %-6d ", rq, wq); -- if (resolve_services && prot == 0) -- printf("%*s:", addr_width, "rtnl"); -- else if (resolve_services && prot == 3) -- printf("%*s:", addr_width, "fw"); -- else if (resolve_services && prot == 4) -- printf("%*s:", addr_width, "tcpdiag"); -+ sock_state_print(&st, "nl"); -+ -+ if (resolve_services) -+ prot_name = nl_proto_n2a(prot, prot_buf, sizeof(prot_buf)); - else -- printf("%*d:", addr_width, prot); -+ prot_name = int_to_str(prot, prot_buf); -+ - if (pid == -1) { -- printf("%-*s ", serv_width, "*"); -+ procname[0] = '*'; - } else if (resolve_services) { - int done = 0; - if (!pid) { - done = 1; -- printf("%-*s ", serv_width, "kernel"); -+ strncpy(procname, "kernel", 6); - } else if (pid > 0) { -- char procname[64]; - FILE *fp; - sprintf(procname, "%s/%d/stat", - getenv("PROC_ROOT") ? : "/proc", pid); - if ((fp = fopen(procname, "r")) != NULL) { - if (fscanf(fp, "%*d (%[^)])", procname) == 1) { - sprintf(procname+strlen(procname), "/%d", pid); -- printf("%-*s ", serv_width, procname); - done = 1; - } - fclose(fp); - } - } - if (!done) -- printf("%-*d ", serv_width, pid); -+ int_to_str(pid, procname); - } else { -- printf("%-*d ", serv_width, pid); -+ int_to_str(pid, procname); - } - -+ sock_addr_print(prot_name, ":", procname, NULL); -+ - if (state == NETLINK_CONNECTED) { -- printf("%*d:%-*d", -- addr_width, dst_group, serv_width, dst_pid); -+ char dst_group_buf[30]; -+ char dst_pid_buf[30]; -+ sock_addr_print(int_to_str(dst_group, dst_group_buf), ":", -+ int_to_str(dst_pid, dst_pid_buf), NULL); - } else { -- printf("%*s*%-*s", -- addr_width, "", serv_width, ""); -+ sock_addr_print("", "*", "", NULL); -+ } -+ -+ char *pid_context = NULL; -+ if (show_proc_ctx) { -+ /* The pid value will either be: -+ * 0 if destination kernel - show kernel initial context. -+ * A valid process pid - use getpidcon. -+ * A unique value allocated by the kernel or netlink user -+ * to the process - show context as "not available". -+ */ -+ if (!pid) -+ security_get_initial_context("kernel", &pid_context); -+ else if (pid > 0) -+ getpidcon(pid, &pid_context); -+ -+ if (pid_context != NULL) { -+ printf("proc_ctx=%-*s ", serv_width, pid_context); -+ free(pid_context); -+ } else { -+ printf("proc_ctx=%-*s ", serv_width, "unavailable"); -+ } - } - - if (show_details) { -@@ -2757,11 +3033,13 @@ static void netlink_show_one(struct filter *f, - } - printf("\n"); - -- return; -+ return 0; - } - --static int netlink_show_sock(struct nlmsghdr *nlh, struct filter *f) -+static int netlink_show_sock(const struct sockaddr_nl *addr, -+ struct nlmsghdr *nlh, void *arg) - { -+ struct filter *f = (struct filter *)arg; - struct netlink_diag_msg *r = NLMSG_DATA(nlh); - struct rtattr *tb[NETLINK_DIAG_MAX+1]; - int rq = 0, wq = 0; -@@ -2781,9 +3059,11 @@ static int netlink_show_sock(struct nlmsghdr *nlh, struct filter *f) - wq = skmeminfo[SK_MEMINFO_WMEM_ALLOC]; - } - -- netlink_show_one(f, r->ndiag_protocol, r->ndiag_portid, groups, -+ if (netlink_show_one(f, r->ndiag_protocol, r->ndiag_portid, groups, - r->ndiag_state, r->ndiag_dst_portid, r->ndiag_dst_group, -- rq, wq, 0, 0); -+ rq, wq, 0, 0)) { -+ return 0; -+ } - - if (show_mem) { - printf("\t"); -@@ -2794,25 +3074,15 @@ static int netlink_show_sock(struct nlmsghdr *nlh, struct filter *f) - return 0; - } - --static int netlink_show_netlink(struct filter *f, FILE *dump_fp) -+static int netlink_show_netlink(struct filter *f) - { -- struct { -- struct nlmsghdr nlh; -- struct netlink_diag_req r; -- } req; -- -- memset(&req, 0, sizeof(req)); -- req.nlh.nlmsg_len = sizeof(req); -- req.nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY; -- req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; -- req.nlh.nlmsg_seq = 123456; -+ DIAG_REQUEST(req, struct netlink_diag_req r); - - req.r.sdiag_family = AF_NETLINK; - req.r.sdiag_protocol = NDIAG_PROTO_ALL; - req.r.ndiag_show = NDIAG_SHOW_GROUPS | NDIAG_SHOW_MEMINFO; - -- return handle_netlink_request(f, dump_fp, &req.nlh, -- sizeof(req), netlink_show_sock); -+ return handle_netlink_request(f, &req.nlh, sizeof(req), netlink_show_sock); - } - - static int netlink_show(struct filter *f) -@@ -2824,11 +3094,11 @@ static int netlink_show(struct filter *f) - int rq, wq, rc; - unsigned long long sk, cb; - -- if (!(f->states & (1<<SS_CLOSE))) -+ if (!filter_af_get(f, AF_NETLINK) || !(f->states & (1 << SS_CLOSE))) - return 0; - - if (!getenv("PROC_NET_NETLINK") && !getenv("PROC_ROOT") && -- netlink_show_netlink(f, NULL) == 0) -+ netlink_show_netlink(f) == 0) - return 0; - - if ((fp = net_netlink_open()) == NULL) -@@ -2898,7 +3168,7 @@ static int get_snmp_int(char *proto, char *key, int *result) - - /* Get stats from sockstat */ - --struct sockstat -+struct ssummary - { - int socks; - int tcp_mem; -@@ -2917,7 +3187,7 @@ struct sockstat - int frag6_mem; - }; - --static void get_sockstat_line(char *line, struct sockstat *s) -+static void get_sockstat_line(char *line, struct ssummary *s) - { - char id[256], rem[256]; - -@@ -2946,7 +3216,7 @@ static void get_sockstat_line(char *line, struct sockstat *s) - &s->tcp_orphans, &s->tcp_tws, &s->tcp_total, &s->tcp_mem); - } - --static int get_sockstat(struct sockstat *s) -+static int get_sockstat(struct ssummary *s) - { - char buf[256]; - FILE *fp; -@@ -2970,7 +3240,7 @@ static int get_sockstat(struct sockstat *s) - - static int print_summary(void) - { -- struct sockstat s; -+ struct ssummary s; - struct snmpstat sn; - - if (get_sockstat(&s) < 0) -@@ -2978,6 +3248,8 @@ static int print_summary(void) - if (get_snmp_int("Tcp:", "CurrEstab", &sn.tcp_estab) < 0) - perror("ss: get_snmpstat"); - -+ get_slabstat(&slabstat); -+ - printf("Total: %d (kernel %d)\n", s.socks, slabstat.socks); - - printf("TCP: %d (estab %d, closed %d, orphaned %d, synrecv %d, timewait %d/%d), ports %d\n", -@@ -3013,36 +3285,45 @@ static void _usage(FILE *dest) - fprintf(dest, - "Usage: ss [ OPTIONS ]\n" - " ss [ OPTIONS ] [ FILTER ]\n" --" -h, --help this message\n" --" -V, --version output version information\n" --" -n, --numeric don't resolve service names\n" -+" -h, --help this message\n" -+" -V, --version output version information\n" -+" -n, --numeric don't resolve service names\n" - " -r, --resolve resolve host names\n" --" -a, --all display all sockets\n" --" -l, --listening display listening sockets\n" -+" -a, --all display all sockets\n" -+" -l, --listening display listening sockets\n" - " -o, --options show timer information\n" - " -e, --extended show detailed socket information\n" - " -m, --memory show socket memory usage\n" --" -p, --processes show process using socket\n" --" -i, --info show internal TCP information\n" --" -s, --summary show socket usage summary\n" -+" -p, --processes show process using socket\n" -+" -i, --info show internal TCP information\n" -+" -s, --summary show socket usage summary\n" - " -b, --bpf show bpf filter socket information\n" -+" -Z, --context display process SELinux security contexts\n" -+" -z, --contexts display process and socket SELinux security contexts\n" -+" -N, --net switch to the specified network namespace name\n" - "\n" - " -4, --ipv4 display only IP version 4 sockets\n" - " -6, --ipv6 display only IP version 6 sockets\n" --" -0, --packet display PACKET sockets\n" --" -t, --tcp display only TCP sockets\n" --" -u, --udp display only UDP sockets\n" --" -d, --dccp display only DCCP sockets\n" --" -w, --raw display only RAW sockets\n" --" -x, --unix display only Unix domain sockets\n" -+" -0, --packet display PACKET sockets\n" -+" -t, --tcp display only TCP sockets\n" -+" -u, --udp display only UDP sockets\n" -+" -d, --dccp display only DCCP sockets\n" -+" -w, --raw display only RAW sockets\n" -+" -x, --unix display only Unix domain sockets\n" - " -f, --family=FAMILY display sockets of type FAMILY\n" - "\n" - " -A, --query=QUERY, --socket=QUERY\n" --" QUERY := {all|inet|tcp|udp|raw|unix|packet|netlink}[,QUERY]\n" -+" QUERY := {all|inet|tcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|netlink}[,QUERY]\n" - "\n" - " -D, --diag=FILE Dump raw information about TCP sockets to FILE\n" - " -F, --filter=FILE read filter information from FILE\n" --" FILTER := [ state TCP-STATE ] [ EXPRESSION ]\n" -+" FILTER := [ state STATE-FILTER ] [ EXPRESSION ]\n" -+" STATE-FILTER := {all|connected|synchronized|bucket|big|TCP-STATES}\n" -+" TCP-STATES := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|closed|close-wait|last-ack|listen|closing}\n" -+" connected := {established|syn-sent|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}\n" -+" synchronized := {established|syn-recv|fin-wait-{1,2}|time-wait|close-wait|last-ack|closing}\n" -+" bucket := {syn-recv|time-wait}\n" -+" big := {established|syn-sent|fin-wait-{1,2}|closed|close-wait|last-ack|listen|closing}\n" - ); - } - -@@ -3085,7 +3366,9 @@ static int scan_state(const char *state) - if (strcasecmp(state, sstate_namel[i]) == 0) - return (1<<i); - } -- return 0; -+ -+ fprintf(stderr, "ss: wrong state name: %s\n", state); -+ exit(-1); - } - - static const struct option long_opts[] = { -@@ -3115,25 +3398,25 @@ static const struct option long_opts[] = { - { "filter", 1, 0, 'F' }, - { "version", 0, 0, 'V' }, - { "help", 0, 0, 'h' }, -+ { "context", 0, 0, 'Z' }, -+ { "contexts", 0, 0, 'z' }, -+ { "net", 1, 0, 'N' }, - { 0 } - - }; - - int main(int argc, char *argv[]) - { -- int do_default = 1; - int saw_states = 0; - int saw_query = 0; - int do_summary = 0; - const char *dump_tcpdiag = NULL; - FILE *filter_fp = NULL; - int ch; -+ struct filter dbs_filter = {}; -+ int state_filter = 0; - -- memset(¤t_filter, 0, sizeof(current_filter)); -- -- current_filter.states = default_filter.states; -- -- while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbf:miA:D:F:vV", -+ while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbf:miA:D:F:vVzZN:", - long_opts, NULL)) != EOF) { - switch(ch) { - case 'n': -@@ -3164,55 +3447,51 @@ int main(int argc, char *argv[]) - show_bpf++; - break; - case 'd': -- current_filter.dbs |= (1<<DCCP_DB); -- do_default = 0; -+ filter_db_set(&dbs_filter, DCCP_DB); - break; - case 't': -- current_filter.dbs |= (1<<TCP_DB); -- do_default = 0; -+ filter_db_set(&dbs_filter, TCP_DB); - break; - case 'u': -- current_filter.dbs |= (1<<UDP_DB); -- do_default = 0; -+ filter_db_set(&dbs_filter, UDP_DB); - break; - case 'w': -- current_filter.dbs |= (1<<RAW_DB); -- do_default = 0; -+ filter_db_set(&dbs_filter, RAW_DB); - break; - case 'x': -- current_filter.dbs |= UNIX_DBM; -- do_default = 0; -+ filter_af_set(¤t_filter, AF_UNIX); - break; - case 'a': -- current_filter.states = SS_ALL; -+ state_filter = SS_ALL; - break; - case 'l': -- current_filter.states = (1<<SS_LISTEN) | (1<<SS_CLOSE); -+ state_filter = (1 << SS_LISTEN) | (1 << SS_CLOSE); - break; - case '4': -- preferred_family = AF_INET; -+ filter_af_set(¤t_filter, AF_INET); - break; - case '6': -- preferred_family = AF_INET6; -+ filter_af_set(¤t_filter, AF_INET6); - break; - case '0': -- preferred_family = AF_PACKET; -+ filter_af_set(¤t_filter, AF_PACKET); - break; - case 'f': - if (strcmp(optarg, "inet") == 0) -- preferred_family = AF_INET; -+ filter_af_set(¤t_filter, AF_INET); - else if (strcmp(optarg, "inet6") == 0) -- preferred_family = AF_INET6; -+ filter_af_set(¤t_filter, AF_INET6); - else if (strcmp(optarg, "link") == 0) -- preferred_family = AF_PACKET; -+ filter_af_set(¤t_filter, AF_PACKET); - else if (strcmp(optarg, "unix") == 0) -- preferred_family = AF_UNIX; -+ filter_af_set(¤t_filter, AF_UNIX); - else if (strcmp(optarg, "netlink") == 0) -- preferred_family = AF_NETLINK; -+ filter_af_set(¤t_filter, AF_NETLINK); - else if (strcmp(optarg, "help") == 0) - help(); - else { -- fprintf(stderr, "ss: \"%s\" is invalid family\n", optarg); -+ fprintf(stderr, "ss: \"%s\" is invalid family\n", -+ optarg); - usage(); - } - break; -@@ -3229,35 +3508,44 @@ int main(int argc, char *argv[]) - if ((p1 = strchr(p, ',')) != NULL) - *p1 = 0; - if (strcmp(p, "all") == 0) { -- current_filter.dbs = ALL_DB; -+ filter_default_dbs(&dbs_filter); - } else if (strcmp(p, "inet") == 0) { -- current_filter.dbs |= (1<<TCP_DB)|(1<<DCCP_DB)|(1<<UDP_DB)|(1<<RAW_DB); -+ filter_db_set(&dbs_filter, UDP_DB); -+ filter_db_set(&dbs_filter, DCCP_DB); -+ filter_db_set(&dbs_filter, TCP_DB); -+ filter_db_set(&dbs_filter, RAW_DB); - } else if (strcmp(p, "udp") == 0) { -- current_filter.dbs |= (1<<UDP_DB); -+ filter_db_set(&dbs_filter, UDP_DB); - } else if (strcmp(p, "dccp") == 0) { -- current_filter.dbs |= (1<<DCCP_DB); -+ filter_db_set(&dbs_filter, DCCP_DB); - } else if (strcmp(p, "tcp") == 0) { -- current_filter.dbs |= (1<<TCP_DB); -+ filter_db_set(&dbs_filter, TCP_DB); - } else if (strcmp(p, "raw") == 0) { -- current_filter.dbs |= (1<<RAW_DB); -+ filter_db_set(&dbs_filter, RAW_DB); - } else if (strcmp(p, "unix") == 0) { -- current_filter.dbs |= UNIX_DBM; -+ filter_db_set(&dbs_filter, UNIX_ST_DB); -+ filter_db_set(&dbs_filter, UNIX_DG_DB); -+ filter_db_set(&dbs_filter, UNIX_SQ_DB); - } else if (strcasecmp(p, "unix_stream") == 0 || - strcmp(p, "u_str") == 0) { -- current_filter.dbs |= (1<<UNIX_ST_DB); -+ filter_db_set(&dbs_filter, UNIX_ST_DB); - } else if (strcasecmp(p, "unix_dgram") == 0 || - strcmp(p, "u_dgr") == 0) { -- current_filter.dbs |= (1<<UNIX_DG_DB); -+ filter_db_set(&dbs_filter, UNIX_DG_DB); -+ } else if (strcasecmp(p, "unix_seqpacket") == 0 || -+ strcmp(p, "u_seq") == 0) { -+ filter_db_set(&dbs_filter, UNIX_SQ_DB); - } else if (strcmp(p, "packet") == 0) { -- current_filter.dbs |= PACKET_DBM; -+ filter_db_set(&dbs_filter, PACKET_R_DB); -+ filter_db_set(&dbs_filter, PACKET_DG_DB); - } else if (strcmp(p, "packet_raw") == 0 || - strcmp(p, "p_raw") == 0) { -- current_filter.dbs |= (1<<PACKET_R_DB); -+ filter_db_set(&dbs_filter, PACKET_R_DB); - } else if (strcmp(p, "packet_dgram") == 0 || - strcmp(p, "p_dgr") == 0) { -- current_filter.dbs |= (1<<PACKET_DG_DB); -+ filter_db_set(&dbs_filter, PACKET_DG_DB); - } else if (strcmp(p, "netlink") == 0) { -- current_filter.dbs |= (1<<NETLINK_DB); -+ filter_db_set(&dbs_filter, NETLINK_DB); - } else { - fprintf(stderr, "ss: \"%s\" is illegal socket table id\n", p); - usage(); -@@ -3290,6 +3578,20 @@ int main(int argc, char *argv[]) - case 'V': - printf("ss utility, iproute2-ss%s\n", SNAPSHOT); - exit(0); -+ case 'z': -+ show_sock_ctx++; -+ case 'Z': -+ if (is_selinux_enabled() <= 0) { -+ fprintf(stderr, "ss: SELinux is not enabled.\n"); -+ exit(1); -+ } -+ show_proc_ctx++; -+ user_ent_hash_build(); -+ break; -+ case 'N': -+ if (netns_switch(optarg)) -+ exit(1); -+ break; - case 'h': - case '?': - help(); -@@ -3301,65 +3603,12 @@ int main(int argc, char *argv[]) - argc -= optind; - argv += optind; - -- get_slabstat(&slabstat); -- - if (do_summary) { - print_summary(); - if (do_default && argc == 0) - exit(0); - } - -- if (do_default) -- current_filter.dbs = default_filter.dbs; -- -- if (preferred_family == AF_UNSPEC) { -- if (!(current_filter.dbs&~UNIX_DBM)) -- preferred_family = AF_UNIX; -- else if (!(current_filter.dbs&~PACKET_DBM)) -- preferred_family = AF_PACKET; -- else if (!(current_filter.dbs&~(1<<NETLINK_DB))) -- preferred_family = AF_NETLINK; -- } -- -- if (preferred_family != AF_UNSPEC) { -- int mask2; -- if (preferred_family == AF_INET || -- preferred_family == AF_INET6) { -- mask2= current_filter.dbs; -- } else if (preferred_family == AF_PACKET) { -- mask2 = PACKET_DBM; -- } else if (preferred_family == AF_UNIX) { -- mask2 = UNIX_DBM; -- } else if (preferred_family == AF_NETLINK) { -- mask2 = (1<<NETLINK_DB); -- } else { -- mask2 = 0; -- } -- -- if (do_default) -- current_filter.dbs = mask2; -- else -- current_filter.dbs &= mask2; -- current_filter.families = (1<<preferred_family); -- } else { -- if (!do_default) -- current_filter.families = ~0; -- else -- current_filter.families = default_filter.families; -- } -- if (current_filter.dbs == 0) { -- fprintf(stderr, "ss: no socket tables to show with such filter.\n"); -- exit(0); -- } -- if (current_filter.families == 0) { -- fprintf(stderr, "ss: no families to show with such filter.\n"); -- exit(0); -- } -- -- if (resolve_services && resolve_hosts && -- (current_filter.dbs&(UNIX_DBM|(1<<TCP_DB)|(1<<UDP_DB)|(1<<DCCP_DB)))) -- init_service_resolver(); -- - /* Now parse filter... */ - if (argc == 0 && filter_fp) { - if (ssfilter_parse(¤t_filter.f, 0, NULL, filter_fp)) -@@ -3370,24 +3619,43 @@ int main(int argc, char *argv[]) - if (strcmp(*argv, "state") == 0) { - NEXT_ARG(); - if (!saw_states) -- current_filter.states = 0; -- current_filter.states |= scan_state(*argv); -+ state_filter = 0; -+ state_filter |= scan_state(*argv); - saw_states = 1; - } else if (strcmp(*argv, "exclude") == 0 || - strcmp(*argv, "excl") == 0) { - NEXT_ARG(); - if (!saw_states) -- current_filter.states = SS_ALL; -- current_filter.states &= ~scan_state(*argv); -+ state_filter = SS_ALL; -+ state_filter &= ~scan_state(*argv); - saw_states = 1; - } else { -- if (ssfilter_parse(¤t_filter.f, argc, argv, filter_fp)) -- usage(); - break; - } - argc--; argv++; - } - -+ if (do_default) { -+ state_filter = state_filter ? state_filter : SS_CONN; -+ filter_default_dbs(¤t_filter); -+ filter_merge(¤t_filter, ¤t_filter, state_filter); -+ } else { -+ filter_merge(¤t_filter, &dbs_filter, state_filter); -+ } -+ -+ if (resolve_services && resolve_hosts && -+ (current_filter.dbs&(UNIX_DBM|(1<<TCP_DB)|(1<<UDP_DB)|(1<<DCCP_DB)))) -+ init_service_resolver(); -+ -+ -+ if (current_filter.dbs == 0) { -+ fprintf(stderr, "ss: no socket tables to show with such filter.\n"); -+ exit(0); -+ } -+ if (current_filter.families == 0) { -+ fprintf(stderr, "ss: no families to show with such filter.\n"); -+ exit(0); -+ } - if (current_filter.states == 0) { - fprintf(stderr, "ss: no socket states to show with such filter.\n"); - exit(0); -@@ -3411,6 +3679,9 @@ int main(int argc, char *argv[]) - exit(0); - } - -+ if (ssfilter_parse(¤t_filter.f, argc, argv, filter_fp)) -+ usage(); -+ - netid_width = 0; - if (current_filter.dbs&(current_filter.dbs-1)) - netid_width = 5; -@@ -3457,6 +3728,10 @@ int main(int argc, char *argv[]) - printf("%-*s ", state_width, "State"); - printf("%-6s %-6s ", "Recv-Q", "Send-Q"); - -+ /* Make enough space for the local/remote port field */ -+ addr_width -= 13; -+ serv_width += 13; -+ - printf("%*s:%-*s %*s:%-*s\n", - addr_width, "Local Address", serv_width, "Port", - addr_width, "Peer Address", serv_width, "Port"); -@@ -3477,5 +3752,9 @@ int main(int argc, char *argv[]) - tcp_show(¤t_filter, IPPROTO_TCP); - if (current_filter.dbs & (1<<DCCP_DB)) - tcp_show(¤t_filter, IPPROTO_DCCP); -+ -+ if (show_users || show_proc_ctx || show_sock_ctx) -+ user_ent_destroy(); -+ - return 0; - } -diff --git a/misc/ssfilter.h b/misc/ssfilter.h -index 00b92e3..b20092b 100644 ---- a/misc/ssfilter.h -+++ b/misc/ssfilter.h -@@ -9,6 +9,8 @@ - #define SSF_S_LE 8 - #define SSF_S_AUTO 9 - -+#include <stdbool.h> -+ - struct ssfilter - { - int type; -@@ -17,5 +19,5 @@ struct ssfilter - }; - - int ssfilter_parse(struct ssfilter **f, int argc, char **argv, FILE *fp); --void *parse_hostcond(char*); -+void *parse_hostcond(char *addr, bool is_port); - -diff --git a/misc/ssfilter.y b/misc/ssfilter.y -index 2e9d962..a258d04 100644 ---- a/misc/ssfilter.y -+++ b/misc/ssfilter.y -@@ -25,6 +25,7 @@ static char **yy_argv; - static int yy_argc; - static FILE *yy_fp; - static ssfilter_t *yy_ret; -+static int tok_type = -1; - - static int yylex(void); - -@@ -220,14 +221,22 @@ int yylex(void) - return '('; - if (strcmp(curtok, ")") == 0) - return ')'; -- if (strcmp(curtok, "dst") == 0) -+ if (strcmp(curtok, "dst") == 0) { -+ tok_type = DCOND; - return DCOND; -- if (strcmp(curtok, "src") == 0) -+ } -+ if (strcmp(curtok, "src") == 0) { -+ tok_type = SCOND; - return SCOND; -- if (strcmp(curtok, "dport") == 0) -+ } -+ if (strcmp(curtok, "dport") == 0) { -+ tok_type = DPORT; - return DPORT; -- if (strcmp(curtok, "sport") == 0) -+ } -+ if (strcmp(curtok, "sport") == 0) { -+ tok_type = SPORT; - return SPORT; -+ } - if (strcmp(curtok, ">=") == 0 || - strcmp(curtok, "ge") == 0 || - strcmp(curtok, "geq") == 0) -@@ -250,9 +259,11 @@ int yylex(void) - if (strcmp(curtok, "<") == 0 || - strcmp(curtok, "lt") == 0) - return '<'; -- if (strcmp(curtok, "autobound") == 0) -+ if (strcmp(curtok, "autobound") == 0) { -+ tok_type = AUTOBOUND; - return AUTOBOUND; -- yylval = (void*)parse_hostcond(curtok); -+ } -+ yylval = (void*)parse_hostcond(curtok, tok_type == SPORT || tok_type == DPORT); - if (yylval == NULL) { - fprintf(stderr, "Cannot parse dst/src address.\n"); - exit(1); --- -2.3.5 - diff --git a/SOURCES/iproute2-3.10.0-tc-fix-for-qdiscs-without-options.patch b/SOURCES/iproute2-3.10.0-tc-fix-for-qdiscs-without-options.patch deleted file mode 100644 index 87ff98b..0000000 --- a/SOURCES/iproute2-3.10.0-tc-fix-for-qdiscs-without-options.patch +++ /dev/null @@ -1,65 +0,0 @@ -From f2794eafcfaa6dacb1bdcf5cfc11bf9d173cad28 Mon Sep 17 00:00:00 2001 -From: Stephen Hemminger <stephen@networkplumber.org> -Date: Mon, 26 Aug 2013 08:41:19 -0700 -Subject: [PATCH] tc: fix for qdiscs without options - -This is a combination of 2 commits which fix tc for adding a qdisc which does -not support options, like e.g. pfifo_fast. A simple test-case is: - -tc qdisc replace dev eth0 root pfifo_fast - -Without this patch applied, the above command fails with the following message: - -qdisc 'pfifo_fast' does not support option parsing - -commit e9e78b0db0e023035e346ba67de838be851eb665 -Author: Stephen Hemminger <stephen@networkplumber.org> -Date: Mon Aug 26 08:41:19 2013 -0700 - - tc: allow qdisc without options - - Pfifo_fast needs no options. So don't force it to have parsing code. - -commit 0a502b21e30be835dcad8d9c6023a41da8709eb1 -Author: Stephen Hemminger <stephen@networkplumber.org> -Date: Sun Oct 27 12:26:47 2013 -0700 - - Fix handling of qdis without options - - Some qdisc like htb want the parse_qopt to be called even if no options - present. Fixes regression caused by: - - e9e78b0db0e023035e346ba67de838be851eb665 is the first bad commit - commit e9e78b0db0e023035e346ba67de838be851eb665 - Author: Stephen Hemminger <stephen@networkplumber.org> - Date: Mon Aug 26 08:41:19 2013 -0700 - - tc: allow qdisc without options ---- - tc/tc_qdisc.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c -index f3bf5b5..e304858 100644 ---- a/tc/tc_qdisc.c -+++ b/tc/tc_qdisc.c -@@ -138,12 +138,13 @@ static int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv) - addattr_l(&req.n, sizeof(req), TCA_RATE, &est, sizeof(est)); - - if (q) { -- if (!q->parse_qopt) { -+ if (q->parse_qopt) { -+ if (q->parse_qopt(q, argc, argv, &req.n)) -+ return 1; -+ } else if (argc) { - fprintf(stderr, "qdisc '%s' does not support option parsing\n", k); - return -1; - } -- if (q->parse_qopt(q, argc, argv, &req.n)) -- return 1; - } else { - if (argc) { - if (matches(*argv, "help") == 0) --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-tc.patch b/SOURCES/iproute2-3.10.0-tc.patch deleted file mode 100644 index 61cab01..0000000 --- a/SOURCES/iproute2-3.10.0-tc.patch +++ /dev/null @@ -1,168 +0,0 @@ -commit 53e34d82748442625618582eb88512fc4ee49c2e -Author: Pavel Šimerda <psimerda@redhat.com> -Date: Thu May 28 12:17:39 2015 +0200 - - backport selected tc features and documentation - -diff --git a/man/man8/tc.8 b/man/man8/tc.8 -index e0acfeb..cc839d9 100644 ---- a/man/man8/tc.8 -+++ b/man/man8/tc.8 -@@ -2,7 +2,9 @@ - .SH NAME - tc \- show / manipulate traffic control settings - .SH SYNOPSIS --.B tc qdisc [ add | change | replace | link | delete ] dev -+.B tc -+.RI "[ " OPTIONS " ]" -+.B qdisc [ add | change | replace | link | delete ] dev - DEV - .B - [ parent -@@ -13,7 +15,9 @@ qdisc-id ] qdisc - [ qdisc specific parameters ] - .P - --.B tc class [ add | change | replace | delete ] dev -+.B tc -+.RI "[ " OPTIONS " ]" -+.B class [ add | change | replace | delete ] dev - DEV - .B parent - qdisc-id -@@ -22,7 +26,9 @@ class-id ] qdisc - [ qdisc specific parameters ] - .P - --.B tc filter [ add | change | replace | delete ] dev -+.B tc -+.RI "[ " OPTIONS " ]" -+.B filter [ add | change | replace | delete ] dev - DEV - .B [ parent - qdisc-id -@@ -35,21 +41,28 @@ priority filtertype - flow-id - - .B tc -+.RI "[ " OPTIONS " ]" - .RI "[ " FORMAT " ]" - .B qdisc show [ dev - DEV - .B ] - .P - .B tc -+.RI "[ " OPTIONS " ]" - .RI "[ " FORMAT " ]" - .B class show dev - DEV - .P --.B tc filter show dev -+.B tc -+.RI "[ " OPTIONS " ]" -+.B filter show dev - DEV - - .P --.B tc [ -force ] -b\fR[\fIatch\fR] \fB[ filename ] -+.ti 8 -+.IR OPTIONS " := {" -+\fB[ -force ] [ -OK ] -b\fR[\fIatch\fR] \fB[ filename ] \fR| -+\fB[ \fB-n\fR[\fIetns\fR] name \fB] \fR} - - .ti 8 - .IR FORMAT " := {" -@@ -407,6 +420,44 @@ link - Only available for qdiscs and performs a replace where the node - must exist already. - -+.SH OPTIONS -+ -+.TP -+.BR "\-b", " \-b filename", " \-batch", " \-batch filename" -+read commands from provided file or standard input and invoke them. -+First failure will cause termination of tc. -+ -+.TP -+.BR "\-force" -+don't terminate tc on errors in batch mode. -+If there were any errors during execution of the commands, the application return code will be non zero. -+ -+.TP -+.BR "\-OK" -+in batch mode, print -+.B OK -+and a new line on standard output after each successfully interpreted command. -+ -+.TP -+.BR "\-n" , " \-net" , " \-netns " <NETNS> -+switches -+.B tc -+to the specified network namespace -+.IR NETNS . -+Actually it just simplifies executing of: -+ -+.B ip netns exec -+.IR NETNS -+.B tc -+.RI "[ " OPTIONS " ] " OBJECT " { " COMMAND " | " -+.BR help " }" -+ -+to -+ -+.B tc -+.RI "-n[etns] " NETNS " [ " OPTIONS " ] " OBJECT " { " COMMAND " | " -+.BR help " }" -+ - .SH FORMAT - The show command has additional formatting options: - -diff --git a/tc/Makefile b/tc/Makefile -index 0277760..af6a277 100644 ---- a/tc/Makefile -+++ b/tc/Makefile -@@ -3,6 +3,11 @@ TCOBJ= tc.o tc_qdisc.o tc_class.o tc_filter.o tc_util.o \ - m_ematch.o emp_ematch.yacc.o emp_ematch.lex.o - - include ../Config -+ -+ifeq ($(IP_CONFIG_SETNS),y) -+ CFLAGS += -DHAVE_SETNS -+endif -+ - SHARED_LIBS ?= y - - TCMODULES := -diff --git a/tc/tc.c b/tc/tc.c -index b43bb47..4aaec21 100644 ---- a/tc/tc.c -+++ b/tc/tc.c -@@ -29,6 +29,7 @@ - #include "utils.h" - #include "tc_util.h" - #include "tc_common.h" -+#include "namespace.h" - - int show_stats = 0; - int show_details = 0; -@@ -186,7 +187,8 @@ static void usage(void) - fprintf(stderr, "Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }\n" - " tc [-force] [-OK] -batch filename\n" - "where OBJECT := { qdisc | class | filter | action | monitor }\n" -- " OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -p[retty] | -b[atch] [filename] }\n"); -+ " OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -p[retty] | -b[atch] [filename] | " -+ "-n[etns] name }\n"); - } - - static int do_cmd(int argc, char **argv) -@@ -299,6 +301,10 @@ int main(int argc, char **argv) - if (argc <= 1) - usage(); - batch_file = argv[1]; -+ } else if (matches(argv[1], "-netns") == 0) { -+ NEXT_ARG(); -+ if (netns_switch(argv[1])) -+ return -1; - } else { - fprintf(stderr, "Option \"%s\" is unknown, try \"tc -help\".\n", argv[1]); - return -1; diff --git a/SOURCES/iproute2-3.10.0-xfrm-state-overflow.patch b/SOURCES/iproute2-3.10.0-xfrm-state-overflow.patch deleted file mode 100644 index dfe448a..0000000 --- a/SOURCES/iproute2-3.10.0-xfrm-state-overflow.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 7887635f629c5a73be5e2db0a1a8a221e8b16077 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Petr=20=C5=A0abata?= <contyk@redhat.com> -Date: Wed, 17 Jul 2013 15:29:54 +0200 -Subject: [PATCH] Avoid overflow segfault with FORTIFY_SOURCE -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Petr Šabata <contyk@redhat.com> ---- - ip/xfrm_state.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c -index 389942c..160ab32 100644 ---- a/ip/xfrm_state.c -+++ b/ip/xfrm_state.c -@@ -157,12 +157,16 @@ static int xfrm_algo_parse(struct xfrm_algo *alg, enum xfrm_attr_type_t type, - buf[j] = val; - } - } else { -+ int i; - len = slen; - if (len > 0) { - if (len > max) - invarg("ALGO-KEYMAT value makes buffer overflow\n", key); - -- strncpy(buf, key, len); -+ for (i = 0 ; i < len && key[i] != '\0'; i++) -+ buf[i] = key[i]; -+ for ( ; i < len; i++) -+ buf[i] = '\0'; - } - } - --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.10.0-xfrm.patch b/SOURCES/iproute2-3.10.0-xfrm.patch deleted file mode 100644 index 3d75f2e..0000000 --- a/SOURCES/iproute2-3.10.0-xfrm.patch +++ /dev/null @@ -1,326 +0,0 @@ -commit f3de468299d13204f47dd8e431750fcba33fcd29 -Author: Christophe Gouault <christophe.gouault@6wind.com> -Date: Thu Apr 9 17:39:32 2015 +0200 - - xfrm: add command for configuring SPD hash table - - add a new command to configure the SPD hash table: - ip xfrm policy set [ hthresh4 LBITS RBITS ] [ hthresh6 LBITS RBITS ] - - and code to display the SPD hash configuration: - ip -s -s xfrm policy count - - hthresh4: defines minimum local and remote IPv4 prefix lengths of - selectors to hash a policy. If prefix lengths are greater or equal - to the thresholds, then the policy is hashed, otherwise it falls back - in the policy_inexact chained list. - - hthresh6: defines minimum local and remote IPv6 prefix lengths of - selectors to hash a policy, otherwise it falls back - in the policy_inexact chained list. - - Example: - - % ip -s -s xfrm policy count - SPD IN 0 OUT 0 FWD 0 (Sock: IN 0 OUT 0 FWD 0) - SPD buckets: count 7 Max 1048576 - SPD IPv4 thresholds: local 32 remote 32 - SPD IPv6 thresholds: local 128 remote 128 - - % ip xfrm pol set hthresh4 24 16 hthresh6 64 56 - - % ip -s -s xfrm policy count - SPD IN 0 OUT 0 FWD 0 (Sock: IN 0 OUT 0 FWD 0) - SPD buckets: count 7 Max 1048576 - SPD IPv4 thresholds: local 24 remote 16 - SPD IPv6 thresholds: local 64 remote 56 - - Signed-off-by: Christophe Gouault <christophe.gouault@6wind.com> - -diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c -index 36e33c9..9ac4a89 100644 ---- a/ip/xfrm_policy.c -+++ b/ip/xfrm_policy.c -@@ -64,7 +64,8 @@ static void usage(void) - fprintf(stderr, " [ index INDEX ] [ ptype PTYPE ] [ action ACTION ] [ priority PRIORITY ]\n"); - fprintf(stderr, " [ flag FLAG-LIST ]\n"); - fprintf(stderr, "Usage: ip xfrm policy flush [ ptype PTYPE ]\n"); -- fprintf(stderr, "Usage: ip xfrm count\n"); -+ fprintf(stderr, "Usage: ip xfrm policy count\n"); -+ fprintf(stderr, "Usage: ip xfrm policy set [ hthresh4 LBITS RBITS ] [ hthresh6 LBITS RBITS ]\n"); - fprintf(stderr, "SELECTOR := [ src ADDR[/PLEN] ] [ dst ADDR[/PLEN] ] [ dev DEV ] [ UPSPEC ]\n"); - fprintf(stderr, "UPSPEC := proto { { "); - fprintf(stderr, "%s | ", strxf_proto(IPPROTO_TCP)); -@@ -935,7 +936,7 @@ static int print_spdinfo( struct nlmsghdr *n, void *arg) - fprintf(fp,")"); - } - -- fprintf(fp,"\n"); -+ fprintf(fp, "%s", _SL_); - } - if (show_stats > 1) { - struct xfrmu_spdhinfo *sh; -@@ -949,13 +950,109 @@ static int print_spdinfo( struct nlmsghdr *n, void *arg) - fprintf(fp,"\t SPD buckets:"); - fprintf(fp," count %d", sh->spdhcnt); - fprintf(fp," Max %d", sh->spdhmcnt); -+ fprintf(fp, "%s", _SL_); -+ } -+ if (tb[XFRMA_SPD_IPV4_HTHRESH]) { -+ struct xfrmu_spdhthresh *th; -+ if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV4_HTHRESH]) < sizeof(*th)) { -+ fprintf(stderr, "SPDinfo: Wrong len %d\n", len); -+ return -1; -+ } -+ th = RTA_DATA(tb[XFRMA_SPD_IPV4_HTHRESH]); -+ fprintf(fp,"\t SPD IPv4 thresholds:"); -+ fprintf(fp," local %d", th->lbits); -+ fprintf(fp," remote %d", th->rbits); -+ fprintf(fp, "%s", _SL_); -+ -+ } -+ if (tb[XFRMA_SPD_IPV6_HTHRESH]) { -+ struct xfrmu_spdhthresh *th; -+ if (RTA_PAYLOAD(tb[XFRMA_SPD_IPV6_HTHRESH]) < sizeof(*th)) { -+ fprintf(stderr, "SPDinfo: Wrong len %d\n", len); -+ return -1; -+ } -+ th = RTA_DATA(tb[XFRMA_SPD_IPV6_HTHRESH]); -+ fprintf(fp,"\t SPD IPv6 thresholds:"); -+ fprintf(fp," local %d", th->lbits); -+ fprintf(fp," remote %d", th->rbits); -+ fprintf(fp, "%s", _SL_); - } - } -- fprintf(fp,"\n"); -+ -+ if (oneline) -+ fprintf(fp, "\n"); - - return 0; - } - -+static int xfrm_spd_setinfo(int argc, char **argv) -+{ -+ struct rtnl_handle rth; -+ struct { -+ struct nlmsghdr n; -+ __u32 flags; -+ char buf[RTA_BUF_SIZE]; -+ } req; -+ -+ char *thr4 = NULL; -+ char *thr6 = NULL; -+ -+ memset(&req, 0, sizeof(req)); -+ -+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(__u32)); -+ req.n.nlmsg_flags = NLM_F_REQUEST; -+ req.n.nlmsg_type = XFRM_MSG_NEWSPDINFO; -+ req.flags = 0XFFFFFFFF; -+ -+ while (argc > 0) { -+ if (strcmp(*argv, "hthresh4") == 0) { -+ struct xfrmu_spdhthresh thr; -+ -+ if (thr4) -+ duparg("hthresh4", *argv); -+ thr4 = *argv; -+ NEXT_ARG(); -+ if (get_u8(&thr.lbits, *argv, 0) || thr.lbits > 32) -+ invarg("hthresh4 LBITS value is invalid", *argv); -+ NEXT_ARG(); -+ if (get_u8(&thr.rbits, *argv, 0) || thr.rbits > 32) -+ invarg("hthresh4 RBITS value is invalid", *argv); -+ -+ addattr_l(&req.n, sizeof(req), XFRMA_SPD_IPV4_HTHRESH, -+ (void *)&thr, sizeof(thr)); -+ } else if (strcmp(*argv, "hthresh6") == 0) { -+ struct xfrmu_spdhthresh thr; -+ -+ if (thr6) -+ duparg("hthresh6", *argv); -+ thr6 = *argv; -+ NEXT_ARG(); -+ if (get_u8(&thr.lbits, *argv, 0) || thr.lbits > 128) -+ invarg("hthresh6 LBITS value is invalid", *argv); -+ NEXT_ARG(); -+ if (get_u8(&thr.rbits, *argv, 0) || thr.rbits > 128) -+ invarg("hthresh6 RBITS value is invalid", *argv); -+ -+ addattr_l(&req.n, sizeof(req), XFRMA_SPD_IPV6_HTHRESH, -+ (void *)&thr, sizeof(thr)); -+ } else { -+ invarg("unknown", *argv); -+ } -+ -+ argc--; argv++; -+ } -+ -+ if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) -+ exit(1); -+ -+ if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ exit(2); -+ -+ rtnl_close(&rth); -+ -+ return 0; -+} -+ - static int xfrm_spd_getinfo(int argc, char **argv) - { - struct rtnl_handle rth; -@@ -1059,6 +1156,8 @@ int do_xfrm_policy(int argc, char **argv) - return xfrm_policy_flush(argc-1, argv+1); - if (matches(*argv, "count") == 0) - return xfrm_spd_getinfo(argc, argv); -+ if (matches(*argv, "set") == 0) -+ return xfrm_spd_setinfo(argc-1, argv+1); - if (matches(*argv, "help") == 0) - usage(); - fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm policy help\".\n", *argv); -commit 0b1562a4459c59d79ecabcf919e3db423a2c321d -Author: Christophe Gouault <christophe.gouault@6wind.com> -Date: Thu Apr 9 17:39:33 2015 +0200 - - xfrm: revise man page and document ip xfrm policy set - - - document ip xfrm policy set - - update ip xfrm monitor documentation - - in DESCRIPTION section, reorganize grouping of commands - - Signed-off-by: Christophe Gouault <christophe.gouault@6wind.com> - -diff --git a/man/man8/ip-xfrm.8 b/man/man8/ip-xfrm.8 -index 2d31b4d..e305c0b 100644 ---- a/man/man8/ip-xfrm.8 -+++ b/man/man8/ip-xfrm.8 -@@ -252,6 +252,13 @@ ip-xfrm \- transform configuration - .B "ip xfrm policy count" - - .ti -8 -+.B "ip xfrm policy set" -+.RB "[ " hthresh4 -+.IR LBITS " " RBITS " ]" -+.RB "[ " hthresh6 -+.IR LBITS " " RBITS " ]" -+ -+.ti -8 - .IR SELECTOR " :=" - .RB "[ " src - .IR ADDR "[/" PLEN "] ]" -@@ -355,6 +362,13 @@ ip-xfrm \- transform configuration - .BR "ip xfrm monitor" " [ " all " |" - .IR LISTofXFRM-OBJECTS " ]" - -+.ti -8 -+.IR LISTofXFRM-OBJECTS " := [ " LISTofXFRM-OBJECTS " ] " XFRM-OBJECT -+ -+.ti -8 -+.IR XFRM-OBJECT " := " -+.BR acquire " | " expire " | " SA " | " policy " | " aevent " | " report -+ - .in -8 - .ad b - -@@ -380,7 +394,6 @@ ip xfrm state deleteall delete all existing state in xfrm - ip xfrm state list print out the list of existing state in xfrm - ip xfrm state flush flush all state in xfrm - ip xfrm state count count all existing state in xfrm --ip xfrm monitor state monitoring for xfrm objects - .TE - - .TP -@@ -502,7 +515,9 @@ encapsulates packets with protocol - .BR espinudp " or " espinudp-nonike "," - .RI "using source port " SPORT ", destination port " DPORT - .RI ", and original address " OADDR "." -+ - .sp -+.PP - .TS - l l. - ip xfrm policy add add a new policy -@@ -512,7 +527,6 @@ ip xfrm policy get get an existing policy - ip xfrm policy deleteall delete all existing xfrm policies - ip xfrm policy list print out the list of xfrm policies - ip xfrm policy flush flush policies --ip xfrm policy count count existing policies - .TE - - .TP -@@ -607,7 +621,50 @@ and inbound trigger - can be - .BR required " (default) or " use "." - -+.sp -+.PP -+.TS -+l l. -+ip xfrm policy count count existing policies -+.TE -+ -+.PP -+Use one or more -s options to display more details, including policy hash table -+information. -+ -+.sp -+.PP -+.TS -+l l. -+ip xfrm policy set configure the policy hash table -+.TE -+ -+.PP -+Security policies whose address prefix lengths are greater than or equal -+policy hash table thresholds are hashed. Others are stored in the -+policy_inexact chained list. -+ -+.TP -+.I LBITS -+specifies the minimum local address prefix length of policies that are -+stored in the Security Policy Database hash table. -+ -+.TP -+.I RBITS -+specifies the minimum remote address prefix length of policies that are -+stored in the Security Policy Database hash table. -+ -+.sp -+.PP -+.TS -+l l. -+ip xfrm monitor state monitoring for xfrm objects -+.TE -+ -+.PP - The xfrm objects to monitor can be optionally specified. - - .SH AUTHOR - Manpage revised by David Ward <david.ward@ll.mit.edu> -+.br -+Manpage revised by Christophe Gouault <christophe.gouault@6wind.com> -commit 5bf9f5c5a0f2d8a0fdb06c60242ff805177a4d73 -Author: Vadim Kochan <vadim4j@gmail.com> -Date: Sat Feb 14 19:45:04 2015 +0200 - - ip xfrm: Allow to specify "all" option for monitor - - Just to be aligned with the usage output. - - Signed-off-by: Vadim Kochan <vadim4j@gmail.com> - -diff --git a/ip/xfrm_monitor.c b/ip/xfrm_monitor.c -index 79453e4..8aa6f49 100644 ---- a/ip/xfrm_monitor.c -+++ b/ip/xfrm_monitor.c -@@ -374,7 +374,7 @@ int do_xfrm_monitor(int argc, char **argv) - groups = 0; - } else if (matches(*argv, "help") == 0) { - usage(); -- } else { -+ } else if (strcmp(*argv, "all")) { - fprintf(stderr, "Argument \"%s\" is unknown, try \"ip xfrm monitor help\".\n", *argv); - exit(-1); - } diff --git a/SOURCES/iproute2-3.11.0-tc-ok.patch b/SOURCES/iproute2-3.11.0-tc-ok.patch deleted file mode 100644 index f717497..0000000 --- a/SOURCES/iproute2-3.11.0-tc-ok.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 3c4b5a852d5bb9070c7fb4428aa50f2e3e1f6e1b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com> -Date: Thu, 19 Sep 2013 11:25:49 +0200 -Subject: [PATCH] Confirm success for each tc -batch command -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If `tc -force -batch' is fed by a controlling program from a pipe, -it's not possible to recognize when a command has been processes -successfully. - -This patch adds an optional `-OK' option to the tc(8) tool, so `tc --force -OK -batch' will print "OK\n" to standard output on each -successfully completed tc command. - -Signed-off-by: Petr Písař <ppisar@redhat.com> ---- - man/man8/tc.8 | 8 +++++++- - tc/tc.c | 8 +++++++- - 2 files changed, 14 insertions(+), 2 deletions(-) - -diff --git a/tc/tc.c b/tc/tc.c -index 9b50e74..b43bb47 100644 ---- a/tc/tc.c -+++ b/tc/tc.c -@@ -39,6 +39,7 @@ int batch_mode = 0; - int resolve_hosts = 0; - int use_iec = 0; - int force = 0; -+int ok = 0; - struct rtnl_handle rth; - - static void *BODY = NULL; /* cached handle dlopen(NULL) */ -@@ -183,7 +184,7 @@ noexist: - static void usage(void) - { - fprintf(stderr, "Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }\n" -- " tc [-force] -batch filename\n" -+ " tc [-force] [-OK] -batch filename\n" - "where OBJECT := { qdisc | class | filter | action | monitor }\n" - " OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -p[retty] | -b[atch] [filename] }\n"); - } -@@ -251,6 +252,9 @@ static int batch(const char *name) - ret = 1; - if (!force) - break; -+ } else if (ok) { -+ printf("OK\n"); -+ fflush(stdout); - } - } - if (line) -@@ -288,6 +292,8 @@ int main(int argc, char **argv) - return 0; - } else if (matches(argv[1], "-force") == 0) { - ++force; -+ } else if (matches(argv[1], "-OK") == 0) { -+ ++ok; - } else if (matches(argv[1], "-batch") == 0) { - argc--; argv++; - if (argc <= 1) --- -1.8.3.1 - diff --git a/SOURCES/iproute2-3.16.0-addrlabel.patch b/SOURCES/iproute2-3.16.0-addrlabel.patch deleted file mode 100644 index 4361395..0000000 --- a/SOURCES/iproute2-3.16.0-addrlabel.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/lib/utils.c b/lib/utils.c -index 4e9c719..eb92414 100644 ---- a/lib/utils.c -+++ b/lib/utils.c -@@ -487,7 +487,7 @@ int get_addr(inet_prefix *dst, const char *arg, int family) - exit(1); - } - if (get_addr_1(dst, arg, family)) { -- fprintf(stderr, "Error: an inet address is expected rather than \"%s\".\n", arg); -+ fprintf(stderr, "Error: an %s address is expected rather than \"%s\".\n", (family == AF_INET6 ? "inet6" : "inet") ,arg); - exit(1); - } - return 0; -@@ -500,7 +500,7 @@ int get_prefix(inet_prefix *dst, char *arg, int family) - exit(1); - } - if (get_prefix_1(dst, arg, family)) { -- fprintf(stderr, "Error: an inet prefix is expected rather than \"%s\".\n", arg); -+ fprintf(stderr, "Error: an %s prefix is expected rather than \"%s\".\n", (family == AF_INET6 ? "inet6" : "inet") ,arg); - exit(1); - } - return 0; diff --git a/SOURCES/iproute2-3.16.0-bpf.patch b/SOURCES/iproute2-3.16.0-bpf.patch deleted file mode 100644 index 28ae5b5..0000000 --- a/SOURCES/iproute2-3.16.0-bpf.patch +++ /dev/null @@ -1,331 +0,0 @@ -From d05df6861f99f251282e59f36dd94d7ff28d1bb8 Mon Sep 17 00:00:00 2001 -From: Daniel Borkmann <dborkman@redhat.com> -Date: Mon, 28 Oct 2013 12:35:33 +0100 -Subject: tc: add cls_bpf frontend - -This is the iproute2 part of the kernel patch "net: sched: -add BPF-based traffic classifier". - -[Will re-submit later again for iproute2 when window for - -next submissions opens.] - -Signed-off-by: Daniel Borkmann <dborkman@redhat.com> -Cc: Thomas Graf <tgraf@suug.ch> - -diff --git a/tc/Makefile b/tc/Makefile -index f54a955..84215c0 100644 ---- a/tc/Makefile -+++ b/tc/Makefile -@@ -22,6 +22,7 @@ TCMODULES += f_u32.o - TCMODULES += f_route.o - TCMODULES += f_fw.o - TCMODULES += f_basic.o -+TCMODULES += f_bpf.o - TCMODULES += f_flow.o - TCMODULES += f_cgroup.o - TCMODULES += q_dsmark.o -diff --git a/tc/f_bpf.c b/tc/f_bpf.c -new file mode 100644 -index 0000000..d52d7d8 ---- /dev/null -+++ b/tc/f_bpf.c -@@ -0,0 +1,288 @@ -+/* -+ * f_bpf.c BPF-based Classifier -+ * -+ * This program is free software; you can distribute 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. -+ * -+ * Authors: Daniel Borkmann <dborkman@redhat.com> -+ */ -+ -+#include <stdio.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <syslog.h> -+#include <fcntl.h> -+#include <sys/socket.h> -+#include <netinet/in.h> -+#include <arpa/inet.h> -+#include <string.h> -+#include <stdbool.h> -+#include <errno.h> -+#include <linux/filter.h> -+#include <linux/if.h> -+ -+#include "utils.h" -+#include "tc_util.h" -+ -+static void explain(void) -+{ -+ fprintf(stderr, "Usage: ... bpf ...\n"); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, " [inline]: run bytecode BPF_BYTECODE\n"); -+ fprintf(stderr, " [from file]: run bytecode-file FILE\n"); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, " [ police POLICE_SPEC ] [ action ACTION_SPEC ]\n"); -+ fprintf(stderr, " [ classid CLASSID ]\n"); -+ fprintf(stderr, "\n"); -+ fprintf(stderr, "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n"); -+ fprintf(stderr, " c,t,f,k and s are decimals; s denotes number of 4-tuples\n"); -+ fprintf(stderr, "Where FILE points to a file containing the BPF_BYTECODE string\n"); -+ fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n"); -+} -+ -+static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len, -+ char **bpf_string, bool *need_release, -+ const char separator) -+{ -+ char sp; -+ -+ if (from_file) { -+ size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,"); -+ char *tmp_string; -+ FILE *fp; -+ -+ tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len; -+ tmp_string = malloc(tmp_len); -+ if (tmp_string == NULL) -+ return -ENOMEM; -+ -+ memset(tmp_string, 0, tmp_len); -+ -+ fp = fopen(arg, "r"); -+ if (fp == NULL) { -+ perror("Cannot fopen"); -+ free(tmp_string); -+ return -ENOENT; -+ } -+ -+ if (!fgets(tmp_string, tmp_len, fp)) { -+ free(tmp_string); -+ fclose(fp); -+ return -EIO; -+ } -+ -+ fclose(fp); -+ -+ *need_release = true; -+ *bpf_string = tmp_string; -+ } else { -+ *need_release = false; -+ *bpf_string = arg; -+ } -+ -+ if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 || -+ sp != separator) { -+ if (*need_release) -+ free(*bpf_string); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int bpf_parse_ops(int argc, char **argv, struct nlmsghdr *n, -+ bool from_file) -+{ -+ char *bpf_string, *token, separator = ','; -+ struct sock_filter bpf_ops[BPF_MAXINSNS]; -+ int ret = 0, i = 0; -+ bool need_release; -+ __u16 bpf_len = 0; -+ -+ if (argc < 1) -+ return -EINVAL; -+ if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string, -+ &need_release, separator)) -+ return -EINVAL; -+ if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ token = bpf_string; -+ while ((token = strchr(token, separator)) && (++token)[0]) { -+ if (i >= bpf_len) { -+ fprintf(stderr, "Real program length exceeds encoded " -+ "length parameter!\n"); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ if (sscanf(token, "%hu %hhu %hhu %u,", -+ &bpf_ops[i].code, &bpf_ops[i].jt, -+ &bpf_ops[i].jf, &bpf_ops[i].k) != 4) { -+ fprintf(stderr, "Error at instruction %d!\n", i); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ i++; -+ } -+ -+ if (i != bpf_len) { -+ fprintf(stderr, "Parsed program length is less than encoded" -+ "length parameter!\n"); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ addattr_l(n, MAX_MSG, TCA_BPF_OPS_LEN, &bpf_len, sizeof(bpf_len)); -+ addattr_l(n, MAX_MSG, TCA_BPF_OPS, &bpf_ops, -+ bpf_len * sizeof(struct sock_filter)); -+out: -+ if (need_release) -+ free(bpf_string); -+ -+ return ret; -+} -+ -+static void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len) -+{ -+ struct sock_filter *ops = (struct sock_filter *) RTA_DATA(bpf_ops); -+ int i; -+ -+ if (len == 0) -+ return; -+ -+ fprintf(f, "bytecode \'%u,", len); -+ -+ for (i = 0; i < len - 1; i++) -+ fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt, -+ ops[i].jf, ops[i].k); -+ -+ fprintf(f, "%hu %hhu %hhu %u\'\n", ops[i].code, ops[i].jt, -+ ops[i].jf, ops[i].k); -+} -+ -+static int bpf_parse_opt(struct filter_util *qu, char *handle, -+ int argc, char **argv, struct nlmsghdr *n) -+{ -+ struct tcmsg *t = NLMSG_DATA(n); -+ struct rtattr *tail; -+ long h = 0; -+ -+ if (argc == 0) -+ return 0; -+ -+ if (handle) { -+ h = strtol(handle, NULL, 0); -+ if (h == LONG_MIN || h == LONG_MAX) { -+ fprintf(stderr, "Illegal handle \"%s\", must be " -+ "numeric.\n", handle); -+ return -1; -+ } -+ } -+ -+ t->tcm_handle = h; -+ -+ tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len)); -+ addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0); -+ -+ while (argc > 0) { -+ if (matches(*argv, "run") == 0) { -+ bool from_file; -+ NEXT_ARG(); -+ if (strcmp(*argv, "bytecode-file") == 0) { -+ from_file = true; -+ } else if (strcmp(*argv, "bytecode") == 0) { -+ from_file = false; -+ } else { -+ fprintf(stderr, "What is \"%s\"?\n", *argv); -+ explain(); -+ return -1; -+ } -+ NEXT_ARG(); -+ if (bpf_parse_ops(argc, argv, n, from_file)) { -+ fprintf(stderr, "Illegal \"bytecode\"\n"); -+ return -1; -+ } -+ } else if (matches(*argv, "classid") == 0 || -+ strcmp(*argv, "flowid") == 0) { -+ unsigned handle; -+ NEXT_ARG(); -+ if (get_tc_classid(&handle, *argv)) { -+ fprintf(stderr, "Illegal \"classid\"\n"); -+ return -1; -+ } -+ addattr_l(n, MAX_MSG, TCA_BPF_CLASSID, &handle, 4); -+ } else if (matches(*argv, "action") == 0) { -+ NEXT_ARG(); -+ if (parse_action(&argc, &argv, TCA_BPF_ACT, n)) { -+ fprintf(stderr, "Illegal \"action\"\n"); -+ return -1; -+ } -+ continue; -+ } else if (matches(*argv, "police") == 0) { -+ NEXT_ARG(); -+ if (parse_police(&argc, &argv, TCA_BPF_POLICE, n)) { -+ fprintf(stderr, "Illegal \"police\"\n"); -+ return -1; -+ } -+ continue; -+ } else if (strcmp(*argv, "help") == 0) { -+ explain(); -+ return -1; -+ } else { -+ fprintf(stderr, "What is \"%s\"?\n", *argv); -+ explain(); -+ return -1; -+ } -+ argc--; argv++; -+ } -+ -+ tail->rta_len = (((void*)n)+n->nlmsg_len) - (void*)tail; -+ return 0; -+} -+ -+static int bpf_print_opt(struct filter_util *qu, FILE *f, -+ struct rtattr *opt, __u32 handle) -+{ -+ struct rtattr *tb[TCA_BPF_MAX + 1]; -+ -+ if (opt == NULL) -+ return 0; -+ -+ parse_rtattr_nested(tb, TCA_BPF_MAX, opt); -+ -+ if (handle) -+ fprintf(f, "handle 0x%x ", handle); -+ -+ if (tb[TCA_BPF_CLASSID]) { -+ SPRINT_BUF(b1); -+ fprintf(f, "flowid %s ", -+ sprint_tc_classid(rta_getattr_u32(tb[TCA_BPF_CLASSID]), b1)); -+ } -+ -+ if (tb[TCA_BPF_OPS] && tb[TCA_BPF_OPS_LEN]) -+ bpf_print_ops(f, tb[TCA_BPF_OPS], -+ rta_getattr_u16(tb[TCA_BPF_OPS_LEN])); -+ -+ if (tb[TCA_BPF_POLICE]) { -+ fprintf(f, "\n"); -+ tc_print_police(f, tb[TCA_BPF_POLICE]); -+ } -+ -+ if (tb[TCA_BPF_ACT]) { -+ tc_print_action(f, tb[TCA_BPF_ACT]); -+ } -+ -+ return 0; -+} -+ -+struct filter_util bpf_filter_util = { -+ .id = "bpf", -+ .parse_fopt = bpf_parse_opt, -+ .print_fopt = bpf_print_opt, -+}; --- -cgit v0.10.1 - -commit 793da0e7023ce29e32914af477fdbcc4bdbb022f -Author: Stephen Hemminger <stephen@networkplumber.org> -Date: Wed Oct 30 16:42:03 2013 -0700 - - Update kernel headers - - Lastest from net-next - diff --git a/SOURCES/iproute2-3.16.0-quickack.patch b/SOURCES/iproute2-3.16.0-quickack.patch deleted file mode 100644 index 8f47261..0000000 --- a/SOURCES/iproute2-3.16.0-quickack.patch +++ /dev/null @@ -1,81 +0,0 @@ -commit b37f2c895d7876416a45e608754a39fff47ddf29 -Author: Cong Wang <amwang@redhat.com> -Date: Sat Jun 15 09:39:19 2013 +0800 - - add quickack option to ip route - - This patch adds quickack option to enable/disable TCP quick ack - mode for per-route. - - Cc: Stephen Hemminger <stephen@networkplumber.org> - Cc: "David S. Miller" <davem@davemloft.net> - Cc: Thomas Graf <tgraf@suug.ch> - Signed-off-by: Cong Wang <amwang@redhat.com> - -diff --git a/ip/iproute.c b/ip/iproute.c -index adef774..46710b2 100644 ---- a/ip/iproute.c -+++ b/ip/iproute.c -@@ -52,6 +52,7 @@ static const char *mx_names[RTAX_MAX+1] = { - [RTAX_FEATURES] = "features", - [RTAX_RTO_MIN] = "rto_min", - [RTAX_INITRWND] = "initrwnd", -+ [RTAX_QUICKACK] = "quickack", - }; - static void usage(void) __attribute__((noreturn)); - -@@ -79,6 +80,7 @@ static void usage(void) - fprintf(stderr, " [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n"); - fprintf(stderr, " [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n"); - fprintf(stderr, " [ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]\n"); -+ fprintf(stderr, " [ quickack BOOL ]\n"); - fprintf(stderr, "TYPE := [ unicast | local | broadcast | multicast | throw |\n"); - fprintf(stderr, " unreachable | prohibit | blackhole | nat ]\n"); - fprintf(stderr, "TABLE_ID := [ local | main | default | all | NUMBER ]\n"); -@@ -86,6 +88,7 @@ static void usage(void) - fprintf(stderr, "NHFLAGS := [ onlink | pervasive ]\n"); - fprintf(stderr, "RTPROTO := [ kernel | boot | static | NUMBER ]\n"); - fprintf(stderr, "TIME := NUMBER[s|ms]\n"); -+ fprintf(stderr, "BOOL := [1|0]\n"); - exit(-1); - } - -@@ -885,6 +888,14 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) - if (get_unsigned(&win, *argv, 0)) - invarg("\"initrwnd\" value is invalid\n", *argv); - rta_addattr32(mxrta, sizeof(mxbuf), RTAX_INITRWND, win); -+ } else if (matches(*argv, "quickack") == 0) { -+ unsigned quickack; -+ NEXT_ARG(); -+ if (get_unsigned(&quickack, *argv, 0)) -+ invarg("\"quickack\" value is invalid\n", *argv); -+ if (quickack != 1 && quickack != 0) -+ invarg("\"quickack\" value should be 0 or 1\n", *argv); -+ rta_addattr32(mxrta, sizeof(mxbuf), RTAX_QUICKACK, quickack); - } else if (matches(*argv, "rttvar") == 0) { - unsigned win; - NEXT_ARG(); -diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in -index 2c35a97..01997fa 100644 ---- a/man/man8/ip-route.8.in -+++ b/man/man8/ip-route.8.in -@@ -111,6 +111,8 @@ replace " } " - .IR NUMBER " ] [ " - .B initrwnd - .IR NUMBER " ]" -+.B quickack -+.IR BOOL " ]" - - .ti -8 - .IR TYPE " := [ " -@@ -401,6 +403,10 @@ Actual window size is this value multiplied by the MSS of the connection. - The default value is zero, meaning to use Slow Start value. - - .TP -+.BI quickack " BOOL " "(3.11+ only)" -+Enable or disable quick ack for connections to this destination. -+ -+.TP - .BI advmss " NUMBER " "(2.3.15+ only)" - the MSS ('Maximal Segment Size') to advertise to these - destinations when establishing TCP connections. If it is not given, diff --git a/SOURCES/iproute2-3.4.0-kernel.patch b/SOURCES/iproute2-3.4.0-kernel.patch deleted file mode 100644 index 1e83729..0000000 --- a/SOURCES/iproute2-3.4.0-kernel.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/Makefile b/Makefile -index c107955..1e15c72 100644 ---- a/Makefile -+++ b/Makefile -@@ -7,6 +7,7 @@ DATADIR=$(PREFIX)/share - DOCDIR=$(DATADIR)/doc/iproute2 - MANDIR=$(DATADIR)/man - ARPDDIR=/var/lib/arpd -+KERNEL_INCLUDE=/usr/include - - # Path to db_185.h include - DBM_INCLUDE:=$(ROOTDIR)/usr/include diff --git a/SOURCES/iproute2-3.8.0-optflags.patch b/SOURCES/iproute2-3.8.0-optflags.patch deleted file mode 100644 index a7aebff..0000000 --- a/SOURCES/iproute2-3.8.0-optflags.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/Makefile b/Makefile -index 5edffc0..898b572 100644 ---- a/Makefile -+++ b/Makefile -@@ -34,7 +34,7 @@ CCOPTS = -O2 - WFLAGS := -Wall -Wstrict-prototypes -Werror -Wmissing-prototypes - WFLAGS += -Wmissing-declarations -Wold-style-definition - --CFLAGS = $(WFLAGS) $(CCOPTS) -I../include $(DEFINES) -+CFLAGS = $(WFLAGS) $(CCOPTS) -I../include $(DEFINES) $(RPM_OPT_FLAGS) - YACCFLAGS = -d -t -v - - SUBDIRS=lib ip tc bridge misc netem genl man diff --git a/SOURCES/iproute2-3.8.0-unused-result.patch b/SOURCES/iproute2-3.8.0-unused-result.patch deleted file mode 100644 index 0527ceb..0000000 --- a/SOURCES/iproute2-3.8.0-unused-result.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/Makefile b/Makefile -index 898b572..70a6e14 100644 ---- a/Makefile -+++ b/Makefile -@@ -31,7 +31,7 @@ CC = gcc - HOSTCC = gcc - DEFINES += -D_GNU_SOURCE - CCOPTS = -O2 --WFLAGS := -Wall -Wstrict-prototypes -Werror -Wmissing-prototypes -+WFLAGS := -Wall -Wstrict-prototypes -Wmissing-prototypes - WFLAGS += -Wmissing-declarations -Wold-style-definition - - CFLAGS = $(WFLAGS) $(CCOPTS) -I../include $(DEFINES) $(RPM_OPT_FLAGS) diff --git a/SOURCES/iproute2-3.9.0-IPPROTO_IP_for_SA.patch b/SOURCES/iproute2-3.9.0-IPPROTO_IP_for_SA.patch deleted file mode 100644 index 6c150ec..0000000 --- a/SOURCES/iproute2-3.9.0-IPPROTO_IP_for_SA.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c -index 0495ff4..b1d4c6e 100644 ---- a/ip/ipxfrm.c -+++ b/ip/ipxfrm.c -@@ -1275,6 +1275,7 @@ static int xfrm_selector_upspec_parse(struct xfrm_selector *sel, - case IPPROTO_UDP: - case IPPROTO_SCTP: - case IPPROTO_DCCP: -+ case IPPROTO_IP: /* to allow shared SA for different protocols */ - break; - default: - fprintf(stderr, "\"sport\" and \"dport\" are invalid with PROTO value \"%s\"\n", strxf_proto(sel->proto)); diff --git a/SOURCES/iproute2-4.0.0-netns.patch b/SOURCES/iproute2-4.0.0-netns.patch deleted file mode 100644 index c374dc4..0000000 --- a/SOURCES/iproute2-4.0.0-netns.patch +++ /dev/null @@ -1,423 +0,0 @@ -commit a721ebaafd6852e86b636e2595e36f635c2b3cae -Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> -Date: Wed Apr 15 14:23:22 2015 +0200 - - netns: allow to dump and monitor nsid - - Two commands are added: - - ip netns list-id - - ip monitor nsid - - A cache is also added to remember the association between the iproute2 netns - name (from /var/run/netns/) and the nsid. - To avoid interfering with the rth socket, a new rtnl socket (rtnsh) is used to - get nsid (we may send rtnl request during listing on rth). - - Example: - $ ip netns list-id - nsid 0 (iproute2 netns name: foo) - $ ip monitor nsid - Deleted nsid 0 (iproute2 netns name: foo) - nsid 16 (iproute2 netns name: bar) - - Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> - -diff --git a/include/ll_map.h b/include/ll_map.h -index f1dda39..a9d9cb3 100644 ---- a/include/ll_map.h -+++ b/include/ll_map.h -@@ -10,5 +10,6 @@ extern const char *ll_index_to_name(unsigned idx); - extern const char *ll_idx_n2a(unsigned idx, char *buf); - extern int ll_index_to_type(unsigned idx); - extern unsigned ll_index_to_flags(unsigned idx); -+extern unsigned namehash(const char *str); - - #endif /* __LL_MAP_H__ */ -diff --git a/ip/ip_common.h b/ip/ip_common.h -index f9b4734..85529f0 100644 ---- a/ip/ip_common.h -+++ b/ip/ip_common.h -@@ -30,6 +30,9 @@ extern int print_rule(const struct sockaddr_nl *who, - struct nlmsghdr *n, void *arg); - extern int print_netconf(const struct sockaddr_nl *who, - struct nlmsghdr *n, void *arg); -+extern void netns_map_init(void); -+extern int print_nsid(const struct sockaddr_nl *who, -+ struct nlmsghdr *n, void *arg); - extern int do_ipaddr(int argc, char **argv); - extern int do_ipaddrlabel(int argc, char **argv); - extern int do_iproute(int argc, char **argv); -diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c -index 86c473e..148cf1e 100644 ---- a/ip/ipmonitor.c -+++ b/ip/ipmonitor.c -@@ -31,7 +31,7 @@ static void usage(void) - { - fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ]\n"); - fprintf(stderr, "LISTofOBJECTS := link | address | route | mroute | prefix |\n"); -- fprintf(stderr, " neigh | netconf\n"); -+ fprintf(stderr, " neigh | netconf | nsid\n"); - fprintf(stderr, "FILE := file FILENAME\n"); - exit(-1); - } -@@ -127,6 +127,12 @@ static int accept_msg(const struct sockaddr_nl *who, - n->nlmsg_type == RTM_NEWTFILTER || - n->nlmsg_type == RTM_DELTFILTER) - return 0; -+ if (n->nlmsg_type == RTM_NEWNSID || n->nlmsg_type == RTM_DELNSID) { -+ if (prefix_banner) -+ fprintf(fp, "[NSID]"); -+ print_nsid(who, n, arg); -+ return 0; -+ } - if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP && - n->nlmsg_type != NLMSG_DONE) { - fprintf(fp, "Unknown message: %08x %08x %08x\n", -@@ -146,6 +152,9 @@ int do_ipmonitor(int argc, char **argv) - int lprefix=0; - int lneigh=0; - int lnetconf=0; -+ int lnsid=0; -+ -+ groups |= nl_mgrp(RTNLGRP_NSID); - - rtnl_close(&rth); - ipaddr_reset_filter(1); -@@ -178,6 +187,9 @@ int do_ipmonitor(int argc, char **argv) - } else if (matches(*argv, "netconf") == 0) { - lnetconf = 1; - groups = 0; -+ } else if (matches(*argv, "nsid") == 0) { -+ lnsid = 1; -+ groups = 0; - } else if (strcmp(*argv, "all") == 0) { - groups = ~RTMGRP_TC; - prefix_banner=1; -@@ -223,6 +235,9 @@ int do_ipmonitor(int argc, char **argv) - if (!preferred_family || preferred_family == AF_INET6) - groups |= nl_mgrp(RTNLGRP_IPV6_NETCONF); - } -+ if (lnsid) { -+ groups |= nl_mgrp(RTNLGRP_NSID); -+ } - if (file) { - FILE *fp; - fp = fopen(file, "r"); -@@ -236,6 +251,7 @@ int do_ipmonitor(int argc, char **argv) - if (rtnl_open(&rth, groups) < 0) - exit(1); - ll_init_map(&rth); -+ netns_map_init(); - - if (rtnl_listen(&rth, accept_msg, stdout) < 0) - exit(2); -diff --git a/ip/ipnetns.c b/ip/ipnetns.c -index 24df167..438d59b 100644 ---- a/ip/ipnetns.c -+++ b/ip/ipnetns.c -@@ -14,10 +14,12 @@ - #include <errno.h> - #include <unistd.h> - #include <ctype.h> -+#include <linux/limits.h> - - #include <linux/net_namespace.h> - - #include "utils.h" -+#include "hlist.h" - #include "ip_common.h" - #include "namespace.h" - -@@ -31,9 +33,13 @@ static int usage(void) - fprintf(stderr, " ip netns pids NAME\n"); - fprintf(stderr, " ip [-all] netns exec [NAME] cmd ...\n"); - fprintf(stderr, " ip netns monitor\n"); -+ fprintf(stderr, " ip netns list-id\n"); - exit(-1); - } - -+/* This socket is used to get nsid */ -+static struct rtnl_handle rtnsh = { .fd = -1 }; -+ - static int have_rtnl_getnsid = -1; - - static int ipnetns_accept_msg(const struct sockaddr_nl *who, -@@ -106,7 +112,7 @@ static int get_netnsid_from_name(const char *name) - return fd; - - addattr32(&req.n, 1024, NETNSA_FD, fd); -- if (rtnl_talk(&rth, &req.n, 0, 0, &answer.n) < 0) { -+ if (rtnl_talk(&rtnsh, &req.n, 0, 0, &answer.n) < 0) { - close(fd); - return -2; - } -@@ -129,6 +135,196 @@ static int get_netnsid_from_name(const char *name) - return -1; - } - -+struct nsid_cache { -+ struct hlist_node nsid_hash; -+ struct hlist_node name_hash; -+ int nsid; -+ char name[NAME_MAX]; -+}; -+ -+#define NSIDMAP_SIZE 128 -+#define NSID_HASH_NSID(nsid) (nsid & (NSIDMAP_SIZE - 1)) -+#define NSID_HASH_NAME(name) (namehash(name) & (NSIDMAP_SIZE - 1)) -+ -+static struct hlist_head nsid_head[NSIDMAP_SIZE]; -+static struct hlist_head name_head[NSIDMAP_SIZE]; -+ -+static struct nsid_cache *netns_map_get_by_nsid(int nsid) -+{ -+ uint32_t h = NSID_HASH_NSID(nsid); -+ struct hlist_node *n; -+ -+ hlist_for_each(n, &nsid_head[h]) { -+ struct nsid_cache *c = container_of(n, struct nsid_cache, -+ nsid_hash); -+ if (c->nsid == nsid) -+ return c; -+ } -+ -+ return NULL; -+} -+ -+static int netns_map_add(int nsid, char *name) -+{ -+ struct nsid_cache *c; -+ uint32_t h; -+ -+ if (netns_map_get_by_nsid(nsid) != NULL) -+ return -EEXIST; -+ -+ c = malloc(sizeof(*c)); -+ if (c == NULL) { -+ perror("malloc"); -+ return -ENOMEM; -+ } -+ c->nsid = nsid; -+ strcpy(c->name, name); -+ -+ h = NSID_HASH_NSID(nsid); -+ hlist_add_head(&c->nsid_hash, &nsid_head[h]); -+ -+ h = NSID_HASH_NAME(name); -+ hlist_add_head(&c->name_hash, &name_head[h]); -+ -+ return 0; -+} -+ -+static void netns_map_del(struct nsid_cache *c) -+{ -+ hlist_del(&c->name_hash); -+ hlist_del(&c->nsid_hash); -+ free(c); -+} -+ -+void netns_map_init(void) -+{ -+ static int initialized; -+ struct dirent *entry; -+ DIR *dir; -+ int nsid; -+ -+ if (initialized || !ipnetns_have_nsid()) -+ return; -+ -+ if (rtnl_open(&rtnsh, 0) < 0) { -+ fprintf(stderr, "Cannot open rtnetlink\n"); -+ exit(1); -+ } -+ -+ dir = opendir(NETNS_RUN_DIR); -+ if (!dir) -+ return; -+ -+ while ((entry = readdir(dir)) != NULL) { -+ if (strcmp(entry->d_name, ".") == 0) -+ continue; -+ if (strcmp(entry->d_name, "..") == 0) -+ continue; -+ nsid = get_netnsid_from_name(entry->d_name); -+ -+ if (nsid >= 0) -+ netns_map_add(nsid, entry->d_name); -+ } -+ closedir(dir); -+ initialized = 1; -+} -+ -+static int netns_get_name(int nsid, char *name) -+{ -+ struct dirent *entry; -+ DIR *dir; -+ int id; -+ -+ dir = opendir(NETNS_RUN_DIR); -+ if (!dir) -+ return -ENOENT; -+ -+ while ((entry = readdir(dir)) != NULL) { -+ if (strcmp(entry->d_name, ".") == 0) -+ continue; -+ if (strcmp(entry->d_name, "..") == 0) -+ continue; -+ id = get_netnsid_from_name(entry->d_name); -+ -+ if (nsid == id) { -+ strcpy(name, entry->d_name); -+ closedir(dir); -+ return 0; -+ } -+ } -+ closedir(dir); -+ return -ENOENT; -+} -+ -+int print_nsid(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) -+{ -+ struct rtgenmsg *rthdr = NLMSG_DATA(n); -+ struct rtattr *tb[NETNSA_MAX+1]; -+ int len = n->nlmsg_len; -+ FILE *fp = (FILE *)arg; -+ struct nsid_cache *c; -+ char name[NAME_MAX]; -+ int nsid; -+ -+ if (n->nlmsg_type != RTM_NEWNSID && n->nlmsg_type != RTM_DELNSID) -+ return 0; -+ -+ len -= NLMSG_SPACE(sizeof(*rthdr)); -+ if (len < 0) { -+ fprintf(stderr, "BUG: wrong nlmsg len %d in %s\n", len, -+ __func__); -+ return -1; -+ } -+ -+ parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len); -+ if (tb[NETNSA_NSID] == NULL) { -+ fprintf(stderr, "BUG: NETNSA_NSID is missing %s\n", __func__); -+ return -1; -+ } -+ -+ if (n->nlmsg_type == RTM_DELNSID) -+ fprintf(fp, "Deleted "); -+ -+ nsid = rta_getattr_u32(tb[NETNSA_NSID]); -+ fprintf(fp, "nsid %u ", nsid); -+ -+ c = netns_map_get_by_nsid(nsid); -+ if (c != NULL) { -+ fprintf(fp, "(iproute2 netns name: %s)", c->name); -+ netns_map_del(c); -+ } -+ -+ /* During 'ip monitor nsid', no chance to have new nsid in cache. */ -+ if (c == NULL && n->nlmsg_type == RTM_NEWNSID) -+ if (netns_get_name(nsid, name) == 0) { -+ fprintf(fp, "(iproute2 netns name: %s)", name); -+ netns_map_add(nsid, name); -+ } -+ -+ fprintf(fp, "\n"); -+ fflush(fp); -+ return 0; -+} -+ -+static int netns_list_id(int argc, char **argv) -+{ -+ if (!ipnetns_have_nsid()) { -+ fprintf(stderr, -+ "RTM_GETNSID is not supported by the kernel.\n"); -+ return -ENOTSUP; -+ } -+ -+ if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETNSID) < 0) { -+ perror("Cannot send dump request"); -+ exit(1); -+ } -+ if (rtnl_dump_filter(&rth, print_nsid, stdout) < 0) { -+ fprintf(stderr, "Dump terminated\n"); -+ exit(1); -+ } -+ return 0; -+} -+ - static int netns_list(int argc, char **argv) - { - struct dirent *entry; -@@ -577,6 +773,8 @@ static int netns_monitor(int argc, char **argv) - - int do_netns(int argc, char **argv) - { -+ netns_map_init(); -+ - if (argc < 1) - return netns_list(0, NULL); - -@@ -584,6 +782,9 @@ int do_netns(int argc, char **argv) - (matches(*argv, "lst") == 0)) - return netns_list(argc-1, argv+1); - -+ if ((matches(*argv, "list-id") == 0)) -+ return netns_list_id(argc-1, argv+1); -+ - if (matches(*argv, "help") == 0) - return usage(); - -diff --git a/lib/ll_map.c b/lib/ll_map.c -index fd7db55..a57a150 100644 ---- a/lib/ll_map.c -+++ b/lib/ll_map.c -@@ -52,7 +52,7 @@ static struct ll_cache *ll_get_by_index(unsigned index) - return NULL; - } - --static unsigned namehash(const char *str) -+unsigned namehash(const char *str) - { - unsigned hash = 5381; - -diff --git a/man/man8/ip-monitor.8 b/man/man8/ip-monitor.8 -index b6e8d1d..a710b34 100644 ---- a/man/man8/ip-monitor.8 -+++ b/man/man8/ip-monitor.8 -@@ -32,7 +32,7 @@ command is the first in the command line and then the object list follows: - is the list of object types that we want to monitor. - It may contain - .BR link ", " address ", " route ", " mroute ", " prefix ", " --.BR neigh " and " netconf "." -+.BR neigh ", " netconf " and " nsid "." - If no - .B file - argument is given, -diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8 -index 80a4ad1..c9b0fbc 100644 ---- a/man/man8/ip-netns.8 -+++ b/man/man8/ip-netns.8 -@@ -42,6 +42,9 @@ ip-netns \- process network namespace management - .ti -8 - .BR "ip netns monitor" - -+.ti -8 -+.BR "ip netns list-id" -+ - .SH DESCRIPTION - A network namespace is logically another copy of the network stack, - with its own routes, firewall rules, and network devices. -@@ -178,6 +181,13 @@ executing. - This command watches network namespace name addition and deletion events - and prints a line for each event it sees. - -+.TP -+.B ip netns list-id - list network namespace ids (nsid) -+.sp -+Network namespace ids are used to identify a peer network namespace. This -+command displays nsid of the current network namespace and provides the -+corresponding iproute2 netns name (from /var/run/netns) if any. -+ - .SH EXAMPLES - .PP - ip netns list diff --git a/SOURCES/iproute2-example-cbq-service.patch b/SOURCES/iproute2-example-cbq-service.patch deleted file mode 100644 index f8b4978..0000000 --- a/SOURCES/iproute2-example-cbq-service.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff -up iproute2-20091106/examples/cbq.init-v0.7.3.fix iproute2-20091106/examples/cbq.init-v0.7.3 ---- iproute2-20091106/examples/cbq.init-v0.7.3.fix 2009-11-10 19:41:44.000000000 +0100 -+++ iproute2-20091106/examples/cbq.init-v0.7.3 2009-11-27 13:36:07.957310549 +0100 -@@ -579,14 +579,14 @@ cbq_show () { - ### Check configuration and load DEVICES, DEVFIELDS and CLASSLIST from $1 - cbq_init () { - ### Get a list of configured classes -- CLASSLIST=`find $1 \( -type f -or -type l \) -name 'cbq-*' \ -- -not -name '*~' -maxdepth 1 -printf "%f\n"| sort` -+ CLASSLIST=`find $1 -maxdepth 1 \( -type f -or -type l \) -name 'cbq-*' \ -+ -not -name '*~' -printf "%f\n"| sort` - [ -z "$CLASSLIST" ] && - cbq_failure "no configuration files found in $1!" - - ### Gather all DEVICE fields from $1/cbq-* -- DEVFIELDS=`find $1 \( -type f -or -type l \) -name 'cbq-*' \ -- -not -name '*~' -maxdepth 1| xargs sed -n 's/#.*//; \ -+ DEVFIELDS=`find $1 -maxdepth 1 \( -type f -or -type l \) -name 'cbq-*' \ -+ -not -name '*~' | xargs sed -n 's/#.*//; \ - s/[[:space:]]//g; /^DEVICE=[^,]*,[^,]*\(,[^,]*\)\?/ \ - { s/.*=//; p; }'| sort -u` - [ -z "$DEVFIELDS" ] && diff --git a/SOURCES/iproute2-ipaddress-fix-ipaddr_flush-for-Linux-3.1.patch b/SOURCES/iproute2-ipaddress-fix-ipaddr_flush-for-Linux-3.1.patch deleted file mode 100644 index fd108c8..0000000 --- a/SOURCES/iproute2-ipaddress-fix-ipaddr_flush-for-Linux-3.1.patch +++ /dev/null @@ -1,167 +0,0 @@ -From 1a47c83cc1e59314c318f29b7cec49a58c6d1af8 Mon Sep 17 00:00:00 2001 -From: Phil Sutter <psutter@redhat.com> -Date: Wed, 17 Feb 2016 14:03:59 +0100 -Subject: [PATCH] ipaddress: fix ipaddr_flush for Linux >= 3.1 - -This is a combination of 3 commits: - -commit 8e72880f6bfa39f439b9c4a88eb84b635b991687 -Author: Phil Sutter <phil@nwl.cc> -Date: Tue Nov 24 15:31:01 2015 +0100 - - libnetlink: introduce nc_flags - - Allow for a filter to ignore certain nlmsg_flags. - - Signed-off-by: Phil Sutter <phil@nwl.cc> - -commit c6995c48025233902a5b0c5fe88654e17ea934f6 -Author: Phil Sutter <phil@nwl.cc> -Date: Tue Nov 24 15:31:00 2015 +0100 - - ipaddress: simplify ipaddr_flush() - - Since it's no longer relevant whether an IP address is primary or - secondary when flushing, ipaddr_flush() can be simplified a bit. - - Signed-off-by: Phil Sutter <phil@nwl.cc> - -commit d25ec03e1dce4cf22093a9f7106e9401ab5bf066 -Author: Phil Sutter <phil@nwl.cc> -Date: Tue Nov 24 15:31:02 2015 +0100 - - ipaddress: fix ipaddr_flush for Linux >= 3.1 - - Linux version 3.1 introduced a consistency check for netlink dumps in - commit 670dc28 ("netlink: advertise incomplete dumps"). This bites - iproute2 when flushing more addresses than can fit into a single - RTM_GETADDR response. To silence the spurious error message "Dump was - interrupted and may be inconsistent.", advise rtnl_dump_filter_l() to - not care about NLM_F_DUMP_INTR. - - Signed-off-by: Phil Sutter <phil@nwl.cc> ---- - include/libnetlink.h | 8 ++++++-- - ip/ipaddress.c | 39 ++------------------------------------- - lib/libnetlink.c | 10 ++++++---- - 3 files changed, 14 insertions(+), 43 deletions(-) - -diff --git a/include/libnetlink.h b/include/libnetlink.h -index 95f41d979828f..b008b93f4e65e 100644 ---- a/include/libnetlink.h -+++ b/include/libnetlink.h -@@ -48,12 +48,16 @@ struct rtnl_dump_filter_arg - { - rtnl_filter_t filter; - void *arg1; -+ __u16 nc_flags; - }; - - extern int rtnl_dump_filter_l(struct rtnl_handle *rth, - const struct rtnl_dump_filter_arg *arg); --extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter, -- void *arg); -+int rtnl_dump_filter_nc(struct rtnl_handle *rth, -+ rtnl_filter_t filter, -+ void *arg, __u16 nc_flags); -+#define rtnl_dump_filter(rth, filter, arg) \ -+ rtnl_dump_filter_nc(rth, filter, arg, 0) - extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, - struct nlmsghdr *answer, size_t len); - extern int rtnl_send(struct rtnl_handle *rth, const void *buf, int); -diff --git a/ip/ipaddress.c b/ip/ipaddress.c -index 94ff53898a915..533c72c5b1c0f 100644 ---- a/ip/ipaddress.c -+++ b/ip/ipaddress.c -@@ -875,28 +875,6 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, - return 0; - } - --static int print_addrinfo_primary(const struct sockaddr_nl *who, -- struct nlmsghdr *n, void *arg) --{ -- struct ifaddrmsg *ifa = NLMSG_DATA(n); -- -- if (ifa->ifa_flags & IFA_F_SECONDARY) -- return 0; -- -- return print_addrinfo(who, n, arg); --} -- --static int print_addrinfo_secondary(const struct sockaddr_nl *who, -- struct nlmsghdr *n, void *arg) --{ -- struct ifaddrmsg *ifa = NLMSG_DATA(n); -- -- if (!(ifa->ifa_flags & IFA_F_SECONDARY)) -- return 0; -- -- return print_addrinfo(who, n, arg); --} -- - struct nlmsg_list - { - struct nlmsg_list *next; -@@ -1139,26 +1117,13 @@ static int ipaddr_flush(void) - filter.flushe = sizeof(flushb); - - while ((max_flush_loops == 0) || (round < max_flush_loops)) { -- const struct rtnl_dump_filter_arg a[3] = { -- { -- .filter = print_addrinfo_secondary, -- .arg1 = stdout, -- }, -- { -- .filter = print_addrinfo_primary, -- .arg1 = stdout, -- }, -- { -- .filter = NULL, -- .arg1 = NULL, -- }, -- }; - if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { - perror("Cannot send dump request"); - exit(1); - } - filter.flushed = 0; -- if (rtnl_dump_filter_l(&rth, a) < 0) { -+ if (rtnl_dump_filter_nc(&rth, print_addrinfo, -+ stdout, NLM_F_DUMP_INTR) < 0) { - fprintf(stderr, "Flush terminated\n"); - exit(1); - } -diff --git a/lib/libnetlink.c b/lib/libnetlink.c -index c455a41eccfdd..ebe3c120aa96b 100644 ---- a/lib/libnetlink.c -+++ b/lib/libnetlink.c -@@ -234,6 +234,8 @@ int rtnl_dump_filter_l(struct rtnl_handle *rth, - while (NLMSG_OK(h, msglen)) { - int err; - -+ h->nlmsg_flags &= ~a->nc_flags; -+ - if (nladdr.nl_pid != 0 || - h->nlmsg_pid != rth->local.nl_pid || - h->nlmsg_seq != rth->dump) -@@ -284,13 +286,13 @@ skip_it: - } - } - --int rtnl_dump_filter(struct rtnl_handle *rth, -+int rtnl_dump_filter_nc(struct rtnl_handle *rth, - rtnl_filter_t filter, -- void *arg1) -+ void *arg1, __u16 nc_flags) - { - const struct rtnl_dump_filter_arg a[2] = { -- { .filter = filter, .arg1 = arg1, }, -- { .filter = NULL, .arg1 = NULL, }, -+ { .filter = filter, .arg1 = arg1, .nc_flags = nc_flags, }, -+ { .filter = NULL, .arg1 = NULL, .nc_flags = 0, }, - }; - - return rtnl_dump_filter_l(rth, a); --- -2.8.2 - diff --git a/SOURCES/iproute2-libnetlink-add-size-argument-to-rtnl_talk.patch b/SOURCES/iproute2-libnetlink-add-size-argument-to-rtnl_talk.patch deleted file mode 100644 index a58eaf9..0000000 --- a/SOURCES/iproute2-libnetlink-add-size-argument-to-rtnl_talk.patch +++ /dev/null @@ -1,804 +0,0 @@ -From 59e3f63d49e544e62f6ff51786594dace8aa9175 Mon Sep 17 00:00:00 2001 -From: Phil Sutter <psutter@redhat.com> -Date: Thu, 11 Feb 2016 15:17:02 +0100 -Subject: [PATCH] libnetlink: add size argument to rtnl_talk - -This is a combination of 2 commits: - -commit c079e121a73af5eb49e003b13607e8a690331df6 -Author: Stephen Hemminger <shemming@brocade.com> -Date: Wed May 27 12:26:14 2015 -0700 - - libnetlink: add size argument to rtnl_talk - - There have been several instances where response from kernel - has overrun the stack buffer from the caller. Avoid future problems - by passing a size argument. - - Also drop the unused peer and group arguments to rtnl_talk. - -commit ed108cfc0260b6b751647982b77d6363b1defb15 -Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> -Date: Thu Dec 3 17:13:48 2015 +0100 - - libnetlink: don't confuse variables in rtnl_talk() - - There is two variables named 'len' in rtnl_talk. In fact, commit - c079e121a73a didn't work. For example, it was possible to trigger - a seg fault with this command: - $ ip link set gre2 type ip6gre hoplimit 32 - - Let's rename the argument len to maxlen. - - Fixes: c079e121a73a ("libnetlink: add size argument to rtnl_talk") - Reported-by: Thomas Faivre <thomas.faivre@6wind.com> - Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> ---- - bridge/fdb.c | 2 +- - bridge/link.c | 2 +- - bridge/mdb.c | 2 +- - bridge/vlan.c | 2 +- - genl/ctrl.c | 4 ++-- - include/libnetlink.h | 4 ++-- - ip/ipaddress.c | 4 ++-- - ip/ipaddrlabel.c | 4 ++-- - ip/ipl2tp.c | 8 ++++---- - ip/iplink.c | 4 ++-- - ip/ipneigh.c | 2 +- - ip/ipnetns.c | 4 ++-- - ip/ipntable.c | 2 +- - ip/iproute.c | 8 ++++---- - ip/iprule.c | 4 ++-- - ip/iptoken.c | 2 +- - ip/link_gre.c | 2 +- - ip/link_gre6.c | 2 +- - ip/link_ip6tnl.c | 2 +- - ip/link_iptnl.c | 2 +- - ip/link_vti.c | 2 +- - ip/link_vti6.c | 2 +- - ip/tcp_metrics.c | 4 ++-- - ip/xfrm_policy.c | 14 +++++++------- - ip/xfrm_state.c | 12 ++++++------ - lib/libgenl.c | 2 +- - lib/libnetlink.c | 40 ++++++++++++++++++++++------------------ - tc/m_action.c | 6 +++--- - tc/tc_class.c | 2 +- - tc/tc_filter.c | 2 +- - tc/tc_qdisc.c | 2 +- - 31 files changed, 79 insertions(+), 75 deletions(-) - -diff --git a/bridge/fdb.c b/bridge/fdb.c -index 615541e2cea2e..3c6c371c02552 100644 ---- a/bridge/fdb.c -+++ b/bridge/fdb.c -@@ -326,7 +326,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv) - return -1; - } - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - - return 0; -diff --git a/bridge/link.c b/bridge/link.c -index 38dfaea2e1808..19d06420aa818 100644 ---- a/bridge/link.c -+++ b/bridge/link.c -@@ -364,7 +364,7 @@ static int brlink_modify(int argc, char **argv) - addattr_nest_end(&req.n, nest); - } - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - - return 0; -diff --git a/bridge/mdb.c b/bridge/mdb.c -index 81d479b9a3407..1cd03e011ded0 100644 ---- a/bridge/mdb.c -+++ b/bridge/mdb.c -@@ -224,7 +224,7 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv) - - addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry)); - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - - return 0; -diff --git a/bridge/vlan.c b/bridge/vlan.c -index 83c40880f0425..54e10d0d94b22 100644 ---- a/bridge/vlan.c -+++ b/bridge/vlan.c -@@ -95,7 +95,7 @@ static int vlan_modify(int cmd, int argc, char **argv) - - addattr_nest_end(&req.n, afspec); - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - - return 0; -diff --git a/genl/ctrl.c b/genl/ctrl.c -index 48cbc3562ad8d..25968839a91b5 100644 ---- a/genl/ctrl.c -+++ b/genl/ctrl.c -@@ -67,7 +67,7 @@ int genl_ctrl_resolve_family(const char *family) - - addattr_l(nlh, 128, CTRL_ATTR_FAMILY_NAME, family, strlen(family) + 1); - -- if (rtnl_talk(&rth, nlh, 0, 0, nlh) < 0) { -+ if (rtnl_talk(&rth, nlh, nlh, sizeof(req)) < 0) { - fprintf(stderr, "Error talking to the kernel\n"); - goto errout; - } -@@ -341,7 +341,7 @@ static int ctrl_list(int cmd, int argc, char **argv) - goto ctrl_done; - } - -- if (rtnl_talk(&rth, nlh, 0, 0, nlh) < 0) { -+ if (rtnl_talk(&rth, nlh, nlh, sizeof(req)) < 0) { - fprintf(stderr, "Error talking to the kernel\n"); - goto ctrl_done; - } -diff --git a/include/libnetlink.h b/include/libnetlink.h -index ae933364761c1..95f41d979828f 100644 ---- a/include/libnetlink.h -+++ b/include/libnetlink.h -@@ -54,8 +54,8 @@ extern int rtnl_dump_filter_l(struct rtnl_handle *rth, - const struct rtnl_dump_filter_arg *arg); - extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter, - void *arg); --extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, -- unsigned groups, struct nlmsghdr *answer); -+extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, -+ struct nlmsghdr *answer, size_t len); - extern int rtnl_send(struct rtnl_handle *rth, const void *buf, int); - extern int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int); - -diff --git a/ip/ipaddress.c b/ip/ipaddress.c -index 30fda4f8b30ec..94ff53898a915 100644 ---- a/ip/ipaddress.c -+++ b/ip/ipaddress.c -@@ -1036,7 +1036,7 @@ static int restore_handler(const struct sockaddr_nl *nl, - - ll_init_map(&rth); - -- ret = rtnl_talk(&rth, n, 0, 0, n); -+ ret = rtnl_talk(&rth, n, n, sizeof(*n)); - if ((ret < 0) && (errno == EEXIST)) - ret = 0; - -@@ -1590,7 +1590,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv) - sizeof(cinfo)); - } - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - return -2; - - return 0; -diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c -index db4dc28df6d29..564bd4203ab3b 100644 ---- a/ip/ipaddrlabel.c -+++ b/ip/ipaddrlabel.c -@@ -182,7 +182,7 @@ static int ipaddrlabel_modify(int cmd, int argc, char **argv) - if (req.ifal.ifal_family == AF_UNSPEC) - req.ifal.ifal_family = AF_INET6; - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - return 2; - - return 0; -@@ -209,7 +209,7 @@ static int flush_addrlabel(const struct sockaddr_nl *who, struct nlmsghdr *n, vo - if (rtnl_open(&rth2, 0) < 0) - return -1; - -- if (rtnl_talk(&rth2, n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth2, n, NULL, 0) < 0) - return -2; - - rtnl_close(&rth2); -diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c -index 5cd863224fda0..2f7c9bf1c737f 100644 ---- a/ip/ipl2tp.c -+++ b/ip/ipl2tp.c -@@ -119,7 +119,7 @@ static int create_tunnel(struct l2tp_parm *p) - addattr16(&req.n, 1024, L2TP_ATTR_UDP_DPORT, p->peer_udp_port); - } - -- if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) - return -2; - - return 0; -@@ -132,7 +132,7 @@ static int delete_tunnel(struct l2tp_parm *p) - - addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id); - -- if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) - return -2; - - return 0; -@@ -166,7 +166,7 @@ static int create_session(struct l2tp_parm *p) - if (p->ifname && p->ifname[0]) - addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname); - -- if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) - return -2; - - return 0; -@@ -179,7 +179,7 @@ static int delete_session(struct l2tp_parm *p) - - addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id); - addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id); -- if (rtnl_talk(&genl_rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0) - return -2; - - return 0; -diff --git a/ip/iplink.c b/ip/iplink.c -index 86ea23e6beaf7..052f0474bc1c1 100644 ---- a/ip/iplink.c -+++ b/ip/iplink.c -@@ -605,7 +605,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) - - req.i.ifi_index = 0; - addattr32(&req.n, sizeof(req), IFLA_GROUP, group); -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - return 0; - } -@@ -680,7 +680,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv) - return -1; - } - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - - return 0; -diff --git a/ip/ipneigh.c b/ip/ipneigh.c -index d76e035c449c9..39a8b4b236e37 100644 ---- a/ip/ipneigh.c -+++ b/ip/ipneigh.c -@@ -174,7 +174,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv) - return -1; - } - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - - return 0; -diff --git a/ip/ipnetns.c b/ip/ipnetns.c -index 00b6cc488b3b5..2c848bc0f14b2 100644 ---- a/ip/ipnetns.c -+++ b/ip/ipnetns.c -@@ -113,7 +113,7 @@ static int get_netnsid_from_name(const char *name) - return fd; - - addattr32(&req.n, 1024, NETNSA_FD, fd); -- if (rtnl_talk(&rtnsh, &req.n, 0, 0, &answer.n) < 0) { -+ if (rtnl_talk(&rtnsh, &req.n, &answer.n, sizeof(answer)) < 0) { - close(fd); - return -2; - } -@@ -698,7 +698,7 @@ static int set_netnsid_from_name(const char *name, int nsid) - - addattr32(&req.n, 1024, NETNSA_FD, fd); - addattr32(&req.n, 1024, NETNSA_NSID, nsid); -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - err = -2; - - close(fd); -diff --git a/ip/ipntable.c b/ip/ipntable.c -index 4aeb71f7f4f89..b88c67b3fa9ab 100644 ---- a/ip/ipntable.c -+++ b/ip/ipntable.c -@@ -313,7 +313,7 @@ static int ipntable_modify(int cmd, int flags, int argc, char **argv) - RTA_PAYLOAD(parms_rta)); - } - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - - return 0; -diff --git a/ip/iproute.c b/ip/iproute.c -index 20980aba45bdc..4e63f3780237e 100644 ---- a/ip/iproute.c -+++ b/ip/iproute.c -@@ -1029,7 +1029,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv) - if (req.r.rtm_family == AF_UNSPEC) - req.r.rtm_family = AF_INET; - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - - return 0; -@@ -1486,7 +1486,7 @@ static int iproute_get(int argc, char **argv) - if (req.r.rtm_family == AF_UNSPEC) - req.r.rtm_family = AF_INET; - -- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) -+ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) - exit(2); - - if (connected && !from_ok) { -@@ -1527,7 +1527,7 @@ static int iproute_get(int argc, char **argv) - req.n.nlmsg_flags = NLM_F_REQUEST; - req.n.nlmsg_type = RTM_GETROUTE; - -- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) -+ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) - exit(2); - } - -@@ -1549,7 +1549,7 @@ static int restore_handler(const struct sockaddr_nl *nl, - - ll_init_map(&rth); - -- ret = rtnl_talk(&rth, n, 0, 0, n); -+ ret = rtnl_talk(&rth, n, n, sizeof(*n)); - if ((ret < 0) && (errno == EEXIST)) - ret = 0; - -diff --git a/ip/iprule.c b/ip/iprule.c -index 167e753bde7b2..475ddc424e46d 100644 ---- a/ip/iprule.c -+++ b/ip/iprule.c -@@ -355,7 +355,7 @@ static int iprule_modify(int cmd, int argc, char **argv) - if (!table_ok && cmd == RTM_NEWRULE) - req.r.rtm_table = RT_TABLE_MAIN; - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - return 2; - - return 0; -@@ -382,7 +382,7 @@ static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *a - if (rtnl_open(&rth2, 0) < 0) - return -1; - -- if (rtnl_talk(&rth2, n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth2, n, NULL, 0) < 0) - return -2; - - rtnl_close(&rth2); -diff --git a/ip/iptoken.c b/ip/iptoken.c -index 5689c2ece5816..0d265e6da8711 100644 ---- a/ip/iptoken.c -+++ b/ip/iptoken.c -@@ -182,7 +182,7 @@ static int iptoken_set(int argc, char **argv) - return -1; - } - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - return -2; - - return 0; -diff --git a/ip/link_gre.c b/ip/link_gre.c -index fda84d832f542..91ac299da1658 100644 ---- a/ip/link_gre.c -+++ b/ip/link_gre.c -@@ -72,7 +72,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, - req.i.ifi_family = preferred_family; - req.i.ifi_index = ifi->ifi_index; - -- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { -+ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { - get_failed: - fprintf(stderr, - "Failed to get existing tunnel info.\n"); -diff --git a/ip/link_gre6.c b/ip/link_gre6.c -index c7183e2fd4e75..d604f558df6ca 100644 ---- a/ip/link_gre6.c -+++ b/ip/link_gre6.c -@@ -86,7 +86,7 @@ static int gre_parse_opt(struct link_util *lu, int argc, char **argv, - req.i.ifi_family = preferred_family; - req.i.ifi_index = ifi->ifi_index; - -- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { -+ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { - get_failed: - fprintf(stderr, - "Failed to get existing tunnel info.\n"); -diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c -index f5b12454cf5f0..3efe2f4553203 100644 ---- a/ip/link_ip6tnl.c -+++ b/ip/link_ip6tnl.c -@@ -84,7 +84,7 @@ static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv, - req.i.ifi_family = preferred_family; - req.i.ifi_index = ifi->ifi_index; - -- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { -+ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { - get_failed: - fprintf(stderr, - "Failed to get existing tunnel info.\n"); -diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c -index 768c4efd4c26d..439c6e160b9ca 100644 ---- a/ip/link_iptnl.c -+++ b/ip/link_iptnl.c -@@ -76,7 +76,7 @@ static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv, - req.i.ifi_family = preferred_family; - req.i.ifi_index = ifi->ifi_index; - -- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { -+ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { - get_failed: - fprintf(stderr, - "Failed to get existing tunnel info.\n"); -diff --git a/ip/link_vti.c b/ip/link_vti.c -index 6274c836cb944..0c0f5ba770d75 100644 ---- a/ip/link_vti.c -+++ b/ip/link_vti.c -@@ -66,7 +66,7 @@ static int vti_parse_opt(struct link_util *lu, int argc, char **argv, - req.i.ifi_family = preferred_family; - req.i.ifi_index = ifi->ifi_index; - -- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { -+ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { - get_failed: - fprintf(stderr, - "Failed to get existing tunnel info.\n"); -diff --git a/ip/link_vti6.c b/ip/link_vti6.c -index 282896df917a0..c146f791abaaa 100644 ---- a/ip/link_vti6.c -+++ b/ip/link_vti6.c -@@ -67,7 +67,7 @@ static int vti6_parse_opt(struct link_util *lu, int argc, char **argv, - req.i.ifi_family = preferred_family; - req.i.ifi_index = ifi->ifi_index; - -- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { -+ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { - get_failed: - fprintf(stderr, - "Failed to get existing tunnel info.\n"); -diff --git a/ip/tcp_metrics.c b/ip/tcp_metrics.c -index c6be3c94415ff..8fa4b26a4965c 100644 ---- a/ip/tcp_metrics.c -+++ b/ip/tcp_metrics.c -@@ -386,10 +386,10 @@ static int tcpm_do_cmd(int cmd, int argc, char **argv) - } - - if (ack) { -- if (rtnl_talk(&grth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&grth, &req.n, NULL, 0) < 0) - return -2; - } else if (atype >= 0) { -- if (rtnl_talk(&grth, &req.n, 0, 0, &req.n) < 0) -+ if (rtnl_talk(&grth, &req.n, &req.n, sizeof(req)) < 0) - return -2; - if (process_msg(NULL, &req.n, stdout) < 0) { - fprintf(stderr, "Dump terminated\n"); -diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c -index a0a9ce14036be..5ff581a2b868b 100644 ---- a/ip/xfrm_policy.c -+++ b/ip/xfrm_policy.c -@@ -392,7 +392,7 @@ static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv) - if (req.xpinfo.sel.family == AF_UNSPEC) - req.xpinfo.sel.family = AF_INET; - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - - rtnl_close(&rth); -@@ -554,7 +554,7 @@ int xfrm_policy_print(const struct sockaddr_nl *who, struct nlmsghdr *n, - } - - static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, -- void *res_nlbuf) -+ void *res_nlbuf, size_t res_size) - { - struct rtnl_handle rth; - struct { -@@ -669,7 +669,7 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, - (void *)&ctx, ctx.sctx.len); - } - -- if (rtnl_talk(&rth, &req.n, 0, 0, res_nlbuf) < 0) -+ if (rtnl_talk(&rth, &req.n, res_nlbuf, res_size) < 0) - exit(2); - - rtnl_close(&rth); -@@ -679,7 +679,7 @@ static int xfrm_policy_get_or_delete(int argc, char **argv, int delete, - - static int xfrm_policy_delete(int argc, char **argv) - { -- return xfrm_policy_get_or_delete(argc, argv, 1, NULL); -+ return xfrm_policy_get_or_delete(argc, argv, 1, NULL, 0); - } - - static int xfrm_policy_get(int argc, char **argv) -@@ -689,7 +689,7 @@ static int xfrm_policy_get(int argc, char **argv) - - memset(buf, 0, sizeof(buf)); - -- xfrm_policy_get_or_delete(argc, argv, 0, n); -+ xfrm_policy_get_or_delete(argc, argv, 0, n, sizeof(buf)); - - if (xfrm_policy_print(NULL, n, (void*)stdout) < 0) { - fprintf(stderr, "An error :-)\n"); -@@ -974,7 +974,7 @@ static int xfrm_spd_getinfo(int argc, char **argv) - if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) - exit(1); - -- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) -+ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) - exit(2); - - print_spdinfo(&req.n, (void*)stdout); -@@ -1026,7 +1026,7 @@ static int xfrm_policy_flush(int argc, char **argv) - if (show_stats > 1) - fprintf(stderr, "Flush policy\n"); - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - - rtnl_close(&rth); -diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c -index dc6993ef26ca9..68884af14772e 100644 ---- a/ip/xfrm_state.c -+++ b/ip/xfrm_state.c -@@ -647,7 +647,7 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) - if (req.xsinfo.family == AF_UNSPEC) - req.xsinfo.family = AF_INET; - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - - rtnl_close(&rth); -@@ -784,7 +784,7 @@ static int xfrm_state_allocspi(int argc, char **argv) - req.xspi.info.family = AF_INET; - - -- if (rtnl_talk(&rth, &req.n, 0, 0, res_n) < 0) -+ if (rtnl_talk(&rth, &req.n, res_n, sizeof(res_buf)) < 0) - exit(2); - - if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) { -@@ -974,7 +974,7 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete) - req.xsid.family = AF_INET; - - if (delete) { -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - } else { - char buf[NLMSG_BUF_SIZE]; -@@ -982,7 +982,7 @@ static int xfrm_state_get_or_delete(int argc, char **argv, int delete) - - memset(buf, 0, sizeof(buf)); - -- if (rtnl_talk(&rth, &req.n, 0, 0, res_n) < 0) -+ if (rtnl_talk(&rth, &req.n, res_n, sizeof(req)) < 0) - exit(2); - - if (xfrm_state_print(NULL, res_n, (void*)stdout) < 0) { -@@ -1223,7 +1223,7 @@ static int xfrm_sad_getinfo(int argc, char **argv) - if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) - exit(1); - -- if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) -+ if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) - exit(2); - - print_sadinfo(&req.n, (void*)stdout); -@@ -1277,7 +1277,7 @@ static int xfrm_state_flush(int argc, char **argv) - fprintf(stderr, "Flush state with XFRM-PROTO value \"%s\"\n", - strxf_xfrmproto(req.xsf.proto)); - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - exit(2); - - rtnl_close(&rth); -diff --git a/lib/libgenl.c b/lib/libgenl.c -index ef3e5db60c8cb..acb1478389476 100644 ---- a/lib/libgenl.c -+++ b/lib/libgenl.c -@@ -53,7 +53,7 @@ int genl_resolve_family(struct rtnl_handle *grth, const char *family) - addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME, - family, strlen(family) + 1); - -- if (rtnl_talk(grth, &req.n, 0, 0, &req.n) < 0) { -+ if (rtnl_talk(grth, &req.n, &req.n, sizeof(req)) < 0) { - fprintf(stderr, "Error talking to the kernel\n"); - return -2; - } -diff --git a/lib/libnetlink.c b/lib/libnetlink.c -index 0a989f46fa519..c455a41eccfdd 100644 ---- a/lib/libnetlink.c -+++ b/lib/libnetlink.c -@@ -29,6 +29,10 @@ - #define SOL_NETLINK 270 - #endif - -+#ifndef MIN -+#define MIN(a, b) ((a) < (b) ? (a) : (b)) -+#endif -+ - int rcvbuf = 1024 * 1024; - - void rtnl_close(struct rtnl_handle *rth) -@@ -292,8 +296,8 @@ int rtnl_dump_filter(struct rtnl_handle *rth, - return rtnl_dump_filter_l(rth, a); - } - --int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, -- unsigned groups, struct nlmsghdr *answer) -+int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, -+ struct nlmsghdr *answer, size_t maxlen) - { - int status; - unsigned seq; -@@ -309,12 +313,10 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, - .msg_iov = &iov, - .msg_iovlen = 1, - }; -- char buf[16384]; -+ char buf[32768]; - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; -- nladdr.nl_pid = peer; -- nladdr.nl_groups = groups; - - n->nlmsg_seq = seq = ++rtnl->seq; - -@@ -322,7 +324,6 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, - n->nlmsg_flags |= NLM_F_ACK; - - status = sendmsg(rtnl->fd, &msg, 0); -- - if (status < 0) { - perror("Cannot talk to rtnetlink"); - return -1; -@@ -331,7 +332,6 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, - memset(buf,0,sizeof(buf)); - - iov.iov_base = buf; -- - while (1) { - iov.iov_len = sizeof(buf); - status = recvmsg(rtnl->fd, &msg, 0); -@@ -364,7 +364,7 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, - exit(1); - } - -- if (nladdr.nl_pid != peer || -+ if (nladdr.nl_pid != 0 || - h->nlmsg_pid != rtnl->local.nl_pid || - h->nlmsg_seq != seq) { - /* Don't forget to skip that message. */ -@@ -377,20 +377,22 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, - struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); - if (l < sizeof(struct nlmsgerr)) { - fprintf(stderr, "ERROR truncated\n"); -- } else { -- if (!err->error) { -- if (answer) -- memcpy(answer, h, h->nlmsg_len); -- return 0; -- } -- -- fprintf(stderr, "RTNETLINK answers: %s\n", strerror(-err->error)); -- errno = -err->error; -+ } else if (!err->error) { -+ if (answer) -+ memcpy(answer, h, -+ MIN(maxlen, h->nlmsg_len)); -+ return 0; - } -+ -+ fprintf(stderr, "RTNETLINK answers: %s\n", -+ strerror(-err->error)); -+ errno = -err->error; - return -1; - } -+ - if (answer) { -- memcpy(answer, h, h->nlmsg_len); -+ memcpy(answer, h, -+ MIN(maxlen, h->nlmsg_len)); - return 0; - } - -@@ -399,10 +401,12 @@ int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, - status -= NLMSG_ALIGN(len); - h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); - } -+ - if (msg.msg_flags & MSG_TRUNC) { - fprintf(stderr, "Message truncated\n"); - continue; - } -+ - if (status) { - fprintf(stderr, "!!!Remnant of size %d\n", status); - exit(1); -diff --git a/tc/m_action.c b/tc/m_action.c -index 4acabef056db1..7cbf37740c3ba 100644 ---- a/tc/m_action.c -+++ b/tc/m_action.c -@@ -451,7 +451,7 @@ static int tc_action_gd(int cmd, unsigned flags, int *argc_p, char ***argv_p) - if (cmd == RTM_GETACTION) - ans = &req.n; - -- if (rtnl_talk(&rth, &req.n, 0, 0, ans) < 0) { -+ if (rtnl_talk(&rth, &req.n, ans, MAX_MSG) < 0) { - fprintf(stderr, "We have an error talking to the kernel\n"); - return 1; - } -@@ -496,7 +496,7 @@ static int tc_action_modify(int cmd, unsigned flags, int *argc_p, char ***argv_p - } - tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail; - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) { -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) { - fprintf(stderr, "We have an error talking to the kernel\n"); - ret = -1; - } -@@ -566,7 +566,7 @@ static int tc_act_list_or_flush(int argc, char **argv, int event) - req.n.nlmsg_type = RTM_DELACTION; - req.n.nlmsg_flags |= NLM_F_ROOT; - req.n.nlmsg_flags |= NLM_F_REQUEST; -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) { -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) { - fprintf(stderr, "We have an error flushing\n"); - return 1; - } -diff --git a/tc/tc_class.c b/tc/tc_class.c -index 6c0850d09f874..8f6908b85a956 100644 ---- a/tc/tc_class.c -+++ b/tc/tc_class.c -@@ -138,7 +138,7 @@ static int tc_class_modify(int cmd, unsigned flags, int argc, char **argv) - } - } - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - return 2; - - return 0; -diff --git a/tc/tc_filter.c b/tc/tc_filter.c -index c3f2d5fa863e9..de1a73f470773 100644 ---- a/tc/tc_filter.c -+++ b/tc/tc_filter.c -@@ -167,7 +167,7 @@ static int tc_filter_modify(int cmd, unsigned flags, int argc, char **argv) - } - } - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) { -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) { - fprintf(stderr, "We have an error talking to the kernel\n"); - return 2; - } -diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c -index e304858044cbb..984f1359a40e0 100644 ---- a/tc/tc_qdisc.c -+++ b/tc/tc_qdisc.c -@@ -187,7 +187,7 @@ static int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv) - req.t.tcm_ifindex = idx; - } - -- if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) -+ if (rtnl_talk(&rth, &req.n, NULL, 0) < 0) - return 2; - - return 0; --- -2.6.4 - diff --git a/SOURCES/man-pages.patch b/SOURCES/man-pages.patch deleted file mode 100644 index be91cf3..0000000 --- a/SOURCES/man-pages.patch +++ /dev/null @@ -1,173 +0,0 @@ -diff --git a/man/man8/cbq.8 b/man/man8/cbq.8 -new file mode 100644 -index 0000000..78940b6 ---- /dev/null -+++ b/man/man8/cbq.8 -@@ -0,0 +1 @@ -+.so man8/tc-cbq.8 -\ No newline at end of file -diff --git a/man/man8/genl.8 b/man/man8/genl.8 -new file mode 100644 -index 0000000..b3e8f98 ---- /dev/null -+++ b/man/man8/genl.8 -@@ -0,0 +1,36 @@ -+.TH GENL 8 -+.SH NAME -+genl \- generic netlink utility frontend -+.SH SYNOPSIS -+.B genl -+.RI [ options ] { ctrl } [ help ] -+.SH DESCRIPTION -+This manual page documents briefly the -+.B genl -+command. -+.PP -+\fBgenl\fP utility provides a simple frontend to the generic netlink library. -+.SH OPTIONS -+genl supports the following options. -+.TP -+.B \-h, \-help -+Show summary of options. -+.TP -+.B \-V, \-Version -+Show version of program. -+.TP -+.B \-s, \-stats, \-statistics -+Show object statistics. -+.TP -+.B \-d, \-details -+Show object details. -+.TP -+.B \-r, \-raw -+Dump raw output only. -+.SH SEE ALSO -+.BR ip (8) -+.br -+.SH AUTHOR -+genl was written by Jamal Hadi Salim <hadi@cyberus.ca>. -+.PP -+This manual page was written by Petr Sabata <contyk@redhat.com>. -diff --git a/man/man8/ifcfg.8 b/man/man8/ifcfg.8 -new file mode 100644 -index 0000000..a6b585e ---- /dev/null -+++ b/man/man8/ifcfg.8 -@@ -0,0 +1,57 @@ -+.TH IFCFG 8 "September 24 2009" "iproute2" "Linux" -+.SH NAME -+ifcfg \- simplistic script which replaces ifconfig IP managment -+.SH SYNOPSIS -+.ad l -+.in +8 -+.ti -8 -+.B ifcfg -+.RI "[ " DEVICE " [ " :ALIAS: " ] ] [ " command " ] " ADDRESS " [ " LENGTH " ] [ " PEER " ] " -+.sp -+ -+.SH DESCRIPTION -+This manual page documents briefly the -+.B ifcfg -+command. -+.PP -+This is a simplistic script replacing one option of -+.B ifconfig -+, namely, IP address management. It not only adds -+addresses, but also carries out Duplicate Address Detection RFC-DHCP, -+sends unsolicited ARP to update the caches of other hosts sharing -+the interface, adds some control routes and restarts Router Discovery -+when it is necessary. -+ -+I strongly recommend using it -+.RI instead -+of -+.RI ifconfig -+both on hosts and on routers. -+ -+.SH IFCONFIG - COMMAND SYNTAX -+ -+.SS -+.TP -+.B DEVICE -+- it may have alias, suffix, separated by colon. -+ -+.TP -+.B command -+- add, delete or stop. -+ -+.TP -+.B address -+- optionally followed by prefix length. -+ -+.TP -+.B peer -+- optional peer address for pointpoint interfaces. -+ -+.SH EXAMPLE -+.nf ifcfg eth0 193.233.7.90/24 -+.fi -+This function determines, whether this is router or host. -+It returns 0, if the host is apparently not router. -+ -+.SH SEE ALSO -+.BR ip-cref.dvi -diff --git a/man/man8/ifstat.8 b/man/man8/ifstat.8 -new file mode 100644 -index 0000000..042dd3e ---- /dev/null -+++ b/man/man8/ifstat.8 -@@ -0,0 +1,54 @@ -+.TH IFSTAST 8 -+.SH NAME -+ifstat \- handy utility to read net interface statistics -+.SH SYNOPSIS -+.B ifstat -+.RI [ options ] -+.RI [ interface -+.RI [ interface -+.RI [ ... ] ] ] -+.SH DESCRIPTION -+This manual page documents briefly the -+.B ifstat -+command. -+.PP -+\fBifstat\fP neatly prints out network interface statistics. -+The utility keeps records of the previous data displayed in history files and by default only shows difference between the last and the current call. Location of the history files defaults to /tmp/.ifstat.u$UID but may be overridden with the IFSTAT_HISTORY environment variable. -+.SH OPTIONS -+.TP -+.B \-h, \-\-help -+Show summary of options. -+.TP -+.B \-V, \-\-version -+Show version of program. -+.TP -+.B \-a, \-\-ignore -+Ignore the history file. -+.TP -+.B \-d, \-\-scan=SECS -+Sample statistics every SECS second. -+.TP -+.B \-e, \-\-errors -+Show errors. -+.TP -+.B \-n, \-\-nooutput -+Don't display any output. Update the history file only. -+.TP -+.B \-r, \-\-reset -+Reset history. -+.TP -+.B \-s, \-\-noupdate -+Don't update the history file. -+.TP -+.B \-t, \-\-interval=SECS -+Report average over the last SECS seconds. -+.TP -+.B \-z, \-\-zeros -+Show entries with zero activity. -+.SH SEE ALSO -+.BR ip (8) -+.br -+.SH AUTHOR -+ifstat was written by Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>. -+.PP -+This manual page was written by Petr Sabata <contyk@redhat.com>. diff --git a/SPECS/iproute.spec b/SPECS/iproute.spec index f4a8243..bc6fdd1 100644 --- a/SPECS/iproute.spec +++ b/SPECS/iproute.spec @@ -1,135 +1,266 @@ %global cbq_version v0.7.3 + +%define rpmversion 3.10.0 +%define baserelease 55.el7 +%define specrelease 74%{?dist} +%define pkg_release %{specrelease}%{?buildid} + Summary: Advanced IP routing and network device configuration tools Name: iproute -Version: 3.10.0 -Release: 54%{?dist}.1 +Version: %{rpmversion} +Release: %{pkg_release} Group: Applications/System URL: http://kernel.org/pub/linux/utils/net/%{name}2/ -Source0: http://kernel.org/pub/linux/utils/net/%{name}2/%{name}2-%{version}.tar.gz +Source0: %{name}-%{rpmversion}-%{baserelease}.tar.xz Source1: cbq-0000.example Source2: avpkt -Patch0: man-pages.patch -Patch1: iproute2-3.4.0-kernel.patch -Patch2: iproute2-3.8.0-optflags.patch -Patch3: iproute2-3.9.0-IPPROTO_IP_for_SA.patch -Patch4: iproute2-example-cbq-service.patch -Patch5: iproute2-2.6.35-print-route.patch -Patch6: iproute2-2.6.39-create-peer-veth-without-a-name.patch -Patch7: iproute2-2.6.39-lnstat-dump-to-stdout.patch -Patch8: iproute2-3.8.0-unused-result.patch -Patch9: iproute2-3.10.0-xfrm-state-overflow.patch -# rhbz#977844 -Patch10: iproute2-3.11.0-tc-ok.patch -# rhbz#1024426 -Patch13: iproute2-3.10.0-lnstat-interval.patch -# rhbz#1032501 -Patch17: iproute2-3.10.0-rtt.patch -# rhbz#1034049 -Patch25: iproute2-3.16.0-addrlabel.patch -# rhbz#1091010 -Patch26: iproute2-3.16.0-quickack.patch -# rhbz#1044535 -Patch27: iproute2-3.16.0-bpf.patch -# Backport linux headers -# -# * git diff v3.10.0..v4.0.0-26-g94f6653 include/linux -# * minor adaptation ip/xfrm_monitor.c -# -# Note: This is useful to avoid having to patch individual kernel header files. -Patch28: iproute2-3.10.0-linux.patch -# Backport selected library functions -Patch29: iproute2-3.10.0-lib.patch -# Backport 'ss' command from 4.0.0 -# -# https://bugzilla.redhat.com/show_bug.cgi?id=1215006 -Patch30: iproute2-3.10.0-ss.patch -# Fix "ip -s xfrm state" segfault -# -# https://bugzilla.redhat.com/show_bug.cgi?id=1139173 -Patch31: iproute2-3.10.0-1139173.patch -# Option to operate on different namespace -# -# https://bugzilla.redhat.com/show_bug.cgi?id=1131928 -Patch32: iproute2-3.10.0-tc.patch -# Backport selected bridge features and documentation -# -# https://bugzilla.redhat.com/show_bug.cgi?id=1131928 -# https://bugzilla.redhat.com//show_bug.cgi?id=1009860 -# https://bugzilla.redhat.com//show_bug.cgi?id=1011818 -# https://bugzilla.redhat.com//show_bug.cgi?id=1024697 -# https://bugzilla.redhat.com//show_bug.cgi?id=1024697 -Patch33: iproute2-3.10.0-bridge.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1212026 -Patch35: iproute2-3.10.0-xfrm.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1198489 -Patch37: iproute2-3.10.0-route.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1219280 -Patch38: 0025-Consolidated-tunnel-support-fixes-for-ip6-gre-and-ip.patch -# Backport selected ip-link and ip-address features -# -# https://bugzilla.redhat.com/show_bug.cgi?id=1040454 -# https://bugzilla.redhat.com/show_bug.cgi?id=1017228 -# https://bugzilla.redhat.com/show_bug.cgi?id=1039855 -# https://bugzilla.redhat.com/show_bug.cgi?id=1061593 -# https://bugzilla.redhat.com/show_bug.cgi?id=1067437 -# https://bugzilla.redhat.com/show_bug.cgi?id=1119180 -# https://bugzilla.redhat.com/show_bug.cgi?id=1198456 -# https://bugzilla.redhat.com/show_bug.cgi?id=1203646 -# https://bugzilla.redhat.com/show_bug.cgi?id=1218568 -# -# Note: It proved very impractical to keep the patches -# separate when importing new upstream features to -# rhel-7.2 and therefore we are using a large patch -# instead. -Patch39: iproute2-3.10.0-address.patch -# Backport selected ip-netns features -# -# https://bugzilla.redhat.com/show_bug.cgi?id=1213869 -Patch40: iproute2-3.10.0-netns.patch -# Backport post-4.0.0 netns patch -Patch41: iproute2-4.0.0-netns.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1169874 -Patch42: iproute2-3.10.0-ip-rule.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1247315 -Patch43: iproute2-3.10.0-backport-additional-INET_DIAG-flags-in-inet_diag.h.patch -Patch44: iproute2-3.10.0-ss-print-value-of-IPV6_V6ONLY-socket-option-if-set.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1241486 -Patch45: iproute2-3.10.0-pkt_sched-fq-Fair-Queue-packet-scheduler.patch -Patch46: iproute2-3.10.0-fq-allow-options-of-fair-queue-set-to-0U.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1244851 -Patch47: iproute2-3.10.0-fix-ip-tunnel-command-for-vti-tunnels-with-io-key-gi.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1155116 -Patch48: iproute2-3.10.0-man-ip-Add-missing-details-option.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1251451 -Patch49: iproute2-3.10.0-Fix-changing-tunnel-remote-and-local-address-to-any.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1213869 -Patch50: iproute2-3.10.0-ip-xfrm-monitor-allows-to-monitor-in-several-netns.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1215006 -Patch51: iproute2-3.10.0-misc-ss-don-t-imply-a-when-A-was-specified.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1251070 -Patch52: iproute2-3.10.0-Fix-multiple-programming-errors.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1198456 -Patch53: iproute2-3.10.0-ip-link-fix-minor-typo-in-manpage.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1210402 -# https://bugzilla.redhat.com/show_bug.cgi?id=1213869 -Patch54: iproute2-3.10.0-ip-link-fix-and-extend-documentation.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1254095 -Patch55: iproute2-3.10.0-bridge-Add-master-device-name-to-bridge-fdb-show.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1255316 -Patch56: iproute2-3.10.0-tc-fix-for-qdiscs-without-options.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1212026 -Patch57: iproute2-3.10.0-Revert-Changes-for-BZ-1212026.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1241486 -Patch58: iproute-3.10.0-man-tc.8-mention-Fair-Queue-scheduler.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1327582 -Patch59: iproute2-libnetlink-add-size-argument-to-rtnl_talk.patch -Patch60: iproute2-ipaddress-fix-ipaddr_flush-for-Linux-3.1.patch - +Patch0: 0001-man-lnstat-rewrite-manpage.patch +Patch1: 0002-lnstat-fix-header-displaying-mechanism.patch +Patch2: 0003-iproute2-Ignore-EADDRNOTAVAIL-errors-during-address-.patch +Patch3: 0004-libnetlink-introduce-nc_flags.patch +Patch4: 0005-ipaddress-simplify-ipaddr_flush.patch +Patch5: 0006-ipaddress-fix-ipaddr_flush-for-Linux-3.1.patch +Patch6: 0007-bridge-drop-reference-to-unused-option-embedded-from.patch +Patch7: 0008-bridge-drop-man-page-fragment.patch +Patch8: 0009-bridge-fdb-add-use-option-to-set-NTF_USE-flag-in-fdb.patch +Patch9: 0010-ip-allow-ip-address-show-to-list-addresses-with-cert.patch +Patch10: 0011-ip-extend-ip-address-man-page-to-reflect-the-recent-.patch +Patch11: 0012-ip-address-fix-and-extend-documentation.patch +Patch12: 0013-ip-address.8.in-fix-BNF-syntax-error.patch +Patch13: 0014-man-ip-address-align-synopsis-with-help-output.patch +Patch14: 0015-man-ip-address-document-mngtmpaddr-and-noprefixroute.patch +Patch15: 0016-ss-return-1-if-an-unrecognized-option-was-given.patch +Patch16: 0017-ss-add-support-for-bytes_acked-bytes_received.patch +Patch17: 0018-ss-add-support-for-segs_in-and-segs_out.patch +Patch18: 0019-ip-address-fix-oneline-mode-for-interfaces-with-VF.patch +Patch19: 0020-neighbor-check-return-values.patch +Patch20: 0021-gre-raising-the-size-of-the-buffer-holding-nl-messag.patch +Patch21: 0022-Allow-specifying-bridge-port-STP-state-by-name-rathe.patch +Patch22: 0023-fix-ip-force-batch-to-continue-on-errors.patch +Patch23: 0024-ip-fix-exit-code-for-addrlabel.patch +Patch24: 0025-link-dump-filter.patch +Patch25: 0026-ip-return-correct-exit-code-on-route-failure.patch +Patch26: 0027-ip-fix-exit-code-for-rule-failures.patch +Patch27: 0028-libnetlink-add-size-argument-to-rtnl_talk.patch +Patch28: 0029-libnetlink-don-t-confuse-variables-in-rtnl_talk.patch +Patch29: 0030-man-ss-Fix-explanation-when-no-options-specified.patch +Patch30: 0031-iproute-restrict-hoplimit-values-to-be-in-range-0-25.patch +Patch31: 0032-iproute2-ip-route.8.in-minor-fixes.patch +Patch32: 0033-ip-route-enable-per-route-ecn-settings-via-features-.patch +Patch33: 0034-ip-route-add-congestion-control-metric.patch +Patch34: 0035-ip-link-remove-warning-message.patch +Patch35: 0036-route-ignore-RTAX_HOPLIMIT-of-value-1.patch +Patch36: 0037-route-Fix-printing-of-locked-entries.patch +Patch37: 0038-man-tc-add-man-page-for-fq-pacer.patch +Patch38: 0039-man-fix-whatis-for-fq.patch +Patch39: 0040-batch-support-quoted-strings.patch +Patch40: 0041-tc-add-a-man-page-for-basic-filter.patch +Patch41: 0042-tc-add-a-man-page-for-cgroup-filter.patch +Patch42: 0043-tc-add-a-man-page-for-flow-filter.patch +Patch43: 0044-tc-add-a-man-page-for-fw-filter.patch +Patch44: 0045-tc-add-a-man-page-for-route-filter.patch +Patch45: 0046-tc-add-a-man-page-for-tcindex-filter.patch +Patch46: 0047-tc-add-a-man-page-for-u32-filter.patch +Patch47: 0048-tc-ship-filter-man-pages-and-refer-to-them-in-tc.8.patch +Patch48: 0049-xfrm-add-command-for-configuring-SPD-hash-table.patch +Patch49: 0050-xfrm-revise-man-page-and-document-ip-xfrm-policy-set.patch +Patch50: 0051-iplink-update-available-type-list.patch +Patch51: 0052-iplink-add-support-for-bonding-netlink.patch +Patch52: 0053-iproute2-finish-support-for-bonding-attributes.patch +Patch53: 0054-introduce-support-for-slave-info-data.patch +Patch54: 0055-iplink-add-support-for-bonding-slave.patch +Patch55: 0056-iplink_bond-fix-arp_all_targets-parameter-name-in-ou.patch +Patch56: 0057-iplink_bond-fix-parameter-value-matching.patch +Patch57: 0058-iplink_bond_slave-show-mii_status-only-once.patch +Patch58: 0059-iplink-can-fix-help-text-and-man-page.patch +Patch59: 0060-ip-add-nlmon-as-a-device-type-to-help-message.patch +Patch60: 0061-iproute2-allow-to-change-slave-options-via-type_slav.patch +Patch61: 0062-add-help-command-to-bonding-master.patch +Patch62: 0063-ip-link-Shortify-printing-the-usage-of-link-type.patch +Patch63: 0064-iplink_bond-add-support-for-ad_actor-and-port_key-op.patch +Patch64: 0065-bonding-export-3ad-actor-and-partner-port-state.patch +Patch65: 0066-iplink-bonding-add-support-for-IFLA_BOND_TLB_DYNAMIC.patch +Patch66: 0067-bond-fix-return-after-invarg.patch +Patch67: 0068-ip-link-missing-options-in-bond-usage.patch +Patch68: 0069-ip-remove-extra-newlines-at-end-of-file.patch +Patch69: 0070-iplink-bond_slave-fix-ad_actor-partner_oper_port_sta.patch +Patch70: 0071-add-bridge_slave-device-support.patch +Patch71: 0072-add-bridge-master-device-support.patch +Patch72: 0073-iplink_bridge-add-support-for-ageing_time.patch +Patch73: 0074-iplink_bridge-add-support-for-stp_state.patch +Patch74: 0075-iplink_bridge-add-support-for-priority.patch +Patch75: 0076-iplink-use-the-short-format-to-print-help-info.patch +Patch76: 0077-iplink-shortify-printing-the-usage-of-link-type.patch +Patch77: 0078-iplink-add-ageing_time-stp_state-and-priority-for-br.patch +Patch78: 0079-ip-link-consolidate-macvlan-and-macvtap.patch +Patch79: 0080-ip-macvlan-support-MACVLAN_FLAG_NOPROMISC-flag.patch +Patch80: 0081-iproute2-ip6gre-update-man-pages.patch +Patch81: 0082-iproute-Descriptions-of-fou-and-gue-options-in-ip-li.patch +Patch82: 0083-ip-link-Document-IPoIB-link-type-in-the-man-page.patch +Patch83: 0084-iproute2-ip-link.8.in-Spelling-fixes.patch +Patch84: 0085-man-ip-link-Add-missing-link-types-vti-ipvlan-nlmon.patch +Patch85: 0086-man-ip-link-fix-a-typo.patch +Patch86: 0087-man-ip-link-document-MACVLAN-MACVTAP-interface-types.patch +Patch87: 0088-iplink-macvtap-fix-man-page.patch +Patch88: 0089-iprule-Align-help-text-with-man-page-synopsis.patch +Patch89: 0090-ipl2tp-Print-help-even-on-systems-without-l2tp-suppo.patch +Patch90: 0091-ip-align-help-text-with-manpage.patch +Patch91: 0092-ipaddrlabel-Improve-help-text-precision.patch +Patch92: 0093-iplink-fix-help-text-syntax.patch +Patch93: 0094-ipneigh-add-missing-proxy-keyword-to-help-text.patch +Patch94: 0095-ipntable-Fix-typo-in-help-text.patch +Patch95: 0096-iproute-TYPE-keyword-is-not-optional-fix-help-text-a.patch +Patch96: 0097-iprule-add-missing-nat-keyword-to-help-text.patch +Patch97: 0098-man-ip-address.8-Minor-syntax-fixes.patch +Patch98: 0099-man-ip-link.8-minor-font-fix.patch +Patch99: 0100-man-ip-link.8-Fix-and-improve-synopsis.patch +Patch100: 0101-man-ip-neighbour-Fix-for-missing-NUD_STATE-descripti.patch +Patch101: 0102-man-ip-netns.8-Clarify-synopsis-a-bit.patch +Patch102: 0103-man-ip-ntable.8-Review-synopsis-section.patch +Patch103: 0104-man-ip-rule.8-Review-synopsis-section.patch +Patch104: 0105-man-ip-token.8-Review-synopsis-section.patch +Patch105: 0106-add-vti-vti6-tunnel-modes-to-ip-tunnel-manual-page.patch +Patch106: 0107-man-ip-tunnel.8-Document-missing-6rd-action.patch +Patch107: 0108-man-ip-xfrm.8-Document-missing-parameters.patch +Patch108: 0109-man-ip-add-h-uman-readable-option.patch +Patch109: 0110-man-ip.8-Add-missing-flags-and-token-subcommand-desc.patch +Patch110: 0111-man-ip-l2tp.8-Fix-BNF-syntax.patch +Patch111: 0112-fix-spelling-of-Kuznetsov.patch +Patch112: 0113-man-Spelling-fixes.patch +Patch113: 0114-man-tc-htb-Fix-HRB-HTB-typo.patch +Patch114: 0115-TBF-man-page-fix-tbf-is-not-classless.patch +Patch115: 0116-man8-scrub-trailing-whitespace.patch +Patch116: 0117-man-ip-.8-drop-any-reference-to-generic-ip-options.patch +Patch117: 0118-fix-indentation-of-ip-neighbour-man-page.patch +Patch118: 0119-man-ip-neighbour.8-Document-all-known-nud-states.patch +Patch119: 0120-libnetlink-Double-the-dump-buffer-size.patch +Patch120: 0121-man-ip-link-Beef-up-VXLAN-csum-options-a-bit.patch +Patch121: 0122-fix-print_ipt-segfault-if-more-then-one-filter-with-.patch +Patch122: 0123-man-rtpr-add-minimal-manpage.patch +Patch123: 0124-tc-introduce-simple-action.patch +Patch124: 0125-simple-print-newline.patch +Patch125: 0126-tc-minor-spelling-fixes.patch +Patch126: 0127-whitespace-cleanup.patch +Patch127: 0128-tc-fix-compilation-warning-on-32bits-arch.patch +Patch128: 0129-man-Add-a-man-page-for-the-csum-action.patch +Patch129: 0130-man-Add-a-man-page-for-the-mirred-action.patch +Patch130: 0131-man-Add-a-man-page-for-the-nat-action.patch +Patch131: 0132-man-Add-a-man-page-for-the-pedit-action.patch +Patch132: 0133-man-Add-a-man-page-for-the-police-action.patch +Patch133: 0134-man-Add-a-man-page-for-the-simple-action.patch +Patch134: 0135-man-Add-a-man-page-for-the-skbedit-action.patch +Patch135: 0136-man-Add-a-man-page-for-the-xt-action.patch +Patch136: 0137-man-tc-u32-Minor-syntax-fix.patch +Patch137: 0138-tc-pedit-document-branch-control-in-help-output.patch +Patch138: 0139-tc-connmark-pedit-Rename-BRANCH-to-CONTROL.patch +Patch139: 0140-man-tc-csum.8-Add-an-example.patch +Patch140: 0141-man-tc-mirred.8-Reword-man-page-a-bit-add-generic-mi.patch +Patch141: 0142-man-tc-police.8-Emphasize-on-the-two-rate-control-me.patch +Patch142: 0143-man-tc-skbedit.8-Elaborate-a-bit-on-TX-queues.patch +Patch143: 0144-man-ship-action-man-pages.patch +Patch144: 0145-doc-Add-my-article-about-tc-filters-and-actions.patch +Patch145: 0146-doc-tc-filters.tex-Drop-overly-subjective-paragraphs.patch +Patch146: 0147-ss-Fix-wrong-filter-behaviour.patch +Patch147: 0148-ss-Drop-silly-assignment.patch +Patch148: 0149-ss-Fix-accidental-state-filter-override.patch +Patch149: 0150-ip-enable-configuring-multicast-group-autojoin.patch +Patch150: 0151-man-ip-ip-link-Fix-ip-option-location.patch +Patch151: 0152-ip-link-Allow-to-filter-devices-by-master-dev.patch +Patch152: 0153-ip-link-Show-devices-by-type.patch +Patch153: 0154-man-ip-link-Small-example-of-ip-link-show-master.patch +Patch154: 0155-ipaddress-Allow-listing-addresses-by-type.patch +Patch155: 0156-add-new-IFLA_VF_TRUST-netlink-attribute.patch +Patch156: 0157-iplink-Support-VF-Trust.patch +Patch157: 0158-ip-link-Support-printing-VF-trust-setting.patch +Patch158: 0159-man-ip-link.8-Fix-ip-link-delete-description.patch +Patch159: 0160-man-ip-address-ip-link-Document-type-quirk.patch +Patch160: 0161-iproute2-GENEVE-support.patch +Patch161: 0162-iproute2-update-ip-link.8-for-geneve-tunnels.patch +Patch162: 0163-iplink_geneve-add-ttl-configuration-at-link-creation.patch +Patch163: 0164-iplink_geneve-add-tos-configuration-at-link-creation.patch +Patch164: 0165-geneve-add-support-for-IPv6-link-partners.patch +Patch165: 0166-geneve-add-support-for-lwt-tunnel-creation-and-dst-p.patch +Patch166: 0167-geneve-Add-support-for-configuring-UDP-checksums.patch +Patch167: 0168-geneve-add-support-to-set-flow-label.patch +Patch168: 0169-geneve-fix-IPv6-remote-address-reporting.patch +Patch169: 0170-iproute2-utils-change-hexstring_n2a-and-hexstring_a2.patch +Patch170: 0171-iproute2-arpd-use-ll_addr_a2n-and-ll_addr_n2a.patch +Patch171: 0172-lib-ll_addr-improve-ll_addr_n2a-a-bit.patch +Patch172: 0173-utils-make-hexstring_a2n-provide-the-number-of-hex-d.patch +Patch173: 0174-utils-add-get_be-16-32-64-use-them-where-possible.patch +Patch174: 0175-utils-provide-get_hex-to-read-a-hex-digit-from-a-cha.patch +Patch175: 0176-ip-add-MACsec-support.patch +Patch176: 0177-utils-fix-hex-digits-parsing-in-hexstring_a2n.patch +Patch177: 0178-RH-INTERNAL-update-kernel-headers-to-v4.6.0.patch +Patch178: 0179-add-if_macsec-header.patch +Patch179: 0180-configure-Add-check-for-the-doc-tools.patch +Patch180: 0181-configure-Check-for-libmnl.patch +Patch181: 0182-configure-cleanup.patch +Patch182: 0183-include-add-linked-list-implementation-from-kernel.patch +Patch183: 0184-add-devlink-tool.patch +Patch184: 0185-devlink-ignore-build-result.patch +Patch185: 0186-devlink-fix-devlink-port-help-message.patch +Patch186: 0187-list-add-list_for_each_entry_reverse-macro.patch +Patch187: 0188-list-add-list_add_tail-helper.patch +Patch188: 0189-devlink-introduce-pr_out_port_handle-helper.patch +Patch189: 0190-devlink-introduce-helper-to-print-out-nice-names-ifn.patch +Patch190: 0191-devlink-split-dl_argv_parse_put-to-parse-and-put-par.patch +Patch191: 0192-devlink-introduce-dump-filtering-function.patch +Patch192: 0193-devlink-allow-to-parse-both-devlink-and-port-handle-.patch +Patch193: 0194-devlink-implement-shared-buffer-support.patch +Patch194: 0195-devlink-implement-shared-buffer-occupancy-control.patch +Patch195: 0196-devlink-add-manpage-for-shared-buffer.patch +Patch196: 0197-ip-route-restore-route-entries-in-correct-order.patch +Patch197: 0198-iproute-constify-rtattr_cmp.patch +Patch198: 0199-ip-link-Add-group-in-usage-for-ip-link-delete.patch +Patch199: 0200-iplink-List-valid-type-argument-in-ip-link-help-text.patch +Patch200: 0201-iplink-bond_slave-Add-missing-help-functions.patch +Patch201: 0202-man-ip-link-Add-deleting-links-by-group.patch +Patch202: 0203-man-ip-link-Add-short-description-about-group.patch +Patch203: 0204-man-ip-link-Remove-extra-GROUP-explanation.patch +Patch204: 0205-ip-link.8-Extend-type-list-in-synopsis.patch +Patch205: 0206-ip-link.8-Place-ip-link-set-warning-more-prominently.patch +Patch206: 0207-ip-link.8-Add-slave-type-option-descriptions.patch +Patch207: 0208-ip-link-fix-unterminated-string-in-manpage.patch +Patch208: 0209-vxlan-fix-help-and-man-text.patch +Patch209: 0210-ip-link-fix-man-page-warnings.patch +Patch210: 0211-ip-link.8-Fix-font-choices.patch +Patch211: 0212-ip-address.8-Document-autojoin-flag.patch +Patch212: 0213-route-allow-routes-to-be-configured-with-expire-valu.patch +Patch213: 0214-ip-route-timeout-for-routes-has-to-be-set-in-seconds.patch +Patch214: 0215-iproute2-ip-route.8.in-Add-expires-option-for-ip-rou.patch +Patch215: 0216-ipneigh-List-all-nud-states-in-help-output.patch +Patch216: 0217-Document-VF-link-state-control-in-the-ip-link-man-pa.patch +Patch217: 0218-man-ip-link-Document-query_rss-option.patch +Patch218: 0219-Add-support-to-configure-SR-IOV-VF-minimum-and-maxim.patch +Patch219: 0220-ip-check-for-missing-dev-arg-when-doing-VF-rate.patch +Patch220: 0221-ip-link-Remove-unnecessary-device-checking.patch +Patch221: 0222-ip-link-Fix-crash-on-older-kernels-when-show-VF-dev.patch +Patch222: 0223-iplink-Add-missing-variable-initialization.patch +Patch223: 0224-iplink-Check-address-length-via-netlink.patch +Patch224: 0225-Fix-MAC-address-length-check.patch +Patch225: 0226-ip-add-paren-to-silence-warning.patch +Patch226: 0227-doc-man-ip-rule-Remove-incorrect-statement-about-rul.patch +Patch227: 0228-man-ip-link-ip-address-Drop-references-to-ipvlan.patch +Patch228: 0229-man-ip-link-Drop-fou-and-gue-related-documentation.patch +Patch229: 0230-Revert-ip-fix-exit-code-for-rule-failures.patch +Patch230: 0231-Revert-ip-return-correct-exit-code-on-route-failure.patch +Patch231: 0232-Revert-link-dump-filter.patch +Patch232: 0233-Revert-ip-fix-exit-code-for-addrlabel.patch +Patch233: 0234-Revert-fix-ip-force-batch-to-continue-on-errors.patch +Patch234: 0235-Revert-Allow-specifying-bridge-port-STP-state-by-nam.patch +Patch235: 0236-man-macsec-fix-macsec-related-typos.patch +Patch236: 0237-ip-link-address-add-macsec-item-to-TYPE-list.patch +Patch237: 0238-macsec-cipher-and-icvlen-can-be-set-separately.patch +Patch238: 0239-man-ip-link.8-Document-missing-geneve-options.patch +Patch239: 0240-ip-link-add-missing-min-max-_tx_rate-to-help-text.patch +Patch240: 0241-ip-route-restore_handler-should-check-tb-RTA_PREFSRC.patch License: GPLv2+ and Public Domain BuildRequires: bison BuildRequires: flex BuildRequires: iptables-devel >= 1.4.5 BuildRequires: libdb-devel +BuildRequires: libmnl-devel BuildRequires: libselinux-devel BuildRequires: linuxdoc-tools BuildRequires: pkgconfig @@ -138,6 +269,7 @@ BuildRequires: tex(cm-super-t1.enc) BuildRequires: tex(dvips) BuildRequires: tex(ecrm1000.tfm) BuildRequires: tex(latex) +BuildRequires: tex(fullpage.sty) %if 0%{?fedora} BuildRequires: linux-atm-libs-devel %endif @@ -168,21 +300,32 @@ Provides: iproute-static = %{version}-%{release} The libnetlink static library. %prep -%setup -q -n %{name}2-%{version} +%setup -q -n %{name}-%{version}-%{baserelease} %patch0 -p1 -sed -i "s/_VERSION_/%{version}/" man/man8/ss.8 -%patch1 -p1 -b .kernel -%patch2 -p1 -b .opt_flags -%patch3 -p1 -b .ipproto -%patch4 -p1 -b .fix_cbq -%patch5 -p1 -b .print-route -%patch6 -p1 -b .peer-veth-without-name -%patch7 -p1 -b .lnstat-dump-to-stdout -%patch8 -p1 -b .unused-result -%patch9 -p1 -b .xfrm-state -%patch10 -p1 -b .ok -%patch13 -p1 -b .lnstat-interval -%patch17 -p1 -b .rtt +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 %patch25 -p1 %patch26 -p1 %patch27 -p1 @@ -192,7 +335,9 @@ sed -i "s/_VERSION_/%{version}/" man/man8/ss.8 %patch31 -p1 %patch32 -p1 %patch33 -p1 +%patch34 -p1 %patch35 -p1 +%patch36 -p1 %patch37 -p1 %patch38 -p1 %patch39 -p1 @@ -217,13 +362,192 @@ sed -i "s/_VERSION_/%{version}/" man/man8/ss.8 %patch58 -p1 %patch59 -p1 %patch60 -p1 - -sed -i 's/^LIBDIR=/LIBDIR?=/' Makefile +%patch61 -p1 +%patch62 -p1 +%patch63 -p1 +%patch64 -p1 +%patch65 -p1 +%patch66 -p1 +%patch67 -p1 +%patch68 -p1 +%patch69 -p1 +%patch70 -p1 +%patch71 -p1 +%patch72 -p1 +%patch73 -p1 +%patch74 -p1 +%patch75 -p1 +%patch76 -p1 +%patch77 -p1 +%patch78 -p1 +%patch79 -p1 +%patch80 -p1 +%patch81 -p1 +%patch82 -p1 +%patch83 -p1 +%patch84 -p1 +%patch85 -p1 +%patch86 -p1 +%patch87 -p1 +%patch88 -p1 +%patch89 -p1 +%patch90 -p1 +%patch91 -p1 +%patch92 -p1 +%patch93 -p1 +%patch94 -p1 +%patch95 -p1 +%patch96 -p1 +%patch97 -p1 +%patch98 -p1 +%patch99 -p1 +%patch100 -p1 +%patch101 -p1 +%patch102 -p1 +%patch103 -p1 +%patch104 -p1 +%patch105 -p1 +%patch106 -p1 +%patch107 -p1 +%patch108 -p1 +%patch109 -p1 +%patch110 -p1 +%patch111 -p1 +%patch112 -p1 +%patch113 -p1 +%patch114 -p1 +%patch115 -p1 +%patch116 -p1 +%patch117 -p1 +%patch118 -p1 +%patch119 -p1 +%patch120 -p1 +%patch121 -p1 +%patch122 -p1 +%patch123 -p1 +%patch124 -p1 +%patch125 -p1 +%patch126 -p1 +%patch127 -p1 +%patch128 -p1 +%patch129 -p1 +%patch130 -p1 +%patch131 -p1 +%patch132 -p1 +%patch133 -p1 +%patch134 -p1 +%patch135 -p1 +%patch136 -p1 +%patch137 -p1 +%patch138 -p1 +%patch139 -p1 +%patch140 -p1 +%patch141 -p1 +%patch142 -p1 +%patch143 -p1 +%patch144 -p1 +%patch145 -p1 +%patch146 -p1 +%patch147 -p1 +%patch148 -p1 +%patch149 -p1 +%patch150 -p1 +%patch151 -p1 +%patch152 -p1 +%patch153 -p1 +%patch154 -p1 +%patch155 -p1 +%patch156 -p1 +%patch157 -p1 +%patch158 -p1 +%patch159 -p1 +%patch160 -p1 +%patch161 -p1 +%patch162 -p1 +%patch163 -p1 +%patch164 -p1 +%patch165 -p1 +%patch166 -p1 +%patch167 -p1 +%patch168 -p1 +%patch169 -p1 +%patch170 -p1 +%patch171 -p1 +%patch172 -p1 +%patch173 -p1 +%patch174 -p1 +%patch175 -p1 +%patch176 -p1 +%patch177 -p1 +%patch178 -p1 +%patch179 -p1 +%patch180 -p1 +%patch181 -p1 +%patch182 -p1 +%patch183 -p1 +%patch184 -p1 +%patch185 -p1 +%patch186 -p1 +%patch187 -p1 +%patch188 -p1 +%patch189 -p1 +%patch190 -p1 +%patch191 -p1 +%patch192 -p1 +%patch193 -p1 +%patch194 -p1 +%patch195 -p1 +%patch196 -p1 +%patch197 -p1 +%patch198 -p1 +%patch199 -p1 +%patch200 -p1 +%patch201 -p1 +%patch202 -p1 +%patch203 -p1 +%patch204 -p1 +%patch205 -p1 +%patch206 -p1 +%patch207 -p1 +%patch208 -p1 +%patch209 -p1 +%patch210 -p1 +%patch211 -p1 +%patch212 -p1 +%patch213 -p1 +%patch214 -p1 +%patch215 -p1 +%patch216 -p1 +%patch217 -p1 +%patch218 -p1 +%patch219 -p1 +%patch220 -p1 +%patch221 -p1 +%patch222 -p1 +%patch223 -p1 +%patch224 -p1 +%patch225 -p1 +%patch226 -p1 +%patch227 -p1 +%patch228 -p1 +%patch229 -p1 +%patch230 -p1 +%patch231 -p1 +%patch232 -p1 +%patch233 -p1 +%patch234 -p1 +%patch235 -p1 +%patch236 -p1 +%patch237 -p1 +%patch238 -p1 +%patch239 -p1 +%patch240 -p1 sed -i 's/iproute-doc/%{name}-%{version}/' man/man8/lnstat.8 %build export LIBDIR=/%{_libdir} export IPT_LIB_DIR=/%{_lib}/xtables +export CFLAGS="${CFLAGS:-%optflags}" ./configure make %{?_smp_mflags} make -C doc @@ -241,6 +565,7 @@ mkdir -p \ for binary in \ bridge/bridge \ + devlink/devlink \ examples/cbq.init-%{cbq_version} \ genl/genl \ ip/ifcfg \ @@ -284,6 +609,7 @@ iconv -f latin1 -t utf8 man/man8/ss.8 > man/man8/ss.8.utf8 && install -m644 man/man3/*.3 %{buildroot}%{_mandir}/man3 install -m644 man/man7/*.7 %{buildroot}%{_mandir}/man7 install -m644 man/man8/*.8 %{buildroot}%{_mandir}/man8 +echo '.so man8/tc-cbq.8' > %{buildroot}%{_mandir}/man8/cbq.8 # Config files install -m644 etc/iproute2/* %{buildroot}%{_sysconfdir}/iproute2 @@ -318,9 +644,291 @@ done %{_includedir}/libnetlink.h %changelog -* Tue May 31 2016 Phil Sutter - 3.10.0-54.1 -- Resolves: #1327582 - ip link show command adds extra "Message Truncated" to - output +* Thu Aug 25 2016 Phil Sutter <psutter@redhat.com> [3.10.0-74.el7] +- ip route: restore_handler should check tb[RTA_PREFSRC] for local networks (Phil Sutter) [1362728] + +* Thu Aug 18 2016 Phil Sutter <psutter@redhat.com> [3.10.0-73.el7] +- ip-link: add missing {min,max}_tx_rate to help text (Phil Sutter) [1340914] +- man: ip-link.8: Document missing geneve options (Phil Sutter) [1339178] +- iproute.spec: Fix for missing cbq.8 man page (Phil Sutter) [1362551] + +* Thu Aug 04 2016 Phil Sutter <psutter@redhat.com> [3.10.0-72.el7] +- macsec: cipher and icvlen can be set separately (Davide Caratti) [1354408] +- ip {link,address}: add 'macsec' item to TYPE list (Davide Caratti) [1354702] +- man: macsec: fix macsec related typos (Davide Caratti) [1354702 1354319] +- Revert "Allow specifying bridge port STP state by name rather than number." (Phil Sutter) [1288042] +- Revert "fix ip -force -batch to continue on errors" (Phil Sutter) [1288042] +- Revert "ip: fix exit code for addrlabel" (Phil Sutter) [1288042] +- Revert "link dump filter" (Phil Sutter) [1288042] +- Revert "ip: return correct exit code on route failure" (Phil Sutter) [1288042] +- Revert "ip: fix exit code for rule failures" (Phil Sutter) [1288042] +- man: ip-link: Drop fou and gue related documentation (Phil Sutter) [1013584] +- man: ip-link, ip-address: Drop references to ipvlan (Phil Sutter) [1013584] +- doc, man: ip-rule: Remove incorrect statement about rule 0 (Phil Sutter) [1362561] + +* Sat Jul 30 2016 Phil Sutter <psutter@redhat.com> [3.10.0-71.el7] +- ip: add paren to silence warning (Phil Sutter) [1340914] +- Fix MAC address length check (Jakub Sitnicki) [1253767 1271580] +- iplink: Check address length via netlink (Jakub Sitnicki) [1253767 1271580] +- iplink: Add missing variable initialization (Jakub Sitnicki) [1253767 1271580] +- ip link: Fix crash on older kernels when show VF dev (Jakub Sitnicki) [1340914] +- ip link: Remove unnecessary device checking (Jakub Sitnicki) [1340914] +- ip: check for missing dev arg when doing VF rate (Jakub Sitnicki) [1340914] +- Add support to configure SR-IOV VF minimum and maximum Tx rate through ip tool (Jakub Sitnicki) [1340914] + +* Fri Jul 22 2016 Phil Sutter <psutter@redhat.com> [3.10.0-70.el7] +- man: ip-link: Document query_rss option (Phil Sutter) [1264146] +- Document VF link state control in the ip-link man page (Phil Sutter) [1264146] +- ipneigh: List all nud states in help output (Phil Sutter) [1276661] +- iproute2: ip-route.8.in: Add expires option for ip route (Phil Sutter) [1357020] +- ip route: timeout for routes has to be set in seconds (Phil Sutter) [1357020] +- route: allow routes to be configured with expire values (Phil Sutter) [1357020] + +* Wed Jul 20 2016 Phil Sutter <psutter@redhat.com> [3.10.0-69.el7] +- ip-address.8: Document autojoin flag (Phil Sutter) [1333513] +- ip-link.8: Fix font choices (Phil Sutter) [1269528] +- ip-link: fix man page warnings (Phil Sutter) [1269528] +- vxlan: fix help and man text (Phil Sutter) [1269528] +- ip-link: fix unterminated string in manpage (Phil Sutter) [1269528] +- ip-link.8: Add slave type option descriptions (Phil Sutter) [1269528] +- ip-link.8: Place 'ip link set' warning more prominently (Phil Sutter) [1269528] +- ip-link.8: Extend type list in synopsis (Phil Sutter) [1269528] +- man ip-link: Remove extra GROUP explanation (Phil Sutter) [1269528] +- man ip-link: Add short description about 'group' (Phil Sutter) [1269528] +- man ip-link: Add deleting links by group (Phil Sutter) [1269528] +- iplink: bond_slave: Add missing help functions (Phil Sutter) [1269528] +- iplink: List valid 'type' argument in ip link help text (Phil Sutter) [1269528] +- ip link: Add group in usage() for 'ip link delete' (Phil Sutter) [1269528] +- iproute: constify rtattr_cmp (Phil Sutter) [1348133] +- ip route: restore route entries in correct order (Phil Sutter) [1348133] + +* Sat Jul 09 2016 Phil Sutter <psutter@redhat.com> [3.10.0-68.el7] +- devlink: add manpage for shared buffer (Phil Sutter) [1342515] +- devlink: implement shared buffer occupancy control (Phil Sutter) [1342515] +- devlink: implement shared buffer support (Phil Sutter) [1342515] +- devlink: allow to parse both devlink and port handle in the same time (Phil Sutter) [1342515] +- devlink: introduce dump filtering function (Phil Sutter) [1342515] +- devlink: split dl_argv_parse_put to parse and put parts (Phil Sutter) [1342515] +- devlink: introduce helper to print out nice names (ifnames) (Phil Sutter) [1342515] +- devlink: introduce pr_out_port_handle helper (Phil Sutter) [1342515] +- list: add list_add_tail helper (Phil Sutter) [1342515] +- list: add list_for_each_entry_reverse macro (Phil Sutter) [1342515] +- devlink: fix "devlink port" help message (Phil Sutter) [1342515] +- devlink: ignore build result (Phil Sutter) [1342515] +- add devlink tool (Phil Sutter) [1342515] +- include: add linked list implementation from kernel (Phil Sutter) [1342515] +- configure: cleanup (Phil Sutter) [1342515] +- configure: Check for libmnl (Phil Sutter) [1342515] +- configure: Add check for the doc tools (Phil Sutter) [1342515] +- add if_macsec header (Davide Caratti) [1300765] +- RH-INTERNAL: update kernel headers to v4.6.0 (Davide Caratti) [1300765] +- utils: fix hex digits parsing in hexstring_a2n() (Davide Caratti) [1300765] +- ip: add MACsec support (Davide Caratti) [1300765] +- utils: provide get_hex to read a hex digit from a char (Davide Caratti) [1300765] +- utils: add get_be{16, 32, 64}, use them where possible (Davide Caratti) [1300765] +- utils: make hexstring_a2n provide the number of hex digits parsed (Davide Caratti) [1300765] +- lib/ll_addr: improve ll_addr_n2a() a bit (Davide Caratti) [1300765] +- iproute2: arpd: use ll_addr_a2n and ll_addr_n2a (Davide Caratti) [1300765] +- iproute2: utils: change hexstring_n2a and hexstring_a2n to do not work with ":" (Davide Caratti) [1300765] + +* Tue Jul 05 2016 Phil Sutter <psutter@redhat.com> [3.10.0-67.el7] +- geneve: fix IPv6 remote address reporting (Phil Sutter) [1339178] +- geneve: add support to set flow label (Phil Sutter) [1339178] +- geneve: Add support for configuring UDP checksums. (Phil Sutter) [1339178] +- geneve: add support for lwt tunnel creation and dst port selection (Phil Sutter) [1339178] +- geneve: add support for IPv6 link partners (Phil Sutter) [1339178] +- iplink_geneve: add tos configuration at link creation (Phil Sutter) [1339178] +- iplink_geneve: add ttl configuration at link creation (Phil Sutter) [1339178] +- iproute2: update ip-link.8 for geneve tunnels (Phil Sutter) [1339178] +- iproute2: GENEVE support (Phil Sutter) [1339178] +- man: ip-address, ip-link: Document 'type' quirk (Phil Sutter) [1341343] +- man: ip-link.8: Fix 'ip link delete' description (Phil Sutter) [1341343] + +* Thu Jun 16 2016 Phil Sutter <psutter@redhat.com> [3.10.0-66.el7] +- ip-link: Support printing VF trust setting (Phil Sutter) [1302119] +- iplink: Support VF Trust (Phil Sutter) [1302119] +- add new IFLA_VF_TRUST netlink attribute (Phil Sutter) [1302119] +- ipaddress: Allow listing addresses by type (Phil Sutter) [1341343] +- man ip-link: Small example of 'ip link show master' (Phil Sutter) [1341343] +- ip link: Show devices by type (Phil Sutter) [1341343] +- ip link: Allow to filter devices by master dev (Phil Sutter) [1341343] + +* Fri Jun 03 2016 Phil Sutter <psutter@redhat.com> [3.10.0-65.el7] +- man: ip, ip-link: Fix ip option location (Phil Sutter) [1251186] +- ip: enable configuring multicast group autojoin (Phil Sutter) [1333513] +- ss: Fix accidental state filter override (Phil Sutter) [1318005] +- ss: Drop silly assignment (Phil Sutter) [1318005] +- ss: Fix wrong filter behaviour (Phil Sutter) [1318005] + +* Wed Mar 30 2016 Phil Sutter <psutter@redhat.com> [3.10.0-64.el7] +- Add missing build dependency to spec file (Phil Sutter) [1275426] + +* Wed Mar 30 2016 Phil Sutter <psutter@redhat.com> [3.10.0-63.el7] +- doc/tc-filters.tex: Drop overly subjective paragraphs (Phil Sutter) [1275426] +- doc: Add my article about tc, filters and actions (Phil Sutter) [1275426] +- gitignore: Ignore 'doc' files generated at runtime (Phil Sutter) [1275426] +- tests: Add runtime generated files to .gitignore (Phil Sutter) [1275426] +- man: ship action man pages (Phil Sutter) [1275426] +- man: tc-skbedit.8: Elaborate a bit on TX queues (Phil Sutter) [1275426] +- man: tc-police.8: Emphasize on the two rate control mechanisms (Phil Sutter) [1275426] +- man: tc-mirred.8: Reword man page a bit, add generic mirror example (Phil Sutter) [1275426] +- man: tc-csum.8: Add an example (Phil Sutter) [1275426] +- tc: connmark, pedit: Rename BRANCH to CONTROL (Phil Sutter) [1275426] +- tc: pedit: document branch control in help output (Phil Sutter) [1275426] +- man: tc-u32: Minor syntax fix (Phil Sutter) [1275426] +- man: Add a man page for the xt action (Phil Sutter) [1275426] +- man: Add a man page for the skbedit action (Phil Sutter) [1275426] +- man: Add a man page for the simple action (Phil Sutter) [1275426] +- man: Add a man page for the police action (Phil Sutter) [1275426] +- man: Add a man page for the pedit action (Phil Sutter) [1275426] +- man: Add a man page for the nat action (Phil Sutter) [1275426] +- man: Add a man page for the mirred action (Phil Sutter) [1275426] +- man: Add a man page for the csum action. (Phil Sutter) [1275426] + +* Wed Mar 23 2016 Phil Sutter <psutter@redhat.com> [3.10.0-62.el7] +- tc: fix compilation warning on 32bits arch (Phil Sutter) [1315930] +- whitespace cleanup (Phil Sutter) [1315930] +- tc: minor spelling fixes (Phil Sutter) [1315930] +- simple print newline (Phil Sutter) [1315930] +- tc: introduce simple action (Phil Sutter) [1315930] +- man: rtpr: add minimal manpage (Phil Sutter) [1316059] + +* Tue Mar 08 2016 Phil Sutter <psutter@redhat.com> [3.10.0-61.el7] +- fix print_ipt: segfault if more then one filter with action -j MARK. (Phil Sutter) [1314403] +- man: ip-link: Beef up VXLAN csum options a bit (Phil Sutter) [1254625] +- libnetlink: Double the dump buffer size (Phil Sutter) [1304840] + +* Mon Mar 07 2016 Phil Sutter <psutter@redhat.com> [3.10.0-60.el7] +- man: ip-neighbour.8: Document all known nud states (Phil Sutter) [1276661] +- fix indentation of ip neighbour man page (Phil Sutter) [1276661] +- man: ip-*.8: drop any reference to generic ip options (Phil Sutter) [1251186] +- man8: scrub trailing whitespace (Phil Sutter) [1251186] +- TBF man page fix (tbf is not classless) (Phil Sutter) [1251186] +- man tc-htb: Fix HRB -> HTB typo (Phil Sutter) [1251186] +- man: Spelling fixes (Phil Sutter) [1251186] +- fix spelling of Kuznetsov (Phil Sutter) [1251186] +- man: ip-l2tp.8: Fix BNF syntax (Phil Sutter) [1251186] +- man: ip.8: Add missing flags and token subcommand description (Phil Sutter) [1251186] +- man: ip: add -h[uman-readable] option (Phil Sutter) [1251186] +- man: ip-xfrm.8: Document missing parameters (Phil Sutter) [1251186] +- man: ip-tunnel.8: Document missing 6rd action (Phil Sutter) [1251186] +- add 'vti'/'vti6' tunnel modes to ip-tunnel manual page (Phil Sutter) [1251186] +- man: ip-token.8: Review synopsis section (Phil Sutter) [1251186] +- man: ip-rule.8: Review synopsis section (Phil Sutter) [1251186] +- man: ip-ntable.8: Review synopsis section (Phil Sutter) [1251186] +- man: ip-netns.8: Clarify synopsis a bit (Phil Sutter) [1251186] +- man: ip-neighbour: Fix for missing NUD_STATE description (Phil Sutter) [1251186] +- man: ip-link.8: Fix and improve synopsis (Phil Sutter) [1251186] +- man: ip-link.8: minor font fix (Phil Sutter) [1251186] +- man: ip-address.8: Minor syntax fixes (Phil Sutter) [1251186] +- iprule: add missing nat keyword to help text (Phil Sutter) [1251186] +- iproute: TYPE keyword is not optional, fix help text accordingly (Phil Sutter) [1251186] +- ipntable: Fix typo in help text (Phil Sutter) [1251186] +- ipneigh: add missing proxy keyword to help text (Phil Sutter) [1251186] +- iplink: fix help text syntax (Phil Sutter) [1251186] +- ipaddrlabel: Improve help text precision (Phil Sutter) [1251186] +- ip: align help text with manpage (Phil Sutter) [1251186] +- ipl2tp: Print help even on systems without l2tp support (Phil Sutter) [1251186] +- iprule: Align help text with man page synopsis (Phil Sutter) [1251186] +- iplink: macvtap: fix man page (Phil Sutter) [1013584] +- man: ip-link: document MACVLAN/MACVTAP interface types (Phil Sutter) [1013584] +- man: ip-link: fix a typo (Phil Sutter) [1013584] +- man ip-link: Add missing link types - vti,ipvlan,nlmon (Phil Sutter) [1013584] +- iproute2: ip-link.8.in: Spelling fixes (Phil Sutter) [1013584] +- ip-link: Document IPoIB link type in the man page (Phil Sutter) [1013584] +- iproute: Descriptions of fou and gue options in ip-link man pages (Phil Sutter) [1013584] +- iproute2: ip6gre: update man pages (Phil Sutter) [1013584] +- ip: macvlan: support MACVLAN_FLAG_NOPROMISC flag (Phil Sutter) [1013584] +- ip: link: consolidate macvlan and macvtap (Phil Sutter) [1013584] + +* Wed Feb 24 2016 Phil Sutter <psutter@redhat.com> [3.10.0-59.el7] +- iplink: add ageing_time, stp_state and priority for bridge (Phil Sutter) [1270759] +- iplink: shortify printing the usage of link type (Phil Sutter) [1270759] +- iplink: use the short format to print help info (Phil Sutter) [1270759] +- iplink_bridge: add support for priority (Phil Sutter) [1270759] +- iplink_bridge: add support for stp_state (Phil Sutter) [1270759] +- iplink_bridge: add support for ageing_time (Phil Sutter) [1270759] +- add bridge master device support (Phil Sutter) [1270759] +- add bridge_slave device support (Phil Sutter) [1270759] +- iplink: bond_slave: fix ad_actor/partner_oper_port_state output (Phil Sutter) [1269528] +- ip: remove extra newlines at end-of-file (Phil Sutter) [1269528] +- ip link: missing options in bond usage (Phil Sutter) [1269528] +- bond: fix return after invarg (Phil Sutter) [1269528] +- iplink: bonding: add support for IFLA_BOND_TLB_DYNAMIC_LB (Phil Sutter) [1269528] +- bonding: export 3ad actor and partner port state (Phil Sutter) [1269528] +- iplink_bond: add support for ad_actor and port_key options (Phil Sutter) [1269528] +- ip link: Shortify printing the usage of link type (Phil Sutter) [1269528] +- add help command to bonding master (Phil Sutter) [1269528] +- iproute2: allow to change slave options via type_slave (Phil Sutter) [1269528] +- ip: add nlmon as a device type to help message (Phil Sutter) [1269528] +- iplink: can: fix help text and man page (Phil Sutter) [1269528] +- iplink_bond_slave: show mii_status only once (Phil Sutter) [1269528] +- iplink_bond: fix parameter value matching (Phil Sutter) [1269528] +- iplink_bond: fix arp_all_targets parameter name in output (Phil Sutter) [1269528] +- iplink: add support for bonding slave (Phil Sutter) [1269528] +- introduce support for slave info data (Phil Sutter) [1269528] +- iproute2: finish support for bonding attributes (Phil Sutter) [1269528] +- iplink: add support for bonding netlink (Phil Sutter) [1269528] +- iplink: update available type list (Phil Sutter) [1269528] +- xfrm: revise man page and document ip xfrm policy set (Phil Sutter) [1269528] +- xfrm: add command for configuring SPD hash table (Phil Sutter) [1212026] + +* Thu Feb 18 2016 Phil Sutter <psutter@redhat.com> [3.10.0-58.el7] +- tc: ship filter man pages and refer to them in tc.8 (Phil Sutter) [1286711] +- tc: add a man page for u32 filter (Phil Sutter) [1286711] +- tc: add a man page for tcindex filter (Phil Sutter) [1286711] +- tc: add a man page for route filter (Phil Sutter) [1286711] +- tc: add a man page for fw filter (Phil Sutter) [1286711] +- tc: add a man page for flow filter (Phil Sutter) [1286711] +- tc: add a man page for cgroup filter (Phil Sutter) [1286711] +- tc: add a man page for basic filter (Phil Sutter) [1286711] +- batch: support quoted strings (Phil Sutter) [1272593] +- man: fix whatis for fq (Phil Sutter) [1261520] +- man: tc: add man page for fq pacer (Phil Sutter) [1261520] + +* Thu Feb 18 2016 Phil Sutter <psutter@redhat.com> [3.10.0-57.el7] +- route: Fix printing of locked entries (Phil Sutter) [1291832] +- route: ignore RTAX_HOPLIMIT of value -1 (Phil Sutter) [1291832] +- ip-link: remove warning message (Phil Sutter) [1291832] +- ip: route: add congestion control metric (Phil Sutter) [1291832] +- ip route: enable per-route ecn settings via 'features' option (Phil Sutter) [1291832] +- iproute2: ip-route.8.in: minor fixes (Phil Sutter) [1291832] +- iproute: restrict hoplimit values to be in range [0; 255] (Phil Sutter) [1291832] +- man ss: Fix explanation when no options specified (Phil Sutter) [1291818] +- libnetlink: don't confuse variables in rtnl_talk() (Phil Sutter) [1288042] +- libnetlink: add size argument to rtnl_talk (Phil Sutter) [1288042] +- ip: fix exit code for rule failures (Phil Sutter) [1288042] +- ip: return correct exit code on route failure (Phil Sutter) [1288042] +- link dump filter (Phil Sutter) [1288042] +- ip: fix exit code for addrlabel (Phil Sutter) [1288042] +- fix ip -force -batch to continue on errors (Phil Sutter) [1288042] +- Allow specifying bridge port STP state by name rather than number. (Phil Sutter) [1288042] +- gre: raising the size of the buffer holding nl messages. (Phil Sutter) [1288042] +- neighbor: check return values (Phil Sutter) [1277094] +- ip-address: fix oneline mode for interfaces with VF (Phil Sutter) [1272405] +- ss: add support for segs_in and segs_out (Phil Sutter) [1269114] +- ss: add support for bytes_acked & bytes_received (Phil Sutter) [1269114] +- ss: return -1 if an unrecognized option was given (Phil Sutter) [1265238] +- man: ip-address: document mngtmpaddr and noprefixroute flags (Phil Sutter) [1231898] +- man: ip-address: align synopsis with help output (Phil Sutter) [1231898] +- ip-address.8.in: fix BNF syntax error (Phil Sutter) [1231898] +- ip-address: fix and extend documentation (Phil Sutter) [1231898] +- ip: extend "ip-address" man page to reflect the recent flag extensions (Phil Sutter) [1231898] +- ip: allow ip address show to list addresses with certain flags not being set (Phil Sutter) [1231898] +- bridge fdb: add 'use' option to set NTF_USE flag in fdb add requests (Phil Sutter) [1075692] +- bridge: drop man page fragment (Phil Sutter) [1075692] +- bridge: drop reference to unused option embedded from manpage (Phil Sutter) [1075692] + +* Thu Feb 18 2016 Phil Sutter <psutter@redhat.com> [3.10.0-56.el7] +- ipaddress: fix ipaddr_flush for Linux >= 3.1 (Phil Sutter) [1291825] +- ipaddress: simplify ipaddr_flush() (Phil Sutter) [1291825] +- libnetlink: introduce nc_flags (Phil Sutter) [1291825] +- iproute2: Ignore EADDRNOTAVAIL errors during address flush operation (Phil Sutter) [1291825] +- lnstat: fix header displaying mechanism (Phil Sutter) [1263392] +- man: lnstat: rewrite manpage (Phil Sutter) [1269133] + +* Wed Feb 17 2016 Phil Sutter <psutter@redhat.com> [3.10.0-55.el7] +- Resolves: #1290860 - Rework list of patches, replace by upstream backports * Thu Sep 17 2015 Phil Sutter - 3.10.0-54 - Related: #1241486 - backport: tc: fq scheduler - add missing documentation