libnl  3.2.24-rc1
mirred.c
1 /*
2  * lib/route/cls/mirred.c mirred action
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation version 2.1
7  * of the License.
8  *
9  * Copyright (c) 2013 Cong Wang <xiyou.wangcong@gmail.com>
10  */
11 
12 /**
13  * @ingroup act
14  * @defgroup act_mirred Mirror and Redirect
15  *
16  * @{
17  */
18 
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>
26 
27 static struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
28  [TCA_MIRRED_PARMS] = { .minlen = sizeof(struct tc_mirred) },
29 };
30 
31 static int mirred_msg_parser(struct rtnl_tc *tc, void *data)
32 {
33  struct rtnl_mirred *u = data;
34  struct nlattr *tb[TCA_MIRRED_MAX + 1];
35  int err;
36 
37  err = tca_parse(tb, TCA_MIRRED_MAX, tc, mirred_policy);
38  if (err < 0)
39  return err;
40 
41  if (!tb[TCA_MIRRED_PARMS])
42  return -NLE_MISSING_ATTR;
43 
44  nla_memcpy(&u->m_parm, tb[TCA_MIRRED_PARMS], sizeof(u->m_parm));
45  return 0;
46 }
47 
48 static void mirred_free_data(struct rtnl_tc *tc, void *data)
49 {
50 }
51 
52 static int mirred_clone(void *_dst, void *_src)
53 {
54  struct rtnl_mirred *dst = _dst, *src = _src;
55 
56  memcpy(&dst->m_parm, &src->m_parm, sizeof(src->m_parm));
57  return 0;
58 }
59 
60 static void mirred_dump_line(struct rtnl_tc *tc, void *data,
61  struct nl_dump_params *p)
62 {
63  struct rtnl_mirred *u = data;
64  if (!u)
65  return;
66 
67  nl_dump(p, " index %u", u->m_parm.ifindex);
68 
69  if (u->m_parm.eaction == TCA_EGRESS_MIRROR)
70  nl_dump(p, " egress mirror");
71  else if (u->m_parm.eaction == TCA_EGRESS_REDIR)
72  nl_dump(p, " egress redirect");
73 
74  switch(u->m_parm.action) {
75  case TC_ACT_UNSPEC:
76  nl_dump(p, " unspecified");
77  break;
78  case TC_ACT_PIPE:
79  nl_dump(p, " pipe");
80  break;
81  case TC_ACT_STOLEN:
82  nl_dump(p, " stolen");
83  break;
84  case TC_ACT_SHOT:
85  nl_dump(p, " shot");
86  break;
87  case TC_ACT_QUEUED:
88  nl_dump(p, " queued");
89  break;
90  case TC_ACT_REPEAT:
91  nl_dump(p, " repeat");
92  break;
93  }
94 }
95 
96 static void mirred_dump_details(struct rtnl_tc *tc, void *data,
97  struct nl_dump_params *p)
98 {
99 }
100 
101 static void mirred_dump_stats(struct rtnl_tc *tc, void *data,
102  struct nl_dump_params *p)
103 {
104  struct rtnl_mirred *u = data;
105 
106  if (!u)
107  return;
108  /* TODO */
109 }
110 
111 
112 static int mirred_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
113 {
114  struct rtnl_mirred *u = data;
115 
116  if (!u)
117  return 0;
118 
119  NLA_PUT(msg, TCA_MIRRED_PARMS, sizeof(u->m_parm), &u->m_parm);
120  return 0;
121 
122 nla_put_failure:
123  return -NLE_NOMEM;
124 }
125 
126 /**
127  * @name Attribute Modifications
128  * @{
129  */
130 
131 int rtnl_mirred_set_action(struct rtnl_act *act, int action)
132 {
133  struct rtnl_mirred *u;
134 
135  if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
136  return -NLE_NOMEM;
137 
138  if (action > TCA_INGRESS_MIRROR || action < TCA_EGRESS_REDIR)
139  return -NLE_INVAL;
140 
141  switch (action) {
142  case TCA_EGRESS_MIRROR:
143  case TCA_EGRESS_REDIR:
144  u->m_parm.eaction = action;
145  break;
146  case TCA_INGRESS_REDIR:
147  case TCA_INGRESS_MIRROR:
148  default:
149  return NLE_OPNOTSUPP;
150  }
151  return 0;
152 }
153 
154 int rtnl_mirred_get_action(struct rtnl_act *act)
155 {
156  struct rtnl_mirred *u;
157 
158  if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
159  return -NLE_NOMEM;
160  return u->m_parm.eaction;
161 }
162 
163 int rtnl_mirred_set_ifindex(struct rtnl_act *act, uint32_t ifindex)
164 {
165  struct rtnl_mirred *u;
166 
167  if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
168  return -NLE_NOMEM;
169 
170  u->m_parm.ifindex = ifindex;
171  return 0;
172 }
173 
174 uint32_t rtnl_mirred_get_ifindex(struct rtnl_act *act)
175 {
176  struct rtnl_mirred *u;
177 
178  if ((u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
179  return u->m_parm.ifindex;
180  return 0;
181 }
182 
183 int rtnl_mirred_set_policy(struct rtnl_act *act, int policy)
184 {
185  struct rtnl_mirred *u;
186 
187  if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
188  return -NLE_NOMEM;
189 
190  if (policy > TC_POLICE_PIPE || policy < TC_POLICE_OK)
191  return -NLE_INVAL;
192 
193  switch (u->m_parm.eaction) {
194  case TCA_EGRESS_MIRROR:
195  case TCA_EGRESS_REDIR:
196  u->m_parm.action = policy;
197  break;
198  case TCA_INGRESS_REDIR:
199  case TCA_INGRESS_MIRROR:
200  default:
201  return NLE_OPNOTSUPP;
202  }
203  return 0;
204 }
205 
206 int rtnl_mirred_get_policy(struct rtnl_act *act)
207 {
208  struct rtnl_mirred *u;
209 
210  if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
211  return -NLE_NOMEM;
212  return u->m_parm.action;
213 }
214 
215 /** @} */
216 
217 static struct rtnl_tc_ops mirred_ops = {
218  .to_kind = "mirred",
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,
225  .to_dump = {
226  [NL_DUMP_LINE] = mirred_dump_line,
227  [NL_DUMP_DETAILS] = mirred_dump_details,
228  [NL_DUMP_STATS] = mirred_dump_stats,
229  },
230 };
231 
232 static void __init mirred_init(void)
233 {
234  rtnl_tc_register(&mirred_ops);
235 }
236 
237 static void __exit mirred_exit(void)
238 {
239  rtnl_tc_unregister(&mirred_ops);
240 }
241 
242 /** @} */