Home | History | Annotate | Download | only in ip
      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 (at) resnulli.us>
     10  *              Scott Feldman <sfeldma (at) 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 		"                [ 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 
    154 static void explain(void)
    155 {
    156 	print_explain(stderr);
    157 }
    158 
    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 
    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 
    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