Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
ee2daf8
network: port vswitch from alexandermbrown
JDuchniewicz Jan 29, 2026
bdfb708
vswitch: adapt to new microkit
JDuchniewicz Feb 12, 2026
ee1664c
vswitch: Design the config structure
JDuchniewicz Feb 12, 2026
1dd43b1
vswitch: flesh out sending
JDuchniewicz Feb 24, 2026
f485b5f
vswitch: first implementation
JDuchniewicz Feb 24, 2026
d8bac98
vswitch: fixup rx and tx, minor vswitch fixes
JDuchniewicz Feb 25, 2026
36dd5b0
vswitch: fixups for compilation
JDuchniewicz Feb 27, 2026
b00e56b
vswitch: Makefile fixes
JDuchniewicz Mar 1, 2026
0561e6d
vswitch: debugging and small fixes
JDuchniewicz Mar 4, 2026
b6a0f41
vswitch: add copiers having mappings to other pds
JDuchniewicz Mar 19, 2026
4692785
vswitch: Fix wrong default port. virt buf.oid stamping
JDuchniewicz Mar 23, 2026
f29adf0
ubsan: fix wrong cast
JDuchniewicz Mar 23, 2026
becb77c
vswitch: add logs to eth driver
JDuchniewicz Mar 25, 2026
c3cd650
vswitch: cleanup logs
JDuchniewicz Mar 30, 2026
907d496
vswitch: cleanup
JDuchniewicz Mar 30, 2026
4caaa06
style: lint
JDuchniewicz Mar 30, 2026
1a06d68
address review comments
JDuchniewicz Mar 30, 2026
e2e88d7
vswitch: fix up naming
JDuchniewicz Mar 30, 2026
fe15135
vswitch: drop packets when client's queues are full
JDuchniewicz Mar 30, 2026
ef8c0c0
vswitch: remove multiple MACs scaffoling
JDuchniewicz Mar 31, 2026
42e0775
vswitch: remove hardcoded buffer size
JDuchniewicz Apr 2, 2026
0bbef98
vswitch: address some review comments
JDuchniewicz Apr 13, 2026
00123af
vswitch: more review remarks
JDuchniewicz Apr 13, 2026
43c70ef
vswitch: change to num_ports instead of hardcode
JDuchniewicz Apr 13, 2026
05294bd
vswitch: batch signalling
JDuchniewicz Apr 14, 2026
a87c1e6
vswitch: add assertions and debug checks
JDuchniewicz Apr 14, 2026
cb82141
vswitch: add ACL support
JDuchniewicz Apr 15, 2026
9e46e68
vswitch: address review comments
JDuchniewicz Apr 15, 2026
1743581
vswitch: fix wrong buffer sizes assumption
JDuchniewicz Apr 15, 2026
9cc9576
vswitch: Prevent flooding the clients with packets
JDuchniewicz Apr 15, 2026
bc635eb
vswitch: Drop packet if no virt connected and cannot match any port
JDuchniewicz Apr 15, 2026
dc0174d
vswitch: style fixes
JDuchniewicz Apr 16, 2026
62d7e5a
vswitch: add checksum zeroing for DHCP packets
JDuchniewicz Apr 16, 2026
ad0eb25
vswitch: build fix
JDuchniewicz Apr 16, 2026
794985b
vswitch: add more robust checksum clearing for all protocols
JDuchniewicz Apr 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 47 additions & 11 deletions include/sddf/network/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <stdint.h>
#include <sddf/resources/common.h>
#include <sddf/resources/device.h>
#include <sddf/network/mac802.h>

#define SDDF_NET_MAX_CLIENTS 64

Expand All @@ -29,9 +30,15 @@ typedef struct net_driver_config {
net_connection_resource_t virt_tx;
} net_driver_config_t;

typedef struct net_virt_tx_data_region {
device_region_resource_t data;
uint32_t num_buffers;
} net_virt_tx_data_region_t;

typedef struct net_virt_tx_client_config {
net_connection_resource_t conn;
device_region_resource_t data;
net_virt_tx_data_region_t regions[SDDF_NET_MAX_CLIENTS];
uint8_t num_regions;
} net_virt_tx_client_config_t;

