L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
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
47
48
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;
170
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();
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;
384
386 unsigned _vq_max_num;
387 Stats_reader_list _stats_readers;
388 Del_cap_irq _del_cap_irq;
393 unsigned _dbg_port_num = 0;
394
410 bool handle_opt_arg(L4::Ipc::Varg const &opt, bool &monitor,
411 char *name, size_t size,
412 l4_uint16_t &vlan_access,
413 std::vector<l4_uint16_t> &vlan_trunk,
414 bool *vlan_trunk_all,
415 l4_uint8_t mac[6], bool &mac_set)
416 {
417 assert(opt.is_of<char const *>());
418 unsigned len = opt.length();
419 const char *opt_str = opt.data();
420 Err err(Err::Normal);
421
422
423 if (len > 5)
424 {
425 if (!strncmp("type=", opt_str, 5))
426 {
427 if (!strncmp("type=monitor", opt_str, len))
428 {
429 monitor = true;
430 return true;
431 }
432 else if (!strncmp("type=none", opt_str, len))
433 return true;
434
435 err.printf("Unknown type '%.*s'\n", opt.length() - 5, opt.data() + 5);
436 return false;
437 }
438 else if (!strncmp("name=", opt_str, 5))
439 {
440 snprintf(name, size, "%.*s", opt.length() - 5, opt.data() + 5);
441 return true;
442 }
443 else if (!strncmp("vlan=", opt_str, 5))
444 {
445 cxx::String str(opt_str + 5, strnlen(opt_str + 5, len - 5));
447
448 if ((idx = str.starts_with("access=")))
449 {
450 str = str.substr(idx);
451 l4_uint16_t vid;
452 int next = str.from_dec(&vid);
453 if (next && next == str.len() && vlan_valid_id(vid))
454 vlan_access = vid;
455 else
456 {
457 err.printf("Invalid VLAN access port id '%.*s'\n",
458 opt.length(), opt.data());
459 return false;
460 }
461 }
462 else if ((idx = str.starts_with("trunk=")))
463 {
464 int next;
465 l4_uint16_t vid;
466 str = str.substr(idx);
467 if (str == cxx::String("all"))
468 {
469 *vlan_trunk_all = true;
470 return true;
471 }
472 while ((next = str.from_dec(&vid)))
473 {
474 if (!vlan_valid_id(vid))
475 break;
476 vlan_trunk.push_back(vid);
477 if (next < str.len() && str[next] != ',')
478 break;
479 str = str.substr(next+1);
480 }
481
482 if (vlan_trunk.empty() || !str.empty())
483 {
484 err.printf("Invalid VLAN trunk port spec '%.*s'\n",
485 opt.length(), opt.data());
486 return false;
487 }
488 }
489 else
490 {
491 err.printf("Invalid VLAN specification..\n");
492 return false;
493 }
494
495 return true;
496 }
497 else if (!strncmp("mac=", opt_str, 4))
498 {
499 size_t const OPT_LEN = 4 /* mac= */ + 6*2 /* digits */ + 5 /* : */;
500 // expect NUL terminated string for simplicity
501 if (len > OPT_LEN && opt_str[OPT_LEN] == '\0' &&
502 sscanf(opt_str+4, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &mac[0],
503 &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) == 6)
504 {
505 mac_set = true;
506 return true;
507 }
508
509 err.printf("Invalid mac address '%.*s'\n", len - 4, opt_str + 4);
510 return false;
511 }
512 }
513
514 err.printf("Unknown option '%.*s'\n", opt.length(), opt.data());
515 return false;
516 }
517
518public:
519 Switch_factory(Virtio_switch *virtio_switch, unsigned vq_max_num)
520 : _virtio_switch{virtio_switch}, _vq_max_num{vq_max_num},
521 _del_cap_irq{virtio_switch, &_stats_readers}
522 {
523 auto c = L4Re::chkcap(server.registry()->register_irq_obj(&_del_cap_irq));
524 L4Re::chksys(L4Re::Env::env()->main_thread()->register_del_irq(c));
525 };
526
533 long op_create(L4::Factory::Rights, L4::Ipc::Cap<void> &res,
535 {
536 switch (type)
537 {
538 case 0:
539 return create_port(res, va);
540 case 1:
541 return create_stats(res);
542 default:
543 Dbg(Dbg::Core, Dbg::Warn).printf("op_create: Invalid object type\n");
544 return -L4_EINVAL;
545 }
546 }
547
548 long create_port(L4::Ipc::Cap<void> &res, L4::Ipc::Varg_list_ref va)
549 {
550 Dbg warn(Dbg::Port, Dbg::Warn, "Port");
551 Dbg info(Dbg::Port, Dbg::Info, "Port");
552
553 info.printf("Incoming port request\n");
554
555 bool monitor = false;
556 char name[20] = "";
557 unsigned arg_n = 2;
558 l4_uint16_t vlan_access = 0;
559 std::vector<l4_uint16_t> vlan_trunk;
560 bool vlan_trunk_all = false;
561
562 l4_uint8_t mac[6];
563 bool mac_set = false;
564 int num_ds = 2;
565
566 for (L4::Ipc::Varg opt: va)
567 {
568 if (!opt.is_of<char const *>())
569 {
570 warn.printf("Unexpected type for argument %d\n", arg_n);
571 return -L4_EINVAL;
572 }
573
574 if (parse_int_param(opt, "ds-max=", &num_ds))
575 {
576 if (num_ds <= 0 || num_ds > 80)
577 {
578 Err(Err::Normal).printf("warning: client requested invalid number"
579 " of data spaces: 0 < %d <= 80\n", num_ds);
580 return -L4_EINVAL;
581 }
582 }
583 else if (!handle_opt_arg(opt, monitor, name, sizeof(name), vlan_access,
584 vlan_trunk, &vlan_trunk_all, mac, mac_set))
585 return -L4_EINVAL;
586
587 ++arg_n;
588 }
589
590 if (!_virtio_switch->port_available(monitor))
591 {
592 warn.printf("No port available\n");
593 return -L4_ENOMEM;
594 }
595
596 if (vlan_access && (!vlan_trunk.empty() || vlan_trunk_all))
597 {
598 warn.printf("VLAN port cannot be access and trunk simultaneously.\n");
599 return -L4_EINVAL;
600 }
601
602 if (!name[0])
603 snprintf(name, sizeof(name), "%s[%u]", monitor ? "monitor": "",
604 _dbg_port_num++);
605
606 info.printf(" Creating port %s%s\n", name,
607 monitor ? " as monitor port" : "");
608
609 // Assign a random MAC address if we assign one to our devices but the
610 // user has not passed an explicit one for a port.
611 if (!mac_set && Options::get_options()->assign_mac())
612 assign_random_mac(mac);
613
614 l4_uint8_t *mac_ptr = (mac_set || Options::get_options()->assign_mac())
615 ? mac : nullptr;
616
617 // create port
618 Port *port;
619 if (monitor)
620 {
621 port = new Monitor_port(server.registry(), _vq_max_num, num_ds, name,
622 mac_ptr);
623 port->set_monitor();
624
625 if (vlan_access)
626 warn.printf("vlan=access=<id> ignored on monitor ports!\n");
627 if (!vlan_trunk.empty())
628 warn.printf("vlan=trunk=... ignored on monitor ports!\n");
629 }
630 else
631 {
632 port = new Switch_port(server.registry(), _virtio_switch, _vq_max_num,
633 num_ds, name, mac_ptr);
634
635 if (vlan_access)
636 port->set_vlan_access(vlan_access);
637 else if (vlan_trunk_all)
638 port->set_vlan_trunk_all();
639 else if (!vlan_trunk.empty())
640 port->set_vlan_trunk(vlan_trunk);
641 }
642
643 port->add_trusted_dataspaces(trusted_dataspaces);
644 if (!trusted_dataspaces->empty())
645 port->enable_trusted_ds_validation();
646
647 // hand port over to the switch
648 bool added = monitor ? _virtio_switch->add_monitor_port(port)
649 : _virtio_switch->add_port(port);
650 if (!added)
651 {
652 delete port;
653 return -L4_ENOMEM;
654 }
655 res = L4::Ipc::make_cap(port->obj_cap(), L4_CAP_FPAGE_RWSD);
656
657 info.printf(" Created port %s\n", name);
658 return L4_EOK;
659 }
660
661 long create_stats(L4::Ipc::Cap<void> &res)
662 {
663 // Create a stats reader and throw away our reference to get a notification
664 // when the external reference vanishes.
665 auto reader = cxx::make_unique<Stats_reader>();
666 L4Re::chkcap(server.registry()->register_obj(reader.get()));
667 reader->obj_cap()->dec_refcnt(1);
668 res = L4::Ipc::make_cap(reader->obj_cap(),
670 _stats_readers.push_back(cxx::move(reader));
671 return L4_EOK;
672 }
673};
674
675#if CONFIG_VNS_IXL
679class Ixl_hw_port : public Ixl_port
680{
681 template<typename Derived>
682 class Port_irq : public L4::Irqep_t<Derived>
683 {
684 public:
685 Port_irq(Virtio_switch *virtio_switch, Ixl_port *port)
686 : _switch{virtio_switch}, _port{port} {}
687
688 protected:
689 Virtio_switch *_switch;
690 Ixl_port *_port;
691 };
692
693 class Receive_irq : public Port_irq<Receive_irq>
694 {
695 public:
696 using Port_irq::Port_irq;
697
704 void handle_irq()
705 {
706 if (!_port->dev()->check_recv_irq(0))
707 return;
708
709 if (_switch->handle_ixl_port_tx(_port))
710 _port->dev()->ack_recv_irq(0);
711 }
712 };
713
714 class Reschedule_tx_irq : public Port_irq<Reschedule_tx_irq>
715 {
716 public:
717 using Port_irq::Port_irq;
718
719 void handle_irq()
720 {
721 if (_switch->handle_ixl_port_tx(_port))
722 // Entire TX queue handled, re-enable the recv IRQ again.
723 _port->dev()->ack_recv_irq(0);
724 }
725 };
726
727 Receive_irq _recv_irq;
728 Reschedule_tx_irq _reschedule_tx_irq;
729
730public:
731 Ixl_hw_port(L4Re::Util::Object_registry *registry,
732 Virtio_switch *virtio_switch, Ixl::Ixl_device *dev)
733 : Ixl_port(dev),
734 _recv_irq(virtio_switch, this),
735 _reschedule_tx_irq(virtio_switch, this)
736 {
737 L4::Cap<L4::Irq> recv_irq_cap = L4Re::chkcap(dev->get_recv_irq(0), "Get receive IRQ");
738 L4Re::chkcap(registry->register_obj(&_recv_irq, recv_irq_cap),
739 "Register receive IRQ.");
740 recv_irq_cap->unmask();
741
742 _pending_tx_reschedule =
743 L4Re::chkcap(registry->register_irq_obj(&_reschedule_tx_irq),
744 "Register TX reschedule IRQ.");
745 _pending_tx_reschedule->unmask();
746 }
747
748 ~Ixl_hw_port() override
749 {
750 server.registry()->unregister_obj(&_recv_irq);
751 }
752};
753
754static void
755discover_ixl_devices(L4::Cap<L4vbus::Vbus> vbus, Virtio_switch *virtio_switch)
756{
757 struct Ixl::Dev_cfg cfg;
758 // Configure the device in asynchronous notify mode.
759 cfg.irq_timeout_ms = -1;
760
761 // TODO: Support detecting multiple devices on a Vbus.
762 // Setup the driver (also resets and initializes the NIC).
763 Ixl::Ixl_device *dev = Ixl::Ixl_device::ixl_init(vbus, 0, cfg);
764 if (!dev)
765 // No Ixl supported device found, Ixl already printed an error message.
766 return;
767
768 Ixl_hw_port *hw_port = new Ixl_hw_port(server.registry(), virtio_switch, dev);
769 if (!virtio_switch->add_port(hw_port))
770 {
771 Err().printf("error adding ixl port\n");
772 delete hw_port;
773 }
774}
775#endif
776
777int main(int argc, char *argv[])
778{
779 trusted_dataspaces = std::make_shared<Ds_vector>();
780 auto *opts = Options::parse_options(argc, argv, trusted_dataspaces);
781 if (!opts)
782 {
783 Err().printf("Error during command line parsing.\n");
784 return 1;
785 }
786
787 // Show welcome message if debug level is not set to quiet
788 if (Dbg(Dbg::Core, Dbg::Warn).is_active())
789 printf("Hello from l4virtio switch\n");
790
791 Virtio_switch *virtio_switch = new Virtio_switch(opts->get_max_ports());
792
793#ifdef CONFIG_VNS_STATS
794 Switch_statistics::get_instance().initialize(opts->get_max_ports());
795#endif
796
797#if CONFIG_VNS_IXL
798 auto vbus = L4Re::Env::env()->get_cap<L4vbus::Vbus>("vbus");
799 if (vbus.is_valid())
800 discover_ixl_devices(vbus, virtio_switch);
801#endif
802
803 Switch_factory *factory = new Switch_factory(virtio_switch,
804 opts->get_virtq_max_num());
805
806 L4::Cap<void> cap = server.registry()->register_obj(factory, "svr");
807 if (!cap.is_valid())
808 {
809 Err().printf("error registering switch\n");
810 return 2;
811 }
812
813 /*
814 * server loop will handle 4 types of events
815 * - Switch_factory
816 * - factory protocol
817 * - capability deletion
818 * - delegated to Virtio_switch::check_ports()
819 * - Switch_factory::Switch_port
820 * - irqs triggered by clients
821 * - delegated to Virtio_switch::handle_l4virtio_port_tx()
822 * - Virtio_net_transfer
823 * - timeouts for pending transfer requests added by
824 * Port_iface::handle_request() via registered via
825 * L4::Epiface::server_iface()->add_timeout()
826 */
827 server.loop();
828 return 0;
829}
830
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.
l4_fpage_t fpage(unsigned rights=L4_CAP_FPAGE_RWS) const noexcept
Return flexpage for the capability.
Definition capability.h:74
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
l4_msgtag_t unmask(l4_utcb_t *utcb=l4_utcb()) noexcept
Unmask this IRQ.
Definition irq:221
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
Exception for an abstract runtime error.
Definition exceptions:129
The virtual bus (Vbus) interface.
Definition vbus:299
virtual L4::Cap< L4::Irq > device_notify_irq() const
Definition l4virtio:848
void enable_notify()
Clear the 'no notify' flag for this queue.
Definition virtio:284
void disable_notify()
Set the 'no notify' flag for this queue.
Definition virtio:273
A Port on the Virtio Net Switch.
void drop_requests()
Drop all requests pending in the transmission queue.
L4virtio_port(unsigned vq_max, unsigned num_ds, char const *name, l4_uint8_t const *mac)
Create a Virtio net port object.
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:533
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:36
void check_ports()
Check validity of ports.
Definition switch.cc:56
bool handle_l4virtio_port_tx(L4virtio_port *port)
Handle TX queue of the given port.
Definition switch.cc:180
bool add_port(Port_iface *port)
Add a port to the switch.
Definition switch.cc:17
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
Unique_cap< T > make_unique_cap()
Allocate a capability slot and wrap it in an Unique_cap.
Definition unique_cap:55
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
@ RW
Readable and writable region.
Definition rm:139
@ Search_addr
Search for a suitable address range.
Definition rm:113
Cap< L4virtio::Device > obj_cap() const
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.