libnl 3.7.0
nh_encap_mpls.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2
3#include <netlink-private/netlink.h>
4#include <netlink-private/types.h>
5#include <netlink-private/route/nexthop-encap.h>
6#include <netlink/route/nexthop.h>
7#include <linux/mpls_iptunnel.h>
8#include <linux/lwtunnel.h>
9
11 struct nl_addr *dst;
12 uint8_t ttl;
13};
14
15static void mpls_encap_dump(void *priv, struct nl_dump_params *dp)
16{
17 struct mpls_iptunnel_encap *encap_info = priv;
18 char buf[256];
19
20 nl_dump(dp, "%s ", nl_addr2str(encap_info->dst, buf, sizeof(buf)));
21
22 if (encap_info->ttl)
23 nl_dump(dp, "ttl %u ", encap_info->ttl);
24}
25
26static int mpls_encap_build_msg(struct nl_msg *msg, void *priv)
27{
28 struct mpls_iptunnel_encap *encap_info = priv;
29
30 NLA_PUT_ADDR(msg, MPLS_IPTUNNEL_DST, encap_info->dst);
31 if (encap_info->ttl)
32 NLA_PUT_U8(msg, MPLS_IPTUNNEL_TTL, encap_info->ttl);
33
34 return 0;
35
36nla_put_failure:
37 return -NLE_MSGSIZE;
38}
39
40static void mpls_encap_destructor(void *priv)
41{
42 struct mpls_iptunnel_encap *encap_info = priv;
43
44 nl_addr_put(encap_info->dst);
45}
46
47static struct nla_policy mpls_encap_policy[MPLS_IPTUNNEL_MAX + 1] = {
48 [MPLS_IPTUNNEL_DST] = { .type = NLA_U32 },
49 [MPLS_IPTUNNEL_TTL] = { .type = NLA_U8 },
50};
51
52static int mpls_encap_parse_msg(struct nlattr *nla, struct rtnl_nexthop *nh)
53{
54 struct nlattr *tb[MPLS_IPTUNNEL_MAX + 1];
55 struct nl_addr *labels;
56 uint8_t ttl = 0;
57 int err;
58
59 err = nla_parse_nested(tb, MPLS_IPTUNNEL_MAX, nla, mpls_encap_policy);
60 if (err < 0)
61 return err;
62
63 if (!tb[MPLS_IPTUNNEL_DST])
64 return -NLE_INVAL;
65
66 labels = nl_addr_alloc_attr(tb[MPLS_IPTUNNEL_DST], AF_MPLS);
67 if (!labels)
68 return -NLE_NOMEM;
69
70 if (tb[MPLS_IPTUNNEL_TTL])
71 ttl = nla_get_u8(tb[MPLS_IPTUNNEL_TTL]);
72
73 err = rtnl_route_nh_encap_mpls(nh, labels, ttl);
74
75 nl_addr_put(labels);
76
77 return err;
78}
79
80static int mpls_encap_compare(void *_a, void *_b)
81{
82 struct mpls_iptunnel_encap *a = _a;
83 struct mpls_iptunnel_encap *b = _b;
84 int diff = 0;
85
86 diff |= (a->ttl != b->ttl);
87 diff |= nl_addr_cmp(a->dst, b->dst);
88
89 return diff;
90}
91
92struct nh_encap_ops mpls_encap_ops = {
93 .encap_type = LWTUNNEL_ENCAP_MPLS,
94 .build_msg = mpls_encap_build_msg,
95 .parse_msg = mpls_encap_parse_msg,
96 .compare = mpls_encap_compare,
97 .dump = mpls_encap_dump,
98 .destructor = mpls_encap_destructor,
99};
100
101int rtnl_route_nh_encap_mpls(struct rtnl_nexthop *nh,
102 struct nl_addr *addr,
103 uint8_t ttl)
104{
105 struct mpls_iptunnel_encap *mpls_encap;
106 struct rtnl_nh_encap *rtnh_encap;
107
108 if (!addr)
109 return -NLE_INVAL;
110
111 rtnh_encap = calloc(1, sizeof(*rtnh_encap));
112 if (!rtnh_encap)
113 return -NLE_NOMEM;
114
115 mpls_encap = calloc(1, sizeof(*mpls_encap));
116 if (!mpls_encap) {
117 free(rtnh_encap);
118 return -NLE_NOMEM;
119 }
120
121 mpls_encap->dst = nl_addr_get(addr);
122 mpls_encap->ttl = ttl;
123
124 rtnh_encap->priv = mpls_encap;
125 rtnh_encap->ops = &mpls_encap_ops;
126
127 nh_set_encap(nh, rtnh_encap);
128
129 return 0;
130}
131
132struct nl_addr *rtnl_route_nh_get_encap_mpls_dst(struct rtnl_nexthop *nh)
133{
134 struct mpls_iptunnel_encap *mpls_encap;
135
136 if (!nh->rtnh_encap || nh->rtnh_encap->ops->encap_type != LWTUNNEL_ENCAP_MPLS)
137 return NULL;
138
139 mpls_encap = (struct mpls_iptunnel_encap *)nh->rtnh_encap->priv;
140 if (!mpls_encap)
141 return NULL;
142
143 return mpls_encap->dst;
144}
145
146uint8_t rtnl_route_nh_get_encap_mpls_ttl(struct rtnl_nexthop *nh)
147{
148 struct mpls_iptunnel_encap *mpls_encap;
149
150 if (!nh->rtnh_encap || nh->rtnh_encap->ops->encap_type != LWTUNNEL_ENCAP_MPLS)
151 return 0;
152
153 mpls_encap = (struct mpls_iptunnel_encap *)nh->rtnh_encap->priv;
154 if (!mpls_encap)
155 return 0;
156
157 return mpls_encap->ttl;
158}
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
Definition: addr.c:522
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
Definition: addr.c:256
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
Definition: addr.c:584
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition: addr.c:998
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition: addr.c:538
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition: attr.h:194
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
Definition: attr.h:283
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition: attr.c:602
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:1016
@ NLA_U8
8 bit integer
Definition: attr.h:35
@ NLA_U32
32 bit integer
Definition: attr.h:37
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:955
Dumping parameters.
Definition: types.h:28
Attribute validation policy.
Definition: attr.h:63
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:65