4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Roopa Prabhu, <roopa@cumulusnetworks.com>
10 * Thomas Graf <tgraf@suug.ch>
19 #include <linux/ila.h>
20 #include <linux/lwtunnel.h>
21 #include <linux/mpls_iptunnel.h>
27 #include "ip_common.h"
28 #include "ila_common.h"
30 #include <linux/seg6.h>
31 #include <linux/seg6_iptunnel.h>
32 #include <linux/seg6_hmac.h>
33 #include <linux/seg6_local.h>
34 #include <linux/if_tunnel.h>
36 static const char *format_encap_type(int type
)
39 case LWTUNNEL_ENCAP_MPLS
:
41 case LWTUNNEL_ENCAP_IP
:
43 case LWTUNNEL_ENCAP_IP6
:
45 case LWTUNNEL_ENCAP_ILA
:
47 case LWTUNNEL_ENCAP_BPF
:
49 case LWTUNNEL_ENCAP_SEG6
:
51 case LWTUNNEL_ENCAP_SEG6_LOCAL
:
58 static void encap_type_usage(void)
62 fprintf(stderr
, "Usage: ip route ... encap TYPE [ OPTIONS ] [...]\n");
64 for (i
= 1; i
<= LWTUNNEL_ENCAP_MAX
; i
++)
65 fprintf(stderr
, "%s %s\n", format_encap_type(i
),
66 i
== 1 ? "TYPE := " : " ");
71 static int read_encap_type(const char *name
)
73 if (strcmp(name
, "mpls") == 0)
74 return LWTUNNEL_ENCAP_MPLS
;
75 else if (strcmp(name
, "ip") == 0)
76 return LWTUNNEL_ENCAP_IP
;
77 else if (strcmp(name
, "ip6") == 0)
78 return LWTUNNEL_ENCAP_IP6
;
79 else if (strcmp(name
, "ila") == 0)
80 return LWTUNNEL_ENCAP_ILA
;
81 else if (strcmp(name
, "bpf") == 0)
82 return LWTUNNEL_ENCAP_BPF
;
83 else if (strcmp(name
, "seg6") == 0)
84 return LWTUNNEL_ENCAP_SEG6
;
85 else if (strcmp(name
, "seg6local") == 0)
86 return LWTUNNEL_ENCAP_SEG6_LOCAL
;
87 else if (strcmp(name
, "help") == 0)
90 return LWTUNNEL_ENCAP_NONE
;
93 static void print_srh(FILE *fp
, struct ipv6_sr_hdr
*srh
)
97 if (is_json_context())
98 open_json_array(PRINT_JSON
, "segs");
100 fprintf(fp
, "segs %d [ ", srh
->first_segment
+ 1);
102 for (i
= srh
->first_segment
; i
>= 0; i
--)
103 print_color_string(PRINT_ANY
, COLOR_INET6
,
105 rt_addr_n2a(AF_INET6
, 16, &srh
->segments
[i
]));
107 if (is_json_context())
108 close_json_array(PRINT_JSON
, NULL
);
112 if (sr_has_hmac(srh
)) {
113 unsigned int offset
= ((srh
->hdrlen
+ 1) << 3) - 40;
114 struct sr6_tlv_hmac
*tlv
;
116 tlv
= (struct sr6_tlv_hmac
*)((char *)srh
+ offset
);
117 print_0xhex(PRINT_ANY
, "hmac",
118 "hmac %llX ", ntohl(tlv
->hmackeyid
));
122 static const char *seg6_mode_types
[] = {
123 [SEG6_IPTUN_MODE_INLINE
] = "inline",
124 [SEG6_IPTUN_MODE_ENCAP
] = "encap",
125 [SEG6_IPTUN_MODE_L2ENCAP
] = "l2encap",
128 static const char *format_seg6mode_type(int mode
)
130 if (mode
< 0 || mode
> ARRAY_SIZE(seg6_mode_types
))
133 return seg6_mode_types
[mode
];
136 static int read_seg6mode_type(const char *mode
)
140 for (i
= 0; i
< ARRAY_SIZE(seg6_mode_types
); i
++) {
141 if (strcmp(mode
, seg6_mode_types
[i
]) == 0)
148 static void print_encap_seg6(FILE *fp
, struct rtattr
*encap
)
150 struct rtattr
*tb
[SEG6_IPTUNNEL_MAX
+1];
151 struct seg6_iptunnel_encap
*tuninfo
;
153 parse_rtattr_nested(tb
, SEG6_IPTUNNEL_MAX
, encap
);
155 if (!tb
[SEG6_IPTUNNEL_SRH
])
158 tuninfo
= RTA_DATA(tb
[SEG6_IPTUNNEL_SRH
]);
159 print_string(PRINT_ANY
, "mode",
160 "mode %s ", format_seg6mode_type(tuninfo
->mode
));
162 print_srh(fp
, tuninfo
->srh
);
165 static const char *seg6_action_names
[SEG6_LOCAL_ACTION_MAX
+ 1] = {
166 [SEG6_LOCAL_ACTION_END
] = "End",
167 [SEG6_LOCAL_ACTION_END_X
] = "End.X",
168 [SEG6_LOCAL_ACTION_END_T
] = "End.T",
169 [SEG6_LOCAL_ACTION_END_DX2
] = "End.DX2",
170 [SEG6_LOCAL_ACTION_END_DX6
] = "End.DX6",
171 [SEG6_LOCAL_ACTION_END_DX4
] = "End.DX4",
172 [SEG6_LOCAL_ACTION_END_DT6
] = "End.DT6",
173 [SEG6_LOCAL_ACTION_END_DT4
] = "End.DT4",
174 [SEG6_LOCAL_ACTION_END_B6
] = "End.B6",
175 [SEG6_LOCAL_ACTION_END_B6_ENCAP
] = "End.B6.Encaps",
176 [SEG6_LOCAL_ACTION_END_BM
] = "End.BM",
177 [SEG6_LOCAL_ACTION_END_S
] = "End.S",
178 [SEG6_LOCAL_ACTION_END_AS
] = "End.AS",
179 [SEG6_LOCAL_ACTION_END_AM
] = "End.AM",
180 [SEG6_LOCAL_ACTION_END_BPF
] = "End.BPF",
183 static const char *format_action_type(int action
)
185 if (action
< 0 || action
> SEG6_LOCAL_ACTION_MAX
)
188 return seg6_action_names
[action
] ?: "<unknown>";
191 static int read_action_type(const char *name
)
195 for (i
= 0; i
< SEG6_LOCAL_ACTION_MAX
+ 1; i
++) {
196 if (!seg6_action_names
[i
])
199 if (strcmp(seg6_action_names
[i
], name
) == 0)
203 return SEG6_LOCAL_ACTION_UNSPEC
;
206 static void print_encap_bpf_prog(FILE *fp
, struct rtattr
*encap
,
209 struct rtattr
*tb
[LWT_BPF_PROG_MAX
+1];
210 const char *progname
= NULL
;
212 parse_rtattr_nested(tb
, LWT_BPF_PROG_MAX
, encap
);
214 if (tb
[LWT_BPF_PROG_NAME
])
215 progname
= rta_getattr_str(tb
[LWT_BPF_PROG_NAME
]);
217 if (is_json_context())
218 print_string(PRINT_JSON
, str
, NULL
,
219 progname
? : "<unknown>");
221 fprintf(fp
, "%s ", str
);
223 fprintf(fp
, "%s ", progname
);
227 static void print_encap_seg6local(FILE *fp
, struct rtattr
*encap
)
229 struct rtattr
*tb
[SEG6_LOCAL_MAX
+ 1];
234 parse_rtattr_nested(tb
, SEG6_LOCAL_MAX
, encap
);
236 if (!tb
[SEG6_LOCAL_ACTION
])
239 action
= rta_getattr_u32(tb
[SEG6_LOCAL_ACTION
]);
241 print_string(PRINT_ANY
, "action",
242 "action %s ", format_action_type(action
));
244 if (tb
[SEG6_LOCAL_SRH
]) {
245 open_json_object("srh");
246 print_srh(fp
, RTA_DATA(tb
[SEG6_LOCAL_SRH
]));
250 if (tb
[SEG6_LOCAL_TABLE
])
251 print_string(PRINT_ANY
, "table", "table %s ",
252 rtnl_rttable_n2a(rta_getattr_u32(tb
[SEG6_LOCAL_TABLE
]),
255 if (tb
[SEG6_LOCAL_NH4
]) {
256 print_string(PRINT_ANY
, "nh4",
257 "nh4 %s ", rt_addr_n2a_rta(AF_INET
, tb
[SEG6_LOCAL_NH4
]));
260 if (tb
[SEG6_LOCAL_NH6
]) {
261 print_string(PRINT_ANY
, "nh6",
262 "nh6 %s ", rt_addr_n2a_rta(AF_INET6
, tb
[SEG6_LOCAL_NH6
]));
265 if (tb
[SEG6_LOCAL_IIF
]) {
266 int iif
= rta_getattr_u32(tb
[SEG6_LOCAL_IIF
]);
268 print_string(PRINT_ANY
, "iif",
269 "iif %s ", ll_index_to_name(iif
));
272 if (tb
[SEG6_LOCAL_OIF
]) {
273 int oif
= rta_getattr_u32(tb
[SEG6_LOCAL_OIF
]);
275 print_string(PRINT_ANY
, "oif",
276 "oif %s ", ll_index_to_name(oif
));
279 if (tb
[SEG6_LOCAL_BPF
])
280 print_encap_bpf_prog(fp
, tb
[SEG6_LOCAL_BPF
], "endpoint");
283 static void print_encap_mpls(FILE *fp
, struct rtattr
*encap
)
285 struct rtattr
*tb
[MPLS_IPTUNNEL_MAX
+1];
287 parse_rtattr_nested(tb
, MPLS_IPTUNNEL_MAX
, encap
);
289 if (tb
[MPLS_IPTUNNEL_DST
])
290 print_string(PRINT_ANY
, "dst", " %s ",
291 format_host_rta(AF_MPLS
, tb
[MPLS_IPTUNNEL_DST
]));
292 if (tb
[MPLS_IPTUNNEL_TTL
])
293 print_uint(PRINT_ANY
, "ttl", "ttl %u ",
294 rta_getattr_u8(tb
[MPLS_IPTUNNEL_TTL
]));
297 static void lwtunnel_print_geneve_opts(struct rtattr
*attr
)
299 struct rtattr
*tb
[LWTUNNEL_IP_OPT_GENEVE_MAX
+ 1];
300 struct rtattr
*i
= RTA_DATA(attr
);
301 int rem
= RTA_PAYLOAD(attr
);
302 char *name
= "geneve_opts";
303 int data_len
, offset
= 0;
304 char data
[rem
* 2 + 1];
309 print_string(PRINT_FP
, name
, "\t%s ", name
);
310 open_json_array(PRINT_JSON
, name
);
313 parse_rtattr(tb
, LWTUNNEL_IP_OPT_GENEVE_MAX
, i
, rem
);
314 class = rta_getattr_be16(tb
[LWTUNNEL_IP_OPT_GENEVE_CLASS
]);
315 type
= rta_getattr_u8(tb
[LWTUNNEL_IP_OPT_GENEVE_TYPE
]);
316 data_len
= RTA_PAYLOAD(tb
[LWTUNNEL_IP_OPT_GENEVE_DATA
]);
317 hexstring_n2a(RTA_DATA(tb
[LWTUNNEL_IP_OPT_GENEVE_DATA
]),
318 data_len
, data
, sizeof(data
));
319 offset
+= data_len
+ 20;
320 rem
-= data_len
+ 20;
321 i
= RTA_DATA(attr
) + offset
;
323 open_json_object(NULL
);
324 print_uint(PRINT_ANY
, "class", "%u", class);
325 print_uint(PRINT_ANY
, "type", ":%u", type
);
327 print_string(PRINT_ANY
, "data", ":%s,", data
);
329 print_string(PRINT_ANY
, "data", ":%s ", data
);
333 close_json_array(PRINT_JSON
, name
);
336 static void lwtunnel_print_vxlan_opts(struct rtattr
*attr
)
338 struct rtattr
*tb
[LWTUNNEL_IP_OPT_VXLAN_MAX
+ 1];
339 struct rtattr
*i
= RTA_DATA(attr
);
340 int rem
= RTA_PAYLOAD(attr
);
341 char *name
= "vxlan_opts";
344 parse_rtattr(tb
, LWTUNNEL_IP_OPT_VXLAN_MAX
, i
, rem
);
345 gbp
= rta_getattr_u32(tb
[LWTUNNEL_IP_OPT_VXLAN_GBP
]);
348 print_string(PRINT_FP
, name
, "\t%s ", name
);
349 open_json_array(PRINT_JSON
, name
);
350 open_json_object(NULL
);
351 print_uint(PRINT_ANY
, "gbp", "%u ", gbp
);
353 close_json_array(PRINT_JSON
, name
);
356 static void lwtunnel_print_opts(struct rtattr
*attr
)
358 struct rtattr
*tb_opt
[LWTUNNEL_IP_OPTS_MAX
+ 1];
360 parse_rtattr_nested(tb_opt
, LWTUNNEL_IP_OPTS_MAX
, attr
);
361 if (tb_opt
[LWTUNNEL_IP_OPTS_GENEVE
])
362 lwtunnel_print_geneve_opts(tb_opt
[LWTUNNEL_IP_OPTS_GENEVE
]);
363 else if (tb_opt
[LWTUNNEL_IP_OPTS_VXLAN
])
364 lwtunnel_print_vxlan_opts(tb_opt
[LWTUNNEL_IP_OPTS_VXLAN
]);
367 static void print_encap_ip(FILE *fp
, struct rtattr
*encap
)
369 struct rtattr
*tb
[LWTUNNEL_IP_MAX
+1];
372 parse_rtattr_nested(tb
, LWTUNNEL_IP_MAX
, encap
);
374 if (tb
[LWTUNNEL_IP_ID
])
375 print_u64(PRINT_ANY
, "id", "id %llu ",
376 ntohll(rta_getattr_u64(tb
[LWTUNNEL_IP_ID
])));
378 if (tb
[LWTUNNEL_IP_SRC
])
379 print_color_string(PRINT_ANY
, COLOR_INET
,
381 rt_addr_n2a_rta(AF_INET
, tb
[LWTUNNEL_IP_SRC
]));
383 if (tb
[LWTUNNEL_IP_DST
])
384 print_color_string(PRINT_ANY
, COLOR_INET
,
386 rt_addr_n2a_rta(AF_INET
, tb
[LWTUNNEL_IP_DST
]));
388 if (tb
[LWTUNNEL_IP_TTL
])
389 print_uint(PRINT_ANY
, "ttl",
390 "ttl %u ", rta_getattr_u8(tb
[LWTUNNEL_IP_TTL
]));
392 if (tb
[LWTUNNEL_IP_TOS
])
393 print_uint(PRINT_ANY
, "tos",
394 "tos %d ", rta_getattr_u8(tb
[LWTUNNEL_IP_TOS
]));
396 if (tb
[LWTUNNEL_IP_FLAGS
]) {
397 flags
= rta_getattr_u16(tb
[LWTUNNEL_IP_FLAGS
]);
398 if (flags
& TUNNEL_KEY
)
399 print_bool(PRINT_ANY
, "key", "key ", true);
400 if (flags
& TUNNEL_CSUM
)
401 print_bool(PRINT_ANY
, "csum", "csum ", true);
402 if (flags
& TUNNEL_SEQ
)
403 print_bool(PRINT_ANY
, "seq", "seq ", true);
406 if (tb
[LWTUNNEL_IP_OPTS
])
407 lwtunnel_print_opts(tb
[LWTUNNEL_IP_OPTS
]);
410 static void print_encap_ila(FILE *fp
, struct rtattr
*encap
)
412 struct rtattr
*tb
[ILA_ATTR_MAX
+1];
414 parse_rtattr_nested(tb
, ILA_ATTR_MAX
, encap
);
416 if (tb
[ILA_ATTR_LOCATOR
]) {
417 char abuf
[ADDR64_BUF_SIZE
];
419 addr64_n2a(rta_getattr_u64(tb
[ILA_ATTR_LOCATOR
]),
421 print_string(PRINT_ANY
, "locator",
425 if (tb
[ILA_ATTR_CSUM_MODE
])
426 print_string(PRINT_ANY
, "csum_mode",
428 ila_csum_mode2name(rta_getattr_u8(tb
[ILA_ATTR_CSUM_MODE
])));
430 if (tb
[ILA_ATTR_IDENT_TYPE
])
431 print_string(PRINT_ANY
, "ident_type",
433 ila_ident_type2name(rta_getattr_u8(tb
[ILA_ATTR_IDENT_TYPE
])));
435 if (tb
[ILA_ATTR_HOOK_TYPE
])
436 print_string(PRINT_ANY
, "hook_type",
438 ila_hook_type2name(rta_getattr_u8(tb
[ILA_ATTR_HOOK_TYPE
])));
441 static void print_encap_ip6(FILE *fp
, struct rtattr
*encap
)
443 struct rtattr
*tb
[LWTUNNEL_IP6_MAX
+1];
446 parse_rtattr_nested(tb
, LWTUNNEL_IP6_MAX
, encap
);
448 if (tb
[LWTUNNEL_IP6_ID
])
449 print_u64(PRINT_ANY
, "id", "id %llu ",
450 ntohll(rta_getattr_u64(tb
[LWTUNNEL_IP6_ID
])));
452 if (tb
[LWTUNNEL_IP6_SRC
])
453 print_color_string(PRINT_ANY
, COLOR_INET6
,
455 rt_addr_n2a_rta(AF_INET6
, tb
[LWTUNNEL_IP6_SRC
]));
457 if (tb
[LWTUNNEL_IP6_DST
])
458 print_color_string(PRINT_ANY
, COLOR_INET6
,
460 rt_addr_n2a_rta(AF_INET6
, tb
[LWTUNNEL_IP6_DST
]));
462 if (tb
[LWTUNNEL_IP6_HOPLIMIT
])
463 print_u64(PRINT_ANY
, "hoplimit",
465 rta_getattr_u8(tb
[LWTUNNEL_IP6_HOPLIMIT
]));
467 if (tb
[LWTUNNEL_IP6_TC
])
468 print_uint(PRINT_ANY
, "tc",
469 "tc %u ", rta_getattr_u8(tb
[LWTUNNEL_IP6_TC
]));
471 if (tb
[LWTUNNEL_IP6_FLAGS
]) {
472 flags
= rta_getattr_u16(tb
[LWTUNNEL_IP6_FLAGS
]);
473 if (flags
& TUNNEL_KEY
)
474 print_bool(PRINT_ANY
, "key", "key ", true);
475 if (flags
& TUNNEL_CSUM
)
476 print_bool(PRINT_ANY
, "csum", "csum ", true);
477 if (flags
& TUNNEL_SEQ
)
478 print_bool(PRINT_ANY
, "seq", "seq ", true);
481 if (tb
[LWTUNNEL_IP6_OPTS
])
482 lwtunnel_print_opts(tb
[LWTUNNEL_IP6_OPTS
]);
485 static void print_encap_bpf(FILE *fp
, struct rtattr
*encap
)
487 struct rtattr
*tb
[LWT_BPF_MAX
+1];
489 parse_rtattr_nested(tb
, LWT_BPF_MAX
, encap
);
492 print_encap_bpf_prog(fp
, tb
[LWT_BPF_IN
], "in");
494 print_encap_bpf_prog(fp
, tb
[LWT_BPF_OUT
], "out");
495 if (tb
[LWT_BPF_XMIT
])
496 print_encap_bpf_prog(fp
, tb
[LWT_BPF_XMIT
], "xmit");
497 if (tb
[LWT_BPF_XMIT_HEADROOM
])
498 print_uint(PRINT_ANY
, "headroom",
499 " %u ", rta_getattr_u32(tb
[LWT_BPF_XMIT_HEADROOM
]));
502 void lwt_print_encap(FILE *fp
, struct rtattr
*encap_type
,
503 struct rtattr
*encap
)
510 et
= rta_getattr_u16(encap_type
);
512 print_string(PRINT_ANY
, "encap", " encap %s ", format_encap_type(et
));
515 case LWTUNNEL_ENCAP_MPLS
:
516 print_encap_mpls(fp
, encap
);
518 case LWTUNNEL_ENCAP_IP
:
519 print_encap_ip(fp
, encap
);
521 case LWTUNNEL_ENCAP_ILA
:
522 print_encap_ila(fp
, encap
);
524 case LWTUNNEL_ENCAP_IP6
:
525 print_encap_ip6(fp
, encap
);
527 case LWTUNNEL_ENCAP_BPF
:
528 print_encap_bpf(fp
, encap
);
530 case LWTUNNEL_ENCAP_SEG6
:
531 print_encap_seg6(fp
, encap
);
533 case LWTUNNEL_ENCAP_SEG6_LOCAL
:
534 print_encap_seg6local(fp
, encap
);
539 static struct ipv6_sr_hdr
*parse_srh(char *segbuf
, int hmac
, bool encap
)
541 struct ipv6_sr_hdr
*srh
;
548 for (i
= 0; *s
; *s
++ == ',' ? i
++ : *s
);
554 srhlen
= 8 + 16*nsegs
;
559 srh
= malloc(srhlen
);
560 memset(srh
, 0, srhlen
);
562 srh
->hdrlen
= (srhlen
>> 3) - 1;
564 srh
->segments_left
= nsegs
- 1;
565 srh
->first_segment
= nsegs
- 1;
568 srh
->flags
|= SR6_FLAG1_HMAC
;
570 i
= srh
->first_segment
;
571 for (s
= strtok(segbuf
, ","); s
; s
= strtok(NULL
, ",")) {
574 get_addr(&addr
, s
, AF_INET6
);
575 memcpy(&srh
->segments
[i
], addr
.data
, sizeof(struct in6_addr
));
580 struct sr6_tlv_hmac
*tlv
;
582 tlv
= (struct sr6_tlv_hmac
*)((char *)srh
+ srhlen
- 40);
583 tlv
->tlvhdr
.type
= SR6_TLV_HMAC
;
584 tlv
->tlvhdr
.len
= 38;
585 tlv
->hmackeyid
= htonl(hmac
);
591 static int parse_encap_seg6(struct rtattr
*rta
, size_t len
, int *argcp
,
594 int mode_ok
= 0, segs_ok
= 0, hmac_ok
= 0;
595 struct seg6_iptunnel_encap
*tuninfo
;
596 struct ipv6_sr_hdr
*srh
;
597 char **argv
= *argvp
;
598 char segbuf
[1024] = "";
606 if (strcmp(*argv
, "mode") == 0) {
609 duparg2("mode", *argv
);
610 encap
= read_seg6mode_type(*argv
);
612 invarg("\"mode\" value is invalid\n", *argv
);
613 } else if (strcmp(*argv
, "segs") == 0) {
616 duparg2("segs", *argv
);
618 invarg("\"segs\" provided before \"mode\"\n",
621 strlcpy(segbuf
, *argv
, 1024);
622 } else if (strcmp(*argv
, "hmac") == 0) {
625 duparg2("hmac", *argv
);
626 get_u32(&hmac
, *argv
, 0);
633 srh
= parse_srh(segbuf
, hmac
, encap
);
634 srhlen
= (srh
->hdrlen
+ 1) << 3;
636 tuninfo
= malloc(sizeof(*tuninfo
) + srhlen
);
637 memset(tuninfo
, 0, sizeof(*tuninfo
) + srhlen
);
639 tuninfo
->mode
= encap
;
641 memcpy(tuninfo
->srh
, srh
, srhlen
);
643 if (rta_addattr_l(rta
, len
, SEG6_IPTUNNEL_SRH
, tuninfo
,
644 sizeof(*tuninfo
) + srhlen
)) {
664 static void bpf_lwt_cb(void *lwt_ptr
, int fd
, const char *annotation
)
666 struct lwt_x
*x
= lwt_ptr
;
668 rta_addattr32(x
->rta
, x
->len
, LWT_BPF_PROG_FD
, fd
);
669 rta_addattr_l(x
->rta
, x
->len
, LWT_BPF_PROG_NAME
, annotation
,
670 strlen(annotation
) + 1);
673 static const struct bpf_cfg_ops bpf_cb_ops
= {
674 .ebpf_cb
= bpf_lwt_cb
,
677 static int lwt_parse_bpf(struct rtattr
*rta
, size_t len
,
678 int *argcp
, char ***argvp
,
679 int attr
, const enum bpf_prog_type bpf_type
)
681 struct bpf_cfg_in cfg
= {
693 nest
= rta_nest(rta
, len
, attr
);
694 err
= bpf_parse_and_load_common(&cfg
, &bpf_cb_ops
, &x
);
696 fprintf(stderr
, "Failed to parse eBPF program: %s\n",
700 rta_nest_end(rta
, nest
);
708 static int parse_encap_seg6local(struct rtattr
*rta
, size_t len
, int *argcp
,
711 int segs_ok
= 0, hmac_ok
= 0, table_ok
= 0, nh4_ok
= 0, nh6_ok
= 0;
712 int iif_ok
= 0, oif_ok
= 0, action_ok
= 0, srh_ok
= 0, bpf_ok
= 0;
713 __u32 action
= 0, table
, iif
, oif
;
714 struct ipv6_sr_hdr
*srh
;
715 char **argv
= *argvp
;
723 if (strcmp(*argv
, "action") == 0) {
726 duparg2("action", *argv
);
727 action
= read_action_type(*argv
);
729 invarg("\"action\" value is invalid\n", *argv
);
730 ret
= rta_addattr32(rta
, len
, SEG6_LOCAL_ACTION
,
732 } else if (strcmp(*argv
, "table") == 0) {
735 duparg2("table", *argv
);
736 rtnl_rttable_a2n(&table
, *argv
);
737 ret
= rta_addattr32(rta
, len
, SEG6_LOCAL_TABLE
, table
);
738 } else if (strcmp(*argv
, "nh4") == 0) {
741 duparg2("nh4", *argv
);
742 get_addr(&addr
, *argv
, AF_INET
);
743 ret
= rta_addattr_l(rta
, len
, SEG6_LOCAL_NH4
,
744 &addr
.data
, addr
.bytelen
);
745 } else if (strcmp(*argv
, "nh6") == 0) {
748 duparg2("nh6", *argv
);
749 get_addr(&addr
, *argv
, AF_INET6
);
750 ret
= rta_addattr_l(rta
, len
, SEG6_LOCAL_NH6
,
751 &addr
.data
, addr
.bytelen
);
752 } else if (strcmp(*argv
, "iif") == 0) {
755 duparg2("iif", *argv
);
756 iif
= ll_name_to_index(*argv
);
759 ret
= rta_addattr32(rta
, len
, SEG6_LOCAL_IIF
, iif
);
760 } else if (strcmp(*argv
, "oif") == 0) {
763 duparg2("oif", *argv
);
764 oif
= ll_name_to_index(*argv
);
767 ret
= rta_addattr32(rta
, len
, SEG6_LOCAL_OIF
, oif
);
768 } else if (strcmp(*argv
, "srh") == 0) {
771 duparg2("srh", *argv
);
772 if (strcmp(*argv
, "segs") != 0)
773 invarg("missing \"segs\" attribute for srh\n",
777 duparg2("segs", *argv
);
778 strncpy(segbuf
, *argv
, 1024);
783 if (strcmp(*argv
, "hmac") == 0) {
786 duparg2("hmac", *argv
);
787 get_u32(&hmac
, *argv
, 0);
791 } else if (strcmp(*argv
, "endpoint") == 0) {
794 duparg2("endpoint", *argv
);
796 if (lwt_parse_bpf(rta
, len
, &argc
, &argv
, SEG6_LOCAL_BPF
,
797 BPF_PROG_TYPE_LWT_SEG6LOCAL
) < 0)
808 fprintf(stderr
, "Missing action type\n");
815 srh
= parse_srh(segbuf
, hmac
,
816 action
== SEG6_LOCAL_ACTION_END_B6_ENCAP
);
817 srhlen
= (srh
->hdrlen
+ 1) << 3;
818 ret
= rta_addattr_l(rta
, len
, SEG6_LOCAL_SRH
, srh
, srhlen
);
828 static int parse_encap_mpls(struct rtattr
*rta
, size_t len
,
829 int *argcp
, char ***argvp
)
833 char **argv
= *argvp
;
836 if (get_addr(&addr
, *argv
, AF_MPLS
)) {
838 "Error: an inet address is expected rather than \"%s\".\n",
843 if (rta_addattr_l(rta
, len
, MPLS_IPTUNNEL_DST
,
844 &addr
.data
, addr
.bytelen
))
851 if (strcmp(*argv
, "ttl") == 0) {
856 duparg2("ttl", *argv
);
857 if (get_u8(&ttl
, *argv
, 0))
858 invarg("\"ttl\" value is invalid\n", *argv
);
859 if (rta_addattr8(rta
, len
, MPLS_IPTUNNEL_TTL
, ttl
))
867 /* argv is currently the first unparsed argument,
868 * but the lwt_parse_encap() caller will move to the next,
877 static int lwtunnel_parse_geneve_opt(char *str
, size_t len
, struct rtattr
*rta
)
883 nest
= rta_nest(rta
, len
, LWTUNNEL_IP_OPTS_GENEVE
| NLA_F_NESTED
);
885 token
= strsep(&str
, ":");
888 case LWTUNNEL_IP_OPT_GENEVE_CLASS
:
894 err
= get_be16(&opt_class
, token
, 0);
898 rta_addattr16(rta
, len
, i
, opt_class
);
901 case LWTUNNEL_IP_OPT_GENEVE_TYPE
:
907 err
= get_u8(&opt_type
, token
, 0);
911 rta_addattr8(rta
, len
, i
, opt_type
);
914 case LWTUNNEL_IP_OPT_GENEVE_DATA
:
916 size_t token_len
= strlen(token
);
921 opts
= malloc(token_len
/ 2);
924 if (hex2mem(token
, opts
, token_len
/ 2) < 0) {
928 rta_addattr_l(rta
, len
, i
, opts
, token_len
/ 2);
934 fprintf(stderr
, "Unknown \"geneve_opts\" type\n");
938 token
= strsep(&str
, ":");
941 rta_nest_end(rta
, nest
);
946 static int lwtunnel_parse_geneve_opts(char *str
, size_t len
, struct rtattr
*rta
)
951 token
= strsep(&str
, ",");
953 err
= lwtunnel_parse_geneve_opt(token
, len
, rta
);
957 token
= strsep(&str
, ",");
963 static int lwtunnel_parse_vxlan_opts(char *str
, size_t len
, struct rtattr
*rta
)
969 nest
= rta_nest(rta
, len
, LWTUNNEL_IP_OPTS_VXLAN
| NLA_F_NESTED
);
970 err
= get_u32(&gbp
, str
, 0);
973 rta_addattr32(rta
, len
, LWTUNNEL_IP_OPT_VXLAN_GBP
, gbp
);
975 rta_nest_end(rta
, nest
);
979 static int parse_encap_ip(struct rtattr
*rta
, size_t len
,
980 int *argcp
, char ***argvp
)
982 int id_ok
= 0, dst_ok
= 0, src_ok
= 0, tos_ok
= 0, ttl_ok
= 0;
983 int key_ok
= 0, csum_ok
= 0, seq_ok
= 0, opts_ok
= 0;
984 char **argv
= *argvp
;
990 if (strcmp(*argv
, "id") == 0) {
995 duparg2("id", *argv
);
996 if (get_be64(&id
, *argv
, 0))
997 invarg("\"id\" value is invalid\n", *argv
);
998 ret
= rta_addattr64(rta
, len
, LWTUNNEL_IP_ID
, id
);
999 } else if (strcmp(*argv
, "dst") == 0) {
1004 duparg2("dst", *argv
);
1005 get_addr(&addr
, *argv
, AF_INET
);
1006 ret
= rta_addattr_l(rta
, len
, LWTUNNEL_IP_DST
,
1007 &addr
.data
, addr
.bytelen
);
1008 } else if (strcmp(*argv
, "src") == 0) {
1013 duparg2("src", *argv
);
1014 get_addr(&addr
, *argv
, AF_INET
);
1015 ret
= rta_addattr_l(rta
, len
, LWTUNNEL_IP_SRC
,
1016 &addr
.data
, addr
.bytelen
);
1017 } else if (strcmp(*argv
, "tos") == 0) {
1022 duparg2("tos", *argv
);
1023 if (rtnl_dsfield_a2n(&tos
, *argv
))
1024 invarg("\"tos\" value is invalid\n", *argv
);
1025 ret
= rta_addattr8(rta
, len
, LWTUNNEL_IP_TOS
, tos
);
1026 } else if (strcmp(*argv
, "ttl") == 0) {
1031 duparg2("ttl", *argv
);
1032 if (get_u8(&ttl
, *argv
, 0))
1033 invarg("\"ttl\" value is invalid\n", *argv
);
1034 ret
= rta_addattr8(rta
, len
, LWTUNNEL_IP_TTL
, ttl
);
1035 } else if (strcmp(*argv
, "geneve_opts") == 0) {
1036 struct rtattr
*nest
;
1039 duparg2("opts", *argv
);
1043 nest
= rta_nest(rta
, len
,
1044 LWTUNNEL_IP_OPTS
| NLA_F_NESTED
);
1045 ret
= lwtunnel_parse_geneve_opts(*argv
, len
, rta
);
1047 invarg("\"geneve_opts\" value is invalid\n",
1049 rta_nest_end(rta
, nest
);
1050 } else if (strcmp(*argv
, "vxlan_opts") == 0) {
1051 struct rtattr
*nest
;
1054 duparg2("opts", *argv
);
1058 nest
= rta_nest(rta
, len
,
1059 LWTUNNEL_IP_OPTS
| NLA_F_NESTED
);
1060 ret
= lwtunnel_parse_vxlan_opts(*argv
, len
, rta
);
1062 invarg("\"vxlan_opts\" value is invalid\n",
1064 rta_nest_end(rta
, nest
);
1065 } else if (strcmp(*argv
, "key") == 0) {
1067 duparg2("key", *argv
);
1068 flags
|= TUNNEL_KEY
;
1069 } else if (strcmp(*argv
, "csum") == 0) {
1071 duparg2("csum", *argv
);
1072 flags
|= TUNNEL_CSUM
;
1073 } else if (strcmp(*argv
, "seq") == 0) {
1075 duparg2("seq", *argv
);
1076 flags
|= TUNNEL_SEQ
;
1086 ret
= rta_addattr16(rta
, len
, LWTUNNEL_IP_FLAGS
, flags
);
1088 /* argv is currently the first unparsed argument,
1089 * but the lwt_parse_encap() caller will move to the next,
1098 static int parse_encap_ila(struct rtattr
*rta
, size_t len
,
1099 int *argcp
, char ***argvp
)
1103 char **argv
= *argvp
;
1106 if (get_addr64(&locator
, *argv
) < 0) {
1107 fprintf(stderr
, "Bad locator: %s\n", *argv
);
1113 if (rta_addattr64(rta
, len
, ILA_ATTR_LOCATOR
, locator
))
1117 if (strcmp(*argv
, "csum-mode") == 0) {
1122 csum_mode
= ila_csum_name2mode(*argv
);
1124 invarg("\"csum-mode\" value is invalid\n",
1127 ret
= rta_addattr8(rta
, len
, ILA_ATTR_CSUM_MODE
,
1131 } else if (strcmp(*argv
, "ident-type") == 0) {
1136 ident_type
= ila_ident_name2type(*argv
);
1138 invarg("\"ident-type\" value is invalid\n",
1141 ret
= rta_addattr8(rta
, len
, ILA_ATTR_IDENT_TYPE
,
1145 } else if (strcmp(*argv
, "hook-type") == 0) {
1150 hook_type
= ila_hook_name2type(*argv
);
1152 invarg("\"hook-type\" value is invalid\n",
1155 ret
= rta_addattr8(rta
, len
, ILA_ATTR_HOOK_TYPE
,
1166 /* argv is currently the first unparsed argument,
1167 * but the lwt_parse_encap() caller will move to the next,
1176 static int parse_encap_ip6(struct rtattr
*rta
, size_t len
,
1177 int *argcp
, char ***argvp
)
1179 int id_ok
= 0, dst_ok
= 0, src_ok
= 0, tos_ok
= 0, ttl_ok
= 0;
1180 int key_ok
= 0, csum_ok
= 0, seq_ok
= 0, opts_ok
= 0;
1181 char **argv
= *argvp
;
1187 if (strcmp(*argv
, "id") == 0) {
1192 duparg2("id", *argv
);
1193 if (get_be64(&id
, *argv
, 0))
1194 invarg("\"id\" value is invalid\n", *argv
);
1195 ret
= rta_addattr64(rta
, len
, LWTUNNEL_IP6_ID
, id
);
1196 } else if (strcmp(*argv
, "dst") == 0) {
1201 duparg2("dst", *argv
);
1202 get_addr(&addr
, *argv
, AF_INET6
);
1203 ret
= rta_addattr_l(rta
, len
, LWTUNNEL_IP6_DST
,
1204 &addr
.data
, addr
.bytelen
);
1205 } else if (strcmp(*argv
, "src") == 0) {
1210 duparg2("src", *argv
);
1211 get_addr(&addr
, *argv
, AF_INET6
);
1212 ret
= rta_addattr_l(rta
, len
, LWTUNNEL_IP6_SRC
,
1213 &addr
.data
, addr
.bytelen
);
1214 } else if (strcmp(*argv
, "tc") == 0) {
1219 duparg2("tc", *argv
);
1220 if (rtnl_dsfield_a2n(&tc
, *argv
))
1221 invarg("\"tc\" value is invalid\n", *argv
);
1222 ret
= rta_addattr8(rta
, len
, LWTUNNEL_IP6_TC
, tc
);
1223 } else if (strcmp(*argv
, "hoplimit") == 0) {
1228 duparg2("hoplimit", *argv
);
1229 if (get_u8(&hoplimit
, *argv
, 0))
1230 invarg("\"hoplimit\" value is invalid\n",
1232 ret
= rta_addattr8(rta
, len
, LWTUNNEL_IP6_HOPLIMIT
,
1234 } else if (strcmp(*argv
, "geneve_opts") == 0) {
1235 struct rtattr
*nest
;
1238 duparg2("opts", *argv
);
1242 nest
= rta_nest(rta
, len
,
1243 LWTUNNEL_IP_OPTS
| NLA_F_NESTED
);
1244 ret
= lwtunnel_parse_geneve_opts(*argv
, len
, rta
);
1246 invarg("\"geneve_opts\" value is invalid\n",
1248 rta_nest_end(rta
, nest
);
1249 } else if (strcmp(*argv
, "vxlan_opts") == 0) {
1250 struct rtattr
*nest
;
1253 duparg2("opts", *argv
);
1257 nest
= rta_nest(rta
, len
,
1258 LWTUNNEL_IP_OPTS
| NLA_F_NESTED
);
1259 ret
= lwtunnel_parse_vxlan_opts(*argv
, len
, rta
);
1261 invarg("\"vxlan_opts\" value is invalid\n",
1263 rta_nest_end(rta
, nest
);
1264 } else if (strcmp(*argv
, "key") == 0) {
1266 duparg2("key", *argv
);
1267 flags
|= TUNNEL_KEY
;
1268 } else if (strcmp(*argv
, "csum") == 0) {
1270 duparg2("csum", *argv
);
1271 flags
|= TUNNEL_CSUM
;
1272 } else if (strcmp(*argv
, "seq") == 0) {
1274 duparg2("seq", *argv
);
1275 flags
|= TUNNEL_SEQ
;
1285 ret
= rta_addattr16(rta
, len
, LWTUNNEL_IP6_FLAGS
, flags
);
1287 /* argv is currently the first unparsed argument,
1288 * but the lwt_parse_encap() caller will move to the next,
1297 static void lwt_bpf_usage(void)
1299 fprintf(stderr
, "Usage: ip route ... encap bpf [ in BPF ] [ out BPF ] [ xmit BPF ] [...]\n");
1300 fprintf(stderr
, "BPF := obj FILE [ section NAME ] [ verbose ]\n");
1304 static int parse_encap_bpf(struct rtattr
*rta
, size_t len
, int *argcp
,
1307 char **argv
= *argvp
;
1309 int headroom_set
= 0;
1312 if (strcmp(*argv
, "in") == 0) {
1314 if (lwt_parse_bpf(rta
, len
, &argc
, &argv
, LWT_BPF_IN
,
1315 BPF_PROG_TYPE_LWT_IN
) < 0)
1317 } else if (strcmp(*argv
, "out") == 0) {
1319 if (lwt_parse_bpf(rta
, len
, &argc
, &argv
, LWT_BPF_OUT
,
1320 BPF_PROG_TYPE_LWT_OUT
) < 0)
1322 } else if (strcmp(*argv
, "xmit") == 0) {
1324 if (lwt_parse_bpf(rta
, len
, &argc
, &argv
, LWT_BPF_XMIT
,
1325 BPF_PROG_TYPE_LWT_XMIT
) < 0)
1327 } else if (strcmp(*argv
, "headroom") == 0) {
1328 unsigned int headroom
;
1331 if (get_unsigned(&headroom
, *argv
, 0) || headroom
== 0)
1332 invarg("headroom is invalid\n", *argv
);
1334 rta_addattr32(rta
, len
, LWT_BPF_XMIT_HEADROOM
,
1337 } else if (strcmp(*argv
, "help") == 0) {
1345 /* argv is currently the first unparsed argument,
1346 * but the lwt_parse_encap() caller will move to the next,
1355 int lwt_parse_encap(struct rtattr
*rta
, size_t len
, int *argcp
, char ***argvp
,
1356 int encap_attr
, int encap_type_attr
)
1358 struct rtattr
*nest
;
1360 char **argv
= *argvp
;
1365 type
= read_encap_type(*argv
);
1367 invarg("\"encap type\" value is invalid\n", *argv
);
1372 "Error: unexpected end of line after \"encap\"\n");
1376 nest
= rta_nest(rta
, len
, encap_attr
);
1378 case LWTUNNEL_ENCAP_MPLS
:
1379 ret
= parse_encap_mpls(rta
, len
, &argc
, &argv
);
1381 case LWTUNNEL_ENCAP_IP
:
1382 ret
= parse_encap_ip(rta
, len
, &argc
, &argv
);
1384 case LWTUNNEL_ENCAP_ILA
:
1385 ret
= parse_encap_ila(rta
, len
, &argc
, &argv
);
1387 case LWTUNNEL_ENCAP_IP6
:
1388 ret
= parse_encap_ip6(rta
, len
, &argc
, &argv
);
1390 case LWTUNNEL_ENCAP_BPF
:
1391 if (parse_encap_bpf(rta
, len
, &argc
, &argv
) < 0)
1394 case LWTUNNEL_ENCAP_SEG6
:
1395 ret
= parse_encap_seg6(rta
, len
, &argc
, &argv
);
1397 case LWTUNNEL_ENCAP_SEG6_LOCAL
:
1398 ret
= parse_encap_seg6local(rta
, len
, &argc
, &argv
);
1401 fprintf(stderr
, "Error: unsupported encap type\n");
1407 rta_nest_end(rta
, nest
);
1409 ret
= rta_addattr16(rta
, len
, encap_type_attr
, type
);