libnl 3.12.0
nexthop_encap.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2
3#include "nl-default.h"
4
5#include <linux/lwtunnel.h>
6
7#include "nl-route.h"
8#include "nexthop-encap.h"
9
10static const struct lwtunnel_encap_type {
11 const char *name;
12 const struct nh_encap_ops *ops;
13} lwtunnel_encap_types[__LWTUNNEL_ENCAP_MAX] = {
14 [LWTUNNEL_ENCAP_NONE] = { .name = "none" },
15 [LWTUNNEL_ENCAP_MPLS] = { .name = "mpls", .ops = &mpls_encap_ops },
16 [LWTUNNEL_ENCAP_IP] = { .name = "ip", .ops = &ip_encap_ops },
17 [LWTUNNEL_ENCAP_IP6] = { .name = "ip6", .ops = &ip6_encap_ops },
18 [LWTUNNEL_ENCAP_ILA] = { .name = "ila", .ops = &ila_encap_ops },
19 [LWTUNNEL_ENCAP_BPF] = { .name = "bpf" },
20};
21
22static const char *nh_encap_type2str(unsigned int type)
23{
24 const char *name;
25
26 if (type > LWTUNNEL_ENCAP_MAX)
27 return "unknown";
28
29 name = lwtunnel_encap_types[type].name;
30
31 return name ? name : "unknown";
32}
33
34void nh_encap_dump(struct rtnl_nh_encap *rtnh_encap, struct nl_dump_params *dp)
35{
36 if (!rtnh_encap->ops)
37 return;
38
39 nl_dump(dp, " encap %s ",
40 nh_encap_type2str(rtnh_encap->ops->encap_type));
41
42 if (rtnh_encap->ops->dump)
43 rtnh_encap->ops->dump(rtnh_encap->priv, dp);
44}
45
46int nh_encap_build_msg(struct nl_msg *msg, struct rtnl_nh_encap *rtnh_encap)
47{
48 struct nlattr *encap;
49 int err;
50
51 if (!rtnh_encap->ops || !rtnh_encap->ops->build_msg) {
52 NL_DBG(2, "Nexthop encap type not implemented\n");
53 return -NLE_INVAL;
54 }
55
56 NLA_PUT_U16(msg, RTA_ENCAP_TYPE, rtnh_encap->ops->encap_type);
57
58 encap = nla_nest_start(msg, RTA_ENCAP);
59 if (!encap)
60 goto nla_put_failure;
61
62 err = rtnh_encap->ops->build_msg(msg, rtnh_encap->priv);
63 if (err < 0)
64 return err;
65
66 nla_nest_end(msg, encap);
67
68 return 0;
69
70nla_put_failure:
71 return -NLE_MSGSIZE;
72}
73
74int nh_encap_parse_msg(struct nlattr *encap, struct nlattr *encap_type,
75 struct rtnl_nh_encap **encap_out)
76{
77 uint16_t e_type = nla_get_u16(encap_type);
78
79 if (e_type == LWTUNNEL_ENCAP_NONE) {
80 NL_DBG(2, "RTA_ENCAP_TYPE should not be LWTUNNEL_ENCAP_NONE\n");
81
82 goto unsupported_encap;
83 }
84
85 if (e_type > LWTUNNEL_ENCAP_MAX) {
86 NL_DBG(2, "Unknown RTA_ENCAP_TYPE: %d\n", e_type);
87
88 goto unsupported_encap;
89 }
90
91 if (!lwtunnel_encap_types[e_type].ops) {
92 NL_DBG(2, "RTA_ENCAP_TYPE %s is not implemented\n",
93 lwtunnel_encap_types[e_type].name);
94
95 goto unsupported_encap;
96 }
97
98 return lwtunnel_encap_types[e_type].ops->parse_msg(encap, encap_out);
99
100unsupported_encap:
101 /* If we don't yet support this lwtunnel, just return 0.
102 *
103 * Force encap_out to NULL so that subsequent calls to set
104 * it on a nexthop/route will simply reset the encapsulation
105 * on that nexthop/route.
106 */
107 *encap_out = NULL;
108 return 0;
109}
110
111int nh_encap_compare(struct rtnl_nh_encap *a, struct rtnl_nh_encap *b)
112{
113 if (!a && !b)
114 return 0;
115
116 if ((a && !b) || (!a && b) || (a->ops != b->ops))
117 return 1;
118
119 if (!a->ops || !a->ops->compare)
120 return 0;
121
122 return a->ops->compare(a->priv, b->priv);
123}
124
125void *nh_encap_check_and_get_priv(struct rtnl_nh_encap *nh_encap,
126 uint16_t encap_type)
127{
128 if (!nh_encap || !nh_encap->ops ||
129 nh_encap->ops->encap_type != encap_type) {
130 return NULL;
131 }
132
133 return nh_encap->priv;
134}
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition attr.c:664
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition attr.h:219
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition attr.c:974
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition attr.c:1037
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