summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Winter <Thomas.Winter@alliedtelesis.co.nz>2018-06-11 20:51:44 (GMT)
committerThomas Haller <thaller@redhat.com>2022-03-11 23:06:32 (GMT)
commitbda19be660662b34d281218872f9038be4a2c125 (patch)
tree3323e7a435e8327cae5b524f54e2cfc32a73f825
parentcdc6c0f321527e3aad06d11e16115daa82b54677 (diff)
downloadlibnl-bda19be660662b34d281218872f9038be4a2c125.zip
libnl-bda19be660662b34d281218872f9038be4a2c125.tar.gz
libnl-bda19be660662b34d281218872f9038be4a2c125.tar.bz2
ip6_tnl: Add fwmark API
This is a new option that was added in Linux v4.12. Signed-off-by: Thomas Winter <Thomas.Winter@alliedtelesis.co.nz>
-rw-r--r--doc/route.txt3
-rw-r--r--include/netlink/route/link/ip6tnl.h3
-rw-r--r--lib/route/link/ip6tnl.c56
-rw-r--r--libnl-route-3.sym2
4 files changed, 64 insertions, 0 deletions
diff --git a/doc/route.txt b/doc/route.txt
index d51a394..60a8cd8 100644
--- a/doc/route.txt
+++ b/doc/route.txt
@@ -1238,6 +1238,9 @@ extern int rtnl_link_ip6_tnl_set_flowinfo(struct rtnl_link *link, uint32_t flowi
extern int rtnl_link_ip6_tnl_set_proto(struct rtnl_link *link, uint8_t proto);
extern uint8_t rtnl_link_ip6_tnl_get_proto(struct rtnl_link *link);
+extern int rtnl_link_ip6_tnl_set_fwmark(struct rtnl_link *link, uint32_t fwmark);
+extern int rtnl_link_ip6_tnl_get_fwmark(struct rtnl_link *link, uint32_t *fwmark);
+
-----
.Example: Add a ip6tnl tunnel device
diff --git a/include/netlink/route/link/ip6tnl.h b/include/netlink/route/link/ip6tnl.h
index 88866e6..865d973 100644
--- a/include/netlink/route/link/ip6tnl.h
+++ b/include/netlink/route/link/ip6tnl.h
@@ -45,6 +45,9 @@ extern "C" {
extern int rtnl_link_ip6_tnl_set_proto(struct rtnl_link *link, uint8_t proto);
extern uint8_t rtnl_link_ip6_tnl_get_proto(struct rtnl_link *link);
+ extern int rtnl_link_ip6_tnl_set_fwmark(struct rtnl_link *link, uint32_t fwmark);
+ extern int rtnl_link_ip6_tnl_get_fwmark(struct rtnl_link *link, uint32_t *fwmark);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/route/link/ip6tnl.c b/lib/route/link/ip6tnl.c
index 640d846..c641c3f 100644
--- a/lib/route/link/ip6tnl.c
+++ b/lib/route/link/ip6tnl.c
@@ -36,6 +36,7 @@
#define IP6_TNL_ATTR_FLAGS (1 << 6)
#define IP6_TNL_ATTR_PROTO (1 << 7)
#define IP6_TNL_ATTR_FLOWINFO (1 << 8)
+#define IP6_TNL_ATTR_FWMARK (1 << 9)
struct ip6_tnl_info
{
@@ -48,6 +49,7 @@ struct ip6_tnl_info
uint32_t flowinfo;
struct in6_addr local;
struct in6_addr remote;
+ uint32_t fwmark;
uint32_t ip6_tnl_mask;
};
@@ -61,6 +63,7 @@ static struct nla_policy ip6_tnl_policy[IFLA_IPTUN_MAX + 1] = {
[IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32 },
[IFLA_IPTUN_FLAGS] = { .type = NLA_U32 },
[IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
+ [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 },
};
static int ip6_tnl_alloc(struct rtnl_link *link)
@@ -144,6 +147,11 @@ static int ip6_tnl_parse(struct rtnl_link *link, struct nlattr *data,
ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_PROTO;
}
+ if (tb[IFLA_IPTUN_FWMARK]) {
+ ip6_tnl->fwmark = nla_get_u32(tb[IFLA_IPTUN_FWMARK]);
+ ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FWMARK;
+ }
+
err = 0;
errout:
@@ -189,6 +197,9 @@ static int ip6_tnl_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
else
NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, 0);
+ if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FWMARK)
+ NLA_PUT_U32(msg, IFLA_IPTUN_FWMARK, ip6_tnl->fwmark);
+
nla_nest_end(msg, data);
nla_put_failure:
@@ -275,6 +286,11 @@ static void ip6_tnl_dump_details(struct rtnl_link *link, struct nl_dump_params *
nl_dump(p, " proto ");
nl_dump_line(p, " (%x)\n", ip6_tnl->proto);
}
+
+ if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FWMARK) {
+ nl_dump(p, " fwmark ");
+ nl_dump_line(p, "%x\n", ip6_tnl->fwmark);
+ }
}
static int ip6_tnl_clone(struct rtnl_link *dst, struct rtnl_link *src)
@@ -682,6 +698,46 @@ uint8_t rtnl_link_ip6_tnl_get_proto(struct rtnl_link *link)
return ip6_tnl->proto;
}
+/**
+ * Set IP6_TNL tunnel fwmark
+ * @arg link Link object
+ * @arg fwmark fwmark
+ *
+ * @return 0 on success or a negative error code
+ */
+int rtnl_link_ip6_tnl_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
+{
+ struct ip6_tnl_info *ip6_tnl = link->l_info;
+
+ IS_IP6_TNL_LINK_ASSERT(link);
+
+ ip6_tnl->fwmark = fwmark;
+ ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FWMARK;
+
+ return 0;
+}
+
+/**
+ * Get IP6_TNL tunnel fwmark
+ * @arg link Link object
+ * @arg fwmark addr to fill in with the fwmark
+ *
+ * @return 0 on success or a negative error code
+ */
+int rtnl_link_ip6_tnl_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
+{
+ struct ip6_tnl_info *ip6_tnl = link->l_info;
+
+ IS_IP6_TNL_LINK_ASSERT(link);
+
+ if (!(ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FWMARK))
+ return -NLE_NOATTR;
+
+ *fwmark = ip6_tnl->fwmark;
+
+ return 0;
+}
+
static void __init ip6_tnl_init(void)
{
rtnl_link_register_info(&ip6_tnl_info_ops);
diff --git a/libnl-route-3.sym b/libnl-route-3.sym
index 7d585b6..7c1682d 100644
--- a/libnl-route-3.sym
+++ b/libnl-route-3.sym
@@ -1153,6 +1153,8 @@ global:
libnl_3_6 {
global:
+ rtnl_link_ip6_tnl_get_fwmark;
+ rtnl_link_ip6_tnl_set_fwmark;
rtnl_link_ip6gre_add;
rtnl_link_ip6gre_alloc;
rtnl_link_ip6gre_get_encaplimit;