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 <stdlib.h>
21#include <string>
22#include <terminate_handler-l4>
23#include <vector>
24
25#include "debug.h"
26#include "options.h"
27#include "switch.h"
28#include "vlan.h"
29#include <l4/virtio-net-switch/stats.h>
30
49/*
50 * Registry for our server, used to register
51 * - factory capability
52 * - irq object for capability deletion irqs
53 * - virtio host kick irqs
54 */
56
57using Ds_vector = std::vector<L4::Cap<L4Re::Dataspace>>;
58static std::shared_ptr<Ds_vector> trusted_dataspaces;
59
60static bool
61parse_int_param(L4::Ipc::Varg const &param, char const *prefix, int *out)
62{
63 l4_size_t headlen = strlen(prefix);
64
65 if (param.length() < headlen)
66 return false;
67
68 char const *pstr = param.value<char const *>();
69
70 if (strncmp(pstr, prefix, headlen) != 0)
71 return false;
72
73 std::string tail(pstr + headlen, param.length() - headlen);
74
75 if (!parse_int_optstring(tail.c_str(), out))
76 {
77 Err(Err::Normal).printf("Bad parameter '%s'. Invalid number specified.\n",
78 prefix);
80 }
81
82 return true;
83}
84
85static void
86assign_random_mac(l4_uint8_t mac[6])
87{
88 static bool initialized = false;
89
90 if (!initialized)
91 {
92 srandom(l4_kip_clock(l4re_kip()));
93 initialized = true;
94 }
95
96 for (int i = 0; i < 6; i++)
97 mac[i] = static_cast<l4_uint8_t>(random());
98
99 mac[0] &= ~(1U << 0); // clear multicast bit
100 mac[0] |= 1U << 1; // set "locally administered" bit
101}
102
114class Switch_factory : public L4::Epiface_t<Switch_factory, L4::Factory>
115{
119 class Port : public L4virtio_port
120 {
121 // Irq used to notify the guest
122 L4::Cap<L4::Irq> _device_notify_irq;
123
124 L4::Cap<L4::Irq> device_notify_irq() const override
125 { return _device_notify_irq; }
126
127 public:
128 Port(unsigned vq_max, unsigned num_ds, char const *name,
129 l4_uint8_t const *mac)
130 : L4virtio_port(vq_max, num_ds, name, mac) {}
131
133 void register_end_points(L4Re::Util::Object_registry* registry,
134 L4::Epiface *kick_irq)
135 {
136 // register virtio host kick irq
137 _device_notify_irq = L4Re::chkcap(registry->register_irq_obj(kick_irq));
138
139 // register virtio endpoint
140 L4Re::chkcap(registry->register_obj(this));
141
142 // decrement ref counter to get a notification when the last
143 // external reference vanishes
144 obj_cap()->dec_refcnt(1);
145 }
146
147 virtual ~Port()
148 { server.registry()->unregister_obj(this); }
149 };
150
154 class Switch_port : public Port
155 {
166 class Kick_irq : public L4::Irqep_t<Kick_irq>
167 {
168 Virtio_switch *_switch;
169 L4virtio_port *_port;
171 public:
178 void handle_irq()
179 { _switch->handle_l4virtio_port_tx(_port); }
180
181 Kick_irq(Virtio_switch *virtio_switch, L4virtio_port *port)
182 : _switch{virtio_switch}, _port{port} {}
183 };
184
185 Kick_irq _kick_irq;
186 Kick_irq _reschedule_tx_irq;
187
188 public:
189 Switch_port(L4Re::Util::Object_registry *registry,
190 Virtio_switch *virtio_switch, unsigned vq_max, unsigned num_ds,
191 char const *name, l4_uint8_t const *mac)
192 : Port(vq_max, num_ds, name, mac),
193 _kick_irq(virtio_switch, this),
194 _reschedule_tx_irq(virtio_switch, this)
195 {
196 register_end_points(registry, &_kick_irq);
197
198 _pending_tx_reschedule =
199 L4Re::chkcap(registry->register_irq_obj(&_reschedule_tx_irq),
200 "Register TX reschedule IRQ.");
201 _pending_tx_reschedule->unmask();
202 }
203
204 virtual ~Switch_port()
205 {
206 // We need to delete the IRQ object created in register_irq_obj() ourselves
207 L4::Cap<L4::Task>(L4Re::This_task)
208 ->unmap(_kick_irq.obj_cap().fpage(),
210 server.registry()->unregister_obj(&_kick_irq);
211
212 L4::Cap<L4::Task>(L4Re::This_task)
213 ->unmap(_pending_tx_reschedule.fpage(),
215 server.registry()->unregister_obj(&_reschedule_tx_irq);
216 }
217 };
218
222 class Monitor_port : public Port
223 {
229 class Kick_irq : public L4::Irqep_t<Kick_irq>
230 {
231 L4virtio_port *_port;
232
233 public:
241 void handle_irq()
242 {
243 do
244 {
245 _port->tx_q()->disable_notify();
246 _port->rx_q()->disable_notify();
247
248 _port->drop_requests();
249
250 _port->tx_q()->enable_notify();
251 _port->rx_q()->enable_notify();
252
253 L4virtio::wmb();
254 L4virtio::rmb();
255 }
256 while (_port->tx_work_pending());
257 }
258
259 Kick_irq(L4virtio_port *port) : _port{port} {}
260 };
261
262 Kick_irq _kick_irq;
263
264 public:
265 Monitor_port(L4Re::Util::Object_registry* registry,
266 unsigned vq_max, unsigned num_ds, char const *name,
267 l4_uint8_t const *mac)
268 : Port(vq_max, num_ds, name, mac), _kick_irq(this)
269 { register_end_points(registry, &_kick_irq); }
270
271 virtual ~Monitor_port()
272 {
273 // We need to delete the IRQ object created in register_irq_obj() ourselves
274 L4::Cap<L4::Task>(L4Re::This_task)
275 ->unmap(_kick_irq.obj_cap().fpage(),
277 server.registry()->unregister_obj(&_kick_irq);
278 }
279 };
280
284 class Stats_reader
285 : public cxx::D_list_item,
286 public L4::Epiface_t<Stats_reader, Virtio_net_switch::Statistics_if>
287 {
289 l4_addr_t _addr;
290
291 public:
292 Stats_reader()
293 {
294 l4_size_t size = Switch_statistics::get_instance().size();
295 _ds = L4Re::Util::make_unique_cap<L4Re::Dataspace>();
296 L4Re::chksys(L4Re::Env::env()->mem_alloc()->alloc(size, _ds.get()),
297 "Could not allocate shared mem ds.");
298 L4Re::chksys(L4Re::Env::env()->rm()->attach(&_addr, _ds->size(),
301 L4::Ipc::make_cap_rw(_ds.get())));
302
303 memset(reinterpret_cast<void*>(_addr), 0, _ds->size());
304 }
305
306 ~Stats_reader()
307 {
308 L4Re::Env::env()->rm()->detach(reinterpret_cast<l4_addr_t>(_addr), 0);
309 server.registry()->unregister_obj(this);
310 }
311
312 long op_get_buffer(Virtio_net_switch::Statistics_if::Rights,
314 {
315 // We hand out the dataspace in a read only manner. Clients must not be
316 // able to modify information as that would create an unwanted data
317 // channel.
319 return L4_EOK;
320 }
321
322 long op_sync(Virtio_net_switch::Statistics_if::Rights)
323 {
324 memcpy(reinterpret_cast<void *>(_addr),
325 reinterpret_cast<void *>(Switch_statistics::get_instance().stats()),
326 Switch_statistics::get_instance().size());
327 return L4_EOK;
328 }
329
330 bool is_valid()
331 { return obj_cap() && obj_cap().validate().label(); }
332 };
333
334 class Stats_reader_list
335 {
336 cxx::D_list<Stats_reader> _readers;
337
338 public:
339 void check_readers()
340 {
341 auto it = _readers.begin();
342 while (it != _readers.end())
343 {
344 auto *reader = *it;
345 if (!reader->is_valid())
346 {
347 it = _readers.erase(it);
348 delete reader;
349 }
350 else
351 ++it;
352 }
353 }
354
355 void push_back(cxx::unique_ptr<Stats_reader> reader)
356 {
357 _readers.push_back(reader.release());
358 }
359 };
360
361 /*
362 * Handle vanishing caps by telling the switch that a port might have gone
363 */
364 struct Del_cap_irq : public L4::Irqep_t<Del_cap_irq>
365 {
366 public:
367 void handle_irq()
368 {
369 _switch->check_ports();
370 _stats_readers->check_readers();
371 }
372
373 Del_cap_irq(Virtio_switch *virtio_switch, Stats_reader_list *stats_readers)
374 : _switch{virtio_switch},
375 _stats_readers{stats_readers}
376 {}
377
378 private:
379 Virtio_switch *_switch;
380 Stats_reader_list *_stats_readers;
381 };
382
383 Virtio_switch *_virtio_switch;
386 unsigned _vq_max_num;
387 Stats_reader_list _stats_readers;
388 Del_cap_irq _del_cap_irq;
389
405 bool handle_opt_arg(L4::Ipc::Varg const &opt, bool &monitor,
406 char *name, size_t size,
407 l4_uint16_t &vlan_access,
408 std::vector<l4_uint16_t> &vlan_trunk,
409 bool *vlan_trunk_all,
410 l4_uint8_t mac[6], bool &mac_set)
411 {
412 assert(opt.is_of<char const *>());
413 unsigned len = opt.length();
414 const char *opt_str = opt.data();
415 Err err(Err::Normal);
416
417
418 if (len > 5)
419 {
420 if (!strncmp("type=", opt_str, 5))
421 {
422 if (!strncmp("type=monitor", opt_str, len))
423 {
424 monitor = true;
425 return true;
426 }
427 else if (!strncmp("type=none", opt_str, len))
428 return true;
429
430 err.printf("Unknown type '%.*s'\n", opt.length() - 5, opt.data() + 5);
431 return false;
432 }
433 else if (!strncmp("name=", opt_str, 5))
434 {
435 snprintf(name, size, "%.*s", opt.length() - 5, opt.data() + 5);
436 return true;
437 }
438 else if (!strncmp("vlan=", opt_str, 5))
439 {
440 cxx::String str(opt_str + 5, strnlen(opt_str + 5, len - 5));
442
443 if ((idx = str.starts_with("access=")))
444 {
445 str = str.substr(idx);
446 l4_uint16_t vid;
447 int next = str.from_dec(&vid);
448 if (next && next == str.len() && vlan_valid_id(vid))
449 vlan_access = vid;
450 else
451 {
452 err.printf("Invalid VLAN access port id '%.*s'\n",
453 opt.length(), opt.data());
454 return false;
455 }
456 }
457 else if ((idx = str.starts_with("trunk=")))
458 {
459 int next;
460 l4_uint16_t vid;
461 str = str.substr(idx);
462 if (str == cxx::String("all"))
463 {
464 *vlan_trunk_all = true;
465 return true;
466 }
467 while ((next = str.from_dec(&vid)))
468 {
469 if (!vlan_valid_id(vid))
470 break;
471 vlan_trunk.push_back(vid);
472 if (next < str.len() && str[next] != ',')
473 break;
474 str = str.substr(next+1);
475 }
476
477 if (vlan_trunk.empty() || !str.empty())
478 {
479 err.printf("Invalid VLAN trunk port spec '%.*s'\n",
480 opt.length(), opt.data());
481 return false;
482 }
483 }
484 else
485 {
486 err.printf("Invalid VLAN specification..\n");
487 return false;
488 }
489
490 return true;
491 }
492 else if (!strncmp("mac=", opt_str, 4))
493 {
494 size_t const OPT_LEN = 4 /* mac= */ + 6*2 /* digits */ + 5 /* : */;
495 // expect NUL terminated string for simplicity
496 if (len > OPT_LEN && opt_str[OPT_LEN] == '\0' &&
497 sscanf(opt_str+4, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &mac[0],
498 &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) == 6)
499 {
500 mac_set = true;
501 return true;
502 }
503
504 err.printf("Invalid mac address '%.*s'\n", len - 4, opt_str + 4);
505 return false;
506 }
507 }
508
509 err.printf("Unknown option '%.*s'\n", opt.length(), opt.data());
510 return false;
511 }
512
513public:
514 Switch_factory(Virtio_switch *virtio_switch, unsigned vq_max_num)
515 : _virtio_switch{virtio_switch}, _vq_max_num{vq_max_num},
516 _del_cap_irq{virtio_switch, &_stats_readers}
517 {
518 auto c = L4Re::chkcap(server.registry()->register_irq_obj(&_del_cap_irq));
519 L4Re::chksys(L4Re::Env::env()->main_thread()->register_del_irq(c));
520 };
521
528 long op_create(L4::Factory::Rights, L4::Ipc::Cap<void> &res,
530 {
531 switch (type)
532 {
533 case 0:
534 return create_port(res, va);
535 case 1:
536 return create_stats(res);
537 default:
538 Dbg(Dbg::Core, Dbg::Warn).printf("op_create: Invalid object type\n");
539 return -L4_EINVAL;
540 }
541 }
542
543 long create_port(L4::Ipc::Cap<void> &res, L4::Ipc::Varg_list_ref va)
544 {
545 Dbg warn(Dbg::Port, Dbg::Warn, "Port");
546 Dbg info(Dbg::Port, Dbg::Info, "Port");
547
548 info.printf("Incoming port request\n");
549
550 bool monitor = false;
551 char name[20] = "";
552 unsigned arg_n = 2;
553 l4_uint16_t vlan_access = 0;
554 std::vector<l4_uint16_t> vlan_trunk;
555 bool vlan_trunk_all = false;
556
557 l4_uint8_t mac[6];
558 bool mac_set = false;
559 int num_ds = 2;
560
561 for (L4::Ipc::Varg opt: va)
562 {
563 if (!opt.is_of<char const *>())
564 {
565 warn.printf("Unexpected type for argument %d\n", arg_n);
566 return -L4_EINVAL;
567 }
568
569 if (parse_int_param(opt, "ds-max=", &num_ds))
570 {
571 if (num_ds <= 0 || num_ds > 80)
572 {
573 Err(Err::Normal).printf("warning: client requested invalid number"
574 " of data spaces: 0 < %d <= 80\n", num_ds);
575 return -L4_EINVAL;
576 }
577 }
578 else if (!handle_opt_arg(opt, monitor, name, sizeof(name), vlan_access,
579 vlan_trunk, &vlan_trunk_all, mac, mac_set))
580 return -L4_EINVAL;
581
582 ++arg_n;
583 }
584
585 int port_num = _virtio_switch->port_available(monitor);
586 if (port_num < 0)
587 {
588 warn.printf("No port available\n");
589 return -L4_ENOMEM;
590 }
591
592 if (vlan_access && (!vlan_trunk.empty() || vlan_trunk_all))
593 {
594 warn.printf("VLAN port cannot be access and trunk simultaneously.\n");
595 return -L4_EINVAL;
596 }
597
598 if (!name[0])
599 snprintf(name, sizeof(name), "%s[%d]", monitor ? "monitor" : "",
600 port_num);
601
602 info.printf(" Creating port %s%s\n", name,
603 monitor ? " as monitor port" : "");
604
605 // Assign a random MAC address if we assign one to our devices but the
606 // user has not passed an explicit one for a port.
607 if (!mac_set && Options::get_options()->assign_mac())
608 assign_random_mac(mac);
609
610 l4_uint8_t *mac_ptr = (mac_set || Options::get_options()->assign_mac())
611 ? mac : nullptr;
612
613 // create port
614 Port *port;
615 if (monitor)
616 {
617 port = new Monitor_port(server.registry(), _vq_max_num, num_ds, name,
618 mac_ptr);
619 port->set_monitor();
620
621 if (vlan_access)
622 warn.printf("vlan=access=<id> ignored on monitor ports!\n");
623 if (!vlan_trunk.empty())
624 warn.printf("vlan=trunk=... ignored on monitor ports!\n");
625 }
626 else
627 {
628 port = new Switch_port(server.registry(), _virtio_switch, _vq_max_num,
629 num_ds, name, mac_ptr);
630
631 if (vlan_access)
632 port->set_vlan_access(vlan_access);
633 else if (vlan_trunk_all)
634 port->set_vlan_trunk_all();
635 else if (!vlan_trunk.empty())
636 port->set_vlan_trunk(vlan_trunk);
637 }
638
639 port->add_trusted_dataspaces(trusted_dataspaces);
640 if (!trusted_dataspaces->empty())
641 port->enable_trusted_ds_validation();
642
643 // hand port over to the switch
644 bool added = monitor ? _virtio_switch->add_monitor_port(port)
645 : _virtio_switch->add_port(port);
646 if (!added)
647 {
648 delete port;
649 return -L4_ENOMEM;
650 }
651 res = L4::Ipc::make_cap(port->obj_cap(), L4_CAP_FPAGE_RWSD);
652
653 info.printf(" Created port %s\n", name);
654 return L4_EOK;
655 }
656
657 long create_stats(L4::Ipc::Cap<void> &res)
658 {
659 // Create a stats reader and throw away our reference to get a notification
660 // when the external reference vanishes.
661 auto reader = cxx::make_unique<Stats_reader>();
662 L4Re::chkcap(server.registry()->register_obj(reader.get()));
663 reader->obj_cap()->dec_refcnt(1);
664 res = L4::Ipc::make_cap(reader->obj_cap(),
666 _stats_readers.push_back(cxx::move(reader));
667 return L4_EOK;
668 }
669};
670
671#if CONFIG_VNS_IXL
675class Ixl_hw_port : public Ixl_port
676{
677 template<typename Derived>
678 class Port_irq : public L4::Irqep_t<Derived>
679 {
680 public:
681 Port_irq(Virtio_switch *virtio_switch, Ixl_port *port)
682 : _switch{virtio_switch}, _port{port} {}
683
684 protected:
685 Virtio_switch *_switch;
686 Ixl_port *_port;
687 };
688
689 class Receive_irq : public Port_irq<Receive_irq>
690 {
691 public:
692 using Port_irq::Port_irq;
693
700 void handle_irq()
701 {
702 if (!_port->dev()->check_recv_irq(0))
703 return;
704
705 if (_switch->handle_ixl_port_tx(_port))
706 _port->dev()->ack_recv_irq(0);
707 }
708 };
709
710 class Reschedule_tx_irq : public Port_irq<Reschedule_tx_irq>
711 {
712 public:
713 using Port_irq::Port_irq;
714
715 void handle_irq()
716 {
717 if (_switch->handle_ixl_port_tx(_port))
718 // Entire TX queue handled, re-enable the recv IRQ again.
719 _port->dev()->ack_recv_irq(0);
720 }
721 };
722
723 Receive_irq _recv_irq;
724 Reschedule_tx_irq _reschedule_tx_irq;
725
726public:
727 Ixl_hw_port(L4Re::Util::Object_registry *registry,
728 Virtio_switch *virtio_switch, Ixl::Ixl_device *dev)
729 : Ixl_port(dev),
730 _recv_irq(virtio_switch, this),
731 _reschedule_tx_irq(virtio_switch, this)
732 {
733 L4::Cap<L4::Irq> recv_irq_cap = L4Re::chkcap(dev->get_recv_irq(0), "Get receive IRQ");
734 L4Re::chkcap(registry->register_obj(&_recv_irq, recv_irq_cap),
735 "Register receive IRQ.");
736 recv_irq_cap->unmask();
737
738 _pending_tx_reschedule =
739 L4Re::chkcap(registry->register_irq_obj(&_reschedule_tx_irq),
740 "Register TX reschedule IRQ.");
741 _pending_tx_reschedule->unmask();
742 }
743
744 ~Ixl_hw_port() override
745 {
746 server.registry()->unregister_obj(&_recv_irq);
747 }
748};
749
750static void
751discover_ixl_devices(L4::Cap<L4vbus::Vbus> vbus, Virtio_switch *virtio_switch)
752{
753 struct Ixl::Dev_cfg cfg;
754 // Configure the device in asynchronous notify mode.
755 cfg.irq_timeout_ms = -1;
756
757 // TODO: Support detecting multiple devices on a Vbus.
758 // Setup the driver (also resets and initializes the NIC).
759 Ixl::Ixl_device *dev = Ixl::Ixl_device::ixl_init(vbus, 0, cfg);
760 if (!dev)
761 // No Ixl supported device found, Ixl already printed an error message.
762 return;
763
764 Ixl_hw_port *hw_port = new Ixl_hw_port(server.registry(), virtio_switch, dev);
765 if (!virtio_switch->add_port(hw_port))
766 {
767 Err().printf("error adding ixl port\n");
768 delete hw_port;
769 }
770}
771#endif
772
773int main(int argc, char *argv[])
774{
775 trusted_dataspaces = std::make_shared<Ds_vector>();
776 auto *opts = Options::parse_options(argc, argv, trusted_dataspaces);
777 if (!opts)
778 {
779 Err().printf("Error during command line parsing.\n");
780 return 1;
781 }
782
783 // Show welcome message if debug level is not set to quiet
784 if (Dbg(Dbg::Core, Dbg::Warn).is_active())
785 printf("Hello from l4virtio switch\n");
786
787 Virtio_switch *virtio_switch = new Virtio_switch(opts->get_max_ports());
788
789#ifdef CONFIG_VNS_STATS
790 Switch_statistics::get_instance().initialize(opts->get_max_ports());
791#endif
792
793#if CONFIG_VNS_IXL
794 auto vbus = L4Re::Env::env()->get_cap<L4vbus::Vbus>("vbus");
795 if (vbus.is_valid())
796 discover_ixl_devices(vbus, virtio_switch);
797#endif
798
799 Switch_factory *factory = new Switch_factory(virtio_switch,
800 opts->get_virtq_max_num());
801
802 L4::Cap<void> cap = server.registry()->register_obj(factory, "svr");
803 if (!cap.is_valid())
804 {
805 Err().printf("error registering switch\n");
806 return 2;
807 }
808
809 /*
810 * server loop will handle 4 types of events
811 * - Switch_factory
812 * - factory protocol
813 * - capability deletion
814 * - delegated to Virtio_switch::check_ports()
815 * - Switch_factory::Switch_port
816 * - irqs triggered by clients
817 * - delegated to Virtio_switch::handle_l4virtio_port_tx()
818 * - Virtio_net_transfer
819 * - timeouts for pending transfer requests added by
820 * Port_iface::handle_request() via registered via
821 * L4::Epiface::server_iface()->add_timeout()
822 */
823 server.loop();
824 return 0;
825}
826
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:115
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
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.
l4_kernel_info_t const * l4re_kip(void) L4_NOTHROW
Get Kernel Info Page.
Definition env.h:185
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_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
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.