From 1f1e0f7a8cae478ee88c3171b22dfceff7362418 Mon Sep 17 00:00:00 2001 From: Christophe Fontaine Date: Fri, 11 Oct 2024 12:26:57 +0000 Subject: [PATCH] ip6: add tracing for ip6 nodes Implement tracing for ip6/icmp6/ndp nodes. Signed-off-by: Christophe Fontaine --- modules/ip6/datapath/gr_ip6_datapath.h | 9 ++++ modules/ip6/datapath/icmp6_input.c | 27 ++++++++++++ modules/ip6/datapath/icmp6_output.c | 4 ++ modules/ip6/datapath/ip6_error.c | 22 ++++++++++ modules/ip6/datapath/ip6_forward.c | 3 ++ modules/ip6/datapath/ip6_input.c | 58 ++++++++++++++++++++++++++ modules/ip6/datapath/ip6_local.c | 4 ++ modules/ip6/datapath/ip6_output.c | 9 ++++ modules/ip6/datapath/ndp_na_input.c | 6 +++ modules/ip6/datapath/ndp_ns_input.c | 3 ++ modules/ip6/datapath/ndp_ns_output.c | 3 ++ 11 files changed, 148 insertions(+) diff --git a/modules/ip6/datapath/gr_ip6_datapath.h b/modules/ip6/datapath/gr_ip6_datapath.h index 3514c8e5..38b8dadd 100644 --- a/modules/ip6/datapath/gr_ip6_datapath.h +++ b/modules/ip6/datapath/gr_ip6_datapath.h @@ -65,4 +65,13 @@ void ndp_update_nexthop( const struct rte_ether_addr *mac ); +struct trace_ip6_data { + struct rte_ipv6_addr src; + struct rte_ipv6_addr dst; + uint8_t hop_limits; + uint8_t proto; +}; + +int format_ip6_data(void *data, char *buf, size_t len); + #endif diff --git a/modules/ip6/datapath/icmp6_input.c b/modules/ip6/datapath/icmp6_input.c index e8ef977b..a0b6da0f 100644 --- a/modules/ip6/datapath/icmp6_input.c +++ b/modules/ip6/datapath/icmp6_input.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,26 @@ enum { EDGE_COUNT, }; +struct trace_icmp6_data { + uint16_t type; +}; + +static int format_icmp6_data(void *data, char *buf, size_t len) { + struct trace_icmp6_data *t = data; + static const char *ICMP6_STR[UINT16_MAX] = { + [ICMP6_TYPE_ECHO_REQUEST] = "Echo Request", + [ICMP6_TYPE_ECHO_REPLY] = "Echo Reply", + [ICMP6_TYPE_NEIGH_SOLICIT] = "Neighbor Solicitation", + [ICMP6_TYPE_NEIGH_ADVERT] = "Neighbor Advertisement", + [ICMP6_TYPE_ROUTER_SOLICIT] = "Router Solicitation", + [ICMP6_TYPE_ROUTER_ADVERT] = "Router Advertisement", + }; + if (ICMP6_STR[t->type]) + return snprintf(buf, len, "%s", ICMP6_STR[t->type]); + else + return snprintf(buf, len, "type: %d", t->type); +} + static uint16_t icmp6_input_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs) { struct ip6_local_mbuf_data *d; @@ -37,6 +58,11 @@ icmp6_input_process(struct rte_graph *graph, struct rte_node *node, void **objs, icmp6 = rte_pktmbuf_mtod(mbuf, struct icmp6 *); d = ip6_local_mbuf_data(mbuf); + if (unlikely(gr_mbuf_trace_is_set(mbuf))) { + struct trace_icmp6_data *t = gr_trace_add(node, mbuf, sizeof(*t)); + t->type = icmp6->type; + } + switch (icmp6->type) { case ICMP6_TYPE_ECHO_REQUEST: if (icmp6->code != 0) { @@ -91,6 +117,7 @@ static struct rte_node_register icmp6_input_node = { static struct gr_node_info icmp6_input_info = { .node = &icmp6_input_node, .register_callback = icmp6_input_register, + .ext_funcs.format_trace = format_icmp6_data, }; GR_NODE_REGISTER(icmp6_input_info); diff --git a/modules/ip6/datapath/icmp6_output.c b/modules/ip6/datapath/icmp6_output.c index 82f65f89..170f6195 100644 --- a/modules/ip6/datapath/icmp6_output.c +++ b/modules/ip6/datapath/icmp6_output.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -61,6 +62,9 @@ static uint16_t icmp6_output_process( o->input_iface = iface; edge = OUTPUT; next: + if (unlikely(gr_mbuf_trace_is_set(mbuf))) + gr_trace_add(node, mbuf, 0); + rte_node_enqueue_x1(graph, node, edge, mbuf); } diff --git a/modules/ip6/datapath/ip6_error.c b/modules/ip6/datapath/ip6_error.c index 085b595d..ebce0819 100644 --- a/modules/ip6/datapath/ip6_error.c +++ b/modules/ip6/datapath/ip6_error.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -20,6 +21,20 @@ enum edges { EDGE_COUNT, }; +struct trace_ip6_error_data { + icmp6_type_t icmp_type; +}; + +static int format_ip6_error_data(void *data, char *buf, size_t len) { + struct trace_ip6_error_data *d = data; + static const char *icmp_error[UINT16_MAX] = { + [ICMP6_ERR_DEST_UNREACH] = "Destination unreachable", + [ICMP6_ERR_TTL_EXCEEDED] = "TTL exceeded", + }; + + return snprintf(buf, len, "%s", icmp_error[d->icmp_type]); +} + static uint16_t ip6_error_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs) { struct icmp6_err_dest_unreach *du; @@ -71,6 +86,11 @@ ip6_error_process(struct rte_graph *graph, struct rte_node *node, void **objs, u break; } + if (unlikely(gr_mbuf_trace_is_set(mbuf))) { + struct trace_ip6_error_data *t = gr_trace_add(node, mbuf, sizeof(*t)); + t->icmp_type = icmp_type; + } + icmp6 = (struct icmp6 *)rte_pktmbuf_prepend(mbuf, sizeof(*icmp6)); if (unlikely(icmp6 == NULL || ip == NULL)) { edge = NO_HEADROOM; @@ -138,10 +158,12 @@ static struct rte_node_register ttl_exceeded_node = { static struct gr_node_info dest_unreach_info = { .node = &dest_unreach_node, + .ext_funcs.format_trace = format_ip6_error_data, }; static struct gr_node_info ttl_exceeded_info = { .node = &ttl_exceeded_node, + .ext_funcs.format_trace = format_ip6_error_data, }; GR_NODE_REGISTER(dest_unreach_info); diff --git a/modules/ip6/datapath/ip6_forward.c b/modules/ip6/datapath/ip6_forward.c index 0eafac3f..7d781535 100644 --- a/modules/ip6/datapath/ip6_forward.c +++ b/modules/ip6/datapath/ip6_forward.c @@ -2,6 +2,7 @@ // Copyright (c) 2024 Robin Jarry #include +#include #include #include @@ -23,6 +24,8 @@ ip6_forward_process(struct rte_graph *graph, struct rte_node *node, void **objs, for (i = 0; i < nb_objs; i++) { mbuf = objs[i]; ip = rte_pktmbuf_mtod(mbuf, struct rte_ipv6_hdr *); + if (unlikely(gr_mbuf_trace_is_set(mbuf))) + gr_trace_add(node, mbuf, 0); if (ip->hop_limits <= 1) { rte_node_enqueue_x1(graph, node, TTL_EXCEEDED, mbuf); diff --git a/modules/ip6/datapath/ip6_input.c b/modules/ip6/datapath/ip6_input.c index 05ec54c0..9c27fce2 100644 --- a/modules/ip6/datapath/ip6_input.c +++ b/modules/ip6/datapath/ip6_input.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,55 @@ enum edges { EDGE_COUNT, }; +int format_ip6_data(void *data, char *buf, size_t len) { + struct trace_ip6_data *t = data; + char src[INET6_ADDRSTRLEN]; + char dst[INET6_ADDRSTRLEN]; + + static const char *protos[UINT8_MAX] = { + [0] = "IPv6 Hop-by-Hop", + [1] = "ICMP", + [2] = "IGMP", + [4] = "IP in IP", + [6] = "TCP", + [17] = "UDP", + [27] = "Reliable Data Protocol", + [41] = "IPv6 Encapsulation", + [43] = "IPv6 Routing Header", + [44] = "IPv6 Fragment Header", + [47] = "GRE", + [50] = "ESP", + [51] = "Authentication Header", + [58] = "IPv6 ICMP", + [59] = "IPv6 No Next Header", + [60] = "IPv6 Destination Options", + [89] = "OSPF", + [112] = "VRRP", + [132] = "SCTP", + [136] = "UDP Lite", + [137] = "MPLS In IP", + [145] = "NSH", + }; + + inet_ntop(AF_INET6, &t->src, src, sizeof(src)); + inet_ntop(AF_INET6, &t->dst, dst, sizeof(dst)); + + if (protos[t->proto]) + return snprintf( + buf, + len, + "%s -> %s next proto %s ttl %d", + src, + dst, + protos[t->proto], + t->hop_limits + ); + else + return snprintf( + buf, len, "%s -> %s next proto %d ttl %d", src, dst, t->proto, t->hop_limits + ); +} + static uint16_t ip6_input_process(struct rte_graph *graph, struct rte_node *node, void **objs, uint16_t nb_objs) { struct ip6_output_mbuf_data *d; @@ -110,6 +160,13 @@ ip6_input_process(struct rte_graph *graph, struct rte_node *node, void **objs, u edge = FORWARD; next: + if (unlikely(gr_mbuf_trace_is_set(mbuf))) { + struct trace_ip6_data *t = gr_trace_add(node, mbuf, sizeof(*t)); + t->src = ip->src_addr; + t->dst = ip->dst_addr; + t->proto = ip->proto; + t->hop_limits = ip->hop_limits; + } // Store the resolved next hop for ip6_output to avoid a second route lookup. d->nh = nh; rte_node_enqueue_x1(graph, node, edge, mbuf); @@ -143,6 +200,7 @@ static struct rte_node_register input_node = { static struct gr_node_info info = { .node = &input_node, .register_callback = ip6_input_register, + .ext_funcs.format_trace = format_ip6_data, }; GR_NODE_REGISTER(info); diff --git a/modules/ip6/datapath/ip6_local.c b/modules/ip6/datapath/ip6_local.c index 7bef3863..0b881a58 100644 --- a/modules/ip6/datapath/ip6_local.c +++ b/modules/ip6/datapath/ip6_local.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -81,6 +82,9 @@ static uint16_t ip6_input_local_process( break; } next: + if (unlikely(gr_mbuf_trace_is_set(m))) + gr_trace_add(node, m, 0); + rte_node_enqueue_x1(graph, node, edge, m); } diff --git a/modules/ip6/datapath/ip6_output.c b/modules/ip6/datapath/ip6_output.c index 6f727d75..dfb3ff31 100644 --- a/modules/ip6/datapath/ip6_output.c +++ b/modules/ip6/datapath/ip6_output.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -150,6 +151,13 @@ ip6_output_process(struct rte_graph *graph, struct rte_node *node, void **objs, eth_data->iface = iface; sent++; next: + if (unlikely(gr_mbuf_trace_is_set(mbuf))) { + struct trace_ip6_data *t = gr_trace_add(node, mbuf, sizeof(*t)); + t->src = ip->src_addr; + t->dst = ip->dst_addr; + t->proto = ip->proto; + t->hop_limits = ip->hop_limits; + } rte_node_enqueue_x1(graph, node, edge, mbuf); } @@ -170,6 +178,7 @@ static struct rte_node_register output_node = { static struct gr_node_info info = { .node = &output_node, + .ext_funcs.format_trace = format_ip6_data, }; GR_NODE_REGISTER(info); diff --git a/modules/ip6/datapath/ndp_na_input.c b/modules/ip6/datapath/ndp_na_input.c index b4baea71..c69ab381 100644 --- a/modules/ip6/datapath/ndp_na_input.c +++ b/modules/ip6/datapath/ndp_na_input.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -135,9 +136,14 @@ static uint16_t ndp_na_input_process( ASSERT_NDP(lladdr_found); ndp_update_nexthop(graph, node, remote, iface, &lladdr); + + if (unlikely(gr_mbuf_trace_is_set(mbuf))) + gr_trace_aggregate(mbuf); rte_pktmbuf_free(mbuf); continue; next: + if (unlikely(gr_mbuf_trace_is_set(mbuf))) + gr_trace_add(node, mbuf, 0); rte_node_enqueue_x1(graph, node, next, mbuf); } diff --git a/modules/ip6/datapath/ndp_ns_input.c b/modules/ip6/datapath/ndp_ns_input.c index 314990c4..86eb2478 100644 --- a/modules/ip6/datapath/ndp_ns_input.c +++ b/modules/ip6/datapath/ndp_ns_input.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -160,6 +161,8 @@ static uint16_t ndp_ns_input_process( next = IP_OUTPUT; next: + if (unlikely(gr_mbuf_trace_is_set(mbuf))) + gr_trace_add(node, mbuf, 0); rte_node_enqueue_x1(graph, node, next, mbuf); } diff --git a/modules/ip6/datapath/ndp_ns_output.c b/modules/ip6/datapath/ndp_ns_output.c index 1726fd37..e41c5ef1 100644 --- a/modules/ip6/datapath/ndp_ns_output.c +++ b/modules/ip6/datapath/ndp_ns_output.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -98,6 +99,8 @@ static uint16_t ndp_ns_output_process( ip6_output_mbuf_data(mbuf)->nh = nh; next = OUTPUT; next: + if (unlikely(gr_mbuf_trace_is_set(mbuf))) + gr_trace_add(node, mbuf, 0); rte_node_enqueue_x1(graph, node, next, mbuf); }