Message ID | 20210724172108.26524-3-justin.iurman@uliege.be (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | David Ahern |
Headers | show |
Series | Provide support for IOAM | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Not a local patch |
> This patch provides a new encap type for routes to insert an IOAM pre-allocated > trace: > > $ ip -6 ro ad fc00::1/128 encap ioam6 trace type 0x800000 ns 1 size 12 dev eth0 > > where: > - "trace" may appear as useless but just anticipates for future implementations > of other ioam option types. > - "type" is a bitfield (=u32) defining the IOAM pre-allocated trace type (see > the corresponding uapi). > - "ns" is an IOAM namespace ID attached to the pre-allocated trace. > - "size" is the trace pre-allocated size in bytes; must be a 4-octet multiple; > limited size (see IOAM6_TRACE_DATA_SIZE_MAX). > > Signed-off-by: Justin Iurman <justin.iurman@uliege.be> > --- > include/uapi/linux/ioam6.h | 133 ++++++++++++++++++++++++++++ > include/uapi/linux/ioam6_iptunnel.h | 20 +++++ > include/uapi/linux/lwtunnel.h | 1 + > ip/iproute.c | 5 +- > ip/iproute_lwtunnel.c | 121 +++++++++++++++++++++++++ > 5 files changed, 278 insertions(+), 2 deletions(-) > create mode 100644 include/uapi/linux/ioam6.h > create mode 100644 include/uapi/linux/ioam6_iptunnel.h > > diff --git a/include/uapi/linux/ioam6.h b/include/uapi/linux/ioam6.h > new file mode 100644 > index 00000000..0a2cc17d > --- /dev/null > +++ b/include/uapi/linux/ioam6.h > @@ -0,0 +1,133 @@ > +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ > +/* > + * IPv6 IOAM implementation > + * > + * Author: > + * Justin Iurman <justin.iurman@uliege.be> > + */ > + > +#ifndef _UAPI_LINUX_IOAM6_H > +#define _UAPI_LINUX_IOAM6_H > + > +#include <asm/byteorder.h> > +#include <linux/types.h> > + > +#define IOAM6_U16_UNAVAILABLE U16_MAX > +#define IOAM6_U32_UNAVAILABLE U32_MAX > +#define IOAM6_U64_UNAVAILABLE U64_MAX > + > +#define IOAM6_DEFAULT_ID (IOAM6_U32_UNAVAILABLE >> 8) > +#define IOAM6_DEFAULT_ID_WIDE (IOAM6_U64_UNAVAILABLE >> 8) > +#define IOAM6_DEFAULT_IF_ID IOAM6_U16_UNAVAILABLE > +#define IOAM6_DEFAULT_IF_ID_WIDE IOAM6_U32_UNAVAILABLE > + > +/* > + * IPv6 IOAM Option Header > + */ > +struct ioam6_hdr { > + __u8 opt_type; > + __u8 opt_len; > + __u8 :8; /* reserved */ > +#define IOAM6_TYPE_PREALLOC 0 > + __u8 type; > +} __attribute__((__packed__)); > + > +/* > + * IOAM Trace Header > + */ > +struct ioam6_trace_hdr { > + __be16 namespace_id; > + > +#if defined(__LITTLE_ENDIAN_BITFIELD) > + > + __u8 :1, /* unused */ > + :1, /* unused */ > + overflow:1, > + nodelen:5; > + > + __u8 remlen:7, > + :1; /* unused */ > + > + union { > + __be32 type_be32; > + > + struct { > + __u32 bit7:1, > + bit6:1, > + bit5:1, > + bit4:1, > + bit3:1, > + bit2:1, > + bit1:1, > + bit0:1, > + bit15:1, /* unused */ > + bit14:1, /* unused */ > + bit13:1, /* unused */ > + bit12:1, /* unused */ > + bit11:1, > + bit10:1, > + bit9:1, > + bit8:1, > + bit23:1, /* reserved */ > + bit22:1, > + bit21:1, /* unused */ > + bit20:1, /* unused */ > + bit19:1, /* unused */ > + bit18:1, /* unused */ > + bit17:1, /* unused */ > + bit16:1, /* unused */ > + :8; /* reserved */ > + } type; > + }; > + > +#elif defined(__BIG_ENDIAN_BITFIELD) > + > + __u8 nodelen:5, > + overflow:1, > + :1, /* unused */ > + :1; /* unused */ > + > + __u8 :1, /* unused */ > + remlen:7; > + > + union { > + __be32 type_be32; > + > + struct { > + __u32 bit0:1, > + bit1:1, > + bit2:1, > + bit3:1, > + bit4:1, > + bit5:1, > + bit6:1, > + bit7:1, > + bit8:1, > + bit9:1, > + bit10:1, > + bit11:1, > + bit12:1, /* unused */ > + bit13:1, /* unused */ > + bit14:1, /* unused */ > + bit15:1, /* unused */ > + bit16:1, /* unused */ > + bit17:1, /* unused */ > + bit18:1, /* unused */ > + bit19:1, /* unused */ > + bit20:1, /* unused */ > + bit21:1, /* unused */ > + bit22:1, > + bit23:1, /* reserved */ > + :8; /* reserved */ > + } type; > + }; > + > +#else > +#error "Please fix <asm/byteorder.h>" > +#endif > + > +#define IOAM6_TRACE_DATA_SIZE_MAX 244 > + __u8 data[0]; > +} __attribute__((__packed__)); > + > +#endif /* _UAPI_LINUX_IOAM6_H */ > diff --git a/include/uapi/linux/ioam6_iptunnel.h > b/include/uapi/linux/ioam6_iptunnel.h > new file mode 100644 > index 00000000..bae14636 > --- /dev/null > +++ b/include/uapi/linux/ioam6_iptunnel.h > @@ -0,0 +1,20 @@ > +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ > +/* > + * IPv6 IOAM Lightweight Tunnel API > + * > + * Author: > + * Justin Iurman <justin.iurman@uliege.be> > + */ > + > +#ifndef _UAPI_LINUX_IOAM6_IPTUNNEL_H > +#define _UAPI_LINUX_IOAM6_IPTUNNEL_H > + > +enum { > + IOAM6_IPTUNNEL_UNSPEC, > + IOAM6_IPTUNNEL_TRACE, /* struct ioam6_trace_hdr */ > + __IOAM6_IPTUNNEL_MAX, > +}; > + > +#define IOAM6_IPTUNNEL_MAX (__IOAM6_IPTUNNEL_MAX - 1) > + > +#endif /* _UAPI_LINUX_IOAM6_IPTUNNEL_H */ > diff --git a/include/uapi/linux/lwtunnel.h b/include/uapi/linux/lwtunnel.h > index b7c0191f..78f0ecd1 100644 > --- a/include/uapi/linux/lwtunnel.h > +++ b/include/uapi/linux/lwtunnel.h > @@ -14,6 +14,7 @@ enum lwtunnel_encap_types { > LWTUNNEL_ENCAP_BPF, > LWTUNNEL_ENCAP_SEG6_LOCAL, > LWTUNNEL_ENCAP_RPL, > + LWTUNNEL_ENCAP_IOAM6, > __LWTUNNEL_ENCAP_MAX, > }; > > diff --git a/ip/iproute.c b/ip/iproute.c > index bdeb9644..330203b0 100644 > --- a/ip/iproute.c > +++ b/ip/iproute.c > @@ -101,8 +101,8 @@ static void usage(void) > "TIME := NUMBER[s|ms]\n" > "BOOL := [1|0]\n" > "FEATURES := ecn\n" > - "ENCAPTYPE := [ mpls | ip | ip6 | seg6 | seg6local | rpl ]\n" > - "ENCAPHDR := [ MPLSLABEL | SEG6HDR | SEG6LOCAL ]\n" > + "ENCAPTYPE := [ mpls | ip | ip6 | seg6 | seg6local | rpl | ioam6 ]\n" > + "ENCAPHDR := [ MPLSLABEL | SEG6HDR | SEG6LOCAL | IOAM6HDR ]\n" > "SEG6HDR := [ mode SEGMODE ] segs ADDR1,ADDRi,ADDRn [hmac HMACKEYID] > [cleanup]\n" > "SEGMODE := [ encap | inline ]\n" > "SEG6LOCAL := action ACTION [ OPTIONS ] [ count ]\n" > @@ -112,6 +112,7 @@ static void usage(void) > "OPTIONS := OPTION [ OPTIONS ]\n" > "OPTION := { srh SEG6HDR | nh4 ADDR | nh6 ADDR | iif DEV | oif DEV |\n" > " table TABLEID | vrftable TABLEID | endpoint PROGNAME }\n" > + "IOAM6HDR := trace type IOAM6_TRACE_TYPE ns IOAM6_NAMESPACE size > IOAM6_TRACE_SIZE\n" > "ROUTE_GET_FLAGS := [ fibmatch ]\n"); > exit(-1); > } > diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c > index c4bae68d..f1e001c4 100644 > --- a/ip/iproute_lwtunnel.c > +++ b/ip/iproute_lwtunnel.c > @@ -34,6 +34,8 @@ > #include <linux/seg6_hmac.h> > #include <linux/seg6_local.h> > #include <linux/if_tunnel.h> > +#include <linux/ioam6.h> > +#include <linux/ioam6_iptunnel.h> > > static const char *format_encap_type(int type) > { > @@ -54,6 +56,8 @@ static const char *format_encap_type(int type) > return "seg6local"; > case LWTUNNEL_ENCAP_RPL: > return "rpl"; > + case LWTUNNEL_ENCAP_IOAM6: > + return "ioam6"; > default: > return "unknown"; > } > @@ -90,6 +94,8 @@ static int read_encap_type(const char *name) > return LWTUNNEL_ENCAP_SEG6_LOCAL; > else if (strcmp(name, "rpl") == 0) > return LWTUNNEL_ENCAP_RPL; > + else if (strcmp(name, "ioam6") == 0) > + return LWTUNNEL_ENCAP_IOAM6; > else if (strcmp(name, "help") == 0) > encap_type_usage(); > > @@ -204,6 +210,23 @@ static void print_encap_rpl(FILE *fp, struct rtattr *encap) > print_rpl_srh(fp, srh); > } > > +static void print_encap_ioam6(FILE *fp, struct rtattr *encap) > +{ > + struct rtattr *tb[IOAM6_IPTUNNEL_MAX + 1]; > + struct ioam6_trace_hdr *trace; > + > + parse_rtattr_nested(tb, IOAM6_IPTUNNEL_MAX, encap); > + > + if (!tb[IOAM6_IPTUNNEL_TRACE]) > + return; > + > + trace = RTA_DATA(tb[IOAM6_IPTUNNEL_TRACE]); > + > + print_hex(PRINT_ANY, "type", "type %#06x ", ntohl(trace->type_be32) >> 8); Uh oh... Should be %#08x instead, sorry for that. Should I submit a v3 to reflect it? > + print_uint(PRINT_ANY, "ns", "ns %u ", ntohs(trace->namespace_id)); > + print_uint(PRINT_ANY, "size", "size %u ", trace->remlen * 4); > +} > + > static const char *seg6_action_names[SEG6_LOCAL_ACTION_MAX + 1] = { > [SEG6_LOCAL_ACTION_END] = "End", > [SEG6_LOCAL_ACTION_END_X] = "End.X", > @@ -657,6 +680,9 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type, > case LWTUNNEL_ENCAP_RPL: > print_encap_rpl(fp, encap); > break; > + case LWTUNNEL_ENCAP_IOAM6: > + print_encap_ioam6(fp, encap); > + break; > } > } > > @@ -853,6 +879,98 @@ out: > return ret; > } > > +static int parse_encap_ioam6(struct rtattr *rta, size_t len, int *argcp, > + char ***argvp) > +{ > + struct ioam6_trace_hdr *trace; > + char **argv = *argvp; > + int argc = *argcp; > + int ns_found = 0; > + __u16 size = 0; > + __u32 type = 0; > + __u16 ns; > + > + trace = calloc(1, sizeof(*trace)); > + if (!trace) > + return -1; > + > + if (strcmp(*argv, "trace")) > + missarg("trace"); > + > + while (NEXT_ARG_OK()) { > + NEXT_ARG_FWD(); > + > + if (strcmp(*argv, "type") == 0) { > + NEXT_ARG(); > + > + if (type) > + duparg2("type", *argv); > + > + if (get_u32(&type, *argv, 0) || !type) > + invarg("Invalid type", *argv); > + > + trace->type_be32 = htonl(type << 8); > + > + } else if (strcmp(*argv, "ns") == 0) { > + NEXT_ARG(); > + > + if (ns_found++) > + duparg2("ns", *argv); > + > + if (!type) > + missarg("type"); > + > + if (get_u16(&ns, *argv, 0)) > + invarg("Invalid namespace ID", *argv); > + > + trace->namespace_id = htons(ns); > + > + } else if (strcmp(*argv, "size") == 0) { > + NEXT_ARG(); > + > + if (size) > + duparg2("size", *argv); > + > + if (!type) > + missarg("type"); > + if (!ns_found) > + missarg("ns"); > + > + if (get_u16(&size, *argv, 0) || !size) > + invarg("Invalid size", *argv); > + > + if (size % 4) > + invarg("Size must be a 4-octet multiple", *argv); > + if (size > IOAM6_TRACE_DATA_SIZE_MAX) > + invarg("Size too big", *argv); > + > + trace->remlen = (__u8)(size / 4); > + > + } else { > + break; > + } > + } > + > + if (!type) > + missarg("type"); > + if (!ns_found) > + missarg("ns"); > + if (!size) > + missarg("size"); > + > + if (rta_addattr_l(rta, len, IOAM6_IPTUNNEL_TRACE, trace, > + sizeof(*trace))) { > + free(trace); > + return -1; > + } > + > + *argcp = argc + 1; > + *argvp = argv - 1; > + > + free(trace); > + return 0; > +} > + > struct lwt_x { > struct rtattr *rta; > size_t len; > @@ -1744,6 +1862,9 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int > *argcp, char ***argvp, > case LWTUNNEL_ENCAP_RPL: > ret = parse_encap_rpl(rta, len, &argc, &argv); > break; > + case LWTUNNEL_ENCAP_IOAM6: > + ret = parse_encap_ioam6(rta, len, &argc, &argv); > + break; > default: > fprintf(stderr, "Error: unsupported encap type\n"); > break; > -- > 2.25.1
On 7/27/21 7:42 AM, Justin Iurman wrote: >> + trace = RTA_DATA(tb[IOAM6_IPTUNNEL_TRACE]); >> + >> + print_hex(PRINT_ANY, "type", "type %#06x ", ntohl(trace->type_be32) >> 8); > Uh oh... Should be %#08x instead, sorry for that. Should I submit a v3 to reflect it? > >> + print_uint(PRINT_ANY, "ns", "ns %u ", ntohs(trace->namespace_id)); >> + print_uint(PRINT_ANY, "size", "size %u ", trace->remlen * 4); >> +} >> + roll it into v3. (also, please chop unrelated content in the reply; it is easy to miss that one line comment scrolling the long message)
diff --git a/include/uapi/linux/ioam6.h b/include/uapi/linux/ioam6.h new file mode 100644 index 00000000..0a2cc17d --- /dev/null +++ b/include/uapi/linux/ioam6.h @@ -0,0 +1,133 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * IPv6 IOAM implementation + * + * Author: + * Justin Iurman <justin.iurman@uliege.be> + */ + +#ifndef _UAPI_LINUX_IOAM6_H +#define _UAPI_LINUX_IOAM6_H + +#include <asm/byteorder.h> +#include <linux/types.h> + +#define IOAM6_U16_UNAVAILABLE U16_MAX +#define IOAM6_U32_UNAVAILABLE U32_MAX +#define IOAM6_U64_UNAVAILABLE U64_MAX + +#define IOAM6_DEFAULT_ID (IOAM6_U32_UNAVAILABLE >> 8) +#define IOAM6_DEFAULT_ID_WIDE (IOAM6_U64_UNAVAILABLE >> 8) +#define IOAM6_DEFAULT_IF_ID IOAM6_U16_UNAVAILABLE +#define IOAM6_DEFAULT_IF_ID_WIDE IOAM6_U32_UNAVAILABLE + +/* + * IPv6 IOAM Option Header + */ +struct ioam6_hdr { + __u8 opt_type; + __u8 opt_len; + __u8 :8; /* reserved */ +#define IOAM6_TYPE_PREALLOC 0 + __u8 type; +} __attribute__((__packed__)); + +/* + * IOAM Trace Header + */ +struct ioam6_trace_hdr { + __be16 namespace_id; + +#if defined(__LITTLE_ENDIAN_BITFIELD) + + __u8 :1, /* unused */ + :1, /* unused */ + overflow:1, + nodelen:5; + + __u8 remlen:7, + :1; /* unused */ + + union { + __be32 type_be32; + + struct { + __u32 bit7:1, + bit6:1, + bit5:1, + bit4:1, + bit3:1, + bit2:1, + bit1:1, + bit0:1, + bit15:1, /* unused */ + bit14:1, /* unused */ + bit13:1, /* unused */ + bit12:1, /* unused */ + bit11:1, + bit10:1, + bit9:1, + bit8:1, + bit23:1, /* reserved */ + bit22:1, + bit21:1, /* unused */ + bit20:1, /* unused */ + bit19:1, /* unused */ + bit18:1, /* unused */ + bit17:1, /* unused */ + bit16:1, /* unused */ + :8; /* reserved */ + } type; + }; + +#elif defined(__BIG_ENDIAN_BITFIELD) + + __u8 nodelen:5, + overflow:1, + :1, /* unused */ + :1; /* unused */ + + __u8 :1, /* unused */ + remlen:7; + + union { + __be32 type_be32; + + struct { + __u32 bit0:1, + bit1:1, + bit2:1, + bit3:1, + bit4:1, + bit5:1, + bit6:1, + bit7:1, + bit8:1, + bit9:1, + bit10:1, + bit11:1, + bit12:1, /* unused */ + bit13:1, /* unused */ + bit14:1, /* unused */ + bit15:1, /* unused */ + bit16:1, /* unused */ + bit17:1, /* unused */ + bit18:1, /* unused */ + bit19:1, /* unused */ + bit20:1, /* unused */ + bit21:1, /* unused */ + bit22:1, + bit23:1, /* reserved */ + :8; /* reserved */ + } type; + }; + +#else +#error "Please fix <asm/byteorder.h>" +#endif + +#define IOAM6_TRACE_DATA_SIZE_MAX 244 + __u8 data[0]; +} __attribute__((__packed__)); + +#endif /* _UAPI_LINUX_IOAM6_H */ diff --git a/include/uapi/linux/ioam6_iptunnel.h b/include/uapi/linux/ioam6_iptunnel.h new file mode 100644 index 00000000..bae14636 --- /dev/null +++ b/include/uapi/linux/ioam6_iptunnel.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * IPv6 IOAM Lightweight Tunnel API + * + * Author: + * Justin Iurman <justin.iurman@uliege.be> + */ + +#ifndef _UAPI_LINUX_IOAM6_IPTUNNEL_H +#define _UAPI_LINUX_IOAM6_IPTUNNEL_H + +enum { + IOAM6_IPTUNNEL_UNSPEC, + IOAM6_IPTUNNEL_TRACE, /* struct ioam6_trace_hdr */ + __IOAM6_IPTUNNEL_MAX, +}; + +#define IOAM6_IPTUNNEL_MAX (__IOAM6_IPTUNNEL_MAX - 1) + +#endif /* _UAPI_LINUX_IOAM6_IPTUNNEL_H */ diff --git a/include/uapi/linux/lwtunnel.h b/include/uapi/linux/lwtunnel.h index b7c0191f..78f0ecd1 100644 --- a/include/uapi/linux/lwtunnel.h +++ b/include/uapi/linux/lwtunnel.h @@ -14,6 +14,7 @@ enum lwtunnel_encap_types { LWTUNNEL_ENCAP_BPF, LWTUNNEL_ENCAP_SEG6_LOCAL, LWTUNNEL_ENCAP_RPL, + LWTUNNEL_ENCAP_IOAM6, __LWTUNNEL_ENCAP_MAX, }; diff --git a/ip/iproute.c b/ip/iproute.c index bdeb9644..330203b0 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -101,8 +101,8 @@ static void usage(void) "TIME := NUMBER[s|ms]\n" "BOOL := [1|0]\n" "FEATURES := ecn\n" - "ENCAPTYPE := [ mpls | ip | ip6 | seg6 | seg6local | rpl ]\n" - "ENCAPHDR := [ MPLSLABEL | SEG6HDR | SEG6LOCAL ]\n" + "ENCAPTYPE := [ mpls | ip | ip6 | seg6 | seg6local | rpl | ioam6 ]\n" + "ENCAPHDR := [ MPLSLABEL | SEG6HDR | SEG6LOCAL | IOAM6HDR ]\n" "SEG6HDR := [ mode SEGMODE ] segs ADDR1,ADDRi,ADDRn [hmac HMACKEYID] [cleanup]\n" "SEGMODE := [ encap | inline ]\n" "SEG6LOCAL := action ACTION [ OPTIONS ] [ count ]\n" @@ -112,6 +112,7 @@ static void usage(void) "OPTIONS := OPTION [ OPTIONS ]\n" "OPTION := { srh SEG6HDR | nh4 ADDR | nh6 ADDR | iif DEV | oif DEV |\n" " table TABLEID | vrftable TABLEID | endpoint PROGNAME }\n" + "IOAM6HDR := trace type IOAM6_TRACE_TYPE ns IOAM6_NAMESPACE size IOAM6_TRACE_SIZE\n" "ROUTE_GET_FLAGS := [ fibmatch ]\n"); exit(-1); } diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c index c4bae68d..f1e001c4 100644 --- a/ip/iproute_lwtunnel.c +++ b/ip/iproute_lwtunnel.c @@ -34,6 +34,8 @@ #include <linux/seg6_hmac.h> #include <linux/seg6_local.h> #include <linux/if_tunnel.h> +#include <linux/ioam6.h> +#include <linux/ioam6_iptunnel.h> static const char *format_encap_type(int type) { @@ -54,6 +56,8 @@ static const char *format_encap_type(int type) return "seg6local"; case LWTUNNEL_ENCAP_RPL: return "rpl"; + case LWTUNNEL_ENCAP_IOAM6: + return "ioam6"; default: return "unknown"; } @@ -90,6 +94,8 @@ static int read_encap_type(const char *name) return LWTUNNEL_ENCAP_SEG6_LOCAL; else if (strcmp(name, "rpl") == 0) return LWTUNNEL_ENCAP_RPL; + else if (strcmp(name, "ioam6") == 0) + return LWTUNNEL_ENCAP_IOAM6; else if (strcmp(name, "help") == 0) encap_type_usage(); @@ -204,6 +210,23 @@ static void print_encap_rpl(FILE *fp, struct rtattr *encap) print_rpl_srh(fp, srh); } +static void print_encap_ioam6(FILE *fp, struct rtattr *encap) +{ + struct rtattr *tb[IOAM6_IPTUNNEL_MAX + 1]; + struct ioam6_trace_hdr *trace; + + parse_rtattr_nested(tb, IOAM6_IPTUNNEL_MAX, encap); + + if (!tb[IOAM6_IPTUNNEL_TRACE]) + return; + + trace = RTA_DATA(tb[IOAM6_IPTUNNEL_TRACE]); + + print_hex(PRINT_ANY, "type", "type %#06x ", ntohl(trace->type_be32) >> 8); + print_uint(PRINT_ANY, "ns", "ns %u ", ntohs(trace->namespace_id)); + print_uint(PRINT_ANY, "size", "size %u ", trace->remlen * 4); +} + static const char *seg6_action_names[SEG6_LOCAL_ACTION_MAX + 1] = { [SEG6_LOCAL_ACTION_END] = "End", [SEG6_LOCAL_ACTION_END_X] = "End.X", @@ -657,6 +680,9 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type, case LWTUNNEL_ENCAP_RPL: print_encap_rpl(fp, encap); break; + case LWTUNNEL_ENCAP_IOAM6: + print_encap_ioam6(fp, encap); + break; } } @@ -853,6 +879,98 @@ out: return ret; } +static int parse_encap_ioam6(struct rtattr *rta, size_t len, int *argcp, + char ***argvp) +{ + struct ioam6_trace_hdr *trace; + char **argv = *argvp; + int argc = *argcp; + int ns_found = 0; + __u16 size = 0; + __u32 type = 0; + __u16 ns; + + trace = calloc(1, sizeof(*trace)); + if (!trace) + return -1; + + if (strcmp(*argv, "trace")) + missarg("trace"); + + while (NEXT_ARG_OK()) { + NEXT_ARG_FWD(); + + if (strcmp(*argv, "type") == 0) { + NEXT_ARG(); + + if (type) + duparg2("type", *argv); + + if (get_u32(&type, *argv, 0) || !type) + invarg("Invalid type", *argv); + + trace->type_be32 = htonl(type << 8); + + } else if (strcmp(*argv, "ns") == 0) { + NEXT_ARG(); + + if (ns_found++) + duparg2("ns", *argv); + + if (!type) + missarg("type"); + + if (get_u16(&ns, *argv, 0)) + invarg("Invalid namespace ID", *argv); + + trace->namespace_id = htons(ns); + + } else if (strcmp(*argv, "size") == 0) { + NEXT_ARG(); + + if (size) + duparg2("size", *argv); + + if (!type) + missarg("type"); + if (!ns_found) + missarg("ns"); + + if (get_u16(&size, *argv, 0) || !size) + invarg("Invalid size", *argv); + + if (size % 4) + invarg("Size must be a 4-octet multiple", *argv); + if (size > IOAM6_TRACE_DATA_SIZE_MAX) + invarg("Size too big", *argv); + + trace->remlen = (__u8)(size / 4); + + } else { + break; + } + } + + if (!type) + missarg("type"); + if (!ns_found) + missarg("ns"); + if (!size) + missarg("size"); + + if (rta_addattr_l(rta, len, IOAM6_IPTUNNEL_TRACE, trace, + sizeof(*trace))) { + free(trace); + return -1; + } + + *argcp = argc + 1; + *argvp = argv - 1; + + free(trace); + return 0; +} + struct lwt_x { struct rtattr *rta; size_t len; @@ -1744,6 +1862,9 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp, case LWTUNNEL_ENCAP_RPL: ret = parse_encap_rpl(rta, len, &argc, &argv); break; + case LWTUNNEL_ENCAP_IOAM6: + ret = parse_encap_ioam6(rta, len, &argc, &argv); + break; default: fprintf(stderr, "Error: unsupported encap type\n"); break;
This patch provides a new encap type for routes to insert an IOAM pre-allocated trace: $ ip -6 ro ad fc00::1/128 encap ioam6 trace type 0x800000 ns 1 size 12 dev eth0 where: - "trace" may appear as useless but just anticipates for future implementations of other ioam option types. - "type" is a bitfield (=u32) defining the IOAM pre-allocated trace type (see the corresponding uapi). - "ns" is an IOAM namespace ID attached to the pre-allocated trace. - "size" is the trace pre-allocated size in bytes; must be a 4-octet multiple; limited size (see IOAM6_TRACE_DATA_SIZE_MAX). Signed-off-by: Justin Iurman <justin.iurman@uliege.be> --- include/uapi/linux/ioam6.h | 133 ++++++++++++++++++++++++++++ include/uapi/linux/ioam6_iptunnel.h | 20 +++++ include/uapi/linux/lwtunnel.h | 1 + ip/iproute.c | 5 +- ip/iproute_lwtunnel.c | 121 +++++++++++++++++++++++++ 5 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 include/uapi/linux/ioam6.h create mode 100644 include/uapi/linux/ioam6_iptunnel.h