typedef struct net_virt_tx_config {
Expand All @@ -41,27 +48,31 @@ typedef struct net_virt_tx_config {
uint8_t num_clients;
} net_virt_tx_config_t;

typedef struct net_virt_rx_config_client {
typedef struct net_virt_rx_client_config {
net_connection_resource_t conn;
uint8_t mac_addr[6];
} net_virt_rx_config_client_t;
mac_addr_t mac_addrs[SDDF_NET_MAX_CLIENTS];
uint8_t num_macs;
} net_virt_rx_client_config_t;

typedef struct net_virt_rx_config {
char magic[SDDF_NET_MAGIC_LEN];
net_connection_resource_t driver;
device_region_resource_t data;
// The system designer must allocate a buffer metadata region for internal
// use by the RX virtualiser. The size of this region must be at least
// 4*drv_queue_capacity. It must be mapped R-W and zero-initialised.
// The Rx virtualiser uses a reference count system to keep track of buffer ownership.
// This is particularly important when a buffer is broadcast to multiple clients,
// as the buffer can only be safely returned to the driver for re-use once it has been freed by all clients.
// These reference counts are stored in the buffer_metadata region,
// thus the region must be large enough to store a count for each Rx DMA buffer in the system
// (i.e. >= sizeof(uint8_t) * drv_queue_capacity bytes). It must also be mapped R-W and zero-initialised.
region_resource_t buffer_metadata;
net_virt_rx_config_client_t clients[SDDF_NET_MAX_CLIENTS];
net_virt_rx_client_config_t clients[SDDF_NET_MAX_CLIENTS];
uint8_t num_clients;
} net_virt_rx_config_t;

typedef struct net_copy_config {
char magic[SDDF_NET_MAGIC_LEN];
net_connection_resource_t virt_rx;
region_resource_t device_data;
net_connection_resource_t rx;
region_resource_t rx_data[SDDF_NET_MAX_CLIENTS];

net_connection_resource_t client;
region_resource_t client_data;
Expand All @@ -75,9 +86,34 @@ typedef struct net_client_config {
net_connection_resource_t tx;
region_resource_t tx_data;

uint8_t mac_addr[6];
mac_addr_t mac_addr;
} net_client_config_t;

typedef struct net_vswitch_port_config {
net_connection_resource_t rx;
net_connection_resource_t tx;
device_region_resource_t tx_data;
/* unused for the virts */
mac_addr_t mac_addr;
uint64_t acl;
} net_vswitch_port_config_t;

typedef struct net_vswitch_config {
char magic[SDDF_NET_MAGIC_LEN];

/* The first num_ports entries in this array are the vswitch's clients.
* The next port after the last client, index num_ports contains the vswitch's connection with the virtualisers.
* However, the rx field is the connection with Tx virtualiser, and the tx field is the connection with the Rx virtualiser.
* This allows the vswitch to treat the virtualiser the same way as it's other clients. */
net_vswitch_port_config_t ports[SDDF_NET_MAX_CLIENTS];
uint8_t num_ports;

// Reference counting buffers; The system designer must allocate a buffer big enough to contain reference counters for buffers.
// The size of this region must be equal to at least num_ports * number_of_buffers_per_port * sizeof(uint8_t).
// It must be mapped R-W and zero-initialised.
region_resource_t buffer_metadata;
} net_vswitch_config_t;

static inline bool net_config_check_magic(void *config)
{
char *magic = (char *)config;
Expand Down
12 changes: 0 additions & 12 deletions include/sddf/network/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,8 @@
#include <os/sddf.h>
#include <stdint.h>

#define ETH_HWADDR_LEN 6

#define NET_BUFFER_SIZE 2048

struct ethernet_address {
uint8_t addr[6];
} __attribute__((packed));

struct ethernet_header {
struct ethernet_address dest;
struct ethernet_address src;
uint16_t type;
} __attribute__((packed));

/*
* By default we assume that the hardware we are dealing with
* cannot generate checksums on transmit. We use this macro
Expand Down
22 changes: 22 additions & 0 deletions include/sddf/network/icmp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2025, UNSW
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <stdint.h>

/* ----------------- ICMP Protocol Definitions ---------------------------*/

/* Shared ICMP header prefix accross all control types */
typedef struct __attribute__((__packed__)) icmp_hdr {
/* ICMP type */
uint8_t type;
/* ICMP sub-type */
uint8_t code;
/* internet checksum calculated over ICMP header and data */
uint16_t check;
/* The following 4 bytes of the header are ICMP type dependent */
} icmp_hdr_t;
64 changes: 64 additions & 0 deletions include/sddf/network/ip.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2026, UNSW
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <stdint.h>

typedef struct __attribute__((__packed__)) ipv4_hdr {
/* internet header length in 32-bit words, variable due to optional fields */
uint8_t ihl : 4;
/* IP version, always 4 for IPv4 */
uint8_t version : 4;
/* explicit congestion notification, optional */
uint8_t ecn : 2;
/* differentiated services code point */
uint8_t dscp : 6;
/* total packet length in bytes, including header and data */
uint16_t tot_len;
/* identifier of packet, used in packet fragmentation */
uint16_t id;
/* offset in 8 bytes of fragment relative to the beginning of the original
unfragmented IP datagram. Fragment offset is a 13 byte value split accross
frag_offset1 and frag_offset2 */
uint8_t frag_offset1 : 5;
/* if packet belongs to fragmented group, 1 indicates this is not the last
fragment */
uint8_t more_frag : 1;
/* specifies whether datagram can be fragmented or not */
uint8_t no_frag : 1;
/* reserved, set to 0 */
uint8_t reserved : 1;
/* offset in 8 bytes of fragment relative to the beginning of the original
unfragmented IP datagram. Fragment offset is a 13 byte value split accross
frag_offset1 and frag_offset2 */
uint8_t frag_offset2;
/* time to live, in seconds but in practice router hops */
uint8_t ttl;
/* transport layer protocol of encapsulated packet */
uint8_t protocol;
/* internet checksum of IPv4 header */
uint16_t check;
/* source IP address */
uint32_t src_ip;
/* destination IP address */
uint32_t dst_ip;
/* optional fields excluded */
} ipv4_hdr_t;

/* Offset of the start of the IPV4 header */
#define IPV4_HDR_OFFSET ETH_HDR_LEN

/* Length of IPv4 header with no optional fields */
#define IPV4_HDR_LEN_MIN sizeof(ipv4_hdr_t)

/* IPv4 differentiated services code point values */
#define IPV4_DSCP_NET_CTRL 48 /* Network control */

/* IPv4 transport layer protocols */
#define IPV4_PROTO_ICMP 0x01
#define IPV4_PROTO_TCP 0x06
#define IPV4_PROTO_UDP 0x11
58 changes: 58 additions & 0 deletions include/sddf/network/mac802.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2026, UNSW
*
* SPDX-License-Identifier: BSD-2-Clause
*/
Comment thread
JDuchniewicz marked this conversation as resolved.

#pragma once

#include <stdint.h>
#include <sddf/util/printf.h>

#define PR_MAC802_ADDR "%x:%x:%x:%x:%x:%x"

/* Expects a *pointer* to a struct ether_hdr */
#define PR_MAC802_ADDR_ARGS(a, dir) (a)->##dir##->addr[0], \
(a)->##dir##->addr[1], \
(a)->##dir##->addr[2], \
(a)->##dir##->addr[3], \
(a)->##dir##->addr[4], \
(a)->##dir##->addr[5]

#define PR_MAC802_DEST_ADDR_ARGS(a) PR_MAC802_ADDR_ARGS(a, dest)
#define PR_MAC802_SRC_ADDR_ARGS(a) PR_MAC802_ADDR_ARGS(a, src)

#define MAC802_BYTES 6
#define ETH_TYPE_IP 0x0800U

typedef struct mac_addr {
uint8_t addr[MAC802_BYTES];
} mac_addr_t;

/* Ethernet packet header */
typedef struct ether_hdr {
mac_addr_t dest;
mac_addr_t src;
uint8_t etype[2]; // Ethertype
} __attribute__((__packed__)) ether_hdr_t;

static inline bool mac802_addr_eq_num(const uint8_t *addr0, const uint8_t *addr1, unsigned int num)
{
for (int i = 0; i < num; i++) {
if (addr0[i] != addr1[i]) {
return false;
}
}
return true;
}

static inline bool mac802_addr_eq(const uint8_t *addr0, const uint8_t *addr1)
{
return mac802_addr_eq_num(addr0, addr1, MAC802_BYTES);
}

static inline bool mac802_addr_is_bcast(const uint8_t *addr)
{
const uint8_t bcast_macaddr[MAC802_BYTES] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
return mac802_addr_eq(addr, bcast_macaddr);
}
13 changes: 12 additions & 1 deletion include/sddf/network/queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ typedef struct net_buff_desc {
uint64_t io_or_offset;
/* length of data inside buffer */
uint16_t len;
/* id of the PD which owns this buffer, and thus which memory region the buffer belongs to.
* Used for extracting virtual/physical addresses and for returning buffers to the correct PD.
* This field is required in cases where a queue holds buffers belonging to multiple memory regions,
* and the memory region source cannot be identified otherwise.
* This scenario arises in systems containing a vswitch - in particular in queues shared between the copiers and vswitch,
* as well as the vswitch and Tx virtualiser.
* The field is ignored by the Rx virtualiser and Ethernet drivers, and should be set to 0 by net clients */
uint8_t oid : 6;
} net_buff_desc_t;

typedef struct net_queue {
Expand Down Expand Up @@ -216,7 +224,10 @@ static inline void net_queue_init(net_queue_handle_t *queue, net_queue_t *free,
static inline void net_buffers_init(net_queue_handle_t *queue, uintptr_t base_addr)
{
for (uint32_t i = 0; i < queue->capacity; i++) {
net_buff_desc_t buffer = {(NET_BUFFER_SIZE * i) + base_addr, 0};
net_buff_desc_t buffer = {
(NET_BUFFER_SIZE * i) + base_addr,
0,
};
int err = net_enqueue_free(queue, buffer);
assert(!err);
}
Expand Down
49 changes: 49 additions & 0 deletions include/sddf/network/tcp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2025, UNSW
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <stdint.h>

/* ----------------- TCP Protocol Definitions ---------------------------*/

typedef struct __attribute__((__packed__)) tcp_hdr {
/* source port */
uint16_t src_port;
/* destination port */
uint16_t dst_port;
/* sequence number */
uint32_t seq;
/* acknowledgement number */
uint32_t ack_seq;
/* reserved, set to 0 */
uint16_t reserved : 4;
/* size of the TCP header in 32 bit words */
uint16_t doff : 4;
/* fin */
uint16_t fin : 1;
/* syn */
uint16_t syn : 1;
/* reset */
uint16_t rst : 1;
/* push */
uint16_t psh : 1;
/* ack */
uint16_t ack : 1;
/* urgent pointer is valid */
uint16_t urg : 1;
/* ECN-Echo*/
uint16_t ece : 1;
/* congestion window reduced */
uint16_t cwr : 1;
/* size of the receive window*/
uint16_t window;
/* checksum over the TCP packet and psuedo-header */
uint16_t check;
/* urgent pointer */
uint16_t urg_ptr;
/* optional fields excluded */
} tcp_hdr_t;
22 changes: 22 additions & 0 deletions include/sddf/network/udp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2025, UNSW
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <stdint.h>

/* ----------------- UDP Protocol Definitions ---------------------------*/

typedef struct __attribute__((__packed__)) udp_hdr {
/* source port */
uint16_t src_port;
/* destination port */
uint16_t dst_port;
/* length in bytes of the UDP datagram including header */
uint16_t len;
/* checksum over the UDP datagram and psuedo-header, optional for IPv4 */
uint16_t check;
} udp_hdr_t;
5 changes: 5 additions & 0 deletions network/components/arp.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
#include <sddf/util/printf.h>
#include <ethernet_config.h>

#define ETH_TYPE_ARP 0x0806U
#define ETHARP_OPCODE_REQUEST 1
#define ETHARP_OPCODE_REPLY 2
#define ETH_HWADDR_LEN 6

#define RX_CH 0
#define TX_CH 1
#define CLIENT_CH 2
Expand Down
Loading
Loading