Skip to content

Commit e12886c

Browse files
committed
Support zero copy while call ff_write, you can enable it by modify ‘FF_ZC_SEND=1' in lib/Makefile.
`FF_ZC_SEND` is same as `FF_USE_PAGE_ARRAY`, it will improve performance slightly in some scenarios, need to be tested in combination with real applications. You can enable both compilation options at the same time or separately.
1 parent 93b7ff1 commit e12886c

File tree

6 files changed

+434
-1
lines changed

6 files changed

+434
-1
lines changed

example/main_zc.c

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <stdint.h>
4+
#include <string.h>
5+
#include <strings.h>
6+
#include <sys/types.h>
7+
#include <sys/socket.h>
8+
#include <arpa/inet.h>
9+
#include <errno.h>
10+
#include <assert.h>
11+
12+
#include "ff_config.h"
13+
#include "ff_api.h"
14+
15+
#define MAX_EVENTS 512
16+
17+
/* kevent set */
18+
struct kevent kevSet;
19+
/* events */
20+
struct kevent events[MAX_EVENTS];
21+
/* kq */
22+
int kq;
23+
int sockfd;
24+
#ifdef INET6
25+
int sockfd6;
26+
#endif
27+
28+
char html[] =
29+
"HTTP/1.1 200 OK\r\n"
30+
"Server: F-Stack\r\n"
31+
"Date: Sat, 25 Feb 2017 09:26:33 GMT\r\n"
32+
"Content-Type: text/html\r\n"
33+
"Content-Length: 438\r\n"
34+
"Last-Modified: Tue, 21 Feb 2017 09:44:03 GMT\r\n"
35+
"Connection: keep-alive\r\n"
36+
"Accept-Ranges: bytes\r\n"
37+
"\r\n"
38+
"<!DOCTYPE html>\r\n"
39+
"<html>\r\n"
40+
"<head>\r\n"
41+
"<title>Welcome to F-Stack!</title>\r\n"
42+
"<style>\r\n"
43+
" body { \r\n"
44+
" width: 35em;\r\n"
45+
" margin: 0 auto; \r\n"
46+
" font-family: Tahoma, Verdana, Arial, sans-serif;\r\n"
47+
" }\r\n"
48+
"</style>\r\n"
49+
"</head>\r\n"
50+
"<body>\r\n"
51+
"<h1>Welcome to F-Stack!</h1>\r\n"
52+
"\r\n"
53+
"<p>For online documentation and support please refer to\r\n"
54+
"<a href=\"http://F-Stack.org/\">F-Stack.org</a>.<br/>\r\n"
55+
"\r\n"
56+
"<p><em>Thank you for using F-Stack.</em></p>\r\n"
57+
"</body>\r\n"
58+
"</html>";
59+
60+
61+
char html1[] =
62+
"HTTP/1.1 200 OK\r\n"
63+
"Server: F-Stack\r\n"
64+
"Date: Sat, 25 Feb 2017 09:26:33 GMT\r\n"
65+
"Content-Type: text/html\r\n"
66+
"Content-Length: 9438\r\n"
67+
"Last-Modified: Tue, 21 Feb 2017 09:44:03 GMT\r\n"
68+
"Connection: keep-alive\r\n"
69+
"Accept-Ranges: bytes\r\n"
70+
"\r\n"
71+
"<!DOCTYPE html>\r\n"
72+
"<html>\r\n"
73+
"<head>\r\n"
74+
"<title>Welcome to F-Stack!</title>\r\n"
75+
"<style>\r\n"
76+
" body { \r\n"
77+
" width: 35em;\r\n"
78+
" margin: 0 auto; \r\n"
79+
" font-family: Tahoma, Verdana, Arial, sans-serif;\r\n"
80+
" }\r\n"
81+
"</style>\r\n"
82+
"</head>\r\n"
83+
"<body>\r\n"
84+
"<h1>Welcome to F-Stack!</h1>\r\n"
85+
"\r\n"
86+
"<p>For online documentation and support please refer to012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234"
87+
88+
"5678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234"
89+
90+
"56789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n"
91+
"<a href=\"http://F-Stack.org/\">F-Stack.org</a>.<br/>\r\n"
92+
"\r\n"
93+
"<p><em>Thank you for using F-Stack.</em></p>\r\n"
94+
"</body>\r\n"
95+
"</html>";
96+
97+
char html2[] =
98+
"HTTP/1.1 200 OK\r\n"
99+
"Server: F-Stack\r\n"
100+
"Date: Sat, 25 Feb 2017 09:26:33 GMT\r\n"
101+
"Content-Type: text/html\r\n"
102+
"Content-Length: 1228\r\n"
103+
"Last-Modified: Tue, 21 Feb 2017 09:44:03 GMT\r\n"
104+
"Connection: keep-alive\r\n"
105+
"Accept-Ranges: bytes\r\n"
106+
"\r\n"
107+
"<!DOCTYPE html>\r\n"
108+
"<html>\r\n"
109+
"<head>\r\n"
110+
"<title>Welcome to F-Stack!</title>\r\n"
111+
"<style>\r\n"
112+
" body { \r\n"
113+
" width: 35em;\r\n"
114+
" margin: 0 auto; \r\n"
115+
" font-family: Tahoma, Verdana, Arial, sans-serif;\r\n"
116+
" }\r\n"
117+
"</style>\r\n"
118+
"</head>\r\n"
119+
"<body>\r\n"
120+
"<h1>Welcome to F-Stack!</h1>\r\n"
121+
"\r\n"
122+
"<p>For online documentation and support please refer to0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n"
123+
"<a href=\"http://F-Stack.org/\">F-Stack.org</a>.<br/>\r\n"
124+
"\r\n"
125+
"<p><em>Thank you for using F-Stack.</em></p>\r\n"
126+
"</body>\r\n"
127+
"</html>";
128+
129+
extern int ff_zc_mbuf_get(struct ff_zc_mbuf *m, int len);
130+
extern int ff_zc_mbuf_write(struct ff_zc_mbuf *m, const char *data, int len);
131+
132+
char *buf_tmp;
133+
char html_buf[10240];
134+
size_t buf_len = 0;
135+
struct ff_zc_mbuf zc_buf;
136+
137+
int loop(void *arg)
138+
{
139+
/* Wait for events to happen */
140+
unsigned nevents = ff_kevent(kq, NULL, 0, events, MAX_EVENTS, NULL);
141+
unsigned i;
142+
143+
buf_len = sizeof(html) - 1;
144+
buf_tmp = html;
145+
146+
for (i = 0; i < nevents; ++i) {
147+
struct kevent event = events[i];
148+
int clientfd = (int)event.ident;
149+
150+
/* Handle disconnect */
151+
if (event.flags & EV_EOF) {
152+
/* Simply close socket */
153+
ff_close(clientfd);
154+
#ifdef INET6
155+
} else if (clientfd == sockfd || clientfd == sockfd6) {
156+
#else
157+
} else if (clientfd == sockfd) {
158+
#endif
159+
int available = (int)event.data;
160+
do {
161+
int nclientfd = ff_accept(clientfd, NULL, NULL);
162+
if (nclientfd < 0) {
163+
printf("ff_accept failed:%d, %s\n", errno,
164+
strerror(errno));
165+
break;
166+
}
167+
168+
/* Add to event list */
169+
EV_SET(&kevSet, nclientfd, EVFILT_READ, EV_ADD, 0, 0, NULL);
170+
171+
if(ff_kevent(kq, &kevSet, 1, NULL, 0, NULL) < 0) {
172+
printf("ff_kevent error:%d, %s\n", errno,
173+
strerror(errno));
174+
return -1;
175+
}
176+
177+
available--;
178+
} while (available);
179+
} else if (event.filter == EVFILT_READ) {
180+
char buf[256];
181+
size_t readlen = ff_read(clientfd, buf, sizeof(buf));
182+
#ifdef FSTACK_ZC_SEND
183+
int ret = ff_zc_mbuf_get(&zc_buf, buf_len);
184+
if (ret < 0) {
185+
printf("ff_zc_mbuf_get failed, len:%d, errno:%d, %s\n", buf_len, errno, strerror(errno));
186+
exit(1);
187+
}
188+
189+
/* APP can call ff_zc_mbuf_write multi times */
190+
int len_part = 1440, off, to_write_len;
191+
for (off = 0; off < buf_len;){
192+
to_write_len = (buf_len - off) > len_part ? len_part : (buf_len - off);
193+
ret = ff_zc_mbuf_write(&zc_buf, (const char *)buf_tmp + off, to_write_len);
194+
if (ret != to_write_len) {
195+
printf("ff_zc_mbuf_write failed, len:%d, errno:%d, %s\n", to_write_len, errno, strerror(errno));
196+
exit(1);
197+
}
198+
off += to_write_len;
199+
}
200+
201+
/* Or call ff_zc_mbuf_write one time */
202+
/*
203+
if (ret != buf_len) {
204+
printf("ff_zc_mbuf_write failed, len:%d, errno:%d, %s\n", buf_len, errno, strerror(errno));
205+
exit(1);
206+
}
207+
*/
208+
209+
/* Simulate the application load */
210+
int i, j = 0;
211+
for (i = 0; i < 10000; i++){
212+
j++;
213+
}
214+
ff_write(clientfd, zc_buf.bsd_mbuf, buf_len);
215+
#else
216+
memcpy(html_buf, buf_tmp, buf_len);
217+
218+
/* Simulate the application load */
219+
int i, j = 0;
220+
for (i = 0; i < 10000; i++){
221+
j++;
222+
}
223+
224+
ff_write(clientfd, html_buf, buf_len);
225+
#endif
226+
} else {
227+
printf("unknown event: %8.8X\n", event.flags);
228+
}
229+
230+
}
231+
}
232+
233+
int main(int argc, char * argv[])
234+
{
235+
ff_init(argc, argv);
236+
237+
assert((kq = ff_kqueue()) > 0);
238+
239+
sockfd = ff_socket(AF_INET, SOCK_STREAM, 0);
240+
if (sockfd < 0) {
241+
printf("ff_socket failed, sockfd:%d, errno:%d, %s\n", sockfd, errno, strerror(errno));
242+
exit(1);
243+
}
244+
245+
struct sockaddr_in my_addr;
246+
bzero(&my_addr, sizeof(my_addr));
247+
my_addr.sin_family = AF_INET;
248+
my_addr.sin_port = htons(80);
249+
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
250+
251+
int ret = ff_bind(sockfd, (struct linux_sockaddr *)&my_addr, sizeof(my_addr));
252+
if (ret < 0) {
253+
printf("ff_bind failed, sockfd:%d, errno:%d, %s\n", sockfd, errno, strerror(errno));
254+
exit(1);
255+
}
256+
257+
ret = ff_listen(sockfd, MAX_EVENTS);
258+
if (ret < 0) {
259+
printf("ff_listen failed, sockfd:%d, errno:%d, %s\n", sockfd, errno, strerror(errno));
260+
exit(1);
261+
}
262+
263+
EV_SET(&kevSet, sockfd, EVFILT_READ, EV_ADD, 0, MAX_EVENTS, NULL);
264+
/* Update kqueue */
265+
ff_kevent(kq, &kevSet, 1, NULL, 0, NULL);
266+
267+
#ifdef INET6
268+
sockfd6 = ff_socket(AF_INET6, SOCK_STREAM, 0);
269+
if (sockfd6 < 0) {
270+
printf("ff_socket failed, sockfd6:%d, errno:%d, %s\n", sockfd6, errno, strerror(errno));
271+
exit(1);
272+
}
273+
274+
struct sockaddr_in6 my_addr6;
275+
bzero(&my_addr6, sizeof(my_addr6));
276+
my_addr6.sin6_family = AF_INET6;
277+
my_addr6.sin6_port = htons(80);
278+
my_addr6.sin6_addr = in6addr_any;
279+
280+
ret = ff_bind(sockfd6, (struct linux_sockaddr *)&my_addr6, sizeof(my_addr6));
281+
if (ret < 0) {
282+
printf("ff_bind failed, sockfd6:%d, errno:%d, %s\n", sockfd6, errno, strerror(errno));
283+
exit(1);
284+
}
285+
286+
ret = ff_listen(sockfd6, MAX_EVENTS);
287+
if (ret < 0) {
288+
printf("ff_listen failed, sockfd6:%d, errno:%d, %s\n", sockfd6, errno, strerror(errno));
289+
exit(1);
290+
}
291+
292+
EV_SET(&kevSet, sockfd6, EVFILT_READ, EV_ADD, 0, MAX_EVENTS, NULL);
293+
ff_kevent(kq, &kevSet, 1, NULL, 0, NULL);
294+
#endif
295+
296+
ff_run(loop, NULL);
297+
return 0;
298+
}

