Skip to content

Commit

Permalink
ipv4: add support for icmp echo reply
Browse files Browse the repository at this point in the history
Signed-off-by: Robin Jarry <[email protected]>
  • Loading branch information
rjarry committed Apr 17, 2024
1 parent 4dc9a35 commit c71d3f3
Show file tree
Hide file tree
Showing 11 changed files with 270 additions and 27 deletions.
2 changes: 1 addition & 1 deletion modules/ip4/datapath/arp_input.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024 Robin Jarry

#include "ip4_mbuf.h"
#include "ip4.h"

#include <br_datapath.h>
#include <br_graph.h>
Expand Down
2 changes: 1 addition & 1 deletion modules/ip4/datapath/arp_output_reply.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024 Robin Jarry

#include "ip4_mbuf.h"
#include "ip4.h"

#include <br_datapath.h>
#include <br_graph.h>
Expand Down
2 changes: 1 addition & 1 deletion modules/ip4/datapath/arp_output_request.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024 Robin Jarry

#include "ip4_mbuf.h"
#include "ip4.h"
#include "rte_mbuf.h"

#include <br_datapath.h>
Expand Down
94 changes: 94 additions & 0 deletions modules/ip4/datapath/icmp_input.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024 Robin Jarry

#include "ip4.h"

#include <br_datapath.h>
#include <br_graph.h>
#include <br_ip4_control.h>
#include <br_log.h>
#include <br_mbuf.h>

#include <rte_byteorder.h>
#include <rte_ether.h>
#include <rte_graph_worker.h>
#include <rte_icmp.h>
#include <rte_ip.h>

enum {
OUTPUT = 0,
INVALID,
UNSUPPORTED,
EDGE_COUNT,
};

#define ICMP_MIN_SIZE 8

static uint16_t
icmp_input_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs) {
struct ip_local_mbuf_data *ip_data;
struct rte_icmp_hdr *icmp;
struct rte_mbuf *mbuf;
rte_edge_t next;
ip4_addr_t ip;

for (uint16_t i = 0; i < nb_objs; i++) {
mbuf = objs[i];
icmp = rte_pktmbuf_mtod(mbuf, struct rte_icmp_hdr *);
ip_data = ip_local_mbuf_data(mbuf);

if (ip_data->len < ICMP_MIN_SIZE || (uint16_t)~rte_raw_cksum(icmp, ip_data->len)) {
next = INVALID;
goto next;
}
switch (icmp->icmp_type) {
case RTE_IP_ICMP_ECHO_REQUEST:
if (icmp->icmp_code != 0) {
next = INVALID;
goto next;
}
icmp->icmp_type = RTE_IP_ICMP_ECHO_REPLY;
ip = ip_data->dst;
ip_data->dst = ip_data->src;
ip_data->src = ip;
break;
default:
next = UNSUPPORTED;
goto next;
}
next:
rte_node_enqueue_x1(graph, node, next, mbuf);
}

return nb_objs;
}

static void icmp_input_register(void) {
rte_edge_t edge = br_node_attach_parent("ipv4_input_local", "icmp_input");
if (edge == RTE_EDGE_ID_INVALID)
ABORT("br_node_attach_parent(classify, icmp_input) failed");
ip4_local_add_proto(IPPROTO_ICMP, edge);
}

static struct rte_node_register icmp_input_node = {
.name = "icmp_input",

.process = icmp_input_process,

.nb_edges = EDGE_COUNT,
.next_nodes = {
[OUTPUT] = "icmp_output",
[INVALID] = "icmp_input_invalid",
[UNSUPPORTED] = "icmp_input_unsupported",
},
};

static struct br_node_info icmp_input_info = {
.node = &icmp_input_node,
.register_callback = icmp_input_register,
};

BR_NODE_REGISTER(icmp_input_info);

BR_DROP_REGISTER(icmp_input_invalid);
BR_DROP_REGISTER(icmp_input_unsupported);
76 changes: 76 additions & 0 deletions modules/ip4/datapath/icmp_output.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024 Robin Jarry

#include "ip4.h"

#include <br_datapath.h>
#include <br_graph.h>
#include <br_ip4_control.h>
#include <br_log.h>
#include <br_mbuf.h>

#include <rte_byteorder.h>
#include <rte_ether.h>
#include <rte_graph_worker.h>
#include <rte_icmp.h>
#include <rte_ip.h>

#include <netinet/in.h>

enum {
OUTPUT = 0,
EDGE_COUNT,
};

#define IPV4_VERSION_IHL 0x45

static uint16_t
icmp_output_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs) {
struct ip_local_mbuf_data *local_data;
struct rte_icmp_hdr *icmp;
struct rte_ipv4_hdr *ip;
struct rte_mbuf *mbuf;

for (uint16_t i = 0; i < nb_objs; i++) {
mbuf = objs[i];
icmp = rte_pktmbuf_mtod(mbuf, struct rte_icmp_hdr *);
local_data = ip_local_mbuf_data(mbuf);

icmp->icmp_cksum = 0;
icmp->icmp_cksum = ~rte_raw_cksum(icmp, local_data->len);

ip = (struct rte_ipv4_hdr *)rte_pktmbuf_prepend(mbuf, sizeof(*ip));

memset(ip, 0, sizeof(*ip));
ip->version_ihl = IPV4_VERSION_IHL;
ip->total_length = rte_cpu_to_be_16(local_data->len + sizeof(*ip));
ip->time_to_live = 64;
ip->next_proto_id = IPPROTO_ICMP;
ip->src_addr = local_data->src;
ip->dst_addr = local_data->dst;
ip->hdr_checksum = rte_ipv4_cksum(ip);

ip_output_mbuf_data(mbuf)->nh = NULL;

rte_node_enqueue_x1(graph, node, OUTPUT, mbuf);
}

return nb_objs;
}

