Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next v2 1/3] net: factor out a helper to decrement the skb refcount
From: Paolo Abeni @ 2017-06-06 14:23 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Eric Dumazet
In-Reply-To: <cover.1496756090.git.pabeni@redhat.com>

The same code is replicated in 3 different places; move it to a
common helper.

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Acked-by: Eric Dumazet <edumazet@google.com>
---
 include/linux/skbuff.h | 13 +++++++++++++
 net/core/datagram.c    |  4 +---
 net/core/skbuff.c      | 14 ++++----------
 3 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 45a59c1..3c25fca 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -867,6 +867,19 @@ static inline unsigned int skb_napi_id(const struct sk_buff *skb)
 #endif
 }
 
+/* decrement the reference count and return true if we can free the skb */
+static inline bool skb_unref(struct sk_buff *skb)
+{
+	if (unlikely(!skb))
+		return false;
+	if (likely(atomic_read(&skb->users) == 1))
+		smp_rmb();
+	else if (likely(!atomic_dec_and_test(&skb->users)))
+		return false;
+
+	return true;
+}
+
 void kfree_skb(struct sk_buff *skb);
 void kfree_skb_list(struct sk_buff *segs);
 void skb_tx_error(struct sk_buff *skb);
diff --git a/net/core/datagram.c b/net/core/datagram.c
index bc46118..e5311a7 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -330,9 +330,7 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len)
 {
 	bool slow;
 
-	if (likely(atomic_read(&skb->users) == 1))
-		smp_rmb();
-	else if (likely(!atomic_dec_and_test(&skb->users))) {
+	if (!skb_unref(skb)) {
 		sk_peek_offset_bwd(sk, len);
 		return;
 	}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 780b7c1..c81b828 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -694,12 +694,9 @@ EXPORT_SYMBOL(__kfree_skb);
  */
 void kfree_skb(struct sk_buff *skb)
 {
-	if (unlikely(!skb))
-		return;
-	if (likely(atomic_read(&skb->users) == 1))
-		smp_rmb();
-	else if (likely(!atomic_dec_and_test(&skb->users)))
+	if (!skb_unref(skb))
 		return;
+
 	trace_kfree_skb(skb, __builtin_return_address(0));
 	__kfree_skb(skb);
 }
@@ -746,12 +743,9 @@ EXPORT_SYMBOL(skb_tx_error);
  */
 void consume_skb(struct sk_buff *skb)
 {
-	if (unlikely(!skb))
-		return;
-	if (likely(atomic_read(&skb->users) == 1))
-		smp_rmb();
-	else if (likely(!atomic_dec_and_test(&skb->users)))
+	if (!skb_unref(skb))
 		return;
+
 	trace_consume_skb(skb);
 	__kfree_skb(skb);
 }
-- 
2.9.4

^ permalink raw reply related

* [PATCH net-next v2 2/3] udp: avoid a cache miss on dequeue
From: Paolo Abeni @ 2017-06-06 14:23 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Eric Dumazet
In-Reply-To: <cover.1496756090.git.pabeni@redhat.com>

Since UDP no more uses sk->destructor, we can clear completely
the skb head state before enqueuing. Amend and use
skb_release_head_state() for that.

All head states share a single cacheline, which is not
normally used/accesses on dequeue. We can avoid entirely accessing
such cacheline implementing and using in the UDP code a specialized
skb free helper which ignores the skb head state.

This saves a cacheline miss at skb deallocation time.

v1 -> v2:
  replaced secpath_reset() with skb_release_head_state()

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
 include/linux/skbuff.h |  2 ++
 net/core/skbuff.c      | 24 ++++++++++++++++++++----
 net/ipv4/udp.c         |  6 +++++-
 3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 3c25fca..ddfb964 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -880,10 +880,12 @@ static inline bool skb_unref(struct sk_buff *skb)
 	return true;
 }
 
+void skb_release_head_state(struct sk_buff *skb);
 void kfree_skb(struct sk_buff *skb);
 void kfree_skb_list(struct sk_buff *segs);
 void skb_tx_error(struct sk_buff *skb);
 void consume_skb(struct sk_buff *skb);
+void consume_stateless_skb(struct sk_buff *skb);
 void  __kfree_skb(struct sk_buff *skb);
 extern struct kmem_cache *skbuff_head_cache;
 
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index c81b828..786cb42 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -643,12 +643,10 @@ static void kfree_skbmem(struct sk_buff *skb)
 	kmem_cache_free(skbuff_fclone_cache, fclones);
 }
 
-static void skb_release_head_state(struct sk_buff *skb)
+void skb_release_head_state(struct sk_buff *skb)
 {
 	skb_dst_drop(skb);
-#ifdef CONFIG_XFRM
-	secpath_put(skb->sp);
-#endif
+	secpath_reset(skb);
 	if (skb->destructor) {
 		WARN_ON(in_irq());
 		skb->destructor(skb);
@@ -751,6 +749,24 @@ void consume_skb(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(consume_skb);
 
+/**
+ *	consume_stateless_skb - free an skbuff, assuming it is stateless
+ *	@skb: buffer to free
+ *
+ *	Works like consume_skb(), but this variant assumes that all the head
+ *	states have been already dropped.
+ */
+void consume_stateless_skb(struct sk_buff *skb)
+{
+	if (!skb_unref(skb))
+		return;
+
+	trace_consume_skb(skb);
+	if (likely(skb->head))
+		skb_release_data(skb);
+	kfree_skbmem(skb);
+}
+
 void __kfree_skb_flush(void)
 {
 	struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index fdcb743..d8b265f 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1359,7 +1359,8 @@ void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len)
 		sk_peek_offset_bwd(sk, len);
 		unlock_sock_fast(sk, slow);
 	}
-	consume_skb(skb);
+
+	consume_stateless_skb(skb);
 }
 EXPORT_SYMBOL_GPL(skb_consume_udp);
 
@@ -1739,6 +1740,9 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 		sk_mark_napi_id_once(sk, skb);
 	}
 
+	/* clear all pending head states while they are hot in the cache */
+	skb_release_head_state(skb);
+
 	rc = __udp_enqueue_schedule_skb(sk, skb);
 	if (rc < 0) {
 		int is_udplite = IS_UDPLITE(sk);
-- 
2.9.4

^ permalink raw reply related

* [PATCH net-next v2 3/3] udp: try to avoid 2 cache miss on dequeue
From: Paolo Abeni @ 2017-06-06 14:23 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Eric Dumazet
In-Reply-To: <cover.1496756090.git.pabeni@redhat.com>

when udp_recvmsg() is executed, on x86_64 and other archs, most skb
fields are on cold cachelines.
If the skb are linear and the kernel don't need to compute the udp
csum, only a handful of skb fields are required by udp_recvmsg().
Since we already use skb->dev_scratch to cache hot data, and
there are 32 bits unused on 64 bit archs, use such field to cache
as much data as we can, and try to prefetch on dequeue the relevant
fields that are left out.

This can save up to 2 cache miss per packet.

v1 -> v2:
  - changed udp_dev_scratch fields types to u{32,16} variant,
    replaced bitfield with bool

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
 net/ipv4/udp.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 103 insertions(+), 11 deletions(-)

diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index d8b265f..2bc638c 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1163,6 +1163,83 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,
 	return ret;
 }
 
