Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] VSOCK: do not disconnect socket when peer has shutdown SEND only
From: Stefan Hajnoczi @ 2016-05-05 18:23 UTC (permalink / raw)
  To: Ian Campbell
  Cc: netdev, David S. Miller, Claudio Imbrenda, Andy King,
	Dmitry Torokhov, Jorgen Hansen, Adit Ranadive
In-Reply-To: <1462368113-5493-1-git-send-email-ian.campbell@docker.com>

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

On Wed, May 04, 2016 at 02:21:53PM +0100, Ian Campbell wrote:
> The peer may be expecting a reply having sent a request and then done a
> shutdown(SHUT_WR), so tearing down the whole socket at this point seems
> wrong and breaks for me with a client which does a SHUT_WR.
> 
> Looking at other socket family's stream_recvmsg callbacks doing a shutdown
> here does not seem to be the norm and removing it does not seem to have
> had any adverse effects that I can see.

Seems fine to me.

> I'm using Stefan's RFC virtio transport patches, I'm unsure of the impact
> on the vmci transport.
> 
> Signed-off-by: Ian Campbell <ian.campbell@docker.com>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Stefan Hajnoczi <stefanha@redhat.com>
> Cc: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
> Cc: Andy King <acking@vmware.com>
> Cc: Dmitry Torokhov <dtor@vmware.com>
> Cc: Jorgen Hansen <jhansen@vmware.com>
> Cc: Adit Ranadive <aditr@vmware.com>
> Cc: netdev@vger.kernel.org
> ---
>  net/vmw_vsock/af_vsock.c | 21 +--------------------
>  1 file changed, 1 insertion(+), 20 deletions(-)
> 
> diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
> index 1e5f5ed..7a25150 100644
> --- a/net/vmw_vsock/af_vsock.c
> +++ b/net/vmw_vsock/af_vsock.c
> @@ -1789,27 +1789,8 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
>  	else if (sk->sk_shutdown & RCV_SHUTDOWN)
>  		err = 0;
>  
> -	if (copied > 0) {
> -		/* We only do these additional bookkeeping/notification steps
> -		 * if we actually copied something out of the queue pair
> -		 * instead of just peeking ahead.
> -		 */
> -
> -		if (!(flags & MSG_PEEK)) {
> -			/* If the other side has shutdown for sending and there
> -			 * is nothing more to read, then modify the socket
> -			 * state.
> -			 */
> -			if (vsk->peer_shutdown & SEND_SHUTDOWN) {
> -				if (vsock_stream_has_data(vsk) <= 0) {
> -					sk->sk_state = SS_UNCONNECTED;
> -					sock_set_flag(sk, SOCK_DONE);
> -					sk->sk_state_change(sk);
> -				}
> -			}
> -		}
> +	if (copied > 0)
>  		err = copied;
> -	}
>  
>  out:
>  	release_sock(sk);
> -- 
> 2.8.1
> 

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

^ permalink raw reply

* Re: [PATCH] rtlwifi: pci: use dev_kfree_skb_irq instead of kfree_skb in rtl_pci_reset_trx_ring
From: Larry Finger @ 2016-05-05 19:25 UTC (permalink / raw)
  To: Wang YanQing, chaoming_li-kXabqFNEczNtrwSWzY7KCg,
	kvalo-sgV2jX0FEOL9JmXXK+q4OQ,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20160505171904.GA16619@udknight>

On 05/05/2016 12:19 PM, Wang YanQing wrote:
> We can't use kfree_skb in irq disable context, because spin_lock_irqsave
> make sure we are always in irq disable context, use dev_kfree_skb_irq
> instead of kfree_skb is better than dev_kfree_skb_any.
>
> This patch fix below kernel warning:
> [ 7612.095528] ------------[ cut here ]------------
> [ 7612.095546] WARNING: CPU: 3 PID: 4460 at kernel/softirq.c:150 __local_bh_enable_ip+0x58/0x80()
> [ 7612.095550] Modules linked in: rtl8723be x86_pkg_temp_thermal btcoexist rtl_pci rtlwifi rtl8723_common
> [ 7612.095567] CPU: 3 PID: 4460 Comm: ifconfig Tainted: G        W       4.4.0+ #4
> [ 7612.095570] Hardware name: LENOVO 20DFA04FCD/20DFA04FCD, BIOS J5ET48WW (1.19 ) 08/27/2015
> [ 7612.095574]  00000000 00000000 da37fc70 c12ce7c5 00000000 da37fca0 c104cc59 c19d4454
> [ 7612.095584]  00000003 0000116c c19d4784 00000096 c10508a8 c10508a8 00000200 c1b42400
> [ 7612.095594]  f29be780 da37fcb0 c104ccad 00000009 00000000 da37fcbc c10508a8 f21f08b8
> [ 7612.095604] Call Trace:
> [ 7612.095614]  [<c12ce7c5>] dump_stack+0x41/0x5c
> [ 7612.095620]  [<c104cc59>] warn_slowpath_common+0x89/0xc0
> [ 7612.095628]  [<c10508a8>] ? __local_bh_enable_ip+0x58/0x80
> [ 7612.095634]  [<c10508a8>] ? __local_bh_enable_ip+0x58/0x80
> [ 7612.095640]  [<c104ccad>] warn_slowpath_null+0x1d/0x20
> [ 7612.095646]  [<c10508a8>] __local_bh_enable_ip+0x58/0x80
> [ 7612.095653]  [<c16b7d34>] destroy_conntrack+0x64/0xa0
> [ 7612.095660]  [<c16b300f>] nf_conntrack_destroy+0xf/0x20
> [ 7612.095665]  [<c1677565>] skb_release_head_state+0x55/0xa0
> [ 7612.095670]  [<c16775bb>] skb_release_all+0xb/0x20
> [ 7612.095674]  [<c167760b>] __kfree_skb+0xb/0x60
> [ 7612.095679]  [<c16776f0>] kfree_skb+0x30/0x70
> [ 7612.095686]  [<f81b869d>] ? rtl_pci_reset_trx_ring+0x22d/0x370 [rtl_pci]
> [ 7612.095692]  [<f81b869d>] rtl_pci_reset_trx_ring+0x22d/0x370 [rtl_pci]
> [ 7612.095698]  [<f81b87f9>] rtl_pci_start+0x19/0x190 [rtl_pci]
> [ 7612.095705]  [<f81970e6>] rtl_op_start+0x56/0x90 [rtlwifi]
> [ 7612.095712]  [<c17e3f16>] drv_start+0x36/0xc0
> [ 7612.095717]  [<c17f5ab3>] ieee80211_do_open+0x2d3/0x890
> [ 7612.095725]  [<c16820fe>] ? call_netdevice_notifiers_info+0x2e/0x60
> [ 7612.095730]  [<c17f60bd>] ieee80211_open+0x4d/0x50
> [ 7612.095736]  [<c16891b3>] __dev_open+0xa3/0x130
> [ 7612.095742]  [<c183fa53>] ? _raw_spin_unlock_bh+0x13/0x20
> [ 7612.095748]  [<c1689499>] __dev_change_flags+0x89/0x140
> [ 7612.095753]  [<c127c70d>] ? selinux_capable+0xd/0x10
> [ 7612.095759]  [<c1689589>] dev_change_flags+0x29/0x60
> [ 7612.095765]  [<c1700b93>] devinet_ioctl+0x553/0x670
> [ 7612.095772]  [<c12db758>] ? _copy_to_user+0x28/0x40
> [ 7612.095777]  [<c17018b5>] inet_ioctl+0x85/0xb0
> [ 7612.095783]  [<c166e647>] sock_ioctl+0x67/0x260
> [ 7612.095788]  [<c166e5e0>] ? sock_fasync+0x80/0x80
> [ 7612.095795]  [<c115c99b>] do_vfs_ioctl+0x6b/0x550
> [ 7612.095800]  [<c127c812>] ? selinux_file_ioctl+0x102/0x1e0
> [ 7612.095807]  [<c10a8914>] ? timekeeping_suspend+0x294/0x320
> [ 7612.095813]  [<c10a256a>] ? __hrtimer_run_queues+0x14a/0x210
> [ 7612.095820]  [<c1276e24>] ? security_file_ioctl+0x34/0x50
> [ 7612.095827]  [<c115cef0>] SyS_ioctl+0x70/0x80
> [ 7612.095832]  [<c1001804>] do_fast_syscall_32+0x84/0x120
> [ 7612.095839]  [<c183ff91>] sysenter_past_esp+0x36/0x55
> [ 7612.095844] ---[ end trace 97e9c637a20e8348 ]---
>
> Signed-off-by: Wang YanQing <udknight-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>   drivers/net/wireless/realtek/rtlwifi/pci.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
> index 1ac41b8..99a3a03 100644
> --- a/drivers/net/wireless/realtek/rtlwifi/pci.c
> +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
> @@ -1572,7 +1572,7 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
>   							 true,
>   							 HW_DESC_TXBUFF_ADDR),
>   						 skb->len, PCI_DMA_TODEVICE);
> -				kfree_skb(skb);
> +				dev_kfree_skb_irq(skb);
>   				ring->idx = (ring->idx + 1) % ring->entries;
>   			}
>   			ring->idx = 0;
>

I am currently testing this patch. It looks OK, but during my first test, I got 
a system crash that was not captured. As I was testing some other things, your 
patch may not have been at fault and I am now testing with only that one change.

By the way, I have never seen the warning that you posted. I always use 64-bit 
Linux, and that may be the difference.

Once I finish my testing, I will ack or nack.

Larry

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH net-next] vxlan: if_arp: introduce ARPHRD_VXLANGPE
From: Jiri Benc @ 2016-05-05 19:31 UTC (permalink / raw)
  To: Thadeu Lima de Souza Cascardo; +Cc: netdev, Simon Horman
In-Reply-To: <1462466204-3534-1-git-send-email-cascardo@redhat.com>

On Thu,  5 May 2016 13:36:44 -0300, Thadeu Lima de Souza Cascardo wrote:
> Use ARPHRD_VXLANGPE to identify VxLAN GPE interfaces. This is going to be used
> to allow GPE interfaces to be added as openvswitch ports.

What's wrong with ARPHRD_NONE? I don't think we need a separate type
for VXLAN-GPE. Just use ARPHRD_NONE in ovs and things should work, for
all ARPHRD_NONE interfaces as a bonus.

> Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@redhat.com>
> Cc: Jiri Benc <jbenc@redhat.com>
> Cc: Simon Horman <simon.horman@netronome.com>

You did not CC me nor Simon :-)

 Jiri

^ permalink raw reply

* [PATCH net-next 0/2] net: vrf: Fixup PKTINFO to return enslaved device index
From: David Ahern @ 2016-05-05 19:37 UTC (permalink / raw)
  To: netdev; +Cc: David Ahern

Applications such as OSPF and BFD need the original ingress device not
the VRF device; the latter can be derived from the former. To that end
move the packet intercept from an rx handler that is invoked by 
__netif_receive_skb_core to the ipv4 and ipv6 receive processing. 

IPv6 already saves the skb_iif to the control buffer in ipv6_rcv. Since
the skb->dev has not been switched the cb has the enslaved device. Make
the same happen for IPv4 by adding the skb_iif to inet_skb_parm and set
it in ipv4 code after clearing the skb control buffer similar to IPv6.
>From there the pktinfo can just pull it from cb with the PKTINFO_SKB_CB
cast.

David Ahern (2):
  net: l3mdev: Add hook in ip and ipv6
  net: original ingress device index in PKTINFO

 drivers/net/vrf.c         | 186 ++++++++++++++++++++++------------------------
 include/linux/ipv6.h      |   3 +-
 include/linux/netdevice.h |   2 +
 include/net/ip.h          |   1 +
 include/net/l3mdev.h      |  43 +++++++++++
 include/net/tcp.h         |   3 +-
 net/core/dev.c            |   3 +-
 net/ipv4/ip_input.c       |   8 ++
 net/ipv4/ip_sockglue.c    |   7 +-
 net/ipv6/ip6_input.c      |   7 ++
 10 files changed, 161 insertions(+), 102 deletions(-)

-- 
2.1.4

^ permalink raw reply

* [PATCH net-next 1/2] net: l3mdev: Add hook in ip and ipv6
From: David Ahern @ 2016-05-05 19:37 UTC (permalink / raw)
  To: netdev; +Cc: David Ahern
In-Reply-To: <1462477063-21699-1-git-send-email-dsa@cumulusnetworks.com>

Currently the VRF driver uses the rx_handler to switch the skb device
to the VRF device. Switching the dev prior to the ip / ipv6 layer
means the VRF driver has to duplicate IP/IPv6 processing which adds
overhead and makes features such as retaining the ingress device index
more complicated than necessary.

This patch moves the hook to the L3 layer just after the first NF_HOOK
for PRE_ROUTING. This location makes exposing the original ingress device
trivial (next patch) and allows adding other NF_HOOKs to the VRF driver
in the future.

dev_queue_xmit_nit is exported so that the VRF driver can cycle the skb
with the switched device through the packet taps to maintain current
behavior (tcpdump can be used on either the vrf device or the enslaved
devices).

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
 drivers/net/vrf.c         | 186 ++++++++++++++++++++++------------------------
 include/linux/ipv6.h      |   3 +-
 include/linux/netdevice.h |   2 +
 include/net/l3mdev.h      |  43 +++++++++++
 include/net/tcp.h         |   3 +-
 net/core/dev.c            |   3 +-
 net/ipv4/ip_input.c       |   7 ++
 net/ipv6/ip6_input.c      |   7 ++
 8 files changed, 153 insertions(+), 101 deletions(-)

diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 8a8f1e58b415..08e06f1d227a 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -42,9 +42,6 @@
 #define DRV_NAME	"vrf"
 #define DRV_VERSION	"1.0"
 
