WiP for MxIP.

This commit is contained in:
Michael Mueller
2025-06-20 17:42:30 +02:00
parent 90761ae232
commit 95e5585752
5 changed files with 111 additions and 60 deletions

View File

@@ -40,8 +40,8 @@ extern "C" {
#define LWIP_TCP_TIMESTAMPS 0 #define LWIP_TCP_TIMESTAMPS 0
#define TCP_LISTEN_BACKLOG 255 #define TCP_LISTEN_BACKLOG 255
#define TCP_MSS 1460 #define TCP_MSS 1460
#define TCP_WND (80 * TCP_MSS) #define TCP_WND (46 * TCP_MSS)
#define TCP_SND_BUF (80 * TCP_MSS) #define TCP_SND_BUF (46 * TCP_MSS)
#define LWIP_WND_SCALE 3 #define LWIP_WND_SCALE 3
#define TCP_RCV_SCALE 2 #define TCP_RCV_SCALE 2
#define TCP_SND_QUEUELEN ((512 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) #define TCP_SND_QUEUELEN ((512 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS))

View File

@@ -0,0 +1,8 @@
#pragma once
#include <mx/synchronization/lock_guard.h>
#include <mx/synchronization/optimistic_lock.h>
namespace Mxip {
extern mx::synchronization::OptimisticLock mxip_lock;
}

View File

@@ -28,6 +28,9 @@
#include "base/allocator.h" #include "base/allocator.h"
#include "mx/memory/global_heap.h" #include "mx/memory/global_heap.h"
#include "mx/system/environment.h"
#include "os/packet_stream.h"
#include "trace/timestamp.h"
#include <memory> #include <memory>
#if ETH_PAD_SIZE #if ETH_PAD_SIZE
#error ETH_PAD_SIZE defined but unsupported by lwip/nic_netif.h #error ETH_PAD_SIZE defined but unsupported by lwip/nic_netif.h
@@ -46,6 +49,7 @@
#include <mx/tasking/runtime.h> #include <mx/tasking/runtime.h>
#include <mx/tasking/task.h> #include <mx/tasking/task.h>
#include "mxip_lock.h"
/* EalanOS includes */ /* EalanOS includes */
#include <ealanos/memory/hamstraaja.h> #include <ealanos/memory/hamstraaja.h>
@@ -92,14 +96,20 @@ namespace Lwip {
{ {
struct pbuf_custom p { }; struct pbuf_custom p { };
Mxip::Nic_netif &netif; Mxip::Nic_netif &netif;
void *payload; void *payload;
Genode::Packet_descriptor packet;
Nic_netif_pbuf(Mxip::Nic_netif &nic, void *pl) Nic_netif_pbuf(Mxip::Nic_netif &nic, void *pl, Genode::Packet_descriptor pkt)
: netif(nic), payload(pl) : netif(nic), payload(pl), packet(pkt)
{ {
p.custom_free_function = nic_netif_pbuf_free; p.custom_free_function = nic_netif_pbuf_free;
} }
}; };
struct Rx_task_stats {
Genode::Trace::Timestamp waiting_time;
Genode::Trace::Timestamp execution_time;
};
} }
class Mxip::Nic_netif class Mxip::Nic_netif
@@ -116,7 +126,7 @@ class Mxip::Nic_netif
}; };
enum { TASK_SIZE = 128, SB_SIZE = 2 * 2048 }; enum { TASK_SIZE = 128, SB_SIZE = 2 * 2048 };
private: private:
Genode::Entrypoint _ep; Genode::Entrypoint _ep;
@@ -153,22 +163,23 @@ class Mxip::Nic_netif
bool _dhcp { false }; bool _dhcp { false };
Lwip::Rx_task_stats _rx_stats[10000100];
public: public:
void free_pbuf(Lwip::Nic_netif_pbuf &pbuf) void free_pbuf(Lwip::Nic_netif_pbuf &pbuf)
{ {
/*bool msg_once = true; bool msg_once = true;
while (!_nic.rx()->ready_to_ack()) { while (!_nic.rx()->ready_to_ack()) {
if (msg_once) //if (msg_once)
Genode::error("Nic rx acknowledgement queue congested, blocking to free pbuf"); //Genode::error("Nic rx acknowledgement queue congested, blocking to free pbuf");
msg_once = false; msg_once = false;
_ep.wait_and_dispatch_one_io_signal(); _ep.wait_and_dispatch_one_io_signal();
} }
_nic.rx()->try_ack_packet(pbuf.packet); _nic.rx()->try_ack_packet(pbuf.packet);
_wakeup_scheduler.schedule_nic_server_wakeup();*/ _wakeup_scheduler.schedule_nic_server_wakeup();
_packet_alloc->free(pbuf.payload); //_packet_alloc->free(pbuf.payload);
_task_alloc->free(&pbuf);//destroy(_pbuf_alloc, &pbuf); _packet_alloc->free(&pbuf);//destroy(_pbuf_alloc, &pbuf);
} }
/************************* /*************************
@@ -401,6 +412,14 @@ class Mxip::Nic_netif
_nic.rx()->wakeup(); _nic.rx()->wakeup();
_nic.tx()->wakeup(); _nic.tx()->wakeup();
} }
void print_stats()
{
for (int id = 0; id < 1000000; id++) {
Genode::log("rx: id =", id, " wait=", _rx_stats[id].waiting_time, " etime: ", _rx_stats[id].execution_time);
}
}
}; };
/************************** /**************************
@@ -411,21 +430,23 @@ class Mxip::Receive_task : public mx::tasking::TaskInterface
{ {
public: public:
Receive_task(void *payload, size_t len, struct Lwip::netif &netif, Mxip::Nic_netif &net) Receive_task(void *payload, size_t len, struct Lwip::netif &netif, Mxip::Nic_netif &net, Genode::Trace::Timestamp arrival, unsigned long id, Genode::Packet_descriptor packet)
: _netif(netif), _payload(payload), _length(len), _net(net) : _netif(netif), _payload(payload), _length(len), _net(net), _arrival(arrival), _id(id), _packet(packet)
{ {
} }
mx::tasking::TaskResult execute(std::uint16_t, std::uint16_t) override mx::tasking::TaskResult execute(std::uint16_t, std::uint16_t) override
{ {
Lwip::Nic_netif_pbuf *nic_pbuf = new (_net._task_alloc->alloc(sizeof(Lwip::Nic_netif_pbuf))) Genode::Trace::Timestamp execution = Genode::Trace::timestamp();
Lwip::Nic_netif_pbuf(_net, _payload); Lwip::Nic_netif_pbuf *nic_pbuf = new (_net._packet_alloc->alloc(sizeof(Lwip::Nic_netif_pbuf)))
Lwip::Nic_netif_pbuf(_net, _payload, _packet);
if (!nic_pbuf) { if (!nic_pbuf) {
Genode::warning("Could not allocate pbuf "); Genode::warning("Could not allocate pbuf ");
_net._task_alloc->free(this); _net._task_alloc->free(this);
return mx::tasking::TaskResult::make_null(); return mx::tasking::TaskResult::make_null();
} }
pbuf *p = pbuf_alloced_custom(PBUF_RAW, _length, PBUF_REF, &nic_pbuf->p, _payload, pbuf *p = pbuf_alloced_custom(PBUF_RAW, _length, PBUF_REF, &nic_pbuf->p, _payload,
_length); _length);
LINK_STATS_INC(link.recv); LINK_STATS_INC(link.recv);
@@ -435,14 +456,19 @@ class Mxip::Receive_task : public mx::tasking::TaskInterface
_net._task_alloc->free(this); _net._task_alloc->free(this);
return mx::tasking::TaskResult::make_null(); return mx::tasking::TaskResult::make_null();
} }
err_t rc = _netif.input(p, &_netif);
err_t rc = _netif.input(p, &_netif);
if (rc != ERR_OK) { if (rc != ERR_OK) {
Genode::error("error forwarding Nic packet to lwIP: error=", Genode::error("error forwarding Nic packet to lwIP: error=",
static_cast<std::int16_t>(rc)); static_cast<std::int16_t>(rc));
pbuf_free(p); pbuf_free(p);
} }
Genode::Trace::Timestamp processed = Genode::Trace::timestamp();
_net._rx_stats[_id].waiting_time =
((execution - _arrival) * 1000) / mx::system::Environment::get_cpu_freq();
_net._rx_stats[_id].execution_time = ((processed - execution) * 1000) / mx::system::Environment::get_cpu_freq();
_net._task_alloc->free(this); _net._task_alloc->free(this);
return mx::tasking::TaskResult::make_null(); return mx::tasking::TaskResult::make_null();
//return mx::tasking::TaskResult::make_remove(); //return mx::tasking::TaskResult::make_remove();
@@ -454,7 +480,9 @@ class Mxip::Receive_task : public mx::tasking::TaskInterface
void *_payload; void *_payload;
std::size_t _length; std::size_t _length;
Mxip::Nic_netif &_net; Mxip::Nic_netif &_net;
Genode::Trace::Timestamp _arrival;
unsigned long _id;
Genode::Packet_descriptor _packet;
}; };
class Mxip::Tx_ready_task : public mx::tasking::TaskInterface class Mxip::Tx_ready_task : public mx::tasking::TaskInterface
@@ -464,12 +492,13 @@ class Mxip::Tx_ready_task : public mx::tasking::TaskInterface
Tx_ready_task(Nic::Connection &nic, Mxip::Nic_netif &netif) : _nic(nic), _netif(netif) { } Tx_ready_task(Nic::Connection &nic, Mxip::Nic_netif &netif) : _nic(nic), _netif(netif) { }
mx::tasking::TaskResult execute(std::uint16_t, std::uint16_t) override mx::tasking::TaskResult execute(std::uint16_t, std::uint16_t) override
{ {
//GENODE_LOG_TSC(1);
auto &tx = *_nic.tx(); auto &tx = *_nic.tx();
bool progress = false; bool progress = false;
while (tx.ack_avail()) { while (tx.ack_avail()) {
tx.release_packet(tx.try_get_acked_packet()); tx.release_packet(tx.try_get_acked_packet());
_netif._tx_saturated = false; //_netif._tx_saturated = false;
progress = true; progress = true;
} }
@@ -504,6 +533,8 @@ class Mxip::Link_state_task : public mx::tasking::TaskInterface
* if the application wants to be informed of the * if the application wants to be informed of the
* link state then it should use 'set_link_callback' * link state then it should use 'set_link_callback'
*/ */
//GENODE_LOG_TSC_NAMED(1, "Link state task");
if (_nic.link_state()) { if (_nic.link_state()) {
Lwip::netif_set_link_up(&_netif); Lwip::netif_set_link_up(&_netif);
if (_dhcp) { if (_dhcp) {
@@ -520,9 +551,9 @@ class Mxip::Link_state_task : public mx::tasking::TaskInterface
Lwip::dhcp_release_and_stop(&_netif); Lwip::dhcp_release_and_stop(&_netif);
} }
} }
_nic_netif._task_alloc->free(this); //_nic_netif._task_alloc->free(this);
return mx::tasking::TaskResult::make_null(); //return mx::tasking::TaskResult::make_null();
//return mx::tasking::TaskResult::make_remove(); return mx::tasking::TaskResult::make_remove();
} }
private: private:

