Add support for IOAM encap modes
This patch adds support for the three IOAM encap modes that were introduced: inline, encap and auto. Signed-off-by: Justin Iurman <justin.iurman@uliege.be> Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
parent
b840c620fe
commit
8fb522cde3
|
|
@ -210,16 +210,54 @@ static void print_encap_rpl(FILE *fp, struct rtattr *encap)
|
||||||
print_rpl_srh(fp, srh);
|
print_rpl_srh(fp, srh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *ioam6_mode_types[IOAM6_IPTUNNEL_MODE_MAX + 1] = {
|
||||||
|
[IOAM6_IPTUNNEL_MODE_INLINE] = "inline",
|
||||||
|
[IOAM6_IPTUNNEL_MODE_ENCAP] = "encap",
|
||||||
|
[IOAM6_IPTUNNEL_MODE_AUTO] = "auto",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *format_ioam6mode_type(int mode)
|
||||||
|
{
|
||||||
|
if (mode < IOAM6_IPTUNNEL_MODE_MIN ||
|
||||||
|
mode > IOAM6_IPTUNNEL_MODE_MAX ||
|
||||||
|
!ioam6_mode_types[mode])
|
||||||
|
return "<unknown>";
|
||||||
|
|
||||||
|
return ioam6_mode_types[mode];
|
||||||
|
}
|
||||||
|
|
||||||
|
static __u8 read_ioam6mode_type(const char *mode)
|
||||||
|
{
|
||||||
|
__u8 i;
|
||||||
|
|
||||||
|
for (i = IOAM6_IPTUNNEL_MODE_MIN; i <= IOAM6_IPTUNNEL_MODE_MAX; i++) {
|
||||||
|
if (ioam6_mode_types[i] && !strcmp(mode, ioam6_mode_types[i]))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void print_encap_ioam6(FILE *fp, struct rtattr *encap)
|
static void print_encap_ioam6(FILE *fp, struct rtattr *encap)
|
||||||
{
|
{
|
||||||
struct rtattr *tb[IOAM6_IPTUNNEL_MAX + 1];
|
struct rtattr *tb[IOAM6_IPTUNNEL_MAX + 1];
|
||||||
struct ioam6_trace_hdr *trace;
|
struct ioam6_trace_hdr *trace;
|
||||||
|
__u8 mode;
|
||||||
|
|
||||||
parse_rtattr_nested(tb, IOAM6_IPTUNNEL_MAX, encap);
|
parse_rtattr_nested(tb, IOAM6_IPTUNNEL_MAX, encap);
|
||||||
|
if (!tb[IOAM6_IPTUNNEL_MODE] || !tb[IOAM6_IPTUNNEL_TRACE])
|
||||||
if (!tb[IOAM6_IPTUNNEL_TRACE])
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
mode = rta_getattr_u8(tb[IOAM6_IPTUNNEL_MODE]);
|
||||||
|
if (!tb[IOAM6_IPTUNNEL_DST] && mode != IOAM6_IPTUNNEL_MODE_INLINE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
print_string(PRINT_ANY, "mode", "mode %s ", format_ioam6mode_type(mode));
|
||||||
|
|
||||||
|
if (mode != IOAM6_IPTUNNEL_MODE_INLINE)
|
||||||
|
print_string(PRINT_ANY, "tundst", "tundst %s ",
|
||||||
|
rt_addr_n2a_rta(AF_INET6, tb[IOAM6_IPTUNNEL_DST]));
|
||||||
|
|
||||||
trace = RTA_DATA(tb[IOAM6_IPTUNNEL_TRACE]);
|
trace = RTA_DATA(tb[IOAM6_IPTUNNEL_TRACE]);
|
||||||
|
|
||||||
print_null(PRINT_ANY, "trace", "trace ", NULL);
|
print_null(PRINT_ANY, "trace", "trace ", NULL);
|
||||||
|
|
@ -884,23 +922,48 @@ out:
|
||||||
static int parse_encap_ioam6(struct rtattr *rta, size_t len, int *argcp,
|
static int parse_encap_ioam6(struct rtattr *rta, size_t len, int *argcp,
|
||||||
char ***argvp)
|
char ***argvp)
|
||||||
{
|
{
|
||||||
|
int ns_found = 0, argc = *argcp;
|
||||||
|
__u16 trace_ns, trace_size = 0;
|
||||||
struct ioam6_trace_hdr *trace;
|
struct ioam6_trace_hdr *trace;
|
||||||
char **argv = *argvp;
|
char **argv = *argvp;
|
||||||
int argc = *argcp;
|
__u32 trace_type = 0;
|
||||||
int ns_found = 0;
|
inet_prefix addr;
|
||||||
__u16 size = 0;
|
__u8 mode;
|
||||||
__u32 type = 0;
|
|
||||||
__u16 ns;
|
|
||||||
|
|
||||||
trace = calloc(1, sizeof(*trace));
|
if (strcmp(*argv, "mode") != 0) {
|
||||||
if (!trace)
|
mode = IOAM6_IPTUNNEL_MODE_INLINE;
|
||||||
return -1;
|
} else {
|
||||||
|
NEXT_ARG();
|
||||||
|
|
||||||
if (strcmp(*argv, "trace"))
|
mode = read_ioam6mode_type(*argv);
|
||||||
|
if (!mode)
|
||||||
|
invarg("Invalid mode", *argv);
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(*argv, "tundst") != 0) {
|
||||||
|
if (mode != IOAM6_IPTUNNEL_MODE_INLINE)
|
||||||
|
missarg("tundst");
|
||||||
|
} else {
|
||||||
|
if (mode == IOAM6_IPTUNNEL_MODE_INLINE)
|
||||||
|
invarg("Inline mode does not need tundst", *argv);
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
|
||||||
|
get_addr(&addr, *argv, AF_INET6);
|
||||||
|
if (addr.family != AF_INET6 || addr.bytelen != 16)
|
||||||
|
invarg("Invalid IPv6 address for tundst", *argv);
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(*argv, "trace") != 0)
|
||||||
missarg("trace");
|
missarg("trace");
|
||||||
|
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (strcmp(*argv, "prealloc"))
|
|
||||||
|
if (strcmp(*argv, "prealloc") != 0)
|
||||||
missarg("prealloc");
|
missarg("prealloc");
|
||||||
|
|
||||||
while (NEXT_ARG_OK()) {
|
while (NEXT_ARG_OK()) {
|
||||||
|
|
@ -909,63 +972,58 @@ static int parse_encap_ioam6(struct rtattr *rta, size_t len, int *argcp,
|
||||||
if (strcmp(*argv, "type") == 0) {
|
if (strcmp(*argv, "type") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
|
|
||||||
if (type)
|
if (trace_type)
|
||||||
duparg2("type", *argv);
|
duparg2("type", *argv);
|
||||||
|
|
||||||
if (get_u32(&type, *argv, 0) || !type)
|
if (get_u32(&trace_type, *argv, 0) || !trace_type)
|
||||||
invarg("Invalid type", *argv);
|
invarg("Invalid trace type", *argv);
|
||||||
|
|
||||||
trace->type_be32 = htonl(type << 8);
|
|
||||||
|
|
||||||
} else if (strcmp(*argv, "ns") == 0) {
|
} else if (strcmp(*argv, "ns") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
|
|
||||||
if (ns_found++)
|
if (ns_found++)
|
||||||
duparg2("ns", *argv);
|
duparg2("ns", *argv);
|
||||||
|
|
||||||
if (!type)
|
if (get_u16(&trace_ns, *argv, 0))
|
||||||
missarg("type");
|
|
||||||
|
|
||||||
if (get_u16(&ns, *argv, 0))
|
|
||||||
invarg("Invalid namespace ID", *argv);
|
invarg("Invalid namespace ID", *argv);
|
||||||
|
|
||||||
trace->namespace_id = htons(ns);
|
|
||||||
|
|
||||||
} else if (strcmp(*argv, "size") == 0) {
|
} else if (strcmp(*argv, "size") == 0) {
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
|
|
||||||
if (size)
|
if (trace_size)
|
||||||
duparg2("size", *argv);
|
duparg2("size", *argv);
|
||||||
|
|
||||||
if (!type)
|
if (get_u16(&trace_size, *argv, 0) || !trace_size)
|
||||||
missarg("type");
|
invarg("Invalid trace size", *argv);
|
||||||
if (!ns_found)
|
|
||||||
missarg("ns");
|
|
||||||
|
|
||||||
if (get_u16(&size, *argv, 0) || !size)
|
if (trace_size % 4)
|
||||||
invarg("Invalid size", *argv);
|
invarg("Trace size must be a 4-octet multiple",
|
||||||
|
*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);
|
|
||||||
|
|
||||||
|
if (trace_size > IOAM6_TRACE_DATA_SIZE_MAX)
|
||||||
|
invarg("Trace size is too big", *argv);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!type)
|
if (!trace_type)
|
||||||
missarg("type");
|
missarg("type");
|
||||||
if (!ns_found)
|
if (!ns_found)
|
||||||
missarg("ns");
|
missarg("ns");
|
||||||
if (!size)
|
if (!trace_size)
|
||||||
missarg("size");
|
missarg("size");
|
||||||
|
|
||||||
if (rta_addattr_l(rta, len, IOAM6_IPTUNNEL_TRACE, trace,
|
trace = calloc(1, sizeof(*trace));
|
||||||
sizeof(*trace))) {
|
if (!trace)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
trace->type_be32 = htonl(trace_type << 8);
|
||||||
|
trace->namespace_id = htons(trace_ns);
|
||||||
|
trace->remlen = (__u8)(trace_size / 4);
|
||||||
|
|
||||||
|
if (rta_addattr8(rta, len, IOAM6_IPTUNNEL_MODE, mode) ||
|
||||||
|
(mode != IOAM6_IPTUNNEL_MODE_INLINE &&
|
||||||
|
rta_addattr_l(rta, len, IOAM6_IPTUNNEL_DST, &addr.data, addr.bytelen)) ||
|
||||||
|
rta_addattr_l(rta, len, IOAM6_IPTUNNEL_TRACE, trace, sizeof(*trace))) {
|
||||||
free(trace);
|
free(trace);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue