Netdev List
 help / color / mirror / Atom feed
* Re: [PATCHv2 2.6.24] fib: fix route replacement, fib_info is shared
From: Jarek Poplawski @ 2008-01-29  8:49 UTC (permalink / raw)
  To: Julian Anastasov; +Cc: David S. Miller, netdev, Joonwoo Park
In-Reply-To: <Pine.LNX.4.58.0801290139450.3181@u.domain.uli>

On Tue, Jan 29, 2008 at 02:30:47AM +0200, Julian Anastasov wrote:
> 
> 	Hello,
> 
> On Mon, 28 Jan 2008, Jarek Poplawski wrote:
> 
> > BTW, the way "add" works wasn't questioned now, but it seems could be,
> > or man ip should call it e.g. "ip route add - add new destination",
> > and append "ip route append" (unless I have old man).
> 
> 	"add" is similar to "prepend", only that checks NLM_F_EXCL
> to avoid many alternative routes, only one route for tos+priority is
> allowed for "add". As for the sorting by tos/priority and the
> insertion position I remember for thread on this issue:

Yes but I've meant this man (8) ip description could be confusing:

"  ip route add - add new route
   ip route change - change route
   ip route replace - change or add new one"

One can wonder why there is an error while adding two new routes with
"add", but OK to do the same with "replace". But, it's "man" problem
of course.

