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 void explain(void)
24 fprintf(stderr
, "Usage: vlan pop\n");
25 fprintf(stderr
, " vlan push [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n");
26 fprintf(stderr
, " VLANPROTO is one of 802.1Q or 802.1AD\n");
27 fprintf(stderr
, " with default: 802.1Q\n");
28 fprintf(stderr
, " CONTROL := reclassify | pipe | drop | continue | pass\n");
31 static void usage(void)
37 static int parse_vlan(struct action_util
*a
, int *argc_p
, char ***argv_p
,
38 int tca_id
, struct nlmsghdr
*n
)
41 char **argv
= *argv_p
;
50 struct tc_vlan parm
= { 0 };
52 if (matches(*argv
, "vlan") != 0)
58 if (matches(*argv
, "pop") == 0) {
60 fprintf(stderr
, "unexpected \"%s\" - action already specified\n",
65 action
= TCA_VLAN_ACT_POP
;
66 } else if (matches(*argv
, "push") == 0) {
68 fprintf(stderr
, "unexpected \"%s\" - action already specified\n",
73 action
= TCA_VLAN_ACT_PUSH
;
74 } else if (matches(*argv
, "id") == 0) {
75 if (action
!= TCA_VLAN_ACT_PUSH
) {
76 fprintf(stderr
, "\"%s\" is only valid for push\n",
82 if (get_u16(&id
, *argv
, 0))
83 invarg("id is invalid", *argv
);
85 } else if (matches(*argv
, "protocol") == 0) {
86 if (action
!= TCA_VLAN_ACT_PUSH
) {
87 fprintf(stderr
, "\"%s\" is only valid for push\n",
93 if (ll_proto_a2n(&proto
, *argv
))
94 invarg("protocol is invalid", *argv
);
96 } else if (matches(*argv
, "priority") == 0) {
97 if (action
!= TCA_VLAN_ACT_PUSH
) {
98 fprintf(stderr
, "\"%s\" is only valid for push\n",
104 if (get_u8(&prio
, *argv
, 0) || (prio
& ~0x7))
105 invarg("prio is invalid", *argv
);
107 } else if (matches(*argv
, "help") == 0) {
116 parm
.action
= TC_ACT_PIPE
;
117 if (argc
&& !action_a2n(*argv
, &parm
.action
, false))
121 if (matches(*argv
, "index") == 0) {
123 if (get_u32(&parm
.index
, *argv
, 10)) {
124 fprintf(stderr
, "vlan: Illegal \"index\"\n");
132 if (action
== TCA_VLAN_ACT_PUSH
&& !id_set
) {
133 fprintf(stderr
, "id needs to be set for push\n");
138 parm
.v_action
= action
;
139 tail
= NLMSG_TAIL(n
);
140 addattr_l(n
, MAX_MSG
, tca_id
, NULL
, 0);
141 addattr_l(n
, MAX_MSG
, TCA_VLAN_PARMS
, &parm
, sizeof(parm
));
143 addattr_l(n
, MAX_MSG
, TCA_VLAN_PUSH_VLAN_ID
, &id
, 2);
145 if (proto
!= htons(ETH_P_8021Q
) &&
146 proto
!= htons(ETH_P_8021AD
)) {
147 fprintf(stderr
, "protocol not supported\n");
152 addattr_l(n
, MAX_MSG
, TCA_VLAN_PUSH_VLAN_PROTOCOL
, &proto
, 2);
155 addattr8(n
, MAX_MSG
, TCA_VLAN_PUSH_VLAN_PRIORITY
, prio
);
157 tail
->rta_len
= (char *)NLMSG_TAIL(n
) - (char *)tail
;
164 static int print_vlan(struct action_util
*au
, FILE *f
, struct rtattr
*arg
)
167 struct rtattr
*tb
[TCA_VLAN_MAX
+ 1];
169 struct tc_vlan
*parm
;
174 parse_rtattr_nested(tb
, TCA_VLAN_MAX
, arg
);
176 if (!tb
[TCA_VLAN_PARMS
]) {
177 fprintf(f
, "[NULL vlan parameters]");
180 parm
= RTA_DATA(tb
[TCA_VLAN_PARMS
]);
184 switch (parm
->v_action
) {
185 case TCA_VLAN_ACT_POP
:
188 case TCA_VLAN_ACT_PUSH
:
190 if (tb
[TCA_VLAN_PUSH_VLAN_ID
]) {
191 val
= rta_getattr_u16(tb
[TCA_VLAN_PUSH_VLAN_ID
]);
192 fprintf(f
, " id %u", val
);
194 if (tb
[TCA_VLAN_PUSH_VLAN_PROTOCOL
]) {
195 fprintf(f
, " protocol %s",
196 ll_proto_n2a(rta_getattr_u16(tb
[TCA_VLAN_PUSH_VLAN_PROTOCOL
]),
199 if (tb
[TCA_VLAN_PUSH_VLAN_PRIORITY
]) {
200 val
= rta_getattr_u8(tb
[TCA_VLAN_PUSH_VLAN_PRIORITY
]);
201 fprintf(f
, " priority %u", val
);
205 fprintf(f
, " %s", action_n2a(parm
->action
));
207 fprintf(f
, "\n\t index %d ref %d bind %d", parm
->index
, parm
->refcnt
,
211 if (tb
[TCA_VLAN_TM
]) {
212 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_VLAN_TM
]);
223 struct action_util vlan_action_util
= {
225 .parse_aopt
= parse_vlan
,
226 .print_aopt
= print_vlan
,