Netdev List
 help / color / mirror / Atom feed
* Re: suspicious RCU usage in net/ipv4/ip_tunnel.c:80
From: Eric Dumazet @ 2014-01-12 17:44 UTC (permalink / raw)
  To: Cong Wang; +Cc: Tom Herbert, netdev
In-Reply-To: <CAHA+R7OMM9ndy4hXF4rJBsA_Rb0KZ-MonuvE++wgzO_oMbo+eQ@mail.gmail.com>

On Sat, 2014-01-11 at 11:15 -0800, Cong Wang wrote:
> On Fri, Jan 10, 2014 at 5:21 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> >
> > Nope, the synchronize_rcu() is not needed here.
> 
> OK.
> 
> >
> > Please use following sparse ready patch, thanks :
> >
> > diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
> > index d3929a69f008..6eda759b5c4b 100644
> > --- a/net/ipv4/ip_tunnel.c
> > +++ b/net/ipv4/ip_tunnel.c
> > @@ -77,10 +77,11 @@ static inline void __tunnel_dst_set(struct ip_tunnel_dst *idst,
> >                 dst = NULL;
> >
> >         spin_lock_bh(&idst->lock);
> > -       old_dst = rcu_dereference(idst->dst);
> > +       old_dst = rcu_dereference_protected(idst->dst,
> > +                                           lockdep_is_held(&idst->lock));
> >         rcu_assign_pointer(idst->dst, dst);
> > -       dst_release(old_dst);
> >         spin_unlock_bh(&idst->lock);
> > +       dst_release(old_dst);
> 
> Do you really need a rcu_dereference*() here? We don't dereference
> it inside spin_lock protection.

Please read rcu_dereference_protected() documentation in
include/linux/rcupdate.h

Also you can run sparse, with CONFIG_SPARSE_RCU_POINTER=y in
your .config

make C=2 net/ipv4/ip_tunnel.o

And then you'll know the answer to this question.

^ permalink raw reply

* Re: [PATCH 3/5] net: mvneta: do not schedule in mvneta_tx_timeout
From: Ben Hutchings @ 2014-01-12 17:38 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: davem, netdev, Thomas Petazzoni, Gregory CLEMENT
In-Reply-To: <20140112165548.GC16576@1wt.eu>

[-- Attachment #1: Type: text/plain, Size: 2810 bytes --]

[Putting another hat on]

On Sun, 2014-01-12 at 17:55 +0100, Willy Tarreau wrote:
> Hi Ben,
> 
> On Sun, Jan 12, 2014 at 04:49:51PM +0000, Ben Hutchings wrote:
> (...)
> > > So for now, let's simply ignore these timeouts generally caused by bugs
> > > only.
> > 
> > No, don't ignore them.  Schedule a work item to reset the device.  (And
> > remember to cancel it when stopping the device.)
> 
> OK I can try to do that. Could you recommend me one driver which does this
> successfully so that I can see exactly what needs to be taken care of ?

sfc does it, though the reset logic there is more complicated than you
would need.

I think this will DTRT, but it's compile-tested only.  I have been given
an OpenBlocks AX3 but haven't set it up yet.

Ben.

---
mvneta: Defer restart from TX watchdog handler to work item

A restart requires sleeping, but the watchdog handler runs in atomic
context.

The work item can race with down-ing of the interface, so take the RTNL
lock and do nothing if the interface is already down.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index d5f0d72..a91dcc2 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -234,6 +234,7 @@ struct mvneta_port {
 	struct mvneta_tx_queue *txqs;
 	struct timer_list tx_done_timer;
 	struct net_device *dev;
+	struct work_struct restart_work;
 
 	u32 cause_rx_tx;
 	struct napi_struct napi;
@@ -2231,8 +2232,22 @@ static void mvneta_tx_timeout(struct net_device *dev)
 	struct mvneta_port *pp = netdev_priv(dev);
 
 	netdev_info(dev, "tx timeout\n");
-	mvneta_stop_dev(pp);
-	mvneta_start_dev(pp);
+
+	/* defer mvneta_restart(), as we're in atomic context here */
+	schedule_work(&pp->restart_work);
+}
+
+static void mvneta_restart(struct work_struct *work)
+{
+	struct mvneta_port *pp =
+		container_of(work, struct mvneta_port, restart_work);
+
+	rtnl_lock();
+	if (netif_running(pp->dev)) {
+		mvneta_stop_dev(pp);
+		mvneta_start_dev(pp);
+	}
+	rtnl_unlock();
 }
 
 /* Return positive if MTU is valid */
@@ -2792,6 +2807,8 @@ static int mvneta_probe(struct platform_device *pdev)
 
 	pp = netdev_priv(dev);
 
+	INIT_WORK(&pp->restart_work, mvneta_restart);
+
 	u64_stats_init(&pp->tx_stats.syncp);
 	u64_stats_init(&pp->rx_stats.syncp);
 
@@ -2890,6 +2907,7 @@ static int mvneta_remove(struct platform_device *pdev)
 	struct mvneta_port *pp = netdev_priv(dev);
 
 	unregister_netdev(dev);
+	cancel_work_sync(&pp->restart_work);
 	mvneta_deinit(pp);
 	clk_disable_unprepare(pp->clk);
 	iounmap(pp->base);

-- 
Ben Hutchings
Quantity is no substitute for quality, but it's the only one we've got.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply related

* a vxlan question.
From: sowmini varadhan @ 2014-01-12 17:25 UTC (permalink / raw)
  To: netdev; +Cc: sowmini.varadhan

A question about the vxlan implementation in linux:

if the inner packet (the frame that is vxlan encapsulated) is an IP
packet that has the DF bit set, i.e., it is a PMTU discovery packet, and
the subsequent vxlan encapsulation results in a ICMP packet-too-big
error,then does the VTEP relay that error back to the originator of
the
PMTU packet?

AFAICT, the current linux code in drivers/net/vxlan.c
does not address any icmp errors (though it sets the DF of the outer
header based on the inner header). From my reading of the code,
we'd end up in __udp4_lib_err for the vxlan-encaps packet, but
there's nothing in there that recognizes that the udp payload is
itself an ethernet+IP frame and relays pmtu back to the (inner) ip src?
Did I miss something?

--Sowmini

^ permalink raw reply

* Re: [PATCH net-next v2 4/4] virtio-net: initial debugfs support, export mergeable rx buffer size
From: Michael S. Tsirkin @ 2014-01-12 17:09 UTC (permalink / raw)
  To: Michael Dalton; +Cc: netdev, lf-virt, Eric Dumazet, David S. Miller
In-Reply-To: <CANJ5vP+Qxa5j_Cp1FBK-qdO+U+dy2kiY5N2bmWdMKbCoY9EwDQ@mail.gmail.com>

On Fri, Jan 10, 2014 at 09:19:37PM -0800, Michael Dalton wrote:
> Hi Jason, Michael
> 
> Sorry for the delay in response. Jason, I agree this patch ended up
> being larger than expected. The major implementation parts are:
> (1) Setup directory structure (driver/per-netdev/rx-queue directories)
> (2) Network device renames (optional, so debugfs dir has the right name)
> (3) Support resizing the # of RX queues (optional - we could just export
>     max_queue_pairs files and not delete files if an RX queue is disabled)
> (4) Reference counting - used in case someone opens a debugfs
>     file and then removes the virtio-net device.
> (5) The actual mergeable rx buffer file implementation itself. For now
>     I have added a seqcount for memory safety, but if a read-only race
>     condition is acceptable we could elide the seqcount. FWIW, the
>     seqcount write in receive_mergeable() should, on modern x86,
>     translate to two non-atomic adds and two compiler barriers, so
>     overhead is not expected to be meaningful.
> 
> We can move to sysfs and this would simplify or eliminate much of the
> above, including most of (1) - (4). I believe our choices for what to
> do for the next patchset include:
> (a) Use debugfs as is currently done, removing any optional features
> listed above that are deemed unnecessary.
> 
> (b) Add a per-netdev sysfs attribute group to net_device->sysfs_groups.
> Each attribute would display the mergeable packet buffer size for a given
> RX queue, and there would be max_queue_pairs attributes in total. This
> is already supported by net/core/net-sysfs.c:netdev_register_kobject(),
> but means that we would have a static set of per-RX queue files for
> all RX queues supported by the netdev, rather than dynamically displaying
> only the files corresponding to enabled RX queues (e.g., when # of RX
> queues is changed by  ethtool -L <device>).  For an example of this
> approach, see drivers/net/bonding/bond_sysfs.c.
> 
> (c) Modify struct netdev_rx_queue to add virtio-net EWMA fields directly,
> and modify net-sysfs.c to manage the new fields. Unlike (b), this approach
> supports the RX queue resizing in (3) but means putting virtio-net info
> in netdev_rx_queue, which currently has only device-independent fields.

Can't we add struct attribute * to netdevice, and pass that in when
creating the kobj?

> My preference would be (b): try using sysfs and adding a device-specific
> attribute group to the virtio-net netdevice (stored in the existing
> 'sysfs_groups' field and supported by net-sysfs).  This would avoid
> adding virtio-net specific information to net-sysfs. What would you
> prefer (or is there a better way than the approaches above)? Thanks!
> 
> Best,
> 
> Mike

^ permalink raw reply