> 
> http://marc.info/?t=109614290600002&r=1&w=2
> 
> > > +		fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
> > > +		list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
> > > +			if (fa->fa_tos != tos)
> > > +				break;
> > > +			if (fa->fa_info->fib_priority != fi->fib_priority)
> > > +				break;
> > > +			if (fa->fa_type == cfg->fc_type &&
> > > +			    fa->fa_scope == cfg->fc_scope &&
> > > +			    fa->fa_info == fi) {
> > > +				fa_match = fa;
> > > +				break;
> > 
> > Why can't we try goto out from here? (less reading...)
> 
> 	The case with NLM_F_REPLACE needs to check more things, one
> day one can combine NLM_F_APPEND+NLM_F_REPLACE to replace last
> alternative route, not only the first one as currently implemented.

I'm not sure I can understand your point: do you mean there could be
something to do for these options is fa_match exists? But, maybe it
relates to my question below...

> 
> > > +			fa = fa_first;
> > > +			if (fa_match) {
> > > +				if (fa == fa_match)
> > > +					err = 0;
> > 
> > Could you comment more why returning an error seems to depend on the
> > order of aliases here? But, IMHO there is no reason to change the old
> > behavior WRT this error, so probably this err = 0 should be always if
> > NLM_F_REPLACE is set.
> 
> 	fa_match is some existing alias that matches all new parameters.
> As NLM_F_REPLACE changes the first alternative route for 
> tos+priority if fa_match == fa_first (we are replacing alias that
> matches all parameters) we return 0, only that routing cache is not 
> flushed - nothing is replaced/changed. So, "fa == fa_match" means
> "replace will not change existing parameters", return 0 as this is
> not an error.

Probably I miss something, but what parameters do we change if
(fa_match) && (fa != fa_match)? Isn't this "goto out" in any case?

> 
> > PS: I think, this FIB info you sent earlier is just fine for
> > Documentation/networking without any changes! (Maybe one more patch?)
> 
> 	This is so small part of the picture, such 15-minute listing
> is not enough to explain everything. May be such and other information
> can be added as part of some known documentation.

This is small but condensed, and IMHO it fits very well what is now
in this directory.

Thanks,
Jarek P.

^ permalink raw reply

* Re: ipcomp regression in 2.6.24
From: Marco Berizzi @ 2008-01-29  8:07 UTC (permalink / raw)
  To: Beschorner Daniel; +Cc: netdev
In-Reply-To: <3C59DB883F7B0B4D8096010D45ACCD134F2086@exch.facton.local>

Beschorner Daniel wrote:

> Has someone an idea which patch could have damaged ipcomp?
>
> Daniel
>
> > With 2.6.24 IPSEC/ESP tunnels to older kernels establish fine, data
> > flows in both directions, but no data comes out of the tunnel.
> > Needed to disable ipcomp.

Same problem here: linux 2.6.24 driven by openswan 2.4.11
on Slackware 11.0




^ permalink raw reply

* Re: [PATCH net-2.6.25 4/7][ATM]: [br2864] routed support
From: Chung-Chi Lo @ 2008-01-29  7:42 UTC (permalink / raw)
  To: chas3; +Cc: netdev, davem
In-Reply-To: <200801261220.m0QCKJ15023510@cmf.nrl.navy.mil>

On Jan 26, 2008 8:20 PM, chas williams - CONTRACTOR
<chas@cmf.nrl.navy.mil> wrote:
> In message <3f696b20801152016r52048016g7c293dbfdc6c9f29@mail.gmail.com>,"Chung-
> Chi Lo" writes:
> >By the way, this routed mode patch doesn't include encaps=VCMUX and
> >RFC2684 routed
> >protocol decapsulation?
>
> yep.  eric believes the following should fix both problems:
>
> commit 43e4b025ffe130cd6a292fa9ff909e39a88f849c
> Author: Chas Williams - CONTRACTOR <chas@relax.cmf.nrl.navy.mil>
> Date:   Sat Jan 26 07:18:26 2008 -0500
>
>     [ATM]: [br2864] fix vcmux support
>
>     From: Eric Kinzie <ekinzie@cmf.nrl.navy.mil>
>     Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
>
> diff --git a/net/atm/br2684.c b/net/atm/br2684.c
> index 31347cb..97b422c 100644
> --- a/net/atm/br2684.c
> +++ b/net/atm/br2684.c
> @@ -400,15 +400,20 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
>                         return;
>                 }
>
> -       } else {
> -               /* first 2 chars should be 0 */
> -               if (*((u16 *) (skb->data)) != 0) {
> -                       brdev->stats.rx_errors++;
> -                       dev_kfree_skb(skb);
> -                       return;
> +       } else { /* vc-mux */
> +               if (brdev->payload == p_routed) {

add line

			skb->protocol = __constant_htons(ETH_P_IP);

here just like LLC did?

> +                       skb_reset_network_header(skb);
> +                       skb->pkt_type = PACKET_HOST;
> +               } else { /* p_bridged */
> +                       /* first 2 chars should be 0 */
> +                       if (*((u16 *) (skb->data)) != 0) {
> +                               brdev->stats.rx_errors++;
> +                               dev_kfree_skb(skb);
> +                               return;
> +                       }
> +                       skb_pull(skb, BR2684_PAD_LEN);
> +                       skb->protocol = eth_type_trans(skb, net_dev);
>                 }
> -               skb_pull(skb, BR2684_PAD_LEN + ETH_HLEN);       /* pad, dstmac, srcmac, ethtype */
> -               skb->protocol = eth_type_trans(skb, net_dev);
>         }
>

Also have a problem when encapsulation is VCMUX and routed mode, in

 /*
@@ -136,6 +156,7 @@ static int br2684_xmit_vcc(struct sk_buff *skb,
struct br2684_dev *brdev,
 {
..
..
+       if (brvcc->encaps == e_llc) {
..
+       } else {
+               skb_push(skb, 2);
+               if (brdev->payload == p_bridged)
+                       memset(skb->data, 0, 2);
+       }

Here should be

	} else {
		if (brdev->payload == p_bridged) {
			skb_push(skb, 2);
			memset(skb->data, 0, 2);
		}
	}

Because VCMUX and routed mode doesn't need two bytes in header.

-- 
Lino, Chung-Chi Lo

^ permalink raw reply

* Feel more pleasure in love!
From: drandsu @ 2008-01-29  5:25 UTC (permalink / raw)
  To: netdev

Join the world of boundless enjoyments! http://uiwm.measureremember.com


^ permalink raw reply

* Re: [PATCHv2 2.6.24] fib_trie: apply fixes from fib_hash
From: David Miller @ 2008-01-29  5:18 UTC (permalink / raw)
  To: ja; +Cc: robert.olsson, netdev, joonwpark81
In-Reply-To: <Pine.LNX.4.58.0801261441470.7864@u.domain.uli>

From: Julian Anastasov <ja@ssi.bg>
Date: Sat, 26 Jan 2008 14:44:36 +0200 (EET)

> 
> 	Update fib_trie with some fib_hash fixes:
> - check for duplicate alternative routes for prefix+tos+priority when
> replacing route
> - properly insert by matching tos together with priority
> - fix alias walking to use list_for_each_entry_continue for insertion
> and deletion when fa_head is not NULL
> - copy state from fa to new_fa on replace (not a problem for now)
> - additionally, avoid replacement without error if new route is same,
> as Joonwoo Park suggests.
> 
> Signed-off-by: Julian Anastasov <ja@ssi.bg>

Also applied, thanks a lot.

^ permalink raw reply

* Re: [PATCHv2 2.6.24] fib: fix route replacement, fib_info is shared
From: David Miller @ 2008-01-29  5:14 UTC (permalink / raw)
  To: ja; +Cc: netdev, joonwpark81
In-Reply-To: <Pine.LNX.4.58.0801261439020.7864@u.domain.uli>

From: Julian Anastasov <ja@ssi.bg>
Date: Sat, 26 Jan 2008 14:41:32 +0200 (EET)

> 
> 	fib_info can be shared by many route prefixes but we don't
> want duplicate alternative routes for a prefix+tos+priority. Last
> change was not correct to check fib_treeref because it accounts usage
> from other prefixes. Additionally, avoid replacement without error
> if new route is same, as Joonwoo Park suggests.
> 
> Signed-off-by: Julian Anastasov <ja@ssi.bg>

Applied, thank you.

^ permalink raw reply

* Re: [PATCH][INET_DIAG]: Fix inet_diag_lock_handler error path
From: David Miller @ 2008-01-29  4:52 UTC (permalink / raw)
  To: herbert; +Cc: acme, spike, netdev, stable
In-Reply-To: <20080128110310.GA6305@gondor.apana.org.au>

From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Mon, 28 Jan 2008 22:03:10 +1100

> On Mon, Jan 28, 2008 at 12:20:50AM -0200, Arnaldo Carvalho de Melo wrote:
> > Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=9825
> > 
> > The inet_diag_lock_handler function uses ERR_PTR to encode errors but
> > its callers were testing against NULL.
> 
> Thanks for catching this Arnaldo!

Applied and queued up for 2.6.24-stable, thanks!

^ permalink raw reply

* Re: [INET]: Prevent out-of-sync truesize on ip_fragment slow path
From: David Miller @ 2008-01-29  4:45 UTC (permalink / raw)
  To: herbert; +Cc: netdev
In-Reply-To: <20080128111259.GA6490@gondor.apana.org.au>

From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Mon, 28 Jan 2008 22:12:59 +1100

> Hi:
> 
> [INET]: Prevent out-of-sync truesize on ip_fragment slow path
> 
> When ip_fragment has to hit the slow path the value of skb->truesize
> may go out of sync because we would have updated it without changing
> the packet length.  This violates the constraints on truesize.
> 
> This patch postpones the update of skb->truesize to prevent this.
> 
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Applied, I'll queue this up for 2.6.24-stable too.

^ permalink raw reply

* Re: [PATCH] [AX25]: Kill ax25_bind() user triggable printk.
From: David Miller @ 2008-01-29  4:44 UTC (permalink / raw)
  To: max; +Cc: netdev
In-Reply-To: <1201541470-25312-1-git-send-email-max@stro.at>

From: maximilian attems <max@stro.at>
Date: Mon, 28 Jan 2008 18:31:09 +0100

> on the last run overlooked that sfuzz triggable message.
> move the message to the corresponding comment.
> 
> Signed-off-by: maximilian attems <max@stro.at>

Applied.

^ permalink raw reply

* Re: [PATCH] [AX25]: Beautify x25_init() version printk.
From: David Miller @ 2008-01-29  4:43 UTC (permalink / raw)
  To: max; +Cc: netdev
In-Reply-To: <1201541470-25312-2-git-send-email-max@stro.at>

From: maximilian attems <max@stro.at>
Date: Mon, 28 Jan 2008 18:31:10 +0100

> kill ref to old version and dup Linux.
> 
> Signed-off-by: maximilian attems <max@stro.at>

Applied

^ permalink raw reply

* Re: [PATCH] [NET] 9p: kill dead static inline buf_put_string
From: David Miller @ 2008-01-29  4:28 UTC (permalink / raw)
  To: ericvh; +Cc: ilpo.jarvinen, netdev
In-Reply-To: <a4e6962a0801281342g1ef25baw6692bb0fff202c03@mail.gmail.com>

From: "Eric Van Hensbergen" <ericvh@gmail.com>
Date: Mon, 28 Jan 2008 15:42:44 -0600

> On Jan 25, 2008 4:46 PM, Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> wrote:
> > From: =?ISO-8859-1?q?Ilpo=20J=E4rvinen?= <ilpo.jarvinen@helsinki.fi>
> >
> > Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
> Acked-by: Eric Van Hensbergen <ericvh@gmail.com>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH] SELinux: Fix double free in selinux_netlbl_sock_setsid()
From: David Miller @ 2008-01-29  3:51 UTC (permalink / raw)
  To: paul.moore; +Cc: linux-kernel, netdev, selinux, stable, bunk, jmorris
In-Reply-To: <20080129022026.7930.18782.stgit@flek.lan>

From: Paul Moore <paul.moore@hp.com>
Date: Mon, 28 Jan 2008 21:20:26 -0500

> As pointed out by Adrian Bunk, commit 45c950e0f839fded922ebc0bfd59b1081cc71b70
> caused a double-free when security_netlbl_sid_to_secattr() fails.  This patch
> fixes this by removing the netlbl_secattr_destroy() call from that function
> since we are already releasing the secattr memory in
> selinux_netlbl_sock_setsid().
> 
> Signed-off-by: Paul Moore <paul.moore@hp.com>

Applied, and I'll queue this up for -stable too.

Please, when mentioning specific commits please also provide
the changelog headline along with the SHA1 hash.

The reason is that when this fix is moved over to another
tree where the SHA1 of the causing change is different people
studying your fix won't be able to find it without more stable
contextual information.

Thanks.

^ permalink raw reply

* Re: [0/3] [IPSEC]: Add async/aead support
From: David Miller @ 2008-01-29  3:38 UTC (permalink / raw)
  To: herbert; +Cc: netdev
In-Reply-To: <20080129031047.GA13625@gondor.apana.org.au>

From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Tue, 29 Jan 2008 14:10:47 +1100

> Hi Dave:
> 
> I've rebased the IPsec AEAD/async patches for the current net-2.6.25
> tree.

I've queued this up into a local tree, thanks Herbert.

I'm going to keep the real net-2.6.25.git tree untouched
until Linus pulls since the last thing I want to do is
screw up that merge :-)

^ permalink raw reply

* [PATCH 3/3] [IPSEC]: Add support for combined mode algorithms
From: Herbert Xu @ 2008-01-29  3:11 UTC (permalink / raw)
  To: David S. Miller, netdev
In-Reply-To: <20080129031047.GA13625@gondor.apana.org.au>

[IPSEC]: Add support for combined mode algorithms

This patch adds support for combined mode algorithms with GCM being the
first algorithm supported.

Combined mode algorithms can be added through the xfrm_user interface
using the new algorithm payload type XFRMA_ALG_AEAD.  Each algorithms
is identified by its name and the ICV length.

For the purposes of matching algorithms in xfrm_tmpl structures, combined
mode algorithms are occupy the same name space as encryption algorithms.
This is in line with how they are negotiated using IKE.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 include/linux/pfkeyv2.h |    6 ++
 include/linux/xfrm.h    |    8 ++
 include/net/xfrm.h      |    8 ++
 net/ipv4/esp4.c         |   71 ++++++++++++++++++++----
 net/ipv6/esp6.c         |   77 +++++++++++++++++++++-----
 net/xfrm/xfrm_algo.c    |  138 ++++++++++++++++++++++++++++++++++++++++++++++++
 net/xfrm/xfrm_user.c    |   71 +++++++++++++++++++++++-
 7 files changed, 347 insertions(+), 32 deletions(-)

diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h
--- a/include/linux/pfkeyv2.h
+++ b/include/linux/pfkeyv2.h
@@ -298,6 +298,12 @@ struct sadb_x_sec_ctx {
 #define SADB_X_EALG_BLOWFISHCBC		7
 #define SADB_EALG_NULL			11
 #define SADB_X_EALG_AESCBC		12
+#define SADB_X_EALG_AES_CCM_ICV8	14
+#define SADB_X_EALG_AES_CCM_ICV12	15
+#define SADB_X_EALG_AES_CCM_ICV16	16
+#define SADB_X_EALG_AES_GCM_ICV8	18
+#define SADB_X_EALG_AES_GCM_ICV12	19
+#define SADB_X_EALG_AES_GCM_ICV16	20
 #define SADB_X_EALG_CAMELLIACBC		22
 #define SADB_EALG_MAX                   253 /* last EALG */
 /* private allocations should use 249-255 (RFC2407) */
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -96,6 +96,13 @@ struct xfrm_algo {
 	char		alg_key[0];
 };
 
+struct xfrm_algo_aead {
+	char	alg_name[64];
+	int	alg_key_len;	/* in bits */
+	int	alg_icv_len;	/* in bits */
+	char	alg_key[0];
+};
+
 struct xfrm_stats {
 	__u32	replay_window;
 	__u32	replay;
@@ -270,6 +277,7 @@ enum xfrm_attr_type_t {
 	XFRMA_LASTUSED,
 	XFRMA_POLICY_TYPE,	/* struct xfrm_userpolicy_type */
 	XFRMA_MIGRATE,
+	XFRMA_ALG_AEAD,		/* struct xfrm_algo_aead */
 	__XFRMA_MAX
 
 #define XFRMA_MAX (__XFRMA_MAX - 1)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -159,6 +159,7 @@ struct xfrm_state
 	struct xfrm_algo	*aalg;
 	struct xfrm_algo	*ealg;
 	struct xfrm_algo	*calg;
+	struct xfrm_algo_aead	*aead;
 
 	/* Data for encapsulator */
 	struct xfrm_encap_tmpl	*encap;
@@ -1108,6 +1109,10 @@ static inline int xfrm_id_proto_match(u8
 /*
  * xfrm algorithm information
  */
+struct xfrm_algo_aead_info {
+	u16 icv_truncbits;
+};
+
 struct xfrm_algo_auth_info {
 	u16 icv_truncbits;
 	u16 icv_fullbits;
@@ -1127,6 +1132,7 @@ struct xfrm_algo_desc {
 	char *compat;
 	u8 available:1;
 	union {
+		struct xfrm_algo_aead_info aead;
 		struct xfrm_algo_auth_info auth;
 		struct xfrm_algo_encr_info encr;
 		struct xfrm_algo_comp_info comp;
@@ -1343,6 +1349,8 @@ extern struct xfrm_algo_desc *xfrm_calg_
 extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe);
 extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe);
 extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe);
+extern struct xfrm_algo_desc *xfrm_aead_get_byname(char *name, int icv_len,
+						   int probe);
 
 struct hash_desc;
 struct scatterlist;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -439,32 +439,53 @@ static void esp_destroy(struct xfrm_stat
 	kfree(esp);
 }
 
-static int esp_init_state(struct xfrm_state *x)
+static int esp_init_aead(struct xfrm_state *x)
+{
+	struct esp_data *esp = x->data;
+	struct crypto_aead *aead;
+	int err;
+
+	aead = crypto_alloc_aead(x->aead->alg_name, 0, 0);
+	err = PTR_ERR(aead);
+	if (IS_ERR(aead))
+		goto error;
+
+	esp->aead = aead;
+
+	err = crypto_aead_setkey(aead, x->aead->alg_key,
+				 (x->aead->alg_key_len + 7) / 8);
+	if (err)
+		goto error;
+
+	err = crypto_aead_setauthsize(aead, x->aead->alg_icv_len / 8);
+	if (err)
+		goto error;
+
+error:
+	return err;
+}
+
+static int esp_init_authenc(struct xfrm_state *x)
 {
-	struct esp_data *esp = NULL;
+	struct esp_data *esp = x->data;
 	struct crypto_aead *aead;
 	struct crypto_authenc_key_param *param;
 	struct rtattr *rta;
 	char *key;
 	char *p;
 	char authenc_name[CRYPTO_MAX_ALG_NAME];
-	u32 align;
 	unsigned int keylen;
 	int err;
 
+	err = -EINVAL;
 	if (x->ealg == NULL)
-		return -EINVAL;
+		goto error;
 
+	err = -ENAMETOOLONG;
 	if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)",
 		     x->aalg ? x->aalg->alg_name : "digest_null",
 		     x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
-		return -ENAMETOOLONG;
-
-	esp = kzalloc(sizeof(*esp), GFP_KERNEL);
-	if (esp == NULL)
-		return -ENOMEM;
-
-	x->data = esp;
+		goto error;
 
 	aead = crypto_alloc_aead(authenc_name, 0, 0);
 	err = PTR_ERR(aead);
@@ -512,8 +533,6 @@ static int esp_init_state(struct xfrm_st
 			goto free_key;
 	}
 
-	esp->padlen = 0;
-
 	param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8);
 	memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8);
 
@@ -522,9 +541,35 @@ static int esp_init_state(struct xfrm_st
 free_key:
 	kfree(key);
 
+error:
+	return err;
+}
+
+static int esp_init_state(struct xfrm_state *x)
+{
+	struct esp_data *esp;
+	struct crypto_aead *aead;
+	u32 align;
+	int err;
+
+	esp = kzalloc(sizeof(*esp), GFP_KERNEL);
+	if (esp == NULL)
+		return -ENOMEM;
+
+	x->data = esp;
+
+	if (x->aead)
+		err = esp_init_aead(x);
+	else
+		err = esp_init_authenc(x);
+
 	if (err)
 		goto error;
 
+	aead = esp->aead;
+
+	esp->padlen = 0;
+
 	x->props.header_len = sizeof(struct ip_esp_hdr) +
 			      crypto_aead_ivsize(aead);
 	if (x->props.mode == XFRM_MODE_TUNNEL)
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -382,35 +382,53 @@ static void esp6_destroy(struct xfrm_sta
 	kfree(esp);
 }
 
-static int esp6_init_state(struct xfrm_state *x)
+static int esp_init_aead(struct xfrm_state *x)
+{
+	struct esp_data *esp = x->data;
+	struct crypto_aead *aead;
+	int err;
+
+	aead = crypto_alloc_aead(x->aead->alg_name, 0, 0);
+	err = PTR_ERR(aead);
+	if (IS_ERR(aead))
+		goto error;
+
+	esp->aead = aead;
+
+	err = crypto_aead_setkey(aead, x->aead->alg_key,
+				 (x->aead->alg_key_len + 7) / 8);
+	if (err)
+		goto error;
+
+	err = crypto_aead_setauthsize(aead, x->aead->alg_icv_len / 8);
+	if (err)
+		goto error;
+
+error:
+	return err;
+}
+
+static int esp_init_authenc(struct xfrm_state *x)
 {
-	struct esp_data *esp = NULL;
+	struct esp_data *esp = x->data;
 	struct crypto_aead *aead;
 	struct crypto_authenc_key_param *param;
 	struct rtattr *rta;
 	char *key;
 	char *p;
 	char authenc_name[CRYPTO_MAX_ALG_NAME];
-	u32 align;
 	unsigned int keylen;
 	int err;
 
+	err = -EINVAL;
 	if (x->ealg == NULL)
-		return -EINVAL;
-
-	if (x->encap)
-		return -EINVAL;
+		goto error;
 
+	err = -ENAMETOOLONG;
 	if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)",
 		     x->aalg ? x->aalg->alg_name : "digest_null",
 		     x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
-		return -ENAMETOOLONG;
-
-	esp = kzalloc(sizeof(*esp), GFP_KERNEL);
-	if (esp == NULL)
-		return -ENOMEM;
-
-	x->data = esp;
+		goto error;
 
 	aead = crypto_alloc_aead(authenc_name, 0, 0);
 	err = PTR_ERR(aead);
@@ -458,8 +476,6 @@ static int esp6_init_state(struct xfrm_s
 			goto free_key;
 	}
 
-	esp->padlen = 0;
-
 	param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8);
 	memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8);
 
@@ -468,9 +484,38 @@ static int esp6_init_state(struct xfrm_s
 free_key:
 	kfree(key);
 
+error:
+	return err;
+}
+
+static int esp6_init_state(struct xfrm_state *x)
+{
+	struct esp_data *esp;
+	struct crypto_aead *aead;
+	u32 align;
+	int err;
+
+	if (x->encap)
+		return -EINVAL;
+
+	esp = kzalloc(sizeof(*esp), GFP_KERNEL);
+	if (esp == NULL)
+		return -ENOMEM;
+
+	x->data = esp;
+
+	if (x->aead)
+		err = esp_init_aead(x);
+	else
+		err = esp_init_authenc(x);
+
 	if (err)
 		goto error;
 
+	aead = esp->aead;
+
+	esp->padlen = 0;
+
 	x->props.header_len = sizeof(struct ip_esp_hdr) +
 			      crypto_aead_ivsize(aead);
 	switch (x->props.mode) {
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -28,6 +28,105 @@
  * that instantiated crypto transforms have correct parameters for IPsec
  * purposes.
  */
+static struct xfrm_algo_desc aead_list[] = {
+{
+	.name = "rfc4106(gcm(aes))",
+
+	.uinfo = {
+		.aead = {
+			.icv_truncbits = 64,
+		}
+	},
+
+	.desc = {
+		.sadb_alg_id = SADB_X_EALG_AES_GCM_ICV8,
+		.sadb_alg_ivlen = 8,
+		.sadb_alg_minbits = 128,
+		.sadb_alg_maxbits = 256
+	}
+},
+{
+	.name = "rfc4106(gcm(aes))",
+
+	.uinfo = {
+		.aead = {
+			.icv_truncbits = 96,
+		}
+	},
+
+	.desc = {
+		.sadb_alg_id = SADB_X_EALG_AES_GCM_ICV12,
+		.sadb_alg_ivlen = 8,
+		.sadb_alg_minbits = 128,
+		.sadb_alg_maxbits = 256
+	}
+},
+{
+	.name = "rfc4106(gcm(aes))",
+
+	.uinfo = {
+		.aead = {
+			.icv_truncbits = 128,
+		}
+	},
+
+	.desc = {
+		.sadb_alg_id = SADB_X_EALG_AES_GCM_ICV16,
+		.sadb_alg_ivlen = 8,
+		.sadb_alg_minbits = 128,
+		.sadb_alg_maxbits = 256
+	}
+},
+{
+	.name = "rfc4309(ccm(aes))",
+
+	.uinfo = {
+		.aead = {
+			.icv_truncbits = 64,
+		}
+	},
+
+	.desc = {
+		.sadb_alg_id = SADB_X_EALG_AES_CCM_ICV8,
+		.sadb_alg_ivlen = 8,
+		.sadb_alg_minbits = 128,
+		.sadb_alg_maxbits = 256
+	}
+},
+{
+	.name = "rfc4309(ccm(aes))",
+
+	.uinfo = {
+		.aead = {
+			.icv_truncbits = 96,
+		}
+	},
+
+	.desc = {
+		.sadb_alg_id = SADB_X_EALG_AES_CCM_ICV12,
+		.sadb_alg_ivlen = 8,
+		.sadb_alg_minbits = 128,
+		.sadb_alg_maxbits = 256
+	}
+},
+{
+	.name = "rfc4309(ccm(aes))",
+
+	.uinfo = {
+		.aead = {
+			.icv_truncbits = 128,
+		}
+	},
+
+	.desc = {
+		.sadb_alg_id = SADB_X_EALG_AES_CCM_ICV16,
+		.sadb_alg_ivlen = 8,
+		.sadb_alg_minbits = 128,
+		.sadb_alg_maxbits = 256
+	}
+},
+};
+
 static struct xfrm_algo_desc aalg_list[] = {
 {
 	.name = "hmac(digest_null)",
@@ -332,6 +431,11 @@ static struct xfrm_algo_desc calg_list[]
 },
 };
 
+static inline int aead_entries(void)
+{
+	return ARRAY_SIZE(aead_list);
+}
+
 static inline int aalg_entries(void)
 {
 	return ARRAY_SIZE(aalg_list);
@@ -354,6 +458,13 @@ struct xfrm_algo_list {
 	u32 mask;
 };
 
+static const struct xfrm_algo_list xfrm_aead_list = {
+	.algs = aead_list,
+	.entries = ARRAY_SIZE(aead_list),
+	.type = CRYPTO_ALG_TYPE_AEAD,
+	.mask = CRYPTO_ALG_TYPE_MASK,
+};
+
 static const struct xfrm_algo_list xfrm_aalg_list = {
 	.algs = aalg_list,
 	.entries = ARRAY_SIZE(aalg_list),
@@ -461,6 +572,33 @@ struct xfrm_algo_desc *xfrm_calg_get_byn
 }
 EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
 
+struct xfrm_aead_name {
+	const char *name;
+	int icvbits;
+};
+
+static int xfrm_aead_name_match(const struct xfrm_algo_desc *entry,
+				const void *data)
+{
+	const struct xfrm_aead_name *aead = data;
+	const char *name = aead->name;
+
+	return aead->icvbits == entry->uinfo.aead.icv_truncbits && name &&
+	       !strcmp(name, entry->name);
+}
+
+struct xfrm_algo_desc *xfrm_aead_get_byname(char *name, int icv_len, int probe)
+{
+	struct xfrm_aead_name data = {
+		.name = name,
+		.icvbits = icv_len,
+	};
+
+	return xfrm_find_algo(&xfrm_aead_list, xfrm_aead_name_match, &data,
+			      probe);
+}
+EXPORT_SYMBOL_GPL(xfrm_aead_get_byname);
+
 struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
 {
 	if (idx >= aalg_entries())
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -31,6 +31,11 @@
 #include <linux/in6.h>
 #endif
 
+static inline int aead_len(struct xfrm_algo_aead *alg)
+{
+	return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
+}
+
 static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
 {
 	struct nlattr *rt = attrs[type];
@@ -68,6 +73,22 @@ static int verify_one_alg(struct nlattr 
 	return 0;
 }
 
+static int verify_aead(struct nlattr **attrs)
+{
+	struct nlattr *rt = attrs[XFRMA_ALG_AEAD];
+	struct xfrm_algo_aead *algp;
+
+	if (!rt)
+		return 0;
+
+	algp = nla_data(rt);
+	if (nla_len(rt) < aead_len(algp))
+		return -EINVAL;
+
+	algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0';
+	return 0;
+}
+
 static void verify_one_addr(struct nlattr **attrs, enum xfrm_attr_type_t type,
 			   xfrm_address_t **addrp)
 {
@@ -119,20 +140,28 @@ static int verify_newsa_info(struct xfrm
 	switch (p->id.proto) {
 	case IPPROTO_AH:
 		if (!attrs[XFRMA_ALG_AUTH]	||
+		    attrs[XFRMA_ALG_AEAD]	||
 		    attrs[XFRMA_ALG_CRYPT]	||
 		    attrs[XFRMA_ALG_COMP])
 			goto out;
 		break;
 
 	case IPPROTO_ESP:
-		if ((!attrs[XFRMA_ALG_AUTH] &&
-		     !attrs[XFRMA_ALG_CRYPT])	||
-		    attrs[XFRMA_ALG_COMP])
+		if (attrs[XFRMA_ALG_COMP])
+			goto out;
+		if (!attrs[XFRMA_ALG_AUTH] &&
+		    !attrs[XFRMA_ALG_CRYPT] &&
+		    !attrs[XFRMA_ALG_AEAD])
 			goto out;
+		if ((attrs[XFRMA_ALG_AUTH] ||
+		     attrs[XFRMA_ALG_CRYPT]) &&
+		    attrs[XFRMA_ALG_AEAD])
+		    	goto out;
 		break;
 
 	case IPPROTO_COMP:
 		if (!attrs[XFRMA_ALG_COMP]	||
+		    attrs[XFRMA_ALG_AEAD]	||
 		    attrs[XFRMA_ALG_AUTH]	||
 		    attrs[XFRMA_ALG_CRYPT])
 			goto out;
@@ -143,6 +172,7 @@ static int verify_newsa_info(struct xfrm
 	case IPPROTO_ROUTING:
 		if (attrs[XFRMA_ALG_COMP]	||
 		    attrs[XFRMA_ALG_AUTH]	||
+		    attrs[XFRMA_ALG_AEAD]	||
 		    attrs[XFRMA_ALG_CRYPT]	||
 		    attrs[XFRMA_ENCAP]		||
 		    attrs[XFRMA_SEC_CTX]	||
@@ -155,6 +185,8 @@ static int verify_newsa_info(struct xfrm
 		goto out;
 	}
 
+	if ((err = verify_aead(attrs)))
+		goto out;
 	if ((err = verify_one_alg(attrs, XFRMA_ALG_AUTH)))
 		goto out;
 	if ((err = verify_one_alg(attrs, XFRMA_ALG_CRYPT)))
@@ -208,6 +240,31 @@ static int attach_one_algo(struct xfrm_a
 	return 0;
 }
 
+static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props,
+		       struct nlattr *rta)
+{
+	struct xfrm_algo_aead *p, *ualg;
+	struct xfrm_algo_desc *algo;
+
+	if (!rta)
+		return 0;
+
+	ualg = nla_data(rta);
+
+	algo = xfrm_aead_get_byname(ualg->alg_name, ualg->alg_icv_len, 1);
+	if (!algo)
+		return -ENOSYS;
+	*props = algo->desc.sadb_alg_id;
+
+	p = kmemdup(ualg, aead_len(ualg), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	strcpy(p->alg_name, algo->name);
+	*algpp = p;
+	return 0;
+}
+
 static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx)
 {
 	int len = 0;
@@ -286,6 +343,9 @@ static struct xfrm_state *xfrm_state_con
 
 	copy_from_user_state(x, p);
 
+	if ((err = attach_aead(&x->aead, &x->props.ealgo,
+			       attrs[XFRMA_ALG_AEAD])))
+		goto error;
 	if ((err = attach_one_algo(&x->aalg, &x->props.aalgo,
 				   xfrm_aalg_get_byname,
 				   attrs[XFRMA_ALG_AUTH])))
@@ -510,6 +570,8 @@ static int copy_to_user_state_extra(stru
 	if (x->lastused)
 		NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused);
 
+	if (x->aead)
+		NLA_PUT(skb, XFRMA_ALG_AEAD, aead_len(x->aead), x->aead);
 	if (x->aalg)
 		NLA_PUT(skb, XFRMA_ALG_AUTH, xfrm_alg_len(x->aalg), x->aalg);
 	if (x->ealg)
@@ -1808,6 +1870,7 @@ static const int xfrm_msg_min[XFRM_NR_MS
 #undef XMSGSIZE
 
 static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
+	[XFRMA_ALG_AEAD]	= { .len = sizeof(struct xfrm_algo_aead) },
 	[XFRMA_ALG_AUTH]	= { .len = sizeof(struct xfrm_algo) },
 	[XFRMA_ALG_CRYPT]	= { .len = sizeof(struct xfrm_algo) },
 	[XFRMA_ALG_COMP]	= { .len = sizeof(struct xfrm_algo) },
@@ -1972,6 +2035,8 @@ static int xfrm_notify_sa_flush(struct k
 static inline size_t xfrm_sa_len(struct xfrm_state *x)
 {
 	size_t l = 0;
+	if (x->aead)
+		l += nla_total_size(aead_len(x->aead));
 	if (x->aalg)
 		l += nla_total_size(xfrm_alg_len(x->aalg));
 	if (x->ealg)

^ permalink raw reply

* [PATCH 2/3] [IPSEC]: Allow async algorithms
From: Herbert Xu @ 2008-01-29  3:11 UTC (permalink / raw)
  To: David S. Miller, netdev
In-Reply-To: <20080129031047.GA13625@gondor.apana.org.au>

[IPSEC]: Allow async algorithms

Now that ESP uses authenc we can turn on the support for async algorithms
in IPsec.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 net/xfrm/xfrm_algo.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -358,21 +358,21 @@ static const struct xfrm_algo_list xfrm_
 	.algs = aalg_list,
 	.entries = ARRAY_SIZE(aalg_list),
 	.type = CRYPTO_ALG_TYPE_HASH,
-	.mask = CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC,
+	.mask = CRYPTO_ALG_TYPE_HASH_MASK,
 };
 
 static const struct xfrm_algo_list xfrm_ealg_list = {
 	.algs = ealg_list,
 	.entries = ARRAY_SIZE(ealg_list),
 	.type = CRYPTO_ALG_TYPE_BLKCIPHER,
-	.mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC,
+	.mask = CRYPTO_ALG_TYPE_BLKCIPHER_MASK,
 };
 
 static const struct xfrm_algo_list xfrm_calg_list = {
 	.algs = calg_list,
 	.entries = ARRAY_SIZE(calg_list),
 	.type = CRYPTO_ALG_TYPE_COMPRESS,
-	.mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC,
+	.mask = CRYPTO_ALG_TYPE_MASK,
 };
 
 static struct xfrm_algo_desc *xfrm_find_algo(

^ permalink raw reply

* [PATCH 1/3] [IPSEC]: Use crypto_aead and authenc in ESP
From: Herbert Xu @ 2008-01-29  3:11 UTC (permalink / raw)
  To: David S. Miller, netdev
In-Reply-To: <20080129031047.GA13625@gondor.apana.org.au>

[IPSEC]: Use crypto_aead and authenc in ESP

This patch converts ESP to use the crypto_aead interface and in particular
the authenc algorithm.  This lays the foundations for future support of
combined mode algorithms.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 include/net/esp.h |   52 -----
 net/ipv4/Kconfig  |    1 
 net/ipv4/esp4.c   |  497 ++++++++++++++++++++++++++++++++----------------------
 net/ipv6/Kconfig  |    1 
 net/ipv6/esp6.c   |  460 ++++++++++++++++++++++++++++++-------------------
 5 files changed, 590 insertions(+), 421 deletions(-)

diff --git a/include/net/esp.h b/include/net/esp.h
--- a/include/net/esp.h
+++ b/include/net/esp.h
@@ -1,58 +1,20 @@
 #ifndef _NET_ESP_H
 #define _NET_ESP_H
 
-#include <linux/crypto.h>
-#include <net/xfrm.h>
-#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
 
-#define ESP_NUM_FAST_SG		4
+struct crypto_aead;
 
-struct esp_data
-{
-	struct scatterlist		sgbuf[ESP_NUM_FAST_SG];
+struct esp_data {
+	/* 0..255 */
+	int padlen;
 
-	/* Confidentiality */
-	struct {
-		int			padlen;		/* 0..255 */
-		/* ivlen is offset from enc_data, where encrypted data start.
-		 * It is logically different of crypto_tfm_alg_ivsize(tfm).
-		 * We assume that it is either zero (no ivec), or
-		 * >= crypto_tfm_alg_ivsize(tfm). */
-		int			ivlen;
-		int			ivinitted;
-		u8			*ivec;		/* ivec buffer */
-		struct crypto_blkcipher	*tfm;		/* crypto handle */
-	} conf;
-
-	/* Integrity. It is active when icv_full_len != 0 */
-	struct {
-		u8			*work_icv;
-		int			icv_full_len;
-		int			icv_trunc_len;
-		struct crypto_hash	*tfm;
-	} auth;
+	/* Confidentiality & Integrity */
+	struct crypto_aead *aead;
 };
 
 extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);
 
-static inline int esp_mac_digest(struct esp_data *esp, struct sk_buff *skb,
-				 int offset, int len)
-{
-	struct hash_desc desc;
-	int err;
-
-	desc.tfm = esp->auth.tfm;
-	desc.flags = 0;
-
-	err = crypto_hash_init(&desc);
-	if (unlikely(err))
-		return err;
-	err = skb_icv_walk(skb, &desc, offset, len, crypto_hash_update);
-	if (unlikely(err))
-		return err;
-	return crypto_hash_final(&desc, esp->auth.work_icv);
-}
-
 struct ip_esp_hdr;
 
 static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb)
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -343,6 +343,7 @@ config INET_ESP
 	tristate "IP: ESP transformation"
 	select XFRM
 	select CRYPTO
+	select CRYPTO_AEAD
 	select CRYPTO_HMAC
 	select CRYPTO_MD5
 	select CRYPTO_CBC
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -1,27 +1,118 @@
+#include <crypto/aead.h>
+#include <crypto/authenc.h>
 #include <linux/err.h>
 #include <linux/module.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
 #include <net/esp.h>
 #include <linux/scatterlist.h>
-#include <linux/crypto.h>
 #include <linux/kernel.h>
 #include <linux/pfkeyv2.h>
-#include <linux/random.h>
+#include <linux/rtnetlink.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/in6.h>
 #include <net/icmp.h>
 #include <net/protocol.h>
 #include <net/udp.h>
 
+struct esp_skb_cb {
+	struct xfrm_skb_cb xfrm;
+	void *tmp;
+};
+
+#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))
+
+/*
+ * Allocate an AEAD request structure with extra space for SG and IV.
+ *
+ * For alignment considerations the IV is placed at the front, followed
+ * by the request and finally the SG list.
+ *
+ * TODO: Use spare space in skb for this where possible.
+ */
+static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags)
+{
+	unsigned int len;
+
+	len = crypto_aead_ivsize(aead);
+	if (len) {
+		len += crypto_aead_alignmask(aead) &
+		       ~(crypto_tfm_ctx_alignment() - 1);
+		len = ALIGN(len, crypto_tfm_ctx_alignment());
+	}
+
+	len += sizeof(struct aead_givcrypt_request) + crypto_aead_reqsize(aead);
+	len = ALIGN(len, __alignof__(struct scatterlist));
+
+	len += sizeof(struct scatterlist) * nfrags;
+
+	return kmalloc(len, GFP_ATOMIC);
+}
+
+static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp)
+{
+	return crypto_aead_ivsize(aead) ? 
+	       PTR_ALIGN((u8 *)tmp, crypto_aead_alignmask(aead) + 1) : tmp;
+}
+
+static inline struct aead_givcrypt_request *esp_tmp_givreq(
+	struct crypto_aead *aead, u8 *iv)
+{
+	struct aead_givcrypt_request *req;
+
+	req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead),
+				crypto_tfm_ctx_alignment());
+	aead_givcrypt_set_tfm(req, aead);
+	return req;
+}
+
+static inline struct aead_request *esp_tmp_req(struct crypto_aead *aead, u8 *iv)
+{
+	struct aead_request *req;
+
+	req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead),
+				crypto_tfm_ctx_alignment());
+	aead_request_set_tfm(req, aead);
+	return req;
+}
+
+static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,
+					     struct aead_request *req)
+{
+	return (void *)ALIGN((unsigned long)(req + 1) +
+			     crypto_aead_reqsize(aead),
+			     __alignof__(struct scatterlist));
+}
+
+static inline struct scatterlist *esp_givreq_sg(
+	struct crypto_aead *aead, struct aead_givcrypt_request *req)
+{
+	return (void *)ALIGN((unsigned long)(req + 1) +
+			     crypto_aead_reqsize(aead),
+			     __alignof__(struct scatterlist));
+}
+
+static void esp_output_done(struct crypto_async_request *base, int err)
+{
+	struct sk_buff *skb = base->data;
+
+	kfree(ESP_SKB_CB(skb)->tmp);
+	xfrm_output_resume(skb, err);
+}
+
 static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err;
 	struct ip_esp_hdr *esph;
-	struct crypto_blkcipher *tfm;
-	struct blkcipher_desc desc;
+	struct crypto_aead *aead;
+	struct aead_givcrypt_request *req;
+	struct scatterlist *sg;
+	struct scatterlist *asg;
 	struct esp_data *esp;
 	struct sk_buff *trailer;
+	void *tmp;
+	u8 *iv;
 	u8 *tail;
 	int blksize;
 	int clen;
@@ -36,18 +127,27 @@ static int esp_output(struct xfrm_state 
 	clen = skb->len;
 
 	esp = x->data;
-	alen = esp->auth.icv_trunc_len;
-	tfm = esp->conf.tfm;
-	desc.tfm = tfm;
-	desc.flags = 0;
-	blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
+	aead = esp->aead;
+	alen = crypto_aead_authsize(aead);
+
+	blksize = ALIGN(crypto_aead_blocksize(aead), 4);
 	clen = ALIGN(clen + 2, blksize);
-	if (esp->conf.padlen)
-		clen = ALIGN(clen, esp->conf.padlen);
+	if (esp->padlen)
+		clen = ALIGN(clen, esp->padlen);
+
+	if ((err = skb_cow_data(skb, clen - skb->len + alen, &trailer)) < 0)
+		goto error;
+	nfrags = err;
 
-	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0)
+	tmp = esp_alloc_tmp(aead, nfrags + 1);
+	if (!tmp)
 		goto error;
 
+	iv = esp_tmp_iv(aead, tmp);
+	req = esp_tmp_givreq(aead, iv);
+	asg = esp_givreq_sg(aead, req);
+	sg = asg + 1;
+
 	/* Fill padding... */
 	tail = skb_tail_pointer(trailer);
 	do {
@@ -56,28 +156,34 @@ static int esp_output(struct xfrm_state 
 			tail[i] = i + 1;
 	} while (0);
 	tail[clen - skb->len - 2] = (clen - skb->len) - 2;
-	pskb_put(skb, trailer, clen - skb->len);
+	tail[clen - skb->len - 1] = *skb_mac_header(skb);
+	pskb_put(skb, trailer, clen - skb->len + alen);
 
 	skb_push(skb, -skb_network_offset(skb));
 	esph = ip_esp_hdr(skb);
-	*(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
 	*skb_mac_header(skb) = IPPROTO_ESP;
 
-	spin_lock_bh(&x->lock);
-
 	/* this is non-NULL only with UDP Encapsulation */
 	if (x->encap) {
 		struct xfrm_encap_tmpl *encap = x->encap;
 		struct udphdr *uh;
 		__be32 *udpdata32;
+		unsigned int sport, dport;
+		int encap_type;
+
+		spin_lock_bh(&x->lock);
+		sport = encap->encap_sport;
+		dport = encap->encap_dport;
+		encap_type = encap->encap_type;
+		spin_unlock_bh(&x->lock);
 
 		uh = (struct udphdr *)esph;
-		uh->source = encap->encap_sport;
-		uh->dest = encap->encap_dport;
-		uh->len = htons(skb->len + alen - skb_transport_offset(skb));
+		uh->source = sport;
+		uh->dest = dport;
+		uh->len = htons(skb->len - skb_transport_offset(skb));
 		uh->check = 0;
 
-		switch (encap->encap_type) {
+		switch (encap_type) {
 		default:
 		case UDP_ENCAP_ESPINUDP:
 			esph = (struct ip_esp_hdr *)(uh + 1);
@@ -95,131 +201,45 @@ static int esp_output(struct xfrm_state 
 	esph->spi = x->id.spi;
 	esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq);
 
-	if (esp->conf.ivlen) {
-		if (unlikely(!esp->conf.ivinitted)) {
-			get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
-			esp->conf.ivinitted = 1;
-		}
-		crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
-	}
-
-	do {
-		struct scatterlist *sg = &esp->sgbuf[0];
-
-		if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
-			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
-			if (!sg)
-				goto unlock;
-		}
-		sg_init_table(sg, nfrags);
-		skb_to_sgvec(skb, sg,
-			     esph->enc_data +
-			     esp->conf.ivlen -
-			     skb->data, clen);
-		err = crypto_blkcipher_encrypt(&desc, sg, sg, clen);
-		if (unlikely(sg != &esp->sgbuf[0]))
-			kfree(sg);
-	} while (0);
-
-	if (unlikely(err))
-		goto unlock;
-
-	if (esp->conf.ivlen) {
-		memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen);
-		crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
-	}
+	sg_init_table(sg, nfrags);
+	skb_to_sgvec(skb, sg,
+		     esph->enc_data + crypto_aead_ivsize(aead) - skb->data,
+		     clen + alen);
+	sg_init_one(asg, esph, sizeof(*esph));
+
+	aead_givcrypt_set_callback(req, 0, esp_output_done, skb);
+	aead_givcrypt_set_crypt(req, sg, sg, clen, iv);
+	aead_givcrypt_set_assoc(req, asg, sizeof(*esph));
+	aead_givcrypt_set_giv(req, esph->enc_data, XFRM_SKB_CB(skb)->seq);
+
+	ESP_SKB_CB(skb)->tmp = tmp;
+	err = crypto_aead_givencrypt(req);
+	if (err == -EINPROGRESS)
+		goto error;
 
-	if (esp->auth.icv_full_len) {
-		err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data,
-				     sizeof(*esph) + esp->conf.ivlen + clen);
-		memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen);
-	}
+	if (err == -EBUSY)
+		err = NET_XMIT_DROP;
 
-unlock:
-	spin_unlock_bh(&x->lock);
+	kfree(tmp);
 
 error:
 	return err;
 }
 
-/*
- * Note: detecting truncated vs. non-truncated authentication data is very
- * expensive, so we only support truncated data, which is the recommended
- * and common case.
- */
-static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
+static int esp_input_done2(struct sk_buff *skb, int err)
 {
 	struct iphdr *iph;
-	struct ip_esp_hdr *esph;
+	struct xfrm_state *x = xfrm_input_state(skb);
 	struct esp_data *esp = x->data;
-	struct crypto_blkcipher *tfm = esp->conf.tfm;
-	struct blkcipher_desc desc = { .tfm = tfm };
-	struct sk_buff *trailer;
-	int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
-	int alen = esp->auth.icv_trunc_len;
-	int elen = skb->len - sizeof(*esph) - esp->conf.ivlen - alen;
-	int nfrags;
+	struct crypto_aead *aead = esp->aead;
+	int alen = crypto_aead_authsize(aead);
+	int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);
+	int elen = skb->len - hlen;
 	int ihl;
 	u8 nexthdr[2];
-	struct scatterlist *sg;
 	int padlen;
-	int err = -EINVAL;
 
-	if (!pskb_may_pull(skb, sizeof(*esph)))
-		goto out;
-
-	if (elen <= 0 || (elen & (blksize-1)))
-		goto out;
-
-	if ((err = skb_cow_data(skb, 0, &trailer)) < 0)
-		goto out;
-	nfrags = err;
-
-	skb->ip_summed = CHECKSUM_NONE;
-
-	spin_lock(&x->lock);
-
-	/* If integrity check is required, do this. */
-	if (esp->auth.icv_full_len) {
-		u8 sum[alen];
-
-		err = esp_mac_digest(esp, skb, 0, skb->len - alen);
-		if (err)
-			goto unlock;
-
-		if (skb_copy_bits(skb, skb->len - alen, sum, alen))
-			BUG();
-
-		if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) {
-			err = -EBADMSG;
-			goto unlock;
-		}
-	}
-
-	esph = (struct ip_esp_hdr *)skb->data;
-
-	/* Get ivec. This can be wrong, check against another impls. */
-	if (esp->conf.ivlen)
-		crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen);
-
-	sg = &esp->sgbuf[0];
-
-	if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
-		err = -ENOMEM;
-		sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
-		if (!sg)
-			goto unlock;
-	}
-	sg_init_table(sg, nfrags);
-	skb_to_sgvec(skb, sg,
-		     sizeof(*esph) + esp->conf.ivlen,
-		     elen);
-	err = crypto_blkcipher_decrypt(&desc, sg, sg, elen);
-	if (unlikely(sg != &esp->sgbuf[0]))
-		kfree(sg);
-
-unlock:
-	spin_unlock(&x->lock);
+	kfree(ESP_SKB_CB(skb)->tmp);
 
 	if (unlikely(err))
 		goto out;
@@ -229,15 +249,11 @@ unlock:
 
 	err = -EINVAL;
 	padlen = nexthdr[0];
-	if (padlen+2 >= elen)
+	if (padlen + 2 + alen >= elen)
 		goto out;
 
 	/* ... check padding bits here. Silly. :-) */
 
-	/* RFC4303: Drop dummy packets without any error */
-	if (nexthdr[1] == IPPROTO_NONE)
-		goto out;
-
 	iph = ip_hdr(skb);
 	ihl = iph->ihl * 4;
 
@@ -279,10 +295,87 @@ unlock:
 	}
 
 	pskb_trim(skb, skb->len - alen - padlen - 2);
-	__skb_pull(skb, sizeof(*esph) + esp->conf.ivlen);
+	__skb_pull(skb, hlen);
 	skb_set_transport_header(skb, -ihl);
 
-	return nexthdr[1];
+	err = nexthdr[1];
+
+	/* RFC4303: Drop dummy packets without any error */
+	if (err == IPPROTO_NONE)
+		err = -EINVAL;
+
+out:
+	return err;
+}
+
+static void esp_input_done(struct crypto_async_request *base, int err)
+{
+	struct sk_buff *skb = base->data;
+
+	xfrm_input_resume(skb, esp_input_done2(skb, err));
+}
+
+/*
+ * Note: detecting truncated vs. non-truncated authentication data is very
+ * expensive, so we only support truncated data, which is the recommended
+ * and common case.
+ */
+static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+	struct ip_esp_hdr *esph;
+	struct esp_data *esp = x->data;
+	struct crypto_aead *aead = esp->aead;
+	struct aead_request *req;
+	struct sk_buff *trailer;
+	int elen = skb->len - sizeof(*esph) - crypto_aead_ivsize(aead);
+	int nfrags;
+	void *tmp;
+	u8 *iv;
+	struct scatterlist *sg;
+	struct scatterlist *asg;
+	int err = -EINVAL;
+
+	if (!pskb_may_pull(skb, sizeof(*esph)))
+		goto out;
+
+	if (elen <= 0)
+		goto out;
+
+	if ((err = skb_cow_data(skb, 0, &trailer)) < 0)
+		goto out;
+	nfrags = err;
+
+	err = -ENOMEM;
+	tmp = esp_alloc_tmp(aead, nfrags + 1);
+	if (!tmp)
+		goto out;
+
+	ESP_SKB_CB(skb)->tmp = tmp;
+	iv = esp_tmp_iv(aead, tmp);
+	req = esp_tmp_req(aead, iv);
+	asg = esp_req_sg(aead, req);
+	sg = asg + 1;
+
+	skb->ip_summed = CHECKSUM_NONE;
+
+	esph = (struct ip_esp_hdr *)skb->data;
+
+	/* Get ivec. This can be wrong, check against another impls. */
+	iv = esph->enc_data;
+
+	sg_init_table(sg, nfrags);
+	skb_to_sgvec(skb, sg, sizeof(*esph) + crypto_aead_ivsize(aead), elen);
+	sg_init_one(asg, esph, sizeof(*esph));
+
+	aead_request_set_callback(req, 0, esp_input_done, skb);
+	aead_request_set_crypt(req, sg, sg, elen, iv);
+	aead_request_set_assoc(req, asg, sizeof(*esph));
+
+	err = crypto_aead_decrypt(req);
+	if (err == -EINPROGRESS)
+		goto out;
+
+	err = esp_input_done2(skb, err);
 
 out:
 	return err;
@@ -291,11 +384,11 @@ out:
 static u32 esp4_get_mtu(struct xfrm_state *x, int mtu)
 {
 	struct esp_data *esp = x->data;
-	u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
-	u32 align = max_t(u32, blksize, esp->conf.padlen);
+	u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4);
+	u32 align = max_t(u32, blksize, esp->padlen);
 	u32 rem;
 
-	mtu -= x->props.header_len + esp->auth.icv_trunc_len;
+	mtu -= x->props.header_len + crypto_aead_authsize(esp->aead);
 	rem = mtu & (align - 1);
 	mtu &= ~(align - 1);
 
@@ -342,80 +435,98 @@ static void esp_destroy(struct xfrm_stat
 	if (!esp)
 		return;
 
-	crypto_free_blkcipher(esp->conf.tfm);
-	esp->conf.tfm = NULL;
-	kfree(esp->conf.ivec);
-	esp->conf.ivec = NULL;
-	crypto_free_hash(esp->auth.tfm);
-	esp->auth.tfm = NULL;
-	kfree(esp->auth.work_icv);
-	esp->auth.work_icv = NULL;
+	crypto_free_aead(esp->aead);
 	kfree(esp);
 }
 
 static int esp_init_state(struct xfrm_state *x)
 {
 	struct esp_data *esp = NULL;
-	struct crypto_blkcipher *tfm;
+	struct crypto_aead *aead;
+	struct crypto_authenc_key_param *param;
+	struct rtattr *rta;
+	char *key;
+	char *p;
+	char authenc_name[CRYPTO_MAX_ALG_NAME];
 	u32 align;
+	unsigned int keylen;
+	int err;
 
 	if (x->ealg == NULL)
-		goto error;
+		return -EINVAL;
+
+	if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)",
+		     x->aalg ? x->aalg->alg_name : "digest_null",
+		     x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
+		return -ENAMETOOLONG;
 
 	esp = kzalloc(sizeof(*esp), GFP_KERNEL);
 	if (esp == NULL)
 		return -ENOMEM;
 
+	x->data = esp;
+
+	aead = crypto_alloc_aead(authenc_name, 0, 0);
+	err = PTR_ERR(aead);
+	if (IS_ERR(aead))
+		goto error;
+
+	esp->aead = aead;
+
+	keylen = (x->aalg ? (x->aalg->alg_key_len + 7) / 8 : 0) +
+		 (x->ealg->alg_key_len + 7) / 8 + RTA_SPACE(sizeof(*param));
+	err = -ENOMEM;
+	key = kmalloc(keylen, GFP_KERNEL);
+	if (!key)
+		goto error;
+
+	p = key;
+	rta = (void *)p;
+	rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM;
+	rta->rta_len = RTA_LENGTH(sizeof(*param));
+	param = RTA_DATA(rta);
+	p += RTA_SPACE(sizeof(*param));
+
 	if (x->aalg) {
 		struct xfrm_algo_desc *aalg_desc;
-		struct crypto_hash *hash;
-
-		hash = crypto_alloc_hash(x->aalg->alg_name, 0,
-					 CRYPTO_ALG_ASYNC);
-		if (IS_ERR(hash))
-			goto error;
 
-		esp->auth.tfm = hash;
-		if (crypto_hash_setkey(hash, x->aalg->alg_key,
-				       (x->aalg->alg_key_len + 7) / 8))
-			goto error;
+		memcpy(p, x->aalg->alg_key, (x->aalg->alg_key_len + 7) / 8);
+		p += (x->aalg->alg_key_len + 7) / 8;
 
 		aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
 		BUG_ON(!aalg_desc);
 
+		err = -EINVAL;
 		if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
-		    crypto_hash_digestsize(hash)) {
+		    crypto_aead_authsize(aead)) {
 			NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
 				 x->aalg->alg_name,
-				 crypto_hash_digestsize(hash),
+				 crypto_aead_authsize(aead),
 				 aalg_desc->uinfo.auth.icv_fullbits/8);
-			goto error;
+			goto free_key;
 		}
 
-		esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
-		esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
-
-		esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL);
-		if (!esp->auth.work_icv)
-			goto error;
+		err = crypto_aead_setauthsize(
+			aead, aalg_desc->uinfo.auth.icv_truncbits / 8);
+		if (err)
+			goto free_key;
 	}
 
-	tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(tfm))
-		goto error;
-	esp->conf.tfm = tfm;
-	esp->conf.ivlen = crypto_blkcipher_ivsize(tfm);
-	esp->conf.padlen = 0;
-	if (esp->conf.ivlen) {
-		esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
-		if (unlikely(esp->conf.ivec == NULL))
-			goto error;
-		esp->conf.ivinitted = 0;
-	}
-	if (crypto_blkcipher_setkey(tfm, x->ealg->alg_key,
-				    (x->ealg->alg_key_len + 7) / 8))
+	esp->padlen = 0;
+
+	param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8);
+	memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8);
+
+	err = crypto_aead_setkey(aead, key, keylen);
+
+free_key:
+	kfree(key);
+
+	if (err)
 		goto error;
-	x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
+
+	x->props.header_len = sizeof(struct ip_esp_hdr) +
+			      crypto_aead_ivsize(aead);
 	if (x->props.mode == XFRM_MODE_TUNNEL)
 		x->props.header_len += sizeof(struct iphdr);
 	else if (x->props.mode == XFRM_MODE_BEET)
@@ -434,18 +545,14 @@ static int esp_init_state(struct xfrm_st
 			break;
 		}
 	}
-	x->data = esp;
-	align = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
-	if (esp->conf.padlen)
-		align = max_t(u32, align, esp->conf.padlen);
-	x->props.trailer_len = align + 1 + esp->auth.icv_trunc_len;
-	return 0;
+
+	align = ALIGN(crypto_aead_blocksize(aead), 4);
+	if (esp->padlen)
+		align = max_t(u32, align, esp->padlen);
+	x->props.trailer_len = align + 1 + crypto_aead_authsize(esp->aead);
 
 error:
-	x->data = esp;
-	esp_destroy(x);
-	x->data = NULL;
-	return -EINVAL;
+	return err;
 }
 
 static struct xfrm_type esp_type =
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -85,6 +85,7 @@ config INET6_ESP
 	depends on IPV6
 	select XFRM
 	select CRYPTO
+	select CRYPTO_AEAD
 	select CRYPTO_HMAC
 	select CRYPTO_MD5
 	select CRYPTO_CBC
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -24,33 +24,124 @@
  * 	This file is derived from net/ipv4/esp.c
  */
 
+#include <crypto/aead.h>
+#include <crypto/authenc.h>
 #include <linux/err.h>
 #include <linux/module.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
 #include <net/esp.h>
 #include <linux/scatterlist.h>
