- all networking modules: check device receive status before sending packet

- networking modules 'slirp' and 'vnet': use device speed for timing of
  emulated replies.
This commit is contained in:
Volker Ruppert 2011-12-18 09:12:38 +00:00
parent 9763643106
commit c9af6d043d
9 changed files with 68 additions and 25 deletions

View File

@ -353,7 +353,11 @@ bx_fbsd_pktmover_c::rx_timer(void)
// filter out packets sourced from this node
if (memcmp(bhdr + bhdr->bh_hdrlen + 6, this->fbsd_macaddr, 6)) {
(*rxh)(this->netdev, phdr + bhdr->bh_hdrlen, bhdr->bh_caplen);
if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) {
this->rxh(this->netdev, phdr + bhdr->bh_hdrlen, bhdr->bh_caplen);
} else {
BX_ERROR(("device not ready to receive data"));
}
}
#if BX_ETH_FBSD_LOGGING

View File

@ -281,7 +281,11 @@ bx_linux_pktmover_c::rx_timer(void)
// let through broadcast, multicast, and our mac address
// if ((memcmp(rxbuf, broadcast_macaddr, 6) == 0) || (memcmp(rxbuf, this->linux_macaddr, 6) == 0) || rxbuf[0] & 0x01) {
BX_DEBUG(("eth_linux: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11]));
(*rxh)(netdev, rxbuf, nbytes);
if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) {
this->rxh(this->netdev, rxbuf, nbytes);
} else {
BX_ERROR(("device not ready to receive data"));
}
// }
}
#endif /* if BX_NETWORKING && BX_NETMOD_LINUX */

View File

@ -218,7 +218,9 @@ private:
dhcp_cfg_t dhcp;
int rx_timer_index;
unsigned netdev_speed;
unsigned tx_time;
static void rx_timer_handler(void *);
void rx_timer();
@ -294,11 +296,14 @@ bx_slirp_pktmover_c::bx_slirp_pktmover_c(const char *netif,
}
}
this->rxh = rxh;
this->rxstat = rxstat;
Bit32u status = this->rxstat(this->netdev) & BX_NETDEV_SPEED;
this->netdev_speed = (status == BX_NETDEV_1GBIT) ? 1000 :
(status == BX_NETDEV_100MBIT) ? 100 : 10;
this->rx_timer_index =
bx_pc_system.register_timer(this, this->rx_timer_handler, 1000,
1, 1, "eth_slirp");
this->rxh = rxh;
this->rxstat = rxstat;
memcpy(&dhcp.guest_macaddr[0], macaddr, ETHERNET_MAC_ADDR_LEN);
// ensure the slirp host has a different mac address
memcpy(&dhcp.host_macaddr[0], macaddr, ETHERNET_MAC_ADDR_LEN);
@ -481,7 +486,7 @@ void bx_slirp_pktmover_c::sendpkt(void *buf, unsigned io_len)
#if BX_ETH_SLIRP_LOGGING
write_pktlog_txt(pktlog_txt, (Bit8u*)buf, io_len, 0);
#endif
this->tx_time = (64 + 96 + 4 * 8 + io_len * 8) / 10;
this->tx_time = (64 + 96 + 4 * 8 + io_len * 8) / this->netdev_speed;
switch (ntohs(ethhdr->type)) {
case ETHERNET_TYPE_IPV4:
if (!handle_ipv4((Bit8u*)buf, io_len)) {
@ -508,7 +513,7 @@ void bx_slirp_pktmover_c::prepare_builtin_reply(unsigned type)
memcpy(ethhdr->dst_mac_addr, dhcp.guest_macaddr, ETHERNET_MAC_ADDR_LEN);
memcpy(ethhdr->src_mac_addr, dhcp.host_macaddr, ETHERNET_MAC_ADDR_LEN);
ethhdr->type = htons(type);
rx_time = (64 + 96 + 4 * 8 + pending_reply_size * 8) / 10;
rx_time = (64 + 96 + 4 * 8 + pending_reply_size * 8) / this->netdev_speed;
bx_pc_system.activate_timer(this->rx_timer_index, this->tx_time + rx_time + 100, 0);
}
@ -529,7 +534,11 @@ void bx_slirp_pktmover_c::rx_timer()
#if BX_ETH_SLIRP_LOGGING
write_pktlog_txt(pktlog_txt, reply_buffer, pending_reply_size, 1);
#endif
(*rxh)(this->netdev, reply_buffer, pending_reply_size);
if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) {
this->rxh(this->netdev, reply_buffer, pending_reply_size);
} else {
BX_ERROR(("device not ready to receive data"));
}
pending_reply_size = 0;
// restore timer
bx_pc_system.activate_timer(this->rx_timer_index, 1000, 1);

View File

@ -410,7 +410,11 @@ void bx_tap_pktmover_c::rx_timer()
BX_INFO(("packet too short (%d), padding to 60", nbytes));
nbytes = 60;
}
(*rxh)(netdev, rxbuf, nbytes);
if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) {
this->rxh(this->netdev, rxbuf, nbytes);
} else {
BX_ERROR(("device not ready to receive data"));
}
}
#endif /* if BX_NETWORKING && BX_NETMOD_TAP */

View File

@ -335,7 +335,11 @@ void bx_tuntap_pktmover_c::rx_timer()
BX_INFO(("packet too short (%d), padding to 60", nbytes));
nbytes = 60;
}
(*rxh)(this->netdev, rxbuf, nbytes);
if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) {
this->rxh(this->netdev, rxbuf, nbytes);
} else {
BX_ERROR(("device not ready to receive data"));
}
}
int tun_alloc(char *dev)

