]> git.proxmox.com Git - mirror_iproute2.git/blob - ip/iplink_macvlan.c
Merge branch 'master' into net-next
[mirror_iproute2.git] / ip / iplink_macvlan.c
1 /*
2 * iplink_macvlan.c macvlan/macvtap 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: Patrick McHardy <kaber@trash.net>
10 * Arnd Bergmann <arnd@arndb.de>
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/socket.h>
17 #include <linux/if_link.h>
18
19 #include "rt_names.h"
20 #include "utils.h"
21 #include "ip_common.h"
22
23 #define pfx_err(lu, ...) { \
24 fprintf(stderr, "%s: ", lu->id); \
25 fprintf(stderr, __VA_ARGS__); \
26 fprintf(stderr, "\n"); \
27 }
28
29 static void print_explain(struct link_util *lu, FILE *f)
30 {
31 fprintf(f,
32 "Usage: ... %s mode { private | vepa | bridge | passthru [nopromisc] }\n",
33 lu->id
34 );
35 }
36
37 static void explain(struct link_util *lu)
38 {
39 print_explain(lu, stderr);
40 }
41
42 static int mode_arg(const char *arg)
43 {
44 fprintf(stderr, "Error: argument of \"mode\" must be \"private\", "
45 "\"vepa\", \"bridge\" or \"passthru\", not \"%s\"\n", arg);
46 return -1;
47 }
48
49 static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
50 struct nlmsghdr *n)
51 {
52 __u32 mode = 0;
53 __u16 flags = 0;
54
55 while (argc > 0) {
56 if (matches(*argv, "mode") == 0) {
57 NEXT_ARG();
58
59 if (strcmp(*argv, "private") == 0)
60 mode = MACVLAN_MODE_PRIVATE;
61 else if (strcmp(*argv, "vepa") == 0)
62 mode = MACVLAN_MODE_VEPA;
63 else if (strcmp(*argv, "bridge") == 0)
64 mode = MACVLAN_MODE_BRIDGE;
65 else if (strcmp(*argv, "passthru") == 0)
66 mode = MACVLAN_MODE_PASSTHRU;
67 else
68 return mode_arg(*argv);
69 } else if (matches(*argv, "nopromisc") == 0) {
70 flags |= MACVLAN_FLAG_NOPROMISC;
71 } else if (matches(*argv, "help") == 0) {
72 explain(lu);
73 return -1;
74 } else {
75 pfx_err(lu, "unknown option \"%s\"?", *argv);
76 explain(lu);
77 return -1;
78 }
79 argc--, argv++;
80 }
81
82 if (mode)
83 addattr32(n, 1024, IFLA_MACVLAN_MODE, mode);
84
85 if (flags) {
86 if (flags & MACVLAN_FLAG_NOPROMISC &&
87 mode != MACVLAN_MODE_PASSTHRU) {
88 pfx_err(lu, "nopromisc flag only valid in passthru mode");
89 explain(lu);
90 return -1;
91 }
92 addattr16(n, 1024, IFLA_MACVLAN_FLAGS, flags);
93 }
94 return 0;
95 }
96
97 static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
98 {
99 __u32 mode;
100 __u16 flags;
101
102 if (!tb)
103 return;
104
105 if (!tb[IFLA_MACVLAN_MODE] ||
106 RTA_PAYLOAD(tb[IFLA_MACVLAN_MODE]) < sizeof(__u32))
107 return;
108
109 mode = rta_getattr_u32(tb[IFLA_MACVLAN_MODE]);
110 fprintf(f, " mode %s ",
111 mode == MACVLAN_MODE_PRIVATE ? "private"
112 : mode == MACVLAN_MODE_VEPA ? "vepa"
113 : mode == MACVLAN_MODE_BRIDGE ? "bridge"
114 : mode == MACVLAN_MODE_PASSTHRU ? "passthru"
115 : "unknown");
116
117 if (!tb[IFLA_MACVLAN_FLAGS] ||
118 RTA_PAYLOAD(tb[IFLA_MACVLAN_FLAGS]) < sizeof(__u16))
119 return;
120
121 flags = rta_getattr_u16(tb[IFLA_MACVLAN_FLAGS]);
122 if (flags & MACVLAN_FLAG_NOPROMISC)
123 fprintf(f, "nopromisc ");
124 }
125
126 static void macvlan_print_help(struct link_util *lu, int argc, char **argv,
127 FILE *f)
128 {
129 print_explain(lu, f);
130 }
131
132 struct link_util macvlan_link_util = {
133 .id = "macvlan",
134 .maxattr = IFLA_MACVLAN_MAX,
135 .parse_opt = macvlan_parse_opt,
136 .print_opt = macvlan_print_opt,
137 .print_help = macvlan_print_help,
138 };
139
140 struct link_util macvtap_link_util = {
141 .id = "macvtap",
142 .maxattr = IFLA_MACVLAN_MAX,
143 .parse_opt = macvlan_parse_opt,
144 .print_opt = macvlan_print_opt,
145 .print_help = macvlan_print_help,
146 };