12#include "request_l4virtio.h"
13#include "virtio_net.h"
42 explicit L4virtio_port(
unsigned vq_max,
unsigned num_ds,
char const *name,
48 Features hf = _dev_config.host_features(0);
52 memcpy((
void *)_dev_config.priv_config()->mac, mac,
53 sizeof(_dev_config.priv_config()->mac));
56 Dbg d(Dbg::Port, Dbg::Info);
57 d.cprintf(
"%s: Adding Mac '", _name);
59 d.cprintf(
"' to host features to %x\n", hf.raw);
61 _dev_config.host_features(0) = hf.raw;
62 _dev_config.reset_hdr();
63 Dbg(Dbg::Port, Dbg::Info)
64 .printf(
"%s: Set host features to %x\n", _name,
65 _dev_config.host_features(0));
67 _mac.to_array(_stats->mac);
42 explicit L4virtio_port(
unsigned vq_max,
unsigned num_ds,
char const *name, {
…}
71 void rx_notify_disable_and_remember()
override
73 kick_disable_and_remember();
76 void rx_notify_emit_and_enable()
override
78 kick_emit_and_enable();
81 bool is_gone()
const override
106 Result handle_request(Port_iface *src_port,
Net_transfer &src,
111 Dbg trace(Dbg::Request, Dbg::Trace,
"REQ-VIO");
112 trace.printf(
"%s: Transfer request %p.\n", _name, src.
req_id());
119 std::vector<Consumed_entry> consumed;
122 Virtqueue *dst_queue =
rx_q();
125 Virtio_net::Hdr *dst_header =
nullptr;
137 trace.printf(
"\tTransfer failed, bad descriptor exception, dropping.\n");
140 if (!consumed.empty())
142 dst_queue->rewind_avail(consumed.at(0).first);
145 dst_queue->rewind_avail(dst_head);
155 if (!dst_queue->ready())
156 return Result::Dropped;
158 auto r = dst_queue->next_avail();
162 trace.printf(
"\tTransfer failed, destination queue depleted, dropping.\n");
164 if (!consumed.empty())
165 dst_queue->rewind_avail(consumed.front().first);
166 return Result::Dropped;
175 Dbg(Dbg::Request, Dbg::Warn,
"REQ")
176 .printf(
"%s: bad descriptor exception: %s - %i"
177 " -- signal device error in destination device %p.\n",
178 __PRETTY_FUNCTION__, e.
message(), e.error, dst_dev);
181 return Result::Exception;
186 if (dst.
left <
sizeof(Virtio_net::Hdr))
188 "Target buffer too small for header");
189 dst_header =
reinterpret_cast<Virtio_net::Hdr *
>(dst.
pos);
190 trace.printf(
"\tCopying header to %p (size: %u)\n",
233 total =
sizeof(Virtio_net::Hdr);
241 bool has_dst_buffer = !dst.
done();
246 has_dst_buffer = dst_req_proc.
next(dst_dev->
mem_info(), &dst);
250 Dbg(Dbg::Request, Dbg::Warn,
"REQ")
251 .printf(
"%s: bad descriptor exception: %s - %i"
252 " -- signal device error in destination device %p.\n",
253 __PRETTY_FUNCTION__, e.
message(), e.error, dst_dev);
255 return Result::Exception;
261 trace.printf(
"\tCopying %p#%p:%u (%x) -> %p#%p:%u (%x)\n",
262 src_port, src_buf.pos, src_buf.left, src_buf.left,
263 static_cast<Port_iface *
>(
this),
266 total += mangle.
copy_pkt(dst, src_buf);
268 else if (negotiated_features().mrg_rxbuf())
271 trace.printf(
"\tSaving descriptor for later\n");
272 consumed.push_back(Consumed_entry(dst_head, total));
273 total_merged += total;
279 trace.printf(
"\tTransfer failed, destination buffer too small, dropping.\n");
281 dst_queue->rewind_avail(dst_head);
282 return Result::Dropped;
295 trace.printf(
"\tTransfer - not started yet, dropping\n");
296 return Result::Dropped;
299 if (consumed.empty())
302 assert(num_merged == 1);
303 trace.printf(
"\tTransfer - Invoke dst_queue->finish()\n");
304 dst_header->num_buffers = 1;
305 dst_queue->finish(dst_head, dst_dev, total);
306 *bytes_transferred = total;
311 dst_header->num_buffers = num_merged;
312 consumed.push_back(Consumed_entry(dst_head, total));
313 trace.printf(
"\tTransfer - Invoke dst_queue->finish(iter)\n");
314 *bytes_transferred = total + total_merged;
315 dst_queue->finish(consumed.begin(), consumed.end(), dst_dev);
317 return Result::Delivered;
Exception for an abstract runtime error.
void device_error()
Transition device into DEVICE_NEEDS_RESET state.
void init_mem_info(unsigned num)
Initialize the memory region list to the given maximum.
Mem_list const * mem_info() const
Get the memory region list used for this device.
Encapsulate the state for processing a VIRTIO request.
bool next(DESC_MAN *dm, ARGS... args)
Switch to the next descriptor in a descriptor chain.
void start(DESC_MAN *dm, Virtqueue *ring, Virtqueue::Head_desc const &request, ARGS... args)
Start processing a new request.
VIRTIO request, essentially a descriptor from the available ring.
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.
std::optional< Virtio_net_request > get_tx_request()
Get one request from the transmission queue.
A wrapper class around the value of a MAC address.
A network request to only a single destination.
virtual void copy_header(Virtio_net::Hdr *dst_header) const =0
Populate the virtio-net header for the destination.
void const * req_id() const
Identifier for the underlying Net_request, used for logging purposes.
virtual bool done()=0
Check whether the transfer has been completed, i.e.
Buffer & cur_buf()
Buffer containing (a part of) the packet data.
static std::optional< Virtio_net_request > get_request(Virtio_net *dev, L4virtio::Svr::Virtqueue *queue)
Construct a request from the next entry of a provided queue.
static void drop_requests(Virtio_net *dev, L4virtio::Svr::Virtqueue *queue)
Drop all requests of a specific queue.
The Base class of a Port.
Virtqueue * rx_q()
Getter for the receive queue.
Virtqueue * tx_q()
Getter for the transmission queue.
Class for VLAN packet rewriting.
void rewrite_hdr(Virtio_net::Hdr *hdr)
Rewrite the virtio network header.
l4_uint32_t copy_pkt(Buffer &dst, Buffer &src)
Copy packet from src to dst.
unsigned char l4_uint8_t
Unsigned 8bit value.
unsigned short int l4_uint16_t
Unsigned 16bit value.
unsigned long long l4_uint64_t
Unsigned 64bit value.
@ L4_EINVAL
Invalid argument.
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
#define L4_LIKELY(x)
Expression is likely to execute.
Data buffer used to transfer packets.
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.
l4_uint32_t left
Bytes left in buffer.
char * pos
Current buffer position.
l4_uint32_t skip(l4_uint32_t bytes)
Skip given number of bytes in this buffer.
bool done() const
Check if there are no more bytes left in the buffer.