From ece5919a0f199c65644b6d6786cbb1f2b7928a89 Mon Sep 17 00:00:00 2001 From: Robin Jarry Date: Fri, 24 Jan 2025 22:43:14 +0100 Subject: [PATCH] ndp: use icmp6 output code to send neigh solicits Do not take a shortcut from ndp_ns_output to ip6_output and duplicate code. Reuse icmp6_output that already handles building the ip6_local_mbuf_data. Adjust icmp6_output to handle multicast destination addresses used for neighbour solicitations. Signed-off-by: Robin Jarry Acked-by: David Marchand --- docs/graph.svg | 408 +++++++++++++-------------- modules/ip6/datapath/icmp6_output.c | 8 +- modules/ip6/datapath/ndp_ns_output.c | 50 ++-- 3 files changed, 237 insertions(+), 229 deletions(-) diff --git a/docs/graph.svg b/docs/graph.svg index a1ea43f3..6f995187 100644 --- a/docs/graph.svg +++ b/docs/graph.svg @@ -4,286 +4,286 @@ - - + + gr-0003 - + 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 - - + + icmp6_local_send - -icmp6_local_send + +icmp6_local_send control_input->icmp6_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 - - + + arp_output_reply - -arp_output_reply + +arp_output_reply control_input->arp_output_reply - - + + ip6_output - -ip6_output + +ip6_output control_input->ip6_output - - + + ip_input - -ip_input + +ip_input loopback_input->ip_input - - + + ip6_input - -ip6_input + +ip6_input loopback_input->ip6_input - - + + eth_output - -eth_output + +eth_output arp_output_request->eth_output - - + + icmp_output - -icmp_output + +icmp_output icmp_local_send->icmp_output - - + + icmp6_output - -icmp6_output + +icmp6_output icmp6_local_send->icmp6_output - - + + - + -ndp_ns_output->ip6_output - - +ndp_ns_output->icmp6_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 - - + + arp_output_reply->eth_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 - - + + eth_input->ip_input - - + + eth_input->ip6_input - - + + @@ -294,8 +294,8 @@ arp_input->arp_input_request - - + + @@ -306,314 +306,314 @@ arp_input->arp_input_reply - - + + ip_input->ip_output - - + + ip_forward - -ip_forward + +ip_forward ip_input->ip_forward - - + + ip_input_local - -ip_input_local + +ip_input_local ip_input->ip_input_local - - + + ip6_input->ip6_output - - + + ip6_forward - -ip6_forward + +ip6_forward ip6_input->ip6_forward - - + + ip6_input_local - -ip6_input_local + +ip6_input_local ip6_input->ip6_input_local - - + + port_tx - -port_tx + +port_tx eth_output->port_tx - - + + loopback_output->control_output - - + + port_rx - -port_rx + +port_rx port_rx->eth_input - - + + arp_input_request->control_output - - + + arp_input_reply->control_output - - + + icmp_input - -icmp_input + +icmp_input icmp_input->control_output - - + + icmp_input->icmp_output - - + + icmp_output->ip_output - - + + ip_forward->ip_output - - + + ip_hold->control_output - - + + ip_input_local->icmp_input - - + + ipip_input - -ipip_input + +ipip_input ip_input_local->ipip_input - - + + l4_input_local - -l4_input_local + +l4_input_local ip_input_local->l4_input_local - - + + ipip_input->ip_input - - + + l4_loopback_output - -l4_loopback_output + +l4_loopback_output l4_input_local->l4_loopback_output - - + + ipip_output->ip_output - - + + icmp6_input - -icmp6_input + +icmp6_input icmp6_input->control_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 - - + + ndp_rs_input - -ndp_rs_input + +ndp_rs_input icmp6_input->ndp_rs_input - - + + icmp6_output->ip6_output - - + + ndp_ns_input->ip6_output - - + + ndp_ns_input->control_output - - + + ndp_na_input->control_output - - + + ndp_rs_input->control_output - - + + ip6_forward->ip6_output - - + + ip6_hold->control_output - - + + ip6_input_local->l4_input_local - - + + ip6_input_local->icmp6_input - - + + l4_loopback_output->loopback_output - - + + diff --git a/modules/ip6/datapath/icmp6_output.c b/modules/ip6/datapath/icmp6_output.c index 6c85d3bd..167cb099 100644 --- a/modules/ip6/datapath/icmp6_output.c +++ b/modules/ip6/datapath/icmp6_output.c @@ -56,7 +56,13 @@ static uint16_t icmp6_output_process( struct icmp6 *t = gr_mbuf_trace_add(mbuf, node, trace_len); memcpy(t, icmp6, trace_len); } - if ((nh = ip6_route_lookup(d->iface->vrf_id, d->iface->id, &d->dst)) == NULL) { + + if (rte_ipv6_addr_is_mcast(&d->dst)) + nh = ip6_nexthop_lookup(d->iface->vrf_id, d->iface->id, &d->src); + else + nh = ip6_route_lookup(d->iface->vrf_id, d->iface->id, &d->dst); + + if (nh == NULL) { edge = NO_ROUTE; goto next; } diff --git a/modules/ip6/datapath/ndp_ns_output.c b/modules/ip6/datapath/ndp_ns_output.c index e6e68cd0..0fed4ce0 100644 --- a/modules/ip6/datapath/ndp_ns_output.c +++ b/modules/ip6/datapath/ndp_ns_output.c @@ -54,8 +54,7 @@ static uint16_t ndp_ns_output_process( const struct nexthop *local, *nh; struct icmp6_opt_lladdr *lladdr; struct icmp6_neigh_solicit *ns; - struct rte_ipv6_addr dst; - struct rte_ipv6_hdr *ip; + struct ip6_local_mbuf_data *d; struct rte_mbuf *mbuf; struct icmp6_opt *opt; uint16_t payload_len; @@ -77,38 +76,41 @@ static uint16_t ndp_ns_output_process( } // Fill ICMP6 layer. - icmp6 = (struct icmp6 *)rte_pktmbuf_append(mbuf, sizeof(*icmp6)); + payload_len = sizeof(*icmp6) + sizeof(*ns) + sizeof(*opt) + sizeof(*lladdr); + icmp6 = (struct icmp6 *)rte_pktmbuf_append(mbuf, payload_len); icmp6->type = ICMP6_TYPE_NEIGH_SOLICIT; icmp6->code = 0; - ns = (struct icmp6_neigh_solicit *)rte_pktmbuf_append(mbuf, sizeof(*ns)); + ns = PAYLOAD(icmp6); ns->__reserved = 0; ns->target = nh->ipv6; - opt = (struct icmp6_opt *)rte_pktmbuf_append(mbuf, sizeof(*opt)); + opt = PAYLOAD(ns); opt->type = ICMP6_OPT_SRC_LLADDR; opt->len = ICMP6_OPT_LEN(sizeof(*opt) + sizeof(*lladdr)); - lladdr = (struct icmp6_opt_lladdr *)rte_pktmbuf_append(mbuf, sizeof(*lladdr)); + lladdr = PAYLOAD(opt); lladdr->mac = local->lladdr; + + // Fill in IP local data + d = ip6_local_mbuf_data(mbuf); + d->iface = iface_from_id(local->iface_id); + d->src = local->ipv6; if (nh->last_reply != 0 && nh->ucast_probes <= NH_UCAST_PROBES) - dst = nh->ipv6; + d->dst = nh->ipv6; else - rte_ipv6_solnode_from_addr(&dst, &nh->ipv6); - // Fill IPv6 layer - payload_len = rte_pktmbuf_pkt_len(mbuf); - ip = (struct rte_ipv6_hdr *)rte_pktmbuf_prepend(mbuf, sizeof(*ip)); - ip6_set_fields(ip, payload_len, IPPROTO_ICMPV6, &local->ipv6, &dst); - // Compute ICMP6 checksum with pseudo header - icmp6->cksum = 0; - icmp6->cksum = rte_ipv6_udptcp_cksum(ip, icmp6); - - if (gr_mbuf_is_traced(mbuf)) { - uint8_t trace_len = RTE_MIN(payload_len, GR_TRACE_ITEM_MAX_LEN); - struct icmp6 *t = gr_mbuf_trace_add(mbuf, node, trace_len); - memcpy(t, icmp6, trace_len); - } - ip6_output_mbuf_data(mbuf)->iface = iface_from_id(nh->iface_id); - ip6_output_mbuf_data(mbuf)->nh = nh; + rte_ipv6_solnode_from_addr(&d->dst, &nh->ipv6); + d->len = payload_len; + d->hop_limit = IP6_DEFAULT_HOP_LIMIT; + d->proto = IPPROTO_ICMPV6; next = OUTPUT; next: + if (gr_mbuf_is_traced(mbuf)) { + if (next == ERROR) { + gr_mbuf_trace_add(mbuf, node, 0); + } else { + uint8_t trace_len = RTE_MIN(payload_len, GR_TRACE_ITEM_MAX_LEN); + struct icmp6 *t = gr_mbuf_trace_add(mbuf, node, trace_len); + memcpy(t, icmp6, trace_len); + } + } rte_node_enqueue_x1(graph, node, next, mbuf); } @@ -124,7 +126,7 @@ static struct rte_node_register node = { .process = ndp_ns_output_process, .nb_edges = EDGE_COUNT, .next_nodes = { - [OUTPUT] = "ip6_output", + [OUTPUT] = "icmp6_output", [ERROR] = "ndp_ns_output_error", }, };