libnl 3.9.0
mirred.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2013 Cong Wang <xiyou.wangcong@gmail.com>
4 */
5
6/**
7 * @ingroup act
8 * @defgroup act_mirred Mirror and Redirect
9 *
10 * @{
11 */
12
13#include "nl-default.h"
14
15#include <netlink/netlink.h>
16#include <netlink/attr.h>
17#include <netlink/utils.h>
18#include <netlink/route/act/mirred.h>
19
20#include "tc-api.h"
21
23 struct tc_mirred m_parm;
24};
25
26static struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
27 [TCA_MIRRED_PARMS] = { .minlen = sizeof(struct tc_mirred) },
28};
29
30static int mirred_msg_parser(struct rtnl_tc *tc, void *data)
31{
32 struct rtnl_mirred *u = data;
33 struct nlattr *tb[TCA_MIRRED_MAX + 1];
34 int err;
35
36 err = tca_parse(tb, TCA_MIRRED_MAX, tc, mirred_policy);
37 if (err < 0)
38 return err;
39
40 if (!tb[TCA_MIRRED_PARMS])
41 return -NLE_MISSING_ATTR;
42
43 nla_memcpy(&u->m_parm, tb[TCA_MIRRED_PARMS], sizeof(u->m_parm));
44 return 0;
45}
46
47static void mirred_free_data(struct rtnl_tc *tc, void *data)
48{
49}
50
51static void mirred_dump_line(struct rtnl_tc *tc, void *data,
52 struct nl_dump_params *p)
53{
54 struct rtnl_mirred *u = data;
55 if (!u)
56 return;
57
58 nl_dump(p, " index %u", u->m_parm.ifindex);
59
60 if (u->m_parm.eaction == TCA_EGRESS_MIRROR)
61 nl_dump(p, " egress mirror");
62 else if (u->m_parm.eaction == TCA_EGRESS_REDIR)
63 nl_dump(p, " egress redirect");
64
65 switch(u->m_parm.action) {
66 case TC_ACT_UNSPEC:
67 nl_dump(p, " unspecified");
68 break;
69 case TC_ACT_PIPE:
70 nl_dump(p, " pipe");
71 break;
72 case TC_ACT_STOLEN:
73 nl_dump(p, " stolen");
74 break;
75 case TC_ACT_SHOT:
76 nl_dump(p, " shot");
77 break;
78 case TC_ACT_QUEUED:
79 nl_dump(p, " queued");
80 break;
81 case TC_ACT_REPEAT:
82 nl_dump(p, " repeat");
83 break;
84 }
85}
86
87static void mirred_dump_details(struct rtnl_tc *tc, void *data,
88 struct nl_dump_params *p)
89{
90}
91
92static void mirred_dump_stats(struct rtnl_tc *tc, void *data,
93 struct nl_dump_params *p)
94{
95 struct rtnl_mirred *u = data;
96
97 if (!u)
98 return;
99 /* TODO */
100}
101
102
103static int mirred_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
104{
105 struct rtnl_mirred *u = data;
106
107 if (!u)
108 return 0;
109
110 NLA_PUT(msg, TCA_MIRRED_PARMS, sizeof(u->m_parm), &u->m_parm);
111 return 0;
112
113nla_put_failure:
114 return -NLE_NOMEM;
115}
116
117/**
118 * @name Attribute Modifications
119 * @{
120 */
121
122int rtnl_mirred_set_action(struct rtnl_act *act, int action)
123{
124 struct rtnl_mirred *u;
125
126 if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
127 return -NLE_NOMEM;
128
129 if (action > TCA_INGRESS_MIRROR || action < TCA_EGRESS_REDIR)
130 return -NLE_INVAL;
131
132 switch (action) {
133 case TCA_EGRESS_MIRROR:
134 case TCA_EGRESS_REDIR:
135 u->m_parm.eaction = action;
136 break;
137 case TCA_INGRESS_REDIR:
138 case TCA_INGRESS_MIRROR:
139 default:
140 return NLE_OPNOTSUPP;
141 }
142 return 0;
143}
144
145int rtnl_mirred_get_action(struct rtnl_act *act)
146{
147 struct rtnl_mirred *u;
148
149 if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
150 return -NLE_NOMEM;
151 return u->m_parm.eaction;
152}
153
154int rtnl_mirred_set_ifindex(struct rtnl_act *act, uint32_t ifindex)
155{
156 struct rtnl_mirred *u;
157
158 if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
159 return -NLE_NOMEM;
160
161 u->m_parm.ifindex = ifindex;
162 return 0;
163}
164
165uint32_t rtnl_mirred_get_ifindex(struct rtnl_act *act)
166{
167 struct rtnl_mirred *u;
168
169 if ((u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
170 return u->m_parm.ifindex;
171 return 0;
172}
173
174int rtnl_mirred_set_policy(struct rtnl_act *act, int policy)
175{
176 struct rtnl_mirred *u;
177
178 if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
179 return -NLE_NOMEM;
180
181 u->m_parm.action = policy;
182
183 return 0;
184}
185
186int rtnl_mirred_get_policy(struct rtnl_act *act)
187{
188 struct rtnl_mirred *u;
189
190 if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
191 return -NLE_NOMEM;
192 return u->m_parm.action;
193}
194
195/** @} */
196
197static struct rtnl_tc_ops mirred_ops = {
198 .to_kind = "mirred",
199 .to_type = RTNL_TC_TYPE_ACT,
200 .to_size = sizeof(struct rtnl_mirred),
201 .to_msg_parser = mirred_msg_parser,
202 .to_free_data = mirred_free_data,
203 .to_clone = NULL,
204 .to_msg_fill = mirred_msg_fill,
205 .to_dump = {
206 [NL_DUMP_LINE] = mirred_dump_line,
207 [NL_DUMP_DETAILS] = mirred_dump_details,
208 [NL_DUMP_STATS] = mirred_dump_stats,
209 },
210};
211
212static void _nl_init mirred_init(void)
213{
214 rtnl_tc_register(&mirred_ops);
215}
216
217static void _nl_exit mirred_exit(void)
218{
219 rtnl_tc_unregister(&mirred_ops);
220}
221
222/** @} */
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition attr.h:159
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition attr.c:351
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition tc.h:50
void * rtnl_tc_data(struct rtnl_tc *)
Return pointer to private data of traffic control object.
Definition tc.c:1079
int rtnl_tc_register(struct rtnl_tc_ops *)
Register a traffic control module.
Definition tc.c:1018
void rtnl_tc_unregister(struct rtnl_tc_ops *)
Unregister a traffic control module.
Definition tc.c:1052
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1017
@ NL_DUMP_STATS
Dump all attributes including statistics.
Definition types.h:22
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition types.h:20
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition types.h:21
Dumping parameters.
Definition types.h:32
Attribute validation policy.
Definition attr.h:63
uint16_t minlen
Minimal length of payload required.
Definition attr.h:68