-#include <linux/crypto.h>
 #include <linux/kernel.h>
 #include <linux/pfkeyv2.h>
 #include <linux/random.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <net/icmp.h>
 #include <net/ipv6.h>
 #include <net/protocol.h>
 #include <linux/icmpv6.h>
 
+struct esp_skb_cb {
+	struct xfrm_skb_cb xfrm;
+	void *tmp;
+};
+
+#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))
+
+/*
+ * Allocate an AEAD request structure with extra space for SG and IV.
+ *
+ * For alignment considerations the IV is placed at the front, followed
+ * by the request and finally the SG list.
+ *
+ * TODO: Use spare space in skb for this where possible.
+ */
+static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags)
+{
+	unsigned int len;
+
+	len = crypto_aead_ivsize(aead);
+	if (len) {
+		len += crypto_aead_alignmask(aead) &
+		       ~(crypto_tfm_ctx_alignment() - 1);
+		len = ALIGN(len, crypto_tfm_ctx_alignment());
+	}
+
+	len += sizeof(struct aead_givcrypt_request) + crypto_aead_reqsize(aead);
+	len = ALIGN(len, __alignof__(struct scatterlist));
+
+	len += sizeof(struct scatterlist) * nfrags;
+
+	return kmalloc(len, GFP_ATOMIC);
+}
+
+static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp)
+{
+	return crypto_aead_ivsize(aead) ? 
+	       PTR_ALIGN((u8 *)tmp, crypto_aead_alignmask(aead) + 1) : tmp;
+}
+
+static inline struct aead_givcrypt_request *esp_tmp_givreq(
+	struct crypto_aead *aead, u8 *iv)
+{
+	struct aead_givcrypt_request *req;
+
+	req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead),
+				crypto_tfm_ctx_alignment());
+	aead_givcrypt_set_tfm(req, aead);
+	return req;
+}
+
+static inline struct aead_request *esp_tmp_req(struct crypto_aead *aead, u8 *iv)
+{
+	struct aead_request *req;
+
+	req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead),
+				crypto_tfm_ctx_alignment());
+	aead_request_set_tfm(req, aead);
+	return req;
+}
+
+static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,
+					     struct aead_request *req)
+{
+	return (void *)ALIGN((unsigned long)(req + 1) +
+			     crypto_aead_reqsize(aead),
+			     __alignof__(struct scatterlist));
+}
+
+static inline struct scatterlist *esp_givreq_sg(
+	struct crypto_aead *aead, struct aead_givcrypt_request *req)
+{
+	return (void *)ALIGN((unsigned long)(req + 1) +
+			     crypto_aead_reqsize(aead),
+			     __alignof__(struct scatterlist));
+}
+
+static void esp_output_done(struct crypto_async_request *base, int err)
+{
+	struct sk_buff *skb = base->data;
+
+	kfree(ESP_SKB_CB(skb)->tmp);
+	xfrm_output_resume(skb, err);
+}
+
 static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err;
 	struct ip_esp_hdr *esph;
