#include <linux/sched.h>
#include <asm/msr.h>
+#include <linux/net.h>
+#include <linux/socket.h>
+#include <net/sock.h>
+
#include <vnet/vnet.h>
#include <vnet/vnet_hashtable.h>
#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;
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,
return -1;
}
+ if (link->sock_proto == UDP) {
+ // no UDP checksumming
+ lock_sock(link->sock->sk);
+ link->sock->sk->sk_no_check = 1;
+ 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)) {
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,
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;
return -1;
}
+ if (vnet_brg_s.serv_proto == UDP) {
+ // No UDP checksumming is done
+ lock_sock(vnet_brg_s.serv_sock->sk);
+ vnet_brg_s.serv_sock->sk->sk_no_check = 1;
+ 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;
}
}
+
+
return 0;
}
struct sockaddr_in pkt_addr;
struct vnet_link * link = NULL;
int len;
+ uint64_t noprogress_count;
INFO("Palacios VNET Bridge: UDP receiving server ..... \n");
return -1;
}
+
+ noprogress_count=0;
while (!kthread_should_stop()) {
// 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;
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;
vnet_brg_s.status = 0;
+ palacios_spinlock_deinit(&(vnet_brg_s.lock));
+
INFO("VNET LNX Bridge Deinit Finished\n");
}