13#include <netlink-private/netlink.h>
14#include <netlink-private/tc.h>
15#include <netlink/netlink.h>
16#include <netlink/attr.h>
17#include <netlink/utils.h>
18#include <netlink-private/route/tc-api.h>
19#include <netlink/route/act/vlan.h>
22#define VLAN_F_VID (1 << 0)
23#define VLAN_F_PROTO (1 << 1)
24#define VLAN_F_PRIO (1 << 2)
25#define VLAN_F_ACT (1 << 3)
26#define VLAN_F_MODE (1 << 4)
28static struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
29 [TCA_VLAN_PARMS] = { .
minlen =
sizeof(
struct tc_vlan) },
30 [TCA_VLAN_PUSH_VLAN_ID] = { .type =
NLA_U16 },
31 [TCA_VLAN_PUSH_VLAN_PROTOCOL] = { .type =
NLA_U16 },
32 [TCA_VLAN_PUSH_VLAN_PRIORITY] = { .type =
NLA_U8 },
35static int vlan_msg_parser(
struct rtnl_tc *tc,
void *data)
37 struct rtnl_vlan *v = data;
38 struct nlattr *tb[TCA_VLAN_MAX + 1];
41 err = tca_parse(tb, TCA_VLAN_MAX, tc, vlan_policy);
46 if (!tb[TCA_VLAN_PARMS])
47 return -NLE_MISSING_ATTR;
49 nla_memcpy(&v->v_parm, tb[TCA_VLAN_PARMS],
sizeof(v->v_parm));
50 v->v_flags |= VLAN_F_ACT;
51 v->v_flags |= VLAN_F_MODE;
54 if (tb[TCA_VLAN_PUSH_VLAN_ID]) {
56 v->v_flags |= VLAN_F_VID;
59 if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) {
60 v->v_proto =
nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]);
61 v->v_flags |= VLAN_F_PROTO;
64 if (tb[TCA_VLAN_PUSH_VLAN_PRIORITY]) {
65 v->v_prio =
nla_get_u8(tb[TCA_VLAN_PUSH_VLAN_PRIORITY]);
66 v->v_flags |= VLAN_F_PRIO;
72static int vlan_msg_fill(
struct rtnl_tc *tc,
void *data,
struct nl_msg *msg)
74 struct rtnl_vlan *v = data;
78 if (!(v->v_flags & VLAN_F_MODE))
79 return -NLE_MISSING_ATTR;
81 NLA_PUT(msg, TCA_VLAN_PARMS,
sizeof(v->v_parm), &v->v_parm);
84 if ((v->v_parm.v_action != TCA_VLAN_ACT_POP) && !(v->v_flags & VLAN_F_VID))
85 return -NLE_MISSING_ATTR;
87 if (v->v_flags & VLAN_F_VID)
90 if (v->v_flags & VLAN_F_PROTO)
91 NLA_PUT_U16(msg, TCA_VLAN_PUSH_VLAN_PROTOCOL, v->v_proto);
93 if (v->v_flags & VLAN_F_PRIO)
94 NLA_PUT_U8(msg, TCA_VLAN_PUSH_VLAN_PRIORITY, v->v_prio);
102static void vlan_free_data(
struct rtnl_tc *tc,
void *data)
106static void vlan_dump_line(
struct rtnl_tc *tc,
void *data,
109 struct rtnl_vlan *v = data;
114 if (!(v->v_flags & VLAN_F_ACT))
117 if (TC_ACT_EXT_CMP(v->v_parm.action, TC_ACT_GOTO_CHAIN))
118 nl_dump(p,
" goto chain %u", v->v_parm.action & TC_ACT_EXT_VAL_MASK);
120 if (TC_ACT_EXT_CMP(v->v_parm.action, TC_ACT_JUMP))
121 nl_dump(p,
" jump %u", v->v_parm.action & TC_ACT_EXT_VAL_MASK);
123 switch(v->v_parm.action){
145static void vlan_dump_details(
struct rtnl_tc *tc,
void *data,
148 struct rtnl_vlan *v = data;
153 if (v->v_flags & VLAN_F_MODE) {
154 switch (v->v_parm.v_action) {
155 case TCA_VLAN_ACT_POP:
158 case TCA_VLAN_ACT_PUSH:
161 case TCA_VLAN_ACT_MODIFY:
167 if (v->v_flags & VLAN_F_VID)
168 nl_dump(p,
" vlan id %u", v->v_vid);
170 if (v->v_flags & VLAN_F_PRIO)
171 nl_dump(p,
" priority %u", v->v_prio);
173 if (v->v_flags & VLAN_F_PROTO)
174 nl_dump(p,
" protocol %u", v->v_proto);
195 if (mode > TCA_VLAN_ACT_MODIFY)
198 v->v_parm.v_action = mode;
199 v->v_flags |= VLAN_F_MODE;
217 if (!(v->v_flags & VLAN_F_MODE))
218 return -NLE_MISSING_ATTR;
220 *out_mode = v->v_parm.v_action;
237 v->v_parm.action = action;
238 v->v_flags |= VLAN_F_ACT;
256 if (!(v->v_flags & VLAN_F_ACT))
257 return -NLE_MISSING_ATTR;
259 *out_action = v->v_parm.action;
276 v->v_proto = protocol;
277 v->v_flags |= VLAN_F_PROTO;
295 if (!(v->v_flags & VLAN_F_PROTO))
296 return -NLE_MISSING_ATTR;
298 *out_protocol = v->v_proto;
319 v->v_flags |= VLAN_F_VID;
337 if (!(v->v_flags & VLAN_F_VID))
338 return -NLE_MISSING_ATTR;
361 v->v_flags |= VLAN_F_PRIO;
379 if (!(v->v_flags & VLAN_F_PRIO))
380 return -NLE_MISSING_ATTR;
382 *out_prio = v->v_prio;
388static struct rtnl_tc_ops vlan_ops = {
390 .to_type = RTNL_TC_TYPE_ACT,
391 .to_size =
sizeof(
struct rtnl_vlan),
392 .to_msg_parser = vlan_msg_parser,
393 .to_free_data = vlan_free_data,
395 .to_msg_fill = vlan_msg_fill,
402static void __init vlan_init(
void)
407static void __exit vlan_exit(
void)
int rtnl_vlan_get_vlan_prio(struct rtnl_act *act, uint8_t *out_prio)
Get vlan prio.
int rtnl_vlan_set_mode(struct rtnl_act *act, int mode)
Set vlan mode.
int rtnl_vlan_set_protocol(struct rtnl_act *act, uint16_t protocol)
Set protocol.
int rtnl_vlan_set_vlan_prio(struct rtnl_act *act, uint8_t prio)
Set vlan prio.
int rtnl_vlan_set_action(struct rtnl_act *act, int action)
Set general action.
int rtnl_vlan_set_vlan_id(struct rtnl_act *act, uint16_t vid)
Set vlan id.
int rtnl_vlan_get_protocol(struct rtnl_act *act, uint16_t *out_protocol)
Get protocol.
int rtnl_vlan_get_vlan_id(struct rtnl_act *act, uint16_t *out_vid)
Get vlan id.
int rtnl_vlan_get_mode(struct rtnl_act *act, int *out_mode)
Get vlan mode.
int rtnl_vlan_get_action(struct rtnl_act *act, int *out_action)
Get general action.
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
void * rtnl_tc_data_peek(struct rtnl_tc *tc)
Returns the private data of the traffic control object.
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
void * rtnl_tc_data(struct rtnl_tc *tc)
Return pointer to private data of traffic control object.
int rtnl_tc_register(struct rtnl_tc_ops *ops)
Register a traffic control module.
void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
Unregister a traffic control module.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
@ NL_DUMP_LINE
Dump object briefly on one line.
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Attribute validation policy.
uint16_t minlen
Minimal length of payload required.