• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
get_name(const char ** tbl,int index)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 
get_index(const char ** tbl,char * name)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 
print_explain(FILE * f)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 		"                [ tlb_dynamic_lb TLB_DYNAMIC_LB ]\n"
137 		"                [ lacp_rate LACP_RATE ]\n"
138 		"                [ ad_select AD_SELECT ]\n"
139 		"                [ ad_user_port_key PORTKEY ]\n"
140 		"                [ ad_actor_sys_prio SYSPRIO ]\n"
141 		"                [ ad_actor_system LLADDR ]\n"
142 		"\n"
143 		"BONDMODE := balance-rr|active-backup|balance-xor|broadcast|802.3ad|balance-tlb|balance-alb\n"
144 		"ARP_VALIDATE := none|active|backup|all\n"
145 		"ARP_ALL_TARGETS := any|all\n"
146 		"PRIMARY_RESELECT := always|better|failure\n"
147 		"FAIL_OVER_MAC := none|active|follow\n"
148 		"XMIT_HASH_POLICY := layer2|layer2+3|layer3+4|encap2+3|encap3+4\n"
149 		"LACP_RATE := slow|fast\n"
150 		"AD_SELECT := stable|bandwidth|count\n"
151 	);
152 }
153 
explain(void)154 static void explain(void)
155 {
156 	print_explain(stderr);
157 }
158 
bond_parse_opt(struct link_util * lu,int argc,char ** argv,struct nlmsghdr * n)159 static int bond_parse_opt(struct link_util *lu, int argc, char **argv,
160 			  struct nlmsghdr *n)
161 {
162 	__u8 mode, use_carrier, primary_reselect, fail_over_mac;
163 	__u8 xmit_hash_policy, num_peer_notif, all_slaves_active;
164 	__u8 lacp_rate, ad_select, tlb_dynamic_lb;
165 	__u16 ad_user_port_key, ad_actor_sys_prio;
166 	__u32 miimon, updelay, downdelay, arp_interval, arp_validate;
167 	__u32 arp_all_targets, resend_igmp, min_links, lp_interval;
168 	__u32 packets_per_slave;
169 	unsigned int ifindex;
170 
171 	while (argc > 0) {
172 		if (matches(*argv, "mode") == 0) {
173 			NEXT_ARG();
174 			if (get_index(mode_tbl, *argv) < 0)
175 				invarg("invalid mode", *argv);
176 			mode = get_index(mode_tbl, *argv);
177 			addattr8(n, 1024, IFLA_BOND_MODE, mode);
178 		} else if (matches(*argv, "active_slave") == 0) {
179 			NEXT_ARG();
180 			ifindex = if_nametoindex(*argv);
181 			if (!ifindex)
182 				return -1;
183 			addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, ifindex);
184 		} else if (matches(*argv, "clear_active_slave") == 0) {
185 			addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, 0);
186 		} else if (matches(*argv, "miimon") == 0) {
187 			NEXT_ARG();
188 			if (get_u32(&miimon, *argv, 0))
189 				invarg("invalid miimon", *argv);
190 			addattr32(n, 1024, IFLA_BOND_MIIMON, miimon);
191 		} else if (matches(*argv, "updelay") == 0) {
192 			NEXT_ARG();
193 			if (get_u32(&updelay, *argv, 0))
194 				invarg("invalid updelay", *argv);
195 			addattr32(n, 1024, IFLA_BOND_UPDELAY, updelay);
196 		} else if (matches(*argv, "downdelay") == 0) {
197 			NEXT_ARG();
198 			if (get_u32(&downdelay, *argv, 0))
199 				invarg("invalid downdelay", *argv);
200 			addattr32(n, 1024, IFLA_BOND_DOWNDELAY, downdelay);
201 		} else if (matches(*argv, "use_carrier") == 0) {
202 			NEXT_ARG();
203 			if (get_u8(&use_carrier, *argv, 0))
204 				invarg("invalid use_carrier", *argv);
205 			addattr8(n, 1024, IFLA_BOND_USE_CARRIER, use_carrier);
206 		} else if (matches(*argv, "arp_interval") == 0) {
207 			NEXT_ARG();
208 			if (get_u32(&arp_interval, *argv, 0))
209 				invarg("invalid arp_interval", *argv);
210 			addattr32(n, 1024, IFLA_BOND_ARP_INTERVAL, arp_interval);
211 		} else if (matches(*argv, "arp_ip_target") == 0) {
212 			struct rtattr *nest = addattr_nest(n, 1024,
213 				IFLA_BOND_ARP_IP_TARGET);
214 			if (NEXT_ARG_OK()) {
215 				NEXT_ARG();
216 				char *targets = strdupa(*argv);
217 				char *target = strtok(targets, ",");
218 				int i;
219 
220 				for (i = 0; target && i < BOND_MAX_ARP_TARGETS; i++) {
221 					__u32 addr = get_addr32(target);
222 
223 					addattr32(n, 1024, i, addr);
224 					target = strtok(NULL, ",");
225 				}
226 				addattr_nest_end(n, nest);
227 			}
228 			addattr_nest_end(n, nest);
229 		} else if (matches(*argv, "arp_validate") == 0) {
230 			NEXT_ARG();
231 			if (get_index(arp_validate_tbl, *argv) < 0)
232 				invarg("invalid arp_validate", *argv);
233 			arp_validate = get_index(arp_validate_tbl, *argv);
234 			addattr32(n, 1024, IFLA_BOND_ARP_VALIDATE, arp_validate);
235 		} else if (matches(*argv, "arp_all_targets") == 0) {
236 			NEXT_ARG();
237 			if (get_index(arp_all_targets_tbl, *argv) < 0)
238 				invarg("invalid arp_all_targets", *argv);
239 			arp_all_targets = get_index(arp_all_targets_tbl, *argv);
240 			addattr32(n, 1024, IFLA_BOND_ARP_ALL_TARGETS, arp_all_targets);
241 		} else if (matches(*argv, "primary") == 0) {
242 			NEXT_ARG();
243 			ifindex = if_nametoindex(*argv);
244 			if (!ifindex)
245 				return -1;
246 			addattr32(n, 1024, IFLA_BOND_PRIMARY, ifindex);
247 		} else if (matches(*argv, "primary_reselect") == 0) {
248 			NEXT_ARG();
249 			if (get_index(primary_reselect_tbl, *argv) < 0)
250 				invarg("invalid primary_reselect", *argv);
251 			primary_reselect = get_index(primary_reselect_tbl, *argv);
252 			addattr8(n, 1024, IFLA_BOND_PRIMARY_RESELECT,
253 				 primary_reselect);
254 		} else if (matches(*argv, "fail_over_mac") == 0) {
255 			NEXT_ARG();
256 			if (get_index(fail_over_mac_tbl, *argv) < 0)
257 				invarg("invalid fail_over_mac", *argv);
258 			fail_over_mac = get_index(fail_over_mac_tbl, *argv);
259 			addattr8(n, 1024, IFLA_BOND_FAIL_OVER_MAC,
260 				 fail_over_mac);
261 		} else if (matches(*argv, "xmit_hash_policy") == 0) {
262 			NEXT_ARG();
263 			if (get_index(xmit_hash_policy_tbl, *argv) < 0)
264 				invarg("invalid xmit_hash_policy", *argv);
265 
266 			xmit_hash_policy = get_index(xmit_hash_policy_tbl, *argv);
267 			addattr8(n, 1024, IFLA_BOND_XMIT_HASH_POLICY,
268 				 xmit_hash_policy);
269 		} else if (matches(*argv, "resend_igmp") == 0) {
270 			NEXT_ARG();
271 			if (get_u32(&resend_igmp, *argv, 0))
272 				invarg("invalid resend_igmp", *argv);
273 
274 			addattr32(n, 1024, IFLA_BOND_RESEND_IGMP, resend_igmp);
275 		} else if (matches(*argv, "num_grat_arp") == 0 ||
276 			   matches(*argv, "num_unsol_na") == 0) {
277 			NEXT_ARG();
278 			if (get_u8(&num_peer_notif, *argv, 0))
279 				invarg("invalid num_grat_arp|num_unsol_na",
280 				       *argv);
281 
282 			addattr8(n, 1024, IFLA_BOND_NUM_PEER_NOTIF,
283 				 num_peer_notif);
284 		} else if (matches(*argv, "all_slaves_active") == 0) {
285 			NEXT_ARG();
286 			if (get_u8(&all_slaves_active, *argv, 0))
287 				invarg("invalid all_slaves_active", *argv);
288 
289 			addattr8(n, 1024, IFLA_BOND_ALL_SLAVES_ACTIVE,
290 				 all_slaves_active);
291 		} else if (matches(*argv, "min_links") == 0) {
292 			NEXT_ARG();
293 			if (get_u32(&min_links, *argv, 0))
294 				invarg("invalid min_links", *argv);
295 
296 			addattr32(n, 1024, IFLA_BOND_MIN_LINKS, min_links);
297 		} else if (matches(*argv, "lp_interval") == 0) {
298 			NEXT_ARG();
299 			if (get_u32(&lp_interval, *argv, 0))
300 				invarg("invalid lp_interval", *argv);
301 
302 			addattr32(n, 1024, IFLA_BOND_LP_INTERVAL, lp_interval);
303 		} else if (matches(*argv, "packets_per_slave") == 0) {
304 			NEXT_ARG();
305 			if (get_u32(&packets_per_slave, *argv, 0))
306 				invarg("invalid packets_per_slave", *argv);
307 
308 			addattr32(n, 1024, IFLA_BOND_PACKETS_PER_SLAVE,
309 				  packets_per_slave);
310 		} else if (matches(*argv, "lacp_rate") == 0) {
311 			NEXT_ARG();
312 			if (get_index(lacp_rate_tbl, *argv) < 0)
313 				invarg("invalid lacp_rate", *argv);
314 
315 			lacp_rate = get_index(lacp_rate_tbl, *argv);
316 			addattr8(n, 1024, IFLA_BOND_AD_LACP_RATE, lacp_rate);
317 		} else if (matches(*argv, "ad_select") == 0) {
318 			NEXT_ARG();
319 			if (get_index(ad_select_tbl, *argv) < 0)
320 				invarg("invalid ad_select", *argv);
321 
322 			ad_select = get_index(ad_select_tbl, *argv);
323 			addattr8(n, 1024, IFLA_BOND_AD_SELECT, ad_select);
324 		} else if (matches(*argv, "ad_user_port_key") == 0) {
325 			NEXT_ARG();
326 			if (get_u16(&ad_user_port_key, *argv, 0))
327 				invarg("invalid ad_user_port_key", *argv);
328 
329 			addattr16(n, 1024, IFLA_BOND_AD_USER_PORT_KEY,
330 				  ad_user_port_key);
331 		} else if (matches(*argv, "ad_actor_sys_prio") == 0) {
332 			NEXT_ARG();
333 			if (get_u16(&ad_actor_sys_prio, *argv, 0))
334 				invarg("invalid ad_actor_sys_prio", *argv);
335 
336 			addattr16(n, 1024, IFLA_BOND_AD_ACTOR_SYS_PRIO,
337 				  ad_actor_sys_prio);
338 		} else if (matches(*argv, "ad_actor_system") == 0) {
339 			int len;
340 			char abuf[32];
341 
342 			NEXT_ARG();
343 			len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
344 			if (len < 0)
345 				return -1;
346 			addattr_l(n, 1024, IFLA_BOND_AD_ACTOR_SYSTEM,
347 				  abuf, len);
348 		} else if (matches(*argv, "tlb_dynamic_lb") == 0) {
349 			NEXT_ARG();
350 			if (get_u8(&tlb_dynamic_lb, *argv, 0)) {
351 				invarg("invalid tlb_dynamic_lb", *argv);
352 				return -1;
353 			}
354 			addattr8(n, 1024, IFLA_BOND_TLB_DYNAMIC_LB,
355 				 tlb_dynamic_lb);
356 		} else if (matches(*argv, "help") == 0) {
357 			explain();
358 			return -1;
359 		} else {
360 			fprintf(stderr, "bond: unknown command \"%s\"?\n", *argv);
361 			explain();
362 			return -1;
363 		}
364 		argc--, argv++;
365 	}
366 
367 	return 0;
368 }
369 
bond_print_opt(struct link_util * lu,FILE * f,struct rtattr * tb[])370 static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
371 {
372 	unsigned int ifindex;
373 
374 	if (!tb)
375 		return;
376 
377 	if (tb[IFLA_BOND_MODE]) {
378 		const char *mode = get_name(mode_tbl,
379 					    rta_getattr_u8(tb[IFLA_BOND_MODE]));
380 		print_string(PRINT_ANY, "mode", "mode %s ", mode);
381 	}
382 
383 	if (tb[IFLA_BOND_ACTIVE_SLAVE] &&
384 	    (ifindex = rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]))) {
385 		char buf[IFNAMSIZ];
386 		const char *n = if_indextoname(ifindex, buf);
387 
388 		if (n)
389 			print_string(PRINT_ANY,
390 				     "active_slave",
391 				     "active_slave %s ",
392 				     n);
393 		else
394 			print_uint(PRINT_ANY,
395 				   "active_slave_index",
396 				   "active_slave %u ",
397 				   ifindex);
398 	}
399 
400 	if (tb[IFLA_BOND_MIIMON])
401 		print_uint(PRINT_ANY,
402 			   "miimon",
403 			   "miimon %u ",
404 			   rta_getattr_u32(tb[IFLA_BOND_MIIMON]));
405 
406 	if (tb[IFLA_BOND_UPDELAY])
407 		print_uint(PRINT_ANY,
408 			   "updelay",
409 			   "updelay %u ",
410 			   rta_getattr_u32(tb[IFLA_BOND_UPDELAY]));
411 
412 	if (tb[IFLA_BOND_DOWNDELAY])
413 		print_uint(PRINT_ANY,
414 			   "downdelay",
415 			   "downdelay %u ",
416 			   rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY]));
417 
418 	if (tb[IFLA_BOND_USE_CARRIER])
419 		print_uint(PRINT_ANY,
420 			   "use_carrier",
421 			   "use_carrier %u ",
422 			   rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER]));
423 
424 	if (tb[IFLA_BOND_ARP_INTERVAL])
425 		print_uint(PRINT_ANY,
426 			   "arp_interval",
427 			   "arp_interval %u ",
428 			   rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL]));
429 
430 	if (tb[IFLA_BOND_ARP_IP_TARGET]) {
431 		struct rtattr *iptb[BOND_MAX_ARP_TARGETS + 1];
432 		int i;
433 
434 		parse_rtattr_nested(iptb, BOND_MAX_ARP_TARGETS,
435 				    tb[IFLA_BOND_ARP_IP_TARGET]);
436 
437 		if (iptb[0]) {
438 			open_json_array(PRINT_JSON, "arp_ip_target");
439 			print_string(PRINT_FP, NULL, "arp_ip_target ", NULL);
440 		}
441 
442 		for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
443 			if (iptb[i])
444 				print_string(PRINT_ANY,
445 					     NULL,
446 					     "%s",
447 					     rt_addr_n2a_rta(AF_INET, iptb[i]));
448 			if (!is_json_context()
449 			    && i < BOND_MAX_ARP_TARGETS-1
450 			    && iptb[i+1])
451 				fprintf(f, ",");
452 		}
453 
454 		if (iptb[0]) {
455 			print_string(PRINT_FP, NULL, " ", NULL);
456 			close_json_array(PRINT_JSON, NULL);
457 		}
458 	}
459 
460 	if (tb[IFLA_BOND_ARP_VALIDATE]) {
461 		__u32 arp_v = rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE]);
462 		const char *arp_validate = get_name(arp_validate_tbl, arp_v);
463 
464 		if (!arp_v && is_json_context())
465 			print_null(PRINT_JSON, "arp_validate", NULL, NULL);
466 		else
467 			print_string(PRINT_ANY,
468 				     "arp_validate",
469 				     "arp_validate %s ",
470 				     arp_validate);
471 	}
472 
473 	if (tb[IFLA_BOND_ARP_ALL_TARGETS]) {
474 		const char *arp_all_targets = get_name(arp_all_targets_tbl,
475 						       rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS]));
476 		print_string(PRINT_ANY,
477 			     "arp_all_targets",
478 			     "arp_all_targets %s ",
479 			     arp_all_targets);
480 	}
481 
482 	if (tb[IFLA_BOND_PRIMARY] &&
483 	    (ifindex = rta_getattr_u32(tb[IFLA_BOND_PRIMARY]))) {
484 		char buf[IFNAMSIZ];
485 		const char *n = if_indextoname(ifindex, buf);
486 
487 		if (n)
488 			print_string(PRINT_ANY, "primary", "primary %s ", n);
489 		else
490 			print_uint(PRINT_ANY,
491 				   "primary_index",
492 				   "primary %u ",
493 				   ifindex);
494 	}
495 
496 	if (tb[IFLA_BOND_PRIMARY_RESELECT]) {
497 		const char *primary_reselect = get_name(primary_reselect_tbl,
498 							rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT]));
499 		print_string(PRINT_ANY,
500 			     "primary_reselect",
501 			     "primary_reselect %s ",
502 			     primary_reselect);
503 	}
504 
505 	if (tb[IFLA_BOND_FAIL_OVER_MAC]) {
506 		const char *fail_over_mac = get_name(fail_over_mac_tbl,
507 						     rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC]));
508 		print_string(PRINT_ANY,
509 			     "fail_over_mac",
510 			     "fail_over_mac %s ",
511 			     fail_over_mac);
512 	}
513 
514 	if (tb[IFLA_BOND_XMIT_HASH_POLICY]) {
515 		const char *xmit_hash_policy = get_name(xmit_hash_policy_tbl,
516 							rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY]));
517 		print_string(PRINT_ANY,
518 			     "xmit_hash_policy",
519 			     "xmit_hash_policy %s ",
520 			     xmit_hash_policy);
521 	}
522 
523 	if (tb[IFLA_BOND_RESEND_IGMP])
524 		print_uint(PRINT_ANY,
525 			   "resend_igmp",
526 			   "resend_igmp %u ",
527 			   rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP]));
528 
529 	if (tb[IFLA_BOND_NUM_PEER_NOTIF])
530 		print_uint(PRINT_ANY,
531 			   "num_peer_notif",
532 			   "num_grat_arp %u ",
533 			   rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF]));
534 
535 	if (tb[IFLA_BOND_ALL_SLAVES_ACTIVE])
536 		print_uint(PRINT_ANY,
537 			   "all_slaves_active",
538 			   "all_slaves_active %u ",
539 			   rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE]));
540 
541 	if (tb[IFLA_BOND_MIN_LINKS])
542 		print_uint(PRINT_ANY,
543 			   "min_links",
544 			   "min_links %u ",
545 			   rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS]));
546 
547 	if (tb[IFLA_BOND_LP_INTERVAL])
548 		print_uint(PRINT_ANY,
549 			   "lp_interval",
550 			   "lp_interval %u ",
551 			   rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL]));
552 
553 	if (tb[IFLA_BOND_PACKETS_PER_SLAVE])
554 		print_uint(PRINT_ANY,
555 			   "packets_per_slave",
556 			   "packets_per_slave %u ",
557 			   rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE]));
558 
559 	if (tb[IFLA_BOND_AD_LACP_RATE]) {
560 		const char *lacp_rate = get_name(lacp_rate_tbl,
561 						 rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE]));
562 		print_string(PRINT_ANY,
563 			     "ad_lacp_rate",
564 			     "lacp_rate %s ",
565 			     lacp_rate);
566 	}
567 
568 	if (tb[IFLA_BOND_AD_SELECT]) {
569 		const char *ad_select = get_name(ad_select_tbl,
570 						 rta_getattr_u8(tb[IFLA_BOND_AD_SELECT]));
571 		print_string(PRINT_ANY,
572 			     "ad_select",
573 			     "ad_select %s ",
574 			     ad_select);
575 	}
576 
577 	if (tb[IFLA_BOND_AD_INFO]) {
578 		struct rtattr *adtb[IFLA_BOND_AD_INFO_MAX + 1];
579 
580 		parse_rtattr_nested(adtb, IFLA_BOND_AD_INFO_MAX,
581 				    tb[IFLA_BOND_AD_INFO]);
582 
583 		open_json_object("ad_info");
584 
585 		if (adtb[IFLA_BOND_AD_INFO_AGGREGATOR])
586 			print_int(PRINT_ANY,
587 				  "aggregator",
588 				  "ad_aggregator %d ",
589 				  rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR]));
590 
591 		if (adtb[IFLA_BOND_AD_INFO_NUM_PORTS])
592 			print_int(PRINT_ANY,
593 				  "num_ports",
594 				  "ad_num_ports %d ",
595 				  rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS]));
596 
597 		if (adtb[IFLA_BOND_AD_INFO_ACTOR_KEY])
598 			print_int(PRINT_ANY,
599 				  "actor_key",
600 				  "ad_actor_key %d ",
601 				  rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]));
602 
603 		if (adtb[IFLA_BOND_AD_INFO_PARTNER_KEY])
604 			print_int(PRINT_ANY,
605 				  "partner_key",
606 				  "ad_partner_key %d ",
607 				  rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]));
608 
609 		if (adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]) {
610 			unsigned char *p =
611 				RTA_DATA(adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]);
612 			SPRINT_BUF(b);
613 			print_string(PRINT_ANY,
614 				     "partner_mac",
615 				     "ad_partner_mac %s ",
616 				     ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b)));
617 		}
618 
619 		close_json_object();
620 	}
621 
622 	if (tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]) {
623 		print_uint(PRINT_ANY,
624 			   "ad_actor_sys_prio",
625 			   "ad_actor_sys_prio %u ",
626 			   rta_getattr_u16(tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]));
627 	}
628 
629 	if (tb[IFLA_BOND_AD_USER_PORT_KEY]) {
630 		print_uint(PRINT_ANY,
631 			   "ad_user_port_key",
632 			   "ad_user_port_key %u ",
633 			   rta_getattr_u16(tb[IFLA_BOND_AD_USER_PORT_KEY]));
634 	}
635 
636 	if (tb[IFLA_BOND_AD_ACTOR_SYSTEM]) {
637 		/* We assume the l2 address is an Ethernet MAC address */
638 		SPRINT_BUF(b1);
639 
640 		print_string(PRINT_ANY,
641 			     "ad_actor_system",
642 			     "ad_actor_system %s ",
643 			     ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
644 					 RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
645 					 1 /*ARPHDR_ETHER*/, b1, sizeof(b1)));
646 	}
647 
648 	if (tb[IFLA_BOND_TLB_DYNAMIC_LB]) {
649 		print_uint(PRINT_ANY,
650 			   "tlb_dynamic_lb",
651 			   "tlb_dynamic_lb %u ",
652 			   rta_getattr_u8(tb[IFLA_BOND_TLB_DYNAMIC_LB]));
653 	}
654 }
655 
bond_print_help(struct link_util * lu,int argc,char ** argv,FILE * f)656 static void bond_print_help(struct link_util *lu, int argc, char **argv,
657 			    FILE *f)
658 {
659 	print_explain(f);
660 }
661 
662 struct link_util bond_link_util = {
663 	.id		= "bond",
664 	.maxattr	= IFLA_BOND_MAX,
665 	.parse_opt	= bond_parse_opt,
666 	.print_opt	= bond_print_opt,
667 	.print_help	= bond_print_help,
668 };
669