-	struct crypto_blkcipher *tfm;
-	struct blkcipher_desc desc;
+	struct crypto_aead *aead;
+	struct aead_givcrypt_request *req;
+	struct scatterlist *sg;
+	struct scatterlist *asg;
 	struct sk_buff *trailer;
+	void *tmp;
 	int blksize;
 	int clen;
 	int alen;
 	int nfrags;
+	u8 *iv;
 	u8 *tail;
 	struct esp_data *esp = x->data;
 
@@ -60,18 +151,26 @@ static int esp6_output(struct xfrm_state
 	/* Round to block size */
 	clen = skb->len;
 
-	alen = esp->auth.icv_trunc_len;
-	tfm = esp->conf.tfm;
-	desc.tfm = tfm;
-	desc.flags = 0;
-	blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
+	aead = esp->aead;
+	alen = crypto_aead_authsize(aead);
+
+	blksize = ALIGN(crypto_aead_blocksize(aead), 4);
 	clen = ALIGN(clen + 2, blksize);
-	if (esp->conf.padlen)
-		clen = ALIGN(clen, esp->conf.padlen);
+	if (esp->padlen)
+		clen = ALIGN(clen, esp->padlen);
 
-	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) {
+	if ((err = skb_cow_data(skb, clen - skb->len + alen, &trailer)) < 0)
 		goto error;
-	}
+	nfrags = err;
+
+	tmp = esp_alloc_tmp(aead, nfrags + 1);
+	if (!tmp)
+		goto error;
+
+	iv = esp_tmp_iv(aead, tmp);
+	req = esp_tmp_givreq(aead, iv);
+	asg = esp_givreq_sg(aead, req);
+	sg = asg + 1;
 
 	/* Fill padding... */
 	tail = skb_tail_pointer(trailer);
@@ -81,86 +180,113 @@ static int esp6_output(struct xfrm_state
 			tail[i] = i + 1;
 	} while (0);
 	tail[clen-skb->len - 2] = (clen - skb->len) - 2;
-	pskb_put(skb, trailer, clen - skb->len);
+	tail[clen - skb->len - 1] = *skb_mac_header(skb);
+	pskb_put(skb, trailer, clen - skb->len + alen);
 
 	skb_push(skb, -skb_network_offset(skb));
 	esph = ip_esp_hdr(skb);
-	*(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
 	*skb_mac_header(skb) = IPPROTO_ESP;
 
 	esph->spi = x->id.spi;
 	esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq);
 
-	spin_lock_bh(&x->lock);
+	sg_init_table(sg, nfrags);
+	skb_to_sgvec(skb, sg,
+		     esph->enc_data + crypto_aead_ivsize(aead) - skb->data,
+		     clen + alen);
+	sg_init_one(asg, esph, sizeof(*esph));
+
+	aead_givcrypt_set_callback(req, 0, esp_output_done, skb);
+	aead_givcrypt_set_crypt(req, sg, sg, clen, iv);
+	aead_givcrypt_set_assoc(req, asg, sizeof(*esph));
+	aead_givcrypt_set_giv(req, esph->enc_data, XFRM_SKB_CB(skb)->seq);
+
+	ESP_SKB_CB(skb)->tmp = tmp;
+	err = crypto_aead_givencrypt(req);
+	if (err == -EINPROGRESS)
+		goto error;
 
-	if (esp->conf.ivlen) {
-		if (unlikely(!esp->conf.ivinitted)) {
-			get_random_bytes(esp->conf.ivec, esp->conf.ivlen);
-			esp->conf.ivinitted = 1;
-		}
-		crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
-	}
+	if (err == -EBUSY)
+		err = NET_XMIT_DROP;
 
-	do {
-		struct scatterlist *sg = &esp->sgbuf[0];
+	kfree(tmp);
 
-		if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
-			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
-			if (!sg)
-				goto unlock;
-		}
-		sg_init_table(sg, nfrags);
-		skb_to_sgvec(skb, sg,
-			     esph->enc_data +
-			     esp->conf.ivlen -
-			     skb->data, clen);
-		err = crypto_blkcipher_encrypt(&desc, sg, sg, clen);
-		if (unlikely(sg != &esp->sgbuf[0]))
-			kfree(sg);
-	} while (0);
+error:
+	return err;
+}
+
+static int esp_input_done2(struct sk_buff *skb, int err)
+{
+	struct xfrm_state *x = xfrm_input_state(skb);
+	struct esp_data *esp = x->data;
+	struct crypto_aead *aead = esp->aead;
+	int alen = crypto_aead_authsize(aead);
+	int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);
+	int elen = skb->len - hlen;
+	int hdr_len = skb_network_header_len(skb);
+	int padlen;
+	u8 nexthdr[2];
+
+	kfree(ESP_SKB_CB(skb)->tmp);
 
 	if (unlikely(err))
-		goto unlock;
+		goto out;
 
-	if (esp->conf.ivlen) {
-		memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen);
-		crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen);
-	}
+	if (skb_copy_bits(skb, skb->len - alen - 2, nexthdr, 2))
+		BUG();
 
-	if (esp->auth.icv_full_len) {
-		err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data,
-				     sizeof(*esph) + esp->conf.ivlen + clen);
-		memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen);
+	err = -EINVAL;
+	padlen = nexthdr[0];
+	if (padlen + 2 + alen >= elen) {
+		LIMIT_NETDEBUG(KERN_WARNING "ipsec esp packet is garbage "
+			       "padlen=%d, elen=%d\n", padlen + 2, elen - alen);
+		goto out;
 	}
 
-unlock:
-	spin_unlock_bh(&x->lock);
+	/* ... check padding bits here. Silly. :-) */
 
-error:
+	pskb_trim(skb, skb->len - alen - padlen - 2);
+	__skb_pull(skb, hlen);
+	skb_set_transport_header(skb, -hdr_len);
+
+	err = nexthdr[1];
+
+	/* RFC4303: Drop dummy packets without any error */
+	if (err == IPPROTO_NONE)
+		err = -EINVAL;
+
+out:
 	return err;
 }
 
+static void esp_input_done(struct crypto_async_request *base, int err)
+{
+	struct sk_buff *skb = base->data;
+
+	xfrm_input_resume(skb, esp_input_done2(skb, err));
+}
+
 static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-	struct ipv6hdr *iph;
 	struct ip_esp_hdr *esph;
 	struct esp_data *esp = x->data;
-	struct crypto_blkcipher *tfm = esp->conf.tfm;
-	struct blkcipher_desc desc = { .tfm = tfm };
+	struct crypto_aead *aead = esp->aead;
+	struct aead_request *req;
 	struct sk_buff *trailer;
-	int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
-	int alen = esp->auth.icv_trunc_len;
-	int elen = skb->len - sizeof(*esph) - esp->conf.ivlen - alen;
-	int hdr_len = skb_network_header_len(skb);
+	int elen = skb->len - sizeof(*esph) - crypto_aead_ivsize(aead);
 	int nfrags;
 	int ret = 0;
+	void *tmp;
+	u8 *iv;
+	struct scatterlist *sg;
+	struct scatterlist *asg;
 
 	if (!pskb_may_pull(skb, sizeof(*esph))) {
 		ret = -EINVAL;
 		goto out;
 	}
 
-	if (elen <= 0 || (elen & (blksize-1))) {
+	if (elen <= 0) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -170,86 +296,38 @@ static int esp6_input(struct xfrm_state 
 		goto out;
 	}
 
-	skb->ip_summed = CHECKSUM_NONE;
+	ret = -ENOMEM;
+	tmp = esp_alloc_tmp(aead, nfrags + 1);
+	if (!tmp)
+		goto out;
 
-	spin_lock(&x->lock);
+	ESP_SKB_CB(skb)->tmp = tmp;
+	iv = esp_tmp_iv(aead, tmp);
+	req = esp_tmp_req(aead, iv);
+	asg = esp_req_sg(aead, req);
+	sg = asg + 1;
 
-	/* If integrity check is required, do this. */
-	if (esp->auth.icv_full_len) {
-		u8 sum[alen];
-
-		ret = esp_mac_digest(esp, skb, 0, skb->len - alen);
-		if (ret)
-			goto unlock;
-
-		if (skb_copy_bits(skb, skb->len - alen, sum, alen))
-			BUG();
-
-		if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) {
-			ret = -EBADMSG;
-			goto unlock;
-		}
-	}
+	skb->ip_summed = CHECKSUM_NONE;
 
 	esph = (struct ip_esp_hdr *)skb->data;
-	iph = ipv6_hdr(skb);
 
 	/* Get ivec. This can be wrong, check against another impls. */
-	if (esp->conf.ivlen)
-		crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen);
-
-	{
-		struct scatterlist *sg = &esp->sgbuf[0];
-
-		if (unlikely(nfrags > ESP_NUM_FAST_SG)) {
-			sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC);
-			if (!sg) {
-				ret = -ENOMEM;
-				goto unlock;
-			}
-		}
-		sg_init_table(sg, nfrags);
-		skb_to_sgvec(skb, sg,
-			     sizeof(*esph) + esp->conf.ivlen,
-			     elen);
-		ret = crypto_blkcipher_decrypt(&desc, sg, sg, elen);
-		if (unlikely(sg != &esp->sgbuf[0]))
-			kfree(sg);
-	}
+	iv = esph->enc_data;
 
-unlock:
-	spin_unlock(&x->lock);
+	sg_init_table(sg, nfrags);
+	skb_to_sgvec(skb, sg, sizeof(*esph) + crypto_aead_ivsize(aead), elen);
+	sg_init_one(asg, esph, sizeof(*esph));
+
+	aead_request_set_callback(req, 0, esp_input_done, skb);
+	aead_request_set_crypt(req, sg, sg, elen, iv);
+	aead_request_set_assoc(req, asg, sizeof(*esph));
 
-	if (unlikely(ret))
+	ret = crypto_aead_decrypt(req);
+	if (ret == -EINPROGRESS)
 		goto out;
 
-	{
-		u8 nexthdr[2];
-		u8 padlen;
-
-		if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2))
-			BUG();
-
-		padlen = nexthdr[0];
-		if (padlen+2 >= elen) {
-			LIMIT_NETDEBUG(KERN_WARNING "ipsec esp packet is garbage padlen=%d, elen=%d\n", padlen+2, elen);
-			ret = -EINVAL;
-			goto out;
-		}
-		/* ... check padding bits here. Silly. :-) */
-
-		/* RFC4303: Drop dummy packets without any error */
-		if (nexthdr[1] == IPPROTO_NONE) {
-			ret = -EINVAL;
-			goto out;
-		}
+	ret = esp_input_done2(skb, ret);
 
-		pskb_trim(skb, skb->len - alen - padlen - 2);
-		ret = nexthdr[1];
-	}
-
-	__skb_pull(skb, sizeof(*esph) + esp->conf.ivlen);
-	skb_set_transport_header(skb, -hdr_len);
 out:
 	return ret;
 }
@@ -257,11 +335,11 @@ out:
 static u32 esp6_get_mtu(struct xfrm_state *x, int mtu)
 {
 	struct esp_data *esp = x->data;
-	u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
-	u32 align = max_t(u32, blksize, esp->conf.padlen);
+	u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4);
+	u32 align = max_t(u32, blksize, esp->padlen);
 	u32 rem;
 
-	mtu -= x->props.header_len + esp->auth.icv_trunc_len;
+	mtu -= x->props.header_len + crypto_aead_authsize(esp->aead);
 	rem = mtu & (align - 1);
 	mtu &= ~(align - 1);
 
@@ -300,81 +378,101 @@ static void esp6_destroy(struct xfrm_sta
 	if (!esp)
 		return;
 
-	crypto_free_blkcipher(esp->conf.tfm);
-	esp->conf.tfm = NULL;
-	kfree(esp->conf.ivec);
-	esp->conf.ivec = NULL;
-	crypto_free_hash(esp->auth.tfm);
-	esp->auth.tfm = NULL;
-	kfree(esp->auth.work_icv);
-	esp->auth.work_icv = NULL;
+	crypto_free_aead(esp->aead);
 	kfree(esp);
 }
 
 static int esp6_init_state(struct xfrm_state *x)
 {
 	struct esp_data *esp = NULL;
-	struct crypto_blkcipher *tfm;
+	struct crypto_aead *aead;
+	struct crypto_authenc_key_param *param;
+	struct rtattr *rta;
+	char *key;
+	char *p;
+	char authenc_name[CRYPTO_MAX_ALG_NAME];
+	u32 align;
+	unsigned int keylen;
+	int err;
 
 	if (x->ealg == NULL)
-		goto error;
+		return -EINVAL;
 
 	if (x->encap)
-		goto error;
+		return -EINVAL;
+
+	if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)",
+		     x->aalg ? x->aalg->alg_name : "digest_null",
+		     x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
+		return -ENAMETOOLONG;
 
 	esp = kzalloc(sizeof(*esp), GFP_KERNEL);
 	if (esp == NULL)
 		return -ENOMEM;
 
+	x->data = esp;
+
+	aead = crypto_alloc_aead(authenc_name, 0, 0);
+	err = PTR_ERR(aead);
+	if (IS_ERR(aead))
+		goto error;
+
+	esp->aead = aead;
+
+	keylen = (x->aalg ? (x->aalg->alg_key_len + 7) / 8 : 0) +
+		 (x->ealg->alg_key_len + 7) / 8 + RTA_SPACE(sizeof(*param));
+	err = -ENOMEM;
+	key = kmalloc(keylen, GFP_KERNEL);
+	if (!key)
+		goto error;
+
+	p = key;
+	rta = (void *)p;
+	rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM;
+	rta->rta_len = RTA_LENGTH(sizeof(*param));
+	param = RTA_DATA(rta);
+	p += RTA_SPACE(sizeof(*param));
+
 	if (x->aalg) {
 		struct xfrm_algo_desc *aalg_desc;
-		struct crypto_hash *hash;
 
-		hash = crypto_alloc_hash(x->aalg->alg_name, 0,
-					 CRYPTO_ALG_ASYNC);
-		if (IS_ERR(hash))
-			goto error;
-
-		esp->auth.tfm = hash;
-		if (crypto_hash_setkey(hash, x->aalg->alg_key,
-				       (x->aalg->alg_key_len + 7) / 8))
-			goto error;
+		memcpy(p, x->aalg->alg_key, (x->aalg->alg_key_len + 7) / 8);
+		p += (x->aalg->alg_key_len + 7) / 8;
 
 		aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
 		BUG_ON(!aalg_desc);
 
+		err = -EINVAL;
 		if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
-		    crypto_hash_digestsize(hash)) {
+		    crypto_aead_authsize(aead)) {
 			NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
 				 x->aalg->alg_name,
-				 crypto_hash_digestsize(hash),
+				 crypto_aead_authsize(aead),
 				 aalg_desc->uinfo.auth.icv_fullbits/8);
-			goto error;
+			goto free_key;
 		}
 
-		esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
-		esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8;
-
-		esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL);
-		if (!esp->auth.work_icv)
-			goto error;
+		err = crypto_aead_setauthsize(
+			aead, aalg_desc->uinfo.auth.icv_truncbits / 8);
+		if (err)
+			goto free_key;
 	}
-	tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(tfm))
-		goto error;
-	esp->conf.tfm = tfm;
-	esp->conf.ivlen = crypto_blkcipher_ivsize(tfm);
-	esp->conf.padlen = 0;
-	if (esp->conf.ivlen) {
-		esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL);
-		if (unlikely(esp->conf.ivec == NULL))
-			goto error;
-		esp->conf.ivinitted = 0;
-	}
-	if (crypto_blkcipher_setkey(tfm, x->ealg->alg_key,
-				    (x->ealg->alg_key_len + 7) / 8))
+
+	esp->padlen = 0;
+
+	param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8);
+	memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8);
+
+	err = crypto_aead_setkey(aead, key, keylen);
+
+free_key:
+	kfree(key);
+
+	if (err)
 		goto error;
-	x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
+
+	x->props.header_len = sizeof(struct ip_esp_hdr) +
+			      crypto_aead_ivsize(aead);
 	switch (x->props.mode) {
 	case XFRM_MODE_BEET:
 	case XFRM_MODE_TRANSPORT:
@@ -385,14 +483,14 @@ static int esp6_init_state(struct xfrm_s
 	default:
 		goto error;
 	}
-	x->data = esp;
-	return 0;
+
+	align = ALIGN(crypto_aead_blocksize(aead), 4);
+	if (esp->padlen)
+		align = max_t(u32, align, esp->padlen);
+	x->props.trailer_len = align + 1 + crypto_aead_authsize(esp->aead);
 
 error:
-	x->data = esp;
-	esp6_destroy(x);
-	x->data = NULL;
-	return -EINVAL;
+	return err;
 }
 
 static struct xfrm_type esp6_type =

^ permalink raw reply

* [0/3] [IPSEC]: Add async/aead support
From: Herbert Xu @ 2008-01-29  3:10 UTC (permalink / raw)
  To: David S. Miller, netdev

Hi Dave:

I've rebased the IPsec AEAD/async patches for the current net-2.6.25
tree.

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* [PATCH] SELinux: Fix double free in selinux_netlbl_sock_setsid()
From: Paul Moore @ 2008-01-29  2:20 UTC (permalink / raw)
  To: linux-kernel; +Cc: netdev, selinux, stable, bunk, jmorris

As pointed out by Adrian Bunk, commit 45c950e0f839fded922ebc0bfd59b1081cc71b70
caused a double-free when security_netlbl_sid_to_secattr() fails.  This patch
fixes this by removing the netlbl_secattr_destroy() call from that function
since we are already releasing the secattr memory in
selinux_netlbl_sock_setsid().

Signed-off-by: Paul Moore <paul.moore@hp.com>
---

 security/selinux/ss/services.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 4bf715d..3a16aba 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2629,7 +2629,6 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 
 netlbl_sid_to_secattr_failure:
 	POLICY_RDUNLOCK;
-	netlbl_secattr_destroy(secattr);
 	return rc;
 }
 #endif /* CONFIG_NETLABEL */

^ permalink raw reply related

* Re: appearing again: kernel: eth0: too many iterations (6) in nv_nic_irq
From: Carlos Carvalho @ 2008-01-29  1:52 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20080128080656.1cc8a4e0@deepthought>

Stephen Hemminger (shemminger@linux-foundation.org) wrote on 28 January 2008 08:06:
 >On Mon, 28 Jan 2008 11:32:55 -0200
 >carlos@fisica.ufpr.br (Carlos Carvalho) wrote:
 >
 >> It seems that this problem with NVidia's nic comes up more and more...
 >> From time to time we get this in the log:
 >> 
 >> Jan 27 14:43:12 duvel kernel: eth0: too many iterations (6) in nv_nic_irq.
 >> 
 >> We algo get
 >> 
 >> Jan 27 11:32:43 duvel kernel: KERNEL: assertion ((int)tcp_packets_in_flight(tp) >= 0) failed at net/ipv4/tcp_input.c (1274)
 >> 
 >> But at different moments, as shown above. Are they related? What's the
 >> meaning of the "assertion failed" one?
 >> 
 >> The messages are more likely to appear when traffic is high
 >> (>500Mb/s). This is with 2.6.22.16.
 >> 
 >> Any suggestions?
 >
 >Use NAPI which is available as configuration option in this driver.

Already in use.

 >Increase the max_interrupt_work from the ridiculously low value of 5
 >to something more larger like 15, with module parameter in
 >/etc/modprobe.d/options:
 >
 >options forcedeth max_interrupt_work=15

