lxip: support link_state handling

* (re-)configure address when link state goes up
* propagate link state to Linux code

issue #5471
This commit is contained in:
Sebastian Sumpf 2025-02-27 09:59:09 +01:00 committed by Norman Feske
parent 6a0c9f50ea
commit f0a75b75fb
10 changed files with 163 additions and 61 deletions

View File

@ -365,6 +365,12 @@ int netdev_register_kobject(struct net_device * ndev)
}
void netdev_unregister_kobject(struct net_device * ndev)
{
lx_emul_trace(__func__);
}
#include <linux/sched/signal.h>
int send_sig(int sig,struct task_struct * p,int priv)

View File

@ -42,12 +42,16 @@ struct Main
: env(env), io_progress(io_progress)
{ }
void _io_progress()
{
if (io_progress && io_progress->callback)
io_progress->callback(io_progress->data);
}
void handle_schedule()
{
Lx_kit::env().scheduler.execute();
if (io_progress && io_progress->callback)
io_progress->callback(io_progress->data);
_io_progress();
}
void handle_nic_client()
@ -62,13 +66,13 @@ struct Main
lx_emul_task_unblock(lx_nic_client_rx_task());
Lx_kit::env().scheduler.execute();
if (io_progress && io_progress->callback)
io_progress->callback(io_progress->data);
_io_progress();
}
void handle_link_state()
{
Genode::error("handle_link_state: not implemented");
socket_update_link_state();
_io_progress();
}
void init()

View File

@ -25,12 +25,38 @@ static struct genode_nic_client *dev_nic_client(struct net_device *dev)
}
static struct net_device *dev_net_device(void)
{
return dev_get_by_name(&init_net, "eth0");
}
static int net_open(struct net_device *dev)
{
return 0;
}
bool lx_nic_client_link_state(void)
{
return netif_carrier_ok(dev_net_device());
}
bool lx_nic_client_update_link_state(void)
{
struct net_device *dev = dev_net_device();
bool state = genode_nic_client_link_state(dev_nic_client(dev));
if (state == false && netif_carrier_ok(dev))
netif_carrier_off(dev);
if (state == true && !netif_carrier_ok(dev))
netif_carrier_on(dev);
return state;
}
struct genode_nic_client_tx_packet_context
{
struct sk_buff *skb;
@ -82,7 +108,7 @@ static int driver_net_xmit(struct sk_buff *skb, struct net_device *dev)
stats->tx_packets++;
stats->tx_bytes += skb->len;
lx_nic_client_schedule_peer();
socket_schedule_peer();
return NETDEV_TX_OK;
}
@ -155,7 +181,7 @@ static int rx_task_function(void *arg)
&ctx)) {
progress = true; }
if (progress) lx_nic_client_schedule_peer();
if (progress) socket_schedule_peer();
}
return 0;
@ -192,6 +218,14 @@ static int __init virtio_net_driver_init(void)
goto out_nic;
}
if (dev_net_device() != dev) {
printk("error: net device name is \"%s\", but must be \"eth0\"\n",
dev->name);
BUG();
}
lx_nic_client_update_link_state();
/* create RX task */
pid = kernel_thread(rx_task_function, dev, "rx_task", CLONE_FS | CLONE_FILES);

View File

@ -18,9 +18,17 @@
#ifdef __cplusplus
extern "C" {
#endif
/* net_driver.c */
struct task_struct;
struct task_struct *lx_nic_client_rx_task(void);
void lx_nic_client_schedule_peer(void);
bool lx_nic_client_link_state(void);
bool lx_nic_client_update_link_state(void);
/* socket.cc */
void socket_schedule_peer(void);
void socket_config_address(void);
void socket_unconfigure_address(void);
void socket_update_link_state(void);
#ifdef __cplusplus
}
#endif

View File