+/* Copy as much information as possible into skb->dev_scratch to avoid
+ * possibly multiple cache miss on dequeue();
+ */
+#if BITS_PER_LONG == 64
+
+/* we can store multiple info here: truesize, len and the bit needed to
+ * compute skb_csum_unnecessary will be on cold cache lines at recvmsg
+ * time.
+ * skb->len can be stored on 16 bits since the udp header has been already
+ * validated and pulled.
+ */
+struct udp_dev_scratch {
+	u32 truesize;
+	u16 len;
+	bool is_linear;
+	bool csum_unnecessary;
+};
+
+static void udp_set_dev_scratch(struct sk_buff *skb)
+{
+	struct udp_dev_scratch *scratch;
+
+	BUILD_BUG_ON(sizeof(struct udp_dev_scratch) > sizeof(long));
+	scratch = (struct udp_dev_scratch *)&skb->dev_scratch;
+	scratch->truesize = skb->truesize;
+	scratch->len = skb->len;
+	scratch->csum_unnecessary = !!skb_csum_unnecessary(skb);
+	scratch->is_linear = !skb_is_nonlinear(skb);
+}
+
+static int udp_skb_truesize(struct sk_buff *skb)
+{
+	return ((struct udp_dev_scratch *)&skb->dev_scratch)->truesize;
+}
+
+static unsigned int udp_skb_len(struct sk_buff *skb)
+{
+	return ((struct udp_dev_scratch *)&skb->dev_scratch)->len;
+}
+
+static bool udp_skb_csum_unnecessary(struct sk_buff *skb)
+{
+	return ((struct udp_dev_scratch *)&skb->dev_scratch)->csum_unnecessary;
+}
+
+static bool udp_skb_is_linear(struct sk_buff *skb)
+{
+	return ((struct udp_dev_scratch *)&skb->dev_scratch)->is_linear;
+}
+
+#else
+static void udp_set_dev_scratch(struct sk_buff *skb)
+{
+	skb->dev_scratch = skb->truesize;
+}
+
+static int udp_skb_truesize(struct sk_buff *skb)
+{
+	return skb->dev_scratch;
+}
+
+static unsigned int udp_skb_len(struct sk_buff *skb)
+{
+	return skb->len;
+}
+
+static bool udp_skb_csum_unnecessary(struct sk_buff *skb)
+{
+	return skb_csum_unnecessary(skb);
+}
+
+static bool udp_skb_is_linear(struct sk_buff *skb)
+{
+	return !skb_is_nonlinear(skb);
+}
+#endif
+
 /* fully reclaim rmem/fwd memory allocated for skb */
 static void udp_rmem_release(struct sock *sk, int size, int partial,
 			     bool rx_queue_lock_held)
@@ -1213,14 +1290,16 @@ static void udp_rmem_release(struct sock *sk, int size, int partial,
  */
 void udp_skb_destructor(struct sock *sk, struct sk_buff *skb)
 {
-	udp_rmem_release(sk, skb->dev_scratch, 1, false);
+	prefetch(&skb->data);
+	udp_rmem_release(sk, udp_skb_truesize(skb), 1, false);
 }
 EXPORT_SYMBOL(udp_skb_destructor);
 
 /* as above, but the caller held the rx queue lock, too */
 static void udp_skb_dtor_locked(struct sock *sk, struct sk_buff *skb)
 {
-	udp_rmem_release(sk, skb->dev_scratch, 1, true);
+	prefetch(&skb->data);
+	udp_rmem_release(sk, udp_skb_truesize(skb), 1, true);
 }
 
 /* Idea of busylocks is to let producers grab an extra spinlock
@@ -1274,10 +1353,7 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
 		busy = busylock_acquire(sk);
 	}
 	size = skb->truesize;
-	/* Copy skb->truesize into skb->dev_scratch to avoid a cache line miss
-	 * in udp_skb_destructor()
-	 */
-	skb->dev_scratch = size;
+	udp_set_dev_scratch(skb);
 
 	/* we drop only if the receive buf is full and the receive
 	 * queue contains some other skb
@@ -1515,6 +1591,18 @@ struct sk_buff *__skb_recv_udp(struct sock *sk, unsigned int flags,
 }
 EXPORT_SYMBOL_GPL(__skb_recv_udp);
 
+static int copy_linear_skb(struct sk_buff *skb, int len, int off,
+			   struct iov_iter *to)
+{
+	int n, copy = len - off;
+
+	n = copy_to_iter(skb->data + off, copy, to);
+	if (n == copy)
+		return 0;
+
+	return -EFAULT;
+}
+
 /*
  * 	This should be easy, if there is something there we
  * 	return it, otherwise we block.
@@ -1541,7 +1629,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
 	if (!skb)
 		return err;
 
-	ulen = skb->len;
+	ulen = udp_skb_len(skb);
 	copied = len;
 	if (copied > ulen - off)
 		copied = ulen - off;
@@ -1556,14 +1644,18 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
 
 	if (copied < ulen || peeking ||
 	    (is_udplite && UDP_SKB_CB(skb)->partial_cov)) {
-		checksum_valid = !udp_lib_checksum_complete(skb);
+		checksum_valid = udp_skb_csum_unnecessary(skb) ||
+				!__udp_lib_checksum_complete(skb);
 		if (!checksum_valid)
 			goto csum_copy_err;
 	}
 
-	if (checksum_valid || skb_csum_unnecessary(skb))
-		err = skb_copy_datagram_msg(skb, off, msg, copied);
-	else {
+	if (checksum_valid || udp_skb_csum_unnecessary(skb)) {
+		if (udp_skb_is_linear(skb))
+			err = copy_linear_skb(skb, copied, off, &msg->msg_iter);
+		else
+			err = skb_copy_datagram_msg(skb, off, msg, copied);
+	} else {
 		err = skb_copy_and_csum_datagram_msg(skb, off, msg);
 
 		if (err == -EINVAL)
-- 
2.9.4

^ permalink raw reply related

* Re: [PATCH] net: ethoc: enable NAPI before poll may be scheduled
From: Florian Fainelli @ 2017-06-06 14:26 UTC (permalink / raw)
  To: Max Filippov, netdev
  Cc: David S. Miller, Thierry Reding, Tobias Klauser, stable
In-Reply-To: <1496712676-11862-1-git-send-email-jcmvbkbc@gmail.com>



On 06/05/2017 06:31 PM, Max Filippov wrote:
> ethoc_reset enables device interrupts, ethoc_interrupt may schedule a
> NAPI poll before NAPI is enabled in the ethoc_open, which results in
> device being unable to send or receive anything until it's closed and
> reopened. In case the device is flooded with ingress packets it may be
> unable to recover at all.
> Move napi_enable above ethoc_reset in the ethoc_open to fix that.
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>

Fixes: a1702857724f ("net: Add support for the OpenCores 10/100 Mbps
Ethernet MAC.")

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

^ permalink raw reply

* [PATCH net] bnx2x: fix pf2vf bulletin DMA mapping leak
From: Michal Schmidt @ 2017-06-06 14:30 UTC (permalink / raw)
  To: netdev; +Cc: Yuval.Mintz

When freeing VF's DMA mappings, an already NULLed pointer was checked
again due to an apparent copy&paste error. Consequently, the pf2vf
bulletin DMA mapping was not freed.

Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index bdfd53b46b..870ea001a7 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -3042,7 +3042,7 @@ void bnx2x_vf_pci_dealloc(struct bnx2x *bp)
 {
 	BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping,
 		       sizeof(struct bnx2x_vf_mbx_msg));
-	BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping,
+	BNX2X_PCI_FREE(bp->pf2vf_bulletin, bp->pf2vf_bulletin_mapping,
 		       sizeof(union pf_vf_bulletin));
 }
 
-- 
2.13.0

^ permalink raw reply related

* Re: [PATCH net] net: stmmac: fix completely hung TX when using TSO
From: Florian Fainelli @ 2017-06-06 14:31 UTC (permalink / raw)
  To: Niklas Cassel, Giuseppe Cavallaro, Alexandre Torgue
  Cc: Niklas Cassel, netdev, linux-kernel
In-Reply-To: <20170606072501.16560-1-niklas.cassel@axis.com>



On 06/06/2017 12:25 AM, Niklas Cassel wrote:
> stmmac_tso_allocator can fail to set the Last Descriptor bit
> on a descriptor that actually was the last descriptor.
> 
> This happens when the buffer of the last descriptor ends
> up having a size of exactly TSO_MAX_BUFF_SIZE.
> 
> When the IP eventually reaches the next last descriptor,
> which actually has the bit set, the DMA will hang.
> 
> When the DMA hangs, we get a tx timeout, however,
> since stmmac does not do a complete reset of the IP
> in stmmac_tx_timeout, we end up in a state with
> completely hung TX.
> 
> Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>

This should have:

Fixes: f748be531d70 ("stmmac: support new GMAC4")

right?

> ---
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 68a188e74c54..440bea049a7f 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -2723,7 +2723,7 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,
>  
>  		priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size,
>  			0, 1,
> -			(last_segment) && (buff_size < TSO_MAX_BUFF_SIZE),
> +			(last_segment) && (tmp_len <= TSO_MAX_BUFF_SIZE),
>  			0, 0);
>  
>  		tmp_len -= TSO_MAX_BUFF_SIZE;
> 

-- 
Florian

^ permalink raw reply

* Re: [PATCH] net: mvpp2: do not bypass the mvpp22_port_mii_set function
From: Antoine Tenart @ 2017-06-06 14:38 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Antoine Tenart, Thomas Petazzoni, netdev, linux, gregory.clement,
	mw, davem, linux-arm-kernel
In-Reply-To: <9ef70606-0918-fc4f-535b-dd1fc3475cb6@gmail.com>

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

Hi Florian,

On Tue, Jun 06, 2017 at 07:24:35AM -0700, Florian Fainelli wrote:
> On 06/06/2017 06:51 AM, Antoine Tenart wrote:
> > On Tue, Jun 06, 2017 at 03:45:35PM +0200, Thomas Petazzoni wrote:
> > 
> >> I am wondering if we shouldn't Cc: stable as well. I don't think we
> >> have seen issues on our side because U-Boot does the necessary
> >> initialization, but people using other bootloaders might have issues.
> > 
> > Yes, that might be safer to cc stable. I'll do this as well.
> 
> David queues network patches for stable provided that you submit those
> against his "net" tree [1] and there is an appropriate Fixes tag (which
> Thomas provided).
> 
> [1]:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/networking/netdev-FAQ.txt#n114

That's good to know!

Thanks,
Antoine

-- 
Antoine Ténart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* [patch net-next] net: propagate tc filter chain index down the ndo_setup_tc call
From: Jiri Pirko @ 2017-06-06 15:00 UTC (permalink / raw)
  To: netdev
  Cc: davem, jhs, xiyou.wangcong, dsa, edumazet, daniel,
	alexander.h.duyck, simon.horman, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

We need to push the chain index down to the drivers, so they have the
information to which chain the rule belongs. For now, no driver supports
multichain offload, so only chain 0 is supported. This is needed to
prevent chain squashes during offload for now. Later this will be used
to implement multichain offload.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c            |  3 ++-
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c     |  4 ++--
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h     |  4 ++--
 drivers/net/ethernet/broadcom/bnxt/bnxt.c           |  4 ++--
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c     |  7 +++++--
 drivers/net/ethernet/freescale/dpaa/dpaa_eth.c      |  4 ++--
 drivers/net/ethernet/intel/fm10k/fm10k_netdev.c     |  4 ++--
 drivers/net/ethernet/intel/i40e/i40e_main.c         |  3 ++-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c       |  7 +++++--
 drivers/net/ethernet/mellanox/mlx4/en_netdev.c      |  3 ++-
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c   |  6 +++++-
 drivers/net/ethernet/mellanox/mlx5/core/en_rep.c    |  7 ++++++-
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c      |  6 +++++-
 drivers/net/ethernet/netronome/nfp/nfp_net_common.c |  7 +++++--
 drivers/net/ethernet/sfc/efx.h                      |  4 ++--
 drivers/net/ethernet/sfc/falcon/efx.h               |  4 ++--
 drivers/net/ethernet/sfc/falcon/tx.c                |  4 ++--
 drivers/net/ethernet/sfc/tx.c                       |  4 ++--
 drivers/net/ethernet/ti/netcp_core.c                |  4 ++--
 include/linux/netdevice.h                           |  4 ++--
 net/dsa/slave.c                                     | 11 ++++++-----
 net/sched/cls_bpf.c                                 |  1 +
 net/sched/cls_flower.c                              | 10 ++++++----
 net/sched/cls_matchall.c                            |  9 +++++----
 net/sched/cls_u32.c                                 | 12 ++++++++----
 net/sched/sch_mqprio.c                              |  5 +++--
 26 files changed, 88 insertions(+), 53 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 5a2ad9c..a934bd5 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -1846,7 +1846,8 @@ static void xgbe_poll_controller(struct net_device *netdev)
 }
 #endif /* End CONFIG_NET_POLL_CONTROLLER */
 
-static int xgbe_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
+static int xgbe_setup_tc(struct net_device *netdev, u32 handle, u32 chain_index,
+			 __be16 proto,
 			 struct tc_to_netdev *tc_to_netdev)
 {
 	struct xgbe_prv_data *pdata = netdev_priv(netdev);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index eccb3d1..b92e2ca 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -4273,8 +4273,8 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc)
 	return 0;
 }
 
-int __bnx2x_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-		     struct tc_to_netdev *tc)
+int __bnx2x_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+		     __be16 proto, struct tc_to_netdev *tc)
 {
 	if (tc->type != TC_SETUP_MQPRIO)
 		return -EINVAL;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 243cb97..c26688d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -486,8 +486,8 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
 
 /* setup_tc callback */
 int bnx2x_setup_tc(struct net_device *dev, u8 num_tc);
-int __bnx2x_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-		     struct tc_to_netdev *tc);
+int __bnx2x_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+		     __be16 proto, struct tc_to_netdev *tc);
 
 int bnx2x_get_vf_config(struct net_device *dev, int vf,
 			struct ifla_vf_info *ivi);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index c1cd72a..11e8a86 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -7103,8 +7103,8 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
 	return 0;
 }
 
-static int bnxt_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-			 struct tc_to_netdev *ntc)
+static int bnxt_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+			 __be16 proto, struct tc_to_netdev *ntc)
 {
 	if (ntc->type != TC_SETUP_MQPRIO)
 		return -EINVAL;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 8c69046..c3902c5 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2698,12 +2698,15 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
 	return err;
 }
 
-static int cxgb_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-			 struct tc_to_netdev *tc)
+static int cxgb_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+			 __be16 proto, struct tc_to_netdev *tc)
 {
 	struct port_info *pi = netdev2pinfo(dev);
 	struct adapter *adap = netdev2adap(dev);
 
+	if (chain_index)
+		return -EOPNOTSUPP;
+
 	if (!(adap->flags & FULL_INIT_DONE)) {
 		dev_err(adap->pdev_dev,
 			"Failed to setup tc on port %d. Link Down?\n",
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 9a520e4..a5501af 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -342,8 +342,8 @@ static void dpaa_get_stats64(struct net_device *net_dev,
 	}
 }
 
-static int dpaa_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
-			 struct tc_to_netdev *tc)
+static int dpaa_setup_tc(struct net_device *net_dev, u32 handle,
+			 u32 chain_index, __be16 proto, struct tc_to_netdev *tc)
 {
 	struct dpaa_priv *priv = netdev_priv(net_dev);
 	u8 num_tc;
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index 24f2f6f..5e37387 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1265,8 +1265,8 @@ int fm10k_setup_tc(struct net_device *dev, u8 tc)
 	return err;
 }
 
-static int __fm10k_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-			    struct tc_to_netdev *tc)
+static int __fm10k_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+			    __be16 proto, struct tc_to_netdev *tc)
 {
 	if (tc->type != TC_SETUP_MQPRIO)
 		return -EINVAL;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index e4eb978..be808c9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -5509,7 +5509,8 @@ static int i40e_setup_tc(struct net_device *netdev, u8 tc)
 	return ret;
 }
 
-static int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
+static int __i40e_setup_tc(struct net_device *netdev, u32 handle,
+			   u32 chain_index, __be16 proto,
 			   struct tc_to_netdev *tc)
 {
 	if (tc->type != TC_SETUP_MQPRIO)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 54463f0..812319a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9200,11 +9200,14 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
 	return err;
 }
 
-static int __ixgbe_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-			    struct tc_to_netdev *tc)
+static int __ixgbe_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+			    __be16 proto, struct tc_to_netdev *tc)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
 
