From: Martin <martin.vargh...@nokia.com> The Bareudp device provides a generic L3 encapsulation for tunnelling different protocols like MPLS,IP,NSH, etc. inside a UDP tunnel.
Signed-off-by: Martin Varghese <martin.vargh...@nokia.com> --- include/uapi/linux/if_link.h | 12 ++++ ip/Makefile | 2 +- ip/iplink_bareudp.c | 154 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 ip/iplink_bareudp.c diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index d36919f..a3a876d 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -578,6 +578,18 @@ enum ifla_geneve_df { GENEVE_DF_MAX = __GENEVE_DF_END - 1, }; +/* Bareudp section */ +enum { + IFLA_BAREUDP_UNSPEC, + IFLA_BAREUDP_PORT, + IFLA_BAREUDP_ETHERTYPE, + IFLA_BAREUDP_SRCPORT_MIN, + IFLA_BAREUDP_EXTMODE, + __IFLA_BAREUDP_MAX +}; + +#define IFLA_BAREUDP_MAX (__IFLA_BAREUDP_MAX - 1) + /* PPP section */ enum { IFLA_PPP_UNSPEC, diff --git a/ip/Makefile b/ip/Makefile index 5ab78d7..784d852 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 iplink_bareudp.o RTMONOBJ=rtmon.o diff --git a/ip/iplink_bareudp.c b/ip/iplink_bareudp.c new file mode 100644 index 0000000..479ad1c --- /dev/null +++ b/ip/iplink_bareudp.c @@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <stdio.h> + +#include "rt_names.h" +#include "utils.h" +#include "ip_common.h" + +#define BAREUDP_ATTRSET(attrs, type) (((attrs) & (1L << (type))) != 0) + +static void print_explain(FILE *f) +{ + fprintf(f, + "Usage: ........ bareudp dstport PORT\n" + " ethertype ETHERTYPE|PROTOCOL\n" + " [ext_mode]\n" + " [srcportmin SRCPORTMIN]\n" + "\n" + "Where: PORT := 0-65535\n" + " : ETHERTYPE|PROTOCOL := ip|mpls|0-65535\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) +{ + __u16 dstport = 0; + __u16 ethertype = 0; + __u16 srcportmin = 0; + bool extmode = 0; + __u64 attrs = 0; + + while (argc > 0) { + if (!matches(*argv, "dstport")) { + NEXT_ARG(); + check_duparg(&attrs, IFLA_BAREUDP_PORT, "dstport", + *argv); + if (get_u16(&dstport, *argv, 0)) + invarg("dstport", *argv); + } else if (!matches(*argv, "extmode")) { + check_duparg(&attrs, IFLA_BAREUDP_EXTMODE, + *argv, *argv); + extmode = true; + } else if (!matches(*argv, "ethertype")) { + NEXT_ARG(); + check_duparg(&attrs, IFLA_BAREUDP_ETHERTYPE, + *argv, *argv); + if (!matches(*argv, "mpls")) { + ethertype = 0x8847; + check_duparg(&attrs, IFLA_BAREUDP_EXTMODE, + *argv, *argv); + extmode = true; + } else if (!matches(*argv, "ip")) { + ethertype = 0x0800; + check_duparg(&attrs, IFLA_BAREUDP_EXTMODE, + *argv, *argv); + extmode = true; + } else { + if (get_u16(ðertype, *argv, 0)) + invarg("ethertype", *argv); + } + } else if (!matches(*argv, "srcportmin")) { + NEXT_ARG(); + check_duparg(&attrs, IFLA_BAREUDP_SRCPORT_MIN, + *argv, *argv); + if (get_u16(&srcportmin, *argv, 0)) + invarg("srcportmin", *argv); + + } else if (matches(*argv, "help") == 0) { + explain(); + return -1; + } else { + fprintf(stderr, "bareudp: unknown command \"%s\"?\n", *argv); + explain(); + return -1; + } + argc--, argv++; + } + + if (!dstport || !ethertype) { + fprintf(stderr, "bareudp : Missing mandatory params\n"); + return -1; + } + + if (dstport) + addattr16(n, 1024, IFLA_BAREUDP_PORT, htons(dstport)); + if (ethertype) + addattr16(n, 1024, IFLA_BAREUDP_ETHERTYPE, htons(ethertype)); + if (extmode) + addattr(n, 1024, IFLA_BAREUDP_EXTMODE); + if (srcportmin) + addattr16(n, 1024, IFLA_BAREUDP_PORT, srcportmin); + + 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, + "port", + "dstport %u ", + rta_getattr_be16(tb[IFLA_BAREUDP_PORT])); + + if (tb[IFLA_BAREUDP_ETHERTYPE]) + print_uint(PRINT_ANY, + "port", + "dstport %u ", + rta_getattr_be16(tb[IFLA_BAREUDP_ETHERTYPE])); + if (tb[IFLA_BAREUDP_SRCPORT_MIN]) + print_uint(PRINT_ANY, + "port", + "dstport %u ", + rta_getattr_u16(tb[IFLA_BAREUDP_SRCPORT_MIN])); + + if (tb[IFLA_BAREUDP_EXTMODE]) { + print_bool(PRINT_ANY, "extmode", "extmode ", true); + return; + } +} + +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, +}; -- 1.8.3.1