diff options
author | Jiri Benc <jbenc@redhat.com> | 2016-02-23 18:02:56 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-02-25 15:17:11 -0500 |
commit | 1ab016e237e7d0734fb7adbbfe6d4cacb3520421 (patch) | |
tree | d7c134822db274d438fffd1f261a11dbaeaae5f1 | |
parent | 64f87d3616a01c53262c6e0e948d62df15923f1c (diff) |
vxlan: move inner L2 header processing to a separate function
This code will be different for VXLAN-GPE, so move it to a separate
function. It will also make the rx path less spaghetti-like.
Signed-off-by: Jiri Benc <jbenc@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/vxlan.c | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 656a303c0ac8..68a8f9f43e2a 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1191,15 +1191,11 @@ out: unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS; } -static void vxlan_rcv(struct vxlan_dev *vxlan, struct vxlan_sock *vs, - struct sk_buff *skb, struct vxlan_metadata *md, - struct metadata_dst *tun_dst) +static bool vxlan_set_mac(struct vxlan_dev *vxlan, + struct vxlan_sock *vs, + struct sk_buff *skb) { - struct iphdr *oip = NULL; - struct ipv6hdr *oip6 = NULL; - struct pcpu_sw_netstats *stats; union vxlan_addr saddr; - int err = 0; skb_reset_mac_header(skb); skb->protocol = eth_type_trans(skb, vxlan->dev); @@ -1207,30 +1203,51 @@ static void vxlan_rcv(struct vxlan_dev *vxlan, struct vxlan_sock *vs, /* Ignore packet loops (and multicast echo) */ if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) - goto drop; + return false; /* Get data from the outer IP header */ if (vxlan_get_sk_family(vs) == AF_INET) { - oip = ip_hdr(skb); - saddr.sin.sin_addr.s_addr = oip->saddr; + saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; saddr.sa.sa_family = AF_INET; #if IS_ENABLED(CONFIG_IPV6) } else { - oip6 = ipv6_hdr(skb); - saddr.sin6.sin6_addr = oip6->saddr; + saddr.sin6.sin6_addr = ipv6_hdr(skb)->saddr; saddr.sa.sa_family = AF_INET6; #endif } + if ((vxlan->flags & VXLAN_F_LEARN) && + vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source)) + return false; + + return true; +} + +static void vxlan_rcv(struct vxlan_dev *vxlan, struct vxlan_sock *vs, + struct sk_buff *skb, struct vxlan_metadata *md, + struct metadata_dst *tun_dst) +{ + struct iphdr *oip = NULL; + struct ipv6hdr *oip6 = NULL; + struct pcpu_sw_netstats *stats; + int err = 0; + + if (!vxlan_set_mac(vxlan, vs, skb)) + goto drop; + + /* Get data from the outer IP header */ + if (vxlan_get_sk_family(vs) == AF_INET) + oip = ip_hdr(skb); +#if IS_ENABLED(CONFIG_IPV6) + else + oip6 = ipv6_hdr(skb); +#endif + if (tun_dst) { skb_dst_set(skb, (struct dst_entry *)tun_dst); tun_dst = NULL; } - if ((vxlan->flags & VXLAN_F_LEARN) && - vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source)) - goto drop; - skb_reset_network_header(skb); if (oip6) |