|
@@ -236,7 +236,7 @@ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,
|
|
|
|
|
|
hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) {
|
|
|
if (inet_sk(vs->sock->sk)->inet_sport == port &&
|
|
|
- inet_sk(vs->sock->sk)->sk.sk_family == family &&
|
|
|
+ vxlan_get_sk_family(vs) == family &&
|
|
|
vs->flags == flags)
|
|
|
return vs;
|
|
|
}
|
|
@@ -625,7 +625,7 @@ static void vxlan_notify_add_rx_port(struct vxlan_sock *vs)
|
|
|
struct net_device *dev;
|
|
|
struct sock *sk = vs->sock->sk;
|
|
|
struct net *net = sock_net(sk);
|
|
|
- sa_family_t sa_family = sk->sk_family;
|
|
|
+ sa_family_t sa_family = vxlan_get_sk_family(vs);
|
|
|
__be16 port = inet_sk(sk)->inet_sport;
|
|
|
int err;
|
|
|
|
|
@@ -650,7 +650,7 @@ static void vxlan_notify_del_rx_port(struct vxlan_sock *vs)
|
|
|
struct net_device *dev;
|
|
|
struct sock *sk = vs->sock->sk;
|
|
|
struct net *net = sock_net(sk);
|
|
|
- sa_family_t sa_family = sk->sk_family;
|
|
|
+ sa_family_t sa_family = vxlan_get_sk_family(vs);
|
|
|
__be16 port = inet_sk(sk)->inet_sport;
|
|
|
|
|
|
rcu_read_lock();
|
|
@@ -1269,17 +1269,27 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
|
|
}
|
|
|
|
|
|
if (vxlan_collect_metadata(vs)) {
|
|
|
- const struct iphdr *iph = ip_hdr(skb);
|
|
|
-
|
|
|
tun_dst = metadata_dst_alloc(sizeof(*md), GFP_ATOMIC);
|
|
|
if (!tun_dst)
|
|
|
goto drop;
|
|
|
|
|
|
info = &tun_dst->u.tun_info;
|
|
|
- info->key.ipv4_src = iph->saddr;
|
|
|
- info->key.ipv4_dst = iph->daddr;
|
|
|
- info->key.ipv4_tos = iph->tos;
|
|
|
- info->key.ipv4_ttl = iph->ttl;
|
|
|
+ if (vxlan_get_sk_family(vs) == AF_INET) {
|
|
|
+ const struct iphdr *iph = ip_hdr(skb);
|
|
|
+
|
|
|
+ info->key.u.ipv4.src = iph->saddr;
|
|
|
+ info->key.u.ipv4.dst = iph->daddr;
|
|
|
+ info->key.tos = iph->tos;
|
|
|
+ info->key.ttl = iph->ttl;
|
|
|
+ } else {
|
|
|
+ const struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
|
|
+
|
|
|
+ info->key.u.ipv6.src = ip6h->saddr;
|
|
|
+ info->key.u.ipv6.dst = ip6h->daddr;
|
|
|
+ info->key.tos = ipv6_get_dsfield(ip6h);
|
|
|
+ info->key.ttl = ip6h->hop_limit;
|
|
|
+ }
|
|
|
+
|
|
|
info->key.tp_src = udp_hdr(skb)->source;
|
|
|
info->key.tp_dst = udp_hdr(skb)->dest;
|
|
|
|
|
@@ -1894,6 +1904,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
|
struct ip_tunnel_info *info;
|
|
|
struct vxlan_dev *vxlan = netdev_priv(dev);
|
|
|
struct sock *sk = vxlan->vn_sock->sock->sk;
|
|
|
+ unsigned short family = vxlan_get_sk_family(vxlan->vn_sock);
|
|
|
struct rtable *rt = NULL;
|
|
|
const struct iphdr *old_iph;
|
|
|
struct flowi4 fl4;
|
|
@@ -1908,8 +1919,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
|
int err;
|
|
|
u32 flags = vxlan->flags;
|
|
|
|
|
|
- /* FIXME: Support IPv6 */
|
|
|
- info = skb_tunnel_info(skb, AF_INET);
|
|
|
+ info = skb_tunnel_info(skb);
|
|
|
|
|
|
if (rdst) {
|
|
|
dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port;
|
|
@@ -1924,8 +1934,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
|
|
|
|
dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
|
|
|
vni = be64_to_cpu(info->key.tun_id);
|
|
|
- remote_ip.sin.sin_family = AF_INET;
|
|
|
- remote_ip.sin.sin_addr.s_addr = info->key.ipv4_dst;
|
|
|
+ remote_ip.sa.sa_family = family;
|
|
|
+ if (family == AF_INET)
|
|
|
+ remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst;
|
|
|
+ else
|
|
|
+ remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst;
|
|
|
dst = &remote_ip;
|
|
|
}
|
|
|
|
|
@@ -1951,23 +1964,24 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
|
src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
|
|
|
vxlan->cfg.port_max, true);
|
|
|
|
|
|
+ if (info) {
|
|
|
+ if (info->key.tun_flags & TUNNEL_CSUM)
|
|
|
+ flags |= VXLAN_F_UDP_CSUM;
|
|
|
+ else
|
|
|
+ flags &= ~VXLAN_F_UDP_CSUM;
|
|
|
+
|
|
|
+ ttl = info->key.ttl;
|
|
|
+ tos = info->key.tos;
|
|
|
+
|
|
|
+ if (info->options_len)
|
|
|
+ md = ip_tunnel_info_opts(info, sizeof(*md));
|
|
|
+ } else {
|
|
|
+ md->gbp = skb->mark;
|
|
|
+ }
|
|
|
+
|
|
|
if (dst->sa.sa_family == AF_INET) {
|
|
|
- if (info) {
|
|
|
- if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT)
|
|
|
- df = htons(IP_DF);
|
|
|
- if (info->key.tun_flags & TUNNEL_CSUM)
|
|
|
- flags |= VXLAN_F_UDP_CSUM;
|
|
|
- else
|
|
|
- flags &= ~VXLAN_F_UDP_CSUM;
|
|
|
-
|
|
|
- ttl = info->key.ipv4_ttl;
|
|
|
- tos = info->key.ipv4_tos;
|
|
|
-
|
|
|
- if (info->options_len)
|
|
|
- md = ip_tunnel_info_opts(info, sizeof(*md));
|
|
|
- } else {
|
|
|
- md->gbp = skb->mark;
|
|
|
- }
|
|
|
+ if (info && (info->key.tun_flags & TUNNEL_DONT_FRAGMENT))
|
|
|
+ df = htons(IP_DF);
|
|
|
|
|
|
memset(&fl4, 0, sizeof(fl4));
|
|
|
fl4.flowi4_oif = rdst ? rdst->remote_ifindex : 0;
|
|
@@ -2025,7 +2039,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
|
} else {
|
|
|
struct dst_entry *ndst;
|
|
|
struct flowi6 fl6;
|
|
|
- u32 flags;
|
|
|
+ u32 rt6i_flags;
|
|
|
|
|
|
memset(&fl6, 0, sizeof(fl6));
|
|
|
fl6.flowi6_oif = rdst ? rdst->remote_ifindex : 0;
|
|
@@ -2050,9 +2064,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
|
}
|
|
|
|
|
|
/* Bypass encapsulation if the destination is local */
|
|
|
- flags = ((struct rt6_info *)ndst)->rt6i_flags;
|
|
|
- if (flags & RTF_LOCAL &&
|
|
|
- !(flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
|
|
|
+ rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags;
|
|
|
+ if (rt6i_flags & RTF_LOCAL &&
|
|
|
+ !(rt6i_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
|
|
|
struct vxlan_dev *dst_vxlan;
|
|
|
|
|
|
dst_release(ndst);
|
|
@@ -2066,12 +2080,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
|
}
|
|
|
|
|
|
ttl = ttl ? : ip6_dst_hoplimit(ndst);
|
|
|
- md->gbp = skb->mark;
|
|
|
-
|
|
|
err = vxlan6_xmit_skb(ndst, sk, skb, dev, &fl6.saddr, &fl6.daddr,
|
|
|
0, ttl, src_port, dst_port, htonl(vni << 8), md,
|
|
|
!net_eq(vxlan->net, dev_net(vxlan->dev)),
|
|
|
- vxlan->flags);
|
|
|
+ flags);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
@@ -2104,8 +2116,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
struct vxlan_rdst *rdst, *fdst = NULL;
|
|
|
struct vxlan_fdb *f;
|
|
|
|
|
|
- /* FIXME: Support IPv6 */
|
|
|
- info = skb_tunnel_info(skb, AF_INET);
|
|
|
+ info = skb_tunnel_info(skb);
|
|
|
|
|
|
skb_reset_mac_header(skb);
|
|
|
eth = eth_hdr(skb);
|
|
@@ -2390,7 +2401,7 @@ void vxlan_get_rx_port(struct net_device *dev)
|
|
|
for (i = 0; i < PORT_HASH_SIZE; ++i) {
|
|
|
hlist_for_each_entry_rcu(vs, &vn->sock_list[i], hlist) {
|
|
|
port = inet_sk(vs->sock->sk)->inet_sport;
|
|
|
- sa_family = vs->sock->sk->sk_family;
|
|
|
+ sa_family = vxlan_get_sk_family(vs);
|
|
|
dev->netdev_ops->ndo_add_vxlan_port(dev, sa_family,
|
|
|
port);
|
|
|
}
|