libnl 3.7.0
nexthop_encap.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 <linux/lwtunnel.h>
7
8static struct lwtunnel_encap_type {
9 const char *name;
10 struct nh_encap_ops *ops;
11} lwtunnel_encap_types[__LWTUNNEL_ENCAP_MAX] = {
12 [LWTUNNEL_ENCAP_NONE] = { .name = "none" },
13 [LWTUNNEL_ENCAP_MPLS] = { .name = "mpls", .ops = &mpls_encap_ops },
14 [LWTUNNEL_ENCAP_IP] = { .name = "ip" },
15 [LWTUNNEL_ENCAP_IP6] = { .name = "ip6" },
16 [LWTUNNEL_ENCAP_ILA] = { .name = "ila" },
17 [LWTUNNEL_ENCAP_BPF] = { .name = "bpf" },
18};
19
20static const char *nh_encap_type2str(unsigned int type)
21{
22 const char *name;
23
24 if (type > LWTUNNEL_ENCAP_MAX)
25 return "unknown";
26
27 name = lwtunnel_encap_types[type].name;
28
29 return name ? name : "unknown";
30}
31
32void nh_encap_dump(struct rtnl_nh_encap *rtnh_encap, struct nl_dump_params *dp)
33{
34 if (!rtnh_encap->ops)
35 return;
36
37 nl_dump(dp, " encap %s ",
38 nh_encap_type2str(rtnh_encap->ops->encap_type));
39
40 if (rtnh_encap->ops->dump)
41 rtnh_encap->ops->dump(rtnh_encap->priv, dp);
42}
43
44int nh_encap_build_msg(struct nl_msg *msg, struct rtnl_nh_encap *rtnh_encap)
45{
46 struct nlattr *encap;
47 int err;
48
49 if (!rtnh_encap->ops || !rtnh_encap->ops->build_msg) {
50 NL_DBG(2, "Nexthop encap type not implemented\n");
51 return -NLE_INVAL;
52 }
53
54 NLA_PUT_U16(msg, RTA_ENCAP_TYPE, rtnh_encap->ops->encap_type);
55
56 encap = nla_nest_start(msg, RTA_ENCAP);
57 if (!encap)
58 goto nla_put_failure;
59
60 err = rtnh_encap->ops->build_msg(msg, rtnh_encap->priv);
61 if (err < 0)
62 return err;
63
64 nla_nest_end(msg, encap);
65
66 return 0;
67
68nla_put_failure:
69 return -NLE_MSGSIZE;
70}
71
72int nh_encap_parse_msg(struct nlattr *encap, struct nlattr *encap_type,
73 struct rtnl_nexthop *rtnh)
74{
75 uint16_t e_type = nla_get_u16(encap_type);
76
77 if (e_type == LWTUNNEL_ENCAP_NONE) {
78 NL_DBG(2, "RTA_ENCAP_TYPE should not be LWTUNNEL_ENCAP_NONE\n");
79 return -NLE_INVAL;
80 }
81 if (e_type > LWTUNNEL_ENCAP_MAX) {
82 NL_DBG(2, "Unknown RTA_ENCAP_TYPE: %d\n", e_type);
83 return -NLE_INVAL;
84 }
85
86 if (!lwtunnel_encap_types[e_type].ops) {
87 NL_DBG(2, "RTA_ENCAP_TYPE %s is not implemented\n",
88 lwtunnel_encap_types[e_type].name);
89 return -NLE_MSGTYPE_NOSUPPORT;
90 }
91
92 return lwtunnel_encap_types[e_type].ops->parse_msg(encap, rtnh);
93}
94
95int nh_encap_compare(struct rtnl_nh_encap *a, struct rtnl_nh_encap *b)
96{
97 if (!a && !b)
98 return 0;
99
100 if ((a && !b) || (!a && b) || (a->ops != b->ops))
101 return 1;
102
103 if (!a->ops || !a->ops->compare)
104 return 0;
105
106 return a->ops->compare(a->priv, b->priv);
107}
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:652
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:212
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:898
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:961
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