netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling
@ 2016-05-18 16:06 Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 01/16] gso: Remove arbitrary checks for unsupported GSO Tom Herbert
                   ` (17 more replies)
  0 siblings, 18 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

This patch set:
  - Fixes GRE6 to process translate flags correctly from configuration
  - Adds support for GSO and GRO for ip6ip6 and ip4ip6
  - Add support for FOU and GUE in IPv6
  - Support GRE, ip6ip6 and ip4ip6 over FOU/GUE
  - Fixes ip6_input to deal with UDP encapsulations
  - Some other minor fixes

v2:
  - Removed a check of GSO types in MPLS
  - Define GSO type SKB_GSO_IPXIP6 and SKB_GSO_IPXIP4 (based on input
    from Alexander)
  - Don't define GSO types specifically for IP6IP6 and IP4IP6, above
    fix makes that unnecessary
  - Don't bother clearing encapsulation flag in UDP tunnel segment
    (another item suggested by Alexander).

v3:
  - Address some minor comments from Alexander

v4:
  - Rebase on changes to fix IP TX tunnels
  - Fix MTU issues in ip4ip6, ip6ip6
  - Add test data for above

v5:
  - Address feedback from Shmulik Ladkani regarding extension header
    code that does not return next header but in instead relies
    on returning value via nhoff. Solution here is to fix EH
    processing to return nexthdr value.
  - Refactored IPv4 encaps so that we won't need to create
    a ip6_tunnel_core.c when adding encap support IPv6.

v6:
  - Fix build issues with regard to new GSO constants
  - FIx MTU calculation issues ip6_tunnel.c pointed out byt ALex
  - Add encap_hlen into headroom for GREv6 to work with FOU/GUE

v7:
  - Added skb_set_inner_ipproto to ip4ip6 and ip6ip6
  - Clarified max_headroom in ip6_tnl_xmit
  - Set features for IPv6 tunnels
  - Other cleanup suggested by Alexander
  - Above fixes throughput performance issues in ip4ip6 and ip6ip6,
    updated test results to reflect that

Tested: Various cases of IP tunnels with netperf TCP_STREAM and TCP_RR.

    - IPv4/GRE/GUE/IPv6 with RCO
      1 TCP_STREAM
      	6616 Mbps
      200 TCP_RR
	1244043 tps
        141/243/446 90/95/99% latencies
	86.61% CPU utilization

    - IPv6/GRE/GUE/IPv6 with RCO
      1 TCP_STREAM
	6940 Mbps
      200 TCP_RR
	1270903 tps
	138/236/440 90/95/99% latencies
	87.51% CPU utilization

     - IP6IP6
      1 TCP_STREAM
	5307 Mbps
      200 TCP_RR
	498981 tps
	388/498/631 90/95/99% latencies
	19.75% CPU utilization (1 CPU saturated)

     - IP6IP6/GUE with RCO
      1 TCP_STREAM
	5575 Mbps
      200 TCP_RR
	1233818 tps
	143/244/451 90/95/99% latencies
	87.57 CPU utilization

     - IP4IP6
      1 TCP_STREAM
	5235 Mbps
      200 TCP_RR
	763774 tps
	250/318/466 90/95/99% latencies
	35.25% CPU utilization (1 CPU saturated)

     - IP4IP6/GUE with RCO
      1 TCP_STREAM
	5337 Mbps
      200 TCP_RR
	1196385 tps
	148/251/460 90/95/99% latencies
	87.56 CPU utilization

     - GRE with keyid
      200 TCP_RR
	744173 tps
	258/332/461 90/95/99% latencies
	34.59% CPU utilization (1 CPU saturated)
      

Tom Herbert (16):
  gso: Remove arbitrary checks for unsupported GSO
  net: define gso types for IPx over IPv4 and IPv6
  ipv6: Fix nexthdr for reinjection
  ipv6: Change "final" protocol processing for encapsulation
  net: Cleanup encap items in ip_tunnels.h
  fou: Call setup_udp_tunnel_sock
  fou: Split out {fou,gue}_build_header
  fou: Support IPv6 in fou
  ip6_tun: Add infrastructure for doing encapsulation
  fou: Add encap ops for IPv6 tunnels
  ip6_gre: Add support for fou/gue encapsulation
  ip6_tunnel: Add support for fou/gue encapsulation
  ipv6: Set features for IPv6 tunnels
  ip6ip6: Support for GSO/GRO
  ip4ip6: Support for GSO/GRO
  ipv6: Don't reset inner headers in ip6_tnl_xmit

 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c  |   5 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c         |   5 +-
 drivers/net/ethernet/intel/i40e/i40e_main.c       |   3 +-
 drivers/net/ethernet/intel/i40e/i40e_txrx.c       |   3 +-
 drivers/net/ethernet/intel/i40evf/i40e_txrx.c     |   3 +-
 drivers/net/ethernet/intel/i40evf/i40evf_main.c   |   3 +-
 drivers/net/ethernet/intel/igb/igb_main.c         |   3 +-
 drivers/net/ethernet/intel/igbvf/netdev.c         |   3 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |   3 +-
 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |   3 +-
 include/linux/netdev_features.h                   |  12 +-
 include/linux/netdevice.h                         |   4 +-
 include/linux/skbuff.h                            |   4 +-
 include/net/fou.h                                 |  10 +-
 include/net/inet_common.h                         |   5 +
 include/net/ip6_tunnel.h                          |  58 +++++++
 include/net/ip_tunnels.h                          |  76 +++++++--
 net/core/ethtool.c                                |   4 +-
 net/ipv4/af_inet.c                                |  32 +---
 net/ipv4/fou.c                                    | 144 +++++++++-------
 net/ipv4/gre_offload.c                            |  14 --
 net/ipv4/ip_tunnel.c                              |  45 -----
 net/ipv4/ip_tunnel_core.c                         |   9 +
 net/ipv4/ipip.c                                   |   2 +-
 net/ipv4/tcp_offload.c                            |  19 ---
 net/ipv4/udp_offload.c                            |  10 --
 net/ipv6/Makefile                                 |   1 +
 net/ipv6/fou6.c                                   | 140 ++++++++++++++++
 net/ipv6/ip6_gre.c                                |  79 ++++++++-
 net/ipv6/ip6_input.c                              |  33 +++-
 net/ipv6/ip6_offload.c                            |  77 ++++++---
 net/ipv6/ip6_tunnel.c                             | 190 ++++++++++++++++++++--
 net/ipv6/sit.c                                    |   4 +-
 net/ipv6/udp_offload.c                            |  13 --
 net/mpls/mpls_gso.c                               |  11 +-
 net/netfilter/ipvs/ip_vs_xmit.c                   |  17 +-
 36 files changed, 737 insertions(+), 310 deletions(-)
 create mode 100644 net/ipv6/fou6.c

-- 
2.8.0.rc2

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 01/16] gso: Remove arbitrary checks for unsupported GSO
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-21  1:02   ` Hannes Frederic Sowa
  2016-05-22  7:44   ` Michael S. Tsirkin
  2016-05-18 16:06 ` [PATCH v7 net-next 02/16] net: define gso types for IPx over IPv4 and IPv6 Tom Herbert
                   ` (16 subsequent siblings)
  17 siblings, 2 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

In several gso_segment functions there are checks of gso_type against
a seemingly arbitrary list of SKB_GSO_* flags. This seems like an
attempt to identify unsupported GSO types, but since the stack is
the one that set these GSO types in the first place this seems
unnecessary to do. If a combination isn't valid in the first
place that stack should not allow setting it.

This is a code simplication especially for add new GSO types.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv4/af_inet.c     | 18 ------------------
 net/ipv4/gre_offload.c | 14 --------------
 net/ipv4/tcp_offload.c | 19 -------------------
 net/ipv4/udp_offload.c | 10 ----------
 net/ipv6/ip6_offload.c | 18 ------------------
 net/ipv6/udp_offload.c | 13 -------------
 net/mpls/mpls_gso.c    | 11 +----------
 7 files changed, 1 insertion(+), 102 deletions(-)

diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 2e6e65f..7f08d45 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1205,24 +1205,6 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 	int ihl;
 	int id;
 
-	if (unlikely(skb_shinfo(skb)->gso_type &
-		     ~(SKB_GSO_TCPV4 |
-		       SKB_GSO_UDP |
-		       SKB_GSO_DODGY |
-		       SKB_GSO_TCP_ECN |
-		       SKB_GSO_GRE |
-		       SKB_GSO_GRE_CSUM |
-		       SKB_GSO_IPIP |
-		       SKB_GSO_SIT |
-		       SKB_GSO_TCPV6 |
-		       SKB_GSO_UDP_TUNNEL |
-		       SKB_GSO_UDP_TUNNEL_CSUM |
-		       SKB_GSO_TCP_FIXEDID |
-		       SKB_GSO_TUNNEL_REMCSUM |
-		       SKB_GSO_PARTIAL |
-		       0)))
-		goto out;
-
 	skb_reset_network_header(skb);
 	nhoff = skb_network_header(skb) - skb_mac_header(skb);
 	if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index e88190a..ecd1e09 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -26,20 +26,6 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
 	int gre_offset, outer_hlen;
 	bool need_csum, ufo;
 
-	if (unlikely(skb_shinfo(skb)->gso_type &
-				~(SKB_GSO_TCPV4 |
-				  SKB_GSO_TCPV6 |
-				  SKB_GSO_UDP |
-				  SKB_GSO_DODGY |
-				  SKB_GSO_TCP_ECN |
-				  SKB_GSO_TCP_FIXEDID |
-				  SKB_GSO_GRE |
-				  SKB_GSO_GRE_CSUM |
-				  SKB_GSO_IPIP |
-				  SKB_GSO_SIT |
-				  SKB_GSO_PARTIAL)))
-		goto out;
-
 	if (!skb->encapsulation)
 		goto out;
 
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index 02737b6..5c59649 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -83,25 +83,6 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
 
 	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
 		/* Packet is from an untrusted source, reset gso_segs. */
-		int type = skb_shinfo(skb)->gso_type;
-
-		if (unlikely(type &
-			     ~(SKB_GSO_TCPV4 |
-			       SKB_GSO_DODGY |
-			       SKB_GSO_TCP_ECN |
-			       SKB_GSO_TCP_FIXEDID |
-			       SKB_GSO_TCPV6 |
-			       SKB_GSO_GRE |
-			       SKB_GSO_GRE_CSUM |
-			       SKB_GSO_IPIP |
-			       SKB_GSO_SIT |
-			       SKB_GSO_UDP_TUNNEL |
-			       SKB_GSO_UDP_TUNNEL_CSUM |
-			       SKB_GSO_TUNNEL_REMCSUM |
-			       0) ||
-			     !(type & (SKB_GSO_TCPV4 |
-				       SKB_GSO_TCPV6))))
-			goto out;
 
 		skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
 
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 6b7459c..81f253b 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -209,16 +209,6 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 
 	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
 		/* Packet is from an untrusted source, reset gso_segs. */
-		int type = skb_shinfo(skb)->gso_type;
-
-		if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
-				      SKB_GSO_UDP_TUNNEL |
-				      SKB_GSO_UDP_TUNNEL_CSUM |
-				      SKB_GSO_TUNNEL_REMCSUM |
-				      SKB_GSO_IPIP |
-				      SKB_GSO_GRE | SKB_GSO_GRE_CSUM) ||
-			     !(type & (SKB_GSO_UDP))))
-			goto out;
 
 		skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
 
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index f5eb184..9ad743b 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -69,24 +69,6 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 	bool encap, udpfrag;
 	int nhoff;
 
-	if (unlikely(skb_shinfo(skb)->gso_type &
-		     ~(SKB_GSO_TCPV4 |
-		       SKB_GSO_UDP |
-		       SKB_GSO_DODGY |
-		       SKB_GSO_TCP_ECN |
-		       SKB_GSO_TCP_FIXEDID |
-		       SKB_GSO_TCPV6 |
-		       SKB_GSO_GRE |
-		       SKB_GSO_GRE_CSUM |
-		       SKB_GSO_IPIP |
-		       SKB_GSO_SIT |
-		       SKB_GSO_UDP_TUNNEL |
-		       SKB_GSO_UDP_TUNNEL_CSUM |
-		       SKB_GSO_TUNNEL_REMCSUM |
-		       SKB_GSO_PARTIAL |
-		       0)))
-		goto out;
-
 	skb_reset_network_header(skb);
 	nhoff = skb_network_header(skb) - skb_mac_header(skb);
 	if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index 5429f6b..ac858c4 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -36,19 +36,6 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
 
 	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
 		/* Packet is from an untrusted source, reset gso_segs. */
-		int type = skb_shinfo(skb)->gso_type;
-
-		if (unlikely(type & ~(SKB_GSO_UDP |
-				      SKB_GSO_DODGY |
-				      SKB_GSO_UDP_TUNNEL |
-				      SKB_GSO_UDP_TUNNEL_CSUM |
-				      SKB_GSO_TUNNEL_REMCSUM |
-				      SKB_GSO_GRE |
-				      SKB_GSO_GRE_CSUM |
-				      SKB_GSO_IPIP |
-				      SKB_GSO_SIT) ||
-			     !(type & (SKB_GSO_UDP))))
-			goto out;
 
 		skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
 
diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c
index bbcf604..2055e57 100644
--- a/net/mpls/mpls_gso.c
+++ b/net/mpls/mpls_gso.c
@@ -26,15 +26,6 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
 	netdev_features_t mpls_features;
 	__be16 mpls_protocol;
 
-	if (unlikely(skb_shinfo(skb)->gso_type &
-				~(SKB_GSO_TCPV4 |
-				  SKB_GSO_TCPV6 |
-				  SKB_GSO_UDP |
-				  SKB_GSO_DODGY |
-				  SKB_GSO_TCP_FIXEDID |
-				  SKB_GSO_TCP_ECN)))
-		goto out;
-
 	/* Setup inner SKB. */
 	mpls_protocol = skb->protocol;
 	skb->protocol = skb->inner_protocol;
@@ -57,7 +48,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
 	 * skb_mac_gso_segment(), an indirect caller of this function.
 	 */
 	__skb_pull(skb, skb->data - skb_mac_header(skb));
-out:
+
 	return segs;
 }
 
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 02/16] net: define gso types for IPx over IPv4 and IPv6
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 01/16] gso: Remove arbitrary checks for unsupported GSO Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 22:03   ` Jeff Kirsher
  2016-05-18 16:06 ` [PATCH v7 net-next 03/16] ipv6: Fix nexthdr for reinjection Tom Herbert
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

This patch defines two new GSO definitions SKB_GSO_IPXIP4 and
SKB_GSO_IPXIP6 along with corresponding NETIF_F_GSO_IPXIP4 and
NETIF_F_GSO_IPXIP6. These are used to described IP in IP
tunnel and what the outer protocol is. The inner protocol
can be deduced from other GSO types (e.g. SKB_GSO_TCPV4 and
SKB_GSO_TCPV6). The GSO types of SKB_GSO_IPIP and SKB_GSO_SIT
are removed (these are both instances of SKB_GSO_IPXIP4).
SKB_GSO_IPXIP6 will be used when support for GSO with IP
encapsulation over IPv6 is added.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  5 ++---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c         |  5 ++---
 drivers/net/ethernet/intel/i40e/i40e_main.c       |  3 +--
 drivers/net/ethernet/intel/i40e/i40e_txrx.c       |  3 +--
 drivers/net/ethernet/intel/i40evf/i40e_txrx.c     |  3 +--
 drivers/net/ethernet/intel/i40evf/i40evf_main.c   |  3 +--
 drivers/net/ethernet/intel/igb/igb_main.c         |  3 +--
 drivers/net/ethernet/intel/igbvf/netdev.c         |  3 +--
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |  3 +--
 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |  3 +--
 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                                |  2 +-
 net/ipv4/ipip.c                                   |  2 +-
 net/ipv6/ip6_offload.c                            |  4 ++--
 net/ipv6/sit.c                                    |  4 ++--
 net/netfilter/ipvs/ip_vs_xmit.c                   | 17 +++++++----------
 19 files changed, 37 insertions(+), 50 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index d465bd7..0a5b770 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_IPXIP4;
 		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_IPXIP4 |
 			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 5a0dca3..72a2eff 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -6311,7 +6311,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_IPXIP4 |
 			   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;
@@ -6321,8 +6321,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_PARTIAL;
+			NETIF_F_GSO_IPXIP4 | NETIF_F_GSO_PARTIAL;
 	dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM |
 				    NETIF_F_GSO_GRE_CSUM;
 	dev->vlan_features = dev->hw_features | NETIF_F_HIGHDMA;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 1cd0ebf..242a1ff 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -9083,8 +9083,7 @@ 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_IPXIP4		|
 				   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 99a524d..0a8122c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -2284,8 +2284,7 @@ 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_IPXIP4 |
 					 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 fd7dae46..2bbbbd0 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
@@ -1559,8 +1559,7 @@ 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_IPXIP4 |
 					 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 642bb45..02d0a1c 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -2230,8 +2230,7 @@ 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_IPXIP4		|
 				   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 2172769..b1a5cdb 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2418,8 +2418,7 @@ 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_IPXIP4 | \
 				  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 322a2d7..79b907f 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -2763,8 +2763,7 @@ 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_IPXIP4 | \
 				    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 9f3677c..69452c3 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9482,8 +9482,7 @@ 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_IPXIP4 | \
 				    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 5e348b1..d86e511 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4062,8 +4062,7 @@ 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_IPXIP4 | \
 				      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 bc87362..aa7b240 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_IPXIP4_BIT,		/* ... IP4 or IP6 over IP4 with TSO */
+	NETIF_F_GSO_IPXIP6_BIT,		/* ... IP4 or IP6 over IP6 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_IPXIP4	__NETIF_F(GSO_IPXIP4)
+#define NETIF_F_GSO_IPXIP6	__NETIF_F(GSO_IPXIP6)
 #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_IPXIP4 |			\
+				 NETIF_F_GSO_IPXIP6 |			\
 				 NETIF_F_GSO_UDP_TUNNEL |		\
 				 NETIF_F_GSO_UDP_TUNNEL_CSUM)
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c148edf..f45929c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4006,8 +4006,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_IPXIP4  != (NETIF_F_GSO_IPXIP4 >> NETIF_F_GSO_SHIFT));
+	BUILD_BUG_ON(SKB_GSO_IPXIP6  != (NETIF_F_GSO_IPXIP6 >> 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 c413c58..65968a9 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_IPXIP4 = 1 << 9,
 
-	SKB_GSO_SIT = 1 << 10,
+	SKB_GSO_IPXIP6 = 1 << 10,
 
 	SKB_GSO_UDP_TUNNEL = 1 << 11,
 
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index bdb4013..f403481 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_IPXIP4_BIT] =	 "tx-ipxip4-segmentation",
+	[NETIF_F_GSO_IPXIP6_BIT] =	 "tx-ipxip6-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 7f08d45..25040b1 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1483,7 +1483,7 @@ 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 |= SKB_GSO_IPXIP4;
 	return inet_gro_complete(skb, nhoff);
 }
 
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 9282748..9783701 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_IPXIP4))
 		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 9ad743b..787e55f 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_IPXIP4 | SKB_GSO_IPXIP6))
 		udpfrag = proto == IPPROTO_UDP && encap;
 	else
 		udpfrag = proto == IPPROTO_UDP && !skb->encapsulation;
@@ -294,7 +294,7 @@ 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 |= SKB_GSO_IPXIP4;
 	return ipv6_gro_complete(skb, nhoff);
 }
 
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index a13d8c1..0a5a255 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_IPXIP4)) {
 		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_IPXIP4))
 		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 6d19d2e..01d3d89 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -932,17 +932,14 @@ 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;
+	switch (encaps_af) {
+	case AF_INET:
+		return SKB_GSO_IPXIP4;
+	case AF_INET6:
+		return SKB_GSO_IPXIP6;
+	default:
+		return 0;
 	}
-
-	/* GSO: we need to provide proper SKB_GSO_ value for IPv6:
-	 * SKB_GSO_SIT/IPV6
-	 */
-	return 0;
 }
 
 /*
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 03/16] ipv6: Fix nexthdr for reinjection
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 01/16] gso: Remove arbitrary checks for unsupported GSO Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 02/16] net: define gso types for IPx over IPv4 and IPv6 Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 04/16] ipv6: Change "final" protocol processing for encapsulation Tom Herbert
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

In ip6_input_finish the nexthdr protocol is retrieved from the
next header offset that is returned in the cb of the skb.
This method does not work for UDP encapsulation that may not
even have a concept of a nexthdr field (e.g. FOU).

This patch checks for a final protocol (INET6_PROTO_FINAL) when a
protocol handler returns > 0. If the protocol is not final then
resubmission is performed on nhoff value. If the protocol is final
then the nexthdr is taken to be the return value.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv6/ip6_input.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index f185cbc..d35dff2 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -236,6 +236,7 @@ resubmit:
 	nhoff = IP6CB(skb)->nhoff;
 	nexthdr = skb_network_header(skb)[nhoff];
 
+resubmit_final:
 	raw = raw6_local_deliver(skb, nexthdr);
 	ipprot = rcu_dereference(inet6_protos[nexthdr]);
 	if (ipprot) {
@@ -263,10 +264,21 @@ resubmit:
 			goto discard;
 
 		ret = ipprot->handler(skb);
-		if (ret > 0)
-			goto resubmit;
-		else if (ret == 0)
+		if (ret > 0) {
+			if (ipprot->flags & INET6_PROTO_FINAL) {
+				/* Not an extension header, most likely UDP
+				 * encapsulation. Use return value as nexthdr
+				 * protocol not nhoff (which presumably is
+				 * not set by handler).
+				 */
+				nexthdr = ret;
+				goto resubmit_final;
+			} else {
+				goto resubmit;
+			}
+		} else if (ret == 0) {
 			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INDELIVERS);
+		}
 	} else {
 		if (!raw) {
 			if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 04/16] ipv6: Change "final" protocol processing for encapsulation
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (2 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 03/16] ipv6: Fix nexthdr for reinjection Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 05/16] net: Cleanup encap items in ip_tunnels.h Tom Herbert
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

When performing foo-over-UDP, UDP packets are processed by the
encapsulation handler which returns another protocol to process.
This may result in processing two (or more) protocols in the
loop that are marked as INET6_PROTO_FINAL. The actions taken
for hitting a final protocol, in particular the skb_postpull_rcsum
can only be performed once.

This patch set adds a check of a final protocol has been seen. The
rules are:
  - If the final protocol has not been seen any protocol is processed
    (final and non-final). In the case of a final protocol, the final
    actions are taken (like the skb_postpull_rcsum)
  - If a final protocol has been seen (e.g. an encapsulating UDP
    header) then no further non-final protocols are allowed
    (e.g. extension headers). For more final protocols the
    final actions are not taken (e.g. skb_postpull_rcsum).

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv6/ip6_input.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index d35dff2..94611e4 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -223,6 +223,7 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk
 	unsigned int nhoff;
 	int nexthdr;
 	bool raw;
+	bool have_final = false;
 
 	/*
 	 *	Parse extension headers
@@ -242,9 +243,21 @@ resubmit_final:
 	if (ipprot) {
 		int ret;
 
-		if (ipprot->flags & INET6_PROTO_FINAL) {
+		if (have_final) {
+			if (!(ipprot->flags & INET6_PROTO_FINAL)) {
+				/* Once we've seen a final protocol don't
+				 * allow encapsulation on any non-final
+				 * ones. This allows foo in UDP encapsulation
+				 * to work.
+				 */
+				goto discard;
+			}
+		} else if (ipprot->flags & INET6_PROTO_FINAL) {
 			const struct ipv6hdr *hdr;
 
+			/* Only do this once for first final protocol */
+			have_final = true;
+
 			/* Free reference early: we don't need it any more,
 			   and it may hold ip_conntrack module loaded
 			   indefinitely. */
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 05/16] net: Cleanup encap items in ip_tunnels.h
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (3 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 04/16] ipv6: Change "final" protocol processing for encapsulation Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 06/16] fou: Call setup_udp_tunnel_sock Tom Herbert
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

Consolidate all the ip_tunnel_encap definitions in one spot in the
header file. Also, move ip_encap_hlen and ip_tunnel_encap from
ip_tunnel.c to ip_tunnels.h so they call be called without a dependency
on ip_tunnel module. Similarly, move iptun_encaps to ip_tunnel_core.c.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 include/net/ip_tunnels.h  | 76 ++++++++++++++++++++++++++++++++++++-----------
 net/ipv4/ip_tunnel.c      | 45 ----------------------------
 net/ipv4/ip_tunnel_core.c |  4 +++
 3 files changed, 62 insertions(+), 63 deletions(-)

diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index d916b43..dbf4444 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -171,22 +171,6 @@ struct ip_tunnel_net {
 	struct ip_tunnel __rcu *collect_md_tun;
 };
 
-struct ip_tunnel_encap_ops {
-	size_t (*encap_hlen)(struct ip_tunnel_encap *e);
-	int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e,
-			    u8 *protocol, struct flowi4 *fl4);
-};
-
-#define MAX_IPTUN_ENCAP_OPS 8
-
-extern const struct ip_tunnel_encap_ops __rcu *
-		iptun_encaps[MAX_IPTUN_ENCAP_OPS];
-
-int ip_tunnel_encap_add_ops(const struct ip_tunnel_encap_ops *op,
-			    unsigned int num);
-int ip_tunnel_encap_del_ops(const struct ip_tunnel_encap_ops *op,
-			    unsigned int num);
-
 static inline void ip_tunnel_key_init(struct ip_tunnel_key *key,
 				      __be32 saddr, __be32 daddr,
 				      u8 tos, u8 ttl, __be32 label,
@@ -251,8 +235,6 @@ void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops);
 void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 		    const struct iphdr *tnl_params, const u8 protocol);
 int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd);
-int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
-		    u8 *protocol, struct flowi4 *fl4);
 int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict);
 int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu);
 
@@ -271,9 +253,67 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
 int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
 		      struct ip_tunnel_parm *p);
 void ip_tunnel_setup(struct net_device *dev, int net_id);
+
+struct ip_tunnel_encap_ops {
+	size_t (*encap_hlen)(struct ip_tunnel_encap *e);
+	int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e,
+			    u8 *protocol, struct flowi4 *fl4);
+};
+
+#define MAX_IPTUN_ENCAP_OPS 8
+
+extern const struct ip_tunnel_encap_ops __rcu *
+		iptun_encaps[MAX_IPTUN_ENCAP_OPS];
+
+int ip_tunnel_encap_add_ops(const struct ip_tunnel_encap_ops *op,
+			    unsigned int num);
+int ip_tunnel_encap_del_ops(const struct ip_tunnel_encap_ops *op,
+			    unsigned int num);
+
 int ip_tunnel_encap_setup(struct ip_tunnel *t,
 			  struct ip_tunnel_encap *ipencap);
 
+static inline int ip_encap_hlen(struct ip_tunnel_encap *e)
+{
+	const struct ip_tunnel_encap_ops *ops;
+	int hlen = -EINVAL;
+
+	if (e->type == TUNNEL_ENCAP_NONE)
+		return 0;
+
+	if (e->type >= MAX_IPTUN_ENCAP_OPS)
+		return -EINVAL;
+
+	rcu_read_lock();
+	ops = rcu_dereference(iptun_encaps[e->type]);
+	if (likely(ops && ops->encap_hlen))
+		hlen = ops->encap_hlen(e);
+	rcu_read_unlock();
+
+	return hlen;
+}
+
+static inline int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
+				  u8 *protocol, struct flowi4 *fl4)
+{
+	const struct ip_tunnel_encap_ops *ops;
+	int ret = -EINVAL;
+
+	if (t->encap.type == TUNNEL_ENCAP_NONE)
+		return 0;
+
+	if (t->encap.type >= MAX_IPTUN_ENCAP_OPS)
+		return -EINVAL;
+
+	rcu_read_lock();
+	ops = rcu_dereference(iptun_encaps[t->encap.type]);
+	if (likely(ops && ops->build_header))
+		ret = ops->build_header(skb, &t->encap, protocol, fl4);
+	rcu_read_unlock();
+
+	return ret;
+}
+
 /* Extract dsfield from inner protocol */
 static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph,
 				       const struct sk_buff *skb)
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index a69ed94..d8f5e0a 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -443,29 +443,6 @@ drop:
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_rcv);
 
-static int ip_encap_hlen(struct ip_tunnel_encap *e)
-{
-	const struct ip_tunnel_encap_ops *ops;
-	int hlen = -EINVAL;
-
-	if (e->type == TUNNEL_ENCAP_NONE)
-		return 0;
-
-	if (e->type >= MAX_IPTUN_ENCAP_OPS)
-		return -EINVAL;
-
-	rcu_read_lock();
-	ops = rcu_dereference(iptun_encaps[e->type]);
-	if (likely(ops && ops->encap_hlen))
-		hlen = ops->encap_hlen(e);
-	rcu_read_unlock();
-
-	return hlen;
-}
-
-const struct ip_tunnel_encap_ops __rcu *
-		iptun_encaps[MAX_IPTUN_ENCAP_OPS] __read_mostly;
-
 int ip_tunnel_encap_add_ops(const struct ip_tunnel_encap_ops *ops,
 			    unsigned int num)
 {
@@ -519,28 +496,6 @@ int ip_tunnel_encap_setup(struct ip_tunnel *t,
 }
 EXPORT_SYMBOL_GPL(ip_tunnel_encap_setup);
 
-int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
-		    u8 *protocol, struct flowi4 *fl4)
-{
-	const struct ip_tunnel_encap_ops *ops;
-	int ret = -EINVAL;
-
-	if (t->encap.type == TUNNEL_ENCAP_NONE)
-		return 0;
-
-	if (t->encap.type >= MAX_IPTUN_ENCAP_OPS)
-		return -EINVAL;
-
-	rcu_read_lock();
-	ops = rcu_dereference(iptun_encaps[t->encap.type]);
-	if (likely(ops && ops->build_header))
-		ret = ops->build_header(skb, &t->encap, protocol, fl4);
-	rcu_read_unlock();
-
-	return ret;
-}
-EXPORT_SYMBOL(ip_tunnel_encap);
-
 static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
 			    struct rtable *rt, __be16 df,
 			    const struct iphdr *inner_iph)
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index 9118b0e..cc66a20 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -47,6 +47,10 @@
 #include <net/rtnetlink.h>
 #include <net/dst_metadata.h>
 
+const struct ip_tunnel_encap_ops __rcu *
+		iptun_encaps[MAX_IPTUN_ENCAP_OPS] __read_mostly;
+EXPORT_SYMBOL(iptun_encaps);
+
 void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
 		   __be32 src, __be32 dst, __u8 proto,
 		   __u8 tos, __u8 ttl, __be16 df, bool xnet)
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 06/16] fou: Call setup_udp_tunnel_sock
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (4 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 05/16] net: Cleanup encap items in ip_tunnels.h Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 07/16] fou: Split out {fou,gue}_build_header Tom Herbert
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

Use helper function to set up UDP tunnel related information for a fou
socket.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv4/fou.c | 50 ++++++++++++++++----------------------------------
 1 file changed, 16 insertions(+), 34 deletions(-)

diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index eeec7d6..6cbc725 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -448,31 +448,13 @@ static void fou_release(struct fou *fou)
 	kfree_rcu(fou, rcu);
 }
 
-static int fou_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg)
-{
-	udp_sk(sk)->encap_rcv = fou_udp_recv;
-	udp_sk(sk)->gro_receive = fou_gro_receive;
-	udp_sk(sk)->gro_complete = fou_gro_complete;
-	fou_from_sock(sk)->protocol = cfg->protocol;
-
-	return 0;
-}
-
-static int gue_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg)
-{
-	udp_sk(sk)->encap_rcv = gue_udp_recv;
-	udp_sk(sk)->gro_receive = gue_gro_receive;
-	udp_sk(sk)->gro_complete = gue_gro_complete;
-
-	return 0;
-}
-
 static int fou_create(struct net *net, struct fou_cfg *cfg,
 		      struct socket **sockp)
 {
 	struct socket *sock = NULL;
 	struct fou *fou = NULL;
 	struct sock *sk;
+	struct udp_tunnel_sock_cfg tunnel_cfg;
 	int err;
 
 	/* Open UDP socket */
@@ -491,33 +473,33 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
 
 	fou->flags = cfg->flags;
 	fou->port = cfg->udp_config.local_udp_port;
+	fou->type = cfg->type;
+	fou->sock = sock;
+
+	memset(&tunnel_cfg, 0, sizeof(tunnel_cfg));
+	tunnel_cfg.encap_type = 1;
+	tunnel_cfg.sk_user_data = fou;
+	tunnel_cfg.encap_destroy = NULL;
 
 	/* Initial for fou type */
 	switch (cfg->type) {
 	case FOU_ENCAP_DIRECT:
-		err = fou_encap_init(sk, fou, cfg);
-		if (err)
-			goto error;
+		tunnel_cfg.encap_rcv = fou_udp_recv;
+		tunnel_cfg.gro_receive = fou_gro_receive;
+		tunnel_cfg.gro_complete = fou_gro_complete;
+		fou->protocol = cfg->protocol;
 		break;
 	case FOU_ENCAP_GUE:
-		err = gue_encap_init(sk, fou, cfg);
-		if (err)
-			goto error;
+		tunnel_cfg.encap_rcv = gue_udp_recv;
+		tunnel_cfg.gro_receive = gue_gro_receive;
+		tunnel_cfg.gro_complete = gue_gro_complete;
 		break;
 	default:
 		err = -EINVAL;
 		goto error;
 	}
 
-	fou->type = cfg->type;
-
-	udp_sk(sk)->encap_type = 1;
-	udp_encap_enable();
-
-	sk->sk_user_data = fou;
-	fou->sock = sock;
-
-	inet_inc_convert_csum(sk);
+	setup_udp_tunnel_sock(net, sock, &tunnel_cfg);
 
 	sk->sk_allocation = GFP_ATOMIC;
 
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 07/16] fou: Split out {fou,gue}_build_header
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (5 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 06/16] fou: Call setup_udp_tunnel_sock Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 08/16] fou: Support IPv6 in fou Tom Herbert
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

Create __fou_build_header and __gue_build_header. These implement the
protocol generic parts of building the fou and gue header.
fou_build_header and gue_build_header implement the IPv4 specific
functions and call the __*_build_header functions.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 include/net/fou.h |  8 ++++----
 net/ipv4/fou.c    | 47 +++++++++++++++++++++++++++++++++++++----------
 2 files changed, 41 insertions(+), 14 deletions(-)

diff --git a/include/net/fou.h b/include/net/fou.h
index 19b8a0c..7d2fda2 100644
--- a/include/net/fou.h
+++ b/include/net/fou.h
@@ -11,9 +11,9 @@
 size_t fou_encap_hlen(struct ip_tunnel_encap *e);
 static size_t gue_encap_hlen(struct ip_tunnel_encap *e);
 
-int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
-		     u8 *protocol, struct flowi4 *fl4);
-int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
-		     u8 *protocol, struct flowi4 *fl4);
+int __fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
+		       u8 *protocol, __be16 *sport, int type);
+int __gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
+		       u8 *protocol, __be16 *sport, int type);
 
 #endif
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index 6cbc725..f4f2ddd 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -780,6 +780,22 @@ static void fou_build_udp(struct sk_buff *skb, struct ip_tunnel_encap *e,
 	*protocol = IPPROTO_UDP;
 }
 
+int __fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
+		       u8 *protocol, __be16 *sport, int type)
+{
+	int err;
+
+	err = iptunnel_handle_offloads(skb, type);
+	if (err)
+		return err;
+
+	*sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
+						skb, 0, 0, false);
+
+	return 0;
+}
+EXPORT_SYMBOL(__fou_build_header);
+
 int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
 		     u8 *protocol, struct flowi4 *fl4)
 {
@@ -788,26 +804,21 @@ int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
 	__be16 sport;
 	int err;
 
-	err = iptunnel_handle_offloads(skb, type);
+	err = __fou_build_header(skb, e, protocol, &sport, type);
 	if (err)
 		return err;
 
-	sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
-					       skb, 0, 0, false);
 	fou_build_udp(skb, e, fl4, protocol, sport);
 
 	return 0;
 }
 EXPORT_SYMBOL(fou_build_header);
 
-int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
-		     u8 *protocol, struct flowi4 *fl4)
+int __gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
+		       u8 *protocol, __be16 *sport, int type)
 {
-	int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM ? SKB_GSO_UDP_TUNNEL_CSUM :
-						       SKB_GSO_UDP_TUNNEL;
 	struct guehdr *guehdr;
 	size_t hdrlen, optlen = 0;
-	__be16 sport;
 	void *data;
 	bool need_priv = false;
 	int err;
@@ -826,8 +837,8 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
 		return err;
 
 	/* Get source port (based on flow hash) before skb_push */
-	sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
-					       skb, 0, 0, false);
+	*sport = e->sport ? : udp_flow_src_port(dev_net(skb->dev),
+						skb, 0, 0, false);
 
 	hdrlen = sizeof(struct guehdr) + optlen;
 
@@ -872,6 +883,22 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
 
 	}
 
+	return 0;
+}
+EXPORT_SYMBOL(__gue_build_header);
+
+int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
+		     u8 *protocol, struct flowi4 *fl4)
+{
+	int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM ? SKB_GSO_UDP_TUNNEL_CSUM :
+						       SKB_GSO_UDP_TUNNEL;
+	__be16 sport;
+	int err;
+
+	err = __gue_build_header(skb, e, protocol, &sport, type);
+	if (err)
+		return err;
+
 	fou_build_udp(skb, e, fl4, protocol, sport);
 
 	return 0;
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 08/16] fou: Support IPv6 in fou
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (6 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 07/16] fou: Split out {fou,gue}_build_header Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 09/16] ip6_tun: Add infrastructure for doing encapsulation Tom Herbert
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

This patch adds receive path support for IPv6 with fou.

- Add address family to fou structure for open sockets. This supports
  AF_INET and AF_INET6. Lookups for fou ports are performed on both the
  port number and family.
- In fou and gue receive adjust tot_len in IPv4 header or payload_len
  based on address family.
- Allow AF_INET6 in FOU_ATTR_AF netlink attribute.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv4/fou.c | 47 +++++++++++++++++++++++++++++++++++------------
 1 file changed, 35 insertions(+), 12 deletions(-)

diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index f4f2ddd..5f9207c 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -21,6 +21,7 @@ struct fou {
 	u8 protocol;
 	u8 flags;
 	__be16 port;
+	u8 family;
 	u16 type;
 	struct list_head list;
 	struct rcu_head rcu;
@@ -47,14 +48,17 @@ static inline struct fou *fou_from_sock(struct sock *sk)
 	return sk->sk_user_data;
 }
 
-static int fou_recv_pull(struct sk_buff *skb, size_t len)
+static int fou_recv_pull(struct sk_buff *skb, struct fou *fou, size_t len)
 {
-	struct iphdr *iph = ip_hdr(skb);
-
 	/* Remove 'len' bytes from the packet (UDP header and
 	 * FOU header if present).
 	 */
-	iph->tot_len = htons(ntohs(iph->tot_len) - len);
+	if (fou->family == AF_INET)
+		ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(skb)->tot_len) - len);
+	else
+		ipv6_hdr(skb)->payload_len =
+		    htons(ntohs(ipv6_hdr(skb)->payload_len) - len);
+
 	__skb_pull(skb, len);
 	skb_postpull_rcsum(skb, udp_hdr(skb), len);
 	skb_reset_transport_header(skb);
@@ -68,7 +72,7 @@ static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
 	if (!fou)
 		return 1;
 
-	if (fou_recv_pull(skb, sizeof(struct udphdr)))
+	if (fou_recv_pull(skb, fou, sizeof(struct udphdr)))
 		goto drop;
 
 	return -fou->protocol;
@@ -141,7 +145,11 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb)
 
 	hdrlen = sizeof(struct guehdr) + optlen;
 
-	ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(skb)->tot_len) - len);
+	if (fou->family == AF_INET)
+		ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(skb)->tot_len) - len);
+	else
+		ipv6_hdr(skb)->payload_len =
+		    htons(ntohs(ipv6_hdr(skb)->payload_len) - len);
 
 	/* Pull csum through the guehdr now . This can be used if
 	 * there is a remote checksum offload.
@@ -426,7 +434,8 @@ static int fou_add_to_port_list(struct net *net, struct fou *fou)
 
 	mutex_lock(&fn->fou_lock);
 	list_for_each_entry(fout, &fn->fou_list, list) {
-		if (fou->port == fout->port) {
+		if (fou->port == fout->port &&
+		    fou->family == fout->family) {
 			mutex_unlock(&fn->fou_lock);
 			return -EALREADY;
 		}
@@ -471,8 +480,9 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
 
 	sk = sock->sk;
 
-	fou->flags = cfg->flags;
 	fou->port = cfg->udp_config.local_udp_port;
+	fou->family = cfg->udp_config.family;
+	fou->flags = cfg->flags;
 	fou->type = cfg->type;
 	fou->sock = sock;
 
@@ -524,12 +534,13 @@ static int fou_destroy(struct net *net, struct fou_cfg *cfg)
 {
 	struct fou_net *fn = net_generic(net, fou_net_id);
 	__be16 port = cfg->udp_config.local_udp_port;
+	u8 family = cfg->udp_config.family;
 	int err = -EINVAL;
 	struct fou *fou;
 
 	mutex_lock(&fn->fou_lock);
 	list_for_each_entry(fou, &fn->fou_list, list) {
-		if (fou->port == port) {
+		if (fou->port == port && fou->family == family) {
 			fou_release(fou);
 			err = 0;
 			break;
@@ -567,8 +578,15 @@ static int parse_nl_config(struct genl_info *info,
 	if (info->attrs[FOU_ATTR_AF]) {
 		u8 family = nla_get_u8(info->attrs[FOU_ATTR_AF]);
 
-		if (family != AF_INET)
-			return -EINVAL;
+		switch (family) {
+		case AF_INET:
+			break;
+		case AF_INET6:
+			cfg->udp_config.ipv6_v6only = 1;
+			break;
+		default:
+			return -EAFNOSUPPORT;
+		}
 
 		cfg->udp_config.family = family;
 	}
@@ -659,6 +677,7 @@ static int fou_nl_cmd_get_port(struct sk_buff *skb, struct genl_info *info)
 	struct fou_cfg cfg;
 	struct fou *fout;
 	__be16 port;
+	u8 family;
 	int ret;
 
 	ret = parse_nl_config(info, &cfg);
@@ -668,6 +687,10 @@ static int fou_nl_cmd_get_port(struct sk_buff *skb, struct genl_info *info)
 	if (port == 0)
 		return -EINVAL;
 
+	family = cfg.udp_config.family;
+	if (family != AF_INET && family != AF_INET6)
+		return -EINVAL;
+
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 	if (!msg)
 		return -ENOMEM;
@@ -675,7 +698,7 @@ static int fou_nl_cmd_get_port(struct sk_buff *skb, struct genl_info *info)
 	ret = -ESRCH;
 	mutex_lock(&fn->fou_lock);
 	list_for_each_entry(fout, &fn->fou_list, list) {
-		if (port == fout->port) {
+		if (port == fout->port && family == fout->family) {
 			ret = fou_dump_info(fout, info->snd_portid,
 					    info->snd_seq, 0, msg,
 					    info->genlhdr->cmd);
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 09/16] ip6_tun: Add infrastructure for doing encapsulation
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (7 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 08/16] fou: Support IPv6 in fou Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 10/16] fou: Add encap ops for IPv6 tunnels Tom Herbert
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

Add encap_hlen and ip_tunnel_encap structure to ip6_tnl. Add functions
for getting encap hlen, setting up encap on a tunnel, performing
encapsulation operation.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 include/net/ip6_tunnel.h  | 58 +++++++++++++++++++++++++++++
 net/ipv4/ip_tunnel_core.c |  5 +++
 net/ipv6/ip6_tunnel.c     | 94 ++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 144 insertions(+), 13 deletions(-)

diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index fb9e015..d325c81 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -52,10 +52,68 @@ struct ip6_tnl {
 	__u32 o_seqno;	/* The last output seqno */
 	int hlen;       /* tun_hlen + encap_hlen */
 	int tun_hlen;	/* Precalculated header length */
+	int encap_hlen; /* Encap header length (FOU,GUE) */
+	struct ip_tunnel_encap encap;
 	int mlink;
+};
 
+struct ip6_tnl_encap_ops {
+	size_t (*encap_hlen)(struct ip_tunnel_encap *e);
+	int (*build_header)(struct sk_buff *skb, struct ip_tunnel_encap *e,
+			    u8 *protocol, struct flowi6 *fl6);
 };
 
+extern const struct ip6_tnl_encap_ops __rcu *
+		ip6tun_encaps[MAX_IPTUN_ENCAP_OPS];
+
+int ip6_tnl_encap_add_ops(const struct ip6_tnl_encap_ops *ops,
+			  unsigned int num);
+int ip6_tnl_encap_del_ops(const struct ip6_tnl_encap_ops *ops,
+			  unsigned int num);
+int ip6_tnl_encap_setup(struct ip6_tnl *t,
+			struct ip_tunnel_encap *ipencap);
+
+static inline int ip6_encap_hlen(struct ip_tunnel_encap *e)
+{
+	const struct ip6_tnl_encap_ops *ops;
+	int hlen = -EINVAL;
+
+	if (e->type == TUNNEL_ENCAP_NONE)
+		return 0;
+
+	if (e->type >= MAX_IPTUN_ENCAP_OPS)
+		return -EINVAL;
+
+	rcu_read_lock();
+	ops = rcu_dereference(ip6tun_encaps[e->type]);
+	if (likely(ops && ops->encap_hlen))
+		hlen = ops->encap_hlen(e);
+	rcu_read_unlock();
+
+	return hlen;
+}
+
+static inline int ip6_tnl_encap(struct sk_buff *skb, struct ip6_tnl *t,
+				u8 *protocol, struct flowi6 *fl6)
+{
+	const struct ip6_tnl_encap_ops *ops;
+	int ret = -EINVAL;
+
+	if (t->encap.type == TUNNEL_ENCAP_NONE)
+		return 0;
+
+	if (t->encap.type >= MAX_IPTUN_ENCAP_OPS)
+		return -EINVAL;
+
+	rcu_read_lock();
+	ops = rcu_dereference(ip6tun_encaps[t->encap.type]);
+	if (likely(ops && ops->build_header))
+		ret = ops->build_header(skb, &t->encap, protocol, fl6);
+	rcu_read_unlock();
+
+	return ret;
+}
+
 /* Tunnel encapsulation limit destination sub-option */
 
 struct ipv6_tlv_tnl_enc_lim {
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index cc66a20..afd6b59 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -37,6 +37,7 @@
 #include <net/icmp.h>
 #include <net/protocol.h>
 #include <net/ip_tunnels.h>
+#include <net/ip6_tunnel.h>
 #include <net/arp.h>
 #include <net/checksum.h>
 #include <net/dsfield.h>
@@ -51,6 +52,10 @@ const struct ip_tunnel_encap_ops __rcu *
 		iptun_encaps[MAX_IPTUN_ENCAP_OPS] __read_mostly;
 EXPORT_SYMBOL(iptun_encaps);
 
+const struct ip6_tnl_encap_ops __rcu *
+		ip6tun_encaps[MAX_IPTUN_ENCAP_OPS] __read_mostly;
+EXPORT_SYMBOL(ip6tun_encaps);
+
 void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
 		   __be32 src, __be32 dst, __u8 proto,
 		   __u8 tos, __u8 ttl, __be16 df, bool xnet)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index e79330f..64ddbeac 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1010,7 +1010,8 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 	struct dst_entry *dst = NULL, *ndst = NULL;
 	struct net_device *tdev;
 	int mtu;
-	unsigned int max_headroom = sizeof(struct ipv6hdr);
+	unsigned int psh_hlen = sizeof(struct ipv6hdr) + t->encap_hlen;
+	unsigned int max_headroom = psh_hlen;
 	int err = -1;
 
 	/* NBMA tunnel */
@@ -1063,7 +1064,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 				     t->parms.name);
 		goto tx_err_dst_release;
 	}
-	mtu = dst_mtu(dst) - sizeof(*ipv6h);
+	mtu = dst_mtu(dst) - psh_hlen;
 	if (encap_limit >= 0) {
 		max_headroom += 8;
 		mtu -= 8;
@@ -1124,11 +1125,18 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 		skb->encapsulation = 1;
 	}
 
+	/* Calculate max headroom for all the headers and adjust
+	 * needed_headroom if necessary.
+	 */
 	max_headroom = LL_RESERVED_SPACE(dst->dev) + sizeof(struct ipv6hdr)
-			+ dst->header_len;
+			+ dst->header_len + t->hlen;
 	if (max_headroom > dev->needed_headroom)
 		dev->needed_headroom = max_headroom;
 
+	err = ip6_tnl_encap(skb, t, &proto, fl6);
+	if (err)
+		return err;
+
 	skb_push(skb, sizeof(struct ipv6hdr));
 	skb_reset_network_header(skb);
 	ipv6h = ipv6_hdr(skb);
@@ -1280,6 +1288,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
 	struct net_device *dev = t->dev;
 	struct __ip6_tnl_parm *p = &t->parms;
 	struct flowi6 *fl6 = &t->fl.u.ip6;
+	int t_hlen;
 
 	memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr));
 	memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr));
@@ -1303,6 +1312,10 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
 	else
 		dev->flags &= ~IFF_POINTOPOINT;
 
+	t->tun_hlen = 0;
+	t->hlen = t->encap_hlen + t->tun_hlen;
+	t_hlen = t->hlen + sizeof(struct ipv6hdr);
+
 	if (p->flags & IP6_TNL_F_CAP_XMIT) {
 		int strict = (ipv6_addr_type(&p->raddr) &
 			      (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL));
@@ -1316,9 +1329,9 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
 
 		if (rt->dst.dev) {
 			dev->hard_header_len = rt->dst.dev->hard_header_len +
-				sizeof(struct ipv6hdr);
+				t_hlen;
 
-			dev->mtu = rt->dst.dev->mtu - sizeof(struct ipv6hdr);
+			dev->mtu = rt->dst.dev->mtu - t_hlen;
 			if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
 				dev->mtu -= 8;
 
@@ -1564,6 +1577,59 @@ int ip6_tnl_get_iflink(const struct net_device *dev)
 }
 EXPORT_SYMBOL(ip6_tnl_get_iflink);
 
+int ip6_tnl_encap_add_ops(const struct ip6_tnl_encap_ops *ops,
+			  unsigned int num)
+{
+	if (num >= MAX_IPTUN_ENCAP_OPS)
+		return -ERANGE;
+
+	return !cmpxchg((const struct ip6_tnl_encap_ops **)
+			&ip6tun_encaps[num],
+			NULL, ops) ? 0 : -1;
+}
+EXPORT_SYMBOL(ip6_tnl_encap_add_ops);
+
+int ip6_tnl_encap_del_ops(const struct ip6_tnl_encap_ops *ops,
+			  unsigned int num)
+{
+	int ret;
+
+	if (num >= MAX_IPTUN_ENCAP_OPS)
+		return -ERANGE;
+
+	ret = (cmpxchg((const struct ip6_tnl_encap_ops **)
+		       &ip6tun_encaps[num],
+		       ops, NULL) == ops) ? 0 : -1;
+
+	synchronize_net();
+
+	return ret;
+}
+EXPORT_SYMBOL(ip6_tnl_encap_del_ops);
+
+int ip6_tnl_encap_setup(struct ip6_tnl *t,
+			struct ip_tunnel_encap *ipencap)
+{
+	int hlen;
+
+	memset(&t->encap, 0, sizeof(t->encap));
+
+	hlen = ip6_encap_hlen(ipencap);
+	if (hlen < 0)
+		return hlen;
+
+	t->encap.type = ipencap->type;
+	t->encap.sport = ipencap->sport;
+	t->encap.dport = ipencap->dport;
+	t->encap.flags = ipencap->flags;
+
+	t->encap_hlen = hlen;
+	t->hlen = t->encap_hlen + t->tun_hlen;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ip6_tnl_encap_setup);
+
 static const struct net_device_ops ip6_tnl_netdev_ops = {
 	.ndo_init	= ip6_tnl_dev_init,
 	.ndo_uninit	= ip6_tnl_dev_uninit,
@@ -1585,19 +1651,13 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
 
 static void ip6_tnl_dev_setup(struct net_device *dev)
 {
-	struct ip6_tnl *t;
-
 	dev->netdev_ops = &ip6_tnl_netdev_ops;
 	dev->destructor = ip6_dev_free;
 
 	dev->type = ARPHRD_TUNNEL6;
-	dev->hard_header_len = LL_MAX_HEADER + sizeof(struct ipv6hdr);
-	dev->mtu = ETH_DATA_LEN - sizeof(struct ipv6hdr);
-	t = netdev_priv(dev);
-	if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
-		dev->mtu -= 8;
 	dev->flags |= IFF_NOARP;
 	dev->addr_len = sizeof(struct in6_addr);
+	dev->features |= NETIF_F_LLTX;
 	netif_keep_dst(dev);
 	/* This perm addr will be used as interface identifier by IPv6 */
 	dev->addr_assign_type = NET_ADDR_RANDOM;
@@ -1615,6 +1675,7 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
 {
 	struct ip6_tnl *t = netdev_priv(dev);
 	int ret;
+	int t_hlen;
 
 	t->dev = dev;
 	t->net = dev_net(dev);
@@ -1630,8 +1691,15 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
 	if (ret)
 		goto destroy_dst;
 
-	t->hlen = 0;
 	t->tun_hlen = 0;
+	t->hlen = t->encap_hlen + t->tun_hlen;
+	t_hlen = t->hlen + sizeof(struct ipv6hdr);
+
+	dev->type = ARPHRD_TUNNEL6;
+	dev->hard_header_len = LL_MAX_HEADER + t_hlen;
+	dev->mtu = ETH_DATA_LEN - t_hlen;
+	if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
+		dev->mtu -= 8;
 
 	return 0;
 
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 10/16] fou: Add encap ops for IPv6 tunnels
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (8 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 09/16] ip6_tun: Add infrastructure for doing encapsulation Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 11/16] ip6_gre: Add support for fou/gue encapsulation Tom Herbert
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

This patch add a new fou6 module that provides encapsulation
operations for IPv6.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 include/net/fou.h |   2 +-
 net/ipv6/Makefile |   1 +
 net/ipv6/fou6.c   | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 142 insertions(+), 1 deletion(-)
 create mode 100644 net/ipv6/fou6.c

diff --git a/include/net/fou.h b/include/net/fou.h
index 7d2fda2..f5cc691 100644
--- a/include/net/fou.h
+++ b/include/net/fou.h
@@ -9,7 +9,7 @@
 #include <net/udp.h>
 
 size_t fou_encap_hlen(struct ip_tunnel_encap *e);
-static size_t gue_encap_hlen(struct ip_tunnel_encap *e);
+size_t gue_encap_hlen(struct ip_tunnel_encap *e);
 
 int __fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
 		       u8 *protocol, __be16 *sport, int type);
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 5e9d6bf..7ec3129 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_IPV6_VTI) += ip6_vti.o
 obj-$(CONFIG_IPV6_SIT) += sit.o
 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
 obj-$(CONFIG_IPV6_GRE) += ip6_gre.o
+obj-$(CONFIG_NET_FOU) += fou6.o
 
 obj-y += addrconf_core.o exthdrs_core.o ip6_checksum.o ip6_icmp.o
 obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload)
diff --git a/net/ipv6/fou6.c b/net/ipv6/fou6.c
new file mode 100644
index 0000000..c972d0b
--- /dev/null
+++ b/net/ipv6/fou6.c
@@ -0,0 +1,140 @@
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/socket.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <net/fou.h>
+#include <net/ip.h>
+#include <net/ip6_tunnel.h>
+#include <net/ip6_checksum.h>
+#include <net/protocol.h>
+#include <net/udp.h>
+#include <net/udp_tunnel.h>
+
+static void fou6_build_udp(struct sk_buff *skb, struct ip_tunnel_encap *e,
+			   struct flowi6 *fl6, u8 *protocol, __be16 sport)
+{
+	struct udphdr *uh;
+
+	skb_push(skb, sizeof(struct udphdr));
+	skb_reset_transport_header(skb);
+
+	uh = udp_hdr(skb);
+
+	uh->dest = e->dport;
+	uh->source = sport;
+	uh->len = htons(skb->len);
+	udp6_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM6), skb,
+		      &fl6->saddr, &fl6->daddr, skb->len);
+
+	*protocol = IPPROTO_UDP;
+}
+
+int fou6_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
+		      u8 *protocol, struct flowi6 *fl6)
+{
+	__be16 sport;
+	int err;
+	int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM6 ?
+		SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
+
+	err = __fou_build_header(skb, e, protocol, &sport, type);
+	if (err)
+		return err;
+
+	fou6_build_udp(skb, e, fl6, protocol, sport);
+
+	return 0;
+}
+EXPORT_SYMBOL(fou6_build_header);
+
+int gue6_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
+		      u8 *protocol, struct flowi6 *fl6)
+{
+	__be16 sport;
+	int err;
+	int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM6 ?
+		SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
+
+	err = __gue_build_header(skb, e, protocol, &sport, type);
+	if (err)
+		return err;
+
+	fou6_build_udp(skb, e, fl6, protocol, sport);
+
+	return 0;
+}
+EXPORT_SYMBOL(gue6_build_header);
+
+#ifdef CONFIG_NET_FOU_IP_TUNNELS
+
+static const struct ip6_tnl_encap_ops fou_ip6tun_ops = {
+	.encap_hlen = fou_encap_hlen,
+	.build_header = fou6_build_header,
+};
+
+static const struct ip6_tnl_encap_ops gue_ip6tun_ops = {
+	.encap_hlen = gue_encap_hlen,
+	.build_header = gue6_build_header,
+};
+
+static int ip6_tnl_encap_add_fou_ops(void)
+{
+	int ret;
+
+	ret = ip6_tnl_encap_add_ops(&fou_ip6tun_ops, TUNNEL_ENCAP_FOU);
+	if (ret < 0) {
+		pr_err("can't add fou6 ops\n");
+		return ret;
+	}
+
+	ret = ip6_tnl_encap_add_ops(&gue_ip6tun_ops, TUNNEL_ENCAP_GUE);
+	if (ret < 0) {
+		pr_err("can't add gue6 ops\n");
+		ip6_tnl_encap_del_ops(&fou_ip6tun_ops, TUNNEL_ENCAP_FOU);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void ip6_tnl_encap_del_fou_ops(void)
+{
+	ip6_tnl_encap_del_ops(&fou_ip6tun_ops, TUNNEL_ENCAP_FOU);
+	ip6_tnl_encap_del_ops(&gue_ip6tun_ops, TUNNEL_ENCAP_GUE);
+}
+
+#else
+
+static int ip6_tnl_encap_add_fou_ops(void)
+{
+	return 0;
+}
+
+static void ip6_tnl_encap_del_fou_ops(void)
+{
+}
+
+#endif
+
+static int __init fou6_init(void)
+{
+	int ret;
+
+	ret = ip6_tnl_encap_add_fou_ops();
+
+	return ret;
+}
+
+static void __exit fou6_fini(void)
+{
+	ip6_tnl_encap_del_fou_ops();
+}
+
+module_init(fou6_init);
+module_exit(fou6_fini);
+MODULE_AUTHOR("Tom Herbert <therbert@google.com>");
+MODULE_LICENSE("GPL");
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 11/16] ip6_gre: Add support for fou/gue encapsulation
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (9 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 10/16] fou: Add encap ops for IPv6 tunnels Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 12/16] ip6_tunnel: " Tom Herbert
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

Add netlink and setup for encapsulation

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv6/ip6_gre.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 75 insertions(+), 4 deletions(-)

diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 4541fa5..6fb1b89 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -729,7 +729,7 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu)
 
 	t->tun_hlen = gre_calc_hlen(t->parms.o_flags);
 
-	t->hlen = t->tun_hlen;
+	t->hlen = t->encap_hlen + t->tun_hlen;
 
 	t_hlen = t->hlen + sizeof(struct ipv6hdr);
 
@@ -1022,9 +1022,7 @@ static int ip6gre_tunnel_init_common(struct net_device *dev)
 	}
 
 	tunnel->tun_hlen = gre_calc_hlen(tunnel->parms.o_flags);
-
-	tunnel->hlen = tunnel->tun_hlen;
-
+	tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
 	t_hlen = tunnel->hlen + sizeof(struct ipv6hdr);
 
 	dev->hard_header_len = LL_MAX_HEADER + t_hlen;
@@ -1290,15 +1288,57 @@ static void ip6gre_tap_setup(struct net_device *dev)
 	dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 }
 
+static bool ip6gre_netlink_encap_parms(struct nlattr *data[],
+				       struct ip_tunnel_encap *ipencap)
+{
+	bool ret = false;
+
+	memset(ipencap, 0, sizeof(*ipencap));
+
+	if (!data)
+		return ret;
+
+	if (data[IFLA_GRE_ENCAP_TYPE]) {
+		ret = true;
+		ipencap->type = nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]);
+	}
+
+	if (data[IFLA_GRE_ENCAP_FLAGS]) {
+		ret = true;
+		ipencap->flags = nla_get_u16(data[IFLA_GRE_ENCAP_FLAGS]);
+	}
+
+	if (data[IFLA_GRE_ENCAP_SPORT]) {
+		ret = true;
+		ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
+	}
+
+	if (data[IFLA_GRE_ENCAP_DPORT]) {
+		ret = true;
+		ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
+	}
+
+	return ret;
+}
+
 static int ip6gre_newlink(struct net *src_net, struct net_device *dev,
 	struct nlattr *tb[], struct nlattr *data[])
 {
 	struct ip6_tnl *nt;
 	struct net *net = dev_net(dev);
 	struct ip6gre_net *ign = net_generic(net, ip6gre_net_id);
+	struct ip_tunnel_encap ipencap;
 	int err;
 
 	nt = netdev_priv(dev);
+
+	if (ip6gre_netlink_encap_parms(data, &ipencap)) {
+		int err = ip6_tnl_encap_setup(nt, &ipencap);
+
+		if (err < 0)
+			return err;
+	}
+
 	ip6gre_netlink_parms(data, &nt->parms);
 
 	if (ip6gre_tunnel_find(net, &nt->parms, dev->type))
@@ -1345,10 +1385,18 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[],
 	struct net *net = nt->net;
 	struct ip6gre_net *ign = net_generic(net, ip6gre_net_id);
 	struct __ip6_tnl_parm p;
+	struct ip_tunnel_encap ipencap;
 
 	if (dev == ign->fb_tunnel_dev)
 		return -EINVAL;
 
+	if (ip6gre_netlink_encap_parms(data, &ipencap)) {
+		int err = ip6_tnl_encap_setup(nt, &ipencap);
+
+		if (err < 0)
+			return err;
+	}
+
 	ip6gre_netlink_parms(data, &p);
 
 	t = ip6gre_tunnel_locate(net, &p, 0);
@@ -1400,6 +1448,14 @@ static size_t ip6gre_get_size(const struct net_device *dev)
 		nla_total_size(4) +
 		/* IFLA_GRE_FLAGS */
 		nla_total_size(4) +
+		/* IFLA_GRE_ENCAP_TYPE */
+		nla_total_size(2) +
+		/* IFLA_GRE_ENCAP_FLAGS */
+		nla_total_size(2) +
+		/* IFLA_GRE_ENCAP_SPORT */
+		nla_total_size(2) +
+		/* IFLA_GRE_ENCAP_DPORT */
+		nla_total_size(2) +
 		0;
 }
 
@@ -1422,6 +1478,17 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	    nla_put_be32(skb, IFLA_GRE_FLOWINFO, p->flowinfo) ||
 	    nla_put_u32(skb, IFLA_GRE_FLAGS, p->flags))
 		goto nla_put_failure;
+
+	if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
+			t->encap.type) ||
+	    nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
+			 t->encap.sport) ||
+	    nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
+			 t->encap.dport) ||
+	    nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
+			t->encap.flags))
+		goto nla_put_failure;
+
 	return 0;
 
 nla_put_failure:
@@ -1440,6 +1507,10 @@ static const struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = {
 	[IFLA_GRE_ENCAP_LIMIT] = { .type = NLA_U8 },
 	[IFLA_GRE_FLOWINFO]    = { .type = NLA_U32 },
 	[IFLA_GRE_FLAGS]       = { .type = NLA_U32 },
+	[IFLA_GRE_ENCAP_TYPE]   = { .type = NLA_U16 },
+	[IFLA_GRE_ENCAP_FLAGS]  = { .type = NLA_U16 },
+	[IFLA_GRE_ENCAP_SPORT]  = { .type = NLA_U16 },
+	[IFLA_GRE_ENCAP_DPORT]  = { .type = NLA_U16 },
 };
 
 static struct rtnl_link_ops ip6gre_link_ops __read_mostly = {
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 12/16] ip6_tunnel: Add support for fou/gue encapsulation
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (10 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 11/16] ip6_gre: Add support for fou/gue encapsulation Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 13/16] ipv6: Set features for IPv6 tunnels Tom Herbert
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

Add netlink and setup for encapsulation

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv6/ip6_tunnel.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 64ddbeac..74b35e4 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1797,13 +1797,55 @@ static void ip6_tnl_netlink_parms(struct nlattr *data[],
 		parms->proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
 }
 
+static bool ip6_tnl_netlink_encap_parms(struct nlattr *data[],
+					struct ip_tunnel_encap *ipencap)
+{
+	bool ret = false;
+
+	memset(ipencap, 0, sizeof(*ipencap));
+
+	if (!data)
+		return ret;
+
+	if (data[IFLA_IPTUN_ENCAP_TYPE]) {
+		ret = true;
+		ipencap->type = nla_get_u16(data[IFLA_IPTUN_ENCAP_TYPE]);
+	}
+
+	if (data[IFLA_IPTUN_ENCAP_FLAGS]) {
+		ret = true;
+		ipencap->flags = nla_get_u16(data[IFLA_IPTUN_ENCAP_FLAGS]);
+	}
+
+	if (data[IFLA_IPTUN_ENCAP_SPORT]) {
+		ret = true;
+		ipencap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]);
+	}
+
+	if (data[IFLA_IPTUN_ENCAP_DPORT]) {
+		ret = true;
+		ipencap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]);
+	}
+
+	return ret;
+}
+
 static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
 			   struct nlattr *tb[], struct nlattr *data[])
 {
 	struct net *net = dev_net(dev);
 	struct ip6_tnl *nt, *t;
+	struct ip_tunnel_encap ipencap;
 
 	nt = netdev_priv(dev);
+
+	if (ip6_tnl_netlink_encap_parms(data, &ipencap)) {
+		int err = ip6_tnl_encap_setup(nt, &ipencap);
+
+		if (err < 0)
+			return err;
+	}
+
 	ip6_tnl_netlink_parms(data, &nt->parms);
 
 	t = ip6_tnl_locate(net, &nt->parms, 0);
@@ -1820,10 +1862,17 @@ static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[],
 	struct __ip6_tnl_parm p;
 	struct net *net = t->net;
 	struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+	struct ip_tunnel_encap ipencap;
 
 	if (dev == ip6n->fb_tnl_dev)
 		return -EINVAL;
 
+	if (ip6_tnl_netlink_encap_parms(data, &ipencap)) {
+		int err = ip6_tnl_encap_setup(t, &ipencap);
+
+		if (err < 0)
+			return err;
+	}
 	ip6_tnl_netlink_parms(data, &p);
 
 	t = ip6_tnl_locate(net, &p, 0);
@@ -1864,6 +1913,14 @@ static size_t ip6_tnl_get_size(const struct net_device *dev)
 		nla_total_size(4) +
 		/* IFLA_IPTUN_PROTO */
 		nla_total_size(1) +
+		/* IFLA_IPTUN_ENCAP_TYPE */
+		nla_total_size(2) +
+		/* IFLA_IPTUN_ENCAP_FLAGS */
+		nla_total_size(2) +
+		/* IFLA_IPTUN_ENCAP_SPORT */
+		nla_total_size(2) +
+		/* IFLA_IPTUN_ENCAP_DPORT */
+		nla_total_size(2) +
 		0;
 }
 
@@ -1881,6 +1938,17 @@ static int ip6_tnl_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	    nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) ||
 	    nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto))
 		goto nla_put_failure;
+
+	if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE,
+			tunnel->encap.type) ||
+	nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT,
+		     tunnel->encap.sport) ||
+	nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT,
+		     tunnel->encap.dport) ||
+	nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS,
+		    tunnel->encap.flags))
+		goto nla_put_failure;
+
 	return 0;
 
 nla_put_failure:
@@ -1904,6 +1972,10 @@ static const struct nla_policy ip6_tnl_policy[IFLA_IPTUN_MAX + 1] = {
 	[IFLA_IPTUN_FLOWINFO]		= { .type = NLA_U32 },
 	[IFLA_IPTUN_FLAGS]		= { .type = NLA_U32 },
 	[IFLA_IPTUN_PROTO]		= { .type = NLA_U8 },
+	[IFLA_IPTUN_ENCAP_TYPE]		= { .type = NLA_U16 },
+	[IFLA_IPTUN_ENCAP_FLAGS]	= { .type = NLA_U16 },
+	[IFLA_IPTUN_ENCAP_SPORT]	= { .type = NLA_U16 },
+	[IFLA_IPTUN_ENCAP_DPORT]	= { .type = NLA_U16 },
 };
 
 static struct rtnl_link_ops ip6_link_ops __read_mostly = {
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 13/16] ipv6: Set features for IPv6 tunnels
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (11 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 12/16] ip6_tunnel: " Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 14/16] ip6ip6: Support for GSO/GRO Tom Herbert
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

Need to set dev features, use same values that are used in GREv6.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv6/ip6_tunnel.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 74b35e4..cabf492 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1640,6 +1640,11 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
 	.ndo_get_iflink = ip6_tnl_get_iflink,
 };
 
+#define IPXIPX_FEATURES (NETIF_F_SG |		\
+			 NETIF_F_FRAGLIST |	\
+			 NETIF_F_HIGHDMA |	\
+			 NETIF_F_GSO_SOFTWARE |	\
+			 NETIF_F_HW_CSUM)
 
 /**
  * ip6_tnl_dev_setup - setup virtual tunnel device
@@ -1659,6 +1664,10 @@ static void ip6_tnl_dev_setup(struct net_device *dev)
 	dev->addr_len = sizeof(struct in6_addr);
 	dev->features |= NETIF_F_LLTX;
 	netif_keep_dst(dev);
+
+	dev->features		|= IPXIPX_FEATURES;
+	dev->hw_features	|= IPXIPX_FEATURES;
+
 	/* This perm addr will be used as interface identifier by IPv6 */
 	dev->addr_assign_type = NET_ADDR_RANDOM;
 	eth_random_addr(dev->perm_addr);
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 14/16] ip6ip6: Support for GSO/GRO
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (12 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 13/16] ipv6: Set features for IPv6 tunnels Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 15/16] ip4ip6: " Tom Herbert
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv6/ip6_offload.c | 24 +++++++++++++++++++++---
 net/ipv6/ip6_tunnel.c  |  5 +++++
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 787e55f..332d6a0 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -253,9 +253,11 @@ out:
 	return pp;
 }
 
-static struct sk_buff **sit_gro_receive(struct sk_buff **head,
-					struct sk_buff *skb)
+static struct sk_buff **sit_ip6ip6_gro_receive(struct sk_buff **head,
+					       struct sk_buff *skb)
 {
+	/* Common GRO receive for SIT and IP6IP6 */
+
 	if (NAPI_GRO_CB(skb)->encap_mark) {
 		NAPI_GRO_CB(skb)->flush = 1;
 		return NULL;
@@ -298,6 +300,13 @@ static int sit_gro_complete(struct sk_buff *skb, int nhoff)
 	return ipv6_gro_complete(skb, nhoff);
 }
 
+static int ip6ip6_gro_complete(struct sk_buff *skb, int nhoff)
+{
+	skb->encapsulation = 1;
+	skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP6;
+	return ipv6_gro_complete(skb, nhoff);
+}
+
 static struct packet_offload ipv6_packet_offload __read_mostly = {
 	.type = cpu_to_be16(ETH_P_IPV6),
 	.callbacks = {
@@ -310,11 +319,19 @@ static struct packet_offload ipv6_packet_offload __read_mostly = {
 static const struct net_offload sit_offload = {
 	.callbacks = {
 		.gso_segment	= ipv6_gso_segment,
-		.gro_receive    = sit_gro_receive,
+		.gro_receive    = sit_ip6ip6_gro_receive,
 		.gro_complete   = sit_gro_complete,
 	},
 };
 
+static const struct net_offload ip6ip6_offload = {
+	.callbacks = {
+		.gso_segment	= ipv6_gso_segment,
+		.gro_receive    = sit_ip6ip6_gro_receive,
+		.gro_complete   = ip6ip6_gro_complete,
+	},
+};
+
 static int __init ipv6_offload_init(void)
 {
 
@@ -326,6 +343,7 @@ static int __init ipv6_offload_init(void)
 	dev_add_offload(&ipv6_packet_offload);
 
 	inet_add_offload(&sit_offload, IPPROTO_IPV6);
+	inet6_add_offload(&ip6ip6_offload, IPPROTO_IPV6);
 
 	return 0;
 }
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index cabf492..d26d226 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1242,6 +1242,11 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
 		fl6.flowi6_mark = skb->mark;
 
+	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
+		return -1;
+
+	skb_set_inner_ipproto(skb, IPPROTO_IPV6);
+
 	err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
 			   IPPROTO_IPV6);
 	if (err != 0) {
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 15/16] ip4ip6: Support for GSO/GRO
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (13 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 14/16] ip6ip6: Support for GSO/GRO Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 16:06 ` [PATCH v7 net-next 16/16] ipv6: Don't reset inner headers in ip6_tnl_xmit Tom Herbert
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 include/net/inet_common.h |  5 +++++
 net/ipv4/af_inet.c        | 12 +++++++-----
 net/ipv6/ip6_offload.c    | 33 ++++++++++++++++++++++++++++++++-
 net/ipv6/ip6_tunnel.c     |  5 +++++
 4 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/include/net/inet_common.h b/include/net/inet_common.h
