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>
26 #include "iproute_lwtunnel.h"
28 static int read_encap_type(const char *name
)
30 if (strcmp(name
, "mpls") == 0)
31 return LWTUNNEL_ENCAP_MPLS
;
32 else if (strcmp(name
, "ip") == 0)
33 return LWTUNNEL_ENCAP_IP
;
34 else if (strcmp(name
, "ip6") == 0)
35 return LWTUNNEL_ENCAP_IP6
;
36 else if (strcmp(name
, "ila") == 0)
37 return LWTUNNEL_ENCAP_ILA
;
39 return LWTUNNEL_ENCAP_NONE
;
42 static const char *format_encap_type(int type
)
45 case LWTUNNEL_ENCAP_MPLS
:
47 case LWTUNNEL_ENCAP_IP
:
49 case LWTUNNEL_ENCAP_IP6
:
51 case LWTUNNEL_ENCAP_ILA
:
58 static void print_encap_mpls(FILE *fp
, struct rtattr
*encap
)
60 struct rtattr
*tb
[MPLS_IPTUNNEL_MAX
+1];
62 parse_rtattr_nested(tb
, MPLS_IPTUNNEL_MAX
, encap
);
64 if (tb
[MPLS_IPTUNNEL_DST
])
66 format_host_rta(AF_MPLS
, tb
[MPLS_IPTUNNEL_DST
]));
69 static void print_encap_ip(FILE *fp
, struct rtattr
*encap
)
71 struct rtattr
*tb
[LWTUNNEL_IP_MAX
+1];
73 parse_rtattr_nested(tb
, LWTUNNEL_IP_MAX
, encap
);
75 if (tb
[LWTUNNEL_IP_ID
])
76 fprintf(fp
, "id %llu ", ntohll(rta_getattr_u64(tb
[LWTUNNEL_IP_ID
])));
78 if (tb
[LWTUNNEL_IP_SRC
])
79 fprintf(fp
, "src %s ",
80 rt_addr_n2a_rta(AF_INET
, tb
[LWTUNNEL_IP_SRC
]));
82 if (tb
[LWTUNNEL_IP_DST
])
83 fprintf(fp
, "dst %s ",
84 rt_addr_n2a_rta(AF_INET
, tb
[LWTUNNEL_IP_DST
]));
86 if (tb
[LWTUNNEL_IP_TTL
])
87 fprintf(fp
, "ttl %d ", rta_getattr_u8(tb
[LWTUNNEL_IP_TTL
]));
89 if (tb
[LWTUNNEL_IP_TOS
])
90 fprintf(fp
, "tos %d ", rta_getattr_u8(tb
[LWTUNNEL_IP_TOS
]));
93 static char *ila_csum_mode2name(__u8 csum_mode
)
96 case ILA_CSUM_ADJUST_TRANSPORT
:
97 return "adj-transport";
98 case ILA_CSUM_NEUTRAL_MAP
:
100 case ILA_CSUM_NO_ACTION
:
107 static __u8
ila_csum_name2mode(char *name
)
109 if (strcmp(name
, "adj-transport") == 0)
110 return ILA_CSUM_ADJUST_TRANSPORT
;
111 else if (strcmp(name
, "neutral-map") == 0)
112 return ILA_CSUM_NEUTRAL_MAP
;
113 else if (strcmp(name
, "no-action") == 0)
114 return ILA_CSUM_NO_ACTION
;
119 static void print_encap_ila(FILE *fp
, struct rtattr
*encap
)
121 struct rtattr
*tb
[ILA_ATTR_MAX
+1];
123 parse_rtattr_nested(tb
, ILA_ATTR_MAX
, encap
);
125 if (tb
[ILA_ATTR_LOCATOR
]) {
126 char abuf
[ADDR64_BUF_SIZE
];
128 addr64_n2a(*(__u64
*)RTA_DATA(tb
[ILA_ATTR_LOCATOR
]),
130 fprintf(fp
, " %s ", abuf
);
133 if (tb
[ILA_ATTR_CSUM_MODE
])
134 fprintf(fp
, " csum-mode %s ",
135 ila_csum_mode2name(rta_getattr_u8(tb
[ILA_ATTR_CSUM_MODE
])));
138 static void print_encap_ip6(FILE *fp
, struct rtattr
*encap
)
140 struct rtattr
*tb
[LWTUNNEL_IP6_MAX
+1];
142 parse_rtattr_nested(tb
, LWTUNNEL_IP6_MAX
, encap
);
144 if (tb
[LWTUNNEL_IP6_ID
])
145 fprintf(fp
, "id %llu ", ntohll(rta_getattr_u64(tb
[LWTUNNEL_IP6_ID
])));
147 if (tb
[LWTUNNEL_IP6_SRC
])
148 fprintf(fp
, "src %s ",
149 rt_addr_n2a_rta(AF_INET6
, tb
[LWTUNNEL_IP6_SRC
]));
151 if (tb
[LWTUNNEL_IP6_DST
])
152 fprintf(fp
, "dst %s ",
153 rt_addr_n2a_rta(AF_INET6
, tb
[LWTUNNEL_IP6_DST
]));
155 if (tb
[LWTUNNEL_IP6_HOPLIMIT
])
156 fprintf(fp
, "hoplimit %d ", rta_getattr_u8(tb
[LWTUNNEL_IP6_HOPLIMIT
]));
158 if (tb
[LWTUNNEL_IP6_TC
])
159 fprintf(fp
, "tc %d ", rta_getattr_u8(tb
[LWTUNNEL_IP6_TC
]));
162 void lwt_print_encap(FILE *fp
, struct rtattr
*encap_type
,
163 struct rtattr
*encap
)
170 et
= rta_getattr_u16(encap_type
);
172 fprintf(fp
, " encap %s ", format_encap_type(et
));
175 case LWTUNNEL_ENCAP_MPLS
:
176 print_encap_mpls(fp
, encap
);
178 case LWTUNNEL_ENCAP_IP
:
179 print_encap_ip(fp
, encap
);
181 case LWTUNNEL_ENCAP_ILA
:
182 print_encap_ila(fp
, encap
);
184 case LWTUNNEL_ENCAP_IP6
:
185 print_encap_ip6(fp
, encap
);
190 static int parse_encap_mpls(struct rtattr
*rta
, size_t len
, int *argcp
, char ***argvp
)
194 char **argv
= *argvp
;
196 if (get_addr(&addr
, *argv
, AF_MPLS
)) {
197 fprintf(stderr
, "Error: an inet address is expected rather than \"%s\".\n", *argv
);
201 rta_addattr_l(rta
, len
, MPLS_IPTUNNEL_DST
, &addr
.data
,
210 static int parse_encap_ip(struct rtattr
*rta
, size_t len
, int *argcp
, char ***argvp
)
212 int id_ok
= 0, dst_ok
= 0, tos_ok
= 0, ttl_ok
= 0;
213 char **argv
= *argvp
;
217 if (strcmp(*argv
, "id") == 0) {
222 duparg2("id", *argv
);
223 if (get_be64(&id
, *argv
, 0))
224 invarg("\"id\" value is invalid\n", *argv
);
225 rta_addattr64(rta
, len
, LWTUNNEL_IP_ID
, id
);
226 } else if (strcmp(*argv
, "dst") == 0) {
231 duparg2("dst", *argv
);
232 get_addr(&addr
, *argv
, AF_INET
);
233 rta_addattr_l(rta
, len
, LWTUNNEL_IP_DST
, &addr
.data
, addr
.bytelen
);
234 } else if (strcmp(*argv
, "tos") == 0) {
239 duparg2("tos", *argv
);
240 if (rtnl_dsfield_a2n(&tos
, *argv
))
241 invarg("\"tos\" value is invalid\n", *argv
);
242 rta_addattr8(rta
, len
, LWTUNNEL_IP_TOS
, tos
);
243 } else if (strcmp(*argv
, "ttl") == 0) {
248 duparg2("ttl", *argv
);
249 if (get_u8(&ttl
, *argv
, 0))
250 invarg("\"ttl\" value is invalid\n", *argv
);
251 rta_addattr8(rta
, len
, LWTUNNEL_IP_TTL
, ttl
);
258 /* argv is currently the first unparsed argument,
259 * but the lwt_parse_encap() caller will move to the next,
267 static int parse_encap_ila(struct rtattr
*rta
, size_t len
,
268 int *argcp
, char ***argvp
)
272 char **argv
= *argvp
;
274 if (get_addr64(&locator
, *argv
) < 0) {
275 fprintf(stderr
, "Bad locator: %s\n", *argv
);
281 rta_addattr64(rta
, 1024, ILA_ATTR_LOCATOR
, locator
);
284 if (strcmp(*argv
, "csum-mode") == 0) {
289 csum_mode
= ila_csum_name2mode(*argv
);
291 invarg("\"csum-mode\" value is invalid\n", *argv
);
293 rta_addattr8(rta
, 1024, ILA_ATTR_CSUM_MODE
, csum_mode
);
301 /* argv is currently the first unparsed argument,
302 * but the lwt_parse_encap() caller will move to the next,
311 static int parse_encap_ip6(struct rtattr
*rta
, size_t len
, int *argcp
, char ***argvp
)
313 int id_ok
= 0, dst_ok
= 0, tos_ok
= 0, ttl_ok
= 0;
314 char **argv
= *argvp
;
318 if (strcmp(*argv
, "id") == 0) {
323 duparg2("id", *argv
);
324 if (get_be64(&id
, *argv
, 0))
325 invarg("\"id\" value is invalid\n", *argv
);
326 rta_addattr64(rta
, len
, LWTUNNEL_IP6_ID
, id
);
327 } else if (strcmp(*argv
, "dst") == 0) {
332 duparg2("dst", *argv
);
333 get_addr(&addr
, *argv
, AF_INET6
);
334 rta_addattr_l(rta
, len
, LWTUNNEL_IP6_DST
, &addr
.data
, addr
.bytelen
);
335 } else if (strcmp(*argv
, "tc") == 0) {
340 duparg2("tc", *argv
);
341 if (rtnl_dsfield_a2n(&tc
, *argv
))
342 invarg("\"tc\" value is invalid\n", *argv
);
343 rta_addattr8(rta
, len
, LWTUNNEL_IP6_TC
, tc
);
344 } else if (strcmp(*argv
, "hoplimit") == 0) {
349 duparg2("hoplimit", *argv
);
350 if (get_u8(&hoplimit
, *argv
, 0))
351 invarg("\"hoplimit\" value is invalid\n", *argv
);
352 rta_addattr8(rta
, len
, LWTUNNEL_IP6_HOPLIMIT
, hoplimit
);
359 /* argv is currently the first unparsed argument,
360 * but the lwt_parse_encap() caller will move to the next,
368 int lwt_parse_encap(struct rtattr
*rta
, size_t len
, int *argcp
, char ***argvp
)
372 char **argv
= *argvp
;
376 type
= read_encap_type(*argv
);
378 invarg("\"encap type\" value is invalid\n", *argv
);
382 fprintf(stderr
, "Error: unexpected end of line after \"encap\"\n");
386 nest
= rta_nest(rta
, 1024, RTA_ENCAP
);
388 case LWTUNNEL_ENCAP_MPLS
:
389 parse_encap_mpls(rta
, len
, &argc
, &argv
);
391 case LWTUNNEL_ENCAP_IP
:
392 parse_encap_ip(rta
, len
, &argc
, &argv
);
394 case LWTUNNEL_ENCAP_ILA
:
395 parse_encap_ila(rta
, len
, &argc
, &argv
);
397 case LWTUNNEL_ENCAP_IP6
:
398 parse_encap_ip6(rta
, len
, &argc
, &argv
);
401 fprintf(stderr
, "Error: unsupported encap type\n");
404 rta_nest_end(rta
, nest
);
406 rta_addattr16(rta
, 1024, RTA_ENCAP_TYPE
, type
);