]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/ipila.c
ila: support for configuring identifier and hook types
[mirror_iproute2.git] / ip / ipila.c
CommitLineData
ec71cae0
TH
1/*
2 * ipila.c ILA (Identifier Locator Addressing) support
3 *
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.
8 *
9 * Authors: Tom Herbert <tom@herbertland.com>
10 */
11
12#include <netdb.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <net/if.h>
17#include <linux/ila.h>
18#include <linux/genetlink.h>
19#include <linux/ip.h>
20#include <arpa/inet.h>
21
22#include "libgenl.h"
23#include "utils.h"
24#include "ip_common.h"
25
26static void usage(void)
27{
28 fprintf(stderr, "Usage: ip ila add loc_match LOCATOR_MATCH "
2a1bc2fb
TH
29 "loc LOCATOR [ dev DEV ] "
30 "[ csum-mode { adj-transport | neutral-map | "
86905c8f
TH
31 "neutral-map-auto | no-action } ] "
32 "[ ident-type { luid | use-format } ]\n");
ec71cae0
TH
33 fprintf(stderr, " ip ila del loc_match LOCATOR_MATCH "
34 "[ loc LOCATOR ] [ dev DEV ]\n");
35 fprintf(stderr, " ip ila list\n");
36 fprintf(stderr, "\n");
37
38 exit(-1);
39}
40
41/* netlink socket */
42static struct rtnl_handle genl_rth = { .fd = -1 };
43static int genl_family = -1;
44
45#define ILA_REQUEST(_req, _bufsiz, _cmd, _flags) \
46 GENL_REQUEST(_req, _bufsiz, genl_family, 0, \
47 ILA_GENL_VERSION, _cmd, _flags)
48
49#define ILA_RTA(g) ((struct rtattr *)(((char *)(g)) + \
50 NLMSG_ALIGN(sizeof(struct genlmsghdr))))
51
52#define ADDR_BUF_SIZE sizeof("xxxx:xxxx:xxxx:xxxx")
53
2a1bc2fb
TH
54static char *ila_csum_mode2name(__u8 csum_mode)
55{
56 switch (csum_mode) {
57 case ILA_CSUM_ADJUST_TRANSPORT:
58 return "adj-transport";
59 case ILA_CSUM_NEUTRAL_MAP:
60 return "neutral-map";
61 case ILA_CSUM_NO_ACTION:
62 return "no-action";
11775523
TH
63 case ILA_CSUM_NEUTRAL_MAP_AUTO:
64 return "neutral-map-auto";
2a1bc2fb
TH
65 default:
66 return "unknown";
67 }
68}
69
70static int ila_csum_name2mode(char *name)
71{
72 if (strcmp(name, "adj-transport") == 0)
73 return ILA_CSUM_ADJUST_TRANSPORT;
74 else if (strcmp(name, "neutral-map") == 0)
75 return ILA_CSUM_NEUTRAL_MAP;
11775523
TH
76 else if (strcmp(name, "neutral-map-auto") == 0)
77 return ILA_CSUM_NEUTRAL_MAP_AUTO;
86905c8f
TH
78 else if (strcmp(name, "no-action") == 0)
79 return ILA_CSUM_NO_ACTION;
80 else if (strcmp(name, "neutral-map-auto") == 0)
81 return ILA_CSUM_NEUTRAL_MAP_AUTO;
82 else
83 return -1;
84}
85
86static char *ila_ident_type2name(__u8 ident_type)
87{
88 switch (ident_type) {
89 case ILA_ATYPE_IID:
90 return "iid";
91 case ILA_ATYPE_LUID:
92 return "luid";
93 case ILA_ATYPE_VIRT_V4:
94 return "virt-v4";
95 case ILA_ATYPE_VIRT_UNI_V6:
96 return "virt-uni-v6";
97 case ILA_ATYPE_VIRT_MULTI_V6:
98 return "virt-multi-v6";
99 case ILA_ATYPE_NONLOCAL_ADDR:
100 return "nonlocal-addr";
101 case ILA_ATYPE_USE_FORMAT:
102 return "use-format";
103 default:
104 return "unknown";
105 }
106}
107
108static int ila_ident_name2type(char *name)
109{
110 if (!strcmp(name, "luid"))
111 return ILA_ATYPE_LUID;
112 else if (!strcmp(name, "use-format"))
113 return ILA_ATYPE_USE_FORMAT;
114#if 0 /* No kernel support for configuring these yet */
115 else if (!strcmp(name, "iid"))
116 return ILA_ATYPE_IID;
117 else if (!strcmp(name, "virt-v4"))
118 return ILA_ATYPE_VIRT_V4;
119 else if (!strcmp(name, "virt-uni-v6"))
120 return ILA_ATYPE_VIRT_UNI_V6;
121 else if (!strcmp(name, "virt-multi-v6"))
122 return ILA_ATYPE_VIRT_MULTI_V6;
123 else if (!strcmp(name, "nonlocal-addr"))
124 return ILA_ATYPE_NONLOCAL_ADDR;
125#endif
2a1bc2fb
TH
126 else
127 return -1;
128}
129
ec71cae0
TH
130static int print_addr64(__u64 addr, char *buff, size_t len)
131{
132 __u16 *words = (__u16 *)&addr;
133 __u16 v;
134 int i, ret;
135 size_t written = 0;
136 char *sep = ":";
137
138 for (i = 0; i < 4; i++) {
139 v = ntohs(words[i]);
140
141 if (i == 3)
142 sep = "";
143
144 ret = snprintf(&buff[written], len - written, "%x%s", v, sep);
145 if (ret < 0)
146 return ret;
147
148 written += ret;
149 }
150
151 return written;
152}
153
154static void print_ila_locid(FILE *fp, int attr, struct rtattr *tb[], int space)
155{
156 char abuf[256];
157 size_t blen;
158 int i;
159
160 if (tb[attr]) {
d3357cfc 161 blen = print_addr64(rta_getattr_u64(tb[attr]),
ec71cae0
TH
162 abuf, sizeof(abuf));
163 fprintf(fp, "%s", abuf);
164 } else {
165 fprintf(fp, "-");
166 blen = 1;
167 }
168
169 for (i = 0; i < space - blen; i++)
170 fprintf(fp, " ");
171}
172
173static int print_ila_mapping(const struct sockaddr_nl *who,
174 struct nlmsghdr *n, void *arg)
175{
176 FILE *fp = (FILE *)arg;
177 struct genlmsghdr *ghdr;
178 struct rtattr *tb[ILA_ATTR_MAX + 1];
179 int len = n->nlmsg_len;
180
181 if (n->nlmsg_type != genl_family)
182 return 0;
183
184 len -= NLMSG_LENGTH(GENL_HDRLEN);
185 if (len < 0)
186 return -1;
187
188 ghdr = NLMSG_DATA(n);
189 parse_rtattr(tb, ILA_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len);
190
191 print_ila_locid(fp, ILA_ATTR_LOCATOR_MATCH, tb, ADDR_BUF_SIZE);
192 print_ila_locid(fp, ILA_ATTR_LOCATOR, tb, ADDR_BUF_SIZE);
193
194 if (tb[ILA_ATTR_IFINDEX])
2a1bc2fb
TH
195 fprintf(fp, "%-16s",
196 ll_index_to_name(rta_getattr_u32(
197 tb[ILA_ATTR_IFINDEX])));
198 else
86905c8f 199 fprintf(fp, "%-10s ", "-");
2a1bc2fb
TH
200
201 if (tb[ILA_ATTR_CSUM_MODE])
202 fprintf(fp, "%s",
203 ila_csum_mode2name(rta_getattr_u8(
204 tb[ILA_ATTR_CSUM_MODE])));
86905c8f
TH
205 else
206 fprintf(fp, "%-10s ", "-");
207
208 if (tb[ILA_ATTR_IDENT_TYPE])
209 fprintf(fp, "%s",
210 ila_ident_type2name(rta_getattr_u8(
211 tb[ILA_ATTR_IDENT_TYPE])));
ec71cae0
TH
212 else
213 fprintf(fp, "-");
2a1bc2fb 214
ec71cae0
TH
215 fprintf(fp, "\n");
216
217 return 0;
218}
219
220#define NLMSG_BUF_SIZE 4096
221
222static int do_list(int argc, char **argv)
223{
224 ILA_REQUEST(req, 1024, ILA_CMD_GET, NLM_F_REQUEST | NLM_F_DUMP);
225
226 if (argc > 0) {
227 fprintf(stderr, "\"ip ila show\" does not take "
228 "any arguments.\n");
229 return -1;
230 }
231
232 if (rtnl_send(&genl_rth, (void *)&req, req.n.nlmsg_len) < 0) {
233 perror("Cannot send dump request");
234 exit(1);
235 }
236
237 if (rtnl_dump_filter(&genl_rth, print_ila_mapping, stdout) < 0) {
238 fprintf(stderr, "Dump terminated\n");
239 return 1;
240 }
241
242 return 0;
243}
244
245static int ila_parse_opt(int argc, char **argv, struct nlmsghdr *n,
246 bool adding)
247{
2d01b393
TH
248 __u64 locator = 0;
249 __u64 locator_match = 0;
ec71cae0 250 int ifindex = 0;
2a1bc2fb 251 int csum_mode = 0;
86905c8f 252 int ident_type = 0;
ec71cae0
TH
253 bool loc_set = false;
254 bool loc_match_set = false;
255 bool ifindex_set = false;
2a1bc2fb 256 bool csum_mode_set = false;
86905c8f 257 bool ident_type_set = false;
ec71cae0
TH
258
259 while (argc > 0) {
260 if (!matches(*argv, "loc")) {
261 NEXT_ARG();
262
263 if (get_addr64(&locator, *argv) < 0) {
264 fprintf(stderr, "Bad locator: %s\n", *argv);
265 return -1;
266 }
267 loc_set = true;
268 } else if (!matches(*argv, "loc_match")) {
269 NEXT_ARG();
270
271 if (get_addr64(&locator_match, *argv) < 0) {
272 fprintf(stderr, "Bad locator to match: %s\n",
273 *argv);
274 return -1;
275 }
276 loc_match_set = true;
2a1bc2fb
TH
277 } else if (!matches(*argv, "csum-mode")) {
278 NEXT_ARG();
279
280 csum_mode = ila_csum_name2mode(*argv);
281 if (csum_mode < 0) {
282 fprintf(stderr, "Bad csum-mode: %s\n",
283 *argv);
284 return -1;
285 }
286 csum_mode_set = true;
86905c8f
TH
287 } else if (!matches(*argv, "ident-type")) {
288 NEXT_ARG();
289
290 ident_type = ila_ident_name2type(*argv);
291 if (ident_type < 0) {
292 fprintf(stderr, "Bad ident-type: %s\n",
293 *argv);
294 return -1;
295 }
296 ident_type_set = true;
ec71cae0
TH
297 } else if (!matches(*argv, "dev")) {
298 NEXT_ARG();
299
300 ifindex = ll_name_to_index(*argv);
301 if (ifindex == 0) {
302 fprintf(stderr, "No such interface: %s\n",
303 *argv);
304 return -1;
305 }
306 ifindex_set = true;
307 } else {
308 usage();
309 return -1;
310 }
311 argc--, argv++;
312 }
313
314 if (adding) {
315 if (!loc_set) {
316 fprintf(stderr, "ila: missing locator\n");
317 return -1;
318 }
319 if (!loc_match_set) {
320 fprintf(stderr, "ila: missing locator0match\n");
321 return -1;
322 }
323 }
324
2d01b393
TH
325 if (loc_match_set)
326 addattr64(n, 1024, ILA_ATTR_LOCATOR_MATCH, locator_match);
327
328 if (loc_set)
329 addattr64(n, 1024, ILA_ATTR_LOCATOR, locator);
ec71cae0
TH
330
331 if (ifindex_set)
332 addattr32(n, 1024, ILA_ATTR_IFINDEX, ifindex);
333
2a1bc2fb
TH
334 if (csum_mode_set)
335 addattr8(n, 1024, ILA_ATTR_CSUM_MODE, csum_mode);
336
86905c8f
TH
337 if (ident_type_set)
338 addattr8(n, 1024, ILA_ATTR_IDENT_TYPE, ident_type);
339
ec71cae0
TH
340 return 0;
341}
342
343static int do_add(int argc, char **argv)
344{
345 ILA_REQUEST(req, 1024, ILA_CMD_ADD, NLM_F_REQUEST);
346
347 ila_parse_opt(argc, argv, &req.n, true);
348
86bf43c7 349 if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
ec71cae0
TH
350 return -2;
351
352 return 0;
353}
354
355static int do_del(int argc, char **argv)
356{
357 ILA_REQUEST(req, 1024, ILA_CMD_DEL, NLM_F_REQUEST);
358
359 ila_parse_opt(argc, argv, &req.n, false);
360
86bf43c7 361 if (rtnl_talk(&genl_rth, &req.n, NULL) < 0)
ec71cae0
TH
362 return -2;
363
364 return 0;
365}
366
367int do_ipila(int argc, char **argv)
368{
ec71cae0
TH
369 if (argc < 1)
370 usage();
371
9423a324
SD
372 if (matches(*argv, "help") == 0)
373 usage();
374
375 if (genl_init_handle(&genl_rth, ILA_GENL_NAME, &genl_family))
376 exit(1);
377
ec71cae0
TH
378 if (matches(*argv, "add") == 0)
379 return do_add(argc-1, argv+1);
380 if (matches(*argv, "delete") == 0)
381 return do_del(argc-1, argv+1);
382 if (matches(*argv, "list") == 0)
383 return do_list(argc-1, argv+1);
ec71cae0
TH
384
385 fprintf(stderr, "Command \"%s\" is unknown, try \"ip ila help\".\n",
386 *argv);
387 exit(-1);
388}