-
Notifications
You must be signed in to change notification settings - Fork 301
Expand file tree
/
Copy pathudp_benchmark.c
More file actions
158 lines (123 loc) · 4.85 KB
/
udp_benchmark.c
File metadata and controls
158 lines (123 loc) · 4.85 KB
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
/* Simple usage of two UDP sockets sending messages to eachother like ping/pong */
#include <libusockets.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef LIBUS_USE_IO_URING
/* This one we allow here since we use it to create the peer addr.
* We should remove this and replace it with bsd_addr_t and a builder function */
#include <netinet/in.h>
struct us_udp_packet_buffer_t *send_buf;
float messages = 0;
void on_wakeup(struct us_loop_t *loop) {
}
void on_pre(struct us_loop_t *loop) {
}
void on_post(struct us_loop_t *loop) {
/* It can be a good idea to use this callback
* for sending off what we have in our outgoing buffer */
}
void timer_cb(struct us_timer_t *timer) {
printf("Messages per second: %f\n", messages);
messages = 0;
}
/* Called whenever you can write more datagrams after a failure to write */
void on_server_drain(struct us_udp_socket_t *s) {
}
/* Called whenever there are received datagrams for the app to consume */
void on_server_data(struct us_udp_socket_t *s, struct us_udp_packet_buffer_t *buf, int packets) {
/* Iterate all received packets */
for (int i = 0; i < packets; i++) {
char *payload = us_udp_packet_buffer_payload(buf, i);
int length = us_udp_packet_buffer_payload_length(buf, i);
int ecn = us_udp_packet_buffer_ecn(buf, i);
void *peer_addr = us_udp_packet_buffer_peer(buf, i);
//printf("ECN is: %d\n", ecn);
char ip[16];
int ip_length = us_udp_packet_buffer_local_ip(buf, i, ip);
if (!ip_length) {
printf("We got no ip on received packet!\n");
exit(0);
}
//printf("Our received destination IP length is: %d\n", ip_length);
int port = us_udp_socket_bound_port(s);
//printf("We received packet on port: %d\n", port);
/* Echo it back */
us_udp_buffer_set_packet_payload(send_buf, i, 0, payload, length, peer_addr);
/* Let's count a one whole message as one whole roundtrip for easier comparison with TCP echo benchmark */
messages += 1;
}
int sent = us_udp_socket_send(s, send_buf, packets);
}
int main(int argc, char **argv) {
int is_client = 0;
int is_ipv6 = 0;
if (argc > 1 && !strcmp(argv[argc - 1], "ipv6")) {
is_ipv6 = 1;
printf("Using IPv6 UDP\n");
}
if (argc >= 2 && !strcmp(argv[1], "client")) {
is_client = 1;
printf("Running as client\n");
} else {
printf("Running as server\n");
}
/* Allocate per thread, UDP packet buffers */
struct us_udp_packet_buffer_t *receive_buf = us_create_udp_packet_buffer();
/* We also want a send buffer we can assemble while iterating the read buffer */
send_buf = us_create_udp_packet_buffer();
/* Create the event loop */
struct us_loop_t *loop = us_create_loop(0, on_wakeup, on_pre, on_post, 0);
/* Create two UDP sockets and bind them to their respective ports */
struct us_udp_socket_t *server;
struct us_udp_socket_t *client;
if (is_client) {
if (is_ipv6) {
client = us_create_udp_socket(loop, receive_buf, on_server_data, on_server_drain, "::1", 0, 0);
} else {
client = us_create_udp_socket(loop, receive_buf, on_server_data, on_server_drain, "127.0.0.1", 0, 0);
}
} else {
if (is_ipv6) {
server = us_create_udp_socket(loop, receive_buf, on_server_data, on_server_drain, "::1", 5678, 0);
} else {
server = us_create_udp_socket(loop, receive_buf, on_server_data, on_server_drain, "127.0.0.1", 5678, 0);
}
}
if (!client && !server) {
printf("Failed to create UDP sockets!\n");
return 1;
}
/* Send first packets from client to server */
/* This is ugly and needs to be wrapped in bsd_addr_t */
struct sockaddr_storage storage = {};
if (is_ipv6) {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *) &storage;
addr->sin6_addr.s6_addr[15] = 1;
addr->sin6_port = htons(5678);
addr->sin6_family = AF_INET6;
} else {
struct sockaddr_in *addr = (struct sockaddr_in *) &storage;
addr->sin_addr.s_addr = 16777343;
addr->sin_port = htons(5678);
addr->sin_family = AF_INET;
}
/* Send initial message batch */
if (is_client) {
for (int i = 0; i < 40; i++) {
us_udp_buffer_set_packet_payload(send_buf, i, 0, "Hello UDP!", 10, &storage);
}
int sent = us_udp_socket_send(client, send_buf, 40);
printf("Sent initial packets: %d\n", sent);
}
/* Start a counting timer */
struct us_timer_t *timer = us_create_timer(loop, 0, 0);
us_timer_set(timer, timer_cb, 1000, 1000);
/* Send packets from one UDP socket to the next, starting the loop */
us_loop_run(loop);
}
#else
int main() {
printf("Not yet available with io_uring backend\n");
}
#endif