-#define vrf_master_get_rcu(dev) \
-	((struct net_device *)rcu_dereference(dev->rx_handler_data))
-
 struct net_vrf {
 	struct rtable           *rth;
 	struct rt6_info		*rt6;
@@ -60,90 +57,12 @@ struct pcpu_dstats {
 	struct u64_stats_sync	syncp;
 };
 
-/* neighbor handling is done with actual device; do not want
- * to flip skb->dev for those ndisc packets. This really fails
- * for multiple next protocols (e.g., NEXTHDR_HOP). But it is
- * a start.
- */
-#if IS_ENABLED(CONFIG_IPV6)
-static bool check_ipv6_frame(const struct sk_buff *skb)
-{
-	const struct ipv6hdr *ipv6h;
-	struct ipv6hdr _ipv6h;
-	bool rc = true;
-
-	ipv6h = skb_header_pointer(skb, 0, sizeof(_ipv6h), &_ipv6h);
-	if (!ipv6h)
-		goto out;
-
-	if (ipv6h->nexthdr == NEXTHDR_ICMP) {
-		const struct icmp6hdr *icmph;
-		struct icmp6hdr _icmph;
-
-		icmph = skb_header_pointer(skb, sizeof(_ipv6h),
-					   sizeof(_icmph), &_icmph);
-		if (!icmph)
-			goto out;
-
-		switch (icmph->icmp6_type) {
-		case NDISC_ROUTER_SOLICITATION:
-		case NDISC_ROUTER_ADVERTISEMENT:
-		case NDISC_NEIGHBOUR_SOLICITATION:
-		case NDISC_NEIGHBOUR_ADVERTISEMENT:
-		case NDISC_REDIRECT:
-			rc = false;
-			break;
-		}
-	}
-
-out:
-	return rc;
-}
-#else
-static bool check_ipv6_frame(const struct sk_buff *skb)
-{
-	return false;
-}
-#endif
-
-static bool is_ip_rx_frame(struct sk_buff *skb)
-{
-	switch (skb->protocol) {
-	case htons(ETH_P_IP):
-		return true;
-	case htons(ETH_P_IPV6):
-		return check_ipv6_frame(skb);
-	}
-	return false;
-}
-
 static void vrf_tx_error(struct net_device *vrf_dev, struct sk_buff *skb)
 {
 	vrf_dev->stats.tx_errors++;
 	kfree_skb(skb);
 }
 
-/* note: already called with rcu_read_lock */
-static rx_handler_result_t vrf_handle_frame(struct sk_buff **pskb)
-{
-	struct sk_buff *skb = *pskb;
-
-	if (is_ip_rx_frame(skb)) {
-		struct net_device *dev = vrf_master_get_rcu(skb->dev);
-		struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
-
-		u64_stats_update_begin(&dstats->syncp);
-		dstats->rx_pkts++;
-		dstats->rx_bytes += skb->len;
-		u64_stats_update_end(&dstats->syncp);
-
-		skb->dev = dev;
-
-		return RX_HANDLER_ANOTHER;
-	}
-	return RX_HANDLER_PASS;
-}
-
 static struct rtnl_link_stats64 *vrf_get_stats64(struct net_device *dev,
 						 struct rtnl_link_stats64 *stats)
 {
@@ -497,28 +416,14 @@ static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
 {
 	int ret;
 
-	/* register the packet handler for slave ports */
-	ret = netdev_rx_handler_register(port_dev, vrf_handle_frame, dev);
-	if (ret) {
-		netdev_err(port_dev,
-			   "Device %s failed to register rx_handler\n",
-			   port_dev->name);
-		goto out_fail;
-	}
-
 	ret = netdev_master_upper_dev_link(port_dev, dev, NULL, NULL);
 	if (ret < 0)
-		goto out_unregister;
+		return ret;
 
 	port_dev->priv_flags |= IFF_L3MDEV_SLAVE;
 	cycle_netdev(port_dev);
 
 	return 0;
-
-out_unregister:
-	netdev_rx_handler_unregister(port_dev);
-out_fail:
-	return ret;
 }
 
 static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
@@ -535,8 +440,6 @@ static int do_vrf_del_slave(struct net_device *dev, struct net_device *port_dev)
 	netdev_upper_dev_unlink(port_dev, dev);
 	port_dev->priv_flags &= ~IFF_L3MDEV_SLAVE;
 
-	netdev_rx_handler_unregister(port_dev);
-
 	cycle_netdev(port_dev);
 
 	return 0;
@@ -659,6 +562,92 @@ static int vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4)
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
+/* neighbor handling is done with actual device; do not want
+ * to flip skb->dev for those ndisc packets. This really fails
+ * for multiple next protocols (e.g., NEXTHDR_HOP). But it is
+ * a start.
+ */
+static bool ipv6_ndisc_frame(const struct sk_buff *skb)
+{
+	const struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb->data;
+	size_t hlen = sizeof(*ipv6h);
+	bool rc = false;
+
+	if (ipv6h->nexthdr == NEXTHDR_ICMP) {
+		const struct icmp6hdr *icmph;
+
+		if (skb->len < hlen + sizeof(*icmph))
+			goto out;
+
+		icmph = (struct icmp6hdr *)(skb->data + sizeof(*ipv6h));
+		switch (icmph->icmp6_type) {
+		case NDISC_ROUTER_SOLICITATION:
+		case NDISC_ROUTER_ADVERTISEMENT:
+		case NDISC_NEIGHBOUR_SOLICITATION:
+		case NDISC_NEIGHBOUR_ADVERTISEMENT:
+		case NDISC_REDIRECT:
+			rc = true;
+			break;
+		}
+	}
+
+out:
+	return rc;
+}
+
+static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
+				   struct sk_buff *skb)
+{
+	/* if packet is NDISC keep the ingress interface */
+	if (!ipv6_ndisc_frame(skb)) {
+		skb->dev = vrf_dev;
+		skb->skb_iif = vrf_dev->ifindex;
+
+		skb_push(skb, skb->mac_len);
+		dev_queue_xmit_nit(skb, vrf_dev);
+		skb_pull(skb, skb->mac_len);
+	}
+
+	return skb;
+}
+
+#else
+static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
+				   struct sk_buff *skb)
+{
+	return skb;
+}
+#endif
+
+static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
+				  struct sk_buff *skb)
+{
+	skb->dev = vrf_dev;
+	skb->skb_iif = vrf_dev->ifindex;
+
+	skb_push(skb, skb->mac_len);
+	dev_queue_xmit_nit(skb, vrf_dev);
+	skb_pull(skb, skb->mac_len);
+
+	return skb;
+}
+
+/* called with rcu lock held */
+static struct sk_buff *vrf_l3_rcv(struct net_device *vrf_dev,
+				  struct sk_buff *skb,
+				  u16 proto)
+{
+	switch (proto) {
+	case AF_INET:
+		return vrf_ip_rcv(vrf_dev, skb);
+	case AF_INET6:
+		return vrf_ip6_rcv(vrf_dev, skb);
+	}
+
+	return skb;
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
 static struct dst_entry *vrf_get_rt6_dst(const struct net_device *dev,
 					 const struct flowi6 *fl6)
 {
@@ -679,6 +668,7 @@ static const struct l3mdev_ops vrf_l3mdev_ops = {
 	.l3mdev_fib_table	= vrf_fib_table,
 	.l3mdev_get_rtable	= vrf_get_rtable,
 	.l3mdev_get_saddr	= vrf_get_saddr,
+	.l3mdev_l3_rcv		= vrf_l3_rcv,
 #if IS_ENABLED(CONFIG_IPV6)
 	.l3mdev_get_rt6_dst	= vrf_get_rt6_dst,
 #endif
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 58d6e158755f..878608834f89 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -123,9 +123,10 @@ struct inet6_skb_parm {
 #define IP6CB(skb)	((struct inet6_skb_parm*)((skb)->cb))
 #define IP6CBMTU(skb)	((struct ip6_mtuinfo *)((skb)->cb))
 
+/* return last skb->dev index. For loopback return iif from cb */
 static inline int inet6_iif(const struct sk_buff *skb)
 {
-	return IP6CB(skb)->iif;
+	return skb->skb_iif > 1 ? skb->skb_iif : IP6CB(skb)->iif;
 }
 
 struct tcp6_request_sock {
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 63580e6d0df4..c2f5112f08f7 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3258,6 +3258,8 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 bool is_skb_forwardable(const struct net_device *dev,
 			const struct sk_buff *skb);
 
+void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
+
 extern int		netdev_budget;
 
 /* Called by rtnetlink.c:rtnl_unlock() */
diff --git a/include/net/l3mdev.h b/include/net/l3mdev.h
index c43a9c73de5e..19d8171d7cbb 100644
--- a/include/net/l3mdev.h
+++ b/include/net/l3mdev.h
@@ -25,6 +25,8 @@
 
 struct l3mdev_ops {
 	u32		(*l3mdev_fib_table)(const struct net_device *dev);
+	struct sk_buff * (*l3mdev_l3_rcv)(struct net_device *dev,
+					  struct sk_buff *skb, u16 proto);
 
 	/* IPv4 ops */
 	struct rtable *	(*l3mdev_get_rtable)(const struct net_device *dev,
@@ -177,6 +179,35 @@ struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net,
 	return dst;
 }
 
+static inline
+struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto)
+{
+	struct net_device *master = NULL;
+
+	if (netif_is_l3_slave(skb->dev))
+		master = netdev_master_upper_dev_get_rcu(skb->dev);
+
+	else if (netif_is_l3_master(skb->dev))
+		master = skb->dev;
+
+	if (master && master->l3mdev_ops->l3mdev_l3_rcv)
+		skb = master->l3mdev_ops->l3mdev_l3_rcv(master, skb, proto);
+
+	return skb;
+}
+
+static inline
+struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb)
+{
+	return l3mdev_l3_rcv(skb, AF_INET);
+}
+
+static inline
+struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)
+{
+	return l3mdev_l3_rcv(skb, AF_INET6);
+}
+
 #else
 
 static inline int l3mdev_master_ifindex_rcu(const struct net_device *dev)
@@ -244,6 +275,18 @@ struct dst_entry *l3mdev_rt6_dst_by_oif(struct net *net,
 {
 	return NULL;
 }
+
+static inline
+struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb)
+{
+	return skb;
+}
+
+static inline
+struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)
+{
+	return skb;
+}
 #endif
 
 #endif /* _NET_L3MDEV_H_ */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 24ec80483805..a68f387ce310 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -781,7 +781,8 @@ struct tcp_skb_cb {
  */
 static inline int tcp_v6_iif(const struct sk_buff *skb)
 {
-	return TCP_SKB_CB(skb)->header.h6.iif;
+	/* return last skb->dev index. For loopback return iif from cb */
+	return skb->skb_iif > 1 ? skb->skb_iif : TCP_SKB_CB(skb)->header.h6.iif;
 }
 #endif
 
diff --git a/net/core/dev.c b/net/core/dev.c
index e98ba63fe280..51a8bf28a3e0 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1850,7 +1850,7 @@ static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb)
  *	taps currently in use.
  */
 
-static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
+void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct packet_type *ptype;
 	struct sk_buff *skb2 = NULL;
@@ -1907,6 +1907,7 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 		pt_prev->func(skb2, skb->dev, pt_prev, skb->dev);
 	rcu_read_unlock();
 }
