summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorThomas Egerer <thomas.egerer@secunet.com>2021-09-09 16:06:32 (GMT)
committerThomas Haller <thaller@redhat.com>2022-03-03 11:56:41 (GMT)
commitc8f33a4851de0b6e67f72308465c3542d88e455f (patch)
treed8053bb0548d82263693eddf2a7c5ef7d5744fce /lib
parentb6cc13d76b2927640dc0e41b98fff0f211c643d4 (diff)
downloadlibnl-c8f33a4851de0b6e67f72308465c3542d88e455f.zip
libnl-c8f33a4851de0b6e67f72308465c3542d88e455f.tar.gz
libnl-c8f33a4851de0b6e67f72308465c3542d88e455f.tar.bz2
xfrm: Add support for xfrm user offloading
Signed-off-by: Thomas Egerer <thomas.egerer@secunet.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/xfrm/sa.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/lib/xfrm/sa.c b/lib/xfrm/sa.c
index 41b9a68..4427e59 100644
--- a/lib/xfrm/sa.c
+++ b/lib/xfrm/sa.c
@@ -78,6 +78,7 @@
#define XFRM_SA_ATTR_REPLAY_MAXDIFF 0x1000000
#define XFRM_SA_ATTR_REPLAY_STATE 0x2000000
#define XFRM_SA_ATTR_EXPIRE 0x4000000
+#define XFRM_SA_ATTR_OFFLOAD_DEV 0x8000000
static struct nl_cache_ops xfrmnl_sa_ops;
static struct nl_object_ops xfrm_sa_obj_ops;
@@ -125,6 +126,8 @@ static void xfrm_sa_free_data(struct nl_object *c)
free (sa->sec_ctx);
if (sa->replay_state_esn)
free (sa->replay_state_esn);
+ if (sa->user_offload)
+ free(sa->user_offload);
}
static int xfrm_sa_clone(struct nl_object *_dst, struct nl_object *_src)
@@ -333,6 +336,7 @@ static const struct trans_tbl sa_attrs[] = {
__ADD(XFRM_SA_ATTR_REPLAY_MAXDIFF, replay_maxdiff),
__ADD(XFRM_SA_ATTR_REPLAY_STATE, replay_state),
__ADD(XFRM_SA_ATTR_EXPIRE, expire),
+ __ADD(XFRM_SA_ATTR_OFFLOAD_DEV, user_offload),
};
static char* xfrm_sa_attrs2str(int attrs, char *buf, size_t len)
@@ -909,6 +913,22 @@ int xfrmnl_sa_parse(struct nlmsghdr *n, struct xfrmnl_sa **result)
sa->replay_state_esn = NULL;
}
+ if (tb[XFRMA_OFFLOAD_DEV]) {
+ struct xfrm_user_offload *offload;
+
+ len = sizeof(struct xfrmnl_user_offload);
+
+ if ((sa->user_offload = calloc(1, len)) == NULL) {
+ err = -NLE_NOMEM;
+ goto errout;
+ }
+
+ offload = nla_data(tb[XFRMA_OFFLOAD_DEV]);
+ sa->user_offload->ifindex = offload->ifindex;
+ sa->user_offload->flags = offload->flags;
+ sa->ce_mask |= XFRM_SA_ATTR_OFFLOAD_DEV;
+ }
+
*result = sa;
return 0;
@@ -1259,6 +1279,21 @@ static int build_xfrm_sa_message(struct xfrmnl_sa *tmpl, int cmd, int flags, str
}
}
+ if (tmpl->ce_mask & XFRM_SA_ATTR_OFFLOAD_DEV) {
+ struct xfrm_user_offload *offload;
+ struct nlattr *attr;
+
+ len = sizeof(struct xfrm_user_offload);
+ attr = nla_reserve(msg, XFRMA_OFFLOAD_DEV, len);
+
+ if (!attr)
+ goto nla_put_failure;
+
+ offload = nla_data(attr);
+ offload->ifindex = tmpl->user_offload->ifindex;
+ offload->flags = tmpl->user_offload->flags;
+ }
+
*result = msg;
return 0;
@@ -2152,6 +2187,57 @@ int xfrmnl_sa_set_replay_state_esn (struct xfrmnl_sa* sa, unsigned int oseq, uns
}
+/**
+ * Get interface id and flags from xfrm_user_offload.
+ *
+ * @arg sa The xfrmnl_sa object.
+ * @arg ifindex An optional output value for the offload interface index.
+ * @arg flags An optional output value for the offload flags.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int xfrmnl_sa_get_user_offload(struct xfrmnl_sa *sa, int *ifindex, uint8_t *flags)
+{
+ int ret = -1;
+
+ if (sa->ce_mask & XFRM_SA_ATTR_OFFLOAD_DEV && sa->user_offload) {
+ if (ifindex)
+ *ifindex = sa->user_offload->ifindex;
+ if (flags)
+ *flags = sa->user_offload->flags;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+
+/**
+ * Set interface id and flags for xfrm_user_offload.
+ *
+ * @arg sa The xfrmnl_sa object.
+ * @arg ifindex Id of the offload interface.
+ * @arg flags Offload flags for the state.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int xfrmnl_sa_set_user_offload(struct xfrmnl_sa *sa, int ifindex, uint8_t flags)
+{
+ _nl_auto_free struct xfrmnl_user_offload *b = NULL;
+
+ if (!(b = calloc(1, sizeof(*b))))
+ return -1;
+
+ b->ifindex = ifindex;
+ b->flags = flags;
+
+ free(sa->user_offload);
+ sa->user_offload = _nl_steal_pointer(&b);
+ sa->ce_mask |= XFRM_SA_ATTR_OFFLOAD_DEV;
+
+ return 0;
+}
+
int xfrmnl_sa_is_hardexpiry_reached (struct xfrmnl_sa* sa)
{
if (sa->ce_mask & XFRM_SA_ATTR_EXPIRE)