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