|
@@ -110,6 +110,11 @@ static __be64 vni_to_tunnel_id(const __u8 *vni)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+static sa_family_t geneve_get_sk_family(struct geneve_sock *gs)
|
|
|
+{
|
|
|
+ return gs->sock->sk->sk_family;
|
|
|
+}
|
|
|
+
|
|
|
static struct geneve_dev *geneve_lookup(struct geneve_sock *gs,
|
|
|
__be32 addr, u8 vni[])
|
|
|
{
|
|
@@ -153,58 +158,60 @@ static inline struct genevehdr *geneve_hdr(const struct sk_buff *skb)
|
|
|
return (struct genevehdr *)(udp_hdr(skb) + 1);
|
|
|
}
|
|
|
|
|
|
-/* geneve receive/decap routine */
|
|
|
-static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
|
|
|
+static struct geneve_dev *geneve_lookup_skb(struct geneve_sock *gs,
|
|
|
+ struct sk_buff *skb)
|
|
|
{
|
|
|
- struct genevehdr *gnvh = geneve_hdr(skb);
|
|
|
- struct metadata_dst *tun_dst = NULL;
|
|
|
- struct geneve_dev *geneve = NULL;
|
|
|
- struct pcpu_sw_netstats *stats;
|
|
|
- struct iphdr *iph = NULL;
|
|
|
+ u8 *vni;
|
|
|
__be32 addr;
|
|
|
static u8 zero_vni[3];
|
|
|
- u8 *vni;
|
|
|
- int err = 0;
|
|
|
- sa_family_t sa_family;
|
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
|
- struct ipv6hdr *ip6h = NULL;
|
|
|
- struct in6_addr addr6;
|
|
|
static struct in6_addr zero_addr6;
|
|
|
#endif
|
|
|
|
|
|
- sa_family = gs->sock->sk->sk_family;
|
|
|
+ if (geneve_get_sk_family(gs) == AF_INET) {
|
|
|
+ struct iphdr *iph;
|
|
|
|
|
|
- if (sa_family == AF_INET) {
|
|
|
iph = ip_hdr(skb); /* outer IP header... */
|
|
|
|
|
|
if (gs->collect_md) {
|
|
|
vni = zero_vni;
|
|
|
addr = 0;
|
|
|
} else {
|
|
|
- vni = gnvh->vni;
|
|
|
-
|
|
|
+ vni = geneve_hdr(skb)->vni;
|
|
|
addr = iph->saddr;
|
|
|
}
|
|
|
|
|
|
- geneve = geneve_lookup(gs, addr, vni);
|
|
|
+ return geneve_lookup(gs, addr, vni);
|
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
|
- } else if (sa_family == 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... */
|
|
|
|
|
|
if (gs->collect_md) {
|
|
|
vni = zero_vni;
|
|
|
addr6 = zero_addr6;
|
|
|
} else {
|
|
|
- vni = gnvh->vni;
|
|
|
-
|
|
|
+ vni = geneve_hdr(skb)->vni;
|
|
|
addr6 = ip6h->saddr;
|
|
|
}
|
|
|
|
|
|
- geneve = geneve6_lookup(gs, addr6, vni);
|
|
|
+ return geneve6_lookup(gs, addr6, vni);
|
|
|
#endif
|
|
|
}
|
|
|
- if (!geneve)
|
|
|
- goto drop;
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+/* 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) {
|
|
|
__be16 flags;
|
|
@@ -213,7 +220,7 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
|
|
|
(gnvh->oam ? TUNNEL_OAM : 0) |
|
|
|
(gnvh->critical ? TUNNEL_CRIT_OPT : 0);
|
|
|
|
|
|
- tun_dst = udp_tun_rx_dst(skb, sa_family, flags,
|
|
|
+ tun_dst = udp_tun_rx_dst(skb, geneve_get_sk_family(gs), flags,
|
|
|
vni_to_tunnel_id(gnvh->vni),
|
|
|
gnvh->opt_len * 4);
|
|
|
if (!tun_dst)
|
|
@@ -230,7 +237,6 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
|
|
|
}
|
|
|
|
|
|
skb_reset_mac_header(skb);
|
|
|
- skb_scrub_packet(skb, !net_eq(geneve->net, dev_net(geneve->dev)));
|
|
|
skb->protocol = eth_type_trans(skb, geneve->dev);
|
|
|
skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
|
|
|
|
|
@@ -241,25 +247,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))
|
|
|
goto drop;
|
|
|
|
|
|
+ oiph = skb_network_header(skb);
|
|
|
skb_reset_network_header(skb);
|
|
|
|
|
|
- if (iph)
|
|
|
- err = IP_ECN_decapsulate(iph, skb);
|
|
|
+ if (geneve_get_sk_family(gs) == AF_INET)
|
|
|
+ err = IP_ECN_decapsulate(oiph, skb);
|
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
|
- if (ip6h)
|
|
|
- err = IP6_ECN_decapsulate(ip6h, skb);
|
|
|
+ else
|
|
|
+ err = IP6_ECN_decapsulate(oiph, skb);
|
|
|
#endif
|
|
|
|
|
|
if (unlikely(err)) {
|
|
|
if (log_ecn_error) {
|
|
|
- if (iph)
|
|
|
+ if (geneve_get_sk_family(gs) == AF_INET)
|
|
|
net_info_ratelimited("non-ECT from %pI4 "
|
|
|
"with TOS=%#x\n",
|
|
|
- &iph->saddr, iph->tos);
|
|
|
+ &((struct iphdr *)oiph)->saddr,
|
|
|
+ ((struct iphdr *)oiph)->tos);
|
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
|
- if (ip6h)
|
|
|
+ else
|
|
|
net_info_ratelimited("non-ECT from %pI6\n",
|
|
|
- &ip6h->saddr);
|
|
|
+ &((struct ipv6hdr *)oiph)->saddr);
|
|
|
#endif
|
|
|
}
|
|
|
if (err > 1) {
|
|
@@ -321,6 +329,7 @@ static void geneve_uninit(struct net_device *dev)
|
|
|
static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
|
|
{
|
|
|
struct genevehdr *geneveh;
|
|
|
+ struct geneve_dev *geneve;
|
|
|
struct geneve_sock *gs;
|
|
|
int opts_len;
|
|
|
|
|
@@ -336,16 +345,21 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
|
|
if (unlikely(geneveh->proto_type != htons(ETH_P_TEB)))
|
|
|
goto error;
|
|
|
|
|
|
- opts_len = geneveh->opt_len * 4;
|
|
|
- if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len,
|
|
|
- htons(ETH_P_TEB)))
|
|
|
- goto drop;
|
|
|
-
|
|
|
gs = rcu_dereference_sk_user_data(sk);
|
|
|
if (!gs)
|
|
|
goto drop;
|
|
|
|
|
|
- geneve_rx(gs, skb);
|
|
|
+ geneve = geneve_lookup_skb(gs, skb);
|
|
|
+ if (!geneve)
|
|
|
+ goto drop;
|
|
|
+
|
|
|
+ opts_len = geneveh->opt_len * 4;
|
|
|
+ if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len,
|
|
|
+ htons(ETH_P_TEB),
|
|
|
+ !net_eq(geneve->net, dev_net(geneve->dev))))
|
|
|
+ goto drop;
|
|
|
+
|
|
|
+ geneve_rx(geneve, gs, skb);
|
|
|
return 0;
|
|
|
|
|
|
drop:
|
|
@@ -392,7 +406,7 @@ static void geneve_notify_add_rx_port(struct geneve_sock *gs)
|
|
|
struct net_device *dev;
|
|
|
struct sock *sk = gs->sock->sk;
|
|
|
struct net *net = sock_net(sk);
|
|
|
- sa_family_t sa_family = sk->sk_family;
|
|
|
+ sa_family_t sa_family = geneve_get_sk_family(gs);
|
|
|
__be16 port = inet_sk(sk)->inet_sport;
|
|
|
int err;
|
|
|
|
|
@@ -553,7 +567,7 @@ static void geneve_notify_del_rx_port(struct geneve_sock *gs)
|
|
|
struct net_device *dev;
|
|
|
struct sock *sk = gs->sock->sk;
|
|
|
struct net *net = sock_net(sk);
|
|
|
- sa_family_t sa_family = sk->sk_family;
|
|
|
+ sa_family_t sa_family = geneve_get_sk_family(gs);
|
|
|
__be16 port = inet_sk(sk)->inet_sport;
|
|
|
|
|
|
rcu_read_lock();
|
|
@@ -596,7 +610,7 @@ static struct geneve_sock *geneve_find_sock(struct geneve_net *gn,
|
|
|
|
|
|
list_for_each_entry(gs, &gn->sock_list, list) {
|
|
|
if (inet_sk(gs->sock->sk)->inet_sport == dst_port &&
|
|
|
- inet_sk(gs->sock->sk)->sk.sk_family == family) {
|
|
|
+ geneve_get_sk_family(gs) == family) {
|
|
|
return gs;
|
|
|
}
|
|
|
}
|