+EXPORT_SYMBOL_GPL(dev_queue_xmit_nit);
 
 /**
  * netif_setup_tc - Handle tc mappings on real_num_tx_queues change
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 751c0658e194..37375eedeef9 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -313,6 +313,13 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 	const struct iphdr *iph = ip_hdr(skb);
 	struct rtable *rt;
 
+	/* if ingress device is enslaved to an L3 master device pass the
+	 * skb to its handler for processing
+	 */
+	skb = l3mdev_ip_rcv(skb);
+	if (!skb)
+		return NET_RX_SUCCESS;
+
 	if (net->ipv4.sysctl_ip_early_demux &&
 	    !skb_dst(skb) &&
 	    !skb->sk &&
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 6ed56012005d..f185cbcda114 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -49,6 +49,13 @@
 
 int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+	/* if ingress device is enslaved to an L3 master device pass the
+	 * skb to its handler for processing
+	 */
+	skb = l3mdev_ip6_rcv(skb);
+	if (!skb)
+		return NET_RX_SUCCESS;
+
 	if (net->ipv4.sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) {
 		const struct inet6_protocol *ipprot;
 
-- 
2.1.4

^ permalink raw reply related

* [PATCH net-next 2/2] net: original ingress device index in PKTINFO
From: David Ahern @ 2016-05-05 19:37 UTC (permalink / raw)
  To: netdev; +Cc: David Ahern
In-Reply-To: <1462477063-21699-1-git-send-email-dsa@cumulusnetworks.com>

Applications such as OSPF and BFD need the original ingress device not
the VRF device; the latter can be derived from the former. To that end
add the skb_iif to inet_skb_parm and set it in ipv4 code after clearing
the skb control buffer similar to IPv6. From there the pktinfo can just
pull it from cb with the PKTINFO_SKB_CB cast.

The previous patch moving the skb->dev change to L3 means nothing else
is needed for IPv6; it just works.

Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
Removed the change to ipv4_datagram_support_cmsg per Julian's comment
when the patch was a part of the larger set.

 include/net/ip.h       | 1 +
 net/ipv4/ip_input.c    | 1 +
 net/ipv4/ip_sockglue.c | 7 ++++++-
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index 247ac82e9cf2..37165fba3741 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -36,6 +36,7 @@
 struct sock;
 
 struct inet_skb_parm {
+	int			iif;
 	struct ip_options	opt;		/* Compiled IP options		*/
 	unsigned char		flags;
 
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 37375eedeef9..4b351af3e67b 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -478,6 +478,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 
 	/* Remove any debris in the socket control block */
 	memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+	IPCB(skb)->iif = skb->skb_iif;
 
 	/* Must drop socket now because of tproxy. */
 	skb_orphan(skb);
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index bdb222c0c6a2..5805762d7fc7 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -1193,7 +1193,12 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
 		       ipv6_sk_rxinfo(sk);
 
 	if (prepare && skb_rtable(skb)) {
-		pktinfo->ipi_ifindex = inet_iif(skb);
+		/* skb->cb is overloaded: prior to this point it is IP{6}CB
+		 * which has interface index (iif) as the first member of the
+		 * underlying inet{6}_skb_parm struct. This code then overlays
+		 * PKTINFO_SKB_CB and in_pktinfo also has iif as the first
+		 * element so the iif is picked up from the prior IPCB
+		 */
 		pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb);
 	} else {
 		pktinfo->ipi_ifindex = 0;
-- 
2.1.4

^ permalink raw reply related

* Re: [PATCH net-next] vxlan: if_arp: introduce ARPHRD_VXLANGPE
From: Thadeu Lima de Souza Cascardo @ 2016-05-05 19:56 UTC (permalink / raw)
  To: Jiri Benc; +Cc: netdev, Simon Horman
In-Reply-To: <20160505213141.7ad29ebd@griffin>

On Thu, May 05, 2016 at 09:31:41PM +0200, Jiri Benc wrote:
> On Thu,  5 May 2016 13:36:44 -0300, Thadeu Lima de Souza Cascardo wrote:
> > Use ARPHRD_VXLANGPE to identify VxLAN GPE interfaces. This is going to be used
> > to allow GPE interfaces to be added as openvswitch ports.
> 
> What's wrong with ARPHRD_NONE? I don't think we need a separate type
> for VXLAN-GPE. Just use ARPHRD_NONE in ovs and things should work, for
> all ARPHRD_NONE interfaces as a bonus.
> 

That's fine for me. I looked quickly at the few devices using ARPHRD_NONE in
upstream kernel, not sure if there are broken out-of-tree drivers out there. And
should we care?

> > Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@redhat.com>
> > Cc: Jiri Benc <jbenc@redhat.com>
> > Cc: Simon Horman <simon.horman@netronome.com>
> 
> You did not CC me nor Simon :-)
> 

I am using sendemail.suppresscc=all to prevent some accidents. I am adding
confirm=always so I can double check before really sending.

Thanks.
Cascardo.

>  Jiri

^ permalink raw reply

* Re: [PATCH net-next 06/13] net: original ingress device index in PKTINFO
From: Julian Anastasov @ 2016-05-05 20:00 UTC (permalink / raw)
  To: David Ahern; +Cc: netdev
In-Reply-To: <572B6012.60806@cumulusnetworks.com>


	Hello,

On Thu, 5 May 2016, David Ahern wrote:

> On 5/5/16 2:41 AM, Julian Anastasov wrote:

> > > +	IPCB(skb)->iif = skb->skb_iif;
> >
> > 	For loopback traffic (including looped back multicast)
> > this is now a zero :( Can inet_iif be moved to ip_rcv_finish
> > instead? Still, we spend cycles in fast path in case nobody
> > listens for such info.
> 
> Why is that? skb_iif is set to skb->dev->index in __netif_receive_skb_core and
> ip_rcv is called it. Is there another path to it?

	You are right, it is 0 only for the output path.

Regards

^ permalink raw reply

* Re: [PATCH nf-next 0/9] netfilter: remove per-netns conntrack tables, part 1
From: Brian Haley @ 2016-05-05 20:27 UTC (permalink / raw)
  To: Florian Westphal, netfilter-devel; +Cc: netdev
In-Reply-To: <1461863628-23350-1-git-send-email-fw@strlen.de>

On 04/28/2016 01:13 PM, Florian Westphal wrote:
> [ CCing netdev so netns folks can have a look too ]
>
> This patch series removes the per-netns connection tracking tables.
> All conntrack objects are then stored in one global global table.
>
> This avoids the infamous 'vmalloc' when lots of namespaces are used:
> We no longer allocate a new conntrack table for each namespace (with 64k
> size this saves 512kb of memory per netns).
>
> - net namespace address is made part of conntrack hash, to spread
>    conntracks over entire table even if netns has overlapping ip addresses.
> - lookup and iterators net_eq() to skip conntracks living in a different
>    namespace.

Hi Florian,

Question on this series.

Openstack networking creates virtual routers using namespaces for isolation 
between users.  VETH pairs are used to connect the interfaces on these routers 
to different networks, whether they are internal (private) or external (public). 
  In most cases NAT is done inside the namespace as packets move between the 
networks.

I've seen cases where certain users are attacked, where the CT table is filled 
such that we start seeing "nf_conntrack: table full, dropping packet" messages 
(as expected).  But other users continue to function normally, unaffected.  Is 
this still the case - each netns has some limit it can't exceed?  I didn't see 
it, but your comment in 9/9 seemed like something was there -  "we would start 
to 'over-subscribe' the affected/overlimit netns".

Thanks,

-Brian

^ permalink raw reply

* Re: mlx5 core/en oops in 4.6-rc6+
From: Saeed Mahameed @ 2016-05-05 20:51 UTC (permalink / raw)
  To: Doug Ledford; +Cc: Linux Netdev List
In-Reply-To: <b4a8c4ca-74c5-b9b4-f9a5-4386cf6857fe@redhat.com>

On Thu, May 5, 2016 at 8:16 PM, Doug Ledford <dledford@redhat.com> wrote:
>
> That depends on which interface actually generated the oops.  If it was
> the base interface, then I don't manually set any special params on it.
> If it's one of the vlan interfaces, then there is a NetworkManager
> dispatcher script that is intended to set the tc count on interface up:
>
> [root@rdma-virt-03 ~]$ more /etc/NetworkManager/dispatcher.d/98-mlx5_roce.4*
> ::::::::::::::
> /etc/NetworkManager/dispatcher.d/98-mlx5_roce.43-egress.conf
> ::::::::::::::
> #!/bin/sh
> interface=$1
> status=$2
> [ "$interface" = mlx5_roce.43 ] || exit 0
> case $status in
> up)
>         tc qdisc add dev mlx5_roce root mqprio num_tc 8 map 5 5 5 5 5 5 5 5 5 5
> 5 5 5 5 5 5

Well, here you are configuring 8 TCs on the base mlx5 interface, so
the answer to my question is yes.

It appears that we have a bug in mlx5e_slelect_queue

int channel_ix = fallback(dev, skb);
return priv->channeltc_to_txq_map[channel_ix][tc];

When num_tc > 1 the fallback can return any value between [0..
num_channles * num_tc ]

while channeltc_to_txq_map is an array of the size num_channels.

so there is a good chance that channel_ix exceeds the array limits and
resulting OOPs.

>         # tc_wrap.py -i mlx5_roce -u 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
>         ;;
> esac
> --More--(Next file:
> /etc/NetworkManager/dispatcher.d/98-mlx5_roce.45-egress.conf::::::::::::::
> /etc/NetworkManager/dispatcher.d/98-mlx5_roce.45-egress.conf
> ::::::::::::::
> #!/bin/sh
> interface=$1
> status=$2
> [ "$interface" = mlx5_roce.45 ] || exit 0
> case $status in
> up)
>         tc qdisc add dev mlx5_roce root mqprio num_tc 8 map 5 5 5 5 5 5 5 5 5 5
> 5 5 5 5 5 5

will, here you map all user skb prios (skb->priority) to HW tc 5.
BTW skprio or user prio in this example is never the vlan prio it is
the ipv4 (ToS).

please see http://lartc.org/manpages/tc-prio.html

So to achieve a vlan prio to HW tc mapping, you will need to map the
skprios to vlan prios using vlan egress mapping
which i see you already do down below.

But, our select queue implementation will extract the vlan priority
and use the corresponding TC from our own
priv->channeltc_to_txq_map[channel_ix][up] mapping
where up is vlan user priority.  but this only applies to kernel
traffic, i don't see why it is needed for RoCE.

Currently this code is buggy and I will need to dig more into how to
provide a full working solution that fits our hardware requirements
and complies with the kernel QoS APIs.


[...]

> [root@rdma-virt-02 vlan]$ for i in *; do echo "$i:"; cat $i; echo; done
> config:
> VLAN Dev name    | VLAN ID
> Name-Type: VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD
> mlx5_roce.45   | 45  | mlx5_roce
> mlx5_roce.43   | 43  | mlx5_roce
>
> mlx5_roce.43:
> mlx5_roce.43  VID: 43    REORDER_HDR: 1  dev->priv_flags: 1001
>          total frames received           57
>           total bytes received         5010
>       Broadcast/Multicast Rcvd            0
>
>       total frames transmitted           20
>        total bytes transmitted         2525
> Device: mlx5_roce
> INGRESS priority mappings: 0:0  1:0  2:0  3:0  4:0  5:0  6:0 7:0
>  EGRESS priority mappings: 0:3 1:3 2:3 3:3 4:3 5:3 6:3 7:3
>

Here you map every SKB prio (0..7) to vlan priorty 3.

>
> mlx5_roce.45:
> mlx5_roce.45  VID: 45    REORDER_HDR: 1  dev->priv_flags: 1001
>          total frames received           57
>           total bytes received         5010
>       Broadcast/Multicast Rcvd            0
>
>       total frames transmitted           21
>        total bytes transmitted         2603
> Device: mlx5_roce
> INGRESS priority mappings: 0:0  1:0  2:0  3:0  4:0  5:0  6:0 7:0
>  EGRESS priority mappings: 0:5 1:5 2:5 3:5 4:5 5:5 6:5 7:5
>
> OK, so the vlans have egress mappings, but they don't match what the
> mlx5_roce.43 egress.conf file should have enabled.  Digging a little
> further on this machine:
>
> [root@rdma-virt-03 vlan]$ more
> /etc/sysconfig/network-scripts/ifcfg-mlx5_roce.4?
> ::::::::::::::
> /etc/sysconfig/network-scripts/ifcfg-mlx5_roce.43
> ::::::::::::::
> DEVICE=mlx5_roce.43
> VLAN=yes
> VLAN_ID=43
> VLAN_EGRESS_PRIORITY_MAP=0:3,1:3,2:3,3:3,4:3,5:3,6:3,7:3
> TYPE=Vlan
> ONBOOT=yes
> BOOTPROTO=dhcp
> DEFROUTE=no
> PEERDNS=no
> PEERROUTES=yes
> IPV4_FAILURE_FATAL=yes
> IPV6INIT=yes
> IPV6_AUTOCONF=yes
> IPV6_DEFROUTE=no
> IPV6_PEERDNS=no
> IPV6_PEERROUTES=yes
> IPV6_FAILURE_FATAL=no
> NAME=mlx5_roce.43
> ::::::::::::::
> /etc/sysconfig/network-scripts/ifcfg-mlx5_roce.45
> ::::::::::::::
> DEVICE=mlx5_roce.45
> VLAN=yes
> VLAN_ID=45
> VLAN_EGRESS_PRIORITY_MAP=0:5,1:5,2:5,3:5,4:5,5:5,6:5,7:5
> TYPE=Vlan
> ONBOOT=yes
> BOOTPROTO=dhcp
> DEFROUTE=no
> PEERDNS=no
> PEERROUTES=yes
> IPV4_FAILURE_FATAL=yes
> IPV6INIT=yes
> IPV6_AUTOCONF=yes
> IPV6_DEFROUTE=no
> IPV6_PEERDNS=no
> IPV6_PEERROUTES=yes
> IPV6_FAILURE_FATAL=no
> NAME=mlx5_roce.45
> [root@rdma-virt-03 vlan]$
>
> This is a Fedora rawhide machine, using NetworkManager to handle the
> network interfaces.  So, the egress priority mappings are being set by
> NM.  I don't know if they are overriding the egress mapping dispatchers
> or if the egress mapping dispatchers are failing to work/run properly.
> It might be the latter.  Let me double check the command...
>
> OK, re-reading the egress dispatchers above, they work on the base
> interface, not on the vlan interface that triggers them.  That's why
> they both use the same command (mapping to egress 5) instead of being
> like the ifcfg files, which map the 43 vlan to egress priority 3, and
> the 45 vlan to egress priority 5.  Running tc qdisc | grep mlx5_roce
> shows that the egress mapping is being applied (although I'm not sure it
> should be...I made that mapping many kernels ago when that was the right
> thing to do, the modern mlx5 ethernet drivers create their own mappings
> that are drastically different).
>
> So, to answer your question, yes, num_tc > 1, num_tc == 8, and I
> probably need to reconfigure that egress dispatcher to do what I want it
> to do (which is merely to make sure that all packets from specific
> interfaces are tagged with specific vlan priorities so per-priority flow
> control between the card and switch works properly, the base interface
> is supposed to have no priority tag, the 43 vlan is supposed to have
> priority tag 3, and vlan 45 is supposed to have priority tag 5) on
> modern kernels.
>

As i said above configuring any num_tc > 1 might cause the panic you saw.

Regarding the proper mapping to do for 45 => priority 5, 43 => prio 3.
the egress mappings you already did above should be sufficient, the
question is, do you need the vlan priorities to be mapped to a
specific HW TC dispatchers ?

if not, then you don't need to configure  "tc qdisc add dev mlx5_roce
root ..." at all.

^ permalink raw reply

* Re: [PATCH nf-next 0/9] netfilter: remove per-netns conntrack tables, part 1
From: Florian Westphal @ 2016-05-05 20:54 UTC (permalink / raw)
  To: Brian Haley; +Cc: Florian Westphal, netfilter-devel, netdev
In-Reply-To: <572BACA3.6070303@hpe.com>

Brian Haley <brian.haley@hpe.com> wrote:
> Openstack networking creates virtual routers using namespaces for isolation
> between users.  VETH pairs are used to connect the interfaces on these
> routers to different networks, whether they are internal (private) or
> external (public).  In most cases NAT is done inside the namespace as
> packets move between the networks.
> 
> I've seen cases where certain users are attacked, where the CT table is
> filled such that we start seeing "nf_conntrack: table full, dropping packet"
> messages (as expected).  But other users continue to function normally,
> unaffected.  Is this still the case - each netns has some limit it can't
> exceed?

The limit is global, the accounting per namespace.

If the bucket count (net.netfilter.nf_conntrack_buckets) is high enough
to accomodate the expected load and noone can create arbitrary number of
net namespaces things are fine.

I haven't changed the way this works yet because I did not have a better
idea so far.

^ permalink raw reply

* Re: [PATCH 0/3] net-next: mediatek: improve phy support
From: David Miller @ 2016-05-05 21:20 UTC (permalink / raw)
  To: john; +Cc: nbd, netdev, linux-mediatek, linux-kernel
In-Reply-To: <1462439856-51788-1-git-send-email-john@phrozen.org>


Sorry, I'm not entertaining 3 seperate patch series for the same
driver at one time.  I'm removing all of these mediatek patches
from my queue.

Submit one series at a time please, thanks.

^ permalink raw reply

* Re: [PATCH net-next v4] macvtap: add namespace support to the sysfs device class
From: David Miller @ 2016-05-05 21:23 UTC (permalink / raw)
  To: marc; +Cc: netdev, ebiederm
In-Reply-To: <1462443266-3166-1-git-send-email-marc@arista.com>

From: Marc Angel <marc@arista.com>
Date: Thu,  5 May 2016 12:14:26 +0200

> When creating macvtaps that are expected to have the same ifindex
> in different network namespaces, only the first one will succeed.
> The others will fail with a sysfs_warn_dup warning due to them trying
> to create the following sysfs link (with 'NN' the ifindex of macvtapX):
> 
> /sys/class/macvtap/tapNN -> /sys/devices/virtual/net/macvtapX/tapNN
> 
> This is reproducible by running the following commands:
> 
> ip netns add ns1
> ip netns add ns2
> ip link add veth0 type veth peer name veth1
> ip link set veth0 netns ns1
> ip link set veth1 netns ns2
> ip netns exec ns1 ip l add link veth0 macvtap0 type macvtap
> ip netns exec ns2 ip l add link veth1 macvtap1 type macvtap
> 
> The last command will fail with "RTNETLINK answers: File exists" (along
> with the kernel warning) but retrying it will work because the ifindex
> was incremented.
> 
> The 'net' device class is isolated between network namespaces so each
> one has its own hierarchy of net devices.
> This isn't the case for the 'macvtap' device class.
> The problem occurs half-way through the netdev registration, when
> `macvtap_device_event` is called-back to create the 'tapNN' macvtap
> class device under the 'macvtapX' net class device.
> 
> This patch adds namespace support to the 'macvtap' device class so
> that /sys/class/macvtap is no longer shared between net namespaces.
> 
> However, making the macvtap sysfs class namespace-aware has the side
> effect of changing /sys/devices/virtual/net/macvtapX/tapNN  into
> /sys/devices/virtual/net/macvtapX/macvtap/tapNN.
> 
> This is due to Commit 24b1442 ("Driver-core: Always create class
> directories for classses that support namespaces") and the fact that
> class devices supporting namespaces are really not supposed to be placed
> directly under other class devices.
> 
> To avoid breaking userland, a tapNN symlink pointing to macvtap/tapNN is
> created inside the macvtapX directory.
> 
> Signed-off-by: Marc Angel <marc@arista.com>

Applied, thanks.

^ permalink raw reply

* Re: [net-next PATCH v2 5/9] mlx4: Add support for UDP tunnel segmentation with outer checksum offload
From: Or Gerlitz @ 2016-05-05 21:39 UTC (permalink / raw)
  To: Alex Duyck
  Cc: Or Gerlitz, Alexander Duyck, Tom Herbert, talal@mellanox.com,
	Linux Netdev List, Michael Chan, David Miller, Gal Pressman,
	Eran Ben Elisha
In-Reply-To: <CAMt9YRqCH8Ab5vefMoQj39gJ8b-gsg2w5nJanW1srqt13bUkSQ@mail.gmail.com>

On Wed, May 4, 2016 at 7:06 PM, Alex Duyck <aduyck@mirantis.com> wrote:
> On Wed, May 4, 2016 at 8:50 AM, Or Gerlitz <ogerlitz@mellanox.com> wrote:
>> On 5/3/2016 6:29 PM, Alexander Duyck wrote:
>>>
>>> We split the one that would be a different size off via GSO.  So we
>>> end up sending up 2 frames to the device if there is going to be one
>>> piece that doesn't quite match.  We split that one piece off via GSO.
>>> That is one of the reasons why I referred to it as partial GSO as all
>>> we are using the software segmentation code for is to make sure we
>>> have the GSO block consists of segments that are all the same size.
>>
>>
>> I see, so if somehow it happens a lot that the TCP stack sends down
>> something which once segmented ends up with the last segment being of
>> different size from the other ones we would have to call the NIC xmit
>> function twice (BTW can we use xmit_more here?)  -- which could be effecting
>> performance, I guess.
>>
>> GSO_UDP_TUNNEL_CSUM (commit  0f4f4ffa7 "net: Add GSO support for UDP tunnels
>> with checksum") came to mark "that a device is capable of computing the UDP
>> checksum in the encapsulating header of a UDP tunnel" -- and the way we use
>> it here is that we do advertize that bit towards the stack for devices whose
>> HW can **not** do that, and things work b/c of LCO (this is my
>> understanding).
>>
>> I miss something in the bigger picture here, what does this buy us? e.g vs
>> just letting this (say) vxlan tunnel use zero checksum on the outer UDP
>> packet, is that has something to do with RCO?
>
> I think the piece you are missing is GSO_PARTIAL.  Basically
> GSO_PARTIAL indicates that we can perform GSO as long as all segments
> are the same size and also allows for ignoring one level of headers.
> So in the case of ixgbe for instance we can support tunnel offloads as
> long as we allow for the inner IPv4 ID to be a fixed value which is
> identified by enabling TSO_MANGLEID.  In the case of i40e, mlx4, and
> mlx5 the key bit is that we just have to have the frames the same size
> for all segments and then we can support tunnels with outer checksum
> because the checksum has been computed once and can be applied to all
> of the segmented frames.

Yep, I think to basically follow on the PARTIAL thing, which once
advertised by i40e, mlx4 and mlx5 allow them support udp (and GRE in
i40e case) tunnels with outer checksum.

My question was what this buy us for the UDP case vs. using zero
checksum for the tunnel (outer packet), I tried to figure out if it
has something to do with the remote side, e.g for RCO or alike.
Basically, under PARTIAL, on the worst case we could have ending up
with 2x packet xmitted to the NIC - e.g if each TCP message which is
to be encapsulated by the stack and later segmented by the NIC HW is
broken to two b/c otherwise the last segmented packet will not be of
equal size as of the all the preceding ones.

Or being a bit more positive... is there an expected performance  gain
when you use MANGLEID and/or PARTIAL to enable supporting UDP tunnel
segmentation checksum offload towards the stack? what is the reason
for that gain?

As for GRE tunnel segmentation checksum offload, I saw in your i40e
patch that it made your testbed to go from 12Gbs to 20Gbs, is this b/c
the stack can not actually let the HW do the segmentation w.o checksum
offload? if not, can you help understand the source of the gain?

> Hope that helps.

yes, your notes are very helpful, thanks for sparing the time..

Or.

^ permalink raw reply

* Re: [PATCH v9 net-next 7/7] openvswitch: use ipgre tunnel rather than gretap tunnel
From: pravin shelar @ 2016-05-05 21:45 UTC (permalink / raw)
  To: Simon Horman; +Cc: ovs dev, Linux Kernel Network Developers
In-Reply-To: <1462347393-22354-8-git-send-email-simon.horman-wFxRvT7yatFl57MIdRCFDg@public.gmane.org>

On Wed, May 4, 2016 at 12:36 AM, Simon Horman
<simon.horman@netronome.com> wrote:
> This allows GRE tunnels to send and receive both
> layer 2 packets (packets with an ethernet header) and
> layer 3 packets (packets without an ethernet header).
>
> Signed-off-by: Simon Horman <simon.horman@netronome.com>
> ---
> v9
> New Patch
> ---
>  include/net/gre.h              |  4 ++--
>  net/ipv4/ip_gre.c              |  8 ++++----
>  net/openvswitch/vport-gre.c    |  4 ++--
>  net/openvswitch/vport-netdev.c | 12 +++++++++++-
>  net/openvswitch/vport-netdev.h |  1 +
>  5 files changed, 20 insertions(+), 9 deletions(-)
>
...
...
> diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
> index f003225de994..b1aa02904ae4 100644
> --- a/net/openvswitch/vport-gre.c
> +++ b/net/openvswitch/vport-gre.c
> @@ -60,7 +60,7 @@ static struct vport *gre_tnl_create(const struct vport_parms *parms)
>                 return vport;
>
>         rtnl_lock();
> -       dev = gretap_fb_dev_create(net, parms->name, NET_NAME_USER);
> +       dev = gre_fb_dev_create(net, parms->name, NET_NAME_USER);
>         if (IS_ERR(dev)) {
>                 rtnl_unlock();
>                 ovs_vport_free(vport);
> @@ -87,7 +87,7 @@ static struct vport *gre_create(const struct vport_parms *parms)
>  static struct vport_ops ovs_gre_vport_ops = {
>         .type           = OVS_VPORT_TYPE_GRE,
>         .create         = gre_create,
> -       .send           = ovs_netdev_send_tap,
> +       .send           = ovs_netdev_send_raw_tun,
>         .destroy        = ovs_netdev_tunnel_destroy,
>  };
>

This trick of using vport-send only works in case of compat tunnel
device mode. But in normal case the LWT interface allows us to use net
devices for tunnel traffic. So you need some sort of mechanism to
handle l3 only packets on vport-netdev.
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

^ permalink raw reply

* Re: [net-next PATCH v2 5/9] mlx4: Add support for UDP tunnel segmentation with outer checksum offload
From: Alexander Duyck @ 2016-05-05 22:00 UTC (permalink / raw)
  To: Or Gerlitz
  Cc: Alex Duyck, Or Gerlitz, Tom Herbert, talal@mellanox.com,
	Linux Netdev List, Michael Chan, David Miller, Gal Pressman,
	Eran Ben Elisha
In-Reply-To: <CAJ3xEMj8z617kmoc2bLMBXf7B7KSBLzqr5tLTuuXYSOA--MYMw@mail.gmail.com>

On Thu, May 5, 2016 at 2:39 PM, Or Gerlitz <gerlitz.or@gmail.com> wrote:
> On Wed, May 4, 2016 at 7:06 PM, Alex Duyck <aduyck@mirantis.com> wrote:
>> On Wed, May 4, 2016 at 8:50 AM, Or Gerlitz <ogerlitz@mellanox.com> wrote:
>>> On 5/3/2016 6:29 PM, Alexander Duyck wrote:
>>>>
>>>> We split the one that would be a different size off via GSO.  So we
>>>> end up sending up 2 frames to the device if there is going to be one
>>>> piece that doesn't quite match.  We split that one piece off via GSO.
>>>> That is one of the reasons why I referred to it as partial GSO as all
>>>> we are using the software segmentation code for is to make sure we
>>>> have the GSO block consists of segments that are all the same size.
>>>
>>>
>>> I see, so if somehow it happens a lot that the TCP stack sends down
>>> something which once segmented ends up with the last segment being of
>>> different size from the other ones we would have to call the NIC xmit
>>> function twice (BTW can we use xmit_more here?)  -- which could be effecting
>>> performance, I guess.
>>>
>>> GSO_UDP_TUNNEL_CSUM (commit  0f4f4ffa7 "net: Add GSO support for UDP tunnels
>>> with checksum") came to mark "that a device is capable of computing the UDP
>>> checksum in the encapsulating header of a UDP tunnel" -- and the way we use
>>> it here is that we do advertize that bit towards the stack for devices whose
>>> HW can **not** do that, and things work b/c of LCO (this is my
>>> understanding).
>>>
>>> I miss something in the bigger picture here, what does this buy us? e.g vs
>>> just letting this (say) vxlan tunnel use zero checksum on the outer UDP
>>> packet, is that has something to do with RCO?
>>
>> I think the piece you are missing is GSO_PARTIAL.  Basically
>> GSO_PARTIAL indicates that we can perform GSO as long as all segments
>> are the same size and also allows for ignoring one level of headers.
>> So in the case of ixgbe for instance we can support tunnel offloads as
>> long as we allow for the inner IPv4 ID to be a fixed value which is
>> identified by enabling TSO_MANGLEID.  In the case of i40e, mlx4, and
>> mlx5 the key bit is that we just have to have the frames the same size
>> for all segments and then we can support tunnels with outer checksum
>> because the checksum has been computed once and can be applied to all
>> of the segmented frames.
>
> Yep, I think to basically follow on the PARTIAL thing, which once
> advertised by i40e, mlx4 and mlx5 allow them support udp (and GRE in
> i40e case) tunnels with outer checksum.
>
> My question was what this buy us for the UDP case vs. using zero
> checksum for the tunnel (outer packet), I tried to figure out if it
> has something to do with the remote side, e.g for RCO or alike.
> Basically, under PARTIAL, on the worst case we could have ending up
> with 2x packet xmitted to the NIC - e.g if each TCP message which is
> to be encapsulated by the stack and later segmented by the NIC HW is
> broken to two b/c otherwise the last segmented packet will not be of
> equal size as of the all the preceding ones.

There ends up being a few pieces to this.  In the case of i40e the Tx
gain seen is mostly for just transmitting the tunnel types with
checksums.  This is because without that we have to use software
segmentation and that is expensive because it requires 40+ frames to
transmit a single 64K block of TCP data.  In the case of GSO_PARTIAL
this data is usually all sent in a single packet because the TCP stack
tries to send MSS aligned blocks.

On the Rx side a gain can be seen if we exceed the number of ports
that can be used to support tunnels on the device.  This is because
the hardware can still offload the outer UDP checksum and as a result
it can still go GRO on the frame thanks to the code Tom Herbert added
that converts validated outer UDP checksums to checksum complete.
Without the outer UDP checksum present we wouldn't be able to do GRO
and throughput drops to the 6 - 9Gb/s range.

> Or being a bit more positive... is there an expected performance  gain
> when you use MANGLEID and/or PARTIAL to enable supporting UDP tunnel
> segmentation checksum offload towards the stack? what is the reason
> for that gain?

The TSO_MANGLEID bit is only really needed for igb and ixgbe.  Those
drivers don't support tunnel offloads directly.  Instead they can
support checksum offloads or a segmentation offload with an arbitrary
IP header size up to 511 bytes.  So in order to do segmentation for
tunnels what we are doing is repeating everything from the outer
transport header through the inner network header for each frame.  As
such we can only perform segmentation offloads for IPv4 in any type of
tunnel if we can repeat the IP ID for the inner header.  If we are
allowed to do that then we can move packets between functions on the
same device at 15Gb/s which is the upper limits of non-encapsulated
traffic for VF to VF.  Without that we are at 12Gb/s with outer
checksums and software segmentation, and only 6Gb/s with software
segmentation and outer checksum forced to 0.

> As for GRE tunnel segmentation checksum offload, I saw in your i40e
> patch that it made your testbed to go from 12Gbs to 20Gbs, is this b/c
> the stack can not actually let the HW do the segmentation w.o checksum
> offload? if not, can you help understand the source of the gain?

The device didn't advertise NETIF_F_GRE_CSUM so if there was a
checksum in the GRE header the packet had to be segmented in software.
By using the GSO_PARTIAL approach the speed is improved and comes up
to about 20Gb/s which is what the hardware does for standard GRE
tunnels.  Basically the best software segmentation can do is 12Gb/s
for most NICs on a single flow.  With hardware segment or GSO partial
we can push somewhere around 20Gb/s or more depending on the
configuration.

>> Hope that helps.
>
> yes, your notes are very helpful, thanks for sparing the time..

No problem.

- Alex

^ permalink raw reply

* [RFC PATCH] gso: Replace SKB_GSO_IPIP and SKB_GSO_SIT with outer L3 types
From: Alexander Duyck @ 2016-05-05 22:12 UTC (permalink / raw)
  To: netdev, michael.chan, alexander.duyck, tom

This patch removes SKB_GSO_IPIP and SKB_GSO_SIT and instead replaces them
with SKB_GSO_IPIPV4 and SKB_GSO_IPIPV6.  The idea here is that SKB_GSO_IPIP
and SKB_GSO_SIT are actually redundant as TCPV4 and TCPV6 were already
representing the inner network header type.  By reporting what the outer
network header type is we should be able to represent all applicable cases
as SKB_GSO_IPIPV4 can be combined with SKB_GSO_TCPV4 or SKB_GSO_TCPV6 and
it should then be possible to describe all possible IP in IP tunnel
combinations for inner and outer v4/v6.

I played it safe with the Broadcom drivers and just merged GSO_IPIP and
GSO_SIT into GSO_IPIPV4, if the drivers do support outer IPv6 tunnels I can
either update this patch to add them in, or can add a patch to enable that
later.

In the case of the Intel drivers I know they should be able to handle IPv6
outer headers so I went ahead and enabled GSO_IPIPV6 for them.

This patch is meant to be applied after "gso: Remove arbitrary checks for
unsupported GSO" which can be found at:
https://patchwork.ozlabs.org/patch/618757/

Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c  |    5 ++---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c         |    4 ++--
 drivers/net/ethernet/intel/i40e/i40e_main.c       |    4 ++--
 drivers/net/ethernet/intel/i40e/i40e_txrx.c       |    4 ++--
 drivers/net/ethernet/intel/i40evf/i40e_txrx.c     |    4 ++--
 drivers/net/ethernet/intel/i40evf/i40evf_main.c   |    4 ++--
 drivers/net/ethernet/intel/igb/igb_main.c         |    4 ++--
 drivers/net/ethernet/intel/igbvf/netdev.c         |    4 ++--
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |    4 ++--
 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |    4 ++--
 include/linux/netdev_features.h                   |   12 ++++++------
 include/linux/netdevice.h                         |    4 ++--
 include/linux/skbuff.h                            |    4 ++--
 net/core/ethtool.c                                |    4 ++--
 net/ipv4/af_inet.c                                |   16 +++++++++++-----
 net/ipv4/ipip.c                                   |    2 +-
 net/ipv6/ip6_offload.c                            |    7 +++++--
 net/ipv6/sit.c                                    |    4 ++--
 net/netfilter/ipvs/ip_vs_xmit.c                   |   14 +++-----------
 19 files changed, 54 insertions(+), 54 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index d465bd721146..fbc713094611 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -13259,12 +13259,11 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
 		NETIF_F_RXHASH | NETIF_F_HW_VLAN_CTAG_TX;
 	if (!chip_is_e1x) {
 		dev->hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL |
-				    NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT;
+				    NETIF_F_GSO_IPIPV4;
 		dev->hw_enc_features =
 			NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
 			NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
-			NETIF_F_GSO_IPIP |
-			NETIF_F_GSO_SIT |
+			NETIF_F_GSO_IPIPV4 |
 			NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL;
 	}
 
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index fd85b6dd4a6e..b3821fbf8e1b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -6218,7 +6218,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
 			   NETIF_F_TSO | NETIF_F_TSO6 |
 			   NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
-			   NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT |
+			   NETIF_F_GSO_IPIPV4 |
 			   NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM |
 			   NETIF_F_GSO_PARTIAL | NETIF_F_RXHASH |
 			   NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO;
@@ -6228,7 +6228,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 			NETIF_F_TSO | NETIF_F_TSO6 |
 			NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
 			NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM |
-			NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT |
+			NETIF_F_GSO_IPIPV4 |
 			NETIF_F_GSO_PARTIAL;
 	dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM |
 				    NETIF_F_GSO_GRE_CSUM;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 1cd0ebf7520a..bf1d31c4e310 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -9083,8 +9083,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 				   NETIF_F_TSO6			|
 				   NETIF_F_GSO_GRE		|
 				   NETIF_F_GSO_GRE_CSUM		|
-				   NETIF_F_GSO_IPIP		|
-				   NETIF_F_GSO_SIT		|
+				   NETIF_F_GSO_IPIPV4		|
+				   NETIF_F_GSO_IPIPV6		|
 				   NETIF_F_GSO_UDP_TUNNEL	|
 				   NETIF_F_GSO_UDP_TUNNEL_CSUM	|
 				   NETIF_F_GSO_PARTIAL		|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 36a34f7191e3..180d4a889c69 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -2302,8 +2302,8 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
 
 	if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
 					 SKB_GSO_GRE_CSUM |
-					 SKB_GSO_IPIP |
-					 SKB_GSO_SIT |
+					 SKB_GSO_IPIPV4 |
+					 SKB_GSO_IPIPV6 |
 					 SKB_GSO_UDP_TUNNEL |
 					 SKB_GSO_UDP_TUNNEL_CSUM)) {
 		if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
index fd7dae46c5d8..e2630c663cfb 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
@@ -1559,8 +1559,8 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
 
 	if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
 					 SKB_GSO_GRE_CSUM |
-					 SKB_GSO_IPIP |
-					 SKB_GSO_SIT |
+					 SKB_GSO_IPIPV4 |
+					 SKB_GSO_IPIPV6 |
 					 SKB_GSO_UDP_TUNNEL |
 					 SKB_GSO_UDP_TUNNEL_CSUM)) {
 		if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 642bb45ed906..3a72568d8175 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -2230,8 +2230,8 @@ int i40evf_process_config(struct i40evf_adapter *adapter)
 				   NETIF_F_TSO6			|
 				   NETIF_F_GSO_GRE		|
 				   NETIF_F_GSO_GRE_CSUM		|
-				   NETIF_F_GSO_IPIP		|
-				   NETIF_F_GSO_SIT		|
+				   NETIF_F_GSO_IPIPV4		|
+				   NETIF_F_GSO_IPIPV6		|
 				   NETIF_F_GSO_UDP_TUNNEL	|
 				   NETIF_F_GSO_UDP_TUNNEL_CSUM	|
 				   NETIF_F_GSO_PARTIAL		|
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 21727692bef6..1ba2213ce5d5 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2418,8 +2418,8 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 #define IGB_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
 				  NETIF_F_GSO_GRE_CSUM | \
-				  NETIF_F_GSO_IPIP | \
-				  NETIF_F_GSO_SIT | \
+				  NETIF_F_GSO_IPIPV4 | \
+				  NETIF_F_GSO_IPIPV6 | \
 				  NETIF_F_GSO_UDP_TUNNEL | \
 				  NETIF_F_GSO_UDP_TUNNEL_CSUM)
 
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 322a2d7828a5..de1827983096 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2763,8 +2763,8 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 #define IGBVF_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
 				    NETIF_F_GSO_GRE_CSUM | \
-				    NETIF_F_GSO_IPIP | \
-				    NETIF_F_GSO_SIT | \
+				    NETIF_F_GSO_IPIPV4 | \
+				    NETIF_F_GSO_IPIPV6 | \
 				    NETIF_F_GSO_UDP_TUNNEL | \
 				    NETIF_F_GSO_UDP_TUNNEL_CSUM)
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index d08fbcfb9417..9180361a909c 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9482,8 +9482,8 @@ skip_sriov:
 
 #define IXGBE_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
 				    NETIF_F_GSO_GRE_CSUM | \
-				    NETIF_F_GSO_IPIP | \
-				    NETIF_F_GSO_SIT | \
+				    NETIF_F_GSO_IPIPV4 | \
+				    NETIF_F_GSO_IPIPV6 | \
 				    NETIF_F_GSO_UDP_TUNNEL | \
 				    NETIF_F_GSO_UDP_TUNNEL_CSUM)
 
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 5e348b125090..622f456ec41e 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4062,8 +4062,8 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 #define IXGBEVF_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
 				      NETIF_F_GSO_GRE_CSUM | \
-				      NETIF_F_GSO_IPIP | \
-				      NETIF_F_GSO_SIT | \
+				      NETIF_F_GSO_IPIPV4 | \
+				      NETIF_F_GSO_IPIPV6 | \
 				      NETIF_F_GSO_UDP_TUNNEL | \
 				      NETIF_F_GSO_UDP_TUNNEL_CSUM)
 
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index bc8736266749..f10248df9705 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -44,8 +44,8 @@ enum {
 	NETIF_F_FSO_BIT,		/* ... FCoE segmentation */
 	NETIF_F_GSO_GRE_BIT,		/* ... GRE with TSO */
 	NETIF_F_GSO_GRE_CSUM_BIT,	/* ... GRE with csum with TSO */
-	NETIF_F_GSO_IPIP_BIT,		/* ... IPIP tunnel with TSO */
-	NETIF_F_GSO_SIT_BIT,		/* ... SIT tunnel with TSO */
+	NETIF_F_GSO_IPIPV4_BIT,		/* ... IP in IPv4 tunnel with TSO */
+	NETIF_F_GSO_IPIPV6_BIT,		/* ... IP in IPv6 tunnel with TSO */
 	NETIF_F_GSO_UDP_TUNNEL_BIT,	/* ... UDP TUNNEL with TSO */
 	NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */
 	NETIF_F_GSO_PARTIAL_BIT,	/* ... Only segment inner-most L4
@@ -121,8 +121,8 @@ enum {
 #define NETIF_F_RXALL		__NETIF_F(RXALL)
 #define NETIF_F_GSO_GRE		__NETIF_F(GSO_GRE)
 #define NETIF_F_GSO_GRE_CSUM	__NETIF_F(GSO_GRE_CSUM)
-#define NETIF_F_GSO_IPIP	__NETIF_F(GSO_IPIP)
-#define NETIF_F_GSO_SIT		__NETIF_F(GSO_SIT)
+#define NETIF_F_GSO_IPIPV4	__NETIF_F(GSO_IPIPV4)
+#define NETIF_F_GSO_IPIPV6	__NETIF_F(GSO_IPIPV6)
 #define NETIF_F_GSO_UDP_TUNNEL	__NETIF_F(GSO_UDP_TUNNEL)
 #define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM)
 #define NETIF_F_TSO_MANGLEID	__NETIF_F(TSO_MANGLEID)
@@ -200,8 +200,8 @@ enum {
 
 #define NETIF_F_GSO_ENCAP_ALL	(NETIF_F_GSO_GRE |			\
 				 NETIF_F_GSO_GRE_CSUM |			\
-				 NETIF_F_GSO_IPIP |			\
-				 NETIF_F_GSO_SIT |			\
+				 NETIF_F_GSO_IPIPV4 |			\
+				 NETIF_F_GSO_IPIPV6 |			\
 				 NETIF_F_GSO_UDP_TUNNEL |		\
 				 NETIF_F_GSO_UDP_TUNNEL_CSUM)
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 63580e6d0df4..d9d05d6b5849 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4005,8 +4005,8 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
 	BUILD_BUG_ON(SKB_GSO_FCOE    != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT));
 	BUILD_BUG_ON(SKB_GSO_GRE     != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT));
 	BUILD_BUG_ON(SKB_GSO_GRE_CSUM != (NETIF_F_GSO_GRE_CSUM >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_IPIP    != (NETIF_F_GSO_IPIP >> NETIF_F_GSO_SHIFT));
-	BUILD_BUG_ON(SKB_GSO_SIT     != (NETIF_F_GSO_SIT >> NETIF_F_GSO_SHIFT));
+	BUILD_BUG_ON(SKB_GSO_IPIPV4  != (NETIF_F_GSO_IPIPV4 >> NETIF_F_GSO_SHIFT));
+	BUILD_BUG_ON(SKB_GSO_IPIPV6  != (NETIF_F_GSO_IPIPV6 >> NETIF_F_GSO_SHIFT));
 	BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));
 	BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));
 	BUILD_BUG_ON(SKB_GSO_PARTIAL != (NETIF_F_GSO_PARTIAL >> NETIF_F_GSO_SHIFT));
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index c413c588a24f..6186a6446d1c 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -471,9 +471,9 @@ enum {
 
 	SKB_GSO_GRE_CSUM = 1 << 8,
 
-	SKB_GSO_IPIP = 1 << 9,
+	SKB_GSO_IPIPV4 = 1 << 9,
 
-	SKB_GSO_SIT = 1 << 10,
+	SKB_GSO_IPIPV6 = 1 << 10,
 
 	SKB_GSO_UDP_TUNNEL = 1 << 11,
 
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index bdb4013581b1..8771dafe93ec 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -84,8 +84,8 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
 	[NETIF_F_FSO_BIT] =              "tx-fcoe-segmentation",
 	[NETIF_F_GSO_GRE_BIT] =		 "tx-gre-segmentation",
 	[NETIF_F_GSO_GRE_CSUM_BIT] =	 "tx-gre-csum-segmentation",
-	[NETIF_F_GSO_IPIP_BIT] =	 "tx-ipip-segmentation",
-	[NETIF_F_GSO_SIT_BIT] =		 "tx-sit-segmentation",
+	[NETIF_F_GSO_IPIPV4_BIT] =	 "tx-ipip4-segmentation",
+	[NETIF_F_GSO_IPIPV6_BIT] =	 "tx-ipip6-segmentation",
 	[NETIF_F_GSO_UDP_TUNNEL_BIT] =	 "tx-udp_tnl-segmentation",
 	[NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation",
 	[NETIF_F_GSO_PARTIAL_BIT] =	 "tx-gso-partial",
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 7f08d4525981..c62230f1b16b 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1459,20 +1459,25 @@ static int inet_gro_complete(struct sk_buff *skb, int nhoff)
 
 	if (skb->encapsulation)
 		skb_set_inner_network_header(skb, nhoff);
+	else
+		skb_set_network_header(skb, nhoff);
 
 	csum_replace2(&iph->check, iph->tot_len, newlen);
 	iph->tot_len = newlen;
 
 	rcu_read_lock();
-	ops = rcu_dereference(inet_offloads[proto]);
-	if (WARN_ON(!ops || !ops->callbacks.gro_complete))
-		goto out_unlock;
 
 	/* Only need to add sizeof(*iph) to get to the next hdr below
 	 * because any hdr with option will have been flushed in
 	 * inet_gro_receive().
 	 */
-	err = ops->callbacks.gro_complete(skb, nhoff + sizeof(*iph));
+	nhoff += sizeof(*iph);
+
+	ops = rcu_dereference(inet_offloads[proto]);
+	if (WARN_ON(!ops || !ops->callbacks.gro_complete))
+		goto out_unlock;
+
+	err = ops->callbacks.gro_complete(skb, nhoff);
 
 out_unlock:
 	rcu_read_unlock();
@@ -1483,7 +1488,8 @@ out_unlock:
 static int ipip_gro_complete(struct sk_buff *skb, int nhoff)
 {
 	skb->encapsulation = 1;
-	skb_shinfo(skb)->gso_type |= SKB_GSO_IPIP;
+	skb_shinfo(skb)->gso_type = (ip_hdr(skb)->version == 4) ?
+				    SKB_GSO_IPIPV4 : SKB_GSO_IPIPV6;
 	return inet_gro_complete(skb, nhoff);
 }
 
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 92827483ee3d..16aa07688955 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -219,7 +219,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (unlikely(skb->protocol != htons(ETH_P_IP)))
 		goto tx_error;
 
-	if (iptunnel_handle_offloads(skb, SKB_GSO_IPIP))
+	if (iptunnel_handle_offloads(skb, SKB_GSO_IPIPV4))
 		goto tx_error;
 
 	skb_set_inner_ipproto(skb, IPPROTO_IPIP);
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 9ad743b2c624..b68a8a88f498 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -86,7 +86,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 	proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
 
 	if (skb->encapsulation &&
-	    skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP))
+	    (skb_shinfo(skb)->gso_type & (SKB_GSO_IPIPV4 | SKB_GSO_IPIPV6)))
 		udpfrag = proto == IPPROTO_UDP && encap;
 	else
 		udpfrag = proto == IPPROTO_UDP && !skb->encapsulation;
