From 88509fe353767cbde707c3e3b1f29392957819f3 Mon Sep 17 00:00:00 2001 From: Mauro Sardara Date: Tue, 24 Mar 2020 17:34:14 +0000 Subject: [HICN-574] Host stack plugin for VPP. Signed-off-by: Mauro Sardara Change-Id: I8d8fdffef31a7013265d6529c5f52f3d5ec70d18 Signed-off-by: Mauro Sardara Signed-off-by: Mauro Signed-off-by: Mauro Sardara --- hicn-plugin/.vscode/settings.json | 5 + hicn-plugin/CMakeLists.txt | 2 +- .../includes/vpp_plugins/hicn/CMakeLists.txt | 34 + hicn-plugin/includes/vpp_plugins/hicn/error.h | 101 ++ .../includes/vpp_plugins/hicn/hicn_all_api_h.h | 22 + hicn-plugin/includes/vpp_plugins/hicn/hicn_api.h | 38 + .../includes/vpp_plugins/hicn/hicn_msg_enum.h | 39 + hicn-plugin/src/CMakeLists.txt | 423 +++---- hicn-plugin/src/cache_policies/cs_lru.c | 268 ---- hicn-plugin/src/cache_policies/cs_lru.h | 76 -- hicn-plugin/src/cache_policies/cs_policy.h | 96 -- hicn-plugin/src/cli.c | 896 ------------- hicn-plugin/src/data_fwd.h | 214 ---- hicn-plugin/src/data_fwd_node.c | 620 --------- hicn-plugin/src/data_input_node.c | 697 ---------- hicn-plugin/src/data_pcslookup.h | 61 - hicn-plugin/src/data_pcslookup_node.c | 223 ---- hicn-plugin/src/error.c | 28 - hicn-plugin/src/error.h | 101 -- hicn-plugin/src/face_db.h | 151 --- hicn-plugin/src/faces/app/address_mgr.c | 241 ---- hicn-plugin/src/faces/app/address_mgr.h | 76 -- hicn-plugin/src/faces/app/face_app_cli.c | 205 --- hicn-plugin/src/faces/app/face_cons.c | 116 -- hicn-plugin/src/faces/app/face_cons.h | 76 -- hicn-plugin/src/faces/app/face_prod.c | 369 ------ hicn-plugin/src/faces/app/face_prod.h | 106 -- hicn-plugin/src/faces/app/face_prod_node.c | 314 ----- hicn-plugin/src/faces/face.c | 475 ------- hicn-plugin/src/faces/face.h | 798 ------------ hicn-plugin/src/faces/face_cli.c | 194 --- hicn-plugin/src/faces/face_node.c | 940 -------------- hicn-plugin/src/faces/face_node.h | 52 - hicn-plugin/src/faces/iface_node.c | 915 -------------- hicn-plugin/src/faces/iface_node.h | 54 - hicn-plugin/src/hashtb.c | 1017 --------------- hicn-plugin/src/hashtb.h | 546 -------- hicn-plugin/src/hicn.api | 579 --------- hicn-plugin/src/hicn.c | 264 ---- hicn-plugin/src/hicn.h | 115 -- hicn-plugin/src/hicn_all_api_h.h | 22 - hicn-plugin/src/hicn_api.c | 727 ----------- hicn-plugin/src/hicn_api.h | 38 - hicn-plugin/src/hicn_api_test.c | 1319 ------------------- hicn-plugin/src/hicn_buffer.h | 136 ++ hicn-plugin/src/hicn_msg_enum.h | 39 - hicn-plugin/src/hicn_plugin.c | 79 ++ hicn-plugin/src/host_stack/FEATURE.yaml | 9 + hicn-plugin/src/host_stack/README.md | 2 + hicn-plugin/src/host_stack/cbr_proto.c | 101 ++ hicn-plugin/src/host_stack/cli.c | 99 ++ hicn-plugin/src/host_stack/debug.h | 0 hicn-plugin/src/host_stack/error.c | 32 + hicn-plugin/src/host_stack/error.h | 33 + hicn-plugin/src/host_stack/errors/hicn_hs.def | 32 + hicn-plugin/src/host_stack/host_stack.c | 517 ++++++++ hicn-plugin/src/host_stack/host_stack.h | 406 ++++++ hicn-plugin/src/host_stack/inlines.h | 520 ++++++++ hicn-plugin/src/host_stack/input_node.c | 477 +++++++ hicn-plugin/src/host_stack/output_node.c | 287 +++++ hicn-plugin/src/host_stack/producer_dpo.c | 90 ++ hicn-plugin/src/host_stack/producer_dpo.h | 33 + hicn-plugin/src/host_stack/proto.h | 48 + hicn-plugin/src/host_stack/route.c | 178 +++ hicn-plugin/src/host_stack/route.h | 37 + hicn-plugin/src/host_stack/test/hicn_hs_client.c | 804 ++++++++++++ hicn-plugin/src/host_stack/test/hicn_hs_client.h | 127 ++ hicn-plugin/src/host_stack/test/hicn_hs_server.c | 505 ++++++++ hicn-plugin/src/host_stack/testbed/Dockerfile | 46 + .../src/host_stack/testbed/client-startup.txt | 6 + hicn-plugin/src/host_stack/testbed/init.sh | 6 + .../src/host_stack/testbed/run-client-server.sh | 24 + .../src/host_stack/testbed/server-startup.txt | 7 + .../src/host_stack/testbed/startup-client.conf | 188 +++ .../src/host_stack/testbed/startup-server.conf | 189 +++ .../src/host_stack/testbed/test_hicn_hs.txt | 6 + hicn-plugin/src/host_stack/testbed/vcl.conf | 7 + hicn-plugin/src/host_stack/utils.h | 95 ++ hicn-plugin/src/infra.h | 102 -- hicn-plugin/src/interest_hitcs.h | 66 - hicn-plugin/src/interest_hitcs_node.c | 291 ----- hicn-plugin/src/interest_hitpit.h | 68 - hicn-plugin/src/interest_hitpit_node.c | 308 ----- hicn-plugin/src/interest_pcslookup.h | 67 - hicn-plugin/src/interest_pcslookup_node.c | 237 ---- hicn-plugin/src/mapme.h | 365 ------ hicn-plugin/src/mapme_ack.h | 58 - hicn-plugin/src/mapme_ack_node.c | 234 ---- hicn-plugin/src/mapme_ctrl.h | 78 -- hicn-plugin/src/mapme_ctrl_node.c | 337 ----- hicn-plugin/src/mapme_eventmgr.c | 567 --------- hicn-plugin/src/mapme_eventmgr.h | 57 - hicn-plugin/src/mgmt.c | 96 -- hicn-plugin/src/mgmt.h | 127 -- hicn-plugin/src/network/asd | 304 +++++ hicn-plugin/src/network/cache_policies/cs_lru.c | 268 ++++ hicn-plugin/src/network/cache_policies/cs_lru.h | 76 ++ hicn-plugin/src/network/cache_policies/cs_policy.h | 96 ++ hicn-plugin/src/network/cli.c | 897 +++++++++++++ hicn-plugin/src/network/data_fwd.h | 214 ++++ hicn-plugin/src/network/data_fwd_node.c | 620 +++++++++ hicn-plugin/src/network/data_input_node.c | 697 ++++++++++ hicn-plugin/src/network/data_pcslookup.h | 61 + hicn-plugin/src/network/data_pcslookup_node.c | 223 ++++ hicn-plugin/src/network/error.c | 28 + hicn-plugin/src/network/face_db.h | 151 +++ hicn-plugin/src/network/faces/app/address_mgr.c | 242 ++++ hicn-plugin/src/network/faces/app/address_mgr.h | 76 ++ hicn-plugin/src/network/faces/app/face_app_cli.c | 205 +++ hicn-plugin/src/network/faces/app/face_cons.c | 116 ++ hicn-plugin/src/network/faces/app/face_cons.h | 76 ++ hicn-plugin/src/network/faces/app/face_prod.c | 369 ++++++ hicn-plugin/src/network/faces/app/face_prod.h | 106 ++ hicn-plugin/src/network/faces/app/face_prod_node.c | 318 +++++ hicn-plugin/src/network/faces/face.c | 475 +++++++ hicn-plugin/src/network/faces/face.h | 796 ++++++++++++ hicn-plugin/src/network/faces/face_cli.c | 194 +++ hicn-plugin/src/network/faces/face_node.c | 940 ++++++++++++++ hicn-plugin/src/network/faces/face_node.h | 52 + hicn-plugin/src/network/faces/iface_node.c | 915 ++++++++++++++ hicn-plugin/src/network/faces/iface_node.h | 54 + hicn-plugin/src/network/hashtb.c | 1017 +++++++++++++++ hicn-plugin/src/network/hashtb.h | 546 ++++++++ hicn-plugin/src/network/hicn.api | 579 +++++++++ hicn-plugin/src/network/hicn.h | 42 + hicn-plugin/src/network/hicn_api.c | 727 +++++++++++ hicn-plugin/src/network/hicn_api_test.c | 1319 +++++++++++++++++++ hicn-plugin/src/network/hicn_config.c | 224 ++++ hicn-plugin/src/network/infra.h | 102 ++ hicn-plugin/src/network/interest_hitcs.h | 66 + hicn-plugin/src/network/interest_hitcs_node.c | 291 +++++ hicn-plugin/src/network/interest_hitpit.h | 68 + hicn-plugin/src/network/interest_hitpit_node.c | 308 +++++ hicn-plugin/src/network/interest_pcslookup.h | 67 + hicn-plugin/src/network/interest_pcslookup_node.c | 237 ++++ hicn-plugin/src/network/mapme.h | 365 ++++++ hicn-plugin/src/network/mapme_ack.h | 58 + hicn-plugin/src/network/mapme_ack_node.c | 234 ++++ hicn-plugin/src/network/mapme_ctrl.h | 78 ++ hicn-plugin/src/network/mapme_ctrl_node.c | 337 +++++ hicn-plugin/src/network/mapme_eventmgr.c | 567 +++++++++ hicn-plugin/src/network/mapme_eventmgr.h | 57 + hicn-plugin/src/network/mgmt.c | 96 ++ hicn-plugin/src/network/mgmt.h | 129 ++ hicn-plugin/src/network/params.h | 126 ++ hicn-plugin/src/network/parser.h | 121 ++ hicn-plugin/src/network/pcs.c | 53 + hicn-plugin/src/network/pcs.h | 839 +++++++++++++ hicn-plugin/src/network/pg.c | 1326 ++++++++++++++++++++ hicn-plugin/src/network/pg.h | 101 ++ hicn-plugin/src/network/route.c | 766 +++++++++++ hicn-plugin/src/network/route.h | 130 ++ hicn-plugin/src/network/state.h | 115 ++ hicn-plugin/src/network/strategies/dpo_mw.c | 161 +++ hicn-plugin/src/network/strategies/dpo_mw.h | 149 +++ hicn-plugin/src/network/strategies/dpo_rr.c | 160 +++ hicn-plugin/src/network/strategies/dpo_rr.h | 152 +++ hicn-plugin/src/network/strategies/strategy_mw.c | 128 ++ hicn-plugin/src/network/strategies/strategy_mw.h | 41 + .../src/network/strategies/strategy_mw_cli.c | 142 +++ hicn-plugin/src/network/strategies/strategy_rr.c | 122 ++ hicn-plugin/src/network/strategies/strategy_rr.h | 41 + hicn-plugin/src/network/strategy.h | 99 ++ hicn-plugin/src/network/strategy_dpo_ctx.c | 164 +++ hicn-plugin/src/network/strategy_dpo_ctx.h | 197 +++ hicn-plugin/src/network/strategy_dpo_manager.c | 160 +++ hicn-plugin/src/network/strategy_dpo_manager.h | 193 +++ hicn-plugin/src/network/strategy_node.c | 323 +++++ hicn-plugin/src/network/udp_tunnels/udp_decap.h | 32 + .../src/network/udp_tunnels/udp_decap_node.c | 623 +++++++++ hicn-plugin/src/network/udp_tunnels/udp_tunnel.c | 281 +++++ hicn-plugin/src/network/udp_tunnels/udp_tunnel.h | 114 ++ hicn-plugin/src/network/utils.h | 87 ++ hicn-plugin/src/params.h | 126 -- hicn-plugin/src/parser.h | 121 -- hicn-plugin/src/pcs.c | 53 - hicn-plugin/src/pcs.h | 839 ------------- hicn-plugin/src/pg.c | 1326 -------------------- hicn-plugin/src/pg.h | 101 -- hicn-plugin/src/route.c | 766 ----------- hicn-plugin/src/route.h | 130 -- hicn-plugin/src/state.h | 115 -- hicn-plugin/src/strategies/dpo_mw.c | 161 --- hicn-plugin/src/strategies/dpo_mw.h | 149 --- hicn-plugin/src/strategies/dpo_rr.c | 160 --- hicn-plugin/src/strategies/dpo_rr.h | 152 --- hicn-plugin/src/strategies/strategy_mw.c | 128 -- hicn-plugin/src/strategies/strategy_mw.h | 41 - hicn-plugin/src/strategies/strategy_mw_cli.c | 142 --- hicn-plugin/src/strategies/strategy_rr.c | 122 -- hicn-plugin/src/strategies/strategy_rr.h | 41 - hicn-plugin/src/strategy.h | 99 -- hicn-plugin/src/strategy_dpo_ctx.c | 164 --- hicn-plugin/src/strategy_dpo_ctx.h | 197 --- hicn-plugin/src/strategy_dpo_manager.c | 160 --- hicn-plugin/src/strategy_dpo_manager.h | 193 --- hicn-plugin/src/strategy_node.c | 323 ----- hicn-plugin/src/udp_tunnels/udp_decap.h | 32 - hicn-plugin/src/udp_tunnels/udp_decap_node.c | 623 --------- hicn-plugin/src/udp_tunnels/udp_tunnel.c | 281 ----- hicn-plugin/src/udp_tunnels/udp_tunnel.h | 114 -- hicn-plugin/src/utils.h | 87 -- hicn-plugin/vapi/CMakeLists.txt | 3 +- 203 files changed, 28596 insertions(+), 23258 deletions(-) create mode 100644 hicn-plugin/.vscode/settings.json create mode 100644 hicn-plugin/includes/vpp_plugins/hicn/CMakeLists.txt create mode 100644 hicn-plugin/includes/vpp_plugins/hicn/error.h create mode 100644 hicn-plugin/includes/vpp_plugins/hicn/hicn_all_api_h.h create mode 100644 hicn-plugin/includes/vpp_plugins/hicn/hicn_api.h create mode 100644 hicn-plugin/includes/vpp_plugins/hicn/hicn_msg_enum.h delete mode 100644 hicn-plugin/src/cache_policies/cs_lru.c delete mode 100644 hicn-plugin/src/cache_policies/cs_lru.h delete mode 100644 hicn-plugin/src/cache_policies/cs_policy.h delete mode 100644 hicn-plugin/src/cli.c delete mode 100644 hicn-plugin/src/data_fwd.h delete mode 100644 hicn-plugin/src/data_fwd_node.c delete mode 100644 hicn-plugin/src/data_input_node.c delete mode 100644 hicn-plugin/src/data_pcslookup.h delete mode 100644 hicn-plugin/src/data_pcslookup_node.c delete mode 100644 hicn-plugin/src/error.c delete mode 100644 hicn-plugin/src/error.h delete mode 100644 hicn-plugin/src/face_db.h delete mode 100644 hicn-plugin/src/faces/app/address_mgr.c delete mode 100644 hicn-plugin/src/faces/app/address_mgr.h delete mode 100644 hicn-plugin/src/faces/app/face_app_cli.c delete mode 100644 hicn-plugin/src/faces/app/face_cons.c delete mode 100644 hicn-plugin/src/faces/app/face_cons.h delete mode 100644 hicn-plugin/src/faces/app/face_prod.c delete mode 100644 hicn-plugin/src/faces/app/face_prod.h delete mode 100644 hicn-plugin/src/faces/app/face_prod_node.c delete mode 100644 hicn-plugin/src/faces/face.c delete mode 100644 hicn-plugin/src/faces/face.h delete mode 100644 hicn-plugin/src/faces/face_cli.c delete mode 100644 hicn-plugin/src/faces/face_node.c delete mode 100644 hicn-plugin/src/faces/face_node.h delete mode 100644 hicn-plugin/src/faces/iface_node.c delete mode 100644 hicn-plugin/src/faces/iface_node.h delete mode 100644 hicn-plugin/src/hashtb.c delete mode 100644 hicn-plugin/src/hashtb.h delete mode 100644 hicn-plugin/src/hicn.api delete mode 100644 hicn-plugin/src/hicn.c delete mode 100644 hicn-plugin/src/hicn.h delete mode 100644 hicn-plugin/src/hicn_all_api_h.h delete mode 100644 hicn-plugin/src/hicn_api.c delete mode 100644 hicn-plugin/src/hicn_api.h delete mode 100644 hicn-plugin/src/hicn_api_test.c create mode 100644 hicn-plugin/src/hicn_buffer.h delete mode 100644 hicn-plugin/src/hicn_msg_enum.h create mode 100644 hicn-plugin/src/hicn_plugin.c create mode 100644 hicn-plugin/src/host_stack/FEATURE.yaml create mode 100644 hicn-plugin/src/host_stack/README.md create mode 100644 hicn-plugin/src/host_stack/cbr_proto.c create mode 100644 hicn-plugin/src/host_stack/cli.c create mode 100644 hicn-plugin/src/host_stack/debug.h create mode 100644 hicn-plugin/src/host_stack/error.c create mode 100644 hicn-plugin/src/host_stack/error.h create mode 100644 hicn-plugin/src/host_stack/errors/hicn_hs.def create mode 100644 hicn-plugin/src/host_stack/host_stack.c create mode 100644 hicn-plugin/src/host_stack/host_stack.h create mode 100644 hicn-plugin/src/host_stack/inlines.h create mode 100644 hicn-plugin/src/host_stack/input_node.c create mode 100644 hicn-plugin/src/host_stack/output_node.c create mode 100644 hicn-plugin/src/host_stack/producer_dpo.c create mode 100644 hicn-plugin/src/host_stack/producer_dpo.h create mode 100644 hicn-plugin/src/host_stack/proto.h create mode 100644 hicn-plugin/src/host_stack/route.c create mode 100644 hicn-plugin/src/host_stack/route.h create mode 100644 hicn-plugin/src/host_stack/test/hicn_hs_client.c create mode 100644 hicn-plugin/src/host_stack/test/hicn_hs_client.h create mode 100644 hicn-plugin/src/host_stack/test/hicn_hs_server.c create mode 100644 hicn-plugin/src/host_stack/testbed/Dockerfile create mode 100644 hicn-plugin/src/host_stack/testbed/client-startup.txt create mode 100644 hicn-plugin/src/host_stack/testbed/init.sh create mode 100644 hicn-plugin/src/host_stack/testbed/run-client-server.sh create mode 100644 hicn-plugin/src/host_stack/testbed/server-startup.txt create mode 100644 hicn-plugin/src/host_stack/testbed/startup-client.conf create mode 100644 hicn-plugin/src/host_stack/testbed/startup-server.conf create mode 100644 hicn-plugin/src/host_stack/testbed/test_hicn_hs.txt create mode 100644 hicn-plugin/src/host_stack/testbed/vcl.conf create mode 100644 hicn-plugin/src/host_stack/utils.h delete mode 100644 hicn-plugin/src/infra.h delete mode 100644 hicn-plugin/src/interest_hitcs.h delete mode 100644 hicn-plugin/src/interest_hitcs_node.c delete mode 100644 hicn-plugin/src/interest_hitpit.h delete mode 100644 hicn-plugin/src/interest_hitpit_node.c delete mode 100644 hicn-plugin/src/interest_pcslookup.h delete mode 100644 hicn-plugin/src/interest_pcslookup_node.c delete mode 100644 hicn-plugin/src/mapme.h delete mode 100644 hicn-plugin/src/mapme_ack.h delete mode 100644 hicn-plugin/src/mapme_ack_node.c delete mode 100644 hicn-plugin/src/mapme_ctrl.h delete mode 100644 hicn-plugin/src/mapme_ctrl_node.c delete mode 100644 hicn-plugin/src/mapme_eventmgr.c delete mode 100644 hicn-plugin/src/mapme_eventmgr.h delete mode 100644 hicn-plugin/src/mgmt.c delete mode 100644 hicn-plugin/src/mgmt.h create mode 100644 hicn-plugin/src/network/asd create mode 100644 hicn-plugin/src/network/cache_policies/cs_lru.c create mode 100644 hicn-plugin/src/network/cache_policies/cs_lru.h create mode 100644 hicn-plugin/src/network/cache_policies/cs_policy.h create mode 100644 hicn-plugin/src/network/cli.c create mode 100644 hicn-plugin/src/network/data_fwd.h create mode 100644 hicn-plugin/src/network/data_fwd_node.c create mode 100644 hicn-plugin/src/network/data_input_node.c create mode 100644 hicn-plugin/src/network/data_pcslookup.h create mode 100644 hicn-plugin/src/network/data_pcslookup_node.c create mode 100644 hicn-plugin/src/network/error.c create mode 100644 hicn-plugin/src/network/face_db.h create mode 100644 hicn-plugin/src/network/faces/app/address_mgr.c create mode 100644 hicn-plugin/src/network/faces/app/address_mgr.h create mode 100644 hicn-plugin/src/network/faces/app/face_app_cli.c create mode 100644 hicn-plugin/src/network/faces/app/face_cons.c create mode 100644 hicn-plugin/src/network/faces/app/face_cons.h create mode 100644 hicn-plugin/src/network/faces/app/face_prod.c create mode 100644 hicn-plugin/src/network/faces/app/face_prod.h create mode 100644 hicn-plugin/src/network/faces/app/face_prod_node.c create mode 100644 hicn-plugin/src/network/faces/face.c create mode 100644 hicn-plugin/src/network/faces/face.h create mode 100644 hicn-plugin/src/network/faces/face_cli.c create mode 100644 hicn-plugin/src/network/faces/face_node.c create mode 100644 hicn-plugin/src/network/faces/face_node.h create mode 100644 hicn-plugin/src/network/faces/iface_node.c create mode 100644 hicn-plugin/src/network/faces/iface_node.h create mode 100644 hicn-plugin/src/network/hashtb.c create mode 100644 hicn-plugin/src/network/hashtb.h create mode 100644 hicn-plugin/src/network/hicn.api create mode 100644 hicn-plugin/src/network/hicn.h create mode 100644 hicn-plugin/src/network/hicn_api.c create mode 100644 hicn-plugin/src/network/hicn_api_test.c create mode 100644 hicn-plugin/src/network/hicn_config.c create mode 100644 hicn-plugin/src/network/infra.h create mode 100644 hicn-plugin/src/network/interest_hitcs.h create mode 100644 hicn-plugin/src/network/interest_hitcs_node.c create mode 100644 hicn-plugin/src/network/interest_hitpit.h create mode 100644 hicn-plugin/src/network/interest_hitpit_node.c create mode 100644 hicn-plugin/src/network/interest_pcslookup.h create mode 100644 hicn-plugin/src/network/interest_pcslookup_node.c create mode 100644 hicn-plugin/src/network/mapme.h create mode 100644 hicn-plugin/src/network/mapme_ack.h create mode 100644 hicn-plugin/src/network/mapme_ack_node.c create mode 100644 hicn-plugin/src/network/mapme_ctrl.h create mode 100644 hicn-plugin/src/network/mapme_ctrl_node.c create mode 100644 hicn-plugin/src/network/mapme_eventmgr.c create mode 100644 hicn-plugin/src/network/mapme_eventmgr.h create mode 100644 hicn-plugin/src/network/mgmt.c create mode 100644 hicn-plugin/src/network/mgmt.h create mode 100644 hicn-plugin/src/network/params.h create mode 100644 hicn-plugin/src/network/parser.h create mode 100644 hicn-plugin/src/network/pcs.c create mode 100644 hicn-plugin/src/network/pcs.h create mode 100644 hicn-plugin/src/network/pg.c create mode 100644 hicn-plugin/src/network/pg.h create mode 100644 hicn-plugin/src/network/route.c create mode 100644 hicn-plugin/src/network/route.h create mode 100644 hicn-plugin/src/network/state.h create mode 100644 hicn-plugin/src/network/strategies/dpo_mw.c create mode 100644 hicn-plugin/src/network/strategies/dpo_mw.h create mode 100644 hicn-plugin/src/network/strategies/dpo_rr.c create mode 100644 hicn-plugin/src/network/strategies/dpo_rr.h create mode 100644 hicn-plugin/src/network/strategies/strategy_mw.c create mode 100644 hicn-plugin/src/network/strategies/strategy_mw.h create mode 100644 hicn-plugin/src/network/strategies/strategy_mw_cli.c create mode 100644 hicn-plugin/src/network/strategies/strategy_rr.c create mode 100644 hicn-plugin/src/network/strategies/strategy_rr.h create mode 100644 hicn-plugin/src/network/strategy.h create mode 100644 hicn-plugin/src/network/strategy_dpo_ctx.c create mode 100644 hicn-plugin/src/network/strategy_dpo_ctx.h create mode 100644 hicn-plugin/src/network/strategy_dpo_manager.c create mode 100644 hicn-plugin/src/network/strategy_dpo_manager.h create mode 100644 hicn-plugin/src/network/strategy_node.c create mode 100644 hicn-plugin/src/network/udp_tunnels/udp_decap.h create mode 100644 hicn-plugin/src/network/udp_tunnels/udp_decap_node.c create mode 100644 hicn-plugin/src/network/udp_tunnels/udp_tunnel.c create mode 100644 hicn-plugin/src/network/udp_tunnels/udp_tunnel.h create mode 100644 hicn-plugin/src/network/utils.h delete mode 100644 hicn-plugin/src/params.h delete mode 100644 hicn-plugin/src/parser.h delete mode 100644 hicn-plugin/src/pcs.c delete mode 100644 hicn-plugin/src/pcs.h delete mode 100644 hicn-plugin/src/pg.c delete mode 100644 hicn-plugin/src/pg.h delete mode 100644 hicn-plugin/src/route.c delete mode 100644 hicn-plugin/src/route.h delete mode 100644 hicn-plugin/src/state.h delete mode 100644 hicn-plugin/src/strategies/dpo_mw.c delete mode 100644 hicn-plugin/src/strategies/dpo_mw.h delete mode 100644 hicn-plugin/src/strategies/dpo_rr.c delete mode 100644 hicn-plugin/src/strategies/dpo_rr.h delete mode 100644 hicn-plugin/src/strategies/strategy_mw.c delete mode 100644 hicn-plugin/src/strategies/strategy_mw.h delete mode 100644 hicn-plugin/src/strategies/strategy_mw_cli.c delete mode 100644 hicn-plugin/src/strategies/strategy_rr.c delete mode 100644 hicn-plugin/src/strategies/strategy_rr.h delete mode 100644 hicn-plugin/src/strategy.h delete mode 100644 hicn-plugin/src/strategy_dpo_ctx.c delete mode 100644 hicn-plugin/src/strategy_dpo_ctx.h delete mode 100644 hicn-plugin/src/strategy_dpo_manager.c delete mode 100644 hicn-plugin/src/strategy_dpo_manager.h delete mode 100644 hicn-plugin/src/strategy_node.c delete mode 100644 hicn-plugin/src/udp_tunnels/udp_decap.h delete mode 100644 hicn-plugin/src/udp_tunnels/udp_decap_node.c delete mode 100644 hicn-plugin/src/udp_tunnels/udp_tunnel.c delete mode 100644 hicn-plugin/src/udp_tunnels/udp_tunnel.h delete mode 100644 hicn-plugin/src/utils.h (limited to 'hicn-plugin') diff --git a/hicn-plugin/.vscode/settings.json b/hicn-plugin/.vscode/settings.json new file mode 100644 index 000000000..685ed8a0f --- /dev/null +++ b/hicn-plugin/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "editor.tabSize": 8, + "editor.insertSpaces": false, + "editor.detectIndentation": false +} \ No newline at end of file diff --git a/hicn-plugin/CMakeLists.txt b/hicn-plugin/CMakeLists.txt index ea933d8a0..07c46aa25 100644 --- a/hicn-plugin/CMakeLists.txt +++ b/hicn-plugin/CMakeLists.txt @@ -37,6 +37,6 @@ set(HICN_PLUGIN hicn-plugin CACHE INTERNAL "" FORCE) include (Packaging) +add_subdirectory(includes/vpp_plugins/hicn) add_subdirectory(src) - add_subdirectory(vapi) diff --git a/hicn-plugin/includes/vpp_plugins/hicn/CMakeLists.txt b/hicn-plugin/includes/vpp_plugins/hicn/CMakeLists.txt new file mode 100644 index 000000000..bea6c9136 --- /dev/null +++ b/hicn-plugin/includes/vpp_plugins/hicn/CMakeLists.txt @@ -0,0 +1,34 @@ +# Copyright (c) 2020 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. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +include(GNUInstallDirs) + +set(ASIO_STANDALONE 1) + +set(HICNPLUGIN_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/../.. "" + ${CMAKE_CURRENT_BUILD_DIR}/ "" + CACHE INTERNAL + "" FORCE +) + +set(HICNPLUGIN_TO_INSTALL_HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/error.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_all_api_h.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_msg_enum.h "" + CACHE INTERNAL + "" FORCE +) \ No newline at end of file diff --git a/hicn-plugin/includes/vpp_plugins/hicn/error.h b/hicn-plugin/includes/vpp_plugins/hicn/error.h new file mode 100644 index 000000000..59ebce61c --- /dev/null +++ b/hicn-plugin/includes/vpp_plugins/hicn/error.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017-2020 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_ERROR_H__ +#define __HICN_ERROR_H__ + +/** + * @file error.h + * + * Error codes for the hICN plugin. + */ + + +#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, "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, "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, "IP adjacency on incomplete face not available") \ + _(APPFACE_ALREADY_ENABLED, -173, "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, "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, "Src and dst addresses have different type (ipv4 and ipv6)") + +typedef enum +{ +#define _(a,b,c) HICN_ERROR_##a = (b), + foreach_hicn_error +#undef _ + HICN_N_ERROR, +} hicn_error_t; + +extern const char *HICN_ERROR_STRING[]; + +#define get_error_string(errno) (char *)(errno ? HICN_ERROR_STRING[(-errno) - 127] : HICN_ERROR_STRING[errno]) + +#endif /* //__HICN_ERROR_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/includes/vpp_plugins/hicn/hicn_all_api_h.h b/hicn-plugin/includes/vpp_plugins/hicn/hicn_all_api_h.h new file mode 100644 index 000000000..c4b19b393 --- /dev/null +++ b/hicn-plugin/includes/vpp_plugins/hicn/hicn_all_api_h.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 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 + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/includes/vpp_plugins/hicn/hicn_api.h b/hicn-plugin/includes/vpp_plugins/hicn/hicn_api.h new file mode 100644 index 000000000..ddaa914a7 --- /dev/null +++ b/hicn-plugin/includes/vpp_plugins/hicn/hicn_api.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2020 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_API_H__ +#define __HICN_API_H__ + +/** + * @file + */ + + +#define HICN_STRATEGY_NULL ~0 +#define HICN_FIB_TABLE 10 + +/* define message structures */ +#define vl_typedefs +#include +#undef vl_typedefs + +#endif /* // __HICN_API_H___ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/includes/vpp_plugins/hicn/hicn_msg_enum.h b/hicn-plugin/includes/vpp_plugins/hicn/hicn_msg_enum.h new file mode 100644 index 000000000..7b4582dbc --- /dev/null +++ b/hicn-plugin/includes/vpp_plugins/hicn/hicn_msg_enum.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017-2019 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_MSG_ENUM_H__ +#define __HICN_MSG_ENUM_H__ + +#include + +/** + * @file + */ +#define vl_msg_id(n, h) n, +typedef enum +{ +#include + /* We'll want to know how many messages IDs we need... */ + VL_MSG_FIRST_AVAILABLE, +} vl_msg_id_t; +#undef vl_msg_id + +#endif /* __HICN_MSG_ENUM_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/CMakeLists.txt b/hicn-plugin/src/CMakeLists.txt index 97284b218..eca7e6436 100644 --- a/hicn-plugin/src/CMakeLists.txt +++ b/hicn-plugin/src/CMakeLists.txt @@ -17,154 +17,155 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) find_package(Vpp REQUIRED) -include_directories(${VPP_INCLUDE_DIR}) +if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) + find_package(Libtransport REQUIRED) + find_package(Libhicn REQUIRED) +else() + if (DISABLE_SHARED_LIBRARIES) + set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_STATIC}) + set(LIBHICN_LIBRARIES ${LIBHICN_STATIC}) + else () + set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_SHARED}) + set(LIBHICN_LIBRARIES ${LIBHICN_SHARED}) + endif () + + list(APPEND DEPENDENCIES + ${LIBHICN_LIBRARIES} + ${LIBTRANSPORT_LIBRARIES} + ) +endif() -set(LIBHICN_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/mapme.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/name.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/ops.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/ah.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/icmp.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/ipv4.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/ipv6.c - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/tcp.c +set(HICN_PLUGIN_SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin.c ) -set(LIBHICN_HEADER_FILES_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/hicn.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/base.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/common.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/error.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/header.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/name.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/ops.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/mapme.h +set(HICN_PLUGIN_HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_buffer.h ) -set(LIBHICN_HEADER_FILES_PROTOCOL - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/ah.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/icmp.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/icmprd.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/ipv4.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/ipv6.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/tcp.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/udp.h +set(HICN_NETWORK_PLUGIN_SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/network/hicn_config.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/hicn_api.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/cli.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/hashtb.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/mgmt.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/pcs.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/route.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategy_dpo_ctx.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategy_dpo_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategy_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/interest_pcslookup_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/interest_hitpit_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/interest_hitcs_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/data_input_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/data_pcslookup_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/data_fwd_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/error.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/face_cli.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/face.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/face_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/iface_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/app/address_mgr.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/app/face_cons.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/app/face_prod.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/app/face_prod_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/app/face_app_cli.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/pg.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategies/dpo_mw.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategies/strategy_mw.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategies/strategy_mw_cli.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategies/dpo_rr.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategies/strategy_rr.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/cache_policies/cs_lru.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/mapme_ack_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/mapme_ctrl_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/mapme_eventmgr.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/udp_tunnels/udp_decap_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/udp_tunnels/udp_tunnel.c ) -set(LIBHICN_HEADER_FILES_UTIL - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/util/ip_address.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/util/token.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/util/types.h +set(HICN_NETWORK_PLUGIN_HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/network/hashtb.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/mgmt.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/params.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/pcs.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/hicn.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/state.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/infra.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/parser.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/route.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategy_dpo_ctx.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategy_dpo_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategy.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/interest_pcslookup.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/interest_hitpit.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/interest_hitcs.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/data_pcslookup.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/data_fwd.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/face_db.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/face.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/face_node.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/iface_node.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/face_dpo.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/app/address_mgr.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/app/face_cons.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/faces/app/face_prod.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/pg.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategies/dpo_mw.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategies/strategy_mw.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategies/dpo_rr.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/strategies/strategy_rr.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/cache_policies/cs_policy.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/cache_policies/cs_lru.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/mapme.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/mapme_ack.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/mapme_ctrl.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/mapme_eventmgr.h + ${CMAKE_CURRENT_SOURCE_DIR}/network/udp_tunnels/udp_tunnel.h ) -set(HICN_PLUGIN_SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/hicn.c - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.c - ${CMAKE_CURRENT_SOURCE_DIR}/cli.c - ${CMAKE_CURRENT_SOURCE_DIR}/hashtb.c - ${CMAKE_CURRENT_SOURCE_DIR}/mgmt.c - ${CMAKE_CURRENT_SOURCE_DIR}/pcs.c - ${CMAKE_CURRENT_SOURCE_DIR}/route.c - ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_ctx.c - ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_manager.c - ${CMAKE_CURRENT_SOURCE_DIR}/strategy_node.c - ${CMAKE_CURRENT_SOURCE_DIR}/interest_pcslookup_node.c - ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitpit_node.c - ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitcs_node.c - ${CMAKE_CURRENT_SOURCE_DIR}/data_input_node.c - ${CMAKE_CURRENT_SOURCE_DIR}/data_pcslookup_node.c - ${CMAKE_CURRENT_SOURCE_DIR}/data_fwd_node.c - ${CMAKE_CURRENT_SOURCE_DIR}/error.c - ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_cli.c - ${CMAKE_CURRENT_SOURCE_DIR}/faces/face.c - ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_node.c - ${CMAKE_CURRENT_SOURCE_DIR}/faces/iface_node.c - ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/address_mgr.c - ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_cons.c - ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_prod.c - ${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}/strategies/dpo_mw.c - ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw.c - ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw_cli.c - ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_rr.c - ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_rr.c - ${CMAKE_CURRENT_SOURCE_DIR}/cache_policies/cs_lru.c - ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ack_node.c - ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ctrl_node.c - ${CMAKE_CURRENT_SOURCE_DIR}/mapme_eventmgr.c - ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_decap_node.c - ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_tunnel.c +set(HICN_HS_PLUGIN_SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/host_stack.c + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/error.c + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/cbr_proto.c + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/cli.c + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/input_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/output_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/producer_dpo.c + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/route.c + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/test/hicn_hs_client.c + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/test/hicn_hs_server.c ) -set(HICN_PLUGIN_HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_all_api_h.h - ${CMAKE_CURRENT_SOURCE_DIR}/hashtb.h - ${CMAKE_CURRENT_SOURCE_DIR}/mgmt.h - ${CMAKE_CURRENT_SOURCE_DIR}/params.h - ${CMAKE_CURRENT_SOURCE_DIR}/pcs.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn.h - ${CMAKE_CURRENT_SOURCE_DIR}/state.h - ${CMAKE_CURRENT_SOURCE_DIR}/infra.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_msg_enum.h - ${CMAKE_CURRENT_SOURCE_DIR}/parser.h - ${CMAKE_CURRENT_SOURCE_DIR}/route.h - ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_ctx.h - ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_manager.h - ${CMAKE_CURRENT_SOURCE_DIR}/strategy.h - ${CMAKE_CURRENT_SOURCE_DIR}/interest_pcslookup.h - ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitpit.h - ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitcs.h - ${CMAKE_CURRENT_SOURCE_DIR}/data_pcslookup.h - ${CMAKE_CURRENT_SOURCE_DIR}/data_fwd.h - ${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_node.h - ${CMAKE_CURRENT_SOURCE_DIR}/faces/iface_node.h - ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_dpo.h - ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/address_mgr.h - ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_cons.h - ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_prod.h - ${CMAKE_CURRENT_SOURCE_DIR}/pg.h - ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_mw.h - ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw.h - ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_rr.h - ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_rr.h - ${CMAKE_CURRENT_SOURCE_DIR}/cache_policies/cs_policy.h - ${CMAKE_CURRENT_SOURCE_DIR}/cache_policies/cs_lru.h - ${CMAKE_CURRENT_SOURCE_DIR}/mapme.h - ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ack.h - ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ctrl.h - ${CMAKE_CURRENT_SOURCE_DIR}/mapme_eventmgr.h - ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_tunnel.h +set(HICN_HS_PLUGIN_HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/error.h + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/debug.h + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/host_stack.h + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/inlines.h + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/producer_dpo.h + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/proto.h + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/route.h + ${CMAKE_CURRENT_SOURCE_DIR}/host_stack/utils.h ) set(HICN_API_TEST_SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api_test.c - ${CMAKE_CURRENT_SOURCE_DIR}/error.c) + ${CMAKE_CURRENT_SOURCE_DIR}/network/hicn_api_test.c + ${CMAKE_CURRENT_SOURCE_DIR}/network/error.c +) set(HICN_API_HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_msg_enum.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_all_api_h.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.h - ${CMAKE_CURRENT_SOURCE_DIR}/error.h) + ${HICNPLUGIN_TO_INSTALL_HEADER_FILES} +) set(HICN_API_GENERATED_FILES - ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.h - ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api_types.h - ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api_enum.h + ${PROJECT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.h + ${PROJECT_BINARY_DIR}/vpp_plugins/hicn/hicn.api_types.h + ${PROJECT_BINARY_DIR}/vpp_plugins/hicn/hicn.api_enum.h ) set(HICN_VAPI_GENERATED_FILES - ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.vapi.h - ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.vapi.hpp) - -set(HICN_VPP_STARTUP_CONF_FILE - ${CMAKE_BINARY_DIR}/startup.conf) + ${PROJECT_BINARY_DIR}/vapi/hicn.api.vapi.h + ${PROJECT_BINARY_DIR}/vapi/hicn.api.vapi.hpp) if (NOT VPP_HOME) set(VPP_HOME /usr) @@ -176,127 +177,101 @@ endif (NOT CMAKE_BUILD_TYPE) SET(HICN_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} CACHE STRING "hicn_install_prefix") -if (CMAKE_BUILD_TYPE STREQUAL "Release") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wall -march=native -O3 -g") -elseif (CMAKE_BUILD_TYPE STREQUAL "Debug") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -march=native -O0 -g") - add_definitions(-DCLIB_DEBUG -fPIC -fstack-protector-all) -endif() +set(COMPILE_FLAGS "-march=native") +set(COMPILE_DEFINITIONS "-DHICN_VPP_PLUGIN=1") -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/hicn) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vapi) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vnet/fib) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vnet/udp) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn) +file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/hicn) +file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/vapi) +file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/vnet/ip) +file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/vnet/fib) +file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/vnet/udp) +file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/vpp_plugins/hicn) # These files are missing from vpp binary distribution execute_process( COMMAND bash -c - "if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vapi_json_parser.py ]; then - curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vpp-api/vapi/vapi_json_parser.py -o ${CMAKE_CURRENT_BINARY_DIR}/vapi_json_parser.py; + "if [ ! -e ${PROJECT_BINARY_DIR}/vapi_json_parser.py ]; then + curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vpp-api/vapi/vapi_json_parser.py -o ${PROJECT_BINARY_DIR}/vapi_json_parser.py; fi; - if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py ]; then - curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vpp-api/vapi/vapi_c_gen.py -o ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py; + if [ ! -e ${PROJECT_BINARY_DIR}/vapi_c_gen.py ]; then + curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vpp-api/vapi/vapi_c_gen.py -o ${PROJECT_BINARY_DIR}/vapi_c_gen.py; fi; - if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py ]; then - curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vpp-api/vapi/vapi_cpp_gen.py -o ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py; + if [ ! -e ${PROJECT_BINARY_DIR}/vapi_cpp_gen.py ]; then + curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vpp-api/vapi/vapi_cpp_gen.py -o ${PROJECT_BINARY_DIR}/vapi_cpp_gen.py; fi; - if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip/ip_types.api ]; then - curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vnet/ip/ip_types.api -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip/ip_types.api; + if [ ! -e ${PROJECT_BINARY_DIR}/vnet/ip/ip_types.api ]; then + curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vnet/ip/ip_types.api -o ${PROJECT_BINARY_DIR}/vnet/ip/ip_types.api; fi; - if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip/ip_format_fns.h ]; then - curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vnet/ip/ip_format_fns.h -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip/ip_format_fns.h; + if [ ! -e ${PROJECT_BINARY_DIR}/vnet/ip/ip_format_fns.h ]; then + curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vnet/ip/ip_format_fns.h -o ${PROJECT_BINARY_DIR}/vnet/ip/ip_format_fns.h; fi; - if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/fib/fib_entry_track.h ]; then - curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vnet/fib/fib_entry_track.h -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/fib/fib_entry_track.h; + if [ ! -e ${PROJECT_BINARY_DIR}/vnet/fib/fib_entry_track.h ]; then + curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vnet/fib/fib_entry_track.h -o ${PROJECT_BINARY_DIR}/vnet/fib/fib_entry_track.h; fi; - if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/udp/udp_encap.h ]; then - curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vnet/udp/udp_encap.h -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/udp/udp_encap.h; + if [ ! -e ${PROJECT_BINARY_DIR}/vnet/udp/udp_encap.h ]; then + curl https://raw.githubusercontent.com/FDio/vpp/stable/2005/src/vnet/udp/udp_encap.h -o ${PROJECT_BINARY_DIR}/vnet/udp/udp_encap.h; fi; - chmod +x ${CMAKE_CURRENT_BINARY_DIR}/vapi_json_parser.py ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py" + chmod +x ${PROJECT_BINARY_DIR}/vapi_json_parser.py ${PROJECT_BINARY_DIR}/vapi_c_gen.py ${PROJECT_BINARY_DIR}/vapi_cpp_gen.py" ) execute_process( - COMMAND ${VPP_HOME}/bin/vppapigen --includedir ${CMAKE_CURRENT_BINARY_DIR} --input ${CMAKE_CURRENT_SOURCE_DIR}/hicn.api --output ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.h --outputdir ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/ - COMMAND ${VPP_HOME}/bin/vppapigen JSON --includedir ${CMAKE_CURRENT_BINARY_DIR} --input ${CMAKE_CURRENT_SOURCE_DIR}/hicn.api --output ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.json --outputdir ${CMAKE_CURRENT_BINARY_DIR}/vapi/ + COMMAND ${VPP_HOME}/bin/vppapigen --includedir ${PROJECT_BINARY_DIR} --input ${CMAKE_CURRENT_SOURCE_DIR}/network/hicn.api --output ${PROJECT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.h --outputdir ${PROJECT_BINARY_DIR}/vpp_plugins/hicn/ + COMMAND ${VPP_HOME}/bin/vppapigen JSON --includedir ${PROJECT_BINARY_DIR} --input ${CMAKE_CURRENT_SOURCE_DIR}/network/hicn.api --output ${PROJECT_BINARY_DIR}/vapi/hicn.api.json --outputdir ${PROJECT_BINARY_DIR}/vapi/ ) execute_process( - COMMAND ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.json - COMMAND ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.json + COMMAND ${PROJECT_BINARY_DIR}/vapi_c_gen.py ${PROJECT_BINARY_DIR}/vapi/hicn.api.json + COMMAND ${PROJECT_BINARY_DIR}/vapi_cpp_gen.py ${PROJECT_BINARY_DIR}/vapi/hicn.api.json ) -include_directories(SYSTEM) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHICN_VPP_PLUGIN=1") -add_library(hicn_plugin SHARED - ${LIBHICN_FILES} - ${HICN_PLUGIN_SOURCE_FILES} - ${HICN_API_GENERATED_FILES} - ${HICN_VAPI_GENERATED_FILES}) - -file(COPY ${HICN_API_HEADER_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn) -include_directories(${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins) +set(HICN_PLUGIN_INCLUDE_DIRS_INTERNAL + ${HICNPLUGIN_INCLUDE_DIRS} + ${PROJECT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${LIBTRANSPORT_INCLUDE_DIRS} + ${LIBHICN_INCLUDE_DIRS} + ${VPP_INCLUDE_DIR} +) -file(COPY ${LIBHICN_HEADER_FILES_SRC} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/hicn) -file(COPY ${LIBHICN_HEADER_FILES_PROTOCOL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/hicn/protocol) -file(COPY ${LIBHICN_HEADER_FILES_UTIL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/hicn/util) +build_library(hicn_plugin + SHARED + SOURCES ${HICN_PLUGIN_SOURCE_FILES} ${HICN_NETWORK_PLUGIN_SOURCE_FILES} ${HICN_HS_PLUGIN_SOURCE_FILES} + INSTALL_HEADERS ${HICN_API_HEADER_FILES} ${HICN_API_GENERATED_FILES} + LINK_LIBRARIES ${LIBTRANSPORT_LIBRARIES} ${LIBHICN_LIBRARIES} + DEPENDS ${DEPENDENCIES} + COMPONENT ${HICN_PLUGIN} + INCLUDE_DIRS ${HICN_PLUGIN_INCLUDE_DIRS_INTERNAL} + HEADER_ROOT_DIR "vpp_plugins/hicn" + LIBRARY_ROOT_DIR "vpp_plugins" + DEFINITIONS ${COMPILE_DEFINITIONS} + COMPILE_FLAGS ${COMPILE_FLAGS} +) -add_library(hicn_api_test_plugin SHARED - ${HICN_API_TEST_SOURCE_FILES} - ${HICN_API_GENERATED_FILES}) +build_library(hicn_api_test_plugin + SHARED + SOURCES ${HICN_API_TEST_SOURCE_FILES} + INSTALL_HEADERS ${HICN_VAPI_GENERATED_FILES} + COMPONENT ${HICN_PLUGIN} + INCLUDE_DIRS ${HICN_PLUGIN_INCLUDE_DIRS_INTERNAL} + HEADER_ROOT_DIR "vapi" + LIBRARY_ROOT_DIR "vpp_api_test_plugins" + DEFINITIONS ${COMPILE_DEFINITIONS} + COMPILE_FLAGS ${COMPILE_FLAGS} +) -set(VPP_INSTALL_PLUGIN ${HICN_INSTALL_PREFIX}/vpp_plugins) -set(VPP_INSTALL_API_TEST_PLUGIN ${HICN_INSTALL_PREFIX}/vpp_api_test_plugins CACHE STRING "vpp_install_api_test_plugin") -set(VPP_STARTUP_CONF /etc/vpp/) +set_target_properties(hicn_plugin.shared + PROPERTIES + LINKER_LANGUAGE C + INSTALL_RPATH "${VPP_INSTALL_PLUGIN}:${HICN_INSTALL_PREFIX}:/home/ubuntu/host-stack/vpp/build-root/install-vpp_debug-native/vpp/lib" + PREFIX "" +) -set_target_properties(hicn_plugin - PROPERTIES - LINKER_LANGUAGE C - INSTALL_RPATH ${VPP_INSTALL_PLUGIN} - PREFIX "") -set_target_properties(hicn_api_test_plugin - PROPERTIES - LINKER_LANGUAGE C - PREFIX "") +set_target_properties(hicn_api_test_plugin.shared + PROPERTIES + LINKER_LANGUAGE C + INSTALL_RPATH "${VPP_INSTALL_PLUGIN}:${HICN_INSTALL_PREFIX}:/home/ubuntu/host-stack/vpp/build-root/install-vpp_debug-native/vpp/lib" + PREFIX "" +) message (STATUS "hicn-plugin variable ${HICN_PLUGIN}") - -install(DIRECTORY - DESTINATION ${VPP_INSTALL_PLUGIN} - COMPONENT ${HICN_PLUGIN}) -install(TARGETS hicn_plugin - DESTINATION - ${VPP_INSTALL_PLUGIN} - COMPONENT ${HICN_PLUGIN}) - -install(DIRECTORY - DESTINATION ${VPP_INSTALL_API_TEST_PLUGIN} - COMPONENT ${HICN_PLUGIN}) -install(TARGETS hicn_api_test_plugin - DESTINATION ${VPP_INSTALL_API_TEST_PLUGIN} - COMPONENT ${HICN_PLUGIN}) - -install(FILES ${HICN_API_HEADER_FILES} ${HICN_API_GENERATED_FILES} - DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vpp_plugins/hicn - COMPONENT ${HICN_PLUGIN}-dev) - -install(FILES ${HICN_API_GENERATED_FILES} - DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vpp_plugins/hicn - COMPONENT ${HICN_PLUGIN}-dev) - -install(FILES ${HICN_VAPI_GENERATED_FILES} - DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vapi - COMPONENT ${HICN_PLUGIN}-dev) - -#Set variables for other project depending on hicn-plugin -set(HICNPLUGIN_INCLUDE_DIRS - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins - ${VPP_INCLUDE_DIRS} - CACHE INTERNAL "" FORCE) -set(HICNPLUGIN_LIBRARIES ${VPP_LIBRARIES} CACHE INTERNAL "" FORCE) diff --git a/hicn-plugin/src/cache_policies/cs_lru.c b/hicn-plugin/src/cache_policies/cs_lru.c deleted file mode 100644 index 079af58ab..000000000 --- a/hicn-plugin/src/cache_policies/cs_lru.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 2017-2019 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 "../hashtb.h" -#include "../strategy_dpo_manager.h" -#include "../error.h" -#include "cs_lru.h" -#include "cs_policy.h" - -hicn_cs_policy_vft_t hicn_cs_lru = { - .hicn_cs_insert = &hicn_cs_lru_insert, - .hicn_cs_update = &hicn_cs_lru_update_head, - .hicn_cs_dequeue = &hicn_cs_lru_dequeue, - .hicn_cs_delete_get = &hicn_cs_lru_delete_get, - .hicn_cs_trim = &hicn_cs_lru_trim, - .hicn_cs_flush = &hicn_cs_lru_flush, -}; - -/* - * Insert a new CS element at the head of the CS LRU - */ -void -hicn_cs_lru_insert (hicn_pit_cs_t * p, hicn_hash_node_t * node, - hicn_pcs_entry_t * pcs, hicn_cs_policy_t * policy_state) -{ - hicn_hash_node_t *lrunode; - hicn_pcs_entry_t *lrupcs; - u32 idx; - - idx = hicn_hashtb_node_idx_from_node (p->pcs_table, node); - - if (policy_state->head != 0) - { - lrunode = hicn_hashtb_node_from_idx (p->pcs_table, policy_state->head); - lrupcs = hicn_pit_get_data (lrunode); - - ASSERT (lrupcs->u.cs.cs_lru_prev == 0); - lrupcs->u.cs.cs_lru_prev = idx; - - pcs->u.cs.cs_lru_prev = 0; - pcs->u.cs.cs_lru_next = policy_state->head; - - policy_state->head = idx; - } - else - { - ASSERT (policy_state->tail == 0); /* We think the list is - * empty */ - - policy_state->head = policy_state->tail = idx; - - pcs->u.cs.cs_lru_next = pcs->u.cs.cs_lru_prev = 0; - } - - policy_state->count++; -} - -void -hicn_cs_lru_delete_get (hicn_pit_cs_t * p, hicn_cs_policy_t * policy_state, - hicn_hash_node_t ** nodep, - hicn_pcs_entry_t ** pcs_entry, - hicn_hash_entry_t ** hash_entry) -{ - *nodep = hicn_hashtb_node_from_idx (p->pcs_table, policy_state->tail); - *pcs_entry = hicn_pit_get_data (*nodep); - - *hash_entry = hicn_hashtb_get_entry (p->pcs_table, (*nodep)->entry_idx, - (*nodep)->bucket_id, - (*nodep)->hn_flags & - HICN_HASH_NODE_OVERFLOW_BUCKET); -} - -/* - * Dequeue an LRU element, for example when it has expired. - */ -void -hicn_cs_lru_dequeue (hicn_pit_cs_t * pit, hicn_hash_node_t * pnode, - hicn_pcs_entry_t * pcs, hicn_cs_policy_t * lru) -{ - hicn_hash_node_t *lrunode; - hicn_pcs_entry_t *lrupcs; - - if (pcs->u.cs.cs_lru_prev != 0) - { - /* Not already on the head of the LRU */ - lrunode = hicn_hashtb_node_from_idx (pit->pcs_table, - pcs->u.cs.cs_lru_prev); - lrupcs = hicn_pit_get_data (lrunode); - - lrupcs->u.cs.cs_lru_next = pcs->u.cs.cs_lru_next; - } - else - { - ASSERT (lru->head == - hicn_hashtb_node_idx_from_node (pit->pcs_table, pnode)); - lru->head = pcs->u.cs.cs_lru_next; - } - - if (pcs->u.cs.cs_lru_next != 0) - { - /* Not already the end of the LRU */ - lrunode = hicn_hashtb_node_from_idx (pit->pcs_table, - pcs->u.cs.cs_lru_next); - lrupcs = hicn_pit_get_data (lrunode); - - lrupcs->u.cs.cs_lru_prev = pcs->u.cs.cs_lru_prev; - } - else - { - /* This was the last LRU element */ - ASSERT (lru->tail == - hicn_hashtb_node_idx_from_node (pit->pcs_table, pnode)); - lru->tail = pcs->u.cs.cs_lru_prev; - } - - pcs->u.cs.cs_lru_next = pcs->u.cs.cs_lru_prev = 0; - lru->count--; -} - -/* - * Move a CS LRU element to the head, probably after it's been used. - */ -void -hicn_cs_lru_update_head (hicn_pit_cs_t * pit, hicn_hash_node_t * pnode, - hicn_pcs_entry_t * pcs, hicn_cs_policy_t * lru) -{ - if (pcs->u.cs.cs_lru_prev != 0) - { - /* - * Not already on the head of the LRU, detach it from its - * current position - */ - hicn_cs_lru_dequeue (pit, pnode, pcs, lru); - - /* Now detached from the list; attach at head */ - hicn_cs_lru_insert (pit, pnode, pcs, lru); - - } - else - { - /* The element is already dequeue */ - if (pcs->u.cs.cs_lru_next == 0) - { - /* Now detached from the list; attach at head */ - hicn_cs_lru_insert (pit, pnode, pcs, lru); - } - ASSERT (lru->head == - hicn_hashtb_node_idx_from_node (pit->pcs_table, pnode)); - } -} - -/* - * Remove a batch of nodes from the CS LRU, copying their node indexes into - * the caller's array. We expect this is done when the LRU size exceeds the - * CS's limit. Return the number of removed nodes. - */ -int -hicn_cs_lru_trim (hicn_pit_cs_t * pit, u32 * node_list, int sz, - hicn_cs_policy_t * lru) -{ - hicn_hash_node_t *lrunode; - hicn_pcs_entry_t *lrupcs; - u32 idx; - int i; - - idx = lru->tail; - - for (i = 0; i < sz; i++) - { - - if (idx == 0) - { - break; - } - lrunode = hicn_hashtb_node_from_idx (pit->pcs_table, idx); - lrupcs = hicn_pit_get_data (lrunode); - - node_list[i] = idx; - - idx = lrupcs->u.cs.cs_lru_prev; - lrupcs->u.cs.cs_lru_prev = 0; - lrupcs->u.cs.cs_lru_next = 0; - } - - lru->count -= i; - - lru->tail = idx; - if (idx != 0) - { - lrunode = hicn_hashtb_node_from_idx (pit->pcs_table, idx); - lrupcs = hicn_pit_get_data (lrunode); - - lrupcs->u.cs.cs_lru_next = 0; - } - else - { - /* If the tail is empty, the whole lru is empty */ - lru->head = 0; - } - - return (i); -} - -int -hicn_cs_lru_flush (vlib_main_t * vm, struct hicn_pit_cs_s *pitcs, - hicn_cs_policy_t * state) -{ - if (state->head == 0 && state->tail == 0) - return 0; - - hicn_hash_node_t *lrunode; - hicn_pcs_entry_t *lrupcs; - u32 idx; - int i = 0; - - idx = state->tail; - - while (idx != 0) - { - lrunode = hicn_hashtb_node_from_idx (pitcs->pcs_table, idx); - lrupcs = hicn_pit_get_data (lrunode); - - u64 hashval = 0; - hicn_hashtb_fullhash ((u8 *) & (lrunode->hn_key.ks.key), - lrunode->hn_keysize, &hashval); - hicn_hash_bucket_t *bucket = NULL; - if ((hashval & (pitcs->pcs_table->ht_bucket_count - 1)) == - lrunode->bucket_id) - { - //The bucket is in the non overflown - bucket = pitcs->pcs_table->ht_buckets + lrunode->bucket_id; - } - else - { - bucket = - pool_elt_at_index (pitcs->pcs_table->ht_overflow_buckets, - lrunode->bucket_id); - } - hicn_hash_entry_t *hash_entry = - &(bucket->hb_entries[lrunode->entry_idx]); - hash_entry->locks++; - hicn_pcs_cs_delete (vm, pitcs, &lrupcs, &lrunode, hash_entry, NULL, - NULL); - idx = state->tail; - i++; - } - - return (i); - -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/cache_policies/cs_lru.h b/hicn-plugin/src/cache_policies/cs_lru.h deleted file mode 100644 index 3bd18060d..000000000 --- a/hicn-plugin/src/cache_policies/cs_lru.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 __LRU_H__ -#define __LRU_H__ - -#include "../pcs.h" -#include "../hashtb.h" -#include "cs_policy.h" - -/** - * @file cs_lru.h - * - * This file implements the LRU policy for the CS - */ - - -extern hicn_cs_policy_vft_t hicn_cs_lru; - -/* - * Insert a new CS element at the head of the CS LRU - */ -void -hicn_cs_lru_insert (hicn_pit_cs_t * pcs, hicn_hash_node_t * pnode, - hicn_pcs_entry_t * entry, hicn_cs_policy_t * lru); - - -/* - * Dequeue an LRU element, for example when it has expired. - */ -void -hicn_cs_lru_dequeue (hicn_pit_cs_t * pcs, hicn_hash_node_t * pnode, - hicn_pcs_entry_t * entry, hicn_cs_policy_t * lru); - -/* - * Move a CS LRU element to the head, probably after it's been used. - */ -void -hicn_cs_lru_update_head (hicn_pit_cs_t * pcs, hicn_hash_node_t * pnode, - hicn_pcs_entry_t * entry, hicn_cs_policy_t * lru); - -void -hicn_cs_lru_delete_get (hicn_pit_cs_t * p, hicn_cs_policy_t * policy, - hicn_hash_node_t ** node, hicn_pcs_entry_t ** pcs, - hicn_hash_entry_t ** hash_entry); - -/* - * Remove a batch of nodes from the CS LRU, copying their node indexes into - * the caller's array. We expect this is done when the LRU size exceeds the - * CS's limit. Return the number of removed nodes. - */ -int hicn_cs_lru_trim (hicn_pit_cs_t * pcs, u32 * node_list, int sz, - hicn_cs_policy_t * lru); - - -int hicn_cs_lru_flush (vlib_main_t * vm, struct hicn_pit_cs_s *pitcs, - hicn_cs_policy_t * state); -#endif /* // __LRU_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/cache_policies/cs_policy.h b/hicn-plugin/src/cache_policies/cs_policy.h deleted file mode 100644 index 0bf745915..000000000 --- a/hicn-plugin/src/cache_policies/cs_policy.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_CS_POLICY_H__ -#define __HICN_CS_POLICY_H__ - -#include "../hashtb.h" - -/** - * @file cs_policy.h - * - * This file provides the needed structures to implement a CS policy - */ - - -/* - * Structure - */ -typedef struct hicn_cs_policy_s -{ - u32 max; - u32 count; - - /* Indexes to hashtable nodes forming CS LRU */ - u32 head; - u32 tail; - -} hicn_cs_policy_t; - -/* Forward declaration */ -struct hicn_pit_cs_s; -struct hicn_hash_node_s; -struct hicn_pcs_entry_s; -struct hicn_cs_policy_s; - -/** - * @brief Definition of the virtual functin table for a cache policy. - * - * A cache policy must implement all the following functions: - * - insert: add a new element - * - update: update the position of an existing element - * - dequeue: remove an element from the list - * - delete_get: return the next element that should be removed trim - * - flush: clean the cs - */ -typedef struct hicn_cs_policy_vft_s -{ - void (*hicn_cs_insert) (struct hicn_pit_cs_s * p, - struct hicn_hash_node_s * node, - struct hicn_pcs_entry_s * pcs, - hicn_cs_policy_t * policy); - - void (*hicn_cs_update) (struct hicn_pit_cs_s * p, - struct hicn_hash_node_s * node, - struct hicn_pcs_entry_s * pcs, - hicn_cs_policy_t * policy); - - void (*hicn_cs_dequeue) (struct hicn_pit_cs_s * p, - struct hicn_hash_node_s * node, - struct hicn_pcs_entry_s * pcs, - hicn_cs_policy_t * policy); - - void (*hicn_cs_delete_get) (struct hicn_pit_cs_s * p, - hicn_cs_policy_t * policy, - struct hicn_hash_node_s ** node, - struct hicn_pcs_entry_s ** pcs, - struct hicn_hash_entry_s ** hash_entry); - - int (*hicn_cs_trim) (struct hicn_pit_cs_s * p, u32 * node_list, int sz, - hicn_cs_policy_t * policy); - - int (*hicn_cs_flush) (vlib_main_t * vm, struct hicn_pit_cs_s * p, - hicn_cs_policy_t * policy_state); -} hicn_cs_policy_vft_t; - - - -#endif /* // __HICN_POLICY_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/cli.c b/hicn-plugin/src/cli.c deleted file mode 100644 index 1adf3595c..000000000 --- a/hicn-plugin/src/cli.c +++ /dev/null @@ -1,896 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 // port registration -#include // ip46_address_t -#include -#include - -#include "hicn.h" -#include "infra.h" -#include "parser.h" -#include "mgmt.h" -#include "strategy_dpo_manager.h" -#include "strategy.h" -#include "pg.h" -#include "error.h" -#include "faces/face.h" -#include "route.h" -#include "hicn_api.h" - -static vl_api_hicn_api_node_params_set_t node_ctl_params = { - .pit_max_size = -1, - .pit_max_lifetime_sec = -1.0f, - .cs_max_size = -1, -}; - -typedef enum -{ - IP, - ETHERNET, -} interface_type_t; - -/* - * cli handler for 'control start' - */ -static clib_error_t * -hicn_cli_node_ctl_start_set_command_fn (vlib_main_t * vm, - unformat_input_t * main_input, - vlib_cli_command_t * cmd) -{ - int ret; - - ret = hicn_infra_plugin_enable_disable (1 /* enable */ , - node_ctl_params.pit_max_size, - node_ctl_params.pit_max_lifetime_sec, - node_ctl_params.cs_max_size, ~0); - - vlib_cli_output (vm, "hicn: fwdr initialize => %s\n", - get_error_string (ret)); - - return (ret == HICN_ERROR_NONE) ? 0 : clib_error_return (0, - get_error_string - (ret)); -} - -/* - * cli handler for 'control stop' - */ -static clib_error_t * -hicn_cli_node_ctl_stop_set_command_fn (vlib_main_t * vm, - unformat_input_t * main_input, - vlib_cli_command_t * cmd) -{ - int ret; - - /* - * Catch unexpected extra arguments on this line. See comment on - * hicn_cli_node_ctrl_start_set_command_fn - */ - if (main_input->index > 0 && - main_input->buffer[main_input->index - 1] != '\n') - { - unformat_input_t _line_input, *line_input = &_line_input; - if (!unformat_user (main_input, unformat_line_input, line_input)) - { - return (0); - } - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - return clib_error_return (0, "%s '%U'", - get_error_string (HICN_ERROR_CLI_INVAL), - format_unformat_error, line_input); - } - } - ret = hicn_infra_plugin_enable_disable (0 /* !enable */ , - node_ctl_params.pit_max_size, - node_ctl_params.pit_max_lifetime_sec, - node_ctl_params.cs_max_size, ~0); - - return (ret == HICN_ERROR_NONE) ? 0 : clib_error_return (0, - get_error_string - (ret)); -} - -#define DFLTD_RANGE_OK(val, min, max) \ -({ \ - __typeof__ (val) _val = (val); \ - __typeof__ (min) _min = (min); \ - __typeof__ (max) _max = (max); \ - (_val == -1) || \ - (_val >= _min && _val <= _max); \ -}) - -/* - * cli handler for 'control param' - */ -static clib_error_t * -hicn_cli_node_ctl_param_set_command_fn (vlib_main_t * vm, - unformat_input_t * main_input, - vlib_cli_command_t * cmd) -{ - int rv = 0; - - int table_size; - f64 lifetime; - - if (hicn_main.is_enabled) - { - return (clib_error_return - (0, "params cannot be altered once hicn started")); - } - /* Get a line of input. */ - unformat_input_t _line_input, *line_input = &_line_input; - if (!unformat_user (main_input, unformat_line_input, line_input)) - { - return clib_error_return (0, - get_error_string - (HICN_ERROR_FWD_ALREADY_ENABLED)); - } - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "pit")) - { - if (unformat (line_input, "size %d", &table_size)) - { - if (!DFLTD_RANGE_OK (table_size, HICN_PARAM_PIT_ENTRIES_MIN, - HICN_PARAM_PIT_ENTRIES_MAX)) - { - rv = HICN_ERROR_PIT_CONFIG_SIZE_OOB; - break; - } - node_ctl_params.pit_max_size = table_size; - } - else if (unformat (line_input, "maxlife %f", &lifetime)) - { - if (!DFLTD_RANGE_OK - (lifetime, HICN_PARAM_PIT_LIFETIME_BOUND_MIN_SEC, - HICN_PARAM_PIT_LIFETIME_BOUND_MAX_SEC)) - { - rv = HICN_ERROR_PIT_CONFIG_MAXLT_OOB; - break; - } - node_ctl_params.pit_max_lifetime_sec = lifetime; - } - else - { - rv = HICN_ERROR_CLI_INVAL; - break; - } - } - else if (unformat (line_input, "cs")) - { - if (unformat (line_input, "size %d", &table_size)) - { - if (!DFLTD_RANGE_OK (table_size, HICN_PARAM_CS_ENTRIES_MIN, - HICN_PARAM_CS_ENTRIES_MAX)) - { - rv = HICN_ERROR_CS_CONFIG_SIZE_OOB; - break; - } - node_ctl_params.cs_max_size = table_size; - } - else - { - rv = HICN_ERROR_CLI_INVAL; - break; - } - } - else - { - rv = HICN_ERROR_CLI_INVAL; - break; - } - } - - if (node_ctl_params.cs_max_size == 0) - vlib_cli_output (vm, - "CS size set to 0. Consider disable CS at compilation time for better performances\n"); - - return (rv == HICN_ERROR_NONE) ? 0 : clib_error_return (0, "%s '%U'", - get_error_string - (rv), - format_unformat_error, - line_input); -} - -/* - * cli handler for 'hicn show' - */ -static clib_error_t * -hicn_cli_show_command_fn (vlib_main_t * vm, unformat_input_t * main_input, - vlib_cli_command_t * cmd) -{ - int face_p = 0, fib_p = 0, all_p, internal_p = 0, strategies_p = 0, ret = - HICN_ERROR_NONE; - - /* Get a line of input. */ - unformat_input_t _line_input, *line_input = &_line_input; - if (unformat_user (main_input, unformat_line_input, line_input)) - { - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "face all")) - { - face_p = 1; - } - else if (unformat (line_input, "internal")) - { - /* - * We consider 'internal' a superset, so - * include 'detail' too - */ - internal_p = 1; - } - else if (unformat (line_input, "strategies")) - { - /* - * We consider 'internal' a superset, so - * include 'detail' too - */ - strategies_p = 1; - } - else - { - ret = HICN_ERROR_CLI_INVAL; - goto done; - } - } - } - /* If nothing specified, show everything */ - if ((face_p == 0) && (fib_p == 0) && (strategies_p == 0)) - { - all_p = 1; - } - if (!hicn_main.is_enabled) - { - if (node_ctl_params.pit_max_size == -1 && - node_ctl_params.pit_max_lifetime_sec == -1 && - node_ctl_params.cs_max_size == -1) - { - ret = HICN_ERROR_FWD_NOT_ENABLED; - goto done; - } - vlib_cli_output (vm, "Forwarder: %sabled\nPreconfiguration:\n", - hicn_main.is_enabled ? "en" : "dis"); - - if (node_ctl_params.pit_max_size != -1) - { - vlib_cli_output (vm, " PIT:: max entries:%d\n", - node_ctl_params.pit_max_size); - } - if (node_ctl_params.pit_max_lifetime_sec != -1) - { - vlib_cli_output (vm, " PIT:: max lifetime: %05.3f seconds\n", - node_ctl_params.pit_max_lifetime_sec); - } - if (node_ctl_params.cs_max_size != -1) - { - vlib_cli_output (vm, " CS:: max entries:%d\n", - node_ctl_params.cs_max_size); - } - goto done; - } - /* Globals */ - vlib_cli_output (vm, - "Forwarder: %sabled\n" - " PIT:: max entries:%d," - " lifetime default: max:%05.3f\n" - " CS:: max entries:%d\n", - hicn_main.is_enabled ? "en" : "dis", - hicn_infra_pit_size, - ((f64) hicn_main.pit_lifetime_max_ms) / SEC_MS, - hicn_infra_cs_size); - - vl_api_hicn_api_node_stats_get_reply_t rm = { 0, } - , *rmp = &rm; - if (hicn_mgmt_node_stats_get (&rm) == HICN_ERROR_NONE) - { - vlib_cli_output (vm, //compare vl_api_hicn_api_node_stats_get_reply_t_handler block - " PIT entries (now): %d\n" - " CS total entries (now): %d, network entries (now): %d\n" - " Forwarding statistics:\n" - " pkts_processed: %d\n" - " pkts_interest_count: %d\n" - " pkts_data_count: %d\n" - " pkts_from_cache_count: %d\n" - " interests_aggregated: %d\n" - " interests_retransmitted: %d\n", - clib_net_to_host_u64 (rmp->pit_entries_count), - clib_net_to_host_u64 (rmp->cs_entries_count), - clib_net_to_host_u64 (rmp->cs_entries_ntw_count), - clib_net_to_host_u64 (rmp->pkts_processed), - clib_net_to_host_u64 (rmp->pkts_interest_count), - clib_net_to_host_u64 (rmp->pkts_data_count), - clib_net_to_host_u64 (rmp->pkts_from_cache_count), - clib_net_to_host_u64 (rmp->interests_aggregated), - clib_net_to_host_u64 (rmp->interests_retx)); - } - if (face_p || all_p) - { - u8 *strbuf = NULL; - - strbuf = format_hicn_face_all (strbuf, 1, 0); - vlib_cli_output (vm, "%s", strbuf); - - } - if (strategies_p || all_p) - { - u8 *strbuf = NULL; - - strbuf = format_hicn_strategy_list (strbuf, 1, 0); - vlib_cli_output (vm, (char *) strbuf); - } -done: - if (all_p && internal_p && ret == HICN_ERROR_NONE) - { - vlib_cli_output (vm, "Plugin features: cs:%d\n", HICN_FEATURE_CS); - vlib_cli_output (vm, - "Removed CS entries (and freed vlib buffers) %d, Removed PIT entries %d\n", - hicn_main.pitcs.pcs_cs_dealloc, - hicn_main.pitcs.pcs_pit_dealloc); - vlib_cli_output (vm, - "Bucke count %d, Overflow buckets count %d, used %d\n", - hicn_main.pitcs.pcs_table->ht_bucket_count, - hicn_main.pitcs.pcs_table->ht_overflow_bucket_count, - hicn_main.pitcs.pcs_table->ht_overflow_buckets_used); - - } - return (ret == HICN_ERROR_NONE) ? 0 : clib_error_return (0, "%s\n", - get_error_string - (ret)); -} - -/* - * cli handler for 'fib' - */ -static clib_error_t * -hicn_cli_strategy_set_command_fn (vlib_main_t * vm, - unformat_input_t * main_input, - vlib_cli_command_t * cmd) -{ - clib_error_t *cl_err = 0; - - int rv = HICN_ERROR_NONE; - int addpfx = -1; - ip46_address_t address; - u32 strategy_id; - u32 plen = 0; - fib_prefix_t prefix; - - /* Get a line of input. */ - unformat_input_t _line_input, *line_input = &_line_input; - if (!unformat_user (main_input, unformat_line_input, line_input)) - { - return (0); - } - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "set %d", &strategy_id)) - { - addpfx = 2; - } - else if (addpfx != -1 - && unformat (line_input, "prefix %U/%d", unformat_ip46_address, - &address, IP46_TYPE_ANY, &plen)) - {; - } - else - { - cl_err = clib_error_return (0, "%s '%U'", - get_error_string (HICN_ERROR_CLI_INVAL), - format_unformat_error, line_input); - goto done; - } - } - - fib_prefix_from_ip46_addr (&address, &prefix); - prefix.fp_len = plen; - /* Check parse */ - if (hicn_dpo_strategy_id_is_valid (strategy_id) == - HICN_ERROR_DPO_MGR_ID_NOT_VALID) - { - cl_err = clib_error_return (0, "Please specify a valid strategy..."); - goto done; - } - - rv = hicn_route_set_strategy (&prefix, strategy_id); - cl_err = - (rv == HICN_ERROR_NONE) ? NULL : clib_error_return (0, - get_error_string - (rv)); -done: - - return (cl_err); -} - -/* - * cli handler for 'pgen' - */ -static clib_error_t * -hicn_cli_pgen_client_set_command_fn (vlib_main_t * vm, - unformat_input_t * main_input, - vlib_cli_command_t * cmd) -{ - hicnpg_main_t *hpgm = &hicnpg_main; - ip46_address_t src_addr; - fib_prefix_t *prefix = malloc (sizeof (fib_prefix_t)); - vnet_main_t *vnm = vnet_get_main (); - u32 sw_if_index = ~0; - u16 lifetime = 4000; - int rv = VNET_API_ERROR_UNIMPLEMENTED; - u32 max_seq = ~0; - u32 n_flows = ~0; - u32 n_ifaces = 1; - - /* Get a line of input. */ - unformat_input_t _line_input, *line_input = &_line_input; - if (unformat_user (main_input, unformat_line_input, line_input)) - { - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat - (line_input, "intfc %U", unformat_vnet_sw_interface, vnm, - &sw_if_index)) - { - ; - } - else if (unformat (line_input, "src %U", - unformat_ip46_address, &src_addr)) - { - ; - } - else if (unformat (line_input, "n_ifaces %d", &n_ifaces)) - { - ; - } - else if (unformat (line_input, "name %U/%d", - unformat_ip46_address, &prefix->fp_addr, - IP46_TYPE_ANY, &prefix->fp_len)) - { - ; - } - else if (unformat (line_input, "lifetime %d", &lifetime)) - { - ; - } - else if (unformat (line_input, "max_seq %d", &max_seq)) - { - ; - } - else if (unformat (line_input, "n_flows %d", &n_flows)) - { - ; - } - else - { - return (clib_error_return - (0, "Unknown input '%U'", format_unformat_error, - line_input)); - break; - } - } - } - hpgm->interest_lifetime = lifetime; - - if (sw_if_index == ~0) - { - return (clib_error_return (0, "Packet generator interface missing")); - } - - //Remove bits that are out of the subnet - 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; - } - 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; - } - - /* - * Enable the feature to divert data packet to the hicnpg-data node to count - * how many data packets have been received. - * Diver all the packets from the packet-generator to the hicn-pg-interest node - * to generate valid interests. - */ - if (ip46_address_is_ip4 (&src_addr) - && ip46_address_is_ip4 (&prefix->fp_addr)) - { - prefix->fp_proto = FIB_PROTOCOL_IP4; - - vnet_feature_enable_disable ("ip4-unicast", "hicnpg-data", - sw_if_index, 1, 0, 0); - - /* Add pgen_client node to the vpp graph */ - vlib_node_add_next (vm, - pg_input_node.index, hicn_pg_interest_node.index); - - - pg_node_t *pn; - pn = pg_get_node (hicn_pg_interest_node.index); - pn->unformat_edit = unformat_pg_ip4_header; - - } - else if (!ip46_address_is_ip4 (&src_addr) - && !ip46_address_is_ip4 (&prefix->fp_addr)) - { - prefix->fp_proto = FIB_PROTOCOL_IP6; - - vnet_feature_enable_disable ("ip6-unicast", "hicnpg-data", - sw_if_index, 1, 0, 0); - - /* Add pgen_client node to the vpp graph */ - vlib_node_add_next (vm, pg_input_node.index, - hicn_pg_interest_node.index); - - pg_node_t *pn; - pn = pg_get_node (hicn_pg_interest_node.index); - pn->unformat_edit = unformat_pg_ip6_header; - } - else - { - return (clib_error_return - (0, - "pg interface source address, source address and hicn name must be of the same type IPv4 or IPv6")); - } - - - hpgm->pgen_clt_src_addr = src_addr; - hpgm->pgen_clt_hicn_name = prefix; - hpgm->max_seq_number = max_seq; - hpgm->n_flows = n_flows; - hpgm->n_ifaces = n_ifaces; - hpgm->sw_if = sw_if_index; - vlib_cli_output (vm, "ifaces %d", hpgm->n_ifaces); - rv = 0; - - switch (rv) - { - case 0: - break; - - case VNET_API_ERROR_UNIMPLEMENTED: - return clib_error_return (0, "Unimplemented, NYI"); - break; - - default: - return clib_error_return (0, "hicn enable_disable returned %d", rv); - } - - return 0; -} - -/* - * cli handler for 'pgen' - */ -static clib_error_t * -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)); - - /* Get a line of input. */ - unformat_input_t _line_input, *line_input = &_line_input; - if (unformat_user (main_input, unformat_line_input, line_input)) - { - /* Parse the arguments */ - 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)) - {; - } - else if (unformat (line_input, "size %d", &payload_size)) - { - if (payload_size > 1440) - { - return (clib_error_return (0, - "Payload size must be <= 1440 bytes...")); - } - } - else - if (unformat - (line_input, "intfc %U", unformat_vnet_sw_interface, vnm, - &sw_if_index)) - { - ; - } - else - { - return (clib_error_return - (0, "Unknown input '%U'", format_unformat_error, - line_input)); - break; - } - } - } - - /* 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) - { - return clib_error_return (0, - "Error: must supply local port, payload size and incoming hICN prefix"); - } - - //Remove bits that are out of the subnet - 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; - } - 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; - } - - /* 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) - { - return (clib_error_return (0, "Impossible to allocate paylod buffer.")); - } - - 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; -} - -static clib_error_t * -hicn_enable_command_fn (vlib_main_t * vm, unformat_input_t * main_input, - vlib_cli_command_t * cmd) -{ - clib_error_t *cl_err = 0; - - int rv = HICN_ERROR_NONE; - fib_prefix_t pfx; - - /* Get a line of input. */ - unformat_input_t _line_input, *line_input = &_line_input; - if (!unformat_user (main_input, unformat_line_input, line_input)) - { - return (0); - } - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "%U/%d", - unformat_ip4_address, &pfx.fp_addr.ip4, &pfx.fp_len)) - { - pfx.fp_proto = FIB_PROTOCOL_IP4; - } - else if (unformat (line_input, "%U/%d", - unformat_ip6_address, &pfx.fp_addr.ip6, &pfx.fp_len)) - { - pfx.fp_proto = FIB_PROTOCOL_IP6; - } - else - { - cl_err = clib_error_return (0, "%s '%U'", - get_error_string (HICN_ERROR_CLI_INVAL), - format_unformat_error, line_input); - goto done; - } - } - rv = hicn_route_enable (&pfx); -done: - - cl_err = - (rv == HICN_ERROR_NONE) ? NULL : clib_error_return (0, - get_error_string - (rv)); - return cl_err; -} - -static clib_error_t * -hicn_disable_command_fn (vlib_main_t * vm, unformat_input_t * main_input, - vlib_cli_command_t * cmd) -{ - clib_error_t *cl_err = 0; - - int rv = HICN_ERROR_NONE; - fib_prefix_t pfx; - - /* Get a line of input. */ - unformat_input_t _line_input, *line_input = &_line_input; - if (!unformat_user (main_input, unformat_line_input, line_input)) - { - return (0); - } - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "%U/%d", - unformat_ip4_address, &pfx.fp_addr.ip4, &pfx.fp_len)) - { - pfx.fp_proto = FIB_PROTOCOL_IP4; - } - else if (unformat (line_input, "%U/%d", - unformat_ip6_address, &pfx.fp_addr.ip6, &pfx.fp_len)) - { - pfx.fp_proto = FIB_PROTOCOL_IP6; - } - else - { - cl_err = clib_error_return (0, "%s '%U'", - get_error_string (HICN_ERROR_CLI_INVAL), - format_unformat_error, line_input); - goto done; - } - } - - rv = hicn_route_disable (&pfx); - -done: - cl_err = - (rv == HICN_ERROR_NONE) ? NULL : clib_error_return (0, - get_error_string - (rv)); - return cl_err; -} - - -/* cli declaration for 'control start' */ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND(hicn_cli_node_ctl_start_set_command, static)= -{ - .path = "hicn control start", - .short_help = "hicn control start", - .function = hicn_cli_node_ctl_start_set_command_fn, -}; - - -/* cli declaration for 'control stop' */ -VLIB_CLI_COMMAND(hicn_cli_node_ctl_stop_set_command, static)= -{ - .path = "hicn control stop", - .short_help = "hicn control stop", - .function = hicn_cli_node_ctl_stop_set_command_fn, -}; - - -/* cli declaration for 'control param' */ -VLIB_CLI_COMMAND(hicn_cli_node_ctl_param_set_command, static)= -{ - .path = "hicn control param", - .short_help = "hicn control param { pit { size | { dfltlife | minlife | maxlife } } | fib size | cs {size | app } }\n", - .function = hicn_cli_node_ctl_param_set_command_fn, -}; - -/* cli declaration for 'control' (root path of multiple commands, for help) */ -VLIB_CLI_COMMAND(hicn_cli_node_ctl_command, static)= -{ - .path = "hicn control", - .short_help = "hicn control" -}; - -/* cli declaration for 'fib' */ -VLIB_CLI_COMMAND(hicn_cli_strategy_set_command, static)= - { - .path = "hicn strategy", - .short_help = "hicn strategy set prefix ", - .function = hicn_cli_strategy_set_command_fn, - }; - -/* cli declaration for 'show' */ -VLIB_CLI_COMMAND(hicn_cli_show_command, static)= -{ - .path = "hicn show", - .short_help = "hicn show " - "[internal]" - "[strategies]", - .function = hicn_cli_show_command_fn, -}; - -/* cli declaration for 'hicn pgen client' */ -VLIB_CLI_COMMAND(hicn_cli_pgen_client_set_command, static)= -{ - .path = "hicn pgen client", - .short_help = "hicn pgen client src name { n_ifaces lifetime intfc max_seq n_flows }", - .long_help = "Run hicn in packet-gen client mode\n", - .function = hicn_cli_pgen_client_set_command_fn, -}; - -/* cli declaration for 'hicn pgen client' */ -VLIB_CLI_COMMAND(hicn_cli_pgen_server_set_command, static)= -{ - .path = "hicn pgen server", - .short_help = "hicn pgen server name intfc size ", - .long_help = "Run hicn in packet-gen server mode\n", - .function = hicn_cli_pgen_server_set_command_fn, -}; - -/* cli declaration for 'hicn pgen client' */ -VLIB_CLI_COMMAND(hicn_enable_command, static)= - { - .path = "hicn enable", - .short_help = "hicn enable ", - .long_help = "Enable hicn for the give prefix\n", - .function = hicn_enable_command_fn, - }; - -/* cli declaration for 'hicn pgen client' */ -VLIB_CLI_COMMAND(hicn_disable_command, static)= - { - .path = "hicn disable", - .short_help = "hicn disable ", - .long_help = "Disable hicn for the give prefix\n", - .function = hicn_disable_command_fn, - }; - -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/data_fwd.h b/hicn-plugin/src/data_fwd.h deleted file mode 100644 index d95f564c3..000000000 --- a/hicn-plugin/src/data_fwd.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_DATA_FWD_H__ -#define __HICN_DATA_FWD_H__ - -#include - -#include "pcs.h" - -/** - * @file data_fwd.h - * - * This is the node encoutered by data packets after the hicn-data-pcslookup. - * This node has two goals: 1) clone/copy the vlib buffer as many time as the number - * of faces stored in the pit entry, 2) store a clone/copy of the vlib buffer in the CS. - * Unless there are memory issue (no more vlib buffer available to perform cloning/copy), - * a single vlib buffer received might results in several vlib buffer sent to the next - * vlib node (hicn4-iface-output or hicn6-iface-output). - * - * It must be noted that cloning is possible only if the lentgh of the data pointed by - * the vlib buffer is at least 256 bytes. This is due to an imposition in the vpp source - * code. In all the other cases the vlib buffer is copied. Cloning is performed by advancing - * the vlib buffer of 256 bytes and a new vlib buffer is created and chained in from of the received - * buffer. Additionally, the 256 bytes removed (advanced) from the received vlib buffer are - * copied in the head vlib buffer. In case of multiple cloning for the same vlib buffer, this - * mechanism allows us to have a different hICN header for each clone (+ the same additional bytes - * due to the vpp restriction on cloning). - */ - - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - u8 packet_data[64]; -} hicn_data_fwd_trace_t; - -typedef enum -{ - HICN_DATA_FWD_NEXT_V4_LOOKUP, - HICN_DATA_FWD_NEXT_V6_LOOKUP, - HICN_DATA_FWD_NEXT_IFACE4_OUT, - HICN_DATA_FWD_NEXT_IFACE6_OUT, - HICN_DATA_FWD_NEXT_ERROR_DROP, - HICN_DATA_FWD_N_NEXT, -} hicn_data_fwd_next_t; - -/** - * @brief Create a maximum of 256 clones of buffer and store them - * in the supplied array. Unlike the original function in the vlib - * library, we don't prevent cloning if n_buffer==1 and if - * s->current_length <= head_end_offset + CLIB_CACHE_LINE_BYTES * 2. - * - * @param vm - (vlib_main_t *) vlib main data structure pointer - * @param src_buffer - (u32) source buffer index - * @param buffers - (u32 * ) buffer index array - * @param n_buffers - (u16) number of buffer clones requested (<=256) - * @param head_end_offset - (u16) offset relative to current position - * where packet head ends - * @return - (u16) number of buffers actually cloned, may be - * less than the number requested or zero - */ -always_inline u16 -vlib_buffer_clone_256_2 (vlib_main_t * vm, u32 src_buffer, u32 * buffers, - u16 n_buffers, u16 head_end_offset) -{ - u16 i; - vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer); - - ASSERT (n_buffers); - ASSERT (n_buffers <= 256); - - if (s->current_length <= head_end_offset + CLIB_CACHE_LINE_BYTES * 2) - { - for (i = 0; i < n_buffers; i++) - { - vlib_buffer_t *d; - d = vlib_buffer_copy (vm, s); - if (d == 0) - return i; - buffers[i] = vlib_get_buffer_index (vm, d); - } - return n_buffers; - } - n_buffers = vlib_buffer_alloc_from_pool (vm, buffers, n_buffers, - s->buffer_pool_index); - - for (i = 0; i < n_buffers; i++) - { - vlib_buffer_t *d = vlib_get_buffer (vm, buffers[i]); - d->current_data = s->current_data; - d->current_length = head_end_offset; - d->trace_handle = s->trace_handle; - - d->total_length_not_including_first_buffer = s->current_length - - head_end_offset; - if (PREDICT_FALSE (s->flags & VLIB_BUFFER_NEXT_PRESENT)) - { - d->total_length_not_including_first_buffer += - s->total_length_not_including_first_buffer; - } - d->flags = s->flags | VLIB_BUFFER_NEXT_PRESENT; - d->flags &= ~VLIB_BUFFER_EXT_HDR_VALID; - d->trace_handle = s->trace_handle; - clib_memcpy_fast (d->opaque, s->opaque, sizeof (s->opaque)); - clib_memcpy_fast (d->opaque2, s->opaque2, sizeof (s->opaque2)); - clib_memcpy_fast (vlib_buffer_get_current (d), - vlib_buffer_get_current (s), head_end_offset); - d->next_buffer = src_buffer; - } - vlib_buffer_advance (s, head_end_offset); - s->ref_count = n_buffers; - while (s->flags & VLIB_BUFFER_NEXT_PRESENT) - { - s = vlib_get_buffer (vm, s->next_buffer); - s->ref_count = n_buffers; - } - - return n_buffers; -} - -/** - * @brief Create multiple clones of buffer and store them - * in the supplied array. Unlike the function in the vlib library, - * we allow src_buffer to have ref_count != 0. - * - * @param vm - (vlib_main_t *) vlib main data structure pointer - * @param src_buffer - (u32) source buffer index - * @param buffers - (u32 * ) buffer index array - * @param n_buffers - (u16) number of buffer clones requested (<=256) - * @param head_end_offset - (u16) offset relative to current position - * where packet head ends - * @return - (u16) number of buffers actually cloned, may be - * less than the number requested or zero - */ -always_inline u16 -vlib_buffer_clone2 (vlib_main_t * vm, u32 src_buffer, u32 * buffers, - u16 n_buffers, u16 head_end_offset) -{ - vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer); - - /* - * total_length_not_including_first_buffer is not initialized to 0 - * when a buffer is used. - */ - if (PREDICT_TRUE (s->next_buffer == 0)) - s->total_length_not_including_first_buffer = 0; - - u16 n_cloned = 0; - u8 n_clone_src = 255 - s->ref_count; - - /* - * We need to copy src for all the clones that cannot be chained in - * the src_buffer - */ - /* MAX(ref_count) = 256 */ - if (n_buffers > n_clone_src) - { - vlib_buffer_t *copy; - /* Ok to call the original vlib_buffer_copy. */ - copy = vlib_buffer_copy (vm, s); - n_cloned += vlib_buffer_clone (vm, - vlib_get_buffer_index (vm, copy), - buffers, - n_buffers - n_clone_src, - head_end_offset); - n_buffers -= n_cloned; - } - /* - * vlib_buffer_clone_256 check if ref_count is 0. We force it to be - * 0 before calling the function and we retore it to the right value - * after the function has been called - */ - u8 tmp_ref_count = s->ref_count; - - s->ref_count = 1; - /* - * The regular vlib_buffer_clone_256 does copy if we need to clone - * only one packet. While this is not a problem per se, it adds - * complexity to the code, especially because we need to add 1 to - * ref_count when the packet is cloned. - */ - n_cloned += vlib_buffer_clone_256_2 (vm, - src_buffer, - (buffers + n_cloned), - n_buffers, head_end_offset); - - s->ref_count += (tmp_ref_count - 1); - - return n_cloned; -} - -#endif /* //__HICN_DATA_FWD_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/data_fwd_node.c b/hicn-plugin/src/data_fwd_node.c deleted file mode 100644 index c65b62454..000000000 --- a/hicn-plugin/src/data_fwd_node.c +++ /dev/null @@ -1,620 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "data_fwd.h" -#include "mgmt.h" -#include "parser.h" -#include "infra.h" -#include "strategy.h" -#include "strategy_dpo_manager.h" -#include "state.h" -#include "error.h" - -/* Stats string values */ -static char *hicn_data_fwd_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -/* Declarations */ -always_inline void -drop_packet (vlib_main_t * vm, u32 bi0, - u32 * n_left_to_next, u32 * next0, u32 ** to_next, - u32 * next_index, vlib_node_runtime_t * node); - -always_inline int -hicn_satisfy_faces (vlib_main_t * vm, u32 b0, - hicn_pcs_entry_t * pitp, u32 * n_left_to_next, - u32 ** to_next, u32 * next_index, - vlib_node_runtime_t * node, u8 isv6, - vl_api_hicn_api_node_stats_get_reply_t * stats); - -always_inline void -clone_data_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t * pitp, hicn_header_t * hicn0, f64 tnow, - hicn_hash_node_t * nodep, vlib_buffer_t * b0, - hicn_hash_entry_t * hash_entry, u64 name_hash, - hicn_buffer_t * hicnb, const hicn_dpo_vft_t * dpo_vft, - dpo_id_t * hicn_dpo_id, hicn_lifetime_t dmsg_lifetime); - - -/* packet trace format function */ -always_inline u8 *hicn_data_fwd_format_trace (u8 * s, va_list * args); - -vlib_node_registration_t hicn_data_fwd_node; - -/* - * ICN forwarder node for interests: handling of Data delivered based on ACL. - * - 1 packet at a time - ipv4/tcp ipv6/tcp - */ -static uword -hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - - u32 n_left_from, *from, *to_next; - hicn_data_fwd_next_t next_index; - hicn_pit_cs_t *pitcs = &hicn_main.pitcs; - vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; - f64 tnow; - u32 data_received = 1; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - /* Capture time in vpp terms */ - tnow = vlib_time_now (vm); - - while (n_left_from > 0) - { - u32 n_left_to_next; - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *b0; - u8 isv6; - u8 *nameptr; - u16 namelen; - u32 bi0; - u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP; - hicn_name_t name; - hicn_header_t *hicn0; - hicn_buffer_t *hicnb0; - hicn_hash_node_t *node0; - const hicn_strategy_vft_t *strategy_vft0; - const hicn_dpo_vft_t *dpo_vft0; - u8 dpo_ctx_id0; - hicn_pcs_entry_t *pitp; - hicn_hash_entry_t *hash_entry0; - int ret = HICN_ERROR_NONE; - - /* Prefetch for next iteration. */ - if (n_left_from > 1) - { - vlib_buffer_t *b1; - b1 = vlib_get_buffer (vm, from[1]); - CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, STORE); - CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, STORE); - } - /* Dequeue a packet buffer */ - /* - * Do not copy the index in the next buffer, we'll do - * it later. The packet might be cloned, so the buffer to move - * to next must be the cloned one - */ - bi0 = from[0]; - from += 1; - n_left_from -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - /* Get hicn buffer and state */ - hicnb0 = hicn_get_buffer (b0); - 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); - 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))) - { - /* - * Remove the lock acquired from - * data_pcslookup node - */ - dpo_id_t hicn_dpo_id0 = { dpo_vft0->hicn_dpo_get_type (), 0, 0, - dpo_ctx_id0 - }; - hicn_pcs_remove_lock (pitcs, &pitp, &node0, vm, - hash_entry0, dpo_vft0, &hicn_dpo_id0); - - drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next, - &next_index, node); - - goto end_processing; - } - /* - * Check if the hit is instead a collision in the - * hash table. Unlikely to happen. - */ - /* - * there is no guarantee that the type of entry has - * not changed from the lookup. - */ - - if (tnow > pitp->shared.expire_time - || (hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED)) - { - dpo_id_t hicn_dpo_id0 = - { dpo_vft0->hicn_dpo_get_type (), 0, 0, dpo_ctx_id0 }; - hicn_pcs_delete (pitcs, &pitp, &node0, vm, hash_entry0, - dpo_vft0, &hicn_dpo_id0); - - drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next, - &next_index, node); - stats.pit_expired_count++; - - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - hicn_data_fwd_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; - t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - t->next_index = next0; - clib_memcpy (t->packet_data, - vlib_buffer_get_current (b0), - sizeof (t->packet_data)); - } - } - else - { - ASSERT ((hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED) - == 0); - - data_received++; - /* - * We do not check if the data is coming from - * the outgoing interest face. - */ - - /* Prepare the buffer for the cloning */ - ret = hicn_satisfy_faces (vm, bi0, pitp, &n_left_to_next, - &to_next, &next_index, node, - isv6, &stats); - - dpo_id_t hicn_dpo_id0 = { dpo_vft0->hicn_dpo_get_type (), 0, 0, - dpo_ctx_id0 - }; - - if (PREDICT_FALSE (ret != HICN_ERROR_NONE)) - { - hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, - hash_entry0, dpo_vft0, &hicn_dpo_id0); - continue; - } - /* - * Call the strategy callback since the - * interest has been satisfied - */ - strategy_vft0->hicn_receive_data (dpo_ctx_id0, - pitp->u.pit.pe_txnh); - -#if HICN_FEATURE_CS - hicn_lifetime_t dmsg_lifetime; - - hicn_type_t type = hicnb0->type; - hicn_ops_vft[type.l1]->get_lifetime (type, &hicn0->protocol, - &dmsg_lifetime); - - if (dmsg_lifetime) - { - /* - * Clone data packet in the content store and - * convert the PIT entry into a CS entry - */ - clone_data_to_cs (vm, pitcs, pitp, hicn0, tnow, node0, - b0, hash_entry0, hicnb0->name_hash, - hicnb0, dpo_vft0, &hicn_dpo_id0, - dmsg_lifetime); - - hicn_pcs_remove_lock (pitcs, &pitp, &node0, vm, - hash_entry0, NULL, NULL); - } - else - { - /* - * If the packet is copied and not cloned, we need to free the vlib_buffer - */ - if (hicnb0->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL) - { - vlib_buffer_free_one (vm, bi0); - } - else - { - /* - * Remove one reference as the buffer is no - * longer in any frame. The vlib_buffer will be freed when - * all its cloned vlib_buffer will be freed. - */ - b0->ref_count--; - } - - /* Delete the PIT entry */ - hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, - hash_entry0, dpo_vft0, &hicn_dpo_id0); - } -#else - ASSERT (pitp == hicn_pit_get_data (node0)); - /* - * If the packet is copied and not cloned, we need to free the vlib_buffer - */ - if (hicnb0->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL) - { - vlib_buffer_free_one (vm, bi0); - } - else - { - /* - * Remove one reference as the buffer is no - * longer in any frame. The vlib_buffer will be freed when - * all its cloned vlib_buffer will be freed. - */ - b0->ref_count--; - } - - /* Delete the PIT entry */ - hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, - hash_entry0, dpo_vft0, &hicn_dpo_id0); -#endif - } - end_processing: - - /* Incr packet counter */ - stats.pkts_processed += 1; - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - u32 pit_int_count = hicn_pit_get_int_count (pitcs); - u32 pit_cs_count = hicn_pit_get_cs_count (pitcs); - - vlib_node_increment_counter (vm, hicn_data_fwd_node.index, - HICNFWD_ERROR_DATAS, stats.pkts_data_count); - - - update_node_counter (vm, hicn_data_fwd_node.index, - HICNFWD_ERROR_INT_COUNT, pit_int_count); - update_node_counter (vm, hicn_data_fwd_node.index, - HICNFWD_ERROR_CS_COUNT, pit_cs_count); - update_node_counter (vm, hicn_data_fwd_node.index, - HICNFWD_ERROR_INTEREST_AGG_ENTRY, - stats.pkts_data_count / data_received); - - return (frame->n_vectors); -} - -always_inline void -drop_packet (vlib_main_t * vm, u32 bi0, - u32 * n_left_to_next, u32 * next0, u32 ** to_next, - u32 * next_index, vlib_node_runtime_t * node) -{ - *next0 = HICN_DATA_FWD_NEXT_ERROR_DROP; - - (*to_next)[0] = bi0; - *to_next += 1; - *n_left_to_next -= 1; - - vlib_validate_buffer_enqueue_x1 (vm, node, *next_index, - *to_next, *n_left_to_next, bi0, *next0); -} - -always_inline int -hicn_satisfy_faces (vlib_main_t * vm, u32 bi0, - hicn_pcs_entry_t * pitp, u32 * n_left_to_next, - u32 ** to_next, u32 * next_index, - vlib_node_runtime_t * node, u8 isv6, - vl_api_hicn_api_node_stats_get_reply_t * stats) -{ - int found = 0; - int ret = HICN_ERROR_NONE; - u32 *clones = NULL, *header = NULL; - u32 n_left_from = 0; - u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP, next1 = - HICN_DATA_FWD_NEXT_ERROR_DROP; - word buffer_advance = CLIB_CACHE_LINE_BYTES * 2; - - /* - * We have a hard limit on the number of vlib_buffer that we can - * chain (no more than 256) - */ - /* - * The first group of vlib_buffer can be directly cloned from b0. We - * need to be careful to clone it only 254 times as the buffer - * already has n_add_reds=1. - */ - vec_alloc (clones, pitp->u.pit.faces.n_faces); - header = clones; - - /* Clone bi0 */ - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0); - - hicn_buffer_t *hicnb = hicn_get_buffer (b0); - - /* - * Mark the buffer as smaller than TWO_CL. It will be stored as is in the CS, without excluding - * the hicn_header. Cloning is not possible, it will be copied. - */ - if (b0->current_length <= (buffer_advance + (CLIB_CACHE_LINE_BYTES * 2))) - { - /* In this case the packet is copied. We don't need to add a reference as no buffer are - * chained to it. - */ - hicnb->flags |= HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL; - } - else - { - /* Add one reference to maintain the buffer in the CS. - * b0->ref_count == 0 has two meaning: it has 1 buffer or no buffer chained to it. - * vlib_buffer_clone2 add a number of reference equalt to pitp->u.pit.faces.n_faces - 1 - * as vlib_buffer_clone does. So after all the packet are forwarded the buffer stored in - * the CS will have ref_count == 0; - */ - b0->ref_count++; - } - - found = n_left_from = - vlib_buffer_clone2 (vm, bi0, clones, pitp->u.pit.faces.n_faces, - buffer_advance); - - ASSERT (n_left_from == pitp->u.pit.faces.n_faces); - - /* Index to iterate over the faces */ - int i = 0; - - while (n_left_from > 0) - { - - //Dual loop, X2 - while (n_left_from >= 4 && *n_left_to_next >= 2) - { - vlib_buffer_t *h0, *h1; - u32 hi0, hi1; - hicn_face_id_t face0, face1; - - /* Prefetch for next iteration. */ - { - vlib_buffer_t *h2, *h3; - h2 = vlib_get_buffer (vm, clones[2]); - h3 = vlib_get_buffer (vm, clones[3]); - CLIB_PREFETCH (h2, 2 * CLIB_CACHE_LINE_BYTES, STORE); - CLIB_PREFETCH (h3, 2 * CLIB_CACHE_LINE_BYTES, STORE); - } - - face0 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces); - face1 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces); - - h0 = vlib_get_buffer (vm, clones[0]); - h1 = vlib_get_buffer (vm, clones[1]); - - (*to_next)[0] = hi0 = clones[0]; - (*to_next)[1] = hi1 = clones[1]; - *to_next += 2; - *n_left_to_next -= 2; - n_left_from -= 2; - clones += 2; - - next0 = isv6 ? HICN_DATA_FWD_NEXT_IFACE6_OUT : - HICN_DATA_FWD_NEXT_IFACE4_OUT; - next1 = isv6 ? HICN_DATA_FWD_NEXT_IFACE6_OUT : - HICN_DATA_FWD_NEXT_IFACE4_OUT; - - vnet_buffer (h0)->ip.adj_index[VLIB_TX] = face0; - vnet_buffer (h1)->ip.adj_index[VLIB_TX] = face1; - - stats->pkts_data_count += 2; - - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (h0->flags & VLIB_BUFFER_IS_TRACED))) - { - hicn_data_fwd_trace_t *t = - vlib_add_trace (vm, node, h0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; - 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), - sizeof (t->packet_data)); - } - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (h1->flags & VLIB_BUFFER_IS_TRACED))) - { - hicn_data_fwd_trace_t *t = - vlib_add_trace (vm, node, h1, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; - 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), - sizeof (t->packet_data)); - } - vlib_validate_buffer_enqueue_x2 (vm, node, *next_index, - (*to_next), *n_left_to_next, - hi0, hi1, next0, next1); - } - - - while (n_left_from > 0 && *n_left_to_next > 0) - { - vlib_buffer_t *h0; - u32 hi0; - hicn_face_id_t face0; - - face0 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces); - - h0 = vlib_get_buffer (vm, clones[0]); - - (*to_next)[0] = hi0 = clones[0]; - *to_next += 1; - *n_left_to_next -= 1; - n_left_from -= 1; - clones += 1; - - next0 = isv6 ? HICN_DATA_FWD_NEXT_IFACE6_OUT : - HICN_DATA_FWD_NEXT_IFACE4_OUT; - vnet_buffer (h0)->ip.adj_index[VLIB_TX] = face0; - - stats->pkts_data_count++; - - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (h0->flags & VLIB_BUFFER_IS_TRACED))) - { - hicn_data_fwd_trace_t *t = - vlib_add_trace (vm, node, h0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; - 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), - sizeof (t->packet_data)); - } - /* - * Verify speculative enqueue, maybe switch current - * next frame - */ - /* - * Fix in case of a wrong speculation. Needed to - * clone the data in the right frame - */ - vlib_validate_buffer_enqueue_x1 (vm, node, *next_index, - *to_next, *n_left_to_next, - hi0, next0); - - } - - /* Ensure that there is space for the next clone (if any) */ - if (PREDICT_FALSE (*n_left_to_next == 0)) - { - vlib_put_next_frame (vm, node, *next_index, *n_left_to_next); - - vlib_get_next_frame (vm, node, *next_index, *to_next, - *n_left_to_next); - } - } - - vec_free (header); - - if (PREDICT_FALSE (!found)) - { - ASSERT (0); - drop_packet (vm, bi0, n_left_to_next, &next0, to_next, next_index, - node); - ret = HICN_ERROR_FACE_NOT_FOUND; - } - return ret; -} - -always_inline void -clone_data_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t * pitp, hicn_header_t * hicn0, f64 tnow, - hicn_hash_node_t * nodep, vlib_buffer_t * b0, - hicn_hash_entry_t * hash_entry, u64 name_hash, - hicn_buffer_t * hicnb, const hicn_dpo_vft_t * dpo_vft, - dpo_id_t * hicn_dpo_id, hicn_lifetime_t dmsg_lifetime) -{ - /* - * At this point we think we're safe to proceed. Store the CS buf in - * the PIT/CS hashtable entry - */ - - /* - * Start turning the PIT into a CS. Note that we may be stepping on - * the PIT part of the union as we update the CS part, so don't - * expect the PIT part to be valid after this point. - */ - hicn_buffer_t *hicnb0 = hicn_get_buffer (b0); - hicn_pit_to_cs (vm, pitcs, pitp, hash_entry, nodep, dpo_vft, hicn_dpo_id, - hicnb->face_id, - hicnb0->flags & HICN_BUFFER_FLAGS_FACE_IS_APP); - - pitp->shared.create_time = tnow; - - if (dmsg_lifetime < HICN_PARAM_CS_LIFETIME_MIN - || dmsg_lifetime > HICN_PARAM_CS_LIFETIME_MAX) - { - dmsg_lifetime = HICN_PARAM_CS_LIFETIME_DFLT; - } - pitp->shared.expire_time = hicn_pcs_get_exp_time (tnow, dmsg_lifetime); - - /* Store the original packet buffer in the CS node */ - pitp->u.cs.cs_pkt_buf = vlib_get_buffer_index (vm, b0); -} - -/* packet trace format function */ -always_inline u8 * -hicn_data_fwd_format_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 *); - hicn_data_fwd_trace_t *t = va_arg (*args, hicn_data_fwd_trace_t *); - u32 indent = format_get_indent (s); - - s = format (s, "DATAFWD: pkt: %d, sw_if_index %d, next index %d\n", - (int) t->pkt_type, t->sw_if_index, t->next_index); - - s = format (s, "%U%U", format_white_space, indent, - format_ip6_header, t->packet_data, sizeof (t->packet_data)); - return (s); -} - -/* - * Node registration for the data forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(hicn_data_fwd_node) = -{ - .function = hicn_data_node_fn, - .name = "hicn-data-fwd", - .vector_size = sizeof(u32), - .format_trace = hicn_data_fwd_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(hicn_data_fwd_error_strings), - .error_strings = hicn_data_fwd_error_strings, - .n_next_nodes = HICN_DATA_FWD_N_NEXT, - /* edit / add dispositions here */ - .next_nodes = { - [HICN_DATA_FWD_NEXT_V4_LOOKUP] = "ip4-lookup", - [HICN_DATA_FWD_NEXT_V6_LOOKUP] = "ip6-lookup", - [HICN_DATA_FWD_NEXT_IFACE4_OUT] = "hicn4-iface-output", - [HICN_DATA_FWD_NEXT_IFACE6_OUT] = "hicn6-iface-output", - [HICN_DATA_FWD_NEXT_ERROR_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/data_input_node.c b/hicn-plugin/src/data_input_node.c deleted file mode 100644 index 8d20f54a6..000000000 --- a/hicn-plugin/src/data_input_node.c +++ /dev/null @@ -1,697 +0,0 @@ -/* - * Copyright (c) 2020 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 /* for FIB table and entry creation */ -#include /* for FIB table and entry creation */ -#include -#include - -#include "mgmt.h" -#include "strategy_dpo_manager.h" - -static __clib_unused char *hicn_data_input_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -typedef struct -{ - u32 next_index; - u32 sw_if_index; -} hicn_data_input_t; - -typedef enum -{ - HICN_DATA_INPUT_IP6_NEXT_FACE, - HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL, - HICN_DATA_INPUT_IP6_N_NEXT, -} hicn_data_input_ip6_next_t; - -typedef enum -{ - HICN_DATA_INPUT_IP4_NEXT_FACE, - HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL, - HICN_DATA_INPUT_IP4_N_NEXT, -} hicn_data_input_ip4_next_t; - -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 isv6; -} hicn_data_input_trace_t; - -vlib_node_registration_t hicn_data_input_ip6_node; -vlib_node_registration_t hicn_data_input_ip4_node; - -static __clib_unused u8 * -format_hicn_data_input_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 *); - hicn_data_input_trace_t *t = va_arg (*args, hicn_data_input_trace_t *); - u32 indent = format_get_indent (s); - u8 isv6 = (u8) va_arg (*args, int); - - s = - format (s, "%U hicn_data_input%s: sw_if_index %d next-index %d", - format_white_space, indent, isv6 ? "_ip6" : "_ip4", - t->sw_if_index, t->next_index); - return s; -} - -static uword -hicn_data_input_ip6_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) -{ - ip6_main_t *im = &ip6_main; - vlib_combined_counter_main_t *cm = &load_balance_main.lbm_to_counters; - u32 n_left_from, n_left_to_next, *from, *to_next; - ip_lookup_next_t next; - u32 thread_index = vm->thread_index; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next = node->cached_next_index; - - while (n_left_from > 0) - { - vlib_get_next_frame (vm, node, next, to_next, n_left_to_next); - - while (n_left_from >= 4 && n_left_to_next >= 2) - { - vlib_buffer_t *p0, *p1; - u32 pi0, pi1, lbi0, lbi1, wrong_next; - ip_lookup_next_t next0, next1; - ip6_header_t *ip0, *ip1; - ip6_address_t *src_addr0, *src_addr1; - const dpo_id_t *dpo0, *dpo1; - const load_balance_t *lb0, *lb1; - - /* 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, sizeof (ip0[0]), LOAD); - CLIB_PREFETCH (p3->data, sizeof (ip0[0]), LOAD); - } - - pi0 = to_next[0] = from[0]; - pi1 = to_next[1] = from[1]; - - p0 = vlib_get_buffer (vm, pi0); - p1 = vlib_get_buffer (vm, pi1); - - ip0 = vlib_buffer_get_current (p0); - ip1 = vlib_buffer_get_current (p1); - - src_addr0 = &ip0->src_address; - src_addr1 = &ip1->src_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); - - lbi0 = ip6_fib_table_fwding_lookup (vnet_buffer (p0)->ip.fib_index, - src_addr0); - lbi1 = ip6_fib_table_fwding_lookup (vnet_buffer (p1)->ip.fib_index, - src_addr1); - - lb0 = load_balance_get (lbi0); - lb1 = load_balance_get (lbi1); - ASSERT (lb0->lb_n_buckets > 0); - ASSERT (lb1->lb_n_buckets > 0); - ASSERT (is_pow2 (lb0->lb_n_buckets)); - ASSERT (is_pow2 (lb1->lb_n_buckets)); - - vnet_buffer (p0)->ip.flow_hash = vnet_buffer (p1)->ip.flow_hash = 0; - - //No vpp loadbalancing. Missing header file to exploit it - dpo0 = load_balance_get_bucket_i (lb0, 0); - dpo1 = load_balance_get_bucket_i (lb1, 0); - - if (dpo_is_hicn (dpo0)) - next0 = HICN_DATA_INPUT_IP6_NEXT_FACE; - else - next0 = HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL; - - if (dpo_is_hicn (dpo1)) - next1 = HICN_DATA_INPUT_IP6_NEXT_FACE; - else - next1 = HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL; - - if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && - (p0->flags & VLIB_BUFFER_IS_TRACED)) - { - hicn_data_input_trace_t *t = - vlib_add_trace (vm, node, p0, sizeof (*t)); - t->sw_if_index = vnet_buffer (p0)->sw_if_index[VLIB_RX]; - t->next_index = next0; - t->isv6 = 1; - } - - if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && - (p1->flags & VLIB_BUFFER_IS_TRACED)) - { - hicn_data_input_trace_t *t = - vlib_add_trace (vm, node, p1, sizeof (*t)); - t->sw_if_index = vnet_buffer (p1)->sw_if_index[VLIB_RX]; - t->next_index = next1; - t->isv6 = 1; - } - - - vlib_increment_combined_counter - (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); - vlib_increment_combined_counter - (cm, thread_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1)); - - from += 2; - to_next += 2; - n_left_to_next -= 2; - n_left_from -= 2; - - wrong_next = (next0 != next) + 2 * (next1 != next); - if (PREDICT_FALSE (wrong_next != 0)) - { - switch (wrong_next) - { - case 1: - /* A B A */ - to_next[-2] = pi1; - to_next -= 1; - n_left_to_next += 1; - vlib_set_next_frame_buffer (vm, node, next0, pi0); - break; - - case 2: - /* A A B */ - to_next -= 1; - n_left_to_next += 1; - vlib_set_next_frame_buffer (vm, node, next1, pi1); - break; - - case 3: - /* A B C */ - to_next -= 2; - n_left_to_next += 2; - vlib_set_next_frame_buffer (vm, node, next0, pi0); - vlib_set_next_frame_buffer (vm, node, next1, pi1); - if (next0 == next1) - { - /* A B B */ - vlib_put_next_frame (vm, node, next, n_left_to_next); - next = next1; - vlib_get_next_frame (vm, node, next, to_next, - n_left_to_next); - } - } - } - } - - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *p0; - ip6_header_t *ip0; - u32 pi0, lbi0; - ip_lookup_next_t next0; - load_balance_t *lb0; - ip6_address_t *src_addr0; - const dpo_id_t *dpo0; - - pi0 = from[0]; - to_next[0] = pi0; - - p0 = vlib_get_buffer (vm, pi0); - ip0 = vlib_buffer_get_current (p0); - src_addr0 = &ip0->src_address; - ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, p0); - lbi0 = ip6_fib_table_fwding_lookup (vnet_buffer (p0)->ip.fib_index, - src_addr0); - - lb0 = load_balance_get (lbi0); - ASSERT (lb0->lb_n_buckets > 0); - ASSERT (is_pow2 (lb0->lb_n_buckets)); - - //No vpp loadbalancing. Missing header file to exploit it - dpo0 = load_balance_get_bucket_i (lb0, 0); - - if (dpo_is_hicn (dpo0)) - next0 = HICN_DATA_INPUT_IP6_NEXT_FACE; - else - next0 = HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL; - - if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && - (p0->flags & VLIB_BUFFER_IS_TRACED)) - { - hicn_data_input_trace_t *t = - vlib_add_trace (vm, node, p0, sizeof (*t)); - t->sw_if_index = vnet_buffer (p0)->sw_if_index[VLIB_RX]; - t->next_index = next0; - t->isv6 = 1; - } - - vlib_increment_combined_counter - (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); - - from += 1; - to_next += 1; - n_left_to_next -= 1; - n_left_from -= 1; - - if (PREDICT_FALSE (next0 != next)) - { - n_left_to_next += 1; - vlib_put_next_frame (vm, node, next, n_left_to_next); - next = next0; - vlib_get_next_frame (vm, node, next, to_next, n_left_to_next); - to_next[0] = pi0; - to_next += 1; - n_left_to_next -= 1; - } - } - - vlib_put_next_frame (vm, node, next, n_left_to_next); - } - - return frame->n_vectors; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(hicn_data_input_ip6) = - { - .function = hicn_data_input_ip6_fn, - .name = "hicn-data-input-ip6", - .vector_size = sizeof(u32), - .format_trace = format_hicn_data_input_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(hicn_data_input_error_strings), - .error_strings = hicn_data_input_error_strings, - .n_next_nodes = HICN_DATA_INPUT_IP6_N_NEXT, - .next_nodes = - { - [HICN_DATA_INPUT_IP6_NEXT_FACE] = "hicn6-face-input", - [HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL] = "ip6-local-end-of-arc" - }, - }; -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -VNET_FEATURE_INIT(hicn_data_input_ip6_arc, static)= - { - .arc_name = "ip6-local", - .node_name = "hicn-data-input-ip6", - .runs_before = VNET_FEATURES("ip6-local-end-of-arc"), - }; -/* *INDENT-ON* */ - - - -always_inline uword -hicn_data_input_ip4_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) -{ - ip4_main_t *im = &ip4_main; - vlib_combined_counter_main_t *cm = &load_balance_main.lbm_to_counters; - u32 n_left, *from; - u32 thread_index = vm->thread_index; - vlib_buffer_t *bufs[VLIB_FRAME_SIZE]; - vlib_buffer_t **b = bufs; - u16 nexts[VLIB_FRAME_SIZE], *next; - - from = vlib_frame_vector_args (frame); - n_left = frame->n_vectors; - next = nexts; - vlib_get_buffers (vm, from, bufs, n_left); - -#if (CLIB_N_PREFETCHES >= 8) - while (n_left >= 4) - { - ip4_header_t *ip0, *ip1, *ip2, *ip3; - const load_balance_t *lb0, *lb1, *lb2, *lb3; - ip4_fib_mtrie_t *mtrie0, *mtrie1, *mtrie2, *mtrie3; - ip4_fib_mtrie_leaf_t leaf0, leaf1, leaf2, leaf3; - ip4_address_t *src_addr0, *src_addr1, *src_addr2, *src_addr3; - u32 lb_index0, lb_index1, lb_index2, lb_index3; - const dpo_id_t *dpo0, *dpo1, *dpo2, *dpo3; - - /* Prefetch next iteration. */ - if (n_left >= 8) - { - vlib_prefetch_buffer_header (b[4], LOAD); - vlib_prefetch_buffer_header (b[5], LOAD); - vlib_prefetch_buffer_header (b[6], LOAD); - vlib_prefetch_buffer_header (b[7], LOAD); - - CLIB_PREFETCH (b[4]->data, sizeof (ip0[0]), LOAD); - CLIB_PREFETCH (b[5]->data, sizeof (ip0[0]), LOAD); - CLIB_PREFETCH (b[6]->data, sizeof (ip0[0]), LOAD); - CLIB_PREFETCH (b[7]->data, sizeof (ip0[0]), LOAD); - } - - ip0 = vlib_buffer_get_current (b[0]); - ip1 = vlib_buffer_get_current (b[1]); - ip2 = vlib_buffer_get_current (b[2]); - ip3 = vlib_buffer_get_current (b[3]); - - src_addr0 = &ip0->src_address; - src_addr1 = &ip1->src_address; - src_addr2 = &ip2->src_address; - src_addr3 = &ip3->src_address; - - ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]); - ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[1]); - ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[2]); - ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[3]); - - mtrie0 = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie; - mtrie1 = &ip4_fib_get (vnet_buffer (b[1])->ip.fib_index)->mtrie; - mtrie2 = &ip4_fib_get (vnet_buffer (b[2])->ip.fib_index)->mtrie; - mtrie3 = &ip4_fib_get (vnet_buffer (b[3])->ip.fib_index)->mtrie; - - leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, src_addr0); - leaf1 = ip4_fib_mtrie_lookup_step_one (mtrie1, src_addr1); - leaf2 = ip4_fib_mtrie_lookup_step_one (mtrie2, src_addr2); - leaf3 = ip4_fib_mtrie_lookup_step_one (mtrie3, src_addr3); - - leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 2); - leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, src_addr1, 2); - leaf2 = ip4_fib_mtrie_lookup_step (mtrie2, leaf2, src_addr2, 2); - leaf3 = ip4_fib_mtrie_lookup_step (mtrie3, leaf3, src_addr3, 2); - - leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 3); - leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, src_addr1, 3); - leaf2 = ip4_fib_mtrie_lookup_step (mtrie2, leaf2, src_addr2, 3); - leaf3 = ip4_fib_mtrie_lookup_step (mtrie3, leaf3, src_addr3, 3); - - lb_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0); - lb_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1); - lb_index2 = ip4_fib_mtrie_leaf_get_adj_index (leaf2); - lb_index3 = ip4_fib_mtrie_leaf_get_adj_index (leaf3); - - ASSERT (lb_index0 && lb_index1 && lb_index2 && lb_index3); - lb0 = load_balance_get (lb_index0); - lb1 = load_balance_get (lb_index1); - lb2 = load_balance_get (lb_index2); - lb3 = load_balance_get (lb_index3); - - ASSERT (lb0->lb_n_buckets > 0); - ASSERT (is_pow2 (lb0->lb_n_buckets)); - ASSERT (lb1->lb_n_buckets > 0); - ASSERT (is_pow2 (lb1->lb_n_buckets)); - ASSERT (lb2->lb_n_buckets > 0); - ASSERT (is_pow2 (lb2->lb_n_buckets)); - ASSERT (lb3->lb_n_buckets > 0); - ASSERT (is_pow2 (lb3->lb_n_buckets)); - - dpo0 = load_balance_get_bucket_i (lb0, 0); - dpo1 = load_balance_get_bucket_i (lb1, 0); - dpo2 = load_balance_get_bucket_i (lb2, 0); - dpo3 = load_balance_get_bucket_i (lb3, 0); - - if (dpo_is_hicn (dpo0)) - next[0] = HICN_DATA_INPUT_IP4_NEXT_FACE; - else - next[0] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; - - if (dpo_is_hicn (dpo1)) - next[1] = HICN_DATA_INPUT_IP4_NEXT_FACE; - else - next[1] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; - - if (dpo_is_hicn (dpo2)) - next[2] = HICN_DATA_INPUT_IP4_NEXT_FACE; - else - next[2] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; - - if (dpo_is_hicn (dpo3)) - next[3] = HICN_DATA_INPUT_IP4_NEXT_FACE; - else - next[3] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; - - - if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && - (b[0]->flags & VLIB_BUFFER_IS_TRACED)) - { - hicn_data_input_trace_t *t = - vlib_add_trace (vm, node, b[0], sizeof (*t)); - t->sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_RX]; - t->next_index = next[0]; - t->isv6 = 0; - } - - if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && - (b[1]->flags & VLIB_BUFFER_IS_TRACED)) - { - hicn_data_input_trace_t *t = - vlib_add_trace (vm, node, b[1], sizeof (*t)); - t->sw_if_index = vnet_buffer (b[1])->sw_if_index[VLIB_RX]; - t->next_index = next[1]; - t->isv6 = 0; - } - - if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && - (b[2]->flags & VLIB_BUFFER_IS_TRACED)) - { - hicn_data_input_trace_t *t = - vlib_add_trace (vm, node, b[2], sizeof (*t)); - t->sw_if_index = vnet_buffer (b[2])->sw_if_index[VLIB_RX]; - t->next_index = next[0]; - t->isv6 = 0; - } - - if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && - (b[3]->flags & VLIB_BUFFER_IS_TRACED)) - { - hicn_data_input_trace_t *t = - vlib_add_trace (vm, node, b[3], sizeof (*t)); - t->sw_if_index = vnet_buffer (b[3])->sw_if_index[VLIB_RX]; - t->next_index = next[3]; - t->isv6 = 0; - } - - vlib_increment_combined_counter - (cm, thread_index, lb_index0, 1, - vlib_buffer_length_in_chain (vm, b[0])); - vlib_increment_combined_counter - (cm, thread_index, lb_index1, 1, - vlib_buffer_length_in_chain (vm, b[1])); - vlib_increment_combined_counter - (cm, thread_index, lb_index2, 1, - vlib_buffer_length_in_chain (vm, b[2])); - vlib_increment_combined_counter - (cm, thread_index, lb_index3, 1, - vlib_buffer_length_in_chain (vm, b[3])); - - b += 4; - next += 4; - n_left -= 4; - } -#elif (CLIB_N_PREFETCHES >= 4) - while (n_left >= 4) - { - ip4_header_t *ip0, *ip1; - const load_balance_t *lb0, *lb1; - ip4_fib_mtrie_t *mtrie0, *mtrie1; - ip4_fib_mtrie_leaf_t leaf0, leaf1; - ip4_address_t *src_addr0, *src_addr1; - u32 lb_index0, lb_index1; - flow_hash_config_t flow_hash_config0, flow_hash_config1; - u32 hash_c0, hash_c1; - const dpo_id_t *dpo0, *dpo1; - - /* Prefetch next iteration. */ - { - vlib_prefetch_buffer_header (b[2], LOAD); - vlib_prefetch_buffer_header (b[3], LOAD); - - CLIB_PREFETCH (b[2]->data, sizeof (ip0[0]), LOAD); - CLIB_PREFETCH (b[3]->data, sizeof (ip0[0]), LOAD); - } - - ip0 = vlib_buffer_get_current (b[0]); - ip1 = vlib_buffer_get_current (b[1]); - - src_addr0 = &ip0->src_address; - src_addr1 = &ip1->src_address; - - ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]); - ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[1]); - - mtrie0 = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie; - mtrie1 = &ip4_fib_get (vnet_buffer (b[1])->ip.fib_index)->mtrie; - - leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, src_addr0); - leaf1 = ip4_fib_mtrie_lookup_step_one (mtrie1, src_addr1); - - leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 2); - leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, src_addr1, 2); - - leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 3); - leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, src_addr1, 3); - - lb_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0); - lb_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1); - - ASSERT (lb_index0 && lb_index1); - lb0 = load_balance_get (lb_index0); - lb1 = load_balance_get (lb_index1); - - ASSERT (lb0->lb_n_buckets > 0); - ASSERT (is_pow2 (lb0->lb_n_buckets)); - ASSERT (lb1->lb_n_buckets > 0); - ASSERT (is_pow2 (lb1->lb_n_buckets)); - - dpo0 = load_balance_get_bucket_i (lb0, 0); - dpo1 = load_balance_get_bucket_i (lb1, 0); - - if (dpo_is_hicn (dpo0)) - next[0] = HICN_DATA_INPUT_IP4_NEXT_FACE; - else - next[0] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; - - if (dpo_is_hicn (dpo1)) - next[1] = HICN_DATA_INPUT_IP4_NEXT_FACE; - else - next[1] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; - - if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && - (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - hicn_data_input_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - t->next_index = next[0]; - t->isv6 = 0; - } - - if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && - (b1->flags & VLIB_BUFFER_IS_TRACED)) - { - hicn_data_input_trace_t *t = - vlib_add_trace (vm, node, b1, sizeof (*t)); - t->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX]; - t->next_index = next[1]; - t->isv6 = 0; - } - - - vlib_increment_combined_counter - (cm, thread_index, lb_index0, 1, - vlib_buffer_length_in_chain (vm, b[0])); - vlib_increment_combined_counter - (cm, thread_index, lb_index1, 1, - vlib_buffer_length_in_chain (vm, b[1])); - - b += 2; - next += 2; - n_left -= 2; - } -#endif - while (n_left > 0) - { - ip4_header_t *ip0; - const load_balance_t *lb0; - ip4_fib_mtrie_t *mtrie0; - ip4_fib_mtrie_leaf_t leaf0; - ip4_address_t *src_addr0; - u32 lbi0; - const dpo_id_t *dpo0; - - ip0 = vlib_buffer_get_current (b[0]); - src_addr0 = &ip0->src_address; - ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]); - - mtrie0 = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie; - leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, src_addr0); - leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 2); - leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 3); - lbi0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0); - - ASSERT (lbi0); - lb0 = load_balance_get (lbi0); - - ASSERT (lb0->lb_n_buckets > 0); - ASSERT (is_pow2 (lb0->lb_n_buckets)); - - dpo0 = load_balance_get_bucket_i (lb0, 0); - - if (dpo_is_hicn (dpo0)) - next[0] = HICN_DATA_INPUT_IP4_NEXT_FACE; - else - next[0] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; - - if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && - (b[0]->flags & VLIB_BUFFER_IS_TRACED)) - { - hicn_data_input_trace_t *t = - vlib_add_trace (vm, node, b[0], sizeof (*t)); - t->sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_RX]; - t->next_index = next[0]; - t->isv6 = 0; - } - - vlib_increment_combined_counter (cm, thread_index, lbi0, 1, - vlib_buffer_length_in_chain (vm, - b[0])); - - b += 1; - next += 1; - n_left -= 1; - } - - vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors); - - if (node->flags & VLIB_NODE_FLAG_TRACE) - ip4_forward_next_trace (vm, node, frame, VLIB_TX); - - return frame->n_vectors; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(hicn_data_input_ip4) = - { - .function = hicn_data_input_ip4_fn, - .name = "hicn-data-input-ip4", - .vector_size = sizeof(u32), - .format_trace = format_hicn_data_input_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(hicn_data_input_error_strings), - .error_strings = hicn_data_input_error_strings, - .n_next_nodes = HICN_DATA_INPUT_IP4_N_NEXT, - .next_nodes = - { - [HICN_DATA_INPUT_IP4_NEXT_FACE] = "hicn4-face-input", - [HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL] = "ip4-local-end-of-arc" - }, - }; -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -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"), - }; -/* *INDENT-ON* */ diff --git a/hicn-plugin/src/data_pcslookup.h b/hicn-plugin/src/data_pcslookup.h deleted file mode 100644 index e3050c31c..000000000 --- a/hicn-plugin/src/data_pcslookup.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2017-2019 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_DATA_PCSLOOKUP_H__ -#define __HICN_DATA_PCSLOOKUP_H__ - -#include "pcs.h" - -/** - * @file data_pcslookup.h - * - * This is the node encoutered by data packets after the hicn6-face-input or - * hicn4-face-input. This node performs a lookup in the pit and content store and - * if there is a hit in the PIT, the vlib buffer is passed to the hicn-data-fwd - * while if there is a hit in the CS or there isn't any hit, the packet is dropped. - */ - -/* - * Node context data; we think this is per-thread/instance - */ -typedef struct hicn_data_pcslookup_runtime_s -{ - int id; - hicn_pit_cs_t *pitcs; -} hicn_data_pcslookup_runtime_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; -} hicn_data_pcslookup_trace_t; - -typedef enum -{ - HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD, /* This must be one position - * before the error drop!! */ - HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP, - HICN_DATA_PCSLOOKUP_N_NEXT, -} hicn_data_pcslookup_next_t; - -#endif /* //__HICN_DATA_PCSLOOKUP_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/data_pcslookup_node.c b/hicn-plugin/src/data_pcslookup_node.c deleted file mode 100644 index 99af350b0..000000000 --- a/hicn-plugin/src/data_pcslookup_node.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2017-2019 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 "data_pcslookup.h" -#include "infra.h" -#include "mgmt.h" -#include "parser.h" -#include "state.h" -#include "strategy.h" -#include "strategy_dpo_manager.h" - -/* Stats string values */ -static char *hicn_data_pcslookup_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -/* packet trace format function */ -always_inline u8 *hicn_data_pcslookup_format_trace (u8 * s, va_list * args); - -vlib_node_registration_t hicn_data_pcslookup_node; - -/* - * hICN node for handling data. It performs a lookup in the PIT. - */ -static uword -hicn_data_pcslookup_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next; - hicn_data_pcslookup_next_t next_index; - hicn_data_pcslookup_runtime_t *rt; - vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; - - rt = vlib_node_get_runtime_data (vm, node->node_index); - - if (PREDICT_FALSE (rt->pitcs == NULL)) - { - rt->pitcs = &hicn_main.pitcs; - } - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - u32 n_left_to_next; - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *b0; - u8 isv6; - u8 *nameptr; - u16 namelen; - u32 bi0; - u32 next0 = HICN_DATA_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; - u8 is_cs0; - u8 hash_entry_id = 0; - u8 bucket_is_overflown = 0; - u32 bucket_id = ~0; - - /* Prefetch for next iteration. */ - if (n_left_from > 1) - { - vlib_buffer_t *b1; - b1 = vlib_get_buffer (vm, from[1]); - // Prefetch two cache lines-- 128 byte-- so that we load the - // hicn_buffer_t as well - CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, STORE); - CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, LOAD); - } - /* Dequeue a packet buffer */ - bi0 = from[0]; - from += 1; - n_left_from -= 1; - to_next[0] = bi0; - to_next += 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - next0 = HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP; - - /* Incr packet counter */ - stats.pkts_processed += 1; - - ret0 = hicn_data_parse_pkt (b0, &name, &namelen, &hicn0, &isv6); - nameptr = (u8 *) (&name); - - if (PREDICT_TRUE (ret0 == HICN_ERROR_NONE && - hicn_hashtb_fullhash (nameptr, namelen, - &name_hash) == - HICN_ERROR_NONE)) - { - int res = - hicn_hashtb_lookup_node (rt->pitcs->pcs_table, nameptr, - namelen, name_hash, - 1 - /*is_data. Do not take lock if hit CS */ - , - &node_id0, &dpo_ctx_id0, &vft_id0, - &is_cs0, &hash_entry_id, &bucket_id, - &bucket_is_overflown); - - stats.pkts_data_count += 1; - - if (res == HICN_ERROR_NONE) - { - /* - * In case the result of the lookup - * is a CS entry, the packet is - * dropped - */ - next0 = HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD + is_cs0; - } - } - - hicn_store_internal_state (b0, name_hash, node_id0, dpo_ctx_id0, - vft_id0, hash_entry_id, bucket_id, - bucket_is_overflown); - - /* - * Verify speculative enqueue, maybe switch current - * next frame - */ - /* - * Fix in case of a wrong speculation. Needed to - * clone the data in the right frame - */ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, - n_left_to_next, bi0, next0); - - /* Maybe trace */ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - hicn_data_pcslookup_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; - t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - t->next_index = next0; - } - } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - /* Check the CS LRU, and trim if necessary. */ - u32 pit_int_count = hicn_pit_get_int_count (rt->pitcs); - u32 pit_cs_count = hicn_pit_get_cs_count (rt->pitcs); - - vlib_node_increment_counter (vm, hicn_data_pcslookup_node.index, - HICNFWD_ERROR_PROCESSED, stats.pkts_processed); - - vlib_node_increment_counter (vm, hicn_data_pcslookup_node.index, - HICNFWD_ERROR_DATAS, stats.pkts_data_count); - - update_node_counter (vm, hicn_data_pcslookup_node.index, - HICNFWD_ERROR_INT_COUNT, pit_int_count); - update_node_counter (vm, hicn_data_pcslookup_node.index, - HICNFWD_ERROR_CS_COUNT, pit_cs_count); - return (frame->n_vectors); -} - -/* packet trace format function */ -static u8 * -hicn_data_pcslookup_format_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 *); - hicn_data_pcslookup_trace_t *t = - va_arg (*args, hicn_data_pcslookup_trace_t *); - - s = format (s, "DATA-PCSLOOKUP: pkt: %d, sw_if_index %d, next index %d", - (int) t->pkt_type, t->sw_if_index, t->next_index); - return (s); -} - -/* - * Node registration for the data forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(hicn_data_pcslookup_node) = -{ - .function = hicn_data_pcslookup_node_fn, - .name = "hicn-data-pcslookup", - .vector_size = sizeof(u32), - .runtime_data_bytes = sizeof(hicn_data_pcslookup_runtime_t), - .format_trace = hicn_data_pcslookup_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(hicn_data_pcslookup_error_strings), - .error_strings = hicn_data_pcslookup_error_strings, - .n_next_nodes = HICN_DATA_PCSLOOKUP_N_NEXT, - .next_nodes = { - [HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD] = "hicn-data-fwd", - [HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/error.c b/hicn-plugin/src/error.c deleted file mode 100644 index 588ae2398..000000000 --- a/hicn-plugin/src/error.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2017-2019 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 "error.h" - -const char *HICN_ERROR_STRING[] = { -#define _(a,b,c) c, - foreach_hicn_error -#undef _ -}; - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/error.h b/hicn-plugin/src/error.h deleted file mode 100644 index 59ebce61c..000000000 --- a/hicn-plugin/src/error.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_ERROR_H__ -#define __HICN_ERROR_H__ - -/** - * @file error.h - * - * Error codes for the hICN plugin. - */ - - -#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, "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, "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, "IP adjacency on incomplete face not available") \ - _(APPFACE_ALREADY_ENABLED, -173, "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, "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, "Src and dst addresses have different type (ipv4 and ipv6)") - -typedef enum -{ -#define _(a,b,c) HICN_ERROR_##a = (b), - foreach_hicn_error -#undef _ - HICN_N_ERROR, -} hicn_error_t; - -extern const char *HICN_ERROR_STRING[]; - -#define get_error_string(errno) (char *)(errno ? HICN_ERROR_STRING[(-errno) - 127] : HICN_ERROR_STRING[errno]) - -#endif /* //__HICN_ERROR_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/face_db.h b/hicn-plugin/src/face_db.h deleted file mode 100644 index 4dd8b2f32..000000000 --- a/hicn-plugin/src/face_db.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_DB_H__ -#define __HICN_FACE_DB_H__ - -#include -#include "faces/face.h" - -/** - * @file face_db.h - * - * Define a face db that is store in every pit entry. A face db containes a list - * of incoming faces for interest packets that are used to forward data packets - * on the interests' reverse path - */ - -/* Must be power of two */ -#define HICN_FACE_DB_INLINE_FACES 8 - -#define HICN_PIT_BITMAP_SIZE_BYTE HICN_PARAM_FACES_MAX/8 -#define HICN_PIT_N_HOP_BITMAP_SIZE HICN_PARAM_FACES_MAX - -#define HICN_PIT_N_HOP_BUCKET (HICN_PARAM_PIT_ENTRY_PHOPS_MAX - HICN_FACE_DB_INLINE_FACES) - -typedef struct hicn_face_bucket_s -{ - /* Array of indexes of virtual faces */ - hicn_face_id_t faces[HICN_PIT_N_HOP_BUCKET]; - - /* Used to check if interests are retransmission */ - u8 bitmap[HICN_PIT_BITMAP_SIZE_BYTE]; - -} hicn_face_bucket_t; - -extern hicn_face_bucket_t *hicn_face_bucket_pool; - -typedef struct __attribute__ ((packed)) hicn_face_db_s -{ - /* 19B + 1B = 20B */ - /* Equal to one or zero */ - u8 is_overflow; - - /* Number of faces in the last bucket */ - /* Or next availabe entry for storing a dpo_id_t */ - /* 20B + 4B = 24B */ - u32 n_faces; - - /* 24B + 32B (8*4) = 56B */ - /* Array of indexes of virtual faces */ - hicn_face_id_t inline_faces[HICN_FACE_DB_INLINE_FACES]; - - /* 56B + 4B = 60B */ - u32 next_bucket; - - /* 60B + 4B = 64B */ - u32 align; - //align back to 64 - -} hicn_face_db_t; - -always_inline hicn_face_id_t -hicn_face_db_get_dpo_face (u32 index, hicn_face_db_t * face_db) -{ - ASSERT (index < face_db->n_faces); - - return index < HICN_FACE_DB_INLINE_FACES ? (face_db->inline_faces[index]) : - (pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket)->faces - [(index - HICN_FACE_DB_INLINE_FACES) & (HICN_PIT_N_HOP_BUCKET - 1)]); -} - -always_inline void -hicn_face_db_init (int max_element) -{ - pool_init_fixed (hicn_face_bucket_pool, max_element); -} - -always_inline hicn_face_bucket_t * -hicn_face_db_get_bucket (u32 bucket_index) -{ - return pool_elt_at_index (hicn_face_bucket_pool, bucket_index); -} - -always_inline void -hicn_face_db_add_face (hicn_face_id_t face_id, hicn_face_db_t * face_db) -{ - //ASSERT (dpo->dpoi_index != ~0); - - hicn_face_bucket_t *faces_bkt = - pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket); - - hicn_face_id_t *element = - face_db->n_faces < - HICN_FACE_DB_INLINE_FACES ? &(face_db->inline_faces[face_db->n_faces]) : - &(faces_bkt->faces - [(face_db->n_faces - - HICN_FACE_DB_INLINE_FACES) & (HICN_PIT_N_HOP_BUCKET - 1)]); - - *element = face_id; - - u32 bitmap_index = face_id % HICN_PIT_N_HOP_BITMAP_SIZE; - u32 position_array = bitmap_index / 8; - u8 bit_index = (u8) (bitmap_index - position_array * 8); - - faces_bkt->bitmap[position_array] |= (0x01 << bit_index); - face_db->n_faces++; -} - -always_inline u8 -hicn_face_search (hicn_face_id_t index, hicn_face_db_t * face_db) -{ - hicn_face_bucket_t *faces_bkt = - pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket); - u32 bitmap_index = index % HICN_PIT_N_HOP_BITMAP_SIZE; - - u32 position_array = bitmap_index / 8; - u8 bit_index = bitmap_index - position_array * 8; - - return (faces_bkt->bitmap[position_array] >> bit_index) & 0x01; -} - -always_inline void -hicn_faces_flush (hicn_face_db_t * face_db) -{ - hicn_face_bucket_t *faces_bkt = - pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket); - clib_memset_u8 (&(faces_bkt->bitmap), 0, HICN_PIT_BITMAP_SIZE_BYTE); - face_db->n_faces = 0; - pool_put_index (hicn_face_bucket_pool, face_db->next_bucket); -} - - -#endif /* // __HICN_FACE_DB_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/faces/app/address_mgr.c b/hicn-plugin/src/faces/app/address_mgr.c deleted file mode 100644 index 2d5894ab8..000000000 --- a/hicn-plugin/src/faces/app/address_mgr.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2017-2020 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. - */ - -/* - * Copyright (c) 2017-2019 by cisco systems inc. All rights reserved. - * - */ - -#include - -#include -#include -#include //ip4_add_del_ip_address -#include //ip6_add_del_ip_address -#include //FIB_PROTOCOL_IP4/6, FIB_NODE_INDEX_INVALID -#include //FIB_SOURCE_PRIORITY_HI -#include -#include -#include //appif_flags -#include //vnet_sw_interface_set_flags - -#include "address_mgr.h" -#include "../../hicn.h" -#include "../../infra.h" -#include "../../error.h" -#include "../face.h" -#include "../../strategy_dpo_ctx.h" -#include "../../route.h" - -typedef struct address_mgr_main_s -{ - ip4_address_t next_ip4_local_addr; - ip6_address_t next_ip6_local_addr; -} address_mgr_main_t; - -address_mgr_main_t address_mgr_main; - -static void -increment_v4_address (ip4_address_t * a, u32 val) -{ - u32 v; - - v = clib_net_to_host_u32 (a->as_u32) + val; - a->as_u32 = clib_host_to_net_u32 (v); -} - -static void -increment_v6_address (ip6_address_t * a, u64 val) -{ - u64 v; - - v = clib_net_to_host_u64 (a->as_u64[1]) + val; - a->as_u64[1] = clib_host_to_net_u64 (v); -} - -void -get_two_ip4_addresses (ip4_address_t * appif_addr, ip4_address_t * nh_addr) -{ - /* We want two consecutives address that fall into a /31 mask */ - if (address_mgr_main.next_ip4_local_addr.as_u8[3] & 0x01) - increment_v4_address (&(address_mgr_main.next_ip4_local_addr), 1); - - *appif_addr = address_mgr_main.next_ip4_local_addr; - increment_v4_address (&(address_mgr_main.next_ip4_local_addr), 1); - *nh_addr = address_mgr_main.next_ip4_local_addr; - fib_prefix_t fib_pfx; - fib_node_index_t fib_entry_index = FIB_NODE_INDEX_INVALID; - u32 fib_index; - - fib_pfx.fp_proto = FIB_PROTOCOL_IP4; - fib_pfx.fp_len = ADDR_MGR_IP4_LEN; - /* At this point the face exists in the face table */ - do - { - /* Check if the route already exist in the fib */ - fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 0, appif_addr->as_u8); - fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto, - HICN_FIB_TABLE, - FIB_SOURCE_PRIORITY_HI); - fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx); - fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PRIORITY_HI); - if (fib_entry_index != FIB_NODE_INDEX_INVALID) - { - fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 0, nh_addr->as_u8); - fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto, - HICN_FIB_TABLE, - FIB_SOURCE_PRIORITY_HI); - fib_entry_index = - fib_table_lookup_exact_match (fib_index, &fib_pfx); - fib_table_unlock (fib_index, fib_pfx.fp_proto, - FIB_SOURCE_PRIORITY_HI); - } - if (fib_entry_index != FIB_NODE_INDEX_INVALID) - { - increment_v4_address (appif_addr, 2); - increment_v4_address (nh_addr, 2); - } - } - while (fib_entry_index != FIB_NODE_INDEX_INVALID); - - address_mgr_main.next_ip4_local_addr = *nh_addr; - increment_v4_address (&(address_mgr_main.next_ip4_local_addr), 1); -} - -void -get_two_ip6_addresses (ip6_address_t * appif_addr, ip6_address_t * nh_addr) -{ - - /* We want two consecutives address that fall into a /127 mask */ - if (address_mgr_main.next_ip6_local_addr.as_u8[15] & 0x01) - increment_v6_address (&(address_mgr_main.next_ip6_local_addr), 1); - - *appif_addr = address_mgr_main.next_ip6_local_addr; - increment_v6_address (&(address_mgr_main.next_ip6_local_addr), 1); - *nh_addr = address_mgr_main.next_ip6_local_addr; - - - fib_prefix_t fib_pfx; - fib_node_index_t fib_entry_index = FIB_NODE_INDEX_INVALID; - u32 fib_index; - - fib_pfx.fp_proto = FIB_PROTOCOL_IP6; - fib_pfx.fp_len = ADDR_MGR_IP6_LEN; - - fib_index = fib_table_find (fib_pfx.fp_proto, 0); - - /* At this point the face exists in the face table */ - do - { - /* Check if the route already exist in the fib */ - fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 1, appif_addr->as_u8); - - fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx); - //fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PRIORITY_HI); - if (fib_entry_index != FIB_NODE_INDEX_INVALID) - { - fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 0, nh_addr->as_u8); - - fib_entry_index = - fib_table_lookup_exact_match (fib_index, &fib_pfx); - // fib_table_unlock (fib_index, fib_pfx.fp_proto, - // FIB_SOURCE_PRIORITY_HI); - } - if (fib_entry_index != FIB_NODE_INDEX_INVALID) - { - increment_v6_address (appif_addr, 2); - increment_v6_address (nh_addr, 2); - } - } - while (fib_entry_index != FIB_NODE_INDEX_INVALID); - - address_mgr_main.next_ip6_local_addr = *nh_addr; - increment_v6_address (&(address_mgr_main.next_ip6_local_addr), 1); -} - -ip4_address_t -get_ip4_address () -{ - ip4_address_t *prefix = &address_mgr_main.next_ip4_local_addr; - fib_prefix_t fib_pfx; - fib_node_index_t fib_entry_index = FIB_NODE_INDEX_INVALID; - u32 fib_index; - - fib_pfx.fp_proto = FIB_PROTOCOL_IP4; - fib_pfx.fp_len = ADDR_MGR_IP4_LEN; - /* At this point the face exists in the face table */ - do - { - /* Check if the route already exist in the fib */ - fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 0, prefix->as_u8); - fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto, - HICN_FIB_TABLE, - FIB_SOURCE_PRIORITY_HI); - fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx); - fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PRIORITY_HI); - increment_v4_address (prefix, 1); - } - while (fib_entry_index != FIB_NODE_INDEX_INVALID); - - return fib_pfx.fp_addr.ip4; -} - -ip6_address_t -get_ip6_address () -{ - ip6_address_t *prefix = &address_mgr_main.next_ip6_local_addr; - fib_prefix_t fib_pfx; - fib_node_index_t fib_entry_index = FIB_NODE_INDEX_INVALID; - u32 fib_index; - - fib_pfx.fp_proto = FIB_PROTOCOL_IP6; - fib_pfx.fp_len = ADDR_MGR_IP6_LEN; - /* At this point the face exists in the face table */ - do - { - /* Check if the route already exist in the fib */ - fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 1, prefix->as_u8); - fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto, - HICN_FIB_TABLE, - FIB_SOURCE_PRIORITY_HI); - fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx); - fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PRIORITY_HI); - increment_v6_address (prefix, 1); - } - while (fib_entry_index != FIB_NODE_INDEX_INVALID); - - return fib_pfx.fp_addr.ip6; -} - -void -address_mgr_init () -{ - - address_mgr_main.next_ip4_local_addr.as_u8[0] = 169; - address_mgr_main.next_ip4_local_addr.as_u8[1] = 254; - address_mgr_main.next_ip4_local_addr.as_u8[2] = 1; - address_mgr_main.next_ip4_local_addr.as_u8[3] = 1; - - ip6_address_set_zero (&address_mgr_main.next_ip6_local_addr); - address_mgr_main.next_ip6_local_addr.as_u16[0] = - clib_host_to_net_u16 (0xfc00); - address_mgr_main.next_ip6_local_addr.as_u8[15] = 1; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/faces/app/address_mgr.h b/hicn-plugin/src/faces/app/address_mgr.h deleted file mode 100644 index 99450dcdd..000000000 --- a/hicn-plugin/src/faces/app/address_mgr.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2017-2019 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 _ADDRESS_MGR_H_ -#define _ADDRESS_MGR_H_ - -/** - * @file - * - * @brief Address manager. - * - * Address manager that maintains a pool of ip4 and ip6 addresses to assign to - * an interface. - */ - -#define ADDR_MGR_IP4_LEN 32 -#define ADDR_MGR_IP4_CONS_LEN 31 -#define ADDR_MGR_IP6_LEN 128 -#define ADDR_MGR_IP6_CONS_LEN 127 - -/** - * @brief Get two consecutive IP v4 addresses from the same /31 subnet - * - * @param addr1 first ip address with the least significant bit set to 0 - * @param addr2 second ip address with the least significant bit set to 1 - */ -void get_two_ip4_addresses (ip4_address_t * addr1, ip4_address_t * addr2); - -/** - * @brief Get two consecutive IP v6 addresses from the same /126 subnet - * - * @param addr1 first ip address with the least significant bit set to 0 - * @param addr2 second ip address with the least significant bit set to 1 - */ -void get_two_ip6_addresses (ip6_address_t * addr1, ip6_address_t * addr2); - -/** - * @brief Get one IP v4 address - * - * @return ip address - */ -ip4_address_t get_ip4_address (void); - -/** - * @brief Get one IP v6 address - * - * @return ip address - */ -ip6_address_t get_ip6_address (void); - -/** - * @brief Init the address manager - */ -void address_mgr_init (void); - -#endif /* _ADDRESS_MGR_ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/faces/app/face_app_cli.c b/hicn-plugin/src/faces/app/face_app_cli.c deleted file mode 100644 index 1aa27adc7..000000000 --- a/hicn-plugin/src/faces/app/face_app_cli.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "../face_dpo.h" -#include "../face.h" -#include "face_prod.h" -#include "face_cons.h" - -#define HICN_FACE_NONE 0 -#define HICN_FACE_DELETE 1 -#define HICN_FACE_ADD 2 - -static clib_error_t * -hicn_face_app_cli_set_command_fn (vlib_main_t * vm, - unformat_input_t * main_input, - vlib_cli_command_t * cmd) -{ - vnet_main_t *vnm = vnet_get_main (); - fib_prefix_t prefix; - hicn_face_id_t face_id1 = HICN_FACE_NULL; - hicn_face_id_t face_id2 = HICN_FACE_NULL; - u32 cs_reserved = HICN_PARAM_FACE_DFT_CS_RESERVED; - int ret = HICN_ERROR_NONE; - int sw_if; - int face_op = HICN_FACE_NONE; - int prod = 0; - - - /* Get a line of input. */ - unformat_input_t _line_input, *line_input = &_line_input; - if (!unformat_user (main_input, unformat_line_input, line_input)) - { - return (0); - } - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "del")) - { - face_op = HICN_FACE_DELETE; - } - else if (face_op == HICN_FACE_DELETE - && unformat (line_input, "id %d", &face_id1)) - ; - else if (unformat (line_input, "add")) - { - face_op = HICN_FACE_ADD; - } - else if (face_op == HICN_FACE_ADD) - { - if (unformat (line_input, "intfc %U", - unformat_vnet_sw_interface, vnm, &sw_if)) - ; - else - if (unformat - (line_input, "prod prefix %U/%d", unformat_ip46_address, - &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) - { - prod = 1; - } - else if (prod && unformat (line_input, "cs_size %d", &cs_reserved)) - ; - else if (unformat (line_input, "cons")) - ; - else - { - return clib_error_return (0, "%s '%U'", - get_error_string - (HICN_ERROR_CLI_INVAL), - format_unformat_error, line_input); - } - } - else - { - return clib_error_return (0, "%s '%U'", - get_error_string (HICN_ERROR_CLI_INVAL), - format_unformat_error, line_input); - } - } - - if (face_id1 != HICN_FACE_NULL) - { - - if (!hicn_dpoi_idx_is_valid (face_id1)) - { - return clib_error_return (0, "%s, face_id1 %d not valid", - get_error_string (ret), face_id1); - } - } - - int rv; - switch (face_op) - { - case HICN_FACE_ADD: - { - ip46_address_t prod_addr; - ip4_address_t cons_addr4; - ip6_address_t cons_addr6; - - if (prod) - { - prefix.fp_proto = - ip46_address_is_ip4 (&prefix. - fp_addr) ? FIB_PROTOCOL_IP4 : - FIB_PROTOCOL_IP6; - rv = - hicn_face_prod_add (&prefix, sw_if, &cs_reserved, &prod_addr, - &face_id1); - if (rv == HICN_ERROR_NONE) - { - u8 *sbuf = NULL; - sbuf = - format (sbuf, "Face id: %d, producer address %U", face_id1, - format_ip46_address, &prod_addr, - 0 /*IP46_ANY_TYPE */ ); - vlib_cli_output (vm, "%s", sbuf); - } - else - { - return clib_error_return (0, get_error_string (rv)); - } - } - else - { - rv = - hicn_face_cons_add (&cons_addr4, &cons_addr6, sw_if, &face_id1, - &face_id2); - if (rv == HICN_ERROR_NONE) - { - u8 *sbuf = NULL; - sbuf = - format (sbuf, - "Face id: %d, address v4 %U, face id: %d address v6 %U", - face_id1, format_ip4_address, &cons_addr4, face_id2, - format_ip6_address, &cons_addr6); - vlib_cli_output (vm, "%s", sbuf); - } - else - { - return clib_error_return (0, get_error_string (rv)); - } - } - break; - } - case HICN_FACE_DELETE: - { - hicn_face_t *face = hicn_dpoi_get_from_idx (face_id1); - - if (face->flags & HICN_FACE_FLAGS_APPFACE_CONS) - rv = hicn_face_cons_del (face_id1); - else - rv = hicn_face_prod_del (face_id1); - if (rv == HICN_ERROR_NONE) - { - vlib_cli_output (vm, "Face %d deleted", face_id1); - } - else - { - return clib_error_return (0, get_error_string (rv)); - } - break; - } - default: - return clib_error_return (0, "Operation (%d) not implemented", face_op); - break; - } - return (rv == HICN_ERROR_NONE) ? 0 : clib_error_return (0, "%s\n", - get_error_string - (rv)); -} - -/* cli declaration for 'cfg face' */ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (hicn_face_app_cli_set_command, static) = -{ - .path = "hicn face app", - .short_help = "hicn face app {add intfc { prod prefix cs_size } {cons} | {del }", - .function = hicn_face_app_cli_set_command_fn, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/faces/app/face_cons.c b/hicn-plugin/src/faces/app/face_cons.c deleted file mode 100644 index d44ba1a2b..000000000 --- a/hicn-plugin/src/faces/app/face_cons.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "face_cons.h" -#include "address_mgr.h" -#include "../../infra.h" - -int -hicn_face_cons_add (ip4_address_t * nh_addr4, ip6_address_t * nh_addr6, - u32 swif, hicn_face_id_t * faceid1, - hicn_face_id_t * faceid2) -{ - /* Create the corresponding appif if */ - /* Retrieve a valid local ip address to assign to the appif */ - /* Set the ip address and create the face in the face db */ - - vlib_main_t *vm = vlib_get_main (); - vnet_main_t *vnm = vnet_get_main (); - - hicn_main_t *hm = &hicn_main; - - ip46_address_t if_ip; - ip46_address_reset (&if_ip); - nh_addr4->as_u32 = 0; - nh_addr6->as_u64[0] = 0; - nh_addr6->as_u64[1] = 0; - u32 if_flags = 0; - - if (!hm->is_enabled) - { - return HICN_ERROR_FWD_NOT_ENABLED; - } - if_flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP; - vnet_sw_interface_set_flags (vnm, swif, if_flags); - - get_two_ip4_addresses (&(if_ip.ip4), nh_addr4); - ip4_add_del_interface_address (vm, - swif, - &(if_ip.ip4), - ADDR_MGR_IP4_CONS_LEN, 0 /* is_del */ ); - - ip46_address_t nh_addr = to_ip46 (0, (u8 *) nh_addr4); - - index_t adj_index = adj_nbr_find(FIB_PROTOCOL_IP4, VNET_LINK_IP4, &nh_addr, swif); - - hicn_iface_add (&nh_addr, swif, faceid1, DPO_PROTO_IP4, adj_index); - - hicn_face_t *face = hicn_dpoi_get_from_idx (*faceid1); - face->flags |= HICN_FACE_FLAGS_APPFACE_CONS; - - get_two_ip6_addresses (&(if_ip.ip6), nh_addr6); - ip6_add_del_interface_address (vm, - swif, - &(if_ip.ip6), - ADDR_MGR_IP6_CONS_LEN, 0 /* is_del */ ); - - adj_index = adj_nbr_find(FIB_PROTOCOL_IP6, VNET_LINK_IP6, &nh_addr, swif); - - hicn_iface_add ((ip46_address_t *) nh_addr6, swif, faceid2, DPO_PROTO_IP6, adj_index); - - face = hicn_dpoi_get_from_idx (*faceid2); - face->flags |= HICN_FACE_FLAGS_APPFACE_CONS; - - return HICN_ERROR_NONE; -} - -int -hicn_face_cons_del (hicn_face_id_t face_id) -{ - if (!hicn_dpoi_idx_is_valid (face_id)) - return HICN_ERROR_APPFACE_NOT_FOUND; - - hicn_face_t *face = hicn_dpoi_get_from_idx (face_id); - - if (face->flags & HICN_FACE_FLAGS_APPFACE_CONS) - { - return hicn_face_del (face_id); - } - else - { - return HICN_ERROR_APPFACE_NOT_FOUND; - } -} - -u8 * -format_hicn_face_cons (u8 * s, va_list * args) -{ - CLIB_UNUSED (index_t index) = va_arg (*args, index_t); - CLIB_UNUSED (u32 indent) = va_arg (*args, u32); - - s = format (s, " (consumer face)"); - - return s; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/faces/app/face_cons.h b/hicn-plugin/src/faces/app/face_cons.h deleted file mode 100644 index 5f8f5dde8..000000000 --- a/hicn-plugin/src/faces/app/face_cons.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2017-2019 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 _FACE_CONSUMER_H_ -#define _FACE_CONSUMER_H_ - -#include -#include "../face.h" - -/** - * @file - * - * @brief Consumer application face. - * - * A consumer application face is built upon an ip face and identify a local - * consumer application (co-located with the forwarder) that acts as a - * consumer. The interface used by the consumer application face is - * assumed to be reserved only for hICN traffic (e.g., dedicated memif that - * connects the applictation to the forwarder). Only one application face can be - * assigned to an interface. - * - * In the vlib graph a consumer application face directly connect the - * device-input node to the hicn-vface-ip node. - */ - -/** - * @brief Add a new consumer application face - * - * The method creates the internal ip face and set the ip address to the interface. - * @param nh_addr4 ipv4 address to assign to interface used by the application to - * send interest to the consumer face - * @param nh_addr6 ipv6 address to assign to interface used by the application to - * send interest to the consumer face - * @param swif interface associated to the face - */ -int -hicn_face_cons_add (ip4_address_t * nh_addr4, ip6_address_t * nh_addr6, - u32 swif, hicn_face_id_t * faceid1, - hicn_face_id_t * faceid2); - -/** - * @brief Delete an existing consumer application face - * - * @param face_id Id of the consumer application face - */ -int hicn_face_cons_del (hicn_face_id_t face_id); - -/** - * @brief Format an application consumer face - * - * @param s Pointer to a previous string. If null it will be initialize - * @param args Array storing input values. Expected u32 face_id and u32 indent - * @return String with the formatted face - */ -u8 *format_hicn_face_cons (u8 * s, va_list * args); - - -#endif /* _FACE_CONSUMER_H_ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/faces/app/face_prod.c b/hicn-plugin/src/faces/app/face_prod.c deleted file mode 100644 index 645154325..000000000 --- a/hicn-plugin/src/faces/app/face_prod.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "face_prod.h" -#include "address_mgr.h" -#include "../../infra.h" -#include "../../route.h" -#include "../../cache_policies/cs_lru.h" - -hicn_face_prod_state_t *face_state_vec; - -/* used to check if an interface is already in the vector */ -u32 *face_state_pool; - -static int -hicn_app_state_create (u32 swif, fib_prefix_t * prefix) -{ - /* Make sure that the pool is not empty */ - pool_validate_index (face_state_pool, 0); - - u32 *swif_app; - u8 found = 0; - /* *INDENT-OFF* */ - pool_foreach (swif_app, face_state_pool,{ - if (*swif_app == swif) - { - found = 1; - } - } - ); - /* *INDENT-ON* */ - - - if (found) - return HICN_ERROR_APPFACE_ALREADY_ENABLED; - - - /* Create the appif and store in the vector */ - vec_validate (face_state_vec, swif); - clib_memcpy (&(face_state_vec[swif].prefix), prefix, sizeof (fib_prefix_t)); - - /* Set as busy the element in the vector */ - pool_get (face_state_pool, swif_app); - *swif_app = swif; - - int ret = HICN_ERROR_NONE; - if (ip46_address_is_ip4 (&(prefix->fp_addr))) - { - ret = - vnet_feature_enable_disable ("ip4-unicast", "hicn-face-prod-input", - swif, 1, 0, 0); - } - else - { - ret = - vnet_feature_enable_disable ("ip6-unicast", "hicn-face-prod-input", - swif, 1, 0, 0); - } - - return ret == 0 ? HICN_ERROR_NONE : HICN_ERROR_APPFACE_FEATURE; -} - -static int -hicn_app_state_del (u32 swif) -{ - /* Make sure that the pool is not empty */ - pool_validate_index (face_state_pool, 0); - - u32 *temp; - u32 *swif_app = NULL; - u8 found = 0; - fib_prefix_t *prefix; - /* *INDENT-OFF* */ - pool_foreach (temp, face_state_pool,{ - if (*temp == swif) - { - found = 1; - swif_app = temp; - } - } - ); - /* *INDENT-ON* */ - - if (!found) - return HICN_ERROR_APPFACE_NOT_FOUND; - - prefix = &(face_state_vec[swif].prefix); - - int ret = HICN_ERROR_NONE; - if (ip46_address_is_ip4 (&prefix->fp_addr)) - { - ret = - vnet_feature_enable_disable ("ip4-unicast", "hicn-face-prod-input", - swif, 0, 0, 0); - } - else - { - ret = - vnet_feature_enable_disable ("ip6-unicast", "hicn-face-prod-input", - swif, 0, 0, 0); - } - - pool_put (face_state_pool, swif_app); - memset (&face_state_vec[swif], 0, sizeof (hicn_face_prod_state_t)); - - return ret == 0 ? HICN_ERROR_NONE : HICN_ERROR_APPFACE_FEATURE; -} - -int -hicn_face_prod_add (fib_prefix_t * prefix, u32 sw_if, u32 * cs_reserved, - ip46_address_t * prod_addr, hicn_face_id_t * faceid) -{ - vlib_main_t *vm = vlib_get_main (); - vnet_main_t *vnm = vnet_get_main (); - - hicn_main_t *hm = &hicn_main; - - ip46_address_t local_app_ip; - CLIB_UNUSED(ip46_address_t remote_app_ip); - u32 if_flags = 0; - - if (!hm->is_enabled) - { - return HICN_ERROR_FWD_NOT_ENABLED; - } - - if (vnet_get_sw_interface_or_null (vnm, sw_if) == NULL) - { - return HICN_ERROR_FACE_HW_INT_NOT_FOUND; - } - - int ret = HICN_ERROR_NONE; - hicn_face_t *face = NULL; - - if_flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP; - vnet_sw_interface_set_flags (vnm, sw_if, if_flags); - - u8 *s0; - s0 = format (0, "Prefix %U", format_fib_prefix, prefix); - - vlib_cli_output (vm, "Received request for %s, swif %d\n", s0, sw_if); - - if (ip46_address_is_zero (&prefix->fp_addr)) - { - return HICN_ERROR_APPFACE_PROD_PREFIX_NULL; - } - - u8 isv6 = ip46_address_is_ip4(prod_addr); - index_t adj_index = adj_nbr_find(isv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4, isv6 ? VNET_LINK_IP6 : VNET_LINK_IP4, prod_addr, sw_if); - - /* - * Check if a producer face is already existing for the same prefix - * and sw_if - */ - face = hicn_face_get (&(prefix->fp_addr), sw_if, - &hicn_face_hashtb, adj_index); - - if (face != NULL) - { - if (!(face->flags & HICN_FACE_FLAGS_DELETED)) - return HICN_ERROR_FACE_ALREADY_CREATED; - - /* - * Something went worng, a consumer face exists for the - * producer's prefix. - */ - /* It should never happens, this is a safety check. */ - if (face->flags & HICN_FACE_FLAGS_APPFACE_CONS) - return HICN_ERROR_FACE_ALREADY_CREATED; - - /* If the face exists but is marked as deleted, undelete it */ - if (face->flags & HICN_FACE_FLAGS_DELETED) - { - /* - * remove the deleted flag and retrieve the face - * local addr - */ - face->flags &= HICN_FACE_FLAGS_DELETED; - } - } - else - { - /* Otherwise create the face */ - if (ip46_address_is_ip4 (&prefix->fp_addr)) - { - /* - * Otherwise retrieve an ip address to assign as a - * local ip addr. - */ - ip4_address_t local_app_ip4; - ip4_address_t remote_app_ip4; - get_two_ip4_addresses (&local_app_ip4, &remote_app_ip4); - ip4_add_del_interface_address (vm, - sw_if, - &local_app_ip4, 31, 0 /* is_del */ ); - local_app_ip = to_ip46 ( /* isv6 */ 0, local_app_ip4.as_u8); - remote_app_ip = to_ip46 ( /* isv6 */ 0, remote_app_ip4.as_u8); - - vnet_build_rewrite_for_sw_interface(vnm, sw_if, VNET_LINK_IP4, &remote_app_ip4); - } - else - { - ip6_address_t local_app_ip6; - ip6_address_t remote_app_ip6; - get_two_ip6_addresses (&local_app_ip6, &remote_app_ip6); - u8 *s0; - s0 = format (0, "%U", format_ip6_address, &local_app_ip6); - - vlib_cli_output (vm, "Setting ip address %s\n", s0); - - ip6_add_del_interface_address (vm, - sw_if, - &local_app_ip6, 127, - 0 /* is_del */ ); - local_app_ip = to_ip46 ( /* isv6 */ 1, local_app_ip6.as_u8); - remote_app_ip = to_ip46 ( /* isv6 */ 1, remote_app_ip6.as_u8); - } - } - - if (ret == HICN_ERROR_NONE) - // && hicn_face_prod_set_lru_max (*faceid, cs_reserved) == HICN_ERROR_NONE) - { - fib_route_path_t rpath = {0}; - fib_route_path_t * rpaths = NULL; - - 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; - - rpath.frp_weight = 1; - rpath.frp_sw_if_index = ~0; - rpath.frp_addr.ip4.as_u32 = remote_app_ip.ip4.as_u32; - rpath.frp_sw_if_index = sw_if; - rpath.frp_proto = DPO_PROTO_IP4; - - vec_add1 (rpaths, rpath); - } - 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; - - rpath.frp_weight = 1; - rpath.frp_sw_if_index = ~0; - rpath.frp_addr.ip6.as_u64[0] = remote_app_ip.ip6.as_u64[0]; - rpath.frp_addr.ip6.as_u64[1] = remote_app_ip.ip6.as_u64[1]; - rpath.frp_sw_if_index = sw_if; - rpath.frp_proto = DPO_PROTO_IP6; - - vec_add1 (rpaths, rpath); - } - - u32 fib_index = fib_table_find (prefix->fp_proto, 0); - fib_table_entry_path_add2 (fib_index, - prefix, - FIB_SOURCE_CLI, - FIB_ENTRY_FLAG_NONE, rpaths); - - hicn_route_enable(prefix); - hicn_app_state_create (sw_if, prefix); - } - - adj_index = adj_nbr_find(isv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4, isv6 ? VNET_LINK_IP6 : VNET_LINK_IP4, prod_addr, sw_if); - face = hicn_face_get(&local_app_ip, sw_if, &hicn_face_hashtb, adj_index);//HICN_FACE_FLAGS_APPFACE_PROD); - - *faceid = hicn_dpoi_get_index (face); - - face->flags |= HICN_FACE_FLAGS_APPFACE_PROD; - - hicn_face_unlock_with_id(*faceid); - - *prod_addr = local_app_ip; - - /* Cleanup in case of something went wrong. */ - if (ret) - { - hicn_app_state_del (sw_if); - } - return ret; -} - -int -hicn_face_prod_del (hicn_face_id_t face_id) -{ - if (!hicn_dpoi_idx_is_valid (face_id)) - return HICN_ERROR_APPFACE_NOT_FOUND; - - hicn_face_t *face = hicn_dpoi_get_from_idx (face_id); - - if (face->flags & HICN_FACE_FLAGS_APPFACE_PROD) - { - /* Remove the face from the fib */ - hicn_route_disable(&(face_state_vec[face->sw_if].prefix)); - //hicn_route_del_nhop (&(face_state_vec[face->sw_if].prefix), - // face_id); - - //int ret = hicn_face_del (face_id); - return hicn_app_state_del (face->sw_if); - //ret == HICN_ERROR_NONE ? hicn_app_state_del (face->sw_if) : ret; - } - else - { - return HICN_ERROR_APPFACE_NOT_FOUND; - } - - return HICN_ERROR_NONE; -} - -u8 * -format_hicn_face_prod (u8 * s, va_list * args) -{ - CLIB_UNUSED (index_t index) = va_arg (*args, index_t); - CLIB_UNUSED (u32 indent) = va_arg (*args, u32); - - s = - format (s, " (producer)"); - - return s; -} - -/* *INDENT-OFF* */ -VNET_FEATURE_INIT(hicn_prod_app_input_ip6, static)= -{ - .arc_name = "ip6-unicast", - .node_name = "hicn-face-prod-input", - .runs_before = VNET_FEATURES("ip6-inacl"), -}; -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -VNET_FEATURE_INIT(hicn_prod_app_input_ip4, static)= -{ - .arc_name = "ip4-unicast", - .node_name = "hicn-face-prod-input", - .runs_before = VNET_FEATURES("ip4-inacl"), -}; -/* *INDENT-ON* */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/faces/app/face_prod.h b/hicn-plugin/src/faces/app/face_prod.h deleted file mode 100644 index 4cb2e3fbf..000000000 --- a/hicn-plugin/src/faces/app/face_prod.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 _FACE_PRODUCER_H_ -#define _FACE_PRODUCER_H_ - -#include "../../cache_policies/cs_policy.h" -#include "../face.h" - -/** - * @file - * - * @brief Producer application face. - * - * A producer application face is built upon an ip face and identify a local - * producer application (co-located with the forwarder) that acts as a producer. In the - * current design an application face is either a face towards a consumer face - * or towards a producer. The interface used by the producer application face is - * assumed to be reserved only for hICN traffic (e.g., dedicated memif that - * connects the applictation to the forwarder). Only one application face can be - * assigned to an interface. - * - * To each producer application face it is assigned a portion of the CS. Every - * data arriving to a producer application will be stored in the portion of the - * CS assigned to the face. The eviction policy is defined in the - * face. Available eviction faces are list in the /cache_policy folder. - * - * In the vlib graph a producer application face is directly connected to the - * device-input node (with the node hicn-face-prod-input) and passes every packet to - * the hicn-face-ip node. - */ - -/** - * @brief Producer application face state that refer to the hICN producer socket - * created by the application. - * - */ -typedef struct -{ - fib_prefix_t prefix; -} hicn_face_prod_state_t; - -extern hicn_face_prod_state_t *face_state_vec; - -#define DEFAULT_PROBING_PORT 3784 - -/** - * @brief Add a new producer application face - * - * The method creates the internal ip face and the state specific to the - * producer application face. This method setups a route in the FIB for the - * producer's prefix. - * @param prefix hicn prefix name assigned to the producer face - * @param len length of the prefix - * @param swif interface associated to the face - * @param cs_reserved return the amount of cs assigned to the face - * @param prod_addr address to assign to interface used by the appliction to - * send data to the producer face - */ -int -hicn_face_prod_add (fib_prefix_t * prefix, u32 swif, u32 * cs_reserved, - ip46_address_t * prod_addr, hicn_face_id_t * faceid); - -/** - * @brief Delete an existing application face - * - * @param faceid id of the face to remove - */ -int hicn_face_prod_del (hicn_face_id_t faceid); - -/** - * @brief Set lru queue size for an app face - * - * @param face_id Id of the producer application face - */ -int hicn_face_prod_set_lru_max (hicn_face_id_t face_id, u32 * requested_size); - -/** - * @brief Format an application producer face - * - * @param s Pointer to a previous string. If null it will be initialize - * @param args Array storing input values. Expected u32 face_id and u32 indent - * @return String with the formatted face - */ -u8 *format_hicn_face_prod (u8 * s, va_list * args); - - -#endif /* _FACE_PROD_H_ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/faces/app/face_prod_node.c b/hicn-plugin/src/faces/app/face_prod_node.c deleted file mode 100644 index 80c3e124c..000000000 --- a/hicn-plugin/src/faces/app/face_prod_node.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 2017-2020 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. - */ - -/** - * @file - * - * @brief Application interface node - * - * This node runs after the device-input node and perfoms some safety checks in - * order to avoid unespected interest and data (i.e., hICN packets whose name do - * not contain the prefix associated to the application face) - */ - -#include "face_prod.h" -#include "../../hicn_api.h" -#include "../../mgmt.h" - -static __clib_unused char *face_prod_input_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -/* Node context data */ -typedef struct hicn_face_prod_runtime_s -{ - int id; -} hicn_face_prod_runtime_t; - -typedef struct -{ - u32 next_index; - u32 sw_if_index; -} hicn_face_prod_input_trace_t; - -typedef enum -{ - HICN_FACE_PROD_NEXT_DATA_IP4, - HICN_FACE_PROD_NEXT_DATA_IP6, - HICN_FACE_PROD_NEXT_ERROR_DROP, - HICN_FACE_PROD_N_NEXT, -} hicn_face_prod_next_t; - -vlib_node_registration_t hicn_face_prod_input_node; - -static __clib_unused u8 * -format_face_prod_input_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 *); - hicn_face_prod_input_trace_t *t = - va_arg (*args, hicn_face_prod_input_trace_t *); - CLIB_UNUSED (u32 indent) = format_get_indent (s); - - s = format (s, "prod-face: sw_if_index %d next-index %d", - t->sw_if_index, t->next_index); - return s; -} - -static_always_inline int -match_ip4_name (u32 * name, fib_prefix_t * prefix) -{ - u32 xor = 0; - - xor = *name & prefix->fp_addr.ip4.data_u32; - - return xor == prefix->fp_addr.ip4.data_u32; -} - -static_always_inline int -match_ip6_name (u8 * name, fib_prefix_t * prefix) -{ - union - { - u32x4 as_u32x4; - u64 as_u64[2]; - u32 as_u32[4]; - } xor_sum __attribute__ ((aligned (sizeof (u32x4)))); - - 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]; - - 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]); -} - -static_always_inline u32 -hicn_face_prod_next_from_data_hdr (vlib_node_runtime_t * node, - vlib_buffer_t * b, fib_prefix_t * prefix) -{ - u8 *ptr = vlib_buffer_get_current (b); - u8 v = *ptr & 0xf0; - int match_res = 1; - - if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr))) - { - match_res = match_ip4_name ((u32 *) & (ptr[12]), prefix); - } - else if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr))) - { - match_res = match_ip6_name (& (ptr[8]), prefix); - } - - return match_res ? HICN_FACE_PROD_NEXT_DATA_IP4 + (v == - 0x60) : - HICN_FACE_PROD_NEXT_ERROR_DROP; -} - -static_always_inline void -hicn_face_prod_trace_buffer (vlib_main_t * vm, vlib_node_runtime_t * node, - u32 swif, vlib_buffer_t * b, u32 next) -{ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b->flags & VLIB_BUFFER_IS_TRACED))) - { - hicn_face_prod_input_trace_t *t = - vlib_add_trace (vm, node, b, sizeof (*t)); - t->next_index = next; - t->sw_if_index = swif; - } -} - -static uword -hicn_face_prod_input_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - 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 }; - - 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 >= 8 && n_left_to_next >= 4) - { - vlib_buffer_t *b0, *b1, *b2, *b3; - 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; - - { - 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); - } - - bi0 = from[0]; - bi1 = from[1]; - bi2 = from[2]; - bi3 = from[3]; - - from += 4; - n_left_from -= 4; - to_next[0] = bi0; - to_next[1] = bi1; - to_next[2] = bi2; - to_next[3] = bi3; - - to_next += 4; - n_left_to_next -= 4; - - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - b2 = vlib_get_buffer (vm, bi2); - b3 = vlib_get_buffer (vm, bi3); - - 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]]; - - 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); - stats.pkts_data_count += 4; - - /* trace */ - hicn_face_prod_trace_buffer (vm, node, - vnet_buffer (b0)->sw_if_index[VLIB_RX], - b0, next0); - hicn_face_prod_trace_buffer (vm, node, - vnet_buffer (b1)->sw_if_index[VLIB_RX], - b1, next1); - hicn_face_prod_trace_buffer (vm, node, - vnet_buffer (b2)->sw_if_index[VLIB_RX], - b2, next2); - hicn_face_prod_trace_buffer (vm, node, - vnet_buffer (b3)->sw_if_index[VLIB_RX], - b3, next3); - - /* enqueue */ - vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next, - n_left_to_next, bi0, bi1, bi2, bi3, - next0, next1, next2, next3); - - stats.pkts_processed += 4; - - } - - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *b0; - u32 bi0, swif; - hicn_face_prod_state_t *prod_face = NULL; - u32 next0; - - if (n_left_from > 1) - { - vlib_buffer_t *b1; - b1 = vlib_get_buffer (vm, from[1]); - CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, STORE); - } - - bi0 = from[0]; - from += 1; - n_left_from -= 1; - to_next[0] = bi0; - to_next += 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - 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); - stats.pkts_data_count++; - - /* trace */ - hicn_face_prod_trace_buffer (vm, node, - vnet_buffer (b0)->sw_if_index[VLIB_RX], - b0, next0); - - /* enqueue */ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, - n_left_to_next, bi0, next0); - - stats.pkts_processed += 1; - - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, node->node_index, - HICNFWD_ERROR_PROCESSED, stats.pkts_processed); - vlib_node_increment_counter (vm, node->node_index, HICNFWD_ERROR_DATAS, - stats.pkts_data_count); - - return (frame->n_vectors); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(hicn_face_prod_input_node) = -{ - .function = hicn_face_prod_input_node_fn, - .name = "hicn-face-prod-input", - .vector_size = sizeof(u32), - .format_trace = format_face_prod_input_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(face_prod_input_error_strings), - .error_strings = face_prod_input_error_strings, - .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_ERROR_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/faces/face.c b/hicn-plugin/src/faces/face.c deleted file mode 100644 index b495d18b0..000000000 --- a/hicn-plugin/src/faces/face.c +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "face.h" -#include "../hicn.h" -#include "../params.h" -#include "../error.h" -#include "../mapme.h" -#include "../mapme_eventmgr.h" - -dpo_id_t *face_dpo_vec; -hicn_face_vft_t *face_vft_vec; -char **face_type_names_vec; - -hicn_face_t *hicn_dpoi_face_pool; - -dpo_type_t first_type = DPO_FIRST; - -vlib_combined_counter_main_t *counters; - -dpo_type_t hicn_face_type; - -fib_node_type_t hicn_face_fib_node_type; - -const char *HICN_FACE_CTRX_STRING[] = { -#define _(a,b,c) c, - foreach_hicn_face_counter -#undef _ -}; - -u8 * -face_show (u8 * s, int face_id, u32 indent) -{ - s = format (s, "%U Faces:\n", format_white_space, indent); - indent += 4; - int i; - vec_foreach_index (i, face_dpo_vec) - { - s = - format (s, "%U", face_vft_vec[i].format_face, - face_dpo_vec[face_id].dpoi_index, indent); - } - - return (s); - -} - -mhash_t hicn_face_vec_hashtb; -mhash_t hicn_face_hashtb; - -hicn_face_vec_t *hicn_vec_pool; - -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, -}; - - -const static char *const *const hicn_face_nodes[DPO_PROTO_NUM] = { - [DPO_PROTO_IP4] = hicn_face4_nodes, - [DPO_PROTO_IP6] = hicn_face6_nodes -}; - -const static dpo_vft_t hicn_face_dpo_vft = { - .dv_lock = hicn_face_lock, - .dv_unlock = hicn_face_unlock, - .dv_format = format_hicn_face, -}; - -static fib_node_t * -hicn_face_node_get (fib_node_index_t index) -{ - hicn_face_t *face; - - face = hicn_dpoi_get_from_idx (index); - - return (&face->fib_node); -} - -static void -hicn_face_last_lock_gone (fib_node_t * node) -{ -} - -static hicn_face_t * -hicn_face_from_fib_node (fib_node_t * node) -{ - return ((hicn_face_t *) (((char *) node) - - STRUCT_OFFSET_OF (hicn_face_t, fib_node))); -} - -static fib_node_back_walk_rc_t -hicn_face_back_walk_notify (fib_node_t * node, fib_node_back_walk_ctx_t * ctx) -{ - - hicn_face_t *face = hicn_face_from_fib_node (node); - - const dpo_id_t *dpo_loadbalance = - fib_entry_contribute_ip_forwarding (face->fib_entry_index); - const load_balance_t *lb0 = load_balance_get (dpo_loadbalance->dpoi_index); - - const dpo_id_t *dpo = load_balance_get_bucket_i (lb0, 0); - - dpo_stack (hicn_face_type, face->dpo.dpoi_proto, &face->dpo, dpo); - /* if (dpo_is_adj(dpo)) */ - /* { */ - /* ip_adjacency_t * adj = adj_get (dpo->dpoi_index); */ - - /* if (dpo->dpoi_type == DPO_ADJACENCY_MIDCHAIN || */ - /* dpo->dpoi_type == DPO_ADJACENCY_MCAST_MIDCHAIN) */ - /* { */ - /* adj_nbr_midchain_stack(dpo->dpoi_index, &face->dpo); */ - /* } */ - /* else */ - /* { */ - /* dpo_stack(hicn_face_type, face->dpo.dpoi_proto, &face->dpo, dpo); */ - /* } */ - /* } */ - - return (FIB_NODE_BACK_WALK_CONTINUE); -} - -static void -hicn_face_show_memory (void) -{ -} - - -static const fib_node_vft_t hicn_face_fib_node_vft = { - .fnv_get = hicn_face_node_get, - .fnv_last_lock = hicn_face_last_lock_gone, - .fnv_back_walk = hicn_face_back_walk_notify, - .fnv_mem_show = hicn_face_show_memory, -}; - -// Make this more flexible for future types face -void -hicn_face_module_init (vlib_main_t * vm) -{ - pool_validate (hicn_dpoi_face_pool); - pool_alloc (hicn_dpoi_face_pool, 1024); - counters = - vec_new (vlib_combined_counter_main_t, - HICN_PARAM_FACES_MAX * HICN_N_COUNTER); - - mhash_init (&hicn_face_vec_hashtb, - sizeof (hicn_face_input_faces_t) /* value */ , - sizeof (hicn_face_key_t) /* key */ ); - mhash_init (&hicn_face_hashtb, sizeof (hicn_face_id_t) /* value */ , - sizeof (hicn_face_key_t) /* key */ ); - - pool_alloc (hicn_vec_pool, 100); - - /* - * How much useful is the following registration? - * So far it seems that we need it only for setting the dpo_type. - */ - hicn_face_type = - dpo_register_new_type (&hicn_face_dpo_vft, hicn_face_nodes); - - /* - * We register a new node type to get informed when the adjacency corresponding - * to a face is updated - */ - hicn_face_fib_node_type = - fib_node_register_new_type (&hicn_face_fib_node_vft); -} - -u8 * -format_hicn_face (u8 * s, va_list * args) -{ - index_t index = va_arg (*args, index_t); - u32 indent = va_arg (*args, u32); - hicn_face_t *face; - - face = hicn_dpoi_get_from_idx (index); - - if (face->flags & HICN_FACE_FLAGS_FACE) - { - hicn_face_id_t face_id = hicn_dpoi_get_index (face); - s = format (s, "%U Face %d: ", format_white_space, indent, face_id); - s = format (s, "nat address %U locks %u, path_label %u", - format_ip46_address, &face->nat_addr, IP46_TYPE_ANY, - face->locks, face->pl_id); - - if ((face->flags & HICN_FACE_FLAGS_APPFACE_PROD)) - s = format (s, " (producer)"); - else if ((face->flags & HICN_FACE_FLAGS_APPFACE_CONS)) - s = format (s, " (consumer)"); - - if ((face->flags & HICN_FACE_FLAGS_DELETED)) - s = format (s, " (deleted)"); - - s = format (s, "\n%U%U", - format_white_space, indent + 2, - format_dpo_id, &face->dpo, indent + 3); - } - else - { - hicn_face_id_t face_id = hicn_dpoi_get_index (face); - s = format (s, "%U iFace %d: ", format_white_space, indent, face_id); - s = format (s, "nat address %U locks %u, path_label %u", - format_ip46_address, &face->nat_addr, IP46_TYPE_ANY, - face->locks, face->pl_id); - - if ((face->flags & HICN_FACE_FLAGS_APPFACE_PROD)) - s = format (s, " (producer)"); - else if ((face->flags & HICN_FACE_FLAGS_APPFACE_CONS)) - s = format (s, " (consumer)"); - - if ((face->flags & HICN_FACE_FLAGS_DELETED)) - s = format (s, " (deleted)"); - } - - return s; -} - - -u8 * -format_hicn_face_all (u8 * s, int n, ...) -{ - va_list ap; - va_start (ap, n); - u32 indent = va_arg (ap, u32); - - s = format (s, "%U Faces:\n", format_white_space, indent); - - hicn_face_t *face; - - /* *INDENT-OFF* */ - pool_foreach ( face, hicn_dpoi_face_pool, - { - s = format(s, "%U\n", format_hicn_face, hicn_dpoi_get_index(face), indent); - }); - /* *INDENT-ON* */ - - return s; -} - -int -hicn_face_del (hicn_face_id_t face_id) -{ - hicn_face_t *face = hicn_dpoi_get_from_idx (face_id); - hicn_face_key_t key; - hicn_face_key_t old_key; - hicn_face_key_t old_key2; - - hicn_face_get_key (&(face->nat_addr), face->sw_if, &(face->dpo), &key); - hicn_face_input_faces_t *in_faces_vec = - hicn_face_get_vec (&(face->nat_addr), - &hicn_face_vec_hashtb); - if (in_faces_vec != NULL) - { - hicn_face_vec_t *vec = - pool_elt_at_index (hicn_vec_pool, in_faces_vec->vec_id); - u32 index_face = vec_search (*vec, face_id); - vec_del1 (*vec, index_face); - - if (vec_len (*vec) == 0) - { - pool_put_index (hicn_vec_pool, in_faces_vec->vec_id); - mhash_unset (&hicn_face_vec_hashtb, &key, (uword *) & old_key); - vec_free (*vec); - } - else - { - /* Check if the face we are deleting is the preferred one. */ - /* If so, repleace with another. */ - if (in_faces_vec->face_id == face_id) - { - in_faces_vec->face_id = (*vec)[0]; - } - } - - mhash_unset (&hicn_face_hashtb, &key, (uword *) & old_key2); - } - - int ret = HICN_ERROR_NONE; - - if (hicn_dpoi_idx_is_valid (face_id)) - { - hicn_face_t *face = hicn_dpoi_get_from_idx (face_id); - face->locks--; - if (face->locks == 0) - pool_put_index (hicn_dpoi_face_pool, face_id); - else - face->flags |= HICN_FACE_FLAGS_DELETED; - } - else - ret = HICN_ERROR_FACE_NOT_FOUND; - - - return ret; -} - -static void -hicn_iface_to_face (hicn_face_t * face, const dpo_id_t * dpo) -{ - dpo_stack (hicn_face_type, dpo->dpoi_proto, &face->dpo, dpo); - - face->flags &= ~HICN_FACE_FLAGS_IFACE; - face->flags |= HICN_FACE_FLAGS_FACE; - - if (dpo_is_adj (dpo)) - { - fib_node_init (&face->fib_node, hicn_face_fib_node_type); - fib_node_lock (&face->fib_node); - - if (dpo->dpoi_type != DPO_ADJACENCY_MIDCHAIN || - dpo->dpoi_type != DPO_ADJACENCY_MCAST_MIDCHAIN) - { - ip_adjacency_t *adj = adj_get (dpo->dpoi_index); - ip46_address_t *nh = &(adj->sub_type.nbr.next_hop); - fib_prefix_t prefix; - - if (!ip46_address_is_zero (nh)) - { - fib_prefix_from_ip46_addr (nh, &prefix); - - u32 fib_index = - fib_table_find (prefix.fp_proto, HICN_FIB_TABLE); - - face->fib_entry_index = fib_entry_track (fib_index, - &prefix, - hicn_face_fib_node_type, - hicn_dpoi_get_index - (face), - &face->fib_sibling); - } - } - } -} - -/* - * Utility that adds a new face cache entry. For the moment we assume that - * the ip_adjacency has already been set up. - */ -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_flags_t flags = (hicn_face_flags_t) 0; - flags |= HICN_FACE_FLAGS_FACE; - - hicn_face_t *face; - - face = - hicn_face_get_with_dpo (nat_address, sw_if, dpo_nh, &hicn_face_hashtb); - - if (face != NULL) - { - *pfaceid = hicn_dpoi_get_index (face); - return HICN_ERROR_FACE_ALREADY_CREATED; - } - - face = - hicn_face_get (nat_address, sw_if, &hicn_face_hashtb, dpo_nh->dpoi_index); - - dpo_id_t temp_dpo = DPO_INVALID; - temp_dpo.dpoi_index = dpo_nh->dpoi_index; - hicn_face_key_t key; - hicn_face_get_key (nat_address, sw_if, dpo_nh, &key); - - if (face == NULL) - { - - hicn_iface_add (nat_address, sw_if, pfaceid, dpo_nh->dpoi_proto, - dpo_nh->dpoi_index); - face = hicn_dpoi_get_from_idx (*pfaceid); - - mhash_set_mem (&hicn_face_hashtb, &key, (uword *) pfaceid, 0); - - hicn_face_get_key (nat_address, sw_if, &temp_dpo, &key); - mhash_set_mem (&hicn_face_hashtb, &key, (uword *) pfaceid, 0); - } - else - { - /* We found an iface and we convert it to a face */ - *pfaceid = hicn_dpoi_get_index (face); - mhash_set_mem (&hicn_face_hashtb, &key, (uword *) pfaceid, 0); - } - - hicn_iface_to_face (face, dpo_nh); - - temp_dpo.dpoi_index = ~0; - - hicn_face_input_faces_t *in_faces = - hicn_face_get_vec (nat_address, &hicn_face_vec_hashtb); - - if (in_faces == NULL) - { - hicn_face_input_faces_t in_faces_temp; - hicn_face_vec_t *vec; - pool_get (hicn_vec_pool, vec); - *vec = vec_new (hicn_face_id_t, 0); - u32 index = vec - hicn_vec_pool; - in_faces_temp.vec_id = index; - vec_add1 (*vec, *pfaceid); - - in_faces_temp.face_id = *pfaceid; - - hicn_face_get_key (nat_address, 0, &temp_dpo, &key); - - mhash_set_mem (&hicn_face_vec_hashtb, &key, - (uword *) & in_faces_temp, 0); - } - else - { - hicn_face_vec_t *vec = - pool_elt_at_index (hicn_vec_pool, in_faces->vec_id); - - /* */ - if (vec_search (*vec, *pfaceid) != ~0) - return HICN_ERROR_FACE_ALREADY_CREATED; - - vec_add1 (*vec, *pfaceid); - - hicn_iface_to_face (face, dpo_nh); - - hicn_face_get_key (nat_address, 0, &temp_dpo, &key); - - mhash_set_mem (&hicn_face_vec_hashtb, &key, (uword *) in_faces, 0); - - /* If the face is an application producer face, we set it as the preferred incoming face. */ - /* This is required to handle the CS separation, and the push api in a lightway */ - if (is_app_prod) - { - in_faces->face_id = *pfaceid; - } - } - - retx_t *retx = vlib_process_signal_event_data (vlib_get_main (), - hicn_mapme_eventmgr_process_node. - index, - HICN_MAPME_EVENT_FACE_ADD, 1, - sizeof (retx_t)); - - /* *INDENT-OFF* */ - *retx = (retx_t) { - .face_id = *pfaceid, - }; - /* *INDENT-ON* */ - - return HICN_ERROR_NONE; -} - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/faces/face.h b/hicn-plugin/src/faces/face.h deleted file mode 100644 index 234c3fcc2..000000000 --- a/hicn-plugin/src/faces/face.h +++ /dev/null @@ -1,798 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_H__ -#define __HICN_FACE_H__ - -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "../error.h" -typedef u8 hicn_face_flags_t; -typedef index_t hicn_face_id_t; - -/** - * @file face.h - * - * This file implements a general face type. The purpose of a face is to - * carry the needed information to forward interest and data packets to the - * next node in the network. There are two type of faces: complete faces (in short - * faces), and incomplete faces (in short ifaces). - * - * A face that does not contain the indication of the adjacency is an - * incomplete face (iface), otherwise it is considered to be complete. Ifaces are - * used to forward data back to the previous hICN hop from which we received an - * interest, while faces are used to forward interest packets to the next hicn node. - * Faces and ifaces are created at two different points in time. Faces are created - * when a route is added, while ifaces are created when an interest is received. - * In details, faces and ifaces carry the following information: - * - nat_addr: the ip address to perform src nat or dst nat on interest and data packets, respectively; - * - pl_id: the path label - * - locks: the number of entities using this face. When 0 the face can be deallocated - * - dpo: the dpo that identifies the next node in the vlib graph for processing the vlib - * buffer. The dpo contains the dpo.dpoi_next field that points to the next node - * in the vlib graph and the dpo.dpoi_index which is an index to adj used by the next node - * to perform the l2 rewrite. In case of ifaces, it is likely we don't know the - * adjacency when creting the face. In this case, the next node in the vlib graph - * will be the node that performs a lookup in the fib. Only in case of udp tunnels, - * which are bidirectional tunnel we know that the incoming tunnel is also the outgoing - * one, therefore in this case we store the tunnel in the dpo.dpoi_index fields. For - * all the other tunnels (which are most likely unidirectional), the source address of - * the interest will be used to retrieve the outgoing tunnel when sending the corresponding - * data back. - * - sw_if: the incoming interface of the interest - * - fib_node, fib_entry_index and fib_sibling are information used to be notified of - * changes in the adjacency pointed by the dpo. - * - * We maintain two hash tables to retrieve faces and ifaces. In particular one hash table which - * index faces and ifaces for nat_address, sw_if and dpo. This is used to retrieve existing faces - * or ifaces when an interest is received and when an new face is created. A second hash table that - * indexes vectors of faces for nat_address and sw_if. This is used to retrieve a list of possible - * incoming faces when a data is received. - */ - -/** - * @brief Structure representing a face. It containes the fields shared among - * all the types of faces as well it leaves some space for storing additional - * information specific to each type. - */ -typedef struct __attribute__ ((packed)) hicn_face_s -{ - /* Flags to idenfity if the face is incomplete (iface), complete (face) */ - /* And a network or application face (1B) */ - hicn_face_flags_t flags; - - /* Align the upcoming fields */ - u8 align; - - /* Path label (2B) */ - u16 pl_id; - - /* Number of dpo holding a reference to the dpoi (4B) */ - u32 locks; - - /* Dpo for the adjacency (8B) */ - union { - dpo_id_t dpo; - u64 align_dpo; - }; - - /* Local address of the interface sw_if */ - ip46_address_t nat_addr; - - /* local interface for the local ip address */ - u32 sw_if; - - fib_node_t fib_node; - - fib_node_index_t fib_entry_index; - - u32 fib_sibling; -} hicn_face_t; - -/* 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_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_FACE_IS_APP 0x01 - -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"); - -STATIC_ASSERT ((HICN_FACE_FLAGS_APPFACE_PROD >> - HICN_FACE_FLAGS_APPFACE_PROD_BIT) == - HICN_BUFFER_FLAGS_FACE_IS_APP, - "hicn buffer app flag does not correspond to HICN_FACE_FLAGS_APPFACE_PROD"); - -STATIC_ASSERT ((HICN_FACE_FLAGS_APPFACE_CONS >> - HICN_FACE_FLAGS_APPFACE_CONS_BIT) == - HICN_BUFFER_FLAGS_FACE_IS_APP, - "hicn buffer app flag does not correspond to HICN_FACE_FLAGS_APPFACE_PROD"); - -/** - * @brief Definition of the virtual functin table for an hICN FACE DPO. - */ -typedef struct hicn_face_vft_s -{ - u8 *(*format_face) (u8 * s, va_list * args); - /**< Format an hICN face dpo*/ - int (*hicn_face_del) (hicn_face_id_t face_id); - void (*hicn_face_get_dpo) (hicn_face_t * face, dpo_id_t * dpo); -} hicn_face_vft_t; - -#define foreach_hicn_face_counter \ - _(INTEREST_RX, 0, "Interest rx") \ - _(INTEREST_TX, 1, "Interest tx") \ - _(DATA_RX, 2, "Data rx") \ - _(DATA_TX, 3, "Data tx") \ - -typedef enum -{ -#define _(a,b,c) HICN_FACE_COUNTERS_##a = (b), - foreach_hicn_face_counter -#undef _ - HICN_N_COUNTER -} hicn_face_counters_t; - -extern mhash_t hicn_face_hashtb; - -extern const char *HICN_FACE_CTRX_STRING[]; - -#define get_face_counter_string(ctrxno) (char *)(HICN_FACE_CTRX_STRING[ctrxno]) - - -/* Vector maintaining a dpo per face */ -extern dpo_id_t *face_dpo_vec; -extern hicn_face_vft_t *face_vft_vec; - -/* Vector holding the set of face names */ -extern char **face_type_names_vec; - -/* First face type registered in the sytem.*/ -extern dpo_type_t first_type; - -/* Per-face counters */ -extern vlib_combined_counter_main_t *counters; - -/** - * @brief Return the face id from the face object - * - * @param Pointer to the face state - * @return face id - */ -always_inline hicn_face_id_t -hicn_dpoi_get_index (hicn_face_t * face_dpoi) -{ - return face_dpoi - hicn_dpoi_face_pool; -} - -/** - * @brief Return the face object from the face id. - * This method is robust to invalid face id. - * - * @param dpoi_index Face identifier - * @return Pointer to the face or NULL - */ -always_inline hicn_face_t * -hicn_dpoi_get_from_idx_safe (hicn_face_id_t dpoi_index) -{ - if (!pool_is_free_index(hicn_dpoi_face_pool, dpoi_index)) - return (hicn_face_t *) pool_elt_at_index (hicn_dpoi_face_pool, dpoi_index); - else - return NULL; -} - -/** - * @brief Return the face from the face id. Face id must be valid. - * - * @param dpoi_index Face identifier - * @return Pointer to the face - */ -always_inline hicn_face_t * -hicn_dpoi_get_from_idx (hicn_face_id_t dpoi_index) -{ - return (hicn_face_t *) pool_elt_at_index (hicn_dpoi_face_pool, dpoi_index); -} - -/** - * @brief Return true if the face id belongs to an existing face - */ -always_inline int -hicn_dpoi_idx_is_valid (hicn_face_id_t face_id) -{ - return pool_len (hicn_dpoi_face_pool) > face_id - && !pool_is_free_index (hicn_dpoi_face_pool, face_id); -} - - -/** - * @brief Add a lock to the face dpo - * - * @param dpo Pointer to the face dpo - */ -always_inline void -hicn_face_lock_with_id (hicn_face_id_t face_id) -{ - hicn_face_t *face; - face = hicn_dpoi_get_from_idx (face_id); - face->locks++; -} - -/** - * @brief Remove a lock to the face dpo. Deallocate the face id locks == 0 - * - * @param dpo Pointer to the face dpo - */ -always_inline void -hicn_face_unlock_with_id (hicn_face_id_t face_id) -{ - hicn_face_t *face; - face = hicn_dpoi_get_from_idx (face_id); - face->locks--; -} - -/** - * @brief Add a lock to the face through its dpo - * - * @param dpo Pointer to the face dpo - */ -always_inline void -hicn_face_lock (dpo_id_t * dpo) -{ - hicn_face_lock_with_id(dpo->dpoi_index); -} - -/** - * @brief Remove a lock to the face through its dpo. Deallocate the face id locks == 0 - * - * @param dpo Pointer to the face dpo - */ -always_inline void -hicn_face_unlock (dpo_id_t * dpo) -{ - hicn_face_unlock_with_id (dpo->dpoi_index); -} - - -/** - * @brief Init the internal structures of the face module - * - * Must be called before processing any packet - */ -void hicn_face_module_init (vlib_main_t * vm); - -u8 * format_hicn_face (u8 * s, va_list * args); - - -/** - * @brief Format all the existing faces - * - * @param s Pointer to a previous string. If null it will be initialize - * @param n Number of input parameters - * @return String with the faces formatted - */ -u8 *format_hicn_face_all (u8 * s, int n, ...); - -/** - * @brief Delete a face - * - * @param face_id Id of the face to delete - * @return HICN_ERROR_FACE_NOT_FOUND if the face does not exist, otherwise - * HICN_ERROR_NONE - */ -int hicn_face_del (hicn_face_id_t face_id); - -/** - * @bried vector of faces used to collect faces having the same local address - * - */ -typedef hicn_face_id_t *hicn_face_vec_t; - -typedef struct hicn_input_faces_s_ -{ - /* Vector of all possible input faces */ - u32 vec_id; - - /* Preferred face. If an prod_app face is in the vector it will be the preferred one. */ - /* It's not possible to have multiple prod_app face in the same vector, they would have */ - /* the same local address. Every prod_app face is a point-to-point face between the forwarder */ - /* and the application. */ - hicn_face_id_t face_id; - -} hicn_face_input_faces_t; - -/** - * Pool containing the vector of possible incoming faces. - */ -extern hicn_face_vec_t *hicn_vec_pool; - -/** - * Hash tables that indexes a face by remote address. For fast lookup when an - * interest arrives. - */ -extern mhash_t hicn_face_vec_hashtb; - - -/** - * Key definition for the mhash table. An face is uniquely identified by ip - * address, the interface id and a dpo pointing to the next node in the vlib graph. - * The ip address can correspond to the remote ip address of the next hicn hop, - * or to the local address of the receiving interface. The former is used to - * retrieve the incoming face when an interest is received, the latter when - * the arring packet is a data. If the face is a regular face - * In case of iface, the following structure can be filled in different ways: - * - dpo equal to DPO_INVALID when the iface is a regular hICN iface - * - in case of udp_tunnel dpo = - * { - * .dpoi_index = tunnel_id, - * .dpoi_type = DPO_FIRST, //We don't need the type, we leave it invalid - * .dpoi_proto = DPO_PROTO_IP4 or DPO_PROTO_IP6, - * .dpoi_next_node = HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP or - * HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP or - * HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP or - * HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP - * } - */ -typedef struct __attribute__ ((packed)) hicn_face_key_s -{ - ip46_address_t addr; - union { - dpo_id_t dpo; - u64 align_dpo; - }; - u32 sw_if; -} hicn_face_key_t; - -/** - * @brief Create the key object for the mhash. Fill in the key object with the - * expected values. - * - * @param addr nat address of the face - * @param sw_if interface associated to the face - * @param key Pointer to an allocated hicn_face_ip_key_t object - */ -always_inline void -hicn_face_get_key (const ip46_address_t * addr, - u32 sw_if, const dpo_id_t * dpo, hicn_face_key_t * key) -{ - key->dpo = *dpo; - key->addr = *addr; - key->sw_if = sw_if; -} - -/** - * @brief Get the face obj from the nat address. Does not add any lock. - * - * @param addr Ip v4 address used to create the key for the hash table. - * @param sw_if Software interface id used to create the key for the hash table. - * @param hashtb Hash table (remote or local) where to perform the lookup. - * - * @result Pointer to the face. - */ -always_inline hicn_face_t * -hicn_face_get (const ip46_address_t * addr, u32 sw_if, mhash_t * hashtb, index_t adj_index) -{ - hicn_face_key_t key; - - dpo_id_t dpo = DPO_INVALID; - - dpo.dpoi_index = adj_index; - - hicn_face_get_key (addr, sw_if, &dpo, &key); - - hicn_face_id_t *dpoi_index = (hicn_face_id_t *) mhash_get (hashtb, - &key); - - if ( dpoi_index != NULL) - { - hicn_face_lock_with_id(*dpoi_index); - return hicn_dpoi_get_from_idx (*dpoi_index); - } - - return NULL; -} - -/** - * @brief Get the face obj from the nat address and the dpo. Does not add any lock. - * - * @param addr Ip v4 address used to create the key for the hash table. - * @param sw_if Software interface id used to create the key for the hash table. - * @param hashtb Hash table (remote or local) where to perform the lookup. - * - * @result Pointer to the face. - */ -always_inline hicn_face_t * -hicn_face_get_with_dpo (const ip46_address_t * addr, u32 sw_if, const dpo_id_t * dpo, mhash_t * hashtb) -{ - hicn_face_key_t key; - - hicn_face_get_key (addr, sw_if, dpo, &key); - - hicn_face_id_t *dpoi_index = (hicn_face_id_t *) mhash_get (hashtb, - &key); - - if ( dpoi_index != NULL) - { - hicn_face_lock_with_id(*dpoi_index); - return hicn_dpoi_get_from_idx (*dpoi_index); - } - - return NULL; -} - -/** - * @brief Get the vector of faces from the ip v4 address. Does not add any lock. - * - * @param addr Ip v4 address used to create the key for the hash table. - * @param sw_if Software interface id used to create the key for the hash table. - * @param hashtb Hash table (remote or local) where to perform the lookup. - * - * @result Pointer to the face. - */ -always_inline hicn_face_input_faces_t * -hicn_face_get_vec (const ip46_address_t * addr, - mhash_t * hashtb) -{ - hicn_face_key_t key; - - dpo_id_t dpo = DPO_INVALID; - - hicn_face_get_key (addr, 0, &dpo, &key); - return (hicn_face_input_faces_t *) mhash_get (hashtb, &key); -} - -/** - * @brief Create a new face ip. API for other modules (e.g., routing) - * - * @param dpo_nh dpo contained in the face that points to the next node in - * the vlib graph - * @param nat_addr nat ip v4 or v6 address of the face - * @param sw_if interface associated to the face - * @param pfaceid Pointer to return the face id - * @param is_app_prod if HICN_FACE_FLAGS_APPFACE_PROD the face is a local application face, all other values are ignored - * @return HICN_ERROR_FACE_NO_GLOBAL_IP if the face does not have a globally - * 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); - -/** - * @brief Create a new incomplete face ip. (Meant to be used by the data plane) - * - * @param local_addr Local ip v4 or v6 address of the face - * @param remote_addr Remote ip v4 or v6 address of the face - * @param sw_if interface associated to the face - * @param pfaceid Pointer to return the face id - * @return HICN_ERROR_FACE_NO_GLOBAL_IP if the face does not have a globally - * reachable ip address, otherwise HICN_ERROR_NONE - */ -always_inline void -hicn_iface_add (ip46_address_t * nat_address, int sw_if, - hicn_face_id_t * pfaceid, dpo_proto_t proto, - u32 adj_index) -{ - hicn_face_t *face; - pool_get (hicn_dpoi_face_pool, face); - - clib_memcpy (&(face->nat_addr), nat_address, - sizeof (ip46_address_t)); - face->sw_if = sw_if; - - face->dpo.dpoi_type = DPO_FIRST; - face->dpo.dpoi_proto = DPO_PROTO_NONE; - face->dpo.dpoi_index = adj_index; - face->dpo.dpoi_next_node = 0; - face->pl_id = (u16) 0; - face->flags = HICN_FACE_FLAGS_IFACE; - face->locks = 1; - - hicn_face_key_t key; - hicn_face_get_key (nat_address, sw_if, &face->dpo, &key); - *pfaceid = hicn_dpoi_get_index (face); - - mhash_set_mem (&hicn_face_hashtb, &key, (uword *) pfaceid, 0); - - for (int i = 0; i < HICN_N_COUNTER; i++) - { - vlib_validate_combined_counter (&counters[(*pfaceid) * HICN_N_COUNTER], - i); - vlib_zero_combined_counter (&counters[(*pfaceid) * HICN_N_COUNTER], i); - } -} - -/**** Helpers to manipulate faces and ifaces from the face/iface input nodes ****/ - -/** - * @brief Retrieve a vector of faces from the ip4 local address and returns its index. - * - * @param vec: Result of the lookup. If no face exists for the local address vec = NULL - * @param hicnb_flags: Flags that indicate whether the face is an application - * face or not - * @param local_addr: Ip v4 nat address of the face - * @param sw_if: software interface id of the face - * - * @result HICN_ERROR_FACE_NOT_FOUND if the face does not exist, otherwise HICN_ERROR_NONE. - */ -always_inline int -hicn_face_ip4_lock (hicn_face_id_t * face_id, - u32 * in_faces_vec_id, - u8 * hicnb_flags, - const ip4_address_t * nat_addr) -{ - ip46_address_t ip_address = {0}; - ip46_address_set_ip4(&ip_address, nat_addr); - hicn_face_input_faces_t *in_faces_vec = - hicn_face_get_vec (&ip_address, &hicn_face_vec_hashtb); - - if (PREDICT_FALSE (in_faces_vec == NULL)) - return HICN_ERROR_FACE_NOT_FOUND; - - *in_faces_vec_id = in_faces_vec->vec_id; - hicn_face_t *face = hicn_dpoi_get_from_idx (in_faces_vec->face_id); - - *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; - *hicnb_flags |= - (face->flags & HICN_FACE_FLAGS_APPFACE_PROD) >> - HICN_FACE_FLAGS_APPFACE_PROD_BIT; - - *face_id = in_faces_vec->face_id; - - return HICN_ERROR_NONE; -} - -/** - * @brief Retrieve a face from the ip6 local address and returns its dpo. This - * method adds a lock on the face state. - * - * @param dpo: Result of the lookup. If the face doesn't exist dpo = NULL - * @param hicnb_flags: Flags that indicate whether the face is an application - * face or not - * @param nat_addr: Ip v6 nat address of the face - * @param sw_if: software interface id of the face - * - * @result HICN_ERROR_FACE_NOT_FOUND if the face does not exist, otherwise HICN_ERROR_NONE. - */ -always_inline int -hicn_face_ip6_lock (hicn_face_id_t * face_id, - u32 * in_faces_vec_id, - u8 * hicnb_flags, - const ip6_address_t * nat_addr) -{ - hicn_face_input_faces_t *in_faces_vec = - hicn_face_get_vec ((ip46_address_t *)nat_addr, &hicn_face_vec_hashtb); - - if (PREDICT_FALSE (in_faces_vec == NULL)) - return HICN_ERROR_FACE_NOT_FOUND; - - *in_faces_vec_id = in_faces_vec->vec_id; - hicn_face_t *face = hicn_dpoi_get_from_idx (in_faces_vec->face_id); - - *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; - *hicnb_flags |= - (face->flags & HICN_FACE_FLAGS_APPFACE_PROD) >> - HICN_FACE_FLAGS_APPFACE_PROD_BIT; - - *face_id = in_faces_vec->face_id; - - return HICN_ERROR_NONE; -} - -/** - * @brief Call back to get the adj of the tunnel - */ -static adj_walk_rc_t -hicn4_iface_adj_walk_cb (adj_index_t ai, - void *ctx) -{ - - hicn_face_t *face = (hicn_face_t *)ctx; - - dpo_set(&face->dpo, DPO_ADJACENCY_MIDCHAIN, DPO_PROTO_IP4, ai); - adj_nbr_midchain_stack(ai, &face->dpo); - - return (ADJ_WALK_RC_CONTINUE); -} - -/** - * @brief Retrieve, or create if it doesn't exist, a face from the ip6 local - * address and returns its dpo. This method adds a lock on the face state. - * - * @param dpo: Result of the lookup - * @param hicnb_flags: Flags that indicate whether the face is an application - * face or not - * @param nat_addr: Ip v4 remote address of the face - * @param sw_if: software interface id of the face - * @param node_index: vlib edge index to use in the packet processing - */ -always_inline void -hicn_iface_ip4_add_and_lock (hicn_face_id_t * index, - u8 * hicnb_flags, - const ip4_address_t * nat_addr, - u32 sw_if, u32 adj_index, u32 node_index) -{ - /*All (complete) faces are indexed by remote addess as well */ - - ip46_address_t ip_address = {0}; - ip46_address_set_ip4(&ip_address, nat_addr); - - /* if the face exists, it adds a lock */ - hicn_face_t *face = - hicn_face_get (&ip_address, sw_if, &hicn_face_hashtb, adj_index); - - if (face == NULL) - { - hicn_face_id_t idx; - hicn_iface_add (&ip_address, sw_if, &idx, DPO_PROTO_IP4, adj_index); - - face = hicn_dpoi_get_from_idx(idx); - - face->dpo.dpoi_type = DPO_FIRST; - face->dpo.dpoi_proto = DPO_PROTO_IP4; - face->dpo.dpoi_index = adj_index; - face->dpo.dpoi_next_node = node_index; - - /* if (nat_addr->as_u32 == 0) */ - /* { */ - adj_nbr_walk(face->sw_if, - FIB_PROTOCOL_IP4, - hicn4_iface_adj_walk_cb, - face); - /* } */ - - *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; - - *index = idx; - return; - } - else - { - /* unlock the face. We don't take a lock on each interest we receive */ - hicn_face_id_t face_id = hicn_dpoi_get_index(face); - hicn_face_unlock_with_id(face_id); - } - - /* 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); -} - -/** - * @brief Call back to get the adj of the tunnel - */ -static adj_walk_rc_t -hicn6_iface_adj_walk_cb (adj_index_t ai, - void *ctx) -{ - - hicn_face_t *face = (hicn_face_t *)ctx; - - ip_adjacency_t *adj = adj_get(ai); - if ((adj->lookup_next_index == IP_LOOKUP_NEXT_MIDCHAIN) || - (adj->lookup_next_index == IP_LOOKUP_NEXT_MCAST_MIDCHAIN)) - { - dpo_set(&face->dpo, DPO_ADJACENCY_MIDCHAIN, adj->ia_nh_proto, ai); - adj_nbr_midchain_stack(ai, &face->dpo); - } - - return (ADJ_WALK_RC_CONTINUE); -} - - -/** - * @brief Retrieve, or create if it doesn't exist, a face from the ip6 local - * address and returns its dpo. This method adds a lock on the face state. - * - * @param dpo: Result of the lookup - * @param hicnb_flags: Flags that indicate whether the face is an application - * face or not - * @param nat_addr: Ip v6 remote address of the face - * @param sw_if: software interface id of the face - * @param node_index: vlib edge index to use in the packet processing - */ -always_inline void -hicn_iface_ip6_add_and_lock (hicn_face_id_t * index, - u8 * hicnb_flags, - const ip6_address_t * nat_addr, - u32 sw_if, u32 adj_index, u32 node_index) -{ - /*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_hashtb, adj_index); - - if (face == NULL) - { - hicn_face_id_t idx; - hicn_iface_add ((ip46_address_t *) nat_addr, sw_if, &idx, DPO_PROTO_IP6, adj_index); - - face = hicn_dpoi_get_from_idx(idx); - - face->dpo.dpoi_type = DPO_FIRST; - face->dpo.dpoi_proto = DPO_PROTO_IP6; - face->dpo.dpoi_index = adj_index; - face->dpo.dpoi_next_node = node_index; - - adj_nbr_walk(face->sw_if, - FIB_PROTOCOL_IP6, - hicn6_iface_adj_walk_cb, - face); - - *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; - - *index = idx; - - return; - } - else - { - /* unlock the face. We don't take a lock on each interest we receive */ - hicn_face_id_t face_id = hicn_dpoi_get_index(face); - hicn_face_unlock_with_id(face_id); - } - - /* 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); -} - -#endif // __HICN_FACE_H__ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/faces/face_cli.c b/hicn-plugin/src/faces/face_cli.c deleted file mode 100644 index e9e516cc6..000000000 --- a/hicn-plugin/src/faces/face_cli.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "face.h" -#include "../error.h" - -static clib_error_t * -hicn_face_cli_show_command_fn (vlib_main_t * vm, - unformat_input_t * main_input, - vlib_cli_command_t * cmd) -{ - - hicn_face_id_t face_id = HICN_FACE_NULL; - char *face_type_name = NULL; - int found = ~0; - int deleted = 0; - u8 *n = 0; - u8 *s = 0; - vlib_counter_t v; - - /* Get a line of input. */ - unformat_input_t _line_input, *line_input = &_line_input; - if (unformat_user (main_input, unformat_line_input, line_input)) - { - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "%u", &face_id)) - ; - else if (unformat (line_input, "type %s", &face_type_name)) - ; - else if (unformat (line_input, "deleted")) - deleted = 1; - else - { - return clib_error_return (0, "%s", - get_error_string - (HICN_ERROR_CLI_INVAL)); - } - } - - if (face_type_name != NULL) - { - int idx = 0; - vec_foreach_index (idx, face_type_names_vec) - { - if (!strcmp (face_type_names_vec[idx], face_type_name)) - found = idx; - } - if (found == ~0) - return (clib_error_return (0, "Face type unknown")); - } - - } - - if (face_id != HICN_FACE_NULL) - { - if (!hicn_dpoi_idx_is_valid (face_id)) - return clib_error_return (0, "%s", - get_error_string - (HICN_ERROR_FACE_NOT_FOUND)); - - hicn_face_t *face = hicn_dpoi_get_from_idx (face_id); - vlib_cli_output (vm, "%U\n", format_hicn_face, face_id, 0 /*indent */ ); - - u32 indent = 3; - - for (int i = 0; i < HICN_N_COUNTER; i++) - { - vlib_get_combined_counter (&counters - [hicn_dpoi_get_index (face) * - HICN_N_COUNTER], i, &v); - s = - format (s, "%U%s", format_white_space, indent, - HICN_FACE_CTRX_STRING[i]); - - if (n) - _vec_len (n) = 0; - n = format (n, "packets"); - s = - format (s, "%U%-16v%16Ld", format_white_space, - 30 - strlen (HICN_FACE_CTRX_STRING[i]), n, v.packets); - - _vec_len (n) = 0; - n = format (n, "bytes"); - s = format (s, "\n%U%-16v%16Ld\n", - format_white_space, indent + 30, n, v.bytes); - } - vlib_cli_output (vm, "%s\n", s); - } - else - { - if (found != ~0) - { - hicn_face_t *face; - /* *INDENT-OFF* */ - pool_foreach(face, hicn_dpoi_face_pool, - { - if (!((face->flags & HICN_FACE_FLAGS_DELETED) && !deleted)) - { - if (face->flags) - { - vlib_cli_output(vm, "%U\n", format_hicn_face, hicn_dpoi_get_index(face), 0); - u8 * s = 0; - u32 indent = 3; - - for (int i = 0; i < HICN_N_COUNTER; i++) - { - vlib_get_combined_counter (&counters[hicn_dpoi_get_index(face) * HICN_N_COUNTER], i, &v); - s = format (s, "%U%s",format_white_space, indent, HICN_FACE_CTRX_STRING[i]); - - if (n) - _vec_len (n) = 0; - n = format (n, "packets"); - s = format (s, "%U%-16v%16Ld", format_white_space, 30-strlen(HICN_FACE_CTRX_STRING[i]), n, v.packets); - - _vec_len (n) = 0; - n = format (n, "bytes"); - s = format (s, "\n%U%-16v%16Ld\n", - format_white_space, indent+30, n, v.bytes); - } - vlib_cli_output (vm, "%s\n", s); - } - } - }); - /* *INDENT-ON* */ - } - else - { - hicn_face_t *face; - /* *INDENT-OFF* */ - pool_foreach(face, hicn_dpoi_face_pool, - { - if (!((face->flags & HICN_FACE_FLAGS_DELETED) && !deleted)) - { - vlib_cli_output(vm, "%U\n", format_hicn_face, hicn_dpoi_get_index(face), 0); - u32 indent = 3; - u8 * s = 0; - - for (int i = 0; i < HICN_N_COUNTER; i++) - { - vlib_get_combined_counter (&counters[hicn_dpoi_get_index(face) * HICN_N_COUNTER], i, &v); - s = format (s, "%U%s",format_white_space, indent, HICN_FACE_CTRX_STRING[i]); - - if (n) - _vec_len (n) = 0; - n = format (n, "packets"); - s = format (s, "%U%-16v%16Ld", format_white_space, 30-strlen(HICN_FACE_CTRX_STRING[i]), n, v.packets); - - _vec_len (n) = 0; - n = format (n, "bytes"); - s = format (s, "\n%U%-16v%16Ld\n", - format_white_space, indent+30, n, v.bytes); - } - vlib_cli_output (vm, "%s\n", s); - } - }); - /* *INDENT-ON* */ - } - } - - return 0; -} - -/* cli declaration for 'show faces' */ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (hicn_face_cli_show_command, static) = -{ - .path = "hicn face show", - .short_help = "hicn face show []", - .function = hicn_face_cli_show_command_fn, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/faces/face_node.c b/hicn-plugin/src/faces/face_node.c deleted file mode 100644 index e1fd81ca0..000000000 --- a/hicn-plugin/src/faces/face_node.c +++ /dev/null @@ -1,940 +0,0 @@ -/* - * Copyright (c) 2020 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 "face.h" -#include "face_node.h" -#include "../strategy_dpo_manager.h" -#include "face.h" -#include "../cache_policies/cs_lru.h" -#include "../infra.h" -#include "../hicn.h" - -/** - * @File - * - * Definition of the nodes for ip incomplete faces. - */ - -vlib_node_registration_t hicn4_face_input_node; -vlib_node_registration_t hicn4_face_output_node; -vlib_node_registration_t hicn6_face_input_node; -vlib_node_registration_t hicn6_face_output_node; - -#define ip_v4 4 -#define ip_v6 6 - -static char *hicn4_face_input_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -static char *hicn6_face_input_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - u8 packet_data[60]; -} -hicn4_face_input_trace_t; - -typedef enum -{ - HICN4_FACE_INPUT_NEXT_DATA, - HICN4_FACE_INPUT_NEXT_MAPME, - HICN4_FACE_INPUT_NEXT_ERROR_DROP, - HICN4_FACE_INPUT_N_NEXT, -} hicn4_face_input_next_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - u8 packet_data[60]; -} -hicn6_face_input_trace_t; - -typedef enum -{ - HICN6_FACE_INPUT_NEXT_DATA, - HICN6_FACE_INPUT_NEXT_MAPME, - HICN6_FACE_INPUT_NEXT_ERROR_DROP, - HICN6_FACE_INPUT_N_NEXT, -} hicn6_face_input_next_t; - -#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_ERROR_DROP_IP4 HICN4_FACE_INPUT_NEXT_ERROR_DROP -#define NEXT_ERROR_DROP_IP6 HICN6_FACE_INPUT_NEXT_ERROR_DROP - -#define IP_HEADER_4 ip4_header_t -#define IP_HEADER_6 ip6_header_t - -#define LOCK_DPO_FACE_IP4 hicn_face_ip4_lock -#define LOCK_DPO_FACE_IP6 hicn_face_ip6_lock - -#define TRACE_INPUT_PKT_IP4 hicn4_face_input_trace_t -#define TRACE_INPUT_PKT_IP6 hicn6_face_input_trace_t - -/* - * NOTE: Both hicn4_face_input_node_fn and hicn6_face_input_node_fn - * present a similar codebase. Macro are hard to debug, although the - * followind code is pretty straighforward and most of the complexity is in - * functions that can be easily debug. - */ -#define face_input_x1(ipv) \ - do{ \ - vlib_buffer_t *b0; \ - u32 bi0; \ - u32 next0 = NEXT_ERROR_DROP_IP##ipv; \ - IP_HEADER_##ipv * ip_hdr = NULL; \ - hicn_buffer_t * hicnb0; \ - 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, 2*CLIB_CACHE_LINE_BYTES, STORE); \ - CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES , LOAD); \ - } \ - /* Dequeue a packet buffer */ \ - bi0 = from[0]; \ - from += 1; \ - n_left_from -= 1; \ - to_next[0] = bi0; \ - to_next += 1; \ - n_left_to_next -= 1; \ - \ - b0 = vlib_get_buffer (vm, bi0); \ - hicnb0 = hicn_get_buffer(b0); \ - ip_hdr = (IP_HEADER_##ipv *) vlib_buffer_get_current(b0); \ - \ - u8 is_icmp = ip_hdr->protocol == IPPROTO_ICMPV##ipv; \ - \ - next0 = is_icmp*NEXT_MAPME_IP##ipv + \ - (1-is_icmp)*NEXT_DATA_IP##ipv; \ - \ - ret = LOCK_DPO_FACE_IP##ipv \ - (&(hicnb0->face_id), \ - &(hicnb0->in_faces_vec_id), \ - &hicnb0->flags, \ - &(ip_hdr->dst_address)); \ - \ - if ( PREDICT_FALSE(ret != HICN_ERROR_NONE) ) \ - next0 = NEXT_ERROR_DROP_IP##ipv; \ - else \ - { \ - 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; \ - } \ - \ - 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->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), \ - sizeof (t->packet_data)); \ - } \ - \ - \ - /* 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); \ - }while(0) - - -#define face_input_x2(ipv) \ - do{ \ - vlib_buffer_t *b0, *b1; \ - u32 bi0, bi1; \ - u32 next0 = NEXT_ERROR_DROP_IP##ipv; \ - u32 next1 = NEXT_ERROR_DROP_IP##ipv; \ - IP_HEADER_##ipv * ip_hdr0 = NULL; \ - IP_HEADER_##ipv * ip_hdr1 = NULL; \ - hicn_buffer_t * hicnb0; \ - hicn_buffer_t * hicnb1; \ - int ret0, ret1; \ - /* Prefetch for next iteration. */ \ - { \ - vlib_buffer_t *b2, *b3; \ - b2 = vlib_get_buffer (vm, from[2]); \ - b3 = vlib_get_buffer (vm, from[3]); \ - CLIB_PREFETCH (b2, 2*CLIB_CACHE_LINE_BYTES, STORE); \ - CLIB_PREFETCH (b3, 2*CLIB_CACHE_LINE_BYTES, STORE); \ - CLIB_PREFETCH (b2->data, CLIB_CACHE_LINE_BYTES , LOAD); \ - CLIB_PREFETCH (b3->data, CLIB_CACHE_LINE_BYTES , LOAD); \ - } \ - /* Dequeue a packet buffer */ \ - bi0 = from[0]; \ - bi1 = from[1]; \ - from += 2; \ - n_left_from -= 2; \ - to_next[0] = bi0; \ - to_next[1] = bi1; \ - to_next += 2; \ - n_left_to_next -= 2; \ - \ - b0 = vlib_get_buffer (vm, bi0); \ - b1 = vlib_get_buffer (vm, bi1); \ - hicnb0 = hicn_get_buffer(b0); \ - hicnb1 = hicn_get_buffer(b1); \ - 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; \ - \ - 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; \ - \ - \ - ret0 = LOCK_DPO_FACE_IP##ipv \ - (&(hicnb0->face_id), \ - &(hicnb0->in_faces_vec_id), \ - &hicnb0->flags, \ - &(ip_hdr0->dst_address)); \ - \ - ret1 = LOCK_DPO_FACE_IP##ipv \ - (&(hicnb1->face_id), \ - &(hicnb1->in_faces_vec_id), \ - &hicnb1->flags, \ - &(ip_hdr1->dst_address)); \ - \ - if ( PREDICT_FALSE(ret0 != HICN_ERROR_NONE) ) \ - next0 = NEXT_ERROR_DROP_IP##ipv; \ - else \ - { \ - 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; \ - } \ - \ - if ( PREDICT_FALSE(ret1 != HICN_ERROR_NONE) ) \ - next1 = NEXT_ERROR_DROP_IP##ipv; \ - else \ - { \ - 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, b1)); \ - stats.pkts_data_count += 1; \ - } \ - \ - 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->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), \ - sizeof (t->packet_data)); \ - } \ - \ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ - (b1->flags & VLIB_BUFFER_IS_TRACED))) \ - { \ - TRACE_INPUT_PKT_IP##ipv *t = \ - vlib_add_trace (vm, node, b1, sizeof (*t)); \ - t->pkt_type = HICN_PKT_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), \ - sizeof (t->packet_data)); \ - } \ - \ - \ - /* Verify speculative enqueue, 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(0) - - -static uword -hicn4_face_input_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next, next_index; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; - u32 thread_index = vm->thread_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); - - /* Dual loop, X2 */ - while (n_left_from >= 4 && n_left_to_next >= 2) - { - face_input_x2 (4); - } - - /* Dual loop, X1 */ - while (n_left_from > 0 && n_left_to_next > 0) - { - face_input_x1 (4); - } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, node->node_index, - HICNFWD_ERROR_DATAS, stats.pkts_data_count); - - return (frame->n_vectors); -} - -/* packet trace format function */ -static u8 * -hicn4_face_input_format_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 *); - hicn4_face_input_trace_t *t = - va_arg (*args, hicn4_face_input_trace_t *); - - s = format (s, "FACE_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)); - return (s); -} - - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(hicn4_face_input_node) = -{ - .function = hicn4_face_input_node_fn, - .name = "hicn4-face-input", - .vector_size = sizeof(u32), - .format_trace = hicn4_face_input_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(hicn4_face_input_error_strings), - .error_strings = hicn4_face_input_error_strings, - .n_next_nodes = HICN4_FACE_INPUT_N_NEXT, - /* edit / add dispositions here */ - .next_nodes = - { - [HICN4_FACE_INPUT_NEXT_DATA] = "hicn-data-pcslookup", - [HICN4_FACE_INPUT_NEXT_MAPME] = "hicn-mapme-ack", - [HICN4_FACE_INPUT_NEXT_ERROR_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -/** - * @brief IPv6 face input node function - * @see hicn6_face_input_node_fn - */ -static uword -hicn6_face_input_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next, next_index; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; - u32 thread_index = vm->thread_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); - - /* Dual loop, X2 */ - while (n_left_from >= 4 && n_left_to_next >= 2) - { - face_input_x2 (6); - } - - /* Dual loop, X1 */ - while (n_left_from > 0 && n_left_to_next > 0) - { - face_input_x1 (6); - } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, node->node_index, - HICNFWD_ERROR_DATAS, stats.pkts_data_count); - - return (frame->n_vectors); -} - -/* packet trace format function */ -static u8 * -hicn6_face_input_format_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 *); - hicn6_face_input_trace_t *t = - va_arg (*args, hicn6_face_input_trace_t *); - - s = format (s, "FACE_IP6_INPUT: pkt: %d, sw_if_index %d, next index %d\n%U", - (int) t->pkt_type, t->sw_if_index, t->next_index, - format_ip6_header, t->packet_data, sizeof (t->packet_data)); - return (s); -} - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(hicn6_face_input_node) = -{ - .function = hicn6_face_input_node_fn, - .name = "hicn6-face-input", - .vector_size = sizeof(u32), - .format_trace = hicn6_face_input_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(hicn6_face_input_error_strings), - .error_strings = hicn6_face_input_error_strings, - .n_next_nodes = HICN6_FACE_INPUT_N_NEXT, - /* edit / add dispositions here */ - .next_nodes = - { - [HICN6_FACE_INPUT_NEXT_DATA] = "hicn-data-pcslookup", - [HICN6_FACE_INPUT_NEXT_MAPME] = "hicn-mapme-ack", - [HICN6_FACE_INPUT_NEXT_ERROR_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -/**** FACE OUTPUT *****/ - -typedef enum -{ - HICN4_FACE_OUTPUT_NEXT_ECHO_REPLY, - HICN4_FACE_OUTPUT_NEXT_UDP4_ENCAP, - HICN4_FACE_OUTPUT_NEXT_UDP6_ENCAP, - HICN4_FACE_OUTPUT_N_NEXT, -} hicn4_face_output_next_t; - -typedef enum -{ - HICN6_FACE_OUTPUT_NEXT_ECHO_REPLY, - HICN6_FACE_OUTPUT_NEXT_UDP4_ENCAP, - HICN6_FACE_OUTPUT_NEXT_UDP6_ENCAP, - 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) -{ - - /* if ((face->flags & HICN_FACE_FLAGS_APPFACE_PROD) && hicn_face_match_probe(b0, face, next)) */ - /* return; */ - - hicn_header_t *hicn = vlib_buffer_get_current (b0); - - //hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data; - - ip46_address_t temp_addr; - ip46_address_reset (&temp_addr); - hicn_type_t type = hicn_get_buffer (b0)->type; - hicn_ops_vft[type.l1]->rewrite_interest (type, &hicn->protocol, - &face->nat_addr, &temp_addr); - - if (ip46_address_is_ip4(&face->nat_addr)) - b0->flags |= VNET_BUFFER_F_OFFLOAD_IP_CKSUM; - - b0->flags |= VNET_BUFFER_F_OFFLOAD_TCP_CKSUM; - - ASSERT(face->flags & HICN_FACE_FLAGS_FACE); - - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = face->dpo.dpoi_index; - *next = face->dpo.dpoi_next_node; -} - -static char *hicn4_face_output_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -static char *hicn6_face_output_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - u8 packet_data[60]; -} -hicn4_face_output_trace_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - u8 packet_data[60]; -} -hicn6_face_output_trace_t; - -#define TRACE_OUTPUT_PKT_IP4 hicn4_face_output_trace_t -#define TRACE_OUTPUT_PKT_IP6 hicn6_face_output_trace_t - -#define face_output_x1(ipv) \ - do { \ - vlib_buffer_t *b0; \ - u32 bi0; \ - u32 next0 = ~0; \ - hicn_face_t * face; \ - \ - /* 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, STORE); \ - CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES , STORE); \ - } \ - /* Dequeue a packet buffer */ \ - bi0 = from[0]; \ - from += 1; \ - n_left_from -= 1; \ - to_next[0] = bi0; \ - to_next += 1; \ - n_left_to_next -= 1; \ - \ - b0 = vlib_get_buffer (vm, bi0); \ - \ - hicn_face_id_t face_id = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; \ - face = \ - hicn_dpoi_get_from_idx (face_id); \ - \ - if (PREDICT_TRUE(face != NULL)) \ - { \ - hicn_face_rewrite_interest \ - (vm, b0, face, &next0); \ - stats.pkts_interest_count += 1; \ - vlib_increment_combined_counter ( \ - &counters[face_id * HICN_N_COUNTER], \ - thread_index, \ - HICN_FACE_COUNTERS_INTEREST_TX, \ - 1, \ - vlib_buffer_length_in_chain(vm, b0)); \ - } \ - \ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ - (b0->flags & VLIB_BUFFER_IS_TRACED))) \ - { \ - TRACE_OUTPUT_PKT_IP##ipv *t = \ - vlib_add_trace (vm, node, b0, sizeof (*t)); \ - t->pkt_type = HICN_PKT_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), \ - sizeof (t->packet_data)); \ - } \ - \ - \ - /* 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); \ - }while(0) - -#define face_output_x2(ipv) \ - do { \ - vlib_buffer_t *b0, *b1; \ - u32 bi0, bi1; \ - u32 next0 = ~0; \ - u32 next1 = ~0; \ - hicn_face_t *face0, *face1; \ - \ - /* Prefetch for next iteration. */ \ - { \ - vlib_buffer_t *b2, *b3; \ - b2 = vlib_get_buffer (vm, from[2]); \ - b3 = vlib_get_buffer (vm, from[3]); \ - CLIB_PREFETCH (b2, CLIB_CACHE_LINE_BYTES, STORE); \ - CLIB_PREFETCH (b3, CLIB_CACHE_LINE_BYTES, STORE); \ - CLIB_PREFETCH (b2->data, CLIB_CACHE_LINE_BYTES , STORE); \ - CLIB_PREFETCH (b3->data, CLIB_CACHE_LINE_BYTES , STORE); \ - } \ - /* Dequeue a packet buffer */ \ - bi0 = from[0]; \ - bi1 = from[1]; \ - from += 2; \ - n_left_from -= 2; \ - to_next[0] = bi0; \ - to_next[1] = bi1; \ - to_next += 2; \ - n_left_to_next -= 2; \ - \ - b0 = vlib_get_buffer (vm, bi0); \ - b1 = vlib_get_buffer (vm, bi1); \ - \ - hicn_face_id_t face_id0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; \ - hicn_face_id_t face_id1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX]; \ - face0 = \ - hicn_dpoi_get_from_idx (face_id0); \ - face1 = \ - hicn_dpoi_get_from_idx (face_id1); \ - \ - if (PREDICT_TRUE(face0 != NULL)) \ - { \ - hicn_face_rewrite_interest \ - (vm, b0, face0, &next0); \ - stats.pkts_interest_count += 1; \ - vlib_increment_combined_counter ( \ - &counters[face_id0 * HICN_N_COUNTER], \ - thread_index, \ - HICN_FACE_COUNTERS_INTEREST_TX, \ - 1, \ - vlib_buffer_length_in_chain(vm, b0)); \ - } \ - \ - if (PREDICT_TRUE(face1 != NULL)) \ - { \ - hicn_face_rewrite_interest \ - (vm, b1, face1, &next1); \ - stats.pkts_interest_count += 1; \ - vlib_increment_combined_counter ( \ - &counters[face_id1 * HICN_N_COUNTER], \ - thread_index, \ - HICN_FACE_COUNTERS_INTEREST_TX, \ - 1, \ - vlib_buffer_length_in_chain(vm, b1)); \ - } \ - \ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ - (b0->flags & VLIB_BUFFER_IS_TRACED))) \ - { \ - TRACE_OUTPUT_PKT_IP##ipv *t = \ - vlib_add_trace (vm, node, b0, sizeof (*t)); \ - t->pkt_type = HICN_PKT_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), \ - sizeof (t->packet_data)); \ - } \ - \ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ - (b1->flags & VLIB_BUFFER_IS_TRACED))) \ - { \ - TRACE_OUTPUT_PKT_IP##ipv *t = \ - vlib_add_trace (vm, node, b1, sizeof (*t)); \ - t->pkt_type = HICN_PKT_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), \ - sizeof (t->packet_data)); \ - } \ - \ - \ - /* Verify speculative enqueue, 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(0) - - -static uword -hicn4_face_output_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next, 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; - 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); - - /* Dual loop, X2 */ - while (n_left_from >= 4 && n_left_to_next >= 2) - { - face_output_x2 (4); - } - - /* Dual loop, X1 */ - while (n_left_from > 0 && n_left_to_next > 0) - { - face_output_x1 (4); - } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, node->node_index, - HICNFWD_ERROR_INTERESTS, - stats.pkts_interest_count); - - return (frame->n_vectors); -} - -/* packet trace format function */ -static u8 * -hicn4_face_output_format_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 *); - hicn4_face_output_trace_t *t = - va_arg (*args, hicn4_face_output_trace_t *); - - s = - format (s, "FACE_IP4_OUTPUT: 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)); - return (s); -} - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(hicn4_face_output_node) = -{ - .function = hicn4_face_output_node_fn, - .name = "hicn4-face-output", - .vector_size = sizeof(u32), - .format_trace = hicn4_face_output_format_trace, - .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_ECHO_REPLY] = "hicn4-face-input", - [HICN4_FACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap", - [HICN4_FACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" - } -}; -/* *INDENT-ON* */ - - -static uword -hicn6_face_output_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next, 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; - 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); - - /* Dual loop, X2 */ - while (n_left_from >= 4 && n_left_to_next >= 2) - { - face_output_x2 (6); - } - - /* Dual loop, X1 */ - while (n_left_from > 0 && n_left_to_next > 0) - { - face_output_x1 (6); - } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, node->node_index, - HICNFWD_ERROR_INTERESTS, - stats.pkts_interest_count); - - return (frame->n_vectors); -} - -/* packet trace format function */ -static u8 * -hicn6_face_output_format_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 *); - hicn6_face_output_trace_t *t = - va_arg (*args, hicn6_face_output_trace_t *); - - s = - format (s, "FACE_IP6_OUTPUT: pkt: %d, sw_if_index %d, next index %d\n%U", - (int) t->pkt_type, t->sw_if_index, t->next_index, - format_ip6_header, t->packet_data, sizeof (t->packet_data)); - return (s); -} - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(hicn6_face_output_node) = -{ - .function = hicn6_face_output_node_fn, - .name = "hicn6-face-output", - .vector_size = sizeof(u32), - .format_trace = hicn6_face_output_format_trace, - .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_ECHO_REPLY] = "hicn6-face-input", - [HICN6_FACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap", - [HICN6_FACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" - } -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/faces/face_node.h b/hicn-plugin/src/faces/face_node.h deleted file mode 100644 index f5a8bf5ae..000000000 --- a/hicn-plugin/src/faces/face_node.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2020 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_NODE_H__ -#define __HICN_FACE_NODE_H__ - -#include -#include - -/** - * @file face_node.h - * - * Implements the input and output face nodes. Input face nodes - * process incoming data while output face nodes process outgoing - * interests packets. - * - * Input face nodes follow hicn-face-input nodes and their purpose - * is to retrieve the list of possible incoming faces for each the data packet. - * The following node to the input face nodes is the hicn-data-pcslookup. - * Output face nodes follow the strategy and the hicn-interest-hitpit nodes and - * they perform the src nat on each interest packet. The node following the - * output face nodes depends on the adjacency type. In case of ip, the following - * node is the ip-rewrite, in case of tunnels the next node is the one implementing - * the tunnel encapsulation (udp-encap, mpls, etc). - */ - -extern vlib_node_registration_t hicn4_face_input_node; -extern vlib_node_registration_t hicn4_face_output_node; -extern vlib_node_registration_t hicn6_face_input_node; -extern vlib_node_registration_t hicn6_face_output_node; - -#endif // __HICN_FACE_NODE_H__ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/faces/iface_node.c b/hicn-plugin/src/faces/iface_node.c deleted file mode 100644 index 433cf0b02..000000000 --- a/hicn-plugin/src/faces/iface_node.c +++ /dev/null @@ -1,915 +0,0 @@ -/* - * Copyright (c) 2020 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 "face.h" -#include "../strategy_dpo_manager.h" -#include "../hicn.h" -#include "../infra.h" -#include "../cache_policies/cs_lru.h" - -/** - * @File - * - * Definition of the nodes for ip incomplete faces. - */ - -vlib_node_registration_t hicn4_iface_input_node; -vlib_node_registration_t hicn4_iface_output_node; -vlib_node_registration_t hicn6_iface_input_node; -vlib_node_registration_t hicn6_iface_output_node; - -u32 data_fwd_iface_ip4_vlib_edge; -u32 data_fwd_iface_ip6_vlib_edge; - -static char *hicn4_iface_input_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -static char *hicn6_iface_input_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - u8 packet_data[60]; -} hicn4_iface_input_trace_t; - -typedef enum -{ - HICN4_IFACE_INPUT_NEXT_INTEREST, - HICN4_IFACE_INPUT_NEXT_MAPME, - HICN4_IFACE_INPUT_NEXT_ERROR_DROP, - HICN4_IFACE_INPUT_N_NEXT, -} hicn4_iface_input_next_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - u8 packet_data[60]; -} hicn6_iface_input_trace_t; - -typedef enum -{ - HICN6_IFACE_INPUT_NEXT_INTEREST, - HICN6_IFACE_INPUT_NEXT_MAPME, - HICN6_IFACE_INPUT_NEXT_ERROR_DROP, - HICN6_IFACE_INPUT_N_NEXT, -} hicn6_iface_input_next_t; - -#define NEXT_MAPME_IP4 HICN4_IFACE_INPUT_NEXT_MAPME -#define NEXT_MAPME_IP6 HICN6_IFACE_INPUT_NEXT_MAPME - -#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_IFACE_IP4 hicn_iface_ip4_add_and_lock -#define DPO_ADD_LOCK_IFACE_IP6 hicn_iface_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 - -#define TRACE_INPUT_PKT_IP4 hicn4_iface_input_trace_t -#define TRACE_INPUT_PKT_IP6 hicn6_iface_input_trace_t - -// NODE OUTPUT - -static char *hicn4_iface_output_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -static char *hicn6_iface_output_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - u8 packet_data[60]; -} hicn4_iface_output_trace_t; - -typedef enum -{ - HICN4_IFACE_OUTPUT_NEXT_LOOKUP, - HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP, - HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP, - HICN4_IFACE_OUTPUT_N_NEXT, -} hicn4_iface_output_next_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - u8 packet_data[60]; -} hicn6_iface_output_trace_t; - -typedef enum -{ - HICN6_IFACE_OUTPUT_NEXT_LOOKUP, - HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP, - HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP, - HICN6_IFACE_OUTPUT_N_NEXT, -} hicn6_iface_output_next_t; - -//#define ERROR_OUTPUT_IP4 HICN4_IFACE_OUTPUT_NEXT_ERROR_DROP -//#define ERROR_OUTPUT_IP6 HICN6_IFACE_OUTPUT_NEXT_ERROR_DROP - -#define NEXT_DATA_LOOKUP_IP4 HICN4_IFACE_OUTPUT_NEXT_LOOKUP -#define NEXT_DATA_LOOKUP_IP6 HICN6_IFACE_OUTPUT_NEXT_LOOKUP - -#define NEXT_UDP_ENCAP_IP4 HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP -#define NEXT_UDP_ENCAP_IP6 HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP - -#define HICN_REWRITE_DATA_IP4 hicn_rewrite_iface_data4 -#define HICN_REWRITE_DATA_IP6 hicn_rewrite_iface_data6 - -#define TRACE_OUTPUT_PKT_IP4 hicn4_iface_output_trace_t -#define TRACE_OUTPUT_PKT_IP6 hicn6_iface_output_trace_t - -// NODES IMPLEMENTATIONS - -#define iface_input_x1(ipv) \ - do { \ - vlib_buffer_t *b0; \ - u32 bi0, next0, next_iface0; \ - IP_HEADER_##ipv * ip_hdr = NULL; \ - hicn_buffer_t * hicnb0; \ - /* Prefetch for next iteration. */ \ - if (n_left_from > 1) \ - { \ - vlib_buffer_t *b1; \ - b1 = vlib_get_buffer (vm, from[1]); \ - CLIB_PREFETCH (b1, 2*CLIB_CACHE_LINE_BYTES, STORE); \ - CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES , LOAD); \ - } \ - /* Dequeue a packet buffer */ \ - bi0 = from[0]; \ - from += 1; \ - n_left_from -= 1; \ - to_next[0] = bi0; \ - to_next += 1; \ - n_left_to_next -= 1; \ - \ - b0 = vlib_get_buffer (vm, bi0); \ - 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; \ - \ - if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL) \ - next_iface0 = NEXT_UDP_ENCAP_IP4; \ - else if(hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) \ - next_iface0 = NEXT_UDP_ENCAP_IP6; \ - \ - DPO_ADD_LOCK_IFACE_IP##ipv \ - (&(hicnb0->face_id), \ - &hicnb0->flags, \ - &(ip_hdr->src_address), \ - vnet_buffer(b0)->sw_if_index[VLIB_RX], \ - 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->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), \ - sizeof (t->packet_data)); \ - \ - } \ - \ - vlib_increment_combined_counter ( \ - &counters[hicnb0->face_id \ - * HICN_N_COUNTER], thread_index, \ - HICN_FACE_COUNTERS_INTEREST_RX, \ - 1, \ - vlib_buffer_length_in_chain(vm, b0)); \ - \ - /* 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); \ - }while(0) - - -#define iface_input_x2(ipv) \ - do { \ - vlib_buffer_t *b0, *b1; \ - u32 bi0, bi1, next0, next1, next_iface0, next_iface1; \ - IP_HEADER_##ipv * ip_hdr0 = NULL; \ - IP_HEADER_##ipv * ip_hdr1 = NULL; \ - hicn_buffer_t *hicnb0, *hicnb1; \ - \ - /* Prefetch for next iteration. */ \ - vlib_buffer_t *b2, *b3; \ - b2 = vlib_get_buffer (vm, from[2]); \ - b3 = vlib_get_buffer (vm, from[3]); \ - CLIB_PREFETCH (b2, 2*CLIB_CACHE_LINE_BYTES, STORE); \ - CLIB_PREFETCH (b3, 2*CLIB_CACHE_LINE_BYTES, STORE); \ - CLIB_PREFETCH (b2->data, CLIB_CACHE_LINE_BYTES , LOAD); \ - CLIB_PREFETCH (b3->data, CLIB_CACHE_LINE_BYTES , LOAD); \ - \ - /* Dequeue a packet buffer */ \ - bi0 = from[0]; \ - bi1 = from[1]; \ - from += 2; \ - n_left_from -= 2; \ - to_next[0] = bi0; \ - to_next[1] = bi1; \ - to_next += 2; \ - n_left_to_next -= 2; \ - \ - b0 = vlib_get_buffer (vm, bi0); \ - b1 = vlib_get_buffer (vm, bi1); \ - hicnb0 = hicn_get_buffer(b0); \ - hicnb1 = hicn_get_buffer(b1); \ - ip_hdr0 = (IP_HEADER_##ipv *) vlib_buffer_get_current(b0); \ - ip_hdr1 = (IP_HEADER_##ipv *) vlib_buffer_get_current(b1); \ - \ - 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; \ - \ - if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL) \ - next_iface0 = NEXT_UDP_ENCAP_IP4; \ - else if(hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) \ - next_iface0 = NEXT_UDP_ENCAP_IP6; \ - \ - next_iface1 = NEXT_DATA_LOOKUP_IP##ipv; \ - \ - if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL) \ - next_iface1 = NEXT_UDP_ENCAP_IP4; \ - else if(hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) \ - next_iface1 = NEXT_UDP_ENCAP_IP6; \ - \ - DPO_ADD_LOCK_IFACE_IP##ipv \ - (&(hicnb0->face_id), \ - &hicnb0->flags, \ - &(ip_hdr0->src_address), \ - vnet_buffer(b0)->sw_if_index[VLIB_RX], \ - vnet_buffer(b0)->ip.adj_index[VLIB_RX], \ - next_iface0); \ - \ - DPO_ADD_LOCK_IFACE_IP##ipv \ - (&(hicnb1->face_id), \ - &hicnb1->flags, \ - &(ip_hdr1->src_address), \ - vnet_buffer(b1)->sw_if_index[VLIB_RX], \ - 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->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), \ - sizeof (t->packet_data)); \ - } \ - \ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ - (b1->flags & VLIB_BUFFER_IS_TRACED))) \ - { \ - TRACE_INPUT_PKT_IP##ipv *t = \ - vlib_add_trace (vm, node, b1, sizeof (*t)); \ - t->pkt_type = HICN_PKT_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), \ - sizeof (t->packet_data)); \ - } \ - \ - vlib_increment_combined_counter ( \ - &counters[hicnb0->face_id \ - * HICN_N_COUNTER], thread_index, \ - HICN_FACE_COUNTERS_INTEREST_RX, \ - 1, \ - vlib_buffer_length_in_chain(vm, b0)); \ - \ - vlib_increment_combined_counter ( \ - &counters[hicnb1->face_id \ - * HICN_N_COUNTER], thread_index, \ - HICN_FACE_COUNTERS_INTEREST_RX, \ - 1, \ - vlib_buffer_length_in_chain(vm, b1)); \ - \ - /* Verify speculative enqueue, 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(0) - -static uword -hicn4_iface_input_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next, next_index; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; - u32 thread_index = vm->thread_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); - - /* Dual loop, X2 */ - while (n_left_from >= 4 && n_left_to_next >= 2) - { - iface_input_x2 (4); - } - - /* Dual loop, X1 */ - while (n_left_from > 0 && n_left_to_next > 0) - { - iface_input_x1 (4); - } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, node->node_index, - HICNFWD_ERROR_INTERESTS, - stats.pkts_interest_count); - - return (frame->n_vectors); -} - -/* packet trace format function */ -static u8 * -hicn4_iface_input_format_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 *); - 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)); - return (s); -} - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (hicn4_iface_input_node) = -{ - .function = hicn4_iface_input_node_fn, - .name = "hicn4-iface-input", - .vector_size = sizeof (u32), - .format_trace = hicn4_iface_input_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN (hicn4_iface_input_error_strings), - .error_strings = hicn4_iface_input_error_strings, - .n_next_nodes = HICN4_IFACE_INPUT_N_NEXT, - /* edit / add dispositions*/ - .next_nodes = - { - [HICN4_IFACE_INPUT_NEXT_INTEREST] = "hicn-interest-pcslookup", - [HICN4_IFACE_INPUT_NEXT_MAPME] = "hicn-mapme-ctrl", - [HICN4_IFACE_INPUT_NEXT_ERROR_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -static uword -hicn6_iface_input_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next, next_index; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; - u32 thread_index = vm->thread_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); - - /* Dual loop, X2 */ - while (n_left_from >= 4 && n_left_to_next >= 2) - { - iface_input_x2 (6); - } - - /* Dual loop, X1 */ - while (n_left_from > 0 && n_left_to_next > 0) - { - iface_input_x1 (6); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, node->node_index, - HICNFWD_ERROR_INTERESTS, - stats.pkts_interest_count); - - return (frame->n_vectors); -} - -/* packet trace format function */ -static u8 * -hicn6_iface_input_format_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 *); - hicn6_iface_input_trace_t *t = - va_arg (*args, hicn6_iface_input_trace_t *); - - s = - format (s, "IFACE_IP6_INPUT: pkt: %d, sw_if_index %d, next index %d\n%U", - (int) t->pkt_type, t->sw_if_index, t->next_index, - format_ip6_header, t->packet_data, sizeof (t->packet_data)); - return (s); -} - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (hicn6_iface_input_node) = -{ - .function = hicn6_iface_input_node_fn, - .name = "hicn6-iface-input", - .vector_size = sizeof (u32), - .format_trace = hicn6_iface_input_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN (hicn6_iface_input_error_strings), - .error_strings = hicn6_iface_input_error_strings, - .n_next_nodes = HICN6_IFACE_INPUT_N_NEXT, - /* edit / add dispositions*/ - .next_nodes = - { - [HICN6_IFACE_INPUT_NEXT_INTEREST] = "hicn-interest-pcslookup", - [HICN6_IFACE_INPUT_NEXT_MAPME] = "hicn-mapme-ctrl", - [HICN6_IFACE_INPUT_NEXT_ERROR_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - - -/**** IFACE OUTPUT *****/ - -static inline void -hicn_rewrite_iface_data4 (vlib_main_t * vm, vlib_buffer_t * b0, - const hicn_face_t * iface, u32 * next) -{ - ip4_header_t *ip0; - - /* Get the pointer to the old ip and tcp header */ - ip0 = vlib_buffer_get_current (b0); - - /* Set up the ip6 header */ - /* IP4 lenght contains the size of the ip4 header too */ - u16 sval = (vlib_buffer_length_in_chain (vm, b0)); - ip0->length = clib_host_to_net_u16 (sval); - ip0->ttl = 254; // FIXME TTL - - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = iface->dpo.dpoi_index; - *next = iface->dpo.dpoi_next_node; - hicn_header_t *hicn = vlib_buffer_get_current (b0); - - ip46_address_t temp_addr; - ip46_address_reset (&temp_addr); - hicn_type_t type = hicn_get_buffer (b0)->type; - hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol, - &(iface->nat_addr), &(temp_addr), - iface->pl_id); -} - -static inline void -hicn_rewrite_iface_data6 (vlib_main_t * vm, vlib_buffer_t * b0, - const hicn_face_t * iface, u32 * next) -{ - ip6_header_t *ip0; - - /* Get the pointer to the old ip and tcp header */ - /* Copy the previous ip and tcp header to the new portion of memory */ - ip0 = vlib_buffer_get_current (b0); - - /* Set up the ip6 header */ - /* IP6 lenght does not include the size of the ip6 header */ - u16 sval = (vlib_buffer_length_in_chain (vm, b0) - (sizeof (ip6_header_t))); - ip0->payload_length = clib_host_to_net_u16 (sval); - ip0->hop_limit = HICN_IP6_HOP_LIMIT; - - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = iface->dpo.dpoi_index; - *next = iface->dpo.dpoi_next_node; - - hicn_header_t *hicn = vlib_buffer_get_current (b0); - - ip46_address_t temp_addr; - ip46_address_reset (&temp_addr); - hicn_type_t type = hicn_get_buffer (b0)->type; - hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol, - &(iface->nat_addr), &(temp_addr), - iface->pl_id); -} - -#define iface_output_x1(ipv) \ - do { \ - vlib_buffer_t *b0; \ - u32 bi0; \ - u32 next0 = next_index; \ - hicn_face_t * face; \ - \ - /* 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, STORE); \ - CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES , STORE); \ - } \ - /* Dequeue a packet buffer */ \ - bi0 = from[0]; \ - from += 1; \ - n_left_from -= 1; \ - to_next[0] = bi0; \ - to_next += 1; \ - n_left_to_next -= 1; \ - \ - b0 = vlib_get_buffer (vm, bi0); \ - \ - hicn_face_id_t face_id = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; \ - face = \ - hicn_dpoi_get_from_idx (face_id); \ - \ - if (PREDICT_TRUE(face != NULL)) \ - { \ - HICN_REWRITE_DATA_IP##ipv \ - (vm, b0, face, &next0); \ - stats.pkts_data_count += 1; \ - vlib_increment_combined_counter ( \ - &counters[face_id * HICN_N_COUNTER], \ - thread_index, \ - HICN_FACE_COUNTERS_DATA_TX, \ - 1, \ - vlib_buffer_length_in_chain(vm, b0));\ - } \ - \ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ - (b0->flags & VLIB_BUFFER_IS_TRACED))) \ - { \ - TRACE_OUTPUT_PKT_IP##ipv *t = \ - vlib_add_trace (vm, node, b0, sizeof (*t)); \ - t->pkt_type = HICN_PKT_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), \ - sizeof (t->packet_data)); \ - } \ - \ - \ - /* 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); \ - }while(0); \ - - -#define iface_output_x2(ipv) \ - do { \ - vlib_buffer_t *b0, *b1; \ - u32 bi0, bi1; \ - u32 next0 = next_index; \ - u32 next1 = next_index; \ - hicn_face_t *face0, *face1; \ - \ - /* Prefetch for next iteration. */ \ - { \ - vlib_buffer_t *b2, *b3; \ - b2 = vlib_get_buffer (vm, from[2]); \ - b3 = vlib_get_buffer (vm, from[3]); \ - CLIB_PREFETCH (b2, CLIB_CACHE_LINE_BYTES, STORE); \ - CLIB_PREFETCH (b3, CLIB_CACHE_LINE_BYTES, STORE); \ - CLIB_PREFETCH (b2->data, CLIB_CACHE_LINE_BYTES , STORE); \ - CLIB_PREFETCH (b3->data, CLIB_CACHE_LINE_BYTES , STORE); \ - } \ - \ - /* Dequeue a packet buffer */ \ - bi0 = from[0]; \ - bi1 = from[1]; \ - from += 2; \ - n_left_from -= 2; \ - to_next[0] = bi0; \ - to_next[1] = bi1; \ - to_next += 2; \ - n_left_to_next -= 2; \ - \ - b0 = vlib_get_buffer (vm, bi0); \ - b1 = vlib_get_buffer (vm, bi1); \ - \ - hicn_face_id_t face_id0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; \ - hicn_face_id_t face_id1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX]; \ - face0 = \ - hicn_dpoi_get_from_idx (face_id0); \ - face1 = \ - hicn_dpoi_get_from_idx (face_id1); \ - \ - if (PREDICT_TRUE(face0 != NULL)) \ - { \ - HICN_REWRITE_DATA_IP##ipv \ - (vm, b0, face0, &next0); \ - stats.pkts_data_count += 1; \ - vlib_increment_combined_counter ( \ - &counters[face_id0 * HICN_N_COUNTER], \ - thread_index, \ - HICN_FACE_COUNTERS_DATA_TX, \ - 1, \ - vlib_buffer_length_in_chain(vm, b0));\ - } \ - \ - if (PREDICT_TRUE(face1 != NULL)) \ - { \ - HICN_REWRITE_DATA_IP##ipv \ - (vm, b1, face1, &next1); \ - stats.pkts_data_count += 1; \ - vlib_increment_combined_counter ( \ - &counters[face_id1 * HICN_N_COUNTER], \ - thread_index, \ - HICN_FACE_COUNTERS_DATA_TX, \ - 1, \ - vlib_buffer_length_in_chain(vm, b1)); \ - } \ - \ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ - (b0->flags & VLIB_BUFFER_IS_TRACED))) \ - { \ - TRACE_OUTPUT_PKT_IP##ipv *t = \ - vlib_add_trace (vm, node, b0, sizeof (*t)); \ - t->pkt_type = HICN_PKT_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), \ - sizeof (t->packet_data)); \ - } \ - \ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ - (b1->flags & VLIB_BUFFER_IS_TRACED))) \ - { \ - TRACE_OUTPUT_PKT_IP##ipv *t = \ - vlib_add_trace (vm, node, b1, sizeof (*t)); \ - t->pkt_type = HICN_PKT_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), \ - sizeof (t->packet_data)); \ - } \ - \ - \ - /* Verify speculative enqueue, 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(0); \ - - - -static uword -hicn4_iface_output_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next, 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; - 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) - { - iface_output_x2 (4); - } - - while (n_left_from > 0 && n_left_to_next > 0) - { - iface_output_x1 (4); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, node->node_index, - HICNFWD_ERROR_DATAS, stats.pkts_data_count); - - return (frame->n_vectors); -} - -/* packet trace format function */ -static u8 * -hicn4_iface_output_format_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 *); - hicn4_iface_output_trace_t *t = - va_arg (*args, hicn4_iface_output_trace_t *); - - s = - format (s, "IFACE_IP4_OUTPUT: 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)); - return (s); -} - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (hicn4_iface_output_node) = -{ - .function = hicn4_iface_output_node_fn, - .name = "hicn4-iface-output", - .vector_size = sizeof (u32), - .format_trace = hicn4_iface_output_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN (hicn4_iface_output_error_strings), - .error_strings = hicn4_iface_output_error_strings, - .n_next_nodes = HICN4_IFACE_OUTPUT_N_NEXT, - /* edit / add dispositions here */ - .next_nodes = - { - [HICN4_IFACE_OUTPUT_NEXT_LOOKUP] = "ip4-lookup", - [HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap", - [HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" - }, -}; -/* *INDENT-ON* */ - - -static uword -hicn6_iface_output_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next, 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; - 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) - { - iface_output_x2 (6); - } - - while (n_left_from > 0 && n_left_to_next > 0) - { - iface_output_x1 (6); - } - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, node->node_index, - HICNFWD_ERROR_DATAS, stats.pkts_data_count); - - return (frame->n_vectors); -} - -/* packet trace format function */ -static u8 * -hicn6_iface_output_format_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 *); - hicn6_iface_output_trace_t *t = - va_arg (*args, hicn6_iface_output_trace_t *); - - s = - format (s, "IFACE_IP6_OUTPUT: pkt: %d, sw_if_index %d, next index %d\n%U", - (int) t->pkt_type, t->sw_if_index, t->next_index, - format_ip6_header, t->packet_data, sizeof (t->packet_data)); - return (s); -} - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (hicn6_iface_output_node) = -{ - .function = hicn6_iface_output_node_fn, - .name = "hicn6-iface-output", - .vector_size = sizeof (u32), - .format_trace = hicn6_iface_output_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN (hicn6_iface_output_error_strings), - .error_strings = hicn6_iface_output_error_strings, - .n_next_nodes = HICN6_IFACE_OUTPUT_N_NEXT, - /* edit / add dispositions here */ - .next_nodes = - { - [HICN6_IFACE_OUTPUT_NEXT_LOOKUP] = "ip6-lookup", - [HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap", - [HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" - - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/faces/iface_node.h b/hicn-plugin/src/faces/iface_node.h deleted file mode 100644 index 1a7c4291b..000000000 --- a/hicn-plugin/src/faces/iface_node.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2020 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_IFACE_NODE_H__ -#define __HICN_IFACE_NODE_H__ - -#include -#include - -/** - * @file iface_node.h - * - * Implements the input and output iface nodes. Input iface nodes - * process incoming interests while output face nodes process outgoing - * data packets. - * - * Input iface nodes follow ip-lookup nodes and their purpose - * is to create (or retrieve if already existing) the list incoming face - * for each the interest packet. - * The following node to the input iface nodes is the hicn-interest-pcslookup. - * Output iface nodes follow the hicn-data-fwd and the hicn-interest-hitcs nodes and - * they perform the dst nat on each data packet. The node following the - * output face nodes depends on the adjacency type. In case of ip, the following - * node is the ip4/6-lookup, in case of tunnels the next node is the one implementing - * the tunnel encapsulation (udp-encap, mpls, etc). - */ - - -/** - * @brief Initialize the ip iface module - */ -void hicn_iface_init (vlib_main_t * vm); - -#endif // __HICN_IFACE_IP_NODE_H__ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/hashtb.c b/hicn-plugin/src/hashtb.c deleted file mode 100644 index 6deddbd84..000000000 --- a/hicn-plugin/src/hashtb.c +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * Copyright (c) 2017-2019 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 - -#include "pcs.h" -#include "hashtb.h" -#include "parser.h" -#include "error.h" - -/* return dvd/dvr, rounded up (intended for integer values) */ -#define CEIL(dvd, dvr) \ - ({ \ - __typeof__ (dvd) _dvd = (dvd); \ - __typeof__ (dvr) _dvr = (dvr); \ - (_dvd + _dvr - 1)/_dvr; \ - }) - -#ifndef ALIGN8 -#define ALIGN8(p) (((p) + 0x7) & ~(0x7)) -#endif - -#ifndef ALIGNPTR8 -#define ALIGNPTR8(p) ((void *)(((u8 * )(p) + 0x7) & ~(0x7))) -#endif - -#ifndef ALIGN64 -#define ALIGN64(p) (((p) + 0x3f) & ~(0x3f)) -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - - -/* - * Offset to aligned start of additional data (PIT/CS, FIB) embedded in each - * node. - */ -u32 ht_node_data_offset_aligned; - -/* Some support for posix vs vpp mem management */ -#define MEM_ALLOC(x) clib_mem_alloc_aligned((x), 8) -#define MEM_FREE(p) clib_mem_free((p)) - -/* - * Internal utilities - */ - -/* Allocate an overflow bucket */ -static hicn_hash_bucket_t * -alloc_overflow_bucket (hicn_hashtb_h h) -{ - hicn_hash_bucket_t *newbkt = NULL; - - if (h->ht_overflow_buckets_used < h->ht_overflow_bucket_count) - { - pool_get_aligned (h->ht_overflow_buckets, newbkt, 8); - - if (newbkt) - { - h->ht_overflow_buckets_used++; - } - } - return (newbkt); -} - -/* Free an overflow bucket; clear caller's pointer */ -static void -free_overflow_bucket (hicn_hashtb_h h, hicn_hash_bucket_t ** pb) -{ - hicn_hash_bucket_t *bkt = *pb; - - ASSERT (h->ht_overflow_buckets_used > 0); - - pool_put (h->ht_overflow_buckets, bkt); - h->ht_overflow_buckets_used--; - *pb = NULL; -} - -/* - * Init, allocate a new hashtable - */ -int -hicn_hashtb_alloc (hicn_hashtb_h * ph, u32 max_elems, size_t app_data_size) -{ - int ret = HICN_ERROR_NONE; - hicn_hashtb_h h = NULL; - u32 count; - u32 total_buckets; - size_t sz; - hicn_hash_node_t *nodep; - hicn_hash_bucket_t *bucket; - - if (ph == NULL) - { - ret = HICN_ERROR_HASHTB_INVAL; - goto done; - } - if (max_elems < HICN_HASHTB_MIN_ENTRIES || - max_elems > HICN_HASHTB_MAX_ENTRIES) - { - goto done; - } - /* Allocate and init main hashtable struct */ - h = MEM_ALLOC (sizeof (hicn_hashtb_t)); - if (h == NULL) - { - ret = HICN_ERROR_HASHTB_NOMEM; - goto done; - } - memset (h, 0, sizeof (hicn_hashtb_t)); - - /* Compute main table bucket (row) count and size, and allocate */ - - /* Consider the last entry as used for containing the overflow bucket */ - total_buckets = CEIL (max_elems, HICN_HASHTB_BUCKET_ENTRIES - 1); - count = ALIGN8 (CEIL (total_buckets, HICN_HASHTB_FILL_FACTOR)); - - h->ht_bucket_count = count; - - /* We _really_ expect to have buckets aligned on cache lines ... */ - sz = sizeof (hicn_hash_bucket_t); - assert (sz == ALIGN64 (sz)); - - h->ht_buckets = MEM_ALLOC (count * sz); - if (h->ht_buckets == NULL) - { - ret = HICN_ERROR_HASHTB_NOMEM; - goto done; - } - memset (h->ht_buckets, 0, count * sz); - - /* - * First time through, compute offset to aligned extra data start in - * each node struct it's crucial that both the node struct (that the - * base hashtable uses) and the extra data area (that's also probably - * a struct) are aligned. - */ - if (ht_node_data_offset_aligned == 0) - { - count = STRUCT_OFFSET_OF (hicn_hash_node_t, hn_data); - ht_node_data_offset_aligned = ALIGN8 (count); - } - //check app struct fits into space provided(HICN_HASH_NODE_APP_DATA_SIZE) - u32 ht_node_data_size; - ht_node_data_size = sizeof (hicn_hash_node_t) - ht_node_data_offset_aligned; - if (app_data_size > ht_node_data_size) - { - clib_error - ("hicn hashtable: fatal error: requested app data size(%u) > hashtb node's configured bytes available(%u), sizeof(hicn_shared_t)=%u, sizeof(hicn_pit_entry_t)=%u, sizeof(hicn_cs_entry_t)=%u", - app_data_size, ht_node_data_size, sizeof (hicn_pcs_shared_t), - sizeof (hicn_pit_entry_t), sizeof (hicn_cs_entry_t)); - } - /* - * Compute entry node count and size, allocate Allocate/'Hide' the - * zero-th node so can use zero as an 'empty' value - */ - pool_alloc_aligned (h->ht_nodes, max_elems, 8); - if (h->ht_nodes == NULL) - { - ret = HICN_ERROR_HASHTB_NOMEM; - goto done; - } - pool_get_aligned (h->ht_nodes, nodep, 8); - //alloc node 0 - nodep = nodep; /* Silence 'not used' warning */ - - h->ht_node_count = max_elems; - h->ht_nodes_used = 1; - - /* - * Compute overflow bucket count and size, allocate - */ - //count = ALIGN8(CEIL(max_elems, HICN_HASHTB_OVERFLOW_FRACTION)); - count = ALIGN8 (total_buckets - h->ht_bucket_count); - - pool_alloc_aligned (h->ht_overflow_buckets, count, 8); - if (h->ht_overflow_buckets == NULL) - { - ret = HICN_ERROR_HASHTB_NOMEM; - goto done; - } - /* 'Hide' the zero-th node so we can use zero as an 'empty' value */ - pool_get_aligned (h->ht_overflow_buckets, bucket, 8); - bucket = bucket; /* Silence 'not used' warning */ - - h->ht_overflow_bucket_count = count; - h->ht_overflow_buckets_used = 1; - -done: - - if (h) - { - if ((ret == HICN_ERROR_NONE) && ph) - { - *ph = h; - } - else - { - hicn_hashtb_free (&h); - } - } - return (ret); -} - -/* - * Free, de-allocate a hashtable - */ -int -hicn_hashtb_free (hicn_hashtb_h * ph) -{ - int ret = 0; - - if (ph) - { - if ((*ph)->ht_nodes) - { - pool_free ((*ph)->ht_nodes); - (*ph)->ht_nodes = 0; - } - if ((*ph)->ht_overflow_buckets) - { - pool_free ((*ph)->ht_overflow_buckets); - (*ph)->ht_overflow_buckets = 0; - } - if ((*ph)->ht_buckets) - { - MEM_FREE ((*ph)->ht_buckets); - (*ph)->ht_buckets = 0; - } - MEM_FREE (*ph); - - *ph = NULL; - } - return (ret); -} - - - -/* - * Basic api to lookup a specific hash+key tuple. This does the entire lookup - * operation, retrieving node structs and comparing keys, so it's not - * optimized for prefetching or high performance. - * - * Returns zero and mails back a node on success, errno otherwise. - */ -int -hicn_hashtb_lookup_node (hicn_hashtb_h h, const u8 * key, - u32 keylen, u64 hashval, u8 is_data, - u32 * node_id, index_t * dpo_ctx_id, u8 * vft_id, - u8 * is_cs, u8 * hash_entry_id, u32 * bucket_id, - u8 * bucket_is_overflow) -{ - return (hicn_hashtb_lookup_node_ex - (h, key, keylen, hashval, is_data, FALSE /* deleted nodes */ , - node_id, - dpo_ctx_id, vft_id, is_cs, hash_entry_id, bucket_id, - bucket_is_overflow)); -} - -/* - * Extended api to lookup a specific hash+key tuple. The implementation - * allows the caller to locate nodes that are marked for deletion, which is - * part of some hashtable applications, such as the FIB. - * - * This does the entire lookup operation, retrieving node structs and comparing - * keys, so it's not optimized for prefetching or high performance. - * - * Returns zero and mails back a node on success, errno otherwise. - */ -int -hicn_hashtb_lookup_node_ex (hicn_hashtb_h h, const u8 * key, - u32 keylen, u64 hashval, u8 is_data, - int include_deleted_p, u32 * node_id, - index_t * dpo_ctx_id, u8 * vft_id, u8 * is_cs, - u8 * hash_entry_id, u32 * bucket_id, - u8 * bucket_is_overflow) -{ - int i, ret = HICN_ERROR_HASHTB_HASH_NOT_FOUND; - int found_p = FALSE; - u32 bidx; - hicn_hash_bucket_t *bucket; - u32 current_bucket_id = ~0; - - /* - * Use some bits of the low half of the hash to locate a row/bucket - * in the table - */ - current_bucket_id = bidx = (hashval & (h->ht_bucket_count - 1)); - - bucket = h->ht_buckets + bidx; - - *bucket_is_overflow = 0; - /* Check the entries in the bucket for matching hash value */ - -loop_buckets: - - for (i = 0; i < HICN_HASHTB_BUCKET_ENTRIES && !found_p; i++) - { - /* - * If an entry is marked for deletion, ignore it unless the - * caller explicitly wants these nodes. - */ - if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_DELETED) - { - if (!include_deleted_p) - { - continue; - } - } - if (bucket->hb_entries[i].he_msb64 == hashval) - { - /* - * Found a candidate - must retrieve the actual node - * and check the key. - */ - *node_id = bucket->hb_entries[i].he_node; - *dpo_ctx_id = bucket->hb_entries[i].dpo_ctx_id; - *vft_id = bucket->hb_entries[i].vft_id; - *is_cs = - bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY; - *hash_entry_id = i; - *bucket_id = current_bucket_id; - /* - * If we are doing lookup for a data, do not take a - * lock in case of a hit with a CS entry - */ - if (!(is_data && *is_cs)) - { - bucket->hb_entries[i].locks++; - } - found_p = TRUE; - ret = HICN_ERROR_NONE; - goto done; - } - } - - /* - * Be prepared to continue to an overflow bucket if necessary. We - * only expect the last entry in a bucket to refer to an overflow - * bucket... - */ - i = HICN_HASHTB_BUCKET_ENTRIES - 1; - if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW) - { - current_bucket_id = bucket->hb_entries[i].he_node; - bucket = pool_elt_at_index (h->ht_overflow_buckets, - bucket->hb_entries[i].he_node); - *bucket_is_overflow = 1; - goto loop_buckets; - } -done: - - return (ret); -} - -/** - * This function allows to split the hash verification from the comparison of - * the entire key. Useful to exploit prefertching. - * return 1 if equals, 0 otherwise - */ -int -hicn_node_compare (const u8 * key, u32 keylen, hicn_hash_node_t * node) -{ - - int ret = 0; - - if (key && keylen == node->hn_keysize) - { - ret = (memcmp (key, node->hn_key.ks.key, keylen) == 0); - } - return ret; -} - -/* - * Utility to init a new entry in a hashtable bucket/row. We use this to add - * new a node+hash, and to clear out an entry during removal. - */ -void -hicn_hashtb_init_entry (hicn_hash_entry_t * entry, u32 nodeidx, - u64 hashval, u32 locks) -{ - entry->he_msb64 = hashval; - entry->he_node = nodeidx; - - /* Clear out some other fields in the entry */ - entry->he_flags = 0; - entry->locks = locks; - entry->vft_id = 0; - entry->dpo_ctx_id = 0; -} - -/* - * Insert a node into the hashtable. We expect the caller has a) computed the - * hash value to use, b) initialized the node with the hash and key info, and - * c) filled in its app-specific data portion of the node. - */ - -int -hicn_hashtb_insert (hicn_hashtb_h h, hicn_hash_node_t * node, - hicn_hash_entry_t ** hash_entry, u64 hash, - u32 * node_id, - index_t * dpo_ctx_id, u8 * vft_id, u8 * is_cs, - u8 * hash_entry_id, u32 * bucket_id, - u8 * bucket_is_overflow) -{ - int i, ret = HICN_ERROR_HASHTB_INVAL; - u32 bidx; - hicn_hash_bucket_t *bucket, *newbkt; - int use_seven; - u32 current_bucket_id = ~0; - int is_overflow = 0; - - *hash_entry = NULL; - - if (h == NULL) - { - goto done; - } - /* - * Use some bits of the low half of the hash to locate a row/bucket - * in the table - */ - current_bucket_id = bidx = (hash & (h->ht_bucket_count - 1)); - - bucket = h->ht_buckets + bidx; - - use_seven = (h->ht_flags & HICN_HASHTB_FLAG_USE_SEVEN); - - /* Locate a free entry slot in the bucket */ - -loop_buckets: - - for (i = 0; i < HICN_HASHTB_BUCKET_ENTRIES; i++) - { - - /* - * If an entry is marked for deletion, ignore it - */ - if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_DELETED) - { - continue; - } - /* - * Be sure that we are not inserting the same entry twice - */ - if (bucket->hb_entries[i].he_msb64 == hash) - { - /* - * We hit an existing pit entry. increase lock. - */ - - *node_id = bucket->hb_entries[i].he_node; - *dpo_ctx_id = bucket->hb_entries[i].dpo_ctx_id; - *vft_id = bucket->hb_entries[i].vft_id; - *is_cs = - bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY; - *hash_entry_id = i; - *bucket_id = current_bucket_id; - *hash_entry = &(bucket->hb_entries[i]); - /* - * If we are doing lookup for a data, do not take a - * lock in case of a hit with a CS entry - */ - if (!(*is_cs)) - bucket->hb_entries[i].locks++; - *bucket_is_overflow = is_overflow; - ret = HICN_ERROR_HASHTB_EXIST; - goto done; - } - if ((bucket->hb_entries[i].he_msb64 == 0LL) && - (bucket->hb_entries[i].he_node == 0)) - { - /* Found a candidate -- fill it in */ - - /* - * Special case if the application asked not to use - * the last entry in each bucket. - */ - if ((i != (HICN_HASHTB_BUCKET_ENTRIES - 1)) || use_seven) - { - hicn_hashtb_init_entry (&(bucket->hb_entries[i]), - NODE_IDX_FROM_NODE (node, h), hash, 0); - - *hash_entry = &(bucket->hb_entries[i]); - - node->bucket_id = current_bucket_id; - node->entry_idx = i; - (*hash_entry)->vft_id = *vft_id; - (*hash_entry)->dpo_ctx_id = *dpo_ctx_id; - if (is_overflow) - node->hn_flags |= HICN_HASH_NODE_OVERFLOW_BUCKET; - - ret = HICN_ERROR_NONE; - goto done; - } - } - } - /* - * Be prepared to continue to an overflow bucket if necessary, or to - * add a new overflow bucket. We only expect the last entry in a - * bucket to refer to an overflow bucket... - */ - i = HICN_HASHTB_BUCKET_ENTRIES - 1; - if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW) - { - /* Existing overflow bucket - re-start the search loop */ - current_bucket_id = bucket->hb_entries[i].he_node; - bucket = pool_elt_at_index (h->ht_overflow_buckets, current_bucket_id); - is_overflow = 1; - goto loop_buckets; - - } - else - { - /* - * Overflow - reached the end of a bucket without finding a - * free entry slot. Need to allocate an overflow bucket, and - * connect it to this bucket. - */ - newbkt = alloc_overflow_bucket (h); - if (newbkt == NULL) - { - ret = HICN_ERROR_HASHTB_NOMEM; - goto done; - } - /* - * We're touching some more bytes than we absolutely have to - * here, but ... that seems ok. - */ - memset (newbkt, 0, sizeof (hicn_hash_bucket_t)); - - if (use_seven) - { - /* - * Copy existing entry into new bucket - we really - * expect these to be properly aligned so they can be - * treated as int. - */ - memcpy (&(newbkt->hb_entries[0]), - &(bucket->hb_entries[i]), sizeof (hicn_hash_entry_t)); - - /* Update bucket id and entry_idx on the hash node */ - hicn_hash_node_t *node = - pool_elt_at_index (h->ht_nodes, newbkt->hb_entries[0].he_node); - node->bucket_id = (newbkt - h->ht_overflow_buckets); - node->entry_idx = 0; - node->hn_flags |= HICN_HASH_NODE_OVERFLOW_BUCKET; - - } - /* - * Connect original bucket to the index of the new overflow - * bucket - */ - bucket->hb_entries[i].he_flags |= HICN_HASH_ENTRY_FLAG_OVERFLOW; - bucket->hb_entries[i].he_node = (newbkt - h->ht_overflow_buckets); - - /* Add new entry to new overflow bucket */ - bucket = newbkt; - - /* - * Use entry [1] in the new bucket _if_ we just copied into - * entry [zero] above. - */ - if (use_seven) - { - - hicn_hashtb_init_entry (&(bucket->hb_entries[1]), - NODE_IDX_FROM_NODE (node, h), hash, 0); - *hash_entry = &(bucket->hb_entries[1]); - - node->bucket_id = (newbkt - h->ht_overflow_buckets); - node->entry_idx = 1; - node->hn_flags |= HICN_HASH_NODE_OVERFLOW_BUCKET; - (*hash_entry)->vft_id = *vft_id; - (*hash_entry)->dpo_ctx_id = *dpo_ctx_id; - } - else - { - - hicn_hashtb_init_entry (&(bucket->hb_entries[0]), - NODE_IDX_FROM_NODE (node, h), hash, 0); - *hash_entry = &(bucket->hb_entries[0]); - node->bucket_id = (newbkt - h->ht_overflow_buckets); - node->entry_idx = 0; - node->hn_flags |= HICN_HASH_NODE_OVERFLOW_BUCKET; - (*hash_entry)->vft_id = *vft_id; - (*hash_entry)->dpo_ctx_id = *dpo_ctx_id; - } - } - - /* And we're done with the overflow bucket */ - ret = HICN_ERROR_NONE; - -done: - - return (ret); -} - -/* - * Delete a node from a hashtable using the node itself, and delete/free the - * node. Caller's pointer is cleared on success. - */ -void -hicn_hashtb_delete (hicn_hashtb_h h, hicn_hash_node_t ** pnode, u64 hashval) -{ - - hicn_hashtb_remove_node (h, *pnode, hashval); - hicn_hashtb_free_node (h, *pnode); - *pnode = NULL; - -} - -/* - * Delete an entry from a hashtable using the node itself. If the node was - * stored in an overflow bucket, and the bucket is empty after freeing the - * node, the bucket is freed as well. - */ -void -hicn_hashtb_remove_node (hicn_hashtb_h h, hicn_hash_node_t * node, - u64 hashval) -{ - int i, count; - u32 bidx, overflow_p; - hicn_hash_bucket_t *bucket, *parent; - - if ((h == NULL) || (node == NULL)) - { - goto done; - } - if (node->hn_flags & HICN_HASH_NODE_OVERFLOW_BUCKET) - bucket = pool_elt_at_index (h->ht_overflow_buckets, node->bucket_id); - else - { - /* - * Use some bits of the low half of the hash to locate a - * row/bucket in the table - */ - bidx = (hashval & (h->ht_bucket_count - 1)); - ASSERT (bidx == node->bucket_id); - bucket = h->ht_buckets + node->bucket_id; - } - - overflow_p = node->hn_flags & HICN_HASH_NODE_OVERFLOW_BUCKET; - - /* Clear out the entry. */ - hicn_hashtb_init_entry (&(bucket->hb_entries[node->entry_idx]), 0, 0LL, 0); - - if (!overflow_p) - { - /* - * And we're done, in the easy case where we didn't change an - * overflow bucket - */ - goto done; - } - /* - * The special case: if this is the last remaining entry in an - * overflow bucket, liberate the bucket. That in turn has a special - * case if this bucket is in the middle of a chain of overflow - * buckets. - * - * Note that we're not trying aggressively (yet) to condense buckets at - * every possible opportunity. - */ - - /* - * Reset this flag; we'll set it again if this bucket links to - * another - */ - overflow_p = FALSE; - - for (i = 0, count = 0; i < HICN_HASHTB_BUCKET_ENTRIES; i++) - { - if (bucket->hb_entries[i].he_node != 0) - { - count++; - } - if (i == (HICN_HASHTB_BUCKET_ENTRIES - 1) && - (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW)) - { - count--; /* Doesn't count as a 'real' entry */ - overflow_p = TRUE; - } - } - - if (count > 0) - { - /* Still a (real) entry in the row */ - goto done; - } - /* - * Need to locate the predecessor of 'bucket': start at the beginning - * of the chain of buckets and move forward - */ - bidx = (hashval & (h->ht_bucket_count - 1)); - - for (parent = h->ht_buckets + bidx; parent != NULL;) - { - - if ((parent->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)].he_flags & - HICN_HASH_ENTRY_FLAG_OVERFLOW) == 0) - { - parent = NULL; - break; - } - bidx = parent->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)].he_node; - - if (pool_elt_at_index (h->ht_overflow_buckets, bidx) == bucket) - { - /* - * Found the predecessor of 'bucket'. If 'bucket' has - * a successor, connect 'parent' to it, and take - * 'bucket out of the middle. - */ - if (overflow_p) - { - parent->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)].he_node = - bucket->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)].he_node; - } - else - { - /* - * Just clear the predecessor entry pointing - * at 'bucket' - */ - hicn_hashtb_init_entry (&parent->hb_entries - [(HICN_HASHTB_BUCKET_ENTRIES - 1)], 0, - 0LL, 0); - } - - break; - } - /* - * After the first iteration, 'parent' will be an overflow - * bucket too - */ - parent = pool_elt_at_index (h->ht_overflow_buckets, bidx); - } - - /* We really expect to have found the predecessor */ - ASSERT (parent != NULL); - - /* And now, finally, we can put 'bucket' back on the free list */ - free_overflow_bucket (h, &bucket); - -done: - return; -} - -/* - * Prepare a hashtable node, supplying the key, and computed hash info. - */ -void -hicn_hashtb_init_node (hicn_hashtb_h h, hicn_hash_node_t * node, - const u8 * key, u32 keylen) -{ - assert (h != NULL); - assert (node != NULL); - assert (keylen <= HICN_PARAM_HICN_NAME_LEN_MAX); - - /* Init the node struct */ - node->hn_flags = HICN_HASH_NODE_FLAGS_DEFAULT; - node->hn_keysize = 0; - node->hn_keysize = keylen; - memcpy (node->hn_key.ks.key, key, keylen); - node->bucket_id = ~0; - node->entry_idx = ~0; -} - -/* - * Release a hashtable node back to the free list when an entry is cleared - */ -void -hicn_hashtb_free_node (hicn_hashtb_h h, hicn_hash_node_t * node) -{ - ASSERT (h->ht_nodes_used > 0); - - /* Return 'node' to the free list */ - pool_put (h->ht_nodes, node); - h->ht_nodes_used--; - -} - -/* - * Walk a hashtable, iterating through the nodes, keeping context in 'ctx'. - */ -int -hicn_hashtb_next_node (hicn_hashtb_h h, hicn_hash_node_t ** pnode, u64 * ctx) -{ - int i, j, ret = HICN_ERROR_HASHTB_INVAL; - u32 bidx, entry; - hicn_hash_bucket_t *bucket; - - if ((h == NULL) || (pnode == NULL) || (ctx == NULL)) - { - goto done; - } - /* Special-case for new iteration */ - if (*ctx == HICN_HASH_WALK_CTX_INITIAL) - { - bidx = 0; - bucket = &h->ht_buckets[0]; - entry = 0; - j = 0; - i = 0; - goto search_table; - } - /* Convert context to bucket and entry indices */ - bidx = *ctx & 0xffffffffLL; - entry = *ctx >> 32; - - if (bidx >= h->ht_bucket_count) - { - ret = HICN_ERROR_HASHTB_HASH_NOT_FOUND; - goto done; - } - bucket = h->ht_buckets + bidx; - - /* Init total index into entries (includes fixed bucket and overflow) */ - j = 0; - -skip_processed_bucket_chunks: - /* - * Figure out where to resume the search for the next entry in the - * table, by trying to find the last entry returned, from the cookie. - * Loop walks one (regular or overflow) bucket chunk, label is used - * for walking chain of chunks. Note that if there was a deletion or - * an addition that created an overflow, iterator can skip entries or - * return duplicate entries, for entries that are present from before - * the walk starts until after it ends. - */ - - for (i = 0; i < HICN_HASHTB_BUCKET_ENTRIES; i++, j++) - { - if (j > entry) - { - /* - * Start search for next here, use existing 'bucket' - * and 'i' - */ - break; - } - /* - * If an entry is marked for deletion, ignore it - */ - if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_DELETED) - { - continue; - } - /* - * Be prepared to continue to an overflow bucket if - * necessary. (We only expect the last entry in a bucket to - * refer to an overflow bucket...) - */ - if (i == (HICN_HASHTB_BUCKET_ENTRIES - 1)) - { - if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW) - { - bucket = pool_elt_at_index (h->ht_overflow_buckets, - bucket->hb_entries[i].he_node); - - /* Increment overall entry counter 'j' */ - j++; - - goto skip_processed_bucket_chunks; - } - /* - * end of row (end of fixed bucket plus any - * overflows) - */ - i = 0; - j = 0; - - bidx++; - - /* Special case - we're at the end */ - if (bidx >= h->ht_bucket_count) - { - ret = HICN_ERROR_HASHTB_HASH_NOT_FOUND; - goto done; - } - bucket = h->ht_buckets + bidx; - break; - } - } - -search_table: - - /* - * Now we're searching through the table for the next entry that's - * set - */ - - for (; i < HICN_HASHTB_BUCKET_ENTRIES; i++, j++) - { - /* - * If an entry is marked for deletion, ignore it - */ - if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_DELETED) - { - continue; - } - /* Is this entry set? */ - if (bucket->hb_entries[i].he_node != 0) - { - - /* Retrieve the node struct */ - *pnode = pool_elt_at_index (h->ht_nodes, - bucket->hb_entries[i].he_node); - - /* - * Set 'entry' as we exit, so we can update the - * cookie - */ - entry = j; - ret = HICN_ERROR_NONE; - break; - } - /* - * Be prepared to continue to an overflow bucket if - * necessary. (We only expect the last entry in a bucket to - * refer to an overflow bucket...) - */ - if (i == (HICN_HASHTB_BUCKET_ENTRIES - 1)) - { - if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW) - { - bucket = pool_elt_at_index (h->ht_overflow_buckets, - bucket->hb_entries[i].he_node); - /* - * Reset per-bucket index 'i', here (not done - * in iterator) - */ - i = 0; - /* Increment overall entry counter 'j' */ - j++; - - goto search_table; - } - else - { - /* - * Move to next bucket, resetting per-bucket - * and overall entry indexes - */ - i = 0; - j = 0; - - bidx++; - - /* Special case - we're at the end */ - if (bidx >= h->ht_bucket_count) - { - ret = HICN_ERROR_HASHTB_HASH_NOT_FOUND; - goto done; - } - bucket = h->ht_buckets + bidx; - goto search_table; - } - } - } - -done: - - if (ret == HICN_ERROR_NONE) - { - /* Update context */ - *ctx = bidx; - *ctx |= ((u64) entry << 32); - } - return (ret); -} - -int -hicn_hashtb_key_to_buf (u8 ** vec_res, hicn_hashtb_h h, - const hicn_hash_node_t * node) -{ - int ret = HICN_ERROR_NONE; - u8 *vec = *vec_res; - - if (node->hn_keysize <= HICN_HASH_KEY_BYTES) - { - vec_add (vec, node->hn_key.ks.key, node->hn_keysize); - } - *vec_res = vec; - return (ret); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/hashtb.h b/hicn-plugin/src/hashtb.h deleted file mode 100644 index 3c72fda65..000000000 --- a/hicn-plugin/src/hashtb.h +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Copyright (c) 2017-2019 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_HASHTB_H__ -#define __HICN_HASHTB_H__ - -#include -#include -#include - -#include "params.h" -#include "parser.h" -#include "error.h" - -/** - * @file hashtb.h - * Lookup is finding a hashtable record whose name matches the name being - * looked up. Most of the lookup work is based on the hash value of the two - * names. Note that the intel cache line size is 64 bytes, and some platforms - * load in 2 cache lines together. - * - first step is to match a record at the bucket/slot level (htab has an - * array of htbucket_t/htbc_elmt, where each bucket has 7 slots to hold indices - * for entries.) Matching at this level implies - * - the hashes of the lookup name and the record map to the same bucket - * - the high 32 bits of the hashes (slot bce_hash_msb32s) match. Read - * cost (on the hash table size, i.e. ignoring reading the name being - * looked up): - * - First step normally requires 1 cache line load to pull in the - * 64-byte htbucket_t with the 7 element slot table holding the - * hash_msb32s. - * - In the event (hopefully rare for a hash table with appropriate - * number of buckets) that more than 7 elements hash to the same bucket, - * lookup may well need to look not only at the static htbc_elmt_t but at - * the chain of dynamically allocated htbc_elmt_t's linked to the static - * htbc_elmt_t, where each of these holds slot entries for additional elements. - * - Before reaching that point, it is initially required to read in the - * hash table record fields (ht_bucket_buf, htnode buf, etc) holding - * pointers to the arrays, but these cache lines are common to all lookups - * so will likely already be in the cache. - * - second step is to match at the record level (htnode/htkb level) once a - * slot-level match happens. Matching at this level implies the following match - * - the hash values (the full 64 bits vs. bucket+32 msb, above). - * - the name which, on the hash table side, is stored as a list of htkb_t (key buffers). - * - * Some hashtables (for which rare false positives are tolerable) store hash - * values but no keys. (In ISM NDN forwarder, this was used for dcm_dpf: data - * cache manager's dataplane filter, where speed was critical and very rare - * false positives would be detected in the full dcm check.) - No key buffers - * are used (or even allocated at hash table creation). - */ - -/* Handy abbreviations for success status, and for boolean values */ -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#define HICN_HASH_INVALID_IDX ~0 -/* - * for hicn_hashtb_next_node() iterator, this otherwise illegal context value - * indicates first call of iteration. Note: must not be 0, which is a legal - * context value. - */ -#define HICN_HASH_WALK_CTX_INITIAL (~((u64)0)) - -/* - * Key memory allocation scheme. - * - * The key is the bytestring that a hashtable entry is storing, e.g. a fib - * prefix or packet name. The hash of the name is used not just to pick the - * bucket, but also as a surrogate for the actual key value. - * - * Client calls pass key/name as contiguous memory for lookup/add/delete but - * hashable stores its copy of the key/name as a list of one or more hash_key - * structs. - key memory is managed as a list of keys (cache line - * sized/aligned buffers). - If (keysize < 128) then use key struct's full - * 128 bytes - If not, first key struct is head of a linked list of elements - * where the first bytes are used for the key and the last 4 bytes are the - * index of the next entry (or an end marker). - key memory is generally the - * single largest use of memory in the hash table, especially for PIT, as - * names are bigger than node structs (which is also per name/entry). - * - */ - -/* Compute hash node index from node pointer */ -#define NODE_IDX_FROM_NODE(p, h) \ - (u32)((p) - ((h)->ht_nodes)) - -#define HICN_HASH_KEY_BYTES 20 - -typedef struct -{ - struct - { - u8 key[HICN_HASH_KEY_BYTES]; - } ks; /* Entire key in one block */ -} hicn_hash_key_t; - -/* - * Ratio of extra key blocks to allocate, in case the embedded ones aren't - * sufficient. This is the fraction of the number of entries allocated. - */ -#define HICN_HASHTB_KEY_RATIO 8 - -/* - * hash node, used to store a hash table entry; indexed by an entry in a - * bucket. the node contains an embedded key; long keys are stored as chains - * of keys. - * - * The memory block for a node includes space for storing outgoing faces for - * interests, additional memory located off the end of the htnode data structure. - * - */ - -/* Size this so that we can offer 64B aligned on 64-bits for storing outgoing - * faces information - */ -#define HICN_HASH_NODE_APP_DATA_SIZE 64 - -/* How to align in the right way */ -typedef struct __attribute__ ((packed)) hicn_hash_node_s -{ - /* Bucket id containing the corresponding hash entry. */ - u32 bucket_id; - - /* Hash entry index in the bucket */ - u32 entry_idx; - - /* Total size of the key */ - u16 hn_keysize; - - /* 1 byte of flags for application use */ - u8 hn_flags; - - u8 _hn_reserved1; /* TBD, to align what follows back to - * 32 */ - - hicn_hash_key_t hn_key; /* Key value embedded in the node, may chain - * to more key buffers if necessary */ - - /* 32B + HICN_HASH_NODE_APP_DATA_SIZE */ - /* Followed by app-specific data (fib or pit or cs entry, e.g.) */ - u8 hn_data[HICN_HASH_NODE_APP_DATA_SIZE]; - -} hicn_hash_node_t; - -#define HICN_HASH_NODE_FLAGS_DEFAULT 0x00 -#define HICN_HASH_NODE_CS_FLAGS 0x01 -#define HICN_HASH_NODE_OVERFLOW_BUCKET 0x02 - -/* - * hicn_hash_entry_t Structure holding all or part of a hash value, a node - * index, and other key pieces of info. - * - * - 128 bytes/bucket with 19 bytes/entry gives 6 entries, or 5 entries plus - * next bucket ptr if overflow Changes in this structure will affect - * hicn_hash_bucket_t - */ -typedef struct __attribute__ ((packed)) hicn_hash_entry_s -{ - - /* MSB of the hash value */ - u64 he_msb64; - - /* Index of node block */ - u32 he_node; - - /* - * Lock to prevent hash_node deletion while there are still interest - * or data referring to it - */ - u32 locks; - - /* Index of dpo (4B) */ - index_t dpo_ctx_id; - - /* A few flags, including 'this points to a chain of buckets' */ - u8 he_flags; - - /* - * Index of the virtual function table corresponding to the dpo_ctx - * strategy - */ - u8 vft_id; - -} hicn_hash_entry_t; //size 22B - -STATIC_ASSERT (sizeof (index_t) <= 4, "sizeof index_t is greater than 4B"); - - -#define HICN_HASH_ENTRY_FLAGS_DEFAULT 0x00 - -/* If entry is PIT this flag is 0 */ -#define HICN_HASH_ENTRY_FLAG_CS_ENTRY 0x01 - -/* - * This entry heads a chain of overflow buckets (we expect to see this only - * in the last entry in a bucket.) In this case, the index is to an overflow - * bucket rather than to a single node block. - */ -#define HICN_HASH_ENTRY_FLAG_OVERFLOW 0x04 - -/* This entry has been marked for deletion */ -#define HICN_HASH_ENTRY_FLAG_DELETED 0x08 - -/* Use fast he_timeout units for expiration, slow if not */ -#define HICN_HASH_ENTRY_FLAG_FAST_TIMEOUT 0x10 - -/* - * hash bucket: Contains an array of entries. Cache line sized/aligned, so no - * room for extra fields unless bucket size is increased to 2 cache lines or - * the entry struct shrinks. - */ - -/* - * Overflow bucket ratio as a fraction of the fixed/configured count; a pool - * of hash buckets used if a row in the fixed table overflows. - */ -#define HICN_HASHTB_BUCKET_ENTRIES 5 - -typedef struct __attribute__ ((packed)) -{ - hicn_hash_entry_t hb_entries[HICN_HASHTB_BUCKET_ENTRIES]; - u64 align1; - u64 align2; - u16 align3; -} hicn_hash_bucket_t; - -/* Overall target fill-factor for the hashtable */ -#define HICN_HASHTB_FILL_FACTOR 4 - -#define HICN_HASHTB_MIN_ENTRIES (1 << 4) // includes dummy node 0 entry -#define HICN_HASHTB_MAX_ENTRIES (1 << 24) - -#define HICN_HASHTB_MIN_BUCKETS (1 << 10) - -/* - * htab_t - * - * Hash table main structure. - * - * Contains - pointers to dynamically allocated arrays of cache-line - * sized/aligned structures (buckets, nodes, keys). Put frequently accessed - * fields in the first cache line. - */ -typedef struct hicn_hashtb_s -{ - - /* 8B - main array of hash buckets */ - hicn_hash_bucket_t *ht_buckets; - - /* 8B - just-in-case block of overflow buckets */ - hicn_hash_bucket_t *ht_overflow_buckets; - - /* 8B - block of nodes associated with entries in buckets */ - hicn_hash_node_t *ht_nodes; - - /* Flags */ - u32 ht_flags; - - /* Count of buckets allocated in the main array */ - u32 ht_bucket_count; - - /* Count of overflow buckets allocated */ - u32 ht_overflow_bucket_count; - u32 ht_overflow_buckets_used; - - /* Count of nodes allocated */ - u32 ht_node_count; - u32 ht_nodes_used; - - /* Count of overflow key structs allocated */ - u32 ht_key_count; - u32 ht_keys_used; - -} hicn_hashtb_t, *hicn_hashtb_h; - -/* - * Offset to aligned start of additional data (PIT/CS, FIB) embedded in each - * node. - */ -extern u32 ht_node_data_offset_aligned; - -/* Flags for hashtable */ - -#define HICN_HASHTB_FLAGS_DEFAULT 0x00 - -/* - * Don't use the last entry in each bucket - only use it for overflow. We use - * this for the FIB, currently, so that we can support in-place FIB changes - * that would be difficult if there were hash entry copies as part of - * overflow handling. - */ -#define HICN_HASHTB_FLAG_USE_SEVEN 0x04 -#define HICN_HASHTB_FLAG_KEY_FMT_PFX 0x08 -#define HICN_HASHTB_FLAG_KEY_FMT_NAME 0x10 - -/* - * Max prefix name components we'll support in our incremental hashing; - * currently used only for LPM in the FIB. - */ -#define HICN_HASHTB_MAX_NAME_COMPS HICN_PARAM_FIB_ENTRY_PFX_COMPS_MAX - -/* - * APIs and inlines - */ - -/* Compute hash node index from node pointer */ -static inline u32 -hicn_hashtb_node_idx_from_node (hicn_hashtb_h h, hicn_hash_node_t * p) -{ - return (p - h->ht_nodes); -} - -/* Retrieve a hashtable node by node index */ -static inline hicn_hash_node_t * -hicn_hashtb_node_from_idx (hicn_hashtb_h h, u32 idx) -{ - return (pool_elt_at_index (h->ht_nodes, idx)); -} - -/* Allocate a brand-new hashtable */ -int -hicn_hashtb_alloc (hicn_hashtb_h * ph, u32 max_elems, size_t app_data_size); - -/* Free a hashtable, including its embedded arrays */ -int hicn_hashtb_free (hicn_hashtb_h * ph); - -/* Hash a bytestring, currently using bihash */ -u64 hicn_hashtb_hash_bytestring (const u8 * key, u32 keylen); - -always_inline hicn_hash_entry_t * -hicn_hashtb_get_entry (hicn_hashtb_h h, u32 entry_idx, u32 bucket_id, - u8 bucket_overflow) -{ - hicn_hash_bucket_t *bucket; - if (bucket_overflow) - bucket = pool_elt_at_index (h->ht_overflow_buckets, bucket_id); - else - bucket = (hicn_hash_bucket_t *) (h->ht_buckets + bucket_id); - - return &(bucket->hb_entries[entry_idx]); -} - -/* Hash a name, currently using bihash */ -always_inline u64 -hicn_hashtb_hash_name (const u8 * key, u16 keylen) -{ - if (key != NULL && keylen == HICN_V4_NAME_LEN) - { - clib_bihash_kv_8_8_t kv; - kv.key = ((u64 *) key)[0]; - return clib_bihash_hash_8_8 (&kv); - } - else if (key != NULL && keylen == HICN_V6_NAME_LEN) - { - clib_bihash_kv_24_8_t kv; - kv.key[0] = ((u64 *) key)[0]; - kv.key[1] = ((u64 *) key)[1]; - kv.key[2] = ((u32 *) key)[4]; - return clib_bihash_hash_24_8 (&kv); - } - else - { - return (-1LL); - } -} - - -/* - * Prepare a hashtable node for insertion, supplying the key and computed - * hash info. This sets up the node->key relationship, possibly allocating - * overflow key buffers. - */ -void -hicn_hashtb_init_node (hicn_hashtb_h h, hicn_hash_node_t * node, - const u8 * key, u32 keylen); - -/* - * Insert a node into the hashtable. We expect the caller has used the init - * api to set the node key and hash info, and populated the extra data area - * (if any) - or done the equivalent work itself. - */ -int -hicn_hashtb_insert (hicn_hashtb_h h, hicn_hash_node_t * node, - hicn_hash_entry_t ** hash_entry, u64 hash, - u32 * node_id, - index_t * dpo_ctx_id, u8 * vft_id, u8 * is_cs, - u8 * hash_entry_id, u32 * bucket_id, - u8 * bucket_is_overflow); - -/* - * Basic api to lookup a specific hash+key tuple. This does the entire lookup - * operation, retrieving node structs and comparing keys, so it's not - * optimized for prefetching or high performance. - * - * Returns zero and mails back a node on success, errno otherwise. - */ -int -hicn_hashtb_lookup_node (hicn_hashtb_h h, const u8 * key, - u32 keylen, u64 hashval, u8 is_data, - u32 * node_id, index_t * dpo_ctx_id, u8 * vft_id, - u8 * is_cs, u8 * hash_entry_id, u32 * bucket_id, - u8 * bucket_is_overflow); - -/* - * Extended api to lookup a specific hash+key tuple. The implementation - * allows the caller to locate nodes that are marked for deletion; this is - * part of some hashtable applications, such as the FIB. - * - * This does the entire lookup operation, retrieving node structs and comparing - * keys, so it's not optimized for prefetching or high performance. - * - * Returns zero and mails back a node on success, errno otherwise. - */ -int -hicn_hashtb_lookup_node_ex (hicn_hashtb_h h, const u8 * key, - u32 keylen, u64 hashval, u8 is_data, - int include_deleted_p, u32 * node_id, - index_t * dpo_ctx_id, u8 * vft_id, u8 * is_cs, - u8 * hash_entry_id, u32 * bucket_id, - u8 * bucket_is_overflow); - -/** - * @brief Compares the key in the node with the given key - * - * This function allows to split the hash verification from the comparison of - * the entire key. Useful to exploit prefertching. - * @result 1 if equals, 0 otherwise - */ -int hicn_node_compare (const u8 * key, u32 keylen, hicn_hash_node_t * node); - -/* - * Remove a node from a hashtable using the node itself. The internal data - * structs are cleaned up, but the node struct itself is not: the caller must - * free the node itself. - */ -void hicn_hashtb_remove_node (hicn_hashtb_h h, hicn_hash_node_t * node, - u64 hashval); - -/* - * Delete a node from a hashtable using the node itself, and delete/free the - * node. Caller's pointer is cleared on success. - */ -void hicn_hashtb_delete (hicn_hashtb_h h, hicn_hash_node_t ** pnode, - u64 hashval); - -/* - * Utility to init a new entry in a hashtable bucket/row. We use this to add - * new a node+hash, and to clear out an entry during removal. - */ -void -hicn_hashtb_init_entry (hicn_hash_entry_t * entry, - u32 nodeidx, u64 hashval, u32 locks); - - -/* - * Return data area embedded in a hash node struct. We maintain an 'offset' - * value in case the common node body struct doesn't leave the data area - * aligned properly. - */ -static inline void * -hicn_hashtb_node_data (hicn_hash_node_t * node) -{ - return ((u8 *) (node) + ht_node_data_offset_aligned); -} - -/* - * Use some bits of the low half of the hash to locate a row/bucket in the - * table - */ -static inline u32 -hicn_hashtb_bucket_idx (hicn_hashtb_h h, u64 hashval) -{ - return ((u32) (hashval & (h->ht_bucket_count - 1))); -} - -/* - * Return a hash node struct from the free list, or NULL. Note that the - * returned struct is _not_ cleared/zeroed - init is up to the caller. - */ -static inline hicn_hash_node_t * -hicn_hashtb_alloc_node (hicn_hashtb_h h) -{ - hicn_hash_node_t *p = NULL; - - if (h->ht_nodes_used < h->ht_node_count) - { - pool_get_aligned (h->ht_nodes, p, 8); - h->ht_nodes_used++; - } - return (p); -} - -/* - * Release a hashtable node back to the free list when an entry is cleared - */ -void hicn_hashtb_free_node (hicn_hashtb_h h, hicn_hash_node_t * node); - -/* - * Walk a hashtable, iterating through the nodes, keeping context in 'ctx' - * between calls. - * - * Set the context value to HICN_HASH_WALK_CTX_INITIAL to start an iteration. - */ -int -hicn_hashtb_next_node (hicn_hashtb_h h, hicn_hash_node_t ** pnode, u64 * ctx); - - -int -hicn_hashtb_key_to_str (hicn_hashtb_h h, const hicn_hash_node_t * node, - char *buf, int bufsize, int must_fit); - -/* - * single hash full name can pass offset for two hashes calculation in case - * we use CS and PIT in a two steps hashes (prefix + seqno) - */ -always_inline int -hicn_hashtb_fullhash (const u8 * name, u16 namelen, u64 * name_hash) -{ - *name_hash = hicn_hashtb_hash_name (name, namelen); - return (*name_hash != (-1LL) ? HICN_ERROR_NONE : HICN_ERROR_HASHTB_INVAL); -} - -#endif /* // __HICN_HASHTB_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/hicn.api b/hicn-plugin/src/hicn.api deleted file mode 100644 index 9643f2098..000000000 --- a/hicn-plugin/src/hicn.api +++ /dev/null @@ -1,579 +0,0 @@ -/* - * Copyright (c) 2017-2020 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. - */ - -option version = "5.1.0"; -import "vnet/ip/ip_types.api"; - -enum hicn_action_type -{ - HICN_DISABLE = 0, - HICN_ENABLE, -}; - -typedef hicn_face -{ - /* IP local address */ - vl_api_address_t nat_addr; - - /* IPv4 local port number */ - u32 swif; - - /* Face flags */ - u32 flags; - - /* Name of the interface */ - u8 if_name[30]; -}; - -define hicn_api_node_params_set -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* Enable / disable ICN forwarder in VPP */ - u8 enable_disable; - - /* PIT maximum size, otherwise -1 to assign default value */ - i32 pit_max_size; - - /* CS maximum size, otherwise -1 to assign default value */ - i32 cs_max_size; - - /* Upper bound on PIT entry lifetime, otherwise -1 to assign default value */ - f64 pit_max_lifetime_sec; -}; - -define hicn_api_node_params_set_reply -{ - /* From the request */ - u32 context; - - /* Return value, zero means all OK */ - i32 retval; -}; - -define hicn_api_node_params_get -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; -}; - -define hicn_api_node_params_get_reply -{ - /* From the request */ - u32 context; - - /* Return value, zero means all OK */ - i32 retval; - - /* Enabled / disabled flag */ - u8 is_enabled; - - /* compile-time plugin features */ - u8 feature_cs; - - /* Number of VPP workers */ - u32 worker_count; - - /* PIT maximum size, otherwise -1 to assign default value */ - u32 pit_max_size; - - /* CS maximum size, otherwise -1 to assign default value */ - u32 cs_max_size; - - /* Upper bound on PIT entry lifetime */ - f64 pit_max_lifetime_sec; -}; - -define hicn_api_node_stats_get -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; -}; - -define hicn_api_node_stats_get_reply -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* Return value, zero means all OK */ - i32 retval; - - /* ICN packets processed */ - u64 pkts_processed; - - /* ICN interests forwarded */ - u64 pkts_interest_count; - - /* ICN data msgs forwarded */ - u64 pkts_data_count; - - /* ICN cached data msg replies */ - u64 pkts_from_cache_count; - - /* ICN no PIT entry drops */ - u64 pkts_no_pit_count; - - /* ICN expired PIT entries */ - u64 pit_expired_count; - - /* ICN expired CS entries */ - u64 cs_expired_count; - - /* ICN LRU CS entries freed */ - u64 cs_lru_count; - - /* ICN msgs dropped due to no packet buffers */ - u64 pkts_drop_no_buf; - - /* ICN Interest messages aggregated in PIT */ - u64 interests_aggregated; - - /* ICN Interest messages retransmitted */ - u64 interests_retx; - - /* ICN Interest messages colliding in hashtb */ - u64 interests_hash_collision; - - /* Number of entries in PIT at the present moment */ - u64 pit_entries_count; - - /* Number of entries in CS at the present moment */ - u64 cs_entries_count; - - /* Number of entries in CS at the present moment */ - u64 cs_entries_ntw_count; -}; - -define hicn_api_face_stats_details -{ -/* From the request */ - u32 context; - - /* Return value, zero means all OK */ - i32 retval; - - /* Id of the face */ - u32 faceid; - - /* Interest rx */ - u64 irx_packets; - - u64 irx_bytes; - - /* Interest tx */ - u64 itx_packets; - - u64 itx_bytes; - - /* data rx */ - u64 drx_packets; - - u64 drx_bytes; - - /* data tx */ - u64 dtx_packets; - - u64 dtx_bytes; -}; - -define hicn_api_face_stats_dump -{ -/* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; -}; - -define hicn_api_face_params_get -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* A Face to be retrieved */ - u32 faceid; -}; - -define hicn_api_face_params_get_reply -{ - /* From the request */ - u32 context; - - /* Return value, zero means all OK */ - i32 retval; - - /* The face required */ - u32 faceid; - - /* IP local address */ - vl_api_address_t nat_addr; - - /* VPP interface (index) associated with the face */ - u32 swif; - - /* Face flags */ - u32 flags; -}; - -define hicn_api_faces_details -{ -/* From the request */ - u32 context; - - /* Return value, zero means all OK */ - i32 retval; - - /* Id of the face */ - u32 faceid; - - /* Face to add */ - vl_api_hicn_face_t face; -}; - -define hicn_api_faces_dump -{ -/* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; -}; - -define hicn_api_face_get -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* A Face to be retrieved */ - u32 faceid; -}; - -define hicn_api_face_get_reply -{ - /* From the request */ - u32 context; - - /* Return value, zero means all OK */ - i32 retval; - - /* Id of the face */ - u32 faceid; - - /* Face to add */ - vl_api_hicn_face_t face; -}; - -define hicn_api_route_get -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* Route prefix */ - vl_api_prefix_t prefix; -}; - -define hicn_api_route_get_reply -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* List of faces pointing to the next hops */ - u32 faceids[5]; - - /* Number of valid faceids */ - u8 nfaces; - - /* Strategy */ - u32 strategy_id; - - /* Return value, zero means all OK */ - i32 retval; -}; - -define hicn_api_routes_details -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* Route prefix */ - vl_api_prefix_t prefix; - - /* List of faces pointing to the next hops */ - u32 faceids[5]; - - /* Number of valid faceids */ - u8 nfaces; - - /* Strategy */ - u32 strategy_id; - - /* Return value, zero means all OK */ - i32 retval; -}; - -define hicn_api_routes_dump -{ -/* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; -}; - -define hicn_api_strategies_get -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; -}; - -define hicn_api_strategies_get_reply -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* Number of available strategies */ - u8 n_strategies; - - /* Strategies */ - u32 strategy_id[256]; - - /* Return value, zero means all OK */ - i32 retval; -}; - -define hicn_api_strategy_get -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* Route prefix */ - u32 strategy_id; -}; - -define hicn_api_strategy_get_reply -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* Strategy description */ - u8 description[200]; - - /* Return value, zero means all OK */ - i32 retval; -}; - -define hicn_api_enable_disable -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* Enable or disable enable/disable hICN*/ - vl_api_hicn_action_type_t enable_disable; - - /* Prefix on which we enable/disable hICN*/ - vl_api_prefix_t prefix; -}; - -define hicn_api_enable_disable_reply -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - -/* Return value, zero means all OK */ - i32 retval; -}; - -define hicn_api_register_prod_app -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* Prefix to match */ - vl_api_prefix_t prefix; - - /* sw_if id */ - u32 swif; - - /* CS memory reserved -- in number of packets */ - u32 cs_reserved; -}; - -define hicn_api_register_prod_app_reply -{ - /* From the request */ - u32 context; - - /* Return value, zero means all OK */ - i32 retval; - - /* Actual CS memory reserved -- in number of packets */ - u32 cs_reserved; - - /* Prod address (ipv4 or ipv6) */ - vl_api_address_t prod_addr; - - /* Return value: new Face ID, ~0 means no Face was created */ - u32 faceid; -}; - -autoreply define hicn_api_face_prod_del -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* A Face ID to be deleted */ - u32 faceid; -}; - -define hicn_api_register_cons_app -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* swif */ - u32 swif; -}; - -define hicn_api_register_cons_app_reply -{ - /* From the request */ - u32 context; - - /* Return value, zero means all OK */ - i32 retval; - - /* Ip4 address */ - vl_api_address_t src_addr4; - - /* Ip6 address */ - vl_api_address_t src_addr6; - - /* Return value: new Face ID, ~0 means no Face was created */ - u32 faceid1; - - /* Return value: new Face ID, ~0 means no Face was created */ - u32 faceid2; -}; - -autoreply define hicn_api_face_cons_del -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* A Face ID to be deleted */ - u32 faceid; -}; - -define hicn_api_udp_tunnel_add_del -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* Source address */ - vl_api_address_t src_addr; - - /* Destination address */ - vl_api_address_t dst_addr; - - /* Source port */ - u16 src_port; - - /* Destination port */ - u16 dst_port; - - /* Add or remove the tunnel*/ - u8 is_add; -}; - -define hicn_api_udp_tunnel_add_del_reply -{ - /* From the request */ - u32 context; - - /* Return value, zero means all OK */ - i32 retval; - - /* Udp encap index */ - u32 uei; -}; - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/hicn.c b/hicn-plugin/src/hicn.c deleted file mode 100644 index 43a717f80..000000000 --- a/hicn-plugin/src/hicn.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "hicn.h" -#include "params.h" -#include "infra.h" -#include "strategy_dpo_manager.h" -#include "mgmt.h" -#include "error.h" -#include "faces/app/address_mgr.h" -#include "face_db.h" -#include "udp_tunnels/udp_tunnel.h" -#include "route.h" - -hicn_main_t hicn_main; -/* Module vars */ -int hicn_infra_fwdr_initialized = 0; - -/* - * Global time counters we're trying out for opportunistic hashtable - * expiration. - */ -uint16_t hicn_infra_fast_timer; /* Counts at 1 second intervals */ -uint16_t hicn_infra_slow_timer; /* Counts at 1 minute intervals */ - -hicn_face_bucket_t *hicn_face_bucket_pool; - -/* - * Init hicn forwarder with configurable PIT, CS sizes - */ -static int -hicn_infra_fwdr_init (uint32_t shard_pit_size, uint32_t shard_cs_size) -{ - int ret = 0; - - if (hicn_infra_fwdr_initialized) - { - ret = HICN_ERROR_FWD_ALREADY_ENABLED; - goto done; - } - /* Init per worker limits */ - hicn_infra_pit_size = shard_pit_size; - hicn_infra_cs_size = shard_cs_size; - - /* Init the global time-compression counters */ - hicn_infra_fast_timer = 1; - hicn_infra_slow_timer = 1; - - ret = hicn_pit_create (&hicn_main.pitcs, hicn_infra_pit_size); - hicn_pit_set_lru_max (&hicn_main.pitcs, hicn_infra_cs_size); -done: - if ((ret == HICN_ERROR_NONE) && !hicn_infra_fwdr_initialized) - { - hicn_infra_fwdr_initialized = 1; - } - return (ret); -} - -/* - * Action function shared between message handler and debug CLI NOTICE: we're - * only 'enabling' now - */ -int -hicn_infra_plugin_enable_disable (int enable_disable, - int pit_size_req, - f64 pit_max_lifetime_sec_req, - int cs_size_req, - vnet_link_t link) -{ - int ret = 0; - - hicn_main_t *sm = &hicn_main; - uint32_t pit_size, cs_size; - - /* Notice if we're already enabled... */ - if (sm->is_enabled) - { - ret = HICN_ERROR_FWD_ALREADY_ENABLED; - goto done; - } - /* Set up params and call fwdr_init set up PIT/CS, forwarder nodes */ - - /* Check the range and assign some globals */ - if (pit_max_lifetime_sec_req < 0) - { - sm->pit_lifetime_max_ms = HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS; - } - else - { - if (pit_max_lifetime_sec_req < HICN_PARAM_PIT_LIFETIME_BOUND_MIN_SEC || - pit_max_lifetime_sec_req > HICN_PARAM_PIT_LIFETIME_BOUND_MAX_SEC) - { - ret = HICN_ERROR_PIT_CONFIG_MAXLT_OOB; - goto done; - } - sm->pit_lifetime_max_ms = pit_max_lifetime_sec_req * SEC_MS; - } - - if (pit_size_req < 0) - { - pit_size = HICN_PARAM_PIT_ENTRIES_DFLT; - } - else - { - if (pit_size_req < HICN_PARAM_PIT_ENTRIES_MIN || - pit_size_req > HICN_PARAM_PIT_ENTRIES_MAX) - { - ret = HICN_ERROR_PIT_CONFIG_SIZE_OOB; - goto done; - } - pit_size = (uint32_t) pit_size_req; - } - - if (cs_size_req < 0) - { - cs_size = HICN_PARAM_CS_ENTRIES_DFLT; - } - else - { - /* - * This should be relatively safe - * At this point vlib buffers should have been already allocated - */ - - vlib_buffer_main_t *bm; - vlib_buffer_pool_t *bp; - vlib_main_t *vm = vlib_get_main (); - bm = vm->buffer_main; - - u32 n_buffers = 0; - vec_foreach (bp, bm->buffer_pools) - n_buffers = n_buffers < bp->n_buffers ? bp->n_buffers : n_buffers; - - // check if CS is bugger tha PIT or bigger than the available vlib_buffers - uword cs_buffers = - (n_buffers > - HICN_PARAM_CS_MIN_MBUF) ? n_buffers - HICN_PARAM_CS_MIN_MBUF : 0; - - if (cs_size_req > (pit_size_req / 2) || cs_size_req > cs_buffers) - { - cs_size_req = - ((pit_size_req / 2) > cs_buffers) ? cs_buffers : pit_size_req / 2; - vlib_cli_output (vm, - "WARNING!! CS too large. Please check size of PIT or the number of buffers available in VPP\n"); - - } - cs_size = (uint32_t) cs_size_req; - } - - ret = hicn_infra_fwdr_init (pit_size, cs_size); - - hicn_face_db_init (pit_size); - - if (ret != HICN_ERROR_NONE) - { - goto done; - } - sm->is_enabled = 1; - sm->link = link; - //hicn_face_udp_init_internal (); - -done: - - return (ret); -} - -static clib_error_t * -hicn_configure (vlib_main_t * vm, unformat_input_t * input) -{ - u32 pit_size = HICN_PARAM_PIT_ENTRIES_DFLT; - u32 cs_size = HICN_PARAM_CS_ENTRIES_DFLT; - u64 pit_lifetime_max_sec = HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS / SEC_MS; - - vnet_link_t link; - - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "pit-size %u", &pit_size)) - ; - else if (unformat (input, "cs-size %u", &cs_size)) - ; - else if (unformat (input, "pit-lifetime-max %u", &pit_lifetime_max_sec)) - ; - else if (unformat (input, "grab mpls-tunnels")) - link = VNET_LINK_MPLS; - else - break; - } - - unformat_free (input); - - hicn_infra_plugin_enable_disable (1, pit_size, - pit_lifetime_max_sec, - cs_size, link); - - - return 0; -} - -VLIB_CONFIG_FUNCTION (hicn_configure, "hicn"); - -/* - * Init entry-point for the icn plugin - */ -static clib_error_t * -hicn_init (vlib_main_t * vm) -{ - clib_error_t *error = 0; - - hicn_main_t *sm = &hicn_main; - - /* Init other elements in the 'main' struct */ - sm->is_enabled = 0; - - error = hicn_api_plugin_hookup (vm); - - /* Init the dpo module */ - hicn_dpos_init (); - - /* Init the app manager */ - address_mgr_init (); - - hicn_face_module_init (vm); - - /* Init the route module */ - hicn_route_init (); - - udp_tunnel_init (); - - return error; -} - -VLIB_INIT_FUNCTION (hicn_init); - -/* *INDENT-OFF* */ -VLIB_PLUGIN_REGISTER() = -{ - .description = "hICN forwarder" -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/hicn.h b/hicn-plugin/src/hicn.h deleted file mode 100644 index 3d980bd49..000000000 --- a/hicn-plugin/src/hicn.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_H__ -#define __HICN_H__ - -#define ip_address_t hicn_ip_address_t -#define ip_address_cmp hicn_ip_address_cmp -#define ip_prefix_t hicn_ip_prefix_t -#define ip_prefix_cmp hicn_ip_prefix_cmp -#undef ip_prefix_len -#define ip_prefix_len hicn_ip_prefix_len -#include -#undef ip_address_t -#undef ip_address_cmp -#undef ip_prefix_t -#undef ip_prefix_cmp -#undef ip_prefix_len -#define ip_prefix_len(_a) (_a)->len - -#include "faces/face.h" - -#include -#include -#include -#include -#include -#include - -/** - * @file - */ - -/* Helper for avoiding warnings about type-punning */ -#define UNION_CAST(x, destType) \ - (((union {__typeof__(x) a; destType b;})x).b) - -/* - * Update CMakeLists.txt as we have to manually replace the type for - * vppapigen - */ -typedef u8 weight_t; - -#define ISV6(isv6, dov6, dov4) isv6 ? dov6 : dov4 -#define HICN_IS_NAMEHASH_CACHED(b) (((u64)(b->opaque2)[0] != 0) || ((u64)(b->opaque2)[1] != 0)) - -#ifndef VLIB_BUFFER_MIN_CHAIN_SEG_SIZE -#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_UDP4_TUNNEL 0x04 -#define HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL 0x08 - -/* The following is stored in the opaque2 field in the vlib_buffer_t */ -typedef struct -{ - /* hash of the name */ - u64 name_hash; - - /* ids to prefetch a PIT/CS entry */ - u32 node_id; - u32 bucket_id; - u8 hash_entry_id; - u8 hash_bucket_flags; - - u8 flags; - u8 dpo_ctx_id; /* used for data path */ - u8 vft_id; /* " */ - - hicn_face_id_t face_id; /* ingress iface, sizeof(u32) */ - u32 in_faces_vec_id; /* vector of possible input face for a data packet */ - - hicn_type_t type; -} hicn_buffer_t; - -STATIC_ASSERT (sizeof (hicn_buffer_t) <= - STRUCT_SIZE_OF (vlib_buffer_t, opaque2), - "hICN buffer opaque2 meta-data too large for vlib_buffer"); - - -always_inline hicn_buffer_t * -hicn_get_buffer (vlib_buffer_t * b0) -{ - return (hicn_buffer_t *) & (b0->opaque2[0]); -} - -always_inline u8 -hicn_is_v6 (hicn_header_t * pkt_hdr) -{ - return ((pkt_hdr->v4.ip.version_ihl >> 4) != 4); -} - -#endif /* __HICN_H__ */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/hicn_all_api_h.h b/hicn-plugin/src/hicn_all_api_h.h deleted file mode 100644 index 1263ea4a2..000000000 --- a/hicn-plugin/src/hicn_all_api_h.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2017-2019 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 - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/hicn_api.c b/hicn-plugin/src/hicn_api.c deleted file mode 100644 index e6050f96c..000000000 --- a/hicn-plugin/src/hicn_api.c +++ /dev/null @@ -1,727 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 -#include -#include -#include -#include -#include - -#include "faces/face.h" -#include "udp_tunnels/udp_tunnel.h" -#include "infra.h" -#include "parser.h" -#include "mgmt.h" -#include "strategy_dpo_manager.h" -#include "strategy_dpo_ctx.h" -#include "strategy.h" -#include "pg.h" -#include "error.h" -#include "faces/app/face_prod.h" -#include "faces/app/face_cons.h" -#include "route.h" - -/* define message IDs */ -#include -#include - -/* define generated endian-swappers */ -#define vl_endianfun -#include -#undef vl_endianfun - -#define REPLY_MSG_ID_BASE sm->msg_id_base -#include - -/****** SUPPORTING FUNCTION DECLARATIONS ******/ - -/* - * Convert a unix return code to a vnet_api return code. Currently stubby: - * should have more cases. - */ -always_inline vnet_api_error_t -hicn_face_api_entry_params_serialize (hicn_face_id_t faceid, - vl_api_hicn_api_face_params_get_reply_t - * reply); - - -/****************** API MESSAGE HANDLERS ******************/ - -/****** NODE ******/ - -static void -vl_api_hicn_api_node_params_set_t_handler (vl_api_hicn_api_node_params_set_t * - mp) -{ - vl_api_hicn_api_node_params_set_reply_t *rmp; - int rv; - - hicn_main_t *sm = &hicn_main; - - int pit_max_size = clib_net_to_host_i32 (mp->pit_max_size); - pit_max_size = - pit_max_size == -1 ? HICN_PARAM_PIT_ENTRIES_DFLT : pit_max_size; - - f64 pit_max_lifetime_sec = mp->pit_max_lifetime_sec; - pit_max_lifetime_sec = - pit_max_lifetime_sec == - -1 ? HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS / SEC_MS : pit_max_lifetime_sec; - - int cs_max_size = clib_net_to_host_i32 (mp->cs_max_size); - cs_max_size = cs_max_size == -1 ? HICN_PARAM_CS_ENTRIES_DFLT : cs_max_size; - - rv = hicn_infra_plugin_enable_disable ((int) (mp->enable_disable), - pit_max_size, - pit_max_lifetime_sec, - cs_max_size, - ~0); - - REPLY_MACRO (VL_API_HICN_API_NODE_PARAMS_SET_REPLY /* , rmp, mp, rv */ ); -} - -static void -vl_api_hicn_api_node_params_get_t_handler (vl_api_hicn_api_node_params_get_t * - mp) -{ - vl_api_hicn_api_node_params_get_reply_t *rmp; - int rv = HICN_ERROR_NONE; - - hicn_main_t *sm = &hicn_main; - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_HICN_API_NODE_PARAMS_GET_REPLY, ( - { - rmp->is_enabled = sm->is_enabled; - rmp->feature_cs = HICN_FEATURE_CS; - rmp->pit_max_size = clib_host_to_net_u32 (hicn_infra_pit_size); - rmp->pit_max_lifetime_sec = ((f64) sm->pit_lifetime_max_ms) / SEC_MS; - rmp->cs_max_size = clib_host_to_net_u32 (hicn_infra_cs_size); - rmp->retval = clib_host_to_net_i32 (rv); - })); - /* *INDENT-ON* */ -} - -static void -vl_api_hicn_api_node_stats_get_t_handler (vl_api_hicn_api_node_stats_get_t * - mp) -{ - vl_api_hicn_api_node_stats_get_reply_t *rmp; - int rv = HICN_ERROR_NONE; - - hicn_main_t *sm = &hicn_main; - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_HICN_API_NODE_STATS_GET_REPLY, ( - { - rv = hicn_mgmt_node_stats_get (rmp); - rmp->retval =clib_host_to_net_i32 (rv); - })); - /* *INDENT-ON* */ -} - - -static void - vl_api_hicn_api_face_params_get_t_handler - (vl_api_hicn_api_face_params_get_t * mp) -{ - vl_api_hicn_api_face_params_get_reply_t *rmp; - int rv = 0; - - hicn_main_t *sm = &hicn_main; - - hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid); - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_HICN_API_FACE_PARAMS_GET_REPLY, ( - { - rv = hicn_face_api_entry_params_serialize(faceid, rmp); - rmp->retval = clib_host_to_net_u32(rv); - })); - /* *INDENT-ON* */ -} - -static void -send_face_details (hicn_face_t * face, vl_api_hicn_face_t * mp) -{ - vnet_main_t *vnm = vnet_get_main (); - - ip_address_encode (&face->nat_addr, IP46_TYPE_ANY, &mp->nat_addr); - mp->flags = clib_host_to_net_u32 (face->flags); - mp->swif = clib_net_to_host_u32 (face->sw_if); - vnet_sw_interface_t *sw_interface = - vnet_get_sw_interface_or_null (vnm, face->sw_if); - u8 *sbuf = 0; - if (sw_interface != NULL) - { - sbuf = - format (0, "%U", format_vnet_sw_interface_name, vnm, sw_interface); - strcpy ((char *) (mp->if_name), (char *) sbuf); - } -} - -static void -send_faces_details (vl_api_registration_t * reg, - hicn_face_t * face, u32 context) -{ - vl_api_hicn_api_faces_details_t *mp; - hicn_main_t *hm = &hicn_main; - mp = vl_msg_api_alloc (sizeof (*mp)); - memset (mp, 0, sizeof (*mp)); - mp->faceid = clib_host_to_net_u32 (hicn_dpoi_get_index (face)); - mp->_vl_msg_id = htons (VL_API_HICN_API_FACES_DETAILS + hm->msg_id_base); - mp->context = context; - - send_face_details (face, &(mp->face)); - - vl_api_send_msg (reg, (u8 *) mp); -} - -static void -vl_api_hicn_api_faces_dump_t_handler (vl_api_hicn_api_faces_dump_t * mp) -{ - hicn_face_t *face; - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - /* *INDENT-OFF* */ - pool_foreach (face, hicn_dpoi_face_pool, - ({ - send_faces_details (reg, face, mp->context); - })); - /* *INDENT-ON* */ -} - -static void -vl_api_hicn_api_face_get_t_handler (vl_api_hicn_api_face_get_t * mp) -{ - vl_api_hicn_api_face_get_reply_t *rmp; - int rv = 0; - - hicn_main_t *sm = &hicn_main; - - hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid); - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_HICN_API_FACE_GET_REPLY, ( - { - rv = hicn_dpoi_idx_is_valid(faceid); - if (rv) - { - hicn_face_t * face = hicn_dpoi_get_from_idx(faceid); - send_face_details(face, &(rmp->face)); - rv = HICN_ERROR_NONE; - } - else - { - rv = HICN_ERROR_FACE_NOT_FOUND; - } - rmp->retval = clib_host_to_net_u32(rv); - })); - /* *INDENT-ON* */ -} - -static void -send_face_stats_details (vl_api_registration_t * reg, - hicn_face_t * face, u32 context) -{ - vl_api_hicn_api_face_stats_details_t *mp; - hicn_main_t *hm = &hicn_main; - mp = vl_msg_api_alloc (sizeof (*mp)); - memset (mp, 0, sizeof (*mp)); - - mp->_vl_msg_id = - htons (VL_API_HICN_API_FACE_STATS_DETAILS + hm->msg_id_base); - mp->context = context; - - mp->faceid = htonl (hicn_dpoi_get_index (face)); - vlib_counter_t v; - vlib_get_combined_counter (&counters - [hicn_dpoi_get_index (face) * HICN_N_COUNTER], - HICN_FACE_COUNTERS_INTEREST_RX, &v); - mp->irx_packets = clib_net_to_host_u64 (v.packets); - mp->irx_bytes = clib_net_to_host_u64 (v.bytes); - - vlib_get_combined_counter (&counters - [hicn_dpoi_get_index (face) * HICN_N_COUNTER], - HICN_FACE_COUNTERS_INTEREST_TX, &v); - mp->itx_packets = clib_net_to_host_u64 (v.packets); - mp->itx_bytes = clib_net_to_host_u64 (v.bytes); - - vlib_get_combined_counter (&counters - [hicn_dpoi_get_index (face) * HICN_N_COUNTER], - HICN_FACE_COUNTERS_DATA_RX, &v); - mp->drx_packets = clib_net_to_host_u64 (v.packets); - mp->drx_bytes = clib_net_to_host_u64 (v.bytes); - - vlib_get_combined_counter (&counters - [hicn_dpoi_get_index (face) * HICN_N_COUNTER], - HICN_FACE_COUNTERS_DATA_TX, &v); - mp->dtx_packets = clib_net_to_host_u64 (v.packets); - mp->dtx_bytes = clib_net_to_host_u64 (v.bytes); - - vl_api_send_msg (reg, (u8 *) mp); -} - -static void - vl_api_hicn_api_face_stats_dump_t_handler - (vl_api_hicn_api_face_stats_dump_t * mp) -{ - hicn_face_t *face; - vl_api_registration_t *reg; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - /* *INDENT-OFF* */ - pool_foreach (face, hicn_dpoi_face_pool, - ({ - send_face_stats_details (reg, face, mp->context); - })); - /* *INDENT-ON* */ -} - - -/****** ROUTE *******/ - -static void vl_api_hicn_api_route_get_t_handler - (vl_api_hicn_api_route_get_t * mp) -{ - vl_api_hicn_api_route_get_reply_t *rmp; - int rv = HICN_ERROR_NONE; - - hicn_main_t *sm = &hicn_main; - - fib_prefix_t prefix; - ip_prefix_decode (&mp->prefix, &prefix); - const dpo_id_t *hicn_dpo_id; - hicn_dpo_ctx_t *hicn_dpo_ctx; - u32 fib_index; - - rv = hicn_route_get_dpo (&prefix, &hicn_dpo_id, &fib_index); - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_HICN_API_ROUTE_GET_REPLY, ( - { - if (rv == HICN_ERROR_NONE) - { - hicn_dpo_ctx = hicn_strategy_dpo_ctx_get(hicn_dpo_id->dpoi_index); - for (int i = 0; hicn_dpo_ctx != NULL && i < hicn_dpo_ctx->entry_count; i++) - { - rmp->faceids[i] = hicn_dpo_ctx->next_hops[i]; - } - rmp->strategy_id = clib_host_to_net_u32(hicn_dpo_get_vft_id(hicn_dpo_id));} - })); - /* *INDENT-ON* */ -} - -static void -send_route_details (vl_api_registration_t * reg, - const fib_prefix_t * pfx, u32 context) -{ - vl_api_hicn_api_routes_details_t *mp; - hicn_main_t *hm = &hicn_main; - mp = vl_msg_api_alloc (sizeof (*mp)); - memset (mp, 0, sizeof (*mp)); - - mp->_vl_msg_id = htons (VL_API_HICN_API_ROUTES_DETAILS + hm->msg_id_base); - mp->context = context; - - ip_prefix_encode (pfx, &mp->prefix); - mp->nfaces = 0; - - const dpo_id_t *hicn_dpo_id; - hicn_dpo_ctx_t *hicn_dpo_ctx; - u32 fib_index; - - int rv = hicn_route_get_dpo (pfx, &hicn_dpo_id, &fib_index); - - if (rv == HICN_ERROR_NONE) - { - hicn_dpo_ctx = hicn_strategy_dpo_ctx_get (hicn_dpo_id->dpoi_index); - for (int i = 0; hicn_dpo_ctx != NULL && i < hicn_dpo_ctx->entry_count; - i++) - { - mp->faceids[i] = - clib_host_to_net_u32 (hicn_dpo_ctx-> - next_hops[i]); - mp->nfaces++; - } - mp->strategy_id = - clib_host_to_net_u32 (hicn_dpo_get_vft_id (hicn_dpo_id)); - } - - vl_api_send_msg (reg, (u8 *) mp); -} - -typedef struct vl_api_hicn_api_route_dump_walk_ctx_t_ -{ - fib_node_index_t *feis; -} vl_api_hicn_api_route_dump_walk_ctx_t; - -static fib_table_walk_rc_t -vl_api_hicn_api_route_dump_walk (fib_node_index_t fei, void *arg) -{ - vl_api_hicn_api_route_dump_walk_ctx_t *ctx = arg; - int found = 0; - const dpo_id_t *former_dpo_id; - - /* Route already existing. We need to update the dpo. */ - const dpo_id_t *load_balance_dpo_id = - fib_entry_contribute_ip_forwarding (fei); - - /* The dpo is not a load balance dpo as expected */ - if (load_balance_dpo_id->dpoi_type == DPO_LOAD_BALANCE) - { - /* former_dpo_id is a load_balance dpo */ - load_balance_t *lb = load_balance_get (load_balance_dpo_id->dpoi_index); - - /* FIB entry exists but there is no hicn dpo. */ - for (int i = 0; i < lb->lb_n_buckets && !found; i++) - { - former_dpo_id = load_balance_get_bucket_i (lb, i); - - if (dpo_is_hicn (former_dpo_id)) - { - vec_add1 (ctx->feis, fei); - } - } - } - - return (FIB_TABLE_WALK_CONTINUE); -} - -static void -vl_api_hicn_api_routes_dump_t_handler (vl_api_hicn_api_routes_dump_t * mp) -{ - vl_api_registration_t *reg; - fib_table_t *fib_table; - ip4_main_t *im = &ip4_main; - ip6_main_t *im6 = &ip6_main; - fib_node_index_t *lfeip; - const fib_prefix_t *pfx; - vl_api_hicn_api_route_dump_walk_ctx_t ctx = { - .feis = NULL, - }; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - pool_foreach (fib_table, im->fibs, ( - { - fib_table_walk (fib_table->ft_index, - FIB_PROTOCOL_IP4, - vl_api_hicn_api_route_dump_walk, - &ctx);} - )); - - pool_foreach (fib_table, im6->fibs, ( - { - fib_table_walk (fib_table->ft_index, - FIB_PROTOCOL_IP6, - vl_api_hicn_api_route_dump_walk, - &ctx);} - )); - - vec_foreach (lfeip, ctx.feis) - { - pfx = fib_entry_get_prefix (*lfeip); - send_route_details (reg, pfx, mp->context); - } - - vec_free (ctx.feis); - -} - -static void vl_api_hicn_api_strategies_get_t_handler - (vl_api_hicn_api_strategies_get_t * mp) -{ - vl_api_hicn_api_strategies_get_reply_t *rmp; - int rv = HICN_ERROR_NONE; - - hicn_main_t *sm = &hicn_main; - - int n_strategies = hicn_strategy_get_all_available (); - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_HICN_API_STRATEGIES_GET_REPLY/* , rmp, mp, rv */ ,( - { - int j = 0; - for (u32 i = 0; i < (u32) n_strategies; i++) - { - if (hicn_dpo_strategy_id_is_valid (i) == HICN_ERROR_NONE) - { - rmp->strategy_id[j] = clib_host_to_net_u32 (i); j++;} - } - rmp->n_strategies = n_strategies; - })); - /* *INDENT-ON* */ -} - -static void vl_api_hicn_api_strategy_get_t_handler - (vl_api_hicn_api_strategy_get_t * mp) -{ - vl_api_hicn_api_strategy_get_reply_t *rmp; - int rv = HICN_ERROR_NONE; - - hicn_main_t *sm = &hicn_main; - - u32 strategy_id = clib_net_to_host_u32 (mp->strategy_id); - rv = hicn_dpo_strategy_id_is_valid (strategy_id); - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_HICN_API_STRATEGY_GET_REPLY /* , rmp, mp, rv */ ,( - { - if (rv == HICN_ERROR_NONE) - { - const hicn_strategy_vft_t * hicn_strategy_vft = - hicn_dpo_get_strategy_vft (strategy_id); - hicn_strategy_vft->hicn_format_strategy (rmp->description, 0);} - })); - /* *INDENT-ON* */ -} - -/************* APP FACE ****************/ - -static void vl_api_hicn_api_register_prod_app_t_handler - (vl_api_hicn_api_register_prod_app_t * mp) -{ - vl_api_hicn_api_register_prod_app_reply_t *rmp; - int rv = HICN_ERROR_NONE; - - hicn_main_t *sm = &hicn_main; - - fib_prefix_t prefix; - ip_prefix_decode (&mp->prefix, &prefix); - u32 swif = clib_net_to_host_u32 (mp->swif); - u32 cs_reserved = clib_net_to_host_u32 (mp->cs_reserved); - u32 faceid; - - ip46_address_t prod_addr; - ip46_address_reset (&prod_addr); - rv = hicn_face_prod_add (&prefix, swif, &cs_reserved, &prod_addr, &faceid); - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_HICN_API_REGISTER_PROD_APP_REPLY, ( - { - ip_address_encode(&prod_addr, IP46_TYPE_ANY, &rmp->prod_addr); - rmp->cs_reserved = clib_net_to_host_u32(cs_reserved); - rmp->faceid = clib_net_to_host_u32(faceid); - })); - /* *INDENT-ON* */ -} - -static void -vl_api_hicn_api_face_prod_del_t_handler (vl_api_hicn_api_face_prod_del_t * mp) -{ - vl_api_hicn_api_face_prod_del_reply_t *rmp; - int rv = HICN_ERROR_FACE_NOT_FOUND; - - hicn_main_t *sm = &hicn_main; - - hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid); - rv = hicn_face_prod_del (faceid); - - REPLY_MACRO (VL_API_HICN_API_FACE_PROD_DEL_REPLY /* , rmp, mp, rv */ ); -} - -static void vl_api_hicn_api_register_cons_app_t_handler - (vl_api_hicn_api_register_cons_app_t * mp) -{ - vl_api_hicn_api_register_cons_app_reply_t *rmp; - int rv = HICN_ERROR_NONE; - - hicn_main_t *sm = &hicn_main; - ip46_address_t src_addr4 = ip46_address_initializer; - ip46_address_t src_addr6 = ip46_address_initializer; - - u32 swif = clib_net_to_host_u32 (mp->swif); - u32 faceid1; - u32 faceid2; - - rv = - hicn_face_cons_add (&src_addr4.ip4, &src_addr6.ip6, swif, &faceid1, - &faceid2); - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_HICN_API_REGISTER_CONS_APP_REPLY, ( - { - ip_address_encode(&src_addr4, IP46_TYPE_ANY, &rmp->src_addr4); - ip_address_encode(&src_addr6, IP46_TYPE_ANY, &rmp->src_addr6); - rmp->faceid1 = clib_net_to_host_u32(faceid1); - rmp->faceid2 = clib_net_to_host_u32(faceid2); - })); - /* *INDENT-ON* */ -} - -static void -vl_api_hicn_api_face_cons_del_t_handler (vl_api_hicn_api_face_cons_del_t * mp) -{ - vl_api_hicn_api_face_cons_del_reply_t *rmp; - int rv = HICN_ERROR_FACE_NOT_FOUND; - - hicn_main_t *sm = &hicn_main; - - hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid); - rv = hicn_face_cons_del (faceid); - - REPLY_MACRO (VL_API_HICN_API_FACE_CONS_DEL_REPLY /* , rmp, mp, rv */ ); -} - -static void vl_api_hicn_api_enable_disable_t_handler -(vl_api_hicn_api_enable_disable_t * mp) -{ - vl_api_hicn_api_enable_disable_reply_t *rmp; - int rv = HICN_ERROR_NONE; - - hicn_main_t *sm = &hicn_main; - - fib_prefix_t prefix; - ip_prefix_decode (&mp->prefix, &prefix); - - switch (clib_net_to_host_u32(mp->enable_disable)) - { - case HICN_ENABLE: - rv = hicn_route_enable(&prefix); - break; - case HICN_DISABLE: - rv = hicn_route_disable(&prefix); - break; - } - - REPLY_MACRO (VL_API_HICN_API_ENABLE_DISABLE_REPLY/* , rmp, mp, rv */ ); -} - -/*********************************** UDP TUNNELS ************************************/ - -static void vl_api_hicn_api_udp_tunnel_add_del_t_handler -(vl_api_hicn_api_udp_tunnel_add_del_t * mp) -{ - vl_api_hicn_api_udp_tunnel_add_del_reply_t *rmp; - int rv = HICN_ERROR_NONE; - - hicn_main_t *sm = &hicn_main; - - ip46_address_t src_addr; - ip46_address_t dst_addr; - u16 src_port; - u16 dst_port; - index_t uei = ~0; - - ip46_type_t type = ip_address_decode (&mp->src_addr, &src_addr); - if (type != ip_address_decode (&mp->dst_addr, &dst_addr)) - { - rv = HICN_ERROR_UDP_TUNNEL_SRC_DST_TYPE; - goto done; - } - - src_port = clib_net_to_host_u16(mp->src_port); - dst_port = clib_net_to_host_u16(mp->dst_port); - - fib_protocol_t proto = ip46_address_is_ip4(&src_addr) ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; - - index_t fib_index = fib_table_find (proto, HICN_FIB_TABLE); - - if (mp->is_add) - { - uei = udp_tunnel_add(proto, - fib_index, &src_addr, &dst_addr, src_port, dst_port, - UDP_ENCAP_FIXUP_NONE); - } - else - { - udp_tunnel_del(proto, - fib_index, &src_addr, &dst_addr, src_port, dst_port, - UDP_ENCAP_FIXUP_NONE); - } - - - done: - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_HICN_API_UDP_TUNNEL_ADD_DEL_REPLY, ( - { - rmp->uei = clib_host_to_net_u32(uei); - })); - /* *INDENT-ON* */ -} - -/************************************************************************************/ - -#include - -/* Set up the API message handling tables */ -clib_error_t * -hicn_api_plugin_hookup (vlib_main_t * vm) -{ - hicn_main_t *hm = &hicn_main; - - hm->msg_id_base = setup_message_id_table (); - return 0; -} - - - -/******************* SUPPORTING FUNCTIONS *******************/ - -/* - * Binary serialization for get face configuration API. for the moment - * assuming only ip faces here. To be completed with othet types of faces - */ -vnet_api_error_t -hicn_face_api_entry_params_serialize (hicn_face_id_t faceid, - vl_api_hicn_api_face_params_get_reply_t - * reply) -{ - int rv = HICN_ERROR_NONE; - - if (!reply) - { - rv = VNET_API_ERROR_INVALID_ARGUMENT; - goto done; - } - hicn_face_t *face = hicn_dpoi_get_from_idx (faceid); - - if (face != NULL) - { - ip_address_encode (&face->nat_addr, IP46_TYPE_ANY, - &reply->nat_addr); - - reply->swif = clib_host_to_net_u32 (face->sw_if); - reply->flags = clib_host_to_net_u32 (face->flags); - reply->faceid = clib_host_to_net_u32 (faceid); - } - else - rv = HICN_ERROR_FACE_IP_ADJ_NOT_FOUND; - -done: - return (rv); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/hicn_api.h b/hicn-plugin/src/hicn_api.h deleted file mode 100644 index ec10a6bbd..000000000 --- a/hicn-plugin/src/hicn_api.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_API_H__ -#define __HICN_API_H__ - -/** - * @file - */ - - -#define HICN_STRATEGY_NULL ~0 -#define HICN_FIB_TABLE 10 - -/* define message structures */ -#define vl_typedefs -#include -#undef vl_typedefs - -#endif /* // __HICN_API_H___ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/hicn_api_test.c b/hicn-plugin/src/hicn_api_test.c deleted file mode 100644 index e4704e8ea..000000000 --- a/hicn-plugin/src/hicn_api_test.c +++ /dev/null @@ -1,1319 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 -#include -#include -#include -#include - -#define __plugin_msg_base hicn_test_main.msg_id_base -#include - -#include - -#include -#include "error.h" - - -/* Declare message IDs */ -#include "hicn_msg_enum.h" - -/* SUPPORTING FUNCTIONS NOT LOADED BY VPP_API_TEST */ -uword -unformat_ip46_address (unformat_input_t * input, va_list * args) -{ - ip46_address_t *ip46 = va_arg (*args, ip46_address_t *); - ip46_type_t type = va_arg (*args, ip46_type_t); - if ((type != IP46_TYPE_IP6) && - unformat (input, "%U", unformat_ip4_address, &ip46->ip4)) - { - ip46_address_mask_ip4 (ip46); - return 1; - } - else if ((type != IP46_TYPE_IP4) && - unformat (input, "%U", unformat_ip6_address, &ip46->ip6)) - { - return 1; - } - return 0; -} - -static ip46_type_t -ip_address_union_decode (const vl_api_address_union_t * in, - vl_api_address_family_t af, ip46_address_t * out) -{ - ip46_type_t type; - - switch (clib_net_to_host_u32 (af)) - { - case ADDRESS_IP4: - clib_memset (out, 0, sizeof (*out)); - clib_memcpy (&out->ip4, &in->ip4, sizeof (out->ip4)); - type = IP46_TYPE_IP4; - break; - case ADDRESS_IP6: - clib_memcpy (&out->ip6, &in->ip6, sizeof (out->ip6)); - type = IP46_TYPE_IP6; - break; - default: - ASSERT (!"Unkown address family in API address type"); - type = IP46_TYPE_ANY; - break; - } - - return type; -} - -void -ip6_address_encode (const ip6_address_t * in, vl_api_ip6_address_t out) -{ - clib_memcpy (out, in, sizeof (*in)); -} - -void -ip6_address_decode (const vl_api_ip6_address_t in, ip6_address_t * out) -{ - clib_memcpy (out, in, sizeof (*out)); -} - -void -ip4_address_encode (const ip4_address_t * in, vl_api_ip4_address_t out) -{ - clib_memcpy (out, in, sizeof (*in)); -} - -void -ip4_address_decode (const vl_api_ip4_address_t in, ip4_address_t * out) -{ - clib_memcpy (out, in, sizeof (*out)); -} - -static void -ip_address_union_encode (const ip46_address_t * in, - vl_api_address_family_t af, - vl_api_address_union_t * out) -{ - if (ADDRESS_IP6 == clib_net_to_host_u32 (af)) - ip6_address_encode (&in->ip6, out->ip6); - else - ip4_address_encode (&in->ip4, out->ip4); -} - -ip46_type_t -ip_address_decode (const vl_api_address_t * in, ip46_address_t * out) -{ - return (ip_address_union_decode (&in->un, in->af, out)); -} - -void -ip_address_encode (const ip46_address_t * in, ip46_type_t type, - vl_api_address_t * out) -{ - switch (type) - { - case IP46_TYPE_IP4: - out->af = clib_net_to_host_u32 (ADDRESS_IP4); - break; - case IP46_TYPE_IP6: - out->af = clib_net_to_host_u32 (ADDRESS_IP6); - break; - case IP46_TYPE_ANY: - if (ip46_address_is_ip4 (in)) - out->af = clib_net_to_host_u32 (ADDRESS_IP4); - else - out->af = clib_net_to_host_u32 (ADDRESS_IP6); - break; - } - ip_address_union_encode (in, out->af, &out->un); -} - -fib_protocol_t -fib_proto_from_ip46 (ip46_type_t iproto) -{ - switch (iproto) - { - case IP46_TYPE_IP4: - return FIB_PROTOCOL_IP4; - case IP46_TYPE_IP6: - return FIB_PROTOCOL_IP6; - case IP46_TYPE_ANY: - ASSERT (0); - return FIB_PROTOCOL_IP4; - } - - ASSERT (0); - return FIB_PROTOCOL_IP4; -} - -ip46_type_t -fib_proto_to_ip46 (fib_protocol_t fproto) -{ - switch (fproto) - { - case FIB_PROTOCOL_IP4: - return (IP46_TYPE_IP4); - case FIB_PROTOCOL_IP6: - return (IP46_TYPE_IP6); - case FIB_PROTOCOL_MPLS: - return (IP46_TYPE_ANY); - } - ASSERT (0); - return (IP46_TYPE_ANY); -} - -void -ip_prefix_decode (const vl_api_prefix_t * in, fib_prefix_t * out) -{ - switch (clib_net_to_host_u32 (in->address.af)) - { - case ADDRESS_IP4: - out->fp_proto = FIB_PROTOCOL_IP4; - break; - case ADDRESS_IP6: - out->fp_proto = FIB_PROTOCOL_IP6; - break; - } - out->fp_len = in->len; - out->___fp___pad = 0; - ip_address_decode (&in->address, &out->fp_addr); -} - -void -ip_prefix_encode (const fib_prefix_t * in, vl_api_prefix_t * out) -{ - out->len = in->fp_len; - ip_address_encode (&in->fp_addr, - fib_proto_to_ip46 (in->fp_proto), &out->address); -} - -///////////////////////////////////////////////////// - -#define HICN_FACE_NULL ~0 - -typedef struct -{ - /* API message ID base */ - u16 msg_id_base; - vat_main_t *vat_main; - u32 ping_id; -} hicn_test_main_t; - -hicn_test_main_t hicn_test_main; - -#define foreach_standard_reply_retval_handler \ -_(hicn_api_node_params_set_reply) \ -_(hicn_api_enable_disable_reply) - -#define _(n) \ - static void vl_api_##n##_t_handler \ - (vl_api_##n##_t * mp) \ - { \ - vat_main_t * vam = hicn_test_main.vat_main; \ - i32 retval = ntohl(mp->retval); \ - if (vam->async_mode) { \ - vam->async_errors += (retval < 0); \ - } else { \ - fformat (vam->ofp,"%s\n", get_error_string(retval));\ - vam->retval = retval; \ - vam->result_ready = 1; \ - } \ - } -foreach_standard_reply_retval_handler; -#undef _ - -/* - * Table of message reply handlers, must include boilerplate handlers we just - * generated - */ -#define foreach_vpe_api_reply_msg \ -_(HICN_API_NODE_PARAMS_SET_REPLY, hicn_api_node_params_set_reply) \ -_(HICN_API_NODE_PARAMS_GET_REPLY, hicn_api_node_params_get_reply) \ -_(HICN_API_NODE_STATS_GET_REPLY, hicn_api_node_stats_get_reply) \ -_(HICN_API_FACE_GET_REPLY, hicn_api_face_get_reply) \ -_(HICN_API_FACES_DETAILS, hicn_api_faces_details) \ -_(HICN_API_FACE_STATS_DETAILS, hicn_api_face_stats_details) \ -_(HICN_API_FACE_PARAMS_GET_REPLY, hicn_api_face_params_get_reply) \ -_(HICN_API_ROUTE_GET_REPLY, hicn_api_route_get_reply) \ -_(HICN_API_ROUTES_DETAILS, hicn_api_routes_details) \ -_(HICN_API_STRATEGIES_GET_REPLY, hicn_api_strategies_get_reply) \ -_(HICN_API_STRATEGY_GET_REPLY, hicn_api_strategy_get_reply) \ -_(HICN_API_ENABLE_DISABLE_REPLY, hicn_api_enable_disable_reply) \ -_(HICN_API_UDP_TUNNEL_ADD_DEL_REPLY, hicn_api_udp_tunnel_add_del_reply) - -static int -api_hicn_api_node_params_set (vat_main_t * vam) -{ - unformat_input_t *input = vam->input; - int enable_disable = 1; - int pit_size = -1, cs_size = -1; - f64 pit_max_lifetime_sec = -1.0f; - int ret; - - vl_api_hicn_api_node_params_set_t *mp; - - /* Parse args required to build the message */ - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "disable")) - { - enable_disable = 0; - } - else if (unformat (input, "PIT size %d", &pit_size)) - {; - } - else if (unformat (input, "CS size %d", &cs_size)) - {; - } - else if (unformat (input, "PIT maxlife %f", &pit_max_lifetime_sec)) - {; - } - else - { - break; - } - } - - /* Construct the API message */ - M (HICN_API_NODE_PARAMS_SET, mp); - mp->enable_disable = clib_host_to_net_u32(enable_disable); - mp->pit_max_size = clib_host_to_net_i32 (pit_size); - mp->cs_max_size = clib_host_to_net_i32 (cs_size); - mp->pit_max_lifetime_sec = pit_max_lifetime_sec; - - /* send it... */ - S (mp); - - /* Wait for a reply... */ - W (ret); - - return ret; -} - -static int -api_hicn_api_node_params_get (vat_main_t * vam) -{ - vl_api_hicn_api_node_params_get_t *mp; - int ret; - - //Construct the API message - M (HICN_API_NODE_PARAMS_GET, mp); - - /* send it... */ - S (mp); - - /* Wait for a reply... */ - W (ret); - - return ret; -} - -static void - vl_api_hicn_api_node_params_get_reply_t_handler - (vl_api_hicn_api_node_params_get_reply_t * mp) -{ - vat_main_t *vam = hicn_test_main.vat_main; - i32 retval = ntohl (mp->retval); - - if (vam->async_mode) - { - vam->async_errors += (retval < 0); - return; - } - vam->retval = retval; - vam->result_ready = 1; - - if (vam->retval < 0) - { - //vpp_api_test infra will also print out string form of error - fformat (vam->ofp, " (API call error: %d)\n", vam->retval); - return; - } - fformat (vam->ofp, - "Enabled %d\n" - " Features: cs:%d\n" - " PIT size %d\n" - " PIT lifetime dflt %.3f, min %.3f, max %.3f\n" - " CS size %d\n", - mp->is_enabled, - mp->feature_cs, - clib_net_to_host_u32 (mp->pit_max_size), - mp->pit_max_lifetime_sec, clib_net_to_host_u32 (mp->cs_max_size)); -} - -static int -api_hicn_api_node_stats_get (vat_main_t * vam) -{ - vl_api_hicn_api_node_stats_get_t *mp; - int ret; - - /* Construct the API message */ - M (HICN_API_NODE_STATS_GET, mp); - - /* send it... */ - S (mp); - - /* Wait for a reply... */ - W (ret); - - return ret; -} - -static void - vl_api_hicn_api_node_stats_get_reply_t_handler - (vl_api_hicn_api_node_stats_get_reply_t * rmp) -{ - vat_main_t *vam = hicn_test_main.vat_main; - i32 retval = ntohl (rmp->retval); - - if (vam->async_mode) - { - vam->async_errors += (retval < 0); - return; - } - vam->retval = retval; - vam->result_ready = 1; - - if (vam->retval < 0) - { - //vpp_api_test infra will also print out string form of error - fformat (vam->ofp, " (API call error: %d)\n", vam->retval); - return; - } - else - { - fformat (vam->ofp, //compare hicn_cli_show_command_fn block:should match - " PIT entries (now): %d\n" - " CS entries (now): %d\n" - " Forwarding statistics:" - " pkts_processed: %d\n" - " pkts_interest_count: %d\n" - " pkts_data_count: %d\n" - " pkts_nak_count: %d\n" - " pkts_from_cache_count: %d\n" - " pkts_nacked_interests_count: %d\n" - " pkts_nak_hoplimit_count: %d\n" - " pkts_nak_no_route_count: %d\n" - " pkts_no_pit_count: %d\n" - " pit_expired_count: %d\n" - " cs_expired_count: %d\n" - " cs_lru_count: %d\n" - " pkts_drop_no_buf: %d\n" - " interests_aggregated: %d\n" - " interests_retransmitted: %d\n", - clib_net_to_host_u64 (rmp->pit_entries_count), - clib_net_to_host_u64 (rmp->cs_entries_count), - clib_net_to_host_u64 (rmp->pkts_processed), - clib_net_to_host_u64 (rmp->pkts_interest_count), - clib_net_to_host_u64 (rmp->pkts_data_count), - clib_net_to_host_u64 (rmp->pkts_from_cache_count), - clib_net_to_host_u64 (rmp->pkts_no_pit_count), - clib_net_to_host_u64 (rmp->pit_expired_count), - clib_net_to_host_u64 (rmp->cs_expired_count), - clib_net_to_host_u64 (rmp->cs_lru_count), - clib_net_to_host_u64 (rmp->pkts_drop_no_buf), - clib_net_to_host_u64 (rmp->interests_aggregated), - clib_net_to_host_u64 (rmp->interests_retx)); - } -} - -static int -api_hicn_api_face_params_get (vat_main_t * vam) -{ - unformat_input_t *input = vam->input; - vl_api_hicn_api_face_params_get_t *mp; - u32 faceid = HICN_FACE_NULL, ret; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "face %d", &faceid)) - {; - } - else - { - break; - } - } - - //Check for presence of face ID - if (faceid == HICN_FACE_NULL) - { - clib_warning ("Please specify face ID"); - return 1; - } - //Construct the API message - M (HICN_API_FACE_PARAMS_GET, mp); - mp->faceid = clib_host_to_net_u32 (faceid); - - //send it... - S (mp); - - //Wait for a reply... - W (ret); - - return ret; -} - -static void - vl_api_hicn_api_face_params_get_reply_t_handler - (vl_api_hicn_api_face_params_get_reply_t * rmp) -{ - vat_main_t *vam = hicn_test_main.vat_main; - i32 retval = ntohl (rmp->retval); - u8 *sbuf = 0; - ip46_address_t nat_addr; - - if (vam->async_mode) - { - vam->async_errors += (retval < 0); - return; - } - vam->retval = retval; - vam->result_ready = 1; - - if (vam->retval < 0) - { - //vpp_api_test infra will also print out string form of error - fformat (vam->ofp, " (API call error: %d)\n", vam->retval); - return; - } - vec_reset_length (sbuf); - ip_address_decode (&rmp->nat_addr, &nat_addr); - sbuf = - format (0, "nat_addr %U", format_ip46_address, - &nat_addr, 0 /*IP46_ANY_TYPE */); - - fformat (vam->ofp, "%s swif %d flags %d\n", - sbuf, - clib_net_to_host_u32 (rmp->swif), - clib_net_to_host_i32 (rmp->flags)); -} - -static void -format_face (vl_api_hicn_face_t * rmp) -{ - vat_main_t *vam = hicn_test_main.vat_main; - u8 *sbuf = 0; - ip46_address_t nat_addr; - ip46_address_t local_addr; - - vec_reset_length (sbuf); - ip_address_decode (&rmp->nat_addr, &nat_addr); - - sbuf = - format (0, "nat_addr %U", format_ip46_address, - &local_addr, 0 /*IP46_ANY_TYPE */); - - fformat (vam->ofp, "%s swif %d flags %d name %s\n", - sbuf, - clib_net_to_host_u32 (rmp->swif), - clib_net_to_host_i32 (rmp->flags), rmp->if_name); -} - -static int -api_hicn_api_faces_dump (vat_main_t * vam) -{ - hicn_test_main_t *hm = &hicn_test_main; - vl_api_hicn_api_faces_dump_t *mp; - vl_api_control_ping_t *mp_ping; - int ret; - - if (vam->json_output) - { - clib_warning ("JSON output not supported for faces_dump"); - return -99; - } - - M (HICN_API_FACES_DUMP, mp); - S (mp); - - if (!hm->ping_id) - hm->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC)); - - /* Use a control ping for synchronization */ - mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping)); - mp_ping->_vl_msg_id = htons (hm->ping_id); - mp_ping->client_index = vam->my_client_index; - - fformat (vam->ofp, "Sending ping id=%d\n", hm->ping_id); - - vam->result_ready = 0; - S (mp_ping); - - W (ret); - return ret; -} - -static void - vl_api_hicn_api_faces_details_t_handler - (vl_api_hicn_api_faces_details_t * mp) -{ - format_face (&(mp->face)); -} - -static int -api_hicn_api_face_get (vat_main_t * vam) -{ - unformat_input_t *input = vam->input; - vl_api_hicn_api_face_get_t *mp; - u32 faceid = HICN_FACE_NULL, ret; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "face %d", &faceid)) - {; - } - else - { - break; - } - } - - //Check for presence of face ID - if (faceid == HICN_FACE_NULL) - { - clib_warning ("Please specify face ID"); - return 1; - } - //Construct the API message - M (HICN_API_FACE_GET, mp); - mp->faceid = clib_host_to_net_u32 (faceid); - - //send it... - S (mp); - - //Wait for a reply... - W (ret); - - return ret; -} - - -static void - vl_api_hicn_api_face_get_reply_t_handler - (vl_api_hicn_api_face_get_reply_t * rmp) -{ - - vat_main_t *vam = hicn_test_main.vat_main; - i32 retval = ntohl (rmp->retval); - - if (vam->async_mode) - { - vam->async_errors += (retval < 0); - return; - } - vam->retval = retval; - vam->result_ready = 1; - - if (vam->retval < 0) - { - //vpp_api_test infra will also print out string form of error - fformat (vam->ofp, " (API call error: %d)\n", vam->retval); - return; - } - format_face (&(rmp->face)); -} - - - -static int -api_hicn_api_face_stats_dump (vat_main_t * vam) -{ - hicn_test_main_t *hm = &hicn_test_main; - vl_api_hicn_api_face_stats_dump_t *mp; - vl_api_control_ping_t *mp_ping; - int ret; - - if (vam->json_output) - { - clib_warning ("JSON output not supported for memif_dump"); - return -99; - } - - M (HICN_API_FACE_STATS_DUMP, mp); - S (mp); - - if (!hm->ping_id) - hm->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC)); - - /* Use a control ping for synchronization */ - mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping)); - mp_ping->_vl_msg_id = htons (hm->ping_id); - mp_ping->client_index = vam->my_client_index; - - fformat (vam->ofp, "Sending ping id=%d\n", hm->ping_id); - - vam->result_ready = 0; - S (mp_ping); - - W (ret); - return ret; -} - -/* face_stats-details message handler */ -static void - vl_api_hicn_api_face_stats_details_t_handler - (vl_api_hicn_api_face_stats_details_t * mp) -{ - vat_main_t *vam = hicn_test_main.vat_main; - - fformat (vam->ofp, "face id %d\n" - " interest rx packets %16Ld\n" - " bytes %16Ld\n" - " interest tx packets %16Ld\n" - " bytes %16Ld\n" - " data rx packets %16Ld\n" - " bytes %16Ld\n" - " data tx packets %16Ld\n" - " bytes %16Ld\n", - clib_host_to_net_u32 (mp->faceid), - clib_host_to_net_u64 (mp->irx_packets), - clib_host_to_net_u64 (mp->irx_bytes), - clib_host_to_net_u64 (mp->itx_packets), - clib_host_to_net_u64 (mp->itx_bytes), - clib_host_to_net_u64 (mp->drx_packets), - clib_host_to_net_u64 (mp->drx_bytes), - clib_host_to_net_u64 (mp->dtx_packets), - clib_host_to_net_u64 (mp->dtx_bytes)); -} - -static int -api_hicn_api_route_get (vat_main_t * vam) -{ - unformat_input_t *input = vam->input; - - vl_api_hicn_api_route_get_t *mp; - fib_prefix_t prefix; - int ret; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "prefix %U/%d", unformat_ip46_address, - &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) - {; - } - else - { - break; - } - } - - /* Check parse */ - if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) - || (prefix.fp_len == 0)) - { - clib_warning ("Please specify a valid prefix..."); - return 1; - } - //Construct the API message - M (HICN_API_ROUTE_GET, mp); - if (!ip46_address_is_ip4 (&(prefix.fp_addr))) - prefix.fp_proto = fib_proto_from_ip46 (IP46_TYPE_IP6); - ip_prefix_encode (&prefix, &mp->prefix); - - //send it... - S (mp); - - //Wait for a reply... - W (ret); - - return ret; -} - -static int -api_hicn_api_routes_dump (vat_main_t * vam) -{ - - hicn_test_main_t *hm = &hicn_test_main; - vl_api_hicn_api_route_get_t *mp; - vl_api_control_ping_t *mp_ping; - int ret; - - if (vam->json_output) - { - clib_warning ("JSON output not supported for routes_dump"); - return -99; - } - - M (HICN_API_ROUTES_DUMP, mp); - S (mp); - - if (!hm->ping_id) - hm->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC)); - - /* Use a control ping for synchronization */ - mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping)); - mp_ping->_vl_msg_id = htons (hm->ping_id); - mp_ping->client_index = vam->my_client_index; - - fformat (vam->ofp, "Sending ping id=%d\n", hm->ping_id); - - vam->result_ready = 0; - S (mp_ping); - - W (ret); - return ret; -} - -static void -vl_api_hicn_api_route_get_reply_t_handler (vl_api_hicn_api_route_get_reply_t * - rmp) -{ - vat_main_t *vam = hicn_test_main.vat_main; - i32 retval = ntohl (rmp->retval); - u8 *sbuf = 0; - - if (vam->async_mode) - { - vam->async_errors += (retval < 0); - return; - } - vam->retval = retval; - vam->result_ready = 1; - - if (vam->retval < 0) - { - //vpp_api_test infra will also print out string form of error - fformat (vam->ofp, " (API call error: %d)\n", vam->retval); - return; - } - int i = 0; - u8 null_face = 0; - u32 faceid; - - vec_reset_length (sbuf); - sbuf = format (sbuf, "Faces: \n"); - while (i < 1000 && !null_face) - { - faceid = clib_net_to_host_u32 (rmp->faceids[i]); - if (faceid != HICN_FACE_NULL) - { - sbuf = - format (sbuf, "faceid %d", - clib_net_to_host_u32 (rmp->faceids[i])); - i++; - } - else - { - null_face = 1; - } - } - - fformat (vam->ofp, "%s\n Strategy: %d\n", - sbuf, clib_net_to_host_u32 (rmp->strategy_id)); -} - -/* face_stats-details message handler */ -static void - vl_api_hicn_api_routes_details_t_handler - (vl_api_hicn_api_routes_details_t * mp) -{ - vat_main_t *vam = hicn_test_main.vat_main; - fib_prefix_t prefix; - u32 faceid; - u8 *sbuf = 0; - vec_reset_length (sbuf); - - ip_prefix_decode (&mp->prefix, &prefix); - sbuf = - format (sbuf, "Prefix: %U/%u\n", format_ip46_address, &prefix.fp_addr, 0, - prefix.fp_len); - - sbuf = format (sbuf, "Faces: \n"); - for (int i = 0; i < mp->nfaces; i++) - { - faceid = clib_net_to_host_u32 (mp->faceids[i]); - sbuf = format (sbuf, " faceid %d\n", faceid); - } - - fformat (vam->ofp, "%sStrategy: %d\n", - sbuf, clib_net_to_host_u32 (mp->strategy_id)); -} - -static int -api_hicn_api_strategies_get (vat_main_t * vam) -{ - vl_api_hicn_api_strategies_get_t *mp; - int ret; - - //TODO - /* Construct the API message */ - M (HICN_API_STRATEGIES_GET, mp); - - /* send it... */ - S (mp); - - /* Wait for a reply... */ - W (ret); - - return ret; -} - -static void - vl_api_hicn_api_strategies_get_reply_t_handler - (vl_api_hicn_api_strategies_get_reply_t * mp) -{ - vat_main_t *vam = hicn_test_main.vat_main; - i32 retval = ntohl (mp->retval); - u8 *sbuf = 0; - - if (vam->async_mode) - { - vam->async_errors += (retval < 0); - return; - } - vam->retval = retval; - vam->result_ready = 1; - - if (vam->retval < 0) - { - //vpp_api_test infra will also print out string form of error - fformat (vam->ofp, " (API call error: %d)\n", vam->retval); - return; - } - int n_strategies = clib_net_to_host_i32 (mp->n_strategies); - - vec_reset_length (sbuf); - sbuf = format (sbuf, "Available strategies:\n"); - - int i; - for (i = 0; i < n_strategies; i++) - { - u32 strategy_id = clib_net_to_host_u32 (mp->strategy_id[i]); - sbuf = format (sbuf, "%d ", strategy_id); - } - fformat (vam->ofp, "%s", sbuf); -} - -static int -api_hicn_api_strategy_get (vat_main_t * vam) -{ - unformat_input_t *input = vam->input; - vl_api_hicn_api_strategy_get_t *mp; - int ret; - - u32 strategy_id = HICN_STRATEGY_NULL; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "strategy %d", strategy_id)) - {; - } - else - { - break; - } - } - - if (strategy_id == HICN_STRATEGY_NULL) - { - clib_warning ("Please specify strategy id..."); - return 1; - } - - /* Construct the API message */ - M (HICN_API_STRATEGY_GET, mp); - mp->strategy_id = clib_host_to_net_u32 (strategy_id); - - /* send it... */ - S (mp); - - /* Wait for a reply... */ - W (ret); - - return ret; -} - -static void - vl_api_hicn_api_strategy_get_reply_t_handler - (vl_api_hicn_api_strategy_get_reply_t * mp) -{ - vat_main_t *vam = hicn_test_main.vat_main; - i32 retval = ntohl (mp->retval); - - if (vam->async_mode) - { - vam->async_errors += (retval < 0); - return; - } - vam->retval = retval; - vam->result_ready = 1; - - if (vam->retval < 0) - { - //vpp_api_test infra will also print out string form of error - fformat (vam->ofp, " (API call error: %d)\n", vam->retval); - return; - } - fformat (vam->ofp, "%s", mp->description); -} - -static int -api_hicn_api_enable_disable (vat_main_t * vam) -{ - unformat_input_t *input = vam->input; - vl_api_hicn_api_enable_disable_t *mp; - int ret; - - fib_prefix_t prefix; - vl_api_hicn_action_type_t en_dis = HICN_ENABLE; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "prefix %U/%d", unformat_ip46_address, - &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) - {; - } - else if (unformat (input, "disable")) - {; - en_dis = HICN_DISABLE; - } - else - { - break; - } - } - - /* Check parse */ - if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) - || (prefix.fp_len == 0)) - { - clib_warning ("Please specify a valid prefix..."); - return 1; - } - - prefix.fp_proto = ip46_address_is_ip4 (&(prefix.fp_addr)) ? FIB_PROTOCOL_IP4 : - FIB_PROTOCOL_IP6; - - //Construct the API message - M (HICN_API_ENABLE_DISABLE, mp); - - ip_prefix_encode (&prefix, &mp->prefix); - mp->enable_disable = en_dis; - - //send it... - S (mp); - - //Wait for a reply... - W (ret); - - return ret; -} - -static int -api_hicn_api_register_prod_app (vat_main_t * vam) -{ - unformat_input_t *input = vam->input; - vl_api_hicn_api_register_prod_app_t *mp; - fib_prefix_t prefix; - u32 swif = ~0; - int ret; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "prefix %U/%d", unformat_ip46_address, - &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) - {; - } - else if (unformat (input, "id %d", &swif)) - {; - } - else - { - break; - } - } - - /* Check parse */ - if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) - || (prefix.fp_len == 0)) - { - clib_warning ("Please specify prefix..."); - return 1; - } - - prefix.fp_proto = - ip46_address_is_ip4 (&(prefix.fp_addr)) ? FIB_PROTOCOL_IP4 : - FIB_PROTOCOL_IP6; - /* Construct the API message */ - M (HICN_API_REGISTER_PROD_APP, mp); - ip_prefix_encode (&prefix, &mp->prefix); - - mp->swif = clib_host_to_net_u32 (swif); - - /* send it... */ - S (mp); - - /* Wait for a reply... */ - W (ret); - - return ret; -} - -static void - vl_api_hicn_api_register_prod_app_reply_t_handler - (vl_api_hicn_api_register_prod_app_reply_t * mp) -{ - vat_main_t *vam = hicn_test_main.vat_main; - i32 retval = ntohl (mp->retval); - - if (vam->async_mode) - { - vam->async_errors += (retval < 0); - return; - } - vam->retval = retval; - vam->result_ready = 1; - - if (vam->retval < 0) - { - //vpp_api_test infra will also print out string form of error - fformat (vam->ofp, " (API call error: %d)\n", vam->retval); - return; - } -} - -static int -api_hicn_api_face_prod_del (vat_main_t * vam) -{ - unformat_input_t *input = vam->input; - vl_api_hicn_api_face_prod_del_t *mp; - u32 faceid = 0, ret; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "face %d", &faceid)) - {; - } - else - { - break; - } - } - - //Check for presence of face ID - if (faceid == ~0) - { - clib_warning ("Please specify face ID"); - return 1; - } - //Construct the API message - M (HICN_API_FACE_PROD_DEL, mp); - mp->faceid = clib_host_to_net_u32 (faceid); - - //send it... - S (mp); - - //Wait for a reply... - W (ret); - - return ret; -} - -static int -api_hicn_api_register_cons_app (vat_main_t * vam) -{ - vl_api_hicn_api_register_cons_app_t *mp; - int ret; - - /* Construct the API message */ - M (HICN_API_REGISTER_CONS_APP, mp); - - /* send it... */ - S (mp); - - /* Wait for a reply... */ - W (ret); - - return ret; -} - -static int -api_hicn_api_face_cons_del (vat_main_t * vam) -{ - unformat_input_t *input = vam->input; - vl_api_hicn_api_face_cons_del_t *mp; - u32 faceid = 0, ret; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "face %d", &faceid)) - {; - } - else - { - break; - } - } - - //Check for presence of face ID - if (faceid == ~0) - { - clib_warning ("Please specify face ID"); - return 1; - } - //Construct the API message - M (HICN_API_FACE_CONS_DEL, mp); - mp->faceid = clib_host_to_net_u32 (faceid); - - //send it... - S (mp); - - //Wait for a reply... - W (ret); - - return ret; -} - -static void - vl_api_hicn_api_register_cons_app_reply_t_handler - (vl_api_hicn_api_register_cons_app_reply_t * mp) -{ - vat_main_t *vam = hicn_test_main.vat_main; - i32 retval = ntohl (mp->retval); - - if (vam->async_mode) - { - vam->async_errors += (retval < 0); - return; - } - vam->retval = retval; - vam->result_ready = 1; - - if (vam->retval < 0) - { - //vpp_api_test infra will also print out string form of error - fformat (vam->ofp, " (API call error: %d)\n", vam->retval); - return; - } - ip46_address_t src_addr4 = ip46_address_initializer; - ip46_address_t src_addr6 = ip46_address_initializer; - ip_address_decode (&mp->src_addr4, &src_addr4); - ip_address_decode (&mp->src_addr6, &src_addr6); - - fformat (vam->ofp, - "ip4 address %U\n" - "ip6 address :%U\n", - format_ip46_address, IP46_TYPE_ANY, &src_addr4, - format_ip46_address, IP46_TYPE_ANY, &src_addr6); -} - -static int -api_hicn_api_udp_tunnel_add_del (vat_main_t * vam) -{ - unformat_input_t *input = vam->input; - vl_api_hicn_api_udp_tunnel_add_del_t *mp; - - ip46_address_t src_ip, dst_ip; - u32 src_port, dst_port; - fib_protocol_t fproto; - u8 is_del; - int ret; - - is_del = 0; - fproto = FIB_PROTOCOL_MAX; - - /* Get a line of input. */ - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "add")) - is_del = 0; - else if (unformat (input, "del")) - is_del = 1; - else if (unformat (input, "%U %U", - unformat_ip4_address, - &src_ip.ip4, unformat_ip4_address, &dst_ip.ip4)) - fproto = FIB_PROTOCOL_IP4; - else if (unformat (input, "%U %U", - unformat_ip6_address, - &src_ip.ip6, unformat_ip6_address, &dst_ip.ip6)) - fproto = FIB_PROTOCOL_IP6; - else if (unformat (input, "%d %d", &src_port, &dst_port)) - ; - else - { - break; - } - } - - - if (fproto == FIB_PROTOCOL_MAX) - { - clib_warning ("Please specify face ID"); - return 1; - } - - /* Construct the API message */ - M (HICN_API_UDP_TUNNEL_ADD_DEL, mp); - ip_address_encode (&src_ip, fproto == FIB_PROTOCOL_IP4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6 ,&mp->src_addr); - ip_address_encode (&dst_ip, fproto == FIB_PROTOCOL_IP4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6 ,&mp->dst_addr); - mp->src_port = clib_host_to_net_u16(src_port); - mp->dst_port = clib_host_to_net_u16(dst_port); - mp->is_add = !is_del; - - /* send it... */ - S (mp); - - /* Wait for a reply... */ - W (ret); - - return ret; -} - -static void -vl_api_hicn_api_udp_tunnel_add_del_reply_t_handler -(vl_api_hicn_api_udp_tunnel_add_del_reply_t * mp) -{ - vat_main_t *vam = hicn_test_main.vat_main; - i32 retval = ntohl (mp->retval); - - if (vam->async_mode) - { - vam->async_errors += (retval < 0); - return; - } - vam->retval = retval; - vam->result_ready = 1; - - if (vam->retval < 0) - { - //vpp_api_test infra will also print out string form of error - fformat (vam->ofp, " (API call error: %d)\n", vam->retval); - return; - } - - index_t uei = clib_net_to_host_u32(mp->uei); - - fformat (vam->ofp, - "udp-encap %d\n", - uei); -} - - - -#include - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/hicn_buffer.h b/hicn-plugin/src/hicn_buffer.h new file mode 100644 index 000000000..3eb2a0530 --- /dev/null +++ b/hicn-plugin/src/hicn_buffer.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2017-2019 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_H__ +#define __HICN_BUFFER_H__ + +#define ip_address_t hicn_ip_address_t +#define ip_address_cmp hicn_ip_address_cmp +#define ip_prefix_t hicn_ip_prefix_t +#define ip_prefix_cmp hicn_ip_prefix_cmp +#undef ip_prefix_len +#define ip_prefix_len hicn_ip_prefix_len +#include +#undef ip_address_t +#undef ip_address_cmp +#undef ip_prefix_t +#undef ip_prefix_cmp +#undef ip_prefix_len +#define ip_prefix_len(_a) (_a)->len + +#include +#include +#include +#include +#include +#include + +/** + * @file + */ + +/* Helper for avoiding warnings about type-punning */ +#define UNION_CAST(x, destType) \ + (((union {__typeof__(x) a; destType b;})x).b) + +/* + * Update CMakeLists.txt as we have to manually replace the type for + * vppapigen + */ +typedef u8 weight_t; +typedef index_t hicn_face_id_t; + +#define ISV6(isv6, dov6, dov4) isv6 ? dov6 : dov4 +#define HICN_IS_NAMEHASH_CACHED(b) (((u64)(b->opaque2)[0] != 0) || ((u64)(b->opaque2)[1] != 0)) + +#ifndef VLIB_BUFFER_MIN_CHAIN_SEG_SIZE +#define VLIB_BUFFER_MIN_CHAIN_SEG_SIZE (128) +#endif + +#define HICN_BUFFER_FLAGS_DEFAULT 0x0 +/* vlib_buffer cloning utilities impose that current_lentgh is more that 2*CLIB_CACHE_LINE_BYTES. */ +#define foreach_hicn_buffer_flags \ + _(FACE_IS_APP, "Packet belong to application face") \ + _(PKT_LESS_TWO_CL, "Packets lenght is less that 2 * CLIB_CACHE_LINE_BYTES.") \ + _(IS_INTEREST, "Packet is interest") \ + _(FLUSH, "Packet must be flush to next node. Used by host stack") \ + _(IS_IP4, "Packet is IP4") \ + _(FROM_UDP4_TUNNEL, "Interest comes from UDP4 tunnel") \ + _(FROM_UDP6_TUNNEL, "Interest comes from UDP6 tunnel") \ + +typedef enum _hicn_buffer_options +{ +#define _(sym, str) HICN_BUFFER_##sym, + foreach_hicn_buffer_flags +#undef _ +} hicn_buffer_options_t; + +typedef enum _hicn_buffer_flags +{ +#define _(sym, str) HICN_BUFFER_FLAGS_##sym = 1 << HICN_BUFFER_##sym, + foreach_hicn_buffer_flags +#undef _ +} hicn_buffer_flags_t; + +/* The following is stored in the opaque2 field in the vlib_buffer_t */ +typedef struct +{ + /* hash of the name */ + u64 name_hash; + + /* ids to prefetch a PIT/CS entry */ + u32 node_id; + u32 bucket_id; + u8 hash_entry_id; + u8 hash_bucket_flags; + + u8 flags; + u8 dpo_ctx_id; /* used for data path */ + u8 vft_id; /* " */ + + hicn_face_id_t face_id; /* ingress iface, sizeof(u32) */ + u32 in_faces_vec_id; /* vector of possible input face for a data packet */ + + u32 ctx_index; /* Host stack context index */ + u32 seq_number; /* Reassembly information */ + + hicn_type_t type; +} hicn_buffer_t; + +STATIC_ASSERT (sizeof (hicn_buffer_t) <= + STRUCT_SIZE_OF (vlib_buffer_t, opaque2), + "hICN buffer opaque2 meta-data too large for vlib_buffer"); + + +always_inline hicn_buffer_t * +hicn_get_buffer (vlib_buffer_t * b0) +{ + return (hicn_buffer_t *) & (b0->opaque2[0]); +} + +always_inline u8 +hicn_is_v6 (hicn_header_t * pkt_hdr) +{ + return ((pkt_hdr->v4.ip.version_ihl >> 4) != 4); +} + +#endif /* __HICN_BUFFER_H__ */ + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/hicn_msg_enum.h b/hicn-plugin/src/hicn_msg_enum.h deleted file mode 100644 index fcf2a1e87..000000000 --- a/hicn-plugin/src/hicn_msg_enum.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2017-2019 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_MSG_ENUM_H__ -#define __HICN_MSG_ENUM_H__ - -#include - -/** - * @file - */ -#define vl_msg_id(n, h) n, -typedef enum -{ -#include - /* We'll want to know how many messages IDs we need... */ - VL_MSG_FIRST_AVAILABLE, -} vl_msg_id_t; -#undef vl_msg_id - -#endif /* __HICN_MSG_ENUM_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/hicn_plugin.c b/hicn-plugin/src/hicn_plugin.c new file mode 100644 index 000000000..5f28f0123 --- /dev/null +++ b/hicn-plugin/src/hicn_plugin.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017-2019 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 "network/hicn.h" +#include "network/params.h" +#include "network/infra.h" +#include "network/strategy_dpo_manager.h" +#include "network/mgmt.h" +#include "network/faces/app/address_mgr.h" +#include "network/face_db.h" +#include "network/udp_tunnels/udp_tunnel.h" +#include "network/route.h" +#include "host_stack/host_stack.h" + +/* + * Init entry-point for the icn plugin + */ +static clib_error_t * +hicn_init(vlib_main_t *vm) +{ + clib_error_t *error = 0; + + hicn_main_t *sm = &hicn_main; + + /* Init other elements in the 'main' struct */ + sm->is_enabled = 0; + + error = hicn_api_plugin_hookup(vm); + + /* Init the dpo module */ + hicn_dpos_init(); + + /* Init the app manager */ + address_mgr_init(); + + hicn_face_module_init(vm); + + /* Init the route module */ + hicn_route_init(); + + udp_tunnel_init(); + + /* Init the host stack module */ + hicn_hs_init(vm); + + return error; +} + +VLIB_INIT_FUNCTION(hicn_init); + +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER() = + { + .description = "hICN network/transport/session plugin"}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/host_stack/FEATURE.yaml b/hicn-plugin/src/host_stack/FEATURE.yaml new file mode 100644 index 000000000..580af2723 --- /dev/null +++ b/hicn-plugin/src/host_stack/FEATURE.yaml @@ -0,0 +1,9 @@ +--- +name: Hicn host stack +maintainer: Mauro Sardara +features: + - Hicn host stack integration via session layer +description: "IETF QUIC Protocol implementation" +state: experimental +properties: [API, CLI, STATS, MULTITHREAD] + diff --git a/hicn-plugin/src/host_stack/README.md b/hicn-plugin/src/host_stack/README.md new file mode 100644 index 000000000..04166336a --- /dev/null +++ b/hicn-plugin/src/host_stack/README.md @@ -0,0 +1,2 @@ +# host-stack-plugin +HICN transport plugin for VPP diff --git a/hicn-plugin/src/host_stack/cbr_proto.c b/hicn-plugin/src/host_stack/cbr_proto.c new file mode 100644 index 000000000..54a851d41 --- /dev/null +++ b/hicn-plugin/src/host_stack/cbr_proto.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2020 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 "host_stack.h" +#include "inlines.h" + +#include + +#define WINDOW_SIZE 200 + +typedef struct hicn_hs_cbr_proto_data_ +{ + u64 next_seq_number; + u16 window_size; + u16 in_flight_interests; +} hicn_hs_cbr_proto_data_t; + +#define proto_data(ctx) ((hicn_hs_cbr_proto_data_t *)(ctx->hs_proto_data)) + +static void +reset_protocol(hicn_hs_cbr_proto_data_t *proto_data) +{ + proto_data->in_flight_interests = 0; + proto_data->window_size = WINDOW_SIZE; + proto_data->next_seq_number = 0; + + TransportAlgorithm *t = transportAlgorithm_CreateRaaqm(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + proto_data->next_seq_number = (u64)t; +} + +static void +schedule_next_interests(hicn_hs_ctx_t *ctx) +{ + hicn_hs_cbr_proto_data_t *data = proto_data(ctx); + u32 scheduled_interests = 0; + + if (data->in_flight_interests < data->window_size) + scheduled_interests = hicn_hs_send_interests(ctx, data->next_seq_number, + data->window_size - data->in_flight_interests); + + data->in_flight_interests += scheduled_interests; + data->next_seq_number += scheduled_interests; +} + +u32 cbr_proto_init(hicn_hs_ctx_t *ctx) +{ + if (ctx->running) + return -1; + + hicn_hs_cbr_proto_data_t *data = proto_data(ctx); + + reset_protocol(data); + schedule_next_interests(ctx); + ctx->running = 1; + + return 0; +} + +u32 cbr_proto_on_data(hicn_hs_ctx_t *ctx, u16 n_data) +{ + hicn_hs_cbr_proto_data_t *data = proto_data(ctx); + data->in_flight_interests -= n_data; + schedule_next_interests(ctx); + return 0; +} + +u32 cbr_proto_on_interest(hicn_hs_ctx_t *ctx) +{ + return 0; +} + +u32 cbr_proto_interest_timeout(hicn_hs_ctx_t *ctx) +{ + return 0; +} + +u32 cbr_proto_event(hicn_hs_ctx_t *ctx, hicn_hs_proto_event_t event) +{ + return 0; +} + +hicn_hs_proto_t cbr_proto = { + .init = cbr_proto_init, + .rcv_data = cbr_proto_on_data, + .rcv_interest = cbr_proto_on_interest, + .on_interest_timeout = cbr_proto_interest_timeout, + .event = cbr_proto_event, + .options = { + .is_stream = 1}}; \ No newline at end of file diff --git a/hicn-plugin/src/host_stack/cli.c b/hicn-plugin/src/host_stack/cli.c new file mode 100644 index 000000000..e569d83f1 --- /dev/null +++ b/hicn-plugin/src/host_stack/cli.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2017-2019 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 "host_stack.h" +#include "route.h" + +#include + +static clib_error_t * +hicn_hs_enable_disable_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + u8 is_en = 1; + clib_error_t *error; + + session_cli_return_if_not_enabled (); + + if (!unformat_user (input, unformat_line_input, line_input)) + return clib_error_return (0, "expected enable | disable"); + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "enable")) + is_en = 1; + else if (unformat (line_input, "disable")) + is_en = 0; + else + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + unformat_free (line_input); + return error; + } + } + + unformat_free (line_input); + return hicn_hs_enable_disable (vm, is_en); +} + +static clib_error_t * +hicn_hs_set_local_prefix_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = 0; + fib_prefix_t prefix; + + if (!unformat_user (input, unformat_line_input, line_input)) + return clib_error_return (0, "expected ip_address/prefix_len"); + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%U/%d", unformat_ip46_address, + &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) + { + prefix.fp_proto = ip46_address_is_ip4(&prefix.fp_addr) ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; + error = hicn_hs_set_local_prefix(&prefix); + } + else + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + } + } + + unformat_free (line_input); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (hicn_hs_onoff, static) = +{ + .path = "hicn hs", + .short_help = "hicn hs [enable|disable]", + .function = hicn_hs_enable_disable_fn, +}; + +VLIB_CLI_COMMAND(hicn_hs_set_local_pfx, static) = +{ + .path = "hicn hs set local prefix", + .short_help = "hicn hs set local prefix ", + .function = hicn_hs_set_local_prefix_fn, +}; +/* *INDENT-ON* */ \ No newline at end of file diff --git a/hicn-plugin/src/host_stack/debug.h b/hicn-plugin/src/host_stack/debug.h new file mode 100644 index 000000000..e69de29bb diff --git a/hicn-plugin/src/host_stack/error.c b/hicn-plugin/src/host_stack/error.c new file mode 100644 index 000000000..fa802b553 --- /dev/null +++ b/hicn-plugin/src/host_stack/error.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019 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 "error.h" + +u8 * +quic_format_err (u8 * s, va_list * args) +{ + u64 code = va_arg (*args, u64); + switch (code) + { + case 0: + s = format (s, "no error"); + break; + default: + s = format (s, "unknown error 0x%lx", code); + break; + } + return s; +} diff --git a/hicn-plugin/src/host_stack/error.h b/hicn-plugin/src/host_stack/error.h new file mode 100644 index 000000000..76c6ff986 --- /dev/null +++ b/hicn-plugin/src/host_stack/error.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020 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 __included_hs_hicn_error_h__ +#define __included_hs_hicn_error_h__ + +#include + +#include + +u8 *hicn_hs_format_err (u8 *s, va_list *args); + +#endif /* __included_hs_hicn_error_h__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/host_stack/errors/hicn_hs.def b/hicn-plugin/src/host_stack/errors/hicn_hs.def new file mode 100644 index 000000000..11474b5d9 --- /dev/null +++ b/hicn-plugin/src/host_stack/errors/hicn_hs.def @@ -0,0 +1,32 @@ +/* + * hicn_hs_input_node_error.def: Errors in hicn_hs input node + * + * Copyright (c) 2013-2019 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. + */ + +hicn_hs_error (NONE, "no error") +hicn_hs_error (ROUTE_NOT_FOUND, "no route found for given prefix") +hicn_hs_error (ROUTE_DPO_NO_HICN, "DPO for route is not hicn dpo") +hicn_hs_error (ROUTE_NO_LB_DPO, "DPO is not load balance") +hicn_hs_error (ROUTE_NO_INSERT, "Route not inserted in FIB.") +hicn_hs_error (NO_CONTEXT, "No context found for received packet") +hicn_hs_error (PACKETS_SENT, "Packets sent") +hicn_hs_error (NO_HICN, "Packet is not hicn") +hicn_hs_error (DISPATCH, "Not possible to dispatch hicn packet") +hicn_hs_error (WRONG_THREAD, "Context not found in current worker data.") +hicn_hs_error (ENQUEUED, "Error enqueueing data to application.") +hicn_hs_error (FORMAT, "Error parsing packet.") +hicn_hs_error (FIFO_FULL, "Error FIFO full.") +hicn_hs_error (ENQUEUED_OOO, "Enqueued OOO datas.") +hicn_hs_error (PARTIALLY_ENQUEUED, "Partially enqueued, probably because of full fifo.") diff --git a/hicn-plugin/src/host_stack/host_stack.c b/hicn-plugin/src/host_stack/host_stack.c new file mode 100644 index 000000000..a8c27b8d0 --- /dev/null +++ b/hicn-plugin/src/host_stack/host_stack.c @@ -0,0 +1,517 @@ +/* + * Copyright (c) 2019 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 + +#include "error.h" +#include "host_stack.h" +#include "inlines.h" + +#include "utils.h" +#include "route.h" + +#define _IPV6 0 + +char *hicn_hs_error_strings[] = { +#define hicn_hs_error(n,s) s, +#include "errors/hicn_hs.def" +#undef hicn_hs_error +}; + +// Main hicn struct +hicn_hs_main_t hicn_hs_main; + +/** + * Initiate the connection to rmt, which is actually a content. + * Send first interest and program rtx. + */ +int +hicn_hs_connect (transport_endpoint_cfg_t * rmt) +{ + hicn_hs_main_t *hmm = hicn_hs_get_main (); + vlib_main_t *vm = vlib_get_main (); + u32 thread_index = vm->thread_index; + int rv; + session_endpoint_cfg_t *sep; + hicn_hs_ctx_t *hc; + app_worker_t *app_wrk; + session_handle_t sh; + session_t *s; + u32 hc_index; + char name[128]; + + hicn_ip_prefix_t ip_address; + hicn_name_t *cons_name; + + CLIB_UNUSED (u32 node_index); + + /* We don't poll main thread if we have workers */ + if (vlib_num_workers ()) + thread_index = 1; + + sep = (session_endpoint_cfg_t *)(rmt); + + /* XXX Here we alloc a new ctx. Not clear yet how to trigger the consumer protocol + from the session layer. TBD */ + hc_index = hicn_hs_ctx_alloc (thread_index); + hc = hicn_hs_get_ctx_by_index(hc_index, thread_index); + + ip_copy (&hc->connection.rmt_ip, &rmt->ip, rmt->is_ip4); + ip_copy ((ip46_address_t*)(&ip_address.address), &rmt->ip, rmt->is_ip4); + ip_address.family = rmt->is_ip4 ? AF_INET : AF_INET6; + ip_address.len = 128; + cons_name = hicn_hs_ctx_get_consumer_name(hc); + + hicn_name_create_from_ip_prefix(&ip_address, 0, cons_name); + hicn_name_ntop(cons_name, name, 128); + HICN_HS_DBG(1, "Set name %s through hicn connect()", name); + + hc->c_rmt_port = rmt->port; + hc->c_is_ip4 = sep->is_ip4; + hc->c_proto = hmm->transport_protocol_id; + /* + FixMe: Hardcoded fib index! + */ + hc->c_fib_index = fib_table_find(hc->c_is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6, 10); + hc->parent_app_wrk_id = sep->app_wrk_index; + hc->c_s_index = HICN_HS_SESSION_INVALID; + hc->c_c_index = hc_index; + hc->c_flags |= TRANSPORT_CONNECTION_F_CLESS; + hc->client_opaque = sep->opaque; + + /* XXX Hardcoded CBR protocol for the moment */ + hc->hs_proto = &cbr_proto; + hc->running = 0; + hc->accepted = 0; + hc->mss = hicn_hs_default_mtu (hmm, hc->c_is_ip4); + hc->current_content_size = 0; + hc->bytes_produced = 0; + hc->download_content_size = ~0; + vec_validate (hc->pending_interests, HICN_HS_PEND_INT_SIZE); + + /* Set context configuration */ + if (!hicn_hs_cfg.csum_offload) + hc->cfg_flags |= HICN_HS_CFG_F_NO_CSUM_OFFLOAD; + + if (!hicn_hs_cfg.allow_tso) + hc->cfg_flags |= HICN_HS_CFG_F_NO_TSO; + + /** + * Connectionless session. + */ + + /** + * Allocate session and fifos now. + * XXX To check: Maybe it is better to allocate sessions and fifos + * upon reception of first data. + */ + s = session_alloc_for_connection (&hc->connection); + s->app_wrk_index = hc->parent_app_wrk_id; + app_wrk = app_worker_get (s->app_wrk_index); +// app_worker_alloc_connects_segment_manager (app_wrk); + + s->session_state = SESSION_STATE_OPENED; + if (app_worker_init_connected (app_wrk, s)) + { + session_free (s); + return -1; + } + + sh = session_handle (s); + session_lookup_add_connection (&hc->connection, sh); + + rv = app_worker_connect_notify (app_wrk, s, SESSION_E_NONE, hc_index); + + /* Initialize CBR protocol - consumer side */ + hc->hs_proto->init(hc); + + return rv; +} + +void hicn_hs_proto_on_close (u32 conn_index, u32 thread_index) +{ + return; +} + +/** + * The port is used as prefix length + */ +static u32 +hicn_hs_get_prefix_from_transport_endpoint(const ip46_address_t* ip, const u16 port, u8 is_ip4, fib_prefix_t *prefix) +{ + HICN_HS_ASSERT(port <= (is_ip4 ? IPV4_ADDR_LEN_BITS : IPV6_ADDR_LEN_BITS)); + fib_prefix_from_ip46_addr(ip, prefix); + prefix->fp_len = port; + + return HICN_HS_ERROR_NONE; +} + +/** + * Start listen for interests belonging to prefix + */ +u32 hicn_hs_start_listen (u32 session_index, transport_endpoint_t * lcl) +{ +// hicn_hs_worker_t *wrk = hicn_hs_get_worker_by_thread(0); + hicn_hs_ctx_t *ctx; + u32 ctx_index; + hicn_hs_main_t *hmm = hicn_hs_get_main (); + +// vnet_listen_args_t _bargs, *args = &_bargs; +// session_handle_t udp_handle; + session_endpoint_cfg_t *sep; +// session_t *udp_listen_session; + app_worker_t *app_wrk; + CLIB_UNUSED(application_t *app); +// u32 lctx_index; +// int rv; + + sep = (session_endpoint_cfg_t *) lcl; + app_wrk = app_worker_get (sep->app_wrk_index); + + app_worker_alloc_connects_segment_manager (app_wrk); + app = application_get (app_wrk->app_index); + HICN_HS_DBG (2, "Called hicn_hs_start_listen for app %d", app_wrk->app_index); + + /** + * Choose a transport index. + * hicn_hs_get_next_trasnport_index().. + */ +// u32 ctx_index = hicn_hs_wrk_get_next_ctx_index(wrk); + /* XXX Here we alloc a new ctx. Not clear yet how to trigger the consumer protocol + from the session layer. TBD */ + ctx_index = hicn_hs_ctx_alloc (0); + ctx = hicn_hs_get_ctx_by_index(ctx_index, 0); + + ip_copy (&ctx->connection.lcl_ip, &lcl->ip, lcl->is_ip4); + ctx->c_lcl_port = clib_net_to_host_u16(lcl->port); + ctx->c_is_ip4 = lcl->is_ip4; + ctx->c_proto = hmm->transport_protocol_id; + /* FixMe: Hardcoded Fib Index! */ + ctx->c_fib_index = fib_table_find(ctx->c_is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6, 10); + ctx->c_c_index = ctx_index; + ctx->session_index = session_index; + ctx->mss = hicn_hs_default_mtu (hmm, ctx->c_is_ip4); + ctx->current_content_size = 0; + ctx->bytes_produced = 0; + + /* Init output buffer hash table */ + clib_bihash_init_24_8 (&ctx->output_buffer, "prod-output-buffer", + /* 256 k */ 256 << 10, /* 8 MB */ 8 << 20); + + /* XXX Hardcoded CBR protocol for the moment */ + ctx->hs_proto = &cbr_proto; + ctx->running = 0; + ctx->accepted = 0; + + /* Set context configuration */ + if (!hicn_hs_cfg.csum_offload) + ctx->cfg_flags |= HICN_HS_CFG_F_NO_CSUM_OFFLOAD; + + if (!hicn_hs_cfg.allow_tso) + ctx->cfg_flags |= HICN_HS_CFG_F_NO_TSO; + + /** + * Setup DPO + */ + hicn_hs_dpo_create(ctx_index, lcl->is_ip4, &ctx->dpo); + + /** + * Get prefix from transport_endpoint_t + */ + hicn_hs_get_prefix_from_transport_endpoint(&ctx->c_lcl_ip, ctx->c_lcl_port, ctx->c_is_ip4, &ctx->producer_prefix); + + /** + * Set prefix in fib + */ + hicn_hs_route_add(&ctx->producer_prefix, &ctx->dpo); + + /** + * Check if hicn_hs input node recives interests + */ + + return ctx_index; +} + +u32 hicn_hs_stop_listen (u32 conn_index) +{ + return 0; +} + +transport_connection_t *hicn_hs_connection_get (u32 conn_idx, u32 thread_idx) +{ + hicn_hs_ctx_t *ctx = hicn_hs_get_ctx_by_index(conn_idx, thread_idx); + return &ctx->connection; +} + +transport_connection_t *hicn_hs_listener_get (u32 conn_index) +{ + hicn_hs_ctx_t *ctx = hicn_hs_get_ctx_by_index(conn_index, 0); + return &ctx->connection; +} + +int hicn_hs_send_params (transport_connection_t * tconn, + transport_send_params_t *sp) +{ + hicn_hs_ctx_t *ctx = (hicn_hs_ctx_t *) (tconn); + sp->snd_space = ~0; + + /* TODO: figure out MTU of output interface! */ + sp->snd_mss = ctx->mss; + sp->tx_offset = 0; + sp->flags = 0; + return 0; +} + +/** + * Push hicn header on data packet. + * This function is not called for interests, which are rather crafted + * directly in the transport layer. + */ +u32 hicn_hs_push_header (transport_connection_t * tconn, vlib_buffer_t * b) +{ + hicn_hs_ctx_t *ctx = (hicn_hs_ctx_t *) (tconn); + hicn_hs_worker_t * wrk = hicn_hs_get_worker_by_context (ctx); + u32 index; + int rv; + + hicn_name_t *name = &ctx->current_production_name; + hicn_hs_buffer(b)->is_interest = 0; + hicn_hs_buffer(b)->ctx_index = ctx->c_c_index; + hicn_hs_buffer(b)->flush = 0; + vlib_buffer_push_hicn(ctx, b, name, ctx->snd_nxt, 0); + + index = vlib_get_buffer_index (wrk->vm, b); + obuffer_kv4_t kv; + make_obuffer_kv (&kv, &ctx->current_production_name.prefix, ctx->snd_nxt++, index); + rv = clib_bihash_add_del_24_8 (&ctx->output_buffer, &kv, 2); + + if (PREDICT_FALSE (rv < 0)) + { + /* We tried to overwrite something already in the table. */ + obuffer_kv4_t kv_ret; + rv = clib_bihash_search_inline_2_24_8 (&ctx->output_buffer, &kv, &kv_ret); + if (!rv) + { + hicn_header_t *interest, *data; + vlib_buffer_t *buffer; + hicn_hs_buffer(b)->flush = 1; + clib_bihash_add_del_24_8 (&ctx->output_buffer, &kv, 1); + + buffer = vlib_get_buffer (wrk->vm, kv_ret.value); + interest = vlib_buffer_get_current (buffer); + data = vlib_buffer_get_current (b); + data->v6.ip.daddr = interest->v6.ip.saddr; + + vlib_buffer_free_one (wrk->vm, kv_ret.value); + } + } + + return 0; +} + +void hicn_hs_update_time (f64 time_now, u8 thread_index) +{ + return; +} + +int hicn_hs_custom_app_rx_callback (transport_connection_t *tconn) +{ + return 0; +} + +int hicn_hs_custom_tx_callback (void *session, transport_send_params_t *sp) +{ + return 0; +} + +u8 *format_hicn_hs_connection (u8 * s, va_list * args) +{ + return NULL; +} + +u8 *format_hicn_hs_half_open (u8 * s, va_list * args) +{ + return NULL; +} + +u8 *format_hicn_hs_listener (u8 * s, va_list * args) +{ + return NULL; +} + +void hicn_hs_get_transport_endpoint (u32 conn_index, u32 thread_index, + transport_endpoint_t *tep, u8 is_lcl) +{ + return; +} + +void hicn_hs_get_transport_listener_endpoint (u32 conn_index, + transport_endpoint_t *tep, + u8 is_lcl) +{ + return; +} + +static void +hicn_hs_expired_timers_dispatch (u32 * expired_timers) +{ + HICN_HS_DBG(1, "Timer expired."); +} + +static const transport_proto_vft_t hicn_hs_proto = { + .connect = hicn_hs_connect, + .close = hicn_hs_proto_on_close, + .start_listen = hicn_hs_start_listen, + .stop_listen = hicn_hs_stop_listen, + .get_connection = hicn_hs_connection_get, + .get_listener = hicn_hs_listener_get, + .update_time = hicn_hs_update_time, + .app_rx_evt = hicn_hs_custom_app_rx_callback, + .custom_tx = hicn_hs_custom_tx_callback, + .send_params = hicn_hs_send_params, + .push_header = hicn_hs_push_header, + .format_connection = format_hicn_hs_connection, + .format_half_open = format_hicn_hs_half_open, + .format_listener = format_hicn_hs_listener, + .get_transport_endpoint = hicn_hs_get_transport_endpoint, + .get_transport_listener_endpoint = hicn_hs_get_transport_listener_endpoint, + .transport_options = { + /* Used by session_register_transport to select the tx function. + TRANSPORT_TX_INTERNAL will delegate the transmission to the transport + protocol itself, throught he function hicn_hs_custom_tx_callback. Magic. */ + .tx_type = TRANSPORT_TX_DEQUEUE, + .service_type = TRANSPORT_SERVICE_APP, + .name = "hicn", + .short_name = "H" + }, +}; + +/** + * Initialize default values for tcp parameters + */ +static void +hicn_hs_configuration_init (void) +{ + hicn_hs_cfg.max_rx_fifo = 32 << 20; + hicn_hs_cfg.min_rx_fifo = 4 << 10; + + hicn_hs_cfg.default_mtu = 1500; + hicn_hs_cfg.enable_tx_pacing = 0; + hicn_hs_cfg.allow_tso = 0; + hicn_hs_cfg.csum_offload = 1; + + /* Time constants defined as timer tick (100ms) multiples */ + hicn_hs_cfg.closewait_time = 20; /* 2s */ + hicn_hs_cfg.cleanup_time = 0.1; /* 100ms */ +} + +clib_error_t * +hicn_hs_enable (vlib_main_t * vm) +{ + HICN_HS_DBG (1, "Function called (%p).", &hicn_hs_proto); + + hicn_hs_main_t *hm = &hicn_hs_main; + + hicn_hs_configuration_init (); + + // Register hicn_hs DPO + hicn_hs_dpo_module_init(); + + // Init route module + hicn_hs_route_init(); + + hm->enabled = 1; + return 0; +} + +clib_error_t * +hicn_hs_enable_disable(vlib_main_t * vm, u8 is_en) +{ + if (is_en) + { + if (session_main_is_enabled()) + return hicn_hs_enable (vm); + else + return clib_error_return (0, "Session not enabled, so hicn hoststack not enabled."); + } + + return 0; +} + +void +hicn_hs_init (vlib_main_t * vm) +{ + HICN_HS_DBG(1, "Function called"); + hicn_hs_main_t *hm = &hicn_hs_main; + vlib_thread_main_t *vtm = vlib_get_thread_main (); + u32 i, num_threads = 1 /* main thread */ + vtm->n_threads; + tw_timer_wheel_1t_3w_1024sl_ov_t *tw; + + hm->app_index = 0; + vec_validate_aligned (hm->workers, num_threads - 1, CLIB_CACHE_LINE_BYTES); + + for (i = 0; i < num_threads; i++) + { + tw = &hm->workers[i].timer_wheel; + tw_timer_wheel_init_1t_3w_1024sl_ov (tw, hicn_hs_expired_timers_dispatch, + 1e-3 /* timer period 1ms */ , ~0); + tw->last_run_time = vlib_time_now (vlib_get_main ()); + hm->workers[i].vm = vlib_mains[i]; + hm->workers[i].next_hicn_ctx = 0; + } + + hm->tstamp_ticks_per_clock = vm->clib_time.seconds_per_clock / HICN_HS_TSTAMP_RESOLUTION; + + hm->hicn_hs_in4_idx = hicn_hs_input4_node.index; + hm->hicn_hs_on4_idx = hicn_hs_output4_node.index; + + hm->hicn_hs_in6_idx = hicn_hs_input6_node.index; + hm->hicn_hs_on6_idx = hicn_hs_output6_node.index; + + // Not enabled by default + hm->enabled = 0; + + // Register new protocol + hm->transport_protocol_id = transport_register_new_protocol(&hicn_hs_proto, + FIB_PROTOCOL_IP6, + hm->hicn_hs_on6_idx); + transport_register_protocol (hm->transport_protocol_id, &hicn_hs_proto, + FIB_PROTOCOL_IP4, hm->hicn_hs_on4_idx); +} + +/* *INDENT-ON* */ + +// static clib_error_t * +// hicn_hs_config_fn (vlib_main_t * vm, unformat_input_t * input) +// { +// HICN_HS_DBG(1, "Function called early."); +// return 0; +// } + +// static clib_error_t * +// hicn_hs_config2_fn (vlib_main_t * vm, unformat_input_t * input) +// { +// HICN_HS_DBG(1, "Function called."); +// return 0; +// } + +// VLIB_EARLY_CONFIG_FUNCTION (hicn_hs_config_fn, "hicn_hs"); +// VLIB_CONFIG_FUNCTION (hicn_hs_config2_fn, "hicn_hs"); diff --git a/hicn-plugin/src/host_stack/host_stack.h b/hicn-plugin/src/host_stack/host_stack.h new file mode 100644 index 000000000..5ad2db1ae --- /dev/null +++ b/hicn-plugin/src/host_stack/host_stack.h @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2020 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 __included_hicn_hs_h__ +#define __included_hicn_hs_h__ + +#include "producer_dpo.h" +#include "hicn_buffer.h" + +#include +#include + +#include +#include +#include +#include +#include + + +/* Log levels + * 1 - errors + * 2 - connection/stream events + * 3 - packet events + * 4 - timer events + **/ + +#define HICN_HS_DEBUG 1 +#define HICN_HS_TSTAMP_RESOLUTION 0.001 /* HICN_HS tick resolution (1ms) */ +#define HICN_HS_TIMER_HANDLE_INVALID ((u32) ~0) +#define HICN_HS_SESSION_INVALID ((u32) ~0 - 1) +#define HICN_HS_MAX_PACKET_SIZE 1280 + +#define HICN_HS_INT_MAX 0x3FFFFFFFFFFFFFFF +#define HICN_HS_DEFAULT_FIFO_SIZE (64 << 10) +#define HICN_HS_DEFAULT_CONN_TIMEOUT (30 * 1000) /* 30 seconds */ +#define HICN_HS_SEND_PACKET_VEC_SIZE 16 +#define HICN_HS_IV_LEN 17 + +#define HICN_HS_INPUT4_NODE_NAME "hicn_hs-input4" +#define HICN_HS_OUTPUT4_NODE_NAME "hicn_hs-output4" + +#define HICN_HS_INPUT6_NODE_NAME "hicn_hs-input6" +#define HICN_HS_OUTPUT6_NODE_NAME "hicn_hs-output6" + +#define HICN_HS_INPUT_INTEREST_NODE_NAME "hicn_hs-input-interest" +#define HICN_HS_INPUT_DATA_NODE_NAME "hicn_hs-input-data" + +#define HICN_HS_DEFAULT_MTU (1500 - 40 - 20) + +#define PROTO_DATA_SIZE 32 +#define HICN_HS_PEND_INT_SIZE (1 << 11) +#define HICN_HS_PEND_INT_MASK (HICN_HS_PEND_INT_SIZE - 1) + +#if HICN_HS_DEBUG +#define HICN_HS_DBG(_lvl, _fmt, _args...) \ + if (_lvl <= HICN_HS_DEBUG) \ + clib_warning (_fmt, ##_args) +#else +#define HICN_HS_DBG(_lvl, _fmt, _args...) +#endif + +#if CLIB_ASSERT_ENABLE +#define HICN_HS_ASSERT(truth) ASSERT (truth) +#else +#define HICN_HS_ASSERT(truth) \ + do { \ + if (PREDICT_FALSE (! (truth))) \ + HICN_HS_ERR ("ASSERT(%s) failed", # truth); \ + } while (0) +#endif + +#define HICN_HS_ERR(_fmt, _args...) \ + do { \ + clib_warning ("HICN_HS-ERR: " _fmt, ##_args); \ + } while (0) + +extern vlib_node_registration_t hicn_hs_input_node; +extern vlib_node_registration_t hicn_hs_input_interest_node; +extern vlib_node_registration_t hicn_hs_input_data_node; + +typedef enum +{ +#define hicn_hs_error(n,s) HICN_HS_ERROR_##n, +#include "errors/hicn_hs.def" +#undef hicn_hs_error + HICN_HS_N_ERROR, +} hicn_hs_error_t; + +typedef struct hicn_hs_proto_ hicn_hs_proto_t; + +/* hicn configuration flags */ +#define foreach_hicn_hs_cfg_flag \ + _(NO_CSUM_OFFLOAD, "No csum offload") \ + _(NO_TSO, "TSO off") + +typedef enum hicn_hs_cfg_flag_bits_ +{ +#define _(sym, str) HICN_HS_CFG_F_##sym##_BIT, + foreach_hicn_hs_cfg_flag +#undef _ + HICN_HS_CFG_N_FLAG_BITS +} hicn_hs_cfg_flag_bits_e; + +typedef enum hicn_hs_cfg_flag_ +{ +#define _(sym, str) HICN_HS_CFG_F_##sym = 1 << HICN_HS_CFG_F_##sym##_BIT, + foreach_hicn_hs_cfg_flag +#undef _ + HICN_HS_CFG_N_FLAGS +} hicn_hs_cfg_flags_e; + +typedef enum hicn_hs_proto_event_ +{ + PROTO_N_EVENT, +} hicn_hs_proto_event_t; + +typedef struct hicn_hs_ctx_ +{ + CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); + transport_connection_t connection; /* Must be first, for convenient casts!!! */ + u32 parent_app_wrk_id; + u32 client_opaque; + u32 timer_handle; + u8 cfg_flags; /**< Hicn ctx configuration flags */ + hicn_hs_proto_t *hs_proto; + u8 hs_proto_data[PROTO_DATA_SIZE]; + + /* Maps interest suffix -> vlib buffer index */ + u32 *pending_interests; + + // The hicn name for the consumer session + hicn_name_t consumer_name; + // The current name in production in th eproducer session + hicn_name_t current_production_name; + + // The prefix for the producer names. + /* XXX To be retrieved from a pool of names configured by the control protocol / network admin */ + fib_prefix_t producer_prefix; + + /* Store the size of the content currently produced. */ + u32 current_content_size; + u32 number_of_segments; + + /* Store size of content to download - consumer side */ + u32 download_content_size; + + u32 bytes_produced; + + /* Seq number to assign to next segment */ + u32 snd_nxt; + + /* Expected bytes */ + u32 rcv_nxt; + + /* Some stats */ + u64 int_in; + u64 data_in; + u64 int_out; + u64 data_out; + u64 bytes_in; + u64 bytes_outs; + + /* The DPO for this hicn_hs ctx */ + dpo_id_t dpo; + + /* Hash table for exact match prefix-suffix */ + clib_bihash_24_8_t output_buffer; + + /* Unused listener session index */ + u32 session_index; + + u8 running; + u8 accepted; + + u16 mss; +} hicn_hs_ctx_t; + +typedef clib_bihash_kv_24_8_t obuffer_kv4_t; + +typedef struct { + u32 ctx_index; + u8 is_interest; + u8 is_ip4; + u8 flush; + u32 seq_number; + hicn_type_t type; +} hicn_hs_buffer_t; + +#define hicn_hs_buffer(b) ((hicn_hs_buffer_t *) (b)->opaque2) +#define hicn_buffer_hdr(b) ((hicn_header_t *) (vlib_buffer_get_current(b))) + +always_inline void * +hicn_hs_proto_data(hicn_hs_ctx_t *ctx) +{ + return (void*)(ctx->hs_proto_data); +} + +struct hicn_hs_proto_ +{ + u32 (*init) (hicn_hs_ctx_t * hc); + u32 (*rcv_data) (hicn_hs_ctx_t * hc, u16 n_data); + u32 (*rcv_interest) (hicn_hs_ctx_t * hc); + u32 (*on_interest_timeout) (hicn_hs_ctx_t *hc); + u32 (*event) (hicn_hs_ctx_t *hc, hicn_hs_proto_event_t event); + struct { + u8 is_stream; + } options; +}; + +typedef struct hicn_hs_worker_ctx_ +{ + CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); + hicn_hs_ctx_t *hicn_ctxs; /**< worker's pool of hicn context */ + u32 next_hicn_ctx; /**< Next hicn context, to be used in start_listen*/ + int64_t time_now; /**< worker time */ + tw_timer_wheel_1t_3w_1024sl_ov_t timer_wheel; /**< worker timer wheel */ + vlib_main_t *vm; /**< pointer to thread's vlib main*/ + /** Peekers rw lock */ + clib_rwlock_t peekers_rw_locks; +} hicn_hs_worker_t; + +typedef struct hicn_hs_configuration_ +{ + /** Max rx fifo size for a session (in bytes). It is used in to compute the + * rfc 7323 window scaling factor */ + u32 max_rx_fifo; + + /** Min rx fifo for a session (in bytes) */ + u32 min_rx_fifo; + + /** Default MTU to be used when establishing connections */ + u16 default_mtu; + + /** Enable tx pacing for new connections */ + u8 enable_tx_pacing; + + /** Allow use of TSO whenever available */ + u8 allow_tso; + + /** Set if csum offloading is enabled */ + u8 csum_offload; + + /** Timer ticks to wait for close from app */ + u16 closewait_time; + + /** Time to wait (sec) before cleaning up the connection */ + f32 cleanup_time; +} hicn_hs_configuration_t; + +typedef struct _hicn_hs_lookup_dispatch +{ + u8 next, error; +} hicn_hs_lookup_dispatch_t; + +#define foreach_hicn_hs_packet \ + _ (DATA, "data") \ + _ (INTEREST, "interest") \ + _ (NO_HICN, "ho hicn") + +typedef enum _hicn_hs_packet +{ + #define _(n, s) HICN_HS_##n, + foreach_hicn_hs_packet + #undef _ + HICN_HS_N_PACKET, +} hicn_hs_packet_t; + +typedef struct hicn_hs_main_ +{ + u32 app_index; + hicn_hs_worker_t *workers; + clib_bihash_24_8_t connection_hash; /**< connection id -> conn handle */ + f64 tstamp_ticks_per_clock; + + // The new registered transport ID + transport_proto_t transport_protocol_id; + + // Input/Output nodes information + u32 hicn_hs_in4_idx; + u32 hicn_hs_on4_idx; + u32 hicn_hs_in6_idx; + u32 hicn_hs_on6_idx; + + // Enabled/Disabled + u8 enabled; + + u32 udp_fifo_size; + u32 udp_fifo_prealloc; + u32 connection_timeout; + + // Configuration + hicn_hs_configuration_t cfg; + + // Dispatch table + hicn_hs_lookup_dispatch_t dispatch_table[HICN_HS_N_PACKET]; +} hicn_hs_main_t; + +void hicn_hs_init (vlib_main_t * vm); + +extern hicn_hs_main_t hicn_hs_main; +extern vlib_node_registration_t hicn_hs_input4_node; +extern vlib_node_registration_t hicn_hs_output4_node; +extern vlib_node_registration_t hicn_hs_input6_node; +extern vlib_node_registration_t hicn_hs_output6_node; +extern char *hicn_hs_error_strings[]; + +#define hicn_hs_cfg (hicn_hs_main.cfg) + +// Protocols +extern hicn_hs_proto_t cbr_proto; + +always_inline +hicn_hs_main_t *hicn_hs_get_main () +{ + return &hicn_hs_main; +} + +always_inline +transport_proto_t hicn_hs_get_protocol_id() +{ + hicn_hs_main_t *hm = hicn_hs_get_main (); + return hm->transport_protocol_id; +} + +clib_error_t * hicn_hs_enable_disable(vlib_main_t * vm, u8 is_en); + +always_inline void +hicn_hs_update_transport(hicn_hs_ctx_t *ctx, u16 recv_data) +{ + // Pass data packet to transport + ctx->hs_proto->rcv_data(ctx, recv_data); +} + +always_inline void +hicn_hs_set_next_prod_size (hicn_hs_ctx_t *ctx, u32 prod_size) +{ + ctx->current_content_size = prod_size; + ctx->number_of_segments = (prod_size / ctx->mss) + ((prod_size % ctx->mss) > 0); +} + +always_inline hicn_hs_worker_t * +hicn_hs_get_worker_by_context (hicn_hs_ctx_t *ctx) +{ + hicn_hs_main_t *hmm = hicn_hs_get_main (); + return &hmm->workers[ctx->c_thread_index]; +} + +always_inline hicn_hs_worker_t * +hicn_hs_get_worker_by_thread (u32 thread_idx) +{ + hicn_hs_main_t *hmm = hicn_hs_get_main (); + return &hmm->workers[thread_idx]; +} + +always_inline hicn_hs_ctx_t * +hicn_hs_wrk_get_ctx(hicn_hs_worker_t *wrk, u32 index) +{ + return pool_elt_at_index (wrk->hicn_ctxs, index); +} + +always_inline u32 +hicn_hs_wrk_get_next_ctx_index(hicn_hs_worker_t *wrk) +{ + return wrk->next_hicn_ctx++; +} + +always_inline hicn_hs_ctx_t * +hicn_hs_get_ctx_by_index (u32 ctx_index, u32 thread_index) +{ + hicn_hs_worker_t *wrk = hicn_hs_get_worker_by_thread(thread_index); + return hicn_hs_wrk_get_ctx(wrk, ctx_index); +} + +always_inline hicn_name_t* +hicn_hs_ctx_get_consumer_name(hicn_hs_ctx_t *ctx) +{ + return &ctx->consumer_name; +} + +always_inline dpo_id_t* +hicn_hs_ctx_get_dpo(hicn_hs_ctx_t *ctx) +{ + return &ctx->dpo; +} + +#endif /* __included_hicn_hs_h__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/host_stack/inlines.h b/hicn-plugin/src/host_stack/inlines.h new file mode 100644 index 000000000..5c2c33915 --- /dev/null +++ b/hicn-plugin/src/host_stack/inlines.h @@ -0,0 +1,520 @@ +/* + * Copyright (c) 2020 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 __included_hicn_hs_inlines_h__ +#define __included_hicn_hs_inlines_h__ + +#include "host_stack.h" +#include "utils.h" + +always_inline void +make_obuffer_kv (obuffer_kv4_t * kv, ip46_address_t * prefix, u32 suffix, u32 bi) +{ + kv->key[0] = prefix->as_u64[0]; + kv->key[1] = prefix->as_u64[1]; + kv->key[2] = suffix; + kv->value = bi; +} + +always_inline void +hicn_hs_app_notify_rx (hicn_hs_ctx_t *ctx) +{ + session_t *s; + s = session_get(ctx->c_s_index, 0); + session_enqueue_notify(s); +} + +always_inline u16 +hicn_hs_default_mtu (hicn_hs_main_t * hm, u8 is_ip4) +{ + u16 hicn_hlen = is_ip4 ? HICN_V4_TCP_HDRLEN : HICN_V6_TCP_HDRLEN; + return (hicn_hs_cfg.default_mtu - hicn_hlen); +} + +always_inline u32 +hicn_hs_ctx_alloc(u32 thread_index) +{ + hicn_hs_worker_t *wrk = hicn_hs_get_worker_by_thread(thread_index); + hicn_hs_ctx_t *ctx; + + u8 will_expand; + pool_get_aligned_will_expand (wrk->hicn_ctxs, will_expand, + CLIB_CACHE_LINE_BYTES); + /* If we have peekers, let them finish */ + if (PREDICT_FALSE (will_expand && vlib_num_workers ())) + { + clib_rwlock_writer_lock (&wrk->peekers_rw_locks); + pool_get_aligned (wrk->hicn_ctxs, ctx, CLIB_CACHE_LINE_BYTES); + clib_rwlock_writer_unlock (&wrk->peekers_rw_locks); + } + else + { + pool_get_aligned (wrk->hicn_ctxs, ctx, CLIB_CACHE_LINE_BYTES); + } + + clib_memset (ctx, 0, sizeof (hicn_hs_ctx_t)); + ctx->c_thread_index = thread_index; + ctx->timer_handle = HICN_HS_TIMER_HANDLE_INVALID; + HICN_HS_DBG (3, "Allocated hicn_hs_ctx_t %u on thread %u", + ctx - wrk->hicn_ctxs, thread_index); + + return ctx - wrk->hicn_ctxs; +} + +always_inline void* +vlib_buffer_push_hicn (hicn_hs_ctx_t *ctx, vlib_buffer_t *b, + hicn_name_t* name, u32 seq_number, u8 is_interest) +{ + hicn_header_t *hicn_header; + hicn_hs_buffer_t *buffer = hicn_hs_buffer (b); + int rv; + u16 current_length = b->current_length; + u16 payload_len = current_length; + if (PREDICT_FALSE (b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID)) + payload_len += b->total_length_not_including_first_buffer; + + hicn_header = vlib_buffer_push_uninit (b, HICN_V6_TCP_HDRLEN); + buffer->type.l4 = IPPROTO_NONE; + buffer->type.l3 = IPPROTO_NONE; + buffer->type.l2 = IPPROTO_TCP; + buffer->type.l1 = IPPROTO_IPV6; + + buffer->flush = 0; + + name->suffix = seq_number; + + rv = hicn_ops_vft[buffer->type.l1]->init_packet_header(buffer->type, &hicn_header->protocol); + rv += hicn_ops_vft[buffer->type.l1]->set_payload_length(buffer->type, &hicn_header->protocol, payload_len); + + if (is_interest) + { + rv += hicn_ops_vft[buffer->type.l1]->set_interest_name(buffer->type, &hicn_header->protocol, name); + rv += hicn_ops_vft[buffer->type.l1]->mark_packet_as_interest(buffer->type, &hicn_header->protocol); + } + else + { + rv += hicn_ops_vft[buffer->type.l1]->set_data_name(buffer->type, &hicn_header->protocol, name); + rv += hicn_ops_vft[buffer->type.l1]->mark_packet_as_data(buffer->type, &hicn_header->protocol); + } + + ASSERT (!rv); + + hicn_header->v6.tcp.csum = hicn_hs_compute_checksum (ctx, b); + + vnet_buffer (b)->l4_hdr_offset = (u8 *) hicn_header - b->data; + b->flags |= VNET_BUFFER_F_L4_HDR_OFFSET_VALID; + + ctx->bytes_produced += current_length; + + if (PREDICT_FALSE (!is_interest && ctx->bytes_produced == ctx->current_content_size)) + { + // Last packet +// rv += hicn_packet_set_rst (hicn_header); + } + + return hicn_header; +} + +always_inline u32 +hicn_hs_make_interest (hicn_hs_ctx_t * ctx, vlib_buffer_t *b, + hicn_name_t *name, u32 seq_number) +{ + vlib_buffer_push_hicn(ctx, b, name, seq_number, 1); + hicn_hs_buffer (b)->flush = 1; + b->ref_count = 1; + return 1; +} + +always_inline void +hicn_hs_enqueue_to_output (vlib_main_t *vm, session_main_t *smm, + vlib_buffer_t * b, u32 bi, u8 is_ip4, + session_type_t st) +{ + session_add_pending_tx_buffer (vm->thread_index, bi, smm->session_type_to_next[st]); +} + +always_inline u32 +hicn_hs_send_interests_i (vlib_main_t *vm, hicn_hs_ctx_t *ctx, vlib_buffer_t **b, u32 *bi, u32 offset, u32 count) +{ + int ret = 0; + hicn_name_t *name = hicn_hs_ctx_get_consumer_name(ctx); + session_type_t st; + hicn_hs_main_t *hm = hicn_hs_get_main(); + session_main_t *smm = vnet_get_session_main (); + transport_proto_t proto = hm->transport_protocol_id; + + st = session_type_from_proto_and_ip (proto, ctx->c_is_ip4); + + while (count >= 8) + { + { + vlib_prefetch_buffer_header (b[4], STORE); + CLIB_PREFETCH (b[4]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE); + + vlib_prefetch_buffer_header (b[5], STORE); + CLIB_PREFETCH (b[5]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE); + + vlib_prefetch_buffer_header (b[6], STORE); + CLIB_PREFETCH (b[6]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE); + + vlib_prefetch_buffer_header (b[7], STORE); + CLIB_PREFETCH (b[7]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE); + } + + ASSERT ((b[0]->flags & VLIB_BUFFER_NEXT_PRESENT) == 0); + b[0]->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; + b[0]->total_length_not_including_first_buffer = 0; + b[0]->current_data = 0; + b[0]->error = 0; + VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[0]); + hicn_hs_buffer(b[0])->ctx_index = ctx->c_c_index; + hicn_hs_buffer(b[0])->is_interest = 1; + /* Leave enough space for headers */ + vlib_buffer_make_headroom (b[0], TRANSPORT_MAX_HDRS_LEN); + ret += hicn_hs_make_interest (ctx, b[0], name, offset++); + hicn_hs_enqueue_to_output (vm, smm, b[0], bi[0], ctx->c_is_ip4, st); + + ASSERT ((b[1]->flags & VLIB_BUFFER_NEXT_PRESENT) == 0); + b[1]->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; + b[1]->total_length_not_including_first_buffer = 0; + b[1]->current_data = 0; + b[1]->error = 0; + VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[1]); + hicn_hs_buffer(b[1])->ctx_index = ctx->c_c_index; + hicn_hs_buffer(b[1])->is_interest = 1; + /* Leave enough space for headers */ + vlib_buffer_make_headroom (b[1], TRANSPORT_MAX_HDRS_LEN); + ret += hicn_hs_make_interest (ctx, b[1], name, offset++); + hicn_hs_enqueue_to_output (vm, smm, b[1], bi[1], ctx->c_is_ip4, st); + + ASSERT ((b[2]->flags & VLIB_BUFFER_NEXT_PRESENT) == 0); + b[2]->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; + b[2]->total_length_not_including_first_buffer = 0; + b[2]->current_data = 0; + b[2]->error = 0; + VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[2]); + hicn_hs_buffer(b[2])->ctx_index = ctx->c_c_index; + hicn_hs_buffer(b[2])->is_interest = 1; + /* Leave enough space for headers */ + vlib_buffer_make_headroom (b[2], TRANSPORT_MAX_HDRS_LEN); + ret += hicn_hs_make_interest (ctx, b[2], name, offset++); + hicn_hs_enqueue_to_output (vm, smm, b[2], bi[2], ctx->c_is_ip4, st); + + ASSERT ((b[3]->flags & VLIB_BUFFER_NEXT_PRESENT) == 0); + b[3]->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; + b[3]->total_length_not_including_first_buffer = 0; + b[3]->current_data = 0; + b[3]->error = 0; + VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[3]); + hicn_hs_buffer(b[3])->ctx_index = ctx->c_c_index; + hicn_hs_buffer(b[3])->is_interest = 1; + /* Leave enough space for headers */ + vlib_buffer_make_headroom (b[3], TRANSPORT_MAX_HDRS_LEN); + ret += hicn_hs_make_interest (ctx, b[3], name, offset++); + hicn_hs_enqueue_to_output (vm, smm, b[3], bi[3], ctx->c_is_ip4, st); + + b += 4; + bi += 4; + count -= 4; + } + while (count) + { + if (count > 1) + { + vlib_prefetch_buffer_header (b[1], STORE); + CLIB_PREFETCH (b[1]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE); + } + ASSERT ((b[0]->flags & VLIB_BUFFER_NEXT_PRESENT) == 0); + b[0]->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; + b[0]->total_length_not_including_first_buffer = 0; + b[0]->current_data = 0; + b[0]->error = 0; + VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[0]); + hicn_hs_buffer(b[0])->ctx_index = ctx->c_c_index; + hicn_hs_buffer(b[0])->is_interest = 1; + /* Leave enough space for headers */ + vlib_buffer_make_headroom (b[0], TRANSPORT_MAX_HDRS_LEN); + ret += hicn_hs_make_interest (ctx, b[0], name, offset++); + hicn_hs_enqueue_to_output (vm, smm, b[0], bi[0], ctx->c_is_ip4, st); + + b += 1; + bi += 1; + count -= 1; + } + + return ret; +} + +always_inline u32 +hicn_hs_send_interests (hicn_hs_ctx_t * ctx, u32 start_offset, u32 n_interest) +{ + hicn_hs_worker_t *wrk = hicn_hs_get_worker_by_context (ctx); + vlib_main_t *vm = wrk->vm; + vlib_buffer_t *b[VLIB_FRAME_SIZE]; + u32 bi[VLIB_FRAME_SIZE]; + + if (PREDICT_FALSE (!vlib_buffer_alloc (vm, bi, n_interest))) + { + HICN_HS_DBG (1, "Vlib buffer alloc failed."); + return 0; + } + vlib_get_buffers (vm, bi, b, n_interest); + return hicn_hs_send_interests_i (vm, ctx, b, bi, start_offset, n_interest); +} + +/* Modulo arithmetic for TCP sequence numbers */ +#define seq_lt(_s1, _s2) ((i32)((_s1)-(_s2)) < 0) +#define seq_leq(_s1, _s2) ((i32)((_s1)-(_s2)) <= 0) +#define seq_gt(_s1, _s2) ((i32)((_s1)-(_s2)) > 0) +#define seq_geq(_s1, _s2) ((i32)((_s1)-(_s2)) >= 0) +#define seq_max(_s1, _s2) (seq_gt((_s1), (_s2)) ? (_s1) : (_s2)) + +/** Enqueue data for delivery to application */ +always_inline int +hicn_hs_enqueue_data (hicn_hs_ctx_t * ctx, vlib_buffer_t * b, + u16 data_len) +{ + int written, error = HICN_HS_ERROR_ENQUEUED; + hicn_hs_buffer_t *buffer = hicn_hs_buffer (b); + + ASSERT (seq_geq (buffer->seq_number, ctx->rcv_nxt)); + ASSERT (data_len); + + written = session_enqueue_stream_connection (&ctx->connection, b, 0, + 1 /* queue event */ , 1); + ctx->bytes_in += written; + + /* Update rcv_nxt */ + if (PREDICT_TRUE (written == data_len)) + { + ctx->rcv_nxt += written; + } + /* If more data written than expected, account for out-of-order bytes. */ + else if (written > data_len) + { + ctx->rcv_nxt += written; + } + else if (written > 0) + { + /* We've written something but FIFO is probably full now */ + ctx->rcv_nxt += written; + error = HICN_HS_ERROR_PARTIALLY_ENQUEUED; + } + else + { + error = HICN_HS_ERROR_FIFO_FULL; + } + + if (PREDICT_FALSE (ctx->rcv_nxt >= ctx->download_content_size)) + hicn_hs_app_notify_rx (ctx); + + return error; +} + +always_inline int +hicn_hs_enqueue_ooo (hicn_hs_ctx_t * ctx, vlib_buffer_t * b, + u16 data_len) +{ + int rv, CLIB_UNUSED(offset); + hicn_hs_buffer_t *buffer = hicn_hs_buffer (b); + + ASSERT (seq_gt (buffer->seq_number, ctx->rcv_nxt)); + ASSERT (data_len); + + /* Enqueue out-of-order data with relative offset */ + rv = session_enqueue_stream_connection (&ctx->connection, b, + buffer->seq_number - ctx->rcv_nxt, + 0 /* queue event */ , 0); + + /* Nothing written */ + if (rv) + { + return HICN_HS_ERROR_FIFO_FULL; + } + + ctx->bytes_in += data_len; + + return HICN_HS_ERROR_ENQUEUED_OOO; +} + +always_inline int +hicn_hs_rcv_stream (hicn_hs_worker_t * wrk, hicn_hs_ctx_t * ctx, + vlib_buffer_t * b) +{ + u32 error; + size_t n_data_bytes, skip; + hicn_hs_buffer_t *buffer = hicn_hs_buffer (b); + hicn_header_t *hicn_header; + int rv; + u8 rst = 0; + hicn_name_t data_name; + + /* XXX Assuming no signature for now. */ + hicn_header = vlib_buffer_get_current (b); + + rv = hicn_ops_vft[buffer->type.l1]->get_payload_length (buffer->type, &hicn_header->protocol, (size_t *)(&n_data_bytes)); + rv += hicn_ops_vft[buffer->type.l1]->get_header_length (buffer->type, &hicn_header->protocol, (size_t *)(&skip)); + rv += hicn_ops_vft[buffer->type.l1]->get_data_name (buffer->type, &hicn_header->protocol, &data_name); + rv += hicn_name_compare (&ctx->consumer_name, &data_name, 0); + + vlib_buffer_advance (b, skip); + + if (PREDICT_FALSE(rv < 0)) + { + error = HICN_HS_ERROR_FORMAT; + return error; + } + +// TODO hicn_packet_test_rst (hicn_header, (bool *)(&rst)); + if (PREDICT_FALSE (rst)) + ctx->download_content_size = (buffer->seq_number - 1) * ctx->mss + n_data_bytes; + + ASSERT (n_data_bytes); + + /* Adjust seq number in order to represent byte number */ + buffer->seq_number *= ctx->mss; + + /* Handle out-of-order data */ + if (PREDICT_FALSE (buffer->seq_number != ctx->rcv_nxt)) + { + rv = hicn_hs_enqueue_ooo (ctx, b, n_data_bytes); + } + else + /* In order data, enqueue. Fifo figures out by itself if any out-of-order + * segments can be enqueued after fifo tail offset changes. */ + rv = hicn_hs_enqueue_data (ctx, b, n_data_bytes); + + vlib_buffer_push_uninit(b, skip); + + return rv; +} + +always_inline +void hicn_hs_process_incoming_interest (hicn_hs_ctx_t *ctx, vlib_buffer_t* interest) +{ + hicn_hs_buffer_t *buffer; + vlib_buffer_t *data_packet; + hicn_hs_worker_t *wrk = hicn_hs_get_worker_by_context (ctx); + session_main_t *smm = vnet_get_session_main (); + hicn_hs_main_t *hm = hicn_hs_get_main (); + vlib_main_t *vm = wrk->vm; + obuffer_kv4_t kv; + int rv; + session_type_t st; + u32 suffix; + u32 interest_index; + + transport_proto_t proto = hm->transport_protocol_id; + st = session_type_from_proto_and_ip (proto, ctx->c_is_ip4); + + buffer = hicn_hs_buffer (interest); + + if (PREDICT_FALSE(!ctx->accepted)) + { + session_stream_accept(&ctx->connection, ctx->session_index, 0, 1); + ctx->accepted = 1; + } + + interest_index = vlib_get_buffer_index (wrk->vm, interest); + + // Check for match in local output buffer + if (PREDICT_FALSE(buffer->is_ip4)) + { + // Handle ip4 case + return; + } + else + { + hicn_hs_buffer_t *b = hicn_hs_buffer (interest); + ip6_header_t *ip6 = vlib_buffer_get_current (interest); + hicn_protocol_t *proto = (hicn_protocol_t *)(ip6); + hicn_ops_vft[b->type.l1]->get_interest_name_suffix(b->type, proto, &suffix); + make_obuffer_kv(&kv, (ip46_address_t *)&ip6->dst_address, suffix, ~0); + rv = clib_bihash_search_inline_24_8(&ctx->output_buffer, &kv); + if (PREDICT_TRUE(!rv)) + { + u32 bi = (u32) kv.value; + + // Retrieve corresponding data packet + data_packet = vlib_get_buffer(vm, bi); + + hicn_header_t *interest = (hicn_header_t *)(proto); + hicn_header_t *data = vlib_buffer_get_current (data_packet); + + ASSERT(!hicn_hs_buffer (data_packet)->is_interest); + hicn_hs_buffer (data_packet)->ctx_index = ctx->c_c_index; + hicn_hs_buffer (data_packet)->flush = 1; + + data->v6.ip.daddr = interest->v6.ip.saddr; + + hicn_hs_enqueue_to_output (vm, smm, data_packet, bi, 0, st); + } + else + { + /** + * What it is better to do here is allocate connection upon + * interest reception, once. This will allow to get the thread index, + * the one which received the interest. The idea is that all interests + * for same content should be processed by same thread. We cannot use + * RSS hashing, since the source address will change.. + * Solutions: + * - Dispatcher node BEFORE hicn network plugin, doing exactly the same of RSS hashing + * - Configure hashing function in order to consider hICN-meaningful part of the packet + */ + + if (ip46_address_is_equal ((ip46_address_t *) (&ctx->current_production_name.prefix), + (ip46_address_t *) (&ip6->dst_address))) + { + /** + * Content currently in production. + **/ + if (PREDICT_FALSE(suffix >= ctx->number_of_segments)) + goto cleanup; + + kv.value = interest_index; + clib_bihash_add_del_24_8 (&ctx->output_buffer, &kv, 1); + return; + } + + // Signal this cache miss to parent app. + // session_enqueue_dgram_connection(ctx->c_s_index, ) + ip46_address_copy((ip46_address_t *) (&ctx->current_production_name.prefix), + (ip46_address_t *) (&ip6->dst_address)); + ctx->current_production_name.suffix = 0; + kv.value = interest_index; + clib_bihash_add_del_24_8 (&ctx->output_buffer, &kv, 1); + hicn_hs_app_notify_rx (ctx); + return; + } + } + +cleanup: + vlib_buffer_free_one (wrk->vm, interest_index); +} + +always_inline +void hicn_hs_process_incoming_data(hicn_hs_ctx_t *ctx, vlib_buffer_t* data) +{ + hicn_hs_worker_t *wrk = hicn_hs_get_worker_by_context (ctx); + hicn_hs_rcv_stream (wrk, ctx, data); + + /** + * If stream connection, tcp seq number in data packet stores + * the byte number of the first byte of data in the TCP packet sent. + */ + +} + +#endif /* __included_hicn_hs_inlines_h__ */ \ No newline at end of file diff --git a/hicn-plugin/src/host_stack/input_node.c b/hicn-plugin/src/host_stack/input_node.c new file mode 100644 index 000000000..962f8a204 --- /dev/null +++ b/hicn-plugin/src/host_stack/input_node.c @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2020 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 "host_stack.h" +#include "inlines.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +typedef enum _hicn_hs_input_next +{ + HICN_HS_INPUT_NEXT_DATA, + HICN_HS_INPUT_NEXT_INTEREST, + HICN_HS_INPUT_NEXT_DROP, + HICN_HS_INPUT_N_NEXT +} hicn_hs_input_next_t; + +#define foreach_hicn_hs_input_next4 \ + _ (DATA, HICN_HS_INPUT_DATA_NODE_NAME) \ + _ (INTEREST, HICN_HS_INPUT_INTEREST_NODE_NAME) \ + _ (DROP, "ip4-drop") + +#define foreach_hicn_hs_input_next6 \ + _ (DATA, HICN_HS_INPUT_DATA_NODE_NAME) \ + _ (INTEREST, HICN_HS_INPUT_INTEREST_NODE_NAME) \ + _ (DROP, "ip6-drop") + +/* packet trace format function */ +static u8 * +format_hicn_hs_input4_trace (u8 * s, va_list * args) +{ + return NULL; +} + +static u8 * +format_hicn_hs_input6_trace (u8 * s, va_list * args) +{ + return NULL; +} + +static u8 * +format_hicn_hs_input_interest_trace (u8 * s, va_list * args) +{ + return NULL; +} + +static u8 * +format_hicn_hs_input_data_trace (u8 * s, va_list * args) +{ + return NULL; +} + +static void +hicn_hs_input_trace_frame (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_buffer_t ** bs, u32 n_bufs, u8 is_ip4) +{ +} + +always_inline hicn_hs_ctx_t * +hicn_hs_input_lookup_buffer (vlib_buffer_t * b, u8 thread_index, u32 * error, + u8 is_ip4) +{ + hicn_hs_ctx_t *ctx = 0; + hicn_header_t *hicn; + hicn_hs_buffer_t *buffer; + u32 ctx_index; + int ret; + u8 *packet_buffer; + u32 seq_number; + + hicn = hicn_buffer_hdr (b); + buffer = hicn_hs_buffer (b); + packet_buffer = vlib_buffer_get_current (b); + + buffer->type.l4 = IPPROTO_NONE; + buffer->type.l3 = IPPROTO_NONE; + buffer->type.l2 = packet_buffer[6 + is_ip4 * 3]; + buffer->type.l1 = (!is_ip4) * (IPPROTO_IPV6); + + ret = hicn_ops_vft[buffer->type.l1]->test_packet_is_interest(buffer->type, &hicn->protocol, &buffer->is_interest); + + if (PREDICT_FALSE(ret < 0)) + { + *error = HICN_HS_ERROR_NO_HICN; + return ctx; + } + + if (buffer->is_interest) + { + ctx_index = vnet_buffer (b)->ip.adj_index[VLIB_TX]; + } + else + { + ctx_index = vnet_buffer (b)->ip.adj_index[VLIB_TX]; + hicn_ops_vft[buffer->type.l1]->get_data_name_suffix (buffer->type, &hicn->protocol, &seq_number); + } + + ctx = hicn_hs_get_ctx_by_index(ctx_index, thread_index); + + if (PREDICT_FALSE(!ctx)) + *error = HICN_HS_ERROR_WRONG_THREAD; + + buffer->seq_number = seq_number; + buffer->is_ip4 = is_ip4; + + return ctx; +} + +static inline void +hicn_hs_input_dispatch_buffer (hicn_hs_main_t * hm, hicn_hs_ctx_t * ctx, + vlib_buffer_t * b, u16 * next, + vlib_node_runtime_t * error_node) +{ + u32 error; + hicn_hs_buffer_t *buffer = hicn_hs_buffer (b); + *next = hm->dispatch_table[buffer->is_interest].next; + error = hm->dispatch_table[buffer->is_interest].error; + b->error = error_node->errors[error]; +} + +always_inline void +hicn_hs_input_set_error_next (hicn_hs_main_t * tm, u16 * next, u32 * error, u8 is_ip4) +{ + *next = HICN_HS_INPUT_NEXT_DROP; +} + +always_inline uword +hicn_hs_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame, u8 is_ip4) +{ + u32 n_left_from, *from, thread_index = vm->thread_index; + hicn_hs_main_t *hm = hicn_hs_get_main (); + vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b; + u16 nexts[VLIB_FRAME_SIZE], *next; + vlib_node_runtime_t *error_node; + +// tcp_set_time_now (tcp_get_worker (thread_index)); + + error_node = vlib_node_get_runtime (vm, is_ip4 ? hicn_hs_input4_node.index : hicn_hs_input6_node.index); + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + vlib_get_buffers (vm, from, bufs, n_left_from); + + b = bufs; + next = nexts; + + while (n_left_from >= 4) + { + u32 error0 = HICN_HS_ERROR_NO_CONTEXT, error1 = HICN_HS_ERROR_NO_CONTEXT; + hicn_hs_ctx_t *ctx0, *ctx1; + + { + vlib_prefetch_buffer_header (b[2], STORE); + CLIB_PREFETCH (b[2]->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD); + + vlib_prefetch_buffer_header (b[3], STORE); + CLIB_PREFETCH (b[3]->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD); + } + + next[0] = next[1] = HICN_HS_INPUT_NEXT_DROP; + + ctx0 = hicn_hs_input_lookup_buffer (b[0], thread_index, &error0, is_ip4); + ctx1 = hicn_hs_input_lookup_buffer (b[1], thread_index, &error1, is_ip4); + + if (PREDICT_TRUE (!ctx0 + !ctx1 == 0)) + { + hicn_hs_input_dispatch_buffer (hm, ctx0, b[0], &next[0], error_node); + hicn_hs_input_dispatch_buffer (hm, ctx1, b[1], &next[1], error_node); + } + else + { + if (PREDICT_TRUE (ctx0 != 0)) + { + hicn_hs_input_dispatch_buffer (hm, ctx0, b[0], &next[0], error_node); + } + else + { + hicn_hs_input_set_error_next (hm, &next[0], &error0, is_ip4); + b[0]->error = error_node->errors[error0]; + } + + if (PREDICT_TRUE (ctx1 != 0)) + { + hicn_hs_input_dispatch_buffer (hm, ctx1, b[1], &next[1], error_node); + } + else + { + hicn_hs_input_set_error_next (hm, &next[1], &error1, is_ip4); + b[1]->error = error_node->errors[error1]; + } + } + + b += 2; + next += 2; + n_left_from -= 2; + } + while (n_left_from > 0) + { + hicn_hs_ctx_t *ctx0; + u32 error0 = HICN_HS_ERROR_NO_CONTEXT; + + if (n_left_from > 1) + { + vlib_prefetch_buffer_header (b[1], STORE); + CLIB_PREFETCH (b[1]->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD); + } + + next[0] = HICN_HS_INPUT_NEXT_DROP; + ctx0 = hicn_hs_input_lookup_buffer (b[0], thread_index, &error0, is_ip4); + if (PREDICT_TRUE (ctx0 != 0)) + { + hicn_hs_input_dispatch_buffer (hm, ctx0, b[0], &next[0], error_node); + } + else + { + hicn_hs_input_set_error_next (hm, &next[0], &error0, is_ip4); + b[0]->error = error_node->errors[error0]; + } + + b += 1; + next += 1; + n_left_from -= 1; + } + + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE)) + hicn_hs_input_trace_frame (vm, node, bufs, frame->n_vectors, is_ip4); + + vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors); + return frame->n_vectors; +} + +static uword +hicn_hs_input_data (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + u32 n_left_from, *from, *first_buffer; + u32 thread_index = vm->thread_index; + vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b; + u32 node_index = hicn_hs_input_data_node.index; + + from = first_buffer = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + vlib_get_buffers (vm, from, bufs, n_left_from); + + b = bufs; + + hicn_hs_ctx_t *ctx0 = 0; + + while (n_left_from >= 4) + { + u32 ctxi0, ctxi1; + hicn_hs_ctx_t *ctx1; + + { + vlib_prefetch_buffer_header (b[2], STORE); + CLIB_PREFETCH (b[2]->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD); + + vlib_prefetch_buffer_header (b[3], STORE); + CLIB_PREFETCH (b[3]->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD); + } + + // ctxi0 = vnet_buffer (b[0])->ip.adj_index[VLIB_TX]; + ctxi0 = hicn_hs_buffer (b[0])->ctx_index; + ctx0 = hicn_hs_get_ctx_by_index(ctxi0, thread_index); + // ctxi1 = vnet_buffer (b[1])->ip.adj_index[VLIB_TX]; + ctxi1 = hicn_hs_buffer (b[1])->ctx_index; + ctx1 = hicn_hs_get_ctx_by_index(ctxi1, thread_index); + + ASSERT (ctx0 && ctx1); + + hicn_hs_process_incoming_data (ctx0, b[0]); + hicn_hs_process_incoming_data (ctx1, b[1]); + + b += 2; + n_left_from -= 2; + } + + while (n_left_from > 0) + { + + u32 ctxi0; + + // ctxi0 = vnet_buffer (b[0])->ip.adj_index[VLIB_TX]; + ctxi0 = hicn_hs_buffer (b[0])->ctx_index; + ctx0 = hicn_hs_get_ctx_by_index(ctxi0, thread_index); + + ASSERT (ctx0); + + hicn_hs_process_incoming_data (ctx0, b[0]); + + b += 1; + n_left_from -= 1; + } + + hicn_hs_update_transport (ctx0, from_frame->n_vectors); + +// vlib_buffer_free (vm, first_buffer, from_frame->n_vectors); + vlib_node_increment_counter (vm, node_index, HICN_HS_ERROR_PACKETS_SENT, from_frame->n_vectors); + return from_frame->n_vectors; +} + +static uword +hicn_hs_input_interest (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + u32 n_left_from, *from, *first_buffer; + u32 thread_index = vm->thread_index; + u32 ctx_index; + + u32 node_index = hicn_hs_input_interest_node.index; + + from = first_buffer = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + + while (n_left_from > 0) + { + u32 bi, CLIB_UNUSED(error) = HICN_HS_ERROR_NONE; + hicn_hs_ctx_t *ctx; + vlib_buffer_t *b; + + bi = from[0]; + from += 1; + n_left_from -= 1; + + b = vlib_get_buffer (vm, bi); + ctx_index = vnet_buffer (b)->ip.adj_index[VLIB_TX]; + ctx = hicn_hs_get_ctx_by_index(ctx_index, thread_index); + hicn_hs_process_incoming_interest(ctx, b); + } + + vlib_node_increment_counter (vm, node_index, HICN_HS_ERROR_PACKETS_SENT, from_frame->n_vectors); + return from_frame->n_vectors; +} + +static uword +hicn_hs_input4 (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return hicn_hs_input_inline (vm, node, frame, 1); +} + +static uword +hicn_hs_input6 (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return hicn_hs_input_inline (vm, node, frame, 0); +} + +/* *INDENT-OFF* */ + +VLIB_REGISTER_NODE (hicn_hs_input_interest_node) = +{ + .function = hicn_hs_input_interest, + .name = HICN_HS_INPUT_INTEREST_NODE_NAME, + .vector_size = sizeof (u32), + .format_trace = format_hicn_hs_input_interest_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = HICN_HS_N_ERROR, + .error_strings = hicn_hs_error_strings, + .n_next_nodes = 0, +}; + +VLIB_REGISTER_NODE (hicn_hs_input_data_node) = +{ + .function = hicn_hs_input_data, + .name = HICN_HS_INPUT_DATA_NODE_NAME, + .vector_size = sizeof (u32), + .format_trace = format_hicn_hs_input_data_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = HICN_HS_N_ERROR, + .error_strings = hicn_hs_error_strings, + .n_next_nodes = 0, +}; + +VLIB_REGISTER_NODE (hicn_hs_input4_node) = +{ + .function = hicn_hs_input4, + .name = HICN_HS_INPUT4_NODE_NAME, + .vector_size = sizeof (u32), + .format_trace = format_hicn_hs_input4_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = HICN_HS_N_ERROR, + .error_strings = hicn_hs_error_strings, + .n_next_nodes = HICN_HS_INPUT_N_NEXT, + .next_nodes = + { +#define _(s,n) [HICN_HS_INPUT_NEXT_##s] = n, + foreach_hicn_hs_input_next4 +#undef _ + }, +}; + +VLIB_REGISTER_NODE (hicn_hs_input6_node) = +{ + .function = hicn_hs_input6, + .name = HICN_HS_INPUT6_NODE_NAME, + .vector_size = sizeof (u32), + .format_trace = format_hicn_hs_input6_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = HICN_HS_N_ERROR, + .error_strings = hicn_hs_error_strings, + .n_next_nodes = HICN_HS_INPUT_N_NEXT, + .next_nodes = + { +#define _(s,n) [HICN_HS_INPUT_NEXT_##s] = n, + foreach_hicn_hs_input_next6 +#undef _ + }, +}; + +/* *INDENT-ON* */ + +static void +hicn_hs_dispatch_table_init (hicn_hs_main_t * tm) +{ + int i; + for (i = 0; i < ARRAY_LEN (tm->dispatch_table); i++) + { + tm->dispatch_table[i].next = HICN_HS_INPUT_NEXT_DROP; + tm->dispatch_table[i].error = HICN_HS_ERROR_DISPATCH; + } + +#define _(t,n,e) \ +do { \ + tm->dispatch_table[HICN_HS_##t].next = (n); \ + tm->dispatch_table[HICN_HS_##t].error = (e); \ +} while (0) + + _ (INTEREST, HICN_HS_INPUT_NEXT_INTEREST, HICN_HS_ERROR_NONE); + _ (DATA, HICN_HS_INPUT_NEXT_DATA, HICN_HS_ERROR_NONE); + +#undef _ +} + +static clib_error_t * +hicn_hs_input_init (vlib_main_t * vm) +{ + hicn_hs_main_t *hm = hicn_hs_get_main (); + + /* Initialize dispatch table. */ + hicn_hs_dispatch_table_init (hm); + + return 0; +} + +VLIB_INIT_FUNCTION (hicn_hs_input_init); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/host_stack/output_node.c b/hicn-plugin/src/host_stack/output_node.c new file mode 100644 index 000000000..8e5f1e307 --- /dev/null +++ b/hicn-plugin/src/host_stack/output_node.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2020 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 "host_stack.h" +#include "inlines.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +typedef enum _hicn_hs_output_next +{ + HICN_HS_OUTPUT_NEXT_IP_LOOKUP, + HICN_HS_OUTPUT_NEXT_NO_FLUSH, + HICN_HS_OUTPUT_N_NEXT +} hicn_hs_output_next_t; + +/** + * Next nodes. + */ +#define foreach_hicn_hs_output4_next \ + _ (IP_LOOKUP, "ip4-lookup") \ + _ (NO_FLUSH, "hicn_hs-no-flush") +// _ (DROP, "ip4-drop") + + +#define foreach_hicn_hs_output6_next \ + _ (IP_LOOKUP, "ip6-lookup") \ + _ (NO_FLUSH, "hicn_hs-no-flush") +// _ (DROP, "ip6-drop") + + +typedef enum +{ +#define _(s, n) HICN_HS_OUTPUT4_NEXT_##s, + foreach_hicn_hs_output4_next +#undef _ + HICN_HS_OUTPUT4_N_NEXT, +} hicn_hs_output4_next_t; + +typedef enum +{ +#define _(s, n) HICN_HS_OUTPUT6_NEXT_##s, + foreach_hicn_hs_output6_next +#undef _ + HICN_HS_OUTPUT6_N_NEXT, +} hicn_hs_output6_next_t; + +typedef struct +{ + u32 next_index; + hicn_name_t name; +} hicn_hs_output_trace_t; + +always_inline u8 * +format_hicn_hs_output_trace_i (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 *); + hicn_hs_output_trace_t *t = va_arg (*args, hicn_hs_output_trace_t *); + char name[64]; + u32 indent = format_get_indent (s); + + hicn_name_ntop(&t->name, name, 64); + s = format (s, "hicn_hs_output: next-index %d", t->next_index); + s = format (s, "\n%Upacket: name %s", format_white_space, indent + 2, + name); + return s; +} + +static u8 * +format_hicn_hs_output4_trace (u8 * s, va_list * args) +{ + return format_hicn_hs_output_trace_i(s, args); +} + +static u8 * +format_hicn_hs_output6_trace (u8 * s, va_list * args) +{ + return format_hicn_hs_output_trace_i(s, args); +} + +static_always_inline void +hicn_hs_trace_buffer (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_buffer_t * b, u32 next, uword * n_tracep) +{ + VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b); + + if (PREDICT_TRUE (b != 0)) + { + hicn_hs_output_trace_t *tr; + vlib_trace_buffer (vm, node, next, b, /* follow_chain */ 0); + vlib_set_trace_count (vm, node, --(*n_tracep)); + tr = vlib_add_trace (vm, node, b, sizeof (*tr)); + tr->next_index = next; +// hicn_interest_get_name(HF_INET6_TCP, +// (const hicn_header_t *)vlib_buffer_get_current(b), +// &tr->name); + } +} + +always_inline uword +hicn_hs_output_inline (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame, int is_ip4) +{ + u32 n_left_from, *from, thread_index = vm->thread_index; + vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b; + u16 nexts[VLIB_FRAME_SIZE], *next; + + uword n_trace = vlib_get_trace_count (vm, node); + + u32 node_index = is_ip4 ? hicn_hs_output4_node.index : hicn_hs_output6_node.index; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + + vlib_get_buffers (vm, from, bufs, n_left_from); + b = bufs; + next = nexts; + + while (n_left_from >= 4) + { + hicn_hs_ctx_t *hc0, *hc1; + u8 flush0, flush1; + + { + vlib_prefetch_buffer_header (b[2], STORE); + CLIB_PREFETCH (b[2]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE); + + vlib_prefetch_buffer_header (b[3], STORE); + CLIB_PREFETCH (b[3]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE); + } + + hc0 = hicn_hs_get_ctx_by_index (hicn_hs_buffer (b[0])->ctx_index, thread_index); + hc1 = hicn_hs_get_ctx_by_index (hicn_hs_buffer (b[1])->ctx_index, thread_index); + flush0 = hicn_hs_buffer(b[0])->flush; + flush1 = hicn_hs_buffer(b[1])->flush; + + ASSERT (hc0 && hc1); + + vnet_buffer (b[0])->sw_if_index[VLIB_TX] = hc0->c_fib_index; + vnet_buffer (b[0])->sw_if_index[VLIB_RX] = 0; + next[0] = !flush0; + + vnet_buffer (b[1])->sw_if_index[VLIB_TX] = hc1->c_fib_index; + vnet_buffer (b[1])->sw_if_index[VLIB_RX] = 0; + next[1] = !flush1; + + if (PREDICT_FALSE (n_trace > 0)) + { + hicn_hs_trace_buffer (vm, node, b[0], next[0], &n_trace); + if (PREDICT_FALSE (n_trace > 0)) + hicn_hs_trace_buffer (vm, node, b[1], next[1], &n_trace); + } + + b += 2; + n_left_from -= 2; + next += 2; + } + while (n_left_from > 0) + { + hicn_hs_ctx_t *hc0; + u8 flush0; + + if (n_left_from > 1) + { + vlib_prefetch_buffer_header (b[1], STORE); + CLIB_PREFETCH (b[1]->data, 2 * CLIB_CACHE_LINE_BYTES, STORE); + } + + hc0 = hicn_hs_get_ctx_by_index (hicn_hs_buffer (b[0])->ctx_index, thread_index); + flush0 = hicn_hs_buffer(b[0])->flush; + + ASSERT (hc0); + + vnet_buffer (b[0])->sw_if_index[VLIB_TX] = hc0->c_fib_index; + vnet_buffer (b[0])->sw_if_index[VLIB_RX] = 0; + next[0] = !flush0; + + if (PREDICT_FALSE (n_trace > 0)) + hicn_hs_trace_buffer (vm, node, b[0], next[0], &n_trace); + + b += 1; + n_left_from -= 1; + next += 1; + } + + vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors); + vlib_node_increment_counter (vm, node_index, HICN_HS_ERROR_PACKETS_SENT, frame->n_vectors); + + return frame->n_vectors; +} + +static uword +hicn_hs_output4_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return hicn_hs_output_inline (vm, node, frame, 1); +} + +static uword +hicn_hs_output6_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return hicn_hs_output_inline (vm, node, frame, 0); +} + +static uword +hicn_hs_no_flush_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return frame->n_vectors; +} + +VLIB_REGISTER_NODE (hicn_hs_no_flush_node) = { + .function = hicn_hs_no_flush_node_fn, + .name = "hicn_hs-no-flush", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = HICN_HS_N_ERROR, + .error_strings = hicn_hs_error_strings, + .n_next_nodes = 0, + .next_nodes = {}, +}; + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn_hs_output4_node) = { + .function = hicn_hs_output4_node_fn, + .name = HICN_HS_OUTPUT4_NODE_NAME, + .vector_size = sizeof (u32), + .flags = VLIB_NODE_FLAG_TRACE_SUPPORTED, + .format_trace = format_hicn_hs_output4_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = HICN_HS_N_ERROR, + .error_strings = hicn_hs_error_strings, + .n_next_nodes = HICN_HS_OUTPUT4_N_NEXT, + .next_nodes = { +#define _(s, n) [HICN_HS_OUTPUT4_NEXT_##s] = n, + foreach_hicn_hs_output4_next +#undef _ + }, +}; + +VLIB_REGISTER_NODE (hicn_hs_output6_node) = { + .function = hicn_hs_output6_node_fn, + .name = HICN_HS_OUTPUT6_NODE_NAME, + .vector_size = sizeof (u32), + .flags = VLIB_NODE_FLAG_TRACE_SUPPORTED, + .format_trace = format_hicn_hs_output6_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = HICN_HS_N_ERROR, + .error_strings = hicn_hs_error_strings, + .n_next_nodes = HICN_HS_OUTPUT6_N_NEXT, + .next_nodes = { +#define _(s, n) [HICN_HS_OUTPUT6_NEXT_##s] = n, + foreach_hicn_hs_output6_next +#undef _ + }, +}; + +/* *INDENT-ON* */ \ No newline at end of file diff --git a/hicn-plugin/src/host_stack/producer_dpo.c b/hicn-plugin/src/host_stack/producer_dpo.c new file mode 100644 index 000000000..c7b77705d --- /dev/null +++ b/hicn-plugin/src/host_stack/producer_dpo.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020 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 "producer_dpo.h" +#include "host_stack.h" + +#include +#include +#include +#include + +dpo_type_t hicn_hs_dpo_type; + +const static char *const hicn_hs_prod_dpo4_nodes[] = { + "hicn_hs-input4", + NULL, +}; + +const static char *const hicn_hs_prod_dpo6_nodes[] = { + "hicn_hs-input6", + NULL, +}; + +const static char *const *const hicn_hs_prod_dpo_nodes[DPO_PROTO_NUM] = { + [DPO_PROTO_IP4] = hicn_hs_prod_dpo4_nodes, + [DPO_PROTO_IP6] = hicn_hs_prod_dpo6_nodes +}; + +void hicn_hs_prod_dpo_lock(dpo_id_t *dpo) +{ + return; +} + +void hicn_hs_prod_dpo_unlock(dpo_id_t *dpo) +{ + return; +} + +u8 *format_hicn_hs_prod_dpo (u8 * s, va_list * args) +{ + return s; +} + +const static dpo_vft_t hicn_hs_prod_dpo_vft = { + .dv_lock = hicn_hs_prod_dpo_lock, + .dv_unlock = hicn_hs_prod_dpo_unlock, + .dv_format = format_hicn_hs_prod_dpo, +}; + +/** + * Register the new DPO type. + */ +void hicn_hs_dpo_module_init(void) +{ + hicn_hs_dpo_type = dpo_register_new_type (&hicn_hs_prod_dpo_vft, hicn_hs_prod_dpo_nodes); +} + +int dpo_is_hicn_hs(const dpo_id_t *dpo) +{ + return dpo->dpoi_type == hicn_hs_dpo_type; +} + +u32 hicn_hs_dpo_create(u32 hicn_hs_ctx_idx, u8 is_ip4, dpo_id_t *dpo) +{ + dpo->dpoi_type = DPO_FIRST; + dpo->dpoi_proto = DPO_PROTO_NONE; + dpo->dpoi_index = INDEX_INVALID; + dpo->dpoi_next_node = 0; + + u16 next_node = is_ip4 ? hicn_hs_input4_node.index : hicn_hs_input6_node.index; + + index_t dpoi_index = hicn_hs_ctx_idx; + dpo_set(dpo, hicn_hs_dpo_type, is_ip4 ? DPO_PROTO_IP4 : DPO_PROTO_IP6, dpoi_index); + dpo->dpoi_next_node = next_node; + dpo_unlock (dpo); + + return HICN_HS_ERROR_NONE; +} diff --git a/hicn-plugin/src/host_stack/producer_dpo.h b/hicn-plugin/src/host_stack/producer_dpo.h new file mode 100644 index 000000000..ac748589b --- /dev/null +++ b/hicn-plugin/src/host_stack/producer_dpo.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020 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. + */ + +/** + * @brief The hicn_hs dpo. It will store the 2 hicn_hs input nodes, + * altogether with the index of the corresponding hicn socket, in order + * to avoid a double lookup. + */ + +#ifndef __HICN_HS_DPO_H__ +#define __HICN_HS_DPO_H__ + +#include + +extern dpo_type_t hicn_hs_dpo_type; + +int dpo_is_hicn_hs(const dpo_id_t *dpo); +u32 hicn_hs_dpo_create(u32 hicn_hs_ctx_idx, u8 is_ip4, dpo_id_t *dpo); +void hicn_hs_dpo_module_init(void); + +#endif /* __HICN_HS_DPO_H__ */ \ No newline at end of file diff --git a/hicn-plugin/src/host_stack/proto.h b/hicn-plugin/src/host_stack/proto.h new file mode 100644 index 000000000..0c89317a6 --- /dev/null +++ b/hicn-plugin/src/host_stack/proto.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019 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 __included_hicn_hs_proto__ +#define __included_hicn_hs_proto__ + +#define PROTO_DATA_SIZE 32 + +typedef enum hicn_hs_proto_event_ +{ + PROTO_N_EVENT, +} hicn_hs_proto_event_t; + +struct hicn_hs_proto_ +{ + u32 (*init) (hicn_hs_ctx_t * hc); + u32 (*rcv_data) (hicn_hs_ctx_t * hc); + u32 (*rcv_interest) (hicn_hs_ctx_t * hc); + u32 (*on_interest_timeout) (hicn_hs_ctx_t *hc); + u32 (*event) (hicn_hs_ctx_t *hc, hicn_hs_proto_event_t event); + u32 (*next_seq_number) (hicn_hs_ctx_t *hc); + u8 proto_data[PROTO_DATA_SIZE]; +}; + +typedef struct hicn_hs_proto_ hicn_hs_proto_t; + +always_inline void * +hicn_hs_proto_data(hicn_hs_proto_t *proto) +{ + return (void*)(proto->proto_data); +} + +always_inline u32 +hicn_hs_proto_init (); + +#enfif /* __included_hicn_hs_proto__ */ \ No newline at end of file diff --git a/hicn-plugin/src/host_stack/route.c b/hicn-plugin/src/host_stack/route.c new file mode 100644 index 000000000..5b42bea26 --- /dev/null +++ b/hicn-plugin/src/host_stack/route.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2020 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 "host_stack.h" +#include "route.h" + +#include +#include +#include +#include +#include +#include +#include + +#define FIB_SOURCE_HICN_HS 0x04 //Right after the FIB_SOURCE_INTERFACE priority +#define HICN_HS_FIB_TABLE 0 + +fib_source_t hicn_hs_fib_src; + +void +hicn_hs_route_init () +{ + hicn_hs_fib_src = fib_source_allocate ("hicn_hs", FIB_SOURCE_HICN_HS, FIB_SOURCE_BH_API); +} + +always_inline int +hicn_route_get_dpo (const fib_prefix_t * prefix, + const dpo_id_t ** hicn_dpo, u32 * fib_index) +{ + //fib_prefix_t fib_pfx; + const dpo_id_t *load_balance_dpo_id; + const dpo_id_t *former_dpo_id; + int found = 0, ret = HICN_HS_ERROR_ROUTE_NOT_FOUND; + fib_node_index_t fib_entry_index; + + /* Check if the route already exist in the fib */ + /* + * ASSUMPTION: we use table 0 which is the default table and it is + * already existing and locked + */ + *fib_index = fib_table_find_or_create_and_lock (prefix->fp_proto, + HICN_HS_FIB_TABLE, + hicn_hs_fib_src); + fib_entry_index = fib_table_lookup_exact_match (*fib_index, prefix); + + if (fib_entry_index != FIB_NODE_INDEX_INVALID) + { + /* Route already existing. We need to update the dpo. */ + load_balance_dpo_id = + fib_entry_contribute_ip_forwarding (fib_entry_index); + + /* The dpo is not a load balance dpo as expected */ + if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) + ret = HICN_HS_ERROR_ROUTE_NO_LB_DPO; + else + { + /* former_dpo_id is a load_balance dpo */ + load_balance_t *lb = + load_balance_get (load_balance_dpo_id->dpoi_index); + + /* FIB entry exists but there is no hicn_hs dpo. */ + ret = HICN_HS_ERROR_ROUTE_DPO_NO_HICN; + for (int i = 0; i < lb->lb_n_buckets && !found; i++) + { + former_dpo_id = load_balance_get_bucket_i (lb, i); + + if (dpo_is_hicn_hs (former_dpo_id)) + { + *hicn_dpo = former_dpo_id; + ret = HICN_HS_ERROR_NONE; + found = 1; + } + } + } + } + /* + * Remove the lock from the table. We keep one lock per route, not + * per dpo + */ + fib_table_unlock (*fib_index, prefix->fp_proto, hicn_hs_fib_src); + + return ret; +} + +/* Add a new route for a name prefix */ +always_inline +int hicn_hs_route_add_flags (const fib_prefix_t * prefix, const dpo_id_t *dpo, fib_entry_flag_t flags) +{ + CLIB_UNUSED(vlib_main_t *vm) = vlib_get_main (); + int ret = HICN_HS_ERROR_NONE; + u32 fib_index; + const dpo_id_t *_dpo; + + ret = hicn_route_get_dpo (prefix, &_dpo, &fib_index); + + if (ret == HICN_HS_ERROR_ROUTE_NOT_FOUND) + { + /* Here is where we create the "via" like route */ + /* + * For the moment we use the global one the prefix you want + * to match Neale suggested -- FIB_SOURCE_HICN the client + * that is adding them -- no easy explanation at this time… + */ + fib_node_index_t new_fib_node_index = + fib_table_entry_special_dpo_add (fib_index, + prefix, + hicn_hs_fib_src, + flags, + dpo); + + /* We added a route, therefore add one lock to the table */ + fib_table_lock (fib_index, prefix->fp_proto, hicn_hs_fib_src); + + ret = + (new_fib_node_index != + FIB_NODE_INDEX_INVALID) ? HICN_HS_ERROR_NONE : + HICN_HS_ERROR_ROUTE_NO_INSERT; + } + + return ret; +} + +int +hicn_hs_route_add (const fib_prefix_t * prefix, const dpo_id_t *dpo) +{ + return hicn_hs_route_add_flags(prefix, dpo, (FIB_ENTRY_FLAG_EXCLUSIVE | + FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT)); +} + +clib_error_t * +hicn_hs_set_local_prefix(const fib_prefix_t * prefix) +{ + clib_error_t * ret = 0; + int rv; + const dpo_id_t *drop_dpo = drop_dpo_get(prefix->fp_proto == FIB_PROTOCOL_IP4 ? DPO_PROTO_IP4 : DPO_PROTO_IP6); + rv = hicn_hs_route_add_flags(prefix, drop_dpo, (FIB_ENTRY_FLAG_EXCLUSIVE | FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT)); + + if (rv) + ret = clib_error_return (0, "Error: %s", hicn_hs_error_strings[rv]); + + return ret; +} + +int +hicn_route_del (fib_prefix_t * prefix) +{ + const dpo_id_t *hicn_dpo_id; + int ret = HICN_HS_ERROR_NONE; + u32 fib_index; + + /* Remove the fib entry only if the dpo is of type hicn */ + ret = hicn_route_get_dpo (prefix, &hicn_dpo_id, &fib_index); + + if (ret == HICN_HS_ERROR_NONE) + { + fib_table_entry_special_remove (HICN_HS_FIB_TABLE, prefix, hicn_hs_fib_src); + + /* + * Remove the lock from the table. We keep one lock per route + */ + fib_table_unlock (fib_index, prefix->fp_proto, hicn_hs_fib_src); + } + + // Remember to remove the lock from the table when removing the entry + return ret; +} \ No newline at end of file diff --git a/hicn-plugin/src/host_stack/route.h b/hicn-plugin/src/host_stack/route.h new file mode 100644 index 000000000..880a34687 --- /dev/null +++ b/hicn-plugin/src/host_stack/route.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 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_HS_ROUTE_H__ +#define __HICN_HS_ROUTE_H__ + +#include +#include + +/* Init the route module */ +void +hicn_hs_route_init (); + +clib_error_t * +hicn_hs_set_local_prefix(const fib_prefix_t * prefix); + +/* Add a new route for a name prefix */ +int +hicn_hs_route_add (const fib_prefix_t * prefix, const dpo_id_t *dpo); + +/* Remove route for a name prefix */ +int +hicn_route_del (fib_prefix_t * prefix); + +#endif /* __HICN_HS_ROUTE_H__ */ diff --git a/hicn-plugin/src/host_stack/test/hicn_hs_client.c b/hicn-plugin/src/host_stack/test/hicn_hs_client.c new file mode 100644 index 000000000..b5f27ee12 --- /dev/null +++ b/hicn-plugin/src/host_stack/test/hicn_hs_client.c @@ -0,0 +1,804 @@ +/* + * hicn_hs_client.c - vpp built-in hicn client + * + * Copyright (c) 2017-2019 by 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 "hicn_hs_client.h" +#include "../host_stack.h" + +hicn_client_main_t hicn_client_main; + +#define HICN_CLIENT_DBG (0) +#define DBG(_fmt, _args...) \ + if (HICN_CLIENT_DBG) \ + clib_warning (_fmt, ##_args) + +#define ec_cli_output(_fmt, _args...) \ + if (!hcm->no_output) \ + vlib_cli_output(vm, _fmt, ##_args) + +f64 t0; + +static void +signal_evt_to_cli_i (int *code) +{ + hicn_client_main_t *hcm = &hicn_client_main; + ASSERT (vlib_get_thread_index () == 0); + vlib_process_signal_event (hcm->vlib_main, hcm->cli_node_index, *code, 0); +} + +static void +signal_evt_to_cli (int code) +{ + if (vlib_get_thread_index () != 0) + vl_api_rpc_call_main_thread (signal_evt_to_cli_i, (u8 *) & code, + sizeof (code)); + else + signal_evt_to_cli_i (&code); +} + +static void +receive_data_chunk (hicn_client_main_t * hcm, eclient_session_t * s) +{ + svm_fifo_t *rx_fifo = s->data.rx_fifo; + u32 thread_index = vlib_get_thread_index (); + int n_read, i; + + if (hcm->test_bytes) + { + if (!hcm->is_dgram) + n_read = app_recv_stream (&s->data, hcm->rx_buf[thread_index], + vec_len (hcm->rx_buf[thread_index])); + else + n_read = app_recv_dgram (&s->data, hcm->rx_buf[thread_index], + vec_len (hcm->rx_buf[thread_index])); + } + else + { + n_read = svm_fifo_max_dequeue_cons (rx_fifo); + svm_fifo_dequeue_drop (rx_fifo, n_read); + } + + if (n_read > 0) + { + if (HICN_CLIENT_DBG) + { + /* *INDENT-OFF* */ + ELOG_TYPE_DECLARE (e) = + { + .format = "rx-deq: %d bytes", + .format_args = "i4", + }; + /* *INDENT-ON* */ + struct + { + u32 data[1]; + } *ed; + ed = ELOG_DATA (&vlib_global_main.elog_main, e); + ed->data[0] = n_read; + } + + if (hcm->test_bytes) + { + for (i = 0; i < n_read; i++) + { + if (hcm->rx_buf[thread_index][i] + != ((s->bytes_received + i) & 0xff)) + { + clib_warning ("read %d error at byte %lld, 0x%x not 0x%x", + n_read, s->bytes_received + i, + hcm->rx_buf[thread_index][i], + ((s->bytes_received + i) & 0xff)); + hcm->test_failed = 1; + } + } + } + vlib_main_t *vm = vlib_get_main(); + hcm->test_end_time = vlib_time_now (vm); + f64 delta = hcm->test_end_time - hcm->test_start_time; + + ec_cli_output ("Throughput (%d, %.20f): %.2f b/s", n_read, delta, ((f64)(n_read)) / delta); + + s->bytes_to_receive -= n_read; + s->bytes_received += n_read; + } +} + +// static uword +// hicn_client_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, +// vlib_frame_t * frame) +// { +// hicns_client_main_t *hcm = &hicn_client_main; +// int my_thread_index = vlib_get_thread_index (); +// eclient_session_t *sp; +// int i; +// int delete_session; +// u32 *connection_indices; +// u32 *connections_this_batch; +// u32 nconnections_this_batch; + +// connection_indices = hcm->connection_index_by_thread[my_thread_index]; +// connections_this_batch = +// hcm->connections_this_batch_by_thread[my_thread_index]; + +// if ((hcm->run_test != HICN_CLIENT_RUNNING) || +// ((vec_len (connection_indices) == 0) +// && vec_len (connections_this_batch) == 0)) +// return 0; + +// /* Grab another pile of connections */ +// if (PREDICT_FALSE (vec_len (connections_this_batch) == 0)) +// { +// nconnections_this_batch = +// clib_min (hcm->connections_per_batch, vec_len (connection_indices)); + +// ASSERT (nconnections_this_batch > 0); +// vec_validate (connections_this_batch, nconnections_this_batch - 1); +// clib_memcpy_fast (connections_this_batch, +// connection_indices + vec_len (connection_indices) +// - nconnections_this_batch, +// nconnections_this_batch * sizeof (u32)); +// _vec_len (connection_indices) -= nconnections_this_batch; +// } + +// if (PREDICT_FALSE (hcm->prev_conns != hcm->connections_per_batch +// && hcm->prev_conns == vec_len (connections_this_batch))) +// { +// hcm->repeats++; +// hcm->prev_conns = vec_len (connections_this_batch); +// if (hcm->repeats == 500000) +// { +// clib_warning ("stuck clients"); +// } +// } +// else +// { +// hcm->prev_conns = vec_len (connections_this_batch); +// hcm->repeats = 0; +// } + +// for (i = 0; i < vec_len (connections_this_batch); i++) +// { +// delete_session = 1; + +// sp = pool_elt_at_index (hcm->sessions, connections_this_batch[i]); + +// if (sp->bytes_to_send > 0) +// { +// send_data_chunk (hcm, sp); +// delete_session = 0; +// } +// if (sp->bytes_to_receive > 0) +// { +// delete_session = 0; +// } +// if (PREDICT_FALSE (delete_session == 1)) +// { +// session_t *s; + +// clib_atomic_fetch_add (&hcm->tx_total, sp->bytes_sent); +// clib_atomic_fetch_add (&hcm->rx_total, sp->bytes_received); +// s = session_get_from_handle_if_valid (sp->vpp_session_handle); + +// if (s) +// { +// vnet_disconnect_args_t _a, *a = &_a; +// a->handle = session_handle (s); +// a->app_index = hcm->app_index; +// vnet_disconnect_session (a); + +// vec_delete (connections_this_batch, 1, i); +// i--; +// clib_atomic_fetch_add (&hcm->ready_connections, -1); +// } +// else +// { +// clib_warning ("session AWOL?"); +// vec_delete (connections_this_batch, 1, i); +// } + +// /* Kick the debug CLI process */ +// if (hcm->ready_connections == 0) +// { +// signal_evt_to_cli (2); +// } +// } +// } + +// hcm->connection_index_by_thread[my_thread_index] = connection_indices; +// hcm->connections_this_batch_by_thread[my_thread_index] = +// connections_this_batch; +// return 0; +// } + +// /* *INDENT-OFF* */ +// VLIB_REGISTER_NODE (hicn_clients_node) = +// { +// .function = hicn_client_node_fn, +// .name = "hicn-client", +// .type = VLIB_NODE_TYPE_INPUT, +// .state = VLIB_NODE_STATE_DISABLED, +// }; +// /* *INDENT-ON* */ + +static int +create_api_loopback (hicn_client_main_t * hcm) +{ + api_main_t *am = vlibapi_get_main (); + vl_shmem_hdr_t *shmem_hdr; + + shmem_hdr = am->shmem_hdr; + hcm->vl_input_queue = shmem_hdr->vl_input_queue; + hcm->my_client_index = vl_api_memclnt_create_internal ("hicn_client", + hcm->vl_input_queue); + return 0; +} + +static int +hicn_client_init (vlib_main_t * vm) +{ + hicn_client_main_t *hcm = &hicn_client_main; + vlib_thread_main_t *vtm = vlib_get_thread_main (); + u32 num_threads; + int i; + + if (create_api_loopback (hcm)) + return -1; + + num_threads = 1 /* main thread */ + vtm->n_threads; + + /* Init test data. Big buffer */ + vec_validate (hcm->connect_test_data, 4 * 1024 * 1024 - 1); + for (i = 0; i < vec_len (hcm->connect_test_data); i++) + hcm->connect_test_data[i] = i & 0xff; + + vec_validate (hcm->rx_buf, num_threads - 1); + for (i = 0; i < num_threads; i++) + vec_validate (hcm->rx_buf[i], vec_len (hcm->connect_test_data) - 1); + + hcm->is_init = 1; + + vec_validate (hcm->connection_index_by_thread, vtm->n_vlib_mains); + vec_validate (hcm->connections_this_batch_by_thread, vtm->n_vlib_mains); + vec_validate (hcm->vpp_event_queue, vtm->n_vlib_mains); + + return 0; +} + +static int +hicn_client_session_connected_callback (u32 app_wrk_index, u32 opaque, + session_t * s, session_error_t code) +{ + hicn_client_main_t *hcm = &hicn_client_main; + eclient_session_t *session; + u32 session_index; + u8 thread_index; + + if (PREDICT_FALSE (hcm->run_test != HICN_CLIENT_STARTING)) + return -1; + + if (code) + { + clib_warning ("connection %d failed!", opaque); + hcm->run_test = HICN_CLIENT_EXITING; + signal_evt_to_cli (-1); + return 0; + } + + thread_index = s->thread_index; + ASSERT (thread_index == vlib_get_thread_index () + || session_transport_service_type (s) == TRANSPORT_SERVICE_CL); + + if (!hcm->vpp_event_queue[thread_index]) + hcm->vpp_event_queue[thread_index] = + session_main_get_vpp_event_queue (thread_index); + + /* + * Setup session + */ + clib_spinlock_lock_if_init (&hcm->sessions_lock); + pool_get (hcm->sessions, session); + clib_spinlock_unlock_if_init (&hcm->sessions_lock); + + clib_memset (session, 0, sizeof (*session)); + session_index = session - hcm->sessions; + session->bytes_to_send = hcm->bytes_to_send; + session->bytes_to_receive = hcm->no_return ? 0ULL : hcm->bytes_to_send; + session->data.rx_fifo = s->rx_fifo; + session->data.rx_fifo->client_session_index = session_index; + session->data.tx_fifo = s->tx_fifo; + session->data.tx_fifo->client_session_index = session_index; + session->data.vpp_evt_q = hcm->vpp_event_queue[thread_index]; + session->vpp_session_handle = session_handle (s); + + if (hcm->is_dgram) + { + transport_connection_t *tc; + tc = session_get_transport (s); + clib_memcpy_fast (&session->data.transport, tc, + sizeof (session->data.transport)); + session->data.is_dgram = 1; + } + + vec_add1 (hcm->connection_index_by_thread[thread_index], session_index); + clib_atomic_fetch_add (&hcm->ready_connections, 1); + if (hcm->ready_connections == hcm->expected_connections) + { + hcm->run_test = HICN_CLIENT_RUNNING; + /* Signal the CLI process that the action is starting... */ + signal_evt_to_cli (1); + } + + return 0; +} + +static void +hicn_client_session_reset_callback (session_t * s) +{ + hicn_client_main_t *hcm = &hicn_client_main; + vnet_disconnect_args_t _a = { 0 }, *a = &_a; + + if (s->session_state == SESSION_STATE_READY) + clib_warning ("Reset active connection %U", format_session, s, 2); + + a->handle = session_handle (s); + a->app_index = hcm->app_index; + vnet_disconnect_session (a); + return; +} + +static int +hicn_client_session_create_callback (session_t * s) +{ + return 0; +} + +static void +hicn_client_session_disconnect_callback (session_t * s) +{ + hicn_client_main_t *hcm = &hicn_client_main; + vnet_disconnect_args_t _a = { 0 }, *a = &_a; + a->handle = session_handle (s); + a->app_index = hcm->app_index; + vnet_disconnect_session (a); + return; +} + +void +hicn_client_session_disconnect (session_t * s) +{ + hicn_client_main_t *hcm = &hicn_client_main; + vnet_disconnect_args_t _a = { 0 }, *a = &_a; + a->handle = session_handle (s); + a->app_index = hcm->app_index; + vnet_disconnect_session (a); +} + +static int +hicn_client_rx_callback (session_t * s) +{ + hicn_client_main_t *hcm = &hicn_client_main; + eclient_session_t *sp; + + if (PREDICT_FALSE (hcm->run_test != HICN_CLIENT_RUNNING)) + { + hicn_client_session_disconnect (s); + return -1; + } + + sp = pool_elt_at_index (hcm->sessions, s->rx_fifo->client_session_index); + receive_data_chunk (hcm, sp); + + if (svm_fifo_max_dequeue_cons (s->rx_fifo)) + { + if (svm_fifo_set_event (s->rx_fifo)) + session_send_io_evt_to_thread (s->rx_fifo, SESSION_IO_EVT_BUILTIN_RX); + } + return 0; +} + +int +hicn_client_add_segment_callback (u32 client_index, u64 segment_handle) +{ + /* New heaps may be added */ + return 0; +} + +/* *INDENT-OFF* */ +static session_cb_vft_t hicn_client = { + .session_reset_callback = hicn_client_session_reset_callback, + .session_connected_callback = hicn_client_session_connected_callback, + .session_accept_callback = hicn_client_session_create_callback, + .session_disconnect_callback = hicn_client_session_disconnect_callback, + .builtin_app_rx_callback = hicn_client_rx_callback, + .add_segment_callback = hicn_client_add_segment_callback +}; +/* *INDENT-ON* */ + +static clib_error_t * +hicn_client_attach (u8 * appns_id, u64 appns_flags, u64 appns_secret) +{ + vnet_app_add_tls_cert_args_t _a_cert, *a_cert = &_a_cert; + vnet_app_add_tls_key_args_t _a_key, *a_key = &_a_key; + u32 prealloc_fifos, segment_size = 256 << 20; + hicn_client_main_t *hcm = &hicn_client_main; + vnet_app_attach_args_t _a, *a = &_a; + u64 options[17]; + int rv; + + clib_memset (a, 0, sizeof (*a)); + clib_memset (options, 0, sizeof (options)); + + a->api_client_index = hcm->my_client_index; + a->session_cb_vft = &hicn_client; + + prealloc_fifos = hcm->prealloc_fifos ? hcm->expected_connections : 1; + + if (hcm->private_segment_size) + segment_size = hcm->private_segment_size; + + options[APP_OPTIONS_ACCEPT_COOKIE] = 0x12345678; + options[APP_OPTIONS_SEGMENT_SIZE] = segment_size; + options[APP_OPTIONS_ADD_SEGMENT_SIZE] = segment_size; + options[APP_OPTIONS_RX_FIFO_SIZE] = hcm->fifo_size; + options[APP_OPTIONS_TX_FIFO_SIZE] = hcm->fifo_size; + options[APP_OPTIONS_PRIVATE_SEGMENT_COUNT] = hcm->private_segment_count; + options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = prealloc_fifos; + options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN; + options[APP_OPTIONS_TLS_ENGINE] = hcm->tls_engine; + options[APP_OPTIONS_PCT_FIRST_ALLOC] = 100; + if (appns_id) + { + options[APP_OPTIONS_FLAGS] |= appns_flags; + options[APP_OPTIONS_NAMESPACE_SECRET] = appns_secret; + } + a->options = options; + a->namespace_id = appns_id; + + if ((rv = vnet_application_attach (a))) + return clib_error_return (0, "attach returned %d", rv); + + hcm->app_index = a->app_index; + + clib_memset (a_cert, 0, sizeof (*a_cert)); + a_cert->app_index = a->app_index; + vec_validate (a_cert->cert, test_srv_crt_rsa_len); + clib_memcpy_fast (a_cert->cert, test_srv_crt_rsa, test_srv_crt_rsa_len); + vnet_app_add_tls_cert (a_cert); + + clib_memset (a_key, 0, sizeof (*a_key)); + a_key->app_index = a->app_index; + vec_validate (a_key->key, test_srv_key_rsa_len); + clib_memcpy_fast (a_key->key, test_srv_key_rsa, test_srv_key_rsa_len); + vnet_app_add_tls_key (a_key); + return 0; +} + +static int +hicn_client_detach () +{ + hicn_client_main_t *hcm = &hicn_client_main; + vnet_app_detach_args_t _da, *da = &_da; + int rv; + + da->app_index = hcm->app_index; + da->api_client_index = ~0; + rv = vnet_application_detach (da); + hcm->test_client_attached = 0; + hcm->app_index = ~0; + return rv; +} + +static void * +hicn_client_thread_fn (void *arg) +{ + return 0; +} + +/** Start a transmit thread */ +int +hicn_client_start_tx_pthread (hicn_client_main_t * hcm) +{ + if (hcm->client_thread_handle == 0) + { + int rv = pthread_create (&hcm->client_thread_handle, + NULL /*attr */ , + hicn_client_thread_fn, 0); + if (rv) + { + hcm->client_thread_handle = 0; + return -1; + } + } + return 0; +} + +clib_error_t * +hicn_client_connect (vlib_main_t * vm, u32 n_clients) +{ + hicn_client_main_t *hcm = &hicn_client_main; + vnet_connect_args_t _a, *a = &_a; + int i, rv; + + clib_memset (a, 0, sizeof (*a)); + + for (i = 0; i < n_clients; i++) + { + a->uri = (char *) hcm->connect_uri; + a->api_context = i; + a->app_index = hcm->app_index; + + vlib_worker_thread_barrier_sync (vm); + if ((rv = vnet_connect_uri (a))) + { + vlib_worker_thread_barrier_release (vm); + return clib_error_return (0, "connect returned: %d", rv); + } + vlib_worker_thread_barrier_release (vm); + + /* Crude pacing for call setups */ + if ((i % 16) == 0) + vlib_process_suspend (vm, 100e-6); + ASSERT (i + 1 >= hcm->ready_connections); + while (i + 1 - hcm->ready_connections > 128) + vlib_process_suspend (vm, 1e-3); + } + + return 0; +} + +static clib_error_t * +hicn_client_command_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + hicn_client_main_t *hcm = &hicn_client_main; + vlib_thread_main_t *thread_main = vlib_get_thread_main (); + u64 total_bytes, appns_flags = 0, appns_secret = 0; + f64 test_timeout = 20.0, syn_timeout = 20.0, delta; + char *default_uri = "hicn://b001::1"; + uword *event_data = 0, event_type; + f64 time_before_connects; + u32 n_clients = 1; + int preallocate_sessions = 0; + char *transfer_type; + clib_error_t *error = 0; + u8 *appns_id = 0; + int i; + session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL; + int rv; + + hcm->bytes_to_send = 8192; + hcm->no_return = 0; + hcm->fifo_size = 128 << 20; + hcm->connections_per_batch = 1000; + hcm->private_segment_count = 0; + hcm->private_segment_size = 0; + hcm->no_output = 0; + hcm->test_bytes = 0; + hcm->test_failed = 0; + hcm->vlib_main = vm; + hcm->tls_engine = CRYPTO_ENGINE_OPENSSL; + hcm->no_copy = 0; + hcm->run_test = HICN_CLIENT_STARTING; + + if (thread_main->n_vlib_mains > 1) + clib_spinlock_init (&hcm->sessions_lock); + vec_free (hcm->connect_uri); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "uri %s", &hcm->connect_uri)) + ; + else + return clib_error_return (0, "failed: unknown input `%U'", + format_unformat_error, input); + } + + /* Store cli process node index for signalling */ + hcm->cli_node_index = + vlib_get_current_process (vm)->node_runtime.node_index; + + if (hcm->is_init == 0) + { + if (hicn_client_init (vm)) + return clib_error_return (0, "failed init"); + } + + + hcm->ready_connections = 0; + hcm->expected_connections = n_clients; + hcm->rx_total = 0; + hcm->tx_total = 0; + + if (!hcm->connect_uri) + { + clib_warning ("No uri provided. Using default: %s", default_uri); + hcm->connect_uri = format (0, "%s%c", default_uri, 0); + } + + vlib_worker_thread_barrier_sync (vm); + vnet_session_enable_disable (vm, 1 /* turn on session and transports */ ); + hicn_hs_enable_disable(vm, 1 /* enable hicn transport */); + vlib_worker_thread_barrier_release (vm); + + if ((rv = parse_uri ((char *) hcm->connect_uri, &sep))) + return clib_error_return (0, "Uri parse error: %d", rv); + hcm->transport_proto = sep.transport_proto; + hcm->is_dgram = (sep.transport_proto == TRANSPORT_PROTO_UDP); + +#if HICN_CLIENT_PTHREAD + hicn_client_start_tx_pthread (); +#endif + + if (hcm->test_client_attached == 0) + { + if ((error = hicn_client_attach (appns_id, appns_flags, appns_secret))) + { + vec_free (appns_id); + clib_error_report (error); + return error; + } + vec_free (appns_id); + } + hcm->test_client_attached = 1; + + /* Turn on the builtin client input nodes */ + for (i = 0; i < thread_main->n_vlib_mains; i++) + vlib_node_set_state (vlib_mains[i], hicn_client_node.index, + VLIB_NODE_STATE_POLLING); + + if (preallocate_sessions) + pool_init_fixed (hcm->sessions, 1.1 * n_clients); + + /* Fire off connect requests */ + time_before_connects = vlib_time_now (vm); + if ((error = hicn_client_connect (vm, n_clients))) + { + goto cleanup; + } + + /* Park until the sessions come up, or ten seconds elapse... */ + vlib_process_wait_for_event_or_clock (vm, syn_timeout); + event_type = vlib_process_get_events (vm, &event_data); + switch (event_type) + { + case ~0: + ec_cli_output ("Timeout with only %d sessions active...", + hcm->ready_connections); + error = clib_error_return (0, "failed: syn timeout with %d sessions", + hcm->ready_connections); + goto cleanup; + + case 1: + delta = vlib_time_now (vm) - time_before_connects; + if (delta != 0.0) + ec_cli_output ("%d three-way handshakes in %.2f seconds %.2f/s", + n_clients, delta, ((f64) n_clients) / delta); + + hcm->test_start_time = vlib_time_now (hcm->vlib_main); + break; + + default: + ec_cli_output ("unexpected event(1): %d", event_type); + error = clib_error_return (0, "failed: unexpected event(1): %d", + event_type); + goto cleanup; + } + + /* Now wait for the sessions to finish... */ + vlib_process_wait_for_event_or_clock (vm, test_timeout); + event_type = vlib_process_get_events (vm, &event_data); + switch (event_type) + { + case ~0: + ec_cli_output ("Timeout with %d sessions still active...", + hcm->ready_connections); + error = clib_error_return (0, "failed: timeout with %d sessions", + hcm->ready_connections); + goto cleanup; + + case 2: + hcm->test_end_time = vlib_time_now (vm); + ec_cli_output ("Test finished at %.6f", hcm->test_end_time); + break; + + default: + ec_cli_output ("unexpected event(2): %d", event_type); + error = clib_error_return (0, "failed: unexpected event(2): %d", + event_type); + goto cleanup; + } + + delta = hcm->test_end_time - hcm->test_start_time; + if (delta != 0.0) + { + total_bytes = (hcm->no_return ? hcm->tx_total : hcm->rx_total); + transfer_type = hcm->no_return ? "half-duplex" : "full-duplex"; + ec_cli_output ("%lld bytes (%lld mbytes, %lld gbytes) in %.2f seconds", + total_bytes, total_bytes / (1ULL << 20), + total_bytes / (1ULL << 30), delta); + ec_cli_output ("%.2f bytes/second %s", ((f64) total_bytes) / (delta), + transfer_type); + ec_cli_output ("%.4f gbit/second %s", + (((f64) total_bytes * 8.0) / delta / 1e9), + transfer_type); + } + else + { + ec_cli_output ("zero delta-t?"); + error = clib_error_return (0, "failed: zero delta-t"); + goto cleanup; + } + + if (hcm->test_bytes && hcm->test_failed) + error = clib_error_return (0, "failed: test bytes"); + +cleanup: + hcm->run_test = HICN_CLIENT_EXITING; + vlib_process_wait_for_event_or_clock (vm, 10e-3); + for (i = 0; i < vec_len (hcm->connection_index_by_thread); i++) + { + vec_reset_length (hcm->connection_index_by_thread[i]); + vec_reset_length (hcm->connections_this_batch_by_thread[i]); + } + + pool_free (hcm->sessions); + + /* Detach the application, so we can use different fifo sizes next time */ + if (hcm->test_client_attached) + { + if (hicn_client_detach ()) + { + error = clib_error_return (0, "failed: app detach"); + ec_cli_output ("WARNING: app detach failed..."); + } + } + if (error) + ec_cli_output ("test failed"); + vec_free (hcm->connect_uri); + return error; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (hicn_client_command, static) = +{ + .path = "test hicn hs client", + .short_help = "test hicn hs client [uri ]", + .function = hicn_client_command_fn, + .is_mp_safe = 1, +}; +/* *INDENT-ON* */ + +clib_error_t * +hicn_client_main_init (vlib_main_t * vm) +{ + hicn_client_main_t *hcm = &hicn_client_main; + hcm->is_init = 0; + return 0; +} + +VLIB_INIT_FUNCTION (hicn_client_main_init); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/host_stack/test/hicn_hs_client.h b/hicn-plugin/src/host_stack/test/hicn_hs_client.h new file mode 100644 index 000000000..6600608e3 --- /dev/null +++ b/hicn-plugin/src/host_stack/test/hicn_hs_client.h @@ -0,0 +1,127 @@ + +/* + * echo_client.h - built-in application layer echo client + * + * Copyright (c) 2017-2019 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 __included_hicn_hs_client_h__ +#define __included_hicn_hs_client_h__ + +#include +#include +#include + +#include +#include +#include +#include + +typedef struct +{ + CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); + app_session_t data; + u64 bytes_to_send; + u64 bytes_sent; + u64 bytes_to_receive; + u64 bytes_received; + u64 vpp_session_handle; + u8 thread_index; +} eclient_session_t; + +typedef struct +{ + /* + * Application setup parameters + */ + svm_queue_t *vl_input_queue; /**< vpe input queue */ + svm_msg_q_t **vpp_event_queue; + + u32 cli_node_index; /**< cli process node index */ + u32 my_client_index; /**< loopback API client handle */ + u32 app_index; /**< app index after attach */ + + /* + * Configuration params + */ + u8 *connect_uri; /**< URI for slave's connect */ + u64 bytes_to_send; /**< Bytes to send */ + u32 configured_segment_size; + u32 fifo_size; + u32 expected_connections; /**< Number of clients/connections */ + u32 connections_per_batch; /**< Connections to rx/tx at once */ + u32 private_segment_count; /**< Number of private fifo segs */ + u32 private_segment_size; /**< size of private fifo segs */ + u32 tls_engine; /**< TLS engine mbedtls/openssl */ + u8 is_dgram; + u32 no_copy; /**< Don't memcpy data to tx fifo */ + + /* + * Test state variables + */ + eclient_session_t *sessions; /**< Session pool, shared */ + clib_spinlock_t sessions_lock; + u8 **rx_buf; /**< intermediate rx buffers */ + u8 *connect_test_data; /**< Pre-computed test data */ + u32 **connection_index_by_thread; + u32 **connections_this_batch_by_thread; /**< active connection batch */ + pthread_t client_thread_handle; + + volatile u32 ready_connections; + volatile u32 finished_connections; + volatile u64 rx_total; + volatile u64 tx_total; + volatile int run_test; /**< Signal start of test */ + + f64 test_start_time; + f64 test_end_time; + u32 prev_conns; + u32 repeats; + /* + * Flags + */ + u8 is_init; + u8 test_client_attached; + u8 no_return; + u8 test_return_packets; + int i_am_master; + int drop_packets; /**< drop all packets */ + u8 prealloc_fifos; /**< Request fifo preallocation */ + u8 no_output; + u8 test_bytes; + u8 test_failed; + u8 transport_proto; + + vlib_main_t *vlib_main; +} hicn_client_main_t; + +enum +{ + HICN_CLIENT_STARTING, + HICN_CLIENT_RUNNING, + HICN_CLIENT_EXITING +} hicn_client_state_e; + +extern hicn_client_main_t hicn_client_main; + +vlib_node_registration_t hicn_client_node; + +#endif /* __included_hicn_hs_client_h__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/host_stack/test/hicn_hs_server.c b/hicn-plugin/src/host_stack/test/hicn_hs_server.c new file mode 100644 index 000000000..cab73adb0 --- /dev/null +++ b/hicn-plugin/src/host_stack/test/hicn_hs_server.c @@ -0,0 +1,505 @@ +/* +* Copyright (c) 2020 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 "../host_stack.h" +#include "../route.h" + +#define HICN_SERVER_DGB (0) +#define DBG(_fmt, _args...) \ + if (HICN_SERVER_DGB) \ + clib_warning (_fmt, ##_args) + +typedef struct +{ + /* + * Server app parameters + */ + svm_msg_q_t **vpp_queue; + svm_queue_t *vl_input_queue; /**< Sever's event queue */ + + u32 app_index; /**< Server app index */ + u32 my_client_index; /**< API client handle */ + u32 node_index; /**< process node index for event scheduling */ + + /* + * Config params + */ + u32 fifo_size; /**< Fifo size */ + u32 rcv_buffer_size; /**< Rcv buffer size */ + u32 prealloc_fifos; /**< Preallocate fifos */ + u32 private_segment_count; /**< Number of private segments */ + u32 private_segment_size; /**< Size of private segments */ + char *server_uri; /**< Server URI */ + u32 tls_engine; /**< TLS engine: mbedtls/openssl */ + u8 is_dgram; /**< set if transport is dgram */ + /* + * Test state + */ + u8 **rx_buf; /**< Per-thread RX buffer */ + u64 byte_index; + u32 **rx_retries; + u8 transport_proto; + u64 listener_handle; /**< Session handle of the root listener */ + + vlib_main_t *vlib_main; +} hicn_server_main_t; + +hicn_server_main_t hicn_server_main; + +extern f64 t0; + +#define DEFAULT_PRODUCE_SIZE 64 << 20 +static u8 bytes[DEFAULT_PRODUCE_SIZE]; + +int +hicn_server_session_accept_callback (session_t * s) +{ + hicn_server_main_t *esm = &hicn_server_main; + esm->vpp_queue[s->thread_index] = + session_main_get_vpp_event_queue (s->thread_index); + s->session_state = SESSION_STATE_READY; + esm->byte_index = 0; + ASSERT (vec_len (esm->rx_retries) > s->thread_index); + vec_validate (esm->rx_retries[s->thread_index], s->session_index); + esm->rx_retries[s->thread_index][s->session_index] = 0; + return 0; +} + +void +hicn_server_session_disconnect_callback (session_t * s) +{ + hicn_server_main_t *esm = &hicn_server_main; + vnet_disconnect_args_t _a = { 0 }, *a = &_a; + + a->handle = session_handle (s); + a->app_index = esm->app_index; + vnet_disconnect_session (a); +} + +void +hicn_server_session_reset_callback (session_t * s) +{ + hicn_server_main_t *esm = &hicn_server_main; + vnet_disconnect_args_t _a = { 0 }, *a = &_a; + clib_warning ("Reset session %U", format_session, s, 2); + a->handle = session_handle (s); + a->app_index = esm->app_index; + vnet_disconnect_session (a); +} + +int +hicn_server_session_connected_callback (u32 app_wrk_index, u32 opaque, + session_t * s, session_error_t code) +{ + clib_warning ("called..."); + return -1; +} + +int +hicn_server_add_segment_callback (u32 client_index, u64 segment_handle) +{ + /* New heaps may be added */ + return 0; +} + +int +hicn_server_redirect_connect_callback (u32 client_index, void *mp) +{ + clib_warning ("called..."); + return -1; +} + +void +test_bytes (hicn_server_main_t * esm, int actual_transfer) +{ + int i; + u32 my_thread_id = vlib_get_thread_index (); + + for (i = 0; i < actual_transfer; i++) + { + if (esm->rx_buf[my_thread_id][i] != ((esm->byte_index + i) & 0xff)) + { + clib_warning ("at %lld expected %d got %d", esm->byte_index + i, + (esm->byte_index + i) & 0xff, + esm->rx_buf[my_thread_id][i]); + } + } + esm->byte_index += actual_transfer; +} + +/* + * If no-echo, just drop the data and be done with it. + */ +int +hicn_server_builtin_server_rx_callback_no_echo (session_t * s) +{ + svm_fifo_t *rx_fifo = s->rx_fifo; + svm_fifo_dequeue_drop (rx_fifo, svm_fifo_max_dequeue_cons (rx_fifo)); + return 0; +} + +int hicn_server_enqueue (session_t * s, svm_fifo_t *tx_fifo, u32 thread_index) +{ + hicn_server_main_t *esm = &hicn_server_main; + CLIB_UNUSED(u32 n_written); + transport_connection_t *transport = session_get_transport(s); + hicn_hs_ctx_t *ctx = (hicn_hs_ctx_t *) (transport); + hicn_hs_set_next_prod_size (ctx, DEFAULT_PRODUCE_SIZE); + + n_written = app_send_stream_raw (tx_fifo, + esm->vpp_queue[thread_index], + bytes, + DEFAULT_PRODUCE_SIZE, + SESSION_IO_EVT_TX, + 1 /* do_evt */ , 0); + + return 0; +} + +int +hicn_server_rx_callback (session_t * s) +{ + u32 max_dequeue, max_enqueue; + svm_fifo_t *tx_fifo, *rx_fifo; + hicn_server_main_t *esm = &hicn_server_main; + u32 thread_index = vlib_get_thread_index (); + + ASSERT (s->thread_index == thread_index); + + rx_fifo = s->rx_fifo; + tx_fifo = s->tx_fifo; + + ASSERT (rx_fifo->master_thread_index == thread_index); + ASSERT (tx_fifo->master_thread_index == thread_index); + + max_enqueue = svm_fifo_max_enqueue_prod (tx_fifo); + if (!esm->is_dgram) + { + max_dequeue = svm_fifo_max_dequeue_cons (rx_fifo); + } + else + { + session_dgram_pre_hdr_t ph; + svm_fifo_peek (rx_fifo, 0, sizeof (ph), (u8 *) & ph); + max_dequeue = ph.data_length - ph.data_offset; + if (!esm->vpp_queue[s->thread_index]) + { + svm_msg_q_t *mq; + mq = session_main_get_vpp_event_queue (s->thread_index); + esm->vpp_queue[s->thread_index] = mq; + } + max_enqueue -= sizeof (session_dgram_hdr_t); + } + + if (max_dequeue == 0) + { + return hicn_server_enqueue (s, tx_fifo, thread_index); + } + + return 0; +} + +static session_cb_vft_t hicn_server_session_cb_vft = { + .session_accept_callback = hicn_server_session_accept_callback, + .session_disconnect_callback = hicn_server_session_disconnect_callback, + .session_connected_callback = hicn_server_session_connected_callback, + .add_segment_callback = hicn_server_add_segment_callback, + .builtin_app_rx_callback = hicn_server_rx_callback, + .session_reset_callback = hicn_server_session_reset_callback +}; + +/* Abuse VPP's input queue */ +static int +create_api_loopback (vlib_main_t * vm) +{ + hicn_server_main_t *esm = &hicn_server_main; + api_main_t *am = vlibapi_get_main (); + vl_shmem_hdr_t *shmem_hdr; + + shmem_hdr = am->shmem_hdr; + esm->vl_input_queue = shmem_hdr->vl_input_queue; + esm->my_client_index = vl_api_memclnt_create_internal ("hicn_server", + esm->vl_input_queue); + return 0; +} + +static int +hicn_server_attach (u8 * appns_id, u64 appns_flags, u64 appns_secret) +{ + vnet_app_add_tls_cert_args_t _a_cert, *a_cert = &_a_cert; + vnet_app_add_tls_key_args_t _a_key, *a_key = &_a_key; + hicn_server_main_t *esm = &hicn_server_main; + vnet_app_attach_args_t _a, *a = &_a; + u64 options[APP_OPTIONS_N_OPTIONS]; + u32 segment_size = 512 << 20; + + clib_memset (a, 0, sizeof (*a)); + clib_memset (options, 0, sizeof (options)); + + hicn_server_session_cb_vft.builtin_app_rx_callback = + hicn_server_rx_callback; + + if (esm->private_segment_size) + segment_size = esm->private_segment_size; + + a->api_client_index = esm->my_client_index; + a->session_cb_vft = &hicn_server_session_cb_vft; + a->options = options; + a->options[APP_OPTIONS_SEGMENT_SIZE] = segment_size; + a->options[APP_OPTIONS_ADD_SEGMENT_SIZE] = segment_size; + a->options[APP_OPTIONS_RX_FIFO_SIZE] = esm->fifo_size; + a->options[APP_OPTIONS_TX_FIFO_SIZE] = esm->fifo_size; + a->options[APP_OPTIONS_PRIVATE_SEGMENT_COUNT] = esm->private_segment_count; + a->options[APP_OPTIONS_TLS_ENGINE] = esm->tls_engine; + a->options[APP_OPTIONS_PCT_FIRST_ALLOC] = 100; + a->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = + esm->prealloc_fifos ? esm->prealloc_fifos : 1; + + a->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN; + if (appns_id) + { + a->namespace_id = appns_id; + a->options[APP_OPTIONS_FLAGS] |= appns_flags; + a->options[APP_OPTIONS_NAMESPACE_SECRET] = appns_secret; + } + + if (vnet_application_attach (a)) + { + clib_warning ("failed to attach server"); + return -1; + } + esm->app_index = a->app_index; + + clib_memset (a_cert, 0, sizeof (*a_cert)); + a_cert->app_index = a->app_index; + vec_validate (a_cert->cert, test_srv_crt_rsa_len); + clib_memcpy_fast (a_cert->cert, test_srv_crt_rsa, test_srv_crt_rsa_len); + vnet_app_add_tls_cert (a_cert); + + clib_memset (a_key, 0, sizeof (*a_key)); + a_key->app_index = a->app_index; + vec_validate (a_key->key, test_srv_key_rsa_len); + clib_memcpy_fast (a_key->key, test_srv_key_rsa, test_srv_key_rsa_len); + vnet_app_add_tls_key (a_key); + return 0; +} + +static int +hicn_server_detach (void) +{ + hicn_server_main_t *esm = &hicn_server_main; + vnet_app_detach_args_t _da, *da = &_da; + int rv; + + da->app_index = esm->app_index; + rv = vnet_application_detach (da); + esm->app_index = ~0; + return rv; +} + +static int +hicn_server_listen () +{ + int rv; + hicn_server_main_t *esm = &hicn_server_main; + vnet_listen_args_t _a, *a = &_a; + clib_memset (a, 0, sizeof (*a)); + a->app_index = esm->app_index; + a->uri = esm->server_uri; + rv = vnet_bind_uri (a); + esm->listener_handle = a->handle; + return rv; +} + +static int +hicn_server_create (vlib_main_t * vm, u8 * appns_id, u64 appns_flags, + u64 appns_secret) +{ + hicn_server_main_t *esm = &hicn_server_main; + vlib_thread_main_t *vtm = vlib_get_thread_main (); + u32 num_threads; + int i; + + if (esm->my_client_index == (u32) ~ 0) + { + if (create_api_loopback (vm)) + { + clib_warning ("failed to create api loopback"); + return -1; + } + } + + num_threads = 1 /* main thread */ + vtm->n_threads; + vec_validate (hicn_server_main.vpp_queue, num_threads - 1); + vec_validate (esm->rx_buf, num_threads - 1); + vec_validate (esm->rx_retries, num_threads - 1); + for (i = 0; i < vec_len (esm->rx_retries); i++) + vec_validate (esm->rx_retries[i], + pool_elts (session_main.wrk[i].sessions)); + esm->rcv_buffer_size = clib_max (esm->rcv_buffer_size, esm->fifo_size); + for (i = 0; i < num_threads; i++) + vec_validate (esm->rx_buf[i], esm->rcv_buffer_size); + + if (hicn_server_attach (appns_id, appns_flags, appns_secret)) + { + clib_warning ("failed to attach server"); + return -1; + } + if (hicn_server_listen ()) + { + clib_warning ("failed to start listening"); + if (hicn_server_detach ()) + clib_warning ("failed to detach"); + return -1; + } + return 0; +} + +static clib_error_t * +hicn_server_create_command_fn (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + hicn_server_main_t *esm = &hicn_server_main; + u8 server_uri_set = 0, *appns_id = 0; + u64 tmp, appns_flags = 0, appns_secret = 0; + char *default_uri = "hicn://b001::1/64"; + int rv, is_stop = 0; + session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL; + + esm->fifo_size = 128 << 20; + esm->rcv_buffer_size = 2 << 20; + esm->prealloc_fifos = 0; + esm->private_segment_count = 0; + esm->private_segment_size = 0; + esm->tls_engine = CRYPTO_ENGINE_OPENSSL; + vec_free (esm->server_uri); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "uri %s", &esm->server_uri)) + server_uri_set = 1; + else if (unformat (input, "fifo-size %d", &esm->fifo_size)) + esm->fifo_size <<= 10; + else if (unformat (input, "rcv-buf-size %d", &esm->rcv_buffer_size)) + ; + else if (unformat (input, "prealloc-fifos %d", &esm->prealloc_fifos)) + ; + else if (unformat (input, "private-segment-count %d", + &esm->private_segment_count)) + ; + else if (unformat (input, "private-segment-size %U", + unformat_memory_size, &tmp)) + { + if (tmp >= 0x100000000ULL) + return clib_error_return + (0, "private segment size %lld (%llu) too large", tmp, tmp); + esm->private_segment_size = tmp; + } + else if (unformat (input, "appns %_%v%_", &appns_id)) + ; + else if (unformat (input, "all-scope")) + appns_flags |= (APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE + | APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE); + else if (unformat (input, "local-scope")) + appns_flags |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE; + else if (unformat (input, "global-scope")) + appns_flags |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE; + else if (unformat (input, "secret %lu", &appns_secret)) + ; + else if (unformat (input, "stop")) + is_stop = 1; + else if (unformat (input, "tls-engine %d", &esm->tls_engine)) + ; + else + return clib_error_return (0, "failed: unknown input `%U'", + format_unformat_error, input); + } + + if (is_stop) + { + if (esm->app_index == (u32) ~ 0) + { + clib_warning ("server not running"); + return clib_error_return (0, "failed: server not running"); + } + rv = hicn_server_detach (); + if (rv) + { + clib_warning ("failed: detach"); + return clib_error_return (0, "failed: server detach %d", rv); + } + return 0; + } + + vnet_session_enable_disable (vm, 1 /* turn on TCP, etc. */ ); + hicn_hs_enable_disable(vm, 1 /* enable hicn transport */); + + if (!server_uri_set) + { + clib_warning ("No uri provided! Using default: %s", default_uri); + esm->server_uri = (char *) format (0, "%s%c", default_uri, 0); + } + + if ((rv = parse_uri ((char *) esm->server_uri, &sep))) + return clib_error_return (0, "Uri parse error: %d", rv); + esm->transport_proto = sep.transport_proto; + esm->is_dgram = 0; + + rv = hicn_server_create (vm, appns_id, appns_flags, appns_secret); + vec_free (appns_id); + if (rv) + { + vec_free (esm->server_uri); + return clib_error_return (0, "failed: server_create returned %d", rv); + } + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (hicn_server_create_command, static) = +{ + .path = "test hicn hs server", + .short_help = "test echo server proto [no echo][fifo-size ]" + "[rcv-buf-size ][prealloc-fifos ]" + "[private-segment-count ][private-segment-size ]" + "[uri ]", + .function = hicn_server_create_command_fn, +}; +/* *INDENT-ON* */ + +clib_error_t * +hicn_server_main_init (vlib_main_t * vm) +{ + hicn_server_main_t *esm = &hicn_server_main; + esm->my_client_index = ~0; + return 0; +} + +VLIB_INIT_FUNCTION (hicn_server_main_init); + +/* +* fd.io coding-style-patch-verification: ON +* +* Local Variables: +* eval: (c-set-style "gnu") +* End: +*/ diff --git a/hicn-plugin/src/host_stack/testbed/Dockerfile b/hicn-plugin/src/host_stack/testbed/Dockerfile new file mode 100644 index 000000000..4e7005938 --- /dev/null +++ b/hicn-plugin/src/host_stack/testbed/Dockerfile @@ -0,0 +1,46 @@ +FROM ubuntu:18.04 + +ARG USERNAME=ubuntu +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +ARG VPP_GRP=vpp +ARG VPP_GID=998 + +ARG WORKDIR=/home/ubuntu + +RUN apt-get update \ + && apt-get -y install --no-install-recommends apt-utils sudo dialog build-essential \ + cmake cppcheck valgrind curl autoconf automake ccache debhelper dkms git libtool \ + libapr1-dev dh-systemd libconfuse-dev git-review exuberant-ctags cscope pkg-config \ + lcov chrpath autoconf indent clang-format libnuma-dev python-all python3-all \ + python3-setuptools python-dev python-virtualenv python-pip libffi6 check \ + libboost-all-dev libffi-dev python3-ply libmbedtls-dev cmake ninja-build uuid-dev \ + python3-jsonschema gdb libssl-dev python-setuptools zsh 2>&1 \ + # + # Verify git, process tools, lsb-release (useful for CLI installs) installed + && apt-get -y install git procps lsb-release curl iproute2 \ + # + # Create a non-root user to use if preferred - see https://aka.ms/vscode-remote/containers/non-root-user. + && groupadd --gid $USER_GID $USERNAME \ + && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \ + # [Optional] Uncomment the next three lines to add sudo support + && apt-get install -y sudo \ + && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME \ + # Create vpp group + && groupadd --gid $VPP_GID $VPP_GRP \ + # + && mkdir -p $WORKDIR \ + # + # Clean up + && apt-get autoremove -y \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* + +USER $USERNAME +COPY init.sh /init.sh + +WORKDIR $WORKDIR + +CMD ["bash", "/init.sh"] diff --git a/hicn-plugin/src/host_stack/testbed/client-startup.txt b/hicn-plugin/src/host_stack/testbed/client-startup.txt new file mode 100644 index 000000000..7165265b3 --- /dev/null +++ b/hicn-plugin/src/host_stack/testbed/client-startup.txt @@ -0,0 +1,6 @@ +create interface memif id 0 master +set int state memif0/0 up +set int ip addr memif0/0 192.168.10.1/24 +set int ip addr memif0/0 2001::1/64 +ip route add b001::/64 via 2001::2 memif0/0 +#hicn enable b001::/64 \ No newline at end of file diff --git a/hicn-plugin/src/host_stack/testbed/init.sh b/hicn-plugin/src/host_stack/testbed/init.sh new file mode 100644 index 000000000..3017c2fea --- /dev/null +++ b/hicn-plugin/src/host_stack/testbed/init.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +sudo modprobe uio_pci_generic +sudo cp /home/ubuntu/host-stack/install/lib/libhicn.so /usr/lib/libhicn.so + +tail -f /dev/null \ No newline at end of file diff --git a/hicn-plugin/src/host_stack/testbed/run-client-server.sh b/hicn-plugin/src/host_stack/testbed/run-client-server.sh new file mode 100644 index 000000000..53388cdda --- /dev/null +++ b/hicn-plugin/src/host_stack/testbed/run-client-server.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +docker run -d \ + --privileged \ + --cap-add=ALL \ + --security-opt seccomp=unconfined \ + --hostname=vpp-client \ + -e STARTUP_CONF=/home/ubuntu/host-stack/vpp/testbed/startup-client.conf \ + -v /home/ubuntu/host-stack:/home/ubuntu/host-stack \ + -v /dev:/dev -v /lib/modules:/lib/modules \ + -v /var/run/vpp:/var/run/vpp \ + --name vpp-client vpp-develop + +docker run -d \ + --privileged \ + --cap-add=SYS_PTRACE \ + --security-opt seccomp=unconfined \ + --hostname=vpp-server \ + -e STARTUP_CONF=/home/ubuntu/host-stack/vpp/testbed/startup-server.conf \ + --cap-add=NET_ADMIN \ + -v /home/ubuntu/host-stack:/home/ubuntu/host-stack \ + -v /dev:/dev -v /lib/modules:/lib/modules \ + -v /var/run/vpp:/var/run/vpp \ + --name vpp-server vpp-develop \ No newline at end of file diff --git a/hicn-plugin/src/host_stack/testbed/server-startup.txt b/hicn-plugin/src/host_stack/testbed/server-startup.txt new file mode 100644 index 000000000..1b4d54338 --- /dev/null +++ b/hicn-plugin/src/host_stack/testbed/server-startup.txt @@ -0,0 +1,7 @@ +create interface memif id 0 slave +set int state memif0/0 up +set int ip addr memif0/0 192.168.10.2/24 +set int ip addr memif0/0 2001::2/64 +hicn hs set local prefix b001::/16 +#test hicn hs server uri hicn://b001::/64 +#hicn enable b001::/64 diff --git a/hicn-plugin/src/host_stack/testbed/startup-client.conf b/hicn-plugin/src/host_stack/testbed/startup-client.conf new file mode 100644 index 000000000..fb0c89c87 --- /dev/null +++ b/hicn-plugin/src/host_stack/testbed/startup-client.conf @@ -0,0 +1,188 @@ + +unix { + nodaemon + interactive + log /var/log/vpp/vpp.log + full-coredump + cli-listen /run/vpp/cli.sock + gid vpp + startup-config /home/ubuntu/host-stack/vpp/testbed/client-startup.txt +} + +api-trace { +## This stanza controls binary API tracing. Unless there is a very strong reason, +## please leave this feature enabled. + on +## Additional parameters: +## +## To set the number of binary API trace records in the circular buffer, configure nitems +## +## nitems +## +## To save the api message table decode tables, configure a filename. Results in /tmp/ +## Very handy for understanding api message changes between versions, identifying missing +## plugins, and so forth. +## +## save-api-table +} + +api-segment { + gid vpp +} + +socksvr { + default +} + +cpu { + ## In the VPP there is one main thread and optionally the user can create worker(s) + ## The main thread and worker thread(s) can be pinned to CPU core(s) manually or automatically + + ## Manual pinning of thread(s) to CPU core(s) + + ## Set logical CPU core where main thread runs, if main core is not set + ## VPP will use core 1 if available + main-core 1 + + ## Set logical CPU core(s) where worker threads are running + # corelist-workers 2-3,18-19 + + ## Automatic pinning of thread(s) to CPU core(s) + + ## Sets number of CPU core(s) to be skipped (1 ... N-1) + ## Skipped CPU core(s) are not used for pinning main thread and working thread(s). + ## The main thread is automatically pinned to the first available CPU core and worker(s) + ## are pinned to next free CPU core(s) after core assigned to main thread + # skip-cores 4 + + ## Specify a number of workers to be created + ## Workers are pinned to N consecutive CPU cores while skipping "skip-cores" CPU core(s) + ## and main thread's CPU core + # workers 2 + + ## Set scheduling policy and priority of main and worker threads + + ## Scheduling policy options are: other (SCHED_OTHER), batch (SCHED_BATCH) + ## idle (SCHED_IDLE), fifo (SCHED_FIFO), rr (SCHED_RR) + # scheduler-policy fifo + + ## Scheduling priority is used only for "real-time policies (fifo and rr), + ## and has to be in the range of priorities supported for a particular policy + # scheduler-priority 50 +} + +buffers { + ## Increase number of buffers allocated, needed only in scenarios with + ## large number of interfaces and worker threads. Value is per numa node. +# Default is 16384 (8192 if running unpriviledged) + buffers-per-numa 600000 + ## Size of buffer data area + ## Default is 2048 + # default data-size 2048 +} + +# dpdk { + ## Change default settings for all interfaces + # dev default { + ## Number of receive queues, enables RSS + ## Default is 1 + # num-rx-queues 3 + + ## Number of transmit queues, Default is equal + ## to number of worker threads or 1 if no workers treads + # num-tx-queues 3 + + ## Number of descriptors in transmit and receive rings + ## increasing or reducing number can impact performance + ## Default is 1024 for both rx and tx + # num-rx-desc 512 + # num-tx-desc 512 + + ## VLAN strip offload mode for interface + ## Default is off + # vlan-strip-offload on + + ## TCP Segment Offload + ## Default is off + ## To enable TSO, 'enable-tcp-udp-checksum' must be set + # tso on + + ## Devargs + ## device specific init args + ## Default is NULL + # devargs safe-mode-support=1,pipeline-mode-support=1 + # } + + ## Whitelist specific interface by specifying PCI address + # dev 0000:13:00.0 + + ## Blacklist specific device type by specifying PCI vendor:device + ## Whitelist entries take precedence + # blacklist 8086:10fb + + ## Set interface name + # dev 0000:02:00.1 { + # name eth0 + # } + + ## Whitelist specific interface by specifying PCI address and in + ## addition specify custom parameters for this interface + # dev 0000:02:00.1 { + # num-rx-queues 2 + # } + + ## Change UIO driver used by VPP, Options are: igb_uio, vfio-pci, + ## uio_pci_generic or auto (default) + # uio-driver vfio-pci + + ## Disable multi-segment buffers, improves performance but + ## disables Jumbo MTU support + # no-multi-seg + + ## Change hugepages allocation per-socket, needed only if there is need for + ## larger number of mbufs. Default is 256M on each detected CPU socket + # socket-mem 2048,2048 + + ## Disables UDP / TCP TX checksum offload. Typically needed for use + ## faster vector PMDs (together with no-multi-seg) + # no-tx-checksum-offload + + ## Enable UDP / TCP TX checksum offload + ## This is the reversed option of 'no-tx-checksum-offload' + # enable-tcp-udp-checksum +# } + + +plugins { + ## Adjusting the plugin path depending on where the VPP plugins are + path /home/ubuntu/host-stack/vpp/build-root/install-vpp_debug-native/vpp/lib/x86_64-linux-gnu/vpp_plugins:/home/ubuntu/host-stack/vpp/build-root/install-vpp_debug-native/vpp/lib/vpp_plugins:/home/ubuntu/host-stack/install/lib/vpp_plugins + ## Disable all plugins by default and then selectively enable specific plugins + plugin default { enable } + plugin dpdk_plugin.so { disable } + plugin hicn_plugin.so { enable } +# plugin hicn_plugin.so { enable } + + + ## Enable all plugins by default and then selectively disable specific plugins + # plugin dpdk_plugin.so { disable } + # plugin acl_plugin.so { disable } +} + +## Statistics Segment +# statseg { + # socket-name , name of the stats segment socket + # defaults to /run/vpp/stats.sock + # size [KMG], size of the stats segment, defaults to 32mb + # per-node-counters on | off, defaults to none + # update-interval , sets the segment scrape / update interval +# } + +#hicn { +# pit-size 2000000 +# cs-size 1000000 +# cs-reserved-app 10 +#} + +session { evt_qs_memfd_seg } +socksvr { socket-name /tmp/vpp-api.sock} +tcp {cc-algo cubic} diff --git a/hicn-plugin/src/host_stack/testbed/startup-server.conf b/hicn-plugin/src/host_stack/testbed/startup-server.conf new file mode 100644 index 000000000..46fc220d8 --- /dev/null +++ b/hicn-plugin/src/host_stack/testbed/startup-server.conf @@ -0,0 +1,189 @@ + +unix { + nodaemon + interactive + log /var/log/vpp/vpp.log + full-coredump + cli-listen /run/vpp/cli.sock + gid vpp + startup-config /home/ubuntu/host-stack/vpp/testbed/server-startup.txt +} + +api-trace { +## This stanza controls binary API tracing. Unless there is a very strong reason, +## please leave this feature enabled. + on +## Additional parameters: +## +## To set the number of binary API trace records in the circular buffer, configure nitems +## +## nitems +## +## To save the api message table decode tables, configure a filename. Results in /tmp/ +## Very handy for understanding api message changes between versions, identifying missing +## plugins, and so forth. +## +## save-api-table +} + +api-segment { + gid vpp +} + +socksvr { + default +} + +cpu { + ## In the VPP there is one main thread and optionally the user can create worker(s) + ## The main thread and worker thread(s) can be pinned to CPU core(s) manually or automatically + + ## Manual pinning of thread(s) to CPU core(s) + + ## Set logical CPU core where main thread runs, if main core is not set + ## VPP will use core 1 if available + main-core 2 + + ## Set logical CPU core(s) where worker threads are running + # corelist-workers 2-3,18-19 + + ## Automatic pinning of thread(s) to CPU core(s) + + ## Sets number of CPU core(s) to be skipped (1 ... N-1) + ## Skipped CPU core(s) are not used for pinning main thread and working thread(s). + ## The main thread is automatically pinned to the first available CPU core and worker(s) + ## are pinned to next free CPU core(s) after core assigned to main thread + # skip-cores 4 + + ## Specify a number of workers to be created + ## Workers are pinned to N consecutive CPU cores while skipping "skip-cores" CPU core(s) + ## and main thread's CPU core + # workers 2 + + ## Set scheduling policy and priority of main and worker threads + + ## Scheduling policy options are: other (SCHED_OTHER), batch (SCHED_BATCH) + ## idle (SCHED_IDLE), fifo (SCHED_FIFO), rr (SCHED_RR) + # scheduler-policy fifo + + ## Scheduling priority is used only for "real-time policies (fifo and rr), + ## and has to be in the range of priorities supported for a particular policy + # scheduler-priority 50 +} + +buffers { + ## Increase number of buffers allocated, needed only in scenarios with + ## large number of interfaces and worker threads. Value is per numa node. +# Default is 16384 (8192 if running unpriviledged) + buffers-per-numa 600000 + ## Size of buffer data area + ## Default is 2048 + # default data-size 2048 +} + +# dpdk { + ## Change default settings for all interfaces + # dev default { + ## Number of receive queues, enables RSS + ## Default is 1 + # num-rx-queues 3 + + ## Number of transmit queues, Default is equal + ## to number of worker threads or 1 if no workers treads + # num-tx-queues 3 + + ## Number of descriptors in transmit and receive rings + ## increasing or reducing number can impact performance + ## Default is 1024 for both rx and tx + # num-rx-desc 512 + # num-tx-desc 512 + + ## VLAN strip offload mode for interface + ## Default is off + # vlan-strip-offload on + + ## TCP Segment Offload + ## Default is off + ## To enable TSO, 'enable-tcp-udp-checksum' must be set + # tso on + + ## Devargs + ## device specific init args + ## Default is NULL + # devargs safe-mode-support=1,pipeline-mode-support=1 + # } + + ## Whitelist specific interface by specifying PCI address + # dev 0000:13:00.1 + + ## Blacklist specific device type by specifying PCI vendor:device + ## Whitelist entries take precedence + # blacklist 8086:10fb + + ## Set interface name + # dev 0000:02:00.1 { + # name eth0 + # } + + ## Whitelist specific interface by specifying PCI address and in + ## addition specify custom parameters for this interface + # dev 0000:02:00.1 { + # num-rx-queues 2 + # } + + ## Change UIO driver used by VPP, Options are: igb_uio, vfio-pci, + ## uio_pci_generic or auto (default) + # uio-driver vfio-pci + + ## Disable multi-segment buffers, improves performance but + ## disables Jumbo MTU support + # no-multi-seg + + ## Change hugepages allocation per-socket, needed only if there is need for + ## larger number of mbufs. Default is 256M on each detected CPU socket + # socket-mem 2048,2048 + + ## Disables UDP / TCP TX checksum offload. Typically needed for use + ## faster vector PMDs (together with no-multi-seg) + # no-tx-checksum-offload + + ## Enable UDP / TCP TX checksum offload + ## This is the reversed option of 'no-tx-checksum-offload' + # enable-tcp-udp-checksum +# } + + +plugins { + ## Adjusting the plugin path depending on where the VPP plugins are + path /home/ubuntu/host-stack/vpp/build-root/install-vpp_debug-native/vpp/lib/x86_64-linux-gnu/vpp_plugins:/home/ubuntu/host-stack/vpp/build-root/install-vpp_debug-native/vpp/lib/vpp_plugins:/home/ubuntu/host-stack/install/lib/vpp_plugins + ## Disable all plugins by default and then selectively enable specific plugins + plugin default { enable } + plugin dpdk_plugin.so { disable } + plugin hicn_plugin.so { enable } +# plugin memif_plugin.so { enable } +# plugin hicn_plugin.so { enable } + + + ## Enable all plugins by default and then selectively disable specific plugins + # plugin dpdk_plugin.so { disable } + # plugin acl_plugin.so { disable } +} + +## Statistics Segment +# statseg { + # socket-name , name of the stats segment socket + # defaults to /run/vpp/stats.sock + # size [KMG], size of the stats segment, defaults to 32mb + # per-node-counters on | off, defaults to none + # update-interval , sets the segment scrape / update interval +# } + +#hicn { +# pit-size 2000000 +# cs-size 1000000 +# cs-reserved-app 10 +#} + +session { evt_qs_memfd_seg } +socksvr { socket-name /tmp/vpp-api.sock} +tcp {cc-algo cubic} diff --git a/hicn-plugin/src/host_stack/testbed/test_hicn_hs.txt b/hicn-plugin/src/host_stack/testbed/test_hicn_hs.txt new file mode 100644 index 000000000..73a5b15f5 --- /dev/null +++ b/hicn-plugin/src/host_stack/testbed/test_hicn_hs.txt @@ -0,0 +1,6 @@ +hicn hs set local prefix b001::/8 +test hicn hs server uri hicn://b001::/64 +test hicn hs client uri hicn://b001::1/64 + + +b hicn_hs.c:772 if ctx->snd_nxt == 46604 \ No newline at end of file diff --git a/hicn-plugin/src/host_stack/testbed/vcl.conf b/hicn-plugin/src/host_stack/testbed/vcl.conf new file mode 100644 index 000000000..694a3e3a1 --- /dev/null +++ b/hicn-plugin/src/host_stack/testbed/vcl.conf @@ -0,0 +1,7 @@ +vcl { + rx-fifo-size 4000000 + tx-fifo-size 4000000 + app-scope-local + app-scope-global + api-socket-name /tmp/vpp-api.sock +} \ No newline at end of file diff --git a/hicn-plugin/src/host_stack/utils.h b/hicn-plugin/src/host_stack/utils.h new file mode 100644 index 000000000..67568d568 --- /dev/null +++ b/hicn-plugin/src/host_stack/utils.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020 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. + */ + +/* Compute TCP checksum in software when offloading is disabled for a connection */ + +#ifndef __HICN_HS_UTILS_H__ +#define __HICN_HS_UTILS_H__ + +#include +#include +#include + +always_inline u16 +ip6_tcp_compute_checksum_custom (vlib_main_t * vm, vlib_buffer_t * p0, + ip46_address_t * src, ip46_address_t * dst) +{ + ip_csum_t sum0; + u16 payload_length_host_byte_order; + u32 i; + + /* Initialize checksum with ip header. */ + sum0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, p0)) + + clib_host_to_net_u16 (IP_PROTOCOL_TCP); + payload_length_host_byte_order = vlib_buffer_length_in_chain (vm, p0); + + for (i = 0; i < ARRAY_LEN (src->ip6.as_uword); i++) + { + sum0 = ip_csum_with_carry + (sum0, clib_mem_unaligned (&src->ip6.as_uword[i], uword)); + sum0 = ip_csum_with_carry + (sum0, clib_mem_unaligned (&dst->ip6.as_uword[i], uword)); + } + + return ip_calculate_l4_checksum (vm, p0, sum0, + payload_length_host_byte_order, NULL, 0, + NULL); +} + +always_inline u16 +ip4_tcp_compute_checksum_custom (vlib_main_t * vm, vlib_buffer_t * p0, + ip46_address_t * src, ip46_address_t * dst) +{ + ip_csum_t sum0; + u32 payload_length_host_byte_order; + + payload_length_host_byte_order = vlib_buffer_length_in_chain (vm, p0); + sum0 = + clib_host_to_net_u32 (payload_length_host_byte_order + + (IP_PROTOCOL_TCP << 16)); + + sum0 = ip_csum_with_carry (sum0, clib_mem_unaligned (&src->ip4, u32)); + sum0 = ip_csum_with_carry (sum0, clib_mem_unaligned (&dst->ip4, u32)); + + return ip_calculate_l4_checksum (vm, p0, sum0, + payload_length_host_byte_order, NULL, 0, + NULL); +} + +always_inline u16 +hicn_hs_compute_checksum (hicn_hs_ctx_t * ctx, vlib_buffer_t * b) +{ + u16 checksum = 0; + if (PREDICT_FALSE (ctx->cfg_flags & HICN_HS_CFG_F_NO_CSUM_OFFLOAD)) + { + hicn_hs_worker_t *wrk = hicn_hs_get_worker_by_context (ctx); + vlib_main_t *vm = wrk->vm; + ip46_address_t local_ip = {0}; + + if (ctx->c_is_ip4) + checksum = ip4_tcp_compute_checksum_custom + (vm, b, &local_ip, &ctx->c_rmt_ip); + else + checksum = ip6_tcp_compute_checksum_custom + (vm, b, &local_ip, &ctx->c_rmt_ip); + } + else + { + b->flags |= VNET_BUFFER_F_OFFLOAD_TCP_CKSUM; + } + return checksum; +} + +#endif /* __HICN_HS_UTILS_H__ */ diff --git a/hicn-plugin/src/infra.h b/hicn-plugin/src/infra.h deleted file mode 100644 index ff76de4e4..000000000 --- a/hicn-plugin/src/infra.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_INFRA_H__ -#define __HICN_INFRA_H__ - -#include -#include -#include - -#include "pcs.h" - -/** - * @file infra.h - * - */ - -/** - * @brief hICN plugin global state. - */ -typedef struct hicn_main_s -{ - /* Binary API message ID base */ - u16 msg_id_base; - - /* Have we been enabled */ - u16 is_enabled; - - /* Forwarder PIT/CS */ - hicn_pit_cs_t pitcs; - - /* Global PIT lifetime info */ - /* - * Boundaries for the interest lifetime. If greater than - * pit_lifetime_max_ms, pit_lifetime_max_ms is used in the PIT - */ - u64 pit_lifetime_max_ms; - - vnet_link_t link; - -} hicn_main_t; - -extern hicn_main_t hicn_main; - -extern int hicn_infra_fwdr_initialized; - -/* PIT and CS size */ -u32 hicn_infra_pit_size; -u32 hicn_infra_cs_size; - -/** - * @brief Enable and disable the hicn plugin - * - * Enable the time the hICN plugin and set the forwarder parameters. - * @param enable_disable 1 if to enable, 0 otherwisw (currently only enable is supported) - * @param pit_max_size Max size of the PIT - * @param pit_max_lifetime_sec_req Maximum timeout allowed for a PIT entry lifetime - * @param cs_max_size CS size. Must be <= than pit_max_size - * @param cs_reserved_app Amount of CS reserved for application faces - */ -int -hicn_infra_plugin_enable_disable (int enable_disable, - int pit_max_size, - f64 pit_max_lifetime_sec_req, - int cs_max_size, - vnet_link_t link); - - -/* vlib nodes that compose the hICN forwarder */ -extern vlib_node_registration_t hicn_interest_pcslookup_node; -extern vlib_node_registration_t hicn_data_pcslookup_node; -extern vlib_node_registration_t hicn_data_fwd_node; -extern vlib_node_registration_t hicn_data_store_node; -extern vlib_node_registration_t hicn_interest_hitpit_node; -extern vlib_node_registration_t hicn_interest_hitcs_node; -extern vlib_node_registration_t hicn_pg_interest_node; -extern vlib_node_registration_t hicn_pg_data_node; -extern vlib_node_registration_t hicn_pg_server_node; -extern vlib_node_registration_t hicn_data_input_ip6_node; -extern vlib_node_registration_t hicn_data_input_ip4_node; - - - -#endif /* // __HICN_INFRA_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/interest_hitcs.h b/hicn-plugin/src/interest_hitcs.h deleted file mode 100644 index 94fa3e6f5..000000000 --- a/hicn-plugin/src/interest_hitcs.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_INTEREST_HITCS_H__ -#define __HICN_INTEREST_HITCS_H__ - -#include -#include - -#include "pcs.h" - -/** - * @file interest_hitcs.h - * - * This is the node encoutered by interest packets after the hicn-interest-pcslookup. - * This node satisfies an interest with a data stored in the CS and send the data back - * from the incoming iface of the interest (i.e., the vlib buffer is sent to the - * hicn6-iface-output or hicn4-iface-output node). In case the data is expired, the - * vlib buffer is sent to the hicn-strategy node. - */ - -/* - * Node context data; we think this is per-thread/instance - */ -typedef struct hicn_interest_hitcs_runtime_s -{ - int id; - hicn_pit_cs_t *pitcs; -} hicn_interest_hitcs_runtime_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; -} hicn_interest_hitcs_trace_t; - -typedef enum -{ - HICN_INTEREST_HITCS_NEXT_STRATEGY, - HICN_INTEREST_HITCS_NEXT_IFACE4_OUT, - HICN_INTEREST_HITCS_NEXT_IFACE6_OUT, - HICN_INTEREST_HITCS_NEXT_ERROR_DROP, - HICN_INTEREST_HITCS_N_NEXT, -} hicn_interest_hitcs_next_t; - -#endif /* // __HICN_INTEREST_HITCS_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/interest_hitcs_node.c b/hicn-plugin/src/interest_hitcs_node.c deleted file mode 100644 index f569fa897..000000000 --- a/hicn-plugin/src/interest_hitcs_node.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "interest_hitcs.h" -#include "mgmt.h" -#include "parser.h" -#include "data_fwd.h" -#include "infra.h" -#include "state.h" -#include "error.h" - -/* packet trace format function */ -static u8 *hicn_interest_hitcs_format_trace (u8 * s, va_list * args); - - -/* Stats string values */ -static char *hicn_interest_hitcs_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -vlib_node_registration_t hicn_interest_hitcs_node; - -always_inline void drop_packet (u32 * next0); - -always_inline void -clone_from_cs (vlib_main_t * vm, u32 * bi0_cs, vlib_buffer_t * dest, u8 isv6) -{ - /* Retrieve the buffer to clone */ - vlib_buffer_t *cs_buf = vlib_get_buffer (vm, *bi0_cs); - hicn_buffer_t *hicnb = hicn_get_buffer (cs_buf); - word buffer_advance = CLIB_CACHE_LINE_BYTES * 2; - if (hicnb->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL) - { - clib_memcpy_fast (vlib_buffer_get_current (dest), - vlib_buffer_get_current (cs_buf), - cs_buf->current_length); - clib_memcpy_fast (dest->opaque2, cs_buf->opaque2, - sizeof (cs_buf->opaque2)); - - dest->current_length = cs_buf->current_length; - dest->total_length_not_including_first_buffer = 0; - } - else - { - vlib_buffer_advance (cs_buf, -buffer_advance); - if (PREDICT_FALSE (cs_buf->ref_count == 255)) - { - vlib_buffer_t *cs_buf2 = vlib_buffer_copy (vm, cs_buf); - vlib_buffer_advance (cs_buf, buffer_advance); - *bi0_cs = vlib_get_buffer_index (vm, cs_buf2); - cs_buf->ref_count--; - cs_buf = cs_buf2; - } - - clib_memcpy_fast (vlib_buffer_get_current (dest), - vlib_buffer_get_current (cs_buf), buffer_advance); - clib_memcpy_fast (dest->opaque2, cs_buf->opaque2, - sizeof (cs_buf->opaque2)); - dest->current_length = buffer_advance; - vlib_buffer_advance (cs_buf, buffer_advance); - vlib_buffer_attach_clone (vm, dest, cs_buf); - } -} - -static uword -hicn_interest_hitcs_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next; - hicn_interest_hitcs_next_t next_index; - 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); - - if (PREDICT_FALSE (rt->pitcs == NULL)) - { - rt->pitcs = &hicn_main.pitcs; - } - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - /* Capture time in vpp terms */ - tnow = vlib_time_now (vm); - while (n_left_from > 0) - { - u32 n_left_to_next; - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *b0; - u8 isv6; - u8 *nameptr; - 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; - hicn_hash_entry_t *hash_entry0; - const hicn_strategy_vft_t *strategy_vft0; - const hicn_dpo_vft_t *dpo_vft0; - u8 dpo_ctx_id0; - - /* Prefetch for next iteration. */ - if (n_left_from > 1) - { - vlib_buffer_t *b1; - b1 = vlib_get_buffer (vm, from[1]); - CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, STORE); - CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, STORE); - } - - /* Dequeue a packet buffer */ - bi0 = from[0]; - from += 1; - n_left_from -= 1; - to_next[0] = bi0; - to_next += 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - /* Get hicn buffer and state */ - hicnb0 = hicn_get_buffer (b0); - 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); - pitp = hicn_pit_get_data (node0); - - dpo_id_t hicn_dpo_id0 = - { dpo_vft0->hicn_dpo_get_type (), 0, 0, dpo_ctx_id0 }; - - if (PREDICT_FALSE - (ret != HICN_ERROR_NONE || - !hicn_node_compare (nameptr, namelen, node0))) - { - /* Remove lock from the entry */ - hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, hash_entry0, - dpo_vft0, &hicn_dpo_id0); - drop_packet (&next0); - goto end_processing; - } - if ((tnow > pitp->shared.expire_time)) - { - /* Delete and clean up expired CS entry */ - hicn_pcs_delete (rt->pitcs, &pitp, &node0, vm, hash_entry0, - dpo_vft0, &hicn_dpo_id0); - stats.cs_expired_count++; - /* Forward interest to the strategy node */ - next0 = HICN_INTEREST_HITCS_NEXT_STRATEGY; - } - else - { - if (PREDICT_TRUE - (!(hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED))) - hicn_pcs_cs_update (vm, rt->pitcs, pitp, pitp, node0); - - /* - * Retrieve the incoming iface and forward - * the data through it - */ - next0 = isv6 ? HICN_INTEREST_HITCS_NEXT_IFACE6_OUT : - HICN_INTEREST_HITCS_NEXT_IFACE4_OUT; - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = hicnb0->face_id; - - clone_from_cs (vm, &pitp->u.cs.cs_pkt_buf, b0, isv6); - - stats.pkts_from_cache_count++; - stats.pkts_data_count++; - /* Remove lock from the entry */ - hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, hash_entry0, - dpo_vft0, &hicn_dpo_id0); - } - - end_processing: - - /* Maybe trace */ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - hicn_interest_hitcs_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_INTEREST; - t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - t->next_index = next0; - } - /* Incr packet counter */ - stats.pkts_processed += 1; - - /* - * 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); - } - - u32 pit_int_count = hicn_pit_get_int_count (rt->pitcs); - - vlib_node_increment_counter (vm, hicn_interest_hitcs_node.index, - HICNFWD_ERROR_CACHED, - stats.pkts_from_cache_count); - - vlib_node_increment_counter (vm, hicn_interest_hitcs_node.index, - HICNFWD_ERROR_DATAS, stats.pkts_data_count); - - update_node_counter (vm, hicn_interest_hitcs_node.index, - HICNFWD_ERROR_INT_COUNT, pit_int_count); - - return (frame->n_vectors); -} - -always_inline void -drop_packet (u32 * next0) -{ - *next0 = HICN_INTEREST_HITCS_NEXT_ERROR_DROP; -} - -/* packet trace format function */ -static u8 * -hicn_interest_hitcs_format_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 *); - hicn_interest_hitcs_trace_t *t = - va_arg (*args, hicn_interest_hitcs_trace_t *); - - s = format (s, "INTEREST-HITCS: pkt: %d, sw_if_index %d, next index %d", - (int) t->pkt_type, t->sw_if_index, t->next_index); - return (s); -} - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(hicn_interest_hitcs_node) = -{ - .function = hicn_interest_hitcs_node_fn, - .name = "hicn-interest-hitcs", - .vector_size = sizeof(u32), - .runtime_data_bytes = sizeof(hicn_interest_hitcs_runtime_t), - .format_trace = hicn_interest_hitcs_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(hicn_interest_hitcs_error_strings), - .error_strings = hicn_interest_hitcs_error_strings, - .n_next_nodes = HICN_INTEREST_HITCS_N_NEXT, - /* edit / add dispositions here */ - .next_nodes = - { - [HICN_INTEREST_HITCS_NEXT_STRATEGY] = "hicn-strategy", - [HICN_INTEREST_HITCS_NEXT_IFACE4_OUT] = "hicn4-iface-output", - [HICN_INTEREST_HITCS_NEXT_IFACE6_OUT] = "hicn6-iface-output", - [HICN_INTEREST_HITCS_NEXT_ERROR_DROP] = "error-drop" - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/interest_hitpit.h b/hicn-plugin/src/interest_hitpit.h deleted file mode 100644 index ffdc61c8f..000000000 --- a/hicn-plugin/src/interest_hitpit.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_INTEREST_HITPIT_H__ -#define __HICN_INTEREST_HITPIT_H__ - -#include -#include - -#include "pcs.h" - -/** - * @file interest_hitpit.h - * - * This is the node encoutered by interest packets after the hicn-interest-pcslookup. - * This node aggregates an interest in the PIT or forward it in case of a retransmission. - * If the interest must be retransmitted the next vlib node will be on of the - * hicn6-face-output or hicn4-face-output nodes. If the pit entry is expired the next vlib node - * will be the hicn-strategy node, otherwise the vlib buffer is dropped. - */ - - -/* - * Node context data; we think this is per-thread/instance - */ -typedef struct hicn_interest_hitpit_runtime_s -{ - int id; - hicn_pit_cs_t *pitcs; -} hicn_interest_hitpit_runtime_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; -} hicn_interest_hitpit_trace_t; - -typedef enum -{ - HICN_INTEREST_HITPIT_NEXT_INTEREST_HITCS, - HICN_INTEREST_HITPIT_NEXT_STRATEGY, - HICN_INTEREST_HITPIT_NEXT_FACE4_OUTPUT, - HICN_INTEREST_HITPIT_NEXT_FACE6_OUTPUT, - HICN_INTEREST_HITPIT_NEXT_ERROR_DROP, - HICN_INTEREST_HITPIT_N_NEXT, -} hicn_interest_hitpit_next_t; - -#endif /* // __HICN_INTEREST_HITPIT_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/interest_hitpit_node.c b/hicn-plugin/src/interest_hitpit_node.c deleted file mode 100644 index 9ebf183c5..000000000 --- a/hicn-plugin/src/interest_hitpit_node.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "interest_hitpit.h" -#include "mgmt.h" -#include "parser.h" -#include "data_fwd.h" -#include "infra.h" -#include "strategy.h" -#include "strategy_dpo_ctx.h" -#include "strategy_dpo_manager.h" -#include "state.h" -#include "error.h" -#include "face_db.h" - -/* packet trace format function */ -static u8 *hicn_interest_hitpit_format_trace (u8 * s, va_list * args); - -/* Stats string values */ -static char *hicn_interest_hitpit_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -vlib_node_registration_t hicn_interest_hitpit_node; - -always_inline void drop_packet (u32 * next0); - -/* - * hICN forwarder node for interests hitting the PIT - */ -static uword -hicn_interest_hitpit_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next; - hicn_interest_hitpit_next_t next_index; - hicn_interest_hitpit_runtime_t *rt; - vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; - f64 tnow; - - rt = vlib_node_get_runtime_data (vm, hicn_interest_hitpit_node.index); - - if (PREDICT_FALSE (rt->pitcs == NULL)) - { - rt->pitcs = &hicn_main.pitcs; - } - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - /* Capture time in vpp terms */ - tnow = vlib_time_now (vm); - - while (n_left_from > 0) - { - u32 n_left_to_next; - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *b0; - u8 isv6; - u8 *nameptr; - 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; - hicn_pcs_entry_t *pitp; - u8 dpo_ctx_id0; - u8 found = 0; - int nh_idx; - hicn_face_id_t outface; - hicn_hash_entry_t *hash_entry0; - hicn_buffer_t *hicnb0; - 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->data, CLIB_CACHE_LINE_BYTES, STORE); - } - - /* Dequeue a packet buffer */ - bi0 = from[0]; - from += 1; - n_left_from -= 1; - to_next[0] = bi0; - to_next += 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - /* Get hicn buffer and state */ - hicnb0 = hicn_get_buffer (b0); - 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); - pitp = hicn_pit_get_data (node0); - dpo_id_t hicn_dpo_id0 = - { dpo_vft0->hicn_dpo_get_type (), 0, 0, dpo_ctx_id0 }; - - /* - * 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))) - { - stats.interests_hash_collision++; - /* Remove lock from the entry */ - hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, hash_entry0, - dpo_vft0, &hicn_dpo_id0); - drop_packet (&next0); - - goto end_processing; - } - /* - * If the entry is expired, remove it no matter of - * the possible cases. - */ - if (tnow > pitp->shared.expire_time) - { - strategy_vft0->hicn_on_interest_timeout (dpo_ctx_id0); - hicn_pcs_delete (rt->pitcs, &pitp, &node0, vm, hash_entry0, - dpo_vft0, &hicn_dpo_id0); - stats.pit_expired_count++; - next0 = HICN_INTEREST_HITPIT_NEXT_STRATEGY; - } - else - { - if ((hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY)) - { - next0 = HICN_INTEREST_HITPIT_NEXT_INTEREST_HITCS; - } - else - { - /* - * Distinguish between aggregation or - * retransmission - */ - - found = - hicn_face_search (hicnb0->face_id, - &(pitp->u.pit.faces)); - - if (found) - { - strategy_vft0->hicn_select_next_hop (dpo_ctx_id0, - &nh_idx, &outface); - /* Retransmission */ - /* - * Prepare the packet for the - * forwarding - */ - next0 = isv6 ? HICN_INTEREST_HITPIT_NEXT_FACE6_OUTPUT : - HICN_INTEREST_HITPIT_NEXT_FACE4_OUTPUT; - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = - outface; - - /* - * Update the egress face in - * the PIT - */ - pitp->u.pit.pe_txnh = nh_idx; - stats.interests_retx++; - } - else - { - hicn_face_db_add_face (hicnb0->face_id, - &pitp->u.pit.faces); - - /* Aggregation */ - drop_packet (&next0); - stats.interests_aggregated++; - } - /* Remove lock from the entry */ - hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, - hash_entry0, dpo_vft0, &hicn_dpo_id0); - - } - } - end_processing: - - /* Maybe trace */ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - hicn_interest_hitpit_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_INTEREST; - t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - t->next_index = next0; - } - /* Incr packet counter */ - stats.pkts_processed += 1; - - /* - * 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); - } - u32 pit_int_count = hicn_pit_get_int_count (rt->pitcs); - - - vlib_node_increment_counter (vm, hicn_interest_hitpit_node.index, - HICNFWD_ERROR_PROCESSED, stats.pkts_processed); - vlib_node_increment_counter (vm, hicn_interest_hitpit_node.index, - HICNFWD_ERROR_INTEREST_AGG, - stats.interests_aggregated); - vlib_node_increment_counter (vm, hicn_interest_hitpit_node.index, - HICNFWD_ERROR_INT_RETRANS, - stats.interests_retx); - vlib_node_increment_counter (vm, hicn_interest_hitpit_node.index, - HICNFWD_ERROR_PIT_EXPIRED, - stats.pit_expired_count); - vlib_node_increment_counter (vm, hicn_interest_hitpit_node.index, - HICNFWD_ERROR_HASH_COLL_HASHTB_COUNT, - stats.interests_hash_collision); - - update_node_counter (vm, hicn_interest_hitpit_node.index, - HICNFWD_ERROR_INT_COUNT, pit_int_count); - - return (frame->n_vectors); -} - -/* packet trace format function */ -static u8 * -hicn_interest_hitpit_format_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 *); - hicn_interest_hitpit_trace_t *t = - va_arg (*args, hicn_interest_hitpit_trace_t *); - - s = format (s, "INTEREST-HITPIT: pkt: %d, sw_if_index %d, next index %d", - (int) t->pkt_type, t->sw_if_index, t->next_index); - return (s); -} - -void -drop_packet (u32 * next0) -{ - *next0 = HICN_INTEREST_HITPIT_NEXT_ERROR_DROP; -} - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(hicn_interest_hitpit_node) = -{ - .function = hicn_interest_hitpit_node_fn, - .name = "hicn-interest-hitpit", - .vector_size = sizeof(u32), - .runtime_data_bytes = sizeof(hicn_interest_hitpit_runtime_t), - .format_trace = hicn_interest_hitpit_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(hicn_interest_hitpit_error_strings), - .error_strings = hicn_interest_hitpit_error_strings, - .n_next_nodes = HICN_INTEREST_HITPIT_N_NEXT, - /* edit / add dispositions here */ - .next_nodes = - { - [HICN_INTEREST_HITPIT_NEXT_INTEREST_HITCS] = "hicn-interest-hitcs", - [HICN_INTEREST_HITPIT_NEXT_STRATEGY] = "hicn-strategy", - [HICN_INTEREST_HITPIT_NEXT_FACE4_OUTPUT] = "hicn4-face-output", - [HICN_INTEREST_HITPIT_NEXT_FACE6_OUTPUT] = "hicn6-face-output", - [HICN_INTEREST_HITPIT_NEXT_ERROR_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/interest_pcslookup.h b/hicn-plugin/src/interest_pcslookup.h deleted file mode 100644 index cbc9dde51..000000000 --- a/hicn-plugin/src/interest_pcslookup.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2017-2019 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_INTEREST_PCSLOOKUP_H__ -#define __HICN_INTEREST_PCSLOOKUP_H__ - -#include -#include - -#include "pcs.h" - -/** - * @file interest_pcslookup.h - * - * This is the node encoutered by interest packets after the hicn6-iface-input or - * hicn4-iface-input. This node performs a lookup in the pit and content store and - * if there is a hit in the PIT, the vlib buffer is passed to the hicn-interest-hitcs - * while if there is a hit in the CS the vlib buffer is passed to the - * hicn-interest-hitpit. If there isn't any hit, the vlib buffer is passed to the - * hicn-strategy node. - */ - -/* - * Node context data; we think this is per-thread/instance - */ -typedef struct hicn_interest_pcslookup_runtime_s -{ - int id; - hicn_pit_cs_t *pitcs; -} hicn_interest_pcslookup_runtime_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; -} hicn_interest_pcslookup_trace_t; - -typedef enum -{ - HICN_INTEREST_PCSLOOKUP_NEXT_STRATEGY, - HICN_INTEREST_PCSLOOKUP_NEXT_INTEREST_HITPIT, - HICN_INTEREST_PCSLOOKUP_NEXT_INTEREST_HITCS, - HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP, - HICN_INTEREST_PCSLOOKUP_N_NEXT, -} hicn_interest_pcslookup_next_t; - -#endif /* // __HICN_INTEREST_PCSLOOKUP_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/interest_pcslookup_node.c b/hicn-plugin/src/interest_pcslookup_node.c deleted file mode 100644 index 6ac2aa3a0..000000000 --- a/hicn-plugin/src/interest_pcslookup_node.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) 2017-2019 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 "interest_pcslookup.h" -#include "mgmt.h" -#include "parser.h" -#include "infra.h" -#include "strategy_dpo_manager.h" -#include "error.h" -#include "state.h" - -/** - * @FILE This node performs a lookup in the PIT and CS for a received interest packet. - * - * This node passes the packet to the interest-hitpit and interest-hitcs nodes - * when there is a hit in the pit or content store, respectively. - */ - -/* Functions declarations */ - -/* packet trace format function */ -static u8 *hicn_interest_pcslookup_format_trace (u8 * s, va_list * args); - - -/* Stats string values */ -static char *hicn_interest_pcslookup_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -vlib_node_registration_t hicn_interest_pcslookup_node; - -/* - * ICN forwarder node for interests: handling of Interests delivered based on - * ACL. - 1 packet at a time - ipv4/tcp ipv6/tcp - */ -static uword -hicn_interest_pcslookup_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next; - 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); - - if (PREDICT_FALSE (rt->pitcs == NULL)) - { - rt->pitcs = &hicn_main.pitcs; - } - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - u32 n_left_to_next; - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *b0; - u8 isv6; - u8 *nameptr; - u16 namelen; - u32 bi0; - u32 next0 = HICN_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; - u8 is_cs0 = 0; - u8 hash_entry_id = 0; - u8 bucket_is_overflown = 0; - u32 bucket_id = ~0; - - /* 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, STORE); - CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, LOAD); - } - /* Dequeue a packet buffer */ - bi0 = from[0]; - from += 1; - n_left_from -= 1; - to_next[0] = bi0; - to_next += 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - 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); - stats.pkts_processed++; - - if (PREDICT_FALSE (ret != HICN_ERROR_NONE || - hicn_hashtb_fullhash (nameptr, namelen, - &name_hash) != - HICN_ERROR_NONE)) - { - next0 = HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP; - } - else - { - if (hicn_hashtb_lookup_node (rt->pitcs->pcs_table, nameptr, - namelen, name_hash, - 0 /* is_data */ , &node_id0, - &dpo_ctx_id0, &vft_id0, &is_cs0, - &hash_entry_id, &bucket_id, - &bucket_is_overflown) == - HICN_ERROR_NONE) - { - next0 = - HICN_INTEREST_PCSLOOKUP_NEXT_INTEREST_HITPIT + is_cs0; - } - stats.pkts_interest_count++; - } - - hicn_store_internal_state (b0, name_hash, node_id0, dpo_ctx_id0, - vft_id0, hash_entry_id, bucket_id, - bucket_is_overflown); - - /* Maybe trace */ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - hicn_interest_pcslookup_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_INTEREST; - t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - t->next_index = next0; - } - /* - * 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); - } - u32 pit_int_count = hicn_pit_get_int_count (rt->pitcs); - u32 pit_cs_count = hicn_pit_get_cs_count (rt->pitcs); - u32 pcs_ntw_count = hicn_pcs_get_ntw_count (rt->pitcs); - - - vlib_node_increment_counter (vm, hicn_interest_pcslookup_node.index, - HICNFWD_ERROR_PROCESSED, stats.pkts_processed); - - vlib_node_increment_counter (vm, hicn_interest_pcslookup_node.index, - HICNFWD_ERROR_INTERESTS, - stats.pkts_interest_count); - - update_node_counter (vm, hicn_interest_pcslookup_node.index, - HICNFWD_ERROR_INT_COUNT, pit_int_count); - - update_node_counter (vm, hicn_interest_pcslookup_node.index, - HICNFWD_ERROR_CS_COUNT, pit_cs_count); - - update_node_counter (vm, hicn_interest_pcslookup_node.index, - HICNFWD_ERROR_CS_NTW_COUNT, pcs_ntw_count); - - return (frame->n_vectors); -} - -/* packet trace format function */ -static u8 * -hicn_interest_pcslookup_format_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 *); - hicn_interest_pcslookup_trace_t *t = - va_arg (*args, hicn_interest_pcslookup_trace_t *); - - s = format (s, "INTEREST_PCSLOOKUP: pkt: %d, sw_if_index %d, next index %d", - (int) t->pkt_type, t->sw_if_index, t->next_index); - return (s); -} - - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(hicn_interest_pcslookup_node) = -{ - .function = hicn_interest_pcslookup_node_fn, - .name = "hicn-interest-pcslookup", - .vector_size = sizeof(u32), - .runtime_data_bytes = sizeof(hicn_interest_pcslookup_runtime_t), - .format_trace = hicn_interest_pcslookup_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(hicn_interest_pcslookup_error_strings), - .error_strings = hicn_interest_pcslookup_error_strings, - .n_next_nodes = HICN_INTEREST_PCSLOOKUP_N_NEXT, - .next_nodes = - { - [HICN_INTEREST_PCSLOOKUP_NEXT_STRATEGY] = "hicn-strategy", - [HICN_INTEREST_PCSLOOKUP_NEXT_INTEREST_HITPIT] = "hicn-interest-hitpit", - [HICN_INTEREST_PCSLOOKUP_NEXT_INTEREST_HITCS] = "hicn-interest-hitcs", - [HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/mapme.h b/hicn-plugin/src/mapme.h deleted file mode 100644 index 17bd9a766..000000000 --- a/hicn-plugin/src/mapme.h +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_MAPME__ -#define __HICN_MAPME__ - -#include -#include -#include - -#include "hicn.h" -#include "route.h" -#include "strategy_dpo_ctx.h" -#include "strategy_dpo_manager.h" // dpo_is_hicn - -/** - * @file - * - * @brief Mapme - * - * Mapme implementation follows the "Anchorless mobility through hICN" document - * specification. In particular, the implementation is made of: - * - two internal nodes: hicn-mapme-ctrl and hicn-mapme-ack. The former processes - * IU and the latter IU acknowledgment. - * - a process node, mapme-eventmgr-process, that is signaled every time a face is - * added or deleted, as well as when a new next hop is added to a fib entry as a - * result of a mobility event. - * - * TFIB implementation is done as an extension of an hICN fib entry. In particular, - * the list of next hops hold the list of next hops in the tfib as well (stored at the - * end of the list of regualt next hops). Mapme implementation follows the hICN vrf - * implementation and consider the vrf 0 (default fib) as the control-plane fib to - * update every time a new next hop must be added or removed. - */ - - -#define HICN_MAPME_ALLOW_LOCATORS 1 - -//#define HICN_MAPME_NOTIFICATIONS 1 - -#define NOT_A_NOTIFICATION false -#define TIMER_NO_REPEAT false - -#define INVALID_SEQ 0 - -STATIC_ASSERT (sizeof(u32) == sizeof(seq_t), - "seq_t is not 4 bytes"); - -typedef struct hicn_mapme_conf_s -{ - hicn_mapme_conf_t conf; - bool remove_dpo; // FIXME used ? - - vlib_main_t *vm; - vlib_log_class_t log_class; -} hicn_mapme_main_t; - -/** - * @brief List of event to signat to the procesing node (eventmgr) - */ -#define foreach_hicn_mapme_event \ - _(FACE_ADD) \ - _(FACE_DEL) \ - _(FACE_APP_ADD) \ - _(FACE_APP_DEL) \ - _(FACE_NH_SET) \ - _(FACE_NH_ADD) \ - _(FACE_PH_ADD) \ - _(FACE_PH_DEL) - -typedef enum -{ -#define _(a) HICN_MAPME_EVENT_##a, - foreach_hicn_mapme_event -#undef _ -} hicn_mapme_event_t; - -typedef hicn_dpo_ctx_t hicn_mapme_tfib_t; - -/* - * Ideally we might need to care about alignment, but this struct is only - * used for casting hicn_dpo_ctx_t. - * - * See otherwise vnet/dpo/dpo.h - */ - -STATIC_ASSERT (sizeof (hicn_mapme_tfib_t) <= sizeof (hicn_dpo_ctx_t), - "hicn_mapme_tfib_t is greater than hicn_dpo_ctx_t"); - -#define TFIB(dpo_ctx) ((hicn_mapme_tfib_t*)(dpo_ctx)) - -static_always_inline int -hicn_mapme_nh_set (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) -{ - hicn_dpo_ctx_t * strategy_ctx = (hicn_dpo_ctx_t *)tfib; - const fib_prefix_t * prefix = fib_entry_get_prefix(strategy_ctx->fib_entry_index); - - u32 n_entries = tfib->entry_count; - /* Remove all the existing next hops and set the new one */ - for (int i = 0; i < n_entries; i++) - { - hicn_face_t * face = hicn_dpoi_get_from_idx(strategy_ctx->next_hops[0]); - ip_adjacency_t * adj = adj_get (face->dpo.dpoi_index); - ip_nh_del_helper(face->dpo.dpoi_proto, prefix, &adj->sub_type.nbr.next_hop, face->sw_if); - } - hicn_face_t * face = hicn_dpoi_get_from_idx(face_id); - ip_nh_add_helper(face->dpo.dpoi_proto, prefix, &face->nat_addr, face->sw_if); - return 0; -} - -/** - * @brief Add a next hop iif it is not already a next hops - */ -static_always_inline int -hicn_mapme_nh_add (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) -{ - for (u8 pos = 0; pos < tfib->entry_count; pos++) - if (tfib->next_hops[pos] == face_id) - return 0; - - /* Add the next hop in the vrf 0 which will add it to the entry in the hICN vrf */ - hicn_dpo_ctx_t * strategy_ctx = (hicn_dpo_ctx_t *)tfib; - const fib_prefix_t * prefix = fib_entry_get_prefix(strategy_ctx->fib_entry_index); - hicn_face_t * face = hicn_dpoi_get_from_idx(face_id); - ip_nh_add_helper(face->dpo.dpoi_proto, prefix, &face->nat_addr, face->sw_if); - - return 0; -} - -/** - * Add a 'previous' hop to the TFIB - * - * XXX we should have the for look in the reverse order for simpler code. - */ -static_always_inline int -hicn_mapme_tfib_add (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) -{ - u8 pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; - - //XXX don 't add if it already exist - // eg.an old IU received on a face on which we are retransmitting - for (u8 pos2 = pos; pos2 < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos2++) - if (tfib->next_hops[pos2] == face_id) - return 0; - - //Make sure we have enough room - if (pos <= tfib->entry_count) - return -1; - - tfib->next_hops[pos - 1] = face_id; - tfib->tfib_entry_count++; - - /* - * Take a lock on the face as if it will be removed from the next_hops a - * lock will be removed. - */ - hicn_face_lock_with_id(face_id); - - return 0; -} - -static_always_inline int -hicn_mapme_tfib_clear (hicn_mapme_tfib_t * tfib) -{ - hicn_face_id_t invalid = NEXT_HOP_INVALID; - /* - * We need to do a linear scan of TFIB entries to find the one to - * remove - */ - u8 start_pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; - u8 pos = ~0; - for (pos = start_pos; pos < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos++) - { - hicn_face_unlock_with_id (tfib->next_hops[pos]); - tfib->next_hops[pos] = invalid; - break; - } - - tfib->tfib_entry_count = 0; - - return 0; -} - -static_always_inline int -hicn_mapme_tfib_del (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) -{ - hicn_face_id_t invalid = NEXT_HOP_INVALID; - /* - * We need to do a linear scan of TFIB entries to find the one to - * remove - */ - u8 start_pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; - u8 pos = ~0; - for (pos = start_pos; pos < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos++) - if (tfib->next_hops[pos] == face_id) - { - hicn_face_unlock_with_id (tfib->next_hops[pos]); - tfib->next_hops[pos] = invalid; - break; - } - if (pos == HICN_PARAM_FIB_ENTRY_NHOPS_MAX) - /* Not found */ - return -1; - - tfib->tfib_entry_count--; - - /* Likely we won't receive a new IU twice from the same face */ - if (PREDICT_TRUE (pos > start_pos)) - memmove (tfib->next_hops + start_pos +1 , tfib->next_hops + start_pos, - (pos - start_pos) * sizeof (hicn_face_id_t)); - - return 0; -} - -/** - * @brief Performs an Exact Prefix Match lookup on the FIB - * @returns the corresponding DPO (hICN or IP LB), or NULL - */ -static_always_inline - dpo_id_t * fib_epm_lookup (ip46_address_t * addr, u8 plen) -{ - fib_prefix_t fib_pfx; - fib_node_index_t fib_entry_index; - u32 fib_index; - dpo_id_t *dpo_id; - load_balance_t *lb; - - const dpo_id_t *load_balance_dpo_id; - - /* At this point the face exists in the face table */ - fib_prefix_from_ip46_addr (addr, &fib_pfx); - fib_pfx.fp_len = plen; - - /* Check if the route already exist in the fib : EPM */ - fib_index = fib_table_find (fib_pfx.fp_proto, HICN_FIB_TABLE); - - fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx); - if (fib_entry_index == FIB_NODE_INDEX_INVALID) - return NULL; - - load_balance_dpo_id = fib_entry_contribute_ip_forwarding (fib_entry_index); - - /* The dpo is not a load balance dpo as expected */ - if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) - return NULL; - - /* former_dpo_id is a load_balance dpo */ - lb = load_balance_get (load_balance_dpo_id->dpoi_index); - - /* Check if there is only one bucket */ - - /* - * We now distinguish the case where we have an hICN route (the - * regular case), and the case where we have an IP route, to be able - * to apply MAP-Me mechanisms even to a locator IP address. - */ - - for (int i = 0; i < lb->lb_n_buckets; i++) - { - /* un-const */ - dpo_id = (dpo_id_t *) load_balance_get_bucket_i (lb, i); - - if (dpo_is_hicn (dpo_id)) - return dpo_id; - } - - /* un-const */ - return (dpo_id_t *) load_balance_dpo_id; -} - -/* DPO types */ - -extern dpo_type_t hicn_face_udp_type; -extern dpo_type_t hicn_face_ip_type; - -/* VLIB EDGE IDs */ - -/* in faces/ip/face_ip.c */ -extern u32 strategy_face_ip4_vlib_edge; -extern u32 strategy_face_ip6_vlib_edge; -/* in faces/udp/face_udp.c */ -extern u32 strategy_face_udp4_vlib_edge; -extern u32 strategy_face_udp6_vlib_edge; - - -/** - * @brief Returns the next hop vlib edge on which we can send an Interest packet. - * - * This is both used to preprocess a dpo that will be stored as a next hop in the FIB, and to determine on which node to send an Interest Update. - */ -always_inline u32 -hicn_mapme_get_dpo_vlib_edge (dpo_id_t * dpo) -{ - if (dpo->dpoi_type == hicn_face_ip_type) - { - switch (dpo->dpoi_proto) - { - case DPO_PROTO_IP4: - return strategy_face_ip4_vlib_edge; - case DPO_PROTO_IP6: - return strategy_face_ip6_vlib_edge; - default: - return ~0; - } - } - else if (dpo->dpoi_type == hicn_face_udp_type) - { - switch (dpo->dpoi_proto) - { - case DPO_PROTO_IP4: - return strategy_face_udp4_vlib_edge; - case DPO_PROTO_IP6: - return strategy_face_udp6_vlib_edge; - default: - return ~0; - } - } - else - { - return ~0; - } -} - -/** - * @brief Returns the next hop node on which we can send an Update packet - */ -always_inline char * -hicn_mapme_get_dpo_face_node (hicn_face_id_t face_id) -{ - hicn_face_t * face = hicn_dpoi_get_from_idx(face_id); - - switch (face->dpo.dpoi_proto) - { - case DPO_PROTO_IP4: - return "hicn4-face-output"; - case DPO_PROTO_IP6: - return "hicn6-face-output"; - default: - return NULL; - } -} - -#define DEBUG(...) //vlib_log_debug(mapme_main.log_class, __VA_ARGS__) -#define WARN(...) //vlib_log_warn(mapme_main.log_class, __VA_ARGS__) -#define ERROR(...) //vlib_log_err(mapme_main.log_class, __VA_ARGS__) - -#endif /* __HICN_MAPME__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/mapme_ack.h b/hicn-plugin/src/mapme_ack.h deleted file mode 100644 index 821baf203..000000000 --- a/hicn-plugin/src/mapme_ack.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2017-2019 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. - */ - -/* - * Copyright (c) 2017-2019 by Cisco Systems Inc. All Rights Reserved. - * - */ - -#ifndef HICN_MAPME_ACK_H -#define HICN_MAPME_ACK_H - -#include -#include - -/** - * @file - * - */ - -/* Node context data */ -typedef struct hicn_mapme_ack_runtime_s -{ - int id; -} hicn_mapme_ack_runtime_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; -} hicn_mapme_ack_trace_t; - -typedef enum -{ - HICN_MAPME_ACK_NEXT_ERROR_DROP, - HICN_MAPME_ACK_N_NEXT, -} hicn_mapme_ack_next_t; - -#endif /* HICN_MAPME_ACK_H */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/mapme_ack_node.c b/hicn-plugin/src/mapme_ack_node.c deleted file mode 100644 index f26895d20..000000000 --- a/hicn-plugin/src/mapme_ack_node.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "hicn.h" -#include "mapme.h" -#include "mapme_ack.h" -#include "mapme_eventmgr.h" -#include "mgmt.h" -#include "parser.h" -#include "data_fwd.h" -#include "infra.h" -#include "strategy_dpo_manager.h" -#include "error.h" -#include "state.h" - -extern hicn_mapme_main_t mapme_main; - -/* packet trace format function */ -static u8 *hicn_mapme_ack_format_trace (u8 * s, va_list * args); - - -/* Stats string values */ -static char *hicn_mapme_ack_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -/* - * @brief Process incoming ack messages (Interest Update Ack) - * @param vm vlib main data structure - * @param b Control packet (IU) - * @param face_id Ingress face id - */ -bool -hicn_mapme_process_ack (vlib_main_t * vm, vlib_buffer_t * b, - hicn_face_id_t in_face) -{ - seq_t fib_seq; - const dpo_id_t *dpo; - hicn_prefix_t prefix; - mapme_params_t params; - int rc; - - /* Parse incoming message */ - rc = - hicn_mapme_parse_packet (vlib_buffer_get_current (b), &prefix, ¶ms); - if (rc < 0) - goto ERR_PARSE; - - /* if (params.seq == INVALID_SEQ) */ - /* { */ - /* DEBUG ("Invalid sequence number found in IU"); */ - /* return true; */ - /* } */ - - dpo = fib_epm_lookup (&(prefix.name), prefix.len); - if (!dpo) - { - DEBUG ("Ignored ACK for non-existing FIB entry. Ignored."); - return true; - - } - - /* We are only expecting ACKs for hICN DPOs */ - ASSERT (dpo_is_hicn (dpo)); - - hicn_mapme_tfib_t *tfib = - TFIB (hicn_strategy_dpo_ctx_get (dpo->dpoi_index)); - - if (tfib == NULL) - { - WARN ("Unable to get strategy ctx."); - return false; - } - - fib_seq = tfib->seq; - - /* - * As we always retransmit IU with the latest seq, we are not interested in - * ACKs with inferior seq - */ - if (params.seq < fib_seq) - { - DEBUG ("Ignored ACK for low seq"); - return true; - } - - hicn_mapme_tfib_del (tfib, in_face); - - /* - * Is the ingress face in TFIB ? if so, remove it, otherwise it might be a - * duplicate - */ - retx_t *retx = vlib_process_signal_event_data (vm, - hicn_mapme_eventmgr_process_node. - index, - HICN_MAPME_EVENT_FACE_PH_DEL, - 1, - sizeof (retx_t)); - *retx = (retx_t) - { - .prefix = prefix, - .dpo = *dpo - }; - - return true; - -ERR_PARSE: - return false; -} - -vlib_node_registration_t hicn_mapme_ack_node; - -static uword -hicn_mapme_ack_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - hicn_buffer_t *hb; - hicn_mapme_ack_next_t next_index; - u32 n_left_from, *from, *to_next; - n_left_from = frame->n_vectors; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) // buffers in the current frame - { - u32 n_left_to_next; - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0; - vlib_buffer_t *b0; - u32 next0 = HICN_MAPME_ACK_NEXT_ERROR_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); - - vlib_cli_output (vm, "Received IUAck"); - hb = hicn_get_buffer (b0); - hicn_mapme_process_ack (vm, b0, hb->face_id); - - /* Single loop: process 1 packet here */ - sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) - && (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - hicn_mapme_ack_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->sw_if_index = sw_if_index0; - t->next_index = next0; - } - /* $$$$$ Done processing 1 packet here $$$$$ */ - - /* 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_mapme_ack_node.index, -// HICN_MAPME_ACK_ERROR_SWAPPED, pkts_swapped); - return (frame->n_vectors); -} - -/* packet trace format function */ -static u8 * -hicn_mapme_ack_format_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 *); - hicn_mapme_ack_trace_t *t = va_arg (*args, hicn_mapme_ack_trace_t *); - - s = format (s, "MAPME_ACK: pkt: %d, sw_if_index %d, next index %d", - (int) t->pkt_type, t->sw_if_index, t->next_index); - return (s); -} - - -/* - * Node registration for the MAP-Me node processing special interests - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (hicn_mapme_ack_node) = -{ - .function = hicn_mapme_ack_node_fn, - .name = "hicn-mapme-ack", - .vector_size = sizeof (u32), - .runtime_data_bytes = sizeof (hicn_mapme_ack_runtime_t), - .format_trace = hicn_mapme_ack_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN (hicn_mapme_ack_error_strings), - .error_strings = hicn_mapme_ack_error_strings, - .n_next_nodes = HICN_MAPME_ACK_N_NEXT, - .next_nodes = - { - [HICN_MAPME_ACK_NEXT_ERROR_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/mapme_ctrl.h b/hicn-plugin/src/mapme_ctrl.h deleted file mode 100644 index 9af4beccc..000000000 --- a/hicn-plugin/src/mapme_ctrl.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2017-2020 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. - */ - -/* - * Copyright (c) 2017-2019 by Cisco Systems Inc. All Rights Reserved. - * - */ - -#ifndef HICN_MAPME_CTRL_H -#define HICN_MAPME_CTRL_H - -#include -#include - -/** - * @file mapme_ctrl.h - * - */ - -/* Node context data */ -typedef struct hicn_mapme_ctrl_runtime_s -{ - int id; -} hicn_mapme_ctrl_runtime_t; - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; -} hicn_mapme_ctrl_trace_t; - -typedef enum -{ - HICN_MAPME_CTRL_NEXT_IP4_OUTPUT, - HICN_MAPME_CTRL_NEXT_IP6_OUTPUT, - HICN_MAPME_CTRL_NEXT_ERROR_DROP, - HICN_MAPME_CTRL_N_NEXT, -} hicn_mapme_ctrl_next_t; -/** - * @brief Returns the next hop node on which we can send an ACK packet - */ -always_inline hicn_mapme_ctrl_next_t -hicn_mapme_ctrl_get_iface_node (hicn_face_id_t face_id) -{ - hicn_face_t * face = hicn_dpoi_get_from_idx(face_id); - - switch (face->dpo.dpoi_proto) - { - case DPO_PROTO_IP4: - return HICN_MAPME_CTRL_NEXT_IP4_OUTPUT; - case DPO_PROTO_IP6: - return HICN_MAPME_CTRL_NEXT_IP6_OUTPUT; - default: - return HICN_MAPME_CTRL_NEXT_ERROR_DROP; - } -} - -#endif /* HICN_MAPME_CTRL_H */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/mapme_ctrl_node.c b/hicn-plugin/src/mapme_ctrl_node.c deleted file mode 100644 index a0be2be1d..000000000 --- a/hicn-plugin/src/mapme_ctrl_node.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (c) 2017-2020 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. - */ - -/* - * This node processses MAP-Me control messages. - */ -#include -#include - -#include "hicn.h" -#include "mapme.h" -#include "mapme_ctrl.h" -#include "mapme_eventmgr.h" -#include "mgmt.h" -#include "parser.h" -#include "infra.h" -#include "strategy_dpo_manager.h" -#include "strategy_dpo_ctx.h" -#include "error.h" -#include "state.h" - -extern hicn_mapme_main_t mapme_main; - -#define MS2NS(x) x * 1000000 - -/* Functions declarations */ - -/* packet trace format function */ -static u8 *hicn_mapme_ctrl_format_trace (u8 * s, va_list * args); - - -/* Stats string values */ -static char *hicn_mapme_ctrl_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -/* - * @brief Process incoming control messages (Interest Update) - * @param vm vlib main data structure - * @param b Control packet (IU) - * @param face_id Ingress face id - * - * NOTE: - * - this function answers locally to the IU interest by replying with a Ack - * (Data) packet, unless in case of outdated information, in which we can - * consider the interest is dropped, and another IU (aka ICMP error) is sent so - * that retransmissions stop. - */ -static_always_inline bool -hicn_mapme_process_ctrl (vlib_main_t * vm, vlib_buffer_t * b, - hicn_face_id_t in_face_id) -{ - seq_t fib_seq; - const dpo_id_t *dpo; - hicn_prefix_t prefix; - mapme_params_t params; - int rc; - - /* Parse incoming message */ - rc = - hicn_mapme_parse_packet (vlib_buffer_get_current (b), &prefix, ¶ms); - if (rc < 0) - goto ERR_PARSE; - - vlib_cli_output (vm, "IU - type:%d seq:%d len:%d", params.type, params.seq, - prefix.len); - - /* if (params.seq == INVALID_SEQ) */ - /* { */ - /* vlib_log_warn (mapme_main.log_class, */ - /* "Invalid sequence number found in IU"); */ - - /* return true; */ - /* } */ - - /* We forge the ACK which we be the packet forwarded by the node */ - hicn_mapme_create_ack (vlib_buffer_get_current (b), ¶ms); - - dpo = fib_epm_lookup (&prefix.name, prefix.len); - if (!dpo) - { -#ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY - /* - * This might happen for a node hosting a producer which has moved. - * Destroying the face has led to removing all corresponding FIB - * entries. In that case, we need to correctly restore the FIB entries. - */ - DEBUG ("Re-creating FIB entry with next hop on connection") -#error "not implemented" -#else - //ERROR("Received IU for non-existing FIB entry"); - return false; -#endif /* HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY */ - - } - -#ifdef HICN_MAPME_ALLOW_LOCATORS - if (!dpo_is_hicn ((dpo))) - { - /* We have an IP DPO */ - WARN ("Not implemented yet."); - return false; - } -#endif - - /* Process the hICN DPO */ - hicn_mapme_tfib_t *tfib = - TFIB (hicn_strategy_dpo_ctx_get (dpo->dpoi_index)); - - if (tfib == NULL) - { - WARN ("Unable to get strategy ctx."); - return false; - } - - fib_seq = tfib->seq; - - if (params.seq > fib_seq) - { - DEBUG - ("Higher sequence number than FIB %d > %d, updating seq and next hops", - params.seq, fib_seq); - - /* This has to be done first to allow processing ack */ - tfib->seq = params.seq; - - // in_face and next_hops are face_id_t - - /* Remove ingress face from TFIB in case it was present */ - hicn_mapme_tfib_del (tfib, in_face_id); - - /* Move next hops to TFIB... but in_face... */ - for (u8 pos = 0; pos < tfib->entry_count; pos++) - { - hicn_face_t * face = hicn_dpoi_get_from_idx(tfib->next_hops[pos]); - hicn_face_t * in_face = hicn_dpoi_get_from_idx(in_face_id); - if (dpo_is_adj(&face->dpo)) - { - ip_adjacency_t * adj = adj_get (dpo->dpoi_index); - if (ip46_address_cmp(&(adj->sub_type.nbr.next_hop), &(in_face->nat_addr))== 0) - break; - } - DEBUG - ("Adding nexthop to the tfib, dpo index in_face %d, dpo index tfib %d", - in_face_id, tfib->next_hops[pos]); - hicn_mapme_tfib_add (tfib, tfib->next_hops[pos]); - } - - hicn_mapme_nh_set (tfib, in_face_id); - - /* We transmit both the prefix and the full dpo (type will be needed to pick the right transmit node */ - retx_t *retx = vlib_process_signal_event_data (vm, - hicn_mapme_eventmgr_process_node. - index, - HICN_MAPME_EVENT_FACE_NH_SET, - 1, - sizeof (retx_t)); - *retx = (retx_t) - { - .prefix = prefix, - .dpo = *dpo - }; - - } - else if (params.seq == fib_seq) - { - DEBUG ("Same sequence number than FIB %d > %d, adding next hop", - params.seq, fib_seq); - - /* Remove ingress face from TFIB in case it was present */ - hicn_mapme_tfib_del (tfib, in_face_id); - - /* Add ingress face to next hops */ - hicn_mapme_nh_add (tfib, in_face_id); - - /* Multipath, multihoming, multiple producers or duplicate interest */ - retx_t *retx = vlib_process_signal_event_data (vm, - hicn_mapme_eventmgr_process_node. - index, - HICN_MAPME_EVENT_FACE_NH_ADD, - 1, - sizeof (retx_t)); - *retx = (retx_t) - { - .prefix = prefix, - .dpo = *dpo - }; - } - else // params.seq < fib_seq - { - /* - * face is propagating outdated information, we can just consider it as a - * prevHops - */ - hicn_mapme_tfib_add (tfib, in_face_id); - - retx_t *retx = vlib_process_signal_event_data (vm, - hicn_mapme_eventmgr_process_node. - index, - HICN_MAPME_EVENT_FACE_PH_ADD, - 1, - sizeof (retx_t)); - *retx = (retx_t) - { - .prefix = prefix, - .dpo = *dpo - }; - } - - /* We just raise events, the event_mgr is in charge of forging packet. */ - - return true; - -//ERR_ACK_CREATE: -ERR_PARSE: - return false; -} - -vlib_node_registration_t hicn_mapme_ctrl_node; - -static uword -hicn_mapme_ctrl_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - hicn_buffer_t *hb; - hicn_mapme_ctrl_next_t next_index; - u32 n_left_from, *from, *to_next; - n_left_from = frame->n_vectors; - //hicn_face_id_t in_face; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) // buffers in the current frame - { - u32 n_left_to_next; - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0; - vlib_buffer_t *b0; - - /* 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); - hb = hicn_get_buffer (b0); - - /* This determines the next node on which the ack will be sent back */ - u32 next0 = hicn_mapme_ctrl_get_iface_node (hb->face_id); - - hicn_mapme_process_ctrl (vm, b0, hb->face_id); - - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = hb->face_id; - - 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_mapme_ctrl_node.index, - // HICN_MAPME_CTRL_ERROR_SWAPPED, pkts_swapped); - return frame->n_vectors; -} - -/* packet trace format function */ -static u8 * -hicn_mapme_ctrl_format_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 *); - hicn_mapme_ctrl_trace_t *t = va_arg (*args, hicn_mapme_ctrl_trace_t *); - - s = format (s, "MAPME_CTRL: pkt: %d, sw_if_index %d, next index %d", - (int) t->pkt_type, t->sw_if_index, t->next_index); - return (s); -} - - -/* - * Node registration for the MAP-Me node processing special interests - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (hicn_mapme_ctrl_node) = -{ - .function = hicn_mapme_ctrl_node_fn, - .name = "hicn-mapme-ctrl", - .vector_size = sizeof (u32), - .runtime_data_bytes = sizeof (hicn_mapme_ctrl_runtime_t), - .format_trace = hicn_mapme_ctrl_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN (hicn_mapme_ctrl_error_strings), - .error_strings = hicn_mapme_ctrl_error_strings, - .n_next_nodes = HICN_MAPME_CTRL_N_NEXT, - .next_nodes = - { - /* - * Control packets are not forwarded by this node, but sent by the Event - * Manager. This node is only responsible for sending ACK back, - * Acks are like data packets are output on iface's - */ - [HICN_MAPME_CTRL_NEXT_IP4_OUTPUT] = "hicn4-iface-output", - [HICN_MAPME_CTRL_NEXT_IP6_OUTPUT] = "hicn6-iface-output", - [HICN_MAPME_CTRL_NEXT_ERROR_DROP] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/mapme_eventmgr.c b/hicn-plugin/src/mapme_eventmgr.c deleted file mode 100644 index d8b7562f8..000000000 --- a/hicn-plugin/src/mapme_eventmgr.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "hicn.h" -#include "strategy_dpo_ctx.h" -#include "mapme.h" -#include "mapme_eventmgr.h" -#include "strategies/dpo_mw.h" - -#include -#include - -#define DEFAULT_TIMEOUT 1.0 /* s */ - -hicn_mapme_main_t mapme_main; - -hicn_prefix_t *retx_pool; -uword *retx_hash; - -void -hicn_mapme_init (vlib_main_t * vm) -{ - mapme_main.vm = vm; - mapme_main.log_class = vlib_log_register_class ("hicn_mapme", 0); -} - -/* borrowed from vnet/fib/ip4_fib.c */ - -typedef struct ip4_fib_show_walk_ctx_t_ -{ - fib_node_index_t *ifsw_indicies; -} ip4_fib_show_walk_ctx_t; - -static fib_table_walk_rc_t -ip4_fib_show_walk_cb (fib_node_index_t fib_entry_index, void *arg) -{ - ip4_fib_show_walk_ctx_t *ctx = arg; - - vec_add1 (ctx->ifsw_indicies, fib_entry_index); - - return (FIB_TABLE_WALK_CONTINUE); -} - -/* borrowed from vnet/fib/ip6_fib.c */ - -typedef struct ip6_fib_show_ctx_t_ -{ - fib_node_index_t *entries; -} ip6_fib_show_ctx_t; - -static fib_table_walk_rc_t -ip6_fib_table_show_walk (fib_node_index_t fib_entry_index, void *arg) -{ - ip6_fib_show_ctx_t *ctx = arg; - - vec_add1 (ctx->entries, fib_entry_index); - - return (FIB_TABLE_WALK_CONTINUE); -} - -void -hicn_mapme_process_fib_entry (vlib_main_t * vm, hicn_face_id_t face, - const fib_node_index_t * fib_entry_index) -{ - const dpo_id_t *load_balance_dpo_id; - load_balance_t *lb; - dpo_id_t *dpo_id; - fib_entry_t *fib_entry; - - load_balance_dpo_id = fib_entry_contribute_ip_forwarding (*fib_entry_index); - - /* The dpo is not a load balance dpo as expected */ - if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) - return; - - /* former_dpo_id is a load_balance dpo */ - lb = load_balance_get (load_balance_dpo_id->dpoi_index); - - for (int i = 0; i < lb->lb_n_buckets; i++) - { - /* un-const */ - dpo_id = (dpo_id_t *) load_balance_get_bucket_i (lb, i); - - if (dpo_is_hicn (dpo_id)) - { - fib_entry = fib_entry_get (*fib_entry_index); - vlib_cli_output (vm, "set face pending %U", format_fib_prefix, - &fib_entry->fe_prefix); - } - } -} - -void -hicn_mapme_process_ip4_fib (vlib_main_t * vm, hicn_face_id_t face) -{ - ip4_main_t *im4 = &ip4_main; - fib_table_t *fib_table; - int table_id = -1, fib_index = ~0; - - /* *INDENT-OFF* */ - pool_foreach (fib_table, im4->fibs, - ({ - ip4_fib_t *fib = pool_elt_at_index(im4->v4_fibs, fib_table->ft_index); - - if (table_id >= 0 && table_id != (int)fib->table_id) - continue; - if (fib_index != ~0 && fib_index != (int)fib->index) - continue; - - fib_node_index_t *fib_entry_index; - ip4_fib_show_walk_ctx_t ctx = { - .ifsw_indicies = NULL, - }; - - ip4_fib_table_walk(fib, ip4_fib_show_walk_cb, &ctx); - //vec_sort_with_function(ctx.ifsw_indicies, fib_entry_cmp_for_sort); - - vec_foreach(fib_entry_index, ctx.ifsw_indicies) - { - hicn_mapme_process_fib_entry(vm, face, fib_entry_index); - } - - vec_free(ctx.ifsw_indicies); - })); - /* *INDENT-ON* */ -} - -void -hicn_mapme_process_ip6_fib (vlib_main_t * vm, hicn_face_id_t face) -{ - /* Walk IPv6 FIB */ - ip6_main_t *im6 = &ip6_main; - fib_table_t *fib_table; - ip6_fib_t *fib; - int table_id = -1, fib_index = ~0; - - /* *INDENT-OFF* */ - pool_foreach (fib_table, im6->fibs, - ({ - fib = pool_elt_at_index(im6->v6_fibs, fib_table->ft_index); - - if (table_id >= 0 && table_id != (int)fib->table_id) - continue; - if (fib_index != ~0 && fib_index != (int)fib->index) - continue; - if (fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL) - continue; - - fib_node_index_t *fib_entry_index; - ip6_fib_show_ctx_t ctx = { - .entries = NULL, - }; - - ip6_fib_table_walk(fib->index, ip6_fib_table_show_walk, &ctx); - //vec_sort_with_function(ctx.entries, fib_entry_cmp_for_sort); - - vec_foreach(fib_entry_index, ctx.entries) - { - hicn_mapme_process_fib_entry(vm, face, fib_entry_index); - } - - vec_free(ctx.entries); - - })); - /* *INDENT-ON* */ -} - - -/** - * Callback called everytime a new face is created (not including app faces) - */ -void -hicn_mapme_on_face_added (vlib_main_t * vm, hicn_face_id_t face) -{ - hicn_mapme_process_ip4_fib (vm, face); - hicn_mapme_process_ip6_fib (vm, face); -} - -/* - * We need a retransmission pool holding all necessary information for crafting - * special interests, thus including both the DPO and the prefix associated to - * it. - */ -#define NUM_RETX_ENTRIES 100 -#define NUM_RETX_SLOT 2 -#define NEXT_SLOT(cur) (1-cur) -#define CUR retx_array[cur] -#define NXT retx_array[NEXT_SLOT(cur)] -#define CURLEN retx_len[cur] -#define NXTLEN retx_len[NEXT_SLOT(cur)] - -static_always_inline void * -get_packet_buffer (vlib_main_t * vm, u32 node_index, u32 dpoi_index, - ip46_address_t * addr, hicn_type_t type) -{ - vlib_frame_t *f; - vlib_buffer_t *b; // for newly created packet - u32 *to_next; - u32 bi; - u8 *buffer; - - if (vlib_buffer_alloc (vm, &bi, 1) != 1) - { - clib_warning ("buffer allocation failure"); - return NULL; - } - - /* Create a new packet from scratch */ - b = vlib_get_buffer (vm, bi); - ASSERT (b->current_data == 0); - - /* Face information for next hop node index */ - vnet_buffer (b)->ip.adj_index[VLIB_TX] = dpoi_index; - hicn_get_buffer (b)->type = type; - - /* Enqueue the packet right now */ - f = vlib_get_frame_to_node (vm, node_index); - to_next = vlib_frame_vector_args (f); - to_next[0] = bi; - f->n_vectors = 1; - vlib_put_frame_to_node (vm, node_index, f); - - // pointer to IP layer ? do we need to prepare for ethernet ??? - buffer = vlib_buffer_get_current (b); - b->current_length = - (type.l1 == IPPROTO_IPV6) ? HICN_MAPME_V6_HDRLEN : HICN_MAPME_V4_HDRLEN; - - return buffer; -} - -static_always_inline bool -hicn_mapme_send_message (vlib_main_t * vm, const hicn_prefix_t * prefix, - mapme_params_t * params, hicn_face_id_t face) -{ - size_t n; - - /* This should be retrieved from face information */ - DEBUG ("Retransmission for prefix %U seq=%d", format_ip46_address, - &prefix->name, IP46_TYPE_ANY, params->seq); - - char *node_name = hicn_mapme_get_dpo_face_node (face); - if (!node_name) - { - clib_warning - ("Could not determine next node for sending MAP-Me packet"); - return false; - } - - vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) node_name); - u32 node_index = node->index; - - u8 *buffer = get_packet_buffer (vm, node_index, face, - (ip46_address_t *) prefix, - (params->protocol == - IPPROTO_IPV6) ? HICN_TYPE_IPV6_ICMP : - HICN_TYPE_IPV4_ICMP); - n = hicn_mapme_create_packet (buffer, prefix, params); - if (n <= 0) - { - clib_warning ("Could not create MAP-Me packet"); - return false; - } - - return true; -} - -static_always_inline void -hicn_mapme_send_updates (vlib_main_t * vm, hicn_prefix_t * prefix, - dpo_id_t dpo, bool send_all) -{ - hicn_mapme_tfib_t *tfib = TFIB (hicn_strategy_dpo_ctx_get (dpo.dpoi_index)); - if (!tfib) - { - DEBUG ("NULL TFIB entry id=%d", dpo.dpoi_index); - return; - } - - u8 tfib_last_idx = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; - - mapme_params_t params = { - .protocol = ip46_address_is_ip4 (&prefix->name) - ? IPPROTO_IP : IPPROTO_IPV6, - .type = UPDATE, - .seq = tfib->seq, - }; - - if (send_all) - { - for (u8 pos = tfib_last_idx; pos < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; - pos++) - { - hicn_mapme_send_message (vm, prefix, ¶ms, - tfib->next_hops[pos]); - } - } - else - { - hicn_mapme_send_message (vm, prefix, ¶ms, - tfib->next_hops[tfib_last_idx]); - } -} - -static uword -hicn_mapme_eventmgr_process (vlib_main_t * vm, - vlib_node_runtime_t * rt, vlib_frame_t * f) -{ - f64 timeout = 0; /* By default, no timer is run */ - f64 current_time, due_time; - u8 idle = 0; - - retx_t retx_array[NUM_RETX_SLOT][NUM_RETX_ENTRIES]; - memset (retx_array, 0, NUM_RETX_SLOT * NUM_RETX_ENTRIES); - u8 retx_len[NUM_RETX_SLOT] = { 0 }; - u8 cur = 0; /* current slot */ - - hicn_mapme_init (vm); - - for (;;) - { - /* NOTE: returned timeout seems to always be 0 with get_event_data - * instead of get_event, and we thus need to reimplement timeout - * management on top, as done elsewhere in VPP code. - * - * The most probable event. For simplicity, for new faces, we pass the same retx_t with no - * prefix - */ - if (timeout != 0) - { - /* timeout = */ vlib_process_wait_for_event_or_clock (vm, timeout); - current_time = vlib_time_now (vm); - - /* - * As we don't accummulate errors, we allow for simple timer - * management with no error correction accounting for elapsed time. - * Also, we only run a timer when there are pending retransmissions. - */ - timeout = - (due_time > - current_time) ? due_time - current_time : DEFAULT_TIMEOUT; - due_time = current_time + timeout; - } - else - { - vlib_process_wait_for_event (vm); - } - - uword event_type = ~0; - void *event_data = vlib_process_get_event_data (vm, &event_type); - - switch (event_type) - { - case HICN_MAPME_EVENT_FACE_ADD: - { - /* - * A face has been added: - * - In case of a local app face, we need to advertise a new prefix - * - For another local face type, we need to advertise local - * prefixes and schedule retransmissions - */ - retx_t *retx_events = event_data; - for (u8 i = 0; i < vec_len (retx_events); i++) - { - hicn_mapme_on_face_added (vm, retx_events[i].face_id); - } - idle = 0; - } - break; - - case HICN_MAPME_EVENT_FACE_DEL: - idle = 0; - break; - - case HICN_MAPME_EVENT_FACE_NH_SET: - { - /* - * An hICN FIB entry has been modified. All operations so far - * have been procedded in the nodes. Here we need to track - * retransmissions upon timeout: we mark the FIB entry as pending in - * the second-to-next slot - */ - - /* Mark FIB entry as pending for second-to-next slot */ - retx_t *retx_events = event_data; - for (u8 i = 0; i < vec_len (retx_events); i++) - { - /* - * retx_events[i] corresponds to the dpoi_index of the (T)FIB - * structure that has been modified. Multiple successive - * events might correspond to the same entry. - * - * The FIB entry has a new next hop, and its TFIB section has: - * - eventually previous prev hops for which a IU with a - * lower seqno has been sent - * - the prev hops that have just been added. - * - * We don't distinguish any and just send an updated IU to all - * of them. The retransmission of the latest IU to all - * facilitates the matching of ACKs to a single seqno which is - * the one stored in the FIB. - * - * Since we retransmit to all prev hops, we can remove this - * (T)FIB entry for the check at the end of the current slot. - */ - retx_t *retx = (retx_t *) & retx_events[i]; - - retx->rtx_count = 0; - /* - * Transmit IU for all TFIB entries with latest seqno (we have - * at least one for sure!) - */ - hicn_mapme_send_updates (vm, &retx->prefix, retx->dpo, true); - - /* Delete entry_id from retransmissions in the current slot (if present) ... */ - for (u8 j = 0; j < CURLEN; j++) - if (!dpo_cmp (&(CUR[j].dpo), &retx->dpo)) - { - CUR[j].dpo.dpoi_index = ~0; /* sufficient */ - } - - /* ... and schedule it for next slot (if not already) */ - u8 j; - for (j = 0; j < NXTLEN; j++) - if (!dpo_cmp (&NXT[j].dpo, &retx->dpo)) - break; - if (j == NXTLEN) /* not found */ - NXT[NXTLEN++] = *retx; - } - idle = 0; - } - break; - - case HICN_MAPME_EVENT_FACE_NH_ADD: - /* - * As per the description of states, this event should add the face - * to the list of next hops, and eventually remove it from TFIB. - * This corresponds to the multipath case. - * - * In all cases, we assume the propagation was already done when the first - * interest with the same sequence number was received, so we stop here - * No change in TFIB = no IU to send - * - * No change in timers. - */ - vlib_cli_output (vm, "[hicn_event_mgr] ADD NEXT HOP IN FIB"); - - /* Add ingress face as next hop */ - idle = 0; - - break; - - case HICN_MAPME_EVENT_FACE_PH_ADD: - /* Back-propagation, interesting even for IN (desync) */ - { - retx_t *retx_events = event_data; - for (u8 i = 0; i < vec_len (retx_events); i++) - { - hicn_mapme_send_updates (vm, &retx_events[i].prefix, - retx_events[i].dpo, false); - } - idle = 0; - } - break; - - case HICN_MAPME_EVENT_FACE_PH_DEL: - /* Ack : remove an element from TFIB */ - break; - - case ~0: - /* Timeout occurred, we have to retransmit IUs for all pending - * prefixes having entries in TFIB - * - * timeouts are slotted - * | | | | - * - * ^ - * +- event occurred - * new face, wait for the second next - * (having two arrays and swapping cur and next) - * retx : put in next - */ - idle += 1; - for (u8 pos = 0; pos < CURLEN; pos++) - { - retx_t *retx = &CUR[pos]; - - if (retx->dpo.dpoi_index == ~0) /* deleted entry */ - continue; - - hicn_mapme_tfib_t *tfib = - TFIB (hicn_strategy_dpo_ctx_get (retx->dpo.dpoi_index)); - if (!tfib) - { - DEBUG ("NULL TFIB entry for dpoi_index=%d", - retx->dpo.dpoi_index); - continue; - } - - hicn_mapme_send_updates (vm, &retx->prefix, retx->dpo, true); - - retx->rtx_count++; - // If we exceed the numver of retransmittion it means that all tfib entries have seens at least HICN_PARAM_RTX_MAX of retransmission - if (retx->rtx_count < HICN_PARAM_RTX_MAX) - { - /* - * We did some retransmissions, so let's reschedule a check in the - * next slot - */ - NXT[NXTLEN++] = CUR[pos]; - idle = 0; - } - else - { - hicn_mapme_tfib_clear (tfib); - } - } - - /* Reset events in this slot and prepare for next one */ - CURLEN = 0; - cur = NEXT_SLOT (cur); - - /* After two empty slots, we disable the timer */ - - break; - } - - if (event_data) - vlib_process_put_event_data (vm, event_data); - - timeout = (idle > 1) ? 0 : DEFAULT_TIMEOUT; - - // if (vlib_process_suspend_time_is_zero (timeout)) { ... } - - } - - /* NOTREACHED */ - return 0; -} - -/* Not static as we need to access it from hicn_face */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (hicn_mapme_eventmgr_process_node) = { //,static) = { - .function = hicn_mapme_eventmgr_process, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "mapme-eventmgr-process", - .process_log2_n_stack_bytes = 16, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/mapme_eventmgr.h b/hicn-plugin/src/mapme_eventmgr.h deleted file mode 100644 index b63d16805..000000000 --- a/hicn-plugin/src/mapme_eventmgr.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 // vlib_node_registration_t (vlib/node.h) - -#include - -/** - * @file mapme_eventmgr.h - * - */ - -/* - * Structure carrying all necessary information for managing Special Interest - * (re)transmissions. - */ -typedef struct -{ - hicn_prefix_t prefix; - dpo_id_t dpo; - hicn_face_id_t face_id; - u8 rtx_count; // Number of retransmissions since last tfib addition -} retx_t; - -#define HASH32(x) ((u16)x ^ (x << 16)) - -/** - * @brief This is a process node reacting to face events. - */ -// not static ! -vlib_node_registration_t hicn_mapme_eventmgr_process_node; - -/** - * @brief Initialize MAP-Me on forwarder - * @params vm - vlib_main_t pointer - */ -void hicn_mapme_init (vlib_main_t * vm); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/mgmt.c b/hicn-plugin/src/mgmt.c deleted file mode 100644 index cfeef6cb6..000000000 --- a/hicn-plugin/src/mgmt.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2017-2019 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 "hicn.h" -#include "infra.h" -#include "mgmt.h" - -/* define message IDs */ -#include "hicn_msg_enum.h" - -/* shared routine betweeen API and CLI, leveraging API message structure */ -int -hicn_mgmt_node_stats_get (vl_api_hicn_api_node_stats_get_reply_t * rmp) -{ - rmp->pkts_processed = 0; - rmp->pkts_interest_count = 0; - rmp->pkts_data_count = 0; - rmp->pkts_from_cache_count = 0; - rmp->pkts_no_pit_count = 0; - rmp->pit_expired_count = 0; - rmp->cs_expired_count = 0; - rmp->cs_lru_count = 0; - rmp->pkts_drop_no_buf = 0; - rmp->interests_aggregated = 0; - rmp->interests_retx = 0; - rmp->pit_entries_count = - clib_host_to_net_u64 (hicn_main.pitcs.pcs_pit_count); - rmp->cs_entries_count = clib_host_to_net_u64 (hicn_main.pitcs.pcs_cs_count); - rmp->cs_entries_ntw_count = - clib_host_to_net_u64 (hicn_main.pitcs.policy_state.count); - - vlib_error_main_t *em; - vlib_node_t *n; - foreach_vlib_main (( - { - em = &this_vlib_main->error_main; - n = - vlib_get_node (this_vlib_main, - hicn_interest_pcslookup_node.index); - u32 node_cntr_base_idx = n->error_heap_index; - rmp->pkts_processed += - clib_host_to_net_u64 (em->counters[node_cntr_base_idx + - HICNFWD_ERROR_PROCESSED]); - rmp->pkts_interest_count += - clib_host_to_net_u64 (em->counters[node_cntr_base_idx + - HICNFWD_ERROR_INTERESTS]); - n = - vlib_get_node (this_vlib_main, - hicn_data_pcslookup_node.index); - node_cntr_base_idx = n->error_heap_index; - rmp->pkts_processed += - clib_host_to_net_u64 (em->counters[node_cntr_base_idx + - HICNFWD_ERROR_PROCESSED]); - rmp->pkts_data_count += - clib_host_to_net_u64 (em->counters[node_cntr_base_idx + - HICNFWD_ERROR_DATAS]); - n = - vlib_get_node (this_vlib_main, - hicn_interest_hitcs_node.index); - node_cntr_base_idx = n->error_heap_index; - rmp->pkts_from_cache_count += - clib_host_to_net_u64 (em->counters[node_cntr_base_idx + - HICNFWD_ERROR_CACHED]); - n = - vlib_get_node (this_vlib_main, - hicn_interest_hitpit_node.index); - node_cntr_base_idx = n->error_heap_index; - rmp->interests_aggregated += - clib_host_to_net_u64 (em->counters[node_cntr_base_idx + - HICNFWD_ERROR_INTEREST_AGG]); - rmp->interests_retx += - clib_host_to_net_u64 (em->counters[node_cntr_base_idx + - HICNFWD_ERROR_INT_RETRANS]);})); - return (HICN_ERROR_NONE); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/mgmt.h b/hicn-plugin/src/mgmt.h deleted file mode 100644 index 6db0fe0c1..000000000 --- a/hicn-plugin/src/mgmt.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2017-2019 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_MGMT_H__ -#define __HICN_MGMT_H__ - -#include -#include "faces/face.h" -#include "hicn_api.h" - -/** - * @file mgmt.h - * - */ - -typedef struct icn_stats_s -{ - u32 pkts_processed; - u32 pkts_interest_count; - u32 pkts_data_count; - u32 pkts_from_cache_count; - u32 pkts_no_pit_count; - u32 pit_expired_count; - u32 cs_expired_count; - u32 no_bufs_count; - u32 pkts_interest_agg; - u32 pkts_int_retrans; - u32 pit_int_count; - u32 pit_cs_count; -} icn_stats_t; - -typedef enum -{ - HICN_MGMT_FACE_OP_NONE = 0, - HICN_MGMT_FACE_OP_CREATE, - HICN_MGMT_FACE_OP_DELETE, - HICN_MGMT_FACE_OP_ADMIN, - HICN_MGMT_FACE_OP_HELLO, -} hicn_mgmt_face_op_e; - -typedef enum -{ - HICN_MGMT_MAPME_OP_NONE = 0, - HICN_MGMT_MAPME_OP_CREATE, - HICN_MGMT_MAPME_OP_DELETE, - HICN_MGMT_MAPME_OP_ENABLE, - HICN_MGMT_MAPME_OP_DISABLE -} hicn_mgmt_mapme_op_e; - -typedef enum -{ - HICN_ADDRESS_TYPE_NONE, - HICN_ADDRESS_TYPE_V4, - HICN_ADDRESS_TYPE_V6 -} hicn_address_type_e; - -/* - * Utility to update error counters in all hICN nodes - */ -always_inline void -update_node_counter (vlib_main_t * vm, u32 node_idx, u32 counter_idx, u64 val) -{ - vlib_node_t *node = vlib_get_node (vm, node_idx); - vlib_error_main_t *em = &(vm->error_main); - u32 base_idx = node->error_heap_index; - - em->counters[base_idx + counter_idx] = val; -} - - -/* - * Stats for the forwarding node, which end up called "error" even though - * they aren't... - */ -#define foreach_hicnfwd_error \ - _(PROCESSED, "hICN packets processed") \ - _(INTERESTS, "hICN interests forwarded") \ - _(DATAS, "hICN data msgs forwarded") \ - _(CACHED, "Cached data ") \ - _(NO_PIT, "hICN no PIT entry drops") \ - _(PIT_EXPIRED, "hICN expired PIT entries") \ - _(CS_EXPIRED, "hICN expired CS entries") \ - _(CS_LRU, "hICN LRU CS entries freed") \ - _(NO_BUFS, "No packet buffers") \ - _(INTEREST_AGG, "Interests aggregated") \ - _(INTEREST_AGG_ENTRY, "Interest aggregated per entry") \ - _(INT_RETRANS, "Interest retransmissions") \ - _(INT_COUNT, "Interests in PIT") \ - _(CS_COUNT, "CS total entries") \ - _(CS_NTW_COUNT, "CS ntw entries") \ - _(CS_APP_COUNT, "CS app entries") \ - _(HASH_COLL_HASHTB_COUNT, "Collisions in Hash table") - -typedef enum -{ -#define _(sym, str) HICNFWD_ERROR_##sym, - foreach_hicnfwd_error -#undef _ - HICNFWD_N_ERROR, -} hicnfwd_error_t; - -/* - * Declarations - */ -clib_error_t *hicn_api_plugin_hookup (vlib_main_t * vm); - -int hicn_mgmt_node_stats_get (vl_api_hicn_api_node_stats_get_reply_t * rmp); - -#endif /* // __HICN_MGMT_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/network/asd b/hicn-plugin/src/network/asd new file mode 100644 index 000000000..13d3b5c3c --- /dev/null +++ b/hicn-plugin/src/network/asd @@ -0,0 +1,304 @@ +# Copyright (c) 2017-2020 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. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +# Dependencies + +find_package(Vpp REQUIRED) + +include_directories(${VPP_INCLUDE_DIR}) + +set(LIBHICN_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/mapme.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/name.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/ops.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/ah.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/icmp.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/ipv4.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/ipv6.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/src/protocol/tcp.c +) + +set(LIBHICN_HEADER_FILES_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/hicn.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/base.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/common.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/error.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/header.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/name.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/ops.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/mapme.h +) + +set(LIBHICN_HEADER_FILES_PROTOCOL + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/ah.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/icmp.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/icmprd.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/ipv4.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/ipv6.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/tcp.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/protocol/udp.h +) + +set(LIBHICN_HEADER_FILES_UTIL + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/util/ip_address.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/util/token.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes/hicn/util/types.h +) + +set(HICN_PLUGIN_SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hicn.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.c + ${CMAKE_CURRENT_SOURCE_DIR}/cli.c + ${CMAKE_CURRENT_SOURCE_DIR}/hashtb.c + ${CMAKE_CURRENT_SOURCE_DIR}/mgmt.c + ${CMAKE_CURRENT_SOURCE_DIR}/pcs.c + ${CMAKE_CURRENT_SOURCE_DIR}/route.c + ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_ctx.c + ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/strategy_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/interest_pcslookup_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitpit_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitcs_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/data_input_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/data_pcslookup_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/data_fwd_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/data_push_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/error.c + ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_cli.c + ${CMAKE_CURRENT_SOURCE_DIR}/faces/face.c + ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/faces/iface_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/faces/dpo_face.h + ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/address_mgr.c + ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_cons.c + ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_prod.c + ${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}/strategies/dpo_mw.c + ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw.c + ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw_cli.c + ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_rr.c + ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_rr.c + ${CMAKE_CURRENT_SOURCE_DIR}/cache_policies/cs_lru.c + ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ack_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ctrl_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/mapme_eventmgr.c + ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_decap_node.c + ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_tunnel.c +) + +set(HICN_PLUGIN_HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_all_api_h.h + ${CMAKE_CURRENT_SOURCE_DIR}/hashtb.h + ${CMAKE_CURRENT_SOURCE_DIR}/mgmt.h + ${CMAKE_CURRENT_SOURCE_DIR}/params.h + ${CMAKE_CURRENT_SOURCE_DIR}/pcs.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn.h + ${CMAKE_CURRENT_SOURCE_DIR}/state.h + ${CMAKE_CURRENT_SOURCE_DIR}/infra.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_msg_enum.h + ${CMAKE_CURRENT_SOURCE_DIR}/parser.h + ${CMAKE_CURRENT_SOURCE_DIR}/route.h + ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_ctx.h + ${CMAKE_CURRENT_SOURCE_DIR}/strategy_dpo_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/strategy.h + ${CMAKE_CURRENT_SOURCE_DIR}/interest_pcslookup.h + ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitpit.h + ${CMAKE_CURRENT_SOURCE_DIR}/interest_hitcs.h + ${CMAKE_CURRENT_SOURCE_DIR}/data_pcslookup.h + ${CMAKE_CURRENT_SOURCE_DIR}/data_fwd.h + ${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_node.h + ${CMAKE_CURRENT_SOURCE_DIR}/faces/iface_node.h + ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_dpo.h + ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/address_mgr.h + ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_cons.h + ${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_prod.h + ${CMAKE_CURRENT_SOURCE_DIR}/pg.h + ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_mw.h + ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw.h + ${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_rr.h + ${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_rr.h + ${CMAKE_CURRENT_SOURCE_DIR}/cache_policies/cs_policy.h + ${CMAKE_CURRENT_SOURCE_DIR}/cache_policies/cs_lru.h + ${CMAKE_CURRENT_SOURCE_DIR}/mapme.h + ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ack.h + ${CMAKE_CURRENT_SOURCE_DIR}/mapme_ctrl.h + ${CMAKE_CURRENT_SOURCE_DIR}/mapme_eventmgr.h + ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_tunnel.h +) + +set(HICN_API_TEST_SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api_test.c + ${CMAKE_CURRENT_SOURCE_DIR}/error.c) + +set(HICN_API_HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_msg_enum.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_all_api_h.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.h + ${CMAKE_CURRENT_SOURCE_DIR}/error.h) + +set(HICN_API_GENERATED_FILES + ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.h + ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api_types.h + ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api_enum.h +) + +set(HICN_VAPI_GENERATED_FILES + ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.vapi.h + ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.vapi.hpp) + +set(HICN_VPP_STARTUP_CONF_FILE + ${CMAKE_BINARY_DIR}/startup.conf) + +if (NOT VPP_HOME) + set(VPP_HOME /usr) +endif() + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE "Release") +endif (NOT CMAKE_BUILD_TYPE) + +SET(HICN_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} CACHE STRING "hicn_install_prefix") + +if (CMAKE_BUILD_TYPE STREQUAL "Release") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wall -march=native -O3 -g") +elseif (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -march=native -O0 -g") + add_definitions(-DCLIB_DEBUG -fPIC -fstack-protector-all) +endif() + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/hicn) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vapi) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vnet/fib) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vnet/udp) + +# These files are missing from vpp binary distribution +execute_process( + COMMAND + bash -c + "if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vapi_json_parser.py ]; then + curl https://raw.githubusercontent.com/FDio/vpp/stable/2001/src/vpp-api/vapi/vapi_json_parser.py -o ${CMAKE_CURRENT_BINARY_DIR}/vapi_json_parser.py; + fi; + if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py ]; then + curl https://raw.githubusercontent.com/FDio/vpp/stable/2001/src/vpp-api/vapi/vapi_c_gen.py -o ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py; + fi; + if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py ]; then + curl https://raw.githubusercontent.com/FDio/vpp/stable/2001/src/vpp-api/vapi/vapi_cpp_gen.py -o ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py; + fi; + if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip/ip_types.api ]; then + curl https://raw.githubusercontent.com/FDio/vpp/stable/2001/src/vnet/ip/ip_types.api -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip/ip_types.api; + fi; + if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip/ip_format_fns.h ]; then + curl https://raw.githubusercontent.com/FDio/vpp/master/src/vnet/ip/ip_format_fns.h -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip/ip_format_fns.h; + fi; + if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/fib/fib_entry_track.h ]; then + curl https://raw.githubusercontent.com/FDio/vpp/master/src/vnet/fib/fib_entry_track.h -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/fib/fib_entry_track.h; + fi; + if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/udp/udp_encap.h ]; then + curl https://raw.githubusercontent.com/FDio/vpp/master/src/vnet/udp/udp_encap.h -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/udp/udp_encap.h; + fi; + + chmod +x ${CMAKE_CURRENT_BINARY_DIR}/vapi_json_parser.py ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py" +) + +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.h ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api_types.h ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api_enum.h ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.json + COMMAND ${VPP_HOME}/bin/vppapigen ARGS --includedir ${CMAKE_CURRENT_BINARY_DIR} --input ${CMAKE_CURRENT_SOURCE_DIR}/hicn.api --output ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/hicn.api.h --outputdir ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn/ + COMMAND ${VPP_HOME}/bin/vppapigen ARGS JSON --includedir ${CMAKE_CURRENT_BINARY_DIR} --input ${CMAKE_CURRENT_SOURCE_DIR}/hicn.api --output ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.json --outputdir ${CMAKE_CURRENT_BINARY_DIR}/vapi/ +) +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.vapi.h ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.vapi.hpp + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py ARGS ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.json + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py ARGS ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.json + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/vapi/hicn.api.json +) + +include_directories(SYSTEM) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHICN_VPP_PLUGIN=1") +add_library(hicn_plugin SHARED + ${LIBHICN_FILES} + ${HICN_PLUGIN_SOURCE_FILES} + ${HICN_API_GENERATED_FILES} + ${HICN_VAPI_GENERATED_FILES}) + +file(COPY ${HICN_API_HEADER_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins/hicn) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins) + +file(COPY ${LIBHICN_HEADER_FILES_SRC} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/hicn) +file(COPY ${LIBHICN_HEADER_FILES_PROTOCOL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/hicn/protocol) +file(COPY ${LIBHICN_HEADER_FILES_UTIL} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/hicn/util) + +add_library(hicn_api_test_plugin SHARED + ${HICN_API_TEST_SOURCE_FILES} + ${HICN_API_GENERATED_FILES}) + +set(VPP_INSTALL_PLUGIN ${HICN_INSTALL_PREFIX}/vpp_plugins) +set(VPP_INSTALL_API_TEST_PLUGIN ${HICN_INSTALL_PREFIX}/vpp_api_test_plugins CACHE STRING "vpp_install_api_test_plugin") +set(VPP_STARTUP_CONF /etc/vpp/) + +set_target_properties(hicn_plugin + PROPERTIES + LINKER_LANGUAGE C + INSTALL_RPATH ${VPP_INSTALL_PLUGIN} + PREFIX "") +set_target_properties(hicn_api_test_plugin + PROPERTIES + LINKER_LANGUAGE C + PREFIX "") + +message (STATUS "hicn-plugin variable ${HICN_PLUGIN}") + +install(DIRECTORY + DESTINATION ${VPP_INSTALL_PLUGIN} + COMPONENT ${HICN_PLUGIN}) +install(TARGETS hicn_plugin + DESTINATION + ${VPP_INSTALL_PLUGIN} + COMPONENT ${HICN_PLUGIN}) + +install(DIRECTORY + DESTINATION ${VPP_INSTALL_API_TEST_PLUGIN} + COMPONENT ${HICN_PLUGIN}) +install(TARGETS hicn_api_test_plugin + DESTINATION ${VPP_INSTALL_API_TEST_PLUGIN} + COMPONENT ${HICN_PLUGIN}) + +install(FILES ${HICN_API_HEADER_FILES} ${HICN_API_GENERATED_FILES} + DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vpp_plugins/hicn + COMPONENT ${HICN_PLUGIN}-dev) + +install(FILES ${HICN_API_GENERATED_FILES} + DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vpp_plugins/hicn + COMPONENT ${HICN_PLUGIN}-dev) + +install(FILES ${HICN_VAPI_GENERATED_FILES} + DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/vapi + COMPONENT ${HICN_PLUGIN}-dev) + +#Set variables for other project depending on hicn-plugin +set(HICNPLUGIN_INCLUDE_DIRS + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins + ${VPP_INCLUDE_DIRS} + CACHE INTERNAL "" FORCE) +set(HICNPLUGIN_LIBRARIES ${VPP_LIBRARIES} CACHE INTERNAL "" FORCE) diff --git a/hicn-plugin/src/network/cache_policies/cs_lru.c b/hicn-plugin/src/network/cache_policies/cs_lru.c new file mode 100644 index 000000000..079af58ab --- /dev/null +++ b/hicn-plugin/src/network/cache_policies/cs_lru.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2017-2019 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 "../hashtb.h" +#include "../strategy_dpo_manager.h" +#include "../error.h" +#include "cs_lru.h" +#include "cs_policy.h" + +hicn_cs_policy_vft_t hicn_cs_lru = { + .hicn_cs_insert = &hicn_cs_lru_insert, + .hicn_cs_update = &hicn_cs_lru_update_head, + .hicn_cs_dequeue = &hicn_cs_lru_dequeue, + .hicn_cs_delete_get = &hicn_cs_lru_delete_get, + .hicn_cs_trim = &hicn_cs_lru_trim, + .hicn_cs_flush = &hicn_cs_lru_flush, +}; + +/* + * Insert a new CS element at the head of the CS LRU + */ +void +hicn_cs_lru_insert (hicn_pit_cs_t * p, hicn_hash_node_t * node, + hicn_pcs_entry_t * pcs, hicn_cs_policy_t * policy_state) +{ + hicn_hash_node_t *lrunode; + hicn_pcs_entry_t *lrupcs; + u32 idx; + + idx = hicn_hashtb_node_idx_from_node (p->pcs_table, node); + + if (policy_state->head != 0) + { + lrunode = hicn_hashtb_node_from_idx (p->pcs_table, policy_state->head); + lrupcs = hicn_pit_get_data (lrunode); + + ASSERT (lrupcs->u.cs.cs_lru_prev == 0); + lrupcs->u.cs.cs_lru_prev = idx; + + pcs->u.cs.cs_lru_prev = 0; + pcs->u.cs.cs_lru_next = policy_state->head; + + policy_state->head = idx; + } + else + { + ASSERT (policy_state->tail == 0); /* We think the list is + * empty */ + + policy_state->head = policy_state->tail = idx; + + pcs->u.cs.cs_lru_next = pcs->u.cs.cs_lru_prev = 0; + } + + policy_state->count++; +} + +void +hicn_cs_lru_delete_get (hicn_pit_cs_t * p, hicn_cs_policy_t * policy_state, + hicn_hash_node_t ** nodep, + hicn_pcs_entry_t ** pcs_entry, + hicn_hash_entry_t ** hash_entry) +{ + *nodep = hicn_hashtb_node_from_idx (p->pcs_table, policy_state->tail); + *pcs_entry = hicn_pit_get_data (*nodep); + + *hash_entry = hicn_hashtb_get_entry (p->pcs_table, (*nodep)->entry_idx, + (*nodep)->bucket_id, + (*nodep)->hn_flags & + HICN_HASH_NODE_OVERFLOW_BUCKET); +} + +/* + * Dequeue an LRU element, for example when it has expired. + */ +void +hicn_cs_lru_dequeue (hicn_pit_cs_t * pit, hicn_hash_node_t * pnode, + hicn_pcs_entry_t * pcs, hicn_cs_policy_t * lru) +{ + hicn_hash_node_t *lrunode; + hicn_pcs_entry_t *lrupcs; + + if (pcs->u.cs.cs_lru_prev != 0) + { + /* Not already on the head of the LRU */ + lrunode = hicn_hashtb_node_from_idx (pit->pcs_table, + pcs->u.cs.cs_lru_prev); + lrupcs = hicn_pit_get_data (lrunode); + + lrupcs->u.cs.cs_lru_next = pcs->u.cs.cs_lru_next; + } + else + { + ASSERT (lru->head == + hicn_hashtb_node_idx_from_node (pit->pcs_table, pnode)); + lru->head = pcs->u.cs.cs_lru_next; + } + + if (pcs->u.cs.cs_lru_next != 0) + { + /* Not already the end of the LRU */ + lrunode = hicn_hashtb_node_from_idx (pit->pcs_table, + pcs->u.cs.cs_lru_next); + lrupcs = hicn_pit_get_data (lrunode); + + lrupcs->u.cs.cs_lru_prev = pcs->u.cs.cs_lru_prev; + } + else + { + /* This was the last LRU element */ + ASSERT (lru->tail == + hicn_hashtb_node_idx_from_node (pit->pcs_table, pnode)); + lru->tail = pcs->u.cs.cs_lru_prev; + } + + pcs->u.cs.cs_lru_next = pcs->u.cs.cs_lru_prev = 0; + lru->count--; +} + +/* + * Move a CS LRU element to the head, probably after it's been used. + */ +void +hicn_cs_lru_update_head (hicn_pit_cs_t * pit, hicn_hash_node_t * pnode, + hicn_pcs_entry_t * pcs, hicn_cs_policy_t * lru) +{ + if (pcs->u.cs.cs_lru_prev != 0) + { + /* + * Not already on the head of the LRU, detach it from its + * current position + */ + hicn_cs_lru_dequeue (pit, pnode, pcs, lru); + + /* Now detached from the list; attach at head */ + hicn_cs_lru_insert (pit, pnode, pcs, lru); + + } + else + { + /* The element is already dequeue */ + if (pcs->u.cs.cs_lru_next == 0) + { + /* Now detached from the list; attach at head */ + hicn_cs_lru_insert (pit, pnode, pcs, lru); + } + ASSERT (lru->head == + hicn_hashtb_node_idx_from_node (pit->pcs_table, pnode)); + } +} + +/* + * Remove a batch of nodes from the CS LRU, copying their node indexes into + * the caller's array. We expect this is done when the LRU size exceeds the + * CS's limit. Return the number of removed nodes. + */ +int +hicn_cs_lru_trim (hicn_pit_cs_t * pit, u32 * node_list, int sz, + hicn_cs_policy_t * lru) +{ + hicn_hash_node_t *lrunode; + hicn_pcs_entry_t *lrupcs; + u32 idx; + int i; + + idx = lru->tail; + + for (i = 0; i < sz; i++) + { + + if (idx == 0) + { + break; + } + lrunode = hicn_hashtb_node_from_idx (pit->pcs_table, idx); + lrupcs = hicn_pit_get_data (lrunode); + + node_list[i] = idx; + + idx = lrupcs->u.cs.cs_lru_prev; + lrupcs->u.cs.cs_lru_prev = 0; + lrupcs->u.cs.cs_lru_next = 0; + } + + lru->count -= i; + + lru->tail = idx; + if (idx != 0) + { + lrunode = hicn_hashtb_node_from_idx (pit->pcs_table, idx); + lrupcs = hicn_pit_get_data (lrunode); + + lrupcs->u.cs.cs_lru_next = 0; + } + else + { + /* If the tail is empty, the whole lru is empty */ + lru->head = 0; + } + + return (i); +} + +int +hicn_cs_lru_flush (vlib_main_t * vm, struct hicn_pit_cs_s *pitcs, + hicn_cs_policy_t * state) +{ + if (state->head == 0 && state->tail == 0) + return 0; + + hicn_hash_node_t *lrunode; + hicn_pcs_entry_t *lrupcs; + u32 idx; + int i = 0; + + idx = state->tail; + + while (idx != 0) + { + lrunode = hicn_hashtb_node_from_idx (pitcs->pcs_table, idx); + lrupcs = hicn_pit_get_data (lrunode); + + u64 hashval = 0; + hicn_hashtb_fullhash ((u8 *) & (lrunode->hn_key.ks.key), + lrunode->hn_keysize, &hashval); + hicn_hash_bucket_t *bucket = NULL; + if ((hashval & (pitcs->pcs_table->ht_bucket_count - 1)) == + lrunode->bucket_id) + { + //The bucket is in the non overflown + bucket = pitcs->pcs_table->ht_buckets + lrunode->bucket_id; + } + else + { + bucket = + pool_elt_at_index (pitcs->pcs_table->ht_overflow_buckets, + lrunode->bucket_id); + } + hicn_hash_entry_t *hash_entry = + &(bucket->hb_entries[lrunode->entry_idx]); + hash_entry->locks++; + hicn_pcs_cs_delete (vm, pitcs, &lrupcs, &lrunode, hash_entry, NULL, + NULL); + idx = state->tail; + i++; + } + + return (i); + +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/cache_policies/cs_lru.h b/hicn-plugin/src/network/cache_policies/cs_lru.h new file mode 100644 index 000000000..3bd18060d --- /dev/null +++ b/hicn-plugin/src/network/cache_policies/cs_lru.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2020 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 __LRU_H__ +#define __LRU_H__ + +#include "../pcs.h" +#include "../hashtb.h" +#include "cs_policy.h" + +/** + * @file cs_lru.h + * + * This file implements the LRU policy for the CS + */ + + +extern hicn_cs_policy_vft_t hicn_cs_lru; + +/* + * Insert a new CS element at the head of the CS LRU + */ +void +hicn_cs_lru_insert (hicn_pit_cs_t * pcs, hicn_hash_node_t * pnode, + hicn_pcs_entry_t * entry, hicn_cs_policy_t * lru); + + +/* + * Dequeue an LRU element, for example when it has expired. + */ +void +hicn_cs_lru_dequeue (hicn_pit_cs_t * pcs, hicn_hash_node_t * pnode, + hicn_pcs_entry_t * entry, hicn_cs_policy_t * lru); + +/* + * Move a CS LRU element to the head, probably after it's been used. + */ +void +hicn_cs_lru_update_head (hicn_pit_cs_t * pcs, hicn_hash_node_t * pnode, + hicn_pcs_entry_t * entry, hicn_cs_policy_t * lru); + +void +hicn_cs_lru_delete_get (hicn_pit_cs_t * p, hicn_cs_policy_t * policy, + hicn_hash_node_t ** node, hicn_pcs_entry_t ** pcs, + hicn_hash_entry_t ** hash_entry); + +/* + * Remove a batch of nodes from the CS LRU, copying their node indexes into + * the caller's array. We expect this is done when the LRU size exceeds the + * CS's limit. Return the number of removed nodes. + */ +int hicn_cs_lru_trim (hicn_pit_cs_t * pcs, u32 * node_list, int sz, + hicn_cs_policy_t * lru); + + +int hicn_cs_lru_flush (vlib_main_t * vm, struct hicn_pit_cs_s *pitcs, + hicn_cs_policy_t * state); +#endif /* // __LRU_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/cache_policies/cs_policy.h b/hicn-plugin/src/network/cache_policies/cs_policy.h new file mode 100644 index 000000000..0bf745915 --- /dev/null +++ b/hicn-plugin/src/network/cache_policies/cs_policy.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2020 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_CS_POLICY_H__ +#define __HICN_CS_POLICY_H__ + +#include "../hashtb.h" + +/** + * @file cs_policy.h + * + * This file provides the needed structures to implement a CS policy + */ + + +/* + * Structure + */ +typedef struct hicn_cs_policy_s +{ + u32 max; + u32 count; + + /* Indexes to hashtable nodes forming CS LRU */ + u32 head; + u32 tail; + +} hicn_cs_policy_t; + +/* Forward declaration */ +struct hicn_pit_cs_s; +struct hicn_hash_node_s; +struct hicn_pcs_entry_s; +struct hicn_cs_policy_s; + +/** + * @brief Definition of the virtual functin table for a cache policy. + * + * A cache policy must implement all the following functions: + * - insert: add a new element + * - update: update the position of an existing element + * - dequeue: remove an element from the list + * - delete_get: return the next element that should be removed trim + * - flush: clean the cs + */ +typedef struct hicn_cs_policy_vft_s +{ + void (*hicn_cs_insert) (struct hicn_pit_cs_s * p, + struct hicn_hash_node_s * node, + struct hicn_pcs_entry_s * pcs, + hicn_cs_policy_t * policy); + + void (*hicn_cs_update) (struct hicn_pit_cs_s * p, + struct hicn_hash_node_s * node, + struct hicn_pcs_entry_s * pcs, + hicn_cs_policy_t * policy); + + void (*hicn_cs_dequeue) (struct hicn_pit_cs_s * p, + struct hicn_hash_node_s * node, + struct hicn_pcs_entry_s * pcs, + hicn_cs_policy_t * policy); + + void (*hicn_cs_delete_get) (struct hicn_pit_cs_s * p, + hicn_cs_policy_t * policy, + struct hicn_hash_node_s ** node, + struct hicn_pcs_entry_s ** pcs, + struct hicn_hash_entry_s ** hash_entry); + + int (*hicn_cs_trim) (struct hicn_pit_cs_s * p, u32 * node_list, int sz, + hicn_cs_policy_t * policy); + + int (*hicn_cs_flush) (vlib_main_t * vm, struct hicn_pit_cs_s * p, + hicn_cs_policy_t * policy_state); +} hicn_cs_policy_vft_t; + + + +#endif /* // __HICN_POLICY_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/cli.c b/hicn-plugin/src/network/cli.c new file mode 100644 index 000000000..22522b28b --- /dev/null +++ b/hicn-plugin/src/network/cli.c @@ -0,0 +1,897 @@ +/* + * Copyright (c) 2017-2020 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 // port registration +#include // ip46_address_t +#include +#include + +#include + +#include "hicn.h" +#include "infra.h" +#include "parser.h" +#include "mgmt.h" +#include "strategy_dpo_manager.h" +#include "strategy.h" +#include "pg.h" +#include "error.h" +#include "faces/face.h" +#include "route.h" + +static vl_api_hicn_api_node_params_set_t node_ctl_params = { + .pit_max_size = -1, + .pit_max_lifetime_sec = -1.0f, + .cs_max_size = -1, +}; + +typedef enum +{ + IP, + ETHERNET, +} interface_type_t; + +/* + * cli handler for 'control start' + */ +static clib_error_t * +hicn_cli_node_ctl_start_set_command_fn (vlib_main_t * vm, + unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + int ret; + + ret = hicn_infra_plugin_enable_disable (1 /* enable */ , + node_ctl_params.pit_max_size, + node_ctl_params.pit_max_lifetime_sec, + node_ctl_params.cs_max_size, ~0); + + vlib_cli_output (vm, "hicn: fwdr initialize => %s\n", + get_error_string (ret)); + + return (ret == HICN_ERROR_NONE) ? 0 : clib_error_return (0, + get_error_string + (ret)); +} + +/* + * cli handler for 'control stop' + */ +static clib_error_t * +hicn_cli_node_ctl_stop_set_command_fn (vlib_main_t * vm, + unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + int ret; + + /* + * Catch unexpected extra arguments on this line. See comment on + * hicn_cli_node_ctrl_start_set_command_fn + */ + if (main_input->index > 0 && + main_input->buffer[main_input->index - 1] != '\n') + { + unformat_input_t _line_input, *line_input = &_line_input; + if (!unformat_user (main_input, unformat_line_input, line_input)) + { + return (0); + } + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + return clib_error_return (0, "%s '%U'", + get_error_string (HICN_ERROR_CLI_INVAL), + format_unformat_error, line_input); + } + } + ret = hicn_infra_plugin_enable_disable (0 /* !enable */ , + node_ctl_params.pit_max_size, + node_ctl_params.pit_max_lifetime_sec, + node_ctl_params.cs_max_size, ~0); + + return (ret == HICN_ERROR_NONE) ? 0 : clib_error_return (0, + get_error_string + (ret)); +} + +#define DFLTD_RANGE_OK(val, min, max) \ +({ \ + __typeof__ (val) _val = (val); \ + __typeof__ (min) _min = (min); \ + __typeof__ (max) _max = (max); \ + (_val == -1) || \ + (_val >= _min && _val <= _max); \ +}) + +/* + * cli handler for 'control param' + */ +static clib_error_t * +hicn_cli_node_ctl_param_set_command_fn (vlib_main_t * vm, + unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + int rv = 0; + + int table_size; + f64 lifetime; + + if (hicn_main.is_enabled) + { + return (clib_error_return + (0, "params cannot be altered once hicn started")); + } + /* Get a line of input. */ + unformat_input_t _line_input, *line_input = &_line_input; + if (!unformat_user (main_input, unformat_line_input, line_input)) + { + return clib_error_return (0, + get_error_string + (HICN_ERROR_FWD_ALREADY_ENABLED)); + } + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "pit")) + { + if (unformat (line_input, "size %d", &table_size)) + { + if (!DFLTD_RANGE_OK (table_size, HICN_PARAM_PIT_ENTRIES_MIN, + HICN_PARAM_PIT_ENTRIES_MAX)) + { + rv = HICN_ERROR_PIT_CONFIG_SIZE_OOB; + break; + } + node_ctl_params.pit_max_size = table_size; + } + else if (unformat (line_input, "maxlife %f", &lifetime)) + { + if (!DFLTD_RANGE_OK + (lifetime, HICN_PARAM_PIT_LIFETIME_BOUND_MIN_SEC, + HICN_PARAM_PIT_LIFETIME_BOUND_MAX_SEC)) + { + rv = HICN_ERROR_PIT_CONFIG_MAXLT_OOB; + break; + } + node_ctl_params.pit_max_lifetime_sec = lifetime; + } + else + { + rv = HICN_ERROR_CLI_INVAL; + break; + } + } + else if (unformat (line_input, "cs")) + { + if (unformat (line_input, "size %d", &table_size)) + { + if (!DFLTD_RANGE_OK (table_size, HICN_PARAM_CS_ENTRIES_MIN, + HICN_PARAM_CS_ENTRIES_MAX)) + { + rv = HICN_ERROR_CS_CONFIG_SIZE_OOB; + break; + } + node_ctl_params.cs_max_size = table_size; + } + else + { + rv = HICN_ERROR_CLI_INVAL; + break; + } + } + else + { + rv = HICN_ERROR_CLI_INVAL; + break; + } + } + + if (node_ctl_params.cs_max_size == 0) + vlib_cli_output (vm, + "CS size set to 0. Consider disable CS at compilation time for better performances\n"); + + return (rv == HICN_ERROR_NONE) ? 0 : clib_error_return (0, "%s '%U'", + get_error_string + (rv), + format_unformat_error, + line_input); +} + +/* + * cli handler for 'hicn show' + */ +static clib_error_t * +hicn_cli_show_command_fn (vlib_main_t * vm, unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + int face_p = 0, fib_p = 0, all_p, internal_p = 0, strategies_p = 0, ret = + HICN_ERROR_NONE; + + /* Get a line of input. */ + unformat_input_t _line_input, *line_input = &_line_input; + if (unformat_user (main_input, unformat_line_input, line_input)) + { + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "face all")) + { + face_p = 1; + } + else if (unformat (line_input, "internal")) + { + /* + * We consider 'internal' a superset, so + * include 'detail' too + */ + internal_p = 1; + } + else if (unformat (line_input, "strategies")) + { + /* + * We consider 'internal' a superset, so + * include 'detail' too + */ + strategies_p = 1; + } + else + { + ret = HICN_ERROR_CLI_INVAL; + goto done; + } + } + } + /* If nothing specified, show everything */ + if ((face_p == 0) && (fib_p == 0) && (strategies_p == 0)) + { + all_p = 1; + } + if (!hicn_main.is_enabled) + { + if (node_ctl_params.pit_max_size == -1 && + node_ctl_params.pit_max_lifetime_sec == -1 && + node_ctl_params.cs_max_size == -1) + { + ret = HICN_ERROR_FWD_NOT_ENABLED; + goto done; + } + vlib_cli_output (vm, "Forwarder: %sabled\nPreconfiguration:\n", + hicn_main.is_enabled ? "en" : "dis"); + + if (node_ctl_params.pit_max_size != -1) + { + vlib_cli_output (vm, " PIT:: max entries:%d\n", + node_ctl_params.pit_max_size); + } + if (node_ctl_params.pit_max_lifetime_sec != -1) + { + vlib_cli_output (vm, " PIT:: max lifetime: %05.3f seconds\n", + node_ctl_params.pit_max_lifetime_sec); + } + if (node_ctl_params.cs_max_size != -1) + { + vlib_cli_output (vm, " CS:: max entries:%d\n", + node_ctl_params.cs_max_size); + } + goto done; + } + /* Globals */ + vlib_cli_output (vm, + "Forwarder: %sabled\n" + " PIT:: max entries:%d," + " lifetime default: max:%05.3f\n" + " CS:: max entries:%d\n", + hicn_main.is_enabled ? "en" : "dis", + hicn_infra_pit_size, + ((f64) hicn_main.pit_lifetime_max_ms) / SEC_MS, + hicn_infra_cs_size); + + vl_api_hicn_api_node_stats_get_reply_t rm = { 0, } + , *rmp = &rm; + if (hicn_mgmt_node_stats_get (&rm) == HICN_ERROR_NONE) + { + vlib_cli_output (vm, //compare vl_api_hicn_api_node_stats_get_reply_t_handler block + " PIT entries (now): %d\n" + " CS total entries (now): %d, network entries (now): %d\n" + " Forwarding statistics:\n" + " pkts_processed: %d\n" + " pkts_interest_count: %d\n" + " pkts_data_count: %d\n" + " pkts_from_cache_count: %d\n" + " interests_aggregated: %d\n" + " interests_retransmitted: %d\n", + clib_net_to_host_u64 (rmp->pit_entries_count), + clib_net_to_host_u64 (rmp->cs_entries_count), + clib_net_to_host_u64 (rmp->cs_entries_ntw_count), + clib_net_to_host_u64 (rmp->pkts_processed), + clib_net_to_host_u64 (rmp->pkts_interest_count), + clib_net_to_host_u64 (rmp->pkts_data_count), + clib_net_to_host_u64 (rmp->pkts_from_cache_count), + clib_net_to_host_u64 (rmp->interests_aggregated), + clib_net_to_host_u64 (rmp->interests_retx)); + } + if (face_p || all_p) + { + u8 *strbuf = NULL; + + strbuf = format_hicn_face_all (strbuf, 1, 0); + vlib_cli_output (vm, "%s", strbuf); + + } + if (strategies_p || all_p) + { + u8 *strbuf = NULL; + + strbuf = format_hicn_strategy_list (strbuf, 1, 0); + vlib_cli_output (vm, (char *) strbuf); + } +done: + if (all_p && internal_p && ret == HICN_ERROR_NONE) + { + vlib_cli_output (vm, "Plugin features: cs:%d\n", HICN_FEATURE_CS); + vlib_cli_output (vm, + "Removed CS entries (and freed vlib buffers) %d, Removed PIT entries %d\n", + hicn_main.pitcs.pcs_cs_dealloc, + hicn_main.pitcs.pcs_pit_dealloc); + vlib_cli_output (vm, + "Bucke count %d, Overflow buckets count %d, used %d\n", + hicn_main.pitcs.pcs_table->ht_bucket_count, + hicn_main.pitcs.pcs_table->ht_overflow_bucket_count, + hicn_main.pitcs.pcs_table->ht_overflow_buckets_used); + + } + return (ret == HICN_ERROR_NONE) ? 0 : clib_error_return (0, "%s\n", + get_error_string + (ret)); +} + +/* + * cli handler for 'fib' + */ +static clib_error_t * +hicn_cli_strategy_set_command_fn (vlib_main_t * vm, + unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + clib_error_t *cl_err = 0; + + int rv = HICN_ERROR_NONE; + int addpfx = -1; + ip46_address_t address; + u32 strategy_id; + u32 plen = 0; + fib_prefix_t prefix; + + /* Get a line of input. */ + unformat_input_t _line_input, *line_input = &_line_input; + if (!unformat_user (main_input, unformat_line_input, line_input)) + { + return (0); + } + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "set %d", &strategy_id)) + { + addpfx = 2; + } + else if (addpfx != -1 + && unformat (line_input, "prefix %U/%d", unformat_ip46_address, + &address, IP46_TYPE_ANY, &plen)) + {; + } + else + { + cl_err = clib_error_return (0, "%s '%U'", + get_error_string (HICN_ERROR_CLI_INVAL), + format_unformat_error, line_input); + goto done; + } + } + + fib_prefix_from_ip46_addr (&address, &prefix); + prefix.fp_len = plen; + /* Check parse */ + if (hicn_dpo_strategy_id_is_valid (strategy_id) == + HICN_ERROR_DPO_MGR_ID_NOT_VALID) + { + cl_err = clib_error_return (0, "Please specify a valid strategy..."); + goto done; + } + + rv = hicn_route_set_strategy (&prefix, strategy_id); + cl_err = + (rv == HICN_ERROR_NONE) ? NULL : clib_error_return (0, + get_error_string + (rv)); +done: + + return (cl_err); +} + +/* + * cli handler for 'pgen' + */ +static clib_error_t * +hicn_cli_pgen_client_set_command_fn (vlib_main_t * vm, + unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + hicnpg_main_t *hpgm = &hicnpg_main; + ip46_address_t src_addr; + fib_prefix_t *prefix = malloc (sizeof (fib_prefix_t)); + vnet_main_t *vnm = vnet_get_main (); + u32 sw_if_index = ~0; + u16 lifetime = 4000; + int rv = VNET_API_ERROR_UNIMPLEMENTED; + u32 max_seq = ~0; + u32 n_flows = ~0; + u32 n_ifaces = 1; + + /* Get a line of input. */ + unformat_input_t _line_input, *line_input = &_line_input; + if (unformat_user (main_input, unformat_line_input, line_input)) + { + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat + (line_input, "intfc %U", unformat_vnet_sw_interface, vnm, + &sw_if_index)) + { + ; + } + else if (unformat (line_input, "src %U", + unformat_ip46_address, &src_addr)) + { + ; + } + else if (unformat (line_input, "n_ifaces %d", &n_ifaces)) + { + ; + } + else if (unformat (line_input, "name %U/%d", + unformat_ip46_address, &prefix->fp_addr, + IP46_TYPE_ANY, &prefix->fp_len)) + { + ; + } + else if (unformat (line_input, "lifetime %d", &lifetime)) + { + ; + } + else if (unformat (line_input, "max_seq %d", &max_seq)) + { + ; + } + else if (unformat (line_input, "n_flows %d", &n_flows)) + { + ; + } + else + { + return (clib_error_return + (0, "Unknown input '%U'", format_unformat_error, + line_input)); + break; + } + } + } + hpgm->interest_lifetime = lifetime; + + if (sw_if_index == ~0) + { + return (clib_error_return (0, "Packet generator interface missing")); + } + + //Remove bits that are out of the subnet + 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; + } + 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; + } + + /* + * Enable the feature to divert data packet to the hicnpg-data node to count + * how many data packets have been received. + * Diver all the packets from the packet-generator to the hicn-pg-interest node + * to generate valid interests. + */ + if (ip46_address_is_ip4 (&src_addr) + && ip46_address_is_ip4 (&prefix->fp_addr)) + { + prefix->fp_proto = FIB_PROTOCOL_IP4; + + vnet_feature_enable_disable ("ip4-unicast", "hicnpg-data", + sw_if_index, 1, 0, 0); + + /* Add pgen_client node to the vpp graph */ + vlib_node_add_next (vm, + pg_input_node.index, hicn_pg_interest_node.index); + + + pg_node_t *pn; + pn = pg_get_node (hicn_pg_interest_node.index); + pn->unformat_edit = unformat_pg_ip4_header; + + } + else if (!ip46_address_is_ip4 (&src_addr) + && !ip46_address_is_ip4 (&prefix->fp_addr)) + { + prefix->fp_proto = FIB_PROTOCOL_IP6; + + vnet_feature_enable_disable ("ip6-unicast", "hicnpg-data", + sw_if_index, 1, 0, 0); + + /* Add pgen_client node to the vpp graph */ + vlib_node_add_next (vm, pg_input_node.index, + hicn_pg_interest_node.index); + + pg_node_t *pn; + pn = pg_get_node (hicn_pg_interest_node.index); + pn->unformat_edit = unformat_pg_ip6_header; + } + else + { + return (clib_error_return + (0, + "pg interface source address, source address and hicn name must be of the same type IPv4 or IPv6")); + } + + + hpgm->pgen_clt_src_addr = src_addr; + hpgm->pgen_clt_hicn_name = prefix; + hpgm->max_seq_number = max_seq; + hpgm->n_flows = n_flows; + hpgm->n_ifaces = n_ifaces; + hpgm->sw_if = sw_if_index; + vlib_cli_output (vm, "ifaces %d", hpgm->n_ifaces); + rv = 0; + + switch (rv) + { + case 0: + break; + + case VNET_API_ERROR_UNIMPLEMENTED: + return clib_error_return (0, "Unimplemented, NYI"); + break; + + default: + return clib_error_return (0, "hicn enable_disable returned %d", rv); + } + + return 0; +} + +/* + * cli handler for 'pgen' + */ +static clib_error_t * +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)); + + /* Get a line of input. */ + unformat_input_t _line_input, *line_input = &_line_input; + if (unformat_user (main_input, unformat_line_input, line_input)) + { + /* Parse the arguments */ + 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)) + {; + } + else if (unformat (line_input, "size %d", &payload_size)) + { + if (payload_size > 1440) + { + return (clib_error_return (0, + "Payload size must be <= 1440 bytes...")); + } + } + else + if (unformat + (line_input, "intfc %U", unformat_vnet_sw_interface, vnm, + &sw_if_index)) + { + ; + } + else + { + return (clib_error_return + (0, "Unknown input '%U'", format_unformat_error, + line_input)); + break; + } + } + } + + /* 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) + { + return clib_error_return (0, + "Error: must supply local port, payload size and incoming hICN prefix"); + } + + //Remove bits that are out of the subnet + 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; + } + 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; + } + + /* 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) + { + return (clib_error_return (0, "Impossible to allocate paylod buffer.")); + } + + 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; +} + +static clib_error_t * +hicn_enable_command_fn (vlib_main_t * vm, unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + clib_error_t *cl_err = 0; + + int rv = HICN_ERROR_NONE; + fib_prefix_t pfx; + + /* Get a line of input. */ + unformat_input_t _line_input, *line_input = &_line_input; + if (!unformat_user (main_input, unformat_line_input, line_input)) + { + return (0); + } + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%U/%d", + unformat_ip4_address, &pfx.fp_addr.ip4, &pfx.fp_len)) + { + pfx.fp_proto = FIB_PROTOCOL_IP4; + } + else if (unformat (line_input, "%U/%d", + unformat_ip6_address, &pfx.fp_addr.ip6, &pfx.fp_len)) + { + pfx.fp_proto = FIB_PROTOCOL_IP6; + } + else + { + cl_err = clib_error_return (0, "%s '%U'", + get_error_string (HICN_ERROR_CLI_INVAL), + format_unformat_error, line_input); + goto done; + } + } + rv = hicn_route_enable (&pfx); +done: + + cl_err = + (rv == HICN_ERROR_NONE) ? NULL : clib_error_return (0, + get_error_string + (rv)); + return cl_err; +} + +static clib_error_t * +hicn_disable_command_fn (vlib_main_t * vm, unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + clib_error_t *cl_err = 0; + + int rv = HICN_ERROR_NONE; + fib_prefix_t pfx; + + /* Get a line of input. */ + unformat_input_t _line_input, *line_input = &_line_input; + if (!unformat_user (main_input, unformat_line_input, line_input)) + { + return (0); + } + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%U/%d", + unformat_ip4_address, &pfx.fp_addr.ip4, &pfx.fp_len)) + { + pfx.fp_proto = FIB_PROTOCOL_IP4; + } + else if (unformat (line_input, "%U/%d", + unformat_ip6_address, &pfx.fp_addr.ip6, &pfx.fp_len)) + { + pfx.fp_proto = FIB_PROTOCOL_IP6; + } + else + { + cl_err = clib_error_return (0, "%s '%U'", + get_error_string (HICN_ERROR_CLI_INVAL), + format_unformat_error, line_input); + goto done; + } + } + + rv = hicn_route_disable (&pfx); + +done: + cl_err = + (rv == HICN_ERROR_NONE) ? NULL : clib_error_return (0, + get_error_string + (rv)); + return cl_err; +} + + +/* cli declaration for 'control start' */ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND(hicn_cli_node_ctl_start_set_command, static)= +{ + .path = "hicn control start", + .short_help = "hicn control start", + .function = hicn_cli_node_ctl_start_set_command_fn, +}; + + +/* cli declaration for 'control stop' */ +VLIB_CLI_COMMAND(hicn_cli_node_ctl_stop_set_command, static)= +{ + .path = "hicn control stop", + .short_help = "hicn control stop", + .function = hicn_cli_node_ctl_stop_set_command_fn, +}; + + +/* cli declaration for 'control param' */ +VLIB_CLI_COMMAND(hicn_cli_node_ctl_param_set_command, static)= +{ + .path = "hicn control param", + .short_help = "hicn control param { pit { size | { dfltlife | minlife | maxlife } } | fib size | cs {size | app } }\n", + .function = hicn_cli_node_ctl_param_set_command_fn, +}; + +/* cli declaration for 'control' (root path of multiple commands, for help) */ +VLIB_CLI_COMMAND(hicn_cli_node_ctl_command, static)= +{ + .path = "hicn control", + .short_help = "hicn control" +}; + +/* cli declaration for 'fib' */ +VLIB_CLI_COMMAND(hicn_cli_strategy_set_command, static)= + { + .path = "hicn strategy", + .short_help = "hicn strategy set prefix ", + .function = hicn_cli_strategy_set_command_fn, + }; + +/* cli declaration for 'show' */ +VLIB_CLI_COMMAND(hicn_cli_show_command, static)= +{ + .path = "hicn show", + .short_help = "hicn show " + "[internal]" + "[strategies]", + .function = hicn_cli_show_command_fn, +}; + +/* cli declaration for 'hicn pgen client' */ +VLIB_CLI_COMMAND(hicn_cli_pgen_client_set_command, static)= +{ + .path = "hicn pgen client", + .short_help = "hicn pgen client src name { n_ifaces lifetime intfc max_seq n_flows }", + .long_help = "Run hicn in packet-gen client mode\n", + .function = hicn_cli_pgen_client_set_command_fn, +}; + +/* cli declaration for 'hicn pgen client' */ +VLIB_CLI_COMMAND(hicn_cli_pgen_server_set_command, static)= +{ + .path = "hicn pgen server", + .short_help = "hicn pgen server name intfc size ", + .long_help = "Run hicn in packet-gen server mode\n", + .function = hicn_cli_pgen_server_set_command_fn, +}; + +/* cli declaration for 'hicn pgen client' */ +VLIB_CLI_COMMAND(hicn_enable_command, static)= + { + .path = "hicn enable", + .short_help = "hicn enable ", + .long_help = "Enable hicn for the give prefix\n", + .function = hicn_enable_command_fn, + }; + +/* cli declaration for 'hicn pgen client' */ +VLIB_CLI_COMMAND(hicn_disable_command, static)= + { + .path = "hicn disable", + .short_help = "hicn disable ", + .long_help = "Disable hicn for the give prefix\n", + .function = hicn_disable_command_fn, + }; + +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/data_fwd.h b/hicn-plugin/src/network/data_fwd.h new file mode 100644 index 000000000..d95f564c3 --- /dev/null +++ b/hicn-plugin/src/network/data_fwd.h @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2017-2020 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_DATA_FWD_H__ +#define __HICN_DATA_FWD_H__ + +#include + +#include "pcs.h" + +/** + * @file data_fwd.h + * + * This is the node encoutered by data packets after the hicn-data-pcslookup. + * This node has two goals: 1) clone/copy the vlib buffer as many time as the number + * of faces stored in the pit entry, 2) store a clone/copy of the vlib buffer in the CS. + * Unless there are memory issue (no more vlib buffer available to perform cloning/copy), + * a single vlib buffer received might results in several vlib buffer sent to the next + * vlib node (hicn4-iface-output or hicn6-iface-output). + * + * It must be noted that cloning is possible only if the lentgh of the data pointed by + * the vlib buffer is at least 256 bytes. This is due to an imposition in the vpp source + * code. In all the other cases the vlib buffer is copied. Cloning is performed by advancing + * the vlib buffer of 256 bytes and a new vlib buffer is created and chained in from of the received + * buffer. Additionally, the 256 bytes removed (advanced) from the received vlib buffer are + * copied in the head vlib buffer. In case of multiple cloning for the same vlib buffer, this + * mechanism allows us to have a different hICN header for each clone (+ the same additional bytes + * due to the vpp restriction on cloning). + */ + + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + u8 packet_data[64]; +} hicn_data_fwd_trace_t; + +typedef enum +{ + HICN_DATA_FWD_NEXT_V4_LOOKUP, + HICN_DATA_FWD_NEXT_V6_LOOKUP, + HICN_DATA_FWD_NEXT_IFACE4_OUT, + HICN_DATA_FWD_NEXT_IFACE6_OUT, + HICN_DATA_FWD_NEXT_ERROR_DROP, + HICN_DATA_FWD_N_NEXT, +} hicn_data_fwd_next_t; + +/** + * @brief Create a maximum of 256 clones of buffer and store them + * in the supplied array. Unlike the original function in the vlib + * library, we don't prevent cloning if n_buffer==1 and if + * s->current_length <= head_end_offset + CLIB_CACHE_LINE_BYTES * 2. + * + * @param vm - (vlib_main_t *) vlib main data structure pointer + * @param src_buffer - (u32) source buffer index + * @param buffers - (u32 * ) buffer index array + * @param n_buffers - (u16) number of buffer clones requested (<=256) + * @param head_end_offset - (u16) offset relative to current position + * where packet head ends + * @return - (u16) number of buffers actually cloned, may be + * less than the number requested or zero + */ +always_inline u16 +vlib_buffer_clone_256_2 (vlib_main_t * vm, u32 src_buffer, u32 * buffers, + u16 n_buffers, u16 head_end_offset) +{ + u16 i; + vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer); + + ASSERT (n_buffers); + ASSERT (n_buffers <= 256); + + if (s->current_length <= head_end_offset + CLIB_CACHE_LINE_BYTES * 2) + { + for (i = 0; i < n_buffers; i++) + { + vlib_buffer_t *d; + d = vlib_buffer_copy (vm, s); + if (d == 0) + return i; + buffers[i] = vlib_get_buffer_index (vm, d); + } + return n_buffers; + } + n_buffers = vlib_buffer_alloc_from_pool (vm, buffers, n_buffers, + s->buffer_pool_index); + + for (i = 0; i < n_buffers; i++) + { + vlib_buffer_t *d = vlib_get_buffer (vm, buffers[i]); + d->current_data = s->current_data; + d->current_length = head_end_offset; + d->trace_handle = s->trace_handle; + + d->total_length_not_including_first_buffer = s->current_length - + head_end_offset; + if (PREDICT_FALSE (s->flags & VLIB_BUFFER_NEXT_PRESENT)) + { + d->total_length_not_including_first_buffer += + s->total_length_not_including_first_buffer; + } + d->flags = s->flags | VLIB_BUFFER_NEXT_PRESENT; + d->flags &= ~VLIB_BUFFER_EXT_HDR_VALID; + d->trace_handle = s->trace_handle; + clib_memcpy_fast (d->opaque, s->opaque, sizeof (s->opaque)); + clib_memcpy_fast (d->opaque2, s->opaque2, sizeof (s->opaque2)); + clib_memcpy_fast (vlib_buffer_get_current (d), + vlib_buffer_get_current (s), head_end_offset); + d->next_buffer = src_buffer; + } + vlib_buffer_advance (s, head_end_offset); + s->ref_count = n_buffers; + while (s->flags & VLIB_BUFFER_NEXT_PRESENT) + { + s = vlib_get_buffer (vm, s->next_buffer); + s->ref_count = n_buffers; + } + + return n_buffers; +} + +/** + * @brief Create multiple clones of buffer and store them + * in the supplied array. Unlike the function in the vlib library, + * we allow src_buffer to have ref_count != 0. + * + * @param vm - (vlib_main_t *) vlib main data structure pointer + * @param src_buffer - (u32) source buffer index + * @param buffers - (u32 * ) buffer index array + * @param n_buffers - (u16) number of buffer clones requested (<=256) + * @param head_end_offset - (u16) offset relative to current position + * where packet head ends + * @return - (u16) number of buffers actually cloned, may be + * less than the number requested or zero + */ +always_inline u16 +vlib_buffer_clone2 (vlib_main_t * vm, u32 src_buffer, u32 * buffers, + u16 n_buffers, u16 head_end_offset) +{ + vlib_buffer_t *s = vlib_get_buffer (vm, src_buffer); + + /* + * total_length_not_including_first_buffer is not initialized to 0 + * when a buffer is used. + */ + if (PREDICT_TRUE (s->next_buffer == 0)) + s->total_length_not_including_first_buffer = 0; + + u16 n_cloned = 0; + u8 n_clone_src = 255 - s->ref_count; + + /* + * We need to copy src for all the clones that cannot be chained in + * the src_buffer + */ + /* MAX(ref_count) = 256 */ + if (n_buffers > n_clone_src) + { + vlib_buffer_t *copy; + /* Ok to call the original vlib_buffer_copy. */ + copy = vlib_buffer_copy (vm, s); + n_cloned += vlib_buffer_clone (vm, + vlib_get_buffer_index (vm, copy), + buffers, + n_buffers - n_clone_src, + head_end_offset); + n_buffers -= n_cloned; + } + /* + * vlib_buffer_clone_256 check if ref_count is 0. We force it to be + * 0 before calling the function and we retore it to the right value + * after the function has been called + */ + u8 tmp_ref_count = s->ref_count; + + s->ref_count = 1; + /* + * The regular vlib_buffer_clone_256 does copy if we need to clone + * only one packet. While this is not a problem per se, it adds + * complexity to the code, especially because we need to add 1 to + * ref_count when the packet is cloned. + */ + n_cloned += vlib_buffer_clone_256_2 (vm, + src_buffer, + (buffers + n_cloned), + n_buffers, head_end_offset); + + s->ref_count += (tmp_ref_count - 1); + + return n_cloned; +} + +#endif /* //__HICN_DATA_FWD_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/data_fwd_node.c b/hicn-plugin/src/network/data_fwd_node.c new file mode 100644 index 000000000..c65b62454 --- /dev/null +++ b/hicn-plugin/src/network/data_fwd_node.c @@ -0,0 +1,620 @@ +/* + * Copyright (c) 2017-2020 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 "data_fwd.h" +#include "mgmt.h" +#include "parser.h" +#include "infra.h" +#include "strategy.h" +#include "strategy_dpo_manager.h" +#include "state.h" +#include "error.h" + +/* Stats string values */ +static char *hicn_data_fwd_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +/* Declarations */ +always_inline void +drop_packet (vlib_main_t * vm, u32 bi0, + u32 * n_left_to_next, u32 * next0, u32 ** to_next, + u32 * next_index, vlib_node_runtime_t * node); + +always_inline int +hicn_satisfy_faces (vlib_main_t * vm, u32 b0, + hicn_pcs_entry_t * pitp, u32 * n_left_to_next, + u32 ** to_next, u32 * next_index, + vlib_node_runtime_t * node, u8 isv6, + vl_api_hicn_api_node_stats_get_reply_t * stats); + +always_inline void +clone_data_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t * pitp, hicn_header_t * hicn0, f64 tnow, + hicn_hash_node_t * nodep, vlib_buffer_t * b0, + hicn_hash_entry_t * hash_entry, u64 name_hash, + hicn_buffer_t * hicnb, const hicn_dpo_vft_t * dpo_vft, + dpo_id_t * hicn_dpo_id, hicn_lifetime_t dmsg_lifetime); + + +/* packet trace format function */ +always_inline u8 *hicn_data_fwd_format_trace (u8 * s, va_list * args); + +vlib_node_registration_t hicn_data_fwd_node; + +/* + * ICN forwarder node for interests: handling of Data delivered based on ACL. + * - 1 packet at a time - ipv4/tcp ipv6/tcp + */ +static uword +hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + + u32 n_left_from, *from, *to_next; + hicn_data_fwd_next_t next_index; + hicn_pit_cs_t *pitcs = &hicn_main.pitcs; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + f64 tnow; + u32 data_received = 1; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + /* Capture time in vpp terms */ + tnow = vlib_time_now (vm); + + while (n_left_from > 0) + { + u32 n_left_to_next; + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *b0; + u8 isv6; + u8 *nameptr; + u16 namelen; + u32 bi0; + u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP; + hicn_name_t name; + hicn_header_t *hicn0; + hicn_buffer_t *hicnb0; + hicn_hash_node_t *node0; + const hicn_strategy_vft_t *strategy_vft0; + const hicn_dpo_vft_t *dpo_vft0; + u8 dpo_ctx_id0; + hicn_pcs_entry_t *pitp; + hicn_hash_entry_t *hash_entry0; + int ret = HICN_ERROR_NONE; + + /* Prefetch for next iteration. */ + if (n_left_from > 1) + { + vlib_buffer_t *b1; + b1 = vlib_get_buffer (vm, from[1]); + CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, STORE); + CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, STORE); + } + /* Dequeue a packet buffer */ + /* + * Do not copy the index in the next buffer, we'll do + * it later. The packet might be cloned, so the buffer to move + * to next must be the cloned one + */ + bi0 = from[0]; + from += 1; + n_left_from -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + /* Get hicn buffer and state */ + hicnb0 = hicn_get_buffer (b0); + 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); + 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))) + { + /* + * Remove the lock acquired from + * data_pcslookup node + */ + dpo_id_t hicn_dpo_id0 = { dpo_vft0->hicn_dpo_get_type (), 0, 0, + dpo_ctx_id0 + }; + hicn_pcs_remove_lock (pitcs, &pitp, &node0, vm, + hash_entry0, dpo_vft0, &hicn_dpo_id0); + + drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next, + &next_index, node); + + goto end_processing; + } + /* + * Check if the hit is instead a collision in the + * hash table. Unlikely to happen. + */ + /* + * there is no guarantee that the type of entry has + * not changed from the lookup. + */ + + if (tnow > pitp->shared.expire_time + || (hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED)) + { + dpo_id_t hicn_dpo_id0 = + { dpo_vft0->hicn_dpo_get_type (), 0, 0, dpo_ctx_id0 }; + hicn_pcs_delete (pitcs, &pitp, &node0, vm, hash_entry0, + dpo_vft0, &hicn_dpo_id0); + + drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next, + &next_index, node); + stats.pit_expired_count++; + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_data_fwd_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = HICN_PKT_TYPE_CONTENT; + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + t->next_index = next0; + clib_memcpy (t->packet_data, + vlib_buffer_get_current (b0), + sizeof (t->packet_data)); + } + } + else + { + ASSERT ((hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED) + == 0); + + data_received++; + /* + * We do not check if the data is coming from + * the outgoing interest face. + */ + + /* Prepare the buffer for the cloning */ + ret = hicn_satisfy_faces (vm, bi0, pitp, &n_left_to_next, + &to_next, &next_index, node, + isv6, &stats); + + dpo_id_t hicn_dpo_id0 = { dpo_vft0->hicn_dpo_get_type (), 0, 0, + dpo_ctx_id0 + }; + + if (PREDICT_FALSE (ret != HICN_ERROR_NONE)) + { + hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, + hash_entry0, dpo_vft0, &hicn_dpo_id0); + continue; + } + /* + * Call the strategy callback since the + * interest has been satisfied + */ + strategy_vft0->hicn_receive_data (dpo_ctx_id0, + pitp->u.pit.pe_txnh); + +#if HICN_FEATURE_CS + hicn_lifetime_t dmsg_lifetime; + + hicn_type_t type = hicnb0->type; + hicn_ops_vft[type.l1]->get_lifetime (type, &hicn0->protocol, + &dmsg_lifetime); + + if (dmsg_lifetime) + { + /* + * Clone data packet in the content store and + * convert the PIT entry into a CS entry + */ + clone_data_to_cs (vm, pitcs, pitp, hicn0, tnow, node0, + b0, hash_entry0, hicnb0->name_hash, + hicnb0, dpo_vft0, &hicn_dpo_id0, + dmsg_lifetime); + + hicn_pcs_remove_lock (pitcs, &pitp, &node0, vm, + hash_entry0, NULL, NULL); + } + else + { + /* + * If the packet is copied and not cloned, we need to free the vlib_buffer + */ + if (hicnb0->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL) + { + vlib_buffer_free_one (vm, bi0); + } + else + { + /* + * Remove one reference as the buffer is no + * longer in any frame. The vlib_buffer will be freed when + * all its cloned vlib_buffer will be freed. + */ + b0->ref_count--; + } + + /* Delete the PIT entry */ + hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, + hash_entry0, dpo_vft0, &hicn_dpo_id0); + } +#else + ASSERT (pitp == hicn_pit_get_data (node0)); + /* + * If the packet is copied and not cloned, we need to free the vlib_buffer + */ + if (hicnb0->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL) + { + vlib_buffer_free_one (vm, bi0); + } + else + { + /* + * Remove one reference as the buffer is no + * longer in any frame. The vlib_buffer will be freed when + * all its cloned vlib_buffer will be freed. + */ + b0->ref_count--; + } + + /* Delete the PIT entry */ + hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, + hash_entry0, dpo_vft0, &hicn_dpo_id0); +#endif + } + end_processing: + + /* Incr packet counter */ + stats.pkts_processed += 1; + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + u32 pit_int_count = hicn_pit_get_int_count (pitcs); + u32 pit_cs_count = hicn_pit_get_cs_count (pitcs); + + vlib_node_increment_counter (vm, hicn_data_fwd_node.index, + HICNFWD_ERROR_DATAS, stats.pkts_data_count); + + + update_node_counter (vm, hicn_data_fwd_node.index, + HICNFWD_ERROR_INT_COUNT, pit_int_count); + update_node_counter (vm, hicn_data_fwd_node.index, + HICNFWD_ERROR_CS_COUNT, pit_cs_count); + update_node_counter (vm, hicn_data_fwd_node.index, + HICNFWD_ERROR_INTEREST_AGG_ENTRY, + stats.pkts_data_count / data_received); + + return (frame->n_vectors); +} + +always_inline void +drop_packet (vlib_main_t * vm, u32 bi0, + u32 * n_left_to_next, u32 * next0, u32 ** to_next, + u32 * next_index, vlib_node_runtime_t * node) +{ + *next0 = HICN_DATA_FWD_NEXT_ERROR_DROP; + + (*to_next)[0] = bi0; + *to_next += 1; + *n_left_to_next -= 1; + + vlib_validate_buffer_enqueue_x1 (vm, node, *next_index, + *to_next, *n_left_to_next, bi0, *next0); +} + +always_inline int +hicn_satisfy_faces (vlib_main_t * vm, u32 bi0, + hicn_pcs_entry_t * pitp, u32 * n_left_to_next, + u32 ** to_next, u32 * next_index, + vlib_node_runtime_t * node, u8 isv6, + vl_api_hicn_api_node_stats_get_reply_t * stats) +{ + int found = 0; + int ret = HICN_ERROR_NONE; + u32 *clones = NULL, *header = NULL; + u32 n_left_from = 0; + u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP, next1 = + HICN_DATA_FWD_NEXT_ERROR_DROP; + word buffer_advance = CLIB_CACHE_LINE_BYTES * 2; + + /* + * We have a hard limit on the number of vlib_buffer that we can + * chain (no more than 256) + */ + /* + * The first group of vlib_buffer can be directly cloned from b0. We + * need to be careful to clone it only 254 times as the buffer + * already has n_add_reds=1. + */ + vec_alloc (clones, pitp->u.pit.faces.n_faces); + header = clones; + + /* Clone bi0 */ + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0); + + hicn_buffer_t *hicnb = hicn_get_buffer (b0); + + /* + * Mark the buffer as smaller than TWO_CL. It will be stored as is in the CS, without excluding + * the hicn_header. Cloning is not possible, it will be copied. + */ + if (b0->current_length <= (buffer_advance + (CLIB_CACHE_LINE_BYTES * 2))) + { + /* In this case the packet is copied. We don't need to add a reference as no buffer are + * chained to it. + */ + hicnb->flags |= HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL; + } + else + { + /* Add one reference to maintain the buffer in the CS. + * b0->ref_count == 0 has two meaning: it has 1 buffer or no buffer chained to it. + * vlib_buffer_clone2 add a number of reference equalt to pitp->u.pit.faces.n_faces - 1 + * as vlib_buffer_clone does. So after all the packet are forwarded the buffer stored in + * the CS will have ref_count == 0; + */ + b0->ref_count++; + } + + found = n_left_from = + vlib_buffer_clone2 (vm, bi0, clones, pitp->u.pit.faces.n_faces, + buffer_advance); + + ASSERT (n_left_from == pitp->u.pit.faces.n_faces); + + /* Index to iterate over the faces */ + int i = 0; + + while (n_left_from > 0) + { + + //Dual loop, X2 + while (n_left_from >= 4 && *n_left_to_next >= 2) + { + vlib_buffer_t *h0, *h1; + u32 hi0, hi1; + hicn_face_id_t face0, face1; + + /* Prefetch for next iteration. */ + { + vlib_buffer_t *h2, *h3; + h2 = vlib_get_buffer (vm, clones[2]); + h3 = vlib_get_buffer (vm, clones[3]); + CLIB_PREFETCH (h2, 2 * CLIB_CACHE_LINE_BYTES, STORE); + CLIB_PREFETCH (h3, 2 * CLIB_CACHE_LINE_BYTES, STORE); + } + + face0 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces); + face1 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces); + + h0 = vlib_get_buffer (vm, clones[0]); + h1 = vlib_get_buffer (vm, clones[1]); + + (*to_next)[0] = hi0 = clones[0]; + (*to_next)[1] = hi1 = clones[1]; + *to_next += 2; + *n_left_to_next -= 2; + n_left_from -= 2; + clones += 2; + + next0 = isv6 ? HICN_DATA_FWD_NEXT_IFACE6_OUT : + HICN_DATA_FWD_NEXT_IFACE4_OUT; + next1 = isv6 ? HICN_DATA_FWD_NEXT_IFACE6_OUT : + HICN_DATA_FWD_NEXT_IFACE4_OUT; + + vnet_buffer (h0)->ip.adj_index[VLIB_TX] = face0; + vnet_buffer (h1)->ip.adj_index[VLIB_TX] = face1; + + stats->pkts_data_count += 2; + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (h0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_data_fwd_trace_t *t = + vlib_add_trace (vm, node, h0, sizeof (*t)); + t->pkt_type = HICN_PKT_TYPE_CONTENT; + 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), + sizeof (t->packet_data)); + } + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (h1->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_data_fwd_trace_t *t = + vlib_add_trace (vm, node, h1, sizeof (*t)); + t->pkt_type = HICN_PKT_TYPE_CONTENT; + 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), + sizeof (t->packet_data)); + } + vlib_validate_buffer_enqueue_x2 (vm, node, *next_index, + (*to_next), *n_left_to_next, + hi0, hi1, next0, next1); + } + + + while (n_left_from > 0 && *n_left_to_next > 0) + { + vlib_buffer_t *h0; + u32 hi0; + hicn_face_id_t face0; + + face0 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces); + + h0 = vlib_get_buffer (vm, clones[0]); + + (*to_next)[0] = hi0 = clones[0]; + *to_next += 1; + *n_left_to_next -= 1; + n_left_from -= 1; + clones += 1; + + next0 = isv6 ? HICN_DATA_FWD_NEXT_IFACE6_OUT : + HICN_DATA_FWD_NEXT_IFACE4_OUT; + vnet_buffer (h0)->ip.adj_index[VLIB_TX] = face0; + + stats->pkts_data_count++; + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (h0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_data_fwd_trace_t *t = + vlib_add_trace (vm, node, h0, sizeof (*t)); + t->pkt_type = HICN_PKT_TYPE_CONTENT; + 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), + sizeof (t->packet_data)); + } + /* + * Verify speculative enqueue, maybe switch current + * next frame + */ + /* + * Fix in case of a wrong speculation. Needed to + * clone the data in the right frame + */ + vlib_validate_buffer_enqueue_x1 (vm, node, *next_index, + *to_next, *n_left_to_next, + hi0, next0); + + } + + /* Ensure that there is space for the next clone (if any) */ + if (PREDICT_FALSE (*n_left_to_next == 0)) + { + vlib_put_next_frame (vm, node, *next_index, *n_left_to_next); + + vlib_get_next_frame (vm, node, *next_index, *to_next, + *n_left_to_next); + } + } + + vec_free (header); + + if (PREDICT_FALSE (!found)) + { + ASSERT (0); + drop_packet (vm, bi0, n_left_to_next, &next0, to_next, next_index, + node); + ret = HICN_ERROR_FACE_NOT_FOUND; + } + return ret; +} + +always_inline void +clone_data_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t * pitp, hicn_header_t * hicn0, f64 tnow, + hicn_hash_node_t * nodep, vlib_buffer_t * b0, + hicn_hash_entry_t * hash_entry, u64 name_hash, + hicn_buffer_t * hicnb, const hicn_dpo_vft_t * dpo_vft, + dpo_id_t * hicn_dpo_id, hicn_lifetime_t dmsg_lifetime) +{ + /* + * At this point we think we're safe to proceed. Store the CS buf in + * the PIT/CS hashtable entry + */ + + /* + * Start turning the PIT into a CS. Note that we may be stepping on + * the PIT part of the union as we update the CS part, so don't + * expect the PIT part to be valid after this point. + */ + hicn_buffer_t *hicnb0 = hicn_get_buffer (b0); + hicn_pit_to_cs (vm, pitcs, pitp, hash_entry, nodep, dpo_vft, hicn_dpo_id, + hicnb->face_id, + hicnb0->flags & HICN_BUFFER_FLAGS_FACE_IS_APP); + + pitp->shared.create_time = tnow; + + if (dmsg_lifetime < HICN_PARAM_CS_LIFETIME_MIN + || dmsg_lifetime > HICN_PARAM_CS_LIFETIME_MAX) + { + dmsg_lifetime = HICN_PARAM_CS_LIFETIME_DFLT; + } + pitp->shared.expire_time = hicn_pcs_get_exp_time (tnow, dmsg_lifetime); + + /* Store the original packet buffer in the CS node */ + pitp->u.cs.cs_pkt_buf = vlib_get_buffer_index (vm, b0); +} + +/* packet trace format function */ +always_inline u8 * +hicn_data_fwd_format_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 *); + hicn_data_fwd_trace_t *t = va_arg (*args, hicn_data_fwd_trace_t *); + u32 indent = format_get_indent (s); + + s = format (s, "DATAFWD: pkt: %d, sw_if_index %d, next index %d\n", + (int) t->pkt_type, t->sw_if_index, t->next_index); + + s = format (s, "%U%U", format_white_space, indent, + format_ip6_header, t->packet_data, sizeof (t->packet_data)); + return (s); +} + +/* + * Node registration for the data forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(hicn_data_fwd_node) = +{ + .function = hicn_data_node_fn, + .name = "hicn-data-fwd", + .vector_size = sizeof(u32), + .format_trace = hicn_data_fwd_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(hicn_data_fwd_error_strings), + .error_strings = hicn_data_fwd_error_strings, + .n_next_nodes = HICN_DATA_FWD_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = { + [HICN_DATA_FWD_NEXT_V4_LOOKUP] = "ip4-lookup", + [HICN_DATA_FWD_NEXT_V6_LOOKUP] = "ip6-lookup", + [HICN_DATA_FWD_NEXT_IFACE4_OUT] = "hicn4-iface-output", + [HICN_DATA_FWD_NEXT_IFACE6_OUT] = "hicn6-iface-output", + [HICN_DATA_FWD_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/data_input_node.c b/hicn-plugin/src/network/data_input_node.c new file mode 100644 index 000000000..8d20f54a6 --- /dev/null +++ b/hicn-plugin/src/network/data_input_node.c @@ -0,0 +1,697 @@ +/* + * Copyright (c) 2020 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 /* for FIB table and entry creation */ +#include /* for FIB table and entry creation */ +#include +#include + +#include "mgmt.h" +#include "strategy_dpo_manager.h" + +static __clib_unused char *hicn_data_input_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +typedef struct +{ + u32 next_index; + u32 sw_if_index; +} hicn_data_input_t; + +typedef enum +{ + HICN_DATA_INPUT_IP6_NEXT_FACE, + HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL, + HICN_DATA_INPUT_IP6_N_NEXT, +} hicn_data_input_ip6_next_t; + +typedef enum +{ + HICN_DATA_INPUT_IP4_NEXT_FACE, + HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL, + HICN_DATA_INPUT_IP4_N_NEXT, +} hicn_data_input_ip4_next_t; + +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 isv6; +} hicn_data_input_trace_t; + +vlib_node_registration_t hicn_data_input_ip6_node; +vlib_node_registration_t hicn_data_input_ip4_node; + +static __clib_unused u8 * +format_hicn_data_input_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 *); + hicn_data_input_trace_t *t = va_arg (*args, hicn_data_input_trace_t *); + u32 indent = format_get_indent (s); + u8 isv6 = (u8) va_arg (*args, int); + + s = + format (s, "%U hicn_data_input%s: sw_if_index %d next-index %d", + format_white_space, indent, isv6 ? "_ip6" : "_ip4", + t->sw_if_index, t->next_index); + return s; +} + +static uword +hicn_data_input_ip6_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + ip6_main_t *im = &ip6_main; + vlib_combined_counter_main_t *cm = &load_balance_main.lbm_to_counters; + u32 n_left_from, n_left_to_next, *from, *to_next; + ip_lookup_next_t next; + u32 thread_index = vm->thread_index; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next = node->cached_next_index; + + while (n_left_from > 0) + { + vlib_get_next_frame (vm, node, next, to_next, n_left_to_next); + + while (n_left_from >= 4 && n_left_to_next >= 2) + { + vlib_buffer_t *p0, *p1; + u32 pi0, pi1, lbi0, lbi1, wrong_next; + ip_lookup_next_t next0, next1; + ip6_header_t *ip0, *ip1; + ip6_address_t *src_addr0, *src_addr1; + const dpo_id_t *dpo0, *dpo1; + const load_balance_t *lb0, *lb1; + + /* 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, sizeof (ip0[0]), LOAD); + CLIB_PREFETCH (p3->data, sizeof (ip0[0]), LOAD); + } + + pi0 = to_next[0] = from[0]; + pi1 = to_next[1] = from[1]; + + p0 = vlib_get_buffer (vm, pi0); + p1 = vlib_get_buffer (vm, pi1); + + ip0 = vlib_buffer_get_current (p0); + ip1 = vlib_buffer_get_current (p1); + + src_addr0 = &ip0->src_address; + src_addr1 = &ip1->src_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); + + lbi0 = ip6_fib_table_fwding_lookup (vnet_buffer (p0)->ip.fib_index, + src_addr0); + lbi1 = ip6_fib_table_fwding_lookup (vnet_buffer (p1)->ip.fib_index, + src_addr1); + + lb0 = load_balance_get (lbi0); + lb1 = load_balance_get (lbi1); + ASSERT (lb0->lb_n_buckets > 0); + ASSERT (lb1->lb_n_buckets > 0); + ASSERT (is_pow2 (lb0->lb_n_buckets)); + ASSERT (is_pow2 (lb1->lb_n_buckets)); + + vnet_buffer (p0)->ip.flow_hash = vnet_buffer (p1)->ip.flow_hash = 0; + + //No vpp loadbalancing. Missing header file to exploit it + dpo0 = load_balance_get_bucket_i (lb0, 0); + dpo1 = load_balance_get_bucket_i (lb1, 0); + + if (dpo_is_hicn (dpo0)) + next0 = HICN_DATA_INPUT_IP6_NEXT_FACE; + else + next0 = HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL; + + if (dpo_is_hicn (dpo1)) + next1 = HICN_DATA_INPUT_IP6_NEXT_FACE; + else + next1 = HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL; + + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + (p0->flags & VLIB_BUFFER_IS_TRACED)) + { + hicn_data_input_trace_t *t = + vlib_add_trace (vm, node, p0, sizeof (*t)); + t->sw_if_index = vnet_buffer (p0)->sw_if_index[VLIB_RX]; + t->next_index = next0; + t->isv6 = 1; + } + + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + (p1->flags & VLIB_BUFFER_IS_TRACED)) + { + hicn_data_input_trace_t *t = + vlib_add_trace (vm, node, p1, sizeof (*t)); + t->sw_if_index = vnet_buffer (p1)->sw_if_index[VLIB_RX]; + t->next_index = next1; + t->isv6 = 1; + } + + + vlib_increment_combined_counter + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); + vlib_increment_combined_counter + (cm, thread_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1)); + + from += 2; + to_next += 2; + n_left_to_next -= 2; + n_left_from -= 2; + + wrong_next = (next0 != next) + 2 * (next1 != next); + if (PREDICT_FALSE (wrong_next != 0)) + { + switch (wrong_next) + { + case 1: + /* A B A */ + to_next[-2] = pi1; + to_next -= 1; + n_left_to_next += 1; + vlib_set_next_frame_buffer (vm, node, next0, pi0); + break; + + case 2: + /* A A B */ + to_next -= 1; + n_left_to_next += 1; + vlib_set_next_frame_buffer (vm, node, next1, pi1); + break; + + case 3: + /* A B C */ + to_next -= 2; + n_left_to_next += 2; + vlib_set_next_frame_buffer (vm, node, next0, pi0); + vlib_set_next_frame_buffer (vm, node, next1, pi1); + if (next0 == next1) + { + /* A B B */ + vlib_put_next_frame (vm, node, next, n_left_to_next); + next = next1; + vlib_get_next_frame (vm, node, next, to_next, + n_left_to_next); + } + } + } + } + + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *p0; + ip6_header_t *ip0; + u32 pi0, lbi0; + ip_lookup_next_t next0; + load_balance_t *lb0; + ip6_address_t *src_addr0; + const dpo_id_t *dpo0; + + pi0 = from[0]; + to_next[0] = pi0; + + p0 = vlib_get_buffer (vm, pi0); + ip0 = vlib_buffer_get_current (p0); + src_addr0 = &ip0->src_address; + ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, p0); + lbi0 = ip6_fib_table_fwding_lookup (vnet_buffer (p0)->ip.fib_index, + src_addr0); + + lb0 = load_balance_get (lbi0); + ASSERT (lb0->lb_n_buckets > 0); + ASSERT (is_pow2 (lb0->lb_n_buckets)); + + //No vpp loadbalancing. Missing header file to exploit it + dpo0 = load_balance_get_bucket_i (lb0, 0); + + if (dpo_is_hicn (dpo0)) + next0 = HICN_DATA_INPUT_IP6_NEXT_FACE; + else + next0 = HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL; + + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + (p0->flags & VLIB_BUFFER_IS_TRACED)) + { + hicn_data_input_trace_t *t = + vlib_add_trace (vm, node, p0, sizeof (*t)); + t->sw_if_index = vnet_buffer (p0)->sw_if_index[VLIB_RX]; + t->next_index = next0; + t->isv6 = 1; + } + + vlib_increment_combined_counter + (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); + + from += 1; + to_next += 1; + n_left_to_next -= 1; + n_left_from -= 1; + + if (PREDICT_FALSE (next0 != next)) + { + n_left_to_next += 1; + vlib_put_next_frame (vm, node, next, n_left_to_next); + next = next0; + vlib_get_next_frame (vm, node, next, to_next, n_left_to_next); + to_next[0] = pi0; + to_next += 1; + n_left_to_next -= 1; + } + } + + vlib_put_next_frame (vm, node, next, n_left_to_next); + } + + return frame->n_vectors; +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(hicn_data_input_ip6) = + { + .function = hicn_data_input_ip6_fn, + .name = "hicn-data-input-ip6", + .vector_size = sizeof(u32), + .format_trace = format_hicn_data_input_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(hicn_data_input_error_strings), + .error_strings = hicn_data_input_error_strings, + .n_next_nodes = HICN_DATA_INPUT_IP6_N_NEXT, + .next_nodes = + { + [HICN_DATA_INPUT_IP6_NEXT_FACE] = "hicn6-face-input", + [HICN_DATA_INPUT_IP6_NEXT_IP6_LOCAL] = "ip6-local-end-of-arc" + }, + }; +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +VNET_FEATURE_INIT(hicn_data_input_ip6_arc, static)= + { + .arc_name = "ip6-local", + .node_name = "hicn-data-input-ip6", + .runs_before = VNET_FEATURES("ip6-local-end-of-arc"), + }; +/* *INDENT-ON* */ + + + +always_inline uword +hicn_data_input_ip4_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + ip4_main_t *im = &ip4_main; + vlib_combined_counter_main_t *cm = &load_balance_main.lbm_to_counters; + u32 n_left, *from; + u32 thread_index = vm->thread_index; + vlib_buffer_t *bufs[VLIB_FRAME_SIZE]; + vlib_buffer_t **b = bufs; + u16 nexts[VLIB_FRAME_SIZE], *next; + + from = vlib_frame_vector_args (frame); + n_left = frame->n_vectors; + next = nexts; + vlib_get_buffers (vm, from, bufs, n_left); + +#if (CLIB_N_PREFETCHES >= 8) + while (n_left >= 4) + { + ip4_header_t *ip0, *ip1, *ip2, *ip3; + const load_balance_t *lb0, *lb1, *lb2, *lb3; + ip4_fib_mtrie_t *mtrie0, *mtrie1, *mtrie2, *mtrie3; + ip4_fib_mtrie_leaf_t leaf0, leaf1, leaf2, leaf3; + ip4_address_t *src_addr0, *src_addr1, *src_addr2, *src_addr3; + u32 lb_index0, lb_index1, lb_index2, lb_index3; + const dpo_id_t *dpo0, *dpo1, *dpo2, *dpo3; + + /* Prefetch next iteration. */ + if (n_left >= 8) + { + vlib_prefetch_buffer_header (b[4], LOAD); + vlib_prefetch_buffer_header (b[5], LOAD); + vlib_prefetch_buffer_header (b[6], LOAD); + vlib_prefetch_buffer_header (b[7], LOAD); + + CLIB_PREFETCH (b[4]->data, sizeof (ip0[0]), LOAD); + CLIB_PREFETCH (b[5]->data, sizeof (ip0[0]), LOAD); + CLIB_PREFETCH (b[6]->data, sizeof (ip0[0]), LOAD); + CLIB_PREFETCH (b[7]->data, sizeof (ip0[0]), LOAD); + } + + ip0 = vlib_buffer_get_current (b[0]); + ip1 = vlib_buffer_get_current (b[1]); + ip2 = vlib_buffer_get_current (b[2]); + ip3 = vlib_buffer_get_current (b[3]); + + src_addr0 = &ip0->src_address; + src_addr1 = &ip1->src_address; + src_addr2 = &ip2->src_address; + src_addr3 = &ip3->src_address; + + ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]); + ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[1]); + ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[2]); + ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[3]); + + mtrie0 = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie; + mtrie1 = &ip4_fib_get (vnet_buffer (b[1])->ip.fib_index)->mtrie; + mtrie2 = &ip4_fib_get (vnet_buffer (b[2])->ip.fib_index)->mtrie; + mtrie3 = &ip4_fib_get (vnet_buffer (b[3])->ip.fib_index)->mtrie; + + leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, src_addr0); + leaf1 = ip4_fib_mtrie_lookup_step_one (mtrie1, src_addr1); + leaf2 = ip4_fib_mtrie_lookup_step_one (mtrie2, src_addr2); + leaf3 = ip4_fib_mtrie_lookup_step_one (mtrie3, src_addr3); + + leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 2); + leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, src_addr1, 2); + leaf2 = ip4_fib_mtrie_lookup_step (mtrie2, leaf2, src_addr2, 2); + leaf3 = ip4_fib_mtrie_lookup_step (mtrie3, leaf3, src_addr3, 2); + + leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 3); + leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, src_addr1, 3); + leaf2 = ip4_fib_mtrie_lookup_step (mtrie2, leaf2, src_addr2, 3); + leaf3 = ip4_fib_mtrie_lookup_step (mtrie3, leaf3, src_addr3, 3); + + lb_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0); + lb_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1); + lb_index2 = ip4_fib_mtrie_leaf_get_adj_index (leaf2); + lb_index3 = ip4_fib_mtrie_leaf_get_adj_index (leaf3); + + ASSERT (lb_index0 && lb_index1 && lb_index2 && lb_index3); + lb0 = load_balance_get (lb_index0); + lb1 = load_balance_get (lb_index1); + lb2 = load_balance_get (lb_index2); + lb3 = load_balance_get (lb_index3); + + ASSERT (lb0->lb_n_buckets > 0); + ASSERT (is_pow2 (lb0->lb_n_buckets)); + ASSERT (lb1->lb_n_buckets > 0); + ASSERT (is_pow2 (lb1->lb_n_buckets)); + ASSERT (lb2->lb_n_buckets > 0); + ASSERT (is_pow2 (lb2->lb_n_buckets)); + ASSERT (lb3->lb_n_buckets > 0); + ASSERT (is_pow2 (lb3->lb_n_buckets)); + + dpo0 = load_balance_get_bucket_i (lb0, 0); + dpo1 = load_balance_get_bucket_i (lb1, 0); + dpo2 = load_balance_get_bucket_i (lb2, 0); + dpo3 = load_balance_get_bucket_i (lb3, 0); + + if (dpo_is_hicn (dpo0)) + next[0] = HICN_DATA_INPUT_IP4_NEXT_FACE; + else + next[0] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; + + if (dpo_is_hicn (dpo1)) + next[1] = HICN_DATA_INPUT_IP4_NEXT_FACE; + else + next[1] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; + + if (dpo_is_hicn (dpo2)) + next[2] = HICN_DATA_INPUT_IP4_NEXT_FACE; + else + next[2] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; + + if (dpo_is_hicn (dpo3)) + next[3] = HICN_DATA_INPUT_IP4_NEXT_FACE; + else + next[3] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; + + + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + (b[0]->flags & VLIB_BUFFER_IS_TRACED)) + { + hicn_data_input_trace_t *t = + vlib_add_trace (vm, node, b[0], sizeof (*t)); + t->sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_RX]; + t->next_index = next[0]; + t->isv6 = 0; + } + + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + (b[1]->flags & VLIB_BUFFER_IS_TRACED)) + { + hicn_data_input_trace_t *t = + vlib_add_trace (vm, node, b[1], sizeof (*t)); + t->sw_if_index = vnet_buffer (b[1])->sw_if_index[VLIB_RX]; + t->next_index = next[1]; + t->isv6 = 0; + } + + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + (b[2]->flags & VLIB_BUFFER_IS_TRACED)) + { + hicn_data_input_trace_t *t = + vlib_add_trace (vm, node, b[2], sizeof (*t)); + t->sw_if_index = vnet_buffer (b[2])->sw_if_index[VLIB_RX]; + t->next_index = next[0]; + t->isv6 = 0; + } + + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + (b[3]->flags & VLIB_BUFFER_IS_TRACED)) + { + hicn_data_input_trace_t *t = + vlib_add_trace (vm, node, b[3], sizeof (*t)); + t->sw_if_index = vnet_buffer (b[3])->sw_if_index[VLIB_RX]; + t->next_index = next[3]; + t->isv6 = 0; + } + + vlib_increment_combined_counter + (cm, thread_index, lb_index0, 1, + vlib_buffer_length_in_chain (vm, b[0])); + vlib_increment_combined_counter + (cm, thread_index, lb_index1, 1, + vlib_buffer_length_in_chain (vm, b[1])); + vlib_increment_combined_counter + (cm, thread_index, lb_index2, 1, + vlib_buffer_length_in_chain (vm, b[2])); + vlib_increment_combined_counter + (cm, thread_index, lb_index3, 1, + vlib_buffer_length_in_chain (vm, b[3])); + + b += 4; + next += 4; + n_left -= 4; + } +#elif (CLIB_N_PREFETCHES >= 4) + while (n_left >= 4) + { + ip4_header_t *ip0, *ip1; + const load_balance_t *lb0, *lb1; + ip4_fib_mtrie_t *mtrie0, *mtrie1; + ip4_fib_mtrie_leaf_t leaf0, leaf1; + ip4_address_t *src_addr0, *src_addr1; + u32 lb_index0, lb_index1; + flow_hash_config_t flow_hash_config0, flow_hash_config1; + u32 hash_c0, hash_c1; + const dpo_id_t *dpo0, *dpo1; + + /* Prefetch next iteration. */ + { + vlib_prefetch_buffer_header (b[2], LOAD); + vlib_prefetch_buffer_header (b[3], LOAD); + + CLIB_PREFETCH (b[2]->data, sizeof (ip0[0]), LOAD); + CLIB_PREFETCH (b[3]->data, sizeof (ip0[0]), LOAD); + } + + ip0 = vlib_buffer_get_current (b[0]); + ip1 = vlib_buffer_get_current (b[1]); + + src_addr0 = &ip0->src_address; + src_addr1 = &ip1->src_address; + + ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]); + ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[1]); + + mtrie0 = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie; + mtrie1 = &ip4_fib_get (vnet_buffer (b[1])->ip.fib_index)->mtrie; + + leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, src_addr0); + leaf1 = ip4_fib_mtrie_lookup_step_one (mtrie1, src_addr1); + + leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 2); + leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, src_addr1, 2); + + leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 3); + leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, src_addr1, 3); + + lb_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0); + lb_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1); + + ASSERT (lb_index0 && lb_index1); + lb0 = load_balance_get (lb_index0); + lb1 = load_balance_get (lb_index1); + + ASSERT (lb0->lb_n_buckets > 0); + ASSERT (is_pow2 (lb0->lb_n_buckets)); + ASSERT (lb1->lb_n_buckets > 0); + ASSERT (is_pow2 (lb1->lb_n_buckets)); + + dpo0 = load_balance_get_bucket_i (lb0, 0); + dpo1 = load_balance_get_bucket_i (lb1, 0); + + if (dpo_is_hicn (dpo0)) + next[0] = HICN_DATA_INPUT_IP4_NEXT_FACE; + else + next[0] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; + + if (dpo_is_hicn (dpo1)) + next[1] = HICN_DATA_INPUT_IP4_NEXT_FACE; + else + next[1] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; + + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + hicn_data_input_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + t->next_index = next[0]; + t->isv6 = 0; + } + + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + (b1->flags & VLIB_BUFFER_IS_TRACED)) + { + hicn_data_input_trace_t *t = + vlib_add_trace (vm, node, b1, sizeof (*t)); + t->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX]; + t->next_index = next[1]; + t->isv6 = 0; + } + + + vlib_increment_combined_counter + (cm, thread_index, lb_index0, 1, + vlib_buffer_length_in_chain (vm, b[0])); + vlib_increment_combined_counter + (cm, thread_index, lb_index1, 1, + vlib_buffer_length_in_chain (vm, b[1])); + + b += 2; + next += 2; + n_left -= 2; + } +#endif + while (n_left > 0) + { + ip4_header_t *ip0; + const load_balance_t *lb0; + ip4_fib_mtrie_t *mtrie0; + ip4_fib_mtrie_leaf_t leaf0; + ip4_address_t *src_addr0; + u32 lbi0; + const dpo_id_t *dpo0; + + ip0 = vlib_buffer_get_current (b[0]); + src_addr0 = &ip0->src_address; + ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, b[0]); + + mtrie0 = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie; + leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, src_addr0); + leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 2); + leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, src_addr0, 3); + lbi0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0); + + ASSERT (lbi0); + lb0 = load_balance_get (lbi0); + + ASSERT (lb0->lb_n_buckets > 0); + ASSERT (is_pow2 (lb0->lb_n_buckets)); + + dpo0 = load_balance_get_bucket_i (lb0, 0); + + if (dpo_is_hicn (dpo0)) + next[0] = HICN_DATA_INPUT_IP4_NEXT_FACE; + else + next[0] = HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL; + + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + (b[0]->flags & VLIB_BUFFER_IS_TRACED)) + { + hicn_data_input_trace_t *t = + vlib_add_trace (vm, node, b[0], sizeof (*t)); + t->sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_RX]; + t->next_index = next[0]; + t->isv6 = 0; + } + + vlib_increment_combined_counter (cm, thread_index, lbi0, 1, + vlib_buffer_length_in_chain (vm, + b[0])); + + b += 1; + next += 1; + n_left -= 1; + } + + vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors); + + if (node->flags & VLIB_NODE_FLAG_TRACE) + ip4_forward_next_trace (vm, node, frame, VLIB_TX); + + return frame->n_vectors; +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(hicn_data_input_ip4) = + { + .function = hicn_data_input_ip4_fn, + .name = "hicn-data-input-ip4", + .vector_size = sizeof(u32), + .format_trace = format_hicn_data_input_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(hicn_data_input_error_strings), + .error_strings = hicn_data_input_error_strings, + .n_next_nodes = HICN_DATA_INPUT_IP4_N_NEXT, + .next_nodes = + { + [HICN_DATA_INPUT_IP4_NEXT_FACE] = "hicn4-face-input", + [HICN_DATA_INPUT_IP4_NEXT_IP4_LOCAL] = "ip4-local-end-of-arc" + }, + }; +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +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"), + }; +/* *INDENT-ON* */ diff --git a/hicn-plugin/src/network/data_pcslookup.h b/hicn-plugin/src/network/data_pcslookup.h new file mode 100644 index 000000000..e3050c31c --- /dev/null +++ b/hicn-plugin/src/network/data_pcslookup.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017-2019 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_DATA_PCSLOOKUP_H__ +#define __HICN_DATA_PCSLOOKUP_H__ + +#include "pcs.h" + +/** + * @file data_pcslookup.h + * + * This is the node encoutered by data packets after the hicn6-face-input or + * hicn4-face-input. This node performs a lookup in the pit and content store and + * if there is a hit in the PIT, the vlib buffer is passed to the hicn-data-fwd + * while if there is a hit in the CS or there isn't any hit, the packet is dropped. + */ + +/* + * Node context data; we think this is per-thread/instance + */ +typedef struct hicn_data_pcslookup_runtime_s +{ + int id; + hicn_pit_cs_t *pitcs; +} hicn_data_pcslookup_runtime_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; +} hicn_data_pcslookup_trace_t; + +typedef enum +{ + HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD, /* This must be one position + * before the error drop!! */ + HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP, + HICN_DATA_PCSLOOKUP_N_NEXT, +} hicn_data_pcslookup_next_t; + +#endif /* //__HICN_DATA_PCSLOOKUP_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/data_pcslookup_node.c b/hicn-plugin/src/network/data_pcslookup_node.c new file mode 100644 index 000000000..99af350b0 --- /dev/null +++ b/hicn-plugin/src/network/data_pcslookup_node.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2017-2019 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 "data_pcslookup.h" +#include "infra.h" +#include "mgmt.h" +#include "parser.h" +#include "state.h" +#include "strategy.h" +#include "strategy_dpo_manager.h" + +/* Stats string values */ +static char *hicn_data_pcslookup_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +/* packet trace format function */ +always_inline u8 *hicn_data_pcslookup_format_trace (u8 * s, va_list * args); + +vlib_node_registration_t hicn_data_pcslookup_node; + +/* + * hICN node for handling data. It performs a lookup in the PIT. + */ +static uword +hicn_data_pcslookup_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next; + hicn_data_pcslookup_next_t next_index; + hicn_data_pcslookup_runtime_t *rt; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + + rt = vlib_node_get_runtime_data (vm, node->node_index); + + if (PREDICT_FALSE (rt->pitcs == NULL)) + { + rt->pitcs = &hicn_main.pitcs; + } + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + u32 n_left_to_next; + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *b0; + u8 isv6; + u8 *nameptr; + u16 namelen; + u32 bi0; + u32 next0 = HICN_DATA_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; + u8 is_cs0; + u8 hash_entry_id = 0; + u8 bucket_is_overflown = 0; + u32 bucket_id = ~0; + + /* Prefetch for next iteration. */ + if (n_left_from > 1) + { + vlib_buffer_t *b1; + b1 = vlib_get_buffer (vm, from[1]); + // Prefetch two cache lines-- 128 byte-- so that we load the + // hicn_buffer_t as well + CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, STORE); + CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, LOAD); + } + /* Dequeue a packet buffer */ + bi0 = from[0]; + from += 1; + n_left_from -= 1; + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + next0 = HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP; + + /* Incr packet counter */ + stats.pkts_processed += 1; + + ret0 = hicn_data_parse_pkt (b0, &name, &namelen, &hicn0, &isv6); + nameptr = (u8 *) (&name); + + if (PREDICT_TRUE (ret0 == HICN_ERROR_NONE && + hicn_hashtb_fullhash (nameptr, namelen, + &name_hash) == + HICN_ERROR_NONE)) + { + int res = + hicn_hashtb_lookup_node (rt->pitcs->pcs_table, nameptr, + namelen, name_hash, + 1 + /*is_data. Do not take lock if hit CS */ + , + &node_id0, &dpo_ctx_id0, &vft_id0, + &is_cs0, &hash_entry_id, &bucket_id, + &bucket_is_overflown); + + stats.pkts_data_count += 1; + + if (res == HICN_ERROR_NONE) + { + /* + * In case the result of the lookup + * is a CS entry, the packet is + * dropped + */ + next0 = HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD + is_cs0; + } + } + + hicn_store_internal_state (b0, name_hash, node_id0, dpo_ctx_id0, + vft_id0, hash_entry_id, bucket_id, + bucket_is_overflown); + + /* + * Verify speculative enqueue, maybe switch current + * next frame + */ + /* + * Fix in case of a wrong speculation. Needed to + * clone the data in the right frame + */ + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, + n_left_to_next, bi0, next0); + + /* Maybe trace */ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_data_pcslookup_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = HICN_PKT_TYPE_CONTENT; + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + t->next_index = next0; + } + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + /* Check the CS LRU, and trim if necessary. */ + u32 pit_int_count = hicn_pit_get_int_count (rt->pitcs); + u32 pit_cs_count = hicn_pit_get_cs_count (rt->pitcs); + + vlib_node_increment_counter (vm, hicn_data_pcslookup_node.index, + HICNFWD_ERROR_PROCESSED, stats.pkts_processed); + + vlib_node_increment_counter (vm, hicn_data_pcslookup_node.index, + HICNFWD_ERROR_DATAS, stats.pkts_data_count); + + update_node_counter (vm, hicn_data_pcslookup_node.index, + HICNFWD_ERROR_INT_COUNT, pit_int_count); + update_node_counter (vm, hicn_data_pcslookup_node.index, + HICNFWD_ERROR_CS_COUNT, pit_cs_count); + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn_data_pcslookup_format_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 *); + hicn_data_pcslookup_trace_t *t = + va_arg (*args, hicn_data_pcslookup_trace_t *); + + s = format (s, "DATA-PCSLOOKUP: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + return (s); +} + +/* + * Node registration for the data forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(hicn_data_pcslookup_node) = +{ + .function = hicn_data_pcslookup_node_fn, + .name = "hicn-data-pcslookup", + .vector_size = sizeof(u32), + .runtime_data_bytes = sizeof(hicn_data_pcslookup_runtime_t), + .format_trace = hicn_data_pcslookup_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(hicn_data_pcslookup_error_strings), + .error_strings = hicn_data_pcslookup_error_strings, + .n_next_nodes = HICN_DATA_PCSLOOKUP_N_NEXT, + .next_nodes = { + [HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD] = "hicn-data-fwd", + [HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/error.c b/hicn-plugin/src/network/error.c new file mode 100644 index 000000000..edd0dd77b --- /dev/null +++ b/hicn-plugin/src/network/error.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017-2019 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 + +const char *HICN_ERROR_STRING[] = { +#define _(a,b,c) c, + foreach_hicn_error +#undef _ +}; + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/face_db.h b/hicn-plugin/src/network/face_db.h new file mode 100644 index 000000000..4dd8b2f32 --- /dev/null +++ b/hicn-plugin/src/network/face_db.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2017-2020 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_DB_H__ +#define __HICN_FACE_DB_H__ + +#include +#include "faces/face.h" + +/** + * @file face_db.h + * + * Define a face db that is store in every pit entry. A face db containes a list + * of incoming faces for interest packets that are used to forward data packets + * on the interests' reverse path + */ + +/* Must be power of two */ +#define HICN_FACE_DB_INLINE_FACES 8 + +#define HICN_PIT_BITMAP_SIZE_BYTE HICN_PARAM_FACES_MAX/8 +#define HICN_PIT_N_HOP_BITMAP_SIZE HICN_PARAM_FACES_MAX + +#define HICN_PIT_N_HOP_BUCKET (HICN_PARAM_PIT_ENTRY_PHOPS_MAX - HICN_FACE_DB_INLINE_FACES) + +typedef struct hicn_face_bucket_s +{ + /* Array of indexes of virtual faces */ + hicn_face_id_t faces[HICN_PIT_N_HOP_BUCKET]; + + /* Used to check if interests are retransmission */ + u8 bitmap[HICN_PIT_BITMAP_SIZE_BYTE]; + +} hicn_face_bucket_t; + +extern hicn_face_bucket_t *hicn_face_bucket_pool; + +typedef struct __attribute__ ((packed)) hicn_face_db_s +{ + /* 19B + 1B = 20B */ + /* Equal to one or zero */ + u8 is_overflow; + + /* Number of faces in the last bucket */ + /* Or next availabe entry for storing a dpo_id_t */ + /* 20B + 4B = 24B */ + u32 n_faces; + + /* 24B + 32B (8*4) = 56B */ + /* Array of indexes of virtual faces */ + hicn_face_id_t inline_faces[HICN_FACE_DB_INLINE_FACES]; + + /* 56B + 4B = 60B */ + u32 next_bucket; + + /* 60B + 4B = 64B */ + u32 align; + //align back to 64 + +} hicn_face_db_t; + +always_inline hicn_face_id_t +hicn_face_db_get_dpo_face (u32 index, hicn_face_db_t * face_db) +{ + ASSERT (index < face_db->n_faces); + + return index < HICN_FACE_DB_INLINE_FACES ? (face_db->inline_faces[index]) : + (pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket)->faces + [(index - HICN_FACE_DB_INLINE_FACES) & (HICN_PIT_N_HOP_BUCKET - 1)]); +} + +always_inline void +hicn_face_db_init (int max_element) +{ + pool_init_fixed (hicn_face_bucket_pool, max_element); +} + +always_inline hicn_face_bucket_t * +hicn_face_db_get_bucket (u32 bucket_index) +{ + return pool_elt_at_index (hicn_face_bucket_pool, bucket_index); +} + +always_inline void +hicn_face_db_add_face (hicn_face_id_t face_id, hicn_face_db_t * face_db) +{ + //ASSERT (dpo->dpoi_index != ~0); + + hicn_face_bucket_t *faces_bkt = + pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket); + + hicn_face_id_t *element = + face_db->n_faces < + HICN_FACE_DB_INLINE_FACES ? &(face_db->inline_faces[face_db->n_faces]) : + &(faces_bkt->faces + [(face_db->n_faces - + HICN_FACE_DB_INLINE_FACES) & (HICN_PIT_N_HOP_BUCKET - 1)]); + + *element = face_id; + + u32 bitmap_index = face_id % HICN_PIT_N_HOP_BITMAP_SIZE; + u32 position_array = bitmap_index / 8; + u8 bit_index = (u8) (bitmap_index - position_array * 8); + + faces_bkt->bitmap[position_array] |= (0x01 << bit_index); + face_db->n_faces++; +} + +always_inline u8 +hicn_face_search (hicn_face_id_t index, hicn_face_db_t * face_db) +{ + hicn_face_bucket_t *faces_bkt = + pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket); + u32 bitmap_index = index % HICN_PIT_N_HOP_BITMAP_SIZE; + + u32 position_array = bitmap_index / 8; + u8 bit_index = bitmap_index - position_array * 8; + + return (faces_bkt->bitmap[position_array] >> bit_index) & 0x01; +} + +always_inline void +hicn_faces_flush (hicn_face_db_t * face_db) +{ + hicn_face_bucket_t *faces_bkt = + pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket); + clib_memset_u8 (&(faces_bkt->bitmap), 0, HICN_PIT_BITMAP_SIZE_BYTE); + face_db->n_faces = 0; + pool_put_index (hicn_face_bucket_pool, face_db->next_bucket); +} + + +#endif /* // __HICN_FACE_DB_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/faces/app/address_mgr.c b/hicn-plugin/src/network/faces/app/address_mgr.c new file mode 100644 index 000000000..ecc99a200 --- /dev/null +++ b/hicn-plugin/src/network/faces/app/address_mgr.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2017-2020 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. + */ + +/* + * Copyright (c) 2017-2019 by cisco systems inc. All rights reserved. + * + */ + +#include + +#include +#include +#include //ip4_add_del_ip_address +#include //ip6_add_del_ip_address +#include //FIB_PROTOCOL_IP4/6, FIB_NODE_INDEX_INVALID +#include //FIB_SOURCE_PRIORITY_HI +#include +#include +#include //appif_flags +#include //vnet_sw_interface_set_flags + +#include + +#include "address_mgr.h" +#include "../../hicn.h" +#include "../../infra.h" +#include "../face.h" +#include "../../strategy_dpo_ctx.h" +#include "../../route.h" + +typedef struct address_mgr_main_s +{ + ip4_address_t next_ip4_local_addr; + ip6_address_t next_ip6_local_addr; +} address_mgr_main_t; + +address_mgr_main_t address_mgr_main; + +static void +increment_v4_address (ip4_address_t * a, u32 val) +{ + u32 v; + + v = clib_net_to_host_u32 (a->as_u32) + val; + a->as_u32 = clib_host_to_net_u32 (v); +} + +static void +increment_v6_address (ip6_address_t * a, u64 val) +{ + u64 v; + + v = clib_net_to_host_u64 (a->as_u64[1]) + val; + a->as_u64[1] = clib_host_to_net_u64 (v); +} + +void +get_two_ip4_addresses (ip4_address_t * appif_addr, ip4_address_t * nh_addr) +{ + /* We want two consecutives address that fall into a /31 mask */ + if (address_mgr_main.next_ip4_local_addr.as_u8[3] & 0x01) + increment_v4_address (&(address_mgr_main.next_ip4_local_addr), 1); + + *appif_addr = address_mgr_main.next_ip4_local_addr; + increment_v4_address (&(address_mgr_main.next_ip4_local_addr), 1); + *nh_addr = address_mgr_main.next_ip4_local_addr; + fib_prefix_t fib_pfx; + fib_node_index_t fib_entry_index = FIB_NODE_INDEX_INVALID; + u32 fib_index; + + fib_pfx.fp_proto = FIB_PROTOCOL_IP4; + fib_pfx.fp_len = ADDR_MGR_IP4_LEN; + /* At this point the face exists in the face table */ + do + { + /* Check if the route already exist in the fib */ + fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 0, appif_addr->as_u8); + fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto, + HICN_FIB_TABLE, + FIB_SOURCE_PRIORITY_HI); + fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx); + fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PRIORITY_HI); + if (fib_entry_index != FIB_NODE_INDEX_INVALID) + { + fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 0, nh_addr->as_u8); + fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto, + HICN_FIB_TABLE, + FIB_SOURCE_PRIORITY_HI); + fib_entry_index = + fib_table_lookup_exact_match (fib_index, &fib_pfx); + fib_table_unlock (fib_index, fib_pfx.fp_proto, + FIB_SOURCE_PRIORITY_HI); + } + if (fib_entry_index != FIB_NODE_INDEX_INVALID) + { + increment_v4_address (appif_addr, 2); + increment_v4_address (nh_addr, 2); + } + } + while (fib_entry_index != FIB_NODE_INDEX_INVALID); + + address_mgr_main.next_ip4_local_addr = *nh_addr; + increment_v4_address (&(address_mgr_main.next_ip4_local_addr), 1); +} + +void +get_two_ip6_addresses (ip6_address_t * appif_addr, ip6_address_t * nh_addr) +{ + + /* We want two consecutives address that fall into a /127 mask */ + if (address_mgr_main.next_ip6_local_addr.as_u8[15] & 0x01) + increment_v6_address (&(address_mgr_main.next_ip6_local_addr), 1); + + *appif_addr = address_mgr_main.next_ip6_local_addr; + increment_v6_address (&(address_mgr_main.next_ip6_local_addr), 1); + *nh_addr = address_mgr_main.next_ip6_local_addr; + + + fib_prefix_t fib_pfx; + fib_node_index_t fib_entry_index = FIB_NODE_INDEX_INVALID; + u32 fib_index; + + fib_pfx.fp_proto = FIB_PROTOCOL_IP6; + fib_pfx.fp_len = ADDR_MGR_IP6_LEN; + + fib_index = fib_table_find (fib_pfx.fp_proto, 0); + + /* At this point the face exists in the face table */ + do + { + /* Check if the route already exist in the fib */ + fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 1, appif_addr->as_u8); + + fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx); + //fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PRIORITY_HI); + if (fib_entry_index != FIB_NODE_INDEX_INVALID) + { + fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 0, nh_addr->as_u8); + + fib_entry_index = + fib_table_lookup_exact_match (fib_index, &fib_pfx); + // fib_table_unlock (fib_index, fib_pfx.fp_proto, + // FIB_SOURCE_PRIORITY_HI); + } + if (fib_entry_index != FIB_NODE_INDEX_INVALID) + { + increment_v6_address (appif_addr, 2); + increment_v6_address (nh_addr, 2); + } + } + while (fib_entry_index != FIB_NODE_INDEX_INVALID); + + address_mgr_main.next_ip6_local_addr = *nh_addr; + increment_v6_address (&(address_mgr_main.next_ip6_local_addr), 1); +} + +ip4_address_t +get_ip4_address () +{ + ip4_address_t *prefix = &address_mgr_main.next_ip4_local_addr; + fib_prefix_t fib_pfx; + fib_node_index_t fib_entry_index = FIB_NODE_INDEX_INVALID; + u32 fib_index; + + fib_pfx.fp_proto = FIB_PROTOCOL_IP4; + fib_pfx.fp_len = ADDR_MGR_IP4_LEN; + /* At this point the face exists in the face table */ + do + { + /* Check if the route already exist in the fib */ + fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 0, prefix->as_u8); + fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto, + HICN_FIB_TABLE, + FIB_SOURCE_PRIORITY_HI); + fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx); + fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PRIORITY_HI); + increment_v4_address (prefix, 1); + } + while (fib_entry_index != FIB_NODE_INDEX_INVALID); + + return fib_pfx.fp_addr.ip4; +} + +ip6_address_t +get_ip6_address () +{ + ip6_address_t *prefix = &address_mgr_main.next_ip6_local_addr; + fib_prefix_t fib_pfx; + fib_node_index_t fib_entry_index = FIB_NODE_INDEX_INVALID; + u32 fib_index; + + fib_pfx.fp_proto = FIB_PROTOCOL_IP6; + fib_pfx.fp_len = ADDR_MGR_IP6_LEN; + /* At this point the face exists in the face table */ + do + { + /* Check if the route already exist in the fib */ + fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 1, prefix->as_u8); + fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto, + HICN_FIB_TABLE, + FIB_SOURCE_PRIORITY_HI); + fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx); + fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PRIORITY_HI); + increment_v6_address (prefix, 1); + } + while (fib_entry_index != FIB_NODE_INDEX_INVALID); + + return fib_pfx.fp_addr.ip6; +} + +void +address_mgr_init () +{ + + address_mgr_main.next_ip4_local_addr.as_u8[0] = 169; + address_mgr_main.next_ip4_local_addr.as_u8[1] = 254; + address_mgr_main.next_ip4_local_addr.as_u8[2] = 1; + address_mgr_main.next_ip4_local_addr.as_u8[3] = 1; + + ip6_address_set_zero (&address_mgr_main.next_ip6_local_addr); + address_mgr_main.next_ip6_local_addr.as_u16[0] = + clib_host_to_net_u16 (0xfc00); + address_mgr_main.next_ip6_local_addr.as_u8[15] = 1; +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/faces/app/address_mgr.h b/hicn-plugin/src/network/faces/app/address_mgr.h new file mode 100644 index 000000000..99450dcdd --- /dev/null +++ b/hicn-plugin/src/network/faces/app/address_mgr.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2019 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 _ADDRESS_MGR_H_ +#define _ADDRESS_MGR_H_ + +/** + * @file + * + * @brief Address manager. + * + * Address manager that maintains a pool of ip4 and ip6 addresses to assign to + * an interface. + */ + +#define ADDR_MGR_IP4_LEN 32 +#define ADDR_MGR_IP4_CONS_LEN 31 +#define ADDR_MGR_IP6_LEN 128 +#define ADDR_MGR_IP6_CONS_LEN 127 + +/** + * @brief Get two consecutive IP v4 addresses from the same /31 subnet + * + * @param addr1 first ip address with the least significant bit set to 0 + * @param addr2 second ip address with the least significant bit set to 1 + */ +void get_two_ip4_addresses (ip4_address_t * addr1, ip4_address_t * addr2); + +/** + * @brief Get two consecutive IP v6 addresses from the same /126 subnet + * + * @param addr1 first ip address with the least significant bit set to 0 + * @param addr2 second ip address with the least significant bit set to 1 + */ +void get_two_ip6_addresses (ip6_address_t * addr1, ip6_address_t * addr2); + +/** + * @brief Get one IP v4 address + * + * @return ip address + */ +ip4_address_t get_ip4_address (void); + +/** + * @brief Get one IP v6 address + * + * @return ip address + */ +ip6_address_t get_ip6_address (void); + +/** + * @brief Init the address manager + */ +void address_mgr_init (void); + +#endif /* _ADDRESS_MGR_ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/faces/app/face_app_cli.c b/hicn-plugin/src/network/faces/app/face_app_cli.c new file mode 100644 index 000000000..1aa27adc7 --- /dev/null +++ b/hicn-plugin/src/network/faces/app/face_app_cli.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2017-2020 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 "../face_dpo.h" +#include "../face.h" +#include "face_prod.h" +#include "face_cons.h" + +#define HICN_FACE_NONE 0 +#define HICN_FACE_DELETE 1 +#define HICN_FACE_ADD 2 + +static clib_error_t * +hicn_face_app_cli_set_command_fn (vlib_main_t * vm, + unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + vnet_main_t *vnm = vnet_get_main (); + fib_prefix_t prefix; + hicn_face_id_t face_id1 = HICN_FACE_NULL; + hicn_face_id_t face_id2 = HICN_FACE_NULL; + u32 cs_reserved = HICN_PARAM_FACE_DFT_CS_RESERVED; + int ret = HICN_ERROR_NONE; + int sw_if; + int face_op = HICN_FACE_NONE; + int prod = 0; + + + /* Get a line of input. */ + unformat_input_t _line_input, *line_input = &_line_input; + if (!unformat_user (main_input, unformat_line_input, line_input)) + { + return (0); + } + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "del")) + { + face_op = HICN_FACE_DELETE; + } + else if (face_op == HICN_FACE_DELETE + && unformat (line_input, "id %d", &face_id1)) + ; + else if (unformat (line_input, "add")) + { + face_op = HICN_FACE_ADD; + } + else if (face_op == HICN_FACE_ADD) + { + if (unformat (line_input, "intfc %U", + unformat_vnet_sw_interface, vnm, &sw_if)) + ; + else + if (unformat + (line_input, "prod prefix %U/%d", unformat_ip46_address, + &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) + { + prod = 1; + } + else if (prod && unformat (line_input, "cs_size %d", &cs_reserved)) + ; + else if (unformat (line_input, "cons")) + ; + else + { + return clib_error_return (0, "%s '%U'", + get_error_string + (HICN_ERROR_CLI_INVAL), + format_unformat_error, line_input); + } + } + else + { + return clib_error_return (0, "%s '%U'", + get_error_string (HICN_ERROR_CLI_INVAL), + format_unformat_error, line_input); + } + } + + if (face_id1 != HICN_FACE_NULL) + { + + if (!hicn_dpoi_idx_is_valid (face_id1)) + { + return clib_error_return (0, "%s, face_id1 %d not valid", + get_error_string (ret), face_id1); + } + } + + int rv; + switch (face_op) + { + case HICN_FACE_ADD: + { + ip46_address_t prod_addr; + ip4_address_t cons_addr4; + ip6_address_t cons_addr6; + + if (prod) + { + prefix.fp_proto = + ip46_address_is_ip4 (&prefix. + fp_addr) ? FIB_PROTOCOL_IP4 : + FIB_PROTOCOL_IP6; + rv = + hicn_face_prod_add (&prefix, sw_if, &cs_reserved, &prod_addr, + &face_id1); + if (rv == HICN_ERROR_NONE) + { + u8 *sbuf = NULL; + sbuf = + format (sbuf, "Face id: %d, producer address %U", face_id1, + format_ip46_address, &prod_addr, + 0 /*IP46_ANY_TYPE */ ); + vlib_cli_output (vm, "%s", sbuf); + } + else + { + return clib_error_return (0, get_error_string (rv)); + } + } + else + { + rv = + hicn_face_cons_add (&cons_addr4, &cons_addr6, sw_if, &face_id1, + &face_id2); + if (rv == HICN_ERROR_NONE) + { + u8 *sbuf = NULL; + sbuf = + format (sbuf, + "Face id: %d, address v4 %U, face id: %d address v6 %U", + face_id1, format_ip4_address, &cons_addr4, face_id2, + format_ip6_address, &cons_addr6); + vlib_cli_output (vm, "%s", sbuf); + } + else + { + return clib_error_return (0, get_error_string (rv)); + } + } + break; + } + case HICN_FACE_DELETE: + { + hicn_face_t *face = hicn_dpoi_get_from_idx (face_id1); + + if (face->flags & HICN_FACE_FLAGS_APPFACE_CONS) + rv = hicn_face_cons_del (face_id1); + else + rv = hicn_face_prod_del (face_id1); + if (rv == HICN_ERROR_NONE) + { + vlib_cli_output (vm, "Face %d deleted", face_id1); + } + else + { + return clib_error_return (0, get_error_string (rv)); + } + break; + } + default: + return clib_error_return (0, "Operation (%d) not implemented", face_op); + break; + } + return (rv == HICN_ERROR_NONE) ? 0 : clib_error_return (0, "%s\n", + get_error_string + (rv)); +} + +/* cli declaration for 'cfg face' */ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (hicn_face_app_cli_set_command, static) = +{ + .path = "hicn face app", + .short_help = "hicn face app {add intfc { prod prefix cs_size } {cons} | {del }", + .function = hicn_face_app_cli_set_command_fn, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/faces/app/face_cons.c b/hicn-plugin/src/network/faces/app/face_cons.c new file mode 100644 index 000000000..d44ba1a2b --- /dev/null +++ b/hicn-plugin/src/network/faces/app/face_cons.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2017-2020 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 "face_cons.h" +#include "address_mgr.h" +#include "../../infra.h" + +int +hicn_face_cons_add (ip4_address_t * nh_addr4, ip6_address_t * nh_addr6, + u32 swif, hicn_face_id_t * faceid1, + hicn_face_id_t * faceid2) +{ + /* Create the corresponding appif if */ + /* Retrieve a valid local ip address to assign to the appif */ + /* Set the ip address and create the face in the face db */ + + vlib_main_t *vm = vlib_get_main (); + vnet_main_t *vnm = vnet_get_main (); + + hicn_main_t *hm = &hicn_main; + + ip46_address_t if_ip; + ip46_address_reset (&if_ip); + nh_addr4->as_u32 = 0; + nh_addr6->as_u64[0] = 0; + nh_addr6->as_u64[1] = 0; + u32 if_flags = 0; + + if (!hm->is_enabled) + { + return HICN_ERROR_FWD_NOT_ENABLED; + } + if_flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP; + vnet_sw_interface_set_flags (vnm, swif, if_flags); + + get_two_ip4_addresses (&(if_ip.ip4), nh_addr4); + ip4_add_del_interface_address (vm, + swif, + &(if_ip.ip4), + ADDR_MGR_IP4_CONS_LEN, 0 /* is_del */ ); + + ip46_address_t nh_addr = to_ip46 (0, (u8 *) nh_addr4); + + index_t adj_index = adj_nbr_find(FIB_PROTOCOL_IP4, VNET_LINK_IP4, &nh_addr, swif); + + hicn_iface_add (&nh_addr, swif, faceid1, DPO_PROTO_IP4, adj_index); + + hicn_face_t *face = hicn_dpoi_get_from_idx (*faceid1); + face->flags |= HICN_FACE_FLAGS_APPFACE_CONS; + + get_two_ip6_addresses (&(if_ip.ip6), nh_addr6); + ip6_add_del_interface_address (vm, + swif, + &(if_ip.ip6), + ADDR_MGR_IP6_CONS_LEN, 0 /* is_del */ ); + + adj_index = adj_nbr_find(FIB_PROTOCOL_IP6, VNET_LINK_IP6, &nh_addr, swif); + + hicn_iface_add ((ip46_address_t *) nh_addr6, swif, faceid2, DPO_PROTO_IP6, adj_index); + + face = hicn_dpoi_get_from_idx (*faceid2); + face->flags |= HICN_FACE_FLAGS_APPFACE_CONS; + + return HICN_ERROR_NONE; +} + +int +hicn_face_cons_del (hicn_face_id_t face_id) +{ + if (!hicn_dpoi_idx_is_valid (face_id)) + return HICN_ERROR_APPFACE_NOT_FOUND; + + hicn_face_t *face = hicn_dpoi_get_from_idx (face_id); + + if (face->flags & HICN_FACE_FLAGS_APPFACE_CONS) + { + return hicn_face_del (face_id); + } + else + { + return HICN_ERROR_APPFACE_NOT_FOUND; + } +} + +u8 * +format_hicn_face_cons (u8 * s, va_list * args) +{ + CLIB_UNUSED (index_t index) = va_arg (*args, index_t); + CLIB_UNUSED (u32 indent) = va_arg (*args, u32); + + s = format (s, " (consumer face)"); + + return s; +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/faces/app/face_cons.h b/hicn-plugin/src/network/faces/app/face_cons.h new file mode 100644 index 000000000..5f8f5dde8 --- /dev/null +++ b/hicn-plugin/src/network/faces/app/face_cons.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2019 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 _FACE_CONSUMER_H_ +#define _FACE_CONSUMER_H_ + +#include +#include "../face.h" + +/** + * @file + * + * @brief Consumer application face. + * + * A consumer application face is built upon an ip face and identify a local + * consumer application (co-located with the forwarder) that acts as a + * consumer. The interface used by the consumer application face is + * assumed to be reserved only for hICN traffic (e.g., dedicated memif that + * connects the applictation to the forwarder). Only one application face can be + * assigned to an interface. + * + * In the vlib graph a consumer application face directly connect the + * device-input node to the hicn-vface-ip node. + */ + +/** + * @brief Add a new consumer application face + * + * The method creates the internal ip face and set the ip address to the interface. + * @param nh_addr4 ipv4 address to assign to interface used by the application to + * send interest to the consumer face + * @param nh_addr6 ipv6 address to assign to interface used by the application to + * send interest to the consumer face + * @param swif interface associated to the face + */ +int +hicn_face_cons_add (ip4_address_t * nh_addr4, ip6_address_t * nh_addr6, + u32 swif, hicn_face_id_t * faceid1, + hicn_face_id_t * faceid2); + +/** + * @brief Delete an existing consumer application face + * + * @param face_id Id of the consumer application face + */ +int hicn_face_cons_del (hicn_face_id_t face_id); + +/** + * @brief Format an application consumer face + * + * @param s Pointer to a previous string. If null it will be initialize + * @param args Array storing input values. Expected u32 face_id and u32 indent + * @return String with the formatted face + */ +u8 *format_hicn_face_cons (u8 * s, va_list * args); + + +#endif /* _FACE_CONSUMER_H_ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/faces/app/face_prod.c b/hicn-plugin/src/network/faces/app/face_prod.c new file mode 100644 index 000000000..645154325 --- /dev/null +++ b/hicn-plugin/src/network/faces/app/face_prod.c @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2017-2020 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 "face_prod.h" +#include "address_mgr.h" +#include "../../infra.h" +#include "../../route.h" +#include "../../cache_policies/cs_lru.h" + +hicn_face_prod_state_t *face_state_vec; + +/* used to check if an interface is already in the vector */ +u32 *face_state_pool; + +static int +hicn_app_state_create (u32 swif, fib_prefix_t * prefix) +{ + /* Make sure that the pool is not empty */ + pool_validate_index (face_state_pool, 0); + + u32 *swif_app; + u8 found = 0; + /* *INDENT-OFF* */ + pool_foreach (swif_app, face_state_pool,{ + if (*swif_app == swif) + { + found = 1; + } + } + ); + /* *INDENT-ON* */ + + + if (found) + return HICN_ERROR_APPFACE_ALREADY_ENABLED; + + + /* Create the appif and store in the vector */ + vec_validate (face_state_vec, swif); + clib_memcpy (&(face_state_vec[swif].prefix), prefix, sizeof (fib_prefix_t)); + + /* Set as busy the element in the vector */ + pool_get (face_state_pool, swif_app); + *swif_app = swif; + + int ret = HICN_ERROR_NONE; + if (ip46_address_is_ip4 (&(prefix->fp_addr))) + { + ret = + vnet_feature_enable_disable ("ip4-unicast", "hicn-face-prod-input", + swif, 1, 0, 0); + } + else + { + ret = + vnet_feature_enable_disable ("ip6-unicast", "hicn-face-prod-input", + swif, 1, 0, 0); + } + + return ret == 0 ? HICN_ERROR_NONE : HICN_ERROR_APPFACE_FEATURE; +} + +static int +hicn_app_state_del (u32 swif) +{ + /* Make sure that the pool is not empty */ + pool_validate_index (face_state_pool, 0); + + u32 *temp; + u32 *swif_app = NULL; + u8 found = 0; + fib_prefix_t *prefix; + /* *INDENT-OFF* */ + pool_foreach (temp, face_state_pool,{ + if (*temp == swif) + { + found = 1; + swif_app = temp; + } + } + ); + /* *INDENT-ON* */ + + if (!found) + return HICN_ERROR_APPFACE_NOT_FOUND; + + prefix = &(face_state_vec[swif].prefix); + + int ret = HICN_ERROR_NONE; + if (ip46_address_is_ip4 (&prefix->fp_addr)) + { + ret = + vnet_feature_enable_disable ("ip4-unicast", "hicn-face-prod-input", + swif, 0, 0, 0); + } + else + { + ret = + vnet_feature_enable_disable ("ip6-unicast", "hicn-face-prod-input", + swif, 0, 0, 0); + } + + pool_put (face_state_pool, swif_app); + memset (&face_state_vec[swif], 0, sizeof (hicn_face_prod_state_t)); + + return ret == 0 ? HICN_ERROR_NONE : HICN_ERROR_APPFACE_FEATURE; +} + +int +hicn_face_prod_add (fib_prefix_t * prefix, u32 sw_if, u32 * cs_reserved, + ip46_address_t * prod_addr, hicn_face_id_t * faceid) +{ + vlib_main_t *vm = vlib_get_main (); + vnet_main_t *vnm = vnet_get_main (); + + hicn_main_t *hm = &hicn_main; + + ip46_address_t local_app_ip; + CLIB_UNUSED(ip46_address_t remote_app_ip); + u32 if_flags = 0; + + if (!hm->is_enabled) + { + return HICN_ERROR_FWD_NOT_ENABLED; + } + + if (vnet_get_sw_interface_or_null (vnm, sw_if) == NULL) + { + return HICN_ERROR_FACE_HW_INT_NOT_FOUND; + } + + int ret = HICN_ERROR_NONE; + hicn_face_t *face = NULL; + + if_flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP; + vnet_sw_interface_set_flags (vnm, sw_if, if_flags); + + u8 *s0; + s0 = format (0, "Prefix %U", format_fib_prefix, prefix); + + vlib_cli_output (vm, "Received request for %s, swif %d\n", s0, sw_if); + + if (ip46_address_is_zero (&prefix->fp_addr)) + { + return HICN_ERROR_APPFACE_PROD_PREFIX_NULL; + } + + u8 isv6 = ip46_address_is_ip4(prod_addr); + index_t adj_index = adj_nbr_find(isv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4, isv6 ? VNET_LINK_IP6 : VNET_LINK_IP4, prod_addr, sw_if); + + /* + * Check if a producer face is already existing for the same prefix + * and sw_if + */ + face = hicn_face_get (&(prefix->fp_addr), sw_if, + &hicn_face_hashtb, adj_index); + + if (face != NULL) + { + if (!(face->flags & HICN_FACE_FLAGS_DELETED)) + return HICN_ERROR_FACE_ALREADY_CREATED; + + /* + * Something went worng, a consumer face exists for the + * producer's prefix. + */ + /* It should never happens, this is a safety check. */ + if (face->flags & HICN_FACE_FLAGS_APPFACE_CONS) + return HICN_ERROR_FACE_ALREADY_CREATED; + + /* If the face exists but is marked as deleted, undelete it */ + if (face->flags & HICN_FACE_FLAGS_DELETED) + { + /* + * remove the deleted flag and retrieve the face + * local addr + */ + face->flags &= HICN_FACE_FLAGS_DELETED; + } + } + else + { + /* Otherwise create the face */ + if (ip46_address_is_ip4 (&prefix->fp_addr)) + { + /* + * Otherwise retrieve an ip address to assign as a + * local ip addr. + */ + ip4_address_t local_app_ip4; + ip4_address_t remote_app_ip4; + get_two_ip4_addresses (&local_app_ip4, &remote_app_ip4); + ip4_add_del_interface_address (vm, + sw_if, + &local_app_ip4, 31, 0 /* is_del */ ); + local_app_ip = to_ip46 ( /* isv6 */ 0, local_app_ip4.as_u8); + remote_app_ip = to_ip46 ( /* isv6 */ 0, remote_app_ip4.as_u8); + + vnet_build_rewrite_for_sw_interface(vnm, sw_if, VNET_LINK_IP4, &remote_app_ip4); + } + else + { + ip6_address_t local_app_ip6; + ip6_address_t remote_app_ip6; + get_two_ip6_addresses (&local_app_ip6, &remote_app_ip6); + u8 *s0; + s0 = format (0, "%U", format_ip6_address, &local_app_ip6); + + vlib_cli_output (vm, "Setting ip address %s\n", s0); + + ip6_add_del_interface_address (vm, + sw_if, + &local_app_ip6, 127, + 0 /* is_del */ ); + local_app_ip = to_ip46 ( /* isv6 */ 1, local_app_ip6.as_u8); + remote_app_ip = to_ip46 ( /* isv6 */ 1, remote_app_ip6.as_u8); + } + } + + if (ret == HICN_ERROR_NONE) + // && hicn_face_prod_set_lru_max (*faceid, cs_reserved) == HICN_ERROR_NONE) + { + fib_route_path_t rpath = {0}; + fib_route_path_t * rpaths = NULL; + + 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; + + rpath.frp_weight = 1; + rpath.frp_sw_if_index = ~0; + rpath.frp_addr.ip4.as_u32 = remote_app_ip.ip4.as_u32; + rpath.frp_sw_if_index = sw_if; + rpath.frp_proto = DPO_PROTO_IP4; + + vec_add1 (rpaths, rpath); + } + 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; + + rpath.frp_weight = 1; + rpath.frp_sw_if_index = ~0; + rpath.frp_addr.ip6.as_u64[0] = remote_app_ip.ip6.as_u64[0]; + rpath.frp_addr.ip6.as_u64[1] = remote_app_ip.ip6.as_u64[1]; + rpath.frp_sw_if_index = sw_if; + rpath.frp_proto = DPO_PROTO_IP6; + + vec_add1 (rpaths, rpath); + } + + u32 fib_index = fib_table_find (prefix->fp_proto, 0); + fib_table_entry_path_add2 (fib_index, + prefix, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_NONE, rpaths); + + hicn_route_enable(prefix); + hicn_app_state_create (sw_if, prefix); + } + + adj_index = adj_nbr_find(isv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4, isv6 ? VNET_LINK_IP6 : VNET_LINK_IP4, prod_addr, sw_if); + face = hicn_face_get(&local_app_ip, sw_if, &hicn_face_hashtb, adj_index);//HICN_FACE_FLAGS_APPFACE_PROD); + + *faceid = hicn_dpoi_get_index (face); + + face->flags |= HICN_FACE_FLAGS_APPFACE_PROD; + + hicn_face_unlock_with_id(*faceid); + + *prod_addr = local_app_ip; + + /* Cleanup in case of something went wrong. */ + if (ret) + { + hicn_app_state_del (sw_if); + } + return ret; +} + +int +hicn_face_prod_del (hicn_face_id_t face_id) +{ + if (!hicn_dpoi_idx_is_valid (face_id)) + return HICN_ERROR_APPFACE_NOT_FOUND; + + hicn_face_t *face = hicn_dpoi_get_from_idx (face_id); + + if (face->flags & HICN_FACE_FLAGS_APPFACE_PROD) + { + /* Remove the face from the fib */ + hicn_route_disable(&(face_state_vec[face->sw_if].prefix)); + //hicn_route_del_nhop (&(face_state_vec[face->sw_if].prefix), + // face_id); + + //int ret = hicn_face_del (face_id); + return hicn_app_state_del (face->sw_if); + //ret == HICN_ERROR_NONE ? hicn_app_state_del (face->sw_if) : ret; + } + else + { + return HICN_ERROR_APPFACE_NOT_FOUND; + } + + return HICN_ERROR_NONE; +} + +u8 * +format_hicn_face_prod (u8 * s, va_list * args) +{ + CLIB_UNUSED (index_t index) = va_arg (*args, index_t); + CLIB_UNUSED (u32 indent) = va_arg (*args, u32); + + s = + format (s, " (producer)"); + + return s; +} + +/* *INDENT-OFF* */ +VNET_FEATURE_INIT(hicn_prod_app_input_ip6, static)= +{ + .arc_name = "ip6-unicast", + .node_name = "hicn-face-prod-input", + .runs_before = VNET_FEATURES("ip6-inacl"), +}; +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +VNET_FEATURE_INIT(hicn_prod_app_input_ip4, static)= +{ + .arc_name = "ip4-unicast", + .node_name = "hicn-face-prod-input", + .runs_before = VNET_FEATURES("ip4-inacl"), +}; +/* *INDENT-ON* */ + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/faces/app/face_prod.h b/hicn-plugin/src/network/faces/app/face_prod.h new file mode 100644 index 000000000..4cb2e3fbf --- /dev/null +++ b/hicn-plugin/src/network/faces/app/face_prod.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017-2020 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 _FACE_PRODUCER_H_ +#define _FACE_PRODUCER_H_ + +#include "../../cache_policies/cs_policy.h" +#include "../face.h" + +/** + * @file + * + * @brief Producer application face. + * + * A producer application face is built upon an ip face and identify a local + * producer application (co-located with the forwarder) that acts as a producer. In the + * current design an application face is either a face towards a consumer face + * or towards a producer. The interface used by the producer application face is + * assumed to be reserved only for hICN traffic (e.g., dedicated memif that + * connects the applictation to the forwarder). Only one application face can be + * assigned to an interface. + * + * To each producer application face it is assigned a portion of the CS. Every + * data arriving to a producer application will be stored in the portion of the + * CS assigned to the face. The eviction policy is defined in the + * face. Available eviction faces are list in the /cache_policy folder. + * + * In the vlib graph a producer application face is directly connected to the + * device-input node (with the node hicn-face-prod-input) and passes every packet to + * the hicn-face-ip node. + */ + +/** + * @brief Producer application face state that refer to the hICN producer socket + * created by the application. + * + */ +typedef struct +{ + fib_prefix_t prefix; +} hicn_face_prod_state_t; + +extern hicn_face_prod_state_t *face_state_vec; + +#define DEFAULT_PROBING_PORT 3784 + +/** + * @brief Add a new producer application face + * + * The method creates the internal ip face and the state specific to the + * producer application face. This method setups a route in the FIB for the + * producer's prefix. + * @param prefix hicn prefix name assigned to the producer face + * @param len length of the prefix + * @param swif interface associated to the face + * @param cs_reserved return the amount of cs assigned to the face + * @param prod_addr address to assign to interface used by the appliction to + * send data to the producer face + */ +int +hicn_face_prod_add (fib_prefix_t * prefix, u32 swif, u32 * cs_reserved, + ip46_address_t * prod_addr, hicn_face_id_t * faceid); + +/** + * @brief Delete an existing application face + * + * @param faceid id of the face to remove + */ +int hicn_face_prod_del (hicn_face_id_t faceid); + +/** + * @brief Set lru queue size for an app face + * + * @param face_id Id of the producer application face + */ +int hicn_face_prod_set_lru_max (hicn_face_id_t face_id, u32 * requested_size); + +/** + * @brief Format an application producer face + * + * @param s Pointer to a previous string. If null it will be initialize + * @param args Array storing input values. Expected u32 face_id and u32 indent + * @return String with the formatted face + */ +u8 *format_hicn_face_prod (u8 * s, va_list * args); + + +#endif /* _FACE_PROD_H_ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/faces/app/face_prod_node.c b/hicn-plugin/src/network/faces/app/face_prod_node.c new file mode 100644 index 000000000..e9b687a06 --- /dev/null +++ b/hicn-plugin/src/network/faces/app/face_prod_node.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2017-2020 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. + */ + +/** + * @file + * + * @brief Application interface node + * + * This node runs after the device-input node and perfoms some safety checks in + * order to avoid unespected interest and data (i.e., hICN packets whose name do + * not contain the prefix associated to the application face) + */ + +#include +#include + +#include + +#include "face_prod.h" +#include "../../mgmt.h" + +static __clib_unused char *face_prod_input_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +/* Node context data */ +typedef struct hicn_face_prod_runtime_s +{ + int id; +} hicn_face_prod_runtime_t; + +typedef struct +{ + u32 next_index; + u32 sw_if_index; +} hicn_face_prod_input_trace_t; + +typedef enum +{ + HICN_FACE_PROD_NEXT_DATA_IP4, + HICN_FACE_PROD_NEXT_DATA_IP6, + HICN_FACE_PROD_NEXT_ERROR_DROP, + HICN_FACE_PROD_N_NEXT, +} hicn_face_prod_next_t; + +vlib_node_registration_t hicn_face_prod_input_node; + +static __clib_unused u8 * +format_face_prod_input_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 *); + hicn_face_prod_input_trace_t *t = + va_arg (*args, hicn_face_prod_input_trace_t *); + CLIB_UNUSED (u32 indent) = format_get_indent (s); + + s = format (s, "prod-face: sw_if_index %d next-index %d", + t->sw_if_index, t->next_index); + return s; +} + +static_always_inline int +match_ip4_name (u32 * name, fib_prefix_t * prefix) +{ + u32 xor = 0; + + xor = *name & prefix->fp_addr.ip4.data_u32; + + return xor == prefix->fp_addr.ip4.data_u32; +} + +static_always_inline int +match_ip6_name (u8 * name, fib_prefix_t * prefix) +{ + union + { + u32x4 as_u32x4; + u64 as_u64[2]; + u32 as_u32[4]; + } xor_sum __attribute__ ((aligned (sizeof (u32x4)))); + + 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]; + + 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]); +} + +static_always_inline u32 +hicn_face_prod_next_from_data_hdr (vlib_node_runtime_t * node, + vlib_buffer_t * b, fib_prefix_t * prefix) +{ + u8 *ptr = vlib_buffer_get_current (b); + u8 v = *ptr & 0xf0; + int match_res = 1; + + if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr))) + { + match_res = match_ip4_name ((u32 *) & (ptr[12]), prefix); + } + else if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr))) + { + match_res = match_ip6_name (& (ptr[8]), prefix); + } + + return match_res ? HICN_FACE_PROD_NEXT_DATA_IP4 + (v == + 0x60) : + HICN_FACE_PROD_NEXT_ERROR_DROP; +} + +static_always_inline void +hicn_face_prod_trace_buffer (vlib_main_t * vm, vlib_node_runtime_t * node, + u32 swif, vlib_buffer_t * b, u32 next) +{ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_face_prod_input_trace_t *t = + vlib_add_trace (vm, node, b, sizeof (*t)); + t->next_index = next; + t->sw_if_index = swif; + } +} + +static uword +hicn_face_prod_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + 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 }; + + 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 >= 8 && n_left_to_next >= 4) + { + vlib_buffer_t *b0, *b1, *b2, *b3; + 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; + + { + 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); + } + + bi0 = from[0]; + bi1 = from[1]; + bi2 = from[2]; + bi3 = from[3]; + + from += 4; + n_left_from -= 4; + to_next[0] = bi0; + to_next[1] = bi1; + to_next[2] = bi2; + to_next[3] = bi3; + + to_next += 4; + n_left_to_next -= 4; + + b0 = vlib_get_buffer (vm, bi0); + b1 = vlib_get_buffer (vm, bi1); + b2 = vlib_get_buffer (vm, bi2); + b3 = vlib_get_buffer (vm, bi3); + + 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]]; + + 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); + stats.pkts_data_count += 4; + + /* trace */ + hicn_face_prod_trace_buffer (vm, node, + vnet_buffer (b0)->sw_if_index[VLIB_RX], + b0, next0); + hicn_face_prod_trace_buffer (vm, node, + vnet_buffer (b1)->sw_if_index[VLIB_RX], + b1, next1); + hicn_face_prod_trace_buffer (vm, node, + vnet_buffer (b2)->sw_if_index[VLIB_RX], + b2, next2); + hicn_face_prod_trace_buffer (vm, node, + vnet_buffer (b3)->sw_if_index[VLIB_RX], + b3, next3); + + /* enqueue */ + vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next, + n_left_to_next, bi0, bi1, bi2, bi3, + next0, next1, next2, next3); + + stats.pkts_processed += 4; + + } + + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *b0; + u32 bi0, swif; + hicn_face_prod_state_t *prod_face = NULL; + u32 next0; + + if (n_left_from > 1) + { + vlib_buffer_t *b1; + b1 = vlib_get_buffer (vm, from[1]); + CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, STORE); + } + + bi0 = from[0]; + from += 1; + n_left_from -= 1; + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + 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); + stats.pkts_data_count++; + + /* trace */ + hicn_face_prod_trace_buffer (vm, node, + vnet_buffer (b0)->sw_if_index[VLIB_RX], + b0, next0); + + /* enqueue */ + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, + n_left_to_next, bi0, next0); + + stats.pkts_processed += 1; + + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_PROCESSED, stats.pkts_processed); + vlib_node_increment_counter (vm, node->node_index, HICNFWD_ERROR_DATAS, + stats.pkts_data_count); + + return (frame->n_vectors); +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(hicn_face_prod_input_node) = +{ + .function = hicn_face_prod_input_node_fn, + .name = "hicn-face-prod-input", + .vector_size = sizeof(u32), + .format_trace = format_face_prod_input_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(face_prod_input_error_strings), + .error_strings = face_prod_input_error_strings, + .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_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/faces/face.c b/hicn-plugin/src/network/faces/face.c new file mode 100644 index 000000000..b495d18b0 --- /dev/null +++ b/hicn-plugin/src/network/faces/face.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2017-2020 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 "face.h" +#include "../hicn.h" +#include "../params.h" +#include "../error.h" +#include "../mapme.h" +#include "../mapme_eventmgr.h" + +dpo_id_t *face_dpo_vec; +hicn_face_vft_t *face_vft_vec; +char **face_type_names_vec; + +hicn_face_t *hicn_dpoi_face_pool; + +dpo_type_t first_type = DPO_FIRST; + +vlib_combined_counter_main_t *counters; + +dpo_type_t hicn_face_type; + +fib_node_type_t hicn_face_fib_node_type; + +const char *HICN_FACE_CTRX_STRING[] = { +#define _(a,b,c) c, + foreach_hicn_face_counter +#undef _ +}; + +u8 * +face_show (u8 * s, int face_id, u32 indent) +{ + s = format (s, "%U Faces:\n", format_white_space, indent); + indent += 4; + int i; + vec_foreach_index (i, face_dpo_vec) + { + s = + format (s, "%U", face_vft_vec[i].format_face, + face_dpo_vec[face_id].dpoi_index, indent); + } + + return (s); + +} + +mhash_t hicn_face_vec_hashtb; +mhash_t hicn_face_hashtb; + +hicn_face_vec_t *hicn_vec_pool; + +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, +}; + + +const static char *const *const hicn_face_nodes[DPO_PROTO_NUM] = { + [DPO_PROTO_IP4] = hicn_face4_nodes, + [DPO_PROTO_IP6] = hicn_face6_nodes +}; + +const static dpo_vft_t hicn_face_dpo_vft = { + .dv_lock = hicn_face_lock, + .dv_unlock = hicn_face_unlock, + .dv_format = format_hicn_face, +}; + +static fib_node_t * +hicn_face_node_get (fib_node_index_t index) +{ + hicn_face_t *face; + + face = hicn_dpoi_get_from_idx (index); + + return (&face->fib_node); +} + +static void +hicn_face_last_lock_gone (fib_node_t * node) +{ +} + +static hicn_face_t * +hicn_face_from_fib_node (fib_node_t * node) +{ + return ((hicn_face_t *) (((char *) node) - + STRUCT_OFFSET_OF (hicn_face_t, fib_node))); +} + +static fib_node_back_walk_rc_t +hicn_face_back_walk_notify (fib_node_t * node, fib_node_back_walk_ctx_t * ctx) +{ + + hicn_face_t *face = hicn_face_from_fib_node (node); + + const dpo_id_t *dpo_loadbalance = + fib_entry_contribute_ip_forwarding (face->fib_entry_index); + const load_balance_t *lb0 = load_balance_get (dpo_loadbalance->dpoi_index); + + const dpo_id_t *dpo = load_balance_get_bucket_i (lb0, 0); + + dpo_stack (hicn_face_type, face->dpo.dpoi_proto, &face->dpo, dpo); + /* if (dpo_is_adj(dpo)) */ + /* { */ + /* ip_adjacency_t * adj = adj_get (dpo->dpoi_index); */ + + /* if (dpo->dpoi_type == DPO_ADJACENCY_MIDCHAIN || */ + /* dpo->dpoi_type == DPO_ADJACENCY_MCAST_MIDCHAIN) */ + /* { */ + /* adj_nbr_midchain_stack(dpo->dpoi_index, &face->dpo); */ + /* } */ + /* else */ + /* { */ + /* dpo_stack(hicn_face_type, face->dpo.dpoi_proto, &face->dpo, dpo); */ + /* } */ + /* } */ + + return (FIB_NODE_BACK_WALK_CONTINUE); +} + +static void +hicn_face_show_memory (void) +{ +} + + +static const fib_node_vft_t hicn_face_fib_node_vft = { + .fnv_get = hicn_face_node_get, + .fnv_last_lock = hicn_face_last_lock_gone, + .fnv_back_walk = hicn_face_back_walk_notify, + .fnv_mem_show = hicn_face_show_memory, +}; + +// Make this more flexible for future types face +void +hicn_face_module_init (vlib_main_t * vm) +{ + pool_validate (hicn_dpoi_face_pool); + pool_alloc (hicn_dpoi_face_pool, 1024); + counters = + vec_new (vlib_combined_counter_main_t, + HICN_PARAM_FACES_MAX * HICN_N_COUNTER); + + mhash_init (&hicn_face_vec_hashtb, + sizeof (hicn_face_input_faces_t) /* value */ , + sizeof (hicn_face_key_t) /* key */ ); + mhash_init (&hicn_face_hashtb, sizeof (hicn_face_id_t) /* value */ , + sizeof (hicn_face_key_t) /* key */ ); + + pool_alloc (hicn_vec_pool, 100); + + /* + * How much useful is the following registration? + * So far it seems that we need it only for setting the dpo_type. + */ + hicn_face_type = + dpo_register_new_type (&hicn_face_dpo_vft, hicn_face_nodes); + + /* + * We register a new node type to get informed when the adjacency corresponding + * to a face is updated + */ + hicn_face_fib_node_type = + fib_node_register_new_type (&hicn_face_fib_node_vft); +} + +u8 * +format_hicn_face (u8 * s, va_list * args) +{ + index_t index = va_arg (*args, index_t); + u32 indent = va_arg (*args, u32); + hicn_face_t *face; + + face = hicn_dpoi_get_from_idx (index); + + if (face->flags & HICN_FACE_FLAGS_FACE) + { + hicn_face_id_t face_id = hicn_dpoi_get_index (face); + s = format (s, "%U Face %d: ", format_white_space, indent, face_id); + s = format (s, "nat address %U locks %u, path_label %u", + format_ip46_address, &face->nat_addr, IP46_TYPE_ANY, + face->locks, face->pl_id); + + if ((face->flags & HICN_FACE_FLAGS_APPFACE_PROD)) + s = format (s, " (producer)"); + else if ((face->flags & HICN_FACE_FLAGS_APPFACE_CONS)) + s = format (s, " (consumer)"); + + if ((face->flags & HICN_FACE_FLAGS_DELETED)) + s = format (s, " (deleted)"); + + s = format (s, "\n%U%U", + format_white_space, indent + 2, + format_dpo_id, &face->dpo, indent + 3); + } + else + { + hicn_face_id_t face_id = hicn_dpoi_get_index (face); + s = format (s, "%U iFace %d: ", format_white_space, indent, face_id); + s = format (s, "nat address %U locks %u, path_label %u", + format_ip46_address, &face->nat_addr, IP46_TYPE_ANY, + face->locks, face->pl_id); + + if ((face->flags & HICN_FACE_FLAGS_APPFACE_PROD)) + s = format (s, " (producer)"); + else if ((face->flags & HICN_FACE_FLAGS_APPFACE_CONS)) + s = format (s, " (consumer)"); + + if ((face->flags & HICN_FACE_FLAGS_DELETED)) + s = format (s, " (deleted)"); + } + + return s; +} + + +u8 * +format_hicn_face_all (u8 * s, int n, ...) +{ + va_list ap; + va_start (ap, n); + u32 indent = va_arg (ap, u32); + + s = format (s, "%U Faces:\n", format_white_space, indent); + + hicn_face_t *face; + + /* *INDENT-OFF* */ + pool_foreach ( face, hicn_dpoi_face_pool, + { + s = format(s, "%U\n", format_hicn_face, hicn_dpoi_get_index(face), indent); + }); + /* *INDENT-ON* */ + + return s; +} + +int +hicn_face_del (hicn_face_id_t face_id) +{ + hicn_face_t *face = hicn_dpoi_get_from_idx (face_id); + hicn_face_key_t key; + hicn_face_key_t old_key; + hicn_face_key_t old_key2; + + hicn_face_get_key (&(face->nat_addr), face->sw_if, &(face->dpo), &key); + hicn_face_input_faces_t *in_faces_vec = + hicn_face_get_vec (&(face->nat_addr), + &hicn_face_vec_hashtb); + if (in_faces_vec != NULL) + { + hicn_face_vec_t *vec = + pool_elt_at_index (hicn_vec_pool, in_faces_vec->vec_id); + u32 index_face = vec_search (*vec, face_id); + vec_del1 (*vec, index_face); + + if (vec_len (*vec) == 0) + { + pool_put_index (hicn_vec_pool, in_faces_vec->vec_id); + mhash_unset (&hicn_face_vec_hashtb, &key, (uword *) & old_key); + vec_free (*vec); + } + else + { + /* Check if the face we are deleting is the preferred one. */ + /* If so, repleace with another. */ + if (in_faces_vec->face_id == face_id) + { + in_faces_vec->face_id = (*vec)[0]; + } + } + + mhash_unset (&hicn_face_hashtb, &key, (uword *) & old_key2); + } + + int ret = HICN_ERROR_NONE; + + if (hicn_dpoi_idx_is_valid (face_id)) + { + hicn_face_t *face = hicn_dpoi_get_from_idx (face_id); + face->locks--; + if (face->locks == 0) + pool_put_index (hicn_dpoi_face_pool, face_id); + else + face->flags |= HICN_FACE_FLAGS_DELETED; + } + else + ret = HICN_ERROR_FACE_NOT_FOUND; + + + return ret; +} + +static void +hicn_iface_to_face (hicn_face_t * face, const dpo_id_t * dpo) +{ + dpo_stack (hicn_face_type, dpo->dpoi_proto, &face->dpo, dpo); + + face->flags &= ~HICN_FACE_FLAGS_IFACE; + face->flags |= HICN_FACE_FLAGS_FACE; + + if (dpo_is_adj (dpo)) + { + fib_node_init (&face->fib_node, hicn_face_fib_node_type); + fib_node_lock (&face->fib_node); + + if (dpo->dpoi_type != DPO_ADJACENCY_MIDCHAIN || + dpo->dpoi_type != DPO_ADJACENCY_MCAST_MIDCHAIN) + { + ip_adjacency_t *adj = adj_get (dpo->dpoi_index); + ip46_address_t *nh = &(adj->sub_type.nbr.next_hop); + fib_prefix_t prefix; + + if (!ip46_address_is_zero (nh)) + { + fib_prefix_from_ip46_addr (nh, &prefix); + + u32 fib_index = + fib_table_find (prefix.fp_proto, HICN_FIB_TABLE); + + face->fib_entry_index = fib_entry_track (fib_index, + &prefix, + hicn_face_fib_node_type, + hicn_dpoi_get_index + (face), + &face->fib_sibling); + } + } + } +} + +/* + * Utility that adds a new face cache entry. For the moment we assume that + * the ip_adjacency has already been set up. + */ +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_flags_t flags = (hicn_face_flags_t) 0; + flags |= HICN_FACE_FLAGS_FACE; + + hicn_face_t *face; + + face = + hicn_face_get_with_dpo (nat_address, sw_if, dpo_nh, &hicn_face_hashtb); + + if (face != NULL) + { + *pfaceid = hicn_dpoi_get_index (face); + return HICN_ERROR_FACE_ALREADY_CREATED; + } + + face = + hicn_face_get (nat_address, sw_if, &hicn_face_hashtb, dpo_nh->dpoi_index); + + dpo_id_t temp_dpo = DPO_INVALID; + temp_dpo.dpoi_index = dpo_nh->dpoi_index; + hicn_face_key_t key; + hicn_face_get_key (nat_address, sw_if, dpo_nh, &key); + + if (face == NULL) + { + + hicn_iface_add (nat_address, sw_if, pfaceid, dpo_nh->dpoi_proto, + dpo_nh->dpoi_index); + face = hicn_dpoi_get_from_idx (*pfaceid); + + mhash_set_mem (&hicn_face_hashtb, &key, (uword *) pfaceid, 0); + + hicn_face_get_key (nat_address, sw_if, &temp_dpo, &key); + mhash_set_mem (&hicn_face_hashtb, &key, (uword *) pfaceid, 0); + } + else + { + /* We found an iface and we convert it to a face */ + *pfaceid = hicn_dpoi_get_index (face); + mhash_set_mem (&hicn_face_hashtb, &key, (uword *) pfaceid, 0); + } + + hicn_iface_to_face (face, dpo_nh); + + temp_dpo.dpoi_index = ~0; + + hicn_face_input_faces_t *in_faces = + hicn_face_get_vec (nat_address, &hicn_face_vec_hashtb); + + if (in_faces == NULL) + { + hicn_face_input_faces_t in_faces_temp; + hicn_face_vec_t *vec; + pool_get (hicn_vec_pool, vec); + *vec = vec_new (hicn_face_id_t, 0); + u32 index = vec - hicn_vec_pool; + in_faces_temp.vec_id = index; + vec_add1 (*vec, *pfaceid); + + in_faces_temp.face_id = *pfaceid; + + hicn_face_get_key (nat_address, 0, &temp_dpo, &key); + + mhash_set_mem (&hicn_face_vec_hashtb, &key, + (uword *) & in_faces_temp, 0); + } + else + { + hicn_face_vec_t *vec = + pool_elt_at_index (hicn_vec_pool, in_faces->vec_id); + + /* */ + if (vec_search (*vec, *pfaceid) != ~0) + return HICN_ERROR_FACE_ALREADY_CREATED; + + vec_add1 (*vec, *pfaceid); + + hicn_iface_to_face (face, dpo_nh); + + hicn_face_get_key (nat_address, 0, &temp_dpo, &key); + + mhash_set_mem (&hicn_face_vec_hashtb, &key, (uword *) in_faces, 0); + + /* If the face is an application producer face, we set it as the preferred incoming face. */ + /* This is required to handle the CS separation, and the push api in a lightway */ + if (is_app_prod) + { + in_faces->face_id = *pfaceid; + } + } + + retx_t *retx = vlib_process_signal_event_data (vlib_get_main (), + hicn_mapme_eventmgr_process_node. + index, + HICN_MAPME_EVENT_FACE_ADD, 1, + sizeof (retx_t)); + + /* *INDENT-OFF* */ + *retx = (retx_t) { + .face_id = *pfaceid, + }; + /* *INDENT-ON* */ + + return HICN_ERROR_NONE; +} + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/faces/face.h b/hicn-plugin/src/network/faces/face.h new file mode 100644 index 000000000..84a36d239 --- /dev/null +++ b/hicn-plugin/src/network/faces/face.h @@ -0,0 +1,796 @@ +/* + * Copyright (c) 2017-2020 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_H__ +#define __HICN_FACE_H__ + +#include "hicn_buffer.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +typedef u8 hicn_face_flags_t; +typedef index_t hicn_face_id_t; + +/** + * @file face.h + * + * This file implements a general face type. The purpose of a face is to + * carry the needed information to forward interest and data packets to the + * next node in the network. There are two type of faces: complete faces (in short + * faces), and incomplete faces (in short ifaces). + * + * A face that does not contain the indication of the adjacency is an + * incomplete face (iface), otherwise it is considered to be complete. Ifaces are + * used to forward data back to the previous hICN hop from which we received an + * interest, while faces are used to forward interest packets to the next hicn node. + * Faces and ifaces are created at two different points in time. Faces are created + * when a route is added, while ifaces are created when an interest is received. + * In details, faces and ifaces carry the following information: + * - nat_addr: the ip address to perform src nat or dst nat on interest and data packets, respectively; + * - pl_id: the path label + * - locks: the number of entities using this face. When 0 the face can be deallocated + * - dpo: the dpo that identifies the next node in the vlib graph for processing the vlib + * buffer. The dpo contains the dpo.dpoi_next field that points to the next node + * in the vlib graph and the dpo.dpoi_index which is an index to adj used by the next node + * to perform the l2 rewrite. In case of ifaces, it is likely we don't know the + * adjacency when creting the face. In this case, the next node in the vlib graph + * will be the node that performs a lookup in the fib. Only in case of udp tunnels, + * which are bidirectional tunnel we know that the incoming tunnel is also the outgoing + * one, therefore in this case we store the tunnel in the dpo.dpoi_index fields. For + * all the other tunnels (which are most likely unidirectional), the source address of + * the interest will be used to retrieve the outgoing tunnel when sending the corresponding + * data back. + * - sw_if: the incoming interface of the interest + * - fib_node, fib_entry_index and fib_sibling are information used to be notified of + * changes in the adjacency pointed by the dpo. + * + * We maintain two hash tables to retrieve faces and ifaces. In particular one hash table which + * index faces and ifaces for nat_address, sw_if and dpo. This is used to retrieve existing faces + * or ifaces when an interest is received and when an new face is created. A second hash table that + * indexes vectors of faces for nat_address and sw_if. This is used to retrieve a list of possible + * incoming faces when a data is received. + */ + +/** + * @brief Structure representing a face. It containes the fields shared among + * all the types of faces as well it leaves some space for storing additional + * information specific to each type. + */ +typedef struct __attribute__ ((packed)) hicn_face_s +{ + /* Flags to idenfity if the face is incomplete (iface), complete (face) */ + /* And a network or application face (1B) */ + hicn_face_flags_t flags; + + /* Align the upcoming fields */ + u8 align; + + /* Path label (2B) */ + u16 pl_id; + + /* Number of dpo holding a reference to the dpoi (4B) */ + u32 locks; + + /* Dpo for the adjacency (8B) */ + union { + dpo_id_t dpo; + u64 align_dpo; + }; + + /* Local address of the interface sw_if */ + ip46_address_t nat_addr; + + /* local interface for the local ip address */ + u32 sw_if; + + fib_node_t fib_node; + + fib_node_index_t fib_entry_index; + + u32 fib_sibling; +} hicn_face_t; + +/* 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_NULL (hicn_face_id_t) ~0 + +#define HICN_FACE_FLAGS_APPFACE_PROD_BIT 2 +#define HICN_FACE_FLAGS_APPFACE_CONS_BIT 3 + +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"); + +STATIC_ASSERT ((HICN_FACE_FLAGS_APPFACE_PROD >> + HICN_FACE_FLAGS_APPFACE_PROD_BIT) == + HICN_BUFFER_FLAGS_FACE_IS_APP, + "hicn buffer app flag does not correspond to HICN_FACE_FLAGS_APPFACE_PROD"); + +STATIC_ASSERT ((HICN_FACE_FLAGS_APPFACE_CONS >> + HICN_FACE_FLAGS_APPFACE_CONS_BIT) == + HICN_BUFFER_FLAGS_FACE_IS_APP, + "hicn buffer app flag does not correspond to HICN_FACE_FLAGS_APPFACE_PROD"); + +/** + * @brief Definition of the virtual functin table for an hICN FACE DPO. + */ +typedef struct hicn_face_vft_s +{ + u8 *(*format_face) (u8 * s, va_list * args); + /**< Format an hICN face dpo*/ + int (*hicn_face_del) (hicn_face_id_t face_id); + void (*hicn_face_get_dpo) (hicn_face_t * face, dpo_id_t * dpo); +} hicn_face_vft_t; + +#define foreach_hicn_face_counter \ + _(INTEREST_RX, 0, "Interest rx") \ + _(INTEREST_TX, 1, "Interest tx") \ + _(DATA_RX, 2, "Data rx") \ + _(DATA_TX, 3, "Data tx") \ + +typedef enum +{ +#define _(a,b,c) HICN_FACE_COUNTERS_##a = (b), + foreach_hicn_face_counter +#undef _ + HICN_N_COUNTER +} hicn_face_counters_t; + +extern mhash_t hicn_face_hashtb; + +extern const char *HICN_FACE_CTRX_STRING[]; + +#define get_face_counter_string(ctrxno) (char *)(HICN_FACE_CTRX_STRING[ctrxno]) + + +/* Vector maintaining a dpo per face */ +extern dpo_id_t *face_dpo_vec; +extern hicn_face_vft_t *face_vft_vec; + +/* Vector holding the set of face names */ +extern char **face_type_names_vec; + +/* First face type registered in the sytem.*/ +extern dpo_type_t first_type; + +/* Per-face counters */ +extern vlib_combined_counter_main_t *counters; + +/** + * @brief Return the face id from the face object + * + * @param Pointer to the face state + * @return face id + */ +always_inline hicn_face_id_t +hicn_dpoi_get_index (hicn_face_t * face_dpoi) +{ + return face_dpoi - hicn_dpoi_face_pool; +} + +/** + * @brief Return the face object from the face id. + * This method is robust to invalid face id. + * + * @param dpoi_index Face identifier + * @return Pointer to the face or NULL + */ +always_inline hicn_face_t * +hicn_dpoi_get_from_idx_safe (hicn_face_id_t dpoi_index) +{ + if (!pool_is_free_index(hicn_dpoi_face_pool, dpoi_index)) + return (hicn_face_t *) pool_elt_at_index (hicn_dpoi_face_pool, dpoi_index); + else + return NULL; +} + +/** + * @brief Return the face from the face id. Face id must be valid. + * + * @param dpoi_index Face identifier + * @return Pointer to the face + */ +always_inline hicn_face_t * +hicn_dpoi_get_from_idx (hicn_face_id_t dpoi_index) +{ + return (hicn_face_t *) pool_elt_at_index (hicn_dpoi_face_pool, dpoi_index); +} + +/** + * @brief Return true if the face id belongs to an existing face + */ +always_inline int +hicn_dpoi_idx_is_valid (hicn_face_id_t face_id) +{ + return pool_len (hicn_dpoi_face_pool) > face_id + && !pool_is_free_index (hicn_dpoi_face_pool, face_id); +} + + +/** + * @brief Add a lock to the face dpo + * + * @param dpo Pointer to the face dpo + */ +always_inline void +hicn_face_lock_with_id (hicn_face_id_t face_id) +{ + hicn_face_t *face; + face = hicn_dpoi_get_from_idx (face_id); + face->locks++; +} + +/** + * @brief Remove a lock to the face dpo. Deallocate the face id locks == 0 + * + * @param dpo Pointer to the face dpo + */ +always_inline void +hicn_face_unlock_with_id (hicn_face_id_t face_id) +{ + hicn_face_t *face; + face = hicn_dpoi_get_from_idx (face_id); + face->locks--; +} + +/** + * @brief Add a lock to the face through its dpo + * + * @param dpo Pointer to the face dpo + */ +always_inline void +hicn_face_lock (dpo_id_t * dpo) +{ + hicn_face_lock_with_id(dpo->dpoi_index); +} + +/** + * @brief Remove a lock to the face through its dpo. Deallocate the face id locks == 0 + * + * @param dpo Pointer to the face dpo + */ +always_inline void +hicn_face_unlock (dpo_id_t * dpo) +{ + hicn_face_unlock_with_id (dpo->dpoi_index); +} + + +/** + * @brief Init the internal structures of the face module + * + * Must be called before processing any packet + */ +void hicn_face_module_init (vlib_main_t * vm); + +u8 * format_hicn_face (u8 * s, va_list * args); + + +/** + * @brief Format all the existing faces + * + * @param s Pointer to a previous string. If null it will be initialize + * @param n Number of input parameters + * @return String with the faces formatted + */ +u8 *format_hicn_face_all (u8 * s, int n, ...); + +/** + * @brief Delete a face + * + * @param face_id Id of the face to delete + * @return HICN_ERROR_FACE_NOT_FOUND if the face does not exist, otherwise + * HICN_ERROR_NONE + */ +int hicn_face_del (hicn_face_id_t face_id); + +/** + * @bried vector of faces used to collect faces having the same local address + * + */ +typedef hicn_face_id_t *hicn_face_vec_t; + +typedef struct hicn_input_faces_s_ +{ + /* Vector of all possible input faces */ + u32 vec_id; + + /* Preferred face. If an prod_app face is in the vector it will be the preferred one. */ + /* It's not possible to have multiple prod_app face in the same vector, they would have */ + /* the same local address. Every prod_app face is a point-to-point face between the forwarder */ + /* and the application. */ + hicn_face_id_t face_id; + +} hicn_face_input_faces_t; + +/** + * Pool containing the vector of possible incoming faces. + */ +extern hicn_face_vec_t *hicn_vec_pool; + +/** + * Hash tables that indexes a face by remote address. For fast lookup when an + * interest arrives. + */ +extern mhash_t hicn_face_vec_hashtb; + + +/** + * Key definition for the mhash table. An face is uniquely identified by ip + * address, the interface id and a dpo pointing to the next node in the vlib graph. + * The ip address can correspond to the remote ip address of the next hicn hop, + * or to the local address of the receiving interface. The former is used to + * retrieve the incoming face when an interest is received, the latter when + * the arring packet is a data. If the face is a regular face + * In case of iface, the following structure can be filled in different ways: + * - dpo equal to DPO_INVALID when the iface is a regular hICN iface + * - in case of udp_tunnel dpo = + * { + * .dpoi_index = tunnel_id, + * .dpoi_type = DPO_FIRST, //We don't need the type, we leave it invalid + * .dpoi_proto = DPO_PROTO_IP4 or DPO_PROTO_IP6, + * .dpoi_next_node = HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP or + * HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP or + * HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP or + * HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP + * } + */ +typedef struct __attribute__ ((packed)) hicn_face_key_s +{ + ip46_address_t addr; + union { + dpo_id_t dpo; + u64 align_dpo; + }; + u32 sw_if; +} hicn_face_key_t; + +/** + * @brief Create the key object for the mhash. Fill in the key object with the + * expected values. + * + * @param addr nat address of the face + * @param sw_if interface associated to the face + * @param key Pointer to an allocated hicn_face_ip_key_t object + */ +always_inline void +hicn_face_get_key (const ip46_address_t * addr, + u32 sw_if, const dpo_id_t * dpo, hicn_face_key_t * key) +{ + key->dpo = *dpo; + key->addr = *addr; + key->sw_if = sw_if; +} + +/** + * @brief Get the face obj from the nat address. Does not add any lock. + * + * @param addr Ip v4 address used to create the key for the hash table. + * @param sw_if Software interface id used to create the key for the hash table. + * @param hashtb Hash table (remote or local) where to perform the lookup. + * + * @result Pointer to the face. + */ +always_inline hicn_face_t * +hicn_face_get (const ip46_address_t * addr, u32 sw_if, mhash_t * hashtb, index_t adj_index) +{ + hicn_face_key_t key; + + dpo_id_t dpo = DPO_INVALID; + + dpo.dpoi_index = adj_index; + + hicn_face_get_key (addr, sw_if, &dpo, &key); + + hicn_face_id_t *dpoi_index = (hicn_face_id_t *) mhash_get (hashtb, + &key); + + if ( dpoi_index != NULL) + { + hicn_face_lock_with_id(*dpoi_index); + return hicn_dpoi_get_from_idx (*dpoi_index); + } + + return NULL; +} + +/** + * @brief Get the face obj from the nat address and the dpo. Does not add any lock. + * + * @param addr Ip v4 address used to create the key for the hash table. + * @param sw_if Software interface id used to create the key for the hash table. + * @param hashtb Hash table (remote or local) where to perform the lookup. + * + * @result Pointer to the face. + */ +always_inline hicn_face_t * +hicn_face_get_with_dpo (const ip46_address_t * addr, u32 sw_if, const dpo_id_t * dpo, mhash_t * hashtb) +{ + hicn_face_key_t key; + + hicn_face_get_key (addr, sw_if, dpo, &key); + + hicn_face_id_t *dpoi_index = (hicn_face_id_t *) mhash_get (hashtb, + &key); + + if ( dpoi_index != NULL) + { + hicn_face_lock_with_id(*dpoi_index); + return hicn_dpoi_get_from_idx (*dpoi_index); + } + + return NULL; +} + +/** + * @brief Get the vector of faces from the ip v4 address. Does not add any lock. + * + * @param addr Ip v4 address used to create the key for the hash table. + * @param sw_if Software interface id used to create the key for the hash table. + * @param hashtb Hash table (remote or local) where to perform the lookup. + * + * @result Pointer to the face. + */ +always_inline hicn_face_input_faces_t * +hicn_face_get_vec (const ip46_address_t * addr, + mhash_t * hashtb) +{ + hicn_face_key_t key; + + dpo_id_t dpo = DPO_INVALID; + + hicn_face_get_key (addr, 0, &dpo, &key); + return (hicn_face_input_faces_t *) mhash_get (hashtb, &key); +} + +/** + * @brief Create a new face ip. API for other modules (e.g., routing) + * + * @param dpo_nh dpo contained in the face that points to the next node in + * the vlib graph + * @param nat_addr nat ip v4 or v6 address of the face + * @param sw_if interface associated to the face + * @param pfaceid Pointer to return the face id + * @param is_app_prod if HICN_FACE_FLAGS_APPFACE_PROD the face is a local application face, all other values are ignored + * @return HICN_ERROR_FACE_NO_GLOBAL_IP if the face does not have a globally + * 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); + +/** + * @brief Create a new incomplete face ip. (Meant to be used by the data plane) + * + * @param local_addr Local ip v4 or v6 address of the face + * @param remote_addr Remote ip v4 or v6 address of the face + * @param sw_if interface associated to the face + * @param pfaceid Pointer to return the face id + * @return HICN_ERROR_FACE_NO_GLOBAL_IP if the face does not have a globally + * reachable ip address, otherwise HICN_ERROR_NONE + */ +always_inline void +hicn_iface_add (ip46_address_t * nat_address, int sw_if, + hicn_face_id_t * pfaceid, dpo_proto_t proto, + u32 adj_index) +{ + hicn_face_t *face; + pool_get (hicn_dpoi_face_pool, face); + + clib_memcpy (&(face->nat_addr), nat_address, + sizeof (ip46_address_t)); + face->sw_if = sw_if; + + face->dpo.dpoi_type = DPO_FIRST; + face->dpo.dpoi_proto = DPO_PROTO_NONE; + face->dpo.dpoi_index = adj_index; + face->dpo.dpoi_next_node = 0; + face->pl_id = (u16) 0; + face->flags = HICN_FACE_FLAGS_IFACE; + face->locks = 1; + + hicn_face_key_t key; + hicn_face_get_key (nat_address, sw_if, &face->dpo, &key); + *pfaceid = hicn_dpoi_get_index (face); + + mhash_set_mem (&hicn_face_hashtb, &key, (uword *) pfaceid, 0); + + for (int i = 0; i < HICN_N_COUNTER; i++) + { + vlib_validate_combined_counter (&counters[(*pfaceid) * HICN_N_COUNTER], + i); + vlib_zero_combined_counter (&counters[(*pfaceid) * HICN_N_COUNTER], i); + } +} + +/**** Helpers to manipulate faces and ifaces from the face/iface input nodes ****/ + +/** + * @brief Retrieve a vector of faces from the ip4 local address and returns its index. + * + * @param vec: Result of the lookup. If no face exists for the local address vec = NULL + * @param hicnb_flags: Flags that indicate whether the face is an application + * face or not + * @param local_addr: Ip v4 nat address of the face + * @param sw_if: software interface id of the face + * + * @result HICN_ERROR_FACE_NOT_FOUND if the face does not exist, otherwise HICN_ERROR_NONE. + */ +always_inline int +hicn_face_ip4_lock (hicn_face_id_t * face_id, + u32 * in_faces_vec_id, + u8 * hicnb_flags, + const ip4_address_t * nat_addr) +{ + ip46_address_t ip_address = {0}; + ip46_address_set_ip4(&ip_address, nat_addr); + hicn_face_input_faces_t *in_faces_vec = + hicn_face_get_vec (&ip_address, &hicn_face_vec_hashtb); + + if (PREDICT_FALSE (in_faces_vec == NULL)) + return HICN_ERROR_FACE_NOT_FOUND; + + *in_faces_vec_id = in_faces_vec->vec_id; + hicn_face_t *face = hicn_dpoi_get_from_idx (in_faces_vec->face_id); + + *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; + *hicnb_flags |= + (face->flags & HICN_FACE_FLAGS_APPFACE_PROD) >> + HICN_FACE_FLAGS_APPFACE_PROD_BIT; + + *face_id = in_faces_vec->face_id; + + return HICN_ERROR_NONE; +} + +/** + * @brief Retrieve a face from the ip6 local address and returns its dpo. This + * method adds a lock on the face state. + * + * @param dpo: Result of the lookup. If the face doesn't exist dpo = NULL + * @param hicnb_flags: Flags that indicate whether the face is an application + * face or not + * @param nat_addr: Ip v6 nat address of the face + * @param sw_if: software interface id of the face + * + * @result HICN_ERROR_FACE_NOT_FOUND if the face does not exist, otherwise HICN_ERROR_NONE. + */ +always_inline int +hicn_face_ip6_lock (hicn_face_id_t * face_id, + u32 * in_faces_vec_id, + u8 * hicnb_flags, + const ip6_address_t * nat_addr) +{ + hicn_face_input_faces_t *in_faces_vec = + hicn_face_get_vec ((ip46_address_t *)nat_addr, &hicn_face_vec_hashtb); + + if (PREDICT_FALSE (in_faces_vec == NULL)) + return HICN_ERROR_FACE_NOT_FOUND; + + *in_faces_vec_id = in_faces_vec->vec_id; + hicn_face_t *face = hicn_dpoi_get_from_idx (in_faces_vec->face_id); + + *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; + *hicnb_flags |= + (face->flags & HICN_FACE_FLAGS_APPFACE_PROD) >> + HICN_FACE_FLAGS_APPFACE_PROD_BIT; + + *face_id = in_faces_vec->face_id; + + return HICN_ERROR_NONE; +} + +/** + * @brief Call back to get the adj of the tunnel + */ +static adj_walk_rc_t +hicn4_iface_adj_walk_cb (adj_index_t ai, + void *ctx) +{ + + hicn_face_t *face = (hicn_face_t *)ctx; + + dpo_set(&face->dpo, DPO_ADJACENCY_MIDCHAIN, DPO_PROTO_IP4, ai); + adj_nbr_midchain_stack(ai, &face->dpo); + + return (ADJ_WALK_RC_CONTINUE); +} + +/** + * @brief Retrieve, or create if it doesn't exist, a face from the ip6 local + * address and returns its dpo. This method adds a lock on the face state. + * + * @param dpo: Result of the lookup + * @param hicnb_flags: Flags that indicate whether the face is an application + * face or not + * @param nat_addr: Ip v4 remote address of the face + * @param sw_if: software interface id of the face + * @param node_index: vlib edge index to use in the packet processing + */ +always_inline void +hicn_iface_ip4_add_and_lock (hicn_face_id_t * index, + u8 * hicnb_flags, + const ip4_address_t * nat_addr, + u32 sw_if, u32 adj_index, u32 node_index) +{ + /*All (complete) faces are indexed by remote addess as well */ + + ip46_address_t ip_address = {0}; + ip46_address_set_ip4(&ip_address, nat_addr); + + /* if the face exists, it adds a lock */ + hicn_face_t *face = + hicn_face_get (&ip_address, sw_if, &hicn_face_hashtb, adj_index); + + if (face == NULL) + { + hicn_face_id_t idx; + hicn_iface_add (&ip_address, sw_if, &idx, DPO_PROTO_IP4, adj_index); + + face = hicn_dpoi_get_from_idx(idx); + + face->dpo.dpoi_type = DPO_FIRST; + face->dpo.dpoi_proto = DPO_PROTO_IP4; + face->dpo.dpoi_index = adj_index; + face->dpo.dpoi_next_node = node_index; + + /* if (nat_addr->as_u32 == 0) */ + /* { */ + adj_nbr_walk(face->sw_if, + FIB_PROTOCOL_IP4, + hicn4_iface_adj_walk_cb, + face); + /* } */ + + *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; + + *index = idx; + return; + } + else + { + /* unlock the face. We don't take a lock on each interest we receive */ + hicn_face_id_t face_id = hicn_dpoi_get_index(face); + hicn_face_unlock_with_id(face_id); + } + + /* 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); +} + +/** + * @brief Call back to get the adj of the tunnel + */ +static adj_walk_rc_t +hicn6_iface_adj_walk_cb (adj_index_t ai, + void *ctx) +{ + + hicn_face_t *face = (hicn_face_t *)ctx; + + ip_adjacency_t *adj = adj_get(ai); + if ((adj->lookup_next_index == IP_LOOKUP_NEXT_MIDCHAIN) || + (adj->lookup_next_index == IP_LOOKUP_NEXT_MCAST_MIDCHAIN)) + { + dpo_set(&face->dpo, DPO_ADJACENCY_MIDCHAIN, adj->ia_nh_proto, ai); + adj_nbr_midchain_stack(ai, &face->dpo); + } + + return (ADJ_WALK_RC_CONTINUE); +} + + +/** + * @brief Retrieve, or create if it doesn't exist, a face from the ip6 local + * address and returns its dpo. This method adds a lock on the face state. + * + * @param dpo: Result of the lookup + * @param hicnb_flags: Flags that indicate whether the face is an application + * face or not + * @param nat_addr: Ip v6 remote address of the face + * @param sw_if: software interface id of the face + * @param node_index: vlib edge index to use in the packet processing + */ +always_inline void +hicn_iface_ip6_add_and_lock (hicn_face_id_t * index, + u8 * hicnb_flags, + const ip6_address_t * nat_addr, + u32 sw_if, u32 adj_index, u32 node_index) +{ + /*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_hashtb, adj_index); + + if (face == NULL) + { + hicn_face_id_t idx; + hicn_iface_add ((ip46_address_t *) nat_addr, sw_if, &idx, DPO_PROTO_IP6, adj_index); + + face = hicn_dpoi_get_from_idx(idx); + + face->dpo.dpoi_type = DPO_FIRST; + face->dpo.dpoi_proto = DPO_PROTO_IP6; + face->dpo.dpoi_index = adj_index; + face->dpo.dpoi_next_node = node_index; + + adj_nbr_walk(face->sw_if, + FIB_PROTOCOL_IP6, + hicn6_iface_adj_walk_cb, + face); + + *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT; + + *index = idx; + + return; + } + else + { + /* unlock the face. We don't take a lock on each interest we receive */ + hicn_face_id_t face_id = hicn_dpoi_get_index(face); + hicn_face_unlock_with_id(face_id); + } + + /* 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); +} + +#endif // __HICN_FACE_H__ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/faces/face_cli.c b/hicn-plugin/src/network/faces/face_cli.c new file mode 100644 index 000000000..e9e516cc6 --- /dev/null +++ b/hicn-plugin/src/network/faces/face_cli.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2017-2020 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 "face.h" +#include "../error.h" + +static clib_error_t * +hicn_face_cli_show_command_fn (vlib_main_t * vm, + unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + + hicn_face_id_t face_id = HICN_FACE_NULL; + char *face_type_name = NULL; + int found = ~0; + int deleted = 0; + u8 *n = 0; + u8 *s = 0; + vlib_counter_t v; + + /* Get a line of input. */ + unformat_input_t _line_input, *line_input = &_line_input; + if (unformat_user (main_input, unformat_line_input, line_input)) + { + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%u", &face_id)) + ; + else if (unformat (line_input, "type %s", &face_type_name)) + ; + else if (unformat (line_input, "deleted")) + deleted = 1; + else + { + return clib_error_return (0, "%s", + get_error_string + (HICN_ERROR_CLI_INVAL)); + } + } + + if (face_type_name != NULL) + { + int idx = 0; + vec_foreach_index (idx, face_type_names_vec) + { + if (!strcmp (face_type_names_vec[idx], face_type_name)) + found = idx; + } + if (found == ~0) + return (clib_error_return (0, "Face type unknown")); + } + + } + + if (face_id != HICN_FACE_NULL) + { + if (!hicn_dpoi_idx_is_valid (face_id)) + return clib_error_return (0, "%s", + get_error_string + (HICN_ERROR_FACE_NOT_FOUND)); + + hicn_face_t *face = hicn_dpoi_get_from_idx (face_id); + vlib_cli_output (vm, "%U\n", format_hicn_face, face_id, 0 /*indent */ ); + + u32 indent = 3; + + for (int i = 0; i < HICN_N_COUNTER; i++) + { + vlib_get_combined_counter (&counters + [hicn_dpoi_get_index (face) * + HICN_N_COUNTER], i, &v); + s = + format (s, "%U%s", format_white_space, indent, + HICN_FACE_CTRX_STRING[i]); + + if (n) + _vec_len (n) = 0; + n = format (n, "packets"); + s = + format (s, "%U%-16v%16Ld", format_white_space, + 30 - strlen (HICN_FACE_CTRX_STRING[i]), n, v.packets); + + _vec_len (n) = 0; + n = format (n, "bytes"); + s = format (s, "\n%U%-16v%16Ld\n", + format_white_space, indent + 30, n, v.bytes); + } + vlib_cli_output (vm, "%s\n", s); + } + else + { + if (found != ~0) + { + hicn_face_t *face; + /* *INDENT-OFF* */ + pool_foreach(face, hicn_dpoi_face_pool, + { + if (!((face->flags & HICN_FACE_FLAGS_DELETED) && !deleted)) + { + if (face->flags) + { + vlib_cli_output(vm, "%U\n", format_hicn_face, hicn_dpoi_get_index(face), 0); + u8 * s = 0; + u32 indent = 3; + + for (int i = 0; i < HICN_N_COUNTER; i++) + { + vlib_get_combined_counter (&counters[hicn_dpoi_get_index(face) * HICN_N_COUNTER], i, &v); + s = format (s, "%U%s",format_white_space, indent, HICN_FACE_CTRX_STRING[i]); + + if (n) + _vec_len (n) = 0; + n = format (n, "packets"); + s = format (s, "%U%-16v%16Ld", format_white_space, 30-strlen(HICN_FACE_CTRX_STRING[i]), n, v.packets); + + _vec_len (n) = 0; + n = format (n, "bytes"); + s = format (s, "\n%U%-16v%16Ld\n", + format_white_space, indent+30, n, v.bytes); + } + vlib_cli_output (vm, "%s\n", s); + } + } + }); + /* *INDENT-ON* */ + } + else + { + hicn_face_t *face; + /* *INDENT-OFF* */ + pool_foreach(face, hicn_dpoi_face_pool, + { + if (!((face->flags & HICN_FACE_FLAGS_DELETED) && !deleted)) + { + vlib_cli_output(vm, "%U\n", format_hicn_face, hicn_dpoi_get_index(face), 0); + u32 indent = 3; + u8 * s = 0; + + for (int i = 0; i < HICN_N_COUNTER; i++) + { + vlib_get_combined_counter (&counters[hicn_dpoi_get_index(face) * HICN_N_COUNTER], i, &v); + s = format (s, "%U%s",format_white_space, indent, HICN_FACE_CTRX_STRING[i]); + + if (n) + _vec_len (n) = 0; + n = format (n, "packets"); + s = format (s, "%U%-16v%16Ld", format_white_space, 30-strlen(HICN_FACE_CTRX_STRING[i]), n, v.packets); + + _vec_len (n) = 0; + n = format (n, "bytes"); + s = format (s, "\n%U%-16v%16Ld\n", + format_white_space, indent+30, n, v.bytes); + } + vlib_cli_output (vm, "%s\n", s); + } + }); + /* *INDENT-ON* */ + } + } + + return 0; +} + +/* cli declaration for 'show faces' */ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (hicn_face_cli_show_command, static) = +{ + .path = "hicn face show", + .short_help = "hicn face show []", + .function = hicn_face_cli_show_command_fn, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/faces/face_node.c b/hicn-plugin/src/network/faces/face_node.c new file mode 100644 index 000000000..e1fd81ca0 --- /dev/null +++ b/hicn-plugin/src/network/faces/face_node.c @@ -0,0 +1,940 @@ +/* + * Copyright (c) 2020 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 "face.h" +#include "face_node.h" +#include "../strategy_dpo_manager.h" +#include "face.h" +#include "../cache_policies/cs_lru.h" +#include "../infra.h" +#include "../hicn.h" + +/** + * @File + * + * Definition of the nodes for ip incomplete faces. + */ + +vlib_node_registration_t hicn4_face_input_node; +vlib_node_registration_t hicn4_face_output_node; +vlib_node_registration_t hicn6_face_input_node; +vlib_node_registration_t hicn6_face_output_node; + +#define ip_v4 4 +#define ip_v6 6 + +static char *hicn4_face_input_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +static char *hicn6_face_input_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + u8 packet_data[60]; +} +hicn4_face_input_trace_t; + +typedef enum +{ + HICN4_FACE_INPUT_NEXT_DATA, + HICN4_FACE_INPUT_NEXT_MAPME, + HICN4_FACE_INPUT_NEXT_ERROR_DROP, + HICN4_FACE_INPUT_N_NEXT, +} hicn4_face_input_next_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + u8 packet_data[60]; +} +hicn6_face_input_trace_t; + +typedef enum +{ + HICN6_FACE_INPUT_NEXT_DATA, + HICN6_FACE_INPUT_NEXT_MAPME, + HICN6_FACE_INPUT_NEXT_ERROR_DROP, + HICN6_FACE_INPUT_N_NEXT, +} hicn6_face_input_next_t; + +#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_ERROR_DROP_IP4 HICN4_FACE_INPUT_NEXT_ERROR_DROP +#define NEXT_ERROR_DROP_IP6 HICN6_FACE_INPUT_NEXT_ERROR_DROP + +#define IP_HEADER_4 ip4_header_t +#define IP_HEADER_6 ip6_header_t + +#define LOCK_DPO_FACE_IP4 hicn_face_ip4_lock +#define LOCK_DPO_FACE_IP6 hicn_face_ip6_lock + +#define TRACE_INPUT_PKT_IP4 hicn4_face_input_trace_t +#define TRACE_INPUT_PKT_IP6 hicn6_face_input_trace_t + +/* + * NOTE: Both hicn4_face_input_node_fn and hicn6_face_input_node_fn + * present a similar codebase. Macro are hard to debug, although the + * followind code is pretty straighforward and most of the complexity is in + * functions that can be easily debug. + */ +#define face_input_x1(ipv) \ + do{ \ + vlib_buffer_t *b0; \ + u32 bi0; \ + u32 next0 = NEXT_ERROR_DROP_IP##ipv; \ + IP_HEADER_##ipv * ip_hdr = NULL; \ + hicn_buffer_t * hicnb0; \ + 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, 2*CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES , LOAD); \ + } \ + /* Dequeue a packet buffer */ \ + bi0 = from[0]; \ + from += 1; \ + n_left_from -= 1; \ + to_next[0] = bi0; \ + to_next += 1; \ + n_left_to_next -= 1; \ + \ + b0 = vlib_get_buffer (vm, bi0); \ + hicnb0 = hicn_get_buffer(b0); \ + ip_hdr = (IP_HEADER_##ipv *) vlib_buffer_get_current(b0); \ + \ + u8 is_icmp = ip_hdr->protocol == IPPROTO_ICMPV##ipv; \ + \ + next0 = is_icmp*NEXT_MAPME_IP##ipv + \ + (1-is_icmp)*NEXT_DATA_IP##ipv; \ + \ + ret = LOCK_DPO_FACE_IP##ipv \ + (&(hicnb0->face_id), \ + &(hicnb0->in_faces_vec_id), \ + &hicnb0->flags, \ + &(ip_hdr->dst_address)); \ + \ + if ( PREDICT_FALSE(ret != HICN_ERROR_NONE) ) \ + next0 = NEXT_ERROR_DROP_IP##ipv; \ + else \ + { \ + 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; \ + } \ + \ + 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->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), \ + sizeof (t->packet_data)); \ + } \ + \ + \ + /* 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); \ + }while(0) + + +#define face_input_x2(ipv) \ + do{ \ + vlib_buffer_t *b0, *b1; \ + u32 bi0, bi1; \ + u32 next0 = NEXT_ERROR_DROP_IP##ipv; \ + u32 next1 = NEXT_ERROR_DROP_IP##ipv; \ + IP_HEADER_##ipv * ip_hdr0 = NULL; \ + IP_HEADER_##ipv * ip_hdr1 = NULL; \ + hicn_buffer_t * hicnb0; \ + hicn_buffer_t * hicnb1; \ + int ret0, ret1; \ + /* Prefetch for next iteration. */ \ + { \ + vlib_buffer_t *b2, *b3; \ + b2 = vlib_get_buffer (vm, from[2]); \ + b3 = vlib_get_buffer (vm, from[3]); \ + CLIB_PREFETCH (b2, 2*CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b3, 2*CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b2->data, CLIB_CACHE_LINE_BYTES , LOAD); \ + CLIB_PREFETCH (b3->data, CLIB_CACHE_LINE_BYTES , LOAD); \ + } \ + /* Dequeue a packet buffer */ \ + bi0 = from[0]; \ + bi1 = from[1]; \ + from += 2; \ + n_left_from -= 2; \ + to_next[0] = bi0; \ + to_next[1] = bi1; \ + to_next += 2; \ + n_left_to_next -= 2; \ + \ + b0 = vlib_get_buffer (vm, bi0); \ + b1 = vlib_get_buffer (vm, bi1); \ + hicnb0 = hicn_get_buffer(b0); \ + hicnb1 = hicn_get_buffer(b1); \ + 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; \ + \ + 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; \ + \ + \ + ret0 = LOCK_DPO_FACE_IP##ipv \ + (&(hicnb0->face_id), \ + &(hicnb0->in_faces_vec_id), \ + &hicnb0->flags, \ + &(ip_hdr0->dst_address)); \ + \ + ret1 = LOCK_DPO_FACE_IP##ipv \ + (&(hicnb1->face_id), \ + &(hicnb1->in_faces_vec_id), \ + &hicnb1->flags, \ + &(ip_hdr1->dst_address)); \ + \ + if ( PREDICT_FALSE(ret0 != HICN_ERROR_NONE) ) \ + next0 = NEXT_ERROR_DROP_IP##ipv; \ + else \ + { \ + 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; \ + } \ + \ + if ( PREDICT_FALSE(ret1 != HICN_ERROR_NONE) ) \ + next1 = NEXT_ERROR_DROP_IP##ipv; \ + else \ + { \ + 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, b1)); \ + stats.pkts_data_count += 1; \ + } \ + \ + 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->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), \ + sizeof (t->packet_data)); \ + } \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b1->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_INPUT_PKT_IP##ipv *t = \ + vlib_add_trace (vm, node, b1, sizeof (*t)); \ + t->pkt_type = HICN_PKT_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), \ + sizeof (t->packet_data)); \ + } \ + \ + \ + /* Verify speculative enqueue, 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(0) + + +static uword +hicn4_face_input_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, next_index; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + u32 thread_index = vm->thread_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); + + /* Dual loop, X2 */ + while (n_left_from >= 4 && n_left_to_next >= 2) + { + face_input_x2 (4); + } + + /* Dual loop, X1 */ + while (n_left_from > 0 && n_left_to_next > 0) + { + face_input_x1 (4); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_DATAS, stats.pkts_data_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn4_face_input_format_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 *); + hicn4_face_input_trace_t *t = + va_arg (*args, hicn4_face_input_trace_t *); + + s = format (s, "FACE_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)); + return (s); +} + + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(hicn4_face_input_node) = +{ + .function = hicn4_face_input_node_fn, + .name = "hicn4-face-input", + .vector_size = sizeof(u32), + .format_trace = hicn4_face_input_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(hicn4_face_input_error_strings), + .error_strings = hicn4_face_input_error_strings, + .n_next_nodes = HICN4_FACE_INPUT_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = + { + [HICN4_FACE_INPUT_NEXT_DATA] = "hicn-data-pcslookup", + [HICN4_FACE_INPUT_NEXT_MAPME] = "hicn-mapme-ack", + [HICN4_FACE_INPUT_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +/** + * @brief IPv6 face input node function + * @see hicn6_face_input_node_fn + */ +static uword +hicn6_face_input_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, next_index; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + u32 thread_index = vm->thread_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); + + /* Dual loop, X2 */ + while (n_left_from >= 4 && n_left_to_next >= 2) + { + face_input_x2 (6); + } + + /* Dual loop, X1 */ + while (n_left_from > 0 && n_left_to_next > 0) + { + face_input_x1 (6); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_DATAS, stats.pkts_data_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn6_face_input_format_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 *); + hicn6_face_input_trace_t *t = + va_arg (*args, hicn6_face_input_trace_t *); + + s = format (s, "FACE_IP6_INPUT: pkt: %d, sw_if_index %d, next index %d\n%U", + (int) t->pkt_type, t->sw_if_index, t->next_index, + format_ip6_header, t->packet_data, sizeof (t->packet_data)); + return (s); +} + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(hicn6_face_input_node) = +{ + .function = hicn6_face_input_node_fn, + .name = "hicn6-face-input", + .vector_size = sizeof(u32), + .format_trace = hicn6_face_input_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(hicn6_face_input_error_strings), + .error_strings = hicn6_face_input_error_strings, + .n_next_nodes = HICN6_FACE_INPUT_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = + { + [HICN6_FACE_INPUT_NEXT_DATA] = "hicn-data-pcslookup", + [HICN6_FACE_INPUT_NEXT_MAPME] = "hicn-mapme-ack", + [HICN6_FACE_INPUT_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +/**** FACE OUTPUT *****/ + +typedef enum +{ + HICN4_FACE_OUTPUT_NEXT_ECHO_REPLY, + HICN4_FACE_OUTPUT_NEXT_UDP4_ENCAP, + HICN4_FACE_OUTPUT_NEXT_UDP6_ENCAP, + HICN4_FACE_OUTPUT_N_NEXT, +} hicn4_face_output_next_t; + +typedef enum +{ + HICN6_FACE_OUTPUT_NEXT_ECHO_REPLY, + HICN6_FACE_OUTPUT_NEXT_UDP4_ENCAP, + HICN6_FACE_OUTPUT_NEXT_UDP6_ENCAP, + 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) +{ + + /* if ((face->flags & HICN_FACE_FLAGS_APPFACE_PROD) && hicn_face_match_probe(b0, face, next)) */ + /* return; */ + + hicn_header_t *hicn = vlib_buffer_get_current (b0); + + //hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data; + + ip46_address_t temp_addr; + ip46_address_reset (&temp_addr); + hicn_type_t type = hicn_get_buffer (b0)->type; + hicn_ops_vft[type.l1]->rewrite_interest (type, &hicn->protocol, + &face->nat_addr, &temp_addr); + + if (ip46_address_is_ip4(&face->nat_addr)) + b0->flags |= VNET_BUFFER_F_OFFLOAD_IP_CKSUM; + + b0->flags |= VNET_BUFFER_F_OFFLOAD_TCP_CKSUM; + + ASSERT(face->flags & HICN_FACE_FLAGS_FACE); + + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = face->dpo.dpoi_index; + *next = face->dpo.dpoi_next_node; +} + +static char *hicn4_face_output_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +static char *hicn6_face_output_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + u8 packet_data[60]; +} +hicn4_face_output_trace_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + u8 packet_data[60]; +} +hicn6_face_output_trace_t; + +#define TRACE_OUTPUT_PKT_IP4 hicn4_face_output_trace_t +#define TRACE_OUTPUT_PKT_IP6 hicn6_face_output_trace_t + +#define face_output_x1(ipv) \ + do { \ + vlib_buffer_t *b0; \ + u32 bi0; \ + u32 next0 = ~0; \ + hicn_face_t * face; \ + \ + /* 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, STORE); \ + CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES , STORE); \ + } \ + /* Dequeue a packet buffer */ \ + bi0 = from[0]; \ + from += 1; \ + n_left_from -= 1; \ + to_next[0] = bi0; \ + to_next += 1; \ + n_left_to_next -= 1; \ + \ + b0 = vlib_get_buffer (vm, bi0); \ + \ + hicn_face_id_t face_id = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; \ + face = \ + hicn_dpoi_get_from_idx (face_id); \ + \ + if (PREDICT_TRUE(face != NULL)) \ + { \ + hicn_face_rewrite_interest \ + (vm, b0, face, &next0); \ + stats.pkts_interest_count += 1; \ + vlib_increment_combined_counter ( \ + &counters[face_id * HICN_N_COUNTER], \ + thread_index, \ + HICN_FACE_COUNTERS_INTEREST_TX, \ + 1, \ + vlib_buffer_length_in_chain(vm, b0)); \ + } \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b0->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_OUTPUT_PKT_IP##ipv *t = \ + vlib_add_trace (vm, node, b0, sizeof (*t)); \ + t->pkt_type = HICN_PKT_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), \ + sizeof (t->packet_data)); \ + } \ + \ + \ + /* 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); \ + }while(0) + +#define face_output_x2(ipv) \ + do { \ + vlib_buffer_t *b0, *b1; \ + u32 bi0, bi1; \ + u32 next0 = ~0; \ + u32 next1 = ~0; \ + hicn_face_t *face0, *face1; \ + \ + /* Prefetch for next iteration. */ \ + { \ + vlib_buffer_t *b2, *b3; \ + b2 = vlib_get_buffer (vm, from[2]); \ + b3 = vlib_get_buffer (vm, from[3]); \ + CLIB_PREFETCH (b2, CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b3, CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b2->data, CLIB_CACHE_LINE_BYTES , STORE); \ + CLIB_PREFETCH (b3->data, CLIB_CACHE_LINE_BYTES , STORE); \ + } \ + /* Dequeue a packet buffer */ \ + bi0 = from[0]; \ + bi1 = from[1]; \ + from += 2; \ + n_left_from -= 2; \ + to_next[0] = bi0; \ + to_next[1] = bi1; \ + to_next += 2; \ + n_left_to_next -= 2; \ + \ + b0 = vlib_get_buffer (vm, bi0); \ + b1 = vlib_get_buffer (vm, bi1); \ + \ + hicn_face_id_t face_id0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; \ + hicn_face_id_t face_id1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX]; \ + face0 = \ + hicn_dpoi_get_from_idx (face_id0); \ + face1 = \ + hicn_dpoi_get_from_idx (face_id1); \ + \ + if (PREDICT_TRUE(face0 != NULL)) \ + { \ + hicn_face_rewrite_interest \ + (vm, b0, face0, &next0); \ + stats.pkts_interest_count += 1; \ + vlib_increment_combined_counter ( \ + &counters[face_id0 * HICN_N_COUNTER], \ + thread_index, \ + HICN_FACE_COUNTERS_INTEREST_TX, \ + 1, \ + vlib_buffer_length_in_chain(vm, b0)); \ + } \ + \ + if (PREDICT_TRUE(face1 != NULL)) \ + { \ + hicn_face_rewrite_interest \ + (vm, b1, face1, &next1); \ + stats.pkts_interest_count += 1; \ + vlib_increment_combined_counter ( \ + &counters[face_id1 * HICN_N_COUNTER], \ + thread_index, \ + HICN_FACE_COUNTERS_INTEREST_TX, \ + 1, \ + vlib_buffer_length_in_chain(vm, b1)); \ + } \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b0->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_OUTPUT_PKT_IP##ipv *t = \ + vlib_add_trace (vm, node, b0, sizeof (*t)); \ + t->pkt_type = HICN_PKT_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), \ + sizeof (t->packet_data)); \ + } \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b1->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_OUTPUT_PKT_IP##ipv *t = \ + vlib_add_trace (vm, node, b1, sizeof (*t)); \ + t->pkt_type = HICN_PKT_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), \ + sizeof (t->packet_data)); \ + } \ + \ + \ + /* Verify speculative enqueue, 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(0) + + +static uword +hicn4_face_output_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, 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; + 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); + + /* Dual loop, X2 */ + while (n_left_from >= 4 && n_left_to_next >= 2) + { + face_output_x2 (4); + } + + /* Dual loop, X1 */ + while (n_left_from > 0 && n_left_to_next > 0) + { + face_output_x1 (4); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_INTERESTS, + stats.pkts_interest_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn4_face_output_format_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 *); + hicn4_face_output_trace_t *t = + va_arg (*args, hicn4_face_output_trace_t *); + + s = + format (s, "FACE_IP4_OUTPUT: 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)); + return (s); +} + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(hicn4_face_output_node) = +{ + .function = hicn4_face_output_node_fn, + .name = "hicn4-face-output", + .vector_size = sizeof(u32), + .format_trace = hicn4_face_output_format_trace, + .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_ECHO_REPLY] = "hicn4-face-input", + [HICN4_FACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap", + [HICN4_FACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" + } +}; +/* *INDENT-ON* */ + + +static uword +hicn6_face_output_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, 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; + 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); + + /* Dual loop, X2 */ + while (n_left_from >= 4 && n_left_to_next >= 2) + { + face_output_x2 (6); + } + + /* Dual loop, X1 */ + while (n_left_from > 0 && n_left_to_next > 0) + { + face_output_x1 (6); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_INTERESTS, + stats.pkts_interest_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn6_face_output_format_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 *); + hicn6_face_output_trace_t *t = + va_arg (*args, hicn6_face_output_trace_t *); + + s = + format (s, "FACE_IP6_OUTPUT: pkt: %d, sw_if_index %d, next index %d\n%U", + (int) t->pkt_type, t->sw_if_index, t->next_index, + format_ip6_header, t->packet_data, sizeof (t->packet_data)); + return (s); +} + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(hicn6_face_output_node) = +{ + .function = hicn6_face_output_node_fn, + .name = "hicn6-face-output", + .vector_size = sizeof(u32), + .format_trace = hicn6_face_output_format_trace, + .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_ECHO_REPLY] = "hicn6-face-input", + [HICN6_FACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap", + [HICN6_FACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" + } +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/faces/face_node.h b/hicn-plugin/src/network/faces/face_node.h new file mode 100644 index 000000000..f5a8bf5ae --- /dev/null +++ b/hicn-plugin/src/network/faces/face_node.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020 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_NODE_H__ +#define __HICN_FACE_NODE_H__ + +#include +#include + +/** + * @file face_node.h + * + * Implements the input and output face nodes. Input face nodes + * process incoming data while output face nodes process outgoing + * interests packets. + * + * Input face nodes follow hicn-face-input nodes and their purpose + * is to retrieve the list of possible incoming faces for each the data packet. + * The following node to the input face nodes is the hicn-data-pcslookup. + * Output face nodes follow the strategy and the hicn-interest-hitpit nodes and + * they perform the src nat on each interest packet. The node following the + * output face nodes depends on the adjacency type. In case of ip, the following + * node is the ip-rewrite, in case of tunnels the next node is the one implementing + * the tunnel encapsulation (udp-encap, mpls, etc). + */ + +extern vlib_node_registration_t hicn4_face_input_node; +extern vlib_node_registration_t hicn4_face_output_node; +extern vlib_node_registration_t hicn6_face_input_node; +extern vlib_node_registration_t hicn6_face_output_node; + +#endif // __HICN_FACE_NODE_H__ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/faces/iface_node.c b/hicn-plugin/src/network/faces/iface_node.c new file mode 100644 index 000000000..433cf0b02 --- /dev/null +++ b/hicn-plugin/src/network/faces/iface_node.c @@ -0,0 +1,915 @@ +/* + * Copyright (c) 2020 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 "face.h" +#include "../strategy_dpo_manager.h" +#include "../hicn.h" +#include "../infra.h" +#include "../cache_policies/cs_lru.h" + +/** + * @File + * + * Definition of the nodes for ip incomplete faces. + */ + +vlib_node_registration_t hicn4_iface_input_node; +vlib_node_registration_t hicn4_iface_output_node; +vlib_node_registration_t hicn6_iface_input_node; +vlib_node_registration_t hicn6_iface_output_node; + +u32 data_fwd_iface_ip4_vlib_edge; +u32 data_fwd_iface_ip6_vlib_edge; + +static char *hicn4_iface_input_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +static char *hicn6_iface_input_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + u8 packet_data[60]; +} hicn4_iface_input_trace_t; + +typedef enum +{ + HICN4_IFACE_INPUT_NEXT_INTEREST, + HICN4_IFACE_INPUT_NEXT_MAPME, + HICN4_IFACE_INPUT_NEXT_ERROR_DROP, + HICN4_IFACE_INPUT_N_NEXT, +} hicn4_iface_input_next_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + u8 packet_data[60]; +} hicn6_iface_input_trace_t; + +typedef enum +{ + HICN6_IFACE_INPUT_NEXT_INTEREST, + HICN6_IFACE_INPUT_NEXT_MAPME, + HICN6_IFACE_INPUT_NEXT_ERROR_DROP, + HICN6_IFACE_INPUT_N_NEXT, +} hicn6_iface_input_next_t; + +#define NEXT_MAPME_IP4 HICN4_IFACE_INPUT_NEXT_MAPME +#define NEXT_MAPME_IP6 HICN6_IFACE_INPUT_NEXT_MAPME + +#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_IFACE_IP4 hicn_iface_ip4_add_and_lock +#define DPO_ADD_LOCK_IFACE_IP6 hicn_iface_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 + +#define TRACE_INPUT_PKT_IP4 hicn4_iface_input_trace_t +#define TRACE_INPUT_PKT_IP6 hicn6_iface_input_trace_t + +// NODE OUTPUT + +static char *hicn4_iface_output_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +static char *hicn6_iface_output_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + u8 packet_data[60]; +} hicn4_iface_output_trace_t; + +typedef enum +{ + HICN4_IFACE_OUTPUT_NEXT_LOOKUP, + HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP, + HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP, + HICN4_IFACE_OUTPUT_N_NEXT, +} hicn4_iface_output_next_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + u8 packet_data[60]; +} hicn6_iface_output_trace_t; + +typedef enum +{ + HICN6_IFACE_OUTPUT_NEXT_LOOKUP, + HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP, + HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP, + HICN6_IFACE_OUTPUT_N_NEXT, +} hicn6_iface_output_next_t; + +//#define ERROR_OUTPUT_IP4 HICN4_IFACE_OUTPUT_NEXT_ERROR_DROP +//#define ERROR_OUTPUT_IP6 HICN6_IFACE_OUTPUT_NEXT_ERROR_DROP + +#define NEXT_DATA_LOOKUP_IP4 HICN4_IFACE_OUTPUT_NEXT_LOOKUP +#define NEXT_DATA_LOOKUP_IP6 HICN6_IFACE_OUTPUT_NEXT_LOOKUP + +#define NEXT_UDP_ENCAP_IP4 HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP +#define NEXT_UDP_ENCAP_IP6 HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP + +#define HICN_REWRITE_DATA_IP4 hicn_rewrite_iface_data4 +#define HICN_REWRITE_DATA_IP6 hicn_rewrite_iface_data6 + +#define TRACE_OUTPUT_PKT_IP4 hicn4_iface_output_trace_t +#define TRACE_OUTPUT_PKT_IP6 hicn6_iface_output_trace_t + +// NODES IMPLEMENTATIONS + +#define iface_input_x1(ipv) \ + do { \ + vlib_buffer_t *b0; \ + u32 bi0, next0, next_iface0; \ + IP_HEADER_##ipv * ip_hdr = NULL; \ + hicn_buffer_t * hicnb0; \ + /* Prefetch for next iteration. */ \ + if (n_left_from > 1) \ + { \ + vlib_buffer_t *b1; \ + b1 = vlib_get_buffer (vm, from[1]); \ + CLIB_PREFETCH (b1, 2*CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES , LOAD); \ + } \ + /* Dequeue a packet buffer */ \ + bi0 = from[0]; \ + from += 1; \ + n_left_from -= 1; \ + to_next[0] = bi0; \ + to_next += 1; \ + n_left_to_next -= 1; \ + \ + b0 = vlib_get_buffer (vm, bi0); \ + 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; \ + \ + if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL) \ + next_iface0 = NEXT_UDP_ENCAP_IP4; \ + else if(hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) \ + next_iface0 = NEXT_UDP_ENCAP_IP6; \ + \ + DPO_ADD_LOCK_IFACE_IP##ipv \ + (&(hicnb0->face_id), \ + &hicnb0->flags, \ + &(ip_hdr->src_address), \ + vnet_buffer(b0)->sw_if_index[VLIB_RX], \ + 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->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), \ + sizeof (t->packet_data)); \ + \ + } \ + \ + vlib_increment_combined_counter ( \ + &counters[hicnb0->face_id \ + * HICN_N_COUNTER], thread_index, \ + HICN_FACE_COUNTERS_INTEREST_RX, \ + 1, \ + vlib_buffer_length_in_chain(vm, b0)); \ + \ + /* 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); \ + }while(0) + + +#define iface_input_x2(ipv) \ + do { \ + vlib_buffer_t *b0, *b1; \ + u32 bi0, bi1, next0, next1, next_iface0, next_iface1; \ + IP_HEADER_##ipv * ip_hdr0 = NULL; \ + IP_HEADER_##ipv * ip_hdr1 = NULL; \ + hicn_buffer_t *hicnb0, *hicnb1; \ + \ + /* Prefetch for next iteration. */ \ + vlib_buffer_t *b2, *b3; \ + b2 = vlib_get_buffer (vm, from[2]); \ + b3 = vlib_get_buffer (vm, from[3]); \ + CLIB_PREFETCH (b2, 2*CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b3, 2*CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b2->data, CLIB_CACHE_LINE_BYTES , LOAD); \ + CLIB_PREFETCH (b3->data, CLIB_CACHE_LINE_BYTES , LOAD); \ + \ + /* Dequeue a packet buffer */ \ + bi0 = from[0]; \ + bi1 = from[1]; \ + from += 2; \ + n_left_from -= 2; \ + to_next[0] = bi0; \ + to_next[1] = bi1; \ + to_next += 2; \ + n_left_to_next -= 2; \ + \ + b0 = vlib_get_buffer (vm, bi0); \ + b1 = vlib_get_buffer (vm, bi1); \ + hicnb0 = hicn_get_buffer(b0); \ + hicnb1 = hicn_get_buffer(b1); \ + ip_hdr0 = (IP_HEADER_##ipv *) vlib_buffer_get_current(b0); \ + ip_hdr1 = (IP_HEADER_##ipv *) vlib_buffer_get_current(b1); \ + \ + 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; \ + \ + if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL) \ + next_iface0 = NEXT_UDP_ENCAP_IP4; \ + else if(hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) \ + next_iface0 = NEXT_UDP_ENCAP_IP6; \ + \ + next_iface1 = NEXT_DATA_LOOKUP_IP##ipv; \ + \ + if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL) \ + next_iface1 = NEXT_UDP_ENCAP_IP4; \ + else if(hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) \ + next_iface1 = NEXT_UDP_ENCAP_IP6; \ + \ + DPO_ADD_LOCK_IFACE_IP##ipv \ + (&(hicnb0->face_id), \ + &hicnb0->flags, \ + &(ip_hdr0->src_address), \ + vnet_buffer(b0)->sw_if_index[VLIB_RX], \ + vnet_buffer(b0)->ip.adj_index[VLIB_RX], \ + next_iface0); \ + \ + DPO_ADD_LOCK_IFACE_IP##ipv \ + (&(hicnb1->face_id), \ + &hicnb1->flags, \ + &(ip_hdr1->src_address), \ + vnet_buffer(b1)->sw_if_index[VLIB_RX], \ + 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->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), \ + sizeof (t->packet_data)); \ + } \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b1->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_INPUT_PKT_IP##ipv *t = \ + vlib_add_trace (vm, node, b1, sizeof (*t)); \ + t->pkt_type = HICN_PKT_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), \ + sizeof (t->packet_data)); \ + } \ + \ + vlib_increment_combined_counter ( \ + &counters[hicnb0->face_id \ + * HICN_N_COUNTER], thread_index, \ + HICN_FACE_COUNTERS_INTEREST_RX, \ + 1, \ + vlib_buffer_length_in_chain(vm, b0)); \ + \ + vlib_increment_combined_counter ( \ + &counters[hicnb1->face_id \ + * HICN_N_COUNTER], thread_index, \ + HICN_FACE_COUNTERS_INTEREST_RX, \ + 1, \ + vlib_buffer_length_in_chain(vm, b1)); \ + \ + /* Verify speculative enqueue, 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(0) + +static uword +hicn4_iface_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, next_index; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + u32 thread_index = vm->thread_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); + + /* Dual loop, X2 */ + while (n_left_from >= 4 && n_left_to_next >= 2) + { + iface_input_x2 (4); + } + + /* Dual loop, X1 */ + while (n_left_from > 0 && n_left_to_next > 0) + { + iface_input_x1 (4); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_INTERESTS, + stats.pkts_interest_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn4_iface_input_format_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 *); + 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)); + return (s); +} + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn4_iface_input_node) = +{ + .function = hicn4_iface_input_node_fn, + .name = "hicn4-iface-input", + .vector_size = sizeof (u32), + .format_trace = hicn4_iface_input_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN (hicn4_iface_input_error_strings), + .error_strings = hicn4_iface_input_error_strings, + .n_next_nodes = HICN4_IFACE_INPUT_N_NEXT, + /* edit / add dispositions*/ + .next_nodes = + { + [HICN4_IFACE_INPUT_NEXT_INTEREST] = "hicn-interest-pcslookup", + [HICN4_IFACE_INPUT_NEXT_MAPME] = "hicn-mapme-ctrl", + [HICN4_IFACE_INPUT_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +static uword +hicn6_iface_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, next_index; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + u32 thread_index = vm->thread_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); + + /* Dual loop, X2 */ + while (n_left_from >= 4 && n_left_to_next >= 2) + { + iface_input_x2 (6); + } + + /* Dual loop, X1 */ + while (n_left_from > 0 && n_left_to_next > 0) + { + iface_input_x1 (6); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_INTERESTS, + stats.pkts_interest_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn6_iface_input_format_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 *); + hicn6_iface_input_trace_t *t = + va_arg (*args, hicn6_iface_input_trace_t *); + + s = + format (s, "IFACE_IP6_INPUT: pkt: %d, sw_if_index %d, next index %d\n%U", + (int) t->pkt_type, t->sw_if_index, t->next_index, + format_ip6_header, t->packet_data, sizeof (t->packet_data)); + return (s); +} + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn6_iface_input_node) = +{ + .function = hicn6_iface_input_node_fn, + .name = "hicn6-iface-input", + .vector_size = sizeof (u32), + .format_trace = hicn6_iface_input_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN (hicn6_iface_input_error_strings), + .error_strings = hicn6_iface_input_error_strings, + .n_next_nodes = HICN6_IFACE_INPUT_N_NEXT, + /* edit / add dispositions*/ + .next_nodes = + { + [HICN6_IFACE_INPUT_NEXT_INTEREST] = "hicn-interest-pcslookup", + [HICN6_IFACE_INPUT_NEXT_MAPME] = "hicn-mapme-ctrl", + [HICN6_IFACE_INPUT_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + + +/**** IFACE OUTPUT *****/ + +static inline void +hicn_rewrite_iface_data4 (vlib_main_t * vm, vlib_buffer_t * b0, + const hicn_face_t * iface, u32 * next) +{ + ip4_header_t *ip0; + + /* Get the pointer to the old ip and tcp header */ + ip0 = vlib_buffer_get_current (b0); + + /* Set up the ip6 header */ + /* IP4 lenght contains the size of the ip4 header too */ + u16 sval = (vlib_buffer_length_in_chain (vm, b0)); + ip0->length = clib_host_to_net_u16 (sval); + ip0->ttl = 254; // FIXME TTL + + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = iface->dpo.dpoi_index; + *next = iface->dpo.dpoi_next_node; + hicn_header_t *hicn = vlib_buffer_get_current (b0); + + ip46_address_t temp_addr; + ip46_address_reset (&temp_addr); + hicn_type_t type = hicn_get_buffer (b0)->type; + hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol, + &(iface->nat_addr), &(temp_addr), + iface->pl_id); +} + +static inline void +hicn_rewrite_iface_data6 (vlib_main_t * vm, vlib_buffer_t * b0, + const hicn_face_t * iface, u32 * next) +{ + ip6_header_t *ip0; + + /* Get the pointer to the old ip and tcp header */ + /* Copy the previous ip and tcp header to the new portion of memory */ + ip0 = vlib_buffer_get_current (b0); + + /* Set up the ip6 header */ + /* IP6 lenght does not include the size of the ip6 header */ + u16 sval = (vlib_buffer_length_in_chain (vm, b0) - (sizeof (ip6_header_t))); + ip0->payload_length = clib_host_to_net_u16 (sval); + ip0->hop_limit = HICN_IP6_HOP_LIMIT; + + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = iface->dpo.dpoi_index; + *next = iface->dpo.dpoi_next_node; + + hicn_header_t *hicn = vlib_buffer_get_current (b0); + + ip46_address_t temp_addr; + ip46_address_reset (&temp_addr); + hicn_type_t type = hicn_get_buffer (b0)->type; + hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol, + &(iface->nat_addr), &(temp_addr), + iface->pl_id); +} + +#define iface_output_x1(ipv) \ + do { \ + vlib_buffer_t *b0; \ + u32 bi0; \ + u32 next0 = next_index; \ + hicn_face_t * face; \ + \ + /* 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, STORE); \ + CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES , STORE); \ + } \ + /* Dequeue a packet buffer */ \ + bi0 = from[0]; \ + from += 1; \ + n_left_from -= 1; \ + to_next[0] = bi0; \ + to_next += 1; \ + n_left_to_next -= 1; \ + \ + b0 = vlib_get_buffer (vm, bi0); \ + \ + hicn_face_id_t face_id = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; \ + face = \ + hicn_dpoi_get_from_idx (face_id); \ + \ + if (PREDICT_TRUE(face != NULL)) \ + { \ + HICN_REWRITE_DATA_IP##ipv \ + (vm, b0, face, &next0); \ + stats.pkts_data_count += 1; \ + vlib_increment_combined_counter ( \ + &counters[face_id * HICN_N_COUNTER], \ + thread_index, \ + HICN_FACE_COUNTERS_DATA_TX, \ + 1, \ + vlib_buffer_length_in_chain(vm, b0));\ + } \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b0->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_OUTPUT_PKT_IP##ipv *t = \ + vlib_add_trace (vm, node, b0, sizeof (*t)); \ + t->pkt_type = HICN_PKT_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), \ + sizeof (t->packet_data)); \ + } \ + \ + \ + /* 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); \ + }while(0); \ + + +#define iface_output_x2(ipv) \ + do { \ + vlib_buffer_t *b0, *b1; \ + u32 bi0, bi1; \ + u32 next0 = next_index; \ + u32 next1 = next_index; \ + hicn_face_t *face0, *face1; \ + \ + /* Prefetch for next iteration. */ \ + { \ + vlib_buffer_t *b2, *b3; \ + b2 = vlib_get_buffer (vm, from[2]); \ + b3 = vlib_get_buffer (vm, from[3]); \ + CLIB_PREFETCH (b2, CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b3, CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b2->data, CLIB_CACHE_LINE_BYTES , STORE); \ + CLIB_PREFETCH (b3->data, CLIB_CACHE_LINE_BYTES , STORE); \ + } \ + \ + /* Dequeue a packet buffer */ \ + bi0 = from[0]; \ + bi1 = from[1]; \ + from += 2; \ + n_left_from -= 2; \ + to_next[0] = bi0; \ + to_next[1] = bi1; \ + to_next += 2; \ + n_left_to_next -= 2; \ + \ + b0 = vlib_get_buffer (vm, bi0); \ + b1 = vlib_get_buffer (vm, bi1); \ + \ + hicn_face_id_t face_id0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; \ + hicn_face_id_t face_id1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX]; \ + face0 = \ + hicn_dpoi_get_from_idx (face_id0); \ + face1 = \ + hicn_dpoi_get_from_idx (face_id1); \ + \ + if (PREDICT_TRUE(face0 != NULL)) \ + { \ + HICN_REWRITE_DATA_IP##ipv \ + (vm, b0, face0, &next0); \ + stats.pkts_data_count += 1; \ + vlib_increment_combined_counter ( \ + &counters[face_id0 * HICN_N_COUNTER], \ + thread_index, \ + HICN_FACE_COUNTERS_DATA_TX, \ + 1, \ + vlib_buffer_length_in_chain(vm, b0));\ + } \ + \ + if (PREDICT_TRUE(face1 != NULL)) \ + { \ + HICN_REWRITE_DATA_IP##ipv \ + (vm, b1, face1, &next1); \ + stats.pkts_data_count += 1; \ + vlib_increment_combined_counter ( \ + &counters[face_id1 * HICN_N_COUNTER], \ + thread_index, \ + HICN_FACE_COUNTERS_DATA_TX, \ + 1, \ + vlib_buffer_length_in_chain(vm, b1)); \ + } \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b0->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_OUTPUT_PKT_IP##ipv *t = \ + vlib_add_trace (vm, node, b0, sizeof (*t)); \ + t->pkt_type = HICN_PKT_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), \ + sizeof (t->packet_data)); \ + } \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b1->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_OUTPUT_PKT_IP##ipv *t = \ + vlib_add_trace (vm, node, b1, sizeof (*t)); \ + t->pkt_type = HICN_PKT_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), \ + sizeof (t->packet_data)); \ + } \ + \ + \ + /* Verify speculative enqueue, 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(0); \ + + + +static uword +hicn4_iface_output_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, 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; + 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) + { + iface_output_x2 (4); + } + + while (n_left_from > 0 && n_left_to_next > 0) + { + iface_output_x1 (4); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_DATAS, stats.pkts_data_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn4_iface_output_format_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 *); + hicn4_iface_output_trace_t *t = + va_arg (*args, hicn4_iface_output_trace_t *); + + s = + format (s, "IFACE_IP4_OUTPUT: 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)); + return (s); +} + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn4_iface_output_node) = +{ + .function = hicn4_iface_output_node_fn, + .name = "hicn4-iface-output", + .vector_size = sizeof (u32), + .format_trace = hicn4_iface_output_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN (hicn4_iface_output_error_strings), + .error_strings = hicn4_iface_output_error_strings, + .n_next_nodes = HICN4_IFACE_OUTPUT_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = + { + [HICN4_IFACE_OUTPUT_NEXT_LOOKUP] = "ip4-lookup", + [HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap", + [HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" + }, +}; +/* *INDENT-ON* */ + + +static uword +hicn6_iface_output_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, 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; + 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) + { + iface_output_x2 (6); + } + + while (n_left_from > 0 && n_left_to_next > 0) + { + iface_output_x1 (6); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_DATAS, stats.pkts_data_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn6_iface_output_format_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 *); + hicn6_iface_output_trace_t *t = + va_arg (*args, hicn6_iface_output_trace_t *); + + s = + format (s, "IFACE_IP6_OUTPUT: pkt: %d, sw_if_index %d, next index %d\n%U", + (int) t->pkt_type, t->sw_if_index, t->next_index, + format_ip6_header, t->packet_data, sizeof (t->packet_data)); + return (s); +} + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn6_iface_output_node) = +{ + .function = hicn6_iface_output_node_fn, + .name = "hicn6-iface-output", + .vector_size = sizeof (u32), + .format_trace = hicn6_iface_output_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN (hicn6_iface_output_error_strings), + .error_strings = hicn6_iface_output_error_strings, + .n_next_nodes = HICN6_IFACE_OUTPUT_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = + { + [HICN6_IFACE_OUTPUT_NEXT_LOOKUP] = "ip6-lookup", + [HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap", + [HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" + + }, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/faces/iface_node.h b/hicn-plugin/src/network/faces/iface_node.h new file mode 100644 index 000000000..1a7c4291b --- /dev/null +++ b/hicn-plugin/src/network/faces/iface_node.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020 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_IFACE_NODE_H__ +#define __HICN_IFACE_NODE_H__ + +#include +#include + +/** + * @file iface_node.h + * + * Implements the input and output iface nodes. Input iface nodes + * process incoming interests while output face nodes process outgoing + * data packets. + * + * Input iface nodes follow ip-lookup nodes and their purpose + * is to create (or retrieve if already existing) the list incoming face + * for each the interest packet. + * The following node to the input iface nodes is the hicn-interest-pcslookup. + * Output iface nodes follow the hicn-data-fwd and the hicn-interest-hitcs nodes and + * they perform the dst nat on each data packet. The node following the + * output face nodes depends on the adjacency type. In case of ip, the following + * node is the ip4/6-lookup, in case of tunnels the next node is the one implementing + * the tunnel encapsulation (udp-encap, mpls, etc). + */ + + +/** + * @brief Initialize the ip iface module + */ +void hicn_iface_init (vlib_main_t * vm); + +#endif // __HICN_IFACE_IP_NODE_H__ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/hashtb.c b/hicn-plugin/src/network/hashtb.c new file mode 100644 index 000000000..6deddbd84 --- /dev/null +++ b/hicn-plugin/src/network/hashtb.c @@ -0,0 +1,1017 @@ +/* + * Copyright (c) 2017-2019 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 + +#include "pcs.h" +#include "hashtb.h" +#include "parser.h" +#include "error.h" + +/* return dvd/dvr, rounded up (intended for integer values) */ +#define CEIL(dvd, dvr) \ + ({ \ + __typeof__ (dvd) _dvd = (dvd); \ + __typeof__ (dvr) _dvr = (dvr); \ + (_dvd + _dvr - 1)/_dvr; \ + }) + +#ifndef ALIGN8 +#define ALIGN8(p) (((p) + 0x7) & ~(0x7)) +#endif + +#ifndef ALIGNPTR8 +#define ALIGNPTR8(p) ((void *)(((u8 * )(p) + 0x7) & ~(0x7))) +#endif + +#ifndef ALIGN64 +#define ALIGN64(p) (((p) + 0x3f) & ~(0x3f)) +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + +/* + * Offset to aligned start of additional data (PIT/CS, FIB) embedded in each + * node. + */ +u32 ht_node_data_offset_aligned; + +/* Some support for posix vs vpp mem management */ +#define MEM_ALLOC(x) clib_mem_alloc_aligned((x), 8) +#define MEM_FREE(p) clib_mem_free((p)) + +/* + * Internal utilities + */ + +/* Allocate an overflow bucket */ +static hicn_hash_bucket_t * +alloc_overflow_bucket (hicn_hashtb_h h) +{ + hicn_hash_bucket_t *newbkt = NULL; + + if (h->ht_overflow_buckets_used < h->ht_overflow_bucket_count) + { + pool_get_aligned (h->ht_overflow_buckets, newbkt, 8); + + if (newbkt) + { + h->ht_overflow_buckets_used++; + } + } + return (newbkt); +} + +/* Free an overflow bucket; clear caller's pointer */ +static void +free_overflow_bucket (hicn_hashtb_h h, hicn_hash_bucket_t ** pb) +{ + hicn_hash_bucket_t *bkt = *pb; + + ASSERT (h->ht_overflow_buckets_used > 0); + + pool_put (h->ht_overflow_buckets, bkt); + h->ht_overflow_buckets_used--; + *pb = NULL; +} + +/* + * Init, allocate a new hashtable + */ +int +hicn_hashtb_alloc (hicn_hashtb_h * ph, u32 max_elems, size_t app_data_size) +{ + int ret = HICN_ERROR_NONE; + hicn_hashtb_h h = NULL; + u32 count; + u32 total_buckets; + size_t sz; + hicn_hash_node_t *nodep; + hicn_hash_bucket_t *bucket; + + if (ph == NULL) + { + ret = HICN_ERROR_HASHTB_INVAL; + goto done; + } + if (max_elems < HICN_HASHTB_MIN_ENTRIES || + max_elems > HICN_HASHTB_MAX_ENTRIES) + { + goto done; + } + /* Allocate and init main hashtable struct */ + h = MEM_ALLOC (sizeof (hicn_hashtb_t)); + if (h == NULL) + { + ret = HICN_ERROR_HASHTB_NOMEM; + goto done; + } + memset (h, 0, sizeof (hicn_hashtb_t)); + + /* Compute main table bucket (row) count and size, and allocate */ + + /* Consider the last entry as used for containing the overflow bucket */ + total_buckets = CEIL (max_elems, HICN_HASHTB_BUCKET_ENTRIES - 1); + count = ALIGN8 (CEIL (total_buckets, HICN_HASHTB_FILL_FACTOR)); + + h->ht_bucket_count = count; + + /* We _really_ expect to have buckets aligned on cache lines ... */ + sz = sizeof (hicn_hash_bucket_t); + assert (sz == ALIGN64 (sz)); + + h->ht_buckets = MEM_ALLOC (count * sz); + if (h->ht_buckets == NULL) + { + ret = HICN_ERROR_HASHTB_NOMEM; + goto done; + } + memset (h->ht_buckets, 0, count * sz); + + /* + * First time through, compute offset to aligned extra data start in + * each node struct it's crucial that both the node struct (that the + * base hashtable uses) and the extra data area (that's also probably + * a struct) are aligned. + */ + if (ht_node_data_offset_aligned == 0) + { + count = STRUCT_OFFSET_OF (hicn_hash_node_t, hn_data); + ht_node_data_offset_aligned = ALIGN8 (count); + } + //check app struct fits into space provided(HICN_HASH_NODE_APP_DATA_SIZE) + u32 ht_node_data_size; + ht_node_data_size = sizeof (hicn_hash_node_t) - ht_node_data_offset_aligned; + if (app_data_size > ht_node_data_size) + { + clib_error + ("hicn hashtable: fatal error: requested app data size(%u) > hashtb node's configured bytes available(%u), sizeof(hicn_shared_t)=%u, sizeof(hicn_pit_entry_t)=%u, sizeof(hicn_cs_entry_t)=%u", + app_data_size, ht_node_data_size, sizeof (hicn_pcs_shared_t), + sizeof (hicn_pit_entry_t), sizeof (hicn_cs_entry_t)); + } + /* + * Compute entry node count and size, allocate Allocate/'Hide' the + * zero-th node so can use zero as an 'empty' value + */ + pool_alloc_aligned (h->ht_nodes, max_elems, 8); + if (h->ht_nodes == NULL) + { + ret = HICN_ERROR_HASHTB_NOMEM; + goto done; + } + pool_get_aligned (h->ht_nodes, nodep, 8); + //alloc node 0 + nodep = nodep; /* Silence 'not used' warning */ + + h->ht_node_count = max_elems; + h->ht_nodes_used = 1; + + /* + * Compute overflow bucket count and size, allocate + */ + //count = ALIGN8(CEIL(max_elems, HICN_HASHTB_OVERFLOW_FRACTION)); + count = ALIGN8 (total_buckets - h->ht_bucket_count); + + pool_alloc_aligned (h->ht_overflow_buckets, count, 8); + if (h->ht_overflow_buckets == NULL) + { + ret = HICN_ERROR_HASHTB_NOMEM; + goto done; + } + /* 'Hide' the zero-th node so we can use zero as an 'empty' value */ + pool_get_aligned (h->ht_overflow_buckets, bucket, 8); + bucket = bucket; /* Silence 'not used' warning */ + + h->ht_overflow_bucket_count = count; + h->ht_overflow_buckets_used = 1; + +done: + + if (h) + { + if ((ret == HICN_ERROR_NONE) && ph) + { + *ph = h; + } + else + { + hicn_hashtb_free (&h); + } + } + return (ret); +} + +/* + * Free, de-allocate a hashtable + */ +int +hicn_hashtb_free (hicn_hashtb_h * ph) +{ + int ret = 0; + + if (ph) + { + if ((*ph)->ht_nodes) + { + pool_free ((*ph)->ht_nodes); + (*ph)->ht_nodes = 0; + } + if ((*ph)->ht_overflow_buckets) + { + pool_free ((*ph)->ht_overflow_buckets); + (*ph)->ht_overflow_buckets = 0; + } + if ((*ph)->ht_buckets) + { + MEM_FREE ((*ph)->ht_buckets); + (*ph)->ht_buckets = 0; + } + MEM_FREE (*ph); + + *ph = NULL; + } + return (ret); +} + + + +/* + * Basic api to lookup a specific hash+key tuple. This does the entire lookup + * operation, retrieving node structs and comparing keys, so it's not + * optimized for prefetching or high performance. + * + * Returns zero and mails back a node on success, errno otherwise. + */ +int +hicn_hashtb_lookup_node (hicn_hashtb_h h, const u8 * key, + u32 keylen, u64 hashval, u8 is_data, + u32 * node_id, index_t * dpo_ctx_id, u8 * vft_id, + u8 * is_cs, u8 * hash_entry_id, u32 * bucket_id, + u8 * bucket_is_overflow) +{ + return (hicn_hashtb_lookup_node_ex + (h, key, keylen, hashval, is_data, FALSE /* deleted nodes */ , + node_id, + dpo_ctx_id, vft_id, is_cs, hash_entry_id, bucket_id, + bucket_is_overflow)); +} + +/* + * Extended api to lookup a specific hash+key tuple. The implementation + * allows the caller to locate nodes that are marked for deletion, which is + * part of some hashtable applications, such as the FIB. + * + * This does the entire lookup operation, retrieving node structs and comparing + * keys, so it's not optimized for prefetching or high performance. + * + * Returns zero and mails back a node on success, errno otherwise. + */ +int +hicn_hashtb_lookup_node_ex (hicn_hashtb_h h, const u8 * key, + u32 keylen, u64 hashval, u8 is_data, + int include_deleted_p, u32 * node_id, + index_t * dpo_ctx_id, u8 * vft_id, u8 * is_cs, + u8 * hash_entry_id, u32 * bucket_id, + u8 * bucket_is_overflow) +{ + int i, ret = HICN_ERROR_HASHTB_HASH_NOT_FOUND; + int found_p = FALSE; + u32 bidx; + hicn_hash_bucket_t *bucket; + u32 current_bucket_id = ~0; + + /* + * Use some bits of the low half of the hash to locate a row/bucket + * in the table + */ + current_bucket_id = bidx = (hashval & (h->ht_bucket_count - 1)); + + bucket = h->ht_buckets + bidx; + + *bucket_is_overflow = 0; + /* Check the entries in the bucket for matching hash value */ + +loop_buckets: + + for (i = 0; i < HICN_HASHTB_BUCKET_ENTRIES && !found_p; i++) + { + /* + * If an entry is marked for deletion, ignore it unless the + * caller explicitly wants these nodes. + */ + if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_DELETED) + { + if (!include_deleted_p) + { + continue; + } + } + if (bucket->hb_entries[i].he_msb64 == hashval) + { + /* + * Found a candidate - must retrieve the actual node + * and check the key. + */ + *node_id = bucket->hb_entries[i].he_node; + *dpo_ctx_id = bucket->hb_entries[i].dpo_ctx_id; + *vft_id = bucket->hb_entries[i].vft_id; + *is_cs = + bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY; + *hash_entry_id = i; + *bucket_id = current_bucket_id; + /* + * If we are doing lookup for a data, do not take a + * lock in case of a hit with a CS entry + */ + if (!(is_data && *is_cs)) + { + bucket->hb_entries[i].locks++; + } + found_p = TRUE; + ret = HICN_ERROR_NONE; + goto done; + } + } + + /* + * Be prepared to continue to an overflow bucket if necessary. We + * only expect the last entry in a bucket to refer to an overflow + * bucket... + */ + i = HICN_HASHTB_BUCKET_ENTRIES - 1; + if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW) + { + current_bucket_id = bucket->hb_entries[i].he_node; + bucket = pool_elt_at_index (h->ht_overflow_buckets, + bucket->hb_entries[i].he_node); + *bucket_is_overflow = 1; + goto loop_buckets; + } +done: + + return (ret); +} + +/** + * This function allows to split the hash verification from the comparison of + * the entire key. Useful to exploit prefertching. + * return 1 if equals, 0 otherwise + */ +int +hicn_node_compare (const u8 * key, u32 keylen, hicn_hash_node_t * node) +{ + + int ret = 0; + + if (key && keylen == node->hn_keysize) + { + ret = (memcmp (key, node->hn_key.ks.key, keylen) == 0); + } + return ret; +} + +/* + * Utility to init a new entry in a hashtable bucket/row. We use this to add + * new a node+hash, and to clear out an entry during removal. + */ +void +hicn_hashtb_init_entry (hicn_hash_entry_t * entry, u32 nodeidx, + u64 hashval, u32 locks) +{ + entry->he_msb64 = hashval; + entry->he_node = nodeidx; + + /* Clear out some other fields in the entry */ + entry->he_flags = 0; + entry->locks = locks; + entry->vft_id = 0; + entry->dpo_ctx_id = 0; +} + +/* + * Insert a node into the hashtable. We expect the caller has a) computed the + * hash value to use, b) initialized the node with the hash and key info, and + * c) filled in its app-specific data portion of the node. + */ + +int +hicn_hashtb_insert (hicn_hashtb_h h, hicn_hash_node_t * node, + hicn_hash_entry_t ** hash_entry, u64 hash, + u32 * node_id, + index_t * dpo_ctx_id, u8 * vft_id, u8 * is_cs, + u8 * hash_entry_id, u32 * bucket_id, + u8 * bucket_is_overflow) +{ + int i, ret = HICN_ERROR_HASHTB_INVAL; + u32 bidx; + hicn_hash_bucket_t *bucket, *newbkt; + int use_seven; + u32 current_bucket_id = ~0; + int is_overflow = 0; + + *hash_entry = NULL; + + if (h == NULL) + { + goto done; + } + /* + * Use some bits of the low half of the hash to locate a row/bucket + * in the table + */ + current_bucket_id = bidx = (hash & (h->ht_bucket_count - 1)); + + bucket = h->ht_buckets + bidx; + + use_seven = (h->ht_flags & HICN_HASHTB_FLAG_USE_SEVEN); + + /* Locate a free entry slot in the bucket */ + +loop_buckets: + + for (i = 0; i < HICN_HASHTB_BUCKET_ENTRIES; i++) + { + + /* + * If an entry is marked for deletion, ignore it + */ + if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_DELETED) + { + continue; + } + /* + * Be sure that we are not inserting the same entry twice + */ + if (bucket->hb_entries[i].he_msb64 == hash) + { + /* + * We hit an existing pit entry. increase lock. + */ + + *node_id = bucket->hb_entries[i].he_node; + *dpo_ctx_id = bucket->hb_entries[i].dpo_ctx_id; + *vft_id = bucket->hb_entries[i].vft_id; + *is_cs = + bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY; + *hash_entry_id = i; + *bucket_id = current_bucket_id; + *hash_entry = &(bucket->hb_entries[i]); + /* + * If we are doing lookup for a data, do not take a + * lock in case of a hit with a CS entry + */ + if (!(*is_cs)) + bucket->hb_entries[i].locks++; + *bucket_is_overflow = is_overflow; + ret = HICN_ERROR_HASHTB_EXIST; + goto done; + } + if ((bucket->hb_entries[i].he_msb64 == 0LL) && + (bucket->hb_entries[i].he_node == 0)) + { + /* Found a candidate -- fill it in */ + + /* + * Special case if the application asked not to use + * the last entry in each bucket. + */ + if ((i != (HICN_HASHTB_BUCKET_ENTRIES - 1)) || use_seven) + { + hicn_hashtb_init_entry (&(bucket->hb_entries[i]), + NODE_IDX_FROM_NODE (node, h), hash, 0); + + *hash_entry = &(bucket->hb_entries[i]); + + node->bucket_id = current_bucket_id; + node->entry_idx = i; + (*hash_entry)->vft_id = *vft_id; + (*hash_entry)->dpo_ctx_id = *dpo_ctx_id; + if (is_overflow) + node->hn_flags |= HICN_HASH_NODE_OVERFLOW_BUCKET; + + ret = HICN_ERROR_NONE; + goto done; + } + } + } + /* + * Be prepared to continue to an overflow bucket if necessary, or to + * add a new overflow bucket. We only expect the last entry in a + * bucket to refer to an overflow bucket... + */ + i = HICN_HASHTB_BUCKET_ENTRIES - 1; + if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW) + { + /* Existing overflow bucket - re-start the search loop */ + current_bucket_id = bucket->hb_entries[i].he_node; + bucket = pool_elt_at_index (h->ht_overflow_buckets, current_bucket_id); + is_overflow = 1; + goto loop_buckets; + + } + else + { + /* + * Overflow - reached the end of a bucket without finding a + * free entry slot. Need to allocate an overflow bucket, and + * connect it to this bucket. + */ + newbkt = alloc_overflow_bucket (h); + if (newbkt == NULL) + { + ret = HICN_ERROR_HASHTB_NOMEM; + goto done; + } + /* + * We're touching some more bytes than we absolutely have to + * here, but ... that seems ok. + */ + memset (newbkt, 0, sizeof (hicn_hash_bucket_t)); + + if (use_seven) + { + /* + * Copy existing entry into new bucket - we really + * expect these to be properly aligned so they can be + * treated as int. + */ + memcpy (&(newbkt->hb_entries[0]), + &(bucket->hb_entries[i]), sizeof (hicn_hash_entry_t)); + + /* Update bucket id and entry_idx on the hash node */ + hicn_hash_node_t *node = + pool_elt_at_index (h->ht_nodes, newbkt->hb_entries[0].he_node); + node->bucket_id = (newbkt - h->ht_overflow_buckets); + node->entry_idx = 0; + node->hn_flags |= HICN_HASH_NODE_OVERFLOW_BUCKET; + + } + /* + * Connect original bucket to the index of the new overflow + * bucket + */ + bucket->hb_entries[i].he_flags |= HICN_HASH_ENTRY_FLAG_OVERFLOW; + bucket->hb_entries[i].he_node = (newbkt - h->ht_overflow_buckets); + + /* Add new entry to new overflow bucket */ + bucket = newbkt; + + /* + * Use entry [1] in the new bucket _if_ we just copied into + * entry [zero] above. + */ + if (use_seven) + { + + hicn_hashtb_init_entry (&(bucket->hb_entries[1]), + NODE_IDX_FROM_NODE (node, h), hash, 0); + *hash_entry = &(bucket->hb_entries[1]); + + node->bucket_id = (newbkt - h->ht_overflow_buckets); + node->entry_idx = 1; + node->hn_flags |= HICN_HASH_NODE_OVERFLOW_BUCKET; + (*hash_entry)->vft_id = *vft_id; + (*hash_entry)->dpo_ctx_id = *dpo_ctx_id; + } + else + { + + hicn_hashtb_init_entry (&(bucket->hb_entries[0]), + NODE_IDX_FROM_NODE (node, h), hash, 0); + *hash_entry = &(bucket->hb_entries[0]); + node->bucket_id = (newbkt - h->ht_overflow_buckets); + node->entry_idx = 0; + node->hn_flags |= HICN_HASH_NODE_OVERFLOW_BUCKET; + (*hash_entry)->vft_id = *vft_id; + (*hash_entry)->dpo_ctx_id = *dpo_ctx_id; + } + } + + /* And we're done with the overflow bucket */ + ret = HICN_ERROR_NONE; + +done: + + return (ret); +} + +/* + * Delete a node from a hashtable using the node itself, and delete/free the + * node. Caller's pointer is cleared on success. + */ +void +hicn_hashtb_delete (hicn_hashtb_h h, hicn_hash_node_t ** pnode, u64 hashval) +{ + + hicn_hashtb_remove_node (h, *pnode, hashval); + hicn_hashtb_free_node (h, *pnode); + *pnode = NULL; + +} + +/* + * Delete an entry from a hashtable using the node itself. If the node was + * stored in an overflow bucket, and the bucket is empty after freeing the + * node, the bucket is freed as well. + */ +void +hicn_hashtb_remove_node (hicn_hashtb_h h, hicn_hash_node_t * node, + u64 hashval) +{ + int i, count; + u32 bidx, overflow_p; + hicn_hash_bucket_t *bucket, *parent; + + if ((h == NULL) || (node == NULL)) + { + goto done; + } + if (node->hn_flags & HICN_HASH_NODE_OVERFLOW_BUCKET) + bucket = pool_elt_at_index (h->ht_overflow_buckets, node->bucket_id); + else + { + /* + * Use some bits of the low half of the hash to locate a + * row/bucket in the table + */ + bidx = (hashval & (h->ht_bucket_count - 1)); + ASSERT (bidx == node->bucket_id); + bucket = h->ht_buckets + node->bucket_id; + } + + overflow_p = node->hn_flags & HICN_HASH_NODE_OVERFLOW_BUCKET; + + /* Clear out the entry. */ + hicn_hashtb_init_entry (&(bucket->hb_entries[node->entry_idx]), 0, 0LL, 0); + + if (!overflow_p) + { + /* + * And we're done, in the easy case where we didn't change an + * overflow bucket + */ + goto done; + } + /* + * The special case: if this is the last remaining entry in an + * overflow bucket, liberate the bucket. That in turn has a special + * case if this bucket is in the middle of a chain of overflow + * buckets. + * + * Note that we're not trying aggressively (yet) to condense buckets at + * every possible opportunity. + */ + + /* + * Reset this flag; we'll set it again if this bucket links to + * another + */ + overflow_p = FALSE; + + for (i = 0, count = 0; i < HICN_HASHTB_BUCKET_ENTRIES; i++) + { + if (bucket->hb_entries[i].he_node != 0) + { + count++; + } + if (i == (HICN_HASHTB_BUCKET_ENTRIES - 1) && + (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW)) + { + count--; /* Doesn't count as a 'real' entry */ + overflow_p = TRUE; + } + } + + if (count > 0) + { + /* Still a (real) entry in the row */ + goto done; + } + /* + * Need to locate the predecessor of 'bucket': start at the beginning + * of the chain of buckets and move forward + */ + bidx = (hashval & (h->ht_bucket_count - 1)); + + for (parent = h->ht_buckets + bidx; parent != NULL;) + { + + if ((parent->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)].he_flags & + HICN_HASH_ENTRY_FLAG_OVERFLOW) == 0) + { + parent = NULL; + break; + } + bidx = parent->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)].he_node; + + if (pool_elt_at_index (h->ht_overflow_buckets, bidx) == bucket) + { + /* + * Found the predecessor of 'bucket'. If 'bucket' has + * a successor, connect 'parent' to it, and take + * 'bucket out of the middle. + */ + if (overflow_p) + { + parent->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)].he_node = + bucket->hb_entries[(HICN_HASHTB_BUCKET_ENTRIES - 1)].he_node; + } + else + { + /* + * Just clear the predecessor entry pointing + * at 'bucket' + */ + hicn_hashtb_init_entry (&parent->hb_entries + [(HICN_HASHTB_BUCKET_ENTRIES - 1)], 0, + 0LL, 0); + } + + break; + } + /* + * After the first iteration, 'parent' will be an overflow + * bucket too + */ + parent = pool_elt_at_index (h->ht_overflow_buckets, bidx); + } + + /* We really expect to have found the predecessor */ + ASSERT (parent != NULL); + + /* And now, finally, we can put 'bucket' back on the free list */ + free_overflow_bucket (h, &bucket); + +done: + return; +} + +/* + * Prepare a hashtable node, supplying the key, and computed hash info. + */ +void +hicn_hashtb_init_node (hicn_hashtb_h h, hicn_hash_node_t * node, + const u8 * key, u32 keylen) +{ + assert (h != NULL); + assert (node != NULL); + assert (keylen <= HICN_PARAM_HICN_NAME_LEN_MAX); + + /* Init the node struct */ + node->hn_flags = HICN_HASH_NODE_FLAGS_DEFAULT; + node->hn_keysize = 0; + node->hn_keysize = keylen; + memcpy (node->hn_key.ks.key, key, keylen); + node->bucket_id = ~0; + node->entry_idx = ~0; +} + +/* + * Release a hashtable node back to the free list when an entry is cleared + */ +void +hicn_hashtb_free_node (hicn_hashtb_h h, hicn_hash_node_t * node) +{ + ASSERT (h->ht_nodes_used > 0); + + /* Return 'node' to the free list */ + pool_put (h->ht_nodes, node); + h->ht_nodes_used--; + +} + +/* + * Walk a hashtable, iterating through the nodes, keeping context in 'ctx'. + */ +int +hicn_hashtb_next_node (hicn_hashtb_h h, hicn_hash_node_t ** pnode, u64 * ctx) +{ + int i, j, ret = HICN_ERROR_HASHTB_INVAL; + u32 bidx, entry; + hicn_hash_bucket_t *bucket; + + if ((h == NULL) || (pnode == NULL) || (ctx == NULL)) + { + goto done; + } + /* Special-case for new iteration */ + if (*ctx == HICN_HASH_WALK_CTX_INITIAL) + { + bidx = 0; + bucket = &h->ht_buckets[0]; + entry = 0; + j = 0; + i = 0; + goto search_table; + } + /* Convert context to bucket and entry indices */ + bidx = *ctx & 0xffffffffLL; + entry = *ctx >> 32; + + if (bidx >= h->ht_bucket_count) + { + ret = HICN_ERROR_HASHTB_HASH_NOT_FOUND; + goto done; + } + bucket = h->ht_buckets + bidx; + + /* Init total index into entries (includes fixed bucket and overflow) */ + j = 0; + +skip_processed_bucket_chunks: + /* + * Figure out where to resume the search for the next entry in the + * table, by trying to find the last entry returned, from the cookie. + * Loop walks one (regular or overflow) bucket chunk, label is used + * for walking chain of chunks. Note that if there was a deletion or + * an addition that created an overflow, iterator can skip entries or + * return duplicate entries, for entries that are present from before + * the walk starts until after it ends. + */ + + for (i = 0; i < HICN_HASHTB_BUCKET_ENTRIES; i++, j++) + { + if (j > entry) + { + /* + * Start search for next here, use existing 'bucket' + * and 'i' + */ + break; + } + /* + * If an entry is marked for deletion, ignore it + */ + if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_DELETED) + { + continue; + } + /* + * Be prepared to continue to an overflow bucket if + * necessary. (We only expect the last entry in a bucket to + * refer to an overflow bucket...) + */ + if (i == (HICN_HASHTB_BUCKET_ENTRIES - 1)) + { + if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW) + { + bucket = pool_elt_at_index (h->ht_overflow_buckets, + bucket->hb_entries[i].he_node); + + /* Increment overall entry counter 'j' */ + j++; + + goto skip_processed_bucket_chunks; + } + /* + * end of row (end of fixed bucket plus any + * overflows) + */ + i = 0; + j = 0; + + bidx++; + + /* Special case - we're at the end */ + if (bidx >= h->ht_bucket_count) + { + ret = HICN_ERROR_HASHTB_HASH_NOT_FOUND; + goto done; + } + bucket = h->ht_buckets + bidx; + break; + } + } + +search_table: + + /* + * Now we're searching through the table for the next entry that's + * set + */ + + for (; i < HICN_HASHTB_BUCKET_ENTRIES; i++, j++) + { + /* + * If an entry is marked for deletion, ignore it + */ + if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_DELETED) + { + continue; + } + /* Is this entry set? */ + if (bucket->hb_entries[i].he_node != 0) + { + + /* Retrieve the node struct */ + *pnode = pool_elt_at_index (h->ht_nodes, + bucket->hb_entries[i].he_node); + + /* + * Set 'entry' as we exit, so we can update the + * cookie + */ + entry = j; + ret = HICN_ERROR_NONE; + break; + } + /* + * Be prepared to continue to an overflow bucket if + * necessary. (We only expect the last entry in a bucket to + * refer to an overflow bucket...) + */ + if (i == (HICN_HASHTB_BUCKET_ENTRIES - 1)) + { + if (bucket->hb_entries[i].he_flags & HICN_HASH_ENTRY_FLAG_OVERFLOW) + { + bucket = pool_elt_at_index (h->ht_overflow_buckets, + bucket->hb_entries[i].he_node); + /* + * Reset per-bucket index 'i', here (not done + * in iterator) + */ + i = 0; + /* Increment overall entry counter 'j' */ + j++; + + goto search_table; + } + else + { + /* + * Move to next bucket, resetting per-bucket + * and overall entry indexes + */ + i = 0; + j = 0; + + bidx++; + + /* Special case - we're at the end */ + if (bidx >= h->ht_bucket_count) + { + ret = HICN_ERROR_HASHTB_HASH_NOT_FOUND; + goto done; + } + bucket = h->ht_buckets + bidx; + goto search_table; + } + } + } + +done: + + if (ret == HICN_ERROR_NONE) + { + /* Update context */ + *ctx = bidx; + *ctx |= ((u64) entry << 32); + } + return (ret); +} + +int +hicn_hashtb_key_to_buf (u8 ** vec_res, hicn_hashtb_h h, + const hicn_hash_node_t * node) +{ + int ret = HICN_ERROR_NONE; + u8 *vec = *vec_res; + + if (node->hn_keysize <= HICN_HASH_KEY_BYTES) + { + vec_add (vec, node->hn_key.ks.key, node->hn_keysize); + } + *vec_res = vec; + return (ret); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/hashtb.h b/hicn-plugin/src/network/hashtb.h new file mode 100644 index 000000000..3c72fda65 --- /dev/null +++ b/hicn-plugin/src/network/hashtb.h @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2017-2019 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_HASHTB_H__ +#define __HICN_HASHTB_H__ + +#include +#include +#include + +#include "params.h" +#include "parser.h" +#include "error.h" + +/** + * @file hashtb.h + * Lookup is finding a hashtable record whose name matches the name being + * looked up. Most of the lookup work is based on the hash value of the two + * names. Note that the intel cache line size is 64 bytes, and some platforms + * load in 2 cache lines together. + * - first step is to match a record at the bucket/slot level (htab has an + * array of htbucket_t/htbc_elmt, where each bucket has 7 slots to hold indices + * for entries.) Matching at this level implies + * - the hashes of the lookup name and the record map to the same bucket + * - the high 32 bits of the hashes (slot bce_hash_msb32s) match. Read + * cost (on the hash table size, i.e. ignoring reading the name being + * looked up): + * - First step normally requires 1 cache line load to pull in the + * 64-byte htbucket_t with the 7 element slot table holding the + * hash_msb32s. + * - In the event (hopefully rare for a hash table with appropriate + * number of buckets) that more than 7 elements hash to the same bucket, + * lookup may well need to look not only at the static htbc_elmt_t but at + * the chain of dynamically allocated htbc_elmt_t's linked to the static + * htbc_elmt_t, where each of these holds slot entries for additional elements. + * - Before reaching that point, it is initially required to read in the + * hash table record fields (ht_bucket_buf, htnode buf, etc) holding + * pointers to the arrays, but these cache lines are common to all lookups + * so will likely already be in the cache. + * - second step is to match at the record level (htnode/htkb level) once a + * slot-level match happens. Matching at this level implies the following match + * - the hash values (the full 64 bits vs. bucket+32 msb, above). + * - the name which, on the hash table side, is stored as a list of htkb_t (key buffers). + * + * Some hashtables (for which rare false positives are tolerable) store hash + * values but no keys. (In ISM NDN forwarder, this was used for dcm_dpf: data + * cache manager's dataplane filter, where speed was critical and very rare + * false positives would be detected in the full dcm check.) - No key buffers + * are used (or even allocated at hash table creation). + */ + +/* Handy abbreviations for success status, and for boolean values */ +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define HICN_HASH_INVALID_IDX ~0 +/* + * for hicn_hashtb_next_node() iterator, this otherwise illegal context value + * indicates first call of iteration. Note: must not be 0, which is a legal + * context value. + */ +#define HICN_HASH_WALK_CTX_INITIAL (~((u64)0)) + +/* + * Key memory allocation scheme. + * + * The key is the bytestring that a hashtable entry is storing, e.g. a fib + * prefix or packet name. The hash of the name is used not just to pick the + * bucket, but also as a surrogate for the actual key value. + * + * Client calls pass key/name as contiguous memory for lookup/add/delete but + * hashable stores its copy of the key/name as a list of one or more hash_key + * structs. - key memory is managed as a list of keys (cache line + * sized/aligned buffers). - If (keysize < 128) then use key struct's full + * 128 bytes - If not, first key struct is head of a linked list of elements + * where the first bytes are used for the key and the last 4 bytes are the + * index of the next entry (or an end marker). - key memory is generally the + * single largest use of memory in the hash table, especially for PIT, as + * names are bigger than node structs (which is also per name/entry). + * + */ + +/* Compute hash node index from node pointer */ +#define NODE_IDX_FROM_NODE(p, h) \ + (u32)((p) - ((h)->ht_nodes)) + +#define HICN_HASH_KEY_BYTES 20 + +typedef struct +{ + struct + { + u8 key[HICN_HASH_KEY_BYTES]; + } ks; /* Entire key in one block */ +} hicn_hash_key_t; + +/* + * Ratio of extra key blocks to allocate, in case the embedded ones aren't + * sufficient. This is the fraction of the number of entries allocated. + */ +#define HICN_HASHTB_KEY_RATIO 8 + +/* + * hash node, used to store a hash table entry; indexed by an entry in a + * bucket. the node contains an embedded key; long keys are stored as chains + * of keys. + * + * The memory block for a node includes space for storing outgoing faces for + * interests, additional memory located off the end of the htnode data structure. + * + */ + +/* Size this so that we can offer 64B aligned on 64-bits for storing outgoing + * faces information + */ +#define HICN_HASH_NODE_APP_DATA_SIZE 64 + +/* How to align in the right way */ +typedef struct __attribute__ ((packed)) hicn_hash_node_s +{ + /* Bucket id containing the corresponding hash entry. */ + u32 bucket_id; + + /* Hash entry index in the bucket */ + u32 entry_idx; + + /* Total size of the key */ + u16 hn_keysize; + + /* 1 byte of flags for application use */ + u8 hn_flags; + + u8 _hn_reserved1; /* TBD, to align what follows back to + * 32 */ + + hicn_hash_key_t hn_key; /* Key value embedded in the node, may chain + * to more key buffers if necessary */ + + /* 32B + HICN_HASH_NODE_APP_DATA_SIZE */ + /* Followed by app-specific data (fib or pit or cs entry, e.g.) */ + u8 hn_data[HICN_HASH_NODE_APP_DATA_SIZE]; + +} hicn_hash_node_t; + +#define HICN_HASH_NODE_FLAGS_DEFAULT 0x00 +#define HICN_HASH_NODE_CS_FLAGS 0x01 +#define HICN_HASH_NODE_OVERFLOW_BUCKET 0x02 + +/* + * hicn_hash_entry_t Structure holding all or part of a hash value, a node + * index, and other key pieces of info. + * + * - 128 bytes/bucket with 19 bytes/entry gives 6 entries, or 5 entries plus + * next bucket ptr if overflow Changes in this structure will affect + * hicn_hash_bucket_t + */ +typedef struct __attribute__ ((packed)) hicn_hash_entry_s +{ + + /* MSB of the hash value */ + u64 he_msb64; + + /* Index of node block */ + u32 he_node; + + /* + * Lock to prevent hash_node deletion while there are still interest + * or data referring to it + */ + u32 locks; + + /* Index of dpo (4B) */ + index_t dpo_ctx_id; + + /* A few flags, including 'this points to a chain of buckets' */ + u8 he_flags; + + /* + * Index of the virtual function table corresponding to the dpo_ctx + * strategy + */ + u8 vft_id; + +} hicn_hash_entry_t; //size 22B + +STATIC_ASSERT (sizeof (index_t) <= 4, "sizeof index_t is greater than 4B"); + + +#define HICN_HASH_ENTRY_FLAGS_DEFAULT 0x00 + +/* If entry is PIT this flag is 0 */ +#define HICN_HASH_ENTRY_FLAG_CS_ENTRY 0x01 + +/* + * This entry heads a chain of overflow buckets (we expect to see this only + * in the last entry in a bucket.) In this case, the index is to an overflow + * bucket rather than to a single node block. + */ +#define HICN_HASH_ENTRY_FLAG_OVERFLOW 0x04 + +/* This entry has been marked for deletion */ +#define HICN_HASH_ENTRY_FLAG_DELETED 0x08 + +/* Use fast he_timeout units for expiration, slow if not */ +#define HICN_HASH_ENTRY_FLAG_FAST_TIMEOUT 0x10 + +/* + * hash bucket: Contains an array of entries. Cache line sized/aligned, so no + * room for extra fields unless bucket size is increased to 2 cache lines or + * the entry struct shrinks. + */ + +/* + * Overflow bucket ratio as a fraction of the fixed/configured count; a pool + * of hash buckets used if a row in the fixed table overflows. + */ +#define HICN_HASHTB_BUCKET_ENTRIES 5 + +typedef struct __attribute__ ((packed)) +{ + hicn_hash_entry_t hb_entries[HICN_HASHTB_BUCKET_ENTRIES]; + u64 align1; + u64 align2; + u16 align3; +} hicn_hash_bucket_t; + +/* Overall target fill-factor for the hashtable */ +#define HICN_HASHTB_FILL_FACTOR 4 + +#define HICN_HASHTB_MIN_ENTRIES (1 << 4) // includes dummy node 0 entry +#define HICN_HASHTB_MAX_ENTRIES (1 << 24) + +#define HICN_HASHTB_MIN_BUCKETS (1 << 10) + +/* + * htab_t + * + * Hash table main structure. + * + * Contains - pointers to dynamically allocated arrays of cache-line + * sized/aligned structures (buckets, nodes, keys). Put frequently accessed + * fields in the first cache line. + */ +typedef struct hicn_hashtb_s +{ + + /* 8B - main array of hash buckets */ + hicn_hash_bucket_t *ht_buckets; + + /* 8B - just-in-case block of overflow buckets */ + hicn_hash_bucket_t *ht_overflow_buckets; + + /* 8B - block of nodes associated with entries in buckets */ + hicn_hash_node_t *ht_nodes; + + /* Flags */ + u32 ht_flags; + + /* Count of buckets allocated in the main array */ + u32 ht_bucket_count; + + /* Count of overflow buckets allocated */ + u32 ht_overflow_bucket_count; + u32 ht_overflow_buckets_used; + + /* Count of nodes allocated */ + u32 ht_node_count; + u32 ht_nodes_used; + + /* Count of overflow key structs allocated */ + u32 ht_key_count; + u32 ht_keys_used; + +} hicn_hashtb_t, *hicn_hashtb_h; + +/* + * Offset to aligned start of additional data (PIT/CS, FIB) embedded in each + * node. + */ +extern u32 ht_node_data_offset_aligned; + +/* Flags for hashtable */ + +#define HICN_HASHTB_FLAGS_DEFAULT 0x00 + +/* + * Don't use the last entry in each bucket - only use it for overflow. We use + * this for the FIB, currently, so that we can support in-place FIB changes + * that would be difficult if there were hash entry copies as part of + * overflow handling. + */ +#define HICN_HASHTB_FLAG_USE_SEVEN 0x04 +#define HICN_HASHTB_FLAG_KEY_FMT_PFX 0x08 +#define HICN_HASHTB_FLAG_KEY_FMT_NAME 0x10 + +/* + * Max prefix name components we'll support in our incremental hashing; + * currently used only for LPM in the FIB. + */ +#define HICN_HASHTB_MAX_NAME_COMPS HICN_PARAM_FIB_ENTRY_PFX_COMPS_MAX + +/* + * APIs and inlines + */ + +/* Compute hash node index from node pointer */ +static inline u32 +hicn_hashtb_node_idx_from_node (hicn_hashtb_h h, hicn_hash_node_t * p) +{ + return (p - h->ht_nodes); +} + +/* Retrieve a hashtable node by node index */ +static inline hicn_hash_node_t * +hicn_hashtb_node_from_idx (hicn_hashtb_h h, u32 idx) +{ + return (pool_elt_at_index (h->ht_nodes, idx)); +} + +/* Allocate a brand-new hashtable */ +int +hicn_hashtb_alloc (hicn_hashtb_h * ph, u32 max_elems, size_t app_data_size); + +/* Free a hashtable, including its embedded arrays */ +int hicn_hashtb_free (hicn_hashtb_h * ph); + +/* Hash a bytestring, currently using bihash */ +u64 hicn_hashtb_hash_bytestring (const u8 * key, u32 keylen); + +always_inline hicn_hash_entry_t * +hicn_hashtb_get_entry (hicn_hashtb_h h, u32 entry_idx, u32 bucket_id, + u8 bucket_overflow) +{ + hicn_hash_bucket_t *bucket; + if (bucket_overflow) + bucket = pool_elt_at_index (h->ht_overflow_buckets, bucket_id); + else + bucket = (hicn_hash_bucket_t *) (h->ht_buckets + bucket_id); + + return &(bucket->hb_entries[entry_idx]); +} + +/* Hash a name, currently using bihash */ +always_inline u64 +hicn_hashtb_hash_name (const u8 * key, u16 keylen) +{ + if (key != NULL && keylen == HICN_V4_NAME_LEN) + { + clib_bihash_kv_8_8_t kv; + kv.key = ((u64 *) key)[0]; + return clib_bihash_hash_8_8 (&kv); + } + else if (key != NULL && keylen == HICN_V6_NAME_LEN) + { + clib_bihash_kv_24_8_t kv; + kv.key[0] = ((u64 *) key)[0]; + kv.key[1] = ((u64 *) key)[1]; + kv.key[2] = ((u32 *) key)[4]; + return clib_bihash_hash_24_8 (&kv); + } + else + { + return (-1LL); + } +} + + +/* + * Prepare a hashtable node for insertion, supplying the key and computed + * hash info. This sets up the node->key relationship, possibly allocating + * overflow key buffers. + */ +void +hicn_hashtb_init_node (hicn_hashtb_h h, hicn_hash_node_t * node, + const u8 * key, u32 keylen); + +/* + * Insert a node into the hashtable. We expect the caller has used the init + * api to set the node key and hash info, and populated the extra data area + * (if any) - or done the equivalent work itself. + */ +int +hicn_hashtb_insert (hicn_hashtb_h h, hicn_hash_node_t * node, + hicn_hash_entry_t ** hash_entry, u64 hash, + u32 * node_id, + index_t * dpo_ctx_id, u8 * vft_id, u8 * is_cs, + u8 * hash_entry_id, u32 * bucket_id, + u8 * bucket_is_overflow); + +/* + * Basic api to lookup a specific hash+key tuple. This does the entire lookup + * operation, retrieving node structs and comparing keys, so it's not + * optimized for prefetching or high performance. + * + * Returns zero and mails back a node on success, errno otherwise. + */ +int +hicn_hashtb_lookup_node (hicn_hashtb_h h, const u8 * key, + u32 keylen, u64 hashval, u8 is_data, + u32 * node_id, index_t * dpo_ctx_id, u8 * vft_id, + u8 * is_cs, u8 * hash_entry_id, u32 * bucket_id, + u8 * bucket_is_overflow); + +/* + * Extended api to lookup a specific hash+key tuple. The implementation + * allows the caller to locate nodes that are marked for deletion; this is + * part of some hashtable applications, such as the FIB. + * + * This does the entire lookup operation, retrieving node structs and comparing + * keys, so it's not optimized for prefetching or high performance. + * + * Returns zero and mails back a node on success, errno otherwise. + */ +int +hicn_hashtb_lookup_node_ex (hicn_hashtb_h h, const u8 * key, + u32 keylen, u64 hashval, u8 is_data, + int include_deleted_p, u32 * node_id, + index_t * dpo_ctx_id, u8 * vft_id, u8 * is_cs, + u8 * hash_entry_id, u32 * bucket_id, + u8 * bucket_is_overflow); + +/** + * @brief Compares the key in the node with the given key + * + * This function allows to split the hash verification from the comparison of + * the entire key. Useful to exploit prefertching. + * @result 1 if equals, 0 otherwise + */ +int hicn_node_compare (const u8 * key, u32 keylen, hicn_hash_node_t * node); + +/* + * Remove a node from a hashtable using the node itself. The internal data + * structs are cleaned up, but the node struct itself is not: the caller must + * free the node itself. + */ +void hicn_hashtb_remove_node (hicn_hashtb_h h, hicn_hash_node_t * node, + u64 hashval); + +/* + * Delete a node from a hashtable using the node itself, and delete/free the + * node. Caller's pointer is cleared on success. + */ +void hicn_hashtb_delete (hicn_hashtb_h h, hicn_hash_node_t ** pnode, + u64 hashval); + +/* + * Utility to init a new entry in a hashtable bucket/row. We use this to add + * new a node+hash, and to clear out an entry during removal. + */ +void +hicn_hashtb_init_entry (hicn_hash_entry_t * entry, + u32 nodeidx, u64 hashval, u32 locks); + + +/* + * Return data area embedded in a hash node struct. We maintain an 'offset' + * value in case the common node body struct doesn't leave the data area + * aligned properly. + */ +static inline void * +hicn_hashtb_node_data (hicn_hash_node_t * node) +{ + return ((u8 *) (node) + ht_node_data_offset_aligned); +} + +/* + * Use some bits of the low half of the hash to locate a row/bucket in the + * table + */ +static inline u32 +hicn_hashtb_bucket_idx (hicn_hashtb_h h, u64 hashval) +{ + return ((u32) (hashval & (h->ht_bucket_count - 1))); +} + +/* + * Return a hash node struct from the free list, or NULL. Note that the + * returned struct is _not_ cleared/zeroed - init is up to the caller. + */ +static inline hicn_hash_node_t * +hicn_hashtb_alloc_node (hicn_hashtb_h h) +{ + hicn_hash_node_t *p = NULL; + + if (h->ht_nodes_used < h->ht_node_count) + { + pool_get_aligned (h->ht_nodes, p, 8); + h->ht_nodes_used++; + } + return (p); +} + +/* + * Release a hashtable node back to the free list when an entry is cleared + */ +void hicn_hashtb_free_node (hicn_hashtb_h h, hicn_hash_node_t * node); + +/* + * Walk a hashtable, iterating through the nodes, keeping context in 'ctx' + * between calls. + * + * Set the context value to HICN_HASH_WALK_CTX_INITIAL to start an iteration. + */ +int +hicn_hashtb_next_node (hicn_hashtb_h h, hicn_hash_node_t ** pnode, u64 * ctx); + + +int +hicn_hashtb_key_to_str (hicn_hashtb_h h, const hicn_hash_node_t * node, + char *buf, int bufsize, int must_fit); + +/* + * single hash full name can pass offset for two hashes calculation in case + * we use CS and PIT in a two steps hashes (prefix + seqno) + */ +always_inline int +hicn_hashtb_fullhash (const u8 * name, u16 namelen, u64 * name_hash) +{ + *name_hash = hicn_hashtb_hash_name (name, namelen); + return (*name_hash != (-1LL) ? HICN_ERROR_NONE : HICN_ERROR_HASHTB_INVAL); +} + +#endif /* // __HICN_HASHTB_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/hicn.api b/hicn-plugin/src/network/hicn.api new file mode 100644 index 000000000..9643f2098 --- /dev/null +++ b/hicn-plugin/src/network/hicn.api @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2017-2020 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. + */ + +option version = "5.1.0"; +import "vnet/ip/ip_types.api"; + +enum hicn_action_type +{ + HICN_DISABLE = 0, + HICN_ENABLE, +}; + +typedef hicn_face +{ + /* IP local address */ + vl_api_address_t nat_addr; + + /* IPv4 local port number */ + u32 swif; + + /* Face flags */ + u32 flags; + + /* Name of the interface */ + u8 if_name[30]; +}; + +define hicn_api_node_params_set +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* Enable / disable ICN forwarder in VPP */ + u8 enable_disable; + + /* PIT maximum size, otherwise -1 to assign default value */ + i32 pit_max_size; + + /* CS maximum size, otherwise -1 to assign default value */ + i32 cs_max_size; + + /* Upper bound on PIT entry lifetime, otherwise -1 to assign default value */ + f64 pit_max_lifetime_sec; +}; + +define hicn_api_node_params_set_reply +{ + /* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; +}; + +define hicn_api_node_params_get +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; +}; + +define hicn_api_node_params_get_reply +{ + /* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; + + /* Enabled / disabled flag */ + u8 is_enabled; + + /* compile-time plugin features */ + u8 feature_cs; + + /* Number of VPP workers */ + u32 worker_count; + + /* PIT maximum size, otherwise -1 to assign default value */ + u32 pit_max_size; + + /* CS maximum size, otherwise -1 to assign default value */ + u32 cs_max_size; + + /* Upper bound on PIT entry lifetime */ + f64 pit_max_lifetime_sec; +}; + +define hicn_api_node_stats_get +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; +}; + +define hicn_api_node_stats_get_reply +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; + + /* ICN packets processed */ + u64 pkts_processed; + + /* ICN interests forwarded */ + u64 pkts_interest_count; + + /* ICN data msgs forwarded */ + u64 pkts_data_count; + + /* ICN cached data msg replies */ + u64 pkts_from_cache_count; + + /* ICN no PIT entry drops */ + u64 pkts_no_pit_count; + + /* ICN expired PIT entries */ + u64 pit_expired_count; + + /* ICN expired CS entries */ + u64 cs_expired_count; + + /* ICN LRU CS entries freed */ + u64 cs_lru_count; + + /* ICN msgs dropped due to no packet buffers */ + u64 pkts_drop_no_buf; + + /* ICN Interest messages aggregated in PIT */ + u64 interests_aggregated; + + /* ICN Interest messages retransmitted */ + u64 interests_retx; + + /* ICN Interest messages colliding in hashtb */ + u64 interests_hash_collision; + + /* Number of entries in PIT at the present moment */ + u64 pit_entries_count; + + /* Number of entries in CS at the present moment */ + u64 cs_entries_count; + + /* Number of entries in CS at the present moment */ + u64 cs_entries_ntw_count; +}; + +define hicn_api_face_stats_details +{ +/* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; + + /* Id of the face */ + u32 faceid; + + /* Interest rx */ + u64 irx_packets; + + u64 irx_bytes; + + /* Interest tx */ + u64 itx_packets; + + u64 itx_bytes; + + /* data rx */ + u64 drx_packets; + + u64 drx_bytes; + + /* data tx */ + u64 dtx_packets; + + u64 dtx_bytes; +}; + +define hicn_api_face_stats_dump +{ +/* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; +}; + +define hicn_api_face_params_get +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* A Face to be retrieved */ + u32 faceid; +}; + +define hicn_api_face_params_get_reply +{ + /* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; + + /* The face required */ + u32 faceid; + + /* IP local address */ + vl_api_address_t nat_addr; + + /* VPP interface (index) associated with the face */ + u32 swif; + + /* Face flags */ + u32 flags; +}; + +define hicn_api_faces_details +{ +/* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; + + /* Id of the face */ + u32 faceid; + + /* Face to add */ + vl_api_hicn_face_t face; +}; + +define hicn_api_faces_dump +{ +/* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; +}; + +define hicn_api_face_get +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* A Face to be retrieved */ + u32 faceid; +}; + +define hicn_api_face_get_reply +{ + /* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; + + /* Id of the face */ + u32 faceid; + + /* Face to add */ + vl_api_hicn_face_t face; +}; + +define hicn_api_route_get +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* Route prefix */ + vl_api_prefix_t prefix; +}; + +define hicn_api_route_get_reply +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* List of faces pointing to the next hops */ + u32 faceids[5]; + + /* Number of valid faceids */ + u8 nfaces; + + /* Strategy */ + u32 strategy_id; + + /* Return value, zero means all OK */ + i32 retval; +}; + +define hicn_api_routes_details +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* Route prefix */ + vl_api_prefix_t prefix; + + /* List of faces pointing to the next hops */ + u32 faceids[5]; + + /* Number of valid faceids */ + u8 nfaces; + + /* Strategy */ + u32 strategy_id; + + /* Return value, zero means all OK */ + i32 retval; +}; + +define hicn_api_routes_dump +{ +/* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; +}; + +define hicn_api_strategies_get +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; +}; + +define hicn_api_strategies_get_reply +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* Number of available strategies */ + u8 n_strategies; + + /* Strategies */ + u32 strategy_id[256]; + + /* Return value, zero means all OK */ + i32 retval; +}; + +define hicn_api_strategy_get +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* Route prefix */ + u32 strategy_id; +}; + +define hicn_api_strategy_get_reply +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* Strategy description */ + u8 description[200]; + + /* Return value, zero means all OK */ + i32 retval; +}; + +define hicn_api_enable_disable +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* Enable or disable enable/disable hICN*/ + vl_api_hicn_action_type_t enable_disable; + + /* Prefix on which we enable/disable hICN*/ + vl_api_prefix_t prefix; +}; + +define hicn_api_enable_disable_reply +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + +/* Return value, zero means all OK */ + i32 retval; +}; + +define hicn_api_register_prod_app +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* Prefix to match */ + vl_api_prefix_t prefix; + + /* sw_if id */ + u32 swif; + + /* CS memory reserved -- in number of packets */ + u32 cs_reserved; +}; + +define hicn_api_register_prod_app_reply +{ + /* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; + + /* Actual CS memory reserved -- in number of packets */ + u32 cs_reserved; + + /* Prod address (ipv4 or ipv6) */ + vl_api_address_t prod_addr; + + /* Return value: new Face ID, ~0 means no Face was created */ + u32 faceid; +}; + +autoreply define hicn_api_face_prod_del +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* A Face ID to be deleted */ + u32 faceid; +}; + +define hicn_api_register_cons_app +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* swif */ + u32 swif; +}; + +define hicn_api_register_cons_app_reply +{ + /* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; + + /* Ip4 address */ + vl_api_address_t src_addr4; + + /* Ip6 address */ + vl_api_address_t src_addr6; + + /* Return value: new Face ID, ~0 means no Face was created */ + u32 faceid1; + + /* Return value: new Face ID, ~0 means no Face was created */ + u32 faceid2; +}; + +autoreply define hicn_api_face_cons_del +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* A Face ID to be deleted */ + u32 faceid; +}; + +define hicn_api_udp_tunnel_add_del +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* Source address */ + vl_api_address_t src_addr; + + /* Destination address */ + vl_api_address_t dst_addr; + + /* Source port */ + u16 src_port; + + /* Destination port */ + u16 dst_port; + + /* Add or remove the tunnel*/ + u8 is_add; +}; + +define hicn_api_udp_tunnel_add_del_reply +{ + /* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; + + /* Udp encap index */ + u32 uei; +}; + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/hicn.h b/hicn-plugin/src/network/hicn.h new file mode 100644 index 000000000..81246c7e9 --- /dev/null +++ b/hicn-plugin/src/network/hicn.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017-2020 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_H__ +#define __HICN_H__ + +#define ip_address_t hicn_ip_address_t +#define ip_address_cmp hicn_ip_address_cmp +#define ip_prefix_t hicn_ip_prefix_t +#define ip_prefix_cmp hicn_ip_prefix_cmp +#undef ip_prefix_len +#define ip_prefix_len hicn_ip_prefix_len +#include +#undef ip_address_t +#undef ip_address_cmp +#undef ip_prefix_t +#undef ip_prefix_cmp +#undef ip_prefix_len +#define ip_prefix_len(_a) (_a)->len + +#include "hicn_buffer.h" + +#endif /* __HICN_H__ */ + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/hicn_api.c b/hicn-plugin/src/network/hicn_api.c new file mode 100644 index 000000000..e8e24b639 --- /dev/null +++ b/hicn-plugin/src/network/hicn_api.c @@ -0,0 +1,727 @@ +/* + * Copyright (c) 2017-2020 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 +#include +#include +#include +#include +#include + +#include "faces/face.h" +#include "udp_tunnels/udp_tunnel.h" +#include "infra.h" +#include "parser.h" +#include "mgmt.h" +#include "strategy_dpo_manager.h" +#include "strategy_dpo_ctx.h" +#include "strategy.h" +#include "pg.h" +#include "error.h" +#include "faces/app/face_prod.h" +#include "faces/app/face_cons.h" +#include "route.h" + +/* define message IDs */ +#include +#include + +/* define generated endian-swappers */ +#define vl_endianfun +#include +#undef vl_endianfun + +#define REPLY_MSG_ID_BASE sm->msg_id_base +#include + +/****** SUPPORTING FUNCTION DECLARATIONS ******/ + +/* + * Convert a unix return code to a vnet_api return code. Currently stubby: + * should have more cases. + */ +always_inline vnet_api_error_t +hicn_face_api_entry_params_serialize (hicn_face_id_t faceid, + vl_api_hicn_api_face_params_get_reply_t + * reply); + + +/****************** API MESSAGE HANDLERS ******************/ + +/****** NODE ******/ + +static void +vl_api_hicn_api_node_params_set_t_handler (vl_api_hicn_api_node_params_set_t * + mp) +{ + vl_api_hicn_api_node_params_set_reply_t *rmp; + int rv; + + hicn_main_t *sm = &hicn_main; + + int pit_max_size = clib_net_to_host_i32 (mp->pit_max_size); + pit_max_size = + pit_max_size == -1 ? HICN_PARAM_PIT_ENTRIES_DFLT : pit_max_size; + + f64 pit_max_lifetime_sec = mp->pit_max_lifetime_sec; + pit_max_lifetime_sec = + pit_max_lifetime_sec == + -1 ? HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS / SEC_MS : pit_max_lifetime_sec; + + int cs_max_size = clib_net_to_host_i32 (mp->cs_max_size); + cs_max_size = cs_max_size == -1 ? HICN_PARAM_CS_ENTRIES_DFLT : cs_max_size; + + rv = hicn_infra_plugin_enable_disable ((int) (mp->enable_disable), + pit_max_size, + pit_max_lifetime_sec, + cs_max_size, + ~0); + + REPLY_MACRO (VL_API_HICN_API_NODE_PARAMS_SET_REPLY /* , rmp, mp, rv */ ); +} + +static void +vl_api_hicn_api_node_params_get_t_handler (vl_api_hicn_api_node_params_get_t * + mp) +{ + vl_api_hicn_api_node_params_get_reply_t *rmp; + int rv = HICN_ERROR_NONE; + + hicn_main_t *sm = &hicn_main; + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_HICN_API_NODE_PARAMS_GET_REPLY, ( + { + rmp->is_enabled = sm->is_enabled; + rmp->feature_cs = HICN_FEATURE_CS; + rmp->pit_max_size = clib_host_to_net_u32 (hicn_infra_pit_size); + rmp->pit_max_lifetime_sec = ((f64) sm->pit_lifetime_max_ms) / SEC_MS; + rmp->cs_max_size = clib_host_to_net_u32 (hicn_infra_cs_size); + rmp->retval = clib_host_to_net_i32 (rv); + })); + /* *INDENT-ON* */ +} + +static void +vl_api_hicn_api_node_stats_get_t_handler (vl_api_hicn_api_node_stats_get_t * + mp) +{ + vl_api_hicn_api_node_stats_get_reply_t *rmp; + int rv = HICN_ERROR_NONE; + + hicn_main_t *sm = &hicn_main; + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_HICN_API_NODE_STATS_GET_REPLY, ( + { + rv = hicn_mgmt_node_stats_get (rmp); + rmp->retval =clib_host_to_net_i32 (rv); + })); + /* *INDENT-ON* */ +} + + +static void + vl_api_hicn_api_face_params_get_t_handler + (vl_api_hicn_api_face_params_get_t * mp) +{ + vl_api_hicn_api_face_params_get_reply_t *rmp; + int rv = 0; + + hicn_main_t *sm = &hicn_main; + + hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid); + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_HICN_API_FACE_PARAMS_GET_REPLY, ( + { + rv = hicn_face_api_entry_params_serialize(faceid, rmp); + rmp->retval = clib_host_to_net_u32(rv); + })); + /* *INDENT-ON* */ +} + +static void +send_face_details (hicn_face_t * face, vl_api_hicn_face_t * mp) +{ + vnet_main_t *vnm = vnet_get_main (); + + ip_address_encode (&face->nat_addr, IP46_TYPE_ANY, &mp->nat_addr); + mp->flags = clib_host_to_net_u32 (face->flags); + mp->swif = clib_net_to_host_u32 (face->sw_if); + vnet_sw_interface_t *sw_interface = + vnet_get_sw_interface_or_null (vnm, face->sw_if); + u8 *sbuf = 0; + if (sw_interface != NULL) + { + sbuf = + format (0, "%U", format_vnet_sw_interface_name, vnm, sw_interface); + strcpy ((char *) (mp->if_name), (char *) sbuf); + } +} + +static void +send_faces_details (vl_api_registration_t * reg, + hicn_face_t * face, u32 context) +{ + vl_api_hicn_api_faces_details_t *mp; + hicn_main_t *hm = &hicn_main; + mp = vl_msg_api_alloc (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + mp->faceid = clib_host_to_net_u32 (hicn_dpoi_get_index (face)); + mp->_vl_msg_id = htons (VL_API_HICN_API_FACES_DETAILS + hm->msg_id_base); + mp->context = context; + + send_face_details (face, &(mp->face)); + + vl_api_send_msg (reg, (u8 *) mp); +} + +static void +vl_api_hicn_api_faces_dump_t_handler (vl_api_hicn_api_faces_dump_t * mp) +{ + hicn_face_t *face; + vl_api_registration_t *reg; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + /* *INDENT-OFF* */ + pool_foreach (face, hicn_dpoi_face_pool, + ({ + send_faces_details (reg, face, mp->context); + })); + /* *INDENT-ON* */ +} + +static void +vl_api_hicn_api_face_get_t_handler (vl_api_hicn_api_face_get_t * mp) +{ + vl_api_hicn_api_face_get_reply_t *rmp; + int rv = 0; + + hicn_main_t *sm = &hicn_main; + + hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid); + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_HICN_API_FACE_GET_REPLY, ( + { + rv = hicn_dpoi_idx_is_valid(faceid); + if (rv) + { + hicn_face_t * face = hicn_dpoi_get_from_idx(faceid); + send_face_details(face, &(rmp->face)); + rv = HICN_ERROR_NONE; + } + else + { + rv = HICN_ERROR_FACE_NOT_FOUND; + } + rmp->retval = clib_host_to_net_u32(rv); + })); + /* *INDENT-ON* */ +} + +static void +send_face_stats_details (vl_api_registration_t * reg, + hicn_face_t * face, u32 context) +{ + vl_api_hicn_api_face_stats_details_t *mp; + hicn_main_t *hm = &hicn_main; + mp = vl_msg_api_alloc (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + + mp->_vl_msg_id = + htons (VL_API_HICN_API_FACE_STATS_DETAILS + hm->msg_id_base); + mp->context = context; + + mp->faceid = htonl (hicn_dpoi_get_index (face)); + vlib_counter_t v; + vlib_get_combined_counter (&counters + [hicn_dpoi_get_index (face) * HICN_N_COUNTER], + HICN_FACE_COUNTERS_INTEREST_RX, &v); + mp->irx_packets = clib_net_to_host_u64 (v.packets); + mp->irx_bytes = clib_net_to_host_u64 (v.bytes); + + vlib_get_combined_counter (&counters + [hicn_dpoi_get_index (face) * HICN_N_COUNTER], + HICN_FACE_COUNTERS_INTEREST_TX, &v); + mp->itx_packets = clib_net_to_host_u64 (v.packets); + mp->itx_bytes = clib_net_to_host_u64 (v.bytes); + + vlib_get_combined_counter (&counters + [hicn_dpoi_get_index (face) * HICN_N_COUNTER], + HICN_FACE_COUNTERS_DATA_RX, &v); + mp->drx_packets = clib_net_to_host_u64 (v.packets); + mp->drx_bytes = clib_net_to_host_u64 (v.bytes); + + vlib_get_combined_counter (&counters + [hicn_dpoi_get_index (face) * HICN_N_COUNTER], + HICN_FACE_COUNTERS_DATA_TX, &v); + mp->dtx_packets = clib_net_to_host_u64 (v.packets); + mp->dtx_bytes = clib_net_to_host_u64 (v.bytes); + + vl_api_send_msg (reg, (u8 *) mp); +} + +static void + vl_api_hicn_api_face_stats_dump_t_handler + (vl_api_hicn_api_face_stats_dump_t * mp) +{ + hicn_face_t *face; + vl_api_registration_t *reg; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + /* *INDENT-OFF* */ + pool_foreach (face, hicn_dpoi_face_pool, + ({ + send_face_stats_details (reg, face, mp->context); + })); + /* *INDENT-ON* */ +} + + +/****** ROUTE *******/ + +static void vl_api_hicn_api_route_get_t_handler + (vl_api_hicn_api_route_get_t * mp) +{ + vl_api_hicn_api_route_get_reply_t *rmp; + int rv = HICN_ERROR_NONE; + + hicn_main_t *sm = &hicn_main; + + fib_prefix_t prefix; + ip_prefix_decode (&mp->prefix, &prefix); + const dpo_id_t *hicn_dpo_id; + hicn_dpo_ctx_t *hicn_dpo_ctx; + u32 fib_index; + + rv = hicn_route_get_dpo (&prefix, &hicn_dpo_id, &fib_index); + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_HICN_API_ROUTE_GET_REPLY, ( + { + if (rv == HICN_ERROR_NONE) + { + hicn_dpo_ctx = hicn_strategy_dpo_ctx_get(hicn_dpo_id->dpoi_index); + for (int i = 0; hicn_dpo_ctx != NULL && i < hicn_dpo_ctx->entry_count; i++) + { + rmp->faceids[i] = hicn_dpo_ctx->next_hops[i]; + } + rmp->strategy_id = clib_host_to_net_u32(hicn_dpo_get_vft_id(hicn_dpo_id));} + })); + /* *INDENT-ON* */ +} + +static void +send_route_details (vl_api_registration_t * reg, + const fib_prefix_t * pfx, u32 context) +{ + vl_api_hicn_api_routes_details_t *mp; + hicn_main_t *hm = &hicn_main; + mp = vl_msg_api_alloc (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + + mp->_vl_msg_id = htons (VL_API_HICN_API_ROUTES_DETAILS + hm->msg_id_base); + mp->context = context; + + ip_prefix_encode (pfx, &mp->prefix); + mp->nfaces = 0; + + const dpo_id_t *hicn_dpo_id; + hicn_dpo_ctx_t *hicn_dpo_ctx; + u32 fib_index; + + int rv = hicn_route_get_dpo (pfx, &hicn_dpo_id, &fib_index); + + if (rv == HICN_ERROR_NONE) + { + hicn_dpo_ctx = hicn_strategy_dpo_ctx_get (hicn_dpo_id->dpoi_index); + for (int i = 0; hicn_dpo_ctx != NULL && i < hicn_dpo_ctx->entry_count; + i++) + { + mp->faceids[i] = + clib_host_to_net_u32 (hicn_dpo_ctx-> + next_hops[i]); + mp->nfaces++; + } + mp->strategy_id = + clib_host_to_net_u32 (hicn_dpo_get_vft_id (hicn_dpo_id)); + } + + vl_api_send_msg (reg, (u8 *) mp); +} + +typedef struct vl_api_hicn_api_route_dump_walk_ctx_t_ +{ + fib_node_index_t *feis; +} vl_api_hicn_api_route_dump_walk_ctx_t; + +static fib_table_walk_rc_t +vl_api_hicn_api_route_dump_walk (fib_node_index_t fei, void *arg) +{ + vl_api_hicn_api_route_dump_walk_ctx_t *ctx = arg; + int found = 0; + const dpo_id_t *former_dpo_id; + + /* Route already existing. We need to update the dpo. */ + const dpo_id_t *load_balance_dpo_id = + fib_entry_contribute_ip_forwarding (fei); + + /* The dpo is not a load balance dpo as expected */ + if (load_balance_dpo_id->dpoi_type == DPO_LOAD_BALANCE) + { + /* former_dpo_id is a load_balance dpo */ + load_balance_t *lb = load_balance_get (load_balance_dpo_id->dpoi_index); + + /* FIB entry exists but there is no hicn dpo. */ + for (int i = 0; i < lb->lb_n_buckets && !found; i++) + { + former_dpo_id = load_balance_get_bucket_i (lb, i); + + if (dpo_is_hicn (former_dpo_id)) + { + vec_add1 (ctx->feis, fei); + } + } + } + + return (FIB_TABLE_WALK_CONTINUE); +} + +static void +vl_api_hicn_api_routes_dump_t_handler (vl_api_hicn_api_routes_dump_t * mp) +{ + vl_api_registration_t *reg; + fib_table_t *fib_table; + ip4_main_t *im = &ip4_main; + ip6_main_t *im6 = &ip6_main; + fib_node_index_t *lfeip; + const fib_prefix_t *pfx; + vl_api_hicn_api_route_dump_walk_ctx_t ctx = { + .feis = NULL, + }; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + pool_foreach (fib_table, im->fibs, ( + { + fib_table_walk (fib_table->ft_index, + FIB_PROTOCOL_IP4, + vl_api_hicn_api_route_dump_walk, + &ctx);} + )); + + pool_foreach (fib_table, im6->fibs, ( + { + fib_table_walk (fib_table->ft_index, + FIB_PROTOCOL_IP6, + vl_api_hicn_api_route_dump_walk, + &ctx);} + )); + + vec_foreach (lfeip, ctx.feis) + { + pfx = fib_entry_get_prefix (*lfeip); + send_route_details (reg, pfx, mp->context); + } + + vec_free (ctx.feis); + +} + +static void vl_api_hicn_api_strategies_get_t_handler + (vl_api_hicn_api_strategies_get_t * mp) +{ + vl_api_hicn_api_strategies_get_reply_t *rmp; + int rv = HICN_ERROR_NONE; + + hicn_main_t *sm = &hicn_main; + + int n_strategies = hicn_strategy_get_all_available (); + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_HICN_API_STRATEGIES_GET_REPLY/* , rmp, mp, rv */ ,( + { + int j = 0; + for (u32 i = 0; i < (u32) n_strategies; i++) + { + if (hicn_dpo_strategy_id_is_valid (i) == HICN_ERROR_NONE) + { + rmp->strategy_id[j] = clib_host_to_net_u32 (i); j++;} + } + rmp->n_strategies = n_strategies; + })); + /* *INDENT-ON* */ +} + +static void vl_api_hicn_api_strategy_get_t_handler + (vl_api_hicn_api_strategy_get_t * mp) +{ + vl_api_hicn_api_strategy_get_reply_t *rmp; + int rv = HICN_ERROR_NONE; + + hicn_main_t *sm = &hicn_main; + + u32 strategy_id = clib_net_to_host_u32 (mp->strategy_id); + rv = hicn_dpo_strategy_id_is_valid (strategy_id); + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_HICN_API_STRATEGY_GET_REPLY /* , rmp, mp, rv */ ,( + { + if (rv == HICN_ERROR_NONE) + { + const hicn_strategy_vft_t * hicn_strategy_vft = + hicn_dpo_get_strategy_vft (strategy_id); + hicn_strategy_vft->hicn_format_strategy (rmp->description, 0);} + })); + /* *INDENT-ON* */ +} + +/************* APP FACE ****************/ + +static void vl_api_hicn_api_register_prod_app_t_handler + (vl_api_hicn_api_register_prod_app_t * mp) +{ + vl_api_hicn_api_register_prod_app_reply_t *rmp; + int rv = HICN_ERROR_NONE; + + hicn_main_t *sm = &hicn_main; + + fib_prefix_t prefix; + ip_prefix_decode (&mp->prefix, &prefix); + u32 swif = clib_net_to_host_u32 (mp->swif); + u32 cs_reserved = clib_net_to_host_u32 (mp->cs_reserved); + u32 faceid; + + ip46_address_t prod_addr; + ip46_address_reset (&prod_addr); + rv = hicn_face_prod_add (&prefix, swif, &cs_reserved, &prod_addr, &faceid); + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_HICN_API_REGISTER_PROD_APP_REPLY, ( + { + ip_address_encode(&prod_addr, IP46_TYPE_ANY, &rmp->prod_addr); + rmp->cs_reserved = clib_net_to_host_u32(cs_reserved); + rmp->faceid = clib_net_to_host_u32(faceid); + })); + /* *INDENT-ON* */ +} + +static void +vl_api_hicn_api_face_prod_del_t_handler (vl_api_hicn_api_face_prod_del_t * mp) +{ + vl_api_hicn_api_face_prod_del_reply_t *rmp; + int rv = HICN_ERROR_FACE_NOT_FOUND; + + hicn_main_t *sm = &hicn_main; + + hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid); + rv = hicn_face_prod_del (faceid); + + REPLY_MACRO (VL_API_HICN_API_FACE_PROD_DEL_REPLY /* , rmp, mp, rv */ ); +} + +static void vl_api_hicn_api_register_cons_app_t_handler + (vl_api_hicn_api_register_cons_app_t * mp) +{ + vl_api_hicn_api_register_cons_app_reply_t *rmp; + int rv = HICN_ERROR_NONE; + + hicn_main_t *sm = &hicn_main; + ip46_address_t src_addr4 = ip46_address_initializer; + ip46_address_t src_addr6 = ip46_address_initializer; + + u32 swif = clib_net_to_host_u32 (mp->swif); + u32 faceid1; + u32 faceid2; + + rv = + hicn_face_cons_add (&src_addr4.ip4, &src_addr6.ip6, swif, &faceid1, + &faceid2); + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_HICN_API_REGISTER_CONS_APP_REPLY, ( + { + ip_address_encode(&src_addr4, IP46_TYPE_ANY, &rmp->src_addr4); + ip_address_encode(&src_addr6, IP46_TYPE_ANY, &rmp->src_addr6); + rmp->faceid1 = clib_net_to_host_u32(faceid1); + rmp->faceid2 = clib_net_to_host_u32(faceid2); + })); + /* *INDENT-ON* */ +} + +static void +vl_api_hicn_api_face_cons_del_t_handler (vl_api_hicn_api_face_cons_del_t * mp) +{ + vl_api_hicn_api_face_cons_del_reply_t *rmp; + int rv = HICN_ERROR_FACE_NOT_FOUND; + + hicn_main_t *sm = &hicn_main; + + hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid); + rv = hicn_face_cons_del (faceid); + + REPLY_MACRO (VL_API_HICN_API_FACE_CONS_DEL_REPLY /* , rmp, mp, rv */ ); +} + +static void vl_api_hicn_api_enable_disable_t_handler +(vl_api_hicn_api_enable_disable_t * mp) +{ + vl_api_hicn_api_enable_disable_reply_t *rmp; + int rv = HICN_ERROR_NONE; + + hicn_main_t *sm = &hicn_main; + + fib_prefix_t prefix; + ip_prefix_decode (&mp->prefix, &prefix); + + switch (clib_net_to_host_u32(mp->enable_disable)) + { + case HICN_ENABLE: + rv = hicn_route_enable(&prefix); + break; + case HICN_DISABLE: + rv = hicn_route_disable(&prefix); + break; + } + + REPLY_MACRO (VL_API_HICN_API_ENABLE_DISABLE_REPLY/* , rmp, mp, rv */ ); +} + +/*********************************** UDP TUNNELS ************************************/ + +static void vl_api_hicn_api_udp_tunnel_add_del_t_handler +(vl_api_hicn_api_udp_tunnel_add_del_t * mp) +{ + vl_api_hicn_api_udp_tunnel_add_del_reply_t *rmp; + int rv = HICN_ERROR_NONE; + + hicn_main_t *sm = &hicn_main; + + ip46_address_t src_addr; + ip46_address_t dst_addr; + u16 src_port; + u16 dst_port; + index_t uei = ~0; + + ip46_type_t type = ip_address_decode (&mp->src_addr, &src_addr); + if (type != ip_address_decode (&mp->dst_addr, &dst_addr)) + { + rv = HICN_ERROR_UDP_TUNNEL_SRC_DST_TYPE; + goto done; + } + + src_port = clib_net_to_host_u16(mp->src_port); + dst_port = clib_net_to_host_u16(mp->dst_port); + + fib_protocol_t proto = ip46_address_is_ip4(&src_addr) ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; + + index_t fib_index = fib_table_find (proto, HICN_FIB_TABLE); + + if (mp->is_add) + { + uei = udp_tunnel_add(proto, + fib_index, &src_addr, &dst_addr, src_port, dst_port, + UDP_ENCAP_FIXUP_NONE); + } + else + { + udp_tunnel_del(proto, + fib_index, &src_addr, &dst_addr, src_port, dst_port, + UDP_ENCAP_FIXUP_NONE); + } + + + done: + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_HICN_API_UDP_TUNNEL_ADD_DEL_REPLY, ( + { + rmp->uei = clib_host_to_net_u32(uei); + })); + /* *INDENT-ON* */ +} + +/************************************************************************************/ + +#include + +/* Set up the API message handling tables */ +clib_error_t * +hicn_api_plugin_hookup (vlib_main_t * vm) +{ + hicn_main_t *hm = &hicn_main; + + hm->msg_id_base = setup_message_id_table (); + return 0; +} + + + +/******************* SUPPORTING FUNCTIONS *******************/ + +/* + * Binary serialization for get face configuration API. for the moment + * assuming only ip faces here. To be completed with othet types of faces + */ +vnet_api_error_t +hicn_face_api_entry_params_serialize (hicn_face_id_t faceid, + vl_api_hicn_api_face_params_get_reply_t + * reply) +{ + int rv = HICN_ERROR_NONE; + + if (!reply) + { + rv = VNET_API_ERROR_INVALID_ARGUMENT; + goto done; + } + hicn_face_t *face = hicn_dpoi_get_from_idx (faceid); + + if (face != NULL) + { + ip_address_encode (&face->nat_addr, IP46_TYPE_ANY, + &reply->nat_addr); + + reply->swif = clib_host_to_net_u32 (face->sw_if); + reply->flags = clib_host_to_net_u32 (face->flags); + reply->faceid = clib_host_to_net_u32 (faceid); + } + else + rv = HICN_ERROR_FACE_IP_ADJ_NOT_FOUND; + +done: + return (rv); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/hicn_api_test.c b/hicn-plugin/src/network/hicn_api_test.c new file mode 100644 index 000000000..033d0a1b3 --- /dev/null +++ b/hicn-plugin/src/network/hicn_api_test.c @@ -0,0 +1,1319 @@ +/* + * Copyright (c) 2017-2020 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 +#include +#include +#include +#include + +#define __plugin_msg_base hicn_test_main.msg_id_base +#include + +#include + +#include +#include + + +/* Declare message IDs */ +#include + +/* SUPPORTING FUNCTIONS NOT LOADED BY VPP_API_TEST */ +uword +unformat_ip46_address (unformat_input_t * input, va_list * args) +{ + ip46_address_t *ip46 = va_arg (*args, ip46_address_t *); + ip46_type_t type = va_arg (*args, ip46_type_t); + if ((type != IP46_TYPE_IP6) && + unformat (input, "%U", unformat_ip4_address, &ip46->ip4)) + { + ip46_address_mask_ip4 (ip46); + return 1; + } + else if ((type != IP46_TYPE_IP4) && + unformat (input, "%U", unformat_ip6_address, &ip46->ip6)) + { + return 1; + } + return 0; +} + +static ip46_type_t +ip_address_union_decode (const vl_api_address_union_t * in, + vl_api_address_family_t af, ip46_address_t * out) +{ + ip46_type_t type; + + switch (clib_net_to_host_u32 (af)) + { + case ADDRESS_IP4: + clib_memset (out, 0, sizeof (*out)); + clib_memcpy (&out->ip4, &in->ip4, sizeof (out->ip4)); + type = IP46_TYPE_IP4; + break; + case ADDRESS_IP6: + clib_memcpy (&out->ip6, &in->ip6, sizeof (out->ip6)); + type = IP46_TYPE_IP6; + break; + default: + ASSERT (!"Unkown address family in API address type"); + type = IP46_TYPE_ANY; + break; + } + + return type; +} + +void +ip6_address_encode (const ip6_address_t * in, vl_api_ip6_address_t out) +{ + clib_memcpy (out, in, sizeof (*in)); +} + +void +ip6_address_decode (const vl_api_ip6_address_t in, ip6_address_t * out) +{ + clib_memcpy (out, in, sizeof (*out)); +} + +void +ip4_address_encode (const ip4_address_t * in, vl_api_ip4_address_t out) +{ + clib_memcpy (out, in, sizeof (*in)); +} + +void +ip4_address_decode (const vl_api_ip4_address_t in, ip4_address_t * out) +{ + clib_memcpy (out, in, sizeof (*out)); +} + +static void +ip_address_union_encode (const ip46_address_t * in, + vl_api_address_family_t af, + vl_api_address_union_t * out) +{ + if (ADDRESS_IP6 == clib_net_to_host_u32 (af)) + ip6_address_encode (&in->ip6, out->ip6); + else + ip4_address_encode (&in->ip4, out->ip4); +} + +ip46_type_t +ip_address_decode (const vl_api_address_t * in, ip46_address_t * out) +{ + return (ip_address_union_decode (&in->un, in->af, out)); +} + +void +ip_address_encode (const ip46_address_t * in, ip46_type_t type, + vl_api_address_t * out) +{ + switch (type) + { + case IP46_TYPE_IP4: + out->af = clib_net_to_host_u32 (ADDRESS_IP4); + break; + case IP46_TYPE_IP6: + out->af = clib_net_to_host_u32 (ADDRESS_IP6); + break; + case IP46_TYPE_ANY: + if (ip46_address_is_ip4 (in)) + out->af = clib_net_to_host_u32 (ADDRESS_IP4); + else + out->af = clib_net_to_host_u32 (ADDRESS_IP6); + break; + } + ip_address_union_encode (in, out->af, &out->un); +} + +fib_protocol_t +fib_proto_from_ip46 (ip46_type_t iproto) +{ + switch (iproto) + { + case IP46_TYPE_IP4: + return FIB_PROTOCOL_IP4; + case IP46_TYPE_IP6: + return FIB_PROTOCOL_IP6; + case IP46_TYPE_ANY: + ASSERT (0); + return FIB_PROTOCOL_IP4; + } + + ASSERT (0); + return FIB_PROTOCOL_IP4; +} + +ip46_type_t +fib_proto_to_ip46 (fib_protocol_t fproto) +{ + switch (fproto) + { + case FIB_PROTOCOL_IP4: + return (IP46_TYPE_IP4); + case FIB_PROTOCOL_IP6: + return (IP46_TYPE_IP6); + case FIB_PROTOCOL_MPLS: + return (IP46_TYPE_ANY); + } + ASSERT (0); + return (IP46_TYPE_ANY); +} + +void +ip_prefix_decode (const vl_api_prefix_t * in, fib_prefix_t * out) +{ + switch (clib_net_to_host_u32 (in->address.af)) + { + case ADDRESS_IP4: + out->fp_proto = FIB_PROTOCOL_IP4; + break; + case ADDRESS_IP6: + out->fp_proto = FIB_PROTOCOL_IP6; + break; + } + out->fp_len = in->len; + out->___fp___pad = 0; + ip_address_decode (&in->address, &out->fp_addr); +} + +void +ip_prefix_encode (const fib_prefix_t * in, vl_api_prefix_t * out) +{ + out->len = in->fp_len; + ip_address_encode (&in->fp_addr, + fib_proto_to_ip46 (in->fp_proto), &out->address); +} + +///////////////////////////////////////////////////// + +#define HICN_FACE_NULL ~0 + +typedef struct +{ + /* API message ID base */ + u16 msg_id_base; + vat_main_t *vat_main; + u32 ping_id; +} hicn_test_main_t; + +hicn_test_main_t hicn_test_main; + +#define foreach_standard_reply_retval_handler \ +_(hicn_api_node_params_set_reply) \ +_(hicn_api_enable_disable_reply) + +#define _(n) \ + static void vl_api_##n##_t_handler \ + (vl_api_##n##_t * mp) \ + { \ + vat_main_t * vam = hicn_test_main.vat_main; \ + i32 retval = ntohl(mp->retval); \ + if (vam->async_mode) { \ + vam->async_errors += (retval < 0); \ + } else { \ + fformat (vam->ofp,"%s\n", get_error_string(retval));\ + vam->retval = retval; \ + vam->result_ready = 1; \ + } \ + } +foreach_standard_reply_retval_handler; +#undef _ + +/* + * Table of message reply handlers, must include boilerplate handlers we just + * generated + */ +#define foreach_vpe_api_reply_msg \ +_(HICN_API_NODE_PARAMS_SET_REPLY, hicn_api_node_params_set_reply) \ +_(HICN_API_NODE_PARAMS_GET_REPLY, hicn_api_node_params_get_reply) \ +_(HICN_API_NODE_STATS_GET_REPLY, hicn_api_node_stats_get_reply) \ +_(HICN_API_FACE_GET_REPLY, hicn_api_face_get_reply) \ +_(HICN_API_FACES_DETAILS, hicn_api_faces_details) \ +_(HICN_API_FACE_STATS_DETAILS, hicn_api_face_stats_details) \ +_(HICN_API_FACE_PARAMS_GET_REPLY, hicn_api_face_params_get_reply) \ +_(HICN_API_ROUTE_GET_REPLY, hicn_api_route_get_reply) \ +_(HICN_API_ROUTES_DETAILS, hicn_api_routes_details) \ +_(HICN_API_STRATEGIES_GET_REPLY, hicn_api_strategies_get_reply) \ +_(HICN_API_STRATEGY_GET_REPLY, hicn_api_strategy_get_reply) \ +_(HICN_API_ENABLE_DISABLE_REPLY, hicn_api_enable_disable_reply) \ +_(HICN_API_UDP_TUNNEL_ADD_DEL_REPLY, hicn_api_udp_tunnel_add_del_reply) + +static int +api_hicn_api_node_params_set (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + int enable_disable = 1; + int pit_size = -1, cs_size = -1; + f64 pit_max_lifetime_sec = -1.0f; + int ret; + + vl_api_hicn_api_node_params_set_t *mp; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "disable")) + { + enable_disable = 0; + } + else if (unformat (input, "PIT size %d", &pit_size)) + {; + } + else if (unformat (input, "CS size %d", &cs_size)) + {; + } + else if (unformat (input, "PIT maxlife %f", &pit_max_lifetime_sec)) + {; + } + else + { + break; + } + } + + /* Construct the API message */ + M (HICN_API_NODE_PARAMS_SET, mp); + mp->enable_disable = clib_host_to_net_u32(enable_disable); + mp->pit_max_size = clib_host_to_net_i32 (pit_size); + mp->cs_max_size = clib_host_to_net_i32 (cs_size); + mp->pit_max_lifetime_sec = pit_max_lifetime_sec; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return ret; +} + +static int +api_hicn_api_node_params_get (vat_main_t * vam) +{ + vl_api_hicn_api_node_params_get_t *mp; + int ret; + + //Construct the API message + M (HICN_API_NODE_PARAMS_GET, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return ret; +} + +static void + vl_api_hicn_api_node_params_get_reply_t_handler + (vl_api_hicn_api_node_params_get_reply_t * mp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + i32 retval = ntohl (mp->retval); + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + return; + } + vam->retval = retval; + vam->result_ready = 1; + + if (vam->retval < 0) + { + //vpp_api_test infra will also print out string form of error + fformat (vam->ofp, " (API call error: %d)\n", vam->retval); + return; + } + fformat (vam->ofp, + "Enabled %d\n" + " Features: cs:%d\n" + " PIT size %d\n" + " PIT lifetime dflt %.3f, min %.3f, max %.3f\n" + " CS size %d\n", + mp->is_enabled, + mp->feature_cs, + clib_net_to_host_u32 (mp->pit_max_size), + mp->pit_max_lifetime_sec, clib_net_to_host_u32 (mp->cs_max_size)); +} + +static int +api_hicn_api_node_stats_get (vat_main_t * vam) +{ + vl_api_hicn_api_node_stats_get_t *mp; + int ret; + + /* Construct the API message */ + M (HICN_API_NODE_STATS_GET, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return ret; +} + +static void + vl_api_hicn_api_node_stats_get_reply_t_handler + (vl_api_hicn_api_node_stats_get_reply_t * rmp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + i32 retval = ntohl (rmp->retval); + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + return; + } + vam->retval = retval; + vam->result_ready = 1; + + if (vam->retval < 0) + { + //vpp_api_test infra will also print out string form of error + fformat (vam->ofp, " (API call error: %d)\n", vam->retval); + return; + } + else + { + fformat (vam->ofp, //compare hicn_cli_show_command_fn block:should match + " PIT entries (now): %d\n" + " CS entries (now): %d\n" + " Forwarding statistics:" + " pkts_processed: %d\n" + " pkts_interest_count: %d\n" + " pkts_data_count: %d\n" + " pkts_nak_count: %d\n" + " pkts_from_cache_count: %d\n" + " pkts_nacked_interests_count: %d\n" + " pkts_nak_hoplimit_count: %d\n" + " pkts_nak_no_route_count: %d\n" + " pkts_no_pit_count: %d\n" + " pit_expired_count: %d\n" + " cs_expired_count: %d\n" + " cs_lru_count: %d\n" + " pkts_drop_no_buf: %d\n" + " interests_aggregated: %d\n" + " interests_retransmitted: %d\n", + clib_net_to_host_u64 (rmp->pit_entries_count), + clib_net_to_host_u64 (rmp->cs_entries_count), + clib_net_to_host_u64 (rmp->pkts_processed), + clib_net_to_host_u64 (rmp->pkts_interest_count), + clib_net_to_host_u64 (rmp->pkts_data_count), + clib_net_to_host_u64 (rmp->pkts_from_cache_count), + clib_net_to_host_u64 (rmp->pkts_no_pit_count), + clib_net_to_host_u64 (rmp->pit_expired_count), + clib_net_to_host_u64 (rmp->cs_expired_count), + clib_net_to_host_u64 (rmp->cs_lru_count), + clib_net_to_host_u64 (rmp->pkts_drop_no_buf), + clib_net_to_host_u64 (rmp->interests_aggregated), + clib_net_to_host_u64 (rmp->interests_retx)); + } +} + +static int +api_hicn_api_face_params_get (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_hicn_api_face_params_get_t *mp; + u32 faceid = HICN_FACE_NULL, ret; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "face %d", &faceid)) + {; + } + else + { + break; + } + } + + //Check for presence of face ID + if (faceid == HICN_FACE_NULL) + { + clib_warning ("Please specify face ID"); + return 1; + } + //Construct the API message + M (HICN_API_FACE_PARAMS_GET, mp); + mp->faceid = clib_host_to_net_u32 (faceid); + + //send it... + S (mp); + + //Wait for a reply... + W (ret); + + return ret; +} + +static void + vl_api_hicn_api_face_params_get_reply_t_handler + (vl_api_hicn_api_face_params_get_reply_t * rmp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + i32 retval = ntohl (rmp->retval); + u8 *sbuf = 0; + ip46_address_t nat_addr; + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + return; + } + vam->retval = retval; + vam->result_ready = 1; + + if (vam->retval < 0) + { + //vpp_api_test infra will also print out string form of error + fformat (vam->ofp, " (API call error: %d)\n", vam->retval); + return; + } + vec_reset_length (sbuf); + ip_address_decode (&rmp->nat_addr, &nat_addr); + sbuf = + format (0, "nat_addr %U", format_ip46_address, + &nat_addr, 0 /*IP46_ANY_TYPE */); + + fformat (vam->ofp, "%s swif %d flags %d\n", + sbuf, + clib_net_to_host_u32 (rmp->swif), + clib_net_to_host_i32 (rmp->flags)); +} + +static void +format_face (vl_api_hicn_face_t * rmp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + u8 *sbuf = 0; + ip46_address_t nat_addr; + ip46_address_t local_addr; + + vec_reset_length (sbuf); + ip_address_decode (&rmp->nat_addr, &nat_addr); + + sbuf = + format (0, "nat_addr %U", format_ip46_address, + &local_addr, 0 /*IP46_ANY_TYPE */); + + fformat (vam->ofp, "%s swif %d flags %d name %s\n", + sbuf, + clib_net_to_host_u32 (rmp->swif), + clib_net_to_host_i32 (rmp->flags), rmp->if_name); +} + +static int +api_hicn_api_faces_dump (vat_main_t * vam) +{ + hicn_test_main_t *hm = &hicn_test_main; + vl_api_hicn_api_faces_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + if (vam->json_output) + { + clib_warning ("JSON output not supported for faces_dump"); + return -99; + } + + M (HICN_API_FACES_DUMP, mp); + S (mp); + + if (!hm->ping_id) + hm->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC)); + + /* Use a control ping for synchronization */ + mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping)); + mp_ping->_vl_msg_id = htons (hm->ping_id); + mp_ping->client_index = vam->my_client_index; + + fformat (vam->ofp, "Sending ping id=%d\n", hm->ping_id); + + vam->result_ready = 0; + S (mp_ping); + + W (ret); + return ret; +} + +static void + vl_api_hicn_api_faces_details_t_handler + (vl_api_hicn_api_faces_details_t * mp) +{ + format_face (&(mp->face)); +} + +static int +api_hicn_api_face_get (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_hicn_api_face_get_t *mp; + u32 faceid = HICN_FACE_NULL, ret; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "face %d", &faceid)) + {; + } + else + { + break; + } + } + + //Check for presence of face ID + if (faceid == HICN_FACE_NULL) + { + clib_warning ("Please specify face ID"); + return 1; + } + //Construct the API message + M (HICN_API_FACE_GET, mp); + mp->faceid = clib_host_to_net_u32 (faceid); + + //send it... + S (mp); + + //Wait for a reply... + W (ret); + + return ret; +} + + +static void + vl_api_hicn_api_face_get_reply_t_handler + (vl_api_hicn_api_face_get_reply_t * rmp) +{ + + vat_main_t *vam = hicn_test_main.vat_main; + i32 retval = ntohl (rmp->retval); + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + return; + } + vam->retval = retval; + vam->result_ready = 1; + + if (vam->retval < 0) + { + //vpp_api_test infra will also print out string form of error + fformat (vam->ofp, " (API call error: %d)\n", vam->retval); + return; + } + format_face (&(rmp->face)); +} + + + +static int +api_hicn_api_face_stats_dump (vat_main_t * vam) +{ + hicn_test_main_t *hm = &hicn_test_main; + vl_api_hicn_api_face_stats_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + if (vam->json_output) + { + clib_warning ("JSON output not supported for memif_dump"); + return -99; + } + + M (HICN_API_FACE_STATS_DUMP, mp); + S (mp); + + if (!hm->ping_id) + hm->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC)); + + /* Use a control ping for synchronization */ + mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping)); + mp_ping->_vl_msg_id = htons (hm->ping_id); + mp_ping->client_index = vam->my_client_index; + + fformat (vam->ofp, "Sending ping id=%d\n", hm->ping_id); + + vam->result_ready = 0; + S (mp_ping); + + W (ret); + return ret; +} + +/* face_stats-details message handler */ +static void + vl_api_hicn_api_face_stats_details_t_handler + (vl_api_hicn_api_face_stats_details_t * mp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + + fformat (vam->ofp, "face id %d\n" + " interest rx packets %16Ld\n" + " bytes %16Ld\n" + " interest tx packets %16Ld\n" + " bytes %16Ld\n" + " data rx packets %16Ld\n" + " bytes %16Ld\n" + " data tx packets %16Ld\n" + " bytes %16Ld\n", + clib_host_to_net_u32 (mp->faceid), + clib_host_to_net_u64 (mp->irx_packets), + clib_host_to_net_u64 (mp->irx_bytes), + clib_host_to_net_u64 (mp->itx_packets), + clib_host_to_net_u64 (mp->itx_bytes), + clib_host_to_net_u64 (mp->drx_packets), + clib_host_to_net_u64 (mp->drx_bytes), + clib_host_to_net_u64 (mp->dtx_packets), + clib_host_to_net_u64 (mp->dtx_bytes)); +} + +static int +api_hicn_api_route_get (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + + vl_api_hicn_api_route_get_t *mp; + fib_prefix_t prefix; + int ret; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "prefix %U/%d", unformat_ip46_address, + &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) + {; + } + else + { + break; + } + } + + /* Check parse */ + if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) + || (prefix.fp_len == 0)) + { + clib_warning ("Please specify a valid prefix..."); + return 1; + } + //Construct the API message + M (HICN_API_ROUTE_GET, mp); + if (!ip46_address_is_ip4 (&(prefix.fp_addr))) + prefix.fp_proto = fib_proto_from_ip46 (IP46_TYPE_IP6); + ip_prefix_encode (&prefix, &mp->prefix); + + //send it... + S (mp); + + //Wait for a reply... + W (ret); + + return ret; +} + +static int +api_hicn_api_routes_dump (vat_main_t * vam) +{ + + hicn_test_main_t *hm = &hicn_test_main; + vl_api_hicn_api_route_get_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + if (vam->json_output) + { + clib_warning ("JSON output not supported for routes_dump"); + return -99; + } + + M (HICN_API_ROUTES_DUMP, mp); + S (mp); + + if (!hm->ping_id) + hm->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC)); + + /* Use a control ping for synchronization */ + mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping)); + mp_ping->_vl_msg_id = htons (hm->ping_id); + mp_ping->client_index = vam->my_client_index; + + fformat (vam->ofp, "Sending ping id=%d\n", hm->ping_id); + + vam->result_ready = 0; + S (mp_ping); + + W (ret); + return ret; +} + +static void +vl_api_hicn_api_route_get_reply_t_handler (vl_api_hicn_api_route_get_reply_t * + rmp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + i32 retval = ntohl (rmp->retval); + u8 *sbuf = 0; + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + return; + } + vam->retval = retval; + vam->result_ready = 1; + + if (vam->retval < 0) + { + //vpp_api_test infra will also print out string form of error + fformat (vam->ofp, " (API call error: %d)\n", vam->retval); + return; + } + int i = 0; + u8 null_face = 0; + u32 faceid; + + vec_reset_length (sbuf); + sbuf = format (sbuf, "Faces: \n"); + while (i < 1000 && !null_face) + { + faceid = clib_net_to_host_u32 (rmp->faceids[i]); + if (faceid != HICN_FACE_NULL) + { + sbuf = + format (sbuf, "faceid %d", + clib_net_to_host_u32 (rmp->faceids[i])); + i++; + } + else + { + null_face = 1; + } + } + + fformat (vam->ofp, "%s\n Strategy: %d\n", + sbuf, clib_net_to_host_u32 (rmp->strategy_id)); +} + +/* face_stats-details message handler */ +static void + vl_api_hicn_api_routes_details_t_handler + (vl_api_hicn_api_routes_details_t * mp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + fib_prefix_t prefix; + u32 faceid; + u8 *sbuf = 0; + vec_reset_length (sbuf); + + ip_prefix_decode (&mp->prefix, &prefix); + sbuf = + format (sbuf, "Prefix: %U/%u\n", format_ip46_address, &prefix.fp_addr, 0, + prefix.fp_len); + + sbuf = format (sbuf, "Faces: \n"); + for (int i = 0; i < mp->nfaces; i++) + { + faceid = clib_net_to_host_u32 (mp->faceids[i]); + sbuf = format (sbuf, " faceid %d\n", faceid); + } + + fformat (vam->ofp, "%sStrategy: %d\n", + sbuf, clib_net_to_host_u32 (mp->strategy_id)); +} + +static int +api_hicn_api_strategies_get (vat_main_t * vam) +{ + vl_api_hicn_api_strategies_get_t *mp; + int ret; + + //TODO + /* Construct the API message */ + M (HICN_API_STRATEGIES_GET, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return ret; +} + +static void + vl_api_hicn_api_strategies_get_reply_t_handler + (vl_api_hicn_api_strategies_get_reply_t * mp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + i32 retval = ntohl (mp->retval); + u8 *sbuf = 0; + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + return; + } + vam->retval = retval; + vam->result_ready = 1; + + if (vam->retval < 0) + { + //vpp_api_test infra will also print out string form of error + fformat (vam->ofp, " (API call error: %d)\n", vam->retval); + return; + } + int n_strategies = clib_net_to_host_i32 (mp->n_strategies); + + vec_reset_length (sbuf); + sbuf = format (sbuf, "Available strategies:\n"); + + int i; + for (i = 0; i < n_strategies; i++) + { + u32 strategy_id = clib_net_to_host_u32 (mp->strategy_id[i]); + sbuf = format (sbuf, "%d ", strategy_id); + } + fformat (vam->ofp, "%s", sbuf); +} + +static int +api_hicn_api_strategy_get (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_hicn_api_strategy_get_t *mp; + int ret; + + u32 strategy_id = HICN_STRATEGY_NULL; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "strategy %d", strategy_id)) + {; + } + else + { + break; + } + } + + if (strategy_id == HICN_STRATEGY_NULL) + { + clib_warning ("Please specify strategy id..."); + return 1; + } + + /* Construct the API message */ + M (HICN_API_STRATEGY_GET, mp); + mp->strategy_id = clib_host_to_net_u32 (strategy_id); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return ret; +} + +static void + vl_api_hicn_api_strategy_get_reply_t_handler + (vl_api_hicn_api_strategy_get_reply_t * mp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + i32 retval = ntohl (mp->retval); + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + return; + } + vam->retval = retval; + vam->result_ready = 1; + + if (vam->retval < 0) + { + //vpp_api_test infra will also print out string form of error + fformat (vam->ofp, " (API call error: %d)\n", vam->retval); + return; + } + fformat (vam->ofp, "%s", mp->description); +} + +static int +api_hicn_api_enable_disable (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_hicn_api_enable_disable_t *mp; + int ret; + + fib_prefix_t prefix; + vl_api_hicn_action_type_t en_dis = HICN_ENABLE; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "prefix %U/%d", unformat_ip46_address, + &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) + {; + } + else if (unformat (input, "disable")) + {; + en_dis = HICN_DISABLE; + } + else + { + break; + } + } + + /* Check parse */ + if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) + || (prefix.fp_len == 0)) + { + clib_warning ("Please specify a valid prefix..."); + return 1; + } + + prefix.fp_proto = ip46_address_is_ip4 (&(prefix.fp_addr)) ? FIB_PROTOCOL_IP4 : + FIB_PROTOCOL_IP6; + + //Construct the API message + M (HICN_API_ENABLE_DISABLE, mp); + + ip_prefix_encode (&prefix, &mp->prefix); + mp->enable_disable = en_dis; + + //send it... + S (mp); + + //Wait for a reply... + W (ret); + + return ret; +} + +static int +api_hicn_api_register_prod_app (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_hicn_api_register_prod_app_t *mp; + fib_prefix_t prefix; + u32 swif = ~0; + int ret; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "prefix %U/%d", unformat_ip46_address, + &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) + {; + } + else if (unformat (input, "id %d", &swif)) + {; + } + else + { + break; + } + } + + /* Check parse */ + if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) + || (prefix.fp_len == 0)) + { + clib_warning ("Please specify prefix..."); + return 1; + } + + prefix.fp_proto = + ip46_address_is_ip4 (&(prefix.fp_addr)) ? FIB_PROTOCOL_IP4 : + FIB_PROTOCOL_IP6; + /* Construct the API message */ + M (HICN_API_REGISTER_PROD_APP, mp); + ip_prefix_encode (&prefix, &mp->prefix); + + mp->swif = clib_host_to_net_u32 (swif); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return ret; +} + +static void + vl_api_hicn_api_register_prod_app_reply_t_handler + (vl_api_hicn_api_register_prod_app_reply_t * mp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + i32 retval = ntohl (mp->retval); + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + return; + } + vam->retval = retval; + vam->result_ready = 1; + + if (vam->retval < 0) + { + //vpp_api_test infra will also print out string form of error + fformat (vam->ofp, " (API call error: %d)\n", vam->retval); + return; + } +} + +static int +api_hicn_api_face_prod_del (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_hicn_api_face_prod_del_t *mp; + u32 faceid = 0, ret; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "face %d", &faceid)) + {; + } + else + { + break; + } + } + + //Check for presence of face ID + if (faceid == ~0) + { + clib_warning ("Please specify face ID"); + return 1; + } + //Construct the API message + M (HICN_API_FACE_PROD_DEL, mp); + mp->faceid = clib_host_to_net_u32 (faceid); + + //send it... + S (mp); + + //Wait for a reply... + W (ret); + + return ret; +} + +static int +api_hicn_api_register_cons_app (vat_main_t * vam) +{ + vl_api_hicn_api_register_cons_app_t *mp; + int ret; + + /* Construct the API message */ + M (HICN_API_REGISTER_CONS_APP, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return ret; +} + +static int +api_hicn_api_face_cons_del (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_hicn_api_face_cons_del_t *mp; + u32 faceid = 0, ret; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "face %d", &faceid)) + {; + } + else + { + break; + } + } + + //Check for presence of face ID + if (faceid == ~0) + { + clib_warning ("Please specify face ID"); + return 1; + } + //Construct the API message + M (HICN_API_FACE_CONS_DEL, mp); + mp->faceid = clib_host_to_net_u32 (faceid); + + //send it... + S (mp); + + //Wait for a reply... + W (ret); + + return ret; +} + +static void + vl_api_hicn_api_register_cons_app_reply_t_handler + (vl_api_hicn_api_register_cons_app_reply_t * mp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + i32 retval = ntohl (mp->retval); + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + return; + } + vam->retval = retval; + vam->result_ready = 1; + + if (vam->retval < 0) + { + //vpp_api_test infra will also print out string form of error + fformat (vam->ofp, " (API call error: %d)\n", vam->retval); + return; + } + ip46_address_t src_addr4 = ip46_address_initializer; + ip46_address_t src_addr6 = ip46_address_initializer; + ip_address_decode (&mp->src_addr4, &src_addr4); + ip_address_decode (&mp->src_addr6, &src_addr6); + + fformat (vam->ofp, + "ip4 address %U\n" + "ip6 address :%U\n", + format_ip46_address, IP46_TYPE_ANY, &src_addr4, + format_ip46_address, IP46_TYPE_ANY, &src_addr6); +} + +static int +api_hicn_api_udp_tunnel_add_del (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_hicn_api_udp_tunnel_add_del_t *mp; + + ip46_address_t src_ip, dst_ip; + u32 src_port, dst_port; + fib_protocol_t fproto; + u8 is_del; + int ret; + + is_del = 0; + fproto = FIB_PROTOCOL_MAX; + + /* Get a line of input. */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "add")) + is_del = 0; + else if (unformat (input, "del")) + is_del = 1; + else if (unformat (input, "%U %U", + unformat_ip4_address, + &src_ip.ip4, unformat_ip4_address, &dst_ip.ip4)) + fproto = FIB_PROTOCOL_IP4; + else if (unformat (input, "%U %U", + unformat_ip6_address, + &src_ip.ip6, unformat_ip6_address, &dst_ip.ip6)) + fproto = FIB_PROTOCOL_IP6; + else if (unformat (input, "%d %d", &src_port, &dst_port)) + ; + else + { + break; + } + } + + + if (fproto == FIB_PROTOCOL_MAX) + { + clib_warning ("Please specify face ID"); + return 1; + } + + /* Construct the API message */ + M (HICN_API_UDP_TUNNEL_ADD_DEL, mp); + ip_address_encode (&src_ip, fproto == FIB_PROTOCOL_IP4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6 ,&mp->src_addr); + ip_address_encode (&dst_ip, fproto == FIB_PROTOCOL_IP4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6 ,&mp->dst_addr); + mp->src_port = clib_host_to_net_u16(src_port); + mp->dst_port = clib_host_to_net_u16(dst_port); + mp->is_add = !is_del; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return ret; +} + +static void +vl_api_hicn_api_udp_tunnel_add_del_reply_t_handler +(vl_api_hicn_api_udp_tunnel_add_del_reply_t * mp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + i32 retval = ntohl (mp->retval); + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + return; + } + vam->retval = retval; + vam->result_ready = 1; + + if (vam->retval < 0) + { + //vpp_api_test infra will also print out string form of error + fformat (vam->ofp, " (API call error: %d)\n", vam->retval); + return; + } + + index_t uei = clib_net_to_host_u32(mp->uei); + + fformat (vam->ofp, + "udp-encap %d\n", + uei); +} + + + +#include + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/hicn_config.c b/hicn-plugin/src/network/hicn_config.c new file mode 100644 index 000000000..441bd03cf --- /dev/null +++ b/hicn-plugin/src/network/hicn_config.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2017-2020 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 "hicn.h" +#include "params.h" +#include "infra.h" +#include "strategy_dpo_manager.h" +#include "mgmt.h" +#include "error.h" +#include "faces/app/address_mgr.h" +#include "face_db.h" +#include "udp_tunnels/udp_tunnel.h" +#include "route.h" + +hicn_main_t hicn_main; +/* Module vars */ +int hicn_infra_fwdr_initialized = 0; + +/* + * Global time counters we're trying out for opportunistic hashtable + * expiration. + */ +uint16_t hicn_infra_fast_timer; /* Counts at 1 second intervals */ +uint16_t hicn_infra_slow_timer; /* Counts at 1 minute intervals */ + +hicn_face_bucket_t *hicn_face_bucket_pool; + +/* + * Init hicn forwarder with configurable PIT, CS sizes + */ +static int +hicn_infra_fwdr_init (uint32_t shard_pit_size, uint32_t shard_cs_size) +{ + int ret = 0; + + if (hicn_infra_fwdr_initialized) + { + ret = HICN_ERROR_FWD_ALREADY_ENABLED; + goto done; + } + /* Init per worker limits */ + hicn_infra_pit_size = shard_pit_size; + hicn_infra_cs_size = shard_cs_size; + + /* Init the global time-compression counters */ + hicn_infra_fast_timer = 1; + hicn_infra_slow_timer = 1; + + ret = hicn_pit_create (&hicn_main.pitcs, hicn_infra_pit_size); + hicn_pit_set_lru_max (&hicn_main.pitcs, hicn_infra_cs_size); +done: + if ((ret == HICN_ERROR_NONE) && !hicn_infra_fwdr_initialized) + { + hicn_infra_fwdr_initialized = 1; + } + return (ret); +} + +/* + * Action function shared between message handler and debug CLI NOTICE: we're + * only 'enabling' now + */ +int +hicn_infra_plugin_enable_disable (int enable_disable, + int pit_size_req, + f64 pit_max_lifetime_sec_req, + int cs_size_req, + vnet_link_t link) +{ + int ret = 0; + + hicn_main_t *sm = &hicn_main; + uint32_t pit_size, cs_size; + + /* Notice if we're already enabled... */ + if (sm->is_enabled) + { + ret = HICN_ERROR_FWD_ALREADY_ENABLED; + goto done; + } + /* Set up params and call fwdr_init set up PIT/CS, forwarder nodes */ + + /* Check the range and assign some globals */ + if (pit_max_lifetime_sec_req < 0) + { + sm->pit_lifetime_max_ms = HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS; + } + else + { + if (pit_max_lifetime_sec_req < HICN_PARAM_PIT_LIFETIME_BOUND_MIN_SEC || + pit_max_lifetime_sec_req > HICN_PARAM_PIT_LIFETIME_BOUND_MAX_SEC) + { + ret = HICN_ERROR_PIT_CONFIG_MAXLT_OOB; + goto done; + } + sm->pit_lifetime_max_ms = pit_max_lifetime_sec_req * SEC_MS; + } + + if (pit_size_req < 0) + { + pit_size = HICN_PARAM_PIT_ENTRIES_DFLT; + } + else + { + if (pit_size_req < HICN_PARAM_PIT_ENTRIES_MIN || + pit_size_req > HICN_PARAM_PIT_ENTRIES_MAX) + { + ret = HICN_ERROR_PIT_CONFIG_SIZE_OOB; + goto done; + } + pit_size = (uint32_t) pit_size_req; + } + + if (cs_size_req < 0) + { + cs_size = HICN_PARAM_CS_ENTRIES_DFLT; + } + else + { + /* + * This should be relatively safe + * At this point vlib buffers should have been already allocated + */ + + vlib_buffer_main_t *bm; + vlib_buffer_pool_t *bp; + vlib_main_t *vm = vlib_get_main (); + bm = vm->buffer_main; + + u32 n_buffers = 0; + vec_foreach (bp, bm->buffer_pools) + n_buffers = n_buffers < bp->n_buffers ? bp->n_buffers : n_buffers; + + // check if CS is bugger tha PIT or bigger than the available vlib_buffers + uword cs_buffers = + (n_buffers > + HICN_PARAM_CS_MIN_MBUF) ? n_buffers - HICN_PARAM_CS_MIN_MBUF : 0; + + if (cs_size_req > (pit_size_req / 2) || cs_size_req > cs_buffers) + { + cs_size_req = + ((pit_size_req / 2) > cs_buffers) ? cs_buffers : pit_size_req / 2; + vlib_cli_output (vm, + "WARNING!! CS too large. Please check size of PIT or the number of buffers available in VPP\n"); + + } + cs_size = (uint32_t) cs_size_req; + } + + ret = hicn_infra_fwdr_init (pit_size, cs_size); + + hicn_face_db_init (pit_size); + + if (ret != HICN_ERROR_NONE) + { + goto done; + } + sm->is_enabled = 1; + sm->link = link; + //hicn_face_udp_init_internal (); + +done: + + return (ret); +} + +static clib_error_t * +hicn_configure (vlib_main_t * vm, unformat_input_t * input) +{ + u32 pit_size = HICN_PARAM_PIT_ENTRIES_DFLT; + u32 cs_size = HICN_PARAM_CS_ENTRIES_DFLT; + u64 pit_lifetime_max_sec = HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS / SEC_MS; + + vnet_link_t link; + + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "pit-size %u", &pit_size)) + ; + else if (unformat (input, "cs-size %u", &cs_size)) + ; + else if (unformat (input, "pit-lifetime-max %u", &pit_lifetime_max_sec)) + ; + else if (unformat (input, "grab mpls-tunnels")) + link = VNET_LINK_MPLS; + else + break; + } + + unformat_free (input); + + hicn_infra_plugin_enable_disable (1, pit_size, + pit_lifetime_max_sec, + cs_size, link); + + + return 0; +} + +VLIB_CONFIG_FUNCTION (hicn_configure, "hicn"); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/infra.h b/hicn-plugin/src/network/infra.h new file mode 100644 index 000000000..ff76de4e4 --- /dev/null +++ b/hicn-plugin/src/network/infra.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2017-2020 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_INFRA_H__ +#define __HICN_INFRA_H__ + +#include +#include +#include + +#include "pcs.h" + +/** + * @file infra.h + * + */ + +/** + * @brief hICN plugin global state. + */ +typedef struct hicn_main_s +{ + /* Binary API message ID base */ + u16 msg_id_base; + + /* Have we been enabled */ + u16 is_enabled; + + /* Forwarder PIT/CS */ + hicn_pit_cs_t pitcs; + + /* Global PIT lifetime info */ + /* + * Boundaries for the interest lifetime. If greater than + * pit_lifetime_max_ms, pit_lifetime_max_ms is used in the PIT + */ + u64 pit_lifetime_max_ms; + + vnet_link_t link; + +} hicn_main_t; + +extern hicn_main_t hicn_main; + +extern int hicn_infra_fwdr_initialized; + +/* PIT and CS size */ +u32 hicn_infra_pit_size; +u32 hicn_infra_cs_size; + +/** + * @brief Enable and disable the hicn plugin + * + * Enable the time the hICN plugin and set the forwarder parameters. + * @param enable_disable 1 if to enable, 0 otherwisw (currently only enable is supported) + * @param pit_max_size Max size of the PIT + * @param pit_max_lifetime_sec_req Maximum timeout allowed for a PIT entry lifetime + * @param cs_max_size CS size. Must be <= than pit_max_size + * @param cs_reserved_app Amount of CS reserved for application faces + */ +int +hicn_infra_plugin_enable_disable (int enable_disable, + int pit_max_size, + f64 pit_max_lifetime_sec_req, + int cs_max_size, + vnet_link_t link); + + +/* vlib nodes that compose the hICN forwarder */ +extern vlib_node_registration_t hicn_interest_pcslookup_node; +extern vlib_node_registration_t hicn_data_pcslookup_node; +extern vlib_node_registration_t hicn_data_fwd_node; +extern vlib_node_registration_t hicn_data_store_node; +extern vlib_node_registration_t hicn_interest_hitpit_node; +extern vlib_node_registration_t hicn_interest_hitcs_node; +extern vlib_node_registration_t hicn_pg_interest_node; +extern vlib_node_registration_t hicn_pg_data_node; +extern vlib_node_registration_t hicn_pg_server_node; +extern vlib_node_registration_t hicn_data_input_ip6_node; +extern vlib_node_registration_t hicn_data_input_ip4_node; + + + +#endif /* // __HICN_INFRA_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/interest_hitcs.h b/hicn-plugin/src/network/interest_hitcs.h new file mode 100644 index 000000000..94fa3e6f5 --- /dev/null +++ b/hicn-plugin/src/network/interest_hitcs.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2020 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_INTEREST_HITCS_H__ +#define __HICN_INTEREST_HITCS_H__ + +#include +#include + +#include "pcs.h" + +/** + * @file interest_hitcs.h + * + * This is the node encoutered by interest packets after the hicn-interest-pcslookup. + * This node satisfies an interest with a data stored in the CS and send the data back + * from the incoming iface of the interest (i.e., the vlib buffer is sent to the + * hicn6-iface-output or hicn4-iface-output node). In case the data is expired, the + * vlib buffer is sent to the hicn-strategy node. + */ + +/* + * Node context data; we think this is per-thread/instance + */ +typedef struct hicn_interest_hitcs_runtime_s +{ + int id; + hicn_pit_cs_t *pitcs; +} hicn_interest_hitcs_runtime_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; +} hicn_interest_hitcs_trace_t; + +typedef enum +{ + HICN_INTEREST_HITCS_NEXT_STRATEGY, + HICN_INTEREST_HITCS_NEXT_IFACE4_OUT, + HICN_INTEREST_HITCS_NEXT_IFACE6_OUT, + HICN_INTEREST_HITCS_NEXT_ERROR_DROP, + HICN_INTEREST_HITCS_N_NEXT, +} hicn_interest_hitcs_next_t; + +#endif /* // __HICN_INTEREST_HITCS_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/interest_hitcs_node.c b/hicn-plugin/src/network/interest_hitcs_node.c new file mode 100644 index 000000000..f569fa897 --- /dev/null +++ b/hicn-plugin/src/network/interest_hitcs_node.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2017-2020 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 "interest_hitcs.h" +#include "mgmt.h" +#include "parser.h" +#include "data_fwd.h" +#include "infra.h" +#include "state.h" +#include "error.h" + +/* packet trace format function */ +static u8 *hicn_interest_hitcs_format_trace (u8 * s, va_list * args); + + +/* Stats string values */ +static char *hicn_interest_hitcs_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +vlib_node_registration_t hicn_interest_hitcs_node; + +always_inline void drop_packet (u32 * next0); + +always_inline void +clone_from_cs (vlib_main_t * vm, u32 * bi0_cs, vlib_buffer_t * dest, u8 isv6) +{ + /* Retrieve the buffer to clone */ + vlib_buffer_t *cs_buf = vlib_get_buffer (vm, *bi0_cs); + hicn_buffer_t *hicnb = hicn_get_buffer (cs_buf); + word buffer_advance = CLIB_CACHE_LINE_BYTES * 2; + if (hicnb->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL) + { + clib_memcpy_fast (vlib_buffer_get_current (dest), + vlib_buffer_get_current (cs_buf), + cs_buf->current_length); + clib_memcpy_fast (dest->opaque2, cs_buf->opaque2, + sizeof (cs_buf->opaque2)); + + dest->current_length = cs_buf->current_length; + dest->total_length_not_including_first_buffer = 0; + } + else + { + vlib_buffer_advance (cs_buf, -buffer_advance); + if (PREDICT_FALSE (cs_buf->ref_count == 255)) + { + vlib_buffer_t *cs_buf2 = vlib_buffer_copy (vm, cs_buf); + vlib_buffer_advance (cs_buf, buffer_advance); + *bi0_cs = vlib_get_buffer_index (vm, cs_buf2); + cs_buf->ref_count--; + cs_buf = cs_buf2; + } + + clib_memcpy_fast (vlib_buffer_get_current (dest), + vlib_buffer_get_current (cs_buf), buffer_advance); + clib_memcpy_fast (dest->opaque2, cs_buf->opaque2, + sizeof (cs_buf->opaque2)); + dest->current_length = buffer_advance; + vlib_buffer_advance (cs_buf, buffer_advance); + vlib_buffer_attach_clone (vm, dest, cs_buf); + } +} + +static uword +hicn_interest_hitcs_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next; + hicn_interest_hitcs_next_t next_index; + 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); + + if (PREDICT_FALSE (rt->pitcs == NULL)) + { + rt->pitcs = &hicn_main.pitcs; + } + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + /* Capture time in vpp terms */ + tnow = vlib_time_now (vm); + while (n_left_from > 0) + { + u32 n_left_to_next; + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *b0; + u8 isv6; + u8 *nameptr; + 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; + hicn_hash_entry_t *hash_entry0; + const hicn_strategy_vft_t *strategy_vft0; + const hicn_dpo_vft_t *dpo_vft0; + u8 dpo_ctx_id0; + + /* Prefetch for next iteration. */ + if (n_left_from > 1) + { + vlib_buffer_t *b1; + b1 = vlib_get_buffer (vm, from[1]); + CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, STORE); + CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, STORE); + } + + /* Dequeue a packet buffer */ + bi0 = from[0]; + from += 1; + n_left_from -= 1; + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + /* Get hicn buffer and state */ + hicnb0 = hicn_get_buffer (b0); + 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); + pitp = hicn_pit_get_data (node0); + + dpo_id_t hicn_dpo_id0 = + { dpo_vft0->hicn_dpo_get_type (), 0, 0, dpo_ctx_id0 }; + + if (PREDICT_FALSE + (ret != HICN_ERROR_NONE || + !hicn_node_compare (nameptr, namelen, node0))) + { + /* Remove lock from the entry */ + hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, hash_entry0, + dpo_vft0, &hicn_dpo_id0); + drop_packet (&next0); + goto end_processing; + } + if ((tnow > pitp->shared.expire_time)) + { + /* Delete and clean up expired CS entry */ + hicn_pcs_delete (rt->pitcs, &pitp, &node0, vm, hash_entry0, + dpo_vft0, &hicn_dpo_id0); + stats.cs_expired_count++; + /* Forward interest to the strategy node */ + next0 = HICN_INTEREST_HITCS_NEXT_STRATEGY; + } + else + { + if (PREDICT_TRUE + (!(hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED))) + hicn_pcs_cs_update (vm, rt->pitcs, pitp, pitp, node0); + + /* + * Retrieve the incoming iface and forward + * the data through it + */ + next0 = isv6 ? HICN_INTEREST_HITCS_NEXT_IFACE6_OUT : + HICN_INTEREST_HITCS_NEXT_IFACE4_OUT; + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = hicnb0->face_id; + + clone_from_cs (vm, &pitp->u.cs.cs_pkt_buf, b0, isv6); + + stats.pkts_from_cache_count++; + stats.pkts_data_count++; + /* Remove lock from the entry */ + hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, hash_entry0, + dpo_vft0, &hicn_dpo_id0); + } + + end_processing: + + /* Maybe trace */ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_interest_hitcs_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = HICN_PKT_TYPE_INTEREST; + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + t->next_index = next0; + } + /* Incr packet counter */ + stats.pkts_processed += 1; + + /* + * 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); + } + + u32 pit_int_count = hicn_pit_get_int_count (rt->pitcs); + + vlib_node_increment_counter (vm, hicn_interest_hitcs_node.index, + HICNFWD_ERROR_CACHED, + stats.pkts_from_cache_count); + + vlib_node_increment_counter (vm, hicn_interest_hitcs_node.index, + HICNFWD_ERROR_DATAS, stats.pkts_data_count); + + update_node_counter (vm, hicn_interest_hitcs_node.index, + HICNFWD_ERROR_INT_COUNT, pit_int_count); + + return (frame->n_vectors); +} + +always_inline void +drop_packet (u32 * next0) +{ + *next0 = HICN_INTEREST_HITCS_NEXT_ERROR_DROP; +} + +/* packet trace format function */ +static u8 * +hicn_interest_hitcs_format_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 *); + hicn_interest_hitcs_trace_t *t = + va_arg (*args, hicn_interest_hitcs_trace_t *); + + s = format (s, "INTEREST-HITCS: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + return (s); +} + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(hicn_interest_hitcs_node) = +{ + .function = hicn_interest_hitcs_node_fn, + .name = "hicn-interest-hitcs", + .vector_size = sizeof(u32), + .runtime_data_bytes = sizeof(hicn_interest_hitcs_runtime_t), + .format_trace = hicn_interest_hitcs_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(hicn_interest_hitcs_error_strings), + .error_strings = hicn_interest_hitcs_error_strings, + .n_next_nodes = HICN_INTEREST_HITCS_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = + { + [HICN_INTEREST_HITCS_NEXT_STRATEGY] = "hicn-strategy", + [HICN_INTEREST_HITCS_NEXT_IFACE4_OUT] = "hicn4-iface-output", + [HICN_INTEREST_HITCS_NEXT_IFACE6_OUT] = "hicn6-iface-output", + [HICN_INTEREST_HITCS_NEXT_ERROR_DROP] = "error-drop" + }, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/interest_hitpit.h b/hicn-plugin/src/network/interest_hitpit.h new file mode 100644 index 000000000..ffdc61c8f --- /dev/null +++ b/hicn-plugin/src/network/interest_hitpit.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017-2020 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_INTEREST_HITPIT_H__ +#define __HICN_INTEREST_HITPIT_H__ + +#include +#include + +#include "pcs.h" + +/** + * @file interest_hitpit.h + * + * This is the node encoutered by interest packets after the hicn-interest-pcslookup. + * This node aggregates an interest in the PIT or forward it in case of a retransmission. + * If the interest must be retransmitted the next vlib node will be on of the + * hicn6-face-output or hicn4-face-output nodes. If the pit entry is expired the next vlib node + * will be the hicn-strategy node, otherwise the vlib buffer is dropped. + */ + + +/* + * Node context data; we think this is per-thread/instance + */ +typedef struct hicn_interest_hitpit_runtime_s +{ + int id; + hicn_pit_cs_t *pitcs; +} hicn_interest_hitpit_runtime_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; +} hicn_interest_hitpit_trace_t; + +typedef enum +{ + HICN_INTEREST_HITPIT_NEXT_INTEREST_HITCS, + HICN_INTEREST_HITPIT_NEXT_STRATEGY, + HICN_INTEREST_HITPIT_NEXT_FACE4_OUTPUT, + HICN_INTEREST_HITPIT_NEXT_FACE6_OUTPUT, + HICN_INTEREST_HITPIT_NEXT_ERROR_DROP, + HICN_INTEREST_HITPIT_N_NEXT, +} hicn_interest_hitpit_next_t; + +#endif /* // __HICN_INTEREST_HITPIT_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/interest_hitpit_node.c b/hicn-plugin/src/network/interest_hitpit_node.c new file mode 100644 index 000000000..9ebf183c5 --- /dev/null +++ b/hicn-plugin/src/network/interest_hitpit_node.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2017-2020 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 "interest_hitpit.h" +#include "mgmt.h" +#include "parser.h" +#include "data_fwd.h" +#include "infra.h" +#include "strategy.h" +#include "strategy_dpo_ctx.h" +#include "strategy_dpo_manager.h" +#include "state.h" +#include "error.h" +#include "face_db.h" + +/* packet trace format function */ +static u8 *hicn_interest_hitpit_format_trace (u8 * s, va_list * args); + +/* Stats string values */ +static char *hicn_interest_hitpit_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +vlib_node_registration_t hicn_interest_hitpit_node; + +always_inline void drop_packet (u32 * next0); + +/* + * hICN forwarder node for interests hitting the PIT + */ +static uword +hicn_interest_hitpit_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next; + hicn_interest_hitpit_next_t next_index; + hicn_interest_hitpit_runtime_t *rt; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + f64 tnow; + + rt = vlib_node_get_runtime_data (vm, hicn_interest_hitpit_node.index); + + if (PREDICT_FALSE (rt->pitcs == NULL)) + { + rt->pitcs = &hicn_main.pitcs; + } + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + /* Capture time in vpp terms */ + tnow = vlib_time_now (vm); + + while (n_left_from > 0) + { + u32 n_left_to_next; + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *b0; + u8 isv6; + u8 *nameptr; + 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; + hicn_pcs_entry_t *pitp; + u8 dpo_ctx_id0; + u8 found = 0; + int nh_idx; + hicn_face_id_t outface; + hicn_hash_entry_t *hash_entry0; + hicn_buffer_t *hicnb0; + 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->data, CLIB_CACHE_LINE_BYTES, STORE); + } + + /* Dequeue a packet buffer */ + bi0 = from[0]; + from += 1; + n_left_from -= 1; + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + /* Get hicn buffer and state */ + hicnb0 = hicn_get_buffer (b0); + 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); + pitp = hicn_pit_get_data (node0); + dpo_id_t hicn_dpo_id0 = + { dpo_vft0->hicn_dpo_get_type (), 0, 0, dpo_ctx_id0 }; + + /* + * 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))) + { + stats.interests_hash_collision++; + /* Remove lock from the entry */ + hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, hash_entry0, + dpo_vft0, &hicn_dpo_id0); + drop_packet (&next0); + + goto end_processing; + } + /* + * If the entry is expired, remove it no matter of + * the possible cases. + */ + if (tnow > pitp->shared.expire_time) + { + strategy_vft0->hicn_on_interest_timeout (dpo_ctx_id0); + hicn_pcs_delete (rt->pitcs, &pitp, &node0, vm, hash_entry0, + dpo_vft0, &hicn_dpo_id0); + stats.pit_expired_count++; + next0 = HICN_INTEREST_HITPIT_NEXT_STRATEGY; + } + else + { + if ((hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY)) + { + next0 = HICN_INTEREST_HITPIT_NEXT_INTEREST_HITCS; + } + else + { + /* + * Distinguish between aggregation or + * retransmission + */ + + found = + hicn_face_search (hicnb0->face_id, + &(pitp->u.pit.faces)); + + if (found) + { + strategy_vft0->hicn_select_next_hop (dpo_ctx_id0, + &nh_idx, &outface); + /* Retransmission */ + /* + * Prepare the packet for the + * forwarding + */ + next0 = isv6 ? HICN_INTEREST_HITPIT_NEXT_FACE6_OUTPUT : + HICN_INTEREST_HITPIT_NEXT_FACE4_OUTPUT; + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = + outface; + + /* + * Update the egress face in + * the PIT + */ + pitp->u.pit.pe_txnh = nh_idx; + stats.interests_retx++; + } + else + { + hicn_face_db_add_face (hicnb0->face_id, + &pitp->u.pit.faces); + + /* Aggregation */ + drop_packet (&next0); + stats.interests_aggregated++; + } + /* Remove lock from the entry */ + hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, + hash_entry0, dpo_vft0, &hicn_dpo_id0); + + } + } + end_processing: + + /* Maybe trace */ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_interest_hitpit_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = HICN_PKT_TYPE_INTEREST; + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + t->next_index = next0; + } + /* Incr packet counter */ + stats.pkts_processed += 1; + + /* + * 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); + } + u32 pit_int_count = hicn_pit_get_int_count (rt->pitcs); + + + vlib_node_increment_counter (vm, hicn_interest_hitpit_node.index, + HICNFWD_ERROR_PROCESSED, stats.pkts_processed); + vlib_node_increment_counter (vm, hicn_interest_hitpit_node.index, + HICNFWD_ERROR_INTEREST_AGG, + stats.interests_aggregated); + vlib_node_increment_counter (vm, hicn_interest_hitpit_node.index, + HICNFWD_ERROR_INT_RETRANS, + stats.interests_retx); + vlib_node_increment_counter (vm, hicn_interest_hitpit_node.index, + HICNFWD_ERROR_PIT_EXPIRED, + stats.pit_expired_count); + vlib_node_increment_counter (vm, hicn_interest_hitpit_node.index, + HICNFWD_ERROR_HASH_COLL_HASHTB_COUNT, + stats.interests_hash_collision); + + update_node_counter (vm, hicn_interest_hitpit_node.index, + HICNFWD_ERROR_INT_COUNT, pit_int_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn_interest_hitpit_format_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 *); + hicn_interest_hitpit_trace_t *t = + va_arg (*args, hicn_interest_hitpit_trace_t *); + + s = format (s, "INTEREST-HITPIT: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + return (s); +} + +void +drop_packet (u32 * next0) +{ + *next0 = HICN_INTEREST_HITPIT_NEXT_ERROR_DROP; +} + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(hicn_interest_hitpit_node) = +{ + .function = hicn_interest_hitpit_node_fn, + .name = "hicn-interest-hitpit", + .vector_size = sizeof(u32), + .runtime_data_bytes = sizeof(hicn_interest_hitpit_runtime_t), + .format_trace = hicn_interest_hitpit_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(hicn_interest_hitpit_error_strings), + .error_strings = hicn_interest_hitpit_error_strings, + .n_next_nodes = HICN_INTEREST_HITPIT_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = + { + [HICN_INTEREST_HITPIT_NEXT_INTEREST_HITCS] = "hicn-interest-hitcs", + [HICN_INTEREST_HITPIT_NEXT_STRATEGY] = "hicn-strategy", + [HICN_INTEREST_HITPIT_NEXT_FACE4_OUTPUT] = "hicn4-face-output", + [HICN_INTEREST_HITPIT_NEXT_FACE6_OUTPUT] = "hicn6-face-output", + [HICN_INTEREST_HITPIT_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/interest_pcslookup.h b/hicn-plugin/src/network/interest_pcslookup.h new file mode 100644 index 000000000..cbc9dde51 --- /dev/null +++ b/hicn-plugin/src/network/interest_pcslookup.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017-2019 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_INTEREST_PCSLOOKUP_H__ +#define __HICN_INTEREST_PCSLOOKUP_H__ + +#include +#include + +#include "pcs.h" + +/** + * @file interest_pcslookup.h + * + * This is the node encoutered by interest packets after the hicn6-iface-input or + * hicn4-iface-input. This node performs a lookup in the pit and content store and + * if there is a hit in the PIT, the vlib buffer is passed to the hicn-interest-hitcs + * while if there is a hit in the CS the vlib buffer is passed to the + * hicn-interest-hitpit. If there isn't any hit, the vlib buffer is passed to the + * hicn-strategy node. + */ + +/* + * Node context data; we think this is per-thread/instance + */ +typedef struct hicn_interest_pcslookup_runtime_s +{ + int id; + hicn_pit_cs_t *pitcs; +} hicn_interest_pcslookup_runtime_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; +} hicn_interest_pcslookup_trace_t; + +typedef enum +{ + HICN_INTEREST_PCSLOOKUP_NEXT_STRATEGY, + HICN_INTEREST_PCSLOOKUP_NEXT_INTEREST_HITPIT, + HICN_INTEREST_PCSLOOKUP_NEXT_INTEREST_HITCS, + HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP, + HICN_INTEREST_PCSLOOKUP_N_NEXT, +} hicn_interest_pcslookup_next_t; + +#endif /* // __HICN_INTEREST_PCSLOOKUP_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/interest_pcslookup_node.c b/hicn-plugin/src/network/interest_pcslookup_node.c new file mode 100644 index 000000000..6ac2aa3a0 --- /dev/null +++ b/hicn-plugin/src/network/interest_pcslookup_node.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2017-2019 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 "interest_pcslookup.h" +#include "mgmt.h" +#include "parser.h" +#include "infra.h" +#include "strategy_dpo_manager.h" +#include "error.h" +#include "state.h" + +/** + * @FILE This node performs a lookup in the PIT and CS for a received interest packet. + * + * This node passes the packet to the interest-hitpit and interest-hitcs nodes + * when there is a hit in the pit or content store, respectively. + */ + +/* Functions declarations */ + +/* packet trace format function */ +static u8 *hicn_interest_pcslookup_format_trace (u8 * s, va_list * args); + + +/* Stats string values */ +static char *hicn_interest_pcslookup_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +vlib_node_registration_t hicn_interest_pcslookup_node; + +/* + * ICN forwarder node for interests: handling of Interests delivered based on + * ACL. - 1 packet at a time - ipv4/tcp ipv6/tcp + */ +static uword +hicn_interest_pcslookup_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next; + 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); + + if (PREDICT_FALSE (rt->pitcs == NULL)) + { + rt->pitcs = &hicn_main.pitcs; + } + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + u32 n_left_to_next; + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *b0; + u8 isv6; + u8 *nameptr; + u16 namelen; + u32 bi0; + u32 next0 = HICN_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; + u8 is_cs0 = 0; + u8 hash_entry_id = 0; + u8 bucket_is_overflown = 0; + u32 bucket_id = ~0; + + /* 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, STORE); + CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, LOAD); + } + /* Dequeue a packet buffer */ + bi0 = from[0]; + from += 1; + n_left_from -= 1; + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + 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); + stats.pkts_processed++; + + if (PREDICT_FALSE (ret != HICN_ERROR_NONE || + hicn_hashtb_fullhash (nameptr, namelen, + &name_hash) != + HICN_ERROR_NONE)) + { + next0 = HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP; + } + else + { + if (hicn_hashtb_lookup_node (rt->pitcs->pcs_table, nameptr, + namelen, name_hash, + 0 /* is_data */ , &node_id0, + &dpo_ctx_id0, &vft_id0, &is_cs0, + &hash_entry_id, &bucket_id, + &bucket_is_overflown) == + HICN_ERROR_NONE) + { + next0 = + HICN_INTEREST_PCSLOOKUP_NEXT_INTEREST_HITPIT + is_cs0; + } + stats.pkts_interest_count++; + } + + hicn_store_internal_state (b0, name_hash, node_id0, dpo_ctx_id0, + vft_id0, hash_entry_id, bucket_id, + bucket_is_overflown); + + /* Maybe trace */ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_interest_pcslookup_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = HICN_PKT_TYPE_INTEREST; + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + t->next_index = next0; + } + /* + * 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); + } + u32 pit_int_count = hicn_pit_get_int_count (rt->pitcs); + u32 pit_cs_count = hicn_pit_get_cs_count (rt->pitcs); + u32 pcs_ntw_count = hicn_pcs_get_ntw_count (rt->pitcs); + + + vlib_node_increment_counter (vm, hicn_interest_pcslookup_node.index, + HICNFWD_ERROR_PROCESSED, stats.pkts_processed); + + vlib_node_increment_counter (vm, hicn_interest_pcslookup_node.index, + HICNFWD_ERROR_INTERESTS, + stats.pkts_interest_count); + + update_node_counter (vm, hicn_interest_pcslookup_node.index, + HICNFWD_ERROR_INT_COUNT, pit_int_count); + + update_node_counter (vm, hicn_interest_pcslookup_node.index, + HICNFWD_ERROR_CS_COUNT, pit_cs_count); + + update_node_counter (vm, hicn_interest_pcslookup_node.index, + HICNFWD_ERROR_CS_NTW_COUNT, pcs_ntw_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn_interest_pcslookup_format_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 *); + hicn_interest_pcslookup_trace_t *t = + va_arg (*args, hicn_interest_pcslookup_trace_t *); + + s = format (s, "INTEREST_PCSLOOKUP: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + return (s); +} + + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(hicn_interest_pcslookup_node) = +{ + .function = hicn_interest_pcslookup_node_fn, + .name = "hicn-interest-pcslookup", + .vector_size = sizeof(u32), + .runtime_data_bytes = sizeof(hicn_interest_pcslookup_runtime_t), + .format_trace = hicn_interest_pcslookup_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(hicn_interest_pcslookup_error_strings), + .error_strings = hicn_interest_pcslookup_error_strings, + .n_next_nodes = HICN_INTEREST_PCSLOOKUP_N_NEXT, + .next_nodes = + { + [HICN_INTEREST_PCSLOOKUP_NEXT_STRATEGY] = "hicn-strategy", + [HICN_INTEREST_PCSLOOKUP_NEXT_INTEREST_HITPIT] = "hicn-interest-hitpit", + [HICN_INTEREST_PCSLOOKUP_NEXT_INTEREST_HITCS] = "hicn-interest-hitcs", + [HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/mapme.h b/hicn-plugin/src/network/mapme.h new file mode 100644 index 000000000..17bd9a766 --- /dev/null +++ b/hicn-plugin/src/network/mapme.h @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2017-2020 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_MAPME__ +#define __HICN_MAPME__ + +#include +#include +#include + +#include "hicn.h" +#include "route.h" +#include "strategy_dpo_ctx.h" +#include "strategy_dpo_manager.h" // dpo_is_hicn + +/** + * @file + * + * @brief Mapme + * + * Mapme implementation follows the "Anchorless mobility through hICN" document + * specification. In particular, the implementation is made of: + * - two internal nodes: hicn-mapme-ctrl and hicn-mapme-ack. The former processes + * IU and the latter IU acknowledgment. + * - a process node, mapme-eventmgr-process, that is signaled every time a face is + * added or deleted, as well as when a new next hop is added to a fib entry as a + * result of a mobility event. + * + * TFIB implementation is done as an extension of an hICN fib entry. In particular, + * the list of next hops hold the list of next hops in the tfib as well (stored at the + * end of the list of regualt next hops). Mapme implementation follows the hICN vrf + * implementation and consider the vrf 0 (default fib) as the control-plane fib to + * update every time a new next hop must be added or removed. + */ + + +#define HICN_MAPME_ALLOW_LOCATORS 1 + +//#define HICN_MAPME_NOTIFICATIONS 1 + +#define NOT_A_NOTIFICATION false +#define TIMER_NO_REPEAT false + +#define INVALID_SEQ 0 + +STATIC_ASSERT (sizeof(u32) == sizeof(seq_t), + "seq_t is not 4 bytes"); + +typedef struct hicn_mapme_conf_s +{ + hicn_mapme_conf_t conf; + bool remove_dpo; // FIXME used ? + + vlib_main_t *vm; + vlib_log_class_t log_class; +} hicn_mapme_main_t; + +/** + * @brief List of event to signat to the procesing node (eventmgr) + */ +#define foreach_hicn_mapme_event \ + _(FACE_ADD) \ + _(FACE_DEL) \ + _(FACE_APP_ADD) \ + _(FACE_APP_DEL) \ + _(FACE_NH_SET) \ + _(FACE_NH_ADD) \ + _(FACE_PH_ADD) \ + _(FACE_PH_DEL) + +typedef enum +{ +#define _(a) HICN_MAPME_EVENT_##a, + foreach_hicn_mapme_event +#undef _ +} hicn_mapme_event_t; + +typedef hicn_dpo_ctx_t hicn_mapme_tfib_t; + +/* + * Ideally we might need to care about alignment, but this struct is only + * used for casting hicn_dpo_ctx_t. + * + * See otherwise vnet/dpo/dpo.h + */ + +STATIC_ASSERT (sizeof (hicn_mapme_tfib_t) <= sizeof (hicn_dpo_ctx_t), + "hicn_mapme_tfib_t is greater than hicn_dpo_ctx_t"); + +#define TFIB(dpo_ctx) ((hicn_mapme_tfib_t*)(dpo_ctx)) + +static_always_inline int +hicn_mapme_nh_set (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) +{ + hicn_dpo_ctx_t * strategy_ctx = (hicn_dpo_ctx_t *)tfib; + const fib_prefix_t * prefix = fib_entry_get_prefix(strategy_ctx->fib_entry_index); + + u32 n_entries = tfib->entry_count; + /* Remove all the existing next hops and set the new one */ + for (int i = 0; i < n_entries; i++) + { + hicn_face_t * face = hicn_dpoi_get_from_idx(strategy_ctx->next_hops[0]); + ip_adjacency_t * adj = adj_get (face->dpo.dpoi_index); + ip_nh_del_helper(face->dpo.dpoi_proto, prefix, &adj->sub_type.nbr.next_hop, face->sw_if); + } + hicn_face_t * face = hicn_dpoi_get_from_idx(face_id); + ip_nh_add_helper(face->dpo.dpoi_proto, prefix, &face->nat_addr, face->sw_if); + return 0; +} + +/** + * @brief Add a next hop iif it is not already a next hops + */ +static_always_inline int +hicn_mapme_nh_add (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) +{ + for (u8 pos = 0; pos < tfib->entry_count; pos++) + if (tfib->next_hops[pos] == face_id) + return 0; + + /* Add the next hop in the vrf 0 which will add it to the entry in the hICN vrf */ + hicn_dpo_ctx_t * strategy_ctx = (hicn_dpo_ctx_t *)tfib; + const fib_prefix_t * prefix = fib_entry_get_prefix(strategy_ctx->fib_entry_index); + hicn_face_t * face = hicn_dpoi_get_from_idx(face_id); + ip_nh_add_helper(face->dpo.dpoi_proto, prefix, &face->nat_addr, face->sw_if); + + return 0; +} + +/** + * Add a 'previous' hop to the TFIB + * + * XXX we should have the for look in the reverse order for simpler code. + */ +static_always_inline int +hicn_mapme_tfib_add (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) +{ + u8 pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; + + //XXX don 't add if it already exist + // eg.an old IU received on a face on which we are retransmitting + for (u8 pos2 = pos; pos2 < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos2++) + if (tfib->next_hops[pos2] == face_id) + return 0; + + //Make sure we have enough room + if (pos <= tfib->entry_count) + return -1; + + tfib->next_hops[pos - 1] = face_id; + tfib->tfib_entry_count++; + + /* + * Take a lock on the face as if it will be removed from the next_hops a + * lock will be removed. + */ + hicn_face_lock_with_id(face_id); + + return 0; +} + +static_always_inline int +hicn_mapme_tfib_clear (hicn_mapme_tfib_t * tfib) +{ + hicn_face_id_t invalid = NEXT_HOP_INVALID; + /* + * We need to do a linear scan of TFIB entries to find the one to + * remove + */ + u8 start_pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; + u8 pos = ~0; + for (pos = start_pos; pos < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos++) + { + hicn_face_unlock_with_id (tfib->next_hops[pos]); + tfib->next_hops[pos] = invalid; + break; + } + + tfib->tfib_entry_count = 0; + + return 0; +} + +static_always_inline int +hicn_mapme_tfib_del (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id) +{ + hicn_face_id_t invalid = NEXT_HOP_INVALID; + /* + * We need to do a linear scan of TFIB entries to find the one to + * remove + */ + u8 start_pos = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; + u8 pos = ~0; + for (pos = start_pos; pos < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos++) + if (tfib->next_hops[pos] == face_id) + { + hicn_face_unlock_with_id (tfib->next_hops[pos]); + tfib->next_hops[pos] = invalid; + break; + } + if (pos == HICN_PARAM_FIB_ENTRY_NHOPS_MAX) + /* Not found */ + return -1; + + tfib->tfib_entry_count--; + + /* Likely we won't receive a new IU twice from the same face */ + if (PREDICT_TRUE (pos > start_pos)) + memmove (tfib->next_hops + start_pos +1 , tfib->next_hops + start_pos, + (pos - start_pos) * sizeof (hicn_face_id_t)); + + return 0; +} + +/** + * @brief Performs an Exact Prefix Match lookup on the FIB + * @returns the corresponding DPO (hICN or IP LB), or NULL + */ +static_always_inline + dpo_id_t * fib_epm_lookup (ip46_address_t * addr, u8 plen) +{ + fib_prefix_t fib_pfx; + fib_node_index_t fib_entry_index; + u32 fib_index; + dpo_id_t *dpo_id; + load_balance_t *lb; + + const dpo_id_t *load_balance_dpo_id; + + /* At this point the face exists in the face table */ + fib_prefix_from_ip46_addr (addr, &fib_pfx); + fib_pfx.fp_len = plen; + + /* Check if the route already exist in the fib : EPM */ + fib_index = fib_table_find (fib_pfx.fp_proto, HICN_FIB_TABLE); + + fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx); + if (fib_entry_index == FIB_NODE_INDEX_INVALID) + return NULL; + + load_balance_dpo_id = fib_entry_contribute_ip_forwarding (fib_entry_index); + + /* The dpo is not a load balance dpo as expected */ + if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) + return NULL; + + /* former_dpo_id is a load_balance dpo */ + lb = load_balance_get (load_balance_dpo_id->dpoi_index); + + /* Check if there is only one bucket */ + + /* + * We now distinguish the case where we have an hICN route (the + * regular case), and the case where we have an IP route, to be able + * to apply MAP-Me mechanisms even to a locator IP address. + */ + + for (int i = 0; i < lb->lb_n_buckets; i++) + { + /* un-const */ + dpo_id = (dpo_id_t *) load_balance_get_bucket_i (lb, i); + + if (dpo_is_hicn (dpo_id)) + return dpo_id; + } + + /* un-const */ + return (dpo_id_t *) load_balance_dpo_id; +} + +/* DPO types */ + +extern dpo_type_t hicn_face_udp_type; +extern dpo_type_t hicn_face_ip_type; + +/* VLIB EDGE IDs */ + +/* in faces/ip/face_ip.c */ +extern u32 strategy_face_ip4_vlib_edge; +extern u32 strategy_face_ip6_vlib_edge; +/* in faces/udp/face_udp.c */ +extern u32 strategy_face_udp4_vlib_edge; +extern u32 strategy_face_udp6_vlib_edge; + + +/** + * @brief Returns the next hop vlib edge on which we can send an Interest packet. + * + * This is both used to preprocess a dpo that will be stored as a next hop in the FIB, and to determine on which node to send an Interest Update. + */ +always_inline u32 +hicn_mapme_get_dpo_vlib_edge (dpo_id_t * dpo) +{ + if (dpo->dpoi_type == hicn_face_ip_type) + { + switch (dpo->dpoi_proto) + { + case DPO_PROTO_IP4: + return strategy_face_ip4_vlib_edge; + case DPO_PROTO_IP6: + return strategy_face_ip6_vlib_edge; + default: + return ~0; + } + } + else if (dpo->dpoi_type == hicn_face_udp_type) + { + switch (dpo->dpoi_proto) + { + case DPO_PROTO_IP4: + return strategy_face_udp4_vlib_edge; + case DPO_PROTO_IP6: + return strategy_face_udp6_vlib_edge; + default: + return ~0; + } + } + else + { + return ~0; + } +} + +/** + * @brief Returns the next hop node on which we can send an Update packet + */ +always_inline char * +hicn_mapme_get_dpo_face_node (hicn_face_id_t face_id) +{ + hicn_face_t * face = hicn_dpoi_get_from_idx(face_id); + + switch (face->dpo.dpoi_proto) + { + case DPO_PROTO_IP4: + return "hicn4-face-output"; + case DPO_PROTO_IP6: + return "hicn6-face-output"; + default: + return NULL; + } +} + +#define DEBUG(...) //vlib_log_debug(mapme_main.log_class, __VA_ARGS__) +#define WARN(...) //vlib_log_warn(mapme_main.log_class, __VA_ARGS__) +#define ERROR(...) //vlib_log_err(mapme_main.log_class, __VA_ARGS__) + +#endif /* __HICN_MAPME__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/mapme_ack.h b/hicn-plugin/src/network/mapme_ack.h new file mode 100644 index 000000000..821baf203 --- /dev/null +++ b/hicn-plugin/src/network/mapme_ack.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017-2019 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. + */ + +/* + * Copyright (c) 2017-2019 by Cisco Systems Inc. All Rights Reserved. + * + */ + +#ifndef HICN_MAPME_ACK_H +#define HICN_MAPME_ACK_H + +#include +#include + +/** + * @file + * + */ + +/* Node context data */ +typedef struct hicn_mapme_ack_runtime_s +{ + int id; +} hicn_mapme_ack_runtime_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; +} hicn_mapme_ack_trace_t; + +typedef enum +{ + HICN_MAPME_ACK_NEXT_ERROR_DROP, + HICN_MAPME_ACK_N_NEXT, +} hicn_mapme_ack_next_t; + +#endif /* HICN_MAPME_ACK_H */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/mapme_ack_node.c b/hicn-plugin/src/network/mapme_ack_node.c new file mode 100644 index 000000000..f26895d20 --- /dev/null +++ b/hicn-plugin/src/network/mapme_ack_node.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2017-2020 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 "hicn.h" +#include "mapme.h" +#include "mapme_ack.h" +#include "mapme_eventmgr.h" +#include "mgmt.h" +#include "parser.h" +#include "data_fwd.h" +#include "infra.h" +#include "strategy_dpo_manager.h" +#include "error.h" +#include "state.h" + +extern hicn_mapme_main_t mapme_main; + +/* packet trace format function */ +static u8 *hicn_mapme_ack_format_trace (u8 * s, va_list * args); + + +/* Stats string values */ +static char *hicn_mapme_ack_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +/* + * @brief Process incoming ack messages (Interest Update Ack) + * @param vm vlib main data structure + * @param b Control packet (IU) + * @param face_id Ingress face id + */ +bool +hicn_mapme_process_ack (vlib_main_t * vm, vlib_buffer_t * b, + hicn_face_id_t in_face) +{ + seq_t fib_seq; + const dpo_id_t *dpo; + hicn_prefix_t prefix; + mapme_params_t params; + int rc; + + /* Parse incoming message */ + rc = + hicn_mapme_parse_packet (vlib_buffer_get_current (b), &prefix, ¶ms); + if (rc < 0) + goto ERR_PARSE; + + /* if (params.seq == INVALID_SEQ) */ + /* { */ + /* DEBUG ("Invalid sequence number found in IU"); */ + /* return true; */ + /* } */ + + dpo = fib_epm_lookup (&(prefix.name), prefix.len); + if (!dpo) + { + DEBUG ("Ignored ACK for non-existing FIB entry. Ignored."); + return true; + + } + + /* We are only expecting ACKs for hICN DPOs */ + ASSERT (dpo_is_hicn (dpo)); + + hicn_mapme_tfib_t *tfib = + TFIB (hicn_strategy_dpo_ctx_get (dpo->dpoi_index)); + + if (tfib == NULL) + { + WARN ("Unable to get strategy ctx."); + return false; + } + + fib_seq = tfib->seq; + + /* + * As we always retransmit IU with the latest seq, we are not interested in + * ACKs with inferior seq + */ + if (params.seq < fib_seq) + { + DEBUG ("Ignored ACK for low seq"); + return true; + } + + hicn_mapme_tfib_del (tfib, in_face); + + /* + * Is the ingress face in TFIB ? if so, remove it, otherwise it might be a + * duplicate + */ + retx_t *retx = vlib_process_signal_event_data (vm, + hicn_mapme_eventmgr_process_node. + index, + HICN_MAPME_EVENT_FACE_PH_DEL, + 1, + sizeof (retx_t)); + *retx = (retx_t) + { + .prefix = prefix, + .dpo = *dpo + }; + + return true; + +ERR_PARSE: + return false; +} + +vlib_node_registration_t hicn_mapme_ack_node; + +static uword +hicn_mapme_ack_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + hicn_buffer_t *hb; + hicn_mapme_ack_next_t next_index; + u32 n_left_from, *from, *to_next; + n_left_from = frame->n_vectors; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + while (n_left_from > 0) // buffers in the current frame + { + u32 n_left_to_next; + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 bi0; + vlib_buffer_t *b0; + u32 next0 = HICN_MAPME_ACK_NEXT_ERROR_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); + + vlib_cli_output (vm, "Received IUAck"); + hb = hicn_get_buffer (b0); + hicn_mapme_process_ack (vm, b0, hb->face_id); + + /* Single loop: process 1 packet here */ + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) + && (b0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_mapme_ack_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->sw_if_index = sw_if_index0; + t->next_index = next0; + } + /* $$$$$ Done processing 1 packet here $$$$$ */ + + /* 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_mapme_ack_node.index, +// HICN_MAPME_ACK_ERROR_SWAPPED, pkts_swapped); + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn_mapme_ack_format_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 *); + hicn_mapme_ack_trace_t *t = va_arg (*args, hicn_mapme_ack_trace_t *); + + s = format (s, "MAPME_ACK: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + return (s); +} + + +/* + * Node registration for the MAP-Me node processing special interests + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn_mapme_ack_node) = +{ + .function = hicn_mapme_ack_node_fn, + .name = "hicn-mapme-ack", + .vector_size = sizeof (u32), + .runtime_data_bytes = sizeof (hicn_mapme_ack_runtime_t), + .format_trace = hicn_mapme_ack_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN (hicn_mapme_ack_error_strings), + .error_strings = hicn_mapme_ack_error_strings, + .n_next_nodes = HICN_MAPME_ACK_N_NEXT, + .next_nodes = + { + [HICN_MAPME_ACK_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/mapme_ctrl.h b/hicn-plugin/src/network/mapme_ctrl.h new file mode 100644 index 000000000..9af4beccc --- /dev/null +++ b/hicn-plugin/src/network/mapme_ctrl.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017-2020 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. + */ + +/* + * Copyright (c) 2017-2019 by Cisco Systems Inc. All Rights Reserved. + * + */ + +#ifndef HICN_MAPME_CTRL_H +#define HICN_MAPME_CTRL_H + +#include +#include + +/** + * @file mapme_ctrl.h + * + */ + +/* Node context data */ +typedef struct hicn_mapme_ctrl_runtime_s +{ + int id; +} hicn_mapme_ctrl_runtime_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; +} hicn_mapme_ctrl_trace_t; + +typedef enum +{ + HICN_MAPME_CTRL_NEXT_IP4_OUTPUT, + HICN_MAPME_CTRL_NEXT_IP6_OUTPUT, + HICN_MAPME_CTRL_NEXT_ERROR_DROP, + HICN_MAPME_CTRL_N_NEXT, +} hicn_mapme_ctrl_next_t; +/** + * @brief Returns the next hop node on which we can send an ACK packet + */ +always_inline hicn_mapme_ctrl_next_t +hicn_mapme_ctrl_get_iface_node (hicn_face_id_t face_id) +{ + hicn_face_t * face = hicn_dpoi_get_from_idx(face_id); + + switch (face->dpo.dpoi_proto) + { + case DPO_PROTO_IP4: + return HICN_MAPME_CTRL_NEXT_IP4_OUTPUT; + case DPO_PROTO_IP6: + return HICN_MAPME_CTRL_NEXT_IP6_OUTPUT; + default: + return HICN_MAPME_CTRL_NEXT_ERROR_DROP; + } +} + +#endif /* HICN_MAPME_CTRL_H */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/mapme_ctrl_node.c b/hicn-plugin/src/network/mapme_ctrl_node.c new file mode 100644 index 000000000..a0be2be1d --- /dev/null +++ b/hicn-plugin/src/network/mapme_ctrl_node.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2017-2020 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. + */ + +/* + * This node processses MAP-Me control messages. + */ +#include +#include + +#include "hicn.h" +#include "mapme.h" +#include "mapme_ctrl.h" +#include "mapme_eventmgr.h" +#include "mgmt.h" +#include "parser.h" +#include "infra.h" +#include "strategy_dpo_manager.h" +#include "strategy_dpo_ctx.h" +#include "error.h" +#include "state.h" + +extern hicn_mapme_main_t mapme_main; + +#define MS2NS(x) x * 1000000 + +/* Functions declarations */ + +/* packet trace format function */ +static u8 *hicn_mapme_ctrl_format_trace (u8 * s, va_list * args); + + +/* Stats string values */ +static char *hicn_mapme_ctrl_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +/* + * @brief Process incoming control messages (Interest Update) + * @param vm vlib main data structure + * @param b Control packet (IU) + * @param face_id Ingress face id + * + * NOTE: + * - this function answers locally to the IU interest by replying with a Ack + * (Data) packet, unless in case of outdated information, in which we can + * consider the interest is dropped, and another IU (aka ICMP error) is sent so + * that retransmissions stop. + */ +static_always_inline bool +hicn_mapme_process_ctrl (vlib_main_t * vm, vlib_buffer_t * b, + hicn_face_id_t in_face_id) +{ + seq_t fib_seq; + const dpo_id_t *dpo; + hicn_prefix_t prefix; + mapme_params_t params; + int rc; + + /* Parse incoming message */ + rc = + hicn_mapme_parse_packet (vlib_buffer_get_current (b), &prefix, ¶ms); + if (rc < 0) + goto ERR_PARSE; + + vlib_cli_output (vm, "IU - type:%d seq:%d len:%d", params.type, params.seq, + prefix.len); + + /* if (params.seq == INVALID_SEQ) */ + /* { */ + /* vlib_log_warn (mapme_main.log_class, */ + /* "Invalid sequence number found in IU"); */ + + /* return true; */ + /* } */ + + /* We forge the ACK which we be the packet forwarded by the node */ + hicn_mapme_create_ack (vlib_buffer_get_current (b), ¶ms); + + dpo = fib_epm_lookup (&prefix.name, prefix.len); + if (!dpo) + { +#ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY + /* + * This might happen for a node hosting a producer which has moved. + * Destroying the face has led to removing all corresponding FIB + * entries. In that case, we need to correctly restore the FIB entries. + */ + DEBUG ("Re-creating FIB entry with next hop on connection") +#error "not implemented" +#else + //ERROR("Received IU for non-existing FIB entry"); + return false; +#endif /* HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY */ + + } + +#ifdef HICN_MAPME_ALLOW_LOCATORS + if (!dpo_is_hicn ((dpo))) + { + /* We have an IP DPO */ + WARN ("Not implemented yet."); + return false; + } +#endif + + /* Process the hICN DPO */ + hicn_mapme_tfib_t *tfib = + TFIB (hicn_strategy_dpo_ctx_get (dpo->dpoi_index)); + + if (tfib == NULL) + { + WARN ("Unable to get strategy ctx."); + return false; + } + + fib_seq = tfib->seq; + + if (params.seq > fib_seq) + { + DEBUG + ("Higher sequence number than FIB %d > %d, updating seq and next hops", + params.seq, fib_seq); + + /* This has to be done first to allow processing ack */ + tfib->seq = params.seq; + + // in_face and next_hops are face_id_t + + /* Remove ingress face from TFIB in case it was present */ + hicn_mapme_tfib_del (tfib, in_face_id); + + /* Move next hops to TFIB... but in_face... */ + for (u8 pos = 0; pos < tfib->entry_count; pos++) + { + hicn_face_t * face = hicn_dpoi_get_from_idx(tfib->next_hops[pos]); + hicn_face_t * in_face = hicn_dpoi_get_from_idx(in_face_id); + if (dpo_is_adj(&face->dpo)) + { + ip_adjacency_t * adj = adj_get (dpo->dpoi_index); + if (ip46_address_cmp(&(adj->sub_type.nbr.next_hop), &(in_face->nat_addr))== 0) + break; + } + DEBUG + ("Adding nexthop to the tfib, dpo index in_face %d, dpo index tfib %d", + in_face_id, tfib->next_hops[pos]); + hicn_mapme_tfib_add (tfib, tfib->next_hops[pos]); + } + + hicn_mapme_nh_set (tfib, in_face_id); + + /* We transmit both the prefix and the full dpo (type will be needed to pick the right transmit node */ + retx_t *retx = vlib_process_signal_event_data (vm, + hicn_mapme_eventmgr_process_node. + index, + HICN_MAPME_EVENT_FACE_NH_SET, + 1, + sizeof (retx_t)); + *retx = (retx_t) + { + .prefix = prefix, + .dpo = *dpo + }; + + } + else if (params.seq == fib_seq) + { + DEBUG ("Same sequence number than FIB %d > %d, adding next hop", + params.seq, fib_seq); + + /* Remove ingress face from TFIB in case it was present */ + hicn_mapme_tfib_del (tfib, in_face_id); + + /* Add ingress face to next hops */ + hicn_mapme_nh_add (tfib, in_face_id); + + /* Multipath, multihoming, multiple producers or duplicate interest */ + retx_t *retx = vlib_process_signal_event_data (vm, + hicn_mapme_eventmgr_process_node. + index, + HICN_MAPME_EVENT_FACE_NH_ADD, + 1, + sizeof (retx_t)); + *retx = (retx_t) + { + .prefix = prefix, + .dpo = *dpo + }; + } + else // params.seq < fib_seq + { + /* + * face is propagating outdated information, we can just consider it as a + * prevHops + */ + hicn_mapme_tfib_add (tfib, in_face_id); + + retx_t *retx = vlib_process_signal_event_data (vm, + hicn_mapme_eventmgr_process_node. + index, + HICN_MAPME_EVENT_FACE_PH_ADD, + 1, + sizeof (retx_t)); + *retx = (retx_t) + { + .prefix = prefix, + .dpo = *dpo + }; + } + + /* We just raise events, the event_mgr is in charge of forging packet. */ + + return true; + +//ERR_ACK_CREATE: +ERR_PARSE: + return false; +} + +vlib_node_registration_t hicn_mapme_ctrl_node; + +static uword +hicn_mapme_ctrl_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + hicn_buffer_t *hb; + hicn_mapme_ctrl_next_t next_index; + u32 n_left_from, *from, *to_next; + n_left_from = frame->n_vectors; + //hicn_face_id_t in_face; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + while (n_left_from > 0) // buffers in the current frame + { + u32 n_left_to_next; + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 bi0; + vlib_buffer_t *b0; + + /* 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); + hb = hicn_get_buffer (b0); + + /* This determines the next node on which the ack will be sent back */ + u32 next0 = hicn_mapme_ctrl_get_iface_node (hb->face_id); + + hicn_mapme_process_ctrl (vm, b0, hb->face_id); + + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = hb->face_id; + + 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_mapme_ctrl_node.index, + // HICN_MAPME_CTRL_ERROR_SWAPPED, pkts_swapped); + return frame->n_vectors; +} + +/* packet trace format function */ +static u8 * +hicn_mapme_ctrl_format_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 *); + hicn_mapme_ctrl_trace_t *t = va_arg (*args, hicn_mapme_ctrl_trace_t *); + + s = format (s, "MAPME_CTRL: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + return (s); +} + + +/* + * Node registration for the MAP-Me node processing special interests + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn_mapme_ctrl_node) = +{ + .function = hicn_mapme_ctrl_node_fn, + .name = "hicn-mapme-ctrl", + .vector_size = sizeof (u32), + .runtime_data_bytes = sizeof (hicn_mapme_ctrl_runtime_t), + .format_trace = hicn_mapme_ctrl_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN (hicn_mapme_ctrl_error_strings), + .error_strings = hicn_mapme_ctrl_error_strings, + .n_next_nodes = HICN_MAPME_CTRL_N_NEXT, + .next_nodes = + { + /* + * Control packets are not forwarded by this node, but sent by the Event + * Manager. This node is only responsible for sending ACK back, + * Acks are like data packets are output on iface's + */ + [HICN_MAPME_CTRL_NEXT_IP4_OUTPUT] = "hicn4-iface-output", + [HICN_MAPME_CTRL_NEXT_IP6_OUTPUT] = "hicn6-iface-output", + [HICN_MAPME_CTRL_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/mapme_eventmgr.c b/hicn-plugin/src/network/mapme_eventmgr.c new file mode 100644 index 000000000..d8b7562f8 --- /dev/null +++ b/hicn-plugin/src/network/mapme_eventmgr.c @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2017-2020 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 "hicn.h" +#include "strategy_dpo_ctx.h" +#include "mapme.h" +#include "mapme_eventmgr.h" +#include "strategies/dpo_mw.h" + +#include +#include + +#define DEFAULT_TIMEOUT 1.0 /* s */ + +hicn_mapme_main_t mapme_main; + +hicn_prefix_t *retx_pool; +uword *retx_hash; + +void +hicn_mapme_init (vlib_main_t * vm) +{ + mapme_main.vm = vm; + mapme_main.log_class = vlib_log_register_class ("hicn_mapme", 0); +} + +/* borrowed from vnet/fib/ip4_fib.c */ + +typedef struct ip4_fib_show_walk_ctx_t_ +{ + fib_node_index_t *ifsw_indicies; +} ip4_fib_show_walk_ctx_t; + +static fib_table_walk_rc_t +ip4_fib_show_walk_cb (fib_node_index_t fib_entry_index, void *arg) +{ + ip4_fib_show_walk_ctx_t *ctx = arg; + + vec_add1 (ctx->ifsw_indicies, fib_entry_index); + + return (FIB_TABLE_WALK_CONTINUE); +} + +/* borrowed from vnet/fib/ip6_fib.c */ + +typedef struct ip6_fib_show_ctx_t_ +{ + fib_node_index_t *entries; +} ip6_fib_show_ctx_t; + +static fib_table_walk_rc_t +ip6_fib_table_show_walk (fib_node_index_t fib_entry_index, void *arg) +{ + ip6_fib_show_ctx_t *ctx = arg; + + vec_add1 (ctx->entries, fib_entry_index); + + return (FIB_TABLE_WALK_CONTINUE); +} + +void +hicn_mapme_process_fib_entry (vlib_main_t * vm, hicn_face_id_t face, + const fib_node_index_t * fib_entry_index) +{ + const dpo_id_t *load_balance_dpo_id; + load_balance_t *lb; + dpo_id_t *dpo_id; + fib_entry_t *fib_entry; + + load_balance_dpo_id = fib_entry_contribute_ip_forwarding (*fib_entry_index); + + /* The dpo is not a load balance dpo as expected */ + if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) + return; + + /* former_dpo_id is a load_balance dpo */ + lb = load_balance_get (load_balance_dpo_id->dpoi_index); + + for (int i = 0; i < lb->lb_n_buckets; i++) + { + /* un-const */ + dpo_id = (dpo_id_t *) load_balance_get_bucket_i (lb, i); + + if (dpo_is_hicn (dpo_id)) + { + fib_entry = fib_entry_get (*fib_entry_index); + vlib_cli_output (vm, "set face pending %U", format_fib_prefix, + &fib_entry->fe_prefix); + } + } +} + +void +hicn_mapme_process_ip4_fib (vlib_main_t * vm, hicn_face_id_t face) +{ + ip4_main_t *im4 = &ip4_main; + fib_table_t *fib_table; + int table_id = -1, fib_index = ~0; + + /* *INDENT-OFF* */ + pool_foreach (fib_table, im4->fibs, + ({ + ip4_fib_t *fib = pool_elt_at_index(im4->v4_fibs, fib_table->ft_index); + + if (table_id >= 0 && table_id != (int)fib->table_id) + continue; + if (fib_index != ~0 && fib_index != (int)fib->index) + continue; + + fib_node_index_t *fib_entry_index; + ip4_fib_show_walk_ctx_t ctx = { + .ifsw_indicies = NULL, + }; + + ip4_fib_table_walk(fib, ip4_fib_show_walk_cb, &ctx); + //vec_sort_with_function(ctx.ifsw_indicies, fib_entry_cmp_for_sort); + + vec_foreach(fib_entry_index, ctx.ifsw_indicies) + { + hicn_mapme_process_fib_entry(vm, face, fib_entry_index); + } + + vec_free(ctx.ifsw_indicies); + })); + /* *INDENT-ON* */ +} + +void +hicn_mapme_process_ip6_fib (vlib_main_t * vm, hicn_face_id_t face) +{ + /* Walk IPv6 FIB */ + ip6_main_t *im6 = &ip6_main; + fib_table_t *fib_table; + ip6_fib_t *fib; + int table_id = -1, fib_index = ~0; + + /* *INDENT-OFF* */ + pool_foreach (fib_table, im6->fibs, + ({ + fib = pool_elt_at_index(im6->v6_fibs, fib_table->ft_index); + + if (table_id >= 0 && table_id != (int)fib->table_id) + continue; + if (fib_index != ~0 && fib_index != (int)fib->index) + continue; + if (fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL) + continue; + + fib_node_index_t *fib_entry_index; + ip6_fib_show_ctx_t ctx = { + .entries = NULL, + }; + + ip6_fib_table_walk(fib->index, ip6_fib_table_show_walk, &ctx); + //vec_sort_with_function(ctx.entries, fib_entry_cmp_for_sort); + + vec_foreach(fib_entry_index, ctx.entries) + { + hicn_mapme_process_fib_entry(vm, face, fib_entry_index); + } + + vec_free(ctx.entries); + + })); + /* *INDENT-ON* */ +} + + +/** + * Callback called everytime a new face is created (not including app faces) + */ +void +hicn_mapme_on_face_added (vlib_main_t * vm, hicn_face_id_t face) +{ + hicn_mapme_process_ip4_fib (vm, face); + hicn_mapme_process_ip6_fib (vm, face); +} + +/* + * We need a retransmission pool holding all necessary information for crafting + * special interests, thus including both the DPO and the prefix associated to + * it. + */ +#define NUM_RETX_ENTRIES 100 +#define NUM_RETX_SLOT 2 +#define NEXT_SLOT(cur) (1-cur) +#define CUR retx_array[cur] +#define NXT retx_array[NEXT_SLOT(cur)] +#define CURLEN retx_len[cur] +#define NXTLEN retx_len[NEXT_SLOT(cur)] + +static_always_inline void * +get_packet_buffer (vlib_main_t * vm, u32 node_index, u32 dpoi_index, + ip46_address_t * addr, hicn_type_t type) +{ + vlib_frame_t *f; + vlib_buffer_t *b; // for newly created packet + u32 *to_next; + u32 bi; + u8 *buffer; + + if (vlib_buffer_alloc (vm, &bi, 1) != 1) + { + clib_warning ("buffer allocation failure"); + return NULL; + } + + /* Create a new packet from scratch */ + b = vlib_get_buffer (vm, bi); + ASSERT (b->current_data == 0); + + /* Face information for next hop node index */ + vnet_buffer (b)->ip.adj_index[VLIB_TX] = dpoi_index; + hicn_get_buffer (b)->type = type; + + /* Enqueue the packet right now */ + f = vlib_get_frame_to_node (vm, node_index); + to_next = vlib_frame_vector_args (f); + to_next[0] = bi; + f->n_vectors = 1; + vlib_put_frame_to_node (vm, node_index, f); + + // pointer to IP layer ? do we need to prepare for ethernet ??? + buffer = vlib_buffer_get_current (b); + b->current_length = + (type.l1 == IPPROTO_IPV6) ? HICN_MAPME_V6_HDRLEN : HICN_MAPME_V4_HDRLEN; + + return buffer; +} + +static_always_inline bool +hicn_mapme_send_message (vlib_main_t * vm, const hicn_prefix_t * prefix, + mapme_params_t * params, hicn_face_id_t face) +{ + size_t n; + + /* This should be retrieved from face information */ + DEBUG ("Retransmission for prefix %U seq=%d", format_ip46_address, + &prefix->name, IP46_TYPE_ANY, params->seq); + + char *node_name = hicn_mapme_get_dpo_face_node (face); + if (!node_name) + { + clib_warning + ("Could not determine next node for sending MAP-Me packet"); + return false; + } + + vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) node_name); + u32 node_index = node->index; + + u8 *buffer = get_packet_buffer (vm, node_index, face, + (ip46_address_t *) prefix, + (params->protocol == + IPPROTO_IPV6) ? HICN_TYPE_IPV6_ICMP : + HICN_TYPE_IPV4_ICMP); + n = hicn_mapme_create_packet (buffer, prefix, params); + if (n <= 0) + { + clib_warning ("Could not create MAP-Me packet"); + return false; + } + + return true; +} + +static_always_inline void +hicn_mapme_send_updates (vlib_main_t * vm, hicn_prefix_t * prefix, + dpo_id_t dpo, bool send_all) +{ + hicn_mapme_tfib_t *tfib = TFIB (hicn_strategy_dpo_ctx_get (dpo.dpoi_index)); + if (!tfib) + { + DEBUG ("NULL TFIB entry id=%d", dpo.dpoi_index); + return; + } + + u8 tfib_last_idx = HICN_PARAM_FIB_ENTRY_NHOPS_MAX - tfib->tfib_entry_count; + + mapme_params_t params = { + .protocol = ip46_address_is_ip4 (&prefix->name) + ? IPPROTO_IP : IPPROTO_IPV6, + .type = UPDATE, + .seq = tfib->seq, + }; + + if (send_all) + { + for (u8 pos = tfib_last_idx; pos < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; + pos++) + { + hicn_mapme_send_message (vm, prefix, ¶ms, + tfib->next_hops[pos]); + } + } + else + { + hicn_mapme_send_message (vm, prefix, ¶ms, + tfib->next_hops[tfib_last_idx]); + } +} + +static uword +hicn_mapme_eventmgr_process (vlib_main_t * vm, + vlib_node_runtime_t * rt, vlib_frame_t * f) +{ + f64 timeout = 0; /* By default, no timer is run */ + f64 current_time, due_time; + u8 idle = 0; + + retx_t retx_array[NUM_RETX_SLOT][NUM_RETX_ENTRIES]; + memset (retx_array, 0, NUM_RETX_SLOT * NUM_RETX_ENTRIES); + u8 retx_len[NUM_RETX_SLOT] = { 0 }; + u8 cur = 0; /* current slot */ + + hicn_mapme_init (vm); + + for (;;) + { + /* NOTE: returned timeout seems to always be 0 with get_event_data + * instead of get_event, and we thus need to reimplement timeout + * management on top, as done elsewhere in VPP code. + * + * The most probable event. For simplicity, for new faces, we pass the same retx_t with no + * prefix + */ + if (timeout != 0) + { + /* timeout = */ vlib_process_wait_for_event_or_clock (vm, timeout); + current_time = vlib_time_now (vm); + + /* + * As we don't accummulate errors, we allow for simple timer + * management with no error correction accounting for elapsed time. + * Also, we only run a timer when there are pending retransmissions. + */ + timeout = + (due_time > + current_time) ? due_time - current_time : DEFAULT_TIMEOUT; + due_time = current_time + timeout; + } + else + { + vlib_process_wait_for_event (vm); + } + + uword event_type = ~0; + void *event_data = vlib_process_get_event_data (vm, &event_type); + + switch (event_type) + { + case HICN_MAPME_EVENT_FACE_ADD: + { + /* + * A face has been added: + * - In case of a local app face, we need to advertise a new prefix + * - For another local face type, we need to advertise local + * prefixes and schedule retransmissions + */ + retx_t *retx_events = event_data; + for (u8 i = 0; i < vec_len (retx_events); i++) + { + hicn_mapme_on_face_added (vm, retx_events[i].face_id); + } + idle = 0; + } + break; + + case HICN_MAPME_EVENT_FACE_DEL: + idle = 0; + break; + + case HICN_MAPME_EVENT_FACE_NH_SET: + { + /* + * An hICN FIB entry has been modified. All operations so far + * have been procedded in the nodes. Here we need to track + * retransmissions upon timeout: we mark the FIB entry as pending in + * the second-to-next slot + */ + + /* Mark FIB entry as pending for second-to-next slot */ + retx_t *retx_events = event_data; + for (u8 i = 0; i < vec_len (retx_events); i++) + { + /* + * retx_events[i] corresponds to the dpoi_index of the (T)FIB + * structure that has been modified. Multiple successive + * events might correspond to the same entry. + * + * The FIB entry has a new next hop, and its TFIB section has: + * - eventually previous prev hops for which a IU with a + * lower seqno has been sent + * - the prev hops that have just been added. + * + * We don't distinguish any and just send an updated IU to all + * of them. The retransmission of the latest IU to all + * facilitates the matching of ACKs to a single seqno which is + * the one stored in the FIB. + * + * Since we retransmit to all prev hops, we can remove this + * (T)FIB entry for the check at the end of the current slot. + */ + retx_t *retx = (retx_t *) & retx_events[i]; + + retx->rtx_count = 0; + /* + * Transmit IU for all TFIB entries with latest seqno (we have + * at least one for sure!) + */ + hicn_mapme_send_updates (vm, &retx->prefix, retx->dpo, true); + + /* Delete entry_id from retransmissions in the current slot (if present) ... */ + for (u8 j = 0; j < CURLEN; j++) + if (!dpo_cmp (&(CUR[j].dpo), &retx->dpo)) + { + CUR[j].dpo.dpoi_index = ~0; /* sufficient */ + } + + /* ... and schedule it for next slot (if not already) */ + u8 j; + for (j = 0; j < NXTLEN; j++) + if (!dpo_cmp (&NXT[j].dpo, &retx->dpo)) + break; + if (j == NXTLEN) /* not found */ + NXT[NXTLEN++] = *retx; + } + idle = 0; + } + break; + + case HICN_MAPME_EVENT_FACE_NH_ADD: + /* + * As per the description of states, this event should add the face + * to the list of next hops, and eventually remove it from TFIB. + * This corresponds to the multipath case. + * + * In all cases, we assume the propagation was already done when the first + * interest with the same sequence number was received, so we stop here + * No change in TFIB = no IU to send + * + * No change in timers. + */ + vlib_cli_output (vm, "[hicn_event_mgr] ADD NEXT HOP IN FIB"); + + /* Add ingress face as next hop */ + idle = 0; + + break; + + case HICN_MAPME_EVENT_FACE_PH_ADD: + /* Back-propagation, interesting even for IN (desync) */ + { + retx_t *retx_events = event_data; + for (u8 i = 0; i < vec_len (retx_events); i++) + { + hicn_mapme_send_updates (vm, &retx_events[i].prefix, + retx_events[i].dpo, false); + } + idle = 0; + } + break; + + case HICN_MAPME_EVENT_FACE_PH_DEL: + /* Ack : remove an element from TFIB */ + break; + + case ~0: + /* Timeout occurred, we have to retransmit IUs for all pending + * prefixes having entries in TFIB + * + * timeouts are slotted + * | | | | + * + * ^ + * +- event occurred + * new face, wait for the second next + * (having two arrays and swapping cur and next) + * retx : put in next + */ + idle += 1; + for (u8 pos = 0; pos < CURLEN; pos++) + { + retx_t *retx = &CUR[pos]; + + if (retx->dpo.dpoi_index == ~0) /* deleted entry */ + continue; + + hicn_mapme_tfib_t *tfib = + TFIB (hicn_strategy_dpo_ctx_get (retx->dpo.dpoi_index)); + if (!tfib) + { + DEBUG ("NULL TFIB entry for dpoi_index=%d", + retx->dpo.dpoi_index); + continue; + } + + hicn_mapme_send_updates (vm, &retx->prefix, retx->dpo, true); + + retx->rtx_count++; + // If we exceed the numver of retransmittion it means that all tfib entries have seens at least HICN_PARAM_RTX_MAX of retransmission + if (retx->rtx_count < HICN_PARAM_RTX_MAX) + { + /* + * We did some retransmissions, so let's reschedule a check in the + * next slot + */ + NXT[NXTLEN++] = CUR[pos]; + idle = 0; + } + else + { + hicn_mapme_tfib_clear (tfib); + } + } + + /* Reset events in this slot and prepare for next one */ + CURLEN = 0; + cur = NEXT_SLOT (cur); + + /* After two empty slots, we disable the timer */ + + break; + } + + if (event_data) + vlib_process_put_event_data (vm, event_data); + + timeout = (idle > 1) ? 0 : DEFAULT_TIMEOUT; + + // if (vlib_process_suspend_time_is_zero (timeout)) { ... } + + } + + /* NOTREACHED */ + return 0; +} + +/* Not static as we need to access it from hicn_face */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn_mapme_eventmgr_process_node) = { //,static) = { + .function = hicn_mapme_eventmgr_process, + .type = VLIB_NODE_TYPE_PROCESS, + .name = "mapme-eventmgr-process", + .process_log2_n_stack_bytes = 16, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/mapme_eventmgr.h b/hicn-plugin/src/network/mapme_eventmgr.h new file mode 100644 index 000000000..b63d16805 --- /dev/null +++ b/hicn-plugin/src/network/mapme_eventmgr.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017-2020 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 // vlib_node_registration_t (vlib/node.h) + +#include + +/** + * @file mapme_eventmgr.h + * + */ + +/* + * Structure carrying all necessary information for managing Special Interest + * (re)transmissions. + */ +typedef struct +{ + hicn_prefix_t prefix; + dpo_id_t dpo; + hicn_face_id_t face_id; + u8 rtx_count; // Number of retransmissions since last tfib addition +} retx_t; + +#define HASH32(x) ((u16)x ^ (x << 16)) + +/** + * @brief This is a process node reacting to face events. + */ +// not static ! +vlib_node_registration_t hicn_mapme_eventmgr_process_node; + +/** + * @brief Initialize MAP-Me on forwarder + * @params vm - vlib_main_t pointer + */ +void hicn_mapme_init (vlib_main_t * vm); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/mgmt.c b/hicn-plugin/src/network/mgmt.c new file mode 100644 index 000000000..7b20fe911 --- /dev/null +++ b/hicn-plugin/src/network/mgmt.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2019 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 "hicn.h" +#include "infra.h" +#include "mgmt.h" + +/* define message IDs */ +#include + +/* shared routine betweeen API and CLI, leveraging API message structure */ +int +hicn_mgmt_node_stats_get (vl_api_hicn_api_node_stats_get_reply_t * rmp) +{ + rmp->pkts_processed = 0; + rmp->pkts_interest_count = 0; + rmp->pkts_data_count = 0; + rmp->pkts_from_cache_count = 0; + rmp->pkts_no_pit_count = 0; + rmp->pit_expired_count = 0; + rmp->cs_expired_count = 0; + rmp->cs_lru_count = 0; + rmp->pkts_drop_no_buf = 0; + rmp->interests_aggregated = 0; + rmp->interests_retx = 0; + rmp->pit_entries_count = + clib_host_to_net_u64 (hicn_main.pitcs.pcs_pit_count); + rmp->cs_entries_count = clib_host_to_net_u64 (hicn_main.pitcs.pcs_cs_count); + rmp->cs_entries_ntw_count = + clib_host_to_net_u64 (hicn_main.pitcs.policy_state.count); + + vlib_error_main_t *em; + vlib_node_t *n; + foreach_vlib_main (( + { + em = &this_vlib_main->error_main; + n = + vlib_get_node (this_vlib_main, + hicn_interest_pcslookup_node.index); + u32 node_cntr_base_idx = n->error_heap_index; + rmp->pkts_processed += + clib_host_to_net_u64 (em->counters[node_cntr_base_idx + + HICNFWD_ERROR_PROCESSED]); + rmp->pkts_interest_count += + clib_host_to_net_u64 (em->counters[node_cntr_base_idx + + HICNFWD_ERROR_INTERESTS]); + n = + vlib_get_node (this_vlib_main, + hicn_data_pcslookup_node.index); + node_cntr_base_idx = n->error_heap_index; + rmp->pkts_processed += + clib_host_to_net_u64 (em->counters[node_cntr_base_idx + + HICNFWD_ERROR_PROCESSED]); + rmp->pkts_data_count += + clib_host_to_net_u64 (em->counters[node_cntr_base_idx + + HICNFWD_ERROR_DATAS]); + n = + vlib_get_node (this_vlib_main, + hicn_interest_hitcs_node.index); + node_cntr_base_idx = n->error_heap_index; + rmp->pkts_from_cache_count += + clib_host_to_net_u64 (em->counters[node_cntr_base_idx + + HICNFWD_ERROR_CACHED]); + n = + vlib_get_node (this_vlib_main, + hicn_interest_hitpit_node.index); + node_cntr_base_idx = n->error_heap_index; + rmp->interests_aggregated += + clib_host_to_net_u64 (em->counters[node_cntr_base_idx + + HICNFWD_ERROR_INTEREST_AGG]); + rmp->interests_retx += + clib_host_to_net_u64 (em->counters[node_cntr_base_idx + + HICNFWD_ERROR_INT_RETRANS]);})); + return (HICN_ERROR_NONE); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/mgmt.h b/hicn-plugin/src/network/mgmt.h new file mode 100644 index 000000000..bafb0194d --- /dev/null +++ b/hicn-plugin/src/network/mgmt.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2017-2019 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_MGMT_H__ +#define __HICN_MGMT_H__ + +#include +#include + +#include "faces/face.h" + + +/** + * @file mgmt.h + * + */ + +typedef struct icn_stats_s +{ + u32 pkts_processed; + u32 pkts_interest_count; + u32 pkts_data_count; + u32 pkts_from_cache_count; + u32 pkts_no_pit_count; + u32 pit_expired_count; + u32 cs_expired_count; + u32 no_bufs_count; + u32 pkts_interest_agg; + u32 pkts_int_retrans; + u32 pit_int_count; + u32 pit_cs_count; +} icn_stats_t; + +typedef enum +{ + HICN_MGMT_FACE_OP_NONE = 0, + HICN_MGMT_FACE_OP_CREATE, + HICN_MGMT_FACE_OP_DELETE, + HICN_MGMT_FACE_OP_ADMIN, + HICN_MGMT_FACE_OP_HELLO, +} hicn_mgmt_face_op_e; + +typedef enum +{ + HICN_MGMT_MAPME_OP_NONE = 0, + HICN_MGMT_MAPME_OP_CREATE, + HICN_MGMT_MAPME_OP_DELETE, + HICN_MGMT_MAPME_OP_ENABLE, + HICN_MGMT_MAPME_OP_DISABLE +} hicn_mgmt_mapme_op_e; + +typedef enum +{ + HICN_ADDRESS_TYPE_NONE, + HICN_ADDRESS_TYPE_V4, + HICN_ADDRESS_TYPE_V6 +} hicn_address_type_e; + +/* + * Utility to update error counters in all hICN nodes + */ +always_inline void +update_node_counter (vlib_main_t * vm, u32 node_idx, u32 counter_idx, u64 val) +{ + vlib_node_t *node = vlib_get_node (vm, node_idx); + vlib_error_main_t *em = &(vm->error_main); + u32 base_idx = node->error_heap_index; + + em->counters[base_idx + counter_idx] = val; +} + + +/* + * Stats for the forwarding node, which end up called "error" even though + * they aren't... + */ +#define foreach_hicnfwd_error \ + _(PROCESSED, "hICN packets processed") \ + _(INTERESTS, "hICN interests forwarded") \ + _(DATAS, "hICN data msgs forwarded") \ + _(CACHED, "Cached data ") \ + _(NO_PIT, "hICN no PIT entry drops") \ + _(PIT_EXPIRED, "hICN expired PIT entries") \ + _(CS_EXPIRED, "hICN expired CS entries") \ + _(CS_LRU, "hICN LRU CS entries freed") \ + _(NO_BUFS, "No packet buffers") \ + _(INTEREST_AGG, "Interests aggregated") \ + _(INTEREST_AGG_ENTRY, "Interest aggregated per entry") \ + _(INT_RETRANS, "Interest retransmissions") \ + _(INT_COUNT, "Interests in PIT") \ + _(CS_COUNT, "CS total entries") \ + _(CS_NTW_COUNT, "CS ntw entries") \ + _(CS_APP_COUNT, "CS app entries") \ + _(HASH_COLL_HASHTB_COUNT, "Collisions in Hash table") + +typedef enum +{ +#define _(sym, str) HICNFWD_ERROR_##sym, + foreach_hicnfwd_error +#undef _ + HICNFWD_N_ERROR, +} hicnfwd_error_t; + +/* + * Declarations + */ +clib_error_t *hicn_api_plugin_hookup (vlib_main_t * vm); + +int hicn_mgmt_node_stats_get (vl_api_hicn_api_node_stats_get_reply_t * rmp); + +#endif /* // __HICN_MGMT_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/params.h b/hicn-plugin/src/network/params.h new file mode 100644 index 000000000..606d50771 --- /dev/null +++ b/hicn-plugin/src/network/params.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2017-2020 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_PARAM_H__ +#define __HICN_PARAM_H__ + +#include + +/** + * @file params.h + * + */ + + +/* + * Features + */ +#define HICN_FEATURE_CS 1 //1 enable 0 disable + +/* + * Face compile-time parameters + */ +#define HICN_PARAM_FACES_MAX 512 + +STATIC_ASSERT ((HICN_PARAM_FACES_MAX & (HICN_PARAM_FACES_MAX - 1)) == 0, + "HICN_PARAM_FACES_MAX must be a power of 2"); + +/* + * Max length for hICN names + */ +#define HICN_PARAM_HICN_NAME_LEN_MAX 20 //bytes + +// Max next - hops supported in a FIB entry +#define HICN_PARAM_FIB_ENTRY_NHOPS_MAX 10 + +// Default and limit on weight, whatever weight means +#define HICN_PARAM_FIB_ENTRY_NHOP_WGHT_DFLT 0x10 +#define HICN_PARAM_FIB_ENTRY_NHOP_WGHT_MAX 0xff + +/* + * PIT compile-time parameters + */ +#define HICN_PARAM_PIT_ENTRIES_MIN 1024 +#define HICN_PARAM_PIT_ENTRIES_DFLT 1024 * 128 +#define HICN_PARAM_PIT_ENTRIES_MAX 2 * 1024 * 1024 + +// aggregation limit(interest previous hops) +// Supported up to 516. For more than 4 faces this param must +// HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4 must be a power of two +#define HICN_PARAM_PIT_ENTRY_PHOPS_MAX 20 + +STATIC_ASSERT ((ceil (log2 ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4)))) == + (floor (log2 ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4)))), + "HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4 must be a power of two"); + +STATIC_ASSERT ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX <= HICN_PARAM_FACES_MAX), + "HICN_PARAM_PIT_ENTRY_PHOP_MAX must be <= than HICN_PARAM_FACES_MAX"); + +//tFIB parameters +#define HICN_PARAM_RTX_MAX 10 + +// PIT lifetime limits on API override this(in seconds, integer type) +#define HICN_PARAM_PIT_LIFETIME_BOUND_MIN_SEC 0 +#define HICN_PARAM_PIT_LIFETIME_BOUND_MAX_SEC 200 + +//PIT lifetime params if not set at API(in mseconds, integer type) +#define HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS 20000 + +// Face CS reservation params +#define HICN_PARAM_FACE_MAX_CS_RESERVED 20000 //packets +#define HICN_PARAM_FACE_MIN_CS_RESERVED 0 //packets +#define HICN_PARAM_FACE_DFT_CS_RESERVED 20000 //packets + +/* + * CS compile-time parameters + */ +#define HICN_PARAM_CS_ENTRIES_MIN 0 // can disable CS +#define HICN_PARAM_CS_ENTRIES_DFLT 4 * 1024 +#define HICN_PARAM_CS_ENTRIES_MAX 1024 * 1024 + +#define HICN_PARAM_CS_LRU_DEFAULT (16 * 1024) + +/* CS lifetime defines, in mseconds, integer type */ +#define HICN_PARAM_CS_LIFETIME_MIN 0 +#define HICN_PARAM_CS_LIFETIME_DFLT (5 * 60 * 1000) // 300 seconds +#define HICN_PARAM_CS_LIFETIME_MAX (24 * 3600 * 1000) //24 hours... + +/* CS reserved portion for applications */ +#define HICN_PARAM_CS_RESERVED_APP 50 //% +#define HICN_PARAM_CS_MIN_MBUF 4096 //this seems to be the minumim default number of mbuf we can have in vpp + +/* Cloning parameters */ +/* ip4 */ +#define HICN_IP4_VERSION_HEADER_LENGTH 0x45 +#define HICN_IP4_PROTOCOL IP_PROTOCOL_TCP +#define HICN_IP4_TTL_DEFAULT 128 + +/* ip6 */ +#define IPV6_DEFAULT_VERSION 6 +#define IPV6_DEFAULT_TRAFFIC_CLASS 0 +#define IPV6_DEFAULT_FLOW_LABEL 0 +#define HCIN_IP6_VERSION_TRAFFIC_FLOW (IPV6_DEFAULT_VERSION << 28) | \ + (IPV6_DEFAULT_TRAFFIC_CLASS << 20) | \ + (IPV6_DEFAULT_FLOW_LABEL & 0xfffff) +#define HICN_IP6_PROTOCOL IP_PROTOCOL_TCP +#define HICN_IP6_HOP_LIMIT 0x40 + +#endif /* // __HICN_PARAM_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/parser.h b/hicn-plugin/src/network/parser.h new file mode 100644 index 000000000..102f63107 --- /dev/null +++ b/hicn-plugin/src/network/parser.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2017-2019 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_PARSER_H__ +#define __HICN_PARSER_H__ + +#include + +#include "hicn.h" +#include + +/** + * @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 + * + * @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 + */ +always_inline int +hicn_interest_parse_pkt (vlib_buffer_t * pkt, hicn_name_t * name, + u16 * namelen, hicn_header_t ** pkt_hdrp, u8 * isv6) +{ + 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 = + IPPROTO_NONE,.l2 = + ip_pkt[next_proto_offset],.l1 = + ip_proto} + }; + 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; + + return HICN_ERROR_NONE; +} + +/** + * @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 + */ +always_inline int +hicn_data_parse_pkt (vlib_buffer_t * pkt, hicn_name_t * name, + u16 * namelen, hicn_header_t ** pkt_hdrp, u8 * isv6) +{ + 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 = + IPPROTO_NONE,.l2 = + ip_pkt[next_proto_offset],.l1 = + ip_proto} + }; + 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; +} + + +#endif /* // __HICN_PARSER_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/pcs.c b/hicn-plugin/src/network/pcs.c new file mode 100644 index 000000000..6c44b9d83 --- /dev/null +++ b/hicn-plugin/src/network/pcs.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017-2020 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 "hashtb.h" +#include "pcs.h" +#include "cache_policies/cs_lru.h" + +int +hicn_pit_create (hicn_pit_cs_t * p, u32 num_elems) +{ + int ret = + hicn_hashtb_alloc (&p->pcs_table, num_elems, sizeof (hicn_pcs_entry_t)); + p->pcs_table->ht_flags |= HICN_HASHTB_FLAG_KEY_FMT_NAME; + + p->pcs_pit_count = p->pcs_cs_count = 0; + + p->policy_state.max = + HICN_PARAM_CS_LRU_DEFAULT - + (HICN_PARAM_CS_LRU_DEFAULT * HICN_PARAM_CS_RESERVED_APP / 100); + p->policy_state.count = 0; + p->policy_state.head = p->policy_state.tail = 0; + + p->policy_vft.hicn_cs_insert = hicn_cs_lru.hicn_cs_insert; + p->policy_vft.hicn_cs_update = hicn_cs_lru.hicn_cs_update; + p->policy_vft.hicn_cs_dequeue = hicn_cs_lru.hicn_cs_dequeue; + p->policy_vft.hicn_cs_delete_get = hicn_cs_lru.hicn_cs_delete_get; + p->policy_vft.hicn_cs_trim = hicn_cs_lru.hicn_cs_trim; + p->policy_vft.hicn_cs_flush = hicn_cs_lru.hicn_cs_flush; + + return (ret); +} + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/pcs.h b/hicn-plugin/src/network/pcs.h new file mode 100644 index 000000000..a9e1ae5a0 --- /dev/null +++ b/hicn-plugin/src/network/pcs.h @@ -0,0 +1,839 @@ +/* + * Copyright (c) 2017-2020 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_PCS_H__ +#define __HICN_PCS_H__ + +#include "hashtb.h" +#include "face_db.h" +#include "strategy_dpo_manager.h" +#include "error.h" +#include "cache_policies/cs_policy.h" +#include "faces/face.h" + +/** + * @file pcs.h + * + * This file implement the PIT and CS which are collapsed in the same + * structure, thereore an entry is either a PIT entry of a CS entry. + * The implementation consist of a hash table where each entry of the + * hash table contains a PIT or CS entry, some counters to maintain the + * status of the PIT/CS and the reference to the eviction policy for + * the CS. The default eviction policy id FIFO. + */ + +/* The PIT and CS are stored as a union */ +#define HICN_PIT_NULL_TYPE 0 +#define HICN_PIT_TYPE 1 +#define HICN_CS_TYPE 2 + +/* + * Definitions and Forward refs for the time counters we're trying out. + * Counters are maintained by the background process. TODO. + */ +#define SEC_MS 1000 +#define HICN_INFRA_FAST_TIMER_SECS 1 +#define HICN_INFRA_FAST_TIMER_MSECS (HICN_INFRA_FAST_TIMER_SECS * SEC_MS) +#define HICN_INFRA_SLOW_TIMER_SECS 60 +#define HICN_INFRA_SLOW_TIMER_MSECS (HICN_INFRA_SLOW_TIMER_SECS * SEC_MS) + +/* + * Note that changing this may change alignment within the PIT struct, so be careful. + */ +typedef struct __attribute__ ((packed)) hicn_pcs_shared_s +{ + + /* Installation/creation time (vpp float units, for now) */ + f64 create_time; + + /* Expiration time (vpp float units, for now) */ + f64 expire_time; + + /* Shared 'flags' octet */ + u8 entry_flags; + + /* Needed to align for the pit or cs portion */ + u8 padding; +} hicn_pcs_shared_t; + +#define HICN_PCS_ENTRY_CS_FLAG 0x01 + +/* + * PIT entry, unioned with a CS entry below + */ +typedef struct __attribute__ ((packed)) hicn_pit_entry_s +{ + + /* Shared size 8 + 8 + 2 = 18B */ + + /* + * Egress next hop (containes the egress face) This id refers to the + * position of the choosen face in the next_hops array of the dpo */ + /* 18B + 1B = 19B */ + u8 pe_txnh; + + /* Array of incoming ifaces */ + /* 24B + 32B (8B*4) =56B */ + hicn_face_db_t faces; + +} hicn_pit_entry_t; + +#define HICN_CS_ENTRY_OPAQUE_SIZE HICN_HASH_NODE_APP_DATA_SIZE - 36 + +/* + * CS entry, unioned with a PIT entry below + */ +typedef struct __attribute__ ((packed)) hicn_cs_entry_s +{ + /* 18B + 2B = 20B */ + u16 align; + + /* Packet buffer, if held */ + /* 20B + 4B = 24B */ + u32 cs_pkt_buf; + + /* Ingress face */ + /* 24B + 4B = 28B */ + hicn_face_id_t cs_rxface; + + /* Linkage for LRU, in the form of hashtable node indexes */ + /* 28B + 8B = 36B */ + u32 cs_lru_prev; + u32 cs_lru_next; + + /* Reserved for implementing cache policy different than LRU */ + /* 36B + (64 - 36)B = 64B */ + u8 opaque[HICN_CS_ENTRY_OPAQUE_SIZE]; + + +} __attribute__ ((packed)) hicn_cs_entry_t; + +/* + * Combined PIT/CS entry data structure, embedded in a hashtable entry after + * the common hashtable preamble struct. This MUST fit in the available + * (fixed) space in a hashtable node. + */ +typedef struct hicn_pcs_entry_s +{ + + hicn_pcs_shared_t shared; + + union + { + hicn_pit_entry_t pit; + hicn_cs_entry_t cs; + } u; +} hicn_pcs_entry_t; + + +/* + * Overall PIT/CS table, based on the common hashtable + */ +typedef struct hicn_pit_cs_s +{ + + hicn_hashtb_t *pcs_table; + + /* Counters for PIT/CS sentries */ + u32 pcs_pit_count; + u32 pcs_cs_count; + u32 pcs_cs_dealloc; + u32 pcs_pit_dealloc; + + /* Total size of PCS */ + u32 pcs_size; + + hicn_cs_policy_t policy_state; + hicn_cs_policy_vft_t policy_vft; + +} hicn_pit_cs_t; + +/* Functions declarations */ +int hicn_pit_create (hicn_pit_cs_t * p, u32 num_elems); + +always_inline void +hicn_pit_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t * pcs_entry, hicn_hash_entry_t * hash_entry, + hicn_hash_node_t * node, const hicn_dpo_vft_t * dpo_vft, + dpo_id_t * hicn_dpo_id, hicn_face_id_t inface_id, u8 is_appface); + +always_inline void +hicn_pcs_cs_update (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t * old_entry, hicn_pcs_entry_t * entry, + hicn_hash_node_t * node); + +always_inline void +hicn_pcs_cs_delete (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t ** pcs_entry, hicn_hash_node_t ** node, + hicn_hash_entry_t * hash_entry, + const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id); + +always_inline int +hicn_pcs_cs_insert (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t * entry, hicn_hash_node_t * node, + hicn_hash_entry_t ** hash_entry, u64 hashval, + u32 * node_id, index_t * dpo_ctx_id, u8 * vft_id, + u8 * is_cs, u8 * hash_entry_id, u32 * bucket_id, + u8 * bucket_is_overflow); + +always_inline int +hicn_pcs_cs_insert_update (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t * entry, hicn_hash_node_t * node, + hicn_hash_entry_t ** hash_entry, u64 hashval, + u32 * node_id, index_t * dpo_ctx_id, u8 * vft_id, + u8 * is_cs, u8 * hash_entry_id, u32 * bucket_id, + u8 * bucket_is_overflow, hicn_face_id_t inface); + +always_inline int +hicn_pcs_pit_insert (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t * entry, + hicn_hash_node_t * node, hicn_hash_entry_t ** hash_entry, + u64 hashval, u32 * node_id, index_t * dpo_ctx_id, + u8 * vft_id, u8 * is_cs, u8 * hash_entry_id, + u32 * bucket_id, u8 * bucket_is_overflow); + +always_inline void +hicn_pcs_pit_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, + hicn_hash_node_t ** node, vlib_main_t * vm, + hicn_hash_entry_t * hash_entry, + const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id); + +always_inline int +hicn_pcs_insert (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t * entry, hicn_hash_node_t * node, + hicn_hash_entry_t ** hash_entry, u64 hashval, u32 * node_id, + index_t * dpo_ctx_id, u8 * vft_id, u8 * is_cs, + u8 * hash_entry_id, u32 * bucket_id, + u8 * bucket_is_overflow); + +always_inline void +hicn_pcs_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, + hicn_hash_node_t ** node, vlib_main_t * vm, + hicn_hash_entry_t * hash_entry, + const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id); + +always_inline void +hicn_pcs_remove_lock (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, + hicn_hash_node_t ** node, vlib_main_t * vm, + hicn_hash_entry_t * hash_entry, + const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id); + +always_inline void +hicn_cs_delete_trimmed (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, + hicn_hash_entry_t * hash_entry, + hicn_hash_node_t ** node, vlib_main_t * vm); + +/* Function implementation */ +/* Accessor for pit/cs data inside hash table node */ +static inline hicn_pcs_entry_t * +hicn_pit_get_data (hicn_hash_node_t * node) +{ + return (hicn_pcs_entry_t *) (hicn_hashtb_node_data (node)); +} + +/* Init pit/cs data block (usually inside hash table node) */ +static inline void +hicn_pit_init_data (hicn_pcs_entry_t * p) +{ + p->shared.entry_flags = 0; + p->u.pit.faces.n_faces = 0; + p->u.pit.faces.is_overflow = 0; + hicn_face_bucket_t *face_bkt; + pool_get (hicn_face_bucket_pool, face_bkt); + + p->u.pit.faces.next_bucket = face_bkt - hicn_face_bucket_pool; +} + +/* Init pit/cs data block (usually inside hash table node) */ +static inline void +hicn_cs_init_data (hicn_pcs_entry_t * p) +{ + p->shared.entry_flags = 0; + p->u.pit.faces.n_faces = 0; + p->u.pit.faces.is_overflow = 0; +} + + +static inline f64 +hicn_pcs_get_exp_time (f64 cur_time_sec, u64 lifetime_msec) +{ + return (cur_time_sec + ((f64) lifetime_msec) / SEC_MS); +} + +/* + * Configure CS LRU limit. Zero is accepted, means 'no limit', probably not a + * good choice. + */ +static inline void +hicn_pit_set_lru_max (hicn_pit_cs_t * p, u32 limit) +{ + p->policy_state.max = limit; +} + +/* + * Accessor for PIT interest counter. + */ +static inline u32 +hicn_pit_get_int_count (const hicn_pit_cs_t * pitcs) +{ + return (pitcs->pcs_pit_count); +} + +/* + * Accessor for PIT cs entries counter. + */ +static inline u32 +hicn_pit_get_cs_count (const hicn_pit_cs_t * pitcs) +{ + return (pitcs->pcs_cs_count); +} + +static inline u32 +hicn_pcs_get_ntw_count (const hicn_pit_cs_t * pitcs) +{ + return (pitcs->policy_state.count); +} + +static inline u32 +hicn_pit_get_htb_bucket_count (const hicn_pit_cs_t * pitcs) +{ + return (pitcs->pcs_table->ht_overflow_buckets_used); +} + +static inline int +hicn_cs_enabled (hicn_pit_cs_t * pit) +{ + switch (HICN_FEATURE_CS) + { + case 0: + default: + return (0); + case 1: + return (pit->policy_state.max > 0); + } +} + +/* + * Delete a PIT/CS entry from the hashtable, freeing the hash node struct. + * The caller's pointers are zeroed! If cs_trim is true, entry has already + * been removed from lru list The main purpose of this wrapper is helping + * maintain the per-PIT stats. + */ +always_inline void +hicn_pcs_delete_internal (hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t ** pcs_entryp, + hicn_hash_entry_t * hash_entry, + hicn_hash_node_t ** node, vlib_main_t * vm, + const hicn_dpo_vft_t * dpo_vft, + dpo_id_t * hicn_dpo_id) +{ + hicn_pcs_entry_t *pcs = *pcs_entryp; + + ASSERT (pcs == hicn_hashtb_node_data (*node)); + + if (hash_entry->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY) + { + pitcs->pcs_cs_dealloc++; + /* Free any associated packet buffer */ + vlib_buffer_free_one (vm, pcs->u.cs.cs_pkt_buf); + pcs->u.cs.cs_pkt_buf = ~0; + ASSERT ((pcs->u.cs.cs_lru_prev == 0) + && (pcs->u.cs.cs_lru_prev == pcs->u.cs.cs_lru_next)); + } + else + { + pitcs->pcs_pit_dealloc++; + hicn_strategy_dpo_ctx_unlock (hicn_dpo_id); + + /* Flush faces */ + hicn_faces_flush (&(pcs->u.pit.faces)); + } + + hicn_hashtb_delete (pitcs->pcs_table, node, hash_entry->he_msb64); + *pcs_entryp = NULL; +} + +/* + * Convert a PIT entry into a CS entry (assumes that the entry is already in + * the hashtable.) This is primarily here to maintain the internal counters. + */ +always_inline void +hicn_pit_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t * pcs_entry, hicn_hash_entry_t * hash_entry, + hicn_hash_node_t * node, const hicn_dpo_vft_t * dpo_vft, + dpo_id_t * hicn_dpo_id, hicn_face_id_t inface_id, u8 is_appface) +{ + + /* + * Different from the insert node. In here we don't need to add a new + * hash entry. + */ + pitcs->pcs_pit_count--; + hicn_strategy_dpo_ctx_unlock (hicn_dpo_id); + /* Flush faces */ + hicn_faces_flush (&(pcs_entry->u.pit.faces)); + + hash_entry->he_flags |= HICN_HASH_ENTRY_FLAG_CS_ENTRY; + node->hn_flags |= HICN_HASH_NODE_CS_FLAGS; + pcs_entry->shared.entry_flags |= HICN_PCS_ENTRY_CS_FLAG; + + pcs_entry->u.cs.cs_rxface = inface_id; + + /* Update the CS according to the policy */ + hicn_cs_policy_t *policy_state; + hicn_cs_policy_vft_t *policy_vft; + + policy_state = &pitcs->policy_state; + policy_vft = &pitcs->policy_vft; + + policy_vft->hicn_cs_insert (pitcs, node, pcs_entry, policy_state); + pitcs->pcs_cs_count++; + + if (policy_state->count > policy_state->max) + { + hicn_hash_node_t *node; + hicn_pcs_entry_t *pcs_entry; + hicn_hash_entry_t *hash_entry; + policy_vft->hicn_cs_delete_get (pitcs, policy_state, + &node, &pcs_entry, &hash_entry); + + + /* + * We don't have to decrease the lock (therefore we cannot + * use hicn_pcs_cs_delete function) + */ + policy_vft->hicn_cs_dequeue (pitcs, node, pcs_entry, policy_state); + + hicn_cs_delete_trimmed (pitcs, &pcs_entry, hash_entry, &node, vm); + + /* Update the global CS counter */ + pitcs->pcs_cs_count--; + } +} + +/* Functions specific for PIT or CS */ + +always_inline void +hicn_pcs_cs_update (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t * old_entry, hicn_pcs_entry_t * entry, + hicn_hash_node_t * node) +{ + hicn_cs_policy_t *policy_state; + hicn_cs_policy_vft_t *policy_vft; + + policy_state = &pitcs->policy_state; + policy_vft = &pitcs->policy_vft; + + if (entry->u.cs.cs_rxface != old_entry->u.cs.cs_rxface) + { + /* Dequeue content from the old queue */ + policy_vft->hicn_cs_dequeue (pitcs, node, old_entry, policy_state); + + old_entry->u.cs.cs_rxface = entry->u.cs.cs_rxface; + policy_state = &pitcs->policy_state; + policy_vft = &pitcs->policy_vft; + + policy_vft->hicn_cs_insert (pitcs, node, old_entry, policy_state); + + if (policy_state->count > policy_state->max) + { + hicn_hash_node_t *node; + hicn_pcs_entry_t *pcs_entry; + hicn_hash_entry_t *hash_entry; + policy_vft->hicn_cs_delete_get (pitcs, policy_state, + &node, &pcs_entry, &hash_entry); + + /* + * We don't have to decrease the lock (therefore we cannot + * use hicn_pcs_cs_delete function) + */ + policy_vft->hicn_cs_dequeue (pitcs, node, pcs_entry, policy_state); + + hicn_cs_delete_trimmed (pitcs, &pcs_entry, hash_entry, &node, vm); + + /* Update the global CS counter */ + pitcs->pcs_cs_count--; + } + } + else + /* Update the CS LRU, moving this item to the head */ + policy_vft->hicn_cs_update (pitcs, node, old_entry, policy_state); +} + +always_inline void +hicn_pcs_cs_delete (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t ** pcs_entryp, hicn_hash_node_t ** nodep, + hicn_hash_entry_t * hash_entry, + const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id) +{ + if (!(hash_entry->he_flags & HICN_HASH_ENTRY_FLAG_DELETED)) + { + hicn_cs_policy_t *policy_state; + hicn_cs_policy_vft_t *policy_vft; + + policy_state = &pitcs->policy_state; + policy_vft = &pitcs->policy_vft; + + policy_vft->hicn_cs_dequeue (pitcs, (*nodep), (*pcs_entryp), + policy_state); + + /* Update the global CS counter */ + pitcs->pcs_cs_count--; + } + + /* A data could have been inserted in the CS through a push. In this case locks == 0 */ + hash_entry->locks--; + if (hash_entry->locks == 0) + { + hicn_pcs_delete_internal + (pitcs, pcs_entryp, hash_entry, nodep, vm, dpo_vft, hicn_dpo_id); + } + else + { + hash_entry->he_flags |= HICN_HASH_ENTRY_FLAG_DELETED; + } +} + +always_inline int +hicn_pcs_cs_insert (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t * entry, hicn_hash_node_t * node, + hicn_hash_entry_t ** hash_entry, u64 hashval, + u32 * node_id, index_t * dpo_ctx_id, u8 * vft_id, + u8 * is_cs, u8 * hash_entry_id, u32 * bucket_id, + u8 * bucket_is_overflow) +{ + ASSERT (entry == hicn_hashtb_node_data (node)); + + int ret = + hicn_hashtb_insert (pitcs->pcs_table, node, hash_entry, hashval, node_id, + dpo_ctx_id, vft_id, is_cs, hash_entry_id, bucket_id, + bucket_is_overflow); + + if (PREDICT_TRUE (ret == HICN_ERROR_NONE)) + { + /* Mark the entry as a CS entry */ + node->hn_flags |= HICN_HASH_NODE_CS_FLAGS; + entry->shared.entry_flags |= HICN_PCS_ENTRY_CS_FLAG; + (*hash_entry)->he_flags |= HICN_HASH_ENTRY_FLAG_CS_ENTRY; + + hicn_cs_policy_t *policy_state; + hicn_cs_policy_vft_t *policy_vft; + + policy_state = &pitcs->policy_state; + policy_vft = &pitcs->policy_vft; + + policy_vft->hicn_cs_insert (pitcs, node, entry, policy_state); + pitcs->pcs_cs_count++; + + if (policy_state->count > policy_state->max) + { + hicn_hash_node_t *node; + hicn_pcs_entry_t *pcs_entry; + hicn_hash_entry_t *hash_entry; + policy_vft->hicn_cs_delete_get (pitcs, policy_state, + &node, &pcs_entry, &hash_entry); + + /* + * We don't have to decrease the lock (therefore we cannot + * use hicn_pcs_cs_delete function) + */ + policy_vft->hicn_cs_dequeue (pitcs, node, pcs_entry, policy_state); + + hicn_cs_delete_trimmed (pitcs, &pcs_entry, hash_entry, &node, vm); + + /* Update the global CS counter */ + pitcs->pcs_cs_count--; + } + } + return ret; +} + +/* + * Insert CS entry into the hashtable The main purpose of this wrapper is + * helping maintain the per-PIT stats. + */ +always_inline int +hicn_pcs_cs_insert_update (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t * entry, hicn_hash_node_t * node, + hicn_hash_entry_t ** hash_entry, u64 hashval, + u32 * node_id, index_t * dpo_ctx_id, u8 * vft_id, + u8 * is_cs, u8 * hash_entry_id, u32 * bucket_id, + u8 * bucket_is_overflow, hicn_face_id_t inface) +{ + int ret; + + ASSERT (entry == hicn_hashtb_node_data (node)); + + entry->u.cs.cs_rxface = inface; + ret = + hicn_pcs_cs_insert (vm, pitcs, entry, node, hash_entry, hashval, node_id, + dpo_ctx_id, vft_id, is_cs, hash_entry_id, bucket_id, + bucket_is_overflow); + + /* A content already exists in CS with the same name */ + if (ret == HICN_ERROR_HASHTB_EXIST && *is_cs) + { + /* Update the entry */ + hicn_hash_node_t *existing_node = + hicn_hashtb_node_from_idx (pitcs->pcs_table, *node_id); + hicn_pcs_entry_t *pitp = hicn_pit_get_data (existing_node); + + /* Free associated packet buffer and update counter */ + pitcs->pcs_cs_dealloc++; + vlib_buffer_free_one (vm, pitp->u.cs.cs_pkt_buf); + + pitp->shared.create_time = entry->shared.create_time; + pitp->shared.expire_time = entry->shared.expire_time; + pitp->u.cs.cs_pkt_buf = entry->u.cs.cs_pkt_buf; + + hicn_pcs_cs_update (vm, pitcs, pitp, entry, existing_node); + } + + return (ret); +} + +/* + * Insert PIT entry into the hashtable The main purpose of this wrapper is + * helping maintain the per-PIT stats. + */ +always_inline int +hicn_pcs_pit_insert (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t * entry, + hicn_hash_node_t * node, hicn_hash_entry_t ** hash_entry, + u64 hashval, u32 * node_id, index_t * dpo_ctx_id, + u8 * vft_id, u8 * is_cs, u8 * hash_entry_id, + u32 * bucket_id, u8 * bucket_is_overflow) +{ + ASSERT (entry == hicn_hashtb_node_data (node)); + + int ret = + hicn_hashtb_insert (pitcs->pcs_table, node, hash_entry, hashval, node_id, + dpo_ctx_id, vft_id, is_cs, hash_entry_id, bucket_id, + bucket_is_overflow); + + if (PREDICT_TRUE (ret == HICN_ERROR_NONE)) + pitcs->pcs_pit_count++; + + return ret; +} + +always_inline void +hicn_pcs_pit_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, + hicn_hash_node_t ** node, vlib_main_t * vm, + hicn_hash_entry_t * hash_entry, + const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id) +{ + hash_entry->locks--; + if (hash_entry->locks == 0) + { + pitcs->pcs_pit_count--; + hicn_pcs_delete_internal + (pitcs, pcs_entryp, hash_entry, node, vm, dpo_vft, hicn_dpo_id); + } + else + { + hash_entry->he_flags |= HICN_HASH_ENTRY_FLAG_DELETED; + } +} + + +/* Generic functions for PIT/CS */ + +/* + * Insert PIT/CS entry into the hashtable The main purpose of this wrapper is + * helping maintain the per-PIT stats. + */ +always_inline int +hicn_pcs_insert (vlib_main_t * vm, hicn_pit_cs_t * pitcs, + hicn_pcs_entry_t * entry, hicn_hash_node_t * node, + hicn_hash_entry_t ** hash_entry, u64 hashval, u32 * node_id, + index_t * dpo_ctx_id, u8 * vft_id, u8 * is_cs, + u8 * hash_entry_id, u32 * bucket_id, u8 * bucket_is_overflow) +{ + int ret; + + if ((*hash_entry)->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY) + { + ret = + hicn_pcs_cs_insert (vm, pitcs, entry, node, hash_entry, hashval, + node_id, dpo_ctx_id, vft_id, is_cs, hash_entry_id, + bucket_id, bucket_is_overflow); + } + else + { + ret = + hicn_pcs_pit_insert (pitcs, entry, node, hash_entry, hashval, node_id, + dpo_ctx_id, vft_id, is_cs, hash_entry_id, + bucket_id, bucket_is_overflow); + } + + return (ret); +} + + +/* + * Delete entry if there are no pending lock on the entry, otherwise mark it + * as to delete. + */ +always_inline void +hicn_pcs_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, + hicn_hash_node_t ** nodep, vlib_main_t * vm, + hicn_hash_entry_t * hash_entry, + const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id) +{ + /* + * If the entry has already been marked as deleted, it has already + * been dequeue + */ + if (hash_entry->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY) + { + hicn_pcs_cs_delete (vm, pitcs, pcs_entryp, nodep, hash_entry, + dpo_vft, hicn_dpo_id); + } + else + { + hicn_pcs_pit_delete (pitcs, pcs_entryp, nodep, vm, + hash_entry, dpo_vft, hicn_dpo_id); + } +} + +/* + * Remove a lock in the entry and delete it if there are no pending lock and + * the entry is marked as to be deleted + */ +always_inline void +hicn_pcs_remove_lock (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, + hicn_hash_node_t ** node, vlib_main_t * vm, + hicn_hash_entry_t * hash_entry, + const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id) +{ + hash_entry->locks--; + if (hash_entry->locks == 0 + && (hash_entry->he_flags & HICN_HASH_ENTRY_FLAG_DELETED)) + { + hicn_pcs_delete_internal + (pitcs, pcs_entryp, hash_entry, node, vm, dpo_vft, hicn_dpo_id); + } +} + +/* + * Delete entry which has already been bulk-removed from lru list + */ +always_inline void +hicn_cs_delete_trimmed (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, + hicn_hash_entry_t * hash_entry, + hicn_hash_node_t ** node, vlib_main_t * vm) +{ + + + if (hash_entry->locks == 0) + { + const hicn_dpo_vft_t *dpo_vft = hicn_dpo_get_vft (hash_entry->vft_id); + dpo_id_t hicn_dpo_id = + { dpo_vft->hicn_dpo_get_type (), 0, 0, hash_entry->dpo_ctx_id }; + + hicn_pcs_delete_internal + (pitcs, pcs_entryp, hash_entry, node, vm, dpo_vft, &hicn_dpo_id); + } + else + { + hash_entry->he_flags |= HICN_HASH_ENTRY_FLAG_DELETED; + } +} + +/* + * wrappable counter math (assumed uint16_t): return sum of addends + */ +always_inline u16 +hicn_infra_seq16_sum (u16 addend1, u16 addend2) +{ + return (addend1 + addend2); +} + +/* + * for comparing wrapping numbers, return lt,eq,gt 0 for a lt,eq,gt b + */ +always_inline int +hicn_infra_seq16_cmp (u16 a, u16 b) +{ + return ((int16_t) (a - b)); +} + +/* + * below are wrappers for lt, le, gt, ge seq16 comparators + */ +always_inline int +hicn_infra_seq16_lt (u16 a, u16 b) +{ + return (hicn_infra_seq16_cmp (a, b) < 0); +} + +always_inline int +hicn_infra_seq16_le (u16 a, u16 b) +{ + return (hicn_infra_seq16_cmp (a, b) <= 0); +} + +always_inline int +hicn_infra_seq16_gt (u16 a, u16 b) +{ + return (hicn_infra_seq16_cmp (a, b) > 0); +} + +always_inline int +hicn_infra_seq16_ge (u16 a, u16 b) +{ + return (hicn_infra_seq16_cmp (a, b) >= 0); +} + + +extern u16 hicn_infra_fast_timer; /* Counts at 1 second intervals */ +extern u16 hicn_infra_slow_timer; /* Counts at 1 minute intervals */ + +/* + * Utilities to convert lifetime into expiry time based on compressed clock, + * suitable for the opportunistic hashtable entry timeout processing. + */ + +//convert time in msec to time in clicks +always_inline u16 +hicn_infra_ms2clicks (u64 time_ms, u64 ms_per_click) +{ + f64 time_clicks = + ((f64) (time_ms + ms_per_click - 1)) / ((f64) ms_per_click); + return ((u16) time_clicks); +} + +always_inline u16 +hicn_infra_get_fast_exp_time (u64 lifetime_ms) +{ + u16 lifetime_clicks = + hicn_infra_ms2clicks (lifetime_ms, HICN_INFRA_FAST_TIMER_MSECS); + return (hicn_infra_seq16_sum (hicn_infra_fast_timer, lifetime_clicks)); +} + +always_inline u16 +hicn_infra_get_slow_exp_time (u64 lifetime_ms) +{ + u16 lifetime_clicks = + hicn_infra_ms2clicks (lifetime_ms, HICN_INFRA_SLOW_TIMER_MSECS); + return (hicn_infra_seq16_sum (hicn_infra_slow_timer, lifetime_clicks)); +} + +#endif /* // __HICN_PCS_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/pg.c b/hicn-plugin/src/network/pg.c new file mode 100644 index 000000000..eb833030d --- /dev/null +++ b/hicn-plugin/src/network/pg.c @@ -0,0 +1,1326 @@ +/* + * Copyright (c) 2017-2019 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; + +hicnpg_main_t hicnpg_main = { + .index = (u32) 0, + .index_ifaces = (u32) 1, + .max_seq_number = (u32) ~ 0, + .interest_lifetime = 4, + .n_flows = (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); + +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; + 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; + + 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); +} + +/* *INDENT-OFF* */ +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" + }, +}; +/* *INDENT-ON* */ + +/* + * 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); +} + + +static_always_inline int +match_ip4_name (u32 * name, fib_prefix_t * prefix) +{ + u32 xor = 0; + + xor = *name & prefix->fp_addr.ip4.data_u32; + + return xor == prefix->fp_addr.ip4.data_u32; +} + +static_always_inline int +match_ip6_name (u8 * name, fib_prefix_t * prefix) +{ + union + { + u32x4 as_u32x4; + u64 as_u64[2]; + u32 as_u32[4]; + } xor_sum __attribute__ ((aligned (sizeof (u32x4)))); + + 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]; + + 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; + + if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr))) + { + if (!match_ip4_name ((u32 *) & (ptr[12]), prefix)) + next = 1; + } + else + if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr))) + { + if (!match_ip6_name (&(ptr[8]), prefix)) + next = 2; + } + + 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 (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 (!match_ip6_name (&(ptr[24]), prefix)) + next = 2; + } + + return next; +} + + + + +/* + * 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; + 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); + + 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); +} + +/* *INDENT-OFF* */ +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", + }, +}; +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +VNET_FEATURE_INIT(hicn_data_input_ip4_arc, static)= + { + .arc_name = "ip4-unicast", + .node_name = "hicnpg-data", + .runs_before = VNET_FEATURES("ip4-inacl"), + }; +/* *INDENT-ON* */ + + +/* *INDENT-OFF* */ +VNET_FEATURE_INIT(hicn_data_input_ip6_arc, static)= + { + .arc_name = "ip6-unicast", + .node_name = "hicnpg-data", + .runs_before = VNET_FEATURES("ip6-inacl"), + }; +/* *INDENT-ON* */ + + +/* + * 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) +{ + 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; + + 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) + { + 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); + } + + 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); +} + +/* *INDENT-OFF* */ +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", + }, +}; +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +VNET_FEATURE_INIT(hicn_pg_server_ip6, static)= + { + .arc_name = "ip6-unicast", + .node_name = "hicnpg-server", + .runs_before = VNET_FEATURES("ip6-inacl"), + }; +/* *INDENT-ON* */ + +/* *INDENT-OFF* */ +VNET_FEATURE_INIT(hicn_pg_server_ip4, static)= + { + .arc_name = "ip4-unicast", + .node_name = "hicnpg-server", + .runs_before = VNET_FEATURES("ip4-inacl"), + }; +/* *INDENT-ON* */ + +/* + * End of packet-generator server node + */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/pg.h b/hicn-plugin/src/network/pg.h new file mode 100644 index 000000000..84a391d43 --- /dev/null +++ b/hicn-plugin/src/network/pg.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017-2020 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_PG_H__ +#define __HICN_PG_H__ + + +/** + * @file pg.h + * + * The packet generator is made of two entities, a client and a server. + * The client issues interests at high speed and the server satisfy each + * interest it receives with the corresponding data. + * The packet generator is made of three nodes: + * - hicnpg-interest that receives packets from a packet generator interface + * and manipulate them to generate interests based on the given configuration. + * This node runs at the client side. + * - hicnpg-data that receives data packets at the client side and counts them. + * This is useful for statistics. The "show err" command will give the number + * of interest issued and data received at the client side + * - hicnpg-server that recevies and interest and replies with the corresponding + * data. The data is generated from the interest switching the src and destination + * address in the packet and appending a payload to the packet. + * + * + * These three nodes are inserted in the vlib graph in the following manner: + * - hicnpg-interest is added as a possible next node of the pg-input node. The packet + * generator stream then specifies it as next node. + * - hicnpg-data is added as next hop of the ip4/6-unicast node exploiting the corresponding + * feature and it runs before the ip4/6-inacl node. In this way, every packet that is + * received through an interface on which this feature is enabled is sent to this node. + * - hicnpg-server is added as next hop of the ip4/6-unicast using the corresponding + * feature and it runs before the ip4/6-inacl node. In this way, every packet that is + * received through an interface on which this feature is enabled is sent to this node. + * + * An example of how to use the pg for hicn is available in the documentation. + */ + +/** + * @brief hICN packet generator main for the pg client nodes + * + * It stores the configuration and make it availables to the pg client nodes. + */ +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 +} hicnpg_main_t; + +extern hicnpg_main_t hicnpg_main; + +/** + * @brief hICN packet generator main for the pg server node + * + * It stores the configuration and make it availables to the pg server node. + */ +typedef struct hicnpg_server_main_s +{ + u32 node_index; + /* Arbitrary content */ + u32 pgen_svr_buffer_idx; + fib_prefix_t *pgen_srv_hicn_name; +} hicnpg_server_main_t; + +extern hicnpg_server_main_t hicnpg_server_main; + +extern vlib_node_registration_t hicn_pg_interest_node; +extern vlib_node_registration_t hicn_pg_data_node; + +#endif // __HICN_PG_H__ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/route.c b/hicn-plugin/src/network/route.c new file mode 100644 index 000000000..3b774cd82 --- /dev/null +++ b/hicn-plugin/src/network/route.c @@ -0,0 +1,766 @@ +/* + * Copyright (c) 2017-2020 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 +#include +#include +#include +#include +#include + +#include "strategy_dpo_ctx.h" +#include "strategy_dpo_manager.h" +#include "strategy.h" +#include "faces/face.h" +#include "error.h" +#include "strategies/dpo_mw.h" +#include "infra.h" +#include "udp_tunnels/udp_tunnel.h" + +#define FIB_SOURCE_HICN 0x04 //Right after the FIB_SOURCE_INTERFACE priority + +fib_source_t hicn_fib_src; + +fib_node_type_t hicn_fib_node_type; + +ip4_address_t localhost4 = {0}; +ip6_address_t localhost6 = {0}; + +int +hicn_route_get_dpo (const fib_prefix_t * prefix, + const dpo_id_t ** hicn_dpo, u32 * fib_index) +{ + //fib_prefix_t fib_pfx; + const dpo_id_t *load_balance_dpo_id; + const dpo_id_t *former_dpo_id; + int found = 0, ret = HICN_ERROR_ROUTE_NOT_FOUND; + fib_node_index_t fib_entry_index; + + /* Check if the route already exist in the fib */ + /* + * ASSUMPTION: we use table 0 which is the default table and it is + * already existing and locked + */ + *fib_index = fib_table_find_or_create_and_lock (prefix->fp_proto, + HICN_FIB_TABLE, + hicn_fib_src); + fib_entry_index = fib_table_lookup_exact_match (*fib_index, prefix); + + if (fib_entry_index != FIB_NODE_INDEX_INVALID) + { + /* Route already existing. We need to update the dpo. */ + load_balance_dpo_id = + fib_entry_contribute_ip_forwarding (fib_entry_index); + + /* The dpo is not a load balance dpo as expected */ + if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) + ret = HICN_ERROR_ROUTE_NO_LD; + else + { + /* former_dpo_id is a load_balance dpo */ + load_balance_t *lb = + load_balance_get (load_balance_dpo_id->dpoi_index); + + /* FIB entry exists but there is no hicn dpo. */ + ret = HICN_ERROR_ROUTE_DPO_NO_HICN; + for (int i = 0; i < lb->lb_n_buckets && !found; i++) + { + former_dpo_id = load_balance_get_bucket_i (lb, i); + + if (dpo_is_hicn (former_dpo_id)) + { + *hicn_dpo = former_dpo_id; + ret = HICN_ERROR_NONE; + found = 1; + } + } + } + } + /* + * Remove the lock from the table. We keep one lock per route, not + * per dpo + */ + fib_table_unlock (*fib_index, prefix->fp_proto, hicn_fib_src); + + return ret; +} + +int +hicn_route_set_strategy (fib_prefix_t * prefix, u8 strategy_id) +{ + const dpo_id_t *hicn_dpo_id; + dpo_id_t new_dpo_id = DPO_INVALID; + int ret; + hicn_dpo_ctx_t *old_hicn_dpo_ctx; + const hicn_dpo_vft_t *new_dpo_vft; + index_t new_hicn_dpo_idx; + u32 fib_index; + + ret = hicn_route_get_dpo (prefix, &hicn_dpo_id, &fib_index); + + if (ret == HICN_ERROR_NONE) + { + old_hicn_dpo_ctx = hicn_strategy_dpo_ctx_get (hicn_dpo_id->dpoi_index); + + new_dpo_vft = hicn_dpo_get_vft_from_id (strategy_id); + + if (new_dpo_vft == NULL || old_hicn_dpo_ctx == NULL) + return HICN_ERROR_STRATEGY_NOT_FOUND; + + /* Create a new dpo for the new strategy */ + new_dpo_vft->hicn_dpo_create (hicn_dpo_id->dpoi_proto, + old_hicn_dpo_ctx->next_hops, + old_hicn_dpo_ctx->entry_count, + &new_hicn_dpo_idx); + + /* the value we got when we registered */ + dpo_set (&new_dpo_id, + new_dpo_vft->hicn_dpo_get_type (), + (ip46_address_is_ip4 (&prefix->fp_addr) ? DPO_PROTO_IP4 : + DPO_PROTO_IP6), new_hicn_dpo_idx); + + /* Here is where we create the "via" like route */ + /* + * For the moment we use the global one the prefix you want + * to match Neale suggested -- FIB_SOURCE_HICN the client + * that is adding them -- no easy explanation at this time… + */ + fib_node_index_t new_fib_node_index = + fib_table_entry_special_dpo_update (fib_index, + prefix, + hicn_fib_src, + FIB_ENTRY_FLAG_EXCLUSIVE, + &new_dpo_id); + + dpo_unlock (&new_dpo_id); + ret = + (new_fib_node_index != + FIB_NODE_INDEX_INVALID) ? HICN_ERROR_NONE : + HICN_ERROR_ROUTE_NOT_UPDATED; + } + //Remember to remove the lock from the table when removing the entry + return ret; + +} + +int +ip_nh_add_helper (fib_protocol_t fib_proto, const fib_prefix_t * rpfx, ip46_address_t * nh, u32 sw_if) +{ + fib_route_path_t *rpaths = NULL, rpath; + + u32 fib_index = fib_table_find(fib_proto, 0); + + clib_memset(&rpath, 0, sizeof(rpath)); + rpath.frp_weight = 1; + rpath.frp_sw_if_index = sw_if; + rpath.frp_addr = *nh; + rpath.frp_proto = ip46_address_is_ip4(nh) ? DPO_PROTO_IP4 : DPO_PROTO_IP6; + + vec_add1(rpaths, rpath); + + fib_table_entry_path_add2 (fib_index, + rpfx, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_NONE, rpaths); + return 0; +} + +int +ip_nh_del_helper (fib_protocol_t fib_proto, const fib_prefix_t * rpfx, ip46_address_t * nh, u32 sw_if) +{ + fib_route_path_t *rpaths = NULL, rpath; + + u32 fib_index = fib_table_find(fib_proto, 0); + + clib_memset(&rpath, 0, sizeof(rpath)); + rpath.frp_weight = 1; + rpath.frp_sw_if_index = sw_if; + rpath.frp_addr = *nh; + rpath.frp_proto = ip46_address_is_ip4(nh) ? DPO_PROTO_IP4 : DPO_PROTO_IP6; + + vec_add1(rpaths, rpath); + + fib_table_entry_path_remove2 (fib_index, + rpfx, + FIB_SOURCE_CLI, + rpaths); + return 0; +} + + +static ip46_address_t * get_address(ip46_address_t * nh, u32 sw_if, fib_protocol_t proto) +{ + ip46_address_t * local_address = calloc(1, sizeof(ip46_address_t)); + + if (proto == FIB_PROTOCOL_IP4) + { + ip_interface_address_t *interface_address; + ip4_address_t *addr = + ip4_interface_address_matching_destination (&ip4_main, + &nh->ip4, + sw_if, + &interface_address); + + if (addr == NULL) + addr = ip4_interface_first_address (&ip4_main, + sw_if, + &interface_address); + if (addr != NULL) + ip46_address_set_ip4 (local_address, addr); + } + else if (proto == FIB_PROTOCOL_IP6) + { + ip_interface_address_t *interface_address; + ip6_interface_address_matching_destination (&ip6_main, + &nh->ip6, + sw_if, + &interface_address); + + ip6_address_t *addr = NULL; + if (interface_address != NULL) + addr = + (ip6_address_t *) + ip_interface_address_get_address (&ip6_main.lookup_main, + interface_address); + + if (addr == NULL) + addr = ip6_interface_first_address (&ip6_main, sw_if); + + if (addr != NULL) + ip46_address_set_ip6 (local_address, addr); + } + + return local_address; +} + +static void +sync_hicn_fib_entry(hicn_dpo_ctx_t *fib_entry) +{ + const dpo_id_t * dpo_loadbalance = fib_entry_contribute_ip_forwarding (fib_entry->fib_entry_index); + const load_balance_t *lb0 = load_balance_get(dpo_loadbalance->dpoi_index); + index_t hicn_fib_entry_index = hicn_strategy_dpo_ctx_get_index(fib_entry); + hicn_face_id_t * vec_faces = 0; + + dpo_id_t temp = DPO_INVALID; + const dpo_id_t *former_dpo = &temp; + int index = 0; + for (int j = 0; j < lb0->lb_n_buckets; j++) { + const dpo_id_t * dpo = load_balance_get_bucket_i(lb0,j); + + int dpo_comparison = dpo_cmp(former_dpo, dpo); + former_dpo = dpo; + /* + * Loadbalancing in ip replicate the dpo in multiple buckets + * in order to honor the assigned weights. + */ + if (dpo_comparison == 0) + continue; + + u32 sw_if = ~0; + ip46_address_t * nh = NULL; + hicn_face_id_t face_id = HICN_FACE_NULL; + + if (dpo_is_adj(dpo)) + { + ip_adjacency_t * adj = adj_get (dpo->dpoi_index); + sw_if = adj->rewrite_header.sw_if_index; + nh = get_address (&(adj->sub_type.nbr.next_hop), sw_if, fib_entry->proto); + } + else if (dpo->dpoi_type == dpo_type_udp_ip4 || dpo->dpoi_type == dpo_type_udp_ip6) + { + u8 proto = dpo->dpoi_type == dpo_type_udp_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; + nh = calloc (1, sizeof(ip46_address_t)); + switch (dpo->dpoi_proto) + { + case FIB_PROTOCOL_IP6: + nh = calloc (1, sizeof(ip46_address_t)); + ip46_address_set_ip6(nh, &localhost6); + break; + case FIB_PROTOCOL_IP4: + nh = calloc (1, sizeof(ip46_address_t)); + ip46_address_set_ip4(nh, &localhost4); + break; + default: + nh = calloc (1, sizeof(ip46_address_t)); + } + udp_tunnel_add_existing (dpo->dpoi_index, proto); + } + else //if (dpo_is_drop(dpo)) + { + sw_if = dpo_get_urpf(dpo); + nh = calloc (1, sizeof(ip46_address_t)); + } + + /* Careful, this adds a lock on the face if it exists */ + hicn_face_add(dpo, nh, sw_if, &face_id, 0); + + vec_validate(vec_faces, index); + vec_faces[index] = face_id; + index++; + + /* Face creation can realloc load_balance_t? Seem the fib_tracking does so. */ + dpo_loadbalance = fib_entry_contribute_ip_forwarding (fib_entry->fib_entry_index); + lb0 = load_balance_get(dpo_loadbalance->dpoi_index); + } + + const hicn_dpo_vft_t * strategy_vft = hicn_dpo_get_vft(fib_entry->dpo_type); + int i = 0; + while (i < fib_entry->entry_count) + { + u32 idx_nh = vec_search(vec_faces, fib_entry->next_hops[i]); + if (idx_nh == ~0) + { + strategy_vft->hicn_dpo_del_nh(fib_entry->next_hops[i], hicn_fib_entry_index); + } + else + { + vec_del1(vec_faces, idx_nh); + + /* Remove the lock added by hicn_face_add */ + hicn_face_unlock_with_id (fib_entry->next_hops[i]); + i++; + } + } + + hicn_face_id_t *face_id; + vec_foreach(face_id, vec_faces) + { + strategy_vft->hicn_dpo_add_update_nh(*face_id, hicn_fib_entry_index); + + /* Remove the lock added by hicn_face_add */ + hicn_face_unlock_with_id (*face_id); + + } + vec_free(vec_faces); +} + +static void +enable_disable_data_receiving (fib_protocol_t proto, u32 sw_if, u8 is_enable) +{ + if (proto == FIB_PROTOCOL_IP4 && sw_if != ~0) + vnet_feature_enable_disable ("ip4-local", "hicn-data-input-ip4", + sw_if, is_enable, 0, 0); + else if (proto == FIB_PROTOCOL_IP6 && sw_if != ~0) + vnet_feature_enable_disable ("ip6-local", "hicn-data-input-ip6", + sw_if, is_enable, 0, 0); + +} + +walk_rc_t enable_data_receiving_new_fib_entry (vnet_main_t * vnm, + vnet_sw_interface_t * si, + void *ctx) +{ + fib_protocol_t *proto = (fib_protocol_t *) ctx; + enable_disable_data_receiving(*proto, si->sw_if_index, 1); + + return (WALK_CONTINUE); +} + +walk_rc_t disable_data_receiving_rm_fib_entry (vnet_main_t * vnm, + vnet_sw_interface_t * si, + void *ctx) +{ + fib_protocol_t *proto = (fib_protocol_t *) ctx; + enable_disable_data_receiving(*proto, si->sw_if_index, 0); + + return (WALK_CONTINUE); + } + +int +hicn_route_enable (fib_prefix_t *prefix) { + + int ret = HICN_ERROR_NONE; + fib_node_index_t fib_entry_index; + + /* Check if the route already exist in the fib */ + /* + * ASSUMPTION: we use table 0 which is the default table and it is + * already existing and locked + */ + u32 fib_index = fib_table_find(prefix->fp_proto, 0); + + fib_entry_index = fib_table_lookup_exact_match (fib_index, prefix); + + if (fib_entry_index == FIB_NODE_INDEX_INVALID) + { + fib_entry_index = fib_table_lookup (fib_index, prefix); + + fib_route_path_t * paths = fib_entry_encode(fib_entry_index); + + fib_table_entry_path_add2(fib_index, prefix, FIB_SOURCE_CLI, FIB_ENTRY_FLAG_NONE, paths); + } + + /* Check if the prefix is already enabled */ + u32 fib_hicn_index = fib_table_find(prefix->fp_proto, HICN_FIB_TABLE); + + fib_node_index_t fib_hicn_entry_index = fib_table_lookup_exact_match (fib_hicn_index, prefix); + + if (fib_hicn_entry_index == FIB_NODE_INDEX_INVALID) + { + dpo_id_t dpo = DPO_INVALID; + index_t dpo_idx; + default_dpo.hicn_dpo_create (prefix->fp_proto, 0, NEXT_HOP_INVALID, + &dpo_idx); + + /* the value we got when we registered */ + /* + * This should be taken from the name?!? the index of the + * object + */ + dpo_set (&dpo, + default_dpo.hicn_dpo_get_type (), + (ip46_address_is_ip4 (&prefix->fp_addr) ? DPO_PROTO_IP4 : + DPO_PROTO_IP6), dpo_idx); + + hicn_dpo_ctx_t * fib_entry = hicn_strategy_dpo_ctx_get(dpo_idx); + + fib_node_init (&fib_entry->fib_node, hicn_fib_node_type); + fib_node_lock (&fib_entry->fib_node); + + fib_entry->fib_entry_index = fib_entry_track (fib_index, + prefix, + hicn_fib_node_type, + dpo_idx, &fib_entry->fib_sibling); + + + /* Here is where we create the "via" like route */ + /* + * For the moment we use the global one the prefix you want + * to match Neale suggested -- FIB_SOURCE_HICN the client + * that is adding them -- no easy explanation at this time… + */ + CLIB_UNUSED (fib_node_index_t new_fib_node_index) = + fib_table_entry_special_dpo_add (fib_hicn_index, + prefix, + hicn_fib_src, + (FIB_ENTRY_FLAG_EXCLUSIVE | + FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT), + &dpo); + + sync_hicn_fib_entry(fib_entry); + + /* We added a route, therefore add one lock to the table */ + fib_table_lock (fib_index, prefix->fp_proto, hicn_fib_src); + + /* Enable the feature to punt data packet every time we enable a new hicn route + * For each enable there must be a disable to defenitely disable the feature + * + * We cannot enable only the interfaces on which we send out interest because + * Data packet might be coming on in different interfaces, as in che case of mpls + * tunnels (packets are received from the physical nic, not the mpls tunnel interface). + */ + vnet_main_t * vnm = vnet_get_main (); + vnet_sw_interface_walk(vnm, enable_data_receiving_new_fib_entry, &(prefix->fp_proto)); + + dpo_unlock (&dpo); + } + else + { + const dpo_id_t *load_balance_dpo_id; + const dpo_id_t *strategy_dpo_id; + + /* Route already existing. We need to update the dpo. */ + load_balance_dpo_id = + fib_entry_contribute_ip_forwarding (fib_hicn_entry_index); + + /* The dpo is not a load balance dpo as expected */ + if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) + { + ret = HICN_ERROR_ROUTE_NO_LD; + goto done; + } + else + { + load_balance_t *lb = + load_balance_get (load_balance_dpo_id->dpoi_index); + + strategy_dpo_id = load_balance_get_bucket_i (lb, 0); + + if (!dpo_is_hicn (strategy_dpo_id)) + { + ret = HICN_ERROR_ROUTE_DPO_NO_HICN; + goto done; + } + + if (lb->lb_n_buckets > 1) + { + ret = HICN_ERROR_ROUTE_MLT_LD; + goto done; + } + + hicn_dpo_ctx_t * hicn_fib_entry = hicn_strategy_dpo_ctx_get(strategy_dpo_id->dpoi_index); + + sync_hicn_fib_entry(hicn_fib_entry); + } + } + + done: + return ret; +} + +int +hicn_route_disable (fib_prefix_t *prefix) { + + int ret = HICN_ERROR_NONE; + + /* Check if the prefix is already enabled */ + u32 fib_hicn_index = fib_table_find(prefix->fp_proto, HICN_FIB_TABLE); + + fib_node_index_t fib_hicn_entry_index = fib_table_lookup_exact_match (fib_hicn_index, prefix); + + if (fib_hicn_entry_index == FIB_NODE_INDEX_INVALID) + { + return HICN_ERROR_ROUTE_NOT_FOUND; + } + else + { + const dpo_id_t *load_balance_dpo_id; + const dpo_id_t *strategy_dpo_id; + hicn_dpo_ctx_t * hicn_fib_entry; + + /* Route already existing. We need to update the dpo. */ + load_balance_dpo_id = + fib_entry_contribute_ip_forwarding (fib_hicn_entry_index); + + /* The dpo is not a load balance dpo as expected */ + if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) + { + ret = HICN_ERROR_ROUTE_NO_LD; + goto done; + } + else + { + load_balance_t *lb = + load_balance_get (load_balance_dpo_id->dpoi_index); + + strategy_dpo_id = load_balance_get_bucket_i (lb, 0); + + if (!dpo_is_hicn (strategy_dpo_id)) + { + ret = HICN_ERROR_ROUTE_DPO_NO_HICN; + goto done; + } + + if (lb->lb_n_buckets > 1) + { + ret = HICN_ERROR_ROUTE_MLT_LD; + goto done; + } + + hicn_fib_entry = hicn_strategy_dpo_ctx_get(strategy_dpo_id->dpoi_index); + + for (int i = 0; i < hicn_fib_entry->entry_count; i++) + { + hicn_strategy_dpo_ctx_del_nh(hicn_fib_entry->next_hops[i], hicn_fib_entry); + } + } + + fib_entry_untrack(hicn_fib_entry->fib_entry_index, hicn_fib_entry->fib_sibling); + + fib_table_entry_special_remove (fib_hicn_index, prefix, hicn_fib_src); + + /* Disable the feature to punt data packet every time we enable a new hicn route */ + vnet_main_t * vnm = vnet_get_main (); + vnet_sw_interface_walk(vnm, disable_data_receiving_rm_fib_entry, &(prefix->fp_proto)); + } + + done: + return ret; +} + + +static fib_node_t * +hicn_ctx_node_get (fib_node_index_t index) +{ + hicn_dpo_ctx_t * hicn_ctx; + + hicn_ctx = hicn_strategy_dpo_ctx_get(index); + + return (&hicn_ctx->fib_node); +} + +static void +hicn_fib_last_lock_gone (fib_node_t *node) +{ +} + +static hicn_dpo_ctx_t * +hicn_ctx_from_fib_node (fib_node_t * node) +{ + return ((hicn_dpo_ctx_t *) (((char *) node) - + STRUCT_OFFSET_OF (hicn_dpo_ctx_t, fib_node))); +} + +static fib_node_back_walk_rc_t +hicn_fib_back_walk_notify (fib_node_t *node, + fib_node_back_walk_ctx_t *ctx) +{ + + hicn_dpo_ctx_t *fib_entry = hicn_ctx_from_fib_node (node); + + sync_hicn_fib_entry(fib_entry); + + return (FIB_NODE_BACK_WALK_CONTINUE); +} + +static void +hicn_fib_show_memory (void) +{ +} + + +static const fib_node_vft_t hicn_fib_vft = +{ + .fnv_get = hicn_ctx_node_get, + .fnv_last_lock = hicn_fib_last_lock_gone, + .fnv_back_walk = hicn_fib_back_walk_notify, + .fnv_mem_show = hicn_fib_show_memory, +}; + +fib_table_walk_rc_t enable_data_on_existing_hicn(fib_node_index_t fei, + void *ctx) +{ + u32 sw_if = *(u32 *)ctx; + const dpo_id_t *load_balance_dpo_id; + const dpo_id_t *strategy_dpo_id; + + /* Route already existing. We need to update the dpo. */ + load_balance_dpo_id = + fib_entry_contribute_ip_forwarding (fei); + + /* The dpo is not a load balance dpo as expected */ + if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) + { + goto done; + } + else + { + load_balance_t *lb = + load_balance_get (load_balance_dpo_id->dpoi_index); + + strategy_dpo_id = load_balance_get_bucket_i (lb, 0); + + if (!dpo_is_hicn (strategy_dpo_id)) + { + goto done; + } + + enable_disable_data_receiving (strategy_dpo_id->dpoi_proto, sw_if, 1); + } + + done: + return (FIB_TABLE_WALK_CONTINUE); +} + +static clib_error_t * +set_table_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add) +{ + + if (!is_add) + return HICN_ERROR_NONE; + + vnet_sw_interface_t * sw_int = vnet_get_sw_interface(vnm, sw_if_index); + vnet_hw_interface_t * hw_int = vnet_get_hw_interface(vnm, sw_int->hw_if_index); + + char * mpls = "mpls"; + if (strstr((char *)hw_int->name, mpls) == NULL) + return 0; + + int rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, HICN_FIB_TABLE, 1); + + if (!rv) + { + rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, HICN_FIB_TABLE, 1); + + if (rv) + { + /* An error occurred. Bind the interface back to the default fib */ + ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, 0, 1); + } + } + + u32 fib_index = fib_table_find(FIB_PROTOCOL_IP4, + HICN_FIB_TABLE); + if (fib_index != ~0) + { + /* + * Walk the ip4 and ip6 fib tables to discover existing hicn fib entries. + * For each of them we need to enable the feature to punt data packets. + */ + fib_table_walk(fib_index, + FIB_PROTOCOL_IP4, + enable_data_on_existing_hicn, + &sw_if_index); + } + + fib_index = fib_table_find(FIB_PROTOCOL_IP6, + HICN_FIB_TABLE); + if (fib_index != ~0) + { + fib_table_walk(fib_index, + FIB_PROTOCOL_IP6, + enable_data_on_existing_hicn, + &sw_if_index); + } + + return rv ? clib_error_return (0, "unable to add hicn table to interface") : 0; +} + +VNET_SW_INTERFACE_ADD_DEL_FUNCTION (set_table_interface_add_del); + +void +hicn_route_init () +{ + vnet_main_t * vnm = vnet_get_main (); + vlib_main_t * vm = vlib_get_main (); + hicn_fib_src = fib_source_allocate ("hicn", + FIB_SOURCE_HICN, FIB_SOURCE_BH_API); + + hicn_fib_node_type = fib_node_register_new_type(&hicn_fib_vft); + + ip_table_create(FIB_PROTOCOL_IP4, HICN_FIB_TABLE, 1, (const u8 *)"hicn4"); + ip_table_create(FIB_PROTOCOL_IP6, HICN_FIB_TABLE, 1, (const u8 *)"hicn6"); + + u32 sw_if_index; + u8 mac_address[6]; + u8 is_specified = 0; + u32 user_instance = 0; + + vnet_create_loopback_interface (&sw_if_index, mac_address, + is_specified, user_instance); + + localhost4.as_u8[0] = 127; + localhost4.as_u8[3] = 1; + u32 length4 = 32, length6 = 128, is_del = 0, flags = 0; + + localhost6.as_u8[15] = 1; + + ip4_add_del_interface_address (vm, sw_if_index, &localhost4, length4, is_del); + ip6_add_del_interface_address (vm, sw_if_index, &localhost6, length6, is_del); + + flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP; + vnet_sw_interface_set_flags (vnm, sw_if_index, flags); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/route.h b/hicn-plugin/src/network/route.h new file mode 100644 index 000000000..a1ba86b3d --- /dev/null +++ b/hicn-plugin/src/network/route.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2017-2020 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_ROUTE__ +#define __HICN_ROUTE__ + +#include +#include +#include "hicn.h" +#include "faces/face.h" + +/** + * @file route.h + * + * hICN uses a specific vrf to install the routes for a prefix has been enabled to + * be hicn. It considers the vrf 0 (the default vrf) as the dominating vrf on + * which every route is stored. Enabling a prefix to be hICN will copy all the routes + * in the vrf 0 for the given prefi, in the vrf HICN. Every modification made on the + * vrf 0 on an hICN enabled prefix is reflected in the vrf hICN (through the use of + * the fib entry tracking functionality). Moreover, we use the lookup in the vrf hICN + * as a way for punting packet that must be processed as hICN. The implementation will + * install a special dpo as a single next hop for the vpp load balancer for each entry + * in the vrf hICN that we enabled. Such dpo will have two purposes: 1) to punt packets + * to the hICN forwarding pipeline, 2) to point to the righe strategy (the dpoi_index will + * be an index to the strategy context while the dpoi_type will be an index to the strategy vft). + * + * Additionally, hICN assign each interface to the vrf hICN; this is required for + * the interest lookup. Vpp performs a lookup in the vrf assigned to the interface, + * therefore if an interface is not assigned to the hICN vrf, the lookup will be done + * on the vrf 0 and the packet won't be processed through the hicn forwarding pipeline. + */ + +/* + * Adding each interface to the vrf hICN has the side effect that to ping you need to + * specify the vrf hICN in the command. + */ + +extern fib_source_t hicn_fib_src; + +extern dpo_type_t udp_encap_dpo_types[FIB_PROTOCOL_MAX]; + +/** + * @Brief Return the hicn_dpo corresponding to the prefix in teh vrf HICN + * + * @param prefix Prefix for which we want to retrieve the hICN dpo + * @param hicn_dpo return value with the hicn_dpo + * @param fib_index return value with the fib index corresponding to the prefix + */ +int +hicn_route_get_dpo (const fib_prefix_t * prefix, + const dpo_id_t ** hicn_dpo, u32 * fib_index); + + +/** + * @Brief Set the strategy for a given prefix + * + * @param prefix Prefix for which we set the strategy + * @param stretegy_id Index of the strategy to set + */ +int +hicn_route_set_strategy (fib_prefix_t * prefix, u32 strategy_id); + +/** + * @Brief Helper to add a nex hop in the vrf 0. If there are no entries in the + * vrf 0 that matches with the prefix (epm), a new one is created. + * + * @param fib_proto FIB_PROTOCOL_IP6 or FIB_PROTOCOL_IP4 (mpls not supported) + * @param pfx Prefix for which to add a next hop + * @param nh Next hop to add + * @param sw_if Software interface index to add in the next hop + */ +int +ip_nh_add_helper (fib_protocol_t fib_proto, const fib_prefix_t * pfx, ip46_address_t * nh, u32 sw_if); + +/** + * @Brief Helper to remove a nex hop in the vrf 0. If there are no entries in the + * vrf 0 nothing happens. + * + * @param fib_proto FIB_PROTOCOL_IP6 or FIB_PROTOCOL_IP4 (mpls not supported) + * @param pfx Prefix for which to remove a next hop + * @param nh Next hop to remove + * @param sw_if Software interface index in the next hop definition + */ +int +ip_nh_del_helper (fib_protocol_t fib_proto, const fib_prefix_t * rpfx, ip46_address_t * nh, u32 sw_if); + +/** + * @Brief Enable an hICN for an ip prefix + * + * @param prefix Prefix for which we enable hICN + * @return HICN_ERROR_NONE if hICN was enabled on the prefix + * HICN_ERROR_ROUTE_NO_LD if the first dpo for the fib entry corresponding to the prefix is not a load_balancer + * HICN_ERROR_ROUTE_DPO_NO_HICN if the loadbalancer in the vrf HICN already contains a dpo which is not an hICN one + * HICN_ERROR_ROUTE_MLT_LD if there are more than a dpo in the vpp loadbalancer + */ +int +hicn_route_enable (fib_prefix_t *prefix); + +/** + * @Brief Disable an hICN for an ip prefix. If hICN wasn't enable on the prefix + * nothing happens and it returns HICN_ERROR_ROUTE_NOT_FOUND + * + * @param prefix Prefix for which we disable hICN + */ +int +hicn_route_disable (fib_prefix_t *prefix); + + +/* Init route internal strustures */ +void +hicn_route_init(); +#endif /* //__HICN_ROUTE__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/state.h b/hicn-plugin/src/network/state.h new file mode 100644 index 000000000..37003d0ae --- /dev/null +++ b/hicn-plugin/src/network/state.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017-2020 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_STATE__ +#define __HICN_STATE__ + +#include +#include + +#include "hicn.h" +#include "pcs.h" +#include "hashtb.h" +#include "strategy.h" +#include "strategy_dpo_ctx.h" +#include "strategy_dpo_manager.h" + +/** + * @file plugin_state + * + * Helper functions to hicn state (hash node, hash entry, strategy vft, dpo vft and dpo context id) + * + */ + +//TODO exploit this state to prefetch hash nodes and entries. + +/** + * @brief Retrieve the hicn state + * + * @param hicnb hicn buffer used to retrieve the hicn state + * @param pitcs pointer to PIT/CS + * @param node node in the hash table referring to the buffer + * @param strategy_vft return value pointing to the strategy vft corresponding to the buffer + * @param dpo_vft return value pointing to the dpo vft corresponding to the buffer + * @param dpo_ctx_id return value pointing to the dpo context id corresponding to the buffer + * @param hash_entry entry in the hash table referring to the buffer + */ +always_inline void +hicn_get_internal_state (hicn_buffer_t * hicnb, hicn_pit_cs_t * pitcs, + hicn_hash_node_t ** node, + const hicn_strategy_vft_t ** strategy_vft, + const hicn_dpo_vft_t ** dpo_vft, u8 * dpo_ctx_id, + hicn_hash_entry_t ** hash_entry) +{ + *node = pool_elt_at_index (pitcs->pcs_table->ht_nodes, hicnb->node_id); + *strategy_vft = hicn_dpo_get_strategy_vft (hicnb->vft_id); + *dpo_vft = hicn_dpo_get_vft (hicnb->vft_id); + *dpo_ctx_id = hicnb->dpo_ctx_id; + + hicn_hash_bucket_t *bucket; + if (hicnb->hash_bucket_flags & HICN_HASH_NODE_OVERFLOW_BUCKET) + bucket = + pool_elt_at_index (pitcs->pcs_table->ht_overflow_buckets, + hicnb->bucket_id); + else + bucket = + (hicn_hash_bucket_t *) (pitcs->pcs_table->ht_buckets + + hicnb->bucket_id); + + *hash_entry = &(bucket->hb_entries[hicnb->hash_entry_id]); +} + +/* + * This function set the PCS entry index, the dpo index and the vft index in + * the opaque2 buffer. In this way, the interest-hitpit and interest-hitcs + * nodes can prefetch the corresponding state (PIT entry, dpo_ctx and the + * strategy vft + */ +/** + * @brief Store the hicn state in the hicn buffer + * + * @param b vlib buffer holding the hICN packet + * @param name_hash hash of the hICN name + * @param node_id id of the node in the hash table referring to the buffer + * @param dpo_ctx_id id of the dpo context id corresponding to the buffer + * @param vft_id id of the strategy vft corresponding to the buffer + * @param hash_entry_id id of the entry in the hash table referring to the buffer + * @param bucket_id id of the hasth table bucket that holds the hash entry + * @param bucket_is_overflow 1 if the bucket is from the ht_overflow_buckets pool + * 0 if the bucket is from the ht_buckets pool + */ +always_inline void +hicn_store_internal_state (vlib_buffer_t * b, u64 name_hash, u32 node_id, + u8 dpo_ctx_id, u8 vft_id, u8 hash_entry_id, + u32 bucket_id, u8 bucket_is_overflow) +{ + hicn_buffer_t *hicnb = hicn_get_buffer (b); + hicnb->name_hash = name_hash; + hicnb->node_id = node_id; + hicnb->dpo_ctx_id = dpo_ctx_id; + hicnb->vft_id = vft_id; + hicnb->hash_entry_id = hash_entry_id; + hicnb->bucket_id = bucket_id; + hicnb->hash_bucket_flags = + HICN_HASH_NODE_OVERFLOW_BUCKET * bucket_is_overflow; +} + +#endif /* // __HICN_STATE__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/strategies/dpo_mw.c b/hicn-plugin/src/network/strategies/dpo_mw.c new file mode 100644 index 000000000..12c77bce8 --- /dev/null +++ b/hicn-plugin/src/network/strategies/dpo_mw.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2017-2020 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 "dpo_mw.h" +#include "strategy_mw.h" +#include "../strategy_dpo_manager.h" +#include "../strategy_dpo_ctx.h" + +/** + * @brief DPO type value for the mw_strategy + */ +static dpo_type_t hicn_dpo_type_mw; + +static const hicn_dpo_vft_t hicn_dpo_mw_vft = { + .hicn_dpo_is_type = &hicn_dpo_is_type_strategy_mw, + .hicn_dpo_get_type = &hicn_dpo_strategy_mw_get_type, + .hicn_dpo_module_init = &hicn_dpo_strategy_mw_module_init, + .hicn_dpo_create = &hicn_strategy_mw_ctx_create, + .hicn_dpo_add_update_nh = &hicn_strategy_mw_ctx_add_nh, + .hicn_dpo_del_nh = &hicn_strategy_mw_ctx_del_nh, + .hicn_dpo_format = &hicn_strategy_mw_format_ctx +}; + +int +hicn_dpo_is_type_strategy_mw (const dpo_id_t * dpo) +{ + return dpo->dpoi_type == hicn_dpo_type_mw; +} + +void +hicn_dpo_strategy_mw_module_init (void) +{ + /* + * Register our type of dpo + */ + hicn_dpo_type_mw = + hicn_dpo_register_new_type (hicn_nodes_strategy, &hicn_dpo_mw_vft, + hicn_mw_strategy_get_vft (), + &dpo_strategy_mw_ctx_vft); +} + +dpo_type_t +hicn_dpo_strategy_mw_get_type (void) +{ + return hicn_dpo_type_mw; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + + +u8 * +hicn_strategy_mw_format_ctx (u8 * s, int n, ...) +{ + va_list args; + va_start (args, n); + s = format_hicn_strategy_mw_ctx (s, &args); + return s; +} + +u8 * +format_hicn_strategy_mw_ctx (u8 * s, va_list * ap) +{ + int i = 0; + index_t index = va_arg (*ap, index_t); + hicn_dpo_ctx_t *dpo_ctx = NULL; + hicn_strategy_mw_ctx_t *mw_dpo_ctx = NULL; + u32 indent = va_arg (*ap, u32);; + + dpo_ctx = hicn_strategy_dpo_ctx_get (index); + if (dpo_ctx == NULL) + return s; + + mw_dpo_ctx = (hicn_strategy_mw_ctx_t *) dpo_ctx->data; + + s = format (s, "hicn-mw"); + for (i = 0; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; i++) + { + u8 *buf = NULL; + if (i < dpo_ctx->entry_count) + buf = format (NULL, "FIB"); + else if (i >= + HICN_PARAM_FIB_ENTRY_NHOPS_MAX - dpo_ctx->tfib_entry_count) + buf = format (NULL, "TFIB"); + else + continue; + + s = format (s, "\n"); + s = + format (s, "%U ", format_hicn_face, dpo_ctx->next_hops[i], + indent); + s = format (s, "weight %u", mw_dpo_ctx->weight[i]); + s = format (s, " %s", buf); + } + + return (s); +} + +void +hicn_strategy_mw_ctx_create (fib_protocol_t proto, const hicn_face_id_t * next_hop, + int nh_len, index_t * dpo_idx) +{ + hicn_strategy_mw_ctx_t *hicn_strategy_mw_ctx; + hicn_dpo_ctx_t *hicn_strategy_ctx; + + /* Allocate a hicn_dpo_ctx on the vpp pool and initialize it */ + hicn_strategy_ctx = hicn_strategy_dpo_ctx_alloc (); + hicn_strategy_mw_ctx = (hicn_strategy_mw_ctx_t *) hicn_strategy_ctx->data; + + *dpo_idx = hicn_strategy_dpo_ctx_get_index (hicn_strategy_ctx); + + init_dpo_ctx (hicn_strategy_ctx, next_hop, nh_len, hicn_dpo_type_mw, proto); + + memset (hicn_strategy_mw_ctx->weight, 0, HICN_PARAM_FIB_ENTRY_NHOPS_MAX); +} + +int +hicn_strategy_mw_ctx_add_nh (hicn_face_id_t nh, index_t dpo_idx) +{ + hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx); + u8 pos = 0; + + if (hicn_strategy_dpo_ctx == NULL) + { + return HICN_ERROR_STRATEGY_NOT_FOUND; + } + + hicn_strategy_dpo_ctx_add_nh (nh, hicn_strategy_dpo_ctx, &pos); + hicn_strategy_mw_ctx_t *hicn_strategy_mw_ctx = + (hicn_strategy_mw_ctx_t *) & hicn_strategy_dpo_ctx->data; + + hicn_strategy_mw_ctx->weight[pos] = DEFAULT_WEIGHT; + return HICN_ERROR_NONE; +} + +int +hicn_strategy_mw_ctx_del_nh (hicn_face_id_t face_id, index_t dpo_idx) +{ + hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx); + //No need to flush the weights, they are initialized when a dpo_ctx is created; + return hicn_strategy_dpo_ctx_del_nh (face_id, hicn_strategy_dpo_ctx); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/strategies/dpo_mw.h b/hicn-plugin/src/network/strategies/dpo_mw.h new file mode 100644 index 000000000..433c415fb --- /dev/null +++ b/hicn-plugin/src/network/strategies/dpo_mw.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2017-2020 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_DPO_MW_H__ +#define __HICN_DPO_MW_H__ + +#include +#include "../strategy_dpo_ctx.h" + +/** + * @file dpo_mw.h + * + * This file implements the strategy vtf (see strategy.h) and + * the dpo vft (see strategy_dpo_manager.h) for the strategy + * maximum weight + */ + +#define DEFAULT_WEIGHT 0 + +typedef struct hicn_strategy_mw_ctx_s +{ + u8 weight[HICN_PARAM_FIB_ENTRY_NHOPS_MAX]; +} hicn_strategy_mw_ctx_t; + +/** + * @brief Format the dpo ctx for a human-readable string + * + * @param s String to which to append the formatted dpo ctx + * @param ap List of parameters for the formatting + * + * @result The string with the formatted dpo ctx + */ +u8 *format_hicn_strategy_mw_ctx (u8 * s, va_list * ap); + +const static dpo_vft_t dpo_strategy_mw_ctx_vft = { + .dv_lock = hicn_strategy_dpo_ctx_lock, + .dv_unlock = hicn_strategy_dpo_ctx_unlock, + .dv_format = format_hicn_strategy_mw_ctx, +}; + +/** + * @brief Retrieve an hicn_strategy_mw_ctx object + * + * @param indext Index of the hicn_dpo_ctx to retrieve + * @return The hicn_dpo_ctx object or NULL + */ +hicn_dpo_ctx_t *hicn_strategy_mw_ctx_get (index_t index); + +/** + * @brief Create a new mw ctx + * + * @param proto The protocol to which the dpo is meant for (see vpp docs) + * @param next_hop A list of next hops to be inserted in the dpo ctx + * @param nh_len Size of the list + * @param dpo_idx index_t that will hold the index of the created dpo ctx + * @return HICN_ERROR_NONE if the creation was fine, otherwise EINVAL + */ +void +hicn_strategy_mw_ctx_create (fib_protocol_t proto, const hicn_face_id_t * next_hop, + int nh_len, index_t * dpo_idx); + +/** + * @brief Add or update a next hop in the dpo ctx. + * + * This function is meant to be used in the control plane and not in the data plane, + * as it is not optimized for the latter. + * + * @param nh Next hop to insert in the dpo ctx + * @param dpo_idx Index of the dpo ctx to update with the new or updated next + * hop + * @return HICN_ERROR_NONE if the update or insert was fine, + * otherwise HICN_ERROR_DPO_CTX_NOT_FOUND + */ +int hicn_strategy_mw_ctx_add_nh (hicn_face_id_t nh, index_t dpo_idx); + +/** + * @brief Delete a next hop in the dpo ctx. + * + * @param face_id Face identifier of the next hop + * @param dpo_idx Index of the dpo ctx to update with the new or updated next + * hop + * @return HICN_ERROR_NONE if the update or insert was fine, + * otherwise HICN_ERROR_DPO_CTS_NOT_FOUND + */ +int hicn_strategy_mw_ctx_del_nh (hicn_face_id_t face_id, index_t dpo_idx); + +/** + * @brief Prefetch a dpo + * + * @param dpo_idx Index of the dpo ctx to prefetch + */ +void hicn_strategy_mw_ctx_prefetch (index_t dpo_idx); + +/** + * @brief Return true if the dpo is of type strategy mw + * + * @param dpo Dpo to check the type + */ +int hicn_dpo_is_type_strategy_mw (const dpo_id_t * dpo); + +/** + * @brief Initialize the Maximum Weight strategy + */ +void hicn_dpo_strategy_mw_module_init (void); + +/** + * @brief Return the dpo type for the Maximum Weight strategy + */ +dpo_type_t hicn_dpo_strategy_mw_get_type (void); + +/** + * @brief Format the dpo ctx for the strategy Maximum Weight + * + * @param s String to append the formatted dpo ctx + * @param ap List of arguments to format + */ +u8 *format_hicn_dpo_strategy_mw (u8 * s, va_list * ap); + +/** + * @brief Format the dpo ctx for the strategy Maximum Weight. To + * call from other functions + * + * @param s String to append the formatted dpo ctx + * @param ... List of arguments to format + */ +u8 *hicn_strategy_mw_format_ctx (u8 * s, int n, ...); + + +#endif // __HICN_DPO_MW_H__ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/strategies/dpo_rr.c b/hicn-plugin/src/network/strategies/dpo_rr.c new file mode 100644 index 000000000..adb7e1025 --- /dev/null +++ b/hicn-plugin/src/network/strategies/dpo_rr.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2017-2020 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 "dpo_rr.h" +#include "strategy_rr.h" +#include "../strategy_dpo_manager.h" +#include "../strategy_dpo_ctx.h" + +/** + * @brief DPO type value for the rr_strategy + */ +static dpo_type_t hicn_dpo_type_rr; + +static const hicn_dpo_vft_t hicn_dpo_rr_vft = { + .hicn_dpo_is_type = &hicn_dpo_is_type_strategy_rr, + .hicn_dpo_get_type = &hicn_dpo_strategy_rr_get_type, + .hicn_dpo_module_init = &hicn_dpo_strategy_rr_module_init, + .hicn_dpo_create = &hicn_strategy_rr_ctx_create, + .hicn_dpo_add_update_nh = &hicn_strategy_rr_ctx_add_nh, + .hicn_dpo_del_nh = &hicn_strategy_rr_ctx_del_nh, + .hicn_dpo_format = &hicn_strategy_rr_format_ctx +}; + +int +hicn_dpo_is_type_strategy_rr (const dpo_id_t * dpo) +{ + return dpo->dpoi_type == hicn_dpo_type_rr; +} + +void +hicn_dpo_strategy_rr_module_init (void) +{ + /* + * Register our type of dpo + */ + hicn_dpo_type_rr = + hicn_dpo_register_new_type (hicn_nodes_strategy, &hicn_dpo_rr_vft, + hicn_rr_strategy_get_vft (), + &dpo_strategy_rr_ctx_vft); +} + +dpo_type_t +hicn_dpo_strategy_rr_get_type (void) +{ + return hicn_dpo_type_rr; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + + +u8 * +hicn_strategy_rr_format_ctx (u8 * s, int n, ...) +{ + va_list args; + va_start (args, n); + s = format_hicn_strategy_rr_ctx (s, &args); + return s; +} + +u8 * +format_hicn_strategy_rr_ctx (u8 * s, va_list * ap) +{ + int i = 0; + index_t index = va_arg (*ap, index_t); + hicn_dpo_ctx_t *dpo_ctx = NULL; + hicn_strategy_rr_ctx_t *rr_dpo_ctx = NULL; + u32 indent = va_arg (*ap, u32); + + dpo_ctx = hicn_strategy_dpo_ctx_get (index); + if (dpo_ctx == NULL) + return s; + + rr_dpo_ctx = (hicn_strategy_rr_ctx_t *) dpo_ctx->data; + + s = + format (s, "hicn-rr, next hop Face %d", + dpo_ctx->next_hops[rr_dpo_ctx->current_nhop]); + + for (i = 0; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; i++) + { + u8 *buf = NULL; + if (i < dpo_ctx->entry_count) + buf = format (NULL, "FIB"); + else if (i >= + HICN_PARAM_FIB_ENTRY_NHOPS_MAX - dpo_ctx->tfib_entry_count) + buf = format (NULL, "TFIB"); + else + continue; + + s = format (s, "\n"); + s = + format (s, "%U ", format_hicn_face, dpo_ctx->next_hops[i], + indent); + s = format (s, " %s", buf); + } + + return (s); +} + +void +hicn_strategy_rr_ctx_create (fib_protocol_t proto, const hicn_face_id_t * next_hop, + int nh_len, index_t * dpo_idx) +{ + hicn_strategy_rr_ctx_t *hicn_strategy_rr_ctx; + hicn_dpo_ctx_t *hicn_strategy_ctx; + + /* Allocate a hicn_dpo_ctx on the vpp pool and initialize it */ + hicn_strategy_ctx = hicn_strategy_dpo_ctx_alloc (); + hicn_strategy_rr_ctx = (hicn_strategy_rr_ctx_t *) hicn_strategy_ctx->data; + + *dpo_idx = hicn_strategy_dpo_ctx_get_index (hicn_strategy_ctx); + + init_dpo_ctx (hicn_strategy_ctx, next_hop, nh_len, hicn_dpo_type_rr, proto); + + hicn_strategy_rr_ctx->current_nhop = 0; +} + +int +hicn_strategy_rr_ctx_add_nh (hicn_face_id_t nh, index_t dpo_idx) +{ + hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx); + u8 pos = 0; + + if (hicn_strategy_dpo_ctx == NULL) + { + return HICN_ERROR_STRATEGY_NOT_FOUND; + } + + hicn_strategy_dpo_ctx_add_nh (nh, hicn_strategy_dpo_ctx, &pos); + //nothing else to initialize in this strategy + return HICN_ERROR_NONE; +} + +int +hicn_strategy_rr_ctx_del_nh (hicn_face_id_t face_id, index_t dpo_idx) +{ + hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx); + //No need to change the current_nhop. It will be updated at the next selection. + return hicn_strategy_dpo_ctx_del_nh (face_id, hicn_strategy_dpo_ctx); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/strategies/dpo_rr.h b/hicn-plugin/src/network/strategies/dpo_rr.h new file mode 100644 index 000000000..e4e5b5372 --- /dev/null +++ b/hicn-plugin/src/network/strategies/dpo_rr.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2017-2020 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_DPO_RR_H__ +#define __HICN_DPO_RR_H__ + +#include +#include "../strategy_dpo_ctx.h" + +/** + * @file dpo_rr.h + * + * This file implements the strategy vtf (see strategy.h) and + * the dpo vft (see strategy_dpo_manager.h) for the strategy + * round robin. + */ + + +/** + * Context for the Round Robin strategy + */ + +typedef struct hicn_strategy_rr_ctx_s +{ + u8 current_nhop; +} hicn_strategy_rr_ctx_t; + +/** + * @brief Format the dpo ctx for a human-readable string + * + * @param s String to which to append the formatted dpo ctx + * @param ap List of parameters for the formatting + * + * @result The string with the formatted dpo ctx + */ +u8 *format_hicn_strategy_rr_ctx (u8 * s, va_list * ap); + +const static dpo_vft_t dpo_strategy_rr_ctx_vft = { + .dv_lock = hicn_strategy_dpo_ctx_lock, + .dv_unlock = hicn_strategy_dpo_ctx_unlock, + .dv_format = format_hicn_strategy_rr_ctx, +}; + +/** + * @brief Retrieve an hicn_strategy_rr_ctx object + * + * @param indext Index of the hicn_dpo_ctx to retrieve + * @return The hicn_dpo_ctx object or NULL + */ +hicn_dpo_ctx_t *hicn_strategy_rr_ctx_get (index_t index); + +/** + * @brief Create a new round robin ctx + * + * @param proto The protocol to which the dpo is meant for (see vpp docs) + * @param next_hop A list of next hops to be inserted in the dpo ctx + * @param nh_len Size of the list + * @param dpo_idx index_t that will hold the index of the created dpo ctx + * @return HICN_ERROR_NONE if the creation was fine, otherwise EINVAL + */ +void +hicn_strategy_rr_ctx_create (fib_protocol_t proto, const hicn_face_id_t * next_hop, + int nh_len, index_t * dpo_idx); + +/** + * @brief Add or update a next hop in the dpo ctx. + * + * This function is meant to be used in the control plane and not in the data plane, + * as it is not optimized for the latter. + * + * @param nh Next hop to insert in the dpo ctx + * @param dpo_idx Index of the dpo ctx to update with the new or updated next + * hop + * @return HICN_ERROR_NONE if the update or insert was fine, + * otherwise HICN_ERROR_DPO_CTX_NOT_FOUND + */ +int hicn_strategy_rr_ctx_add_nh (hicn_face_id_t nh, index_t dpo_idx); + +/** + * @brief Delete a next hop in the dpo ctx. + * + * @param face_id Face identifier of the next hop + * @param dpo_idx Index of the dpo ctx to update with the new or updated next + * hop + * @return HICN_ERROR_NONE if the update or insert was fine, + * otherwise HICN_ERROR_DPO_CTS_NOT_FOUND + */ +int hicn_strategy_rr_ctx_del_nh (hicn_face_id_t face_id, index_t dpo_idx); + +/** + * @brief Prefetch a dpo + * + * @param dpo_idx Index of the dpo ctx to prefetch + */ +void hicn_strategy_rr_ctx_prefetch (index_t dpo_idx); + +/** + * @brief Return true if the dpo is of type strategy rr + * + * @param dpo Dpo to check the type + */ +int hicn_dpo_is_type_strategy_rr (const dpo_id_t * dpo); + +/** + * @brief Initialize the Round Robin strategy + */ +void hicn_dpo_strategy_rr_module_init (void); + +/** + * @brief Return the dpo type for the Round Robin strategy + */ +dpo_type_t hicn_dpo_strategy_rr_get_type (void); + +/** + * @brief Format the dpo ctx for the strategy Round Robin + * + * @param s String to append the formatted dpo ctx + * @param ap List of arguments to format + */ +u8 *format_hicn_dpo_strategy_rr (u8 * s, va_list * ap); + +/** + * @brief Format the dpo ctx for the strategy Round Robin. To + * call from other functions + * + * @param s String to append the formatted dpo ctx + * @param ... List of arguments to format + */ +u8 *hicn_strategy_rr_format_ctx (u8 * s, int n, ...); + + +#endif // __HICN_DPO_RR_H__ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/strategies/strategy_mw.c b/hicn-plugin/src/network/strategies/strategy_mw.c new file mode 100644 index 000000000..fe4d5896a --- /dev/null +++ b/hicn-plugin/src/network/strategies/strategy_mw.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017-2020 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 "dpo_mw.h" +#include "../strategy.h" +#include "../strategy_dpo_ctx.h" +#include "../faces/face.h" +#include "../hashtb.h" +#include "../strategy_dpo_manager.h" + +/* Simple strategy that chooses the next hop with the maximum weight */ +/* It does not require to exend the hicn_dpo */ +void hicn_receive_data_mw (index_t dpo_idx, int nh_idx); +void hicn_add_interest_mw (index_t dpo_idx, hicn_hash_entry_t * pit_entry); +void hicn_on_interest_timeout_mw (index_t dpo_idx); +u32 hicn_select_next_hop_mw (index_t dpo_idx, int *nh_idx, + hicn_face_id_t* outface); +u32 get_strategy_node_index_mw (void); +u8 *hicn_strategy_format_trace_mw (u8 * s, hicn_strategy_trace_t * t); +u8 *hicn_strategy_format_mw (u8 * s, va_list * ap); + + +static hicn_strategy_vft_t hicn_strategy_mw_vft = { + .hicn_receive_data = &hicn_receive_data_mw, + .hicn_add_interest = &hicn_add_interest_mw, + .hicn_on_interest_timeout = &hicn_on_interest_timeout_mw, + .hicn_select_next_hop = &hicn_select_next_hop_mw, + .hicn_format_strategy_trace = hicn_strategy_format_trace_mw, + .hicn_format_strategy = &hicn_strategy_format_mw +}; + +/* + * Return the vft of the strategy. + */ +hicn_strategy_vft_t * +hicn_mw_strategy_get_vft (void) +{ + return &hicn_strategy_mw_vft; +} + +/* DPO should be give in input as it containes all the information to calculate the next hops*/ +u32 +hicn_select_next_hop_mw (index_t dpo_idx, int *nh_idx, hicn_face_id_t* outface) +{ + hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx); + + if (dpo_ctx == NULL) + return HICN_ERROR_STRATEGY_NOT_FOUND; + + hicn_strategy_mw_ctx_t *hicn_strategy_mw_ctx = + (hicn_strategy_mw_ctx_t *) dpo_ctx->data; + + u8 next_hop_index = 0; + for (int i = 0; i < dpo_ctx->entry_count; i++) + { + if (hicn_strategy_mw_ctx->weight[next_hop_index] < + hicn_strategy_mw_ctx->weight[i]) + { + next_hop_index = i; + } + } + + *outface = dpo_ctx->next_hops[next_hop_index]; + + return HICN_ERROR_NONE; +} + +void +hicn_add_interest_mw (index_t dpo_ctx_idx, hicn_hash_entry_t * hash_entry) +{ + hash_entry->dpo_ctx_id = dpo_ctx_idx; + dpo_id_t hicn_dpo_id = + { hicn_dpo_strategy_mw_get_type (), 0, 0, dpo_ctx_idx }; + hicn_strategy_dpo_ctx_lock (&hicn_dpo_id); + hash_entry->vft_id = hicn_dpo_get_vft_id (&hicn_dpo_id); +} + +void +hicn_on_interest_timeout_mw (index_t dpo_idx) +{ + /* Nothign to do in the mw strategy when we receive an interest */ +} + +void +hicn_receive_data_mw (index_t dpo_idx, int nh_idx) +{ +} + + +/* packet trace format function */ +u8 * +hicn_strategy_format_trace_mw (u8 * s, hicn_strategy_trace_t * t) +{ + s = format (s, "Strategy_mw: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + return (s); +} + +u8 * +hicn_strategy_format_mw (u8 * s, va_list * ap) +{ + + u32 indent = va_arg (*ap, u32); + s = + format (s, + "Static Weights: weights are updated by the control plane, next hop is the one with the maximum weight.\n", + indent); + return (s); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/strategies/strategy_mw.h b/hicn-plugin/src/network/strategies/strategy_mw.h new file mode 100644 index 000000000..9e0078b23 --- /dev/null +++ b/hicn-plugin/src/network/strategies/strategy_mw.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017-2020 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_STRATEGY_MW_H__ +#define __HICN_STRATEGY_MW_H__ + +#include "../strategy.h" + +/** + * @file strategy_mw.h + * + * This file implements the maximum weight strategy. In this + * strategy the choosen next hop is one with the maximum weight. + */ + +/** + * @brief Return the vft for the Maximum Weight strategy + */ +hicn_strategy_vft_t *hicn_mw_strategy_get_vft (void); + +#endif // __HICN_STRATEGY_MW_H__ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/strategies/strategy_mw_cli.c b/hicn-plugin/src/network/strategies/strategy_mw_cli.c new file mode 100644 index 000000000..636d7effa --- /dev/null +++ b/hicn-plugin/src/network/strategies/strategy_mw_cli.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017-2020 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 "../strategy_dpo_manager.h" +#include "../faces/face.h" +#include "../error.h" +#include "../route.h" +#include "dpo_mw.h" + +static clib_error_t * +hicn_mw_strategy_cli_set_weight_command_fn (vlib_main_t * vm, + unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + clib_error_t *cl_err = 0; + int ret = HICN_ERROR_NONE; + fib_prefix_t prefix; + hicn_face_id_t faceid = HICN_FACE_NULL; + u32 fib_index; + u32 weight = HICN_PARAM_FIB_ENTRY_NHOP_WGHT_DFLT; + hicn_dpo_ctx_t *hicn_dpo_ctx; + const dpo_id_t *hicn_dpo_id; + + /* Get a line of input. */ + unformat_input_t _line_input, *line_input = &_line_input; + if (unformat_user (main_input, unformat_line_input, line_input)) + { + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "prefix %U/%u", unformat_ip46_address, + &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) + ; + else if (unformat (line_input, "face %u", &faceid)) + ; + else if (unformat (line_input, "weight %u", &weight)) + ; + else + { + return clib_error_return (0, "%s", + get_error_string + (HICN_ERROR_CLI_INVAL)); + } + + } + } + + if (((weight < 0) || (weight > HICN_PARAM_FIB_ENTRY_NHOP_WGHT_MAX))) + { + cl_err = clib_error_return (0, + "Next-hop weight must be between 0 and %d", + (int) HICN_PARAM_FIB_ENTRY_NHOP_WGHT_MAX); + goto done; + } + + if (((ip46_address_is_zero (&prefix.fp_addr)) || faceid == HICN_FACE_NULL)) + { + cl_err = + clib_error_return (0, "Please specify prefix and a valid faceid..."); + goto done; + } + + prefix.fp_proto = + ip46_address_is_ip4 (&prefix. + fp_addr) ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; + ret = hicn_route_get_dpo (&prefix, &hicn_dpo_id, &fib_index); + + if (ret == HICN_ERROR_NONE) + { + hicn_dpo_ctx = hicn_strategy_dpo_ctx_get (hicn_dpo_id->dpoi_index); + + if (hicn_dpo_ctx == NULL + || hicn_dpo_id->dpoi_type != hicn_dpo_strategy_mw_get_type ()) + { + cl_err = clib_error_return (0, get_error_string (ret)); + goto done; + } + + hicn_strategy_mw_ctx_t *mw_dpo = + (hicn_strategy_mw_ctx_t *) hicn_dpo_ctx; + int idx = ~0; + for (int i = 0; i < hicn_dpo_ctx->entry_count; i++) + if (hicn_dpo_ctx->next_hops[i] == faceid) + idx = i; + + if (idx == ~0) + { + cl_err = + clib_error_return (0, + get_error_string + (HICN_ERROR_STRATEGY_NH_NOT_FOUND)); + goto done; + } + + mw_dpo->weight[idx] = weight; + } + else + { + cl_err = clib_error_return (0, get_error_string (ret)); + + } + +done: + + return (cl_err); + +} + +/* cli declaration for 'strategy mw' */ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND(hicn_mw_strategy_cli_set_weight_command, static)= +{ + .path = "hicn strategy mw set", + .short_help = "hicn strategy mw set prefix face weight ", + .function = hicn_mw_strategy_cli_set_weight_command_fn, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/strategies/strategy_rr.c b/hicn-plugin/src/network/strategies/strategy_rr.c new file mode 100644 index 000000000..4c65ce52a --- /dev/null +++ b/hicn-plugin/src/network/strategies/strategy_rr.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2017-2020 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 "dpo_rr.h" +#include "../strategy.h" +#include "../strategy_dpo_ctx.h" +#include "../faces/face.h" +#include "../hashtb.h" +#include "../strategy_dpo_manager.h" + +/* Simple strategy that chooses the next hop with the maximum weight */ +/* It does not require to exend the hicn_dpo */ +void hicn_receive_data_rr (index_t dpo_idx, int nh_idx); +void hicn_add_interest_rr (index_t dpo_idx, hicn_hash_entry_t * pit_entry); +void hicn_on_interest_timeout_rr (index_t dpo_idx); +u32 hicn_select_next_hop_rr (index_t dpo_idx, int *nh_idx, + hicn_face_id_t* outface); +u8 *hicn_strategy_format_trace_rr (u8 * s, hicn_strategy_trace_t * t); +u8 *hicn_strategy_format_rr (u8 * s, va_list * ap); + + +static hicn_strategy_vft_t hicn_strategy_rr_vft = { + .hicn_receive_data = &hicn_receive_data_rr, + .hicn_add_interest = &hicn_add_interest_rr, + .hicn_on_interest_timeout = &hicn_on_interest_timeout_rr, + .hicn_select_next_hop = &hicn_select_next_hop_rr, + .hicn_format_strategy_trace = &hicn_strategy_format_trace_rr, + .hicn_format_strategy = &hicn_strategy_format_rr +}; + +/* + * Return the vft of the strategy. + */ +hicn_strategy_vft_t * +hicn_rr_strategy_get_vft (void) +{ + return &hicn_strategy_rr_vft; +} + +/* DPO should be give in input as it containes all the information to calculate the next hops*/ +u32 +hicn_select_next_hop_rr (index_t dpo_idx, int *nh_idx, hicn_face_id_t* outface) +{ + hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx); + + if (dpo_ctx == NULL) + return HICN_ERROR_STRATEGY_NOT_FOUND; + + hicn_strategy_rr_ctx_t *hicn_strategy_rr_ctx = + (hicn_strategy_rr_ctx_t *) dpo_ctx->data; + + *outface = + dpo_ctx->next_hops[hicn_strategy_rr_ctx->current_nhop]; + + hicn_strategy_rr_ctx->current_nhop = + (hicn_strategy_rr_ctx->current_nhop + 1) % dpo_ctx->entry_count; + + return HICN_ERROR_NONE; +} + +void +hicn_add_interest_rr (index_t dpo_ctx_idx, hicn_hash_entry_t * hash_entry) +{ + hash_entry->dpo_ctx_id = dpo_ctx_idx; + dpo_id_t hicn_dpo_id = + { hicn_dpo_strategy_rr_get_type (), 0, 0, dpo_ctx_idx }; + hicn_strategy_dpo_ctx_lock (&hicn_dpo_id); + hash_entry->vft_id = hicn_dpo_get_vft_id (&hicn_dpo_id); +} + +void +hicn_on_interest_timeout_rr (index_t dpo_idx) +{ + /* Nothing to do in the rr strategy when we receive an interest */ +} + +void +hicn_receive_data_rr (index_t dpo_idx, int nh_idx) +{ +} + + +/* packet trace format function */ +u8 * +hicn_strategy_format_trace_rr (u8 * s, hicn_strategy_trace_t * t) +{ + s = format (s, "Strategy_rr: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + return (s); +} + +u8 * +hicn_strategy_format_rr (u8 * s, va_list * ap) +{ + + u32 indent = va_arg (*ap, u32); + s = + format (s, + "Round Robin: next hop is chosen ciclying between all the available next hops, one after the other.\n", + indent); + return (s); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/strategies/strategy_rr.h b/hicn-plugin/src/network/strategies/strategy_rr.h new file mode 100644 index 000000000..4dfe76b43 --- /dev/null +++ b/hicn-plugin/src/network/strategies/strategy_rr.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017-2019 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_STRATEGY_RR_H__ +#define __HICN_STRATEGY_RR_H__ + +#include "../strategy.h" + +/** + * @file strategy_rr.h + * + * This file implements the round robin strategy. In this + * strategy the next hop is choosen in a round robin way. + */ + +/** + * @brief Return the vft for the Round Robin strategy + */ +hicn_strategy_vft_t *hicn_rr_strategy_get_vft (void); + +#endif // __HICN_STRATEGY_RR_H__ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/strategy.h b/hicn-plugin/src/network/strategy.h new file mode 100644 index 000000000..d949f38a4 --- /dev/null +++ b/hicn-plugin/src/network/strategy.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2017-2020 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_STRATEGY__ +#define __HICN_STRATEGY__ + +#include "hicn.h" +#include "hashtb.h" +#include "mgmt.h" +#include "faces/face.h" + +/** + * @file strategy.h + * + * A strategy is defined as a dpo and a set of function (vft) that will be called + * during the packet processing. A strategy is associated to an entry in the fib by + * assigning the corresponding dpo to the fib entry. The dpo points to a hICN dpo + * context (ctx) which contains the information needed by the strategy to compute + * the next hop. Each strategy hash its own dpo type, which means that the dpo_type + * uniquely identifies a strategy and its vft. The strategy node will use the dpo_type + * to retrieve the corresponding vft. + * Here we provide: + * - a template for the callbacks to implement in order to create a new strategy + * (hicn_fwd_strategy_t) + * - a default implementation for the strategy node which will call the strategy + * functions while processing the interest packets + */ + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; + dpo_type_t dpo_type; +} hicn_strategy_trace_t; + +typedef struct hicn_strategy_vft_s +{ + void (*hicn_receive_data) (index_t dpo_idx, int nh_idx); + void (*hicn_on_interest_timeout) (index_t dpo_idx); + void (*hicn_add_interest) (index_t dpo_idx, hicn_hash_entry_t * pit_entry); + u32 (*hicn_select_next_hop) (index_t dpo_idx, int *nh_idx, + hicn_face_id_t* outface); + u8 *(*hicn_format_strategy_trace) (u8 *, hicn_strategy_trace_t *); + u8 *(*hicn_format_strategy) (u8 * s, va_list * ap); + /**< Format an hICN dpo*/ +} hicn_strategy_vft_t; + +typedef enum +{ + HICN_STRATEGY_NEXT_INTEREST_HITPIT, + HICN_STRATEGY_NEXT_INTEREST_HITCS, + HICN_STRATEGY_NEXT_INTEREST_FACE4, + HICN_STRATEGY_NEXT_INTEREST_FACE6, + HICN_STRATEGY_NEXT_ERROR_DROP, + HICN_STRATEGY_N_NEXT, +} hicn_strategy_next_t; + +const static char *const hicn_ip6_nodes[] = +{ + "hicn6-iface-input", // this is the name you give your node in VLIB_REGISTER_NODE + NULL, +}; + +const static char *const hicn_ip4_nodes[] = +{ + "hicn4-iface-input", // this is the name you give your node in VLIB_REGISTER_NODE + NULL, +}; + +const static char *const *const hicn_nodes_strategy[DPO_PROTO_NUM] = +{ + [DPO_PROTO_IP6] = hicn_ip6_nodes, + [DPO_PROTO_IP4] = hicn_ip4_nodes, +}; + + +extern vlib_node_registration_t hicn_strategy_node; + +#endif /* //__HICN_STRATEGY__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/strategy_dpo_ctx.c b/hicn-plugin/src/network/strategy_dpo_ctx.c new file mode 100644 index 000000000..342c78bb5 --- /dev/null +++ b/hicn-plugin/src/network/strategy_dpo_ctx.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2020 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 "strategy_dpo_ctx.h" +#include "strategy_dpo_manager.h" + +hicn_dpo_ctx_t *hicn_strategy_dpo_ctx_pool; + +void +hicn_strategy_init_dpo_ctx_pool () +{ + pool_init_fixed (hicn_strategy_dpo_ctx_pool, 256); + +} + +void +hicn_strategy_dpo_ctx_lock (dpo_id_t * dpo) +{ + hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo->dpoi_index); + + if (dpo_ctx != NULL) + { + dpo_ctx->locks++; + } +} + +void +hicn_strategy_dpo_ctx_unlock (dpo_id_t * dpo) +{ + hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = + (hicn_dpo_ctx_t *) hicn_strategy_dpo_ctx_get (dpo->dpoi_index); + + if (hicn_strategy_dpo_ctx != NULL) + { + hicn_strategy_dpo_ctx->locks--; + + if (0 == hicn_strategy_dpo_ctx->locks) + { + pool_put (hicn_strategy_dpo_ctx_pool, hicn_strategy_dpo_ctx); + } + } +} + +u8 * +hicn_strategy_dpo_format_ctx (u8 * s, va_list * ap) +{ + index_t index = va_arg (*ap, index_t); + hicn_dpo_ctx_t *dpo = NULL; + u32 indent = va_arg (*ap, u32); + + dpo = (hicn_dpo_ctx_t *) hicn_strategy_dpo_ctx_get (index); + + const hicn_dpo_vft_t *dpo_vft = hicn_dpo_get_vft (dpo->dpo_type); + + s = dpo_vft->hicn_dpo_format (s, 2, index, indent); + + return (s); +} + +index_t +hicn_strategy_dpo_ctx_get_index (hicn_dpo_ctx_t * cd) +{ + return (cd - hicn_strategy_dpo_ctx_pool); +} + +hicn_dpo_ctx_t * +hicn_strategy_dpo_ctx_get (index_t index) +{ + hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = NULL; + if (!pool_is_free_index (hicn_strategy_dpo_ctx_pool, index)) + { + hicn_strategy_dpo_ctx = + (pool_elt_at_index (hicn_strategy_dpo_ctx_pool, index)); + } + + return hicn_strategy_dpo_ctx; +} + +hicn_dpo_ctx_t * +hicn_strategy_dpo_ctx_alloc () +{ + hicn_dpo_ctx_t *dpo_ctx; + pool_get (hicn_strategy_dpo_ctx_pool, dpo_ctx); + return dpo_ctx; +} + +int +hicn_strategy_dpo_ctx_add_nh (hicn_face_id_t nh, hicn_dpo_ctx_t * dpo_ctx, + u8 * pos) +{ + + int empty = dpo_ctx->entry_count; + + /* Iterate through the list of faces to find if the face is already a next hop */ + for (int i = 0; i < dpo_ctx->entry_count; i++) + { + if (nh == dpo_ctx->next_hops[i]) + { + /* If face is marked as deleted, ignore it */ + hicn_face_t *face = + hicn_dpoi_get_from_idx (dpo_ctx->next_hops[i]); + if (face->flags & HICN_FACE_FLAGS_DELETED) + { + continue; + } + return HICN_ERROR_DPO_CTX_NHOPS_EXISTS; + } + } + + /* Get an empty place */ + if (empty > HICN_PARAM_FIB_ENTRY_NHOPS_MAX) + { + return HICN_ERROR_DPO_CTX_NHOPS_NS; + } + + dpo_ctx->next_hops[empty] = nh; + hicn_face_lock_with_id (nh); + dpo_ctx->entry_count++; + *pos = empty; + + return HICN_ERROR_NONE; +} + +int +hicn_strategy_dpo_ctx_del_nh (hicn_face_id_t face_id, + hicn_dpo_ctx_t * dpo_ctx) +{ + int ret = HICN_ERROR_DPO_CTX_NOT_FOUND; + hicn_face_id_t invalid = NEXT_HOP_INVALID; + + for (int i = 0; i < dpo_ctx->entry_count; i++) + { + if (dpo_ctx->next_hops[i] == face_id) + { + hicn_face_unlock_with_id (dpo_ctx->next_hops[i]); + dpo_ctx->entry_count--; + dpo_ctx->next_hops[i] = dpo_ctx->next_hops[dpo_ctx->entry_count]; + dpo_ctx->next_hops[dpo_ctx->entry_count] = invalid; + ret = HICN_ERROR_NONE; + break; + } + } + + return ret; + +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/strategy_dpo_ctx.h b/hicn-plugin/src/network/strategy_dpo_ctx.h new file mode 100644 index 000000000..214ed88ad --- /dev/null +++ b/hicn-plugin/src/network/strategy_dpo_ctx.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2017-2020 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_STRATEGY_DPO_CTX_H__ +#define __HICN_STRATEGY_DPO_CTX_H__ + +#include +#include + +#include "params.h" +#include "faces/face.h" + +/** + * @file strategy_dpo_ctx.h + * + * This file implements the general hICN DPO ctx (shared among all the strategies). + * + * An hICN DPO ctx contains the list of next hops, auxiliaries fields to maintain the dpo, map-me + * specifics (tfib_entry_count and seq), the dpo_type and 64B to let each strategy to store additional + * information. Each next hop is an hicn_face_id_t that refers to an index for an hICN face. The + * dpo_type is used to identify the strategy and to retrieve the vft corresponding to the strategy + * (see strategy.h) and to the dpo ctx (see strategy_dpo_manager.h) + */ + +//FIB table for hicn. 0 is the default one used by ip +#define HICN_FIB_TABLE 10 + +#define NEXT_HOP_INVALID ~0 + +#define INIT_SEQ 0 + +typedef struct __attribute__ ((packed)) hicn_dpo_ctx_s +{ + CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); + /* 4B*10 = 40B */ + hicn_face_id_t next_hops[HICN_PARAM_FIB_ENTRY_NHOPS_MAX]; + /* 40B + 4B = 44B */ + u32 locks; + /* 44B + 1B = 45B */ + u8 entry_count; + /* 45B + 1B = 46B */ + /* Number of TFIB entries (stored at the end of the next_hops array */ + u8 tfib_entry_count; + + dpo_type_t dpo_type; + + /* 46B + 2B = 48B */ + u8 padding; /* To align to 8B */ + + /* 48 + 4B = 52; last sequence number */ + u32 seq; + + /* 52 + 12 = 64 */ + fib_node_t fib_node; + + CLIB_CACHE_LINE_ALIGN_MARK (cacheline1); + + fib_node_index_t fib_entry_index; + + u32 fib_sibling; + + union + { + u32 padding_proto; + fib_protocol_t proto; + }; + + u8 data[CLIB_CACHE_LINE_BYTES - 12]; + +} hicn_dpo_ctx_t; + +extern hicn_dpo_ctx_t *hicn_strategy_dpo_ctx_pool; + +/** + * @brief Initialize the hICN dpo ctx + * + * @param dpo_ctx Pointer to the hICN dpo ctx to initialize + * @param next_hop List of netx hops to store in the dpo ctx + * @param nh_len Number of elements in the list of next hops + * @param dpo_type Type of dpo. It identifies the strategy. + */ +always_inline void +init_dpo_ctx (hicn_dpo_ctx_t * dpo_ctx, const hicn_face_id_t * next_hop, + int nh_len, dpo_type_t dpo_type, dpo_proto_t proto) +{ + hicn_face_id_t invalid = NEXT_HOP_INVALID; + + dpo_ctx->entry_count = 0; + dpo_ctx->locks = 0; + + dpo_ctx->tfib_entry_count = 0; + + dpo_ctx->seq = INIT_SEQ; + dpo_ctx->dpo_type = dpo_type; + + dpo_ctx->proto = proto; + + for (int i = 0; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX && i < nh_len; i++) + { + dpo_ctx->next_hops[i] = next_hop[i]; + dpo_ctx->entry_count++; + } + + + for (int i = nh_len; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; i++) + { + dpo_ctx->next_hops[i] = invalid; + } + +} + +/** + * @brief Initialize the pool containing the hICN dpo ctx + * + */ +void hicn_strategy_init_dpo_ctx_pool (void); + +/** + * @brief Allocate a new hICN dpo ctx from the pool + */ +hicn_dpo_ctx_t *hicn_strategy_dpo_ctx_alloc (); + +/** + * @brief Retrieve an existing hICN dpo ctx from the pool + */ +hicn_dpo_ctx_t *hicn_strategy_dpo_ctx_get (index_t index); + +/** + * @brief Retrieve the index of the hICN dpo ctx + */ +index_t hicn_strategy_dpo_ctx_get_index (hicn_dpo_ctx_t * cd); + +/** + * @brief Lock the dpo of a strategy ctx + * + * @param dpo Identifier of the dpo of the strategy ctx + */ +void hicn_strategy_dpo_ctx_lock (dpo_id_t * dpo); + +/** + * @brief Unlock the dpo of a strategy ctx + * + * @param dpo Identifier of the dpo of the strategy ctx + */ +void hicn_strategy_dpo_ctx_unlock (dpo_id_t * dpo); + +/** + * @brief Add or update a next hop in the dpo ctx. + * + * This function is meant to be used in the control plane and not in the data plane, + * as it is not optimized for the latter. + * + * @param nh Next hop to insert in the dpo ctx + * @param dpo_ctx Dpo ctx to update with the new or updated next hop + * @param pos Return the position of the nh that has been added + * @return HICN_ERROR_NONE if the update or insert was fine, + * otherwise HICN_ERROR_DPO_CTX_NOT_FOUND + */ +int +hicn_strategy_dpo_ctx_add_nh (hicn_face_id_t nh, hicn_dpo_ctx_t * dpo_ctx, + u8 * pos); + +/** + * @brief Delete a next hop in the dpo ctx. + * + * @param face_id Face identifier of the next hop + * @param dpo_ctx Dpo ctx to update by removing the face + * @return HICN_ERROR_NONE if the update or insert was fine, + * otherwise HICN_ERROR_DPO_CTS_NOT_FOUND + */ +int +hicn_strategy_dpo_ctx_del_nh (hicn_face_id_t face_id, + hicn_dpo_ctx_t * dpo_ctx); + + +STATIC_ASSERT (sizeof (hicn_dpo_ctx_t) <= 2 * CLIB_CACHE_LINE_BYTES, + "sizeof hicn_dpo_ctx_t is greater than 128B"); + +#endif /* // __HICN_STRATEGY_DPO_CTX_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/strategy_dpo_manager.c b/hicn-plugin/src/network/strategy_dpo_manager.c new file mode 100644 index 000000000..f8d41a372 --- /dev/null +++ b/hicn-plugin/src/network/strategy_dpo_manager.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2017-2019 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 "strategy_dpo_manager.h" +#include "strategy_dpo_ctx.h" +#include "strategies/dpo_mw.h" +#include "strategies/dpo_rr.h" +#include "strategy.h" +#include "faces/face.h" + +static dpo_type_t *strategies_id; +static const hicn_dpo_vft_t **hicn_dpo_vfts; + +static const hicn_strategy_vft_t **hicn_strategy_vfts; + +int hicn_strategies = 0; + +hicn_dpo_vft_t default_dpo; + +dpo_type_t +hicn_dpo_register_new_type (const char *const *const *hicn_nodes, + const hicn_dpo_vft_t * hicn_dpo_vft, + const hicn_strategy_vft_t * hicn_strategy_vft, + const dpo_vft_t * dpo_ctx_vft) +{ + dpo_type_t dpo_type = dpo_register_new_type (dpo_ctx_vft, hicn_nodes); + vec_validate (hicn_dpo_vfts, dpo_type); + hicn_dpo_vfts[dpo_type] = hicn_dpo_vft; + + vec_validate (hicn_strategy_vfts, dpo_type); + hicn_strategy_vfts[dpo_type] = hicn_strategy_vft; + + vec_validate (strategies_id, hicn_strategies); + strategies_id[hicn_strategies] = dpo_type; + hicn_strategies++; + + return dpo_type; +} + +u32 +dpo_is_hicn (const dpo_id_t * dpo) +{ + for (int i = 0; i < hicn_strategies; i++) + { + if (hicn_dpo_vfts[strategies_id[i]]->hicn_dpo_is_type (dpo)) + return 1; + } + return 0; +} + +dpo_type_t +hicn_dpo_get_vft_id (const dpo_id_t * dpo) +{ + return dpo->dpoi_type; +} + +const hicn_dpo_vft_t * +hicn_dpo_get_vft (dpo_type_t vfts_id) +{ + return hicn_dpo_vfts[vfts_id]; +} + +const hicn_dpo_vft_t * +hicn_dpo_get_vft_from_id (u8 strategy_id) +{ + return hicn_dpo_vfts[strategies_id[strategy_id]]; +} + +const hicn_strategy_vft_t * +hicn_dpo_get_strategy_vft (dpo_type_t vfts_id) +{ + return hicn_strategy_vfts[vfts_id]; +} + +const hicn_strategy_vft_t * +hicn_dpo_get_strategy_vft_from_id (u8 vfts_id) +{ + return hicn_strategy_vfts[strategies_id[vfts_id]]; +} + +void +hicn_dpos_init (void) +{ + hicn_strategy_init_dpo_ctx_pool (); + hicn_dpo_strategy_mw_module_init (); + hicn_dpo_strategy_rr_module_init (); + + default_dpo.hicn_dpo_is_type = &hicn_dpo_is_type_strategy_mw; + default_dpo.hicn_dpo_get_type = &hicn_dpo_strategy_mw_get_type; + default_dpo.hicn_dpo_module_init = &hicn_dpo_strategy_mw_module_init; + default_dpo.hicn_dpo_create = &hicn_strategy_mw_ctx_create; + default_dpo.hicn_dpo_add_update_nh = &hicn_strategy_mw_ctx_add_nh; + default_dpo.hicn_dpo_del_nh = &hicn_strategy_mw_ctx_del_nh; + default_dpo.hicn_dpo_format = &hicn_strategy_mw_format_ctx; +} + +u8 * +format_hicn_strategy_list (u8 * s, int n, ...) +{ + va_list ap; + va_start (ap, n); + u32 indent = va_arg (ap, u32); + va_end (ap); + + s = format (s, "%U Strategies:\n", format_white_space, indent); + indent += 4; + int i; + vec_foreach_index (i, strategies_id) + { + s = format (s, "%U (%d) ", format_white_space, indent, i); + s = hicn_strategy_vfts[strategies_id[i]]->hicn_format_strategy (s, &ap); + } + + return (s); +} + +u8 +hicn_dpo_strategy_id_is_valid (int strategy_id) +{ + return vec_len (strategies_id) > strategy_id ? + HICN_ERROR_NONE : HICN_ERROR_DPO_MGR_ID_NOT_VALID; +} + +int +hicn_strategy_get_all_available (void) +{ + return hicn_strategies; +} + +/** + * @brief Registers a dpo by calling its module init function. + * + * This is typically called from the ctor for dpo's registered at compilation + * time. + */ +void +hicn_dpo_register (const hicn_dpo_vft_t * hicn_dpo) +{ + hicn_dpo->hicn_dpo_module_init (); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/strategy_dpo_manager.h b/hicn-plugin/src/network/strategy_dpo_manager.h new file mode 100644 index 000000000..e96e050d9 --- /dev/null +++ b/hicn-plugin/src/network/strategy_dpo_manager.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2017-2020 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_STRATEGY_DPO_MANAGER_H__ +#define __HICN_STRATEGY_DPO_MANAGER_H__ + +#include "strategy_dpo_ctx.h" +#include "strategy.h" + +/** + * @file strategy_dpo_manager.h + * + * This file implements structs and helper functions to manipulate hICN dpo. + * An hICN DPO is a combination of: + * - a hICN DPO ctx (context) that holds the structure containing the + * information to choose the next hop, + * - a dpo vft that specify how to update the hICN DPO ctx when a next hop is + * added, deleted or updated, + * - a strategy containing (see strategy.h): (i) the vpp node that processes Interest packets + * subjected to such strategy, (ii) the definition of the vft that defines + * the hICN strategy functions + * An hICN DPO is places as the sole next hop in the vpp loadbalancer, and it containes + * a list of next hops that will be used by the associated strategy when forwarding + * interest packets. + */ + +/** + * @brief Definition of the virtual function table for a hICN DPO. + * + * The following virtual function table + * template that glues together the fuction to interact with the context and the + * creating the dpo + */ +typedef struct hicn_dpo_vft_s +{ + int (*hicn_dpo_is_type) (const dpo_id_t * dpo); + /**< Check if the type of the + hICN DPO is the expected */ + dpo_type_t (*hicn_dpo_get_type) (void); + /**< Return the type of the hICN dpo */ + void (*hicn_dpo_module_init) (void); /**< Initialize the hICN dpo */ + void (*hicn_dpo_create) (fib_protocol_t proto, const hicn_face_id_t * nh, int nh_len, index_t * dpo_idx); /**< Create the context of the hICN dpo */ + int (*hicn_dpo_add_update_nh) (hicn_face_id_t nh, index_t dpo_idx); /**< Add a next hop to the hICN dpo context */ + int (*hicn_dpo_del_nh) (hicn_face_id_t face_id, index_t dpo_idx); + u8 *(*hicn_dpo_format) (u8 * s, int, ...); + /**< Format an hICN dpo*/ +} hicn_dpo_vft_t; + +/* + * Default dpo to be used to create fib entry when a strategy is not + * specified + */ +extern hicn_dpo_vft_t default_dpo; + +/** + * @brief Register a new hICN dpo to the manager. + * + * Registering a hICN DPO allows the plugin to be aware of the new dpo an be + * able to apply it to the FIB entries. + * + * @param hicn_nodes A list of vpp to which pass an interest that matches with + * the FIB entry to which the hICN DPO is applied. This list must contain the + * name of the strategy node (or nodes in case of differentiation between IPv4 + * and IPv6). Unless really needed otherwise (i.e., different implementation of + * iface input), the list of node to use should be one provided in the strategy.h + * (hicn_nodes_strategy) + * @param hicn_dpo_vft The structure holding the virtual function table to + * interact with the hICN dpo and its context. + * @param hicn_strategy_vft The structure holding the virtual function table + * containing the hICN strategy functions. + * @return the dpo type registered in the VPP Data plane graph. + */ +dpo_type_t +hicn_dpo_register_new_type (const char *const *const *hicn_nodes, + const hicn_dpo_vft_t * hicn_dpo_vft, + const hicn_strategy_vft_t * + hicn_strategy_vft, const dpo_vft_t * dpo_ctx_vft); + +/** + * @brief Check if the type of the dpo is among the list of hicn dpo types + * + * Iterate through the list of dpo types registered in the hicn dpo manager. + * + * @param dpo The id of the dpo to which check the type + * @return 1 if there is a match, 0 otherwise. + */ +u32 dpo_is_hicn (const dpo_id_t * dpo); + +/** + * @brief Return the dpo_vtf and strategy_vtf identifier + * + * Iterate through the list of dpo types registered in the hicn dpo manager and + * retrieve the corresponding dpo_vtf/strategy_vtf identifier. + * + * @param dpo The id of the dpo to which check the type + * @return the dpo_vft/strategy_vft id or HICN_ERROR_DPO_NOT_FOUND in case the dpo is not an hICN dpo. + */ +u8 hicn_dpo_get_vft_id (const dpo_id_t * dpo); + +/** + * @brief Get the vft to manage the dpo context. + * + * @param The id of the hicn_dpo_vft to retrieve. + * @return The vft struct that contains the list of callbacks that allows to + * manage the dpo context. + */ +const hicn_dpo_vft_t *hicn_dpo_get_vft (dpo_type_t vfts_id); + +/** + * @brief Get the vft to manage the dpo context from the strategy id. + * + * @param The strategy id of the hicn_dpo_vft to retrieve. + * @return The vft struct that contains the list of callbacks that allows to + * manage the dpo context. + */ +const hicn_dpo_vft_t *hicn_dpo_get_vft_from_id (u8 strategy_id); + +/** + * @brief Get the vft with the hICN strategy functions. + * + * @param The id of the hicn_strategy_vft to retrieve. + * @return The vft struct that contains the list hICN strategy functions. + */ +const hicn_strategy_vft_t *hicn_dpo_get_strategy_vft (dpo_type_t vfts_id); + +/** + * @brief Get the vft with the hICN strategy functions from the strategy id. + * + * @param The id of the hicn_strategy_vft to retrieve. + * @return The vft struct that contains the list hICN strategy functions. + */ +const hicn_strategy_vft_t *hicn_dpo_get_strategy_vft_from_id (u8 vfts_id); + +/** + * @brief Initialize all the types hicn dpo registered + * + * Call the init functions of all the hicn dpo implemented. + * This init is called when the plugin bootstrap. + */ +void hicn_dpos_init (void); + +/** + * @brief Print the list of the registered hICN DPO + * + * @param s String to which to append the list of hICN DPO (strategies) + * @param n number of parameters to pass + * + * @result The string with the list of hICN DPO (strategies) + */ +u8 *format_hicn_strategy_list (u8 * s, int n, ...); + +/** + * @brief Check if a given id points to a strategy and the corresponding dpo ctx + * + * @param The id of the strategy to check. + * + * @result HICN_ERROR_NONE is the id is valid, otherwise EINVAL + */ +u8 hicn_dpo_strategy_id_is_valid (int strategy_id); + +/** + * @brief Return the number of available strategies. This number can be used to + * as an upperbond for valid vfts_id. + * + * @result Return the number of available strategies. + */ +int hicn_strategy_get_all_available (void); + +/** + * @brief Registers a module at compilation time to be initialized as part of + * the ctor. + */ +void hicn_dpo_register (const hicn_dpo_vft_t * hicn_dpo); + +#endif /* // __HICN_STRATEGY_DPO_MANAGER_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/strategy_node.c b/hicn-plugin/src/network/strategy_node.c new file mode 100644 index 000000000..0659a871a --- /dev/null +++ b/hicn-plugin/src/network/strategy_node.c @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2017-2020 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 "hicn.h" +#include "parser.h" +#include "strategy.h" +#include "strategy_dpo_ctx.h" +#include "face_db.h" +#include "infra.h" +#include "mgmt.h" +#include "pcs.h" +#include "state.h" +#include "strategies/strategy_mw.h" + +/* Registration struct for a graph node */ +vlib_node_registration_t hicn_strategy_node; + +/* + * Node context data (to be used in all the strategy nodes); we think this is + * per-thread/instance + */ +typedef struct hicn_strategy_runtime_s +{ + int id; + hicn_pit_cs_t *pitcs; +} hicn_strategy_runtime_t; + +/* Stats string values */ +static char *hicn_strategy_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +/* packet trace format function */ +u8 * +hicn_strategy_format_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 *); + hicn_strategy_trace_t *t = va_arg (*args, hicn_strategy_trace_t *); + + const hicn_strategy_vft_t *vft = hicn_dpo_get_strategy_vft (t->dpo_type); + + return vft->hicn_format_strategy_trace (s, t); +} + + +always_inline int +hicn_new_interest (hicn_strategy_runtime_t * rt, vlib_buffer_t * b0, + u32 * next, f64 tnow, u8 * nameptr, + u16 namelen, hicn_face_id_t outface, int nh_idx, + index_t dpo_ctx_id0, const hicn_strategy_vft_t * strategy, + dpo_type_t dpo_type, u8 isv6, + vl_api_hicn_api_node_stats_get_reply_t * stats) +{ + int ret; + hicn_hash_node_t *nodep; + hicn_pcs_entry_t *pitp; + hicn_header_t *hicn0; + hicn_main_t *sm = &hicn_main; + hicn_buffer_t *hicnb0 = hicn_get_buffer (b0); + u32 node_id0 = 0; + u8 vft_id0 = dpo_type; + u8 is_cs0 = 0; + u8 hash_entry_id = 0; + u8 bucket_is_overflow = 0; + u32 bucket_id = ~0; + + + /* Create PIT node and init PIT entry */ + nodep = hicn_hashtb_alloc_node (rt->pitcs->pcs_table); + if (PREDICT_FALSE (nodep == NULL)) + { + /* Nothing we can do - no mem */ + *next = HICN_STRATEGY_NEXT_ERROR_DROP; + return HICN_ERROR_HASHTB_NOMEM; + } + pitp = hicn_pit_get_data (nodep); + hicn_pit_init_data (pitp); + pitp->shared.create_time = tnow; + + hicn0 = vlib_buffer_get_current (b0); + hicn_lifetime_t imsg_lifetime; + hicn_type_t type = hicnb0->type; + hicn_ops_vft[type.l1]->get_lifetime (type, &hicn0->protocol, + &imsg_lifetime); + + if (imsg_lifetime > sm->pit_lifetime_max_ms) + { + imsg_lifetime = sm->pit_lifetime_max_ms; + } + pitp->shared.expire_time = hicn_pcs_get_exp_time (tnow, imsg_lifetime); + + /* Set up the hash node and insert it */ + hicn_hash_entry_t *hash_entry; + hicn_hashtb_init_node (rt->pitcs->pcs_table, nodep, nameptr, namelen); + + ret = + hicn_pcs_pit_insert (rt->pitcs, pitp, nodep, &hash_entry, + hicnb0->name_hash, &node_id0, &dpo_ctx_id0, &vft_id0, + &is_cs0, &hash_entry_id, &bucket_id, + &bucket_is_overflow); + + if (ret == HICN_ERROR_NONE) + { + strategy->hicn_add_interest (vnet_buffer (b0)->ip.adj_index[VLIB_TX], + hash_entry); + + /* Add face */ + hicn_face_db_add_face (hicnb0->face_id, &(pitp->u.pit.faces)); + + *next = isv6 ? HICN_STRATEGY_NEXT_INTEREST_FACE6 : + HICN_STRATEGY_NEXT_INTEREST_FACE4; + + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = outface; + stats->pkts_interest_count++; + pitp->u.pit.pe_txnh = nh_idx; + } + else + { + /* Interest aggregate in PIT */ + if (ret == HICN_ERROR_HASHTB_EXIST) + { + hicn_store_internal_state (b0, hicnb0->name_hash, node_id0, + dpo_ctx_id0, vft_id0, hash_entry_id, + bucket_id, bucket_is_overflow); + // We need to take a lock as the lock is not taken on the hash + // entry because it is a CS entry (hash_insert function). + hash_entry->locks++; + *next = + is_cs0 ? HICN_STRATEGY_NEXT_INTEREST_HITCS : + HICN_STRATEGY_NEXT_INTEREST_HITPIT; + } + else + { + /* Send the packet to the interest-hitpit node */ + *next = HICN_STRATEGY_NEXT_ERROR_DROP; + } + hicn_faces_flush (&(pitp->u.pit.faces)); + hicn_hashtb_free_node (rt->pitcs->pcs_table, nodep); + } + + return (ret); + +} + +/* + * ICN strategy later node for interests: - 1 packet at a time - ipv4/tcp + * ipv6/tcp + */ +uword +hicn_strategy_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + + u32 n_left_from, *from, *to_next, n_left_to_next; + hicn_strategy_next_t next_index; + hicn_strategy_runtime_t *rt = NULL; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + f64 tnow; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = (hicn_strategy_next_t) node->cached_next_index; + rt = vlib_node_get_runtime_data (vm, hicn_strategy_node.index); + rt->pitcs = &hicn_main.pitcs; + /* Capture time in vpp terms */ + tnow = vlib_time_now (vm); + + while (n_left_from > 0) + { + + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + while (n_left_from > 0 && n_left_to_next > 0) + { + u8 isv6; + u8 *nameptr; + u16 namelen; + hicn_name_t name; + hicn_header_t *hicn0; + vlib_buffer_t *b0; + u32 bi0; + hicn_face_id_t outface; + int nh_idx; + u32 next0 = next_index; + int ret; + + /* Prefetch for next iteration. */ + 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); + } + /* Dequeue a packet buffer */ + bi0 = from[0]; + from += 1; + n_left_from -= 1; + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + next0 = HICN_STRATEGY_NEXT_ERROR_DROP; + + hicn_dpo_ctx_t *dpo_ctx = + hicn_strategy_dpo_ctx_get (vnet_buffer (b0)->ip. + adj_index[VLIB_TX]); + const hicn_strategy_vft_t *strategy = + hicn_dpo_get_strategy_vft (dpo_ctx->dpo_type); + + ret = hicn_interest_parse_pkt (b0, &name, &namelen, &hicn0, &isv6); + stats.pkts_processed++; + /* Select next hop */ + /* + * Double check that the interest has been through + * the interest-pcslookup node due to misconfiguration in + * the punting rules. + */ + if (PREDICT_TRUE + (ret == HICN_ERROR_NONE && HICN_IS_NAMEHASH_CACHED (b0) + && strategy->hicn_select_next_hop (vnet_buffer (b0)-> + ip.adj_index[VLIB_TX], + &nh_idx, + &outface) == + HICN_ERROR_NONE)) + { + /* + * No need to check if parsing was successful + * here. Already checked in the interest_pcslookup + * node + */ + nameptr = (u8 *) (&name); + hicn_new_interest (rt, b0, &next0, tnow, nameptr, namelen, + outface, nh_idx, + vnet_buffer (b0)->ip.adj_index[VLIB_TX], + strategy, dpo_ctx->dpo_type, isv6, &stats); + } + /* Maybe trace */ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b0->flags & VLIB_BUFFER_IS_TRACED))) + { + hicn_strategy_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->pkt_type = HICN_PKT_TYPE_CONTENT; + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + t->next_index = next0; + t->dpo_type = dpo_ctx->dpo_type; + } + /* + * Verify speculative enqueue, maybe switch current + * next frame + */ + /* + * Fix in case of a wrong speculation. Needed for + * cloning the data in the right frame + */ + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, n_left_to_next, + bi0, next0); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, hicn_strategy_node.index, + HICNFWD_ERROR_PROCESSED, stats.pkts_processed); + vlib_node_increment_counter (vm, hicn_strategy_node.index, + HICNFWD_ERROR_INTERESTS, + stats.pkts_interest_count); + + return (frame->n_vectors); +} + +/* + * Node registration for the forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn_strategy_node) = + { + .name = "hicn-strategy", + .function = hicn_strategy_fn, + .vector_size = sizeof (u32), + .runtime_data_bytes = sizeof (int) + sizeof(hicn_pit_cs_t *), + .format_trace = hicn_strategy_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN (hicn_strategy_error_strings), + .error_strings = hicn_strategy_error_strings, + .n_next_nodes = HICN_STRATEGY_N_NEXT, + .next_nodes = + { + [HICN_STRATEGY_NEXT_INTEREST_HITPIT] = "hicn-interest-hitpit", + [HICN_STRATEGY_NEXT_INTEREST_HITCS] = "hicn-interest-hitcs", + [HICN_STRATEGY_NEXT_INTEREST_FACE4] = "hicn4-face-output", + [HICN_STRATEGY_NEXT_INTEREST_FACE6] = "hicn6-face-output", + [HICN_STRATEGY_NEXT_ERROR_DROP] = "error-drop", + }, + }; + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/udp_tunnels/udp_decap.h b/hicn-plugin/src/network/udp_tunnels/udp_decap.h new file mode 100644 index 000000000..9ddb8a73b --- /dev/null +++ b/hicn-plugin/src/network/udp_tunnels/udp_decap.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 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 __UDP_DECAP_H__ +#define __UDP_DECAP_H__ + +/** + * @file udp_decap.h + * + * Implements the udp decapsulation for udp tunnels + * + * Udp decap nodes follow the ip4/6-local nodes and their purpose + * is to retrieve the udp tunnel for the incoming packet. If a tunnel does + * not exist the packet is dropped. + * The following node to the udp decap nodes are the ip4/6-lookup nodes. + */ + +extern vlib_node_registration_t udp_decap_node; + +#endif // __UDP_DECAP_H__ diff --git a/hicn-plugin/src/network/udp_tunnels/udp_decap_node.c b/hicn-plugin/src/network/udp_tunnels/udp_decap_node.c new file mode 100644 index 000000000..5603f20f9 --- /dev/null +++ b/hicn-plugin/src/network/udp_tunnels/udp_decap_node.c @@ -0,0 +1,623 @@ +/* + * Copyright (c) 2020 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 "udp_tunnel.h" +#include "../mgmt.h" +#include "../hicn.h" +#include "../strategy_dpo_ctx.h" + +vlib_node_registration_t udp_decap_node; + +static char *udp_decap_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +/* Trace context struct */ +typedef enum +{ + UDP4_DECAP_NEXT_LOOKUP_IP4, + UDP4_DECAP_NEXT_LOOKUP_IP6, + UDP4_DECAP_N_NEXT, +} udp4_decap_next_t; + +typedef enum +{ + UDP6_DECAP_NEXT_LOOKUP_IP4, + UDP6_DECAP_NEXT_LOOKUP_IP6, + UDP6_DECAP_N_NEXT, +} udp6_decap_next_t; + +typedef struct udp4_decap_trace_t_ +{ + ip4_header_t ip; + udp_header_t udp; +} udp4_decap_trace_t; + +typedef struct udp6_decap_trace_t_ +{ + ip6_header_t ip; + udp_header_t udp; +} udp6_decap_trace_t; + +typedef struct udp_decap_trace_t_ +{ + union + { + udp4_decap_trace_t udp4; + udp6_decap_trace_t udp6; + }; + + u8 isv6; + u8 ishicn; +} udp_decap_trace_t; + + +static u8 * +format_udp_decap_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 *); + udp_decap_trace_t *t; + + t = va_arg (*args, udp_decap_trace_t *); + + if (t->isv6) + { + s = format (s, "%U\n %U \n %s", + format_ip4_header, &t->udp6.ip, sizeof (t->udp6.ip), + format_udp_header, &t->udp6.udp, sizeof (t->udp6.udp), + t->ishicn ? "hICN udp tunnel" : ""); + } + else + { + s = format (s, "%U\n %U \n %s", + format_ip4_header, &t->udp4.ip, sizeof (t->udp4.ip), + format_udp_header, &t->udp4.udp, sizeof (t->udp4.udp), + t->ishicn ? "hICN udp tunnel" : ""); + } + return (s); +} + +static_always_inline void +udp_decap_trace_buffer (vlib_main_t * vm, vlib_node_runtime_t * node, + u8 isv6, vlib_buffer_t * b) +{ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && + (b->flags & VLIB_BUFFER_IS_TRACED))) + { + udp_decap_trace_t *t = + vlib_add_trace (vm, node, b, sizeof (*t)); + t->isv6 = isv6; + hicn_buffer_t *hb = hicn_get_buffer(b); + + if (isv6) + { + clib_memcpy(&(t->udp6.udp), vlib_buffer_get_current(b) + sizeof(ip6_header_t), sizeof(udp_header_t)); + clib_memcpy(&(t->udp6.ip), vlib_buffer_get_current(b), sizeof(ip6_header_t)); + t->ishicn = hb->flags & hb->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL; + } + else + { + clib_memcpy(&(t->udp4.udp), vlib_buffer_get_current(b) + sizeof(ip4_header_t), sizeof(udp_header_t)); + clib_memcpy(&(t->udp4.ip), vlib_buffer_get_current(b), sizeof(ip4_header_t)); + t->ishicn = hb->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL; + } + } +} + +static uword +udp4_decap_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, next_index; + + 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); + + /* Dual loop, X2 */ + while (n_left_from >= 8 && n_left_to_next >= 4) + { + vlib_buffer_t *b0, *b1, *b2, *b3; + u32 bi0, bi1, bi2, bi3; + u32 next0, next1, next2, next3; + + { + 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); + } + + bi0 = from[0]; + bi1 = from[1]; + bi2 = from[2]; + bi3 = from[3]; + + from += 4; + n_left_from -= 4; + to_next[0] = bi0; + to_next[1] = bi1; + to_next[2] = bi2; + to_next[3] = bi3; + + to_next += 4; + n_left_to_next -= 4; + + b0 = vlib_get_buffer (vm, bi0); + b1 = vlib_get_buffer (vm, bi1); + b2 = vlib_get_buffer (vm, bi2); + b3 = vlib_get_buffer (vm, bi3); + + u8 *ptr0 = vlib_buffer_get_current (b0); + u8 *ptr1 = vlib_buffer_get_current (b1); + u8 *ptr2 = vlib_buffer_get_current (b2); + u8 *ptr3 = vlib_buffer_get_current (b3); + u8 v0 = *ptr0 & 0xf0; + u8 v1 = *ptr1 & 0xf0; + u8 v2 = *ptr2 & 0xf0; + u8 v3 = *ptr3 & 0xf0; + + u8 advance = sizeof(ip4_header_t) + sizeof(udp_header_t); + + vlib_buffer_advance(b0, -advance); + vlib_buffer_advance(b1, -advance); + vlib_buffer_advance(b2, -advance); + vlib_buffer_advance(b3, -advance); + + u8 *outer_ptr0 = vlib_buffer_get_current (b0); + u8 *outer_ptr1 = vlib_buffer_get_current (b1); + u8 *outer_ptr2 = vlib_buffer_get_current (b2); + u8 *outer_ptr3 = vlib_buffer_get_current (b3); + u8 outer_v0 = *outer_ptr0 & 0xf0; + u8 outer_v1 = *outer_ptr1 & 0xf0; + u8 outer_v2 = *outer_ptr2 & 0xf0; + u8 outer_v3 = *outer_ptr3 & 0xf0; + + ip46_address_t src0 = {0}; + ip46_address_t src1 = {0}; + ip46_address_t src2 = {0}; + ip46_address_t src3 = {0}; + + ip46_address_t dst0 = {0}; + ip46_address_t dst1 = {0}; + ip46_address_t dst2 = {0}; + ip46_address_t dst3 = {0}; + + udp_header_t * udp0 = NULL; + udp_header_t * udp1 = NULL; + udp_header_t * udp2 = NULL; + udp_header_t * udp3 = NULL; + + ip46_address_set_ip4(&src0, &((ip4_header_t *)outer_ptr0)->src_address); + ip46_address_set_ip4(&dst0, &((ip4_header_t *)outer_ptr0)->dst_address); + udp0 = (udp_header_t *)(outer_ptr0 + sizeof(ip4_header_t)); + next0 = v0 == 0x40? UDP4_DECAP_NEXT_LOOKUP_IP4 : UDP4_DECAP_NEXT_LOOKUP_IP6; + + ip46_address_set_ip4(&src1, &((ip4_header_t *)outer_ptr1)->src_address); + ip46_address_set_ip4(&dst1, &((ip4_header_t *)outer_ptr1)->dst_address); + udp1 = (udp_header_t *)(outer_ptr1 + sizeof(ip4_header_t)); + next1 = v1 == 0x40? UDP4_DECAP_NEXT_LOOKUP_IP4 : UDP4_DECAP_NEXT_LOOKUP_IP6; + + ip46_address_set_ip4(&src2, &((ip4_header_t *)outer_ptr2)->src_address); + ip46_address_set_ip4(&dst2, &((ip4_header_t *)outer_ptr2)->dst_address); + udp2 = (udp_header_t *)(outer_ptr2 + sizeof(ip4_header_t)); + next2 = v2 == 0x40? UDP4_DECAP_NEXT_LOOKUP_IP4 : UDP4_DECAP_NEXT_LOOKUP_IP6; + + ip46_address_set_ip4(&src3, &((ip4_header_t *)outer_ptr3)->src_address); + ip46_address_set_ip4(&dst3, &((ip4_header_t *)outer_ptr3)->dst_address); + udp3 = (udp_header_t *)(outer_ptr3 + sizeof(ip4_header_t)); + next3 = v3 == 0x40? UDP4_DECAP_NEXT_LOOKUP_IP4 : UDP4_DECAP_NEXT_LOOKUP_IP6; + + hicn_buffer_t *hicnb0, *hicnb1, *hicnb2, *hicnb3; + hicnb0 = hicn_get_buffer(b0); + hicnb1 = hicn_get_buffer(b1); + hicnb2 = hicn_get_buffer(b2); + hicnb3 = hicn_get_buffer(b3); + + + /* Udp encap-decap tunnels have dst and src addresses and port swapped */ + vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst0, &src0, udp0->dst_port, udp0->src_port); + vnet_buffer (b1)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst1, &src1, udp1->dst_port, udp1->src_port); + vnet_buffer (b2)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst2, &src2, udp2->dst_port, udp2->src_port); + vnet_buffer (b3)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst3, &src3, udp3->dst_port, udp3->src_port); + + if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] != + UDP_TUNNEL_INVALID) + hicnb0->flags |= (outer_v0 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); + + if (vnet_buffer (b1)->ip.adj_index[VLIB_RX] != + UDP_TUNNEL_INVALID) + hicnb1->flags |= (outer_v1 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); + + if (vnet_buffer (b2)->ip.adj_index[VLIB_RX] != + UDP_TUNNEL_INVALID) + hicnb2->flags |= (outer_v2 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); + + if (vnet_buffer (b3)->ip.adj_index[VLIB_RX] != + UDP_TUNNEL_INVALID) + hicnb3->flags |= (outer_v3 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); + + udp_decap_trace_buffer (vm, node, 1, b0); + udp_decap_trace_buffer (vm, node, 1, b1); + udp_decap_trace_buffer (vm, node, 1, b2); + udp_decap_trace_buffer (vm, node, 1, b3); + + vlib_buffer_advance(b0, advance); + vlib_buffer_advance(b1, advance); + vlib_buffer_advance(b2, advance); + vlib_buffer_advance(b3, advance); + + vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next, + n_left_to_next, bi0, bi1, bi2, bi3, + next0, next1, next2, next3); + } + + /* Dual loop, X1 */ + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *b0; + u32 bi0; + /* udp_encap_t *udp_tunnel0 = NULL; */ + u32 next0; + + if (n_left_from > 1) + { + vlib_buffer_t *b1; + b1 = vlib_get_buffer (vm, from[1]); + CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, STORE); + } + + bi0 = from[0]; + from += 1; + n_left_from -= 1; + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + u8 *ptr0 = vlib_buffer_get_current (b0); + u8 v0 = *ptr0 & 0xf0; + + u8 advance = sizeof(ip4_header_t) + sizeof(udp_header_t);; + + vlib_buffer_advance(b0, -advance); + + u8 *outer_ptr0 = vlib_buffer_get_current (b0); + u8 outer_v0 = *outer_ptr0 & 0xf0; + + ip46_address_t src0 = {0}; + ip46_address_t dst0 = {0}; + udp_header_t * udp0 = NULL; + + ip46_address_set_ip4(&src0, &((ip4_header_t *)outer_ptr0)->src_address); + ip46_address_set_ip4(&dst0, &((ip4_header_t *)outer_ptr0)->dst_address); + udp0 = (udp_header_t *)(outer_ptr0 + sizeof(ip4_header_t)); + next0 = v0 == 0x40 ? UDP4_DECAP_NEXT_LOOKUP_IP4: UDP4_DECAP_NEXT_LOOKUP_IP6; + + hicn_buffer_t *hicnb0 = hicn_get_buffer(b0); + + vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst0, &src0, udp0->dst_port, udp0->src_port); + + if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] != + UDP_TUNNEL_INVALID) + hicnb0->flags |= (outer_v0 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); + + udp_decap_trace_buffer (vm, node, 1, b0); + + vlib_buffer_advance(b0, advance); + + 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); + } + + return (frame->n_vectors); +} + + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(udp4_decap_node) = +{ + .function = udp4_decap_node_fn, + .name = "udp4-decap", + .vector_size = sizeof(u32), + .format_trace = format_udp_decap_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(udp_decap_error_strings), + .error_strings = udp_decap_error_strings, + .n_next_nodes = UDP4_DECAP_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = + { + [UDP4_DECAP_NEXT_LOOKUP_IP4] = "ip4-lookup", + [UDP4_DECAP_NEXT_LOOKUP_IP6] = "ip6-lookup" + }, +}; +/* *INDENT-ON* */ + +static uword +udp6_decap_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, next_index; + + 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); + + /* Dual loop, X2 */ + while (n_left_from >= 8 && n_left_to_next >= 4) + { + vlib_buffer_t *b0, *b1, *b2, *b3; + u32 bi0, bi1, bi2, bi3; + u32 next0, next1, next2, next3; + + { + 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); + } + + bi0 = from[0]; + bi1 = from[1]; + bi2 = from[2]; + bi3 = from[3]; + + from += 4; + n_left_from -= 4; + to_next[0] = bi0; + to_next[1] = bi1; + to_next[2] = bi2; + to_next[3] = bi3; + + to_next += 4; + n_left_to_next -= 4; + + b0 = vlib_get_buffer (vm, bi0); + b1 = vlib_get_buffer (vm, bi1); + b2 = vlib_get_buffer (vm, bi2); + b3 = vlib_get_buffer (vm, bi3); + + u8 *ptr0 = vlib_buffer_get_current (b0); + u8 *ptr1 = vlib_buffer_get_current (b1); + u8 *ptr2 = vlib_buffer_get_current (b2); + u8 *ptr3 = vlib_buffer_get_current (b3); + u8 v0 = *ptr0 & 0xf0; + u8 v1 = *ptr1 & 0xf0; + u8 v2 = *ptr2 & 0xf0; + u8 v3 = *ptr3 & 0xf0; + + u8 advance = sizeof(ip6_header_t) + sizeof(udp_header_t); + + vlib_buffer_advance(b0, -advance); + vlib_buffer_advance(b1, -advance); + vlib_buffer_advance(b2, -advance); + vlib_buffer_advance(b3, -advance); + + u8 *outer_ptr0 = vlib_buffer_get_current (b0); + u8 *outer_ptr1 = vlib_buffer_get_current (b1); + u8 *outer_ptr2 = vlib_buffer_get_current (b2); + u8 *outer_ptr3 = vlib_buffer_get_current (b3); + u8 outer_v0 = *outer_ptr0 & 0xf0; + u8 outer_v1 = *outer_ptr1 & 0xf0; + u8 outer_v2 = *outer_ptr2 & 0xf0; + u8 outer_v3 = *outer_ptr3 & 0xf0; + + ip46_address_t src0 = {0}; + ip46_address_t src1 = {0}; + ip46_address_t src2 = {0}; + ip46_address_t src3 = {0}; + + ip46_address_t dst0 = {0}; + ip46_address_t dst1 = {0}; + ip46_address_t dst2 = {0}; + ip46_address_t dst3 = {0}; + + udp_header_t * udp0 = NULL; + udp_header_t * udp1 = NULL; + udp_header_t * udp2 = NULL; + udp_header_t * udp3 = NULL; + + ip46_address_set_ip6(&src0, &((ip6_header_t *)outer_ptr0)->src_address); + ip46_address_set_ip6(&dst0, &((ip6_header_t *)outer_ptr0)->dst_address); + udp0 = (udp_header_t *)(outer_ptr0 + sizeof(ip6_header_t)); + next0 = v0 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6; + + ip46_address_set_ip6(&src1, &((ip6_header_t *)outer_ptr1)->src_address); + ip46_address_set_ip6(&dst1, &((ip6_header_t *)outer_ptr1)->dst_address); + udp1 = (udp_header_t *)(outer_ptr1 + sizeof(ip6_header_t)); + next1 = v1 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6; + + ip46_address_set_ip6(&src2, &((ip6_header_t *)outer_ptr2)->src_address); + ip46_address_set_ip6(&dst2, &((ip6_header_t *)outer_ptr2)->dst_address); + udp2 = (udp_header_t *)(outer_ptr2 + sizeof(ip6_header_t)); + next2 = v2 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6; + + ip46_address_set_ip6(&src3, &((ip6_header_t *)outer_ptr3)->src_address); + ip46_address_set_ip6(&dst3, &((ip6_header_t *)outer_ptr3)->dst_address); + udp3 = (udp_header_t *)(outer_ptr3 + sizeof(ip6_header_t)); + next3 = v3 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6; + + hicn_buffer_t *hicnb0, *hicnb1, *hicnb2, *hicnb3; + hicnb0 = hicn_get_buffer(b0); + hicnb1 = hicn_get_buffer(b1); + hicnb2 = hicn_get_buffer(b2); + hicnb3 = hicn_get_buffer(b3); + + + /* Udp encap-decap tunnels have dst and src addresses and port swapped */ + vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst0, &src0, udp0->dst_port, udp0->src_port); + vnet_buffer (b1)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst1, &src1, udp1->dst_port, udp1->src_port); + vnet_buffer (b2)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst2, &src2, udp2->dst_port, udp2->src_port); + vnet_buffer (b3)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst3, &src3, udp3->dst_port, udp3->src_port); + + if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] != + UDP_TUNNEL_INVALID) + hicnb0->flags |= (outer_v0 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); + + if (vnet_buffer (b1)->ip.adj_index[VLIB_RX] != + UDP_TUNNEL_INVALID) + hicnb1->flags |= (outer_v1 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); + + if (vnet_buffer (b2)->ip.adj_index[VLIB_RX] != + UDP_TUNNEL_INVALID) + hicnb2->flags |= (outer_v2 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); + + if (vnet_buffer (b3)->ip.adj_index[VLIB_RX] != + UDP_TUNNEL_INVALID) + hicnb3->flags |= (outer_v3 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); + + udp_decap_trace_buffer (vm, node, 0, b0); + udp_decap_trace_buffer (vm, node, 0, b1); + udp_decap_trace_buffer (vm, node, 0, b2); + udp_decap_trace_buffer (vm, node, 0, b3); + + vlib_buffer_advance(b0, advance); + vlib_buffer_advance(b1, advance); + vlib_buffer_advance(b2, advance); + vlib_buffer_advance(b3, advance); + + vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next, + n_left_to_next, bi0, bi1, bi2, bi3, + next0, next1, next2, next3); + } + + /* Dual loop, X1 */ + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *b0; + u32 bi0; + /* udp_encap_t *udp_tunnel0 = NULL; */ + u32 next0; + + if (n_left_from > 1) + { + vlib_buffer_t *b1; + b1 = vlib_get_buffer (vm, from[1]); + CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, STORE); + } + + bi0 = from[0]; + from += 1; + n_left_from -= 1; + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + u8 *ptr0 = vlib_buffer_get_current (b0); + u8 v0 = *ptr0 & 0xf0; + + u8 advance = sizeof(ip6_header_t) + sizeof(udp_header_t); + + vlib_buffer_advance(b0, -advance); + + u8 *outer_ptr0 = vlib_buffer_get_current (b0); + u8 outer_v0 = *outer_ptr0 & 0xf0; + + ip46_address_t src0 = {0}; + ip46_address_t dst0 = {0}; + udp_header_t * udp0 = NULL; + + ip46_address_set_ip6(&src0, &((ip6_header_t *)outer_ptr0)->src_address); + ip46_address_set_ip6(&dst0, &((ip6_header_t *)outer_ptr0)->dst_address); + udp0 = (udp_header_t *)(outer_ptr0 + sizeof(ip6_header_t)); + next0 = v0 == 0x40? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6; + + hicn_buffer_t *hicnb0 = hicn_get_buffer(b0); + + vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst0, &src0, udp0->dst_port, udp0->src_port); + + if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] != + UDP_TUNNEL_INVALID) + hicnb0->flags |= (outer_v0 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); + + udp_decap_trace_buffer (vm, node, 0, b0); + + vlib_buffer_advance(b0, advance); + + 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); + } + + return (frame->n_vectors); +} + + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE(udp6_decap_node) = +{ + .function = udp6_decap_node_fn, + .name = "udp6-decap", + .vector_size = sizeof(u32), + .format_trace = format_udp_decap_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(udp_decap_error_strings), + .error_strings = udp_decap_error_strings, + .n_next_nodes = UDP6_DECAP_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = + { + [UDP6_DECAP_NEXT_LOOKUP_IP4] = "ip4-lookup", + [UDP6_DECAP_NEXT_LOOKUP_IP6] = "ip6-lookup" + }, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/hicn-plugin/src/network/udp_tunnels/udp_tunnel.c b/hicn-plugin/src/network/udp_tunnels/udp_tunnel.c new file mode 100644 index 000000000..872e4cd82 --- /dev/null +++ b/hicn-plugin/src/network/udp_tunnels/udp_tunnel.c @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2020 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 "../error.h" +#include "../strategy_dpo_ctx.h" +#include "udp_tunnel.h" + +clib_bihash_40_8_t udp_tunnels_hashtb; +dpo_type_t dpo_type_udp_ip4; +dpo_type_t dpo_type_udp_ip6; + +u32 udp_tunnel_add (fib_protocol_t proto, + index_t fib_index, + const ip46_address_t * src_ip, + const ip46_address_t * dst_ip, + u16 src_port, + u16 dst_port, + udp_encap_fixup_flags_t flags) +{ + vlib_main_t *vm = vlib_get_main(); + clib_bihash_kv_40_8_t kv; + clib_memcpy(&kv.key[0], src_ip, sizeof(ip46_address_t)); + clib_memcpy(&kv.key[2], dst_ip, sizeof(ip46_address_t)); + kv.key[4] = (clib_host_to_net_u16(src_port) << 16) + clib_host_to_net_u16(dst_port); + + clib_bihash_kv_40_8_t value; + int rv = clib_bihash_search_40_8 (&udp_tunnels_hashtb, &kv, &value); + + if (rv != 0) + { + u32 uei = udp_encap_add_and_lock(proto, fib_index, src_ip, dst_ip, src_port, dst_port, flags); + kv.value = uei; + clib_bihash_add_del_40_8(&udp_tunnels_hashtb, &kv, 1); + value.value = kv.value; + if (proto == FIB_PROTOCOL_IP4) + { + udp_register_dst_port(vm, src_port, udp4_decap_node.index, 1); + } + else + { + udp_register_dst_port(vm, src_port, udp6_decap_node.index, 0); + } + } + + return value.value; +} + +void udp_tunnel_add_existing (index_t uei, dpo_proto_t proto) +{ + vlib_main_t *vm = vlib_get_main(); + udp_encap_t * udp_encap = udp_encap_get(uei); + clib_bihash_kv_40_8_t kv; + + ip46_address_t src = {0}; + ip46_address_t dst = {0}; + u16 src_port = 0, dst_port = 0; + + switch (proto) + { + case DPO_PROTO_IP4: + ip46_address_set_ip4(&src, &(udp_encap->ue_hdrs.ip4.ue_ip4.src_address)); + ip46_address_set_ip4(&dst, &(udp_encap->ue_hdrs.ip4.ue_ip4.dst_address)); + src_port = udp_encap->ue_hdrs.ip4.ue_udp.src_port; + dst_port = udp_encap->ue_hdrs.ip4.ue_udp.dst_port; + break; + case DPO_PROTO_IP6: + ip46_address_set_ip6(&src, &(udp_encap->ue_hdrs.ip6.ue_ip6.src_address)); + ip46_address_set_ip6(&dst, &(udp_encap->ue_hdrs.ip6.ue_ip6.dst_address)); + src_port = udp_encap->ue_hdrs.ip6.ue_udp.src_port; + dst_port = udp_encap->ue_hdrs.ip6.ue_udp.dst_port; + break; + default: + break; + } + + clib_memcpy(&kv.key[0], &src, sizeof(ip46_address_t)); + clib_memcpy(&kv.key[2], &dst, sizeof(ip46_address_t)); + kv.key[4] = (src_port << 16) + dst_port ; + kv.value = uei; + + clib_bihash_add_del_40_8(&udp_tunnels_hashtb, &kv, 1); + + if (proto == DPO_PROTO_IP4) + { + udp_register_dst_port(vm, clib_net_to_host_u16(src_port), udp4_decap_node.index, 1); + } + else + { + udp_register_dst_port(vm, clib_net_to_host_u16(src_port), udp6_decap_node.index, 0); + } +} + +int udp_tunnel_del (fib_protocol_t proto, + index_t fib_index, + const ip46_address_t * src_ip, + const ip46_address_t * dst_ip, + u16 src_port, + u16 dst_port, + udp_encap_fixup_flags_t flags) +{ + clib_bihash_kv_40_8_t kv; + clib_memcpy(&kv.key[0], src_ip, sizeof(ip46_address_t)); + clib_memcpy(&kv.key[2], dst_ip, sizeof(ip46_address_t)); + kv.key[4] = (clib_host_to_net_u16(src_port) << 16) + clib_host_to_net_u16(dst_port); + + clib_bihash_kv_40_8_t value; + int ret = clib_bihash_search_40_8 (&udp_tunnels_hashtb, &kv, &value); + + if (ret == 0) + { + udp_encap_unlock((u32)value.value); + clib_bihash_add_del_40_8(&udp_tunnels_hashtb, &kv, 0); + ret = HICN_ERROR_NONE; + } + else + { + ret = HICN_ERROR_UDP_TUNNEL_NOT_FOUND; + } + + return ret; +} + +u32 udp_tunnel_get(const ip46_address_t * src_ip, + const ip46_address_t * dst_ip, + u16 src_port, + u16 dst_port) +{ + clib_bihash_kv_40_8_t kv; + clib_memcpy(&kv.key[0], src_ip, sizeof(ip46_address_t)); + clib_memcpy(&kv.key[2], dst_ip, sizeof(ip46_address_t)); + kv.key[4] = (src_port << 16) + dst_port; + + clib_bihash_kv_40_8_t value; + int ret = clib_bihash_search_40_8 (&udp_tunnels_hashtb, &kv, &value); + + return ret == 0 ? (u32)value.value : UDP_TUNNEL_INVALID; +} + + +void udp_tunnel_init() +{ + clib_bihash_init_40_8(&udp_tunnels_hashtb, "udp encap table", + 2048, 256 << 20); + + /* + * Udp encap does not expose the dpo type when it registers. + * In the following we understand what is the dpo type for a udp_encap dpo. + */ + ip46_address_t src = {0}; + ip46_address_t dst = {0}; + + src.ip6.as_u8[15] = 1; + dst.ip6.as_u8[15] = 2; + + u32 fib_index = fib_table_find (FIB_PROTOCOL_IP6, HICN_FIB_TABLE); + u32 uei = udp_encap_add_and_lock(FIB_PROTOCOL_IP6, fib_index, &src, &dst, 4444, 4444, UDP_ENCAP_FIXUP_NONE); + + dpo_id_t temp = DPO_INVALID; + udp_encap_contribute_forwarding(uei, DPO_PROTO_IP6, &temp); + dpo_type_udp_ip6 = temp.dpoi_type; + udp_encap_unlock(uei); + + dpo_id_t temp2 = DPO_INVALID; + fib_index = fib_table_find (FIB_PROTOCOL_IP4, HICN_FIB_TABLE); + uei = udp_encap_add_and_lock(FIB_PROTOCOL_IP4, fib_index, &src, &dst, 4444, 4444, UDP_ENCAP_FIXUP_NONE); + udp_encap_contribute_forwarding(uei, DPO_PROTO_IP4, &temp2); + dpo_type_udp_ip4 = temp2.dpoi_type; + udp_encap_unlock(uei); +} + +static clib_error_t * +udp_tunnel_command_fn (vlib_main_t * vm, + unformat_input_t * main_input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + clib_error_t *error = NULL; + ip46_address_t src_ip = {0}, dst_ip = {0}; + u32 table_id, src_port, dst_port; + fib_protocol_t fproto; + u8 is_del; + index_t uei; + + is_del = 0; + fproto = FIB_PROTOCOL_MAX; + uei = ~0; + table_id = HICN_FIB_TABLE; + + /* Get a line of input. */ + if (unformat_user (main_input, unformat_line_input, line_input)) + { + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "index %d", &uei)) + ; + else if (unformat (line_input, "add")) + is_del = 0; + else if (unformat (line_input, "del")) + is_del = 1; + else if (unformat (line_input, "%U %U", + unformat_ip4_address, + &src_ip.ip4, unformat_ip4_address, &dst_ip.ip4)) + fproto = FIB_PROTOCOL_IP4; + else if (unformat (line_input, "%U %U", + unformat_ip6_address, + &src_ip.ip6, unformat_ip6_address, &dst_ip.ip6)) + fproto = FIB_PROTOCOL_IP6; + else if (unformat (line_input, "%d %d", &src_port, &dst_port)) + ; + else if (unformat (line_input, "table-id %d", &table_id)) + ; + else + { + error = unformat_parse_error (line_input); + goto done; + } + } + } + + index_t fib_index = fib_table_find (fproto, table_id); + if (~0 == fib_index) + { + error = clib_error_return (0, "Nonexistent table id %d", table_id); + goto done; + } + + if (!is_del && fproto != FIB_PROTOCOL_MAX) + { + uei = udp_tunnel_add(fproto, fib_index, &src_ip, &dst_ip, src_port, dst_port, UDP_ENCAP_FIXUP_NONE); + + vlib_cli_output (vm, "udp-encap: %d\n", uei); + } + else if (is_del) + { + int ret = udp_tunnel_del(fproto, fib_index, &src_ip, &dst_ip, src_port, dst_port, UDP_ENCAP_FIXUP_NONE); + error = (ret == HICN_ERROR_NONE) ? 0 : clib_error_return (0, "%s\n", + get_error_string + (ret)); + } + else + { + error = clib_error_return (0, "specify some IP addresses"); + } + + done: + unformat_free (line_input); + return error; + +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (udp_tunnel_command, static) = + { + .path = "udp tunnel", + .short_help = "udp tunnel [add/del] src_address dst_address src_port dst_port", + .function = udp_tunnel_command_fn, + }; +/* *INDENT-ON* */ + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/network/udp_tunnels/udp_tunnel.h b/hicn-plugin/src/network/udp_tunnels/udp_tunnel.h new file mode 100644 index 000000000..2ec92056c --- /dev/null +++ b/hicn-plugin/src/network/udp_tunnels/udp_tunnel.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2020 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 __UDP_TUNNEL__ +#define __UDP_TUNNEL__ + +#include +#include +#include + +/** + * @file udp_tunnel.h + * + * This file implements bidirectional udp tunnels. Udp tunnels exploit + * the udp encap functionality in vpp. In particular, a udp tunnel creates + * an udp encap object with the information for encapsulating packets and it + * implements the udp decap node. The udp decap node checks if a udp tunnel exists + * before performing the decapsulation. If the tunnel does not exist the packet + * is dropped. + */ + +#define UDP_TUNNEL_INVALID ~0 + +extern dpo_type_t dpo_type_udp_ip4; +extern dpo_type_t dpo_type_udp_ip6; + +extern vlib_node_registration_t udp4_decap_node; +extern vlib_node_registration_t udp6_decap_node; + +/** + * @brief Create a udp tunnel + * + * @param proto FIB_PROTOCOL_IP4 or FIB_PROTOCOL_IP6 + * @param fib_index fib index to add to the udp encap + * @param src_ip source address of the tunnel + * @param dst_ip destination address of the tunnel + * @param src_port source port + * @param src_port destination port + * @param flags flags for the udp encap + * + * @return return the id of the tunnel + */ +u32 udp_tunnel_add (fib_protocol_t proto, + index_t fib_index, + const ip46_address_t * src_ip, + const ip46_address_t * dst_ip, + u16 src_port, + u16 dst_port, + udp_encap_fixup_flags_t flags); + +/** + * @brief Retrieve the index of a udp tunnel (same id of the udp encap) + * + * @param src_ip source address of the tunnel + * @param dst_ip destination address of the tunnel + * @param src_port source port + * @param src_port destination port + * + * @return id of the udp tunnel/encap + */ +u32 udp_tunnel_get(const ip46_address_t * src_ip, + const ip46_address_t * dst_ip, + u16 src_port, + u16 dst_port); + +/** + * @brief Delete a udp tunnel + * + * @param proto FIB_PROTOCOL_IP4 or FIB_PROTOCOL_IP6 + * @param fib_index fib index to add to the udp encap + * @param src_ip source address of the tunnel + * @param dst_ip destination address of the tunnel + * @param src_port source port + * @param src_port destination port + * @param flags flags for the udp encap + * + * @return HICN_ERROR_UDP_TUNNEL_NOT_FOUND if the tunnel was not found + * or HICN_ERROR_NONE if the tunnel has been deleted + */ +int udp_tunnel_del (fib_protocol_t proto, + index_t fib_index, + const ip46_address_t * src_ip, + const ip46_address_t * dst_ip, + u16 src_port, + u16 dst_port, + udp_encap_fixup_flags_t flags); + +/** + * @brief Add a udp tunnel from an existing udp encap + * + * @param uei index of the udp encap object + * @param proto DPO_PROTO_IP6 or DPO_PROTO_IP4 + */ +void udp_tunnel_add_existing (index_t uei, dpo_proto_t proto); + +/** + * @brief Init the udp tunnel module + * + */ +void udp_tunnel_init(); + +#endif diff --git a/hicn-plugin/src/network/utils.h b/hicn-plugin/src/network/utils.h new file mode 100644 index 000000000..689942ab6 --- /dev/null +++ b/hicn-plugin/src/network/utils.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2017-2019 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_UTILS_H__ +#define __HICN_UTILS_H__ + +#include "hicn.h" + +/** + * @file + * + * Helpers to print hicn headers + */ + +/** + * @Brief Print the hicn name + * + * @param name hicn name to print + */ +always_inline void +hicn_print_name6 (hicn_name_t * name) +{ + u8 *s0; + s0 = format (0, "Source addr %U, seq_number %u", format_ip6_address, + (ip6_address_t *) name->ip6.prefix, + clib_net_to_host_u32 (name->ip6.suffix)); + + printf ("%s\n", s0); +} + +/** + * @Brief Print the ipv6 hicn header (src and dst address and port) + * + * @param hicn0 hICN header to print + */ +always_inline void +hicn_print6 (hicn_header_t * hicn0) +{ + vlib_main_t *vm = vlib_get_main (); + u8 *s0; + s0 = format (0, "Source addr %U:%u, dest addr %U:%u", format_ip6_address, + &(hicn0->v6.ip.saddr), + clib_net_to_host_u32 (hicn0->v6.tcp.seq), format_ip6_address, + &(hicn0->v6.ip.daddr), + clib_net_to_host_u32 (hicn0->v6.tcp.seq)); + + vlib_cli_output (vm, "%s\n", s0); +} + +/** + * @Brief Print the ipv4 hicn header (src and dst address and port) + * + * @param hicn0 hICN header to print + */ +always_inline void +hicn_print4 (hicn_header_t * hicn0) +{ + u8 *s0; + s0 = format (0, "Source addr %U:%u, dest addr %U:%u", format_ip4_address, + &(hicn0->v4.ip.saddr), + clib_net_to_host_u32 (hicn0->v4.tcp.seq), format_ip4_address, + &(hicn0->v4.ip.daddr), + clib_net_to_host_u32 (hicn0->v4.tcp.seq)); + + printf ("%s\n", s0); +} + +#endif /* // __HICN_UTILS_H__ */ + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: eval: (c-set-style "gnu") End: + */ diff --git a/hicn-plugin/src/params.h b/hicn-plugin/src/params.h deleted file mode 100644 index 606d50771..000000000 --- a/hicn-plugin/src/params.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_PARAM_H__ -#define __HICN_PARAM_H__ - -#include - -/** - * @file params.h - * - */ - - -/* - * Features - */ -#define HICN_FEATURE_CS 1 //1 enable 0 disable - -/* - * Face compile-time parameters - */ -#define HICN_PARAM_FACES_MAX 512 - -STATIC_ASSERT ((HICN_PARAM_FACES_MAX & (HICN_PARAM_FACES_MAX - 1)) == 0, - "HICN_PARAM_FACES_MAX must be a power of 2"); - -/* - * Max length for hICN names - */ -#define HICN_PARAM_HICN_NAME_LEN_MAX 20 //bytes - -// Max next - hops supported in a FIB entry -#define HICN_PARAM_FIB_ENTRY_NHOPS_MAX 10 - -// Default and limit on weight, whatever weight means -#define HICN_PARAM_FIB_ENTRY_NHOP_WGHT_DFLT 0x10 -#define HICN_PARAM_FIB_ENTRY_NHOP_WGHT_MAX 0xff - -/* - * PIT compile-time parameters - */ -#define HICN_PARAM_PIT_ENTRIES_MIN 1024 -#define HICN_PARAM_PIT_ENTRIES_DFLT 1024 * 128 -#define HICN_PARAM_PIT_ENTRIES_MAX 2 * 1024 * 1024 - -// aggregation limit(interest previous hops) -// Supported up to 516. For more than 4 faces this param must -// HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4 must be a power of two -#define HICN_PARAM_PIT_ENTRY_PHOPS_MAX 20 - -STATIC_ASSERT ((ceil (log2 ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4)))) == - (floor (log2 ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4)))), - "HICN_PARAM_PIT_ENTRY_PHOPS_MAX - 4 must be a power of two"); - -STATIC_ASSERT ((HICN_PARAM_PIT_ENTRY_PHOPS_MAX <= HICN_PARAM_FACES_MAX), - "HICN_PARAM_PIT_ENTRY_PHOP_MAX must be <= than HICN_PARAM_FACES_MAX"); - -//tFIB parameters -#define HICN_PARAM_RTX_MAX 10 - -// PIT lifetime limits on API override this(in seconds, integer type) -#define HICN_PARAM_PIT_LIFETIME_BOUND_MIN_SEC 0 -#define HICN_PARAM_PIT_LIFETIME_BOUND_MAX_SEC 200 - -//PIT lifetime params if not set at API(in mseconds, integer type) -#define HICN_PARAM_PIT_LIFETIME_DFLT_MAX_MS 20000 - -// Face CS reservation params -#define HICN_PARAM_FACE_MAX_CS_RESERVED 20000 //packets -#define HICN_PARAM_FACE_MIN_CS_RESERVED 0 //packets -#define HICN_PARAM_FACE_DFT_CS_RESERVED 20000 //packets - -/* - * CS compile-time parameters - */ -#define HICN_PARAM_CS_ENTRIES_MIN 0 // can disable CS -#define HICN_PARAM_CS_ENTRIES_DFLT 4 * 1024 -#define HICN_PARAM_CS_ENTRIES_MAX 1024 * 1024 - -#define HICN_PARAM_CS_LRU_DEFAULT (16 * 1024) - -/* CS lifetime defines, in mseconds, integer type */ -#define HICN_PARAM_CS_LIFETIME_MIN 0 -#define HICN_PARAM_CS_LIFETIME_DFLT (5 * 60 * 1000) // 300 seconds -#define HICN_PARAM_CS_LIFETIME_MAX (24 * 3600 * 1000) //24 hours... - -/* CS reserved portion for applications */ -#define HICN_PARAM_CS_RESERVED_APP 50 //% -#define HICN_PARAM_CS_MIN_MBUF 4096 //this seems to be the minumim default number of mbuf we can have in vpp - -/* Cloning parameters */ -/* ip4 */ -#define HICN_IP4_VERSION_HEADER_LENGTH 0x45 -#define HICN_IP4_PROTOCOL IP_PROTOCOL_TCP -#define HICN_IP4_TTL_DEFAULT 128 - -/* ip6 */ -#define IPV6_DEFAULT_VERSION 6 -#define IPV6_DEFAULT_TRAFFIC_CLASS 0 -#define IPV6_DEFAULT_FLOW_LABEL 0 -#define HCIN_IP6_VERSION_TRAFFIC_FLOW (IPV6_DEFAULT_VERSION << 28) | \ - (IPV6_DEFAULT_TRAFFIC_CLASS << 20) | \ - (IPV6_DEFAULT_FLOW_LABEL & 0xfffff) -#define HICN_IP6_PROTOCOL IP_PROTOCOL_TCP -#define HICN_IP6_HOP_LIMIT 0x40 - -#endif /* // __HICN_PARAM_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/parser.h b/hicn-plugin/src/parser.h deleted file mode 100644 index e79d65831..000000000 --- a/hicn-plugin/src/parser.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2017-2019 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_PARSER_H__ -#define __HICN_PARSER_H__ - -#include - -#include "hicn.h" -#include "error.h" - -/** - * @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 - * - * @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 - */ -always_inline int -hicn_interest_parse_pkt (vlib_buffer_t * pkt, hicn_name_t * name, - u16 * namelen, hicn_header_t ** pkt_hdrp, u8 * isv6) -{ - 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 = - IPPROTO_NONE,.l2 = - ip_pkt[next_proto_offset],.l1 = - ip_proto} - }; - 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; - - return HICN_ERROR_NONE; -} - -/** - * @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 - */ -always_inline int -hicn_data_parse_pkt (vlib_buffer_t * pkt, hicn_name_t * name, - u16 * namelen, hicn_header_t ** pkt_hdrp, u8 * isv6) -{ - 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 = - IPPROTO_NONE,.l2 = - ip_pkt[next_proto_offset],.l1 = - ip_proto} - }; - 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; -} - - -#endif /* // __HICN_PARSER_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/pcs.c b/hicn-plugin/src/pcs.c deleted file mode 100644 index 6c44b9d83..000000000 --- a/hicn-plugin/src/pcs.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "hashtb.h" -#include "pcs.h" -#include "cache_policies/cs_lru.h" - -int -hicn_pit_create (hicn_pit_cs_t * p, u32 num_elems) -{ - int ret = - hicn_hashtb_alloc (&p->pcs_table, num_elems, sizeof (hicn_pcs_entry_t)); - p->pcs_table->ht_flags |= HICN_HASHTB_FLAG_KEY_FMT_NAME; - - p->pcs_pit_count = p->pcs_cs_count = 0; - - p->policy_state.max = - HICN_PARAM_CS_LRU_DEFAULT - - (HICN_PARAM_CS_LRU_DEFAULT * HICN_PARAM_CS_RESERVED_APP / 100); - p->policy_state.count = 0; - p->policy_state.head = p->policy_state.tail = 0; - - p->policy_vft.hicn_cs_insert = hicn_cs_lru.hicn_cs_insert; - p->policy_vft.hicn_cs_update = hicn_cs_lru.hicn_cs_update; - p->policy_vft.hicn_cs_dequeue = hicn_cs_lru.hicn_cs_dequeue; - p->policy_vft.hicn_cs_delete_get = hicn_cs_lru.hicn_cs_delete_get; - p->policy_vft.hicn_cs_trim = hicn_cs_lru.hicn_cs_trim; - p->policy_vft.hicn_cs_flush = hicn_cs_lru.hicn_cs_flush; - - return (ret); -} - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/pcs.h b/hicn-plugin/src/pcs.h deleted file mode 100644 index a9e1ae5a0..000000000 --- a/hicn-plugin/src/pcs.h +++ /dev/null @@ -1,839 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_PCS_H__ -#define __HICN_PCS_H__ - -#include "hashtb.h" -#include "face_db.h" -#include "strategy_dpo_manager.h" -#include "error.h" -#include "cache_policies/cs_policy.h" -#include "faces/face.h" - -/** - * @file pcs.h - * - * This file implement the PIT and CS which are collapsed in the same - * structure, thereore an entry is either a PIT entry of a CS entry. - * The implementation consist of a hash table where each entry of the - * hash table contains a PIT or CS entry, some counters to maintain the - * status of the PIT/CS and the reference to the eviction policy for - * the CS. The default eviction policy id FIFO. - */ - -/* The PIT and CS are stored as a union */ -#define HICN_PIT_NULL_TYPE 0 -#define HICN_PIT_TYPE 1 -#define HICN_CS_TYPE 2 - -/* - * Definitions and Forward refs for the time counters we're trying out. - * Counters are maintained by the background process. TODO. - */ -#define SEC_MS 1000 -#define HICN_INFRA_FAST_TIMER_SECS 1 -#define HICN_INFRA_FAST_TIMER_MSECS (HICN_INFRA_FAST_TIMER_SECS * SEC_MS) -#define HICN_INFRA_SLOW_TIMER_SECS 60 -#define HICN_INFRA_SLOW_TIMER_MSECS (HICN_INFRA_SLOW_TIMER_SECS * SEC_MS) - -/* - * Note that changing this may change alignment within the PIT struct, so be careful. - */ -typedef struct __attribute__ ((packed)) hicn_pcs_shared_s -{ - - /* Installation/creation time (vpp float units, for now) */ - f64 create_time; - - /* Expiration time (vpp float units, for now) */ - f64 expire_time; - - /* Shared 'flags' octet */ - u8 entry_flags; - - /* Needed to align for the pit or cs portion */ - u8 padding; -} hicn_pcs_shared_t; - -#define HICN_PCS_ENTRY_CS_FLAG 0x01 - -/* - * PIT entry, unioned with a CS entry below - */ -typedef struct __attribute__ ((packed)) hicn_pit_entry_s -{ - - /* Shared size 8 + 8 + 2 = 18B */ - - /* - * Egress next hop (containes the egress face) This id refers to the - * position of the choosen face in the next_hops array of the dpo */ - /* 18B + 1B = 19B */ - u8 pe_txnh; - - /* Array of incoming ifaces */ - /* 24B + 32B (8B*4) =56B */ - hicn_face_db_t faces; - -} hicn_pit_entry_t; - -#define HICN_CS_ENTRY_OPAQUE_SIZE HICN_HASH_NODE_APP_DATA_SIZE - 36 - -/* - * CS entry, unioned with a PIT entry below - */ -typedef struct __attribute__ ((packed)) hicn_cs_entry_s -{ - /* 18B + 2B = 20B */ - u16 align; - - /* Packet buffer, if held */ - /* 20B + 4B = 24B */ - u32 cs_pkt_buf; - - /* Ingress face */ - /* 24B + 4B = 28B */ - hicn_face_id_t cs_rxface; - - /* Linkage for LRU, in the form of hashtable node indexes */ - /* 28B + 8B = 36B */ - u32 cs_lru_prev; - u32 cs_lru_next; - - /* Reserved for implementing cache policy different than LRU */ - /* 36B + (64 - 36)B = 64B */ - u8 opaque[HICN_CS_ENTRY_OPAQUE_SIZE]; - - -} __attribute__ ((packed)) hicn_cs_entry_t; - -/* - * Combined PIT/CS entry data structure, embedded in a hashtable entry after - * the common hashtable preamble struct. This MUST fit in the available - * (fixed) space in a hashtable node. - */ -typedef struct hicn_pcs_entry_s -{ - - hicn_pcs_shared_t shared; - - union - { - hicn_pit_entry_t pit; - hicn_cs_entry_t cs; - } u; -} hicn_pcs_entry_t; - - -/* - * Overall PIT/CS table, based on the common hashtable - */ -typedef struct hicn_pit_cs_s -{ - - hicn_hashtb_t *pcs_table; - - /* Counters for PIT/CS sentries */ - u32 pcs_pit_count; - u32 pcs_cs_count; - u32 pcs_cs_dealloc; - u32 pcs_pit_dealloc; - - /* Total size of PCS */ - u32 pcs_size; - - hicn_cs_policy_t policy_state; - hicn_cs_policy_vft_t policy_vft; - -} hicn_pit_cs_t; - -/* Functions declarations */ -int hicn_pit_create (hicn_pit_cs_t * p, u32 num_elems); - -always_inline void -hicn_pit_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t * pcs_entry, hicn_hash_entry_t * hash_entry, - hicn_hash_node_t * node, const hicn_dpo_vft_t * dpo_vft, - dpo_id_t * hicn_dpo_id, hicn_face_id_t inface_id, u8 is_appface); - -always_inline void -hicn_pcs_cs_update (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t * old_entry, hicn_pcs_entry_t * entry, - hicn_hash_node_t * node); - -always_inline void -hicn_pcs_cs_delete (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t ** pcs_entry, hicn_hash_node_t ** node, - hicn_hash_entry_t * hash_entry, - const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id); - -always_inline int -hicn_pcs_cs_insert (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t * entry, hicn_hash_node_t * node, - hicn_hash_entry_t ** hash_entry, u64 hashval, - u32 * node_id, index_t * dpo_ctx_id, u8 * vft_id, - u8 * is_cs, u8 * hash_entry_id, u32 * bucket_id, - u8 * bucket_is_overflow); - -always_inline int -hicn_pcs_cs_insert_update (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t * entry, hicn_hash_node_t * node, - hicn_hash_entry_t ** hash_entry, u64 hashval, - u32 * node_id, index_t * dpo_ctx_id, u8 * vft_id, - u8 * is_cs, u8 * hash_entry_id, u32 * bucket_id, - u8 * bucket_is_overflow, hicn_face_id_t inface); - -always_inline int -hicn_pcs_pit_insert (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t * entry, - hicn_hash_node_t * node, hicn_hash_entry_t ** hash_entry, - u64 hashval, u32 * node_id, index_t * dpo_ctx_id, - u8 * vft_id, u8 * is_cs, u8 * hash_entry_id, - u32 * bucket_id, u8 * bucket_is_overflow); - -always_inline void -hicn_pcs_pit_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, - hicn_hash_node_t ** node, vlib_main_t * vm, - hicn_hash_entry_t * hash_entry, - const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id); - -always_inline int -hicn_pcs_insert (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t * entry, hicn_hash_node_t * node, - hicn_hash_entry_t ** hash_entry, u64 hashval, u32 * node_id, - index_t * dpo_ctx_id, u8 * vft_id, u8 * is_cs, - u8 * hash_entry_id, u32 * bucket_id, - u8 * bucket_is_overflow); - -always_inline void -hicn_pcs_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, - hicn_hash_node_t ** node, vlib_main_t * vm, - hicn_hash_entry_t * hash_entry, - const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id); - -always_inline void -hicn_pcs_remove_lock (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, - hicn_hash_node_t ** node, vlib_main_t * vm, - hicn_hash_entry_t * hash_entry, - const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id); - -always_inline void -hicn_cs_delete_trimmed (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, - hicn_hash_entry_t * hash_entry, - hicn_hash_node_t ** node, vlib_main_t * vm); - -/* Function implementation */ -/* Accessor for pit/cs data inside hash table node */ -static inline hicn_pcs_entry_t * -hicn_pit_get_data (hicn_hash_node_t * node) -{ - return (hicn_pcs_entry_t *) (hicn_hashtb_node_data (node)); -} - -/* Init pit/cs data block (usually inside hash table node) */ -static inline void -hicn_pit_init_data (hicn_pcs_entry_t * p) -{ - p->shared.entry_flags = 0; - p->u.pit.faces.n_faces = 0; - p->u.pit.faces.is_overflow = 0; - hicn_face_bucket_t *face_bkt; - pool_get (hicn_face_bucket_pool, face_bkt); - - p->u.pit.faces.next_bucket = face_bkt - hicn_face_bucket_pool; -} - -/* Init pit/cs data block (usually inside hash table node) */ -static inline void -hicn_cs_init_data (hicn_pcs_entry_t * p) -{ - p->shared.entry_flags = 0; - p->u.pit.faces.n_faces = 0; - p->u.pit.faces.is_overflow = 0; -} - - -static inline f64 -hicn_pcs_get_exp_time (f64 cur_time_sec, u64 lifetime_msec) -{ - return (cur_time_sec + ((f64) lifetime_msec) / SEC_MS); -} - -/* - * Configure CS LRU limit. Zero is accepted, means 'no limit', probably not a - * good choice. - */ -static inline void -hicn_pit_set_lru_max (hicn_pit_cs_t * p, u32 limit) -{ - p->policy_state.max = limit; -} - -/* - * Accessor for PIT interest counter. - */ -static inline u32 -hicn_pit_get_int_count (const hicn_pit_cs_t * pitcs) -{ - return (pitcs->pcs_pit_count); -} - -/* - * Accessor for PIT cs entries counter. - */ -static inline u32 -hicn_pit_get_cs_count (const hicn_pit_cs_t * pitcs) -{ - return (pitcs->pcs_cs_count); -} - -static inline u32 -hicn_pcs_get_ntw_count (const hicn_pit_cs_t * pitcs) -{ - return (pitcs->policy_state.count); -} - -static inline u32 -hicn_pit_get_htb_bucket_count (const hicn_pit_cs_t * pitcs) -{ - return (pitcs->pcs_table->ht_overflow_buckets_used); -} - -static inline int -hicn_cs_enabled (hicn_pit_cs_t * pit) -{ - switch (HICN_FEATURE_CS) - { - case 0: - default: - return (0); - case 1: - return (pit->policy_state.max > 0); - } -} - -/* - * Delete a PIT/CS entry from the hashtable, freeing the hash node struct. - * The caller's pointers are zeroed! If cs_trim is true, entry has already - * been removed from lru list The main purpose of this wrapper is helping - * maintain the per-PIT stats. - */ -always_inline void -hicn_pcs_delete_internal (hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t ** pcs_entryp, - hicn_hash_entry_t * hash_entry, - hicn_hash_node_t ** node, vlib_main_t * vm, - const hicn_dpo_vft_t * dpo_vft, - dpo_id_t * hicn_dpo_id) -{ - hicn_pcs_entry_t *pcs = *pcs_entryp; - - ASSERT (pcs == hicn_hashtb_node_data (*node)); - - if (hash_entry->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY) - { - pitcs->pcs_cs_dealloc++; - /* Free any associated packet buffer */ - vlib_buffer_free_one (vm, pcs->u.cs.cs_pkt_buf); - pcs->u.cs.cs_pkt_buf = ~0; - ASSERT ((pcs->u.cs.cs_lru_prev == 0) - && (pcs->u.cs.cs_lru_prev == pcs->u.cs.cs_lru_next)); - } - else - { - pitcs->pcs_pit_dealloc++; - hicn_strategy_dpo_ctx_unlock (hicn_dpo_id); - - /* Flush faces */ - hicn_faces_flush (&(pcs->u.pit.faces)); - } - - hicn_hashtb_delete (pitcs->pcs_table, node, hash_entry->he_msb64); - *pcs_entryp = NULL; -} - -/* - * Convert a PIT entry into a CS entry (assumes that the entry is already in - * the hashtable.) This is primarily here to maintain the internal counters. - */ -always_inline void -hicn_pit_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t * pcs_entry, hicn_hash_entry_t * hash_entry, - hicn_hash_node_t * node, const hicn_dpo_vft_t * dpo_vft, - dpo_id_t * hicn_dpo_id, hicn_face_id_t inface_id, u8 is_appface) -{ - - /* - * Different from the insert node. In here we don't need to add a new - * hash entry. - */ - pitcs->pcs_pit_count--; - hicn_strategy_dpo_ctx_unlock (hicn_dpo_id); - /* Flush faces */ - hicn_faces_flush (&(pcs_entry->u.pit.faces)); - - hash_entry->he_flags |= HICN_HASH_ENTRY_FLAG_CS_ENTRY; - node->hn_flags |= HICN_HASH_NODE_CS_FLAGS; - pcs_entry->shared.entry_flags |= HICN_PCS_ENTRY_CS_FLAG; - - pcs_entry->u.cs.cs_rxface = inface_id; - - /* Update the CS according to the policy */ - hicn_cs_policy_t *policy_state; - hicn_cs_policy_vft_t *policy_vft; - - policy_state = &pitcs->policy_state; - policy_vft = &pitcs->policy_vft; - - policy_vft->hicn_cs_insert (pitcs, node, pcs_entry, policy_state); - pitcs->pcs_cs_count++; - - if (policy_state->count > policy_state->max) - { - hicn_hash_node_t *node; - hicn_pcs_entry_t *pcs_entry; - hicn_hash_entry_t *hash_entry; - policy_vft->hicn_cs_delete_get (pitcs, policy_state, - &node, &pcs_entry, &hash_entry); - - - /* - * We don't have to decrease the lock (therefore we cannot - * use hicn_pcs_cs_delete function) - */ - policy_vft->hicn_cs_dequeue (pitcs, node, pcs_entry, policy_state); - - hicn_cs_delete_trimmed (pitcs, &pcs_entry, hash_entry, &node, vm); - - /* Update the global CS counter */ - pitcs->pcs_cs_count--; - } -} - -/* Functions specific for PIT or CS */ - -always_inline void -hicn_pcs_cs_update (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t * old_entry, hicn_pcs_entry_t * entry, - hicn_hash_node_t * node) -{ - hicn_cs_policy_t *policy_state; - hicn_cs_policy_vft_t *policy_vft; - - policy_state = &pitcs->policy_state; - policy_vft = &pitcs->policy_vft; - - if (entry->u.cs.cs_rxface != old_entry->u.cs.cs_rxface) - { - /* Dequeue content from the old queue */ - policy_vft->hicn_cs_dequeue (pitcs, node, old_entry, policy_state); - - old_entry->u.cs.cs_rxface = entry->u.cs.cs_rxface; - policy_state = &pitcs->policy_state; - policy_vft = &pitcs->policy_vft; - - policy_vft->hicn_cs_insert (pitcs, node, old_entry, policy_state); - - if (policy_state->count > policy_state->max) - { - hicn_hash_node_t *node; - hicn_pcs_entry_t *pcs_entry; - hicn_hash_entry_t *hash_entry; - policy_vft->hicn_cs_delete_get (pitcs, policy_state, - &node, &pcs_entry, &hash_entry); - - /* - * We don't have to decrease the lock (therefore we cannot - * use hicn_pcs_cs_delete function) - */ - policy_vft->hicn_cs_dequeue (pitcs, node, pcs_entry, policy_state); - - hicn_cs_delete_trimmed (pitcs, &pcs_entry, hash_entry, &node, vm); - - /* Update the global CS counter */ - pitcs->pcs_cs_count--; - } - } - else - /* Update the CS LRU, moving this item to the head */ - policy_vft->hicn_cs_update (pitcs, node, old_entry, policy_state); -} - -always_inline void -hicn_pcs_cs_delete (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t ** pcs_entryp, hicn_hash_node_t ** nodep, - hicn_hash_entry_t * hash_entry, - const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id) -{ - if (!(hash_entry->he_flags & HICN_HASH_ENTRY_FLAG_DELETED)) - { - hicn_cs_policy_t *policy_state; - hicn_cs_policy_vft_t *policy_vft; - - policy_state = &pitcs->policy_state; - policy_vft = &pitcs->policy_vft; - - policy_vft->hicn_cs_dequeue (pitcs, (*nodep), (*pcs_entryp), - policy_state); - - /* Update the global CS counter */ - pitcs->pcs_cs_count--; - } - - /* A data could have been inserted in the CS through a push. In this case locks == 0 */ - hash_entry->locks--; - if (hash_entry->locks == 0) - { - hicn_pcs_delete_internal - (pitcs, pcs_entryp, hash_entry, nodep, vm, dpo_vft, hicn_dpo_id); - } - else - { - hash_entry->he_flags |= HICN_HASH_ENTRY_FLAG_DELETED; - } -} - -always_inline int -hicn_pcs_cs_insert (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t * entry, hicn_hash_node_t * node, - hicn_hash_entry_t ** hash_entry, u64 hashval, - u32 * node_id, index_t * dpo_ctx_id, u8 * vft_id, - u8 * is_cs, u8 * hash_entry_id, u32 * bucket_id, - u8 * bucket_is_overflow) -{ - ASSERT (entry == hicn_hashtb_node_data (node)); - - int ret = - hicn_hashtb_insert (pitcs->pcs_table, node, hash_entry, hashval, node_id, - dpo_ctx_id, vft_id, is_cs, hash_entry_id, bucket_id, - bucket_is_overflow); - - if (PREDICT_TRUE (ret == HICN_ERROR_NONE)) - { - /* Mark the entry as a CS entry */ - node->hn_flags |= HICN_HASH_NODE_CS_FLAGS; - entry->shared.entry_flags |= HICN_PCS_ENTRY_CS_FLAG; - (*hash_entry)->he_flags |= HICN_HASH_ENTRY_FLAG_CS_ENTRY; - - hicn_cs_policy_t *policy_state; - hicn_cs_policy_vft_t *policy_vft; - - policy_state = &pitcs->policy_state; - policy_vft = &pitcs->policy_vft; - - policy_vft->hicn_cs_insert (pitcs, node, entry, policy_state); - pitcs->pcs_cs_count++; - - if (policy_state->count > policy_state->max) - { - hicn_hash_node_t *node; - hicn_pcs_entry_t *pcs_entry; - hicn_hash_entry_t *hash_entry; - policy_vft->hicn_cs_delete_get (pitcs, policy_state, - &node, &pcs_entry, &hash_entry); - - /* - * We don't have to decrease the lock (therefore we cannot - * use hicn_pcs_cs_delete function) - */ - policy_vft->hicn_cs_dequeue (pitcs, node, pcs_entry, policy_state); - - hicn_cs_delete_trimmed (pitcs, &pcs_entry, hash_entry, &node, vm); - - /* Update the global CS counter */ - pitcs->pcs_cs_count--; - } - } - return ret; -} - -/* - * Insert CS entry into the hashtable The main purpose of this wrapper is - * helping maintain the per-PIT stats. - */ -always_inline int -hicn_pcs_cs_insert_update (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t * entry, hicn_hash_node_t * node, - hicn_hash_entry_t ** hash_entry, u64 hashval, - u32 * node_id, index_t * dpo_ctx_id, u8 * vft_id, - u8 * is_cs, u8 * hash_entry_id, u32 * bucket_id, - u8 * bucket_is_overflow, hicn_face_id_t inface) -{ - int ret; - - ASSERT (entry == hicn_hashtb_node_data (node)); - - entry->u.cs.cs_rxface = inface; - ret = - hicn_pcs_cs_insert (vm, pitcs, entry, node, hash_entry, hashval, node_id, - dpo_ctx_id, vft_id, is_cs, hash_entry_id, bucket_id, - bucket_is_overflow); - - /* A content already exists in CS with the same name */ - if (ret == HICN_ERROR_HASHTB_EXIST && *is_cs) - { - /* Update the entry */ - hicn_hash_node_t *existing_node = - hicn_hashtb_node_from_idx (pitcs->pcs_table, *node_id); - hicn_pcs_entry_t *pitp = hicn_pit_get_data (existing_node); - - /* Free associated packet buffer and update counter */ - pitcs->pcs_cs_dealloc++; - vlib_buffer_free_one (vm, pitp->u.cs.cs_pkt_buf); - - pitp->shared.create_time = entry->shared.create_time; - pitp->shared.expire_time = entry->shared.expire_time; - pitp->u.cs.cs_pkt_buf = entry->u.cs.cs_pkt_buf; - - hicn_pcs_cs_update (vm, pitcs, pitp, entry, existing_node); - } - - return (ret); -} - -/* - * Insert PIT entry into the hashtable The main purpose of this wrapper is - * helping maintain the per-PIT stats. - */ -always_inline int -hicn_pcs_pit_insert (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t * entry, - hicn_hash_node_t * node, hicn_hash_entry_t ** hash_entry, - u64 hashval, u32 * node_id, index_t * dpo_ctx_id, - u8 * vft_id, u8 * is_cs, u8 * hash_entry_id, - u32 * bucket_id, u8 * bucket_is_overflow) -{ - ASSERT (entry == hicn_hashtb_node_data (node)); - - int ret = - hicn_hashtb_insert (pitcs->pcs_table, node, hash_entry, hashval, node_id, - dpo_ctx_id, vft_id, is_cs, hash_entry_id, bucket_id, - bucket_is_overflow); - - if (PREDICT_TRUE (ret == HICN_ERROR_NONE)) - pitcs->pcs_pit_count++; - - return ret; -} - -always_inline void -hicn_pcs_pit_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, - hicn_hash_node_t ** node, vlib_main_t * vm, - hicn_hash_entry_t * hash_entry, - const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id) -{ - hash_entry->locks--; - if (hash_entry->locks == 0) - { - pitcs->pcs_pit_count--; - hicn_pcs_delete_internal - (pitcs, pcs_entryp, hash_entry, node, vm, dpo_vft, hicn_dpo_id); - } - else - { - hash_entry->he_flags |= HICN_HASH_ENTRY_FLAG_DELETED; - } -} - - -/* Generic functions for PIT/CS */ - -/* - * Insert PIT/CS entry into the hashtable The main purpose of this wrapper is - * helping maintain the per-PIT stats. - */ -always_inline int -hicn_pcs_insert (vlib_main_t * vm, hicn_pit_cs_t * pitcs, - hicn_pcs_entry_t * entry, hicn_hash_node_t * node, - hicn_hash_entry_t ** hash_entry, u64 hashval, u32 * node_id, - index_t * dpo_ctx_id, u8 * vft_id, u8 * is_cs, - u8 * hash_entry_id, u32 * bucket_id, u8 * bucket_is_overflow) -{ - int ret; - - if ((*hash_entry)->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY) - { - ret = - hicn_pcs_cs_insert (vm, pitcs, entry, node, hash_entry, hashval, - node_id, dpo_ctx_id, vft_id, is_cs, hash_entry_id, - bucket_id, bucket_is_overflow); - } - else - { - ret = - hicn_pcs_pit_insert (pitcs, entry, node, hash_entry, hashval, node_id, - dpo_ctx_id, vft_id, is_cs, hash_entry_id, - bucket_id, bucket_is_overflow); - } - - return (ret); -} - - -/* - * Delete entry if there are no pending lock on the entry, otherwise mark it - * as to delete. - */ -always_inline void -hicn_pcs_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, - hicn_hash_node_t ** nodep, vlib_main_t * vm, - hicn_hash_entry_t * hash_entry, - const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id) -{ - /* - * If the entry has already been marked as deleted, it has already - * been dequeue - */ - if (hash_entry->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY) - { - hicn_pcs_cs_delete (vm, pitcs, pcs_entryp, nodep, hash_entry, - dpo_vft, hicn_dpo_id); - } - else - { - hicn_pcs_pit_delete (pitcs, pcs_entryp, nodep, vm, - hash_entry, dpo_vft, hicn_dpo_id); - } -} - -/* - * Remove a lock in the entry and delete it if there are no pending lock and - * the entry is marked as to be deleted - */ -always_inline void -hicn_pcs_remove_lock (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, - hicn_hash_node_t ** node, vlib_main_t * vm, - hicn_hash_entry_t * hash_entry, - const hicn_dpo_vft_t * dpo_vft, dpo_id_t * hicn_dpo_id) -{ - hash_entry->locks--; - if (hash_entry->locks == 0 - && (hash_entry->he_flags & HICN_HASH_ENTRY_FLAG_DELETED)) - { - hicn_pcs_delete_internal - (pitcs, pcs_entryp, hash_entry, node, vm, dpo_vft, hicn_dpo_id); - } -} - -/* - * Delete entry which has already been bulk-removed from lru list - */ -always_inline void -hicn_cs_delete_trimmed (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp, - hicn_hash_entry_t * hash_entry, - hicn_hash_node_t ** node, vlib_main_t * vm) -{ - - - if (hash_entry->locks == 0) - { - const hicn_dpo_vft_t *dpo_vft = hicn_dpo_get_vft (hash_entry->vft_id); - dpo_id_t hicn_dpo_id = - { dpo_vft->hicn_dpo_get_type (), 0, 0, hash_entry->dpo_ctx_id }; - - hicn_pcs_delete_internal - (pitcs, pcs_entryp, hash_entry, node, vm, dpo_vft, &hicn_dpo_id); - } - else - { - hash_entry->he_flags |= HICN_HASH_ENTRY_FLAG_DELETED; - } -} - -/* - * wrappable counter math (assumed uint16_t): return sum of addends - */ -always_inline u16 -hicn_infra_seq16_sum (u16 addend1, u16 addend2) -{ - return (addend1 + addend2); -} - -/* - * for comparing wrapping numbers, return lt,eq,gt 0 for a lt,eq,gt b - */ -always_inline int -hicn_infra_seq16_cmp (u16 a, u16 b) -{ - return ((int16_t) (a - b)); -} - -/* - * below are wrappers for lt, le, gt, ge seq16 comparators - */ -always_inline int -hicn_infra_seq16_lt (u16 a, u16 b) -{ - return (hicn_infra_seq16_cmp (a, b) < 0); -} - -always_inline int -hicn_infra_seq16_le (u16 a, u16 b) -{ - return (hicn_infra_seq16_cmp (a, b) <= 0); -} - -always_inline int -hicn_infra_seq16_gt (u16 a, u16 b) -{ - return (hicn_infra_seq16_cmp (a, b) > 0); -} - -always_inline int -hicn_infra_seq16_ge (u16 a, u16 b) -{ - return (hicn_infra_seq16_cmp (a, b) >= 0); -} - - -extern u16 hicn_infra_fast_timer; /* Counts at 1 second intervals */ -extern u16 hicn_infra_slow_timer; /* Counts at 1 minute intervals */ - -/* - * Utilities to convert lifetime into expiry time based on compressed clock, - * suitable for the opportunistic hashtable entry timeout processing. - */ - -//convert time in msec to time in clicks -always_inline u16 -hicn_infra_ms2clicks (u64 time_ms, u64 ms_per_click) -{ - f64 time_clicks = - ((f64) (time_ms + ms_per_click - 1)) / ((f64) ms_per_click); - return ((u16) time_clicks); -} - -always_inline u16 -hicn_infra_get_fast_exp_time (u64 lifetime_ms) -{ - u16 lifetime_clicks = - hicn_infra_ms2clicks (lifetime_ms, HICN_INFRA_FAST_TIMER_MSECS); - return (hicn_infra_seq16_sum (hicn_infra_fast_timer, lifetime_clicks)); -} - -always_inline u16 -hicn_infra_get_slow_exp_time (u64 lifetime_ms) -{ - u16 lifetime_clicks = - hicn_infra_ms2clicks (lifetime_ms, HICN_INFRA_SLOW_TIMER_MSECS); - return (hicn_infra_seq16_sum (hicn_infra_slow_timer, lifetime_clicks)); -} - -#endif /* // __HICN_PCS_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/pg.c b/hicn-plugin/src/pg.c deleted file mode 100644 index eb833030d..000000000 --- a/hicn-plugin/src/pg.c +++ /dev/null @@ -1,1326 +0,0 @@ -/* - * Copyright (c) 2017-2019 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; - -hicnpg_main_t hicnpg_main = { - .index = (u32) 0, - .index_ifaces = (u32) 1, - .max_seq_number = (u32) ~ 0, - .interest_lifetime = 4, - .n_flows = (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); - -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; - 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; - - 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); -} - -/* *INDENT-OFF* */ -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" - }, -}; -/* *INDENT-ON* */ - -/* - * 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); -} - - -static_always_inline int -match_ip4_name (u32 * name, fib_prefix_t * prefix) -{ - u32 xor = 0; - - xor = *name & prefix->fp_addr.ip4.data_u32; - - return xor == prefix->fp_addr.ip4.data_u32; -} - -static_always_inline int -match_ip6_name (u8 * name, fib_prefix_t * prefix) -{ - union - { - u32x4 as_u32x4; - u64 as_u64[2]; - u32 as_u32[4]; - } xor_sum __attribute__ ((aligned (sizeof (u32x4)))); - - 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]; - - 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; - - if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr))) - { - if (!match_ip4_name ((u32 *) & (ptr[12]), prefix)) - next = 1; - } - else - if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr))) - { - if (!match_ip6_name (&(ptr[8]), prefix)) - next = 2; - } - - 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 (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 (!match_ip6_name (&(ptr[24]), prefix)) - next = 2; - } - - return next; -} - - - - -/* - * 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; - 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); - - 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); -} - -/* *INDENT-OFF* */ -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", - }, -}; -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -VNET_FEATURE_INIT(hicn_data_input_ip4_arc, static)= - { - .arc_name = "ip4-unicast", - .node_name = "hicnpg-data", - .runs_before = VNET_FEATURES("ip4-inacl"), - }; -/* *INDENT-ON* */ - - -/* *INDENT-OFF* */ -VNET_FEATURE_INIT(hicn_data_input_ip6_arc, static)= - { - .arc_name = "ip6-unicast", - .node_name = "hicnpg-data", - .runs_before = VNET_FEATURES("ip6-inacl"), - }; -/* *INDENT-ON* */ - - -/* - * 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) -{ - 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; - - 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) - { - 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); - } - - 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); -} - -/* *INDENT-OFF* */ -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", - }, -}; -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -VNET_FEATURE_INIT(hicn_pg_server_ip6, static)= - { - .arc_name = "ip6-unicast", - .node_name = "hicnpg-server", - .runs_before = VNET_FEATURES("ip6-inacl"), - }; -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -VNET_FEATURE_INIT(hicn_pg_server_ip4, static)= - { - .arc_name = "ip4-unicast", - .node_name = "hicnpg-server", - .runs_before = VNET_FEATURES("ip4-inacl"), - }; -/* *INDENT-ON* */ - -/* - * End of packet-generator server node - */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/pg.h b/hicn-plugin/src/pg.h deleted file mode 100644 index 84a391d43..000000000 --- a/hicn-plugin/src/pg.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_PG_H__ -#define __HICN_PG_H__ - - -/** - * @file pg.h - * - * The packet generator is made of two entities, a client and a server. - * The client issues interests at high speed and the server satisfy each - * interest it receives with the corresponding data. - * The packet generator is made of three nodes: - * - hicnpg-interest that receives packets from a packet generator interface - * and manipulate them to generate interests based on the given configuration. - * This node runs at the client side. - * - hicnpg-data that receives data packets at the client side and counts them. - * This is useful for statistics. The "show err" command will give the number - * of interest issued and data received at the client side - * - hicnpg-server that recevies and interest and replies with the corresponding - * data. The data is generated from the interest switching the src and destination - * address in the packet and appending a payload to the packet. - * - * - * These three nodes are inserted in the vlib graph in the following manner: - * - hicnpg-interest is added as a possible next node of the pg-input node. The packet - * generator stream then specifies it as next node. - * - hicnpg-data is added as next hop of the ip4/6-unicast node exploiting the corresponding - * feature and it runs before the ip4/6-inacl node. In this way, every packet that is - * received through an interface on which this feature is enabled is sent to this node. - * - hicnpg-server is added as next hop of the ip4/6-unicast using the corresponding - * feature and it runs before the ip4/6-inacl node. In this way, every packet that is - * received through an interface on which this feature is enabled is sent to this node. - * - * An example of how to use the pg for hicn is available in the documentation. - */ - -/** - * @brief hICN packet generator main for the pg client nodes - * - * It stores the configuration and make it availables to the pg client nodes. - */ -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 -} hicnpg_main_t; - -extern hicnpg_main_t hicnpg_main; - -/** - * @brief hICN packet generator main for the pg server node - * - * It stores the configuration and make it availables to the pg server node. - */ -typedef struct hicnpg_server_main_s -{ - u32 node_index; - /* Arbitrary content */ - u32 pgen_svr_buffer_idx; - fib_prefix_t *pgen_srv_hicn_name; -} hicnpg_server_main_t; - -extern hicnpg_server_main_t hicnpg_server_main; - -extern vlib_node_registration_t hicn_pg_interest_node; -extern vlib_node_registration_t hicn_pg_data_node; - -#endif // __HICN_PG_H__ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/route.c b/hicn-plugin/src/route.c deleted file mode 100644 index 3b774cd82..000000000 --- a/hicn-plugin/src/route.c +++ /dev/null @@ -1,766 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 -#include -#include -#include -#include -#include - -#include "strategy_dpo_ctx.h" -#include "strategy_dpo_manager.h" -#include "strategy.h" -#include "faces/face.h" -#include "error.h" -#include "strategies/dpo_mw.h" -#include "infra.h" -#include "udp_tunnels/udp_tunnel.h" - -#define FIB_SOURCE_HICN 0x04 //Right after the FIB_SOURCE_INTERFACE priority - -fib_source_t hicn_fib_src; - -fib_node_type_t hicn_fib_node_type; - -ip4_address_t localhost4 = {0}; -ip6_address_t localhost6 = {0}; - -int -hicn_route_get_dpo (const fib_prefix_t * prefix, - const dpo_id_t ** hicn_dpo, u32 * fib_index) -{ - //fib_prefix_t fib_pfx; - const dpo_id_t *load_balance_dpo_id; - const dpo_id_t *former_dpo_id; - int found = 0, ret = HICN_ERROR_ROUTE_NOT_FOUND; - fib_node_index_t fib_entry_index; - - /* Check if the route already exist in the fib */ - /* - * ASSUMPTION: we use table 0 which is the default table and it is - * already existing and locked - */ - *fib_index = fib_table_find_or_create_and_lock (prefix->fp_proto, - HICN_FIB_TABLE, - hicn_fib_src); - fib_entry_index = fib_table_lookup_exact_match (*fib_index, prefix); - - if (fib_entry_index != FIB_NODE_INDEX_INVALID) - { - /* Route already existing. We need to update the dpo. */ - load_balance_dpo_id = - fib_entry_contribute_ip_forwarding (fib_entry_index); - - /* The dpo is not a load balance dpo as expected */ - if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) - ret = HICN_ERROR_ROUTE_NO_LD; - else - { - /* former_dpo_id is a load_balance dpo */ - load_balance_t *lb = - load_balance_get (load_balance_dpo_id->dpoi_index); - - /* FIB entry exists but there is no hicn dpo. */ - ret = HICN_ERROR_ROUTE_DPO_NO_HICN; - for (int i = 0; i < lb->lb_n_buckets && !found; i++) - { - former_dpo_id = load_balance_get_bucket_i (lb, i); - - if (dpo_is_hicn (former_dpo_id)) - { - *hicn_dpo = former_dpo_id; - ret = HICN_ERROR_NONE; - found = 1; - } - } - } - } - /* - * Remove the lock from the table. We keep one lock per route, not - * per dpo - */ - fib_table_unlock (*fib_index, prefix->fp_proto, hicn_fib_src); - - return ret; -} - -int -hicn_route_set_strategy (fib_prefix_t * prefix, u8 strategy_id) -{ - const dpo_id_t *hicn_dpo_id; - dpo_id_t new_dpo_id = DPO_INVALID; - int ret; - hicn_dpo_ctx_t *old_hicn_dpo_ctx; - const hicn_dpo_vft_t *new_dpo_vft; - index_t new_hicn_dpo_idx; - u32 fib_index; - - ret = hicn_route_get_dpo (prefix, &hicn_dpo_id, &fib_index); - - if (ret == HICN_ERROR_NONE) - { - old_hicn_dpo_ctx = hicn_strategy_dpo_ctx_get (hicn_dpo_id->dpoi_index); - - new_dpo_vft = hicn_dpo_get_vft_from_id (strategy_id); - - if (new_dpo_vft == NULL || old_hicn_dpo_ctx == NULL) - return HICN_ERROR_STRATEGY_NOT_FOUND; - - /* Create a new dpo for the new strategy */ - new_dpo_vft->hicn_dpo_create (hicn_dpo_id->dpoi_proto, - old_hicn_dpo_ctx->next_hops, - old_hicn_dpo_ctx->entry_count, - &new_hicn_dpo_idx); - - /* the value we got when we registered */ - dpo_set (&new_dpo_id, - new_dpo_vft->hicn_dpo_get_type (), - (ip46_address_is_ip4 (&prefix->fp_addr) ? DPO_PROTO_IP4 : - DPO_PROTO_IP6), new_hicn_dpo_idx); - - /* Here is where we create the "via" like route */ - /* - * For the moment we use the global one the prefix you want - * to match Neale suggested -- FIB_SOURCE_HICN the client - * that is adding them -- no easy explanation at this time… - */ - fib_node_index_t new_fib_node_index = - fib_table_entry_special_dpo_update (fib_index, - prefix, - hicn_fib_src, - FIB_ENTRY_FLAG_EXCLUSIVE, - &new_dpo_id); - - dpo_unlock (&new_dpo_id); - ret = - (new_fib_node_index != - FIB_NODE_INDEX_INVALID) ? HICN_ERROR_NONE : - HICN_ERROR_ROUTE_NOT_UPDATED; - } - //Remember to remove the lock from the table when removing the entry - return ret; - -} - -int -ip_nh_add_helper (fib_protocol_t fib_proto, const fib_prefix_t * rpfx, ip46_address_t * nh, u32 sw_if) -{ - fib_route_path_t *rpaths = NULL, rpath; - - u32 fib_index = fib_table_find(fib_proto, 0); - - clib_memset(&rpath, 0, sizeof(rpath)); - rpath.frp_weight = 1; - rpath.frp_sw_if_index = sw_if; - rpath.frp_addr = *nh; - rpath.frp_proto = ip46_address_is_ip4(nh) ? DPO_PROTO_IP4 : DPO_PROTO_IP6; - - vec_add1(rpaths, rpath); - - fib_table_entry_path_add2 (fib_index, - rpfx, - FIB_SOURCE_CLI, - FIB_ENTRY_FLAG_NONE, rpaths); - return 0; -} - -int -ip_nh_del_helper (fib_protocol_t fib_proto, const fib_prefix_t * rpfx, ip46_address_t * nh, u32 sw_if) -{ - fib_route_path_t *rpaths = NULL, rpath; - - u32 fib_index = fib_table_find(fib_proto, 0); - - clib_memset(&rpath, 0, sizeof(rpath)); - rpath.frp_weight = 1; - rpath.frp_sw_if_index = sw_if; - rpath.frp_addr = *nh; - rpath.frp_proto = ip46_address_is_ip4(nh) ? DPO_PROTO_IP4 : DPO_PROTO_IP6; - - vec_add1(rpaths, rpath); - - fib_table_entry_path_remove2 (fib_index, - rpfx, - FIB_SOURCE_CLI, - rpaths); - return 0; -} - - -static ip46_address_t * get_address(ip46_address_t * nh, u32 sw_if, fib_protocol_t proto) -{ - ip46_address_t * local_address = calloc(1, sizeof(ip46_address_t)); - - if (proto == FIB_PROTOCOL_IP4) - { - ip_interface_address_t *interface_address; - ip4_address_t *addr = - ip4_interface_address_matching_destination (&ip4_main, - &nh->ip4, - sw_if, - &interface_address); - - if (addr == NULL) - addr = ip4_interface_first_address (&ip4_main, - sw_if, - &interface_address); - if (addr != NULL) - ip46_address_set_ip4 (local_address, addr); - } - else if (proto == FIB_PROTOCOL_IP6) - { - ip_interface_address_t *interface_address; - ip6_interface_address_matching_destination (&ip6_main, - &nh->ip6, - sw_if, - &interface_address); - - ip6_address_t *addr = NULL; - if (interface_address != NULL) - addr = - (ip6_address_t *) - ip_interface_address_get_address (&ip6_main.lookup_main, - interface_address); - - if (addr == NULL) - addr = ip6_interface_first_address (&ip6_main, sw_if); - - if (addr != NULL) - ip46_address_set_ip6 (local_address, addr); - } - - return local_address; -} - -static void -sync_hicn_fib_entry(hicn_dpo_ctx_t *fib_entry) -{ - const dpo_id_t * dpo_loadbalance = fib_entry_contribute_ip_forwarding (fib_entry->fib_entry_index); - const load_balance_t *lb0 = load_balance_get(dpo_loadbalance->dpoi_index); - index_t hicn_fib_entry_index = hicn_strategy_dpo_ctx_get_index(fib_entry); - hicn_face_id_t * vec_faces = 0; - - dpo_id_t temp = DPO_INVALID; - const dpo_id_t *former_dpo = &temp; - int index = 0; - for (int j = 0; j < lb0->lb_n_buckets; j++) { - const dpo_id_t * dpo = load_balance_get_bucket_i(lb0,j); - - int dpo_comparison = dpo_cmp(former_dpo, dpo); - former_dpo = dpo; - /* - * Loadbalancing in ip replicate the dpo in multiple buckets - * in order to honor the assigned weights. - */ - if (dpo_comparison == 0) - continue; - - u32 sw_if = ~0; - ip46_address_t * nh = NULL; - hicn_face_id_t face_id = HICN_FACE_NULL; - - if (dpo_is_adj(dpo)) - { - ip_adjacency_t * adj = adj_get (dpo->dpoi_index); - sw_if = adj->rewrite_header.sw_if_index; - nh = get_address (&(adj->sub_type.nbr.next_hop), sw_if, fib_entry->proto); - } - else if (dpo->dpoi_type == dpo_type_udp_ip4 || dpo->dpoi_type == dpo_type_udp_ip6) - { - u8 proto = dpo->dpoi_type == dpo_type_udp_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; - nh = calloc (1, sizeof(ip46_address_t)); - switch (dpo->dpoi_proto) - { - case FIB_PROTOCOL_IP6: - nh = calloc (1, sizeof(ip46_address_t)); - ip46_address_set_ip6(nh, &localhost6); - break; - case FIB_PROTOCOL_IP4: - nh = calloc (1, sizeof(ip46_address_t)); - ip46_address_set_ip4(nh, &localhost4); - break; - default: - nh = calloc (1, sizeof(ip46_address_t)); - } - udp_tunnel_add_existing (dpo->dpoi_index, proto); - } - else //if (dpo_is_drop(dpo)) - { - sw_if = dpo_get_urpf(dpo); - nh = calloc (1, sizeof(ip46_address_t)); - } - - /* Careful, this adds a lock on the face if it exists */ - hicn_face_add(dpo, nh, sw_if, &face_id, 0); - - vec_validate(vec_faces, index); - vec_faces[index] = face_id; - index++; - - /* Face creation can realloc load_balance_t? Seem the fib_tracking does so. */ - dpo_loadbalance = fib_entry_contribute_ip_forwarding (fib_entry->fib_entry_index); - lb0 = load_balance_get(dpo_loadbalance->dpoi_index); - } - - const hicn_dpo_vft_t * strategy_vft = hicn_dpo_get_vft(fib_entry->dpo_type); - int i = 0; - while (i < fib_entry->entry_count) - { - u32 idx_nh = vec_search(vec_faces, fib_entry->next_hops[i]); - if (idx_nh == ~0) - { - strategy_vft->hicn_dpo_del_nh(fib_entry->next_hops[i], hicn_fib_entry_index); - } - else - { - vec_del1(vec_faces, idx_nh); - - /* Remove the lock added by hicn_face_add */ - hicn_face_unlock_with_id (fib_entry->next_hops[i]); - i++; - } - } - - hicn_face_id_t *face_id; - vec_foreach(face_id, vec_faces) - { - strategy_vft->hicn_dpo_add_update_nh(*face_id, hicn_fib_entry_index); - - /* Remove the lock added by hicn_face_add */ - hicn_face_unlock_with_id (*face_id); - - } - vec_free(vec_faces); -} - -static void -enable_disable_data_receiving (fib_protocol_t proto, u32 sw_if, u8 is_enable) -{ - if (proto == FIB_PROTOCOL_IP4 && sw_if != ~0) - vnet_feature_enable_disable ("ip4-local", "hicn-data-input-ip4", - sw_if, is_enable, 0, 0); - else if (proto == FIB_PROTOCOL_IP6 && sw_if != ~0) - vnet_feature_enable_disable ("ip6-local", "hicn-data-input-ip6", - sw_if, is_enable, 0, 0); - -} - -walk_rc_t enable_data_receiving_new_fib_entry (vnet_main_t * vnm, - vnet_sw_interface_t * si, - void *ctx) -{ - fib_protocol_t *proto = (fib_protocol_t *) ctx; - enable_disable_data_receiving(*proto, si->sw_if_index, 1); - - return (WALK_CONTINUE); -} - -walk_rc_t disable_data_receiving_rm_fib_entry (vnet_main_t * vnm, - vnet_sw_interface_t * si, - void *ctx) -{ - fib_protocol_t *proto = (fib_protocol_t *) ctx; - enable_disable_data_receiving(*proto, si->sw_if_index, 0); - - return (WALK_CONTINUE); - } - -int -hicn_route_enable (fib_prefix_t *prefix) { - - int ret = HICN_ERROR_NONE; - fib_node_index_t fib_entry_index; - - /* Check if the route already exist in the fib */ - /* - * ASSUMPTION: we use table 0 which is the default table and it is - * already existing and locked - */ - u32 fib_index = fib_table_find(prefix->fp_proto, 0); - - fib_entry_index = fib_table_lookup_exact_match (fib_index, prefix); - - if (fib_entry_index == FIB_NODE_INDEX_INVALID) - { - fib_entry_index = fib_table_lookup (fib_index, prefix); - - fib_route_path_t * paths = fib_entry_encode(fib_entry_index); - - fib_table_entry_path_add2(fib_index, prefix, FIB_SOURCE_CLI, FIB_ENTRY_FLAG_NONE, paths); - } - - /* Check if the prefix is already enabled */ - u32 fib_hicn_index = fib_table_find(prefix->fp_proto, HICN_FIB_TABLE); - - fib_node_index_t fib_hicn_entry_index = fib_table_lookup_exact_match (fib_hicn_index, prefix); - - if (fib_hicn_entry_index == FIB_NODE_INDEX_INVALID) - { - dpo_id_t dpo = DPO_INVALID; - index_t dpo_idx; - default_dpo.hicn_dpo_create (prefix->fp_proto, 0, NEXT_HOP_INVALID, - &dpo_idx); - - /* the value we got when we registered */ - /* - * This should be taken from the name?!? the index of the - * object - */ - dpo_set (&dpo, - default_dpo.hicn_dpo_get_type (), - (ip46_address_is_ip4 (&prefix->fp_addr) ? DPO_PROTO_IP4 : - DPO_PROTO_IP6), dpo_idx); - - hicn_dpo_ctx_t * fib_entry = hicn_strategy_dpo_ctx_get(dpo_idx); - - fib_node_init (&fib_entry->fib_node, hicn_fib_node_type); - fib_node_lock (&fib_entry->fib_node); - - fib_entry->fib_entry_index = fib_entry_track (fib_index, - prefix, - hicn_fib_node_type, - dpo_idx, &fib_entry->fib_sibling); - - - /* Here is where we create the "via" like route */ - /* - * For the moment we use the global one the prefix you want - * to match Neale suggested -- FIB_SOURCE_HICN the client - * that is adding them -- no easy explanation at this time… - */ - CLIB_UNUSED (fib_node_index_t new_fib_node_index) = - fib_table_entry_special_dpo_add (fib_hicn_index, - prefix, - hicn_fib_src, - (FIB_ENTRY_FLAG_EXCLUSIVE | - FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT), - &dpo); - - sync_hicn_fib_entry(fib_entry); - - /* We added a route, therefore add one lock to the table */ - fib_table_lock (fib_index, prefix->fp_proto, hicn_fib_src); - - /* Enable the feature to punt data packet every time we enable a new hicn route - * For each enable there must be a disable to defenitely disable the feature - * - * We cannot enable only the interfaces on which we send out interest because - * Data packet might be coming on in different interfaces, as in che case of mpls - * tunnels (packets are received from the physical nic, not the mpls tunnel interface). - */ - vnet_main_t * vnm = vnet_get_main (); - vnet_sw_interface_walk(vnm, enable_data_receiving_new_fib_entry, &(prefix->fp_proto)); - - dpo_unlock (&dpo); - } - else - { - const dpo_id_t *load_balance_dpo_id; - const dpo_id_t *strategy_dpo_id; - - /* Route already existing. We need to update the dpo. */ - load_balance_dpo_id = - fib_entry_contribute_ip_forwarding (fib_hicn_entry_index); - - /* The dpo is not a load balance dpo as expected */ - if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) - { - ret = HICN_ERROR_ROUTE_NO_LD; - goto done; - } - else - { - load_balance_t *lb = - load_balance_get (load_balance_dpo_id->dpoi_index); - - strategy_dpo_id = load_balance_get_bucket_i (lb, 0); - - if (!dpo_is_hicn (strategy_dpo_id)) - { - ret = HICN_ERROR_ROUTE_DPO_NO_HICN; - goto done; - } - - if (lb->lb_n_buckets > 1) - { - ret = HICN_ERROR_ROUTE_MLT_LD; - goto done; - } - - hicn_dpo_ctx_t * hicn_fib_entry = hicn_strategy_dpo_ctx_get(strategy_dpo_id->dpoi_index); - - sync_hicn_fib_entry(hicn_fib_entry); - } - } - - done: - return ret; -} - -int -hicn_route_disable (fib_prefix_t *prefix) { - - int ret = HICN_ERROR_NONE; - - /* Check if the prefix is already enabled */ - u32 fib_hicn_index = fib_table_find(prefix->fp_proto, HICN_FIB_TABLE); - - fib_node_index_t fib_hicn_entry_index = fib_table_lookup_exact_match (fib_hicn_index, prefix); - - if (fib_hicn_entry_index == FIB_NODE_INDEX_INVALID) - { - return HICN_ERROR_ROUTE_NOT_FOUND; - } - else - { - const dpo_id_t *load_balance_dpo_id; - const dpo_id_t *strategy_dpo_id; - hicn_dpo_ctx_t * hicn_fib_entry; - - /* Route already existing. We need to update the dpo. */ - load_balance_dpo_id = - fib_entry_contribute_ip_forwarding (fib_hicn_entry_index); - - /* The dpo is not a load balance dpo as expected */ - if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) - { - ret = HICN_ERROR_ROUTE_NO_LD; - goto done; - } - else - { - load_balance_t *lb = - load_balance_get (load_balance_dpo_id->dpoi_index); - - strategy_dpo_id = load_balance_get_bucket_i (lb, 0); - - if (!dpo_is_hicn (strategy_dpo_id)) - { - ret = HICN_ERROR_ROUTE_DPO_NO_HICN; - goto done; - } - - if (lb->lb_n_buckets > 1) - { - ret = HICN_ERROR_ROUTE_MLT_LD; - goto done; - } - - hicn_fib_entry = hicn_strategy_dpo_ctx_get(strategy_dpo_id->dpoi_index); - - for (int i = 0; i < hicn_fib_entry->entry_count; i++) - { - hicn_strategy_dpo_ctx_del_nh(hicn_fib_entry->next_hops[i], hicn_fib_entry); - } - } - - fib_entry_untrack(hicn_fib_entry->fib_entry_index, hicn_fib_entry->fib_sibling); - - fib_table_entry_special_remove (fib_hicn_index, prefix, hicn_fib_src); - - /* Disable the feature to punt data packet every time we enable a new hicn route */ - vnet_main_t * vnm = vnet_get_main (); - vnet_sw_interface_walk(vnm, disable_data_receiving_rm_fib_entry, &(prefix->fp_proto)); - } - - done: - return ret; -} - - -static fib_node_t * -hicn_ctx_node_get (fib_node_index_t index) -{ - hicn_dpo_ctx_t * hicn_ctx; - - hicn_ctx = hicn_strategy_dpo_ctx_get(index); - - return (&hicn_ctx->fib_node); -} - -static void -hicn_fib_last_lock_gone (fib_node_t *node) -{ -} - -static hicn_dpo_ctx_t * -hicn_ctx_from_fib_node (fib_node_t * node) -{ - return ((hicn_dpo_ctx_t *) (((char *) node) - - STRUCT_OFFSET_OF (hicn_dpo_ctx_t, fib_node))); -} - -static fib_node_back_walk_rc_t -hicn_fib_back_walk_notify (fib_node_t *node, - fib_node_back_walk_ctx_t *ctx) -{ - - hicn_dpo_ctx_t *fib_entry = hicn_ctx_from_fib_node (node); - - sync_hicn_fib_entry(fib_entry); - - return (FIB_NODE_BACK_WALK_CONTINUE); -} - -static void -hicn_fib_show_memory (void) -{ -} - - -static const fib_node_vft_t hicn_fib_vft = -{ - .fnv_get = hicn_ctx_node_get, - .fnv_last_lock = hicn_fib_last_lock_gone, - .fnv_back_walk = hicn_fib_back_walk_notify, - .fnv_mem_show = hicn_fib_show_memory, -}; - -fib_table_walk_rc_t enable_data_on_existing_hicn(fib_node_index_t fei, - void *ctx) -{ - u32 sw_if = *(u32 *)ctx; - const dpo_id_t *load_balance_dpo_id; - const dpo_id_t *strategy_dpo_id; - - /* Route already existing. We need to update the dpo. */ - load_balance_dpo_id = - fib_entry_contribute_ip_forwarding (fei); - - /* The dpo is not a load balance dpo as expected */ - if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) - { - goto done; - } - else - { - load_balance_t *lb = - load_balance_get (load_balance_dpo_id->dpoi_index); - - strategy_dpo_id = load_balance_get_bucket_i (lb, 0); - - if (!dpo_is_hicn (strategy_dpo_id)) - { - goto done; - } - - enable_disable_data_receiving (strategy_dpo_id->dpoi_proto, sw_if, 1); - } - - done: - return (FIB_TABLE_WALK_CONTINUE); -} - -static clib_error_t * -set_table_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add) -{ - - if (!is_add) - return HICN_ERROR_NONE; - - vnet_sw_interface_t * sw_int = vnet_get_sw_interface(vnm, sw_if_index); - vnet_hw_interface_t * hw_int = vnet_get_hw_interface(vnm, sw_int->hw_if_index); - - char * mpls = "mpls"; - if (strstr((char *)hw_int->name, mpls) == NULL) - return 0; - - int rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, HICN_FIB_TABLE, 1); - - if (!rv) - { - rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, HICN_FIB_TABLE, 1); - - if (rv) - { - /* An error occurred. Bind the interface back to the default fib */ - ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, 0, 1); - } - } - - u32 fib_index = fib_table_find(FIB_PROTOCOL_IP4, - HICN_FIB_TABLE); - if (fib_index != ~0) - { - /* - * Walk the ip4 and ip6 fib tables to discover existing hicn fib entries. - * For each of them we need to enable the feature to punt data packets. - */ - fib_table_walk(fib_index, - FIB_PROTOCOL_IP4, - enable_data_on_existing_hicn, - &sw_if_index); - } - - fib_index = fib_table_find(FIB_PROTOCOL_IP6, - HICN_FIB_TABLE); - if (fib_index != ~0) - { - fib_table_walk(fib_index, - FIB_PROTOCOL_IP6, - enable_data_on_existing_hicn, - &sw_if_index); - } - - return rv ? clib_error_return (0, "unable to add hicn table to interface") : 0; -} - -VNET_SW_INTERFACE_ADD_DEL_FUNCTION (set_table_interface_add_del); - -void -hicn_route_init () -{ - vnet_main_t * vnm = vnet_get_main (); - vlib_main_t * vm = vlib_get_main (); - hicn_fib_src = fib_source_allocate ("hicn", - FIB_SOURCE_HICN, FIB_SOURCE_BH_API); - - hicn_fib_node_type = fib_node_register_new_type(&hicn_fib_vft); - - ip_table_create(FIB_PROTOCOL_IP4, HICN_FIB_TABLE, 1, (const u8 *)"hicn4"); - ip_table_create(FIB_PROTOCOL_IP6, HICN_FIB_TABLE, 1, (const u8 *)"hicn6"); - - u32 sw_if_index; - u8 mac_address[6]; - u8 is_specified = 0; - u32 user_instance = 0; - - vnet_create_loopback_interface (&sw_if_index, mac_address, - is_specified, user_instance); - - localhost4.as_u8[0] = 127; - localhost4.as_u8[3] = 1; - u32 length4 = 32, length6 = 128, is_del = 0, flags = 0; - - localhost6.as_u8[15] = 1; - - ip4_add_del_interface_address (vm, sw_if_index, &localhost4, length4, is_del); - ip6_add_del_interface_address (vm, sw_if_index, &localhost6, length6, is_del); - - flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP; - vnet_sw_interface_set_flags (vnm, sw_if_index, flags); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/route.h b/hicn-plugin/src/route.h deleted file mode 100644 index a1ba86b3d..000000000 --- a/hicn-plugin/src/route.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_ROUTE__ -#define __HICN_ROUTE__ - -#include -#include -#include "hicn.h" -#include "faces/face.h" - -/** - * @file route.h - * - * hICN uses a specific vrf to install the routes for a prefix has been enabled to - * be hicn. It considers the vrf 0 (the default vrf) as the dominating vrf on - * which every route is stored. Enabling a prefix to be hICN will copy all the routes - * in the vrf 0 for the given prefi, in the vrf HICN. Every modification made on the - * vrf 0 on an hICN enabled prefix is reflected in the vrf hICN (through the use of - * the fib entry tracking functionality). Moreover, we use the lookup in the vrf hICN - * as a way for punting packet that must be processed as hICN. The implementation will - * install a special dpo as a single next hop for the vpp load balancer for each entry - * in the vrf hICN that we enabled. Such dpo will have two purposes: 1) to punt packets - * to the hICN forwarding pipeline, 2) to point to the righe strategy (the dpoi_index will - * be an index to the strategy context while the dpoi_type will be an index to the strategy vft). - * - * Additionally, hICN assign each interface to the vrf hICN; this is required for - * the interest lookup. Vpp performs a lookup in the vrf assigned to the interface, - * therefore if an interface is not assigned to the hICN vrf, the lookup will be done - * on the vrf 0 and the packet won't be processed through the hicn forwarding pipeline. - */ - -/* - * Adding each interface to the vrf hICN has the side effect that to ping you need to - * specify the vrf hICN in the command. - */ - -extern fib_source_t hicn_fib_src; - -extern dpo_type_t udp_encap_dpo_types[FIB_PROTOCOL_MAX]; - -/** - * @Brief Return the hicn_dpo corresponding to the prefix in teh vrf HICN - * - * @param prefix Prefix for which we want to retrieve the hICN dpo - * @param hicn_dpo return value with the hicn_dpo - * @param fib_index return value with the fib index corresponding to the prefix - */ -int -hicn_route_get_dpo (const fib_prefix_t * prefix, - const dpo_id_t ** hicn_dpo, u32 * fib_index); - - -/** - * @Brief Set the strategy for a given prefix - * - * @param prefix Prefix for which we set the strategy - * @param stretegy_id Index of the strategy to set - */ -int -hicn_route_set_strategy (fib_prefix_t * prefix, u32 strategy_id); - -/** - * @Brief Helper to add a nex hop in the vrf 0. If there are no entries in the - * vrf 0 that matches with the prefix (epm), a new one is created. - * - * @param fib_proto FIB_PROTOCOL_IP6 or FIB_PROTOCOL_IP4 (mpls not supported) - * @param pfx Prefix for which to add a next hop - * @param nh Next hop to add - * @param sw_if Software interface index to add in the next hop - */ -int -ip_nh_add_helper (fib_protocol_t fib_proto, const fib_prefix_t * pfx, ip46_address_t * nh, u32 sw_if); - -/** - * @Brief Helper to remove a nex hop in the vrf 0. If there are no entries in the - * vrf 0 nothing happens. - * - * @param fib_proto FIB_PROTOCOL_IP6 or FIB_PROTOCOL_IP4 (mpls not supported) - * @param pfx Prefix for which to remove a next hop - * @param nh Next hop to remove - * @param sw_if Software interface index in the next hop definition - */ -int -ip_nh_del_helper (fib_protocol_t fib_proto, const fib_prefix_t * rpfx, ip46_address_t * nh, u32 sw_if); - -/** - * @Brief Enable an hICN for an ip prefix - * - * @param prefix Prefix for which we enable hICN - * @return HICN_ERROR_NONE if hICN was enabled on the prefix - * HICN_ERROR_ROUTE_NO_LD if the first dpo for the fib entry corresponding to the prefix is not a load_balancer - * HICN_ERROR_ROUTE_DPO_NO_HICN if the loadbalancer in the vrf HICN already contains a dpo which is not an hICN one - * HICN_ERROR_ROUTE_MLT_LD if there are more than a dpo in the vpp loadbalancer - */ -int -hicn_route_enable (fib_prefix_t *prefix); - -/** - * @Brief Disable an hICN for an ip prefix. If hICN wasn't enable on the prefix - * nothing happens and it returns HICN_ERROR_ROUTE_NOT_FOUND - * - * @param prefix Prefix for which we disable hICN - */ -int -hicn_route_disable (fib_prefix_t *prefix); - - -/* Init route internal strustures */ -void -hicn_route_init(); -#endif /* //__HICN_ROUTE__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/state.h b/hicn-plugin/src/state.h deleted file mode 100644 index 37003d0ae..000000000 --- a/hicn-plugin/src/state.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_STATE__ -#define __HICN_STATE__ - -#include -#include - -#include "hicn.h" -#include "pcs.h" -#include "hashtb.h" -#include "strategy.h" -#include "strategy_dpo_ctx.h" -#include "strategy_dpo_manager.h" - -/** - * @file plugin_state - * - * Helper functions to hicn state (hash node, hash entry, strategy vft, dpo vft and dpo context id) - * - */ - -//TODO exploit this state to prefetch hash nodes and entries. - -/** - * @brief Retrieve the hicn state - * - * @param hicnb hicn buffer used to retrieve the hicn state - * @param pitcs pointer to PIT/CS - * @param node node in the hash table referring to the buffer - * @param strategy_vft return value pointing to the strategy vft corresponding to the buffer - * @param dpo_vft return value pointing to the dpo vft corresponding to the buffer - * @param dpo_ctx_id return value pointing to the dpo context id corresponding to the buffer - * @param hash_entry entry in the hash table referring to the buffer - */ -always_inline void -hicn_get_internal_state (hicn_buffer_t * hicnb, hicn_pit_cs_t * pitcs, - hicn_hash_node_t ** node, - const hicn_strategy_vft_t ** strategy_vft, - const hicn_dpo_vft_t ** dpo_vft, u8 * dpo_ctx_id, - hicn_hash_entry_t ** hash_entry) -{ - *node = pool_elt_at_index (pitcs->pcs_table->ht_nodes, hicnb->node_id); - *strategy_vft = hicn_dpo_get_strategy_vft (hicnb->vft_id); - *dpo_vft = hicn_dpo_get_vft (hicnb->vft_id); - *dpo_ctx_id = hicnb->dpo_ctx_id; - - hicn_hash_bucket_t *bucket; - if (hicnb->hash_bucket_flags & HICN_HASH_NODE_OVERFLOW_BUCKET) - bucket = - pool_elt_at_index (pitcs->pcs_table->ht_overflow_buckets, - hicnb->bucket_id); - else - bucket = - (hicn_hash_bucket_t *) (pitcs->pcs_table->ht_buckets + - hicnb->bucket_id); - - *hash_entry = &(bucket->hb_entries[hicnb->hash_entry_id]); -} - -/* - * This function set the PCS entry index, the dpo index and the vft index in - * the opaque2 buffer. In this way, the interest-hitpit and interest-hitcs - * nodes can prefetch the corresponding state (PIT entry, dpo_ctx and the - * strategy vft - */ -/** - * @brief Store the hicn state in the hicn buffer - * - * @param b vlib buffer holding the hICN packet - * @param name_hash hash of the hICN name - * @param node_id id of the node in the hash table referring to the buffer - * @param dpo_ctx_id id of the dpo context id corresponding to the buffer - * @param vft_id id of the strategy vft corresponding to the buffer - * @param hash_entry_id id of the entry in the hash table referring to the buffer - * @param bucket_id id of the hasth table bucket that holds the hash entry - * @param bucket_is_overflow 1 if the bucket is from the ht_overflow_buckets pool - * 0 if the bucket is from the ht_buckets pool - */ -always_inline void -hicn_store_internal_state (vlib_buffer_t * b, u64 name_hash, u32 node_id, - u8 dpo_ctx_id, u8 vft_id, u8 hash_entry_id, - u32 bucket_id, u8 bucket_is_overflow) -{ - hicn_buffer_t *hicnb = hicn_get_buffer (b); - hicnb->name_hash = name_hash; - hicnb->node_id = node_id; - hicnb->dpo_ctx_id = dpo_ctx_id; - hicnb->vft_id = vft_id; - hicnb->hash_entry_id = hash_entry_id; - hicnb->bucket_id = bucket_id; - hicnb->hash_bucket_flags = - HICN_HASH_NODE_OVERFLOW_BUCKET * bucket_is_overflow; -} - -#endif /* // __HICN_STATE__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/strategies/dpo_mw.c b/hicn-plugin/src/strategies/dpo_mw.c deleted file mode 100644 index 12c77bce8..000000000 --- a/hicn-plugin/src/strategies/dpo_mw.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "dpo_mw.h" -#include "strategy_mw.h" -#include "../strategy_dpo_manager.h" -#include "../strategy_dpo_ctx.h" - -/** - * @brief DPO type value for the mw_strategy - */ -static dpo_type_t hicn_dpo_type_mw; - -static const hicn_dpo_vft_t hicn_dpo_mw_vft = { - .hicn_dpo_is_type = &hicn_dpo_is_type_strategy_mw, - .hicn_dpo_get_type = &hicn_dpo_strategy_mw_get_type, - .hicn_dpo_module_init = &hicn_dpo_strategy_mw_module_init, - .hicn_dpo_create = &hicn_strategy_mw_ctx_create, - .hicn_dpo_add_update_nh = &hicn_strategy_mw_ctx_add_nh, - .hicn_dpo_del_nh = &hicn_strategy_mw_ctx_del_nh, - .hicn_dpo_format = &hicn_strategy_mw_format_ctx -}; - -int -hicn_dpo_is_type_strategy_mw (const dpo_id_t * dpo) -{ - return dpo->dpoi_type == hicn_dpo_type_mw; -} - -void -hicn_dpo_strategy_mw_module_init (void) -{ - /* - * Register our type of dpo - */ - hicn_dpo_type_mw = - hicn_dpo_register_new_type (hicn_nodes_strategy, &hicn_dpo_mw_vft, - hicn_mw_strategy_get_vft (), - &dpo_strategy_mw_ctx_vft); -} - -dpo_type_t -hicn_dpo_strategy_mw_get_type (void) -{ - return hicn_dpo_type_mw; -} - -////////////////////////////////////////////////////////////////////////////////////////////////// - - -u8 * -hicn_strategy_mw_format_ctx (u8 * s, int n, ...) -{ - va_list args; - va_start (args, n); - s = format_hicn_strategy_mw_ctx (s, &args); - return s; -} - -u8 * -format_hicn_strategy_mw_ctx (u8 * s, va_list * ap) -{ - int i = 0; - index_t index = va_arg (*ap, index_t); - hicn_dpo_ctx_t *dpo_ctx = NULL; - hicn_strategy_mw_ctx_t *mw_dpo_ctx = NULL; - u32 indent = va_arg (*ap, u32);; - - dpo_ctx = hicn_strategy_dpo_ctx_get (index); - if (dpo_ctx == NULL) - return s; - - mw_dpo_ctx = (hicn_strategy_mw_ctx_t *) dpo_ctx->data; - - s = format (s, "hicn-mw"); - for (i = 0; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; i++) - { - u8 *buf = NULL; - if (i < dpo_ctx->entry_count) - buf = format (NULL, "FIB"); - else if (i >= - HICN_PARAM_FIB_ENTRY_NHOPS_MAX - dpo_ctx->tfib_entry_count) - buf = format (NULL, "TFIB"); - else - continue; - - s = format (s, "\n"); - s = - format (s, "%U ", format_hicn_face, dpo_ctx->next_hops[i], - indent); - s = format (s, "weight %u", mw_dpo_ctx->weight[i]); - s = format (s, " %s", buf); - } - - return (s); -} - -void -hicn_strategy_mw_ctx_create (fib_protocol_t proto, const hicn_face_id_t * next_hop, - int nh_len, index_t * dpo_idx) -{ - hicn_strategy_mw_ctx_t *hicn_strategy_mw_ctx; - hicn_dpo_ctx_t *hicn_strategy_ctx; - - /* Allocate a hicn_dpo_ctx on the vpp pool and initialize it */ - hicn_strategy_ctx = hicn_strategy_dpo_ctx_alloc (); - hicn_strategy_mw_ctx = (hicn_strategy_mw_ctx_t *) hicn_strategy_ctx->data; - - *dpo_idx = hicn_strategy_dpo_ctx_get_index (hicn_strategy_ctx); - - init_dpo_ctx (hicn_strategy_ctx, next_hop, nh_len, hicn_dpo_type_mw, proto); - - memset (hicn_strategy_mw_ctx->weight, 0, HICN_PARAM_FIB_ENTRY_NHOPS_MAX); -} - -int -hicn_strategy_mw_ctx_add_nh (hicn_face_id_t nh, index_t dpo_idx) -{ - hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx); - u8 pos = 0; - - if (hicn_strategy_dpo_ctx == NULL) - { - return HICN_ERROR_STRATEGY_NOT_FOUND; - } - - hicn_strategy_dpo_ctx_add_nh (nh, hicn_strategy_dpo_ctx, &pos); - hicn_strategy_mw_ctx_t *hicn_strategy_mw_ctx = - (hicn_strategy_mw_ctx_t *) & hicn_strategy_dpo_ctx->data; - - hicn_strategy_mw_ctx->weight[pos] = DEFAULT_WEIGHT; - return HICN_ERROR_NONE; -} - -int -hicn_strategy_mw_ctx_del_nh (hicn_face_id_t face_id, index_t dpo_idx) -{ - hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx); - //No need to flush the weights, they are initialized when a dpo_ctx is created; - return hicn_strategy_dpo_ctx_del_nh (face_id, hicn_strategy_dpo_ctx); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/strategies/dpo_mw.h b/hicn-plugin/src/strategies/dpo_mw.h deleted file mode 100644 index 433c415fb..000000000 --- a/hicn-plugin/src/strategies/dpo_mw.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_DPO_MW_H__ -#define __HICN_DPO_MW_H__ - -#include -#include "../strategy_dpo_ctx.h" - -/** - * @file dpo_mw.h - * - * This file implements the strategy vtf (see strategy.h) and - * the dpo vft (see strategy_dpo_manager.h) for the strategy - * maximum weight - */ - -#define DEFAULT_WEIGHT 0 - -typedef struct hicn_strategy_mw_ctx_s -{ - u8 weight[HICN_PARAM_FIB_ENTRY_NHOPS_MAX]; -} hicn_strategy_mw_ctx_t; - -/** - * @brief Format the dpo ctx for a human-readable string - * - * @param s String to which to append the formatted dpo ctx - * @param ap List of parameters for the formatting - * - * @result The string with the formatted dpo ctx - */ -u8 *format_hicn_strategy_mw_ctx (u8 * s, va_list * ap); - -const static dpo_vft_t dpo_strategy_mw_ctx_vft = { - .dv_lock = hicn_strategy_dpo_ctx_lock, - .dv_unlock = hicn_strategy_dpo_ctx_unlock, - .dv_format = format_hicn_strategy_mw_ctx, -}; - -/** - * @brief Retrieve an hicn_strategy_mw_ctx object - * - * @param indext Index of the hicn_dpo_ctx to retrieve - * @return The hicn_dpo_ctx object or NULL - */ -hicn_dpo_ctx_t *hicn_strategy_mw_ctx_get (index_t index); - -/** - * @brief Create a new mw ctx - * - * @param proto The protocol to which the dpo is meant for (see vpp docs) - * @param next_hop A list of next hops to be inserted in the dpo ctx - * @param nh_len Size of the list - * @param dpo_idx index_t that will hold the index of the created dpo ctx - * @return HICN_ERROR_NONE if the creation was fine, otherwise EINVAL - */ -void -hicn_strategy_mw_ctx_create (fib_protocol_t proto, const hicn_face_id_t * next_hop, - int nh_len, index_t * dpo_idx); - -/** - * @brief Add or update a next hop in the dpo ctx. - * - * This function is meant to be used in the control plane and not in the data plane, - * as it is not optimized for the latter. - * - * @param nh Next hop to insert in the dpo ctx - * @param dpo_idx Index of the dpo ctx to update with the new or updated next - * hop - * @return HICN_ERROR_NONE if the update or insert was fine, - * otherwise HICN_ERROR_DPO_CTX_NOT_FOUND - */ -int hicn_strategy_mw_ctx_add_nh (hicn_face_id_t nh, index_t dpo_idx); - -/** - * @brief Delete a next hop in the dpo ctx. - * - * @param face_id Face identifier of the next hop - * @param dpo_idx Index of the dpo ctx to update with the new or updated next - * hop - * @return HICN_ERROR_NONE if the update or insert was fine, - * otherwise HICN_ERROR_DPO_CTS_NOT_FOUND - */ -int hicn_strategy_mw_ctx_del_nh (hicn_face_id_t face_id, index_t dpo_idx); - -/** - * @brief Prefetch a dpo - * - * @param dpo_idx Index of the dpo ctx to prefetch - */ -void hicn_strategy_mw_ctx_prefetch (index_t dpo_idx); - -/** - * @brief Return true if the dpo is of type strategy mw - * - * @param dpo Dpo to check the type - */ -int hicn_dpo_is_type_strategy_mw (const dpo_id_t * dpo); - -/** - * @brief Initialize the Maximum Weight strategy - */ -void hicn_dpo_strategy_mw_module_init (void); - -/** - * @brief Return the dpo type for the Maximum Weight strategy - */ -dpo_type_t hicn_dpo_strategy_mw_get_type (void); - -/** - * @brief Format the dpo ctx for the strategy Maximum Weight - * - * @param s String to append the formatted dpo ctx - * @param ap List of arguments to format - */ -u8 *format_hicn_dpo_strategy_mw (u8 * s, va_list * ap); - -/** - * @brief Format the dpo ctx for the strategy Maximum Weight. To - * call from other functions - * - * @param s String to append the formatted dpo ctx - * @param ... List of arguments to format - */ -u8 *hicn_strategy_mw_format_ctx (u8 * s, int n, ...); - - -#endif // __HICN_DPO_MW_H__ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/strategies/dpo_rr.c b/hicn-plugin/src/strategies/dpo_rr.c deleted file mode 100644 index adb7e1025..000000000 --- a/hicn-plugin/src/strategies/dpo_rr.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "dpo_rr.h" -#include "strategy_rr.h" -#include "../strategy_dpo_manager.h" -#include "../strategy_dpo_ctx.h" - -/** - * @brief DPO type value for the rr_strategy - */ -static dpo_type_t hicn_dpo_type_rr; - -static const hicn_dpo_vft_t hicn_dpo_rr_vft = { - .hicn_dpo_is_type = &hicn_dpo_is_type_strategy_rr, - .hicn_dpo_get_type = &hicn_dpo_strategy_rr_get_type, - .hicn_dpo_module_init = &hicn_dpo_strategy_rr_module_init, - .hicn_dpo_create = &hicn_strategy_rr_ctx_create, - .hicn_dpo_add_update_nh = &hicn_strategy_rr_ctx_add_nh, - .hicn_dpo_del_nh = &hicn_strategy_rr_ctx_del_nh, - .hicn_dpo_format = &hicn_strategy_rr_format_ctx -}; - -int -hicn_dpo_is_type_strategy_rr (const dpo_id_t * dpo) -{ - return dpo->dpoi_type == hicn_dpo_type_rr; -} - -void -hicn_dpo_strategy_rr_module_init (void) -{ - /* - * Register our type of dpo - */ - hicn_dpo_type_rr = - hicn_dpo_register_new_type (hicn_nodes_strategy, &hicn_dpo_rr_vft, - hicn_rr_strategy_get_vft (), - &dpo_strategy_rr_ctx_vft); -} - -dpo_type_t -hicn_dpo_strategy_rr_get_type (void) -{ - return hicn_dpo_type_rr; -} - -////////////////////////////////////////////////////////////////////////////////////////////////// - - -u8 * -hicn_strategy_rr_format_ctx (u8 * s, int n, ...) -{ - va_list args; - va_start (args, n); - s = format_hicn_strategy_rr_ctx (s, &args); - return s; -} - -u8 * -format_hicn_strategy_rr_ctx (u8 * s, va_list * ap) -{ - int i = 0; - index_t index = va_arg (*ap, index_t); - hicn_dpo_ctx_t *dpo_ctx = NULL; - hicn_strategy_rr_ctx_t *rr_dpo_ctx = NULL; - u32 indent = va_arg (*ap, u32); - - dpo_ctx = hicn_strategy_dpo_ctx_get (index); - if (dpo_ctx == NULL) - return s; - - rr_dpo_ctx = (hicn_strategy_rr_ctx_t *) dpo_ctx->data; - - s = - format (s, "hicn-rr, next hop Face %d", - dpo_ctx->next_hops[rr_dpo_ctx->current_nhop]); - - for (i = 0; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; i++) - { - u8 *buf = NULL; - if (i < dpo_ctx->entry_count) - buf = format (NULL, "FIB"); - else if (i >= - HICN_PARAM_FIB_ENTRY_NHOPS_MAX - dpo_ctx->tfib_entry_count) - buf = format (NULL, "TFIB"); - else - continue; - - s = format (s, "\n"); - s = - format (s, "%U ", format_hicn_face, dpo_ctx->next_hops[i], - indent); - s = format (s, " %s", buf); - } - - return (s); -} - -void -hicn_strategy_rr_ctx_create (fib_protocol_t proto, const hicn_face_id_t * next_hop, - int nh_len, index_t * dpo_idx) -{ - hicn_strategy_rr_ctx_t *hicn_strategy_rr_ctx; - hicn_dpo_ctx_t *hicn_strategy_ctx; - - /* Allocate a hicn_dpo_ctx on the vpp pool and initialize it */ - hicn_strategy_ctx = hicn_strategy_dpo_ctx_alloc (); - hicn_strategy_rr_ctx = (hicn_strategy_rr_ctx_t *) hicn_strategy_ctx->data; - - *dpo_idx = hicn_strategy_dpo_ctx_get_index (hicn_strategy_ctx); - - init_dpo_ctx (hicn_strategy_ctx, next_hop, nh_len, hicn_dpo_type_rr, proto); - - hicn_strategy_rr_ctx->current_nhop = 0; -} - -int -hicn_strategy_rr_ctx_add_nh (hicn_face_id_t nh, index_t dpo_idx) -{ - hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx); - u8 pos = 0; - - if (hicn_strategy_dpo_ctx == NULL) - { - return HICN_ERROR_STRATEGY_NOT_FOUND; - } - - hicn_strategy_dpo_ctx_add_nh (nh, hicn_strategy_dpo_ctx, &pos); - //nothing else to initialize in this strategy - return HICN_ERROR_NONE; -} - -int -hicn_strategy_rr_ctx_del_nh (hicn_face_id_t face_id, index_t dpo_idx) -{ - hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx); - //No need to change the current_nhop. It will be updated at the next selection. - return hicn_strategy_dpo_ctx_del_nh (face_id, hicn_strategy_dpo_ctx); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/strategies/dpo_rr.h b/hicn-plugin/src/strategies/dpo_rr.h deleted file mode 100644 index e4e5b5372..000000000 --- a/hicn-plugin/src/strategies/dpo_rr.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_DPO_RR_H__ -#define __HICN_DPO_RR_H__ - -#include -#include "../strategy_dpo_ctx.h" - -/** - * @file dpo_rr.h - * - * This file implements the strategy vtf (see strategy.h) and - * the dpo vft (see strategy_dpo_manager.h) for the strategy - * round robin. - */ - - -/** - * Context for the Round Robin strategy - */ - -typedef struct hicn_strategy_rr_ctx_s -{ - u8 current_nhop; -} hicn_strategy_rr_ctx_t; - -/** - * @brief Format the dpo ctx for a human-readable string - * - * @param s String to which to append the formatted dpo ctx - * @param ap List of parameters for the formatting - * - * @result The string with the formatted dpo ctx - */ -u8 *format_hicn_strategy_rr_ctx (u8 * s, va_list * ap); - -const static dpo_vft_t dpo_strategy_rr_ctx_vft = { - .dv_lock = hicn_strategy_dpo_ctx_lock, - .dv_unlock = hicn_strategy_dpo_ctx_unlock, - .dv_format = format_hicn_strategy_rr_ctx, -}; - -/** - * @brief Retrieve an hicn_strategy_rr_ctx object - * - * @param indext Index of the hicn_dpo_ctx to retrieve - * @return The hicn_dpo_ctx object or NULL - */ -hicn_dpo_ctx_t *hicn_strategy_rr_ctx_get (index_t index); - -/** - * @brief Create a new round robin ctx - * - * @param proto The protocol to which the dpo is meant for (see vpp docs) - * @param next_hop A list of next hops to be inserted in the dpo ctx - * @param nh_len Size of the list - * @param dpo_idx index_t that will hold the index of the created dpo ctx - * @return HICN_ERROR_NONE if the creation was fine, otherwise EINVAL - */ -void -hicn_strategy_rr_ctx_create (fib_protocol_t proto, const hicn_face_id_t * next_hop, - int nh_len, index_t * dpo_idx); - -/** - * @brief Add or update a next hop in the dpo ctx. - * - * This function is meant to be used in the control plane and not in the data plane, - * as it is not optimized for the latter. - * - * @param nh Next hop to insert in the dpo ctx - * @param dpo_idx Index of the dpo ctx to update with the new or updated next - * hop - * @return HICN_ERROR_NONE if the update or insert was fine, - * otherwise HICN_ERROR_DPO_CTX_NOT_FOUND - */ -int hicn_strategy_rr_ctx_add_nh (hicn_face_id_t nh, index_t dpo_idx); - -/** - * @brief Delete a next hop in the dpo ctx. - * - * @param face_id Face identifier of the next hop - * @param dpo_idx Index of the dpo ctx to update with the new or updated next - * hop - * @return HICN_ERROR_NONE if the update or insert was fine, - * otherwise HICN_ERROR_DPO_CTS_NOT_FOUND - */ -int hicn_strategy_rr_ctx_del_nh (hicn_face_id_t face_id, index_t dpo_idx); - -/** - * @brief Prefetch a dpo - * - * @param dpo_idx Index of the dpo ctx to prefetch - */ -void hicn_strategy_rr_ctx_prefetch (index_t dpo_idx); - -/** - * @brief Return true if the dpo is of type strategy rr - * - * @param dpo Dpo to check the type - */ -int hicn_dpo_is_type_strategy_rr (const dpo_id_t * dpo); - -/** - * @brief Initialize the Round Robin strategy - */ -void hicn_dpo_strategy_rr_module_init (void); - -/** - * @brief Return the dpo type for the Round Robin strategy - */ -dpo_type_t hicn_dpo_strategy_rr_get_type (void); - -/** - * @brief Format the dpo ctx for the strategy Round Robin - * - * @param s String to append the formatted dpo ctx - * @param ap List of arguments to format - */ -u8 *format_hicn_dpo_strategy_rr (u8 * s, va_list * ap); - -/** - * @brief Format the dpo ctx for the strategy Round Robin. To - * call from other functions - * - * @param s String to append the formatted dpo ctx - * @param ... List of arguments to format - */ -u8 *hicn_strategy_rr_format_ctx (u8 * s, int n, ...); - - -#endif // __HICN_DPO_RR_H__ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/strategies/strategy_mw.c b/hicn-plugin/src/strategies/strategy_mw.c deleted file mode 100644 index fe4d5896a..000000000 --- a/hicn-plugin/src/strategies/strategy_mw.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "dpo_mw.h" -#include "../strategy.h" -#include "../strategy_dpo_ctx.h" -#include "../faces/face.h" -#include "../hashtb.h" -#include "../strategy_dpo_manager.h" - -/* Simple strategy that chooses the next hop with the maximum weight */ -/* It does not require to exend the hicn_dpo */ -void hicn_receive_data_mw (index_t dpo_idx, int nh_idx); -void hicn_add_interest_mw (index_t dpo_idx, hicn_hash_entry_t * pit_entry); -void hicn_on_interest_timeout_mw (index_t dpo_idx); -u32 hicn_select_next_hop_mw (index_t dpo_idx, int *nh_idx, - hicn_face_id_t* outface); -u32 get_strategy_node_index_mw (void); -u8 *hicn_strategy_format_trace_mw (u8 * s, hicn_strategy_trace_t * t); -u8 *hicn_strategy_format_mw (u8 * s, va_list * ap); - - -static hicn_strategy_vft_t hicn_strategy_mw_vft = { - .hicn_receive_data = &hicn_receive_data_mw, - .hicn_add_interest = &hicn_add_interest_mw, - .hicn_on_interest_timeout = &hicn_on_interest_timeout_mw, - .hicn_select_next_hop = &hicn_select_next_hop_mw, - .hicn_format_strategy_trace = hicn_strategy_format_trace_mw, - .hicn_format_strategy = &hicn_strategy_format_mw -}; - -/* - * Return the vft of the strategy. - */ -hicn_strategy_vft_t * -hicn_mw_strategy_get_vft (void) -{ - return &hicn_strategy_mw_vft; -} - -/* DPO should be give in input as it containes all the information to calculate the next hops*/ -u32 -hicn_select_next_hop_mw (index_t dpo_idx, int *nh_idx, hicn_face_id_t* outface) -{ - hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx); - - if (dpo_ctx == NULL) - return HICN_ERROR_STRATEGY_NOT_FOUND; - - hicn_strategy_mw_ctx_t *hicn_strategy_mw_ctx = - (hicn_strategy_mw_ctx_t *) dpo_ctx->data; - - u8 next_hop_index = 0; - for (int i = 0; i < dpo_ctx->entry_count; i++) - { - if (hicn_strategy_mw_ctx->weight[next_hop_index] < - hicn_strategy_mw_ctx->weight[i]) - { - next_hop_index = i; - } - } - - *outface = dpo_ctx->next_hops[next_hop_index]; - - return HICN_ERROR_NONE; -} - -void -hicn_add_interest_mw (index_t dpo_ctx_idx, hicn_hash_entry_t * hash_entry) -{ - hash_entry->dpo_ctx_id = dpo_ctx_idx; - dpo_id_t hicn_dpo_id = - { hicn_dpo_strategy_mw_get_type (), 0, 0, dpo_ctx_idx }; - hicn_strategy_dpo_ctx_lock (&hicn_dpo_id); - hash_entry->vft_id = hicn_dpo_get_vft_id (&hicn_dpo_id); -} - -void -hicn_on_interest_timeout_mw (index_t dpo_idx) -{ - /* Nothign to do in the mw strategy when we receive an interest */ -} - -void -hicn_receive_data_mw (index_t dpo_idx, int nh_idx) -{ -} - - -/* packet trace format function */ -u8 * -hicn_strategy_format_trace_mw (u8 * s, hicn_strategy_trace_t * t) -{ - s = format (s, "Strategy_mw: pkt: %d, sw_if_index %d, next index %d", - (int) t->pkt_type, t->sw_if_index, t->next_index); - return (s); -} - -u8 * -hicn_strategy_format_mw (u8 * s, va_list * ap) -{ - - u32 indent = va_arg (*ap, u32); - s = - format (s, - "Static Weights: weights are updated by the control plane, next hop is the one with the maximum weight.\n", - indent); - return (s); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/strategies/strategy_mw.h b/hicn-plugin/src/strategies/strategy_mw.h deleted file mode 100644 index 9e0078b23..000000000 --- a/hicn-plugin/src/strategies/strategy_mw.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_STRATEGY_MW_H__ -#define __HICN_STRATEGY_MW_H__ - -#include "../strategy.h" - -/** - * @file strategy_mw.h - * - * This file implements the maximum weight strategy. In this - * strategy the choosen next hop is one with the maximum weight. - */ - -/** - * @brief Return the vft for the Maximum Weight strategy - */ -hicn_strategy_vft_t *hicn_mw_strategy_get_vft (void); - -#endif // __HICN_STRATEGY_MW_H__ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/strategies/strategy_mw_cli.c b/hicn-plugin/src/strategies/strategy_mw_cli.c deleted file mode 100644 index 636d7effa..000000000 --- a/hicn-plugin/src/strategies/strategy_mw_cli.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "../strategy_dpo_manager.h" -#include "../faces/face.h" -#include "../error.h" -#include "../route.h" -#include "dpo_mw.h" - -static clib_error_t * -hicn_mw_strategy_cli_set_weight_command_fn (vlib_main_t * vm, - unformat_input_t * main_input, - vlib_cli_command_t * cmd) -{ - clib_error_t *cl_err = 0; - int ret = HICN_ERROR_NONE; - fib_prefix_t prefix; - hicn_face_id_t faceid = HICN_FACE_NULL; - u32 fib_index; - u32 weight = HICN_PARAM_FIB_ENTRY_NHOP_WGHT_DFLT; - hicn_dpo_ctx_t *hicn_dpo_ctx; - const dpo_id_t *hicn_dpo_id; - - /* Get a line of input. */ - unformat_input_t _line_input, *line_input = &_line_input; - if (unformat_user (main_input, unformat_line_input, line_input)) - { - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "prefix %U/%u", unformat_ip46_address, - &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len)) - ; - else if (unformat (line_input, "face %u", &faceid)) - ; - else if (unformat (line_input, "weight %u", &weight)) - ; - else - { - return clib_error_return (0, "%s", - get_error_string - (HICN_ERROR_CLI_INVAL)); - } - - } - } - - if (((weight < 0) || (weight > HICN_PARAM_FIB_ENTRY_NHOP_WGHT_MAX))) - { - cl_err = clib_error_return (0, - "Next-hop weight must be between 0 and %d", - (int) HICN_PARAM_FIB_ENTRY_NHOP_WGHT_MAX); - goto done; - } - - if (((ip46_address_is_zero (&prefix.fp_addr)) || faceid == HICN_FACE_NULL)) - { - cl_err = - clib_error_return (0, "Please specify prefix and a valid faceid..."); - goto done; - } - - prefix.fp_proto = - ip46_address_is_ip4 (&prefix. - fp_addr) ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6; - ret = hicn_route_get_dpo (&prefix, &hicn_dpo_id, &fib_index); - - if (ret == HICN_ERROR_NONE) - { - hicn_dpo_ctx = hicn_strategy_dpo_ctx_get (hicn_dpo_id->dpoi_index); - - if (hicn_dpo_ctx == NULL - || hicn_dpo_id->dpoi_type != hicn_dpo_strategy_mw_get_type ()) - { - cl_err = clib_error_return (0, get_error_string (ret)); - goto done; - } - - hicn_strategy_mw_ctx_t *mw_dpo = - (hicn_strategy_mw_ctx_t *) hicn_dpo_ctx; - int idx = ~0; - for (int i = 0; i < hicn_dpo_ctx->entry_count; i++) - if (hicn_dpo_ctx->next_hops[i] == faceid) - idx = i; - - if (idx == ~0) - { - cl_err = - clib_error_return (0, - get_error_string - (HICN_ERROR_STRATEGY_NH_NOT_FOUND)); - goto done; - } - - mw_dpo->weight[idx] = weight; - } - else - { - cl_err = clib_error_return (0, get_error_string (ret)); - - } - -done: - - return (cl_err); - -} - -/* cli declaration for 'strategy mw' */ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND(hicn_mw_strategy_cli_set_weight_command, static)= -{ - .path = "hicn strategy mw set", - .short_help = "hicn strategy mw set prefix face weight ", - .function = hicn_mw_strategy_cli_set_weight_command_fn, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/strategies/strategy_rr.c b/hicn-plugin/src/strategies/strategy_rr.c deleted file mode 100644 index 4c65ce52a..000000000 --- a/hicn-plugin/src/strategies/strategy_rr.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "dpo_rr.h" -#include "../strategy.h" -#include "../strategy_dpo_ctx.h" -#include "../faces/face.h" -#include "../hashtb.h" -#include "../strategy_dpo_manager.h" - -/* Simple strategy that chooses the next hop with the maximum weight */ -/* It does not require to exend the hicn_dpo */ -void hicn_receive_data_rr (index_t dpo_idx, int nh_idx); -void hicn_add_interest_rr (index_t dpo_idx, hicn_hash_entry_t * pit_entry); -void hicn_on_interest_timeout_rr (index_t dpo_idx); -u32 hicn_select_next_hop_rr (index_t dpo_idx, int *nh_idx, - hicn_face_id_t* outface); -u8 *hicn_strategy_format_trace_rr (u8 * s, hicn_strategy_trace_t * t); -u8 *hicn_strategy_format_rr (u8 * s, va_list * ap); - - -static hicn_strategy_vft_t hicn_strategy_rr_vft = { - .hicn_receive_data = &hicn_receive_data_rr, - .hicn_add_interest = &hicn_add_interest_rr, - .hicn_on_interest_timeout = &hicn_on_interest_timeout_rr, - .hicn_select_next_hop = &hicn_select_next_hop_rr, - .hicn_format_strategy_trace = &hicn_strategy_format_trace_rr, - .hicn_format_strategy = &hicn_strategy_format_rr -}; - -/* - * Return the vft of the strategy. - */ -hicn_strategy_vft_t * -hicn_rr_strategy_get_vft (void) -{ - return &hicn_strategy_rr_vft; -} - -/* DPO should be give in input as it containes all the information to calculate the next hops*/ -u32 -hicn_select_next_hop_rr (index_t dpo_idx, int *nh_idx, hicn_face_id_t* outface) -{ - hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo_idx); - - if (dpo_ctx == NULL) - return HICN_ERROR_STRATEGY_NOT_FOUND; - - hicn_strategy_rr_ctx_t *hicn_strategy_rr_ctx = - (hicn_strategy_rr_ctx_t *) dpo_ctx->data; - - *outface = - dpo_ctx->next_hops[hicn_strategy_rr_ctx->current_nhop]; - - hicn_strategy_rr_ctx->current_nhop = - (hicn_strategy_rr_ctx->current_nhop + 1) % dpo_ctx->entry_count; - - return HICN_ERROR_NONE; -} - -void -hicn_add_interest_rr (index_t dpo_ctx_idx, hicn_hash_entry_t * hash_entry) -{ - hash_entry->dpo_ctx_id = dpo_ctx_idx; - dpo_id_t hicn_dpo_id = - { hicn_dpo_strategy_rr_get_type (), 0, 0, dpo_ctx_idx }; - hicn_strategy_dpo_ctx_lock (&hicn_dpo_id); - hash_entry->vft_id = hicn_dpo_get_vft_id (&hicn_dpo_id); -} - -void -hicn_on_interest_timeout_rr (index_t dpo_idx) -{ - /* Nothing to do in the rr strategy when we receive an interest */ -} - -void -hicn_receive_data_rr (index_t dpo_idx, int nh_idx) -{ -} - - -/* packet trace format function */ -u8 * -hicn_strategy_format_trace_rr (u8 * s, hicn_strategy_trace_t * t) -{ - s = format (s, "Strategy_rr: pkt: %d, sw_if_index %d, next index %d", - (int) t->pkt_type, t->sw_if_index, t->next_index); - return (s); -} - -u8 * -hicn_strategy_format_rr (u8 * s, va_list * ap) -{ - - u32 indent = va_arg (*ap, u32); - s = - format (s, - "Round Robin: next hop is chosen ciclying between all the available next hops, one after the other.\n", - indent); - return (s); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/strategies/strategy_rr.h b/hicn-plugin/src/strategies/strategy_rr.h deleted file mode 100644 index 4dfe76b43..000000000 --- a/hicn-plugin/src/strategies/strategy_rr.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017-2019 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_STRATEGY_RR_H__ -#define __HICN_STRATEGY_RR_H__ - -#include "../strategy.h" - -/** - * @file strategy_rr.h - * - * This file implements the round robin strategy. In this - * strategy the next hop is choosen in a round robin way. - */ - -/** - * @brief Return the vft for the Round Robin strategy - */ -hicn_strategy_vft_t *hicn_rr_strategy_get_vft (void); - -#endif // __HICN_STRATEGY_RR_H__ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/strategy.h b/hicn-plugin/src/strategy.h deleted file mode 100644 index d949f38a4..000000000 --- a/hicn-plugin/src/strategy.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_STRATEGY__ -#define __HICN_STRATEGY__ - -#include "hicn.h" -#include "hashtb.h" -#include "mgmt.h" -#include "faces/face.h" - -/** - * @file strategy.h - * - * A strategy is defined as a dpo and a set of function (vft) that will be called - * during the packet processing. A strategy is associated to an entry in the fib by - * assigning the corresponding dpo to the fib entry. The dpo points to a hICN dpo - * context (ctx) which contains the information needed by the strategy to compute - * the next hop. Each strategy hash its own dpo type, which means that the dpo_type - * uniquely identifies a strategy and its vft. The strategy node will use the dpo_type - * to retrieve the corresponding vft. - * Here we provide: - * - a template for the callbacks to implement in order to create a new strategy - * (hicn_fwd_strategy_t) - * - a default implementation for the strategy node which will call the strategy - * functions while processing the interest packets - */ - -/* Trace context struct */ -typedef struct -{ - u32 next_index; - u32 sw_if_index; - u8 pkt_type; - dpo_type_t dpo_type; -} hicn_strategy_trace_t; - -typedef struct hicn_strategy_vft_s -{ - void (*hicn_receive_data) (index_t dpo_idx, int nh_idx); - void (*hicn_on_interest_timeout) (index_t dpo_idx); - void (*hicn_add_interest) (index_t dpo_idx, hicn_hash_entry_t * pit_entry); - u32 (*hicn_select_next_hop) (index_t dpo_idx, int *nh_idx, - hicn_face_id_t* outface); - u8 *(*hicn_format_strategy_trace) (u8 *, hicn_strategy_trace_t *); - u8 *(*hicn_format_strategy) (u8 * s, va_list * ap); - /**< Format an hICN dpo*/ -} hicn_strategy_vft_t; - -typedef enum -{ - HICN_STRATEGY_NEXT_INTEREST_HITPIT, - HICN_STRATEGY_NEXT_INTEREST_HITCS, - HICN_STRATEGY_NEXT_INTEREST_FACE4, - HICN_STRATEGY_NEXT_INTEREST_FACE6, - HICN_STRATEGY_NEXT_ERROR_DROP, - HICN_STRATEGY_N_NEXT, -} hicn_strategy_next_t; - -const static char *const hicn_ip6_nodes[] = -{ - "hicn6-iface-input", // this is the name you give your node in VLIB_REGISTER_NODE - NULL, -}; - -const static char *const hicn_ip4_nodes[] = -{ - "hicn4-iface-input", // this is the name you give your node in VLIB_REGISTER_NODE - NULL, -}; - -const static char *const *const hicn_nodes_strategy[DPO_PROTO_NUM] = -{ - [DPO_PROTO_IP6] = hicn_ip6_nodes, - [DPO_PROTO_IP4] = hicn_ip4_nodes, -}; - - -extern vlib_node_registration_t hicn_strategy_node; - -#endif /* //__HICN_STRATEGY__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/strategy_dpo_ctx.c b/hicn-plugin/src/strategy_dpo_ctx.c deleted file mode 100644 index 342c78bb5..000000000 --- a/hicn-plugin/src/strategy_dpo_ctx.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2020 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 "strategy_dpo_ctx.h" -#include "strategy_dpo_manager.h" - -hicn_dpo_ctx_t *hicn_strategy_dpo_ctx_pool; - -void -hicn_strategy_init_dpo_ctx_pool () -{ - pool_init_fixed (hicn_strategy_dpo_ctx_pool, 256); - -} - -void -hicn_strategy_dpo_ctx_lock (dpo_id_t * dpo) -{ - hicn_dpo_ctx_t *dpo_ctx = hicn_strategy_dpo_ctx_get (dpo->dpoi_index); - - if (dpo_ctx != NULL) - { - dpo_ctx->locks++; - } -} - -void -hicn_strategy_dpo_ctx_unlock (dpo_id_t * dpo) -{ - hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = - (hicn_dpo_ctx_t *) hicn_strategy_dpo_ctx_get (dpo->dpoi_index); - - if (hicn_strategy_dpo_ctx != NULL) - { - hicn_strategy_dpo_ctx->locks--; - - if (0 == hicn_strategy_dpo_ctx->locks) - { - pool_put (hicn_strategy_dpo_ctx_pool, hicn_strategy_dpo_ctx); - } - } -} - -u8 * -hicn_strategy_dpo_format_ctx (u8 * s, va_list * ap) -{ - index_t index = va_arg (*ap, index_t); - hicn_dpo_ctx_t *dpo = NULL; - u32 indent = va_arg (*ap, u32); - - dpo = (hicn_dpo_ctx_t *) hicn_strategy_dpo_ctx_get (index); - - const hicn_dpo_vft_t *dpo_vft = hicn_dpo_get_vft (dpo->dpo_type); - - s = dpo_vft->hicn_dpo_format (s, 2, index, indent); - - return (s); -} - -index_t -hicn_strategy_dpo_ctx_get_index (hicn_dpo_ctx_t * cd) -{ - return (cd - hicn_strategy_dpo_ctx_pool); -} - -hicn_dpo_ctx_t * -hicn_strategy_dpo_ctx_get (index_t index) -{ - hicn_dpo_ctx_t *hicn_strategy_dpo_ctx = NULL; - if (!pool_is_free_index (hicn_strategy_dpo_ctx_pool, index)) - { - hicn_strategy_dpo_ctx = - (pool_elt_at_index (hicn_strategy_dpo_ctx_pool, index)); - } - - return hicn_strategy_dpo_ctx; -} - -hicn_dpo_ctx_t * -hicn_strategy_dpo_ctx_alloc () -{ - hicn_dpo_ctx_t *dpo_ctx; - pool_get (hicn_strategy_dpo_ctx_pool, dpo_ctx); - return dpo_ctx; -} - -int -hicn_strategy_dpo_ctx_add_nh (hicn_face_id_t nh, hicn_dpo_ctx_t * dpo_ctx, - u8 * pos) -{ - - int empty = dpo_ctx->entry_count; - - /* Iterate through the list of faces to find if the face is already a next hop */ - for (int i = 0; i < dpo_ctx->entry_count; i++) - { - if (nh == dpo_ctx->next_hops[i]) - { - /* If face is marked as deleted, ignore it */ - hicn_face_t *face = - hicn_dpoi_get_from_idx (dpo_ctx->next_hops[i]); - if (face->flags & HICN_FACE_FLAGS_DELETED) - { - continue; - } - return HICN_ERROR_DPO_CTX_NHOPS_EXISTS; - } - } - - /* Get an empty place */ - if (empty > HICN_PARAM_FIB_ENTRY_NHOPS_MAX) - { - return HICN_ERROR_DPO_CTX_NHOPS_NS; - } - - dpo_ctx->next_hops[empty] = nh; - hicn_face_lock_with_id (nh); - dpo_ctx->entry_count++; - *pos = empty; - - return HICN_ERROR_NONE; -} - -int -hicn_strategy_dpo_ctx_del_nh (hicn_face_id_t face_id, - hicn_dpo_ctx_t * dpo_ctx) -{ - int ret = HICN_ERROR_DPO_CTX_NOT_FOUND; - hicn_face_id_t invalid = NEXT_HOP_INVALID; - - for (int i = 0; i < dpo_ctx->entry_count; i++) - { - if (dpo_ctx->next_hops[i] == face_id) - { - hicn_face_unlock_with_id (dpo_ctx->next_hops[i]); - dpo_ctx->entry_count--; - dpo_ctx->next_hops[i] = dpo_ctx->next_hops[dpo_ctx->entry_count]; - dpo_ctx->next_hops[dpo_ctx->entry_count] = invalid; - ret = HICN_ERROR_NONE; - break; - } - } - - return ret; - -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/strategy_dpo_ctx.h b/hicn-plugin/src/strategy_dpo_ctx.h deleted file mode 100644 index 214ed88ad..000000000 --- a/hicn-plugin/src/strategy_dpo_ctx.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_STRATEGY_DPO_CTX_H__ -#define __HICN_STRATEGY_DPO_CTX_H__ - -#include -#include - -#include "params.h" -#include "faces/face.h" - -/** - * @file strategy_dpo_ctx.h - * - * This file implements the general hICN DPO ctx (shared among all the strategies). - * - * An hICN DPO ctx contains the list of next hops, auxiliaries fields to maintain the dpo, map-me - * specifics (tfib_entry_count and seq), the dpo_type and 64B to let each strategy to store additional - * information. Each next hop is an hicn_face_id_t that refers to an index for an hICN face. The - * dpo_type is used to identify the strategy and to retrieve the vft corresponding to the strategy - * (see strategy.h) and to the dpo ctx (see strategy_dpo_manager.h) - */ - -//FIB table for hicn. 0 is the default one used by ip -#define HICN_FIB_TABLE 10 - -#define NEXT_HOP_INVALID ~0 - -#define INIT_SEQ 0 - -typedef struct __attribute__ ((packed)) hicn_dpo_ctx_s -{ - CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); - /* 4B*10 = 40B */ - hicn_face_id_t next_hops[HICN_PARAM_FIB_ENTRY_NHOPS_MAX]; - /* 40B + 4B = 44B */ - u32 locks; - /* 44B + 1B = 45B */ - u8 entry_count; - /* 45B + 1B = 46B */ - /* Number of TFIB entries (stored at the end of the next_hops array */ - u8 tfib_entry_count; - - dpo_type_t dpo_type; - - /* 46B + 2B = 48B */ - u8 padding; /* To align to 8B */ - - /* 48 + 4B = 52; last sequence number */ - u32 seq; - - /* 52 + 12 = 64 */ - fib_node_t fib_node; - - CLIB_CACHE_LINE_ALIGN_MARK (cacheline1); - - fib_node_index_t fib_entry_index; - - u32 fib_sibling; - - union - { - u32 padding_proto; - fib_protocol_t proto; - }; - - u8 data[CLIB_CACHE_LINE_BYTES - 12]; - -} hicn_dpo_ctx_t; - -extern hicn_dpo_ctx_t *hicn_strategy_dpo_ctx_pool; - -/** - * @brief Initialize the hICN dpo ctx - * - * @param dpo_ctx Pointer to the hICN dpo ctx to initialize - * @param next_hop List of netx hops to store in the dpo ctx - * @param nh_len Number of elements in the list of next hops - * @param dpo_type Type of dpo. It identifies the strategy. - */ -always_inline void -init_dpo_ctx (hicn_dpo_ctx_t * dpo_ctx, const hicn_face_id_t * next_hop, - int nh_len, dpo_type_t dpo_type, dpo_proto_t proto) -{ - hicn_face_id_t invalid = NEXT_HOP_INVALID; - - dpo_ctx->entry_count = 0; - dpo_ctx->locks = 0; - - dpo_ctx->tfib_entry_count = 0; - - dpo_ctx->seq = INIT_SEQ; - dpo_ctx->dpo_type = dpo_type; - - dpo_ctx->proto = proto; - - for (int i = 0; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX && i < nh_len; i++) - { - dpo_ctx->next_hops[i] = next_hop[i]; - dpo_ctx->entry_count++; - } - - - for (int i = nh_len; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; i++) - { - dpo_ctx->next_hops[i] = invalid; - } - -} - -/** - * @brief Initialize the pool containing the hICN dpo ctx - * - */ -void hicn_strategy_init_dpo_ctx_pool (void); - -/** - * @brief Allocate a new hICN dpo ctx from the pool - */ -hicn_dpo_ctx_t *hicn_strategy_dpo_ctx_alloc (); - -/** - * @brief Retrieve an existing hICN dpo ctx from the pool - */ -hicn_dpo_ctx_t *hicn_strategy_dpo_ctx_get (index_t index); - -/** - * @brief Retrieve the index of the hICN dpo ctx - */ -index_t hicn_strategy_dpo_ctx_get_index (hicn_dpo_ctx_t * cd); - -/** - * @brief Lock the dpo of a strategy ctx - * - * @param dpo Identifier of the dpo of the strategy ctx - */ -void hicn_strategy_dpo_ctx_lock (dpo_id_t * dpo); - -/** - * @brief Unlock the dpo of a strategy ctx - * - * @param dpo Identifier of the dpo of the strategy ctx - */ -void hicn_strategy_dpo_ctx_unlock (dpo_id_t * dpo); - -/** - * @brief Add or update a next hop in the dpo ctx. - * - * This function is meant to be used in the control plane and not in the data plane, - * as it is not optimized for the latter. - * - * @param nh Next hop to insert in the dpo ctx - * @param dpo_ctx Dpo ctx to update with the new or updated next hop - * @param pos Return the position of the nh that has been added - * @return HICN_ERROR_NONE if the update or insert was fine, - * otherwise HICN_ERROR_DPO_CTX_NOT_FOUND - */ -int -hicn_strategy_dpo_ctx_add_nh (hicn_face_id_t nh, hicn_dpo_ctx_t * dpo_ctx, - u8 * pos); - -/** - * @brief Delete a next hop in the dpo ctx. - * - * @param face_id Face identifier of the next hop - * @param dpo_ctx Dpo ctx to update by removing the face - * @return HICN_ERROR_NONE if the update or insert was fine, - * otherwise HICN_ERROR_DPO_CTS_NOT_FOUND - */ -int -hicn_strategy_dpo_ctx_del_nh (hicn_face_id_t face_id, - hicn_dpo_ctx_t * dpo_ctx); - - -STATIC_ASSERT (sizeof (hicn_dpo_ctx_t) <= 2 * CLIB_CACHE_LINE_BYTES, - "sizeof hicn_dpo_ctx_t is greater than 128B"); - -#endif /* // __HICN_STRATEGY_DPO_CTX_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/strategy_dpo_manager.c b/hicn-plugin/src/strategy_dpo_manager.c deleted file mode 100644 index f8d41a372..000000000 --- a/hicn-plugin/src/strategy_dpo_manager.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2017-2019 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 "strategy_dpo_manager.h" -#include "strategy_dpo_ctx.h" -#include "strategies/dpo_mw.h" -#include "strategies/dpo_rr.h" -#include "strategy.h" -#include "faces/face.h" - -static dpo_type_t *strategies_id; -static const hicn_dpo_vft_t **hicn_dpo_vfts; - -static const hicn_strategy_vft_t **hicn_strategy_vfts; - -int hicn_strategies = 0; - -hicn_dpo_vft_t default_dpo; - -dpo_type_t -hicn_dpo_register_new_type (const char *const *const *hicn_nodes, - const hicn_dpo_vft_t * hicn_dpo_vft, - const hicn_strategy_vft_t * hicn_strategy_vft, - const dpo_vft_t * dpo_ctx_vft) -{ - dpo_type_t dpo_type = dpo_register_new_type (dpo_ctx_vft, hicn_nodes); - vec_validate (hicn_dpo_vfts, dpo_type); - hicn_dpo_vfts[dpo_type] = hicn_dpo_vft; - - vec_validate (hicn_strategy_vfts, dpo_type); - hicn_strategy_vfts[dpo_type] = hicn_strategy_vft; - - vec_validate (strategies_id, hicn_strategies); - strategies_id[hicn_strategies] = dpo_type; - hicn_strategies++; - - return dpo_type; -} - -u32 -dpo_is_hicn (const dpo_id_t * dpo) -{ - for (int i = 0; i < hicn_strategies; i++) - { - if (hicn_dpo_vfts[strategies_id[i]]->hicn_dpo_is_type (dpo)) - return 1; - } - return 0; -} - -dpo_type_t -hicn_dpo_get_vft_id (const dpo_id_t * dpo) -{ - return dpo->dpoi_type; -} - -const hicn_dpo_vft_t * -hicn_dpo_get_vft (dpo_type_t vfts_id) -{ - return hicn_dpo_vfts[vfts_id]; -} - -const hicn_dpo_vft_t * -hicn_dpo_get_vft_from_id (u8 strategy_id) -{ - return hicn_dpo_vfts[strategies_id[strategy_id]]; -} - -const hicn_strategy_vft_t * -hicn_dpo_get_strategy_vft (dpo_type_t vfts_id) -{ - return hicn_strategy_vfts[vfts_id]; -} - -const hicn_strategy_vft_t * -hicn_dpo_get_strategy_vft_from_id (u8 vfts_id) -{ - return hicn_strategy_vfts[strategies_id[vfts_id]]; -} - -void -hicn_dpos_init (void) -{ - hicn_strategy_init_dpo_ctx_pool (); - hicn_dpo_strategy_mw_module_init (); - hicn_dpo_strategy_rr_module_init (); - - default_dpo.hicn_dpo_is_type = &hicn_dpo_is_type_strategy_mw; - default_dpo.hicn_dpo_get_type = &hicn_dpo_strategy_mw_get_type; - default_dpo.hicn_dpo_module_init = &hicn_dpo_strategy_mw_module_init; - default_dpo.hicn_dpo_create = &hicn_strategy_mw_ctx_create; - default_dpo.hicn_dpo_add_update_nh = &hicn_strategy_mw_ctx_add_nh; - default_dpo.hicn_dpo_del_nh = &hicn_strategy_mw_ctx_del_nh; - default_dpo.hicn_dpo_format = &hicn_strategy_mw_format_ctx; -} - -u8 * -format_hicn_strategy_list (u8 * s, int n, ...) -{ - va_list ap; - va_start (ap, n); - u32 indent = va_arg (ap, u32); - va_end (ap); - - s = format (s, "%U Strategies:\n", format_white_space, indent); - indent += 4; - int i; - vec_foreach_index (i, strategies_id) - { - s = format (s, "%U (%d) ", format_white_space, indent, i); - s = hicn_strategy_vfts[strategies_id[i]]->hicn_format_strategy (s, &ap); - } - - return (s); -} - -u8 -hicn_dpo_strategy_id_is_valid (int strategy_id) -{ - return vec_len (strategies_id) > strategy_id ? - HICN_ERROR_NONE : HICN_ERROR_DPO_MGR_ID_NOT_VALID; -} - -int -hicn_strategy_get_all_available (void) -{ - return hicn_strategies; -} - -/** - * @brief Registers a dpo by calling its module init function. - * - * This is typically called from the ctor for dpo's registered at compilation - * time. - */ -void -hicn_dpo_register (const hicn_dpo_vft_t * hicn_dpo) -{ - hicn_dpo->hicn_dpo_module_init (); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/strategy_dpo_manager.h b/hicn-plugin/src/strategy_dpo_manager.h deleted file mode 100644 index e96e050d9..000000000 --- a/hicn-plugin/src/strategy_dpo_manager.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2017-2020 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_STRATEGY_DPO_MANAGER_H__ -#define __HICN_STRATEGY_DPO_MANAGER_H__ - -#include "strategy_dpo_ctx.h" -#include "strategy.h" - -/** - * @file strategy_dpo_manager.h - * - * This file implements structs and helper functions to manipulate hICN dpo. - * An hICN DPO is a combination of: - * - a hICN DPO ctx (context) that holds the structure containing the - * information to choose the next hop, - * - a dpo vft that specify how to update the hICN DPO ctx when a next hop is - * added, deleted or updated, - * - a strategy containing (see strategy.h): (i) the vpp node that processes Interest packets - * subjected to such strategy, (ii) the definition of the vft that defines - * the hICN strategy functions - * An hICN DPO is places as the sole next hop in the vpp loadbalancer, and it containes - * a list of next hops that will be used by the associated strategy when forwarding - * interest packets. - */ - -/** - * @brief Definition of the virtual function table for a hICN DPO. - * - * The following virtual function table - * template that glues together the fuction to interact with the context and the - * creating the dpo - */ -typedef struct hicn_dpo_vft_s -{ - int (*hicn_dpo_is_type) (const dpo_id_t * dpo); - /**< Check if the type of the - hICN DPO is the expected */ - dpo_type_t (*hicn_dpo_get_type) (void); - /**< Return the type of the hICN dpo */ - void (*hicn_dpo_module_init) (void); /**< Initialize the hICN dpo */ - void (*hicn_dpo_create) (fib_protocol_t proto, const hicn_face_id_t * nh, int nh_len, index_t * dpo_idx); /**< Create the context of the hICN dpo */ - int (*hicn_dpo_add_update_nh) (hicn_face_id_t nh, index_t dpo_idx); /**< Add a next hop to the hICN dpo context */ - int (*hicn_dpo_del_nh) (hicn_face_id_t face_id, index_t dpo_idx); - u8 *(*hicn_dpo_format) (u8 * s, int, ...); - /**< Format an hICN dpo*/ -} hicn_dpo_vft_t; - -/* - * Default dpo to be used to create fib entry when a strategy is not - * specified - */ -extern hicn_dpo_vft_t default_dpo; - -/** - * @brief Register a new hICN dpo to the manager. - * - * Registering a hICN DPO allows the plugin to be aware of the new dpo an be - * able to apply it to the FIB entries. - * - * @param hicn_nodes A list of vpp to which pass an interest that matches with - * the FIB entry to which the hICN DPO is applied. This list must contain the - * name of the strategy node (or nodes in case of differentiation between IPv4 - * and IPv6). Unless really needed otherwise (i.e., different implementation of - * iface input), the list of node to use should be one provided in the strategy.h - * (hicn_nodes_strategy) - * @param hicn_dpo_vft The structure holding the virtual function table to - * interact with the hICN dpo and its context. - * @param hicn_strategy_vft The structure holding the virtual function table - * containing the hICN strategy functions. - * @return the dpo type registered in the VPP Data plane graph. - */ -dpo_type_t -hicn_dpo_register_new_type (const char *const *const *hicn_nodes, - const hicn_dpo_vft_t * hicn_dpo_vft, - const hicn_strategy_vft_t * - hicn_strategy_vft, const dpo_vft_t * dpo_ctx_vft); - -/** - * @brief Check if the type of the dpo is among the list of hicn dpo types - * - * Iterate through the list of dpo types registered in the hicn dpo manager. - * - * @param dpo The id of the dpo to which check the type - * @return 1 if there is a match, 0 otherwise. - */ -u32 dpo_is_hicn (const dpo_id_t * dpo); - -/** - * @brief Return the dpo_vtf and strategy_vtf identifier - * - * Iterate through the list of dpo types registered in the hicn dpo manager and - * retrieve the corresponding dpo_vtf/strategy_vtf identifier. - * - * @param dpo The id of the dpo to which check the type - * @return the dpo_vft/strategy_vft id or HICN_ERROR_DPO_NOT_FOUND in case the dpo is not an hICN dpo. - */ -u8 hicn_dpo_get_vft_id (const dpo_id_t * dpo); - -/** - * @brief Get the vft to manage the dpo context. - * - * @param The id of the hicn_dpo_vft to retrieve. - * @return The vft struct that contains the list of callbacks that allows to - * manage the dpo context. - */ -const hicn_dpo_vft_t *hicn_dpo_get_vft (dpo_type_t vfts_id); - -/** - * @brief Get the vft to manage the dpo context from the strategy id. - * - * @param The strategy id of the hicn_dpo_vft to retrieve. - * @return The vft struct that contains the list of callbacks that allows to - * manage the dpo context. - */ -const hicn_dpo_vft_t *hicn_dpo_get_vft_from_id (u8 strategy_id); - -/** - * @brief Get the vft with the hICN strategy functions. - * - * @param The id of the hicn_strategy_vft to retrieve. - * @return The vft struct that contains the list hICN strategy functions. - */ -const hicn_strategy_vft_t *hicn_dpo_get_strategy_vft (dpo_type_t vfts_id); - -/** - * @brief Get the vft with the hICN strategy functions from the strategy id. - * - * @param The id of the hicn_strategy_vft to retrieve. - * @return The vft struct that contains the list hICN strategy functions. - */ -const hicn_strategy_vft_t *hicn_dpo_get_strategy_vft_from_id (u8 vfts_id); - -/** - * @brief Initialize all the types hicn dpo registered - * - * Call the init functions of all the hicn dpo implemented. - * This init is called when the plugin bootstrap. - */ -void hicn_dpos_init (void); - -/** - * @brief Print the list of the registered hICN DPO - * - * @param s String to which to append the list of hICN DPO (strategies) - * @param n number of parameters to pass - * - * @result The string with the list of hICN DPO (strategies) - */ -u8 *format_hicn_strategy_list (u8 * s, int n, ...); - -/** - * @brief Check if a given id points to a strategy and the corresponding dpo ctx - * - * @param The id of the strategy to check. - * - * @result HICN_ERROR_NONE is the id is valid, otherwise EINVAL - */ -u8 hicn_dpo_strategy_id_is_valid (int strategy_id); - -/** - * @brief Return the number of available strategies. This number can be used to - * as an upperbond for valid vfts_id. - * - * @result Return the number of available strategies. - */ -int hicn_strategy_get_all_available (void); - -/** - * @brief Registers a module at compilation time to be initialized as part of - * the ctor. - */ -void hicn_dpo_register (const hicn_dpo_vft_t * hicn_dpo); - -#endif /* // __HICN_STRATEGY_DPO_MANAGER_H__ */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/strategy_node.c b/hicn-plugin/src/strategy_node.c deleted file mode 100644 index 0659a871a..000000000 --- a/hicn-plugin/src/strategy_node.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (c) 2017-2020 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 "hicn.h" -#include "parser.h" -#include "strategy.h" -#include "strategy_dpo_ctx.h" -#include "face_db.h" -#include "infra.h" -#include "mgmt.h" -#include "pcs.h" -#include "state.h" -#include "strategies/strategy_mw.h" - -/* Registration struct for a graph node */ -vlib_node_registration_t hicn_strategy_node; - -/* - * Node context data (to be used in all the strategy nodes); we think this is - * per-thread/instance - */ -typedef struct hicn_strategy_runtime_s -{ - int id; - hicn_pit_cs_t *pitcs; -} hicn_strategy_runtime_t; - -/* Stats string values */ -static char *hicn_strategy_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -/* packet trace format function */ -u8 * -hicn_strategy_format_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 *); - hicn_strategy_trace_t *t = va_arg (*args, hicn_strategy_trace_t *); - - const hicn_strategy_vft_t *vft = hicn_dpo_get_strategy_vft (t->dpo_type); - - return vft->hicn_format_strategy_trace (s, t); -} - - -always_inline int -hicn_new_interest (hicn_strategy_runtime_t * rt, vlib_buffer_t * b0, - u32 * next, f64 tnow, u8 * nameptr, - u16 namelen, hicn_face_id_t outface, int nh_idx, - index_t dpo_ctx_id0, const hicn_strategy_vft_t * strategy, - dpo_type_t dpo_type, u8 isv6, - vl_api_hicn_api_node_stats_get_reply_t * stats) -{ - int ret; - hicn_hash_node_t *nodep; - hicn_pcs_entry_t *pitp; - hicn_header_t *hicn0; - hicn_main_t *sm = &hicn_main; - hicn_buffer_t *hicnb0 = hicn_get_buffer (b0); - u32 node_id0 = 0; - u8 vft_id0 = dpo_type; - u8 is_cs0 = 0; - u8 hash_entry_id = 0; - u8 bucket_is_overflow = 0; - u32 bucket_id = ~0; - - - /* Create PIT node and init PIT entry */ - nodep = hicn_hashtb_alloc_node (rt->pitcs->pcs_table); - if (PREDICT_FALSE (nodep == NULL)) - { - /* Nothing we can do - no mem */ - *next = HICN_STRATEGY_NEXT_ERROR_DROP; - return HICN_ERROR_HASHTB_NOMEM; - } - pitp = hicn_pit_get_data (nodep); - hicn_pit_init_data (pitp); - pitp->shared.create_time = tnow; - - hicn0 = vlib_buffer_get_current (b0); - hicn_lifetime_t imsg_lifetime; - hicn_type_t type = hicnb0->type; - hicn_ops_vft[type.l1]->get_lifetime (type, &hicn0->protocol, - &imsg_lifetime); - - if (imsg_lifetime > sm->pit_lifetime_max_ms) - { - imsg_lifetime = sm->pit_lifetime_max_ms; - } - pitp->shared.expire_time = hicn_pcs_get_exp_time (tnow, imsg_lifetime); - - /* Set up the hash node and insert it */ - hicn_hash_entry_t *hash_entry; - hicn_hashtb_init_node (rt->pitcs->pcs_table, nodep, nameptr, namelen); - - ret = - hicn_pcs_pit_insert (rt->pitcs, pitp, nodep, &hash_entry, - hicnb0->name_hash, &node_id0, &dpo_ctx_id0, &vft_id0, - &is_cs0, &hash_entry_id, &bucket_id, - &bucket_is_overflow); - - if (ret == HICN_ERROR_NONE) - { - strategy->hicn_add_interest (vnet_buffer (b0)->ip.adj_index[VLIB_TX], - hash_entry); - - /* Add face */ - hicn_face_db_add_face (hicnb0->face_id, &(pitp->u.pit.faces)); - - *next = isv6 ? HICN_STRATEGY_NEXT_INTEREST_FACE6 : - HICN_STRATEGY_NEXT_INTEREST_FACE4; - - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = outface; - stats->pkts_interest_count++; - pitp->u.pit.pe_txnh = nh_idx; - } - else - { - /* Interest aggregate in PIT */ - if (ret == HICN_ERROR_HASHTB_EXIST) - { - hicn_store_internal_state (b0, hicnb0->name_hash, node_id0, - dpo_ctx_id0, vft_id0, hash_entry_id, - bucket_id, bucket_is_overflow); - // We need to take a lock as the lock is not taken on the hash - // entry because it is a CS entry (hash_insert function). - hash_entry->locks++; - *next = - is_cs0 ? HICN_STRATEGY_NEXT_INTEREST_HITCS : - HICN_STRATEGY_NEXT_INTEREST_HITPIT; - } - else - { - /* Send the packet to the interest-hitpit node */ - *next = HICN_STRATEGY_NEXT_ERROR_DROP; - } - hicn_faces_flush (&(pitp->u.pit.faces)); - hicn_hashtb_free_node (rt->pitcs->pcs_table, nodep); - } - - return (ret); - -} - -/* - * ICN strategy later node for interests: - 1 packet at a time - ipv4/tcp - * ipv6/tcp - */ -uword -hicn_strategy_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) -{ - - u32 n_left_from, *from, *to_next, n_left_to_next; - hicn_strategy_next_t next_index; - hicn_strategy_runtime_t *rt = NULL; - vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; - f64 tnow; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = (hicn_strategy_next_t) node->cached_next_index; - rt = vlib_node_get_runtime_data (vm, hicn_strategy_node.index); - rt->pitcs = &hicn_main.pitcs; - /* Capture time in vpp terms */ - tnow = vlib_time_now (vm); - - while (n_left_from > 0) - { - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - while (n_left_from > 0 && n_left_to_next > 0) - { - u8 isv6; - u8 *nameptr; - u16 namelen; - hicn_name_t name; - hicn_header_t *hicn0; - vlib_buffer_t *b0; - u32 bi0; - hicn_face_id_t outface; - int nh_idx; - u32 next0 = next_index; - int ret; - - /* Prefetch for next iteration. */ - 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); - } - /* Dequeue a packet buffer */ - bi0 = from[0]; - from += 1; - n_left_from -= 1; - to_next[0] = bi0; - to_next += 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - next0 = HICN_STRATEGY_NEXT_ERROR_DROP; - - hicn_dpo_ctx_t *dpo_ctx = - hicn_strategy_dpo_ctx_get (vnet_buffer (b0)->ip. - adj_index[VLIB_TX]); - const hicn_strategy_vft_t *strategy = - hicn_dpo_get_strategy_vft (dpo_ctx->dpo_type); - - ret = hicn_interest_parse_pkt (b0, &name, &namelen, &hicn0, &isv6); - stats.pkts_processed++; - /* Select next hop */ - /* - * Double check that the interest has been through - * the interest-pcslookup node due to misconfiguration in - * the punting rules. - */ - if (PREDICT_TRUE - (ret == HICN_ERROR_NONE && HICN_IS_NAMEHASH_CACHED (b0) - && strategy->hicn_select_next_hop (vnet_buffer (b0)-> - ip.adj_index[VLIB_TX], - &nh_idx, - &outface) == - HICN_ERROR_NONE)) - { - /* - * No need to check if parsing was successful - * here. Already checked in the interest_pcslookup - * node - */ - nameptr = (u8 *) (&name); - hicn_new_interest (rt, b0, &next0, tnow, nameptr, namelen, - outface, nh_idx, - vnet_buffer (b0)->ip.adj_index[VLIB_TX], - strategy, dpo_ctx->dpo_type, isv6, &stats); - } - /* Maybe trace */ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b0->flags & VLIB_BUFFER_IS_TRACED))) - { - hicn_strategy_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->pkt_type = HICN_PKT_TYPE_CONTENT; - t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - t->next_index = next0; - t->dpo_type = dpo_ctx->dpo_type; - } - /* - * Verify speculative enqueue, maybe switch current - * next frame - */ - /* - * Fix in case of a wrong speculation. Needed for - * cloning the data in the right frame - */ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - vlib_node_increment_counter (vm, hicn_strategy_node.index, - HICNFWD_ERROR_PROCESSED, stats.pkts_processed); - vlib_node_increment_counter (vm, hicn_strategy_node.index, - HICNFWD_ERROR_INTERESTS, - stats.pkts_interest_count); - - return (frame->n_vectors); -} - -/* - * Node registration for the forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (hicn_strategy_node) = - { - .name = "hicn-strategy", - .function = hicn_strategy_fn, - .vector_size = sizeof (u32), - .runtime_data_bytes = sizeof (int) + sizeof(hicn_pit_cs_t *), - .format_trace = hicn_strategy_format_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN (hicn_strategy_error_strings), - .error_strings = hicn_strategy_error_strings, - .n_next_nodes = HICN_STRATEGY_N_NEXT, - .next_nodes = - { - [HICN_STRATEGY_NEXT_INTEREST_HITPIT] = "hicn-interest-hitpit", - [HICN_STRATEGY_NEXT_INTEREST_HITCS] = "hicn-interest-hitcs", - [HICN_STRATEGY_NEXT_INTEREST_FACE4] = "hicn4-face-output", - [HICN_STRATEGY_NEXT_INTEREST_FACE6] = "hicn6-face-output", - [HICN_STRATEGY_NEXT_ERROR_DROP] = "error-drop", - }, - }; - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/udp_tunnels/udp_decap.h b/hicn-plugin/src/udp_tunnels/udp_decap.h deleted file mode 100644 index 9ddb8a73b..000000000 --- a/hicn-plugin/src/udp_tunnels/udp_decap.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2020 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 __UDP_DECAP_H__ -#define __UDP_DECAP_H__ - -/** - * @file udp_decap.h - * - * Implements the udp decapsulation for udp tunnels - * - * Udp decap nodes follow the ip4/6-local nodes and their purpose - * is to retrieve the udp tunnel for the incoming packet. If a tunnel does - * not exist the packet is dropped. - * The following node to the udp decap nodes are the ip4/6-lookup nodes. - */ - -extern vlib_node_registration_t udp_decap_node; - -#endif // __UDP_DECAP_H__ diff --git a/hicn-plugin/src/udp_tunnels/udp_decap_node.c b/hicn-plugin/src/udp_tunnels/udp_decap_node.c deleted file mode 100644 index 5603f20f9..000000000 --- a/hicn-plugin/src/udp_tunnels/udp_decap_node.c +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Copyright (c) 2020 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 "udp_tunnel.h" -#include "../mgmt.h" -#include "../hicn.h" -#include "../strategy_dpo_ctx.h" - -vlib_node_registration_t udp_decap_node; - -static char *udp_decap_error_strings[] = { -#define _(sym, string) string, - foreach_hicnfwd_error -#undef _ -}; - -/* Trace context struct */ -typedef enum -{ - UDP4_DECAP_NEXT_LOOKUP_IP4, - UDP4_DECAP_NEXT_LOOKUP_IP6, - UDP4_DECAP_N_NEXT, -} udp4_decap_next_t; - -typedef enum -{ - UDP6_DECAP_NEXT_LOOKUP_IP4, - UDP6_DECAP_NEXT_LOOKUP_IP6, - UDP6_DECAP_N_NEXT, -} udp6_decap_next_t; - -typedef struct udp4_decap_trace_t_ -{ - ip4_header_t ip; - udp_header_t udp; -} udp4_decap_trace_t; - -typedef struct udp6_decap_trace_t_ -{ - ip6_header_t ip; - udp_header_t udp; -} udp6_decap_trace_t; - -typedef struct udp_decap_trace_t_ -{ - union - { - udp4_decap_trace_t udp4; - udp6_decap_trace_t udp6; - }; - - u8 isv6; - u8 ishicn; -} udp_decap_trace_t; - - -static u8 * -format_udp_decap_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 *); - udp_decap_trace_t *t; - - t = va_arg (*args, udp_decap_trace_t *); - - if (t->isv6) - { - s = format (s, "%U\n %U \n %s", - format_ip4_header, &t->udp6.ip, sizeof (t->udp6.ip), - format_udp_header, &t->udp6.udp, sizeof (t->udp6.udp), - t->ishicn ? "hICN udp tunnel" : ""); - } - else - { - s = format (s, "%U\n %U \n %s", - format_ip4_header, &t->udp4.ip, sizeof (t->udp4.ip), - format_udp_header, &t->udp4.udp, sizeof (t->udp4.udp), - t->ishicn ? "hICN udp tunnel" : ""); - } - return (s); -} - -static_always_inline void -udp_decap_trace_buffer (vlib_main_t * vm, vlib_node_runtime_t * node, - u8 isv6, vlib_buffer_t * b) -{ - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && - (b->flags & VLIB_BUFFER_IS_TRACED))) - { - udp_decap_trace_t *t = - vlib_add_trace (vm, node, b, sizeof (*t)); - t->isv6 = isv6; - hicn_buffer_t *hb = hicn_get_buffer(b); - - if (isv6) - { - clib_memcpy(&(t->udp6.udp), vlib_buffer_get_current(b) + sizeof(ip6_header_t), sizeof(udp_header_t)); - clib_memcpy(&(t->udp6.ip), vlib_buffer_get_current(b), sizeof(ip6_header_t)); - t->ishicn = hb->flags & hb->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL; - } - else - { - clib_memcpy(&(t->udp4.udp), vlib_buffer_get_current(b) + sizeof(ip4_header_t), sizeof(udp_header_t)); - clib_memcpy(&(t->udp4.ip), vlib_buffer_get_current(b), sizeof(ip4_header_t)); - t->ishicn = hb->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL; - } - } -} - -static uword -udp4_decap_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next, next_index; - - 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); - - /* Dual loop, X2 */ - while (n_left_from >= 8 && n_left_to_next >= 4) - { - vlib_buffer_t *b0, *b1, *b2, *b3; - u32 bi0, bi1, bi2, bi3; - u32 next0, next1, next2, next3; - - { - 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); - } - - bi0 = from[0]; - bi1 = from[1]; - bi2 = from[2]; - bi3 = from[3]; - - from += 4; - n_left_from -= 4; - to_next[0] = bi0; - to_next[1] = bi1; - to_next[2] = bi2; - to_next[3] = bi3; - - to_next += 4; - n_left_to_next -= 4; - - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - b2 = vlib_get_buffer (vm, bi2); - b3 = vlib_get_buffer (vm, bi3); - - u8 *ptr0 = vlib_buffer_get_current (b0); - u8 *ptr1 = vlib_buffer_get_current (b1); - u8 *ptr2 = vlib_buffer_get_current (b2); - u8 *ptr3 = vlib_buffer_get_current (b3); - u8 v0 = *ptr0 & 0xf0; - u8 v1 = *ptr1 & 0xf0; - u8 v2 = *ptr2 & 0xf0; - u8 v3 = *ptr3 & 0xf0; - - u8 advance = sizeof(ip4_header_t) + sizeof(udp_header_t); - - vlib_buffer_advance(b0, -advance); - vlib_buffer_advance(b1, -advance); - vlib_buffer_advance(b2, -advance); - vlib_buffer_advance(b3, -advance); - - u8 *outer_ptr0 = vlib_buffer_get_current (b0); - u8 *outer_ptr1 = vlib_buffer_get_current (b1); - u8 *outer_ptr2 = vlib_buffer_get_current (b2); - u8 *outer_ptr3 = vlib_buffer_get_current (b3); - u8 outer_v0 = *outer_ptr0 & 0xf0; - u8 outer_v1 = *outer_ptr1 & 0xf0; - u8 outer_v2 = *outer_ptr2 & 0xf0; - u8 outer_v3 = *outer_ptr3 & 0xf0; - - ip46_address_t src0 = {0}; - ip46_address_t src1 = {0}; - ip46_address_t src2 = {0}; - ip46_address_t src3 = {0}; - - ip46_address_t dst0 = {0}; - ip46_address_t dst1 = {0}; - ip46_address_t dst2 = {0}; - ip46_address_t dst3 = {0}; - - udp_header_t * udp0 = NULL; - udp_header_t * udp1 = NULL; - udp_header_t * udp2 = NULL; - udp_header_t * udp3 = NULL; - - ip46_address_set_ip4(&src0, &((ip4_header_t *)outer_ptr0)->src_address); - ip46_address_set_ip4(&dst0, &((ip4_header_t *)outer_ptr0)->dst_address); - udp0 = (udp_header_t *)(outer_ptr0 + sizeof(ip4_header_t)); - next0 = v0 == 0x40? UDP4_DECAP_NEXT_LOOKUP_IP4 : UDP4_DECAP_NEXT_LOOKUP_IP6; - - ip46_address_set_ip4(&src1, &((ip4_header_t *)outer_ptr1)->src_address); - ip46_address_set_ip4(&dst1, &((ip4_header_t *)outer_ptr1)->dst_address); - udp1 = (udp_header_t *)(outer_ptr1 + sizeof(ip4_header_t)); - next1 = v1 == 0x40? UDP4_DECAP_NEXT_LOOKUP_IP4 : UDP4_DECAP_NEXT_LOOKUP_IP6; - - ip46_address_set_ip4(&src2, &((ip4_header_t *)outer_ptr2)->src_address); - ip46_address_set_ip4(&dst2, &((ip4_header_t *)outer_ptr2)->dst_address); - udp2 = (udp_header_t *)(outer_ptr2 + sizeof(ip4_header_t)); - next2 = v2 == 0x40? UDP4_DECAP_NEXT_LOOKUP_IP4 : UDP4_DECAP_NEXT_LOOKUP_IP6; - - ip46_address_set_ip4(&src3, &((ip4_header_t *)outer_ptr3)->src_address); - ip46_address_set_ip4(&dst3, &((ip4_header_t *)outer_ptr3)->dst_address); - udp3 = (udp_header_t *)(outer_ptr3 + sizeof(ip4_header_t)); - next3 = v3 == 0x40? UDP4_DECAP_NEXT_LOOKUP_IP4 : UDP4_DECAP_NEXT_LOOKUP_IP6; - - hicn_buffer_t *hicnb0, *hicnb1, *hicnb2, *hicnb3; - hicnb0 = hicn_get_buffer(b0); - hicnb1 = hicn_get_buffer(b1); - hicnb2 = hicn_get_buffer(b2); - hicnb3 = hicn_get_buffer(b3); - - - /* Udp encap-decap tunnels have dst and src addresses and port swapped */ - vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst0, &src0, udp0->dst_port, udp0->src_port); - vnet_buffer (b1)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst1, &src1, udp1->dst_port, udp1->src_port); - vnet_buffer (b2)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst2, &src2, udp2->dst_port, udp2->src_port); - vnet_buffer (b3)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst3, &src3, udp3->dst_port, udp3->src_port); - - if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] != - UDP_TUNNEL_INVALID) - hicnb0->flags |= (outer_v0 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); - - if (vnet_buffer (b1)->ip.adj_index[VLIB_RX] != - UDP_TUNNEL_INVALID) - hicnb1->flags |= (outer_v1 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); - - if (vnet_buffer (b2)->ip.adj_index[VLIB_RX] != - UDP_TUNNEL_INVALID) - hicnb2->flags |= (outer_v2 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); - - if (vnet_buffer (b3)->ip.adj_index[VLIB_RX] != - UDP_TUNNEL_INVALID) - hicnb3->flags |= (outer_v3 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); - - udp_decap_trace_buffer (vm, node, 1, b0); - udp_decap_trace_buffer (vm, node, 1, b1); - udp_decap_trace_buffer (vm, node, 1, b2); - udp_decap_trace_buffer (vm, node, 1, b3); - - vlib_buffer_advance(b0, advance); - vlib_buffer_advance(b1, advance); - vlib_buffer_advance(b2, advance); - vlib_buffer_advance(b3, advance); - - vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next, - n_left_to_next, bi0, bi1, bi2, bi3, - next0, next1, next2, next3); - } - - /* Dual loop, X1 */ - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *b0; - u32 bi0; - /* udp_encap_t *udp_tunnel0 = NULL; */ - u32 next0; - - if (n_left_from > 1) - { - vlib_buffer_t *b1; - b1 = vlib_get_buffer (vm, from[1]); - CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, STORE); - } - - bi0 = from[0]; - from += 1; - n_left_from -= 1; - to_next[0] = bi0; - to_next += 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - u8 *ptr0 = vlib_buffer_get_current (b0); - u8 v0 = *ptr0 & 0xf0; - - u8 advance = sizeof(ip4_header_t) + sizeof(udp_header_t);; - - vlib_buffer_advance(b0, -advance); - - u8 *outer_ptr0 = vlib_buffer_get_current (b0); - u8 outer_v0 = *outer_ptr0 & 0xf0; - - ip46_address_t src0 = {0}; - ip46_address_t dst0 = {0}; - udp_header_t * udp0 = NULL; - - ip46_address_set_ip4(&src0, &((ip4_header_t *)outer_ptr0)->src_address); - ip46_address_set_ip4(&dst0, &((ip4_header_t *)outer_ptr0)->dst_address); - udp0 = (udp_header_t *)(outer_ptr0 + sizeof(ip4_header_t)); - next0 = v0 == 0x40 ? UDP4_DECAP_NEXT_LOOKUP_IP4: UDP4_DECAP_NEXT_LOOKUP_IP6; - - hicn_buffer_t *hicnb0 = hicn_get_buffer(b0); - - vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst0, &src0, udp0->dst_port, udp0->src_port); - - if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] != - UDP_TUNNEL_INVALID) - hicnb0->flags |= (outer_v0 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); - - udp_decap_trace_buffer (vm, node, 1, b0); - - vlib_buffer_advance(b0, advance); - - 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); - } - - return (frame->n_vectors); -} - - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(udp4_decap_node) = -{ - .function = udp4_decap_node_fn, - .name = "udp4-decap", - .vector_size = sizeof(u32), - .format_trace = format_udp_decap_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(udp_decap_error_strings), - .error_strings = udp_decap_error_strings, - .n_next_nodes = UDP4_DECAP_N_NEXT, - /* edit / add dispositions here */ - .next_nodes = - { - [UDP4_DECAP_NEXT_LOOKUP_IP4] = "ip4-lookup", - [UDP4_DECAP_NEXT_LOOKUP_IP6] = "ip6-lookup" - }, -}; -/* *INDENT-ON* */ - -static uword -udp6_decap_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, *from, *to_next, next_index; - - 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); - - /* Dual loop, X2 */ - while (n_left_from >= 8 && n_left_to_next >= 4) - { - vlib_buffer_t *b0, *b1, *b2, *b3; - u32 bi0, bi1, bi2, bi3; - u32 next0, next1, next2, next3; - - { - 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); - } - - bi0 = from[0]; - bi1 = from[1]; - bi2 = from[2]; - bi3 = from[3]; - - from += 4; - n_left_from -= 4; - to_next[0] = bi0; - to_next[1] = bi1; - to_next[2] = bi2; - to_next[3] = bi3; - - to_next += 4; - n_left_to_next -= 4; - - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - b2 = vlib_get_buffer (vm, bi2); - b3 = vlib_get_buffer (vm, bi3); - - u8 *ptr0 = vlib_buffer_get_current (b0); - u8 *ptr1 = vlib_buffer_get_current (b1); - u8 *ptr2 = vlib_buffer_get_current (b2); - u8 *ptr3 = vlib_buffer_get_current (b3); - u8 v0 = *ptr0 & 0xf0; - u8 v1 = *ptr1 & 0xf0; - u8 v2 = *ptr2 & 0xf0; - u8 v3 = *ptr3 & 0xf0; - - u8 advance = sizeof(ip6_header_t) + sizeof(udp_header_t); - - vlib_buffer_advance(b0, -advance); - vlib_buffer_advance(b1, -advance); - vlib_buffer_advance(b2, -advance); - vlib_buffer_advance(b3, -advance); - - u8 *outer_ptr0 = vlib_buffer_get_current (b0); - u8 *outer_ptr1 = vlib_buffer_get_current (b1); - u8 *outer_ptr2 = vlib_buffer_get_current (b2); - u8 *outer_ptr3 = vlib_buffer_get_current (b3); - u8 outer_v0 = *outer_ptr0 & 0xf0; - u8 outer_v1 = *outer_ptr1 & 0xf0; - u8 outer_v2 = *outer_ptr2 & 0xf0; - u8 outer_v3 = *outer_ptr3 & 0xf0; - - ip46_address_t src0 = {0}; - ip46_address_t src1 = {0}; - ip46_address_t src2 = {0}; - ip46_address_t src3 = {0}; - - ip46_address_t dst0 = {0}; - ip46_address_t dst1 = {0}; - ip46_address_t dst2 = {0}; - ip46_address_t dst3 = {0}; - - udp_header_t * udp0 = NULL; - udp_header_t * udp1 = NULL; - udp_header_t * udp2 = NULL; - udp_header_t * udp3 = NULL; - - ip46_address_set_ip6(&src0, &((ip6_header_t *)outer_ptr0)->src_address); - ip46_address_set_ip6(&dst0, &((ip6_header_t *)outer_ptr0)->dst_address); - udp0 = (udp_header_t *)(outer_ptr0 + sizeof(ip6_header_t)); - next0 = v0 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6; - - ip46_address_set_ip6(&src1, &((ip6_header_t *)outer_ptr1)->src_address); - ip46_address_set_ip6(&dst1, &((ip6_header_t *)outer_ptr1)->dst_address); - udp1 = (udp_header_t *)(outer_ptr1 + sizeof(ip6_header_t)); - next1 = v1 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6; - - ip46_address_set_ip6(&src2, &((ip6_header_t *)outer_ptr2)->src_address); - ip46_address_set_ip6(&dst2, &((ip6_header_t *)outer_ptr2)->dst_address); - udp2 = (udp_header_t *)(outer_ptr2 + sizeof(ip6_header_t)); - next2 = v2 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6; - - ip46_address_set_ip6(&src3, &((ip6_header_t *)outer_ptr3)->src_address); - ip46_address_set_ip6(&dst3, &((ip6_header_t *)outer_ptr3)->dst_address); - udp3 = (udp_header_t *)(outer_ptr3 + sizeof(ip6_header_t)); - next3 = v3 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6; - - hicn_buffer_t *hicnb0, *hicnb1, *hicnb2, *hicnb3; - hicnb0 = hicn_get_buffer(b0); - hicnb1 = hicn_get_buffer(b1); - hicnb2 = hicn_get_buffer(b2); - hicnb3 = hicn_get_buffer(b3); - - - /* Udp encap-decap tunnels have dst and src addresses and port swapped */ - vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst0, &src0, udp0->dst_port, udp0->src_port); - vnet_buffer (b1)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst1, &src1, udp1->dst_port, udp1->src_port); - vnet_buffer (b2)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst2, &src2, udp2->dst_port, udp2->src_port); - vnet_buffer (b3)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst3, &src3, udp3->dst_port, udp3->src_port); - - if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] != - UDP_TUNNEL_INVALID) - hicnb0->flags |= (outer_v0 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); - - if (vnet_buffer (b1)->ip.adj_index[VLIB_RX] != - UDP_TUNNEL_INVALID) - hicnb1->flags |= (outer_v1 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); - - if (vnet_buffer (b2)->ip.adj_index[VLIB_RX] != - UDP_TUNNEL_INVALID) - hicnb2->flags |= (outer_v2 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); - - if (vnet_buffer (b3)->ip.adj_index[VLIB_RX] != - UDP_TUNNEL_INVALID) - hicnb3->flags |= (outer_v3 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); - - udp_decap_trace_buffer (vm, node, 0, b0); - udp_decap_trace_buffer (vm, node, 0, b1); - udp_decap_trace_buffer (vm, node, 0, b2); - udp_decap_trace_buffer (vm, node, 0, b3); - - vlib_buffer_advance(b0, advance); - vlib_buffer_advance(b1, advance); - vlib_buffer_advance(b2, advance); - vlib_buffer_advance(b3, advance); - - vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next, - n_left_to_next, bi0, bi1, bi2, bi3, - next0, next1, next2, next3); - } - - /* Dual loop, X1 */ - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *b0; - u32 bi0; - /* udp_encap_t *udp_tunnel0 = NULL; */ - u32 next0; - - if (n_left_from > 1) - { - vlib_buffer_t *b1; - b1 = vlib_get_buffer (vm, from[1]); - CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, STORE); - } - - bi0 = from[0]; - from += 1; - n_left_from -= 1; - to_next[0] = bi0; - to_next += 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - u8 *ptr0 = vlib_buffer_get_current (b0); - u8 v0 = *ptr0 & 0xf0; - - u8 advance = sizeof(ip6_header_t) + sizeof(udp_header_t); - - vlib_buffer_advance(b0, -advance); - - u8 *outer_ptr0 = vlib_buffer_get_current (b0); - u8 outer_v0 = *outer_ptr0 & 0xf0; - - ip46_address_t src0 = {0}; - ip46_address_t dst0 = {0}; - udp_header_t * udp0 = NULL; - - ip46_address_set_ip6(&src0, &((ip6_header_t *)outer_ptr0)->src_address); - ip46_address_set_ip6(&dst0, &((ip6_header_t *)outer_ptr0)->dst_address); - udp0 = (udp_header_t *)(outer_ptr0 + sizeof(ip6_header_t)); - next0 = v0 == 0x40? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6; - - hicn_buffer_t *hicnb0 = hicn_get_buffer(b0); - - vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst0, &src0, udp0->dst_port, udp0->src_port); - - if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] != - UDP_TUNNEL_INVALID) - hicnb0->flags |= (outer_v0 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL); - - udp_decap_trace_buffer (vm, node, 0, b0); - - vlib_buffer_advance(b0, advance); - - 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); - } - - return (frame->n_vectors); -} - - -/* - * Node registration for the interest forwarder node - */ -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE(udp6_decap_node) = -{ - .function = udp6_decap_node_fn, - .name = "udp6-decap", - .vector_size = sizeof(u32), - .format_trace = format_udp_decap_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - .n_errors = ARRAY_LEN(udp_decap_error_strings), - .error_strings = udp_decap_error_strings, - .n_next_nodes = UDP6_DECAP_N_NEXT, - /* edit / add dispositions here */ - .next_nodes = - { - [UDP6_DECAP_NEXT_LOOKUP_IP4] = "ip4-lookup", - [UDP6_DECAP_NEXT_LOOKUP_IP6] = "ip6-lookup" - }, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/hicn-plugin/src/udp_tunnels/udp_tunnel.c b/hicn-plugin/src/udp_tunnels/udp_tunnel.c deleted file mode 100644 index 872e4cd82..000000000 --- a/hicn-plugin/src/udp_tunnels/udp_tunnel.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2020 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 "../error.h" -#include "../strategy_dpo_ctx.h" -#include "udp_tunnel.h" - -clib_bihash_40_8_t udp_tunnels_hashtb; -dpo_type_t dpo_type_udp_ip4; -dpo_type_t dpo_type_udp_ip6; - -u32 udp_tunnel_add (fib_protocol_t proto, - index_t fib_index, - const ip46_address_t * src_ip, - const ip46_address_t * dst_ip, - u16 src_port, - u16 dst_port, - udp_encap_fixup_flags_t flags) -{ - vlib_main_t *vm = vlib_get_main(); - clib_bihash_kv_40_8_t kv; - clib_memcpy(&kv.key[0], src_ip, sizeof(ip46_address_t)); - clib_memcpy(&kv.key[2], dst_ip, sizeof(ip46_address_t)); - kv.key[4] = (clib_host_to_net_u16(src_port) << 16) + clib_host_to_net_u16(dst_port); - - clib_bihash_kv_40_8_t value; - int rv = clib_bihash_search_40_8 (&udp_tunnels_hashtb, &kv, &value); - - if (rv != 0) - { - u32 uei = udp_encap_add_and_lock(proto, fib_index, src_ip, dst_ip, src_port, dst_port, flags); - kv.value = uei; - clib_bihash_add_del_40_8(&udp_tunnels_hashtb, &kv, 1); - value.value = kv.value; - if (proto == FIB_PROTOCOL_IP4) - { - udp_register_dst_port(vm, src_port, udp4_decap_node.index, 1); - } - else - { - udp_register_dst_port(vm, src_port, udp6_decap_node.index, 0); - } - } - - return value.value; -} - -void udp_tunnel_add_existing (index_t uei, dpo_proto_t proto) -{ - vlib_main_t *vm = vlib_get_main(); - udp_encap_t * udp_encap = udp_encap_get(uei); - clib_bihash_kv_40_8_t kv; - - ip46_address_t src = {0}; - ip46_address_t dst = {0}; - u16 src_port = 0, dst_port = 0; - - switch (proto) - { - case DPO_PROTO_IP4: - ip46_address_set_ip4(&src, &(udp_encap->ue_hdrs.ip4.ue_ip4.src_address)); - ip46_address_set_ip4(&dst, &(udp_encap->ue_hdrs.ip4.ue_ip4.dst_address)); - src_port = udp_encap->ue_hdrs.ip4.ue_udp.src_port; - dst_port = udp_encap->ue_hdrs.ip4.ue_udp.dst_port; - break; - case DPO_PROTO_IP6: - ip46_address_set_ip6(&src, &(udp_encap->ue_hdrs.ip6.ue_ip6.src_address)); - ip46_address_set_ip6(&dst, &(udp_encap->ue_hdrs.ip6.ue_ip6.dst_address)); - src_port = udp_encap->ue_hdrs.ip6.ue_udp.src_port; - dst_port = udp_encap->ue_hdrs.ip6.ue_udp.dst_port; - break; - default: - break; - } - - clib_memcpy(&kv.key[0], &src, sizeof(ip46_address_t)); - clib_memcpy(&kv.key[2], &dst, sizeof(ip46_address_t)); - kv.key[4] = (src_port << 16) + dst_port ; - kv.value = uei; - - clib_bihash_add_del_40_8(&udp_tunnels_hashtb, &kv, 1); - - if (proto == DPO_PROTO_IP4) - { - udp_register_dst_port(vm, clib_net_to_host_u16(src_port), udp4_decap_node.index, 1); - } - else - { - udp_register_dst_port(vm, clib_net_to_host_u16(src_port), udp6_decap_node.index, 0); - } -} - -int udp_tunnel_del (fib_protocol_t proto, - index_t fib_index, - const ip46_address_t * src_ip, - const ip46_address_t * dst_ip, - u16 src_port, - u16 dst_port, - udp_encap_fixup_flags_t flags) -{ - clib_bihash_kv_40_8_t kv; - clib_memcpy(&kv.key[0], src_ip, sizeof(ip46_address_t)); - clib_memcpy(&kv.key[2], dst_ip, sizeof(ip46_address_t)); - kv.key[4] = (clib_host_to_net_u16(src_port) << 16) + clib_host_to_net_u16(dst_port); - - clib_bihash_kv_40_8_t value; - int ret = clib_bihash_search_40_8 (&udp_tunnels_hashtb, &kv, &value); - - if (ret == 0) - { - udp_encap_unlock((u32)value.value); - clib_bihash_add_del_40_8(&udp_tunnels_hashtb, &kv, 0); - ret = HICN_ERROR_NONE; - } - else - { - ret = HICN_ERROR_UDP_TUNNEL_NOT_FOUND; - } - - return ret; -} - -u32 udp_tunnel_get(const ip46_address_t * src_ip, - const ip46_address_t * dst_ip, - u16 src_port, - u16 dst_port) -{ - clib_bihash_kv_40_8_t kv; - clib_memcpy(&kv.key[0], src_ip, sizeof(ip46_address_t)); - clib_memcpy(&kv.key[2], dst_ip, sizeof(ip46_address_t)); - kv.key[4] = (src_port << 16) + dst_port; - - clib_bihash_kv_40_8_t value; - int ret = clib_bihash_search_40_8 (&udp_tunnels_hashtb, &kv, &value); - - return ret == 0 ? (u32)value.value : UDP_TUNNEL_INVALID; -} - - -void udp_tunnel_init() -{ - clib_bihash_init_40_8(&udp_tunnels_hashtb, "udp encap table", - 2048, 256 << 20); - - /* - * Udp encap does not expose the dpo type when it registers. - * In the following we understand what is the dpo type for a udp_encap dpo. - */ - ip46_address_t src = {0}; - ip46_address_t dst = {0}; - - src.ip6.as_u8[15] = 1; - dst.ip6.as_u8[15] = 2; - - u32 fib_index = fib_table_find (FIB_PROTOCOL_IP6, HICN_FIB_TABLE); - u32 uei = udp_encap_add_and_lock(FIB_PROTOCOL_IP6, fib_index, &src, &dst, 4444, 4444, UDP_ENCAP_FIXUP_NONE); - - dpo_id_t temp = DPO_INVALID; - udp_encap_contribute_forwarding(uei, DPO_PROTO_IP6, &temp); - dpo_type_udp_ip6 = temp.dpoi_type; - udp_encap_unlock(uei); - - dpo_id_t temp2 = DPO_INVALID; - fib_index = fib_table_find (FIB_PROTOCOL_IP4, HICN_FIB_TABLE); - uei = udp_encap_add_and_lock(FIB_PROTOCOL_IP4, fib_index, &src, &dst, 4444, 4444, UDP_ENCAP_FIXUP_NONE); - udp_encap_contribute_forwarding(uei, DPO_PROTO_IP4, &temp2); - dpo_type_udp_ip4 = temp2.dpoi_type; - udp_encap_unlock(uei); -} - -static clib_error_t * -udp_tunnel_command_fn (vlib_main_t * vm, - unformat_input_t * main_input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - clib_error_t *error = NULL; - ip46_address_t src_ip = {0}, dst_ip = {0}; - u32 table_id, src_port, dst_port; - fib_protocol_t fproto; - u8 is_del; - index_t uei; - - is_del = 0; - fproto = FIB_PROTOCOL_MAX; - uei = ~0; - table_id = HICN_FIB_TABLE; - - /* Get a line of input. */ - if (unformat_user (main_input, unformat_line_input, line_input)) - { - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "index %d", &uei)) - ; - else if (unformat (line_input, "add")) - is_del = 0; - else if (unformat (line_input, "del")) - is_del = 1; - else if (unformat (line_input, "%U %U", - unformat_ip4_address, - &src_ip.ip4, unformat_ip4_address, &dst_ip.ip4)) - fproto = FIB_PROTOCOL_IP4; - else if (unformat (line_input, "%U %U", - unformat_ip6_address, - &src_ip.ip6, unformat_ip6_address, &dst_ip.ip6)) - fproto = FIB_PROTOCOL_IP6; - else if (unformat (line_input, "%d %d", &src_port, &dst_port)) - ; - else if (unformat (line_input, "table-id %d", &table_id)) - ; - else - { - error = unformat_parse_error (line_input); - goto done; - } - } - } - - index_t fib_index = fib_table_find (fproto, table_id); - if (~0 == fib_index) - { - error = clib_error_return (0, "Nonexistent table id %d", table_id); - goto done; - } - - if (!is_del && fproto != FIB_PROTOCOL_MAX) - { - uei = udp_tunnel_add(fproto, fib_index, &src_ip, &dst_ip, src_port, dst_port, UDP_ENCAP_FIXUP_NONE); - - vlib_cli_output (vm, "udp-encap: %d\n", uei); - } - else if (is_del) - { - int ret = udp_tunnel_del(fproto, fib_index, &src_ip, &dst_ip, src_port, dst_port, UDP_ENCAP_FIXUP_NONE); - error = (ret == HICN_ERROR_NONE) ? 0 : clib_error_return (0, "%s\n", - get_error_string - (ret)); - } - else - { - error = clib_error_return (0, "specify some IP addresses"); - } - - done: - unformat_free (line_input); - return error; - -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (udp_tunnel_command, static) = - { - .path = "udp tunnel", - .short_help = "udp tunnel [add/del] src_address dst_address src_port dst_port", - .function = udp_tunnel_command_fn, - }; -/* *INDENT-ON* */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/src/udp_tunnels/udp_tunnel.h b/hicn-plugin/src/udp_tunnels/udp_tunnel.h deleted file mode 100644 index 2ec92056c..000000000 --- a/hicn-plugin/src/udp_tunnels/udp_tunnel.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2020 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 __UDP_TUNNEL__ -#define __UDP_TUNNEL__ - -#include -#include -#include - -/** - * @file udp_tunnel.h - * - * This file implements bidirectional udp tunnels. Udp tunnels exploit - * the udp encap functionality in vpp. In particular, a udp tunnel creates - * an udp encap object with the information for encapsulating packets and it - * implements the udp decap node. The udp decap node checks if a udp tunnel exists - * before performing the decapsulation. If the tunnel does not exist the packet - * is dropped. - */ - -#define UDP_TUNNEL_INVALID ~0 - -extern dpo_type_t dpo_type_udp_ip4; -extern dpo_type_t dpo_type_udp_ip6; - -extern vlib_node_registration_t udp4_decap_node; -extern vlib_node_registration_t udp6_decap_node; - -/** - * @brief Create a udp tunnel - * - * @param proto FIB_PROTOCOL_IP4 or FIB_PROTOCOL_IP6 - * @param fib_index fib index to add to the udp encap - * @param src_ip source address of the tunnel - * @param dst_ip destination address of the tunnel - * @param src_port source port - * @param src_port destination port - * @param flags flags for the udp encap - * - * @return return the id of the tunnel - */ -u32 udp_tunnel_add (fib_protocol_t proto, - index_t fib_index, - const ip46_address_t * src_ip, - const ip46_address_t * dst_ip, - u16 src_port, - u16 dst_port, - udp_encap_fixup_flags_t flags); - -/** - * @brief Retrieve the index of a udp tunnel (same id of the udp encap) - * - * @param src_ip source address of the tunnel - * @param dst_ip destination address of the tunnel - * @param src_port source port - * @param src_port destination port - * - * @return id of the udp tunnel/encap - */ -u32 udp_tunnel_get(const ip46_address_t * src_ip, - const ip46_address_t * dst_ip, - u16 src_port, - u16 dst_port); - -/** - * @brief Delete a udp tunnel - * - * @param proto FIB_PROTOCOL_IP4 or FIB_PROTOCOL_IP6 - * @param fib_index fib index to add to the udp encap - * @param src_ip source address of the tunnel - * @param dst_ip destination address of the tunnel - * @param src_port source port - * @param src_port destination port - * @param flags flags for the udp encap - * - * @return HICN_ERROR_UDP_TUNNEL_NOT_FOUND if the tunnel was not found - * or HICN_ERROR_NONE if the tunnel has been deleted - */ -int udp_tunnel_del (fib_protocol_t proto, - index_t fib_index, - const ip46_address_t * src_ip, - const ip46_address_t * dst_ip, - u16 src_port, - u16 dst_port, - udp_encap_fixup_flags_t flags); - -/** - * @brief Add a udp tunnel from an existing udp encap - * - * @param uei index of the udp encap object - * @param proto DPO_PROTO_IP6 or DPO_PROTO_IP4 - */ -void udp_tunnel_add_existing (index_t uei, dpo_proto_t proto); - -/** - * @brief Init the udp tunnel module - * - */ -void udp_tunnel_init(); - -#endif diff --git a/hicn-plugin/src/utils.h b/hicn-plugin/src/utils.h deleted file mode 100644 index 689942ab6..000000000 --- a/hicn-plugin/src/utils.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2017-2019 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_UTILS_H__ -#define __HICN_UTILS_H__ - -#include "hicn.h" - -/** - * @file - * - * Helpers to print hicn headers - */ - -/** - * @Brief Print the hicn name - * - * @param name hicn name to print - */ -always_inline void -hicn_print_name6 (hicn_name_t * name) -{ - u8 *s0; - s0 = format (0, "Source addr %U, seq_number %u", format_ip6_address, - (ip6_address_t *) name->ip6.prefix, - clib_net_to_host_u32 (name->ip6.suffix)); - - printf ("%s\n", s0); -} - -/** - * @Brief Print the ipv6 hicn header (src and dst address and port) - * - * @param hicn0 hICN header to print - */ -always_inline void -hicn_print6 (hicn_header_t * hicn0) -{ - vlib_main_t *vm = vlib_get_main (); - u8 *s0; - s0 = format (0, "Source addr %U:%u, dest addr %U:%u", format_ip6_address, - &(hicn0->v6.ip.saddr), - clib_net_to_host_u32 (hicn0->v6.tcp.seq), format_ip6_address, - &(hicn0->v6.ip.daddr), - clib_net_to_host_u32 (hicn0->v6.tcp.seq)); - - vlib_cli_output (vm, "%s\n", s0); -} - -/** - * @Brief Print the ipv4 hicn header (src and dst address and port) - * - * @param hicn0 hICN header to print - */ -always_inline void -hicn_print4 (hicn_header_t * hicn0) -{ - u8 *s0; - s0 = format (0, "Source addr %U:%u, dest addr %U:%u", format_ip4_address, - &(hicn0->v4.ip.saddr), - clib_net_to_host_u32 (hicn0->v4.tcp.seq), format_ip4_address, - &(hicn0->v4.ip.daddr), - clib_net_to_host_u32 (hicn0->v4.tcp.seq)); - - printf ("%s\n", s0); -} - -#endif /* // __HICN_UTILS_H__ */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: eval: (c-set-style "gnu") End: - */ diff --git a/hicn-plugin/vapi/CMakeLists.txt b/hicn-plugin/vapi/CMakeLists.txt index 03fd489ca..382ccc34a 100644 --- a/hicn-plugin/vapi/CMakeLists.txt +++ b/hicn-plugin/vapi/CMakeLists.txt @@ -32,6 +32,7 @@ set (LIBRARIES ${VPP_LIBRARY_VAPICLIENT}) list (APPEND INCLUDE_DIRS + ${HICNPLUGIN_INCLUDE_DIRS} ${VPP_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include) @@ -42,7 +43,7 @@ build_library(${SAFE_VAPI} LINK_LIBRARIES ${LIBRARIES} COMPONENT ${HICN_PLUGIN} INCLUDE_DIRS ${INCLUDE_DIRS} - INSTALL_ROOT_DIR / + HEADER_ROOT_DIR / DEFINITIONS ${COMPILER_DEFINITIONS} ) -- cgit 1.2.3-korg