Implemented the network transmit queue.
This commit is contained in:
@@ -116,6 +116,8 @@ extern void network_close(void);
|
||||
extern void network_reset(void);
|
||||
extern int network_available(void);
|
||||
extern void network_tx(uint8_t *, int);
|
||||
extern void network_do_tx(void);
|
||||
extern int network_tx_queue_check(void);
|
||||
|
||||
extern int net_pcap_prepare(netdev_t *);
|
||||
extern int net_pcap_init(void);
|
||||
@@ -139,7 +141,7 @@ extern const device_t *network_card_getdevice(int);
|
||||
extern void network_set_wait(int wait);
|
||||
extern int network_get_wait(void);
|
||||
|
||||
extern void network_queue_put(void *priv, uint8_t *data, int len);
|
||||
extern void network_queue_put(int tx, void *priv, uint8_t *data, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -166,6 +166,7 @@ poll_thread(void *arg)
|
||||
uint32_t mac_cmp32[2];
|
||||
uint16_t mac_cmp16[2];
|
||||
event_t *evt;
|
||||
int tx;
|
||||
|
||||
pcap_log("PCAP: polling started.\n");
|
||||
thread_set_event(poll_state);
|
||||
@@ -181,16 +182,16 @@ poll_thread(void *arg)
|
||||
/* Wait for a poll request. */
|
||||
network_poll();
|
||||
|
||||
if (pcap == NULL) break;
|
||||
if (pcap == NULL)
|
||||
break;
|
||||
|
||||
/* Wait for the next packet to arrive. */
|
||||
tx = network_tx_queue_check();
|
||||
if (network_get_wait() || (poll_card->set_link_state && poll_card->set_link_state(poll_card->priv)) || (poll_card->wait && poll_card->wait(poll_card->priv)))
|
||||
data = NULL;
|
||||
else
|
||||
data = (uint8_t *)f_pcap_next((void *)pcap, &h);
|
||||
if (data != NULL) {
|
||||
// ui_sb_update_icon(SB_NETWORK, 1);
|
||||
|
||||
/* Received MAC. */
|
||||
mac_cmp32[0] = *(uint32_t *)(data+6);
|
||||
mac_cmp16[0] = *(uint16_t *)(data+10);
|
||||
@@ -201,19 +202,19 @@ poll_thread(void *arg)
|
||||
if ((mac_cmp32[0] != mac_cmp32[1]) ||
|
||||
(mac_cmp16[0] != mac_cmp16[1])) {
|
||||
|
||||
network_queue_put(poll_card->priv, data, h.caplen);
|
||||
// poll_card->rx(poll_card->priv, data, h.caplen);
|
||||
network_queue_put(0, poll_card->priv, data, h.caplen);
|
||||
} else {
|
||||
/* Mark as invalid packet. */
|
||||
data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (tx)
|
||||
network_do_tx();
|
||||
|
||||
/* If we did not get anything, wait a while. */
|
||||
if (data == NULL) {
|
||||
// ui_sb_update_icon(SB_NETWORK, 0);
|
||||
if ((data == NULL) && !tx)
|
||||
thread_wait_event(evt, 10);
|
||||
}
|
||||
|
||||
/* Release ownership of the device. */
|
||||
network_wait(0);
|
||||
@@ -295,17 +296,8 @@ net_pcap_init(void)
|
||||
char *str;
|
||||
|
||||
/* Did we already load the library? */
|
||||
if (pcap_handle == NULL) return(-1);
|
||||
#if 0
|
||||
// no, we don't..
|
||||
/* Load the DLL if needed. We already know it exists. */
|
||||
#ifdef _WIN32
|
||||
pcap_handle = dynld_module("wpcap.dll", pcap_imports);
|
||||
#else
|
||||
pcap_handle = dynld_module("libpcap.so", pcap_imports);
|
||||
#endif
|
||||
if (pcap_handle == NULL) return(-1);
|
||||
#endif
|
||||
if (pcap_handle == NULL)
|
||||
return(-1);
|
||||
|
||||
/* Get the PCAP library name and version. */
|
||||
strcpy(errbuf, f_pcap_lib_version());
|
||||
@@ -333,8 +325,6 @@ net_pcap_close(void)
|
||||
{
|
||||
void *pc;
|
||||
|
||||
// ui_sb_update_icon(SB_NETWORK, 0);
|
||||
|
||||
if (pcap == NULL) return;
|
||||
|
||||
pcap_log("PCAP: closing.\n");
|
||||
@@ -360,15 +350,6 @@ net_pcap_close(void)
|
||||
/* OK, now shut down Pcap itself. */
|
||||
f_pcap_close(pc);
|
||||
pcap = NULL;
|
||||
|
||||
#if 0
|
||||
// no, we don't..
|
||||
/* Unload the DLL if possible. */
|
||||
if (pcap_handle != NULL) {
|
||||
dynld_close((void *)pcap_handle);
|
||||
pcap_handle = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -390,8 +371,6 @@ net_pcap_reset(const netcard_t *card, uint8_t *mac)
|
||||
char filter_exp[255];
|
||||
struct bpf_program fp;
|
||||
|
||||
// ui_sb_update_icon(SB_NETWORK, 0);
|
||||
|
||||
/* Open a PCAP live channel. */
|
||||
if ((pcap = f_pcap_open_live(network_host, /* interface name */
|
||||
1518, /* max packet size */
|
||||
@@ -438,15 +417,8 @@ net_pcap_reset(const netcard_t *card, uint8_t *mac)
|
||||
void
|
||||
net_pcap_in(uint8_t *bufp, int len)
|
||||
{
|
||||
if (pcap == NULL) return;
|
||||
|
||||
// ui_sb_update_icon(SB_NETWORK, 1);
|
||||
|
||||
network_busy(1);
|
||||
if (pcap == NULL)
|
||||
return;
|
||||
|
||||
f_pcap_sendpacket((void *)pcap, bufp, len);
|
||||
|
||||
network_busy(0);
|
||||
|
||||
// ui_sb_update_icon(SB_NETWORK, 0);
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ poll_thread(void *arg)
|
||||
uint16_t mac_cmp16[2];
|
||||
event_t *evt;
|
||||
int data_valid = 0;
|
||||
int tx;
|
||||
|
||||
slirp_log("SLiRP: polling started.\n");
|
||||
thread_set_event(poll_state);
|
||||
@@ -145,12 +146,11 @@ poll_thread(void *arg)
|
||||
if (slirpq == NULL) break;
|
||||
|
||||
/* Wait for the next packet to arrive. */
|
||||
tx = network_tx_queue_check();
|
||||
data_valid = 0;
|
||||
|
||||
if ((!network_get_wait() && !(poll_card->set_link_state && poll_card->set_link_state(poll_card->priv)) && !(poll_card->wait && poll_card->wait(poll_card->priv))) && (QueuePeek(slirpq) != 0)) {
|
||||
/* Grab a packet from the queue. */
|
||||
// ui_sb_update_icon(SB_NETWORK, 1);
|
||||
|
||||
qp = QueueDelete(slirpq);
|
||||
slirp_log("SLiRP: inQ:%d got a %dbyte packet @%08lx\n",
|
||||
QueuePeek(slirpq), qp->len, qp);
|
||||
@@ -165,8 +165,7 @@ poll_thread(void *arg)
|
||||
if ((mac_cmp32[0] != mac_cmp32[1]) ||
|
||||
(mac_cmp16[0] != mac_cmp16[1])) {
|
||||
|
||||
network_queue_put(poll_card->priv, (uint8_t *)qp->data, qp->len);
|
||||
// poll_card->rx(poll_card->priv, (uint8_t *)qp->data, qp->len);
|
||||
network_queue_put(0, poll_card->priv, (uint8_t *)qp->data, qp->len);
|
||||
data_valid = 1;
|
||||
}
|
||||
|
||||
@@ -174,11 +173,12 @@ poll_thread(void *arg)
|
||||
free(qp);
|
||||
}
|
||||
|
||||
if (tx)
|
||||
network_do_tx();
|
||||
|
||||
/* If we did not get anything, wait a while. */
|
||||
if (!data_valid) {
|
||||
// ui_sb_update_icon(SB_NETWORK, 0);
|
||||
if (!data_valid && !tx)
|
||||
thread_wait_event(evt, 10);
|
||||
}
|
||||
|
||||
/* Release ownership of the queue. */
|
||||
network_wait(0);
|
||||
@@ -218,8 +218,6 @@ net_slirp_init(void)
|
||||
int
|
||||
net_slirp_reset(const netcard_t *card, uint8_t *mac)
|
||||
{
|
||||
// ui_sb_update_icon(SB_NETWORK, 0);
|
||||
|
||||
/* Save the callback info. */
|
||||
poll_card = card;
|
||||
|
||||
@@ -237,9 +235,8 @@ net_slirp_close(void)
|
||||
{
|
||||
queueADT sl;
|
||||
|
||||
// ui_sb_update_icon(SB_NETWORK, 0);
|
||||
|
||||
if (slirpq == NULL) return;
|
||||
if (slirpq == NULL)
|
||||
return;
|
||||
|
||||
slirp_log("SLiRP: closing.\n");
|
||||
|
||||
@@ -271,17 +268,10 @@ net_slirp_close(void)
|
||||
void
|
||||
net_slirp_in(uint8_t *pkt, int pkt_len)
|
||||
{
|
||||
if (slirpq == NULL) return;
|
||||
|
||||
// ui_sb_update_icon(SB_NETWORK, 1);
|
||||
|
||||
network_busy(1);
|
||||
if (slirpq == NULL)
|
||||
return;
|
||||
|
||||
slirp_input((const uint8_t *)pkt, pkt_len);
|
||||
|
||||
network_busy(0);
|
||||
|
||||
// ui_sb_update_icon(SB_NETWORK, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -111,16 +111,20 @@ static netcard_t net_cards[] = {
|
||||
int network_type;
|
||||
int network_ndev;
|
||||
int network_card;
|
||||
static volatile int net_wait = 0;
|
||||
char network_host[522];
|
||||
netdev_t network_devs[32];
|
||||
#ifdef ENABLE_NIC_LOG
|
||||
int nic_do_log = ENABLE_NIC_LOG;
|
||||
#endif
|
||||
static mutex_t *network_mutex;
|
||||
static uint8_t *network_mac;
|
||||
pc_timer_t network_queue_timer;
|
||||
netpkt_t *first_pkt = NULL, *last_pkt = NULL;
|
||||
|
||||
|
||||
/* Local variables. */
|
||||
static volatile int net_wait = 0;
|
||||
static mutex_t *network_mutex;
|
||||
static uint8_t *network_mac;
|
||||
static pc_timer_t network_rx_queue_timer;
|
||||
static netpkt_t *first_pkt[2] = { NULL, NULL },
|
||||
*last_pkt[2] = { NULL, NULL };
|
||||
|
||||
|
||||
static struct {
|
||||
@@ -219,7 +223,7 @@ network_init(void)
|
||||
|
||||
|
||||
void
|
||||
network_queue_put(void *priv, uint8_t *data, int len)
|
||||
network_queue_put(int tx, void *priv, uint8_t *data, int len)
|
||||
{
|
||||
netpkt_t *temp;
|
||||
|
||||
@@ -229,50 +233,52 @@ network_queue_put(void *priv, uint8_t *data, int len)
|
||||
temp->data = (uint8_t *) malloc(len);
|
||||
memcpy(temp->data, data, len);
|
||||
temp->len = len;
|
||||
temp->prev = last_pkt[tx];
|
||||
temp->next = NULL;
|
||||
|
||||
if (last_pkt != NULL)
|
||||
last_pkt->next = temp;
|
||||
last_pkt = temp;
|
||||
if (last_pkt[tx] != NULL)
|
||||
last_pkt[tx]->next = temp;
|
||||
last_pkt[tx] = temp;
|
||||
|
||||
if (first_pkt == NULL)
|
||||
first_pkt = temp;
|
||||
if (first_pkt[tx] == NULL)
|
||||
first_pkt[tx] = temp;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
network_queue_get(netpkt_t **pkt)
|
||||
network_queue_get(int tx, netpkt_t **pkt)
|
||||
{
|
||||
if (first_pkt == NULL)
|
||||
if (first_pkt[tx] == NULL)
|
||||
*pkt = NULL;
|
||||
else
|
||||
*pkt = first_pkt;
|
||||
*pkt = first_pkt[tx];
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
network_queue_advance(void)
|
||||
network_queue_advance(int tx)
|
||||
{
|
||||
netpkt_t *temp;
|
||||
|
||||
temp = first_pkt;
|
||||
temp = first_pkt[tx];
|
||||
|
||||
if (temp == NULL)
|
||||
return;
|
||||
|
||||
first_pkt = temp->next;
|
||||
first_pkt[tx] = temp->next;
|
||||
if (temp->data != NULL)
|
||||
free(temp->data);
|
||||
free(temp);
|
||||
|
||||
if (first_pkt == NULL)
|
||||
last_pkt = NULL;
|
||||
if (first_pkt[tx] == NULL)
|
||||
last_pkt[tx] = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
network_queue_clear(void)
|
||||
network_queue_clear(int tx)
|
||||
{
|
||||
netpkt_t *temp = first_pkt;
|
||||
netpkt_t *temp = first_pkt[tx];
|
||||
|
||||
if (temp == NULL)
|
||||
return;
|
||||
@@ -284,27 +290,27 @@ network_queue_clear(void)
|
||||
temp = temp->next;
|
||||
} while (temp != NULL);
|
||||
|
||||
first_pkt = last_pkt = NULL;
|
||||
first_pkt[tx] = last_pkt[tx] = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
network_queue(void *priv)
|
||||
network_rx_queue(void *priv)
|
||||
{
|
||||
netpkt_t *pkt = NULL;
|
||||
|
||||
network_busy(1);
|
||||
|
||||
network_queue_get(&pkt);
|
||||
network_queue_get(0, &pkt);
|
||||
if ((pkt != NULL) && (pkt->len > 0)) {
|
||||
net_cards[network_card].rx(pkt->priv, pkt->data, pkt->len);
|
||||
if (pkt->len >= 128)
|
||||
timer_on_auto(&network_queue_timer, 0.762939453125 * 2.0 * ((double) pkt->len));
|
||||
timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * ((double) pkt->len));
|
||||
else
|
||||
timer_on_auto(&network_queue_timer, 0.762939453125 * 2.0 * 128.0);
|
||||
timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0);
|
||||
} else
|
||||
timer_on_auto(&network_queue_timer, 0.762939453125 * 2.0 * 128.0);
|
||||
network_queue_advance();
|
||||
timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0 * 128.0);
|
||||
network_queue_advance(0);
|
||||
|
||||
network_busy(0);
|
||||
}
|
||||
@@ -346,10 +352,11 @@ network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKST
|
||||
break;
|
||||
}
|
||||
|
||||
first_pkt = last_pkt = NULL;
|
||||
timer_add(&network_queue_timer, network_queue, NULL, 0);
|
||||
first_pkt[0] = first_pkt[1] = NULL;
|
||||
last_pkt[0] = last_pkt[1] = NULL;
|
||||
timer_add(&network_rx_queue_timer, network_rx_queue, NULL, 0);
|
||||
/* 10 mbps. */
|
||||
timer_on_auto(&network_queue_timer, 0.762939453125 * 2.0);
|
||||
timer_on_auto(&network_rx_queue_timer, 0.762939453125 * 2.0);
|
||||
}
|
||||
|
||||
|
||||
@@ -357,7 +364,7 @@ network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait, NETSETLINKST
|
||||
void
|
||||
network_close(void)
|
||||
{
|
||||
timer_stop(&network_queue_timer);
|
||||
timer_stop(&network_rx_queue_timer);
|
||||
|
||||
/* If already closed, do nothing. */
|
||||
if (network_mutex == NULL) return;
|
||||
@@ -383,8 +390,9 @@ network_close(void)
|
||||
network_mutex = NULL;
|
||||
network_mac = NULL;
|
||||
|
||||
/* Here is where we should clear the queue. */
|
||||
network_queue_clear();
|
||||
/* Here is where we clear the queues. */
|
||||
network_queue_clear(0);
|
||||
network_queue_clear(1);
|
||||
|
||||
network_log("NETWORK: closed.\n");
|
||||
}
|
||||
@@ -458,23 +466,51 @@ network_reset(void)
|
||||
}
|
||||
|
||||
|
||||
/* Transmit a packet to one of the network providers. */
|
||||
/* Queue a packet for transmission to one of the network providers. */
|
||||
void
|
||||
network_tx(uint8_t *bufp, int len)
|
||||
{
|
||||
network_busy(1);
|
||||
|
||||
ui_sb_update_icon(SB_NETWORK, 1);
|
||||
|
||||
switch(network_type) {
|
||||
case NET_TYPE_PCAP:
|
||||
net_pcap_in(bufp, len);
|
||||
break;
|
||||
|
||||
case NET_TYPE_SLIRP:
|
||||
net_slirp_in(bufp, len);
|
||||
break;
|
||||
}
|
||||
network_queue_put(1, NULL, bufp, len);
|
||||
|
||||
ui_sb_update_icon(SB_NETWORK, 0);
|
||||
|
||||
network_busy(0);
|
||||
}
|
||||
|
||||
|
||||
/* Actually transmit the packet. */
|
||||
void
|
||||
network_do_tx(void)
|
||||
{
|
||||
netpkt_t *pkt = NULL;
|
||||
|
||||
network_queue_get(1, &pkt);
|
||||
if ((pkt != NULL) && (pkt->len > 0)) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
network_tx_queue_check(void)
|
||||
{
|
||||
if ((first_pkt[1] == NULL) && (last_pkt[1] == NULL))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user