2 * m_vlan.c vlan manipulation module
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: Jiri Pirko <jiri@resnulli.us>
16 #include <linux/if_ether.h>
20 #include <linux/tc_act/tc_vlan.h>
22 static const char * const action_names[] = {
23 [TCA_VLAN_ACT_POP] = "pop",
24 [TCA_VLAN_ACT_PUSH] = "push",
25 [TCA_VLAN_ACT_MODIFY] = "modify",
28 static void explain(void)
32 " vlan push [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n"
33 " vlan modify [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n"
34 " VLANPROTO is one of 802.1Q or 802.1AD\n"
35 " with default: 802.1Q\n"
36 " CONTROL := reclassify | pipe | drop | continue | pass |\n"
37 " goto chain <CHAIN_INDEX>\n");
40 static void usage(void)
46 static bool has_push_attribs(int action)
48 return action == TCA_VLAN_ACT_PUSH || action == TCA_VLAN_ACT_MODIFY;
51 static void unexpected(const char *arg)
54 "unexpected \"%s\" - action already specified\n",
59 static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p,
60 int tca_id, struct nlmsghdr *n)
63 char **argv = *argv_p;
72 struct tc_vlan parm = {};
74 if (matches(*argv, "vlan") != 0)
80 if (matches(*argv, "pop") == 0) {
85 action = TCA_VLAN_ACT_POP;
86 } else if (matches(*argv, "push") == 0) {
91 action = TCA_VLAN_ACT_PUSH;
92 } else if (matches(*argv, "modify") == 0) {
97 action = TCA_VLAN_ACT_MODIFY;
98 } else if (matches(*argv, "id") == 0) {
99 if (!has_push_attribs(action))
100 invarg("only valid for push/modify", *argv);
103 if (get_u16(&id, *argv, 0))
104 invarg("id is invalid", *argv);
106 } else if (matches(*argv, "protocol") == 0) {
107 if (!has_push_attribs(action))
108 invarg("only valid for push/modify", *argv);
111 if (ll_proto_a2n(&proto, *argv))
112 invarg("protocol is invalid", *argv);
114 } else if (matches(*argv, "priority") == 0) {
115 if (!has_push_attribs(action))
116 invarg("only valid for push/modify", *argv);
119 if (get_u8(&prio, *argv, 0) || (prio & ~0x7))
120 invarg("prio is invalid", *argv);
122 } else if (matches(*argv, "help") == 0) {
131 parse_action_control_dflt(&argc, &argv, &parm.action,
135 if (matches(*argv, "index") == 0) {
137 if (get_u32(&parm.index, *argv, 10)) {
138 fprintf(stderr, "vlan: Illegal \"index\"\n");
146 if (has_push_attribs(action) && !id_set) {
147 fprintf(stderr, "id needs to be set for %s\n",
148 action_names[action]);
153 parm.v_action = action;
154 tail = addattr_nest(n, MAX_MSG, tca_id);
155 addattr_l(n, MAX_MSG, TCA_VLAN_PARMS, &parm, sizeof(parm));
157 addattr_l(n, MAX_MSG, TCA_VLAN_PUSH_VLAN_ID, &id, 2);
159 if (proto != htons(ETH_P_8021Q) &&
160 proto != htons(ETH_P_8021AD)) {
161 fprintf(stderr, "protocol not supported\n");
166 addattr_l(n, MAX_MSG, TCA_VLAN_PUSH_VLAN_PROTOCOL, &proto, 2);
169 addattr8(n, MAX_MSG, TCA_VLAN_PUSH_VLAN_PRIORITY, prio);
171 addattr_nest_end(n, tail);
178 static int print_vlan(struct action_util *au, FILE *f, struct rtattr *arg)
181 struct rtattr *tb[TCA_VLAN_MAX + 1];
183 struct tc_vlan *parm;
188 parse_rtattr_nested(tb, TCA_VLAN_MAX, arg);
190 if (!tb[TCA_VLAN_PARMS]) {
191 fprintf(stderr, "Missing vlanparameters\n");
194 parm = RTA_DATA(tb[TCA_VLAN_PARMS]);
196 print_string(PRINT_ANY, "kind", "%s ", "vlan");
197 print_string(PRINT_ANY, "vlan_action", " %s",
198 action_names[parm->v_action]);
200 switch (parm->v_action) {
201 case TCA_VLAN_ACT_PUSH:
202 case TCA_VLAN_ACT_MODIFY:
203 if (tb[TCA_VLAN_PUSH_VLAN_ID]) {
204 val = rta_getattr_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
205 print_uint(PRINT_ANY, "id", " id %u", val);
207 if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) {
210 proto = rta_getattr_u16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]);
211 print_string(PRINT_ANY, "protocol", " protocol %s",
212 ll_proto_n2a(proto, b1, sizeof(b1)));
214 if (tb[TCA_VLAN_PUSH_VLAN_PRIORITY]) {
215 val = rta_getattr_u8(tb[TCA_VLAN_PUSH_VLAN_PRIORITY]);
216 print_uint(PRINT_ANY, "priority", " priority %u", val);
220 print_action_control(f, " ", parm->action, "");
222 print_uint(PRINT_ANY, "index", "\n\t index %u", parm->index);
223 print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
224 print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);
227 if (tb[TCA_VLAN_TM]) {
228 struct tcf_t *tm = RTA_DATA(tb[TCA_VLAN_TM]);
234 print_string(PRINT_FP, NULL, "%s", "\n");
239 struct action_util vlan_action_util = {
241 .parse_aopt = parse_vlan,
242 .print_aopt = print_vlan,