]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/iplink_bond.c
add a source addres length parameter to rt_addr_n2a
[mirror_iproute2.git] / ip / iplink_bond.c
CommitLineData
cc26a890
JP
1/*
2 * iplink_bond.c Bonding device 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: Jiri Pirko <jiri@resnulli.us>
63d127b0 10 * Scott Feldman <sfeldma@cumulusnetworks.com>
cc26a890
JP
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <linux/if_link.h>
63d127b0 17#include <linux/if_ether.h>
cc26a890
JP
18#include <net/if.h>
19
20#include "rt_names.h"
21#include "utils.h"
22#include "ip_common.h"
23
63d127b0 24#define BOND_MAX_ARP_TARGETS 16
25
26static const char *mode_tbl[] = {
27 "balance-rr",
28 "active-backup",
29 "balance-xor",
30 "broadcast",
31 "802.3ad",
32 "balance-tlb",
33 "balance-alb",
34 NULL,
35};
36
37static const char *arp_validate_tbl[] = {
38 "none",
39 "active",
40 "backup",
41 "all",
42 NULL,
43};
44
45static const char *arp_all_targets_tbl[] = {
46 "any",
47 "all",
48 NULL,
49};
50
51static const char *primary_reselect_tbl[] = {
52 "always",
53 "better",
54 "failure",
55 NULL,
56};
57
58static const char *fail_over_mac_tbl[] = {
59 "none",
60 "active",
61 "follow",
62 NULL,
63};
64
65static const char *xmit_hash_policy_tbl[] = {
66 "layer2",
67 "layer3+4",
68 "layer2+3",
69 "encap2+3",
70 "encap3+4",
71 NULL,
72};
73
74static const char *lacp_rate_tbl[] = {
75 "slow",
76 "fast",
77 NULL,
78};
79
80static const char *ad_select_tbl[] = {
81 "stable",
82 "bandwidth",
83 "count",
84 NULL,
85};
86
87static const char *get_name(const char **tbl, int index)
88{
89 int i;
90
91 for (i = 0; tbl[i]; i++)
92 if (i == index)
93 return tbl[i];
94
95 return "UNKNOWN";
96}
97
98static int get_index(const char **tbl, char *name)
99{
100 int i, index;
101
102 /* check for integer index passed in instead of name */
103 if (get_integer(&index, name, 10) == 0)
104 for (i = 0; tbl[i]; i++)
105 if (i == index)
106 return i;
107
108 for (i = 0; tbl[i]; i++)
f7a45e09 109 if (strcmp(tbl[i], name) == 0)
63d127b0 110 return i;
111
112 return -1;
113}
114
561e650e 115static void print_explain(FILE *f)
cc26a890 116{
561e650e 117 fprintf(f,
cc26a890 118 "Usage: ... bond [ mode BONDMODE ] [ active_slave SLAVE_DEV ]\n"
63d127b0 119 " [ clear_active_slave ] [ miimon MIIMON ]\n"
120 " [ updelay UPDELAY ] [ downdelay DOWNDELAY ]\n"
121 " [ use_carrier USE_CARRIER ]\n"
122 " [ arp_interval ARP_INTERVAL ]\n"
123 " [ arp_validate ARP_VALIDATE ]\n"
124 " [ arp_all_targets ARP_ALL_TARGETS ]\n"
125 " [ arp_ip_target [ ARP_IP_TARGET, ... ] ]\n"
126 " [ primary SLAVE_DEV ]\n"
127 " [ primary_reselect PRIMARY_RESELECT ]\n"
128 " [ fail_over_mac FAIL_OVER_MAC ]\n"
129 " [ xmit_hash_policy XMIT_HASH_POLICY ]\n"
130 " [ resend_igmp RESEND_IGMP ]\n"
131 " [ num_grat_arp|num_unsol_na NUM_GRAT_ARP|NUM_UNSOL_NA ]\n"
132 " [ all_slaves_active ALL_SLAVES_ACTIVE ]\n"
133 " [ min_links MIN_LINKS ]\n"
134 " [ lp_interval LP_INTERVAL ]\n"
135 " [ packets_per_slave PACKETS_PER_SLAVE ]\n"
136 " [ lacp_rate LACP_RATE ]\n"
137 " [ ad_select AD_SELECT ]\n"
cc26a890 138 "\n"
63d127b0 139 "BONDMODE := balance-rr|active-backup|balance-xor|broadcast|802.3ad|balance-tlb|balance-alb\n"
140 "ARP_VALIDATE := none|active|backup|all\n"
141 "ARP_ALL_TARGETS := any|all\n"
142 "PRIMARY_RESELECT := always|better|failure\n"
143 "FAIL_OVER_MAC := none|active|follow\n"
144 "XMIT_HASH_POLICY := layer2|layer2+3|layer3+4\n"
145 "LACP_RATE := slow|fast\n"
146 "AD_SELECT := stable|bandwidth|count\n"
cc26a890
JP
147 );
148}
149
561e650e 150static void explain(void)
151{
152 print_explain(stderr);
153}
154
cc26a890
JP
155static int bond_parse_opt(struct link_util *lu, int argc, char **argv,
156 struct nlmsghdr *n)
157{
63d127b0 158 __u8 mode, use_carrier, primary_reselect, fail_over_mac;
159 __u8 xmit_hash_policy, num_peer_notif, all_slaves_active;
160 __u8 lacp_rate, ad_select;
161 __u32 miimon, updelay, downdelay, arp_interval, arp_validate;
162 __u32 arp_all_targets, resend_igmp, min_links, lp_interval;
163 __u32 packets_per_slave;
cc26a890
JP
164 unsigned ifindex;
165
166 while (argc > 0) {
167 if (matches(*argv, "mode") == 0) {
168 NEXT_ARG();
63d127b0 169 if (get_index(mode_tbl, *argv) < 0) {
170 invarg("invalid mode", *argv);
cc26a890
JP
171 return -1;
172 }
63d127b0 173 mode = get_index(mode_tbl, *argv);
cc26a890
JP
174 addattr8(n, 1024, IFLA_BOND_MODE, mode);
175 } else if (matches(*argv, "active_slave") == 0) {
176 NEXT_ARG();
177 ifindex = if_nametoindex(*argv);
178 if (!ifindex)
179 return -1;
180 addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, ifindex);
181 } else if (matches(*argv, "clear_active_slave") == 0) {
182 addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, 0);
63d127b0 183 } else if (matches(*argv, "miimon") == 0) {
184 NEXT_ARG();
185 if (get_u32(&miimon, *argv, 0)) {
186 invarg("invalid miimon", *argv);
187 return -1;
188 }
189 addattr32(n, 1024, IFLA_BOND_MIIMON, miimon);
190 } else if (matches(*argv, "updelay") == 0) {
191 NEXT_ARG();
192 if (get_u32(&updelay, *argv, 0)) {
193 invarg("invalid updelay", *argv);
194 return -1;
195 }
196 addattr32(n, 1024, IFLA_BOND_UPDELAY, updelay);
197 } else if (matches(*argv, "downdelay") == 0) {
198 NEXT_ARG();
199 if (get_u32(&downdelay, *argv, 0)) {
200 invarg("invalid downdelay", *argv);
201 return -1;
202 }
203 addattr32(n, 1024, IFLA_BOND_DOWNDELAY, downdelay);
204 } else if (matches(*argv, "use_carrier") == 0) {
205 NEXT_ARG();
206 if (get_u8(&use_carrier, *argv, 0)) {
207 invarg("invalid use_carrier", *argv);
208 return -1;
209 }
210 addattr8(n, 1024, IFLA_BOND_USE_CARRIER, use_carrier);
211 } else if (matches(*argv, "arp_interval") == 0) {
212 NEXT_ARG();
213 if (get_u32(&arp_interval, *argv, 0)) {
214 invarg("invalid arp_interval", *argv);
215 return -1;
216 }
217 addattr32(n, 1024, IFLA_BOND_ARP_INTERVAL, arp_interval);
218 } else if (matches(*argv, "arp_ip_target") == 0) {
219 struct rtattr * nest = addattr_nest(n, 1024,
220 IFLA_BOND_ARP_IP_TARGET);
221 if (NEXT_ARG_OK()) {
222 NEXT_ARG();
223 char *targets = strdupa(*argv);
224 char *target = strtok(targets, ",");
225 int i;
226
227 for(i = 0; target && i < BOND_MAX_ARP_TARGETS; i++) {
228 __u32 addr = get_addr32(target);
229 addattr32(n, 1024, i, addr);
230 target = strtok(NULL, ",");
231 }
232 addattr_nest_end(n, nest);
233 }
234 addattr_nest_end(n, nest);
235 } else if (matches(*argv, "arp_validate") == 0) {
236 NEXT_ARG();
237 if (get_index(arp_validate_tbl, *argv) < 0) {
238 invarg("invalid arp_validate", *argv);
239 return -1;
240 }
241 arp_validate = get_index(arp_validate_tbl, *argv);
242 addattr32(n, 1024, IFLA_BOND_ARP_VALIDATE, arp_validate);
243 } else if (matches(*argv, "arp_all_targets") == 0) {
244 NEXT_ARG();
245 if (get_index(arp_all_targets_tbl, *argv) < 0) {
246 invarg("invalid arp_all_targets", *argv);
247 return -1;
248 }
249 arp_all_targets = get_index(arp_all_targets_tbl, *argv);
250 addattr32(n, 1024, IFLA_BOND_ARP_ALL_TARGETS, arp_all_targets);
251 } else if (matches(*argv, "primary") == 0) {
252 NEXT_ARG();
253 ifindex = if_nametoindex(*argv);
254 if (!ifindex)
255 return -1;
256 addattr32(n, 1024, IFLA_BOND_PRIMARY, ifindex);
257 } else if (matches(*argv, "primary_reselect") == 0) {
258 NEXT_ARG();
259 if (get_index(primary_reselect_tbl, *argv) < 0) {
260 invarg("invalid primary_reselect", *argv);
261 return -1;
262 }
263 primary_reselect = get_index(primary_reselect_tbl, *argv);
264 addattr8(n, 1024, IFLA_BOND_PRIMARY_RESELECT,
265 primary_reselect);
266 } else if (matches(*argv, "fail_over_mac") == 0) {
267 NEXT_ARG();
268 if (get_index(fail_over_mac_tbl, *argv) < 0) {
269 invarg("invalid fail_over_mac", *argv);
270 return -1;
271 }
272 fail_over_mac = get_index(fail_over_mac_tbl, *argv);
273 addattr8(n, 1024, IFLA_BOND_FAIL_OVER_MAC,
274 fail_over_mac);
275 } else if (matches(*argv, "xmit_hash_policy") == 0) {
276 NEXT_ARG();
277 if (get_index(xmit_hash_policy_tbl, *argv) < 0) {
278 invarg("invalid xmit_hash_policy", *argv);
279 return -1;
280 }
281 xmit_hash_policy = get_index(xmit_hash_policy_tbl, *argv);
282 addattr8(n, 1024, IFLA_BOND_XMIT_HASH_POLICY,
283 xmit_hash_policy);
284 } else if (matches(*argv, "resend_igmp") == 0) {
285 NEXT_ARG();
286 if (get_u32(&resend_igmp, *argv, 0)) {
287 invarg("invalid resend_igmp", *argv);
288 return -1;
289 }
290 addattr32(n, 1024, IFLA_BOND_RESEND_IGMP, resend_igmp);
291 } else if (matches(*argv, "num_grat_arp") == 0 ||
292 matches(*argv, "num_unsol_na") == 0) {
293 NEXT_ARG();
294 if (get_u8(&num_peer_notif, *argv, 0)) {
295 invarg("invalid num_grat_arp|num_unsol_na",
296 *argv);
297 return -1;
298 }
299 addattr8(n, 1024, IFLA_BOND_NUM_PEER_NOTIF,
300 num_peer_notif);
301 } else if (matches(*argv, "all_slaves_active") == 0) {
302 NEXT_ARG();
303 if (get_u8(&all_slaves_active, *argv, 0)) {
304 invarg("invalid all_slaves_active", *argv);
305 return -1;
306 }
307 addattr8(n, 1024, IFLA_BOND_ALL_SLAVES_ACTIVE,
308 all_slaves_active);
309 } else if (matches(*argv, "min_links") == 0) {
310 NEXT_ARG();
311 if (get_u32(&min_links, *argv, 0)) {
312 invarg("invalid min_links", *argv);
313 return -1;
314 }
315 addattr32(n, 1024, IFLA_BOND_MIN_LINKS, min_links);
316 } else if (matches(*argv, "lp_interval") == 0) {
317 NEXT_ARG();
318 if (get_u32(&lp_interval, *argv, 0)) {
319 invarg("invalid lp_interval", *argv);
320 return -1;
321 }
322 addattr32(n, 1024, IFLA_BOND_LP_INTERVAL, lp_interval);
323 } else if (matches(*argv, "packets_per_slave") == 0) {
324 NEXT_ARG();
325 if (get_u32(&packets_per_slave, *argv, 0)) {
326 invarg("invalid packets_per_slave", *argv);
327 return -1;
328 }
329 addattr32(n, 1024, IFLA_BOND_PACKETS_PER_SLAVE,
330 packets_per_slave);
331 } else if (matches(*argv, "lacp_rate") == 0) {
332 NEXT_ARG();
333 if (get_index(lacp_rate_tbl, *argv) < 0) {
334 invarg("invalid lacp_rate", *argv);
335 return -1;
336 }
337 lacp_rate = get_index(lacp_rate_tbl, *argv);
338 addattr8(n, 1024, IFLA_BOND_AD_LACP_RATE, lacp_rate);
339 } else if (matches(*argv, "ad_select") == 0) {
340 NEXT_ARG();
341 if (get_index(ad_select_tbl, *argv) < 0) {
342 invarg("invalid ad_select", *argv);
343 return -1;
344 }
345 ad_select = get_index(ad_select_tbl, *argv);
346 addattr8(n, 1024, IFLA_BOND_AD_SELECT, ad_select);
7feb76ce
JP
347 } else if (matches(*argv, "help") == 0) {
348 explain();
349 return -1;
cc26a890
JP
350 } else {
351 fprintf(stderr, "bond: unknown command \"%s\"?\n", *argv);
352 explain();
353 return -1;
354 }
355 argc--, argv++;
356 }
357
358 return 0;
359}
360
361static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
362{
363 unsigned ifindex;
364
365 if (!tb)
366 return;
367
63d127b0 368 if (tb[IFLA_BOND_MODE]) {
369 const char *mode = get_name(mode_tbl,
370 rta_getattr_u8(tb[IFLA_BOND_MODE]));
371 fprintf(f, "mode %s ", mode);
372 }
cc26a890
JP
373
374 if (tb[IFLA_BOND_ACTIVE_SLAVE] &&
375 (ifindex = rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]))) {
376 char buf[IFNAMSIZ];
377 const char *n = if_indextoname(ifindex, buf);
378
379 if (n)
380 fprintf(f, "active_slave %s ", n);
381 else
382 fprintf(f, "active_slave %u ", ifindex);
383 }
63d127b0 384
385 if (tb[IFLA_BOND_MIIMON])
386 fprintf(f, "miimon %u ", rta_getattr_u32(tb[IFLA_BOND_MIIMON]));
387
388 if (tb[IFLA_BOND_UPDELAY])
389 fprintf(f, "updelay %u ", rta_getattr_u32(tb[IFLA_BOND_UPDELAY]));
390
391 if (tb[IFLA_BOND_DOWNDELAY])
392 fprintf(f, "downdelay %u ",
393 rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY]));
394
395 if (tb[IFLA_BOND_USE_CARRIER])
396 fprintf(f, "use_carrier %u ",
397 rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER]));
398
399 if (tb[IFLA_BOND_ARP_INTERVAL])
400 fprintf(f, "arp_interval %u ",
401 rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL]));
402
403 if (tb[IFLA_BOND_ARP_IP_TARGET]) {
404 struct rtattr *iptb[BOND_MAX_ARP_TARGETS + 1];
405 char buf[INET_ADDRSTRLEN];
406 int i;
407
408 parse_rtattr_nested(iptb, BOND_MAX_ARP_TARGETS,
409 tb[IFLA_BOND_ARP_IP_TARGET]);
410
411 if (iptb[0])
412 fprintf(f, "arp_ip_target ");
413
414 for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
415 if (iptb[i])
416 fprintf(f, "%s",
417 rt_addr_n2a(AF_INET,
26dcdf3a 418 RTA_PAYLOAD(iptb[i]),
63d127b0 419 RTA_DATA(iptb[i]),
420 buf,
421 INET_ADDRSTRLEN));
422 if (i < BOND_MAX_ARP_TARGETS-1 && iptb[i+1])
423 fprintf(f, ",");
424 }
425
426 if (iptb[0])
427 fprintf(f, " ");
428 }
429
430 if (tb[IFLA_BOND_ARP_VALIDATE]) {
431 const char *arp_validate = get_name(arp_validate_tbl,
432 rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE]));
433 fprintf(f, "arp_validate %s ", arp_validate);
434 }
435
436 if (tb[IFLA_BOND_ARP_ALL_TARGETS]) {
437 const char *arp_all_targets = get_name(arp_all_targets_tbl,
438 rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS]));
32ad31fb 439 fprintf(f, "arp_all_targets %s ", arp_all_targets);
63d127b0 440 }
441
442 if (tb[IFLA_BOND_PRIMARY] &&
443 (ifindex = rta_getattr_u32(tb[IFLA_BOND_PRIMARY]))) {
444 char buf[IFNAMSIZ];
445 const char *n = if_indextoname(ifindex, buf);
446
447 if (n)
448 fprintf(f, "primary %s ", n);
449 else
450 fprintf(f, "primary %u ", ifindex);
451 }
452
453 if (tb[IFLA_BOND_PRIMARY_RESELECT]) {
454 const char *primary_reselect = get_name(primary_reselect_tbl,
455 rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT]));
456 fprintf(f, "primary_reselect %s ", primary_reselect);
457 }
458
459 if (tb[IFLA_BOND_FAIL_OVER_MAC]) {
460 const char *fail_over_mac = get_name(fail_over_mac_tbl,
461 rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC]));
462 fprintf(f, "fail_over_mac %s ", fail_over_mac);
463 }
464
465 if (tb[IFLA_BOND_XMIT_HASH_POLICY]) {
466 const char *xmit_hash_policy = get_name(xmit_hash_policy_tbl,
467 rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY]));
468 fprintf(f, "xmit_hash_policy %s ", xmit_hash_policy);
469 }
470
471 if (tb[IFLA_BOND_RESEND_IGMP])
472 fprintf(f, "resend_igmp %u ",
473 rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP]));
474
475 if (tb[IFLA_BOND_NUM_PEER_NOTIF])
476 fprintf(f, "num_grat_arp %u ",
477 rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF]));
478
479 if (tb[IFLA_BOND_ALL_SLAVES_ACTIVE])
480 fprintf(f, "all_slaves_active %u ",
481 rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE]));
482
483 if (tb[IFLA_BOND_MIN_LINKS])
484 fprintf(f, "min_links %u ",
485 rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS]));
486
487 if (tb[IFLA_BOND_LP_INTERVAL])
488 fprintf(f, "lp_interval %u ",
489 rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL]));
490
491 if (tb[IFLA_BOND_PACKETS_PER_SLAVE])
492 fprintf(f, "packets_per_slave %u ",
493 rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE]));
494
495 if (tb[IFLA_BOND_AD_LACP_RATE]) {
496 const char *lacp_rate = get_name(lacp_rate_tbl,
497 rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE]));
498 fprintf(f, "lacp_rate %s ", lacp_rate);
499 }
500
501 if (tb[IFLA_BOND_AD_SELECT]) {
502 const char *ad_select = get_name(ad_select_tbl,
503 rta_getattr_u8(tb[IFLA_BOND_AD_SELECT]));
504 fprintf(f, "ad_select %s ", ad_select);
505 }
506
507 if (tb[IFLA_BOND_AD_INFO]) {
508 struct rtattr *adtb[IFLA_BOND_AD_INFO_MAX + 1];
509
510 parse_rtattr_nested(adtb, IFLA_BOND_AD_INFO_MAX,
511 tb[IFLA_BOND_AD_INFO]);
512
513 if (adtb[IFLA_BOND_AD_INFO_AGGREGATOR])
514 fprintf(f, "ad_aggregator %d ",
515 rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR]));
516
517 if (adtb[IFLA_BOND_AD_INFO_NUM_PORTS])
518 fprintf(f, "ad_num_ports %d ",
519 rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS]));
520
521 if (adtb[IFLA_BOND_AD_INFO_ACTOR_KEY])
522 fprintf(f, "ad_actor_key %d ",
523 rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]));
524
525 if (adtb[IFLA_BOND_AD_INFO_PARTNER_KEY])
526 fprintf(f, "ad_partner_key %d ",
527 rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]));
528
529 if (adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]) {
530 unsigned char *p =
531 RTA_DATA(adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]);
532 SPRINT_BUF(b);
533 fprintf(f, "ad_partner_mac %s ",
534 ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b)));
535 }
536 }
cc26a890
JP
537}
538
561e650e 539static void bond_print_help(struct link_util *lu, int argc, char **argv,
540 FILE *f)
541{
542 print_explain(f);
543}
544
cc26a890
JP
545struct link_util bond_link_util = {
546 .id = "bond",
547 .maxattr = IFLA_BOND_MAX,
548 .parse_opt = bond_parse_opt,
549 .print_opt = bond_print_opt,
561e650e 550 .print_help = bond_print_help,
cc26a890 551};