Loading drivers/net/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -148,6 +148,7 @@ config VXLAN tristate "Virtual eXtensible Local Area Network (VXLAN)" depends on INET select NET_IP_TUNNEL select NET_UDP_TUNNEL ---help--- This allows one to create vxlan virtual interfaces that provide Layer 2 Networks over Layer 3 Networks. VXLAN is often used Loading drivers/net/vxlan.c +24 −91 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <net/ip_tunnels.h> #include <net/icmp.h> #include <net/udp.h> #include <net/udp_tunnel.h> #include <net/rtnetlink.h> #include <net/route.h> #include <net/dsfield.h> Loading Loading @@ -2339,102 +2340,37 @@ static void vxlan_del_work(struct work_struct *work) kfree_rcu(vs, rcu); } #if IS_ENABLED(CONFIG_IPV6) /* Create UDP socket for encapsulation receive. AF_INET6 socket * could be used for both IPv4 and IPv6 communications, but * users may set bindv6only=1. */ static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags) static struct socket *vxlan_create_sock(struct net *net, bool ipv6, __be16 port, u32 flags) { struct sock *sk; struct socket *sock; struct sockaddr_in6 vxlan_addr = { .sin6_family = AF_INET6, .sin6_port = port, }; int rc, val = 1; rc = sock_create_kern(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock); if (rc < 0) { pr_debug("UDPv6 socket create failed\n"); return ERR_PTR(rc); } /* Put in proper namespace */ sk = sock->sk; sk_change_net(sk, net); kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val)); rc = kernel_bind(sock, (struct sockaddr *)&vxlan_addr, sizeof(struct sockaddr_in6)); if (rc < 0) { pr_debug("bind for UDPv6 socket %pI6:%u (%d)\n", &vxlan_addr.sin6_addr, ntohs(vxlan_addr.sin6_port), rc); sk_release_kernel(sk); return ERR_PTR(rc); } /* At this point, IPv6 module should have been loaded in * sock_create_kern(). */ BUG_ON(!ipv6_stub); /* Disable multicast loopback */ inet_sk(sk)->mc_loop = 0; if (flags & VXLAN_F_UDP_ZERO_CSUM6_TX) udp_set_no_check6_tx(sk, true); if (flags & VXLAN_F_UDP_ZERO_CSUM6_RX) udp_set_no_check6_rx(sk, true); return sock; } #else struct udp_port_cfg udp_conf; int err; static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags) { return ERR_PTR(-EPFNOSUPPORT); } #endif memset(&udp_conf, 0, sizeof(udp_conf)); static struct socket *create_v4_sock(struct net *net, __be16 port, u32 flags) { struct sock *sk; struct socket *sock; struct sockaddr_in vxlan_addr = { .sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_ANY), .sin_port = port, }; int rc; /* Create UDP socket for encapsulation receive. */ rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); if (rc < 0) { pr_debug("UDP socket create failed\n"); return ERR_PTR(rc); if (ipv6) { udp_conf.family = AF_INET6; udp_conf.use_udp6_tx_checksums = !!(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); udp_conf.use_udp6_rx_checksums = !!(flags & VXLAN_F_UDP_ZERO_CSUM6_RX); } else { udp_conf.family = AF_INET; udp_conf.local_ip.s_addr = INADDR_ANY; udp_conf.use_udp_checksums = !!(flags & VXLAN_F_UDP_CSUM); } /* Put in proper namespace */ sk = sock->sk; sk_change_net(sk, net); udp_conf.local_udp_port = port; rc = kernel_bind(sock, (struct sockaddr *) &vxlan_addr, sizeof(vxlan_addr)); if (rc < 0) { pr_debug("bind for UDP socket %pI4:%u (%d)\n", &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc); sk_release_kernel(sk); return ERR_PTR(rc); } /* Open UDP socket */ err = udp_sock_create(net, &udp_conf, &sock); if (err < 0) return ERR_PTR(err); /* Disable multicast loopback */ inet_sk(sk)->mc_loop = 0; if (!(flags & VXLAN_F_UDP_CSUM)) sock->sk->sk_no_check_tx = 1; inet_sk(sock->sk)->mc_loop = 0; return sock; } Loading @@ -2460,10 +2396,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, INIT_WORK(&vs->del_work, vxlan_del_work); if (ipv6) sock = create_v6_sock(net, port, flags); else sock = create_v4_sock(net, port, flags); sock = vxlan_create_sock(net, ipv6, port, flags); if (IS_ERR(sock)) { kfree(vs); return ERR_CAST(sock); Loading Loading
drivers/net/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -148,6 +148,7 @@ config VXLAN tristate "Virtual eXtensible Local Area Network (VXLAN)" depends on INET select NET_IP_TUNNEL select NET_UDP_TUNNEL ---help--- This allows one to create vxlan virtual interfaces that provide Layer 2 Networks over Layer 3 Networks. VXLAN is often used Loading
drivers/net/vxlan.c +24 −91 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <net/ip_tunnels.h> #include <net/icmp.h> #include <net/udp.h> #include <net/udp_tunnel.h> #include <net/rtnetlink.h> #include <net/route.h> #include <net/dsfield.h> Loading Loading @@ -2339,102 +2340,37 @@ static void vxlan_del_work(struct work_struct *work) kfree_rcu(vs, rcu); } #if IS_ENABLED(CONFIG_IPV6) /* Create UDP socket for encapsulation receive. AF_INET6 socket * could be used for both IPv4 and IPv6 communications, but * users may set bindv6only=1. */ static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags) static struct socket *vxlan_create_sock(struct net *net, bool ipv6, __be16 port, u32 flags) { struct sock *sk; struct socket *sock; struct sockaddr_in6 vxlan_addr = { .sin6_family = AF_INET6, .sin6_port = port, }; int rc, val = 1; rc = sock_create_kern(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock); if (rc < 0) { pr_debug("UDPv6 socket create failed\n"); return ERR_PTR(rc); } /* Put in proper namespace */ sk = sock->sk; sk_change_net(sk, net); kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val)); rc = kernel_bind(sock, (struct sockaddr *)&vxlan_addr, sizeof(struct sockaddr_in6)); if (rc < 0) { pr_debug("bind for UDPv6 socket %pI6:%u (%d)\n", &vxlan_addr.sin6_addr, ntohs(vxlan_addr.sin6_port), rc); sk_release_kernel(sk); return ERR_PTR(rc); } /* At this point, IPv6 module should have been loaded in * sock_create_kern(). */ BUG_ON(!ipv6_stub); /* Disable multicast loopback */ inet_sk(sk)->mc_loop = 0; if (flags & VXLAN_F_UDP_ZERO_CSUM6_TX) udp_set_no_check6_tx(sk, true); if (flags & VXLAN_F_UDP_ZERO_CSUM6_RX) udp_set_no_check6_rx(sk, true); return sock; } #else struct udp_port_cfg udp_conf; int err; static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags) { return ERR_PTR(-EPFNOSUPPORT); } #endif memset(&udp_conf, 0, sizeof(udp_conf)); static struct socket *create_v4_sock(struct net *net, __be16 port, u32 flags) { struct sock *sk; struct socket *sock; struct sockaddr_in vxlan_addr = { .sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_ANY), .sin_port = port, }; int rc; /* Create UDP socket for encapsulation receive. */ rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); if (rc < 0) { pr_debug("UDP socket create failed\n"); return ERR_PTR(rc); if (ipv6) { udp_conf.family = AF_INET6; udp_conf.use_udp6_tx_checksums = !!(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); udp_conf.use_udp6_rx_checksums = !!(flags & VXLAN_F_UDP_ZERO_CSUM6_RX); } else { udp_conf.family = AF_INET; udp_conf.local_ip.s_addr = INADDR_ANY; udp_conf.use_udp_checksums = !!(flags & VXLAN_F_UDP_CSUM); } /* Put in proper namespace */ sk = sock->sk; sk_change_net(sk, net); udp_conf.local_udp_port = port; rc = kernel_bind(sock, (struct sockaddr *) &vxlan_addr, sizeof(vxlan_addr)); if (rc < 0) { pr_debug("bind for UDP socket %pI4:%u (%d)\n", &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc); sk_release_kernel(sk); return ERR_PTR(rc); } /* Open UDP socket */ err = udp_sock_create(net, &udp_conf, &sock); if (err < 0) return ERR_PTR(err); /* Disable multicast loopback */ inet_sk(sk)->mc_loop = 0; if (!(flags & VXLAN_F_UDP_CSUM)) sock->sk->sk_no_check_tx = 1; inet_sk(sock->sk)->mc_loop = 0; return sock; } Loading @@ -2460,10 +2396,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, INIT_WORK(&vs->del_work, vxlan_del_work); if (ipv6) sock = create_v6_sock(net, port, flags); else sock = create_v4_sock(net, port, flags); sock = vxlan_create_sock(net, ipv6, port, flags); if (IS_ERR(sock)) { kfree(vs); return ERR_CAST(sock); Loading