diff options
Diffstat (limited to 'hicn-plugin/src/strategy_node.c')
-rw-r--r-- | hicn-plugin/src/strategy_node.c | 266 |
1 files changed, 110 insertions, 156 deletions
diff --git a/hicn-plugin/src/strategy_node.c b/hicn-plugin/src/strategy_node.c index ec57d76e2..add5772a4 100644 --- a/hicn-plugin/src/strategy_node.c +++ b/hicn-plugin/src/strategy_node.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -20,11 +20,11 @@ #include "parser.h" #include "strategy.h" #include "strategy_dpo_ctx.h" -#include "face_db.h" #include "infra.h" #include "mgmt.h" #include "pcs.h" #include "state.h" +#include "data_fwd.h" #include "strategies/strategy_mw.h" /* Registration struct for a graph node */ @@ -60,97 +60,32 @@ hicn_strategy_format_trace (u8 *s, va_list *args) return vft->hicn_format_strategy_trace (s, t); } -always_inline int -hicn_new_interest (hicn_strategy_runtime_t *rt, vlib_buffer_t *b0, u32 *next, - f64 tnow, u8 *nameptr, u16 namelen, hicn_face_id_t outface, - int nh_idx, index_t dpo_ctx_id0, - const hicn_strategy_vft_t *strategy, dpo_type_t dpo_type, - u8 isv6, vl_api_hicn_api_node_stats_get_reply_t *stats) +always_inline void +drop_packet (vlib_main_t *vm, u32 bi0, u32 *n_left_to_next, u32 *next0, + u32 **to_next, u32 *next_index, vlib_node_runtime_t *node) { - int ret; - hicn_hash_node_t *nodep; - hicn_pcs_entry_t *pitp; - hicn_header_t *hicn0; - hicn_main_t *sm = &hicn_main; - hicn_buffer_t *hicnb0 = hicn_get_buffer (b0); - u32 node_id0 = 0; - u8 vft_id0 = dpo_type; - u8 is_cs0 = 0; - u8 hash_entry_id = 0; - u8 bucket_is_overflow = 0; - u32 bucket_id = ~0; - - /* Create PIT node and init PIT entry */ - nodep = hicn_hashtb_alloc_node (rt->pitcs->pcs_table); - if (PREDICT_FALSE (nodep == NULL)) - { - /* Nothing we can do - no mem */ - *next = HICN_STRATEGY_NEXT_ERROR_DROP; - return HICN_ERROR_HASHTB_NOMEM; - } - pitp = hicn_pit_get_data (nodep); - hicn_pit_init_data (pitp); - pitp->shared.create_time = tnow; - - hicn0 = vlib_buffer_get_current (b0); - hicn_lifetime_t imsg_lifetime; - hicn_type_t type = hicnb0->type; - hicn_ops_vft[type.l1]->get_lifetime (type, &hicn0->protocol, &imsg_lifetime); + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0); - if (imsg_lifetime > sm->pit_lifetime_max_ms) - { - imsg_lifetime = sm->pit_lifetime_max_ms; - } - pitp->shared.expire_time = hicn_pcs_get_exp_time (tnow, imsg_lifetime); + *next0 = HICN_STRATEGY_NEXT_ERROR_DROP; - /* Set up the hash node and insert it */ - hicn_hash_entry_t *hash_entry; - hicn_hashtb_init_node (rt->pitcs->pcs_table, nodep, nameptr, namelen); + (*to_next)[0] = bi0; + *to_next += 1; + *n_left_to_next -= 1; - ret = hicn_pcs_pit_insert (rt->pitcs, pitp, nodep, &hash_entry, - hicnb0->name_hash, &node_id0, &dpo_ctx_id0, - &vft_id0, &is_cs0, &hash_entry_id, &bucket_id, - &bucket_is_overflow); - - if (ret == HICN_ERROR_NONE) + // Maybe trace + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b0->flags & VLIB_BUFFER_IS_TRACED))) { - strategy->hicn_add_interest (vnet_buffer (b0)->ip.adj_index[VLIB_TX], - hash_entry); - - /* Add face */ - hicn_face_db_add_face (hicnb0->face_id, &(pitp->u.pit.faces)); - - *next = isv6 ? HICN_STRATEGY_NEXT_INTEREST_FACE6 : - HICN_STRATEGY_NEXT_INTEREST_FACE4; - - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = outface; - stats->pkts_interest_count++; - pitp->u.pit.pe_txnh = nh_idx; - } - else - { - /* Interest aggregate in PIT */ - if (ret == HICN_ERROR_HASHTB_EXIST) - { - hicn_store_internal_state (b0, hicnb0->name_hash, node_id0, - dpo_ctx_id0, vft_id0, hash_entry_id, - bucket_id, bucket_is_overflow); - // We need to take a lock as the lock is not taken on the hash - // entry because it is a CS entry (hash_insert function). - hash_entry->locks++; - *next = is_cs0 ? HICN_STRATEGY_NEXT_INTEREST_HITCS : - HICN_STRATEGY_NEXT_INTEREST_HITPIT; - } - else - { - /* Send the packet to the interest-hitpit node */ - *next = HICN_STRATEGY_NEXT_ERROR_DROP; - } - hicn_faces_flush (&(pitp->u.pit.faces)); - hicn_hashtb_free_node (rt->pitcs->pcs_table, nodep); + hicn_strategy_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = HICN_PACKET_TYPE_INTEREST; + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + t->next_index = *next0; + t->dpo_type = hicn_get_buffer (b0)->vft_id; + t->out_face = -1; } - return (ret); + vlib_validate_buffer_enqueue_x1 (vm, node, *next_index, *to_next, + *n_left_to_next, bi0, *next0); } /* @@ -162,11 +97,19 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) { + int ret; u32 n_left_from, *from, *to_next, n_left_to_next; hicn_strategy_next_t next_index; hicn_strategy_runtime_t *rt = NULL; vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; - f64 tnow; + vlib_buffer_t *b0; + u32 bi0; + hicn_face_id_t outfaces[MAX_OUT_FACES]; + u32 clones[MAX_OUT_FACES]; + u16 outfaces_len; + u32 next0; + const hicn_strategy_vft_t *strategy; + hicn_buffer_t *hicnb0; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -174,97 +117,108 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node, rt = vlib_node_get_runtime_data (vm, hicn_strategy_node.index); rt->pitcs = &hicn_main.pitcs; /* Capture time in vpp terms */ - tnow = vlib_time_now (vm); + next0 = next_index; while (n_left_from > 0) { - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); while (n_left_from > 0 && n_left_to_next > 0) { - u8 isv6; - u8 *nameptr; - u16 namelen; - hicn_name_t name; - hicn_header_t *hicn0; - vlib_buffer_t *b0; - u32 bi0; - hicn_face_id_t outface; - int nh_idx; - u32 next0 = next_index; - int ret; - - /* Prefetch for next iteration. */ + // Prefetch for next iteration if (n_left_from > 1) { vlib_buffer_t *b1; b1 = vlib_get_buffer (vm, from[1]); - CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, LOAD); - CLIB_PREFETCH (&b1->trace_handle, 2 * CLIB_CACHE_LINE_BYTES, - STORE); + CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, LOAD); } - /* Dequeue a packet buffer */ + + // Dequeue a packet buffer bi0 = from[0]; from += 1; n_left_from -= 1; - to_next[0] = bi0; - to_next += 1; - n_left_to_next -= 1; - b0 = vlib_get_buffer (vm, bi0); - next0 = HICN_STRATEGY_NEXT_ERROR_DROP; - hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get ( - vnet_buffer (b0)->ip.adj_index[VLIB_TX]); - const hicn_strategy_vft_t *strategy = - hicn_dpo_get_strategy_vft (dpo_ctx->dpo_type); + // Drop by default + next0 = HICN_STRATEGY_NEXT_ERROR_DROP; - ret = hicn_interest_parse_pkt (b0, &name, &namelen, &hicn0, &isv6); + // Increment counters stats.pkts_processed++; - /* Select next hop */ - /* - * Double check that the interest has been through - * the interest-pcslookup node due to misconfiguration in - * the punting rules. - */ - if (PREDICT_TRUE (ret == HICN_ERROR_NONE && - HICN_IS_NAMEHASH_CACHED (b0) && - strategy->hicn_select_next_hop ( - vnet_buffer (b0)->ip.adj_index[VLIB_TX], &nh_idx, - &outface) == HICN_ERROR_NONE)) + + hicnb0 = hicn_get_buffer (b0); + + // Get the strategy VFT + strategy = hicn_dpo_get_strategy_vft (hicnb0->vft_id); + + // Check we have at least one next hop for the packet + ret = strategy->hicn_select_next_hop ( + hicnb0->dpo_ctx_id, hicnb0->face_id, outfaces, &outfaces_len); + + if (PREDICT_FALSE (ret != HICN_ERROR_NONE || outfaces_len == 0)) + { + drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next, + &next_index, node); + continue; + } + + // Set next node + next0 = hicn_buffer_is_v6 (b0) ? HICN_STRATEGY_NEXT_INTEREST_FACE6 : + HICN_STRATEGY_NEXT_INTEREST_FACE4; + + if (PREDICT_TRUE (ret == HICN_ERROR_NONE)) { - /* - * No need to check if parsing was successful - * here. Already checked in the interest_pcslookup - * node - */ - nameptr = (u8 *) (&name); - hicn_new_interest (rt, b0, &next0, tnow, nameptr, namelen, - outface, nh_idx, - vnet_buffer (b0)->ip.adj_index[VLIB_TX], - strategy, dpo_ctx->dpo_type, isv6, &stats); + // Clone interest if needed + if (outfaces_len > 1) + { + ret = vlib_buffer_clone (vm, bi0, clones, (u16) outfaces_len, + CLIB_CACHE_LINE_BYTES * 2); + ASSERT (ret == outfaces_len); + } + else + { + clones[0] = bi0; + } + + // Send interest to next hops + for (u32 nh = 0; nh < outfaces_len; nh++) + { + vlib_buffer_t *local_b0 = vlib_get_buffer (vm, clones[nh]); + + to_next[0] = clones[nh]; + to_next += 1; + n_left_to_next -= 1; + + vnet_buffer (local_b0)->ip.adj_index[VLIB_TX] = outfaces[nh]; + stats.pkts_interest_count++; + + // Maybe trace + if (PREDICT_FALSE ( + (node->flags & VLIB_NODE_FLAG_TRACE) && + (local_b0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_strategy_trace_t *t = + vlib_add_trace (vm, node, local_b0, sizeof (*t)); + t->pkt_type = HICN_PACKET_TYPE_INTEREST; + t->sw_if_index = + vnet_buffer (local_b0)->sw_if_index[VLIB_RX]; + t->next_index = next0; + t->dpo_type = hicnb0->vft_id; + t->out_face = outfaces[nh]; + } + + /* + * Fix in case of a wrong speculation. Needed for + * cloning the data in the right frame + */ + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, n_left_to_next, + clones[nh], next0); + } } - /* Maybe trace */ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b0->flags & VLIB_BUFFER_IS_TRACED))) + else { - hicn_strategy_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; - t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - t->next_index = next0; - t->dpo_type = dpo_ctx->dpo_type; + drop_packet (vm, bi0, &n_left_from, &next0, &to_next, + &next_index, node); } - /* - * Verify speculative enqueue, maybe switch current - * next frame - */ - /* - * Fix in case of a wrong speculation. Needed for - * cloning the data in the right frame - */ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, - n_left_to_next, bi0, next0); } vlib_put_next_frame (vm, node, next_index, n_left_to_next); |