@@ -274,6 +274,8 @@ static int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
 
 	if (skb->encapsulation)
 		skb_set_inner_network_header(skb, nhoff);
+	else
+		skb_set_network_header(skb, nhoff);
 
 	iph->payload_len = htons(skb->len - nhoff - sizeof(*iph));
 
@@ -294,7 +296,8 @@ out_unlock:
 static int sit_gro_complete(struct sk_buff *skb, int nhoff)
 {
 	skb->encapsulation = 1;
-	skb_shinfo(skb)->gso_type |= SKB_GSO_SIT;
+	skb_shinfo(skb)->gso_type = (ipv6_hdr(skb)->version == 6) ?
+				    SKB_GSO_IPIPV6 : SKB_GSO_IPIPV4;
 	return ipv6_gro_complete(skb, nhoff);
 }
 
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index a13d8c114ccb..3945df11efaf 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -913,7 +913,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 		goto tx_error;
 	}
 
-	if (iptunnel_handle_offloads(skb, SKB_GSO_SIT)) {
+	if (iptunnel_handle_offloads(skb, SKB_GSO_IPIPV4)) {
 		ip_rt_put(rt);
 		goto tx_error;
 	}
@@ -1000,7 +1000,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	const struct iphdr  *tiph = &tunnel->parms.iph;
 
-	if (iptunnel_handle_offloads(skb, SKB_GSO_IPIP))
+	if (iptunnel_handle_offloads(skb, SKB_GSO_IPIPV4))
 		goto tx_error;
 
 	skb_set_inner_ipproto(skb, IPPROTO_IPIP);
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 6d19d2eeaa60..c2c8732ed652 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -932,17 +932,9 @@ error:
 
 static inline int __tun_gso_type_mask(int encaps_af, int orig_af)
 {
-	if (encaps_af == AF_INET) {
-		if (orig_af == AF_INET)
-			return SKB_GSO_IPIP;
-
-		return SKB_GSO_SIT;
-	}
-
-	/* GSO: we need to provide proper SKB_GSO_ value for IPv6:
-	 * SKB_GSO_SIT/IPV6
-	 */
-	return 0;
+	if (encaps_af == AF_INET)
+		return SKB_GSO_IPIPV4;
+	return SKB_GSO_IPIPV6;
 }
 
 /*

^ permalink raw reply related

* Re: [PATCH nf-next 0/9] netfilter: remove per-netns conntrack tables, part 1
From: Brian Haley @ 2016-05-05 22:22 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter-devel, netdev
In-Reply-To: <20160505205418.GA21687@breakpoint.cc>

On 05/05/2016 04:54 PM, Florian Westphal wrote:
> Brian Haley <brian.haley@hpe.com> wrote:
>> Openstack networking creates virtual routers using namespaces for isolation
>> between users.  VETH pairs are used to connect the interfaces on these
>> routers to different networks, whether they are internal (private) or
>> external (public).  In most cases NAT is done inside the namespace as
>> packets move between the networks.
>>
>> I've seen cases where certain users are attacked, where the CT table is
>> filled such that we start seeing "nf_conntrack: table full, dropping packet"
>> messages (as expected).  But other users continue to function normally,
>> unaffected.  Is this still the case - each netns has some limit it can't
>> exceed?
>
> The limit is global, the accounting per namespace.

So this is a change from existing.

> If the bucket count (net.netfilter.nf_conntrack_buckets) is high enough
> to accomodate the expected load and noone can create arbitrary number of
> net namespaces things are fine.

In my case we can't control the number of namespaces, each user will get one as 
a virtual router is created.  We could change how we size things, but that 
doesn't stop one user from consuming larger than their 1/N share of entries. 
Typically we just increase the number of systems hosting these "routers" when we 
hit a limit, which decreases the netns count per node.

> I haven't changed the way this works yet because I did not have a better
> idea so far.

Creating a per-netns maximum seems doable, but maybe not practical from the 
accounting side of things.  Can't think of anything else at the moment.

-Brian

^ permalink raw reply

* Re: [v10, 1/7] Documentation: DT: update Freescale DCFG compatible
From: Rob Herring @ 2016-05-05 22:25 UTC (permalink / raw)
  To: Yangbo Lu
  Cc: linux-mmc, linuxppc-dev, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-i2c, iommu, netdev, ulf.hansson,
	Scott Wood, Mark Rutland, Russell King, Jochen Friedrich,
	Joerg Roedel, Claudiu Manoil, Bhupesh Sharma, Qiang Zhao,
	Kumar Gala, Santosh Shilimkar, leoyang.li, xiaobo.xie
In-Reply-To: <1462417950-46796-2-git-send-email-yangbo.lu@nxp.com>

On Thu, May 05, 2016 at 11:12:24AM +0800, Yangbo Lu wrote:
> Update Freescale DCFG compatible with 'fsl,<chip>-dcfg' instead
> of 'fsl,ls1021a-dcfg' to include more chips such as ls1021a,
> ls1043a, and ls2080a.
> 
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> ---
> Changes for v8:
> 	- Added this patch
> Changes for v9:
> 	- Added a list for the possible compatibles
> Changes for v10:
> 	- None
> ---
>  Documentation/devicetree/bindings/arm/fsl.txt | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply

* Re: [RFC PATCH] gso: Replace SKB_GSO_IPIP and SKB_GSO_SIT with outer L3 types
From: Tom Herbert @ 2016-05-05 22:34 UTC (permalink / raw)
  To: Alexander Duyck
  Cc: Linux Kernel Network Developers, michael.chan, Alexander Duyck
In-Reply-To: <20160505221243.11909.29048.stgit@ahduyck-xeon-server>

I'm testing a similar change, it seems like a good idea.

On Thu, May 5, 2016 at 3:12 PM, Alexander Duyck <aduyck@mirantis.com> wrote:
> This patch removes SKB_GSO_IPIP and SKB_GSO_SIT and instead replaces them
> with SKB_GSO_IPIPV4 and SKB_GSO_IPIPV6.  The idea here is that SKB_GSO_IPIP
> and SKB_GSO_SIT are actually redundant as TCPV4 and TCPV6 were already
> representing the inner network header type.  By reporting what the outer
> network header type is we should be able to represent all applicable cases
> as SKB_GSO_IPIPV4 can be combined with SKB_GSO_TCPV4 or SKB_GSO_TCPV6 and
> it should then be possible to describe all possible IP in IP tunnel
> combinations for inner and outer v4/v6.
>
> I played it safe with the Broadcom drivers and just merged GSO_IPIP and
> GSO_SIT into GSO_IPIPV4, if the drivers do support outer IPv6 tunnels I can
> either update this patch to add them in, or can add a patch to enable that
> later.
>
> In the case of the Intel drivers I know they should be able to handle IPv6
> outer headers so I went ahead and enabled GSO_IPIPV6 for them.
>
> This patch is meant to be applied after "gso: Remove arbitrary checks for
> unsupported GSO" which can be found at:
> https://patchwork.ozlabs.org/patch/618757/
>
> Signed-off-by: Alexander Duyck <aduyck@mirantis.com>
> ---
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c  |    5 ++---
>  drivers/net/ethernet/broadcom/bnxt/bnxt.c         |    4 ++--
>  drivers/net/ethernet/intel/i40e/i40e_main.c       |    4 ++--
>  drivers/net/ethernet/intel/i40e/i40e_txrx.c       |    4 ++--
>  drivers/net/ethernet/intel/i40evf/i40e_txrx.c     |    4 ++--
>  drivers/net/ethernet/intel/i40evf/i40evf_main.c   |    4 ++--
>  drivers/net/ethernet/intel/igb/igb_main.c         |    4 ++--
>  drivers/net/ethernet/intel/igbvf/netdev.c         |    4 ++--
>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |    4 ++--
>  drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |    4 ++--
>  include/linux/netdev_features.h                   |   12 ++++++------
>  include/linux/netdevice.h                         |    4 ++--
>  include/linux/skbuff.h                            |    4 ++--
>  net/core/ethtool.c                                |    4 ++--
>  net/ipv4/af_inet.c                                |   16 +++++++++++-----
>  net/ipv4/ipip.c                                   |    2 +-
>  net/ipv6/ip6_offload.c                            |    7 +++++--
>  net/ipv6/sit.c                                    |    4 ++--
>  net/netfilter/ipvs/ip_vs_xmit.c                   |   14 +++-----------
>  19 files changed, 54 insertions(+), 54 deletions(-)
>
> diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> index d465bd721146..fbc713094611 100644
> --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
> @@ -13259,12 +13259,11 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
>                 NETIF_F_RXHASH | NETIF_F_HW_VLAN_CTAG_TX;
>         if (!chip_is_e1x) {
>                 dev->hw_features |= NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL |
> -                                   NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT;
> +                                   NETIF_F_GSO_IPIPV4;

I prefer using IPXIP4 and IPXIP6, especially to be clear that the
inner protocol is either IP version.

>                 dev->hw_enc_features =
>                         NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
>                         NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 |
> -                       NETIF_F_GSO_IPIP |
> -                       NETIF_F_GSO_SIT |
> +                       NETIF_F_GSO_IPIPV4 |
>                         NETIF_F_GSO_GRE | NETIF_F_GSO_UDP_TUNNEL;
>         }
>
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> index fd85b6dd4a6e..b3821fbf8e1b 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> @@ -6218,7 +6218,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>         dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG |
>                            NETIF_F_TSO | NETIF_F_TSO6 |
>                            NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
> -                          NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT |
> +                          NETIF_F_GSO_IPIPV4 |
>                            NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM |
>                            NETIF_F_GSO_PARTIAL | NETIF_F_RXHASH |
>                            NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO;
> @@ -6228,7 +6228,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>                         NETIF_F_TSO | NETIF_F_TSO6 |
>                         NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
>                         NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM |
> -                       NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT |
> +                       NETIF_F_GSO_IPIPV4 |
>                         NETIF_F_GSO_PARTIAL;
>         dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM |
>                                     NETIF_F_GSO_GRE_CSUM;
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
> index 1cd0ebf7520a..bf1d31c4e310 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> @@ -9083,8 +9083,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
>                                    NETIF_F_TSO6                 |
>                                    NETIF_F_GSO_GRE              |
>                                    NETIF_F_GSO_GRE_CSUM         |
> -                                  NETIF_F_GSO_IPIP             |
> -                                  NETIF_F_GSO_SIT              |
> +                                  NETIF_F_GSO_IPIPV4           |
> +                                  NETIF_F_GSO_IPIPV6           |
>                                    NETIF_F_GSO_UDP_TUNNEL       |
>                                    NETIF_F_GSO_UDP_TUNNEL_CSUM  |
>                                    NETIF_F_GSO_PARTIAL          |
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
> index 36a34f7191e3..180d4a889c69 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
> @@ -2302,8 +2302,8 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
>
>         if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
>                                          SKB_GSO_GRE_CSUM |
> -                                        SKB_GSO_IPIP |
> -                                        SKB_GSO_SIT |
> +                                        SKB_GSO_IPIPV4 |
> +                                        SKB_GSO_IPIPV6 |
>                                          SKB_GSO_UDP_TUNNEL |
>                                          SKB_GSO_UDP_TUNNEL_CSUM)) {
>                 if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
> diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
> index fd7dae46c5d8..e2630c663cfb 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
> +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
> @@ -1559,8 +1559,8 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
>
>         if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
>                                          SKB_GSO_GRE_CSUM |
> -                                        SKB_GSO_IPIP |
> -                                        SKB_GSO_SIT |
> +                                        SKB_GSO_IPIPV4 |
> +                                        SKB_GSO_IPIPV6 |
>                                          SKB_GSO_UDP_TUNNEL |
>                                          SKB_GSO_UDP_TUNNEL_CSUM)) {
>                 if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
> diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
> index 642bb45ed906..3a72568d8175 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
> +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
> @@ -2230,8 +2230,8 @@ int i40evf_process_config(struct i40evf_adapter *adapter)
>                                    NETIF_F_TSO6                 |
>                                    NETIF_F_GSO_GRE              |
>                                    NETIF_F_GSO_GRE_CSUM         |
> -                                  NETIF_F_GSO_IPIP             |
> -                                  NETIF_F_GSO_SIT              |
> +                                  NETIF_F_GSO_IPIPV4           |
> +                                  NETIF_F_GSO_IPIPV6           |
>                                    NETIF_F_GSO_UDP_TUNNEL       |
>                                    NETIF_F_GSO_UDP_TUNNEL_CSUM  |
>                                    NETIF_F_GSO_PARTIAL          |
> diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
> index 21727692bef6..1ba2213ce5d5 100644
> --- a/drivers/net/ethernet/intel/igb/igb_main.c
> +++ b/drivers/net/ethernet/intel/igb/igb_main.c
> @@ -2418,8 +2418,8 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>
>  #define IGB_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
>                                   NETIF_F_GSO_GRE_CSUM | \
> -                                 NETIF_F_GSO_IPIP | \
> -                                 NETIF_F_GSO_SIT | \
> +                                 NETIF_F_GSO_IPIPV4 | \
> +                                 NETIF_F_GSO_IPIPV6 | \
>                                   NETIF_F_GSO_UDP_TUNNEL | \
>                                   NETIF_F_GSO_UDP_TUNNEL_CSUM)
>
> diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
> index 322a2d7828a5..de1827983096 100644
> --- a/drivers/net/ethernet/intel/igbvf/netdev.c
> +++ b/drivers/net/ethernet/intel/igbvf/netdev.c
> @@ -2763,8 +2763,8 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>
>  #define IGBVF_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
>                                     NETIF_F_GSO_GRE_CSUM | \
> -                                   NETIF_F_GSO_IPIP | \
> -                                   NETIF_F_GSO_SIT | \
> +                                   NETIF_F_GSO_IPIPV4 | \
> +                                   NETIF_F_GSO_IPIPV6 | \
>                                     NETIF_F_GSO_UDP_TUNNEL | \
>                                     NETIF_F_GSO_UDP_TUNNEL_CSUM)
>
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> index d08fbcfb9417..9180361a909c 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> @@ -9482,8 +9482,8 @@ skip_sriov:
>
>  #define IXGBE_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
>                                     NETIF_F_GSO_GRE_CSUM | \
> -                                   NETIF_F_GSO_IPIP | \
> -                                   NETIF_F_GSO_SIT | \
> +                                   NETIF_F_GSO_IPIPV4 | \
> +                                   NETIF_F_GSO_IPIPV6 | \
>                                     NETIF_F_GSO_UDP_TUNNEL | \
>                                     NETIF_F_GSO_UDP_TUNNEL_CSUM)
>
> diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
> index 5e348b125090..622f456ec41e 100644
> --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
> +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
> @@ -4062,8 +4062,8 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
>
>  #define IXGBEVF_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
>                                       NETIF_F_GSO_GRE_CSUM | \
> -                                     NETIF_F_GSO_IPIP | \
> -                                     NETIF_F_GSO_SIT | \
> +                                     NETIF_F_GSO_IPIPV4 | \
> +                                     NETIF_F_GSO_IPIPV6 | \
>                                       NETIF_F_GSO_UDP_TUNNEL | \
>                                       NETIF_F_GSO_UDP_TUNNEL_CSUM)
>
> diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
> index bc8736266749..f10248df9705 100644
> --- a/include/linux/netdev_features.h
> +++ b/include/linux/netdev_features.h
> @@ -44,8 +44,8 @@ enum {
>         NETIF_F_FSO_BIT,                /* ... FCoE segmentation */
>         NETIF_F_GSO_GRE_BIT,            /* ... GRE with TSO */
>         NETIF_F_GSO_GRE_CSUM_BIT,       /* ... GRE with csum with TSO */
> -       NETIF_F_GSO_IPIP_BIT,           /* ... IPIP tunnel with TSO */
> -       NETIF_F_GSO_SIT_BIT,            /* ... SIT tunnel with TSO */
> +       NETIF_F_GSO_IPIPV4_BIT,         /* ... IP in IPv4 tunnel with TSO */
> +       NETIF_F_GSO_IPIPV6_BIT,         /* ... IP in IPv6 tunnel with TSO */
>         NETIF_F_GSO_UDP_TUNNEL_BIT,     /* ... UDP TUNNEL with TSO */
>         NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */
>         NETIF_F_GSO_PARTIAL_BIT,        /* ... Only segment inner-most L4
> @@ -121,8 +121,8 @@ enum {
>  #define NETIF_F_RXALL          __NETIF_F(RXALL)
>  #define NETIF_F_GSO_GRE                __NETIF_F(GSO_GRE)
>  #define NETIF_F_GSO_GRE_CSUM   __NETIF_F(GSO_GRE_CSUM)
> -#define NETIF_F_GSO_IPIP       __NETIF_F(GSO_IPIP)
> -#define NETIF_F_GSO_SIT                __NETIF_F(GSO_SIT)
> +#define NETIF_F_GSO_IPIPV4     __NETIF_F(GSO_IPIPV4)
> +#define NETIF_F_GSO_IPIPV6     __NETIF_F(GSO_IPIPV6)
>  #define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL)
>  #define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM)
>  #define NETIF_F_TSO_MANGLEID   __NETIF_F(TSO_MANGLEID)
> @@ -200,8 +200,8 @@ enum {
>
>  #define NETIF_F_GSO_ENCAP_ALL  (NETIF_F_GSO_GRE |                      \
>                                  NETIF_F_GSO_GRE_CSUM |                 \
> -                                NETIF_F_GSO_IPIP |                     \
> -                                NETIF_F_GSO_SIT |                      \
> +                                NETIF_F_GSO_IPIPV4 |                   \
> +                                NETIF_F_GSO_IPIPV6 |                   \
>                                  NETIF_F_GSO_UDP_TUNNEL |               \
>                                  NETIF_F_GSO_UDP_TUNNEL_CSUM)
>
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 63580e6d0df4..d9d05d6b5849 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -4005,8 +4005,8 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
>         BUILD_BUG_ON(SKB_GSO_FCOE    != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT));
>         BUILD_BUG_ON(SKB_GSO_GRE     != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT));
>         BUILD_BUG_ON(SKB_GSO_GRE_CSUM != (NETIF_F_GSO_GRE_CSUM >> NETIF_F_GSO_SHIFT));
> -       BUILD_BUG_ON(SKB_GSO_IPIP    != (NETIF_F_GSO_IPIP >> NETIF_F_GSO_SHIFT));
> -       BUILD_BUG_ON(SKB_GSO_SIT     != (NETIF_F_GSO_SIT >> NETIF_F_GSO_SHIFT));
> +       BUILD_BUG_ON(SKB_GSO_IPIPV4  != (NETIF_F_GSO_IPIPV4 >> NETIF_F_GSO_SHIFT));
> +       BUILD_BUG_ON(SKB_GSO_IPIPV6  != (NETIF_F_GSO_IPIPV6 >> NETIF_F_GSO_SHIFT));
>         BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));
>         BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));
>         BUILD_BUG_ON(SKB_GSO_PARTIAL != (NETIF_F_GSO_PARTIAL >> NETIF_F_GSO_SHIFT));
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index c413c588a24f..6186a6446d1c 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -471,9 +471,9 @@ enum {
>
>         SKB_GSO_GRE_CSUM = 1 << 8,
>
> -       SKB_GSO_IPIP = 1 << 9,
> +       SKB_GSO_IPIPV4 = 1 << 9,
>
> -       SKB_GSO_SIT = 1 << 10,
> +       SKB_GSO_IPIPV6 = 1 << 10,
>
>         SKB_GSO_UDP_TUNNEL = 1 << 11,
>
> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
> index bdb4013581b1..8771dafe93ec 100644
> --- a/net/core/ethtool.c
> +++ b/net/core/ethtool.c
> @@ -84,8 +84,8 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
>         [NETIF_F_FSO_BIT] =              "tx-fcoe-segmentation",
>         [NETIF_F_GSO_GRE_BIT] =          "tx-gre-segmentation",
>         [NETIF_F_GSO_GRE_CSUM_BIT] =     "tx-gre-csum-segmentation",
> -       [NETIF_F_GSO_IPIP_BIT] =         "tx-ipip-segmentation",
> -       [NETIF_F_GSO_SIT_BIT] =          "tx-sit-segmentation",
> +       [NETIF_F_GSO_IPIPV4_BIT] =       "tx-ipip4-segmentation",
> +       [NETIF_F_GSO_IPIPV6_BIT] =       "tx-ipip6-segmentation",
>         [NETIF_F_GSO_UDP_TUNNEL_BIT] =   "tx-udp_tnl-segmentation",
>         [NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation",
>         [NETIF_F_GSO_PARTIAL_BIT] =      "tx-gso-partial",
> diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
> index 7f08d4525981..c62230f1b16b 100644
> --- a/net/ipv4/af_inet.c
> +++ b/net/ipv4/af_inet.c
> @@ -1459,20 +1459,25 @@ static int inet_gro_complete(struct sk_buff *skb, int nhoff)
>
>         if (skb->encapsulation)
>                 skb_set_inner_network_header(skb, nhoff);
> +       else
> +               skb_set_network_header(skb, nhoff);

This seems like an unrelated change.

>
>         csum_replace2(&iph->check, iph->tot_len, newlen);
>         iph->tot_len = newlen;
>
>         rcu_read_lock();
> -       ops = rcu_dereference(inet_offloads[proto]);
> -       if (WARN_ON(!ops || !ops->callbacks.gro_complete))
> -               goto out_unlock;
>
>         /* Only need to add sizeof(*iph) to get to the next hdr below
>          * because any hdr with option will have been flushed in
>          * inet_gro_receive().
>          */
> -       err = ops->callbacks.gro_complete(skb, nhoff + sizeof(*iph));
> +       nhoff += sizeof(*iph);
> +
> +       ops = rcu_dereference(inet_offloads[proto]);
> +       if (WARN_ON(!ops || !ops->callbacks.gro_complete))
> +               goto out_unlock;
> +
> +       err = ops->callbacks.gro_complete(skb, nhoff);

Why this change?

>
>  out_unlock:
>         rcu_read_unlock();
> @@ -1483,7 +1488,8 @@ out_unlock:
>  static int ipip_gro_complete(struct sk_buff *skb, int nhoff)
>  {
>         skb->encapsulation = 1;
> -       skb_shinfo(skb)->gso_type |= SKB_GSO_IPIP;
> +       skb_shinfo(skb)->gso_type = (ip_hdr(skb)->version == 4) ?
> +                                   SKB_GSO_IPIPV4 : SKB_GSO_IPIPV6;

I don't think this is necessary. IPIP means IPv4 over IPv4, IPv4 over
IPv6 can have its own gro_complete

>         return inet_gro_complete(skb, nhoff);
>  }
>
> diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
> index 92827483ee3d..16aa07688955 100644
> --- a/net/ipv4/ipip.c
> +++ b/net/ipv4/ipip.c
> @@ -219,7 +219,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
>         if (unlikely(skb->protocol != htons(ETH_P_IP)))
>                 goto tx_error;
>
> -       if (iptunnel_handle_offloads(skb, SKB_GSO_IPIP))
> +       if (iptunnel_handle_offloads(skb, SKB_GSO_IPIPV4))
>                 goto tx_error;
>
>         skb_set_inner_ipproto(skb, IPPROTO_IPIP);
> diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
> index 9ad743b2c624..b68a8a88f498 100644
> --- a/net/ipv6/ip6_offload.c
> +++ b/net/ipv6/ip6_offload.c
> @@ -86,7 +86,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
>         proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
>
>         if (skb->encapsulation &&
> -           skb_shinfo(skb)->gso_type & (SKB_GSO_SIT|SKB_GSO_IPIP))
> +           (skb_shinfo(skb)->gso_type & (SKB_GSO_IPIPV4 | SKB_GSO_IPIPV6)))
>                 udpfrag = proto == IPPROTO_UDP && encap;
>         else
>                 udpfrag = proto == IPPROTO_UDP && !skb->encapsulation;
> @@ -274,6 +274,8 @@ static int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
>
>         if (skb->encapsulation)
>                 skb_set_inner_network_header(skb, nhoff);
> +       else
> +               skb_set_network_header(skb, nhoff);

