xref: /linux/tools/testing/selftests/bpf/network_helpers.h (revision 4f9786035f9e519db41375818e1d0b5f20da2f10)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __NETWORK_HELPERS_H
3 #define __NETWORK_HELPERS_H
4 #include <arpa/inet.h>
5 #include <sys/socket.h>
6 #include <sys/types.h>
7 #include <linux/types.h>
8 typedef __u16 __sum16;
9 #include <linux/if_ether.h>
10 #include <linux/if_packet.h>
11 #include <linux/if_tun.h>
12 #include <linux/ip.h>
13 #include <linux/ipv6.h>
14 #include <linux/ethtool.h>
15 #include <linux/sockios.h>
16 #include <linux/err.h>
17 #include <netinet/tcp.h>
18 #include <netinet/udp.h>
19 #include <bpf/bpf_endian.h>
20 #include <net/if.h>
21 #include <stdio.h>
22 
23 #define MAGIC_VAL 0x1234
24 #define NUM_ITER 100000
25 #define VIP_NUM 5
26 #define MAGIC_BYTES 123
27 
28 struct network_helper_opts {
29 	int timeout_ms;
30 	int proto;
31 	/* +ve: Passed to listen() as-is.
32 	 *   0: Default when the test does not set
33 	 *      a particular value during the struct init.
34 	 *      It is changed to 1 before passing to listen().
35 	 *      Most tests only have one on-going connection.
36 	 * -ve: It is changed to 0 before passing to listen().
37 	 *      It is useful to force syncookie without
38 	 *	changing the "tcp_syncookies" sysctl from 1 to 2.
39 	 */
40 	int backlog;
41 	int (*post_socket_cb)(int fd, void *opts);
42 	void *cb_opts;
43 };
44 
45 /* ipv4 test vector */
46 struct ipv4_packet {
47 	struct ethhdr eth;
48 	struct iphdr iph;
49 	struct tcphdr tcp;
50 } __packed;
51 extern struct ipv4_packet pkt_v4;
52 
53 /* ipv6 test vector */
54 struct ipv6_packet {
55 	struct ethhdr eth;
56 	struct ipv6hdr iph;
57 	struct tcphdr tcp;
58 } __packed;
59 extern struct ipv6_packet pkt_v6;
60 
61 int settimeo(int fd, int timeout_ms);
62 int start_server_str(int family, int type, const char *addr_str, __u16 port,
63 		     const struct network_helper_opts *opts);
64 int start_server(int family, int type, const char *addr, __u16 port,
65 		 int timeout_ms);
66 int *start_reuseport_server(int family, int type, const char *addr_str,
67 			    __u16 port, int timeout_ms,
68 			    unsigned int nr_listens);
69 int start_server_addr(int type, const struct sockaddr_storage *addr, socklen_t len,
70 		      const struct network_helper_opts *opts);
71 void free_fds(int *fds, unsigned int nr_close_fds);
72 int client_socket(int family, int type,
73 		  const struct network_helper_opts *opts);
74 int connect_to_addr(int type, const struct sockaddr_storage *addr, socklen_t len,
75 		    const struct network_helper_opts *opts);
76 int connect_to_addr_str(int family, int type, const char *addr_str, __u16 port,
77 			const struct network_helper_opts *opts);
78 int connect_to_fd(int server_fd, int timeout_ms);
79 int connect_to_fd_opts(int server_fd, const struct network_helper_opts *opts);
80 int connect_fd_to_fd(int client_fd, int server_fd, int timeout_ms);
81 int fastopen_connect(int server_fd, const char *data, unsigned int data_len,
82 		     int timeout_ms);
83 int make_sockaddr(int family, const char *addr_str, __u16 port,
84 		  struct sockaddr_storage *addr, socklen_t *len);
85 char *ping_command(int family);
86 int get_socket_local_port(int sock_fd);
87 int get_hw_ring_size(char *ifname, struct ethtool_ringparam *ring_param);
88 int set_hw_ring_size(char *ifname, struct ethtool_ringparam *ring_param);
89 
90 int open_tuntap(const char *dev_name, bool need_mac);
91 
92 struct nstoken;
93 /**
94  * open_netns() - Switch to specified network namespace by name.
95  *
96  * Returns token with which to restore the original namespace
97  * using close_netns().
98  */
99 struct nstoken *open_netns(const char *name);
100 void close_netns(struct nstoken *token);
101 int send_recv_data(int lfd, int fd, uint32_t total_bytes);
102 int make_netns(const char *name);
103 int remove_netns(const char *name);
104 
105 /**
106  * append_tid() - Append thread ID to the given string.
107  *
108  * @str: string to extend
109  * @sz: string's size
110  *
111  * 8 characters are used to append the thread ID (7 digits + '\0')
112  *
113  * Returns -1 on errors, 0 otherwise
114  */
115 int append_tid(char *str, size_t sz);
116 
117 static __u16 csum_fold(__u32 csum)
118 {
119 	csum = (csum & 0xffff) + (csum >> 16);
120 	csum = (csum & 0xffff) + (csum >> 16);
121 
122 	return (__u16)~csum;
123 }
124 
125 static __wsum csum_partial(const void *buf, int len, __wsum sum)
126 {
127 	__u16 *p = (__u16 *)buf;
128 	int num_u16 = len >> 1;
129 	int i;
130 
131 	for (i = 0; i < num_u16; i++)
132 		sum += p[i];
133 
134 	return sum;
135 }
136 
137 static inline __sum16 build_ip_csum(struct iphdr *iph)
138 {
139 	__u32 sum = 0;
140 	__u16 *p;
141 
142 	iph->check = 0;
143 	p = (void *)iph;
144 	sum = csum_partial(p, iph->ihl << 2, 0);
145 
146 	return csum_fold(sum);
147 }
148 
149 /**
150  * csum_tcpudp_magic - compute IP pseudo-header checksum
151  *
152  * Compute the IPv4 pseudo header checksum. The helper can take a
153  * accumulated sum from the transport layer to accumulate it and directly
154  * return the transport layer
155  *
156  * @saddr: IP source address
157  * @daddr: IP dest address
158  * @len: IP data size
159  * @proto: transport layer protocol
160  * @csum: The accumulated partial sum to add to the computation
161  *
162  * Returns the folded sum
163  */
164 static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
165 					__u32 len, __u8 proto,
166 					__wsum csum)
167 {
168 	__u64 s = csum;
169 
170 	s += (__u32)saddr;
171 	s += (__u32)daddr;
172 	s += htons(proto + len);
173 	s = (s & 0xffffffff) + (s >> 32);
174 	s = (s & 0xffffffff) + (s >> 32);
175 
176 	return csum_fold((__u32)s);
177 }
178 
179 /**
180  * csum_ipv6_magic - compute IPv6 pseudo-header checksum
181  *
182  * Compute the ipv6 pseudo header checksum. The helper can take a
183  * accumulated sum from the transport layer to accumulate it and directly
184  * return the transport layer
185  *
186  * @saddr: IPv6 source address
187  * @daddr: IPv6 dest address
188  * @len: IPv6 data size
189  * @proto: transport layer protocol
190  * @csum: The accumulated partial sum to add to the computation
191  *
192  * Returns the folded sum
193  */
194 static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
195 				      const struct in6_addr *daddr,
196 					__u32 len, __u8 proto,
197 					__wsum csum)
198 {
199 	__u64 s = csum;
200 	int i;
201 
202 	for (i = 0; i < 4; i++)
203 		s += (__u32)saddr->s6_addr32[i];
204 	for (i = 0; i < 4; i++)
205 		s += (__u32)daddr->s6_addr32[i];
206 	s += htons(proto + len);
207 	s = (s & 0xffffffff) + (s >> 32);
208 	s = (s & 0xffffffff) + (s >> 32);
209 
210 	return csum_fold((__u32)s);
211 }
212 
213 /**
214  * build_udp_v4_csum - compute UDP checksum for UDP over IPv4
215  *
216  * Compute the checksum to embed in UDP header, composed of the sum of IP
217  * pseudo-header checksum, UDP header checksum and UDP data checksum
218  * @iph IP header
219  * @udph UDP header, which must be immediately followed by UDP data
220  *
221  * Returns the total checksum
222  */
223 
224 static inline __sum16 build_udp_v4_csum(const struct iphdr *iph,
225 					const struct udphdr *udph)
226 {
227 	unsigned long sum;
228 
229 	sum = csum_partial(udph, ntohs(udph->len), 0);
230 	return csum_tcpudp_magic(iph->saddr, iph->daddr, ntohs(udph->len),
231 				 IPPROTO_UDP, sum);
232 }
233 
234 /**
235  * build_udp_v6_csum - compute UDP checksum for UDP over IPv6
236  *
237  * Compute the checksum to embed in UDP header, composed of the sum of IPv6
238  * pseudo-header checksum, UDP header checksum and UDP data checksum
239  * @ip6h IPv6 header
240  * @udph UDP header, which must be immediately followed by UDP data
241  *
242  * Returns the total checksum
243  */
244 static inline __sum16 build_udp_v6_csum(const struct ipv6hdr *ip6h,
245 					const struct udphdr *udph)
246 {
247 	unsigned long sum;
248 
249 	sum = csum_partial(udph, ntohs(udph->len), 0);
250 	return csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, ntohs(udph->len),
251 			       IPPROTO_UDP, sum);
252 }
253 
254 struct tmonitor_ctx;
255 
256 typedef int (*tm_print_fn_t)(const char *format, va_list args);
257 
258 #ifdef TRAFFIC_MONITOR
259 struct tmonitor_ctx *traffic_monitor_start(const char *netns, const char *test_name,
260 					   const char *subtest_name);
261 void traffic_monitor_stop(struct tmonitor_ctx *ctx);
262 tm_print_fn_t traffic_monitor_set_print(tm_print_fn_t fn);
263 #else
264 static inline struct tmonitor_ctx *traffic_monitor_start(const char *netns, const char *test_name,
265 							 const char *subtest_name)
266 {
267 	return NULL;
268 }
269 
270 static inline void traffic_monitor_stop(struct tmonitor_ctx *ctx)
271 {
272 }
273 
274 static inline tm_print_fn_t traffic_monitor_set_print(tm_print_fn_t fn)
275 {
276 	return NULL;
277 }
278 #endif
279 
280 #endif
281