* Re: [PATCH 3/5] net: mvneta: do not schedule in mvneta_tx_timeout
From: Willy Tarreau @ 2014-01-12 16:55 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: davem, netdev, Thomas Petazzoni, Gregory CLEMENT
In-Reply-To: <1389545391.3720.56.camel@deadeye.wl.decadent.org.uk>

Hi Ben,

On Sun, Jan 12, 2014 at 04:49:51PM +0000, Ben Hutchings wrote:
(...)
> > So for now, let's simply ignore these timeouts generally caused by bugs
> > only.
> 
> No, don't ignore them.  Schedule a work item to reset the device.  (And
> remember to cancel it when stopping the device.)

OK I can try to do that. Could you recommend me one driver which does this
successfully so that I can see exactly what needs to be taken care of ?

Thanks,
Willy

^ permalink raw reply

* Re: [PATCH 3/5] net: mvneta: do not schedule in mvneta_tx_timeout
From: Ben Hutchings @ 2014-01-12 16:49 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: davem, netdev, Thomas Petazzoni, Gregory CLEMENT
In-Reply-To: <1389519069-1619-4-git-send-email-w@1wt.eu>

On Sun, 2014-01-12 at 10:31 +0100, Willy Tarreau wrote:
> If a queue timeout is reported, we can oops because of some
> schedules while the caller is atomic, as shown below :
> 
>   mvneta d0070000.ethernet eth0: tx timeout
>   BUG: scheduling while atomic: bash/1528/0x00000100
>   Modules linked in: slhttp_ethdiv(C) [last unloaded: slhttp_ethdiv]
>   CPU: 2 PID: 1528 Comm: bash Tainted: G        WC   3.13.0-rc4-mvebu-nf #180
>   [<c0011bd9>] (unwind_backtrace+0x1/0x98) from [<c000f1ab>] (show_stack+0xb/0xc)
>   [<c000f1ab>] (show_stack+0xb/0xc) from [<c02ad323>] (dump_stack+0x4f/0x64)
>   [<c02ad323>] (dump_stack+0x4f/0x64) from [<c02abe67>] (__schedule_bug+0x37/0x4c)
>   [<c02abe67>] (__schedule_bug+0x37/0x4c) from [<c02ae261>] (__schedule+0x325/0x3ec)
>   [<c02ae261>] (__schedule+0x325/0x3ec) from [<c02adb97>] (schedule_timeout+0xb7/0x118)
>   [<c02adb97>] (schedule_timeout+0xb7/0x118) from [<c0020a67>] (msleep+0xf/0x14)
>   [<c0020a67>] (msleep+0xf/0x14) from [<c01dcbe5>] (mvneta_stop_dev+0x21/0x194)
>   [<c01dcbe5>] (mvneta_stop_dev+0x21/0x194) from [<c01dcfe9>] (mvneta_tx_timeout+0x19/0x24)
>   [<c01dcfe9>] (mvneta_tx_timeout+0x19/0x24) from [<c024afc7>] (dev_watchdog+0x18b/0x1c4)
>   [<c024afc7>] (dev_watchdog+0x18b/0x1c4) from [<c0020b53>] (call_timer_fn.isra.27+0x17/0x5c)
>   [<c0020b53>] (call_timer_fn.isra.27+0x17/0x5c) from [<c0020cad>] (run_timer_softirq+0x115/0x170)
>   [<c0020cad>] (run_timer_softirq+0x115/0x170) from [<c001ccb9>] (__do_softirq+0xbd/0x1a8)
>   [<c001ccb9>] (__do_softirq+0xbd/0x1a8) from [<c001cfad>] (irq_exit+0x61/0x98)
>   [<c001cfad>] (irq_exit+0x61/0x98) from [<c000d4bf>] (handle_IRQ+0x27/0x60)
>   [<c000d4bf>] (handle_IRQ+0x27/0x60) from [<c000843b>] (armada_370_xp_handle_irq+0x33/0xc8)
>   [<c000843b>] (armada_370_xp_handle_irq+0x33/0xc8) from [<c000fba9>] (__irq_usr+0x49/0x60)
> 
> So for now, let's simply ignore these timeouts generally caused by bugs
> only.

No, don't ignore them.  Schedule a work item to reset the device.  (And
remember to cancel it when stopping the device.)

Ben.

> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Cc: Gregory CLEMENT <gregory.clement@free-electrons.com>
> Signed-off-by: Willy Tarreau <w@1wt.eu>
> ---
>  drivers/net/ethernet/marvell/mvneta.c | 11 -----------
>  1 file changed, 11 deletions(-)
> 
> diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
> index 40d3e8b..84220c1 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -2244,16 +2244,6 @@ static void mvneta_stop_dev(struct mvneta_port *pp)
>  	mvneta_rx_reset(pp);
>  }
>  
> -/* tx timeout callback - display a message and stop/start the network device */
> -static void mvneta_tx_timeout(struct net_device *dev)
> -{
> -	struct mvneta_port *pp = netdev_priv(dev);
> -
> -	netdev_info(dev, "tx timeout\n");
> -	mvneta_stop_dev(pp);
> -	mvneta_start_dev(pp);
> -}
> -
>  /* Return positive if MTU is valid */
>  static int mvneta_check_mtu_valid(struct net_device *dev, int mtu)
>  {
> @@ -2634,7 +2624,6 @@ static const struct net_device_ops mvneta_netdev_ops = {
>  	.ndo_set_rx_mode     = mvneta_set_rx_mode,
>  	.ndo_set_mac_address = mvneta_set_mac_addr,
>  	.ndo_change_mtu      = mvneta_change_mtu,
> -	.ndo_tx_timeout      = mvneta_tx_timeout,
>  	.ndo_get_stats64     = mvneta_get_stats64,
>  	.ndo_do_ioctl        = mvneta_ioctl,
>  };

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* [PATCH net-next 3/3] packet: use percpu mmap tx frame pending refcount
From: Daniel Borkmann @ 2014-01-12 16:22 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1389543768-20234-1-git-send-email-dborkman@redhat.com>

In PF_PACKET's packet mmap(), we can avoid using one atomic_inc()
and one atomic_dec() call in skb destructor and use a percpu
reference count instead in order to determine if packets are
still pending to be sent out. Micro-benchmark with [1] that has
been slightly modified (that is, protcol = 0 in socket(2) and
bind(2)), example on an i7-3520M machine:

./packet_mm_tx -s7000 -m7200 -z700000 em1, avg over 2500 runs:

With patch:    4,022,015 cyc
Without patch: 4,812,994 cyc

time ./packet_mm_tx -s64 -c10000000 em1 > /dev/null, stable:

With patch:
  real         1m32.241s
  user         0m0.287s
  sys          1m29.316s

Without patch:
  real         1m38.386s
  user         0m0.265s
  sys          1m35.572s

In function tpacket_snd(), it is okay to use packet_read_pending()
since in fast-path we short-circuit the condition already with
ph != NULL, since we have next frames to process.

In case we have MSG_DONTWAIT, we also do not execute this path as
need_wait is false here anyway, and in case of _no_ MSG_DONTWAIT
flag, it is okay to call a packet_read_pending(), because when
we ever reach that path, we're done processing frames anyway and
only look if there are skbs still outstanding to be orphaned.

The BUG_ON() in tpacket_destruct_skb() we can remove as well. It
can _only_ be set from inside tpacket_snd() path and we made
sure to increase tx_ring.pending in any case before we called
po->xmit(skb). So testing for tx_ring.pending == 0 is not too
useful. Instead, it would rather have been useful to test if
lower layers didn't orphan the skb so that we're missing ring
slots being put back to TP_STATUS_AVAILABLE. But such a bug will
be caught in user space already as we end up realizing that we do
not have any TP_STATUS_AVAILABLE slots left anymore. Therefore,
we're all set.

Btw, in case of RX_RING path, we do not make use of the pending
member, therefore we also don't need to use up any percpu memory
here.

  [1] http://wiki.ipxwarzone.com/index.php5?title=Linux_packet_mmap

Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
---
 net/packet/af_packet.c | 65 +++++++++++++++++++++++++++++++++++++++++++++-----
 net/packet/diag.c      |  1 +
 net/packet/internal.h  |  2 +-
 3 files changed, 61 insertions(+), 7 deletions(-)

diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index d5495d8..6803be98 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -89,6 +89,7 @@
 #include <linux/errqueue.h>
 #include <linux/net_tstamp.h>
 #include <linux/reciprocal_div.h>
+#include <linux/percpu.h>
 #ifdef CONFIG_INET
 #include <net/inet_common.h>
 #endif
@@ -1168,6 +1169,46 @@ static void packet_increment_head(struct packet_ring_buffer *buff)
 	buff->head = buff->head != buff->frame_max ? buff->head+1 : 0;
 }
 