Separate patch maybe?

>
>         iph->payload_len = htons(skb->len - nhoff - sizeof(*iph));
>
> @@ -294,7 +296,8 @@ out_unlock:
>  static int sit_gro_complete(struct sk_buff *skb, int nhoff)
>  {
>         skb->encapsulation = 1;
> -       skb_shinfo(skb)->gso_type |= SKB_GSO_SIT;
> +       skb_shinfo(skb)->gso_type = (ipv6_hdr(skb)->version == 6) ?
> +                                   SKB_GSO_IPIPV6 : SKB_GSO_IPIPV4;

Can have separate gro_complete for ip6ip6 also

>         return ipv6_gro_complete(skb, nhoff);
>  }
>
> diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
> index a13d8c114ccb..3945df11efaf 100644
> --- a/net/ipv6/sit.c
> +++ b/net/ipv6/sit.c
> @@ -913,7 +913,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
>                 goto tx_error;
>         }
>
> -       if (iptunnel_handle_offloads(skb, SKB_GSO_SIT)) {
> +       if (iptunnel_handle_offloads(skb, SKB_GSO_IPIPV4)) {
>                 ip_rt_put(rt);
>                 goto tx_error;
>         }
> @@ -1000,7 +1000,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
>         struct ip_tunnel *tunnel = netdev_priv(dev);
>         const struct iphdr  *tiph = &tunnel->parms.iph;
>
> -       if (iptunnel_handle_offloads(skb, SKB_GSO_IPIP))
> +       if (iptunnel_handle_offloads(skb, SKB_GSO_IPIPV4))
>                 goto tx_error;
>
>         skb_set_inner_ipproto(skb, IPPROTO_IPIP);
> diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
> index 6d19d2eeaa60..c2c8732ed652 100644
> --- a/net/netfilter/ipvs/ip_vs_xmit.c
> +++ b/net/netfilter/ipvs/ip_vs_xmit.c
> @@ -932,17 +932,9 @@ error:
>
>  static inline int __tun_gso_type_mask(int encaps_af, int orig_af)
>  {
> -       if (encaps_af == AF_INET) {
> -               if (orig_af == AF_INET)
> -                       return SKB_GSO_IPIP;
> -
> -               return SKB_GSO_SIT;
> -       }
> -
> -       /* GSO: we need to provide proper SKB_GSO_ value for IPv6:
> -        * SKB_GSO_SIT/IPV6
> -        */
> -       return 0;
> +       if (encaps_af == AF_INET)
> +               return SKB_GSO_IPIPV4;
> +       return SKB_GSO_IPIPV6;
>  }
>
>  /*
>

^ permalink raw reply

* Re: [PATCH nf-next 0/9] netfilter: remove per-netns conntrack tables, part 1
From: Florian Westphal @ 2016-05-05 22:36 UTC (permalink / raw)
  To: Brian Haley; +Cc: Florian Westphal, netfilter-devel, netdev
In-Reply-To: <572BC7A5.1060503@hpe.com>

Brian Haley <brian.haley@hpe.com> wrote:
> >>I've seen cases where certain users are attacked, where the CT table is
> >>filled such that we start seeing "nf_conntrack: table full, dropping packet"
> >>messages (as expected).  But other users continue to function normally,
> >>unaffected.  Is this still the case - each netns has some limit it can't
> >>exceed?
> >
> >The limit is global, the accounting per namespace.
> 
> So this is a change from existing.

No, see __nf_conntrack_alloc():

        if (nf_conntrack_max &&
            unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) {
		...

ct.count is whatever number of entries the namespace has allocated,
so max number of possible conntracks is always infinite if number
of net namespaces is unlimited (barring memory constraints, of course).

I did not change this.

^ permalink raw reply

* [PATCH] tools: bpf_jit_disasm: check for klogctl failure
From: Colin King @ 2016-05-05 22:39 UTC (permalink / raw)
  To: David S . Miller, netdev; +Cc: linux-kernel

From: Colin Ian King <colin.king@canonical.com>

klogctl can fail and return -ve len, so check for this and
return NULL to avoid passing a (size_t)-1 to malloc.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 tools/net/bpf_jit_disasm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/net/bpf_jit_disasm.c b/tools/net/bpf_jit_disasm.c
index 5b32413..544b05a 100644
--- a/tools/net/bpf_jit_disasm.c
+++ b/tools/net/bpf_jit_disasm.c
@@ -98,6 +98,9 @@ static char *get_klog_buff(unsigned int *klen)
 	char *buff;
 
 	len = klogctl(CMD_ACTION_SIZE_BUFFER, NULL, 0);
+	if (len < 0)
+		return NULL;
+
 	buff = malloc(len);
 	if (!buff)
 		return NULL;
-- 
2.8.1

^ permalink raw reply related

* [RFC PATCH net-next 00/20] net: dsa: mv88e6xxx: turn into monolithic driver
From: Vivien Didelot @ 2016-05-05 22:40 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot

This patchset merges all mv88e6* drivers supported by the shared
mv88e6xxx code into a single mv88e6xxx DSA switch driver.

Some flags are added to describe the capabilities of a switch model,
such as the presence of a PPU, EEPROM, some old or new registers, etc.

First these flags are used to conditionally support the same set of
functions in every driver, then specific driver files are removed in
favor of the common mv88e6xxx driver.

Only the merge of driver specific setup code assumes a few differences.
If these differences such as frames priorities are really needed for
some models, they can easily be brought back in a future patch.

Some inconsistencies might show up, such as the need for
MV88E6XXX_FLAG_PPU and MV88E6XXX_FLAG_PPU_ACTIVE flags. But this
patchset does not aim to fix them yet. A future patch can do that if
they end up being inconsistencies.

Vivien Didelot (20):
  net: dsa: mv88e6xxx: factorize PHY access with PPU
  net: dsa: mv88e6xxx: factorize PHY indirect access
  net: dsa: mv88e6xxx: factorize EEPROM access
  net: dsa: mv88e6xxx: factorize temperature access
  net: dsa: mv88e6xxx: factorize MAC address setting
  net: dsa: mv88e6xxx: factorize EEE access
  net: dsa: mv88e6xxx: factorize registers access
  net: dsa: mv88e6xxx: factorize bridge support
  net: dsa: mv88e6xxx: factorize VTU access
  net: dsa: mv88e6xxx: factorize ATU access
  net: dsa: mv88e6xxx: factorize switch reset
  net: dsa: mv88e6xxx: factorize global setup
  net: dsa: mv88e6xxx: factorize GLOBAL_CONTROL setup
  net: dsa: mv88e6xxx: factorize VLAN Ethertype
  net: dsa: mv88e6xxx: factorize GLOBAL_MONITOR_CONTROL setup
  net: dsa: mv88e6xxx: factorize GLOBAL_CONTROL_2 setup
  net: dsa: mv88e6xxx: factorize frames priorities
  net: dsa: mv88e6xxx: factorize switch setup
  net: dsa: mv88e6xxx: factorize tag protocol
  net: dsa: mv88e6xxx: factorize the switch driver

 arch/arm/configs/multi_v5_defconfig |    5 +-
 arch/arm/configs/mvebu_v7_defconfig |    2 +-
 arch/arm/configs/orion5x_defconfig  |    3 +-
 arch/tile/configs/tilegx_defconfig  |    3 +-
 arch/tile/configs/tilepro_defconfig |    3 +-
 drivers/net/dsa/Kconfig             |   41 +-
 drivers/net/dsa/Makefile            |   15 +-
 drivers/net/dsa/mv88e6123.c         |  130 ----
 drivers/net/dsa/mv88e6131.c         |  204 ------
 drivers/net/dsa/mv88e6171.c         |  151 ----
 drivers/net/dsa/mv88e6352.c         |  377 ----------
 drivers/net/dsa/mv88e6xxx.c         | 1348 +++++++++++++++++++++++++----------
 drivers/net/dsa/mv88e6xxx.h         |  190 ++---
 13 files changed, 1084 insertions(+), 1388 deletions(-)
 delete mode 100644 drivers/net/dsa/mv88e6123.c
 delete mode 100644 drivers/net/dsa/mv88e6131.c
 delete mode 100644 drivers/net/dsa/mv88e6171.c
 delete mode 100644 drivers/net/dsa/mv88e6352.c

-- 
2.8.2

^ permalink raw reply

* [RFC PATCH net-next 01/20] net: dsa: mv88e6xxx: factorize PHY access with PPU
From: Vivien Didelot @ 2016-05-05 22:40 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <1462488064-1841-1-git-send-email-vivien.didelot@savoirfairelinux.com>

Add a flags bitmap to the mv88e6xxx_info structure to help describing
features supported or not by a switch model.

Add a MV88E6XXX_FLAG_PPU flag to describe switch models with a PHY
Polling Unit. This allows to merge PPU specific PHY access code in the
share code. In the meantime, use unlocked register accesses.

Since the PPU code is shared, also remove NET_DSA_MV88E6XXX_NEED_PPU.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 drivers/net/dsa/Kconfig     |   5 --
 drivers/net/dsa/mv88e6131.c |  43 ++-------------
 drivers/net/dsa/mv88e6xxx.c | 130 +++++++++++++++++++++-----------------------
 drivers/net/dsa/mv88e6xxx.h |  25 ++++++---
 4 files changed, 86 insertions(+), 117 deletions(-)

diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index 90ba003..4aaadce 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -13,15 +13,10 @@ config NET_DSA_MV88E6060
 	  This enables support for the Marvell 88E6060 ethernet switch
 	  chip.
 
-config NET_DSA_MV88E6XXX_NEED_PPU
-	bool
-	default n
-
 config NET_DSA_MV88E6131
 	tristate "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support"
 	depends on NET_DSA
 	select NET_DSA_MV88E6XXX
-	select NET_DSA_MV88E6XXX_NEED_PPU
 	select NET_DSA_TAG_DSA
 	---help---
 	  This enables support for the Marvell 88E6085/6095/6095F/6131
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 357ab79..437faf8 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -24,24 +24,28 @@ static const struct mv88e6xxx_info mv88e6131_table[] = {
 		.name = "Marvell 88E6095/88E6095F",
 		.num_databases = 256,
 		.num_ports = 11,
+		.flags = MV88E6XXX_FLAG_PPU,
 	}, {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6085,
 		.family = MV88E6XXX_FAMILY_6097,
 		.name = "Marvell 88E6085",
 		.num_databases = 4096,
 		.num_ports = 10,
+		.flags = MV88E6XXX_FLAG_PPU,
 	}, {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6131,
 		.family = MV88E6XXX_FAMILY_6185,
 		.name = "Marvell 88E6131",
 		.num_databases = 256,
 		.num_ports = 8,
+		.flags = MV88E6XXX_FLAG_PPU,
 	}, {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6185,
 		.family = MV88E6XXX_FAMILY_6185,
 		.name = "Marvell 88E6185",
 		.num_databases = 256,
 		.num_ports = 10,
+		.flags = MV88E6XXX_FLAG_PPU,
 	}
 };
 
@@ -128,8 +132,6 @@ static int mv88e6131_setup(struct dsa_switch *ds)
 	if (ret < 0)
 		return ret;
 
-	mv88e6xxx_ppu_state_init(ps);
-
 	ret = mv88e6xxx_switch_reset(ps, false);
 	if (ret < 0)
 		return ret;
@@ -141,46 +143,13 @@ static int mv88e6131_setup(struct dsa_switch *ds)
 	return mv88e6xxx_setup_ports(ds);
 }
 
-static int mv88e6131_port_to_phy_addr(struct dsa_switch *ds, int port)
-{
-	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-
-	if (port >= 0 && port < ps->info->num_ports)
-		return port;
-
-	return -EINVAL;
-}
-
-static int
-mv88e6131_phy_read(struct dsa_switch *ds, int port, int regnum)
-{
-	int addr = mv88e6131_port_to_phy_addr(ds, port);
-
-	if (addr < 0)
-		return addr;
-
-	return mv88e6xxx_phy_read_ppu(ds, addr, regnum);
-}
-
-static int
-mv88e6131_phy_write(struct dsa_switch *ds,
-			      int port, int regnum, u16 val)
-{
-	int addr = mv88e6131_port_to_phy_addr(ds, port);
-
-	if (addr < 0)
-		return addr;
-
-	return mv88e6xxx_phy_write_ppu(ds, addr, regnum, val);
-}
-
 struct dsa_switch_driver mv88e6131_switch_driver = {
 	.tag_protocol		= DSA_TAG_PROTO_DSA,
 	.probe			= mv88e6131_drv_probe,
 	.setup			= mv88e6131_setup,
 	.set_addr		= mv88e6xxx_set_addr_direct,
-	.phy_read		= mv88e6131_phy_read,
-	.phy_write		= mv88e6131_phy_write,
+	.phy_read		= mv88e6xxx_phy_read,
+	.phy_write		= mv88e6xxx_phy_write,
 	.get_strings		= mv88e6xxx_get_strings,
 	.get_ethtool_stats	= mv88e6xxx_get_ethtool_stats,
 	.get_sset_count		= mv88e6xxx_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 470cfc7..4e031aa 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -241,60 +241,39 @@ static int _mv88e6xxx_phy_write(struct mv88e6xxx_priv_state *ps, int addr,
 	return 0;
 }
 
-#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
-static int mv88e6xxx_ppu_disable(struct mv88e6xxx_priv_state *ps)
+static int _mv88e6xxx_ppu_enable(struct mv88e6xxx_priv_state *ps, bool enable)
 {
-	int ret;
 	unsigned long timeout;
+	int ret;
 
-	ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);
+	ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);
 	if (ret < 0)
 		return ret;
 
-	ret = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
-				  ret & ~GLOBAL_CONTROL_PPU_ENABLE);
-	if (ret)
-		return ret;
-
-	timeout = jiffies + 1 * HZ;
-	while (time_before(jiffies, timeout)) {
-		ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS);
-		if (ret < 0)
-			return ret;
-
-		usleep_range(1000, 2000);
-		if ((ret & GLOBAL_STATUS_PPU_MASK) !=
-		    GLOBAL_STATUS_PPU_POLLING)
-			return 0;
-	}
-
-	return -ETIMEDOUT;
-}
-
-static int mv88e6xxx_ppu_enable(struct mv88e6xxx_priv_state *ps)
-{
-	int ret, err;
-	unsigned long timeout;
+	if (enable)
+		ret |= GLOBAL_CONTROL_PPU_ENABLE;
+	else
+		ret &= ~GLOBAL_CONTROL_PPU_ENABLE;
 
-	ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_CONTROL);
+	ret = _mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL, ret);
 	if (ret < 0)
 		return ret;
 
-	err = mv88e6xxx_reg_write(ps, REG_GLOBAL, GLOBAL_CONTROL,
-				  ret | GLOBAL_CONTROL_PPU_ENABLE);
-	if (err)
-		return err;
-
 	timeout = jiffies + 1 * HZ;
 	while (time_before(jiffies, timeout)) {
-		ret = mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS);
+		ret = _mv88e6xxx_reg_read(ps, REG_GLOBAL, GLOBAL_STATUS);
 		if (ret < 0)
 			return ret;
 
 		usleep_range(1000, 2000);
-		if ((ret & GLOBAL_STATUS_PPU_MASK) ==
-		    GLOBAL_STATUS_PPU_POLLING)
+
+		ret &= GLOBAL_STATUS_PPU_MASK;
+
+		if ((enable && ret == GLOBAL_STATUS_PPU_POLLING) ||
+		    (!enable && ret != GLOBAL_STATUS_PPU_POLLING)) {
+			ps->ppu_disabled = !enable;
 			return 0;
+		}
 	}
 
 	return -ETIMEDOUT;
@@ -305,9 +284,12 @@ static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
 	struct mv88e6xxx_priv_state *ps;
 
 	ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
+
 	if (mutex_trylock(&ps->ppu_mutex)) {
-		if (mv88e6xxx_ppu_enable(ps) == 0)
-			ps->ppu_disabled = 0;
+		mutex_lock(&ps->smi_mutex);
+		_mv88e6xxx_ppu_enable(ps, true);
+		mutex_unlock(&ps->smi_mutex);
+
 		mutex_unlock(&ps->ppu_mutex);
 	}
 }
@@ -319,9 +301,9 @@ static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps)
 	schedule_work(&ps->ppu_work);
 }
 
-static int mv88e6xxx_ppu_access_get(struct mv88e6xxx_priv_state *ps)
+static int _mv88e6xxx_ppu_access_get(struct mv88e6xxx_priv_state *ps)
 {
-	int ret;
+	int err;
 
 	mutex_lock(&ps->ppu_mutex);
 
@@ -330,29 +312,27 @@ static int mv88e6xxx_ppu_access_get(struct mv88e6xxx_priv_state *ps)
 	 * disabled, cancel the timer that is going to re-enable
 	 * it.
 	 */
-	if (!ps->ppu_disabled) {
-		ret = mv88e6xxx_ppu_disable(ps);
-		if (ret < 0) {
+	if (ps->ppu_disabled) {
+		del_timer(&ps->ppu_timer);
+	} else {
+		err = _mv88e6xxx_ppu_enable(ps, false);
+		if (err) {
 			mutex_unlock(&ps->ppu_mutex);
-			return ret;
+			return err;
 		}
-		ps->ppu_disabled = 1;
-	} else {
-		del_timer(&ps->ppu_timer);
-		ret = 0;
 	}
 
-	return ret;
+	return 0;
 }
 
-static void mv88e6xxx_ppu_access_put(struct mv88e6xxx_priv_state *ps)
+static void _mv88e6xxx_ppu_access_put(struct mv88e6xxx_priv_state *ps)
 {
 	/* Schedule a timer to re-enable the PHY polling unit. */
 	mod_timer(&ps->ppu_timer, jiffies + msecs_to_jiffies(10));
 	mutex_unlock(&ps->ppu_mutex);
 }
 
-void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps)
+static void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps)
 {
 	mutex_init(&ps->ppu_mutex);
 	INIT_WORK(&ps->ppu_work, mv88e6xxx_ppu_reenable_work);
@@ -361,35 +341,33 @@ void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps)
 	ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
 }
 
