diff --git a/src/network/network.c b/src/network/network.c index efcbc9ccf..2428d7305 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -122,7 +122,7 @@ static uint8_t network_timer_active = 0; static pc_timer_t network_rx_queue_timer; static netpkt_t *first_pkt[3] = { NULL, NULL, NULL }, *last_pkt[3] = { NULL, NULL, NULL }; -static netpkt_t *queued_pkt = NULL; +static netpkt_t queued_pkt; #ifdef ENABLE_NETWORK_LOG @@ -244,8 +244,7 @@ network_queue_put(int tx, void *priv, uint8_t *data, int len) { netpkt_t *temp; - temp = (netpkt_t *) malloc(sizeof(netpkt_t)); - memset(temp, 0, sizeof(netpkt_t)); + temp = (netpkt_t *) calloc(sizeof(netpkt_t), 1); temp->priv = priv; memcpy(temp->data, data, len); temp->len = len; @@ -262,17 +261,29 @@ network_queue_put(int tx, void *priv, uint8_t *data, int len) static void -network_queue_get(int tx, netpkt_t **pkt) +network_queue_get(int tx, netpkt_t *pkt) { + netpkt_t *temp; + + temp = first_pkt[tx]; + + if (temp == NULL) { + memset(pkt, 0x00, sizeof(netpkt_t)); + return; + } + + memcpy(pkt, temp, sizeof(netpkt_t)); + + first_pkt[tx] = temp->next; + free(temp); + if (first_pkt[tx] == NULL) - *pkt = NULL; - else - *pkt = first_pkt[tx]; + last_pkt[tx] = NULL; } static void -network_queue_advance(int tx) +network_queue_transmit(int tx) { netpkt_t *temp; @@ -281,6 +292,20 @@ network_queue_advance(int tx) if (temp == NULL) return; + if (temp->len > 0) { + network_dump_packet(temp); + /* Why on earth is this not a function pointer?! */ + switch(network_type) { + case NET_TYPE_PCAP: + net_pcap_in(temp->data, temp->len); + break; + + case NET_TYPE_SLIRP: + net_slirp_in(temp->data, temp->len); + break; + } + } + first_pkt[tx] = temp->next; free(temp); @@ -289,6 +314,38 @@ network_queue_advance(int tx) } +static void +network_queue_copy(int dest, int src) +{ + netpkt_t *temp, *temp2; + + temp = first_pkt[src]; + + if (temp == NULL) + return; + + temp2 = (netpkt_t *) calloc(sizeof(netpkt_t), 1); + temp2->priv = temp->priv; + memcpy(temp2->data, temp->data, temp->len); + temp2->len = temp->len; + temp2->prev = last_pkt[dest]; + temp2->next = NULL; + + if (last_pkt[dest] != NULL) + last_pkt[dest]->next = temp2; + last_pkt[dest] = temp2; + + if (first_pkt[dest] == NULL) + first_pkt[dest] = temp2; + + first_pkt[src] = temp->next; + free(temp); + + if (first_pkt[src] == NULL) + last_pkt[src] = NULL; +} + + static void network_queue_clear(int tx) { @@ -311,36 +368,24 @@ static void network_rx_queue(void *priv) { int ret = 1; - netpkt_t *tx_queued_pkt = NULL; - if (network_rx_pause) { + if (network_rx_pause || !thread_test_mutex(network_mutex)) { timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0); return; } - network_wait(1); - - if (queued_pkt == NULL) + if (queued_pkt.len == 0) network_queue_get(0, &queued_pkt); - if ((queued_pkt != NULL) && (queued_pkt->len > 0)) { - network_dump_packet(queued_pkt); - ret = net_cards[network_card].rx(queued_pkt->priv, queued_pkt->data, queued_pkt->len); - if (queued_pkt->len >= 128) - timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * ((double) queued_pkt->len)); - else - timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0); - } else - timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0); + if (queued_pkt.len > 0) { + network_dump_packet(&queued_pkt); + ret = net_cards[network_card].rx(queued_pkt.priv, queued_pkt.data, queued_pkt.len); + } + timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * ((queued_pkt.len >= 128) ? ((double) queued_pkt.len) : 128.0)); if (ret) - queued_pkt = NULL; - network_queue_advance(0); + queued_pkt.len = 0; /* Transmission. */ - network_queue_get(2, &tx_queued_pkt); - if (tx_queued_pkt != NULL) { - network_queue_put(1, tx_queued_pkt->priv, tx_queued_pkt->data, tx_queued_pkt->len); - network_queue_advance(2); - } + network_queue_copy(1, 2); network_wait(0); } @@ -380,7 +425,7 @@ network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKST first_pkt[0] = first_pkt[1] = first_pkt[2] = NULL; last_pkt[0] = last_pkt[1] = last_pkt[2] = NULL; - queued_pkt = NULL; + memset(&queued_pkt, 0x00, sizeof(netpkt_t)); memset(&network_rx_queue_timer, 0x00, sizeof(pc_timer_t)); timer_add(&network_rx_queue_timer, network_rx_queue, NULL, 0); /* 10 mbps. */ @@ -516,28 +561,13 @@ network_tx(uint8_t *bufp, int len) int network_tx_queue_check(void) { - netpkt_t *pkt = NULL; - if ((first_pkt[1] == NULL) && (last_pkt[1] == NULL)) return 0; if (network_tx_pause) return 1; - network_queue_get(1, &pkt); - if ((pkt != NULL) && (pkt->len > 0)) { - network_dump_packet(pkt); - switch(network_type) { - case NET_TYPE_PCAP: - net_pcap_in(pkt->data, pkt->len); - break; - - case NET_TYPE_SLIRP: - net_slirp_in(pkt->data, pkt->len); - break; - } - } - network_queue_advance(1); + network_queue_transmit(1); return 1; }