Skip to content

Commit

Permalink
l4: add udp port handler
Browse files Browse the repository at this point in the history
For VxLan tunnels, we need to register a specific destination udp port.

Add a new node and api, and push all non-handled packets back
to the management (loopback) interface, as done today.

Signed-off-by: Christophe Fontaine <[email protected]>
  • Loading branch information
christophefontaine authored and rjarry committed Jan 15, 2025
1 parent cdfe435 commit 1d6f86a
Show file tree
Hide file tree
Showing 6 changed files with 456 additions and 422 deletions.
520 changes: 248 additions & 272 deletions docs/graph.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions modules/l4/gr_l4.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024 Christophe Fontaine

#ifndef _GR_L4_H
#define _GR_L4_H

#include <rte_byteorder.h>

#include <stdint.h>

void l4_input_register_port(uint8_t proto, rte_be16_t port, const char *next_node);

#endif
96 changes: 96 additions & 0 deletions modules/l4/l4_input_local.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024 Christophe Fontaine

#include "gr_l4.h"

#include <gr_datapath.h>
#include <gr_graph.h>
#include <gr_ip4_datapath.h>
#include <gr_ip6_datapath.h>
#include <gr_log.h>
#include <gr_port.h>
#include <gr_trace.h>

#include <rte_graph_worker.h>
#include <rte_ip.h>
#include <rte_mbuf.h>

enum edges {
MANAGEMENT = 0,
BAD_PROTO,
EDGE_COUNT,
};

static rte_edge_t udp_edges[65536] = {MANAGEMENT};

void l4_input_register_port(uint8_t proto, rte_be16_t port, const char *next_node) {
LOG(DEBUG, "l4_input_register_port: proto=%hhu port=%hu-> %s", proto, port, next_node);
switch (proto) {
case IPPROTO_UDP:
if (udp_edges[port] != MANAGEMENT)
ABORT("next node already registered for udp port=%hhu", port);
udp_edges[proto] = gr_node_attach_parent("ip_input_local", next_node);
gr_node_attach_parent("ip6_input_local", next_node);
break;
default:
ABORT("proto not supported %hhu", proto);
}
}

static uint16_t l4_input_local_process(
struct rte_graph *graph,
struct rte_node *node,
void **objs,
uint16_t nb_objs
) {
struct rte_udp_hdr *hdr;
struct rte_mbuf *mbuf;
rte_edge_t edge;
uint8_t proto;

for (uint16_t i = 0; i < nb_objs; i++) {
mbuf = objs[i];
edge = BAD_PROTO;

if (mbuf->packet_type & RTE_PTYPE_L3_IPV4)
proto = ip_local_mbuf_data(mbuf)->proto;
else if (mbuf->packet_type & RTE_PTYPE_L3_IPV6)
proto = ip6_local_mbuf_data(mbuf)->proto;
else
goto next;

if (proto != IPPROTO_UDP) {
edge = MANAGEMENT;
goto next;
}

hdr = rte_pktmbuf_mtod(mbuf, struct rte_udp_hdr *);
edge = udp_edges[hdr->dst_port];
next:
rte_node_enqueue_x1(graph, node, edge, mbuf);
}
return nb_objs;
}

static void l4_input_local_register(void) {
ip_input_local_add_proto(IPPROTO_UDP, "l4_input_local");
ip_input_local_add_proto(IPPROTO_TCP, "l4_input_local");
ip6_input_local_add_proto(IPPROTO_UDP, "l4_input_local");
ip6_input_local_add_proto(IPPROTO_TCP, "l4_input_local");
}
static struct rte_node_register input_node = {
.name = "l4_input_local",
.process = l4_input_local_process,
.nb_edges = EDGE_COUNT,
.next_nodes = {
[MANAGEMENT] = "l4_loopback_output",
[BAD_PROTO] = "l4_bad_proto",
},
};

static struct gr_node_info info = {
.node = &input_node,
.register_callback = l4_input_local_register,
};

GR_NODE_REGISTER(info);
97 changes: 97 additions & 0 deletions modules/l4/l4_loopback_output.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024 Christophe Fontaine

#include <gr_datapath.h>
#include <gr_graph.h>
#include <gr_ip4_datapath.h>
#include <gr_ip6_datapath.h>
#include <gr_log.h>
#include <gr_port.h>
#include <gr_trace.h>

#include <rte_graph_worker.h>
#include <rte_ip.h>
#include <rte_mbuf.h>

enum edges {
REDIRECT = 0,
NO_IFACE,
BAD_PROTO,
NO_HEADROOM,
EDGE_COUNT,
};

static uint16_t l4_loopback_output_process(
struct rte_graph *graph,
struct rte_node *node,
void **objs,
uint16_t nb_objs
) {
struct rte_mbuf *mbuf;
struct mbuf_data *d;
rte_edge_t edge;

for (uint16_t i = 0; i < nb_objs; i++) {
mbuf = objs[i];
edge = REDIRECT;

d = mbuf_data(mbuf);
d->iface = get_vrf_iface(d->iface->vrf_id);
if (!d->iface) {
edge = NO_IFACE;
goto next;
}

if (mbuf->packet_type & RTE_PTYPE_L3_IPV4) {
struct ip_local_mbuf_data *d = ip_local_mbuf_data(mbuf);
struct rte_ipv4_hdr *ip;
ip = (struct rte_ipv4_hdr *)rte_pktmbuf_prepend(mbuf, sizeof(*ip));
if (ip == NULL) {
edge = NO_HEADROOM;
goto next;
}
ip_set_fields(ip, d);
} else if (mbuf->packet_type & RTE_PTYPE_L3_IPV6) {
struct ip6_local_mbuf_data *d = ip6_local_mbuf_data(mbuf);
struct rte_ipv6_hdr *ip;
ip = (struct rte_ipv6_hdr *)rte_pktmbuf_prepend(mbuf, sizeof(*ip));
if (ip == NULL) {
edge = NO_HEADROOM;
goto next;
}
ip6_set_fields(ip, d->len, d->proto, &d->src, &d->dst);
ip->hop_limits = d->hop_limit;
} else {
edge = BAD_PROTO;
}

next:
if (gr_mbuf_is_traced(mbuf)) {
gr_mbuf_trace_add(mbuf, node, 0);
}
rte_node_enqueue_x1(graph, node, edge, mbuf);
}

return nb_objs;
}

static struct rte_node_register l4_loopback_output_node = {
.name = "l4_loopback_output",
.process = l4_loopback_output_process,
.nb_edges = EDGE_COUNT,
.next_nodes = {
[REDIRECT] = "loopback_output",
[NO_IFACE] = "no_loop_iface",
[BAD_PROTO] = "l4_bad_proto",
[NO_HEADROOM] = "error_no_headroom",
},
};

static struct gr_node_info info = {
.node = &l4_loopback_output_node,
};

GR_NODE_REGISTER(info);

GR_DROP_REGISTER(no_loop_iface);
GR_DROP_REGISTER(l4_bad_proto);
149 changes: 0 additions & 149 deletions modules/l4/l4_redirect_loopback.c

This file was deleted.

3 changes: 2 additions & 1 deletion modules/l4/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Copyright (c) 2024 Christophe Fontaine

src += files(
'l4_redirect_loopback.c',
'l4_input_local.c',
'l4_loopback_output.c',
)
inc += include_directories('.')

0 comments on commit 1d6f86a

Please sign in to comment.