mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-16 06:08:16 +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
@ -32,29 +32,32 @@ namespace Ipxe {
|
||||
|
||||
static Driver *instance;
|
||||
|
||||
static void dde_rx_handler(unsigned if_index,
|
||||
const char *packet,
|
||||
unsigned packet_len)
|
||||
private:
|
||||
|
||||
Nic::Mac_address _mac_addr;
|
||||
Nic::Rx_buffer_alloc &_alloc;
|
||||
Nic::Driver_notification &_notify;
|
||||
|
||||
static void _rx_callback(unsigned if_index,
|
||||
const char *packet,
|
||||
unsigned packet_len)
|
||||
{
|
||||
instance->rx_handler(packet, packet_len);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Nic::Mac_address _mac_addr;
|
||||
Nic::Rx_buffer_alloc &_alloc;
|
||||
static void _link_callback() { instance->link_state_changed(); }
|
||||
|
||||
public:
|
||||
|
||||
Driver(Nic::Rx_buffer_alloc &alloc)
|
||||
: _alloc(alloc)
|
||||
Driver(Nic::Rx_buffer_alloc &alloc, Nic::Driver_notification ¬ify)
|
||||
: _alloc(alloc), _notify(notify)
|
||||
{
|
||||
PINF("--- init iPXE NIC");
|
||||
int cnt = dde_ipxe_nic_init();
|
||||
PINF(" number of devices: %d", cnt);
|
||||
|
||||
PINF("--- init rx_callbacks");
|
||||
dde_ipxe_nic_register_rx_callback(dde_rx_handler);
|
||||
PINF("--- init callbacks");
|
||||
dde_ipxe_nic_register_callbacks(_rx_callback, _link_callback);
|
||||
|
||||
dde_ipxe_nic_get_mac_addr(1, _mac_addr.addr);
|
||||
PINF("--- get MAC address %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
@ -70,16 +73,23 @@ namespace Ipxe {
|
||||
Genode::memcpy(buffer, packet, packet_len);
|
||||
_alloc.submit();
|
||||
} catch (...) {
|
||||
PDBG("failed to process received packet");
|
||||
PDBG("failed to process received packet");
|
||||
}
|
||||
}
|
||||
|
||||
void link_state_changed() { _notify.link_state_changed(); }
|
||||
|
||||
|
||||
/***************************
|
||||
** Nic::Driver interface **
|
||||
***************************/
|
||||
|
||||
Nic::Mac_address mac_address() { return _mac_addr; }
|
||||
Nic::Mac_address mac_address() override { return _mac_addr; }
|
||||
|
||||
bool link_state() override
|
||||
{
|
||||
return dde_ipxe_nic_link_state(1);
|
||||
}
|
||||
|
||||
void tx(char const *packet, Genode::size_t size)
|
||||
{
|
||||
@ -87,7 +97,6 @@ namespace Ipxe {
|
||||
PWRN("Sending packet failed!");
|
||||
}
|
||||
|
||||
|
||||
/******************************
|
||||
** Irq_activation interface **
|
||||
******************************/
|
||||
@ -97,9 +106,10 @@ namespace Ipxe {
|
||||
|
||||
class Driver_factory : public Nic::Driver_factory
|
||||
{
|
||||
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc)
|
||||
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc,
|
||||
Nic::Driver_notification ¬ify)
|
||||
{
|
||||
Driver::instance = new (Genode::env()->heap()) Ipxe::Driver(alloc);
|
||||
Driver::instance = new (Genode::env()->heap()) Ipxe::Driver(alloc, notify);
|
||||
return Driver::instance;
|
||||
}
|
||||
|
||||
|
@ -36,32 +36,35 @@ namespace Ipxe {
|
||||
|
||||
static Driver *instance;
|
||||
|
||||
static void dde_rx_handler(unsigned if_index,
|
||||
const char *packet,
|
||||
unsigned packet_len)
|
||||
private:
|
||||
|
||||
Nic::Mac_address _mac_addr;
|
||||
Nic::Rx_buffer_alloc &_alloc;
|
||||
Nic::Driver_notification &_notify;
|
||||
|
||||
Timer::Connection _timer;
|
||||
Nic::Measurement _stat;
|
||||
|
||||
static void _rx_callback(unsigned if_index,
|
||||
const char *packet,
|
||||
unsigned packet_len)
|
||||
{
|
||||
instance->rx_handler_stat(packet, packet_len);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Nic::Mac_address _mac_addr;
|
||||
Nic::Rx_buffer_alloc &_alloc;
|
||||
|
||||
Timer::Connection _timer;
|
||||
Nic::Measurement _stat;
|
||||
static void _link_callback() { instance->link_state_changed(); }
|
||||
|
||||
public:
|
||||
|
||||
Driver(Nic::Rx_buffer_alloc &alloc)
|
||||
: _alloc(alloc), _stat(_timer)
|
||||
Driver(Nic::Rx_buffer_alloc &alloc, Nic::Driver_notification ¬ify)
|
||||
: _alloc(alloc), _notify(notify), _stat(_timer)
|
||||
{
|
||||
PINF("--- init iPXE NIC");
|
||||
int cnt = dde_ipxe_nic_init();
|
||||
PINF(" number of devices: %d", cnt);
|
||||
|
||||
PINF("--- init rx_callbacks");
|
||||
dde_ipxe_nic_register_rx_callback(dde_rx_handler);
|
||||
PINF("--- init callbacks");
|
||||
dde_ipxe_nic_register_callbacks(_rx_callback, _link_callback);
|
||||
|
||||
dde_ipxe_nic_get_mac_addr(1, _mac_addr.addr);
|
||||
PINF("--- get MAC address %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
@ -90,6 +93,8 @@ namespace Ipxe {
|
||||
_alloc.submit();
|
||||
}
|
||||
|
||||
void link_state_changed() { _notify.link_state_changed(); }
|
||||
|
||||
|
||||
/***************************
|
||||
** Nic::Driver interface **
|
||||
@ -97,6 +102,11 @@ namespace Ipxe {
|
||||
|
||||
Nic::Mac_address mac_address() { return _mac_addr; }
|
||||
|
||||
bool link_state() override
|
||||
{
|
||||
return dde_ipxe_nic_link_state(1);
|
||||
}
|
||||
|
||||
void tx(char const *packet, Genode::size_t size)
|
||||
{
|
||||
if (dde_ipxe_nic_tx(1, packet, size))
|
||||
@ -112,9 +122,9 @@ namespace Ipxe {
|
||||
|
||||
class Driver_factory : public Nic::Driver_factory
|
||||
{
|
||||
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc)
|
||||
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc, Nic::Driver_notification ¬ify)
|
||||
{
|
||||
Driver::instance = new (Genode::env()->heap()) Ipxe::Driver(alloc);
|
||||
Driver::instance = new (Genode::env()->heap()) Ipxe::Driver(alloc, notify);
|
||||
return Driver::instance;
|
||||
}
|
||||
|
||||
|
@ -48,9 +48,15 @@ static struct dde_kit_sem *bh_sema;
|
||||
static struct net_device *net_dev;
|
||||
|
||||
/**
|
||||
* RX callback function pointer
|
||||
* Link-state change detected
|
||||
*/
|
||||
static dde_ipxe_nic_rx_cb rx_callback;
|
||||
static int link_state_changed;
|
||||
|
||||
/**
|
||||
* Callback function pointers
|
||||
*/
|
||||
static dde_ipxe_nic_link_cb link_callback;
|
||||
static dde_ipxe_nic_rx_cb rx_callback;
|
||||
|
||||
/**
|
||||
* Known iPXE driver structures (located in the driver binaries)
|
||||
@ -71,7 +77,6 @@ static struct pci_driver *pci_drivers[] = {
|
||||
&pcnet32_driver
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update BARs of PCI device
|
||||
*/
|
||||
@ -201,9 +206,15 @@ static void irq_handler(void *p)
|
||||
{
|
||||
ENTER;
|
||||
|
||||
/* check for the link-state to change on each interrupt */
|
||||
int link_ok = netdev_link_ok(net_dev);
|
||||
|
||||
/* poll the device for packets and also link-state changes */
|
||||
netdev_poll(net_dev);
|
||||
dde_kit_sem_up(bh_sema);
|
||||
|
||||
link_state_changed = (link_ok != netdev_link_ok(net_dev));
|
||||
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
@ -220,6 +231,15 @@ static void bh_handler(void *p)
|
||||
|
||||
ENTER;
|
||||
|
||||
/* report link-state changes */
|
||||
if (link_state_changed) {
|
||||
LEAVE;
|
||||
if (link_callback)
|
||||
link_callback();
|
||||
ENTER;
|
||||
link_state_changed = 0;
|
||||
}
|
||||
|
||||
struct io_buffer *iobuf;
|
||||
while ((iobuf = netdev_rx_dequeue(net_dev))) {
|
||||
LEAVE;
|
||||
@ -238,15 +258,30 @@ static void bh_handler(void *p)
|
||||
** API implementation **
|
||||
************************/
|
||||
|
||||
dde_ipxe_nic_rx_cb dde_ipxe_nic_register_rx_callback(dde_ipxe_nic_rx_cb cb)
|
||||
void dde_ipxe_nic_register_callbacks(dde_ipxe_nic_rx_cb rx_cb,
|
||||
dde_ipxe_nic_link_cb link_cb)
|
||||
{
|
||||
ENTER;
|
||||
|
||||
dde_ipxe_nic_rx_cb old = rx_callback;
|
||||
rx_callback = cb;
|
||||
rx_callback = rx_cb;
|
||||
link_callback = link_cb;
|
||||
|
||||
LEAVE;
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
int dde_ipxe_nic_link_state(unsigned if_index)
|
||||
{
|
||||
if (if_index != 1)
|
||||
return -1;
|
||||
|
||||
ENTER;
|
||||
|
||||
int link_state = netdev_link_ok(net_dev);
|
||||
|
||||
LEAVE;
|
||||
|
||||
return link_state;
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user