+static void packet_inc_pending(struct packet_ring_buffer *rb)
+{
+	this_cpu_inc(*rb->pending_refcnt);
+}
+
+static void packet_dec_pending(struct packet_ring_buffer *rb)
+{
+	this_cpu_dec(*rb->pending_refcnt);
+}
+
+static int packet_read_pending(const struct packet_ring_buffer *rb)
+{
+	int i, refcnt = 0;
+
+	/* We don't use pending refcount in rx_ring. */
+	if (rb->pending_refcnt == NULL)
+		return 0;
+
+	for_each_possible_cpu(i)
+		refcnt += *per_cpu_ptr(rb->pending_refcnt, i);
+
+	return refcnt;
+}
+
+static int packet_alloc_pending(struct packet_sock *po)
+{
+	po->rx_ring.pending_refcnt = NULL;
+
+	po->tx_ring.pending_refcnt = alloc_percpu(int);
+	if (unlikely(po->tx_ring.pending_refcnt == NULL))
+		return -ENOBUFS;
+
+	return 0;
+}
+
+static void packet_free_pending(struct packet_sock *po)
+{
+	free_percpu(po->tx_ring.pending_refcnt);
+}
+
 static bool packet_rcv_has_room(struct packet_sock *po, struct sk_buff *skb)
 {
 	struct sock *sk = &po->sk;
@@ -2014,8 +2055,7 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
 		__u32 ts;
 
 		ph = skb_shinfo(skb)->destructor_arg;
-		BUG_ON(atomic_read(&po->tx_ring.pending) == 0);
-		atomic_dec(&po->tx_ring.pending);
+		packet_dec_pending(&po->tx_ring);
 
 		ts = __packet_set_timestamp(po, ph, skb);
 		__packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);
@@ -2236,7 +2276,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 		skb_set_queue_mapping(skb, packet_pick_tx_queue(dev));
 		skb->destructor = tpacket_destruct_skb;
 		__packet_set_status(po, ph, TP_STATUS_SENDING);
-		atomic_inc(&po->tx_ring.pending);
+		packet_inc_pending(&po->tx_ring);
 
 		status = TP_STATUS_SEND_REQUEST;
 		err = po->xmit(skb);
@@ -2256,8 +2296,14 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 		}
 		packet_increment_head(&po->tx_ring);
 		len_sum += tp_len;
-	} while (likely((ph != NULL) || (need_wait &&
-					 atomic_read(&po->tx_ring.pending))));
+	} while (likely((ph != NULL) ||
+		/* Note: packet_read_pending() might be slow if we have
+		 * to call it as it's per_cpu variable, but in fast-path
+		 * we already short-circuit the loop with the first
+		 * condition, and luckily don't have to go that path
+		 * anyway.
+		 */
+		 (need_wait && packet_read_pending(&po->tx_ring))));
 
 	err = len_sum;
 	goto out_put;
@@ -2556,6 +2602,7 @@ static int packet_release(struct socket *sock)
 	/* Purge queues */
 
 	skb_queue_purge(&sk->sk_receive_queue);
+	packet_free_pending(po);
 	sk_refcnt_debug_release(sk);
 
 	sock_put(sk);
@@ -2717,6 +2764,10 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
 	po->num = proto;
 	po->xmit = dev_queue_xmit;
 
+	err = packet_alloc_pending(po);
+	if (err)
+		goto out2;
+
 	packet_cached_dev_reset(po);
 
 	sk->sk_destruct = packet_sock_destruct;
@@ -2749,6 +2800,8 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
 	preempt_enable();
 
 	return 0;
+out2:
+	sk_free(sk);
 out:
 	return err;
 }
@@ -3676,7 +3729,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 	if (!closing) {
 		if (atomic_read(&po->mapped))
 			goto out;
-		if (atomic_read(&rb->pending))
+		if (packet_read_pending(rb))
 			goto out;
 	}
 
diff --git a/net/packet/diag.c b/net/packet/diag.c
index a9584a2..533ce4f 100644
--- a/net/packet/diag.c
+++ b/net/packet/diag.c
@@ -3,6 +3,7 @@
 #include <linux/net.h>
 #include <linux/netdevice.h>
 #include <linux/packet_diag.h>
+#include <linux/percpu.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
 
diff --git a/net/packet/internal.h b/net/packet/internal.h
index 0a87d7b..a47d5b5 100644
--- a/net/packet/internal.h
+++ b/net/packet/internal.h
@@ -64,7 +64,7 @@ struct packet_ring_buffer {
 	unsigned int		pg_vec_pages;
 	unsigned int		pg_vec_len;
 
-	atomic_t		pending;
+	int __percpu		*pending_refcnt;
 
 	struct tpacket_kbdq_core	prb_bdqc;
 };
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH net-next 2/3] packet: don't unconditionally schedule() in case of MSG_DONTWAIT
From: Daniel Borkmann @ 2014-01-12 16:22 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1389543768-20234-1-git-send-email-dborkman@redhat.com>

In tpacket_snd(), when we've discovered a first frame that is
not in status TP_STATUS_SEND_REQUEST, and return a NULL buffer,
we exit the send routine in case of MSG_DONTWAIT, since we've
finished traversing the mmaped send ring buffer and don't care
about pending frames.

While doing so, we still unconditionally call an expensive
schedule() in the packet_current_frame() "error" path, which
is unnecessary in this case since it's enough to just quit
the function.

Also, in case MSG_DONTWAIT is not set, we should rather test
for need_resched() first and do schedule() only if necessary
since meanwhile pending frames could already have finished
processing and called skb destructor.

Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
---
 net/packet/af_packet.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 85bb38c..d5495d8 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2156,6 +2156,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 	int err, reserve = 0;
 	void *ph;
 	struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name;
+	bool need_wait = !(msg->msg_flags & MSG_DONTWAIT);
 	int tp_len, size_max;
 	unsigned char *addr;
 	int len_sum = 0;
@@ -2198,10 +2199,10 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 
 	do {
 		ph = packet_current_frame(po, &po->tx_ring,
-				TP_STATUS_SEND_REQUEST);
-
+					  TP_STATUS_SEND_REQUEST);
 		if (unlikely(ph == NULL)) {
-			schedule();
+			if (need_wait && need_resched())
+				schedule();
 			continue;
 		}
 
@@ -2255,10 +2256,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 		}
 		packet_increment_head(&po->tx_ring);
 		len_sum += tp_len;
-	} while (likely((ph != NULL) ||
-			((!(msg->msg_flags & MSG_DONTWAIT)) &&
-			 (atomic_read(&po->tx_ring.pending))))
-		);
+	} while (likely((ph != NULL) || (need_wait &&
+					 atomic_read(&po->tx_ring.pending))));
 
 	err = len_sum;
 	goto out_put;
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH net-next 1/3] packet: improve socket create/bind latency in some cases
From: Daniel Borkmann @ 2014-01-12 16:22 UTC (permalink / raw)
  To: davem; +Cc: netdev
In-Reply-To: <1389543768-20234-1-git-send-email-dborkman@redhat.com>

Most people acquire PF_PACKET sockets with a protocol argument in
the socket call, e.g. libpcap does so with htons(ETH_P_ALL) for
all its sockets. Most likely, at some point in time a subsequent
bind() call will follow, e.g. in libpcap with ...

  memset(&sll, 0, sizeof(sll));
  sll.sll_family          = AF_PACKET;
  sll.sll_ifindex         = ifindex;
  sll.sll_protocol        = htons(ETH_P_ALL);

... as arguments. What happens in the kernel is that already
in socket() syscall, we install a proto hook via register_prot_hook()
if our protocol argument is != 0. Yet, in bind() we're almost
doing the same work by doing a unregister_prot_hook() with an
expensive synchronize_net() call in case during socket() the proto
was != 0, plus follow-up register_prot_hook() with a bound device
to it this time, in order to limit traffic we get.

In the case when the protocol and user supplied device index (== 0)
does not change from socket() to bind(), we can spare us doing
the same work twice. Similarly for re-binding to the same device
and protocol. For these scenarios, we can decrease create/bind
latency from ~7447us (sock-bind-2 case) to ~89us (sock-bind-1 case)
with this patch.

Alternatively, for the first case, if people care, they should
simply create their sockets with proto == 0 argument and define
the protocol during bind() as this saves a call to synchronize_net()
as well (sock-bind-3 case).

In all other cases, we're tied to user space behaviour we must not
change, also since a bind() is not strictly required. Thus, we need
the synchronize_net() to make sure no asynchronous packet processing
paths still refer to the previous elements of po->prot_hook.

In case of mmap()ed sockets, the workflow that includes bind() is
socket() -> setsockopt(<ring>) -> bind(). In that case, a pair of
{__unregister, register}_prot_hook is being called from setsockopt()
in order to install the new protocol receive handler. Thus, when
we call bind and can skip a re-hook, we have already previously
installed the new handler. For fanout, this is handled different
entirely, so we should be good.

Timings on an i7-3520M machine:

  * sock-bind-1:   89 us
  * sock-bind-2: 7447 us
  * sock-bind-3:   75 us

sock-bind-1:
  socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)) = 3
  bind(3, {sa_family=AF_PACKET, proto=htons(ETH_P_IP), if=all(0),
           pkttype=PACKET_HOST, addr(0)={0, }, 20) = 0

sock-bind-2:
  socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)) = 3
  bind(3, {sa_family=AF_PACKET, proto=htons(ETH_P_IP), if=lo(1),
           pkttype=PACKET_HOST, addr(0)={0, }, 20) = 0

sock-bind-3:
  socket(PF_PACKET, SOCK_RAW, 0) = 3
  bind(3, {sa_family=AF_PACKET, proto=htons(ETH_P_IP), if=lo(1),
           pkttype=PACKET_HOST, addr(0)={0, }, 20) = 0

Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
---
 v1->v2:
  - applied Dave's feedback to move assignments under bind lock
  - removed cleanup part

 net/packet/af_packet.c | 33 ++++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 279467b..85bb38c 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2567,9 +2567,12 @@ static int packet_release(struct socket *sock)
  *	Attach a packet hook.
  */
 
-static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protocol)
+static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto)
 {
 	struct packet_sock *po = pkt_sk(sk);
+	const struct net_device *dev_curr;
+	__be16 proto_curr;
+	bool need_rehook;
 
 	if (po->fanout) {
 		if (dev)
@@ -2579,21 +2582,29 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc
 	}
 
 	lock_sock(sk);
-
 	spin_lock(&po->bind_lock);
-	unregister_prot_hook(sk, true);
 
-	po->num = protocol;
-	po->prot_hook.type = protocol;
-	if (po->prot_hook.dev)
-		dev_put(po->prot_hook.dev);
+	proto_curr = po->prot_hook.type;
+	dev_curr = po->prot_hook.dev;
+
+	need_rehook = proto_curr != proto || dev_curr != dev;
+
+	if (need_rehook) {
+		unregister_prot_hook(sk, true);
 
-	po->prot_hook.dev = dev;
-	po->ifindex = dev ? dev->ifindex : 0;
+		po->num = proto;
+		po->prot_hook.type = proto;
+
+		if (po->prot_hook.dev)
+			dev_put(po->prot_hook.dev);
 
-	packet_cached_dev_assign(po, dev);
+		po->prot_hook.dev = dev;
+
+		po->ifindex = dev ? dev->ifindex : 0;
+		packet_cached_dev_assign(po, dev);
+	}
 
-	if (protocol == 0)
+	if (proto == 0 || !need_rehook)
 		goto out_unlock;
 
 	if (!dev || (dev->flags & IFF_UP)) {
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH net-next 0/3] pf_packet updates
From: Daniel Borkmann @ 2014-01-12 16:22 UTC (permalink / raw)
  To: davem; +Cc: netdev

Daniel Borkmann (3):
  packet: improve socket create/bind latency in some cases
  packet: don't unconditionally schedule() in case of MSG_DONTWAIT
  packet: use percpu mmap tx frame pending refcount

 net/packet/af_packet.c | 105 +++++++++++++++++++++++++++++++++++++++----------
 net/packet/diag.c      |   1 +
 net/packet/internal.h  |   2 +-
 3 files changed, 86 insertions(+), 22 deletions(-)

-- 
1.7.11.7

^ permalink raw reply

* Re: [PATCH net-next] IPv6: enable TCP to use an anycast address
From: François-Xavier Le Bail @ 2014-01-12 14:53 UTC (permalink / raw)
  To: Alexey Kuznetsov, Hannes Frederic Sowa
  Cc: netdev, David S. Miller, James Morris, Hideaki Yoshifuji,
	Patrick McHardy

On Sat, 1/11/14, Hannes Frederic Sowa <hannes@stressinduktion.org> wrote:

> On Sat, Jan 11, 2014 at 05:38:27PM +0400, Alexey Kuznetsov wrote:
> > On Sat, Jan 11, 2014 at 5:06 PM, François-Xavier Le Bail
> > <fx.lebail@yahoo.com> wrote:
> > > Many DNS root-servers use TCP with anycast (IPv4 and IPV6).
> > 
> > Actually, I was alerted by reset processing in your patch, it cannot be right.
> > 
> > Do not you think this must not be enabled for common use? At least
> > some separate sysctl disabled by default.

> The idea I had, was, that if a socket does knowingly bind to an anycast
> address, it is allowed to do so and process queries on it with both TCP and
> UDP. I don't think we need a sysctl for that? Anycast addresses are either
> pre-defined (e.g. the subnet router anycast address) or specified by a flag
> when the administrator adds one. Currently one can only add anycast addresses
> either by forwarding and gets the per-subnet anycast address or with a
> setsockopt IPV6_JOIN_ANYCAST.

> So the problem is what should be allowed when the socket listens on an any
> address? Maybe this should be protected by a sysctl?

Hi,

TCP case:
With my two patches (the one for bind and this one for tcp), when a
SOCK_STREAM socket listen to in6addr_any, the server is able to 
send TCP reply with unicast or anycast source address, according
to the destination address used by the client.

dest request unicast => src reply unicast (current behavior)
dest resquet anycast => src reply anycast (new)

So, I don't think there is a need for a sysctl.

UDP case:
By default (no socket option), the server program don't know the
destination address of the request. The ipv6_dev_get_saddr() is 
used for choosing the unicast source address of the reply.

I am not sure a change is needed here.

When using IPV6_RECVPKTINFO, a server is able to know
the destination address of the request and can use it as source
address for the reply.
To enable anycast for this (don't get EINVAL), there is need for
a patch like the one I posted ("IPv6: add option to use anycast
addresses as source addresses for datagrams").
I am working on a v2.

With the appropriate change:
dest request unicast => src reply unicast (current behavior)
dest resquet anycast => src reply anycast (new)

I don't think, there either, there is a need for a sysctl.

What do you think about it?

BR,
Francois-Xavier

^ permalink raw reply

* Re: [RFC PATCH 00/12] RCU'ify the net:sched classifier chains
From: Jamal Hadi Salim @ 2014-01-12 14:18 UTC (permalink / raw)
  To: John Fastabend, xiyou.wangcong, eric.dumazet; +Cc: netdev, davem
In-Reply-To: <52D29F4C.90808@mojatatu.com>

On 01/12/14 08:57, Jamal Hadi Salim wrote:

> I looked and here's a general question:
> Does even using RCU make any sense here? What we have
> is a lot of updates and very very little reads (reads essentially
> are done from the control side; the data path is is all about updates).
>
> I am not sure if RCU is a win in such a case - it could make things
> worse. At least that used to be the Truth(tm) many moons back.
> Is that not the case anymore?
>

Never mind.
You are not trying to make stats rcu - rather the list
of filters and actions (which is read mostly from data path).
Looking at the u32 piece - i think this is in the right
direction. Good stuff John!

cheers,
jamal

^ permalink raw reply

* Re: [RFC PATCH 00/12] RCU'ify the net:sched classifier chains
From: Jamal Hadi Salim @ 2014-01-12 13:57 UTC (permalink / raw)
  To: John Fastabend, xiyou.wangcong, eric.dumazet; +Cc: netdev, davem
In-Reply-To: <52D2987D.5060807@mojatatu.com>

On 01/12/14 08:28, Jamal Hadi Salim wrote:

> I will scan through the patches...
>

I looked and here's a general question:
Does even using RCU make any sense here? What we have
is a lot of updates and very very little reads (reads essentially
are done from the control side; the data path is is all about updates).

I am not sure if RCU is a win in such a case - it could make things
worse. At least that used to be the Truth(tm) many moons back.
Is that not the case anymore?

cheers,
jamal

> This is fun stuff - I will try to participate whenever i can
> (unfortunately not much time at the moment).
>

^ permalink raw reply

* Re: [PATCH net-next 0/3] bonding: cleanup bond_3ad.c
From: Veaceslav Falico @ 2014-01-12 13:27 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, fubar, andy
In-Reply-To: <20140110.180614.405638448761352206.davem@davemloft.net>

On Fri, Jan 10, 2014 at 06:06:14PM -0500, David Miller wrote:
>From: Veaceslav Falico <vfalico@redhat.com>
>Date: Wed,  8 Jan 2014 16:46:45 +0100
>
>> It's a huge mess there currently - and, thus, really hard to read and
>> debug.
>>
>> This is the first series, and doesn't change the logic at all, only makes
>> it a bit more readable.
>>
>> CC: Jay Vosburgh <fubar@us.ibm.com>
>> CC: Andy Gospodarek <andy@greyhouse.net>
>> Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
>
>Series applied, thanks.

Hrm, still can't see them. Did I miss something?..

^ permalink raw reply

* Re: [RFC PATCH 00/12] RCU'ify the net:sched classifier chains
From: Jamal Hadi Salim @ 2014-01-12 13:28 UTC (permalink / raw)
  To: John Fastabend, xiyou.wangcong, eric.dumazet; +Cc: netdev, davem
In-Reply-To: <20140110092041.7193.5952.stgit@nitbit.x32>

On 01/10/14 04:36, John Fastabend wrote:

>
> The ingress qdisc is a simple qdisc which doesn't maintain any
> actual list of skb's and is primarily a hook to attach filters.
> Further the only qdisc that can be attached to the ingress qdisc
> is sch_ingress. The qdisc lock is currently serializing two
> operations (1) tc_classify which is addressed here and (2)
> statistics accounting. The second point is not solved here but
> it could be a matter of making the bstats and qstats per cpu
> stats.

I think as you observed in your other email:
There is a little more than just the stats (on qdiscs as well);
internal to specific filters etc.

> This is an RFC for now and needs some more work. Some items
> I know about are (a) an audit of the ematch code paths, (b) resolving
> the checpatch errors mostly due to moving code around that
> generates those errors, (c) run smatch, (d) audit u32 code
> for correctness,

Ok, my feel-good dial went up reading #d above;->

>(e) do a lot more testing so far only very
> basic testing has been done. I tried to put some reasonable
> comments in the commit logs but yes they need more work.
>

Things like MSI based devices, massive single tun device
tests, ifb with redirect etc would help cleanse things up.

> Cong, if its not too much to ask can we use this as a base
> set of patches for this work? I think its reasonably close to
> correct as is.
>

I believe these are based on your original patches John, no?
So I would agree we use these as a base.

I will scan through the patches...

This is fun stuff - I will try to participate whenever i can
(unfortunately not much time at the moment).

cheers,
jamal

> Thanks! John.
>
> ---
>
> John Fastabend (12):
>        net: qdisc: use rcu prefix and silence sparse warnings
>        net: rcu-ify tcf_proto
>        net: sched: cls_basic use RCU
>        net: sched: cls_cgroup use RCU
>        net: sched: cls_flow use RCU
>        net: sched: fw use RCU
>        net: sched: RCU cls_route
>        net: sched: RCU cls_tcindex
>        net: sched: make cls_u32 lockless
>        net: sched: rcu'ify cls_rsvp
>        net: make cls_bpf rcu safe
>        net: sched: make tc_action safe to walk under RCU
>
>
>   include/linux/netdevice.h |   41 +-----
>   include/linux/rtnetlink.h |   10 +
>   include/net/act_api.h     |    1
>   include/net/pkt_cls.h     |   12 +-
>   include/net/sch_generic.h |   34 ++++-
>   net/core/dev.c            |   54 +++++++
>   net/sched/act_api.c       |   18 +-
>   net/sched/cls_api.c       |   44 +++---
>   net/sched/cls_basic.c     |   82 ++++++-----
>   net/sched/cls_bpf.c       |   79 ++++++-----
>   net/sched/cls_cgroup.c    |   65 ++++++---
>   net/sched/cls_flow.c      |  145 ++++++++++++--------
>   net/sched/cls_fw.c        |  112 +++++++++++----
>   net/sched/cls_route.c     |  218 +++++++++++++++++-------------
>   net/sched/cls_rsvp.h      |  152 ++++++++++++---------
>   net/sched/cls_tcindex.c   |  327 ++++++++++++++++++++++++++-------------------
>   net/sched/cls_u32.c       |  258 +++++++++++++++++++++++-------------
>   net/sched/sch_api.c       |    6 -
>   net/sched/sch_atm.c       |   30 +++-
>   net/sched/sch_cbq.c       |   21 ++-
>   net/sched/sch_choke.c     |   18 ++
>   net/sched/sch_drr.c       |   10 +
>   net/sched/sch_dsmark.c    |    8 +
>   net/sched/sch_fq_codel.c  |   11 +-
>   net/sched/sch_generic.c   |    4 -
>   net/sched/sch_hfsc.c      |   17 ++
>   net/sched/sch_htb.c       |   23 ++-
>   net/sched/sch_ingress.c   |    8 +
>   net/sched/sch_mqprio.c    |    4 -
>   net/sched/sch_multiq.c    |    8 +
>   net/sched/sch_prio.c      |   11 +-
>   net/sched/sch_qfq.c       |    9 +
>   net/sched/sch_sfb.c       |   15 +-
>   net/sched/sch_sfq.c       |   11 +-
>   net/sched/sch_teql.c      |    9 +
>   35 files changed, 1139 insertions(+), 736 deletions(-)
>

^ permalink raw reply

* Re: [Patch net-next 7/7] net_sched: act: remove struct tcf_act_hdr
From: Jamal Hadi Salim @ 2014-01-12 13:13 UTC (permalink / raw)
  To: Cong Wang, netdev; +Cc: David S. Miller
In-Reply-To: <1389312845-10304-8-git-send-email-xiyou.wangcong@gmail.com>

On 01/09/14 19:14, Cong Wang wrote:
> It is not necessary at all.
>
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>

Interestingly enough this is how things were originally ;->

Thanks Cong for all the effort.

Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>

cheers,
jamal

^ permalink raw reply

* Re: [Patch net-next 6/7] net_sched: cls: move allocation in ->init to generic layer
From: Jamal Hadi Salim @ 2014-01-12 13:07 UTC (permalink / raw)
  To: Cong Wang, netdev; +Cc: Thomas Graf, David S. Miller
In-Reply-To: <1389312845-10304-7-git-send-email-xiyou.wangcong@gmail.com>

On 01/09/14 19:14, Cong Wang wrote:
> Most of the filters need allocation of tp->root in ->init()
> and free it in ->destroy(), make this generic.
>
> Also we could reduce the use of tcf_tree_lock a bit.
>
> Cc: Thomas Graf <tgraf@suug.ch>
> Cc: David S. Miller <davem@davemloft.net>
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>


Hrm. This one worries me a little.
I dont see how just pre-allocing the private head of the classifier
magically allows you to get rid of locks. Have you tested against those
classifiers you changed?
If those locks are useless - then that is a separate patch to kill
them (sorry, dont have time to test myself right now).

cheers,
jamal

> ---
>   include/net/sch_generic.h |  1 +
>   net/sched/cls_api.c       |  7 +++++++
>   net/sched/cls_basic.c     |  8 ++------
>   net/sched/cls_bpf.c       | 11 ++---------
>   net/sched/cls_cgroup.c    | 21 +++++++--------------
>   net/sched/cls_flow.c      |  8 ++------
>   net/sched/cls_fw.c        | 14 ++++----------
>   net/sched/cls_route.c     | 15 ++-------------
>   net/sched/cls_rsvp.h      | 10 ++--------
>   net/sched/cls_tcindex.c   | 13 ++-----------
>   net/sched/cls_u32.c       |  9 ++-------
>   net/sched/sch_api.c       |  1 +
>   12 files changed, 34 insertions(+), 84 deletions(-)
>
> diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
> index d062f81..819dc1d 100644
> --- a/include/net/sch_generic.h
> +++ b/include/net/sch_generic.h
> @@ -208,6 +208,7 @@ struct tcf_proto_ops {
>   					struct sk_buff *skb, struct tcmsg*);
>
>   	struct module		*owner;
> +	size_t			root_size;
>   };
>
>   struct tcf_proto {
> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
> index 29a30a1..8460c75 100644
> --- a/net/sched/cls_api.c
> +++ b/net/sched/cls_api.c
> @@ -262,6 +262,13 @@ replay:
>   		tp->q = q;
>   		tp->classify = tp_ops->classify;
>   		tp->classid = parent;
> +		tp->root = kzalloc(tp_ops->root_size, GFP_KERNEL);
> +		if (!tp->root) {
> +			err = -ENOBUFS;
> +			module_put(tp_ops->owner);
> +			kfree(tp);
> +			goto errout;
> +		}
>
>   		err = tp_ops->init(tp);
>   		if (err != 0) {
> diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
> index e98ca99..318f672 100644
> --- a/net/sched/cls_basic.c
> +++ b/net/sched/cls_basic.c
> @@ -75,13 +75,9 @@ static void basic_put(struct tcf_proto *tp, unsigned long f)
>
>   static int basic_init(struct tcf_proto *tp)
>   {
> -	struct basic_head *head;
> +	struct basic_head *head = tp->root;
>
> -	head = kzalloc(sizeof(*head), GFP_KERNEL);
> -	if (head == NULL)
> -		return -ENOBUFS;
>   	INIT_LIST_HEAD(&head->flist);
> -	tp->root = head;
>   	return 0;
>   }
>
> @@ -102,7 +98,6 @@ static void basic_destroy(struct tcf_proto *tp)
>   		list_del(&f->link);
>   		basic_delete_filter(tp, f);
>   	}
> -	kfree(head);
>   }
>
>   static int basic_delete(struct tcf_proto *tp, unsigned long arg)
> @@ -288,6 +283,7 @@ static struct tcf_proto_ops cls_basic_ops __read_mostly = {
>   	.walk		=	basic_walk,
>   	.dump		=	basic_dump,
>   	.owner		=	THIS_MODULE,
> +	.root_size	=	sizeof(struct basic_head),
>   };
>
>   static int __init init_basic(void)
> diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
> index 8e3cf49..eedd296 100644
> --- a/net/sched/cls_bpf.c
> +++ b/net/sched/cls_bpf.c
> @@ -75,15 +75,9 @@ static int cls_bpf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
>
>   static int cls_bpf_init(struct tcf_proto *tp)
>   {
> -	struct cls_bpf_head *head;
> -
> -	head = kzalloc(sizeof(*head), GFP_KERNEL);
> -	if (head == NULL)
> -		return -ENOBUFS;
> +	struct cls_bpf_head *head = tp->root;
>
>   	INIT_LIST_HEAD(&head->plist);
> -	tp->root = head;
> -
>   	return 0;
>   }
>
> @@ -126,8 +120,6 @@ static void cls_bpf_destroy(struct tcf_proto *tp)
>   		list_del(&prog->link);
>   		cls_bpf_delete_prog(tp, prog);
>   	}
> -
> -	kfree(head);
>   }
>
>   static unsigned long cls_bpf_get(struct tcf_proto *tp, u32 handle)
> @@ -366,6 +358,7 @@ static struct tcf_proto_ops cls_bpf_ops __read_mostly = {
>   	.delete		=	cls_bpf_delete,
>   	.walk		=	cls_bpf_walk,
>   	.dump		=	cls_bpf_dump,
> +	.root_size	=	sizeof(struct cls_bpf_head),
>   };
>
>   static int __init cls_bpf_init_mod(void)
> diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
> index 8e2158a..4b7e083 100644
> --- a/net/sched/cls_cgroup.c
> +++ b/net/sched/cls_cgroup.c
> @@ -22,6 +22,7 @@ struct cls_cgroup_head {
>   	u32			handle;
>   	struct tcf_exts		exts;
>   	struct tcf_ematch_tree	ematches;
> +	bool			init;
>   };
>
>   static int cls_cgroup_classify(struct sk_buff *skb, const struct tcf_proto *tp,
> @@ -73,6 +74,9 @@ static void cls_cgroup_put(struct tcf_proto *tp, unsigned long f)
>
>   static int cls_cgroup_init(struct tcf_proto *tp)
>   {
> +	struct cls_cgroup_head *head = tp->root;
> +
> +	tcf_exts_init(&head->exts, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
>   	return 0;
>   }
>
> @@ -94,20 +98,9 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
>   	if (!tca[TCA_OPTIONS])
>   		return -EINVAL;
>
> -	if (head == NULL) {
> -		if (!handle)
> -			return -EINVAL;
> -
> -		head = kzalloc(sizeof(*head), GFP_KERNEL);
> -		if (head == NULL)
> -			return -ENOBUFS;
> -
> -		tcf_exts_init(&head->exts, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
> +	if (!head->init) {
>   		head->handle = handle;
> -
> -		tcf_tree_lock(tp);
> -		tp->root = head;
> -		tcf_tree_unlock(tp);
> +		head->init = true;
>   	}
>
>   	if (handle != head->handle)
> @@ -140,7 +133,6 @@ static void cls_cgroup_destroy(struct tcf_proto *tp)
>   	if (head) {
>   		tcf_exts_destroy(tp, &head->exts);
>   		tcf_em_tree_destroy(tp, &head->ematches);
> -		kfree(head);
>   	}
>   }
>
> @@ -205,6 +197,7 @@ static struct tcf_proto_ops cls_cgroup_ops __read_mostly = {
>   	.walk		=	cls_cgroup_walk,
>   	.dump		=	cls_cgroup_dump,
>   	.owner		=	THIS_MODULE,
> +	.root_size	=	sizeof(struct cls_cgroup_head),
>   };
>
>   static int __init init_cgroup_cls(void)
> diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
> index 257029c..b39080a 100644
> --- a/net/sched/cls_flow.c
> +++ b/net/sched/cls_flow.c
> @@ -526,13 +526,9 @@ static int flow_delete(struct tcf_proto *tp, unsigned long arg)
>
>   static int flow_init(struct tcf_proto *tp)
>   {
> -	struct flow_head *head;
> +	struct flow_head *head = tp->root;
>
> -	head = kzalloc(sizeof(*head), GFP_KERNEL);
> -	if (head == NULL)
> -		return -ENOBUFS;
>   	INIT_LIST_HEAD(&head->filters);
> -	tp->root = head;
>   	return 0;
>   }
>
> @@ -545,7 +541,6 @@ static void flow_destroy(struct tcf_proto *tp)
>   		list_del(&f->list);
>   		flow_destroy_filter(tp, f);
>   	}
> -	kfree(head);
>   }
>
>   static unsigned long flow_get(struct tcf_proto *tp, u32 handle)
> @@ -653,6 +648,7 @@ static struct tcf_proto_ops cls_flow_ops __read_mostly = {
>   	.dump		= flow_dump,
>   	.walk		= flow_walk,
>   	.owner		= THIS_MODULE,
> +	.root_size	= sizeof(struct flow_head),
>   };
>
>   static int __init cls_flow_init(void)
> diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
> index ed00e8c..73cd277 100644
> --- a/net/sched/cls_fw.c
> +++ b/net/sched/cls_fw.c
> @@ -34,6 +34,7 @@
>   struct fw_head {
>   	struct fw_filter *ht[HTSIZE];
>   	u32 mask;
> +	bool init;
>   };
>
>   struct fw_filter {
> @@ -155,7 +156,6 @@ static void fw_destroy(struct tcf_proto *tp)
>   			fw_delete_filter(tp, f);
>   		}
>   	}
> -	kfree(head);
>   }
>
>   static int fw_delete(struct tcf_proto *tp, unsigned long arg)
> @@ -259,19 +259,12 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
>   	if (!handle)
>   		return -EINVAL;
>
> -	if (head == NULL) {
> +	if (!head->init) {
>   		u32 mask = 0xFFFFFFFF;
>   		if (tb[TCA_FW_MASK])
>   			mask = nla_get_u32(tb[TCA_FW_MASK]);
> -
> -		head = kzalloc(sizeof(struct fw_head), GFP_KERNEL);
> -		if (head == NULL)
> -			return -ENOBUFS;
>   		head->mask = mask;
> -
> -		tcf_tree_lock(tp);
> -		tp->root = head;
> -		tcf_tree_unlock(tp);
> +		head->init = true;
>   	}
>
>   	f = kzalloc(sizeof(struct fw_filter), GFP_KERNEL);
> @@ -388,6 +381,7 @@ static struct tcf_proto_ops cls_fw_ops __read_mostly = {
>   	.walk		=	fw_walk,
>   	.dump		=	fw_dump,
>   	.owner		=	THIS_MODULE,
> +	.root_size	= 	sizeof(struct fw_head),
>   };
>
>   static int __init init_fw(void)
> diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
> index 1ad3068..038f35f 100644
> --- a/net/sched/cls_route.c
> +++ b/net/sched/cls_route.c
> @@ -279,7 +279,6 @@ static void route4_destroy(struct tcf_proto *tp)
>   			kfree(b);
>   		}
>   	}
> -	kfree(head);
>   }
>
>   static int route4_delete(struct tcf_proto *tp, unsigned long arg)
> @@ -462,20 +461,9 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
>   		goto reinsert;
>   	}
>
> -	err = -ENOBUFS;
> -	if (head == NULL) {
> -		head = kzalloc(sizeof(struct route4_head), GFP_KERNEL);
> -		if (head == NULL)
> -			goto errout;
> -
> -		tcf_tree_lock(tp);
> -		tp->root = head;
> -		tcf_tree_unlock(tp);
> -	}
> -
>   	f = kzalloc(sizeof(struct route4_filter), GFP_KERNEL);
>   	if (f == NULL)
> -		goto errout;
> +		return -ENOBUFS;
>
>   	tcf_exts_init(&f->exts, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
>   	err = route4_set_parms(net, tp, base, f, handle, head, tb,
> @@ -613,6 +601,7 @@ static struct tcf_proto_ops cls_route4_ops __read_mostly = {
>   	.walk		=	route4_walk,
>   	.dump		=	route4_dump,
>   	.owner		=	THIS_MODULE,
> +	.root_size	=	sizeof(struct route4_head),
>   };
>
>   static int __init init_route4(void)
> diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
> index 19f8e5d..47930bc 100644
> --- a/net/sched/cls_rsvp.h
> +++ b/net/sched/cls_rsvp.h
> @@ -242,14 +242,7 @@ static void rsvp_put(struct tcf_proto *tp, unsigned long f)
>
>   static int rsvp_init(struct tcf_proto *tp)
>   {
> -	struct rsvp_head *data;
> -
> -	data = kzalloc(sizeof(struct rsvp_head), GFP_KERNEL);
> -	if (data) {
> -		tp->root = data;
> -		return 0;
> -	}
> -	return -ENOBUFS;
> +	return 0;
>   }
>
>   static void
> @@ -656,6 +649,7 @@ static struct tcf_proto_ops RSVP_OPS __read_mostly = {
>   	.walk		=	rsvp_walk,
>   	.dump		=	rsvp_dump,
>   	.owner		=	THIS_MODULE,
> +	.root_size	=	sizeof(struct rsvp_head),
>   };
>
>   static int __init init_rsvp(void)
> diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
> index eed8404..6454158 100644
> --- a/net/sched/cls_tcindex.c
> +++ b/net/sched/cls_tcindex.c
> @@ -118,18 +118,11 @@ static void tcindex_put(struct tcf_proto *tp, unsigned long f)
>
>   static int tcindex_init(struct tcf_proto *tp)
>   {
> -	struct tcindex_data *p;
> -
> -	pr_debug("tcindex_init(tp %p)\n", tp);
> -	p = kzalloc(sizeof(struct tcindex_data), GFP_KERNEL);
> -	if (!p)
> -		return -ENOMEM;
> +	struct tcindex_data *p = tp->root;
>
>   	p->mask = 0xffff;
>   	p->hash = DEFAULT_HASH_SIZE;
>   	p->fall_through = 1;
> -
> -	tp->root = p;
>   	return 0;
>   }
>
> @@ -407,15 +400,12 @@ static void tcindex_destroy(struct tcf_proto *tp)
>   	struct tcindex_data *p = tp->root;
>   	struct tcf_walker walker;
>
> -	pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p);
>   	walker.count = 0;
>   	walker.skip = 0;
>   	walker.fn = &tcindex_destroy_element;
>   	tcindex_walk(tp, &walker);
>   	kfree(p->perfect);
>   	kfree(p->h);
> -	kfree(p);
> -	tp->root = NULL;
>   }
>
>
> @@ -491,6 +481,7 @@ static struct tcf_proto_ops cls_tcindex_ops __read_mostly = {
>   	.walk		=	tcindex_walk,
>   	.dump		=	tcindex_dump,
>   	.owner		=	THIS_MODULE,
> +	.root_size	=	sizeof(struct tcindex_data),
>   };
>
>   static int __init init_tcindex(void)
> diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
> index 84c28da..678c2d72 100644
> --- a/net/sched/cls_u32.c
> +++ b/net/sched/cls_u32.c
> @@ -300,15 +300,11 @@ static u32 gen_new_htid(struct tc_u_common *tp_c)
>
>   static int u32_init(struct tcf_proto *tp)
>   {
> -	struct tc_u_hnode *root_ht;
> +	struct tc_u_hnode *root_ht = tp->root;
>   	struct tc_u_common *tp_c;
>
>   	tp_c = tp->q->u32_node;
>
> -	root_ht = kzalloc(sizeof(*root_ht), GFP_KERNEL);
> -	if (root_ht == NULL)
> -		return -ENOBUFS;
> -
>   	root_ht->divisor = 0;
>   	root_ht->refcnt++;
>   	root_ht->handle = tp_c ? gen_new_htid(tp_c) : 0x80000000;
> @@ -329,7 +325,6 @@ static int u32_init(struct tcf_proto *tp)
>   	tp_c->hlist = root_ht;
>   	root_ht->tp_c = tp_c;
>
> -	tp->root = root_ht;
>   	tp->data = tp_c;
>   	return 0;
>   }
> @@ -394,7 +389,6 @@ static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
>   	for (hn = &tp_c->hlist; *hn; hn = &(*hn)->next) {
>   		if (*hn == ht) {
>   			*hn = ht->next;
> -			kfree(ht);
>   			return 0;
>   		}
>   	}
> @@ -801,6 +795,7 @@ static struct tcf_proto_ops cls_u32_ops __read_mostly = {
>   	.walk		=	u32_walk,
>   	.dump		=	u32_dump,
>   	.owner		=	THIS_MODULE,
> +	.root_size	=	sizeof(struct tc_u_hnode),
>   };
>
>   static int __init init_u32(void)
> diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
> index 1313145..5fef7f4 100644
> --- a/net/sched/sch_api.c
> +++ b/net/sched/sch_api.c
> @@ -1829,6 +1829,7 @@ EXPORT_SYMBOL(tc_classify);
>   void tcf_destroy(struct tcf_proto *tp)
>   {
>   	tp->ops->destroy(tp);
> +	kfree(tp->root);
>   	module_put(tp->ops->owner);
>   	kfree(tp);
>   }
>

