10#include "virtio_net.h"
39 Delivered, Exception, Dropped,
58 Dbg trace(Dbg::Request, Dbg::Trace,
"REQ");
59 trace.printf(
"Transfer request: %p\n", request.header());
76 Buffer src = request.first_buffer();
81 std::vector<Consumed_entry> consumed;
85 Virtio_net::Hdr *dst_header =
nullptr;
97 trace.printf(
"\tTransfer failed, bad descriptor exception, dropping.\n");
100 if (!consumed.empty())
115 if (!dst_queue->
ready())
116 return Result::Dropped;
122 trace.printf(
"\tTransfer %p failed, destination queue depleted, dropping.\n",
125 if (!consumed.empty())
127 return Result::Dropped;
136 Dbg(Dbg::Request, Dbg::Warn,
"REQ")
137 .printf(
"%s: bad descriptor exception: %s - %i"
138 " -- signal device error in destination device %p.\n",
139 __PRETTY_FUNCTION__, e.
message(), e.error, dst_dev);
142 return Result::Exception;
147 if (dst.
left <
sizeof(Virtio_net::Hdr))
149 "Target buffer too small for header");
150 dst_header =
reinterpret_cast<Virtio_net::Hdr *
>(dst.
pos);
151 trace.printf(
"\t: Copying header to %p (size: %u)\n",
194 total =
sizeof(Virtio_net::Hdr);
195 memcpy(dst_header, request.header(), total);
202 bool has_dst_buffer = !dst.
done();
207 has_dst_buffer = dst_req_proc.
next(dst_dev->
mem_info(), &dst);
211 Dbg(Dbg::Request, Dbg::Warn,
"REQ")
212 .printf(
"%s: bad descriptor exception: %s - %i"
213 " -- signal device error in destination device %p.\n",
214 __PRETTY_FUNCTION__, e.
message(), e.error, dst_dev);
216 return Result::Exception;
221 trace.printf(
"\t: Copying %p#%p:%u (%x) -> %p#%p:%u (%x)\n",
231 trace.printf(
"\t: Saving descriptor for later\n");
232 consumed.push_back(Consumed_entry(dst_head, total));
247 trace.printf(
"\tTransfer %p - not started yet, dropping\n", request.header());
248 return Result::Dropped;
251 if (consumed.empty())
254 assert(num_merged == 1);
255 trace.printf(
"\tTransfer - Invoke dst_queue->finish()\n");
256 dst_header->num_buffers = 1;
257 dst_queue->
finish(dst_head, dst_dev, total);
262 dst_header->num_buffers = num_merged;
263 consumed.push_back(Consumed_entry(dst_head, total));
264 trace.printf(
"\tTransfer - Invoke dst_queue->finish(iter)\n");
265 dst_queue->
finish(consumed.begin(), consumed.end(), dst_dev);
268 return Result::Delivered;
Exception for an abstract runtime error.
void device_error()
Transition device into DEVICE_NEEDS_RESET state.
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.
Virtqueue implementation for the device.
Request next_avail()
Get the next available descriptor from the available ring.
void finish(Head_desc &d, QUEUE_OBSERVER *o, l4_uint32_t len=0)
Add a descriptor to the used ring, and notify an observer.
void rewind_avail(Head_desc const &d)
Return unfinished descriptors to the available ring, i.e.
bool ready() const
Test if this queue is in working state.
Abstraction for a network request.
A network request to only a single destination.
static Result transfer(Virtio_net_request const &request, Virtio_net *dst_dev, L4virtio::Svr::Virtqueue *dst_queue, Virtio_vlan_mangle &mangle)
Deliver the request to the destination port.
The Base class of a Port.
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 short int l4_uint16_t
Unsigned 16bit value.
@ L4_EINVAL
Invalid argument.
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Data buffer used to transfer packets.
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.