19 #include <netlink-private/netlink.h>
20 #include <netlink-private/tc.h>
21 #include <netlink/netlink.h>
22 #include <netlink/attr.h>
23 #include <netlink/utils.h>
24 #include <netlink-private/route/tc-api.h>
25 #include <netlink/route/act/mirred.h>
27 static struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
28 [TCA_MIRRED_PARMS] = { .
minlen =
sizeof(
struct tc_mirred) },
31 static int mirred_msg_parser(
struct rtnl_tc *tc,
void *data)
33 struct rtnl_mirred *u = data;
34 struct nlattr *tb[TCA_MIRRED_MAX + 1];
37 err = tca_parse(tb, TCA_MIRRED_MAX, tc, mirred_policy);
41 if (!tb[TCA_MIRRED_PARMS])
42 return -NLE_MISSING_ATTR;
44 nla_memcpy(&u->m_parm, tb[TCA_MIRRED_PARMS],
sizeof(u->m_parm));
48 static void mirred_free_data(
struct rtnl_tc *tc,
void *data)
52 static int mirred_clone(
void *_dst,
void *_src)
54 struct rtnl_mirred *dst = _dst, *src = _src;
56 memcpy(&dst->m_parm, &src->m_parm,
sizeof(src->m_parm));
60 static void mirred_dump_line(
struct rtnl_tc *tc,
void *data,
63 struct rtnl_mirred *u = data;
67 nl_dump(p,
" index %u", u->m_parm.ifindex);
69 if (u->m_parm.eaction == TCA_EGRESS_MIRROR)
71 else if (u->m_parm.eaction == TCA_EGRESS_REDIR)
74 switch(u->m_parm.action) {
96 static void mirred_dump_details(
struct rtnl_tc *tc,
void *data,
101 static void mirred_dump_stats(
struct rtnl_tc *tc,
void *data,
104 struct rtnl_mirred *u = data;
112 static int mirred_msg_fill(
struct rtnl_tc *tc,
void *data,
struct nl_msg *msg)
114 struct rtnl_mirred *u = data;
119 NLA_PUT(msg, TCA_MIRRED_PARMS,
sizeof(u->m_parm), &u->m_parm);
131 int rtnl_mirred_set_action(
struct rtnl_act *act,
int action)
133 struct rtnl_mirred *u;
138 if (action > TCA_INGRESS_MIRROR || action < TCA_EGRESS_REDIR)
142 case TCA_EGRESS_MIRROR:
143 case TCA_EGRESS_REDIR:
144 u->m_parm.eaction = action;
146 case TCA_INGRESS_REDIR:
147 case TCA_INGRESS_MIRROR:
149 return NLE_OPNOTSUPP;
154 int rtnl_mirred_get_action(
struct rtnl_act *act)
156 struct rtnl_mirred *u;
160 return u->m_parm.eaction;
163 int rtnl_mirred_set_ifindex(
struct rtnl_act *act, uint32_t ifindex)
165 struct rtnl_mirred *u;
170 u->m_parm.ifindex = ifindex;
174 uint32_t rtnl_mirred_get_ifindex(
struct rtnl_act *act)
176 struct rtnl_mirred *u;
179 return u->m_parm.ifindex;
183 int rtnl_mirred_set_policy(
struct rtnl_act *act,
int policy)
185 struct rtnl_mirred *u;
190 if (policy > TC_POLICE_PIPE || policy < TC_POLICE_OK)
193 switch (u->m_parm.eaction) {
194 case TCA_EGRESS_MIRROR:
195 case TCA_EGRESS_REDIR:
196 u->m_parm.action = policy;
198 case TCA_INGRESS_REDIR:
199 case TCA_INGRESS_MIRROR:
201 return NLE_OPNOTSUPP;
206 int rtnl_mirred_get_policy(
struct rtnl_act *act)
208 struct rtnl_mirred *u;
212 return u->m_parm.action;
217 static struct rtnl_tc_ops mirred_ops = {
219 .to_type = RTNL_TC_TYPE_ACT,
220 .to_size =
sizeof(
struct rtnl_mirred),
221 .to_msg_parser = mirred_msg_parser,
222 .to_free_data = mirred_free_data,
223 .to_clone = mirred_clone,
224 .to_msg_fill = mirred_msg_fill,
232 static void __init mirred_init(
void)
237 static void __exit mirred_exit(
void)