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