xref: /aosp_15_r20/external/libnl/lib/route/act/vlan.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker  * Copyright (c) 2018 Volodymyr Bendiuga <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker  */
5*4dc78e53SAndroid Build Coastguard Worker 
6*4dc78e53SAndroid Build Coastguard Worker /**
7*4dc78e53SAndroid Build Coastguard Worker  * @ingroup act
8*4dc78e53SAndroid Build Coastguard Worker  * @defgroup act_vlan VLAN Manipulation
9*4dc78e53SAndroid Build Coastguard Worker  *
10*4dc78e53SAndroid Build Coastguard Worker  * @{
11*4dc78e53SAndroid Build Coastguard Worker  */
12*4dc78e53SAndroid Build Coastguard Worker 
13*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
14*4dc78e53SAndroid Build Coastguard Worker 
15*4dc78e53SAndroid Build Coastguard Worker #include <linux/tc_act/tc_vlan.h>
16*4dc78e53SAndroid Build Coastguard Worker 
17*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
18*4dc78e53SAndroid Build Coastguard Worker #include <netlink/attr.h>
19*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
20*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/act/vlan.h>
21*4dc78e53SAndroid Build Coastguard Worker 
22*4dc78e53SAndroid Build Coastguard Worker #include "tc-api.h"
23*4dc78e53SAndroid Build Coastguard Worker 
24*4dc78e53SAndroid Build Coastguard Worker struct rtnl_vlan
25*4dc78e53SAndroid Build Coastguard Worker {
26*4dc78e53SAndroid Build Coastguard Worker 	struct tc_vlan v_parm;
27*4dc78e53SAndroid Build Coastguard Worker 	uint16_t       v_vid;
28*4dc78e53SAndroid Build Coastguard Worker 	uint16_t       v_proto;
29*4dc78e53SAndroid Build Coastguard Worker 	uint8_t        v_prio;
30*4dc78e53SAndroid Build Coastguard Worker 	uint32_t       v_flags;
31*4dc78e53SAndroid Build Coastguard Worker };
32*4dc78e53SAndroid Build Coastguard Worker 
33*4dc78e53SAndroid Build Coastguard Worker #define VLAN_F_VID   (1 << 0)
34*4dc78e53SAndroid Build Coastguard Worker #define VLAN_F_PROTO (1 << 1)
35*4dc78e53SAndroid Build Coastguard Worker #define VLAN_F_PRIO  (1 << 2)
36*4dc78e53SAndroid Build Coastguard Worker #define VLAN_F_ACT   (1 << 3)
37*4dc78e53SAndroid Build Coastguard Worker #define VLAN_F_MODE  (1 << 4)
38*4dc78e53SAndroid Build Coastguard Worker 
39*4dc78e53SAndroid Build Coastguard Worker static struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
40*4dc78e53SAndroid Build Coastguard Worker 	[TCA_VLAN_PARMS]                = { .minlen = sizeof(struct tc_vlan) },
41*4dc78e53SAndroid Build Coastguard Worker 	[TCA_VLAN_PUSH_VLAN_ID]         = { .type = NLA_U16 },
42*4dc78e53SAndroid Build Coastguard Worker 	[TCA_VLAN_PUSH_VLAN_PROTOCOL]   = { .type = NLA_U16 },
43*4dc78e53SAndroid Build Coastguard Worker 	[TCA_VLAN_PUSH_VLAN_PRIORITY]   = { .type = NLA_U8 },
44*4dc78e53SAndroid Build Coastguard Worker };
45*4dc78e53SAndroid Build Coastguard Worker 
vlan_msg_parser(struct rtnl_tc * tc,void * data)46*4dc78e53SAndroid Build Coastguard Worker static int vlan_msg_parser(struct rtnl_tc *tc, void *data)
47*4dc78e53SAndroid Build Coastguard Worker {
48*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v = data;
49*4dc78e53SAndroid Build Coastguard Worker 	struct nlattr *tb[TCA_VLAN_MAX + 1];
50*4dc78e53SAndroid Build Coastguard Worker 	int err;
51*4dc78e53SAndroid Build Coastguard Worker 
52*4dc78e53SAndroid Build Coastguard Worker 	err = tca_parse(tb, TCA_VLAN_MAX, tc, vlan_policy);
53*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
54*4dc78e53SAndroid Build Coastguard Worker 		return err;
55*4dc78e53SAndroid Build Coastguard Worker 
56*4dc78e53SAndroid Build Coastguard Worker 	v->v_flags = 0;
57*4dc78e53SAndroid Build Coastguard Worker 	if (!tb[TCA_VLAN_PARMS])
58*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
59*4dc78e53SAndroid Build Coastguard Worker 	else {
60*4dc78e53SAndroid Build Coastguard Worker 		nla_memcpy(&v->v_parm, tb[TCA_VLAN_PARMS], sizeof(v->v_parm));
61*4dc78e53SAndroid Build Coastguard Worker 		v->v_flags |= VLAN_F_ACT;
62*4dc78e53SAndroid Build Coastguard Worker 		v->v_flags |= VLAN_F_MODE;
63*4dc78e53SAndroid Build Coastguard Worker 	}
64*4dc78e53SAndroid Build Coastguard Worker 
65*4dc78e53SAndroid Build Coastguard Worker 	if (tb[TCA_VLAN_PUSH_VLAN_ID]) {
66*4dc78e53SAndroid Build Coastguard Worker 		v->v_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
67*4dc78e53SAndroid Build Coastguard Worker 		v->v_flags |= VLAN_F_VID;
68*4dc78e53SAndroid Build Coastguard Worker 	}
69*4dc78e53SAndroid Build Coastguard Worker 
70*4dc78e53SAndroid Build Coastguard Worker 	if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) {
71*4dc78e53SAndroid Build Coastguard Worker 		v->v_proto = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]);
72*4dc78e53SAndroid Build Coastguard Worker 		v->v_flags |= VLAN_F_PROTO;
73*4dc78e53SAndroid Build Coastguard Worker 	}
74*4dc78e53SAndroid Build Coastguard Worker 
75*4dc78e53SAndroid Build Coastguard Worker 	if (tb[TCA_VLAN_PUSH_VLAN_PRIORITY]) {
76*4dc78e53SAndroid Build Coastguard Worker 		v->v_prio = nla_get_u8(tb[TCA_VLAN_PUSH_VLAN_PRIORITY]);
77*4dc78e53SAndroid Build Coastguard Worker 		v->v_flags |= VLAN_F_PRIO;
78*4dc78e53SAndroid Build Coastguard Worker 	}
79*4dc78e53SAndroid Build Coastguard Worker 
80*4dc78e53SAndroid Build Coastguard Worker 	return 0;
81*4dc78e53SAndroid Build Coastguard Worker }
82*4dc78e53SAndroid Build Coastguard Worker 
vlan_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)83*4dc78e53SAndroid Build Coastguard Worker static int vlan_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
84*4dc78e53SAndroid Build Coastguard Worker {
85*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v = data;
86*4dc78e53SAndroid Build Coastguard Worker 
87*4dc78e53SAndroid Build Coastguard Worker 	if (!v)
88*4dc78e53SAndroid Build Coastguard Worker 		return 0;
89*4dc78e53SAndroid Build Coastguard Worker 	if (!(v->v_flags & VLAN_F_MODE))
90*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
91*4dc78e53SAndroid Build Coastguard Worker 
92*4dc78e53SAndroid Build Coastguard Worker 	NLA_PUT(msg, TCA_VLAN_PARMS, sizeof(v->v_parm), &v->v_parm);
93*4dc78e53SAndroid Build Coastguard Worker 
94*4dc78e53SAndroid Build Coastguard Worker 	/* vid is required for PUSH & MODIFY modes */
95*4dc78e53SAndroid Build Coastguard Worker 	if ((v->v_parm.v_action != TCA_VLAN_ACT_POP) && !(v->v_flags & VLAN_F_VID))
96*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
97*4dc78e53SAndroid Build Coastguard Worker 
98*4dc78e53SAndroid Build Coastguard Worker 	if (v->v_flags & VLAN_F_VID)
99*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U16(msg, TCA_VLAN_PUSH_VLAN_ID, v->v_vid);
100*4dc78e53SAndroid Build Coastguard Worker 
101*4dc78e53SAndroid Build Coastguard Worker 	if (v->v_flags & VLAN_F_PROTO)
102*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U16(msg, TCA_VLAN_PUSH_VLAN_PROTOCOL, v->v_proto);
103*4dc78e53SAndroid Build Coastguard Worker 
104*4dc78e53SAndroid Build Coastguard Worker 	if (v->v_flags & VLAN_F_PRIO)
105*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U8(msg, TCA_VLAN_PUSH_VLAN_PRIORITY, v->v_prio);
106*4dc78e53SAndroid Build Coastguard Worker 
107*4dc78e53SAndroid Build Coastguard Worker 	return 0;
108*4dc78e53SAndroid Build Coastguard Worker 
109*4dc78e53SAndroid Build Coastguard Worker nla_put_failure:
110*4dc78e53SAndroid Build Coastguard Worker 	return -NLE_NOMEM;
111*4dc78e53SAndroid Build Coastguard Worker }
112*4dc78e53SAndroid Build Coastguard Worker 
vlan_free_data(struct rtnl_tc * tc,void * data)113*4dc78e53SAndroid Build Coastguard Worker static void vlan_free_data(struct rtnl_tc *tc, void *data)
114*4dc78e53SAndroid Build Coastguard Worker {
115*4dc78e53SAndroid Build Coastguard Worker }
116*4dc78e53SAndroid Build Coastguard Worker 
vlan_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)117*4dc78e53SAndroid Build Coastguard Worker static void vlan_dump_line(struct rtnl_tc *tc, void *data,
118*4dc78e53SAndroid Build Coastguard Worker                            struct nl_dump_params *p)
119*4dc78e53SAndroid Build Coastguard Worker {
120*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v = data;
121*4dc78e53SAndroid Build Coastguard Worker 
122*4dc78e53SAndroid Build Coastguard Worker 	if (!v)
123*4dc78e53SAndroid Build Coastguard Worker 		return;
124*4dc78e53SAndroid Build Coastguard Worker 
125*4dc78e53SAndroid Build Coastguard Worker 	if (!(v->v_flags & VLAN_F_ACT))
126*4dc78e53SAndroid Build Coastguard Worker 		return;
127*4dc78e53SAndroid Build Coastguard Worker 
128*4dc78e53SAndroid Build Coastguard Worker 	if (TC_ACT_EXT_CMP(v->v_parm.action, TC_ACT_GOTO_CHAIN))
129*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " goto chain %u", v->v_parm.action & TC_ACT_EXT_VAL_MASK);
130*4dc78e53SAndroid Build Coastguard Worker 
131*4dc78e53SAndroid Build Coastguard Worker 	if (TC_ACT_EXT_CMP(v->v_parm.action, TC_ACT_JUMP))
132*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " jump %u", v->v_parm.action & TC_ACT_EXT_VAL_MASK);
133*4dc78e53SAndroid Build Coastguard Worker 
134*4dc78e53SAndroid Build Coastguard Worker 	switch(v->v_parm.action){
135*4dc78e53SAndroid Build Coastguard Worker 	case TC_ACT_UNSPEC:
136*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " unspecified");
137*4dc78e53SAndroid Build Coastguard Worker 		break;
138*4dc78e53SAndroid Build Coastguard Worker 	case TC_ACT_PIPE:
139*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " pipe");
140*4dc78e53SAndroid Build Coastguard Worker 		break;
141*4dc78e53SAndroid Build Coastguard Worker 	case TC_ACT_STOLEN:
142*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " stolen");
143*4dc78e53SAndroid Build Coastguard Worker 		break;
144*4dc78e53SAndroid Build Coastguard Worker 	case TC_ACT_SHOT:
145*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " shot");
146*4dc78e53SAndroid Build Coastguard Worker 		break;
147*4dc78e53SAndroid Build Coastguard Worker 	case TC_ACT_QUEUED:
148*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " queued");
149*4dc78e53SAndroid Build Coastguard Worker 		break;
150*4dc78e53SAndroid Build Coastguard Worker 	case TC_ACT_REPEAT:
151*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " repeat");
152*4dc78e53SAndroid Build Coastguard Worker 		break;
153*4dc78e53SAndroid Build Coastguard Worker 	}
154*4dc78e53SAndroid Build Coastguard Worker }
155*4dc78e53SAndroid Build Coastguard Worker 
vlan_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)156*4dc78e53SAndroid Build Coastguard Worker static void vlan_dump_details(struct rtnl_tc *tc, void *data,
157*4dc78e53SAndroid Build Coastguard Worker                               struct nl_dump_params *p)
158*4dc78e53SAndroid Build Coastguard Worker {
159*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v = data;
160*4dc78e53SAndroid Build Coastguard Worker 
161*4dc78e53SAndroid Build Coastguard Worker 	if (!v)
162*4dc78e53SAndroid Build Coastguard Worker 		return;
163*4dc78e53SAndroid Build Coastguard Worker 
164*4dc78e53SAndroid Build Coastguard Worker 	if (v->v_flags & VLAN_F_MODE) {
165*4dc78e53SAndroid Build Coastguard Worker 		switch (v->v_parm.v_action) {
166*4dc78e53SAndroid Build Coastguard Worker 		case TCA_VLAN_ACT_POP:
167*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, " mode POP");
168*4dc78e53SAndroid Build Coastguard Worker 			break;
169*4dc78e53SAndroid Build Coastguard Worker 		case TCA_VLAN_ACT_PUSH:
170*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, " mode PUSH");
171*4dc78e53SAndroid Build Coastguard Worker 			break;
172*4dc78e53SAndroid Build Coastguard Worker 		case TCA_VLAN_ACT_MODIFY:
173*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, " mode MODIFY");
174*4dc78e53SAndroid Build Coastguard Worker 			break;
175*4dc78e53SAndroid Build Coastguard Worker 		}
176*4dc78e53SAndroid Build Coastguard Worker 	}
177*4dc78e53SAndroid Build Coastguard Worker 
178*4dc78e53SAndroid Build Coastguard Worker 	if (v->v_flags & VLAN_F_VID)
179*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " vlan id %u", v->v_vid);
180*4dc78e53SAndroid Build Coastguard Worker 
181*4dc78e53SAndroid Build Coastguard Worker 	if (v->v_flags & VLAN_F_PRIO)
182*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " priority %u", v->v_prio);
183*4dc78e53SAndroid Build Coastguard Worker 
184*4dc78e53SAndroid Build Coastguard Worker 	if (v->v_flags & VLAN_F_PROTO)
185*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " protocol %u", v->v_proto);
186*4dc78e53SAndroid Build Coastguard Worker }
187*4dc78e53SAndroid Build Coastguard Worker 
188*4dc78e53SAndroid Build Coastguard Worker /**
189*4dc78e53SAndroid Build Coastguard Worker  * @name Attribute Modifications
190*4dc78e53SAndroid Build Coastguard Worker  * @{
191*4dc78e53SAndroid Build Coastguard Worker  */
192*4dc78e53SAndroid Build Coastguard Worker 
193*4dc78e53SAndroid Build Coastguard Worker /**
194*4dc78e53SAndroid Build Coastguard Worker  * Set vlan mode
195*4dc78e53SAndroid Build Coastguard Worker  * @arg act             vlan action
196*4dc78e53SAndroid Build Coastguard Worker  * @arg mode            one of (TCA_VLAN_ACT_*: POP, PUSH, MODIFY)
197*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
198*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_vlan_set_mode(struct rtnl_act * act,int mode)199*4dc78e53SAndroid Build Coastguard Worker int rtnl_vlan_set_mode(struct rtnl_act *act, int mode)
200*4dc78e53SAndroid Build Coastguard Worker {
201*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v;
202*4dc78e53SAndroid Build Coastguard Worker 
203*4dc78e53SAndroid Build Coastguard Worker 	if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act))))
204*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
205*4dc78e53SAndroid Build Coastguard Worker 
206*4dc78e53SAndroid Build Coastguard Worker 	if (mode > TCA_VLAN_ACT_MODIFY)
207*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_RANGE;
208*4dc78e53SAndroid Build Coastguard Worker 
209*4dc78e53SAndroid Build Coastguard Worker 	v->v_parm.v_action = mode;
210*4dc78e53SAndroid Build Coastguard Worker 	v->v_flags |= VLAN_F_MODE;
211*4dc78e53SAndroid Build Coastguard Worker 
212*4dc78e53SAndroid Build Coastguard Worker 	return 0;
213*4dc78e53SAndroid Build Coastguard Worker }
214*4dc78e53SAndroid Build Coastguard Worker 
215*4dc78e53SAndroid Build Coastguard Worker /**
216*4dc78e53SAndroid Build Coastguard Worker  * Get vlan mode
217*4dc78e53SAndroid Build Coastguard Worker  * @arg act             vlan action
218*4dc78e53SAndroid Build Coastguard Worker  * @arg out_mode        vlan mode output paramter
219*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success if the vlan mode was returned or a negative error code.
220*4dc78e53SAndroid Build Coastguard Worker */
rtnl_vlan_get_mode(struct rtnl_act * act,int * out_mode)221*4dc78e53SAndroid Build Coastguard Worker int rtnl_vlan_get_mode(struct rtnl_act *act, int *out_mode)
222*4dc78e53SAndroid Build Coastguard Worker {
223*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v;
224*4dc78e53SAndroid Build Coastguard Worker 
225*4dc78e53SAndroid Build Coastguard Worker 	if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act))))
226*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
227*4dc78e53SAndroid Build Coastguard Worker 
228*4dc78e53SAndroid Build Coastguard Worker 	if (!(v->v_flags & VLAN_F_MODE))
229*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
230*4dc78e53SAndroid Build Coastguard Worker 
231*4dc78e53SAndroid Build Coastguard Worker 	*out_mode = v->v_parm.v_action;
232*4dc78e53SAndroid Build Coastguard Worker 	return 0;
233*4dc78e53SAndroid Build Coastguard Worker }
234*4dc78e53SAndroid Build Coastguard Worker 
235*4dc78e53SAndroid Build Coastguard Worker /**
236*4dc78e53SAndroid Build Coastguard Worker  * Set general action
237*4dc78e53SAndroid Build Coastguard Worker  * @arg act             vlan action
238*4dc78e53SAndroid Build Coastguard Worker  * @arg action          one of (TCA_ACT_*: PIPE, SHOT, GOTO_CHAIN, etc)
239*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
240*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_vlan_set_action(struct rtnl_act * act,int action)241*4dc78e53SAndroid Build Coastguard Worker int rtnl_vlan_set_action(struct rtnl_act *act, int action)
242*4dc78e53SAndroid Build Coastguard Worker {
243*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v;
244*4dc78e53SAndroid Build Coastguard Worker 
245*4dc78e53SAndroid Build Coastguard Worker 	if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act))))
246*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
247*4dc78e53SAndroid Build Coastguard Worker 
248*4dc78e53SAndroid Build Coastguard Worker 	v->v_parm.action = action;
249*4dc78e53SAndroid Build Coastguard Worker 	v->v_flags |= VLAN_F_ACT;
250*4dc78e53SAndroid Build Coastguard Worker 
251*4dc78e53SAndroid Build Coastguard Worker 	return 0;
252*4dc78e53SAndroid Build Coastguard Worker }
253*4dc78e53SAndroid Build Coastguard Worker 
254*4dc78e53SAndroid Build Coastguard Worker /**
255*4dc78e53SAndroid Build Coastguard Worker  * Get general action
256*4dc78e53SAndroid Build Coastguard Worker  * @arg act             vlan action
257*4dc78e53SAndroid Build Coastguard Worker  * @arg out_action      output parameter
258*4dc78e53SAndroid Build Coastguard Worker  * @return general 0 if out_action was set or a negative error code.
259*4dc78e53SAndroid Build Coastguard Worker */
rtnl_vlan_get_action(struct rtnl_act * act,int * out_action)260*4dc78e53SAndroid Build Coastguard Worker int rtnl_vlan_get_action(struct rtnl_act *act, int *out_action)
261*4dc78e53SAndroid Build Coastguard Worker {
262*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v;
263*4dc78e53SAndroid Build Coastguard Worker 
264*4dc78e53SAndroid Build Coastguard Worker 	if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act))))
265*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
266*4dc78e53SAndroid Build Coastguard Worker 
267*4dc78e53SAndroid Build Coastguard Worker 	if (!(v->v_flags & VLAN_F_ACT))
268*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
269*4dc78e53SAndroid Build Coastguard Worker 
270*4dc78e53SAndroid Build Coastguard Worker 	*out_action = v->v_parm.action;
271*4dc78e53SAndroid Build Coastguard Worker 	return 0;
272*4dc78e53SAndroid Build Coastguard Worker }
273*4dc78e53SAndroid Build Coastguard Worker 
274*4dc78e53SAndroid Build Coastguard Worker /**
275*4dc78e53SAndroid Build Coastguard Worker  * Set protocol
276*4dc78e53SAndroid Build Coastguard Worker  * @arg act             vlan action
277*4dc78e53SAndroid Build Coastguard Worker  * @arg protocol        one of (ETH_P_8021Q || ETH_P_8021AD)
278*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
279*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_vlan_set_protocol(struct rtnl_act * act,uint16_t protocol)280*4dc78e53SAndroid Build Coastguard Worker int rtnl_vlan_set_protocol(struct rtnl_act *act, uint16_t protocol)
281*4dc78e53SAndroid Build Coastguard Worker {
282*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v;
283*4dc78e53SAndroid Build Coastguard Worker 
284*4dc78e53SAndroid Build Coastguard Worker 	if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act))))
285*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
286*4dc78e53SAndroid Build Coastguard Worker 
287*4dc78e53SAndroid Build Coastguard Worker 	v->v_proto = protocol;
288*4dc78e53SAndroid Build Coastguard Worker 	v->v_flags |= VLAN_F_PROTO;
289*4dc78e53SAndroid Build Coastguard Worker 
290*4dc78e53SAndroid Build Coastguard Worker 	return 0;
291*4dc78e53SAndroid Build Coastguard Worker }
292*4dc78e53SAndroid Build Coastguard Worker 
293*4dc78e53SAndroid Build Coastguard Worker /**
294*4dc78e53SAndroid Build Coastguard Worker  * Get protocol
295*4dc78e53SAndroid Build Coastguard Worker  * @arg act             vlan action
296*4dc78e53SAndroid Build Coastguard Worker  * @arg out_protocol    protocol output argument
297*4dc78e53SAndroid Build Coastguard Worker  * @return 0 if the protocol was returned or a negative error code.
298*4dc78e53SAndroid Build Coastguard Worker */
rtnl_vlan_get_protocol(struct rtnl_act * act,uint16_t * out_protocol)299*4dc78e53SAndroid Build Coastguard Worker int rtnl_vlan_get_protocol(struct rtnl_act *act, uint16_t *out_protocol)
300*4dc78e53SAndroid Build Coastguard Worker {
301*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v;
302*4dc78e53SAndroid Build Coastguard Worker 
303*4dc78e53SAndroid Build Coastguard Worker 	if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act))))
304*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
305*4dc78e53SAndroid Build Coastguard Worker 
306*4dc78e53SAndroid Build Coastguard Worker 	if (!(v->v_flags & VLAN_F_PROTO))
307*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
308*4dc78e53SAndroid Build Coastguard Worker 
309*4dc78e53SAndroid Build Coastguard Worker 	*out_protocol = v->v_proto;
310*4dc78e53SAndroid Build Coastguard Worker 	return 0;
311*4dc78e53SAndroid Build Coastguard Worker }
312*4dc78e53SAndroid Build Coastguard Worker 
313*4dc78e53SAndroid Build Coastguard Worker /**
314*4dc78e53SAndroid Build Coastguard Worker  * Set vlan id
315*4dc78e53SAndroid Build Coastguard Worker  * @arg act             vlan action
316*4dc78e53SAndroid Build Coastguard Worker  * @arg vid             vlan id
317*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
318*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_vlan_set_vlan_id(struct rtnl_act * act,uint16_t vid)319*4dc78e53SAndroid Build Coastguard Worker int rtnl_vlan_set_vlan_id(struct rtnl_act *act, uint16_t vid)
320*4dc78e53SAndroid Build Coastguard Worker {
321*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v;
322*4dc78e53SAndroid Build Coastguard Worker 
323*4dc78e53SAndroid Build Coastguard Worker 	if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act))))
324*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
325*4dc78e53SAndroid Build Coastguard Worker 
326*4dc78e53SAndroid Build Coastguard Worker 	if (vid > 4095)
327*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_RANGE;
328*4dc78e53SAndroid Build Coastguard Worker 
329*4dc78e53SAndroid Build Coastguard Worker 	v->v_vid = vid;
330*4dc78e53SAndroid Build Coastguard Worker 	v->v_flags |= VLAN_F_VID;
331*4dc78e53SAndroid Build Coastguard Worker 
332*4dc78e53SAndroid Build Coastguard Worker 	return 0;
333*4dc78e53SAndroid Build Coastguard Worker }
334*4dc78e53SAndroid Build Coastguard Worker 
335*4dc78e53SAndroid Build Coastguard Worker /**
336*4dc78e53SAndroid Build Coastguard Worker  * Get vlan id
337*4dc78e53SAndroid Build Coastguard Worker  * @arg act             vlan action
338*4dc78e53SAndroid Build Coastguard Worker  * @arg out_vid         output vlan id
339*4dc78e53SAndroid Build Coastguard Worker  * @return 0 if the vlan id was returned or a negative error code.
340*4dc78e53SAndroid Build Coastguard Worker */
rtnl_vlan_get_vlan_id(struct rtnl_act * act,uint16_t * out_vid)341*4dc78e53SAndroid Build Coastguard Worker int rtnl_vlan_get_vlan_id(struct rtnl_act *act, uint16_t *out_vid)
342*4dc78e53SAndroid Build Coastguard Worker {
343*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v;
344*4dc78e53SAndroid Build Coastguard Worker 
345*4dc78e53SAndroid Build Coastguard Worker 	if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act))))
346*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
347*4dc78e53SAndroid Build Coastguard Worker 
348*4dc78e53SAndroid Build Coastguard Worker 	if (!(v->v_flags & VLAN_F_VID))
349*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
350*4dc78e53SAndroid Build Coastguard Worker 
351*4dc78e53SAndroid Build Coastguard Worker 	*out_vid = v->v_vid;
352*4dc78e53SAndroid Build Coastguard Worker 	return 0;
353*4dc78e53SAndroid Build Coastguard Worker }
354*4dc78e53SAndroid Build Coastguard Worker 
355*4dc78e53SAndroid Build Coastguard Worker /**
356*4dc78e53SAndroid Build Coastguard Worker  * Set vlan prio
357*4dc78e53SAndroid Build Coastguard Worker  * @arg act             vlan action
358*4dc78e53SAndroid Build Coastguard Worker  * @arg prio            vlan priority (0 - 7)
359*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
360*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_vlan_set_vlan_prio(struct rtnl_act * act,uint8_t prio)361*4dc78e53SAndroid Build Coastguard Worker int rtnl_vlan_set_vlan_prio(struct rtnl_act *act, uint8_t prio)
362*4dc78e53SAndroid Build Coastguard Worker {
363*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v;
364*4dc78e53SAndroid Build Coastguard Worker 
365*4dc78e53SAndroid Build Coastguard Worker 	if (!(v = (struct rtnl_vlan *) rtnl_tc_data(TC_CAST(act))))
366*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
367*4dc78e53SAndroid Build Coastguard Worker 
368*4dc78e53SAndroid Build Coastguard Worker 	if (prio > 7)
369*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_RANGE;
370*4dc78e53SAndroid Build Coastguard Worker 
371*4dc78e53SAndroid Build Coastguard Worker 	v->v_prio = prio;
372*4dc78e53SAndroid Build Coastguard Worker 	v->v_flags |= VLAN_F_PRIO;
373*4dc78e53SAndroid Build Coastguard Worker 
374*4dc78e53SAndroid Build Coastguard Worker 	return 0;
375*4dc78e53SAndroid Build Coastguard Worker }
376*4dc78e53SAndroid Build Coastguard Worker 
377*4dc78e53SAndroid Build Coastguard Worker /**
378*4dc78e53SAndroid Build Coastguard Worker  * Get vlan prio
379*4dc78e53SAndroid Build Coastguard Worker  * @arg act             vlan action
380*4dc78e53SAndroid Build Coastguard Worker  * @arg out_prio        the output vlan prio
381*4dc78e53SAndroid Build Coastguard Worker  * @return 0 if the vlan prio was returned or a negative error code.
382*4dc78e53SAndroid Build Coastguard Worker */
rtnl_vlan_get_vlan_prio(struct rtnl_act * act,uint8_t * out_prio)383*4dc78e53SAndroid Build Coastguard Worker int rtnl_vlan_get_vlan_prio(struct rtnl_act *act, uint8_t *out_prio)
384*4dc78e53SAndroid Build Coastguard Worker {
385*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_vlan *v;
386*4dc78e53SAndroid Build Coastguard Worker 
387*4dc78e53SAndroid Build Coastguard Worker 	if (!(v = (struct rtnl_vlan *) rtnl_tc_data_peek(TC_CAST(act))))
388*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
389*4dc78e53SAndroid Build Coastguard Worker 
390*4dc78e53SAndroid Build Coastguard Worker 	if (!(v->v_flags & VLAN_F_PRIO))
391*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
392*4dc78e53SAndroid Build Coastguard Worker 
393*4dc78e53SAndroid Build Coastguard Worker 	*out_prio = v->v_prio;
394*4dc78e53SAndroid Build Coastguard Worker 	return 0;
395*4dc78e53SAndroid Build Coastguard Worker }
396*4dc78e53SAndroid Build Coastguard Worker 
397*4dc78e53SAndroid Build Coastguard Worker /** @} */
398*4dc78e53SAndroid Build Coastguard Worker 
399*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_tc_ops vlan_ops = {
400*4dc78e53SAndroid Build Coastguard Worker 	.to_kind                = "vlan",
401*4dc78e53SAndroid Build Coastguard Worker 	.to_type                = RTNL_TC_TYPE_ACT,
402*4dc78e53SAndroid Build Coastguard Worker 	.to_size                = sizeof(struct rtnl_vlan),
403*4dc78e53SAndroid Build Coastguard Worker 	.to_msg_parser          = vlan_msg_parser,
404*4dc78e53SAndroid Build Coastguard Worker 	.to_free_data           = vlan_free_data,
405*4dc78e53SAndroid Build Coastguard Worker 	.to_clone               = NULL,
406*4dc78e53SAndroid Build Coastguard Worker 	.to_msg_fill            = vlan_msg_fill,
407*4dc78e53SAndroid Build Coastguard Worker 	.to_dump = {
408*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_LINE]      = vlan_dump_line,
409*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_DETAILS]   = vlan_dump_details,
410*4dc78e53SAndroid Build Coastguard Worker 	},
411*4dc78e53SAndroid Build Coastguard Worker };
412*4dc78e53SAndroid Build Coastguard Worker 
vlan_init(void)413*4dc78e53SAndroid Build Coastguard Worker static void _nl_init vlan_init(void)
414*4dc78e53SAndroid Build Coastguard Worker {
415*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_register(&vlan_ops);
416*4dc78e53SAndroid Build Coastguard Worker }
417*4dc78e53SAndroid Build Coastguard Worker 
vlan_exit(void)418*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit vlan_exit(void)
419*4dc78e53SAndroid Build Coastguard Worker {
420*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_unregister(&vlan_ops);
421*4dc78e53SAndroid Build Coastguard Worker }
422*4dc78e53SAndroid Build Coastguard Worker 
423*4dc78e53SAndroid Build Coastguard Worker /** @} */
424