📄 net_io.c
字号:
} strcpy(nged->dev_name,dev_name); if (!(nged->pcap_dev = gen_eth_init(dev_name))) { netio_free(nio,NULL); return NULL; } nio->type = NETIO_TYPE_GEN_ETH; nio->send = (void *)netio_geneth_send; nio->recv = (void *)netio_geneth_recv; nio->save_cfg = netio_geneth_save_cfg; nio->dptr = &nio->u.nged; if (netio_record(nio) == -1) { netio_free(nio,NULL); return NULL; } return nio;}#endif /* GEN_ETH *//* * ========================================================================= * FIFO Driver (intra-hypervisor communications) * ========================================================================= *//* Extract the first packet of the FIFO */static netio_fifo_pkt_t *netio_fifo_extract_pkt(netio_fifo_desc_t *nfd){ netio_fifo_pkt_t *p; if (!(p = nfd->head)) return NULL; nfd->pkt_count--; nfd->head = p->next; if (!nfd->head) nfd->last = NULL; return p;}/* Insert a packet into the FIFO (in tail) */static void netio_fifo_insert_pkt(netio_fifo_desc_t *nfd,netio_fifo_pkt_t *p){ pthread_mutex_lock(&nfd->lock); nfd->pkt_count++; p->next = NULL; if (nfd->last) { nfd->last->next = p; } else { nfd->head = p; } nfd->last = p; pthread_mutex_unlock(&nfd->lock);}/* Free the packet list */static void netio_fifo_free_pkt_list(netio_fifo_desc_t *nfd){ netio_fifo_pkt_t *p,*next; for(p=nfd->head;p;p=next) { next = p->next; free(p); } nfd->head = nfd->last = NULL; nfd->pkt_count = 0;}/* Establish a cross-connect between two FIFO NetIO */int netio_fifo_crossconnect(netio_desc_t *a,netio_desc_t *b){ netio_fifo_desc_t *pa,*pb; if ((a->type != NETIO_TYPE_FIFO) || (b->type != NETIO_TYPE_FIFO)) return(-1); pa = &a->u.nfd; pb = &b->u.nfd; /* A => B */ pthread_mutex_lock(&pa->endpoint_lock); pthread_mutex_lock(&pa->lock); pa->endpoint = pb; netio_fifo_free_pkt_list(pa); pthread_mutex_unlock(&pa->lock); pthread_mutex_unlock(&pa->endpoint_lock); /* B => A */ pthread_mutex_lock(&pb->endpoint_lock); pthread_mutex_lock(&pb->lock); pb->endpoint = pa; netio_fifo_free_pkt_list(pb); pthread_mutex_unlock(&pb->lock); pthread_mutex_unlock(&pb->endpoint_lock); return(0);}/* Unbind an endpoint */static void netio_fifo_unbind_endpoint(netio_fifo_desc_t *nfd){ pthread_mutex_lock(&nfd->endpoint_lock); nfd->endpoint = NULL; pthread_mutex_unlock(&nfd->endpoint_lock);}/* Free a NetIO FIFO descriptor */static void netio_fifo_free(netio_fifo_desc_t *nfd){ if (nfd->endpoint) netio_fifo_unbind_endpoint(nfd->endpoint); netio_fifo_free_pkt_list(nfd); pthread_mutex_destroy(&nfd->lock); pthread_cond_destroy(&nfd->cond);}/* Send a packet (to the endpoint FIFO) */static ssize_t netio_fifo_send(netio_fifo_desc_t *nfd,void *pkt,size_t pkt_len){ netio_fifo_pkt_t *p; size_t len; pthread_mutex_lock(&nfd->endpoint_lock); /* The cross-connect must have been established before */ if (!nfd->endpoint) goto error; /* Allocate a a new packet and insert it into the endpoint FIFO */ len = sizeof(netio_fifo_pkt_t) + pkt_len; if (!(p = malloc(len))) goto error; memcpy(p->pkt,pkt,pkt_len); p->pkt_len = pkt_len; netio_fifo_insert_pkt(nfd->endpoint,p); pthread_cond_signal(&nfd->endpoint->cond); pthread_mutex_unlock(&nfd->endpoint_lock); return(pkt_len); error: pthread_mutex_unlock(&nfd->endpoint_lock); return(-1);}/* Read a packet from the local FIFO queue */static ssize_t netio_fifo_recv(netio_fifo_desc_t *nfd,void *pkt,size_t max_len){ struct timespec ts; m_tmcnt_t expire; netio_fifo_pkt_t *p; size_t len = -1; /* Wait for the endpoint to signal a new arriving packet */ expire = m_gettime_usec() + 50000; ts.tv_sec = expire / 1000000; ts.tv_nsec = (expire % 1000000) * 1000; pthread_mutex_lock(&nfd->lock); pthread_cond_timedwait(&nfd->cond,&nfd->lock,&ts); /* Extract a packet from the list */ p = netio_fifo_extract_pkt(nfd); pthread_mutex_unlock(&nfd->lock); if (p) { len = m_min(p->pkt_len,max_len); memcpy(pkt,p->pkt,len); free(p); } return(len);}/* Create a new NetIO descriptor with FIFO method */netio_desc_t *netio_desc_create_fifo(char *nio_name){ netio_fifo_desc_t *nfd; netio_desc_t *nio; if (!(nio = netio_create(nio_name))) return NULL; nfd = &nio->u.nfd; pthread_mutex_init(&nfd->lock,NULL); pthread_mutex_init(&nfd->endpoint_lock,NULL); pthread_cond_init(&nfd->cond,NULL); nio->type = NETIO_TYPE_FIFO; nio->send = (void *)netio_fifo_send; nio->recv = (void *)netio_fifo_recv; nio->dptr = nfd; if (netio_record(nio) == -1) { netio_free(nio,NULL); return NULL; } return nio;}/* * ========================================================================= * NULL Driver (does nothing, used for debugging) * ========================================================================= */static ssize_t netio_null_send(void *null_ptr,void *pkt,size_t pkt_len){ return(pkt_len);}static ssize_t netio_null_recv(void *null_ptr,void *pkt,size_t max_len){ usleep(200000); return(-1);}static void netio_null_save_cfg(netio_desc_t *nio,FILE *fd){ fprintf(fd,"nio create_null %s\n",nio->name);}/* Create a new NetIO descriptor with NULL method */netio_desc_t *netio_desc_create_null(char *nio_name){ netio_desc_t *nio; if (!(nio = netio_create(nio_name))) return NULL; nio->type = NETIO_TYPE_NULL; nio->send = (void *)netio_null_send; nio->recv = (void *)netio_null_recv; nio->save_cfg = netio_null_save_cfg; nio->dptr = NULL; if (netio_record(nio) == -1) { netio_free(nio,NULL); return NULL; } return nio;}/* Free a NetIO descriptor */static int netio_free(void *data,void *arg){ netio_desc_t *nio = data; if (nio) { netio_filter_unbind(nio,NETIO_FILTER_DIR_RX); netio_filter_unbind(nio,NETIO_FILTER_DIR_TX); switch(nio->type) { case NETIO_TYPE_UNIX: netio_unix_free(&nio->u.nud); break; case NETIO_TYPE_VDE: netio_vde_free(&nio->u.nvd); break; case NETIO_TYPE_TAP: netio_tap_free(&nio->u.ntd); break; case NETIO_TYPE_TCP_CLI: case NETIO_TYPE_TCP_SER: netio_tcp_free(&nio->u.nid); break; case NETIO_TYPE_UDP: netio_udp_free(&nio->u.nid); break;#ifdef LINUX_ETH case NETIO_TYPE_LINUX_ETH: netio_lnxeth_free(&nio->u.nled); break;#endif#ifdef GEN_ETH case NETIO_TYPE_GEN_ETH: netio_geneth_free(&nio->u.nged); break;#endif case NETIO_TYPE_FIFO: netio_fifo_free(&nio->u.nfd); break; case NETIO_TYPE_NULL: break; default: fprintf(stderr,"NETIO: unknown descriptor type %u\n",nio->type); } free(nio->name); free(nio); } return(TRUE);}/* * ========================================================================= * RX Listeners * ========================================================================= *//* Find a RX listener */static inline struct netio_rx_listener *netio_rxl_find(netio_desc_t *nio){ struct netio_rx_listener *rxl; for(rxl=netio_rxl_list;rxl;rxl=rxl->next) if (rxl->nio == nio) return rxl; return NULL;}/* Remove a NIO from the listener list */static int netio_rxl_remove_internal(netio_desc_t *nio){ struct netio_rx_listener *rxl; int res = -1; if ((rxl = netio_rxl_find(nio))) { /* we suppress this NIO only when the ref count hits 0 */ rxl->ref_count--; if (!rxl->ref_count) { /* remove this listener from the double linked list */ if (rxl->next) rxl->next->prev = rxl->prev; if (rxl->prev) rxl->prev->next = rxl->next; else netio_rxl_list = rxl->next; /* if this is non-FD NIO, wait for thread to terminate */ if (netio_get_fd(rxl->nio) == -1) { rxl->running = FALSE; pthread_join(rxl->spec_thread,NULL); } free(rxl); } res = 0; } return(res);}/* Add a RXL listener to the listener list */static void netio_rxl_add_internal(struct netio_rx_listener *rxl){ struct netio_rx_listener *tmp; if ((tmp = netio_rxl_find(rxl->nio))) { tmp->ref_count++; free(rxl); } else { rxl->prev = NULL; rxl->next = netio_rxl_list; if (rxl->next) rxl->next->prev = rxl; netio_rxl_list = rxl; }}/* RX Listener dedicated thread (for non-FD NIO) */static void *netio_rxl_spec_thread(void *arg){ struct netio_rx_listener *rxl = arg; u_char pkt[NETIO_MAX_PKT_SIZE]; ssize_t pkt_len; while(rxl->running) { pkt_len = netio_recv(rxl->nio,pkt,sizeof(pkt)); if (pkt_len > 0) rxl->rx_handler(rxl->nio,pkt,pkt_len,rxl->arg1,rxl->arg2); } return NULL;}/* RX Listener General Thread */void *netio_rxl_gen_thread(void *arg){ struct netio_rx_listener *rxl; u_char pkt[NETIO_MAX_PKT_SIZE]; ssize_t pkt_len; netio_desc_t *nio; struct timeval tv; int fd,fd_max,res; fd_set rfds; for(;;) { NETIO_RXL_LOCK(); NETIO_RXQ_LOCK(); /* Add the new waiting NIO to the active list */ while(netio_rxl_add_list != NULL) { rxl = netio_rxl_add_list; netio_rxl_add_list = netio_rxl_add_list->next; netio_rxl_add_internal(rxl); } /* Delete the NIO present in the remove list */ while(netio_rxl_remove_list != NULL) { nio = netio_rxl_remove_list; netio_rxl_remove_list = netio_rxl_remove_list->rxl_next; netio_rxl_remove_internal(nio); } pthread_cond_broadcast(&netio_rxl_cond); NETIO_RXQ_UNLOCK(); /* Build the FD set */ FD_ZERO(&rfds); fd_max = -1; for(rxl=netio_rxl_list;rxl;rxl=rxl->next) { if ((fd = netio_get_fd(rxl->nio)) == -1) continue; if (fd > fd_max) fd_max = fd; FD_SET(fd,&rfds); } NETIO_RXL_UNLOCK(); /* Wait for incoming packets */ tv.tv_sec = 0; tv.tv_usec = 20 * 1000; /* 200 ms */ res = select(fd_max+1,&rfds,NULL,NULL,&tv); if (res == -1) { if (errno != EINTR) perror("netio_rxl_thread: select"); continue; } /* Examine active FDs and call user handlers */ NETIO_RXL_LOCK(); for(rxl=netio_rxl_list;rxl;rxl=rxl->next) { if ((fd = netio_get_fd(rxl->nio)) == -1) continue; if (FD_ISSET(fd,&rfds)) { pkt_len = netio_recv(rxl->nio,pkt,sizeof(pkt)); if (pkt_len > 0) rxl->rx_handler(rxl->nio,pkt,pkt_len,rxl->arg1,rxl->arg2); } } NETIO_RXL_UNLOCK(); } return NULL;}/* Add a RX listener in the listener list */int netio_rxl_add(netio_desc_t *nio,netio_rx_handler_t rx_handler, void *arg1,void *arg2){ struct netio_rx_listener *rxl; NETIO_RXQ_LOCK(); if (!(rxl = malloc(sizeof(*rxl)))) { NETIO_RXQ_UNLOCK(); fprintf(stderr,"netio_rxl_add: unable to create structure.\n"); return(-1); } memset(rxl,0,sizeof(*rxl)); rxl->nio = nio; rxl->ref_count = 1; rxl->rx_handler = rx_handler; rxl->arg1 = arg1; rxl->arg2 = arg2; rxl->running = TRUE; if ((netio_get_fd(rxl->nio) == -1) && pthread_create(&rxl->spec_thread,NULL,netio_rxl_spec_thread,rxl)) { NETIO_RXQ_UNLOCK(); fprintf(stderr,"netio_rxl_add: unable to create specific thread.\n"); free(rxl); return(-1); } rxl->next = netio_rxl_add_list; netio_rxl_add_list = rxl; pthread_cond_wait(&netio_rxl_cond,&netio_rxq_mutex); NETIO_RXQ_UNLOCK(); return(0);}/* Remove a NIO from the listener list */int netio_rxl_remove(netio_desc_t *nio){ NETIO_RXQ_LOCK(); nio->rxl_next = netio_rxl_remove_list; netio_rxl_remove_list = nio; pthread_cond_wait(&netio_rxl_cond,&netio_rxq_mutex); NETIO_RXQ_UNLOCK(); return(0);}/* Initialize the RXL thread */int netio_rxl_init(void){ pthread_cond_init(&netio_rxl_cond,NULL); if (pthread_create(&netio_rxl_thread,NULL,netio_rxl_gen_thread,NULL)) { perror("netio_rxl_init: pthread_create"); return(-1); } return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -