Loading...
Searching...
No Matches
main.cc
/*
* Copyright (C) 2016-2020, 2022-2024 Kernkonzept GmbH.
* Author(s): Jean Wolter <jean.wolter@kernkonzept.com>
* Manuel von Oltersdorff-Kalettka <manuel.kalettka@kernkonzept.com>
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#include <l4/re/util/meta>
#include <l4/re/util/object_registry>
#include <l4/re/util/br_manager>
#include <l4/sys/factory>
#include <l4/sys/task>
#include <l4/sys/cxx/ipc_epiface>
#include <l4/sys/cxx/ipc_varg>
#include <l4/cxx/dlist>
#include <l4/cxx/string>
#include <stdlib.h>
#include <string>
#include <terminate_handler-l4>
#include <vector>
#include "debug.h"
#include "options.h"
#include "switch.h"
#include "vlan.h"
#include <l4/virtio-net-switch/stats.h>
/*
* Registry for our server, used to register
* - factory capability
* - irq object for capability deletion irqs
* - virtio host kick irqs
*/
static L4Re::Util::Registry_server<L4Re::Util::Br_manager_hooks> server;
using Ds_vector = std::vector<L4::Cap<L4Re::Dataspace>>;
static std::shared_ptr<Ds_vector> trusted_dataspaces;
static bool
parse_int_param(L4::Ipc::Varg const &param, char const *prefix, int *out)
{
l4_size_t headlen = strlen(prefix);
if (param.length() < headlen)
return false;
char const *pstr = param.value<char const *>();
if (strncmp(pstr, prefix, headlen) != 0)
return false;
std::string tail(pstr + headlen, param.length() - headlen);
if (!parse_int_optstring(tail.c_str(), out))
{
Err(Err::Normal).printf("Bad parameter '%s'. Invalid number specified.\n",
prefix);
throw L4::Runtime_error(-L4_EINVAL);
}
return true;
}
static void
assign_random_mac(l4_uint8_t mac[6])
{
static bool initialized = false;
if (!initialized)
{
srandom(l4_kip_clock(l4re_kip()));
initialized = true;
}
for (int i = 0; i < 6; i++)
mac[i] = static_cast< l4_uint8_t >(random());
mac[0] &= ~(1U << 0); // clear multicast bit
mac[0] |= 1U << 1; // set "locally administered" bit
}
class Switch_factory : public L4::Epiface_t<Switch_factory, L4::Factory>
{
class Port : public L4virtio_port
{
// Irq used to notify the guest
L4::Cap<L4::Irq> _device_notify_irq;
L4::Cap<L4::Irq> device_notify_irq() const override
{ return _device_notify_irq; }
public:
Port(unsigned vq_max, unsigned num_ds, char const *name,
l4_uint8_t const *mac)
: L4virtio_port(vq_max, num_ds, name, mac) {}
void register_end_points(L4Re::Util::Object_registry* registry,
L4::Epiface *kick_irq)
{
// register virtio host kick irq
_device_notify_irq = L4Re::chkcap(registry->register_irq_obj(kick_irq));
// register virtio endpoint
L4Re::chkcap(registry->register_obj(this));
// decrement ref counter to get a notification when the last
// external reference vanishes
obj_cap()->dec_refcnt(1);
}
virtual ~Port()
{ server.registry()->unregister_obj(this); }
};
class Switch_port : public Port
{
class Kick_irq : public L4::Irqep_t<Kick_irq>
{
Virtio_switch *_switch;
L4virtio_port *_port;
public:
void handle_irq()
{ _switch->handle_l4virtio_port_tx(_port); }
Kick_irq(Virtio_switch *virtio_switch, L4virtio_port *port)
: _switch{virtio_switch}, _port{port} {}
};
Kick_irq _kick_irq;
Kick_irq _reschedule_tx_irq;
public:
Switch_port(L4Re::Util::Object_registry *registry,
Virtio_switch *virtio_switch, unsigned vq_max, unsigned num_ds,
char const *name, l4_uint8_t const *mac)
: Port(vq_max, num_ds, name, mac),
_kick_irq(virtio_switch, this),
_reschedule_tx_irq(virtio_switch, this)
{
register_end_points(registry, &_kick_irq);
_pending_tx_reschedule =
L4Re::chkcap(registry->register_irq_obj(&_reschedule_tx_irq),
"Register TX reschedule IRQ.");
_pending_tx_reschedule->unmask();
}
virtual ~Switch_port()
{
// We need to delete the IRQ object created in register_irq_obj() ourselves
L4::Cap<L4::Task>(L4Re::This_task)
->unmap(_kick_irq.obj_cap().fpage(),
L4_FP_ALL_SPACES | L4_FP_DELETE_OBJ);
server.registry()->unregister_obj(&_kick_irq);
L4::Cap<L4::Task>(L4Re::This_task)
->unmap(_pending_tx_reschedule.fpage(),
L4_FP_ALL_SPACES | L4_FP_DELETE_OBJ);
server.registry()->unregister_obj(&_reschedule_tx_irq);
}
};
class Monitor_port : public Port
{
class Kick_irq : public L4::Irqep_t<Kick_irq>
{
L4virtio_port *_port;
public:
void handle_irq()
{
do
{
_port->tx_q()->disable_notify();
_port->rx_q()->disable_notify();
_port->drop_requests();
_port->tx_q()->enable_notify();
_port->rx_q()->enable_notify();
L4virtio::wmb();
L4virtio::rmb();
}
while (_port->tx_work_pending());
}
Kick_irq(L4virtio_port *port) : _port{port} {}
};
Kick_irq _kick_irq;
public:
Monitor_port(L4Re::Util::Object_registry* registry,
unsigned vq_max, unsigned num_ds, char const *name,
l4_uint8_t const *mac)
: Port(vq_max, num_ds, name, mac), _kick_irq(this)
{ register_end_points(registry, &_kick_irq); }
virtual ~Monitor_port()
{
// We need to delete the IRQ object created in register_irq_obj() ourselves
L4::Cap<L4::Task>(L4Re::This_task)
->unmap(_kick_irq.obj_cap().fpage(),
L4_FP_ALL_SPACES | L4_FP_DELETE_OBJ);
server.registry()->unregister_obj(&_kick_irq);
}
};
class Stats_reader
: public cxx::D_list_item,
public L4::Epiface_t<Stats_reader, Virtio_net_switch::Statistics_if>
{
L4Re::Util::Unique_cap<L4Re::Dataspace> _ds;
l4_addr_t _addr;
public:
Stats_reader()
{
l4_size_t size = Switch_statistics::get_instance().size();
_ds = L4Re::Util::make_unique_cap<L4Re::Dataspace>();
L4Re::chksys(L4Re::Env::env()->mem_alloc()->alloc(size, _ds.get()),
"Could not allocate shared mem ds.");
L4Re::chksys(L4Re::Env::env()->rm()->attach(&_addr, _ds->size(),
L4Re::Rm::F::Search_addr
| L4Re::Rm::F::RW,
L4::Ipc::make_cap_rw(_ds.get())));
memset(reinterpret_cast<void*>(_addr), 0, _ds->size());
}
~Stats_reader()
{
L4Re::Env::env()->rm()->detach(reinterpret_cast< l4_addr_t >(_addr), 0);
server.registry()->unregister_obj(this);
}
long op_get_buffer(Virtio_net_switch::Statistics_if::Rights,
L4::Ipc::Cap<L4Re::Dataspace> &ds)
{
// We hand out the dataspace in a read only manner. Clients must not be
// able to modify information as that would create an unwanted data
// channel.
ds = L4::Ipc::Cap<L4Re::Dataspace>(_ds.get(), L4_CAP_FPAGE_RO);
return L4_EOK;
}
long op_sync(Virtio_net_switch::Statistics_if::Rights)
{
memcpy(reinterpret_cast<void *>(_addr),
reinterpret_cast<void *>(Switch_statistics::get_instance().stats()),
Switch_statistics::get_instance().size());
return L4_EOK;
}
bool is_valid()
{ return obj_cap() && obj_cap().validate().label(); }
};
class Stats_reader_list
{
cxx::D_list<Stats_reader> _readers;
public:
void check_readers()
{
auto it = _readers.begin();
while (it != _readers.end())
{
auto *reader = *it;
if (!reader->is_valid())
{
it = _readers.erase(it);
delete reader;
}
else
++it;
}
}
void push_back(cxx::unique_ptr<Stats_reader> reader)
{
_readers.push_back(reader.release());
}
};
/*
* Handle vanishing caps by telling the switch that a port might have gone
*/
struct Del_cap_irq : public L4::Irqep_t<Del_cap_irq>
{
public:
void handle_irq()
{
_switch->check_ports();
_stats_readers->check_readers();
}
Del_cap_irq(Virtio_switch *virtio_switch, Stats_reader_list *stats_readers)
: _switch{virtio_switch},
_stats_readers{stats_readers}
{}
private:
Virtio_switch *_switch;
Stats_reader_list *_stats_readers;
};
Virtio_switch *_virtio_switch;
unsigned _vq_max_num;
Stats_reader_list _stats_readers;
Del_cap_irq _del_cap_irq;
bool handle_opt_arg(L4::Ipc::Varg const &opt, bool &monitor,
char *name, size_t size,
l4_uint16_t &vlan_access,
std::vector<l4_uint16_t> &vlan_trunk,
bool *vlan_trunk_all,
l4_uint8_t mac[6], bool &mac_set)
{
assert(opt.is_of<char const *>());
unsigned len = opt.length();
const char *opt_str = opt.data();
Err err(Err::Normal);
if (len > 5)
{
if (!strncmp("type=", opt_str, 5))
{
if (!strncmp("type=monitor", opt_str, len))
{
monitor = true;
return true;
}
else if (!strncmp("type=none", opt_str, len))
return true;
err.printf("Unknown type '%.*s'\n", opt.length() - 5, opt.data() + 5);
return false;
}
else if (!strncmp("name=", opt_str, 5))
{
snprintf(name, size, "%.*s", opt.length() - 5, opt.data() + 5);
return true;
}
else if (!strncmp("vlan=", opt_str, 5))
{
cxx::String str(opt_str + 5, strnlen(opt_str + 5, len - 5));
cxx::String::Index idx;
if ((idx = str.starts_with("access=")))
{
str = str.substr(idx);
l4_uint16_t vid;
int next = str.from_dec(&vid);
if (next && next == str.len() && vlan_valid_id(vid))
vlan_access = vid;
else
{
err.printf("Invalid VLAN access port id '%.*s'\n",
opt.length(), opt.data());
return false;
}
}
else if ((idx = str.starts_with("trunk=")))
{
int next;
l4_uint16_t vid;
str = str.substr(idx);
if (str == cxx::String("all"))
{
*vlan_trunk_all = true;
return true;
}
while ((next = str.from_dec(&vid)))
{
if (!vlan_valid_id(vid))
break;
vlan_trunk.push_back(vid);
if (next < str.len() && str[next] != ',')
break;
str = str.substr(next+1);
}
if (vlan_trunk.empty() || !str.empty())
{
err.printf("Invalid VLAN trunk port spec '%.*s'\n",
opt.length(), opt.data());
return false;
}
}
else
{
err.printf("Invalid VLAN specification..\n");
return false;
}
return true;
}
else if (!strncmp("mac=", opt_str, 4))
{
size_t const OPT_LEN = 4 /* mac= */ + 6*2 /* digits */ + 5 /* : */;
// expect NUL terminated string for simplicity
if (len > OPT_LEN && opt_str[OPT_LEN] == '\0' &&
sscanf(opt_str+4, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &mac[0],
&mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) == 6)
{
mac_set = true;
return true;
}
err.printf("Invalid mac address '%.*s'\n", len - 4, opt_str + 4);
return false;
}
}
err.printf("Unknown option '%.*s'\n", opt.length(), opt.data());
return false;
}
public:
Switch_factory(Virtio_switch *virtio_switch, unsigned vq_max_num)
: _virtio_switch{virtio_switch}, _vq_max_num{vq_max_num},
_del_cap_irq{virtio_switch, &_stats_readers}
{
auto c = L4Re::chkcap(server.registry()->register_irq_obj(&_del_cap_irq));
L4Re::chksys(L4Re::Env::env()->main_thread()->register_del_irq(c));
};
long op_create(L4::Factory::Rights, L4::Ipc::Cap<void> &res,
l4_umword_t type, L4::Ipc::Varg_list_ref va)
{
switch (type)
{
case 0:
return create_port(res, va);
case 1:
return create_stats(res);
default:
Dbg(Dbg::Core, Dbg::Warn).printf("op_create: Invalid object type\n");
return -L4_EINVAL;
}
}
long create_port(L4::Ipc::Cap<void> &res, L4::Ipc::Varg_list_ref va)
{
Dbg warn(Dbg::Port, Dbg::Warn, "Port");
Dbg info(Dbg::Port, Dbg::Info, "Port");
info.printf("Incoming port request\n");
bool monitor = false;
char name[20] = "";
unsigned arg_n = 2;
l4_uint16_t vlan_access = 0;
std::vector<l4_uint16_t> vlan_trunk;
bool vlan_trunk_all = false;
l4_uint8_t mac[6];
bool mac_set = false;
int num_ds = 2;
for (L4::Ipc::Varg opt: va)
{
if (!opt.is_of<char const *>())
{
warn.printf("Unexpected type for argument %d\n", arg_n);
return -L4_EINVAL;
}
if (parse_int_param(opt, "ds-max=", &num_ds))
{
if (num_ds <= 0 || num_ds > 80)
{
Err(Err::Normal).printf("warning: client requested invalid number"
" of data spaces: 0 < %d <= 80\n", num_ds);
return -L4_EINVAL;
}
}
else if (!handle_opt_arg(opt, monitor, name, sizeof(name), vlan_access,
vlan_trunk, &vlan_trunk_all, mac, mac_set))
return -L4_EINVAL;
++arg_n;
}
int port_num = _virtio_switch->port_available(monitor);
if (port_num < 0)
{
warn.printf("No port available\n");
return -L4_ENOMEM;
}
if (vlan_access && (!vlan_trunk.empty() || vlan_trunk_all))
{
warn.printf("VLAN port cannot be access and trunk simultaneously.\n");
return -L4_EINVAL;
}
if (!name[0])
snprintf(name, sizeof(name), "%s[%d]", monitor ? "monitor" : "",
port_num);
info.printf(" Creating port %s%s\n", name,
monitor ? " as monitor port" : "");
// Assign a random MAC address if we assign one to our devices but the
// user has not passed an explicit one for a port.
if (!mac_set && Options::get_options()->assign_mac())
assign_random_mac(mac);
l4_uint8_t *mac_ptr = (mac_set || Options::get_options()->assign_mac())
? mac : nullptr;
// create port
Port *port;
if (monitor)
{
port = new Monitor_port(server.registry(), _vq_max_num, num_ds, name,
mac_ptr);
port->set_monitor();
if (vlan_access)
warn.printf("vlan=access=<id> ignored on monitor ports!\n");
if (!vlan_trunk.empty())
warn.printf("vlan=trunk=... ignored on monitor ports!\n");
}
else
{
port = new Switch_port(server.registry(), _virtio_switch, _vq_max_num,
num_ds, name, mac_ptr);
if (vlan_access)
port->set_vlan_access(vlan_access);
else if (vlan_trunk_all)
port->set_vlan_trunk_all();
else if (!vlan_trunk.empty())
port->set_vlan_trunk(vlan_trunk);
}
port->add_trusted_dataspaces(trusted_dataspaces);
if (!trusted_dataspaces->empty())
port->enable_trusted_ds_validation();
// hand port over to the switch
bool added = monitor ? _virtio_switch->add_monitor_port(port)
: _virtio_switch->add_port(port);
if (!added)
{
delete port;
return -L4_ENOMEM;
}
res = L4::Ipc::make_cap(port->obj_cap(), L4_CAP_FPAGE_RWSD);
info.printf(" Created port %s\n", name);
return L4_EOK;
}
long create_stats(L4::Ipc::Cap<void> &res)
{
// Create a stats reader and throw away our reference to get a notification
// when the external reference vanishes.
auto reader = cxx::make_unique<Stats_reader>();
L4Re::chkcap(server.registry()->register_obj(reader.get()));
reader->obj_cap()->dec_refcnt(1);
res = L4::Ipc::make_cap(reader->obj_cap(),
L4_CAP_FPAGE_R | L4_CAP_FPAGE_D);
_stats_readers.push_back(cxx::move(reader));
return L4_EOK;
}
};
#if CONFIG_VNS_IXL
class Ixl_hw_port : public Ixl_port
{
template<typename Derived>
class Port_irq : public L4::Irqep_t<Derived>
{
public:
Port_irq(Virtio_switch *virtio_switch, Ixl_port *port)
: _switch{virtio_switch}, _port{port} {}
protected:
Virtio_switch *_switch;
Ixl_port *_port;
};
class Receive_irq : public Port_irq<Receive_irq>
{
public:
using Port_irq::Port_irq;
void handle_irq()
{
if (!_port->dev()->check_recv_irq(0))
return;
if (_switch->handle_ixl_port_tx(_port))
_port->dev()->ack_recv_irq(0);
}
};
class Reschedule_tx_irq : public Port_irq<Reschedule_tx_irq>
{
public:
using Port_irq::Port_irq;
void handle_irq()
{
if (_switch->handle_ixl_port_tx(_port))
// Entire TX queue handled, re-enable the recv IRQ again.
_port->dev()->ack_recv_irq(0);
}
};
Receive_irq _recv_irq;
Reschedule_tx_irq _reschedule_tx_irq;
public:
Ixl_hw_port(L4Re::Util::Object_registry *registry,
Virtio_switch *virtio_switch, Ixl::Ixl_device *dev)
: Ixl_port(dev),
_recv_irq(virtio_switch, this),
_reschedule_tx_irq(virtio_switch, this)
{
L4::Cap<L4::Irq> recv_irq_cap = L4Re::chkcap(dev->get_recv_irq(0), "Get receive IRQ");
L4Re::chkcap(registry->register_obj(&_recv_irq, recv_irq_cap),
"Register receive IRQ.");
recv_irq_cap->unmask();
_pending_tx_reschedule =
L4Re::chkcap(registry->register_irq_obj(&_reschedule_tx_irq),
"Register TX reschedule IRQ.");
_pending_tx_reschedule->unmask();
}
~Ixl_hw_port() override
{
server.registry()->unregister_obj(&_recv_irq);
}
};
static void
discover_ixl_devices(L4::Cap<L4vbus::Vbus> vbus, Virtio_switch *virtio_switch)
{
struct Ixl::Dev_cfg cfg;
// Configure the device in asynchronous notify mode.
cfg.irq_timeout_ms = -1;
// TODO: Support detecting multiple devices on a Vbus.
// Setup the driver (also resets and initializes the NIC).
Ixl::Ixl_device *dev = Ixl::Ixl_device::ixl_init(vbus, 0, cfg);
if (!dev)
// No Ixl supported device found, Ixl already printed an error message.
return;
Ixl_hw_port *hw_port = new Ixl_hw_port(server.registry(), virtio_switch, dev);
if (!virtio_switch->add_port(hw_port))
{
Err().printf("error adding ixl port\n");
delete hw_port;
}
}
#endif
int main(int argc, char *argv[])
{
trusted_dataspaces = std::make_shared<Ds_vector>();
auto *opts = Options::parse_options(argc, argv, trusted_dataspaces);
if (!opts)
{
Err().printf("Error during command line parsing.\n");
return 1;
}
// Show welcome message if debug level is not set to quiet
if (Dbg(Dbg::Core, Dbg::Warn).is_active())
printf("Hello from l4virtio switch\n");
Virtio_switch *virtio_switch = new Virtio_switch(opts->get_max_ports());
#ifdef CONFIG_VNS_STATS
Switch_statistics::get_instance().initialize(opts->get_max_ports());
#endif
#if CONFIG_VNS_IXL
auto vbus = L4Re::Env::env()->get_cap<L4vbus::Vbus>("vbus");
if (vbus.is_valid())
discover_ixl_devices(vbus, virtio_switch);
#endif
Switch_factory *factory = new Switch_factory(virtio_switch,
opts->get_virtq_max_num());
L4::Cap<void> cap = server.registry()->register_obj(factory, "svr");
if (!cap.is_valid())
{
Err().printf("error registering switch\n");
return 2;
}
/*
* server loop will handle 4 types of events
* - Switch_factory
* - factory protocol
* - capability deletion
* - delegated to Virtio_switch::check_ports()
* - Switch_factory::Switch_port
* - irqs triggered by clients
* - delegated to Virtio_switch::handle_l4virtio_port_tx()
* - Virtio_net_transfer
* - timeouts for pending transfer requests added by
* Port_iface::handle_request() via registered via
* L4::Epiface::server_iface()->add_timeout()
*/
server.loop();
return 0;
}
L4Re::Env::env
static Env const * env() noexcept
Returns the initial environment for the current task.
Definition env:96
L4Re::Env::rm
L4::Cap< Rm > rm() const noexcept
Object-capability to the region map.
Definition env:120
L4Re::Env::get_cap
L4::Cap< T > get_cap(char const *name, unsigned l) const noexcept
Get the capability selector for the object named name.
Definition env:197
L4Re::Util::Object_registry
A registry that manages server objects and their attached IPC gates for a single server loop for a sp...
Definition object_registry:44
L4Re::Util::Object_registry::register_irq_obj
L4::Cap< L4::Irq > register_irq_obj(L4::Epiface *o) override
Register a handler for an interrupt.
Definition object_registry:227
L4Re::Util::Object_registry::register_obj
L4::Cap< void > register_obj(L4::Epiface *o, char const *service) override
Register a new server object to a pre-allocated receive endpoint.
Definition object_registry:194
L4Re::Util::Registry_server
A server loop object which has a Object_registry included.
Definition object_registry:294
L4::Cap_base::fpage
l4_fpage_t fpage(unsigned rights=L4_CAP_FPAGE_RWS) const noexcept
Return flexpage for the capability.
Definition capability.h:74
L4::Cap_base::is_valid
bool is_valid() const noexcept
Test whether the capability is a valid capability index (i.e., not L4_INVALID_CAP).
Definition capability.h:57
L4::Cap
C++ interface for capabilities.
Definition capability.h:224
L4::Ipc::Cap
Capability type for RPC interfaces (see L4::Cap<T>).
Definition ipc_types:699
L4::Ipc::Varg_list_ref
List of variable-sized RPC parameters as received by the server.
Definition ipc_varg:254
L4::Ipc::Varg
Variably sized RPC argument.
Definition ipc_varg:97
L4::Ipc::Varg::value
Va_type< V >::Ret_value value() const
Definition ipc_varg:155
L4::Ipc::Varg::is_of
bool is_of() const
Definition ipc_varg:169
L4::Ipc::Varg::length
unsigned length() const
Get the size of the RPC argument.
Definition ipc_varg:114
L4::Ipc::Varg::data
void data(char const *d)
Set Varg to indirect data value (usually in UTCB).
Definition ipc_varg:120
L4::Irq::unmask
l4_msgtag_t unmask(l4_utcb_t *utcb=l4_utcb()) noexcept
Unmask this IRQ.
Definition irq:221
L4::Kobject::dec_refcnt
l4_msgtag_t dec_refcnt(l4_mword_t diff, l4_utcb_t *utcb=l4_utcb())
Decrement the in kernel reference counter for the object.
Definition kobject:100
L4::Runtime_error
Exception for an abstract runtime error.
Definition exceptions:129
L4vbus::Vbus
The virtual bus (Vbus) interface.
Definition vbus:299
L4virtio::Svr::Device_t< No_custom_data >::device_notify_irq
virtual L4::Cap< L4::Irq > device_notify_irq() const
Definition l4virtio:848
L4virtio::Svr::Virtqueue::enable_notify
void enable_notify()
Clear the 'no notify' flag for this queue.
Definition virtio:284
L4virtio::Svr::Virtqueue::disable_notify
void disable_notify()
Set the 'no notify' flag for this queue.
Definition virtio:273
L4virtio_port
A Port on the Virtio Net Switch.
Definition port_l4virtio.h:37
L4virtio_port::drop_requests
void drop_requests()
Drop all requests pending in the transmission queue.
Definition port_l4virtio.h:103
L4virtio_port::L4virtio_port
L4virtio_port(unsigned vq_max, unsigned num_ds, char const *name, l4_uint8_t const *mac)
Create a Virtio net port object.
Definition port_l4virtio.h:42
L4virtio_port::tx_work_pending
bool tx_work_pending() const
Check whether there is any work pending on the transmission queue.
Definition port_l4virtio.h:87
Switch_factory
The IPC interface for creating ports.
Definition main.cc:115
Switch_factory::op_create
long op_create(L4::Factory::Rights, L4::Ipc::Cap< void > &res, l4_umword_t type, L4::Ipc::Varg_list_ref va)
Handle factory protocol.
Definition main.cc:528
Virtio_net::rx_q
Virtqueue * rx_q()
Getter for the receive queue.
Definition virtio_net.h:307
Virtio_net::tx_q
Virtqueue * tx_q()
Getter for the transmission queue.
Definition virtio_net.h:305
Virtio_switch
The Virtio switch contains all ports and processes network requests.
Definition switch.h:34
Virtio_switch::check_ports
void check_ports()
Check validity of ports.
Definition switch.cc:69
Virtio_switch::handle_l4virtio_port_tx
bool handle_l4virtio_port_tx(L4virtio_port *port)
Handle TX queue of the given port.
Definition switch.cc:194
Virtio_switch::add_port
bool add_port(Port_iface *port)
Add a port to the switch.
Definition switch.cc:29
cxx::String
Allocation free string class with explicit length field.
Definition string:31
cxx::String::empty
bool empty() const
Check if the string has length zero.
Definition string:65
cxx::String::substr
String substr(unsigned long idx, unsigned long len=~0UL) const
Substring of length len starting at idx.
Definition string:84
cxx::String::Index
char const * Index
Character index type.
Definition string:35
cxx::String::from_dec
int from_dec(INT *v) const
Convert decimal string to integer.
Definition string:228
cxx::String::starts_with
Index starts_with(cxx::String const &c) const
Check if c is a prefix of string.
Definition string:155
cxx::String::len
int len() const
Length.
Definition string:58
factory
Common factory related definitions.
l4re_kip
l4_kernel_info_t const * l4re_kip(void) L4_NOTHROW
Get Kernel Info Page.
Definition env.h:185
l4_size_t
unsigned int l4_size_t
Unsigned size type.
Definition l4int.h:24
l4_umword_t
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
l4_addr_t
unsigned long l4_addr_t
Address type.
Definition l4int.h:34
l4_uint8_t
unsigned char l4_uint8_t
Unsigned 8bit value.
Definition l4int.h:25
l4_uint16_t
unsigned short int l4_uint16_t
Unsigned 16bit value.
Definition l4int.h:27
L4_EINVAL
@ L4_EINVAL
Invalid argument.
Definition err.h:46
L4_EOK
@ L4_EOK
Ok.
Definition err.h:32
L4_ENOMEM
@ L4_ENOMEM
No memory.
Definition err.h:39
L4_CAP_FPAGE_RO
@ L4_CAP_FPAGE_RO
Read right for capability flexpages.
Definition __l4_fpage.h:176
L4_CAP_FPAGE_R
@ L4_CAP_FPAGE_R
Read right for capability flexpages.
Definition __l4_fpage.h:175
L4_CAP_FPAGE_RWSD
@ L4_CAP_FPAGE_RWSD
Full rights for capability flexpages.
Definition __l4_fpage.h:212
L4_CAP_FPAGE_D
@ L4_CAP_FPAGE_D
Delete right for capability flexpages.
Definition __l4_fpage.h:185
l4_kip_clock
l4_cpu_time_t l4_kip_clock(l4_kernel_info_t const *kip) L4_NOTHROW
Return clock value from the KIP.
Definition kip.h:242
L4_FP_DELETE_OBJ
@ L4_FP_DELETE_OBJ
Flag that indicates that an unmap operation on object capabilities shall try to delete the correspond...
Definition consts.h:197
L4_FP_ALL_SPACES
@ L4_FP_ALL_SPACES
Flag to tell the unmap operation to revoke permissions from all child mappings including the mapping ...
Definition consts.h:183
L4Re::Util::make_unique_cap
Unique_cap< T > make_unique_cap()
Allocate a capability slot and wrap it in an Unique_cap.
Definition unique_cap:55
L4Re::Util::Unique_cap
L4::Detail::Unique_cap_impl< T, Smart_cap_auto< L4_FP_ALL_SPACES > > Unique_cap
Unique capability that implements automatic free and unmap of the capability selector.
Definition unique_cap:43
L4Re::chksys
long chksys(long err, char const *extra="", long ret=0)
Generate C++ exception on error.
Definition error_helper:72
L4Re::chkcap
T chkcap(T &&cap, char const *extra="", long err=-L4_ENOMEM)
Check for valid capability or raise C++ exception.
Definition error_helper:149
L4::Ipc::make_cap
Cap< T > make_cap(L4::Cap< T > cap, unsigned rights) noexcept
Make an L4::Ipc::Cap<T> for the given capability and rights.
Definition ipc_types:785
L4::Ipc::make_cap_rw
Cap< T > make_cap_rw(L4::Cap< T > cap) noexcept
Make an L4::Ipc::Cap<T> for the given capability with L4_CAP_FPAGE_RW rights.
Definition ipc_types:795
L4Re::Rm::F::RW
@ RW
Readable and writable region.
Definition rm:139
L4Re::Rm::F::Search_addr
@ Search_addr
Search for a suitable address range.
Definition rm:114
L4::Epiface_t0< L4virtio::Device, L4::Epiface >::obj_cap
Cap< L4virtio::Device > obj_cap() const
Definition ipc_epiface:269
L4::Epiface_t
Epiface implementation for Kobject-based interface implementations.
Definition ipc_epiface:504
L4::Epiface
Base class for interface implementations.
Definition ipc_epiface:146
L4::Irqep_t
Epiface implementation for interrupt handlers.
Definition ipc_epiface:283
task
Common task related definitions.