/* * This function assumes it is being called from dev_queue_xmit() * and that skb is filled properly by that function. */ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); const struct iphdr *tiph; struct iphdr fiph; if (unlikely(skb->protocol != htons(ETH_P_IP))) goto tx_error; skb = iptunnel_handle_offloads(skb, false, SKB_GSO_IPIP); if (IS_ERR(skb)) goto out; if (ipip_tunnel_is_fan(tunnel)) { if (ipip_build_fan_iphdr(tunnel, skb, &fiph)) goto tx_error; tiph = &fiph; } else { tiph = &tunnel->parms.iph; } skb_set_inner_ipproto(skb, IPPROTO_IPIP); ip_tunnel_xmit(skb, dev, tiph, tiph->protocol); return NETDEV_TX_OK; tx_error: kfree_skb(skb); out: dev->stats.tx_errors++; return NETDEV_TX_OK; }
/* * This function assumes it is being called from dev_queue_xmit() * and that skb is filled properly by that function. */ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); const struct iphdr *tiph = &tunnel->parms.iph; u8 ipproto; switch (skb->protocol) { case htons(ETH_P_IP): ipproto = IPPROTO_IPIP; break; #if IS_ENABLED(CONFIG_MPLS) case htons(ETH_P_MPLS_UC): ipproto = IPPROTO_MPLS; break; #endif default: goto tx_error; } if (tiph->protocol != ipproto && tiph->protocol != 0) goto tx_error; if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4)) goto tx_error; skb_set_inner_ipproto(skb, ipproto); if (tunnel->collect_md) ip_md_tunnel_xmit(skb, dev, ipproto); else ip_tunnel_xmit(skb, dev, tiph, ipproto); return NETDEV_TX_OK; tx_error: kfree_skb(skb); dev->stats.tx_errors++; return NETDEV_TX_OK; }
/* * This function assumes it is being called from dev_queue_xmit() * and that skb is filled properly by that function. */ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); const struct iphdr *tiph = &tunnel->parms.iph; struct net_device *mcdev; /* madcap device */ #ifdef OVBENCH if (SKB_OVBENCH (skb)) { skb->ipip_tunnel_xmit_in = rdtsc (); } #endif if (unlikely(skb->protocol != htons(ETH_P_IP))) goto tx_error; skb = iptunnel_handle_offloads(skb, false, SKB_GSO_IPIP); if (IS_ERR(skb)) goto out; if (madcap_enable) { mcdev = __dev_get_by_index (dev_net (dev), tunnel->parms.link); if (mcdev && get_madcap_ops (mcdev)) { madcap_queue_xmit (skb, mcdev); return NETDEV_TX_OK; } } skb_set_inner_ipproto(skb, IPPROTO_IPIP); ip_tunnel_xmit(skb, dev, tiph, tiph->protocol); return NETDEV_TX_OK; tx_error: kfree_skb(skb); out: dev->stats.tx_errors++; return NETDEV_TX_OK; }