summaryrefslogtreecommitdiff
path: root/net/xfrm
diff options
context:
space:
mode:
authorSandeep Malik <Sandeep.Malik@freescale.com>2012-03-16 18:41:21 (GMT)
committerEmil Medve <Emilian.Medve@Freescale.com>2013-03-21 18:42:12 (GMT)
commitd6f980c22a79c7db1c5a2f918fa9d3a28d105adf (patch)
treedf6a2f743cb12523570ebff7db43e96232858405 /net/xfrm
parent9126496b944c60065992c6d7b9677ce2a3582dd8 (diff)
downloadlinux-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/xfrm')
-rw-r--r--net/xfrm/xfrm_input.c12
-rw-r--r--net/xfrm/xfrm_output.c8
-rw-r--r--net/xfrm/xfrm_policy.c38
-rw-r--r--net/xfrm/xfrm_state.c63
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);