^ permalink raw reply

* [PATCH TRIVIAL] net: Spelling s/transmition/transmission/
From: Geert Uytterhoeven @ 2014-01-12 13:06 UTC (permalink / raw)
  To: Andy Gospodarek, David S. Miller, Jiri Kosina
  Cc: netdev, linux-wireless, Geert Uytterhoeven

From: Geert Uytterhoeven <geert+renesas@linux-m68k.org>

Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
---
 drivers/net/ethernet/tehuti/tehuti.c |    2 +-
 drivers/net/wan/hd64570.h            |    4 ++--
 drivers/net/wan/hd64572.h            |    2 +-
 net/nfc/hci/llc_shdlc.c              |    2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c
index 4f1d2549130e..2ead87759ab4 100644
--- a/drivers/net/ethernet/tehuti/tehuti.c
+++ b/drivers/net/ethernet/tehuti/tehuti.c
@@ -1764,7 +1764,7 @@ static void bdx_tx_cleanup(struct bdx_priv *priv)
 	WRITE_REG(priv, f->m.reg_RPTR, f->m.rptr & TXF_WPTR_WR_PTR);
 
 	/* We reclaimed resources, so in case the Q is stopped by xmit callback,
-	 * we resume the transmition and use tx_lock to synchronize with xmit.*/
+	 * we resume the transmission and use tx_lock to synchronize with xmit.*/
 	spin_lock(&priv->tx_lock);
 	priv->tx_level += tx_level;
 	BDX_ASSERT(priv->tx_level <= 0 || priv->tx_level > BDX_MAX_TX_LEVEL);
diff --git a/drivers/net/wan/hd64570.h b/drivers/net/wan/hd64570.h
index e4f539ad071b..10963e8f4b39 100644
--- a/drivers/net/wan/hd64570.h
+++ b/drivers/net/wan/hd64570.h
@@ -159,7 +159,7 @@ typedef struct {
 /* Packet Descriptor Status bits */
 
 #define ST_TX_EOM     0x80	/* End of frame */
-#define ST_TX_EOT     0x01	/* End of transmition */
+#define ST_TX_EOT     0x01	/* End of transmission */
 
 #define ST_RX_EOM     0x80	/* End of frame */
 #define ST_RX_SHORT   0x40	/* Short frame */
@@ -211,7 +211,7 @@ typedef struct {
 
 #define CTL_NORTS     0x01
 #define CTL_IDLE      0x10	/* Transmit an idle pattern */
-#define CTL_UDRNC     0x20	/* Idle after CRC or FCS+flag transmition */
+#define CTL_UDRNC     0x20	/* Idle after CRC or FCS+flag transmission */
 
 #define ST0_TXRDY     0x02	/* TX ready */
 #define ST0_RXRDY     0x01	/* RX ready */
diff --git a/drivers/net/wan/hd64572.h b/drivers/net/wan/hd64572.h
index 96567c2dc4db..22137ee669cf 100644
--- a/drivers/net/wan/hd64572.h
+++ b/drivers/net/wan/hd64572.h
@@ -218,7 +218,7 @@ typedef struct {
 #define ST_TX_EOM     0x80	/* End of frame */
 #define ST_TX_UNDRRUN 0x08
 #define ST_TX_OWNRSHP 0x02
-#define ST_TX_EOT     0x01	/* End of transmition */
+#define ST_TX_EOT     0x01	/* End of transmission */
 
 #define ST_RX_EOM     0x80	/* End of frame */
 #define ST_RX_SHORT   0x40	/* Short frame */
diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c
index 27b313befc35..3e53c1e029dc 100644
--- a/net/nfc/hci/llc_shdlc.c
+++ b/net/nfc/hci/llc_shdlc.c
@@ -300,7 +300,7 @@ static void llc_shdlc_rcv_rej(struct llc_shdlc *shdlc, int y_nr)
 {
 	struct sk_buff *skb;
 
-	pr_debug("remote asks retransmition from frame %d\n", y_nr);
+	pr_debug("remote asks retransmission from frame %d\n", y_nr);
 
 	if (llc_shdlc_x_lteq_y_lt_z(shdlc->dnr, y_nr, shdlc->ns)) {
 		if (shdlc->t2_active) {
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH TRIVIAL] net: amd8111e: Spelling s/recive/receive/
From: Geert Uytterhoeven @ 2014-01-12 13:02 UTC (permalink / raw)
  To: Jiri Kosina, netdev; +Cc: Geert Uytterhoeven

From: Geert Uytterhoeven <geert+renesas@linux-m68k.org>

Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
---
 drivers/net/ethernet/amd/amd8111e.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/amd/amd8111e.h b/drivers/net/ethernet/amd/amd8111e.h
index 8baa3527ba74..be19c3058d69 100644
--- a/drivers/net/ethernet/amd/amd8111e.h
+++ b/drivers/net/ethernet/amd/amd8111e.h
@@ -753,7 +753,7 @@ struct amd8111e_priv{
 	const char *name;
 	struct pci_dev *pci_dev;	/* Ptr to the associated pci_dev */
 	struct net_device* amd8111e_net_dev; 	/* ptr to associated net_device */
-	/* Transmit and recive skbs */
+	/* Transmit and receive skbs */
 	struct sk_buff *tx_skbuff[NUM_TX_BUFFERS];
 	struct sk_buff *rx_skbuff[NUM_RX_BUFFERS];
 	/* Transmit and receive dma mapped addr */
-- 
1.7.9.5

^ permalink raw reply related

* Re: [Patch net-next 5/7] net_sched: avoid casting void pointer
From: Jamal Hadi Salim @ 2014-01-12 12:55 UTC (permalink / raw)
  To: Cong Wang, netdev; +Cc: David S. Miller
In-Reply-To: <1389312845-10304-6-git-send-email-xiyou.wangcong@gmail.com>

On 01/09/14 19:14, Cong Wang wrote:
> tp->root is a void* pointer, no need to cast it.
>
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>


Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>

cheers,
jamal

^ permalink raw reply

* Re: [Patch net-next 4/7] net_sched: optimize tcf_match_indev()
From: Jamal Hadi Salim @ 2014-01-12 12:50 UTC (permalink / raw)
  To: Cong Wang, netdev; +Cc: David S. Miller
In-Reply-To: <1389312845-10304-5-git-send-email-xiyou.wangcong@gmail.com>

On 01/09/14 19:14, Cong Wang wrote:
> tcf_match_indev() is called in fast path, it is not wise to
> search for a netdev by ifindex and then compare by its name,
> just compare the ifindex.
>
> Also, dev->name could be changed by user-space, therefore
> the match would be always fail, but dev->ifindex could
> be consistent.
>
> BTW, this will also save some bytes from the core struct of u32.
>

excellent.

Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>

cheers,
jamal

^ permalink raw reply

* [PATCH net-next] bnx2x: Correct default Tx switching behaviour
From: Yuval Mintz @ 2014-01-12 12:37 UTC (permalink / raw)
  To: davem, netdev; +Cc: Yuval Mintz, Ariel Elior

With this patch bnx2x will configure the PF to perform Tx switching on
out-going traffic as soon as SR-IOV is dynamically enabled and de-activate
it when it is disabled.
This will allow VFs to communicate with their parent PFs.

Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com>
Signed-off-by: Ariel Elior <ariele@broadcom.com>
---
Hi Dave,

Please consider applying this to `net-next'.

Thanks,
Yuval
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x.h       |  1 +
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  3 ++
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c    |  7 +++
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h    |  4 +-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 61 +++++++++++++++++++++++
 5 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index eb105ab..e800b01 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1542,6 +1542,7 @@ struct bnx2x {
 #define NO_ISCSI_FLAG			(1 << 14)
 #define NO_FCOE_FLAG			(1 << 15)
 #define BC_SUPPORTS_PFC_STATS		(1 << 17)
+#define TX_SWITCHING			(1 << 18)
 #define BC_SUPPORTS_FCOE_FEATURES	(1 << 19)
 #define USING_SINGLE_MSIX_FLAG		(1 << 20)
 #define BC_SUPPORTS_DCBX_MSG_NON_PMF	(1 << 21)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 18498fe..1fdc8a3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -3001,6 +3001,9 @@ static unsigned long bnx2x_get_common_flags(struct bnx2x *bp,
 	if (zero_stats)
 		__set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags);
 
+	if (bp->flags & TX_SWITCHING)
+		__set_bit(BNX2X_Q_FLG_TX_SWITCH, &flags);
+
 	__set_bit(BNX2X_Q_FLG_PCSUM_ON_PKT, &flags);
 	__set_bit(BNX2X_Q_FLG_TUN_INC_INNER_IP_ID, &flags);
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index 98cccd4..6036405 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -4988,6 +4988,13 @@ static void bnx2x_q_fill_update_data(struct bnx2x *bp,
 		test_bit(BNX2X_Q_UPDATE_SILENT_VLAN_REM, &params->update_flags);
 	data->silent_vlan_value = cpu_to_le16(params->silent_removal_value);
 	data->silent_vlan_mask = cpu_to_le16(params->silent_removal_mask);
+
+	/* tx switching */
+	data->tx_switching_flg =
+		test_bit(BNX2X_Q_UPDATE_TX_SWITCHING, &params->update_flags);
+	data->tx_switching_change_flg =
+		test_bit(BNX2X_Q_UPDATE_TX_SWITCHING_CHNG,
+			 &params->update_flags);
 }
 
 static inline int bnx2x_q_send_update(struct bnx2x *bp,
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
index 6a53c15..d34664f 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
@@ -770,7 +770,9 @@ enum {
 	BNX2X_Q_UPDATE_DEF_VLAN_EN,
 	BNX2X_Q_UPDATE_DEF_VLAN_EN_CHNG,
 	BNX2X_Q_UPDATE_SILENT_VLAN_REM_CHNG,
-	BNX2X_Q_UPDATE_SILENT_VLAN_REM
+	BNX2X_Q_UPDATE_SILENT_VLAN_REM,
+	BNX2X_Q_UPDATE_TX_SWITCHING_CHNG,
+	BNX2X_Q_UPDATE_TX_SWITCHING
 };
 
 /* Allowed Queue states */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index 31ab924..049edd1 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -3130,6 +3130,60 @@ void bnx2x_unlock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf,
 	   vf->abs_vfid, vf->op_current);
 }
 
+static int bnx2x_set_pf_tx_switching(struct bnx2x *bp, bool enable)
+{
+	struct bnx2x_queue_state_params q_params;
+	u32 prev_flags;
+	int i, rc;
+
+	/* Verify changes are needed and record current Tx switching state */
+	prev_flags = bp->flags;
+	if (enable)
+		bp->flags |= TX_SWITCHING;
+	else
+		bp->flags &= ~TX_SWITCHING;
+	if (prev_flags == bp->flags)
+		return 0;
+
+	/* Verify state enables the sending of queue ramrods */
+	if ((bp->state != BNX2X_STATE_OPEN) ||
+	    (bnx2x_get_q_logical_state(bp,
+				      &bnx2x_sp_obj(bp, &bp->fp[0]).q_obj) !=
+	     BNX2X_Q_LOGICAL_STATE_ACTIVE))
+		return 0;
+
+	/* send q. update ramrod to configure Tx switching */
+	memset(&q_params, 0, sizeof(q_params));
+	__set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags);
+	q_params.cmd = BNX2X_Q_CMD_UPDATE;
+	__set_bit(BNX2X_Q_UPDATE_TX_SWITCHING_CHNG,
+		  &q_params.params.update.update_flags);
+	if (enable)
+		__set_bit(BNX2X_Q_UPDATE_TX_SWITCHING,
+			  &q_params.params.update.update_flags);
+	else
+		__clear_bit(BNX2X_Q_UPDATE_TX_SWITCHING,
+			    &q_params.params.update.update_flags);
+
+	/* send the ramrod on all the queues of the PF */
+	for_each_eth_queue(bp, i) {
+		struct bnx2x_fastpath *fp = &bp->fp[i];
+
+		/* Set the appropriate Queue object */
+		q_params.q_obj = &bnx2x_sp_obj(bp, fp).q_obj;
+
+		/* Update the Queue state */
+		rc = bnx2x_queue_state_change(bp, &q_params);
+		if (rc) {
+			BNX2X_ERR("Failed to configure Tx switching\n");
+			return rc;
+		}
+	}
+
+	DP(BNX2X_MSG_IOV, "%s Tx Switching\n", enable ? "Enabled" : "Disabled");
+	return 0;
+}
+
 int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param)
 {
 	struct bnx2x *bp = netdev_priv(pci_get_drvdata(dev));
@@ -3157,12 +3211,14 @@ int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param)
 
 	bp->requested_nr_virtfn = num_vfs_param;
 	if (num_vfs_param == 0) {
+		bnx2x_set_pf_tx_switching(bp, false);
 		pci_disable_sriov(dev);
 		return 0;
 	} else {
 		return bnx2x_enable_sriov(bp);
 	}
 }
+
 #define IGU_ENTRY_SIZE 4
 
 int bnx2x_enable_sriov(struct bnx2x *bp)
@@ -3240,6 +3296,11 @@ int bnx2x_enable_sriov(struct bnx2x *bp)
 	 */
 	DP(BNX2X_MSG_IOV, "about to call enable sriov\n");
 	bnx2x_disable_sriov(bp);
+
+	rc = bnx2x_set_pf_tx_switching(bp, true);
+	if (rc)
+		return rc;
+
 	rc = pci_enable_sriov(bp->pdev, req_vfs);
 	if (rc) {
 		BNX2X_ERR("pci_enable_sriov failed with %d\n", rc);
-- 
1.8.1.227.g44fe835

^ permalink raw reply related

* Re: [Patch net-next 3/7] net_sched: add struct net pointer to tcf_proto_ops->dump
From: Jamal Hadi Salim @ 2014-01-12 12:46 UTC (permalink / raw)
  To: Cong Wang, netdev; +Cc: David S. Miller
In-Reply-To: <1389312845-10304-4-git-send-email-xiyou.wangcong@gmail.com>

On 01/09/14 19:14, Cong Wang wrote:
> It will be needed by the next patch.
>
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>


Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>

cheers,
jamal

^ permalink raw reply

* Re: net/mlx4_en: call gro handler for encapsulated frames
From: Amir Vadai @ 2014-01-12 12:43 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev, Or Gerlitz, Jerry Chu
In-Reply-To: <1389292213.31367.49.camel@edumazet-glaptop2.roam.corp.google.com>

On 09/01/14 10:30 -0800, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
> 
> In order to use the native GRO handling of encapsulated protocols on
> mlx4, we need to call napi_gro_receive() instead of netif_receive_skb()
> unless busy polling is in action.
> 
> While we are at it, rename mlx4_en_cq_ll_polling() to
> mlx4_en_cq_busy_polling()
> 
> Tested with GRE tunnel : GRO aggregation is now performed on the
> ethernet device instead of being done later on gre device.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Amir Vadai <amirv@mellanox.com>
> Cc: Jerry Chu <hkchu@google.com>
> Cc: Or Gerlitz <ogerlitz@mellanox.com>
> ---
>  drivers/net/ethernet/mellanox/mlx4/en_rx.c   |    8 +++++---
>  drivers/net/ethernet/mellanox/mlx4/mlx4_en.h |    4 ++--
>  2 files changed, 7 insertions(+), 5 deletions(-)
> 

Acked-By: Amir Vadai <amirv@mellanox.com>

^ permalink raw reply

* Re: [Patch net-next 2/7] net_sched: act: clean up notification functions
From: Jamal Hadi Salim @ 2014-01-12 12:38 UTC (permalink / raw)
  To: Cong Wang, netdev; +Cc: David S. Miller
In-Reply-To: <1389312845-10304-3-git-send-email-xiyou.wangcong@gmail.com>

On 01/09/14 19:14, Cong Wang wrote:
> Refactor tcf_add_notify() and factor out tcf_del_notify().
>
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>


Thanks Cong!

Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>

^ permalink raw reply


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