+	if (chain_index)
+		return -EOPNOTSUPP;
+
 	if (TC_H_MAJ(handle) == TC_H_MAJ(TC_H_INGRESS) &&
 	    tc->type == TC_SETUP_CLSU32) {
 		switch (tc->cls_u32->command) {
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 8243674..c1de75f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -86,7 +86,8 @@ int mlx4_en_setup_tc(struct net_device *dev, u8 up)
 	return 0;
 }
 
-static int __mlx4_en_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
+static int __mlx4_en_setup_tc(struct net_device *dev, u32 handle,
+			      u32 chain_index, __be16 proto,
 			      struct tc_to_netdev *tc)
 {
 	if (tc->type != TC_SETUP_MQPRIO)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index cdff04b..5afec0f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -2991,13 +2991,17 @@ static int mlx5e_setup_tc(struct net_device *netdev, u8 tc)
 }
 
 static int mlx5e_ndo_setup_tc(struct net_device *dev, u32 handle,
-			      __be16 proto, struct tc_to_netdev *tc)
+			      u32 chain_index, __be16 proto,
+			      struct tc_to_netdev *tc)
 {
 	struct mlx5e_priv *priv = netdev_priv(dev);
 
 	if (TC_H_MAJ(handle) != TC_H_MAJ(TC_H_INGRESS))
 		goto mqprio;
 
+	if (chain_index)
+		return -EOPNOTSUPP;
+
 	switch (tc->type) {
 	case TC_SETUP_CLSFLOWER:
 		switch (tc->cls_flower->command) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 79462c0..70c2b8d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -652,7 +652,8 @@ static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
 }
 
 static int mlx5e_rep_ndo_setup_tc(struct net_device *dev, u32 handle,
-				  __be16 proto, struct tc_to_netdev *tc)
+				  u32 chain_index, __be16 proto,
+				  struct tc_to_netdev *tc)
 {
 	struct mlx5e_priv *priv = netdev_priv(dev);
 
@@ -664,9 +665,13 @@ static int mlx5e_rep_ndo_setup_tc(struct net_device *dev, u32 handle,
 		struct net_device *uplink_dev = mlx5_eswitch_get_uplink_netdev(esw);
 
 		return uplink_dev->netdev_ops->ndo_setup_tc(uplink_dev, handle,
+							    chain_index,
 							    proto, tc);
 	}
 
+	if (chain_index)
+		return -EOPNOTSUPP;
+
 	switch (tc->type) {
 	case TC_SETUP_CLSFLOWER:
 		switch (tc->cls_flower->command) {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index f60e2ba..a2316d0 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1699,11 +1699,15 @@ static void mlxsw_sp_port_del_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
 }
 
 static int mlxsw_sp_setup_tc(struct net_device *dev, u32 handle,
-			     __be16 proto, struct tc_to_netdev *tc)
+			     u32 chain_index, __be16 proto,
+			     struct tc_to_netdev *tc)
 {
 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
 	bool ingress = TC_H_MAJ(handle) == TC_H_MAJ(TC_H_INGRESS);
 
+	if (chain_index)
+		return -EOPNOTSUPP;
+
 	switch (tc->type) {
 	case TC_SETUP_MATCHALL:
 		switch (tc->cls_mall->command) {
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index c3235d0..1ae7a63 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2682,11 +2682,14 @@ static void nfp_net_stat64(struct net_device *netdev,
 }
 
 static int
-nfp_net_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
-		 struct tc_to_netdev *tc)
+nfp_net_setup_tc(struct net_device *netdev, u32 handle, u32 chain_index,
+		 __be16 proto, struct tc_to_netdev *tc)
 {
 	struct nfp_net *nn = netdev_priv(netdev);
 
+	if (chain_index)
+		return -EOPNOTSUPP;
+
 	return nfp_app_setup_tc(nn->app, netdev, handle, proto, tc);
 }
 
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index a0c52e3..fcea937 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -32,8 +32,8 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
 				struct net_device *net_dev);
 netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
-int efx_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
-		 struct tc_to_netdev *tc);
+int efx_setup_tc(struct net_device *net_dev, u32 handle, u32 chain_index,
+		 __be16 proto, struct tc_to_netdev *tc);
 unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);
 extern unsigned int efx_piobuf_size;
 extern bool efx_separate_tx_channels;
diff --git a/drivers/net/ethernet/sfc/falcon/efx.h b/drivers/net/ethernet/sfc/falcon/efx.h
index c89456f..e5a7a40 100644
--- a/drivers/net/ethernet/sfc/falcon/efx.h
+++ b/drivers/net/ethernet/sfc/falcon/efx.h
@@ -32,8 +32,8 @@ netdev_tx_t ef4_hard_start_xmit(struct sk_buff *skb,
 				struct net_device *net_dev);
 netdev_tx_t ef4_enqueue_skb(struct ef4_tx_queue *tx_queue, struct sk_buff *skb);
 void ef4_xmit_done(struct ef4_tx_queue *tx_queue, unsigned int index);
-int ef4_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
-		 struct tc_to_netdev *tc);
+int ef4_setup_tc(struct net_device *net_dev, u32 handle, u32 chain_index,
+		 __be16 proto, struct tc_to_netdev *tc);
 unsigned int ef4_tx_max_skb_descs(struct ef4_nic *efx);
 extern bool ef4_separate_tx_channels;
 
diff --git a/drivers/net/ethernet/sfc/falcon/tx.c b/drivers/net/ethernet/sfc/falcon/tx.c
index f6daf09..f1520a4 100644
--- a/drivers/net/ethernet/sfc/falcon/tx.c
+++ b/drivers/net/ethernet/sfc/falcon/tx.c
@@ -425,8 +425,8 @@ void ef4_init_tx_queue_core_txq(struct ef4_tx_queue *tx_queue)
 				     efx->n_tx_channels : 0));
 }
 
-int ef4_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
-		 struct tc_to_netdev *ntc)
+int ef4_setup_tc(struct net_device *net_dev, u32 handle, u32 chain_index,
+		 __be16 proto, struct tc_to_netdev *ntc)
 {
 	struct ef4_nic *efx = netdev_priv(net_dev);
 	struct ef4_channel *channel;
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 3bdf87f..02d41eb 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -653,8 +653,8 @@ void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue)
 				     efx->n_tx_channels : 0));
 }
 
-int efx_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
-		 struct tc_to_netdev *ntc)
+int efx_setup_tc(struct net_device *net_dev, u32 handle, u32 chain_index,
+		 __be16 proto, struct tc_to_netdev *ntc)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	struct efx_channel *channel;
diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c
index e6222e5..9d52c3a 100644
--- a/drivers/net/ethernet/ti/netcp_core.c
+++ b/drivers/net/ethernet/ti/netcp_core.c
@@ -1877,8 +1877,8 @@ static u16 netcp_select_queue(struct net_device *dev, struct sk_buff *skb,
 	return 0;
 }
 
-static int netcp_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-			  struct tc_to_netdev *tc)
+static int netcp_setup_tc(struct net_device *dev, u32 handle, u32 chain_index,
+			  __be16 proto, struct tc_to_netdev *tc)
 {
 	u8 num_tc;
 	int i;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c50c921..524c777 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -972,7 +972,7 @@ struct xfrmdev_ops {
  *      with PF and querying it may introduce a theoretical security risk.
  * int (*ndo_set_vf_rss_query_en)(struct net_device *dev, int vf, bool setting);
  * int (*ndo_get_vf_port)(struct net_device *dev, int vf, struct sk_buff *skb);
- * int (*ndo_setup_tc)(struct net_device *dev, u32 handle,
+ * int (*ndo_setup_tc)(struct net_device *dev, u32 handle, u32 chain_index,
  *		       __be16 protocol, struct tc_to_netdev *tc);
  *	Called to setup any 'tc' scheduler, classifier or action on @dev.
  *	This is always called from the stack with the rtnl lock held and netif
@@ -1222,7 +1222,7 @@ struct net_device_ops {
 						   struct net_device *dev,
 						   int vf, bool setting);
 	int			(*ndo_setup_tc)(struct net_device *dev,
-						u32 handle,
+						u32 handle, u32 chain_index,
 						__be16 protocol,
 						struct tc_to_netdev *tc);
 #if IS_ENABLED(CONFIG_FCOE)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 1cfdb31..5f3caee 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -836,10 +836,13 @@ static void dsa_slave_del_cls_matchall(struct net_device *dev,
 }
 
 static int dsa_slave_setup_tc(struct net_device *dev, u32 handle,
-			      __be16 protocol, struct tc_to_netdev *tc)
+			      u32 chain_index, __be16 protocol,
+			      struct tc_to_netdev *tc)
 {
 	bool ingress = TC_H_MAJ(handle) == TC_H_MAJ(TC_H_INGRESS);
-	int ret = -EOPNOTSUPP;
+
+	if (chain_index)
+		return -EOPNOTSUPP;
 
 	switch (tc->type) {
 	case TC_SETUP_MATCHALL:
@@ -853,10 +856,8 @@ static int dsa_slave_setup_tc(struct net_device *dev, u32 handle,
 			return 0;
 		}
 	default:
-		break;
+		return -EOPNOTSUPP;
 	}
-
-	return ret;
 }
 
 void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops)
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index a9c56ad..be0cfdf 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -162,6 +162,7 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
 	bpf_offload.gen_flags = prog->gen_flags;
 
 	err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+					    tp->chain->index,
 					    tp->protocol, &offload);
 
 	if (!err && (cmd == TC_CLSBPF_ADD || cmd == TC_CLSBPF_REPLACE))
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 33feaee..7832eb9 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -239,7 +239,8 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
 	tc->type = TC_SETUP_CLSFLOWER;
 	tc->cls_flower = &offload;
 