View File

@ -253,7 +253,11 @@ void bx_vde_pktmover_c::rx_timer()
BX_INFO(("packet too short (%d), padding to 60", nbytes));
nbytes = 60;
}
(*rxh)(this->netdev, rxbuf, nbytes);
if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) {
this->rxh(this->netdev, rxbuf, nbytes);
} else {
BX_ERROR(("device not ready to receive data"));
}
}
//enum request_type { REQ_NEW_CONTROL };

View File

@ -191,7 +191,9 @@ private:
static void rx_timer_handler(void *);
void rx_timer(void);
int rx_timer_index;
unsigned netdev_speed;
unsigned tx_time;
#if BX_ETH_VNET_LOGGING
@ -273,6 +275,9 @@ void bx_vnet_pktmover_c::pktmover_init(
register_layer4_handler(0x11,INET_PORT_BOOTP_SERVER,udpipv4_dhcp_handler);
register_layer4_handler(0x11,INET_PORT_TFTP_SERVER,udpipv4_tftp_handler);
Bit32u status = this->rxstat(this->netdev) & BX_NETDEV_SPEED;
this->netdev_speed = (status == BX_NETDEV_1GBIT) ? 1000 :
(status == BX_NETDEV_100MBIT) ? 100 : 10;
this->rx_timer_index =
bx_pc_system.register_timer(this, this->rx_timer_handler, 1000,
0, 0, "eth_vnet");
@ -321,7 +326,7 @@ void bx_vnet_pktmover_c::guest_to_host(const Bit8u *buf, unsigned io_len)
}
#endif
this->tx_time = (64 + 96 + 4 * 8 + io_len * 8) / 10;
this->tx_time = (64 + 96 + 4 * 8 + io_len * 8) / this->netdev_speed;
if ((io_len >= 14) &&
(!memcmp(&buf[6],&dhcp.guest_macaddr[0],6)) &&
(!memcmp(&buf[0],&dhcp.host_macaddr[0],6) ||
@ -349,21 +354,25 @@ void bx_vnet_pktmover_c::rx_timer_handler(void *this_ptr)
void bx_vnet_pktmover_c::rx_timer(void)
{
this->rxh(this->netdev, (void *)packet_buffer, packet_len);
if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) {
this->rxh(this->netdev, (void *)packet_buffer, packet_len);
#if BX_ETH_VNET_LOGGING
write_pktlog_txt(pktlog_txt, packet_buffer, packet_len, 1);
write_pktlog_txt(pktlog_txt, packet_buffer, packet_len, 1);
#endif
#if BX_ETH_VNET_PCAP_LOGGING
if (pktlog_pcap && !ferror((FILE *)pktlog_pcap)) {
Bit64u time = bx_pc_system.time_usec();
pcaphdr.ts.tv_usec = time % 1000000;
pcaphdr.ts.tv_sec = time / 1000000;
pcaphdr.caplen = packet_len;
pcaphdr.len = packet_len;
pcap_dump((u_char *)pktlog_pcap, &pcaphdr, packet_buffer);
fflush((FILE *)pktlog_pcap);
}
if (pktlog_pcap && !ferror((FILE *)pktlog_pcap)) {
Bit64u time = bx_pc_system.time_usec();
pcaphdr.ts.tv_usec = time % 1000000;
pcaphdr.ts.tv_sec = time / 1000000;
pcaphdr.caplen = packet_len;
pcaphdr.len = packet_len;
pcap_dump((u_char *)pktlog_pcap, &pcaphdr, packet_buffer);
fflush((FILE *)pktlog_pcap);
}
#endif
} else {
BX_ERROR(("device not ready to receive data"));
}
}
void bx_vnet_pktmover_c::host_to_guest(Bit8u *buf, unsigned io_len)
@ -384,7 +393,7 @@ void bx_vnet_pktmover_c::host_to_guest(Bit8u *buf, unsigned io_len)
packet_len = io_len;
memcpy(&packet_buffer, &buf[0], io_len);
unsigned rx_time = (64 + 96 + 4 * 8 + io_len * 8) / 10;
unsigned rx_time = (64 + 96 + 4 * 8 + io_len * 8) / this->netdev_speed;
bx_pc_system.activate_timer(this->rx_timer_index, this->tx_time + rx_time + 100, 0);
}

View File

@ -378,7 +378,11 @@ void bx_win32_pktmover_c::rx_timer(void)
#if BX_ETH_WIN32_LOGGING
write_pktlog_txt(pktlog_txt, pPacket, pktlen, 1);
#endif
(*this->rxh)(this->netdev, pPacket, pktlen);
if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) {
this->rxh(this->netdev, pPacket, pktlen);
} else {
BX_ERROR(("device not ready to receive data"));
}
}
}
iOffset = Packet_WORDALIGN(iOffset + (hdr->bh_hdrlen + hdr->bh_caplen));

View File

@ -39,9 +39,10 @@ public:
// device receive status definitions
#define BX_NETDEV_RXREADY 0x0001
#define BX_NETDEV_SPEED 0x000e
#define BX_NETDEV_10MBIT 0x0002
#define BX_NETDEV_100MBIT 0x0004
#define BX_NETDEV_1GBIT 0x0006
#define BX_NETDEV_1GBIT 0x0008
typedef void (*eth_rx_handler_t)(void *arg, const void *buf, unsigned len);
typedef Bit32u (*eth_rx_status_t)(void *arg);