* Re: [PATCH 0/2] phylib: Cleanup marvell.c and add 88E1149R support.
From: David Miller @ 2010-11-22 16:34 UTC (permalink / raw)
To: ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, cyril-l0cyMroinI0,
arnaud.patard-dQbF7i+pzddAfugRpC6u6w
In-Reply-To: <1290203933-28251-1-git-send-email-ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
From: David Daney <ddaney-M3mlKVOIwJVv6pq1l3V1OdBPR1lH4CV8@public.gmane.org>
Date: Fri, 19 Nov 2010 13:58:51 -0800
> This is the second iteration of this patch. I have split out the
> device tree support from the first version to a different patch set.
> The 88E1149R support is useful 'stand alone', so if it is acceptable,
> it can be merged first.
>
> The first patch is a small cleanup suggested by Cyril Chemparathy, the
> second one adds basic 88E1149R support.
All applied to net-2.6, thanks.
^ permalink raw reply
* Re: [PATCH] qlge: Fix incorrect usage of module parameters and netdev msg level
From: David Miller @ 2010-11-22 16:29 UTC (permalink / raw)
To: sonnyrao; +Cc: netdev, miltonm, ron.mercer, linux-driver, linux-kernel
In-Reply-To: <1290075903-3038-1-git-send-email-sonnyrao@linux.vnet.ibm.com>
From: Sonny Rao <sonnyrao@linux.vnet.ibm.com>
Date: Thu, 18 Nov 2010 04:25:03 -0600
> Driver appears to be mistaking the permission field with default value
> in the case of debug and qlge_irq_type.
>
> Driver is also passing debug as a bitmask into netif_msg_init()
> which really wants a number of bits, so fix that.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> Signed-off-by: Sonny Rao <sonnyrao@linux.vnet.ibm.com>
Applied, thanks Sonny.
^ permalink raw reply
* Re: [PATCH] macvlan: Introduce 'passthru' mode to takeover the underlying device
From: David Miller @ 2010-11-22 16:24 UTC (permalink / raw)
To: sri; +Cc: arnd, kaber, shemminger, mst, netdev, kvm
In-Reply-To: <1288307450.30131.82.camel@sridhar.beaverton.ibm.com>
From: Sridhar Samudrala <sri@us.ibm.com>
Date: Thu, 28 Oct 2010 16:10:50 -0700
> With the current default 'vepa' mode, a KVM guest using virtio with
> macvtap backend has the following limitations.
> - cannot change/add a mac address on the guest virtio-net
> - cannot create a vlan device on the guest virtio-net
> - cannot enable promiscuous mode on guest virtio-net
>
> To address these limitations, this patch introduces a new mode called
> 'passthru' when creating a macvlan device which allows takeover of the
> underlying device and passing it to a guest using virtio with macvtap
> backend.
>
> Only one macvlan device is allowed in passthru mode and it inherits
> the mac address from the underlying device and sets it in promiscuous
> mode to receive and forward all the packets.
>
> Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Applied, thanks Sridhar.
^ permalink raw reply
* Re: linux-next: Tree for November 18 (netfilter)
From: Randy Dunlap @ 2010-11-22 16:19 UTC (permalink / raw)
To: KOVACS Krisztian
Cc: Patrick McHardy, Stephen Rothwell, netfilter-devel, linux-next,
LKML, netdev, Balazs Scheidler
In-Reply-To: <1290428929.726241.1.camel@nienna.balabit>
On 11/22/10 04:28, KOVACS Krisztian wrote:
> Hi,
>
> On Mon, 2010-11-22 at 13:14 +0100, KOVACS Krisztian wrote:
>> Indeed, we were missing quite a few of those ifdefs... The patch below
>> seems to fix the issue for me.
>>
>> commit ec0ac6f3e7749e25f481c1e0f75766974820fe84
>> Author: KOVACS Krisztian <hidden@balabit.hu>
>> Date: Mon Nov 22 13:07:15 2010 +0100
>
> Bah, it seems the patch got line-wrapped by my MUA, here it is again.
> Let's hope I got it right this time...
>
> commit ec0ac6f3e7749e25f481c1e0f75766974820fe84
> Author: KOVACS Krisztian <hidden@balabit.hu>
> Date: Mon Nov 22 13:07:15 2010 +0100
>
> netfilter: fix compilation when conntrack is disabled but tproxy is enabled
>
> The IPv6 tproxy patches split IPv6 defragmentation off of conntrack, but
> failed to update the #ifdef stanzas guarding the defragmentation related
> fields and code in skbuff and conntrack related code in nf_defrag_ipv6.c.
>
> This patch adds the required #ifdefs so that IPv6 tproxy can truly be used
> without connection tracking.
>
> Original report:
> http://marc.info/?l=linux-netdev&m=129010118516341&w=2
>
> Reported-by: Randy Dunlap <randy.dunlap@oracle.com>
> Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
That builds. Thanks.
Acked-by: Randy Dunlap <randy.dunlap@oracle.com>
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index e6ba898..4f2db79 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -255,6 +255,11 @@ typedef unsigned int sk_buff_data_t;
> typedef unsigned char *sk_buff_data_t;
> #endif
>
> +#if defined(CONFIG_NF_DEFRAG_IPV4) || defined(CONFIG_NF_DEFRAG_IPV4_MODULE) || \
> + defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
> +#define NET_SKBUFF_NF_DEFRAG_NEEDED 1
> +#endif
> +
> /**
> * struct sk_buff - socket buffer
> * @next: Next buffer in list
> @@ -362,6 +367,8 @@ struct sk_buff {
> void (*destructor)(struct sk_buff *skb);
> #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> struct nf_conntrack *nfct;
> +#endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> struct sk_buff *nfct_reasm;
> #endif
> #ifdef CONFIG_BRIDGE_NETFILTER
> @@ -2051,6 +2058,8 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
> if (nfct)
> atomic_inc(&nfct->use);
> }
> +#endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> static inline void nf_conntrack_get_reasm(struct sk_buff *skb)
> {
> if (skb)
> @@ -2079,6 +2088,8 @@ static inline void nf_reset(struct sk_buff *skb)
> #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> nf_conntrack_put(skb->nfct);
> skb->nfct = NULL;
> +#endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> nf_conntrack_put_reasm(skb->nfct_reasm);
> skb->nfct_reasm = NULL;
> #endif
> @@ -2095,6 +2106,8 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
> dst->nfct = src->nfct;
> nf_conntrack_get(src->nfct);
> dst->nfctinfo = src->nfctinfo;
> +#endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> dst->nfct_reasm = src->nfct_reasm;
> nf_conntrack_get_reasm(src->nfct_reasm);
> #endif
> @@ -2108,6 +2121,8 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
> {
> #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> nf_conntrack_put(dst->nfct);
> +#endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> nf_conntrack_put_reasm(dst->nfct_reasm);
> #endif
> #ifdef CONFIG_BRIDGE_NETFILTER
> diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
> index 1ee717e..a4c9936 100644
> --- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
> +++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
> @@ -7,16 +7,6 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
> extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
> extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
>
> -extern int nf_ct_frag6_init(void);
> -extern void nf_ct_frag6_cleanup(void);
> -extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
> -extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
> - struct net_device *in,
> - struct net_device *out,
> - int (*okfn)(struct sk_buff *));
> -
> -struct inet_frags_ctl;
> -
> #include <linux/sysctl.h>
> extern struct ctl_table nf_ct_ipv6_sysctl_table[];
>
> diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
> index 94dd54d..fd79c9a 100644
> --- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h
> +++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
> @@ -3,4 +3,14 @@
>
> extern void nf_defrag_ipv6_enable(void);
>
> +extern int nf_ct_frag6_init(void);
> +extern void nf_ct_frag6_cleanup(void);
> +extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
> +extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
> + struct net_device *in,
> + struct net_device *out,
> + int (*okfn)(struct sk_buff *));
> +
> +struct inet_frags_ctl;
> +
> #endif /* _NF_DEFRAG_IPV6_H */
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 104f844..74ebf4b 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -380,6 +380,8 @@ static void skb_release_head_state(struct sk_buff *skb)
> }
> #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> nf_conntrack_put(skb->nfct);
> +#endif
> +#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
> nf_conntrack_put_reasm(skb->nfct_reasm);
> #endif
> #ifdef CONFIG_BRIDGE_NETFILTER
> diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
> index 99abfb5..97c5b21 100644
> --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
> +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
> @@ -19,13 +19,15 @@
>
> #include <linux/netfilter_ipv6.h>
> #include <linux/netfilter_bridge.h>
> +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> #include <net/netfilter/nf_conntrack.h>
> #include <net/netfilter/nf_conntrack_helper.h>
> #include <net/netfilter/nf_conntrack_l4proto.h>
> #include <net/netfilter/nf_conntrack_l3proto.h>
> #include <net/netfilter/nf_conntrack_core.h>
> -#include <net/netfilter/nf_conntrack_zones.h>
> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
> +#endif
> +#include <net/netfilter/nf_conntrack_zones.h>
> #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
>
> static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
> @@ -33,8 +35,10 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
> {
> u16 zone = NF_CT_DEFAULT_ZONE;
>
> +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> if (skb->nfct)
> zone = nf_ct_zone((struct nf_conn *)skb->nfct);
> +#endif
>
> #ifdef CONFIG_BRIDGE_NETFILTER
> if (skb->nf_bridge &&
> @@ -56,9 +60,11 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
> {
> struct sk_buff *reasm;
>
> +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
> /* Previously seen (loopback)? */
> if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
> return NF_ACCEPT;
> +#endif
>
> reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
> /* queued */
>
>
--
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
^ permalink raw reply
* Re: [PATCH 00/00] Remove deprecated items from Makefiles
From: David Miller @ 2010-11-22 16:17 UTC (permalink / raw)
To: tdent48227
Cc: marcel, padovan, linux-bluetooth, netdev, sjur.brandeland,
socketcan, urs.thuermann, socketcan-core, sage, ceph-devel,
wang840925, jlayton, kaber, pekkas, linux-kernel, netfilter-devel,
netfilter, samuel
In-Reply-To: <1290387808-2239-1-git-send-email-tdent48227@gmail.com>
From: Tracey Dent <tdent48227@gmail.com>
Date: Sun, 21 Nov 2010 20:03:11 -0500
> I changed Makefiles to use <modules>-y instead of <modules>-objs because -objs
> is deprecated and not even mentioned in Documentation/kbuild/makefiles.txt.
>
> Also, remove some if-conditional statments because I used the ccflags-$ flag
> instead of EXTRA_CFLAGS because EXTRA_CFLAGS.
All applied, thanks Tracey.
^ permalink raw reply
* Re: [PATCH 56/62] iwlwifi: Use static const
From: Guy, Wey-Yi @ 2010-11-22 15:37 UTC (permalink / raw)
To: Joe Perches
Cc: Stefano Brivio, Chatre, Reinette, Intel Linux Wireless,
John W. Linville,
linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <2773a20a26f4e326f0849e8ae8fb4f347d6a6ecb.1290305776.git.joe-6d6DIl74uiNBDgjK7y7TUQ@public.gmane.org>
Hi Joe,
On Sat, 2010-11-20 at 18:38 -0800, Joe Perches wrote:
> Using static const generally increases object text and decreases data size.
> It also generally decreases overall object size.
>
> text data bss dec hex filename
> 48644 57 12120 60821 ed95 drivers/net/wireless/b43/phy_n.o.new
> 48661 57 12120 60838 eda6 drivers/net/wireless/b43/phy_n.o.old
> 37906 86 7904 45896 b348 drivers/net/wireless/iwlwifi/iwl-agn-lib.o.new
> 37937 86 7904 45927 b367 drivers/net/wireless/iwlwifi/iwl-agn-lib.o.old
> 37781 523 6752 45056 b000 drivers/net/wireless/iwlwifi/iwl-3945.o.new
> 37781 523 6752 45056 b000 drivers/net/wireless/iwlwifi/iwl-3945.o.old
>
> Changed b43_nphy_write_clip_detection to take a const u16 *
>
> Signed-off-by: Joe Perches <joe-6d6DIl74uiNBDgjK7y7TUQ@public.gmane.org>
> ---
I don't see size difference on 3945, otherwise the patch looks ok to me
Wey
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: iwl3945: regression - unregister_netdevice: waiting for wlan0 to become free. Usage count = 1
From: David Miller @ 2010-11-22 15:36 UTC (permalink / raw)
To: eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w
Cc: mhocko-AlSwsSmVLrQ, linux-wireless-u79uwXL29TY76Z2rM5mHXA,
reinette.chatre-ral2JQCrhuEAvxtiuMwx3w,
wey-yi.w.guy-ral2JQCrhuEAvxtiuMwx3w, ilw-VuQAYsv1563Yd54FQh9/CA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1290424776.2811.32.camel@edumazet-laptop>
From: Eric Dumazet <eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Date: Mon, 22 Nov 2010 12:19:36 +0100
> Oh well, it seems David put the fix in net-next-2.6 instead of net-2.6
>
> Please try :
>
> http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=commitdiff;h=9d82ca98f71fd686ef2f3017c5e3e6a4871b6e46
My bad, I'll toss this into net-2.6
Thanks for catching this Eric.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCN net-next-2.6] drivers/net: use vzalloc()
From: Jon Mason @ 2010-11-22 14:42 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1290420906.2811.14.camel@edumazet-laptop>
On Mon, Nov 22, 2010 at 02:15:06AM -0800, Eric Dumazet wrote:
> Use vzalloc() and vzalloc_node() in net drivers
>
Acking the vxge portions.
Acked-by: Jon Mason <jon.mason@exar.com>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> ---
> People, I hope you dont mind if I make a single patch, and dont Cc all
> maintainers, for such trivial change.
>
> drivers/net/bnx2.c | 9 +------
> drivers/net/cxgb3/cxgb3_offload.c | 6 +---
> drivers/net/cxgb4/cxgb4_main.c | 6 +---
> drivers/net/e1000/e1000_main.c | 6 +---
> drivers/net/e1000e/netdev.c | 6 +---
> drivers/net/ehea/ehea_main.c | 4 ---
> drivers/net/igb/igb_main.c | 6 +---
> drivers/net/igbvf/netdev.c | 6 +---
> drivers/net/ixgb/ixgb_main.c | 6 +---
> drivers/net/ixgbe/ixgbe_main.c | 10 +++-----
> drivers/net/ixgbevf/ixgbevf_main.c | 6 +---
> drivers/net/netxen/netxen_nic_init.c | 6 +---
> drivers/net/pch_gbe/pch_gbe_main.c | 6 +---
> drivers/net/pptp.c | 3 --
> drivers/net/qlcnic/qlcnic_init.c | 6 +---
> drivers/net/sfc/filter.c | 3 --
> drivers/net/vxge/vxge-config.c | 31 ++++++-------------------
> 17 files changed, 39 insertions(+), 87 deletions(-)
>
> diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
> index 062600b..0de196d 100644
> --- a/drivers/net/bnx2.c
> +++ b/drivers/net/bnx2.c
> @@ -766,13 +766,10 @@ bnx2_alloc_rx_mem(struct bnx2 *bp)
> int j;
>
> rxr->rx_buf_ring =
> - vmalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
> + vzalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
> if (rxr->rx_buf_ring == NULL)
> return -ENOMEM;
>
> - memset(rxr->rx_buf_ring, 0,
> - SW_RXBD_RING_SIZE * bp->rx_max_ring);
> -
> for (j = 0; j < bp->rx_max_ring; j++) {
> rxr->rx_desc_ring[j] =
> dma_alloc_coherent(&bp->pdev->dev,
> @@ -785,13 +782,11 @@ bnx2_alloc_rx_mem(struct bnx2 *bp)
> }
>
> if (bp->rx_pg_ring_size) {
> - rxr->rx_pg_ring = vmalloc(SW_RXPG_RING_SIZE *
> + rxr->rx_pg_ring = vzalloc(SW_RXPG_RING_SIZE *
> bp->rx_max_pg_ring);
> if (rxr->rx_pg_ring == NULL)
> return -ENOMEM;
>
> - memset(rxr->rx_pg_ring, 0, SW_RXPG_RING_SIZE *
> - bp->rx_max_pg_ring);
> }
>
> for (j = 0; j < bp->rx_max_pg_ring; j++) {
> diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
> index bcf0753..ef02aa6 100644
> --- a/drivers/net/cxgb3/cxgb3_offload.c
> +++ b/drivers/net/cxgb3/cxgb3_offload.c
> @@ -1164,12 +1164,10 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
> */
> void *cxgb_alloc_mem(unsigned long size)
> {
> - void *p = kmalloc(size, GFP_KERNEL);
> + void *p = kzalloc(size, GFP_KERNEL);
>
> if (!p)
> - p = vmalloc(size);
> - if (p)
> - memset(p, 0, size);
> + p = vzalloc(size);
> return p;
> }
>
> diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
> index f50bc98..848f89d 100644
> --- a/drivers/net/cxgb4/cxgb4_main.c
> +++ b/drivers/net/cxgb4/cxgb4_main.c
> @@ -868,12 +868,10 @@ out: release_firmware(fw);
> */
> void *t4_alloc_mem(size_t size)
> {
> - void *p = kmalloc(size, GFP_KERNEL);
> + void *p = kzalloc(size, GFP_KERNEL);
>
> if (!p)
> - p = vmalloc(size);
> - if (p)
> - memset(p, 0, size);
> + p = vzalloc(size);
> return p;
> }
>
> diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
> index 4686c39..dcb7f82 100644
> --- a/drivers/net/e1000/e1000_main.c
> +++ b/drivers/net/e1000/e1000_main.c
> @@ -1425,13 +1425,12 @@ static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
> int size;
>
> size = sizeof(struct e1000_buffer) * txdr->count;
> - txdr->buffer_info = vmalloc(size);
> + txdr->buffer_info = vzalloc(size);
> if (!txdr->buffer_info) {
> e_err(probe, "Unable to allocate memory for the Tx descriptor "
> "ring\n");
> return -ENOMEM;
> }
> - memset(txdr->buffer_info, 0, size);
>
> /* round up to nearest 4K */
>
> @@ -1621,13 +1620,12 @@ static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
> int size, desc_len;
>
> size = sizeof(struct e1000_buffer) * rxdr->count;
> - rxdr->buffer_info = vmalloc(size);
> + rxdr->buffer_info = vzalloc(size);
> if (!rxdr->buffer_info) {
> e_err(probe, "Unable to allocate memory for the Rx descriptor "
> "ring\n");
> return -ENOMEM;
> }
> - memset(rxdr->buffer_info, 0, size);
>
> desc_len = sizeof(struct e1000_rx_desc);
>
> diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
> index 9b3f0a9..0adcb79 100644
> --- a/drivers/net/e1000e/netdev.c
> +++ b/drivers/net/e1000e/netdev.c
> @@ -2059,10 +2059,9 @@ int e1000e_setup_tx_resources(struct e1000_adapter *adapter)
> int err = -ENOMEM, size;
>
> size = sizeof(struct e1000_buffer) * tx_ring->count;
> - tx_ring->buffer_info = vmalloc(size);
> + tx_ring->buffer_info = vzalloc(size);
> if (!tx_ring->buffer_info)
> goto err;
> - memset(tx_ring->buffer_info, 0, size);
>
> /* round up to nearest 4K */
> tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc);
> @@ -2095,10 +2094,9 @@ int e1000e_setup_rx_resources(struct e1000_adapter *adapter)
> int i, size, desc_len, err = -ENOMEM;
>
> size = sizeof(struct e1000_buffer) * rx_ring->count;
> - rx_ring->buffer_info = vmalloc(size);
> + rx_ring->buffer_info = vzalloc(size);
> if (!rx_ring->buffer_info)
> goto err;
> - memset(rx_ring->buffer_info, 0, size);
>
> for (i = 0; i < rx_ring->count; i++) {
> buffer_info = &rx_ring->buffer_info[i];
> diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
> index 182b2a7..a84c389 100644
> --- a/drivers/net/ehea/ehea_main.c
> +++ b/drivers/net/ehea/ehea_main.c
> @@ -1496,12 +1496,10 @@ static int ehea_init_q_skba(struct ehea_q_skb_arr *q_skba, int max_q_entries)
> {
> int arr_size = sizeof(void *) * max_q_entries;
>
> - q_skba->arr = vmalloc(arr_size);
> + q_skba->arr = vzalloc(arr_size);
> if (!q_skba->arr)
> return -ENOMEM;
>
> - memset(q_skba->arr, 0, arr_size);
> -
> q_skba->len = max_q_entries;
> q_skba->index = 0;
> q_skba->os_skbs = 0;
> diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
> index 892d196..67ea262 100644
> --- a/drivers/net/igb/igb_main.c
> +++ b/drivers/net/igb/igb_main.c
> @@ -2436,10 +2436,9 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring)
> int size;
>
> size = sizeof(struct igb_buffer) * tx_ring->count;
> - tx_ring->buffer_info = vmalloc(size);
> + tx_ring->buffer_info = vzalloc(size);
> if (!tx_ring->buffer_info)
> goto err;
> - memset(tx_ring->buffer_info, 0, size);
>
> /* round up to nearest 4K */
> tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
> @@ -2587,10 +2586,9 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
> int size, desc_len;
>
> size = sizeof(struct igb_buffer) * rx_ring->count;
> - rx_ring->buffer_info = vmalloc(size);
> + rx_ring->buffer_info = vzalloc(size);
> if (!rx_ring->buffer_info)
> goto err;
> - memset(rx_ring->buffer_info, 0, size);
>
> desc_len = sizeof(union e1000_adv_rx_desc);
>
> diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
> index 4c998b7..8dbde23 100644
> --- a/drivers/net/igbvf/netdev.c
> +++ b/drivers/net/igbvf/netdev.c
> @@ -430,10 +430,9 @@ int igbvf_setup_tx_resources(struct igbvf_adapter *adapter,
> int size;
>
> size = sizeof(struct igbvf_buffer) * tx_ring->count;
> - tx_ring->buffer_info = vmalloc(size);
> + tx_ring->buffer_info = vzalloc(size);
> if (!tx_ring->buffer_info)
> goto err;
> - memset(tx_ring->buffer_info, 0, size);
>
> /* round up to nearest 4K */
> tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
> @@ -470,10 +469,9 @@ int igbvf_setup_rx_resources(struct igbvf_adapter *adapter,
> int size, desc_len;
>
> size = sizeof(struct igbvf_buffer) * rx_ring->count;
> - rx_ring->buffer_info = vmalloc(size);
> + rx_ring->buffer_info = vzalloc(size);
> if (!rx_ring->buffer_info)
> goto err;
> - memset(rx_ring->buffer_info, 0, size);
>
> desc_len = sizeof(union e1000_adv_rx_desc);
>
> diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
> index caa8192..211a169 100644
> --- a/drivers/net/ixgb/ixgb_main.c
> +++ b/drivers/net/ixgb/ixgb_main.c
> @@ -669,13 +669,12 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
> int size;
>
> size = sizeof(struct ixgb_buffer) * txdr->count;
> - txdr->buffer_info = vmalloc(size);
> + txdr->buffer_info = vzalloc(size);
> if (!txdr->buffer_info) {
> netif_err(adapter, probe, adapter->netdev,
> "Unable to allocate transmit descriptor ring memory\n");
> return -ENOMEM;
> }
> - memset(txdr->buffer_info, 0, size);
>
> /* round up to nearest 4K */
>
> @@ -759,13 +758,12 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
> int size;
>
> size = sizeof(struct ixgb_buffer) * rxdr->count;
> - rxdr->buffer_info = vmalloc(size);
> + rxdr->buffer_info = vzalloc(size);
> if (!rxdr->buffer_info) {
> netif_err(adapter, probe, adapter->netdev,
> "Unable to allocate receive descriptor ring\n");
> return -ENOMEM;
> }
> - memset(rxdr->buffer_info, 0, size);
>
> /* Round up to nearest 4K */
>
> diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
> index 5409af3..4249b51 100644
> --- a/drivers/net/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ixgbe/ixgbe_main.c
> @@ -5181,12 +5181,11 @@ int ixgbe_setup_tx_resources(struct ixgbe_ring *tx_ring)
> int size;
>
> size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count;
> - tx_ring->tx_buffer_info = vmalloc_node(size, tx_ring->numa_node);
> + tx_ring->tx_buffer_info = vzalloc_node(size, tx_ring->numa_node);
> if (!tx_ring->tx_buffer_info)
> - tx_ring->tx_buffer_info = vmalloc(size);
> + tx_ring->tx_buffer_info = vzalloc(size);
> if (!tx_ring->tx_buffer_info)
> goto err;
> - memset(tx_ring->tx_buffer_info, 0, size);
>
> /* round up to nearest 4K */
> tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc);
> @@ -5246,12 +5245,11 @@ int ixgbe_setup_rx_resources(struct ixgbe_ring *rx_ring)
> int size;
>
> size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count;
> - rx_ring->rx_buffer_info = vmalloc_node(size, rx_ring->numa_node);
> + rx_ring->rx_buffer_info = vzalloc_node(size, rx_ring->numa_node);
> if (!rx_ring->rx_buffer_info)
> - rx_ring->rx_buffer_info = vmalloc(size);
> + rx_ring->rx_buffer_info = vzalloc(size);
> if (!rx_ring->rx_buffer_info)
> goto err;
> - memset(rx_ring->rx_buffer_info, 0, size);
>
> /* Round up to nearest 4K */
> rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
> diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
> index 5b8063c..2216a3c 100644
> --- a/drivers/net/ixgbevf/ixgbevf_main.c
> +++ b/drivers/net/ixgbevf/ixgbevf_main.c
> @@ -2489,10 +2489,9 @@ int ixgbevf_setup_tx_resources(struct ixgbevf_adapter *adapter,
> int size;
>
> size = sizeof(struct ixgbevf_tx_buffer) * tx_ring->count;
> - tx_ring->tx_buffer_info = vmalloc(size);
> + tx_ring->tx_buffer_info = vzalloc(size);
> if (!tx_ring->tx_buffer_info)
> goto err;
> - memset(tx_ring->tx_buffer_info, 0, size);
>
> /* round up to nearest 4K */
> tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc);
> @@ -2556,14 +2555,13 @@ int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter,
> int size;
>
> size = sizeof(struct ixgbevf_rx_buffer) * rx_ring->count;
> - rx_ring->rx_buffer_info = vmalloc(size);
> + rx_ring->rx_buffer_info = vzalloc(size);
> if (!rx_ring->rx_buffer_info) {
> hw_dbg(&adapter->hw,
> "Unable to vmalloc buffer memory for "
> "the receive descriptor ring\n");
> goto alloc_failed;
> }
> - memset(rx_ring->rx_buffer_info, 0, size);
>
> /* Round up to nearest 4K */
> rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc);
> diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
> index 95fe552..f946de2 100644
> --- a/drivers/net/netxen/netxen_nic_init.c
> +++ b/drivers/net/netxen/netxen_nic_init.c
> @@ -214,13 +214,12 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
> tx_ring->num_desc = adapter->num_txd;
> tx_ring->txq = netdev_get_tx_queue(netdev, 0);
>
> - cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring));
> + cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring));
> if (cmd_buf_arr == NULL) {
> dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n",
> netdev->name);
> goto err_out;
> }
> - memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
> tx_ring->cmd_buf_arr = cmd_buf_arr;
>
> recv_ctx = &adapter->recv_ctx;
> @@ -280,7 +279,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
>
> }
> rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
> - vmalloc(RCV_BUFF_RINGSIZE(rds_ring));
> + vzalloc(RCV_BUFF_RINGSIZE(rds_ring));
> if (rds_ring->rx_buf_arr == NULL) {
> printk(KERN_ERR "%s: Failed to allocate "
> "rx buffer ring %d\n",
> @@ -288,7 +287,6 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
> /* free whatever was already allocated */
> goto err_out;
> }
> - memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring));
> INIT_LIST_HEAD(&rds_ring->free_list);
> /*
> * Now go through all of them, set reference handles
> diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c
> index 472056b..afb7506 100644
> --- a/drivers/net/pch_gbe/pch_gbe_main.c
> +++ b/drivers/net/pch_gbe/pch_gbe_main.c
> @@ -1523,12 +1523,11 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
> int desNo;
>
> size = (int)sizeof(struct pch_gbe_buffer) * tx_ring->count;
> - tx_ring->buffer_info = vmalloc(size);
> + tx_ring->buffer_info = vzalloc(size);
> if (!tx_ring->buffer_info) {
> pr_err("Unable to allocate memory for the buffer infomation\n");
> return -ENOMEM;
> }
> - memset(tx_ring->buffer_info, 0, size);
>
> tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc);
>
> @@ -1573,12 +1572,11 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
> int desNo;
>
> size = (int)sizeof(struct pch_gbe_buffer) * rx_ring->count;
> - rx_ring->buffer_info = vmalloc(size);
> + rx_ring->buffer_info = vzalloc(size);
> if (!rx_ring->buffer_info) {
> pr_err("Unable to allocate memory for the receive descriptor ring\n");
> return -ENOMEM;
> }
> - memset(rx_ring->buffer_info, 0, size);
> rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc);
> rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
> &rx_ring->dma, GFP_KERNEL);
> diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c
> index ccbc913..7556a92 100644
> --- a/drivers/net/pptp.c
> +++ b/drivers/net/pptp.c
> @@ -673,8 +673,7 @@ static int __init pptp_init_module(void)
> int err = 0;
> pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n");
>
> - callid_sock = __vmalloc((MAX_CALLID + 1) * sizeof(void *),
> - GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
> + callid_sock = vzalloc((MAX_CALLID + 1) * sizeof(void *));
> if (!callid_sock) {
> pr_err("PPTP: cann't allocate memory\n");
> return -ENOMEM;
> diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
> index 0d180c6..3f97018 100644
> --- a/drivers/net/qlcnic/qlcnic_init.c
> +++ b/drivers/net/qlcnic/qlcnic_init.c
> @@ -236,12 +236,11 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
> tx_ring->num_desc = adapter->num_txd;
> tx_ring->txq = netdev_get_tx_queue(netdev, 0);
>
> - cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring));
> + cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring));
> if (cmd_buf_arr == NULL) {
> dev_err(&netdev->dev, "failed to allocate cmd buffer ring\n");
> goto err_out;
> }
> - memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring));
> tx_ring->cmd_buf_arr = cmd_buf_arr;
>
> recv_ctx = &adapter->recv_ctx;
> @@ -276,13 +275,12 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
> break;
> }
> rds_ring->rx_buf_arr = (struct qlcnic_rx_buffer *)
> - vmalloc(RCV_BUFF_RINGSIZE(rds_ring));
> + vzalloc(RCV_BUFF_RINGSIZE(rds_ring));
> if (rds_ring->rx_buf_arr == NULL) {
> dev_err(&netdev->dev, "Failed to allocate "
> "rx buffer ring %d\n", ring);
> goto err_out;
> }
> - memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring));
> INIT_LIST_HEAD(&rds_ring->free_list);
> /*
> * Now go through all of them, set reference handles
> diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c
> index 52cb608..44500b5 100644
> --- a/drivers/net/sfc/filter.c
> +++ b/drivers/net/sfc/filter.c
> @@ -428,10 +428,9 @@ int efx_probe_filters(struct efx_nic *efx)
> GFP_KERNEL);
> if (!table->used_bitmap)
> goto fail;
> - table->spec = vmalloc(table->size * sizeof(*table->spec));
> + table->spec = vzalloc(table->size * sizeof(*table->spec));
> if (!table->spec)
> goto fail;
> - memset(table->spec, 0, table->size * sizeof(*table->spec));
> }
>
> return 0;
> diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c
> index 409c2e6..44d3ddd 100644
> --- a/drivers/net/vxge/vxge-config.c
> +++ b/drivers/net/vxge/vxge-config.c
> @@ -1220,13 +1220,12 @@ vxge_hw_device_initialize(
> goto exit;
>
> hldev = (struct __vxge_hw_device *)
> - vmalloc(sizeof(struct __vxge_hw_device));
> + vzalloc(sizeof(struct __vxge_hw_device));
> if (hldev == NULL) {
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> goto exit;
> }
>
> - memset(hldev, 0, sizeof(struct __vxge_hw_device));
> hldev->magic = VXGE_HW_DEVICE_MAGIC;
>
> vxge_hw_device_debug_set(hldev, VXGE_ERR, VXGE_COMPONENT_ALL);
> @@ -2064,15 +2063,12 @@ __vxge_hw_mempool_grow(struct vxge_hw_mempool *mempool, u32 num_allocate,
> * allocate new memblock and its private part at once.
> * This helps to minimize memory usage a lot. */
> mempool->memblocks_priv_arr[i] =
> - vmalloc(mempool->items_priv_size * n_items);
> + vzalloc(mempool->items_priv_size * n_items);
> if (mempool->memblocks_priv_arr[i] == NULL) {
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> goto exit;
> }
>
> - memset(mempool->memblocks_priv_arr[i], 0,
> - mempool->items_priv_size * n_items);
> -
> /* allocate DMA-capable memblock */
> mempool->memblocks_arr[i] =
> __vxge_hw_blockpool_malloc(mempool->devh,
> @@ -2145,12 +2141,11 @@ __vxge_hw_mempool_create(
> }
>
> mempool = (struct vxge_hw_mempool *)
> - vmalloc(sizeof(struct vxge_hw_mempool));
> + vzalloc(sizeof(struct vxge_hw_mempool));
> if (mempool == NULL) {
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> goto exit;
> }
> - memset(mempool, 0, sizeof(struct vxge_hw_mempool));
>
> mempool->devh = devh;
> mempool->memblock_size = memblock_size;
> @@ -2170,31 +2165,27 @@ __vxge_hw_mempool_create(
>
> /* allocate array of memblocks */
> mempool->memblocks_arr =
> - (void **) vmalloc(sizeof(void *) * mempool->memblocks_max);
> + (void **) vzalloc(sizeof(void *) * mempool->memblocks_max);
> if (mempool->memblocks_arr == NULL) {
> __vxge_hw_mempool_destroy(mempool);
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> mempool = NULL;
> goto exit;
> }
> - memset(mempool->memblocks_arr, 0,
> - sizeof(void *) * mempool->memblocks_max);
>
> /* allocate array of private parts of items per memblocks */
> mempool->memblocks_priv_arr =
> - (void **) vmalloc(sizeof(void *) * mempool->memblocks_max);
> + (void **) vzalloc(sizeof(void *) * mempool->memblocks_max);
> if (mempool->memblocks_priv_arr == NULL) {
> __vxge_hw_mempool_destroy(mempool);
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> mempool = NULL;
> goto exit;
> }
> - memset(mempool->memblocks_priv_arr, 0,
> - sizeof(void *) * mempool->memblocks_max);
>
> /* allocate array of memblocks DMA objects */
> mempool->memblocks_dma_arr = (struct vxge_hw_mempool_dma *)
> - vmalloc(sizeof(struct vxge_hw_mempool_dma) *
> + vzalloc(sizeof(struct vxge_hw_mempool_dma) *
> mempool->memblocks_max);
>
> if (mempool->memblocks_dma_arr == NULL) {
> @@ -2203,20 +2194,16 @@ __vxge_hw_mempool_create(
> mempool = NULL;
> goto exit;
> }
> - memset(mempool->memblocks_dma_arr, 0,
> - sizeof(struct vxge_hw_mempool_dma) *
> - mempool->memblocks_max);
>
> /* allocate hash array of items */
> mempool->items_arr =
> - (void **) vmalloc(sizeof(void *) * mempool->items_max);
> + (void **) vzalloc(sizeof(void *) * mempool->items_max);
> if (mempool->items_arr == NULL) {
> __vxge_hw_mempool_destroy(mempool);
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> mempool = NULL;
> goto exit;
> }
> - memset(mempool->items_arr, 0, sizeof(void *) * mempool->items_max);
>
> /* calculate initial number of memblocks */
> memblocks_to_allocate = (mempool->items_initial +
> @@ -4272,14 +4259,12 @@ vxge_hw_vpath_open(struct __vxge_hw_device *hldev,
> goto vpath_open_exit1;
>
> vp = (struct __vxge_hw_vpath_handle *)
> - vmalloc(sizeof(struct __vxge_hw_vpath_handle));
> + vzalloc(sizeof(struct __vxge_hw_vpath_handle));
> if (vp == NULL) {
> status = VXGE_HW_ERR_OUT_OF_MEMORY;
> goto vpath_open_exit2;
> }
>
> - memset(vp, 0, sizeof(struct __vxge_hw_vpath_handle));
> -
> vp->vpath = vpath;
>
> if (vpath->vp_config->fifo.enable == VXGE_HW_FIFO_ENABLE) {
>
>
> --
> 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
The information and any attached documents contained in this message
may be confidential and/or legally privileged. The message is
intended solely for the addressee(s). If you are not the intended
recipient, you are hereby notified that any use, dissemination, or
reproduction is strictly prohibited and may be unlawful. If you are
not the intended recipient, please contact the sender immediately by
return e-mail and destroy all copies of the original message.
^ permalink raw reply
* Re: [PATCH] arch/tile: fix rwlock so would-be write lockers don't block new readers
From: Chris Metcalf @ 2010-11-22 13:35 UTC (permalink / raw)
To: Cypher Wu; +Cc: linux-kernel, Américo Wang, Eric Dumazet, netdev
In-Reply-To: <AANLkTikGj+zG9OqVJseKh4fGqQNnqnJpHgcaaXOL8nNi@mail.gmail.com>
On 11/22/2010 12:39 AM, Cypher Wu wrote:
> 2010/11/15 Chris Metcalf <cmetcalf@tilera.com>:
>> This avoids a deadlock in the IGMP code where one core gets a read
>> lock, another core starts trying to get a write lock (thus blocking
>> new readers), and then the first core tries to recursively re-acquire
>> the read lock.
>>
>> We still try to preserve some degree of balance by giving priority
>> to additional write lockers that come along while the lock is held
>> for write, so they can all complete quickly and return the lock to
>> the readers.
>>
>> Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
>> ---
>> This should apply relatively cleanly to 2.6.26.7 source code too.
>> [...]
>
> I've finished my business trip and tested that patch for more than an
> hour and it works. The test is still running now.
>
> But it seems there still has a potential problem: we used ticket lock
> for write_lock(), and if there are so many write_lock() occurred, is
> 256 ticket enough for 64 or even more cores to avoiding overflow?
> Since is we try to write_unlock() and there's already write_lock()
> waiting we'll only adding current ticket.
This is OK, since each core can issue at most one (blocking) write_lock(),
and we have only 64 cores. Future >256 core machines will be based on
TILE-Gx anyway, which doesn't have the 256-core limit since it doesn't use
the spinlock_32.c implementation.
--
Chris Metcalf, Tilera Corp.
http://www.tilera.com
^ permalink raw reply
* Re: [PATCH 2/2 v7] xps: Transmit Packet Steering
From: Eric Dumazet @ 2010-11-22 13:33 UTC (permalink / raw)
To: Tom Herbert; +Cc: davem, netdev
In-Reply-To: <alpine.DEB.2.00.1011211501430.14906@pokey.mtv.corp.google.com>
Le dimanche 21 novembre 2010 à 15:17 -0800, Tom Herbert a écrit :
...
> +
> +static DEFINE_MUTEX(xps_map_mutex);
> +
> +static ssize_t store_xps_map(struct netdev_queue *queue,
> + struct netdev_queue_attribute *attribute,
> + const char *buf, size_t len)
> +{
> + struct net_device *dev = queue->dev;
> + cpumask_var_t mask;
> + int err, i, cpu, pos, map_len, alloc_len, need_set;
> + unsigned long index;
> + struct xps_map *map, *new_map;
> + struct xps_dev_maps *dev_maps, *new_dev_maps;
> + int nonempty = 0;
> +
> + if (!capable(CAP_NET_ADMIN))
> + return -EPERM;
> +
> + if (!alloc_cpumask_var(&mask, GFP_KERNEL))
> + return -ENOMEM;
> +
> + index = get_netdev_queue_index(queue);
> +
> + err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits);
> + if (err) {
> + free_cpumask_var(mask);
> + return err;
> + }
> +
> + new_dev_maps = kzalloc(max_t(unsigned,
> + XPS_DEV_MAPS_SIZE, L1_CACHE_BYTES), GFP_KERNEL);
> + if (!new_dev_maps) {
> + free_cpumask_var(mask);
> + return -ENOMEM;
> + }
> +
> + mutex_lock(&xps_map_mutex);
> +
> + dev_maps = dev->xps_maps;
> +
> + for_each_possible_cpu(cpu) {
> + new_map = map = dev_maps ? dev_maps->cpu_map[cpu] : NULL;
> +
> + if (map) {
> + for (pos = 0; pos < map->len; pos++)
> + if (map->queues[pos] == index)
> + break;
> + map_len = map->len;
> + alloc_len = map->alloc_len;
> + } else
> + pos = map_len = alloc_len = 0;
> +
> + need_set = cpu_isset(cpu, *mask) && cpu_online(cpu);
> +
> + if (need_set && pos >= map_len) {
> + /* Need to add queue to this CPU's map */
> + if (map_len >= alloc_len) {
> + alloc_len = alloc_len ?
> + 2 * alloc_len : XPS_MIN_MAP_ALLOC;
> + new_map = kzalloc(XPS_MAP_SIZE(alloc_len),
> + GFP_KERNEL);
kzalloc_node(size, GFP_KERNEL, cpu_to_node(cpu))
to get memory close to the cpu ?
> + if (!new_map)
> + goto error;
> + new_map->alloc_len = alloc_len;
> + for (i = 0; i < map_len; i++)
> + new_map->queues[i] = map->queues[i];
> + new_map->len = map_len;
> + }
> + new_map->queues[new_map->len++] = index;
> + } else if (!need_set && pos < map_len) {
> + /* Need to remove queue from this CPU's map */
> + if (map_len > 1)
> + new_map->queues[pos] =
> + new_map->queues[--new_map->len];
> + else
> + new_map = NULL;
> + }
> + new_dev_maps->cpu_map[cpu] = new_map;
> + }
> +
> + /* Cleanup old maps */
> + for_each_possible_cpu(cpu) {
> + map = dev_maps ? dev_maps->cpu_map[cpu] : NULL;
> + if (map && new_dev_maps->cpu_map[cpu] != map)
> + call_rcu(&map->rcu, xps_map_release);
> + if (new_dev_maps->cpu_map[cpu])
> + nonempty = 1;
> + }
> +
^ permalink raw reply
* [PATCH] netns: Don't leak others' openreq-s in proc
From: Pavel Emelyanov @ 2010-11-22 13:26 UTC (permalink / raw)
To: David Miller, Linux Netdev List
The /proc/net/tcp leaks openreq sockets from other namespaces.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
---
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 69ccbc1..e13da6d 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2043,7 +2043,9 @@ get_req:
}
get_sk:
sk_nulls_for_each_from(sk, node) {
- if (sk->sk_family == st->family && net_eq(sock_net(sk), net)) {
+ if (!net_eq(sock_net(sk), net))
+ continue;
+ if (sk->sk_family == st->family) {
cur = sk;
goto out;
}
^ permalink raw reply related
* [PATCH] ks8842: Fix TX cache flush issue
From: Richard Röjfors @ 2010-11-22 12:50 UTC (permalink / raw)
To: netdev; +Cc: davem, ferringb
This patch fixes a cache sync issue found in MeeGo 1.1.
It was found that bytes after the first 64 of the TX buffer was not
flushed from the cache correctly.
The patch switches out kmalloc/dma_map_single/dma_sync_single_for_device
to dma_alloc_coherent.
Signed-off-by: Richard Röjfors <richard.rojfors@pelagicore.com>
---
diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c
index 928b2b8..55a11ba 100644
--- a/drivers/net/ks8842.c
+++ b/drivers/net/ks8842.c
@@ -449,10 +449,6 @@ static int ks8842_tx_frame_dma(struct sk_buff *skb, struct net_device *netdev)
*buf++ = (skb->len >> 8) & 0xff;
skb_copy_from_linear_data(skb, buf, skb->len);
- dma_sync_single_range_for_device(adapter->dev,
- sg_dma_address(&ctl->sg), 0, sg_dma_len(&ctl->sg),
- DMA_TO_DEVICE);
-
/* make sure the length is a multiple of 4 */
if (sg_dma_len(&ctl->sg) % 4)
sg_dma_len(&ctl->sg) += 4 - sg_dma_len(&ctl->sg) % 4;
@@ -908,12 +904,10 @@ static void ks8842_dealloc_dma_bufs(struct ks8842_adapter *adapter)
tasklet_kill(&rx_ctl->tasklet);
- if (sg_dma_address(&tx_ctl->sg))
- dma_unmap_single(adapter->dev, sg_dma_address(&tx_ctl->sg),
- DMA_BUFFER_SIZE, DMA_TO_DEVICE);
+ if (tx_ctl->buf)
+ dma_free_coherent(adapter->dev, DMA_BUFFER_SIZE,
+ tx_ctl->buf, sg_dma_address(&tx_ctl->sg));
sg_dma_address(&tx_ctl->sg) = 0;
-
- kfree(tx_ctl->buf);
tx_ctl->buf = NULL;
}
@@ -945,21 +939,13 @@ static int ks8842_alloc_dma_bufs(struct net_device *netdev)
}
/* allocate DMA buffer */
- tx_ctl->buf = kmalloc(DMA_BUFFER_SIZE, GFP_KERNEL);
+ tx_ctl->buf = dma_alloc_coherent(adapter->dev, DMA_BUFFER_SIZE,
+ &sg_dma_address(&tx_ctl->sg), GFP_KERNEL);
if (!tx_ctl->buf) {
err = -ENOMEM;
goto err;
}
- sg_dma_address(&tx_ctl->sg) = dma_map_single(adapter->dev,
- tx_ctl->buf, DMA_BUFFER_SIZE, DMA_TO_DEVICE);
- err = dma_mapping_error(adapter->dev,
- sg_dma_address(&tx_ctl->sg));
- if (err) {
- sg_dma_address(&tx_ctl->sg) = 0;
- goto err;
- }
-
rx_ctl->chan = dma_request_channel(mask, ks8842_dma_filter_fn,
(void *)(long)rx_ctl->channel);
if (!rx_ctl->chan) {
^ permalink raw reply related
* Re: iwl3945: regression - unregister_netdevice: waiting for wlan0 to become free. Usage count = 1
From: Michal Hocko @ 2010-11-22 12:46 UTC (permalink / raw)
To: Eric Dumazet
Cc: David Miller, linux-wireless, Reinette Chatre, Wey-Yi Guy,
Intel Linux Wireless, LKML, netdev
In-Reply-To: <1290424776.2811.32.camel@edumazet-laptop>
On Mon 22-11-10 12:19:36, Eric Dumazet wrote:
> Le lundi 22 novembre 2010 ?? 11:43 +0100, Michal Hocko a ??crit :
> > Hi,
> > I am experiencing iwl3945 driver reference counting problem with the current
> > 2.6.37-rc2 kernel release.
> >
> > The problem can be easily reproduced by associating to an AP (I have
> > tried only wep and wpa based auth) and then rmmod iw3945 which gets
> > stuck in unregister_netdevice (in the endless loop as there is no way -
> > I guess - to decrease the reference count to 0) spitting the following
> > message:
> >
> > unregister_netdevice: waiting for wlan0 to become free. Usage count = 1
> >
[...]
>
>
> Oh well, it seems David put the fix in net-next-2.6 instead of net-2.6
>
> Please try :
>
> http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=commitdiff;h=9d82ca98f71fd686ef2f3017c5e3e6a4871b6e46
Yes, the patch really fixes the issue. Thanks a lot!
Btw. I have checked -rc3 which doesn't conttain the fix as well.
>
> Thanks
>
>
--
Michal Hocko
L3 team
SUSE LINUX s.r.o.
Lihovarska 1060/12
190 00 Praha 9
Czech Republic
^ permalink raw reply
* Re: linux-next: Tree for November 18 (netfilter)
From: KOVACS Krisztian @ 2010-11-22 12:28 UTC (permalink / raw)
To: Patrick McHardy
Cc: Randy Dunlap, Stephen Rothwell, netfilter-devel, linux-next, LKML,
netdev, Balazs Scheidler
In-Reply-To: <1290428077.725556.3.camel@nienna.balabit>
Hi,
On Mon, 2010-11-22 at 13:14 +0100, KOVACS Krisztian wrote:
> Indeed, we were missing quite a few of those ifdefs... The patch below
> seems to fix the issue for me.
>
> commit ec0ac6f3e7749e25f481c1e0f75766974820fe84
> Author: KOVACS Krisztian <hidden@balabit.hu>
> Date: Mon Nov 22 13:07:15 2010 +0100
Bah, it seems the patch got line-wrapped by my MUA, here it is again.
Let's hope I got it right this time...
commit ec0ac6f3e7749e25f481c1e0f75766974820fe84
Author: KOVACS Krisztian <hidden@balabit.hu>
Date: Mon Nov 22 13:07:15 2010 +0100
netfilter: fix compilation when conntrack is disabled but tproxy is enabled
The IPv6 tproxy patches split IPv6 defragmentation off of conntrack, but
failed to update the #ifdef stanzas guarding the defragmentation related
fields and code in skbuff and conntrack related code in nf_defrag_ipv6.c.
This patch adds the required #ifdefs so that IPv6 tproxy can truly be used
without connection tracking.
Original report:
http://marc.info/?l=linux-netdev&m=129010118516341&w=2
Reported-by: Randy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index e6ba898..4f2db79 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -255,6 +255,11 @@ typedef unsigned int sk_buff_data_t;
typedef unsigned char *sk_buff_data_t;
#endif
+#if defined(CONFIG_NF_DEFRAG_IPV4) || defined(CONFIG_NF_DEFRAG_IPV4_MODULE) || \
+ defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
+#define NET_SKBUFF_NF_DEFRAG_NEEDED 1
+#endif
+
/**
* struct sk_buff - socket buffer
* @next: Next buffer in list
@@ -362,6 +367,8 @@ struct sk_buff {
void (*destructor)(struct sk_buff *skb);
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct nf_conntrack *nfct;
+#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
struct sk_buff *nfct_reasm;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
@@ -2051,6 +2058,8 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
if (nfct)
atomic_inc(&nfct->use);
}
+#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
static inline void nf_conntrack_get_reasm(struct sk_buff *skb)
{
if (skb)
@@ -2079,6 +2088,8 @@ static inline void nf_reset(struct sk_buff *skb)
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_conntrack_put(skb->nfct);
skb->nfct = NULL;
+#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
nf_conntrack_put_reasm(skb->nfct_reasm);
skb->nfct_reasm = NULL;
#endif
@@ -2095,6 +2106,8 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
dst->nfct = src->nfct;
nf_conntrack_get(src->nfct);
dst->nfctinfo = src->nfctinfo;
+#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
dst->nfct_reasm = src->nfct_reasm;
nf_conntrack_get_reasm(src->nfct_reasm);
#endif
@@ -2108,6 +2121,8 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_conntrack_put(dst->nfct);
+#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
nf_conntrack_put_reasm(dst->nfct_reasm);
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
index 1ee717e..a4c9936 100644
--- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -7,16 +7,6 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
-extern int nf_ct_frag6_init(void);
-extern void nf_ct_frag6_cleanup(void);
-extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
-extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
- struct net_device *in,
- struct net_device *out,
- int (*okfn)(struct sk_buff *));
-
-struct inet_frags_ctl;
-
#include <linux/sysctl.h>
extern struct ctl_table nf_ct_ipv6_sysctl_table[];
diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
index 94dd54d..fd79c9a 100644
--- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
@@ -3,4 +3,14 @@
extern void nf_defrag_ipv6_enable(void);
+extern int nf_ct_frag6_init(void);
+extern void nf_ct_frag6_cleanup(void);
+extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
+extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
+ struct net_device *in,
+ struct net_device *out,
+ int (*okfn)(struct sk_buff *));
+
+struct inet_frags_ctl;
+
#endif /* _NF_DEFRAG_IPV6_H */
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 104f844..74ebf4b 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -380,6 +380,8 @@ static void skb_release_head_state(struct sk_buff *skb)
}
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_conntrack_put(skb->nfct);
+#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
nf_conntrack_put_reasm(skb->nfct_reasm);
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
index 99abfb5..97c5b21 100644
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -19,13 +19,15 @@
#include <linux/netfilter_ipv6.h>
#include <linux/netfilter_bridge.h>
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_core.h>
-#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
+#endif
+#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
@@ -33,8 +35,10 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
{
u16 zone = NF_CT_DEFAULT_ZONE;
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
if (skb->nfct)
zone = nf_ct_zone((struct nf_conn *)skb->nfct);
+#endif
#ifdef CONFIG_BRIDGE_NETFILTER
if (skb->nf_bridge &&
@@ -56,9 +60,11 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
{
struct sk_buff *reasm;
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
/* Previously seen (loopback)? */
if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
return NF_ACCEPT;
+#endif
reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
/* queued */
^ permalink raw reply related
* Re: linux-next: Tree for November 18 (netfilter)
From: KOVACS Krisztian @ 2010-11-22 12:14 UTC (permalink / raw)
To: Patrick McHardy
Cc: Randy Dunlap, Stephen Rothwell, netfilter-devel, linux-next, LKML,
netdev, Balazs Scheidler
In-Reply-To: <4CE5712B.2080909@trash.net>
Hi,
On Thu, 2010-11-18 at 19:32 +0100, Patrick McHardy wrote:
> Krisztian, Balazs, could you please have a look at this? If the
> intention is to use NF_DEFRAG_IPV6 without conntrack, we probably
> need a couple of ifdefs.
Indeed, we were missing quite a few of those ifdefs... The patch below
seems to fix the issue for me.
commit ec0ac6f3e7749e25f481c1e0f75766974820fe84
Author: KOVACS Krisztian <hidden@balabit.hu>
Date: Mon Nov 22 13:07:15 2010 +0100
netfilter: fix compilation when conntrack is disabled but tproxy is
enabled
The IPv6 tproxy patches split IPv6 defragmentation off of conntrack,
but
failed to update the #ifdef stanzas guarding the defragmentation
related
fields and code in skbuff and conntrack related code in
nf_defrag_ipv6.c.
This patch adds the required #ifdefs so that IPv6 tproxy can truly
be used
without connection tracking.
Original report:
http://marc.info/?l=linux-netdev&m=129010118516341&w=2
Reported-by: Randy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: KOVACS Krisztian <hidden@balabit.hu>
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index e6ba898..4f2db79 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -255,6 +255,11 @@ typedef unsigned int sk_buff_data_t;
typedef unsigned char *sk_buff_data_t;
#endif
+#if defined(CONFIG_NF_DEFRAG_IPV4) ||
defined(CONFIG_NF_DEFRAG_IPV4_MODULE) || \
+ defined(CONFIG_NF_DEFRAG_IPV6) ||
defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
+#define NET_SKBUFF_NF_DEFRAG_NEEDED 1
+#endif
+
/**
* struct sk_buff - socket buffer
* @next: Next buffer in list
@@ -362,6 +367,8 @@ struct sk_buff {
void (*destructor)(struct sk_buff *skb);
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct nf_conntrack *nfct;
+#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
struct sk_buff *nfct_reasm;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
@@ -2051,6 +2058,8 @@ static inline void nf_conntrack_get(struct
nf_conntrack *nfct)
if (nfct)
atomic_inc(&nfct->use);
}
+#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
static inline void nf_conntrack_get_reasm(struct sk_buff *skb)
{
if (skb)
@@ -2079,6 +2088,8 @@ static inline void nf_reset(struct sk_buff *skb)
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_conntrack_put(skb->nfct);
skb->nfct = NULL;
+#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
nf_conntrack_put_reasm(skb->nfct_reasm);
skb->nfct_reasm = NULL;
#endif
@@ -2095,6 +2106,8 @@ static inline void __nf_copy(struct sk_buff *dst,
const struct sk_buff *src)
dst->nfct = src->nfct;
nf_conntrack_get(src->nfct);
dst->nfctinfo = src->nfctinfo;
+#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
dst->nfct_reasm = src->nfct_reasm;
nf_conntrack_get_reasm(src->nfct_reasm);
#endif
@@ -2108,6 +2121,8 @@ static inline void nf_copy(struct sk_buff *dst,
const struct sk_buff *src)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_conntrack_put(dst->nfct);
+#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
nf_conntrack_put_reasm(dst->nfct_reasm);
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
index 1ee717e..a4c9936 100644
--- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -7,16 +7,6 @@ extern struct nf_conntrack_l4proto
nf_conntrack_l4proto_tcp6;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
-extern int nf_ct_frag6_init(void);
-extern void nf_ct_frag6_cleanup(void);
-extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32
user);
-extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff
*skb,
- struct net_device *in,
- struct net_device *out,
- int (*okfn)(struct sk_buff *));
-
-struct inet_frags_ctl;
-
#include <linux/sysctl.h>
extern struct ctl_table nf_ct_ipv6_sysctl_table[];
diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h
b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
index 94dd54d..fd79c9a 100644
--- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
@@ -3,4 +3,14 @@
extern void nf_defrag_ipv6_enable(void);
+extern int nf_ct_frag6_init(void);
+extern void nf_ct_frag6_cleanup(void);
+extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32
user);
+extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff
*skb,
+ struct net_device *in,
+ struct net_device *out,
+ int (*okfn)(struct sk_buff *));
+
+struct inet_frags_ctl;
+
#endif /* _NF_DEFRAG_IPV6_H */
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 104f844..74ebf4b 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -380,6 +380,8 @@ static void skb_release_head_state(struct sk_buff
*skb)
}
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_conntrack_put(skb->nfct);
+#endif
+#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
nf_conntrack_put_reasm(skb->nfct_reasm);
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
index 99abfb5..97c5b21 100644
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -19,13 +19,15 @@
#include <linux/netfilter_ipv6.h>
#include <linux/netfilter_bridge.h>
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_core.h>
-#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
+#endif
+#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
@@ -33,8 +35,10 @@ static enum ip6_defrag_users
nf_ct6_defrag_user(unsigned int hooknum,
{
u16 zone = NF_CT_DEFAULT_ZONE;
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
if (skb->nfct)
zone = nf_ct_zone((struct nf_conn *)skb->nfct);
+#endif
#ifdef CONFIG_BRIDGE_NETFILTER
if (skb->nf_bridge &&
@@ -56,9 +60,11 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
{
struct sk_buff *reasm;
+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
/* Previously seen (loopback)? */
if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
return NF_ACCEPT;
+#endif
reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
/* queued */
^ permalink raw reply related
* Re: [PATCH 2/2 v7] xps: Transmit Packet Steering
From: Changli Gao @ 2010-11-22 11:42 UTC (permalink / raw)
To: Tom Herbert; +Cc: davem, netdev, eric.dumazet
In-Reply-To: <alpine.DEB.2.00.1011211501430.14906@pokey.mtv.corp.google.com>
On Mon, Nov 22, 2010 at 7:17 AM, Tom Herbert <therbert@google.com> wrote:
> This patch implements transmit packet steering (XPS) for multiqueue
> devices. XPS selects a transmit queue during packet transmission based
> on configuration. This is done by mapping the CPU transmitting the
> packet to a queue. This is the transmit side analogue to RPS-- where
> RPS is selecting a CPU based on receive queue, XPS selects a queue
> based on the CPU (previously there was an XPS patch from Eric
> Dumazet, but that might more appropriately be called transmit completion
> steering).
>
> Each transmit queue can be associated with a number of CPUs which will
> use the queue to send packets. This is configured as a CPU mask on a
> per queue basis in:
>
> /sys/class/net/eth<n>/queues/tx-<n>/xps_cpus
>
> The mappings are stored per device in an inverted data structure that
> maps CPUs to queues. In the netdevice structure this is an array of
> num_possible_cpu structures where each structure holds and array of
> queue_indexes for queues which that CPU can use.
>
> The benefits of XPS are improved locality in the per queue data
> structures. Also, transmit completions are more likely to be done
> nearer to the sending thread, so this should promote locality back
> to the socket on free (e.g. UDP). The benefits of XPS are dependent on
> cache hierarchy, application load, and other factors. XPS would
> nominally be configured so that a queue would only be shared by CPUs
> which are sharing a cache, the degenerative configuration woud be that
> each CPU has it's own queue.
>
> Below are some benchmark results which show the potential benfit of
> this patch. The netperf test has 500 instances of netperf TCP_RR test
> with 1 byte req. and resp.
>
> bnx2x on 16 core AMD
> XPS (16 queues, 1 TX queue per CPU) 1234K at 100% CPU
> No XPS (16 queues) 996K at 100% CPU
>
> Signed-off-by: Tom Herbert <therbert@google.com>
> ---
> include/linux/netdevice.h | 30 ++++
> net/core/dev.c | 53 ++++++-
> net/core/net-sysfs.c | 369 ++++++++++++++++++++++++++++++++++++++++++++-
> net/core/net-sysfs.h | 3 +
> 4 files changed, 447 insertions(+), 8 deletions(-)
>
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index b45c1b8..badf928 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -503,6 +503,10 @@ struct netdev_queue {
> struct Qdisc *qdisc;
> unsigned long state;
> struct Qdisc *qdisc_sleeping;
> +#ifdef CONFIG_RPS
> + struct kobject kobj;
> +#endif
> +
Why do you reuse CONFIG_RPS? I think it is confusing, as the code
enclosed is for XPS not RPS.
--
Regards,
Changli Gao(xiaosuo@gmail.com)
^ permalink raw reply
* [PATCH net-next-2.6]: rtnl: make link af-specific updates atomic
From: Thomas Graf @ 2010-11-22 11:31 UTC (permalink / raw)
To: davem; +Cc: netdev
As David pointed out correctly, updates to af-specific attributes
are currently not atomic. If multiple changes are requested and
one of them fails, previous updates may have been applied already
leaving the link behind in a undefined state.
This patch splits the function parse_link_af() into two functions
validate_link_af() and set_link_at(). validate_link_af() is placed
to validate_linkmsg() check for errors as early as possible before
any changes to the link have been made. set_link_af() is called to
commit the changes later.
This method is not fail proof, while it is currently sufficient
to make set_link_af() inerrable and thus 100% atomic, the
validation function method will not be able to detect all error
scenarios in the future, there will likely always be errors
depending on states which are f.e. not protected by rtnl_mutex
and thus may change between validation and setting.
Also, instead of silently ignoring unknown address families and
config blocks for address families which did not register a set
function the errors EAFNOSUPPORT respectively EOPNOSUPPORT are
returned to avoid comitting 4 out of 5 update requests without
notifying the user.
Signed-off-by: Thomas Graf <tgraf@infradead.org>
Index: net-next-2.6/include/net/rtnetlink.h
===================================================================
--- net-next-2.6.orig/include/net/rtnetlink.h
+++ net-next-2.6/include/net/rtnetlink.h
@@ -92,8 +92,10 @@ extern void rtnl_link_unregister(struct
* specific netlink attributes.
* @get_link_af_size: Function to calculate size of address family specific
* netlink attributes exlusive the container attribute.
- * @parse_link_af: Function to parse a IFLA_AF_SPEC attribute and modify
- * net_device accordingly.
+ * @validate_link_af: Validate a IFLA_AF_SPEC attribute, must check attr
+ * for invalid configuration settings.
+ * @set_link_af: Function to parse a IFLA_AF_SPEC attribute and modify
+ * net_device accordingly.
*/
struct rtnl_af_ops {
struct list_head list;
@@ -103,8 +105,10 @@ struct rtnl_af_ops {
const struct net_device *dev);
size_t (*get_link_af_size)(const struct net_device *dev);
- int (*parse_link_af)(struct net_device *dev,
- const struct nlattr *attr);
+ int (*validate_link_af)(const struct net_device *dev,
+ const struct nlattr *attr);
+ int (*set_link_af)(struct net_device *dev,
+ const struct nlattr *attr);
};
extern int __rtnl_af_register(struct rtnl_af_ops *ops);
Index: net-next-2.6/net/core/rtnetlink.c
===================================================================
--- net-next-2.6.orig/net/core/rtnetlink.c
+++ net-next-2.6/net/core/rtnetlink.c
@@ -1107,6 +1107,28 @@ static int validate_linkmsg(struct net_d
return -EINVAL;
}
+ if (tb[IFLA_AF_SPEC]) {
+ struct nlattr *af;
+ int rem, err;
+
+ nla_for_each_nested(af, tb[IFLA_AF_SPEC], rem) {
+ const struct rtnl_af_ops *af_ops;
+
+ if (!(af_ops = rtnl_af_lookup(nla_type(af))))
+ return -EAFNOSUPPORT;
+
+ if (!af_ops->set_link_af)
+ return -EOPNOTSUPP;
+
+ if (af_ops->validate_link_af) {
+ err = af_ops->validate_link_af(dev,
+ tb[IFLA_AF_SPEC]);
+ if (err < 0)
+ return err;
+ }
+ }
+ }
+
return 0;
}
@@ -1356,12 +1378,9 @@ static int do_setlink(struct net_device
const struct rtnl_af_ops *af_ops;
if (!(af_ops = rtnl_af_lookup(nla_type(af))))
- continue;
-
- if (!af_ops->parse_link_af)
- continue;
+ BUG();
- err = af_ops->parse_link_af(dev, af);
+ err = af_ops->set_link_af(dev, af);
if (err < 0)
goto errout;
Index: net-next-2.6/net/ipv4/devinet.c
===================================================================
--- net-next-2.6.orig/net/ipv4/devinet.c
+++ net-next-2.6/net/ipv4/devinet.c
@@ -1289,14 +1289,14 @@ static const struct nla_policy inet_af_p
[IFLA_INET_CONF] = { .type = NLA_NESTED },
};
-static int inet_parse_link_af(struct net_device *dev, const struct nlattr *nla)
+static int inet_validate_link_af(const struct net_device *dev,
+ const struct nlattr *nla)
{
- struct in_device *in_dev = __in_dev_get_rcu(dev);
struct nlattr *a, *tb[IFLA_INET_MAX+1];
int err, rem;
- if (!in_dev)
- return -EOPNOTSUPP;
+ if (dev && !__in_dev_get_rcu(dev))
+ return -EAFNOSUPPORT;
err = nla_parse_nested(tb, IFLA_INET_MAX, nla, inet_af_policy);
if (err < 0)
@@ -1314,6 +1314,21 @@ static int inet_parse_link_af(struct net
}
}
+ return 0;
+}
+
+static int inet_set_link_af(struct net_device *dev, const struct nlattr *nla)
+{
+ struct in_device *in_dev = __in_dev_get_rcu(dev);
+ struct nlattr *a, *tb[IFLA_INET_MAX+1];
+ int rem;
+
+ if (!in_dev)
+ return -EAFNOSUPPORT;
+
+ if (nla_parse_nested(tb, IFLA_INET_MAX, nla, NULL) < 0)
+ BUG();
+
if (tb[IFLA_INET_CONF]) {
nla_for_each_nested(a, tb[IFLA_INET_CONF], rem)
ipv4_devconf_set(in_dev, nla_type(a), nla_get_u32(a));
@@ -1689,7 +1704,8 @@ static struct rtnl_af_ops inet_af_ops =
.family = AF_INET,
.fill_link_af = inet_fill_link_af,
.get_link_af_size = inet_get_link_af_size,
- .parse_link_af = inet_parse_link_af,
+ .validate_link_af = inet_validate_link_af,
+ .set_link_af = inet_set_link_af,
};
void __init devinet_init(void)
Index: net-next-2.6/net/ipv6/addrconf.c
===================================================================
--- net-next-2.6.orig/net/ipv6/addrconf.c
+++ net-next-2.6/net/ipv6/addrconf.c
@@ -3956,11 +3956,6 @@ static int inet6_fill_link_af(struct sk_
return 0;
}
-static int inet6_parse_link_af(struct net_device *dev, const struct nlattr *nla)
-{
- return -EOPNOTSUPP;
-}
-
static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
u32 pid, u32 seq, int event, unsigned int flags)
{
@@ -4670,7 +4665,6 @@ static struct rtnl_af_ops inet6_ops = {
.family = AF_INET6,
.fill_link_af = inet6_fill_link_af,
.get_link_af_size = inet6_get_link_af_size,
- .parse_link_af = inet6_parse_link_af,
};
/*
^ permalink raw reply
* Re: iwl3945: regression - unregister_netdevice: waiting for wlan0 to become free. Usage count = 1
From: Eric Dumazet @ 2010-11-22 11:19 UTC (permalink / raw)
To: Michal Hocko, David Miller
Cc: linux-wireless, Reinette Chatre, Wey-Yi Guy, Intel Linux Wireless,
LKML, netdev
In-Reply-To: <20101122104341.GA3897@tiehlicka.suse.cz>
Le lundi 22 novembre 2010 à 11:43 +0100, Michal Hocko a écrit :
> Hi,
> I am experiencing iwl3945 driver reference counting problem with the current
> 2.6.37-rc2 kernel release.
>
> The problem can be easily reproduced by associating to an AP (I have
> tried only wep and wpa based auth) and then rmmod iw3945 which gets
> stuck in unregister_netdevice (in the endless loop as there is no way -
> I guess - to decrease the reference count to 0) spitting the following
> message:
>
> unregister_netdevice: waiting for wlan0 to become free. Usage count = 1
>
> The situation is even worse as the rmmod process sits on the CPU and
> cannot be killed and the loop never ends so the only solution is
> rebooting.
>
> 2.6.37-rc1 looks good. I have tried to bisect to the culprit but I am
> failing to boot some of the kernels on the way (due to some unrelated
> issue which is already fixed in rc2). This is a partial bisect log
> (maybe it helps to narrow down the range of commits):
>
> $ git bisect log
> git bisect start
> # bad: [e53beacd23d9cb47590da6a7a7f6d417b941a994] Linux 2.6.37-rc2
> git bisect bad e53beacd23d9cb47590da6a7a7f6d417b941a994
> # good: [151f52f09c5728ecfdd0c289da1a4b30bb416f2c] ipw2x00: remove the right /proc/net entry
> git bisect good 151f52f09c5728ecfdd0c289da1a4b30bb416f2c
> # good: [891cbd30ef456664e50bbd28436ef3006a81cf7c] Merge branch 'upstream/core' of git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen
> git bisect good 891cbd30ef456664e50bbd28436ef3006a81cf7c
> # good: [80ef913f5e6a84551545016cea709f5e96d0cda6] Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
> git bisect good 80ef913f5e6a84551545016cea709f5e96d0cda6
> # bad: [c22cff08db00ef0411be088956d7934681a1f988] Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
> git bisect bad c22cff08db00ef0411be088956d7934681a1f988
> # skip: [8877870f8a8127b653f8c9a55c6b4de9f96f639b] Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
> git bisect skip 8877870f8a8127b653f8c9a55c6b4de9f96f639b
> # skip: [75e6047431872dadd0b13503b374e48ccd71a507] ucc_geth: Fix deadlock
> git bisect skip 75e6047431872dadd0b13503b374e48ccd71a507
> # skip: [18943d292facbc70e6a36fc62399ae833f64671b] inet: fix ip_mc_drop_socket()
> git bisect skip 18943d292facbc70e6a36fc62399ae833f64671b
> [Here I gave up]
>
> skipped steps are non-bootable kernels. From the log it looks like the last
> good commit is 80ef913f5e6a845.
>
> There is only one patch in that range for iwlwifi drivers:
> $ git shortlog 80ef913f5e6a845..v2.6.37-rc2 -- drivers/net/wireless/iwlwifi/
> Wey-Yi Guy (1):
> iwlwifi: dont use pci_dev before it being assign
>
> and this one doesn't look to manipulate the reference counting so I
> guess this is more general problem.
>
> $ git shortlog 80ef913f5e6a845..v2.6.37-rc2 -- net/wireless/
> Felix Fietkau (1):
> cfg80211: fix a crash in dev lookup on dump commands
>
> Doesn't look to be the culprit as well, though. Btw. I am getting the
> same patches also in the v2.6.37-rc1..v2.6.37-rc2 range.
>
> Please let me know if you need any further information.
> Thanks!
Oh well, it seems David put the fix in net-next-2.6 instead of net-2.6
Please try :
http://git.kernel.org/?p=linux/kernel/git/davem/net-next-2.6.git;a=commitdiff;h=9d82ca98f71fd686ef2f3017c5e3e6a4871b6e46
Thanks
^ permalink raw reply
* [RFC] [PATCH] iproute2: Add IPsec extended sequence number support
From: Steffen Klassert @ 2010-11-22 10:37 UTC (permalink / raw)
To: Herbert Xu, David Miller
Cc: Andreas Gruenbacher, Alex Badea, netdev, linux-crypto
In-Reply-To: <20101122102455.GC1868@secunet.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/linux/xfrm.h | 12 ++++++++++++
ip/ipxfrm.c | 8 +++++++-
ip/xfrm_state.c | 37 +++++++++++++++++++++++++++++--------
3 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 07f2b63..dd6928d 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -84,6 +84,16 @@ struct xfrm_replay_state {
__u32 bitmap;
};
+struct xfrm_replay_state_esn {
+ unsigned int len;
+ __u32 oseq;
+ __u32 oseq_hi;
+ __u32 seq;
+ __u32 seq_hi;
+ __u32 replay_window;
+ __u32 bmp[0];
+};
+
struct xfrm_algo {
char alg_name[64];
unsigned int alg_key_len; /* in bits */
@@ -283,6 +293,7 @@ enum xfrm_attr_type_t {
XFRMA_KMADDRESS, /* struct xfrm_user_kmaddress */
XFRMA_ALG_AUTH_TRUNC, /* struct xfrm_algo_auth */
XFRMA_MARK, /* struct xfrm_mark */
+ XFRMA_REPLAY_ESN_VAL, /* struct xfrm_replay_esn */
__XFRMA_MAX
#define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -349,6 +360,7 @@ struct xfrm_usersa_info {
#define XFRM_STATE_WILDRECV 8
#define XFRM_STATE_ICMP 16
#define XFRM_STATE_AF_UNSPEC 32
+#define XFRM_STATE_ESN 64
};
struct xfrm_usersa_id {
diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c
index 99a6756..548e4a4 100644
--- a/ip/ipxfrm.c
+++ b/ip/ipxfrm.c
@@ -665,6 +665,12 @@ done:
void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
FILE *fp, const char *prefix)
{
+
+ if (tb[XFRMA_REPLAY_ESN_VAL]) {
+ struct rtattr *rta = tb[XFRMA_REPLAY_ESN_VAL];
+ struct xfrm_replay_state_esn *repl = (struct xfrm_replay_state_esn *) RTA_DATA(rta);
+ fprintf(fp, "\treplay-window %u\n", repl->replay_window);
+ }
if (tb[XFRMA_MARK]) {
struct rtattr *rta = tb[XFRMA_MARK];
struct xfrm_mark *m = (struct xfrm_mark *) RTA_DATA(rta);
@@ -809,7 +815,6 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
STRBUF_CAT(buf, "\t");
fputs(buf, fp);
- fprintf(fp, "replay-window %u ", xsinfo->replay_window);
if (show_stats > 0)
fprintf(fp, "seq 0x%08u ", xsinfo->seq);
if (show_stats > 0 || xsinfo->flags) {
@@ -822,6 +827,7 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_WILDRECV, "wildrecv");
XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_ICMP, "icmp");
XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_AF_UNSPEC, "af-unspec");
+ XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_ESN, "replay-esn");
if (flags)
fprintf(fp, "%x", flags);
}
diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c
index 38d4039..4c66923 100644
--- a/ip/xfrm_state.c
+++ b/ip/xfrm_state.c
@@ -50,15 +50,16 @@
#define NLMSG_BUF_SIZE 4096
#define RTA_BUF_SIZE 2048
#define XFRM_ALGO_KEY_BUF_SIZE 512
+#define XFRM_REPLAY_BMP_SIZE_U32 16
static void usage(void) __attribute__((noreturn));
static void usage(void)
{
fprintf(stderr, "Usage: ip xfrm state { add | update } ID [ XFRM_OPT ] [ mode MODE ]\n");
- fprintf(stderr, " [ reqid REQID ] [ seq SEQ ] [ replay-window SIZE ] [ flag FLAG-LIST ]\n");
+ fprintf(stderr, " [ reqid REQID ] [ seq SEQ ][ replay-window SIZE ] [ flag FLAG-LIST ]\n");
fprintf(stderr, " [ encap ENCAP ] [ sel SELECTOR ] [ replay-seq SEQ ]\n");
- fprintf(stderr, " [ replay-oseq SEQ ] [ LIMIT-LIST ]\n");
+ fprintf(stderr, " [ replay-oseq SEQ ] [ replay-seqhi SEQ ] [ replay-oseqhi SEQ ] [ LIMIT-LIST ]\n");
fprintf(stderr, "Usage: ip xfrm state allocspi ID [ mode MODE ] [ reqid REQID ] [ seq SEQ ]\n");
fprintf(stderr, " [ min SPI max SPI ]\n");
fprintf(stderr, "Usage: ip xfrm state { delete | get } ID\n");
@@ -214,6 +215,8 @@ static int xfrm_state_flag_parse(__u8 *flags, int *argcp, char ***argvp)
*flags |= XFRM_STATE_ICMP;
else if (strcmp(*argv, "af-unspec") == 0)
*flags |= XFRM_STATE_AF_UNSPEC;
+ else if (strcmp(*argv, "replay-esn") == 0)
+ *flags |= XFRM_STATE_ESN;
else {
PREV_ARG(); /* back track */
break;
@@ -239,7 +242,11 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)
struct xfrm_usersa_info xsinfo;
char buf[RTA_BUF_SIZE];
} req;
- struct xfrm_replay_state replay;
+ struct {
+ struct xfrm_replay_state_esn state;
+ __u32 bmp[XFRM_REPLAY_BMP_SIZE_U32];
+ } replay;
+
char *idp = NULL;
char *aeadop = NULL;
char *ealgop = NULL;
@@ -249,8 +256,11 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)
struct xfrm_mark mark = {0, 0};
memset(&req, 0, sizeof(req));
+
memset(&replay, 0, sizeof(replay));
+ replay.state.len = sizeof(replay);
+
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xsinfo));
req.n.nlmsg_flags = NLM_F_REQUEST|flags;
req.n.nlmsg_type = cmd;
@@ -275,16 +285,24 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)
xfrm_seq_parse(&req.xsinfo.seq, &argc, &argv);
} else if (strcmp(*argv, "replay-window") == 0) {
NEXT_ARG();
- if (get_u8(&req.xsinfo.replay_window, *argv, 0))
+ if (get_u32(&replay.state.replay_window, *argv, 0))
invarg("\"replay-window\" value is invalid", *argv);
} else if (strcmp(*argv, "replay-seq") == 0) {
NEXT_ARG();
- if (get_u32(&replay.seq, *argv, 0))
+ if (get_u32(&replay.state.seq, *argv, 0))
invarg("\"replay-seq\" value is invalid", *argv);
} else if (strcmp(*argv, "replay-oseq") == 0) {
NEXT_ARG();
- if (get_u32(&replay.oseq, *argv, 0))
+ if (get_u32(&replay.state.oseq, *argv, 0))
invarg("\"replay-oseq\" value is invalid", *argv);
+ } else if (strcmp(*argv, "replay-seqhi") == 0) {
+ NEXT_ARG();
+ if (get_u32(&replay.state.seq_hi, *argv, 0))
+ invarg("\"replay-seqhi\" value is invalid", *argv);
+ } else if (strcmp(*argv, "replay-oseqhi") == 0) {
+ NEXT_ARG();
+ if (get_u32(&replay.state.oseq_hi, *argv, 0))
+ invarg("\"replay-oseqhi\" value is invalid", *argv);
} else if (strcmp(*argv, "flag") == 0) {
NEXT_ARG();
xfrm_state_flag_parse(&req.xsinfo.flags, &argc, &argv);
@@ -434,9 +452,12 @@ parse_algo:
argc--; argv++;
}
- if (replay.seq || replay.oseq)
- addattr_l(&req.n, sizeof(req.buf), XFRMA_REPLAY_VAL,
+ if (replay.state.replay_window || replay.state.seq || replay.state.oseq ||
+ replay.state.seq_hi || replay.state.oseq_hi ) {
+
+ addattr_l(&req.n, sizeof(req.buf), XFRMA_REPLAY_ESN_VAL,
(void *)&replay, sizeof(replay));
+ }
if (!idp) {
fprintf(stderr, "Not enough information: \"ID\" is required\n");
--
1.7.0.4
^ permalink raw reply related
* [RFC] [PATCH 11/11] xfrm: Add user interface for esn and big anti-replay windows
From: Steffen Klassert @ 2010-11-22 10:34 UTC (permalink / raw)
To: Herbert Xu, David Miller
Cc: Andreas Gruenbacher, Alex Badea, netdev, linux-crypto
In-Reply-To: <20101122102455.GC1868@secunet.com>
This patch adds a netlink based user interface to configure
esn and big anti-replay windows. The new netlink attribute
XFRMA_REPLAY_ESN_VAL is used to configure the new implementation.
If the XFRM_STATE_ESN flag is set, we use esn and support for big
anti-replay windows for the configured state. If this flag is not
set we use the new implementation with 32 bit sequence numbers.
A big anti-replay window can be configured in this case anyway.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_state.c | 2 +
net/xfrm/xfrm_user.c | 99 ++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 87 insertions(+), 14 deletions(-)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index a5035c0..fc82563 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -355,6 +355,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
kfree(x->calg);
kfree(x->encap);
kfree(x->coaddr);
+ kfree(x->replay_esn);
+ kfree(x->preplay_esn);
if (x->inner_mode)
xfrm_put_mode(x->inner_mode);
if (x->inner_mode_iaf)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 77452dc..cf6cab2 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -118,6 +118,19 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs)
return 0;
}
+static inline int verify_replay(struct xfrm_usersa_info *p,
+ struct nlattr **attrs)
+{
+ struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
+
+ if (!rt)
+ return 0;
+
+ if (p->replay_window != 0)
+ return -EINVAL;
+
+ return 0;
+}
static int verify_newsa_info(struct xfrm_usersa_info *p,
struct nlattr **attrs)
@@ -207,6 +220,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
goto out;
if ((err = verify_sec_ctx_len(attrs)))
goto out;
+ if ((err = verify_replay(p, attrs)))
+ goto out;
err = -EINVAL;
switch (p->mode) {
@@ -337,6 +352,33 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props,
return 0;
}
+static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn,
+ struct xfrm_replay_state_esn **preplay_esn,
+ struct nlattr *rta)
+{
+ struct xfrm_replay_state_esn *p, *pp, *up;
+
+ if (!rta)
+ return 0;
+
+ up = nla_data(rta);
+
+ p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
+ if (!pp) {
+ kfree(p);
+ return -ENOMEM;
+ }
+
+ *replay_esn = p;
+ *preplay_esn = pp;
+
+ return 0;
+}
+
static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx)
{
int len = 0;
@@ -372,10 +414,20 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs)
{
struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
+ struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
+ if (re) {
+ struct xfrm_replay_state_esn *replay_esn;
+ replay_esn = nla_data(re);
+ memcpy(x->replay_esn, replay_esn,
+ xfrm_replay_state_esn_len(replay_esn));
+ memcpy(x->preplay_esn, replay_esn,
+ xfrm_replay_state_esn_len(replay_esn));
+ }
+
if (rp) {
struct xfrm_replay_state *replay;
replay = nla_data(rp);
@@ -456,13 +508,14 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX])))
goto error;
+ if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn,
+ attrs[XFRMA_REPLAY_ESN_VAL])))
+ goto error;
+
x->km.seq = p->seq;
x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth;
/* sysctl_xfrm_aevent_etime is in 100ms units */
x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M;
- x->preplay.bitmap = 0;
- x->preplay.seq = x->replay.seq+x->replay_maxdiff;
- x->preplay.oseq = x->replay.oseq +x->replay_maxdiff;
if ((err = xfrm_init_replay(x)))
goto error;
@@ -693,6 +746,10 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
if (xfrm_mark_put(skb, &x->mark))
goto nla_put_failure;
+ if (x->replay_esn)
+ NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL,
+ xfrm_replay_state_esn_len(x->replay_esn), x->replay_esn);
+
if (x->security && copy_sec_ctx(x->security, skb) < 0)
goto nla_put_failure;
@@ -1560,10 +1617,14 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
return 0;
}
-static inline size_t xfrm_aevent_msgsize(void)
+static inline size_t xfrm_aevent_msgsize(struct xfrm_state *x)
{
+ size_t replay_size = x->replay_esn ?
+ xfrm_replay_state_esn_len(x->replay_esn) :
+ sizeof(struct xfrm_replay_state);
+
return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id))
- + nla_total_size(sizeof(struct xfrm_replay_state))
+ + nla_total_size(replay_size)
+ nla_total_size(sizeof(struct xfrm_lifetime_cur))
+ nla_total_size(sizeof(struct xfrm_mark))
+ nla_total_size(4) /* XFRM_AE_RTHR */
@@ -1588,7 +1649,13 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve
id->reqid = x->props.reqid;
id->flags = c->data.aevent;
- NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay);
+ if (x->replay_esn)
+ NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL,
+ xfrm_replay_state_esn_len(x->replay_esn),
+ x->replay_esn);
+ else
+ NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay);
+
NLA_PUT(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft);
if (id->flags & XFRM_AE_RTHR)
@@ -1621,16 +1688,16 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
struct xfrm_aevent_id *p = nlmsg_data(nlh);
struct xfrm_usersa_id *id = &p->sa_id;
- r_skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC);
- if (r_skb == NULL)
- return -ENOMEM;
-
mark = xfrm_mark_get(attrs, &m);
x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family);
- if (x == NULL) {
- kfree_skb(r_skb);
+ if (x == NULL)
return -ESRCH;
+
+ r_skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
+ if (r_skb == NULL) {
+ xfrm_state_put(x);
+ return -ENOMEM;
}
/*
@@ -1662,9 +1729,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
struct xfrm_mark m;
struct xfrm_aevent_id *p = nlmsg_data(nlh);
struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
+ struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
- if (!lt && !rp)
+ if (!lt && !rp && !re)
return err;
/* pedantic mode - thou shalt sayeth replaceth */
@@ -2124,6 +2192,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
[XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) },
[XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) },
[XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) },
+ [XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) },
};
static struct xfrm_link {
@@ -2251,7 +2320,7 @@ static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c)
struct net *net = xs_net(x);
struct sk_buff *skb;
- skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC);
+ skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;
@@ -2303,6 +2372,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x)
l += nla_total_size(sizeof(*x->calg));
if (x->encap)
l += nla_total_size(sizeof(*x->encap));
+ if (x->replay_esn)
+ l += nla_total_size(xfrm_replay_state_esn_len(x->replay_esn));
if (x->security)
l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) +
x->security->ctx_len);
--
1.7.0.4
^ permalink raw reply related
* [RFC] [PATCH 10/11] xfrm: Add support for IPsec extended sequence numbers
From: Steffen Klassert @ 2010-11-22 10:33 UTC (permalink / raw)
To: Herbert Xu, David Miller
Cc: Andreas Gruenbacher, Alex Badea, netdev, linux-crypto
In-Reply-To: <20101122102455.GC1868@secunet.com>
This patch adds support for IPsec extended sequence numbers (esn)
as defined in RFC 4303. The bits to manage the anti-replay window
are based on a patch from Alex Badea.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/xfrm.h | 1 +
net/xfrm/xfrm_input.c | 4 +
net/xfrm/xfrm_replay.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 194 insertions(+), 1 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 4b1559a..a6ef001 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1412,6 +1412,7 @@ extern int xfrm_state_delete(struct xfrm_state *x);
extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
extern void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
+extern u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
extern int xfrm_init_replay(struct xfrm_state *x);
extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
extern int xfrm_init_state(struct xfrm_state *x);
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 55d5f5c..872065c 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -107,6 +107,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
struct net *net = dev_net(skb->dev);
int err;
__be32 seq;
+ __be32 seq_hi;
struct xfrm_state *x;
xfrm_address_t *daddr;
struct xfrm_mode *inner_mode;
@@ -184,7 +185,10 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
spin_unlock(&x->lock);
+ seq_hi = htonl(xfrm_replay_seqhi(x, seq));
+
XFRM_SKB_CB(skb)->seq.input.low = seq;
+ XFRM_SKB_CB(skb)->seq.input.hi = seq_hi;
nexthdr = x->type->input(x, skb);
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
index be2c9eb..52433b5 100644
--- a/net/xfrm/xfrm_replay.c
+++ b/net/xfrm/xfrm_replay.c
@@ -20,6 +20,31 @@
#include <net/xfrm.h>
+u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq)
+{
+ u32 seq, seq_hi, bottom;
+ struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+
+ if (!(x->props.flags & XFRM_STATE_ESN))
+ return 0;
+
+ seq = ntohl(net_seq);
+ seq_hi = replay_esn->seq_hi;
+ bottom = replay_esn->seq - replay_esn->replay_window + 1;
+
+ if (likely(replay_esn->seq >= replay_esn->replay_window - 1)) {
+ /* A. same subspace */
+ if (unlikely(seq < bottom))
+ seq_hi++;
+ } else {
+ /* B. window spans two subspaces */
+ if (unlikely(seq >= bottom))
+ seq_hi--;
+ }
+
+ return seq_hi;
+}
+
static void xfrm_replay_notify(struct xfrm_state *x, int event)
{
struct km_event c;
@@ -313,6 +338,160 @@ static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
x->xflags &= ~XFRM_TIME_DEFER;
}
+static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb)
+{
+ int err = 0;
+ struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+ struct net *net = xs_net(x);
+
+ if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
+ XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
+ XFRM_SKB_CB(skb)->seq.output.hi = replay_esn->oseq_hi;
+
+ if (unlikely(replay_esn->oseq == 0)) {
+ XFRM_SKB_CB(skb)->seq.output.hi = ++replay_esn->oseq_hi;
+
+ if (replay_esn->oseq_hi == 0) {
+ replay_esn->oseq--;
+ replay_esn->oseq_hi--;
+ xfrm_audit_state_replay_overflow(x, skb);
+ err = -EOVERFLOW;
+
+ return err;
+ }
+ }
+ if (xfrm_aevent_is_on(net))
+ x->repl->notify(x, XFRM_REPLAY_UPDATE);
+ }
+
+ return err;
+}
+
+static int xfrm_replay_check_esn(struct xfrm_state *x,
+ struct sk_buff *skb, __be32 net_seq)
+{
+ unsigned int bitnr, nr;
+ u32 diff;
+ struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+ u32 seq = ntohl(net_seq);
+ u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+ u32 wsize = replay_esn->replay_window;
+ u32 top = replay_esn->seq;
+ u32 bottom = top - wsize + 1;
+
+ if (unlikely(seq == 0 && replay_esn->seq_hi == 0 &&
+ (replay_esn->seq < replay_esn->replay_window - 1)))
+ goto err;
+
+ diff = top - seq;
+
+ if (likely(top >= wsize - 1)) {
+ /* A. same subspace */
+ if (likely(seq > top) || seq < bottom)
+ return 0;
+ } else {
+ /* B. window spans two subspaces */
+ if (likely(seq > top && seq < bottom))
+ return 0;
+ if (seq >= bottom)
+ diff = ~seq + top + 1;
+ }
+
+ if (diff >= replay_esn->replay_window) {
+ x->stats.replay_window++;
+ goto err;
+ }
+
+ if (pos >= diff) {
+ bitnr = (pos - diff) % replay_esn->replay_window;
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ if (replay_esn->bmp[nr] & (1U << bitnr))
+ goto err_replay;
+ } else {
+ bitnr = replay_esn->replay_window - (diff - pos);
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ if (replay_esn->bmp[nr] & (1U << bitnr))
+ goto err_replay;
+ }
+ return 0;
+
+err_replay:
+ x->stats.replay++;
+err:
+ xfrm_audit_state_replay(x, skb, net_seq);
+ return -EINVAL;
+}
+
+static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
+{
+ unsigned int bitnr, nr, i;
+ int wrap;
+ u32 diff, pos, seq, seq_hi;
+ struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+
+ if (!replay_esn->replay_window)
+ return;
+
+ seq = ntohl(net_seq);
+ pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+ seq_hi = xfrm_replay_seqhi(x, net_seq);
+ wrap = seq_hi - replay_esn->seq_hi;
+
+ if ((!wrap && seq > replay_esn->seq) || wrap > 0) {
+ if (likely(!wrap))
+ diff = seq - replay_esn->seq;
+ else
+ diff = ~replay_esn->seq + seq + 1;
+
+ if (diff < replay_esn->replay_window) {
+ for (i = 1; i < diff; i++) {
+ bitnr = (pos + i) % replay_esn->replay_window;
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ replay_esn->bmp[nr] &= ~(1U << bitnr);
+ }
+
+ bitnr = (pos + diff) % replay_esn->replay_window;
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ replay_esn->bmp[nr] |= (1U << bitnr);
+ } else {
+ nr = replay_esn->replay_window >> 5;
+ for (i = 0; i <= nr; i++)
+ replay_esn->bmp[i] = 0;
+
+ bitnr = (pos + diff) % replay_esn->replay_window;
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ replay_esn->bmp[nr] |= (1U << bitnr);
+ }
+
+ replay_esn->seq = seq;
+
+ if (unlikely(wrap > 0))
+ replay_esn->seq_hi++;
+ } else {
+ diff = replay_esn->seq - seq;
+
+ if (pos >= diff) {
+ bitnr = (pos - diff) % replay_esn->replay_window;
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ replay_esn->bmp[nr] |= (1U << bitnr);
+ } else {
+ bitnr = replay_esn->replay_window - (diff - pos);
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ replay_esn->bmp[nr] |= (1U << bitnr);
+ }
+ }
+
+ if (xfrm_aevent_is_on(xs_net(x)))
+ xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+}
+
static struct xfrm_replay xfrm_replay_legacy = {
.advance = xfrm_replay_advance,
.check = xfrm_replay_check,
@@ -327,9 +506,18 @@ static struct xfrm_replay xfrm_replay_bmp = {
.overflow = xfrm_replay_overflow_bmp,
};
+static struct xfrm_replay xfrm_replay_esn = {
+ .advance = xfrm_replay_advance_esn,
+ .check = xfrm_replay_check_esn,
+ .notify = xfrm_replay_notify_bmp,
+ .overflow = xfrm_replay_overflow_esn,
+};
+
int xfrm_init_replay(struct xfrm_state *x)
{
- if (x->replay_esn)
+ if ((x->props.flags & XFRM_STATE_ESN) && x->replay_esn)
+ x->repl = &xfrm_replay_esn;
+ else if (x->replay_esn)
x->repl = &xfrm_replay_bmp;
else
x->repl = &xfrm_replay_legacy;
--
1.7.0.4
^ permalink raw reply related
* [RFC] [PATCH 09/11] xfrm: Support anti-replay window size bigger than 32 packets
From: Steffen Klassert @ 2010-11-22 10:32 UTC (permalink / raw)
To: Herbert Xu, David Miller
Cc: Andreas Gruenbacher, Alex Badea, netdev, linux-crypto
In-Reply-To: <20101122102455.GC1868@secunet.com>
As it is, the anti-replay bitmap in struct xfrm_replay_state can
only accomodate 32 packets. Even though it is possible to configure
anti-replay window sizes up to 255 packets from userspace. So we
reject any packet with a sequence number within the configured window
but outside the bitmap. With this patch, we represent the anti-replay
window as a bitmap of variable length that can be accessed via the
new struct xfrm_replay_state_esn. Thus, we have no limit on the
window size anymore. To use the new anti-replay window implementantion,
new userspace tools are required. We leave the old implementation
untouched to stay in sync with old userspace tools.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_replay.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 184 insertions(+), 1 deletions(-)
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
index 598ca4c..be2c9eb 100644
--- a/net/xfrm/xfrm_replay.c
+++ b/net/xfrm/xfrm_replay.c
@@ -141,6 +141,178 @@ static void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
}
+static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb)
+{
+ int err = 0;
+ struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+ struct net *net = xs_net(x);
+
+ if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
+ XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
+ if (unlikely(replay_esn->oseq == 0)) {
+ replay_esn->oseq--;
+ xfrm_audit_state_replay_overflow(x, skb);
+ err = -EOVERFLOW;
+
+ return err;
+ }
+ if (xfrm_aevent_is_on(net))
+ x->repl->notify(x, XFRM_REPLAY_UPDATE);
+ }
+
+ return err;
+}
+
+static int xfrm_replay_check_bmp(struct xfrm_state *x,
+ struct sk_buff *skb, __be32 net_seq)
+{
+ unsigned int bitnr, nr;
+ struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+ u32 seq = ntohl(net_seq);
+ u32 diff = replay_esn->seq - seq;
+ u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+
+ if (unlikely(seq == 0))
+ goto err;
+
+ if (likely(seq > replay_esn->seq))
+ return 0;
+
+ if (diff >= replay_esn->replay_window) {
+ x->stats.replay_window++;
+ goto err;
+ }
+
+ if (pos >= diff) {
+ bitnr = (pos - diff) % replay_esn->replay_window;
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ if (replay_esn->bmp[nr] & (1U << bitnr))
+ goto err_replay;
+ } else {
+ bitnr = replay_esn->replay_window - (diff - pos);
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ if (replay_esn->bmp[nr] & (1U << bitnr))
+ goto err_replay;
+ }
+ return 0;
+
+err_replay:
+ x->stats.replay++;
+err:
+ xfrm_audit_state_replay(x, skb, net_seq);
+ return -EINVAL;
+}
+
+static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq)
+{
+ unsigned int bitnr, nr, i;
+ u32 diff;
+ struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+ u32 seq = ntohl(net_seq);
+ u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+
+ if (!replay_esn->replay_window)
+ return;
+
+ if (seq > replay_esn->seq) {
+ diff = seq - replay_esn->seq;
+
+ if (diff < replay_esn->replay_window) {
+ for (i = 1; i < diff; i++) {
+ bitnr = (pos + i) % replay_esn->replay_window;
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ replay_esn->bmp[nr] &= ~(1U << bitnr);
+ }
+
+ bitnr = (pos + diff) % replay_esn->replay_window;
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ replay_esn->bmp[nr] |= (1U << bitnr);
+ } else {
+ nr = replay_esn->replay_window >> 5;
+ for (i = 0; i <= nr; i++)
+ replay_esn->bmp[i] = 0;
+
+ bitnr = (pos + diff) % replay_esn->replay_window;
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ replay_esn->bmp[nr] |= (1U << bitnr);
+ }
+
+ replay_esn->seq = seq;
+ } else {
+ diff = replay_esn->seq - seq;
+
+ if (pos >= diff) {
+ bitnr = (pos - diff) % replay_esn->replay_window;
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ replay_esn->bmp[nr] |= (1U << bitnr);
+ } else {
+ bitnr = replay_esn->replay_window - (diff - pos);
+ nr = bitnr >> 5;
+ bitnr = bitnr & 0x1F;
+ replay_esn->bmp[nr] |= (1U << bitnr);
+ }
+ }
+
+ if (xfrm_aevent_is_on(xs_net(x)))
+ xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+}
+
+static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
+{
+ struct km_event c;
+ struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+ struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn;
+
+ /* we send notify messages in case
+ * 1. we updated on of the sequence numbers, and the seqno difference
+ * is at least x->replay_maxdiff, in this case we also update the
+ * timeout of our timer function
+ * 2. if x->replay_maxage has elapsed since last update,
+ * and there were changes
+ *
+ * The state structure must be locked!
+ */
+
+ switch (event) {
+ case XFRM_REPLAY_UPDATE:
+ if (x->replay_maxdiff &&
+ (replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) &&
+ (replay_esn->oseq - preplay_esn->oseq < x->replay_maxdiff)) {
+ if (x->xflags & XFRM_TIME_DEFER)
+ event = XFRM_REPLAY_TIMEOUT;
+ else
+ return;
+ }
+
+ break;
+
+ case XFRM_REPLAY_TIMEOUT:
+ if (memcmp(x->replay_esn, x->preplay_esn,
+ xfrm_replay_state_esn_len(replay_esn)) == 0) {
+ x->xflags |= XFRM_TIME_DEFER;
+ return;
+ }
+
+ break;
+ }
+
+ memcpy(x->preplay_esn, x->replay_esn,
+ xfrm_replay_state_esn_len(replay_esn));
+ c.event = XFRM_MSG_NEWAE;
+ c.data.aevent = event;
+ km_state_notify(x, &c);
+
+ if (x->replay_maxage &&
+ !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
+ x->xflags &= ~XFRM_TIME_DEFER;
+}
+
static struct xfrm_replay xfrm_replay_legacy = {
.advance = xfrm_replay_advance,
.check = xfrm_replay_check,
@@ -148,9 +320,20 @@ static struct xfrm_replay xfrm_replay_legacy = {
.overflow = xfrm_replay_overflow,
};
+static struct xfrm_replay xfrm_replay_bmp = {
+ .advance = xfrm_replay_advance_bmp,
+ .check = xfrm_replay_check_bmp,
+ .notify = xfrm_replay_notify_bmp,
+ .overflow = xfrm_replay_overflow_bmp,
+};
+
int xfrm_init_replay(struct xfrm_state *x)
{
- x->repl = &xfrm_replay_legacy;
+ if (x->replay_esn)
+ x->repl = &xfrm_replay_bmp;
+ else
+ x->repl = &xfrm_replay_legacy;
+
return 0;
}
--
1.7.0.4
^ permalink raw reply related
* [RFC] [PATCH 08/11] xfrm: Move IPsec replay detection functions to a separate file
From: Steffen Klassert @ 2010-11-22 10:31 UTC (permalink / raw)
To: Herbert Xu, David Miller
Cc: Andreas Gruenbacher, Alex Badea, netdev, linux-crypto
In-Reply-To: <20101122102455.GC1868@secunet.com>
To support multiple versions of replay detection, we move the replay
detection functions to a separate file and make them accessible
via function pointers contained in the struct xfrm_replay.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/xfrm.h | 24 ++++++-
net/xfrm/Makefile | 2 +-
net/xfrm/xfrm_input.c | 5 +-
net/xfrm/xfrm_output.c | 15 +----
net/xfrm/xfrm_replay.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++
net/xfrm/xfrm_state.c | 111 +---------------------------------
net/xfrm/xfrm_user.c | 4 +-
7 files changed, 190 insertions(+), 128 deletions(-)
create mode 100644 net/xfrm/xfrm_replay.c
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 7f196e5..4b1559a 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -190,6 +190,9 @@ struct xfrm_state {
struct xfrm_replay_state preplay;
struct xfrm_replay_state_esn *preplay_esn;
+ /* The functions for replay detection. */
+ struct xfrm_replay *repl;
+
/* internal flag that only holds state for delayed aevent at the
* moment
*/
@@ -259,6 +262,15 @@ struct km_event {
struct net *net;
};
+struct xfrm_replay {
+ void (*advance)(struct xfrm_state *x, __be32 net_seq);
+ int (*check)(struct xfrm_state *x,
+ struct sk_buff *skb,
+ __be32 net_seq);
+ void (*notify)(struct xfrm_state *x, int event);
+ int (*overflow)(struct xfrm_state *x, struct sk_buff *skb);
+};
+
struct net_device;
struct xfrm_type;
struct xfrm_dst;
@@ -682,6 +694,8 @@ extern void xfrm_audit_state_delete(struct xfrm_state *x, int result,
u32 auid, u32 ses, u32 secid);
extern void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
struct sk_buff *skb);
+extern void xfrm_audit_state_replay(struct xfrm_state *x,
+ struct sk_buff *skb, __be32 net_seq);
extern void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family);
extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
__be32 net_spi, __be32 net_seq);
@@ -714,6 +728,11 @@ static inline void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
{
}
+static inline void xfrm_audit_state_replay(struct xfrm_state *x,
+ struct sk_buff *skb, __be32 net_seq)
+{
+}
+
static inline void xfrm_audit_state_notfound_simple(struct sk_buff *skb,
u16 family)
{
@@ -1393,10 +1412,7 @@ extern int xfrm_state_delete(struct xfrm_state *x);
extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
extern void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
-extern int xfrm_replay_check(struct xfrm_state *x,
- struct sk_buff *skb, __be32 seq);
-extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
-extern void xfrm_replay_notify(struct xfrm_state *x, int event);
+extern int xfrm_init_replay(struct xfrm_state *x);
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);
diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile
index c631047..aa429ee 100644
--- a/net/xfrm/Makefile
+++ b/net/xfrm/Makefile
@@ -4,7 +4,7 @@
obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
xfrm_input.o xfrm_output.o xfrm_algo.o \
- xfrm_sysctl.o
+ xfrm_sysctl.o xfrm_replay.o
obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
obj-$(CONFIG_XFRM_USER) += xfrm_user.o
obj-$(CONFIG_XFRM_IPCOMP) += xfrm_ipcomp.o
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index b173b7f..55d5f5c 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -172,7 +172,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
goto drop_unlock;
}
- if (x->props.replay_window && xfrm_replay_check(x, skb, seq)) {
+ if (x->props.replay_window && x->repl->check(x, skb, seq)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR);
goto drop_unlock;
}
@@ -206,8 +206,7 @@ resume:
/* only the first xfrm gets the encap type */
encap_type = 0;
- if (x->props.replay_window)
- xfrm_replay_advance(x, seq);
+ x->repl->advance(x, seq);
x->curlft.bytes += skb->len;
x->curlft.packets++;
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 4b63776..1aba03f 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -67,17 +67,10 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
goto error;
}
- if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
- XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq;
- if (unlikely(x->replay.oseq == 0)) {
- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATESEQERROR);
- x->replay.oseq--;
- xfrm_audit_state_replay_overflow(x, skb);
- err = -EOVERFLOW;
- goto error;
- }
- if (xfrm_aevent_is_on(net))
- xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+ err = x->repl->overflow(x, skb);
+ if (err) {
+ XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATESEQERROR);
+ goto error;
}
x->curlft.bytes += skb->len;
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
new file mode 100644
index 0000000..598ca4c
--- /dev/null
+++ b/net/xfrm/xfrm_replay.c
@@ -0,0 +1,157 @@
+/*
+ * xfrm_replay.c - xfrm replay detection, derived from xfrm_state.c.
+ *
+ * Copyright (C) 2009 secunet Security Networks AG
+ * Copyright (C) 2009 Steffen Klassert <steffen.klassert@secunet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <net/xfrm.h>
+
+static void xfrm_replay_notify(struct xfrm_state *x, int event)
+{
+ struct km_event c;
+ /* we send notify messages in case
+ * 1. we updated on of the sequence numbers, and the seqno difference
+ * is at least x->replay_maxdiff, in this case we also update the
+ * timeout of our timer function
+ * 2. if x->replay_maxage has elapsed since last update,
+ * and there were changes
+ *
+ * The state structure must be locked!
+ */
+
+ switch (event) {
+ case XFRM_REPLAY_UPDATE:
+ if (x->replay_maxdiff &&
+ (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
+ (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
+ if (x->xflags & XFRM_TIME_DEFER)
+ event = XFRM_REPLAY_TIMEOUT;
+ else
+ return;
+ }
+
+ break;
+
+ case XFRM_REPLAY_TIMEOUT:
+ if (memcmp(&x->replay, &x->preplay,
+ sizeof(struct xfrm_replay_state)) == 0) {
+ x->xflags |= XFRM_TIME_DEFER;
+ return;
+ }
+
+ break;
+ }
+
+ memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
+ c.event = XFRM_MSG_NEWAE;
+ c.data.aevent = event;
+ km_state_notify(x, &c);
+
+ if (x->replay_maxage &&
+ !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
+ x->xflags &= ~XFRM_TIME_DEFER;
+}
+
+static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
+{
+ int err = 0;
+ struct net *net = xs_net(x);
+
+ if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
+ XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq;
+ if (unlikely(x->replay.oseq == 0)) {
+ x->replay.oseq--;
+ xfrm_audit_state_replay_overflow(x, skb);
+ err = -EOVERFLOW;
+
+ return err;
+ }
+ if (xfrm_aevent_is_on(net))
+ x->repl->notify(x, XFRM_REPLAY_UPDATE);
+ }
+
+ return err;
+}
+
+static int xfrm_replay_check(struct xfrm_state *x,
+ struct sk_buff *skb, __be32 net_seq)
+{
+ u32 diff;
+ u32 seq = ntohl(net_seq);
+
+ if (unlikely(seq == 0))
+ goto err;
+
+ if (likely(seq > x->replay.seq))
+ return 0;
+
+ diff = x->replay.seq - seq;
+ if (diff >= min_t(unsigned int, x->props.replay_window,
+ sizeof(x->replay.bitmap) * 8)) {
+ x->stats.replay_window++;
+ goto err;
+ }
+
+ if (x->replay.bitmap & (1U << diff)) {
+ x->stats.replay++;
+ goto err;
+ }
+ return 0;
+
+err:
+ xfrm_audit_state_replay(x, skb, net_seq);
+ return -EINVAL;
+}
+
+static void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
+{
+ u32 diff;
+ u32 seq = ntohl(net_seq);
+
+ if (!x->props.replay_window)
+ return;
+
+ if (seq > x->replay.seq) {
+ diff = seq - x->replay.seq;
+ if (diff < x->props.replay_window)
+ x->replay.bitmap = ((x->replay.bitmap) << diff) | 1;
+ else
+ x->replay.bitmap = 1;
+ x->replay.seq = seq;
+ } else {
+ diff = x->replay.seq - seq;
+ x->replay.bitmap |= (1U << diff);
+ }
+
+ if (xfrm_aevent_is_on(xs_net(x)))
+ xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+}
+
+static struct xfrm_replay xfrm_replay_legacy = {
+ .advance = xfrm_replay_advance,
+ .check = xfrm_replay_check,
+ .notify = xfrm_replay_notify,
+ .overflow = xfrm_replay_overflow,
+};
+
+int xfrm_init_replay(struct xfrm_state *x)
+{
+ x->repl = &xfrm_replay_legacy;
+
+ return 0;
+}
+EXPORT_SYMBOL(xfrm_init_replay);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index eb96ce5..a5035c0 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -42,13 +42,6 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
-#ifdef CONFIG_AUDITSYSCALL
-static void xfrm_audit_state_replay(struct xfrm_state *x,
- struct sk_buff *skb, __be32 net_seq);
-#else
-#define xfrm_audit_state_replay(x, s, sq) do { ; } while (0)
-#endif /* CONFIG_AUDITSYSCALL */
-
static inline unsigned int xfrm_dst_hash(struct net *net,
xfrm_address_t *daddr,
xfrm_address_t *saddr,
@@ -1609,54 +1602,6 @@ void xfrm_state_walk_done(struct xfrm_state_walk *walk)
}
EXPORT_SYMBOL(xfrm_state_walk_done);
-
-void xfrm_replay_notify(struct xfrm_state *x, int event)
-{
- struct km_event c;
- /* we send notify messages in case
- * 1. we updated on of the sequence numbers, and the seqno difference
- * is at least x->replay_maxdiff, in this case we also update the
- * timeout of our timer function
- * 2. if x->replay_maxage has elapsed since last update,
- * and there were changes
- *
- * The state structure must be locked!
- */
-
- switch (event) {
- case XFRM_REPLAY_UPDATE:
- if (x->replay_maxdiff &&
- (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
- (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
- if (x->xflags & XFRM_TIME_DEFER)
- event = XFRM_REPLAY_TIMEOUT;
- else
- return;
- }
-
- break;
-
- case XFRM_REPLAY_TIMEOUT:
- if ((x->replay.seq == x->preplay.seq) &&
- (x->replay.bitmap == x->preplay.bitmap) &&
- (x->replay.oseq == x->preplay.oseq)) {
- x->xflags |= XFRM_TIME_DEFER;
- return;
- }
-
- break;
- }
-
- memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
- c.event = XFRM_MSG_NEWAE;
- c.data.aevent = event;
- km_state_notify(x, &c);
-
- if (x->replay_maxage &&
- !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
- x->xflags &= ~XFRM_TIME_DEFER;
-}
-
static void xfrm_replay_timer_handler(unsigned long data)
{
struct xfrm_state *x = (struct xfrm_state*)data;
@@ -1665,7 +1610,7 @@ static void xfrm_replay_timer_handler(unsigned long data)
if (x->km.state == XFRM_STATE_VALID) {
if (xfrm_aevent_is_on(xs_net(x)))
- xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
+ x->repl->notify(x, XFRM_REPLAY_TIMEOUT);
else
x->xflags |= XFRM_TIME_DEFER;
}
@@ -1673,57 +1618,6 @@ static void xfrm_replay_timer_handler(unsigned long data)
spin_unlock(&x->lock);
}
-int xfrm_replay_check(struct xfrm_state *x,
- struct sk_buff *skb, __be32 net_seq)
-{
- u32 diff;
- u32 seq = ntohl(net_seq);
-
- if (unlikely(seq == 0))
- goto err;
-
- if (likely(seq > x->replay.seq))
- return 0;
-
- diff = x->replay.seq - seq;
- if (diff >= min_t(unsigned int, x->props.replay_window,
- sizeof(x->replay.bitmap) * 8)) {
- x->stats.replay_window++;
- goto err;
- }
-
- if (x->replay.bitmap & (1U << diff)) {
- x->stats.replay++;
- goto err;
- }
- return 0;
-
-err:
- xfrm_audit_state_replay(x, skb, net_seq);
- return -EINVAL;
-}
-
-void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
-{
- u32 diff;
- u32 seq = ntohl(net_seq);
-
- if (seq > x->replay.seq) {
- diff = seq - x->replay.seq;
- if (diff < x->props.replay_window)
- x->replay.bitmap = ((x->replay.bitmap) << diff) | 1;
- else
- x->replay.bitmap = 1;
- x->replay.seq = seq;
- } else {
- diff = x->replay.seq - seq;
- x->replay.bitmap |= (1U << diff);
- }
-
- if (xfrm_aevent_is_on(xs_net(x)))
- xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
-}
-
static LIST_HEAD(xfrm_km_list);
static DEFINE_RWLOCK(xfrm_km_lock);
@@ -2236,7 +2130,7 @@ void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
}
EXPORT_SYMBOL_GPL(xfrm_audit_state_replay_overflow);
-static void xfrm_audit_state_replay(struct xfrm_state *x,
+void xfrm_audit_state_replay(struct xfrm_state *x,
struct sk_buff *skb, __be32 net_seq)
{
struct audit_buffer *audit_buf;
@@ -2251,6 +2145,7 @@ static void xfrm_audit_state_replay(struct xfrm_state *x,
spi, spi, ntohl(net_seq));
audit_log_end(audit_buf);
}
+EXPORT_SYMBOL_GPL(xfrm_audit_state_replay);
void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family)
{
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 8bae6b2..77452dc 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -464,8 +464,10 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
x->preplay.seq = x->replay.seq+x->replay_maxdiff;
x->preplay.oseq = x->replay.oseq +x->replay_maxdiff;
- /* override default values from above */
+ if ((err = xfrm_init_replay(x)))
+ goto error;
+ /* override default values from above */
xfrm_update_ae_params(x, attrs);
return x;
--
1.7.0.4
^ permalink raw reply related
* [RFC] [PATCH 07/11] esp6: Add support for IPsec extended sequence numbers
From: Steffen Klassert @ 2010-11-22 10:31 UTC (permalink / raw)
To: Herbert Xu, David Miller
Cc: Andreas Gruenbacher, Alex Badea, netdev, linux-crypto
In-Reply-To: <20101122102455.GC1868@secunet.com>
this patch adds IPsec extended sequence numbers support to esp6.
We use the authencesn crypto algorithm to handle esp with separate
encryption/authentication algorithms.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv6/esp6.c | 103 ++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 84 insertions(+), 19 deletions(-)
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 672cb69..e018dfa 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -52,16 +52,20 @@ struct esp_skb_cb {
/*
* 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.
+ * For alignment considerations the upper 32 bits of the sequence number are
+ * placed at the front, if present. Followed by the IV, 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)
+static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqihlen)
{
unsigned int len;
- len = crypto_aead_ivsize(aead);
+ len = seqihlen;
+
+ len += crypto_aead_ivsize(aead);
+
if (len) {
len += crypto_aead_alignmask(aead) &
~(crypto_tfm_ctx_alignment() - 1);
@@ -76,10 +80,16 @@ static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags)
return kmalloc(len, GFP_ATOMIC);
}
-static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp)
+static inline __be32 *esp_tmp_seqhi(void *tmp)
+{
+ return PTR_ALIGN((__be32 *)tmp, __alignof__(__be32));
+}
+
+static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int seqhilen)
{
return crypto_aead_ivsize(aead) ?
- PTR_ALIGN((u8 *)tmp, crypto_aead_alignmask(aead) + 1) : tmp;
+ PTR_ALIGN((u8 *)tmp + seqhilen,
+ crypto_aead_alignmask(aead) + 1) : tmp + seqhilen;
}
static inline struct aead_givcrypt_request *esp_tmp_givreq(
@@ -141,8 +151,12 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
int clen;
int alen;
int nfrags;
+ int assoclen;
+ int sglists;
+ int seqhilen;
u8 *iv;
u8 *tail;
+ __be32 *seqhi;
struct esp_data *esp = x->data;
/* skb is pure payload to encrypt */
@@ -163,14 +177,25 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
goto error;
nfrags = err;
- tmp = esp_alloc_tmp(aead, nfrags + 1);
+ assoclen = sizeof(*esph);
+ sglists = 1;
+ seqhilen = 0;
+
+ if (x->props.flags & XFRM_STATE_ESN) {
+ sglists++;
+ seqhilen += sizeof(__be32);
+ assoclen += seqhilen;
+ }
+
+ tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
if (!tmp)
goto error;
- iv = esp_tmp_iv(aead, tmp);
+ seqhi = esp_tmp_seqhi(tmp);
+ iv = esp_tmp_iv(aead, tmp, seqhilen);
req = esp_tmp_givreq(aead, iv);
asg = esp_givreq_sg(aead, req);
- sg = asg + 1;
+ sg = asg + sglists;
/* Fill padding... */
tail = skb_tail_pointer(trailer);
@@ -194,11 +219,18 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
skb_to_sgvec(skb, sg,
esph->enc_data + crypto_aead_ivsize(aead) - skb->data,
clen + alen);
- sg_init_one(asg, esph, sizeof(*esph));
+
+ if ((x->props.flags & XFRM_STATE_ESN)) {
+ sg_init_table(asg, 2);
+ sg_set_buf(asg, esph, sizeof(*esph));
+ *seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
+ sg_set_buf(asg + 1, seqhi, seqhilen);
+ } else
+ 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_assoc(req, asg, assoclen);
aead_givcrypt_set_giv(req, esph->enc_data,
XFRM_SKB_CB(skb)->seq.output.low);
@@ -276,8 +308,12 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
struct sk_buff *trailer;
int elen = skb->len - sizeof(*esph) - crypto_aead_ivsize(aead);
int nfrags;
+ int assoclen;
+ int sglists;
+ int seqhilen;
int ret = 0;
void *tmp;
+ __be32 *seqhi;
u8 *iv;
struct scatterlist *sg;
struct scatterlist *asg;
@@ -298,12 +334,24 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
}
ret = -ENOMEM;
- tmp = esp_alloc_tmp(aead, nfrags + 1);
+
+ assoclen = sizeof(*esph);
+ sglists = 1;
+ seqhilen = 0;
+
+ if (x->props.flags & XFRM_STATE_ESN) {
+ sglists++;
+ seqhilen += sizeof(__be32);
+ assoclen += seqhilen;
+ }
+
+ tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
if (!tmp)
goto out;
ESP_SKB_CB(skb)->tmp = tmp;
- iv = esp_tmp_iv(aead, tmp);
+ seqhi = esp_tmp_seqhi(tmp);
+ iv = esp_tmp_iv(aead, tmp, seqhilen);
req = esp_tmp_req(aead, iv);
asg = esp_req_sg(aead, req);
sg = asg + 1;
@@ -317,11 +365,18 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
sg_init_table(sg, nfrags);
skb_to_sgvec(skb, sg, sizeof(*esph) + crypto_aead_ivsize(aead), elen);
- sg_init_one(asg, esph, sizeof(*esph));
+
+ if ((x->props.flags & XFRM_STATE_ESN)) {
+ sg_init_table(asg, 2);
+ sg_set_buf(asg, esph, sizeof(*esph));
+ *seqhi = XFRM_SKB_CB(skb)->seq.input.hi;
+ sg_set_buf(asg + 1, seqhi, seqhilen);
+ } else
+ 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));
+ aead_request_set_assoc(req, asg, assoclen);
ret = crypto_aead_decrypt(req);
if (ret == -EINPROGRESS)
@@ -427,10 +482,20 @@ static int esp_init_authenc(struct xfrm_state *x)
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)
- goto error;
+
+ if ((x->props.flags & XFRM_STATE_ESN)) {
+ if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
+ "authencesn(%s,%s)",
+ x->aalg ? x->aalg->alg_name : "digest_null",
+ x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
+ goto error;
+ } else {
+ 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)
+ goto error;
+ }
aead = crypto_alloc_aead(authenc_name, 0, 0);
err = PTR_ERR(aead);
--
1.7.0.4
^ permalink raw reply related
* [RFC] [PATCH 06/11] esp4: Add support for IPsec extended sequence numbers
From: Steffen Klassert @ 2010-11-22 10:30 UTC (permalink / raw)
To: Herbert Xu, David Miller
Cc: Andreas Gruenbacher, Alex Badea, netdev, linux-crypto
In-Reply-To: <20101122102455.GC1868@secunet.com>
This patch adds IPsec extended sequence numbers support to esp4.
We use the authencesn crypto algorithm to handle esp with separate
encryption/authentication algorithms.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/esp4.c | 98 ++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 80 insertions(+), 18 deletions(-)
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index f986aee..1a4ac47 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -31,11 +31,14 @@ struct esp_skb_cb {
*
* TODO: Use spare space in skb for this where possible.
*/
-static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags)
+static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqhilen)
{
unsigned int len;
- len = crypto_aead_ivsize(aead);
+ len = seqhilen;
+
+ len += crypto_aead_ivsize(aead);
+
if (len) {
len += crypto_aead_alignmask(aead) &
~(crypto_tfm_ctx_alignment() - 1);
@@ -50,10 +53,15 @@ static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags)
return kmalloc(len, GFP_ATOMIC);
}
-static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp)
+static inline __be32 *esp_tmp_seqhi(void *tmp)
+{
+ return PTR_ALIGN((__be32 *)tmp, __alignof__(__be32));
+}
+static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int seqhilen)
{
return crypto_aead_ivsize(aead) ?
- PTR_ALIGN((u8 *)tmp, crypto_aead_alignmask(aead) + 1) : tmp;
+ PTR_ALIGN((u8 *)tmp + seqhilen,
+ crypto_aead_alignmask(aead) + 1) : tmp + seqhilen;
}
static inline struct aead_givcrypt_request *esp_tmp_givreq(
@@ -118,6 +126,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
int clen;
int alen;
int nfrags;
+ int assoclen;
+ int sglists;
+ int seqhilen;
+ __be32 *seqhi;
/* skb is pure payload to encrypt */
@@ -139,14 +151,25 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
goto error;
nfrags = err;
- tmp = esp_alloc_tmp(aead, nfrags + 1);
+ assoclen = sizeof(*esph);
+ sglists = 1;
+ seqhilen = 0;
+
+ if (x->props.flags & XFRM_STATE_ESN) {
+ sglists++;
+ seqhilen += sizeof(__be32);
+ assoclen += seqhilen;
+ }
+
+ tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
if (!tmp)
goto error;
- iv = esp_tmp_iv(aead, tmp);
+ seqhi = esp_tmp_seqhi(tmp);
+ iv = esp_tmp_iv(aead, tmp, seqhilen);
req = esp_tmp_givreq(aead, iv);
asg = esp_givreq_sg(aead, req);
- sg = asg + 1;
+ sg = asg + sglists;
/* Fill padding... */
tail = skb_tail_pointer(trailer);
@@ -205,11 +228,18 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
skb_to_sgvec(skb, sg,
esph->enc_data + crypto_aead_ivsize(aead) - skb->data,
clen + alen);
- sg_init_one(asg, esph, sizeof(*esph));
+
+ if ((x->props.flags & XFRM_STATE_ESN)) {
+ sg_init_table(asg, 2);
+ sg_set_buf(asg, esph, sizeof(*esph));
+ *seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
+ sg_set_buf(asg + 1, seqhi, seqhilen);
+ } else
+ 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_assoc(req, asg, assoclen);
aead_givcrypt_set_giv(req, esph->enc_data,
XFRM_SKB_CB(skb)->seq.output.low);
@@ -330,6 +360,10 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
struct sk_buff *trailer;
int elen = skb->len - sizeof(*esph) - crypto_aead_ivsize(aead);
int nfrags;
+ int assoclen;
+ int sglists;
+ int seqhilen;
+ __be32 *seqhi;
void *tmp;
u8 *iv;
struct scatterlist *sg;
@@ -346,16 +380,27 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
goto out;
nfrags = err;
+ assoclen = sizeof(*esph);
+ sglists = 1;
+ seqhilen = 0;
+
+ if (x->props.flags & XFRM_STATE_ESN) {
+ sglists++;
+ seqhilen += sizeof(__be32);
+ assoclen += seqhilen;
+ }
+
err = -ENOMEM;
- tmp = esp_alloc_tmp(aead, nfrags + 1);
+ tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
if (!tmp)
goto out;
ESP_SKB_CB(skb)->tmp = tmp;
- iv = esp_tmp_iv(aead, tmp);
+ seqhi = esp_tmp_seqhi(tmp);
+ iv = esp_tmp_iv(aead, tmp, seqhilen);
req = esp_tmp_req(aead, iv);
asg = esp_req_sg(aead, req);
- sg = asg + 1;
+ sg = asg + sglists;
skb->ip_summed = CHECKSUM_NONE;
@@ -366,11 +411,18 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
sg_init_table(sg, nfrags);
skb_to_sgvec(skb, sg, sizeof(*esph) + crypto_aead_ivsize(aead), elen);
- sg_init_one(asg, esph, sizeof(*esph));
+
+ if ((x->props.flags & XFRM_STATE_ESN)) {
+ sg_init_table(asg, 2);
+ sg_set_buf(asg, esph, sizeof(*esph));
+ *seqhi = XFRM_SKB_CB(skb)->seq.input.hi;
+ sg_set_buf(asg + 1, seqhi, seqhilen);
+ } else
+ 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));
+ aead_request_set_assoc(req, asg, assoclen);
err = crypto_aead_decrypt(req);
if (err == -EINPROGRESS)
@@ -484,10 +536,20 @@ static int esp_init_authenc(struct xfrm_state *x)
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)
- goto error;
+
+ if ((x->props.flags & XFRM_STATE_ESN)) {
+ if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
+ "authencesn(%s,%s)",
+ x->aalg ? x->aalg->alg_name : "digest_null",
+ x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
+ goto error;
+ } else {
+ 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)
+ goto error;
+ }
aead = crypto_alloc_aead(authenc_name, 0, 0);
err = PTR_ERR(aead);
--
1.7.0.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox