From 9ba7b2eddea284506d2ec22227cd8fd05230a25b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Thu, 6 Oct 2016 11:26:26 +0200 Subject: [PATCH] vbox: improve network backend VirtualBox mainly derives the initial link-state for its device models from checking the 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. --- repos/ports/src/virtualbox/network.cpp | 37 +++++++++++++++++++------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/repos/ports/src/virtualbox/network.cpp b/repos/ports/src/virtualbox/network.cpp index 8746762614..efd3e0fbf2 100644 --- a/repos/ports/src/virtualbox/network.cpp +++ b/repos/ports/src/virtualbox/network.cpp @@ -89,6 +89,8 @@ class Nic_client Genode::Signal_dispatcher _rx_ready_to_ack_dispatcher; Genode::Signal_dispatcher _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 */