diff options
author | Pravin B Shelar <pshelar@nicira.com> | 2013-06-17 20:50:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-19 21:07:41 -0400 |
commit | 3d7b46cd20e300bd6989fb1f43d46f1b9645816e (patch) | |
tree | b8a063f8ecb7e380f0e1672a60815ff48c3f9b56 /net | |
parent | 0e6fbc5b6c6218987c93b8c7ca60cf786062899d (diff) |
ip_tunnel: push generic protocol handling to ip_tunnel module.
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/gre.c | 3 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel.c | 30 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel_core.c | 34 | ||||
-rw-r--r-- | net/ipv4/ipip.c | 6 | ||||
-rw-r--r-- | net/ipv6/sit.c | 7 |
5 files changed, 53 insertions, 27 deletions
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c index 5ecc9c49b4dc..ba4803e609b5 100644 --- a/net/ipv4/gre.c +++ b/net/ipv4/gre.c | |||
@@ -201,7 +201,8 @@ static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, | |||
201 | return -EINVAL; | 201 | return -EINVAL; |
202 | } | 202 | } |
203 | } | 203 | } |
204 | return 0; | 204 | |
205 | return iptunnel_pull_header(skb, hdr_len, tpi->proto); | ||
205 | } | 206 | } |
206 | 207 | ||
207 | static int gre_cisco_rcv(struct sk_buff *skb) | 208 | static int gre_cisco_rcv(struct sk_buff *skb) |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index a06a2ed49597..bd227e5ea9da 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -408,13 +408,6 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, | |||
408 | const struct iphdr *iph = ip_hdr(skb); | 408 | const struct iphdr *iph = ip_hdr(skb); |
409 | int err; | 409 | int err; |
410 | 410 | ||
411 | secpath_reset(skb); | ||
412 | |||
413 | skb->protocol = tpi->proto; | ||
414 | |||
415 | skb->mac_header = skb->network_header; | ||
416 | __pskb_pull(skb, tunnel->hlen); | ||
417 | skb_postpull_rcsum(skb, skb_transport_header(skb), tunnel->hlen); | ||
418 | #ifdef CONFIG_NET_IPGRE_BROADCAST | 411 | #ifdef CONFIG_NET_IPGRE_BROADCAST |
419 | if (ipv4_is_multicast(iph->daddr)) { | 412 | if (ipv4_is_multicast(iph->daddr)) { |
420 | /* Looped back packet, drop it! */ | 413 | /* Looped back packet, drop it! */ |
@@ -442,23 +435,6 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, | |||
442 | tunnel->i_seqno = ntohl(tpi->seq) + 1; | 435 | tunnel->i_seqno = ntohl(tpi->seq) + 1; |
443 | } | 436 | } |
444 | 437 | ||
445 | /* Warning: All skb pointers will be invalidated! */ | ||
446 | if (tunnel->dev->type == ARPHRD_ETHER) { | ||
447 | if (!pskb_may_pull(skb, ETH_HLEN)) { | ||
448 | tunnel->dev->stats.rx_length_errors++; | ||
449 | tunnel->dev->stats.rx_errors++; | ||
450 | goto drop; | ||
451 | } | ||
452 | |||
453 | iph = ip_hdr(skb); | ||
454 | skb->protocol = eth_type_trans(skb, tunnel->dev); | ||
455 | skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); | ||
456 | } | ||
457 | |||
458 | skb->pkt_type = PACKET_HOST; | ||
459 | __skb_tunnel_rx(skb, tunnel->dev); | ||
460 | |||
461 | skb_reset_network_header(skb); | ||
462 | err = IP_ECN_decapsulate(iph, skb); | 438 | err = IP_ECN_decapsulate(iph, skb); |
463 | if (unlikely(err)) { | 439 | if (unlikely(err)) { |
464 | if (log_ecn_error) | 440 | if (log_ecn_error) |
@@ -477,6 +453,12 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, | |||
477 | tstats->rx_bytes += skb->len; | 453 | tstats->rx_bytes += skb->len; |
478 | u64_stats_update_end(&tstats->syncp); | 454 | u64_stats_update_end(&tstats->syncp); |
479 | 455 | ||
456 | if (tunnel->dev->type == ARPHRD_ETHER) { | ||
457 | skb->protocol = eth_type_trans(skb, tunnel->dev); | ||
458 | skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); | ||
459 | } else { | ||
460 | skb->dev = tunnel->dev; | ||
461 | } | ||
480 | gro_cells_receive(&tunnel->gro_cells, skb); | 462 | gro_cells_receive(&tunnel->gro_cells, skb); |
481 | return 0; | 463 | return 0; |
482 | 464 | ||
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 927687e83f18..7167b08977df 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c | |||
@@ -86,3 +86,37 @@ int iptunnel_xmit(struct net *net, struct rtable *rt, | |||
86 | return pkt_len; | 86 | return pkt_len; |
87 | } | 87 | } |
88 | EXPORT_SYMBOL_GPL(iptunnel_xmit); | 88 | EXPORT_SYMBOL_GPL(iptunnel_xmit); |
89 | |||
90 | int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto) | ||
91 | { | ||
92 | if (unlikely(!pskb_may_pull(skb, hdr_len))) | ||
93 | return -ENOMEM; | ||
94 | |||
95 | skb_pull_rcsum(skb, hdr_len); | ||
96 | |||
97 | if (inner_proto == htons(ETH_P_TEB)) { | ||
98 | struct ethhdr *eh = (struct ethhdr *)skb->data; | ||
99 | |||
100 | if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | if (likely(ntohs(eh->h_proto) >= ETH_P_802_3_MIN)) | ||
104 | skb->protocol = eh->h_proto; | ||
105 | else | ||
106 | skb->protocol = htons(ETH_P_802_2); | ||
107 | |||
108 | } else { | ||
109 | skb->protocol = inner_proto; | ||
110 | } | ||
111 | |||
112 | nf_reset(skb); | ||
113 | secpath_reset(skb); | ||
114 | if (!skb->l4_rxhash) | ||
115 | skb->rxhash = 0; | ||
116 | skb_dst_drop(skb); | ||
117 | skb->vlan_tci = 0; | ||
118 | skb_set_queue_mapping(skb, 0); | ||
119 | skb->pkt_type = PACKET_HOST; | ||
120 | return 0; | ||
121 | } | ||
122 | EXPORT_SYMBOL_GPL(iptunnel_pull_header); | ||
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 9df7ecd393f2..e6905fbda2a2 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -188,8 +188,12 @@ static int ipip_rcv(struct sk_buff *skb) | |||
188 | struct net *net = dev_net(skb->dev); | 188 | struct net *net = dev_net(skb->dev); |
189 | struct ip_tunnel_net *itn = net_generic(net, ipip_net_id); | 189 | struct ip_tunnel_net *itn = net_generic(net, ipip_net_id); |
190 | struct ip_tunnel *tunnel; | 190 | struct ip_tunnel *tunnel; |
191 | const struct iphdr *iph = ip_hdr(skb); | 191 | const struct iphdr *iph; |
192 | 192 | ||
193 | if (iptunnel_pull_header(skb, 0, tpi.proto)) | ||
194 | goto drop; | ||
195 | |||
196 | iph = ip_hdr(skb); | ||
193 | tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, | 197 | tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, |
194 | iph->saddr, iph->daddr, 0); | 198 | iph->saddr, iph->daddr, 0); |
195 | if (tunnel) { | 199 | if (tunnel) { |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 76bb8de435b2..6cee844678e2 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -640,9 +640,14 @@ static const struct tnl_ptk_info tpi = { | |||
640 | 640 | ||
641 | static int ipip_rcv(struct sk_buff *skb) | 641 | static int ipip_rcv(struct sk_buff *skb) |
642 | { | 642 | { |
643 | const struct iphdr *iph = ip_hdr(skb); | 643 | const struct iphdr *iph; |
644 | struct ip_tunnel *tunnel; | 644 | struct ip_tunnel *tunnel; |
645 | 645 | ||
646 | if (iptunnel_pull_header(skb, 0, tpi.proto)) | ||
647 | goto drop; | ||
648 | |||
649 | iph = ip_hdr(skb); | ||
650 | |||
646 | tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev, | 651 | tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev, |
647 | iph->saddr, iph->daddr); | 652 | iph->saddr, iph->daddr); |
648 | if (tunnel != NULL) { | 653 | if (tunnel != NULL) { |