Skip to content

Commit

Permalink
[IPSEC]: Add async resume support on output
Browse files Browse the repository at this point in the history
This patch adds support for async resumptions on output.  To do so,
the transform would return -EINPROGRESS and subsequently invoke the
function xfrm_output_resume to resume processing.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Herbert Xu authored and David S. Miller committed Jan 28, 2008
1 parent 862b82c commit c6581a4
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 17 deletions.
1 change: 1 addition & 0 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,7 @@ extern void xfrm_replay_notify(struct xfrm_state *x, int event);
extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
extern int xfrm_init_state(struct xfrm_state *x);
extern int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm_output_resume(struct sk_buff *skb, int err);
extern int xfrm_output(struct sk_buff *skb);
extern int xfrm4_extract_header(struct sk_buff *skb);
extern int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb);
Expand Down
57 changes: 40 additions & 17 deletions net/xfrm/xfrm_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <net/dst.h>
#include <net/xfrm.h>

static int xfrm_output2(struct sk_buff *skb);

static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
Expand All @@ -41,17 +43,13 @@ static int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb)
return err;
}

static int xfrm_output_one(struct sk_buff *skb)
static int xfrm_output_one(struct sk_buff *skb, int err)
{
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
int err;

if (skb->ip_summed == CHECKSUM_PARTIAL) {
err = skb_checksum_help(skb);
if (err)
goto error_nolock;
}
if (err <= 0)
goto resume;

do {
err = x->outer_mode->output(x, skb);
Expand All @@ -75,6 +73,8 @@ static int xfrm_output_one(struct sk_buff *skb)
spin_unlock_bh(&x->lock);

err = x->type->output(x, skb);

resume:
if (err)
goto error_nolock;

Expand All @@ -97,18 +97,16 @@ static int xfrm_output_one(struct sk_buff *skb)
goto out_exit;
}

static int xfrm_output2(struct sk_buff *skb)
int xfrm_output_resume(struct sk_buff *skb, int err)
{
int err;

while (likely((err = xfrm_output_one(skb)) == 0)) {
while (likely((err = xfrm_output_one(skb, err)) == 0)) {
struct xfrm_state *x;

nf_reset(skb);

err = skb->dst->ops->local_out(skb);
if (unlikely(err != 1))
break;
goto out;

x = skb->dst->xfrm;
if (!x)
Expand All @@ -118,18 +116,25 @@ static int xfrm_output2(struct sk_buff *skb)
x->inner_mode->afinfo->nf_post_routing, skb,
NULL, skb->dst->dev, xfrm_output2);
if (unlikely(err != 1))
break;
goto out;
}

if (err == -EINPROGRESS)
err = 0;

out:
return err;
}
EXPORT_SYMBOL_GPL(xfrm_output_resume);

int xfrm_output(struct sk_buff *skb)
static int xfrm_output2(struct sk_buff *skb)
{
struct sk_buff *segs;
return xfrm_output_resume(skb, 1);
}

if (!skb_is_gso(skb))
return xfrm_output2(skb);
static int xfrm_output_gso(struct sk_buff *skb)
{
struct sk_buff *segs;

segs = skb_gso_segment(skb, 0);
kfree_skb(skb);
Expand Down Expand Up @@ -157,4 +162,22 @@ int xfrm_output(struct sk_buff *skb)

return 0;
}

int xfrm_output(struct sk_buff *skb)
{
int err;

if (skb_is_gso(skb))
return xfrm_output_gso(skb);

if (skb->ip_summed == CHECKSUM_PARTIAL) {
err = skb_checksum_help(skb);
if (err) {
kfree_skb(skb);
return err;
}
}

return xfrm_output2(skb);
}
EXPORT_SYMBOL_GPL(xfrm_output);

0 comments on commit c6581a4

Please sign in to comment.