-	dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, tc);
+	dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->chain->index,
+				      tp->protocol, tc);
 }
 
 static int fl_hw_replace_filter(struct tcf_proto *tp,
@@ -275,8 +276,8 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
 	tc->type = TC_SETUP_CLSFLOWER;
 	tc->cls_flower = &offload;
 
-	err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
-					    tc);
+	err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+					    tp->chain->index, tp->protocol, tc);
 	if (!err)
 		f->flags |= TCA_CLS_FLAGS_IN_HW;
 
@@ -302,7 +303,8 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
 	tc->type = TC_SETUP_CLSFLOWER;
 	tc->cls_flower = &offload;
 
-	dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, tc);
+	dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+				      tp->chain->index, tp->protocol, tc);
 }
 
 static void __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f)
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
index 51859b8..9dc26c3 100644
--- a/net/sched/cls_matchall.c
+++ b/net/sched/cls_matchall.c
@@ -64,8 +64,9 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
 	offload.cls_mall->exts = &head->exts;
 	offload.cls_mall->cookie = cookie;
 
-	err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
-					    &offload);
+	err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+					    tp->chain->index,
+					    tp->protocol, &offload);
 	if (!err)
 		head->flags |= TCA_CLS_FLAGS_IN_HW;
 
@@ -86,8 +87,8 @@ static void mall_destroy_hw_filter(struct tcf_proto *tp,
 	offload.cls_mall->exts = NULL;
 	offload.cls_mall->cookie = cookie;
 
-	dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
-					     &offload);
+	dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->chain->index,
+				      tp->protocol, &offload);
 }
 
 static void mall_destroy(struct tcf_proto *tp)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index d20e72a..2d01195 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -441,7 +441,8 @@ static void u32_remove_hw_knode(struct tcf_proto *tp, u32 handle)
 		offload.cls_u32->command = TC_CLSU32_DELETE_KNODE;
 		offload.cls_u32->knode.handle = handle;
 		dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-					      tp->protocol, &offload);
+					      tp->chain->index, tp->protocol,
+					      &offload);
 	}
 }
 
@@ -465,7 +466,8 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
 	offload.cls_u32->hnode.prio = h->prio;
 
 	err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-					    tp->protocol, &offload);
+					    tp->chain->index, tp->protocol,
+					    &offload);
 	if (tc_skip_sw(flags))
 		return err;
 
@@ -488,7 +490,8 @@ static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
 		offload.cls_u32->hnode.prio = h->prio;
 
 		dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-					      tp->protocol, &offload);
+					      tp->chain->index, tp->protocol,
+					      &offload);
 	}
 }
 
@@ -522,7 +525,8 @@ static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
 		offload.cls_u32->knode.link_handle = n->ht_down->handle;
 
 	err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-					    tp->protocol, &offload);
+					    tp->chain->index, tp->protocol,
+					    &offload);
 
 	if (!err)
 		n->flags |= TCA_CLS_FLAGS_IN_HW;
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
index 0a4cf27..e0c0272 100644
--- a/net/sched/sch_mqprio.c
+++ b/net/sched/sch_mqprio.c
@@ -43,7 +43,7 @@ static void mqprio_destroy(struct Qdisc *sch)
 		struct tc_to_netdev tc = { .type = TC_SETUP_MQPRIO,
 					   { .mqprio = &offload } };
 
-		dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
+		dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, 0, &tc);
 	} else {
 		netdev_set_num_tc(dev, 0);
 	}
@@ -152,7 +152,8 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
 		struct tc_to_netdev tc = { .type = TC_SETUP_MQPRIO,
 					   { .mqprio = &offload } };
 
-		err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
+		err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle,
+						    0, 0, &tc);
 		if (err)
 			return err;
 
-- 
2.9.3

^ permalink raw reply related

* [PATCH net] net: rps: send out pending IPI's on CPU hotplug
From: ashwanth @ 2017-06-06 15:17 UTC (permalink / raw)
  To: netdev; +Cc: eric.dumazet

IPI's from the victim cpu are not handled in dev_cpu_callback.
So these pending IPI's would be sent to the remote cpu only when
NET_RX is scheduled on the victim cpu and since this trigger is
unpredictable it would result in packet latencies on the remote cpu.

This patch adds support to send the pending ipi's of victim cpu.

Signed-off-by: Ashwanth Goli <ashwanth@codeaurora.org>
---
  net/core/dev.c | 31 ++++++++++++++++++++++---------
  1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index fca407b..e6bfa54 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4948,6 +4948,19 @@ __sum16 __skb_gro_checksum_complete(struct 
sk_buff *skb)
  }
  EXPORT_SYMBOL(__skb_gro_checksum_complete);

+static void net_rps_send_ipi(struct softnet_data *remsd)
+{
+#ifdef CONFIG_RPS
+	while (remsd) {
+		struct softnet_data *next = remsd->rps_ipi_next;
+
+		if (cpu_online(remsd->cpu))
+			smp_call_function_single_async(remsd->cpu, &remsd->csd);
+		remsd = next;
+	}
+#endif
+}
+
  /*
   * net_rps_action_and_irq_enable sends any pending IPI's for rps.
   * Note: called with local irq disabled, but exits with local irq 
enabled.
@@ -4963,14 +4976,7 @@ static void net_rps_action_and_irq_enable(struct 
softnet_data *sd)
  		local_irq_enable();

  		/* Send pending IPI's to kick RPS processing on remote cpus. */
-		while (remsd) {
-			struct softnet_data *next = remsd->rps_ipi_next;
-
-			if (cpu_online(remsd->cpu))
-				smp_call_function_single_async(remsd->cpu,
-							   &remsd->csd);
-			remsd = next;
-		}
+		net_rps_send_ipi(remsd);
  	} else
  #endif
  		local_irq_enable();
@@ -8192,7 +8198,7 @@ static int dev_cpu_dead(unsigned int oldcpu)
  	struct sk_buff **list_skb;
  	struct sk_buff *skb;
  	unsigned int cpu;
-	struct softnet_data *sd, *oldsd;
+	struct softnet_data *sd, *oldsd, *remsd;

  	local_irq_disable();
  	cpu = smp_processor_id();
@@ -8233,6 +8239,13 @@ static int dev_cpu_dead(unsigned int oldcpu)
  	raise_softirq_irqoff(NET_TX_SOFTIRQ);
  	local_irq_enable();

+#ifdef CONFIG_RPS
+	remsd = oldsd->rps_ipi_list;
+	oldsd->rps_ipi_list = NULL;
+#endif
+	/* send out pending IPI's on offline CPU */
+	net_rps_send_ipi(remsd);
+
  	/* Process offline CPU's input_pkt_queue */
  	while ((skb = __skb_dequeue(&oldsd->process_queue))) {
  		netif_rx_ni(skb);
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH] sit: reload iphdr in ipip6_rcv
From: David Miller @ 2017-06-06 15:35 UTC (permalink / raw)
  To: yanhaishuang
  Cc: eric.dumazet, jesse, kuznet, jmorris, yoshfuji, kaber, netdev,
	linux-kernel