-int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
+static int _mv88e6xxx_phy_read_ppu(struct mv88e6xxx_priv_state *ps, int addr,
+				   int regnum)
 {
-	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
 
-	ret = mv88e6xxx_ppu_access_get(ps);
+	ret = _mv88e6xxx_ppu_access_get(ps);
 	if (ret >= 0) {
-		ret = mv88e6xxx_reg_read(ps, addr, regnum);
-		mv88e6xxx_ppu_access_put(ps);
+		ret = _mv88e6xxx_reg_read(ps, addr, regnum);
+		_mv88e6xxx_ppu_access_put(ps);
 	}
 
 	return ret;
 }
 
-int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
-			    int regnum, u16 val)
+static int _mv88e6xxx_phy_write_ppu(struct mv88e6xxx_priv_state *ps, int addr,
+				    int regnum, u16 val)
 {
-	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int ret;
 
-	ret = mv88e6xxx_ppu_access_get(ps);
+	ret = _mv88e6xxx_ppu_access_get(ps);
 	if (ret >= 0) {
-		ret = mv88e6xxx_reg_write(ps, addr, regnum, val);
-		mv88e6xxx_ppu_access_put(ps);
+		ret = _mv88e6xxx_reg_write(ps, addr, regnum, val);
+		_mv88e6xxx_ppu_access_put(ps);
 	}
 
 	return ret;
 }
