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