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

@ -72,6 +72,7 @@ class Lan9118 : public Nic::Driver
Timer::Connection _timer;
Nic::Rx_buffer_alloc &_rx_buffer_alloc;
Nic::Mac_address _mac_addr;
Nic::Driver_notification &_notify;
enum { IRQ_STACK_SIZE = 4096 };
Genode::Irq_activation _irq_activation;
@ -201,11 +202,13 @@ class Lan9118 : public Nic::Driver
* \throw Device_not_supported
*/
Lan9118(Genode::addr_t mmio_base, Genode::size_t mmio_size, int irq,
Nic::Rx_buffer_alloc &rx_buffer_alloc)
Nic::Rx_buffer_alloc &rx_buffer_alloc,
Nic::Driver_notification &notify)
:
_mmio(mmio_base, mmio_size),
_reg_base(_mmio.local_addr<Genode::uint32_t>()),
_rx_buffer_alloc(rx_buffer_alloc),
_notify(notify),
_irq_activation(irq, *this, IRQ_STACK_SIZE)
{
unsigned long const id_rev = _reg_read(ID_REV),
@ -287,6 +290,8 @@ class Lan9118 : public Nic::Driver
_mac_csr_write(MAC_CR, 0);
}
void link_state_changed() { _notify.link_state_changed(); }
/***************************
** Nic::Driver interface **
@ -297,6 +302,12 @@ class Lan9118 : public Nic::Driver
return _mac_addr;
}
bool link_state()
{
/* XXX always return true for now */
return true;
}
void tx(char const *packet, Genode::size_t size)
{
/* limit size to 11 bits, the maximum supported by lan9118 */

View File

@ -37,10 +37,11 @@ int main(int, char **)
*/
struct Lan9118_driver_factory : Nic::Driver_factory
{
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc)
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc,
Nic::Driver_notification &notify)
{
return new (env()->heap())
Lan9118(LAN9118_PHYS, LAN9118_SIZE, LAN9118_IRQ, alloc);
Lan9118(LAN9118_PHYS, LAN9118_SIZE, LAN9118_IRQ, alloc, notify);
}
void destroy(Nic::Driver *driver)

View File

@ -67,8 +67,9 @@ class Linux_driver : public Nic::Driver
}
};
Nic::Mac_address _mac_addr;
Nic::Rx_buffer_alloc &_alloc;
Nic::Mac_address _mac_addr;
Nic::Rx_buffer_alloc &_alloc;
Nic::Driver_notification &_notify;
char _packet_buffer[1514]; /* maximum ethernet packet length */
int _tap_fd;
@ -114,8 +115,11 @@ class Linux_driver : public Nic::Driver
public:
Linux_driver(Nic::Rx_buffer_alloc &alloc)
: _alloc(alloc), _tap_fd(_setup_tap_fd()), _rx_thread(_tap_fd, *this)
Linux_driver(Nic::Rx_buffer_alloc &alloc,
Nic::Driver_notification &notify)
:
_alloc(alloc), _notify(notify),
_tap_fd(_setup_tap_fd()), _rx_thread(_tap_fd, *this)
{
/* try using configured MAC address */
try {
@ -141,6 +145,8 @@ class Linux_driver : public Nic::Driver
_rx_thread.start();
}
void link_state_changed() { _notify.link_state_changed(); }
/***************************
** Nic::Driver interface **
@ -148,6 +154,12 @@ class Linux_driver : public Nic::Driver
Nic::Mac_address mac_address() { return _mac_addr; }
bool link_state()
{
/* XXX return always true for now */
return true;
}
void tx(char const *packet, Genode::size_t size)
{
int ret;
@ -200,9 +212,10 @@ int main(int, char **)
*/
struct Linux_driver_factory : Nic::Driver_factory
{
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc)
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc,
Nic::Driver_notification &notify)
{
return new (env()->heap()) Linux_driver(alloc);
return new (env()->heap()) Linux_driver(alloc, notify);
}
void destroy(Nic::Driver *driver)

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>