-#endif
 
 static bool mv88e6xxx_6065_family(struct mv88e6xxx_priv_state *ps)
 {
@@ -2599,6 +2577,9 @@ int mv88e6xxx_setup_common(struct mv88e6xxx_priv_state *ps)
 
 	INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
 
+	if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
+		mv88e6xxx_ppu_state_init(ps);
+
 	return 0;
 }
 
@@ -2884,8 +2865,14 @@ mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
 		return 0xffff;
 
 	mutex_lock(&ps->smi_mutex);
-	ret = _mv88e6xxx_phy_read(ps, addr, regnum);
+
+	if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
+		ret = _mv88e6xxx_phy_read_ppu(ps, addr, regnum);
+	else
+		ret = _mv88e6xxx_phy_read(ps, addr, regnum);
+
 	mutex_unlock(&ps->smi_mutex);
+
 	return ret;
 }
 
@@ -2894,15 +2881,22 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
 {
 	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 	int addr = mv88e6xxx_port_to_phy_addr(ps, port);
-	int ret;
+	int err;
 
 	if (addr < 0)
 		return 0xffff;
 
+
 	mutex_lock(&ps->smi_mutex);
-	ret = _mv88e6xxx_phy_write(ps, addr, regnum, val);
+
+	if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
+		err = _mv88e6xxx_phy_write_ppu(ps, addr, regnum, val);
+	else
+		err = _mv88e6xxx_phy_write(ps, addr, regnum, val);
+
 	mutex_unlock(&ps->smi_mutex);
-	return ret;
+
+	return err;
 }
 
 int
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 4f455d2..3e77985 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -350,12 +350,23 @@ enum mv88e6xxx_family {
 	MV88E6XXX_FAMILY_6352,	/* 6172 6176 6240 6352 */
 };
 
