L4Re Operating System Framework
Interface and Usage Documentation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
main.cc
1/*
2 * Copyright (C) 2016-2020, 2022-2024 Kernkonzept GmbH.
3 * Author(s): Jean Wolter <jean.wolter@kernkonzept.com>
4 * Manuel von Oltersdorff-Kalettka <manuel.kalettka@kernkonzept.com>
5 *
6 * License: see LICENSE.spdx (in this directory or the directories above)
7 */
8#include <l4/re/util/meta>
9#include <l4/re/util/object_registry>
10#include <l4/re/util/br_manager>
11
12#include <l4/sys/factory>
13#include <l4/sys/task>
14
15#include <l4/sys/cxx/ipc_epiface>
16#include <l4/sys/cxx/ipc_varg>
17#include <l4/cxx/dlist>
18#include <l4/cxx/string>
19
20#include <vector>
21#include <string>
22#include <terminate_handler-l4>
23
24#include "debug.h"
25#include "options.h"
26#include "switch.h"
27#include "vlan.h"
28#include <l4/virtio-net-switch/stats.h>
29
48/*
49 * Registry for our server, used to register
50 * - factory capability
51 * - irq object for capability deletion irqs
52 * - virtio host kick irqs
53 */
55
56using Ds_vector = std::vector<L4::Cap<L4Re::Dataspace>>;
57static std::shared_ptr<Ds_vector> trusted_dataspaces;
58
59static bool
60parse_int_param(L4::Ipc::Varg const &param, char const *prefix, int *out)
61{
62 l4_size_t headlen = strlen(prefix);
63
64 if (param.length() < headlen)
65 return false;
66
67 char const *pstr = param.value<char const *>();
68
69 if (strncmp(pstr, prefix, headlen) != 0)
70 return false;
71
72 std::string tail(pstr + headlen, param.length() - headlen);
73
74 if (!parse_int_optstring(tail.c_str(), out))
75 {
76 Err(Err::Normal).printf("Bad parameter '%s'. Invalid number specified.\n",
77 prefix);
79 }
80
81 return true;
82}
83
95class Switch_factory : public L4::Epiface_t<Switch_factory, L4::Factory>
96{
100 class Port : public L4virtio_port
101 {
102 // Irq used to notify the guest
103 L4::Cap<L4::Irq> _device_notify_irq;
104
105 L4::Cap<L4::Irq> device_notify_irq() const override
106 { return _device_notify_irq; }
107
108 public:
109 Port(unsigned vq_max, unsigned num_ds, char const *name,
110 l4_uint8_t const *mac)
111 : L4virtio_port(vq_max, num_ds, name, mac) {}
112
114 void register_end_points(L4Re::Util::Object_registry* registry,
115 L4::Epiface *kick_irq)
116 {
117 // register virtio host kick irq
118 _device_notify_irq = L4Re::chkcap(registry->register_irq_obj(kick_irq));
119
120 // register virtio endpoint
121 L4Re::chkcap(registry->register_obj(this));
122
123 // decrement ref counter to get a notification when the last
124 // external reference vanishes
125 obj_cap()->dec_refcnt(1);
126 }
127
128 virtual ~Port()
129 { server.registry()->unregister_obj(this); }
130 };
131
135 class Switch_port : public Port
136 {
147 class Kick_irq : public L4::Irqep_t<Kick_irq>
148 {
149 Virtio_switch *_switch;
150 L4virtio_port *_port;
152 public:
159 void handle_irq()
160 { _switch->handle_l4virtio_port_tx(_port); }
161
162 Kick_irq(Virtio_switch *virtio_switch, L4virtio_port *port)
163 : _switch{virtio_switch}, _port{port} {}
164 };
165
166 Kick_irq _kick_irq;
167 Kick_irq _reschedule_tx_irq;
168
169 public:
170 Switch_port(L4Re::Util::Object_registry *registry,
171 Virtio_switch *virtio_switch, unsigned vq_max, unsigned num_ds,
172 char const *name, l4_uint8_t const *mac)
173 : Port(vq_max, num_ds, name, mac),
174 _kick_irq(virtio_switch, this),
175 _reschedule_tx_irq(virtio_switch, this)
176 {
177 register_end_points(registry, &_kick_irq);
178
179 _pending_tx_reschedule =
180 L4Re::chkcap(registry->register_irq_obj(&_reschedule_tx_irq),
181 "Register TX reschedule IRQ.");
182 _pending_tx_reschedule->unmask();
183 }
184
185 virtual ~Switch_port()
186 {
187 // We need to delete the IRQ object created in register_irq_obj() ourselves
188 L4::Cap<L4::Task>(L4Re::This_task)
189 ->unmap(_kick_irq.obj_cap().fpage(),
191 server.registry()->unregister_obj(&_kick_irq);
192 }
193 };
194
198 class Monitor_port : public Port
199 {
205 class Kick_irq : public L4::Irqep_t<Kick_irq>
206 {
207 L4virtio_port *_port;
208
209 public:
217 void handle_irq()
218 {
219 do
220 {
221 _port->tx_q()->disable_notify();
222 _port->rx_q()->disable_notify();
223
224 _port->drop_requests();
225
226 _port->tx_q()->enable_notify();
227 _port->rx_q()->enable_notify();
228
229 L4virtio::wmb();
230 L4virtio::rmb();
231 }
232 while (_port->tx_work_pending());
233 }
234
235 Kick_irq(L4virtio_port *port) : _port{port} {}
236 };
237
238 Kick_irq _kick_irq;
239
240 public:
241 Monitor_port(L4Re::Util::Object_registry* registry,
242 unsigned vq_max, unsigned num_ds, char const *name,
243 l4_uint8_t const *mac)
244 : Port(vq_max, num_ds, name, mac), _kick_irq(this)
245 { register_end_points(registry, &_kick_irq); }
246
247 virtual ~Monitor_port()
248 {
249 // We need to delete the IRQ object created in register_irq_obj() ourselves
250 L4::Cap<L4::Task>(L4Re::This_task)
251 ->unmap(_kick_irq.obj_cap().fpage(),
253 server.registry()->unregister_obj(&_kick_irq);
254 }
255 };
256
260 class Stats_reader
261 : public cxx::D_list_item,
262 public L4::Epiface_t<Stats_reader, Virtio_net_switch::Statistics_if>
263 {
265 l4_addr_t _addr;
266
267 public:
268 Stats_reader()
269 {
270 l4_size_t size = Switch_statistics::get_instance().size();
271 _ds = L4Re::Util::make_unique_cap<L4Re::Dataspace>();
272 L4Re::chksys(L4Re::Env::env()->mem_alloc()->alloc(size, _ds.get()),
273 "Could not allocate shared mem ds.");
274 L4Re::chksys(L4Re::Env::env()->rm()->attach(&_addr, _ds->size(),
277 L4::Ipc::make_cap_rw(_ds.get())));
278
279 memset(reinterpret_cast<void*>(_addr), 0, _ds->size());
280 }
281
282 ~Stats_reader()
283 {
284 L4Re::Env::env()->rm()->detach(reinterpret_cast<l4_addr_t>(_addr), 0);
285 server.registry()->unregister_obj(this);
286 }
287
288 long op_get_buffer(Virtio_net_switch::Statistics_if::Rights,
290 {
291 // We hand out the dataspace in a read only manner. Clients must not be
292 // able to modify information as that would create an unwanted data
293 // channel.
295 return L4_EOK;
296 }
297
298 long op_sync(Virtio_net_switch::Statistics_if::Rights)
299 {
300 memcpy(reinterpret_cast<void *>(_addr),
301 reinterpret_cast<void *>(Switch_statistics::get_instance().stats()),
302 Switch_statistics::get_instance().size());
303 return L4_EOK;
304 }
305
306 bool is_valid()
307 { return obj_cap() && obj_cap().validate().label(); }
308 };
309
310 class Stats_reader_list
311 {
312 cxx::D_list<Stats_reader> _readers;
313
314 public:
315 void check_readers()
316 {
317 auto it = _readers.begin();
318 while (it != _readers.end())
319 {
320 auto *reader = *it;
321 if (!reader->is_valid())
322 {
323 it = _readers.erase(it);
324 delete reader;
325 }
326 else
327 ++it;
328 }
329 }
330
331 void push_back(cxx::unique_ptr<Stats_reader> reader)
332 {
333 _readers.push_back(reader.release());
334 }
335 };
336
337 /*
338 * Handle vanishing caps by telling the switch that a port might have gone
339 */
340 struct Del_cap_irq : public L4::Irqep_t<Del_cap_irq>
341 {
342 public:
343 void handle_irq()
344 {
345 _switch->check_ports();
346 _stats_readers->check_readers();
347 }
348
349 Del_cap_irq(Virtio_switch *virtio_switch, Stats_reader_list *stats_readers)
350 : _switch{virtio_switch},
351 _stats_readers{stats_readers}
352 {}
353
354 private:
355 Virtio_switch *_switch;
356 Stats_reader_list *_stats_readers;
357 };
358
359 Virtio_switch *_virtio_switch;
362 unsigned _vq_max_num;
363 Stats_reader_list _stats_readers;
364 Del_cap_irq _del_cap_irq;
365
381 bool handle_opt_arg(L4::Ipc::Varg const &opt, bool &monitor,
382 char *name, size_t size,
383 l4_uint16_t &vlan_access,
384 std::vector<l4_uint16_t> &vlan_trunk,
385 bool *vlan_trunk_all,
386 l4_uint8_t mac[6], bool &mac_set)
387 {
388 assert(opt.is_of<char const *>());
389 unsigned len = opt.length();
390 const char *opt_str = opt.data();
391 Err err(Err::Normal);
392
393
394 if (len > 5)
395 {
396 if (!strncmp("type=", opt_str, 5))
397 {
398 if (!strncmp("type=monitor", opt_str, len))
399 {
400 monitor = true;
401 return true;
402 }
403 else if (!strncmp("type=none", opt_str, len))
404 return true;
405
406 err.printf("Unknown type '%.*s'\n", opt.length() - 5, opt.data() + 5);
407 return false;
408 }
409 else if (!strncmp("name=", opt_str, 5))
410 {
411 snprintf(name, size, "%.*s", opt.length() - 5, opt.data() + 5);
412 return true;
413 }
414 else if (!strncmp("vlan=", opt_str, 5))
415 {
416 cxx::String str(opt_str + 5, strnlen(opt_str + 5, len - 5));
418
419 if ((idx = str.starts_with("access=")))
420 {
421 str = str.substr(idx);
422 l4_uint16_t vid;
423 int next = str.from_dec(&vid);
424 if (next && next == str.len() && vlan_valid_id(vid))
425 vlan_access = vid;
426 else
427 {
428 err.printf("Invalid VLAN access port id '%.*s'\n",
429 opt.length(), opt.data());
430 return false;
431 }
432 }
433 else if ((idx = str.starts_with("trunk=")))
434 {
435 int next;
436 l4_uint16_t vid;
437 str = str.substr(idx);
438 if (str == cxx::String("all"))
439 {
440 *vlan_trunk_all = true;
441 return true;
442 }
443 while ((next = str.from_dec(&vid)))
444 {
445 if (!vlan_valid_id(vid))
446 break;
447 vlan_trunk.push_back(vid);
448 if (next < str.len() && str[next] != ',')
449 break;
450 str = str.substr(next+1);
451 }
452
453 if (vlan_trunk.empty() || !str.empty())
454 {
455 err.printf("Invalid VLAN trunk port spec '%.*s'\n",
456 opt.length(), opt.data());
457 return false;
458 }
459 }
460 else
461 {
462 err.printf("Invalid VLAN specification..\n");
463 return false;
464 }
465
466 return true;
467 }
468 else if (!strncmp("mac=", opt_str, 4))
469 {
470 size_t const OPT_LEN = 4 /* mac= */ + 6*2 /* digits */ + 5 /* : */;
471 // expect NUL terminated string for simplicity
472 if (len > OPT_LEN && opt_str[OPT_LEN] == '\0' &&
473 sscanf(opt_str+4, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &mac[0],
474 &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) == 6)
475 {
476 mac_set = true;
477 return true;
478 }
479
480 err.printf("Invalid mac address '%.*s'\n", len - 4, opt_str + 4);
481 return false;
482 }
483 }
484
485 err.printf("Unknown option '%.*s'\n", opt.length(), opt.data());
486 return false;
487 }
488
489public:
490 Switch_factory(Virtio_switch *virtio_switch, unsigned vq_max_num)
491 : _virtio_switch{virtio_switch}, _vq_max_num{vq_max_num},
492 _del_cap_irq{virtio_switch, &_stats_readers}
493 {
494 auto c = L4Re::chkcap(server.registry()->register_irq_obj(&_del_cap_irq));
495 L4Re::chksys(L4Re::Env::env()->main_thread()->register_del_irq(c));
496 };
497
504 long op_create(L4::Factory::Rights, L4::Ipc::Cap<void> &res,
506 {
507 switch (type)
508 {
509 case 0:
510 return create_port(res, va);
511 case 1:
512 return create_stats(res);
513 default:
514 Dbg(Dbg::Core, Dbg::Warn).printf("op_create: Invalid object type\n");
515 return -L4_EINVAL;
516 }
517 }
518
519 long create_port(L4::Ipc::Cap<void> &res, L4::Ipc::Varg_list_ref va)
520 {
521 Dbg warn(Dbg::Port, Dbg::Warn, "Port");
522 Dbg info(Dbg::Port, Dbg::Info, "Port");
523
524 info.printf("Incoming port request\n");
525
526 bool monitor = false;
527 char name[20] = "";
528 unsigned arg_n = 2;
529 l4_uint16_t vlan_access = 0;
530 std::vector<l4_uint16_t> vlan_trunk;
531 bool vlan_trunk_all = false;
532
533 // Default MAC address. Might be overridden by a "mac=..." option.
534 // First octet: 0x02
535 // * bit 0: Individual/Group address bit
536 // * bit 1: Universally/Locally Administered address bit
537 // Last two octets are filled with port number.
538 l4_uint8_t mac[6] = { 0x02, 0x08, 0x0f, 0x2a, 0x00, 0x00 };
539 bool mac_set = false;
540 int num_ds = 2;
541
542 for (L4::Ipc::Varg opt: va)
543 {
544 if (!opt.is_of<char const *>())
545 {
546 warn.printf("Unexpected type for argument %d\n", arg_n);
547 return -L4_EINVAL;
548 }
549
550 if (parse_int_param(opt, "ds-max=", &num_ds))
551 {
552 if (num_ds <= 0 || num_ds > 80)
553 {
554 Err(Err::Normal).printf("warning: client requested invalid number"
555 " of data spaces: 0 < %d <= 80\n", num_ds);
556 return -L4_EINVAL;
557 }
558 }
559 else if (!handle_opt_arg(opt, monitor, name, sizeof(name), vlan_access,
560 vlan_trunk, &vlan_trunk_all, mac, mac_set))
561 return -L4_EINVAL;
562
563 ++arg_n;
564 }
565
566 int port_num = _virtio_switch->port_available(monitor);
567 if (port_num < 0)
568 {
569 warn.printf("No port available\n");
570 return -L4_ENOMEM;
571 }
572
573 if (vlan_access && (!vlan_trunk.empty() || vlan_trunk_all))
574 {
575 warn.printf("VLAN port cannot be access and trunk simultaneously.\n");
576 return -L4_EINVAL;
577 }
578
579 if (!name[0])
580 snprintf(name, sizeof(name), "%s[%d]", monitor ? "monitor" : "",
581 port_num);
582
583 info.printf(" Creating port %s%s\n", name,
584 monitor ? " as monitor port" : "");
585
586 if (!mac_set)
587 {
588 // assign a dedicated MAC address to the monitor interface
589 // assuming we will never have more than 57000 (0xdea8) normal
590 // ports
591 if (monitor)
592 {
593 mac[4] = 0xde;
594 mac[5] = 0xad;
595 }
596 else
597 {
598 mac[4] = (l4_uint8_t)(port_num >> 8);
599 mac[5] = (l4_uint8_t)port_num;
600 }
601 }
602 l4_uint8_t *mac_ptr = (mac_set || Options::get_options()->assign_mac())
603 ? mac : nullptr;
604
605 // create port
606 Port *port;
607 if (monitor)
608 {
609 port = new Monitor_port(server.registry(), _vq_max_num, num_ds, name,
610 mac_ptr);
611 port->set_monitor();
612
613 if (vlan_access)
614 warn.printf("vlan=access=<id> ignored on monitor ports!\n");
615 if (!vlan_trunk.empty())
616 warn.printf("vlan=trunk=... ignored on monitor ports!\n");
617 }
618 else
619 {
620 port = new Switch_port(server.registry(), _virtio_switch, _vq_max_num,
621 num_ds, name, mac_ptr);
622
623 if (vlan_access)
624 port->set_vlan_access(vlan_access);
625 else if (vlan_trunk_all)
626 port->set_vlan_trunk_all();
627 else if (!vlan_trunk.empty())
628 port->set_vlan_trunk(vlan_trunk);
629 }
630
631 port->add_trusted_dataspaces(trusted_dataspaces);
632 if (!trusted_dataspaces->empty())
633 port->enable_trusted_ds_validation();
634
635 // hand port over to the switch
636 bool added = monitor ? _virtio_switch->add_monitor_port(port)
637 : _virtio_switch->add_port(port);
638 if (!added)
639 {
640 delete port;
641 return -L4_ENOMEM;
642 }
643 res = L4::Ipc::make_cap(port->obj_cap(), L4_CAP_FPAGE_RWSD);
644
645 info.printf(" Created port %s\n", name);
646 return L4_EOK;
647 };
648
649 long create_stats(L4::Ipc::Cap<void> &res)
650 {
651 // Create a stats reader and throw away our reference to get a notification
652 // when the external reference vanishes.
653 auto reader = cxx::make_unique<Stats_reader>();
654 L4Re::chkcap(server.registry()->register_obj(reader.get()));
655 reader->obj_cap()->dec_refcnt(1);
656 res = L4::Ipc::make_cap(reader->obj_cap(),
658 _stats_readers.push_back(cxx::move(reader));
659 return L4_EOK;
660 }
661};
662
663#if CONFIG_VNS_IXL
667class Ixl_hw_port : public Ixl_port
668{
669 template<typename Derived>
670 class Port_irq : public L4::Irqep_t<Derived>
671 {
672 public:
673 Port_irq(Virtio_switch *virtio_switch, Ixl_port *port)
674 : _switch{virtio_switch}, _port{port} {}
675
676 protected:
677 Virtio_switch *_switch;
678 Ixl_port *_port;
679 };
680
681 class Receive_irq : public Port_irq<Receive_irq>
682 {
683 public:
684 using Port_irq::Port_irq;
685
692 void handle_irq()
693 {
694 if (!_port->dev()->check_recv_irq(0))
695 return;
696
697 if (_switch->handle_ixl_port_tx(_port))
698 _port->dev()->ack_recv_irq(0);
699 }
700 };
701
702 class Reschedule_tx_irq : public Port_irq<Reschedule_tx_irq>
703 {
704 public:
705 using Port_irq::Port_irq;
706
707 void handle_irq()
708 {
709 if (_switch->handle_ixl_port_tx(_port))
710 // Entire TX queue handled, re-enable the recv IRQ again.
711 _port->dev()->ack_recv_irq(0);
712 }
713 };
714
715 Receive_irq _recv_irq;
716 Reschedule_tx_irq _reschedule_tx_irq;
717
718public:
719 Ixl_hw_port(L4Re::Util::Object_registry *registry,
720 Virtio_switch *virtio_switch, Ixl::Ixl_device *dev)
721 : Ixl_port(dev),
722 _recv_irq(virtio_switch, this),
723 _reschedule_tx_irq(virtio_switch, this)
724 {
725 L4::Cap<L4::Irq> recv_irq_cap = L4Re::chkcap(dev->get_recv_irq(0), "Get receive IRQ");
726 L4Re::chkcap(registry->register_obj(&_recv_irq, recv_irq_cap),
727 "Register receive IRQ.");
728 recv_irq_cap->unmask();
729
730 _pending_tx_reschedule =
731 L4Re::chkcap(registry->register_irq_obj(&_reschedule_tx_irq),
732 "Register TX reschedule IRQ.");
733 _pending_tx_reschedule->unmask();
734 }
735
736 ~Ixl_hw_port() override
737 {
738 server.registry()->unregister_obj(&_recv_irq);
739 }
740};
741
742static void
743discover_ixl_devices(L4::Cap<L4vbus::Vbus> vbus, Virtio_switch *virtio_switch)
744{
745 struct Ixl::Dev_cfg cfg;
746 // Configure the device in asynchronous notify mode.
747 cfg.irq_timeout_ms = -1;
748
749 // TODO: Support detecting multiple devices on a Vbus.
750 // Setup the driver (also resets and initializes the NIC).
751 Ixl::Ixl_device *dev = Ixl::Ixl_device::ixl_init(vbus, 0, cfg);
752 if (!dev)
753 // No Ixl supported device found, Ixl already printed an error message.
754 return;
755
756 Ixl_hw_port *hw_port = new Ixl_hw_port(server.registry(), virtio_switch, dev);
757 if (!virtio_switch->add_port(hw_port))
758 {
759 Err().printf("error adding ixl port\n");
760 delete hw_port;
761 }
762}
763#endif
764
765int main(int argc, char *argv[])
766{
767 trusted_dataspaces = std::make_shared<Ds_vector>();
768 auto *opts = Options::parse_options(argc, argv, trusted_dataspaces);
769 if (!opts)
770 {
771 Err().printf("Error during command line parsing.\n");
772 return 1;
773 }
774
775 // Show welcome message if debug level is not set to quiet
776 if (Dbg(Dbg::Core, Dbg::Warn).is_active())
777 printf("Hello from l4virtio switch\n");
778
779 Virtio_switch *virtio_switch = new Virtio_switch(opts->get_max_ports());
780
781#if CONFIG_VNS_IXL
782 auto vbus = L4Re::Env::env()->get_cap<L4vbus::Vbus>("vbus");
783 if (vbus.is_valid())
784 discover_ixl_devices(vbus, virtio_switch);
785#endif
786
787 Switch_factory *factory = new Switch_factory(virtio_switch,
788 opts->get_virtq_max_num());
789
790#ifdef CONFIG_VNS_STATS
791 Switch_statistics::get_instance().initialize(opts->get_max_ports());
792#endif
793
794 L4::Cap<void> cap = server.registry()->register_obj(factory, "svr");
795 if (!cap.is_valid())
796 {
797 Err().printf("error registering switch\n");
798 return 2;
799 }
800
801 /*
802 * server loop will handle 4 types of events
803 * - Switch_factory
804 * - factory protocol
805 * - capability deletion
806 * - delegated to Virtio_switch::check_ports()
807 * - Switch_factory::Switch_port
808 * - irqs triggered by clients
809 * - delegated to Virtio_switch::handle_l4virtio_port_tx()
810 * - Virtio_net_transfer
811 * - timeouts for pending transfer requests added by
812 * Port_iface::handle_request() via registered via
813 * L4::Epiface::server_iface()->add_timeout()
814 */
815 server.loop();
816 return 0;
817}
818
static Env const * env() noexcept
Returns the initial environment for the current task.
Definition env:96
L4::Cap< Rm > rm() const noexcept
Object-capability to the region map.
Definition env:120
L4::Cap< T > get_cap(char const *name, unsigned l) const noexcept
Get the capability selector for the object named name.
Definition env:197
A registry that manages server objects and their attached IPC gates for a single server loop for a sp...
L4::Cap< L4::Irq > register_irq_obj(L4::Epiface *o) override
Register a handler for an interrupt.
L4::Cap< void > register_obj(L4::Epiface *o, char const *service) override
Register a new server object to a pre-allocated receive endpoint.
A server loop object which has a Object_registry included.
bool is_valid() const noexcept
Test whether the capability is a valid capability index (i.e., not L4_INVALID_CAP).
Definition capability.h:57
C++ interface for capabilities.
Definition capability.h:224
Capability type for RPC interfaces (see L4::Cap<T>).
Definition ipc_types:699
List of variable-sized RPC parameters as received by the server.
Definition ipc_varg:254
Variably sized RPC argument.
Definition ipc_varg:97
Va_type< V >::Ret_value value() const
Definition ipc_varg:155
bool is_of() const
Definition ipc_varg:169
unsigned length() const
Get the size of the RPC argument.
Definition ipc_varg:114
void data(char const *d)
Set Varg to indirect data value (usually in UTCB)
Definition ipc_varg:120
Exception for an abstract runtime error.
Definition exceptions:129
The virtual bus (Vbus) interface.
Definition vbus:299
A Port on the Virtio Net Switch.
void drop_requests()
Drop all requests pending in the transmission queue.
bool tx_work_pending() const
Check whether there is any work pending on the transmission queue.
The IPC interface for creating ports.
Definition main.cc:96
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:504
Virtqueue * rx_q()
Getter for the receive queue.
Definition virtio_net.h:307
Virtqueue * tx_q()
Getter for the transmission queue.
Definition virtio_net.h:305
The Virtio switch contains all ports and processes network requests.
Definition switch.h:34
bool add_monitor_port(Port_iface *port)
Add a monitor port to the switch.
Definition switch.cc:55
bool handle_l4virtio_port_tx(L4virtio_port *port)
Handle TX queue of the given port.
Definition switch.cc:195
int port_available(bool monitor)
Is there still a free port on this switch available?
Definition switch.h:148
bool add_port(Port_iface *port)
Add a port to the switch.
Definition switch.cc:30
Allocation free string class with explicit length field.
Definition string:31
bool empty() const
Check if the string has length zero.
Definition string:65
String substr(unsigned long idx, unsigned long len=~0UL) const
Substring of length len starting at idx.
Definition string:84
char const * Index
Character index type.
Definition string:35
int from_dec(INT *v) const
Convert decimal string to integer.
Definition string:228
Index starts_with(cxx::String const &c) const
Check if c is a prefix of string.
Definition string:155
int len() const
Length.
Definition string:58
Common factory related definitions.
unsigned int l4_size_t
Unsigned size type.
Definition l4int.h:24
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
unsigned long l4_addr_t
Address type.
Definition l4int.h:34
unsigned char l4_uint8_t
Unsigned 8bit value.
Definition l4int.h:25
unsigned short int l4_uint16_t
Unsigned 16bit value.
Definition l4int.h:27
@ L4_EINVAL
Invalid argument.
Definition err.h:46
@ L4_EOK
Ok.
Definition err.h:32
@ L4_ENOMEM
No memory.
Definition err.h:39
@ L4_CAP_FPAGE_RO
Read right for capability flexpages.
Definition __l4_fpage.h:176
@ L4_CAP_FPAGE_R
Read right for capability flexpages.
Definition __l4_fpage.h:175
@ L4_CAP_FPAGE_RWSD
Full rights for capability flexpages.
Definition __l4_fpage.h:212
@ L4_CAP_FPAGE_D
Delete right for capability flexpages.
Definition __l4_fpage.h:185
@ 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
Flag to tell the unmap operation to revoke permissions from all child mappings including the mapping ...
Definition consts.h:183
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
long chksys(long err, char const *extra="", long ret=0)
Generate C++ exception on error.
Definition error_helper:72
T chkcap(T &&cap, char const *extra="", long err=-L4_ENOMEM)
Check for valid capability or raise C++ exception.
Definition error_helper:149
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
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
Debug C interface.
@ RW
Readable and writable region.
Definition rm:139
@ Search_addr
Search for a suitable address range.
Definition rm:114
Cap< RPC_IFACE > obj_cap() const
Get the (typed) capability to this object.
Definition ipc_epiface:269
Epiface implementation for Kobject-based interface implementations.
Definition ipc_epiface:504
Base class for interface implementations.
Definition ipc_epiface:146
Epiface implementation for interrupt handlers.
Definition ipc_epiface:283
Common task related definitions.