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