13: _max_ports(max_ports)
19 if (_ports.size() == _max_ports)
21 Dbg(Dbg::Port, Dbg::Warn)
22 .printf(
"Port limit (%u) has been reached.\n", _max_ports);
27 for (
auto const *p: _ports)
28 if (p->mac() == port->mac())
30 Dbg(Dbg::Port, Dbg::Warn)
31 .printf(
"Rejecting port '%s'. MAC address already in use.\n",
36 _ports.push_back(port);
49 Dbg(Dbg::Port, Dbg::Warn).printf(
"'%s' already defined as monitor port,"
50 " rejecting monitor port '%s'\n",
51 _monitor->get_name(), port->get_name());
58 for (std::vector<Port_iface *>::iterator it = _ports.begin();
64 Dbg(Dbg::Port, Dbg::Info)
65 .printf(
"Client on port %p has gone. Deleting...\n", port);
67 _mac_table.flush(port);
68 it = _ports.erase(it);
75 if (_monitor && _monitor->is_gone())
84Virtio_switch::handle_tx_request(Port_iface *port, REQ
const &request)
88 if (port->is_trunk() && !port->match_vlan(request.vlan_id()))
91 port->stat_inc_tx_dropped();
96 if (port->is_access() && request.has_vlan())
99 port->stat_inc_tx_dropped();
103 auto handle_request = [](Port_iface *dst_port, Port_iface *src_port,
106 auto transfer_src = req.transfer_src();
108 auto res = dst_port->handle_request(src_port, transfer_src, &bytes);
111 case Port_iface::Result::Delivered:
112 dst_port->stat_inc_tx_num();
113 dst_port->stat_inc_tx_bytes(bytes);
114 src_port->stat_inc_rx_num();
115 src_port->stat_inc_rx_bytes(bytes);
117 case Port_iface::Result::Dropped:
119 case Port_iface::Result::Exception:
122 dst_port->stat_inc_tx_dropped();
127 Mac_addr src = request.src_mac();
129 auto dst = request.dst_mac();
130 bool is_broadcast = dst.is_broadcast();
131 uint16_t vlan = request.has_vlan() ? request.vlan_id() : port->get_vlan();
132 _mac_table.learn(src, port, vlan);
135 auto *target = _mac_table.lookup(dst, vlan);
143 handle_request(target, port, request);
144 if (_monitor && !filter_request(request))
145 handle_request(_monitor, port, request);
153 for (
auto *target: _ports)
155 if (target != port && target->match_vlan(vlan))
156 handle_request(target, port, request);
160 if (_monitor && !filter_request(request))
161 handle_request(_monitor, port, request);
164template<
typename PORT>
166Virtio_switch::handle_tx_requests(PORT *port,
unsigned &num_reqs_handled)
168 while (
auto req = port->get_tx_request())
170 req->dump_request(port);
171 handle_tx_request(port, *req);
173 if (++num_reqs_handled >= Tx_burst)
184 Dbg(Dbg::Port, Dbg::Debug)
185 .printf(
"%s: Irq without pending work\n", port->get_name());
187 unsigned num_reqs_handled = 0;
193 if (num_reqs_handled >= Tx_burst)
195 Dbg(Dbg::Port, Dbg::Debug)
197 "%s: Tx burst limit hit, reschedule remaining Tx work.\n",
203 port->reschedule_pending_tx();
210 all_rx_notify_disable_and_remember();
215 handle_tx_requests(port, num_reqs_handled);
219 Dbg(Dbg::Port, Dbg::Warn,
"REQ")
220 .printf(
"%s: caught bad descriptor exception: %s - %i"
221 " -- Signal device error on device %p.\n",
222 __PRETTY_FUNCTION__, e.
message(), e.error, port);
224 all_rx_notify_emit_and_enable();
228 all_rx_notify_emit_and_enable();
243Virtio_switch::handle_ixl_port_tx(Ixl_port *port)
245 unsigned num_reqs_handled = 0;
247 all_rx_notify_disable_and_remember();
248 handle_tx_requests(port, num_reqs_handled);
249 all_rx_notify_emit_and_enable();
251 if (num_reqs_handled >= Tx_burst && port->tx_work_pending())
253 Dbg(Dbg::Port, Dbg::Info)
254 .printf(
"%s: Tx burst limit hit, reschedule remaining Tx work.\n",
260 port->reschedule_pending_tx();
void device_error()
Transition device into DEVICE_NEEDS_RESET state.
void enable_notify()
Clear the 'no notify' flag for this queue.
void disable_notify()
Set the 'no notify' flag for this queue.
A Port on the Virtio Net Switch.
bool tx_work_pending() const
Check whether there is any work pending on the transmission queue.
bool is_unknown() const
Check if the MAC address is not yet known.
Virtqueue * rx_q()
Getter for the receive queue.
Virtqueue * tx_q()
Getter for the transmission queue.
void check_ports()
Check validity of ports.
Virtio_switch(unsigned max_ports)
Create a switch with n ports.
bool add_monitor_port(Port_iface *port)
Add a monitor port to the switch.
bool handle_l4virtio_port_tx(L4virtio_port *port)
Handle TX queue of the given port.
bool add_port(Port_iface *port)
Add a port to the switch.
unsigned long long l4_uint64_t
Unsigned 64bit value.
#define L4_LIKELY(x)
Expression is likely to execute.
Exception used by Queue to indicate descriptor errors.
char const * message() const
Get a human readable description of the error code.