Skip to content

Commit 9f89452

Browse files
committed
ila-encap: Add support for ILA nexthop encapsulation
Full support as well as tests. Added rtnl_nh_clear_encap_ila_* functions to clear certain fields. This is needed because 0 is a valid value for those fields. Signed-off-by: Christoph Paasch <[email protected]>
1 parent e378f0e commit 9f89452

File tree

7 files changed

+511
-1
lines changed

7 files changed

+511
-1
lines changed

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ lib_libnl_route_3_la_SOURCES = \
528528
lib/route/nexthop.c \
529529
lib/route/nexthop_encap.c \
530530
lib/route/nh.c \
531+
lib/route/nh_encap_ila.c \
531532
lib/route/nh_encap_ip.c \
532533
lib/route/nh_encap_ip6.c \
533534
lib/route/nh_encap_mpls.c \

include/netlink/route/nexthop.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,23 @@ struct nl_addr *rtnl_nh_get_encap_ip6_src(struct rtnl_nh_encap *);
9191
extern int rtnl_nh_set_encap_ip6_flags(struct rtnl_nh_encap *, uint16_t);
9292
extern int rtnl_nh_get_encap_ip6_flags(struct rtnl_nh_encap *);
9393

94+
/* ILA encap */
95+
extern int rtnl_nh_encap_ila(struct rtnl_nh_encap *nh_encap, uint64_t locator);
96+
extern int rtnl_nh_get_encap_ila_locator(struct rtnl_nh_encap *nh_encap,
97+
uint64_t *locator);
98+
extern int rtnl_nh_set_encap_ila_csum_mode(struct rtnl_nh_encap *nh_encap,
99+
uint8_t csum_mode);
100+
extern int rtnl_nh_clear_encap_ila_csum_mode(struct rtnl_nh_encap *nh_encap);
101+
extern int rtnl_nh_get_encap_ila_csum_mode(struct rtnl_nh_encap *nh_encap);
102+
extern int rtnl_nh_set_encap_ila_ident_type(struct rtnl_nh_encap *nh_encap,
103+
uint8_t ident_type);
104+
extern int rtnl_nh_clear_encap_ila_ident_type(struct rtnl_nh_encap *nh_encap);
105+
extern int rtnl_nh_get_encap_ila_ident_type(struct rtnl_nh_encap *nh_encap);
106+
extern int rtnl_nh_set_encap_ila_hook_type(struct rtnl_nh_encap *nh_encap,
107+
uint8_t hook_type);
108+
extern int rtnl_nh_clear_encap_ila_hook_type(struct rtnl_nh_encap *nh_encap);
109+
extern int rtnl_nh_get_encap_ila_hook_type(struct rtnl_nh_encap *nh_encap);
110+
94111
/* IPv4 encap */
95112
extern int rtnl_nh_encap_ip(struct rtnl_nh_encap *nh_encap,
96113
struct nl_addr *dst);

lib/route/nexthop-encap.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,9 @@ extern struct nh_encap_ops ip6_encap_ops;
4444
* IPv4 encap
4545
*/
4646
extern struct nh_encap_ops ip_encap_ops;
47+
48+
/*
49+
* ILA encap
50+
*/
51+
extern struct nh_encap_ops ila_encap_ops;
4752
#endif

lib/route/nexthop_encap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ static struct lwtunnel_encap_type {
1515
[LWTUNNEL_ENCAP_MPLS] = { .name = "mpls", .ops = &mpls_encap_ops },
1616
[LWTUNNEL_ENCAP_IP] = { .name = "ip", .ops = &ip_encap_ops },
1717
[LWTUNNEL_ENCAP_IP6] = { .name = "ip6", .ops = &ip6_encap_ops },
18-
[LWTUNNEL_ENCAP_ILA] = { .name = "ila" },
18+
[LWTUNNEL_ENCAP_ILA] = { .name = "ila", .ops = &ila_encap_ops },
1919
[LWTUNNEL_ENCAP_BPF] = { .name = "bpf" },
2020
};
2121

