From 00b2034029840ddad255352c46db0ae21342ce56 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 3 May 2016 17:10:06 +0200 Subject: gre: remove superfluous pskb_may_pull The call to gre_parse_header is either followed by iptunnel_pull_header, or in the case of ICMP error path, the actual header is not accessed at all. In the first case, iptunnel_pull_header will call pskb_may_pull anyway and it's pointless to do it twice. The only difference is what call will fail with what error code but the net effect is still the same in all call sites. In the second case, pskb_may_pull is pointless, as skb->data is at the outer IP header and not at the GRE header. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c index a41e73a..d78e2ee 100644 --- a/net/ipv4/gre_demux.c +++ b/net/ipv4/gre_demux.c @@ -114,11 +114,8 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, */ if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) { tpi->proto = htons(ETH_P_IP); - if ((*(u8 *)options & 0xF0) != 0x40) { + if ((*(u8 *)options & 0xF0) != 0x40) hdr_len += 4; - if (!pskb_may_pull(skb, hdr_len)) - return -EINVAL; - } } return hdr_len; } -- cgit v0.10.2 From 244a797bdcf1b74567fa59d7e72d89ed0ee1ffd9 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 3 May 2016 17:10:07 +0200 Subject: gre: move iptunnel_pull_header down to ipgre_rcv This will allow to make the pull dependent on the tunnel type. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 8260a70..8f377da 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -260,7 +260,8 @@ static __be32 tunnel_id_to_key(__be64 x) #endif } -static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) +static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + int hdr_len) { struct net *net = dev_net(skb->dev); struct metadata_dst *tun_dst = NULL; @@ -278,6 +279,9 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) iph->saddr, iph->daddr, tpi->key); if (tunnel) { + if (iptunnel_pull_header(skb, hdr_len, tpi->proto, false) < 0) + goto drop; + skb_pop_mac_header(skb); if (tunnel->collect_md) { __be16 flags; @@ -294,6 +298,10 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) return PACKET_RCVD; } return PACKET_REJECT; + +drop: + kfree_skb(skb); + return PACKET_RCVD; } static int gre_rcv(struct sk_buff *skb) @@ -314,10 +322,7 @@ static int gre_rcv(struct sk_buff *skb) if (hdr_len < 0) goto drop; - if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false)) - goto drop; - - if (ipgre_rcv(skb, &tpi) == PACKET_RCVD) + if (ipgre_rcv(skb, &tpi, hdr_len) == PACKET_RCVD) return 0; icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); -- cgit v0.10.2 From 125372faa4feb15e86f410c1adabbca9186d9c4a Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 3 May 2016 17:10:08 +0200 Subject: gre: receive also TEB packets for lwtunnels For ipgre interfaces in collect metadata mode, receive also traffic with encapsulated Ethernet headers. The lwtunnel users are supposed to sort this out correctly. This allows to have mixed Ethernet + L3-only traffic on the same lwtunnel interface. This is the same way as VXLAN-GPE behaves. To keep backwards compatibility and prevent any surprises, gretap interfaces have priority in receiving packets with Ethernet headers. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 6d79091..d916b43 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -160,6 +160,7 @@ struct tnl_ptk_info { #define PACKET_RCVD 0 #define PACKET_REJECT 1 +#define PACKET_NEXT 2 #define IP_TNL_HASH_BITS 7 #define IP_TNL_HASH_SIZE (1 << IP_TNL_HASH_BITS) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 8f377da..2b267e7 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -260,26 +260,20 @@ static __be32 tunnel_id_to_key(__be64 x) #endif } -static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, - int hdr_len) +static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + struct ip_tunnel_net *itn, int hdr_len, bool raw_proto) { - struct net *net = dev_net(skb->dev); struct metadata_dst *tun_dst = NULL; - struct ip_tunnel_net *itn; const struct iphdr *iph; struct ip_tunnel *tunnel; - if (tpi->proto == htons(ETH_P_TEB)) - itn = net_generic(net, gre_tap_net_id); - else - itn = net_generic(net, ipgre_net_id); - iph = ip_hdr(skb); tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, iph->saddr, iph->daddr, tpi->key); if (tunnel) { - if (iptunnel_pull_header(skb, hdr_len, tpi->proto, false) < 0) + if (__iptunnel_pull_header(skb, hdr_len, tpi->proto, + raw_proto, false) < 0) goto drop; skb_pop_mac_header(skb); @@ -297,13 +291,36 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, ip_tunnel_rcv(tunnel, skb, tpi, tun_dst, log_ecn_error); return PACKET_RCVD; } - return PACKET_REJECT; + return PACKET_NEXT; drop: kfree_skb(skb); return PACKET_RCVD; } +static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + int hdr_len) +{ + struct net *net = dev_net(skb->dev); + struct ip_tunnel_net *itn; + int res; + + if (tpi->proto == htons(ETH_P_TEB)) + itn = net_generic(net, gre_tap_net_id); + else + itn = net_generic(net, ipgre_net_id); + + res = __ipgre_rcv(skb, tpi, itn, hdr_len, false); + if (res == PACKET_NEXT && tpi->proto == htons(ETH_P_TEB)) { + /* ipgre tunnels in collect metadata mode should receive + * also ETH_P_TEB traffic. + */ + itn = net_generic(net, ipgre_net_id); + res = __ipgre_rcv(skb, tpi, itn, hdr_len, true); + } + return res; +} + static int gre_rcv(struct sk_buff *skb) { struct tnl_ptk_info tpi; -- cgit v0.10.2