+enum mv88e6xxx_cap {
+	/* PHY Polling Unit.
+	 * See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
+	 */
+	MV88E6XXX_CAP_PPU,
+};
+
+/* Bitmask of capabilities */
+#define MV88E6XXX_FLAG_PPU		BIT(MV88E6XXX_CAP_PPU)
+
 struct mv88e6xxx_info {
 	enum mv88e6xxx_family family;
 	u16 prod_num;
 	const char *name;
 	unsigned int num_databases;
 	unsigned int num_ports;
+	unsigned long flags;
 };
 
 struct mv88e6xxx_atu_entry {
@@ -403,15 +414,13 @@ struct mv88e6xxx_priv_state {
 	struct mii_bus *bus;
 	int sw_addr;
 
-#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
 	/* Handles automatic disabling and re-enabling of the PHY
 	 * polling unit.
 	 */
 	struct mutex		ppu_mutex;
-	int			ppu_disabled;
+	bool			ppu_disabled;
 	struct work_struct	ppu_work;
 	struct timer_list	ppu_timer;
-#endif
 
 	/* This mutex serialises access to the statistics unit.
 	 * Hold this mutex over snapshot + dump sequences.
@@ -449,6 +458,12 @@ struct mv88e6xxx_hw_stat {
 	enum stat_type type;
 };
 
+static inline bool mv88e6xxx_has(struct mv88e6xxx_priv_state *ps,
+				 unsigned long flags)
+{
+	return (ps->info->flags & flags) == flags;
+}
+
 int mv88e6xxx_switch_reset(struct mv88e6xxx_priv_state *ps, bool ppu_active);
 const char *mv88e6xxx_drv_probe(struct device *dsa_dev, struct device *host_dev,
 				int sw_addr, void **priv,
@@ -468,10 +483,6 @@ int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val);
 int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum);
 int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
 				 u16 val);
-void mv88e6xxx_ppu_state_init(struct mv88e6xxx_priv_state *ps);
-int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum);
-int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
-			    int regnum, u16 val);
 void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data);
 void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
 				 uint64_t *data);
-- 
2.8.2

^ permalink raw reply related

* [RFC PATCH net-next 02/20] net: dsa: mv88e6xxx: factorize PHY indirect access
From: Vivien Didelot @ 2016-05-05 22:40 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
	Andrew Lunn, Vivien Didelot
In-Reply-To: <1462488064-1841-1-git-send-email-vivien.didelot@savoirfairelinux.com>

Some switch has dedicated SMI PHY Command and Data registers, used to
indirectly access the PHYs, instead of direct access.

Identify these switch models and make mv88e6xxx_phy_{read,write} generic
enough to support every models.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 drivers/net/dsa/mv88e6171.c |  8 ++++++--
 drivers/net/dsa/mv88e6352.c | 10 ++++++++--
 drivers/net/dsa/mv88e6xxx.c | 37 ++++---------------------------------
 drivers/net/dsa/mv88e6xxx.h | 10 +++++++---
 4 files changed, 25 insertions(+), 40 deletions(-)

diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index f75164d..304e25e 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -24,24 +24,28 @@ static const struct mv88e6xxx_info mv88e6171_table[] = {
 		.name = "Marvell 88E6171",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.flags = MV88E6XXX_FLAG_SMI_PHY,
 	}, {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6175,
 		.family = MV88E6XXX_FAMILY_6351,
 		.name = "Marvell 88E6175",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.flags = MV88E6XXX_FLAG_SMI_PHY,
 	}, {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6350,
 		.family = MV88E6XXX_FAMILY_6351,
 		.name = "Marvell 88E6350",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.flags = MV88E6XXX_FLAG_SMI_PHY,
 	}, {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6351,
 		.family = MV88E6XXX_FAMILY_6351,
 		.name = "Marvell 88E6351",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.flags = MV88E6XXX_FLAG_SMI_PHY,
 	}
 };
 
@@ -120,8 +124,8 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
 	.probe			= mv88e6171_drv_probe,
 	.setup			= mv88e6171_setup,
 	.set_addr		= mv88e6xxx_set_addr_indirect,
-	.phy_read		= mv88e6xxx_phy_read_indirect,
-	.phy_write		= mv88e6xxx_phy_write_indirect,
+	.phy_read		= mv88e6xxx_phy_read,
+	.phy_write		= mv88e6xxx_phy_write,
 	.get_strings		= mv88e6xxx_get_strings,
 	.get_ethtool_stats	= mv88e6xxx_get_ethtool_stats,
 	.get_sset_count		= mv88e6xxx_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index c622a1d..df9f944 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -29,36 +29,42 @@ static const struct mv88e6xxx_info mv88e6352_table[] = {
 		.name = "Marvell 88E6320",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.flags = MV88E6XXX_FLAG_SMI_PHY,
 	}, {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6321,
 		.family = MV88E6XXX_FAMILY_6320,
 		.name = "Marvell 88E6321",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.flags = MV88E6XXX_FLAG_SMI_PHY,
 	}, {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6172,
 		.family = MV88E6XXX_FAMILY_6352,
 		.name = "Marvell 88E6172",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.flags = MV88E6XXX_FLAG_SMI_PHY,
 	}, {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6176,
 		.family = MV88E6XXX_FAMILY_6352,
 		.name = "Marvell 88E6176",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.flags = MV88E6XXX_FLAG_SMI_PHY,
 	}, {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6240,
 		.family = MV88E6XXX_FAMILY_6352,
 		.name = "Marvell 88E6240",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.flags = MV88E6XXX_FLAG_SMI_PHY,
 	}, {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6352,
 		.family = MV88E6XXX_FAMILY_6352,
 		.name = "Marvell 88E6352",
 		.num_databases = 4096,
 		.num_ports = 7,
+		.flags = MV88E6XXX_FLAG_SMI_PHY,
 	}
 };
 
@@ -338,8 +344,8 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
 	.probe			= mv88e6352_drv_probe,
 	.setup			= mv88e6352_setup,
 	.set_addr		= mv88e6xxx_set_addr_indirect,
-	.phy_read		= mv88e6xxx_phy_read_indirect,
-	.phy_write		= mv88e6xxx_phy_write_indirect,
+	.phy_read		= mv88e6xxx_phy_read,
+	.phy_write		= mv88e6xxx_phy_write,
 	.get_strings		= mv88e6xxx_get_strings,
 	.get_ethtool_stats	= mv88e6xxx_get_ethtool_stats,
 	.get_sset_count		= mv88e6xxx_get_sset_count,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 4e031aa..e48271c 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2868,6 +2868,8 @@ mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
 
 	if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
 		ret = _mv88e6xxx_phy_read_ppu(ps, addr, regnum);
+	else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SMI_PHY))
+		ret = _mv88e6xxx_phy_read_indirect(ps, addr, regnum);
 	else
 		ret = _mv88e6xxx_phy_read(ps, addr, regnum);
 
@@ -2891,6 +2893,8 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
 
 	if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
 		err = _mv88e6xxx_phy_write_ppu(ps, addr, regnum, val);
+	else if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_SMI_PHY))
+		err = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val);
 	else
 		err = _mv88e6xxx_phy_write(ps, addr, regnum, val);
 
@@ -2899,39 +2903,6 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
 	return err;
 }
 
-int
-mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum)
-{
-	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-	int addr = mv88e6xxx_port_to_phy_addr(ps, port);
-	int ret;
-
-	if (addr < 0)
-		return 0xffff;
-
-	mutex_lock(&ps->smi_mutex);
-	ret = _mv88e6xxx_phy_read_indirect(ps, addr, regnum);
-	mutex_unlock(&ps->smi_mutex);
-	return ret;
-}
-
-int
-mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
-			     u16 val)
-{
-	struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-	int addr = mv88e6xxx_port_to_phy_addr(ps, port);
-	int ret;
-
-	if (addr < 0)
-		return addr;
-
-	mutex_lock(&ps->smi_mutex);
-	ret = _mv88e6xxx_phy_write_indirect(ps, addr, regnum, val);
-	mutex_unlock(&ps->smi_mutex);
-	return ret;
-}
-
 #ifdef CONFIG_NET_DSA_HWMON
 
 static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 3e77985..95cbb8b 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -355,10 +355,17 @@ enum mv88e6xxx_cap {
 	 * See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
 	 */
 	MV88E6XXX_CAP_PPU,
+
+	/* SMI PHY Command and Data registers.
+	 * This requires an indirect access to PHY registers through
+	 * GLOBAL2_SMI_OP, otherwise direct access to PHY registers is done.
+	 */
+	MV88E6XXX_CAP_SMI_PHY,
 };
 
 /* Bitmask of capabilities */
 #define MV88E6XXX_FLAG_PPU		BIT(MV88E6XXX_CAP_PPU)
+#define MV88E6XXX_FLAG_SMI_PHY		BIT(MV88E6XXX_CAP_SMI_PHY)
 
 struct mv88e6xxx_info {
 	enum mv88e6xxx_family family;
@@ -480,9 +487,6 @@ int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr);
 int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr);
 int mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum);
 int mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val);
-int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum);
-int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
-				 u16 val);
 void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data);
 void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
 				 uint64_t *data);
-- 
2.8.2

^ permalink raw reply related


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