mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 19:51:31 -04:00
tcp/udp: Make early_demux back namespacified.
commit 11052589cf5c0bab3b4884d423d5f60c38fcf25d upstream. Commite21145a987("ipv4: namespacify ip_early_demux sysctl knob") made it possible to enable/disable early_demux on a per-netns basis. Then, we introduced two knobs, tcp_early_demux and udp_early_demux, to switch it for TCP/UDP in commitdddb64bcb3("net: Add sysctl to toggle early demux for tcp and udp"). However, the .proc_handler() was wrong and actually disabled us from changing the behaviour in each netns. We can execute early_demux if net.ipv4.ip_early_demux is on and each proto .early_demux() handler is not NULL. When we toggle (tcp|udp)_early_demux, the change itself is saved in each netns variable, but the .early_demux() handler is a global variable, so the handler is switched based on the init_net's sysctl variable. Thus, netns (tcp|udp)_early_demux knobs have nothing to do with the logic. Whether we CAN execute proto .early_demux() is always decided by init_net's sysctl knob, and whether we DO it or not is by each netns ip_early_demux knob. This patch namespacifies (tcp|udp)_early_demux again. For now, the users of the .early_demux() handler are TCP and UDP only, and they are called directly to avoid retpoline. So, we can remove the .early_demux() handler from inet6?_protos and need not dereference them in ip6?_rcv_finish_core(). If another proto needs .early_demux(), we can restore it at that time. Fixes:dddb64bcb3("net: Add sysctl to toggle early demux for tcp and udp") Signed-off-by: Kuniyuki Iwashima <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
This commit is contained in:
parent
4ae03c869c
commit
fe3da74428
9 changed files with 48 additions and 113 deletions
|
|
@ -44,21 +44,25 @@
|
|||
#include <net/inet_ecn.h>
|
||||
#include <net/dst_metadata.h>
|
||||
|
||||
INDIRECT_CALLABLE_DECLARE(void udp_v6_early_demux(struct sk_buff *));
|
||||
INDIRECT_CALLABLE_DECLARE(void tcp_v6_early_demux(struct sk_buff *));
|
||||
void udp_v6_early_demux(struct sk_buff *);
|
||||
void tcp_v6_early_demux(struct sk_buff *);
|
||||
static void ip6_rcv_finish_core(struct net *net, struct sock *sk,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
void (*edemux)(struct sk_buff *skb);
|
||||
|
||||
if (net->ipv4.sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) {
|
||||
const struct inet6_protocol *ipprot;
|
||||
|
||||
ipprot = rcu_dereference(inet6_protos[ipv6_hdr(skb)->nexthdr]);
|
||||
if (ipprot && (edemux = READ_ONCE(ipprot->early_demux)))
|
||||
INDIRECT_CALL_2(edemux, tcp_v6_early_demux,
|
||||
udp_v6_early_demux, skb);
|
||||
if (READ_ONCE(net->ipv4.sysctl_ip_early_demux) &&
|
||||
!skb_dst(skb) && !skb->sk) {
|
||||
switch (ipv6_hdr(skb)->nexthdr) {
|
||||
case IPPROTO_TCP:
|
||||
if (READ_ONCE(net->ipv4.sysctl_tcp_early_demux))
|
||||
tcp_v6_early_demux(skb);
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
if (READ_ONCE(net->ipv4.sysctl_udp_early_demux))
|
||||
udp_v6_early_demux(skb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!skb_valid_dst(skb))
|
||||
ip6_route_input(skb);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1729,7 +1729,7 @@ do_time_wait:
|
|||
goto discard_it;
|
||||
}
|
||||
|
||||
INDIRECT_CALLABLE_SCOPE void tcp_v6_early_demux(struct sk_buff *skb)
|
||||
void tcp_v6_early_demux(struct sk_buff *skb)
|
||||
{
|
||||
const struct ipv6hdr *hdr;
|
||||
const struct tcphdr *th;
|
||||
|
|
@ -2084,12 +2084,7 @@ struct proto tcpv6_prot = {
|
|||
.diag_destroy = tcp_abort,
|
||||
};
|
||||
|
||||
/* thinking of making this const? Don't.
|
||||
* early_demux can change based on sysctl.
|
||||
*/
|
||||
static struct inet6_protocol tcpv6_protocol = {
|
||||
.early_demux = tcp_v6_early_demux,
|
||||
.early_demux_handler = tcp_v6_early_demux,
|
||||
static const struct inet6_protocol tcpv6_protocol = {
|
||||
.handler = tcp_v6_rcv,
|
||||
.err_handler = tcp_v6_err,
|
||||
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
|
||||
|
|
|
|||
|
|
@ -973,7 +973,7 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
INDIRECT_CALLABLE_SCOPE void udp_v6_early_demux(struct sk_buff *skb)
|
||||
void udp_v6_early_demux(struct sk_buff *skb)
|
||||
{
|
||||
struct net *net = dev_net(skb->dev);
|
||||
const struct udphdr *uh;
|
||||
|
|
@ -1603,12 +1603,7 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* thinking of making this const? Don't.
|
||||
* early_demux can change based on sysctl.
|
||||
*/
|
||||
static struct inet6_protocol udpv6_protocol = {
|
||||
.early_demux = udp_v6_early_demux,
|
||||
.early_demux_handler = udp_v6_early_demux,
|
||||
static const struct inet6_protocol udpv6_protocol = {
|
||||
.handler = udpv6_rcv,
|
||||
.err_handler = udpv6_err,
|
||||
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
|
||||
|
|
|
|||
Loading…
Reference in a new issue