Commit 86b368b4 authored by David S. Miller's avatar David S. Miller

Merge branch 'vxlan_tx'

Tom Herbert says:

====================
vxlan: Don't use UDP socket for transmit

UDP socket is not pertinent to transmit for UDP tunnels, checksum
enablement can be done without a socket. This patch set eliminates
reference to a socket in udp_tunnel_xmit functions and in VXLAN
transmit.

Also, make GBP, RCO, can CSUM6_RX flags visible to receive socket
and only match these for shareable socket.

v2: Fix geneve to call udp_tunnel_xmit with good arguments.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2b995f63 af33c1ad
...@@ -270,12 +270,13 @@ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family, ...@@ -270,12 +270,13 @@ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,
__be16 port, u32 flags) __be16 port, u32 flags)
{ {
struct vxlan_sock *vs; struct vxlan_sock *vs;
u32 match_flags = flags & VXLAN_F_UNSHAREABLE;
flags &= VXLAN_F_RCV_FLAGS;
hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) { hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) {
if (inet_sk(vs->sock->sk)->inet_sport == port && if (inet_sk(vs->sock->sk)->inet_sport == port &&
inet_sk(vs->sock->sk)->sk.sk_family == family && inet_sk(vs->sock->sk)->sk.sk_family == family &&
(vs->flags & VXLAN_F_UNSHAREABLE) == match_flags) vs->flags == flags)
return vs; return vs;
} }
return NULL; return NULL;
...@@ -1674,7 +1675,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb) ...@@ -1674,7 +1675,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
return false; return false;
} }
static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, struct vxlan_sock *vs, static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, u32 vxflags,
struct vxlan_metadata *md) struct vxlan_metadata *md)
{ {
struct vxlanhdr_gbp *gbp; struct vxlanhdr_gbp *gbp;
...@@ -1692,21 +1693,20 @@ static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, struct vxlan_sock *vs, ...@@ -1692,21 +1693,20 @@ static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, struct vxlan_sock *vs,
} }
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
static int vxlan6_xmit_skb(struct vxlan_sock *vs, static int vxlan6_xmit_skb(struct dst_entry *dst, struct sk_buff *skb,
struct dst_entry *dst, struct sk_buff *skb,
struct net_device *dev, struct in6_addr *saddr, struct net_device *dev, struct in6_addr *saddr,
struct in6_addr *daddr, __u8 prio, __u8 ttl, struct in6_addr *daddr, __u8 prio, __u8 ttl,
__be16 src_port, __be16 dst_port, __be16 src_port, __be16 dst_port,
struct vxlan_metadata *md, bool xnet) struct vxlan_metadata *md, bool xnet, u32 vxflags)
{ {
struct vxlanhdr *vxh; struct vxlanhdr *vxh;
int min_headroom; int min_headroom;
int err; int err;
bool udp_sum = !udp_get_no_check6_tx(vs->sock->sk); bool udp_sum = !(vxflags & VXLAN_F_UDP_ZERO_CSUM6_TX);
int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
u16 hdrlen = sizeof(struct vxlanhdr); u16 hdrlen = sizeof(struct vxlanhdr);
if ((vs->flags & VXLAN_F_REMCSUM_TX) && if ((vxflags & VXLAN_F_REMCSUM_TX) &&
skb->ip_summed == CHECKSUM_PARTIAL) { skb->ip_summed == CHECKSUM_PARTIAL) {
int csum_start = skb_checksum_start_offset(skb); int csum_start = skb_checksum_start_offset(skb);
...@@ -1764,13 +1764,14 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, ...@@ -1764,13 +1764,14 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs,
} }
} }
if (vs->flags & VXLAN_F_GBP) if (vxflags & VXLAN_F_GBP)
vxlan_build_gbp_hdr(vxh, vs, md); vxlan_build_gbp_hdr(vxh, vxflags, md);
skb_set_inner_protocol(skb, htons(ETH_P_TEB)); skb_set_inner_protocol(skb, htons(ETH_P_TEB));
udp_tunnel6_xmit_skb(vs->sock, dst, skb, dev, saddr, daddr, prio, udp_tunnel6_xmit_skb(dst, skb, dev, saddr, daddr, prio,
ttl, src_port, dst_port); ttl, src_port, dst_port,
!!(vxflags & VXLAN_F_UDP_ZERO_CSUM6_TX));
return 0; return 0;
err: err:
dst_release(dst); dst_release(dst);
...@@ -1778,20 +1779,19 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, ...@@ -1778,20 +1779,19 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs,
} }
#endif #endif
int vxlan_xmit_skb(struct vxlan_sock *vs, int vxlan_xmit_skb(struct rtable *rt, struct sk_buff *skb,
struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df, __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
__be16 src_port, __be16 dst_port, __be16 src_port, __be16 dst_port,
struct vxlan_metadata *md, bool xnet) struct vxlan_metadata *md, bool xnet, u32 vxflags)
{ {
struct vxlanhdr *vxh; struct vxlanhdr *vxh;
int min_headroom; int min_headroom;
int err; int err;
bool udp_sum = !vs->sock->sk->sk_no_check_tx; bool udp_sum = !!(vxflags & VXLAN_F_UDP_CSUM);
int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
u16 hdrlen = sizeof(struct vxlanhdr); u16 hdrlen = sizeof(struct vxlanhdr);
if ((vs->flags & VXLAN_F_REMCSUM_TX) && if ((vxflags & VXLAN_F_REMCSUM_TX) &&
skb->ip_summed == CHECKSUM_PARTIAL) { skb->ip_summed == CHECKSUM_PARTIAL) {
int csum_start = skb_checksum_start_offset(skb); int csum_start = skb_checksum_start_offset(skb);
...@@ -1843,13 +1843,14 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, ...@@ -1843,13 +1843,14 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
} }
} }
if (vs->flags & VXLAN_F_GBP) if (vxflags & VXLAN_F_GBP)
vxlan_build_gbp_hdr(vxh, vs, md); vxlan_build_gbp_hdr(vxh, vxflags, md);
skb_set_inner_protocol(skb, htons(ETH_P_TEB)); skb_set_inner_protocol(skb, htons(ETH_P_TEB));
return udp_tunnel_xmit_skb(vs->sock, rt, skb, src, dst, tos, return udp_tunnel_xmit_skb(rt, skb, src, dst, tos,
ttl, df, src_port, dst_port, xnet); ttl, df, src_port, dst_port, xnet,
!(vxflags & VXLAN_F_UDP_CSUM));
} }
EXPORT_SYMBOL_GPL(vxlan_xmit_skb); EXPORT_SYMBOL_GPL(vxlan_xmit_skb);
...@@ -1981,10 +1982,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ...@@ -1981,10 +1982,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
md.vni = htonl(vni << 8); md.vni = htonl(vni << 8);
md.gbp = skb->mark; md.gbp = skb->mark;
err = vxlan_xmit_skb(vxlan->vn_sock, rt, skb, err = vxlan_xmit_skb(rt, skb, fl4.saddr,
fl4.saddr, dst->sin.sin_addr.s_addr, dst->sin.sin_addr.s_addr, tos, ttl, df,
tos, ttl, df, src_port, dst_port, &md, src_port, dst_port, &md,
!net_eq(vxlan->net, dev_net(vxlan->dev))); !net_eq(vxlan->net, dev_net(vxlan->dev)),
vxlan->flags);
if (err < 0) { if (err < 0) {
/* skb is already freed. */ /* skb is already freed. */
skb = NULL; skb = NULL;
...@@ -2040,10 +2042,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ...@@ -2040,10 +2042,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
md.vni = htonl(vni << 8); md.vni = htonl(vni << 8);
md.gbp = skb->mark; md.gbp = skb->mark;
err = vxlan6_xmit_skb(vxlan->vn_sock, ndst, skb, err = vxlan6_xmit_skb(ndst, skb, dev, &fl6.saddr, &fl6.daddr,
dev, &fl6.saddr, &fl6.daddr, 0, ttl, 0, ttl, src_port, dst_port, &md,
src_port, dst_port, &md, !net_eq(vxlan->net, dev_net(vxlan->dev)),
!net_eq(vxlan->net, dev_net(vxlan->dev))); vxlan->flags);
#endif #endif
} }
...@@ -2515,15 +2517,11 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6, ...@@ -2515,15 +2517,11 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
if (ipv6) { if (ipv6) {
udp_conf.family = AF_INET6; udp_conf.family = AF_INET6;
udp_conf.use_udp6_tx_checksums =
!(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
udp_conf.use_udp6_rx_checksums = udp_conf.use_udp6_rx_checksums =
!(flags & VXLAN_F_UDP_ZERO_CSUM6_RX); !(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
} else { } else {
udp_conf.family = AF_INET; udp_conf.family = AF_INET;
udp_conf.local_ip.s_addr = INADDR_ANY; udp_conf.local_ip.s_addr = INADDR_ANY;
udp_conf.use_udp_checksums =
!!(flags & VXLAN_F_UDP_CSUM);
} }
udp_conf.local_udp_port = port; udp_conf.local_udp_port = port;
...@@ -2567,7 +2565,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, ...@@ -2567,7 +2565,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port,
atomic_set(&vs->refcnt, 1); atomic_set(&vs->refcnt, 1);
vs->rcv = rcv; vs->rcv = rcv;
vs->data = data; vs->data = data;
vs->flags = flags; vs->flags = (flags & VXLAN_F_RCV_FLAGS);
/* Initialize the vxlan udp offloads structure */ /* Initialize the vxlan udp offloads structure */
vs->udp_offloads.port = port; vs->udp_offloads.port = port;
......
...@@ -77,17 +77,17 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock, ...@@ -77,17 +77,17 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
struct udp_tunnel_sock_cfg *sock_cfg); struct udp_tunnel_sock_cfg *sock_cfg);
/* Transmit the skb using UDP encapsulation. */ /* Transmit the skb using UDP encapsulation. */
int udp_tunnel_xmit_skb(struct socket *sock, struct rtable *rt, int udp_tunnel_xmit_skb(struct rtable *rt, struct sk_buff *skb,
struct sk_buff *skb, __be32 src, __be32 dst, __be32 src, __be32 dst, __u8 tos, __u8 ttl,
__u8 tos, __u8 ttl, __be16 df, __be16 src_port, __be16 df, __be16 src_port, __be16 dst_port,
__be16 dst_port, bool xnet); bool xnet, bool nocheck);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
int udp_tunnel6_xmit_skb(struct socket *sock, struct dst_entry *dst, int udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sk_buff *skb,
struct sk_buff *skb, struct net_device *dev, struct net_device *dev, struct in6_addr *saddr,
struct in6_addr *saddr, struct in6_addr *daddr, struct in6_addr *daddr,
__u8 prio, __u8 ttl, __be16 src_port, __u8 prio, __u8 ttl, __be16 src_port,
__be16 dst_port); __be16 dst_port, bool nocheck);
#endif #endif
void udp_tunnel_sock_release(struct socket *sock); void udp_tunnel_sock_release(struct socket *sock);
......
...@@ -129,8 +129,12 @@ struct vxlan_sock { ...@@ -129,8 +129,12 @@ struct vxlan_sock {
#define VXLAN_F_REMCSUM_RX 0x400 #define VXLAN_F_REMCSUM_RX 0x400
#define VXLAN_F_GBP 0x800 #define VXLAN_F_GBP 0x800
/* These flags must match in order for a socket to be shareable */ /* Flags that are used in the receive patch. These flags must match in
#define VXLAN_F_UNSHAREABLE VXLAN_F_GBP * order for a socket to be shareable
*/
#define VXLAN_F_RCV_FLAGS (VXLAN_F_GBP | \
VXLAN_F_UDP_ZERO_CSUM6_RX | \
VXLAN_F_REMCSUM_RX)
struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
vxlan_rcv_t *rcv, void *data, vxlan_rcv_t *rcv, void *data,
...@@ -138,11 +142,10 @@ struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, ...@@ -138,11 +142,10 @@ struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
void vxlan_sock_release(struct vxlan_sock *vs); void vxlan_sock_release(struct vxlan_sock *vs);
int vxlan_xmit_skb(struct vxlan_sock *vs, int vxlan_xmit_skb(struct rtable *rt, struct sk_buff *skb,
struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df, __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
__be16 src_port, __be16 dst_port, struct vxlan_metadata *md, __be16 src_port, __be16 dst_port, struct vxlan_metadata *md,
bool xnet); bool xnet, u32 vxflags);
static inline netdev_features_t vxlan_features_check(struct sk_buff *skb, static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
netdev_features_t features) netdev_features_t features)
......
...@@ -136,8 +136,9 @@ int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt, ...@@ -136,8 +136,9 @@ int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt,
skb_set_inner_protocol(skb, htons(ETH_P_TEB)); skb_set_inner_protocol(skb, htons(ETH_P_TEB));
return udp_tunnel_xmit_skb(gs->sock, rt, skb, src, dst, return udp_tunnel_xmit_skb(rt, skb, src, dst,
tos, ttl, df, src_port, dst_port, xnet); tos, ttl, df, src_port, dst_port, xnet,
gs->sock->sk->sk_no_check_tx);
} }
EXPORT_SYMBOL_GPL(geneve_xmit_skb); EXPORT_SYMBOL_GPL(geneve_xmit_skb);
......
...@@ -75,10 +75,10 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock, ...@@ -75,10 +75,10 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
} }
EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock); EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock);
int udp_tunnel_xmit_skb(struct socket *sock, struct rtable *rt, int udp_tunnel_xmit_skb(struct rtable *rt, struct sk_buff *skb,
struct sk_buff *skb, __be32 src, __be32 dst, __be32 src, __be32 dst, __u8 tos, __u8 ttl,
__u8 tos, __u8 ttl, __be16 df, __be16 src_port, __be16 df, __be16 src_port, __be16 dst_port,
__be16 dst_port, bool xnet) bool xnet, bool nocheck)
{ {
struct udphdr *uh; struct udphdr *uh;
...@@ -90,9 +90,9 @@ int udp_tunnel_xmit_skb(struct socket *sock, struct rtable *rt, ...@@ -90,9 +90,9 @@ int udp_tunnel_xmit_skb(struct socket *sock, struct rtable *rt,
uh->source = src_port; uh->source = src_port;
uh->len = htons(skb->len); uh->len = htons(skb->len);
udp_set_csum(sock->sk->sk_no_check_tx, skb, src, dst, skb->len); udp_set_csum(nocheck, skb, src, dst, skb->len);
return iptunnel_xmit(sock->sk, rt, skb, src, dst, IPPROTO_UDP, return iptunnel_xmit(skb->sk, rt, skb, src, dst, IPPROTO_UDP,
tos, ttl, df, xnet); tos, ttl, df, xnet);
} }
EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb); EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb);
......
...@@ -62,14 +62,14 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, ...@@ -62,14 +62,14 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
} }
EXPORT_SYMBOL_GPL(udp_sock_create6); EXPORT_SYMBOL_GPL(udp_sock_create6);
int udp_tunnel6_xmit_skb(struct socket *sock, struct dst_entry *dst, int udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sk_buff *skb,
struct sk_buff *skb, struct net_device *dev, struct net_device *dev, struct in6_addr *saddr,
struct in6_addr *saddr, struct in6_addr *daddr, struct in6_addr *daddr,
__u8 prio, __u8 ttl, __be16 src_port, __be16 dst_port) __u8 prio, __u8 ttl, __be16 src_port,
__be16 dst_port, bool nocheck)
{ {
struct udphdr *uh; struct udphdr *uh;
struct ipv6hdr *ip6h; struct ipv6hdr *ip6h;
struct sock *sk = sock->sk;
__skb_push(skb, sizeof(*uh)); __skb_push(skb, sizeof(*uh));
skb_reset_transport_header(skb); skb_reset_transport_header(skb);
...@@ -85,7 +85,7 @@ int udp_tunnel6_xmit_skb(struct socket *sock, struct dst_entry *dst, ...@@ -85,7 +85,7 @@ int udp_tunnel6_xmit_skb(struct socket *sock, struct dst_entry *dst,
| IPSKB_REROUTED); | IPSKB_REROUTED);
skb_dst_set(skb, dst); skb_dst_set(skb, dst);
udp6_set_csum(udp_get_no_check6_tx(sk), skb, saddr, daddr, skb->len); udp6_set_csum(nocheck, skb, saddr, daddr, skb->len);
__skb_push(skb, sizeof(*ip6h)); __skb_push(skb, sizeof(*ip6h));
skb_reset_network_header(skb); skb_reset_network_header(skb);
......
...@@ -252,12 +252,10 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb) ...@@ -252,12 +252,10 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
md.vni = htonl(be64_to_cpu(tun_key->tun_id) << 8); md.vni = htonl(be64_to_cpu(tun_key->tun_id) << 8);
md.gbp = vxlan_ext_gbp(skb); md.gbp = vxlan_ext_gbp(skb);
err = vxlan_xmit_skb(vxlan_port->vs, rt, skb, err = vxlan_xmit_skb(rt, skb, fl.saddr, tun_key->ipv4_dst,
fl.saddr, tun_key->ipv4_dst,
tun_key->ipv4_tos, tun_key->ipv4_ttl, df, tun_key->ipv4_tos, tun_key->ipv4_ttl, df,
src_port, dst_port, src_port, dst_port,
&md, &md, false, vxlan_port->exts);
false);
if (err < 0) if (err < 0)
ip_rt_put(rt); ip_rt_put(rt);
return err; return err;
......
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