9#include <l4/l4virtio/server/virtio>
12#include "virtio_net_buffer.h"
13#include "virtio_net.h"
55 Virtio_net::Hdr *_header;
58 bool _next_buffer(
Buffer *buf)
69 if (_queue ==
nullptr || !_queue->
ready())
72 Dbg(Dbg::Virtio, Dbg::Trace).printf(
"%s(%p)\n", __PRETTY_FUNCTION__,
this);
73 _queue->
finish(_head, _dev, 0);
90 const uint8_t *
buffer(
size_t *size)
const
93 return (uint8_t *)_pkt.
pos;
98 uint8_t *packet = (uint8_t *)_pkt.
pos;
99 Dbg debug(Dbg::Request, Dbg::Debug,
"REQ");
100 if (debug.is_active())
102 debug.printf(
"%p: Next packet: %p:%p - %x bytes\n",
103 dev, _header, packet, _pkt.
left);
104 if (_header->flags.raw || _header->gso_type)
106 debug.cprintf(
"flags:\t%x\n\t"
108 "header len:\t%x\n\t"
110 "csum start:\t%x\n\t"
112 "\tnum buffer:\t%x\n",
114 _header->gso_type, _header->hdr_len,
116 _header->csum_start, _header->csum_offset,
117 _header->num_buffers);
120 Dbg pkt_debug(Dbg::Packet, Dbg::Debug,
"PKT");
121 if (pkt_debug.is_active())
123 pkt_debug.cprintf(
"\t");
125 pkt_debug.cprintf(
" -> ");
127 pkt_debug.cprintf(
"\n");
128 if (Dbg::is_active(Dbg::Packet, Dbg::Trace))
130 pkt_debug.cprintf(
"\n\tEthertype: ");
131 uint16_t ether_type = (uint16_t)*(packet + 12) << 8
132 | (uint16_t)*(packet + 13);
133 char const *protocol;
136 case 0x0800: protocol =
"IPv4";
break;
137 case 0x0806: protocol =
"ARP";
break;
138 case 0x8100: protocol =
"Vlan";
break;
139 case 0x86dd: protocol =
"IPv6";
break;
140 case 0x8863: protocol =
"PPPoE Discovery";
break;
141 case 0x8864: protocol =
"PPPoE Session";
break;
142 default: protocol =
nullptr;
145 pkt_debug.cprintf(
"%s\n", protocol);
147 pkt_debug.cprintf(
"%04x\n", ether_type);
159 _queue(other._queue),
160 _head(std::move(other._head)),
161 _req_proc(std::move(other._req_proc)),
162 _header(other._header),
163 _pkt(std::move(other._pkt))
167 other._queue =
nullptr;
176 _queue = other._queue;
177 _head = std::move(other._head);
178 _req_proc = std::move(other._req_proc);
179 _header = other._header;
180 _pkt = std::move(other._pkt);
183 other._queue =
nullptr;
189 L4virtio::Svr::Virtqueue::Request
const &req)
190 : _dev(dev), _queue(queue)
194 _header = (Virtio_net::Hdr *)_pkt.
pos;
197 if (
L4_UNLIKELY( (skipped !=
sizeof(Virtio_net::Hdr))
198 || (_pkt.
done() && !_next_buffer(&_pkt))))
201 Dbg(Dbg::Queue, Dbg::Warn).printf(
"Invalid request\n");
210 {
return _header != 0; }
229 Dbg(Dbg::Request, Dbg::Debug)
230 .printf(
"Dropping incoming packets on monitor port\n");
238 queue->
finish(head, dev, 0);
248 static std::optional<Virtio_net_request>
265 request.dump_request(dev);
272 Buffer const &first_buffer()
const
275 Virtio_net::Hdr
const *header()
const
281 return (_pkt.
pos && _pkt.
left >= Mac_addr::Addr_length)
289 return (_pkt.
pos && _pkt.
left >= Mac_addr::Addr_length * 2)
294 bool has_vlan()
const
296 if (!_pkt.
pos || _pkt.
left < 14)
299 uint8_t *p =
reinterpret_cast<uint8_t*
>(_pkt.
pos);
300 return p[12] == 0x81U && p[13] == 0x00U;
303 uint16_t vlan_id()
const
305 if (!has_vlan() || _pkt.
left < 16)
306 return VLAN_ID_NATIVE;
308 uint8_t *p =
reinterpret_cast<uint8_t*
>(_pkt.
pos);
309 return ((uint16_t)p[14] << 8 | (uint16_t)p[15]) & 0xfffU;
313 {
return _req_proc; }
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.
bool desc_avail() const
Test for available descriptors.
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.
bool ready() const
Test if this queue is in working state.
A wrapper class around the value of a MAC address.
Abstraction for a network request.
const uint8_t * buffer(size_t *size) const
Get the location and size of the current buffer.
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.
Mac_addr src_mac() const
Get the Mac address of the source port.
Mac_addr dst_mac() const
Get the Mac address of the destination port.
The Base class of a Port.
unsigned int l4_uint32_t
Unsigned 32bit value.
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Data buffer used to transfer packets.
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.
Some useful assert-style macros.