mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-16 14:18:27 +00:00
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:
committed by
Christian Helmuth
parent
e4f6fca355
commit
dd47129bef
@ -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 ¬ify)
|
||||
:
|
||||
_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 */
|
||||
|
@ -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 ¬ify)
|
||||
{
|
||||
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)
|
||||
|
@ -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 ¬ify)
|
||||
:
|
||||
_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 ¬ify)
|
||||
{
|
||||
return new (env()->heap()) Linux_driver(alloc);
|
||||
return new (env()->heap()) Linux_driver(alloc, notify);
|
||||
}
|
||||
|
||||
void destroy(Nic::Driver *driver)
|
||||
|
@ -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();
|
||||
|
@ -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 **
|
||||
******************************/
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 **
|
||||
|
@ -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)
|
||||
{ }
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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>
|
||||
|
Reference in New Issue
Block a user