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