* [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling
@ 2016-05-05 1:02 Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 01/14] gso: Remove arbitrary checks for unsupported GSO Tom Herbert
` (13 more replies)
0 siblings, 14 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 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
Tested:
Tested a variety of case, but not the full matrix (which is quite
large now). Most of the obivous cases (e.g. GRE) work fine. Still
some issues probably with GSO/GRO being effective in all cases.
- 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
2576 Mbps
200 TCP_RR
498981 tps
388/498/631 90/95/99% latencies
19.75% CPU utilization (1 CPU saturated)
- IP6IP6/GUE/IPv6 with RCO
1 TCP_STREAM
1854 Mbps
200 TCP_RR
1233818 tps
143/244/451 90/95/99% latencies
87.57 CPU utilization
- IP4IP6
1 TCP_STREAM
200 TCP_RR
763774 tps
250/318/466 90/95/99% latencies
35.25% CPU utilization (1 CPU saturated)
- GRE with keyid
200 TCP_RR
744173 tps
258/332/461 90/95/99% latencies
34.59% CPU utilization (1 CPU saturated)
Tom Herbert (14):
gso: Remove arbitrary checks for unsupported GSO
gre6: Fix flag translations
udp: Don't set skb->encapsulation with RCO
fou: Call setup_udp_tunnel_sock
fou: Split out {fou,gue}_build_header
fou: Add encap ops for IPv6 tunnels
ipv6: Fix nexthdr for reinjection
ipv6: Change "final" protocol processing for encapsulation
fou: Support IPv6 in fou
ip6_tun: Add infrastructure for doing encapsulation
ip6_gre: Add support for fou/gue encapsulation
ip6_tunnel: Add support for fou/gue encapsulation
ip6ip6: Support for GSO/GRO
ip4ip6: Support for GSO/GRO
include/linux/netdev_features.h | 8 ++-
include/linux/netdevice.h | 2 +
include/linux/skbuff.h | 4 ++
include/net/fou.h | 10 +--
include/net/inet_common.h | 5 ++
include/net/ip6_tunnel.h | 22 +++++-
net/core/ethtool.c | 1 +
net/ipv4/af_inet.c | 30 ++-------
net/ipv4/fou.c | 144 ++++++++++++++++++++++++----------------
net/ipv4/gre_offload.c | 14 ----
net/ipv4/tcp_offload.c | 19 ------
net/ipv4/udp_offload.c | 20 ++----
net/ipv6/Makefile | 4 +-
net/ipv6/fou6.c | 140 ++++++++++++++++++++++++++++++++++++++
net/ipv6/ip6_gre.c | 95 +++++++++++++++++++++++---
net/ipv6/ip6_input.c | 24 +++++--
net/ipv6/ip6_offload.c | 76 +++++++++++++++------
net/ipv6/ip6_tunnel.c | 101 ++++++++++++++++++++++++++--
net/ipv6/ip6_tunnel_core.c | 108 ++++++++++++++++++++++++++++++
net/ipv6/udp_offload.c | 13 ----
20 files changed, 652 insertions(+), 188 deletions(-)
create mode 100644 net/ipv6/fou6.c
create mode 100644 net/ipv6/ip6_tunnel_core.c
--
2.8.0.rc2
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH net-next 01/14] gso: Remove arbitrary checks for unsupported GSO
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 2:59 ` Alexander Duyck
2016-05-05 1:02 ` [PATCH net-next 02/14] gre6: Fix flag translations Tom Herbert
` (12 subsequent siblings)
13 siblings, 1 reply; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
In several gso_segment functions there are checks of gso_type against
a seemingly abitrary 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 -------------
6 files changed, 92 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 097060de..b556ef6 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);
--
2.8.0.rc2
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH net-next 02/14] gre6: Fix flag translations
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 01/14] gso: Remove arbitrary checks for unsupported GSO Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 03/14] udp: Don't set skb->encapsulation with RCO Tom Herbert
` (11 subsequent siblings)
13 siblings, 0 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
GRE for IPv6 does not properly translate for GRE flags to tunnel
flags and vice versa. This patch fixes that.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
net/ipv6/ip6_gre.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 1012774..c827ae8 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -798,8 +798,8 @@ static void ip6gre_tnl_parm_from_user(struct __ip6_tnl_parm *p,
p->link = u->link;
p->i_key = u->i_key;
p->o_key = u->o_key;
- p->i_flags = u->i_flags;
- p->o_flags = u->o_flags;
+ p->i_flags = gre_flags_to_tnl_flags(u->i_flags);
+ p->o_flags = gre_flags_to_tnl_flags(u->o_flags);
memcpy(p->name, u->name, sizeof(u->name));
}
@@ -816,8 +816,8 @@ static void ip6gre_tnl_parm_to_user(struct ip6_tnl_parm2 *u,
u->link = p->link;
u->i_key = p->i_key;
u->o_key = p->o_key;
- u->i_flags = p->i_flags;
- u->o_flags = p->o_flags;
+ u->i_flags = gre_tnl_flags_to_gre_flags(p->i_flags);
+ u->o_flags = gre_tnl_flags_to_gre_flags(p->o_flags);
memcpy(u->name, p->name, sizeof(u->name));
}
@@ -1216,10 +1216,12 @@ static void ip6gre_netlink_parms(struct nlattr *data[],
parms->link = nla_get_u32(data[IFLA_GRE_LINK]);
if (data[IFLA_GRE_IFLAGS])
- parms->i_flags = nla_get_be16(data[IFLA_GRE_IFLAGS]);
+ parms->i_flags = gre_flags_to_tnl_flags(
+ nla_get_be16(data[IFLA_GRE_IFLAGS]));
if (data[IFLA_GRE_OFLAGS])
- parms->o_flags = nla_get_be16(data[IFLA_GRE_OFLAGS]);
+ parms->o_flags = gre_flags_to_tnl_flags(
+ nla_get_be16(data[IFLA_GRE_OFLAGS]));
if (data[IFLA_GRE_IKEY])
parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]);
@@ -1411,8 +1413,10 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
struct __ip6_tnl_parm *p = &t->parms;
if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
- nla_put_be16(skb, IFLA_GRE_IFLAGS, p->i_flags) ||
- nla_put_be16(skb, IFLA_GRE_OFLAGS, p->o_flags) ||
+ nla_put_be16(skb, IFLA_GRE_IFLAGS,
+ gre_tnl_flags_to_gre_flags(p->i_flags)) ||
+ nla_put_be16(skb, IFLA_GRE_OFLAGS,
+ gre_tnl_flags_to_gre_flags(p->o_flags)) ||
nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
nla_put_in6_addr(skb, IFLA_GRE_LOCAL, &p->laddr) ||
--
2.8.0.rc2
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH net-next 03/14] udp: Don't set skb->encapsulation with RCO
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 01/14] gso: Remove arbitrary checks for unsupported GSO Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 02/14] gre6: Fix flag translations Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 2:42 ` Alexander Duyck
2016-05-05 1:02 ` [PATCH net-next 04/14] fou: Call setup_udp_tunnel_sock Tom Herbert
` (10 subsequent siblings)
13 siblings, 1 reply; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
When RCO is in effect we want to ensure that the outer checksum is
properly offloaded. Don't set skb->encapsulation in this case to
ensure that checksum offload is later considered for hw_features
instead of hw_enc_features.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
net/ipv4/udp_offload.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index b556ef6..4eedec6 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -94,11 +94,13 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
do {
unsigned int len;
- if (remcsum)
+ if (remcsum) {
skb->ip_summed = CHECKSUM_NONE;
-
- /* Set up inner headers if we are offloading inner checksum */
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ skb->encapsulation = 0;
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ /* Set up inner headers if we are offloading inner
+ * checksum
+ */
skb_reset_inner_headers(skb);
skb->encapsulation = 1;
}
--
2.8.0.rc2
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH net-next 04/14] fou: Call setup_udp_tunnel_sock
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
` (2 preceding siblings ...)
2016-05-05 1:02 ` [PATCH net-next 03/14] udp: Don't set skb->encapsulation with RCO Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 05/14] fou: Split out {fou,gue}_build_header Tom Herbert
` (9 subsequent siblings)
13 siblings, 0 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 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 7ac5ec8..a8b5cbf 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -446,31 +446,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 */
@@ -489,33 +471,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] 25+ messages in thread
* [PATCH net-next 05/14] fou: Split out {fou,gue}_build_header
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
` (3 preceding siblings ...)
2016-05-05 1:02 ` [PATCH net-next 04/14] fou: Call setup_udp_tunnel_sock Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 06/14] fou: Add encap ops for IPv6 tunnels Tom Herbert
` (8 subsequent siblings)
13 siblings, 0 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 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 a8b5cbf..971c8c6 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -778,6 +778,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)
{
@@ -786,26 +802,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;
@@ -824,8 +835,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;
@@ -870,6 +881,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] 25+ messages in thread
* [PATCH net-next 06/14] fou: Add encap ops for IPv6 tunnels
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
` (4 preceding siblings ...)
2016-05-05 1:02 ` [PATCH net-next 05/14] fou: Split out {fou,gue}_build_header Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 07/14] ipv6: Fix nexthdr for reinjection Tom Herbert
` (7 subsequent siblings)
13 siblings, 0 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Thsi packet adds IP tunnel encapsulation operations for IPv6. This
includes the infrastructure to add and delete operations. IPv6 variants
for fou6_build_header and gue6_build_header are added in a new
fou6 module. These encapsulation operations for fou and gue are
automatically added when the fou6 module loads.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/net/fou.h | 2 +-
include/net/ip6_tunnel.h | 14 +++++
net/ipv6/Makefile | 4 +-
net/ipv6/fou6.c | 140 +++++++++++++++++++++++++++++++++++++++++++++
net/ipv6/ip6_tunnel_core.c | 44 ++++++++++++++
5 files changed, 202 insertions(+), 2 deletions(-)
create mode 100644 net/ipv6/fou6.c
create mode 100644 net/ipv6/ip6_tunnel_core.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/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index fb9e015..1c14c27 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -34,6 +34,20 @@ struct __ip6_tnl_parm {
__be32 o_key;
};
+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 *op,
+ unsigned int num);
+int ip6_tnl_encap_del_ops(const struct ip6_tnl_encap_ops *op,
+ unsigned int num);
+
/* IPv6 tunnel */
struct ip6_tnl {
struct ip6_tnl __rcu *next; /* next tunnel in list */
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 5e9d6bf..5cf4a1f 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -9,7 +9,7 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \
exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o \
- udp_offload.o
+ udp_offload.o ip6_tunnel_core.o
ipv6-offload := ip6_offload.o tcpv6_offload.o exthdrs_offload.o
@@ -43,6 +43,8 @@ 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");
diff --git a/net/ipv6/ip6_tunnel_core.c b/net/ipv6/ip6_tunnel_core.c
new file mode 100644
index 0000000..5f5b79e
--- /dev/null
+++ b/net/ipv6/ip6_tunnel_core.c
@@ -0,0 +1,44 @@
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/if.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/net.h>
+#include <linux/in6.h>
+#include <net/ip6_tunnel.h>
+
+const struct ip6_tnl_encap_ops __rcu *
+ ip6tun_encaps[MAX_IPTUN_ENCAP_OPS] __read_mostly;
+EXPORT_SYMBOL(ip6tun_encaps);
+
+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);
+
--
2.8.0.rc2
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH net-next 07/14] ipv6: Fix nexthdr for reinjection
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
` (5 preceding siblings ...)
2016-05-05 1:02 ` [PATCH net-next 06/14] fou: Add encap ops for IPv6 tunnels Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 08/14] ipv6: Change "final" protocol processing for encapsulation Tom Herbert
` (6 subsequent siblings)
13 siblings, 0 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
In ip6_input_finish the protocol handle returns a value greater than
zero the packet needs to be resubmitted using the returned protocol.
The returned protocol is being ignored and each time through resubmit
nexthdr is taken from an offest in the packet. This patch fixes that
so that nexthdr is taken from return value of the protocol handler.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
net/ipv6/ip6_input.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 6ed5601..2a0258a 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -222,13 +222,14 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk
*/
rcu_read_lock();
-resubmit:
+
idev = ip6_dst_idev(skb_dst(skb));
if (!pskb_pull(skb, skb_transport_offset(skb)))
goto discard;
nhoff = IP6CB(skb)->nhoff;
nexthdr = skb_network_header(skb)[nhoff];
+resubmit:
raw = raw6_local_deliver(skb, nexthdr);
ipprot = rcu_dereference(inet6_protos[nexthdr]);
if (ipprot) {
@@ -256,10 +257,12 @@ resubmit:
goto discard;
ret = ipprot->handler(skb);
- if (ret > 0)
+ if (ret > 0) {
+ nexthdr = ret;
goto resubmit;
- else if (ret == 0)
+ } 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] 25+ messages in thread
* [PATCH net-next 08/14] ipv6: Change "final" protocol processing for encapsulation
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
` (6 preceding siblings ...)
2016-05-05 1:02 ` [PATCH net-next 07/14] ipv6: Fix nexthdr for reinjection Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 09/14] fou: Support IPv6 in fou Tom Herbert
` (5 subsequent siblings)
13 siblings, 0 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
When performing foo-over-UDP, UDP are receveived processed by the
encapsulation header 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.
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 2a0258a..7d98d01 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -216,6 +216,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
@@ -235,9 +236,21 @@ resubmit:
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] 25+ messages in thread
* [PATCH net-next 09/14] fou: Support IPv6 in fou
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
` (7 preceding siblings ...)
2016-05-05 1:02 ` [PATCH net-next 08/14] ipv6: Change "final" protocol processing for encapsulation Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 10/14] ip6_tun: Add infrastructure for doing encapsulation Tom Herbert
` (4 subsequent siblings)
13 siblings, 0 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 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 971c8c6..00100d9 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.
@@ -424,7 +432,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;
}
@@ -469,8 +478,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;
@@ -522,12 +532,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;
@@ -565,8 +576,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;
}
@@ -657,6 +675,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);
@@ -666,6 +685,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;
@@ -673,7 +696,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] 25+ messages in thread
* [PATCH net-next 10/14] ip6_tun: Add infrastructure for doing encapsulation
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
` (8 preceding siblings ...)
2016-05-05 1:02 ` [PATCH net-next 09/14] fou: Support IPv6 in fou Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 11/14] ip6_gre: Add support for fou/gue encapsulation Tom Herbert
` (3 subsequent siblings)
13 siblings, 0 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 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 | 8 +++++-
net/ipv6/ip6_tunnel.c | 4 +++
net/ipv6/ip6_tunnel_core.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h
index 1c14c27..1b8db86 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -66,10 +66,16 @@ 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;
-
};
+int ip6_tnl_encap_setup(struct ip6_tnl *t,
+ struct ip_tunnel_encap *ipencap);
+int ip6_tnl_encap(struct sk_buff *skb, struct ip6_tnl *t,
+ u8 *protocol, struct flowi6 *fl6);
+
/* Tunnel encapsulation limit destination sub-option */
struct ipv6_tlv_tnl_enc_lim {
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index ade55af..2c096ab 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1013,6 +1013,10 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
unsigned int max_headroom = sizeof(struct ipv6hdr);
int err = -1;
+ err = ip6_tnl_encap(skb, t, &proto, fl6);
+ if (err)
+ return err;
+
/* NBMA tunnel */
if (ipv6_addr_any(&t->parms.raddr)) {
struct in6_addr *addr6;
diff --git a/net/ipv6/ip6_tunnel_core.c b/net/ipv6/ip6_tunnel_core.c
index 5f5b79e..94aa414 100644
--- a/net/ipv6/ip6_tunnel_core.c
+++ b/net/ipv6/ip6_tunnel_core.c
@@ -42,3 +42,67 @@ int ip6_tnl_encap_del_ops(const struct ip6_tnl_encap_ops *ops,
}
EXPORT_SYMBOL(ip6_tnl_encap_del_ops);
+static 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;
+}
+
+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);
+
+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;
+}
+EXPORT_SYMBOL(ip6_tnl_encap);
--
2.8.0.rc2
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH net-next 11/14] ip6_gre: Add support for fou/gue encapsulation
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
` (9 preceding siblings ...)
2016-05-05 1:02 ` [PATCH net-next 10/14] ip6_tun: Add infrastructure for doing encapsulation Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 12/14] ip6_tunnel: " Tom Herbert
` (2 subsequent siblings)
13 siblings, 0 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 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 | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index c827ae8..2beb212 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1026,6 +1026,8 @@ 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->encap_hlen;
+
t_hlen = tunnel->hlen + sizeof(struct ipv6hdr);
dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;
@@ -1292,15 +1294,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))
@@ -1347,10 +1391,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);
@@ -1404,6 +1456,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;
}
@@ -1427,6 +1487,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:
@@ -1445,6 +1516,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] 25+ messages in thread
* [PATCH net-next 12/14] ip6_tunnel: Add support for fou/gue encapsulation
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
` (10 preceding siblings ...)
2016-05-05 1:02 ` [PATCH net-next 11/14] ip6_gre: Add support for fou/gue encapsulation Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 13/14] ip6ip6: Support for GSO/GRO Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 14/14] ip4ip6: " Tom Herbert
13 siblings, 0 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 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 | 89 +++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 83 insertions(+), 6 deletions(-)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 2c096ab..0e72af4 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1067,7 +1067,8 @@ 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) - dev->hard_header_len -
+ sizeof(*ipv6h);
if (encap_limit >= 0) {
max_headroom += 8;
mtu -= 8;
@@ -1131,7 +1132,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
}
max_headroom = LL_RESERVED_SPACE(dst->dev) + sizeof(struct ipv6hdr)
- + dst->header_len;
+ + dst->header_len + t->encap_hlen;
if (max_headroom > dev->needed_headroom)
dev->needed_headroom = max_headroom;
@@ -1322,9 +1323,10 @@ 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);
+ sizeof(struct ipv6hdr) + t->hlen;
- dev->mtu = rt->dst.dev->mtu - sizeof(struct ipv6hdr);
+ dev->mtu = rt->dst.dev->mtu - sizeof(struct ipv6hdr) -
+ t->hlen;
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
dev->mtu -= 8;
@@ -1598,12 +1600,13 @@ static void ip6_tnl_dev_setup(struct net_device *dev)
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);
+ dev->mtu = ETH_DATA_LEN - sizeof(struct ipv6hdr) - t->hlen;
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;
@@ -1621,6 +1624,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);
@@ -1636,8 +1640,9 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
if (ret)
goto destroy_dst;
- t->hlen = 0;
t->tun_hlen = 0;
+ t->hlen = t->tun_hlen + t->encap_hlen;
+ t_hlen = t->hlen + sizeof(struct ipv6hdr);
return 0;
@@ -1735,13 +1740,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);
@@ -1758,10 +1805,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);
@@ -1802,6 +1856,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;
}
@@ -1819,6 +1881,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:
@@ -1842,6 +1915,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] 25+ messages in thread
* [PATCH net-next 13/14] ip6ip6: Support for GSO/GRO
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
` (11 preceding siblings ...)
2016-05-05 1:02 ` [PATCH net-next 12/14] ip6_tunnel: " Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 14/14] ip4ip6: " Tom Herbert
13 siblings, 0 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/linux/netdev_features.h | 5 ++++-
include/linux/netdevice.h | 1 +
include/linux/skbuff.h | 2 ++
net/core/ethtool.c | 1 +
net/ipv6/ip6_offload.c | 27 +++++++++++++++++++++++----
net/ipv6/ip6_tunnel.c | 3 +++
6 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index bc87362..db52030 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -53,8 +53,9 @@ enum {
* headers in software.
*/
NETIF_F_GSO_TUNNEL_REMCSUM_BIT, /* ... TUNNEL with TSO & REMCSUM */
+ NETIF_F_GSO_IP6IP6_BIT, /* ... IP6IP6 tunnel with TSO */
/**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */
- NETIF_F_GSO_TUNNEL_REMCSUM_BIT,
+ NETIF_F_GSO_IP6IP6_BIT,
NETIF_F_FCOE_CRC_BIT, /* FCoE CRC32 */
NETIF_F_SCTP_CRC_BIT, /* SCTP checksum offload */
@@ -122,6 +123,7 @@ enum {
#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_IP6IP6 __NETIF_F(GSO_IP6IP6)
#define NETIF_F_GSO_SIT __NETIF_F(GSO_SIT)
#define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL)
#define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM)
@@ -201,6 +203,7 @@ enum {
#define NETIF_F_GSO_ENCAP_ALL (NETIF_F_GSO_GRE | \
NETIF_F_GSO_GRE_CSUM | \
NETIF_F_GSO_IPIP | \
+ NETIF_F_GSO_IP6IP6 | \
NETIF_F_GSO_SIT | \
NETIF_F_GSO_UDP_TUNNEL | \
NETIF_F_GSO_UDP_TUNNEL_CSUM)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f218259..724b9d5 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4005,6 +4005,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
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_IP6IP6 != (NETIF_F_GSO_IP6IP6 >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_SIT != (NETIF_F_GSO_SIT >> 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));
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index c413c58..928b456 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -482,6 +482,8 @@ enum {
SKB_GSO_PARTIAL = 1 << 13,
SKB_GSO_TUNNEL_REMCSUM = 1 << 14,
+
+ SKB_GSO_IP6IP6 = 1 << 15,
};
#if BITS_PER_LONG > 32
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index bdb4013..a6a6dde 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -85,6 +85,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
[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_IP6IP6_BIT] = "tx-ip6ip6-segmentation",
[NETIF_F_GSO_SIT_BIT] = "tx-sit-segmentation",
[NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation",
[NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT] = "tx-udp_tnl-csum-segmentation",
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 9ad743b..cea42ad 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -86,7 +86,8 @@ 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_SIT | SKB_GSO_IPIP |
+ SKB_GSO_IP6IP6))
udpfrag = proto == IPPROTO_UDP && encap;
else
udpfrag = proto == IPPROTO_UDP && !skb->encapsulation;
@@ -253,9 +254,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 +301,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_IP6IP6;
+ 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 +320,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 +344,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 0e72af4..0d01cef 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1241,6 +1241,9 @@ 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_IP6IP6))
+ return -1;
+
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] 25+ messages in thread
* [PATCH net-next 14/14] ip4ip6: Support for GSO/GRO
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
` (12 preceding siblings ...)
2016-05-05 1:02 ` [PATCH net-next 13/14] ip6ip6: Support for GSO/GRO Tom Herbert
@ 2016-05-05 1:02 ` Tom Herbert
2016-05-05 1:20 ` Eric Dumazet
13 siblings, 1 reply; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 1:02 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/linux/netdev_features.h | 5 ++++-
include/linux/netdevice.h | 1 +
include/linux/skbuff.h | 2 ++
include/net/inet_common.h | 5 +++++
net/ipv4/af_inet.c | 12 +++++++-----
net/ipv6/ip6_offload.c | 33 ++++++++++++++++++++++++++++++++-
net/ipv6/ip6_tunnel.c | 5 ++++-
7 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index db52030..d30ea91 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -54,8 +54,9 @@ enum {
*/
NETIF_F_GSO_TUNNEL_REMCSUM_BIT, /* ... TUNNEL with TSO & REMCSUM */
NETIF_F_GSO_IP6IP6_BIT, /* ... IP6IP6 tunnel with TSO */
+ NETIF_F_GSO_IP4IP6_BIT, /* ... IP4IP6 tunnel with TSO */
/**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */
- NETIF_F_GSO_IP6IP6_BIT,
+ NETIF_F_GSO_IP4IP6_BIT,
NETIF_F_FCOE_CRC_BIT, /* FCoE CRC32 */
NETIF_F_SCTP_CRC_BIT, /* SCTP checksum offload */
@@ -125,6 +126,7 @@ enum {
#define NETIF_F_GSO_IPIP __NETIF_F(GSO_IPIP)
#define NETIF_F_GSO_IP6IP6 __NETIF_F(GSO_IP6IP6)
#define NETIF_F_GSO_SIT __NETIF_F(GSO_SIT)
+#define NETIF_F_GSO_IP4IP6 __NETIF_F(GSO_IP4IP6)
#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)
@@ -204,6 +206,7 @@ enum {
NETIF_F_GSO_GRE_CSUM | \
NETIF_F_GSO_IPIP | \
NETIF_F_GSO_IP6IP6 | \
+ NETIF_F_GSO_IP4IP6 | \
NETIF_F_GSO_SIT | \
NETIF_F_GSO_UDP_TUNNEL | \
NETIF_F_GSO_UDP_TUNNEL_CSUM)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 724b9d5..4fa678a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -4006,6 +4006,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
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_IP6IP6 != (NETIF_F_GSO_IP6IP6 >> NETIF_F_GSO_SHIFT));
+ BUILD_BUG_ON(SKB_GSO_IP4IP6 != (NETIF_F_GSO_IP4IP6 >> NETIF_F_GSO_SHIFT));
BUILD_BUG_ON(SKB_GSO_SIT != (NETIF_F_GSO_SIT >> 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));
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 928b456..6a811fa 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -484,6 +484,8 @@ enum {
SKB_GSO_TUNNEL_REMCSUM = 1 << 14,
SKB_GSO_IP6IP6 = 1 << 15,
+
+ SKB_GSO_IP4IP6 = 1 << 16,
};
#if BITS_PER_LONG > 32
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 7f08d45..9d2bf87 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 cea42ad..507f701 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"
@@ -269,6 +270,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;
@@ -308,6 +324,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_IP4IP6;
+ return inet_gro_complete(skb, nhoff);
+}
+
static struct packet_offload ipv6_packet_offload __read_mostly = {
.type = cpu_to_be16(ETH_P_IPV6),
.callbacks = {
@@ -325,6 +348,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,
@@ -332,7 +363,6 @@ static const struct net_offload ip6ip6_offload = {
.gro_complete = ip6ip6_gro_complete,
},
};
-
static int __init ipv6_offload_init(void)
{
@@ -345,6 +375,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 0d01cef..7ad31b6 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -897,7 +897,7 @@ drop:
static int ip4ip6_rcv(struct sk_buff *skb)
{
- return ipxip6_rcv(skb, IPPROTO_IP, &tpi_v4,
+ return ipxip6_rcv(skb, IPPROTO_IPIP, &tpi_v4,
ip4ip6_dscp_ecn_decapsulate);
}
@@ -1187,6 +1187,9 @@ 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_IP4IP6))
+ return -1;
+
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] 25+ messages in thread
* Re: [PATCH net-next 14/14] ip4ip6: Support for GSO/GRO
2016-05-05 1:02 ` [PATCH net-next 14/14] ip4ip6: " Tom Herbert
@ 2016-05-05 1:20 ` Eric Dumazet
2016-05-05 3:26 ` Alexander Duyck
0 siblings, 1 reply; 25+ messages in thread
From: Eric Dumazet @ 2016-05-05 1:20 UTC (permalink / raw)
To: Tom Herbert; +Cc: davem, netdev, kernel-team
On Wed, 2016-05-04 at 18:02 -0700, Tom Herbert wrote:
> Signed-off-by: Tom Herbert <tom@herbertland.com>
> ---
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 928b456..6a811fa 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -484,6 +484,8 @@ enum {
> SKB_GSO_TUNNEL_REMCSUM = 1 << 14,
>
> SKB_GSO_IP6IP6 = 1 << 15,
> +
> + SKB_GSO_IP4IP6 = 1 << 16,
> };
>
Houston, we have a problem.
gso_type is 16bit (unsigned short), or maybe I missed something ?
struct skb_shared_info {
unsigned char nr_frags;
__u8 tx_flags;
unsigned short gso_size;
unsigned short gso_segs;
unsigned short gso_type; <<-->>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next 03/14] udp: Don't set skb->encapsulation with RCO
2016-05-05 1:02 ` [PATCH net-next 03/14] udp: Don't set skb->encapsulation with RCO Tom Herbert
@ 2016-05-05 2:42 ` Alexander Duyck
2016-05-05 15:38 ` Tom Herbert
0 siblings, 1 reply; 25+ messages in thread
From: Alexander Duyck @ 2016-05-05 2:42 UTC (permalink / raw)
To: Tom Herbert; +Cc: David Miller, Netdev, Kernel Team
On Wed, May 4, 2016 at 6:02 PM, Tom Herbert <tom@herbertland.com> wrote:
> When RCO is in effect we want to ensure that the outer checksum is
> properly offloaded. Don't set skb->encapsulation in this case to
> ensure that checksum offload is later considered for hw_features
> instead of hw_enc_features.
>
> Signed-off-by: Tom Herbert <tom@herbertland.com>
> ---
> net/ipv4/udp_offload.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
> index b556ef6..4eedec6 100644
> --- a/net/ipv4/udp_offload.c
> +++ b/net/ipv4/udp_offload.c
> @@ -94,11 +94,13 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
> do {
> unsigned int len;
>
> - if (remcsum)
> + if (remcsum) {
> skb->ip_summed = CHECKSUM_NONE;
> -
> - /* Set up inner headers if we are offloading inner checksum */
> - if (skb->ip_summed == CHECKSUM_PARTIAL) {
> + skb->encapsulation = 0;
> + } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
> + /* Set up inner headers if we are offloading inner
> + * checksum
> + */
> skb_reset_inner_headers(skb);
> skb->encapsulation = 1;
> }
Why are you wasting cycles clearing a value that should have already
been cleared?
We set skb->encapsulation to 0 for the incoming skb before we segment
it. As such all of the segments we get should also not have it set.
It seems like you are just wasting cycles writing it again even though
it isn't written.
- Alex
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next 01/14] gso: Remove arbitrary checks for unsupported GSO
2016-05-05 1:02 ` [PATCH net-next 01/14] gso: Remove arbitrary checks for unsupported GSO Tom Herbert
@ 2016-05-05 2:59 ` Alexander Duyck
2016-05-05 16:09 ` Alexander Duyck
0 siblings, 1 reply; 25+ messages in thread
From: Alexander Duyck @ 2016-05-05 2:59 UTC (permalink / raw)
To: Tom Herbert; +Cc: David Miller, Netdev, Kernel Team
On Wed, May 4, 2016 at 6:02 PM, Tom Herbert <tom@herbertland.com> wrote:
> In several gso_segment functions there are checks of gso_type against
> a seemingly abitrary 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.
You would think that was the case. The problem is I have already seen
one issue with GUE allowing an unsupported combination of GRE_CSUM and
UDP tunnels.
> This is a code simplication especially for add new GSO types.
I'd say you might be better off going through and just putting in
place a few specific restrictions with a WARN_ONCE or something like
that.
> 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 -------------
> 6 files changed, 92 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;
> -
This can go. It basically just reads like a feature list for GSO.
> 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;
> -
This is trying to catch that specific case I mentioned where GRE and
UDP are being applied to the same tunnel. We should have a mutual
exclusion on them, but UDP is getting around it by skipping over the
GRE header in its offload. If GRE contains a UDP tunnel we definitely
should throw something like a WARN_ONCE. I'd say just test for the
UDP_TUNNEL and UDP_TUNNEL_CSUM bits though until GRE and UDP_TUNNEL
can find a way to deal with sharing the inner_mac_header.
> 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;
This could probably be reduced to a check for SKB_GSO_UDP.
> 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 097060de..b556ef6 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;
This could be reduced to a check for the GSO types specific to TCP.
> 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;
> -
You could drop this one.
> 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;
This is another one where all that is being checked for is TCP.
> skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
>
> --
> 2.8.0.rc2
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next 14/14] ip4ip6: Support for GSO/GRO
2016-05-05 1:20 ` Eric Dumazet
@ 2016-05-05 3:26 ` Alexander Duyck
2016-05-05 16:48 ` Tom Herbert
0 siblings, 1 reply; 25+ messages in thread
From: Alexander Duyck @ 2016-05-05 3:26 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Tom Herbert, David Miller, Netdev, Kernel Team
On Wed, May 4, 2016 at 6:20 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Wed, 2016-05-04 at 18:02 -0700, Tom Herbert wrote:
>> Signed-off-by: Tom Herbert <tom@herbertland.com>
>> ---
>> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
>> index 928b456..6a811fa 100644
>> --- a/include/linux/skbuff.h
>> +++ b/include/linux/skbuff.h
>> @@ -484,6 +484,8 @@ enum {
>> SKB_GSO_TUNNEL_REMCSUM = 1 << 14,
>>
>> SKB_GSO_IP6IP6 = 1 << 15,
>> +
>> + SKB_GSO_IP4IP6 = 1 << 16,
>> };
>>
>
> Houston, we have a problem.
>
> gso_type is 16bit (unsigned short), or maybe I missed something ?
>
> struct skb_shared_info {
> unsigned char nr_frags;
> __u8 tx_flags;
> unsigned short gso_size;
> unsigned short gso_segs;
> unsigned short gso_type; <<-->>
No, I am pretty sure you have it right. We are out of bits.
Also it seems like we are generating a number of duplicate entries.
What is the difference between IP6IP6 and SIT over IPv6? I'm not
really seeing the difference.
I'm wondering if maybe we shouldn't look at the possibly using the
IPIP and SIT bits to instead indicate that the frame is encapsulated
in an outer IPv4 or outer IPv6 header since we already have TCPV4 and
TCPV6 to indicate if the inner network type is a V4 or V6. Then there
is no need for this patch set to introduce any new tunnel types to be
segmented since all cases should be covered. As far as I can tell
SKB_GSO_IPIP/SIT were never really being tested against anyway so we
might want to go the IPIPV4 IPIPV6 route instead as that is probably
closer to what most device limitations would be.
- Alex
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next 03/14] udp: Don't set skb->encapsulation with RCO
2016-05-05 2:42 ` Alexander Duyck
@ 2016-05-05 15:38 ` Tom Herbert
2016-05-05 15:44 ` Alexander Duyck
0 siblings, 1 reply; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 15:38 UTC (permalink / raw)
To: Alexander Duyck; +Cc: David Miller, Netdev, Kernel Team
On Wed, May 4, 2016 at 7:42 PM, Alexander Duyck
<alexander.duyck@gmail.com> wrote:
> On Wed, May 4, 2016 at 6:02 PM, Tom Herbert <tom@herbertland.com> wrote:
>> When RCO is in effect we want to ensure that the outer checksum is
>> properly offloaded. Don't set skb->encapsulation in this case to
>> ensure that checksum offload is later considered for hw_features
>> instead of hw_enc_features.
>>
>> Signed-off-by: Tom Herbert <tom@herbertland.com>
>> ---
>> net/ipv4/udp_offload.c | 10 ++++++----
>> 1 file changed, 6 insertions(+), 4 deletions(-)
>>
>> diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
>> index b556ef6..4eedec6 100644
>> --- a/net/ipv4/udp_offload.c
>> +++ b/net/ipv4/udp_offload.c
>> @@ -94,11 +94,13 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
>> do {
>> unsigned int len;
>>
>> - if (remcsum)
>> + if (remcsum) {
>> skb->ip_summed = CHECKSUM_NONE;
>> -
>> - /* Set up inner headers if we are offloading inner checksum */
>> - if (skb->ip_summed == CHECKSUM_PARTIAL) {
>> + skb->encapsulation = 0;
>> + } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
>> + /* Set up inner headers if we are offloading inner
>> + * checksum
>> + */
>> skb_reset_inner_headers(skb);
>> skb->encapsulation = 1;
>> }
>
>
> Why are you wasting cycles clearing a value that should have already
> been cleared?
>
> We set skb->encapsulation to 0 for the incoming skb before we segment
> it. As such all of the segments we get should also not have it set.
> It seems like you are just wasting cycles writing it again even though
> it isn't written.
>
I believe this is needed because skb->encapsulation could have been
set at a lower inner GRO, like if we were encapsulating GRE in UDP...
Tom
> - Alex
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next 03/14] udp: Don't set skb->encapsulation with RCO
2016-05-05 15:38 ` Tom Herbert
@ 2016-05-05 15:44 ` Alexander Duyck
0 siblings, 0 replies; 25+ messages in thread
From: Alexander Duyck @ 2016-05-05 15:44 UTC (permalink / raw)
To: Tom Herbert; +Cc: David Miller, Netdev, Kernel Team
On Thu, May 5, 2016 at 8:38 AM, Tom Herbert <tom@herbertland.com> wrote:
> On Wed, May 4, 2016 at 7:42 PM, Alexander Duyck
> <alexander.duyck@gmail.com> wrote:
>> On Wed, May 4, 2016 at 6:02 PM, Tom Herbert <tom@herbertland.com> wrote:
>>> When RCO is in effect we want to ensure that the outer checksum is
>>> properly offloaded. Don't set skb->encapsulation in this case to
>>> ensure that checksum offload is later considered for hw_features
>>> instead of hw_enc_features.
>>>
>>> Signed-off-by: Tom Herbert <tom@herbertland.com>
>>> ---
>>> net/ipv4/udp_offload.c | 10 ++++++----
>>> 1 file changed, 6 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
>>> index b556ef6..4eedec6 100644
>>> --- a/net/ipv4/udp_offload.c
>>> +++ b/net/ipv4/udp_offload.c
>>> @@ -94,11 +94,13 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
>>> do {
>>> unsigned int len;
>>>
>>> - if (remcsum)
>>> + if (remcsum) {
>>> skb->ip_summed = CHECKSUM_NONE;
>>> -
>>> - /* Set up inner headers if we are offloading inner checksum */
>>> - if (skb->ip_summed == CHECKSUM_PARTIAL) {
>>> + skb->encapsulation = 0;
>>> + } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
>>> + /* Set up inner headers if we are offloading inner
>>> + * checksum
>>> + */
>>> skb_reset_inner_headers(skb);
>>> skb->encapsulation = 1;
>>> }
>>
>>
>> Why are you wasting cycles clearing a value that should have already
>> been cleared?
>>
>> We set skb->encapsulation to 0 for the incoming skb before we segment
>> it. As such all of the segments we get should also not have it set.
>> It seems like you are just wasting cycles writing it again even though
>> it isn't written.
>>
> I believe this is needed because skb->encapsulation could have been
> set at a lower inner GRO, like if we were encapsulating GRE in UDP...
That cannot happen. The GRE header processing is completely skipped
as we use the inner_mac_header to determine the next header to jump
to. The L3 types use encap_level and we reset that as well so there
should be no risk of skb->encapsulation being set for a remote
checksum offloaded frame.
- Alex
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next 01/14] gso: Remove arbitrary checks for unsupported GSO
2016-05-05 2:59 ` Alexander Duyck
@ 2016-05-05 16:09 ` Alexander Duyck
2016-05-05 16:11 ` Tom Herbert
0 siblings, 1 reply; 25+ messages in thread
From: Alexander Duyck @ 2016-05-05 16:09 UTC (permalink / raw)
To: Tom Herbert; +Cc: David Miller, Netdev, Kernel Team
On Wed, May 4, 2016 at 7:59 PM, Alexander Duyck
<alexander.duyck@gmail.com> wrote:
> On Wed, May 4, 2016 at 6:02 PM, Tom Herbert <tom@herbertland.com> wrote:
>> In several gso_segment functions there are checks of gso_type against
>> a seemingly abitrary 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.
>
> You would think that was the case. The problem is I have already seen
> one issue with GUE allowing an unsupported combination of GRE_CSUM and
> UDP tunnels.
I thought about this some more and it isn't as if the checks would
have caught this anyway as the GRE bits were being skipped over. I'd
say we can probably just drop all these checks and save ourselves the
space. So I retract my earlier comments against this specific patch
and will Ack it when we get the issues with the other patches in the
series resolved.
- Alex
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next 01/14] gso: Remove arbitrary checks for unsupported GSO
2016-05-05 16:09 ` Alexander Duyck
@ 2016-05-05 16:11 ` Tom Herbert
0 siblings, 0 replies; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 16:11 UTC (permalink / raw)
To: Alexander Duyck; +Cc: David Miller, Netdev, Kernel Team
On Thu, May 5, 2016 at 9:09 AM, Alexander Duyck
<alexander.duyck@gmail.com> wrote:
> On Wed, May 4, 2016 at 7:59 PM, Alexander Duyck
> <alexander.duyck@gmail.com> wrote:
>> On Wed, May 4, 2016 at 6:02 PM, Tom Herbert <tom@herbertland.com> wrote:
>>> In several gso_segment functions there are checks of gso_type against
>>> a seemingly abitrary 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.
>>
>> You would think that was the case. The problem is I have already seen
>> one issue with GUE allowing an unsupported combination of GRE_CSUM and
>> UDP tunnels.
>
> I thought about this some more and it isn't as if the checks would
> have caught this anyway as the GRE bits were being skipped over. I'd
> say we can probably just drop all these checks and save ourselves the
> space. So I retract my earlier comments against this specific patch
> and will Ack it when we get the issues with the other patches in the
> series resolved.
>
Wow, you sent this ten seconds before I hit send for a well crafted reply. :-)
Thanks,
Tom
> - Alex
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next 14/14] ip4ip6: Support for GSO/GRO
2016-05-05 3:26 ` Alexander Duyck
@ 2016-05-05 16:48 ` Tom Herbert
2016-05-05 17:48 ` Alexander Duyck
0 siblings, 1 reply; 25+ messages in thread
From: Tom Herbert @ 2016-05-05 16:48 UTC (permalink / raw)
To: Alexander Duyck; +Cc: Eric Dumazet, David Miller, Netdev, Kernel Team
On Wed, May 4, 2016 at 8:26 PM, Alexander Duyck
<alexander.duyck@gmail.com> wrote:
> On Wed, May 4, 2016 at 6:20 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>> On Wed, 2016-05-04 at 18:02 -0700, Tom Herbert wrote:
>>> Signed-off-by: Tom Herbert <tom@herbertland.com>
>>> ---
>>> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
>>> index 928b456..6a811fa 100644
>>> --- a/include/linux/skbuff.h
>>> +++ b/include/linux/skbuff.h
>>> @@ -484,6 +484,8 @@ enum {
>>> SKB_GSO_TUNNEL_REMCSUM = 1 << 14,
>>>
>>> SKB_GSO_IP6IP6 = 1 << 15,
>>> +
>>> + SKB_GSO_IP4IP6 = 1 << 16,
>>> };
>>>
>>
>> Houston, we have a problem.
>>
>> gso_type is 16bit (unsigned short), or maybe I missed something ?
>>
>> struct skb_shared_info {
>> unsigned char nr_frags;
>> __u8 tx_flags;
>> unsigned short gso_size;
>> unsigned short gso_segs;
>> unsigned short gso_type; <<-->>
>
> No, I am pretty sure you have it right. We are out of bits.
>
> Also it seems like we are generating a number of duplicate entries.
> What is the difference between IP6IP6 and SIT over IPv6? I'm not
> really seeing the difference.
>
> I'm wondering if maybe we shouldn't look at the possibly using the
> IPIP and SIT bits to instead indicate that the frame is encapsulated
> in an outer IPv4 or outer IPv6 header since we already have TCPV4 and
> TCPV6 to indicate if the inner network type is a V4 or V6. Then there
> is no need for this patch set to introduce any new tunnel types to be
> segmented since all cases should be covered. As far as I can tell
> SKB_GSO_IPIP/SIT were never really being tested against anyway so we
> might want to go the IPIPV4 IPIPV6 route instead as that is probably
> closer to what most device limitations would be.
>
My worry is that the current public interface means IPIP is IPv4 over
IPv4, and SIT means IPv6 over IPv4. There are some drivers advertising
offload support for these so I don't think we safely redefine
SKB_GSO_IPIP/SIT.
For finding more bits in gso_type there are some SKB_GOS_* that are
not really types at all but more flags. I'm going try to turn
SKB_GSO_DODGY into a skbuff for the purposes here. We'll still have
the problem of running out bits next time a new type is added (maybe
SKB_GSO_SCTP?) but can probably make room for one or two more. Longer
term I think the the solution is too eliminate gso_type altogether as
we are once again running into the problem of trying to indicate a
combinatorial set of constraints and complex layering in a just few
flag bits.
Tom
> - Alex
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH net-next 14/14] ip4ip6: Support for GSO/GRO
2016-05-05 16:48 ` Tom Herbert
@ 2016-05-05 17:48 ` Alexander Duyck
0 siblings, 0 replies; 25+ messages in thread
From: Alexander Duyck @ 2016-05-05 17:48 UTC (permalink / raw)
To: Tom Herbert; +Cc: Eric Dumazet, David Miller, Netdev, Kernel Team
On Thu, May 5, 2016 at 9:48 AM, Tom Herbert <tom@herbertland.com> wrote:
> On Wed, May 4, 2016 at 8:26 PM, Alexander Duyck
> <alexander.duyck@gmail.com> wrote:
>> On Wed, May 4, 2016 at 6:20 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>>> On Wed, 2016-05-04 at 18:02 -0700, Tom Herbert wrote:
>>>> Signed-off-by: Tom Herbert <tom@herbertland.com>
>>>> ---
>>>> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
>>>> index 928b456..6a811fa 100644
>>>> --- a/include/linux/skbuff.h
>>>> +++ b/include/linux/skbuff.h
>>>> @@ -484,6 +484,8 @@ enum {
>>>> SKB_GSO_TUNNEL_REMCSUM = 1 << 14,
>>>>
>>>> SKB_GSO_IP6IP6 = 1 << 15,
>>>> +
>>>> + SKB_GSO_IP4IP6 = 1 << 16,
>>>> };
>>>>
>>>
>>> Houston, we have a problem.
>>>
>>> gso_type is 16bit (unsigned short), or maybe I missed something ?
>>>
>>> struct skb_shared_info {
>>> unsigned char nr_frags;
>>> __u8 tx_flags;
>>> unsigned short gso_size;
>>> unsigned short gso_segs;
>>> unsigned short gso_type; <<-->>
>>
>> No, I am pretty sure you have it right. We are out of bits.
>>
>> Also it seems like we are generating a number of duplicate entries.
>> What is the difference between IP6IP6 and SIT over IPv6? I'm not
>> really seeing the difference.
>>
>> I'm wondering if maybe we shouldn't look at the possibly using the
>> IPIP and SIT bits to instead indicate that the frame is encapsulated
>> in an outer IPv4 or outer IPv6 header since we already have TCPV4 and
>> TCPV6 to indicate if the inner network type is a V4 or V6. Then there
>> is no need for this patch set to introduce any new tunnel types to be
>> segmented since all cases should be covered. As far as I can tell
>> SKB_GSO_IPIP/SIT were never really being tested against anyway so we
>> might want to go the IPIPV4 IPIPV6 route instead as that is probably
>> closer to what most device limitations would be.
>>
> My worry is that the current public interface means IPIP is IPv4 over
> IPv4, and SIT means IPv6 over IPv4. There are some drivers advertising
> offload support for these so I don't think we safely redefine
> SKB_GSO_IPIP/SIT.
The group is pretty small, and they all advertise support for SIT and
IPIP. Even if they don't support an outer IPv6 tunnel it just means
we are essentially combining the 2 bits into 1.
In the case of the Intel drivers that advertise support for it they
could support the change without any issue since the use the header
pointers to set the offsets of the inner and outer headers and don't
care if they are v4 or v6.
> For finding more bits in gso_type there are some SKB_GOS_* that are
> not really types at all but more flags. I'm going try to turn
> SKB_GSO_DODGY into a skbuff for the purposes here. We'll still have
> the problem of running out bits next time a new type is added (maybe
> SKB_GSO_SCTP?) but can probably make room for one or two more. Longer
> term I think the the solution is too eliminate gso_type altogether as
> we are once again running into the problem of trying to indicate a
> combinatorial set of constraints and complex layering in a just few
> flag bits.
Still, I don't think there is much gain to be had by specifying the
inner network type twice, once in the outer tunnel segmentation type,
and then again in the inner TCP segmentation type. That is why I was
thinking it would be better to just specify an IPIPV4 and IPIPV6 since
then you can run v4 or v6 on the inside and let TSOV4 or TSOV6 in the
hw_enc_features take care of specifying if you can support inner IPV6
or not.
- Alex
^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2016-05-05 17:48 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-05 1:02 [PATCH net-next 00/14] ipv6: Enable GUEoIPv6 and more fixes for v6 tunneling Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 01/14] gso: Remove arbitrary checks for unsupported GSO Tom Herbert
2016-05-05 2:59 ` Alexander Duyck
2016-05-05 16:09 ` Alexander Duyck
2016-05-05 16:11 ` Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 02/14] gre6: Fix flag translations Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 03/14] udp: Don't set skb->encapsulation with RCO Tom Herbert
2016-05-05 2:42 ` Alexander Duyck
2016-05-05 15:38 ` Tom Herbert
2016-05-05 15:44 ` Alexander Duyck
2016-05-05 1:02 ` [PATCH net-next 04/14] fou: Call setup_udp_tunnel_sock Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 05/14] fou: Split out {fou,gue}_build_header Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 06/14] fou: Add encap ops for IPv6 tunnels Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 07/14] ipv6: Fix nexthdr for reinjection Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 08/14] ipv6: Change "final" protocol processing for encapsulation Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 09/14] fou: Support IPv6 in fou Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 10/14] ip6_tun: Add infrastructure for doing encapsulation Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 11/14] ip6_gre: Add support for fou/gue encapsulation Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 12/14] ip6_tunnel: " Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 13/14] ip6ip6: Support for GSO/GRO Tom Herbert
2016-05-05 1:02 ` [PATCH net-next 14/14] ip4ip6: " Tom Herbert
2016-05-05 1:20 ` Eric Dumazet
2016-05-05 3:26 ` Alexander Duyck
2016-05-05 16:48 ` Tom Herbert
2016-05-05 17:48 ` Alexander Duyck
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).