rxrpc: call udp_tunnel_encap_enable in rxrpc_open_socket
Subsystems (4)
PATCH v4 2/2 rxrpc: call udp_tunnel_encap_enable in rxrpc_open_socket
When doing encap_enable/increasing encap_needed_key, up->encap_enabled is not set in rxrpc_open_socket(), and it will cause encap_needed_key not being decreased in udpv6_destroy_sock().
This patch is to improve it by just calling udp_tunnel_encap_enable() where it increases both UDP and UDPv6 encap_needed_key and sets up->encap_enabled.
--- net/rxrpc/local_object.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
net/rxrpc/local_object.c +1 -5
@@ -135,11 +135,7 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)udp_sk (usk)->gro_receive =NULL ;udp_sk (usk)->gro_complete =NULL ; -udp_encap_enable (); -#if IS_ENABLED (CONFIG_AF_RXRPC_IPV6 ) -if (local->srx.transport.family ==AF_INET6 ) -udpv6_encap_enable (); -#endif +udp_tunnel_encap_enable (local->socket); usk->sk_error_report = rxrpc_error_report;/* if a local address was supplied then bind it */
Signature · 1 line
2.1.0
David Howells
maintainernet/rxrpc/local_object.c static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net) · line 138
Quoted 6 lines · Xin Long
net/rxrpc/local_object.c +1
-5-udp_encap_enable (); -#if IS_ENABLED (CONFIG_AF_RXRPC_IPV6 ) -if (local->srx.transport.family ==AF_INET6 ) -udpv6_encap_enable (); -#endif +udp_tunnel_encap_enable (local->socket);
You need this too:
--- a/net/rxrpc/local_object.c +++ b/net/rxrpc/local_object.c @@ -16,6 +16,7 @@ #include <linux/hashtable.h> #include <net/sock.h> #include <net/udp.h> +#include <net/udp_tunnel.h> #include <net/af_rxrpc.h> #include "ar-internal.h"
With that, it seems to work still:
David
v4 cover net: enable udp v6 sockets receiving v4 packets with UDP GRO
Currently, udp v6 socket can not process v4 packets with UDP GRO, as udp_encap_needed_key is not increased when udp_tunnel_encap_enable() is called for v6 socket.
This patchset is to increase it and remove the unnecessary code in bareudp in Patch 1/2, and improve rxrpc encap_enable by calling udp_tunnel_encap_enable().
Xin Long (2):
udp: call udp_encap_enable for v6 sockets when enabling encap
rxrpc: call udp_tunnel_encap_enable in rxrpc_open_socket
drivers/net/bareudp.c | 6 ------ include/net/udp.h | 1 + include/net/udp_tunnel.h | 3 +-- net/ipv4/udp.c | 6 ++++++ net/ipv6/udp.c | 4 +++- net/rxrpc/local_object.c | 6 +----- 6 files changed, 12 insertions(+), 14 deletions(-)
Signature · 1 line
2.1.0
PATCH v4 1/2 udp: call udp_encap_enable for v6 sockets when enabling encap
When enabling encap for a ipv6 socket without udp_encap_needed_key increased, UDP GRO won't work for v4 mapped v6 address packets as sk will be NULL in udp4_gro_receive().
This patch is to enable it by increasing udp_encap_needed_key for v6 sockets in udp_tunnel_encap_enable(), and correspondingly decrease udp_encap_needed_key in udpv6_destroy_sock().
v1->v2:
- add udp_encap_disable() and export it.v2->v3:
- add the change for rxrpc and bareudp into one patch, as Alex suggested.v3->v4:
- move rxrpc part to another patch.
--- drivers/net/bareudp.c | 6 ------ include/net/udp.h | 1 + include/net/udp_tunnel.h | 3 +-- net/ipv4/udp.c | 6 ++++++ net/ipv6/udp.c | 4 +++- 5 files changed, 11 insertions(+), 9 deletions(-)
drivers/net/bareudp.c +0 -6
@@ -240,12 +240,6 @@ static int bareudp_socket_create(struct bareudp_dev *bareudp, __be16 port) tunnel_cfg.encap_destroy =NULL ;setup_udp_tunnel_sock (bareudp->net, sock, &tunnel_cfg); -/* As the setup_udp_tunnel_sock does not call udp_encap_enable if the -* socket type is v6 an explicit call to udp_encap_enable is needed. -*/ -if (sock->sk->sk_family ==AF_INET6 ) -udp_encap_enable (); -rcu_assign_pointer (bareudp->sock, sock);return 0 ; }
include/net/udp.h +1 -0
@@ -467,6 +467,7 @@ void udp_init(void);DECLARE_STATIC_KEY_FALSE (udp_encap_needed_key);void udp_encap_enable (void ); +void udp_encap_disable (void );#if IS_ENABLED (CONFIG_IPV6 )DECLARE_STATIC_KEY_FALSE (udpv6_encap_needed_key);void udpv6_encap_enable (void );
include/net/udp_tunnel.h +1 -2
@@ -181,9 +181,8 @@ static inline void udp_tunnel_encap_enable(struct socket *sock)#if IS_ENABLED (CONFIG_IPV6 )if (sock->sk->sk_family ==PF_INET6 ) ipv6_stub->udpv6_encap_enable (); - else#endif -udp_encap_enable (); +udp_encap_enable (); }#define UDP_TUNNEL_NIC_MAX_TABLES 4
net/ipv4/udp.c +6 -0
@@ -596,6 +596,12 @@ void udp_encap_enable(void) }EXPORT_SYMBOL (udp_encap_enable); +void udp_encap_disable (void ) +{ +static_branch_dec (&udp_encap_needed_key); +} +EXPORT_SYMBOL (udp_encap_disable); +/* Handler for tunnels with arbitrary destination ports: no socket lookup, go * through error handlers in encapsulations looking for a match. */
net/ipv6/udp.c +3 -1
@@ -1608,8 +1608,10 @@ void udpv6_destroy_sock(struct sock *sk)if (encap_destroy)encap_destroy (sk); } -if (up->encap_enabled) +if (up->encap_enabled) {static_branch_dec (&udpv6_encap_needed_key); +udp_encap_disable (); + } }inet6_destroy_sock (sk);
Signature · 1 line
2.1.0
Re: [PATCHv4 net-next 1/2] udp: call udp_encap_enable for v6 sockets when enabling encap
Quoted 17 lines · Xin Long
When enabling encap for a ipv6 socket without
udp_encap_needed_keyincreased, UDP GRO won't work for v4 mapped v6 address packets as sk will be NULL inudp4_gro_receive().This patch is to enable it by increasing
udp_encap_needed_keyfor v6 sockets inudp_tunnel_encap_enable(), and correspondingly decreaseudp_encap_needed_keyinudpv6_destroy_sock().
v1->v2:
- addudp_encap_disable()and export it.v2->v3:
- add the change for rxrpc and bareudp into one patch, as Alex suggested.v3->v4:
- move rxrpc part to another patch.
Quoted 1 line
Signed-off-by Xin Long <[email protected]>
Re: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO
In reply to Xin LongHi, Jakub,
I saw the state of this patchset is still new, should I repost it?
Quoted 24 lines · Xin Long
Currently, udp v6 socket can not process v4 packets with UDP GRO, as
udp_encap_needed_keyis not increased whenudp_tunnel_encap_enable()is called for v6 socket.This patchset is to increase it and remove the unnecessary code in bareudp in Patch 1/2, and improve rxrpc
encap_enableby callingudp_tunnel_encap_enable().Xin Long (2):
udp: calludp_encap_enablefor v6 sockets when enabling encap
rxrpc: calludp_tunnel_encap_enableinrxrpc_open_socketdrivers/net/bareudp.c | 6 ------ include/net/udp.h | 1 + include/net/udp_tunnel.h | 3 +-- net/ipv4/udp.c | 6 ++++++ net/ipv6/udp.c | 4 +++- net/rxrpc/local_object.c | 6 +----- 6 files changed, 12 insertions(+), 14 deletions(-)--
2.1.0
David Howells
maintainerRe: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO
Quoted 1 line · Xin Long
I saw the state of this patchset is still new, should I repost it?
It needs a fix in patch 2 (see my response to that patch).
Thanks,
David
Re: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO
Quoted 7 lines · David Howells
Quoted 1 line · Xin Long
I saw the state of this patchset is still new, should I repost it?
It needs a fix in patch 2 (see my response to that patch).
Sorry, my mistake, I forgot to enable rxrpc when building kernel. Will repost, Thank you.
BTW, I'm also thinking to use udp_sock_create(), the only problem I can see is it may not do bind() in rxrpc_open_socket(), is that true? or we can actually bind to some address when a local address is not supplied?
David Howells
maintainerRe: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO
Quoted 3 lines · Xin Long
BTW, I'm also thinking to use
udp_sock_create(), the only problem I can see is it may not dobind()inrxrpc_open_socket(), is that true? or we can actually bind to some address when a local address is not supplied?
If a local address isn't explicitly bound to the AF_RXRPC socket, binding the UDP socket to a random local port is fine. In fact, sometimes I want to explicitly bind an rxrpc server socket to a random port. See fs/afs/rxrpc.c function afs_open_socket():
/* bind the callback manager's address to make this a server socket */
memset(&srx, 0, sizeof(srx));
srx.srx_family = AF_RXRPC;
srx.srx_service = CM_SERVICE;
srx.transport_type = SOCK_DGRAM;
srx.transport_len = sizeof(srx.transport.sin6);
srx.transport.sin6.sin6_family = AF_INET6;
srx.transport.sin6.sin6_port = htons(AFS_CM_PORT);
...
ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
if (ret == -EADDRINUSE) {
srx.transport.sin6.sin6_port = 0;
^^^ That's hoping to get a random port bound.
ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
}
if (ret < 0)
goto error_2;The client cache manager server socket here is used to receive notifications back from the fileserver. There's a standard port (7001) for the service, but if that's in use, we can use any other port. The fileserver grabs the source port from incoming RPC requests - and then uses that when sending 3rd-party change notifications back.
If you could arrange for a random port to be assigned in such a case (and indicated back to the caller), that would be awesome. Possibly I just don't need to actually use bind in this case.
David
Re: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO
Quoted 38 lines · David Howells
Quoted 3 lines · Xin Long
BTW, I'm also thinking to use
udp_sock_create(), the only problem I can see is it may not dobind()inrxrpc_open_socket(), is that true? or we can actually bind to some address when a local address is not supplied?If a local address isn't explicitly bound to the
AF_RXRPCsocket, binding the UDP socket to a random local port is fine. In fact, sometimes I want to explicitly bind an rxrpc server socket to a random port. Seefs/afs/rxrpc.cfunctionafs_open_socket():/* bind the callback manager's address to make this a server socket */ memset(&srx, 0, sizeof(srx)); srx.srx_family = AF_RXRPC; srx.srx_service = CM_SERVICE; srx.transport_type = SOCK_DGRAM; srx.transport_len = sizeof(srx.transport.sin6); srx.transport.sin6.sin6_family = AF_INET6; srx.transport.sin6.sin6_port = htons(AFS_CM_PORT); ... ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx)); if (ret == -EADDRINUSE) { srx.transport.sin6.sin6_port = 0; ^^^ That's hoping to get a random port bound. ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx)); } if (ret < 0) goto error_2;The client cache manager server socket here is used to receive notifications back from the fileserver. There's a standard port (7001) for the service, but if that's in use, we can use any other port. The fileserver grabs the source port from incoming RPC requests - and then uses that when sending 3rd-party change notifications back.
Quoted 4 lines
If you could arrange for a random port to be assigned in such a case (and indicated back to the caller), that would be awesome. Possibly I just don't need to actually use bind in this case.
The patch is attached (based on this patch):
+ udp_conf.family = srx->transport.family;
+ if (udp_conf.family == AF_INET) {
+ udp_conf.local_ip = srx->transport.sin.sin_addr;
+ udp_conf.local_udp_port = srx->transport.sin.sin_port;
+ } else {
+ udp_conf.local_ip6 = srx->transport.sin6.sin6_addr;
+ udp_conf.local_udp_port = srx->transport.sin6.sin6_port;
+ }
+ ret = udp_sock_create(net, &udp_conf, &local->socket);
I think this will work well. When the socket is not bound, srx->transport.sin.sin(6)_addr/sin(6)_port are zero. It'll bind to a random port in udp_sock_create().
BTW: do you have any testing for this?
Thanks.
From 5748d6312ad8025f6e347a0b067b204320b1c770 Mon Sep 17 00:00:00 2001
Message-Id: <5748d6312ad8025f6e347a0b067b204320b1c770.1612359043.git.lucien.xin@gmail.com>
From: Xin Long <[email protected]>
Date: Wed, 3 Feb 2021 08:25:28 -0500
Subject: [PATCH net-next] rxrpc: use udp tunnel APIs instead of open code in
rxrpc_open_socket
--- net/rxrpc/local_object.c | 69 ++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 45 deletions(-)
net/rxrpc/local_object.c +24 -45
@@ -107,54 +107,42 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,*/ static int rxrpc_open_socket (struct rxrpc_local *local,struct net *net) { +struct udp_tunnel_sock_cfg tuncfg = {NULL }; +struct sockaddr_rxrpc *srx = &local->srx; +struct udp_port_cfg udp_conf = {0 };struct sock *usk;int ret;_enter ("%p{%d,%d}" , - local, local->srx.transport_type, local->srx.transport.family); - -/* create a socket to represent the local endpoint */ - ret =sock_create_kern (net, local->srx.transport.family, - local->srx.transport_type,0 , &local->socket); + local, srx->transport_type, srx->transport.family); + + udp_conf.family = srx->transport.family; +if (udp_conf.family ==AF_INET ) { + udp_conf.local_ip = srx->transport.sin.sin_addr; + udp_conf.local_udp_port = srx->transport.sin.sin_port; + }else { + udp_conf.local_ip6 = srx->transport.sin6.sin6_addr; + udp_conf.local_udp_port = srx->transport.sin6.sin6_port; + } + ret =udp_sock_create (net, &udp_conf, &local->socket);if (ret <0 ) {_leave (" = %d [socket]" , ret);return ret; } + tuncfg.encap_type =UDP_ENCAP_RXRPC ; + tuncfg.encap_rcv = rxrpc_input_packet; + tuncfg.sk_user_data = local; +setup_udp_tunnel_sock (net, local->socket, &tuncfg); +/* set the socket up */ usk = local->socket->sk; -inet_sk (usk)->mc_loop =0 ; - -/* Enable CHECKSUM_UNNECESSARY to CHECKSUM_COMPLETE conversion */ -inet_inc_convert_csum (usk); - -rcu_assign_sk_user_data (usk, local); - -udp_sk (usk)->encap_type =UDP_ENCAP_RXRPC ; -udp_sk (usk)->encap_rcv = rxrpc_input_packet; -udp_sk (usk)->encap_destroy =NULL ; -udp_sk (usk)->gro_receive =NULL ; -udp_sk (usk)->gro_complete =NULL ; - -udp_tunnel_encap_enable (local->socket); usk->sk_error_report = rxrpc_error_report; -/* if a local address was supplied then bind it */ -if (local->srx.transport_len >sizeof (sa_family_t)) { -_debug ("bind" ); - ret =kernel_bind (local->socket, - (struct sockaddr *)&local->srx.transport, - local->srx.transport_len); -if (ret <0 ) { -_debug ("bind failed %d" , ret); - goto error; - } - } - -switch (local->srx.transport.family) { +switch (srx->transport.family) {case AF_INET6 :/* we want to receive ICMPv6 errors */ -ip6_sock_set_recverr (local->socket->sk); +ip6_sock_set_recverr (usk);/* Fall through and set IPv4 options too otherwise we don't get * errors from IPv4 packets sent through the IPv6 socket.
@@ -162,13 +150,13 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net) fallthrough;case AF_INET :/* we want to receive ICMP errors */ -ip_sock_set_recverr (local->socket->sk); +ip_sock_set_recverr (usk);/* we want to set the don't fragment bit */ -ip_sock_set_mtu_discover (local->socket->sk,IP_PMTUDISC_DO ); +ip_sock_set_mtu_discover (usk,IP_PMTUDISC_DO );/* We want receive timestamps. */ -sock_enable_timestamps (local->socket->sk); +sock_enable_timestamps (usk);break ;default :
@@ -177,15 +165,6 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)_leave (" = 0" );return 0 ; - -error: -kernel_sock_shutdown (local->socket,SHUT_RDWR ); - local->socket->sk->sk_user_data =NULL ; -sock_release (local->socket); - local->socket =NULL ; - -_leave (" = %d" , ret); -return ret; }/*
Signature · 1 line
2.18.1
David Howells
maintainerRe: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO
Quoted 1 line · Xin Long
BTW: do you have any testing for this?
If you're using a distro like a recent-ish Fedora or, I think, Debian, you should be able to install a kafs-client package. If that works, start the afs.mount service with systemctl and then look in /afs. You should see directories corresponding to a bunch of places that you can try accessing. I recommend you try "ls /afs/openafs.org".
If you don't have that available, if you have the keyutils package installed, you can try:
mount -t afs %openafs.org:root.cell /mnt
then do "ls /mnt".
David
David Howells
maintainerRe: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO
In reply to Xin LongQuoted 5 lines · Xin Long
Quoted 4 lines
If you could arrange for a random port to be assigned in such a case (and indicated back to the caller), that would be awesome. Possibly I just don't need to actually use bind in this case.
The patch is attached (based on this patch):
Initial testing seems to show that it works. I'll poke at it some more tomorrow.
David
David Howells
maintainerRe: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO
In reply to Xin LongQuoted 4 lines · Xin Long
Subject: [PATCH net-next] rxrpc: use udp tunnel APIs instead of open code in
rxrpc_open_socketSigned-off-by Xin Long <[email protected]>
You can add "Acked-by: David Howells <[email protected]>" if you want.
David
Re: [PATCHv4 net-next 0/2] net: enable udp v6 sockets receiving v4 packets with UDP GRO
Quoted 10 lines · David Howells
Quoted 4 lines · Xin Long
Subject: [PATCH net-next] rxrpc: use udp tunnel APIs instead of open code in
rxrpc_open_socketSigned-off-by Xin Long <[email protected]>You can add "Acked-by: David Howells <[email protected]>" if you want.
OK, Thank you so much!