mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +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:
parent
e4f6fca355
commit
dd47129bef
@ -15,6 +15,11 @@
|
||||
#ifndef _DDE_IPXE__NIC_H_
|
||||
#define _DDE_IPXE__NIC_H_
|
||||
|
||||
/**
|
||||
* Link-state change callback
|
||||
*/
|
||||
typedef void (*dde_ipxe_nic_link_cb)(void);
|
||||
|
||||
/**
|
||||
* Packet reception callback
|
||||
*
|
||||
@ -27,14 +32,14 @@ typedef void (*dde_ipxe_nic_rx_cb)(unsigned if_index, const char *packet, unsign
|
||||
/**
|
||||
* Register packet reception callback
|
||||
*
|
||||
* \param cb new callback function
|
||||
*
|
||||
* \return old callback function pointer
|
||||
* \param rx_cb packet-reception callback function
|
||||
* \param link_cb link-state change callback function
|
||||
*
|
||||
* This registers a function pointer as rx callback. Incoming ethernet packets
|
||||
* are passed to this function.
|
||||
*/
|
||||
extern dde_ipxe_nic_rx_cb dde_ipxe_nic_register_rx_callback(dde_ipxe_nic_rx_cb cb);
|
||||
extern void dde_ipxe_nic_register_callbacks(dde_ipxe_nic_rx_cb rx_cb,
|
||||
dde_ipxe_nic_link_cb link_cb);
|
||||
|
||||
/**
|
||||
* Send packet
|
||||
@ -57,6 +62,15 @@ extern int dde_ipxe_nic_tx(unsigned if_index, const char *packet, unsigned packe
|
||||
*/
|
||||
extern int dde_ipxe_nic_get_mac_addr(unsigned if_index, char *out_mac_addr);
|
||||
|
||||
/**
|
||||
* Get current link-state of device
|
||||
*
|
||||
* \param if_index index of the receiving network interface
|
||||
*
|
||||
* \return 1 if link is up, 0 if no link is detected
|
||||
*/
|
||||
extern int dde_ipxe_nic_link_state(unsigned if_index);
|
||||
|
||||
/**
|
||||
* Initialize network sub-system
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -80,6 +80,11 @@ namespace Nic {
|
||||
*/
|
||||
virtual Mac_address mac_address() = 0;
|
||||
|
||||
/**
|
||||
* Return current link-state (true if link detected)
|
||||
*/
|
||||
virtual bool link_state() = 0;
|
||||
|
||||
/**
|
||||
* Set session belonging to this driver
|
||||
*/
|
||||
@ -130,6 +135,8 @@ namespace Nic {
|
||||
bool _tx_alloc; /* get next packet from client or use _tx_packet */
|
||||
Packet_descriptor _tx_packet; /* saved packet in case of driver errors */
|
||||
|
||||
Signal_context_capability _link_state_sigh;
|
||||
|
||||
void _send_packet_avail_signal() {
|
||||
Signal_transmitter(_tx.sigh_packet_avail()).submit(); }
|
||||
|
||||
@ -256,8 +263,23 @@ namespace Nic {
|
||||
_tx_alloc(true)
|
||||
{ _device->session(this); }
|
||||
|
||||
/**
|
||||
* Link state changed (called from driver)
|
||||
*/
|
||||
void link_state_changed()
|
||||
{
|
||||
if (_link_state_sigh.valid())
|
||||
Genode::Signal_transmitter(_link_state_sigh).submit();
|
||||
}
|
||||
|
||||
Mac_address mac_address() { return _device->mac_address(); }
|
||||
|
||||
bool link_state() override {
|
||||
return _device->link_state(); }
|
||||
|
||||
void link_state_sigh(Genode::Signal_context_capability sigh) {
|
||||
_link_state_sigh = sigh; }
|
||||
|
||||
/**
|
||||
* Send packet to client (called form driver)
|
||||
*/
|
||||
|
@ -144,6 +144,7 @@ class Nic_device : public Nic::Device
|
||||
struct net_device *_ndev; /* Linux-net device */
|
||||
fixup_t _tx_fixup;
|
||||
bool const _burst;
|
||||
bool _has_link { false };
|
||||
|
||||
public:
|
||||
|
||||
@ -177,11 +178,29 @@ class Nic_device : public Nic::Device
|
||||
static Nic_device *add(struct net_device *ndev) {
|
||||
return new (Genode::env()->heap()) Nic_device(ndev); }
|
||||
|
||||
/**
|
||||
* Report link state
|
||||
*/
|
||||
void link_state(bool link)
|
||||
{
|
||||
/* only report changes of the link state */
|
||||
if (link == _has_link)
|
||||
return;
|
||||
|
||||
_has_link = link;
|
||||
|
||||
if (_session)
|
||||
_session->link_state_changed();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************
|
||||
** Device interface **
|
||||
**********************/
|
||||
|
||||
bool link_state() override { return _has_link; }
|
||||
|
||||
/**
|
||||
* Submit packet to driver
|
||||
*/
|
||||
@ -344,12 +363,16 @@ int netif_carrier_ok(const struct net_device *dev)
|
||||
void netif_carrier_on(struct net_device *dev)
|
||||
{
|
||||
dev->state &= ~(1 << __LINK_STATE_NOCARRIER);
|
||||
if (_nic)
|
||||
_nic->link_state(true);
|
||||
}
|
||||
|
||||
|
||||
void netif_carrier_off(struct net_device *dev)
|
||||
{
|
||||
dev->state |= 1 << __LINK_STATE_NOCARRIER;
|
||||
if (_nic)
|
||||
_nic->link_state(false);
|
||||
}
|
||||
|
||||
#ifdef GENODE_NET_STAT
|
||||
|
@ -39,13 +39,16 @@ namespace Nic {
|
||||
|
||||
|
||||
class Nic::Session_component : public Genode::Allocator_avl,
|
||||
public Session_rpc_object, public Rx_buffer_alloc
|
||||
public Session_rpc_object, public Rx_buffer_alloc,
|
||||
public Driver_notification
|
||||
{
|
||||
private:
|
||||
|
||||
Driver_factory &_driver_factory;
|
||||
Driver &_driver;
|
||||
|
||||
Genode::Signal_context_capability _link_state_sigh;
|
||||
|
||||
/* rx packet descriptor */
|
||||
Genode::Packet_descriptor _curr_rx_packet;
|
||||
|
||||
@ -126,7 +129,7 @@ class Nic::Session_component : public Genode::Allocator_avl,
|
||||
Genode::env()->ram_session()->alloc(rx_buf_size),
|
||||
static_cast<Genode::Range_allocator *>(this), ep),
|
||||
_driver_factory(driver_factory),
|
||||
_driver(*driver_factory.create(*this)),
|
||||
_driver(*driver_factory.create(*this, *this)),
|
||||
_tx_thread(_tx.sink(), _driver)
|
||||
{ }
|
||||
|
||||
@ -138,12 +141,21 @@ class Nic::Session_component : public Genode::Allocator_avl,
|
||||
_driver_factory.destroy(&_driver);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
** Driver-notification interface **
|
||||
***********************************/
|
||||
|
||||
void link_state_changed() override
|
||||
{
|
||||
if (_link_state_sigh.valid())
|
||||
Genode::Signal_transmitter(_link_state_sigh).submit();
|
||||
}
|
||||
|
||||
/*******************************
|
||||
** Rx_buffer_alloc interface **
|
||||
*******************************/
|
||||
|
||||
void *alloc(Genode::size_t size)
|
||||
void *alloc(Genode::size_t size) override
|
||||
{
|
||||
/* assign rx packet descriptor */
|
||||
_curr_rx_packet = _rx.source()->alloc_packet(size);
|
||||
@ -151,7 +163,7 @@ class Nic::Session_component : public Genode::Allocator_avl,
|
||||
return _rx.source()->packet_content(_curr_rx_packet);
|
||||
}
|
||||
|
||||
void submit()
|
||||
void submit() override
|
||||
{
|
||||
/* check for acknowledgements from the client */
|
||||
while (_rx.source()->ack_avail()) {
|
||||
@ -175,8 +187,14 @@ class Nic::Session_component : public Genode::Allocator_avl,
|
||||
****************************/
|
||||
|
||||
Mac_address mac_address() { return _driver.mac_address(); }
|
||||
bool link_state() { return _driver.link_state(); }
|
||||
Tx::Sink* tx_sink() { return _tx.sink(); }
|
||||
Rx::Source* rx_source() { return _rx.source(); }
|
||||
|
||||
void link_state_sigh(Genode::Signal_context_capability sigh) override
|
||||
{
|
||||
_link_state_sigh = sigh;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -22,6 +22,7 @@ namespace Nic {
|
||||
struct Rx_buffer_alloc;
|
||||
struct Driver;
|
||||
struct Driver_factory;
|
||||
struct Driver_notification;
|
||||
}
|
||||
|
||||
|
||||
@ -42,6 +43,12 @@ struct Nic::Rx_buffer_alloc
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Interface for driver-to-component notifications
|
||||
*/
|
||||
struct Nic::Driver_notification { virtual void link_state_changed() = 0; };
|
||||
|
||||
|
||||
/**
|
||||
* Interface to be implemented by the device-specific driver code
|
||||
*/
|
||||
@ -52,6 +59,11 @@ struct Nic::Driver : Genode::Irq_handler
|
||||
*/
|
||||
virtual Mac_address mac_address() = 0;
|
||||
|
||||
/**
|
||||
* Return link state (true if link detected)
|
||||
*/
|
||||
virtual bool link_state() = 0;
|
||||
|
||||
/**
|
||||
* Transmit packet
|
||||
*
|
||||
@ -83,8 +95,10 @@ struct Nic::Driver_factory
|
||||
*
|
||||
* \param rx_buffer_alloc buffer allocator used for storing incoming
|
||||
* packets
|
||||
* \param notifier callback for notifications
|
||||
*/
|
||||
virtual Driver *create(Rx_buffer_alloc &rx_buffer_alloc) = 0;
|
||||
virtual Driver *create(Rx_buffer_alloc &rx_buffer_alloc,
|
||||
Driver_notification ¬ify) = 0;
|
||||
|
||||
/**
|
||||
* Destroy driver
|
||||
|
@ -56,6 +56,13 @@ class Nic::Session_client : public Genode::Rpc_client<Session>
|
||||
Rx *rx_channel() { return &_rx; }
|
||||
Tx::Source *tx() { return _tx.source(); }
|
||||
Rx::Sink *rx() { return _rx.sink(); }
|
||||
|
||||
void link_state_sigh(Genode::Signal_context_capability sigh) override
|
||||
{
|
||||
call<Rpc_link_state_sigh>(sigh);
|
||||
}
|
||||
|
||||
bool link_state() override { return call<Rpc_link_state>(); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__NIC_SESSION__CLIENT_H_ */
|
||||
|
@ -93,6 +93,15 @@ struct Nic::Session : Genode::Session
|
||||
*/
|
||||
virtual Rx::Sink *rx() { return 0; }
|
||||
|
||||
/**
|
||||
* Request current link state of network adapter (true means link detected)
|
||||
*/
|
||||
virtual bool link_state() = 0;
|
||||
|
||||
/**
|
||||
* Register signal handler for link state changes
|
||||
*/
|
||||
virtual void link_state_sigh(Genode::Signal_context_capability sigh) = 0;
|
||||
|
||||
/*******************
|
||||
** RPC interface **
|
||||
@ -101,8 +110,12 @@ struct Nic::Session : Genode::Session
|
||||
GENODE_RPC(Rpc_mac_address, Mac_address, mac_address);
|
||||
GENODE_RPC(Rpc_tx_cap, Genode::Capability<Tx>, _tx_cap);
|
||||
GENODE_RPC(Rpc_rx_cap, Genode::Capability<Rx>, _rx_cap);
|
||||
GENODE_RPC(Rpc_link_state, bool, link_state);
|
||||
GENODE_RPC(Rpc_link_state_sigh, void, link_state_sigh,
|
||||
Genode::Signal_context_capability);
|
||||
|
||||
GENODE_RPC_INTERFACE(Rpc_mac_address, Rpc_tx_cap, Rpc_rx_cap);
|
||||
GENODE_RPC_INTERFACE(Rpc_mac_address, Rpc_link_state,
|
||||
Rpc_link_state_sigh, Rpc_tx_cap, Rpc_rx_cap);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__NIC_SESSION__NIC_SESSION_H_ */
|
||||
|
@ -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>
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
@ -87,8 +87,9 @@ class Nic_driver : public Tuntap_device,
|
||||
{
|
||||
private:
|
||||
|
||||
Nic::Mac_address _mac_addr {{ 0x02, 0x00, 0x00, 0x00, 0x00, 0x01 }};
|
||||
Nic::Rx_buffer_alloc &_alloc;
|
||||
Nic::Mac_address _mac_addr {{ 0x02, 0x00, 0x00, 0x00, 0x00, 0x01 }};
|
||||
Nic::Rx_buffer_alloc &_alloc;
|
||||
Nic::Driver_notification &_notify;
|
||||
|
||||
char const *_packet;
|
||||
|
||||
@ -101,10 +102,9 @@ class Nic_driver : public Tuntap_device,
|
||||
|
||||
public:
|
||||
|
||||
Nic_driver(Nic::Rx_buffer_alloc &alloc)
|
||||
Nic_driver(Nic::Rx_buffer_alloc &alloc, Nic::Driver_notification ¬ify)
|
||||
:
|
||||
_alloc(alloc),
|
||||
_packet(0)
|
||||
_alloc(alloc), _notify(notify), _packet(0)
|
||||
{
|
||||
if (pipe(_pipefd)) {
|
||||
PERR("could not create pipe");
|
||||
@ -114,6 +114,7 @@ class Nic_driver : public Tuntap_device,
|
||||
|
||||
~Nic_driver() { PDBG("should probably be implemented"); }
|
||||
|
||||
void link_state_changed() { _notify.link_state_changed(); }
|
||||
|
||||
/***************************
|
||||
** Nic::Driver interface **
|
||||
@ -121,6 +122,12 @@ class Nic_driver : public Tuntap_device,
|
||||
|
||||
Nic::Mac_address mac_address() { return _mac_addr; }
|
||||
|
||||
bool link_state()
|
||||
{
|
||||
/* XXX always return true for now */
|
||||
return true;
|
||||
}
|
||||
|
||||
void tx(char const *packet, Genode::size_t size)
|
||||
{
|
||||
PDBGV("packet:0x%p size:%zu", packet, size);
|
||||
@ -185,11 +192,12 @@ struct Main
|
||||
Nic_driver *drv { 0 };
|
||||
Openvpn_thread *openvpn { 0 };
|
||||
|
||||
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc)
|
||||
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc,
|
||||
Nic::Driver_notification ¬ify)
|
||||
{
|
||||
/* there can be only one */
|
||||
if (!drv) {
|
||||
drv = new (Genode::env()->heap()) Nic_driver(alloc);
|
||||
drv = new (Genode::env()->heap()) Nic_driver(alloc, notify);
|
||||
|
||||
/**
|
||||
* Setting the pointer in this manner is quite hackish but it has
|
||||
|
Loading…
x
Reference in New Issue
Block a user