Loading...
Searching...
No Matches
vlan.h
/*
* Copyright (C) 2020, 2022-2024 Kernkonzept GmbH.
* Author(s): Jan Klötzke <jan.kloetzke@kernkonzept.com>
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
#include <l4/cxx/minmax>
#include <l4/l4virtio/server/virtio>
#include <l4/sys/types.h>
#include <string.h>
#include "virtio_net.h"
#include "virtio_net_buffer.h"
namespace {
const l4_uint16_t VLAN_ID_NATIVE = 0xffffU;
const l4_uint16_t VLAN_ID_TRUNK = 0xfffeU;
inline bool vlan_valid_id(l4_uint16_t id)
{
return id > 0U && id < 0xfffU;
}
}
class Virtio_vlan_mangle
{
l4_uint16_t _tci;
l4_uint8_t _mac_remaining;
l4_int8_t _tag_remaining;
constexpr Virtio_vlan_mangle(l4_uint16_t tci, l4_int8_t tag_remaining)
: _tci{tci}, _mac_remaining{12}, _tag_remaining{tag_remaining}
{}
public:
Virtio_vlan_mangle()
: _tci{0}, _mac_remaining{0}, _tag_remaining{0}
{}
static constexpr Virtio_vlan_mangle add(l4_uint16_t tci)
{
return Virtio_vlan_mangle(tci, 4);
}
static constexpr Virtio_vlan_mangle remove()
{
return Virtio_vlan_mangle(0xffffU, -4);
}
l4_uint32_t copy_pkt(Buffer &dst, Buffer &src)
{
l4_uint32_t ret;
if (L4_LIKELY(_tci == 0))
{
// pass through (no tag or keep tag)
ret = src.copy_to(&dst);
}
else if (_mac_remaining)
{
// copy initial MAC addresses
ret = src.copy_to(&dst, _mac_remaining);
_mac_remaining -= ret;
}
else if (_tag_remaining > 0)
{
// add VLAN tag
l4_uint8_t tag[4] = {
0x81, 0x00,
static_cast< l4_uint8_t >(_tci >> 8),
static_cast< l4_uint8_t >(_tci & 0xffU)
};
ret = cxx::min(static_cast< l4_uint32_t >(_tag_remaining), dst.left);
memcpy(dst.pos, &tag[4 - _tag_remaining], ret);
dst.skip(ret);
_tag_remaining -= (int)ret;
}
else if (_tag_remaining < 0)
{
// remove VLAN tag
_tag_remaining += static_cast<int>(src.skip(-_tag_remaining));
ret = 0;
}
else
ret = src.copy_to(&dst);
return ret;
}
void rewrite_hdr(Virtio_net::Hdr *hdr)
{
if (L4_UNLIKELY(_tci != 0 && hdr->flags.need_csum()))
{
if (_tci == 0xffffU)
hdr->csum_start -= 4U;
else
hdr->csum_start += 4U;
}
}
};
Virtio_vlan_mangle::remove
static constexpr Virtio_vlan_mangle remove()
Construct an object that removes the VLAN tag.
Definition vlan.h:75
Virtio_vlan_mangle::rewrite_hdr
void rewrite_hdr(Virtio_net::Hdr *hdr)
Rewrite the virtio network header.
Definition vlan.h:142
Virtio_vlan_mangle::Virtio_vlan_mangle
Virtio_vlan_mangle()
Default constructor.
Definition vlan.h:52
Virtio_vlan_mangle::add
static constexpr Virtio_vlan_mangle add(l4_uint16_t tci)
Construct an object that adds a VLAN tag.
Definition vlan.h:64
Virtio_vlan_mangle::copy_pkt
l4_uint32_t copy_pkt(Buffer &dst, Buffer &src)
Copy packet from src to dst.
Definition vlan.h:93
l4_uint8_t
unsigned char l4_uint8_t
Unsigned 8bit value.
Definition l4int.h:25
l4_int8_t
signed char l4_int8_t
Signed 8bit value.
Definition l4int.h:24
l4_uint32_t
unsigned int l4_uint32_t
Unsigned 32bit value.
Definition l4int.h:29
l4_uint16_t
unsigned short int l4_uint16_t
Unsigned 16bit value.
Definition l4int.h:27
L4_UNLIKELY
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:284
L4_LIKELY
#define L4_LIKELY(x)
Expression is likely to execute.
Definition compiler.h:283
types.h
Common L4 ABI Data Types.
string.h
String.
Buffer
Data buffer used to transfer packets.
Definition virtio_net_buffer.h:20
L4virtio::Svr::Data_buffer::copy_to
l4_uint32_t copy_to(Data_buffer *dst, l4_uint32_t max=UINT_MAX)
Copy contents from this buffer to the destination buffer.
Definition virtio:354
L4virtio::Svr::Data_buffer::left
l4_uint32_t left
Bytes left in buffer.
Definition virtio:309
L4virtio::Svr::Data_buffer::pos
char * pos
Current buffer position.
Definition virtio:308
L4virtio::Svr::Data_buffer::skip
l4_uint32_t skip(l4_uint32_t bytes)
Skip given number of bytes in this buffer.
Definition virtio:375