network: improve throughput by batch processing packets
This commit is contained in:
@@ -240,12 +240,11 @@ network_init(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
network_queue_init(netqueue_t *queue)
|
||||
{
|
||||
queue->size = NET_QUEUE_LEN;
|
||||
queue->head = queue->tail = 0;
|
||||
for (int i=0; i<queue->size; i++) {
|
||||
for (int i=0; i<NET_QUEUE_LEN; i++) {
|
||||
queue->packets[i].data = calloc(1, NET_MAX_FRAME);
|
||||
queue->packets[i].len = 0;
|
||||
}
|
||||
@@ -255,7 +254,7 @@ network_queue_init(netqueue_t *queue)
|
||||
static bool
|
||||
network_queue_full(netqueue_t *queue)
|
||||
{
|
||||
return ((queue->head + 1) % queue->size) == queue->tail;
|
||||
return ((queue->head + 1) & NET_QUEUE_LEN_MASK) == queue->tail;
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -264,30 +263,50 @@ network_queue_empty(netqueue_t *queue)
|
||||
return (queue->head == queue->tail);
|
||||
}
|
||||
|
||||
static inline void
|
||||
network_swap_packet(netpkt_t *pkt1, netpkt_t *pkt2)
|
||||
{
|
||||
netpkt_t tmp = *pkt2;
|
||||
*pkt2 = *pkt1;
|
||||
*pkt1 = tmp;
|
||||
}
|
||||
|
||||
int
|
||||
network_queue_put(netqueue_t *queue, uint8_t *data, int len)
|
||||
{
|
||||
if (len > NET_MAX_FRAME || network_queue_full(queue)) {
|
||||
if (len == 0 || len > NET_MAX_FRAME || network_queue_full(queue)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
netpkt_t *pkt = &queue->packets[queue->head];
|
||||
memcpy(pkt->data, data, len);
|
||||
pkt->len = len;
|
||||
queue->head = (queue->head + 1) % queue->size;
|
||||
queue->head = (queue->head + 1) & NET_QUEUE_LEN_MASK;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
network_queue_put_swap(netqueue_t *queue, netpkt_t *src_pkt)
|
||||
{
|
||||
if (src_pkt->len == 0 || src_pkt->len > NET_MAX_FRAME || network_queue_full(queue)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
netpkt_t *dst_pkt = &queue->packets[queue->head];
|
||||
network_swap_packet(src_pkt, dst_pkt);
|
||||
|
||||
queue->head = (queue->head + 1) & NET_QUEUE_LEN_MASK;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
network_queue_get(netqueue_t *queue, netpkt_t *dst_pkt) {
|
||||
network_queue_get_swap(netqueue_t *queue, netpkt_t *dst_pkt) {
|
||||
if (network_queue_empty(queue))
|
||||
return 0;
|
||||
|
||||
netpkt_t *pkt = &queue->packets[queue->tail];
|
||||
memcpy(dst_pkt->data, pkt->data, pkt->len);
|
||||
dst_pkt->len = pkt->len;
|
||||
queue->tail = (queue->tail + 1) % queue->size;
|
||||
|
||||
netpkt_t *src_pkt = &queue->packets[queue->tail];
|
||||
network_swap_packet(src_pkt, dst_pkt);
|
||||
queue->tail = (queue->tail + 1) & NET_QUEUE_LEN_MASK;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -303,23 +322,18 @@ network_queue_move(netqueue_t *dst_q, netqueue_t *src_q)
|
||||
|
||||
netpkt_t *src_pkt = &src_q->packets[src_q->tail];
|
||||
netpkt_t *dst_pkt = &dst_q->packets[dst_q->head];
|
||||
uint8_t *tmp_dat = dst_pkt->data;
|
||||
|
||||
dst_pkt->data = src_pkt->data;
|
||||
dst_pkt->len = src_pkt->len;
|
||||
dst_q->head = (dst_q->head + 1) % dst_q->size;
|
||||
network_swap_packet(src_pkt, dst_pkt);
|
||||
dst_q->head = (dst_q->head + 1) & NET_QUEUE_LEN_MASK;
|
||||
src_q->tail = (src_q->tail + 1) & NET_QUEUE_LEN_MASK;
|
||||
|
||||
src_pkt->data = tmp_dat;
|
||||
src_pkt->len = 0;
|
||||
src_q->tail = (src_q->tail + 1) % src_q->size;
|
||||
|
||||
return 1;
|
||||
return dst_pkt->len;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
network_queue_clear(netqueue_t *queue)
|
||||
{
|
||||
for (int i=0; i<queue->size; i++) {
|
||||
for (int i=0; i<NET_QUEUE_LEN; i++) {
|
||||
free(queue->packets[i].data);
|
||||
queue->packets[i].len = 0;
|
||||
}
|
||||
@@ -331,41 +345,47 @@ static void
|
||||
network_rx_queue(void *priv)
|
||||
{
|
||||
netcard_t *card = (netcard_t *)priv;
|
||||
double timer_period;
|
||||
int ret = 0;
|
||||
|
||||
bool activity = false;
|
||||
uint32_t rx_bytes = 0;
|
||||
for (int i = 0; i < NET_QUEUE_LEN; i++) {
|
||||
if (card->queued_pkt.len == 0) {
|
||||
thread_wait_mutex(card->rx_mutex);
|
||||
int res = network_queue_get_swap(&card->queues[NET_QUEUE_RX], &card->queued_pkt);
|
||||
thread_release_mutex(card->rx_mutex);
|
||||
if (!res)
|
||||
break;
|
||||
}
|
||||
|
||||
if (card->queued_pkt.len == 0) {
|
||||
thread_wait_mutex(card->rx_mutex);
|
||||
network_queue_get(&card->queues[NET_QUEUE_RX], &card->queued_pkt);
|
||||
thread_release_mutex(card->rx_mutex);
|
||||
}
|
||||
|
||||
if (card->queued_pkt.len > 0) {
|
||||
network_dump_packet(&card->queued_pkt);
|
||||
ret = card->rx(card->card_drv, card->queued_pkt.data, card->queued_pkt.len);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
activity = true;
|
||||
timer_period = 0.762939453125 * ((card->queued_pkt.len >= 128) ? ((double) card->queued_pkt.len) : 128.0);
|
||||
int res = card->rx(card->card_drv, card->queued_pkt.data, card->queued_pkt.len);
|
||||
if (!res)
|
||||
break;
|
||||
rx_bytes += card->queued_pkt.len;
|
||||
card->queued_pkt.len = 0;
|
||||
} else {
|
||||
timer_period = 0.762939453125 * 128.0;
|
||||
}
|
||||
timer_on_auto(&card->timer, timer_period);
|
||||
|
||||
/* Transmission. */
|
||||
uint32_t tx_bytes = 0;
|
||||
thread_wait_mutex(card->tx_mutex);
|
||||
ret = network_queue_move(&card->queues[NET_QUEUE_TX_HOST], &card->queues[NET_QUEUE_TX_VM]);
|
||||
for (int i = 0; i < NET_QUEUE_LEN; i++) {
|
||||
uint32_t bytes = network_queue_move(&card->queues[NET_QUEUE_TX_HOST], &card->queues[NET_QUEUE_TX_VM]);
|
||||
if (!bytes)
|
||||
break;
|
||||
tx_bytes += bytes;
|
||||
}
|
||||
thread_release_mutex(card->tx_mutex);
|
||||
if (ret) {
|
||||
if (tx_bytes) {
|
||||
/* Notify host that a packet is available in the TX queue */
|
||||
card->host_drv.notify_in(card->host_drv.priv);
|
||||
activity = true;
|
||||
}
|
||||
|
||||
double timer_period = 0.762939453125 * (rx_bytes > tx_bytes ? rx_bytes : tx_bytes);
|
||||
if (timer_period < 200)
|
||||
timer_period = 200;
|
||||
|
||||
timer_on_auto(&card->timer, timer_period);
|
||||
|
||||
bool activity = rx_bytes || tx_bytes;
|
||||
ui_sb_update_icon(SB_NETWORK, activity);
|
||||
}
|
||||
|
||||
@@ -498,12 +518,29 @@ int network_tx_pop(netcard_t *card, netpkt_t *out_pkt)
|
||||
int ret = 0;
|
||||
|
||||
thread_wait_mutex(card->tx_mutex);
|
||||
ret = network_queue_get(&card->queues[NET_QUEUE_TX_HOST], out_pkt);
|
||||
ret = network_queue_get_swap(&card->queues[NET_QUEUE_TX_HOST], out_pkt);
|
||||
thread_release_mutex(card->tx_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int network_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size)
|
||||
{
|
||||
int pkt_count = 0;
|
||||
|
||||
netqueue_t *queue = &card->queues[NET_QUEUE_TX_HOST];
|
||||
thread_wait_mutex(card->tx_mutex);
|
||||
for (int i = 0; i < vec_size; i++) {
|
||||
if (!network_queue_get_swap(queue, pkt_vec))
|
||||
break;
|
||||
pkt_count++;
|
||||
pkt_vec++;
|
||||
}
|
||||
thread_release_mutex(card->tx_mutex);
|
||||
|
||||
return pkt_count;
|
||||
}
|
||||
|
||||
int network_rx_put(netcard_t *card, uint8_t *bufp, int len)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -515,6 +552,17 @@ int network_rx_put(netcard_t *card, uint8_t *bufp, int len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int network_rx_put_pkt(netcard_t *card, netpkt_t *pkt)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
thread_wait_mutex(card->rx_mutex);
|
||||
ret = network_queue_put_swap(&card->queues[NET_QUEUE_RX], pkt);
|
||||
thread_release_mutex(card->rx_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
network_dev_to_id(char *devname)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user