From 6b94663b2455e212009a544ae23bb6a8c55407f8 Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Thu, 9 Jun 2022 21:34:09 +0200 Subject: refactor(lib, hicn-light, vpp, hiperf): HICN-723 - move infra data structure into the shared lib - new packet cache using double hashing and lookup on prefix suffix - testing updates - authenticated requests using interest manifests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mauro Sardara Co-authored-by: Jordan Augé Co-authored-by: Michele Papalini Co-authored-by: Olivier Roques Co-authored-by: Enrico Loparco Change-Id: Iaddebfe6aa5279ea8553433b0f519578f6b9ccd9 Signed-off-by: Luca Muscariello --- hicn-plugin/includes/vpp_plugins/hicn/error.h | 112 ++- hicn-plugin/src/CMakeLists.txt | 3 + hicn-plugin/src/cli.c | 90 +- hicn-plugin/src/data_fwd_node.c | 17 +- hicn-plugin/src/data_input_node.c | 8 +- hicn-plugin/src/data_pcslookup_node.c | 14 +- hicn-plugin/src/faces/app/face_prod_node.c | 150 +-- hicn-plugin/src/faces/face.c | 6 +- hicn-plugin/src/faces/face.h | 69 +- hicn-plugin/src/faces/face_flags.h | 39 + hicn-plugin/src/faces/face_node.c | 290 +++--- hicn-plugin/src/faces/iface_node.c | 316 ++++-- hicn-plugin/src/hicn.c | 14 +- hicn-plugin/src/hicn.h | 58 +- hicn-plugin/src/hicn_buffer_flags.h | 35 + hicn-plugin/src/interest_hitcs_node.c | 14 +- hicn-plugin/src/interest_hitpit.h | 4 +- hicn-plugin/src/interest_hitpit_node.c | 17 +- hicn-plugin/src/interest_pcslookup_node.c | 20 +- hicn-plugin/src/parser.h | 186 ++-- hicn-plugin/src/pg.c | 1340 ++++--------------------- hicn-plugin/src/pg.h | 142 ++- hicn-plugin/src/pg_node.c | 1132 +++++++++++++++++++++ hicn-plugin/src/route.c | 10 +- hicn-plugin/src/strategy_node.c | 27 +- 25 files changed, 2307 insertions(+), 1806 deletions(-) create mode 100644 hicn-plugin/src/faces/face_flags.h create mode 100644 hicn-plugin/src/hicn_buffer_flags.h create mode 100644 hicn-plugin/src/pg_node.c (limited to 'hicn-plugin') diff --git a/hicn-plugin/includes/vpp_plugins/hicn/error.h b/hicn-plugin/includes/vpp_plugins/hicn/error.h index a8a941a79..af9f5da46 100644 --- a/hicn-plugin/includes/vpp_plugins/hicn/error.h +++ b/hicn-plugin/includes/vpp_plugins/hicn/error.h @@ -25,67 +25,69 @@ #define foreach_hicn_error \ _ (NONE, 0, "Ok") \ _ (UNSPECIFIED, -128, "Unspecified Error") \ - _ (FACE_NOT_FOUND, -129, "Face not found in Face table") \ - _ (FACE_NULL, -130, "Face null") \ - _ (FACE_IP_ADJ_NOT_FOUND, -131, "Ip adjacecny for face not found") \ - _ (FACE_HW_INT_NOT_FOUND, -132, "Hardware interface not found") \ - _ (FACE_NOMEM, -133, "Face table is full") \ - _ (FACE_NO_GLOBAL_IP, -134, "No global ip address for face") \ - _ (FACE_NOT_FOUND_IN_ENTRY, -135, "Face not found in entry") \ - _ (FACE_ALREADY_DELETED, -136, "Face alredy deleted") \ - _ (FACE_ALREADY_CREATED, -137, "Face alredy created") \ - _ (FWD_NOT_ENABLED, -138, "hICN forwarder not enabled") \ - _ (FWD_ALREADY_ENABLED, -139, "hICN forwarder alredy enabled") \ - _ (PARSER_UNSUPPORTED_PROTO, -140, "Unsupported protocol") \ - _ (PARSER_PKT_INVAL, -141, "Packet null") \ - _ (PIT_CONFIG_MINLT_OOB, -142, "Min lifetime ouf of bounds") \ - _ (PIT_CONFIG_MAXLT_OOB, -143, "Max lifetime ouf of bounds") \ - _ (PIT_CONFIG_MINMAXLT, -144, "Min lifetime grater than max lifetime") \ - _ (PIT_CONFIG_DFTLT_OOB, -145, "Default lifetime ouf of bounds") \ - _ (PIT_CONFIG_SIZE_OOB, -146, "Pit size ouf of bounds") \ - _ (CS_CONFIG_SIZE_OOB, -147, "CS size ouf of bounds") \ - _ (CS_CONFIG_RESERVED_OOB, -148, \ + _ (FACE_NOT_FOUND, -1000, "Face not found in Face table") \ + _ (FACE_NULL, -1001, "Face null") \ + _ (FACE_IP_ADJ_NOT_FOUND, -1002, "Ip adjacecny for face not found") \ + _ (FACE_HW_INT_NOT_FOUND, -1003, "Hardware interface not found") \ + _ (FACE_NOMEM, -1004, "Face table is full") \ + _ (FACE_NO_GLOBAL_IP, -1005, "No global ip address for face") \ + _ (FACE_NOT_FOUND_IN_ENTRY, -1006, "Face not found in entry") \ + _ (FACE_ALREADY_DELETED, -1007, "Face alredy deleted") \ + _ (FACE_ALREADY_CREATED, -1008, "Face alredy created") \ + _ (FWD_NOT_ENABLED, -2000, "hICN forwarder not enabled") \ + _ (FWD_ALREADY_ENABLED, -2001, "hICN forwarder alredy enabled") \ + _ (PARSER_UNSUPPORTED_PROTO, -3000, "Unsupported protocol") \ + _ (PARSER_PKT_INVAL, -3001, "Packet null") \ + _ (PARSER_MAPME_PACKET, -3002, "Packet is mapme") \ + _ (PIT_CONFIG_MINLT_OOB, -4000, "Min lifetime ouf of bounds") \ + _ (PIT_CONFIG_MAXLT_OOB, -4001, "Max lifetime ouf of bounds") \ + _ (PIT_CONFIG_MINMAXLT, -4002, "Min lifetime grater than max lifetime") \ + _ (PIT_CONFIG_DFTLT_OOB, -4003, "Default lifetime ouf of bounds") \ + _ (PIT_CONFIG_SIZE_OOB, -4004, "Pit size ouf of bounds") \ + _ (CS_CONFIG_SIZE_OOB, -5000, "CS size ouf of bounds") \ + _ (CS_CONFIG_RESERVED_OOB, -5001, \ "Reseved CS must be between 0 and 100 (excluded)") \ - _ (DPO_CTX_NHOPS_NS, -149, "No space for additional next hop") \ - _ (DPO_CTX_NHOPS_EXISTS, -150, "Next hop already in the route") \ - _ (DPO_CTX_NOT_FOUND, -151, "Dpo context not found") \ - _ (DPO_MGR_ID_NOT_VALID, -152, "Dpo id for strategy and context not valid") \ - _ (HASHTB_HASH_NOT_FOUND, -153, "Hash not found in hash table") \ - _ (HASHTB_HASH_INVAL, -154, "Error while calculating the hash") \ - _ (HASHTB_NOMEM, -155, "Unable to allocate new buckets or nodes") \ - _ (HASHTB_INVAL, -156, "Invalid argument") \ - _ (HASHTB_KEY_INVAL, -157, "Invalid hashtb key") \ - _ (HASHTB_EXIST, -158, "Hash already in hashtable") \ - _ (ROUTE_INVAL, -159, "Invalid face id and weight") \ - _ (ROUTE_NO_LD, -160, "Expected load balance dpo") \ - _ (ROUTE_MLT_LD, -161, "Unexpected mulitple buckets in load balance dpo") \ - _ (ROUTE_NO_INSERT, -162, "Unable to insert a new FIB entry") \ - _ (ROUTE_DPO_NO_HICN, -163, "Dpo is not of type hICN") \ - _ (ROUTE_NOT_FOUND, -164, "Route not found in FIB") \ - _ (ROUTE_NOT_UPDATED, -165, "Unable to update route") \ - _ (ROUTE_ALREADY_EXISTS, -166, "Route already in FIB") \ - _ (CLI_INVAL, -167, "Invalid input") \ - _ (IPS_ADDR_TYPE_NONUNIFORM, -168, \ + _ (DPO_CTX_NHOPS_NS, -6000, "No space for additional next hop") \ + _ (DPO_CTX_NHOPS_EXISTS, -6001, "Next hop already in the route") \ + _ (DPO_CTX_NOT_FOUND, -6002, "Dpo context not found") \ + _ (DPO_MGR_ID_NOT_VALID, -6003, \ + "Dpo id for strategy and context not valid") \ + _ (HASHTB_HASH_NOT_FOUND, -7000, "Hash not found in hash table") \ + _ (HASHTB_HASH_INVAL, -7001, "Error while calculating the hash") \ + _ (HASHTB_NOMEM, -7002, "Unable to allocate new buckets or nodes") \ + _ (HASHTB_INVAL, -7003, "Invalid argument") \ + _ (HASHTB_KEY_INVAL, -7004, "Invalid hashtb key") \ + _ (HASHTB_EXIST, -7005, "Hash already in hashtable") \ + _ (ROUTE_INVAL, -8000, "Invalid face id and weight") \ + _ (ROUTE_NO_LD, -8001, "Expected load balance dpo") \ + _ (ROUTE_MLT_LD, -8002, "Unexpected mulitple buckets in load balance dpo") \ + _ (ROUTE_NO_INSERT, -8003, "Unable to insert a new FIB entry") \ + _ (ROUTE_DPO_NO_HICN, -8004, "Dpo is not of type hICN") \ + _ (ROUTE_NOT_FOUND, -8005, "Route not found in FIB") \ + _ (ROUTE_NOT_UPDATED, -8006, "Unable to update route") \ + _ (ROUTE_ALREADY_EXISTS, -8007, "Route already in FIB") \ + _ (CLI_INVAL, -9000, "Invalid input") \ + _ (IPS_ADDR_TYPE_NONUNIFORM, -10000, \ "Src and dst addr have different ip types") \ - _ (FACE_TYPE_EXISTS, -169, "Face type already registered") \ - _ (NO_BUFFERS, -170, "No vlib_buffer available for packet cloning.") \ - _ (NOT_IMPLEMENTED, -171, "Function not yet implemented") \ - _ (IFACE_IP_ADJ_NOT_FOUND, -172, \ + _ (FACE_TYPE_EXISTS, -11000, "Face type already registered") \ + _ (NO_BUFFERS, -12000, "No vlib_buffer available for packet cloning.") \ + _ (NOT_IMPLEMENTED, -13000, "Function not yet implemented") \ + _ (IFACE_IP_ADJ_NOT_FOUND, -14000, \ "IP adjacency on incomplete face not available") \ - _ (APPFACE_ALREADY_ENABLED, -173, \ + _ (APPFACE_ALREADY_ENABLED, -15000, \ "Application face already enabled on interface") \ - _ (APPFACE_FEATURE, -174, "Error while enabling app face feature") \ - _ (APPFACE_NOT_FOUND, -175, "Application face not found") \ - _ (APPFACE_PROD_PREFIX_NULL, -176, \ + _ (APPFACE_FEATURE, -15001, "Error while enabling app face feature") \ + _ (APPFACE_NOT_FOUND, -15002, "Application face not found") \ + _ (APPFACE_PROD_PREFIX_NULL, -15003, \ "Prefix must not be null for producer face") \ - _ (STRATEGY_NH_NOT_FOUND, -177, "Next hop not found") \ - _ (MW_STRATEGY_SET, -178, "Error while setting weight for next hop") \ - _ (STRATEGY_NOT_FOUND, -179, "Strategy not found") \ - _ (UDP_TUNNEL_NOT_FOUND, -180, "Udp tunnel not found") \ - _ (UDP_TUNNEL_SRC_DST_TYPE, -181, \ + _ (STRATEGY_NH_NOT_FOUND, -16000, "Next hop not found") \ + _ (MW_STRATEGY_SET, -16001, "Error while setting weight for next hop") \ + _ (STRATEGY_NOT_FOUND, -16002, "Strategy not found") \ + _ (UDP_TUNNEL_NOT_FOUND, -17000, "Udp tunnel not found") \ + _ (UDP_TUNNEL_SRC_DST_TYPE, -17001, \ "Src and dst addresses have different type (ipv4 and ipv6)") \ - _ (MAPME_NEXT_HOP_ADDED, -182, "Next hop added to mapme") \ - _ (MAPME_NEXT_HOP_NOT_ADDED, -183, "Next hop added to mapme") + _ (MAPME_NEXT_HOP_ADDED, -18000, "Next hop added to mapme") \ + _ (MAPME_NEXT_HOP_NOT_ADDED, -18001, "Next hop added to mapme") typedef enum { diff --git a/hicn-plugin/src/CMakeLists.txt b/hicn-plugin/src/CMakeLists.txt index 2141ec596..e071b3b9d 100644 --- a/hicn-plugin/src/CMakeLists.txt +++ b/hicn-plugin/src/CMakeLists.txt @@ -59,6 +59,7 @@ set(HICN_PLUGIN_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_prod_node.c ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_app_cli.c ${CMAKE_CURRENT_SOURCE_DIR}/pg.c + ${CMAKE_CURRENT_SOURCE_DIR}/pg_node.c ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_mw.c ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw.c ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw_cli.c @@ -83,6 +84,7 @@ set(HICN_PLUGIN_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/pcs.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_buffer_flags.h ${CMAKE_CURRENT_SOURCE_DIR}/state.h ${CMAKE_CURRENT_SOURCE_DIR}/infra.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn_msg_enum.h @@ -99,6 +101,7 @@ set(HICN_PLUGIN_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/error.h ${CMAKE_CURRENT_SOURCE_DIR}/face_db.h ${CMAKE_CURRENT_SOURCE_DIR}/faces/face.h + ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_flags.h ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_node.h ${CMAKE_CURRENT_SOURCE_DIR}/faces/iface_node.h ${CMAKE_CURRENT_SOURCE_DIR}/faces/inlines.h diff --git a/hicn-plugin/src/cli.c b/hicn-plugin/src/cli.c index cd45607ca..f743f6362 100644 --- a/hicn-plugin/src/cli.c +++ b/hicn-plugin/src/cli.c @@ -585,13 +585,15 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd) { - clib_error_t *cl_err; - int rv = HICN_ERROR_NONE; - hicnpg_server_main_t *pg_main = &hicnpg_server_main; int payload_size = 1440; u32 sw_if_index = ~0; vnet_main_t *vnm = vnet_get_main (); - fib_prefix_t *prefix = calloc (1, sizeof (fib_prefix_t)); + fib_prefix_t prefix; + u32 hicnpg_server_index; + ip46_address_t locator; + + locator.as_u64[0] = 0; + locator.as_u64[1] = 0; /* Get a line of input. */ unformat_input_t _line_input, *line_input = &_line_input; @@ -601,7 +603,7 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t *vm, while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { if (unformat (line_input, "name %U/%d", unformat_ip46_address, - &prefix->fp_addr, IP46_TYPE_ANY, &prefix->fp_len)) + &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) { ; } @@ -618,6 +620,11 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t *vm, { ; } + else if (unformat (line_input, "dst %U", unformat_ip46_address, + &locator, IP46_TYPE_ANY)) + { + ; + } else { return (clib_error_return (0, "Unknown input '%U'", @@ -628,70 +635,45 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t *vm, } /* Attach our packet-gen node for ip4 udp local traffic */ - if ((prefix->fp_addr.ip6.as_u64[0] == (u64) 0 && - prefix->fp_addr.ip6.as_u64[1] == 0) || - payload_size == 0 || sw_if_index == ~0) + if ((prefix.fp_addr.ip6.as_u64[0] == (u64) 0 && + prefix.fp_addr.ip6.as_u64[1] == 0) || + payload_size == 0 || sw_if_index == ~0 || + ip46_address_is_zero (&locator)) { - return clib_error_return (0, "Error: must supply local port, payload " + return clib_error_return (0, "Error: must supply locator, payload " "size and incoming hICN prefix"); } // Remove bits that are out of the subnet - if (ip46_address_is_ip4 (&prefix->fp_addr)) + if (ip46_address_is_ip4 (&prefix.fp_addr)) { ip4_address_t mask; - ip4_preflen_to_mask (prefix->fp_len, &mask); - prefix->fp_addr.ip4.as_u32 = prefix->fp_addr.ip4.as_u32 & mask.as_u32; - prefix->fp_proto = FIB_PROTOCOL_IP4; + ip4_preflen_to_mask (prefix.fp_len, &mask); + prefix.fp_addr.ip4.as_u32 = prefix.fp_addr.ip4.as_u32 & mask.as_u32; + prefix.fp_proto = FIB_PROTOCOL_IP4; } else { ip6_address_t mask; - ip6_preflen_to_mask (prefix->fp_len, &mask); - prefix->fp_addr.ip6.as_u64[0] = - prefix->fp_addr.ip6.as_u64[0] & mask.as_u64[0]; - prefix->fp_addr.ip6.as_u64[1] = - prefix->fp_addr.ip6.as_u64[1] & mask.as_u64[1]; - prefix->fp_proto = FIB_PROTOCOL_IP6; + ip6_preflen_to_mask (prefix.fp_len, &mask); + prefix.fp_addr.ip6.as_u64[0] = + prefix.fp_addr.ip6.as_u64[0] & mask.as_u64[0]; + prefix.fp_addr.ip6.as_u64[1] = + prefix.fp_addr.ip6.as_u64[1] & mask.as_u64[1]; + prefix.fp_proto = FIB_PROTOCOL_IP6; } - /* Allocate the buffer with the actual content payload TLV */ - int n_buf = vlib_buffer_alloc (vm, &pg_main->pgen_svr_buffer_idx, 1); - - if (n_buf == 0) + fib_protocol_t dest_proto = + ip46_address_is_ip4 (&locator) ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; + if (prefix.fp_proto != dest_proto) { - return (clib_error_return (0, "Impossible to allocate paylod buffer.")); + return clib_error_return (0, "Error: prefix and locator must be of the " + "same protocol"); } - vlib_buffer_t *rb = NULL; - rb = vlib_get_buffer (vm, pg_main->pgen_svr_buffer_idx); - - pg_main->pgen_srv_hicn_name = prefix; - - /* Initialize the buffer data with zeros */ - memset (rb->data, 0, payload_size); - rb->current_length = payload_size; - - vnet_feature_enable_disable ("ip4-unicast", "hicnpg-server", sw_if_index, 1, - 0, 0); - vnet_feature_enable_disable ("ip6-unicast", "hicnpg-server", sw_if_index, 1, - 0, 0); - - switch (rv) - { - case 0: - cl_err = 0; - break; - - case VNET_API_ERROR_UNIMPLEMENTED: - cl_err = clib_error_return (0, "Unimplemented, NYI"); - break; - - default: - cl_err = clib_error_return (0, "hicn pgen server returned %d", rv); - } - - return cl_err; + // Create hicnpg_server + return hicnpg_server_add_and_lock (&prefix, &hicnpg_server_index, &locator, + payload_size); } static clib_error_t * @@ -855,7 +837,7 @@ VLIB_CLI_COMMAND (hicn_cli_pgen_client_set_command, static) = { VLIB_CLI_COMMAND (hicn_cli_pgen_server_set_command, static) = { .path = "hicn pgen server", .short_help = "hicn pgen server name intfc " - "size ", + "dst size ", .long_help = "Run hicn in packet-gen server mode\n", .function = hicn_cli_pgen_server_set_command_fn, }; diff --git a/hicn-plugin/src/data_fwd_node.c b/hicn-plugin/src/data_fwd_node.c index 6acb5915b..a3f1a592f 100644 --- a/hicn-plugin/src/data_fwd_node.c +++ b/hicn-plugin/src/data_fwd_node.c @@ -91,7 +91,6 @@ hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, u16 namelen; u32 bi0; u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP; - hicn_name_t name; hicn_header_t *hicn0; hicn_buffer_t *hicnb0; hicn_hash_node_t *node0; @@ -124,15 +123,15 @@ hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, /* 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); - ret = hicn_data_parse_pkt (b0, &name, &namelen, &hicn0, &isv6); + hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen); + isv6 = hicn_buffer_is_v6 (b0); pitp = hicn_pit_get_data (node0); - nameptr = (u8 *) (&name); if (PREDICT_FALSE ( - ret != HICN_ERROR_NONE || !hicn_node_compare (nameptr, namelen, node0) || (hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY))) { @@ -182,7 +181,7 @@ hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, { hicn_data_fwd_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; + 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), @@ -442,7 +441,7 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp, { hicn_data_fwd_trace_t *t = vlib_add_trace (vm, node, h0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; + t->pkt_type = HICN_PACKET_TYPE_DATA; t->sw_if_index = vnet_buffer (h0)->sw_if_index[VLIB_RX]; t->next_index = next0; clib_memcpy (t->packet_data, vlib_buffer_get_current (h0), @@ -453,7 +452,7 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp, { hicn_data_fwd_trace_t *t = vlib_add_trace (vm, node, h1, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; + t->pkt_type = HICN_PACKET_TYPE_DATA; t->sw_if_index = vnet_buffer (h1)->sw_if_index[VLIB_RX]; t->next_index = next1; clib_memcpy (t->packet_data, vlib_buffer_get_current (h1), @@ -491,7 +490,7 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp, { hicn_data_fwd_trace_t *t = vlib_add_trace (vm, node, h0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; + t->pkt_type = HICN_PACKET_TYPE_DATA; t->sw_if_index = vnet_buffer (h0)->sw_if_index[VLIB_RX]; t->next_index = next0; clib_memcpy (t->packet_data, vlib_buffer_get_current (h0), @@ -607,4 +606,4 @@ VLIB_REGISTER_NODE(hicn_data_fwd_node) = * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */ + */ \ No newline at end of file diff --git a/hicn-plugin/src/data_input_node.c b/hicn-plugin/src/data_input_node.c index 46fda1080..65bba7b1b 100644 --- a/hicn-plugin/src/data_input_node.c +++ b/hicn-plugin/src/data_input_node.c @@ -80,6 +80,7 @@ hicn_data_input_set_adj_index (vlib_buffer_t *b, const ip46_address_t *dst_addr, const hicn_dpo_ctx_t *dpo_ctx) { + CLIB_UNUSED (u8 set) = 0; for (u8 pos = 0; pos < dpo_ctx->entry_count; pos++) { hicn_face_t *face = hicn_dpoi_get_from_idx (dpo_ctx->next_hops[pos]); @@ -87,9 +88,12 @@ hicn_data_input_set_adj_index (vlib_buffer_t *b, if (ip46_address_cmp (&(face->nat_addr), dst_addr) == 0) { vnet_buffer (b)->ip.adj_index[VLIB_RX] = face->dpo.dpoi_index; + set = 1; break; } } + + ASSERT (set == 1); } static uword @@ -147,7 +151,7 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node, src_addr1 = &ip1->src_address; ip46_address_set_ip6 (&dst_addr0, &ip0->dst_address); - ip46_address_set_ip6 (&dst_addr0, &ip1->dst_address); + ip46_address_set_ip6 (&dst_addr1, &ip1->dst_address); ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, p0); ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, p1); @@ -701,4 +705,4 @@ VNET_FEATURE_INIT (hicn_data_input_ip4_arc, static) = { .arc_name = "ip4-local", .node_name = "hicn-data-input-ip4", .runs_before = VNET_FEATURES ("ip4-local-end-of-arc"), -}; +}; \ No newline at end of file diff --git a/hicn-plugin/src/data_pcslookup_node.c b/hicn-plugin/src/data_pcslookup_node.c index 69278c306..95db66f54 100644 --- a/hicn-plugin/src/data_pcslookup_node.c +++ b/hicn-plugin/src/data_pcslookup_node.c @@ -63,17 +63,13 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, 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_PCSLOOKUP_NEXT_ERROR_DROP; u64 name_hash = 0; - hicn_name_t name; - hicn_header_t *hicn0 = NULL; u32 node_id0 = 0; index_t dpo_ctx_id0 = 0; - int ret0; u8 vft_id0 = 0; u8 is_cs0; u8 hash_entry_id = 0; @@ -104,13 +100,11 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, /* Incr packet counter */ stats.pkts_processed += 1; - ret0 = hicn_data_parse_pkt (b0, &name, &namelen, &hicn0, &isv6); - nameptr = (u8 *) (&name); + hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen); if (PREDICT_TRUE ( - ret0 == HICN_ERROR_NONE && hicn_hashtb_fullhash (nameptr, namelen, &name_hash) == - HICN_ERROR_NONE)) + HICN_ERROR_NONE)) { int res = hicn_hashtb_lookup_node ( rt->pitcs->pcs_table, nameptr, namelen, name_hash, @@ -154,7 +148,7 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, { hicn_data_pcslookup_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; + t->pkt_type = HICN_PACKET_TYPE_DATA; t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; t->next_index = next0; } @@ -216,4 +210,4 @@ VLIB_REGISTER_NODE(hicn_data_pcslookup_node) = * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */ + */ \ No newline at end of file diff --git a/hicn-plugin/src/faces/app/face_prod_node.c b/hicn-plugin/src/faces/app/face_prod_node.c index 5d2b54040..e3241e477 100644 --- a/hicn-plugin/src/faces/app/face_prod_node.c +++ b/hicn-plugin/src/faces/app/face_prod_node.c @@ -42,12 +42,12 @@ typedef struct { u32 next_index; u32 sw_if_index; + hicn_error_t error; } hicn_face_prod_input_trace_t; typedef enum { - HICN_FACE_PROD_NEXT_DATA_IP4, - HICN_FACE_PROD_NEXT_DATA_IP6, + HICN_FACE_PROD_NEXT_PCS, HICN_FACE_PROD_NEXT_ERROR_DROP, HICN_FACE_PROD_N_NEXT, } hicn_face_prod_next_t; @@ -65,11 +65,14 @@ format_face_prod_input_trace (u8 *s, va_list *args) s = format (s, "prod-face: sw_if_index %d next-index %d", t->sw_if_index, t->next_index); + + if (t->error != HICN_ERROR_NONE) + s = format (s, " error %s", get_error_string (t->error)); return s; } static_always_inline int -match_ip4_name (u32 *name, fib_prefix_t *prefix) +match_ip4_name (u32 *name, const fib_prefix_t *prefix) { u32 xor = 0; @@ -79,7 +82,7 @@ match_ip4_name (u32 *name, fib_prefix_t *prefix) } static_always_inline int -match_ip6_name (u8 *name, fib_prefix_t *prefix) +match_ip6_name (u8 *name, const fib_prefix_t *prefix) { union { @@ -96,24 +99,42 @@ match_ip6_name (u8 *name, fib_prefix_t *prefix) } static_always_inline u32 -hicn_face_prod_next_from_data_hdr (vlib_node_runtime_t *node, vlib_buffer_t *b, - fib_prefix_t *prefix) +hicn_face_prod_next_from_data_hdr (vlib_buffer_t *b) { - u8 *ptr = vlib_buffer_get_current (b); - u8 v = *ptr & 0xf0; + u8 is_v6; int match_res = 1; + int ret = 0; + hicn_name_t *name; + hicn_face_prod_state_t *prod_face = NULL; + + // 1 - ensure the packet is hicn and its format is correct + ret = hicn_data_parse_pkt (b); + if (PREDICT_FALSE (ret)) + { + return HICN_FACE_PROD_NEXT_ERROR_DROP; + } - if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr))) + // 2 - make sure the packet refers to a valid producer app state and + // retrieve app state information + prod_face = &face_state_vec[vnet_buffer (b)->sw_if_index[VLIB_RX]]; + vnet_buffer (b)->ip.adj_index[VLIB_RX] = prod_face->adj_index; + + // 3 - make sure the address in the packet belongs to the producer prefix + // of this face + const fib_prefix_t *prefix = &prod_face->prefix; + is_v6 = hicn_buffer_is_v6 (b); + name = &hicn_get_buffer (b)->name; + if (PREDICT_TRUE (!is_v6 && ip46_address_is_ip4 (&prefix->fp_addr))) { - match_res = match_ip4_name ((u32 *) &(ptr[12]), prefix); + match_res = match_ip4_name (&name->prefix.ip4.as_u32, prefix); } - else if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr))) + else if (PREDICT_TRUE (is_v6 && !ip46_address_is_ip4 (&prefix->fp_addr))) { - match_res = match_ip6_name (&(ptr[8]), prefix); + match_res = match_ip6_name (name->prefix.ip6.as_u8, prefix); } - return match_res ? HICN_FACE_PROD_NEXT_DATA_IP4 + (v == 0x60) : - HICN_FACE_PROD_NEXT_ERROR_DROP; + // 4 - if match found, forward data to next hicn node + return match_res ? HICN_FACE_PROD_NEXT_PCS : HICN_FACE_PROD_NEXT_ERROR_DROP; } static_always_inline void @@ -137,6 +158,7 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, u32 n_left_from, *from, *to_next; hicn_face_prod_next_t next_index; vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + u32 thread_index = vm->thread_index; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -152,22 +174,28 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b0, *b1, *b2, *b3; hicn_buffer_t *hicnb0, *hicnb1, *hicnb2, *hicnb3; u32 bi0, bi1, bi2, bi3; - hicn_face_prod_state_t *prod_face0 = NULL; - hicn_face_prod_state_t *prod_face1 = NULL; - hicn_face_prod_state_t *prod_face2 = NULL; - hicn_face_prod_state_t *prod_face3 = NULL; u32 next0, next1, next2, next3; + // Prefetch next iteration { vlib_buffer_t *b4, *b5, *b6, *b7; b4 = vlib_get_buffer (vm, from[4]); b5 = vlib_get_buffer (vm, from[5]); b6 = vlib_get_buffer (vm, from[6]); b7 = vlib_get_buffer (vm, from[7]); - CLIB_PREFETCH (b4, CLIB_CACHE_LINE_BYTES, STORE); - CLIB_PREFETCH (b5, CLIB_CACHE_LINE_BYTES, STORE); - CLIB_PREFETCH (b6, CLIB_CACHE_LINE_BYTES, STORE); - CLIB_PREFETCH (b7, CLIB_CACHE_LINE_BYTES, STORE); + CLIB_PREFETCH (b4, 2 * CLIB_CACHE_LINE_BYTES, WRITE); + CLIB_PREFETCH (b5, 2 * CLIB_CACHE_LINE_BYTES, WRITE); + CLIB_PREFETCH (b6, 2 * CLIB_CACHE_LINE_BYTES, WRITE); + CLIB_PREFETCH (b7, 2 * CLIB_CACHE_LINE_BYTES, WRITE); + + CLIB_PREFETCH (vlib_buffer_get_current (b4), + 2 * CLIB_CACHE_LINE_BYTES, WRITE); + CLIB_PREFETCH (vlib_buffer_get_current (b5), + 2 * CLIB_CACHE_LINE_BYTES, WRITE); + CLIB_PREFETCH (vlib_buffer_get_current (b6), + 2 * CLIB_CACHE_LINE_BYTES, WRITE); + CLIB_PREFETCH (vlib_buffer_get_current (b7), + 2 * CLIB_CACHE_LINE_BYTES, WRITE); } bi0 = from[0]; @@ -200,31 +228,39 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, hicnb2->flags = HICN_FACE_FLAGS_DEFAULT; hicnb3->flags = HICN_FACE_FLAGS_DEFAULT; - prod_face0 = &face_state_vec[vnet_buffer (b0)->sw_if_index[VLIB_RX]]; - prod_face1 = &face_state_vec[vnet_buffer (b1)->sw_if_index[VLIB_RX]]; - prod_face2 = &face_state_vec[vnet_buffer (b2)->sw_if_index[VLIB_RX]]; - prod_face3 = &face_state_vec[vnet_buffer (b3)->sw_if_index[VLIB_RX]]; - - vnet_buffer (b0)->ip.adj_index[VLIB_RX] = - face_state_vec[vnet_buffer (b0)->sw_if_index[VLIB_RX]].adj_index; - vnet_buffer (b1)->ip.adj_index[VLIB_RX] = - face_state_vec[vnet_buffer (b1)->sw_if_index[VLIB_RX]].adj_index; - vnet_buffer (b2)->ip.adj_index[VLIB_RX] = - face_state_vec[vnet_buffer (b2)->sw_if_index[VLIB_RX]].adj_index; - vnet_buffer (b3)->ip.adj_index[VLIB_RX] = - face_state_vec[vnet_buffer (b3)->sw_if_index[VLIB_RX]].adj_index; - - next0 = - hicn_face_prod_next_from_data_hdr (node, b0, &prod_face0->prefix); - next1 = - hicn_face_prod_next_from_data_hdr (node, b1, &prod_face1->prefix); - next2 = - hicn_face_prod_next_from_data_hdr (node, b2, &prod_face2->prefix); - next3 = - hicn_face_prod_next_from_data_hdr (node, b3, &prod_face3->prefix); + // parse packets and get next node + next0 = hicn_face_prod_next_from_data_hdr (b0); + next1 = hicn_face_prod_next_from_data_hdr (b1); + next2 = hicn_face_prod_next_from_data_hdr (b2); + next3 = hicn_face_prod_next_from_data_hdr (b3); stats.pkts_data_count += 4; - /* trace */ + // counters + vlib_increment_combined_counter ( + &counters[hicnb0->face_id * HICN_N_COUNTER], thread_index, + HICN_FACE_COUNTERS_DATA_RX, 1, + vlib_buffer_length_in_chain (vm, b0)); + stats.pkts_data_count += 1; + + vlib_increment_combined_counter ( + &counters[hicnb1->face_id * HICN_N_COUNTER], thread_index, + HICN_FACE_COUNTERS_DATA_RX, 1, + vlib_buffer_length_in_chain (vm, b0)); + stats.pkts_data_count += 1; + + vlib_increment_combined_counter ( + &counters[hicnb2->face_id * HICN_N_COUNTER], thread_index, + HICN_FACE_COUNTERS_DATA_RX, 1, + vlib_buffer_length_in_chain (vm, b0)); + stats.pkts_data_count += 1; + + vlib_increment_combined_counter ( + &counters[hicnb3->face_id * HICN_N_COUNTER], thread_index, + HICN_FACE_COUNTERS_DATA_RX, 1, + vlib_buffer_length_in_chain (vm, b0)); + stats.pkts_data_count += 1; + + // trace hicn_face_prod_trace_buffer ( vm, node, vnet_buffer (b0)->sw_if_index[VLIB_RX], b0, next0); hicn_face_prod_trace_buffer ( @@ -234,7 +270,7 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, hicn_face_prod_trace_buffer ( vm, node, vnet_buffer (b3)->sw_if_index[VLIB_RX], b3, next3); - /* enqueue */ + // enqueue vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next, n_left_to_next, bi0, bi1, bi2, bi3, next0, next1, next2, next3); @@ -246,8 +282,7 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, { vlib_buffer_t *b0; hicn_buffer_t *hicnb0; - u32 bi0, swif; - hicn_face_prod_state_t *prod_face = NULL; + u32 bi0; u32 next0; if (n_left_from > 1) @@ -267,15 +302,17 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, b0 = vlib_get_buffer (vm, bi0); hicnb0 = hicn_get_buffer (b0); hicnb0->flags = HICN_FACE_FLAGS_DEFAULT; - swif = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - prod_face = &face_state_vec[swif]; - next0 = - hicn_face_prod_next_from_data_hdr (node, b0, &prod_face->prefix); - vnet_buffer (b0)->ip.adj_index[VLIB_RX] = - face_state_vec[swif].adj_index; + next0 = hicn_face_prod_next_from_data_hdr (b0); stats.pkts_data_count++; + // counters + vlib_increment_combined_counter ( + &counters[hicnb0->face_id * HICN_N_COUNTER], thread_index, + HICN_FACE_COUNTERS_DATA_RX, 1, + vlib_buffer_length_in_chain (vm, b0)); + stats.pkts_data_count += 1; + /* trace */ hicn_face_prod_trace_buffer ( vm, node, vnet_buffer (b0)->sw_if_index[VLIB_RX], b0, next0); @@ -310,8 +347,7 @@ VLIB_REGISTER_NODE(hicn_face_prod_input_node) = .n_next_nodes = HICN_FACE_PROD_N_NEXT, .next_nodes = { - [HICN_FACE_PROD_NEXT_DATA_IP4] = "hicn4-face-input", - [HICN_FACE_PROD_NEXT_DATA_IP6] = "hicn6-face-input", + [HICN_FACE_PROD_NEXT_PCS] = "hicn-data-pcslookup", [HICN_FACE_PROD_NEXT_ERROR_DROP] = "error-drop", }, }; @@ -320,4 +356,4 @@ VLIB_REGISTER_NODE(hicn_face_prod_input_node) = * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */ + */ \ No newline at end of file diff --git a/hicn-plugin/src/faces/face.c b/hicn-plugin/src/faces/face.c index 854fd81d3..4ee1c283f 100644 --- a/hicn-plugin/src/faces/face.c +++ b/hicn-plugin/src/faces/face.c @@ -62,16 +62,12 @@ mhash_t hicn_face_hashtb; const static char *const hicn_face6_nodes[] = { "hicn6-face-output", // this is the name you give your node in // VLIB_REGISTER_NODE - "hicn6-iface-output", // this is the name you give your node in - // VLIB_REGISTER_NODE NULL, }; const static char *const hicn_face4_nodes[] = { "hicn4-face-output", // this is the name you give your node in // VLIB_REGISTER_NODE - "hicn4-iface-output", // this is the name you give your node in - // VLIB_REGISTER_NODE NULL, }; @@ -304,7 +300,7 @@ hicn_iface_to_face (hicn_face_t *face, const dpo_id_t *dpo) */ int hicn_face_add (const dpo_id_t *dpo_nh, ip46_address_t *nat_address, int sw_if, - hicn_face_id_t *pfaceid, u8 is_app_prod) + hicn_face_id_t *pfaceid) { hicn_face_flags_t flags = (hicn_face_flags_t) 0; diff --git a/hicn-plugin/src/faces/face.h b/hicn-plugin/src/faces/face.h index 39505c942..e4b759bec 100644 --- a/hicn-plugin/src/faces/face.h +++ b/hicn-plugin/src/faces/face.h @@ -27,6 +27,8 @@ #include +#include "face_flags.h" +#include "../hicn_buffer_flags.h" #include "../udp_tunnels/udp_tunnel.h" #include "../hicn_logging.h" @@ -117,40 +119,8 @@ typedef struct __attribute__ ((packed)) hicn_face_s /* Pool of faces */ extern hicn_face_t *hicn_dpoi_face_pool; -/* Flags */ -/* A face is complete and it stores all the information. A iface lacks of the - adj index, therefore sending a packet through a iface require a lookup in - the FIB. */ -#define HICN_FACE_FLAGS_DEFAULT 0x00 -#define HICN_FACE_FLAGS_FACE 0x01 -#define HICN_FACE_FLAGS_IFACE 0x02 -#define HICN_FACE_FLAGS_APPFACE_PROD \ - 0x04 /* Currently only IP face can be appface */ -#define HICN_FACE_FLAGS_APPFACE_CONS \ - 0x08 /* Currently only IP face can be appface */ -#define HICN_FACE_FLAGS_DELETED 0x10 -#define HICN_FACE_FLAGS_UDP 0x20 - #define HICN_FACE_NULL (hicn_face_id_t) ~0 -#define HICN_FACE_FLAGS_APPFACE_PROD_BIT 2 -#define HICN_FACE_FLAGS_APPFACE_CONS_BIT 3 - -#define HICN_BUFFER_FLAGS_DEFAULT 0x00 -#define HICN_BUFFER_FLAGS_NEW_FACE 0x02 -#define HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL 0x04 -#define HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL 0x08 - -STATIC_ASSERT ((1 << HICN_FACE_FLAGS_APPFACE_PROD_BIT) == - HICN_FACE_FLAGS_APPFACE_PROD, - "HICN_FACE_FLAGS_APPFACE_PROD_BIT and " - "HICN_FACE_FLAGS_APPFACE_PROD must correspond"); - -STATIC_ASSERT ((1 << HICN_FACE_FLAGS_APPFACE_CONS_BIT) == - HICN_FACE_FLAGS_APPFACE_CONS, - "HICN_FACE_FLAGS_APPFACE_CONS_BIT and " - "HICN_FACE_FLAGS_APPFACE_CONS must correspond"); - /** * @brief Definition of the virtual functin table for an hICN FACE DPO. */ @@ -484,7 +454,7 @@ hicn_face_get_with_dpo (const ip46_address_t *addr, u32 sw_if, * reachable ip address, otherwise HICN_ERROR_NONE */ int hicn_face_add (const dpo_id_t *dpo_nh, ip46_address_t *nat_address, - int sw_if, hicn_face_id_t *pfaceid, u8 is_app_prod); + int sw_if, hicn_face_id_t *pfaceid); /** * @brief Create a new incomplete face ip. (Meant to be used by the data plane) @@ -497,7 +467,7 @@ int hicn_face_add (const dpo_id_t *dpo_nh, ip46_address_t *nat_address, * reachable ip address, otherwise HICN_ERROR_NONE */ always_inline void -hicn_iface_add (ip46_address_t *nat_address, int sw_if, +hicn_iface_add (const ip46_address_t *nat_address, int sw_if, hicn_face_id_t *pfaceid, u32 adj_index, u8 flags) { hicn_face_t *face; @@ -615,7 +585,6 @@ hicn_face_ip4_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags, *hicnb_flags |= HICN_BUFFER_FLAGS_NEW_FACE; *index = idx; - return ret; } else { @@ -623,15 +592,10 @@ hicn_face_ip4_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags, hicn_face_id_t face_id = hicn_dpoi_get_index (face); hicn_face_unlock_with_id (face_id); ret = HICN_ERROR_FACE_ALREADY_CREATED; + *index = hicn_dpoi_get_index (face); + *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; } - /* Code replicated on purpose */ - *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; - *hicnb_flags |= (face->flags & HICN_FACE_FLAGS_APPFACE_PROD) >> - HICN_FACE_FLAGS_APPFACE_PROD_BIT; - - *index = hicn_dpoi_get_index (face); - return ret; } @@ -676,7 +640,7 @@ hicn_face_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags, /*All (complete) faces are indexed by remote addess as well */ /* if the face exists, it adds a lock */ - hicn_face_t *face = hicn_face_get ((ip46_address_t *) nat_addr, sw_if, + hicn_face_t *face = hicn_face_get ((const ip46_address_t *) nat_addr, sw_if, &hicn_face_hashtb, adj_index); if (face == NULL) @@ -684,8 +648,8 @@ hicn_face_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags, hicn_face_id_t idx; u8 face_flags = 0; - hicn_iface_add ((ip46_address_t *) nat_addr, sw_if, &idx, adj_index, - face_flags); + hicn_iface_add ((const ip46_address_t *) nat_addr, sw_if, &idx, + adj_index, face_flags); face = hicn_dpoi_get_from_idx (idx); @@ -712,12 +676,8 @@ hicn_face_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags, adj_nbr_walk (face->sw_if, FIB_PROTOCOL_IP6, hicn6_iface_adj_walk_cb, face); - *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; - *hicnb_flags |= HICN_BUFFER_FLAGS_NEW_FACE; - + *hicnb_flags = HICN_BUFFER_FLAGS_NEW_FACE; *index = idx; - - return ret; } else { @@ -725,15 +685,10 @@ hicn_face_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags, hicn_face_id_t face_id = hicn_dpoi_get_index (face); hicn_face_unlock_with_id (face_id); ret = HICN_ERROR_FACE_ALREADY_CREATED; + *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; + *index = hicn_dpoi_get_index (face); } - /* Code replicated on purpose */ - *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; - *hicnb_flags |= (face->flags & HICN_FACE_FLAGS_APPFACE_PROD) >> - HICN_FACE_FLAGS_APPFACE_PROD_BIT; - - *index = hicn_dpoi_get_index (face); - return ret; } diff --git a/hicn-plugin/src/faces/face_flags.h b/hicn-plugin/src/faces/face_flags.h new file mode 100644 index 000000000..61dee5465 --- /dev/null +++ b/hicn-plugin/src/faces/face_flags.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 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: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HICN_FACE_FLAGS_H__ +#define __HICN_FACE_FLAGS_H__ + +/* Flags */ +/* A face is complete and it stores all the information. A iface lacks of the + adj index, therefore sending a packet through a iface require a lookup in + the FIB. */ +#define foreach_face_flag \ + _ (0, FACE, "face") \ + _ (1, IFACE, "iface") \ + _ (2, APPFACE_PROD, "face is consumer face") \ + _ (3, APPFACE_CONS, "face is consumer face") \ + _ (4, DELETED, "face is deleted") \ + _ (5, UDP, "face is udp") + +enum +{ + HICN_FACE_FLAGS_DEFAULT = 0, +#define _(a, b, c) HICN_FACE_FLAGS_##b = (1 << a), + foreach_face_flag +#undef _ +}; + +#endif /* __HICN_FACE_FLAGS_H__ */ \ No newline at end of file diff --git a/hicn-plugin/src/faces/face_node.c b/hicn-plugin/src/faces/face_node.c index dc9bfffd0..6dedbe1c4 100644 --- a/hicn-plugin/src/faces/face_node.c +++ b/hicn-plugin/src/faces/face_node.c @@ -56,6 +56,7 @@ typedef struct u32 next_index; u32 sw_if_index; u8 pkt_type; + hicn_error_t error; u8 packet_data[60]; } hicn4_face_input_trace_t; @@ -73,6 +74,7 @@ typedef struct u32 next_index; u32 sw_if_index; u8 pkt_type; + hicn_error_t error; u8 packet_data[60]; } hicn6_face_input_trace_t; @@ -86,8 +88,9 @@ typedef enum #define NEXT_MAPME_IP4 HICN4_FACE_INPUT_NEXT_MAPME #define NEXT_MAPME_IP6 HICN6_FACE_INPUT_NEXT_MAPME -#define NEXT_DATA_IP4 HICN4_FACE_INPUT_NEXT_DATA -#define NEXT_DATA_IP6 HICN6_FACE_INPUT_NEXT_DATA + +#define NEXT_DATA_IP4 HICN4_FACE_INPUT_NEXT_DATA +#define NEXT_DATA_IP6 HICN6_FACE_INPUT_NEXT_DATA #define NEXT_ERROR_DROP_IP4 HICN4_FACE_INPUT_NEXT_ERROR_DROP #define NEXT_ERROR_DROP_IP6 HICN6_FACE_INPUT_NEXT_ERROR_DROP @@ -110,10 +113,11 @@ typedef enum vlib_buffer_t *b0; \ u32 bi0, sw_if0; \ u32 next0 = NEXT_ERROR_DROP_IP##ipv; \ + u8 is_icmp0; \ IP_HEADER_##ipv *ip_hdr = NULL; \ hicn_buffer_t *hicnb0; \ int from_tunnel0; \ - int ret0; \ + int ret0 = HICN_ERROR_NONE; \ /* Prefetch for next iteration. */ \ if (n_left_from > 1) \ { \ @@ -134,23 +138,35 @@ typedef enum hicnb0 = hicn_get_buffer (b0); \ ip_hdr = (IP_HEADER_##ipv *) vlib_buffer_get_current (b0); \ \ - u8 is_icmp = ip_hdr->protocol == IPPROTO_ICMPV##ipv; \ - \ - from_tunnel0 = \ - (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \ - hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \ - sw_if0 = (from_tunnel0) * ~0 + \ - (1 - from_tunnel0) * vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ - \ - ret0 = hicn_face_ip##ipv##_add_and_lock ( \ - &hicnb0->face_id, &hicnb0->flags, &ip_hdr->dst_address, sw_if0, \ - vnet_buffer (b0)->ip.adj_index[VLIB_RX], \ - /* Should not be used */ ~0); \ - /* Make sure the face is not created here */ \ - ASSERT (ret0 == HICN_ERROR_FACE_ALREADY_CREATED); \ + /* Parse packet and cache useful info in opaque2 */ \ + ret0 = hicn_data_parse_pkt (b0); \ + is_icmp0 = ret0 == HICN_ERROR_PARSER_MAPME_PACKET; \ + ret0 = (ret0 == HICN_ERROR_NONE) || \ + (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \ \ - next0 = \ - is_icmp * NEXT_MAPME_IP##ipv + (1 - is_icmp) * NEXT_DATA_IP##ipv; \ + /* If parsing is ok, send packet to next node */ \ + if (PREDICT_FALSE (!ret0)) \ + { \ + next0 = HICN##ipv##_FACE_INPUT_NEXT_ERROR_DROP; \ + } \ + else \ + { \ + next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \ + (1 - is_icmp0) * NEXT_DATA_IP##ipv; \ + from_tunnel0 = \ + (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \ + hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \ + sw_if0 = \ + (from_tunnel0) * ~0 + \ + (1 - from_tunnel0) * vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ + \ + ret0 = hicn_face_ip##ipv##_add_and_lock ( \ + &hicnb0->face_id, &hicnb0->flags, &ip_hdr->dst_address, sw_if0, \ + vnet_buffer (b0)->ip.adj_index[VLIB_RX], \ + /* Should not be used */ ~0); \ + /* Make sure the face is not created here */ \ + ASSERT (ret0 == HICN_ERROR_FACE_ALREADY_CREATED); \ + } \ \ vlib_increment_combined_counter ( \ &counters[hicnb0->face_id * HICN_N_COUNTER], thread_index, \ @@ -162,8 +178,9 @@ typedef enum { \ TRACE_INPUT_PKT_IP##ipv *t = \ vlib_add_trace (vm, node, b0, sizeof (*t)); \ - t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->pkt_type = HICN_PACKET_TYPE_INTEREST; \ t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ + t->error = ret0; \ t->next_index = next0; \ clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \ sizeof (t->packet_data)); \ @@ -182,6 +199,7 @@ typedef enum u32 bi0, bi1, sw_if0, sw_if1; \ u32 next0 = NEXT_ERROR_DROP_IP##ipv; \ u32 next1 = NEXT_ERROR_DROP_IP##ipv; \ + u8 is_icmp0, is_icmp1; \ IP_HEADER_##ipv *ip_hdr0 = NULL; \ IP_HEADER_##ipv *ip_hdr1 = NULL; \ hicn_buffer_t *hicnb0; \ @@ -215,40 +233,95 @@ typedef enum ip_hdr0 = (IP_HEADER_##ipv *) vlib_buffer_get_current (b0); \ ip_hdr1 = (IP_HEADER_##ipv *) vlib_buffer_get_current (b1); \ \ - u8 is_icmp0 = ip_hdr0->protocol == IPPROTO_ICMPV##ipv; \ - u8 is_icmp1 = ip_hdr1->protocol == IPPROTO_ICMPV##ipv; \ - \ - from_tunnel0 = \ - (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \ - hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \ - sw_if0 = (from_tunnel0) * ~0 + \ - (1 - from_tunnel0) * vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ - \ - ret0 = hicn_face_ip##ipv##_add_and_lock ( \ - &hicnb0->face_id, &hicnb0->flags, &ip_hdr0->dst_address, sw_if0, \ - vnet_buffer (b0)->ip.adj_index[VLIB_RX], \ - /* Should not be used */ ~0); \ - /* Make sure the face is not created here */ \ - ASSERT (ret0 == HICN_ERROR_FACE_ALREADY_CREATED); \ - \ - from_tunnel1 = \ - (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \ - hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \ - sw_if1 = (from_tunnel1) * ~0 + \ - (1 - from_tunnel1) * vnet_buffer (b1)->sw_if_index[VLIB_RX]; \ - \ - ret1 = hicn_face_ip##ipv##_add_and_lock ( \ - &hicnb1->face_id, &hicnb1->flags, &ip_hdr1->dst_address, sw_if1, \ - vnet_buffer (b1)->ip.adj_index[VLIB_RX], \ - /* Should not be used */ ~0); \ - /* Make sure the face is not created here */ \ - ASSERT (ret1 == HICN_ERROR_FACE_ALREADY_CREATED); \ - \ - next0 = \ - is_icmp0 * NEXT_MAPME_IP##ipv + (1 - is_icmp0) * NEXT_DATA_IP##ipv; \ - \ - next1 = \ - is_icmp1 * NEXT_MAPME_IP##ipv + (1 - is_icmp1) * NEXT_DATA_IP##ipv; \ + /* Parse packet and cache useful info in opaque2 */ \ + /* Parse packet and cache useful info in opaque2 */ \ + ret0 = hicn_data_parse_pkt (b0); \ + ret1 = hicn_data_parse_pkt (b1); \ + is_icmp0 = ret0 == HICN_ERROR_PARSER_MAPME_PACKET; \ + is_icmp1 = ret1 == HICN_ERROR_PARSER_MAPME_PACKET; \ + ret0 = (ret0 == HICN_ERROR_NONE) || \ + (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \ + ret1 = (ret1 == HICN_ERROR_NONE) || \ + (ret1 == HICN_ERROR_PARSER_MAPME_PACKET); \ + if (PREDICT_TRUE (ret0 && ret1)) \ + { \ + next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \ + (1 - is_icmp0) * NEXT_DATA_IP##ipv; \ + \ + next1 = is_icmp1 * NEXT_MAPME_IP##ipv + \ + (1 - is_icmp1) * NEXT_DATA_IP##ipv; \ + \ + from_tunnel0 = \ + (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \ + hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \ + sw_if0 = \ + (from_tunnel0) * ~0 + \ + (1 - from_tunnel0) * vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ + \ + ret0 = hicn_face_ip##ipv##_add_and_lock ( \ + &hicnb0->face_id, &hicnb0->flags, &ip_hdr0->dst_address, sw_if0, \ + vnet_buffer (b0)->ip.adj_index[VLIB_RX], \ + /* Should not be used */ ~0); \ + /* Make sure the face is not created here */ \ + ASSERT (ret0 == HICN_ERROR_FACE_ALREADY_CREATED); \ + \ + from_tunnel1 = \ + (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \ + hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \ + sw_if1 = \ + (from_tunnel1) * ~0 + \ + (1 - from_tunnel1) * vnet_buffer (b1)->sw_if_index[VLIB_RX]; \ + \ + ret1 = hicn_face_ip##ipv##_add_and_lock ( \ + &hicnb1->face_id, &hicnb1->flags, &ip_hdr1->dst_address, sw_if1, \ + vnet_buffer (b1)->ip.adj_index[VLIB_RX], \ + /* Should not be used */ ~0); \ + /* Make sure the face is not created here */ \ + ASSERT (ret1 == HICN_ERROR_FACE_ALREADY_CREATED); \ + } \ + else if (ret0 && !ret1) \ + { \ + next1 = HICN##ipv##_FACE_INPUT_NEXT_ERROR_DROP; \ + from_tunnel0 = \ + (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \ + hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \ + sw_if0 = \ + (from_tunnel0) * ~0 + \ + (1 - from_tunnel0) * vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ + \ + ret0 = hicn_face_ip##ipv##_add_and_lock ( \ + &hicnb0->face_id, &hicnb0->flags, &ip_hdr0->dst_address, sw_if0, \ + vnet_buffer (b0)->ip.adj_index[VLIB_RX], \ + /* Should not be used */ ~0); \ + /* Make sure the face is not created here */ \ + ASSERT (ret0 == HICN_ERROR_FACE_ALREADY_CREATED); \ + next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \ + (1 - is_icmp0) * NEXT_DATA_IP##ipv; \ + } \ + else if (!ret0 && ret1) \ + { \ + next0 = HICN##ipv##_FACE_INPUT_NEXT_ERROR_DROP; \ + from_tunnel1 = \ + (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \ + hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \ + sw_if1 = \ + (from_tunnel1) * ~0 + \ + (1 - from_tunnel1) * vnet_buffer (b1)->sw_if_index[VLIB_RX]; \ + \ + ret1 = hicn_face_ip##ipv##_add_and_lock ( \ + &hicnb1->face_id, &hicnb1->flags, &ip_hdr1->dst_address, sw_if1, \ + vnet_buffer (b1)->ip.adj_index[VLIB_RX], \ + /* Should not be used */ ~0); \ + /* Make sure the face is not created here */ \ + ASSERT (ret1 == HICN_ERROR_FACE_ALREADY_CREATED); \ + next1 = is_icmp1 * NEXT_MAPME_IP##ipv + \ + (1 - is_icmp1) * NEXT_DATA_IP##ipv; \ + } \ + else \ + { \ + next0 = HICN##ipv##_FACE_INPUT_NEXT_ERROR_DROP; \ + next1 = HICN##ipv##_FACE_INPUT_NEXT_ERROR_DROP; \ + } \ \ vlib_increment_combined_counter ( \ &counters[hicnb0->face_id * HICN_N_COUNTER], thread_index, \ @@ -265,8 +338,9 @@ typedef enum { \ TRACE_INPUT_PKT_IP##ipv *t = \ vlib_add_trace (vm, node, b0, sizeof (*t)); \ - t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->pkt_type = HICN_PACKET_TYPE_INTEREST; \ t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ + t->error = ret0; \ t->next_index = next0; \ clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \ sizeof (t->packet_data)); \ @@ -277,8 +351,9 @@ typedef enum { \ TRACE_INPUT_PKT_IP##ipv *t = \ vlib_add_trace (vm, node, b1, sizeof (*t)); \ - t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->pkt_type = HICN_PACKET_TYPE_INTEREST; \ t->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \ + t->error = ret1; \ t->next_index = next1; \ clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b1), \ sizeof (t->packet_data)); \ @@ -461,80 +536,6 @@ typedef enum HICN6_FACE_OUTPUT_N_NEXT, } hicn6_face_output_next_t; -/* static_always_inline void */ -/* hicn_reply_probe_v4 (vlib_buffer_t * b, hicn_face_t * face) */ -/* { */ -/* hicn_header_t *h0 = vlib_buffer_get_current (b); */ -/* hicn_face_ip_t * face_ip = (hicn_face_ip_t *)(&face->data); */ -/* h0->v4.ip.saddr = h0->v4.ip.daddr; */ -/* h0->v4.ip.daddr = face_ip->local_addr.ip4; */ -/* vnet_buffer (b)->sw_if_index[VLIB_RX] = face->shared.sw_if; */ - -/* u16 * dst_port_ptr = (u16 *)(((u8*)h0) + sizeof(ip4_header_t) + - * sizeof(u16)); */ -/* u16 dst_port = *dst_port_ptr; */ -/* u16 * src_port_ptr = (u16 *)(((u8*)h0) + sizeof(ip4_header_t)); */ - -/* *dst_port_ptr = *src_port_ptr; */ -/* *src_port_ptr = dst_port; */ - -/* hicn_type_t type = hicn_get_buffer (b)->type; */ -/* hicn_ops_vft[type.l1]->set_lifetime (type, &h0->protocol, 0); */ -/* } */ - -/* static_always_inline void */ -/* hicn_reply_probe_v6 (vlib_buffer_t * b, hicn_face_t * face) */ -/* { */ -/* hicn_header_t *h0 = vlib_buffer_get_current (b); */ -/* hicn_face_ip_t * face_ip = (hicn_face_ip_t *)(&face->data); */ -/* h0->v6.ip.saddr = h0->v6.ip.daddr; */ -/* h0->v6.ip.daddr = face_ip->local_addr.ip6; */ -/* vnet_buffer (b)->sw_if_index[VLIB_RX] = face->shared.sw_if; */ - -/* u16 * dst_port_ptr = (u16 *)(((u8*)h0) + sizeof(ip6_header_t) + - * sizeof(u16)); */ -/* u16 dst_port = *dst_port_ptr; */ -/* u16 * src_port_ptr = (u16 *)(((u8*)h0) + sizeof(ip6_header_t)); */ - -/* *dst_port_ptr = *src_port_ptr; */ -/* *src_port_ptr = dst_port; */ - -/* hicn_type_t type = hicn_get_buffer (b)->type; */ -/* hicn_ops_vft[type.l1]->set_lifetime (type, &h0->protocol, 0); */ - -/* } */ - -/* static_always_inline u32 */ -/* hicn_face_match_probe (vlib_buffer_t * b, hicn_face_t * face, u32 * next) */ -/* { */ - -/* u8 *ptr = vlib_buffer_get_current (b); */ -/* u8 v = *ptr & 0xf0; */ -/* u8 res = 0; */ - -/* if ( v == 0x40 ) */ -/* { */ -/* u16 * dst_port = (u16 *)(ptr + sizeof(ip4_header_t) + sizeof(u16)); */ -/* if (*dst_port == clib_net_to_host_u16(DEFAULT_PROBING_PORT)) */ -/* { */ -/* hicn_reply_probe_v6(b, face); */ -/* *next = HICN4_FACE_NEXT_ECHO_REPLY; */ -/* res = 1; */ -/* } */ -/* } */ -/* else if ( v == 0x60 ) */ -/* { */ -/* u16 * dst_port = (u16 *)(ptr + sizeof(ip6_header_t) + sizeof(u16)); */ -/* if (*dst_port == clib_net_to_host_u16(DEFAULT_PROBING_PORT)) */ -/* { */ -/* hicn_reply_probe_v6(b, face); */ -/* *next = HICN6_FACE_NEXT_ECHO_REPLY; */ -/* res = 1; */ -/* } */ -/* } */ -/* return res; */ -/* } */ - static inline void hicn_face_rewrite_interest (vlib_main_t *vm, vlib_buffer_t *b0, hicn_face_t *face, u32 *next) @@ -546,6 +547,9 @@ hicn_face_rewrite_interest (vlib_main_t *vm, vlib_buffer_t *b0, hicn_header_t *hicn = vlib_buffer_get_current (b0); + u8 is_v4 = ip46_address_is_ip4 (&face->nat_addr) && + !ip6_address_is_loopback (&face->nat_addr.ip6); + // hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data; ip46_address_t temp_addr; @@ -553,11 +557,8 @@ hicn_face_rewrite_interest (vlib_main_t *vm, vlib_buffer_t *b0, hicn_type_t type = hicn_get_buffer (b0)->type; int ret = hicn_ops_vft[type.l1]->rewrite_interest ( type, &hicn->protocol, &face->nat_addr, &temp_addr); - if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED) { - u8 is_v4 = ip46_address_is_ip4 (&face->nat_addr) && - !ip6_address_is_loopback (&face->nat_addr.ip6); ensure_offload_flags (b0, is_v4); } @@ -645,7 +646,7 @@ typedef struct { \ TRACE_OUTPUT_PKT_IP##ipv *t = \ vlib_add_trace (vm, node, b0, sizeof (*t)); \ - t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->pkt_type = HICN_PACKET_TYPE_INTEREST; \ t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ t->next_index = next0; \ clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \ @@ -724,7 +725,7 @@ typedef struct { \ TRACE_OUTPUT_PKT_IP##ipv *t = \ vlib_add_trace (vm, node, b0, sizeof (*t)); \ - t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->pkt_type = HICN_PACKET_TYPE_INTEREST; \ t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ t->next_index = next0; \ clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \ @@ -736,7 +737,7 @@ typedef struct { \ TRACE_OUTPUT_PKT_IP##ipv *t = \ vlib_add_trace (vm, node, b1, sizeof (*t)); \ - t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->pkt_type = HICN_PACKET_TYPE_INTEREST; \ t->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \ t->next_index = next1; \ clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b1), \ @@ -812,12 +813,7 @@ VLIB_REGISTER_NODE (hicn4_face_output_node) = { .type = VLIB_NODE_TYPE_INTERNAL, .n_errors = ARRAY_LEN (hicn4_face_output_error_strings), .error_strings = hicn4_face_output_error_strings, - .n_next_nodes = HICN4_FACE_OUTPUT_N_NEXT, - /* Reusing the list of nodes from lookup to be compatible with arp */ - .next_nodes = { [HICN4_FACE_OUTPUT_NEXT_ERROR_DROP] = "error-drop", - [HICN4_FACE_OUTPUT_NEXT_ECHO_REPLY] = "hicn4-face-input", - [HICN4_FACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap", - [HICN4_FACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" } + .sibling_of = "ip4-lookup", }; static uword @@ -882,13 +878,7 @@ VLIB_REGISTER_NODE (hicn6_face_output_node) = { .type = VLIB_NODE_TYPE_INTERNAL, .n_errors = ARRAY_LEN (hicn6_face_output_error_strings), .error_strings = hicn6_face_output_error_strings, - .n_next_nodes = HICN6_FACE_OUTPUT_N_NEXT, - /* Reusing the list of nodes from lookup to be compatible with neighbour - discovery */ - .next_nodes = { [HICN6_FACE_OUTPUT_NEXT_ERROR_DROP] = "error-drop", - [HICN6_FACE_OUTPUT_NEXT_ECHO_REPLY] = "hicn6-face-input", - [HICN6_FACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap", - [HICN6_FACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" } + .sibling_of = "ip6-lookup", }; /* @@ -897,4 +887,4 @@ VLIB_REGISTER_NODE (hicn6_face_output_node) = { * Local Variables: * eval: (c-set-style "gnu") * End: - */ + */ \ No newline at end of file diff --git a/hicn-plugin/src/faces/iface_node.c b/hicn-plugin/src/faces/iface_node.c index 84205af9b..3b6634d77 100644 --- a/hicn-plugin/src/faces/iface_node.c +++ b/hicn-plugin/src/faces/iface_node.c @@ -52,6 +52,7 @@ typedef struct u32 next_index; u32 sw_if_index; u8 pkt_type; + hicn_error_t error; u8 packet_data[60]; } hicn4_iface_input_trace_t; @@ -69,6 +70,7 @@ typedef struct u32 next_index; u32 sw_if_index; u8 pkt_type; + hicn_error_t error; u8 packet_data[60]; } hicn6_iface_input_trace_t; @@ -86,33 +88,9 @@ typedef enum #define NEXT_INTEREST_IP4 HICN4_IFACE_INPUT_NEXT_INTEREST #define NEXT_INTEREST_IP6 HICN6_IFACE_INPUT_NEXT_INTEREST -#define ADDRESS_IP4 \ - ip_interface_address_t *ia = 0; \ - ip4_address_t *local_address = \ - ip4_interface_first_address (&ip4_main, swif, &ia) -#define ADDRESS_IP6 \ - ip6_address_t *local_address = ip6_interface_first_address (&ip6_main, swif) - -#define ADDRESSX2_IP4 \ - ip_interface_address_t *ia0, *ia1; \ - ia0 = ia1 = 0; \ - ip4_address_t *local_address0 = \ - ip4_interface_first_address (&ip4_main, swif0, &ia0); \ - ip4_address_t *local_address1 = \ - ip4_interface_first_address (&ip4_main, swif1, &ia1); - -#define ADDRESSX2_IP6 \ - ip6_address_t *local_address0 = \ - ip6_interface_first_address (&ip6_main, swif0); \ - ip6_address_t *local_address1 = \ - ip6_interface_first_address (&ip6_main, swif1); - #define DPO_ADD_LOCK_FACE_IP4 hicn_face_ip4_add_and_lock #define DPO_ADD_LOCK_FACE_IP6 hicn_face_ip6_add_and_lock -//#define VLIB_EDGE_IP4 data_fwd_iface_ip4_vlib_edge -//#define VLIB_EDGE_IP6 data_fwd_iface_ip6_vlib_edge - #define IP_HEADER_4 ip4_header_t #define IP_HEADER_6 ip6_header_t @@ -148,6 +126,7 @@ typedef enum HICN4_IFACE_OUTPUT_NEXT_LOOKUP, HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP, HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP, + HICN4_IFACE_OUTPUT_NEXT_PG, HICN4_IFACE_OUTPUT_N_NEXT, } hicn4_iface_output_next_t; @@ -166,6 +145,7 @@ typedef enum HICN6_IFACE_OUTPUT_NEXT_LOOKUP, HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP, HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP, + HICN6_IFACE_OUTPUT_NEXT_PG, HICN6_IFACE_OUTPUT_N_NEXT, } hicn6_iface_output_next_t; @@ -178,6 +158,9 @@ typedef enum #define NEXT_UDP_ENCAP_IP4 HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP #define NEXT_UDP_ENCAP_IP6 HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP +#define NEXT_PG4 HICN4_IFACE_OUTPUT_NEXT_PG +#define NEXT_PG6 HICN6_IFACE_OUTPUT_NEXT_PG + #define HICN_REWRITE_DATA_IP4 hicn_rewrite_iface_data4 #define HICN_REWRITE_DATA_IP6 hicn_rewrite_iface_data6 @@ -190,9 +173,11 @@ typedef enum do \ { \ vlib_buffer_t *b0; \ - u32 bi0, next0, next_iface0, sw_if0; \ + u32 bi0, next0, next_iface0, sw_if0 = ~0; \ IP_HEADER_##ipv *ip_hdr = NULL; \ hicn_buffer_t *hicnb0; \ + int ret0 = HICN_ERROR_NONE; \ + u8 is_icmp0; \ /* Prefetch for next iteration. */ \ if (n_left_from > 1) \ { \ @@ -213,41 +198,55 @@ typedef enum hicnb0 = hicn_get_buffer (b0); \ ip_hdr = (IP_HEADER_##ipv *) vlib_buffer_get_current (b0); \ \ - stats.pkts_interest_count += 1; \ - \ - u8 is_icmp = ip_hdr->protocol == IPPROTO_ICMPV##ipv; \ - \ - next0 = \ - is_icmp * NEXT_MAPME_IP##ipv + (1 - is_icmp) * NEXT_INTEREST_IP##ipv; \ - \ - next_iface0 = NEXT_DATA_LOOKUP_IP##ipv; \ - sw_if0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ - \ - if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \ - vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \ + /* Parse packet and cache useful info in opaque2 */ \ + ret0 = hicn_interest_parse_pkt (b0); \ + is_icmp0 = (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \ + ret0 = (ret0 == HICN_ERROR_NONE) || \ + (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \ + if (PREDICT_FALSE (!ret0)) \ { \ - next_iface0 = NEXT_UDP_ENCAP_IP4; \ - sw_if0 = ~0; \ + next0 = HICN##ipv##_IFACE_INPUT_NEXT_ERROR_DROP; \ } \ - else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \ - vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \ + else \ { \ - next_iface0 = NEXT_UDP_ENCAP_IP6; \ - sw_if0 = ~0; \ + next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \ + (1 - is_icmp0) * NEXT_INTEREST_IP##ipv; \ + \ + next_iface0 = NEXT_DATA_LOOKUP_IP##ipv; \ + sw_if0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ + \ + if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \ + vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \ + { \ + next_iface0 = NEXT_UDP_ENCAP_IP4; \ + sw_if0 = ~0; \ + } \ + else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \ + vnet_buffer (b0)->ip.adj_index[VLIB_RX] != \ + ADJ_INDEX_INVALID) \ + { \ + next_iface0 = NEXT_UDP_ENCAP_IP6; \ + sw_if0 = ~0; \ + } \ + else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_PG) \ + { \ + next_iface0 = NEXT_PG##ipv; \ + } \ + \ + DPO_ADD_LOCK_FACE_IP##ipv ( \ + &(hicnb0->face_id), &hicnb0->flags, &(ip_hdr->src_address), \ + sw_if0, vnet_buffer (b0)->ip.adj_index[VLIB_RX], next_iface0); \ } \ \ - DPO_ADD_LOCK_FACE_IP##ipv ( \ - &(hicnb0->face_id), &hicnb0->flags, &(ip_hdr->src_address), sw_if0, \ - vnet_buffer (b0)->ip.adj_index[VLIB_RX], next_iface0); \ - \ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ (b0->flags & VLIB_BUFFER_IS_TRACED))) \ { \ TRACE_INPUT_PKT_IP##ipv *t = \ vlib_add_trace (vm, node, b0, sizeof (*t)); \ - t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->pkt_type = HICN_PACKET_TYPE_INTEREST; \ t->sw_if_index = sw_if0; \ t->next_index = next0; \ + t->error = ret0; \ clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \ sizeof (t->packet_data)); \ } \ @@ -267,9 +266,12 @@ typedef enum do \ { \ vlib_buffer_t *b0, *b1; \ - u32 bi0, bi1, next0, next1, next_iface0, next_iface1, sw_if0, sw_if1; \ + u32 bi0, bi1, next0, next1; \ + u32 next_iface0, next_iface1, sw_if0 = ~0, sw_if1 = ~0; \ + u8 is_icmp0, is_icmp1; \ IP_HEADER_##ipv *ip_hdr0 = NULL; \ IP_HEADER_##ipv *ip_hdr1 = NULL; \ + int ret0 = HICN_ERROR_NONE, ret1 = HICN_ERROR_NONE; \ hicn_buffer_t *hicnb0, *hicnb1; \ \ /* Prefetch for next iteration. */ \ @@ -300,63 +302,149 @@ typedef enum \ stats.pkts_interest_count += 2; \ \ - u8 is_icmp0 = ip_hdr0->protocol == IPPROTO_ICMPV##ipv; \ - u8 is_icmp1 = ip_hdr1->protocol == IPPROTO_ICMPV##ipv; \ - \ - next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \ - (1 - is_icmp0) * NEXT_INTEREST_IP##ipv; \ - \ - next1 = is_icmp1 * NEXT_MAPME_IP##ipv + \ - (1 - is_icmp1) * NEXT_INTEREST_IP##ipv; \ - \ - next_iface0 = NEXT_DATA_LOOKUP_IP##ipv; \ - sw_if0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ - \ - if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \ - vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \ + /* Parse packet and cache useful info in opaque2 */ \ + ret0 = hicn_interest_parse_pkt (b0); \ + ret1 = hicn_interest_parse_pkt (b1); \ + is_icmp0 = ret0 == HICN_ERROR_PARSER_MAPME_PACKET; \ + is_icmp1 = ret1 == HICN_ERROR_PARSER_MAPME_PACKET; \ + ret0 = (ret0 == HICN_ERROR_NONE) || \ + (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \ + ret1 = (ret1 == HICN_ERROR_NONE) || \ + (ret1 == HICN_ERROR_PARSER_MAPME_PACKET); \ + \ + if (PREDICT_TRUE (ret0 && ret1)) \ { \ - next_iface0 = NEXT_UDP_ENCAP_IP4; \ - sw_if0 = ~0; \ + next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \ + (1 - is_icmp0) * NEXT_INTEREST_IP##ipv; \ + \ + next1 = is_icmp1 * NEXT_MAPME_IP##ipv + \ + (1 - is_icmp1) * NEXT_INTEREST_IP##ipv; \ + \ + next_iface0 = NEXT_DATA_LOOKUP_IP##ipv; \ + sw_if0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ + \ + if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \ + vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \ + { \ + next_iface0 = NEXT_UDP_ENCAP_IP4; \ + sw_if0 = ~0; \ + } \ + else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \ + vnet_buffer (b0)->ip.adj_index[VLIB_RX] != \ + ADJ_INDEX_INVALID) \ + { \ + next_iface0 = NEXT_UDP_ENCAP_IP6; \ + sw_if0 = ~0; \ + } \ + else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_PG) \ + { \ + next_iface0 = NEXT_PG##ipv; \ + } \ + \ + next_iface1 = NEXT_DATA_LOOKUP_IP##ipv; \ + sw_if1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \ + \ + if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \ + vnet_buffer (b1)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \ + { \ + next_iface1 = NEXT_UDP_ENCAP_IP4; \ + sw_if1 = ~0; \ + } \ + else if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \ + vnet_buffer (b1)->ip.adj_index[VLIB_RX] != \ + ADJ_INDEX_INVALID) \ + { \ + next_iface1 = NEXT_UDP_ENCAP_IP6; \ + sw_if1 = ~0; \ + } \ + else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_PG) \ + { \ + next_iface1 = NEXT_PG##ipv; \ + } \ + \ + DPO_ADD_LOCK_FACE_IP##ipv ( \ + &(hicnb0->face_id), &hicnb0->flags, &(ip_hdr0->src_address), \ + sw_if0, vnet_buffer (b0)->ip.adj_index[VLIB_RX], next_iface0); \ + \ + DPO_ADD_LOCK_FACE_IP##ipv ( \ + &(hicnb1->face_id), &hicnb1->flags, &(ip_hdr1->src_address), \ + sw_if1, vnet_buffer (b1)->ip.adj_index[VLIB_RX], next_iface1); \ } \ - else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \ - vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \ + else if (ret0 && !ret1) \ { \ - next_iface0 = NEXT_UDP_ENCAP_IP6; \ - sw_if0 = ~0; \ + next1 = HICN##ipv##_IFACE_INPUT_NEXT_ERROR_DROP; \ + next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \ + (1 - is_icmp0) * NEXT_INTEREST_IP##ipv; \ + next_iface0 = NEXT_DATA_LOOKUP_IP##ipv; \ + sw_if0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ + \ + if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \ + vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \ + { \ + next_iface0 = NEXT_UDP_ENCAP_IP4; \ + sw_if0 = ~0; \ + } \ + else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \ + vnet_buffer (b0)->ip.adj_index[VLIB_RX] != \ + ADJ_INDEX_INVALID) \ + { \ + next_iface0 = NEXT_UDP_ENCAP_IP6; \ + sw_if0 = ~0; \ + } \ + else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_PG) \ + { \ + next_iface0 = NEXT_PG##ipv; \ + } \ + \ + DPO_ADD_LOCK_FACE_IP##ipv ( \ + &(hicnb0->face_id), &hicnb0->flags, &(ip_hdr0->src_address), \ + sw_if0, vnet_buffer (b0)->ip.adj_index[VLIB_RX], next_iface0); \ } \ - \ - next_iface1 = NEXT_DATA_LOOKUP_IP##ipv; \ - sw_if1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \ - \ - if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \ - vnet_buffer (b1)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \ + else if (!ret0 && ret1) \ { \ - next_iface1 = NEXT_UDP_ENCAP_IP4; \ - sw_if1 = ~0; \ + next0 = HICN##ipv##_IFACE_INPUT_NEXT_ERROR_DROP; \ + next_iface1 = NEXT_DATA_LOOKUP_IP##ipv; \ + sw_if1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \ + next1 = is_icmp1 * NEXT_MAPME_IP##ipv + \ + (1 - is_icmp1) * NEXT_INTEREST_IP##ipv; \ + \ + if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \ + vnet_buffer (b1)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \ + { \ + next_iface1 = NEXT_UDP_ENCAP_IP4; \ + sw_if1 = ~0; \ + } \ + else if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \ + vnet_buffer (b1)->ip.adj_index[VLIB_RX] != \ + ADJ_INDEX_INVALID) \ + { \ + next_iface1 = NEXT_UDP_ENCAP_IP6; \ + sw_if1 = ~0; \ + } \ + else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_PG) \ + { \ + next_iface1 = NEXT_PG##ipv; \ + } \ + \ + DPO_ADD_LOCK_FACE_IP##ipv ( \ + &(hicnb1->face_id), &hicnb1->flags, &(ip_hdr1->src_address), \ + sw_if1, vnet_buffer (b1)->ip.adj_index[VLIB_RX], next_iface1); \ } \ - else if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \ - vnet_buffer (b1)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \ + else \ { \ - next_iface1 = NEXT_UDP_ENCAP_IP6; \ - sw_if1 = ~0; \ + next0 = HICN##ipv##_IFACE_INPUT_NEXT_ERROR_DROP; \ + next1 = HICN##ipv##_IFACE_INPUT_NEXT_ERROR_DROP; \ } \ \ - DPO_ADD_LOCK_FACE_IP##ipv ( \ - &(hicnb0->face_id), &hicnb0->flags, &(ip_hdr0->src_address), sw_if0, \ - vnet_buffer (b0)->ip.adj_index[VLIB_RX], next_iface0); \ - \ - DPO_ADD_LOCK_FACE_IP##ipv ( \ - &(hicnb1->face_id), &hicnb1->flags, &(ip_hdr1->src_address), sw_if1, \ - vnet_buffer (b1)->ip.adj_index[VLIB_RX], next_iface1); \ - \ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ (b0->flags & VLIB_BUFFER_IS_TRACED))) \ { \ TRACE_INPUT_PKT_IP##ipv *t = \ vlib_add_trace (vm, node, b0, sizeof (*t)); \ - t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->pkt_type = HICN_PACKET_TYPE_INTEREST; \ t->sw_if_index = sw_if0; \ t->next_index = next0; \ + t->error = ret0; \ clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \ sizeof (t->packet_data)); \ } \ @@ -366,9 +454,10 @@ typedef enum { \ TRACE_INPUT_PKT_IP##ipv *t = \ vlib_add_trace (vm, node, b1, sizeof (*t)); \ - t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->pkt_type = HICN_PACKET_TYPE_INTEREST; \ t->sw_if_index = sw_if1; \ t->next_index = next1; \ + t->error = ret1; \ clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b1), \ sizeof (t->packet_data)); \ } \ @@ -435,9 +524,17 @@ hicn4_iface_input_format_trace (u8 *s, va_list *args) CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); hicn4_iface_input_trace_t *t = va_arg (*args, hicn4_iface_input_trace_t *); - s = format (s, "IFACE_IP4_INPUT: pkt: %d, sw_if_index %d, next index %d\n%U", - (int) t->pkt_type, t->sw_if_index, t->next_index, - format_ip4_header, t->packet_data, sizeof (t->packet_data)); + s = format (s, "IFACE_IP4_INPUT: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + + if (t->error) + { + s = format (s, " drop reason: %s", get_error_string (t->error)); + } + + s = format (s, "\n%U", format_ip4_header, t->packet_data, + sizeof (t->packet_data)); + return (s); } @@ -544,6 +641,7 @@ hicn_rewrite_iface_data4 (vlib_main_t *vm, vlib_buffer_t *b0, const hicn_face_t *iface, u32 *next) { ip4_header_t *ip0; + int ret = HICN_ERROR_NONE; /* Get the pointer to the old ip and tcp header */ ip0 = vlib_buffer_get_current (b0); @@ -563,9 +661,11 @@ hicn_rewrite_iface_data4 (vlib_main_t *vm, vlib_buffer_t *b0, hicn_type_t type = hicn_get_buffer (b0)->type; u8 flags = hicn_get_buffer (b0)->flags; u8 reset_pl = flags & HICN_BUFFER_FLAGS_FROM_CS; - int ret = hicn_ops_vft[type.l1]->rewrite_data ( - type, &hicn->protocol, &(iface->nat_addr), &(temp_addr), iface->pl_id, - reset_pl); + + ret = hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol, + &(iface->nat_addr), &(temp_addr), + iface->pl_id, reset_pl); + if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED) { ensure_offload_flags (b0, 1 /* is_v4 */); @@ -577,6 +677,7 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0, const hicn_face_t *iface, u32 *next) { ip6_header_t *ip0; + int ret = HICN_ERROR_NONE; /* Get the pointer to the old ip and tcp header */ /* Copy the previous ip and tcp header to the new portion of memory */ @@ -598,9 +699,10 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0, hicn_type_t type = hicn_get_buffer (b0)->type; u8 flags = hicn_get_buffer (b0)->flags; u8 reset_pl = flags & HICN_BUFFER_FLAGS_FROM_CS; - int ret = hicn_ops_vft[type.l1]->rewrite_data ( - type, &hicn->protocol, &(iface->nat_addr), &(temp_addr), iface->pl_id, - reset_pl); + + ret = hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol, + &(iface->nat_addr), &(temp_addr), + iface->pl_id, reset_pl); if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED) { @@ -653,7 +755,7 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0, { \ TRACE_OUTPUT_PKT_IP##ipv *t = \ vlib_add_trace (vm, node, b0, sizeof (*t)); \ - t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->pkt_type = HICN_PACKET_TYPE_INTEREST; \ t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ t->next_index = next0; \ clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \ @@ -731,7 +833,7 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0, { \ TRACE_OUTPUT_PKT_IP##ipv *t = \ vlib_add_trace (vm, node, b0, sizeof (*t)); \ - t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->pkt_type = HICN_PACKET_TYPE_INTEREST; \ t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ t->next_index = next0; \ clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \ @@ -743,7 +845,7 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0, { \ TRACE_OUTPUT_PKT_IP##ipv *t = \ vlib_add_trace (vm, node, b1, sizeof (*t)); \ - t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->pkt_type = HICN_PACKET_TYPE_INTEREST; \ t->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \ t->next_index = next1; \ clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b1), \ @@ -824,7 +926,8 @@ VLIB_REGISTER_NODE (hicn4_iface_output_node) = { .next_nodes = { [HICN4_IFACE_OUTPUT_NEXT_DROP] = "error-drop", [HICN4_IFACE_OUTPUT_NEXT_LOOKUP] = "ip4-lookup", [HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap", - [HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" }, + [HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap", + [HICN4_IFACE_OUTPUT_NEXT_PG] = "hicnpg-data" }, }; static uword @@ -893,7 +996,8 @@ VLIB_REGISTER_NODE (hicn6_iface_output_node) = { .next_nodes = { [HICN6_IFACE_OUTPUT_NEXT_DROP] = "error-drop", [HICN6_IFACE_OUTPUT_NEXT_LOOKUP] = "ip6-lookup", [HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap", - [HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" }, + [HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap", + [HICN6_IFACE_OUTPUT_NEXT_PG] = "hicnpg-data" }, }; /* @@ -902,4 +1006,4 @@ VLIB_REGISTER_NODE (hicn6_iface_output_node) = { * Local Variables: * eval: (c-set-style "gnu") * End: - */ + */ \ No newline at end of file diff --git a/hicn-plugin/src/hicn.c b/hicn-plugin/src/hicn.c index 1131d4339..1789f5407 100644 --- a/hicn-plugin/src/hicn.c +++ b/hicn-plugin/src/hicn.c @@ -28,6 +28,7 @@ #include "face_db.h" #include "udp_tunnels/udp_tunnel.h" #include "route.h" +#include "pg.h" hicn_main_t hicn_main; /* Module vars */ @@ -223,24 +224,29 @@ hicn_init (vlib_main_t *vm) hicn_main_t *sm = &hicn_main; - /* Init other elements in the 'main' struct */ + // Init other elements in the 'main' struct sm->is_enabled = 0; error = hicn_api_plugin_hookup (vm); - /* Init the dpo module */ + // Init the dpo module hicn_dpos_init (); - /* Init the app manager */ + // Init the app manager address_mgr_init (); + // Init the face module hicn_face_module_init (vm); - /* Init the route module */ + // Init the route module hicn_route_init (); + // Init the UDP tunnels module udp_tunnel_init (); + // Init the packet generator module + hicn_pg_init (vm); + return error; } diff --git a/hicn-plugin/src/hicn.h b/hicn-plugin/src/hicn.h index aaf16c917..22309e3e5 100644 --- a/hicn-plugin/src/hicn.h +++ b/hicn-plugin/src/hicn.h @@ -57,32 +57,44 @@ typedef u8 weight_t; #define VLIB_BUFFER_MIN_CHAIN_SEG_SIZE (128) #endif -/* vlib_buffer cloning utilities impose that current_lentgh is more that - * 2*CLIB_CACHE_LINE_BYTES. */ -/* This flag is used to mark packets whose lenght is less that - * 2*CLIB_CACHE_LINE_BYTES. */ -#define HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL 0x02 -#define HICN_BUFFER_FLAGS_FROM_CS 0x10 - /* The following is stored in the opaque2 field in the vlib_buffer_t */ typedef struct { - /* hash of the name */ + /** + * Hash of the name (8) + */ u64 name_hash; - /* ids to prefetch a PIT/CS entry */ + /** + * IDs to prefetch a PIT/CS entry (4+4+1+1) + */ u32 node_id; u32 bucket_id; u8 hash_entry_id; u8 hash_bucket_flags; + /** + * hICN buffer flags (1) + */ u8 flags; - u8 dpo_ctx_id; /* used for data path */ - u8 vft_id; /* " */ - hicn_face_id_t face_id; /* ingress iface, sizeof(u32) */ + /** + * used for data path (1+1) + */ + u8 dpo_ctx_id; + u8 vft_id; + + /** + * Ingress face (4) + */ + hicn_face_id_t face_id; + /** + * Cached packet info + */ hicn_type_t type; + hicn_name_t name; + u16 port; } hicn_buffer_t; STATIC_ASSERT (sizeof (hicn_buffer_t) <= @@ -101,6 +113,28 @@ hicn_is_v6 (hicn_header_t *pkt_hdr) return ((pkt_hdr->v4.ip.version_ihl >> 4) != 4); } +always_inline void +hicn_buffer_get_name_and_namelen (vlib_buffer_t *b0, u8 **nameptr, + u16 *namelen) +{ + *nameptr = (u8 *) (&hicn_get_buffer (b0)->name); + *namelen = ip_address_is_v4 (&hicn_get_buffer (b0)->name.prefix) ? + HICN_V4_NAME_LEN : + HICN_V6_NAME_LEN; +} + +always_inline u8 +hicn_buffer_is_v6 (vlib_buffer_t *b0) +{ + return hicn_get_buffer (b0)->type.l1 == IPPROTO_IPV6; +} + +always_inline void +hicn_buffer_set_flags (vlib_buffer_t *b, u8 flags) +{ + hicn_buffer_t *hb = hicn_get_buffer (b); + hb->flags |= flags; +} #endif /* __HICN_H__ */ /* diff --git a/hicn-plugin/src/hicn_buffer_flags.h b/hicn-plugin/src/hicn_buffer_flags.h new file mode 100644 index 000000000..7d99e6d33 --- /dev/null +++ b/hicn-plugin/src/hicn_buffer_flags.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 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: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HICN_BUFFER_FLAGS_H__ +#define __HICN_BUFFER_FLAGS_H__ + +#define foreach_hicn_buffer_flag \ + _ (0, NEW_FACE, "new face") \ + _ (1, PKT_LESS_TWO_CL, "packet is less that 2 cache lines length") \ + _ (2, FROM_UDP4_TUNNEL, "packet is from udp4 tunnel") \ + _ (3, FROM_UDP6_TUNNEL, "packet is from udp6 tunnel") \ + _ (4, FROM_CS, "packet is from cs") \ + _ (5, FROM_PG, "packet is from packet generator") + +enum +{ + HICN_BUFFER_FLAGS_DEFAULT = 0, +#define _(a, b, c) HICN_BUFFER_FLAGS_##b = (1 << a), + foreach_hicn_buffer_flag +#undef _ +}; + +#endif /* __HICN_BUFFER_FLAGS_H__ */ \ No newline at end of file diff --git a/hicn-plugin/src/interest_hitcs_node.c b/hicn-plugin/src/interest_hitcs_node.c index 947b4cb68..1af21191c 100644 --- a/hicn-plugin/src/interest_hitcs_node.c +++ b/hicn-plugin/src/interest_hitcs_node.c @@ -90,7 +90,6 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, hicn_interest_hitcs_runtime_t *rt; vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; f64 tnow; - int ret; rt = vlib_node_get_runtime_data (vm, hicn_interest_hitcs_node.index); @@ -116,8 +115,6 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, u16 namelen; u32 bi0; u32 next0 = HICN_INTEREST_HITCS_NEXT_ERROR_DROP; - hicn_name_t name; - hicn_header_t *hicn0; hicn_buffer_t *hicnb0; hicn_hash_node_t *node0; hicn_pcs_entry_t *pitp; @@ -150,8 +147,8 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, hicn_get_internal_state (hicnb0, rt->pitcs, &node0, &strategy_vft0, &dpo_vft0, &dpo_ctx_id0, &hash_entry0); - ret = hicn_interest_parse_pkt (b0, &name, &namelen, &hicn0, &isv6); - nameptr = (u8 *) (&name); + hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen); + isv6 = hicn_buffer_is_v6 (b0); pitp = hicn_pit_get_data (node0); dpo_id_t hicn_dpo_id0 = { .dpoi_type = @@ -160,8 +157,7 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, .dpoi_next_node = 0, .dpoi_index = dpo_ctx_id0 }; - if (PREDICT_FALSE (ret != HICN_ERROR_NONE || - !hicn_node_compare (nameptr, namelen, node0))) + if (PREDICT_FALSE (!hicn_node_compare (nameptr, namelen, node0))) { /* Remove lock from the entry */ hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, hash_entry0, @@ -209,7 +205,7 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, { hicn_interest_hitcs_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_INTEREST; + t->pkt_type = HICN_PACKET_TYPE_INTEREST; t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; t->next_index = next0; } @@ -285,4 +281,4 @@ VLIB_REGISTER_NODE (hicn_interest_hitcs_node) = { * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */ + */ \ No newline at end of file diff --git a/hicn-plugin/src/interest_hitpit.h b/hicn-plugin/src/interest_hitpit.h index 18ef94aa7..46659e67c 100644 --- a/hicn-plugin/src/interest_hitpit.h +++ b/hicn-plugin/src/interest_hitpit.h @@ -46,7 +46,7 @@ typedef struct { u32 next_index; u32 sw_if_index; - u8 pkt_type; + u32 pkt_type; } hicn_interest_hitpit_trace_t; typedef enum @@ -65,4 +65,4 @@ typedef enum * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */ + */ \ No newline at end of file diff --git a/hicn-plugin/src/interest_hitpit_node.c b/hicn-plugin/src/interest_hitpit_node.c index 33dc782cd..c98baf7e9 100644 --- a/hicn-plugin/src/interest_hitpit_node.c +++ b/hicn-plugin/src/interest_hitpit_node.c @@ -79,8 +79,6 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, u16 namelen; u32 bi0; u32 next0 = HICN_INTEREST_HITPIT_NEXT_ERROR_DROP; - hicn_name_t name; - hicn_header_t *hicn0; hicn_hash_node_t *node0; const hicn_strategy_vft_t *strategy_vft0; const hicn_dpo_vft_t *dpo_vft0; @@ -92,7 +90,6 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, u32 outfaces_len; hicn_hash_entry_t *hash_entry0; hicn_buffer_t *hicnb0; - int ret; /* Prefetch for next iteration. */ if (n_left_from > 1) @@ -118,8 +115,9 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, hicn_get_internal_state (hicnb0, rt->pitcs, &node0, &strategy_vft0, &dpo_vft0, &dpo_ctx_id0, &hash_entry0); - ret = hicn_interest_parse_pkt (b0, &name, &namelen, &hicn0, &isv6); - nameptr = (u8 *) (&name); + hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen); + isv6 = hicn_buffer_is_v6 (b0); + pitp = hicn_pit_get_data (node0); dpo_id_t hicn_dpo_id0 = { .dpoi_type = dpo_vft0->hicn_dpo_get_type (), @@ -131,8 +129,7 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, * Check if the hit is instead a collision in the * hash table. Unlikely to happen. */ - if (PREDICT_FALSE (ret != HICN_ERROR_NONE || - !hicn_node_compare (nameptr, namelen, node0))) + if (PREDICT_FALSE (!hicn_node_compare (nameptr, namelen, node0))) { stats.interests_hash_collision++; /* Remove lock from the entry */ @@ -227,7 +224,7 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, hicn_interest_hitpit_trace_t *t = vlib_add_trace (vm, node, local_b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_INTEREST; + t->pkt_type = HICN_PACKET_TYPE_INTEREST; t->sw_if_index = vnet_buffer (local_b0) ->sw_if_index[VLIB_RX]; t->next_index = next0; @@ -266,7 +263,7 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, { hicn_interest_hitpit_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_INTEREST; + t->pkt_type = HICN_PACKET_TYPE_INTEREST; t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; t->next_index = next0; } @@ -354,4 +351,4 @@ VLIB_REGISTER_NODE(hicn_interest_hitpit_node) = * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */ + */ \ No newline at end of file diff --git a/hicn-plugin/src/interest_pcslookup_node.c b/hicn-plugin/src/interest_pcslookup_node.c index ff0da12d7..e569573b7 100644 --- a/hicn-plugin/src/interest_pcslookup_node.c +++ b/hicn-plugin/src/interest_pcslookup_node.c @@ -57,7 +57,6 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, hicn_interest_pcslookup_next_t next_index; hicn_interest_pcslookup_runtime_t *rt; vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; - int ret; rt = vlib_node_get_runtime_data (vm, hicn_interest_pcslookup_node.index); @@ -76,14 +75,11 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, 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_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP; u64 name_hash = 0; - hicn_name_t name; - hicn_header_t *hicn0; u32 node_id0 = 0; index_t dpo_ctx_id0 = 0; u8 vft_id0 = 0; @@ -109,19 +105,15 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, n_left_to_next -= 1; b0 = vlib_get_buffer (vm, bi0); - ret = hicn_interest_parse_pkt (b0, &name, &namelen, &hicn0, &isv6); - if (PREDICT_TRUE (ret == HICN_ERROR_NONE)) - { - next0 = HICN_INTEREST_PCSLOOKUP_NEXT_STRATEGY; - } - nameptr = (u8 *) (&name); + hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen); + + next0 = HICN_INTEREST_PCSLOOKUP_NEXT_STRATEGY; stats.pkts_processed++; if (PREDICT_FALSE ( - ret != HICN_ERROR_NONE || hicn_hashtb_fullhash (nameptr, namelen, &name_hash) != - HICN_ERROR_NONE)) + HICN_ERROR_NONE)) { next0 = HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP; } @@ -149,7 +141,7 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, { hicn_interest_pcslookup_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_INTEREST; + t->pkt_type = HICN_PACKET_TYPE_INTEREST; t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; t->next_index = next0; } @@ -226,4 +218,4 @@ VLIB_REGISTER_NODE(hicn_interest_pcslookup_node) = * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */ + */ \ No newline at end of file diff --git a/hicn-plugin/src/parser.h b/hicn-plugin/src/parser.h index 0e60c526f..29405ebec 100644 --- a/hicn-plugin/src/parser.h +++ b/hicn-plugin/src/parser.h @@ -25,93 +25,149 @@ * @file parser.h */ -/* - * Key type codes for header, header tlvs, body tlvs, and child tlvs - */ - -// FIXME(reuse lib struct, no more control ?) -enum hicn_pkt_type_e -{ - HICN_PKT_TYPE_INTEREST = 0, - HICN_PKT_TYPE_CONTENT = 1, -}; - /** - * @brief Parse an interest packet + * @brief Parse a interest packet * * @param pkt vlib buffer holding the interest - * @param name return variable that will point to the hicn name - * @param namelen return valiable that will hold the length of the name - * @param pkt_hdrp return valiable that will point to the packet header - * @param isv6 return variable that will be equale to 1 is the header is ipv6 + * @param name [RETURNED] variable that will point to the hicn name + * @param namelen [RETURNED] variable that will hold the length of the name + * @param port [RETURNED] variable that will hold the source port of the packet + * @param pkt_hdrp [RETURNED] valiable that will point to the packet header + * @param isv6 [RETURNED] variable that will be equale to 1 is the header is + * ipv6 */ always_inline int -hicn_interest_parse_pkt (vlib_buffer_t *pkt, hicn_name_t *name, u16 *namelen, - hicn_header_t **pkt_hdrp, u8 *isv6) +hicn_interest_parse_pkt (vlib_buffer_t *pkt) { if (pkt == NULL) return HICN_ERROR_PARSER_PKT_INVAL; - hicn_header_t *pkt_hdr = vlib_buffer_get_current (pkt); - *pkt_hdrp = pkt_hdr; - u8 *ip_pkt = vlib_buffer_get_current (pkt); - *isv6 = hicn_is_v6 (pkt_hdr); - u8 ip_proto = (*isv6) * IPPROTO_IPV6; - u8 next_proto_offset = 6 + (1 - *isv6) * 3; - // in the ipv6 header the next header field is at byte 6 - // in the ipv4 header the protocol field is at byte 9 - hicn_type_t type = - (hicn_type_t){ { .l4 = IPPROTO_NONE, - .l3 = ip_pkt[next_proto_offset] == IPPROTO_UDP ? - IPPROTO_ENCAP : - IPPROTO_NONE, - .l2 = ip_pkt[next_proto_offset], - .l1 = ip_proto } }; + + int ret = HICN_LIB_ERROR_NONE; + + hicn_header_t *pkt_hdr; + u8 *ip_pkt; + u8 ip_proto; + u8 next_proto_offset; + hicn_type_t type; + hicn_name_t *name; + u16 *port; + int isv6; + + // start parsing first fields to get the protocols + pkt_hdr = vlib_buffer_get_current (pkt); + isv6 = hicn_is_v6 (pkt_hdr); + + ip_pkt = vlib_buffer_get_current (pkt); + ip_proto = (1 - isv6) * IPPROTO_IP + (isv6) *IPPROTO_IPV6; + + // in the ipv6 header the next header field is at byte 6 in the ipv4 + // header the protocol field is at byte 9 + next_proto_offset = 6 + (1 - isv6) * 3; + + // get type info + type.l4 = IPPROTO_NONE; + type.l3 = + ip_pkt[next_proto_offset] == IPPROTO_UDP ? IPPROTO_ENCAP : IPPROTO_NONE; + type.l2 = ip_pkt[next_proto_offset]; + type.l1 = ip_proto; + + // cache hicn packet type in opaque2 hicn_get_buffer (pkt)->type = type; - hicn_ops_vft[type.l1]->get_interest_name (type, &pkt_hdr->protocol, name); - *namelen = (1 - (*isv6)) * HICN_V4_NAME_LEN + (*isv6) * HICN_V6_NAME_LEN; + // get name and name length + name = &hicn_get_buffer (pkt)->name; + ret = + hicn_ops_vft[type.l1]->get_interest_name (type, &pkt_hdr->protocol, name); + if (PREDICT_FALSE (ret)) + { + if (type.l2 == IPPROTO_ICMPV4 || type.l2 == IPPROTO_ICMPV6) + { + return HICN_ERROR_PARSER_MAPME_PACKET; + } + return HICN_ERROR_PARSER_PKT_INVAL; + } - return HICN_ERROR_NONE; + // get source port + port = &hicn_get_buffer (pkt)->port; + hicn_ops_vft[type.l1]->get_source_port (type, &pkt_hdr->protocol, port); + if (PREDICT_FALSE (ret)) + { + return HICN_ERROR_PARSER_PKT_INVAL; + } + + return ret; } /** * @brief Parse a data packet * - * @param pkt vlib buffer holding the interest - * @param name return variable that will point to the hicn name - * @param namelen return valiable that will hold the length of the name - * @param pkt_hdrp return valiable that will point to the packet header - * @param isv6 return variable that will be equale to 1 is the header is ipv6 + * @param pkt vlib buffer holding the data + * @param name [RETURNED] variable that will point to the hicn name + * @param namelen [RETURNED] variable that will hold the length of the name + * @param port [RETURNED] variable that will hold the source port of the packet + * @param pkt_hdrp [RETURNED] valiable that will point to the packet header + * @param isv6 [RETURNED] variable that will be equale to 1 is the header is + * ipv6 */ always_inline int -hicn_data_parse_pkt (vlib_buffer_t *pkt, hicn_name_t *name, u16 *namelen, - hicn_header_t **pkt_hdrp, u8 *isv6) +hicn_data_parse_pkt (vlib_buffer_t *pkt) { if (pkt == NULL) return HICN_ERROR_PARSER_PKT_INVAL; - hicn_header_t *pkt_hdr = vlib_buffer_get_current (pkt); - *pkt_hdrp = pkt_hdr; - *pkt_hdrp = pkt_hdr; - u8 *ip_pkt = vlib_buffer_get_current (pkt); - *isv6 = hicn_is_v6 (pkt_hdr); - u8 ip_proto = (*isv6) * IPPROTO_IPV6; - /* - * in the ipv6 header the next header field is at byte 6 in the ipv4 - * header the protocol field is at byte 9 - */ - u8 next_proto_offset = 6 + (1 - *isv6) * 3; - hicn_type_t type = - (hicn_type_t){ { .l4 = IPPROTO_NONE, - .l3 = ip_pkt[next_proto_offset] == IPPROTO_UDP ? - IPPROTO_ENCAP : - IPPROTO_NONE, - .l2 = ip_pkt[next_proto_offset], - .l1 = ip_proto } }; + + int ret = HICN_LIB_ERROR_NONE; + + hicn_header_t *pkt_hdr; + u8 *ip_pkt; + u8 ip_proto; + int isv6; + u8 next_proto_offset; + hicn_type_t type; + hicn_name_t *name; + u16 *port; + + // start parsing first fields to get the protocols + pkt_hdr = vlib_buffer_get_current (pkt); + isv6 = hicn_is_v6 (pkt_hdr); + + ip_pkt = vlib_buffer_get_current (pkt); + ip_proto = (1 - isv6) * IPPROTO_IP + (isv6) *IPPROTO_IPV6; + + // in the ipv6 header the next header field is at byte 6 in the ipv4 + // header the protocol field is at byte 9 + next_proto_offset = 6 + (1 - isv6) * 3; + + // get type info + type.l4 = IPPROTO_NONE; + type.l3 = + ip_pkt[next_proto_offset] == IPPROTO_UDP ? IPPROTO_ENCAP : IPPROTO_NONE; + type.l2 = ip_pkt[next_proto_offset]; + type.l1 = ip_proto; + + // cache hicn packet type in opaque2 hicn_get_buffer (pkt)->type = type; - hicn_ops_vft[type.l1]->get_data_name (type, &pkt_hdr->protocol, name); - *namelen = (1 - (*isv6)) * HICN_V4_NAME_LEN + (*isv6) * HICN_V6_NAME_LEN; - return HICN_ERROR_NONE; + // get name and name length + name = &hicn_get_buffer (pkt)->name; + ret = hicn_ops_vft[type.l1]->get_data_name (type, &pkt_hdr->protocol, name); + if (PREDICT_FALSE (ret)) + { + if (type.l2 == IPPROTO_ICMPV4 || type.l2 == IPPROTO_ICMPV6) + { + return HICN_ERROR_PARSER_MAPME_PACKET; + } + return HICN_ERROR_PARSER_PKT_INVAL; + } + + // get source port + port = &hicn_get_buffer (pkt)->port; + hicn_ops_vft[type.l1]->get_source_port (type, &pkt_hdr->protocol, port); + if (PREDICT_FALSE (ret)) + { + return HICN_ERROR_PARSER_PKT_INVAL; + } + + return ret; } #endif /* // __HICN_PARSER_H__ */ @@ -120,4 +176,4 @@ hicn_data_parse_pkt (vlib_buffer_t *pkt, hicn_name_t *name, u16 *namelen, * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */ + */ \ No newline at end of file diff --git a/hicn-plugin/src/pg.c b/hicn-plugin/src/pg.c index b77e8fcac..05172345b 100644 --- a/hicn-plugin/src/pg.c +++ b/hicn-plugin/src/pg.c @@ -18,57 +18,13 @@ #include #include #include +#include #include "hicn.h" #include "pg.h" #include "parser.h" #include "infra.h" - -/* Registration struct for a graph node */ -vlib_node_registration_t hicn_pg_interest_node; -vlib_node_registration_t hicn_pg_data_node; - -/* Stats, which end up called "error" even though they aren't... */ -#define foreach_hicnpg_error \ - _ (PROCESSED, "hICN PG packets processed") \ - _ (DROPPED, "hICN PG packets dropped") \ - _ (INTEREST_MSGS_GENERATED, "hICN PG Interests generated") \ - _ (CONTENT_MSGS_RECEIVED, "hICN PG Content msgs received") - -typedef enum -{ -#define _(sym, str) HICNPG_ERROR_##sym, - foreach_hicnpg_error -#undef _ - HICNPG_N_ERROR, -} hicnpg_error_t; - -static char *hicnpg_error_strings[] = { -#define _(sym, string) string, - foreach_hicnpg_error -#undef _ -}; - -/* - * Next graph nodes, which reference the list in the actual registration - * block below - */ -typedef enum -{ - HICNPG_INTEREST_NEXT_V4_LOOKUP, - HICNPG_INTEREST_NEXT_V6_LOOKUP, - HICNPG_INTEREST_NEXT_DROP, - HICNPG_N_NEXT, -} hicnpg_interest_next_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - u16 msg_type; -} hicnpg_trace_t; +#include "route.h" hicnpg_main_t hicnpg_main = { .index = (u32) 0, .index_ifaces = (u32) 1, @@ -78,1183 +34,281 @@ hicnpg_main_t hicnpg_main = { .index = (u32) 0, .n_ifaces = (u32) 1, .sw_if = (u32) 0 }; -hicnpg_server_main_t hicnpg_server_main = { - .node_index = 0, -}; - -/* packet trace format function */ -static u8 * -format_hicnpg_trace (u8 *s, va_list *args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - hicnpg_trace_t *t = va_arg (*args, hicnpg_trace_t *); - - s = format (s, "HICNPG: pkt: %d, msg %d, sw_if_index %d, next index %d", - (int) t->pkt_type, (int) t->msg_type, t->sw_if_index, - t->next_index); - return (s); -} - -always_inline void hicn_rewrite_interestv4 (vlib_main_t *vm, vlib_buffer_t *b0, - u32 seq_number, u16 lifetime, - u32 next_flow, u32 iface); - -always_inline void hicn_rewrite_interestv6 (vlib_main_t *vm, vlib_buffer_t *b0, - u32 seq_number, u16 lifetime, - u32 next_flow, u32 iface); - -always_inline void convert_interest_to_data_v4 (vlib_main_t *vm, - vlib_buffer_t *b0, - vlib_buffer_t *rb, u32 bi0); - -always_inline void convert_interest_to_data_v6 (vlib_main_t *vm, - vlib_buffer_t *b0, - vlib_buffer_t *rb, u32 bi0); - -always_inline void calculate_tcp_checksum_v4 (vlib_main_t *vm, - vlib_buffer_t *b0); +/** + * Pool of hicnpg_server_t + */ +hicnpg_server_t *hicnpg_server_pool; -always_inline void calculate_tcp_checksum_v6 (vlib_main_t *vm, - vlib_buffer_t *b0); /* - * Node function for the icn packet-generator client. The goal here is to - * manipulate/tweak a stream of packets that have been injected by the vpp - * packet generator to generate icn request traffic. + * hicnph servrer FIB node type */ -static uword -hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, - vlib_frame_t *frame) -{ - u32 n_left_from, *from, *to_next; - hicnpg_interest_next_t next_index; - u32 pkts_processed = 0, pkts_dropped = 0; - u32 interest_msgs_generated = 0; - u32 bi0, bi1; - vlib_buffer_t *b0, *b1; - u8 pkt_type0 = 0, pkt_type1 = 0; - u16 msg_type0 = 0, msg_type1 = 0; - hicn_header_t *hicn0 = NULL, *hicn1 = NULL; - hicn_name_t name0, name1; - u16 namelen0, namelen1; - hicnpg_main_t *hpgm = &hicnpg_main; - int iface = 0; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - 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 >= 4 && n_left_to_next >= 2) - { - u32 next0 = HICNPG_INTEREST_NEXT_DROP; - u32 next1 = HICNPG_INTEREST_NEXT_DROP; - u32 sw_if_index0 = ~0, sw_if_index1 = ~0; - u8 isv6_0; - u8 isv6_1; - - /* Prefetch next iteration. */ - { - vlib_buffer_t *p2, *p3; - - p2 = vlib_get_buffer (vm, from[2]); - p3 = vlib_get_buffer (vm, from[3]); - - vlib_prefetch_buffer_header (p2, LOAD); - vlib_prefetch_buffer_header (p3, LOAD); - - CLIB_PREFETCH (p2->data, (2 * CLIB_CACHE_LINE_BYTES), STORE); - CLIB_PREFETCH (p3->data, (2 * CLIB_CACHE_LINE_BYTES), STORE); - } - - /* - * speculatively enqueue b0 and b1 to the current - * next frame - */ - to_next[0] = bi0 = from[0]; - to_next[1] = bi1 = from[1]; - from += 2; - to_next += 2; - n_left_from -= 2; - n_left_to_next -= 2; - - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; - vnet_buffer (b0)->sw_if_index[VLIB_RX] = hpgm->sw_if; - vnet_buffer (b1)->sw_if_index[VLIB_RX] = hpgm->sw_if; - - /* Check icn packets, locate names */ - if (hicn_interest_parse_pkt (b0, &name0, &namelen0, &hicn0, - &isv6_0) == HICN_ERROR_NONE) - { - /* this node grabs only interests */ - - /* Increment the appropriate message counter */ - interest_msgs_generated++; - - iface = (hpgm->index_ifaces % hpgm->n_ifaces); - /* Rewrite and send */ - isv6_0 ? - hicn_rewrite_interestv6 ( - vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number, - hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, - iface) : - hicn_rewrite_interestv4 ( - vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number, - hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface); - - hpgm->index_ifaces++; - if (iface == (hpgm->n_ifaces - 1)) - hpgm->index++; - - next0 = isv6_0 ? HICNPG_INTEREST_NEXT_V6_LOOKUP : - HICNPG_INTEREST_NEXT_V4_LOOKUP; - } - if (hicn_interest_parse_pkt (b1, &name1, &namelen1, &hicn1, - &isv6_1) == HICN_ERROR_NONE) - { - /* this node grabs only interests */ - - /* Increment the appropriate message counter */ - interest_msgs_generated++; - - iface = (hpgm->index_ifaces % hpgm->n_ifaces); - /* Rewrite and send */ - isv6_1 ? - hicn_rewrite_interestv6 ( - vm, b1, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number, - hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, - iface) : - hicn_rewrite_interestv4 ( - vm, b1, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number, - hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface); - - hpgm->index_ifaces++; - if (iface == (hpgm->n_ifaces - 1)) - hpgm->index++; - - next1 = isv6_1 ? HICNPG_INTEREST_NEXT_V6_LOOKUP : - HICNPG_INTEREST_NEXT_V4_LOOKUP; - } - /* Send pkt to next node */ - vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0; - vnet_buffer (b1)->sw_if_index[VLIB_TX] = ~0; - - pkts_processed += 2; - - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE))) - { - if (b0->flags & VLIB_BUFFER_IS_TRACED) - { - hicnpg_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = pkt_type0; - t->msg_type = msg_type0; - t->sw_if_index = sw_if_index0; - t->next_index = next0; - } - if (b1->flags & VLIB_BUFFER_IS_TRACED) - { - hicnpg_trace_t *t = - vlib_add_trace (vm, node, b1, sizeof (*t)); - t->pkt_type = pkt_type1; - t->msg_type = msg_type1; - t->sw_if_index = sw_if_index1; - t->next_index = next1; - } - } - if (next0 == HICNPG_INTEREST_NEXT_DROP) - { - pkts_dropped++; - } - if (next1 == HICNPG_INTEREST_NEXT_DROP) - { - pkts_dropped++; - } - /* - * verify speculative enqueues, maybe switch current - * next frame - */ - vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, - n_left_to_next, bi0, bi1, next0, - next1); - } - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 next0 = HICNPG_INTEREST_NEXT_DROP; - u32 sw_if_index0; - u8 isv6_0; - - /* speculatively enqueue b0 to the current next frame */ - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - vnet_buffer (b0)->sw_if_index[VLIB_RX] = hpgm->sw_if; - - /* Check icn packets, locate names */ - if (hicn_interest_parse_pkt (b0, &name0, &namelen0, &hicn0, - &isv6_0) == HICN_ERROR_NONE) - { - /* this node grabs only interests */ - - /* Increment the appropriate message counter */ - interest_msgs_generated++; - - iface = (hpgm->index_ifaces % hpgm->n_ifaces); - - /* Rewrite and send */ - isv6_0 ? - hicn_rewrite_interestv6 ( - vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number, - hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, - iface) : - hicn_rewrite_interestv4 ( - vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number, - hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface); - - hpgm->index_ifaces++; - if (iface == (hpgm->n_ifaces - 1)) - hpgm->index++; - - next0 = isv6_0 ? HICNPG_INTEREST_NEXT_V6_LOOKUP : - HICNPG_INTEREST_NEXT_V4_LOOKUP; - } - /* Send pkt to ip lookup */ - vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0; +fib_node_type_t hicnpg_server_fib_node_type; - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - hicnpg_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = pkt_type0; - t->msg_type = msg_type0; - t->sw_if_index = sw_if_index0; - t->next_index = next0; - } - pkts_processed += 1; - - if (next0 == HICNPG_INTEREST_NEXT_DROP) - { - pkts_dropped++; - } - /* - * verify speculative enqueue, maybe switch current - * next 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); - } - - vlib_node_increment_counter (vm, hicn_pg_interest_node.index, - HICNPG_ERROR_PROCESSED, pkts_processed); - vlib_node_increment_counter (vm, hicn_pg_interest_node.index, - HICNPG_ERROR_DROPPED, pkts_dropped); - vlib_node_increment_counter (vm, hicn_pg_interest_node.index, - HICNPG_ERROR_INTEREST_MSGS_GENERATED, - interest_msgs_generated); +/** + * Registered DPO type. + */ +dpo_type_t hicnpg_server_dpo_type; - return (frame->n_vectors); +static void +hicnpg_server_restack (hicnpg_server_t *hicnpg_server) +{ + dpo_stack ( + hicnpg_server_dpo_type, fib_proto_to_dpo (hicnpg_server->prefix.fp_proto), + &hicnpg_server->dpo, + fib_entry_contribute_ip_forwarding (hicnpg_server->fib_entry_index)); } -void -hicn_rewrite_interestv4 (vlib_main_t *vm, vlib_buffer_t *b0, u32 seq_number, - u16 interest_lifetime, u32 next_flow, u32 iface) +static hicnpg_server_t * +hicnpg_server_from_fib_node (fib_node_t *node) { - hicn_header_t *h0 = vlib_buffer_get_current (b0); - - /* Generate the right src and dst corresponding to flow and iface */ - ip46_address_t src_addr = { - .ip4 = hicnpg_main.pgen_clt_src_addr.ip4, - }; - hicn_name_t dst_name = { - .prefix.ip4 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip4, - .suffix = seq_number, - }; - - src_addr.ip4.as_u32 += clib_host_to_net_u32 (iface); - dst_name.prefix.ip4.as_u32 += clib_net_to_host_u32 (next_flow); - - /* Update locator and name */ - hicn_type_t type = hicn_get_buffer (b0)->type; - HICN_OPS4->set_interest_locator (type, &h0->protocol, &src_addr); - HICN_OPS4->set_interest_name (type, &h0->protocol, &dst_name); - - /* Update lifetime (currently L4 checksum is not updated) */ - HICN_OPS4->set_lifetime (type, &h0->protocol, interest_lifetime); - - /* Update checksums */ - HICN_OPS4->update_checksums (type, &h0->protocol, 0, 0); + ASSERT (hicnpg_server_fib_node_type == node->fn_type); + return ((hicnpg_server_t *) (((char *) node) - + STRUCT_OFFSET_OF (hicnpg_server_t, fib_node))); } /** - * @brief Rewrite the IPv6 header as the next generated packet - * - * Set up a name prefix - * - etiher generate interest in which the name varies only after the prefix - * (inc : seq_number), then the flow acts on the prefix (CHECK) - * seq_number => TCP, FLOW => - * - * SRC : pgen_clt_src_addr.ip6 DST = generate name (pgen_clt_hicn_name.ip6) - * ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff - * \__/ \__/ - * +iface + flow - * Source is used to emulate different consumers. - * FIXME iface is ill-named, better name it consumer id - * Destination is used to iterate on the content. + * Function definition to backwalk a FIB node */ -void -hicn_rewrite_interestv6 (vlib_main_t *vm, vlib_buffer_t *b0, u32 seq_number, - u16 interest_lifetime, u32 next_flow, u32 iface) +static fib_node_back_walk_rc_t +hicnpg_server_fib_back_walk (fib_node_t *node, fib_node_back_walk_ctx_t *ctx) { - hicn_header_t *h0 = vlib_buffer_get_current (b0); - - /* Generate the right src and dst corresponding to flow and iface */ - ip46_address_t src_addr = { - .ip6 = hicnpg_main.pgen_clt_src_addr.ip6, - }; - hicn_name_t dst_name = { - .prefix.ip6 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip6, - .suffix = seq_number, - }; - src_addr.ip6.as_u32[3] += clib_host_to_net_u32 (iface); - dst_name.prefix.ip6.as_u32[3] += clib_net_to_host_u32 (next_flow); + hicnpg_server_restack (hicnpg_server_from_fib_node (node)); - /* Update locator and name */ - hicn_type_t type = hicn_get_buffer (b0)->type; - HICN_OPS6->set_interest_locator (type, &h0->protocol, &src_addr); - HICN_OPS6->set_interest_name (type, &h0->protocol, &dst_name); - - /* Update lifetime */ - HICN_OPS6->set_lifetime (type, &h0->protocol, interest_lifetime); - - /* Update checksums */ - calculate_tcp_checksum_v6 (vm, b0); + return FIB_NODE_BACK_WALK_CONTINUE; } -void -calculate_tcp_checksum_v4 (vlib_main_t *vm, vlib_buffer_t *b0) +/** + * Function definition to get a FIB node from its index + */ +static fib_node_t * +hicnpg_server_fib_node_get (fib_node_index_t index) { - ip4_header_t *ip0; - tcp_header_t *tcp0; - ip_csum_t sum0; - u32 tcp_len0; - - ip0 = (ip4_header_t *) (vlib_buffer_get_current (b0)); - tcp0 = - (tcp_header_t *) (vlib_buffer_get_current (b0) + sizeof (ip4_header_t)); - tcp_len0 = clib_net_to_host_u16 (ip0->length) - sizeof (ip4_header_t); - - /* Initialize checksum with header. */ - if (BITS (sum0) == 32) - { - sum0 = clib_mem_unaligned (&ip0->src_address, u32); - sum0 = - ip_csum_with_carry (sum0, clib_mem_unaligned (&ip0->dst_address, u32)); - } - else - sum0 = clib_mem_unaligned (&ip0->src_address, u64); - - sum0 = ip_csum_with_carry ( - sum0, clib_host_to_net_u32 (tcp_len0 + (ip0->protocol << 16))); - - /* Invalidate possibly old checksum. */ - tcp0->checksum = 0; + hicnpg_server_t *hpg_server; - u32 tcp_offset = sizeof (ip4_header_t); - sum0 = ip_incremental_checksum_buffer (vm, b0, tcp_offset, tcp_len0, sum0); + hpg_server = pool_elt_at_index (hicnpg_server_pool, index); - tcp0->checksum = ~ip_csum_fold (sum0); + return (&hpg_server->fib_node); } -void -calculate_tcp_checksum_v6 (vlib_main_t *vm, vlib_buffer_t *b0) +/** + * Function definition to inform the FIB node that its last lock has gone. + */ +static void +hicnpg_server_fib_last_lock_gone (fib_node_t *node) { - ip6_header_t *ip0; - tcp_header_t *tcp0; - ip_csum_t sum0; - u32 tcp_len0; - - ip0 = (ip6_header_t *) (vlib_buffer_get_current (b0)); - tcp0 = - (tcp_header_t *) (vlib_buffer_get_current (b0) + sizeof (ip6_header_t)); - tcp_len0 = clib_net_to_host_u16 (ip0->payload_length); + hicnpg_server_t *hpg_server; - /* Initialize checksum with header. */ - if (BITS (sum0) == 32) - { - sum0 = clib_mem_unaligned (&ip0->src_address, u32); - sum0 = - ip_csum_with_carry (sum0, clib_mem_unaligned (&ip0->dst_address, u32)); - } - else - sum0 = clib_mem_unaligned (&ip0->src_address, u64); - - sum0 = ip_csum_with_carry ( - sum0, clib_host_to_net_u32 (tcp_len0 + (ip0->protocol << 16))); + hpg_server = hicnpg_server_from_fib_node (node); - /* Invalidate possibly old checksum. */ - tcp0->checksum = 0; - - u32 tcp_offset = sizeof (ip6_header_t); - sum0 = ip_incremental_checksum_buffer (vm, b0, tcp_offset, tcp_len0, sum0); + /** + * reset the stacked DPO to unlock it + */ + dpo_reset (&hpg_server->dpo); - tcp0->checksum = ~ip_csum_fold (sum0); + pool_put (hicnpg_server_pool, hpg_server); } -VLIB_REGISTER_NODE (hicn_pg_interest_node) = { - .function = hicnpg_client_interest_node_fn, - .name = "hicnpg-interest", - .vector_size = sizeof (u32), - .format_trace = format_hicnpg_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN (hicnpg_error_strings), - .error_strings = hicnpg_error_strings, - .n_next_nodes = HICNPG_N_NEXT, - .next_nodes = { [HICNPG_INTEREST_NEXT_V4_LOOKUP] = "ip4-lookup", - [HICNPG_INTEREST_NEXT_V6_LOOKUP] = "ip6-lookup", - [HICNPG_INTEREST_NEXT_DROP] = "error-drop" }, -}; - -/* - * Next graph nodes, which reference the list in the actual registration - * block below - */ -typedef enum -{ - HICNPG_DATA_NEXT_DROP, - HICNPG_DATA_NEXT_LOOKUP4, - HICNPG_DATA_NEXT_LOOKUP6, - HICNPG_DATA_N_NEXT, -} hicnpg_data_next_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - u16 msg_type; -} icnpg_data_trace_t; - -/* packet trace format function */ -static u8 * -format_hicnpg_data_trace (u8 *s, va_list *args) +static void +hicnpg_server_dpo_lock (dpo_id_t *dpo) { - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - hicnpg_trace_t *t = va_arg (*args, hicnpg_trace_t *); - - s = format (s, "HICNPG: pkt: %d, msg %d, sw_if_index %d, next index %d", - (int) t->pkt_type, (int) t->msg_type, t->sw_if_index, - t->next_index); - return (s); + hicnpg_server_t *hpg_server; + hpg_server = hicnpg_server_get (dpo->dpoi_index); + fib_node_lock (&hpg_server->fib_node); } -static_always_inline int -match_ip4_name (u32 *name, fib_prefix_t *prefix) +static void +hicnpg_server_dpo_unlock (dpo_id_t *dpo) { - u32 xor = 0; - - xor = *name & prefix->fp_addr.ip4.data_u32; - - return xor == prefix->fp_addr.ip4.data_u32; + hicnpg_server_t *hpg_server; + hpg_server = hicnpg_server_get (dpo->dpoi_index); + fib_node_unlock (&hpg_server->fib_node); } -static_always_inline int -match_ip6_name (u8 *name, fib_prefix_t *prefix) +static u8 * +format_hicnpg_server_i (u8 *s, va_list *args) { - union - { - u32x4 as_u32x4; - u64 as_u64[2]; - u32 as_u32[4]; - } xor_sum __attribute__ ((aligned (sizeof (u32x4)))); + index_t hicnpg_server_i = va_arg (*args, index_t); + // u32 indent = va_arg (*args, u32); + u32 details = va_arg (*args, u32); + // vlib_counter_t to; + hicnpg_server_t *hpg; - xor_sum.as_u64[0] = ((u64 *) name)[0] & prefix->fp_addr.ip6.as_u64[0]; - xor_sum.as_u64[1] = ((u64 *) name)[1] & prefix->fp_addr.ip6.as_u64[1]; + hpg = hicnpg_server_get (hicnpg_server_i); - return (xor_sum.as_u64[0] == prefix->fp_addr.ip6.as_u64[0]) && - (xor_sum.as_u64[1] == prefix->fp_addr.ip6.as_u64[1]); -} - -/* - * Return 0,1,2. - * 0 matches - * 1 does not match and the prefix is ip4 - * 2 does not match and the prefix is ip6 - */ -static_always_inline u32 -match_data (vlib_buffer_t *b, fib_prefix_t *prefix) -{ - u8 *ptr = vlib_buffer_get_current (b); - u8 v = *ptr & 0xf0; - u32 next = 0; + // FIXME + s = format (s, "dpo-hicnpg-server:[%d]: ip-fib-index:%d ", hicnpg_server_i, + hpg->fib_index); - if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr))) + if (FIB_PROTOCOL_IP4 == hpg->prefix.fp_proto) { - if (!match_ip4_name ((u32 *) &(ptr[12]), prefix)) - next = 1; + s = format (s, "protocol:FIB_PROTOCOL_IP4 prefix: %U", + format_fib_prefix, &hpg->prefix); } - else if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr))) + else { - if (!match_ip6_name (&(ptr[8]), prefix)) - next = 2; + s = format (s, "protocol:FIB_PROTOCOL_IP6 prefix: %U", + format_fib_prefix, &hpg->prefix); } - return next; -} - -/* - * Return 0,1,2. - * 0 matches - * 1 does not match and the prefix is ip4 - * 2 does not match and the prefix is ip6 - */ -static_always_inline u32 -match_interest (vlib_buffer_t *b, fib_prefix_t *prefix) -{ - u8 *ptr = vlib_buffer_get_current (b); - u8 v = *ptr & 0xf0; - u32 next = 0; +#if 0 + vlib_get_combined_counter (&(udp_encap_counters), uei, &to); + s = format (s, " to:[%Ld:%Ld]]", to.packets, to.bytes);s +#endif - if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr))) - { - if (!match_ip4_name ((u32 *) &(ptr[16]), prefix)) - next = 1; - } - else if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr))) + if (details) { - if (!match_ip6_name (&(ptr[24]), prefix)) - next = 2; + s = format (s, " locks:%d", hpg->fib_node.fn_locks); + // s = format (s, "\n%UStacked on:", format_white_space, indent + + // 1); s = format (s, "\n%U%U", format_white_space, indent + 2, + // format_dpo_id, + // &hpg->dpo, indent + 3); } - return next; + return s; } -/* - * Node function for the icn packet-generator client. The goal here is to - * manipulate/tweak a stream of packets that have been injected by the vpp - * packet generator to generate icn request traffic. - */ -static uword -hicnpg_client_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, - vlib_frame_t *frame) +static u8 * +format_hicnpg_server_dpo (u8 *s, va_list *args) { - u32 n_left_from, *from, *to_next; - hicnpg_data_next_t next_index; - u32 pkts_processed = 0; - u32 content_msgs_received = 0; - u32 bi0, bi1; - vlib_buffer_t *b0, *b1; - u8 pkt_type0 = 0, pkt_type1 = 0; - u16 msg_type0 = 1, msg_type1 = 1; - hicnpg_main_t *hpgm = &hicnpg_main; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - 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 >= 4 && n_left_to_next >= 2) - { - u32 next0 = HICNPG_DATA_NEXT_DROP; - u32 next1 = HICNPG_DATA_NEXT_DROP; - u32 sw_if_index0, sw_if_index1; - - /* Prefetch next iteration. */ - { - vlib_buffer_t *p2, *p3; - - p2 = vlib_get_buffer (vm, from[2]); - p3 = vlib_get_buffer (vm, from[3]); - - vlib_prefetch_buffer_header (p2, LOAD); - vlib_prefetch_buffer_header (p3, LOAD); - - CLIB_PREFETCH (p2->data, (2 * CLIB_CACHE_LINE_BYTES), STORE); - CLIB_PREFETCH (p3->data, (2 * CLIB_CACHE_LINE_BYTES), STORE); - } - - /* - * speculatively enqueue b0 and b1 to the current - * next frame - */ - to_next[0] = bi0 = from[0]; - to_next[1] = bi1 = from[1]; - from += 2; - to_next += 2; - n_left_from -= 2; - n_left_to_next -= 2; - - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; - - next0 = - HICNPG_DATA_NEXT_DROP + match_data (b0, hpgm->pgen_clt_hicn_name); - next1 = - HICNPG_DATA_NEXT_DROP + match_data (b1, hpgm->pgen_clt_hicn_name); - - if (PREDICT_FALSE (vnet_get_feature_count ( - vnet_buffer (b0)->feature_arc_index, - vnet_buffer (b0)->sw_if_index[VLIB_RX]) > 1)) - vnet_feature_next (&next0, b0); - - if (PREDICT_FALSE (vnet_get_feature_count ( - vnet_buffer (b1)->feature_arc_index, - vnet_buffer (b1)->sw_if_index[VLIB_RX]) > 1)) - vnet_feature_next (&next1, b1); - - if (next0 == HICNPG_DATA_NEXT_DROP) - { - /* Increment a counter */ - content_msgs_received++; - } - - if (next1 == HICNPG_DATA_NEXT_DROP) - { - /* Increment a counter */ - content_msgs_received++; - } - - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE))) - { - if (b0->flags & VLIB_BUFFER_IS_TRACED) - { - icnpg_data_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = pkt_type0; - t->msg_type = msg_type0; - t->sw_if_index = sw_if_index0; - t->next_index = next0; - } - if (b1->flags & VLIB_BUFFER_IS_TRACED) - { - icnpg_data_trace_t *t = - vlib_add_trace (vm, node, b1, sizeof (*t)); - t->pkt_type = pkt_type1; - t->msg_type = msg_type1; - t->sw_if_index = sw_if_index1; - t->next_index = next1; - } - } - - vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, - n_left_to_next, bi0, bi1, next0, - next1); - pkts_processed += 2; - } - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 next0 = HICNPG_DATA_NEXT_DROP; - u32 sw_if_index0; - - /* speculatively enqueue b0 to the current next frame */ - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - - next0 = - HICNPG_DATA_NEXT_DROP + match_data (b0, hpgm->pgen_clt_hicn_name); - - if (PREDICT_FALSE (vnet_get_feature_count ( - vnet_buffer (b0)->feature_arc_index, - vnet_buffer (b0)->sw_if_index[VLIB_RX]) > 1)) - vnet_feature_next (&next0, b0); + index_t hpg_server_i = va_arg (*args, index_t); + u32 indent = va_arg (*args, u32); - if (next0 == HICNPG_DATA_NEXT_DROP) - { - /* Increment a counter */ - content_msgs_received++; - } - - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - icnpg_data_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = pkt_type0; - t->msg_type = msg_type0; - t->sw_if_index = sw_if_index0; - t->next_index = next0; - } - - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, - n_left_to_next, bi0, next0); - - pkts_processed++; - } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, hicn_pg_data_node.index, - HICNPG_ERROR_PROCESSED, pkts_processed); - vlib_node_increment_counter (vm, hicn_pg_data_node.index, - HICNPG_ERROR_CONTENT_MSGS_RECEIVED, - content_msgs_received); - return (frame->n_vectors); + return (format (s, "%U", format_hicnpg_server_i, hpg_server_i, indent, 1)); } -VLIB_REGISTER_NODE(hicn_pg_data_node) = -{ - .function = hicnpg_client_data_node_fn, - .name = "hicnpg-data", - .vector_size = sizeof(u32), - .format_trace = format_hicnpg_data_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(hicnpg_error_strings), - .error_strings = hicnpg_error_strings, - .n_next_nodes = HICNPG_DATA_N_NEXT, - .next_nodes = - { - [HICNPG_DATA_NEXT_DROP] = "error-drop", - [HICNPG_DATA_NEXT_LOOKUP4] = "ip4-lookup", - [HICNPG_DATA_NEXT_LOOKUP6] = "ip6-lookup", - }, +/* + * Virtual function table registered by hicn pg server + * for participation in the FIB object graph. + */ +const static fib_node_vft_t hicnpg_server_fib_vft = { + .fnv_get = hicnpg_server_fib_node_get, + .fnv_last_lock = hicnpg_server_fib_last_lock_gone, + .fnv_back_walk = hicnpg_server_fib_back_walk, }; -VNET_FEATURE_INIT (hicn_data_input_ip4_arc, static) = { - .arc_name = "ip4-unicast", - .node_name = "hicnpg-data", - .runs_before = VNET_FEATURES ("ip4-inacl"), +const static dpo_vft_t hicnpg_server_dpo_vft = { + .dv_lock = hicnpg_server_dpo_lock, + .dv_unlock = hicnpg_server_dpo_unlock, + .dv_format = format_hicnpg_server_dpo, }; -VNET_FEATURE_INIT (hicn_data_input_ip6_arc, static) = { - .arc_name = "ip6-unicast", - .node_name = "hicnpg-data", - .runs_before = VNET_FEATURES ("ip6-inacl"), +const static char *const hicnpg_server_ip4_nodes[] = { + "hicnpg-server-4", + NULL, }; -/* - * End of packet-generator client node - */ - -/* - * Beginning of packet-generation server node - */ - -/* Registration struct for a graph node */ -vlib_node_registration_t hicn_pg_server_node; - -/* Stats, which end up called "error" even though they aren't... */ -#define foreach_icnpg_server_error \ - _ (PROCESSED, "hICN PG Server packets processed") \ - _ (DROPPED, "hICN PG Server packets dropped") - -typedef enum -{ -#define _(sym, str) HICNPG_SERVER_ERROR_##sym, - foreach_icnpg_server_error -#undef _ - HICNPG_SERVER_N_ERROR, -} icnpg_server_error_t; - -static char *icnpg_server_error_strings[] = { -#define _(sym, string) string, - foreach_icnpg_server_error -#undef _ +const static char *const hicnpg_server_ip6_nodes[] = { + "hicnpg-server-6", + NULL, }; -/* - * Next graph nodes, which reference the list in the actual registration - * block below - */ -typedef enum -{ - HICNPG_SERVER_NEXT_V4_LOOKUP, - HICNPG_SERVER_NEXT_V6_LOOKUP, - HICNPG_SERVER_NEXT_DROP, - HICNPG_SERVER_N_NEXT, -} icnpg_server_next_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - u16 msg_type; -} hicnpg_server_trace_t; +const static char *const *const hicnpg_server_nodes[DPO_PROTO_NUM] = { + [DPO_PROTO_IP4] = hicnpg_server_ip4_nodes, + [DPO_PROTO_IP6] = hicnpg_server_ip6_nodes +}; -/* packet trace format function */ -static u8 * -format_icnpg_server_trace (u8 *s, va_list *args) +clib_error_t * +hicnpg_server_add_and_lock (fib_prefix_t *prefix, u32 *hicnpg_server_index, + ip46_address_t *locator, size_t payload_size) { - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - hicnpg_server_trace_t *t = va_arg (*args, hicnpg_server_trace_t *); + hicnpg_server_t *hpg; + index_t hpgi; + u32 fib_index; + fib_node_index_t fib_entry_index; + u32 buffer_index; + vlib_buffer_t *rb = NULL; - s = format ( - s, "HICNPG SERVER: pkt: %d, msg %d, sw_if_index %d, next index %d", - (int) t->pkt_type, (int) t->msg_type, t->sw_if_index, t->next_index); - return (s); -} + // Retrieve hicn fib table + fib_index = + fib_table_find_or_create_and_lock (prefix->fp_proto, 0, hicn_fib_src); -/* - * Node function for the icn packet-generator server. - */ -static uword -hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node, - vlib_frame_t *frame) -{ - u32 n_left_from, *from, *to_next; - icnpg_server_next_t next_index; - u32 pkts_processed = 0, pkts_dropped = 0; - u32 bi0, bi1; - vlib_buffer_t *b0, *b1; - u8 pkt_type0 = 0, pkt_type1 = 0; - u16 msg_type0 = 0, msg_type1 = 0; - hicn_header_t *hicn0 = NULL, *hicn1 = NULL; - hicn_name_t name0, name1; - u16 namelen0, namelen1; + // Check the prefix we are adding is not already in the table + fib_entry_index = fib_table_lookup_exact_match (fib_index, prefix); - hicnpg_server_main_t *hpgsm = &hicnpg_server_main; - - from = vlib_frame_vector_args (frame); - - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) + if (fib_entry_index != FIB_NODE_INDEX_INVALID) { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from >= 4 && n_left_to_next >= 2) - { - u32 next0 = HICNPG_SERVER_NEXT_DROP; - u32 next1 = HICNPG_SERVER_NEXT_DROP; - u8 isv6_0 = 0; - u8 isv6_1 = 0; - u32 sw_if_index0, sw_if_index1; - - /* Prefetch next iteration. */ - { - vlib_buffer_t *p2, *p3; - - p2 = vlib_get_buffer (vm, from[2]); - p3 = vlib_get_buffer (vm, from[3]); - - vlib_prefetch_buffer_header (p2, LOAD); - vlib_prefetch_buffer_header (p3, LOAD); - - CLIB_PREFETCH (p2->data, (2 * CLIB_CACHE_LINE_BYTES), STORE); - CLIB_PREFETCH (p3->data, (2 * CLIB_CACHE_LINE_BYTES), STORE); - } - - /* - * speculatively enqueue b0 and b1 to the current - * next frame - */ - to_next[0] = bi0 = from[0]; - to_next[1] = bi1 = from[1]; - from += 2; - to_next += 2; - n_left_from -= 2; - n_left_to_next -= 2; - - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; - - vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0; - vnet_buffer (b1)->sw_if_index[VLIB_TX] = ~0; - - u32 match0 = match_interest (b0, hpgsm->pgen_srv_hicn_name); - u32 match1 = match_interest (b1, hpgsm->pgen_srv_hicn_name); - - if (match0) - { - next0 = match0 - 1; - } - else if (hicn_interest_parse_pkt (b0, &name0, &namelen0, &hicn0, - &isv6_0) == HICN_ERROR_NONE) - { - /* this node grabs only interests */ - vlib_buffer_t *rb = NULL; - rb = vlib_get_buffer (vm, hpgsm->pgen_svr_buffer_idx); - - isv6_0 ? convert_interest_to_data_v6 (vm, b0, rb, bi0) : - convert_interest_to_data_v4 (vm, b0, rb, bi0); - - next0 = isv6_0 ? HICNPG_SERVER_NEXT_V6_LOOKUP : - HICNPG_SERVER_NEXT_V4_LOOKUP; - } - - if (match1) - { - next1 = match1 - 1; - } - else if (hicn_interest_parse_pkt (b1, &name1, &namelen1, &hicn1, - &isv6_1) == HICN_ERROR_NONE) - { - /* this node grabs only interests */ - vlib_buffer_t *rb = NULL; - rb = vlib_get_buffer (vm, hpgsm->pgen_svr_buffer_idx); - - isv6_1 ? convert_interest_to_data_v6 (vm, b1, rb, bi1) : - convert_interest_to_data_v4 (vm, b1, rb, bi1); - - next1 = isv6_1 ? HICNPG_SERVER_NEXT_V6_LOOKUP : - HICNPG_SERVER_NEXT_V4_LOOKUP; - } - pkts_processed += 2; - - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE))) - { - if (b0->flags & VLIB_BUFFER_IS_TRACED) - { - hicnpg_server_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = pkt_type0; - t->msg_type = msg_type0; - t->sw_if_index = sw_if_index0; - t->next_index = next0; - } - if (b1->flags & VLIB_BUFFER_IS_TRACED) - { - hicnpg_server_trace_t *t = - vlib_add_trace (vm, node, b1, sizeof (*t)); - t->pkt_type = pkt_type1; - t->msg_type = msg_type1; - t->sw_if_index = sw_if_index1; - t->next_index = next1; - } - } - if (next0 == HICNPG_SERVER_NEXT_DROP) - { - pkts_dropped++; - } - if (next1 == HICNPG_SERVER_NEXT_DROP) - { - pkts_dropped++; - } - /* - * verify speculative enqueues, maybe switch current - * next frame - */ - vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, - n_left_to_next, bi0, bi1, next0, - next1); - } - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 next0 = HICNPG_SERVER_NEXT_DROP; - u32 sw_if_index0 = ~0; - u8 isv6_0 = 0; - - /* speculatively enqueue b0 to the current next frame */ - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0; - - u32 match0 = match_interest (b0, hpgsm->pgen_srv_hicn_name); - - if (match0) - { - next0 = match0 - 1; - } - else if (hicn_interest_parse_pkt (b0, &name0, &namelen0, &hicn0, - &isv6_0) == HICN_ERROR_NONE) - { - /* this node grabs only interests */ - vlib_buffer_t *rb = NULL; - rb = vlib_get_buffer (vm, hpgsm->pgen_svr_buffer_idx); - - isv6_0 ? convert_interest_to_data_v6 (vm, b0, rb, bi0) : - convert_interest_to_data_v4 (vm, b0, rb, bi0); - - next0 = isv6_0 ? HICNPG_SERVER_NEXT_V6_LOOKUP : - HICNPG_SERVER_NEXT_V4_LOOKUP; - } - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - hicnpg_server_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = pkt_type0; - t->msg_type = msg_type0; - t->sw_if_index = sw_if_index0; - t->next_index = next0; - } - pkts_processed += 1; - - if (next0 == HICNPG_SERVER_NEXT_DROP) - { - pkts_dropped++; - } - /* - * verify speculative enqueue, maybe switch current - * next 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); + // Route already existing. + return clib_error_return (0, "Route exist already."); } - vlib_node_increment_counter (vm, hicn_pg_server_node.index, - HICNPG_SERVER_ERROR_PROCESSED, pkts_processed); - vlib_node_increment_counter (vm, hicn_pg_server_node.index, - HICNPG_SERVER_ERROR_DROPPED, pkts_dropped); - - return (frame->n_vectors); -} - -void -convert_interest_to_data_v4 (vlib_main_t *vm, vlib_buffer_t *b0, - vlib_buffer_t *rb, u32 bi0) -{ - hicn_header_t *h0 = vlib_buffer_get_current (b0); - - /* Get the packet length */ - u16 pkt_len = clib_net_to_host_u16 (h0->v4.ip.len); + // Allocate packet buffer + int n_buf = vlib_buffer_alloc (vlib_get_main (), &buffer_index, 1); - /* - * Rule of thumb: We want the size of the IP packet to be <= 1500 bytes - */ - u16 bytes_to_copy = rb->current_length; - if ((bytes_to_copy + pkt_len) > 1500) + if (n_buf == 0) { - bytes_to_copy = 1500 - pkt_len; + return clib_error_return (0, "Impossible to allocate paylod buffer."); } - /* Add content to the data packet */ - vlib_buffer_add_data (vm, &bi0, rb->data, bytes_to_copy); - b0 = vlib_get_buffer (vm, bi0); - - h0 = vlib_buffer_get_current (b0); - - ip4_address_t src_addr = h0->v4.ip.saddr; - h0->v4.ip.saddr = h0->v4.ip.daddr; - h0->v4.ip.daddr = src_addr; - - h0->v4.ip.len = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); - h0->v4.ip.csum = ip4_header_checksum ((ip4_header_t *) &(h0->v4.ip)); - calculate_tcp_checksum_v4 (vm, b0); + // Initialize the buffer data with zeros + rb = vlib_get_buffer (vlib_get_main (), buffer_index); + memset (rb->data, 0, payload_size); + rb->current_length = payload_size; + + // We can proceed. Get a new hicnpg_server_t + pool_get_aligned_zero (hicnpg_server_pool, hpg, 2 * CLIB_CACHE_LINE_BYTES); + hpgi = hpg - hicnpg_server_pool; + + // Set DPO + dpo_set ( + &hpg->dpo, hicnpg_server_dpo_type, + (ip46_address_is_ip4 (&prefix->fp_addr) ? DPO_PROTO_IP4 : DPO_PROTO_IP6), + hpgi); + + // Add the route via the hicnpg_server_dpo_type. In this way packets will + // endup in the hicnpg_server node + CLIB_UNUSED (fib_node_index_t new_fib_node_index) = + fib_table_entry_special_dpo_add ( + fib_index, prefix, hicn_fib_src, + (FIB_ENTRY_FLAG_EXCLUSIVE | FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT), + &hpg->dpo); + +#if 0 + vlib_validate_combined_counter (&(udp_encap_counters), uei); + vlib_zero_combined_counter (&(udp_encap_counters), uei); +#endif + + // Init remaining struct fields + fib_node_init (&hpg->fib_node, hicnpg_server_fib_node_type); + fib_node_lock (&hpg->fib_node); + hpg->fib_index = fib_index; + hpg->prefix = *prefix; + hpg->buffer_index = buffer_index; + hpg->fib_entry_index = fib_entry_index; + hpg->hicn_locator = *locator; + + // track the destination address + // hpg->fib_entry_index = + // fib_entry_track (fib_index, &hpg->prefix, + // hicnpg_server_fib_node_type, hpgi, &hpg->fib_sibling); + // hicnpg_server_restack (hpg); + + HICN_DEBUG ("Calling hicn enable for pg-server face"); + + hicn_face_id_t *vec_faces = NULL; + hicn_route_enable (prefix, &vec_faces); + if (vec_faces != NULL) + vec_free (vec_faces); + + // Return the index of the hicnpg_server_t + *hicnpg_server_index = hpgi; + + return NULL; } -void -convert_interest_to_data_v6 (vlib_main_t *vm, vlib_buffer_t *b0, - vlib_buffer_t *rb, u32 bi0) +clib_error_t * +hicn_pg_init (vlib_main_t *vm) { - hicn_header_t *h0 = vlib_buffer_get_current (b0); - - /* Get the packet length */ - uint16_t pkt_len = - clib_net_to_host_u16 (h0->v6.ip.len) + sizeof (ip6_header_t); + hicnpg_server_fib_node_type = fib_node_register_new_type ( + "hicnpg_server_fib_node", &hicnpg_server_fib_vft); - /* - * Figure out how many bytes we can add to the content - * - * Rule of thumb: We want the size of the IP packet to be <= 1400 bytes - */ - u16 bytes_to_copy = rb->current_length; - if ((bytes_to_copy + pkt_len) > 1500) - { - bytes_to_copy = 1500 - pkt_len; - } - /* Add content to the data packet */ - vlib_buffer_add_data (vm, &bi0, rb->data, bytes_to_copy); + hicnpg_server_dpo_type = + dpo_register_new_type (&hicnpg_server_dpo_vft, hicnpg_server_nodes); - b0 = vlib_get_buffer (vm, bi0); - - h0 = vlib_buffer_get_current (b0); - ip6_address_t src_addr = h0->v6.ip.saddr; - h0->v6.ip.saddr = h0->v6.ip.daddr; - h0->v6.ip.daddr = src_addr; - - h0->v6.ip.len = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) - - sizeof (ip6_header_t)); - h0->v6.tcp.data_offset_and_reserved |= 0x0f; - h0->v6.tcp.urg_ptr = htons (0xffff); - - calculate_tcp_checksum_v6 (vm, b0); + return NULL; } -VLIB_REGISTER_NODE(hicn_pg_server_node) = -{ - .function = hicnpg_node_server_fn, - .name = "hicnpg-server", - .vector_size = sizeof(u32), - .format_trace = format_icnpg_server_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(icnpg_server_error_strings), - .error_strings = icnpg_server_error_strings, - .n_next_nodes = HICNPG_SERVER_N_NEXT, - /* edit / add dispositions here */ - .next_nodes = - { - [HICNPG_SERVER_NEXT_V4_LOOKUP] = "ip4-lookup", - [HICNPG_SERVER_NEXT_V6_LOOKUP] = "ip6-lookup", - [HICNPG_SERVER_NEXT_DROP] = "error-drop", - }, -}; - -VNET_FEATURE_INIT (hicn_pg_server_ip6, static) = { - .arc_name = "ip6-unicast", - .node_name = "hicnpg-server", - .runs_before = VNET_FEATURES ("ip6-inacl"), -}; - -VNET_FEATURE_INIT (hicn_pg_server_ip4, static) = { - .arc_name = "ip4-unicast", - .node_name = "hicnpg-server", - .runs_before = VNET_FEATURES ("ip4-inacl"), -}; - -/* - * End of packet-generator server node - */ - /* * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */ + */ \ No newline at end of file diff --git a/hicn-plugin/src/pg.h b/hicn-plugin/src/pg.h index 7855248e6..deb585714 100644 --- a/hicn-plugin/src/pg.h +++ b/hicn-plugin/src/pg.h @@ -16,6 +16,8 @@ #ifndef __HICN_PG_H__ #define __HICN_PG_H__ +#include + /** * @file pg.h * @@ -57,23 +59,58 @@ */ typedef struct hicnpg_main_s { - u32 index; // used to compute the sequence number - fib_prefix_t *pgen_clt_hicn_name; // hICN name to put in the destiantion - // addess of an interest - u32 - index_ifaces; /* used to mimic interests coming from different consumer */ - u32 n_ifaces; /* The source address will change from interest to interest */ - /* index_ifaces is used to keep a global reference to the iface used */ - /* and it is incremented when we want to change "consumer" */ - /* n_ifaces identifies how many consumers to simulate */ - u32 max_seq_number; // Use to limit the max sequence number - u32 n_flows; // Use to simulate multiple flows (a flow always have the same - // hICN name) - ip46_address_t pgen_clt_src_addr; // Source addess base to use in the - // interest - - u16 interest_lifetime; // Interest lifetime - u32 sw_if; // Interface where to send interest and receives data + /* + * used to compute the sequence number + */ + u32 index; + + /* + * hICN name to put in the destination addess of an interest + */ + fib_prefix_t *pgen_clt_hicn_name; + + /* + * Used to mimic interests coming from different consumer. The source address + * will change from interest to interest index_ifaces is used to keep a + * global reference to the iface used and it is incremented when we want to + * change "consumer" + */ + u32 index_ifaces; + + /* + * n_ifaces identifies how many consumers to simulate + */ + u32 n_ifaces; + + /* + * Use to limit the max sequence number + */ + u32 max_seq_number; + + /* + * Use to simulate multiple flows (a flow always have the same hICN name) + */ + u32 n_flows; + + /* + * Source addess base to use in the interest + */ + ip46_address_t pgen_clt_src_addr; + + /* + * Interest lifetime + */ + u16 interest_lifetime; + + /* + * Interface where to send interest and receives data. + */ + u32 sw_if; + + /* + * Fib node type + */ + fib_node_type_t hicn_fib_node_type; } hicnpg_main_t; extern hicnpg_main_t hicnpg_main; @@ -83,18 +120,75 @@ extern hicnpg_main_t hicnpg_main; * * It stores the configuration and make it availables to the pg server node. */ -typedef struct hicnpg_server_main_s +typedef struct hicnpg_server_s { - u32 node_index; - /* Arbitrary content */ - u32 pgen_svr_buffer_idx; - fib_prefix_t *pgen_srv_hicn_name; -} hicnpg_server_main_t; + /* + * Prefix served by this packet generator server + */ + fib_prefix_t prefix; + + /* + * IP address to put in the destination addess of the data + */ + ip46_address_t hicn_locator; + + /* + * Buffer index + */ + u32 buffer_index; + + /** + * The DPO used to forward to the next node in the VLIB graph + */ + dpo_id_t dpo; -extern hicnpg_server_main_t hicnpg_server_main; + /* + * linkage into the FIB graph + */ + fib_node_t fib_node; + /* + * Tracking information for the IP destination + */ + fib_node_index_t fib_entry_index; + + /* + * The FIB index + */ + index_t fib_index; +} hicnpg_server_t; + +STATIC_ASSERT (sizeof (hicnpg_server_t) <= 2 * CLIB_CACHE_LINE_BYTES, + "hicnpg_server_t is too large"); + +extern hicnpg_server_t hicnpg_server_main; extern vlib_node_registration_t hicn_pg_interest_node; extern vlib_node_registration_t hicn_pg_data_node; +extern dpo_type_t hicnpg_server_dpo_type; + +/** + * Pool of hicnpg_servers + */ +extern hicnpg_server_t *hicnpg_server_pool; + +always_inline hicnpg_server_t * +hicnpg_server_get (index_t hpgi) +{ + return pool_elt_at_index (hicnpg_server_pool, hpgi); +} + +always_inline u8 +dpo_is_pgserver (const dpo_id_t *dpo) +{ + return (dpo->dpoi_type == hicnpg_server_dpo_type); +} + +clib_error_t *hicnpg_server_add_and_lock (fib_prefix_t *prefix, + u32 *hicnpg_server_index, + ip46_address_t *locator, + size_t payload_size); + +clib_error_t *hicn_pg_init (vlib_main_t *vm); #endif // __HICN_PG_H__ diff --git a/hicn-plugin/src/pg_node.c b/hicn-plugin/src/pg_node.c new file mode 100644 index 000000000..3672a6b72 --- /dev/null +++ b/hicn-plugin/src/pg_node.c @@ -0,0 +1,1132 @@ +/* + * Copyright (c) 2021 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: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "hicn.h" +#include "pg.h" +#include "parser.h" +#include "infra.h" + +/* Registration struct for a graph node */ +vlib_node_registration_t hicn_pg_interest_node; +vlib_node_registration_t hicn_pg_data_node; + +/* Stats, which end up called "error" even though they aren't... */ +#define foreach_hicnpg_error \ + _ (PROCESSED, "hICN PG packets processed") \ + _ (DROPPED, "hICN PG packets dropped") \ + _ (INTEREST_MSGS_GENERATED, "hICN PG Interests generated") \ + _ (CONTENT_MSGS_RECEIVED, "hICN PG Content msgs received") + +typedef enum +{ +#define _(sym, str) HICNPG_ERROR_##sym, + foreach_hicnpg_error +#undef _ + HICNPG_N_ERROR, +} hicnpg_error_t; + +static char *hicnpg_error_strings[] = { +#define _(sym, string) string, + foreach_hicnpg_error +#undef _ +}; + +/* + * Next graph nodes, which reference the list in the actual registration + * block below + */ +typedef enum +{ + HICNPG_INTEREST_NEXT_V4_LOOKUP, + HICNPG_INTEREST_NEXT_V6_LOOKUP, + HICNPG_INTEREST_NEXT_DROP, + HICNPG_N_NEXT, +} hicnpg_interest_next_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + u16 msg_type; +} hicnpg_trace_t; + +/* packet trace format function */ +static u8 * +format_hicnpg_trace (u8 *s, va_list *args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + hicnpg_trace_t *t = va_arg (*args, hicnpg_trace_t *); + + s = format (s, "HICNPG: pkt: %d, msg %d, sw_if_index %d, next index %d", + (int) t->pkt_type, (int) t->msg_type, t->sw_if_index, + t->next_index); + return (s); +} + +always_inline void hicn_rewrite_interestv4 (vlib_main_t *vm, vlib_buffer_t *b0, + u32 seq_number, u16 lifetime, + u32 next_flow, u32 iface); + +always_inline void hicn_rewrite_interestv6 (vlib_main_t *vm, vlib_buffer_t *b0, + u32 seq_number, u16 lifetime, + u32 next_flow, u32 iface); + +always_inline void convert_interest_to_data_v4 (vlib_main_t *vm, + vlib_buffer_t *b0, + vlib_buffer_t *rb, u32 bi0); + +always_inline void convert_interest_to_data_v6 (vlib_main_t *vm, + vlib_buffer_t *b0, + vlib_buffer_t *rb, u32 bi0); + +always_inline void calculate_tcp_checksum_v4 (vlib_main_t *vm, + vlib_buffer_t *b0); + +always_inline void calculate_tcp_checksum_v6 (vlib_main_t *vm, + vlib_buffer_t *b0); +/* + * Node function for the icn packet-generator client. The goal here is to + * manipulate/tweak a stream of packets that have been injected by the vpp + * packet generator to generate icn request traffic. + */ +static uword +hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + u32 n_left_from, *from, *to_next; + hicnpg_interest_next_t next_index; + u32 pkts_processed = 0, pkts_dropped = 0; + u32 interest_msgs_generated = 0; + u32 bi0, bi1; + vlib_buffer_t *b0, *b1; + u8 pkt_type0 = 0, pkt_type1 = 0; + u16 msg_type0 = 0, msg_type1 = 0; + hicnpg_main_t *hpgm = &hicnpg_main; + int iface = 0; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + 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 >= 4 && n_left_to_next >= 2) + { + u32 next0 = HICNPG_INTEREST_NEXT_DROP; + u32 next1 = HICNPG_INTEREST_NEXT_DROP; + u32 sw_if_index0 = ~0, sw_if_index1 = ~0; + u8 isv6_0; + u8 isv6_1; + + /* Prefetch next iteration. */ + { + vlib_buffer_t *p2, *p3; + + p2 = vlib_get_buffer (vm, from[2]); + p3 = vlib_get_buffer (vm, from[3]); + + vlib_prefetch_buffer_header (p2, LOAD); + vlib_prefetch_buffer_header (p3, LOAD); + + CLIB_PREFETCH (p2->data, (2 * CLIB_CACHE_LINE_BYTES), STORE); + CLIB_PREFETCH (p3->data, (2 * CLIB_CACHE_LINE_BYTES), STORE); + } + + /* + * speculatively enqueue b0 and b1 to the current + * next frame + */ + to_next[0] = bi0 = from[0]; + to_next[1] = bi1 = from[1]; + from += 2; + to_next += 2; + n_left_from -= 2; + n_left_to_next -= 2; + + b0 = vlib_get_buffer (vm, bi0); + b1 = vlib_get_buffer (vm, bi1); + + hicn_buffer_set_flags (b0, HICN_BUFFER_FLAGS_FROM_PG); + hicn_buffer_set_flags (b1, HICN_BUFFER_FLAGS_FROM_PG); + + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; + vnet_buffer (b0)->sw_if_index[VLIB_RX] = hpgm->sw_if; + vnet_buffer (b1)->sw_if_index[VLIB_RX] = hpgm->sw_if; + + /* Check icn packets, locate names */ + if (hicn_interest_parse_pkt (b0) == HICN_ERROR_NONE) + { + /* this node grabs only interests */ + isv6_0 = hicn_buffer_is_v6 (b0); + + /* Increment the appropriate message counter */ + interest_msgs_generated++; + + iface = (hpgm->index_ifaces % hpgm->n_ifaces); + /* Rewrite and send */ + isv6_0 ? + hicn_rewrite_interestv6 ( + vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number, + hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, + iface) : + hicn_rewrite_interestv4 ( + vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number, + hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface); + + hpgm->index_ifaces++; + if (iface == (hpgm->n_ifaces - 1)) + hpgm->index++; + + next0 = isv6_0 ? HICNPG_INTEREST_NEXT_V6_LOOKUP : + HICNPG_INTEREST_NEXT_V4_LOOKUP; + } + if (hicn_interest_parse_pkt (b1) == HICN_ERROR_NONE) + { + /* this node grabs only interests */ + isv6_1 = hicn_buffer_is_v6 (b1); + + /* Increment the appropriate message counter */ + interest_msgs_generated++; + + iface = (hpgm->index_ifaces % hpgm->n_ifaces); + /* Rewrite and send */ + isv6_1 ? + hicn_rewrite_interestv6 ( + vm, b1, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number, + hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, + iface) : + hicn_rewrite_interestv4 ( + vm, b1, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number, + hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface); + + hpgm->index_ifaces++; + if (iface == (hpgm->n_ifaces - 1)) + hpgm->index++; + + next1 = isv6_1 ? HICNPG_INTEREST_NEXT_V6_LOOKUP : + HICNPG_INTEREST_NEXT_V4_LOOKUP; + } + /* Send pkt to next node */ + vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0; + vnet_buffer (b1)->sw_if_index[VLIB_TX] = ~0; + + pkts_processed += 2; + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE))) + { + if (b0->flags & VLIB_BUFFER_IS_TRACED) + { + hicnpg_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = pkt_type0; + t->msg_type = msg_type0; + t->sw_if_index = sw_if_index0; + t->next_index = next0; + } + if (b1->flags & VLIB_BUFFER_IS_TRACED) + { + hicnpg_trace_t *t = + vlib_add_trace (vm, node, b1, sizeof (*t)); + t->pkt_type = pkt_type1; + t->msg_type = msg_type1; + t->sw_if_index = sw_if_index1; + t->next_index = next1; + } + } + if (next0 == HICNPG_INTEREST_NEXT_DROP) + { + pkts_dropped++; + } + if (next1 == HICNPG_INTEREST_NEXT_DROP) + { + pkts_dropped++; + } + /* + * verify speculative enqueues, maybe switch current + * next frame + */ + vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, + n_left_to_next, bi0, bi1, next0, + next1); + } + + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 next0 = HICNPG_INTEREST_NEXT_DROP; + u32 sw_if_index0; + u8 isv6_0; + + /* speculatively enqueue b0 to the current next frame */ + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + hicn_buffer_set_flags (b0, HICN_BUFFER_FLAGS_FROM_PG); + + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + vnet_buffer (b0)->sw_if_index[VLIB_RX] = hpgm->sw_if; + + /* Check icn packets, locate names */ + if (hicn_interest_parse_pkt (b0) == HICN_ERROR_NONE) + { + /* this node grabs only interests */ + isv6_0 = hicn_buffer_is_v6 (b0); + + /* Increment the appropriate message counter */ + interest_msgs_generated++; + + iface = (hpgm->index_ifaces % hpgm->n_ifaces); + + /* Rewrite and send */ + isv6_0 ? + hicn_rewrite_interestv6 ( + vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number, + hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, + iface) : + hicn_rewrite_interestv4 ( + vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number, + hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface); + + hpgm->index_ifaces++; + if (iface == (hpgm->n_ifaces - 1)) + hpgm->index++; + + next0 = isv6_0 ? HICNPG_INTEREST_NEXT_V6_LOOKUP : + HICNPG_INTEREST_NEXT_V4_LOOKUP; + } + /* Send pkt to ip lookup */ + vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0; + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicnpg_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = pkt_type0; + t->msg_type = msg_type0; + t->sw_if_index = sw_if_index0; + t->next_index = next0; + } + pkts_processed += 1; + + if (next0 == HICNPG_INTEREST_NEXT_DROP) + { + pkts_dropped++; + } + /* + * verify speculative enqueue, maybe switch current + * next 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); + } + + vlib_node_increment_counter (vm, hicn_pg_interest_node.index, + HICNPG_ERROR_PROCESSED, pkts_processed); + vlib_node_increment_counter (vm, hicn_pg_interest_node.index, + HICNPG_ERROR_DROPPED, pkts_dropped); + vlib_node_increment_counter (vm, hicn_pg_interest_node.index, + HICNPG_ERROR_INTEREST_MSGS_GENERATED, + interest_msgs_generated); + + return (frame->n_vectors); +} + +void +hicn_rewrite_interestv4 (vlib_main_t *vm, vlib_buffer_t *b0, u32 seq_number, + u16 interest_lifetime, u32 next_flow, u32 iface) +{ + hicn_header_t *h0 = vlib_buffer_get_current (b0); + + /* Generate the right src and dst corresponding to flow and iface */ + ip46_address_t src_addr = { + .ip4 = hicnpg_main.pgen_clt_src_addr.ip4, + }; + hicn_name_t dst_name = { + .prefix.ip4 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip4, + .suffix = seq_number, + }; + + src_addr.ip4.as_u32 += clib_host_to_net_u32 (iface); + dst_name.prefix.ip4.as_u32 += clib_net_to_host_u32 (next_flow); + + /* Update locator and name */ + hicn_type_t type = hicn_get_buffer (b0)->type; + HICN_OPS4->set_interest_locator (type, &h0->protocol, &src_addr); + HICN_OPS4->set_interest_name (type, &h0->protocol, &dst_name); + + /* Update lifetime (currently L4 checksum is not updated) */ + HICN_OPS4->set_lifetime (type, &h0->protocol, interest_lifetime); + + /* Update checksums */ + HICN_OPS4->update_checksums (type, &h0->protocol, 0, 0); +} + +/** + * @brief Rewrite the IPv6 header as the next generated packet + * + * Set up a name prefix + * - etiher generate interest in which the name varies only after the prefix + * (inc : seq_number), then the flow acts on the prefix (CHECK) + * seq_number => TCP, FLOW => + * + * SRC : pgen_clt_src_addr.ip6 DST = generate name (pgen_clt_hicn_name.ip6) + * ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff + * \__/ \__/ + * +iface + flow + * Source is used to emulate different consumers. + * FIXME iface is ill-named, better name it consumer id + * Destination is used to iterate on the content. + */ +void +hicn_rewrite_interestv6 (vlib_main_t *vm, vlib_buffer_t *b0, u32 seq_number, + u16 interest_lifetime, u32 next_flow, u32 iface) +{ + hicn_header_t *h0 = vlib_buffer_get_current (b0); + + /* Generate the right src and dst corresponding to flow and iface */ + ip46_address_t src_addr = { + .ip6 = hicnpg_main.pgen_clt_src_addr.ip6, + }; + hicn_name_t dst_name = { + .prefix.ip6 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip6, + .suffix = seq_number, + }; + src_addr.ip6.as_u32[3] += clib_host_to_net_u32 (iface); + dst_name.prefix.ip6.as_u32[3] += clib_net_to_host_u32 (next_flow); + + /* Update locator and name */ + hicn_type_t type = hicn_get_buffer (b0)->type; + HICN_OPS6->set_interest_locator (type, &h0->protocol, &src_addr); + HICN_OPS6->set_interest_name (type, &h0->protocol, &dst_name); + + /* Update lifetime */ + HICN_OPS6->set_lifetime (type, &h0->protocol, interest_lifetime); + + /* Update checksums */ + calculate_tcp_checksum_v6 (vm, b0); +} + +void +calculate_tcp_checksum_v4 (vlib_main_t *vm, vlib_buffer_t *b0) +{ + ip4_header_t *ip0; + tcp_header_t *tcp0; + ip_csum_t sum0; + u32 tcp_len0; + + ip0 = (ip4_header_t *) (vlib_buffer_get_current (b0)); + tcp0 = + (tcp_header_t *) (vlib_buffer_get_current (b0) + sizeof (ip4_header_t)); + tcp_len0 = clib_net_to_host_u16 (ip0->length) - sizeof (ip4_header_t); + + /* Initialize checksum with header. */ + if (BITS (sum0) == 32) + { + sum0 = clib_mem_unaligned (&ip0->src_address, u32); + sum0 = + ip_csum_with_carry (sum0, clib_mem_unaligned (&ip0->dst_address, u32)); + } + else + sum0 = clib_mem_unaligned (&ip0->src_address, u64); + + sum0 = ip_csum_with_carry ( + sum0, clib_host_to_net_u32 (tcp_len0 + (ip0->protocol << 16))); + + /* Invalidate possibly old checksum. */ + tcp0->checksum = 0; + + u32 tcp_offset = sizeof (ip4_header_t); + sum0 = ip_incremental_checksum_buffer (vm, b0, tcp_offset, tcp_len0, sum0); + + tcp0->checksum = ~ip_csum_fold (sum0); +} + +void +calculate_tcp_checksum_v6 (vlib_main_t *vm, vlib_buffer_t *b0) +{ + ip6_header_t *ip0; + tcp_header_t *tcp0; + ip_csum_t sum0; + u32 tcp_len0; + + ip0 = (ip6_header_t *) (vlib_buffer_get_current (b0)); + tcp0 = + (tcp_header_t *) (vlib_buffer_get_current (b0) + sizeof (ip6_header_t)); + tcp_len0 = clib_net_to_host_u16 (ip0->payload_length); + + /* Initialize checksum with header. */ + if (BITS (sum0) == 32) + { + sum0 = clib_mem_unaligned (&ip0->src_address, u32); + sum0 = + ip_csum_with_carry (sum0, clib_mem_unaligned (&ip0->dst_address, u32)); + } + else + sum0 = clib_mem_unaligned (&ip0->src_address, u64); + + sum0 = ip_csum_with_carry ( + sum0, clib_host_to_net_u32 (tcp_len0 + (ip0->protocol << 16))); + + /* Invalidate possibly old checksum. */ + tcp0->checksum = 0; + + u32 tcp_offset = sizeof (ip6_header_t); + sum0 = ip_incremental_checksum_buffer (vm, b0, tcp_offset, tcp_len0, sum0); + + tcp0->checksum = ~ip_csum_fold (sum0); +} + +VLIB_REGISTER_NODE (hicn_pg_interest_node) = { + .function = hicnpg_client_interest_node_fn, + .name = "hicnpg-interest", + .vector_size = sizeof (u32), + .format_trace = format_hicnpg_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN (hicnpg_error_strings), + .error_strings = hicnpg_error_strings, + .n_next_nodes = HICNPG_N_NEXT, + .next_nodes = { [HICNPG_INTEREST_NEXT_V4_LOOKUP] = "ip4-lookup", + [HICNPG_INTEREST_NEXT_V6_LOOKUP] = "ip6-lookup", + [HICNPG_INTEREST_NEXT_DROP] = "error-drop" }, +}; + +/* + * Next graph nodes, which reference the list in the actual registration + * block below + */ +typedef enum +{ + HICNPG_DATA_NEXT_DROP, + HICNPG_DATA_NEXT_LOOKUP4, + HICNPG_DATA_NEXT_LOOKUP6, + HICNPG_DATA_N_NEXT, +} hicnpg_data_next_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + u16 msg_type; +} icnpg_data_trace_t; + +/* packet trace format function */ +static u8 * +format_hicnpg_data_trace (u8 *s, va_list *args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + hicnpg_trace_t *t = va_arg (*args, hicnpg_trace_t *); + + s = format (s, "HICNPG: pkt: %d, msg %d, sw_if_index %d, next index %d", + (int) t->pkt_type, (int) t->msg_type, t->sw_if_index, + t->next_index); + return (s); +} + +/* + * Node function for the icn packet-generator client. The goal here is to + * manipulate/tweak a stream of packets that have been injected by the vpp + * packet generator to generate icn request traffic. + */ +static uword +hicnpg_client_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + u32 n_left_from, *from, *to_next; + hicnpg_data_next_t next_index; + u32 pkts_processed = 0; + u32 content_msgs_received = 0; + u32 bi0, bi1; + vlib_buffer_t *b0, *b1; + u8 pkt_type0 = 0, pkt_type1 = 0; + u16 msg_type0 = 1, msg_type1 = 1; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + 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 >= 4 && n_left_to_next >= 2) + { + u32 next0 = HICNPG_DATA_NEXT_DROP; + u32 next1 = HICNPG_DATA_NEXT_DROP; + u32 sw_if_index0, sw_if_index1; + + /* Prefetch next iteration. */ + { + vlib_buffer_t *p2, *p3; + + p2 = vlib_get_buffer (vm, from[2]); + p3 = vlib_get_buffer (vm, from[3]); + + vlib_prefetch_buffer_header (p2, LOAD); + vlib_prefetch_buffer_header (p3, LOAD); + + CLIB_PREFETCH (p2->data, (2 * CLIB_CACHE_LINE_BYTES), STORE); + CLIB_PREFETCH (p3->data, (2 * CLIB_CACHE_LINE_BYTES), STORE); + } + + /* + * speculatively enqueue b0 and b1 to the current + * next frame + */ + to_next[0] = bi0 = from[0]; + to_next[1] = bi1 = from[1]; + from += 2; + to_next += 2; + n_left_from -= 2; + n_left_to_next -= 2; + + b0 = vlib_get_buffer (vm, bi0); + b1 = vlib_get_buffer (vm, bi1); + + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; + + next0 = HICNPG_DATA_NEXT_DROP; + next1 = HICNPG_DATA_NEXT_DROP; + + // Increment counter + content_msgs_received += 2; + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE))) + { + if (b0->flags & VLIB_BUFFER_IS_TRACED) + { + icnpg_data_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = pkt_type0; + t->msg_type = msg_type0; + t->sw_if_index = sw_if_index0; + t->next_index = next0; + } + if (b1->flags & VLIB_BUFFER_IS_TRACED) + { + icnpg_data_trace_t *t = + vlib_add_trace (vm, node, b1, sizeof (*t)); + t->pkt_type = pkt_type1; + t->msg_type = msg_type1; + t->sw_if_index = sw_if_index1; + t->next_index = next1; + } + } + + vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, + n_left_to_next, bi0, bi1, next0, + next1); + pkts_processed += 2; + } + + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 next0 = HICNPG_DATA_NEXT_DROP; + u32 sw_if_index0; + + /* speculatively enqueue b0 to the current next frame */ + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + + next0 = HICNPG_DATA_NEXT_DROP; + + // Increment a counter + content_msgs_received += 1; + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b0->flags & VLIB_BUFFER_IS_TRACED))) + { + icnpg_data_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = pkt_type0; + t->msg_type = msg_type0; + t->sw_if_index = sw_if_index0; + t->next_index = next0; + } + + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, + n_left_to_next, bi0, next0); + + pkts_processed++; + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, hicn_pg_data_node.index, + HICNPG_ERROR_PROCESSED, pkts_processed); + vlib_node_increment_counter (vm, hicn_pg_data_node.index, + HICNPG_ERROR_CONTENT_MSGS_RECEIVED, + content_msgs_received); + return (frame->n_vectors); +} + +VLIB_REGISTER_NODE(hicn_pg_data_node) = +{ + .function = hicnpg_client_data_node_fn, + .name = "hicnpg-data", + .vector_size = sizeof(u32), + .format_trace = format_hicnpg_data_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(hicnpg_error_strings), + .error_strings = hicnpg_error_strings, + .n_next_nodes = HICNPG_DATA_N_NEXT, + .next_nodes = + { + [HICNPG_DATA_NEXT_DROP] = "error-drop", + [HICNPG_DATA_NEXT_LOOKUP4] = "ip4-lookup", + [HICNPG_DATA_NEXT_LOOKUP6] = "ip6-lookup", + }, +}; + +VNET_FEATURE_INIT (hicn_data_input_ip4_arc, static) = { + .arc_name = "ip4-unicast", + .node_name = "hicnpg-data", + .runs_before = VNET_FEATURES ("ip4-inacl"), +}; + +VNET_FEATURE_INIT (hicn_data_input_ip6_arc, static) = { + .arc_name = "ip6-unicast", + .node_name = "hicnpg-data", + .runs_before = VNET_FEATURES ("ip6-inacl"), +}; + +/* + * End of packet-generator client node + */ + +/* + * Beginning of packet-generation server node + */ + +/* Registration struct for a graph node */ +vlib_node_registration_t hicn_pg_server_node; + +/* Stats, which end up called "error" even though they aren't... */ +#define foreach_icnpg_server_error \ + _ (PROCESSED, "hICN PG Server packets processed") \ + _ (DROPPED, "hICN PG Server packets dropped") + +typedef enum +{ +#define _(sym, str) HICNPG_SERVER_ERROR_##sym, + foreach_icnpg_server_error +#undef _ + HICNPG_SERVER_N_ERROR, +} icnpg_server_error_t; + +static char *icnpg_server_error_strings[] = { +#define _(sym, string) string, + foreach_icnpg_server_error +#undef _ +}; + +/* + * Next graph nodes, which reference the list in the actual registration + * block below + */ +typedef enum +{ + HICNPG_SERVER_NEXT_V4_LOOKUP, + HICNPG_SERVER_NEXT_V6_LOOKUP, + HICNPG_SERVER_NEXT_DROP, + HICNPG_SERVER_N_NEXT, +} icnpg_server_next_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + u16 msg_type; +} hicnpg_server_trace_t; + +/* packet trace format function */ +static u8 * +format_icnpg_server_trace (u8 *s, va_list *args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + hicnpg_server_trace_t *t = va_arg (*args, hicnpg_server_trace_t *); + + s = format ( + s, "HICNPG SERVER: pkt: %d, msg %d, sw_if_index %d, next index %d", + (int) t->pkt_type, (int) t->msg_type, t->sw_if_index, t->next_index); + return (s); +} + +/* + * Node function for the icn packet-generator server. + */ +static uword +hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame, int isv6) +{ + u32 n_left_from, *from, *to_next; + icnpg_server_next_t next_index; + u32 pkts_processed = 0, pkts_dropped = 0; + u32 bi0, bi1; + vlib_buffer_t *b0, *b1; + u8 pkt_type0 = 0, pkt_type1 = 0; + u16 msg_type0 = 0, msg_type1 = 0; + + from = vlib_frame_vector_args (frame); + + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + 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 >= 4 && n_left_to_next >= 2) + { + u32 next0 = HICNPG_SERVER_NEXT_DROP; + u32 next1 = HICNPG_SERVER_NEXT_DROP; + u32 sw_if_index0, sw_if_index1; + u32 hpgi0, hpgi1; + hicnpg_server_t *hpg0, *hpg1; + + /* Prefetch next iteration. */ + { + vlib_buffer_t *p2, *p3; + + p2 = vlib_get_buffer (vm, from[2]); + p3 = vlib_get_buffer (vm, from[3]); + + vlib_prefetch_buffer_header (p2, LOAD); + vlib_prefetch_buffer_header (p3, LOAD); + + CLIB_PREFETCH (p2->data, (2 * CLIB_CACHE_LINE_BYTES), STORE); + CLIB_PREFETCH (p3->data, (2 * CLIB_CACHE_LINE_BYTES), STORE); + } + + /* + * speculatively enqueue b0 and b1 to the current + * next frame + */ + to_next[0] = bi0 = from[0]; + to_next[1] = bi1 = from[1]; + from += 2; + to_next += 2; + n_left_from -= 2; + n_left_to_next -= 2; + + b0 = vlib_get_buffer (vm, bi0); + b1 = vlib_get_buffer (vm, bi1); + + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; + + vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0; + vnet_buffer (b1)->sw_if_index[VLIB_TX] = ~0; + + hpgi0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; + hpgi1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX]; + + hpg0 = hicnpg_server_get (hpgi0); + hpg1 = hicnpg_server_get (hpgi1); + + if (hicn_interest_parse_pkt (b0) == HICN_ERROR_NONE) + { + vlib_buffer_t *rb = NULL; + rb = vlib_get_buffer (vm, hpg0->buffer_index); + + isv6 ? convert_interest_to_data_v6 (vm, b0, rb, bi0) : + convert_interest_to_data_v4 (vm, b0, rb, bi0); + + next0 = isv6 ? HICNPG_SERVER_NEXT_V6_LOOKUP : + HICNPG_SERVER_NEXT_V4_LOOKUP; + } + + if (hicn_interest_parse_pkt (b1) == HICN_ERROR_NONE) + { + vlib_buffer_t *rb = NULL; + rb = vlib_get_buffer (vm, hpg1->buffer_index); + + isv6 ? convert_interest_to_data_v6 (vm, b1, rb, bi1) : + convert_interest_to_data_v4 (vm, b1, rb, bi1); + + next1 = isv6 ? HICNPG_SERVER_NEXT_V6_LOOKUP : + HICNPG_SERVER_NEXT_V4_LOOKUP; + } + pkts_processed += 2; + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE))) + { + if (b0->flags & VLIB_BUFFER_IS_TRACED) + { + hicnpg_server_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = pkt_type0; + t->msg_type = msg_type0; + t->sw_if_index = sw_if_index0; + t->next_index = next0; + } + if (b1->flags & VLIB_BUFFER_IS_TRACED) + { + hicnpg_server_trace_t *t = + vlib_add_trace (vm, node, b1, sizeof (*t)); + t->pkt_type = pkt_type1; + t->msg_type = msg_type1; + t->sw_if_index = sw_if_index1; + t->next_index = next1; + } + } + if (next0 == HICNPG_SERVER_NEXT_DROP) + { + pkts_dropped++; + } + if (next1 == HICNPG_SERVER_NEXT_DROP) + { + pkts_dropped++; + } + /* + * verify speculative enqueues, maybe switch current + * next frame + */ + vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, + n_left_to_next, bi0, bi1, next0, + next1); + } + + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 next0 = HICNPG_SERVER_NEXT_DROP; + u32 sw_if_index0 = ~0; + u32 hpgi0; + hicnpg_server_t *hpg0; + + /* speculatively enqueue b0 to the current next frame */ + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0; + + hpgi0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; + hpg0 = hicnpg_server_get (hpgi0); + + if (hicn_interest_parse_pkt (b0) == HICN_ERROR_NONE) + { + /* this node grabs only interests */ + vlib_buffer_t *rb = NULL; + rb = vlib_get_buffer (vm, hpg0->buffer_index); + + isv6 ? convert_interest_to_data_v6 (vm, b0, rb, bi0) : + convert_interest_to_data_v4 (vm, b0, rb, bi0); + + next0 = isv6 ? HICNPG_SERVER_NEXT_V6_LOOKUP : + HICNPG_SERVER_NEXT_V4_LOOKUP; + } + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicnpg_server_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = pkt_type0; + t->msg_type = msg_type0; + t->sw_if_index = sw_if_index0; + t->next_index = next0; + } + pkts_processed += 1; + + if (next0 == HICNPG_SERVER_NEXT_DROP) + { + pkts_dropped++; + } + /* + * verify speculative enqueue, maybe switch current + * next 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); + } + + vlib_node_increment_counter (vm, hicn_pg_server_node.index, + HICNPG_SERVER_ERROR_PROCESSED, pkts_processed); + vlib_node_increment_counter (vm, hicn_pg_server_node.index, + HICNPG_SERVER_ERROR_DROPPED, pkts_dropped); + + return (frame->n_vectors); +} + +void +convert_interest_to_data_v4 (vlib_main_t *vm, vlib_buffer_t *b0, + vlib_buffer_t *rb, u32 bi0) +{ + hicn_header_t *h0 = vlib_buffer_get_current (b0); + + /* Get the packet length */ + u16 pkt_len = clib_net_to_host_u16 (h0->v4.ip.len); + + /* + * Rule of thumb: We want the size of the IP packet to be <= 1500 bytes + */ + u16 bytes_to_copy = rb->current_length; + if ((bytes_to_copy + pkt_len) > 1500) + { + bytes_to_copy = 1500 - pkt_len; + } + /* Add content to the data packet */ + vlib_buffer_add_data (vm, &bi0, rb->data, bytes_to_copy); + + b0 = vlib_get_buffer (vm, bi0); + + h0 = vlib_buffer_get_current (b0); + + ip4_address_t src_addr = h0->v4.ip.saddr; + h0->v4.ip.saddr = h0->v4.ip.daddr; + h0->v4.ip.daddr = src_addr; + + h0->v4.ip.len = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); + h0->v4.ip.csum = ip4_header_checksum ((ip4_header_t *) &(h0->v4.ip)); + calculate_tcp_checksum_v4 (vm, b0); +} + +void +convert_interest_to_data_v6 (vlib_main_t *vm, vlib_buffer_t *b0, + vlib_buffer_t *rb, u32 bi0) +{ + hicn_header_t *h0 = vlib_buffer_get_current (b0); + + /* Get the packet length */ + uint16_t pkt_len = + clib_net_to_host_u16 (h0->v6.ip.len) + sizeof (ip6_header_t); + + /* + * Figure out how many bytes we can add to the content + * + * Rule of thumb: We want the size of the IP packet to be <= 1400 bytes + */ + u16 bytes_to_copy = rb->current_length; + if ((bytes_to_copy + pkt_len) > 1500) + { + bytes_to_copy = 1500 - pkt_len; + } + /* Add content to the data packet */ + vlib_buffer_add_data (vm, &bi0, rb->data, bytes_to_copy); + + b0 = vlib_get_buffer (vm, bi0); + + h0 = vlib_buffer_get_current (b0); + ip6_address_t src_addr = h0->v6.ip.saddr; + h0->v6.ip.saddr = h0->v6.ip.daddr; + h0->v6.ip.daddr = src_addr; + + h0->v6.ip.len = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) - + sizeof (ip6_header_t)); + h0->v6.tcp.data_offset_and_reserved |= 0x0f; + h0->v6.tcp.urg_ptr = htons (0xffff); + + calculate_tcp_checksum_v6 (vm, b0); +} + +VLIB_NODE_FN (hicn_pg_server6_node) +(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) +{ + return hicnpg_node_server_fn (vm, node, frame, 1 /* is_v6 */); +} + +VLIB_NODE_FN (hicn_pg_server4_node) +(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) +{ + return hicnpg_node_server_fn (vm, node, frame, 0 /* is_v6 */); +} + +VLIB_REGISTER_NODE(hicn_pg_server6_node) = +{ + .name = "hicnpg-server-6", + .vector_size = sizeof(u32), + .format_trace = format_icnpg_server_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(icnpg_server_error_strings), + .error_strings = icnpg_server_error_strings, + .n_next_nodes = HICNPG_SERVER_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = + { + [HICNPG_SERVER_NEXT_V4_LOOKUP] = "ip4-lookup", + [HICNPG_SERVER_NEXT_V6_LOOKUP] = "ip6-lookup", + [HICNPG_SERVER_NEXT_DROP] = "error-drop", + }, +}; + +VLIB_REGISTER_NODE(hicn_pg_server4_node) = +{ + .name = "hicnpg-server-4", + .vector_size = sizeof(u32), + .format_trace = format_icnpg_server_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(icnpg_server_error_strings), + .error_strings = icnpg_server_error_strings, + .n_next_nodes = HICNPG_SERVER_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = + { + [HICNPG_SERVER_NEXT_V4_LOOKUP] = "ip4-lookup", + [HICNPG_SERVER_NEXT_V6_LOOKUP] = "ip6-lookup", + [HICNPG_SERVER_NEXT_DROP] = "error-drop", + }, +}; + +/* + * End of packet-generator server node + */ \ No newline at end of file diff --git a/hicn-plugin/src/route.c b/hicn-plugin/src/route.c index a84891b9a..0c96e1412 100644 --- a/hicn-plugin/src/route.c +++ b/hicn-plugin/src/route.c @@ -34,6 +34,7 @@ #include "infra.h" #include "udp_tunnels/udp_tunnel.h" #include "mapme.h" +#include "pg.h" #define FIB_SOURCE_HICN 0x04 // Right after the FIB_SOURCE_INTERFACE priority @@ -234,7 +235,7 @@ sync_hicn_fib_entry (hicn_dpo_ctx_t *fib_entry, hicn_face_id_t **pvec_faces) do \ { \ /* Careful, this adds a lock on the face if it exists */ \ - hicn_face_add (dpo, nh, sw_if, &face_id, 0); \ + hicn_face_add (dpo, nh, sw_if, &face_id); \ vec_validate (vec_faces, index); \ vec_faces[index] = face_id; \ (index)++; \ @@ -294,10 +295,15 @@ sync_hicn_fib_entry (hicn_dpo_ctx_t *fib_entry, hicn_face_id_t **pvec_faces) default: continue; } - HICN_DEBUG ("Added new UDP face: %d because of route prefix %s", + HICN_DEBUG ("Added new UDP face: %d because of route prefix %U", face_id, format_ip_prefix, &_fib_entry->fe_prefix); udp_tunnel_add_existing (dpo->dpoi_index, proto); } + else if (dpo_is_pgserver (dpo)) + { + hicnpg_server_t *pg_server = hicnpg_server_get (dpo->dpoi_index); + ADD_FACE (&pg_server->hicn_locator); + } } const hicn_dpo_vft_t *strategy_vft = hicn_dpo_get_vft (fib_entry->dpo_type); diff --git a/hicn-plugin/src/strategy_node.c b/hicn-plugin/src/strategy_node.c index 66d9c2dbb..3ff2d0209 100644 --- a/hicn-plugin/src/strategy_node.c +++ b/hicn-plugin/src/strategy_node.c @@ -66,7 +66,7 @@ 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, + vl_api_hicn_api_node_stats_get_reply_t *stats, u8 is_replication) { int ret; @@ -81,6 +81,7 @@ hicn_new_interest (hicn_strategy_runtime_t *rt, vlib_buffer_t *b0, u32 *next, u8 hash_entry_id = 0; u8 bucket_is_overflow = 0; u32 bucket_id = ~0; + u8 isv6 = hicn_buffer_is_v6 (b0); if (is_replication) { @@ -202,27 +203,22 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node, 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 outfaces[MAX_OUT_FACES]; u32 outfaces_len; int nh_idx; u32 next0 = next_index; - int ret; /* 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); + CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, LOAD); } /* Dequeue a packet buffer */ bi0 = from[0]; @@ -248,7 +244,8 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node, const hicn_strategy_vft_t *strategy = hicn_dpo_get_strategy_vft (dpo_ctx->dpo_type); - ret = hicn_interest_parse_pkt (b0, &name, &namelen, &hicn0, &isv6); + hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen); + stats.pkts_processed++; /* Select next hop */ /* @@ -256,8 +253,7 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node, * the interest-pcslookup node due to misconfiguration in * the punting rules. */ - if (PREDICT_TRUE (ret == HICN_ERROR_NONE && - HICN_IS_NAMEHASH_CACHED (b0) && + if (PREDICT_TRUE (HICN_IS_NAMEHASH_CACHED (b0) && strategy->hicn_select_next_hop ( vnet_buffer (b0)->ip.adj_index[VLIB_TX], &nh_idx, outfaces, &outfaces_len) == HICN_ERROR_NONE)) @@ -267,7 +263,6 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node, * here. Already checked in the interest_pcslookup * node */ - nameptr = (u8 *) (&name); u32 clones[outfaces_len]; if (outfaces_len > 1) { @@ -295,7 +290,7 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node, rt, local_b0, &next0, tnow, nameptr, namelen, outfaces[nh], nh_idx, vnet_buffer (local_b0)->ip.adj_index[VLIB_TX], - strategy, dpo_ctx->dpo_type, isv6, &stats, 0); + strategy, dpo_ctx->dpo_type, &stats, 0); } else { @@ -304,7 +299,7 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node, rt, local_b0, &next0, tnow, nameptr, namelen, outfaces[nh], nh_idx, vnet_buffer (local_b0)->ip.adj_index[VLIB_TX], - strategy, dpo_ctx->dpo_type, isv6, &stats, 1); + strategy, dpo_ctx->dpo_type, &stats, 1); } /* Maybe trace */ @@ -314,7 +309,7 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node, { hicn_strategy_trace_t *t = vlib_add_trace (vm, node, local_b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; + t->pkt_type = HICN_PACKET_TYPE_DATA; t->sw_if_index = vnet_buffer (local_b0)->sw_if_index[VLIB_RX]; t->next_index = next0; @@ -376,4 +371,4 @@ VLIB_REGISTER_NODE (hicn_strategy_node) = * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */ + */ \ No newline at end of file -- cgit 1.2.3-korg