lib/route/nh_encap_ila.c

Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
/* SPDX-License-Identifier: LGPL-2.1-only */
2+
3+
#include "nl-default.h"
4+
5+
#include <linux/ila.h>
6+
#include <linux/lwtunnel.h>
7+
8+
#include <netlink/route/nexthop.h>
9+
10+
#include "nexthop-encap.h"
11+
#include "nl-aux-route/nl-route.h"
12+
#include "nl-route.h"
13+
14+
struct ila_tunnel_encap {
15+
uint64_t locator;
16+
uint8_t csum_mode;
17+
uint8_t ident_type;
18+
uint8_t hook_type;
19+
bool has_csum_mode : 1;
20+
bool has_ident_type : 1;
21+
bool has_hook_type : 1;
22+
};
23+
24+
static void ila_encap_dump(void *priv, struct nl_dump_params *dp)
25+
{
26+
struct ila_tunnel_encap *ila_encap = priv;
27+
28+
nl_dump(dp, " locator 0x%llx ", (unsigned long long)ila_encap->locator);
29+
30+
if (ila_encap->has_csum_mode)
31+
nl_dump(dp, " csum-mode %u ", ila_encap->csum_mode);
32+
33+
if (ila_encap->has_ident_type)
34+
nl_dump(dp, " ident-type %u ", ila_encap->ident_type);
35+
36+
if (ila_encap->has_hook_type)
37+
nl_dump(dp, " hook-type %u ", ila_encap->hook_type);
38+
}
39+
40+
static int ila_encap_build_msg(struct nl_msg *msg, void *priv)
41+
{
42+
struct ila_tunnel_encap *ila_encap = priv;
43+
44+
NLA_PUT_U64(msg, ILA_ATTR_LOCATOR, ila_encap->locator);
45+
46+
if (ila_encap->has_csum_mode)
47+
NLA_PUT_U8(msg, ILA_ATTR_CSUM_MODE, ila_encap->csum_mode);
48+
49+
if (ila_encap->has_ident_type)
50+
NLA_PUT_U8(msg, ILA_ATTR_IDENT_TYPE, ila_encap->ident_type);
51+
52+
if (ila_encap->has_hook_type)
53+
NLA_PUT_U8(msg, ILA_ATTR_HOOK_TYPE, ila_encap->hook_type);
54+
55+
return 0;
56+
57+
nla_put_failure:
58+
return -NLE_MSGSIZE;
59+
}
60+
61+
static void *ila_encap_clone(void *priv)
62+
{
63+
return priv ? _nl_memdup(priv, sizeof(struct ila_tunnel_encap)) : NULL;
64+
}
65+
66+
static int ila_encap_compare(void *_a, void *_b)
67+
{
68+
struct ila_tunnel_encap *a = _a;
69+
struct ila_tunnel_encap *b = _b;
70+
71+
if (!a || !b)
72+
return a != b;
73+
74+
if (a->locator != b->locator)
75+
return 1;
76+
77+
if (a->has_csum_mode != b->has_csum_mode)
78+
return 1;
79+
80+
if (a->has_csum_mode && a->csum_mode != b->csum_mode)
81+
return 1;
82+
83+
if (a->has_ident_type != b->has_ident_type)
84+
return 1;
85+
86+
if (a->has_ident_type && a->ident_type != b->ident_type)
87+
return 1;
88+
89+
if (a->has_hook_type != b->has_hook_type)
90+
return 1;
91+
92+
if (a->has_hook_type && a->hook_type != b->hook_type)
93+
return 1;
94+
95+
return 0;
96+
}
97+
98+
static struct nla_policy ila_encap_policy[ILA_ATTR_MAX + 1] = {
99+
[ILA_ATTR_LOCATOR] = { .type = NLA_U64 },
100+
[ILA_ATTR_CSUM_MODE] = { .type = NLA_U8 },
101+
[ILA_ATTR_IDENT_TYPE] = { .type = NLA_U8 },
102+
[ILA_ATTR_HOOK_TYPE] = { .type = NLA_U8 },
103+
};
104+
105+
static int ila_encap_parse_msg(struct nlattr *nla,
106+
struct rtnl_nh_encap **encap_out)
107+
{
108+
_nl_auto_rtnl_nh_encap struct rtnl_nh_encap *nh_encap = NULL;
109+
struct nlattr *tb[ILA_ATTR_MAX + 1];
110+
uint64_t locator;
111+
int err;
112+
113+
err = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_encap_policy);
114+
if (err < 0)
115+
return err;
116+
117+
if (!tb[ILA_ATTR_LOCATOR])
118+
return -NLE_INVAL;
119+
120+
locator = nla_get_u64(tb[ILA_ATTR_LOCATOR]);
121+
122+
nh_encap = rtnl_nh_encap_alloc();
123+
if (!nh_encap)
124+
return -NLE_NOMEM;
125+
126+
err = rtnl_nh_encap_ila(nh_encap, locator);
127+
if (err < 0)
128+
return err;
129+
130+
if (tb[ILA_ATTR_CSUM_MODE]) {
131+
err = rtnl_nh_set_encap_ila_csum_mode(
132+
nh_encap, nla_get_u8(tb[ILA_ATTR_CSUM_MODE]));
133+
if (err < 0)
134+
return err;
135+
}
136+
137+
if (tb[ILA_ATTR_IDENT_TYPE]) {
138+
err = rtnl_nh_set_encap_ila_ident_type(
139+
nh_encap, nla_get_u8(tb[ILA_ATTR_IDENT_TYPE]));
140+
if (err < 0)
141+
return err;
142+
}
143+
144+
if (tb[ILA_ATTR_HOOK_TYPE]) {
145+
err = rtnl_nh_set_encap_ila_hook_type(
146+
nh_encap, nla_get_u8(tb[ILA_ATTR_HOOK_TYPE]));
147+
if (err < 0)
148+
return err;
149+
}
150+
151+
*encap_out = _nl_steal_pointer(&nh_encap);
152+
153+
return 0;
154+
}
155+
156+
struct nh_encap_ops ila_encap_ops = {
157+
.encap_type = LWTUNNEL_ENCAP_ILA,
158+
.build_msg = ila_encap_build_msg,
159+
.parse_msg = ila_encap_parse_msg,
160+
.compare = ila_encap_compare,
161+
.clone = ila_encap_clone,
162+
.dump = ila_encap_dump,
163+
};
164+
165+
static struct ila_tunnel_encap *nh_encap_get_ila(struct rtnl_nh_encap *nh_encap)
166+
{
167+
return nh_encap_check_and_get_priv(nh_encap, LWTUNNEL_ENCAP_ILA);
168+
}
169+
170+
int rtnl_nh_encap_ila(struct rtnl_nh_encap *nh_encap, uint64_t locator)
171+
{
172+
struct ila_tunnel_encap *ila_encap;
173+
174+
if (!nh_encap)
175+
return -NLE_INVAL;
176+
177+
ila_encap = calloc(1, sizeof(*ila_encap));
178+
if (!ila_encap)
179+
return -NLE_NOMEM;
180+
181+
ila_encap->locator = locator;
182+
183+
nh_encap->priv = ila_encap;
184+
nh_encap->ops = &ila_encap_ops;
185+
186+
return 0;
187+
}
188+
189+
int rtnl_nh_get_encap_ila_locator(struct rtnl_nh_encap *nh_encap,
190+
uint64_t *locator)
191+
{
192+
struct ila_tunnel_encap *ila_encap;
193+
194+
if (!locator)
195+
return -NLE_INVAL;
196+
197+
ila_encap = nh_encap_get_ila(nh_encap);
198+
if (!ila_encap)
199+
return -NLE_INVAL;
200+
201+
*locator = ila_encap->locator;
202+
203+
return 0;
204+
}
205+
206+
int rtnl_nh_set_encap_ila_csum_mode(struct rtnl_nh_encap *nh_encap,
207+
uint8_t csum_mode)
208+
{
209+
struct ila_tunnel_encap *ila_encap;
210+
211+
ila_encap = nh_encap_get_ila(nh_encap);
212+
if (!ila_encap)
213+
return -NLE_INVAL;
214+
215+
ila_encap->csum_mode = csum_mode;
216+
ila_encap->has_csum_mode = true;
217+
218+
return 0;
219+
}
220+
221+
int rtnl_nh_clear_encap_ila_csum_mode(struct rtnl_nh_encap *nh_encap)
222+
{
223+
struct ila_tunnel_encap *ila_encap;
224+
225+
ila_encap = nh_encap_get_ila(nh_encap);
226+
if (!ila_encap)
227+
return -NLE_INVAL;
228+
229+
ila_encap->has_csum_mode = false;
230+
ila_encap->csum_mode = 0;
231+
232+
return 0;
233+
}
234+
235+
int rtnl_nh_get_encap_ila_csum_mode(struct rtnl_nh_encap *nh_encap)
236+
{
237+
struct ila_tunnel_encap *ila_encap;
238+
239+
ila_encap = nh_encap_get_ila(nh_encap);
240+
if (!ila_encap)
241+
return -NLE_INVAL;
242+
243+
if (!ila_encap->has_csum_mode)
244+
return -NLE_MISSING_ATTR;
245+
246+
return ila_encap->csum_mode;
247+
}
248+
249+
int rtnl_nh_set_encap_ila_ident_type(struct rtnl_nh_encap *nh_encap,
250+
uint8_t ident_type)
251+
{
252+
struct ila_tunnel_encap *ila_encap;
253+
254+
ila_encap = nh_encap_get_ila(nh_encap);
255+
if (!ila_encap)
256+
return -NLE_INVAL;
257+
258+
ila_encap->ident_type = ident_type;
259+
ila_encap->has_ident_type = true;
260+
261+
return 0;
262+
}
263+
264+
int rtnl_nh_clear_encap_ila_ident_type(struct rtnl_nh_encap *nh_encap)
265+
{
266+
struct ila_tunnel_encap *ila_encap;
267+
268+
ila_encap = nh_encap_get_ila(nh_encap);
269+
if (!ila_encap)
270+
return -NLE_INVAL;
271+
272+
ila_encap->has_ident_type = false;
273+
ila_encap->ident_type = 0;
274+
275+
return 0;
276+
}
277+
278+
int rtnl_nh_get_encap_ila_ident_type(struct rtnl_nh_encap *nh_encap)
279+
{
280+
struct ila_tunnel_encap *ila_encap;
281+
282+
ila_encap = nh_encap_get_ila(nh_encap);
283+
if (!ila_encap)
284+
return -NLE_INVAL;
285+
286+
if (!ila_encap->has_ident_type)
287+
return -NLE_MISSING_ATTR;
288+
289+
return ila_encap->ident_type;
290+
}
291+
292+
int rtnl_nh_set_encap_ila_hook_type(struct rtnl_nh_encap *nh_encap,
293+
uint8_t hook_type)
294+
{
295+
struct ila_tunnel_encap *ila_encap;
296+
297+
ila_encap = nh_encap_get_ila(nh_encap);
298+
if (!ila_encap)
299+
return -NLE_INVAL;
300+
301+
ila_encap->hook_type = hook_type;
302+
ila_encap->has_hook_type = true;
303+
304+
return 0;
305+
}
306+
307+
int rtnl_nh_clear_encap_ila_hook_type(struct rtnl_nh_encap *nh_encap)
308+
{
309+
struct ila_tunnel_encap *ila_encap;
310+
311+
ila_encap = nh_encap_get_ila(nh_encap);
312+
if (!ila_encap)
313+
return -NLE_INVAL;
314+
315+
ila_encap->has_hook_type = false;
316+
ila_encap->hook_type = 0;
317+
318+
return 0;
319+
}
320+
321+
int rtnl_nh_get_encap_ila_hook_type(struct rtnl_nh_encap *nh_encap)
322+
{
323+
struct ila_tunnel_encap *ila_encap;
324+
325+
ila_encap = nh_encap_get_ila(nh_encap);
326+
if (!ila_encap)
327+
return -NLE_INVAL;
328+
329+
if (!ila_encap->has_hook_type)
330+
return -NLE_MISSING_ATTR;
331+
332+
return ila_encap->hook_type;
333+
}

0 commit comments

Comments
 (0)