diff options
author | Thomas Egerer <thomas.egerer@secunet.com> | 2021-09-09 16:06:32 (GMT) |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-03-03 11:56:41 (GMT) |
commit | c8f33a4851de0b6e67f72308465c3542d88e455f (patch) | |
tree | d8053bb0548d82263693eddf2a7c5ef7d5744fce /lib | |
parent | b6cc13d76b2927640dc0e41b98fff0f211c643d4 (diff) | |
download | libnl-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.c | 86 |
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) |