diff --git a/docs/graph.svg b/docs/graph.svg index fb6f8140..2aff9e2f 100644 --- a/docs/graph.svg +++ b/docs/graph.svg @@ -1,613 +1,577 @@ - - - - -gr-0003 - + + + +gr-0005 + control_input - -control_input + +control_input loopback_input - -loopback_input + +loopback_input control_input->loopback_input - - + + arp_output_request - -arp_output_request + +arp_output_request control_input->arp_output_request - - + + icmp_local_send - -icmp_local_send + +icmp_local_send control_input->icmp_local_send - - + + ndp_ns_output - -ndp_ns_output + +ndp_ns_output control_input->ndp_ns_output - - + + ip_output - -ip_output + +ip_output control_input->ip_output - - + + ip6_output - -ip6_output + +ip6_output control_input->ip6_output - - + + loopback_input->ip_output - - + + loopback_input->ip6_output - - + + ip_input_local - -ip_input_local + +ip_input_local loopback_input->ip_input_local - - + + ip6_input_local - -ip6_input_local + +ip6_input_local loopback_input->ip6_input_local - - + + eth_output - -eth_output + +eth_output arp_output_request->eth_output - - + + icmp_output - -icmp_output + +icmp_output icmp_local_send->icmp_output - - + + - + ndp_ns_output->ip6_output - - + + - + ip_output->eth_output - - + + loopback_output - -loopback_output + +loopback_output - + ip_output->loopback_output - - + + ip_hold - -ip_hold + +ip_hold - + ip_output->ip_hold - - + + - + ipip_output - -ipip_output + +ipip_output - + ip_output->ipip_output - - + + - + ip6_output->eth_output - - + + - + ip6_output->loopback_output - - + + - + ip6_hold - -ip6_hold + +ip6_hold - + ip6_output->ip6_hold - - + + control_output - -control_output + +control_output eth_input - -eth_input + +eth_input arp_input - -arp_input + +arp_input eth_input->arp_input - - + + ip_input - -ip_input + +ip_input eth_input->ip_input - - + + ip6_input - -ip6_input + +ip6_input eth_input->ip6_input - - + + arp_input_request - -arp_input_request + +arp_input_request arp_input->arp_input_request - - + + arp_input_reply - -arp_input_reply + +arp_input_reply arp_input->arp_input_reply - - + + ip_input->ip_input_local - - + + ip_forward - -ip_forward + +ip_forward ip_input->ip_forward - - + + - + ip6_input->ip6_input_local - - + + - + ip6_forward - -ip6_forward + +ip6_forward - + ip6_input->ip6_forward - - + + port_tx - -port_tx + +port_tx eth_output->port_tx - - + + icmp_input - -icmp_input + +icmp_input ip_input_local->icmp_input - - + + ipip_input - -ipip_input + +ipip_input ip_input_local->ipip_input - - + + - + -tcp_redirect_loopback - -tcp_redirect_loopback +l4_input_local + +l4_input_local - + -ip_input_local->tcp_redirect_loopback - - - - - -udp_redirect_loopback - -udp_redirect_loopback - - - -ip_input_local->udp_redirect_loopback - - +ip_input_local->l4_input_local + + - - -sctp_redirect_loopback - -sctp_redirect_loopback - - - -ip_input_local->sctp_redirect_loopback - - - - - -ip6_input_local->tcp_redirect_loopback - - - - - -ip6_input_local->udp_redirect_loopback - - - - - -ip6_input_local->sctp_redirect_loopback - - + + +ip6_input_local->l4_input_local + + - + icmp6_input - -icmp6_input + +icmp6_input - + ip6_input_local->icmp6_input - - + + loopback_output->control_output - - + + port_rx - -port_rx + +port_rx port_rx->eth_input - - + + arp_input_request->control_output - - + + arp_output_reply - -arp_output_reply + +arp_output_reply arp_input_request->arp_output_reply - - + + arp_input_reply->control_output - - + + arp_output_reply->eth_output - - + + icmp_input->control_output - - + + icmp_input->icmp_output - - + + icmp_output->ip_output - - + + ip_forward->ip_output - - + + ip_hold->control_output - - + + - + ipip_input->ip_input - - - - - -tcp_redirect_loopback->loopback_output - - - - - -udp_redirect_loopback->loopback_output - - - - - -sctp_redirect_loopback->loopback_output - - + + + + + +l4_redirect_loopback + +l4_redirect_loopback + + + +l4_input_local->l4_redirect_loopback + + - + ipip_output->ip_output - - + + - + icmp6_output - -icmp6_output + +icmp6_output - + icmp6_input->icmp6_output - - + + - + ndp_ns_input - -ndp_ns_input + +ndp_ns_input - + icmp6_input->ndp_ns_input - - + + - + ndp_na_input - -ndp_na_input + +ndp_na_input - + icmp6_input->ndp_na_input - - + + - + icmp6_output->ip6_output - - + + - + ndp_ns_input->ip6_output - - + + - + ndp_ns_input->control_output - - + + - + ndp_na_input->control_output - - + + - + ip6_forward->ip6_output - - + + - + ip6_hold->control_output - - + + + + + +l4_redirect_loopback->loopback_output + + diff --git a/modules/infra/control/loopback.c b/modules/infra/control/loopback.c index 3e6781bc..4c110cf4 100644 --- a/modules/infra/control/loopback.c +++ b/modules/infra/control/loopback.c @@ -134,6 +134,7 @@ static void iface_loopback_poll(evutil_socket_t, short reason, void *ev_iface) { // packet sent from linux tun iface, no need to compute checksum; mbuf->ol_flags = RTE_MBUF_F_RX_IP_CKSUM_GOOD; + mbuf->packet_type = data[0] == 6 ? RTE_PTYPE_L3_IPV6 : RTE_PTYPE_L3_IPV4; // Emulate ethernet input, required by ip(6)_input e = eth_input_mbuf_data(mbuf); e->iface = iface; diff --git a/modules/l4/gr_l4.h b/modules/l4/gr_l4.h new file mode 100644 index 00000000..0bf0605a --- /dev/null +++ b/modules/l4/gr_l4.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2024 Christophe Fontaine + +#ifndef _GR_L4_H +#define _GR_L4_H + +#include + +void l4_input_register_port(uint8_t proto, uint16_t port, const char *next_node); + +#endif diff --git a/modules/l4/l4_input_local.c b/modules/l4/l4_input_local.c new file mode 100644 index 00000000..39fa1754 --- /dev/null +++ b/modules/l4/l4_input_local.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: BSD-3-Clause +// Copyright (c) 2024 Christophe Fontaine + +#include "gr_l4.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +enum edges { + MANAGEMENT = 0, + BAD_PROTO, + EDGE_COUNT, +}; + +static rte_edge_t udp_edges[65536] = {MANAGEMENT}; + +void l4_input_register_port(uint8_t proto, uint16_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"); + 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_redirect_loopback", + [BAD_PROTO] = "l4_bad_proto", + }, +}; + +static struct gr_node_info info = { + .node = &input_node, + .register_callback = l4_input_local_register, +}; + +GR_NODE_REGISTER(info); + +GR_DROP_REGISTER(l4_bad_proto); diff --git a/modules/l4/meson.build b/modules/l4/meson.build index 78ee8332..4aee75f2 100644 --- a/modules/l4/meson.build +++ b/modules/l4/meson.build @@ -2,6 +2,7 @@ # Copyright (c) 2024 Christophe Fontaine src += files( + 'l4_input_local.c', 'l4_redirect_loopback.c', ) inc += include_directories('.')