• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2024 Huawei Device Co., Ltd.
4  *
5  * Operations on the lowpower protocol
6  * Authors: yangyanjun
7  */
8 #ifdef CONFIG_LOWPOWER_PROTOCOL
9 #include <linux/types.h>
10 #include <linux/kernel.h>
11 #include <linux/proc_fs.h>
12 #include <linux/printk.h>
13 #include <linux/net_namespace.h>
14 #include <net/sock.h>
15 #include <net/ip.h>
16 #include <net/tcp.h>
17 #include <net/lowpower_protocol.h>
18 
19 static atomic_t g_foreground_uid = ATOMIC_INIT(FOREGROUND_UID_INIT);
20 
foreground_uid_atomic_set(uid_t val)21 static void foreground_uid_atomic_set(uid_t val)
22 {
23 	atomic_set(&g_foreground_uid, val);
24 }
25 
foreground_uid_atomic_read(void)26 static uid_t foreground_uid_atomic_read(void)
27 {
28 	return (uid_t)atomic_read(&g_foreground_uid);
29 }
30 
foreground_uid_show(struct seq_file * seq,void * v)31 static int foreground_uid_show(struct seq_file *seq, void *v)
32 {
33 	uid_t uid = foreground_uid_atomic_read();
34 
35 	seq_printf(seq, "%u\n", uid);
36 	return 0;
37 }
38 
39 // echo xx > /proc/net/foreground_uid
foreground_uid_write(struct file * file,char * buf,size_t size)40 static int foreground_uid_write(struct file *file, char *buf, size_t size)
41 {
42 	char *p = buf;
43 	uid_t uid = simple_strtoul(p, &p, 10);
44 
45 	if (!p)
46 		return -EINVAL;
47 
48 	foreground_uid_atomic_set(uid);
49 	return 0;
50 }
51 
52 // call this fun in net/ipv4/af_inet.c inet_init_net()
lowpower_protocol_net_init(struct net * net)53 void __net_init lowpower_protocol_net_init(struct net *net)
54 {
55 	if (!proc_create_net_single_write("foreground_uid", 0644,
56 					  net->proc_net,
57 					  foreground_uid_show,
58 					  foreground_uid_write,
59 					  NULL))
60 		pr_err("fail to register /proc/net/foreground_uid");
61 }
62 
foreground_uid_match(struct net * net,struct sock * sk)63 static bool foreground_uid_match(struct net *net, struct sock *sk)
64 {
65 	uid_t kuid;
66 	uid_t foreground_uid;
67 	struct sock *fullsk;
68 
69 	if (!net || !sk)
70 		return false;
71 
72 	fullsk = sk_to_full_sk(sk);
73 	if (!fullsk || !sk_fullsock(fullsk))
74 		return false;
75 
76 	kuid = sock_net_uid(net, fullsk).val;
77 	foreground_uid = foreground_uid_atomic_read();
78 	if (kuid != foreground_uid)
79 		return false;
80 
81 	return true;
82 }
83 
84 /*
85  * ack optimization is only enable for large data receiving tasks and
86  * there is no packet loss scenario
87  */
tcp_ack_num(struct sock * sk)88 int tcp_ack_num(struct sock *sk)
89 {
90 	if (!sk)
91 		return 1;
92 
93 	if (foreground_uid_match(sock_net(sk), sk) == false)
94 		return 1;
95 
96 	if (tcp_sk(sk)->bytes_received >= BIG_DATA_BYTES &&
97 	    tcp_sk(sk)->dup_ack_counter < TCP_FASTRETRANS_THRESH)
98 		return TCP_ACK_NUM;
99 	return 1;
100 }
101 
netfilter_bypass_enable(struct net * net,struct sk_buff * skb,int (* fun)(struct net *,struct sock *,struct sk_buff *),int * ret)102 bool netfilter_bypass_enable(struct net *net, struct sk_buff *skb,
103 			     int (*fun)(struct net *, struct sock *, struct sk_buff *),
104 			     int *ret)
105 {
106 	if (!net || !skb || !ip_hdr(skb) || ip_hdr(skb)->protocol != IPPROTO_TCP)
107 		return false;
108 
109 	if (foreground_uid_match(net, skb->sk)) {
110 		*ret = fun(net, NULL, skb);
111 		return true;
112 	}
113 	return false;
114 }
115 #endif /* CONFIG_LOWPOWER_PROTOCOL */
116