|
|
|
Re: Query on skb headroom and bridging ethernet and wlan | |
| [Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] |
|
Hello David/Johannes,
Any thoughts/inputs on this?
Thanks
Yogesh
On Thu, Apr 14, 2011 at 01:46:45AM -0700, Yogesh Ashok Powar wrote:
> Hello All,
> We have observed significant throughput drop on TX path on
> embedded system when bridging packets from ethernet to wireless side.
> Our drivers on ethernet and wireless are MV643XX and MWL8K, respectively.
>
> We found that mac80211 end up calling ieee80211_skb_resize (from
> net/mac80211/tx.c) for every data packet as the skb_headroom was few
> bytes short than the actual requirement.
>
> We are considering two possible solutions to the problem:
> 1. Use the scheme developed by Johannes and David.
> 2. Address the issue by tuning the required extra tx headroom in the mwl8k
> wireless driver.
>
> The scheme developed by Johannes and David is discussed at the thread started by
> Johannes on "mac80211: assign needed_headroom/tailroom for netdevs".
>
> Can be seen at
> http://kerneltrap.com/mailarchive/linux-netdev/2008/5/4/1719104
>
> In one of the reply, David Miller has proposed a solution for such cases; please
> see http://lists.openwall.net/netdev/2008/05/05/133
>
> For completeness I am adding David's patch after few modifications, mainly
> replacing old variables with the updated ones to make compilation error free.
>
> With the patch below and a change in ethernet driver to use netdev_alloc_skb,
> overhead of ieee80211_skb_resize can be avoided on our setup.
>
> We would like to know, why is this patch (or something similar) not upstream?
> Or, are there issues that are difficult to resolve?
>
> Thanks
> Yogesh Powar
>
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 0249fe7..1827ef0 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -1193,6 +1193,7 @@ struct net_device {
> * use it if/when necessary, to
> * avoid dirtying this cache line.
> */
> + unsigned int rx_alloc_extra;
>
> struct net_device *master; /* Pointer to master device of a group,
> * which this device is member of.
> diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
> index ee64287..cb2a462 100644
> --- a/net/bridge/br_forward.c
> +++ b/net/bridge/br_forward.c
> @@ -46,6 +46,23 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
> (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb))) {
> kfree_skb(skb);
> } else {
> + unsigned int headroom = skb_headroom(skb);
> + unsigned int hh_len = LL_RESERVED_SPACE(skb->dev);
> +
> + if (headroom < hh_len) {
> + struct net_device *in_dev;
> + unsigned int extra;
> +
> + in_dev = __dev_get_by_index(dev_net(skb->dev), skb->skb_iif);
> +
> + BUG_ON(!in_dev);
> +
> + extra = hh_len - headroom;
> +
> + if (extra > in_dev->rx_alloc_extra)
> + in_dev->rx_alloc_extra = extra;
> + }
> +
> skb_push(skb, ETH_HLEN);
> dev_queue_xmit(skb);
> }
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 801dd08..d9cbd4f 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -249,10 +249,11 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
> unsigned int length, gfp_t gfp_mask)
> {
> struct sk_buff *skb;
> + unsigned int extra = dev->rx_alloc_extra + NET_SKB_PAD;
>
> - skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, NUMA_NO_NODE);
> + skb = __alloc_skb(length + extra, gfp_mask, 0, NUMA_NO_NODE);
> if (likely(skb)) {
> - skb_reserve(skb, NET_SKB_PAD);
> + skb_reserve(skb, extra);
> skb->dev = dev;
> }
> return skb;
> --
--
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
[Netdev] [Ethernet Bridging] [Linux 802.1Q VLAN] [Linux Wireless] [Kernel Newbies] [Security] [Linux for Hams] [Netfilter] [Git] [Bugtraq] [Photo] [Yosemite] [Yosemite News and Information] [MIPS Linux] [ARM Linux] [Linux RAID] [Linux PCI] [Linux Admin] [Samba] [Video 4 Linux] [Linux Resources]