In-Reply-To: <C9A276FB-FF6E-439A-AFE4-F8A5551DDA30@cmss.chinamobile.com>

From: 严海双 <yanhaishuang@cmss.chinamobile.com>
Date: Tue, 6 Jun 2017 10:09:45 +0800

> 
>> On 5 Jun 2017, at 9:03 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>> 
>> On Sun, 2017-06-04 at 14:43 +0800, Haishuang Yan wrote:
>>> Since iptunnel_pull_header() can call pskb_may_pull(),
>>> we must reload any pointer that was related to skb->head.
>>> 
>>> Fixes: a09a4c8dd1ec ("tunnels: Remove encapsulation offloads on decap")
>>> Signed-off-by: Haishuang Yan <yanhaishuang@cmss.chinamobile.com>
>>> ---
>>> net/ipv6/sit.c | 1 +
>>> 1 file changed, 1 insertion(+)
>>> 
>>> diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
>>> index 61e5902..af832e7 100644
>>> --- a/net/ipv6/sit.c
>>> +++ b/net/ipv6/sit.c
>>> @@ -657,6 +657,7 @@ static int ipip6_rcv(struct sk_buff *skb)
>>> 		if (iptunnel_pull_header(skb, 0, htons(ETH_P_IPV6),
>>> 		    !net_eq(tunnel->net, dev_net(tunnel->dev))))
>>> 			goto out;
>>> +		iph = ip_hdr(skb);
>>> 
>>> 		err = IP_ECN_decapsulate(iph, skb);
>>> 		if (unlikely(err)) {
>> 
>> This seems unnecessary.
>> 
>> By the time ipip6_rcv() is called, we already have the guarantee the
>> IPv4 header is in skb linear part.
>> 
>> Otherwise we could not use iph->saddr and iph->daddr in the call to
>> ipip6_tunnel_lookup()
>> 
>> Therefore, the pskb_may_pull() is a nop in this particular case.
> 
> Yes, it’s right. Thanks!

Ok, I reverted, thanks everyone.

^ permalink raw reply

* Re: [PATCH] net: mvpp2: do not bypass the mvpp22_port_mii_set function
From: Sergei Shtylyov @ 2017-06-06 15:44 UTC (permalink / raw)
  To: Antoine Tenart, davem, netdev, thomas.petazzoni
  Cc: gregory.clement, mw, linux, linux-arm-kernel
In-Reply-To: <20170606133615.20747-1-antoine.tenart@free-electrons.com>

Hello!

On 06/06/2017 04:36 PM, Antoine Tenart wrote:

> The mvpp22_port_mii_set() function was added by 2697582144dd, but the

    Need to also specify the commit summary line enclosed in ("").

> function directly returns without doing anything. This return was used
> when debugging and wasn't removed before sending the patch. Fix this.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
[...]

MBR, Sergei

^ permalink raw reply

* Re: [for-next 4/6] net/mlx5: FPGA, Add basic support for Innova
From: David Miller @ 2017-06-06 15:50 UTC (permalink / raw)
  To: ilant-VPRAkNaXOzVWk0Htik3J/w
  Cc: jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/,
	alexei.starovoitov-Re5JQEeQqe8AvxtiuMwx3w,
	saeedm-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb,
	dledford-H+wXaHxf7aLQT0dZR+AlfA, netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA, jsorensen-b10kYP2dOMg,
	andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w,
	linux-fpga-u79uwXL29TY76Z2rM5mHXA,
	atull-yzvPICuk2ABMcg4IHK0kFoH6Mc4MB0Vx,
	yi1.li-VuQAYsv1563Yd54FQh9/CA, borisp-VPRAkNaXOzVWk0Htik3J/w
In-Reply-To: <AM4PR0501MB194008AAABEB6AAAA2ADFC82DBCB0-dp/nxUn679gfNUYDR5dMTsDSnupUy6xnnBOFsp37pqbUKgpGm//BTAC/G2K4zDHf@public.gmane.org>

From: Ilan Tayari <ilant-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Date: Tue, 6 Jun 2017 06:52:15 +0000

> The fact that we configure the FPGA using special inband packets isn't
> changing anything. IMO, it might have been any other bus on the card,
> standard or proprietary, and the arguments for how to design the driver
> would stay the same.

+1

> So neither the host stack nor the network are aware of them.
> They exist momentarily only on the internal traces on the board and not
> anywhere else.

+1
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" 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: [net-next 00/11][pull request] 1GbE Intel Wired LAN Driver Updates 2017-06-06
From: David Miller @ 2017-06-06 15:58 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, nhorman, sassmann, jogreene
In-Reply-To: <20170606085809.78571-1-jeffrey.t.kirsher@intel.com>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Tue,  6 Jun 2017 01:57:58 -0700

> This series contains updates and fixes to e1000e and igb.

Looks good, pulled, thanks Jeff.

^ permalink raw reply

* [PATCH] net: fix up hash documentation
From: Michael S. Tsirkin @ 2017-06-06 16:01 UTC (permalink / raw)
  To: linux-kernel; +Cc: Tom Herbert, Jonathan Corbet, netdev, David Miller

commit 61b905da33 ("net: Rename skb->rxhash to skb->hash")
didn't update the documentation, fix this up.

Cc: Tom Herbert <therbert@google.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 Documentation/networking/scaling.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/networking/scaling.txt b/Documentation/networking/scaling.txt
index 59f4db2..f55639d 100644
--- a/Documentation/networking/scaling.txt
+++ b/Documentation/networking/scaling.txt
@@ -122,7 +122,7 @@ associated flow of the packet. The hash is either provided by hardware
 or will be computed in the stack. Capable hardware can pass the hash in
 the receive descriptor for the packet; this would usually be the same
 hash used for RSS (e.g. computed Toeplitz hash). The hash is saved in
-skb->rx_hash and can be used elsewhere in the stack as a hash of the
+skb->hash and can be used elsewhere in the stack as a hash of the
 packet’s flow.
 
 Each receive hardware queue has an associated list of CPUs to which
-- 
MST

^ permalink raw reply related

* Re: [PATCH net-next 0/4] rxrpc: Support service upgrade
From: David Miller @ 2017-06-06 16:06 UTC (permalink / raw)
  To: dhowells; +Cc: netdev, linux-afs, linux-kernel
In-Reply-To: <149674286135.26138.12623162384868251541.stgit@warthog.procyon.org.uk>

From: David Howells <dhowells@redhat.com>
Date: Tue, 06 Jun 2017 10:54:21 +0100

> Here's a set of patches that allow AF_RXRPC to support the AuriStor service
> upgrade facility.  This allows the server to change the service ID
> requested to an upgraded service if the client requests it upon the
> initiation of a connection.
 ...
> Tagged thusly:
> 
> 	git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
> 	rxrpc-rewrite-20170606

Pulled, thanks David.

^ permalink raw reply

* Re: [net 0/2][pull request] Intel Wired LAN Driver Updates 2017-06-06
From: David Miller @ 2017-06-06 16:13 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, nhorman, sassmann, jogreene
In-Reply-To: <20170606100055.63648-1-jeffrey.t.kirsher@intel.com>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Tue,  6 Jun 2017 03:00:53 -0700

> This series contains fixes to i40e and i40evf only.

Ok, pulled, thanks a lot.

^ permalink raw reply

* Re: [for-next 4/6] net/mlx5: FPGA, Add basic support for Innova
From: Jason Gunthorpe @ 2017-06-06 16:17 UTC (permalink / raw)
  To: Ilan Tayari
  Cc: Alexei Starovoitov, Saeed Mahameed, David S. Miller, Doug Ledford,
	netdev@vger.kernel.org, linux-rdma@vger.kernel.org,
	jsorensen@fb.com, Andy Shevchenko, linux-fpga@vger.kernel.org,
	Alan Tull, yi1.li@linux.intel.com, Boris Pismenny
In-Reply-To: <AM4PR0501MB194008AAABEB6AAAA2ADFC82DBCB0@AM4PR0501MB1940.eurprd05.prod.outlook.com>

On Tue, Jun 06, 2017 at 06:52:15AM +0000, Ilan Tayari wrote:

> So neither the host stack nor the network are aware of them.
> They exist momentarily only on the internal traces on the board and not
> anywhere else.

Is that really true? If you are creating rocee QPs' then the RDMA
stack sees this stuff and now we have buried a RDMA ULP inside an
ethernet driver which seems really wonky..

> I don't mind explaining further, but I think you will just see it in the
> patchset when we submit.

You described exactly what I thought.. I just disagree with you that
an ethernet connected and controlled IP accelerator is 'part of the
NIC', even if it happens to be colocated on the same circuit board.

Jason

^ permalink raw reply

* Re: [PATCH][net-next] net/mlxfw: remove redundant goto on error check
From: David Miller @ 2017-06-06 16:22 UTC (permalink / raw)
  To: colin.king; +Cc: yotamg, netdev, kernel-janitors, linux-kernel
In-Reply-To: <20170606104740.15712-1-colin.king@canonical.com>

From: Colin King <colin.king@canonical.com>
Date: Tue,  6 Jun 2017 11:47:40 +0100

> From: Colin Ian King <colin.king@canonical.com>
> 
> The check to see of err is set and the subsequent goto is extraneous
> as the next statement is where the goto is jumping to. Remove this
> redundant check and goto.
> 
> Detected by CoverityScan, CID#1437734 ("Identical code for
> different branches")
> 
> Signed-off-by: Colin Ian King <colin.king@canonical.com>

Applied, thanks.

^ permalink raw reply

* [PATCH net-next] bpf: cgroup skb progs cannot access ld_abs/ind
From: Daniel Borkmann @ 2017-06-06 16:38 UTC (permalink / raw)
  To: davem; +Cc: netdev, fengc, ast, Daniel Borkmann

Commit fb9a307d11d6 ("bpf: Allow CGROUP_SKB eBPF program to
access sk_buff") enabled programs of BPF_PROG_TYPE_CGROUP_SKB
type to use ld_abs/ind instructions. However, at this point,
we cannot use them, since offsets relative to SKF_LL_OFF will
end up pointing skb_mac_header(skb) out of bounds since in the
egress path it is not yet set at that point in time, but only
after __dev_queue_xmit() did a general reset on the mac header.
bpf_internal_load_pointer_neg_helper() will then end up reading
data from a wrong offset.

BPF_PROG_TYPE_CGROUP_SKB programs can use bpf_skb_load_bytes()
already to access packet data, which is also more flexible than
the insns carried over from cBPF.

Fixes: fb9a307d11d6 ("bpf: Allow CGROUP_SKB eBPF program to access sk_buff")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Chenbo Feng <fengc@google.com>
---
 kernel/bpf/verifier.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 8acae64..14ccb07 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2426,7 +2426,6 @@ static bool may_access_skb(enum bpf_prog_type type)
 	case BPF_PROG_TYPE_SOCKET_FILTER:
 	case BPF_PROG_TYPE_SCHED_CLS:
 	case BPF_PROG_TYPE_SCHED_ACT:
-	case BPF_PROG_TYPE_CGROUP_SKB:
 		return true;
 	default:
 		return false;
-- 
1.9.3

^ permalink raw reply related

* Re: [PATCH net-next v2 1/2] bpf: Allow CGROUP_SKB eBPF program to access sk_buff
From: Daniel Borkmann @ 2017-06-06 16:40 UTC (permalink / raw)
  To: Chenbo Feng, netdev, David Miller; +Cc: Lorenzo Colitti, Chenbo Feng, ast
In-Reply-To: <59369A30.1060301@iogearbox.net>

On 06/06/2017 02:04 PM, Daniel Borkmann wrote:
> On 06/01/2017 03:15 AM, Chenbo Feng wrote:
>> From: Chenbo Feng <fengc@google.com>
>>
>> This allows cgroup eBPF program to classify packet based on their
>> protocol or other detail information. Currently program need
>> CAP_NET_ADMIN privilege to attach a cgroup eBPF program, and A
>> process with CAP_NET_ADMIN can already see all packets on the system,
>> for example, by creating an iptables rules that causes the packet to
>> be passed to userspace via NFLOG.
>>
>> Signed-off-by: Chenbo Feng <fengc@google.com>
>
> Sorry, but I am puzzled what above change log has to do with the
> below diff?! Back then we decided not to add BPF_PROG_TYPE_CGROUP_SKB
> to may_access_skb(), since one can already use bpf_skb_load_bytes()
> helper to access pkt data, which is a much more flexible interface.
> Mind to elaborate why you cannot use bpf_skb_load_bytes() instead?

See my other email [1], this one is also problematic wrt SKF_LL_OFF.

   [1] http://patchwork.ozlabs.org/patch/771946/

^ permalink raw reply

* Re: [patch net-next v2 0/6] introduce trap control action to tc and offload it
From: David Miller @ 2017-06-06 16:45 UTC (permalink / raw)
  To: jiri
  Cc: netdev, jhs, xiyou.wangcong, edumazet, alexander.h.duyck, stephen,
	daniel, mlxsw, andrew
In-Reply-To: <20170606121207.2921-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@resnulli.us>
Date: Tue,  6 Jun 2017 14:12:01 +0200

> This patchset introduces a control action dedicated to indicate
> to trap the matched packet to CPU. This is specific action for
> HW offloads. Also, the patchset offloads the action to mlxsw driver.
> 
> Example usage:
> $ tc filter add dev enp3s0np19 parent ffff: protocol ip prio 20 flower skip_sw dst_ip 192.168.10.1 action trap

Series applied, thanks Jiri.

^ permalink raw reply

* [PATCH net-next] net: ipmr: add getlink support
From: Nikolay Aleksandrov @ 2017-06-06 16:41 UTC (permalink / raw)
  To: netdev; +Cc: roopa, davem, sharpd, Nikolay Aleksandrov

Currently there's no way to dump the VIF table for an ipmr table other
than the default (via proc). This is a major issue when debugging ipmr
issues and in general it is good to know which interfaces are
configured. This patch adds support for RTM_GETLINK for the ipmr family
so we can dump the VIF table and the ipmr table's current config for
each table. We're protected by rtnl so no need to acquire RCU or
mrt_lock.

Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
---
The plan is to add full netlink control to ipmr via new/set/dellink later.
Also this would allow us to dump any number of VIFs in the future when we
remove the VIF device limit.

 include/uapi/linux/mroute.h |  38 +++++++++++++++
 net/ipv4/ipmr.c             | 114 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 152 insertions(+)

diff --git a/include/uapi/linux/mroute.h b/include/uapi/linux/mroute.h
index 1fe4c1e7d66e..7860be2d2c25 100644
--- a/include/uapi/linux/mroute.h
+++ b/include/uapi/linux/mroute.h
@@ -110,6 +110,44 @@ struct igmpmsg {
 	struct in_addr im_src,im_dst;
 };
 
+/* netlink table attribute format */
+enum {
+	IPMR_NL_TABLE_UNSPEC,
+	IPMR_NL_TABLE,
+	IPMR_NL_TABLE_VIFS,
+	__IPMR_NL_TABLE_MAX
+};
+#define IPMR_NL_TABLE_MAX (__IPMR_NL_TABLE_MAX - 1)
+
+struct ipmr_nl_tbl {
+	__u32 id;
+	__u32 cache_resolve_queue_len;
+	int mroute_reg_vif_num;
+	__u32 unused;
+};
+
+/* netlink vif attribute format */
+enum {
+	IPMR_NL_VIF_UNSPEC,
+	IPMR_NL_VIF_ENTRY,
+	__IPMR_NL_VIF_MAX
+};
+#define IPMR_NL_VIF_MAX (__IPMR_NL_VIF_MAX - 1)
+
+struct ipmr_nl_vif {
+	unsigned long bytes_in;
+	unsigned long bytes_out;
+	unsigned long packets_in;
+	unsigned long packets_out;
+	unsigned long rate_limit;
+	__u32 ifindex;
+	__u16 vif_id;
+	__u16 flags;
+	__be32 local;
+	__be32 remote;
+	__u8 threshold;
+};
+
 /* That's all usermode folks */
 
 #define MFC_ASSERT_THRESH (3*HZ)		/* Maximal freq. of asserts */
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 551de4d023a8..8ec88e50f7ad 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -2528,6 +2528,117 @@ static int ipmr_rtm_route(struct sk_buff *skb, struct nlmsghdr *nlh,
 		return ipmr_mfc_delete(tbl, &mfcc, parent);
 }
 
+static int ipmr_fill_vif(struct mr_table *mrt, int vifid, struct sk_buff *skb)
+{
+	struct vif_device *vif = &mrt->vif_table[vifid];
+	struct ipmr_nl_vif nlvif;
+
+	/* previous existence check should've confirmed it but in case it's
+	 * missing warn and do not signal error so the caller can move on
+	 */
+	if (WARN_ON(!vif->dev))
+		return 0;
+
+	memset(&nlvif, 0, sizeof(nlvif));
+	nlvif.ifindex = vif->dev->ifindex;
+	nlvif.vif_id = vifid;
+	nlvif.flags = vif->flags;
+	nlvif.threshold = vif->threshold;
+	nlvif.local = vif->local;
+	nlvif.remote = vif->remote;
+	nlvif.bytes_in = vif->bytes_in;
+	nlvif.bytes_out = vif->bytes_out;
+	nlvif.packets_in = vif->pkt_in;
+	nlvif.packets_out = vif->pkt_out;
+	nlvif.rate_limit = vif->rate_limit;
+
+	return nla_put(skb, IPMR_NL_VIF_ENTRY, sizeof(nlvif), &nlvif);
+}
+
+static int ipmr_rtm_dumplink(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct net *net = sock_net(skb->sk);
+	struct nlmsghdr *nlh = NULL;
+	unsigned int t = 0, s_t;
+	unsigned int e = 0, s_e;
+	struct mr_table *mrt;
+
+	s_t = cb->args[0];
+	s_e = cb->args[1];
+
+	ipmr_for_each_table(mrt, net) {
+		struct nlattr *vifs, *af;
+		struct ipmr_nl_tbl tbl;
+		struct ifinfomsg *hdr;
+		u32 queue_len;
+		int i;
+
+		if (t < s_t)
+			goto skip_table;
+		nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid,
+				cb->nlh->nlmsg_seq, RTM_GETLINK,
+				sizeof(*hdr), NLM_F_MULTI);
+		if (!nlh)
+			break;
+
+		hdr = nlmsg_data(nlh);
+		memset(hdr, 0, sizeof(*hdr));
+		hdr->ifi_family = RTNL_FAMILY_IPMR;
+
+		af = nla_nest_start(skb, IFLA_AF_SPEC);
+		if (!af) {
+			nlmsg_cancel(skb, nlh);
+			goto out;
+		}
+
+		if (!s_e) {
+			memset(&tbl, 0, sizeof(tbl));
+			tbl.id = mrt->id;
+			queue_len = atomic_read(&mrt->cache_resolve_queue_len);
+			tbl.cache_resolve_queue_len = queue_len;
+			tbl.mroute_reg_vif_num = mrt->mroute_reg_vif_num;
+			if (nla_put(skb, IPMR_NL_TABLE, sizeof(tbl), &tbl)) {
+				nlmsg_cancel(skb, nlh);
+				goto out;
+			}
+		}
+
+		vifs = nla_nest_start(skb, IPMR_NL_TABLE_VIFS);
+		if (!vifs) {
+			nla_nest_end(skb, af);
+			nlmsg_end(skb, nlh);
+			goto out;
+		}
+		for (i = 0; i < mrt->maxvif; i++) {
+			if (!VIF_EXISTS(mrt, i))
+				continue;
+			if (e < s_e)
+				goto skip_entry;
+			if (ipmr_fill_vif(mrt, i, skb)) {
+				nla_nest_end(skb, vifs);
+				nla_nest_end(skb, af);
+				nlmsg_end(skb, nlh);
+				goto out;
+			}
+skip_entry:
+			e++;
+		}
+		s_e = 0;
+		e = 0;
+		nla_nest_end(skb, vifs);
+		nla_nest_end(skb, af);
+		nlmsg_end(skb, nlh);
+skip_table:
+		t++;
+	}
+
+out:
+	cb->args[1] = e;
+	cb->args[0] = t;
+
+	return skb->len;
+}
+
 #ifdef CONFIG_PROC_FS
 /* The /proc interfaces to multicast routing :
  * /proc/net/ip_mr_cache & /proc/net/ip_mr_vif
@@ -2870,6 +2981,9 @@ int __init ip_mr_init(void)
 		      ipmr_rtm_route, NULL, NULL);
 	rtnl_register(RTNL_FAMILY_IPMR, RTM_DELROUTE,
 		      ipmr_rtm_route, NULL, NULL);
+
+	rtnl_register(RTNL_FAMILY_IPMR, RTM_GETLINK,
+		      NULL, ipmr_rtm_dumplink, NULL);
 	return 0;
 
 #ifdef CONFIG_IP_PIMSM_V2
-- 
2.1.4

^ permalink raw reply related

* Re: [PATCH net] net: rps: send out pending IPI's on CPU hotplug
From: Eric Dumazet @ 2017-06-06 16:53 UTC (permalink / raw)
  To: ashwanth; +Cc: netdev
In-Reply-To: <913335638b07570e5189713e1db9cbe6@codeaurora.org>

On Tue, 2017-06-06 at 20:47 +0530, ashwanth@codeaurora.org wrote:
> IPI's from the victim cpu are not handled in dev_cpu_callback.
> So these pending IPI's would be sent to the remote cpu only when
> NET_RX is scheduled on the victim cpu and since this trigger is
> unpredictable it would result in packet latencies on the remote cpu.
> 
> This patch adds support to send the pending ipi's of victim cpu.
> 
> Signed-off-by: Ashwanth Goli <ashwanth@codeaurora.org>
> ---

Acked-by: Eric Dumazet <edumazet@google.com>

Thanks !

^ permalink raw reply

* Re: pull-request: wireless-drivers 2017-06-06
From: David Miller @ 2017-06-06 16:54 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <8760g95muz.fsf@codeaurora.org>

From: Kalle Valo <kvalo@codeaurora.org>
Date: Tue, 06 Jun 2017 15:20:20 +0300

> fixes to net tree, more info in the tag below. Please let me know if
> there are any problems.

Pulled, thanks Kalle.

^ permalink raw reply

* Re: [PATCH net-next v2 2/2] bpf: Remove the capability check for cgroup skb eBPF program
From: Daniel Borkmann @ 2017-06-06 16:56 UTC (permalink / raw)
  To: Alexei Starovoitov, Chenbo Feng
  Cc: netdev, David Miller, Lorenzo Colitti, Chenbo Feng
In-Reply-To: <20170601234235.iwu55crijtxuq5mp@ast-mbp>

On 06/02/2017 01:42 AM, Alexei Starovoitov wrote:
> On Wed, May 31, 2017 at 06:16:00PM -0700, Chenbo Feng wrote:
>> From: Chenbo Feng <fengc@google.com>
>>
>> Currently loading a cgroup skb eBPF program require a CAP_SYS_ADMIN
>> capability while attaching the program to a cgroup only requires the
>> user have CAP_NET_ADMIN privilege. We can escape the capability
>> check when load the program just like socket filter program to make
>> the capability requirement consistent.
>>
>> Change since v1:
>> Change the code style in order to be compliant with checkpatch.pl
>> preference
>>
>> Signed-off-by: Chenbo Feng <fengc@google.com>
>
> as far as I can see they're indeed the same as socket filters, so
> Acked-by: Alexei Starovoitov <ast@kernel.org>
>
> but I don't quite understand how it helps, since as you said
> attaching such unpriv fd to cgroup still requires root.
> Do you have more patches to follow?

Hmm, when we relax this from capable(CAP_SYS_ADMIN) to unprivileged,
then we must at least also zero out the not-yet-initialized memory
for the mac header for egress case in __cgroup_bpf_run_filter_skb().

^ 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