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