]>
git.proxmox.com Git - mirror_iproute2.git/blob - ip/iplink_vlan.c
2 * iplink_vlan.c VLAN 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>
15 #include <linux/if_vlan.h>
19 #include "ip_common.h"
21 static void print_explain(FILE *f
)
24 "Usage: ... vlan id VLANID\n"
25 " [ protocol VLANPROTO ]\n"
26 " [ reorder_hdr { on | off } ]\n"
27 " [ gvrp { on | off } ]\n"
28 " [ mvrp { on | off } ]\n"
29 " [ loose_binding { on | off } ]\n"
30 " [ bridge_binding { on | off } ]\n"
31 " [ ingress-qos-map QOS-MAP ]\n"
32 " [ egress-qos-map QOS-MAP ]\n"
35 "VLANPROTO: [ 802.1Q | 802.1ad ]\n"
36 "QOS-MAP := [ QOS-MAP ] QOS-MAPPING\n"
37 "QOS-MAPPING := FROM:TO\n"
41 static void explain(void)
43 print_explain(stderr
);
46 static int on_off(const char *msg
, const char *arg
)
48 fprintf(stderr
, "Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n", msg
, arg
);
52 static int parse_qos_mapping(__u32 key
, char *value
, void *data
)
54 struct nlmsghdr
*n
= data
;
55 struct ifla_vlan_qos_mapping m
= {
59 if (get_u32(&m
.to
, value
, 0))
62 return addattr_l(n
, 1024, IFLA_VLAN_QOS_MAPPING
, &m
, sizeof(m
));
65 static int vlan_parse_qos_map(int *argcp
, char ***argvp
, struct nlmsghdr
*n
,
70 tail
= addattr_nest(n
, 1024, attrtype
);
72 if (parse_mapping(argcp
, argvp
, false, &parse_qos_mapping
, n
))
75 addattr_nest_end(n
, tail
);
79 static int vlan_parse_opt(struct link_util
*lu
, int argc
, char **argv
,
82 struct ifla_vlan_flags flags
= { 0 };
86 if (matches(*argv
, "protocol") == 0) {
88 if (ll_proto_a2n(&proto
, *argv
))
89 invarg("protocol is invalid", *argv
);
90 addattr_l(n
, 1024, IFLA_VLAN_PROTOCOL
, &proto
, 2);
91 } else if (matches(*argv
, "id") == 0) {
93 if (get_u16(&id
, *argv
, 0))
94 invarg("id is invalid", *argv
);
95 addattr_l(n
, 1024, IFLA_VLAN_ID
, &id
, 2);
96 } else if (matches(*argv
, "reorder_hdr") == 0) {
98 flags
.mask
|= VLAN_FLAG_REORDER_HDR
;
99 if (strcmp(*argv
, "on") == 0)
100 flags
.flags
|= VLAN_FLAG_REORDER_HDR
;
101 else if (strcmp(*argv
, "off") == 0)
102 flags
.flags
&= ~VLAN_FLAG_REORDER_HDR
;
104 return on_off("reorder_hdr", *argv
);
105 } else if (matches(*argv
, "gvrp") == 0) {
107 flags
.mask
|= VLAN_FLAG_GVRP
;
108 if (strcmp(*argv
, "on") == 0)
109 flags
.flags
|= VLAN_FLAG_GVRP
;
110 else if (strcmp(*argv
, "off") == 0)
111 flags
.flags
&= ~VLAN_FLAG_GVRP
;
113 return on_off("gvrp", *argv
);
114 } else if (matches(*argv
, "mvrp") == 0) {
116 flags
.mask
|= VLAN_FLAG_MVRP
;
117 if (strcmp(*argv
, "on") == 0)
118 flags
.flags
|= VLAN_FLAG_MVRP
;
119 else if (strcmp(*argv
, "off") == 0)
120 flags
.flags
&= ~VLAN_FLAG_MVRP
;
122 return on_off("mvrp", *argv
);
123 } else if (matches(*argv
, "loose_binding") == 0) {
125 flags
.mask
|= VLAN_FLAG_LOOSE_BINDING
;
126 if (strcmp(*argv
, "on") == 0)
127 flags
.flags
|= VLAN_FLAG_LOOSE_BINDING
;
128 else if (strcmp(*argv
, "off") == 0)
129 flags
.flags
&= ~VLAN_FLAG_LOOSE_BINDING
;
131 return on_off("loose_binding", *argv
);
132 } else if (matches(*argv
, "bridge_binding") == 0) {
134 flags
.mask
|= VLAN_FLAG_BRIDGE_BINDING
;
135 if (strcmp(*argv
, "on") == 0)
136 flags
.flags
|= VLAN_FLAG_BRIDGE_BINDING
;
137 else if (strcmp(*argv
, "off") == 0)
138 flags
.flags
&= ~VLAN_FLAG_BRIDGE_BINDING
;
140 return on_off("bridge_binding", *argv
);
141 } else if (matches(*argv
, "ingress-qos-map") == 0) {
143 if (vlan_parse_qos_map(&argc
, &argv
, n
,
144 IFLA_VLAN_INGRESS_QOS
))
145 invarg("invalid ingress-qos-map", *argv
);
147 } else if (matches(*argv
, "egress-qos-map") == 0) {
149 if (vlan_parse_qos_map(&argc
, &argv
, n
,
150 IFLA_VLAN_EGRESS_QOS
))
151 invarg("invalid egress-qos-map", *argv
);
153 } else if (matches(*argv
, "help") == 0) {
157 fprintf(stderr
, "vlan: unknown command \"%s\"?\n", *argv
);
165 addattr_l(n
, 1024, IFLA_VLAN_FLAGS
, &flags
, sizeof(flags
));
170 static void vlan_print_map(FILE *f
,
171 const char *name_json
,
175 struct ifla_vlan_qos_mapping
*m
;
179 open_json_array(PRINT_JSON
, name_json
);
181 print_string(PRINT_FP
, NULL
, " %s { ", name_fp
);
183 rem
= RTA_PAYLOAD(attr
);
184 for (i
= RTA_DATA(attr
); RTA_OK(i
, rem
); i
= RTA_NEXT(i
, rem
)) {
187 if (is_json_context()) {
188 open_json_object(NULL
);
189 print_uint(PRINT_JSON
, "from", NULL
, m
->from
);
190 print_uint(PRINT_JSON
, "to", NULL
, m
->to
);
193 fprintf(f
, "%u:%u ", m
->from
, m
->to
);
197 close_json_array(PRINT_JSON
, NULL
);
198 print_string(PRINT_FP
, NULL
, "%s ", "}");
201 static void vlan_print_flags(FILE *fp
, __u32 flags
)
203 open_json_array(PRINT_ANY
, is_json_context() ? "flags" : "<");
204 #define _PF(f) if (flags & VLAN_FLAG_##f) { \
205 flags &= ~VLAN_FLAG_##f; \
206 print_string(PRINT_ANY, NULL, flags ? "%s," : "%s", #f); \
215 print_hex(PRINT_ANY
, NULL
, "%x", flags
);
216 close_json_array(PRINT_ANY
, "> ");
219 static void vlan_print_opt(struct link_util
*lu
, FILE *f
, struct rtattr
*tb
[])
221 struct ifla_vlan_flags
*flags
;
228 if (tb
[IFLA_VLAN_PROTOCOL
] &&
229 RTA_PAYLOAD(tb
[IFLA_VLAN_PROTOCOL
]) < sizeof(__u16
))
231 if (!tb
[IFLA_VLAN_ID
] ||
232 RTA_PAYLOAD(tb
[IFLA_VLAN_ID
]) < sizeof(__u16
))
235 if (tb
[IFLA_VLAN_PROTOCOL
])
236 print_string(PRINT_ANY
,
240 rta_getattr_u16(tb
[IFLA_VLAN_PROTOCOL
]),
243 print_string(PRINT_ANY
, "protocol", "protocol %s ", "802.1q");
245 print_uint(PRINT_ANY
,
248 rta_getattr_u16(tb
[IFLA_VLAN_ID
]));
250 if (tb
[IFLA_VLAN_FLAGS
]) {
251 if (RTA_PAYLOAD(tb
[IFLA_VLAN_FLAGS
]) < sizeof(*flags
))
253 flags
= RTA_DATA(tb
[IFLA_VLAN_FLAGS
]);
254 vlan_print_flags(f
, flags
->flags
);
256 if (tb
[IFLA_VLAN_INGRESS_QOS
])
260 tb
[IFLA_VLAN_INGRESS_QOS
]);
261 if (tb
[IFLA_VLAN_EGRESS_QOS
])
265 tb
[IFLA_VLAN_EGRESS_QOS
]);
268 static void vlan_print_help(struct link_util
*lu
, int argc
, char **argv
,
274 struct link_util vlan_link_util
= {
276 .maxattr
= IFLA_VLAN_MAX
,
277 .parse_opt
= vlan_parse_opt
,
278 .print_opt
= vlan_print_opt
,
279 .print_help
= vlan_print_help
,