libnl: /data/src/libnl3/lib/route/nh_encap_mpls.c Source File

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