libnl  3.5.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 
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 
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 
32 void nh_encap_dump(struct rtnl_nh_encap *rtnh_encap, struct nl_dump_params *dp)
33 {
34  nl_dump(dp, " encap %s ",
35  nh_encap_type2str(rtnh_encap->ops->encap_type));
36 
37  if (rtnh_encap->ops && rtnh_encap->ops->dump)
38  rtnh_encap->ops->dump(rtnh_encap->priv, dp);
39 }
40 
41 int nh_encap_build_msg(struct nl_msg *msg, struct rtnl_nh_encap *rtnh_encap)
42 {
43  struct nlattr *encap;
44  int err;
45 
46  if (!rtnh_encap->ops || !rtnh_encap->ops->build_msg) {
47  NL_DBG(2, "Nexthop encap type not implemented\n");
48  return -NLE_INVAL;
49  }
50 
51  NLA_PUT_U16(msg, RTA_ENCAP_TYPE, rtnh_encap->ops->encap_type);
52 
53  encap = nla_nest_start(msg, RTA_ENCAP);
54  if (!encap)
55  goto nla_put_failure;
56 
57  err = rtnh_encap->ops->build_msg(msg, rtnh_encap->priv);
58  if (err)
59  return err;
60 
61  nla_nest_end(msg, encap);
62 
63  return 0;
64 
65 nla_put_failure:
66  return -NLE_MSGSIZE;
67 }
68 
69 int nh_encap_parse_msg(struct nlattr *encap, struct nlattr *encap_type,
70  struct rtnl_nexthop *rtnh)
71 {
72  uint16_t e_type = nla_get_u16(encap_type);
73 
74  if (e_type == LWTUNNEL_ENCAP_NONE) {
75  NL_DBG(2, "RTA_ENCAP_TYPE should not be LWTUNNEL_ENCAP_NONE\n");
76  return -NLE_INVAL;
77  }
78  if (e_type > LWTUNNEL_ENCAP_MAX) {
79  NL_DBG(2, "Unknown RTA_ENCAP_TYPE: %d\n", e_type);
80  return -NLE_INVAL;
81  }
82 
83  if (!lwtunnel_encap_types[e_type].ops) {
84  NL_DBG(2, "RTA_ENCAP_TYPE %s is not implemented\n",
85  lwtunnel_encap_types[e_type].name);
86  return -NLE_MSGTYPE_NOSUPPORT;
87  }
88 
89  return lwtunnel_encap_types[e_type].ops->parse_msg(encap, rtnh);
90 }
91 
92 int nh_encap_compare(struct rtnl_nh_encap *a, struct rtnl_nh_encap *b)
93 {
94  if (!a && !b)
95  return 0;
96 
97  if ((a && !b) || (!a && b) || (a->ops != b->ops))
98  return 1;
99 
100  if (!a->ops || !a->ops->compare)
101  return 0;
102 
103  return a->ops->compare(a->priv, b->priv);
104 }
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:966
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:657
Dumping parameters.
Definition: types.h:33
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:218
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:962
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:903