View File

@@ -1,62 +1,69 @@
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "mx/synchronization/optimistic_lock.h"
#include "trace/timestamp.h"
#include <cstring> #include <cstring>
#include <mxip/mxnic_netif.h> #include <mxip/mxnic_netif.h>
#include <mx/memory/global_heap.h> #include <mx/memory/global_heap.h>
#include <mx/tasking/runtime.h> #include <mx/tasking/runtime.h>
#include <base/log.h> #include <base/log.h>
mx::synchronization::OptimisticLock Mxip::mxip_lock{};
void Mxip::Nic_netif::handle_rx_packets() void Mxip::Nic_netif::handle_rx_packets()
{ {
Nic::Session::Rx::Sink *rx = _nic.rx(); Nic::Session::Rx::Sink *rx = _nic.rx();
bool progress = false; bool progress = false;
while (rx->packet_avail() && rx->ready_to_ack()) { // TODO: Reduce time spent in the loops body as it is executed hundreds of times
//GENODE_LOG_TSC(1);
while (rx->packet_avail() && rx->ready_to_ack()) {
try Genode::Trace::Timestamp arrival = Genode::Trace::timestamp();
{ try {
Nic::Packet_descriptor packet = rx->try_get_packet(); static unsigned long id = 0;
progress = true;
Nic::Packet_descriptor packet = rx->try_get_packet();
progress = true;
void *payload = _packet_alloc->alloc(sizeof(packet.size())); /*void *payload = _packet_alloc->alloc(sizeof(packet.size()));
memcpy(payload, rx->packet_content(packet), packet.size()); memcpy(payload, rx->packet_content(packet), packet.size());*/
void *payload = rx->packet_content(packet);
Mxip::Receive_task *task = new (_task_alloc->alloc(sizeof(Mxip::Receive_task))) Mxip::Receive_task(payload, packet.size(), _netif, *this); Mxip::Receive_task *task = new (_task_alloc->alloc(sizeof(Mxip::Receive_task))) Mxip::Receive_task(payload, packet.size(), _netif, *this, arrival, id++, packet);
if (task == nullptr)
//auto task = mx::tasking::runtime::new_task<Mxip::Receive_task>(1, payload, packet.size(), _netif, *this, arrival, id++, packet);
if (task == nullptr)
{
Genode::warning("Could not allocate task object.");
return;
}
task->annotate(static_cast<mx::tasking::TaskInterface::channel>(0));
mx::tasking::runtime::spawn(*task);
if (progress) {
_wakeup_scheduler.schedule_nic_server_wakeup();
}
}
catch (Genode::Exception)
{ {
Genode::warning("Could not allocate task object."); Genode::warning("Got signal without actual packet in queue");
return;
}
task->annotate(static_cast<mx::tasking::TaskInterface::channel>(0));
mx::tasking::runtime::spawn(*task);
if (progress) {
while (!_nic.rx()->ready_to_ack()) { _ep.wait_and_dispatch_one_io_signal(); }
rx->try_ack_packet(packet);
_wakeup_scheduler.schedule_nic_server_wakeup();
} }
} }
catch (Genode::Exception)
{
Genode::warning("Got signal without actual packet in queue");
}
}
} }
void Mxip::Nic_netif::handle_tx_ready() void Mxip::Nic_netif::handle_tx_ready()
{ {
/*Mxip::Tx_ready_task *task = new (_task_alloc->alloc(sizeof(Mxip::Tx_ready_task))) //GENODE_LOG_TSC(1);
Mxip::Tx_ready_task(_nic, *this); if (task == nullptr) /*Mxip::Tx_ready_task *task = new (_task_alloc->alloc(sizeof(Mxip::Tx_ready_task)))
{ Mxip::Tx_ready_task(_nic, *this); if (task == nullptr)
Genode::warning("Could not allocate tx_ready task object."); {
return; Genode::warning("Could not allocate tx_ready task object.");
} return;
task->annotate(static_cast<mx::tasking::TaskInterface::channel>(0)); }
mx::tasking::runtime::spawn(*task);*/ task->annotate(static_cast<mx::tasking::TaskInterface::channel>(0));
mx::tasking::runtime::spawn(*task);*/
auto &tx = *_nic.tx(); auto &tx = *_nic.tx();
bool progress = false; bool progress = false;
@@ -76,7 +83,10 @@ mx::tasking::runtime::spawn(*task);*/
void Mxip::Nic_netif::handle_link_state() void Mxip::Nic_netif::handle_link_state()
{ {
Mxip::Link_state_task *task = new (_task_alloc->alloc(sizeof(Mxip::Link_state_task))) Mxip::Link_state_task(_nic, _netif, *this, _dhcp); //Mxip::Link_state_task *task = new (_task_alloc->alloc(sizeof(Mxip::Link_state_task))) Mxip::Link_state_task(_nic, _netif, *this, _dhcp);
auto task = mx::tasking::runtime::new_task<Mxip::Link_state_task>(0, _nic, _netif, *this, _dhcp);
if (task == nullptr) { if (task == nullptr) {
Genode::warning("Could not allocate link state task object."); Genode::warning("Could not allocate link state task object.");
return; return;

View File

@@ -13,11 +13,13 @@
*/ */
/* Genode includes */ /* Genode includes */
#include "mxip_lock.h"
#include <timer_session/connection.h> #include <timer_session/connection.h>
#include <util/reconstructible.h> #include <util/reconstructible.h>
#include <base/sleep.h> #include <base/sleep.h>
#include <mxip/genode_init.h> #include <mxip/genode_init.h>
#include <mxip/mxip_lock.h>
#include <mx/tasking/task.h> #include <mx/tasking/task.h>
#include <mx/tasking/runtime.h> #include <mx/tasking/runtime.h>