X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=linux_module%2Fpalacios-vnet-brg.c;h=abf4142dcd9dde14452275b96dd38adf1536d3a0;hb=c8b23e99efde3aa5a2c26d1b8e9bc7dc914e6113;hp=efb7d18b58378302ba681473387037846bb4c3ba;hpb=07aa8f3c18a33af0961e7546980a63ab5f6fba4f;p=palacios.git diff --git a/linux_module/palacios-vnet-brg.c b/linux_module/palacios-vnet-brg.c index efb7d18..abf4142 100644 --- a/linux_module/palacios-vnet-brg.c +++ b/linux_module/palacios-vnet-brg.c @@ -19,15 +19,22 @@ #include #include +#include +#include +#include + #include #include #include "palacios-vnet.h" #include "palacios.h" + #define VNET_SERVER_PORT 9000 -#define VNET_YIELD_TIME_USEC 1000 +#define VNET_ADAPTIVE_BRIDGE 1 // set this to one to have bridge go to sleep if there nothing to do... +#define VNET_NOPROGRESS_LIMIT 1000 // ... after this many iterations +#define VNET_YIELD_TIME_USEC 1000 // ... and go to sleep for this long struct vnet_link { uint32_t dst_ip; @@ -94,15 +101,15 @@ static inline struct vnet_link * _link_by_idx(int idx) { static void _delete_link(struct vnet_link * link){ - unsigned long flags; + unsigned long flags = 0; link->sock->ops->release(link->sock); - spin_lock_irqsave(&(vnet_brg_s.lock), flags); + palacios_spinlock_lock_irqsave(&(vnet_brg_s.lock), flags); list_del(&(link->node)); vnet_htable_remove(vnet_brg_s.ip2link, (addr_t)&(link->dst_ip), 0); vnet_brg_s.num_links --; - spin_unlock_irqrestore(&(vnet_brg_s.lock), flags); + palacios_spinlock_unlock_irqrestore(&(vnet_brg_s.lock), flags); INFO("VNET Bridge: Link deleted, ip 0x%x, port: %d, idx: %d\n", link->dst_ip, @@ -122,7 +129,7 @@ void vnet_brg_delete_link(uint32_t idx){ } static void deinit_links_list(void){ - struct vnet_link * link, * tmp_link; + struct vnet_link * link = NULL, * tmp_link = NULL; list_for_each_entry_safe(link, tmp_link, &(vnet_brg_s.link_list), node) { _delete_link(link); @@ -152,23 +159,37 @@ static uint32_t _create_link(struct vnet_link * link) { return -1; } + if (link->sock_proto == UDP) { + // no UDP checksumming + lock_sock(link->sock->sk); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0) + link->sock->sk->sk_no_check = 1; +#else + link->sock->sk->sk_no_check_tx = 1; + link->sock->sk->sk_no_check_rx = 1; +#endif + release_sock(link->sock->sk); + } + memset(&link->sock_addr, 0, sizeof(struct sockaddr)); link->sock_addr.sin_family = AF_INET; link->sock_addr.sin_addr.s_addr = link->dst_ip; link->sock_addr.sin_port = htons(link->dst_port); - if ((err = link->sock->ops->connect(link->sock, (struct sockaddr *)&(link->sock_addr), sizeof(struct sockaddr), 0) < 0)) { + + if ((err = link->sock->ops->connect(link->sock, (struct sockaddr *)&(link->sock_addr), sizeof(struct sockaddr), 0)) < 0) { WARNING("Could not connect to remote VNET Server, error %d\n", err); return -1; } - spin_lock_irqsave(&(vnet_brg_s.lock), flags); + + palacios_spinlock_lock_irqsave(&(vnet_brg_s.lock), flags); list_add(&(link->node), &(vnet_brg_s.link_list)); vnet_brg_s.num_links ++; link->idx = ++ vnet_brg_s.link_idx; vnet_htable_insert(vnet_brg_s.ip2link, (addr_t)&(link->dst_ip), (addr_t)link); - spin_unlock_irqrestore(&(vnet_brg_s.lock), flags); + palacios_spinlock_unlock_irqrestore(&(vnet_brg_s.lock), flags); INFO("VNET Bridge: Link created, ip 0x%x, port: %d, idx: %d, link: %p, protocol: %s\n", link->dst_ip, @@ -237,13 +258,17 @@ _udp_send(struct socket * sock, iov.iov_base = buf; iov.iov_len = len; - msg.msg_flags = 0; + msg.msg_flags = MSG_NOSIGNAL; msg.msg_name = addr; msg.msg_namelen = sizeof(struct sockaddr_in); msg.msg_control = NULL; msg.msg_controllen = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) msg.msg_iov = &iov; msg.msg_iovlen = 1; +#else + iov_iter_init(&(msg.msg_iter),WRITE,&iov,1,0); +#endif msg.msg_control = NULL; oldfs = get_fs(); @@ -277,8 +302,12 @@ _udp_recv(struct socket * sock, msg.msg_namelen = sizeof(struct sockaddr_in); msg.msg_control = NULL; msg.msg_controllen = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) msg.msg_iov = &iov; msg.msg_iovlen = 1; +#else + iov_iter_init(&(msg.msg_iter),READ,&iov,1,0); +#endif msg.msg_control = NULL; oldfs = get_fs(); @@ -296,7 +325,9 @@ send_to_palacios(unsigned char * buf, int len, int link_id){ struct v3_vnet_pkt pkt; + memset(&pkt,0,sizeof(struct v3_vnet_pkt)); pkt.size = len; + pkt.dst_type = LINK_NOSET; pkt.src_type = LINK_EDGE; pkt.src_id = link_id; memcpy(pkt.header, buf, ETHERNET_HEADER_LEN); @@ -321,7 +352,7 @@ static int bridge_send_pkt(struct v3_vm_info * vm, struct v3_vnet_pkt * pkt, void * private_data) { - struct vnet_link * link; + struct vnet_link * link = NULL; if(net_debug >= 2){ DEBUG("VNET Lnx Host Bridge: packet received from VNET Core ... pkt size: %d, link: %d\n", @@ -382,6 +413,18 @@ static int init_vnet_serv(void) { return -1; } + if (vnet_brg_s.serv_proto == UDP) { + // No UDP checksumming is done + lock_sock(vnet_brg_s.serv_sock->sk); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0) + vnet_brg_s.serv_sock->sk->sk_no_check = 1; +#else + vnet_brg_s.serv_sock->sk->sk_no_check_tx = 1; + vnet_brg_s.serv_sock->sk->sk_no_check_rx = 1; +#endif + release_sock(vnet_brg_s.serv_sock->sk); + } + memset(&vnet_brg_s.serv_addr, 0, sizeof(struct sockaddr)); vnet_brg_s.serv_addr.sin_family = AF_INET; @@ -402,6 +445,8 @@ static int init_vnet_serv(void) { } } + + return 0; } @@ -410,6 +455,7 @@ static int _udp_server(void * arg) { struct sockaddr_in pkt_addr; struct vnet_link * link = NULL; int len; + uint64_t noprogress_count; INFO("Palacios VNET Bridge: UDP receiving server ..... \n"); @@ -420,6 +466,8 @@ static int _udp_server(void * arg) { return -1; } + + noprogress_count=0; while (!kthread_should_stop()) { @@ -434,10 +482,32 @@ static int _udp_server(void * arg) { // If it would have blocked, we have no packet, and so // we will give other threads on this core a chance if (len==-EAGAIN || len==-EWOULDBLOCK || len==-EINTR) { - palacios_yield_cpu_timed(VNET_YIELD_TIME_USEC); + + // avoid rollover in the counter out of paranoia + if (! ((noprogress_count + 1) < noprogress_count)) { + noprogress_count++; + } + + // adaptively select yielding strategy depending on + // whether we are making progress + if ((!VNET_ADAPTIVE_BRIDGE) || (noprogress_count < VNET_NOPROGRESS_LIMIT)) { + // Likely making progress, do fast yield so we + // come back immediately if there is no other action + palacios_yield_cpu(); + } else { + // Likely not making progress, do potentially slow + // yield - we won't come back for until VNET_YIELD_TIME_USEC has passed + palacios_sleep_cpu(VNET_YIELD_TIME_USEC); + } + continue; } + + // Something interesting has happened, therefore progress! + noprogress_count=0; + + if(len < 0) { WARNING("Receive error: Could not get packet, error %d\n", len); continue; @@ -504,7 +574,7 @@ int vnet_bridge_init(void) { memset(&vnet_brg_s, 0, sizeof(struct vnet_brg_state)); INIT_LIST_HEAD(&(vnet_brg_s.link_list)); - spin_lock_init(&(vnet_brg_s.lock)); + palacios_spinlock_init(&(vnet_brg_s.lock)); vnet_brg_s.serv_proto = UDP; @@ -558,6 +628,8 @@ void vnet_bridge_deinit(void){ vnet_brg_s.status = 0; + palacios_spinlock_deinit(&(vnet_brg_s.lock)); + INFO("VNET LNX Bridge Deinit Finished\n"); }