nic session: link-state change handling

A Nic::Session client can install a signal handler that is used to
propagate changes of the link-state by calling 'link_state_sigh()'.
The actual link state is queried via 'link_state()'.

The nic-driver interface now provides a Driver_notification callback,
which is used to forward link-state changes from the driver to the
Nic::Session_component.

The following drivers now provide real link state: dde_ipxe, nic_bridge,
and usb_drv. Currently, OpenVPN, Linux nic_drv, and lan9118 do not
support link state and always report link up.

Fixes #1327
This commit is contained in:
Josef Söntgen
2015-03-11 11:33:03 +01:00
committed by Christian Helmuth
parent e4f6fca355
commit dd47129bef
21 changed files with 314 additions and 67 deletions

View File

@ -102,6 +102,10 @@ void Session_component::_free_ipv4_node()
}
bool Session_component::link_state() {
return Net::Env::nic()->link_state(); }
void Session_component::set_ipv4_address(Ipv4_packet::Ipv4_address ip_addr)
{
_free_ipv4_node();

View File

@ -105,6 +105,8 @@ namespace Net {
Mac_address_node _mac_node;
Ipv4_address_node *_ipv4_node;
Genode::Signal_context_capability _link_state_sigh;
void _free_ipv4_node();
public:
@ -137,8 +139,23 @@ namespace Net {
return m;
}
void link_state_changed()
{
if (_link_state_sigh.valid())
Genode::Signal_transmitter(_link_state_sigh).submit();
}
void set_ipv4_address(Ipv4_packet::Ipv4_address ip_addr);
/****************************************
** Nic::Driver notification interface **
****************************************/
bool link_state();
void link_state_sigh(Genode::Signal_context_capability sigh) {
_link_state_sigh = sigh; }
/******************************
** Packet_handler interface **
******************************/

View File

@ -134,4 +134,5 @@ Net::Nic::Nic()
_nic.rx_channel()->sigh_packet_avail(_sink_submit);
_nic.tx_channel()->sigh_ack_avail(_source_ack);
_nic.tx_channel()->sigh_ready_to_submit(_source_submit);
_nic.link_state_sigh(_client_link_state);
}

View File

@ -45,6 +45,7 @@ class Net::Nic : public Net::Packet_handler
::Nic::Connection *nic() { return &_nic; }
Ethernet_frame::Mac_address mac() { return _mac; }
bool link_state() { return _nic.link_state(); }
/******************************
** Packet_handler interface **

View File

@ -54,6 +54,16 @@ void Packet_handler::_ready_to_ack(unsigned)
}
void Packet_handler::_link_state(unsigned)
{
Mac_address_node *node = Env::vlan()->mac_list()->first();
while (node) {
node->component()->link_state_changed();
node = node->next();
}
}
void Packet_handler::broadcast_to_clients(Ethernet_frame *eth, Genode::size_t size)
{
/* check whether it's really a broadcast packet */
@ -121,5 +131,6 @@ Packet_handler::Packet_handler()
: _sink_ack(*Net::Env::receiver(), *this, &Packet_handler::_ack_avail),
_sink_submit(*Net::Env::receiver(), *this, &Packet_handler::_ready_to_submit),
_source_ack(*Net::Env::receiver(), *this, &Packet_handler::_ready_to_ack),
_source_submit(*Net::Env::receiver(), *this, &Packet_handler::_packet_avail)
_source_submit(*Net::Env::receiver(), *this, &Packet_handler::_packet_avail),
_client_link_state(*Net::Env::receiver(), *this, &Packet_handler::_link_state)
{ }

View File

@ -65,12 +65,18 @@ class Net::Packet_handler
*/
void _packet_avail(unsigned) { }
/**
* the link-state of changed
*/
void _link_state(unsigned);
protected:
Genode::Signal_dispatcher<Packet_handler> _sink_ack;
Genode::Signal_dispatcher<Packet_handler> _sink_submit;
Genode::Signal_dispatcher<Packet_handler> _source_ack;
Genode::Signal_dispatcher<Packet_handler> _source_submit;
Genode::Signal_dispatcher<Packet_handler> _client_link_state;
public:

View File

@ -142,6 +142,14 @@ namespace Nic {
Mac_address result = {{1,2,3,4,5,6}};
return result;
}
bool link_state()
{
/* XXX always return true, for now */
return true;
}
void link_state_sigh(Genode::Signal_context_capability sigh) { }
};
class Root : public Genode::Root_component<Session_component>