diff options
Diffstat (limited to 'hicn-plugin/src/data_fwd_node.c')
-rw-r--r-- | hicn-plugin/src/data_fwd_node.c | 542 |
1 files changed, 228 insertions, 314 deletions
diff --git a/hicn-plugin/src/data_fwd_node.c b/hicn-plugin/src/data_fwd_node.c index a3f1a592f..f909ae536 100644 --- a/hicn-plugin/src/data_fwd_node.c +++ b/hicn-plugin/src/data_fwd_node.c @@ -32,291 +32,6 @@ static char *hicn_data_fwd_error_strings[] = { }; /* Declarations */ -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); - -always_inline int -hicn_satisfy_faces (vlib_main_t *vm, u32 b0, hicn_pcs_entry_t *pitp, - u32 *n_left_to_next, u32 **to_next, u32 *next_index, - vlib_node_runtime_t *node, u8 isv6, - vl_api_hicn_api_node_stats_get_reply_t *stats); - -always_inline void -clone_data_to_cs (vlib_main_t *vm, hicn_pit_cs_t *pitcs, - hicn_pcs_entry_t *pitp, hicn_header_t *hicn0, f64 tnow, - hicn_hash_node_t *nodep, vlib_buffer_t *b0, - hicn_hash_entry_t *hash_entry, u64 name_hash, - hicn_buffer_t *hicnb, const hicn_dpo_vft_t *dpo_vft, - dpo_id_t *hicn_dpo_id, hicn_lifetime_t dmsg_lifetime); - -/* packet trace format function */ -always_inline u8 *hicn_data_fwd_format_trace (u8 *s, va_list *args); - -vlib_node_registration_t hicn_data_fwd_node; - -/* - * ICN forwarder node for interests: handling of Data delivered based on ACL. - * - 1 packet at a time - ipv4/tcp ipv6/tcp - */ -static uword -hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, - vlib_frame_t *frame) -{ - - u32 n_left_from, *from, *to_next; - hicn_data_fwd_next_t next_index; - hicn_pit_cs_t *pitcs = &hicn_main.pitcs; - vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; - f64 tnow; - u32 data_received = 1; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - /* Capture time in vpp terms */ - tnow = vlib_time_now (vm); - - while (n_left_from > 0) - { - u32 n_left_to_next; - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *b0; - u8 isv6; - u8 *nameptr; - u16 namelen; - u32 bi0; - u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP; - hicn_header_t *hicn0; - hicn_buffer_t *hicnb0; - hicn_hash_node_t *node0; - const hicn_strategy_vft_t *strategy_vft0; - const hicn_dpo_vft_t *dpo_vft0; - u8 dpo_ctx_id0; - hicn_pcs_entry_t *pitp; - hicn_hash_entry_t *hash_entry0; - int ret = HICN_ERROR_NONE; - - /* Prefetch for next iteration. */ - if (n_left_from > 1) - { - vlib_buffer_t *b1; - b1 = vlib_get_buffer (vm, from[1]); - CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, STORE); - CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, STORE); - } - /* Dequeue a packet buffer */ - /* - * Do not copy the index in the next buffer, we'll do - * it later. The packet might be cloned, so the buffer to move - * to next must be the cloned one - */ - bi0 = from[0]; - from += 1; - n_left_from -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - /* Get hicn buffer and state */ - hicnb0 = hicn_get_buffer (b0); - hicn0 = (hicn_header_t *) (vlib_buffer_get_current (b0)); - hicn_get_internal_state (hicnb0, pitcs, &node0, &strategy_vft0, - &dpo_vft0, &dpo_ctx_id0, &hash_entry0); - - hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen); - isv6 = hicn_buffer_is_v6 (b0); - pitp = hicn_pit_get_data (node0); - - if (PREDICT_FALSE ( - !hicn_node_compare (nameptr, namelen, node0) || - (hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY))) - { - /* - * Remove the lock acquired from - * data_pcslookup node - */ - dpo_id_t hicn_dpo_id0 = { .dpoi_type = - dpo_vft0->hicn_dpo_get_type (), - .dpoi_proto = 0, - .dpoi_next_node = 0, - .dpoi_index = dpo_ctx_id0 }; - hicn_pcs_remove_lock (pitcs, &pitp, &node0, vm, hash_entry0, - dpo_vft0, &hicn_dpo_id0); - - drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next, - &next_index, node); - - goto end_processing; - } - /* - * Check if the hit is instead a collision in the - * hash table. Unlikely to happen. - */ - /* - * there is no guarantee that the type of entry has - * not changed from the lookup. - */ - - if (tnow > pitp->shared.expire_time || - (hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED)) - { - dpo_id_t hicn_dpo_id0 = { .dpoi_type = - dpo_vft0->hicn_dpo_get_type (), - .dpoi_proto = 0, - .dpoi_next_node = 0, - .dpoi_index = dpo_ctx_id0 }; - hicn_pcs_delete (pitcs, &pitp, &node0, vm, hash_entry0, dpo_vft0, - &hicn_dpo_id0); - - drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next, - &next_index, node); - stats.pit_expired_count++; - - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - hicn_data_fwd_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PACKET_TYPE_DATA; - t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - t->next_index = next0; - clib_memcpy (t->packet_data, vlib_buffer_get_current (b0), - sizeof (t->packet_data)); - } - } - else - { - ASSERT ((hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED) == - 0); - - data_received++; - /* - * We do not check if the data is coming from - * the outgoing interest face. - */ - - /* Prepare the buffer for the cloning */ - ret = - hicn_satisfy_faces (vm, bi0, pitp, &n_left_to_next, &to_next, - &next_index, node, isv6, &stats); - - dpo_id_t hicn_dpo_id0 = { .dpoi_type = - dpo_vft0->hicn_dpo_get_type (), - .dpoi_proto = 0, - .dpoi_next_node = 0, - .dpoi_index = dpo_ctx_id0 }; - - if (PREDICT_FALSE (ret != HICN_ERROR_NONE)) - { - hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, hash_entry0, - dpo_vft0, &hicn_dpo_id0); - continue; - } - /* - * Call the strategy callback since the - * interest has been satisfied - */ - strategy_vft0->hicn_receive_data (dpo_ctx_id0, - pitp->u.pit.pe_txnh); - -#if HICN_FEATURE_CS - hicn_lifetime_t dmsg_lifetime; - - hicn_type_t type = hicnb0->type; - hicn_ops_vft[type.l1]->get_lifetime (type, &hicn0->protocol, - &dmsg_lifetime); - - if (dmsg_lifetime) - { - /* - * Clone data packet in the content store and - * convert the PIT entry into a CS entry - */ - clone_data_to_cs (vm, pitcs, pitp, hicn0, tnow, node0, b0, - hash_entry0, hicnb0->name_hash, hicnb0, - dpo_vft0, &hicn_dpo_id0, dmsg_lifetime); - - hicn_pcs_remove_lock (pitcs, &pitp, &node0, vm, hash_entry0, - NULL, NULL); - } - else - { - /* - * If the packet is copied and not cloned, we need to free - * the vlib_buffer - */ - if (hicnb0->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL) - { - vlib_buffer_free_one (vm, bi0); - } - else - { - /* - * Remove one reference as the buffer is no - * longer in any frame. The vlib_buffer will be freed - * when all its cloned vlib_buffer will be freed. - */ - b0->ref_count--; - } - - /* Delete the PIT entry */ - hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, hash_entry0, - dpo_vft0, &hicn_dpo_id0); - } -#else - ASSERT (pitp == hicn_pit_get_data (node0)); - /* - * If the packet is copied and not cloned, we need to free the - * vlib_buffer - */ - if (hicnb0->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL) - { - vlib_buffer_free_one (vm, bi0); - } - else - { - /* - * Remove one reference as the buffer is no - * longer in any frame. The vlib_buffer will be freed when - * all its cloned vlib_buffer will be freed. - */ - b0->ref_count--; - } - - /* Delete the PIT entry */ - hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, hash_entry0, - dpo_vft0, &hicn_dpo_id0); -#endif - } - end_processing: - - /* Incr packet counter */ - stats.pkts_processed += 1; - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - u32 pit_int_count = hicn_pit_get_int_count (pitcs); - u32 pit_cs_count = hicn_pit_get_cs_count (pitcs); - - vlib_node_increment_counter (vm, hicn_data_fwd_node.index, - HICNFWD_ERROR_DATAS, stats.pkts_data_count); - - update_node_counter (vm, hicn_data_fwd_node.index, HICNFWD_ERROR_INT_COUNT, - pit_int_count); - update_node_counter (vm, hicn_data_fwd_node.index, HICNFWD_ERROR_CS_COUNT, - pit_cs_count); - update_node_counter (vm, hicn_data_fwd_node.index, - HICNFWD_ERROR_INTEREST_AGG_ENTRY, - stats.pkts_data_count / data_received); - - return (frame->n_vectors); -} - 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) @@ -339,7 +54,8 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp, { int found = 0; int ret = HICN_ERROR_NONE; - u32 *clones = NULL, *header = NULL; + u32 inline_clones[HICN_FACE_DB_INLINE_FACES]; + u32 *clones = inline_clones, *header = NULL; u32 n_left_from = 0; u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP, next1 = HICN_DATA_FWD_NEXT_ERROR_DROP; @@ -354,8 +70,11 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp, * need to be careful to clone it only 254 times as the buffer * already has n_add_reds=1. */ - vec_alloc (clones, pitp->u.pit.faces.n_faces); - header = clones; + if (hicn_pcs_entry_pit_get_n_faces (pitp) > HICN_FACE_DB_INLINE_FACES) + { + vec_alloc (clones, hicn_pcs_entry_pit_get_n_faces (pitp)); + header = clones; + } /* Clone bi0 */ vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0); @@ -378,7 +97,7 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp, { /* Add one reference to maintain the buffer in the CS. * b0->ref_count == 0 has two meaning: it has 1 buffer or no buffer - * chained to it. vlib_buffer_clone2 add a number of reference equalt to + * chained to it. vlib_buffer_clone2 add a number of reference equal to * pitp->u.pit.faces.n_faces - 1 as vlib_buffer_clone does. So after all * the packet are forwarded the buffer stored in the CS will have * ref_count == 0; @@ -386,17 +105,16 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp, b0->ref_count++; } - found = n_left_from = vlib_buffer_clone2 ( - vm, bi0, clones, pitp->u.pit.faces.n_faces, buffer_advance); + found = n_left_from = + vlib_buffer_clone2 (vm, bi0, clones, pitp->u.pit.n_faces, buffer_advance); - ASSERT (n_left_from == pitp->u.pit.faces.n_faces); + ASSERT (n_left_from == hicn_pcs_entry_pit_get_n_faces (pitp)); /* Index to iterate over the faces */ int i = 0; while (n_left_from > 0) { - // Dual loop, X2 while (n_left_from >= 4 && *n_left_to_next >= 2) { @@ -413,8 +131,11 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp, CLIB_PREFETCH (h3, 2 * CLIB_CACHE_LINE_BYTES, STORE); } - face0 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces); - face1 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces); + face0 = hicn_pcs_entry_pit_get_dpo_face (pitp, i); + face1 = hicn_pcs_entry_pit_get_dpo_face (pitp, i + 1); + + // Increment index + i += 2; h0 = vlib_get_buffer (vm, clones[0]); h1 = vlib_get_buffer (vm, clones[1]); @@ -469,7 +190,8 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp, u32 hi0; hicn_face_id_t face0; - face0 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces); + face0 = hicn_pcs_entry_pit_get_dpo_face (pitp, i); + i += 1; h0 = vlib_get_buffer (vm, clones[0]); @@ -530,36 +252,28 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp, } always_inline void -clone_data_to_cs (vlib_main_t *vm, hicn_pit_cs_t *pitcs, - hicn_pcs_entry_t *pitp, hicn_header_t *hicn0, f64 tnow, - hicn_hash_node_t *nodep, vlib_buffer_t *b0, - hicn_hash_entry_t *hash_entry, u64 name_hash, - hicn_buffer_t *hicnb, const hicn_dpo_vft_t *dpo_vft, - dpo_id_t *hicn_dpo_id, hicn_lifetime_t dmsg_lifetime) +clone_data_to_cs (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *pcs_entry, + u32 buffer_index, hicn_header_t *hicn0, f64 tnow, + hicn_lifetime_t dmsg_lifetime) { /* * At this point we think we're safe to proceed. Store the CS buf in * the PIT/CS hashtable entry */ - /* - * Start turning the PIT into a CS. Note that we may be stepping on - * the PIT part of the union as we update the CS part, so don't - * expect the PIT part to be valid after this point. - */ - hicn_pit_to_cs (vm, pitcs, pitp, hash_entry, nodep, dpo_vft, hicn_dpo_id); - - pitp->shared.create_time = tnow; + // Start turning the PIT into a CS. Note that we may be stepping on the PIT + // part of the union as we update the CS part, so don't expect the PIT part + // to be valid after this point. + hicn_pit_to_cs (pitcs, pcs_entry, buffer_index); + hicn_pcs_entry_set_create_time (pcs_entry, tnow); if (dmsg_lifetime < HICN_PARAM_CS_LIFETIME_MIN || dmsg_lifetime > HICN_PARAM_CS_LIFETIME_MAX) { dmsg_lifetime = HICN_PARAM_CS_LIFETIME_DFLT; } - pitp->shared.expire_time = hicn_pcs_get_exp_time (tnow, dmsg_lifetime); - - /* Store the original packet buffer in the CS node */ - pitp->u.cs.cs_pkt_buf = vlib_get_buffer_index (vm, b0); + hicn_pcs_entry_set_expire_time (pcs_entry, + hicn_pcs_get_exp_time (tnow, dmsg_lifetime)); } /* packet trace format function */ @@ -579,6 +293,206 @@ hicn_data_fwd_format_trace (u8 *s, va_list *args) return (s); } +vlib_node_registration_t hicn_data_fwd_node; + +/* + * ICN forwarder node for interests: handling of Data delivered based on ACL. + * - 1 packet at a time - ipv4/tcp ipv6/tcp + */ +static uword +hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + + u32 n_left_from, *from, *to_next; + hicn_data_fwd_next_t next_index; + hicn_data_fwd_runtime_t *rt; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + f64 tnow; + u32 data_received = 1; + vlib_buffer_t *b0; + u8 isv6; + u32 bi0; + u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP; + hicn_header_t *hicn0; + hicn_buffer_t *hicnb0; + const hicn_strategy_vft_t *strategy_vft0 = NULL; + const hicn_dpo_vft_t *dpo_vft0; + u8 dpo_ctx_id0 = ~0; + u32 pcs_entry_id; + hicn_pcs_entry_t *pcs_entry = NULL; + hicn_lifetime_t dmsg_lifetime; + int ret = HICN_ERROR_NONE; + + rt = vlib_node_get_runtime_data (vm, node->node_index); + + if (PREDICT_FALSE (rt->pitcs == NULL)) + { + rt->pitcs = &hicn_main.pitcs; + } + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + /* Capture time in vpp terms */ + tnow = vlib_time_now (vm); + + while (n_left_from > 0) + { + u32 n_left_to_next; + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + while (n_left_from > 0 && n_left_to_next > 0) + { + /* Prefetch for next iteration. */ + if (n_left_from > 1) + { + vlib_buffer_t *b1; + b1 = vlib_get_buffer (vm, from[1]); + CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, STORE); + } + + // Dequeue a packet buffer. Do not copy the index in the next buffer, + // we'll do it later. The packet might be cloned, so the buffer to + // move to next must be the cloned one + bi0 = from[0]; + from += 1; + n_left_from -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + // Get hicn buffer and state + hicnb0 = hicn_get_buffer (b0); + hicn0 = (hicn_header_t *) (vlib_buffer_get_current (b0)); + + hicn_get_internal_state (hicnb0, &pcs_entry_id, &strategy_vft0, + &dpo_vft0, &dpo_ctx_id0); + + // Get PCS entry + pcs_entry = + hicn_pcs_entry_get_entry_from_index (rt->pitcs, pcs_entry_id); + + isv6 = hicn_buffer_is_v6 (b0); + + // If PCS entry is CS, drop the packet + if (PREDICT_FALSE (hicn_pcs_entry_is_cs (pcs_entry))) + { + drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next, + &next_index, node); + + goto end_processing; + } + + // We are sure the entry is a PIT entry. Check whether it is expired. + if (tnow > hicn_pcs_entry_get_expire_time (pcs_entry)) + { + // Entry expired. Release lock + hicn_pcs_entry_remove_lock (rt->pitcs, pcs_entry); + + // Drop packet + drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next, + &next_index, node); + + // Update stats + stats.pit_expired_count++; + + // Trace + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_data_fwd_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = HICN_PACKET_TYPE_DATA; + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + t->next_index = next0; + clib_memcpy (t->packet_data, vlib_buffer_get_current (b0), + sizeof (t->packet_data)); + } + } + else + { + // Update stats + data_received++; + + /* + * We do not check if the data is coming from + * the outgoing interest face. + */ + + // Prepare the buffer for the cloning + ret = + hicn_satisfy_faces (vm, bi0, pcs_entry, &n_left_to_next, + &to_next, &next_index, node, isv6, &stats); + + if (PREDICT_FALSE (ret != HICN_ERROR_NONE)) + { + hicn_pcs_entry_remove_lock (rt->pitcs, pcs_entry); + continue; + } + + // Call the strategy callback since the interest has been + // satisfied + strategy_vft0->hicn_receive_data ( + dpo_ctx_id0, vnet_buffer (b0)->ip.adj_index[VLIB_RX]); + + dmsg_lifetime = hicn_buffer_get_lifetime (b0); + + if (dmsg_lifetime) + { + // Clone data packet in the content store and convert the PIT + // entry into a CS entry + clone_data_to_cs (rt->pitcs, pcs_entry, bi0, hicn0, tnow, + dmsg_lifetime); + } + else + { + /* + * If the packet is copied and not cloned, we need to free + * the vlib_buffer + */ + if (hicnb0->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL) + { + vlib_buffer_free_one (vm, bi0); + } + else + { + /* + * Remove one reference as the buffer is no + * longer in any frame. The vlib_buffer will be freed + * when all its cloned vlib_buffer will be freed. + */ + b0->ref_count--; + } + // Delete the PIT entry + hicn_pcs_entry_remove_lock (rt->pitcs, pcs_entry); + } + } + end_processing: + + /* Incr packet counter */ + stats.pkts_processed += 1; + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + u32 pit_int_count = hicn_pcs_get_pit_count (rt->pitcs); + u32 pit_cs_count = hicn_pcs_get_cs_count (rt->pitcs); + + vlib_node_increment_counter (vm, hicn_data_fwd_node.index, + HICNFWD_ERROR_DATAS, stats.pkts_data_count); + + update_node_counter (vm, hicn_data_fwd_node.index, HICNFWD_ERROR_INT_COUNT, + pit_int_count); + update_node_counter (vm, hicn_data_fwd_node.index, HICNFWD_ERROR_CS_COUNT, + pit_cs_count); + update_node_counter (vm, hicn_data_fwd_node.index, + HICNFWD_ERROR_INTEREST_AGG_ENTRY, + stats.pkts_data_count / data_received); + + return (frame->n_vectors); +} + /* * Node registration for the data forwarder node */ |