UDP控制块
// udp ctrl block
struct localhost {
int fd;
uint8_t localmac[RTE_ETHER_ADDR_LEN];
uint32_t localip;
uint16_t localport;
uint8_t protocol;
struct rte_ring* sendbuf;
struct rte_ring* recvbuf;
struct localhost* prev;
struct localhost* next;
pthread_mutex_t mutex;
pthread_cond_t cond;
};
fd
:文件句柄localmac
:硬件地址localip
:IP地址localport
:端口号protocol
:协议sendbuf
:发送缓冲区recvbuf
:接收缓冲区prev
:链表指向前一个节点next
:链表指向下一个节点mutex
:互斥锁cond
:条件变量
Posix API
参考前一篇中的api说明。
int nsocket(__attribute__((unused)) int domain, int type, __attribute__((unused)) int protocol) {
int fd = get_fd_frombitmap();
struct localhost* host = rte_malloc("localhost", sizeof(struct localhost), 0);
if (host == NULL) {
return -1;
}
host->fd = fd;
if (type == SOCK_DGRAM) {
host->protocol = IPPROTO_UDP;
}
host->recvbuf = rte_ring_create("recv buf", RING_SIZE, rte_socket_id(), RING_F_SC_DEQ | RING_F_SP_ENQ);
if (host->recvbuf == NULL) {
rte_free(host);
return -1;
}
host->sendbuf = rte_ring_create("send buf", RING_SIZE, rte_socket_id(), RING_F_SC_DEQ | RING_F_SP_ENQ);
if (host->sendbuf == NULL) {
rte_ring_free(host->recvbuf);
rte_free(host);
return -1;
}
pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER;
rte_memcpy(&host->mutex, &blank_mutex, sizeof(pthread_mutex_t));
rte_memcpy(&host->cond, &blank_cond, sizeof(pthread_cond_t));
return 0;
}
int nbind(int sockfd, const struct sockaddr *addr, __attribute__((unused)) socklen_t addrlen) {
struct localhost* host = get_host_fromfd(sockfd);
if (host == NULL) {
return -1;
}
const struct sockaddr_in* laddr = (const struct sockaddr_in*)addr;
host->localport = laddr->sin_port;
rte_memcpy(&host->localip, &laddr->sin_addr.s_addr, sizeof(uint32_t));
rte_memcpy(host->localmac, nSrcMac, RTE_ETHER_ADDR_LEN);
return 0;
}
ssize_t nrecvfrom(int sockfd, void *buf, size_t len, __attribute__((unused)) int flags, struct sockaddr *src_addr, __attribute__((unused)) socklen_t *addrlen) {
struct localhost* host = get_host_fromfd(sockfd);
if (host == NULL) {
return -1;
}
struct offload* ol = NULL;
uint8_t* ptr = NULL;
struct sockaddr_in* laddr = (struct sockaddr_in*)src_addr;
int nb = -1;
pthread_mutex_lock(&host->mutex);
while ((nb = rte_ring_mc_dequeue(host->recvbuf, (void**)&ol)) < 0) {
pthread_cond_wait(&host->cond, &host->mutex);
}
pthread_mutex_unlock(&host->mutex);
laddr->sin_port = ol->sport;
rte_memcpy(&laddr->sin_addr.s_addr, &ol->sip, sizeof(uint32_t));
if (len < ol->length) {
rte_memcpy(buf, ol->data, len);
ptr = rte_malloc("ol buf", ol->length - len, 0);
rte_memcpy(ptr, ol->data + len, ol->length - len);
ol->length = ol->length - len;
rte_free(ol->data);
ol->data = ptr;
rte_ring_mp_enqueue(host->recvbuf, (void**)ol);
return len;
}
else {
rte_memcpy(buf, ol->data, ol->length);
rte_free(ol->data);
rte_free(ol);
return ol->length;
}
}
ssize_t nsendto(int sockfd, const void *buf, size_t len, __attribute__((unused)) int flags, const struct sockaddr *dest_addr, __attribute__((unused)) socklen_t addrlen) {
struct localhost* host = get_host_fromfd(sockfd);
if (host == NULL) {
return -1;
}
const struct sockaddr_in* daddr = (const struct sockaddr_in*)dest_addr;
struct offload* ol = rte_malloc("ol", sizeof(struct offload), 0);
if (ol == NULL) {
return -1;
}
ol->dip = daddr->sin_addr.s_addr;
ol->dport = daddr->sin_port;
ol->sport = host->localport;
ol->sip = host->localip;
ol->data = rte_malloc("ol data", len, 0);
rte_memcpy(ol->data, buf, len);
if (ol->data == NULL) {
rte_free(ol);
return -1;
}
rte_memcpy(ol->data, buf, len);
rte_ring_mp_enqueue(host->sendbuf, (void**)ol);
return len;
}
int nclose(int fd) {
struct localhost* host = get_host_fromfd(fd);
if (host == NULL) {
return -1;
}
LL_REMOVE(host, lhost);
if (host->recvbuf) {
rte_ring_free(host->recvbuf);
}
if (host->sendbuf) {
rte_ring_free(host->sendbuf);
}
rte_free(host);
return 0;
}
评论