index 109e3ee..5d68342 100644
--- a/include/net/inet_common.h
+++ b/include/net/inet_common.h
@@ -39,6 +39,11 @@ int inet_ctl_sock_create(struct sock **sk, unsigned short family,
 int inet_recv_error(struct sock *sk, struct msghdr *msg, int len,
 		    int *addr_len);
 
+struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb);
+int inet_gro_complete(struct sk_buff *skb, int nhoff);
+struct sk_buff *inet_gso_segment(struct sk_buff *skb,
+				 netdev_features_t features);
+
 static inline void inet_ctl_sock_destroy(struct sock *sk)
 {
 	if (sk)
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 25040b1..377424e 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1192,8 +1192,8 @@ int inet_sk_rebuild_header(struct sock *sk)
 }
 EXPORT_SYMBOL(inet_sk_rebuild_header);
 
-static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
-					netdev_features_t features)
+struct sk_buff *inet_gso_segment(struct sk_buff *skb,
+				 netdev_features_t features)
 {
 	bool udpfrag = false, fixedid = false, encap;
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
@@ -1280,9 +1280,9 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 out:
 	return segs;
 }
+EXPORT_SYMBOL(inet_gso_segment);
 
-static struct sk_buff **inet_gro_receive(struct sk_buff **head,
-					 struct sk_buff *skb)
+struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb)
 {
 	const struct net_offload *ops;
 	struct sk_buff **pp = NULL;
@@ -1398,6 +1398,7 @@ out:
 
 	return pp;
 }
+EXPORT_SYMBOL(inet_gro_receive);
 
 static struct sk_buff **ipip_gro_receive(struct sk_buff **head,
 					 struct sk_buff *skb)
@@ -1449,7 +1450,7 @@ int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
 	return -EINVAL;
 }
 
-static int inet_gro_complete(struct sk_buff *skb, int nhoff)
+int inet_gro_complete(struct sk_buff *skb, int nhoff)
 {
 	__be16 newlen = htons(skb->len - nhoff);
 	struct iphdr *iph = (struct iphdr *)(skb->data + nhoff);
@@ -1479,6 +1480,7 @@ out_unlock:
 
 	return err;
 }
+EXPORT_SYMBOL(inet_gro_complete);
 
 static int ipip_gro_complete(struct sk_buff *skb, int nhoff)
 {
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 332d6a0..22e90e5 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -16,6 +16,7 @@
 
 #include <net/protocol.h>
 #include <net/ipv6.h>
+#include <net/inet_common.h>
 
 #include "ip6_offload.h"
 
@@ -268,6 +269,21 @@ static struct sk_buff **sit_ip6ip6_gro_receive(struct sk_buff **head,
 	return ipv6_gro_receive(head, skb);
 }
 
+static struct sk_buff **ip4ip6_gro_receive(struct sk_buff **head,
+					   struct sk_buff *skb)
+{
+	/* Common GRO receive for SIT and IP6IP6 */
+
+	if (NAPI_GRO_CB(skb)->encap_mark) {
+		NAPI_GRO_CB(skb)->flush = 1;
+		return NULL;
+	}
+
+	NAPI_GRO_CB(skb)->encap_mark = 1;
+
+	return inet_gro_receive(head, skb);
+}
+
 static int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
 {
 	const struct net_offload *ops;
@@ -307,6 +323,13 @@ static int ip6ip6_gro_complete(struct sk_buff *skb, int nhoff)
 	return ipv6_gro_complete(skb, nhoff);
 }
 
+static int ip4ip6_gro_complete(struct sk_buff *skb, int nhoff)
+{
+	skb->encapsulation = 1;
+	skb_shinfo(skb)->gso_type |= SKB_GSO_IPXIP6;
+	return inet_gro_complete(skb, nhoff);
+}
+
 static struct packet_offload ipv6_packet_offload __read_mostly = {
 	.type = cpu_to_be16(ETH_P_IPV6),
 	.callbacks = {
@@ -324,6 +347,14 @@ static const struct net_offload sit_offload = {
 	},
 };
 
+static const struct net_offload ip4ip6_offload = {
+	.callbacks = {
+		.gso_segment	= inet_gso_segment,
+		.gro_receive    = ip4ip6_gro_receive,
+		.gro_complete   = ip4ip6_gro_complete,
+	},
+};
+
 static const struct net_offload ip6ip6_offload = {
 	.callbacks = {
 		.gso_segment	= ipv6_gso_segment,
@@ -331,7 +362,6 @@ static const struct net_offload ip6ip6_offload = {
 		.gro_complete   = ip6ip6_gro_complete,
 	},
 };
-
 static int __init ipv6_offload_init(void)
 {
 
@@ -344,6 +374,7 @@ static int __init ipv6_offload_init(void)
 
 	inet_add_offload(&sit_offload, IPPROTO_IPV6);
 	inet6_add_offload(&ip6ip6_offload, IPPROTO_IPV6);
+	inet6_add_offload(&ip4ip6_offload, IPPROTO_IPIP);
 
 	return 0;
 }
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index d26d226..823dad1 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1188,6 +1188,11 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
 		fl6.flowi6_mark = skb->mark;
 
+	if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
+		return -1;
+
+	skb_set_inner_ipproto(skb, IPPROTO_IPIP);
+
 	err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
 			   IPPROTO_IPIP);
 	if (err != 0) {
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH v7 net-next 16/16] ipv6: Don't reset inner headers in ip6_tnl_xmit
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (14 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 15/16] ip4ip6: " Tom Herbert
@ 2016-05-18 16:06 ` Tom Herbert
  2016-05-18 17:32 ` [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Alexander Duyck
  2016-05-20 22:03 ` David Miller
  17 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 16:06 UTC (permalink / raw)
  To: davem, netdev; +Cc: kernel-team

Since iptunnel_handle_offloads() is called in all paths we can
probably drop the block in ip6_tnl_xmit that was checking for
skb->encapsulation and resetting the inner headers.

Signed-off-by: Tom Herbert <tom@herbertland.com>
---
 net/ipv6/ip6_tunnel.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 823dad1..7b0481e 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1120,11 +1120,6 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 		ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL);
 	}
 
-	if (likely(!skb->encapsulation)) {
-		skb_reset_inner_headers(skb);
-		skb->encapsulation = 1;
-	}
-
 	/* Calculate max headroom for all the headers and adjust
 	 * needed_headroom if necessary.
 	 */
-- 
2.8.0.rc2

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (15 preceding siblings ...)
  2016-05-18 16:06 ` [PATCH v7 net-next 16/16] ipv6: Don't reset inner headers in ip6_tnl_xmit Tom Herbert
@ 2016-05-18 17:32 ` Alexander Duyck
  2016-05-18 17:40   ` Tom Herbert
  2016-05-20 22:03 ` David Miller
  17 siblings, 1 reply; 26+ messages in thread
From: Alexander Duyck @ 2016-05-18 17:32 UTC (permalink / raw)
  To: Tom Herbert; +Cc: David Miller, Netdev, Kernel Team

On Wed, May 18, 2016 at 9:06 AM, Tom Herbert <tom@herbertland.com> wrote:
> This patch set:
>   - Fixes GRE6 to process translate flags correctly from configuration
>   - Adds support for GSO and GRO for ip6ip6 and ip4ip6
>   - Add support for FOU and GUE in IPv6
>   - Support GRE, ip6ip6 and ip4ip6 over FOU/GUE
>   - Fixes ip6_input to deal with UDP encapsulations
>   - Some other minor fixes
>
> v2:
>   - Removed a check of GSO types in MPLS
>   - Define GSO type SKB_GSO_IPXIP6 and SKB_GSO_IPXIP4 (based on input
>     from Alexander)
>   - Don't define GSO types specifically for IP6IP6 and IP4IP6, above
>     fix makes that unnecessary
>   - Don't bother clearing encapsulation flag in UDP tunnel segment
>     (another item suggested by Alexander).
>
> v3:
>   - Address some minor comments from Alexander
>
> v4:
>   - Rebase on changes to fix IP TX tunnels
>   - Fix MTU issues in ip4ip6, ip6ip6
>   - Add test data for above
>
> v5:
>   - Address feedback from Shmulik Ladkani regarding extension header
>     code that does not return next header but in instead relies
>     on returning value via nhoff. Solution here is to fix EH
>     processing to return nexthdr value.
>   - Refactored IPv4 encaps so that we won't need to create
>     a ip6_tunnel_core.c when adding encap support IPv6.
>
> v6:
>   - Fix build issues with regard to new GSO constants
>   - FIx MTU calculation issues ip6_tunnel.c pointed out byt ALex
>   - Add encap_hlen into headroom for GREv6 to work with FOU/GUE
>
> v7:
>   - Added skb_set_inner_ipproto to ip4ip6 and ip6ip6
>   - Clarified max_headroom in ip6_tnl_xmit
>   - Set features for IPv6 tunnels
>   - Other cleanup suggested by Alexander
>   - Above fixes throughput performance issues in ip4ip6 and ip6ip6,
>     updated test results to reflect that
>
> Tested: Various cases of IP tunnels with netperf TCP_STREAM and TCP_RR.
>
>     - IPv4/GRE/GUE/IPv6 with RCO
>       1 TCP_STREAM
>         6616 Mbps
>       200 TCP_RR
>         1244043 tps
>         141/243/446 90/95/99% latencies
>         86.61% CPU utilization
>
>     - IPv6/GRE/GUE/IPv6 with RCO
>       1 TCP_STREAM
>         6940 Mbps
>       200 TCP_RR
>         1270903 tps
>         138/236/440 90/95/99% latencies
>         87.51% CPU utilization
>
>      - IP6IP6
>       1 TCP_STREAM
>         5307 Mbps
>       200 TCP_RR
>         498981 tps
>         388/498/631 90/95/99% latencies
>         19.75% CPU utilization (1 CPU saturated)
>
>      - IP6IP6/GUE with RCO
>       1 TCP_STREAM
>         5575 Mbps
>       200 TCP_RR
>         1233818 tps
>         143/244/451 90/95/99% latencies
>         87.57 CPU utilization
>
>      - IP4IP6
>       1 TCP_STREAM
>         5235 Mbps
>       200 TCP_RR
>         763774 tps
>         250/318/466 90/95/99% latencies
>         35.25% CPU utilization (1 CPU saturated)
>
>      - IP4IP6/GUE with RCO
>       1 TCP_STREAM
>         5337 Mbps
>       200 TCP_RR
>         1196385 tps
>         148/251/460 90/95/99% latencies
>         87.56 CPU utilization
>
>      - GRE with keyid
>       200 TCP_RR
>         744173 tps
>         258/332/461 90/95/99% latencies
>         34.59% CPU utilization (1 CPU saturated)
>
>
> Tom Herbert (16):
>   gso: Remove arbitrary checks for unsupported GSO
>   net: define gso types for IPx over IPv4 and IPv6
>   ipv6: Fix nexthdr for reinjection
>   ipv6: Change "final" protocol processing for encapsulation
>   net: Cleanup encap items in ip_tunnels.h
>   fou: Call setup_udp_tunnel_sock
>   fou: Split out {fou,gue}_build_header
>   fou: Support IPv6 in fou
>   ip6_tun: Add infrastructure for doing encapsulation
>   fou: Add encap ops for IPv6 tunnels
>   ip6_gre: Add support for fou/gue encapsulation
>   ip6_tunnel: Add support for fou/gue encapsulation
>   ipv6: Set features for IPv6 tunnels
>   ip6ip6: Support for GSO/GRO
>   ip4ip6: Support for GSO/GRO
>   ipv6: Don't reset inner headers in ip6_tnl_xmit
>
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c  |   5 +-
>  drivers/net/ethernet/broadcom/bnxt/bnxt.c         |   5 +-
>  drivers/net/ethernet/intel/i40e/i40e_main.c       |   3 +-
>  drivers/net/ethernet/intel/i40e/i40e_txrx.c       |   3 +-
>  drivers/net/ethernet/intel/i40evf/i40e_txrx.c     |   3 +-
>  drivers/net/ethernet/intel/i40evf/i40evf_main.c   |   3 +-
>  drivers/net/ethernet/intel/igb/igb_main.c         |   3 +-
>  drivers/net/ethernet/intel/igbvf/netdev.c         |   3 +-
>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |   3 +-
>  drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |   3 +-
>  include/linux/netdev_features.h                   |  12 +-
>  include/linux/netdevice.h                         |   4 +-
>  include/linux/skbuff.h                            |   4 +-
>  include/net/fou.h                                 |  10 +-
>  include/net/inet_common.h                         |   5 +
>  include/net/ip6_tunnel.h                          |  58 +++++++
>  include/net/ip_tunnels.h                          |  76 +++++++--
>  net/core/ethtool.c                                |   4 +-
>  net/ipv4/af_inet.c                                |  32 +---
>  net/ipv4/fou.c                                    | 144 +++++++++-------
>  net/ipv4/gre_offload.c                            |  14 --
>  net/ipv4/ip_tunnel.c                              |  45 -----
>  net/ipv4/ip_tunnel_core.c                         |   9 +
>  net/ipv4/ipip.c                                   |   2 +-
>  net/ipv4/tcp_offload.c                            |  19 ---
>  net/ipv4/udp_offload.c                            |  10 --
>  net/ipv6/Makefile                                 |   1 +
>  net/ipv6/fou6.c                                   | 140 ++++++++++++++++
>  net/ipv6/ip6_gre.c                                |  79 ++++++++-
>  net/ipv6/ip6_input.c                              |  33 +++-
>  net/ipv6/ip6_offload.c                            |  77 ++++++---
>  net/ipv6/ip6_tunnel.c                             | 190 ++++++++++++++++++++--
>  net/ipv6/sit.c                                    |   4 +-
>  net/ipv6/udp_offload.c                            |  13 --
>  net/mpls/mpls_gso.c                               |  11 +-
>  net/netfilter/ipvs/ip_vs_xmit.c                   |  17 +-
>  36 files changed, 737 insertions(+), 310 deletions(-)
>  create mode 100644 net/ipv6/fou6.c
>
> --
> 2.8.0.rc2
>

So I have put this patch series through a quick check by comparing it
against the code I had in terms of fixes and as such and it looks
good.

I have 2 follow-up patches I will probably want to submit for it.  One
prevents us from supporting segmentation offloads if GRE_CSUM is
enabled for a FOU/GUE tunnel with GRE, and the other enables the Intel
NICs to offload this in hardware or via a mix of hardware and software
using GSO_PARTIAL.

Reviewed-by: Alexander Duyck <aduyck@mirantis.com>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling
  2016-05-18 17:32 ` [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Alexander Duyck
@ 2016-05-18 17:40   ` Tom Herbert
  0 siblings, 0 replies; 26+ messages in thread
From: Tom Herbert @ 2016-05-18 17:40 UTC (permalink / raw)
  To: Alexander Duyck; +Cc: David Miller, Netdev, Kernel Team

On Wed, May 18, 2016 at 10:32 AM, Alexander Duyck
<alexander.duyck@gmail.com> wrote:
> On Wed, May 18, 2016 at 9:06 AM, Tom Herbert <tom@herbertland.com> wrote:
>> This patch set:
>>   - Fixes GRE6 to process translate flags correctly from configuration
>>   - Adds support for GSO and GRO for ip6ip6 and ip4ip6
>>   - Add support for FOU and GUE in IPv6
>>   - Support GRE, ip6ip6 and ip4ip6 over FOU/GUE
>>   - Fixes ip6_input to deal with UDP encapsulations
>>   - Some other minor fixes
>>
>> v2:
>>   - Removed a check of GSO types in MPLS
>>   - Define GSO type SKB_GSO_IPXIP6 and SKB_GSO_IPXIP4 (based on input
>>     from Alexander)
>>   - Don't define GSO types specifically for IP6IP6 and IP4IP6, above
>>     fix makes that unnecessary
>>   - Don't bother clearing encapsulation flag in UDP tunnel segment
>>     (another item suggested by Alexander).
>>
>> v3:
>>   - Address some minor comments from Alexander
>>
>> v4:
>>   - Rebase on changes to fix IP TX tunnels
>>   - Fix MTU issues in ip4ip6, ip6ip6
>>   - Add test data for above
>>
>> v5:
>>   - Address feedback from Shmulik Ladkani regarding extension header
>>     code that does not return next header but in instead relies
>>     on returning value via nhoff. Solution here is to fix EH
>>     processing to return nexthdr value.
>>   - Refactored IPv4 encaps so that we won't need to create
>>     a ip6_tunnel_core.c when adding encap support IPv6.
>>
>> v6:
>>   - Fix build issues with regard to new GSO constants
>>   - FIx MTU calculation issues ip6_tunnel.c pointed out byt ALex
>>   - Add encap_hlen into headroom for GREv6 to work with FOU/GUE
>>
>> v7:
>>   - Added skb_set_inner_ipproto to ip4ip6 and ip6ip6
>>   - Clarified max_headroom in ip6_tnl_xmit
>>   - Set features for IPv6 tunnels
>>   - Other cleanup suggested by Alexander
>>   - Above fixes throughput performance issues in ip4ip6 and ip6ip6,
>>     updated test results to reflect that
>>
>> Tested: Various cases of IP tunnels with netperf TCP_STREAM and TCP_RR.
>>
>>     - IPv4/GRE/GUE/IPv6 with RCO
>>       1 TCP_STREAM
>>         6616 Mbps
>>       200 TCP_RR
>>         1244043 tps
>>         141/243/446 90/95/99% latencies
>>         86.61% CPU utilization
>>
>>     - IPv6/GRE/GUE/IPv6 with RCO
>>       1 TCP_STREAM
>>         6940 Mbps
>>       200 TCP_RR
>>         1270903 tps
>>         138/236/440 90/95/99% latencies
>>         87.51% CPU utilization
>>
>>      - IP6IP6
>>       1 TCP_STREAM
>>         5307 Mbps
>>       200 TCP_RR
>>         498981 tps
>>         388/498/631 90/95/99% latencies
>>         19.75% CPU utilization (1 CPU saturated)
>>
>>      - IP6IP6/GUE with RCO
>>       1 TCP_STREAM
>>         5575 Mbps
>>       200 TCP_RR
>>         1233818 tps
>>         143/244/451 90/95/99% latencies
>>         87.57 CPU utilization
>>
>>      - IP4IP6
>>       1 TCP_STREAM
>>         5235 Mbps
>>       200 TCP_RR
>>         763774 tps
>>         250/318/466 90/95/99% latencies
>>         35.25% CPU utilization (1 CPU saturated)
>>
>>      - IP4IP6/GUE with RCO
>>       1 TCP_STREAM
>>         5337 Mbps
>>       200 TCP_RR
>>         1196385 tps
>>         148/251/460 90/95/99% latencies
>>         87.56 CPU utilization
>>
>>      - GRE with keyid
>>       200 TCP_RR
>>         744173 tps
>>         258/332/461 90/95/99% latencies
>>         34.59% CPU utilization (1 CPU saturated)
>>
>>
>> Tom Herbert (16):
>>   gso: Remove arbitrary checks for unsupported GSO
>>   net: define gso types for IPx over IPv4 and IPv6
>>   ipv6: Fix nexthdr for reinjection
>>   ipv6: Change "final" protocol processing for encapsulation
>>   net: Cleanup encap items in ip_tunnels.h
>>   fou: Call setup_udp_tunnel_sock
>>   fou: Split out {fou,gue}_build_header
>>   fou: Support IPv6 in fou
>>   ip6_tun: Add infrastructure for doing encapsulation
>>   fou: Add encap ops for IPv6 tunnels
>>   ip6_gre: Add support for fou/gue encapsulation
>>   ip6_tunnel: Add support for fou/gue encapsulation
>>   ipv6: Set features for IPv6 tunnels
>>   ip6ip6: Support for GSO/GRO
>>   ip4ip6: Support for GSO/GRO
>>   ipv6: Don't reset inner headers in ip6_tnl_xmit
>>
>>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c  |   5 +-
>>  drivers/net/ethernet/broadcom/bnxt/bnxt.c         |   5 +-
>>  drivers/net/ethernet/intel/i40e/i40e_main.c       |   3 +-
>>  drivers/net/ethernet/intel/i40e/i40e_txrx.c       |   3 +-
>>  drivers/net/ethernet/intel/i40evf/i40e_txrx.c     |   3 +-
>>  drivers/net/ethernet/intel/i40evf/i40evf_main.c   |   3 +-
>>  drivers/net/ethernet/intel/igb/igb_main.c         |   3 +-
>>  drivers/net/ethernet/intel/igbvf/netdev.c         |   3 +-
>>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |   3 +-
>>  drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |   3 +-
>>  include/linux/netdev_features.h                   |  12 +-
>>  include/linux/netdevice.h                         |   4 +-
>>  include/linux/skbuff.h                            |   4 +-
>>  include/net/fou.h                                 |  10 +-
>>  include/net/inet_common.h                         |   5 +
>>  include/net/ip6_tunnel.h                          |  58 +++++++
>>  include/net/ip_tunnels.h                          |  76 +++++++--
>>  net/core/ethtool.c                                |   4 +-
>>  net/ipv4/af_inet.c                                |  32 +---
>>  net/ipv4/fou.c                                    | 144 +++++++++-------
>>  net/ipv4/gre_offload.c                            |  14 --
>>  net/ipv4/ip_tunnel.c                              |  45 -----
>>  net/ipv4/ip_tunnel_core.c                         |   9 +
>>  net/ipv4/ipip.c                                   |   2 +-
>>  net/ipv4/tcp_offload.c                            |  19 ---
>>  net/ipv4/udp_offload.c                            |  10 --
>>  net/ipv6/Makefile                                 |   1 +
>>  net/ipv6/fou6.c                                   | 140 ++++++++++++++++
>>  net/ipv6/ip6_gre.c                                |  79 ++++++++-
>>  net/ipv6/ip6_input.c                              |  33 +++-
>>  net/ipv6/ip6_offload.c                            |  77 ++++++---
>>  net/ipv6/ip6_tunnel.c                             | 190 ++++++++++++++++++++--
>>  net/ipv6/sit.c                                    |   4 +-
>>  net/ipv6/udp_offload.c                            |  13 --
>>  net/mpls/mpls_gso.c                               |  11 +-
>>  net/netfilter/ipvs/ip_vs_xmit.c                   |  17 +-
>>  36 files changed, 737 insertions(+), 310 deletions(-)
>>  create mode 100644 net/ipv6/fou6.c
>>
>> --
>> 2.8.0.rc2
>>
>
> So I have put this patch series through a quick check by comparing it
> against the code I had in terms of fixes and as such and it looks
> good.
>
> I have 2 follow-up patches I will probably want to submit for it.  One
> prevents us from supporting segmentation offloads if GRE_CSUM is
> enabled for a FOU/GUE tunnel with GRE, and the other enables the Intel
> NICs to offload this in hardware or via a mix of hardware and software
> using GSO_PARTIAL.
>
That sounds good. I also assume some drivers will want to enable
IPXIP6 offloads.

> Reviewed-by: Alexander Duyck <aduyck@mirantis.com>

Thanks for all your hard work on this!

Tom

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v7 net-next 02/16] net: define gso types for IPx over IPv4 and IPv6
  2016-05-18 16:06 ` [PATCH v7 net-next 02/16] net: define gso types for IPx over IPv4 and IPv6 Tom Herbert
@ 2016-05-18 22:03   ` Jeff Kirsher
  0 siblings, 0 replies; 26+ messages in thread
From: Jeff Kirsher @ 2016-05-18 22:03 UTC (permalink / raw)
  To: Tom Herbert, davem, netdev; +Cc: kernel-team

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

On Wed, 2016-05-18 at 09:06 -0700, Tom Herbert wrote:
> This patch defines two new GSO definitions SKB_GSO_IPXIP4 and
> SKB_GSO_IPXIP6 along with corresponding NETIF_F_GSO_IPXIP4 and
> NETIF_F_GSO_IPXIP6. These are used to described IP in IP
> tunnel and what the outer protocol is. The inner protocol
> can be deduced from other GSO types (e.g. SKB_GSO_TCPV4 and
> SKB_GSO_TCPV6). The GSO types of SKB_GSO_IPIP and SKB_GSO_SIT
> are removed (these are both instances of SKB_GSO_IPXIP4).
> SKB_GSO_IPXIP6 will be used when support for GSO with IP
> encapsulation over IPv6 is added.
> 
> Signed-off-by: Tom Herbert <tom@herbertland.com>

Acked-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
For the Intel Ethernet driver changes...

> ---
>  drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  5 ++---
>  drivers/net/ethernet/broadcom/bnxt/bnxt.c         |  5 ++---
>  drivers/net/ethernet/intel/i40e/i40e_main.c       |  3 +--
>  drivers/net/ethernet/intel/i40e/i40e_txrx.c       |  3 +--
>  drivers/net/ethernet/intel/i40evf/i40e_txrx.c     |  3 +--
>  drivers/net/ethernet/intel/i40evf/i40evf_main.c   |  3 +--
>  drivers/net/ethernet/intel/igb/igb_main.c         |  3 +--
>  drivers/net/ethernet/intel/igbvf/netdev.c         |  3 +--
>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c     |  3 +--
>  drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |  3 +--
>  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                                |  2 +-
>  net/ipv4/ipip.c                                   |  2 +-
>  net/ipv6/ip6_offload.c                            |  4 ++--
>  net/ipv6/sit.c                                    |  4 ++--
>  net/netfilter/ipvs/ip_vs_xmit.c                   | 17 +++++++----------
>  19 files changed, 37 insertions(+), 50 deletions(-)

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling
  2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
                   ` (16 preceding siblings ...)
  2016-05-18 17:32 ` [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Alexander Duyck
@ 2016-05-20 22:03 ` David Miller
  17 siblings, 0 replies; 26+ messages in thread
From: David Miller @ 2016-05-20 22:03 UTC (permalink / raw)
  To: tom; +Cc: netdev, kernel-team

From: Tom Herbert <tom@herbertland.com>
Date: Wed, 18 May 2016 09:06:08 -0700

> This patch set:
>   - Fixes GRE6 to process translate flags correctly from configuration
>   - Adds support for GSO and GRO for ip6ip6 and ip4ip6
>   - Add support for FOU and GUE in IPv6
>   - Support GRE, ip6ip6 and ip4ip6 over FOU/GUE
>   - Fixes ip6_input to deal with UDP encapsulations
>   - Some other minor fixes

Series applied, thanks Tom.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v7 net-next 01/16] gso: Remove arbitrary checks for unsupported GSO
  2016-05-18 16:06 ` [PATCH v7 net-next 01/16] gso: Remove arbitrary checks for unsupported GSO Tom Herbert
@ 2016-05-21  1:02   ` Hannes Frederic Sowa
  2016-05-21  3:56     ` Alexander Duyck
  2016-05-22  7:44     ` Michael S. Tsirkin
  2016-05-22  7:44   ` Michael S. Tsirkin
  1 sibling, 2 replies; 26+ messages in thread
From: Hannes Frederic Sowa @ 2016-05-21  1:02 UTC (permalink / raw)
  To: Tom Herbert, davem, netdev; +Cc: kernel-team, Michael S. Tsirkin

Hello,

On 18.05.2016 18:06, Tom Herbert wrote:
> In several gso_segment functions there are checks of gso_type against
> a seemingly arbitrary list of SKB_GSO_* flags. This seems like an
> attempt to identify unsupported GSO types, but since the stack is
> the one that set these GSO types in the first place this seems
> unnecessary to do. If a combination isn't valid in the first
> place that stack should not allow setting it.
> 
> This is a code simplication especially for add new GSO types.

I couldn't still wrap my head around this.

I wonder if this is safe in case of if the packet is generated from an
untrusted virtual machine over virtio_net?

Bye,
Hannes

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v7 net-next 01/16] gso: Remove arbitrary checks for unsupported GSO
  2016-05-21  1:02   ` Hannes Frederic Sowa
@ 2016-05-21  3:56     ` Alexander Duyck
  2016-05-22  7:44     ` Michael S. Tsirkin
  1 sibling, 0 replies; 26+ messages in thread
From: Alexander Duyck @ 2016-05-21  3:56 UTC (permalink / raw)
  To: Hannes Frederic Sowa
  Cc: Tom Herbert, David Miller, Netdev, Kernel Team, Michael S. Tsirkin

On Fri, May 20, 2016 at 6:02 PM, Hannes Frederic Sowa
<hannes@stressinduktion.org> wrote:
> Hello,
>
> On 18.05.2016 18:06, Tom Herbert wrote:
>> In several gso_segment functions there are checks of gso_type against
>> a seemingly arbitrary list of SKB_GSO_* flags. This seems like an
>> attempt to identify unsupported GSO types, but since the stack is
>> the one that set these GSO types in the first place this seems
>> unnecessary to do. If a combination isn't valid in the first
>> place that stack should not allow setting it.
>>
>> This is a code simplication especially for add new GSO types.
>
> I couldn't still wrap my head around this.
>
> I wonder if this is safe in case of if the packet is generated from an
> untrusted virtual machine over virtio_net?

The problem is the test is kind of pointless.  I think the original
point of the tests was to prevent the case of IPIP and TSO6 or SIT and
TSO4.  However since we dropped IPIP and SIT and instead replaced them
with the IPXIP6 and IPXIP4 there shouldn't be any combinations that
don't work now other than UDP being combined with TCP segmentation.

If we are wanting to prevent that case we might place something
earlier in the segmentation code that would perform an and with all
the L4 GSO types that should be mutually exclusive, verify that value
is non-zero, and then and that value with itself - 1 to verify that
exactly 1 bit is set in that grouping and no more than that.

- Alex

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v7 net-next 01/16] gso: Remove arbitrary checks for unsupported GSO
  2016-05-21  1:02   ` Hannes Frederic Sowa
  2016-05-21  3:56     ` Alexander Duyck
@ 2016-05-22  7:44     ` Michael S. Tsirkin
  2016-05-22 12:33       ` Hannes Frederic Sowa
  1 sibling, 1 reply; 26+ messages in thread
From: Michael S. Tsirkin @ 2016-05-22  7:44 UTC (permalink / raw)
  To: Hannes Frederic Sowa; +Cc: Tom Herbert, davem, netdev, kernel-team

On Sat, May 21, 2016 at 03:02:30AM +0200, Hannes Frederic Sowa wrote:
> Hello,
> 
> On 18.05.2016 18:06, Tom Herbert wrote:
> > In several gso_segment functions there are checks of gso_type against
> > a seemingly arbitrary list of SKB_GSO_* flags. This seems like an
> > attempt to identify unsupported GSO types, but since the stack is
> > the one that set these GSO types in the first place this seems
> > unnecessary to do. If a combination isn't valid in the first
> > place that stack should not allow setting it.
> > 
> > This is a code simplication especially for add new GSO types.
> 
> I couldn't still wrap my head around this.
> 
> I wonder if this is safe in case of if the packet is generated from an
> untrusted virtual machine over virtio_net?
> 
> Bye,
> Hannes

I'm not sure how you use virtio_net, but neither it nor tun or macvtap
commonly used as backends for it pass gso flags through
from untrusted entities.

-- 
MST

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v7 net-next 01/16] gso: Remove arbitrary checks for unsupported GSO
  2016-05-18 16:06 ` [PATCH v7 net-next 01/16] gso: Remove arbitrary checks for unsupported GSO Tom Herbert
  2016-05-21  1:02   ` Hannes Frederic Sowa
@ 2016-05-22  7:44   ` Michael S. Tsirkin
  1 sibling, 0 replies; 26+ messages in thread
From: Michael S. Tsirkin @ 2016-05-22  7:44 UTC (permalink / raw)
  To: Tom Herbert; +Cc: davem, netdev, kernel-team

On Wed, May 18, 2016 at 09:06:09AM -0700, Tom Herbert wrote:
> In several gso_segment functions there are checks of gso_type against
> a seemingly arbitrary list of SKB_GSO_* flags. This seems like an
> attempt to identify unsupported GSO types, but since the stack is
> the one that set these GSO types in the first place this seems
> unnecessary to do. If a combination isn't valid in the first
> place that stack should not allow setting it.
> 
> This is a code simplication especially for add new GSO types.
> 
> Signed-off-by: Tom Herbert <tom@herbertland.com>


I don't know of instances where gso_flags are passed in
from a VM, so FWIW

Acked-by: Michael S. Tsirkin <mst@redhat.com>


> ---
>  net/ipv4/af_inet.c     | 18 ------------------
>  net/ipv4/gre_offload.c | 14 --------------
>  net/ipv4/tcp_offload.c | 19 -------------------
>  net/ipv4/udp_offload.c | 10 ----------
>  net/ipv6/ip6_offload.c | 18 ------------------
>  net/ipv6/udp_offload.c | 13 -------------
>  net/mpls/mpls_gso.c    | 11 +----------
>  7 files changed, 1 insertion(+), 102 deletions(-)
> 
> diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
> index 2e6e65f..7f08d45 100644
> --- a/net/ipv4/af_inet.c
> +++ b/net/ipv4/af_inet.c
> @@ -1205,24 +1205,6 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
>  	int ihl;
>  	int id;
>  
> -	if (unlikely(skb_shinfo(skb)->gso_type &
> -		     ~(SKB_GSO_TCPV4 |
> -		       SKB_GSO_UDP |
> -		       SKB_GSO_DODGY |
> -		       SKB_GSO_TCP_ECN |
> -		       SKB_GSO_GRE |
> -		       SKB_GSO_GRE_CSUM |
> -		       SKB_GSO_IPIP |
> -		       SKB_GSO_SIT |
> -		       SKB_GSO_TCPV6 |
> -		       SKB_GSO_UDP_TUNNEL |
> -		       SKB_GSO_UDP_TUNNEL_CSUM |
> -		       SKB_GSO_TCP_FIXEDID |
> -		       SKB_GSO_TUNNEL_REMCSUM |
> -		       SKB_GSO_PARTIAL |
> -		       0)))
> -		goto out;
> -
>  	skb_reset_network_header(skb);
>  	nhoff = skb_network_header(skb) - skb_mac_header(skb);
>  	if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
> diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
> index e88190a..ecd1e09 100644
> --- a/net/ipv4/gre_offload.c
> +++ b/net/ipv4/gre_offload.c
> @@ -26,20 +26,6 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
>  	int gre_offset, outer_hlen;
>  	bool need_csum, ufo;
>  
> -	if (unlikely(skb_shinfo(skb)->gso_type &
> -				~(SKB_GSO_TCPV4 |
> -				  SKB_GSO_TCPV6 |
> -				  SKB_GSO_UDP |
> -				  SKB_GSO_DODGY |
> -				  SKB_GSO_TCP_ECN |
> -				  SKB_GSO_TCP_FIXEDID |
> -				  SKB_GSO_GRE |
> -				  SKB_GSO_GRE_CSUM |
> -				  SKB_GSO_IPIP |
> -				  SKB_GSO_SIT |
> -				  SKB_GSO_PARTIAL)))
> -		goto out;
> -
>  	if (!skb->encapsulation)
>  		goto out;
>  
> diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
> index 02737b6..5c59649 100644
> --- a/net/ipv4/tcp_offload.c
> +++ b/net/ipv4/tcp_offload.c
> @@ -83,25 +83,6 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
>  
>  	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
>  		/* Packet is from an untrusted source, reset gso_segs. */
> -		int type = skb_shinfo(skb)->gso_type;
> -
> -		if (unlikely(type &
> -			     ~(SKB_GSO_TCPV4 |
> -			       SKB_GSO_DODGY |
> -			       SKB_GSO_TCP_ECN |
> -			       SKB_GSO_TCP_FIXEDID |
> -			       SKB_GSO_TCPV6 |
> -			       SKB_GSO_GRE |
> -			       SKB_GSO_GRE_CSUM |
> -			       SKB_GSO_IPIP |
> -			       SKB_GSO_SIT |
> -			       SKB_GSO_UDP_TUNNEL |
> -			       SKB_GSO_UDP_TUNNEL_CSUM |
> -			       SKB_GSO_TUNNEL_REMCSUM |
> -			       0) ||
> -			     !(type & (SKB_GSO_TCPV4 |
> -				       SKB_GSO_TCPV6))))
> -			goto out;
>  
>  		skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
>  
> diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
> index 6b7459c..81f253b 100644
> --- a/net/ipv4/udp_offload.c
> +++ b/net/ipv4/udp_offload.c
> @@ -209,16 +209,6 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
>  
>  	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
>  		/* Packet is from an untrusted source, reset gso_segs. */
> -		int type = skb_shinfo(skb)->gso_type;
> -
> -		if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
> -				      SKB_GSO_UDP_TUNNEL |
> -				      SKB_GSO_UDP_TUNNEL_CSUM |
> -				      SKB_GSO_TUNNEL_REMCSUM |
> -				      SKB_GSO_IPIP |
> -				      SKB_GSO_GRE | SKB_GSO_GRE_CSUM) ||
> -			     !(type & (SKB_GSO_UDP))))
> -			goto out;
>  
>  		skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
>  
> diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
> index f5eb184..9ad743b 100644
> --- a/net/ipv6/ip6_offload.c
> +++ b/net/ipv6/ip6_offload.c
> @@ -69,24 +69,6 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
>  	bool encap, udpfrag;
>  	int nhoff;
>  
> -	if (unlikely(skb_shinfo(skb)->gso_type &
> -		     ~(SKB_GSO_TCPV4 |
> -		       SKB_GSO_UDP |
> -		       SKB_GSO_DODGY |
> -		       SKB_GSO_TCP_ECN |
> -		       SKB_GSO_TCP_FIXEDID |
> -		       SKB_GSO_TCPV6 |
> -		       SKB_GSO_GRE |
> -		       SKB_GSO_GRE_CSUM |
> -		       SKB_GSO_IPIP |
> -		       SKB_GSO_SIT |
> -		       SKB_GSO_UDP_TUNNEL |
> -		       SKB_GSO_UDP_TUNNEL_CSUM |
> -		       SKB_GSO_TUNNEL_REMCSUM |
> -		       SKB_GSO_PARTIAL |
> -		       0)))
> -		goto out;
> -
>  	skb_reset_network_header(skb);
>  	nhoff = skb_network_header(skb) - skb_mac_header(skb);
>  	if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
> diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
> index 5429f6b..ac858c4 100644
> --- a/net/ipv6/udp_offload.c
> +++ b/net/ipv6/udp_offload.c
> @@ -36,19 +36,6 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
>  
>  	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
>  		/* Packet is from an untrusted source, reset gso_segs. */
> -		int type = skb_shinfo(skb)->gso_type;
> -
> -		if (unlikely(type & ~(SKB_GSO_UDP |
> -				      SKB_GSO_DODGY |
> -				      SKB_GSO_UDP_TUNNEL |
> -				      SKB_GSO_UDP_TUNNEL_CSUM |
> -				      SKB_GSO_TUNNEL_REMCSUM |
> -				      SKB_GSO_GRE |
> -				      SKB_GSO_GRE_CSUM |
> -				      SKB_GSO_IPIP |
> -				      SKB_GSO_SIT) ||
> -			     !(type & (SKB_GSO_UDP))))
> -			goto out;
>  
>  		skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
>  
> diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c
> index bbcf604..2055e57 100644
> --- a/net/mpls/mpls_gso.c
> +++ b/net/mpls/mpls_gso.c
> @@ -26,15 +26,6 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
>  	netdev_features_t mpls_features;
>  	__be16 mpls_protocol;
>  
> -	if (unlikely(skb_shinfo(skb)->gso_type &
> -				~(SKB_GSO_TCPV4 |
> -				  SKB_GSO_TCPV6 |
> -				  SKB_GSO_UDP |
> -				  SKB_GSO_DODGY |
> -				  SKB_GSO_TCP_FIXEDID |
> -				  SKB_GSO_TCP_ECN)))
> -		goto out;
> -
>  	/* Setup inner SKB. */
>  	mpls_protocol = skb->protocol;
>  	skb->protocol = skb->inner_protocol;
> @@ -57,7 +48,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
>  	 * skb_mac_gso_segment(), an indirect caller of this function.
>  	 */
>  	__skb_pull(skb, skb->data - skb_mac_header(skb));
> -out:
> +
>  	return segs;
>  }
>  
> -- 
> 2.8.0.rc2

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v7 net-next 01/16] gso: Remove arbitrary checks for unsupported GSO
  2016-05-22  7:44     ` Michael S. Tsirkin
@ 2016-05-22 12:33       ` Hannes Frederic Sowa
  0 siblings, 0 replies; 26+ messages in thread
From: Hannes Frederic Sowa @ 2016-05-22 12:33 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Tom Herbert, davem, netdev, kernel-team

On 22.05.2016 09:44, Michael S. Tsirkin wrote:
> On Sat, May 21, 2016 at 03:02:30AM +0200, Hannes Frederic Sowa wrote:
>> Hello,
>>
>> On 18.05.2016 18:06, Tom Herbert wrote:
>>> In several gso_segment functions there are checks of gso_type against
>>> a seemingly arbitrary list of SKB_GSO_* flags. This seems like an
>>> attempt to identify unsupported GSO types, but since the stack is
>>> the one that set these GSO types in the first place this seems
>>> unnecessary to do. If a combination isn't valid in the first
>>> place that stack should not allow setting it.
>>>
>>> This is a code simplication especially for add new GSO types.
>>
>> I couldn't still wrap my head around this.
>>
>> I wonder if this is safe in case of if the packet is generated from an
>> untrusted virtual machine over virtio_net?
>>
>> Bye,
>> Hannes
> 
> I'm not sure how you use virtio_net, but neither it nor tun or macvtap
> commonly used as backends for it pass gso flags through
> from untrusted entities.

Sorry for the noise, I see the flags gets sanitized during transport.

Thanks,
Hannes

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2016-05-22 12:33 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-18 16:06 [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 01/16] gso: Remove arbitrary checks for unsupported GSO Tom Herbert
2016-05-21  1:02   ` Hannes Frederic Sowa
2016-05-21  3:56     ` Alexander Duyck
2016-05-22  7:44     ` Michael S. Tsirkin
2016-05-22 12:33       ` Hannes Frederic Sowa
2016-05-22  7:44   ` Michael S. Tsirkin
2016-05-18 16:06 ` [PATCH v7 net-next 02/16] net: define gso types for IPx over IPv4 and IPv6 Tom Herbert
2016-05-18 22:03   ` Jeff Kirsher
2016-05-18 16:06 ` [PATCH v7 net-next 03/16] ipv6: Fix nexthdr for reinjection Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 04/16] ipv6: Change "final" protocol processing for encapsulation Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 05/16] net: Cleanup encap items in ip_tunnels.h Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 06/16] fou: Call setup_udp_tunnel_sock Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 07/16] fou: Split out {fou,gue}_build_header Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 08/16] fou: Support IPv6 in fou Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 09/16] ip6_tun: Add infrastructure for doing encapsulation Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 10/16] fou: Add encap ops for IPv6 tunnels Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 11/16] ip6_gre: Add support for fou/gue encapsulation Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 12/16] ip6_tunnel: " Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 13/16] ipv6: Set features for IPv6 tunnels Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 14/16] ip6ip6: Support for GSO/GRO Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 15/16] ip4ip6: " Tom Herbert
2016-05-18 16:06 ` [PATCH v7 net-next 16/16] ipv6: Don't reset inner headers in ip6_tnl_xmit Tom Herbert
2016-05-18 17:32 ` [PATCH v7 net-next 00/16] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Alexander Duyck
2016-05-18 17:40   ` Tom Herbert
2016-05-20 22:03 ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).