@ -37,7 +37,10 @@ using Socket_queue = Fifo<Lx_call>;
struct Statics
{
genode_socket_wakeup *wakeup_remote;
genode_socket_wakeup *wakeup_remote { nullptr };
genode_socket_config config{ };
bool address_configured { false };
bool address_valid { false };
};
@ -433,6 +436,39 @@ struct Lx_sock_release : Lx_call
};
struct Lx_nic_link_state : Lx_call
{
bool state { false };
Lx_nic_link_state(genode_socket_handle &handle) : Lx_call(handle)
{
schedule();
}
void execute() override
{
state = lx_nic_client_link_state();
finished = true;
}
};
struct Lx_nic_update_link_state : Lx_call
{
bool state { false };
Lx_nic_update_link_state(genode_socket_handle &handle) : Lx_call(handle)
{
schedule();
}
void execute() override
{
state = lx_nic_client_update_link_state();
finished = true;
}
};
/*
* Dispatch socket calls in Linux task
*/
@ -485,18 +521,38 @@ static void _destroy_handle(genode_socket_handle *handle)
}
static genode_socket_handle _disposable_handle()
{
return {
.sock = nullptr,
.task = lx_socket_dispatch_root(),
.queue = static_cast<Socket_queue *>(lx_socket_dispatch_queue()),
};
}
/*
* Genode socket C-API
*/
void genode_socket_config_address(struct genode_socket_config *config)
{
genode_socket_handle handle = {
.task = lx_socket_dispatch_root(),
.queue = static_cast<Socket_queue *>(lx_socket_dispatch_queue()),
};
Lx_address addr { handle, config };
statics().config = *config;
statics().address_valid = true;
genode_socket_handle handle { _disposable_handle() };
Lx_nic_link_state link { handle };
if (link.state) {
/* local implementation here */
statics().address_configured = false;
socket_config_address();
}
/* wait for link state change to trigger ip configuration */
while (!statics().address_configured) {
genode_socket_wakeup_remote();
genode_socket_wait_for_progress();
}
}
@ -505,9 +561,6 @@ extern "C" unsigned int ic_netmask;
extern "C" unsigned int ic_gateway;
extern "C" unsigned int ic_nameservers[1];
//XXX: implement link state
bool ic_link_state = true;
void genode_socket_config_info(struct genode_socket_info *info)
{
if (!info) return;
@ -515,16 +568,16 @@ void genode_socket_config_info(struct genode_socket_info *info)
info->netmask = ic_netmask;
info->gateway = ic_gateway;
info->nameserver = ic_nameservers[0];
info->link_state = ic_link_state;
genode_socket_handle handle { _disposable_handle() };
Lx_nic_link_state link { handle };
info->link_state = link.state;
}
void genode_socket_configure_mtu(unsigned mtu)
{
genode_socket_handle handle = {
.task = lx_socket_dispatch_root(),
.queue = static_cast<Socket_queue *>(lx_socket_dispatch_queue()),
};
genode_socket_handle handle { _disposable_handle() };
Lx_mtu addr { handle, mtu };
}
@ -708,11 +761,43 @@ void genode_socket_register_wakeup(struct genode_socket_wakeup *remote)
/*
* Called by net_driver.c
* local C-interface
*/
void lx_nic_client_schedule_peer(void)
void socket_schedule_peer(void)
{
if (statics().wakeup_remote && statics().wakeup_remote->callback) {
statics().wakeup_remote->callback(statics().wakeup_remote->data);
}
}
void socket_config_address(void)
{
if (statics().address_configured || statics().address_valid == false)
return;
genode_socket_handle handle { _disposable_handle() };
Lx_address addr { handle, &statics().config };
statics().address_configured = true;
}
void socket_unconfigure_address(void)
{
statics().address_configured = false;
}
void socket_update_link_state(void)
{
genode_socket_handle handle { _disposable_handle() };
Lx_nic_update_link_state link { handle };
if (link.state)
socket_config_address();
else
statics().address_configured = false;
}

View File

@ -580,13 +580,6 @@ void * mtree_load(struct maple_tree * mt,unsigned long index)
}
extern void netdev_unregister_kobject(struct net_device * ndev);
void netdev_unregister_kobject(struct net_device * ndev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/pipe_fs_i.h>
const struct pipe_buf_operations nosteal_pipe_buf_ops;

View File

@ -471,13 +471,6 @@ void * mtree_load(struct maple_tree * mt,unsigned long index)
}
extern void netdev_unregister_kobject(struct net_device * ndev);
void netdev_unregister_kobject(struct net_device * ndev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/pipe_fs_i.h>
const struct pipe_buf_operations nosteal_pipe_buf_ops;

View File

@ -588,13 +588,6 @@ void * mtree_load(struct maple_tree * mt,unsigned long index)
}
extern void netdev_unregister_kobject(struct net_device * ndev);
void netdev_unregister_kobject(struct net_device * ndev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/pipe_fs_i.h>
const struct pipe_buf_operations nosteal_pipe_buf_ops;

View File

@ -543,13 +543,6 @@ void * mtree_load(struct maple_tree * mt,unsigned long index)
}
extern void netdev_unregister_kobject(struct net_device * ndev);
void netdev_unregister_kobject(struct net_device * ndev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/pipe_fs_i.h>
const struct pipe_buf_operations nosteal_pipe_buf_ops;

View File

@ -548,13 +548,6 @@ void * mtree_load(struct maple_tree * mt,unsigned long index)
}
extern void netdev_unregister_kobject(struct net_device * ndev);
void netdev_unregister_kobject(struct net_device * ndev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/pipe_fs_i.h>
const struct pipe_buf_operations nosteal_pipe_buf_ops;