diff --git a/ip/Makefile b/ip/Makefile index 8735b8e4..4cad619c 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 ipmptcp.o + ipnexthop.o ipmptcp.o iplink_bareudp.o RTMONOBJ=rtmon.o diff --git a/ip/iplink.c b/ip/iplink.c index 47f73988..7d4b244d 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -124,7 +124,7 @@ void iplink_usage(void) " bridge | bond | team | ipoib | ip6tnl | ipip | sit | vxlan |\n" " gre | gretap | erspan | ip6gre | ip6gretap | ip6erspan |\n" " vti | nlmon | team_slave | bond_slave | bridge_slave |\n" - " ipvlan | ipvtap | geneve | vrf | macsec | netdevsim | rmnet |\n" + " ipvlan | ipvtap | geneve | bareudp | vrf | macsec | netdevsim | rmnet |\n" " xfrm }\n"); } exit(-1); diff --git a/ip/iplink_bareudp.c b/ip/iplink_bareudp.c new file mode 100644 index 00000000..885e1110 --- /dev/null +++ b/ip/iplink_bareudp.c @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include + +#include "libnetlink.h" +#include "linux/if_ether.h" +#include "linux/if_link.h" +#include "linux/netlink.h" +#include "linux/rtnetlink.h" +#include "rt_names.h" +#include "utils.h" +#include "ip_common.h" +#include "json_print.h" + +#define BAREUDP_ATTRSET(attrs, type) (((attrs) & (1L << (type))) != 0) + +static void print_explain(FILE *f) +{ + fprintf(f, + "Usage: ... bareudp dstport PORT\n" + " ethertype PROTO\n" + " [ srcportmin PORT ]\n" + " [ [no]multiproto ]\n" + "\n" + "Where: PORT := 0-65535\n" + " PROTO := NUMBER | ip | mpls\n" + " SRCPORTMIN := 0-65535\n" + ); +} + +static void explain(void) +{ + print_explain(stderr); +} + +static void check_duparg(__u64 *attrs, int type, const char *key, + const char *argv) +{ + if (!BAREUDP_ATTRSET(*attrs, type)) { + *attrs |= (1L << type); + return; + } + duparg2(key, argv); +} + +static int bareudp_parse_opt(struct link_util *lu, int argc, char **argv, + struct nlmsghdr *n) +{ + bool multiproto = false; + __u16 srcportmin = 0; + __be16 ethertype = 0; + __be16 dstport = 0; + __u64 attrs = 0; + + while (argc > 0) { + if (matches(*argv, "dstport") == 0) { + NEXT_ARG(); + check_duparg(&attrs, IFLA_BAREUDP_PORT, "dstport", + *argv); + if (get_be16(&dstport, *argv, 0)) + invarg("dstport", *argv); + } else if (matches(*argv, "ethertype") == 0) { + NEXT_ARG(); + check_duparg(&attrs, IFLA_BAREUDP_ETHERTYPE, + "ethertype", *argv); + if (ll_proto_a2n(ðertype, *argv)) + invarg("ethertype", *argv); + } else if (matches(*argv, "srcportmin") == 0) { + NEXT_ARG(); + check_duparg(&attrs, IFLA_BAREUDP_SRCPORT_MIN, + "srcportmin", *argv); + if (get_u16(&srcportmin, *argv, 0)) + invarg("srcportmin", *argv); + } else if (matches(*argv, "multiproto") == 0) { + check_duparg(&attrs, IFLA_BAREUDP_MULTIPROTO_MODE, + *argv, *argv); + multiproto = true; + } else if (matches(*argv, "nomultiproto") == 0) { + check_duparg(&attrs, IFLA_BAREUDP_MULTIPROTO_MODE, + *argv, *argv); + multiproto = false; + } else if (matches(*argv, "help") == 0) { + explain(); + return -1; + } else { + fprintf(stderr, "bareudp: unknown command \"%s\"?\n", + *argv); + explain(); + return -1; + } + argc--, argv++; + } + + if (!BAREUDP_ATTRSET(attrs, IFLA_BAREUDP_PORT)) + missarg("dstport"); + if (!BAREUDP_ATTRSET(attrs, IFLA_BAREUDP_ETHERTYPE)) + missarg("ethertype"); + + addattr16(n, 1024, IFLA_BAREUDP_PORT, dstport); + addattr16(n, 1024, IFLA_BAREUDP_ETHERTYPE, ethertype); + if (BAREUDP_ATTRSET(attrs, IFLA_BAREUDP_SRCPORT_MIN)) + addattr16(n, 1024, IFLA_BAREUDP_SRCPORT_MIN, srcportmin); + if (multiproto) + addattr(n, 1024, IFLA_BAREUDP_MULTIPROTO_MODE); + + return 0; +} + +static void bareudp_print_opt(struct link_util *lu, FILE *f, + struct rtattr *tb[]) +{ + if (!tb) + return; + + if (tb[IFLA_BAREUDP_PORT]) + print_uint(PRINT_ANY, "dstport", "dstport %u ", + rta_getattr_be16(tb[IFLA_BAREUDP_PORT])); + + if (tb[IFLA_BAREUDP_ETHERTYPE]) { + struct rtattr *attr = tb[IFLA_BAREUDP_ETHERTYPE]; + SPRINT_BUF(ethertype); + + print_string(PRINT_ANY, "ethertype", "ethertype %s ", + ll_proto_n2a(rta_getattr_u16(attr), + ethertype, sizeof(ethertype))); + } + + if (tb[IFLA_BAREUDP_SRCPORT_MIN]) + print_uint(PRINT_ANY, "srcportmin", "srcportmin %u ", + rta_getattr_u16(tb[IFLA_BAREUDP_SRCPORT_MIN])); + + if (tb[IFLA_BAREUDP_MULTIPROTO_MODE]) + print_bool(PRINT_ANY, "multiproto", "multiproto ", true); + else + print_bool(PRINT_ANY, "multiproto", "nomultiproto ", false); +} + +static void bareudp_print_help(struct link_util *lu, int argc, char **argv, + FILE *f) +{ + print_explain(f); +} + +struct link_util bareudp_link_util = { + .id = "bareudp", + .maxattr = IFLA_BAREUDP_MAX, + .parse_opt = bareudp_parse_opt, + .print_opt = bareudp_print_opt, + .print_help = bareudp_print_help, +}; diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in index e8a25451..c6bd2c53 100644 --- a/man/man8/ip-link.8.in +++ b/man/man8/ip-link.8.in @@ -223,6 +223,7 @@ ip-link \- network device configuration .BR ipvtap " |" .BR lowpan " |" .BR geneve " |" +.BR bareudp " |" .BR vrf " |" .BR macsec " |" .BR netdevsim " |" @@ -356,6 +357,9 @@ Link types: .BR geneve - GEneric NEtwork Virtualization Encapsulation .sp +.BR bareudp +- Bare UDP L3 encapsulation support +.sp .BR macsec - Interface for IEEE 802.1AE MAC Security (MACsec) .sp @@ -1293,6 +1297,46 @@ options. .in -8 +.TP +Bareudp Type Support +For a link of type +.I Bareudp +the following additional arguments are supported: + +.BI "ip link add " DEVICE +.BI type " bareudp " dstport " PORT " ethertype " ETHERTYPE" +[ +.BI srcportmin " SRCPORTMIN " +] [ +.RB [ no ] multiproto +] + +.in +8 +.sp +.BI dstport " PORT" +- specifies the destination port for the UDP tunnel. + +.sp +.BI ethertype " ETHERTYPE" +- specifies the ethertype of the L3 protocol being tunnelled. + +.sp +.BI srcportmin " SRCPORTMIN" +- selects the lowest value of the UDP tunnel source port range. + +.sp +.RB [ no ] multiproto +- activates support for protocols similar to the one +.RB "specified by " ethertype . +When +.I ETHERTYPE +is "mpls_uc" (that is, unicast MPLS), this allows the tunnel to also handle +multicast MPLS. +When +.I ETHERTYPE +is "ipv4", this allows the tunnel to also handle IPv6. This option is disabled +by default. + .TP MACVLAN and MACVTAP Type Support For a link of type