From c03739c72c836bae303a6204cb9e72dfbf07a779 Mon Sep 17 00:00:00 2001 From: yangyanjun Date: Sun, 7 Apr 2024 18:02:31 +0800 Subject: [PATCH] add lowpower protocol Signed-off-by: yangyanjun --- include/net/lowpower_protocol.h | 30 +++++++++ net/Kconfig | 7 ++ net/core/Makefile | 1 + net/core/lowpower_protocol.c | 110 ++++++++++++++++++++++++++++++++ net/ipv4/af_inet.c | 6 ++ net/ipv4/ip_input.c | 11 ++++ net/ipv4/tcp.c | 12 +++- net/ipv4/tcp_input.c | 10 ++- net/ipv4/tcp_output.c | 7 +- 9 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 include/net/lowpower_protocol.h create mode 100644 net/core/lowpower_protocol.c diff --git a/include/net/lowpower_protocol.h b/include/net/lowpower_protocol.h new file mode 100644 index 000000000000..afe525e12192 --- /dev/null +++ b/include/net/lowpower_protocol.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Operations on the lowpower protocol + * Authors: yangyanjun + */ +#ifndef __LOWPOWER_PROTOCOL_H +#define __LOWPOWER_PROTOCOL_H + +#ifdef CONFIG_LOWPOWER_PROTOCOL +#include +#include +#include +#include +#include +#include + +#define FOREGROUND_UID_INIT 0xEFFFFFFF +#define TCP_RCV_WND_INIT 133120 +#define BIG_DATA_BYTES 200000 +#define TCP_ACK_NUM 30 + +void __net_init lowpower_protocol_net_init(struct net *net); +int tcp_ack_num(struct sock *sk); +bool netfilter_bypass_enable(struct net *net, struct sk_buff *skb, + int (*fun)(struct net *, struct sock *, struct sk_buff *), + int *ret); +#endif /* CONFIG_LOWPOWER_PROTOCOL */ +#endif /* __LOWPOWER_PROTOCOL_H */ \ No newline at end of file diff --git a/net/Kconfig b/net/Kconfig index b07ee3b024ab..6f863a06fbc5 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -466,6 +466,13 @@ config TCP_NB_URC This option enables the NetiBooster Ultra-Reliable Connection feature. When enabled, the kernel will include support for CONFIG_TCP_NB_URC. +config LOWPOWER_PROTOCOL + bool "lowpower protocol" + default n + help + This option enables the lowpower protocol feature. + When enabled, the kernel will include support for CONFIG_LOWPOWER_PROTOCOL. + endif # if NET # Used by archs to tell that they support BPF JIT compiler plus which flavour. diff --git a/net/core/Makefile b/net/core/Makefile index 3e2c378e5f31..71db490d0732 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -35,3 +35,4 @@ obj-$(CONFIG_NET_DEVLINK) += devlink.o obj-$(CONFIG_GRO_CELLS) += gro_cells.o obj-$(CONFIG_FAILOVER) += failover.o obj-$(CONFIG_BPF_SYSCALL) += bpf_sk_storage.o +obj-$(CONFIG_LOWPOWER_PROTOCOL) += lowpower_protocol.o diff --git a/net/core/lowpower_protocol.c b/net/core/lowpower_protocol.c new file mode 100644 index 000000000000..a428f233e8db --- /dev/null +++ b/net/core/lowpower_protocol.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * + * Operations on the lowpower protocol + * Authors: yangyanjun + */ +#ifdef CONFIG_LOWPOWER_PROTOCOL +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static atomic_t g_foreground_uid = ATOMIC_INIT(FOREGROUND_UID_INIT); + +static void foreground_uid_atomic_set(uid_t val) +{ + atomic_set(&g_foreground_uid, val); +} + +static uid_t foreground_uid_atomic_read(void) +{ + return (uid_t)atomic_read(&g_foreground_uid); +} + +static int foreground_uid_show(struct seq_file *seq, void *v) +{ + uid_t uid = foreground_uid_atomic_read(); + + seq_printf(seq, "%u\n", uid); + return 0; +} + +// echo xx > /proc/net/foreground_uid +static int foreground_uid_write(struct file *file, char *buf, size_t size) +{ + char *p = buf; + uid_t uid = simple_strtoul(p, &p, 10); + + if (!p) + return -EINVAL; + + foreground_uid_atomic_set(uid); + return 0; +} + +// call this fun in net/ipv4/af_inet.c inet_init_net() +void __net_init lowpower_protocol_net_init(struct net *net) +{ + if (!proc_create_net_single_write("foreground_uid", 0644, + net->proc_net, + foreground_uid_show, + foreground_uid_write, + NULL)) + pr_err("fail to register /proc/net/foreground_uid"); +} + +static bool foreground_uid_match(struct net *net, struct sock *sk) +{ + uid_t kuid; + uid_t foreground_uid; + + if (!sk) + return false; + + kuid = sock_net_uid(net, sk).val; + foreground_uid = foreground_uid_atomic_read(); + if (kuid != foreground_uid) + return false; + + return true; +} + +/* + * ack optimization is only enable for large data receiving tasks and + * there is no packet loss scenario + */ +int tcp_ack_num(struct sock *sk) +{ + if (!sk) + return 1; + + if (foreground_uid_match(sock_net(sk), sk) == false) + return 1; + + if (tcp_sk(sk)->bytes_received >= BIG_DATA_BYTES && + tcp_sk(sk)->dup_ack_counter < TCP_FASTRETRANS_THRESH) + return TCP_ACK_NUM; + return 1; +} + +bool netfilter_bypass_enable(struct net *net, struct sk_buff *skb, + int (*fun)(struct net *, struct sock *, struct sk_buff *), + int *ret) +{ + if (!net || !skb || ip_hdr(skb)->protocol != IPPROTO_TCP) + return false; + + if (foreground_uid_match(net, skb->sk)) { + *ret = fun(net, NULL, skb); + return true; + } + return false; +} +#endif /* CONFIG_LOWPOWER_PROTOCOL */ diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index dcc1df34b10f..96f74ba1b28b 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -117,6 +117,9 @@ #endif #include #include +#ifdef CONFIG_LOWPOWER_PROTOCOL +#include +#endif /* CONFIG_LOWPOWER_PROTOCOL */ #include @@ -1877,6 +1880,9 @@ static __net_init int inet_init_net(struct net *net) net->ipv4.sysctl_igmp_llm_reports = 1; net->ipv4.sysctl_igmp_qrv = 2; +#ifdef CONFIG_LOWPOWER_PROTOCOL + lowpower_protocol_net_init(net); +#endif /* CONFIG_LOWPOWER_PROTOCOL */ return 0; } diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index eccd7897e7aa..72f249be44a0 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -141,6 +141,9 @@ #include #include #include +#ifdef CONFIG_LOWPOWER_PROTOCOL +#include +#endif /* CONFIG_LOWPOWER_PROTOCOL */ /* * Process Router Attention IP option (RFC 2113) @@ -243,12 +246,20 @@ int ip_local_deliver(struct sk_buff *skb) * Reassemble IP fragments. */ struct net *net = dev_net(skb->dev); +#ifdef CONFIG_LOWPOWER_PROTOCOL + int ret; +#endif /* CONFIG_LOWPOWER_PROTOCOL */ if (ip_is_fragment(ip_hdr(skb))) { if (ip_defrag(net, skb, IP_DEFRAG_LOCAL_DELIVER)) return 0; } +#ifdef CONFIG_LOWPOWER_PROTOCOL + if (netfilter_bypass_enable(net, skb, ip_local_deliver_finish, &ret)) + return ret; +#endif /* CONFIG_LOWPOWER_PROTOCOL */ + return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, net, NULL, skb, skb->dev, NULL, ip_local_deliver_finish); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index ccb58ac269af..066c10dfde2a 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -279,6 +279,9 @@ #include #include #include +#ifdef CONFIG_LOWPOWER_PROTOCOL +#include +#endif /* CONFIG_LOWPOWER_PROTOCOL */ DEFINE_PER_CPU(unsigned int, tcp_orphan_count); EXPORT_PER_CPU_SYMBOL_GPL(tcp_orphan_count); @@ -1553,9 +1556,13 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied) if (inet_csk_ack_scheduled(sk)) { const struct inet_connection_sock *icsk = inet_csk(sk); + __u16 rcv_mss = icsk->icsk_ack.rcv_mss; +#ifdef CONFIG_LOWPOWER_PROTOCOL + rcv_mss *= tcp_ack_num(sk); +#endif /* CONFIG_LOWPOWER_PROTOCOL */ if (/* Once-per-two-segments ACK was not sent by tcp_input.c */ - tp->rcv_nxt - tp->rcv_wup > icsk->icsk_ack.rcv_mss || + tp->rcv_nxt - tp->rcv_wup > rcv_mss || /* * If this read emptied read buffer, we send ACK, if * connection is not bidirectional, user drained @@ -3156,7 +3163,8 @@ int tcp_sock_set_keepcnt(struct sock *sk, int val) EXPORT_SYMBOL(tcp_sock_set_keepcnt); #ifdef CONFIG_TCP_NB_URC -static int tcp_set_nb_urc(struct sock *sk, sockptr_t optval, int optlen) { +static int tcp_set_nb_urc(struct sock *sk, sockptr_t optval, int optlen) +{ int err = 0; struct tcp_nb_urc opt = {}; struct inet_connection_sock *icsk = inet_csk(sk); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index d6dfbb88dcf5..dcc50f3e1850 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -80,6 +80,9 @@ #include #include #include +#ifdef CONFIG_LOWPOWER_PROTOCOL +#include +#endif /* CONFIG_LOWPOWER_PROTOCOL */ int sysctl_tcp_max_orphans __read_mostly = NR_FILE; @@ -5456,9 +5459,12 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible) { struct tcp_sock *tp = tcp_sk(sk); unsigned long rtt, delay; - + __u16 rcv_mss = inet_csk(sk)->icsk_ack.rcv_mss; +#ifdef CONFIG_LOWPOWER_PROTOCOL + rcv_mss *= tcp_ack_num(sk); +#endif /* CONFIG_LOWPOWER_PROTOCOL */ /* More than one full frame received... */ - if (((tp->rcv_nxt - tp->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss && + if (((tp->rcv_nxt - tp->rcv_wup) > rcv_mss && /* ... and right edge of window advances far enough. * (tcp_recvmsg() will send ACK otherwise). * If application uses SO_RCVLOWAT, we want send ack now if diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index a2fa68588ad5..2437d43059e8 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -44,7 +44,9 @@ #include #include #include - +#ifdef CONFIG_LOWPOWER_PROTOCOL +#include +#endif /* CONFIG_LOWPOWER_PROTOCOL */ #include /* Refresh clocks of a TCP socket, @@ -3700,6 +3702,9 @@ static void tcp_connect_init(struct sock *sk) &rcv_wscale, rcv_wnd); +#ifdef CONFIG_LOWPOWER_PROTOCOL + tp->rcv_wnd = TCP_RCV_WND_INIT; +#endif /* CONFIG_LOWPOWER_PROTOCOL */ tp->rx_opt.rcv_wscale = rcv_wscale; tp->rcv_ssthresh = tp->rcv_wnd; -- Gitee