vxlan: Bypass encapsulation if the destination is local
This patch bypasses vxlan encapsulation if the destination vxlan endpoint is a local device. Changes since v1: added missing check for vxlan_find_vni() failure Signed-off-by: Sridhar Samudrala <sri@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c4637cdf48
commit
9dcc71e1fd
|
@ -912,6 +912,36 @@ static int handle_offloads(struct sk_buff *skb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bypass encapsulation if the destination is local */
|
||||||
|
static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
|
||||||
|
struct vxlan_dev *dst_vxlan)
|
||||||
|
{
|
||||||
|
struct pcpu_tstats *tx_stats = this_cpu_ptr(src_vxlan->dev->tstats);
|
||||||
|
struct pcpu_tstats *rx_stats = this_cpu_ptr(dst_vxlan->dev->tstats);
|
||||||
|
|
||||||
|
skb->pkt_type = PACKET_HOST;
|
||||||
|
skb->encapsulation = 0;
|
||||||
|
skb->dev = dst_vxlan->dev;
|
||||||
|
__skb_pull(skb, skb_network_offset(skb));
|
||||||
|
|
||||||
|
if (dst_vxlan->flags & VXLAN_F_LEARN)
|
||||||
|
vxlan_snoop(skb->dev, INADDR_LOOPBACK, eth_hdr(skb)->h_source);
|
||||||
|
|
||||||
|
u64_stats_update_begin(&tx_stats->syncp);
|
||||||
|
tx_stats->tx_packets++;
|
||||||
|
tx_stats->tx_bytes += skb->len;
|
||||||
|
u64_stats_update_end(&tx_stats->syncp);
|
||||||
|
|
||||||
|
if (netif_rx(skb) == NET_RX_SUCCESS) {
|
||||||
|
u64_stats_update_begin(&rx_stats->syncp);
|
||||||
|
rx_stats->rx_packets++;
|
||||||
|
rx_stats->rx_bytes += skb->len;
|
||||||
|
u64_stats_update_end(&rx_stats->syncp);
|
||||||
|
} else {
|
||||||
|
skb->dev->stats.rx_dropped++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||||
struct vxlan_rdst *rdst, bool did_rsc)
|
struct vxlan_rdst *rdst, bool did_rsc)
|
||||||
{
|
{
|
||||||
|
@ -922,7 +952,6 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||||
struct vxlanhdr *vxh;
|
struct vxlanhdr *vxh;
|
||||||
struct udphdr *uh;
|
struct udphdr *uh;
|
||||||
struct flowi4 fl4;
|
struct flowi4 fl4;
|
||||||
unsigned int pkt_len = skb->len;
|
|
||||||
__be32 dst;
|
__be32 dst;
|
||||||
__u16 src_port, dst_port;
|
__u16 src_port, dst_port;
|
||||||
u32 vni;
|
u32 vni;
|
||||||
|
@ -935,22 +964,8 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||||
|
|
||||||
if (!dst) {
|
if (!dst) {
|
||||||
if (did_rsc) {
|
if (did_rsc) {
|
||||||
__skb_pull(skb, skb_network_offset(skb));
|
|
||||||
skb->ip_summed = CHECKSUM_NONE;
|
|
||||||
skb->pkt_type = PACKET_HOST;
|
|
||||||
|
|
||||||
/* short-circuited back to local bridge */
|
/* short-circuited back to local bridge */
|
||||||
if (netif_rx(skb) == NET_RX_SUCCESS) {
|
vxlan_encap_bypass(skb, vxlan, vxlan);
|
||||||
struct pcpu_tstats *stats = this_cpu_ptr(dev->tstats);
|
|
||||||
|
|
||||||
u64_stats_update_begin(&stats->syncp);
|
|
||||||
stats->tx_packets++;
|
|
||||||
stats->tx_bytes += pkt_len;
|
|
||||||
u64_stats_update_end(&stats->syncp);
|
|
||||||
} else {
|
|
||||||
dev->stats.tx_errors++;
|
|
||||||
dev->stats.tx_aborted_errors++;
|
|
||||||
}
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
goto drop;
|
goto drop;
|
||||||
|
@ -997,6 +1012,18 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||||
goto tx_error;
|
goto tx_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bypass encapsulation if the destination is local */
|
||||||
|
if (rt->rt_flags & RTCF_LOCAL) {
|
||||||
|
struct vxlan_dev *dst_vxlan;
|
||||||
|
|
||||||
|
ip_rt_put(rt);
|
||||||
|
dst_vxlan = vxlan_find_vni(dev_net(dev), vni);
|
||||||
|
if (!dst_vxlan)
|
||||||
|
goto tx_error;
|
||||||
|
vxlan_encap_bypass(skb, vxlan, dst_vxlan);
|
||||||
|
return NETDEV_TX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
|
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
|
||||||
IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
|
IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
|
||||||
IPSKB_REROUTED);
|
IPSKB_REROUTED);
|
||||||
|
|
Loading…
Reference in New Issue