1
2
3
4
5
6
7
8
9
10
11
12#include <stdio.h>
13#include <sys/socket.h>
14#include <linux/if_bonding.h>
15
16#include "rt_names.h"
17#include "utils.h"
18#include "ip_common.h"
19
20static void print_explain(FILE *f)
21{
22 fprintf(f, "Usage: ... bond_slave [ queue_id ID ]\n");
23}
24
25static void explain(void)
26{
27 print_explain(stderr);
28}
29
30static const char *slave_states[] = {
31 [BOND_STATE_ACTIVE] = "ACTIVE",
32 [BOND_STATE_BACKUP] = "BACKUP",
33};
34
35static void print_slave_state(FILE *f, struct rtattr *tb)
36{
37 unsigned int state = rta_getattr_u8(tb);
38
39 if (state >= ARRAY_SIZE(slave_states))
40 print_int(PRINT_ANY, "state_index", "state %d ", state);
41 else
42 print_string(PRINT_ANY,
43 "state",
44 "state %s ",
45 slave_states[state]);
46}
47
48static const char *slave_mii_status[] = {
49 [BOND_LINK_UP] = "UP",
50 [BOND_LINK_FAIL] = "GOING_DOWN",
51 [BOND_LINK_DOWN] = "DOWN",
52 [BOND_LINK_BACK] = "GOING_BACK",
53};
54
55static void print_slave_mii_status(FILE *f, struct rtattr *tb)
56{
57 unsigned int status = rta_getattr_u8(tb);
58
59 if (status >= ARRAY_SIZE(slave_mii_status))
60 print_int(PRINT_ANY,
61 "mii_status_index",
62 "mii_status %d ",
63 status);
64 else
65 print_string(PRINT_ANY,
66 "mii_status",
67 "mii_status %s ",
68 slave_mii_status[status]);
69}
70
71static void print_slave_oper_state(FILE *fp, const char *name, __u16 state)
72{
73 open_json_array(PRINT_ANY, name);
74 print_string(PRINT_FP, NULL, " <", NULL);
75#define _PF(s, str) if (state & LACP_STATE_##s) { \
76 state &= ~LACP_STATE_##s; \
77 print_string(PRINT_ANY, NULL, \
78 state ? "%s," : "%s", str); }
79 _PF(LACP_ACTIVITY, "active");
80 _PF(LACP_TIMEOUT, "short_timeout");
81 _PF(AGGREGATION, "aggregating");
82 _PF(SYNCHRONIZATION, "in_sync");
83 _PF(COLLECTING, "collecting");
84 _PF(DISTRIBUTING, "distributing");
85 _PF(DEFAULTED, "defaulted");
86 _PF(EXPIRED, "expired");
87#undef _PF
88 close_json_array(PRINT_ANY, "> ");
89}
90
91static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
92{
93 SPRINT_BUF(b1);
94 if (!tb)
95 return;
96
97 if (tb[IFLA_BOND_SLAVE_STATE])
98 print_slave_state(f, tb[IFLA_BOND_SLAVE_STATE]);
99
100 if (tb[IFLA_BOND_SLAVE_MII_STATUS])
101 print_slave_mii_status(f, tb[IFLA_BOND_SLAVE_MII_STATUS]);
102
103 if (tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT])
104 print_int(PRINT_ANY,
105 "link_failure_count",
106 "link_failure_count %d ",
107 rta_getattr_u32(tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT]));
108
109 if (tb[IFLA_BOND_SLAVE_PERM_HWADDR])
110 print_string(PRINT_ANY,
111 "perm_hwaddr",
112 "perm_hwaddr %s ",
113 ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_SLAVE_PERM_HWADDR]),
114 RTA_PAYLOAD(tb[IFLA_BOND_SLAVE_PERM_HWADDR]),
115 0, b1, sizeof(b1)));
116
117 if (tb[IFLA_BOND_SLAVE_QUEUE_ID])
118 print_int(PRINT_ANY,
119 "queue_id",
120 "queue_id %d ",
121 rta_getattr_u16(tb[IFLA_BOND_SLAVE_QUEUE_ID]));
122
123 if (tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID])
124 print_int(PRINT_ANY,
125 "ad_aggregator_id",
126 "ad_aggregator_id %d ",
127 rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID]));
128
129 if (tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]) {
130 __u8 state = rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]);
131
132 print_int(PRINT_ANY,
133 "ad_actor_oper_port_state",
134 "ad_actor_oper_port_state %d ",
135 state);
136 print_slave_oper_state(f, "ad_actor_oper_port_state_str", state);
137 }
138
139 if (tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]) {
140 __u16 state = rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]);
141
142 print_int(PRINT_ANY,
143 "ad_partner_oper_port_state",
144 "ad_partner_oper_port_state %d ",
145 state);
146 print_slave_oper_state(f, "ad_partner_oper_port_state_str", state);
147 }
148}
149
150static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv,
151 struct nlmsghdr *n)
152{
153 __u16 queue_id;
154
155 while (argc > 0) {
156 if (matches(*argv, "queue_id") == 0) {
157 NEXT_ARG();
158 if (get_u16(&queue_id, *argv, 0))
159 invarg("queue_id is invalid", *argv);
160 addattr16(n, 1024, IFLA_BOND_SLAVE_QUEUE_ID, queue_id);
161 } else {
162 if (matches(*argv, "help") != 0)
163 fprintf(stderr,
164 "bond_slave: unknown option \"%s\"?\n",
165 *argv);
166 explain();
167 return -1;
168 }
169 argc--, argv++;
170 }
171
172 return 0;
173}
174
175static void bond_slave_print_help(struct link_util *lu, int argc, char **argv,
176 FILE *f)
177{
178 print_explain(f);
179}
180
181struct link_util bond_slave_link_util = {
182 .id = "bond_slave",
183 .maxattr = IFLA_BOND_SLAVE_MAX,
184 .print_opt = bond_slave_print_opt,
185 .parse_opt = bond_slave_parse_opt,
186 .print_help = bond_slave_print_help,
187 .parse_ifla_xstats = bond_parse_xstats,
188 .print_ifla_xstats = bond_print_xstats,
189};
190