forked from mirrors/linux
		
	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>
This commit is contained in:
		
							parent
							
								
									0e6fbc5b6c
								
							
						
					
					
						commit
						3d7b46cd20
					
				
					 6 changed files with 54 additions and 27 deletions
				
			
		| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue