static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) { struct net *net = dev_net(skb->dev); struct metadata_dst tun_dst; struct ip_tunnel_net *itn; const struct iphdr *iph; struct ip_tunnel *tunnel; if (tpi->proto != htons(ETH_P_TEB)) return PACKET_REJECT; itn = net_generic(net, gre_tap_net_id); iph = ip_hdr(skb); tunnel = rcu_dereference(itn->collect_md_tun); if (tunnel) { __be16 flags; __be64 tun_id; int err; skb_pop_mac_header(skb); flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); tun_id = key_to_tunnel_id(tpi->key); ovs_ip_tun_rx_dst(&tun_dst, skb, flags, tun_id, 0); skb_reset_network_header(skb); err = IP_ECN_decapsulate(iph, skb); if (unlikely(err)) { if (err > 1) { ++tunnel->dev->stats.rx_frame_errors; ++tunnel->dev->stats.rx_errors; return PACKET_REJECT; } } ovs_ip_tunnel_rcv(tunnel->dev, skb, &tun_dst); return PACKET_RCVD; } return PACKET_REJECT; }
static int __ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi, struct ip_tunnel_net *itn, int hdr_len, bool raw_proto) { struct metadata_dst tun_dst; const struct iphdr *iph; struct ip_tunnel *tunnel; iph = ip_hdr(skb); tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, iph->saddr, iph->daddr, tpi->key); if (tunnel) { if (__iptunnel_pull_header(skb, hdr_len, tpi->proto, raw_proto, false) < 0) goto drop; if (tunnel->dev->type != ARPHRD_NONE) skb_pop_mac_header(skb); else skb_reset_mac_header(skb); if (tunnel->collect_md) { __be16 flags; __be64 tun_id; flags = tpi->flags & (TUNNEL_CSUM | TUNNEL_KEY); tun_id = key32_to_tunnel_id(tpi->key); ovs_ip_tun_rx_dst(&tun_dst, skb, flags, tun_id, 0); } ovs_ip_tunnel_rcv(tunnel->dev, skb, &tun_dst); return PACKET_RCVD; } return PACKET_NEXT; drop: kfree_skb(skb); return PACKET_RCVD; }