]> Pileus Git - ~andy/linux/commitdiff
ip_tunnel: push generic protocol handling to ip_tunnel module.
authorPravin B Shelar <pshelar@nicira.com>
Tue, 18 Jun 2013 00:50:02 +0000 (17:50 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 20 Jun 2013 01:07:41 +0000 (18:07 -0700)
Process skb tunnel header before sending packet to protocol handler.
this allows code sharing between gre and ovs gre modules.

Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip_tunnels.h
net/ipv4/gre.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_tunnel_core.c
net/ipv4/ipip.c
net/ipv6/sit.c

index b84f1ab09d78ebd2668ed2ed8dd0a4d4f793dbf3..32e130b560fa697e334bfaaecf613234acdb060f 100644 (file)
@@ -155,6 +155,7 @@ static inline void tunnel_ip_select_ident(struct sk_buff *skb,
                                  (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 }
 
+int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto);
 int iptunnel_xmit(struct net *net, struct rtable *rt,
                  struct sk_buff *skb,
                  __be32 src, __be32 dst, __u8 proto,
index 5ecc9c49b4dc28e5584eadc9752baf37b930a227..ba4803e609b5fb0636e90d59099afc261868aa4f 100644 (file)
@@ -201,7 +201,8 @@ static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
                                return -EINVAL;
                }
        }
-       return 0;
+
+       return iptunnel_pull_header(skb, hdr_len, tpi->proto);
 }
 
 static int gre_cisco_rcv(struct sk_buff *skb)
index a06a2ed49597ade4922eb3c15cb98bb16b46e5b3..bd227e5ea9dae9cd9d43fdb762f37e59a26d11fe 100644 (file)
@@ -408,13 +408,6 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
        const struct iphdr *iph = ip_hdr(skb);
        int err;
 
-       secpath_reset(skb);
-
-       skb->protocol = tpi->proto;
-
-       skb->mac_header = skb->network_header;
-       __pskb_pull(skb, tunnel->hlen);
-       skb_postpull_rcsum(skb, skb_transport_header(skb), tunnel->hlen);
 #ifdef CONFIG_NET_IPGRE_BROADCAST
        if (ipv4_is_multicast(iph->daddr)) {
                /* Looped back packet, drop it! */
@@ -442,23 +435,6 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
                tunnel->i_seqno = ntohl(tpi->seq) + 1;
        }
 
-       /* Warning: All skb pointers will be invalidated! */
-       if (tunnel->dev->type == ARPHRD_ETHER) {
-               if (!pskb_may_pull(skb, ETH_HLEN)) {
-                       tunnel->dev->stats.rx_length_errors++;
-                       tunnel->dev->stats.rx_errors++;
-                       goto drop;
-               }
-
-               iph = ip_hdr(skb);
-               skb->protocol = eth_type_trans(skb, tunnel->dev);
-               skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
-       }
-
-       skb->pkt_type = PACKET_HOST;
-       __skb_tunnel_rx(skb, tunnel->dev);
-
-       skb_reset_network_header(skb);
        err = IP_ECN_decapsulate(iph, skb);
        if (unlikely(err)) {
                if (log_ecn_error)
@@ -477,6 +453,12 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
        tstats->rx_bytes += skb->len;
        u64_stats_update_end(&tstats->syncp);
 
+       if (tunnel->dev->type == ARPHRD_ETHER) {
+               skb->protocol = eth_type_trans(skb, tunnel->dev);
+               skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
+       } else {
+               skb->dev = tunnel->dev;
+       }
        gro_cells_receive(&tunnel->gro_cells, skb);
        return 0;
 
index 927687e83f182788c76651d9439d4f7129a7de17..7167b08977df582bd38565cf960568a8553f29d4 100644 (file)
@@ -86,3 +86,37 @@ int iptunnel_xmit(struct net *net, struct rtable *rt,
        return pkt_len;
 }
 EXPORT_SYMBOL_GPL(iptunnel_xmit);
+
+int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto)
+{
+       if (unlikely(!pskb_may_pull(skb, hdr_len)))
+               return -ENOMEM;
+
+       skb_pull_rcsum(skb, hdr_len);
+
+       if (inner_proto == htons(ETH_P_TEB)) {
+               struct ethhdr *eh = (struct ethhdr *)skb->data;
+
+               if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
+                       return -ENOMEM;
+
+               if (likely(ntohs(eh->h_proto) >= ETH_P_802_3_MIN))
+                       skb->protocol = eh->h_proto;
+               else
+                       skb->protocol = htons(ETH_P_802_2);
+
+       } else {
+               skb->protocol = inner_proto;
+       }
+
+       nf_reset(skb);
+       secpath_reset(skb);
+       if (!skb->l4_rxhash)
+               skb->rxhash = 0;
+       skb_dst_drop(skb);
+       skb->vlan_tci = 0;
+       skb_set_queue_mapping(skb, 0);
+       skb->pkt_type = PACKET_HOST;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(iptunnel_pull_header);
index 9df7ecd393f20246d5fcb0246cdf5c35323eb4be..e6905fbda2a2981ebc5e9f347265507ec2154f27 100644 (file)
@@ -188,8 +188,12 @@ static int ipip_rcv(struct sk_buff *skb)
        struct net *net = dev_net(skb->dev);
        struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
        struct ip_tunnel *tunnel;
-       const struct iphdr *iph = ip_hdr(skb);
+       const struct iphdr *iph;
 
+       if (iptunnel_pull_header(skb, 0, tpi.proto))
+               goto drop;
+
+       iph = ip_hdr(skb);
        tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
                        iph->saddr, iph->daddr, 0);
        if (tunnel) {
index 76bb8de435b25064359f6acbcc15d26750c4fd53..6cee844678e2418c2fefc84ddbfd9c34584ea613 100644 (file)
@@ -640,9 +640,14 @@ static const struct tnl_ptk_info tpi = {
 
 static int ipip_rcv(struct sk_buff *skb)
 {
-       const struct iphdr *iph = ip_hdr(skb);
+       const struct iphdr *iph;
        struct ip_tunnel *tunnel;
 
+       if (iptunnel_pull_header(skb, 0, tpi.proto))
+               goto drop;
+
+       iph = ip_hdr(skb);
+
        tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev,
                                     iph->saddr, iph->daddr);
        if (tunnel != NULL) {