freebsd/kern/uipc_mbuf.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,16 @@ m_uiotombuf(struct uio *uio, int how, int len, int align, int flags)
15361536
* Give us the full allocation or nothing.
15371537
* If len is zero return the smallest empty mbuf.
15381538
*/
1539+
#ifdef FSTACK_ZC_SEND
1540+
if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_rw == UIO_WRITE) {
1541+
m = (struct mbuf *)uio->uio_iov->iov_base;
1542+
uio->uio_iov->iov_base = (char *)(uio->uio_iov->iov_base) + total;
1543+
uio->uio_iov->iov_len = 0;
1544+
uio->uio_resid = 0;
1545+
uio->uio_offset = total;
1546+
progress = total;
1547+
} else {
1548+
#endif
15391549
m = m_getm2(NULL, max(total + align, 1), how, MT_DATA, flags);
15401550
if (m == NULL)
15411551
return (NULL);
@@ -1556,6 +1566,9 @@ m_uiotombuf(struct uio *uio, int how, int len, int align, int flags)
15561566
if (flags & M_PKTHDR)
15571567
m->m_pkthdr.len += length;
15581568
}
1569+
#ifdef FSTACK_ZC_SEND
1570+
}
1571+
#endif
15591572
KASSERT(progress == total, ("%s: progress != total", __func__));
15601573

15611574
return (m);

lib/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ FF_KNI=1
3030
#FF_NETGRAPH=1
3131
#FF_IPFW=1
3232
#FF_USE_PAGE_ARRAY=1
33+
#FF_ZC_SEND=1
3334
FF_INET6=1
3435

3536

@@ -138,7 +139,6 @@ ifeq (${MACHINE_CPUARCH},i386)
138139
MACHINE=i386
139140
endif
140141

141-
142142
#
143143
# Distilled from FreeBSD src/sys/conf/Makefile.mips
144144
#
@@ -156,6 +156,10 @@ endif
156156

157157
CFLAGS+= -DFSTACK
158158

159+
ifdef FF_ZC_SEND
160+
CFLAGS+= -DFSTACK_ZC_SEND
161+
endif
162+
159163
# add for LVS tcp option toa, disabled by default
160164
# CFLAGS+= -DLVS_TCPOPT_TOA
161165

0 commit comments

Comments
 (0)