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 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 int open_tuntap(const char *dev_name, bool need_mac); 90 91 struct nstoken; 92 /** 93 * open_netns() - Switch to specified network namespace by name. 94 * 95 * Returns token with which to restore the original namespace 96 * using close_netns(). 97 */ 98 struct nstoken *open_netns(const char *name); 99 void close_netns(struct nstoken *token); 100 int send_recv_data(int lfd, int fd, uint32_t total_bytes); 101 int make_netns(const char *name); 102 int remove_netns(const char *name); 103 104 static __u16 csum_fold(__u32 csum) 105 { 106 csum = (csum & 0xffff) + (csum >> 16); 107 csum = (csum & 0xffff) + (csum >> 16); 108 109 return (__u16)~csum; 110 } 111 112 static __wsum csum_partial(const void *buf, int len, __wsum sum) 113 { 114 __u16 *p = (__u16 *)buf; 115 int num_u16 = len >> 1; 116 int i; 117 118 for (i = 0; i < num_u16; i++) 119 sum += p[i]; 120 121 return sum; 122 } 123 124 static inline __sum16 build_ip_csum(struct iphdr *iph) 125 { 126 __u32 sum = 0; 127 __u16 *p; 128 129 iph->check = 0; 130 p = (void *)iph; 131 sum = csum_partial(p, iph->ihl << 2, 0); 132 133 return csum_fold(sum); 134 } 135 136 /** 137 * csum_tcpudp_magic - compute IP pseudo-header checksum 138 * 139 * Compute the IPv4 pseudo header checksum. The helper can take a 140 * accumulated sum from the transport layer to accumulate it and directly 141 * return the transport layer 142 * 143 * @saddr: IP source address 144 * @daddr: IP dest address 145 * @len: IP data size 146 * @proto: transport layer protocol 147 * @csum: The accumulated partial sum to add to the computation 148 * 149 * Returns the folded sum 150 */ 151 static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, 152 __u32 len, __u8 proto, 153 __wsum csum) 154 { 155 __u64 s = csum; 156 157 s += (__u32)saddr; 158 s += (__u32)daddr; 159 s += htons(proto + len); 160 s = (s & 0xffffffff) + (s >> 32); 161 s = (s & 0xffffffff) + (s >> 32); 162 163 return csum_fold((__u32)s); 164 } 165 166 /** 167 * csum_ipv6_magic - compute IPv6 pseudo-header checksum 168 * 169 * Compute the ipv6 pseudo header checksum. The helper can take a 170 * accumulated sum from the transport layer to accumulate it and directly 171 * return the transport layer 172 * 173 * @saddr: IPv6 source address 174 * @daddr: IPv6 dest address 175 * @len: IPv6 data size 176 * @proto: transport layer protocol 177 * @csum: The accumulated partial sum to add to the computation 178 * 179 * Returns the folded sum 180 */ 181 static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr, 182 const struct in6_addr *daddr, 183 __u32 len, __u8 proto, 184 __wsum csum) 185 { 186 __u64 s = csum; 187 int i; 188 189 for (i = 0; i < 4; i++) 190 s += (__u32)saddr->s6_addr32[i]; 191 for (i = 0; i < 4; i++) 192 s += (__u32)daddr->s6_addr32[i]; 193 s += htons(proto + len); 194 s = (s & 0xffffffff) + (s >> 32); 195 s = (s & 0xffffffff) + (s >> 32); 196 197 return csum_fold((__u32)s); 198 } 199 200 /** 201 * build_udp_v4_csum - compute UDP checksum for UDP over IPv4 202 * 203 * Compute the checksum to embed in UDP header, composed of the sum of IP 204 * pseudo-header checksum, UDP header checksum and UDP data checksum 205 * @iph IP header 206 * @udph UDP header, which must be immediately followed by UDP data 207 * 208 * Returns the total checksum 209 */ 210 211 static inline __sum16 build_udp_v4_csum(const struct iphdr *iph, 212 const struct udphdr *udph) 213 { 214 unsigned long sum; 215 216 sum = csum_partial(udph, ntohs(udph->len), 0); 217 return csum_tcpudp_magic(iph->saddr, iph->daddr, ntohs(udph->len), 218 IPPROTO_UDP, sum); 219 } 220 221 /** 222 * build_udp_v6_csum - compute UDP checksum for UDP over IPv6 223 * 224 * Compute the checksum to embed in UDP header, composed of the sum of IPv6 225 * pseudo-header checksum, UDP header checksum and UDP data checksum 226 * @ip6h IPv6 header 227 * @udph UDP header, which must be immediately followed by UDP data 228 * 229 * Returns the total checksum 230 */ 231 static inline __sum16 build_udp_v6_csum(const struct ipv6hdr *ip6h, 232 const struct udphdr *udph) 233 { 234 unsigned long sum; 235 236 sum = csum_partial(udph, ntohs(udph->len), 0); 237 return csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, ntohs(udph->len), 238 IPPROTO_UDP, sum); 239 } 240 241 struct tmonitor_ctx; 242 243 #ifdef TRAFFIC_MONITOR 244 struct tmonitor_ctx *traffic_monitor_start(const char *netns, const char *test_name, 245 const char *subtest_name); 246 void traffic_monitor_stop(struct tmonitor_ctx *ctx); 247 #else 248 static inline struct tmonitor_ctx *traffic_monitor_start(const char *netns, const char *test_name, 249 const char *subtest_name) 250 { 251 return NULL; 252 } 253 254 static inline void traffic_monitor_stop(struct tmonitor_ctx *ctx) 255 { 256 } 257 #endif 258 259 #endif 260