1
2
3
4
5
6
7
8
9
10
11
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <linux/if_bonding.h>
17
18#include "rt_names.h"
19#include "utils.h"
20#include "ip_common.h"
21#include "json_print.h"
22
23#define BOND_MAX_ARP_TARGETS 16
24
25static unsigned int xstats_print_attr;
26static int filter_index;
27
28static const char *mode_tbl[] = {
29 "balance-rr",
30 "active-backup",
31 "balance-xor",
32 "broadcast",
33 "802.3ad",
34 "balance-tlb",
35 "balance-alb",
36 NULL,
37};
38
39static const char *arp_validate_tbl[] = {
40 "none",
41 "active",
42 "backup",
43 "all",
44 "filter",
45 "filter_active",
46 "filter_backup",
47 NULL,
48};
49
50static const char *arp_all_targets_tbl[] = {
51 "any",
52 "all",
53 NULL,
54};
55
56static const char *primary_reselect_tbl[] = {
57 "always",
58 "better",
59 "failure",
60 NULL,
61};
62
63static const char *fail_over_mac_tbl[] = {
64 "none",
65 "active",
66 "follow",
67 NULL,
68};
69
70static const char *xmit_hash_policy_tbl[] = {
71 "layer2",
72 "layer3+4",
73 "layer2+3",
74 "encap2+3",
75 "encap3+4",
76 "vlan+srcmac",
77 NULL,
78};
79
80static const char *lacp_active_tbl[] = {
81 "off",
82 "on",
83 NULL,
84};
85
86static const char *lacp_rate_tbl[] = {
87 "slow",
88 "fast",
89 NULL,
90};
91
92static const char *ad_select_tbl[] = {
93 "stable",
94 "bandwidth",
95 "count",
96 NULL,
97};
98
99static const char *get_name(const char **tbl, int index)
100{
101 int i;
102
103 for (i = 0; tbl[i]; i++)
104 if (i == index)
105 return tbl[i];
106
107 return "UNKNOWN";
108}
109
110static int get_index(const char **tbl, char *name)
111{
112 int i, index;
113
114
115 if (get_integer(&index, name, 10) == 0)
116 for (i = 0; tbl[i]; i++)
117 if (i == index)
118 return i;
119
120 for (i = 0; tbl[i]; i++)
121 if (strcmp(tbl[i], name) == 0)
122 return i;
123
124 return -1;
125}
126
127static void print_explain(FILE *f)
128{
129 fprintf(f,
130 "Usage: ... bond [ mode BONDMODE ] [ active_slave SLAVE_DEV ]\n"
131 " [ clear_active_slave ] [ miimon MIIMON ]\n"
132 " [ updelay UPDELAY ] [ downdelay DOWNDELAY ]\n"
133 " [ peer_notify_delay DELAY ]\n"
134 " [ use_carrier USE_CARRIER ]\n"
135 " [ arp_interval ARP_INTERVAL ]\n"
136 " [ arp_validate ARP_VALIDATE ]\n"
137 " [ arp_all_targets ARP_ALL_TARGETS ]\n"
138 " [ arp_ip_target [ ARP_IP_TARGET, ... ] ]\n"
139 " [ primary SLAVE_DEV ]\n"
140 " [ primary_reselect PRIMARY_RESELECT ]\n"
141 " [ fail_over_mac FAIL_OVER_MAC ]\n"
142 " [ xmit_hash_policy XMIT_HASH_POLICY ]\n"
143 " [ resend_igmp RESEND_IGMP ]\n"
144 " [ num_grat_arp|num_unsol_na NUM_GRAT_ARP|NUM_UNSOL_NA ]\n"
145 " [ all_slaves_active ALL_SLAVES_ACTIVE ]\n"
146 " [ min_links MIN_LINKS ]\n"
147 " [ lp_interval LP_INTERVAL ]\n"
148 " [ packets_per_slave PACKETS_PER_SLAVE ]\n"
149 " [ tlb_dynamic_lb TLB_DYNAMIC_LB ]\n"
150 " [ lacp_rate LACP_RATE ]\n"
151 " [ lacp_active LACP_ACTIVE]\n"
152 " [ ad_select AD_SELECT ]\n"
153 " [ ad_user_port_key PORTKEY ]\n"
154 " [ ad_actor_sys_prio SYSPRIO ]\n"
155 " [ ad_actor_system LLADDR ]\n"
156 "\n"
157 "BONDMODE := balance-rr|active-backup|balance-xor|broadcast|802.3ad|balance-tlb|balance-alb\n"
158 "ARP_VALIDATE := none|active|backup|all|filter|filter_active|filter_backup\n"
159 "ARP_ALL_TARGETS := any|all\n"
160 "PRIMARY_RESELECT := always|better|failure\n"
161 "FAIL_OVER_MAC := none|active|follow\n"
162 "XMIT_HASH_POLICY := layer2|layer2+3|layer3+4|encap2+3|encap3+4|vlan+srcmac\n"
163 "LACP_ACTIVE := off|on\n"
164 "LACP_RATE := slow|fast\n"
165 "AD_SELECT := stable|bandwidth|count\n"
166 );
167}
168
169static void explain(void)
170{
171 print_explain(stderr);
172}
173
174static int bond_parse_opt(struct link_util *lu, int argc, char **argv,
175 struct nlmsghdr *n)
176{
177 __u8 mode, use_carrier, primary_reselect, fail_over_mac;
178 __u8 xmit_hash_policy, num_peer_notif, all_slaves_active;
179 __u8 lacp_active, lacp_rate, ad_select, tlb_dynamic_lb;
180 __u16 ad_user_port_key, ad_actor_sys_prio;
181 __u32 miimon, updelay, downdelay, peer_notify_delay, arp_interval, arp_validate;
182 __u32 arp_all_targets, resend_igmp, min_links, lp_interval;
183 __u32 packets_per_slave;
184 unsigned int ifindex;
185
186 while (argc > 0) {
187 if (matches(*argv, "mode") == 0) {
188 NEXT_ARG();
189 if (get_index(mode_tbl, *argv) < 0)
190 invarg("invalid mode", *argv);
191 mode = get_index(mode_tbl, *argv);
192 addattr8(n, 1024, IFLA_BOND_MODE, mode);
193 } else if (matches(*argv, "active_slave") == 0) {
194 NEXT_ARG();
195 ifindex = ll_name_to_index(*argv);
196 if (!ifindex)
197 return nodev(*argv);
198 addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, ifindex);
199 } else if (matches(*argv, "clear_active_slave") == 0) {
200 addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, 0);
201 } else if (matches(*argv, "miimon") == 0) {
202 NEXT_ARG();
203 if (get_u32(&miimon, *argv, 0))
204 invarg("invalid miimon", *argv);
205 addattr32(n, 1024, IFLA_BOND_MIIMON, miimon);
206 } else if (matches(*argv, "updelay") == 0) {
207 NEXT_ARG();
208 if (get_u32(&updelay, *argv, 0))
209 invarg("invalid updelay", *argv);
210 addattr32(n, 1024, IFLA_BOND_UPDELAY, updelay);
211 } else if (matches(*argv, "downdelay") == 0) {
212 NEXT_ARG();
213 if (get_u32(&downdelay, *argv, 0))
214 invarg("invalid downdelay", *argv);
215 addattr32(n, 1024, IFLA_BOND_DOWNDELAY, downdelay);
216 } else if (matches(*argv, "peer_notify_delay") == 0) {
217 NEXT_ARG();
218 if (get_u32(&peer_notify_delay, *argv, 0))
219 invarg("invalid peer_notify_delay", *argv);
220 addattr32(n, 1024, IFLA_BOND_PEER_NOTIF_DELAY, peer_notify_delay);
221 } else if (matches(*argv, "use_carrier") == 0) {
222 NEXT_ARG();
223 if (get_u8(&use_carrier, *argv, 0))
224 invarg("invalid use_carrier", *argv);
225 addattr8(n, 1024, IFLA_BOND_USE_CARRIER, use_carrier);
226 } else if (matches(*argv, "arp_interval") == 0) {
227 NEXT_ARG();
228 if (get_u32(&arp_interval, *argv, 0))
229 invarg("invalid arp_interval", *argv);
230 addattr32(n, 1024, IFLA_BOND_ARP_INTERVAL, arp_interval);
231 } else if (matches(*argv, "arp_ip_target") == 0) {
232 struct rtattr *nest = addattr_nest(n, 1024,
233 IFLA_BOND_ARP_IP_TARGET);
234 if (NEXT_ARG_OK()) {
235 NEXT_ARG();
236 char *targets = strdupa(*argv);
237 char *target = strtok(targets, ",");
238 int i;
239
240 for (i = 0; target && i < BOND_MAX_ARP_TARGETS; i++) {
241 __u32 addr = get_addr32(target);
242
243 addattr32(n, 1024, i, addr);
244 target = strtok(NULL, ",");
245 }
246 addattr_nest_end(n, nest);
247 }
248 addattr_nest_end(n, nest);
249 } else if (matches(*argv, "arp_validate") == 0) {
250 NEXT_ARG();
251 if (get_index(arp_validate_tbl, *argv) < 0)
252 invarg("invalid arp_validate", *argv);
253 arp_validate = get_index(arp_validate_tbl, *argv);
254 addattr32(n, 1024, IFLA_BOND_ARP_VALIDATE, arp_validate);
255 } else if (matches(*argv, "arp_all_targets") == 0) {
256 NEXT_ARG();
257 if (get_index(arp_all_targets_tbl, *argv) < 0)
258 invarg("invalid arp_all_targets", *argv);
259 arp_all_targets = get_index(arp_all_targets_tbl, *argv);
260 addattr32(n, 1024, IFLA_BOND_ARP_ALL_TARGETS, arp_all_targets);
261 } else if (matches(*argv, "primary") == 0) {
262 NEXT_ARG();
263 ifindex = ll_name_to_index(*argv);
264 if (!ifindex)
265 return nodev(*argv);
266 addattr32(n, 1024, IFLA_BOND_PRIMARY, ifindex);
267 } else if (matches(*argv, "primary_reselect") == 0) {
268 NEXT_ARG();
269 if (get_index(primary_reselect_tbl, *argv) < 0)
270 invarg("invalid primary_reselect", *argv);
271 primary_reselect = get_index(primary_reselect_tbl, *argv);
272 addattr8(n, 1024, IFLA_BOND_PRIMARY_RESELECT,
273 primary_reselect);
274 } else if (matches(*argv, "fail_over_mac") == 0) {
275 NEXT_ARG();
276 if (get_index(fail_over_mac_tbl, *argv) < 0)
277 invarg("invalid fail_over_mac", *argv);
278 fail_over_mac = get_index(fail_over_mac_tbl, *argv);
279 addattr8(n, 1024, IFLA_BOND_FAIL_OVER_MAC,
280 fail_over_mac);
281 } else if (matches(*argv, "xmit_hash_policy") == 0) {
282 NEXT_ARG();
283 if (get_index(xmit_hash_policy_tbl, *argv) < 0)
284 invarg("invalid xmit_hash_policy", *argv);
285
286 xmit_hash_policy = get_index(xmit_hash_policy_tbl, *argv);
287 addattr8(n, 1024, IFLA_BOND_XMIT_HASH_POLICY,
288 xmit_hash_policy);
289 } else if (matches(*argv, "resend_igmp") == 0) {
290 NEXT_ARG();
291 if (get_u32(&resend_igmp, *argv, 0))
292 invarg("invalid resend_igmp", *argv);
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
302 addattr8(n, 1024, IFLA_BOND_NUM_PEER_NOTIF,
303 num_peer_notif);
304 } else if (matches(*argv, "all_slaves_active") == 0) {
305 NEXT_ARG();
306 if (get_u8(&all_slaves_active, *argv, 0))
307 invarg("invalid all_slaves_active", *argv);
308
309 addattr8(n, 1024, IFLA_BOND_ALL_SLAVES_ACTIVE,
310 all_slaves_active);
311 } else if (matches(*argv, "min_links") == 0) {
312 NEXT_ARG();
313 if (get_u32(&min_links, *argv, 0))
314 invarg("invalid min_links", *argv);
315
316 addattr32(n, 1024, IFLA_BOND_MIN_LINKS, min_links);
317 } else if (matches(*argv, "lp_interval") == 0) {
318 NEXT_ARG();
319 if (get_u32(&lp_interval, *argv, 0))
320 invarg("invalid lp_interval", *argv);
321
322 addattr32(n, 1024, IFLA_BOND_LP_INTERVAL, lp_interval);
323 } else if (matches(*argv, "packets_per_slave") == 0) {
324 NEXT_ARG();
325 if (get_u32(&packets_per_slave, *argv, 0))
326 invarg("invalid packets_per_slave", *argv);
327
328 addattr32(n, 1024, IFLA_BOND_PACKETS_PER_SLAVE,
329 packets_per_slave);
330 } else if (matches(*argv, "lacp_rate") == 0) {
331 NEXT_ARG();
332 if (get_index(lacp_rate_tbl, *argv) < 0)
333 invarg("invalid lacp_rate", *argv);
334
335 lacp_rate = get_index(lacp_rate_tbl, *argv);
336 addattr8(n, 1024, IFLA_BOND_AD_LACP_RATE, lacp_rate);
337 } else if (strcmp(*argv, "lacp_active") == 0) {
338 NEXT_ARG();
339 if (get_index(lacp_active_tbl, *argv) < 0)
340 invarg("invalid lacp_active", *argv);
341
342 lacp_active = get_index(lacp_active_tbl, *argv);
343 addattr8(n, 1024, IFLA_BOND_AD_LACP_ACTIVE, lacp_active);
344 } else if (matches(*argv, "ad_select") == 0) {
345 NEXT_ARG();
346 if (get_index(ad_select_tbl, *argv) < 0)
347 invarg("invalid ad_select", *argv);
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
356 addattr16(n, 1024, IFLA_BOND_AD_USER_PORT_KEY,
357 ad_user_port_key);
358 } else if (matches(*argv, "ad_actor_sys_prio") == 0) {
359 NEXT_ARG();
360 if (get_u16(&ad_actor_sys_prio, *argv, 0))
361 invarg("invalid ad_actor_sys_prio", *argv);
362
363 addattr16(n, 1024, IFLA_BOND_AD_ACTOR_SYS_PRIO,
364 ad_actor_sys_prio);
365 } else if (matches(*argv, "ad_actor_system") == 0) {
366 int len;
367 char abuf[32];
368
369 NEXT_ARG();
370 len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
371 if (len < 0)
372 return -1;
373 addattr_l(n, 1024, IFLA_BOND_AD_ACTOR_SYSTEM,
374 abuf, len);
375 } else if (matches(*argv, "tlb_dynamic_lb") == 0) {
376 NEXT_ARG();
377 if (get_u8(&tlb_dynamic_lb, *argv, 0)) {
378 invarg("invalid tlb_dynamic_lb", *argv);
379 return -1;
380 }
381 addattr8(n, 1024, IFLA_BOND_TLB_DYNAMIC_LB,
382 tlb_dynamic_lb);
383 } else if (matches(*argv, "help") == 0) {
384 explain();
385 return -1;
386 } else {
387 fprintf(stderr, "bond: unknown command \"%s\"?\n", *argv);
388 explain();
389 return -1;
390 }
391 argc--, argv++;
392 }
393
394 return 0;
395}
396
397static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
398{
399 if (!tb)
400 return;
401
402 if (tb[IFLA_BOND_MODE]) {
403 const char *mode = get_name(mode_tbl,
404 rta_getattr_u8(tb[IFLA_BOND_MODE]));
405 print_string(PRINT_ANY, "mode", "mode %s ", mode);
406 }
407
408 if (tb[IFLA_BOND_ACTIVE_SLAVE]) {
409 unsigned int ifindex =
410 rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]);
411
412 if (ifindex) {
413 print_string(PRINT_ANY,
414 "active_slave",
415 "active_slave %s ",
416 ll_index_to_name(ifindex));
417 }
418 }
419
420 if (tb[IFLA_BOND_MIIMON])
421 print_uint(PRINT_ANY,
422 "miimon",
423 "miimon %u ",
424 rta_getattr_u32(tb[IFLA_BOND_MIIMON]));
425
426 if (tb[IFLA_BOND_UPDELAY])
427 print_uint(PRINT_ANY,
428 "updelay",
429 "updelay %u ",
430 rta_getattr_u32(tb[IFLA_BOND_UPDELAY]));
431
432 if (tb[IFLA_BOND_DOWNDELAY])
433 print_uint(PRINT_ANY,
434 "downdelay",
435 "downdelay %u ",
436 rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY]));
437
438 if (tb[IFLA_BOND_PEER_NOTIF_DELAY])
439 print_uint(PRINT_ANY,
440 "peer_notify_delay",
441 "peer_notify_delay %u ",
442 rta_getattr_u32(tb[IFLA_BOND_PEER_NOTIF_DELAY]));
443
444 if (tb[IFLA_BOND_USE_CARRIER])
445 print_uint(PRINT_ANY,
446 "use_carrier",
447 "use_carrier %u ",
448 rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER]));
449
450 if (tb[IFLA_BOND_ARP_INTERVAL])
451 print_uint(PRINT_ANY,
452 "arp_interval",
453 "arp_interval %u ",
454 rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL]));
455
456 if (tb[IFLA_BOND_ARP_IP_TARGET]) {
457 struct rtattr *iptb[BOND_MAX_ARP_TARGETS + 1];
458 int i;
459
460 parse_rtattr_nested(iptb, BOND_MAX_ARP_TARGETS,
461 tb[IFLA_BOND_ARP_IP_TARGET]);
462
463 if (iptb[0]) {
464 open_json_array(PRINT_JSON, "arp_ip_target");
465 print_string(PRINT_FP, NULL, "arp_ip_target ", NULL);
466 }
467
468 for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
469 if (iptb[i])
470 print_string(PRINT_ANY,
471 NULL,
472 "%s",
473 rt_addr_n2a_rta(AF_INET, iptb[i]));
474 if (!is_json_context()
475 && i < BOND_MAX_ARP_TARGETS-1
476 && iptb[i+1])
477 fprintf(f, ",");
478 }
479
480 if (iptb[0]) {
481 print_string(PRINT_FP, NULL, " ", NULL);
482 close_json_array(PRINT_JSON, NULL);
483 }
484 }
485
486 if (tb[IFLA_BOND_ARP_VALIDATE]) {
487 __u32 arp_v = rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE]);
488 const char *arp_validate = get_name(arp_validate_tbl, arp_v);
489
490 if (!arp_v && is_json_context())
491 print_null(PRINT_JSON, "arp_validate", NULL, NULL);
492 else
493 print_string(PRINT_ANY,
494 "arp_validate",
495 "arp_validate %s ",
496 arp_validate);
497 }
498
499 if (tb[IFLA_BOND_ARP_ALL_TARGETS]) {
500 const char *arp_all_targets = get_name(arp_all_targets_tbl,
501 rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS]));
502 print_string(PRINT_ANY,
503 "arp_all_targets",
504 "arp_all_targets %s ",
505 arp_all_targets);
506 }
507
508 if (tb[IFLA_BOND_PRIMARY]) {
509 unsigned int ifindex = rta_getattr_u32(tb[IFLA_BOND_PRIMARY]);
510
511 if (ifindex) {
512 print_string(PRINT_ANY,
513 "primary",
514 "primary %s ",
515 ll_index_to_name(ifindex));
516 }
517 }
518
519 if (tb[IFLA_BOND_PRIMARY_RESELECT]) {
520 const char *primary_reselect = get_name(primary_reselect_tbl,
521 rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT]));
522 print_string(PRINT_ANY,
523 "primary_reselect",
524 "primary_reselect %s ",
525 primary_reselect);
526 }
527
528 if (tb[IFLA_BOND_FAIL_OVER_MAC]) {
529 const char *fail_over_mac = get_name(fail_over_mac_tbl,
530 rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC]));
531 print_string(PRINT_ANY,
532 "fail_over_mac",
533 "fail_over_mac %s ",
534 fail_over_mac);
535 }
536
537 if (tb[IFLA_BOND_XMIT_HASH_POLICY]) {
538 const char *xmit_hash_policy = get_name(xmit_hash_policy_tbl,
539 rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY]));
540 print_string(PRINT_ANY,
541 "xmit_hash_policy",
542 "xmit_hash_policy %s ",
543 xmit_hash_policy);
544 }
545
546 if (tb[IFLA_BOND_RESEND_IGMP])
547 print_uint(PRINT_ANY,
548 "resend_igmp",
549 "resend_igmp %u ",
550 rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP]));
551
552 if (tb[IFLA_BOND_NUM_PEER_NOTIF])
553 print_uint(PRINT_ANY,
554 "num_peer_notif",
555 "num_grat_arp %u ",
556 rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF]));
557
558 if (tb[IFLA_BOND_ALL_SLAVES_ACTIVE])
559 print_uint(PRINT_ANY,
560 "all_slaves_active",
561 "all_slaves_active %u ",
562 rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE]));
563
564 if (tb[IFLA_BOND_MIN_LINKS])
565 print_uint(PRINT_ANY,
566 "min_links",
567 "min_links %u ",
568 rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS]));
569
570 if (tb[IFLA_BOND_LP_INTERVAL])
571 print_uint(PRINT_ANY,
572 "lp_interval",
573 "lp_interval %u ",
574 rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL]));
575
576 if (tb[IFLA_BOND_PACKETS_PER_SLAVE])
577 print_uint(PRINT_ANY,
578 "packets_per_slave",
579 "packets_per_slave %u ",
580 rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE]));
581
582 if (tb[IFLA_BOND_AD_LACP_ACTIVE]) {
583 const char *lacp_active = get_name(lacp_active_tbl,
584 rta_getattr_u8(tb[IFLA_BOND_AD_LACP_ACTIVE]));
585 print_string(PRINT_ANY,
586 "ad_lacp_active",
587 "lacp_active %s ",
588 lacp_active);
589 }
590
591 if (tb[IFLA_BOND_AD_LACP_RATE]) {
592 const char *lacp_rate = get_name(lacp_rate_tbl,
593 rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE]));
594 print_string(PRINT_ANY,
595 "ad_lacp_rate",
596 "lacp_rate %s ",
597 lacp_rate);
598 }
599
600 if (tb[IFLA_BOND_AD_SELECT]) {
601 const char *ad_select = get_name(ad_select_tbl,
602 rta_getattr_u8(tb[IFLA_BOND_AD_SELECT]));
603 print_string(PRINT_ANY,
604 "ad_select",
605 "ad_select %s ",
606 ad_select);
607 }
608
609 if (tb[IFLA_BOND_AD_INFO]) {
610 struct rtattr *adtb[IFLA_BOND_AD_INFO_MAX + 1];
611
612 parse_rtattr_nested(adtb, IFLA_BOND_AD_INFO_MAX,
613 tb[IFLA_BOND_AD_INFO]);
614
615 open_json_object("ad_info");
616
617 if (adtb[IFLA_BOND_AD_INFO_AGGREGATOR])
618 print_int(PRINT_ANY,
619 "aggregator",
620 "ad_aggregator %d ",
621 rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR]));
622
623 if (adtb[IFLA_BOND_AD_INFO_NUM_PORTS])
624 print_int(PRINT_ANY,
625 "num_ports",
626 "ad_num_ports %d ",
627 rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS]));
628
629 if (adtb[IFLA_BOND_AD_INFO_ACTOR_KEY])
630 print_int(PRINT_ANY,
631 "actor_key",
632 "ad_actor_key %d ",
633 rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]));
634
635 if (adtb[IFLA_BOND_AD_INFO_PARTNER_KEY])
636 print_int(PRINT_ANY,
637 "partner_key",
638 "ad_partner_key %d ",
639 rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]));
640
641 if (adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]) {
642 unsigned char *p =
643 RTA_DATA(adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]);
644 SPRINT_BUF(b);
645 print_string(PRINT_ANY,
646 "partner_mac",
647 "ad_partner_mac %s ",
648 ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b)));
649 }
650
651 close_json_object();
652 }
653
654 if (tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]) {
655 print_uint(PRINT_ANY,
656 "ad_actor_sys_prio",
657 "ad_actor_sys_prio %u ",
658 rta_getattr_u16(tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]));
659 }
660
661 if (tb[IFLA_BOND_AD_USER_PORT_KEY]) {
662 print_uint(PRINT_ANY,
663 "ad_user_port_key",
664 "ad_user_port_key %u ",
665 rta_getattr_u16(tb[IFLA_BOND_AD_USER_PORT_KEY]));
666 }
667
668 if (tb[IFLA_BOND_AD_ACTOR_SYSTEM]) {
669
670 SPRINT_BUF(b1);
671
672 print_string(PRINT_ANY,
673 "ad_actor_system",
674 "ad_actor_system %s ",
675 ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
676 RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
677 1 , b1, sizeof(b1)));
678 }
679
680 if (tb[IFLA_BOND_TLB_DYNAMIC_LB]) {
681 print_uint(PRINT_ANY,
682 "tlb_dynamic_lb",
683 "tlb_dynamic_lb %u ",
684 rta_getattr_u8(tb[IFLA_BOND_TLB_DYNAMIC_LB]));
685 }
686}
687
688static void bond_print_help(struct link_util *lu, int argc, char **argv,
689 FILE *f)
690{
691 print_explain(f);
692}
693
694static void bond_print_xstats_help(struct link_util *lu, FILE *f)
695{
696 fprintf(f, "Usage: ... %s [ 802.3ad ] [ dev DEVICE ]\n", lu->id);
697}
698
699static void bond_print_3ad_stats(struct rtattr *lacpattr)
700{
701 struct rtattr *lacptb[BOND_3AD_STAT_MAX+1];
702 __u64 val;
703
704 parse_rtattr(lacptb, BOND_3AD_STAT_MAX, RTA_DATA(lacpattr),
705 RTA_PAYLOAD(lacpattr));
706 open_json_object("802.3ad");
707 if (lacptb[BOND_3AD_STAT_LACPDU_RX]) {
708 print_string(PRINT_FP, NULL, "%-16s ", "");
709 print_u64(PRINT_ANY, "lacpdu_rx", "LACPDU Rx %llu\n",
710 rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_RX]));
711 }
712 if (lacptb[BOND_3AD_STAT_LACPDU_TX]) {
713 print_string(PRINT_FP, NULL, "%-16s ", "");
714 print_u64(PRINT_ANY, "lacpdu_tx", "LACPDU Tx %llu\n",
715 rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_TX]));
716 }
717 if (lacptb[BOND_3AD_STAT_LACPDU_UNKNOWN_RX]) {
718 print_string(PRINT_FP, NULL, "%-16s ", "");
719 val = rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_UNKNOWN_RX]);
720 print_u64(PRINT_ANY,
721 "lacpdu_unknown_rx",
722 "LACPDU Unknown type Rx %llu\n",
723 val);
724 }
725 if (lacptb[BOND_3AD_STAT_LACPDU_ILLEGAL_RX]) {
726 print_string(PRINT_FP, NULL, "%-16s ", "");
727 val = rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_ILLEGAL_RX]);
728 print_u64(PRINT_ANY,
729 "lacpdu_illegal_rx",
730 "LACPDU Illegal Rx %llu\n",
731 val);
732 }
733 if (lacptb[BOND_3AD_STAT_MARKER_RX]) {
734 print_string(PRINT_FP, NULL, "%-16s ", "");
735 print_u64(PRINT_ANY, "marker_rx", "Marker Rx %llu\n",
736 rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_RX]));
737 }
738 if (lacptb[BOND_3AD_STAT_MARKER_TX]) {
739 print_string(PRINT_FP, NULL, "%-16s ", "");
740 print_u64(PRINT_ANY, "marker_tx", "Marker Tx %llu\n",
741 rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_TX]));
742 }
743 if (lacptb[BOND_3AD_STAT_MARKER_RESP_RX]) {
744 print_string(PRINT_FP, NULL, "%-16s ", "");
745 val = rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_RESP_RX]);
746 print_u64(PRINT_ANY,
747 "marker_response_rx",
748 "Marker response Rx %llu\n",
749 val);
750 }
751 if (lacptb[BOND_3AD_STAT_MARKER_RESP_TX]) {
752 print_string(PRINT_FP, NULL, "%-16s ", "");
753 val = rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_RESP_TX]);
754 print_u64(PRINT_ANY,
755 "marker_response_tx",
756 "Marker response Tx %llu\n",
757 val);
758 }
759 if (lacptb[BOND_3AD_STAT_MARKER_UNKNOWN_RX]) {
760 print_string(PRINT_FP, NULL, "%-16s ", "");
761 val = rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_UNKNOWN_RX]);
762 print_u64(PRINT_ANY,
763 "marker_unknown_rx",
764 "Marker unknown type Rx %llu\n",
765 val);
766 }
767 close_json_object();
768}
769
770static void bond_print_stats_attr(struct rtattr *attr, int ifindex)
771{
772 struct rtattr *bondtb[LINK_XSTATS_TYPE_MAX+1];
773 struct rtattr *i, *list;
774 const char *ifname = "";
775 int rem;
776
777 parse_rtattr(bondtb, LINK_XSTATS_TYPE_MAX+1, RTA_DATA(attr),
778 RTA_PAYLOAD(attr));
779 if (!bondtb[LINK_XSTATS_TYPE_BOND])
780 return;
781
782 list = bondtb[LINK_XSTATS_TYPE_BOND];
783 rem = RTA_PAYLOAD(list);
784 open_json_object(NULL);
785 ifname = ll_index_to_name(ifindex);
786 print_string(PRINT_ANY, "ifname", "%-16s\n", ifname);
787 for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
788 if (xstats_print_attr && i->rta_type != xstats_print_attr)
789 continue;
790
791 switch (i->rta_type) {
792 case BOND_XSTATS_3AD:
793 bond_print_3ad_stats(i);
794 break;
795 }
796 break;
797 }
798 close_json_object();
799}
800
801int bond_print_xstats(struct nlmsghdr *n, void *arg)
802{
803 struct if_stats_msg *ifsm = NLMSG_DATA(n);
804 struct rtattr *tb[IFLA_STATS_MAX+1];
805 int len = n->nlmsg_len;
806
807 len -= NLMSG_LENGTH(sizeof(*ifsm));
808 if (len < 0) {
809 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
810 return -1;
811 }
812 if (filter_index && filter_index != ifsm->ifindex)
813 return 0;
814
815 parse_rtattr(tb, IFLA_STATS_MAX, IFLA_STATS_RTA(ifsm), len);
816 if (tb[IFLA_STATS_LINK_XSTATS])
817 bond_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS],
818 ifsm->ifindex);
819
820 if (tb[IFLA_STATS_LINK_XSTATS_SLAVE])
821 bond_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS_SLAVE],
822 ifsm->ifindex);
823
824 return 0;
825}
826
827int bond_parse_xstats(struct link_util *lu, int argc, char **argv)
828{
829 while (argc > 0) {
830 if (strcmp(*argv, "lacp") == 0 ||
831 strcmp(*argv, "802.3ad") == 0) {
832 xstats_print_attr = BOND_XSTATS_3AD;
833 } else if (strcmp(*argv, "dev") == 0) {
834 NEXT_ARG();
835 filter_index = ll_name_to_index(*argv);
836 if (!filter_index)
837 return nodev(*argv);
838 } else if (strcmp(*argv, "help") == 0) {
839 bond_print_xstats_help(lu, stdout);
840 exit(0);
841 } else {
842 invarg("unknown attribute", *argv);
843 }
844 argc--; argv++;
845 }
846
847 return 0;
848}
849
850
851struct link_util bond_link_util = {
852 .id = "bond",
853 .maxattr = IFLA_BOND_MAX,
854 .parse_opt = bond_parse_opt,
855 .print_opt = bond_print_opt,
856 .print_help = bond_print_help,
857 .parse_ifla_xstats = bond_parse_xstats,
858 .print_ifla_xstats = bond_print_xstats,
859};
860