From: Eyal Birger Date: Mon, 3 Oct 2022 09:12:12 +0000 (+0300) Subject: ip: xfrm: support adding xfrm metadata as lwtunnel info in routes X-Git-Tag: v6.1.0~33^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=75776cf2472d14f89eabe51b9253f5ecfb84f462;p=thirdparty%2Fiproute2.git ip: xfrm: support adding xfrm metadata as lwtunnel info in routes Support for xfrm metadata as lwtunnel metadata was added in kernel commit 2c2493b9da91 ("xfrm: lwtunnel: add lwtunnel support for xfrm interfaces in collect_md mode") This commit adds the respective support in lwt routes. Example use (consider ipsec1 as an xfrm interface in "external" mode): ip route add 10.1.0.0/24 dev ipsec1 encap xfrm if_id 1 Or in the context of vrf, one can also specify the "link" property: ip route add 10.1.0.0/24 dev ipsec1 encap xfrm if_id 1 link_dev eth15 Signed-off-by: Eyal Birger Reviewed-by: Nicolas Dichtel Signed-off-by: David Ahern --- diff --git a/ip/iproute.c b/ip/iproute.c index 8b2d1fbe9..b4b9d1b20 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -102,8 +102,8 @@ static void usage(void) "TIME := NUMBER[s|ms]\n" "BOOL := [1|0]\n" "FEATURES := ecn\n" - "ENCAPTYPE := [ mpls | ip | ip6 | seg6 | seg6local | rpl | ioam6 ]\n" - "ENCAPHDR := [ MPLSLABEL | SEG6HDR | SEG6LOCAL | IOAM6HDR ]\n" + "ENCAPTYPE := [ mpls | ip | ip6 | seg6 | seg6local | rpl | ioam6 | xfrm ]\n" + "ENCAPHDR := [ MPLSLABEL | SEG6HDR | SEG6LOCAL | IOAM6HDR | XFRMINFO ]\n" "SEG6HDR := [ mode SEGMODE ] segs ADDR1,ADDRi,ADDRn [hmac HMACKEYID] [cleanup]\n" "SEGMODE := [ encap | encap.red | inline | l2encap | l2encap.red ]\n" "SEG6LOCAL := action ACTION [ OPTIONS ] [ count ]\n" @@ -116,6 +116,7 @@ static void usage(void) "FLAVORS := { FLAVOR[,FLAVOR] }\n" "FLAVOR := { psp | usp | usd | next-csid }\n" "IOAM6HDR := trace prealloc type IOAM6_TRACE_TYPE ns IOAM6_NAMESPACE size IOAM6_TRACE_SIZE\n" + "XFRMINFO := if_id IF_ID [ link_dev LINK ]\n" "ROUTE_GET_FLAGS := [ fibmatch ]\n"); exit(-1); } diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c index 86128c9b6..bf4468b6d 100644 --- a/ip/iproute_lwtunnel.c +++ b/ip/iproute_lwtunnel.c @@ -58,6 +58,8 @@ static const char *format_encap_type(int type) return "rpl"; case LWTUNNEL_ENCAP_IOAM6: return "ioam6"; + case LWTUNNEL_ENCAP_XFRM: + return "xfrm"; default: return "unknown"; } @@ -96,6 +98,8 @@ static int read_encap_type(const char *name) return LWTUNNEL_ENCAP_RPL; else if (strcmp(name, "ioam6") == 0) return LWTUNNEL_ENCAP_IOAM6; + else if (strcmp(name, "xfrm") == 0) + return LWTUNNEL_ENCAP_XFRM; else if (strcmp(name, "help") == 0) encap_type_usage(); @@ -814,6 +818,24 @@ static void print_encap_bpf(FILE *fp, struct rtattr *encap) " %u ", rta_getattr_u32(tb[LWT_BPF_XMIT_HEADROOM])); } +static void print_encap_xfrm(FILE *fp, struct rtattr *encap) +{ + struct rtattr *tb[LWT_XFRM_MAX+1]; + + parse_rtattr_nested(tb, LWT_XFRM_MAX, encap); + + if (tb[LWT_XFRM_IF_ID]) + print_uint(PRINT_ANY, "if_id", "if_id %lu ", + rta_getattr_u32(tb[LWT_XFRM_IF_ID])); + + if (tb[LWT_XFRM_LINK]) { + int link = rta_getattr_u32(tb[LWT_XFRM_LINK]); + + print_string(PRINT_ANY, "link_dev", "link_dev %s ", + ll_index_to_name(link)); + } +} + void lwt_print_encap(FILE *fp, struct rtattr *encap_type, struct rtattr *encap) { @@ -854,6 +876,9 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type, case LWTUNNEL_ENCAP_IOAM6: print_encap_ioam6(fp, encap); break; + case LWTUNNEL_ENCAP_XFRM: + print_encap_xfrm(fp, encap); + break; } } @@ -2129,6 +2154,61 @@ static int parse_encap_bpf(struct rtattr *rta, size_t len, int *argcp, return 0; } +static void lwt_xfrm_usage(void) +{ + fprintf(stderr, "Usage: ip route ... encap xfrm if_id IF_ID [ link_dev LINK ]\n"); + exit(-1); +} + +static int parse_encap_xfrm(struct rtattr *rta, size_t len, + int *argcp, char ***argvp) +{ + int if_id_ok = 0, link_ok = 0; + char **argv = *argvp; + int argc = *argcp; + int ret = 0; + + while (argc > 0) { + if (!strcmp(*argv, "if_id")) { + __u32 if_id; + + NEXT_ARG(); + if (if_id_ok++) + duparg2("if_id", *argv); + if (get_u32(&if_id, *argv, 0) || if_id == 0) + invarg("\"if_id\" value is invalid\n", *argv); + ret = rta_addattr32(rta, len, LWT_XFRM_IF_ID, if_id); + } else if (!strcmp(*argv, "link_dev")) { + int link; + + NEXT_ARG(); + if (link_ok++) + duparg2("link_dev", *argv); + link = ll_name_to_index(*argv); + if (!link) + exit(nodev(*argv)); + ret = rta_addattr32(rta, len, LWT_XFRM_LINK, link); + } else if (!strcmp(*argv, "help")) { + lwt_xfrm_usage(); + } + if (ret) + break; + argc--; argv++; + } + + if (!if_id_ok) + lwt_xfrm_usage(); + + /* argv is currently the first unparsed argument, + * but the lwt_parse_encap() caller will move to the next, + * so step back + */ + *argcp = argc + 1; + *argvp = argv - 1; + + return ret; +} + int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp, int encap_attr, int encap_type_attr) { @@ -2180,6 +2260,9 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp, case LWTUNNEL_ENCAP_IOAM6: ret = parse_encap_ioam6(rta, len, &argc, &argv); break; + case LWTUNNEL_ENCAP_XFRM: + ret = parse_encap_xfrm(rta, len, &argc, &argv); + break; default: fprintf(stderr, "Error: unsupported encap type\n"); break; diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in index bd38b7d86..194dc780d 100644 --- a/man/man8/ip-route.8.in +++ b/man/man8/ip-route.8.in @@ -738,6 +738,9 @@ is a string specifying the supported encapsulation type. Namely: .sp .BI ioam6 - encapsulation type IPv6 IOAM +.sp +.BI xfrm +- encapsulation type XFRM .in -8 .I ENCAPHDR @@ -1024,6 +1027,14 @@ mode. .B size .I IOAM6_TRACE_SIZE - Size, in octets, of the pre-allocated trace data block. +.in -2 + +.B xfrm +.in +2 +.B if_id +.I IF_ID +.B " [ link_dev +.IR LINK_DEV " ] " .in -4 .in -8