Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
51 changes: 45 additions & 6 deletions examples/firewall/net_components/firewall_network_virt_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ net_queue_handle_t tx_queue_clients[SDDF_NET_MAX_CLIENTS];
fw_queue_t fw_free_clients[FW_MAX_FW_CLIENTS];
fw_queue_t fw_active_clients[FW_MAX_FW_CLIENTS];

/* Alternates which of the net/fw client groups tx_provide() will serve first, to
prevent starvation on tx_queue_drv. */
bool fw_clients_priority = false;

static int extract_offset_net_client(uintptr_t *phys)
{
for (int client = 0; client < config.num_clients; client++) {
Expand All @@ -48,13 +52,19 @@ static int extract_offset_fw_client(uintptr_t *phys)
return -1;
}

static void tx_provide(void)
/* sdfgen sizes tx_queue_drv for the net clients only, not the firewall
clients also feeding it, so fullness must be checked before every enqueue. */
static void tx_provide_net_clients(bool *enqueued, bool *drv_full)
{
bool enqueued = false;
for (int client = 0; client < config.num_clients; client++) {
for (int client = 0; client < config.num_clients && !*drv_full; client++) {
bool reprocess = true;
while (reprocess) {
while (!net_queue_empty_active(&tx_queue_clients[client])) {
if (net_queue_full_active(&tx_queue_drv)) {
*drv_full = true;
break;
}

net_buff_desc_t buffer;
int err = net_dequeue_active(&tx_queue_clients[client], &buffer);
assert(!err);
Expand All @@ -75,7 +85,11 @@ static void tx_provide(void)

err = net_enqueue_active(&tx_queue_drv, buffer);
assert(!err);
enqueued = true;
*enqueued = true;
}

if (*drv_full) {
break;
}

net_request_signal_active(&tx_queue_clients[client]);
Expand All @@ -87,9 +101,19 @@ static void tx_provide(void)
}
}
}
}

for (int client = 0; client < fw_config.num_active_clients; client++) {
static void tx_provide_fw_clients(bool *enqueued, bool *drv_full)
{
for (int client = 0; client < fw_config.num_active_clients && !*drv_full; client++) {
while (!fw_queue_empty(&fw_active_clients[client])) {
if (net_queue_full_active(&tx_queue_drv)) {
/* Leave remaining buffers queued rather than dropping them;
picked up on the next tx_provide() once tx_return() frees space. */
*drv_full = true;
break;
}

fw_buff_desc_t buffer;
int err = fw_dequeue(&fw_active_clients[client], &buffer);
assert(!err);
Expand All @@ -105,9 +129,24 @@ static void tx_provide(void)
net_buff_desc_t net_buffer = { .io_or_offset = io_addr, .len = buffer.len };
err = net_enqueue_active(&tx_queue_drv, net_buffer);
assert(!err);
enqueued = true;
*enqueued = true;
}
}
}

static void tx_provide(void)
{
bool enqueued = false;
bool drv_full = false;

if (fw_clients_priority) {
tx_provide_fw_clients(&enqueued, &drv_full);
tx_provide_net_clients(&enqueued, &drv_full);
} else {
tx_provide_net_clients(&enqueued, &drv_full);
tx_provide_fw_clients(&enqueued, &drv_full);
}
fw_clients_priority = !fw_clients_priority;

if (enqueued && net_require_signal_active(&tx_queue_drv)) {
net_cancel_signal_active(&tx_queue_drv);
Expand Down
35 changes: 32 additions & 3 deletions examples/firewall/routing/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,20 @@ static bool enqueue_icmp_unreachable(fw_buff_desc_t buffer, uint32_t next_hop)
return enqueued;
}

static void transmit_packet(fw_buff_desc_t buffer, uint8_t *mac_addr, uint8_t out_interface)
static void drop_buffer(fw_buff_desc_t buffer)
{
net_buff_desc_t net_buff = { .io_or_offset = buffer.offset, .len = buffer.len };
int err = fw_enqueue(&rx_free[buffer.interface], &net_buff);
assert(!err);
returned[buffer.interface] = true;
}

static bool transmit_packet(fw_buff_desc_t buffer, uint8_t *mac_addr, uint8_t out_interface)
{
if (fw_queue_full(&tx_active[out_interface])) {
return false;
}

uintptr_t pkt_vaddr = data_vaddr[buffer.interface] + buffer.offset;
eth_hdr_t *eth_hdr = (eth_hdr_t *)pkt_vaddr;
ipv4_hdr_t *ip_hdr = (ipv4_hdr_t *)(pkt_vaddr + IPV4_HDR_OFFSET);
Expand All @@ -103,6 +115,7 @@ static void transmit_packet(fw_buff_desc_t buffer, uint8_t *mac_addr, uint8_t ou
int err = fw_enqueue(&tx_active[out_interface], &buffer);
assert(!err);
tx_net[out_interface] = true;
return true;
}

static void process_arp_waiting(uint8_t out_interface)
Expand Down Expand Up @@ -143,7 +156,11 @@ static void process_arp_waiting(uint8_t out_interface)
/* Substitute the MAC address and send packets out of the NIC */
pkt_waiting_node_t *node = root;
for (uint16_t i = 0; i < root->num_children + 1; i++) {
transmit_packet(node->buffer, response.mac_addr, out_interface);
bool sent = transmit_packet(node->buffer, response.mac_addr, out_interface);
if (!sent) {
LOG_FIREWALL("ROUTING", "tx queue for interface %u full, dropping packet\n", out_interface);
drop_buffer(node->buffer);
}
node = pkts_waiting_next_child(&pkt_waiting_queue[out_interface], node);
}
}
Expand Down Expand Up @@ -196,6 +213,14 @@ static void route(void)
/* Check for webserver traffic */
tcp_hdr_t *tcp_pkt = (tcp_hdr_t *)(pkt_vaddr + transport_layer_offset(ip_hdr));
if (ip_hdr->protocol == IPV4_PROTO_TCP && tcp_pkt->dst_port == htons(WEBSERVER_PORT)) {
if (fw_queue_full(&webserver)) {
/* Webserver queue can receive buffers from any interface */
LOG_FIREWALL("ROUTING", "webserver queue full, dropping packet from interface %u\n",
interface);
drop_buffer(fw_buffer);
continue;
}

err = fw_enqueue(&webserver, &fw_buffer);
assert(!err);
tx_webserver = true;
Expand Down Expand Up @@ -303,7 +328,11 @@ static void route(void)
}

/* valid arp entry found, transmit packet */
transmit_packet(fw_buffer, arp->mac_addr, out_interface);
bool sent = transmit_packet(fw_buffer, arp->mac_addr, out_interface);
if (!sent) {
LOG_FIREWALL("ROUTING", "tx queue for interface %u full, dropping packet\n", out_interface);
drop_buffer(fw_buffer);
}
}
}
}
Expand Down
Loading