13: _max_ports{max_ports},
20Virtio_switch::lookup_free_slot()
22 for (
unsigned idx = 0; idx < _max_ports; ++idx)
33 for (
unsigned idx = 0; idx < _max_ports; ++idx)
34 if (_ports[idx] && _ports[idx]->mac() == port->
mac())
36 Dbg(Dbg::Port, Dbg::Warn)
37 .printf(
"Rejecting port '%s'. MAC address already in use.\n",
42 int idx = lookup_free_slot();
46 unsigned uidx =
static_cast<unsigned>(idx);
48 if (_max_used == uidx)
63 Dbg(Dbg::Port, Dbg::Warn).printf(
"'%s' already defined as monitor port,"
64 " rejecting monitor port '%s'\n",
65 _monitor->get_name(), port->get_name());
72 for (
unsigned idx = 0; idx < _max_used; ++idx)
75 if (port && port->
obj_cap() && !port->
obj_cap().validate().label())
77 Dbg(Dbg::Port, Dbg::Info)
78 .printf(
"Client on port %p has gone. Deleting...\n", port);
80 _ports[idx] =
nullptr;
81 if (idx == _max_used-1)
84 _mac_table.
flush(port);
89 if ( _monitor && _monitor->
obj_cap()
90 && !_monitor->
obj_cap().validate().label())
105 _mac_table.
learn(src, port);
107 auto dst = request->dst_mac();
108 bool is_broadcast = dst.is_broadcast();
109 uint16_t vlan = request->has_vlan() ? request->vlan_id() : port->get_vlan();
112 auto *target = _mac_table.
lookup(dst);
118 if (target != port && target->match_vlan(vlan))
121 if (_monitor && !filter_request(*request))
130 for (
unsigned idx = 0; idx < _max_used && _ports[idx]; ++idx)
132 auto *target = _ports[idx];
133 if (target != port && target->match_vlan(vlan))
134 target->handle_request(port, *request);
138 if (_monitor && !filter_request(*request))
147 Dbg(Dbg::Port, Dbg::Info)
148 .printf(
"Port %s: Irq without pending work\n", port->get_name());
152 port->
tx_q()->disable_notify();
153 port->
rx_q()->disable_notify();
156 all_kick_disable_remember();
162 handle_tx_queue(port);
166 Dbg(Dbg::Port, Dbg::Warn,
"REQ")
167 .printf(
"%s: caught bad descriptor exception: %s - %i"
168 " -- Signal device error on device %p.\n",
169 __PRETTY_FUNCTION__, e.
message(), e.error, port);
171 all_kick_emit_enable();
175 all_kick_emit_enable();
177 port->
tx_q()->enable_notify();
178 port->
rx_q()->enable_notify();
void device_error()
Transition device into DEVICE_NEEDS_RESET state.
A wrapper class around the value of a MAC address.
bool is_unknown() const
Check if the MAC address is not yet known.
void flush(Virtio_port *port)
Flush all associations with a given port.
Virtio_port * lookup(Mac_addr dst) const
Find the destination port for a MAC address.
void learn(Mac_addr src, Virtio_port *port)
Learn a MAC address (add it to the MAC table).
Virtqueue * rx_q()
Getter for the receive queue.
Virtqueue * tx_q()
Getter for the transmission queue.
A Port on the Virtio Net Switch.
std::optional< Virtio_net_request > get_tx_request()
Get one request from the transmission queue.
bool tx_work_pending() const
Check whether there is any work pending on the transmission queue.
void handle_request(Virtio_port *src_port, Virtio_net_request const &request)
Handle a request - send it to the guest associated with this port.
Mac_addr mac() const
Get MAC address.
bool add_monitor_port(Virtio_port *port)
Add a monitor port to the switch.
void check_ports()
Check validity of ports.
bool add_port(Virtio_port *port)
Add a port to the switch.
Virtio_switch(unsigned max_ports)
Create a switch with n ports.
void handle_port_irq(Virtio_port *port)
Handle an incoming irq on a given port.
#define L4_LIKELY(x)
Expression is likely to execute.
Cap< RPC_IFACE > obj_cap() const
Get the (typed) capability to this object.
Exception used by Queue to indicate descriptor errors.
char const * message() const
Get a human readable description of the error code.