Skip to content

Commit

Permalink
ip_tunnel: push generic protocol handling to ip_tunnel module.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Pravin B Shelar authored and David S. Miller committed Jun 20, 2013
1 parent 0e6fbc5 commit 3d7b46c
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 27 deletions.
1 change: 1 addition & 0 deletions include/net/ip_tunnels.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion net/ipv4/gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
30 changes: 6 additions & 24 deletions net/ipv4/ip_tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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! */
Expand Down Expand Up @@ -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)
Expand All @@ -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;

Expand Down
34 changes: 34 additions & 0 deletions net/ipv4/ip_tunnel_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
6 changes: 5 additions & 1 deletion net/ipv4/ipip.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
7 changes: 6 additions & 1 deletion net/ipv6/sit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 3d7b46c

Please sign in to comment.