void _tx_ack(bool block = false) { /* check for acknowledgements */ while (_nic.tx()->ack_avail() || block) { Nic::Packet_descriptor acked_packet = _nic.tx()->get_acked_packet(); _nic.tx()->release_packet(acked_packet); block = false; } }
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); }
int send_packet(void *packet, uint32_t packet_len) { Nic::Packet_descriptor tx_packet = _alloc_tx_packet(packet_len); char *tx_content = _nic.tx()->packet_content(tx_packet); Genode::memcpy(tx_content, packet, packet_len); _nic.tx()->submit_packet(tx_packet); _tx_ack(); return VINF_SUCCESS; }
Nic_client(PDRVNIC drvtap) : _tx_block_alloc(_packet_allocator()), _nic(_tx_block_alloc, BUF_SIZE, BUF_SIZE), _link_state_dispatcher(_sig_rec, *this, &Nic_client::_handle_link_state), _rx_packet_avail_dispatcher(_sig_rec, *this, &Nic_client::_handle_rx_packet_avail), _rx_ready_to_ack_dispatcher(_sig_rec, *this, &Nic_client::_handle_rx_ready_to_ack), _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); }
void _handle_rx_packet_avail(unsigned) { while (_nic.rx()->packet_avail() && _nic.rx()->ready_to_ack()) { Nic::Packet_descriptor rx_packet = _nic.rx()->get_packet(); char *rx_content = _nic.rx()->packet_content(rx_packet); int rc = _down_rx->pfnWaitReceiveAvail(_down_rx, RT_INDEFINITE_WAIT); if (RT_FAILURE(rc)) continue; rc = _down_rx->pfnReceive(_down_rx, rx_content, rx_packet.size()); AssertRC(rc); _nic.rx()->acknowledge_packet(rx_packet); } }
void _handle_link_state(unsigned) { _link_up = _nic.link_state(); _down_rx_config->pfnSetLinkState(_down_rx_config, _link_up ? PDMNETWORKLINKSTATE_UP : PDMNETWORKLINKSTATE_DOWN); }
Nic::Packet_descriptor _alloc_tx_packet(Genode::size_t len) { while (true) { try { Nic::Packet_descriptor packet = _nic.tx()->alloc_packet(len); return packet; } catch (Nic::Session::Tx::Source::Packet_alloc_failed) { _tx_ack(true); } } }
Nic::Mac_address mac_address() { return _nic.mac_address(); }