2 * iplink_macvlan.c macvlan/macvtap device support
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.
9 * Authors: Patrick McHardy <kaber@trash.net>
10 * Arnd Bergmann <arnd@arndb.de>
16 #include <sys/socket.h>
17 #include <linux/if_link.h>
18 #include <linux/if_ether.h>
22 #include "ip_common.h"
24 #define pfx_err(lu, ...) { \
25 fprintf(stderr, "%s: ", lu->id); \
26 fprintf(stderr, __VA_ARGS__); \
27 fprintf(stderr, "\n"); \
30 static void print_explain(struct link_util
*lu
, FILE *f
)
33 "Usage: ... %s mode MODE [flag MODE_FLAG] MODE_OPTS [bcqueuelen BC_QUEUE_LEN]\n"
35 "MODE: private | vepa | bridge | passthru | source\n"
36 "MODE_FLAG: null | nopromisc\n"
37 "MODE_OPTS: for mode \"source\":\n"
38 "\tmacaddr { { add | del } <macaddr> | set [ <macaddr> [ <macaddr> ... ] ] | flush }\n"
39 "BC_QUEUE_LEN: Length of the rx queue for broadcast/multicast: [0-4294967295]\n",
44 static void explain(struct link_util
*lu
)
46 print_explain(lu
, stderr
);
50 static int mode_arg(const char *arg
)
53 "Error: argument of \"mode\" must be \"private\", \"vepa\", \"bridge\", \"passthru\" or \"source\", not \"%s\"\n",
58 static int flag_arg(const char *arg
)
61 "Error: argument of \"flag\" must be \"nopromisc\" or \"null\", not \"%s\"\n",
66 static int bc_queue_len_arg(const char *arg
)
69 "Error: argument of \"bcqueuelen\" must be a positive integer [0-4294967295], not \"%s\"\n",
74 static int macvlan_parse_opt(struct link_util
*lu
, int argc
, char **argv
,
85 if (matches(*argv
, "mode") == 0) {
88 if (strcmp(*argv
, "private") == 0)
89 mode
= MACVLAN_MODE_PRIVATE
;
90 else if (strcmp(*argv
, "vepa") == 0)
91 mode
= MACVLAN_MODE_VEPA
;
92 else if (strcmp(*argv
, "bridge") == 0)
93 mode
= MACVLAN_MODE_BRIDGE
;
94 else if (strcmp(*argv
, "passthru") == 0)
95 mode
= MACVLAN_MODE_PASSTHRU
;
96 else if (strcmp(*argv
, "source") == 0)
97 mode
= MACVLAN_MODE_SOURCE
;
99 return mode_arg(*argv
);
100 } else if (matches(*argv
, "flag") == 0) {
103 if (strcmp(*argv
, "nopromisc") == 0)
104 flags
|= MACVLAN_FLAG_NOPROMISC
;
105 else if (strcmp(*argv
, "null") == 0)
108 return flag_arg(*argv
);
112 } else if (matches(*argv
, "macaddr") == 0) {
115 if (strcmp(*argv
, "add") == 0) {
116 mac_mode
= MACVLAN_MACADDR_ADD
;
117 } else if (strcmp(*argv
, "del") == 0) {
118 mac_mode
= MACVLAN_MACADDR_DEL
;
119 } else if (strcmp(*argv
, "set") == 0) {
120 mac_mode
= MACVLAN_MACADDR_SET
;
121 } else if (strcmp(*argv
, "flush") == 0) {
122 mac_mode
= MACVLAN_MACADDR_FLUSH
;
128 addattr32(n
, 1024, IFLA_MACVLAN_MACADDR_MODE
, mac_mode
);
130 if (mac_mode
== MACVLAN_MACADDR_ADD
||
131 mac_mode
== MACVLAN_MACADDR_DEL
) {
134 if (ll_addr_a2n(mac
, sizeof(mac
),
138 addattr_l(n
, 1024, IFLA_MACVLAN_MACADDR
, &mac
,
142 if (mac_mode
== MACVLAN_MACADDR_SET
) {
143 nmac
= addattr_nest(n
, 1024,
144 IFLA_MACVLAN_MACADDR_DATA
);
145 while (NEXT_ARG_OK()) {
148 if (ll_addr_a2n(mac
, sizeof(mac
),
149 *argv
) != ETH_ALEN
) {
154 addattr_l(n
, 1024, IFLA_MACVLAN_MACADDR
,
157 addattr_nest_end(n
, nmac
);
159 } else if (matches(*argv
, "nopromisc") == 0) {
160 flags
|= MACVLAN_FLAG_NOPROMISC
;
162 } else if (matches(*argv
, "bcqueuelen") == 0) {
166 if (get_u32(&bc_queue_len
, *argv
, 0)) {
167 return bc_queue_len_arg(*argv
);
169 addattr32(n
, 1024, IFLA_MACVLAN_BC_QUEUE_LEN
, bc_queue_len
);
170 } else if (matches(*argv
, "help") == 0) {
174 pfx_err(lu
, "unknown option \"%s\"?", *argv
);
182 addattr32(n
, 1024, IFLA_MACVLAN_MODE
, mode
);
185 if (flags
& MACVLAN_FLAG_NOPROMISC
&&
186 mode
!= MACVLAN_MODE_PASSTHRU
) {
187 pfx_err(lu
, "nopromisc flag only valid in passthru mode");
191 addattr16(n
, 1024, IFLA_MACVLAN_FLAGS
, flags
);
196 static void macvlan_print_opt(struct link_util
*lu
, FILE *f
, struct rtattr
*tb
[])
208 if (!tb
[IFLA_MACVLAN_MODE
] ||
209 RTA_PAYLOAD(tb
[IFLA_MACVLAN_MODE
]) < sizeof(__u32
))
212 mode
= rta_getattr_u32(tb
[IFLA_MACVLAN_MODE
]);
213 print_string(PRINT_ANY
,
216 mode
== MACVLAN_MODE_PRIVATE
? "private"
217 : mode
== MACVLAN_MODE_VEPA
? "vepa"
218 : mode
== MACVLAN_MODE_BRIDGE
? "bridge"
219 : mode
== MACVLAN_MODE_PASSTHRU
? "passthru"
220 : mode
== MACVLAN_MODE_SOURCE
? "source"
223 if (!tb
[IFLA_MACVLAN_FLAGS
] ||
224 RTA_PAYLOAD(tb
[IFLA_MACVLAN_FLAGS
]) < sizeof(__u16
))
227 flags
= rta_getattr_u16(tb
[IFLA_MACVLAN_FLAGS
]);
229 if (flags
& MACVLAN_FLAG_NOPROMISC
)
230 print_bool(PRINT_ANY
, "nopromisc", "nopromisc ", true);
232 if (tb
[IFLA_MACVLAN_BC_QUEUE_LEN
] &&
233 RTA_PAYLOAD(tb
[IFLA_MACVLAN_BC_QUEUE_LEN
]) >= sizeof(__u32
)) {
234 __u32 bc_queue_len
= rta_getattr_u32(tb
[IFLA_MACVLAN_BC_QUEUE_LEN
]);
235 print_luint(PRINT_ANY
, "bcqueuelen", "bcqueuelen %lu ", bc_queue_len
);
238 if (tb
[IFLA_MACVLAN_BC_QUEUE_LEN_USED
] &&
239 RTA_PAYLOAD(tb
[IFLA_MACVLAN_BC_QUEUE_LEN_USED
]) >= sizeof(__u32
)) {
240 __u32 bc_queue_len
= rta_getattr_u32(tb
[IFLA_MACVLAN_BC_QUEUE_LEN_USED
]);
241 print_luint(PRINT_ANY
, "usedbcqueuelen", "usedbcqueuelen %lu ", bc_queue_len
);
244 /* in source mode, there are more options to print */
246 if (mode
!= MACVLAN_MODE_SOURCE
)
249 if (!tb
[IFLA_MACVLAN_MACADDR_COUNT
] ||
250 RTA_PAYLOAD(tb
[IFLA_MACVLAN_MACADDR_COUNT
]) < sizeof(__u32
))
253 count
= rta_getattr_u32(tb
[IFLA_MACVLAN_MACADDR_COUNT
]);
254 print_int(PRINT_ANY
, "macaddr_count", "remotes (%d) ", count
);
256 if (!tb
[IFLA_MACVLAN_MACADDR_DATA
])
259 rta
= RTA_DATA(tb
[IFLA_MACVLAN_MACADDR_DATA
]);
260 len
= RTA_PAYLOAD(tb
[IFLA_MACVLAN_MACADDR_DATA
]);
262 open_json_array(PRINT_JSON
, "macaddr_data");
263 for (; RTA_OK(rta
, len
); rta
= RTA_NEXT(rta
, len
)) {
264 if (rta
->rta_type
!= IFLA_MACVLAN_MACADDR
||
265 RTA_PAYLOAD(rta
) < 6)
267 addr
= RTA_DATA(rta
);
268 if (is_json_context()) {
271 snprintf(b1
, sizeof(b1
),
272 "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", addr
[0],
273 addr
[1], addr
[2], addr
[3], addr
[4], addr
[5]);
274 print_string(PRINT_JSON
, NULL
, NULL
, b1
);
276 fprintf(f
, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x ", addr
[0],
277 addr
[1], addr
[2], addr
[3], addr
[4], addr
[5]);
280 close_json_array(PRINT_JSON
, NULL
);
283 static void macvlan_print_help(struct link_util
*lu
, int argc
, char **argv
,
286 print_explain(lu
, f
);
289 struct link_util macvlan_link_util
= {
291 .maxattr
= IFLA_MACVLAN_MAX
,
292 .parse_opt
= macvlan_parse_opt
,
293 .print_opt
= macvlan_print_opt
,
294 .print_help
= macvlan_print_help
,
297 struct link_util macvtap_link_util
= {
299 .maxattr
= IFLA_MACVLAN_MAX
,
300 .parse_opt
= macvlan_parse_opt
,
301 .print_opt
= macvlan_print_opt
,
302 .print_help
= macvlan_print_help
,