mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 14:12:06 +00:00
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
@ -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 New Issue
Block a user