From 0ac2f3813e6469d42d1d065a8d75b06ca362a81e Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jul 28 2020 06:34:53 +0000 Subject: import iproute-5.3.0-5.el8 --- diff --git a/SOURCES/0001-Update-kernel-headers.patch b/SOURCES/0001-Update-kernel-headers.patch new file mode 100644 index 0000000..4d6f5d2 --- /dev/null +++ b/SOURCES/0001-Update-kernel-headers.patch @@ -0,0 +1,226 @@ +From 4cd2ea662ae3255713a7de44e496e6ed32ade0c9 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 16 Apr 2020 12:41:48 +0200 +Subject: [PATCH] Update kernel headers + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1770671 +Upstream Status: iproute2.git commit e3af717a8d410 + +commit e3af717a8d410c97d9e0b985219ab8fc9ff18b79 +Author: David Ahern +Date: Sun Aug 18 11:48:02 2019 -0700 + + Update kernel headers + + Update kernel headers to commit: + d83d508b74c4 ("Merge branch 'stmmac-next'") + + Signed-off-by: David Ahern +--- + include/uapi/linux/bpf.h | 37 ++++++++++++++++++- + include/uapi/linux/can/netlink.h | 6 ++-- + include/uapi/linux/devlink.h | 62 ++++++++++++++++++++++++++++++++ + include/uapi/linux/if_bridge.h | 1 + + 4 files changed, 102 insertions(+), 4 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 1e08475275702..79701d3e66f0b 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -134,6 +134,7 @@ enum bpf_map_type { + BPF_MAP_TYPE_QUEUE, + BPF_MAP_TYPE_STACK, + BPF_MAP_TYPE_SK_STORAGE, ++ BPF_MAP_TYPE_DEVMAP_HASH, + }; + + /* Note that tracing related programs such as +@@ -2713,6 +2714,33 @@ union bpf_attr { + * **-EPERM** if no permission to send the *sig*. + * + * **-EAGAIN** if bpf program can try again. ++ * ++ * s64 bpf_tcp_gen_syncookie(struct bpf_sock *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len) ++ * Description ++ * Try to issue a SYN cookie for the packet with corresponding ++ * IP/TCP headers, *iph* and *th*, on the listening socket in *sk*. ++ * ++ * *iph* points to the start of the IPv4 or IPv6 header, while ++ * *iph_len* contains **sizeof**\ (**struct iphdr**) or ++ * **sizeof**\ (**struct ip6hdr**). ++ * ++ * *th* points to the start of the TCP header, while *th_len* ++ * contains the length of the TCP header. ++ * ++ * Return ++ * On success, lower 32 bits hold the generated SYN cookie in ++ * followed by 16 bits which hold the MSS value for that cookie, ++ * and the top 16 bits are unused. ++ * ++ * On failure, the returned value is one of the following: ++ * ++ * **-EINVAL** SYN cookie cannot be issued due to error ++ * ++ * **-ENOENT** SYN cookie should not be issued (no SYN flood) ++ * ++ * **-EOPNOTSUPP** kernel configuration does not enable SYN cookies ++ * ++ * **-EPROTONOSUPPORT** IP packet version is not 4 or 6 + */ + #define __BPF_FUNC_MAPPER(FN) \ + FN(unspec), \ +@@ -2824,7 +2852,8 @@ union bpf_attr { + FN(strtoul), \ + FN(sk_storage_get), \ + FN(sk_storage_delete), \ +- FN(send_signal), ++ FN(send_signal), \ ++ FN(tcp_gen_syncookie), + + /* integer value in 'imm' field of BPF_CALL instruction selects which helper + * function eBPF program intends to call +@@ -3507,6 +3536,10 @@ enum bpf_task_fd_type { + BPF_FD_TYPE_URETPROBE, /* filename + offset */ + }; + ++#define BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG (1U << 0) ++#define BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL (1U << 1) ++#define BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP (1U << 2) ++ + struct bpf_flow_keys { + __u16 nhoff; + __u16 thoff; +@@ -3528,6 +3561,8 @@ struct bpf_flow_keys { + __u32 ipv6_dst[4]; /* in6_addr; network order */ + }; + }; ++ __u32 flags; ++ __be32 flow_label; + }; + + struct bpf_func_info { +diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h +index f0c5e58b8ee76..c1f62640e87bc 100644 +--- a/include/uapi/linux/can/netlink.h ++++ b/include/uapi/linux/can/netlink.h +@@ -40,15 +40,15 @@ struct can_bittiming { + }; + + /* +- * CAN harware-dependent bit-timing constant ++ * CAN hardware-dependent bit-timing constant + * + * Used for calculating and checking bit-timing parameters + */ + struct can_bittiming_const { + char name[16]; /* Name of the CAN controller hardware */ +- __u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */ ++ __u32 tseg1_min; /* Time segment 1 = prop_seg + phase_seg1 */ + __u32 tseg1_max; +- __u32 tseg2_min; /* Time segement 2 = phase_seg2 */ ++ __u32 tseg2_min; /* Time segment 2 = phase_seg2 */ + __u32 tseg2_max; + __u32 sjw_max; /* Synchronisation jump width */ + __u32 brp_min; /* Bit-rate prescaler */ +diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h +index fc195cbd66f45..3fb683bee6ba1 100644 +--- a/include/uapi/linux/devlink.h ++++ b/include/uapi/linux/devlink.h +@@ -107,6 +107,16 @@ enum devlink_command { + DEVLINK_CMD_FLASH_UPDATE_END, /* notification only */ + DEVLINK_CMD_FLASH_UPDATE_STATUS, /* notification only */ + ++ DEVLINK_CMD_TRAP_GET, /* can dump */ ++ DEVLINK_CMD_TRAP_SET, ++ DEVLINK_CMD_TRAP_NEW, ++ DEVLINK_CMD_TRAP_DEL, ++ ++ DEVLINK_CMD_TRAP_GROUP_GET, /* can dump */ ++ DEVLINK_CMD_TRAP_GROUP_SET, ++ DEVLINK_CMD_TRAP_GROUP_NEW, ++ DEVLINK_CMD_TRAP_GROUP_DEL, ++ + /* add new commands above here */ + __DEVLINK_CMD_MAX, + DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 +@@ -194,6 +204,47 @@ enum devlink_param_fw_load_policy_value { + DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH, + }; + ++enum { ++ DEVLINK_ATTR_STATS_RX_PACKETS, /* u64 */ ++ DEVLINK_ATTR_STATS_RX_BYTES, /* u64 */ ++ ++ __DEVLINK_ATTR_STATS_MAX, ++ DEVLINK_ATTR_STATS_MAX = __DEVLINK_ATTR_STATS_MAX - 1 ++}; ++ ++/** ++ * enum devlink_trap_action - Packet trap action. ++ * @DEVLINK_TRAP_ACTION_DROP: Packet is dropped by the device and a copy is not ++ * sent to the CPU. ++ * @DEVLINK_TRAP_ACTION_TRAP: The sole copy of the packet is sent to the CPU. ++ */ ++enum devlink_trap_action { ++ DEVLINK_TRAP_ACTION_DROP, ++ DEVLINK_TRAP_ACTION_TRAP, ++}; ++ ++/** ++ * enum devlink_trap_type - Packet trap type. ++ * @DEVLINK_TRAP_TYPE_DROP: Trap reason is a drop. Trapped packets are only ++ * processed by devlink and not injected to the ++ * kernel's Rx path. ++ * @DEVLINK_TRAP_TYPE_EXCEPTION: Trap reason is an exception. Packet was not ++ * forwarded as intended due to an exception ++ * (e.g., missing neighbour entry) and trapped to ++ * control plane for resolution. Trapped packets ++ * are processed by devlink and injected to ++ * the kernel's Rx path. ++ */ ++enum devlink_trap_type { ++ DEVLINK_TRAP_TYPE_DROP, ++ DEVLINK_TRAP_TYPE_EXCEPTION, ++}; ++ ++enum { ++ /* Trap can report input port as metadata */ ++ DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT, ++}; ++ + enum devlink_attr { + /* don't change the order or add anything between, this is ABI! */ + DEVLINK_ATTR_UNSPEC, +@@ -348,6 +399,17 @@ enum devlink_attr { + DEVLINK_ATTR_PORT_PCI_PF_NUMBER, /* u16 */ + DEVLINK_ATTR_PORT_PCI_VF_NUMBER, /* u16 */ + ++ DEVLINK_ATTR_STATS, /* nested */ ++ ++ DEVLINK_ATTR_TRAP_NAME, /* string */ ++ /* enum devlink_trap_action */ ++ DEVLINK_ATTR_TRAP_ACTION, /* u8 */ ++ /* enum devlink_trap_type */ ++ DEVLINK_ATTR_TRAP_TYPE, /* u8 */ ++ DEVLINK_ATTR_TRAP_GENERIC, /* flag */ ++ DEVLINK_ATTR_TRAP_METADATA, /* nested */ ++ DEVLINK_ATTR_TRAP_GROUP_NAME, /* string */ ++ + /* add new attributes above here, update the policy in devlink.c */ + + __DEVLINK_ATTR_MAX, +diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h +index 04f763cf53029..31fc51bdedb3c 100644 +--- a/include/uapi/linux/if_bridge.h ++++ b/include/uapi/linux/if_bridge.h +@@ -237,6 +237,7 @@ struct br_mdb_entry { + #define MDB_PERMANENT 1 + __u8 state; + #define MDB_FLAGS_OFFLOAD (1 << 0) ++#define MDB_FLAGS_FAST_LEAVE (1 << 1) + __u8 flags; + __u16 vid; + struct { +-- +2.25.4 + diff --git a/SOURCES/0002-Update-kernel-headers.patch b/SOURCES/0002-Update-kernel-headers.patch new file mode 100644 index 0000000..3ffe6a3 --- /dev/null +++ b/SOURCES/0002-Update-kernel-headers.patch @@ -0,0 +1,140 @@ +From 864c5a906ccfe205f886aa4bfb69f738a9a4fb45 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 16 Apr 2020 12:41:49 +0200 +Subject: [PATCH] Update kernel headers + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1770671 +Upstream Status: iproute2.git commit 17a948c80af57 + +commit 17a948c80af57da2fa86a8e34153f755f86e9c9c +Author: David Ahern +Date: Sat Nov 2 07:43:01 2019 -0700 + + Update kernel headers + + Update kernel headers to commit: + c23fcbbc6aa4 ("tc-testing: added tests with cookie for conntrack TC action") + + Signed-off-by: David Ahern +--- + include/uapi/linux/bpf.h | 28 +++++++++++++++++++++++++++- + include/uapi/linux/pkt_cls.h | 5 +++++ + include/uapi/linux/tcp.h | 10 +++++++++- + include/uapi/linux/tipc.h | 1 + + 4 files changed, 42 insertions(+), 2 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 79701d3e66f0b..3e195ff43fa01 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -413,6 +413,7 @@ union bpf_attr { + __u32 line_info_rec_size; /* userspace bpf_line_info size */ + __aligned_u64 line_info; /* line info */ + __u32 line_info_cnt; /* number of bpf_line_info records */ ++ __u32 attach_btf_id; /* in-kernel BTF type id to attach to */ + }; + + struct { /* anonymous struct used by BPF_OBJ_* commands */ +@@ -2741,6 +2742,30 @@ union bpf_attr { + * **-EOPNOTSUPP** kernel configuration does not enable SYN cookies + * + * **-EPROTONOSUPPORT** IP packet version is not 4 or 6 ++ * ++ * int bpf_skb_output(void *ctx, struct bpf_map *map, u64 flags, void *data, u64 size) ++ * Description ++ * Write raw *data* blob into a special BPF perf event held by ++ * *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf ++ * event must have the following attributes: **PERF_SAMPLE_RAW** ++ * as **sample_type**, **PERF_TYPE_SOFTWARE** as **type**, and ++ * **PERF_COUNT_SW_BPF_OUTPUT** as **config**. ++ * ++ * The *flags* are used to indicate the index in *map* for which ++ * the value must be put, masked with **BPF_F_INDEX_MASK**. ++ * Alternatively, *flags* can be set to **BPF_F_CURRENT_CPU** ++ * to indicate that the index of the current CPU core should be ++ * used. ++ * ++ * The value to write, of *size*, is passed through eBPF stack and ++ * pointed by *data*. ++ * ++ * *ctx* is a pointer to in-kernel struct sk_buff. ++ * ++ * This helper is similar to **bpf_perf_event_output**\ () but ++ * restricted to raw_tracepoint bpf programs. ++ * Return ++ * 0 on success, or a negative error in case of failure. + */ + #define __BPF_FUNC_MAPPER(FN) \ + FN(unspec), \ +@@ -2853,7 +2878,8 @@ union bpf_attr { + FN(sk_storage_get), \ + FN(sk_storage_delete), \ + FN(send_signal), \ +- FN(tcp_gen_syncookie), ++ FN(tcp_gen_syncookie), \ ++ FN(skb_output), + + /* integer value in 'imm' field of BPF_CALL instruction selects which helper + * function eBPF program intends to call +diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h +index b057aeeb63386..0a9ab625cba7b 100644 +--- a/include/uapi/linux/pkt_cls.h ++++ b/include/uapi/linux/pkt_cls.h +@@ -16,9 +16,14 @@ enum { + TCA_ACT_STATS, + TCA_ACT_PAD, + TCA_ACT_COOKIE, ++ TCA_ACT_FLAGS, + __TCA_ACT_MAX + }; + ++#define TCA_ACT_FLAGS_NO_PERCPU_STATS 1 /* Don't use percpu allocator for ++ * actions stats. ++ */ ++ + #define TCA_ACT_MAX __TCA_ACT_MAX + #define TCA_OLD_COMPAT (TCA_ACT_MAX+1) + #define TCA_ACT_MAX_PRIO 32 +diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h +index 3fd9b29146b17..acb15ca8558c0 100644 +--- a/include/uapi/linux/tcp.h ++++ b/include/uapi/linux/tcp.h +@@ -155,6 +155,14 @@ enum { + TCP_QUEUES_NR, + }; + ++/* why fastopen failed from client perspective */ ++enum tcp_fastopen_client_fail { ++ TFO_STATUS_UNSPEC, /* catch-all */ ++ TFO_COOKIE_UNAVAILABLE, /* if not in TFO_CLIENT_NO_COOKIE mode */ ++ TFO_DATA_NOT_ACKED, /* SYN-ACK did not ack SYN data */ ++ TFO_SYN_RETRANSMITTED, /* SYN-ACK did not ack SYN data after timeout */ ++}; ++ + /* for TCP_INFO socket option */ + #define TCPI_OPT_TIMESTAMPS 1 + #define TCPI_OPT_SACK 2 +@@ -211,7 +219,7 @@ struct tcp_info { + __u8 tcpi_backoff; + __u8 tcpi_options; + __u8 tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; +- __u8 tcpi_delivery_rate_app_limited:1; ++ __u8 tcpi_delivery_rate_app_limited:1, tcpi_fastopen_client_fail:2; + + __u32 tcpi_rto; + __u32 tcpi_ato; +diff --git a/include/uapi/linux/tipc.h b/include/uapi/linux/tipc.h +index e16cb4e2af587..0f6f28b2e3010 100644 +--- a/include/uapi/linux/tipc.h ++++ b/include/uapi/linux/tipc.h +@@ -191,6 +191,7 @@ struct sockaddr_tipc { + #define TIPC_GROUP_JOIN 135 /* Takes struct tipc_group_req* */ + #define TIPC_GROUP_LEAVE 136 /* No argument */ + #define TIPC_SOCK_RECVQ_USED 137 /* Default: none (read only) */ ++#define TIPC_NODELAY 138 /* Default: false */ + + /* + * Flag values +-- +2.25.4 + diff --git a/SOURCES/0003-tc-implement-support-for-action-flags.patch b/SOURCES/0003-tc-implement-support-for-action-flags.patch new file mode 100644 index 0000000..aef92b7 --- /dev/null +++ b/SOURCES/0003-tc-implement-support-for-action-flags.patch @@ -0,0 +1,116 @@ +From a3d12445422afa12a67a7cd121b7add89f6c7d67 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 16 Apr 2020 12:41:49 +0200 +Subject: [PATCH] tc: implement support for action flags + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1770671 +Upstream Status: iproute2.git commit fb2e033add073 + +commit fb2e033add073893dea71bb483353790fe8c5354 +Author: Vlad Buslov +Date: Wed Oct 30 16:20:40 2019 +0200 + + tc: implement support for action flags + + Implement setting and printing of action flags with single available flag + value "no_percpu" that translates to kernel UAPI TCA_ACT_FLAGS value + TCA_ACT_FLAGS_NO_PERCPU_STATS. Update man page with information regarding + usage of action flags. + + Example usage: + + # tc actions add action gact drop no_percpu + # sudo tc actions list action gact + total acts 1 + + action order 0: gact action drop + random type none pass val 0 + index 1 ref 1 bind 0 + no_percpu + + Signed-off-by: Vlad Buslov + Signed-off-by: David Ahern +--- + man/man8/tc-actions.8 | 14 ++++++++++++++ + tc/m_action.c | 19 +++++++++++++++++++ + 2 files changed, 33 insertions(+) + +diff --git a/man/man8/tc-actions.8 b/man/man8/tc-actions.8 +index f46166e3f6859..bee59f7247fae 100644 +--- a/man/man8/tc-actions.8 ++++ b/man/man8/tc-actions.8 +@@ -47,6 +47,8 @@ actions \- independently defined actions in tc + ] [ + .I COOKIESPEC + ] [ ++.I FLAGS ++] [ + .I CONTROL + ] + +@@ -71,6 +73,10 @@ ACTNAME + := + .BI cookie " COOKIE" + ++.I FLAGS ++:= ++.I no_percpu ++ + .I ACTDETAIL + := + .I ACTNAME ACTPARAMS +@@ -186,6 +192,14 @@ As such, it can be used as a correlating value for maintaining user state. + The value to be stored is completely arbitrary and does not require a specific + format. It is stored inside the action structure itself. + ++.TP ++.I FLAGS ++Action-specific flags. Currently, the only supported flag is ++.I no_percpu ++which indicates that action is expected to have minimal software data-path ++traffic and doesn't need to allocate stat counters with percpu allocator. ++This option is intended to be used by hardware-offloaded actions. ++ + .TP + .BI since " MSTIME" + When dumping large number of actions, a millisecond time-filter can be +diff --git a/tc/m_action.c b/tc/m_action.c +index bdc62720879c1..c46aeaafa8ebf 100644 +--- a/tc/m_action.c ++++ b/tc/m_action.c +@@ -249,6 +249,16 @@ done0: + addattr_l(n, MAX_MSG, TCA_ACT_COOKIE, + &act_ck, act_ck_len); + ++ if (*argv && strcmp(*argv, "no_percpu") == 0) { ++ struct nla_bitfield32 flags = ++ { TCA_ACT_FLAGS_NO_PERCPU_STATS, ++ TCA_ACT_FLAGS_NO_PERCPU_STATS }; ++ ++ addattr_l(n, MAX_MSG, TCA_ACT_FLAGS, &flags, ++ sizeof(struct nla_bitfield32)); ++ NEXT_ARG_FWD(); ++ } ++ + addattr_nest_end(n, tail); + ok++; + } +@@ -317,6 +327,15 @@ static int tc_print_one_action(FILE *f, struct rtattr *arg) + strsz, b1, sizeof(b1))); + print_string(PRINT_FP, NULL, "%s", _SL_); + } ++ if (tb[TCA_ACT_FLAGS]) { ++ struct nla_bitfield32 *flags = RTA_DATA(tb[TCA_ACT_FLAGS]); ++ ++ if (flags->selector & TCA_ACT_FLAGS_NO_PERCPU_STATS) ++ print_bool(PRINT_ANY, "no_percpu", "\tno_percpu", ++ flags->value & ++ TCA_ACT_FLAGS_NO_PERCPU_STATS); ++ print_string(PRINT_FP, NULL, "%s", _SL_); ++ } + + return 0; + } +-- +2.25.4 + diff --git a/SOURCES/0004-man-rdma-statistic-Add-filter-description.patch b/SOURCES/0004-man-rdma-statistic-Add-filter-description.patch new file mode 100644 index 0000000..9b805b9 --- /dev/null +++ b/SOURCES/0004-man-rdma-statistic-Add-filter-description.patch @@ -0,0 +1,110 @@ +From f0596659bb2ba71bbe6ec80df9d54ea02775f40f Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 23 Apr 2020 12:47:12 +0200 +Subject: [PATCH] man: rdma-statistic: Add filter description + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1786565 +Upstream Status: iproute2.git commit 31824e2299bf5 + +commit 31824e2299bf5dc609026436db629b0c25cc1a10 +Author: Andrea Claudi +Date: Fri Feb 28 18:36:25 2020 +0100 + + man: rdma-statistic: Add filter description + + Add description for filters on rdma statistics show command. + Also add a filter description on the help message of the command. + Additionally, fix some whitespace issue in the man page. + + Reported-by: Zhaojuan Guo + Signed-off-by: Andrea Claudi + Signed-off-by: Stephen Hemminger +--- + man/man8/rdma-statistic.8 | 16 ++++++++++++---- + rdma/stat.c | 1 + + 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/man/man8/rdma-statistic.8 b/man/man8/rdma-statistic.8 +index dea6ff24b499b..cd85ca46993a0 100644 +--- a/man/man8/rdma-statistic.8 ++++ b/man/man8/rdma-statistic.8 +@@ -9,7 +9,7 @@ rdma-statistic \- RDMA statistic counter configuration + .B rdma + .RI "[ " OPTIONS " ]" + .B statistic +-.RI " { " COMMAND " | " ++.RI "{ " COMMAND " | " + .BR help " }" + .sp + +@@ -23,6 +23,7 @@ rdma-statistic \- RDMA statistic counter configuration + .RI "[ " OBJECT " ]" + .B show link + .RI "[ " DEV/PORT_INDX " ]" ++.RI "[ " FILTER_NAME " " FILTER_VALUE " ]" + + .ti -8 + .B rdma statistic +@@ -34,7 +35,7 @@ rdma-statistic \- RDMA statistic counter configuration + .IR OBJECT + .B set + .IR COUNTER_SCOPE +-.RI "[ " DEV/PORT_INDEX "]" ++.RI "[ " DEV/PORT_INDEX " ]" + .B auto + .RI "{ " CRITERIA " | " + .BR off " }" +@@ -44,7 +45,7 @@ rdma-statistic \- RDMA statistic counter configuration + .IR OBJECT + .B bind + .IR COUNTER_SCOPE +-.RI "[ " DEV/PORT_INDEX "]" ++.RI "[ " DEV/PORT_INDEX " ]" + .RI "[ " OBJECT-ID " ]" + .RI "[ " COUNTER-ID " ]" + +@@ -53,7 +54,7 @@ rdma-statistic \- RDMA statistic counter configuration + .IR OBJECT + .B unbind + .IR COUNTER_SCOPE +-.RI "[ " DEV/PORT_INDEX "]" ++.RI "[ " DEV/PORT_INDEX " ]" + .RI "[ " COUNTER-ID " ]" + .RI "[ " OBJECT-ID " ]" + +@@ -69,6 +70,10 @@ rdma-statistic \- RDMA statistic counter configuration + .IR CRITERIA " := " + .RB "{ " type " }" + ++.ti -8 ++.IR FILTER_NAME " := " ++.RB "{ " cntn " | " lqpn " | " pid " }" ++ + .SH "DESCRIPTION" + .SS rdma statistic [object] show - Queries the specified RDMA device for RDMA and driver-specific statistics. Show the default hw counters if object is not specified + +@@ -79,6 +84,9 @@ rdma-statistic \- RDMA statistic counter configuration + .I "PORT_INDEX" + - specifies counters on this RDMA port to show. + ++.I "FILTER_NAME ++- specifies a filter to show only the results matching it. ++ + .SS rdma statistic set - configure counter statistic auto-mode for a specific device/port + In auto mode all objects belong to one category are bind automatically to a single counter set. + +diff --git a/rdma/stat.c b/rdma/stat.c +index ef0bbcf147a70..cd99b7ace73fc 100644 +--- a/rdma/stat.c ++++ b/rdma/stat.c +@@ -22,6 +22,7 @@ static int stat_help(struct rd *rd) + pr_out("where OBJECT: = { qp }\n"); + pr_out(" CRITERIA : = { type }\n"); + pr_out(" COUNTER_SCOPE: = { link | dev }\n"); ++ pr_out(" FILTER_NAME: = { cntn | lqpn | pid }\n"); + pr_out("Examples:\n"); + pr_out(" %s statistic qp show\n", rd->filename); + pr_out(" %s statistic qp show link mlx5_2/1\n", rd->filename); +-- +2.25.4 + diff --git a/SOURCES/0005-man-rdma.8-Add-missing-resource-subcommand-descripti.patch b/SOURCES/0005-man-rdma.8-Add-missing-resource-subcommand-descripti.patch new file mode 100644 index 0000000..2a64a79 --- /dev/null +++ b/SOURCES/0005-man-rdma.8-Add-missing-resource-subcommand-descripti.patch @@ -0,0 +1,51 @@ +From 44362b42a40ed0f3a3598f55318ed4b0c9f8eb94 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 23 Apr 2020 12:49:03 +0200 +Subject: [PATCH] man: rdma.8: Add missing resource subcommand description + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1786576 +Upstream Status: iproute2.git commit 8f1c9d4a3c0d4 + +commit 8f1c9d4a3c0d4e720026b942c922372b3c12e110 +Author: Andrea Claudi +Date: Fri Feb 28 18:36:24 2020 +0100 + + man: rdma.8: Add missing resource subcommand description + + Add resource subcommand in the OBJECT section and a short + description for it. + + Reported-by: Zhaojuan Guo + Signed-off-by: Andrea Claudi + Signed-off-by: Stephen Hemminger +--- + man/man8/rdma.8 | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/man/man8/rdma.8 b/man/man8/rdma.8 +index ef29b1c633644..221bf3343bf4c 100644 +--- a/man/man8/rdma.8 ++++ b/man/man8/rdma.8 +@@ -19,7 +19,7 @@ rdma \- RDMA tool + + .ti -8 + .IR OBJECT " := { " +-.BR dev " | " link " | " system " | " statistic " }" ++.BR dev " | " link " | " resource " | " system " | " statistic " }" + .sp + + .ti -8 +@@ -70,6 +70,10 @@ Generate JSON output. + .B link + - RDMA port related. + ++.TP ++.B resource ++- RDMA resource configuration. ++ + .TP + .B sys + - RDMA subsystem related. +-- +2.25.4 + diff --git a/SOURCES/0006-ip-xfrm-Fix-help-messages.patch b/SOURCES/0006-ip-xfrm-Fix-help-messages.patch new file mode 100644 index 0000000..11858c1 --- /dev/null +++ b/SOURCES/0006-ip-xfrm-Fix-help-messages.patch @@ -0,0 +1,108 @@ +From 028ce3bafd9c8415a0cd72ff135f9498d833db21 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Wed, 15 Apr 2020 19:09:48 +0200 +Subject: [PATCH] ip-xfrm: Fix help messages + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1796045 +Upstream Status: iproute2.git commit 38dd041bfe773 + +commit 38dd041bfe773e481ebf9c8250e49c665af2e215 +Author: Andrea Claudi +Date: Wed Jan 29 15:56:40 2020 +0100 + + ip-xfrm: Fix help messages + + After commit 8589eb4efdf2a ("treewide: refactor help messages") help + messages for xfrm state and policy are broken, printing many times the + same protocol in UPSPEC section: + + $ ip xfrm state help + [...] + UPSPEC := proto { { tcp | tcp | tcp | tcp } [ sport PORT ] [ dport PORT ] | + { icmp | icmp | icmp } [ type NUMBER ] [ code NUMBER ] | + gre [ key { DOTTED-QUAD | NUMBER } ] | PROTO } + + This happens because strxf_proto function is non-reentrant and gets called + multiple times in the same fprintf instruction. + + This commit fix the issue avoiding calls to strxf_proto() with a constant + param, just hardcoding strings for protocol names. + + Fixes: 8589eb4efdf2a ("treewide: refactor help messages") + Signed-off-by: Andrea Claudi + Signed-off-by: Stephen Hemminger +--- + ip/xfrm_policy.c | 21 +++------------------ + ip/xfrm_state.c | 24 +++--------------------- + 2 files changed, 6 insertions(+), 39 deletions(-) + +diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c +index 7c0233c182902..d3c706d3225f0 100644 +--- a/ip/xfrm_policy.c ++++ b/ip/xfrm_policy.c +@@ -66,24 +66,9 @@ static void usage(void) + "Usage: ip xfrm policy count\n" + "Usage: ip xfrm policy set [ hthresh4 LBITS RBITS ] [ hthresh6 LBITS RBITS ]\n" + "SELECTOR := [ src ADDR[/PLEN] ] [ dst ADDR[/PLEN] ] [ dev DEV ] [ UPSPEC ]\n" +- "UPSPEC := proto { { "); +- fprintf(stderr, "%s | %s | %s | %s } ", +- strxf_proto(IPPROTO_TCP), +- strxf_proto(IPPROTO_UDP), +- strxf_proto(IPPROTO_SCTP), +- strxf_proto(IPPROTO_DCCP)); +- fprintf(stderr, +- "[ sport PORT ] [ dport PORT ] |\n" +- " { %s | %s | %s } ", +- strxf_proto(IPPROTO_ICMP), +- strxf_proto(IPPROTO_ICMPV6), +- strxf_proto(IPPROTO_MH)); +- fprintf(stderr, +- "[ type NUMBER ] [ code NUMBER ] |\n" +- " %s", +- strxf_proto(IPPROTO_GRE)); +- fprintf(stderr, +- " [ key { DOTTED-QUAD | NUMBER } ] | PROTO }\n" ++ "UPSPEC := proto { { tcp | udp | sctp | dccp } [ sport PORT ] [ dport PORT ] |\n" ++ " { icmp | ipv6-icmp | mobility-header } [ type NUMBER ] [ code NUMBER ] |\n" ++ " gre [ key { DOTTED-QUAD | NUMBER } ] | PROTO }\n" + "DIR := in | out | fwd\n" + "PTYPE := main | sub\n" + "ACTION := allow | block\n" +diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c +index b03ccc5807e90..7b413cd9b9a22 100644 +--- a/ip/xfrm_state.c ++++ b/ip/xfrm_state.c +@@ -106,27 +106,9 @@ static void usage(void) + "EXTRA-FLAG-LIST := [ EXTRA-FLAG-LIST ] EXTRA-FLAG\n" + "EXTRA-FLAG := dont-encap-dscp\n" + "SELECTOR := [ src ADDR[/PLEN] ] [ dst ADDR[/PLEN] ] [ dev DEV ] [ UPSPEC ]\n" +- "UPSPEC := proto { { "); +- fprintf(stderr, +- "%s | %s | %s | %s", +- strxf_proto(IPPROTO_TCP), +- strxf_proto(IPPROTO_UDP), +- strxf_proto(IPPROTO_SCTP), +- strxf_proto(IPPROTO_DCCP)); +- fprintf(stderr, +- " } [ sport PORT ] [ dport PORT ] |\n" +- " { "); +- fprintf(stderr, +- "%s | %s | %s", +- strxf_proto(IPPROTO_ICMP), +- strxf_proto(IPPROTO_ICMPV6), +- strxf_proto(IPPROTO_MH)); +- fprintf(stderr, +- " } [ type NUMBER ] [ code NUMBER ] |\n"); +- fprintf(stderr, +- " %s", strxf_proto(IPPROTO_GRE)); +- fprintf(stderr, +- " [ key { DOTTED-QUAD | NUMBER } ] | PROTO }\n" ++ "UPSPEC := proto { { tcp | udp | sctp | dccp } [ sport PORT ] [ dport PORT ] |\n" ++ " { icmp | ipv6-icmp | mobility-header } [ type NUMBER ] [ code NUMBER ] |\n" ++ " gre [ key { DOTTED-QUAD | NUMBER } ] | PROTO }\n" + "LIMIT-LIST := [ LIMIT-LIST ] limit LIMIT\n" + "LIMIT := { time-soft | time-hard | time-use-soft | time-use-hard } SECONDS |\n" + " { byte-soft | byte-hard } SIZE | { packet-soft | packet-hard } COUNT\n" +-- +2.25.4 + diff --git a/SOURCES/0007-xfrm-not-try-to-delete-ipcomp-states-when-using-dele.patch b/SOURCES/0007-xfrm-not-try-to-delete-ipcomp-states-when-using-dele.patch new file mode 100644 index 0000000..66d479f --- /dev/null +++ b/SOURCES/0007-xfrm-not-try-to-delete-ipcomp-states-when-using-dele.patch @@ -0,0 +1,55 @@ +From 7c1351ea866ec811ade4452b5f1791b34b0effe3 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 16 Apr 2020 12:10:23 +0200 +Subject: [PATCH] xfrm: not try to delete ipcomp states when using deleteall + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1808634 +Upstream Status: iproute2.git commit f9d696cf414c2 + +commit f9d696cf414c2c475764aa3b29cf288350f1e21f +Author: Xin Long +Date: Mon Feb 24 09:57:01 2020 -0500 + + xfrm: not try to delete ipcomp states when using deleteall + + In kernel space, ipcomp(sub) states used by main states are not + allowed to be deleted by users, they would be freed only when + all main states are destroyed and no one uses them. + + In user space, ip xfrm sta deleteall doesn't filter these ipcomp + states out, and it causes errors: + + # ip xfrm state add src 192.168.0.1 dst 192.168.0.2 spi 0x1000 \ + proto comp comp deflate mode tunnel sel src 192.168.0.1 dst \ + 192.168.0.2 proto gre + # ip xfrm sta deleteall + Failed to send delete-all request + : Operation not permitted + + This patch is to fix it by filtering ipcomp states with a check + xsinfo->id.proto == IPPROTO_IPIP. + + Fixes: c7699875bee0 ("Import patch ipxfrm-20040707_2.diff") + Signed-off-by: Xin Long + Signed-off-by: Stephen Hemminger +--- + ip/xfrm_state.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c +index 7b413cd9b9a22..d014444e9af4f 100644 +--- a/ip/xfrm_state.c ++++ b/ip/xfrm_state.c +@@ -1131,6 +1131,9 @@ static int xfrm_state_keep(struct nlmsghdr *n, void *arg) + if (!xfrm_state_filter_match(xsinfo)) + return 0; + ++ if (xsinfo->id.proto == IPPROTO_IPIP) ++ return 0; ++ + if (xb->offset > xb->size) { + fprintf(stderr, "State buffer overflow\n"); + return -1; +-- +2.25.4 + diff --git a/SOURCES/0008-man-ip.8-Add-missing-vrf-subcommand-description.patch b/SOURCES/0008-man-ip.8-Add-missing-vrf-subcommand-description.patch new file mode 100644 index 0000000..0a36572 --- /dev/null +++ b/SOURCES/0008-man-ip.8-Add-missing-vrf-subcommand-description.patch @@ -0,0 +1,59 @@ +From 310becad3223411bc26e0401a838f2a7063406f3 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 23 Apr 2020 18:56:14 +0200 +Subject: [PATCH] man: ip.8: Add missing vrf subcommand description + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1780010 +Upstream Status: iproute2.git commit 229bb886a3c44 + +commit 229bb886a3c4444521eca16c7ab74a539aaf9cb4 +Author: Andrea Claudi +Date: Thu Feb 27 17:45:43 2020 +0100 + + man: ip.8: Add missing vrf subcommand description + + Add description to the vrf subcommand and a reference to the + dedicated man page. + + Signed-off-by: Andrea Claudi + Reviewed-by: David Ahern + Signed-off-by: Stephen Hemminger +--- + man/man8/ip.8 | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/man/man8/ip.8 b/man/man8/ip.8 +index e2bda2a2ea904..c425aaf1d506e 100644 +--- a/man/man8/ip.8 ++++ b/man/man8/ip.8 +@@ -22,7 +22,7 @@ ip \- show / manipulate routing, network devices, interfaces and tunnels + .BR link " | " address " | " addrlabel " | " route " | " rule " | " neigh " | "\ + ntable " | " tunnel " | " tuntap " | " maddress " | " mroute " | " mrule " | "\ + monitor " | " xfrm " | " netns " | " l2tp " | " tcp_metrics " | " token " | "\ +- macsec " }" ++ macsec " | " vrf " }" + .sp + + .ti -8 +@@ -312,6 +312,10 @@ readability. + .B tuntap + - manage TUN/TAP devices. + ++.TP ++.B vrf ++- manage virtual routing and forwarding devices. ++ + .TP + .B xfrm + - manage IPSec policies. +@@ -411,6 +415,7 @@ was written by Alexey N. Kuznetsov and added in Linux 2.2. + .BR ip-tcp_metrics (8), + .BR ip-token (8), + .BR ip-tunnel (8), ++.BR ip-vrf (8), + .BR ip-xfrm (8) + .br + .RB "IP Command reference " ip-cref.ps +-- +2.25.4 + diff --git a/SOURCES/0009-nstat-print-useful-error-messages-in-abort-cases.patch b/SOURCES/0009-nstat-print-useful-error-messages-in-abort-cases.patch new file mode 100644 index 0000000..8e439d5 --- /dev/null +++ b/SOURCES/0009-nstat-print-useful-error-messages-in-abort-cases.patch @@ -0,0 +1,122 @@ +From 5723280683d940b33647b8dc92a3aa3b1a9a5466 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 30 Apr 2020 12:20:17 +0200 +Subject: [PATCH] nstat: print useful error messages in abort() cases +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1824896 +Upstream Status: iproute2.git commit 2c7056ac26412 + +commit 2c7056ac26412fe99443a283f0c1261cb81ccea2 +Author: Andrea Claudi +Date: Mon Feb 17 14:46:18 2020 +0100 + + nstat: print useful error messages in abort() cases + + When nstat temporary file is corrupted or in some other corner cases, + nstat use abort() to stop its execution. This can puzzle some users, + wondering what is the reason for the crash. + + This commit replaces abort() with some meaningful error messages and exit() + + Reported-by: Renaud Métrich + Signed-off-by: Andrea Claudi + Signed-off-by: Stephen Hemminger +--- + misc/nstat.c | 47 +++++++++++++++++++++++++++++++++-------------- + 1 file changed, 33 insertions(+), 14 deletions(-) + +diff --git a/misc/nstat.c b/misc/nstat.c +index 23113b223b22d..425e75ef461ec 100644 +--- a/misc/nstat.c ++++ b/misc/nstat.c +@@ -142,14 +142,19 @@ static void load_good_table(FILE *fp) + } + /* idbuf is as big as buf, so this is safe */ + nr = sscanf(buf, "%s%llu%lg", idbuf, &val, &rate); +- if (nr < 2) +- abort(); ++ if (nr < 2) { ++ fprintf(stderr, "%s:%d: error parsing history file\n", ++ __FILE__, __LINE__); ++ exit(-2); ++ } + if (nr < 3) + rate = 0; + if (useless_number(idbuf)) + continue; +- if ((n = malloc(sizeof(*n))) == NULL) +- abort(); ++ if ((n = malloc(sizeof(*n))) == NULL) { ++ perror("nstat: malloc"); ++ exit(-1); ++ } + n->id = strdup(idbuf); + n->val = val; + n->rate = rate; +@@ -190,8 +195,11 @@ static void load_ugly_table(FILE *fp) + int count1, count2, skip = 0; + + p = strchr(buf, ':'); +- if (!p) +- abort(); ++ if (!p) { ++ fprintf(stderr, "%s:%d: error parsing history file\n", ++ __FILE__, __LINE__); ++ exit(-2); ++ } + count1 = count_spaces(buf); + *p = 0; + idbuf[0] = 0; +@@ -211,8 +219,10 @@ static void load_ugly_table(FILE *fp) + strncat(idbuf, p, sizeof(idbuf) - off - 1); + } + n = malloc(sizeof(*n)); +- if (!n) +- abort(); ++ if (!n) { ++ perror("nstat: malloc"); ++ exit(-1); ++ } + n->id = strdup(idbuf); + n->rate = 0; + n->next = db; +@@ -221,18 +231,27 @@ static void load_ugly_table(FILE *fp) + } + n = db; + nread = getline(&buf, &buflen, fp); +- if (nread == -1) +- abort(); ++ if (nread == -1) { ++ fprintf(stderr, "%s:%d: error parsing history file\n", ++ __FILE__, __LINE__); ++ exit(-2); ++ } + count2 = count_spaces(buf); + if (count2 > count1) + skip = count2 - count1; + do { + p = strrchr(buf, ' '); +- if (!p) +- abort(); ++ if (!p) { ++ fprintf(stderr, "%s:%d: error parsing history file\n", ++ __FILE__, __LINE__); ++ exit(-2); ++ } + *p = 0; +- if (sscanf(p+1, "%llu", &n->val) != 1) +- abort(); ++ if (sscanf(p+1, "%llu", &n->val) != 1) { ++ fprintf(stderr, "%s:%d: error parsing history file\n", ++ __FILE__, __LINE__); ++ exit(-2); ++ } + /* Trick to skip "dummy" trailing ICMP MIB in 2.4 */ + if (skip) + skip--; +-- +2.25.4 + diff --git a/SOURCES/0010-ip-link-xstats-fix-TX-IGMP-reports-string.patch b/SOURCES/0010-ip-link-xstats-fix-TX-IGMP-reports-string.patch new file mode 100644 index 0000000..0ab0707 --- /dev/null +++ b/SOURCES/0010-ip-link-xstats-fix-TX-IGMP-reports-string.patch @@ -0,0 +1,40 @@ +From 28a6ef808bd5c196c2259f7841a97c1ba703479d Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 30 Apr 2020 12:32:41 +0200 +Subject: [PATCH] ip link: xstats: fix TX IGMP reports string + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1796041 +Upstream Status: iproute2.git commit 5cdeb77cd6ec2 + +commit 5cdeb77cd6ec26f0a7103dfb21494a6a43903206 +Author: Andrea Claudi +Date: Wed Jan 29 15:31:11 2020 +0100 + + ip link: xstats: fix TX IGMP reports string + + This restore the string format we have before jsonification, adding a + missing space between v2 and v3 on TX IGMP reports string. + + Fixes: a9bc23a79227a ("ip: bridge: add xstats json support") + Signed-off-by: Andrea Claudi + Signed-off-by: Stephen Hemminger +--- + ip/iplink_bridge.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c +index 06f736d4dc710..868ea6e266ebe 100644 +--- a/ip/iplink_bridge.c ++++ b/ip/iplink_bridge.c +@@ -742,7 +742,7 @@ static void bridge_print_stats_attr(struct rtattr *attr, int ifindex) + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", + mstats->igmp_v1reports[BR_MCAST_DIR_TX]); +- print_u64(PRINT_ANY, "tx_v2", "v2 %llu", ++ print_u64(PRINT_ANY, "tx_v2", "v2 %llu ", + mstats->igmp_v2reports[BR_MCAST_DIR_TX]); + print_u64(PRINT_ANY, "tx_v3", "v3 %llu\n", + mstats->igmp_v3reports[BR_MCAST_DIR_TX]); +-- +2.25.4 + diff --git a/SOURCES/0011-ip-fix-ip-route-show-json-output-for-multipath-nexth.patch b/SOURCES/0011-ip-fix-ip-route-show-json-output-for-multipath-nexth.patch new file mode 100644 index 0000000..c82b769 --- /dev/null +++ b/SOURCES/0011-ip-fix-ip-route-show-json-output-for-multipath-nexth.patch @@ -0,0 +1,148 @@ +From 65d5e933e5162c3464857ee233a2f20e778ee1b6 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 30 Apr 2020 12:35:47 +0200 +Subject: [PATCH] ip: fix ip route show json output for multipath nexthops + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1738633 +Upstream Status: iproute2.git commit 4ecefff3cf250 + +commit 4ecefff3cf250c1e4499dff14c80ed38bec6d7de +Author: Julien Fortin +Date: Thu Sep 26 17:29:34 2019 +0200 + + ip: fix ip route show json output for multipath nexthops + + print_rta_multipath doesn't support JSON output: + + { + "dst":"27.0.0.13", + "protocol":"bgp", + "metric":20, + "flags":[], + "gateway":"169.254.0.1"dev uplink-1 weight 1 , + "flags":["onlink"], + "gateway":"169.254.0.1"dev uplink-2 weight 1 , + "flags":["onlink"] + }, + + since RTA_MULTIPATH has nested objects we should print them + in a json array. + + With the path we have the following output: + + { + "flags": [], + "dst": "36.0.0.13", + "protocol": "bgp", + "metric": 20, + "nexthops": [ + { + "weight": 1, + "flags": [ + "onlink" + ], + "gateway": "169.254.0.1", + "dev": "uplink-1" + }, + { + "weight": 1, + "flags": [ + "onlink" + ], + "gateway": "169.254.0.1", + "dev": "uplink-2" + } + ] + } + + Fixes: 663c3cb23103f4 ("iproute: implement JSON and color output") + + Signed-off-by: Julien Fortin + Signed-off-by: David Ahern +--- + ip/iproute.c | 46 ++++++++++++++++++++++++++++------------------ + 1 file changed, 28 insertions(+), 18 deletions(-) + +diff --git a/ip/iproute.c b/ip/iproute.c +index a453385113cb9..32bb52df250c2 100644 +--- a/ip/iproute.c ++++ b/ip/iproute.c +@@ -649,24 +649,26 @@ static void print_rta_multipath(FILE *fp, const struct rtmsg *r, + int len = RTA_PAYLOAD(rta); + int first = 1; + ++ open_json_array(PRINT_JSON, "nexthops"); ++ + while (len >= sizeof(*nh)) { + struct rtattr *tb[RTA_MAX + 1]; + + if (nh->rtnh_len > len) + break; + +- if (!is_json_context()) { +- if ((r->rtm_flags & RTM_F_CLONED) && +- r->rtm_type == RTN_MULTICAST) { +- if (first) { +- fprintf(fp, "Oifs: "); +- first = 0; +- } else { +- fprintf(fp, " "); +- } +- } else +- fprintf(fp, "%s\tnexthop ", _SL_); +- } ++ open_json_object(NULL); ++ ++ if ((r->rtm_flags & RTM_F_CLONED) && ++ r->rtm_type == RTN_MULTICAST) { ++ if (first) { ++ print_string(PRINT_FP, NULL, "Oifs: ", NULL); ++ first = 0; ++ } else { ++ print_string(PRINT_FP, NULL, " ", NULL); ++ } ++ } else ++ print_string(PRINT_FP, NULL, "%s\tnexthop ", _SL_); + + if (nh->rtnh_len > sizeof(*nh)) { + parse_rtattr(tb, RTA_MAX, RTNH_DATA(nh), +@@ -689,22 +691,30 @@ static void print_rta_multipath(FILE *fp, const struct rtmsg *r, + + if ((r->rtm_flags & RTM_F_CLONED) && + r->rtm_type == RTN_MULTICAST) { +- fprintf(fp, "%s", ll_index_to_name(nh->rtnh_ifindex)); ++ print_string(PRINT_ANY, "dev", ++ "%s", ll_index_to_name(nh->rtnh_ifindex)); ++ + if (nh->rtnh_hops != 1) +- fprintf(fp, "(ttl>%d)", nh->rtnh_hops); +- fprintf(fp, " "); ++ print_int(PRINT_ANY, "ttl", "(ttl>%d)", nh->rtnh_hops); ++ ++ print_string(PRINT_FP, NULL, " ", NULL); + } else { +- fprintf(fp, "dev %s ", ll_index_to_name(nh->rtnh_ifindex)); ++ print_string(PRINT_ANY, "dev", ++ "dev %s ", ll_index_to_name(nh->rtnh_ifindex)); ++ + if (r->rtm_family != AF_MPLS) +- fprintf(fp, "weight %d ", +- nh->rtnh_hops+1); ++ print_int(PRINT_ANY, "weight", ++ "weight %d ", nh->rtnh_hops + 1); + } + + print_rt_flags(fp, nh->rtnh_flags); + + len -= NLMSG_ALIGN(nh->rtnh_len); + nh = RTNH_NEXT(nh); ++ ++ close_json_object(); + } ++ close_json_array(PRINT_JSON, NULL); + } + + int print_route(struct nlmsghdr *n, void *arg) +-- +2.25.4 + diff --git a/SOURCES/0012-man-bridge.8-fix-bridge-link-show-description.patch b/SOURCES/0012-man-bridge.8-fix-bridge-link-show-description.patch new file mode 100644 index 0000000..7e0c378 --- /dev/null +++ b/SOURCES/0012-man-bridge.8-fix-bridge-link-show-description.patch @@ -0,0 +1,48 @@ +From 12bf930c542feeb9578d9320bc39a34365747127 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 30 Apr 2020 12:43:30 +0200 +Subject: [PATCH] man: bridge.8: fix bridge link show description + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1817571 +Upstream Status: iproute2.git commit 0641bed8a3c77 + +commit 0641bed8a3c779c37746c4d7be9e01a35e920841 +Author: Andrea Claudi +Date: Fri Mar 27 11:45:12 2020 +0100 + + man: bridge.8: fix bridge link show description + + When multiple bridges are present, 'bridge link show' diplays ports + for all bridges. Make this clear in the command description, and + point out the user to the ip command to display ports for a specific + bridge. + + Reported-by: Marc Muehlfeld + Signed-off-by: Andrea Claudi + Signed-off-by: Stephen Hemminger +--- + man/man8/bridge.8 | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/man/man8/bridge.8 b/man/man8/bridge.8 +index bb4fb521f8e57..d750e54a17b8b 100644 +--- a/man/man8/bridge.8 ++++ b/man/man8/bridge.8 +@@ -409,9 +409,12 @@ link setting is configured on the software bridge (default) + .BR "\-t" , " \-timestamp" + display current time when using monitor option. + +-.SS bridge link show - list bridge port configuration. ++.SS bridge link show - list ports configuration for all bridges. + +-This command displays the current bridge port configuration and flags. ++This command displays port configuration and flags for all bridges. ++ ++To display port configuration and flags for a specific bridge, use the ++"ip link show master " command. + + .SH bridge fdb - forwarding database management + +-- +2.25.4 + diff --git a/SOURCES/0013-xfrm-also-check-for-ipv6-state-in-xfrm_state_keep.patch b/SOURCES/0013-xfrm-also-check-for-ipv6-state-in-xfrm_state_keep.patch new file mode 100644 index 0000000..8d5b4b4 --- /dev/null +++ b/SOURCES/0013-xfrm-also-check-for-ipv6-state-in-xfrm_state_keep.patch @@ -0,0 +1,53 @@ +From 40dda2fc9fb2597996e443117df18995c58444a9 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 30 Apr 2020 12:46:30 +0200 +Subject: [PATCH] xfrm: also check for ipv6 state in xfrm_state_keep + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1828033 +Upstream Status: iproute2.git commit d27fc6390ce32 + +commit d27fc6390ce32ecdba6324e22b1c341791c5c63f +Author: Xin Long +Date: Mon Apr 27 15:14:24 2020 +0800 + + xfrm: also check for ipv6 state in xfrm_state_keep + + As commit f9d696cf414c ("xfrm: not try to delete ipcomp states when using + deleteall") does, this patch is to fix the same issue for ip6 state where + xsinfo->id.proto == IPPROTO_IPV6. + + # ip xfrm state add src 2000::1 dst 2000::2 spi 0x1000 \ + proto comp comp deflate mode tunnel sel src 2000::1 dst \ + 2000::2 proto gre + # ip xfrm sta deleteall + Failed to send delete-all request + : Operation not permitted + + Note that the xsinfo->proto in common states can never be IPPROTO_IPV6. + + Fixes: f9d696cf414c ("xfrm: not try to delete ipcomp states when using deleteall") + Reported-by: Xiumei Mu + Signed-off-by: Xin Long + Acked-by: Andrea Claudi + Signed-off-by: Stephen Hemminger +--- + ip/xfrm_state.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c +index d014444e9af4f..44f08ceed24dd 100644 +--- a/ip/xfrm_state.c ++++ b/ip/xfrm_state.c +@@ -1131,7 +1131,8 @@ static int xfrm_state_keep(struct nlmsghdr *n, void *arg) + if (!xfrm_state_filter_match(xsinfo)) + return 0; + +- if (xsinfo->id.proto == IPPROTO_IPIP) ++ if (xsinfo->id.proto == IPPROTO_IPIP || ++ xsinfo->id.proto == IPPROTO_IPV6) + return 0; + + if (xb->offset > xb->size) { +-- +2.25.4 + diff --git a/SOURCES/0014-Update-kernel-headers-and-import-udp.h.patch b/SOURCES/0014-Update-kernel-headers-and-import-udp.h.patch new file mode 100644 index 0000000..cef917b --- /dev/null +++ b/SOURCES/0014-Update-kernel-headers-and-import-udp.h.patch @@ -0,0 +1,115 @@ +From 90897540c719814eca34ce6b5b78b3bb76c4a43a Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Fri, 5 Jun 2020 15:42:49 +0200 +Subject: [PATCH] Update kernel headers and import udp.h + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1844045 +Upstream Status: iproute2.git commit 4df5ad933ca8c + +commit 4df5ad933ca8cebf23a4868061b28ab869e9b77a +Author: David Ahern +Date: Wed Jan 22 03:40:26 2020 +0000 + + Update kernel headers and import udp.h + + Update kernel headers to commit: + 4f2c17e0f332 ("Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next") + + and import udp.h for the next patch. + + Signed-off-by: David Ahern +--- + include/uapi/linux/hdlc/ioctl.h | 9 +++++++ + include/uapi/linux/if.h | 1 + + include/uapi/linux/udp.h | 47 +++++++++++++++++++++++++++++++++ + 3 files changed, 57 insertions(+) + create mode 100644 include/uapi/linux/udp.h + +diff --git a/include/uapi/linux/hdlc/ioctl.h b/include/uapi/linux/hdlc/ioctl.h +index 0fe4238e82462..b06341acab5ec 100644 +--- a/include/uapi/linux/hdlc/ioctl.h ++++ b/include/uapi/linux/hdlc/ioctl.h +@@ -79,6 +79,15 @@ typedef struct { + unsigned int timeout; + } cisco_proto; + ++typedef struct { ++ unsigned short dce; /* 1 for DCE (network side) operation */ ++ unsigned int modulo; /* modulo (8 = basic / 128 = extended) */ ++ unsigned int window; /* frame window size */ ++ unsigned int t1; /* timeout t1 */ ++ unsigned int t2; /* timeout t2 */ ++ unsigned int n2; /* frame retry counter */ ++} x25_hdlc_proto; ++ + /* PPP doesn't need any info now - supply length = 0 to ioctl */ + + #endif /* __ASSEMBLY__ */ +diff --git a/include/uapi/linux/if.h b/include/uapi/linux/if.h +index 495cdd2324428..626da393123b6 100644 +--- a/include/uapi/linux/if.h ++++ b/include/uapi/linux/if.h +@@ -210,6 +210,7 @@ struct if_settings { + fr_proto *fr; + fr_proto_pvc *fr_pvc; + fr_proto_pvc_info *fr_pvc_info; ++ x25_hdlc_proto *x25; + + /* interface settings */ + sync_serial_settings *sync; +diff --git a/include/uapi/linux/udp.h b/include/uapi/linux/udp.h +new file mode 100644 +index 0000000000000..d0a7223a0119c +--- /dev/null ++++ b/include/uapi/linux/udp.h +@@ -0,0 +1,47 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++/* ++ * INET An implementation of the TCP/IP protocol suite for the LINUX ++ * operating system. INET is implemented using the BSD Socket ++ * interface as the means of communication with the user level. ++ * ++ * Definitions for the UDP protocol. ++ * ++ * Version: @(#)udp.h 1.0.2 04/28/93 ++ * ++ * Author: Fred N. van Kempen, ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++#ifndef _LINUX_UDP_H ++#define _LINUX_UDP_H ++ ++#include ++ ++struct udphdr { ++ __be16 source; ++ __be16 dest; ++ __be16 len; ++ __sum16 check; ++}; ++ ++/* UDP socket options */ ++#define UDP_CORK 1 /* Never send partially complete segments */ ++#define UDP_ENCAP 100 /* Set the socket to accept encapsulated packets */ ++#define UDP_NO_CHECK6_TX 101 /* Disable sending checksum for UDP6X */ ++#define UDP_NO_CHECK6_RX 102 /* Disable accpeting checksum for UDP6 */ ++#define UDP_SEGMENT 103 /* Set GSO segmentation size */ ++#define UDP_GRO 104 /* This socket can receive UDP GRO packets */ ++ ++/* UDP encapsulation types */ ++#define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */ ++#define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */ ++#define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */ ++#define UDP_ENCAP_GTP0 4 /* GSM TS 09.60 */ ++#define UDP_ENCAP_GTP1U 5 /* 3GPP TS 29.060 */ ++#define UDP_ENCAP_RXRPC 6 ++#define TCP_ENCAP_ESPINTCP 7 /* Yikes, this is really xfrm encap types. */ ++ ++#endif /* _LINUX_UDP_H */ +-- +2.26.2 + diff --git a/SOURCES/0015-ip-xfrm-add-espintcp-encapsulation.patch b/SOURCES/0015-ip-xfrm-add-espintcp-encapsulation.patch new file mode 100644 index 0000000..d19a729 --- /dev/null +++ b/SOURCES/0015-ip-xfrm-add-espintcp-encapsulation.patch @@ -0,0 +1,110 @@ +From b0312111114ed805f84b1e96d73f468e3a372025 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Fri, 5 Jun 2020 15:42:49 +0200 +Subject: [PATCH] ip: xfrm: add espintcp encapsulation + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1844045 +Upstream Status: iproute2.git commit 22aec42679d57 + +commit 22aec42679d57b8e0aef864c4d45feadb727c3ce +Author: Sabrina Dubroca +Date: Sun Jan 19 11:32:09 2020 +0100 + + ip: xfrm: add espintcp encapsulation + + While at it, convert xfrm_xfrma_print and xfrm_encap_type_parse to use + the UAPI macros for encap_type as suggested by David Ahern, and add the + UAPI udp.h header (sync'd from ipsec-next to get the TCP_ENCAP_ESPINTCP + definition). + + Co-developed-by: Herbert Xu + Signed-off-by: Sabrina Dubroca + Signed-off-by: David Ahern +--- + ip/ipxfrm.c | 14 ++++++++++---- + ip/xfrm_state.c | 2 +- + man/man8/ip-xfrm.8 | 4 ++-- + 3 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c +index 32f560933a477..fec206abc1f03 100644 +--- a/ip/ipxfrm.c ++++ b/ip/ipxfrm.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + #include "utils.h" + #include "xfrm.h" +@@ -753,12 +754,15 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family, + + fprintf(fp, "type "); + switch (e->encap_type) { +- case 1: ++ case UDP_ENCAP_ESPINUDP_NON_IKE: + fprintf(fp, "espinudp-nonike "); + break; +- case 2: ++ case UDP_ENCAP_ESPINUDP: + fprintf(fp, "espinudp "); + break; ++ case TCP_ENCAP_ESPINTCP: ++ fprintf(fp, "espintcp "); ++ break; + default: + fprintf(fp, "%u ", e->encap_type); + break; +@@ -1208,9 +1212,11 @@ int xfrm_encap_type_parse(__u16 *type, int *argcp, char ***argvp) + char **argv = *argvp; + + if (strcmp(*argv, "espinudp-nonike") == 0) +- *type = 1; ++ *type = UDP_ENCAP_ESPINUDP_NON_IKE; + else if (strcmp(*argv, "espinudp") == 0) +- *type = 2; ++ *type = UDP_ENCAP_ESPINUDP; ++ else if (strcmp(*argv, "espintcp") == 0) ++ *type = TCP_ENCAP_ESPINTCP; + else + invarg("ENCAP-TYPE value is invalid", *argv); + +diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c +index 44f08ceed24dd..f4bf3356bb01f 100644 +--- a/ip/xfrm_state.c ++++ b/ip/xfrm_state.c +@@ -112,7 +112,7 @@ static void usage(void) + "LIMIT-LIST := [ LIMIT-LIST ] limit LIMIT\n" + "LIMIT := { time-soft | time-hard | time-use-soft | time-use-hard } SECONDS |\n" + " { byte-soft | byte-hard } SIZE | { packet-soft | packet-hard } COUNT\n" +- "ENCAP := { espinudp | espinudp-nonike } SPORT DPORT OADDR\n" ++ "ENCAP := { espinudp | espinudp-nonike | espintcp } SPORT DPORT OADDR\n" + "DIR := in | out\n"); + + exit(-1); +diff --git a/man/man8/ip-xfrm.8 b/man/man8/ip-xfrm.8 +index cfce1e40b7f7d..f99f30bb448a6 100644 +--- a/man/man8/ip-xfrm.8 ++++ b/man/man8/ip-xfrm.8 +@@ -207,7 +207,7 @@ ip-xfrm \- transform configuration + + .ti -8 + .IR ENCAP " :=" +-.RB "{ " espinudp " | " espinudp-nonike " }" ++.RB "{ " espinudp " | " espinudp-nonike " | " espintcp " }" + .IR SPORT " " DPORT " " OADDR + + .ti -8 +@@ -548,7 +548,7 @@ sets limits in seconds, bytes, or numbers of packets. + .TP + .I ENCAP + encapsulates packets with protocol +-.BR espinudp " or " espinudp-nonike "," ++.BR espinudp ", " espinudp-nonike ", or " espintcp "," + .RI "using source port " SPORT ", destination port " DPORT + .RI ", and original address " OADDR "." + +-- +2.26.2 + diff --git a/SOURCES/0016-Update-kernel-headers-and-import-mptcp.h.patch b/SOURCES/0016-Update-kernel-headers-and-import-mptcp.h.patch new file mode 100644 index 0000000..2d709bd --- /dev/null +++ b/SOURCES/0016-Update-kernel-headers-and-import-mptcp.h.patch @@ -0,0 +1,177 @@ +From 93f77d1e57c84093b91bc9227929cfb4a24534e9 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:25:47 +0200 +Subject: [PATCH] Update kernel headers and import mptcp.h + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: iproute2.git commit 02ade5a8ea1c2 +Conflicts: on bpf uapi due to missing commit b5a77cf70116f ("uapi: update bpf.h") + and on if_bridge uapi due to several unrelated missing changes. + +commit 02ade5a8ea1c23201a99d8cdf7e02a6ba90d7718 +Author: David Ahern +Date: Wed Apr 29 16:41:39 2020 +0000 + + Update kernel headers and import mptcp.h + + Update kernel headers to commit + 790ab249b55d ("net: ethernet: fec: Prevent MII event after MII_SPEED write") + + and import mptcp.h + + Signed-off-by: David Ahern +--- + include/uapi/linux/if.h | 1 + + include/uapi/linux/if_bridge.h | 1 + + include/uapi/linux/if_ether.h | 1 + + include/uapi/linux/if_link.h | 1 + + include/uapi/linux/mptcp.h | 89 ++++++++++++++++++++++++++++++++++ + 5 files changed, 93 insertions(+) + create mode 100644 include/uapi/linux/mptcp.h + +diff --git a/include/uapi/linux/if.h b/include/uapi/linux/if.h +index 626da393123b6..9a3bc23d0235e 100644 +--- a/include/uapi/linux/if.h ++++ b/include/uapi/linux/if.h +@@ -175,6 +175,7 @@ enum { + enum { + IF_LINK_MODE_DEFAULT, + IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */ ++ IF_LINK_MODE_TESTING, /* limit upward transition to testing */ + }; + + /* +diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h +index 31fc51bdedb3c..53ba8385b022e 100644 +--- a/include/uapi/linux/if_bridge.h ++++ b/include/uapi/linux/if_bridge.h +@@ -120,6 +120,7 @@ enum { + IFLA_BRIDGE_MODE, + IFLA_BRIDGE_VLAN_INFO, + IFLA_BRIDGE_VLAN_TUNNEL_INFO, ++ IFLA_BRIDGE_MRP, + __IFLA_BRIDGE_MAX, + }; + #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) +diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h +index 728c42dfd59c1..1a0c7dfe8e38e 100644 +--- a/include/uapi/linux/if_ether.h ++++ b/include/uapi/linux/if_ether.h +@@ -92,6 +92,7 @@ + #define ETH_P_PREAUTH 0x88C7 /* 802.11 Preauthentication */ + #define ETH_P_TIPC 0x88CA /* TIPC */ + #define ETH_P_LLDP 0x88CC /* Link Layer Discovery Protocol */ ++#define ETH_P_MRP 0x88E3 /* Media Redundancy Protocol */ + #define ETH_P_MACSEC 0x88E5 /* 802.1ae MACsec */ + #define ETH_P_8021AH 0x88E7 /* 802.1ah Backbone Service Tag */ + #define ETH_P_MVRP 0x88F5 /* 802.1Q MVRP */ +diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h +index d36919fb4024a..4da0768d7a5a3 100644 +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -338,6 +338,7 @@ enum { + IFLA_BRPORT_NEIGH_SUPPRESS, + IFLA_BRPORT_ISOLATED, + IFLA_BRPORT_BACKUP_PORT, ++ IFLA_BRPORT_MRP_RING_OPEN, + __IFLA_BRPORT_MAX + }; + #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) +diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h +new file mode 100644 +index 0000000000000..009b8f0b0e8be +--- /dev/null ++++ b/include/uapi/linux/mptcp.h +@@ -0,0 +1,89 @@ ++/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ ++#ifndef _MPTCP_H ++#define _MPTCP_H ++ ++#include ++#include ++ ++#define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0) ++#define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1) ++#define MPTCP_SUBFLOW_FLAG_JOIN_REM _BITUL(2) ++#define MPTCP_SUBFLOW_FLAG_JOIN_LOC _BITUL(3) ++#define MPTCP_SUBFLOW_FLAG_BKUP_REM _BITUL(4) ++#define MPTCP_SUBFLOW_FLAG_BKUP_LOC _BITUL(5) ++#define MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED _BITUL(6) ++#define MPTCP_SUBFLOW_FLAG_CONNECTED _BITUL(7) ++#define MPTCP_SUBFLOW_FLAG_MAPVALID _BITUL(8) ++ ++enum { ++ MPTCP_SUBFLOW_ATTR_UNSPEC, ++ MPTCP_SUBFLOW_ATTR_TOKEN_REM, ++ MPTCP_SUBFLOW_ATTR_TOKEN_LOC, ++ MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ, ++ MPTCP_SUBFLOW_ATTR_MAP_SEQ, ++ MPTCP_SUBFLOW_ATTR_MAP_SFSEQ, ++ MPTCP_SUBFLOW_ATTR_SSN_OFFSET, ++ MPTCP_SUBFLOW_ATTR_MAP_DATALEN, ++ MPTCP_SUBFLOW_ATTR_FLAGS, ++ MPTCP_SUBFLOW_ATTR_ID_REM, ++ MPTCP_SUBFLOW_ATTR_ID_LOC, ++ MPTCP_SUBFLOW_ATTR_PAD, ++ __MPTCP_SUBFLOW_ATTR_MAX ++}; ++ ++#define MPTCP_SUBFLOW_ATTR_MAX (__MPTCP_SUBFLOW_ATTR_MAX - 1) ++ ++/* netlink interface */ ++#define MPTCP_PM_NAME "mptcp_pm" ++#define MPTCP_PM_CMD_GRP_NAME "mptcp_pm_cmds" ++#define MPTCP_PM_VER 0x1 ++ ++/* ++ * ATTR types defined for MPTCP ++ */ ++enum { ++ MPTCP_PM_ATTR_UNSPEC, ++ ++ MPTCP_PM_ATTR_ADDR, /* nested address */ ++ MPTCP_PM_ATTR_RCV_ADD_ADDRS, /* u32 */ ++ MPTCP_PM_ATTR_SUBFLOWS, /* u32 */ ++ ++ __MPTCP_PM_ATTR_MAX ++}; ++ ++#define MPTCP_PM_ATTR_MAX (__MPTCP_PM_ATTR_MAX - 1) ++ ++enum { ++ MPTCP_PM_ADDR_ATTR_UNSPEC, ++ ++ MPTCP_PM_ADDR_ATTR_FAMILY, /* u16 */ ++ MPTCP_PM_ADDR_ATTR_ID, /* u8 */ ++ MPTCP_PM_ADDR_ATTR_ADDR4, /* struct in_addr */ ++ MPTCP_PM_ADDR_ATTR_ADDR6, /* struct in6_addr */ ++ MPTCP_PM_ADDR_ATTR_PORT, /* u16 */ ++ MPTCP_PM_ADDR_ATTR_FLAGS, /* u32 */ ++ MPTCP_PM_ADDR_ATTR_IF_IDX, /* s32 */ ++ ++ __MPTCP_PM_ADDR_ATTR_MAX ++}; ++ ++#define MPTCP_PM_ADDR_ATTR_MAX (__MPTCP_PM_ADDR_ATTR_MAX - 1) ++ ++#define MPTCP_PM_ADDR_FLAG_SIGNAL (1 << 0) ++#define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1) ++#define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2) ++ ++enum { ++ MPTCP_PM_CMD_UNSPEC, ++ ++ MPTCP_PM_CMD_ADD_ADDR, ++ MPTCP_PM_CMD_DEL_ADDR, ++ MPTCP_PM_CMD_GET_ADDR, ++ MPTCP_PM_CMD_FLUSH_ADDRS, ++ MPTCP_PM_CMD_SET_LIMITS, ++ MPTCP_PM_CMD_GET_LIMITS, ++ ++ __MPTCP_PM_CMD_AFTER_LAST ++}; ++ ++#endif /* _MPTCP_H */ +-- +2.26.2 + diff --git a/SOURCES/0017-add-support-for-mptcp-netlink-interface.patch b/SOURCES/0017-add-support-for-mptcp-netlink-interface.patch new file mode 100644 index 0000000..47995fd --- /dev/null +++ b/SOURCES/0017-add-support-for-mptcp-netlink-interface.patch @@ -0,0 +1,532 @@ +From 1f25184a76227f8a7a1e425434e6e0f0bd13457d Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:26:50 +0200 +Subject: [PATCH] add support for mptcp netlink interface + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: unknown commit 7e0767cd862bb + +commit 7e0767cd862bb5dd2d41c41c5e6f55d633f953ea +Author: Paolo Abeni +Date: Thu Apr 23 15:37:08 2020 +0200 + + add support for mptcp netlink interface + + Implement basic commands to: + - manipulate MPTCP endpoints list + - manipulate MPTCP connection limits + + Examples: + 1. Allows multiple subflows per MPTCP connection + $ ip mptcp limits set subflows 2 + + 2. Accept ADD_ADDR announcement from the peer (server): + $ ip mptcp limits set add_addr_accepted 2 + + 3. Add a ipv4 address to be annunced for backup subflows: + $ ip mptcp endpoint add 10.99.1.2 signal backup + + 4. Add an ipv6 address used as source for additional subflows: + $ ip mptcp endpoint add 2001::2 subflow + + Signed-off-by: Paolo Abeni + Signed-off-by: David Ahern +--- + ip/Makefile | 2 +- + ip/ip.c | 3 +- + ip/ip_common.h | 1 + + ip/ipmptcp.c | 436 +++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 440 insertions(+), 2 deletions(-) + create mode 100644 ip/ipmptcp.c + +diff --git a/ip/Makefile b/ip/Makefile +index 5ab78d7d3b84e..8735b8e4706b3 100644 +--- a/ip/Makefile ++++ b/ip/Makefile +@@ -11,7 +11,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ + iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \ + iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \ + ipvrf.o iplink_xstats.o ipseg6.o iplink_netdevsim.o iplink_rmnet.o \ +- ipnexthop.o ++ ipnexthop.o ipmptcp.o + + RTMONOBJ=rtmon.o + +diff --git a/ip/ip.c b/ip/ip.c +index fed26f8d48279..8d62f4e312bdc 100644 +--- a/ip/ip.c ++++ b/ip/ip.c +@@ -51,7 +51,7 @@ static void usage(void) + "where OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |\n" + " tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |\n" + " netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |\n" +- " vrf | sr | nexthop }\n" ++ " vrf | sr | nexthop | mptcp }\n" + " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" + " -h[uman-readable] | -iec | -j[son] | -p[retty] |\n" + " -f[amily] { inet | inet6 | mpls | bridge | link } |\n" +@@ -103,6 +103,7 @@ static const struct cmd { + { "vrf", do_ipvrf}, + { "sr", do_seg6 }, + { "nexthop", do_ipnh }, ++ { "mptcp", do_mptcp }, + { "help", do_help }, + { 0 } + }; +diff --git a/ip/ip_common.h b/ip/ip_common.h +index cd916ec87c265..0dd4a53fc8333 100644 +--- a/ip/ip_common.h ++++ b/ip/ip_common.h +@@ -82,6 +82,7 @@ void vrf_reset(void); + int netns_identify_pid(const char *pidstr, char *name, int len); + int do_seg6(int argc, char **argv); + int do_ipnh(int argc, char **argv); ++int do_mptcp(int argc, char **argv); + + int iplink_get(char *name, __u32 filt_mask); + int iplink_ifla_xstats(int argc, char **argv); +diff --git a/ip/ipmptcp.c b/ip/ipmptcp.c +new file mode 100644 +index 0000000000000..bc12418bd39c6 +--- /dev/null ++++ b/ip/ipmptcp.c +@@ -0,0 +1,436 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "utils.h" ++#include "ip_common.h" ++#include "libgenl.h" ++#include "json_print.h" ++ ++static void usage(void) ++{ ++ fprintf(stderr, ++ "Usage: ip mptcp endpoint add ADDRESS [ dev NAME ] [ id ID ]\n" ++ " [ FLAG-LIST ]\n" ++ " ip mptcp endpoint delete id ID\n" ++ " ip mptcp endpoint show [ id ID ]\n" ++ " ip mptcp endpoint flush\n" ++ " ip mptcp limits set [ subflows NR ] [ add_addr_accepted NR ]\n" ++ " ip mptcp limits show\n" ++ "FLAG-LIST := [ FLAG-LIST ] FLAG\n" ++ "FLAG := [ signal | subflow | backup ]\n"); ++ ++ exit(-1); ++} ++ ++/* netlink socket */ ++static struct rtnl_handle genl_rth = { .fd = -1 }; ++static int genl_family = -1; ++ ++#define MPTCP_BUFLEN 4096 ++#define MPTCP_REQUEST(_req, _cmd, _flags) \ ++ GENL_REQUEST(_req, MPTCP_BUFLEN, genl_family, 0, \ ++ MPTCP_PM_VER, _cmd, _flags) ++ ++/* Mapping from argument to address flag mask */ ++static const struct { ++ const char *name; ++ unsigned long value; ++} mptcp_addr_flag_names[] = { ++ { "signal", MPTCP_PM_ADDR_FLAG_SIGNAL }, ++ { "subflow", MPTCP_PM_ADDR_FLAG_SUBFLOW }, ++ { "backup", MPTCP_PM_ADDR_FLAG_BACKUP }, ++}; ++ ++static void print_mptcp_addr_flags(unsigned int flags) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(mptcp_addr_flag_names); i++) { ++ unsigned long mask = mptcp_addr_flag_names[i].value; ++ ++ if (flags & mask) { ++ print_string(PRINT_FP, NULL, "%s ", ++ mptcp_addr_flag_names[i].name); ++ print_bool(PRINT_JSON, ++ mptcp_addr_flag_names[i].name, NULL, true); ++ } ++ ++ flags &= ~mask; ++ } ++ ++ if (flags) { ++ /* unknown flags */ ++ SPRINT_BUF(b1); ++ ++ snprintf(b1, sizeof(b1), "%02x", flags); ++ print_string(PRINT_ANY, "rawflags", "rawflags %s ", b1); ++ } ++} ++ ++static int get_flags(const char *arg, __u32 *flags) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(mptcp_addr_flag_names); i++) { ++ if (strcmp(arg, mptcp_addr_flag_names[i].name)) ++ continue; ++ ++ *flags |= mptcp_addr_flag_names[i].value; ++ return 0; ++ } ++ return -1; ++} ++ ++static int mptcp_parse_opt(int argc, char **argv, struct nlmsghdr *n, ++ bool adding) ++{ ++ struct rtattr *attr_addr; ++ bool addr_set = false; ++ inet_prefix address; ++ bool id_set = false; ++ __u32 index = 0; ++ __u32 flags = 0; ++ __u8 id = 0; ++ ++ ll_init_map(&rth); ++ while (argc > 0) { ++ if (get_flags(*argv, &flags) == 0) { ++ } else if (matches(*argv, "id") == 0) { ++ NEXT_ARG(); ++ ++ if (get_u8(&id, *argv, 0)) ++ invarg("invalid ID\n", *argv); ++ id_set = true; ++ } else if (matches(*argv, "dev") == 0) { ++ const char *ifname; ++ ++ NEXT_ARG(); ++ ++ ifname = *argv; ++ ++ if (check_ifname(ifname)) ++ invarg("invalid interface name\n", ifname); ++ ++ index = ll_name_to_index(ifname); ++ ++ if (!index) ++ invarg("device does not exist\n", ifname); ++ ++ } else if (get_addr(&address, *argv, AF_UNSPEC) == 0) { ++ addr_set = true; ++ } else { ++ invarg("unknown argument", *argv); ++ } ++ NEXT_ARG_FWD(); ++ } ++ ++ if (!addr_set && adding) ++ missarg("ADDRESS"); ++ ++ if (!id_set && !adding) ++ missarg("ID"); ++ ++ attr_addr = addattr_nest(n, MPTCP_BUFLEN, ++ MPTCP_PM_ATTR_ADDR | NLA_F_NESTED); ++ if (id_set) ++ addattr8(n, MPTCP_BUFLEN, MPTCP_PM_ADDR_ATTR_ID, id); ++ if (flags) ++ addattr32(n, MPTCP_BUFLEN, MPTCP_PM_ADDR_ATTR_FLAGS, flags); ++ if (index) ++ addattr32(n, MPTCP_BUFLEN, MPTCP_PM_ADDR_ATTR_IF_IDX, index); ++ if (addr_set) { ++ int type; ++ ++ addattr16(n, MPTCP_BUFLEN, MPTCP_PM_ADDR_ATTR_FAMILY, ++ address.family); ++ type = address.family == AF_INET ? MPTCP_PM_ADDR_ATTR_ADDR4 : ++ MPTCP_PM_ADDR_ATTR_ADDR6; ++ addattr_l(n, MPTCP_BUFLEN, type, &address.data, ++ address.bytelen); ++ } ++ ++ addattr_nest_end(n, attr_addr); ++ return 0; ++} ++ ++static int mptcp_addr_modify(int argc, char **argv, int cmd) ++{ ++ MPTCP_REQUEST(req, cmd, NLM_F_REQUEST); ++ int ret; ++ ++ ret = mptcp_parse_opt(argc, argv, &req.n, cmd == MPTCP_PM_CMD_ADD_ADDR); ++ if (ret) ++ return ret; ++ ++ if (rtnl_talk(&genl_rth, &req.n, NULL) < 0) ++ return -2; ++ ++ return 0; ++} ++ ++static int print_mptcp_addrinfo(struct rtattr *addrinfo) ++{ ++ struct rtattr *tb[MPTCP_PM_ADDR_ATTR_MAX + 1]; ++ __u8 family = AF_UNSPEC, addr_attr_type; ++ const char *ifname; ++ unsigned int flags; ++ int index; ++ __u16 id; ++ ++ parse_rtattr_nested(tb, MPTCP_PM_ADDR_ATTR_MAX, addrinfo); ++ ++ open_json_object(NULL); ++ if (tb[MPTCP_PM_ADDR_ATTR_FAMILY]) ++ family = rta_getattr_u8(tb[MPTCP_PM_ADDR_ATTR_FAMILY]); ++ ++ addr_attr_type = family == AF_INET ? MPTCP_PM_ADDR_ATTR_ADDR4 : ++ MPTCP_PM_ADDR_ATTR_ADDR6; ++ if (tb[addr_attr_type]) { ++ print_string(PRINT_ANY, "address", "%s ", ++ format_host_rta(family, tb[addr_attr_type])); ++ } ++ if (tb[MPTCP_PM_ADDR_ATTR_ID]) { ++ id = rta_getattr_u8(tb[MPTCP_PM_ADDR_ATTR_ID]); ++ print_uint(PRINT_ANY, "id", "id %u ", id); ++ } ++ if (tb[MPTCP_PM_ADDR_ATTR_FLAGS]) { ++ flags = rta_getattr_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]); ++ print_mptcp_addr_flags(flags); ++ } ++ if (tb[MPTCP_PM_ADDR_ATTR_IF_IDX]) { ++ index = rta_getattr_s32(tb[MPTCP_PM_ADDR_ATTR_IF_IDX]); ++ ifname = index ? ll_index_to_name(index) : NULL; ++ ++ if (ifname) ++ print_string(PRINT_ANY, "dev", "dev %s ", ifname); ++ } ++ ++ close_json_object(); ++ print_string(PRINT_FP, NULL, "\n", NULL); ++ fflush(stdout); ++ ++ return 0; ++} ++ ++static int print_mptcp_addr(struct nlmsghdr *n, void *arg) ++{ ++ struct rtattr *tb[MPTCP_PM_ATTR_MAX + 1]; ++ struct genlmsghdr *ghdr; ++ struct rtattr *addrinfo; ++ int len = n->nlmsg_len; ++ ++ if (n->nlmsg_type != genl_family) ++ return 0; ++ ++ len -= NLMSG_LENGTH(GENL_HDRLEN); ++ if (len < 0) ++ return -1; ++ ++ ghdr = NLMSG_DATA(n); ++ parse_rtattr_flags(tb, MPTCP_PM_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, ++ len, NLA_F_NESTED); ++ addrinfo = tb[MPTCP_PM_ATTR_ADDR]; ++ if (!addrinfo) ++ return -1; ++ ++ ll_init_map(&rth); ++ return print_mptcp_addrinfo(addrinfo); ++} ++ ++static int mptcp_addr_dump(void) ++{ ++ MPTCP_REQUEST(req, MPTCP_PM_CMD_GET_ADDR, NLM_F_REQUEST | NLM_F_DUMP); ++ ++ if (rtnl_send(&genl_rth, &req.n, req.n.nlmsg_len) < 0) { ++ perror("Cannot send show request"); ++ exit(1); ++ } ++ ++ new_json_obj(json); ++ ++ if (rtnl_dump_filter(&genl_rth, print_mptcp_addr, stdout) < 0) { ++ fprintf(stderr, "Dump terminated\n"); ++ delete_json_obj(); ++ fflush(stdout); ++ return -2; ++ } ++ ++ close_json_object(); ++ fflush(stdout); ++ return 0; ++} ++ ++static int mptcp_addr_show(int argc, char **argv) ++{ ++ MPTCP_REQUEST(req, MPTCP_PM_CMD_GET_ADDR, NLM_F_REQUEST); ++ struct nlmsghdr *answer; ++ int ret; ++ ++ if (!argv) ++ return mptcp_addr_dump(); ++ ++ ret = mptcp_parse_opt(argc, argv, &req.n, false); ++ if (ret) ++ return ret; ++ ++ if (rtnl_talk(&genl_rth, &req.n, &answer) < 0) ++ return -2; ++ ++ return print_mptcp_addr(answer, stdout); ++} ++ ++static int mptcp_addr_flush(int argc, char **argv) ++{ ++ MPTCP_REQUEST(req, MPTCP_PM_CMD_FLUSH_ADDRS, NLM_F_REQUEST); ++ ++ if (rtnl_talk(&genl_rth, &req.n, NULL) < 0) ++ return -2; ++ ++ return 0; ++} ++ ++static int mptcp_parse_limit(int argc, char **argv, struct nlmsghdr *n) ++{ ++ bool set_rcv_add_addrs = false; ++ bool set_subflows = false; ++ __u32 rcv_add_addrs = 0; ++ __u32 subflows = 0; ++ ++ while (argc > 0) { ++ if (matches(*argv, "subflows") == 0) { ++ NEXT_ARG(); ++ ++ if (get_u32(&subflows, *argv, 0)) ++ invarg("invalid subflows\n", *argv); ++ set_subflows = true; ++ } else if (matches(*argv, "add_addr_accepted") == 0) { ++ NEXT_ARG(); ++ ++ if (get_u32(&rcv_add_addrs, *argv, 0)) ++ invarg("invalid add_addr_accepted\n", *argv); ++ set_rcv_add_addrs = true; ++ } else { ++ invarg("unknown limit", *argv); ++ } ++ NEXT_ARG_FWD(); ++ } ++ ++ if (set_rcv_add_addrs) ++ addattr32(n, MPTCP_BUFLEN, MPTCP_PM_ATTR_RCV_ADD_ADDRS, ++ rcv_add_addrs); ++ if (set_subflows) ++ addattr32(n, MPTCP_BUFLEN, MPTCP_PM_ATTR_SUBFLOWS, subflows); ++ return set_rcv_add_addrs || set_subflows; ++} ++ ++static int print_mptcp_limit(struct nlmsghdr *n, void *arg) ++{ ++ struct rtattr *tb[MPTCP_PM_ATTR_MAX + 1]; ++ struct genlmsghdr *ghdr; ++ int len = n->nlmsg_len; ++ __u32 val; ++ ++ if (n->nlmsg_type != genl_family) ++ return 0; ++ ++ len -= NLMSG_LENGTH(GENL_HDRLEN); ++ if (len < 0) ++ return -1; ++ ++ ghdr = NLMSG_DATA(n); ++ parse_rtattr(tb, MPTCP_PM_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len); ++ ++ open_json_object(NULL); ++ if (tb[MPTCP_PM_ATTR_RCV_ADD_ADDRS]) { ++ val = rta_getattr_u32(tb[MPTCP_PM_ATTR_RCV_ADD_ADDRS]); ++ ++ print_uint(PRINT_ANY, "add_addr_accepted", ++ "add_addr_accepted %d ", val); ++ } ++ ++ if (tb[MPTCP_PM_ATTR_SUBFLOWS]) { ++ val = rta_getattr_u32(tb[MPTCP_PM_ATTR_SUBFLOWS]); ++ ++ print_uint(PRINT_ANY, "subflows", "subflows %d ", val); ++ } ++ print_string(PRINT_FP, NULL, "%s", "\n"); ++ fflush(stdout); ++ close_json_object(); ++ return 0; ++} ++ ++static int mptcp_limit_get_set(int argc, char **argv, int cmd) ++{ ++ bool do_get = cmd == MPTCP_PM_CMD_GET_LIMITS; ++ MPTCP_REQUEST(req, cmd, NLM_F_REQUEST); ++ struct nlmsghdr *answer; ++ int ret; ++ ++ ret = mptcp_parse_limit(argc, argv, &req.n); ++ if (ret < 0) ++ return -1; ++ ++ if (rtnl_talk(&genl_rth, &req.n, do_get ? &answer : NULL) < 0) ++ return -2; ++ ++ if (do_get) ++ return print_mptcp_limit(answer, stdout); ++ return 0; ++} ++ ++int do_mptcp(int argc, char **argv) ++{ ++ if (argc == 0) ++ usage(); ++ ++ if (matches(*argv, "help") == 0) ++ usage(); ++ ++ if (genl_init_handle(&genl_rth, MPTCP_PM_NAME, &genl_family)) ++ exit(1); ++ ++ if (matches(*argv, "endpoint") == 0) { ++ NEXT_ARG_FWD(); ++ if (argc == 0) ++ return mptcp_addr_show(0, NULL); ++ ++ if (matches(*argv, "add") == 0) ++ return mptcp_addr_modify(argc-1, argv+1, ++ MPTCP_PM_CMD_ADD_ADDR); ++ if (matches(*argv, "delete") == 0) ++ return mptcp_addr_modify(argc-1, argv+1, ++ MPTCP_PM_CMD_DEL_ADDR); ++ if (matches(*argv, "show") == 0) ++ return mptcp_addr_show(argc-1, argv+1); ++ if (matches(*argv, "flush") == 0) ++ return mptcp_addr_flush(argc-1, argv+1); ++ ++ goto unknown; ++ } ++ ++ if (matches(*argv, "limits") == 0) { ++ NEXT_ARG_FWD(); ++ if (argc == 0) ++ return mptcp_limit_get_set(0, NULL, ++ MPTCP_PM_CMD_GET_LIMITS); ++ ++ if (matches(*argv, "set") == 0) ++ return mptcp_limit_get_set(argc-1, argv+1, ++ MPTCP_PM_CMD_SET_LIMITS); ++ if (matches(*argv, "show") == 0) ++ return mptcp_limit_get_set(argc-1, argv+1, ++ MPTCP_PM_CMD_GET_LIMITS); ++ } ++ ++unknown: ++ fprintf(stderr, "Command \"%s\" is unknown, try \"ip mptcp help\".\n", ++ *argv); ++ exit(-1); ++} +-- +2.26.2 + diff --git a/SOURCES/0018-Update-kernel-headers.patch b/SOURCES/0018-Update-kernel-headers.patch new file mode 100644 index 0000000..9129be5 --- /dev/null +++ b/SOURCES/0018-Update-kernel-headers.patch @@ -0,0 +1,217 @@ +From 98f0c643a333ff630407828f4141131502edc6f9 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:26:50 +0200 +Subject: [PATCH] Update kernel headers + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: unknown commit 3d72f125c300d + +commit 3d72f125c300dd261a5151cf1cac7cfa152376b2 +Author: David Ahern +Date: Sun Sep 15 10:32:58 2019 -0700 + + Update kernel headers + + Update kernel headers to commit: + aa2eaa8c272a ("Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net") + + Signed-off-by: David Ahern +--- + include/uapi/linux/bpf.h | 15 ++++++++++++--- + include/uapi/linux/can.h | 20 +++++++++++++++++++- + include/uapi/linux/devlink.h | 11 +++++++++++ + include/uapi/linux/inet_diag.h | 9 +++++++++ + include/uapi/linux/pkt_cls.h | 2 ++ + include/uapi/linux/sctp.h | 3 +++ + 6 files changed, 56 insertions(+), 4 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 3e195ff43fa01..6d55239a4cc0f 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -106,6 +106,7 @@ enum bpf_cmd { + BPF_TASK_FD_QUERY, + BPF_MAP_LOOKUP_AND_DELETE_ELEM, + BPF_MAP_FREEZE, ++ BPF_BTF_GET_NEXT_ID, + }; + + enum bpf_map_type { +@@ -284,6 +285,9 @@ enum bpf_attach_type { + */ + #define BPF_F_TEST_RND_HI32 (1U << 2) + ++/* The verifier internal test flag. Behavior is undefined */ ++#define BPF_F_TEST_STATE_FREQ (1U << 3) ++ + /* When BPF ldimm64's insn[0].src_reg != 0 then this can have + * two extensions: + * +@@ -337,6 +341,9 @@ enum bpf_attach_type { + #define BPF_F_RDONLY_PROG (1U << 7) + #define BPF_F_WRONLY_PROG (1U << 8) + ++/* Clone map from listener for newly accepted socket */ ++#define BPF_F_CLONE (1U << 9) ++ + /* flags for BPF_PROG_QUERY */ + #define BPF_F_QUERY_EFFECTIVE (1U << 0) + +@@ -577,6 +584,8 @@ union bpf_attr { + * limited to five). + * + * Each time the helper is called, it appends a line to the trace. ++ * Lines are discarded while *\/sys/kernel/debug/tracing/trace* is ++ * open, use *\/sys/kernel/debug/tracing/trace_pipe* to avoid this. + * The format of the trace is customizable, and the exact output + * one will get depends on the options set in + * *\/sys/kernel/debug/tracing/trace_options* (see also the +@@ -1015,7 +1024,7 @@ union bpf_attr { + * The realm of the route for the packet associated to *skb*, or 0 + * if none was found. + * +- * int bpf_perf_event_output(struct pt_reg *ctx, struct bpf_map *map, u64 flags, void *data, u64 size) ++ * int bpf_perf_event_output(struct pt_regs *ctx, struct bpf_map *map, u64 flags, void *data, u64 size) + * Description + * Write raw *data* blob into a special BPF perf event held by + * *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf +@@ -1077,7 +1086,7 @@ union bpf_attr { + * Return + * 0 on success, or a negative error in case of failure. + * +- * int bpf_get_stackid(struct pt_reg *ctx, struct bpf_map *map, u64 flags) ++ * int bpf_get_stackid(struct pt_regs *ctx, struct bpf_map *map, u64 flags) + * Description + * Walk a user or a kernel stack and return its id. To achieve + * this, the helper needs *ctx*, which is a pointer to the context +@@ -1726,7 +1735,7 @@ union bpf_attr { + * Return + * 0 on success, or a negative error in case of failure. + * +- * int bpf_override_return(struct pt_reg *regs, u64 rc) ++ * int bpf_override_return(struct pt_regs *regs, u64 rc) + * Description + * Used for error injection, this helper uses kprobes to override + * the return value of the probed function, and to set it to *rc*. +diff --git a/include/uapi/linux/can.h b/include/uapi/linux/can.h +index 9009f0b6505cf..c61cdc7ad5cc6 100644 +--- a/include/uapi/linux/can.h ++++ b/include/uapi/linux/can.h +@@ -157,7 +157,8 @@ struct canfd_frame { + #define CAN_TP20 4 /* VAG Transport Protocol v2.0 */ + #define CAN_MCNET 5 /* Bosch MCNet */ + #define CAN_ISOTP 6 /* ISO 15765-2 Transport Protocol */ +-#define CAN_NPROTO 7 ++#define CAN_J1939 7 /* SAE J1939 */ ++#define CAN_NPROTO 8 + + #define SOL_CAN_BASE 100 + +@@ -174,6 +175,23 @@ struct sockaddr_can { + /* transport protocol class address information (e.g. ISOTP) */ + struct { canid_t rx_id, tx_id; } tp; + ++ /* J1939 address information */ ++ struct { ++ /* 8 byte name when using dynamic addressing */ ++ __u64 name; ++ ++ /* pgn: ++ * 8 bit: PS in PDU2 case, else 0 ++ * 8 bit: PF ++ * 1 bit: DP ++ * 1 bit: reserved ++ */ ++ __u32 pgn; ++ ++ /* 1 byte address */ ++ __u8 addr; ++ } j1939; ++ + /* reserved for future CAN protocols address information */ + } can_addr; + }; +diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h +index 3fb683bee6ba1..79e1405db67cc 100644 +--- a/include/uapi/linux/devlink.h ++++ b/include/uapi/linux/devlink.h +@@ -202,6 +202,15 @@ enum devlink_param_cmode { + enum devlink_param_fw_load_policy_value { + DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER, + DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH, ++ DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK, ++ DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_UNKNOWN, ++}; ++ ++enum devlink_param_reset_dev_on_drv_probe_value { ++ DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_UNKNOWN, ++ DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_ALWAYS, ++ DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_NEVER, ++ DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK, + }; + + enum { +@@ -410,6 +419,8 @@ enum devlink_attr { + DEVLINK_ATTR_TRAP_METADATA, /* nested */ + DEVLINK_ATTR_TRAP_GROUP_NAME, /* string */ + ++ DEVLINK_ATTR_RELOAD_FAILED, /* u8 0 or 1 */ ++ + /* add new attributes above here, update the policy in devlink.c */ + + __DEVLINK_ATTR_MAX, +diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h +index f3bcd7ee82771..3dff6841486a4 100644 +--- a/include/uapi/linux/inet_diag.h ++++ b/include/uapi/linux/inet_diag.h +@@ -153,11 +153,20 @@ enum { + INET_DIAG_BBRINFO, /* request as INET_DIAG_VEGASINFO */ + INET_DIAG_CLASS_ID, /* request as INET_DIAG_TCLASS */ + INET_DIAG_MD5SIG, ++ INET_DIAG_ULP_INFO, + __INET_DIAG_MAX, + }; + + #define INET_DIAG_MAX (__INET_DIAG_MAX - 1) + ++enum { ++ INET_ULP_INFO_UNSPEC, ++ INET_ULP_INFO_NAME, ++ INET_ULP_INFO_TLS, ++ __INET_ULP_INFO_MAX, ++}; ++#define INET_ULP_INFO_MAX (__INET_ULP_INFO_MAX - 1) ++ + /* INET_DIAG_MEM */ + + struct inet_diag_meminfo { +diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h +index 0a9ab625cba7b..c6ad22f76edee 100644 +--- a/include/uapi/linux/pkt_cls.h ++++ b/include/uapi/linux/pkt_cls.h +@@ -165,6 +165,8 @@ enum { + TCA_POLICE_RESULT, + TCA_POLICE_TM, + TCA_POLICE_PAD, ++ TCA_POLICE_RATE64, ++ TCA_POLICE_PEAKRATE64, + __TCA_POLICE_MAX + #define TCA_POLICE_RESULT TCA_POLICE_RESULT + }; +diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h +index c4bce0a2011c1..0d4c1507a169d 100644 +--- a/include/uapi/linux/sctp.h ++++ b/include/uapi/linux/sctp.h +@@ -134,6 +134,9 @@ typedef __s32 sctp_assoc_t; + #define SCTP_INTERLEAVING_SUPPORTED 125 + #define SCTP_SENDMSG_CONNECT 126 + #define SCTP_EVENT 127 ++#define SCTP_ASCONF_SUPPORTED 128 ++#define SCTP_AUTH_SUPPORTED 129 ++#define SCTP_ECN_SUPPORTED 130 + + /* PR-SCTP policies */ + #define SCTP_PR_SCTP_NONE 0x0000 +-- +2.26.2 + diff --git a/SOURCES/0019-Update-kernel-headers.patch b/SOURCES/0019-Update-kernel-headers.patch new file mode 100644 index 0000000..f6e47ee --- /dev/null +++ b/SOURCES/0019-Update-kernel-headers.patch @@ -0,0 +1,150 @@ +From 4dfaa0a3e4ea077d95d7355e73a8069b1c8af97b Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:26:50 +0200 +Subject: [PATCH] Update kernel headers + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: unknown commit ce9191ffee31d +Conflicts: several unrelated missing changes in uapi + +commit ce9191ffee31d440591bf49ef530b80ee9975dfb +Author: David Ahern +Date: Tue Mar 31 23:23:28 2020 +0000 + + Update kernel headers + + Update kernel headers to commit: + 7f80ccfe9968 ("net: ipv6: rpl_iptunnel: Fix potential memory leak in rpl_do_srh_inline") + + Signed-off-by: David Ahern +--- + include/uapi/linux/bpf.h | 20 +++++++++++++++++++- + include/uapi/linux/devlink.h | 6 ++++++ + include/uapi/linux/if_link.h | 5 ++++- + include/uapi/linux/inet_diag.h | 1 + + include/uapi/linux/lwtunnel.h | 1 + + 5 files changed, 31 insertions(+), 2 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 6d55239a4cc0f..94aa5a1d38215 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -483,7 +483,7 @@ union bpf_attr { + __u32 prog_cnt; + } query; + +- struct { ++ struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */ + __u64 name; + __u32 prog_fd; + } raw_tracepoint; +@@ -511,6 +511,24 @@ union bpf_attr { + __u64 probe_offset; /* output: probe_offset */ + __u64 probe_addr; /* output: probe_addr */ + } task_fd_query; ++ ++ struct { /* struct used by BPF_LINK_CREATE command */ ++ __u32 prog_fd; /* eBPF program to attach */ ++ __u32 target_fd; /* object to attach to */ ++ __u32 attach_type; /* attach type */ ++ __u32 flags; /* extra flags */ ++ } link_create; ++ ++ struct { /* struct used by BPF_LINK_UPDATE command */ ++ __u32 link_fd; /* link fd */ ++ /* new program fd to update link with */ ++ __u32 new_prog_fd; ++ __u32 flags; /* extra flags */ ++ /* expected link's program fd; is specified only if ++ * BPF_F_REPLACE flag is set in flags */ ++ __u32 old_prog_fd; ++ } link_update; ++ + } __attribute__((aligned(8))); + + /* The description below is an attempt at providing documentation to eBPF +diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h +index 79e1405db67cc..e63aeab76bcb8 100644 +--- a/include/uapi/linux/devlink.h ++++ b/include/uapi/linux/devlink.h +@@ -117,6 +117,11 @@ enum devlink_command { + DEVLINK_CMD_TRAP_GROUP_NEW, + DEVLINK_CMD_TRAP_GROUP_DEL, + ++ DEVLINK_CMD_TRAP_POLICER_GET, /* can dump */ ++ DEVLINK_CMD_TRAP_POLICER_SET, ++ DEVLINK_CMD_TRAP_POLICER_NEW, ++ DEVLINK_CMD_TRAP_POLICER_DEL, ++ + /* add new commands above here */ + __DEVLINK_CMD_MAX, + DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 +@@ -216,6 +221,7 @@ enum devlink_param_reset_dev_on_drv_probe_value { + enum { + DEVLINK_ATTR_STATS_RX_PACKETS, /* u64 */ + DEVLINK_ATTR_STATS_RX_BYTES, /* u64 */ ++ DEVLINK_ATTR_STATS_RX_DROPPED, /* u64 */ + + __DEVLINK_ATTR_STATS_MAX, + DEVLINK_ATTR_STATS_MAX = __DEVLINK_ATTR_STATS_MAX - 1 +diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h +index 4da0768d7a5a3..5d69479b8052d 100644 +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -459,6 +459,7 @@ enum { + IFLA_MACSEC_REPLAY_PROTECT, + IFLA_MACSEC_VALIDATION, + IFLA_MACSEC_PAD, ++ IFLA_MACSEC_OFFLOAD, + __IFLA_MACSEC_MAX, + }; + +@@ -949,11 +950,12 @@ enum { + #define XDP_FLAGS_SKB_MODE (1U << 1) + #define XDP_FLAGS_DRV_MODE (1U << 2) + #define XDP_FLAGS_HW_MODE (1U << 3) ++#define XDP_FLAGS_REPLACE (1U << 4) + #define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | \ + XDP_FLAGS_DRV_MODE | \ + XDP_FLAGS_HW_MODE) + #define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \ +- XDP_FLAGS_MODES) ++ XDP_FLAGS_MODES | XDP_FLAGS_REPLACE) + + /* These are stored into IFLA_XDP_ATTACHED on dump. */ + enum { +@@ -973,6 +975,7 @@ enum { + IFLA_XDP_DRV_PROG_ID, + IFLA_XDP_SKB_PROG_ID, + IFLA_XDP_HW_PROG_ID, ++ IFLA_XDP_EXPECTED_FD, + __IFLA_XDP_MAX, + }; + +diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h +index 3dff6841486a4..db45fc664a5fd 100644 +--- a/include/uapi/linux/inet_diag.h ++++ b/include/uapi/linux/inet_diag.h +@@ -163,6 +163,7 @@ enum { + INET_ULP_INFO_UNSPEC, + INET_ULP_INFO_NAME, + INET_ULP_INFO_TLS, ++ INET_ULP_INFO_MPTCP, + __INET_ULP_INFO_MAX, + }; + #define INET_ULP_INFO_MAX (__INET_ULP_INFO_MAX - 1) +diff --git a/include/uapi/linux/lwtunnel.h b/include/uapi/linux/lwtunnel.h +index 3f3fe6f30df0b..0ba94063c1809 100644 +--- a/include/uapi/linux/lwtunnel.h ++++ b/include/uapi/linux/lwtunnel.h +@@ -13,6 +13,7 @@ enum lwtunnel_encap_types { + LWTUNNEL_ENCAP_SEG6, + LWTUNNEL_ENCAP_BPF, + LWTUNNEL_ENCAP_SEG6_LOCAL, ++ LWTUNNEL_ENCAP_RPL, + __LWTUNNEL_ENCAP_MAX, + }; + +-- +2.26.2 + diff --git a/SOURCES/0020-ss-allow-dumping-MPTCP-subflow-information.patch b/SOURCES/0020-ss-allow-dumping-MPTCP-subflow-information.patch new file mode 100644 index 0000000..2189263 --- /dev/null +++ b/SOURCES/0020-ss-allow-dumping-MPTCP-subflow-information.patch @@ -0,0 +1,144 @@ +From afc9c910cc9c818180364860b04535def3c19b6e Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:27:41 +0200 +Subject: [PATCH] ss: allow dumping MPTCP subflow information + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: unknown commit 712fdd98c0839 +Conflicts: context changes and code slightly adapted in tcp_show_info() + due to missing commit 14cadc707b919 ("ss: allow dumping kTLS info") + +commit 712fdd98c0839540a50baca0fb858c7a72d18031 +Author: Davide Caratti +Date: Thu Apr 23 15:37:09 2020 +0200 + + ss: allow dumping MPTCP subflow information + + [root@f31 packetdrill]# ss -tni + + ESTAB 0 0 192.168.82.247:8080 192.0.2.1:35273 + cubic wscale:7,8 [...] tcp-ulp-mptcp flags:Mec token:0000(id:0)/5f856c60(id:0) seq:b810457db34209a5 sfseq:1 ssnoff:0 maplen:190 + + Additionally extends ss manpage to describe the new entry layout. + + Signed-off-by: Davide Caratti + Signed-off-by: Paolo Abeni + Signed-off-by: David Ahern +--- + man/man8/ss.8 | 5 ++++ + misc/ss.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 74 insertions(+) + +diff --git a/man/man8/ss.8 b/man/man8/ss.8 +index 023d771b17878..c80853f98c49a 100644 +--- a/man/man8/ss.8 ++++ b/man/man8/ss.8 +@@ -261,6 +261,11 @@ the pacing rate and max pacing rate + .TP + .B rcv_space: + a helper variable for TCP internal auto tuning socket receive buffer ++.P ++.TP ++.B tcp-ulp-mptcp flags:[MmBbJjecv] token: seq: sfseq: ssnoff: maplen: ++MPTCP subflow information ++.P + .RE + .TP + .B \-\-tos +diff --git a/misc/ss.c b/misc/ss.c +index 363b4c8d87cd3..3d565af86087c 100644 +--- a/misc/ss.c ++++ b/misc/ss.c +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + + /* AF_VSOCK/PF_VSOCK is only provided since glibc 2.18 */ + #ifndef PF_VSOCK +@@ -2751,6 +2752,59 @@ static void print_md5sig(struct tcp_diag_md5sig *sig) + print_escape_buf(sig->tcpm_key, sig->tcpm_keylen, " ,"); + } + ++static void mptcp_subflow_info(struct rtattr *tb[]) ++{ ++ u_int32_t flags = 0; ++ ++ if (tb[MPTCP_SUBFLOW_ATTR_FLAGS]) { ++ char caps[32 + 1] = { 0 }, *cap = &caps[0]; ++ ++ flags = rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_FLAGS]); ++ ++ if (flags & MPTCP_SUBFLOW_FLAG_MCAP_REM) ++ *cap++ = 'M'; ++ if (flags & MPTCP_SUBFLOW_FLAG_MCAP_LOC) ++ *cap++ = 'm'; ++ if (flags & MPTCP_SUBFLOW_FLAG_JOIN_REM) ++ *cap++ = 'J'; ++ if (flags & MPTCP_SUBFLOW_FLAG_JOIN_LOC) ++ *cap++ = 'j'; ++ if (flags & MPTCP_SUBFLOW_FLAG_BKUP_REM) ++ *cap++ = 'B'; ++ if (flags & MPTCP_SUBFLOW_FLAG_BKUP_LOC) ++ *cap++ = 'b'; ++ if (flags & MPTCP_SUBFLOW_FLAG_FULLY_ESTABLISHED) ++ *cap++ = 'e'; ++ if (flags & MPTCP_SUBFLOW_FLAG_CONNECTED) ++ *cap++ = 'c'; ++ if (flags & MPTCP_SUBFLOW_FLAG_MAPVALID) ++ *cap++ = 'v'; ++ if (flags) ++ out(" flags:%s", caps); ++ } ++ if (tb[MPTCP_SUBFLOW_ATTR_TOKEN_REM] && ++ tb[MPTCP_SUBFLOW_ATTR_TOKEN_LOC] && ++ tb[MPTCP_SUBFLOW_ATTR_ID_REM] && ++ tb[MPTCP_SUBFLOW_ATTR_ID_LOC]) ++ out(" token:%04x(id:%hhu)/%04x(id:%hhu)", ++ rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_TOKEN_REM]), ++ rta_getattr_u8(tb[MPTCP_SUBFLOW_ATTR_ID_REM]), ++ rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_TOKEN_LOC]), ++ rta_getattr_u8(tb[MPTCP_SUBFLOW_ATTR_ID_LOC])); ++ if (tb[MPTCP_SUBFLOW_ATTR_MAP_SEQ]) ++ out(" seq:%llx", ++ rta_getattr_u64(tb[MPTCP_SUBFLOW_ATTR_MAP_SEQ])); ++ if (tb[MPTCP_SUBFLOW_ATTR_MAP_SFSEQ]) ++ out(" sfseq:%x", ++ rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_MAP_SFSEQ])); ++ if (tb[MPTCP_SUBFLOW_ATTR_SSN_OFFSET]) ++ out(" ssnoff:%x", ++ rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_SSN_OFFSET])); ++ if (tb[MPTCP_SUBFLOW_ATTR_MAP_DATALEN]) ++ out(" maplen:%x", ++ rta_getattr_u32(tb[MPTCP_SUBFLOW_ATTR_MAP_DATALEN])); ++} ++ + #define TCPI_HAS_OPT(info, opt) !!(info->tcpi_options & (opt)) + + static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, +@@ -2906,6 +2960,21 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, + print_md5sig(sig++); + } + } ++ if (tb[INET_DIAG_ULP_INFO]) { ++ struct rtattr *ulpinfo[INET_ULP_INFO_MAX + 1] = { 0 }; ++ ++ parse_rtattr_nested(ulpinfo, INET_ULP_INFO_MAX, ++ tb[INET_DIAG_ULP_INFO]); ++ ++ if (ulpinfo[INET_ULP_INFO_MPTCP]) { ++ struct rtattr *sfinfo[MPTCP_SUBFLOW_ATTR_MAX + 1] = ++ { 0 }; ++ ++ parse_rtattr_nested(sfinfo, MPTCP_SUBFLOW_ATTR_MAX, ++ ulpinfo[INET_ULP_INFO_MPTCP]); ++ mptcp_subflow_info(sfinfo); ++ } ++ } + } + + static const char *format_host_sa(struct sockaddr_storage *sa) +-- +2.26.2 + diff --git a/SOURCES/0021-man-mptcp-man-page.patch b/SOURCES/0021-man-mptcp-man-page.patch new file mode 100644 index 0000000..f9aed62 --- /dev/null +++ b/SOURCES/0021-man-mptcp-man-page.patch @@ -0,0 +1,174 @@ +From af65892658d7c271d1fb328065a35f8017610418 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:28:45 +0200 +Subject: [PATCH] man: mptcp man page + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: unknown commit 2d8b5fe93e9de + +commit 2d8b5fe93e9decb56acc243905d82fb22d6c4cfd +Author: Paolo Abeni +Date: Thu Apr 23 15:37:10 2020 +0200 + + man: mptcp man page + + describe the mptcp subcommands implemented so far. + + Signed-off-by: Paolo Abeni + Signed-off-by: David Ahern +--- + man/man8/ip-mptcp.8 | 142 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 142 insertions(+) + create mode 100644 man/man8/ip-mptcp.8 + +diff --git a/man/man8/ip-mptcp.8 b/man/man8/ip-mptcp.8 +new file mode 100644 +index 0000000000000..f6457e97efbe8 +--- /dev/null ++++ b/man/man8/ip-mptcp.8 +@@ -0,0 +1,142 @@ ++.TH IP\-MPTCP 8 "4 Apr 2020" "iproute2" "Linux" ++.SH "NAME" ++ip-mptcp \- MPTCP path manager configuration ++.SH "SYNOPSIS" ++.sp ++.ad l ++.in +8 ++.ti -8 ++.B ip ++.RI "[ " OPTIONS " ]" ++.B mptcp ++.RB "{ " ++.B endpoint ++.RB " | " ++.B limits ++.RB " | " ++.B help ++.RB " }" ++.sp ++ ++.ti -8 ++.BR "ip mptcp endpoint add " ++.IR IFADDR ++.RB "[ " dev ++.IR IFNAME " ]" ++.RB "[ " id ++.I ID ++.RB "] [ " ++.I FLAG-LIST ++.RB "] " ++ ++.ti -8 ++.BR "ip mptcp endpoint del id " ++.I ID ++ ++.ti -8 ++.BR "ip mptcp endpoint show " ++.RB "[ " id ++.I ID ++.RB "]" ++ ++.ti -8 ++.BR "ip mptcp endpoint flush" ++ ++.ti -8 ++.IR FLAG-LIST " := [ " FLAG-LIST " ] " FLAG ++ ++.ti -8 ++.IR FLAG " := [" ++.B signal ++.RB "|" ++.B subflow ++.RB "|" ++.B backup ++.RB "]" ++ ++.ti -8 ++.BR "ip mptcp limits set " ++.RB "[ " ++.B subflow ++.IR SUBFLOW_NR " ]" ++.RB "[ " ++.B add_addr_accepted ++.IR ADD_ADDR_ACCEPTED_NR " ]" ++ ++.ti -8 ++.BR "ip mptcp limits show" ++ ++.SH DESCRIPTION ++ ++MPTCP is a transport protocol built on top of TCP that allows TCP ++connections to use multiple paths to maximize resource usage and increase ++redundancy. The ip-mptcp sub-commands allow configuring several aspects of the ++MPTCP path manager, which is in charge of subflows creation: ++ ++.P ++The ++.B endpoint ++object specifies the IP addresses that will be used and/or announced for ++additional subflows: ++ ++.TS ++l l. ++ip mptcp endpoint add add new MPTCP endpoint ++ip mptcp endpoint delete delete existing MPTCP endpoint ++ip mptcp endpoint show get existing MPTCP endpoint ++ip mptcp endpoint flush flush all existing MPTCP endpoints ++.TE ++ ++.TP ++.IR ID ++is a unique numeric identifier for the given endpoint ++ ++.TP ++.BR signal ++the endpoint will be announced/signalled to each peer via an ADD_ADDR MPTCP ++sub-option ++ ++.TP ++.BR subflow ++if additional subflow creation is allowed by MPTCP limits, the endpoint will ++be used as the source address to create an additional subflow after that ++the MPTCP connection is established. ++ ++.TP ++.BR backup ++the endpoint will be announced as a backup address, if this is a ++.BR signal ++endpoint, or the subflow will be created as a backup one if this is a ++.BR subflow ++endpoint ++ ++.sp ++.PP ++The ++.B limits ++object specifies the constraints for subflow creations: ++ ++.TS ++l l. ++ip mptcp limits show get current MPTCP subflow creation limits ++ip mptcp limits set change the MPTCP subflow creation limits ++.TE ++ ++.TP ++.IR SUBFLOW_NR ++specifies the maximum number of additional subflows allowed for each MPTCP ++connection. Additional subflows can be created due to: incoming accepted ++ADD_ADDR option, local ++.BR subflow ++endpoints, additional subflows started by the peer. ++ ++.TP ++.IR ADD_ADDR_ACCEPTED_NR ++specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP ++connection. The MPTCP path manager will try to create a new subflow for ++each accepted ADD_ADDR option, respecting the ++.IR SUBFLOW_NR ++limit. ++ ++.SH AUTHOR ++Original Manpage by Paolo Abeni +-- +2.26.2 + diff --git a/SOURCES/0022-man-ip.8-add-reference-to-mptcp-man-page.patch b/SOURCES/0022-man-ip.8-add-reference-to-mptcp-man-page.patch new file mode 100644 index 0000000..c38458f --- /dev/null +++ b/SOURCES/0022-man-ip.8-add-reference-to-mptcp-man-page.patch @@ -0,0 +1,70 @@ +From c2e8f8b4c1980c773b967953b795f81942e209fb Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 19:28:45 +0200 +Subject: [PATCH] man: ip.8: add reference to mptcp man-page + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: unknown commit 0c42c6b130196 + +commit 0c42c6b130196d1d7e87acc5122f8fd325e75c5b +Author: Paolo Abeni +Date: Wed Apr 29 19:17:22 2020 +0200 + + man: ip.8: add reference to mptcp man-page + + While at it, additionally fix a mandoc warning in mptcp.8 + + Signed-off-by: Paolo Abeni + Signed-off-by: David Ahern +--- + man/man8/ip-mptcp.8 | 1 - + man/man8/ip.8 | 7 ++++++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/man/man8/ip-mptcp.8 b/man/man8/ip-mptcp.8 +index f6457e97efbe8..ef8409ea4a24d 100644 +--- a/man/man8/ip-mptcp.8 ++++ b/man/man8/ip-mptcp.8 +@@ -2,7 +2,6 @@ + .SH "NAME" + ip-mptcp \- MPTCP path manager configuration + .SH "SYNOPSIS" +-.sp + .ad l + .in +8 + .ti -8 +diff --git a/man/man8/ip.8 b/man/man8/ip.8 +index c425aaf1d506e..f391237b4fcae 100644 +--- a/man/man8/ip.8 ++++ b/man/man8/ip.8 +@@ -22,7 +22,7 @@ ip \- show / manipulate routing, network devices, interfaces and tunnels + .BR link " | " address " | " addrlabel " | " route " | " rule " | " neigh " | "\ + ntable " | " tunnel " | " tuntap " | " maddress " | " mroute " | " mrule " | "\ + monitor " | " xfrm " | " netns " | " l2tp " | " tcp_metrics " | " token " | "\ +- macsec " | " vrf " }" ++ macsec " | " vrf " | " mptcp " }" + .sp + + .ti -8 +@@ -268,6 +268,10 @@ readability. + .B monitor + - watch for netlink messages. + ++.TP ++.B mptcp ++- manage MPTCP path manager. ++ + .TP + .B mroute + - multicast routing cache entry. +@@ -406,6 +410,7 @@ was written by Alexey N. Kuznetsov and added in Linux 2.2. + .BR ip-link (8), + .BR ip-maddress (8), + .BR ip-monitor (8), ++.BR ip-mptcp (8), + .BR ip-mroute (8), + .BR ip-neighbour (8), + .BR ip-netns (8), +-- +2.26.2 + diff --git a/SOURCES/0023-Update-kernel-headers.patch b/SOURCES/0023-Update-kernel-headers.patch new file mode 100644 index 0000000..7d329c4 --- /dev/null +++ b/SOURCES/0023-Update-kernel-headers.patch @@ -0,0 +1,568 @@ +From f0023a7d874697821516583c1b3be95e2f110668 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:41:59 +0200 +Subject: [PATCH] Update kernel headers + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: iproute2.git commit 7438afd2cc8d3 +Conflicts: on devlink uapi due to missing commit 9dcd8788fe6bc + ("Update kernel headers") + +commit 7438afd2cc8d37fd7f12e29963e1d926de53dda7 +Author: David Ahern +Date: Mon Nov 25 23:13:09 2019 +0000 + + Update kernel headers + + Update kernel headers to commit: + c431047c4efe ("enetc: add support Credit Based Shaper(CBS) for hardware offload") + + Signed-off-by: David Ahern +--- + include/uapi/linux/bpf.h | 130 ++++++++++++++------ + include/uapi/linux/gen_stats.h | 5 +- + include/uapi/linux/lwtunnel.h | 41 ++++++ + include/uapi/linux/netfilter/ipset/ip_set.h | 2 + + include/uapi/linux/pkt_cls.h | 29 +++++ + include/uapi/linux/pkt_sched.h | 22 ++-- + include/uapi/linux/sctp.h | 15 +++ + include/uapi/linux/tc_act/tc_tunnel_key.h | 29 +++++ + include/uapi/linux/tipc.h | 21 ++++ + include/uapi/linux/tipc_netlink.h | 4 + + 10 files changed, 246 insertions(+), 52 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 94aa5a1d38215..bf3475f915cf1 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -173,6 +173,7 @@ enum bpf_prog_type { + BPF_PROG_TYPE_CGROUP_SYSCTL, + BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE, + BPF_PROG_TYPE_CGROUP_SOCKOPT, ++ BPF_PROG_TYPE_TRACING, + }; + + enum bpf_attach_type { +@@ -199,6 +200,9 @@ enum bpf_attach_type { + BPF_CGROUP_UDP6_RECVMSG, + BPF_CGROUP_GETSOCKOPT, + BPF_CGROUP_SETSOCKOPT, ++ BPF_TRACE_RAW_TP, ++ BPF_TRACE_FENTRY, ++ BPF_TRACE_FEXIT, + __MAX_BPF_ATTACH_TYPE + }; + +@@ -344,6 +348,9 @@ enum bpf_attach_type { + /* Clone map from listener for newly accepted socket */ + #define BPF_F_CLONE (1U << 9) + ++/* Enable memory-mapping BPF map */ ++#define BPF_F_MMAPABLE (1U << 10) ++ + /* flags for BPF_PROG_QUERY */ + #define BPF_F_QUERY_EFFECTIVE (1U << 0) + +@@ -421,6 +428,7 @@ union bpf_attr { + __aligned_u64 line_info; /* line info */ + __u32 line_info_cnt; /* number of bpf_line_info records */ + __u32 attach_btf_id; /* in-kernel BTF type id to attach to */ ++ __u32 attach_prog_fd; /* 0 to attach to vmlinux */ + }; + + struct { /* anonymous struct used by BPF_OBJ_* commands */ +@@ -579,10 +587,13 @@ union bpf_attr { + * Return + * 0 on success, or a negative error in case of failure. + * +- * int bpf_probe_read(void *dst, u32 size, const void *src) ++ * int bpf_probe_read(void *dst, u32 size, const void *unsafe_ptr) + * Description + * For tracing programs, safely attempt to read *size* bytes from +- * address *src* and store the data in *dst*. ++ * kernel space address *unsafe_ptr* and store the data in *dst*. ++ * ++ * Generally, use bpf_probe_read_user() or bpf_probe_read_kernel() ++ * instead. + * Return + * 0 on success, or a negative error in case of failure. + * +@@ -1444,45 +1455,14 @@ union bpf_attr { + * Return + * 0 on success, or a negative error in case of failure. + * +- * int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr) ++ * int bpf_probe_read_str(void *dst, u32 size, const void *unsafe_ptr) + * Description +- * Copy a NUL terminated string from an unsafe address +- * *unsafe_ptr* to *dst*. The *size* should include the +- * terminating NUL byte. In case the string length is smaller than +- * *size*, the target is not padded with further NUL bytes. If the +- * string length is larger than *size*, just *size*-1 bytes are +- * copied and the last byte is set to NUL. +- * +- * On success, the length of the copied string is returned. This +- * makes this helper useful in tracing programs for reading +- * strings, and more importantly to get its length at runtime. See +- * the following snippet: +- * +- * :: +- * +- * SEC("kprobe/sys_open") +- * void bpf_sys_open(struct pt_regs *ctx) +- * { +- * char buf[PATHLEN]; // PATHLEN is defined to 256 +- * int res = bpf_probe_read_str(buf, sizeof(buf), +- * ctx->di); +- * +- * // Consume buf, for example push it to +- * // userspace via bpf_perf_event_output(); we +- * // can use res (the string length) as event +- * // size, after checking its boundaries. +- * } ++ * Copy a NUL terminated string from an unsafe kernel address ++ * *unsafe_ptr* to *dst*. See bpf_probe_read_kernel_str() for ++ * more details. + * +- * In comparison, using **bpf_probe_read()** helper here instead +- * to read the string would require to estimate the length at +- * compile time, and would often result in copying more memory +- * than necessary. +- * +- * Another useful use case is when parsing individual process +- * arguments or individual environment variables navigating +- * *current*\ **->mm->arg_start** and *current*\ +- * **->mm->env_start**: using this helper and the return value, +- * one can quickly iterate at the right offset of the memory area. ++ * Generally, use bpf_probe_read_user_str() or bpf_probe_read_kernel_str() ++ * instead. + * Return + * On success, the strictly positive length of the string, + * including the trailing NUL character. On error, a negative +@@ -2793,6 +2773,72 @@ union bpf_attr { + * restricted to raw_tracepoint bpf programs. + * Return + * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_probe_read_user(void *dst, u32 size, const void *unsafe_ptr) ++ * Description ++ * Safely attempt to read *size* bytes from user space address ++ * *unsafe_ptr* and store the data in *dst*. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_probe_read_kernel(void *dst, u32 size, const void *unsafe_ptr) ++ * Description ++ * Safely attempt to read *size* bytes from kernel space address ++ * *unsafe_ptr* and store the data in *dst*. ++ * Return ++ * 0 on success, or a negative error in case of failure. ++ * ++ * int bpf_probe_read_user_str(void *dst, u32 size, const void *unsafe_ptr) ++ * Description ++ * Copy a NUL terminated string from an unsafe user address ++ * *unsafe_ptr* to *dst*. The *size* should include the ++ * terminating NUL byte. In case the string length is smaller than ++ * *size*, the target is not padded with further NUL bytes. If the ++ * string length is larger than *size*, just *size*-1 bytes are ++ * copied and the last byte is set to NUL. ++ * ++ * On success, the length of the copied string is returned. This ++ * makes this helper useful in tracing programs for reading ++ * strings, and more importantly to get its length at runtime. See ++ * the following snippet: ++ * ++ * :: ++ * ++ * SEC("kprobe/sys_open") ++ * void bpf_sys_open(struct pt_regs *ctx) ++ * { ++ * char buf[PATHLEN]; // PATHLEN is defined to 256 ++ * int res = bpf_probe_read_user_str(buf, sizeof(buf), ++ * ctx->di); ++ * ++ * // Consume buf, for example push it to ++ * // userspace via bpf_perf_event_output(); we ++ * // can use res (the string length) as event ++ * // size, after checking its boundaries. ++ * } ++ * ++ * In comparison, using **bpf_probe_read_user()** helper here ++ * instead to read the string would require to estimate the length ++ * at compile time, and would often result in copying more memory ++ * than necessary. ++ * ++ * Another useful use case is when parsing individual process ++ * arguments or individual environment variables navigating ++ * *current*\ **->mm->arg_start** and *current*\ ++ * **->mm->env_start**: using this helper and the return value, ++ * one can quickly iterate at the right offset of the memory area. ++ * Return ++ * On success, the strictly positive length of the string, ++ * including the trailing NUL character. On error, a negative ++ * value. ++ * ++ * int bpf_probe_read_kernel_str(void *dst, u32 size, const void *unsafe_ptr) ++ * Description ++ * Copy a NUL terminated string from an unsafe kernel address *unsafe_ptr* ++ * to *dst*. Same semantics as with bpf_probe_read_user_str() apply. ++ * Return ++ * On success, the strictly positive length of the string, including ++ * the trailing NUL character. On error, a negative value. + */ + #define __BPF_FUNC_MAPPER(FN) \ + FN(unspec), \ +@@ -2906,7 +2952,11 @@ union bpf_attr { + FN(sk_storage_delete), \ + FN(send_signal), \ + FN(tcp_gen_syncookie), \ +- FN(skb_output), ++ FN(skb_output), \ ++ FN(probe_read_user), \ ++ FN(probe_read_kernel), \ ++ FN(probe_read_user_str), \ ++ FN(probe_read_kernel_str), + + /* integer value in 'imm' field of BPF_CALL instruction selects which helper + * function eBPF program intends to call +diff --git a/include/uapi/linux/gen_stats.h b/include/uapi/linux/gen_stats.h +index 065408e16a807..852f234f1fd63 100644 +--- a/include/uapi/linux/gen_stats.h ++++ b/include/uapi/linux/gen_stats.h +@@ -13,6 +13,7 @@ enum { + TCA_STATS_RATE_EST64, + TCA_STATS_PAD, + TCA_STATS_BASIC_HW, ++ TCA_STATS_PKT64, + __TCA_STATS_MAX, + }; + #define TCA_STATS_MAX (__TCA_STATS_MAX - 1) +@@ -26,10 +27,6 @@ struct gnet_stats_basic { + __u64 bytes; + __u32 packets; + }; +-struct gnet_stats_basic_packed { +- __u64 bytes; +- __u32 packets; +-} __attribute__ ((packed)); + + /** + * struct gnet_stats_rate_est - rate estimator +diff --git a/include/uapi/linux/lwtunnel.h b/include/uapi/linux/lwtunnel.h +index 0ba94063c1809..b7c0191fd1b5f 100644 +--- a/include/uapi/linux/lwtunnel.h ++++ b/include/uapi/linux/lwtunnel.h +@@ -28,6 +28,7 @@ enum lwtunnel_ip_t { + LWTUNNEL_IP_TOS, + LWTUNNEL_IP_FLAGS, + LWTUNNEL_IP_PAD, ++ LWTUNNEL_IP_OPTS, + __LWTUNNEL_IP_MAX, + }; + +@@ -42,11 +43,51 @@ enum lwtunnel_ip6_t { + LWTUNNEL_IP6_TC, + LWTUNNEL_IP6_FLAGS, + LWTUNNEL_IP6_PAD, ++ LWTUNNEL_IP6_OPTS, + __LWTUNNEL_IP6_MAX, + }; + + #define LWTUNNEL_IP6_MAX (__LWTUNNEL_IP6_MAX - 1) + ++enum { ++ LWTUNNEL_IP_OPTS_UNSPEC, ++ LWTUNNEL_IP_OPTS_GENEVE, ++ LWTUNNEL_IP_OPTS_VXLAN, ++ LWTUNNEL_IP_OPTS_ERSPAN, ++ __LWTUNNEL_IP_OPTS_MAX, ++}; ++ ++#define LWTUNNEL_IP_OPTS_MAX (__LWTUNNEL_IP_OPTS_MAX - 1) ++ ++enum { ++ LWTUNNEL_IP_OPT_GENEVE_UNSPEC, ++ LWTUNNEL_IP_OPT_GENEVE_CLASS, ++ LWTUNNEL_IP_OPT_GENEVE_TYPE, ++ LWTUNNEL_IP_OPT_GENEVE_DATA, ++ __LWTUNNEL_IP_OPT_GENEVE_MAX, ++}; ++ ++#define LWTUNNEL_IP_OPT_GENEVE_MAX (__LWTUNNEL_IP_OPT_GENEVE_MAX - 1) ++ ++enum { ++ LWTUNNEL_IP_OPT_VXLAN_UNSPEC, ++ LWTUNNEL_IP_OPT_VXLAN_GBP, ++ __LWTUNNEL_IP_OPT_VXLAN_MAX, ++}; ++ ++#define LWTUNNEL_IP_OPT_VXLAN_MAX (__LWTUNNEL_IP_OPT_VXLAN_MAX - 1) ++ ++enum { ++ LWTUNNEL_IP_OPT_ERSPAN_UNSPEC, ++ LWTUNNEL_IP_OPT_ERSPAN_VER, ++ LWTUNNEL_IP_OPT_ERSPAN_INDEX, ++ LWTUNNEL_IP_OPT_ERSPAN_DIR, ++ LWTUNNEL_IP_OPT_ERSPAN_HWID, ++ __LWTUNNEL_IP_OPT_ERSPAN_MAX, ++}; ++ ++#define LWTUNNEL_IP_OPT_ERSPAN_MAX (__LWTUNNEL_IP_OPT_ERSPAN_MAX - 1) ++ + enum { + LWT_BPF_PROG_UNSPEC, + LWT_BPF_PROG_FD, +diff --git a/include/uapi/linux/netfilter/ipset/ip_set.h b/include/uapi/linux/netfilter/ipset/ip_set.h +index c512003dba6ba..4b372f46f0d04 100644 +--- a/include/uapi/linux/netfilter/ipset/ip_set.h ++++ b/include/uapi/linux/netfilter/ipset/ip_set.h +@@ -205,6 +205,8 @@ enum ipset_cadt_flags { + IPSET_FLAG_WITH_FORCEADD = (1 << IPSET_FLAG_BIT_WITH_FORCEADD), + IPSET_FLAG_BIT_WITH_SKBINFO = 6, + IPSET_FLAG_WITH_SKBINFO = (1 << IPSET_FLAG_BIT_WITH_SKBINFO), ++ IPSET_FLAG_BIT_IFACE_WILDCARD = 7, ++ IPSET_FLAG_IFACE_WILDCARD = (1 << IPSET_FLAG_BIT_IFACE_WILDCARD), + IPSET_FLAG_CADT_MAX = 15, + }; + +diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h +index c6ad22f76edee..449a63971451f 100644 +--- a/include/uapi/linux/pkt_cls.h ++++ b/include/uapi/linux/pkt_cls.h +@@ -571,6 +571,14 @@ enum { + * TCA_FLOWER_KEY_ENC_OPT_GENEVE_ + * attributes + */ ++ TCA_FLOWER_KEY_ENC_OPTS_VXLAN, /* Nested ++ * TCA_FLOWER_KEY_ENC_OPT_VXLAN_ ++ * attributes ++ */ ++ TCA_FLOWER_KEY_ENC_OPTS_ERSPAN, /* Nested ++ * TCA_FLOWER_KEY_ENC_OPT_ERSPAN_ ++ * attributes ++ */ + __TCA_FLOWER_KEY_ENC_OPTS_MAX, + }; + +@@ -588,6 +596,27 @@ enum { + #define TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX \ + (__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1) + ++enum { ++ TCA_FLOWER_KEY_ENC_OPT_VXLAN_UNSPEC, ++ TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP, /* u32 */ ++ __TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX, ++}; ++ ++#define TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX \ ++ (__TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX - 1) ++ ++enum { ++ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_UNSPEC, ++ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER, /* u8 */ ++ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX, /* be32 */ ++ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR, /* u8 */ ++ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID, /* u8 */ ++ __TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX, ++}; ++ ++#define TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX \ ++ (__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX - 1) ++ + enum { + TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0), + TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1), +diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h +index 18f185299f472..dab60bd8f0f4a 100644 +--- a/include/uapi/linux/pkt_sched.h ++++ b/include/uapi/linux/pkt_sched.h +@@ -950,19 +950,25 @@ enum { + TCA_PIE_BETA, + TCA_PIE_ECN, + TCA_PIE_BYTEMODE, ++ TCA_PIE_DQ_RATE_ESTIMATOR, + __TCA_PIE_MAX + }; + #define TCA_PIE_MAX (__TCA_PIE_MAX - 1) + + struct tc_pie_xstats { +- __u64 prob; /* current probability */ +- __u32 delay; /* current delay in ms */ +- __u32 avg_dq_rate; /* current average dq_rate in bits/pie_time */ +- __u32 packets_in; /* total number of packets enqueued */ +- __u32 dropped; /* packets dropped due to pie_action */ +- __u32 overlimit; /* dropped due to lack of space in queue */ +- __u32 maxq; /* maximum queue size */ +- __u32 ecn_mark; /* packets marked with ecn*/ ++ __u64 prob; /* current probability */ ++ __u32 delay; /* current delay in ms */ ++ __u32 avg_dq_rate; /* current average dq_rate in ++ * bits/pie_time ++ */ ++ __u32 dq_rate_estimating; /* is avg_dq_rate being calculated? */ ++ __u32 packets_in; /* total number of packets enqueued */ ++ __u32 dropped; /* packets dropped due to pie_action */ ++ __u32 overlimit; /* dropped due to lack of space ++ * in queue ++ */ ++ __u32 maxq; /* maximum queue size */ ++ __u32 ecn_mark; /* packets marked with ecn*/ + }; + + /* CBS */ +diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h +index 0d4c1507a169d..f8f218b16c280 100644 +--- a/include/uapi/linux/sctp.h ++++ b/include/uapi/linux/sctp.h +@@ -105,6 +105,7 @@ typedef __s32 sctp_assoc_t; + #define SCTP_DEFAULT_SNDINFO 34 + #define SCTP_AUTH_DEACTIVATE_KEY 35 + #define SCTP_REUSE_PORT 36 ++#define SCTP_PEER_ADDR_THLDS_V2 37 + + /* Internal Socket Options. Some of the sctp library functions are + * implemented using these socket options. +@@ -137,6 +138,8 @@ typedef __s32 sctp_assoc_t; + #define SCTP_ASCONF_SUPPORTED 128 + #define SCTP_AUTH_SUPPORTED 129 + #define SCTP_ECN_SUPPORTED 130 ++#define SCTP_EXPOSE_POTENTIALLY_FAILED_STATE 131 ++#define SCTP_EXPOSE_PF_STATE SCTP_EXPOSE_POTENTIALLY_FAILED_STATE + + /* PR-SCTP policies */ + #define SCTP_PR_SCTP_NONE 0x0000 +@@ -410,6 +413,8 @@ enum sctp_spc_state { + SCTP_ADDR_ADDED, + SCTP_ADDR_MADE_PRIM, + SCTP_ADDR_CONFIRMED, ++ SCTP_ADDR_POTENTIALLY_FAILED, ++#define SCTP_ADDR_PF SCTP_ADDR_POTENTIALLY_FAILED + }; + + +@@ -917,6 +922,7 @@ struct sctp_paddrinfo { + enum sctp_spinfo_state { + SCTP_INACTIVE, + SCTP_PF, ++#define SCTP_POTENTIALLY_FAILED SCTP_PF + SCTP_ACTIVE, + SCTP_UNCONFIRMED, + SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */ +@@ -1062,6 +1068,15 @@ struct sctp_paddrthlds { + __u16 spt_pathpfthld; + }; + ++/* Use a new structure with spt_pathcpthld for back compatibility */ ++struct sctp_paddrthlds_v2 { ++ sctp_assoc_t spt_assoc_id; ++ struct sockaddr_storage spt_address; ++ __u16 spt_pathmaxrxt; ++ __u16 spt_pathpfthld; ++ __u16 spt_pathcpthld; ++}; ++ + /* + * Socket Option for Getting the Association/Stream-Specific PR-SCTP Status + */ +diff --git a/include/uapi/linux/tc_act/tc_tunnel_key.h b/include/uapi/linux/tc_act/tc_tunnel_key.h +index 41c8b462c177c..3f10dc4e7a4bb 100644 +--- a/include/uapi/linux/tc_act/tc_tunnel_key.h ++++ b/include/uapi/linux/tc_act/tc_tunnel_key.h +@@ -50,6 +50,14 @@ enum { + * TCA_TUNNEL_KEY_ENC_OPTS_ + * attributes + */ ++ TCA_TUNNEL_KEY_ENC_OPTS_VXLAN, /* Nested ++ * TCA_TUNNEL_KEY_ENC_OPTS_ ++ * attributes ++ */ ++ TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN, /* Nested ++ * TCA_TUNNEL_KEY_ENC_OPTS_ ++ * attributes ++ */ + __TCA_TUNNEL_KEY_ENC_OPTS_MAX, + }; + +@@ -67,4 +75,25 @@ enum { + #define TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX \ + (__TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX - 1) + ++enum { ++ TCA_TUNNEL_KEY_ENC_OPT_VXLAN_UNSPEC, ++ TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP, /* u32 */ ++ __TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX, ++}; ++ ++#define TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX \ ++ (__TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX - 1) ++ ++enum { ++ TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_UNSPEC, ++ TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER, /* u8 */ ++ TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX, /* be32 */ ++ TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR, /* u8 */ ++ TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID, /* u8 */ ++ __TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX, ++}; ++ ++#define TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX \ ++ (__TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX - 1) ++ + #endif +diff --git a/include/uapi/linux/tipc.h b/include/uapi/linux/tipc.h +index 0f6f28b2e3010..de5bcd2a09fae 100644 +--- a/include/uapi/linux/tipc.h ++++ b/include/uapi/linux/tipc.h +@@ -233,6 +233,27 @@ struct tipc_sioc_nodeid_req { + char node_id[TIPC_NODEID_LEN]; + }; + ++/* ++ * TIPC Crypto, AEAD ++ */ ++#define TIPC_AEAD_ALG_NAME (32) ++ ++struct tipc_aead_key { ++ char alg_name[TIPC_AEAD_ALG_NAME]; ++ unsigned int keylen; /* in bytes */ ++ char key[]; ++}; ++ ++#define TIPC_AEAD_KEYLEN_MIN (16 + 4) ++#define TIPC_AEAD_KEYLEN_MAX (32 + 4) ++#define TIPC_AEAD_KEY_SIZE_MAX (sizeof(struct tipc_aead_key) + \ ++ TIPC_AEAD_KEYLEN_MAX) ++ ++static __inline__ int tipc_aead_key_size(struct tipc_aead_key *key) ++{ ++ return sizeof(*key) + key->keylen; ++} ++ + /* The macros and functions below are deprecated: + */ + +diff --git a/include/uapi/linux/tipc_netlink.h b/include/uapi/linux/tipc_netlink.h +index efb958fd167d0..6c2194ab745bd 100644 +--- a/include/uapi/linux/tipc_netlink.h ++++ b/include/uapi/linux/tipc_netlink.h +@@ -63,6 +63,8 @@ enum { + TIPC_NL_PEER_REMOVE, + TIPC_NL_BEARER_ADD, + TIPC_NL_UDP_GET_REMOTEIP, ++ TIPC_NL_KEY_SET, ++ TIPC_NL_KEY_FLUSH, + + __TIPC_NL_CMD_MAX, + TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1 +@@ -160,6 +162,8 @@ enum { + TIPC_NLA_NODE_UNSPEC, + TIPC_NLA_NODE_ADDR, /* u32 */ + TIPC_NLA_NODE_UP, /* flag */ ++ TIPC_NLA_NODE_ID, /* data */ ++ TIPC_NLA_NODE_KEY, /* data */ + + __TIPC_NLA_NODE_MAX, + TIPC_NLA_NODE_MAX = __TIPC_NLA_NODE_MAX - 1 +-- +2.26.2 + diff --git a/SOURCES/0024-iproute_lwtunnel-add-options-support-for-geneve-meta.patch b/SOURCES/0024-iproute_lwtunnel-add-options-support-for-geneve-meta.patch new file mode 100644 index 0000000..e093682 --- /dev/null +++ b/SOURCES/0024-iproute_lwtunnel-add-options-support-for-geneve-meta.patch @@ -0,0 +1,297 @@ +From c6f909bd0f40c58f39f857e1c57638cb41241fa2 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:43:01 +0200 +Subject: [PATCH] iproute_lwtunnel: add options support for geneve metadata + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit ca7614d4c6f45 + +commit ca7614d4c6f456187d831a8202bb4a8559a72f8b +Author: Xin Long +Date: Mon Apr 27 18:27:45 2020 +0800 + + iproute_lwtunnel: add options support for geneve metadata + + This patch is to add LWTUNNEL_IP(6)_OPTS and LWTUNNEL_IP_OPTS_GENEVE's + parse and print to implement geneve options support in iproute_lwtunnel. + + Options are expressed as class:type:data and multiple options may be + listed using a comma delimiter, class and type are numbers and data + is a hex string. + + With this patch, users can add and dump geneve options like: + + # ip netns add a + # ip netns add b + # ip -n a link add eth0 type veth peer name eth0 netns b + # ip -n a link set eth0 up; ip -n b link set eth0 up + # ip -n a addr add 10.1.0.1/24 dev eth0 + # ip -n b addr add 10.1.0.2/24 dev eth0 + # ip -n b link add geneve1 type geneve id 1 remote 10.1.0.1 ttl 64 + # ip -n b addr add 1.1.1.1/24 dev geneve1 + # ip -n b link set geneve1 up + # ip -n b route add 2.1.1.0/24 dev geneve1 + # ip -n a link add geneve1 type geneve external + # ip -n a addr add 2.1.1.1/24 dev geneve1 + # ip -n a link set geneve1 up + # ip -n a route add 1.1.1.0/24 encap ip id 1 geneve_opts \ + 1:1:1212121234567890,1:1:1212121234567890,1:1:1212121234567890 \ + dst 10.1.0.2 dev geneve1 + # ip -n a route show + # ip netns exec a ping 1.1.1.1 -c 1 + + 1.1.1.0/24 encap ip id 1 src 0.0.0.0 dst 10.1.0.2 ttl 0 tos 0 + geneve_opts 1:1:1212121234567890,1:1:1212121234567890 ... + + PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. + 64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=0.079 ms + + v1->v2: + - improve the changelog. + - use PRINT_ANY to support dumping with json format. + v2->v3: + - implement proper JSON array for opts instead of just bunch of strings. + v3->v4: + - keep the same format between input and output, json and non json. + - print class and type as uint and print data as hex string. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + ip/iproute_lwtunnel.c | 174 +++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 172 insertions(+), 2 deletions(-) + +diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c +index 60f34a32a6e5b..76d906c47c44f 100644 +--- a/ip/iproute_lwtunnel.c ++++ b/ip/iproute_lwtunnel.c +@@ -291,6 +291,54 @@ static void print_encap_mpls(FILE *fp, struct rtattr *encap) + rta_getattr_u8(tb[MPLS_IPTUNNEL_TTL])); + } + ++static void lwtunnel_print_geneve_opts(struct rtattr *attr) ++{ ++ struct rtattr *tb[LWTUNNEL_IP_OPT_GENEVE_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ int rem = RTA_PAYLOAD(attr); ++ char *name = "geneve_opts"; ++ int data_len, offset = 0; ++ char data[rem * 2 + 1]; ++ __u16 class; ++ __u8 type; ++ ++ print_nl(); ++ print_string(PRINT_FP, name, "\t%s ", name); ++ open_json_array(PRINT_JSON, name); ++ ++ while (rem) { ++ parse_rtattr(tb, LWTUNNEL_IP_OPT_GENEVE_MAX, i, rem); ++ class = rta_getattr_be16(tb[LWTUNNEL_IP_OPT_GENEVE_CLASS]); ++ type = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_GENEVE_TYPE]); ++ data_len = RTA_PAYLOAD(tb[LWTUNNEL_IP_OPT_GENEVE_DATA]); ++ hexstring_n2a(RTA_DATA(tb[LWTUNNEL_IP_OPT_GENEVE_DATA]), ++ data_len, data, sizeof(data)); ++ offset += data_len + 20; ++ rem -= data_len + 20; ++ i = RTA_DATA(attr) + offset; ++ ++ open_json_object(NULL); ++ print_uint(PRINT_ANY, "class", "%u", class); ++ print_uint(PRINT_ANY, "type", ":%u", type); ++ if (rem) ++ print_string(PRINT_ANY, "data", ":%s,", data); ++ else ++ print_string(PRINT_ANY, "data", ":%s ", data); ++ close_json_object(); ++ } ++ ++ close_json_array(PRINT_JSON, name); ++} ++ ++static void lwtunnel_print_opts(struct rtattr *attr) ++{ ++ struct rtattr *tb_opt[LWTUNNEL_IP_OPTS_MAX + 1]; ++ ++ parse_rtattr_nested(tb_opt, LWTUNNEL_IP_OPTS_MAX, attr); ++ if (tb_opt[LWTUNNEL_IP_OPTS_GENEVE]) ++ lwtunnel_print_geneve_opts(tb_opt[LWTUNNEL_IP_OPTS_GENEVE]); ++} ++ + static void print_encap_ip(FILE *fp, struct rtattr *encap) + { + struct rtattr *tb[LWTUNNEL_IP_MAX+1]; +@@ -329,6 +377,9 @@ static void print_encap_ip(FILE *fp, struct rtattr *encap) + if (flags & TUNNEL_SEQ) + print_bool(PRINT_ANY, "seq", "seq ", true); + } ++ ++ if (tb[LWTUNNEL_IP_OPTS]) ++ lwtunnel_print_opts(tb[LWTUNNEL_IP_OPTS]); + } + + static void print_encap_ila(FILE *fp, struct rtattr *encap) +@@ -401,6 +452,9 @@ static void print_encap_ip6(FILE *fp, struct rtattr *encap) + if (flags & TUNNEL_SEQ) + print_bool(PRINT_ANY, "seq", "seq ", true); + } ++ ++ if (tb[LWTUNNEL_IP6_OPTS]) ++ lwtunnel_print_opts(tb[LWTUNNEL_IP6_OPTS]); + } + + static void print_encap_bpf(FILE *fp, struct rtattr *encap) +@@ -795,11 +849,97 @@ static int parse_encap_mpls(struct rtattr *rta, size_t len, + return 0; + } + ++static int lwtunnel_parse_geneve_opt(char *str, size_t len, struct rtattr *rta) ++{ ++ struct rtattr *nest; ++ char *token; ++ int i, err; ++ ++ nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_GENEVE | NLA_F_NESTED); ++ i = 1; ++ token = strsep(&str, ":"); ++ while (token) { ++ switch (i) { ++ case LWTUNNEL_IP_OPT_GENEVE_CLASS: ++ { ++ __be16 opt_class; ++ ++ if (!strlen(token)) ++ break; ++ err = get_be16(&opt_class, token, 0); ++ if (err) ++ return err; ++ ++ rta_addattr16(rta, len, i, opt_class); ++ break; ++ } ++ case LWTUNNEL_IP_OPT_GENEVE_TYPE: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ rta_addattr8(rta, len, i, opt_type); ++ break; ++ } ++ case LWTUNNEL_IP_OPT_GENEVE_DATA: ++ { ++ size_t token_len = strlen(token); ++ __u8 *opts; ++ ++ if (!token_len) ++ break; ++ opts = malloc(token_len / 2); ++ if (!opts) ++ return -1; ++ if (hex2mem(token, opts, token_len / 2) < 0) { ++ free(opts); ++ return -1; ++ } ++ rta_addattr_l(rta, len, i, opts, token_len / 2); ++ free(opts); ++ ++ break; ++ } ++ default: ++ fprintf(stderr, "Unknown \"geneve_opts\" type\n"); ++ return -1; ++ } ++ ++ token = strsep(&str, ":"); ++ i++; ++ } ++ rta_nest_end(rta, nest); ++ ++ return 0; ++} ++ ++static int lwtunnel_parse_geneve_opts(char *str, size_t len, struct rtattr *rta) ++{ ++ char *token; ++ int err; ++ ++ token = strsep(&str, ","); ++ while (token) { ++ err = lwtunnel_parse_geneve_opt(token, len, rta); ++ if (err) ++ return err; ++ ++ token = strsep(&str, ","); ++ } ++ ++ return 0; ++} ++ + static int parse_encap_ip(struct rtattr *rta, size_t len, + int *argcp, char ***argvp) + { + int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0; +- int key_ok = 0, csum_ok = 0, seq_ok = 0; ++ int key_ok = 0, csum_ok = 0, seq_ok = 0, opts_ok = 0; + char **argv = *argvp; + int argc = *argcp; + int ret = 0; +@@ -851,6 +991,21 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, + if (get_u8(&ttl, *argv, 0)) + invarg("\"ttl\" value is invalid\n", *argv); + ret = rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl); ++ } else if (strcmp(*argv, "geneve_opts") == 0) { ++ struct rtattr *nest; ++ ++ if (opts_ok++) ++ duparg2("opts", *argv); ++ ++ NEXT_ARG(); ++ ++ nest = rta_nest(rta, len, ++ LWTUNNEL_IP_OPTS | NLA_F_NESTED); ++ ret = lwtunnel_parse_geneve_opts(*argv, len, rta); ++ if (ret) ++ invarg("\"geneve_opts\" value is invalid\n", ++ *argv); ++ rta_nest_end(rta, nest); + } else if (strcmp(*argv, "key") == 0) { + if (key_ok++) + duparg2("key", *argv); +@@ -966,7 +1121,7 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + int *argcp, char ***argvp) + { + int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0; +- int key_ok = 0, csum_ok = 0, seq_ok = 0; ++ int key_ok = 0, csum_ok = 0, seq_ok = 0, opts_ok = 0; + char **argv = *argvp; + int argc = *argcp; + int ret = 0; +@@ -1020,6 +1175,21 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + *argv); + ret = rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT, + hoplimit); ++ } else if (strcmp(*argv, "geneve_opts") == 0) { ++ struct rtattr *nest; ++ ++ if (opts_ok++) ++ duparg2("opts", *argv); ++ ++ NEXT_ARG(); ++ ++ nest = rta_nest(rta, len, ++ LWTUNNEL_IP_OPTS | NLA_F_NESTED); ++ ret = lwtunnel_parse_geneve_opts(*argv, len, rta); ++ if (ret) ++ invarg("\"geneve_opts\" value is invalid\n", ++ *argv); ++ rta_nest_end(rta, nest); + } else if (strcmp(*argv, "key") == 0) { + if (key_ok++) + duparg2("key", *argv); +-- +2.26.2 + diff --git a/SOURCES/0025-iproute_lwtunnel-add-options-support-for-vxlan-metad.patch b/SOURCES/0025-iproute_lwtunnel-add-options-support-for-vxlan-metad.patch new file mode 100644 index 0000000..cc25df9 --- /dev/null +++ b/SOURCES/0025-iproute_lwtunnel-add-options-support-for-vxlan-metad.patch @@ -0,0 +1,175 @@ +From 873511fb86756c40631f80963356179627d69d49 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:43:01 +0200 +Subject: [PATCH] iproute_lwtunnel: add options support for vxlan metadata + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit b1bc0f3892222 + +commit b1bc0f38922220b379ed39552a5e2a7cf9dccd92 +Author: Xin Long +Date: Mon Apr 27 18:27:46 2020 +0800 + + iproute_lwtunnel: add options support for vxlan metadata + + This patch is to add LWTUNNEL_IP_OPTS_VXLAN's parse and print to implement + vxlan options support in iproute_lwtunnel. + + Option is expressed a number for gbp only, and vxlan doesn't support + multiple options. + + With this patch, users can add and dump vxlan options like: + + # ip netns add a + # ip netns add b + # ip -n a link add eth0 type veth peer name eth0 netns b + # ip -n a link set eth0 up + # ip -n b link set eth0 up + # ip -n a addr add 10.1.0.1/24 dev eth0 + # ip -n b addr add 10.1.0.2/24 dev eth0 + # ip -n b link add vxlan1 type vxlan id 1 local 10.1.0.2 \ + remote 10.1.0.1 dev eth0 ttl 64 gbp + # ip -n b addr add 1.1.1.1/24 dev vxlan1 + # ip -n b link set vxlan1 up + # ip -n b route add 2.1.1.0/24 dev vxlan1 + # ip -n a link add vxlan1 type vxlan local 10.1.0.1 dev eth0 ttl 64 \ + gbp external + # ip -n a addr add 2.1.1.1/24 dev vxlan1 + # ip -n a link set vxlan1 up + # ip -n a route add 1.1.1.0/24 encap ip id 1 \ + vxlan_opts 1110 dst 10.1.0.2 dev vxlan1 + # ip -n a route show + # ip netns exec a ping 1.1.1.1 -c 1 + + 1.1.1.0/24 encap ip id 1 src 0.0.0.0 dst 10.1.0.2 ttl 0 tos 0 + vxlan_opts 1110 dev vxlan1 scope link + + PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. + 64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=0.111 ms + + v1->v2: + - improve the changelog. + - get_u32 with base = 0 for gbp. + - use PRINT_ANY to support dumping with json format. + v2->v3: + - implement proper JSON array for opts. + v3->v4: + - keep the same format between input and output, json and non json. + - print gbp as uint. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + ip/iproute_lwtunnel.c | 68 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 68 insertions(+) + +diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c +index 76d906c47c44f..17514dcad9219 100644 +--- a/ip/iproute_lwtunnel.c ++++ b/ip/iproute_lwtunnel.c +@@ -330,6 +330,26 @@ static void lwtunnel_print_geneve_opts(struct rtattr *attr) + close_json_array(PRINT_JSON, name); + } + ++static void lwtunnel_print_vxlan_opts(struct rtattr *attr) ++{ ++ struct rtattr *tb[LWTUNNEL_IP_OPT_VXLAN_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ int rem = RTA_PAYLOAD(attr); ++ char *name = "vxlan_opts"; ++ __u32 gbp; ++ ++ parse_rtattr(tb, LWTUNNEL_IP_OPT_VXLAN_MAX, i, rem); ++ gbp = rta_getattr_u32(tb[LWTUNNEL_IP_OPT_VXLAN_GBP]); ++ ++ print_nl(); ++ print_string(PRINT_FP, name, "\t%s ", name); ++ open_json_array(PRINT_JSON, name); ++ open_json_object(NULL); ++ print_uint(PRINT_ANY, "gbp", "%u ", gbp); ++ close_json_object(); ++ close_json_array(PRINT_JSON, name); ++} ++ + static void lwtunnel_print_opts(struct rtattr *attr) + { + struct rtattr *tb_opt[LWTUNNEL_IP_OPTS_MAX + 1]; +@@ -337,6 +357,8 @@ static void lwtunnel_print_opts(struct rtattr *attr) + parse_rtattr_nested(tb_opt, LWTUNNEL_IP_OPTS_MAX, attr); + if (tb_opt[LWTUNNEL_IP_OPTS_GENEVE]) + lwtunnel_print_geneve_opts(tb_opt[LWTUNNEL_IP_OPTS_GENEVE]); ++ else if (tb_opt[LWTUNNEL_IP_OPTS_VXLAN]) ++ lwtunnel_print_vxlan_opts(tb_opt[LWTUNNEL_IP_OPTS_VXLAN]); + } + + static void print_encap_ip(FILE *fp, struct rtattr *encap) +@@ -935,6 +957,22 @@ static int lwtunnel_parse_geneve_opts(char *str, size_t len, struct rtattr *rta) + return 0; + } + ++static int lwtunnel_parse_vxlan_opts(char *str, size_t len, struct rtattr *rta) ++{ ++ struct rtattr *nest; ++ __u32 gbp; ++ int err; ++ ++ nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_VXLAN | NLA_F_NESTED); ++ err = get_u32(&gbp, str, 0); ++ if (err) ++ return err; ++ rta_addattr32(rta, len, LWTUNNEL_IP_OPT_VXLAN_GBP, gbp); ++ ++ rta_nest_end(rta, nest); ++ return 0; ++} ++ + static int parse_encap_ip(struct rtattr *rta, size_t len, + int *argcp, char ***argvp) + { +@@ -1006,6 +1044,21 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, + invarg("\"geneve_opts\" value is invalid\n", + *argv); + rta_nest_end(rta, nest); ++ } else if (strcmp(*argv, "vxlan_opts") == 0) { ++ struct rtattr *nest; ++ ++ if (opts_ok++) ++ duparg2("opts", *argv); ++ ++ NEXT_ARG(); ++ ++ nest = rta_nest(rta, len, ++ LWTUNNEL_IP_OPTS | NLA_F_NESTED); ++ ret = lwtunnel_parse_vxlan_opts(*argv, len, rta); ++ if (ret) ++ invarg("\"vxlan_opts\" value is invalid\n", ++ *argv); ++ rta_nest_end(rta, nest); + } else if (strcmp(*argv, "key") == 0) { + if (key_ok++) + duparg2("key", *argv); +@@ -1190,6 +1243,21 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + invarg("\"geneve_opts\" value is invalid\n", + *argv); + rta_nest_end(rta, nest); ++ } else if (strcmp(*argv, "vxlan_opts") == 0) { ++ struct rtattr *nest; ++ ++ if (opts_ok++) ++ duparg2("opts", *argv); ++ ++ NEXT_ARG(); ++ ++ nest = rta_nest(rta, len, ++ LWTUNNEL_IP_OPTS | NLA_F_NESTED); ++ ret = lwtunnel_parse_vxlan_opts(*argv, len, rta); ++ if (ret) ++ invarg("\"vxlan_opts\" value is invalid\n", ++ *argv); ++ rta_nest_end(rta, nest); + } else if (strcmp(*argv, "key") == 0) { + if (key_ok++) + duparg2("key", *argv); +-- +2.26.2 + diff --git a/SOURCES/0026-iproute_lwtunnel-add-options-support-for-erspan-meta.patch b/SOURCES/0026-iproute_lwtunnel-add-options-support-for-erspan-meta.patch new file mode 100644 index 0000000..d9f0bb6 --- /dev/null +++ b/SOURCES/0026-iproute_lwtunnel-add-options-support-for-erspan-meta.patch @@ -0,0 +1,246 @@ +From 3628115b53f7b693f623638fb5ec71bc292a3a00 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:43:01 +0200 +Subject: [PATCH] iproute_lwtunnel: add options support for erspan metadata + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit 39fa047938fbe + +commit 39fa047938fbef6cd08687b0daa4d86afbfdc61c +Author: Xin Long +Date: Mon Apr 27 18:27:47 2020 +0800 + + iproute_lwtunnel: add options support for erspan metadata + + This patch is to add LWTUNNEL_IP_OPTS_ERSPAN's parse and print to implement + erspan options support in iproute_lwtunnel. + + Option is expressed as version:index:dir:hwid, dir and hwid will be parsed + when version is 2, while index will be parsed when version is 1. All of + these are numbers. erspan doesn't support multiple options. + + With this patch, users can add and dump erspan options like: + + # ip netns add a + # ip netns add b + # ip -n a link add eth0 type veth peer name eth0 netns b + # ip -n a link set eth0 up + # ip -n b link set eth0 up + # ip -n a addr add 10.1.0.1/24 dev eth0 + # ip -n b addr add 10.1.0.2/24 dev eth0 + # ip -n b link add erspan1 type erspan key 1 seq erspan 123 \ + local 10.1.0.2 remote 10.1.0.1 + # ip -n b addr add 1.1.1.1/24 dev erspan1 + # ip -n b link set erspan1 up + # ip -n b route add 2.1.1.0/24 dev erspan1 + # ip -n a link add erspan1 type erspan key 1 seq local 10.1.0.1 external + # ip -n a addr add 2.1.1.1/24 dev erspan1 + # ip -n a link set erspan1 up + # ip -n a route add 1.1.1.0/24 encap ip id 1 \ + erspan_opts 2:123:1:2 dst 10.1.0.2 dev erspan1 + # ip -n a route show + # ip netns exec a ping 1.1.1.1 -c 1 + + 1.1.1.0/24 encap ip id 1 src 0.0.0.0 dst 10.1.0.2 ttl 0 tos 0 + erspan_opts 2:0:1:2 dev erspan1 scope link + + PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. + 64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=0.124 ms + + v1->v2: + - improve the changelog. + - use PRINT_ANY to support dumping with json format. + v2->v3: + - implement proper JSON object for opts instead of just bunch of strings. + v3->v4: + - keep the same format between input and output, json and non json. + - print version, index, dir and hwid as uint. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + ip/iproute_lwtunnel.c | 140 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 140 insertions(+) + +diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c +index 17514dcad9219..7e145768c111f 100644 +--- a/ip/iproute_lwtunnel.c ++++ b/ip/iproute_lwtunnel.c +@@ -350,6 +350,38 @@ static void lwtunnel_print_vxlan_opts(struct rtattr *attr) + close_json_array(PRINT_JSON, name); + } + ++static void lwtunnel_print_erspan_opts(struct rtattr *attr) ++{ ++ struct rtattr *tb[LWTUNNEL_IP_OPT_ERSPAN_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ char *name = "erspan_opts"; ++ __u8 ver, hwid, dir; ++ __u32 idx; ++ ++ parse_rtattr(tb, LWTUNNEL_IP_OPT_ERSPAN_MAX, i, RTA_PAYLOAD(attr)); ++ ver = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_ERSPAN_VER]); ++ if (ver == 1) { ++ idx = rta_getattr_be32(tb[LWTUNNEL_IP_OPT_ERSPAN_INDEX]); ++ dir = 0; ++ hwid = 0; ++ } else { ++ idx = 0; ++ dir = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_ERSPAN_DIR]); ++ hwid = rta_getattr_u8(tb[LWTUNNEL_IP_OPT_ERSPAN_HWID]); ++ } ++ ++ print_nl(); ++ print_string(PRINT_FP, name, "\t%s ", name); ++ open_json_array(PRINT_JSON, name); ++ open_json_object(NULL); ++ print_uint(PRINT_ANY, "ver", "%u", ver); ++ print_uint(PRINT_ANY, "index", ":%u", idx); ++ print_uint(PRINT_ANY, "dir", ":%u", dir); ++ print_uint(PRINT_ANY, "hwid", ":%u ", hwid); ++ close_json_object(); ++ close_json_array(PRINT_JSON, name); ++} ++ + static void lwtunnel_print_opts(struct rtattr *attr) + { + struct rtattr *tb_opt[LWTUNNEL_IP_OPTS_MAX + 1]; +@@ -359,6 +391,8 @@ static void lwtunnel_print_opts(struct rtattr *attr) + lwtunnel_print_geneve_opts(tb_opt[LWTUNNEL_IP_OPTS_GENEVE]); + else if (tb_opt[LWTUNNEL_IP_OPTS_VXLAN]) + lwtunnel_print_vxlan_opts(tb_opt[LWTUNNEL_IP_OPTS_VXLAN]); ++ else if (tb_opt[LWTUNNEL_IP_OPTS_ERSPAN]) ++ lwtunnel_print_erspan_opts(tb_opt[LWTUNNEL_IP_OPTS_ERSPAN]); + } + + static void print_encap_ip(FILE *fp, struct rtattr *encap) +@@ -973,6 +1007,82 @@ static int lwtunnel_parse_vxlan_opts(char *str, size_t len, struct rtattr *rta) + return 0; + } + ++static int lwtunnel_parse_erspan_opts(char *str, size_t len, struct rtattr *rta) ++{ ++ struct rtattr *nest; ++ char *token; ++ int i, err; ++ ++ nest = rta_nest(rta, len, LWTUNNEL_IP_OPTS_ERSPAN | NLA_F_NESTED); ++ i = 1; ++ token = strsep(&str, ":"); ++ while (token) { ++ switch (i) { ++ case LWTUNNEL_IP_OPT_ERSPAN_VER: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ rta_addattr8(rta, len, i, opt_type); ++ break; ++ } ++ case LWTUNNEL_IP_OPT_ERSPAN_INDEX: ++ { ++ __be32 opt_class; ++ ++ if (!strlen(token)) ++ break; ++ err = get_be32(&opt_class, token, 0); ++ if (err) ++ return err; ++ ++ rta_addattr32(rta, len, i, opt_class); ++ break; ++ } ++ case LWTUNNEL_IP_OPT_ERSPAN_DIR: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ rta_addattr8(rta, len, i, opt_type); ++ break; ++ } ++ case LWTUNNEL_IP_OPT_ERSPAN_HWID: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ rta_addattr8(rta, len, i, opt_type); ++ break; ++ } ++ default: ++ fprintf(stderr, "Unknown \"geneve_opts\" type\n"); ++ return -1; ++ } ++ ++ token = strsep(&str, ":"); ++ i++; ++ } ++ ++ rta_nest_end(rta, nest); ++ return 0; ++} ++ + static int parse_encap_ip(struct rtattr *rta, size_t len, + int *argcp, char ***argvp) + { +@@ -1059,6 +1169,21 @@ static int parse_encap_ip(struct rtattr *rta, size_t len, + invarg("\"vxlan_opts\" value is invalid\n", + *argv); + rta_nest_end(rta, nest); ++ } else if (strcmp(*argv, "erspan_opts") == 0) { ++ struct rtattr *nest; ++ ++ if (opts_ok++) ++ duparg2("opts", *argv); ++ ++ NEXT_ARG(); ++ ++ nest = rta_nest(rta, len, ++ LWTUNNEL_IP_OPTS | NLA_F_NESTED); ++ ret = lwtunnel_parse_erspan_opts(*argv, len, rta); ++ if (ret) ++ invarg("\"erspan_opts\" value is invalid\n", ++ *argv); ++ rta_nest_end(rta, nest); + } else if (strcmp(*argv, "key") == 0) { + if (key_ok++) + duparg2("key", *argv); +@@ -1258,6 +1383,21 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len, + invarg("\"vxlan_opts\" value is invalid\n", + *argv); + rta_nest_end(rta, nest); ++ } else if (strcmp(*argv, "erspan_opts") == 0) { ++ struct rtattr *nest; ++ ++ if (opts_ok++) ++ duparg2("opts", *argv); ++ ++ NEXT_ARG(); ++ ++ nest = rta_nest(rta, len, ++ LWTUNNEL_IP_OPTS | NLA_F_NESTED); ++ ret = lwtunnel_parse_erspan_opts(*argv, len, rta); ++ if (ret) ++ invarg("\"erspan_opts\" value is invalid\n", ++ *argv); ++ rta_nest_end(rta, nest); + } else if (strcmp(*argv, "key") == 0) { + if (key_ok++) + duparg2("key", *argv); +-- +2.26.2 + diff --git a/SOURCES/0027-tc-m_tunnel_key-add-options-support-for-vxlan.patch b/SOURCES/0027-tc-m_tunnel_key-add-options-support-for-vxlan.patch new file mode 100644 index 0000000..b86d0b3 --- /dev/null +++ b/SOURCES/0027-tc-m_tunnel_key-add-options-support-for-vxlan.patch @@ -0,0 +1,258 @@ +From f970b592af7421ce932a788a6a14161c351d75e0 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:43:01 +0200 +Subject: [PATCH] tc: m_tunnel_key: add options support for vxlan + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit f72c3ad00f3b7 +Conflicts: context change due to missing commit 7b0d424abef16 + ("tc: do not output newline in oneline mode") + +commit f72c3ad00f3b7869e90840d0098a83cb88224892 +Author: Xin Long +Date: Mon Apr 27 18:27:48 2020 +0800 + + tc: m_tunnel_key: add options support for vxlan + + This patch is to add TCA_TUNNEL_KEY_ENC_OPTS_VXLAN's parse and + print to implement vxlan options support in m_tunnel_key, like + Commit 6217917a3826 ("tc: m_tunnel_key: Add tunnel option support + to act_tunnel_key") for geneve options support. + + Option is expressed a 32bit number for gbp only, and vxlan + doesn't support multiple options. + + With this patch, users can add and dump vxlan options like: + + # ip link add name vxlan1 type vxlan dstport 0 external + # tc qdisc add dev eth0 ingress + # tc filter add dev eth0 protocol ip parent ffff: \ + flower indev eth0 \ + ip_proto udp \ + action tunnel_key \ + set src_ip 10.0.99.192 \ + dst_ip 10.0.99.193 \ + dst_port 6081 \ + id 11 \ + vxlan_opts 65793 \ + action mirred egress redirect dev vxlan1 + # tc -s filter show dev eth0 parent ffff: + + filter protocol ip pref 49152 flower chain 0 handle 0x1 + indev eth0 + eth_type ipv4 + ip_proto udp + not_in_hw + action order 1: tunnel_key set + src_ip 10.0.99.192 + dst_ip 10.0.99.193 + key_id 11 + dst_port 6081 + vxlan_opts 65793 + ... + + v1->v2: + - get_u32 with base = 0 for gbp. + - use to print_unint("0x%x") to print gbp. + v2->v3: + - implement proper JSON array for opts. + v3->v4: + - keep the same format between input and output, json and non json. + - print gbp as uint. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + man/man8/tc-tunnel_key.8 | 10 ++++- + tc/m_tunnel_key.c | 85 +++++++++++++++++++++++++++++++++++----- + 2 files changed, 85 insertions(+), 10 deletions(-) + +diff --git a/man/man8/tc-tunnel_key.8 b/man/man8/tc-tunnel_key.8 +index 2145eb62e70e2..c208e2c82a181 100644 +--- a/man/man8/tc-tunnel_key.8 ++++ b/man/man8/tc-tunnel_key.8 +@@ -66,8 +66,10 @@ options. + .B id + , + .B dst_port +-and ++, + .B geneve_opts ++and ++.B vxlan_opts + are optional. + .RS + .TP +@@ -91,6 +93,12 @@ is specified in the form CLASS:TYPE:DATA, where CLASS is represented as a + variable length hexadecimal value. Additionally multiple options may be + listed using a comma delimiter. + .TP ++.B vxlan_opts ++Vxlan metatdata options. ++.B vxlan_opts ++is specified in the form GBP, as a 32bit number. Multiple options is not ++supported. ++.TP + .B tos + Outer header TOS + .TP +diff --git a/tc/m_tunnel_key.c b/tc/m_tunnel_key.c +index 4e65e444776a2..76391d6c85fb2 100644 +--- a/tc/m_tunnel_key.c ++++ b/tc/m_tunnel_key.c +@@ -29,7 +29,7 @@ static void explain(void) + "src_ip (mandatory)\n" + "dst_ip (mandatory)\n" + "dst_port \n" +- "geneve_opts \n" ++ "geneve_opts | vxlan_opts \n" + "csum | nocsum (default is \"csum\")\n"); + } + +@@ -112,6 +112,21 @@ static int tunnel_key_parse_u8(char *str, int base, int type, + return 0; + } + ++static int tunnel_key_parse_u32(char *str, int base, int type, ++ struct nlmsghdr *n) ++{ ++ __u32 value; ++ int ret; ++ ++ ret = get_u32(&value, str, base); ++ if (ret) ++ return ret; ++ ++ addattr32(n, MAX_MSG, type, value); ++ ++ return 0; ++} ++ + static int tunnel_key_parse_geneve_opt(char *str, struct nlmsghdr *n) + { + char *token, *saveptr = NULL; +@@ -190,6 +205,27 @@ static int tunnel_key_parse_geneve_opts(char *str, struct nlmsghdr *n) + return 0; + } + ++static int tunnel_key_parse_vxlan_opt(char *str, struct nlmsghdr *n) ++{ ++ struct rtattr *encap, *nest; ++ int ret; ++ ++ encap = addattr_nest(n, MAX_MSG, ++ TCA_TUNNEL_KEY_ENC_OPTS | NLA_F_NESTED); ++ nest = addattr_nest(n, MAX_MSG, ++ TCA_TUNNEL_KEY_ENC_OPTS_VXLAN | NLA_F_NESTED); ++ ++ ret = tunnel_key_parse_u32(str, 0, ++ TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP, n); ++ if (ret) ++ return ret; ++ ++ addattr_nest_end(n, nest); ++ addattr_nest_end(n, encap); ++ ++ return 0; ++} ++ + static int tunnel_key_parse_tos_ttl(char *str, int type, struct nlmsghdr *n) + { + int ret; +@@ -287,6 +323,13 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p, + fprintf(stderr, "Illegal \"geneve_opts\"\n"); + return -1; + } ++ } else if (matches(*argv, "vxlan_opts") == 0) { ++ NEXT_ARG(); ++ ++ if (tunnel_key_parse_vxlan_opt(*argv, n)) { ++ fprintf(stderr, "Illegal \"vxlan_opts\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "tos") == 0) { + NEXT_ARG(); + ret = tunnel_key_parse_tos_ttl(*argv, +@@ -406,13 +449,13 @@ static void tunnel_key_print_flag(FILE *f, const char *name_on, + rta_getattr_u8(attr) ? name_on : name_off); + } + +-static void tunnel_key_print_geneve_options(const char *name, +- struct rtattr *attr) ++static void tunnel_key_print_geneve_options(struct rtattr *attr) + { + struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1]; + struct rtattr *i = RTA_DATA(attr); + int ii, data_len = 0, offset = 0; + int rem = RTA_PAYLOAD(attr); ++ char *name = "geneve_opts"; + char strbuf[rem * 2 + 1]; + char data[rem * 2 + 1]; + uint8_t data_r[rem]; +@@ -420,7 +463,8 @@ static void tunnel_key_print_geneve_options(const char *name, + uint8_t type; + + open_json_array(PRINT_JSON, name); +- print_string(PRINT_FP, name, "\n\t%s ", "geneve_opt"); ++ print_nl(); ++ print_string(PRINT_FP, name, "\t%s ", name); + + while (rem) { + parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX, i, rem); +@@ -453,7 +497,27 @@ static void tunnel_key_print_geneve_options(const char *name, + close_json_array(PRINT_JSON, name); + } + +-static void tunnel_key_print_key_opt(const char *name, struct rtattr *attr) ++static void tunnel_key_print_vxlan_options(struct rtattr *attr) ++{ ++ struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ int rem = RTA_PAYLOAD(attr); ++ char *name = "vxlan_opts"; ++ __u32 gbp; ++ ++ parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX, i, rem); ++ gbp = rta_getattr_u32(tb[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP]); ++ ++ print_nl(); ++ print_string(PRINT_FP, name, "\t%s ", name); ++ open_json_array(PRINT_JSON, name); ++ open_json_object(NULL); ++ print_uint(PRINT_ANY, "gbp", "%u", gbp); ++ close_json_object(); ++ close_json_array(PRINT_JSON, name); ++} ++ ++static void tunnel_key_print_key_opt(struct rtattr *attr) + { + struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1]; + +@@ -461,8 +525,12 @@ static void tunnel_key_print_key_opt(const char *name, struct rtattr *attr) + return; + + parse_rtattr_nested(tb, TCA_TUNNEL_KEY_ENC_OPTS_MAX, attr); +- tunnel_key_print_geneve_options(name, +- tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE]); ++ if (tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE]) ++ tunnel_key_print_geneve_options( ++ tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE]); ++ else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]) ++ tunnel_key_print_vxlan_options( ++ tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]); + } + + static void tunnel_key_print_tos_ttl(FILE *f, char *name, +@@ -518,8 +586,7 @@ static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg) + tb[TCA_TUNNEL_KEY_ENC_KEY_ID]); + tunnel_key_print_dst_port(f, "dst_port", + tb[TCA_TUNNEL_KEY_ENC_DST_PORT]); +- tunnel_key_print_key_opt("geneve_opts", +- tb[TCA_TUNNEL_KEY_ENC_OPTS]); ++ tunnel_key_print_key_opt(tb[TCA_TUNNEL_KEY_ENC_OPTS]); + tunnel_key_print_flag(f, "nocsum", "csum", + tb[TCA_TUNNEL_KEY_NO_CSUM]); + tunnel_key_print_tos_ttl(f, "tos", +-- +2.26.2 + diff --git a/SOURCES/0028-tc-m_tunnel_key-add-options-support-for-erpsan.patch b/SOURCES/0028-tc-m_tunnel_key-add-options-support-for-erpsan.patch new file mode 100644 index 0000000..5dfebf0 --- /dev/null +++ b/SOURCES/0028-tc-m_tunnel_key-add-options-support-for-erpsan.patch @@ -0,0 +1,265 @@ +From 2fb8c115a8031d893fff588181cc42764391e4d5 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:43:50 +0200 +Subject: [PATCH] tc: m_tunnel_key: add options support for erpsan + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit 668fd9b25d9ec + +commit 668fd9b25d9eca3067040273239f7825db95442b +Author: Xin Long +Date: Mon Apr 27 18:27:49 2020 +0800 + + tc: m_tunnel_key: add options support for erpsan + + This patch is to add TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN's parse and + print to implement erspan options support in m_tunnel_key, like + Commit 6217917a3826 ("tc: m_tunnel_key: Add tunnel option support + to act_tunnel_key") for geneve options support. + + Option is expressed as version:index:dir:hwid, dir and hwid will + be parsed when version is 2, while index will be parsed when + version is 1. erspan doesn't support multiple options. + + With this patch, users can add and dump erspan options like: + + # ip link add name erspan1 type erspan external + # tc qdisc add dev eth0 ingress + # tc filter add dev eth0 protocol ip parent ffff: \ + flower indev eth0 \ + ip_proto udp \ + action tunnel_key \ + set src_ip 10.0.99.192 \ + dst_ip 10.0.99.193 \ + dst_port 6081 \ + id 11 \ + erspan_opts 1:2:0:0 \ + action mirred egress redirect dev erspan1 + # tc -s filter show dev eth0 parent ffff: + + filter protocol ip pref 49151 flower chain 0 handle 0x1 + indev eth0 + eth_type ipv4 + ip_proto udp + not_in_hw + action order 1: tunnel_key set + src_ip 10.0.99.192 + dst_ip 10.0.99.193 + key_id 11 + dst_port 6081 + erspan_opts 1:2:0:0 + csum pipe + index 2 ref 1 bind 1 + ... + v1->v2: + - no change. + v2->v3: + - no change. + v3->v4: + - keep the same format between input and output, json and non json. + - print version, index, dir and hwid as uint. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + man/man8/tc-tunnel_key.8 | 12 +++- + tc/m_tunnel_key.c | 117 ++++++++++++++++++++++++++++++++++++++- + 2 files changed, 127 insertions(+), 2 deletions(-) + +diff --git a/man/man8/tc-tunnel_key.8 b/man/man8/tc-tunnel_key.8 +index c208e2c82a181..ad9972402c0e5 100644 +--- a/man/man8/tc-tunnel_key.8 ++++ b/man/man8/tc-tunnel_key.8 +@@ -68,8 +68,10 @@ options. + .B dst_port + , + .B geneve_opts +-and ++, + .B vxlan_opts ++and ++.B erspan_opts + are optional. + .RS + .TP +@@ -99,6 +101,14 @@ Vxlan metatdata options. + is specified in the form GBP, as a 32bit number. Multiple options is not + supported. + .TP ++.B erspan_opts ++Erspan metatdata options. ++.B erspan_opts ++is specified in the form VERSION:INDEX:DIR:HWID, where VERSION is represented ++as a 8bit number, INDEX as an 32bit number, DIR and HWID as a 8bit number. ++Multiple options is not supported. Note INDEX is used when VERSION is 1, ++and DIR and HWID are used when VERSION is 2. ++.TP + .B tos + Outer header TOS + .TP +diff --git a/tc/m_tunnel_key.c b/tc/m_tunnel_key.c +index 76391d6c85fb2..a56fe24413fa0 100644 +--- a/tc/m_tunnel_key.c ++++ b/tc/m_tunnel_key.c +@@ -29,7 +29,7 @@ static void explain(void) + "src_ip (mandatory)\n" + "dst_ip (mandatory)\n" + "dst_port \n" +- "geneve_opts | vxlan_opts \n" ++ "geneve_opts | vxlan_opts | erspan_opts \n" + "csum | nocsum (default is \"csum\")\n"); + } + +@@ -97,6 +97,21 @@ static int tunnel_key_parse_be16(char *str, int base, int type, + return 0; + } + ++static int tunnel_key_parse_be32(char *str, int base, int type, ++ struct nlmsghdr *n) ++{ ++ __be32 value; ++ int ret; ++ ++ ret = get_be32(&value, str, base); ++ if (ret) ++ return ret; ++ ++ addattr32(n, MAX_MSG, type, value); ++ ++ return 0; ++} ++ + static int tunnel_key_parse_u8(char *str, int base, int type, + struct nlmsghdr *n) + { +@@ -226,6 +241,63 @@ static int tunnel_key_parse_vxlan_opt(char *str, struct nlmsghdr *n) + return 0; + } + ++static int tunnel_key_parse_erspan_opt(char *str, struct nlmsghdr *n) ++{ ++ char *token, *saveptr = NULL; ++ struct rtattr *encap, *nest; ++ int i, ret; ++ ++ encap = addattr_nest(n, MAX_MSG, ++ TCA_TUNNEL_KEY_ENC_OPTS | NLA_F_NESTED); ++ nest = addattr_nest(n, MAX_MSG, ++ TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN | NLA_F_NESTED); ++ ++ token = strtok_r(str, ":", &saveptr); ++ i = 1; ++ while (token) { ++ switch (i) { ++ case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER: ++ { ++ ret = tunnel_key_parse_u8(token, 0, i, n); ++ if (ret) ++ return ret; ++ break; ++ } ++ case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX: ++ { ++ ret = tunnel_key_parse_be32(token, 0, i, n); ++ if (ret) ++ return ret; ++ break; ++ } ++ case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR: ++ { ++ ret = tunnel_key_parse_u8(token, 0, i, n); ++ if (ret) ++ return ret; ++ break; ++ } ++ case TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID: ++ { ++ ret = tunnel_key_parse_u8(token, 0, i, n); ++ if (ret) ++ return ret; ++ break; ++ } ++ default: ++ return -1; ++ } ++ ++ token = strtok_r(NULL, ":", &saveptr); ++ i++; ++ } ++ ++ addattr_nest_end(n, nest); ++ addattr_nest_end(n, encap); ++ ++ return 0; ++} ++ + static int tunnel_key_parse_tos_ttl(char *str, int type, struct nlmsghdr *n) + { + int ret; +@@ -330,6 +402,13 @@ static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p, + fprintf(stderr, "Illegal \"vxlan_opts\"\n"); + return -1; + } ++ } else if (matches(*argv, "erspan_opts") == 0) { ++ NEXT_ARG(); ++ ++ if (tunnel_key_parse_erspan_opt(*argv, n)) { ++ fprintf(stderr, "Illegal \"erspan_opts\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "tos") == 0) { + NEXT_ARG(); + ret = tunnel_key_parse_tos_ttl(*argv, +@@ -517,6 +596,39 @@ static void tunnel_key_print_vxlan_options(struct rtattr *attr) + close_json_array(PRINT_JSON, name); + } + ++static void tunnel_key_print_erspan_options(struct rtattr *attr) ++{ ++ struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ int rem = RTA_PAYLOAD(attr); ++ char *name = "erspan_opts"; ++ __u8 ver, hwid, dir; ++ __u32 idx; ++ ++ parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX, i, rem); ++ ver = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER]); ++ if (ver == 1) { ++ idx = rta_getattr_be32(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX]); ++ dir = 0; ++ hwid = 0; ++ } else { ++ idx = 0; ++ dir = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR]); ++ hwid = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID]); ++ } ++ ++ print_nl(); ++ print_string(PRINT_FP, name, "\t%s ", name); ++ open_json_array(PRINT_JSON, name); ++ open_json_object(NULL); ++ print_uint(PRINT_ANY, "ver", "%u", ver); ++ print_uint(PRINT_ANY, "index", ":%u", idx); ++ print_uint(PRINT_ANY, "dir", ":%u", dir); ++ print_uint(PRINT_ANY, "hwid", ":%u", hwid); ++ close_json_object(); ++ close_json_array(PRINT_JSON, name); ++} ++ + static void tunnel_key_print_key_opt(struct rtattr *attr) + { + struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1]; +@@ -531,6 +643,9 @@ static void tunnel_key_print_key_opt(struct rtattr *attr) + else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]) + tunnel_key_print_vxlan_options( + tb[TCA_TUNNEL_KEY_ENC_OPTS_VXLAN]); ++ else if (tb[TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN]) ++ tunnel_key_print_erspan_options( ++ tb[TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN]); + } + + static void tunnel_key_print_tos_ttl(FILE *f, char *name, +-- +2.26.2 + diff --git a/SOURCES/0029-tc-f_flower-add-options-support-for-vxlan.patch b/SOURCES/0029-tc-f_flower-add-options-support-for-vxlan.patch new file mode 100644 index 0000000..0de0f70 --- /dev/null +++ b/SOURCES/0029-tc-f_flower-add-options-support-for-vxlan.patch @@ -0,0 +1,316 @@ +From 4bd1eb80a195ce1a64e33f5fc9d5c58bf9f30c8d Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:43:50 +0200 +Subject: [PATCH] tc: f_flower: add options support for vxlan + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit 93c8d5f72f8ce +Conflicts: on a removed line due to missing commit 93c8d5f72f8ce + ("tc: f_flower: add options support for vxlan") + +commit 93c8d5f72f8ce4b98c68508e85457f83933302c0 +Author: Xin Long +Date: Mon Apr 27 18:27:50 2020 +0800 + + tc: f_flower: add options support for vxlan + + This patch is to add TCA_FLOWER_KEY_ENC_OPTS_VXLAN's parse and + print to implement vxlan options support in m_tunnel_key, like + Commit 56155d4df86d ("tc: f_flower: add geneve option match + support to flower") for geneve options support. + + Option is expressed a 32bit number for gbp only, and vxlan + doesn't support multiple options. + + With this patch, users can add and dump vxlan options like: + + # ip link add name vxlan1 type vxlan dstport 0 external + # tc qdisc add dev vxlan1 ingress + # tc filter add dev vxlan1 protocol ip parent ffff: \ + flower \ + enc_src_ip 10.0.99.192 \ + enc_dst_ip 10.0.99.193 \ + enc_key_id 11 \ + vxlan_opts 65793/4008635966 \ + ip_proto udp \ + action mirred egress redirect dev eth1 + # tc -s filter show dev vxlan1 parent ffff: + + filter protocol ip pref 49152 flower chain 0 handle 0x1 + eth_type ipv4 + ip_proto udp + enc_dst_ip 10.0.99.193 + enc_src_ip 10.0.99.192 + enc_key_id 11 + vxlan_opts 65793/4008635966 + not_in_hw + action order 1: mirred (Egress Redirect to device eth1) stolen + index 3 ref 1 bind 1 + Action statistics: + Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) + backlog 0b 0p requeues 0 + + v1->v2: + - get_u32 with base = 0 for gbp. + v2->v3: + - implement proper JSON array for opts. + v3->v4: + - keep the same format between input and output, json and non json. + - print gbp as uint. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + man/man8/tc-flower.8 | 12 ++++ + tc/f_flower.c | 130 +++++++++++++++++++++++++++++++++++++------ + 2 files changed, 126 insertions(+), 16 deletions(-) + +diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8 +index adff41e39b006..0efacbfdf9a95 100644 +--- a/man/man8/tc-flower.8 ++++ b/man/man8/tc-flower.8 +@@ -81,7 +81,11 @@ flower \- flow based traffic control filter + .IR TOS " | " + .B enc_ttl + .IR TTL " | " ++{ + .B geneve_opts ++| ++.B vxlan_opts ++} + .IR OPTIONS " | " + .BR ip_flags + .IR IP_FLAGS +@@ -290,6 +294,8 @@ bits is assumed. + .BI enc_ttl " NUMBER" + .TQ + .BI geneve_opts " OPTIONS" ++.TQ ++.BI vxlan_opts " OPTIONS" + Match on IP tunnel metadata. Key id + .I NUMBER + is a 32 bit tunnel key id (e.g. VNI for VXLAN tunnel). +@@ -310,6 +316,12 @@ the masks is missing, \fBtc\fR assumes a full-length match. The options can + be described in the form CLASS:TYPE:DATA/CLASS_MASK:TYPE_MASK:DATA_MASK, + where CLASS is represented as a 16bit hexadecimal value, TYPE as an 8bit + hexadecimal value and DATA as a variable length hexadecimal value. ++vxlan_opts ++.I OPTIONS ++doesn't support multiple options, and it consists of a key followed by a slash ++and corresponding mask. If the mask is missing, \fBtc\fR assumes a full-length ++match. The option can be described in the form GBP/GBP_MASK, where GBP is ++represented as a 32bit number. + .TP + .BI ip_flags " IP_FLAGS" + .I IP_FLAGS +diff --git a/tc/f_flower.c b/tc/f_flower.c +index 70d40d3b2f2bf..09079cd2c2280 100644 +--- a/tc/f_flower.c ++++ b/tc/f_flower.c +@@ -81,6 +81,7 @@ static void explain(void) + " enc_tos MASKED-IP_TOS |\n" + " enc_ttl MASKED-IP_TTL |\n" + " geneve_opts MASKED-OPTIONS |\n" ++ " vxlan_opts MASKED-OPTIONS |\n" + " ip_flags IP-FLAGS | \n" + " enc_dst_port [ port_number ] }\n" + " FILTERID := X:Y:Z\n" +@@ -648,7 +649,7 @@ static int flower_parse_enc_port(char *str, int type, struct nlmsghdr *n) + return 0; + } + +-static int flower_parse_geneve_opts(char *str, struct nlmsghdr *n) ++static int flower_parse_geneve_opt(char *str, struct nlmsghdr *n) + { + struct rtattr *nest; + char *token; +@@ -718,14 +719,33 @@ static int flower_parse_geneve_opts(char *str, struct nlmsghdr *n) + return 0; + } + +-static int flower_parse_enc_opt_part(char *str, struct nlmsghdr *n) ++static int flower_parse_vxlan_opt(char *str, struct nlmsghdr *n) ++{ ++ struct rtattr *nest; ++ __u32 gbp; ++ int err; ++ ++ nest = addattr_nest(n, MAX_MSG, ++ TCA_FLOWER_KEY_ENC_OPTS_VXLAN | NLA_F_NESTED); ++ ++ err = get_u32(&gbp, str, 0); ++ if (err) ++ return err; ++ addattr32(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP, gbp); ++ ++ addattr_nest_end(n, nest); ++ ++ return 0; ++} ++ ++static int flower_parse_geneve_opts(char *str, struct nlmsghdr *n) + { + char *token; + int err; + + token = strsep(&str, ","); + while (token) { +- err = flower_parse_geneve_opts(token, n); ++ err = flower_parse_geneve_opt(token, n); + if (err) + return err; + +@@ -755,7 +775,7 @@ static int flower_check_enc_opt_key(char *key) + return 0; + } + +-static int flower_parse_enc_opts(char *str, struct nlmsghdr *n) ++static int flower_parse_enc_opts_geneve(char *str, struct nlmsghdr *n) + { + char key[XATTR_SIZE_MAX], mask[XATTR_SIZE_MAX]; + int data_len, key_len, mask_len, err; +@@ -807,13 +827,50 @@ static int flower_parse_enc_opts(char *str, struct nlmsghdr *n) + mask[mask_len - 1] = '\0'; + + nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS); +- err = flower_parse_enc_opt_part(key, n); ++ err = flower_parse_geneve_opts(key, n); + if (err) + return err; + addattr_nest_end(n, nest); + + nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS_MASK); +- err = flower_parse_enc_opt_part(mask, n); ++ err = flower_parse_geneve_opts(mask, n); ++ if (err) ++ return err; ++ addattr_nest_end(n, nest); ++ ++ return 0; ++} ++ ++static int flower_parse_enc_opts_vxlan(char *str, struct nlmsghdr *n) ++{ ++ char key[XATTR_SIZE_MAX], mask[XATTR_SIZE_MAX]; ++ struct rtattr *nest; ++ char *slash; ++ int err; ++ ++ slash = strchr(str, '/'); ++ if (slash) { ++ *slash++ = '\0'; ++ if (strlen(slash) > XATTR_SIZE_MAX) ++ return -1; ++ strcpy(mask, slash); ++ } else { ++ strcpy(mask, "0xffffffff"); ++ } ++ ++ if (strlen(str) > XATTR_SIZE_MAX) ++ return -1; ++ strcpy(key, str); ++ ++ nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS | NLA_F_NESTED); ++ err = flower_parse_vxlan_opt(str, n); ++ if (err) ++ return err; ++ addattr_nest_end(n, nest); ++ ++ nest = addattr_nest(n, MAX_MSG, ++ TCA_FLOWER_KEY_ENC_OPTS_MASK | NLA_F_NESTED); ++ err = flower_parse_vxlan_opt(mask, n); + if (err) + return err; + addattr_nest_end(n, nest); +@@ -1275,11 +1332,18 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + } + } else if (matches(*argv, "geneve_opts") == 0) { + NEXT_ARG(); +- ret = flower_parse_enc_opts(*argv, n); ++ ret = flower_parse_enc_opts_geneve(*argv, n); + if (ret < 0) { + fprintf(stderr, "Illegal \"geneve_opts\"\n"); + return -1; + } ++ } else if (matches(*argv, "vxlan_opts") == 0) { ++ NEXT_ARG(); ++ ret = flower_parse_enc_opts_vxlan(*argv, n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"vxlan_opts\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "action") == 0) { + NEXT_ARG(); + ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n); +@@ -1643,10 +1707,29 @@ static void flower_print_geneve_opts(const char *name, struct rtattr *attr, + close_json_array(PRINT_JSON, name); + } + +-static void flower_print_geneve_parts(const char *name, struct rtattr *attr, +- char *key, char *mask) ++static void flower_print_vxlan_opts(const char *name, struct rtattr *attr, ++ char *strbuf) ++{ ++ struct rtattr *tb[TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX + 1]; ++ struct rtattr *i = RTA_DATA(attr); ++ int rem = RTA_PAYLOAD(attr); ++ __u32 gbp; ++ ++ parse_rtattr(tb, TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX, i, rem); ++ gbp = rta_getattr_u32(tb[TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP]); ++ ++ open_json_array(PRINT_JSON, name); ++ open_json_object(NULL); ++ print_uint(PRINT_JSON, "gbp", NULL, gbp); ++ close_json_object(); ++ close_json_array(PRINT_JSON, name); ++ ++ sprintf(strbuf, "%u", gbp); ++} ++ ++static void flower_print_enc_parts(const char *name, const char *namefrm, ++ struct rtattr *attr, char *key, char *mask) + { +- char *namefrm = "\n geneve_opt %s"; + char *key_token, *mask_token, *out; + int len; + +@@ -1687,14 +1770,29 @@ static void flower_print_enc_opts(const char *name, struct rtattr *attr, + goto err_key_free; + + parse_rtattr_nested(key_tb, TCA_FLOWER_KEY_ENC_OPTS_MAX, attr); +- flower_print_geneve_opts("geneve_opt_key", +- key_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE], key); +- + parse_rtattr_nested(msk_tb, TCA_FLOWER_KEY_ENC_OPTS_MAX, mask_attr); +- flower_print_geneve_opts("geneve_opt_mask", +- msk_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE], msk); + +- flower_print_geneve_parts(name, attr, key, msk); ++ if (key_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE]) { ++ flower_print_geneve_opts("geneve_opt_key", ++ key_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE], key); ++ ++ if (msk_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE]) ++ flower_print_geneve_opts("geneve_opt_mask", ++ msk_tb[TCA_FLOWER_KEY_ENC_OPTS_GENEVE], msk); ++ ++ flower_print_enc_parts(name, " geneve_opts %s", attr, key, ++ msk); ++ } else if (key_tb[TCA_FLOWER_KEY_ENC_OPTS_VXLAN]) { ++ flower_print_vxlan_opts("vxlan_opt_key", ++ key_tb[TCA_FLOWER_KEY_ENC_OPTS_VXLAN], key); ++ ++ if (msk_tb[TCA_FLOWER_KEY_ENC_OPTS_VXLAN]) ++ flower_print_vxlan_opts("vxlan_opt_mask", ++ msk_tb[TCA_FLOWER_KEY_ENC_OPTS_VXLAN], msk); ++ ++ flower_print_enc_parts(name, " vxlan_opts %s", attr, key, ++ msk); ++ } + + free(msk); + err_key_free: +-- +2.26.2 + diff --git a/SOURCES/0030-tc-f_flower-add-options-support-for-erspan.patch b/SOURCES/0030-tc-f_flower-add-options-support-for-erspan.patch new file mode 100644 index 0000000..6c1469b --- /dev/null +++ b/SOURCES/0030-tc-f_flower-add-options-support-for-erspan.patch @@ -0,0 +1,324 @@ +From 6784a916b142c3bd5cf7c20a30b23e362bd4908a Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Thu, 4 Jun 2020 21:44:22 +0200 +Subject: [PATCH] tc: f_flower: add options support for erspan + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1830485 +Upstream Status: unknown commit 4e578c78fedfe + +commit 4e578c78fedfe6ffa5fa5fde56778b264485829b +Author: Xin Long +Date: Mon Apr 27 18:27:51 2020 +0800 + + tc: f_flower: add options support for erspan + + This patch is to add TCA_FLOWER_KEY_ENC_OPTS_ERSPAN's parse and + print to implement erspan options support in m_tunnel_key, like + Commit 56155d4df86d ("tc: f_flower: add geneve option match + support to flower") for geneve options support. + + Option is expressed as version:index:dir:hwid, dir and hwid will + be parsed when version is 2, while index will be parsed when + version is 1. erspan doesn't support multiple options. + + With this patch, users can add and dump erspan options like: + + # ip link add name erspan1 type erspan external + # tc qdisc add dev erspan1 ingress + # tc filter add dev erspan1 protocol ip parent ffff: \ + flower \ + enc_src_ip 10.0.99.192 \ + enc_dst_ip 10.0.99.193 \ + enc_key_id 11 \ + erspan_opts 1:2:0:0/1:255:0:0 \ + ip_proto udp \ + action mirred egress redirect dev eth1 + # tc -s filter show dev erspan1 parent ffff: + + filter protocol ip pref 49152 flower chain 0 handle 0x1 + eth_type ipv4 + ip_proto udp + enc_dst_ip 10.0.99.193 + enc_src_ip 10.0.99.192 + enc_key_id 11 + erspan_opts 1:2:0:0/1:255:0:0 + not_in_hw + action order 1: mirred (Egress Redirect to device eth1) stolen + index 1 ref 1 bind 1 + Action statistics: + Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) + backlog 0b 0p requeues 0 + + v1->v2: + - no change. + v2->v3: + - no change. + v3->v4: + - keep the same format between input and output, json and non json. + - print version, index, dir and hwid as uint. + + Signed-off-by: Xin Long + Signed-off-by: David Ahern +--- + man/man8/tc-flower.8 | 13 ++++ + tc/f_flower.c | 171 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 184 insertions(+) + +diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8 +index 0efacbfdf9a95..f41b0f7f1ef13 100644 +--- a/man/man8/tc-flower.8 ++++ b/man/man8/tc-flower.8 +@@ -85,6 +85,8 @@ flower \- flow based traffic control filter + .B geneve_opts + | + .B vxlan_opts ++| ++.B erspan_opts + } + .IR OPTIONS " | " + .BR ip_flags +@@ -296,6 +298,8 @@ bits is assumed. + .BI geneve_opts " OPTIONS" + .TQ + .BI vxlan_opts " OPTIONS" ++.TQ ++.BI erspan_opts " OPTIONS" + Match on IP tunnel metadata. Key id + .I NUMBER + is a 32 bit tunnel key id (e.g. VNI for VXLAN tunnel). +@@ -322,6 +326,15 @@ doesn't support multiple options, and it consists of a key followed by a slash + and corresponding mask. If the mask is missing, \fBtc\fR assumes a full-length + match. The option can be described in the form GBP/GBP_MASK, where GBP is + represented as a 32bit number. ++erspan_opts ++.I OPTIONS ++doesn't support multiple options, and it consists of a key followed by a slash ++and corresponding mask. If the mask is missing, \fBtc\fR assumes a full-length ++match. The option can be described in the form ++VERSION:INDEX:DIR:HWID/VERSION:INDEX_MASK:DIR_MASK:HWID_MASK, where VERSION is ++represented as a 8bit number, INDEX as an 32bit number, DIR and HWID as a 8bit ++number. Multiple options is not supported. Note INDEX/INDEX_MASK is used when ++VERSION is 1, and DIR/DIR_MASK and HWID/HWID_MASK are used when VERSION is 2. + .TP + .BI ip_flags " IP_FLAGS" + .I IP_FLAGS +diff --git a/tc/f_flower.c b/tc/f_flower.c +index 09079cd2c2280..691541ec59d4c 100644 +--- a/tc/f_flower.c ++++ b/tc/f_flower.c +@@ -82,6 +82,7 @@ static void explain(void) + " enc_ttl MASKED-IP_TTL |\n" + " geneve_opts MASKED-OPTIONS |\n" + " vxlan_opts MASKED-OPTIONS |\n" ++ " erspan_opts MASKED-OPTIONS |\n" + " ip_flags IP-FLAGS | \n" + " enc_dst_port [ port_number ] }\n" + " FILTERID := X:Y:Z\n" +@@ -738,6 +739,84 @@ static int flower_parse_vxlan_opt(char *str, struct nlmsghdr *n) + return 0; + } + ++static int flower_parse_erspan_opt(char *str, struct nlmsghdr *n) ++{ ++ struct rtattr *nest; ++ char *token; ++ int i, err; ++ ++ nest = addattr_nest(n, MAX_MSG, ++ TCA_FLOWER_KEY_ENC_OPTS_ERSPAN | NLA_F_NESTED); ++ ++ i = 1; ++ token = strsep(&str, ":"); ++ while (token) { ++ switch (i) { ++ case TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ addattr8(n, MAX_MSG, i, opt_type); ++ break; ++ } ++ case TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX: ++ { ++ __be32 opt_index; ++ ++ if (!strlen(token)) ++ break; ++ err = get_be32(&opt_index, token, 0); ++ if (err) ++ return err; ++ ++ addattr32(n, MAX_MSG, i, opt_index); ++ break; ++ } ++ case TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ addattr8(n, MAX_MSG, i, opt_type); ++ break; ++ } ++ case TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID: ++ { ++ __u8 opt_type; ++ ++ if (!strlen(token)) ++ break; ++ err = get_u8(&opt_type, token, 0); ++ if (err) ++ return err; ++ ++ addattr8(n, MAX_MSG, i, opt_type); ++ break; ++ } ++ default: ++ fprintf(stderr, "Unknown \"geneve_opts\" type\n"); ++ return -1; ++ } ++ ++ token = strsep(&str, ":"); ++ i++; ++ } ++ addattr_nest_end(n, nest); ++ ++ return 0; ++} ++ + static int flower_parse_geneve_opts(char *str, struct nlmsghdr *n) + { + char *token; +@@ -878,6 +957,49 @@ static int flower_parse_enc_opts_vxlan(char *str, struct nlmsghdr *n) + return 0; + } + ++static int flower_parse_enc_opts_erspan(char *str, struct nlmsghdr *n) ++{ ++ char key[XATTR_SIZE_MAX], mask[XATTR_SIZE_MAX]; ++ struct rtattr *nest; ++ char *slash; ++ int err; ++ ++ ++ slash = strchr(str, '/'); ++ if (slash) { ++ *slash++ = '\0'; ++ if (strlen(slash) > XATTR_SIZE_MAX) ++ return -1; ++ strcpy(mask, slash); ++ } else { ++ int index; ++ ++ slash = strchr(str, ':'); ++ index = (int)(slash - str); ++ memcpy(mask, str, index); ++ strcpy(mask + index, ":0xffffffff:0xff:0xff"); ++ } ++ ++ if (strlen(str) > XATTR_SIZE_MAX) ++ return -1; ++ strcpy(key, str); ++ ++ nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS | NLA_F_NESTED); ++ err = flower_parse_erspan_opt(key, n); ++ if (err) ++ return err; ++ addattr_nest_end(n, nest); ++ ++ nest = addattr_nest(n, MAX_MSG, ++ TCA_FLOWER_KEY_ENC_OPTS_MASK | NLA_F_NESTED); ++ err = flower_parse_erspan_opt(mask, n); ++ if (err) ++ return err; ++ addattr_nest_end(n, nest); ++ ++ return 0; ++} ++ + static int flower_parse_opt(struct filter_util *qu, char *handle, + int argc, char **argv, struct nlmsghdr *n) + { +@@ -1344,6 +1466,13 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + fprintf(stderr, "Illegal \"vxlan_opts\"\n"); + return -1; + } ++ } else if (matches(*argv, "erspan_opts") == 0) { ++ NEXT_ARG(); ++ ret = flower_parse_enc_opts_erspan(*argv, n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"erspan_opts\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "action") == 0) { + NEXT_ARG(); + ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n); +@@ -1727,6 +1856,38 @@ static void flower_print_vxlan_opts(const char *name, struct rtattr *attr, + sprintf(strbuf, "%u", gbp); + } + ++static void flower_print_erspan_opts(const char *name, struct rtattr *attr, ++ char *strbuf) ++{ ++ struct rtattr *tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX + 1]; ++ __u8 ver, hwid, dir; ++ __u32 idx; ++ ++ parse_rtattr(tb, TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX, RTA_DATA(attr), ++ RTA_PAYLOAD(attr)); ++ ver = rta_getattr_u8(tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER]); ++ if (ver == 1) { ++ idx = rta_getattr_be32(tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX]); ++ hwid = 0; ++ dir = 0; ++ } else { ++ idx = 0; ++ hwid = rta_getattr_u8(tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID]); ++ dir = rta_getattr_u8(tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR]); ++ } ++ ++ open_json_array(PRINT_JSON, name); ++ open_json_object(NULL); ++ print_uint(PRINT_JSON, "ver", NULL, ver); ++ print_uint(PRINT_JSON, "index", NULL, idx); ++ print_uint(PRINT_JSON, "dir", NULL, dir); ++ print_uint(PRINT_JSON, "hwid", NULL, hwid); ++ close_json_object(); ++ close_json_array(PRINT_JSON, name); ++ ++ sprintf(strbuf, "%u:%u:%u:%u", ver, idx, dir, hwid); ++} ++ + static void flower_print_enc_parts(const char *name, const char *namefrm, + struct rtattr *attr, char *key, char *mask) + { +@@ -1792,6 +1953,16 @@ static void flower_print_enc_opts(const char *name, struct rtattr *attr, + + flower_print_enc_parts(name, " vxlan_opts %s", attr, key, + msk); ++ } else if (key_tb[TCA_FLOWER_KEY_ENC_OPTS_ERSPAN]) { ++ flower_print_erspan_opts("erspan_opt_key", ++ key_tb[TCA_FLOWER_KEY_ENC_OPTS_ERSPAN], key); ++ ++ if (msk_tb[TCA_FLOWER_KEY_ENC_OPTS_ERSPAN]) ++ flower_print_erspan_opts("erspan_opt_mask", ++ msk_tb[TCA_FLOWER_KEY_ENC_OPTS_ERSPAN], msk); ++ ++ flower_print_enc_parts(name, " erspan_opts %s", attr, key, ++ msk); + } + + free(msk); +-- +2.26.2 + diff --git a/SOURCES/0031-devlink-Add-health-error-recovery-status-monitoring.patch b/SOURCES/0031-devlink-Add-health-error-recovery-status-monitoring.patch new file mode 100644 index 0000000..813691b --- /dev/null +++ b/SOURCES/0031-devlink-Add-health-error-recovery-status-monitoring.patch @@ -0,0 +1,116 @@ +From 81a035c029c2ef108da0f854c5a670aa3f06bb94 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Wed, 17 Jun 2020 12:10:11 +0200 +Subject: [PATCH] devlink: Add health error recovery status monitoring + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1821039 +Upstream Status: iproute2.git commit 5023df6a21c73 +Conflicts: context change due to missing commit + - ef12d6dafaeb9 ("devlink: Add devlink trap set and show commands") + - 4ede9e9d56206 ("devlink: Add devlink trap group set and show commands") + - a66af5569337b ("devlink: Add devlink trap policer set and show commands") + +commit 5023df6a21c73560b514d7fde5381d140373afe9 +Author: Moshe Shemesh +Date: Tue Feb 4 23:37:02 2020 +0200 + + devlink: Add health error recovery status monitoring + + Add support for devlink health error recovery status monitoring. + Update devlink-monitor man page accordingly. + + Signed-off-by: Moshe Shemesh + Acked-by: Jiri Pirko + Signed-off-by: David Ahern +--- + devlink/devlink.c | 17 +++++++++++++++-- + man/man8/devlink-monitor.8 | 3 ++- + 2 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/devlink/devlink.c b/devlink/devlink.c +index 0293373928f50..f7e859c266394 100644 +--- a/devlink/devlink.c ++++ b/devlink/devlink.c +@@ -3764,6 +3764,7 @@ static const char *cmd_name(uint8_t cmd) + case DEVLINK_CMD_REGION_SET: return "set"; + case DEVLINK_CMD_REGION_NEW: return "new"; + case DEVLINK_CMD_REGION_DEL: return "del"; ++ case DEVLINK_CMD_HEALTH_REPORTER_RECOVER: return "status"; + default: return ""; + } + } +@@ -3792,6 +3793,8 @@ static const char *cmd_obj(uint8_t cmd) + case DEVLINK_CMD_REGION_NEW: + case DEVLINK_CMD_REGION_DEL: + return "region"; ++ case DEVLINK_CMD_HEALTH_REPORTER_RECOVER: ++ return "health"; + default: return ""; + } + } +@@ -3817,6 +3820,7 @@ static bool cmd_filter_check(struct dl *dl, uint8_t cmd) + } + + static void pr_out_region(struct dl *dl, struct nlattr **tb); ++static void pr_out_health(struct dl *dl, struct nlattr **tb_health); + + static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) + { +@@ -3872,6 +3876,14 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) + pr_out_mon_header(genl->cmd); + pr_out_region(dl, tb); + break; ++ case DEVLINK_CMD_HEALTH_REPORTER_RECOVER: ++ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); ++ if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || ++ !tb[DEVLINK_ATTR_HEALTH_REPORTER]) ++ return MNL_CB_ERROR; ++ pr_out_mon_header(genl->cmd); ++ pr_out_health(dl, tb); ++ break; + } + return MNL_CB_OK; + } +@@ -3885,7 +3897,8 @@ static int cmd_mon_show(struct dl *dl) + while ((cur_obj = dl_argv_index(dl, index++))) { + if (strcmp(cur_obj, "all") != 0 && + strcmp(cur_obj, "dev") != 0 && +- strcmp(cur_obj, "port") != 0) { ++ strcmp(cur_obj, "port") != 0 && ++ strcmp(cur_obj, "health") != 0) { + pr_err("Unknown object \"%s\"\n", cur_obj); + return -EINVAL; + } +@@ -3902,7 +3915,7 @@ static int cmd_mon_show(struct dl *dl) + static void cmd_mon_help(void) + { + pr_err("Usage: devlink monitor [ all | OBJECT-LIST ]\n" +- "where OBJECT-LIST := { dev | port }\n"); ++ "where OBJECT-LIST := { dev | port | health }\n"); + } + + static int cmd_mon(struct dl *dl) +diff --git a/man/man8/devlink-monitor.8 b/man/man8/devlink-monitor.8 +index 13fe641dc8f54..9bc579673ebf4 100644 +--- a/man/man8/devlink-monitor.8 ++++ b/man/man8/devlink-monitor.8 +@@ -21,7 +21,7 @@ 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 ". ++.BR dev ", " port ", " health ". + + .B devlink + opens Devlink Netlink socket, listens on it and dumps state changes. +@@ -31,6 +31,7 @@ opens Devlink Netlink socket, listens on it and dumps state changes. + .BR devlink-dev (8), + .BR devlink-sb (8), + .BR devlink-port (8), ++.BR devlink-health (8), + .br + + .SH AUTHOR +-- +2.26.2 + diff --git a/SOURCES/0032-ss-allow-dumping-kTLS-info.patch b/SOURCES/0032-ss-allow-dumping-kTLS-info.patch new file mode 100644 index 0000000..9fe02ae --- /dev/null +++ b/SOURCES/0032-ss-allow-dumping-kTLS-info.patch @@ -0,0 +1,139 @@ +From 06bd12bd8e48182f7f3293bbec187b4e90da796f Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Mon, 29 Jun 2020 14:36:51 +0200 +Subject: [PATCH] ss: allow dumping kTLS info + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1812207 +Upstream Status: iproute2.git commit 14cadc707b919 +Conflicts: due to out-of-order cherry-pick of commit + 712fdd98c0839 ("ss: allow dumping MPTCP subflow information") + +commit 14cadc707b919914e9a2d5dffad9232c3ae97c5f +Author: Davide Caratti +Date: Mon Oct 7 12:16:44 2019 +0200 + + ss: allow dumping kTLS info + + now that INET_DIAG_INFO requests can dump TCP ULP information, extend 'ss' + to allow diagnosing kTLS when it is attached to a TCP socket. While at it, + import kTLS uAPI definitions from the latest net-next tree. + + CC: Andrea Claudi + Co-developed-by: Jakub Kicinski + Signed-off-by: Jakub Kicinski + Signed-off-by: Davide Caratti + Signed-off-by: David Ahern +--- + misc/ss.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 82 insertions(+) + +diff --git a/misc/ss.c b/misc/ss.c +index 3d565af86087c..8285382bd6c4a 100644 +--- a/misc/ss.c ++++ b/misc/ss.c +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + #include + + /* AF_VSOCK/PF_VSOCK is only provided since glibc 2.18 */ +@@ -2752,6 +2753,72 @@ static void print_md5sig(struct tcp_diag_md5sig *sig) + print_escape_buf(sig->tcpm_key, sig->tcpm_keylen, " ,"); + } + ++static void tcp_tls_version(struct rtattr *attr) ++{ ++ u_int16_t val; ++ ++ if (!attr) ++ return; ++ val = rta_getattr_u16(attr); ++ ++ switch (val) { ++ case TLS_1_2_VERSION: ++ out(" version: 1.2"); ++ break; ++ case TLS_1_3_VERSION: ++ out(" version: 1.3"); ++ break; ++ default: ++ out(" version: unknown(%hu)", val); ++ break; ++ } ++} ++ ++static void tcp_tls_cipher(struct rtattr *attr) ++{ ++ u_int16_t val; ++ ++ if (!attr) ++ return; ++ val = rta_getattr_u16(attr); ++ ++ switch (val) { ++ case TLS_CIPHER_AES_GCM_128: ++ out(" cipher: aes-gcm-128"); ++ break; ++ case TLS_CIPHER_AES_GCM_256: ++ out(" cipher: aes-gcm-256"); ++ break; ++ } ++} ++ ++static void tcp_tls_conf(const char *name, struct rtattr *attr) ++{ ++ u_int16_t val; ++ ++ if (!attr) ++ return; ++ val = rta_getattr_u16(attr); ++ ++ switch (val) { ++ case TLS_CONF_BASE: ++ out(" %s: none", name); ++ break; ++ case TLS_CONF_SW: ++ out(" %s: sw", name); ++ break; ++ case TLS_CONF_HW: ++ out(" %s: hw", name); ++ break; ++ case TLS_CONF_HW_RECORD: ++ out(" %s: hw-record", name); ++ break; ++ default: ++ out(" %s: unknown(%hu)", name, val); ++ break; ++ } ++} ++ + static void mptcp_subflow_info(struct rtattr *tb[]) + { + u_int32_t flags = 0; +@@ -2966,6 +3033,21 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, + parse_rtattr_nested(ulpinfo, INET_ULP_INFO_MAX, + tb[INET_DIAG_ULP_INFO]); + ++ if (ulpinfo[INET_ULP_INFO_NAME]) ++ out(" tcp-ulp-%s", ++ rta_getattr_str(ulpinfo[INET_ULP_INFO_NAME])); ++ ++ if (ulpinfo[INET_ULP_INFO_TLS]) { ++ struct rtattr *tlsinfo[TLS_INFO_MAX + 1] = { 0 }; ++ ++ parse_rtattr_nested(tlsinfo, TLS_INFO_MAX, ++ ulpinfo[INET_ULP_INFO_TLS]); ++ ++ tcp_tls_version(tlsinfo[TLS_INFO_VERSION]); ++ tcp_tls_cipher(tlsinfo[TLS_INFO_CIPHER]); ++ tcp_tls_conf("rxconf", tlsinfo[TLS_INFO_RXCONF]); ++ tcp_tls_conf("txconf", tlsinfo[TLS_INFO_TXCONF]); ++ } + if (ulpinfo[INET_ULP_INFO_MPTCP]) { + struct rtattr *sfinfo[MPTCP_SUBFLOW_ATTR_MAX + 1] = + { 0 }; +-- +2.26.2 + diff --git a/SOURCES/0033-Import-tc_act-tc_ct.h-uapi-file.patch b/SOURCES/0033-Import-tc_act-tc_ct.h-uapi-file.patch new file mode 100644 index 0000000..f3c473d --- /dev/null +++ b/SOURCES/0033-Import-tc_act-tc_ct.h-uapi-file.patch @@ -0,0 +1,73 @@ +From 4c330f41bce887a4a06d6c84c62a3a8c1b0b5160 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Tue, 9 Jun 2020 15:45:55 +0200 +Subject: [PATCH] Import tc_act/tc_ct.h uapi file + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1844637 +Upstream Status: iproute2.git commit f47081befffc5 + +commit f47081befffc50a5eef734d0a6654b59047e7808 +Author: David Ahern +Date: Thu Jul 18 15:40:07 2019 -0700 + + Import tc_act/tc_ct.h uapi file + + Import include/uapi/linux/tc_act/tc_ct.h header from commit of last + kernel headers sync. + + Signed-off-by: David Ahern +--- + include/uapi/linux/tc_act/tc_ct.h | 41 +++++++++++++++++++++++++++++++ + 1 file changed, 41 insertions(+) + create mode 100644 include/uapi/linux/tc_act/tc_ct.h + +diff --git a/include/uapi/linux/tc_act/tc_ct.h b/include/uapi/linux/tc_act/tc_ct.h +new file mode 100644 +index 0000000000000..5fb1d7ac10272 +--- /dev/null ++++ b/include/uapi/linux/tc_act/tc_ct.h +@@ -0,0 +1,41 @@ ++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++#ifndef __UAPI_TC_CT_H ++#define __UAPI_TC_CT_H ++ ++#include ++#include ++ ++enum { ++ TCA_CT_UNSPEC, ++ TCA_CT_PARMS, ++ TCA_CT_TM, ++ TCA_CT_ACTION, /* u16 */ ++ TCA_CT_ZONE, /* u16 */ ++ TCA_CT_MARK, /* u32 */ ++ TCA_CT_MARK_MASK, /* u32 */ ++ TCA_CT_LABELS, /* u128 */ ++ TCA_CT_LABELS_MASK, /* u128 */ ++ TCA_CT_NAT_IPV4_MIN, /* be32 */ ++ TCA_CT_NAT_IPV4_MAX, /* be32 */ ++ TCA_CT_NAT_IPV6_MIN, /* struct in6_addr */ ++ TCA_CT_NAT_IPV6_MAX, /* struct in6_addr */ ++ TCA_CT_NAT_PORT_MIN, /* be16 */ ++ TCA_CT_NAT_PORT_MAX, /* be16 */ ++ TCA_CT_PAD, ++ __TCA_CT_MAX ++}; ++ ++#define TCA_CT_MAX (__TCA_CT_MAX - 1) ++ ++#define TCA_CT_ACT_COMMIT (1 << 0) ++#define TCA_CT_ACT_FORCE (1 << 1) ++#define TCA_CT_ACT_CLEAR (1 << 2) ++#define TCA_CT_ACT_NAT (1 << 3) ++#define TCA_CT_ACT_NAT_SRC (1 << 4) ++#define TCA_CT_ACT_NAT_DST (1 << 5) ++ ++struct tc_ct { ++ tc_gen; ++}; ++ ++#endif /* __UAPI_TC_CT_H */ +-- +2.26.2 + diff --git a/SOURCES/0034-tc-add-NLA_F_NESTED-flag-to-all-actions-options-nest.patch b/SOURCES/0034-tc-add-NLA_F_NESTED-flag-to-all-actions-options-nest.patch new file mode 100644 index 0000000..5832ac4 --- /dev/null +++ b/SOURCES/0034-tc-add-NLA_F_NESTED-flag-to-all-actions-options-nest.patch @@ -0,0 +1,40 @@ +From bf795d2418ee298ddc73171829d6dc4914c22a46 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Tue, 9 Jun 2020 15:45:56 +0200 +Subject: [PATCH] tc: add NLA_F_NESTED flag to all actions options nested block + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1844637 +Upstream Status: iproute2.git commit 18aa9f5583e94 + +commit 18aa9f5583e94abc7204b2376b819ede1180da97 +Author: Paul Blakey +Date: Thu Jul 11 11:14:25 2019 +0300 + + tc: add NLA_F_NESTED flag to all actions options nested block + + Strict netlink validation now requires this flag on all nested + attributes, add it for action options. + + Signed-off-by: Paul Blakey + Signed-off-by: David Ahern +--- + tc/m_action.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tc/m_action.c b/tc/m_action.c +index c46aeaafa8ebf..4da810c8c0aa7 100644 +--- a/tc/m_action.c ++++ b/tc/m_action.c +@@ -214,7 +214,8 @@ done0: + tail = addattr_nest(n, MAX_MSG, ++prio); + addattr_l(n, MAX_MSG, TCA_ACT_KIND, k, strlen(k) + 1); + +- ret = a->parse_aopt(a, &argc, &argv, TCA_ACT_OPTIONS, ++ ret = a->parse_aopt(a, &argc, &argv, ++ TCA_ACT_OPTIONS | NLA_F_NESTED, + n); + + if (ret < 0) { +-- +2.26.2 + diff --git a/SOURCES/0035-tc-Introduce-tc-ct-action.patch b/SOURCES/0035-tc-Introduce-tc-ct-action.patch new file mode 100644 index 0000000..3971adf --- /dev/null +++ b/SOURCES/0035-tc-Introduce-tc-ct-action.patch @@ -0,0 +1,621 @@ +From ef66b6a546f3f1fd517cfa306cc347ad096bd932 Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Tue, 9 Jun 2020 15:45:56 +0200 +Subject: [PATCH] tc: Introduce tc ct action + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1844637 +Upstream Status: iproute2.git commit c8a494314c400 + +commit c8a494314c400eb023d7555933ba8ab40345519b +Author: Paul Blakey +Date: Thu Jul 11 11:14:26 2019 +0300 + + tc: Introduce tc ct action + + New tc action to send packets to conntrack module, commit + them, and set a zone, labels, mark, and nat on the connection. + + It can also clear the packet's conntrack state by using clear. + + Usage: + ct clear + ct commit [force] [zone] [mark] [label] [nat] + ct [nat] [zone] + + Signed-off-by: Paul Blakey + Signed-off-by: Marcelo Ricardo Leitner + Signed-off-by: Yossi Kuperman + Acked-by: Jiri Pirko + Acked-by: Roi Dayan + Signed-off-by: David Ahern +--- + tc/Makefile | 1 + + tc/m_ct.c | 497 +++++++++++++++++++++++++++++++++++++++++++++++++++ + tc/tc_util.c | 44 +++++ + tc/tc_util.h | 4 + + 4 files changed, 546 insertions(+) + create mode 100644 tc/m_ct.c + +diff --git a/tc/Makefile b/tc/Makefile +index 09ff3692b1663..14171a28cba5d 100644 +--- a/tc/Makefile ++++ b/tc/Makefile +@@ -53,6 +53,7 @@ TCMODULES += m_ctinfo.o + TCMODULES += m_bpf.o + TCMODULES += m_tunnel_key.o + TCMODULES += m_sample.o ++TCMODULES += m_ct.o + TCMODULES += p_ip.o + TCMODULES += p_ip6.o + TCMODULES += p_icmp.o +diff --git a/tc/m_ct.c b/tc/m_ct.c +new file mode 100644 +index 0000000000000..8589cb9a3c515 +--- /dev/null ++++ b/tc/m_ct.c +@@ -0,0 +1,497 @@ ++// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB ++/* - ++ * m_ct.c Connection tracking action ++ * ++ * Authors: Paul Blakey ++ * Yossi Kuperman ++ * Marcelo Ricardo Leitner ++ */ ++ ++#include ++#include ++#include ++#include ++#include "utils.h" ++#include "tc_util.h" ++#include ++ ++static void ++usage(void) ++{ ++ fprintf(stderr, ++ "Usage: ct clear\n" ++ " ct commit [force] [zone ZONE] [mark MASKED_MARK] [label MASKED_LABEL] [nat NAT_SPEC]\n" ++ " ct [nat] [zone ZONE]\n" ++ "Where: ZONE is the conntrack zone table number\n" ++ " NAT_SPEC is {src|dst} addr addr1[-addr2] [port port1[-port2]]\n" ++ "\n"); ++ exit(-1); ++} ++ ++static int ct_parse_nat_addr_range(const char *str, struct nlmsghdr *n) ++{ ++ inet_prefix addr = { .family = AF_UNSPEC, }; ++ char *addr1, *addr2 = 0; ++ SPRINT_BUF(buffer); ++ int attr; ++ int ret; ++ ++ strncpy(buffer, str, sizeof(buffer) - 1); ++ ++ addr1 = buffer; ++ addr2 = strchr(addr1, '-'); ++ if (addr2) { ++ *addr2 = '\0'; ++ addr2++; ++ } ++ ++ ret = get_addr(&addr, addr1, AF_UNSPEC); ++ if (ret) ++ return ret; ++ attr = addr.family == AF_INET ? TCA_CT_NAT_IPV4_MIN : ++ TCA_CT_NAT_IPV6_MIN; ++ addattr_l(n, MAX_MSG, attr, addr.data, addr.bytelen); ++ ++ if (addr2) { ++ ret = get_addr(&addr, addr2, addr.family); ++ if (ret) ++ return ret; ++ } ++ attr = addr.family == AF_INET ? TCA_CT_NAT_IPV4_MAX : ++ TCA_CT_NAT_IPV6_MAX; ++ addattr_l(n, MAX_MSG, attr, addr.data, addr.bytelen); ++ ++ return 0; ++} ++ ++static int ct_parse_nat_port_range(const char *str, struct nlmsghdr *n) ++{ ++ char *port1, *port2 = 0; ++ SPRINT_BUF(buffer); ++ __be16 port; ++ int ret; ++ ++ strncpy(buffer, str, sizeof(buffer) - 1); ++ ++ port1 = buffer; ++ port2 = strchr(port1, '-'); ++ if (port2) { ++ *port2 = '\0'; ++ port2++; ++ } ++ ++ ret = get_be16(&port, port1, 10); ++ if (ret) ++ return -1; ++ addattr16(n, MAX_MSG, TCA_CT_NAT_PORT_MIN, port); ++ ++ if (port2) { ++ ret = get_be16(&port, port2, 10); ++ if (ret) ++ return -1; ++ } ++ addattr16(n, MAX_MSG, TCA_CT_NAT_PORT_MAX, port); ++ ++ return 0; ++} ++ ++ ++static int ct_parse_u16(char *str, int value_type, int mask_type, ++ struct nlmsghdr *n) ++{ ++ __u16 value, mask; ++ char *slash = 0; ++ ++ if (mask_type != TCA_CT_UNSPEC) { ++ slash = strchr(str, '/'); ++ if (slash) ++ *slash = '\0'; ++ } ++ ++ if (get_u16(&value, str, 0)) ++ return -1; ++ ++ if (slash) { ++ if (get_u16(&mask, slash + 1, 0)) ++ return -1; ++ } else { ++ mask = UINT16_MAX; ++ } ++ ++ addattr16(n, MAX_MSG, value_type, value); ++ if (mask_type != TCA_CT_UNSPEC) ++ addattr16(n, MAX_MSG, mask_type, mask); ++ ++ return 0; ++} ++ ++static int ct_parse_u32(char *str, int value_type, int mask_type, ++ struct nlmsghdr *n) ++{ ++ __u32 value, mask; ++ char *slash; ++ ++ slash = strchr(str, '/'); ++ if (slash) ++ *slash = '\0'; ++ ++ if (get_u32(&value, str, 0)) ++ return -1; ++ ++ if (slash) { ++ if (get_u32(&mask, slash + 1, 0)) ++ return -1; ++ } else { ++ mask = UINT32_MAX; ++ } ++ ++ addattr32(n, MAX_MSG, value_type, value); ++ addattr32(n, MAX_MSG, mask_type, mask); ++ ++ return 0; ++} ++ ++static int ct_parse_mark(char *str, struct nlmsghdr *n) ++{ ++ return ct_parse_u32(str, TCA_CT_MARK, TCA_CT_MARK_MASK, n); ++} ++ ++static int ct_parse_labels(char *str, struct nlmsghdr *n) ++{ ++#define LABELS_SIZE 16 ++ uint8_t labels[LABELS_SIZE], lmask[LABELS_SIZE]; ++ char *slash, *mask = NULL; ++ size_t slen, slen_mask = 0; ++ ++ slash = index(str, '/'); ++ if (slash) { ++ *slash = 0; ++ mask = slash+1; ++ slen_mask = strlen(mask); ++ } ++ ++ slen = strlen(str); ++ if (slen > LABELS_SIZE*2 || slen_mask > LABELS_SIZE*2) { ++ char errmsg[128]; ++ ++ snprintf(errmsg, sizeof(errmsg), ++ "%zd Max allowed size %d", ++ slen, LABELS_SIZE*2); ++ invarg(errmsg, str); ++ } ++ ++ if (hex2mem(str, labels, slen/2) < 0) ++ invarg("ct: labels must be a hex string\n", str); ++ addattr_l(n, MAX_MSG, TCA_CT_LABELS, labels, slen/2); ++ ++ if (mask) { ++ if (hex2mem(mask, lmask, slen_mask/2) < 0) ++ invarg("ct: labels mask must be a hex string\n", mask); ++ } else { ++ memset(lmask, 0xff, sizeof(lmask)); ++ slen_mask = sizeof(lmask)*2; ++ } ++ addattr_l(n, MAX_MSG, TCA_CT_LABELS_MASK, lmask, slen_mask/2); ++ ++ return 0; ++} ++ ++static int ++parse_ct(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, ++ struct nlmsghdr *n) ++{ ++ struct tc_ct sel = {}; ++ char **argv = *argv_p; ++ struct rtattr *tail; ++ int argc = *argc_p; ++ int ct_action = 0; ++ int ret; ++ ++ tail = addattr_nest(n, MAX_MSG, tca_id); ++ ++ if (argc && matches(*argv, "ct") == 0) ++ NEXT_ARG_FWD(); ++ ++ while (argc > 0) { ++ if (matches(*argv, "zone") == 0) { ++ NEXT_ARG(); ++ ++ if (ct_parse_u16(*argv, ++ TCA_CT_ZONE, TCA_CT_UNSPEC, n)) { ++ fprintf(stderr, "ct: Illegal \"zone\"\n"); ++ return -1; ++ } ++ } else if (matches(*argv, "nat") == 0) { ++ ct_action |= TCA_CT_ACT_NAT; ++ ++ NEXT_ARG(); ++ if (matches(*argv, "src") == 0) ++ ct_action |= TCA_CT_ACT_NAT_SRC; ++ else if (matches(*argv, "dst") == 0) ++ ct_action |= TCA_CT_ACT_NAT_DST; ++ else ++ continue; ++ ++ NEXT_ARG(); ++ if (matches(*argv, "addr") != 0) ++ usage(); ++ ++ NEXT_ARG(); ++ ret = ct_parse_nat_addr_range(*argv, n); ++ if (ret) { ++ fprintf(stderr, "ct: Illegal nat address range\n"); ++ return -1; ++ } ++ ++ NEXT_ARG_FWD(); ++ if (matches(*argv, "port") != 0) ++ continue; ++ ++ NEXT_ARG(); ++ ret = ct_parse_nat_port_range(*argv, n); ++ if (ret) { ++ fprintf(stderr, "ct: Illegal nat port range\n"); ++ return -1; ++ } ++ } else if (matches(*argv, "clear") == 0) { ++ ct_action |= TCA_CT_ACT_CLEAR; ++ } else if (matches(*argv, "commit") == 0) { ++ ct_action |= TCA_CT_ACT_COMMIT; ++ } else if (matches(*argv, "force") == 0) { ++ ct_action |= TCA_CT_ACT_FORCE; ++ } else if (matches(*argv, "index") == 0) { ++ NEXT_ARG(); ++ if (get_u32(&sel.index, *argv, 10)) { ++ fprintf(stderr, "ct: Illegal \"index\"\n"); ++ return -1; ++ } ++ } else if (matches(*argv, "mark") == 0) { ++ NEXT_ARG(); ++ ++ ret = ct_parse_mark(*argv, n); ++ if (ret) { ++ fprintf(stderr, "ct: Illegal \"mark\"\n"); ++ return -1; ++ } ++ } else if (matches(*argv, "label") == 0) { ++ NEXT_ARG(); ++ ++ ret = ct_parse_labels(*argv, n); ++ if (ret) { ++ fprintf(stderr, "ct: Illegal \"label\"\n"); ++ return -1; ++ } ++ } else if (matches(*argv, "help") == 0) { ++ usage(); ++ } else { ++ break; ++ } ++ NEXT_ARG_FWD(); ++ } ++ ++ if (ct_action & TCA_CT_ACT_CLEAR && ++ ct_action & ~TCA_CT_ACT_CLEAR) { ++ fprintf(stderr, "ct: clear can only be used alone\n"); ++ return -1; ++ } ++ ++ if (ct_action & TCA_CT_ACT_NAT_SRC && ++ ct_action & TCA_CT_ACT_NAT_DST) { ++ fprintf(stderr, "ct: src and dst nat can't be used together\n"); ++ return -1; ++ } ++ ++ if ((ct_action & TCA_CT_ACT_COMMIT) && ++ (ct_action & TCA_CT_ACT_NAT) && ++ !(ct_action & (TCA_CT_ACT_NAT_SRC | TCA_CT_ACT_NAT_DST))) { ++ fprintf(stderr, "ct: commit and nat must set src or dst\n"); ++ return -1; ++ } ++ ++ if (!(ct_action & TCA_CT_ACT_COMMIT) && ++ (ct_action & (TCA_CT_ACT_NAT_SRC | TCA_CT_ACT_NAT_DST))) { ++ fprintf(stderr, "ct: src or dst is only valid if commit is set\n"); ++ return -1; ++ } ++ ++ parse_action_control_dflt(&argc, &argv, &sel.action, false, ++ TC_ACT_PIPE); ++ NEXT_ARG_FWD(); ++ ++ addattr16(n, MAX_MSG, TCA_CT_ACTION, ct_action); ++ addattr_l(n, MAX_MSG, TCA_CT_PARMS, &sel, sizeof(sel)); ++ addattr_nest_end(n, tail); ++ ++ *argc_p = argc; ++ *argv_p = argv; ++ return 0; ++} ++ ++static int ct_sprint_port(char *buf, const char *prefix, struct rtattr *attr) ++{ ++ if (!attr) ++ return 0; ++ ++ return sprintf(buf, "%s%d", prefix, rta_getattr_be16(attr)); ++} ++ ++static int ct_sprint_ip_addr(char *buf, const char *prefix, ++ struct rtattr *attr) ++{ ++ int family; ++ size_t len; ++ ++ if (!attr) ++ return 0; ++ ++ len = RTA_PAYLOAD(attr); ++ ++ if (len == 4) ++ family = AF_INET; ++ else if (len == 16) ++ family = AF_INET6; ++ else ++ return 0; ++ ++ return sprintf(buf, "%s%s", prefix, rt_addr_n2a_rta(family, attr)); ++} ++ ++static void ct_print_nat(int ct_action, struct rtattr **tb) ++{ ++ size_t done = 0; ++ char out[256] = ""; ++ bool nat; ++ ++ if (!(ct_action & TCA_CT_ACT_NAT)) ++ return; ++ ++ if (ct_action & TCA_CT_ACT_NAT_SRC) { ++ nat = true; ++ done += sprintf(out + done, "src"); ++ } else if (ct_action & TCA_CT_ACT_NAT_DST) { ++ nat = true; ++ done += sprintf(out + done, "dst"); ++ } ++ ++ if (nat) { ++ done += ct_sprint_ip_addr(out + done, " addr ", ++ tb[TCA_CT_NAT_IPV4_MIN]); ++ done += ct_sprint_ip_addr(out + done, " addr ", ++ tb[TCA_CT_NAT_IPV6_MIN]); ++ if (tb[TCA_CT_NAT_IPV4_MAX] && ++ memcmp(RTA_DATA(tb[TCA_CT_NAT_IPV4_MIN]), ++ RTA_DATA(tb[TCA_CT_NAT_IPV4_MAX]), 4)) ++ done += ct_sprint_ip_addr(out + done, "-", ++ tb[TCA_CT_NAT_IPV4_MAX]); ++ else if (tb[TCA_CT_NAT_IPV6_MAX] && ++ memcmp(RTA_DATA(tb[TCA_CT_NAT_IPV6_MIN]), ++ RTA_DATA(tb[TCA_CT_NAT_IPV6_MAX]), 16)) ++ done += ct_sprint_ip_addr(out + done, "-", ++ tb[TCA_CT_NAT_IPV6_MAX]); ++ done += ct_sprint_port(out + done, " port ", ++ tb[TCA_CT_NAT_PORT_MIN]); ++ if (tb[TCA_CT_NAT_PORT_MAX] && ++ memcmp(RTA_DATA(tb[TCA_CT_NAT_PORT_MIN]), ++ RTA_DATA(tb[TCA_CT_NAT_PORT_MAX]), 2)) ++ done += ct_sprint_port(out + done, "-", ++ tb[TCA_CT_NAT_PORT_MAX]); ++ } ++ ++ if (done) ++ print_string(PRINT_ANY, "nat", " nat %s", out); ++ else ++ print_string(PRINT_ANY, "nat", " nat", ""); ++} ++ ++static void ct_print_labels(struct rtattr *attr, ++ struct rtattr *mask_attr) ++{ ++ const unsigned char *str; ++ bool print_mask = false; ++ char out[256], *p; ++ int data_len, i; ++ ++ if (!attr) ++ return; ++ ++ data_len = RTA_PAYLOAD(attr); ++ hexstring_n2a(RTA_DATA(attr), data_len, out, sizeof(out)); ++ p = out + data_len*2; ++ ++ data_len = RTA_PAYLOAD(attr); ++ str = RTA_DATA(mask_attr); ++ if (data_len != 16) ++ print_mask = true; ++ for (i = 0; !print_mask && i < data_len; i++) { ++ if (str[i] != 0xff) ++ print_mask = true; ++ } ++ if (print_mask) { ++ *p++ = '/'; ++ hexstring_n2a(RTA_DATA(mask_attr), data_len, p, ++ sizeof(out)-(p-out)); ++ p += data_len*2; ++ } ++ *p = '\0'; ++ ++ print_string(PRINT_ANY, "label", " label %s", out); ++} ++ ++static int print_ct(struct action_util *au, FILE *f, struct rtattr *arg) ++{ ++ struct rtattr *tb[TCA_CT_MAX + 1]; ++ const char *commit; ++ struct tc_ct *p; ++ int ct_action = 0; ++ ++ if (arg == NULL) ++ return -1; ++ ++ parse_rtattr_nested(tb, TCA_CT_MAX, arg); ++ if (tb[TCA_CT_PARMS] == NULL) { ++ print_string(PRINT_FP, NULL, "%s", "[NULL ct parameters]"); ++ return -1; ++ } ++ ++ p = RTA_DATA(tb[TCA_CT_PARMS]); ++ ++ print_string(PRINT_ANY, "kind", "%s", "ct"); ++ ++ if (tb[TCA_CT_ACTION]) ++ ct_action = rta_getattr_u16(tb[TCA_CT_ACTION]); ++ if (ct_action & TCA_CT_ACT_COMMIT) { ++ commit = ct_action & TCA_CT_ACT_FORCE ? ++ "commit force" : "commit"; ++ print_string(PRINT_ANY, "action", " %s", commit); ++ } else if (ct_action & TCA_CT_ACT_CLEAR) { ++ print_string(PRINT_ANY, "action", " %s", "clear"); ++ } ++ ++ print_masked_u32("mark", tb[TCA_CT_MARK], tb[TCA_CT_MARK_MASK]); ++ print_masked_u16("zone", tb[TCA_CT_ZONE], NULL); ++ ct_print_labels(tb[TCA_CT_LABELS], tb[TCA_CT_LABELS_MASK]); ++ ct_print_nat(ct_action, tb); ++ ++ print_action_control(f, " ", p->action, ""); ++ ++ print_uint(PRINT_ANY, "index", "\n\t index %u", p->index); ++ print_int(PRINT_ANY, "ref", " ref %d", p->refcnt); ++ print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt); ++ ++ if (show_stats) { ++ if (tb[TCA_CT_TM]) { ++ struct tcf_t *tm = RTA_DATA(tb[TCA_CT_TM]); ++ ++ print_tm(f, tm); ++ } ++ } ++ print_string(PRINT_FP, NULL, "%s", "\n "); ++ ++ return 0; ++} ++ ++struct action_util ct_action_util = { ++ .id = "ct", ++ .parse_aopt = parse_ct, ++ .print_aopt = print_ct, ++}; +diff --git a/tc/tc_util.c b/tc/tc_util.c +index b90d256c33a4a..0eb530408d056 100644 +--- a/tc/tc_util.c ++++ b/tc/tc_util.c +@@ -914,3 +914,47 @@ compat_xstats: + if (tb[TCA_XSTATS] && xstats) + *xstats = tb[TCA_XSTATS]; + } ++ ++void print_masked_u32(const char *name, struct rtattr *attr, ++ struct rtattr *mask_attr) ++{ ++ __u32 value, mask; ++ SPRINT_BUF(namefrm); ++ SPRINT_BUF(out); ++ size_t done; ++ ++ if (!attr) ++ return; ++ ++ value = rta_getattr_u32(attr); ++ mask = mask_attr ? rta_getattr_u32(mask_attr) : UINT32_MAX; ++ ++ done = sprintf(out, "%u", value); ++ if (mask != UINT32_MAX) ++ sprintf(out + done, "/0x%x", mask); ++ ++ sprintf(namefrm, " %s %%s", name); ++ print_string(PRINT_ANY, name, namefrm, out); ++} ++ ++void print_masked_u16(const char *name, struct rtattr *attr, ++ struct rtattr *mask_attr) ++{ ++ __u16 value, mask; ++ SPRINT_BUF(namefrm); ++ SPRINT_BUF(out); ++ size_t done; ++ ++ if (!attr) ++ return; ++ ++ value = rta_getattr_u16(attr); ++ mask = mask_attr ? rta_getattr_u16(mask_attr) : UINT16_MAX; ++ ++ done = sprintf(out, "%u", value); ++ if (mask != UINT16_MAX) ++ sprintf(out + done, "/0x%x", mask); ++ ++ sprintf(namefrm, " %s %%s", name); ++ print_string(PRINT_ANY, name, namefrm, out); ++} +diff --git a/tc/tc_util.h b/tc/tc_util.h +index eb4b60db3fdd7..0c3425abc62fa 100644 +--- a/tc/tc_util.h ++++ b/tc/tc_util.h +@@ -127,4 +127,8 @@ int action_a2n(char *arg, int *result, bool allow_num); + + bool tc_qdisc_block_exists(__u32 block_index); + ++void print_masked_u32(const char *name, struct rtattr *attr, ++ struct rtattr *mask_attr); ++void print_masked_u16(const char *name, struct rtattr *attr, ++ struct rtattr *mask_attr); + #endif +-- +2.26.2 + diff --git a/SOURCES/0036-tc-flower-Add-matching-on-conntrack-info.patch b/SOURCES/0036-tc-flower-Add-matching-on-conntrack-info.patch new file mode 100644 index 0000000..9de9989 --- /dev/null +++ b/SOURCES/0036-tc-flower-Add-matching-on-conntrack-info.patch @@ -0,0 +1,393 @@ +From b60d960c65c6aa5695ecf1c71b18790ca0cb475c Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Tue, 9 Jun 2020 15:45:56 +0200 +Subject: [PATCH] tc: flower: Add matching on conntrack info + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1844637 +Upstream Status: iproute2.git commit 2fffb1c03056e + +commit 2fffb1c03056e71d49d623f7ca460883fa6110a6 +Author: Paul Blakey +Date: Thu Jul 11 11:14:27 2019 +0300 + + tc: flower: Add matching on conntrack info + + Matches on conntrack state, zone, mark, and label. + + Signed-off-by: Paul Blakey + Signed-off-by: Marcelo Ricardo Leitner + Signed-off-by: Yossi Kuperman + Acked-by: Jiri Pirko + Acked-by: Roi Dayan + Signed-off-by: David Ahern +--- + man/man8/tc-flower.8 | 35 ++++++ + tc/f_flower.c | 276 ++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 310 insertions(+), 1 deletion(-) + +diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8 +index f41b0f7f1ef13..0f95f303f23b7 100644 +--- a/man/man8/tc-flower.8 ++++ b/man/man8/tc-flower.8 +@@ -295,6 +295,41 @@ bits is assumed. + .TQ + .BI enc_ttl " NUMBER" + .TQ ++.BR ++.TP ++.BI ct_state " CT_STATE" ++.TQ ++.BI ct_zone " CT_MASKED_ZONE" ++.TQ ++.BI ct_mark " CT_MASKED_MARK" ++.TQ ++.BI ct_label " CT_MASKED_LABEL" ++Matches on connection tracking info ++.RS ++.TP ++.I CT_STATE ++Match the connection state, and can ne combination of [{+|-}flag] flags, where flag can be one of ++.RS ++.TP ++trk - Tracked connection. ++.TP ++new - New connection. ++.TP ++est - Established connection. ++.TP ++Example: +trk+est ++.RE ++.TP ++.I CT_MASKED_ZONE ++Match the connection zone, and can be masked. ++.TP ++.I CT_MASKED_MARK ++32bit match on the connection mark, and can be masked. ++.TP ++.I CT_MASKED_LABEL ++128bit match on the connection label, and can be masked. ++.RE ++.TP + .BI geneve_opts " OPTIONS" + .TQ + .BI vxlan_opts " OPTIONS" +diff --git a/tc/f_flower.c b/tc/f_flower.c +index 691541ec59d4c..0a6eaa0df94ce 100644 +--- a/tc/f_flower.c ++++ b/tc/f_flower.c +@@ -84,9 +84,14 @@ static void explain(void) + " vxlan_opts MASKED-OPTIONS |\n" + " erspan_opts MASKED-OPTIONS |\n" + " ip_flags IP-FLAGS | \n" +- " enc_dst_port [ port_number ] }\n" ++ " enc_dst_port [ port_number ] |\n" ++ " ct_state MASKED_CT_STATE |\n" ++ " ct_label MASKED_CT_LABEL |\n" ++ " ct_mark MASKED_CT_MARK |\n" ++ " ct_zone MASKED_CT_ZONE }\n" + " FILTERID := X:Y:Z\n" + " MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS }\n" ++ " MASKED_CT_STATE := combination of {+|-} and flags trk,est,new\n" + " ACTION-SPEC := ... look at individual actions\n" + "\n" + "NOTE: CLASSID, IP-PROTO are parsed as hexadecimal input.\n" +@@ -216,6 +221,159 @@ static int flower_parse_matching_flags(char *str, + return 0; + } + ++static int flower_parse_u16(char *str, int value_type, int mask_type, ++ struct nlmsghdr *n) ++{ ++ __u16 value, mask; ++ char *slash; ++ ++ slash = strchr(str, '/'); ++ if (slash) ++ *slash = '\0'; ++ ++ if (get_u16(&value, str, 0)) ++ return -1; ++ ++ if (slash) { ++ if (get_u16(&mask, slash + 1, 0)) ++ return -1; ++ } else { ++ mask = UINT16_MAX; ++ } ++ ++ addattr16(n, MAX_MSG, value_type, value); ++ addattr16(n, MAX_MSG, mask_type, mask); ++ ++ return 0; ++} ++ ++static int flower_parse_u32(char *str, int value_type, int mask_type, ++ struct nlmsghdr *n) ++{ ++ __u32 value, mask; ++ char *slash; ++ ++ slash = strchr(str, '/'); ++ if (slash) ++ *slash = '\0'; ++ ++ if (get_u32(&value, str, 0)) ++ return -1; ++ ++ if (slash) { ++ if (get_u32(&mask, slash + 1, 0)) ++ return -1; ++ } else { ++ mask = UINT32_MAX; ++ } ++ ++ addattr32(n, MAX_MSG, value_type, value); ++ addattr32(n, MAX_MSG, mask_type, mask); ++ ++ return 0; ++} ++ ++static int flower_parse_ct_mark(char *str, struct nlmsghdr *n) ++{ ++ return flower_parse_u32(str, ++ TCA_FLOWER_KEY_CT_MARK, ++ TCA_FLOWER_KEY_CT_MARK_MASK, ++ n); ++} ++ ++static int flower_parse_ct_zone(char *str, struct nlmsghdr *n) ++{ ++ return flower_parse_u16(str, ++ TCA_FLOWER_KEY_CT_ZONE, ++ TCA_FLOWER_KEY_CT_ZONE_MASK, ++ n); ++} ++ ++static int flower_parse_ct_labels(char *str, struct nlmsghdr *n) ++{ ++#define LABELS_SIZE 16 ++ uint8_t labels[LABELS_SIZE], lmask[LABELS_SIZE]; ++ char *slash, *mask = NULL; ++ size_t slen, slen_mask = 0; ++ ++ slash = index(str, '/'); ++ if (slash) { ++ *slash = 0; ++ mask = slash + 1; ++ slen_mask = strlen(mask); ++ } ++ ++ slen = strlen(str); ++ if (slen > LABELS_SIZE * 2 || slen_mask > LABELS_SIZE * 2) { ++ char errmsg[128]; ++ ++ snprintf(errmsg, sizeof(errmsg), ++ "%zd Max allowed size %d", ++ slen, LABELS_SIZE*2); ++ invarg(errmsg, str); ++ } ++ ++ if (hex2mem(str, labels, slen / 2) < 0) ++ invarg("labels must be a hex string\n", str); ++ addattr_l(n, MAX_MSG, TCA_FLOWER_KEY_CT_LABELS, labels, slen / 2); ++ ++ if (mask) { ++ if (hex2mem(mask, lmask, slen_mask / 2) < 0) ++ invarg("labels mask must be a hex string\n", mask); ++ } else { ++ memset(lmask, 0xff, sizeof(lmask)); ++ slen_mask = sizeof(lmask) * 2; ++ } ++ addattr_l(n, MAX_MSG, TCA_FLOWER_KEY_CT_LABELS_MASK, lmask, ++ slen_mask / 2); ++ ++ return 0; ++} ++ ++static struct flower_ct_states { ++ char *str; ++ int flag; ++} flower_ct_states[] = { ++ { "trk", TCA_FLOWER_KEY_CT_FLAGS_TRACKED }, ++ { "new", TCA_FLOWER_KEY_CT_FLAGS_NEW }, ++ { "est", TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED }, ++}; ++ ++static int flower_parse_ct_state(char *str, struct nlmsghdr *n) ++{ ++ int flags = 0, mask = 0, len, i; ++ bool p; ++ ++ while (*str != '\0') { ++ if (*str == '+') ++ p = true; ++ else if (*str == '-') ++ p = false; ++ else ++ return -1; ++ ++ for (i = 0; i < ARRAY_SIZE(flower_ct_states); i++) { ++ len = strlen(flower_ct_states[i].str); ++ if (strncmp(str + 1, flower_ct_states[i].str, len)) ++ continue; ++ ++ if (p) ++ flags |= flower_ct_states[i].flag; ++ mask |= flower_ct_states[i].flag; ++ break; ++ } ++ ++ if (i == ARRAY_SIZE(flower_ct_states)) ++ return -1; ++ ++ str += len + 1; ++ } ++ ++ addattr16(n, MAX_MSG, TCA_FLOWER_KEY_CT_STATE, flags); ++ addattr16(n, MAX_MSG, TCA_FLOWER_KEY_CT_STATE_MASK, mask); ++ return 0; ++} ++ + static int flower_parse_ip_proto(char *str, __be16 eth_type, int type, + __u8 *p_ip_proto, struct nlmsghdr *n) + { +@@ -1077,6 +1235,34 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, + flags |= TCA_CLS_FLAGS_SKIP_HW; + } else if (matches(*argv, "skip_sw") == 0) { + flags |= TCA_CLS_FLAGS_SKIP_SW; ++ } else if (matches(*argv, "ct_state") == 0) { ++ NEXT_ARG(); ++ ret = flower_parse_ct_state(*argv, n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"ct_state\"\n"); ++ return -1; ++ } ++ } else if (matches(*argv, "ct_zone") == 0) { ++ NEXT_ARG(); ++ ret = flower_parse_ct_zone(*argv, n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"ct_zone\"\n"); ++ return -1; ++ } ++ } else if (matches(*argv, "ct_mark") == 0) { ++ NEXT_ARG(); ++ ret = flower_parse_ct_mark(*argv, n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"ct_mark\"\n"); ++ return -1; ++ } ++ } else if (matches(*argv, "ct_label") == 0) { ++ NEXT_ARG(); ++ ret = flower_parse_ct_labels(*argv, n); ++ if (ret < 0) { ++ fprintf(stderr, "Illegal \"ct_label\"\n"); ++ return -1; ++ } + } else if (matches(*argv, "indev") == 0) { + NEXT_ARG(); + if (check_ifname(*argv)) +@@ -1783,6 +1969,85 @@ static void flower_print_tcp_flags(const char *name, struct rtattr *flags_attr, + print_string(PRINT_ANY, name, namefrm, out); + } + ++static void flower_print_ct_state(struct rtattr *flags_attr, ++ struct rtattr *mask_attr) ++{ ++ SPRINT_BUF(out); ++ uint16_t state; ++ uint16_t state_mask; ++ size_t done = 0; ++ int i; ++ ++ if (!flags_attr) ++ return; ++ ++ state = rta_getattr_u16(flags_attr); ++ if (mask_attr) ++ state_mask = rta_getattr_u16(mask_attr); ++ else ++ state_mask = UINT16_MAX; ++ ++ for (i = 0; i < ARRAY_SIZE(flower_ct_states); i++) { ++ if (!(state_mask & flower_ct_states[i].flag)) ++ continue; ++ ++ if (state & flower_ct_states[i].flag) ++ done += sprintf(out + done, "+%s", ++ flower_ct_states[i].str); ++ else ++ done += sprintf(out + done, "-%s", ++ flower_ct_states[i].str); ++ } ++ ++ print_string(PRINT_ANY, "ct_state", "\n ct_state %s", out); ++} ++ ++static void flower_print_ct_label(struct rtattr *attr, ++ struct rtattr *mask_attr) ++{ ++ const unsigned char *str; ++ bool print_mask = false; ++ int data_len, i; ++ SPRINT_BUF(out); ++ char *p; ++ ++ if (!attr) ++ return; ++ ++ data_len = RTA_PAYLOAD(attr); ++ hexstring_n2a(RTA_DATA(attr), data_len, out, sizeof(out)); ++ p = out + data_len*2; ++ ++ data_len = RTA_PAYLOAD(attr); ++ str = RTA_DATA(mask_attr); ++ if (data_len != 16) ++ print_mask = true; ++ for (i = 0; !print_mask && i < data_len; i++) { ++ if (str[i] != 0xff) ++ print_mask = true; ++ } ++ if (print_mask) { ++ *p++ = '/'; ++ hexstring_n2a(RTA_DATA(mask_attr), data_len, p, ++ sizeof(out)-(p-out)); ++ p += data_len*2; ++ } ++ *p = '\0'; ++ ++ print_string(PRINT_ANY, "ct_label", "\n ct_label %s", out); ++} ++ ++static void flower_print_ct_zone(struct rtattr *attr, ++ struct rtattr *mask_attr) ++{ ++ print_masked_u16("ct_zone", attr, mask_attr); ++} ++ ++static void flower_print_ct_mark(struct rtattr *attr, ++ struct rtattr *mask_attr) ++{ ++ print_masked_u32("ct_mark", attr, mask_attr); ++} + + static void flower_print_key_id(const char *name, struct rtattr *attr) + { +@@ -2218,6 +2483,15 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, + tb[TCA_FLOWER_KEY_FLAGS], + tb[TCA_FLOWER_KEY_FLAGS_MASK]); + ++ flower_print_ct_state(tb[TCA_FLOWER_KEY_CT_STATE], ++ tb[TCA_FLOWER_KEY_CT_STATE_MASK]); ++ flower_print_ct_zone(tb[TCA_FLOWER_KEY_CT_ZONE], ++ tb[TCA_FLOWER_KEY_CT_ZONE_MASK]); ++ flower_print_ct_mark(tb[TCA_FLOWER_KEY_CT_MARK], ++ tb[TCA_FLOWER_KEY_CT_MARK_MASK]); ++ flower_print_ct_label(tb[TCA_FLOWER_KEY_CT_LABELS], ++ tb[TCA_FLOWER_KEY_CT_LABELS_MASK]); ++ + close_json_object(); + + if (tb[TCA_FLOWER_FLAGS]) { +-- +2.26.2 + diff --git a/SOURCES/0037-man-tc-ct.8-Add-manual-page-for-ct-tc-action.patch b/SOURCES/0037-man-tc-ct.8-Add-manual-page-for-ct-tc-action.patch new file mode 100644 index 0000000..5888574 --- /dev/null +++ b/SOURCES/0037-man-tc-ct.8-Add-manual-page-for-ct-tc-action.patch @@ -0,0 +1,154 @@ +From 7c371119412595ad2d063b91fdea616dcacb4eed Mon Sep 17 00:00:00 2001 +From: Andrea Claudi +Date: Tue, 9 Jun 2020 15:45:56 +0200 +Subject: [PATCH] man: tc-ct.8: Add manual page for ct tc action + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1844637 +Upstream Status: iproute2.git commit 924c43778a845 + +commit 924c43778a8453e2cd0fd1440b9224bed9c87c0d +Author: Paul Blakey +Date: Thu May 14 17:10:20 2020 +0300 + + man: tc-ct.8: Add manual page for ct tc action + + Signed-off-by: Paul Blakey + Signed-off-by: Stephen Hemminger +--- + man/man8/tc-ct.8 | 107 +++++++++++++++++++++++++++++++++++++++++++ + man/man8/tc-flower.8 | 6 +++ + 2 files changed, 113 insertions(+) + create mode 100644 man/man8/tc-ct.8 + +diff --git a/man/man8/tc-ct.8 b/man/man8/tc-ct.8 +new file mode 100644 +index 0000000000000..45d29320f1d01 +--- /dev/null ++++ b/man/man8/tc-ct.8 +@@ -0,0 +1,107 @@ ++.TH "ct action in tc" 8 "14 May 2020" "iproute2" "Linux" ++.SH NAME ++ct \- tc connection tracking action ++.SH SYNOPSIS ++.in +8 ++.ti -8 ++.BR "tc ... action ct commit [ force ] [ zone " ++.IR ZONE ++.BR "] [ mark " ++.IR MASKED_MARK ++.BR "] [ label " ++.IR MASKED_LABEL ++.BR "] [ nat " ++.IR NAT_SPEC ++.BR "]" ++ ++.ti -8 ++.BR "tc ... action ct [ nat ] [ zone " ++.IR ZONE ++.BR "]" ++ ++.ti -8 ++.BR "tc ... action ct clear" ++ ++.SH DESCRIPTION ++The ct action is a tc action for sending packets and interacting with the netfilter conntrack module. ++ ++It can (as shown in the synopsis, in order): ++ ++Send the packet to conntrack, and commit the connection, while configuring ++a 32bit mark, 128bit label, and src/dst nat. ++ ++Send the packet to conntrack, which will mark the packet with the connection's state and ++configured metadata (mark/label), and execute previous configured nat. ++ ++Clear the packet's of previous connection tracking state. ++ ++.SH OPTIONS ++.TP ++.BI zone " ZONE" ++Specify a conntrack zone number on which to send the packet to conntrack. ++.TP ++.BI mark " MASKED_MARK" ++Specify a masked 32bit mark to set for the connection (only valid with commit). ++.TP ++.BI label " MASKED_LABEL" ++Specify a masked 128bit label to set for the connection (only valid with commit). ++.TP ++.BI nat " NAT_SPEC" ++.BI Where " NAT_SPEC " ":= {src|dst} addr" " addr1" "[-" "addr2" "] [port " "port1" "[-" "port2" "]]" ++ ++Specify src/dst and range of nat to configure for the connection (only valid with commit). ++.RS ++.TP ++src/dst - configure src or dst nat ++.TP ++.BI "" "addr1" "/" "addr2" " - IPv4/IPv6 addresses" ++.TP ++.BI "" "port1" "/" "port2" " - Port numbers" ++.RE ++.TP ++.BI nat ++Restore any previous configured nat. ++.TP ++.BI clear ++Remove any conntrack state and metadata (mark/label) from the packet (must only option specified). ++.TP ++.BI force ++Forces conntrack direction for a previously commited connections, so that current direction will become the original direction (only valid with commit). ++ ++.SH EXAMPLES ++Example showing natted firewall in conntrack zone 2, and conntrack mark usage: ++.EX ++ ++#Add ingress qdisc on eth0 and eth1 interfaces ++.nf ++$ tc qdisc add dev eth0 handle ingress ++$ tc qdisc add dev eth1 handle ingress ++ ++#Setup filters on eth0, allowing opening new connections in zone 2, and doing src nat + mark for each new connection ++$ tc filter add dev eth0 ingress prio 1 chain 0 proto ip flower ip_proto tcp ct_state -trk \\ ++action ct zone 2 pipe action goto chain 2 ++$ tc filter add dev eth0 ingress prio 1 chain 2 proto ip flower ct_state +trk+new \\ ++action ct zone 2 commit mark 0xbb nat src addr 5.5.5.7 pipe action mirred egress redirect dev eth1 ++$ tc filter add dev eth0 ingress prio 1 chain 2 proto ip flower ct_zone 2 ct_mark 0xbb ct_state +trk+est \\ ++action ct nat pipe action mirred egress redirect dev eth1 ++ ++#Setup filters on eth1, allowing only established connections of zone 2 through, and reverse nat (dst nat in this case) ++$ tc filter add dev eth1 ingress prio 1 chain 0 proto ip flower ip_proto tcp ct_state -trk \\ ++action ct zone 2 pipe action goto chain 1 ++$ tc filter add dev eth1 ingress prio 1 chain 1 proto ip flower ct_zone 2 ct_mark 0xbb ct_state +trk+est \\ ++action ct nat pipe action mirred egress redirect dev eth0 ++.fi ++ ++.EE ++ ++.RE ++.SH SEE ALSO ++.BR tc (8), ++.BR tc-flower (8) ++.BR tc-mirred (8) ++.SH AUTHORS ++Paul Blakey ++ ++Marcelo Ricardo Leitner ++ ++Yossi Kuperman +diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8 +index 0f95f303f23b7..02a7256f36ebb 100644 +--- a/man/man8/tc-flower.8 ++++ b/man/man8/tc-flower.8 +@@ -1,5 +1,11 @@ + .TH "Flower filter in tc" 8 "22 Oct 2015" "iproute2" "Linux" + ++ "Usage: ct clear\n" ++ " ct commit [force] [zone ZONE] [mark MASKED_MARK] [label MASKED_LABEL] [nat NAT_SPEC] [OFFLOAD_POLICY]\n" ++ " ct [nat] [zone ZONE] [OFFLOAD_POLICY]\n" ++ "Where: ZONE is the conntrack zone table number\n" ++ " NAT_SPEC is {src|dst} addr addr1[-addr2] [port port1[-port2]]\n" ++ " OFFLOAD_POLICY is [policy_pkts PACKETS] [policy_timeout TIMEOUT]\n" + .SH NAME + flower \- flow based traffic control filter + .SH SYNOPSIS +-- +2.26.2 + diff --git a/SPECS/iproute.spec b/SPECS/iproute.spec index 43be57b..9c2fe0a 100644 --- a/SPECS/iproute.spec +++ b/SPECS/iproute.spec @@ -1,5 +1,5 @@ %define rpmversion 5.3.0 -%define specrelease 1%{?dist} +%define specrelease 5%{?dist} %define pkg_release %{specrelease}%{?buildid} Summary: Advanced IP routing and network device configuration tools @@ -12,6 +12,43 @@ Source0: http://kernel.org/pub/linux/utils/net/%{name}2/%{name}2-%{ve Source1: cbq-0000.example Source2: avpkt Source3: rt_dsfield.deprecated +Patch0: 0001-Update-kernel-headers.patch +Patch1: 0002-Update-kernel-headers.patch +Patch2: 0003-tc-implement-support-for-action-flags.patch +Patch3: 0004-man-rdma-statistic-Add-filter-description.patch +Patch4: 0005-man-rdma.8-Add-missing-resource-subcommand-descripti.patch +Patch5: 0006-ip-xfrm-Fix-help-messages.patch +Patch6: 0007-xfrm-not-try-to-delete-ipcomp-states-when-using-dele.patch +Patch7: 0008-man-ip.8-Add-missing-vrf-subcommand-description.patch +Patch8: 0009-nstat-print-useful-error-messages-in-abort-cases.patch +Patch9: 0010-ip-link-xstats-fix-TX-IGMP-reports-string.patch +Patch10: 0011-ip-fix-ip-route-show-json-output-for-multipath-nexth.patch +Patch11: 0012-man-bridge.8-fix-bridge-link-show-description.patch +Patch12: 0013-xfrm-also-check-for-ipv6-state-in-xfrm_state_keep.patch +Patch13: 0014-Update-kernel-headers-and-import-udp.h.patch +Patch14: 0015-ip-xfrm-add-espintcp-encapsulation.patch +Patch15: 0016-Update-kernel-headers-and-import-mptcp.h.patch +Patch16: 0017-add-support-for-mptcp-netlink-interface.patch +Patch17: 0018-Update-kernel-headers.patch +Patch18: 0019-Update-kernel-headers.patch +Patch19: 0020-ss-allow-dumping-MPTCP-subflow-information.patch +Patch20: 0021-man-mptcp-man-page.patch +Patch21: 0022-man-ip.8-add-reference-to-mptcp-man-page.patch +Patch22: 0023-Update-kernel-headers.patch +Patch23: 0024-iproute_lwtunnel-add-options-support-for-geneve-meta.patch +Patch24: 0025-iproute_lwtunnel-add-options-support-for-vxlan-metad.patch +Patch25: 0026-iproute_lwtunnel-add-options-support-for-erspan-meta.patch +Patch26: 0027-tc-m_tunnel_key-add-options-support-for-vxlan.patch +Patch27: 0028-tc-m_tunnel_key-add-options-support-for-erpsan.patch +Patch28: 0029-tc-f_flower-add-options-support-for-vxlan.patch +Patch29: 0030-tc-f_flower-add-options-support-for-erspan.patch +Patch30: 0031-devlink-Add-health-error-recovery-status-monitoring.patch +Patch31: 0032-ss-allow-dumping-kTLS-info.patch +Patch32: 0033-Import-tc_act-tc_ct.h-uapi-file.patch +Patch33: 0034-tc-add-NLA_F_NESTED-flag-to-all-actions-options-nest.patch +Patch34: 0035-tc-Introduce-tc-ct-action.patch +Patch35: 0036-tc-flower-Add-matching-on-conntrack-info.patch +Patch36: 0037-man-tc-ct.8-Add-manual-page-for-ct-tc-action.patch License: GPLv2+ and Public Domain BuildRequires: bison BuildRequires: elfutils-libelf-devel @@ -156,6 +193,51 @@ cat %{SOURCE3} >>%{buildroot}%{_sysconfdir}/iproute2/rt_dsfield %{_includedir}/iproute2/bpf_elf.h %changelog +* Mon Jun 29 2020 Andrea Claudi [5.3.0-5.el8] +- man: tc-ct.8: Add manual page for ct tc action (Andrea Claudi) [1844637] +- tc: flower: Add matching on conntrack info (Andrea Claudi) [1844637] +- tc: Introduce tc ct action (Andrea Claudi) [1844637] +- tc: add NLA_F_NESTED flag to all actions options nested block (Andrea Claudi) [1844637] +- Import tc_act/tc_ct.h uapi file (Andrea Claudi) [1844637] +- ss: allow dumping kTLS info (Andrea Claudi) [1812207] +- devlink: Add health error recovery status monitoring (Andrea Claudi) [1821039] + +* Fri Jun 05 2020 Andrea Claudi [5.3.0-4.el8] +- tc: f_flower: add options support for erspan (Andrea Claudi) [1830485] +- tc: f_flower: add options support for vxlan (Andrea Claudi) [1830485] +- tc: m_tunnel_key: add options support for erpsan (Andrea Claudi) [1830485] +- tc: m_tunnel_key: add options support for vxlan (Andrea Claudi) [1830485] +- iproute_lwtunnel: add options support for erspan metadata (Andrea Claudi) [1830485] +- iproute_lwtunnel: add options support for vxlan metadata (Andrea Claudi) [1830485] +- iproute_lwtunnel: add options support for geneve metadata (Andrea Claudi) [1830485] +- Update kernel headers (Andrea Claudi) [1830485] +- man: ip.8: add reference to mptcp man-page (Andrea Claudi) [1812207] +- man: mptcp man page (Andrea Claudi) [1812207] +- ss: allow dumping MPTCP subflow information (Andrea Claudi) [1812207] +- Update kernel headers (Andrea Claudi) [1812207] +- Update kernel headers (Andrea Claudi) [1812207] +- add support for mptcp netlink interface (Andrea Claudi) [1812207] +- Update kernel headers and import mptcp.h (Andrea Claudi) [1812207] +- ip: xfrm: add espintcp encapsulation (Andrea Claudi) [1844045] +- Update kernel headers and import udp.h (Andrea Claudi) [1844045] + +* Thu Apr 30 2020 Andrea Claudi [5.3.0-3.el8] +- xfrm: also check for ipv6 state in xfrm_state_keep (Andrea Claudi) [1828033] +- man: bridge.8: fix bridge link show description (Andrea Claudi) [1817571] +- ip: fix ip route show json output for multipath nexthops (Andrea Claudi) [1738633] +- ip link: xstats: fix TX IGMP reports string (Andrea Claudi) [1796041] +- nstat: print useful error messages in abort() cases (Andrea Claudi) [1824896] + +* Thu Apr 23 2020 Andrea Claudi [5.3.0-2.el8] +- man: ip.8: Add missing vrf subcommand description (Andrea Claudi) [1780010] +- xfrm: not try to delete ipcomp states when using deleteall (Andrea Claudi) [1808634] +- ip-xfrm: Fix help messages (Andrea Claudi) [1796045] +- man: rdma.8: Add missing resource subcommand description (Andrea Claudi) [1786576] +- man: rdma-statistic: Add filter description (Andrea Claudi) [1786565] +- tc: implement support for action flags (Andrea Claudi) [1770671] +- Update kernel headers (Andrea Claudi) [1770671] +- Update kernel headers (Andrea Claudi) [1770671] + * Tue Oct 15 2019 Andrea Claudi [5.3.0-1.el8] - New version 5.3.0 [1752857]