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