From 7d9572ae0e90964af0a071222b6dcbfe131d2e67 Mon Sep 17 00:00:00 2001 From: Sergey Kacheev Date: Sun, 26 Jan 2025 18:42:13 +0300 Subject: [PATCH] feat: implement decap_packet lib function --- dataplane/modules/decap.h | 14 ----- dataplane/modules/meson.build | 21 ------- lib/dataplane/packet/decap.c | 110 +++++++++++++++++++++++++++++----- lib/dataplane/packet/packet.c | 36 +++++------ lib/dataplane/packet/packet.h | 6 ++ modules/decap/dataplane.c | 18 +++--- 6 files changed, 127 insertions(+), 78 deletions(-) delete mode 100644 dataplane/modules/decap.h delete mode 100644 dataplane/modules/meson.build diff --git a/dataplane/modules/decap.h b/dataplane/modules/decap.h deleted file mode 100644 index 89bb562..0000000 --- a/dataplane/modules/decap.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "module.h" - -#include "filter.h" - -struct decap_module { - struct module module; - - struct filter filter; -}; - -struct decap_module * -new_decap(); diff --git a/dataplane/modules/meson.build b/dataplane/modules/meson.build deleted file mode 100644 index 87c6d19..0000000 --- a/dataplane/modules/meson.build +++ /dev/null @@ -1,21 +0,0 @@ -dependencies = [] - -dependencies += libdpdk.get_variable('dpdk_dep') - -dependencies += libcommon_dep -dependencies += libfilter_dep -dependencies += libpacket_dep -dependencies += libdataplane_dep - -sources = files('acl.c', - 'kernel.c', - 'route.c') - -libmodules = static_library('modules', - sources, - dependencies: dependencies, - install: false) - -libmodules_dep = declare_dependency( - link_with: libmodules -) diff --git a/lib/dataplane/packet/decap.c b/lib/dataplane/packet/decap.c index c438d17..fc801ff 100644 --- a/lib/dataplane/packet/decap.c +++ b/lib/dataplane/packet/decap.c @@ -1,27 +1,105 @@ +#include +#include +#include + #include "decap.h" +#include "packet.h" -#include +// (first u32 + count of optional u32) * 4 +#define decap_gre_header_size(byte0) \ + (1 + __builtin_popcount((byte0) & 0xb0)) << 2 -#include +/// GRE Header: +/// 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 +/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/// |C| |K|S| Reserved0 | Ver | Protocol Type | +/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/// | Checksum (optional) | Reserved1 (Optional) | +/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/// | Key (optional) | +/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/// | Sequence Number (optional) | +/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +/// https://datatracker.ietf.org/doc/html/rfc2890#section-2 +static int +packet_skip_gre( + struct packet *packet, + uint16_t *type, + uint16_t *offset, + uint16_t *next_proto +) { + struct rte_gre_hdr *gre_hdr = rte_pktmbuf_mtod_offset( + packet->mbuf, + struct rte_gre_hdr *, + packet->transport_header.offset + ); + *next_proto = gre_hdr->proto; + if (gre_hdr->proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) { + *type = IPPROTO_IPIP; + } else if (gre_hdr->proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) { + *type = IPPROTO_IPV6; + } else { // error case + return -1; + } + *offset += decap_gre_header_size(*(uint8_t *)gre_hdr); + return 0; +} int packet_decap(struct packet *packet) { - (void)packet; - - /* - if (packet->network_header.type == - rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) { - struct rte_ipv4_hdr *ipv4Header = - rte_pktmbuf_mtod_offset( mbuf, struct rte_ipv4_hdr *, - packet->network_header.offset - ); - if (ipv4Header->proto = IPPROTO_IPIP) { - - } - } else { + uint16_t next_transport = packet->transport_header.type; + uint16_t next_offset = packet->transport_header.offset; + uint16_t next_ether_type; + + if (next_transport == IPPROTO_GRE) { + if (packet_skip_gre( + packet, + &next_transport, + &next_offset, + &next_ether_type + )) { return -1; } - */ + } + uint16_t tun_hdrs_size = next_offset - packet->network_header.offset; + + if (next_transport == IPPROTO_IPIP) { + if (parse_ipv4_header(packet, &next_transport, &next_offset)) { + return -1; + } + } else if (next_transport == IPPROTO_IPV6) { + if (parse_ipv6_header(packet, &next_transport, &next_offset)) { + return -1; + } + } else { + // unknown tunnel + return -1; + } + + struct rte_mbuf *mbuf = packet_to_mbuf(packet); + + // Remove tunnel headers + uint8_t *prev_start = rte_pktmbuf_mtod(mbuf, uint8_t *); + + // FIXME: separate strip header function + // FIXME: handle rte_pktmbuf_adj() == NULL + /* Copy ether header over rather than moving whole packet */ + memmove(rte_pktmbuf_adj(mbuf, tun_hdrs_size), + prev_start, + // size of eth_hdr plus optional vlans + packet->network_header.offset); + + // Update ether type + uint16_t *prev_eth_type = rte_pktmbuf_mtod_offset( + mbuf, + uint16_t *, + packet->network_header.offset - sizeof(uint16_t) + ); + *prev_eth_type = next_ether_type; + // and transport_header meta + packet->transport_header.type = next_transport; + packet->transport_header.offset = next_offset - tun_hdrs_size; return 0; } diff --git a/lib/dataplane/packet/packet.c b/lib/dataplane/packet/packet.c index 6406132..a0982b0 100644 --- a/lib/dataplane/packet/packet.c +++ b/lib/dataplane/packet/packet.c @@ -20,9 +20,9 @@ parse_ether_header(struct packet *packet, uint16_t *type, uint16_t *offset) { return -1; } - const struct rte_ether_hdr *etherHeader = + const struct rte_ether_hdr *ether_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ether_hdr *, *offset); - *type = etherHeader->ether_type; + *type = ether_hdr->ether_type; *offset += sizeof(struct rte_ether_hdr); return 0; } @@ -37,17 +37,17 @@ parse_vlan_header(struct packet *packet, uint16_t *type, uint16_t *offset) { return -1; } - const struct rte_vlan_hdr *vlanHeader = + const struct rte_vlan_hdr *vlan_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_vlan_hdr *, *offset); - packet->vlan = rte_be_to_cpu_16(vlanHeader->vlan_tci); + packet->vlan = rte_be_to_cpu_16(vlan_hdr->vlan_tci); - *type = vlanHeader->eth_proto; + *type = vlan_hdr->eth_proto; *offset += sizeof(struct rte_vlan_hdr); return 0; } -static inline int +inline int parse_ipv4_header(struct packet *packet, uint16_t *type, uint16_t *offset) { struct rte_mbuf *mbuf = packet_to_mbuf(packet); @@ -57,22 +57,22 @@ parse_ipv4_header(struct packet *packet, uint16_t *type, uint16_t *offset) { return -1; } - const struct rte_ipv4_hdr *ipv4Header = + const struct rte_ipv4_hdr *ipv4_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, *offset); if (rte_pktmbuf_pkt_len(mbuf) < - (uint32_t)*offset + rte_be_to_cpu_16(ipv4Header->total_length)) { + (uint32_t)*offset + rte_be_to_cpu_16(ipv4_hdr->total_length)) { *type = PACKET_HEADER_TYPE_UNKNOWN; return -1; } - if ((ipv4Header->version_ihl & 0x0F) < 0x05) { + if ((ipv4_hdr->version_ihl & 0x0F) < 0x05) { *type = PACKET_HEADER_TYPE_UNKNOWN; return -1; } - if (rte_be_to_cpu_16(ipv4Header->total_length) < - 4 * (ipv4Header->version_ihl & 0x0F)) { + if (rte_be_to_cpu_16(ipv4_hdr->total_length) < + 4 * (ipv4_hdr->version_ihl & 0x0F)) { *type = PACKET_HEADER_TYPE_UNKNOWN; return -1; } @@ -80,13 +80,13 @@ parse_ipv4_header(struct packet *packet, uint16_t *type, uint16_t *offset) { // FIXME: check if fragmented // FIXME: process extensions - *type = ipv4Header->next_proto_id; - *offset += 4 * (ipv4Header->version_ihl & 0x0F); + *type = ipv4_hdr->next_proto_id; + *offset += 4 * (ipv4_hdr->version_ihl & 0x0F); return 0; } -static inline int +inline int parse_ipv6_header(struct packet *packet, uint16_t *type, uint16_t *offset) { struct rte_mbuf *mbuf = packet_to_mbuf(packet); @@ -96,12 +96,12 @@ parse_ipv6_header(struct packet *packet, uint16_t *type, uint16_t *offset) { return -1; } - const struct rte_ipv6_hdr *ipv6Header = + const struct rte_ipv6_hdr *ipv6_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv6_hdr *, *offset); if (rte_pktmbuf_pkt_len(mbuf) < *offset + sizeof(struct rte_ipv6_hdr) + - rte_be_to_cpu_16(ipv6Header->payload_len)) { + rte_be_to_cpu_16(ipv6_hdr->payload_len)) { *type = PACKET_HEADER_TYPE_UNKNOWN; return -1; } @@ -109,8 +109,8 @@ parse_ipv6_header(struct packet *packet, uint16_t *type, uint16_t *offset) { // walk through extensions *offset += sizeof(struct rte_ipv6_hdr); uint16_t max_offset = - *offset + rte_be_to_cpu_16(ipv6Header->payload_len); - uint8_t ext_type = ipv6Header->proto; + *offset + rte_be_to_cpu_16(ipv6_hdr->payload_len); + uint8_t ext_type = ipv6_hdr->proto; while (*offset < max_offset) { if (ext_type == IPPROTO_HOPOPTS || ext_type == IPPROTO_ROUTING || diff --git a/lib/dataplane/packet/packet.h b/lib/dataplane/packet/packet.h index 958babf..7f1e9e0 100644 --- a/lib/dataplane/packet/packet.h +++ b/lib/dataplane/packet/packet.h @@ -99,6 +99,12 @@ packet_list_pop(struct packet_list *packets) { return res; } +int +parse_ipv4_header(struct packet *packet, uint16_t *type, uint16_t *offset); + +int +parse_ipv6_header(struct packet *packet, uint16_t *type, uint16_t *offset); + int parse_packet(struct packet *packet); diff --git a/modules/decap/dataplane.c b/modules/decap/dataplane.c index e5be74e..4695228 100644 --- a/modules/decap/dataplane.c +++ b/modules/decap/dataplane.c @@ -1,7 +1,5 @@ #include "dataplane.h" -#include "dataplane/pipeline/pipeline.h" - #include "dataplane/packet/decap.h" #include "rte_ether.h" @@ -11,11 +9,11 @@ static int decap_handle_v4(const struct lpm *lpm, struct packet *packet) { struct rte_mbuf *mbuf = packet_to_mbuf(packet); - struct rte_ipv4_hdr *ipv4Header = rte_pktmbuf_mtod_offset( + struct rte_ipv4_hdr *ipv4_hdr = rte_pktmbuf_mtod_offset( mbuf, struct rte_ipv4_hdr *, packet->network_header.offset ); - if (lpm_lookup(lpm, 4, (uint8_t *)&ipv4Header->dst_addr) != + if (lpm_lookup(lpm, 4, (uint8_t *)&ipv4_hdr->dst_addr) != LPM_VALUE_INVALID) { return packet_decap(packet); } @@ -27,12 +25,13 @@ static int decap_handle_v6(const struct lpm *lpm, struct packet *packet) { struct rte_mbuf *mbuf = packet_to_mbuf(packet); - struct rte_ipv6_hdr *ipv4Header = rte_pktmbuf_mtod_offset( + struct rte_ipv6_hdr *ipv6_hdr = rte_pktmbuf_mtod_offset( mbuf, struct rte_ipv6_hdr *, packet->network_header.offset ); - if (lpm_lookup(lpm, 16, (uint8_t *)&ipv4Header->dst_addr) != + if (lpm_lookup(lpm, 16, (uint8_t *)&ipv6_hdr->dst_addr) != LPM_VALUE_INVALID) { + // FIXME: preserve flowlabel return packet_decap(packet); } @@ -46,6 +45,7 @@ decap_handle_packets( struct packet_front *packet_front ) { (void)module; + struct decap_module_config *decap_config = container_of(config, struct decap_module_config, config); @@ -67,6 +67,9 @@ decap_handle_packets( if (result) { packet_front_drop(packet_front, packet); } else { + // FIXME: if packet is ipv4 then mark ipv4 dscp + // FIXME: if packet is ipv6 restore flowlabel + packet_front_output(packet_front, packet); } } @@ -80,9 +83,6 @@ decap_handle_configure( struct module_config **new_config ) { (void)module; - (void)config_data; - (void)config_data_size; - (void)new_config; struct decap_module_config *config = (struct decap_module_config *) malloc(sizeof(struct decap_module_config));