1 /*
2  * iplink_bond_slave.c	Bonding slave 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@resnulli.us>
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 
print_explain(FILE * f)20 static void print_explain(FILE *f)
21 {
22 	fprintf(f, "Usage: ... bond_slave [ queue_id ID ]\n");
23 }
24 
explain(void)25 static void explain(void)
26 {
27 	print_explain(stderr);
28 }
29 
30 static const char *slave_states[] = {
31 	[BOND_STATE_ACTIVE] = "ACTIVE",
32 	[BOND_STATE_BACKUP] = "BACKUP",
33 };
34 
print_slave_state(FILE * f,struct rtattr * tb)35 static 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 
48 static 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 
print_slave_mii_status(FILE * f,struct rtattr * tb)55 static 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 
bond_slave_print_opt(struct link_util * lu,FILE * f,struct rtattr * tb[])71 static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
72 {
73 	SPRINT_BUF(b1);
74 	if (!tb)
75 		return;
76 
77 	if (tb[IFLA_BOND_SLAVE_STATE])
78 		print_slave_state(f, tb[IFLA_BOND_SLAVE_STATE]);
79 
80 	if (tb[IFLA_BOND_SLAVE_MII_STATUS])
81 		print_slave_mii_status(f, tb[IFLA_BOND_SLAVE_MII_STATUS]);
82 
83 	if (tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT])
84 		print_int(PRINT_ANY,
85 			  "link_failure_count",
86 			  "link_failure_count %d ",
87 			  rta_getattr_u32(tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT]));
88 
89 	if (tb[IFLA_BOND_SLAVE_PERM_HWADDR])
90 		print_string(PRINT_ANY,
91 			     "perm_hwaddr",
92 			     "perm_hwaddr %s ",
93 			     ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_SLAVE_PERM_HWADDR]),
94 					 RTA_PAYLOAD(tb[IFLA_BOND_SLAVE_PERM_HWADDR]),
95 					 0, b1, sizeof(b1)));
96 
97 	if (tb[IFLA_BOND_SLAVE_QUEUE_ID])
98 		print_int(PRINT_ANY,
99 			  "queue_id",
100 			  "queue_id %d ",
101 			  rta_getattr_u16(tb[IFLA_BOND_SLAVE_QUEUE_ID]));
102 
103 	if (tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID])
104 		print_int(PRINT_ANY,
105 			  "ad_aggregator_id",
106 			  "ad_aggregator_id %d ",
107 			  rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID]));
108 
109 	if (tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE])
110 		print_int(PRINT_ANY,
111 			  "ad_actor_oper_port_state",
112 			  "ad_actor_oper_port_state %d ",
113 			  rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]));
114 
115 	if (tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE])
116 		print_int(PRINT_ANY,
117 			  "ad_partner_oper_port_state",
118 			  "ad_partner_oper_port_state %d ",
119 			  rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]));
120 }
121 
bond_slave_parse_opt(struct link_util * lu,int argc,char ** argv,struct nlmsghdr * n)122 static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv,
123 				struct nlmsghdr *n)
124 {
125 	__u16 queue_id;
126 
127 	while (argc > 0) {
128 		if (matches(*argv, "queue_id") == 0) {
129 			NEXT_ARG();
130 			if (get_u16(&queue_id, *argv, 0))
131 				invarg("queue_id is invalid", *argv);
132 			addattr16(n, 1024, IFLA_BOND_SLAVE_QUEUE_ID, queue_id);
133 		} else {
134 			if (matches(*argv, "help") != 0)
135 				fprintf(stderr,
136 					"bond_slave: unknown option \"%s\"?\n",
137 					*argv);
138 			explain();
139 			return -1;
140 		}
141 		argc--, argv++;
142 	}
143 
144 	return 0;
145 }
146 
bond_slave_print_help(struct link_util * lu,int argc,char ** argv,FILE * f)147 static void bond_slave_print_help(struct link_util *lu, int argc, char **argv,
148 				  FILE *f)
149 {
150 	print_explain(f);
151 }
152 
153 struct link_util bond_slave_link_util = {
154 	.id		= "bond_slave",
155 	.maxattr	= IFLA_BOND_SLAVE_MAX,
156 	.print_opt	= bond_slave_print_opt,
157 	.parse_opt	= bond_slave_parse_opt,
158 	.print_help	= bond_slave_print_help,
159 };
160