• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 static 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 
nh_encap_type2str(unsigned int type)20 static 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 
nh_encap_dump(struct rtnl_nh_encap * rtnh_encap,struct nl_dump_params * dp)32 void 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 
nh_encap_build_msg(struct nl_msg * msg,struct rtnl_nh_encap * rtnh_encap)44 int 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 
68 nla_put_failure:
69 	return -NLE_MSGSIZE;
70 }
71 
nh_encap_parse_msg(struct nlattr * encap,struct nlattr * encap_type,struct rtnl_nexthop * rtnh)72 int 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 
nh_encap_compare(struct rtnl_nh_encap * a,struct rtnl_nh_encap * b)95 int 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 }
108