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 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 addattr32(n, 1024, i, addr); 223 target = strtok(NULL, ","); 224 } 225 addattr_nest_end(n, nest); 226 } 227 addattr_nest_end(n, nest); 228 } else if (matches(*argv, "arp_validate") == 0) { 229 NEXT_ARG(); 230 if (get_index(arp_validate_tbl, *argv) < 0) 231 invarg("invalid arp_validate", *argv); 232 arp_validate = get_index(arp_validate_tbl, *argv); 233 addattr32(n, 1024, IFLA_BOND_ARP_VALIDATE, arp_validate); 234 } else if (matches(*argv, "arp_all_targets") == 0) { 235 NEXT_ARG(); 236 if (get_index(arp_all_targets_tbl, *argv) < 0) 237 invarg("invalid arp_all_targets", *argv); 238 arp_all_targets = get_index(arp_all_targets_tbl, *argv); 239 addattr32(n, 1024, IFLA_BOND_ARP_ALL_TARGETS, arp_all_targets); 240 } else if (matches(*argv, "primary") == 0) { 241 NEXT_ARG(); 242 ifindex = if_nametoindex(*argv); 243 if (!ifindex) 244 return -1; 245 addattr32(n, 1024, IFLA_BOND_PRIMARY, ifindex); 246 } else if (matches(*argv, "primary_reselect") == 0) { 247 NEXT_ARG(); 248 if (get_index(primary_reselect_tbl, *argv) < 0) 249 invarg("invalid primary_reselect", *argv); 250 primary_reselect = get_index(primary_reselect_tbl, *argv); 251 addattr8(n, 1024, IFLA_BOND_PRIMARY_RESELECT, 252 primary_reselect); 253 } else if (matches(*argv, "fail_over_mac") == 0) { 254 NEXT_ARG(); 255 if (get_index(fail_over_mac_tbl, *argv) < 0) 256 invarg("invalid fail_over_mac", *argv); 257 fail_over_mac = get_index(fail_over_mac_tbl, *argv); 258 addattr8(n, 1024, IFLA_BOND_FAIL_OVER_MAC, 259 fail_over_mac); 260 } else if (matches(*argv, "xmit_hash_policy") == 0) { 261 NEXT_ARG(); 262 if (get_index(xmit_hash_policy_tbl, *argv) < 0) 263 invarg("invalid xmit_hash_policy", *argv); 264 265 xmit_hash_policy = get_index(xmit_hash_policy_tbl, *argv); 266 addattr8(n, 1024, IFLA_BOND_XMIT_HASH_POLICY, 267 xmit_hash_policy); 268 } else if (matches(*argv, "resend_igmp") == 0) { 269 NEXT_ARG(); 270 if (get_u32(&resend_igmp, *argv, 0)) 271 invarg("invalid resend_igmp", *argv); 272 273 addattr32(n, 1024, IFLA_BOND_RESEND_IGMP, resend_igmp); 274 } else if (matches(*argv, "num_grat_arp") == 0 || 275 matches(*argv, "num_unsol_na") == 0) { 276 NEXT_ARG(); 277 if (get_u8(&num_peer_notif, *argv, 0)) 278 invarg("invalid num_grat_arp|num_unsol_na", 279 *argv); 280 281 addattr8(n, 1024, IFLA_BOND_NUM_PEER_NOTIF, 282 num_peer_notif); 283 } else if (matches(*argv, "all_slaves_active") == 0) { 284 NEXT_ARG(); 285 if (get_u8(&all_slaves_active, *argv, 0)) 286 invarg("invalid all_slaves_active", *argv); 287 288 addattr8(n, 1024, IFLA_BOND_ALL_SLAVES_ACTIVE, 289 all_slaves_active); 290 } else if (matches(*argv, "min_links") == 0) { 291 NEXT_ARG(); 292 if (get_u32(&min_links, *argv, 0)) 293 invarg("invalid min_links", *argv); 294 295 addattr32(n, 1024, IFLA_BOND_MIN_LINKS, min_links); 296 } else if (matches(*argv, "lp_interval") == 0) { 297 NEXT_ARG(); 298 if (get_u32(&lp_interval, *argv, 0)) 299 invarg("invalid lp_interval", *argv); 300 301 addattr32(n, 1024, IFLA_BOND_LP_INTERVAL, lp_interval); 302 } else if (matches(*argv, "packets_per_slave") == 0) { 303 NEXT_ARG(); 304 if (get_u32(&packets_per_slave, *argv, 0)) 305 invarg("invalid packets_per_slave", *argv); 306 307 addattr32(n, 1024, IFLA_BOND_PACKETS_PER_SLAVE, 308 packets_per_slave); 309 } else if (matches(*argv, "lacp_rate") == 0) { 310 NEXT_ARG(); 311 if (get_index(lacp_rate_tbl, *argv) < 0) 312 invarg("invalid lacp_rate", *argv); 313 314 lacp_rate = get_index(lacp_rate_tbl, *argv); 315 addattr8(n, 1024, IFLA_BOND_AD_LACP_RATE, lacp_rate); 316 } else if (matches(*argv, "ad_select") == 0) { 317 NEXT_ARG(); 318 if (get_index(ad_select_tbl, *argv) < 0) 319 invarg("invalid ad_select", *argv); 320 321 ad_select = get_index(ad_select_tbl, *argv); 322 addattr8(n, 1024, IFLA_BOND_AD_SELECT, ad_select); 323 } else if (matches(*argv, "ad_user_port_key") == 0) { 324 NEXT_ARG(); 325 if (get_u16(&ad_user_port_key, *argv, 0)) 326 invarg("invalid ad_user_port_key", *argv); 327 328 addattr16(n, 1024, IFLA_BOND_AD_USER_PORT_KEY, 329 ad_user_port_key); 330 } else if (matches(*argv, "ad_actor_sys_prio") == 0) { 331 NEXT_ARG(); 332 if (get_u16(&ad_actor_sys_prio, *argv, 0)) 333 invarg("invalid ad_actor_sys_prio", *argv); 334 335 addattr16(n, 1024, IFLA_BOND_AD_ACTOR_SYS_PRIO, 336 ad_actor_sys_prio); 337 } else if (matches(*argv, "ad_actor_system") == 0) { 338 int len; 339 char abuf[32]; 340 341 NEXT_ARG(); 342 len = ll_addr_a2n(abuf, sizeof(abuf), *argv); 343 if (len < 0) 344 return -1; 345 addattr_l(n, 1024, IFLA_BOND_AD_ACTOR_SYSTEM, 346 abuf, len); 347 } else if (matches(*argv, "tlb_dynamic_lb") == 0) { 348 NEXT_ARG(); 349 if (get_u8(&tlb_dynamic_lb, *argv, 0)) { 350 invarg("invalid tlb_dynamic_lb", *argv); 351 return -1; 352 } 353 addattr8(n, 1024, IFLA_BOND_TLB_DYNAMIC_LB, 354 tlb_dynamic_lb); 355 } else if (matches(*argv, "help") == 0) { 356 explain(); 357 return -1; 358 } else { 359 fprintf(stderr, "bond: unknown command \"%s\"?\n", *argv); 360 explain(); 361 return -1; 362 } 363 argc--, argv++; 364 } 365 366 return 0; 367 } 368 369 static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) 370 { 371 unsigned ifindex; 372 373 if (!tb) 374 return; 375 376 if (tb[IFLA_BOND_MODE]) { 377 const char *mode = get_name(mode_tbl, 378 rta_getattr_u8(tb[IFLA_BOND_MODE])); 379 fprintf(f, "mode %s ", mode); 380 } 381 382 if (tb[IFLA_BOND_ACTIVE_SLAVE] && 383 (ifindex = rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]))) { 384 char buf[IFNAMSIZ]; 385 const char *n = if_indextoname(ifindex, buf); 386 387 if (n) 388 fprintf(f, "active_slave %s ", n); 389 else 390 fprintf(f, "active_slave %u ", ifindex); 391 } 392 393 if (tb[IFLA_BOND_MIIMON]) 394 fprintf(f, "miimon %u ", rta_getattr_u32(tb[IFLA_BOND_MIIMON])); 395 396 if (tb[IFLA_BOND_UPDELAY]) 397 fprintf(f, "updelay %u ", rta_getattr_u32(tb[IFLA_BOND_UPDELAY])); 398 399 if (tb[IFLA_BOND_DOWNDELAY]) 400 fprintf(f, "downdelay %u ", 401 rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY])); 402 403 if (tb[IFLA_BOND_USE_CARRIER]) 404 fprintf(f, "use_carrier %u ", 405 rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER])); 406 407 if (tb[IFLA_BOND_ARP_INTERVAL]) 408 fprintf(f, "arp_interval %u ", 409 rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL])); 410 411 if (tb[IFLA_BOND_ARP_IP_TARGET]) { 412 struct rtattr *iptb[BOND_MAX_ARP_TARGETS + 1]; 413 char buf[INET_ADDRSTRLEN]; 414 int i; 415 416 parse_rtattr_nested(iptb, BOND_MAX_ARP_TARGETS, 417 tb[IFLA_BOND_ARP_IP_TARGET]); 418 419 if (iptb[0]) 420 fprintf(f, "arp_ip_target "); 421 422 for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) { 423 if (iptb[i]) 424 fprintf(f, "%s", 425 rt_addr_n2a(AF_INET, 426 RTA_PAYLOAD(iptb[i]), 427 RTA_DATA(iptb[i]), 428 buf, 429 INET_ADDRSTRLEN)); 430 if (i < BOND_MAX_ARP_TARGETS-1 && iptb[i+1]) 431 fprintf(f, ","); 432 } 433 434 if (iptb[0]) 435 fprintf(f, " "); 436 } 437 438 if (tb[IFLA_BOND_ARP_VALIDATE]) { 439 const char *arp_validate = get_name(arp_validate_tbl, 440 rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE])); 441 fprintf(f, "arp_validate %s ", arp_validate); 442 } 443 444 if (tb[IFLA_BOND_ARP_ALL_TARGETS]) { 445 const char *arp_all_targets = get_name(arp_all_targets_tbl, 446 rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS])); 447 fprintf(f, "arp_all_targets %s ", arp_all_targets); 448 } 449 450 if (tb[IFLA_BOND_PRIMARY] && 451 (ifindex = rta_getattr_u32(tb[IFLA_BOND_PRIMARY]))) { 452 char buf[IFNAMSIZ]; 453 const char *n = if_indextoname(ifindex, buf); 454 455 if (n) 456 fprintf(f, "primary %s ", n); 457 else 458 fprintf(f, "primary %u ", ifindex); 459 } 460 461 if (tb[IFLA_BOND_PRIMARY_RESELECT]) { 462 const char *primary_reselect = get_name(primary_reselect_tbl, 463 rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT])); 464 fprintf(f, "primary_reselect %s ", primary_reselect); 465 } 466 467 if (tb[IFLA_BOND_FAIL_OVER_MAC]) { 468 const char *fail_over_mac = get_name(fail_over_mac_tbl, 469 rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC])); 470 fprintf(f, "fail_over_mac %s ", fail_over_mac); 471 } 472 473 if (tb[IFLA_BOND_XMIT_HASH_POLICY]) { 474 const char *xmit_hash_policy = get_name(xmit_hash_policy_tbl, 475 rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY])); 476 fprintf(f, "xmit_hash_policy %s ", xmit_hash_policy); 477 } 478 479 if (tb[IFLA_BOND_RESEND_IGMP]) 480 fprintf(f, "resend_igmp %u ", 481 rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP])); 482 483 if (tb[IFLA_BOND_NUM_PEER_NOTIF]) 484 fprintf(f, "num_grat_arp %u ", 485 rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF])); 486 487 if (tb[IFLA_BOND_ALL_SLAVES_ACTIVE]) 488 fprintf(f, "all_slaves_active %u ", 489 rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE])); 490 491 if (tb[IFLA_BOND_MIN_LINKS]) 492 fprintf(f, "min_links %u ", 493 rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS])); 494 495 if (tb[IFLA_BOND_LP_INTERVAL]) 496 fprintf(f, "lp_interval %u ", 497 rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL])); 498 499 if (tb[IFLA_BOND_PACKETS_PER_SLAVE]) 500 fprintf(f, "packets_per_slave %u ", 501 rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE])); 502 503 if (tb[IFLA_BOND_AD_LACP_RATE]) { 504 const char *lacp_rate = get_name(lacp_rate_tbl, 505 rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE])); 506 fprintf(f, "lacp_rate %s ", lacp_rate); 507 } 508 509 if (tb[IFLA_BOND_AD_SELECT]) { 510 const char *ad_select = get_name(ad_select_tbl, 511 rta_getattr_u8(tb[IFLA_BOND_AD_SELECT])); 512 fprintf(f, "ad_select %s ", ad_select); 513 } 514 515 if (tb[IFLA_BOND_AD_INFO]) { 516 struct rtattr *adtb[IFLA_BOND_AD_INFO_MAX + 1]; 517 518 parse_rtattr_nested(adtb, IFLA_BOND_AD_INFO_MAX, 519 tb[IFLA_BOND_AD_INFO]); 520 521 if (adtb[IFLA_BOND_AD_INFO_AGGREGATOR]) 522 fprintf(f, "ad_aggregator %d ", 523 rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR])); 524 525 if (adtb[IFLA_BOND_AD_INFO_NUM_PORTS]) 526 fprintf(f, "ad_num_ports %d ", 527 rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS])); 528 529 if (adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]) 530 fprintf(f, "ad_actor_key %d ", 531 rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY])); 532 533 if (adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]) 534 fprintf(f, "ad_partner_key %d ", 535 rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY])); 536 537 if (adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]) { 538 unsigned char *p = 539 RTA_DATA(adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]); 540 SPRINT_BUF(b); 541 fprintf(f, "ad_partner_mac %s ", 542 ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b))); 543 } 544 } 545 546 if (tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]) { 547 fprintf(f, "ad_actor_sys_prio %u ", 548 rta_getattr_u16(tb[IFLA_BOND_AD_ACTOR_SYS_PRIO])); 549 } 550 551 if (tb[IFLA_BOND_AD_USER_PORT_KEY]) { 552 fprintf(f, "ad_user_port_key %u ", 553 rta_getattr_u16(tb[IFLA_BOND_AD_USER_PORT_KEY])); 554 } 555 556 if (tb[IFLA_BOND_AD_ACTOR_SYSTEM]) { 557 /* We assume the l2 address is an Ethernet MAC address */ 558 SPRINT_BUF(b1); 559 fprintf(f, "ad_actor_system %s ", 560 ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_AD_ACTOR_SYSTEM]), 561 RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]), 562 1 /*ARPHDR_ETHER*/, b1, sizeof(b1))); 563 } 564 565 if (tb[IFLA_BOND_TLB_DYNAMIC_LB]) { 566 fprintf(f, "tlb_dynamic_lb %u ", 567 rta_getattr_u8(tb[IFLA_BOND_TLB_DYNAMIC_LB])); 568 } 569 } 570 571 static void bond_print_help(struct link_util *lu, int argc, char **argv, 572 FILE *f) 573 { 574 print_explain(f); 575 } 576 577 struct link_util bond_link_util = { 578 .id = "bond", 579 .maxattr = IFLA_BOND_MAX, 580 .parse_opt = bond_parse_opt, 581 .print_opt = bond_print_opt, 582 .print_help = bond_print_help, 583 }; 584