* [PATCH iproute2-next 0/4] iproute: mptcp support
@ 2020-04-23 13:37 Paolo Abeni
2020-04-23 13:37 ` [PATCH iproute2-next 1/4] uapi: update linux/mptcp.h Paolo Abeni
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Paolo Abeni @ 2020-04-23 13:37 UTC (permalink / raw)
To: stephen, netdev; +Cc: dcaratti
This introduces support for the MPTCP PM netlink interface, allowing admins
to configure several aspects of the MPTCP path manager. The subcommand is
documented with a newly added man-page.
This series also includes support for MPTCP subflow diag.
Davide Caratti (1):
ss: allow dumping MPTCP subflow information
Paolo Abeni (3):
uapi: update linux/mptcp.h
add support for mptcp netlink interface
man: mptcp man page
include/uapi/linux/mptcp.h | 89 ++++++++
ip/Makefile | 2 +-
ip/ip.c | 3 +-
ip/ip_common.h | 1 +
ip/ipmptcp.c | 436 +++++++++++++++++++++++++++++++++++++
man/man8/ip-mptcp.8 | 142 ++++++++++++
man/man8/ss.8 | 5 +
misc/ss.c | 62 ++++++
8 files changed, 738 insertions(+), 2 deletions(-)
create mode 100644 include/uapi/linux/mptcp.h
create mode 100644 ip/ipmptcp.c
create mode 100644 man/man8/ip-mptcp.8
--
2.21.1
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH iproute2-next 1/4] uapi: update linux/mptcp.h 2020-04-23 13:37 [PATCH iproute2-next 0/4] iproute: mptcp support Paolo Abeni @ 2020-04-23 13:37 ` Paolo Abeni 2020-04-23 13:37 ` [PATCH iproute2-next 2/4] add support for mptcp netlink interface Paolo Abeni ` (5 subsequent siblings) 6 siblings, 0 replies; 9+ messages in thread From: Paolo Abeni @ 2020-04-23 13:37 UTC (permalink / raw) To: stephen, netdev; +Cc: dcaratti Signed-off-by: Paolo Abeni <pabeni@redhat.com> --- include/uapi/linux/mptcp.h | 89 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 include/uapi/linux/mptcp.h diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h new file mode 100644 index 00000000..5f2c7708 --- /dev/null +++ b/include/uapi/linux/mptcp.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +#ifndef _UAPI_MPTCP_H +#define _UAPI_MPTCP_H + +#include <linux/const.h> +#include <linux/types.h> + +#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 /* _UAPI_MPTCP_H */ -- 2.21.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH iproute2-next 2/4] add support for mptcp netlink interface 2020-04-23 13:37 [PATCH iproute2-next 0/4] iproute: mptcp support Paolo Abeni 2020-04-23 13:37 ` [PATCH iproute2-next 1/4] uapi: update linux/mptcp.h Paolo Abeni @ 2020-04-23 13:37 ` Paolo Abeni 2020-04-23 13:37 ` [PATCH iproute2-next 3/4] ss: allow dumping MPTCP subflow information Paolo Abeni ` (4 subsequent siblings) 6 siblings, 0 replies; 9+ messages in thread From: Paolo Abeni @ 2020-04-23 13:37 UTC (permalink / raw) To: stephen, netdev; +Cc: dcaratti 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 <pabeni@redhat.com> --- 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 5ab78d7d..8735b8e4 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 90392c2a..4249df03 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 879287e3..d604f755 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -83,6 +83,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 00000000..bc12418b --- /dev/null +++ b/ip/ipmptcp.c @@ -0,0 +1,436 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <stdio.h> +#include <string.h> +#include <rt_names.h> +#include <errno.h> + +#include <linux/genetlink.h> +#include <linux/mptcp.h> + +#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.21.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH iproute2-next 3/4] ss: allow dumping MPTCP subflow information 2020-04-23 13:37 [PATCH iproute2-next 0/4] iproute: mptcp support Paolo Abeni 2020-04-23 13:37 ` [PATCH iproute2-next 1/4] uapi: update linux/mptcp.h Paolo Abeni 2020-04-23 13:37 ` [PATCH iproute2-next 2/4] add support for mptcp netlink interface Paolo Abeni @ 2020-04-23 13:37 ` Paolo Abeni 2020-04-23 13:37 ` [PATCH iproute2-next 4/4] man: mptcp man page Paolo Abeni ` (3 subsequent siblings) 6 siblings, 0 replies; 9+ messages in thread From: Paolo Abeni @ 2020-04-23 13:37 UTC (permalink / raw) To: stephen, netdev; +Cc: dcaratti From: Davide Caratti <dcaratti@redhat.com> [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 <dcaratti@redhat.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com> --- man/man8/ss.8 | 5 +++++ misc/ss.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/man/man8/ss.8 b/man/man8/ss.8 index 023d771b..c80853f9 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:<rcv_space> a helper variable for TCP internal auto tuning socket receive buffer +.P +.TP +.B tcp-ulp-mptcp flags:[MmBbJjecv] token:<rem_token(rem_id)/loc_token(loc_id)> seq:<sn> sfseq:<ssn> ssnoff:<off> maplen:<maplen> +MPTCP subflow information +.P .RE .TP .B \-\-tos diff --git a/misc/ss.c b/misc/ss.c index 3ef151fb..ee840149 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -53,6 +53,7 @@ #include <linux/tipc_netlink.h> #include <linux/tipc_sockets_diag.h> #include <linux/tls.h> +#include <linux/mptcp.h> /* AF_VSOCK/PF_VSOCK is only provided since glibc 2.18 */ #ifndef PF_VSOCK @@ -2836,6 +2837,59 @@ static void tcp_tls_conf(const char *name, struct rtattr *attr) } } +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, @@ -3012,6 +3066,14 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r, 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 }; + + parse_rtattr_nested(sfinfo, MPTCP_SUBFLOW_ATTR_MAX, + ulpinfo[INET_ULP_INFO_MPTCP]); + mptcp_subflow_info(sfinfo); + } } } -- 2.21.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH iproute2-next 4/4] man: mptcp man page 2020-04-23 13:37 [PATCH iproute2-next 0/4] iproute: mptcp support Paolo Abeni ` (2 preceding siblings ...) 2020-04-23 13:37 ` [PATCH iproute2-next 3/4] ss: allow dumping MPTCP subflow information Paolo Abeni @ 2020-04-23 13:37 ` Paolo Abeni 2020-04-27 14:04 ` [PATCH iproute2-next 0/4] iproute: mptcp support Paolo Abeni ` (2 subsequent siblings) 6 siblings, 0 replies; 9+ messages in thread From: Paolo Abeni @ 2020-04-23 13:37 UTC (permalink / raw) To: stephen, netdev; +Cc: dcaratti describe the mptcp subcommands implemented so far. Signed-off-by: Paolo Abeni <pabeni@redhat.com> --- 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 00000000..f6457e97 --- /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 <pabeni@redhat.com> -- 2.21.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH iproute2-next 0/4] iproute: mptcp support 2020-04-23 13:37 [PATCH iproute2-next 0/4] iproute: mptcp support Paolo Abeni ` (3 preceding siblings ...) 2020-04-23 13:37 ` [PATCH iproute2-next 4/4] man: mptcp man page Paolo Abeni @ 2020-04-27 14:04 ` Paolo Abeni 2020-04-27 14:35 ` David Ahern 2020-04-28 16:47 ` Andrea Claudi 2020-04-29 16:51 ` David Ahern 6 siblings, 1 reply; 9+ messages in thread From: Paolo Abeni @ 2020-04-27 14:04 UTC (permalink / raw) To: David Ahern; +Cc: dcaratti, stephen, netdev Hi David, On Thu, 2020-04-23 at 15:37 +0200, Paolo Abeni wrote: > This introduces support for the MPTCP PM netlink interface, allowing admins > to configure several aspects of the MPTCP path manager. The subcommand is > documented with a newly added man-page. > > This series also includes support for MPTCP subflow diag. > > Davide Caratti (1): > ss: allow dumping MPTCP subflow information > > Paolo Abeni (3): > uapi: update linux/mptcp.h > add support for mptcp netlink interface > man: mptcp man page Due to PEBKAC, I did not include your email address in the recipient list. Do you prefer I'll re-submit this including you, or are you still fine with it? Thank you! Paolo ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH iproute2-next 0/4] iproute: mptcp support 2020-04-27 14:04 ` [PATCH iproute2-next 0/4] iproute: mptcp support Paolo Abeni @ 2020-04-27 14:35 ` David Ahern 0 siblings, 0 replies; 9+ messages in thread From: David Ahern @ 2020-04-27 14:35 UTC (permalink / raw) To: Paolo Abeni; +Cc: dcaratti, stephen, netdev On 4/27/20 8:04 AM, Paolo Abeni wrote: > Due to PEBKAC, I did not include your email address in the recipient > list. Do you prefer I'll re-submit this including you, or are you still > fine with it? Generically, sending to me directly makes me aware of patches in a timely manner. Sending only to netdev means I get to it as time arises to scan emails to that list. In this case, I saw them over the weekend. Just need time for an in-depth look at the change. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH iproute2-next 0/4] iproute: mptcp support 2020-04-23 13:37 [PATCH iproute2-next 0/4] iproute: mptcp support Paolo Abeni ` (4 preceding siblings ...) 2020-04-27 14:04 ` [PATCH iproute2-next 0/4] iproute: mptcp support Paolo Abeni @ 2020-04-28 16:47 ` Andrea Claudi 2020-04-29 16:51 ` David Ahern 6 siblings, 0 replies; 9+ messages in thread From: Andrea Claudi @ 2020-04-28 16:47 UTC (permalink / raw) To: Paolo Abeni; +Cc: Stephen Hemminger, linux-netdev, Davide Caratti, David Ahern On Thu, Apr 23, 2020 at 3:39 PM Paolo Abeni <pabeni@redhat.com> wrote: > > This introduces support for the MPTCP PM netlink interface, allowing admins > to configure several aspects of the MPTCP path manager. The subcommand is > documented with a newly added man-page. > > This series also includes support for MPTCP subflow diag. > > Davide Caratti (1): > ss: allow dumping MPTCP subflow information > > Paolo Abeni (3): > uapi: update linux/mptcp.h > add support for mptcp netlink interface > man: mptcp man page > > include/uapi/linux/mptcp.h | 89 ++++++++ > ip/Makefile | 2 +- > ip/ip.c | 3 +- > ip/ip_common.h | 1 + > ip/ipmptcp.c | 436 +++++++++++++++++++++++++++++++++++++ > man/man8/ip-mptcp.8 | 142 ++++++++++++ > man/man8/ss.8 | 5 + > misc/ss.c | 62 ++++++ > 8 files changed, 738 insertions(+), 2 deletions(-) > create mode 100644 include/uapi/linux/mptcp.h > create mode 100644 ip/ipmptcp.c > create mode 100644 man/man8/ip-mptcp.8 > > -- > 2.21.1 > Acked-by: Andrea Claudi <aclaudi@redhat.com> ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH iproute2-next 0/4] iproute: mptcp support 2020-04-23 13:37 [PATCH iproute2-next 0/4] iproute: mptcp support Paolo Abeni ` (5 preceding siblings ...) 2020-04-28 16:47 ` Andrea Claudi @ 2020-04-29 16:51 ` David Ahern 6 siblings, 0 replies; 9+ messages in thread From: David Ahern @ 2020-04-29 16:51 UTC (permalink / raw) To: Paolo Abeni, stephen, netdev; +Cc: dcaratti On 4/23/20 7:37 AM, Paolo Abeni wrote: > This introduces support for the MPTCP PM netlink interface, allowing admins > to configure several aspects of the MPTCP path manager. The subcommand is > documented with a newly added man-page. > > This series also includes support for MPTCP subflow diag. > > Davide Caratti (1): > ss: allow dumping MPTCP subflow information > > Paolo Abeni (3): > uapi: update linux/mptcp.h > add support for mptcp netlink interface > man: mptcp man page > applied to iproute2-next. Thanks please send an update for man/man8/ip.8 ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2020-04-29 16:52 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-04-23 13:37 [PATCH iproute2-next 0/4] iproute: mptcp support Paolo Abeni 2020-04-23 13:37 ` [PATCH iproute2-next 1/4] uapi: update linux/mptcp.h Paolo Abeni 2020-04-23 13:37 ` [PATCH iproute2-next 2/4] add support for mptcp netlink interface Paolo Abeni 2020-04-23 13:37 ` [PATCH iproute2-next 3/4] ss: allow dumping MPTCP subflow information Paolo Abeni 2020-04-23 13:37 ` [PATCH iproute2-next 4/4] man: mptcp man page Paolo Abeni 2020-04-27 14:04 ` [PATCH iproute2-next 0/4] iproute: mptcp support Paolo Abeni 2020-04-27 14:35 ` David Ahern 2020-04-28 16:47 ` Andrea Claudi 2020-04-29 16:51 ` David Ahern
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).