Will try.

 >Also, see if you motherboard supports MSI, if so add "msi=1" module parameter

It does, I have this in the config:

CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_MSI=y

How can I set these options with the driver compiled in the kernel and
not as a module? I can change the max_interrupt_work in the source but
what about msi?

Any ideas about the assertion ((int)tcp_packets_in_flight...?

^ permalink raw reply

* Re: Udev coldplugging loads 8139too driver instead of 8139cp
From: Stephen Hemminger @ 2008-01-29  1:08 UTC (permalink / raw)
  To: Michael Tokarev; +Cc: netdev, linux-kernel
In-Reply-To: <479E7750.9060304@msgid.tls.msk.ru>

On Tue, 29 Jan 2008 03:46:08 +0300
Michael Tokarev <mjt@tls.msk.ru> wrote:

> Frederik Himpe wrote:
> > Linux 2.6.24 kernel gives the following messages when udev coldplugging
> > loads the driver for my NIC:
> > 
> > 8139too 0000:00:0b.0: This (id 10ec:8139 rev 20) is an enhanced 8139C+ chip
> > 8139too 0000:00:0b.0: Use the "8139cp" driver for improved performance and stability.
> 
> There are 2 drivers for 8139-based NICs.  For really different two kinds
> of hardware, which both uses the same PCI identifiers.  Both drivers
> "claims" to work with all NICs with those PCI ids, because "externally"
> (by means of udev for example) it's impossible to distinguish the two
> kinds of hardware, it becomes clean only when the driver (either of the
> two) loads and actually checks which hardware we have here.

Is there any chance of using subdevice or subversion to tell them apart?
That worked for other vendors like DLINK who slapped same ID on different
cards.

> Udev in fact loads both - 8139cp and 8139too.  The difference is the ORDER
> in which it loads them - if for "cp-handled" hardware it first loads "too",
> too will complain as above and will NOT claim the device.  The same is
> true for the opposite.
> 
> So - in short - things has always been this way (thanks to realtec).
> I've seen similar (but opposite) effects on my systems, which are all
> should be serviced by 8139too driver but 8139cp loaded first - up
> till i gave up and just disabled 8139cp...
> 
> I don't know what happened in 2.6.24, but my guess is that since 8139too-based
> hw is now alot more common, the two drivers are listed in the opposite
> order.
> 
> In short: NotABug, or ComplainToRealtec (but that's waaaay too late and
> will not help anyway) ;)
> 
> /mjt
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


-- 
Stephen Hemminger <stephen.hemminger@vyatta.com>

^ permalink raw reply

* Re: appearing again: kernel: eth0: too many iterations (6) in nv_nic_irq
From: Andy Gospodarek @ 2008-01-29  1:07 UTC (permalink / raw)
  To: Carlos Carvalho; +Cc: netdev
In-Reply-To: <18333.55687.621653.838538@fisica.ufpr.br>

On Mon, Jan 28, 2008 at 11:32:55AM -0200, Carlos Carvalho wrote:
> It seems that this problem with NVidia's nic comes up more and more...
> From time to time we get this in the log:
> 
> Jan 27 14:43:12 duvel kernel: eth0: too many iterations (6) in nv_nic_irq.
> 
> We algo get
> 
> Jan 27 11:32:43 duvel kernel: KERNEL: assertion ((int)tcp_packets_in_flight(tp) >= 0) failed at net/ipv4/tcp_input.c (1274)
> 
> But at different moments, as shown above. Are they related? What's the
> meaning of the "assertion failed" one?
> 
> The messages are more likely to appear when traffic is high
> (>500Mb/s). This is with 2.6.22.16.
> 
> Any suggestions?


I've noticed that when running the latest forcedeth on an older base
kernel (2.6.18 in my case) that enable_irq and disable_irq don't quite
behave the same way with using MSI as they do with INTx.  2.6.24 works
great on the same hardware so something has changed between at leat
2.6.18 and now to make life better.  I've been meaning to look at those
calls and figure out if we can replace them with simple calls to disable
the hardware IRQs only, but haven't had a chance yet.


^ permalink raw reply

* Re: Udev coldplugging loads 8139too driver instead of 8139cp
From: Michael Tokarev @ 2008-01-29  0:46 UTC (permalink / raw)
  To: Frederik Himpe; +Cc: LKML, netdev
In-Reply-To: <1201554992.13883.13.camel@Anastacia>

Frederik Himpe wrote:
> Linux 2.6.24 kernel gives the following messages when udev coldplugging
> loads the driver for my NIC:
> 
> 8139too 0000:00:0b.0: This (id 10ec:8139 rev 20) is an enhanced 8139C+ chip
> 8139too 0000:00:0b.0: Use the "8139cp" driver for improved performance and stability.

There are 2 drivers for 8139-based NICs.  For really different two kinds
of hardware, which both uses the same PCI identifiers.  Both drivers
"claims" to work with all NICs with those PCI ids, because "externally"
(by means of udev for example) it's impossible to distinguish the two
kinds of hardware, it becomes clean only when the driver (either of the
two) loads and actually checks which hardware we have here.

Udev in fact loads both - 8139cp and 8139too.  The difference is the ORDER
in which it loads them - if for "cp-handled" hardware it first loads "too",
too will complain as above and will NOT claim the device.  The same is
true for the opposite.

So - in short - things has always been this way (thanks to realtec).
I've seen similar (but opposite) effects on my systems, which are all
should be serviced by 8139too driver but 8139cp loaded first - up
till i gave up and just disabled 8139cp...

I don't know what happened in 2.6.24, but my guess is that since 8139too-based
hw is now alot more common, the two drivers are listed in the opposite
order.

In short: NotABug, or ComplainToRealtec (but that's waaaay too late and
will not help anyway) ;)

/mjt


^ permalink raw reply

* Re: [PATCH] PHYLIB: Locking fixes for PHY I/O potentially sleeping
From: Jeff Garzik @ 2008-01-29  0:43 UTC (permalink / raw)
  To: Andy Fleming; +Cc: Nate Case, David S. Miller, netdev
In-Reply-To: <6D762C47-9C9C-422E-A80E-CC418F624B05@freescale.com>

Andy Fleming wrote:
> Jeff, Dave, any chance we can get this one in for 2.6.25?  It will allow 
> a number of other drivers to start using PHY Lib.
> I'm sure Nate can resend if needed.
> 
> On Jan 3, 2008, at 17:36, Nate Case wrote:
> 
>> PHY read/write functions can potentially sleep (e.g., a PHY accessed
>> via I2C).  The following changes were made to account for this:
>>
>>     * Change spin locks to mutex locks
>>     * Add a BUG_ON() to phy_read() phy_write() to warn against
>>       calling them from an interrupt context.
>>     * Use work queue for PHY state machine handling since
>>       it can potentially sleep
>>     * Change phydev lock from spinlock to mutex
>>
>> Signed-off-by: Nate Case <ncase@xes-inc.com>

don't see it in my queue, so please resend.



^ permalink raw reply

* Re: [PATCH] bonding: fix race that causes invalid statistics
From: Andy Gospodarek @ 2008-01-29  0:38 UTC (permalink / raw)
  To: Jay Vosburgh; +Cc: netdev, csnook
In-Reply-To: <23624.1201564743@death>

On Mon, Jan 28, 2008 at 03:59:03PM -0800, Jay Osbourn wrote:
> Andy Gospodarek <andy@greyhouse.net> wrote:
> 
> >+	memcpy(stats,&local_stats,sizeof(net_device_stats));
> 
> 	FYI, this generates a compiler error (missing the word "struct"
> in here).  Other than not compiling, the patch seems reasonable.  I'll
> fix it up and include it in the series I'll post tomorrow or so.
> 
> 	-J
> 

Crap.  Here's the one I intended to send.

Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Chris Snook <csnook@redhat.com>

---

 bond_main.c |   57 ++++++++++++++++++++++++++++++---------------------------
 1 files changed, 30 insertions(+), 27 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 49a1982..901de6d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3769,41 +3769,44 @@ static struct net_device_stats *bond_get_stats(struct net_device *bond_dev)
 {
 	struct bonding *bond = bond_dev->priv;
 	struct net_device_stats *stats = &(bond->stats), *sstats;
+	struct net_device_stats local_stats;
 	struct slave *slave;
 	int i;
 
-	memset(stats, 0, sizeof(struct net_device_stats));
+	memset(&local_stats, 0, sizeof(struct net_device_stats));
 
 	read_lock_bh(&bond->lock);
 
 	bond_for_each_slave(bond, slave, i) {
 		sstats = slave->dev->get_stats(slave->dev);
-		stats->rx_packets += sstats->rx_packets;
-		stats->rx_bytes += sstats->rx_bytes;
-		stats->rx_errors += sstats->rx_errors;
-		stats->rx_dropped += sstats->rx_dropped;
-
-		stats->tx_packets += sstats->tx_packets;
-		stats->tx_bytes += sstats->tx_bytes;
-		stats->tx_errors += sstats->tx_errors;
-		stats->tx_dropped += sstats->tx_dropped;
-
-		stats->multicast += sstats->multicast;
-		stats->collisions += sstats->collisions;
-
-		stats->rx_length_errors += sstats->rx_length_errors;
-		stats->rx_over_errors += sstats->rx_over_errors;
-		stats->rx_crc_errors += sstats->rx_crc_errors;
-		stats->rx_frame_errors += sstats->rx_frame_errors;
-		stats->rx_fifo_errors += sstats->rx_fifo_errors;
-		stats->rx_missed_errors += sstats->rx_missed_errors;
-
-		stats->tx_aborted_errors += sstats->tx_aborted_errors;
-		stats->tx_carrier_errors += sstats->tx_carrier_errors;
-		stats->tx_fifo_errors += sstats->tx_fifo_errors;
-		stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
-		stats->tx_window_errors += sstats->tx_window_errors;
-	}
+		local_stats.rx_packets += sstats->rx_packets;
+		local_stats.rx_bytes += sstats->rx_bytes;
+		local_stats.rx_errors += sstats->rx_errors;
+		local_stats.rx_dropped += sstats->rx_dropped;
+
+		local_stats.tx_packets += sstats->tx_packets;
+		local_stats.tx_bytes += sstats->tx_bytes;
+		local_stats.tx_errors += sstats->tx_errors;
+		local_stats.tx_dropped += sstats->tx_dropped;
+
+		local_stats.multicast += sstats->multicast;
+		local_stats.collisions += sstats->collisions;
+
+		local_stats.rx_length_errors += sstats->rx_length_errors;
+		local_stats.rx_over_errors += sstats->rx_over_errors;
+		local_stats.rx_crc_errors += sstats->rx_crc_errors;
+		local_stats.rx_frame_errors += sstats->rx_frame_errors;
+		local_stats.rx_fifo_errors += sstats->rx_fifo_errors;
+		local_stats.rx_missed_errors += sstats->rx_missed_errors;
+
+		local_stats.tx_aborted_errors += sstats->tx_aborted_errors;
+		local_stats.tx_carrier_errors += sstats->tx_carrier_errors;
+		local_stats.tx_fifo_errors += sstats->tx_fifo_errors;
+		local_stats.tx_heartbeat_errors += sstats->tx_heartbeat_errors;
+		local_stats.tx_window_errors += sstats->tx_window_errors;
+	}
+
+	memcpy(stats,&local_stats,sizeof(struct net_device_stats));
 
 	read_unlock_bh(&bond->lock);
 

^ permalink raw reply related

* Re: [PATCH] PHYLIB: Locking fixes for PHY I/O potentially sleeping
From: David Miller @ 2008-01-29  0:32 UTC (permalink / raw)
  To: afleming; +Cc: ncase, jeff, netdev
In-Reply-To: <6D762C47-9C9C-422E-A80E-CC418F624B05@freescale.com>

From: Andy Fleming <afleming@freescale.com>
Date: Mon, 28 Jan 2008 18:29:39 -0600

> Jeff, Dave, any chance we can get this one in for 2.6.25?  It will  
> allow a number of other drivers to start using PHY Lib.
> I'm sure Nate can resend if needed.

This shouldn't be a problem.

I just did my initial merge with Linus, so after he pulls
that in Jeff can merge stuff like this to me so that it
can go into my second pass.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox