Commit 9fc47545 authored by Jiri Benc's avatar Jiri Benc Committed by David S. Miller

geneve: move geneve device lookup before iptunnel_pull_header

This is in preparation for iptunnel_pull_header calling skb_scrub_packet.
Signed-off-by: default avatarJiri Benc <jbenc@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1e9f12ec
...@@ -158,55 +158,60 @@ static inline struct genevehdr *geneve_hdr(const struct sk_buff *skb) ...@@ -158,55 +158,60 @@ static inline struct genevehdr *geneve_hdr(const struct sk_buff *skb)
return (struct genevehdr *)(udp_hdr(skb) + 1); return (struct genevehdr *)(udp_hdr(skb) + 1);
} }
/* geneve receive/decap routine */ static struct geneve_dev *geneve_lookup_skb(struct geneve_sock *gs,
static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb) struct sk_buff *skb)
{ {
struct genevehdr *gnvh = geneve_hdr(skb); u8 *vni;
struct metadata_dst *tun_dst = NULL;
struct geneve_dev *geneve = NULL;
struct pcpu_sw_netstats *stats;
struct iphdr *iph = NULL;
__be32 addr; __be32 addr;
static u8 zero_vni[3]; static u8 zero_vni[3];
u8 *vni;
int err = 0;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
struct ipv6hdr *ip6h = NULL;
struct in6_addr addr6;
static struct in6_addr zero_addr6; static struct in6_addr zero_addr6;
#endif #endif
if (geneve_get_sk_family(gs) == AF_INET) { if (geneve_get_sk_family(gs) == AF_INET) {
struct iphdr *iph;
iph = ip_hdr(skb); /* outer IP header... */ iph = ip_hdr(skb); /* outer IP header... */
if (gs->collect_md) { if (gs->collect_md) {
vni = zero_vni; vni = zero_vni;
addr = 0; addr = 0;
} else { } else {
vni = gnvh->vni; vni = geneve_hdr(skb)->vni;
addr = iph->saddr; addr = iph->saddr;
} }
geneve = geneve_lookup(gs, addr, vni); return geneve_lookup(gs, addr, vni);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
} else if (geneve_get_sk_family(gs) == AF_INET6) { } else if (geneve_get_sk_family(gs) == AF_INET6) {
struct ipv6hdr *ip6h;
struct in6_addr addr6;
ip6h = ipv6_hdr(skb); /* outer IPv6 header... */ ip6h = ipv6_hdr(skb); /* outer IPv6 header... */
if (gs->collect_md) { if (gs->collect_md) {
vni = zero_vni; vni = zero_vni;
addr6 = zero_addr6; addr6 = zero_addr6;
} else { } else {
vni = gnvh->vni; vni = geneve_hdr(skb)->vni;
addr6 = ip6h->saddr; addr6 = ip6h->saddr;
} }
geneve = geneve6_lookup(gs, addr6, vni); return geneve6_lookup(gs, addr6, vni);
#endif #endif
} }
if (!geneve) return NULL;
goto drop; }
/* geneve receive/decap routine */
static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
struct sk_buff *skb)
{
struct genevehdr *gnvh = geneve_hdr(skb);
struct metadata_dst *tun_dst = NULL;
struct pcpu_sw_netstats *stats;
int err = 0;
void *oiph;
if (ip_tunnel_collect_metadata() || gs->collect_md) { if (ip_tunnel_collect_metadata() || gs->collect_md) {
__be16 flags; __be16 flags;
...@@ -243,25 +248,27 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb) ...@@ -243,25 +248,27 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
if (ether_addr_equal(eth_hdr(skb)->h_source, geneve->dev->dev_addr)) if (ether_addr_equal(eth_hdr(skb)->h_source, geneve->dev->dev_addr))
goto drop; goto drop;
oiph = skb_network_header(skb);
skb_reset_network_header(skb); skb_reset_network_header(skb);
if (iph) if (geneve_get_sk_family(gs) == AF_INET)
err = IP_ECN_decapsulate(iph, skb); err = IP_ECN_decapsulate(oiph, skb);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
if (ip6h) else
err = IP6_ECN_decapsulate(ip6h, skb); err = IP6_ECN_decapsulate(oiph, skb);
#endif #endif
if (unlikely(err)) { if (unlikely(err)) {
if (log_ecn_error) { if (log_ecn_error) {
if (iph) if (geneve_get_sk_family(gs) == AF_INET)
net_info_ratelimited("non-ECT from %pI4 " net_info_ratelimited("non-ECT from %pI4 "
"with TOS=%#x\n", "with TOS=%#x\n",
&iph->saddr, iph->tos); &((struct iphdr *)oiph)->saddr,
((struct iphdr *)oiph)->tos);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
if (ip6h) else
net_info_ratelimited("non-ECT from %pI6\n", net_info_ratelimited("non-ECT from %pI6\n",
&ip6h->saddr); &((struct ipv6hdr *)oiph)->saddr);
#endif #endif
} }
if (err > 1) { if (err > 1) {
...@@ -323,6 +330,7 @@ static void geneve_uninit(struct net_device *dev) ...@@ -323,6 +330,7 @@ static void geneve_uninit(struct net_device *dev)
static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb) static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
{ {
struct genevehdr *geneveh; struct genevehdr *geneveh;
struct geneve_dev *geneve;
struct geneve_sock *gs; struct geneve_sock *gs;
int opts_len; int opts_len;
...@@ -338,16 +346,20 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb) ...@@ -338,16 +346,20 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
if (unlikely(geneveh->proto_type != htons(ETH_P_TEB))) if (unlikely(geneveh->proto_type != htons(ETH_P_TEB)))
goto error; goto error;
gs = rcu_dereference_sk_user_data(sk);
if (!gs)
goto drop;
geneve = geneve_lookup_skb(gs, skb);
if (!geneve)
goto drop;
opts_len = geneveh->opt_len * 4; opts_len = geneveh->opt_len * 4;
if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len, if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len,
htons(ETH_P_TEB))) htons(ETH_P_TEB)))
goto drop; goto drop;
gs = rcu_dereference_sk_user_data(sk); geneve_rx(geneve, gs, skb);
if (!gs)
goto drop;
geneve_rx(gs, skb);
return 0; return 0;
drop: drop:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment