New IOAM6 encap type for routes
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 prealloc type 0x800000 ns 1 size 12 dev eth0 where: - "trace" and "prealloc" may appear as useless but just anticipate 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> Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
parent
f0b3808afa
commit
2d83c71082
|
|
@ -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 prealloc type IOAM6_TRACE_TYPE ns IOAM6_NAMESPACE size IOAM6_TRACE_SIZE\n"
|
||||
"ROUTE_GET_FLAGS := [ fibmatch ]\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,25 @@ 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_null(PRINT_ANY, "trace", "trace ", NULL);
|
||||
print_null(PRINT_ANY, "prealloc", "prealloc ", NULL);
|
||||
print_hex(PRINT_ANY, "type", "type %#08x ", 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 +682,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 +881,102 @@ 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");
|
||||
|
||||
NEXT_ARG();
|
||||
if (strcmp(*argv, "prealloc"))
|
||||
missarg("prealloc");
|
||||
|
||||
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 +1868,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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue