diff options
author | Sandeep Malik <Sandeep.Malik@freescale.com> | 2012-03-16 18:41:21 (GMT) |
---|---|---|
committer | Emil Medve <Emilian.Medve@Freescale.com> | 2013-03-21 18:42:12 (GMT) |
commit | d6f980c22a79c7db1c5a2f918fa9d3a28d105adf (patch) | |
tree | df6a2f743cb12523570ebff7db43e96232858405 /net | |
parent | 9126496b944c60065992c6d7b9677ce2a3582dd8 (diff) | |
download | linux-fsl-qoriq-d6f980c22a79c7db1c5a2f918fa9d3a28d105adf.tar.xz |
xfrm: Add hooks for ASF IPsecdd hooks for ASF IPsec
cherry picked and merged from commit 9586eb2dd0a560c9b5729aba64e0f08199632ba5
Diffstat (limited to 'net')
-rw-r--r-- | net/xfrm/xfrm_input.c | 12 | ||||
-rw-r--r-- | net/xfrm/xfrm_output.c | 8 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 38 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 63 |
4 files changed, 121 insertions, 0 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index ab2bb42..dafbb09 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -173,6 +173,18 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) goto drop_unlock; } +#ifdef CONFIG_AS_FASTPATH + if (!x->asf_sa_cookie && asf_cb_fns.ipsec_dec_hook) + asf_cb_fns.ipsec_dec_hook(NULL, x, NULL, skb->skb_iif); + + spin_unlock(&x->lock); + if (x->asf_sa_cookie && asf_cb_fns.ipsec_decrypt_n_send) { + if (!asf_cb_fns.ipsec_decrypt_n_send(skb, x)) + return 0; + } + spin_lock(&x->lock); +#endif + if (x->repl->check(x, skb, seq)) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); goto drop_unlock; diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 95a338c..3476a27 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -54,6 +54,14 @@ static int xfrm_output_one(struct sk_buff *skb, int err) goto error_nolock; } +#ifdef CONFIG_AS_FASTPATH + if (x->asf_sa_cookie && asf_cb_fns.ipsec_encrypt_n_send) { + err = -EINPROGRESS; + if (!asf_cb_fns.ipsec_encrypt_n_send(skb, x)) + goto out_exit; + } +#endif + err = x->outer_mode->output(x, skb); if (err) { XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 07c5857..970b63d 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -56,6 +56,33 @@ static int xfrm_bundle_ok(struct xfrm_dst *xdst); static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, int dir); +#ifdef CONFIG_AS_FASTPATH +struct asf_ipsec_callbackfn_s asf_cb_fns = {0}; + +void register_ipsec_offload_hook(struct asf_ipsec_callbackfn_s *p_fn_list) +{ + asf_cb_fns.ipsec_enc_hook = p_fn_list->ipsec_enc_hook; + asf_cb_fns.ipsec_dec_hook = p_fn_list->ipsec_dec_hook; + asf_cb_fns.ipsec_sync_sa = p_fn_list->ipsec_sync_sa; + asf_cb_fns.ipsec_encrypt_n_send + = p_fn_list->ipsec_encrypt_n_send; + asf_cb_fns.ipsec_decrypt_n_send + = p_fn_list->ipsec_decrypt_n_send; + +} +EXPORT_SYMBOL(register_ipsec_offload_hook); + +void unregister_ipsec_offload_hook(void) +{ + asf_cb_fns.ipsec_enc_hook = NULL; + asf_cb_fns.ipsec_dec_hook = NULL; + asf_cb_fns.ipsec_sync_sa = NULL; + asf_cb_fns.ipsec_encrypt_n_send = NULL; + asf_cb_fns.ipsec_decrypt_n_send = NULL; +} +EXPORT_SYMBOL(unregister_ipsec_offload_hook); +#endif /* CONFIG_AS_FASTPATH */ + static inline bool __xfrm4_selector_match(const struct xfrm_selector *sel, const struct flowi *fl) { @@ -606,6 +633,11 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) if (delpol) __xfrm_policy_unlink(delpol, dir); policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir); + +#ifdef CONFIG_AS_FASTPATH + policy->asf_cookie = delpol ? delpol->asf_cookie : 0; +#endif + hlist_add_head(&policy->byidx, net->xfrm.policy_byidx+idx_hash(net, policy->index)); policy->curlft.add_time = get_seconds(); policy->curlft.use_time = 0; @@ -981,6 +1013,7 @@ __xfrm_policy_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir #endif return xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, fl, family, dir); } +EXPORT_SYMBOL(__xfrm_policy_lookup); static struct flow_cache_object * xfrm_policy_lookup(struct net *net, const struct flowi *fl, u16 family, @@ -1147,6 +1180,11 @@ static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir) newp->xfrm_nr = old->xfrm_nr; newp->index = old->index; newp->type = old->type; + +#ifdef CONFIG_AS_FASTPATH + newp->asf_cookie = old->asf_cookie; +#endif + memcpy(newp->xfrm_vec, old->xfrm_vec, newp->xfrm_nr*sizeof(struct xfrm_tmpl)); write_lock_bh(&xfrm_policy_lock); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 3459692..8cec4f9 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1647,6 +1647,69 @@ static void xfrm_replay_timer_handler(unsigned long data) spin_unlock(&x->lock); } +#ifdef CONFIG_AS_FASTPATH +struct xfrm_policy *xfrm_state_policy_mapping(struct xfrm_state *xfrm) +{ + struct xfrm_policy *xp = 0, *matched_pol = 0; + struct net *xfrm_net = xs_net(xfrm); + struct list_head *list_policy_head = &xfrm_net->xfrm.policy_all; + struct xfrm_policy_walk_entry *x; + struct xfrm_tmpl *tmpl; + unsigned int dir; + + if (!list_policy_head) { + printk(KERN_INFO "No Security Policies in the system\n"); + return matched_pol; + } + x = list_first_entry(list_policy_head, + struct xfrm_policy_walk_entry, all); + if (!x) { + printk(KERN_INFO "Security Policies list is empty\n"); + return matched_pol; + } + if (xfrm->props.family == AF_INET) { + list_for_each_entry_from(x, list_policy_head, all) { + if (x->dead) + continue; + xp = container_of(x, struct xfrm_policy, walk); + tmpl = &xp->xfrm_vec[0]; + dir = xfrm_policy_id2dir(xp->index); + if (dir <= XFRM_POLICY_OUT && + tmpl->id.daddr.a4 == xfrm->id.daddr.a4 && + tmpl->saddr.a4 == xfrm->props.saddr.a4 && + xfrm->props.reqid == tmpl->reqid && + xfrm->props.mode == tmpl->mode) { + matched_pol = xp; + xfrm->asf_sa_direction = dir; + break; + } + } + } else if (xfrm->props.family == AF_INET6) { + list_for_each_entry_from(x, list_policy_head, all) { + if (x->dead) + continue; + xp = container_of(x, struct xfrm_policy, walk); + tmpl = &xp->xfrm_vec[0]; + dir = xfrm_policy_id2dir(xp->index); + if (dir <= XFRM_POLICY_OUT && + !memcmp(tmpl->id.daddr.a6, + xfrm->id.daddr.a6, 16) && + !memcmp(tmpl->saddr.a6, + xfrm->props.saddr.a6, 16) && + xfrm->props.reqid == tmpl->reqid && + xfrm->props.mode == tmpl->mode) { + matched_pol = xp; + xfrm->asf_sa_direction = dir; + break; + } + } + } else + return NULL; + + return matched_pol; +} +EXPORT_SYMBOL(xfrm_state_policy_mapping); +#endif static LIST_HEAD(xfrm_km_list); static DEFINE_RWLOCK(xfrm_km_lock); |