static struct rte_node_register icmp_output_node = {
.name = "icmp_output",

.process = icmp_output_process,

.nb_edges = EDGE_COUNT,
.next_nodes = {
[OUTPUT] = "ipv4_output",
},
};

static struct br_node_info icmp_output_info = {
.node = &icmp_output_node,
};

BR_NODE_REGISTER(icmp_output_info);
30 changes: 30 additions & 0 deletions modules/ip4/datapath/ip4.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024 Robin Jarry

#ifndef _IP4_H
#define _IP4_H

#include <br_mbuf.h>
#include <br_net_types.h>

#include <rte_graph_worker.h>

#include <stdint.h>

BR_MBUF_PRIV_DATA_TYPE(ip_output_mbuf_data, { struct nexthop *nh; });

BR_MBUF_PRIV_DATA_TYPE(arp_mbuf_data, {
struct nexthop *local;
struct nexthop *remote;
});

BR_MBUF_PRIV_DATA_TYPE(ip_local_mbuf_data, {
ip4_addr_t src;
ip4_addr_t dst;
uint16_t len;
uint8_t proto;
});

void ip4_local_add_proto(uint8_t proto, rte_edge_t edge);

#endif
16 changes: 0 additions & 16 deletions modules/ip4/datapath/ip4_mbuf.h

This file was deleted.

9 changes: 2 additions & 7 deletions modules/ip4/datapath/ip_input.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024 Robin Jarry

#include "ip4_mbuf.h"
#include "ip4.h"

#include <br_datapath.h>
#include <br_graph.h>
Expand Down Expand Up @@ -47,11 +47,7 @@ input_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint1
// (2) The IP checksum must be correct.
if ((mbuf->ol_flags & RTE_MBUF_F_RX_IP_CKSUM_MASK) == RTE_MBUF_F_RX_IP_CKSUM_NONE) {
// if this is not checked in H/W, check it.
uint16_t actual_cksum, expected_cksum;
actual_cksum = ip->hdr_checksum;
ip->hdr_checksum = 0;
expected_cksum = rte_ipv4_cksum(ip);
if (actual_cksum != expected_cksum) {
if (rte_ipv4_cksum(ip)) {
next = BAD_CHECKSUM;
goto next_packet;
}
Expand Down Expand Up @@ -121,7 +117,6 @@ static struct br_node_info info = {

BR_NODE_REGISTER(info);

BR_DROP_REGISTER(ipv4_input_local);
BR_DROP_REGISTER(ipv4_input_no_route);
BR_DROP_REGISTER(ipv4_input_bad_checksum);
BR_DROP_REGISTER(ipv4_input_bad_length);
61 changes: 61 additions & 0 deletions modules/ip4/datapath/ip_local.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024 Robin Jarry

#include "ip4.h"

#include <br_datapath.h>
#include <br_graph.h>

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

#define UNKNOWN_PROTO 0
static rte_edge_t edges[256] = {UNKNOWN_PROTO};

void ip4_local_add_proto(uint8_t proto, rte_edge_t edge) {
edges[proto] = edge;
LOG(DEBUG, "ip_input_local: proto=%u -> edge %u", proto, edge);
}

static uint16_t
local_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs) {
struct rte_ipv4_hdr *ip;
struct rte_mbuf *mbuf;
rte_edge_t next;
uint16_t i;

for (i = 0; i < nb_objs; i++) {
mbuf = objs[i];
ip = rte_pktmbuf_mtod(mbuf, struct rte_ipv4_hdr *);
next = edges[ip->next_proto_id];
if (next != UNKNOWN_PROTO) {
struct ip_local_mbuf_data *data = ip_local_mbuf_data(mbuf);
data->src = ip->src_addr;
data->dst = ip->dst_addr;
data->len = rte_be_to_cpu_16(ip->total_length) - rte_ipv4_hdr_len(ip);
data->proto = ip->next_proto_id;
rte_pktmbuf_adj(mbuf, sizeof(*ip));
}
rte_node_enqueue_x1(graph, node, next, mbuf);
}

return nb_objs;
}

static struct rte_node_register input_node = {
.name = "ipv4_input_local",
.process = local_process,
.nb_edges = 1,
.next_nodes = {
[UNKNOWN_PROTO] = "ipv4_input_local_unknown_proto",
},
};

static struct br_node_info info = {
.node = &input_node,
};

BR_NODE_REGISTER(info);

BR_DROP_REGISTER(ipv4_input_local_unknown_proto);
2 changes: 1 addition & 1 deletion modules/ip4/datapath/ip_output.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024 Robin Jarry

#include "ip4_mbuf.h"
#include "ip4.h"

#include <br_datapath.h>
#include <br_graph.h>
Expand Down
3 changes: 3 additions & 0 deletions modules/ip4/datapath/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ src += files(
'arp_input.c',
'arp_output_reply.c',
'arp_output_request.c',
'icmp_input.c',
'icmp_output.c',
'ip_forward.c',
'ip_input.c',
'ip_local.c',
'ip_output.c',
)
inc += include_directories('.')

0 comments on commit c71d3f3

Please sign in to comment.