mirror of https://github.com/F-Stack/f-stack.git
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.
This commit is contained in:
parent
93b7ff1c3f
commit
e12886c02c
|
@ -0,0 +1,298 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ff_config.h"
|
||||
#include "ff_api.h"
|
||||
|
||||
#define MAX_EVENTS 512
|
||||
|
||||
/* kevent set */
|
||||
struct kevent kevSet;
|
||||
/* events */
|
||||
struct kevent events[MAX_EVENTS];
|
||||
/* kq */
|
||||
int kq;
|
||||
int sockfd;
|
||||
#ifdef INET6
|
||||
int sockfd6;
|
||||
#endif
|
||||
|
||||
char html[] =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Server: F-Stack\r\n"
|
||||
"Date: Sat, 25 Feb 2017 09:26:33 GMT\r\n"
|
||||
"Content-Type: text/html\r\n"
|
||||
"Content-Length: 438\r\n"
|
||||
"Last-Modified: Tue, 21 Feb 2017 09:44:03 GMT\r\n"
|
||||
"Connection: keep-alive\r\n"
|
||||
"Accept-Ranges: bytes\r\n"
|
||||
"\r\n"
|
||||
"<!DOCTYPE html>\r\n"
|
||||
"<html>\r\n"
|
||||
"<head>\r\n"
|
||||
"<title>Welcome to F-Stack!</title>\r\n"
|
||||
"<style>\r\n"
|
||||
" body { \r\n"
|
||||
" width: 35em;\r\n"
|
||||
" margin: 0 auto; \r\n"
|
||||
" font-family: Tahoma, Verdana, Arial, sans-serif;\r\n"
|
||||
" }\r\n"
|
||||
"</style>\r\n"
|
||||
"</head>\r\n"
|
||||
"<body>\r\n"
|
||||
"<h1>Welcome to F-Stack!</h1>\r\n"
|
||||
"\r\n"
|
||||
"<p>For online documentation and support please refer to\r\n"
|
||||
"<a href=\"http://F-Stack.org/\">F-Stack.org</a>.<br/>\r\n"
|
||||
"\r\n"
|
||||
"<p><em>Thank you for using F-Stack.</em></p>\r\n"
|
||||
"</body>\r\n"
|
||||
"</html>";
|
||||
|
||||
|
||||
char html1[] =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Server: F-Stack\r\n"
|
||||
"Date: Sat, 25 Feb 2017 09:26:33 GMT\r\n"
|
||||
"Content-Type: text/html\r\n"
|
||||
"Content-Length: 9438\r\n"
|
||||
"Last-Modified: Tue, 21 Feb 2017 09:44:03 GMT\r\n"
|
||||
"Connection: keep-alive\r\n"
|
||||
"Accept-Ranges: bytes\r\n"
|
||||
"\r\n"
|
||||
"<!DOCTYPE html>\r\n"
|
||||
"<html>\r\n"
|
||||
"<head>\r\n"
|
||||
"<title>Welcome to F-Stack!</title>\r\n"
|
||||
"<style>\r\n"
|
||||
" body { \r\n"
|
||||
" width: 35em;\r\n"
|
||||
" margin: 0 auto; \r\n"
|
||||
" font-family: Tahoma, Verdana, Arial, sans-serif;\r\n"
|
||||
" }\r\n"
|
||||
"</style>\r\n"
|
||||
"</head>\r\n"
|
||||
"<body>\r\n"
|
||||
"<h1>Welcome to F-Stack!</h1>\r\n"
|
||||
"\r\n"
|
||||
"<p>For online documentation and support please refer to012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234"
|
||||
|
||||
"5678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234"
|
||||
|
||||
"56789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n"
|
||||
"<a href=\"http://F-Stack.org/\">F-Stack.org</a>.<br/>\r\n"
|
||||
"\r\n"
|
||||
"<p><em>Thank you for using F-Stack.</em></p>\r\n"
|
||||
"</body>\r\n"
|
||||
"</html>";
|
||||
|
||||
char html2[] =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Server: F-Stack\r\n"
|
||||
"Date: Sat, 25 Feb 2017 09:26:33 GMT\r\n"
|
||||
"Content-Type: text/html\r\n"
|
||||
"Content-Length: 1228\r\n"
|
||||
"Last-Modified: Tue, 21 Feb 2017 09:44:03 GMT\r\n"
|
||||
"Connection: keep-alive\r\n"
|
||||
"Accept-Ranges: bytes\r\n"
|
||||
"\r\n"
|
||||
"<!DOCTYPE html>\r\n"
|
||||
"<html>\r\n"
|
||||
"<head>\r\n"
|
||||
"<title>Welcome to F-Stack!</title>\r\n"
|
||||
"<style>\r\n"
|
||||
" body { \r\n"
|
||||
" width: 35em;\r\n"
|
||||
" margin: 0 auto; \r\n"
|
||||
" font-family: Tahoma, Verdana, Arial, sans-serif;\r\n"
|
||||
" }\r\n"
|
||||
"</style>\r\n"
|
||||
"</head>\r\n"
|
||||
"<body>\r\n"
|
||||
"<h1>Welcome to F-Stack!</h1>\r\n"
|
||||
"\r\n"
|
||||
"<p>For online documentation and support please refer to0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n"
|
||||
"<a href=\"http://F-Stack.org/\">F-Stack.org</a>.<br/>\r\n"
|
||||
"\r\n"
|
||||
"<p><em>Thank you for using F-Stack.</em></p>\r\n"
|
||||
"</body>\r\n"
|
||||
"</html>";
|
||||
|
||||
extern int ff_zc_mbuf_get(struct ff_zc_mbuf *m, int len);
|
||||
extern int ff_zc_mbuf_write(struct ff_zc_mbuf *m, const char *data, int len);
|
||||
|
||||
char *buf_tmp;
|
||||
char html_buf[10240];
|
||||
size_t buf_len = 0;
|
||||
struct ff_zc_mbuf zc_buf;
|
||||
|
||||
int loop(void *arg)
|
||||
{
|
||||
/* Wait for events to happen */
|
||||
unsigned nevents = ff_kevent(kq, NULL, 0, events, MAX_EVENTS, NULL);
|
||||
unsigned i;
|
||||
|
||||
buf_len = sizeof(html) - 1;
|
||||
buf_tmp = html;
|
||||
|
||||
for (i = 0; i < nevents; ++i) {
|
||||
struct kevent event = events[i];
|
||||
int clientfd = (int)event.ident;
|
||||
|
||||
/* Handle disconnect */
|
||||
if (event.flags & EV_EOF) {
|
||||
/* Simply close socket */
|
||||
ff_close(clientfd);
|
||||
#ifdef INET6
|
||||
} else if (clientfd == sockfd || clientfd == sockfd6) {
|
||||
#else
|
||||
} else if (clientfd == sockfd) {
|
||||
#endif
|
||||
int available = (int)event.data;
|
||||
do {
|
||||
int nclientfd = ff_accept(clientfd, NULL, NULL);
|
||||
if (nclientfd < 0) {
|
||||
printf("ff_accept failed:%d, %s\n", errno,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Add to event list */
|
||||
EV_SET(&kevSet, nclientfd, EVFILT_READ, EV_ADD, 0, 0, NULL);
|
||||
|
||||
if(ff_kevent(kq, &kevSet, 1, NULL, 0, NULL) < 0) {
|
||||
printf("ff_kevent error:%d, %s\n", errno,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
available--;
|
||||
} while (available);
|
||||
} else if (event.filter == EVFILT_READ) {
|
||||
char buf[256];
|
||||
size_t readlen = ff_read(clientfd, buf, sizeof(buf));
|
||||
#ifdef FSTACK_ZC_SEND
|
||||
int ret = ff_zc_mbuf_get(&zc_buf, buf_len);
|
||||
if (ret < 0) {
|
||||
printf("ff_zc_mbuf_get failed, len:%d, errno:%d, %s\n", buf_len, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* APP can call ff_zc_mbuf_write multi times */
|
||||
int len_part = 1440, off, to_write_len;
|
||||
for (off = 0; off < buf_len;){
|
||||
to_write_len = (buf_len - off) > len_part ? len_part : (buf_len - off);
|
||||
ret = ff_zc_mbuf_write(&zc_buf, (const char *)buf_tmp + off, to_write_len);
|
||||
if (ret != to_write_len) {
|
||||
printf("ff_zc_mbuf_write failed, len:%d, errno:%d, %s\n", to_write_len, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
off += to_write_len;
|
||||
}
|
||||
|
||||
/* Or call ff_zc_mbuf_write one time */
|
||||
/*
|
||||
if (ret != buf_len) {
|
||||
printf("ff_zc_mbuf_write failed, len:%d, errno:%d, %s\n", buf_len, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
*/
|
||||
|
||||
/* Simulate the application load */
|
||||
int i, j = 0;
|
||||
for (i = 0; i < 10000; i++){
|
||||
j++;
|
||||
}
|
||||
ff_write(clientfd, zc_buf.bsd_mbuf, buf_len);
|
||||
#else
|
||||
memcpy(html_buf, buf_tmp, buf_len);
|
||||
|
||||
/* Simulate the application load */
|
||||
int i, j = 0;
|
||||
for (i = 0; i < 10000; i++){
|
||||
j++;
|
||||
}
|
||||
|
||||
ff_write(clientfd, html_buf, buf_len);
|
||||
#endif
|
||||
} else {
|
||||
printf("unknown event: %8.8X\n", event.flags);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
ff_init(argc, argv);
|
||||
|
||||
assert((kq = ff_kqueue()) > 0);
|
||||
|
||||
sockfd = ff_socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) {
|
||||
printf("ff_socket failed, sockfd:%d, errno:%d, %s\n", sockfd, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct sockaddr_in my_addr;
|
||||
bzero(&my_addr, sizeof(my_addr));
|
||||
my_addr.sin_family = AF_INET;
|
||||
my_addr.sin_port = htons(80);
|
||||
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
int ret = ff_bind(sockfd, (struct linux_sockaddr *)&my_addr, sizeof(my_addr));
|
||||
if (ret < 0) {
|
||||
printf("ff_bind failed, sockfd:%d, errno:%d, %s\n", sockfd, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ff_listen(sockfd, MAX_EVENTS);
|
||||
if (ret < 0) {
|
||||
printf("ff_listen failed, sockfd:%d, errno:%d, %s\n", sockfd, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
EV_SET(&kevSet, sockfd, EVFILT_READ, EV_ADD, 0, MAX_EVENTS, NULL);
|
||||
/* Update kqueue */
|
||||
ff_kevent(kq, &kevSet, 1, NULL, 0, NULL);
|
||||
|
||||
#ifdef INET6
|
||||
sockfd6 = ff_socket(AF_INET6, SOCK_STREAM, 0);
|
||||
if (sockfd6 < 0) {
|
||||
printf("ff_socket failed, sockfd6:%d, errno:%d, %s\n", sockfd6, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct sockaddr_in6 my_addr6;
|
||||
bzero(&my_addr6, sizeof(my_addr6));
|
||||
my_addr6.sin6_family = AF_INET6;
|
||||
my_addr6.sin6_port = htons(80);
|
||||
my_addr6.sin6_addr = in6addr_any;
|
||||
|
||||
ret = ff_bind(sockfd6, (struct linux_sockaddr *)&my_addr6, sizeof(my_addr6));
|
||||
if (ret < 0) {
|
||||
printf("ff_bind failed, sockfd6:%d, errno:%d, %s\n", sockfd6, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = ff_listen(sockfd6, MAX_EVENTS);
|
||||
if (ret < 0) {
|
||||
printf("ff_listen failed, sockfd6:%d, errno:%d, %s\n", sockfd6, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
EV_SET(&kevSet, sockfd6, EVFILT_READ, EV_ADD, 0, MAX_EVENTS, NULL);
|
||||
ff_kevent(kq, &kevSet, 1, NULL, 0, NULL);
|
||||
#endif
|
||||
|
||||
ff_run(loop, NULL);
|
||||
return 0;
|
||||
}
|
|
@ -1536,6 +1536,16 @@ m_uiotombuf(struct uio *uio, int how, int len, int align, int flags)
|
|||
* Give us the full allocation or nothing.
|
||||
* If len is zero return the smallest empty mbuf.
|
||||
*/
|
||||
#ifdef FSTACK_ZC_SEND
|
||||
if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_rw == UIO_WRITE) {
|
||||
m = (struct mbuf *)uio->uio_iov->iov_base;
|
||||
uio->uio_iov->iov_base = (char *)(uio->uio_iov->iov_base) + total;
|
||||
uio->uio_iov->iov_len = 0;
|
||||
uio->uio_resid = 0;
|
||||
uio->uio_offset = total;
|
||||
progress = total;
|
||||
} else {
|
||||
#endif
|
||||
m = m_getm2(NULL, max(total + align, 1), how, MT_DATA, flags);
|
||||
if (m == NULL)
|
||||
return (NULL);
|
||||
|
@ -1556,6 +1566,9 @@ m_uiotombuf(struct uio *uio, int how, int len, int align, int flags)
|
|||
if (flags & M_PKTHDR)
|
||||
m->m_pkthdr.len += length;
|
||||
}
|
||||
#ifdef FSTACK_ZC_SEND
|
||||
}
|
||||
#endif
|
||||
KASSERT(progress == total, ("%s: progress != total", __func__));
|
||||
|
||||
return (m);
|
||||
|
|
|
@ -30,6 +30,7 @@ FF_KNI=1
|
|||
#FF_NETGRAPH=1
|
||||
#FF_IPFW=1
|
||||
#FF_USE_PAGE_ARRAY=1
|
||||
#FF_ZC_SEND=1
|
||||
FF_INET6=1
|
||||
|
||||
|
||||
|
@ -138,7 +139,6 @@ ifeq (${MACHINE_CPUARCH},i386)
|
|||
MACHINE=i386
|
||||
endif
|
||||
|
||||
|
||||
#
|
||||
# Distilled from FreeBSD src/sys/conf/Makefile.mips
|
||||
#
|
||||
|
@ -156,6 +156,10 @@ endif
|
|||
|
||||
CFLAGS+= -DFSTACK
|
||||
|
||||
ifdef FF_ZC_SEND
|
||||
CFLAGS+= -DFSTACK_ZC_SEND
|
||||
endif
|
||||
|
||||
# add for LVS tcp option toa, disabled by default
|
||||
# CFLAGS+= -DLVS_TCPOPT_TOA
|
||||
|
||||
|
|
56
lib/ff_api.h
56
lib/ff_api.h
|
@ -241,6 +241,62 @@ int ff_ngctl(int cmd, void *data);
|
|||
|
||||
/* internal api end */
|
||||
|
||||
/* zero ccopy API begin */
|
||||
struct ff_zc_mbuf {
|
||||
void *bsd_mbuf; /* point to the head mbuf */
|
||||
void *bsd_mbuf_off; /* ponit to the current mbuf in the mbuf chain with offset */
|
||||
int off; /* the offset of total mbuf, APP shouldn't modify it */
|
||||
int len; /* the total len of the mbuf chain */
|
||||
};
|
||||
|
||||
/*
|
||||
* Get the ff zero copy mbuf.
|
||||
*
|
||||
* @param m
|
||||
* The ponitor of 'sturct ff_zc_mbuf', and can't be NULL.
|
||||
* Can used by 'ff_zc_mbuf_write' and 'ff_zc_mbuf_read'.
|
||||
* @param len
|
||||
* The total buf len of mbuf chain that you want to alloc.
|
||||
*
|
||||
* @return error_no
|
||||
* 0 means success.
|
||||
* -1 means error.
|
||||
*/
|
||||
int ff_zc_mbuf_get(struct ff_zc_mbuf *m, int len);
|
||||
|
||||
/*
|
||||
* Write data to the mbuf chain in 'sturct ff_zc_mbuf'.
|
||||
* APP can call this function multiple times, need pay attion to the offset of data.
|
||||
* but the total len can't be larger than m->len.
|
||||
* After this fuction return success,
|
||||
* the struct 'ff_zc_mbuf *m' can be reused in `ff_zc_mbuf_get`.
|
||||
*
|
||||
* APP nedd call 'ff_write' to send data actually after finish write data to mbuf,
|
||||
* And use 'bsd_mbuf' of 'struct ff_zc_mbuf' as the 'buf' argument.
|
||||
*
|
||||
* See 'example/main_zc.c'
|
||||
*
|
||||
* @param m
|
||||
* The ponitor of 'sturct ff_zc_mbuf', must be call 'ff_zc_mbuf_get' first.
|
||||
* @param data
|
||||
* The pointer of data that want to write to socket, need pay attion to the offset.
|
||||
* @param len
|
||||
* The len that APP want to write to mbuf chain this time.
|
||||
*
|
||||
* @return error_no
|
||||
* 0 means success.
|
||||
* -1 means error.
|
||||
*/
|
||||
int ff_zc_mbuf_write(struct ff_zc_mbuf *m, const char *data, int len);
|
||||
|
||||
/*
|
||||
* Read data to the mbuf chain in 'sturct ff_zc_mbuf'.
|
||||
* not implemented now.
|
||||
*/
|
||||
int ff_zc_mbuf_read(struct ff_zc_mbuf *m, const char *data, int len);
|
||||
|
||||
/* ZERO COPY API end */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -54,3 +54,6 @@ ff_next_mbuf
|
|||
ff_mbuf_mtod
|
||||
ff_rte_frm_extcl
|
||||
ff_mbuf_set_vlan_info
|
||||
ff_zc_mbuf_get
|
||||
ff_zc_mbuf_write
|
||||
ff_zc_mbuf_read
|
||||
|
|
|
@ -205,6 +205,65 @@ ff_mbuf_ext_free(struct mbuf *m, void *arg1, void *arg2)
|
|||
ff_dpdk_pktmbuf_free(arg1);
|
||||
}
|
||||
|
||||
int ff_zc_mbuf_get(struct ff_zc_mbuf *m, int len) {
|
||||
struct mbuf *mb;
|
||||
|
||||
if (m == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mb = m_getm2(NULL, max(len, 1), M_WAITOK, MT_DATA, 0);
|
||||
if (mb == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
m->bsd_mbuf = m->bsd_mbuf_off = mb;
|
||||
m->off = 0;
|
||||
m->len = len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ff_zc_mbuf_write(struct ff_zc_mbuf *zm, const char *data, int len)
|
||||
{
|
||||
int ret, length, progress = 0;
|
||||
struct mbuf *m, *mb;
|
||||
|
||||
if (zm == NULL) {
|
||||
return -1;
|
||||
}
|
||||
m = (struct mbuf *)zm->bsd_mbuf_off;
|
||||
|
||||
if (zm->off + len > zm->len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (mb = m; mb != NULL; mb = mb->m_next) {
|
||||
length = min(M_TRAILINGSPACE(mb), len - progress);
|
||||
bcopy(data + progress, mtod(mb, char *) + mb->m_len, length);
|
||||
|
||||
mb->m_len += length;
|
||||
progress += length;
|
||||
if (len == progress) {
|
||||
break;
|
||||
}
|
||||
//if (flags & M_PKTHDR)
|
||||
// m->m_pkthdr.len += length;
|
||||
}
|
||||
zm->off += len;
|
||||
zm->bsd_mbuf_off = mb;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
ff_zc_mbuf_read(struct ff_zc_mbuf *m, const char *data, int len)
|
||||
{
|
||||
// DOTO: Support read zero copy
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *
|
||||
ff_mbuf_gethdr(void *pkt, uint16_t total, void *data,
|
||||
uint16_t len, uint8_t rx_csum)
|
||||
|
|
Loading…
Reference in New Issue