vbox: improve network backend

VirtualBox mainly derives the initial link-state for its device models
from checking the <Adapter ... cable="true"/> attribute. Our backend
only propagates the current state of the Nic session if it receives a
link-state signal. This may lead to problems if a guest detects a link
up state when it is actually down and wants to use the interface. The
backend now queries the Nic session and sets the link-state accordingly
when it is constructed.

In case there is no link do not attempt to submit a packet to the packet
stream but return with an error so that upper layers can handle it.

Enable signals for network on poweron and not already during
construction. The network model may be not yet ready to process incoming
signals and data.

Fixes #2117.
This commit is contained in:
Josef Söntgen 2016-10-06 11:26:26 +02:00 committed by Christian Helmuth
parent f75f199947
commit 9ba7b2edde

View File

@ -89,6 +89,8 @@ class Nic_client
Genode::Signal_dispatcher<Nic_client> _rx_ready_to_ack_dispatcher;
Genode::Signal_dispatcher<Nic_client> _destruct_dispatcher;
bool _link_up = false;
/* VM <-> device driver (down) <-> nic_client (up) <-> nic session */
PPDMINETWORKDOWN _down_rx;
PPDMINETWORKCONFIG _down_rx_config;
@ -115,9 +117,11 @@ class Nic_client
void _handle_link_state(unsigned)
{
_link_up = _nic.link_state();
_down_rx_config->pfnSetLinkState(_down_rx_config,
_nic.link_state() ? PDMNETWORKLINKSTATE_UP
: PDMNETWORKLINKSTATE_DOWN);
_link_up ? PDMNETWORKLINKSTATE_UP
: PDMNETWORKLINKSTATE_DOWN);
}
/**
@ -167,11 +171,7 @@ class Nic_client
_destruct_dispatcher(_sig_rec, *this, &Nic_client::_handle_destruct),
_down_rx(drvtap->pIAboveNet),
_down_rx_config(drvtap->pIAboveConfig)
{
_nic.link_state_sigh(_link_state_dispatcher);
_nic.rx_channel()->sigh_packet_avail(_rx_packet_avail_dispatcher);
_nic.rx_channel()->sigh_ready_to_ack(_rx_ready_to_ack_dispatcher);
}
{ }
~Nic_client()
{
@ -179,12 +179,24 @@ class Nic_client
destroy(env()->heap(), _tx_block_alloc);
}
void enable_signals()
{
_nic.link_state_sigh(_link_state_dispatcher);
_nic.rx_channel()->sigh_packet_avail(_rx_packet_avail_dispatcher);
_nic.rx_channel()->sigh_ready_to_ack(_rx_ready_to_ack_dispatcher);
/* set initial link-state */
_handle_link_state(1);
}
Genode::Signal_context_capability &dispatcher() { return _destruct_dispatcher; }
Genode::Signal_receiver &sig_rec() { return _sig_rec; }
Nic::Mac_address mac_address() { return _nic.mac_address(); }
int send_packet(void *packet, uint32_t packet_len)
{
if (!_link_up) { return VERR_NET_DOWN; }
Nic::Packet_descriptor tx_packet = _alloc_tx_packet(packet_len);
char *tx_content = _nic.tx()->packet_content(tx_packet);
@ -548,6 +560,14 @@ static DECLCALLBACK(int) drvNicConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uin
}
static DECLCALLBACK(void) drvNicPowerOn(PPDMDRVINS pDrvIns)
{
PDRVNIC pThis = PDMINS_2_DATA(pDrvIns, PDRVNIC);
if (pThis && pThis->nic_client)
pThis->nic_client->enable_signals();
}
/**
* Nic network transport driver registration record.
*/
@ -579,8 +599,7 @@ const PDMDRVREG g_DrvHostInterface =
NULL,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
NULL,
drvNicPowerOn,
/* pfnReset */
NULL,
/* pfnSuspend */