libnl 3.12.0
nh_encap_mpls.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2
3#include "nl-default.h"
4
5#include <linux/mpls_iptunnel.h>
6#include <linux/lwtunnel.h>
7
8#include <netlink/route/nexthop.h>
9
10#include "nexthop-encap.h"
11#include "nl-aux-core/nl-core.h"
12#include "nl-aux-route/nl-route.h"
13#include "nl-route.h"
14
16 struct nl_addr *dst;
17 uint8_t ttl;
18};
19
20static void mpls_encap_dump(void *priv, struct nl_dump_params *dp)
21{
22 struct mpls_iptunnel_encap *encap_info = priv;
23 char buf[256];
24
25 nl_dump(dp, "%s ", nl_addr2str(encap_info->dst, buf, sizeof(buf)));
26
27 if (encap_info->ttl)
28 nl_dump(dp, "ttl %u ", encap_info->ttl);
29}
30
31static int mpls_encap_build_msg(struct nl_msg *msg, void *priv)
32{
33 struct mpls_iptunnel_encap *encap_info = priv;
34
35 NLA_PUT_ADDR(msg, MPLS_IPTUNNEL_DST, encap_info->dst);
36 if (encap_info->ttl)
37 NLA_PUT_U8(msg, MPLS_IPTUNNEL_TTL, encap_info->ttl);
38
39 return 0;
40
41nla_put_failure:
42 return -NLE_MSGSIZE;
43}
44
45static void mpls_encap_destructor(void *priv)
46{
47 struct mpls_iptunnel_encap *encap_info = priv;
48
49 nl_addr_put(encap_info->dst);
50}
51
52static void *mpls_encap_clone(void *priv)
53{
54 struct mpls_iptunnel_encap *src = priv;
55 struct mpls_iptunnel_encap *clone;
56
57 if (!src)
58 return NULL;
59
60 clone = calloc(1, sizeof(*clone));
61 if (!clone)
62 return NULL;
63
64 clone->dst = nl_addr_get(src->dst);
65 clone->ttl = src->ttl;
66
67 return clone;
68}
69
70static struct nla_policy mpls_encap_policy[MPLS_IPTUNNEL_MAX + 1] = {
71 [MPLS_IPTUNNEL_DST] = { .type = NLA_U32 },
72 [MPLS_IPTUNNEL_TTL] = { .type = NLA_U8 },
73};
74
75static int mpls_encap_parse_msg(struct nlattr *nla,
76 struct rtnl_nh_encap **encap_out)
77{
78 _nl_auto_rtnl_nh_encap struct rtnl_nh_encap *nh_encap = NULL;
79 _nl_auto_nl_addr struct nl_addr *labels = NULL;
80 struct nlattr *tb[MPLS_IPTUNNEL_MAX + 1];
81 uint8_t ttl = 0;
82 int err;
83
84 err = nla_parse_nested(tb, MPLS_IPTUNNEL_MAX, nla, mpls_encap_policy);
85 if (err < 0)
86 return err;
87
88 if (!tb[MPLS_IPTUNNEL_DST])
89 return -NLE_INVAL;
90
91 labels = nl_addr_alloc_attr(tb[MPLS_IPTUNNEL_DST], AF_MPLS);
92 if (!labels)
93 return -NLE_NOMEM;
94
95 if (tb[MPLS_IPTUNNEL_TTL])
96 ttl = nla_get_u8(tb[MPLS_IPTUNNEL_TTL]);
97
98 nh_encap = rtnl_nh_encap_alloc();
99 if (!nh_encap)
100 return -NLE_NOMEM;
101
102 err = rtnl_nh_encap_mpls(nh_encap, labels, ttl);
103 if (err < 0)
104 return err;
105
106 *encap_out = _nl_steal_pointer(&nh_encap);
107
108 return 0;
109}
110
111static int mpls_encap_compare(void *_a, void *_b)
112{
113 struct mpls_iptunnel_encap *a = _a;
114 struct mpls_iptunnel_encap *b = _b;
115 int diff = 0;
116
117 diff |= (a->ttl != b->ttl);
118 diff |= nl_addr_cmp(a->dst, b->dst);
119
120 return diff;
121}
122
123const struct nh_encap_ops mpls_encap_ops = {
124 .encap_type = LWTUNNEL_ENCAP_MPLS,
125 .build_msg = mpls_encap_build_msg,
126 .parse_msg = mpls_encap_parse_msg,
127 .compare = mpls_encap_compare,
128 .clone = mpls_encap_clone,
129 .dump = mpls_encap_dump,
130 .destructor = mpls_encap_destructor,
131};
132
133int rtnl_nh_encap_mpls(struct rtnl_nh_encap *nh_encap, struct nl_addr *dst,
134 uint8_t ttl)
135{
136 struct mpls_iptunnel_encap *mpls_encap;
137
138 if (!dst || !nh_encap)
139 return -NLE_INVAL;
140
141 mpls_encap = calloc(1, sizeof(*mpls_encap));
142 if (!mpls_encap) {
143 return -NLE_NOMEM;
144 }
145
146 mpls_encap->dst = nl_addr_get(dst);
147 mpls_encap->ttl = ttl;
148
149 nh_encap->priv = mpls_encap;
150 nh_encap->ops = &mpls_encap_ops;
151
152 return 0;
153}
154
155int rtnl_route_nh_encap_mpls(struct rtnl_nexthop *nh, struct nl_addr *addr,
156 uint8_t ttl)
157{
158 _nl_auto_rtnl_nh_encap struct rtnl_nh_encap *rtnh_encap = NULL;
159 int ret;
160
161 rtnh_encap = rtnl_nh_encap_alloc();
162 if (!rtnh_encap)
163 return -NLE_NOMEM;
164
165 ret = rtnl_nh_encap_mpls(rtnh_encap, addr, ttl);
166 if (ret < 0)
167 return ret;
168
169 rtnl_route_nh_set_encap(nh, _nl_steal_pointer(&rtnh_encap));
170
171 return 0;
172}
173
174static struct mpls_iptunnel_encap *
175nh_encap_get_mpls(struct rtnl_nh_encap *nh_encap)
176{
177 return (struct mpls_iptunnel_encap *)nh_encap_check_and_get_priv(
178 nh_encap, LWTUNNEL_ENCAP_MPLS);
179}
180
181struct nl_addr *rtnl_nh_get_encap_mpls_dst(struct rtnl_nh_encap *nh_encap)
182{
183 struct mpls_iptunnel_encap *mpls_encap;
184
185 mpls_encap = nh_encap_get_mpls(nh_encap);
186 if (!mpls_encap)
187 return NULL;
188
189 return mpls_encap->dst;
190}
191
192struct nl_addr *rtnl_route_nh_get_encap_mpls_dst(struct rtnl_nexthop *nh)
193{
194 return rtnl_nh_get_encap_mpls_dst(nh->rtnh_encap);
195}
196
197int rtnl_nh_get_encap_mpls_ttl(struct rtnl_nh_encap *nh_encap)
198{
199 struct mpls_iptunnel_encap *mpls_encap;
200
201 mpls_encap = nh_encap_get_mpls(nh_encap);
202 if (!mpls_encap)
203 return -NLE_INVAL;
204
205 return mpls_encap->ttl;
206}
207
208uint8_t rtnl_route_nh_get_encap_mpls_ttl(struct rtnl_nexthop *nh)
209{
210 int ttl = rtnl_nh_get_encap_mpls_ttl(nh->rtnh_encap);
211
212 if (ttl < 0)
213 return 0;
214 return (uint8_t)ttl;
215}
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
Definition addr.c:525
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
Definition addr.c:261
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
Definition addr.c:587
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition addr.c:1001
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition addr.c:541
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition attr.h:201
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
Definition attr.h:290
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition attr.c:614
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition attr.c:1101
@ NLA_U8
8 bit integer
Definition attr.h:35
@ NLA_U32
32 bit integer
Definition attr.h:37
int rtnl_route_nh_set_encap(struct rtnl_nexthop *nh, struct rtnl_nh_encap *nh_encap)
Set nexthop encapsulation.
Definition nexthop.c:396
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
Dumping parameters.
Definition types.h:32
Attribute validation policy.
Definition attr.h:66