aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEnrico Loparco (eloparco) <eloparco@cisco.com>2021-06-24 09:15:41 +0200
committerEnrico Loparco (eloparco) <eloparco@cisco.com>2021-06-24 09:15:41 +0200
commit229385955109b866a23c4ac2aa03d4d11044c39d (patch)
tree0591f9c2fc4144d62330337cc2b94c63dfeded54
parent6ffbb5ed61733b8dbef39b1a9d437e899e9359d7 (diff)
[HICN-708] Rebase with master
Signed-off-by: Enrico Loparco (eloparco) <eloparco@cisco.com> Change-Id: I2122e1d61dd3b2e039972624ffbdbcb3c5610159
-rw-r--r--.gitignore3
-rw-r--r--CMakeLists.txt22
-rw-r--r--apps/.clang-format14
-rw-r--r--apps/CMakeLists.txt25
-rw-r--r--apps/cmake/Modules/Packaging.cmake10
-rw-r--r--apps/higet/CMakeLists.txt4
-rw-r--r--apps/higet/higet.cc43
-rw-r--r--apps/http-proxy/CMakeLists.txt41
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt39
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h200
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h107
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h (renamed from apps/http-proxy/src/HTTP1.xMessageFastParser.h)33
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/http_proxy.h210
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/http_session.h (renamed from apps/http-proxy/src/ATSConnector.h)49
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h (renamed from apps/http-proxy/src/IcnReceiver.h)41
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/utils.h51
-rw-r--r--apps/http-proxy/main.cc135
-rw-r--r--apps/http-proxy/src/forwarder_interface.cc263
-rw-r--r--apps/http-proxy/src/http_1x_message_fast_parser.cc (renamed from apps/http-proxy/src/HTTP1.xMessageFastParser.cc)47
-rw-r--r--apps/http-proxy/src/http_proxy.cc376
-rw-r--r--apps/http-proxy/src/http_session.cc (renamed from apps/http-proxy/src/ATSConnector.cc)166
-rw-r--r--apps/http-proxy/src/icn_receiver.cc (renamed from apps/http-proxy/src/IcnReceiver.cc)103
-rw-r--r--cmake/Modules/BuildMacros.cmake82
-rw-r--r--cmake/Modules/FindCollectd.cmake10
-rw-r--r--cmake/Modules/FindLibFec.cmake24
-rw-r--r--cmake/Modules/FindLibRely.cmake24
-rw-r--r--cmake/Modules/FindLibconfig++.cmake44
-rw-r--r--cmake/Modules/FindLibconfig.cmake43
-rw-r--r--cmake/Modules/FindLibhicn.cmake2
-rw-r--r--cmake/Modules/GTestImport.cmake21
-rw-r--r--cmake/Modules/License.txt12
-rw-r--r--cmake/Modules/Packager.cmake162
-rw-r--r--cmake/Modules/PostInstall.cmake83
-rw-r--r--cmake/Modules/ServiceScript.cmake2
-rw-r--r--ctrl/facemgr/CMakeLists.txt19
-rw-r--r--ctrl/facemgr/cmake/Modules/Packaging.cmake15
-rw-r--r--ctrl/facemgr/config/facemgr.conf194
-rw-r--r--ctrl/facemgr/config/facemgr.service24
-rwxr-xr-xctrl/facemgr/config/post5
-rwxr-xr-xctrl/facemgr/config/postinst3
-rwxr-xr-xctrl/facemgr/config/prerm3
-rwxr-xr-xctrl/facemgr/config/preun3
-rw-r--r--ctrl/facemgr/examples/mobility/Makefile23
-rw-r--r--ctrl/facemgr/examples/mobility/mobility.c88
-rw-r--r--ctrl/facemgr/src/CMakeLists.txt8
-rw-r--r--ctrl/facemgr/src/api.c96
-rw-r--r--ctrl/facemgr/src/facelet.c6
-rw-r--r--ctrl/facemgr/src/interfaces/android_utility/android_utility.c6
-rw-r--r--ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c28
-rw-r--r--ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c146
-rw-r--r--ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h45
-rw-r--r--ctrl/facemgr/src/main.c2
-rw-r--r--ctrl/libhicnctrl/cmake/Modules/Packaging.cmake4
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h5
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/commands.h97
-rw-r--r--ctrl/libhicnctrl/src/CMakeLists.txt8
-rw-r--r--ctrl/libhicnctrl/src/api.c325
-rw-r--r--ctrl/libhicnctrl/src/hicn_plugin_api.c641
-rw-r--r--ctrl/libhicnctrl/src/hicnctrl.c2
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt2
-rw-r--r--ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt2
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt6
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c6
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c13
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/mainpage.dox48
-rw-r--r--ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c1739
-rw-r--r--ctrl/sysrepo-plugins/yang/hicn/hicn.yang509
-rw-r--r--docs/doxygen/CMakeLists.txt (renamed from lib/doc/CMakeLists.txt)2
-rw-r--r--docs/doxygen/Doxyfile.in (renamed from lib/doc/Doxyfile.in)4
-rw-r--r--docs/source/control.md59
-rw-r--r--docs/source/packethicn.md127
-rw-r--r--docs/source/vpp-plugin.md88
-rw-r--r--extras/libmemif/CMakeLists.txt5
-rw-r--r--extras/libmemif/CMakeLists1.patch3
-rw-r--r--extras/libmemif/CMakeLists2.patch4
-rw-r--r--extras/libmemif/cmake/Modules/Packaging.cmake16
-rw-r--r--extras/packethicn/CMakeLists.txt104
-rw-r--r--extras/packethicn/cmake/Modules/Packaging.cmake31
-rwxr-xr-xextras/packethicn/install_macos.sh45
-rw-r--r--extras/packethicn/packet-hicn.c248
-rw-r--r--hicn-light/CMakeLists.txt4
-rw-r--r--hicn-light/src/hicn/cli/color.c1
-rw-r--r--hicn-light/src/hicn/config/configuration.c27
-rw-r--r--hicn-light/src/hicn/config/configuration.h1
-rw-r--r--hicn-light/src/hicn/core/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/core/fib_entry.c9
-rw-r--r--hicn-light/src/hicn/core/fib_entry.h7
-rw-r--r--hicn-light/src/hicn/core/forwarder.c4
-rw-r--r--hicn-light/src/hicn/core/forwarder.h2
-rw-r--r--hicn-light/src/hicn/core/mapme.h2
-rw-r--r--hicn-light/src/hicn/core/messageHandler.h39
-rw-r--r--hicn-light/src/hicn/core/msgbuf.h6
-rw-r--r--hicn-light/src/hicn/core/nameBitvector.c2
-rw-r--r--hicn-light/src/hicn/core/strategy.h11
-rw-r--r--hicn-light/src/hicn/io/tcp.c1
-rw-r--r--hicn-light/src/hicn/strategies/low_latency.h4
-rw-r--r--hicn-light/src/hicn/utils/CMakeLists.txt3
-rw-r--r--hicn-light/src/hicn/utils/commands.h378
-rw-r--r--hicn-light/src/hicn/utils/utils.h5
-rw-r--r--hicn-plugin/.clang-format21
-rw-r--r--hicn-plugin/cmake/Modules/Packaging.cmake10
-rw-r--r--hicn-plugin/src/CMakeLists.txt84
-rw-r--r--hicn-plugin/src/cache_policies/cs_lru.h9
-rw-r--r--hicn-plugin/src/cache_policies/cs_policy.h16
-rw-r--r--hicn-plugin/src/cli.c586
-rw-r--r--hicn-plugin/src/data_fwd.h28
-rw-r--r--hicn-plugin/src/data_fwd_node.c293
-rw-r--r--hicn-plugin/src/data_input_node.c167
-rw-r--r--hicn-plugin/src/data_pcslookup.h12
-rw-r--r--hicn-plugin/src/data_pcslookup_node.c60
-rw-r--r--hicn-plugin/src/data_push_node.c326
-rw-r--r--hicn-plugin/src/error.h14
-rw-r--r--hicn-plugin/src/face_db.h30
-rw-r--r--hicn-plugin/src/faces/app/address_mgr.c20
-rw-r--r--hicn-plugin/src/faces/app/face_app_cli.c88
-rw-r--r--hicn-plugin/src/faces/app/face_cons.c18
-rw-r--r--hicn-plugin/src/faces/app/face_prod.c317
-rw-r--r--hicn-plugin/src/faces/app/face_prod.h13
-rw-r--r--hicn-plugin/src/faces/app/face_prod_node.c91
-rw-r--r--hicn-plugin/src/faces/face.c434
-rw-r--r--hicn-plugin/src/faces/face.h632
-rw-r--r--hicn-plugin/src/faces/face_cli.c186
-rw-r--r--hicn-plugin/src/faces/face_node.c881
-rw-r--r--hicn-plugin/src/faces/face_node.h52
-rw-r--r--hicn-plugin/src/faces/iface_node.c876
-rw-r--r--hicn-plugin/src/faces/iface_node.h54
-rw-r--r--hicn-plugin/src/faces/inlines.h42
-rw-r--r--hicn-plugin/src/faces/ip/dpo_ip.c90
-rw-r--r--hicn-plugin/src/faces/ip/dpo_ip.h288
-rw-r--r--hicn-plugin/src/faces/ip/face_ip.c571
-rw-r--r--hicn-plugin/src/faces/ip/face_ip.h310
-rw-r--r--hicn-plugin/src/faces/ip/face_ip_cli.c208
-rw-r--r--hicn-plugin/src/faces/ip/face_ip_node.c993
-rw-r--r--hicn-plugin/src/faces/ip/iface_ip_node.c919
-rw-r--r--hicn-plugin/src/faces/udp/dpo_udp.c157
-rw-r--r--hicn-plugin/src/faces/udp/dpo_udp.h289
-rw-r--r--hicn-plugin/src/faces/udp/face_udp.c449
-rw-r--r--hicn-plugin/src/faces/udp/face_udp.h356
-rw-r--r--hicn-plugin/src/faces/udp/face_udp_cli.c164
-rw-r--r--hicn-plugin/src/faces/udp/face_udp_node.c1030
-rw-r--r--hicn-plugin/src/faces/udp/iface_udp_node.c987
-rw-r--r--hicn-plugin/src/hashtb.h73
-rw-r--r--hicn-plugin/src/hicn.api295
-rw-r--r--hicn-plugin/src/hicn.c84
-rw-r--r--hicn-plugin/src/hicn.h16
-rw-r--r--hicn-plugin/src/hicn_api.c797
-rw-r--r--hicn-plugin/src/hicn_api.h8
-rw-r--r--hicn-plugin/src/hicn_api_test.c659
-rw-r--r--hicn-plugin/src/hicn_msg_enum.h3
-rw-r--r--hicn-plugin/src/infra.h19
-rw-r--r--hicn-plugin/src/interest_hitcs.h16
-rw-r--r--hicn-plugin/src/interest_hitcs_node.c69
-rw-r--r--hicn-plugin/src/interest_hitpit.h15
-rw-r--r--hicn-plugin/src/interest_hitpit_node.c53
-rw-r--r--hicn-plugin/src/interest_pcslookup.h11
-rw-r--r--hicn-plugin/src/interest_pcslookup_node.c44
-rw-r--r--hicn-plugin/src/mapme.h125
-rw-r--r--hicn-plugin/src/mapme_ack.h5
-rw-r--r--hicn-plugin/src/mapme_ack_node.c57
-rw-r--r--hicn-plugin/src/mapme_ctrl.h44
-rw-r--r--hicn-plugin/src/mapme_ctrl_node.c161
-rw-r--r--hicn-plugin/src/mapme_eventmgr.c218
-rw-r--r--hicn-plugin/src/mapme_eventmgr.h12
-rw-r--r--hicn-plugin/src/mgmt.h5
-rw-r--r--hicn-plugin/src/params.h10
-rw-r--r--hicn-plugin/src/parser.h21
-rw-r--r--hicn-plugin/src/pcs.c3
-rw-r--r--hicn-plugin/src/pcs.h488
-rw-r--r--hicn-plugin/src/pg.c438
-rw-r--r--hicn-plugin/src/pg.h2
-rw-r--r--hicn-plugin/src/route.c782
-rw-r--r--hicn-plugin/src/route.h98
-rw-r--r--hicn-plugin/src/state.h51
-rw-r--r--hicn-plugin/src/strategies/dpo_mw.c26
-rw-r--r--hicn-plugin/src/strategies/dpo_mw.h12
-rw-r--r--hicn-plugin/src/strategies/dpo_rr.c25
-rw-r--r--hicn-plugin/src/strategies/dpo_rr.h15
-rw-r--r--hicn-plugin/src/strategies/strategy_mw.c51
-rw-r--r--hicn-plugin/src/strategies/strategy_mw.h7
-rw-r--r--hicn-plugin/src/strategies/strategy_mw_cli.c51
-rw-r--r--hicn-plugin/src/strategies/strategy_rr.c47
-rw-r--r--hicn-plugin/src/strategies/strategy_rr.h7
-rw-r--r--hicn-plugin/src/strategy.h32
-rw-r--r--hicn-plugin/src/strategy_dpo_ctx.c17
-rw-r--r--hicn-plugin/src/strategy_dpo_ctx.h64
-rw-r--r--hicn-plugin/src/strategy_dpo_manager.h55
-rw-r--r--hicn-plugin/src/strategy_node.c78
-rw-r--r--hicn-plugin/src/udp_tunnels/udp_decap.h32
-rw-r--r--hicn-plugin/src/udp_tunnels/udp_decap_node.c661
-rw-r--r--hicn-plugin/src/udp_tunnels/udp_tunnel.c281
-rw-r--r--hicn-plugin/src/udp_tunnels/udp_tunnel.h114
-rw-r--r--hicn-plugin/src/utils.h21
-rw-r--r--hicn-plugin/vapi/CMakeLists.txt2
-rw-r--r--hicn-plugin/vapi/vapi_safe.c6
-rw-r--r--lib/.clang-format21
-rw-r--r--lib/CMakeLists.txt1
-rw-r--r--lib/includes/CMakeLists.txt5
-rw-r--r--lib/includes/hicn/base.h36
-rw-r--r--lib/includes/hicn/common.h14
-rw-r--r--lib/includes/hicn/compat.h299
-rw-r--r--lib/includes/hicn/error.h21
-rw-r--r--lib/includes/hicn/face.h1
-rw-r--r--lib/includes/hicn/ops.h38
-rw-r--r--lib/includes/hicn/policy.h10
-rw-r--r--lib/includes/hicn/protocol/tcp.h14
-rw-r--r--lib/includes/hicn/strategy.h36
-rw-r--r--lib/includes/hicn/util/log.h2
-rw-r--r--lib/includes/hicn/util/windows/dlfcn.h33
-rwxr-xr-xlib/includes/hicn/util/windows/windows_utils.h8
-rw-r--r--lib/src/CMakeLists.txt9
-rw-r--r--lib/src/common.c3
-rw-r--r--lib/src/compat.c472
-rw-r--r--lib/src/name.c2
-rw-r--r--lib/src/ops.c2
-rw-r--r--lib/src/protocol/ah.c4
-rw-r--r--lib/src/protocol/icmp.c4
-rw-r--r--lib/src/protocol/ipv4.c16
-rw-r--r--lib/src/protocol/ipv6.c32
-rw-r--r--lib/src/protocol/tcp.c95
-rw-r--r--lib/src/strategy.c39
-rw-r--r--lib/src/util/ip_address.c5
-rw-r--r--lib/src/util/windows/dlfcn.c65
-rw-r--r--libtransport/CMakeLists.txt87
-rw-r--r--libtransport/cmake/Modules/DefaultConfiguration.cmake3
-rw-r--r--libtransport/cmake/Modules/Packaging.cmake8
-rw-r--r--libtransport/includes/hicn/transport/CMakeLists.txt4
-rw-r--r--libtransport/includes/hicn/transport/auth/CMakeLists.txt29
-rw-r--r--libtransport/includes/hicn/transport/auth/common.h (renamed from hicn-plugin/src/faces/ip/iface_ip_node.h)26
-rw-r--r--libtransport/includes/hicn/transport/auth/crypto_hash.h121
-rw-r--r--libtransport/includes/hicn/transport/auth/crypto_hash_type.h (renamed from hicn-plugin/src/faces/udp/iface_udp_node.h)31
-rw-r--r--libtransport/includes/hicn/transport/auth/crypto_hasher.h70
-rw-r--r--libtransport/includes/hicn/transport/auth/crypto_suite.h (renamed from hicn-plugin/src/faces/ip/face_ip_node.h)39
-rw-r--r--libtransport/includes/hicn/transport/auth/identity.h66
-rw-r--r--libtransport/includes/hicn/transport/auth/key_id.h27
-rw-r--r--libtransport/includes/hicn/transport/auth/policies.h33
-rw-r--r--libtransport/includes/hicn/transport/auth/signer.h92
-rw-r--r--libtransport/includes/hicn/transport/auth/verifier.h169
-rw-r--r--libtransport/includes/hicn/transport/core/CMakeLists.txt4
-rw-r--r--libtransport/includes/hicn/transport/core/connector.h212
-rw-r--r--libtransport/includes/hicn/transport/core/connector_stats.h40
-rw-r--r--libtransport/includes/hicn/transport/core/content_object.h50
-rw-r--r--libtransport/includes/hicn/transport/core/endpoint.h80
-rw-r--r--libtransport/includes/hicn/transport/core/global_object_pool.h122
-rw-r--r--libtransport/includes/hicn/transport/core/interest.h78
-rw-r--r--libtransport/includes/hicn/transport/core/io_module.h127
-rw-r--r--libtransport/includes/hicn/transport/core/name.h6
-rw-r--r--libtransport/includes/hicn/transport/core/packet.h142
-rw-r--r--libtransport/includes/hicn/transport/core/payload_type.h3
-rw-r--r--libtransport/includes/hicn/transport/core/prefix.h8
-rw-r--r--libtransport/includes/hicn/transport/errors/errors.h5
-rw-r--r--libtransport/includes/hicn/transport/http/client_connection.h4
-rw-r--r--libtransport/includes/hicn/transport/http/request.h5
-rw-r--r--libtransport/includes/hicn/transport/interfaces/CMakeLists.txt3
-rw-r--r--libtransport/includes/hicn/transport/interfaces/callbacks.h21
-rw-r--r--libtransport/includes/hicn/transport/interfaces/global_conf_interface.h60
-rw-r--r--libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h4
-rw-r--r--libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h5
-rw-r--r--libtransport/includes/hicn/transport/interfaces/portal.h8
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_consumer.h53
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h1
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_options_keys.h12
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_producer.h49
-rw-r--r--libtransport/includes/hicn/transport/interfaces/statistics.h79
-rw-r--r--libtransport/includes/hicn/transport/portability/c_portability.h2
-rw-r--r--libtransport/includes/hicn/transport/portability/platform.h108
-rw-r--r--libtransport/includes/hicn/transport/portability/portability.h2
-rw-r--r--libtransport/includes/hicn/transport/portability/win_portability.h3
-rw-r--r--libtransport/includes/hicn/transport/utils/CMakeLists.txt7
-rw-r--r--libtransport/includes/hicn/transport/utils/conversions.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/enum_iterator.h43
-rw-r--r--libtransport/includes/hicn/transport/utils/event_thread.h126
-rw-r--r--libtransport/includes/hicn/transport/utils/file.h28
-rw-r--r--libtransport/includes/hicn/transport/utils/fixed_block_allocator.h209
-rw-r--r--libtransport/includes/hicn/transport/utils/linux.h4
-rw-r--r--libtransport/includes/hicn/transport/utils/membuf.h32
-rw-r--r--libtransport/includes/hicn/transport/utils/move_wrapper.h (renamed from hicn-plugin/src/faces/udp/face_udp_node.h)36
-rw-r--r--libtransport/includes/hicn/transport/utils/noncopyable.h29
-rw-r--r--libtransport/includes/hicn/transport/utils/object_pool.h25
-rw-r--r--libtransport/includes/hicn/transport/utils/ring_buffer.h1
-rw-r--r--libtransport/includes/hicn/transport/utils/shared_ptr_utils.h28
-rw-r--r--libtransport/includes/hicn/transport/utils/singleton.h39
-rw-r--r--libtransport/includes/hicn/transport/utils/string_utils.h75
-rw-r--r--libtransport/src/CMakeLists.txt41
-rw-r--r--libtransport/src/auth/CMakeLists.txt22
-rw-r--r--libtransport/src/auth/identity.cc116
-rw-r--r--libtransport/src/auth/signer.cc208
-rw-r--r--libtransport/src/auth/verifier.cc335
-rw-r--r--libtransport/src/config.h.in4
-rw-r--r--libtransport/src/core/CMakeLists.txt50
-rw-r--r--libtransport/src/core/content_object.cc45
-rw-r--r--libtransport/src/core/errors.cc49
-rw-r--r--libtransport/src/core/errors.h87
-rw-r--r--libtransport/src/core/facade.h22
-rw-r--r--libtransport/src/core/fec.cc880
-rw-r--r--libtransport/src/core/fec.h65
-rw-r--r--libtransport/src/core/forwarder_interface.h8
-rw-r--r--libtransport/src/core/global_configuration.cc174
-rw-r--r--libtransport/src/core/global_configuration.h102
-rw-r--r--libtransport/src/core/hicn_forwarder_interface.cc2
-rw-r--r--libtransport/src/core/hicn_forwarder_interface.h2
-rw-r--r--libtransport/src/core/hicn_vapi.c45
-rw-r--r--libtransport/src/core/hicn_vapi.h6
-rw-r--r--libtransport/src/core/interest.cc82
-rw-r--r--libtransport/src/core/io_module.cc88
-rw-r--r--libtransport/src/core/local_connector.cc47
-rw-r--r--libtransport/src/core/local_connector.h62
-rw-r--r--libtransport/src/core/manifest.h19
-rw-r--r--libtransport/src/core/manifest_format.h10
-rw-r--r--libtransport/src/core/manifest_format_fixed.cc43
-rw-r--r--libtransport/src/core/manifest_format_fixed.h19
-rw-r--r--libtransport/src/core/manifest_inline.h41
-rw-r--r--libtransport/src/core/memif_connector.cc11
-rw-r--r--libtransport/src/core/memif_connector.h5
-rw-r--r--libtransport/src/core/name.cc10
-rw-r--r--libtransport/src/core/packet.cc371
-rw-r--r--libtransport/src/core/pending_interest.h16
-rw-r--r--libtransport/src/core/portal.cc151
-rw-r--r--libtransport/src/core/portal.h299
-rw-r--r--libtransport/src/core/prefix.cc26
-rw-r--r--libtransport/src/core/rs.cc370
-rw-r--r--libtransport/src/core/rs.h340
-rw-r--r--libtransport/src/core/tcp_socket_connector.cc9
-rw-r--r--libtransport/src/core/tcp_socket_connector.h3
-rw-r--r--libtransport/src/core/test/CMakeLists.txt10
-rw-r--r--libtransport/src/core/vpp_forwarder_interface.cc23
-rw-r--r--libtransport/src/core/vpp_forwarder_interface.h2
-rw-r--r--libtransport/src/http/client_connection.cc31
-rw-r--r--libtransport/src/http/request.cc66
-rw-r--r--libtransport/src/http/response.cc19
-rw-r--r--libtransport/src/implementation/CMakeLists.txt10
-rw-r--r--libtransport/src/implementation/p2psecure_socket_consumer.cc153
-rw-r--r--libtransport/src/implementation/p2psecure_socket_consumer.h20
-rw-r--r--libtransport/src/implementation/p2psecure_socket_producer.cc309
-rw-r--r--libtransport/src/implementation/p2psecure_socket_producer.h61
-rw-r--r--libtransport/src/implementation/socket.cc26
-rw-r--r--libtransport/src/implementation/socket.h52
-rw-r--r--libtransport/src/implementation/socket_consumer.h209
-rw-r--r--libtransport/src/implementation/socket_producer.h642
-rw-r--r--libtransport/src/implementation/tls_rtc_socket_producer.cc33
-rw-r--r--libtransport/src/implementation/tls_rtc_socket_producer.h7
-rw-r--r--libtransport/src/implementation/tls_socket_consumer.cc62
-rw-r--r--libtransport/src/implementation/tls_socket_consumer.h26
-rw-r--r--libtransport/src/implementation/tls_socket_producer.cc323
-rw-r--r--libtransport/src/implementation/tls_socket_producer.h59
-rw-r--r--libtransport/src/interfaces/CMakeLists.txt6
-rw-r--r--libtransport/src/interfaces/global_configuration.cc50
-rw-r--r--libtransport/src/interfaces/p2psecure_socket_consumer.cc11
-rw-r--r--libtransport/src/interfaces/p2psecure_socket_producer.cc3
-rw-r--r--libtransport/src/interfaces/portal.cc37
-rw-r--r--libtransport/src/interfaces/socket_consumer.cc36
-rw-r--r--libtransport/src/interfaces/socket_producer.cc78
-rw-r--r--libtransport/src/interfaces/tls_rtc_socket_producer.cc3
-rw-r--r--libtransport/src/interfaces/tls_rtc_socket_producer.h4
-rw-r--r--libtransport/src/interfaces/tls_socket_consumer.cc3
-rw-r--r--libtransport/src/interfaces/tls_socket_producer.cc3
-rw-r--r--libtransport/src/io_modules/CMakeLists.txt38
-rw-r--r--libtransport/src/io_modules/forwarder/CMakeLists.txt44
-rw-r--r--libtransport/src/io_modules/forwarder/configuration.h89
-rw-r--r--libtransport/src/io_modules/forwarder/errors.cc52
-rw-r--r--libtransport/src/io_modules/forwarder/errors.h91
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder.cc296
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder.h90
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder_module.cc87
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder_module.h70
-rw-r--r--libtransport/src/io_modules/forwarder/global_id_counter.h54
-rw-r--r--libtransport/src/io_modules/forwarder/udp_tunnel.cc288
-rw-r--r--libtransport/src/io_modules/forwarder/udp_tunnel.h147
-rw-r--r--libtransport/src/io_modules/forwarder/udp_tunnel_listener.cc177
-rw-r--r--libtransport/src/io_modules/forwarder/udp_tunnel_listener.h110
-rw-r--r--libtransport/src/io_modules/loopback/CMakeLists.txt34
-rw-r--r--libtransport/src/io_modules/loopback/local_face.cc69
-rw-r--r--libtransport/src/io_modules/loopback/local_face.h54
-rw-r--r--libtransport/src/io_modules/loopback/loopback_module.cc84
-rw-r--r--libtransport/src/io_modules/loopback/loopback_module.h70
-rw-r--r--libtransport/src/io_modules/memif/CMakeLists.txt56
-rw-r--r--libtransport/src/io_modules/memif/hicn_vapi.c229
-rw-r--r--libtransport/src/io_modules/memif/hicn_vapi.h82
-rw-r--r--libtransport/src/io_modules/memif/memif_connector.cc493
-rw-r--r--libtransport/src/io_modules/memif/memif_connector.h130
-rw-r--r--libtransport/src/io_modules/memif/memif_vapi.c127
-rw-r--r--libtransport/src/io_modules/memif/memif_vapi.h54
-rw-r--r--libtransport/src/io_modules/memif/vpp_forwarder_module.cc263
-rw-r--r--libtransport/src/io_modules/memif/vpp_forwarder_module.h83
-rw-r--r--libtransport/src/io_modules/raw_socket/raw_socket_connector.cc201
-rw-r--r--libtransport/src/io_modules/raw_socket/raw_socket_connector.h80
-rw-r--r--libtransport/src/io_modules/raw_socket/raw_socket_interface.cc56
-rw-r--r--libtransport/src/io_modules/raw_socket/raw_socket_interface.h61
-rw-r--r--libtransport/src/io_modules/udp/CMakeLists.txt46
-rw-r--r--libtransport/src/io_modules/udp/hicn_forwarder_module.cc181
-rw-r--r--libtransport/src/io_modules/udp/hicn_forwarder_module.h86
-rw-r--r--libtransport/src/io_modules/udp/udp_socket_connector.cc211
-rw-r--r--libtransport/src/io_modules/udp/udp_socket_connector.h89
-rw-r--r--libtransport/src/protocols/CMakeLists.txt21
-rw-r--r--libtransport/src/protocols/byte_stream_reassembly.cc59
-rw-r--r--libtransport/src/protocols/byte_stream_reassembly.h4
-rw-r--r--libtransport/src/protocols/cbr.cc1
-rw-r--r--libtransport/src/protocols/consumer.conf2
-rw-r--r--libtransport/src/protocols/data_processing_events.h3
-rw-r--r--libtransport/src/protocols/datagram_reassembly.cc4
-rw-r--r--libtransport/src/protocols/datagram_reassembly.h2
-rw-r--r--libtransport/src/protocols/errors.cc4
-rw-r--r--libtransport/src/protocols/fec_base.h86
-rw-r--r--libtransport/src/protocols/incremental_indexer.cc33
-rw-r--r--libtransport/src/protocols/incremental_indexer.h35
-rw-r--r--libtransport/src/protocols/indexer.cc24
-rw-r--r--libtransport/src/protocols/indexer.h16
-rw-r--r--libtransport/src/protocols/manifest_incremental_indexer.cc213
-rw-r--r--libtransport/src/protocols/manifest_incremental_indexer.h39
-rw-r--r--libtransport/src/protocols/prod_protocol_bytestream.cc390
-rw-r--r--libtransport/src/protocols/prod_protocol_bytestream.h72
-rw-r--r--libtransport/src/protocols/prod_protocol_rtc.cc481
-rw-r--r--libtransport/src/protocols/prod_protocol_rtc.h127
-rw-r--r--libtransport/src/protocols/production_protocol.cc135
-rw-r--r--libtransport/src/protocols/production_protocol.h108
-rw-r--r--libtransport/src/protocols/protocol.cc34
-rw-r--r--libtransport/src/protocols/protocol.h7
-rw-r--r--libtransport/src/protocols/raaqm.cc82
-rw-r--r--libtransport/src/protocols/raaqm.h18
-rw-r--r--libtransport/src/protocols/raaqm_data_path.cc1
-rw-r--r--libtransport/src/protocols/raaqm_data_path.h1
-rw-r--r--libtransport/src/protocols/rate_estimation.cc1
-rw-r--r--libtransport/src/protocols/rate_estimation.h1
-rw-r--r--libtransport/src/protocols/reassembly.cc1
-rw-r--r--libtransport/src/protocols/reassembly.h2
-rw-r--r--libtransport/src/protocols/rtc.cc52
-rw-r--r--libtransport/src/protocols/rtc.h5
-rw-r--r--libtransport/src/protocols/rtc/CMakeLists.txt38
-rw-r--r--libtransport/src/protocols/rtc/congestion_detection.cc101
-rw-r--r--libtransport/src/protocols/rtc/congestion_detection.h138
-rw-r--r--libtransport/src/protocols/rtc/probe_handler.cc107
-rw-r--r--libtransport/src/protocols/rtc/probe_handler.h75
-rw-r--r--libtransport/src/protocols/rtc/rtc.cc607
-rw-r--r--libtransport/src/protocols/rtc/rtc.h113
-rw-r--r--libtransport/src/protocols/rtc/rtc_consts.h121
-rw-r--r--libtransport/src/protocols/rtc/rtc_data_path.cc197
-rw-r--r--libtransport/src/protocols/rtc/rtc_data_path.h97
-rw-r--r--libtransport/src/protocols/rtc/rtc_ldr.cc427
-rw-r--r--libtransport/src/protocols/rtc/rtc_ldr.h108
-rw-r--r--libtransport/src/protocols/rtc/rtc_packet.h93
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc.h58
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_frame.cc79
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_frame.h46
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_queue.cc106
-rw-r--r--libtransport/src/protocols/rtc/rtc_rc_queue.h47
-rw-r--r--libtransport/src/protocols/rtc/rtc_state.cc560
-rw-r--r--libtransport/src/protocols/rtc/rtc_state.h253
-rw-r--r--libtransport/src/protocols/rtc/trendline_estimator.cc334
-rw-r--r--libtransport/src/protocols/rtc/trendline_estimator.h147
-rw-r--r--libtransport/src/protocols/test/CMakeLists.txt10
-rw-r--r--libtransport/src/protocols/transport_protocol.cc132
-rw-r--r--libtransport/src/protocols/transport_protocol.h104
-rw-r--r--libtransport/src/security/verifier.cc1
-rw-r--r--libtransport/src/test/CMakeLists.txt39
-rw-r--r--libtransport/src/test/fec_reed_solomon.cc154
-rw-r--r--libtransport/src/test/fec_rely.cc156
-rw-r--r--libtransport/src/test/packet_samples.h58
-rw-r--r--libtransport/src/test/test_auth.cc110
-rw-r--r--libtransport/src/test/test_consumer_producer_rtc.cc176
-rw-r--r--libtransport/src/test/test_core_manifest.cc (renamed from libtransport/src/core/test/test_core_manifest.cc)146
-rw-r--r--libtransport/src/test/test_event_thread.cc106
-rw-r--r--libtransport/src/test/test_fec_reedsolomon.cc291
-rw-r--r--libtransport/src/test/test_interest.cc267
-rw-r--r--libtransport/src/test/test_packet.cc1047
-rw-r--r--libtransport/src/test/test_transport_producer.cc (renamed from libtransport/src/protocols/test/test_transport_producer.cc)26
-rw-r--r--libtransport/src/transport.config27
-rw-r--r--libtransport/src/utils/CMakeLists.txt1
-rw-r--r--libtransport/src/utils/content_store.cc4
-rw-r--r--libtransport/src/utils/content_store.h2
-rw-r--r--libtransport/src/utils/daemonizator.cc1
-rw-r--r--libtransport/src/utils/epoll_event_reactor.cc12
-rw-r--r--libtransport/src/utils/epoll_event_reactor.h2
-rw-r--r--libtransport/src/utils/event_thread.h99
-rw-r--r--libtransport/src/utils/fd_deadline_timer.h6
-rw-r--r--libtransport/src/utils/membuf.cc44
-rw-r--r--libtransport/src/utils/memory_pool_allocator.h2
-rw-r--r--libtransport/src/utils/min_filter.h5
-rw-r--r--scripts/build-packages.sh12
-rw-r--r--scripts/functions.sh10
-rw-r--r--telemetry/vpp-collectd/CMakeLists.txt2
-rw-r--r--telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt9
-rw-r--r--telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c30
-rw-r--r--telemetry/vpp-collectd/vpp/CMakeLists.txt22
-rw-r--r--telemetry/vpp-collectd/vpp/vpp.c58
-rw-r--r--utils/.clang-format14
-rw-r--r--utils/CMakeLists.txt4
-rw-r--r--utils/src/hiperf.cc643
-rw-r--r--utils/src/ping_client.cc55
-rw-r--r--utils/src/ping_server.cc33
488 files changed, 33569 insertions, 17786 deletions
diff --git a/.gitignore b/.gitignore
index 869c74668..79be94a51 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
build*
.ccls-cache/
compile_commands.json
-.vscode \ No newline at end of file
+.vscode
+.DS_Store \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 194084de8..61d0fb295 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,10 +19,6 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules")
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
-# Enable gtests (`make test`)
-# `make test ARGS="-V"` can be used for verbose output
-enable_testing()
-
## Enabled components
option(BUILD_LIBHICN "Build the hicn core library" ON)
option(BUILD_HICNLIGHT "Build the hicn light forwarder" ON)
@@ -40,6 +36,7 @@ option(BUILD_HICNPLUGIN "Build the hicn vpp plugin" OFF)
option(BUILD_SYSREPOPLUGIN "Build the sysrepo plugin" OFF)
option(BUILD_EXTRAS "Build external projects" OFF)
option(BUILD_TELEMETRY "Build telemetry projects" OFF)
+option(BUILD_TESTS "Build unit tests" OFF)
option(DISABLE_EXECUTABLES "Disable executables" OFF)
if ((BUILD_APPS OR BUILD_UTILS) AND NOT BUILD_LIBTRANSPORT)
@@ -84,6 +81,7 @@ set(BUILD_UTILS_DIR utils)
set(BUILD_APPS_DIR apps)
set(BUILD_CTRL_DIR ctrl)
set(BUILD_HICNPLUGIN_DIR hicn-plugin)
+set(BUILD_SYSREPOPLUGIN_DIR ctrl/sysrepo-plugins)
set(BUILD_EXTRAS_DIR extras/)
set(BUILD_TELEMETRY_DIR telemetry)
@@ -100,11 +98,25 @@ if (NOT WIN32)
add_compile_options(-Wall -Werror -Wno-shorten-64-to-32)
endif ()
+# Add unit tests
+if (BUILD_TESTS)
+ message(STATUS "Tests enabled.")
+ include (GTestImport)
+
+ if(${CMAKE_VERSION} VERSION_GREATER "3.10.0")
+ include (GoogleTest)
+ else()
+ include (CTest)
+ endif()
+endif()
+
message(STATUS "Building the following subprojects: ${subdirs}")
foreach(dir ${subdirs})
add_subdirectory(${dir})
endforeach()
+add_subdirectory(docs/doxygen)
+
include(Packager)
-make_packages()
+make_packages() \ No newline at end of file
diff --git a/apps/.clang-format b/apps/.clang-format
new file mode 100644
index 000000000..cd21e2017
--- /dev/null
+++ b/apps/.clang-format
@@ -0,0 +1,14 @@
+# Copyright (c) 2017-2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+BasedOnStyle: Google
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index f5075a7aa..37e44f9e7 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -29,15 +29,19 @@ set(HICN_APPS hicn-apps CACHE INTERNAL "" FORCE)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
find_package(Libtransport REQUIRED)
+ find_package(hicnctrl REQUIRED)
find_package(Threads REQUIRED)
- include_directories(${LIBTRANSPORT_INCLUDE_DIRS})
else()
- if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
+ if (DISABLE_SHARED_LIBRARIES)
find_package(OpenSSL REQUIRED)
- find_package(ZLIB REQUIRED)
+ if (NOT WIN32)
+ find_package(ZLIB REQUIRED)
+ endif ()
set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_STATIC})
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_STATIC})
else ()
set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_SHARED})
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_SHARED})
endif ()
list(APPEND DEPENDENCIES
@@ -45,21 +49,19 @@ else()
)
endif()
-set(SUFFIX "")
-if (${LIBTRANSPORT_LIBRARIES} MATCHES ".*-memif.*")
- set(DEPENDENCIES ${LIBMEMIF_SHARED})
- set(SUFFIX "-memif")
+# Worksroung for unresolved symbols in vpp libraries
+if(${CMAKE_SYSTEM_NAME} MATCHES Linux)
set(LINK_FLAGS "-Wl,-unresolved-symbols=ignore-in-shared-libs")
endif()
-set(HICN_APPS "${HICN_APPS}${SUFFIX}")
-
list(APPEND LIBRARIES
${LIBTRANSPORT_LIBRARIES}
+ ${LIBHICNCTRL_LIBRARIES}
${OPENSSL_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
+set(APPS_LIBRARY_LIST "${OPENSSL_LIBRARIES};${CMAKE_THREAD_LIBS_INIT}" CACHE INTERNAL "APPS_LIBRARY_LIST")
if (WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4200 /wd4996")
endif ()
@@ -68,6 +70,7 @@ include(Packaging)
set(HIGET higet)
set(HTTP_PROXY hicn-http-proxy)
-
-add_subdirectory(http-proxy)
+if (NOT WIN32)
+ add_subdirectory(http-proxy)
+endif ()
add_subdirectory(higet)
diff --git a/apps/cmake/Modules/Packaging.cmake b/apps/cmake/Modules/Packaging.cmake
index 6a6e34777..9b3fa2e72 100644
--- a/apps/cmake/Modules/Packaging.cmake
+++ b/apps/cmake/Modules/Packaging.cmake
@@ -22,7 +22,17 @@ set(${HICN_APPS}_DEB_DEPENDENCIES
CACHE STRING "Dependencies for deb/rpm package."
)
+set(${HICN_APPS}-dev_DEB_DEPENDENCIES
+ "lib${LIBTRANSPORT}-dev (>= stable_version)"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
+
set(${HICN_APPS}_RPM_DEPENDENCIES
"lib${LIBTRANSPORT} >= stable_version"
CACHE STRING "Dependencies for deb/rpm package."
+)
+
+set(${HICN_APPS}-dev_RPM_DEPENDENCIES
+ "lib${LIBTRANSPORT}-devel >= stable_version"
+ CACHE STRING "Dependencies for deb/rpm package."
) \ No newline at end of file
diff --git a/apps/higet/CMakeLists.txt b/apps/higet/CMakeLists.txt
index 1cf14c287..b929a24e4 100644
--- a/apps/higet/CMakeLists.txt
+++ b/apps/higet/CMakeLists.txt
@@ -31,6 +31,10 @@ list(APPEND APPS_SRC
higet.cc
)
+if (WIN32)
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\"" )
+endif()
+
if (NOT DISABLE_EXECUTABLES)
build_executable(${HIGET}
SOURCES ${APPS_SRC}
diff --git a/apps/higet/higet.cc b/apps/higet/higet.cc
index 2aa42e460..9ae869731 100644
--- a/apps/higet/higet.cc
+++ b/apps/higet/higet.cc
@@ -14,12 +14,12 @@
*/
#include <hicn/transport/http/client_connection.h>
+
+#include <algorithm>
#include <fstream>
+#include <functional>
#include <map>
-#include <experimental/algorithm>
-#include <experimental/functional>
-
#define ASIO_STANDALONE
#include <asio.hpp>
#undef ASIO_STANDALONE
@@ -114,15 +114,12 @@ class ReadBytesCallbackImplementation
// read next chunk size
const char *begin = (const char *)payload->data();
const char *end = (const char *)payload->tail();
-
- using std::experimental::make_boyer_moore_searcher;
- auto it = std::experimental::search(
- begin, end,
- make_boyer_moore_searcher(chunk_separator.begin(),
- chunk_separator.end()));
+ const char *begincrlf2 = (const char *)chunk_separator.c_str();
+ const char *endcrlf2 = begincrlf2 + chunk_separator.size();
+ auto it = std::search(begin, end, begincrlf2, endcrlf2);
if (it != end) {
chunk_size_ = std::stoul(begin, 0, 16);
- content_size_ += chunk_size_;
+ content_size_ += (long)chunk_size_;
payload->trimStart(it + chunk_separator.size() - begin);
std::size_t to_write;
@@ -134,7 +131,7 @@ class ReadBytesCallbackImplementation
}
out_->write((char *)payload->data(), to_write);
- byte_downloaded_ += to_write;
+ byte_downloaded_ += (long)to_write;
payload->trimStart(to_write);
if (payload->length() >= chunk_separator.size()) {
@@ -144,7 +141,7 @@ class ReadBytesCallbackImplementation
}
} else {
out_->write((char *)payload->data(), payload->length());
- byte_downloaded_ += payload->length();
+ byte_downloaded_ += (long)payload->length();
}
if (file_name_ != "-") {
@@ -200,12 +197,18 @@ class ReadBytesCallbackImplementation
void print_bar(long value, long max_value, bool last) {
float progress = (float)value / max_value;
+#ifdef _WIN32
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
+ int barWidth = csbi.srWindow.Right - csbi.srWindow.Left + 7;
+#else
struct winsize size;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &size);
int barWidth = size.ws_col - 8;
+#endif
std::cout << "[";
- int pos = barWidth * progress;
+ int pos = barWidth * (int)progress;
for (int i = 0; i < barWidth; ++i) {
if (i < pos) {
std::cout << "=";
@@ -252,7 +255,7 @@ long checkFileStatus(std::string file_name) {
void usage(char *program_name) {
std::cerr << "usage:" << std::endl;
std::cerr << program_name << " [option]... [url]..." << std::endl;
- std::cerr << program_name << "options:" << std::endl;
+ std::cerr << program_name << " options:" << std::endl;
std::cerr
<< "-O <out_put_path> = write documents to <out_put_file>"
<< std::endl;
@@ -303,8 +306,11 @@ int main(int argc, char **argv) {
}
}
- name = argv[optind];
+ if (!argv[optind]) {
+ usage(argv[0]);
+ }
+ name = argv[optind];
std::cerr << "Using name " << name << " and name first word "
<< conf.ipv6_first_word << std::endl;
@@ -329,9 +335,14 @@ int main(int argc, char **argv) {
{"Connection", "Keep-Alive"},
{"Range", range}};
}
+
transport::http::HTTPClientConnection connection;
+
if (!conf.producer_certificate.empty()) {
- connection.setCertificate(conf.producer_certificate);
+ std::shared_ptr<transport::auth::Verifier> verifier =
+ std::make_shared<transport::auth::AsymmetricVerifier>(
+ conf.producer_certificate);
+ connection.setVerifier(verifier);
}
t1 = std::chrono::system_clock::now();
diff --git a/apps/http-proxy/CMakeLists.txt b/apps/http-proxy/CMakeLists.txt
index d6681097c..8c2043c30 100644
--- a/apps/http-proxy/CMakeLists.txt
+++ b/apps/http-proxy/CMakeLists.txt
@@ -14,6 +14,18 @@
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
set(CMAKE_CXX_STANDARD 14)
+# -Wno-c99-designator issue
+#
+# Unsure about version for which this was introduced
+# clang version 9.0.8 (no flag), 11.0.5 (ndk22, flag)
+if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+ EXECUTE_PROCESS( COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE clang_full_version_string )
+ string (REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string})
+ if (CLANG_VERSION_STRING VERSION_GREATER_EQUAL 11)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c99-designator")
+ endif()
+endif()
+
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${CMAKE_SOURCE_DIR}/cmake/Modules/"
@@ -24,39 +36,36 @@ if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif ()
-include_directories(
- SYSTEM
- ${CMAKE_BINARY_DIR}
- ${LIB${TRANSPORT_LIBRARY}_INCLUDE_DIR}
-)
-
set(LIB_SOURCE_FILES
- src/ATSConnector.cc
- src/HTTP1.xMessageFastParser.cc
- src/IcnReceiver.cc
-)
-
-set(LIB_SERVER_HEADER_FILES
- src/IcnReceiver.h
- src/ATSConnector.h
- src/HTTP1.xMessageFastParser.h
+ src/http_session.cc
+ src/http_proxy.cc
+ src/http_1x_message_fast_parser.cc
+ src/icn_receiver.cc
+ src/forwarder_interface.cc
)
set(APP_SOURCE_FILES
main.cc
)
+add_subdirectory(includes/hicn/http-proxy)
set(LIBHTTP_PROXY hicnhttpproxy)
set(LIBHTTP_PROXY_STATIC ${LIBHTTP_PROXY}.static)
+list(APPEND COMPILER_DEFINITIONS
+ -DWITH_POLICY
+)
+
build_library(${LIBHTTP_PROXY}
STATIC
SOURCES ${LIB_SOURCE_FILES}
LINK_LIBRARIES ${LIBRARIES}
DEPENDS ${DEPENDENCIES}
- INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS}
+ INSTALL_HEADERS ${LIBPROXY_TO_INSTALL_HEADER_FILES}
+ INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBHICNCTRL_INCLUDE_DIRS} ${LIBPROXY_INCLUDE_DIRS}
COMPONENT ${HICN_APPS}
LINK_FLAGS ${LINK_FLAGS}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
)
if (NOT DISABLE_EXECUTABLES)
diff --git a/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt b/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt
new file mode 100644
index 000000000..75cbbd64b
--- /dev/null
+++ b/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt
@@ -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.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/forwarder_config.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/forwarder_interface.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/http_proxy.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/http_session.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/http_1x_message_fast_parser.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/icn_receiver.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/utils.h
+)
+
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
+
+set(LIBPROXY_INCLUDE_DIRS
+ ${CMAKE_CURRENT_SOURCE_DIR}/../.. ""
+ CACHE INTERNAL
+ "" FORCE
+)
+
+set(LIBPROXY_TO_INSTALL_HEADER_FILES
+ ${HEADER_FILES} ""
+ CACHE INTERNAL
+ "" FORCE
+)
+
diff --git a/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h b/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h
new file mode 100644
index 000000000..19c96a9e3
--- /dev/null
+++ b/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/portability/c_portability.h>
+#include <hicn/transport/utils/branch_prediction.h>
+#include <hicn/transport/utils/log.h>
+#include <hicn/transport/utils/string_utils.h>
+
+#include <asio.hpp>
+#include <chrono>
+#include <sstream>
+#include <string>
+
+#include "forwarder_interface.h"
+
+
+#define RETRY_INTERVAL 300
+
+namespace transport {
+
+static constexpr char server_header[] = "server";
+static constexpr char prefix_header[] = "prefix";
+static constexpr char port_header[] = "port";
+
+using OnForwarderConfiguredCallback = std::function<void(bool)>;
+
+class ForwarderConfig {
+ public:
+ using ListenerRetrievedCallback = std::function<void(std::error_code)>;
+
+ template <typename Callback>
+ ForwarderConfig(asio::io_service& io_service, Callback&& callback)
+ : forwarder_interface_(io_service),
+ resolver_(io_service),
+ retx_count_(0),
+ timer_(io_service),
+ hicn_listen_port_(~0),
+ listener_retrieved_callback_(std::forward<Callback>(callback)) {}
+
+ void close() {
+ timer_.cancel();
+ resolver_.cancel();
+ forwarder_interface_.close();
+ }
+
+ void tryToConnectToForwarder() {
+ doTryToConnectToForwarder(std::make_error_code(std::errc(0)));
+ }
+
+ void doTryToConnectToForwarder(std::error_code ec) {
+ if (!ec) {
+ // ec == 0 --> timer expired
+ int ret = forwarder_interface_.connectToForwarder();
+ if (ret < 0) {
+ // We were not able to connect to the local forwarder. Do not give up
+ // and retry.
+ TRANSPORT_LOGE("Could not connect to local forwarder. Retrying.");
+
+ timer_.expires_from_now(std::chrono::milliseconds(RETRY_INTERVAL));
+ timer_.async_wait(std::bind(&ForwarderConfig::doTryToConnectToForwarder,
+ this, std::placeholders::_1));
+ } else {
+ timer_.cancel();
+ retx_count_ = 0;
+ doGetMainListener(std::make_error_code(std::errc(0)));
+ }
+ } else {
+ TRANSPORT_LOGD("Timer for re-trying forwarder connection canceled.");
+ }
+ }
+
+ void doGetMainListener(std::error_code ec) {
+ if (!ec) {
+ // ec == 0 --> timer expired
+ int ret = forwarder_interface_.getMainListenerPort();
+ if (ret <= 0) {
+ // Since without the main listener of the forwarder the proxy cannot
+ // work, we can stop the program here until we get the listener port.
+ TRANSPORT_LOGE(
+ "Could not retrieve main listener port from the forwarder. "
+ "Retrying.");
+
+ timer_.expires_from_now(std::chrono::milliseconds(RETRY_INTERVAL));
+ timer_.async_wait(std::bind(&ForwarderConfig::doGetMainListener, this,
+ std::placeholders::_1));
+ } else {
+ timer_.cancel();
+ retx_count_ = 0;
+ hicn_listen_port_ = uint16_t(ret);
+ listener_retrieved_callback_(std::make_error_code(std::errc(0)));
+ }
+ } else {
+ TRANSPORT_LOGI("Timer for retrieving main hicn listener canceled.");
+ }
+ }
+
+ template <typename Callback>
+ TRANSPORT_ALWAYS_INLINE bool parseHicnHeader(std::string& header,
+ Callback&& callback) {
+ std::stringstream ss(header);
+ route_info_t* ret = new route_info_t();
+ std::string port_string;
+
+ while (ss.good()) {
+ std::string substr;
+ getline(ss, substr, ',');
+
+ if (TRANSPORT_EXPECT_FALSE(substr.empty())) {
+ continue;
+ }
+
+ utils::trim(substr);
+ auto it = std::find_if(substr.begin(), substr.end(),
+ [](int ch) { return ch == '='; });
+ if (it != std::end(substr)) {
+ auto key = std::string(substr.begin(), it);
+ auto value = std::string(it + 1, substr.end());
+
+ if (key == server_header) {
+ ret->remote_addr = value;
+ } else if (key == prefix_header) {
+ auto it = std::find_if(value.begin(), value.end(),
+ [](int ch) { return ch == '/'; });
+
+ if (it != std::end(value)) {
+ ret->route_addr = std::string(value.begin(), it);
+ ret->route_len = std::stoul(std::string(it + 1, value.end()));
+ } else {
+ return false;
+ }
+ } else if (key == port_header) {
+ ret->remote_port = std::stoul(value);
+ port_string = value;
+ } else {
+ // Header not recognized
+ return false;
+ }
+ }
+ }
+
+ /*
+ * Resolve server address
+ */
+ auto results =
+ resolver_.resolve({ret->remote_addr, port_string,
+ asio::ip::resolver_query_base::numeric_service});
+
+#if ((ASIO_VERSION / 100 % 1000) < 12)
+ asio::ip::udp::resolver::iterator end;
+ auto& it = results;
+ while (it != end) {
+#else
+ for (auto it = results.begin(); it != results.end(); it++) {
+#endif
+ if (it->endpoint().address().is_v4()) {
+ // Use this v4 address to configure the forwarder.
+ ret->remote_addr = it->endpoint().address().to_string();
+ ret->family = AF_INET;
+ std::string _prefix = ret->route_addr;
+ forwarder_interface_.createFaceAndRoute(
+ RouteInfoPtr(ret), [callback = std::forward<Callback>(callback),
+ configured_prefix = std::move(_prefix)](
+ uint32_t route_id, bool result) {
+ callback(result, configured_prefix);
+ });
+
+ return true;
+ }
+#if ((ASIO_VERSION / 100 % 1000) < 12)
+ it++;
+#endif
+ }
+
+ return false;
+ }
+
+ private:
+ ForwarderInterface forwarder_interface_;
+ asio::ip::udp::resolver resolver_;
+ std::uint32_t retx_count_;
+ asio::steady_timer timer_;
+ uint16_t hicn_listen_port_;
+ ListenerRetrievedCallback listener_retrieved_callback_;
+}; // namespace transport
+
+} // namespace transport \ No newline at end of file
diff --git a/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h b/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h
new file mode 100644
index 000000000..54941a4ba
--- /dev/null
+++ b/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+extern "C" {
+#include <hicn/ctrl/api.h>
+#include <hicn/util/ip_address.h>
+}
+
+#ifndef ASIO_STANDALONE
+#define ASIO_STANDALONE 1
+#endif
+#include <asio.hpp>
+#include <asio/steady_timer.hpp>
+#include <functional>
+#include <thread>
+#include <unordered_map>
+
+namespace transport {
+
+typedef std::function<void(uint32_t, bool)> SetRouteCallback;
+
+struct route_info_t {
+ int family;
+ std::string remote_addr;
+ uint16_t remote_port;
+ std::string route_addr;
+ uint8_t route_len;
+};
+
+using RouteInfoPtr = std::shared_ptr<route_info_t>;
+
+class ForwarderInterface {
+ public:
+ ForwarderInterface(asio::io_service &io_service)
+ : external_ioservice_(io_service),
+ work_(std::make_unique<asio::io_service::work>(internal_ioservice_)),
+ sock_(nullptr),
+ thread_(std::make_unique<std::thread>(
+ [this]() { internal_ioservice_.run(); })),
+ check_routes_timer_(nullptr),
+ pending_add_route_counter_(0),
+ route_id_(0),
+ closed_(false) {}
+
+ ~ForwarderInterface();
+
+ int connectToForwarder();
+
+ void removeConnectedUserNow(uint32_t route_id);
+
+ // to be called at the server
+ // at the client this creates a race condition
+ // and the program enters in a loop
+ void scheduleRemoveConnectedUser(uint32_t route_id);
+
+ template <typename Callback>
+ void createFaceAndRoute(RouteInfoPtr &&route_info, Callback &&callback) {
+ internal_ioservice_.post([this, _route_info = std::move(route_info),
+ _callback = std::forward<Callback>(callback)]() {
+ pending_add_route_counter_++;
+ uint8_t max_try = 5;
+ auto timer = new asio::steady_timer(internal_ioservice_);
+ internalCreateFaceAndRoute(std::move(_route_info), max_try, timer,
+ std::move(_callback));
+ });
+ }
+
+ int32_t getMainListenerPort();
+
+ void close();
+
+ private:
+ void internalRemoveConnectedUser(uint32_t route_id);
+
+ void internalCreateFaceAndRoute(RouteInfoPtr route_info, uint8_t max_try,
+ asio::steady_timer *timer,
+ SetRouteCallback callback);
+
+ int tryToCreateFaceAndRoute(route_info_t *route_info);
+
+ asio::io_service &external_ioservice_;
+ asio::io_service internal_ioservice_;
+ std::unique_ptr<asio::io_service::work> work_;
+ hc_sock_t *sock_;
+ std::unique_ptr<std::thread> thread_;
+ std::unordered_map<uint32_t, RouteInfoPtr> route_status_;
+ std::unique_ptr<asio::steady_timer> check_routes_timer_;
+ uint32_t pending_add_route_counter_;
+ uint32_t route_id_;
+ bool closed_;
+};
+
+} // namespace transport
diff --git a/apps/http-proxy/src/HTTP1.xMessageFastParser.h b/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h
index 79dbce19d..7c035c83b 100644
--- a/apps/http-proxy/src/HTTP1.xMessageFastParser.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h
@@ -15,16 +15,43 @@
#pragma once
+#include <hicn/transport/http/message.h>
+
#include <algorithm>
#include <string>
-#include <hicn/transport/http/message.h>
-
using transport::http::HTTPHeaders;
+namespace transport {
+struct Metadata;
+}
+
class HTTPMessageFastParser {
public:
- static HTTPHeaders getHeaders(const uint8_t* headers, std::size_t length);
+ static constexpr char http_ok[] =
+ "HTTP/1.1 200 OK\r\n"
+ "Access-Control-Allow-Origin: *\r\n"
+ "Connection: close\r\n"
+ "Content-Length: 0\r\n\r\n";
+
+ static constexpr char http_cors[] =
+ "HTTP/1.1 200 OK\r\n"
+ "Date: %s\r\n"
+ "Connection: close\r\n"
+ "Content-Length: 0\r\n"
+ "Access-Control-Allow-Origin: *\r\n"
+ "Access-Control-Allow-Methods: GET\r\n"
+ "Access-Control-Allow-Headers: hicn\r\n"
+ "Access-Control-Max-Age: 1800\r\n\r\n";
+
+ static constexpr char http_failed[] =
+ "HTTP/1.1 500 Internal Server Error\r\n"
+ "Date: %s\r\n"
+ "Content-Length: 0\r\nConnection: "
+ "close\r\n\r\n";
+
+ static void getHeaders(const uint8_t* headers, std::size_t length,
+ bool request, transport::Metadata* metadata);
static std::size_t hasBody(const uint8_t* headers, std::size_t length);
static bool isMpdRequest(const uint8_t* headers, std::size_t length);
static uint32_t parseCacheControl(const uint8_t* headers, std::size_t length);
diff --git a/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h b/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h
new file mode 100644
index 000000000..a4139a620
--- /dev/null
+++ b/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/interfaces/socket_consumer.h>
+#include <hicn/transport/utils/event_thread.h>
+
+#include "forwarder_config.h"
+#include "http_session.h"
+#include "icn_receiver.h"
+
+#define ASIO_STANDALONE
+#include <asio.hpp>
+#include <asio/version.hpp>
+#include <unordered_set>
+
+class TcpListener {
+ public:
+ using AcceptCallback = std::function<void(asio::ip::tcp::socket&&)>;
+
+ TcpListener(asio::io_service& io_service, short port, AcceptCallback callback)
+ : acceptor_(io_service),
+#if ((ASIO_VERSION / 100 % 1000) < 12)
+ socket_(io_service),
+#endif
+ callback_(callback) {
+ acceptor_.open(asio::ip::tcp::v4());
+ typedef asio::detail::socket_option::boolean<SOL_SOCKET, SO_REUSEPORT>
+ reuse_port;
+ acceptor_.set_option(reuse_port(true));
+ acceptor_.bind(asio::ip::tcp::endpoint(
+ asio::ip::address::from_string("127.0.0.1"), port));
+ acceptor_.listen();
+ }
+
+ public:
+ void doAccept() {
+#if ((ASIO_VERSION / 100 % 1000) >= 12)
+ acceptor_.async_accept(
+ [this](std::error_code ec, asio::ip::tcp::socket socket) {
+#else
+ acceptor_.async_accept(socket_, [this](std::error_code ec) {
+ auto socket = std::move(socket_);
+#endif
+ if (!ec) {
+ callback_(std::move(socket));
+ doAccept();
+ }
+ });
+ }
+
+ void stop() { acceptor_.close(); }
+
+ asio::ip::tcp::acceptor acceptor_;
+#if ((ASIO_VERSION / 100 % 1000) < 12)
+ asio::ip::tcp::socket socket_;
+#endif
+ AcceptCallback callback_;
+};
+
+namespace transport {
+
+class HTTPClientConnectionCallback;
+
+class Receiver {
+ public:
+ Receiver() : thread_() {}
+ virtual ~Receiver() = default;
+ void stopAndJoinThread() { thread_.stop(); }
+ virtual void stop() = 0;
+
+ protected:
+ utils::EventThread thread_;
+};
+
+class TcpReceiver : public Receiver {
+ friend class HTTPClientConnectionCallback;
+
+ public:
+ TcpReceiver(std::uint16_t port, const std::string& prefix,
+ const std::string& ipv6_first_word);
+
+ void stop() override;
+
+ private:
+ void onNewConnection(asio::ip::tcp::socket&& socket);
+ void onClientDisconnect(HTTPClientConnectionCallback* client);
+
+ template <typename Callback>
+ void parseHicnHeader(std::string& hicn_header, Callback&& callback) {
+ forwarder_config_.parseHicnHeader(hicn_header,
+ std::forward<Callback>(callback));
+ }
+
+ TcpListener listener_;
+ std::string prefix_;
+ std::string ipv6_first_word_;
+ std::string prefix_hash_;
+ std::deque<HTTPClientConnectionCallback*> http_clients_;
+ std::unordered_set<HTTPClientConnectionCallback*> used_http_clients_;
+ ForwarderConfig forwarder_config_;
+ bool stopped_;
+};
+
+class IcnReceiver : public Receiver {
+ public:
+ template <typename... Args>
+ IcnReceiver(Args&&... args)
+ : Receiver(),
+ icn_consum_producer_(thread_.getIoService(),
+ std::forward<Args>(args)...) {
+ icn_consum_producer_.run();
+ }
+
+ void stop() override {
+ thread_.add([this]() {
+ /* Stop the listener */
+ icn_consum_producer_.stop();
+ });
+ }
+
+ private:
+ AsyncConsumerProducer icn_consum_producer_;
+};
+
+class HTTPProxy {
+ public:
+ enum Server { CREATE };
+ enum Client { WRAP_BUFFER };
+
+ struct CommonParams {
+ std::string prefix;
+ std::string first_ipv6_word;
+
+ virtual void printParams() { std::cout << "Parameters: " << std::endl; };
+ };
+
+ struct ClientParams : virtual CommonParams {
+ short tcp_listen_port;
+ void printParams() override {
+ std::cout << "Running HTTP/TCP -> HTTP/hICN proxy." << std::endl;
+ CommonParams::printParams();
+ std::cout << "\t"
+ << "HTTP listen port: " << tcp_listen_port << std::endl;
+ std::cout << "\t"
+ << "Consumer Prefix: " << prefix << std::endl;
+ std::cout << "\t"
+ << "Prefix first word: " << first_ipv6_word << std::endl;
+ }
+ };
+
+ struct ServerParams : virtual CommonParams {
+ std::string origin_address;
+ std::string origin_port;
+ std::string cache_size;
+ std::string mtu;
+ std::string content_lifetime;
+ bool manifest;
+
+ void printParams() override {
+ std::cout << "Running HTTP/hICN -> HTTP/TCP proxy." << std::endl;
+ CommonParams::printParams();
+ std::cout << "\t"
+ << "Origin address: " << origin_address << std::endl;
+ std::cout << "\t"
+ << "Origin port: " << origin_port << std::endl;
+ std::cout << "\t"
+ << "Producer cache size: " << cache_size << std::endl;
+ std::cout << "\t"
+ << "hICN MTU: " << mtu << std::endl;
+ std::cout << "\t"
+ << "Default content lifetime: " << content_lifetime
+ << std::endl;
+ std::cout << "\t"
+ << "Producer Prefix: " << prefix << std::endl;
+ std::cout << "\t"
+ << "Prefix first word: " << first_ipv6_word << std::endl;
+ std::cout << "\t"
+ << "Use manifest: " << manifest << std::endl;
+ }
+ };
+
+ HTTPProxy(ClientParams& icn_params, std::size_t n_thread = 1);
+ HTTPProxy(ServerParams& icn_params, std::size_t n_thread = 1);
+
+ void run() { main_io_context_.run(); }
+ void stop();
+
+ private:
+ void setupSignalHandler();
+
+ std::vector<std::unique_ptr<Receiver>> receivers_;
+ asio::io_service main_io_context_;
+ asio::signal_set signals_;
+};
+
+} // namespace transport \ No newline at end of file
diff --git a/apps/http-proxy/src/ATSConnector.h b/apps/http-proxy/includes/hicn/http-proxy/http_session.h
index 8d91b7b7b..f4a3dbdee 100644
--- a/apps/http-proxy/src/ATSConnector.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/http_session.h
@@ -17,6 +17,8 @@
#include <hicn/transport/core/packet.h>
+#include "http_1x_message_fast_parser.h"
+
#define ASIO_STANDALONE
#include <asio.hpp>
#include <deque>
@@ -26,16 +28,36 @@ namespace transport {
using asio::ip::tcp;
+struct Metadata;
+
typedef std::function<void(const uint8_t *data, std::size_t size, bool is_last,
- bool headers)>
+ bool headers, Metadata *metadata)>
ContentReceivedCallback;
-typedef std::function<void()> OnReconnect;
+typedef std::function<bool(asio::ip::tcp::socket &socket)> OnConnectionClosed;
typedef std::function<void()> ContentSentCallback;
typedef std::deque<
std::pair<std::unique_ptr<utils::MemBuf>, ContentSentCallback>>
BufferQueue;
-class ATSConnector {
+struct Metadata {
+ std::string http_version;
+ HTTPHeaders headers;
+};
+
+struct RequestMetadata : Metadata {
+ std::string method;
+ std::string path;
+};
+
+struct ResponseMetadata : Metadata {
+ std::string status_code;
+ std::string status_string;
+};
+
+class HTTPClientConnectionCallback;
+
+class HTTPSession {
+ friend class HTTPClientConnectionCallback;
static constexpr uint32_t buffer_size = 1024 * 512;
enum class ConnectorState {
@@ -45,11 +67,15 @@ class ATSConnector {
};
public:
- ATSConnector(asio::io_service &io_service, std::string &ip_address,
- std::string &port, ContentReceivedCallback receive_callback,
- OnReconnect on_reconnect_callback);
+ HTTPSession(asio::io_service &io_service, std::string &ip_address,
+ std::string &port, ContentReceivedCallback receive_callback,
+ OnConnectionClosed on_reconnect_callback, bool client = false);
- ~ATSConnector();
+ HTTPSession(asio::ip::tcp::socket socket,
+ ContentReceivedCallback receive_callback,
+ OnConnectionClosed on_reconnect_callback, bool client = true);
+
+ ~HTTPSession();
void send(const uint8_t *buffer, std::size_t len,
ContentSentCallback &&content_sent = 0);
@@ -65,9 +91,6 @@ class ATSConnector {
void doReadBody(std::size_t body_size, std::size_t additional_bytes);
- // void handleReadChunked(std::error_code ec, std::size_t length,
- // std::size_t size);
-
void doReadChunkedHeader();
void doWrite();
@@ -90,6 +113,7 @@ class ATSConnector {
asio::streambuf input_buffer_;
+ bool reverse_;
bool is_reconnection_;
bool data_available_;
@@ -100,7 +124,10 @@ class ATSConnector {
bool chunked_;
ContentReceivedCallback receive_callback_;
- OnReconnect on_reconnect_callback_;
+ OnConnectionClosed on_connection_closed_callback_;
+
+ // HTTP headers
+ std::unique_ptr<Metadata> header_info_;
// Connector state
ConnectorState state_;
diff --git a/apps/http-proxy/src/IcnReceiver.h b/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h
index 9d0ab5172..780037665 100644
--- a/apps/http-proxy/src/IcnReceiver.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h
@@ -13,18 +13,20 @@
* limitations under the License.
*/
-#include "ATSConnector.h"
-
#include <hicn/transport/core/prefix.h>
#include <hicn/transport/interfaces/publication_options.h>
#include <hicn/transport/interfaces/socket_producer.h>
#include <hicn/transport/utils/spinlock.h>
+#include <asio.hpp>
#include <cassert>
#include <cstring>
#include <queue>
#include <utility>
+#include <hicn/http-proxy/http_session.h>
+//#include "http_session.h"
+
namespace transport {
class AsyncConsumerProducer {
@@ -33,17 +35,31 @@ class AsyncConsumerProducer {
using RequestQueue = std::queue<interface::PublicationOptions>;
public:
- explicit AsyncConsumerProducer(const std::string& prefix,
- std::string& ip_address, std::string& port,
- std::string& cache_size, std::string& mtu,
- std::string& first_ipv6_word,
- unsigned long default_content_lifetime, bool manifest);
-
- void start();
+ explicit AsyncConsumerProducer(
+ asio::io_service& io_service, const std::string& prefix,
+ const std::string& first_ipv6_word, const std::string& origin_address,
+ const std::string& origin_port, const std::string& cache_size,
+ const std::string& mtu, const std::string& content_lifetime,
+ bool manifest);
+
+ explicit AsyncConsumerProducer(
+ const std::string& prefix, const std::string& first_ipv6_word,
+ const std::string& origin_address, const std::string& origin_port,
+ const std::string& cache_size, const std::string& mtu,
+ const std::string& content_lifetime, bool manifest)
+ : AsyncConsumerProducer(internal_io_service_, prefix, first_ipv6_word,
+ origin_address, origin_port, cache_size, mtu,
+ content_lifetime, manifest) {
+ external_io_service_ = false;
+ }
void run();
+ void stop();
+
private:
+ void start();
+
void doSend();
void doReceive();
@@ -55,7 +71,9 @@ class AsyncConsumerProducer {
utils::MemBuf* payload);
core::Prefix prefix_;
- asio::io_service io_service_;
+ asio::io_service& io_service_;
+ asio::io_service internal_io_service_;
+ bool external_io_service_;
interface::ProducerSocket producer_socket_;
std::string ip_address_;
@@ -64,11 +82,10 @@ class AsyncConsumerProducer {
uint32_t mtu_;
uint64_t request_counter_;
- asio::signal_set signals_;
// std::unordered_map<core::Name, std::shared_ptr<ATSConnector>>
// connection_map_;
- ATSConnector connector_;
+ HTTPSession connector_;
unsigned long default_content_lifetime_;
diff --git a/apps/http-proxy/includes/hicn/http-proxy/utils.h b/apps/http-proxy/includes/hicn/http-proxy/utils.h
new file mode 100644
index 000000000..d87c796d0
--- /dev/null
+++ b/apps/http-proxy/includes/hicn/http-proxy/utils.h
@@ -0,0 +1,51 @@
+/*
+ * 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 <hicn/transport/core/prefix.h>
+#include <hicn/transport/utils/hash.h>
+
+#include <sstream>
+#include <string>
+
+#pragma once
+
+TRANSPORT_ALWAYS_INLINE std::string generatePrefix(
+ const std::string& prefix_url, const std::string& first_ipv6_word) {
+ const char* str = prefix_url.c_str();
+ uint16_t pos = 0;
+
+ if (strncmp("http://", str, 7) == 0) {
+ pos = 7;
+ } else if (strncmp("https://", str, 8) == 0) {
+ pos = 8;
+ }
+
+ str += pos;
+
+ uint32_t locator_hash = utils::hash::fnv32_buf(str, strlen(str));
+
+ std::stringstream stream;
+ stream << first_ipv6_word << ":0";
+
+ for (uint16_t* word = (uint16_t*)&locator_hash;
+ std::size_t(word) < (std::size_t(&locator_hash) + sizeof(locator_hash));
+ word++) {
+ stream << ":" << std::hex << *word;
+ }
+
+ stream << "::";
+
+ return stream.str();
+} \ No newline at end of file
diff --git a/apps/http-proxy/main.cc b/apps/http-proxy/main.cc
index 20655071c..d9c29ecde 100644
--- a/apps/http-proxy/main.cc
+++ b/apps/http-proxy/main.cc
@@ -13,53 +13,128 @@
* limitations under the License.
*/
-#include "src/IcnReceiver.h"
+#include <hicn/http-proxy/http_proxy.h>
using namespace transport;
int usage(char* program) {
- std::cerr << "ICN Plugin not loaded!" << std::endl;
- std::cerr << "USAGE: " << program << "\n"
- << "[HTTP_PREFIX] -a [SERVER_IP_ADDRESS] "
- "-p [SERVER_PORT] -c [CACHE_SIZE] -m [MTU] -l [DEFAULT_LIFETIME "
- "(seconds)] -P [FIRST_IPv6_WORD_HEX] -M (enable manifest)"
+ std::cerr << "USAGE: " << program << "[-C|-S] [options] <http_prefix>\n"
+ << "Server or Client: \n"
+ << " -P [FIRST_IPv6_WORD_HEX]\n"
+ << " -t [number of threads]\n"
+ << "Client Options: \n"
+ << " -L [PROXY_LISTEN_PORT]\n"
+ << "Server Options: \n"
+ << " -a [ORIGIN_IP_ADDRESS]\n"
+ << " -p [ORIGIN_PORT]\n"
+ << " -c [CACHE_SIZE]\n"
+ << " -m [MTU]"
+ << " -l [DEFAULT_CONTENT_LIFETIME] (seconds)\n"
+ << " -M (enable manifest)\n"
+ << std::endl
+ << "Example Server:\n"
+ << " " << program
+ << " -S -a example.com -p 80 -c 10000 -m 1300 -l 7200 -M -t 1 "
+ "http://httpserver\n"
+ << "Example Client:\n"
+ << " " << program << " -C -L 9091 http://httpserver\n"
<< std::endl;
return -1;
}
+struct Params : HTTPProxy::ClientParams, HTTPProxy::ServerParams {
+ void printParams() override {
+ if (client) {
+ HTTPProxy::ClientParams::printParams();
+ } else if (server) {
+ HTTPProxy::ServerParams::printParams();
+ } else {
+ throw std::runtime_error(
+ "Proxy configured as client and server at the same time.");
+ }
+
+ std::cout << "\t"
+ << "N Threads: " << n_thread << std::endl;
+ }
+
+ HTTPProxy* instantiateProxyAsValue() {
+ if (client) {
+ HTTPProxy::ClientParams* p = dynamic_cast<HTTPProxy::ClientParams*>(this);
+ return new transport::HTTPProxy(*p, n_thread);
+ } else if (server) {
+ HTTPProxy::ServerParams* p = dynamic_cast<HTTPProxy::ServerParams*>(this);
+ return new transport::HTTPProxy(*p, n_thread);
+ } else {
+ throw std::runtime_error(
+ "Proxy configured as client and server at the same time.");
+ }
+ }
+
+ bool client = false;
+ bool server = false;
+ std::uint16_t n_thread = 1;
+};
+
int main(int argc, char** argv) {
- std::string prefix("http://hicn-http-proxy");
- std::string ip_address("127.0.0.1");
- std::string port("80");
- std::string cache_size("50000");
- std::string mtu("1500");
- std::string first_ipv6_word("b001");
- std::string default_content_lifetime("7200"); // seconds
- bool manifest = false;
+ Params params;
+
+ params.prefix = "http://hicn-http-proxy";
+ params.origin_address = "127.0.0.1";
+ params.origin_port = "80";
+ params.cache_size = "50000";
+ params.mtu = "1500";
+ params.first_ipv6_word = "b001";
+ params.content_lifetime = "7200;"; // seconds
+ params.manifest = false;
+ params.tcp_listen_port = 8080;
int opt;
- while ((opt = getopt(argc, argv, "a:p:c:m:P:l:M")) != -1) {
+ while ((opt = getopt(argc, argv, "CSa:p:c:m:P:l:ML:t:")) != -1) {
switch (opt) {
+ case 'C':
+ if (params.server) {
+ std::cerr << "Cannot be both client and server (both -C anc -S "
+ "options specified.)."
+ << std::endl;
+ return usage(argv[0]);
+ }
+ params.client = true;
+ break;
+ case 'S':
+ if (params.client) {
+ std::cerr << "Cannot be both client and server (both -C anc -S "
+ "options specified.)."
+ << std::endl;
+ return usage(argv[0]);
+ }
+ params.server = true;
+ break;
case 'a':
- ip_address = optarg;
+ params.origin_address = optarg;
break;
case 'p':
- port = optarg;
+ params.origin_port = optarg;
break;
case 'c':
- cache_size = optarg;
+ params.cache_size = optarg;
break;
case 'm':
- mtu = optarg;
+ params.mtu = optarg;
break;
case 'P':
- first_ipv6_word = optarg;
+ params.first_ipv6_word = optarg;
break;
case 'l':
- default_content_lifetime = optarg;
+ params.content_lifetime = optarg;
+ break;
+ case 'L':
+ params.tcp_listen_port = std::stoul(optarg);
break;
case 'M':
- manifest = true;
+ params.manifest = true;
+ break;
+ case 't':
+ params.n_thread = std::stoul(optarg);
break;
case 'h':
default:
@@ -69,19 +144,15 @@ int main(int argc, char** argv) {
}
if (argv[optind] == 0) {
- std::cerr << "Using default prefix " << prefix << std::endl;
+ std::cerr << "Using default prefix " << params.prefix << std::endl;
} else {
- prefix = argv[optind];
+ params.prefix = argv[optind];
}
- std::cout << "Connecting to " << ip_address << " port " << port
- << " Cache size " << cache_size << " Prefix " << prefix << " MTU "
- << mtu << " IPv6 first word " << first_ipv6_word << std::endl;
- transport::AsyncConsumerProducer proxy(
- prefix, ip_address, port, cache_size, mtu, first_ipv6_word,
- std::stoul(default_content_lifetime) * 1000, manifest);
-
- proxy.run();
+ params.printParams();
+ auto proxy = params.instantiateProxyAsValue();
+ proxy->run();
+ delete proxy;
return 0;
} \ No newline at end of file
diff --git a/apps/http-proxy/src/forwarder_interface.cc b/apps/http-proxy/src/forwarder_interface.cc
new file mode 100644
index 000000000..7d8235ac6
--- /dev/null
+++ b/apps/http-proxy/src/forwarder_interface.cc
@@ -0,0 +1,263 @@
+/*
+ * 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 <arpa/inet.h>
+#include <hicn/http-proxy/forwarder_interface.h>
+#include <hicn/transport/utils/log.h>
+
+#include <chrono>
+#include <iostream>
+#include <thread>
+#include <unordered_set>
+
+namespace transport {
+
+ForwarderInterface::~ForwarderInterface() {}
+
+int ForwarderInterface::connectToForwarder() {
+ sock_ = hc_sock_create();
+ if (!sock_) return -1;
+
+ if (hc_sock_connect(sock_) < 0) {
+ hc_sock_free(sock_);
+ sock_ = nullptr;
+ return -1;
+ }
+
+ return 0;
+}
+
+void ForwarderInterface::close() {
+ if (!closed_) {
+ internal_ioservice_.post([this]() {
+ work_.reset();
+ if (sock_) {
+ hc_sock_free(sock_);
+ sock_ = nullptr;
+ }
+ });
+
+ if (thread_->joinable()) {
+ thread_->join();
+ }
+ }
+}
+
+void ForwarderInterface::removeConnectedUserNow(uint32_t route_id) {
+ internalRemoveConnectedUser(route_id);
+}
+
+void ForwarderInterface::scheduleRemoveConnectedUser(uint32_t route_id) {
+ internal_ioservice_.post(
+ [this, route_id]() { internalRemoveConnectedUser(route_id); });
+}
+
+int32_t ForwarderInterface::getMainListenerPort() {
+ if (!sock_) return -1;
+
+ hc_data_t *data;
+ if (hc_listener_list(sock_, &data) < 0) return -1;
+
+ int ret = -1;
+ foreach_listener(l, data) {
+ std::string interface = std::string(l->interface_name);
+ if (interface.compare("lo") != 0) {
+ ret = l->local_port;
+ break;
+ }
+ }
+
+ hc_data_free(data);
+ return ret;
+}
+
+void ForwarderInterface::internalRemoveConnectedUser(uint32_t route_id) {
+ auto it = route_status_.find(route_id);
+ if (it == route_status_.end()) return;
+
+ if (!sock_) return;
+
+ // remove route
+ hc_data_t *data;
+ if (hc_route_list(sock_, &data) < 0) return;
+
+ std::vector<hc_route_t *> routes_to_remove;
+ foreach_route(r, data) {
+ char remote_addr[INET6_ADDRSTRLEN];
+ int ret = ip_address_ntop(&r->remote_addr, remote_addr, r->len, r->family);
+ if (ret < 0) continue;
+
+ std::string route_addr(remote_addr);
+ if (route_addr.compare(it->second->route_addr) == 0 &&
+ r->len == it->second->route_len) {
+ // route found
+ routes_to_remove.push_back(r);
+ }
+ }
+
+ route_status_.erase(it);
+
+ if (routes_to_remove.size() == 0) {
+ // nothing to do here
+ hc_data_free(data);
+ return;
+ }
+
+ std::unordered_set<uint32_t> connids_to_remove;
+ for (unsigned i = 0; i < routes_to_remove.size(); i++) {
+ connids_to_remove.insert(routes_to_remove[i]->face_id);
+ if (hc_route_delete(sock_, routes_to_remove[i]) < 0) {
+ TRANSPORT_LOGE("Error removing route from forwarder.");
+ }
+ }
+
+ // remove connection
+ if (hc_connection_list(sock_, &data) < 0) {
+ hc_data_free(data);
+ return;
+ }
+
+ // collects pointerst to the connections using the conn IDs
+ std::vector<hc_connection_t *> conns_to_remove;
+ foreach_connection(c, data) {
+ if (connids_to_remove.find(c->id) != connids_to_remove.end()) {
+ // conn found
+ conns_to_remove.push_back(c);
+ }
+ }
+
+ if (conns_to_remove.size() == 0) {
+ // nothing else to do here
+ hc_data_free(data);
+ return;
+ }
+
+ for (unsigned i = 0; i < conns_to_remove.size(); i++) {
+ if (hc_connection_delete(sock_, conns_to_remove[i]) < 0) {
+ TRANSPORT_LOGE("Error removing connection from forwarder.");
+ }
+ }
+
+ hc_data_free(data);
+}
+
+void ForwarderInterface::internalCreateFaceAndRoute(RouteInfoPtr route_info,
+ uint8_t max_try,
+ asio::steady_timer *timer,
+ SetRouteCallback callback) {
+ int ret = tryToCreateFaceAndRoute(route_info.get());
+
+ if (ret < 0 && max_try > 0) {
+ max_try--;
+ timer->expires_from_now(std::chrono::milliseconds(500));
+ timer->async_wait([this, _route_info = std::move(route_info), max_try,
+ timer, callback](std::error_code ec) {
+ if (ec) return;
+ internalCreateFaceAndRoute(std::move(_route_info), max_try, timer,
+ std::move(callback));
+ });
+ return;
+ }
+
+ if (max_try == 0 && ret < 0) {
+ pending_add_route_counter_--;
+ external_ioservice_.post([callback]() { callback(false, ~0); });
+ } else {
+ pending_add_route_counter_--;
+ route_status_[route_id_] = std::move(route_info);
+ external_ioservice_.post(
+ [route_id = route_id_, callback]() { callback(route_id, true); });
+ route_id_++;
+ }
+
+ delete timer;
+}
+
+int ForwarderInterface::tryToCreateFaceAndRoute(route_info_t *route_info) {
+ if (!sock_) return -1;
+
+ hc_data_t *data;
+ if (hc_listener_list(sock_, &data) < 0) {
+ return -1;
+ }
+
+ bool found = false;
+ uint32_t face_id;
+
+ foreach_listener(l, data) {
+ std::string interface = std::string(l->interface_name);
+ if (interface.compare("lo") != 0) {
+ found = true;
+
+ ip_address_t remote_ip;
+ if (ip_address_pton(route_info->remote_addr.c_str(), &remote_ip) < 0) {
+ hc_data_free(data);
+ return -1;
+ }
+
+ hc_face_t face;
+ memset(&face, 0, sizeof(hc_face_t));
+
+ face.face.type = FACE_TYPE_UDP;
+ face.face.family = route_info->family;
+ face.face.local_addr = l->local_addr;
+ face.face.remote_addr = remote_ip;
+ face.face.local_port = l->local_port;
+ face.face.remote_port = route_info->remote_port;
+
+ if (netdevice_set_name(&face.face.netdevice, l->interface_name) < 0) {
+ hc_data_free(data);
+ return -1;
+ }
+
+ if (hc_face_create(sock_, &face) < 0) {
+ hc_data_free(data);
+ return -1;
+ }
+
+ face_id = face.id;
+ break;
+ }
+ }
+
+ if (!found) {
+ hc_data_free(data);
+ return -1;
+ }
+
+ ip_address_t route_ip;
+ hc_route_t route;
+
+ if (ip_address_pton(route_info->route_addr.c_str(), &route_ip) < 0) {
+ hc_data_free(data);
+ return -1;
+ }
+
+ route.face_id = face_id;
+ route.family = AF_INET6;
+ route.remote_addr = route_ip;
+ route.len = route_info->route_len;
+ route.cost = 1;
+
+ if (hc_route_create(sock_, &route) < 0) {
+ hc_data_free(data);
+ return -1;
+ }
+
+ hc_data_free(data);
+ return 0;
+}
+
+} // namespace transport
diff --git a/apps/http-proxy/src/HTTP1.xMessageFastParser.cc b/apps/http-proxy/src/http_1x_message_fast_parser.cc
index 729eb3aeb..4b6b78d55 100644
--- a/apps/http-proxy/src/HTTP1.xMessageFastParser.cc
+++ b/apps/http-proxy/src/http_1x_message_fast_parser.cc
@@ -13,33 +13,48 @@
* limitations under the License.
*/
-#include "HTTP1.xMessageFastParser.h"
-
+#include <hicn/http-proxy/http_session.h>
+#include <hicn/transport/http/request.h>
#include <hicn/transport/http/response.h>
#include <experimental/algorithm>
#include <experimental/functional>
#include <iostream>
+constexpr char HTTPMessageFastParser::http_ok[];
+constexpr char HTTPMessageFastParser::http_cors[];
+constexpr char HTTPMessageFastParser::http_failed[];
+
std::string HTTPMessageFastParser::numbers = "0123456789";
-std::string HTTPMessageFastParser::content_length = "Content-Length";
-std::string HTTPMessageFastParser::transfer_encoding = "Transfer-Encoding";
+std::string HTTPMessageFastParser::content_length = "content-length";
+std::string HTTPMessageFastParser::transfer_encoding = "transfer-encoding";
std::string HTTPMessageFastParser::chunked = "chunked";
-std::string HTTPMessageFastParser::cache_control = "Cache-Control";
+std::string HTTPMessageFastParser::cache_control = "cache-control";
std::string HTTPMessageFastParser::mpd = "mpd";
-std::string HTTPMessageFastParser::connection = "Connection";
+std::string HTTPMessageFastParser::connection = "connection";
std::string HTTPMessageFastParser::separator = "\r\n\r\n";
-HTTPHeaders HTTPMessageFastParser::getHeaders(const uint8_t *headers,
- std::size_t length) {
- HTTPHeaders ret;
- std::string http_version;
- std::string status_code;
- std::string status_string;
-
- if (transport::http::HTTPResponse::parseHeaders(headers, length, ret, http_version,
- status_code, status_string)) {
- return ret;
+void HTTPMessageFastParser::getHeaders(const uint8_t *headers,
+ std::size_t length, bool request,
+ transport::Metadata *metadata) {
+ if (request) {
+ transport::RequestMetadata *_metadata =
+ (transport::RequestMetadata *)(metadata);
+
+ if (transport::http::HTTPRequest::parseHeaders(
+ headers, length, _metadata->headers, _metadata->http_version,
+ _metadata->method, _metadata->path)) {
+ return;
+ }
+ } else {
+ transport::ResponseMetadata *_metadata =
+ (transport::ResponseMetadata *)(metadata);
+
+ if (transport::http::HTTPResponse::parseHeaders(
+ headers, length, _metadata->headers, _metadata->http_version,
+ _metadata->status_code, _metadata->status_string)) {
+ return;
+ }
}
throw std::runtime_error("Error parsing response headers.");
diff --git a/apps/http-proxy/src/http_proxy.cc b/apps/http-proxy/src/http_proxy.cc
new file mode 100644
index 000000000..262fcb8e1
--- /dev/null
+++ b/apps/http-proxy/src/http_proxy.cc
@@ -0,0 +1,376 @@
+/*
+ * 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 <hicn/http-proxy/http_proxy.h>
+#include <hicn/http-proxy/http_session.h>
+#include <hicn/http-proxy/utils.h>
+#include <hicn/transport/core/interest.h>
+#include <hicn/transport/utils/log.h>
+#include <hicn/transport/utils/string_utils.h>
+
+namespace transport {
+
+using core::Interest;
+using core::Name;
+using interface::ConsumerCallbacksOptions;
+using interface::ConsumerInterestCallback;
+using interface::ConsumerSocket;
+using interface::TransportProtocolAlgorithms;
+
+class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback {
+ public:
+ HTTPClientConnectionCallback(TcpReceiver& tcp_receiver,
+ utils::EventThread& thread)
+ : tcp_receiver_(tcp_receiver),
+ thread_(thread),
+ prefix_hash_(tcp_receiver_.prefix_hash_),
+ consumer_(TransportProtocolAlgorithms::RAAQM, thread_.getIoService()),
+ session_(nullptr),
+ current_size_(0) {
+ consumer_.setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK, this);
+ consumer_.setSocketOption(
+ ConsumerCallbacksOptions::INTEREST_OUTPUT,
+ (ConsumerInterestCallback)std::bind(
+ &HTTPClientConnectionCallback::processLeavingInterest, this,
+ std::placeholders::_1, std::placeholders::_2));
+ consumer_.setSocketOption(
+ ConsumerCallbacksOptions::INTEREST_RETRANSMISSION,
+ (ConsumerInterestCallback)std::bind(
+ &HTTPClientConnectionCallback::processInterestRetx, this,
+ std::placeholders::_1, std::placeholders::_2));
+ consumer_.connect();
+ }
+
+ void stop() { session_->close(); }
+
+ void setHttpSession(asio::ip::tcp::socket&& socket) {
+ session_ = std::make_unique<HTTPSession>(
+ std::move(socket),
+ std::bind(&HTTPClientConnectionCallback::readDataFromTcp, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4,
+ std::placeholders::_5),
+ [this](asio::ip::tcp::socket& socket) -> bool {
+ try {
+ std::string remote_address =
+ socket.remote_endpoint().address().to_string();
+ std::uint16_t remote_port = socket.remote_endpoint().port();
+ TRANSPORT_LOGD("Client %s:%d disconnected.", remote_address.c_str(),
+ remote_port);
+ } catch (std::system_error& e) {
+ // Do nothing
+ }
+
+ consumer_.stop();
+ request_buffer_queue_.clear();
+ tcp_receiver_.onClientDisconnect(this);
+ return false;
+ });
+
+ current_size_ = 0;
+ }
+
+ private:
+ void consumeNextRequest() {
+ if (request_buffer_queue_.size() == 0) {
+ TRANSPORT_LOGD("No additional requests to process.");
+ return;
+ }
+
+ auto& buffer = request_buffer_queue_.front().second;
+ uint64_t request_hash =
+ utils::hash::fnv64_buf(buffer.data(), buffer.size());
+
+ std::stringstream name;
+ name << prefix_hash_.substr(0, prefix_hash_.length() - 2);
+
+ for (uint16_t* word = (uint16_t*)&request_hash;
+ std::size_t(word) <
+ (std::size_t(&request_hash) + sizeof(request_hash));
+ word++) {
+ name << ":" << std::hex << *word;
+ }
+
+ name << "|0";
+
+ // Non blocking consume :)
+ consumer_.consume(Name(name.str()));
+ }
+
+ // tcp callbacks
+
+ void readDataFromTcp(const uint8_t* data, std::size_t size, bool is_last,
+ bool headers, Metadata* metadata) {
+ if (headers) {
+ // Add the request to the request queue
+ RequestMetadata* _metadata = reinterpret_cast<RequestMetadata*>(metadata);
+ tmp_buffer_ = std::make_pair(utils::MemBuf::copyBuffer(data, size),
+ _metadata->path);
+ if (TRANSPORT_EXPECT_FALSE(
+ _metadata->path.compare("/isHicnProxyOn") == 0 && is_last)) {
+ /**
+ * It seems this request is for us.
+ * Get hicn parameters.
+ */
+ processClientRequest(_metadata);
+ return;
+ }
+ } else {
+ // Append payload chunk to last request added. Here we are assuming
+ // HTTP/1.1.
+ tmp_buffer_.first->prependChain(utils::MemBuf::copyBuffer(data, size));
+ }
+
+ current_size_ += size;
+
+ if (is_last) {
+ TRANSPORT_LOGD("Request received: %s",
+ std::string((const char*)tmp_buffer_.first->data(),
+ tmp_buffer_.first->length())
+ .c_str());
+ if (current_size_ < 1400) {
+ request_buffer_queue_.emplace_back(std::move(tmp_buffer_));
+ } else {
+ TRANSPORT_LOGE("Ignoring client request due to size (%zu) > 1400.",
+ current_size_);
+ session_->close();
+ current_size_ = 0;
+ return;
+ }
+
+ if (!consumer_.isRunning()) {
+ TRANSPORT_LOGD(
+ "Consumer stopped, triggering consume from TCP session "
+ "handler..");
+ consumeNextRequest();
+ }
+
+ current_size_ = 0;
+ }
+ }
+
+ // hicn callbacks
+
+ void processLeavingInterest(interface::ConsumerSocket& c,
+ const core::Interest& interest) {
+ if (interest.getName().getSuffix() == 0 && interest.payloadSize() == 0) {
+ Interest& int2 = const_cast<Interest&>(interest);
+ int2.appendPayload(request_buffer_queue_.front().first->clone());
+ }
+ }
+
+ void processInterestRetx(interface::ConsumerSocket& c,
+ const core::Interest& interest) {
+ if (interest.payloadSize() == 0) {
+ Interest& int2 = const_cast<Interest&>(interest);
+ int2.appendPayload(request_buffer_queue_.front().first->clone());
+ }
+ }
+
+ bool isBufferMovable() noexcept { return true; }
+ void getReadBuffer(uint8_t** application_buffer, size_t* max_length) {}
+ void readDataAvailable(size_t length) noexcept {}
+ size_t maxBufferSize() const { return 64 * 1024; }
+
+ void readBufferAvailable(std::unique_ptr<utils::MemBuf>&& buffer) noexcept {
+ // Response received. Send it back to client
+ auto _buffer = buffer.release();
+ TRANSPORT_LOGD("From hicn: %zu bytes.", _buffer->length());
+ session_->send(_buffer, []() {});
+ }
+
+ void readError(const std::error_code ec) noexcept {
+ TRANSPORT_LOGE("Error reading from hicn consumer socket. Closing session.");
+ session_->close();
+ }
+
+ void readSuccess(std::size_t total_size) noexcept {
+ request_buffer_queue_.pop_front();
+ consumeNextRequest();
+ }
+
+ void processClientRequest(RequestMetadata* metadata) {
+ auto it = metadata->headers.find("hicn");
+ if (it == metadata->headers.end()) {
+ /*
+ * Probably it is an OPTION message for access control.
+ * Let's grant it!
+ */
+ if (metadata->method == "OPTIONS") {
+ session_->send(
+ (const uint8_t*)HTTPMessageFastParser::http_cors,
+ std::strlen(HTTPMessageFastParser::http_cors), [this]() {
+ auto& socket = session_->socket_;
+ TRANSPORT_LOGI(
+ "Sent OPTIONS to client %s:%d",
+ socket.remote_endpoint().address().to_string().c_str(),
+ socket.remote_endpoint().port());
+ });
+ }
+ } else {
+ tcp_receiver_.parseHicnHeader(
+ it->second, [this](bool result, std::string configured_prefix) {
+ const char* reply = nullptr;
+ if (result) {
+ reply = HTTPMessageFastParser::http_ok;
+ } else {
+ reply = HTTPMessageFastParser::http_failed;
+ }
+
+ /* Route created. Send back a 200 OK to client */
+ session_->send(
+ (const uint8_t*)reply, std::strlen(reply), [this, result]() {
+ auto& socket = session_->socket_;
+ TRANSPORT_LOGI(
+ "Sent %d response to client %s:%d", result,
+ socket.remote_endpoint().address().to_string().c_str(),
+ socket.remote_endpoint().port());
+ });
+ });
+ }
+ }
+
+ private:
+ TcpReceiver& tcp_receiver_;
+ utils::EventThread& thread_;
+ std::string& prefix_hash_;
+ ConsumerSocket consumer_;
+ std::unique_ptr<HTTPSession> session_;
+ std::deque<std::pair<std::unique_ptr<utils::MemBuf>, std::string>>
+ request_buffer_queue_;
+ std::pair<std::unique_ptr<utils::MemBuf>, std::string> tmp_buffer_;
+ std::size_t current_size_;
+};
+
+TcpReceiver::TcpReceiver(std::uint16_t port, const std::string& prefix,
+ const std::string& ipv6_first_word)
+ : Receiver(),
+ listener_(thread_.getIoService(), port,
+ std::bind(&TcpReceiver::onNewConnection, this,
+ std::placeholders::_1)),
+ prefix_(prefix),
+ ipv6_first_word_(ipv6_first_word),
+ prefix_hash_(generatePrefix(prefix_, ipv6_first_word_)),
+ forwarder_config_(
+ thread_.getIoService(),
+ [this](std::error_code ec) {
+ if (!ec) {
+ listener_.doAccept();
+ for (int i = 0; i < 10; i++) {
+ http_clients_.emplace_back(
+ new HTTPClientConnectionCallback(*this, thread_));
+ }
+ }
+ }),
+ stopped_(false) {
+ forwarder_config_.tryToConnectToForwarder();
+}
+
+void TcpReceiver::stop() {
+ thread_.add([this]() {
+ stopped_ = true;
+
+ /* Stop the listener */
+ listener_.stop();
+
+ /* Close connection with forwarder */
+ forwarder_config_.close();
+
+ /* Stop the used http clients */
+ for (auto& client : used_http_clients_) {
+ client->stop();
+ }
+
+ /* Delete unused clients */
+ for (auto& client : http_clients_) {
+ delete client;
+ }
+ });
+}
+
+void TcpReceiver::onClientDisconnect(HTTPClientConnectionCallback* client) {
+ if (stopped_) {
+ delete client;
+ return;
+ }
+
+ http_clients_.emplace_front(client);
+ used_http_clients_.erase(client);
+}
+
+void TcpReceiver::onNewConnection(asio::ip::tcp::socket&& socket) {
+ if (http_clients_.size() == 0) {
+ // Create new HTTPClientConnectionCallback
+ TRANSPORT_LOGD("Creating new HTTPClientConnectionCallback.");
+ http_clients_.emplace_back(
+ new HTTPClientConnectionCallback(*this, thread_));
+ }
+
+ // Get new HTTPClientConnectionCallback
+ HTTPClientConnectionCallback* c = http_clients_.front();
+ http_clients_.pop_front();
+
+ // Set http session
+ c->setHttpSession(std::move(socket));
+
+ // Move it to used clients
+ used_http_clients_.insert(c);
+}
+
+void HTTPProxy::setupSignalHandler() {
+ signals_.async_wait([this](const std::error_code& ec, int signal_number) {
+ if (!ec) {
+ TRANSPORT_LOGI("Received signal %d. Stopping gracefully.", signal_number);
+ stop();
+ }
+ });
+}
+
+void HTTPProxy::stop() {
+ for (auto& receiver : receivers_) {
+ receiver->stop();
+ }
+
+ for (auto& receiver : receivers_) {
+ receiver->stopAndJoinThread();
+ }
+
+ signals_.cancel();
+}
+
+HTTPProxy::HTTPProxy(ClientParams& params, std::size_t n_thread)
+ : signals_(main_io_context_, SIGINT, SIGQUIT) {
+ for (uint16_t i = 0; i < n_thread; i++) {
+ // icn_receivers_.emplace_back(std::make_unique<IcnReceiver>(icn_params));
+ receivers_.emplace_back(std::make_unique<TcpReceiver>(
+ params.tcp_listen_port, params.prefix, params.first_ipv6_word));
+ }
+
+ setupSignalHandler();
+}
+
+HTTPProxy::HTTPProxy(ServerParams& params, std::size_t n_thread)
+ : signals_(main_io_context_, SIGINT, SIGQUIT) {
+ for (uint16_t i = 0; i < n_thread; i++) {
+ receivers_.emplace_back(std::make_unique<IcnReceiver>(
+ params.prefix, params.first_ipv6_word, params.origin_address,
+ params.origin_port, params.cache_size, params.mtu,
+ params.content_lifetime, params.manifest));
+ }
+
+ setupSignalHandler();
+}
+
+} // namespace transport
diff --git a/apps/http-proxy/src/ATSConnector.cc b/apps/http-proxy/src/http_session.cc
index a9b889941..6b91c12c3 100644
--- a/apps/http-proxy/src/ATSConnector.cc
+++ b/apps/http-proxy/src/http_session.cc
@@ -13,48 +13,95 @@
* limitations under the License.
*/
-#include "ATSConnector.h"
-#include "HTTP1.xMessageFastParser.h"
-
+#include <hicn/http-proxy/http_proxy.h>
#include <hicn/transport/utils/branch_prediction.h>
#include <hicn/transport/utils/log.h>
+
#include <iostream>
namespace transport {
-ATSConnector::ATSConnector(asio::io_service &io_service,
- std::string &ip_address, std::string &port,
- ContentReceivedCallback receive_callback,
- OnReconnect on_reconnect_callback)
+HTTPSession::HTTPSession(asio::io_service &io_service, std::string &ip_address,
+ std::string &port,
+ ContentReceivedCallback receive_callback,
+ OnConnectionClosed on_connection_closed_callback,
+ bool client)
: io_service_(io_service),
socket_(io_service_),
resolver_(io_service_),
endpoint_iterator_(resolver_.resolve({ip_address, port})),
timer_(io_service),
+ reverse_(client),
is_reconnection_(false),
data_available_(false),
content_length_(0),
is_last_chunk_(false),
chunked_(false),
receive_callback_(receive_callback),
- on_reconnect_callback_(on_reconnect_callback) {
+ on_connection_closed_callback_(on_connection_closed_callback) {
input_buffer_.prepare(buffer_size + 2048);
state_ = ConnectorState::CONNECTING;
+
+ if (reverse_) {
+ header_info_ = std::make_unique<RequestMetadata>();
+ } else {
+ header_info_ = std::make_unique<ResponseMetadata>();
+ }
+
doConnect();
}
-ATSConnector::~ATSConnector() {}
+HTTPSession::HTTPSession(asio::ip::tcp::socket socket,
+ ContentReceivedCallback receive_callback,
+ OnConnectionClosed on_connection_closed_callback,
+ bool client)
+ :
+#if ((ASIO_VERSION / 100 % 1000) < 12)
+ io_service_(socket.get_io_service()),
+#else
+ io_service_((asio::io_context &)(socket.get_executor().context())),
+#endif
+ socket_(std::move(socket)),
+ resolver_(io_service_),
+ timer_(io_service_),
+ reverse_(client),
+ is_reconnection_(false),
+ data_available_(false),
+ content_length_(0),
+ is_last_chunk_(false),
+ chunked_(false),
+ receive_callback_(receive_callback),
+ on_connection_closed_callback_(on_connection_closed_callback) {
+ input_buffer_.prepare(buffer_size + 2048);
+ state_ = ConnectorState::CONNECTED;
+ asio::ip::tcp::no_delay noDelayOption(true);
+ socket_.set_option(noDelayOption);
-void ATSConnector::send(const uint8_t *packet, std::size_t len,
- ContentSentCallback &&content_sent) {
- asio::async_write(
- socket_, asio::buffer(packet, len),
- [content_sent = std::move(content_sent)](
- std::error_code ec, std::size_t /*length*/) { content_sent(); });
+ if (reverse_) {
+ header_info_ = std::make_unique<RequestMetadata>();
+ } else {
+ header_info_ = std::make_unique<ResponseMetadata>();
+ }
+ doReadHeader();
}
-void ATSConnector::send(utils::MemBuf *buffer,
- ContentSentCallback &&content_sent) {
+HTTPSession::~HTTPSession() {}
+
+void HTTPSession::send(const uint8_t *packet, std::size_t len,
+ ContentSentCallback &&content_sent) {
+ io_service_.dispatch([this, packet, len, content_sent]() {
+ asio::async_write(socket_, asio::buffer(packet, len),
+ [content_sent = std::move(content_sent)](
+ std::error_code ec, std::size_t /*length*/) {
+ if (!ec) {
+ content_sent();
+ }
+ });
+ });
+}
+
+void HTTPSession::send(utils::MemBuf *buffer,
+ ContentSentCallback &&content_sent) {
io_service_.dispatch([this, buffer, callback = std::move(content_sent)]() {
bool write_in_progress = !write_msgs_.empty();
write_msgs_.emplace_back(std::unique_ptr<utils::MemBuf>(buffer),
@@ -70,24 +117,25 @@ void ATSConnector::send(utils::MemBuf *buffer,
});
}
-void ATSConnector::close() {
+void HTTPSession::close() {
if (state_ != ConnectorState::CLOSED) {
state_ = ConnectorState::CLOSED;
if (socket_.is_open()) {
- socket_.shutdown(asio::ip::tcp::socket::shutdown_type::shutdown_both);
+ // socket_.shutdown(asio::ip::tcp::socket::shutdown_type::shutdown_both);
socket_.close();
// on_disconnect_callback_();
}
}
}
-void ATSConnector::doWrite() {
+void HTTPSession::doWrite() {
auto &buffer = write_msgs_.front().first;
asio::async_write(socket_, asio::buffer(buffer->data(), buffer->length()),
[this](std::error_code ec, std::size_t length) {
if (TRANSPORT_EXPECT_FALSE(!ec)) {
- TRANSPORT_LOGD("Content successfully sent!");
+ TRANSPORT_LOGD("Content successfully sent! %zu",
+ length);
write_msgs_.front().second();
write_msgs_.pop_front();
if (!write_msgs_.empty()) {
@@ -99,12 +147,14 @@ void ATSConnector::doWrite() {
});
} // namespace transport
-void ATSConnector::handleRead(std::error_code ec, std::size_t length) {
+void HTTPSession::handleRead(std::error_code ec, std::size_t length) {
if (TRANSPORT_EXPECT_TRUE(!ec)) {
content_length_ -= length;
const uint8_t *buffer =
asio::buffer_cast<const uint8_t *>(input_buffer_.data());
- receive_callback_(buffer, input_buffer_.size(), !content_length_, false);
+ bool is_last = chunked_ ? (is_last_chunk_ ? !content_length_ : false)
+ : !content_length_;
+ receive_callback_(buffer, input_buffer_.size(), is_last, false, nullptr);
input_buffer_.consume(input_buffer_.size());
if (!content_length_) {
@@ -117,7 +167,7 @@ void ATSConnector::handleRead(std::error_code ec, std::size_t length) {
auto to_read =
content_length_ >= buffer_size ? buffer_size : content_length_;
asio::async_read(socket_, input_buffer_, asio::transfer_exactly(to_read),
- std::bind(&ATSConnector::handleRead, this,
+ std::bind(&HTTPSession::handleRead, this,
std::placeholders::_1, std::placeholders::_2));
}
} else if (ec == asio::error::eof) {
@@ -126,8 +176,8 @@ void ATSConnector::handleRead(std::error_code ec, std::size_t length) {
}
}
-void ATSConnector::doReadBody(std::size_t body_size,
- std::size_t additional_bytes) {
+void HTTPSession::doReadBody(std::size_t body_size,
+ std::size_t additional_bytes) {
auto bytes_to_read =
body_size > additional_bytes ? (body_size - additional_bytes) : 0;
@@ -140,14 +190,16 @@ void ATSConnector::doReadBody(std::size_t body_size,
if (to_read > 0) {
content_length_ = bytes_to_read;
asio::async_read(socket_, input_buffer_, asio::transfer_exactly(to_read),
- std::bind(&ATSConnector::handleRead, this,
+ std::bind(&HTTPSession::handleRead, this,
std::placeholders::_1, std::placeholders::_2));
} else {
- const uint8_t *buffer =
- asio::buffer_cast<const uint8_t *>(input_buffer_.data());
- receive_callback_(buffer, body_size, chunked_ ? is_last_chunk_ : !to_read,
- false);
- input_buffer_.consume(body_size);
+ if (body_size) {
+ const uint8_t *buffer =
+ asio::buffer_cast<const uint8_t *>(input_buffer_.data());
+ receive_callback_(buffer, body_size, chunked_ ? is_last_chunk_ : !to_read,
+ false, nullptr);
+ input_buffer_.consume(body_size);
+ }
if (!chunked_ || is_last_chunk_) {
doReadHeader();
@@ -157,7 +209,7 @@ void ATSConnector::doReadBody(std::size_t body_size,
}
}
-void ATSConnector::doReadChunkedHeader() {
+void HTTPSession::doReadChunkedHeader() {
asio::async_read_until(
socket_, input_buffer_, "\r\n",
[this](std::error_code ec, std::size_t length) {
@@ -176,14 +228,17 @@ void ATSConnector::doReadChunkedHeader() {
});
}
-void ATSConnector::doReadHeader() {
+void HTTPSession::doReadHeader() {
asio::async_read_until(
socket_, input_buffer_, "\r\n\r\n",
[this](std::error_code ec, std::size_t length) {
if (TRANSPORT_EXPECT_TRUE(!ec)) {
const uint8_t *buffer =
asio::buffer_cast<const uint8_t *>(input_buffer_.data());
- auto headers = HTTPMessageFastParser::getHeaders(buffer, length);
+ HTTPMessageFastParser::getHeaders(buffer, length, reverse_,
+ header_info_.get());
+
+ auto &headers = header_info_->headers;
// Try to get content length, if available
auto it = headers.find(HTTPMessageFastParser::content_length);
@@ -199,7 +254,8 @@ void ATSConnector::doReadHeader() {
}
}
- receive_callback_(buffer, length, !size && !chunked_, true);
+ receive_callback_(buffer, length, !size && !chunked_, true,
+ header_info_.get());
auto additional_bytes = input_buffer_.size() - length;
input_buffer_.consume(length);
@@ -215,23 +271,25 @@ void ATSConnector::doReadHeader() {
});
}
-void ATSConnector::tryReconnection() {
- TRANSPORT_LOGD("Connection lost. Trying to reconnect...\n");
- if (state_ == ConnectorState::CONNECTED) {
- state_ = ConnectorState::CONNECTING;
- is_reconnection_ = true;
- io_service_.post([this]() {
- if (socket_.is_open()) {
- // socket_.shutdown(asio::ip::tcp::socket::shutdown_type::shutdown_both);
- socket_.close();
- }
- startConnectionTimer();
- doConnect();
- });
+void HTTPSession::tryReconnection() {
+ if (on_connection_closed_callback_(socket_)) {
+ if (state_ == ConnectorState::CONNECTED) {
+ TRANSPORT_LOGD("Connection lost. Trying to reconnect...\n");
+ state_ = ConnectorState::CONNECTING;
+ is_reconnection_ = true;
+ io_service_.post([this]() {
+ if (socket_.is_open()) {
+ // socket_.shutdown(asio::ip::tcp::socket::shutdown_type::shutdown_both);
+ socket_.close();
+ }
+ startConnectionTimer();
+ doConnect();
+ });
+ }
}
}
-void ATSConnector::doConnect() {
+void HTTPSession::doConnect() {
asio::async_connect(socket_, endpoint_iterator_,
[this](std::error_code ec, tcp::resolver::iterator) {
if (!ec) {
@@ -263,17 +321,17 @@ void ATSConnector::doConnect() {
});
}
-bool ATSConnector::checkConnected() {
+bool HTTPSession::checkConnected() {
return state_ == ConnectorState::CONNECTED;
}
-void ATSConnector::startConnectionTimer() {
+void HTTPSession::startConnectionTimer() {
timer_.expires_from_now(std::chrono::seconds(10));
timer_.async_wait(
- std::bind(&ATSConnector::handleDeadline, this, std::placeholders::_1));
+ std::bind(&HTTPSession::handleDeadline, this, std::placeholders::_1));
}
-void ATSConnector::handleDeadline(const std::error_code &ec) {
+void HTTPSession::handleDeadline(const std::error_code &ec) {
if (!ec) {
io_service_.post([this]() {
socket_.close();
diff --git a/apps/http-proxy/src/IcnReceiver.cc b/apps/http-proxy/src/icn_receiver.cc
index 24b0eb5dc..23e5b5623 100644
--- a/apps/http-proxy/src/IcnReceiver.cc
+++ b/apps/http-proxy/src/icn_receiver.cc
@@ -13,9 +13,9 @@
* limitations under the License.
*/
-#include "IcnReceiver.h"
-#include "HTTP1.xMessageFastParser.h"
-
+#include <hicn/http-proxy/http_1x_message_fast_parser.h>
+#include <hicn/http-proxy/icn_receiver.h>
+#include <hicn/http-proxy/utils.h>
#include <hicn/transport/core/interest.h>
#include <hicn/transport/http/default_values.h>
#include <hicn/transport/utils/hash.h>
@@ -26,56 +26,31 @@
namespace transport {
-core::Prefix generatePrefix(const std::string& prefix_url,
- std::string& first_ipv6_word) {
- const char* str = prefix_url.c_str();
- uint16_t pos = 0;
-
- if (strncmp("http://", str, 7) == 0) {
- pos = 7;
- } else if (strncmp("https://", str, 8) == 0) {
- pos = 8;
- }
-
- str += pos;
-
- uint32_t locator_hash = utils::hash::fnv32_buf(str, strlen(str));
-
- std::stringstream stream;
- stream << first_ipv6_word << ":0";
-
- for (uint16_t* word = (uint16_t*)&locator_hash;
- std::size_t(word) < (std::size_t(&locator_hash) + sizeof(locator_hash));
- word++) {
- stream << ":" << std::hex << *word;
- }
-
- stream << "::0";
-
- return core::Prefix(stream.str(), 64);
-}
-
AsyncConsumerProducer::AsyncConsumerProducer(
- const std::string& prefix, std::string& ip_address, std::string& port,
- std::string& cache_size, std::string& mtu, std::string& first_ipv6_word,
- unsigned long default_lifetime, bool manifest)
- : prefix_(generatePrefix(prefix, first_ipv6_word)),
+ asio::io_service& io_service, const std::string& prefix,
+ const std::string& first_ipv6_word, const std::string& origin_address,
+ const std::string& origin_port, const std::string& cache_size,
+ const std::string& mtu, const std::string& content_lifetime, bool manifest)
+ : prefix_(core::Prefix(generatePrefix(prefix, first_ipv6_word), 64)),
+ io_service_(io_service),
+ external_io_service_(true),
producer_socket_(),
- ip_address_(ip_address),
- port_(port),
+ ip_address_(origin_address),
+ port_(origin_port),
cache_size_(std::stoul(cache_size)),
mtu_(std::stoul(mtu)),
request_counter_(0),
- signals_(io_service_, SIGINT, SIGQUIT),
connector_(io_service_, ip_address_, port_,
std::bind(&AsyncConsumerProducer::publishContent, this,
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4),
- [this]() {
+ [this](asio::ip::tcp::socket& socket) -> bool {
std::queue<interface::PublicationOptions> empty;
std::swap(response_name_queue_, empty);
+
+ return true;
}),
- default_content_lifetime_(default_lifetime) {
+ default_content_lifetime_(std::stoul(content_lifetime)) {
int ret = producer_socket_.setSocketOption(
interface::GeneralTransportOptions::OUTPUT_BUFFER_SIZE, cache_size_);
@@ -98,15 +73,6 @@ AsyncConsumerProducer::AsyncConsumerProducer(
}
producer_socket_.registerPrefix(prefix_);
-
- // Let the main thread to catch SIGINT and SIGQUIT
- signals_.async_wait(
- [this](const std::error_code& errorCode, int signal_number) {
- TRANSPORT_LOGI("Number of requests processed by plugin: %lu",
- (unsigned long)request_counter_);
- producer_socket_.stop();
- connector_.close();
- });
}
void AsyncConsumerProducer::start() {
@@ -116,7 +82,19 @@ void AsyncConsumerProducer::start() {
void AsyncConsumerProducer::run() {
start();
- io_service_.run();
+
+ if (!external_io_service_) {
+ io_service_.run();
+ }
+}
+
+void AsyncConsumerProducer::stop() {
+ io_service_.post([this]() {
+ TRANSPORT_LOGI("Number of requests processed by plugin: %lu",
+ (unsigned long)request_counter_);
+ producer_socket_.stop();
+ connector_.close();
+ });
}
void AsyncConsumerProducer::doReceive() {
@@ -124,11 +102,13 @@ void AsyncConsumerProducer::doReceive() {
interface::ProducerCallbacksOptions::CACHE_MISS,
[this](interface::ProducerSocket& producer,
interface::Interest& interest) {
- // core::Name n(interest.getWritableName(), true);
- io_service_.post(std::bind(
- &AsyncConsumerProducer::manageIncomingInterest, this,
- interest.getWritableName(), interest.acquireMemBufReference(),
- interest.getPayload().release()));
+ if (interest.payloadSize() > 0) {
+ // Interest may contain http request
+ io_service_.post(std::bind(
+ &AsyncConsumerProducer::manageIncomingInterest, this,
+ interest.getWritableName(), interest.acquireMemBufReference(),
+ interest.getPayload().release()));
+ }
});
producer_socket_.connect();
@@ -141,16 +121,15 @@ void AsyncConsumerProducer::manageIncomingInterest(
auto _it = chunk_number_map_.find(name);
auto _end = chunk_number_map_.end();
- std::cout << "Received interest " << seg << std::endl;
-
if (_it != _end) {
if (_it->second.second) {
- // Content is in production
+ TRANSPORT_LOGD(
+ "Content is in production, interests will be satisfied shortly.");
return;
}
if (seg >= _it->second.first) {
- TRANSPORT_LOGI(
+ TRANSPORT_LOGD(
"Ignoring interest with name %s for a content object which does not "
"exist. (Request: %u, max: %u)",
name.toString().c_str(), (uint32_t)seg, (uint32_t)_it->second.first);
@@ -158,8 +137,6 @@ void AsyncConsumerProducer::manageIncomingInterest(
}
}
- std::cout << "Received interest " << seg << std::endl;
-
bool is_mpd =
HTTPMessageFastParser::isMpdRequest(payload->data(), payload->length());
@@ -212,7 +189,7 @@ void AsyncConsumerProducer::publishContent(const uint8_t* data,
}
it->second.first +=
- producer_socket_.produce(name, data, size, is_last, start_suffix);
+ producer_socket_.produceStream(name, data, size, is_last, start_suffix);
if (is_last) {
it->second.second = false;
diff --git a/cmake/Modules/BuildMacros.cmake b/cmake/Modules/BuildMacros.cmake
index ed95259b2..c57aaa73c 100644
--- a/cmake/Modules/BuildMacros.cmake
+++ b/cmake/Modules/BuildMacros.cmake
@@ -21,7 +21,7 @@ macro(build_executable exec)
cmake_parse_arguments(ARG
"NO_INSTALL"
"COMPONENT"
- "SOURCES;LINK_LIBRARIES;DEPENDS;INCLUDE_DIRS;DEFINITIONS;LINK_FLAGS"
+ "SOURCES;LINK_LIBRARIES;DEPENDS;INCLUDE_DIRS;DEFINITIONS;COMPILE_OPTIONS;LINK_FLAGS"
${ARGN}
)
@@ -48,6 +48,10 @@ macro(build_executable exec)
add_dependencies(${exec}-bin ${ARG_DEPENDS})
endif()
+ if (ARG_COMPILE_OPTIONS)
+ target_compile_options(${exec}-bin ${ARG_COMPILE_OPTIONS})
+ endif()
+
if(ARG_DEFINITIONS)
target_compile_definitions(${exec}-bin PRIVATE ${ARG_DEFINITIONS})
endif()
@@ -73,10 +77,15 @@ macro(build_library lib)
cmake_parse_arguments(ARG
"SHARED;STATIC;NO_DEV"
"COMPONENT;"
- "SOURCES;LINK_LIBRARIES;INSTALL_HEADERS;DEPENDS;INCLUDE_DIRS;DEFINITIONS;INSTALL_ROOT_DIR;INSTALL_FULL_PATH_DIR;EMPTY_PREFIX;"
+ "SOURCES;LINK_LIBRARIES;INSTALL_HEADERS;DEPENDS;INCLUDE_DIRS;DEFINITIONS;HEADER_ROOT_DIR;LIBRARY_ROOT_DIR;INSTALL_FULL_PATH_DIR;EMPTY_PREFIX;COMPILE_OPTIONS;VERSION"
${ARGN}
)
+ message(STATUS "Building library ${lib}")
+
+ # Clear target_libs
+ unset(TARGET_LIBS)
+
if (ARG_SHARED)
list(APPEND TARGET_LIBS
${lib}.shared
@@ -128,13 +137,13 @@ macro(build_library lib)
endif()
if (WIN32)
- target_compile_options(${library} PRIVATE)
+ target_compile_options(${library} PRIVATE ${ARG_COMPILE_OPTIONS})
set_target_properties(${library}
PROPERTIES
WINDOWS_EXPORT_ALL_SYMBOLS TRUE
)
else ()
- target_compile_options(${library} PRIVATE -Wall)
+ target_compile_options(${library} PRIVATE -Wall ${ARG_COMPILE_OPTIONS})
set_target_properties(${library}
PROPERTIES
OUTPUT_NAME ${lib}
@@ -157,7 +166,14 @@ macro(build_library lib)
)
endif()
- set(INSTALL_LIB_PATH ${CMAKE_INSTALL_LIBDIR})
+ if(ARG_VERSION)
+ set_target_properties(${library}
+ PROPERTIES
+ VERSION ${ARG_VERSION}
+ )
+ endif()
+
+ set(INSTALL_LIB_PATH "${CMAKE_INSTALL_LIBDIR}/${ARG_LIBRARY_ROOT_DIR}")
if (ARG_INSTALL_FULL_PATH_DIR)
set(INSTALL_LIB_PATH ${ARG_INSTALL_FULL_PATH_DIR})
@@ -178,8 +194,8 @@ macro(build_library lib)
# install headers
if(ARG_INSTALL_HEADERS)
- if (NOT ARG_INSTALL_ROOT_DIR)
- set(ARG_INSTALL_ROOT_DIR "hicn")
+ if (NOT ARG_HEADER_ROOT_DIR)
+ set(ARG_HEADER_ROOT_DIR "hicn")
endif()
list(APPEND local_comps
@@ -197,7 +213,7 @@ macro(build_library lib)
if ("${dir}" STREQUAL includes)
set(dir "")
endif()
- if ("${dir}" STREQUAL ${ARG_INSTALL_ROOT_DIR})
+ if ("${dir}" STREQUAL ${ARG_HEADER_ROOT_DIR})
set(dir "")
endif()
else()
@@ -210,12 +226,60 @@ macro(build_library lib)
endif()
install(
FILES ${file}
- DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${ARG_INSTALL_ROOT_DIR}/${dir}
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${ARG_HEADER_ROOT_DIR}/${dir}
COMPONENT ${COMPONENT}
)
endforeach()
endif()
endmacro()
+macro (build_module module)
+ cmake_parse_arguments(ARG
+ "SHARED;STATIC;NO_DEV"
+ "COMPONENT;"
+ "SOURCES;LINK_LIBRARIES;INSTALL_HEADERS;DEPENDS;INCLUDE_DIRS;DEFINITIONS;HEADER_ROOT_DIR;LIBRARY_ROOT_DIR;INSTALL_FULL_PATH_DIR;EMPTY_PREFIX;COMPILE_OPTIONS;VERSION"
+ ${ARGN}
+ )
+
+ message(STATUS "Building module ${module}")
+
+ build_library(${module}
+ SHARED
+ SOURCES ${ARG_SOURCES}
+ LINK_LIBRARIES ${ARG_LINK_LIBRARIES}
+ INSTALL_HEADERS ${ARG_INSTALL_HEADERS}
+ DEPENDS ${ARG_DEPENDS}
+ COMPONENT lib${LIBTRANSPORT}
+ INCLUDE_DIRS ${ARG_INCLUDE_DIRS}
+ HEADER_ROOT_DIR ${ARG_HEADER_ROOT_DIR}
+ LIBRARY_ROOT_DIR ${ARG_LIBRARY_ROOT_DIR}
+ INSTALL_FULL_PATH_DIR ${ARG_INSTALL_FULL_PATH_DIR}
+ DEFINITIONS ${ARG_DEFINITIONS}
+ EMPTY_PREFIX ${ARG_EMPTY_PREFIX}
+ COMPILE_OPTIONS ${ARG_COMPILE_OPTIONS}
+ VERSION ${ARG_VERSION}
+ )
+
+ if (${CMAKE_SYSTEM_NAME} MATCHES Darwin)
+ set(LINK_FLAGS "-Wl,-undefined,dynamic_lookup")
+ elseif(${CMAKE_SYSTEM_NAME} MATCHES iOS)
+ set(LINK_FLAGS "-Wl,-undefined,dynamic_lookup")
+ elseif(${CMAKE_SYSTEM_NAME} MATCHES Linux)
+ set(LINK_FLAGS "-Wl,-unresolved-symbols=ignore-all")
+ elseif(${CMAKE_SYSTEM_NAME} MATCHES Windows)
+ set(LINK_FLAGS "/wd4275")
+ else()
+ message(FATAL_ERROR "Trying to build module on a not supportd platform. Aborting.")
+ endif()
+
+ set_target_properties(${module}.shared
+ PROPERTIES
+ LINKER_LANGUAGE C
+ PREFIX ""
+ LINK_FLAGS ${LINK_FLAGS}
+ )
+
+endmacro(build_module)
+
include(IosMacros)
include(WindowsMacros)
diff --git a/cmake/Modules/FindCollectd.cmake b/cmake/Modules/FindCollectd.cmake
index 76d2df43f..244fd14e5 100644
--- a/cmake/Modules/FindCollectd.cmake
+++ b/cmake/Modules/FindCollectd.cmake
@@ -25,21 +25,15 @@ find_path(COLLECTD_INCLUDE_DIR collectd.h
DOC "Find the collectd includes"
)
-find_path(COLLECTD_COMMON_INCLUDE_DIR common.h
- HINTS ${COLLECTD_SEARCH_PATH_LIST}
- PATH_SUFFIXES include/collectd/core/daemon/ utils/common/
- DOC "Find the collectd includes"
-)
-
find_path(COLLECTD_CONFIG_INCLUDE_DIR config.h
HINTS ${COLLECTD_SEARCH_PATH_LIST}
PATH_SUFFIXES include/collectd/core/
DOC "Find the collectd includes"
)
-message(STATUS ${COLLECTD_INCLUDE_DIR} ${COLLECTD_COMMON_INCLUDE_DIR} ${COLLECTD_CONFIG_INCLUDE_DIR})
+message(STATUS ${COLLECTD_INCLUDE_DIR} ${COLLECTD_CONFIG_INCLUDE_DIR})
-set(COLLECTD_INCLUDE_DIRS ${COLLECTD_INCLUDE_DIR} ${COLLECTD_COMMON_INCLUDE_DIR} ${COLLECTD_CONFIG_INCLUDE_DIR})
+set(COLLECTD_INCLUDE_DIRS ${COLLECTD_INCLUDE_DIR} ${COLLECTD_CONFIG_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Collectd DEFAULT_MSG COLLECTD_INCLUDE_DIRS)
diff --git a/cmake/Modules/FindLibFec.cmake b/cmake/Modules/FindLibFec.cmake
new file mode 100644
index 000000000..f8b33ad6b
--- /dev/null
+++ b/cmake/Modules/FindLibFec.cmake
@@ -0,0 +1,24 @@
+set(LIBFEC_SEARCH_PATH_LIST
+ ${LIBFEC_HOME}
+ $ENV{DEPENDENCIES}
+ $ENV{LIBFEC_HOME}
+ /usr/local
+ /opt
+ /usr
+ )
+
+find_path(LIBFEC_INCLUDE_DIR fec/version.h
+ HINTS ${LIBFEC_SEARCH_PATH_LIST}
+ PATH_SUFFIXES include
+ DOC "Find the LibFec includes" )
+
+find_library(LIBFEC_LIBRARY NAMES fec
+ HINTS ${LIBFEC_SEARCH_PATH_LIST}
+ PATH_SUFFIXES lib
+ DOC "Find the LibFec libraries" )
+
+set(LIBFEC_LIBRARIES ${LIBFEC_LIBRARY})
+set(LIBFEC_INCLUDE_DIRS ${LIBFEC_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(LibFec DEFAULT_MSG LIBFEC_LIBRARY LIBFEC_INCLUDE_DIR) \ No newline at end of file
diff --git a/cmake/Modules/FindLibRely.cmake b/cmake/Modules/FindLibRely.cmake
new file mode 100644
index 000000000..4b8960041
--- /dev/null
+++ b/cmake/Modules/FindLibRely.cmake
@@ -0,0 +1,24 @@
+set(LIBRELY_SEARCH_PATH_LIST
+ ${LIBRELY_HOME}
+ $ENV{DEPENDENCIES}
+ $ENV{LIBRELY_HOME}
+ /usr/local
+ /opt
+ /usr
+ )
+
+find_path(LIBRELY_INCLUDE_DIR rely/version.hpp
+ HINTS ${LIBRELY_SEARCH_PATH_LIST}
+ PATH_SUFFIXES include
+ DOC "Find the LibRely includes" )
+
+find_library(LIBRELY_LIBRARY NAMES rely
+ HINTS ${LIBRELY_SEARCH_PATH_LIST}
+ PATH_SUFFIXES lib
+ DOC "Find the LibRely libraries" )
+
+set(LIBRELY_LIBRARIES ${LIBRELY_LIBRARY})
+set(LIBRELY_INCLUDE_DIRS ${LIBRELY_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(LibRely DEFAULT_MSG LIBRELY_LIBRARY LIBRELY_INCLUDE_DIR) \ No newline at end of file
diff --git a/cmake/Modules/FindLibconfig++.cmake b/cmake/Modules/FindLibconfig++.cmake
new file mode 100644
index 000000000..8dfc5fbe8
--- /dev/null
+++ b/cmake/Modules/FindLibconfig++.cmake
@@ -0,0 +1,44 @@
+set(LIBCONFIG_SEARCH_PATH_LIST
+ ${LIBCONFIG_HOME}
+ $ENV{LIBCONFIG_HOME}
+ /usr/local
+ /opt
+ /usr
+)
+
+find_path(LIBCONFIG_INCLUDE_DIR libconfig.h++
+ HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
+ PATH_SUFFIXES include
+ DOC "Find the libconfig include"
+)
+
+if (WIN32)
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ find_library(LIBCONFIG_CPP_LIBRARIES NAMES libconfig++.lib
+ HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
+ PATH_SUFFIXES lib/x64
+ DOC "Find the libconfig libraries"
+ )
+ elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
+ find_library(LIBCONFIG_CPP_LIBRARIES NAMES libconfig++.lib
+ HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
+ PATH_SUFFIXES lib/x32
+ DOC "Find the libconfig libraries"
+ )
+ endif()
+else()
+ find_library(LIBCONFIG_CPP_LIBRARY NAMES config++
+ HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
+ PATH_SUFFIXES lib
+ DOC "Find the libconfig++ libraries"
+ )
+endif()
+
+set(LIBCONFIG_CPP_LIBRARIES ${LIBCONFIG_CPP_LIBRARY})
+set(LIBCONFIG_INCLUDE_DIRS ${LIBCONFIG_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Libconfig++ LIBCONFIG_CPP_LIBRARIES LIBCONFIG_INCLUDE_DIRS)
+
+
+mark_as_advanced(LIBCONFIG_CPP_LIBRARIES LIBCONFIG_INCLUDE_DIRS)
diff --git a/cmake/Modules/FindLibconfig.cmake b/cmake/Modules/FindLibconfig.cmake
new file mode 100644
index 000000000..55d2a0fad
--- /dev/null
+++ b/cmake/Modules/FindLibconfig.cmake
@@ -0,0 +1,43 @@
+set(LIBCONFIG_SEARCH_PATH_LIST
+ ${LIBCONFIG_HOME}
+ $ENV{LIBCONFIG_HOME}
+ /usr/local
+ /opt
+ /usr
+)
+
+find_path(LIBCONFIG_INCLUDE_DIR libconfig.h
+ HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
+ PATH_SUFFIXES include
+ DOC "Find the libconfig include"
+)
+
+if (WIN32)
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ find_library(LIBCONFIG_LIBRARY NAMES libconfig.lib
+ HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
+ PATH_SUFFIXES lib/x64
+ DOC "Find the libconfig libraries"
+ )
+ elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
+ find_library(LIBCONFIG_LIBRARY NAMES libconfig.lib
+ HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
+ PATH_SUFFIXES lib/x32
+ DOC "Find the libconfig libraries"
+ )
+ endif()
+else()
+ find_library(LIBCONFIG_LIBRARY NAMES config
+ HINTS ${LIBCONFIG_SEARCH_PATH_LIST}
+ PATH_SUFFIXES lib
+ DOC "Find the libconfig libraries"
+ )
+endif()
+
+set(LIBCONFIG_LIBRARIES ${LIBCONFIG_LIBRARY})
+set(LIBCONFIG_INCLUDE_DIRS ${LIBCONFIG_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Libconfig LIBCONFIG_LIBRARIES LIBCONFIG_INCLUDE_DIRS)
+
+mark_as_advanced(LIBCONFIG_LIBRARIES LIBCONFIG_INCLUDE_DIRS)
diff --git a/cmake/Modules/FindLibhicn.cmake b/cmake/Modules/FindLibhicn.cmake
index 38775be6a..5f241a6cd 100644
--- a/cmake/Modules/FindLibhicn.cmake
+++ b/cmake/Modules/FindLibhicn.cmake
@@ -44,7 +44,7 @@ find_library(HICN_LIBRARY NAMES hicn
set(HICN_LIBRARIES ${HICN_LIBRARY})
if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
-set(HICN_LIBRARIES ${HICN_LIBRARIES} log)
+ set(HICN_LIBRARIES ${HICN_LIBRARIES} log)
endif()
set(HICN_INCLUDE_DIRS ${HICN_INCLUDE_DIR})
diff --git a/cmake/Modules/GTestImport.cmake b/cmake/Modules/GTestImport.cmake
index cdca922d6..d9d182578 100644
--- a/cmake/Modules/GTestImport.cmake
+++ b/cmake/Modules/GTestImport.cmake
@@ -18,13 +18,12 @@ include(ExternalProject)
ExternalProject_Add(gtest
URL https://github.com/google/googletest/archive/v1.10.x.zip
PREFIX ${CMAKE_BINARY_DIR}/gtest
+ BUILD_BYPRODUCTS
+ ${CMAKE_BINARY_DIR}/gtest/src/gtest-build/lib/libgmock_main.a
+ ${CMAKE_BINARY_DIR}/gtest/src/gtest-build/lib/libgmock.a
+ ${CMAKE_BINARY_DIR}/gtest/src/gtest-build/lib/libgtest_main.a
+ ${CMAKE_BINARY_DIR}/gtest/src/gtest-build/lib/libgtest.a
INSTALL_COMMAND ""
-
- # Necessary to build using ninja
- BUILD_BYPRODUCTS "${CMAKE_BINARY_DIR}/gtest/src/gtest-build/lib/libgmock.a"
- BUILD_BYPRODUCTS "${CMAKE_BINARY_DIR}/gtest/src/gtest-build/lib/libgmock_main.a"
- BUILD_BYPRODUCTS "${CMAKE_BINARY_DIR}/gtest/src/gtest-build/lib/libgtest_main.a"
- BUILD_BYPRODUCTS "${CMAKE_BINARY_DIR}/gtest/src/gtest-build/lib/libgtest.a"
)
ExternalProject_Get_Property(gtest source_dir binary_dir)
@@ -35,4 +34,12 @@ message (STATUS "GTest libs: ${binary_dir}/lib/libgmock_main.a ${binary_dir}/lib
set(GTEST_INCLUDE_DIRS ${source_dir}/googlemock/include ${source_dir}/googletest/include)
set(GTEST_LIBRARIES ${binary_dir}/lib/libgmock_main.a ${binary_dir}/lib/libgmock.a ${binary_dir}/lib/libgtest_main.a ${binary_dir}/lib/libgtest.a)
-enable_testing() \ No newline at end of file
+macro(add_test_internal test)
+ if(${CMAKE_VERSION} VERSION_GREATER "3.10.0")
+ gtest_discover_tests(${test}-bin TEST_PREFIX new:)
+ else()
+ add_test(NAME ${test}-bin COMMAND ${test})
+ endif()
+endmacro(add_test_internal)
+
+enable_testing()
diff --git a/cmake/Modules/License.txt b/cmake/Modules/License.txt
new file mode 100644
index 000000000..4d84c0dc7
--- /dev/null
+++ b/cmake/Modules/License.txt
@@ -0,0 +1,12 @@
+Copyright (c) 2017-2021 Cisco and/or its affiliates.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at:
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License. \ No newline at end of file
diff --git a/cmake/Modules/Packager.cmake b/cmake/Modules/Packager.cmake
index 1edfd671d..f27479188 100644
--- a/cmake/Modules/Packager.cmake
+++ b/cmake/Modules/Packager.cmake
@@ -26,10 +26,10 @@ function(get_next_version VERSION NEXT_VERSION)
list(GET VER_NUMBERS 0 major)
list(GET VER_NUMBERS 1 minor)
- math(EXPR minor "${minor} + 3")
+ math(EXPR minor "${minor} + 4")
if (minor GREATER 12)
- set(minor "1")
+ math(EXPR minor "${minor} % 12")
math(EXPR major "${major} + 1")
endif()
@@ -52,17 +52,17 @@ macro(extract_version)
if (NOT VER)
set(VER "v1.2-0-gcafe")
endif()
-
message(STATUS "Git describe output: ${VER}")
- string(REGEX REPLACE "v([0-9]+).([0-9]+).*-([0-9]+)-(g[0-9a-f]+)" "\\1;\\2;\\3;\\4" VER ${VER})
+ string(REGEX REPLACE "v([0-9]+).([0-9]+)-?(.*)?-([0-9]+)-(g[0-9a-f]+)" "\\1;\\2;\\3;\\4;\\5;" VER ${VER})
list(GET VER 0 VERSION_MAJOR)
list(GET VER 1 VERSION_MINOR)
- list(GET VER 2 VERSION_REVISION)
- list(GET VER 3 COMMIT_NAME)
+ list(GET VER 2 RELEASE_CANDIDATE)
+ list(GET VER 3 VERSION_REVISION)
+ list(GET VER 4 COMMIT_NAME)
endmacro(extract_version)
-macro(make_packages)
+function(make_packages)
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
# parse /etc/os-release
file(READ "/etc/os-release" os_version)
@@ -78,6 +78,7 @@ macro(make_packages)
message(STATUS "Version major: ${VERSION_MAJOR}")
message(STATUS "Version minor: ${VERSION_MINOR}")
+ message(STATUS "Release: ${RELEASE_CANDIDATE}")
message(STATUS "Revision: ${VERSION_REVISION}")
message(STATUS "Commit hash: ${COMMIT_NAME}")
@@ -91,24 +92,43 @@ macro(make_packages)
else()
set(bld "b$ENV{BUILD_NUMBER}")
endif()
-
- message("Build number is: ${bld}")
+ message(STATUS "Build number is: ${bld}")
#define DEB and RPM version numbers
- if(${commit_num} EQUAL 0)
- set(deb_ver "${tag}")
- set(rpm_ver "${tag}")
+ if(NOT RELEASE_CANDIDATE)
+ if (commit_num)
+ set(deb_ver "${tag}.${commit_num}-release")
+ set(rpm_ver "${tag}.${commit_num}")
+ else()
+ set(deb_ver "${tag}-release")
+ set(rpm_ver "${tag}")
+ endif()
+ set(rpm_release "release")
else()
- set(deb_ver "${tag}-${commit_num}-release")
- set(rpm_ver "${tag}-${commit_num}-release")
+ # TODO To be changed for next release with
+ # set(deb_ver "${tag}${RELEASE_CANDIDATE}~${commit_num}")
+ # set(rpm_ver "${tag}")
+ # set(rpm_release "${RELEASE_CANDIDATE}~${commit_num}")
+ set(deb_ver "${tag}-${commit_num}")
+ set(rpm_ver "${tag}-${commit_num}")
+ set(rpm_release "1")
endif()
+ message(STATUS "Version: ${deb_ver}")
+
get_next_version(${tag} next_version)
+ message(STATUS "Next version: ${next_version}")
get_cmake_property(components COMPONENTS)
list(REMOVE_ITEM components "Unspecified")
set(CPACK_COMPONENTS_ALL ${components})
+ list(LENGTH components N_COMPONENTS)
+
+ if (NOT N_COMPONENTS)
+ return()
+ endif()
+
if(OS_ID MATCHES "debian" OR OS_ID_LIKE MATCHES "debian")
set(CPACK_GENERATOR "DEB")
set(type "DEBIAN")
@@ -119,7 +139,7 @@ macro(make_packages)
OUTPUT_STRIP_TRAILING_WHITESPACE
)
- set(CPACK_PACKAGE_VERSION "${deb_ver}")
+ set(CPACK_${type}_PACKAGE_VERSION "${deb_ver}")
foreach(lc ${components})
if (${lc} MATCHES ".*Unspecified.*")
continue()
@@ -152,7 +172,8 @@ macro(make_packages)
OUTPUT_STRIP_TRAILING_WHITESPACE
)
- set(CPACK_PACKAGE_VERSION "${rpm_ver}")
+ set(CPACK_${type}_PACKAGE_VERSION "${rpm_ver}")
+ set(CPACK_${type}_PACKAGE_RELEASE "${rpm_release}")
foreach(lc ${components})
if (${lc} MATCHES ".*Unspecified.*")
continue()
@@ -162,7 +183,7 @@ macro(make_packages)
set(CPACK_${type}_${uc}_DESCRIPTION "${${lc}_DESCRIPTION}")
set(RPM_DEPS)
- if (NOT ${${lc}_DEB_DEPENDENCIES} STREQUAL "")
+ if (NOT ${${lc}_RPM_DEPENDENCIES} STREQUAL "")
string(REPLACE "stable_version" ${tag} RPM_DEPS ${${lc}_RPM_DEPENDENCIES})
string(REPLACE "next_version" ${next_version} RPM_DEPS ${RPM_DEPS})
endif()
@@ -176,7 +197,7 @@ macro(make_packages)
endif()
set(CPACK_RPM_${uc}_PACKAGE_NAME "${package_name}")
- set(CPACK_${type}_${uc}_FILE_NAME "${package_name}-${rpm_ver}.${arch}.rpm")
+ set(CPACK_${type}_${uc}_FILE_NAME "${package_name}-${rpm_ver}-${rpm_release}.${arch}.rpm")
if (NOT ${${lc}_RPM_POST_INSTALL_SCRIPT_FILE} STREQUAL "")
set(CPACK_RPM_${uc}_POST_INSTALL_SCRIPT_FILE "${${lc}_RPM_POST_INSTALL_SCRIPT_FILE}")
@@ -199,8 +220,109 @@ macro(make_packages)
set(CPACK_COMPONENTS_IGNORE_GROUPS 1)
set(CPACK_${CPACK_GENERATOR}_COMPONENT_INSTALL ON)
set(CPACK_${type}_PACKAGE_MAINTAINER "HICN Team")
- set(CPACK_${type}_PACKAGE_RELEASE 1)
+ set(CPACK_PACKAGE_CONTACT ${CONTACT})
include(CPack)
endif()
+ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR ${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ set(CMAKE_SKIP_BUILD_RPATH FALSE)
+ set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
+ set(CMAKE_INSTALL_RPATH /opt/hicn)
+ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+ set(CPACK_SET_DESTDIR true)
+ set(CMAKE_INSTALL_RPATH "\${CPACK_INSTALL_PREFIX}")
+ set(CMAKE_SKIP_INSTALL_RPATH FALSE)
+ set(HICN_DEPENDECIES_INSTALLER "${LIBTRANSPORT_LIBRARIES_LIST};${FACEMGR_LIBRARY_LIST};${APPS_LIBRARY_LIST}")
+ separate_arguments(HICN_DEPENDECIES_INSTALLER)
+ foreach (HICN_DEPENDECY ${HICN_DEPENDECIES_INSTALLER})
+ get_filename_component(DEPENDENCY_NAME "${HICN_DEPENDECY}" NAME)
+ get_filename_component(DEPENDENCY "${HICN_DEPENDECY}" REALPATH)
+ get_filename_component(DEPENDENCY_PATH "${DEPENDENCY}" DIRECTORY)
+ install(FILES ${DEPENDENCY} DESTINATION lib COMPONENT dependencies)
+ endforeach()
+ set(CPACK_PACKAGE_NAME "hicn")
+ extract_version()
+ set(CPACK_PACKAGE_VENDOR "${PACKAGE_VENDOR}")
+ set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "hICN")
+ set(CPACK_PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}")
+ set(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}")
+ set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}")
+ set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_REVISION}")
+ set(CPACK_PACKAGE_INSTALL_DIRECTORY "hICN Components")
+ set(CPACK_COMPONENTS_ALL dependencies ${HICN_UTILS} ${HICN_LIGHT} ${HICN_APPS} ${FACEMGR} lib${LIBTRANSPORT} ${LIBTRANSPORT}-dev lib${LIBHICN} ${LIBHICN}-dev ${HICN_UTILS}-dev ${HICN_LIGHT}-dev ${HICN_APPS}-dev ${FACEMGR}-dev)
+ set(CPACK_COMPONENT_DEPENDENCIES_DISPLAY_NAME "Dependencies")
+ if (HICN_UTILS)
+ string(TOUPPER ${HICN_UTILS} HICN_UTILS_UPPERCASE)
+ set(CPACK_COMPONENT_${HICN_UTILS_UPPERCASE}_DISPLAY_NAME "hICN utils")
+ set(CPACK_COMPONENT_${HICN_UTILS_UPPERCASE}_GROUP "Executables")
+ set(CPACK_COMPONENT_${HICN_UTILS_UPPERCASE}_INSTALL_TYPES Full)
+ set(CPACK_COMPONENT_${HICN_APPS_DEV_UPPERCASE}_DISPLAY_NAME "hicn-apps headers")
+ endif()
+ string(TOUPPER ${HICN_LIGHT} HICN_LIGHT_UPPERCASE)
+ if (HICN_APPS)
+ string(TOUPPER ${HICN_APPS} HICN_APPS_UPPERCASE)
+ string(TOUPPER ${HICN_APPS}-dev HICN_APPS_DEV_UPPERCASE)
+ set(CPACK_COMPONENT_${HICN_APPS_UPPERCASE}_DISPLAY_NAME "hICN apps")
+ set(CPACK_COMPONENT_${HICN_APPS_DEV_UPPERCASE}_GROUP "Headers")
+ set(CPACK_COMPONENT_${HICN_APPS_UPPERCASE}_INSTALL_TYPES Full)
+ set(CPACK_COMPONENT_${HICN_APPS_DEV_UPPERCASE}_INSTALL_TYPES Full)
+ endif()
+ if (FACEMGR)
+ string(TOUPPER ${FACEMGR} FACEMGR_UPPERCASE)
+ string(TOUPPER ${FACEMGR}-dev FACEMGR_DEV_UPPERCASE)
+ set(CPACK_COMPONENT_${FACEMGR_DEV_UPPERCASE}_DISPLAY_NAME "facemgr headers")
+ set(CPACK_COMPONENT_${FACEMGR_UPPERCASE}_DISPLAY_NAME "facemgr")
+ set(CPACK_COMPONENT_${FACEMGR_UPPERCASE}_GROUP "Executables")
+ set(CPACK_COMPONENT_${FACEMGR_DEV_UPPERCASE}_GROUP "Headers")
+ set(CPACK_COMPONENT_${FACEMGR_UPPERCASE}_INSTALL_TYPES Full)
+ set(CPACK_COMPONENT_${FACEMGR_DEV_UPPERCASE}_INSTALL_TYPES Full)
+ endif()
+ string(TOUPPER lib${LIBTRANSPORT} LIBTRANSPORT_UPPERCASE)
+ string(TOUPPER ${LIBTRANSPORT}-dev LIBTRANSPORT_DEV_UPPERCASE)
+ string(TOUPPER lib${LIBHICN} LIBHICN_UPPERCASE)
+ string(TOUPPER ${LIBHICN}-dev LIBHICN_DEV_UPPERCASE)
+ string(TOUPPER ${HICN_UTILS}-dev HICN_UTILS_DEV_UPPERCASE)
+ string(TOUPPER ${HICN_LIGHT}-dev HICN_LIGHT_DEV_UPPERCASE)
+ set(CPACK_COMPONENT_${HICN_LIGHT_UPPERCASE}_DISPLAY_NAME "hICN light apps")
+ set(CPACK_COMPONENT_${LIBTRANSPORT_UPPERCASE}_DISPLAY_NAME "libtransport libs")
+ set(CPACK_COMPONENT_${LIBHICN_UPPERCASE}_DISPLAY_NAME "hicn libs")
+ set(CPACK_COMPONENT_${LIBTRANSPORT_DEV_UPPERCASE}_DISPLAY_NAME "libtransport headers")
+ set(CPACK_COMPONENT_${LIBHICN_DEV_UPPERCASE}_DISPLAY_NAME "hicn headers")
+ set(CPACK_COMPONENT_${HICN_UTILS_DEV_UPPERCASE}_DISPLAY_NAME "hicn utils headers")
+ set(CPACK_COMPONENT_${HICN_LIGHT_DEV_UPPERCASE}_DISPLAY_NAME "hicn-light headers")
+ set (CPACK_RESOURCE_FILE_LICENSE
+ "${PROJECT_SOURCE_DIR}/cmake/Modules/License.txt")
+ set(CPACK_COMPONENT_DEPENDENCIES_DESCRIPTION
+ "All dependency libreries")
+ set(CPACK_COMPONENT_${HICN_LIGHT_UPPERCASE}_GROUP "Executables")
+ set(CPACK_COMPONENT_${HICN_APPS_UPPERCASE}_GROUP "Executables")
+ set(CPACK_COMPONENT_${LIBTRANSPORT_UPPERCASE}_GROUP "Libraries")
+ set(CPACK_COMPONENT_${LIBHICN_UPPERCASE}_GROUP "Libraries")
+ set(CPACK_COMPONENT_${LIBTRANSPORT_DEV_UPPERCASE}_GROUP "Headers")
+ set(CPACK_COMPONENT_${LIBHICN_DEV_UPPERCASE}_GROUP "Headers")
+ set(CPACK_COMPONENT_${HICN_UTILS_DEV_UPPERCASE}_GROUP "Headers")
+ set(CPACK_COMPONENT_${HICN_LIGHT_DEV_UPPERCASE}_GROUP "Headers")
+ set(CPACK_COMPONENT_DEPENDENCIES_GROUP "Dependencies")
+ set(CPACK_COMPONENT_GROUP_DEVELOPMENT_EXPANDED ON)
+ set(CPACK_COMPONENT_GROUP_DEPENDENCIES_DESCRIPTION
+ "All dependency libreries")
+ set(CPACK_ALL_INSTALL_TYPES Full Developer)
+ set(CPACK_INSTALL_TYPE_FULL_DISPLAY_NAME "Everything")
+ set(CPACK_COMPONENT_${HICN_LIGHT_UPPERCASE}_INSTALL_TYPES Full)
+ set(CPACK_COMPONENT_${LIBTRANSPORT_UPPERCASE}_INSTALL_TYPES Full)
+ set(CPACK_COMPONENT_${LIBHICN_UPPERCASE}_INSTALL_TYPES Full)
+ set(CPACK_COMPONENT_${LIBTRANSPORT_DEV_UPPERCASE}_INSTALL_TYPES Full)
+ set(CPACK_COMPONENT_${LIBHICN_DEV_UPPERCASE}_INSTALL_TYPES Full)
+ set(CPACK_COMPONENT_${HICN_UTILS_DEV_UPPERCASE}_INSTALL_TYPES Full)
+ set(CPACK_COMPONENT_${HICN_LIGHT_DEV_UPPERCASE}_INSTALL_TYPES Full)
+ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ set(CMAKE_INSTALL_RPATH /opt/hicn)
+
+ set(CPACK_INSTALL_PREFIX "/opt/hicn")
+ set(CPACK_GENERATOR productbuild)
+ set( CPACK_PRE_BUILD_SCRIPTS "${PROJECT_SOURCE_DIR}/cmake/Modules/PostInstall.cmake")
+ else()
+ set(CPACK_INSTALL_PREFIX "c:/Program Files/hicn")
+ endif()
+ include(CPack)
endif()
-endmacro()
+endfunction()
diff --git a/cmake/Modules/PostInstall.cmake b/cmake/Modules/PostInstall.cmake
new file mode 100644
index 000000000..89c7b9f68
--- /dev/null
+++ b/cmake/Modules/PostInstall.cmake
@@ -0,0 +1,83 @@
+function(change_rpath LIB_PATH TYPE)
+ execute_process (
+ COMMAND bash -c "ls ${LIB_PATH}"
+ OUTPUT_VARIABLE ITEMS
+ )
+ string(REPLACE "\n" ";" ITEMS ${ITEMS})
+
+ separate_arguments(ITEMS)
+ foreach (ITEM ${ITEMS})
+ if (NOT ITEM MATCHES ".a$")
+ if (TYPE STREQUAL "LIB")
+ execute_process (
+ COMMAND bash -c "otool -L ${LIB_PATH}/${ITEM} | head -2 | tail -1| sed -e 's/^[[:space:]]*//'|awk '{print $1;}'"
+ OUTPUT_VARIABLE OTOOL_OUTPUT
+ )
+ string(REPLACE "\n" "" OTOOL_OUTPUT ${OTOOL_OUTPUT})
+
+ execute_process (
+ COMMAND bash -c "basename ${OTOOL_OUTPUT}| sed -e 's/^[[:space:]]*//'"
+ OUTPUT_VARIABLE BASENAME
+ )
+ string(REPLACE "\n" "" BASENAME ${BASENAME})
+ execute_process (
+ COMMAND bash -c "install_name_tool -id ${CPACK_INSTALL_PREFIX}/${BASENAME} ${LIB_PATH}/${ITEM}"
+ OUTPUT_VARIABLE OUTPUT_INSTALL_NAME_TOOL
+ )
+ #change rpath
+ execute_process (
+ COMMAND bash -c "otool -L ${LIB_PATH}/${ITEM} | tail -n +3| sed -e 's/^[[:space:]]*//'|awk '{print $1;}'"
+ OUTPUT_VARIABLE OTOOL_OUTPUTS
+ )
+ else ()
+ #change rpath
+ execute_process (
+ COMMAND bash -c "otool -L ${LIB_PATH}/${ITEM} | tail -n +2| sed -e 's/^[[:space:]]*//'|awk '{print $1;}'"
+ OUTPUT_VARIABLE OTOOL_OUTPUTS
+ )
+ endif ()
+ string(REPLACE "\n" ";" OTOOL_OUTPUTS ${OTOOL_OUTPUTS})
+ separate_arguments(OTOOL_OUTPUTS)
+ foreach (OTOOL_OUTPUT ${OTOOL_OUTPUTS})
+ execute_process (
+ COMMAND bash -c "basename ${OTOOL_OUTPUT}| sed -e 's/^[[:space:]]*//'"
+ OUTPUT_VARIABLE BASENAME
+ )
+ string(REPLACE "\n" "" BASENAME ${BASENAME})
+ execute_process (
+ COMMAND bash -c "dirname ${OTOOL_OUTPUT}| sed -e 's/^[[:space:]]*//'"
+ OUTPUT_VARIABLE DIRNAME
+ )
+ string(REPLACE "\n" "" DIRNAME ${DIRNAME})
+ if(NOT DIRNAME MATCHES "/usr/lib")
+ execute_process (
+ COMMAND bash -c "install_name_tool -change ${OTOOL_OUTPUT} ${CPACK_INSTALL_PREFIX}/${BASENAME} ${LIB_PATH}/${ITEM}"
+ OUTPUT_VARIABLE OUTPUT_INSTALL_NAME_TOOL
+ )
+ endif()
+
+ endforeach()
+ endif()
+ endforeach()
+endfunction()
+string(TOLOWER ${CPACK_COMPONENT_DEPENDENCIES_GROUP} CPACK_COMPONENT_DEPENDENCIES_GROUP )
+set(LIB_PATH "${CPACK_TEMPORARY_DIRECTORY}/${CPACK_COMPONENT_DEPENDENCIES_GROUP}${CPACK_INSTALL_PREFIX}/lib")
+change_rpath(${LIB_PATH} LIB)
+
+set(LIB_PATH "${CPACK_TEMPORARY_DIRECTORY}/facemgr${CPACK_INSTALL_PREFIX}/lib")
+change_rpath(${LIB_PATH} LIB)
+set(LIB_PATH "${CPACK_TEMPORARY_DIRECTORY}/libhicntransport${CPACK_INSTALL_PREFIX}/lib")
+change_rpath(${LIB_PATH} LIB)
+set(LIB_PATH "${CPACK_TEMPORARY_DIRECTORY}/libhicn${CPACK_INSTALL_PREFIX}/lib")
+change_rpath(${LIB_PATH} LIB)
+
+set(EXE_PATH "${CPACK_TEMPORARY_DIRECTORY}/hicn-utils${CPACK_INSTALL_PREFIX}/bin")
+change_rpath(${EXE_PATH} EXE)
+set(EXE_PATH "${CPACK_TEMPORARY_DIRECTORY}/hicn-light${CPACK_INSTALL_PREFIX}/bin")
+change_rpath(${EXE_PATH} EXE)
+set(EXE_PATH "${CPACK_TEMPORARY_DIRECTORY}/hicn-apps${CPACK_INSTALL_PREFIX}/bin")
+change_rpath(${EXE_PATH} EXE)
+set(EXE_PATH "${CPACK_TEMPORARY_DIRECTORY}/facemgr${CPACK_INSTALL_PREFIX}/bin")
+change_rpath(${EXE_PATH} EXE)
+#set(EXE_PATH "${CPACK_TEMPORARY_DIRECTORY}/hicnctrl${CPACK_INSTALL_PREFIX}/bin")
+#change_rpath(${EXE_PATH} EXE)
diff --git a/cmake/Modules/ServiceScript.cmake b/cmake/Modules/ServiceScript.cmake
index 110aa816b..8e7056a5a 100644
--- a/cmake/Modules/ServiceScript.cmake
+++ b/cmake/Modules/ServiceScript.cmake
@@ -39,4 +39,4 @@ cmake_parse_arguments(ARG
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ${CMAKE_INSTALL_PREFIX} STREQUAL "/usr")
install (FILES ${script} DESTINATION ${SYSTEMD_SERVICE_FOLDER} COMPONENT ${ARG_COMPONENT})
endif()
-endmacro(install_service_script) \ No newline at end of file
+endmacro(install_service_script)
diff --git a/ctrl/facemgr/CMakeLists.txt b/ctrl/facemgr/CMakeLists.txt
index 4290d9cd6..ba9de9464 100644
--- a/ctrl/facemgr/CMakeLists.txt
+++ b/ctrl/facemgr/CMakeLists.txt
@@ -42,8 +42,7 @@ if (NOT CMAKE_BUILD_TYPE)
endif()
if(CMAKE_BUILD_TYPE MATCHES Debug)
-message("IN DEBUG MODE")
-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3")
+ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3")
endif()
set(CMAKE_MODULE_PATH
@@ -59,7 +58,7 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)
-find_package_wrapper(Config REQUIRED)
+find_package_wrapper(Libconfig REQUIRED)
find_package_wrapper(LibEvent REQUIRED)
set(FACEMGR facemgr CACHE INTERNAL "" FORCE)
@@ -95,6 +94,20 @@ add_subdirectory(src)
include(Packaging)
+# Install service file in linux systems
+include(ServiceScript)
+install_service_script(
+ ${CMAKE_CURRENT_SOURCE_DIR}/config/facemgr.service
+ COMPONENT ${FACEMGR}
+)
+
+# Configuration file
+set(FACEMGR_CONF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/config/facemgr.conf)
+set(FACEMGR_CONF_FOLDER "/etc/facemgr")
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+ install (FILES ${FACEMGR_CONF_FILE} DESTINATION ${FACEMGR_CONF_FOLDER} COMPONENT ${FACEMGR})
+endif()
+
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
include(Packager)
make_packages()
diff --git a/ctrl/facemgr/cmake/Modules/Packaging.cmake b/ctrl/facemgr/cmake/Modules/Packaging.cmake
index 3a7e5a85c..bb4fa42fa 100644
--- a/ctrl/facemgr/cmake/Modules/Packaging.cmake
+++ b/ctrl/facemgr/cmake/Modules/Packaging.cmake
@@ -25,7 +25,22 @@ set(${FACEMGR}_DEB_DEPENDENCIES
CACHE STRING "Dependencies for deb/rpm package."
)
+set(${HICN_LIGHT}_DEB_PACKAGE_CONTROL_EXTRA
+ "${CMAKE_CURRENT_SOURCE_DIR}/config/postinst;${CMAKE_CURRENT_SOURCE_DIR}/config/prerm"
+ CACHE STRING "Control scripts conffiles, postinst, postrm, prerm."
+)
+
set(${FACEMGR}_RPM_DEPENDENCIES
"libconfig, libevent-devel, lib${LIBHICNCTRL} >= stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
+
+set(${HICN_LIGHT}_RPM_POST_INSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_SOURCE_DIR}/config/post"
+ CACHE STRING "Install script that will be copied in the %post section"
+)
+
+set(${HICN_LIGHT}_RPM_PRE_UNINSTALL_SCRIPT_FILE
+ "${CMAKE_CURRENT_SOURCE_DIR}/config/preun"
+ CACHE STRING "Install script that will be copied in the %post section"
+)
diff --git a/ctrl/facemgr/config/facemgr.conf b/ctrl/facemgr/config/facemgr.conf
new file mode 100644
index 000000000..d9c6f5fa9
--- /dev/null
+++ b/ctrl/facemgr/config/facemgr.conf
@@ -0,0 +1,194 @@
+#
+# hICN facemgr configuration file
+#
+
+################################################################################
+# Global settings
+################################################################################
+
+global = {
+
+# Default type for face creation
+#
+# Values: "auto" | "native-udp" | "native-tcp" | "overlay-udp" | "overlay-tcp"
+# Default "auto"
+#
+#face_type = "auto";
+face_type = "overlay-udp"
+
+# Disable service discovery for overlay creation
+#
+# This is only meaningful for overlay_* face types. If service discovery is
+# disabled, only manually entered overlay information will be used, if any.
+# Otherwise, no face will be created.
+#
+# Values : true | false
+# Default: false
+#
+#disable_discovery = true;
+
+# Disable IPv4 face creation
+#
+# Values : true | false
+# Default: false
+#
+#disable_ipv4 = true;
+
+# Disable IPv6 face creation
+#
+# Values : true | false
+# Default: false
+#
+#disable_ipv6 = true;
+
+# overlay
+#
+# By default, no address is specified, and local and remote ports are set to
+# the standard value for hICN (9695).
+#
+
+};
+
+################################################################################
+# Per-interface rules
+################################################################################
+#
+# Rules allow to override the default behaviour of the face manager.
+#
+# The list of rules must be specified as follows (note that the last one has no
+# coma at the end) :
+#
+# rules = (
+# { ... },
+# { ... },
+# { ... }
+# );
+#
+# A rule is composed of match and override attributes, and has the following
+# syntax:
+#
+# {
+# match = {
+# interface_name = STRING;
+# interface_type = STRING;
+# };
+# override = {
+# face_type = STRING;
+# disable_discovery = BOOL;
+# ignore = BOOL;
+# tags = (STRING, STRING, STRING);
+# overlay = {
+# ipv4 = {
+# local_port = PORT;
+# remote_addr = IP_ADDRESS;
+# remote_port = PORT;
+# };
+# ipv6 = {
+# local_port = PORT;
+# remote_addr = IP_ADDRESS;
+# remote_port = PORT;
+# };
+# };
+# };
+# }
+#
+# Match attributes:
+#
+# Match attributes serve to identify rules and as such defining two rules with
+# similar matches is not allowed. However, overlapping match definitions are
+# possible, in which case only the first matching rule is considered.
+#
+# A match is composed of the name of an interface and/or its type (either
+# attribute is optional but at least one has to be specified).
+#
+# * interface_name - a string representing an interface name
+#
+# * interface_type - the type of interface to match
+#
+# Values: "wired" | "wifi" | "cellular"
+#
+# Override attributes:
+#
+# Those attributes are applied when all specified match attributes correspond,
+# and override general settings or default values.
+#
+# * face_type - type used for face creation
+#
+# Values: "auto" | "native_udp" | "native_tcp" | "overlay_udp" | "overlay_tcp"
+#
+# * disable_discovery - disable service discovery for overlay creation
+#
+# Values : true | false
+#
+# * ignore - a boolean indicating whether that interface should be ignored
+#
+# * TODO tags - a (possibly empty) list of tags to be associated to the created face.
+#
+# Values: "wired" | "wifi" | "cellular" | "trusted"
+#
+# * overlay
+#
+# An overlay specification is used to complement any information retrieved
+# through service discovery (or replace it if service discovery is
+# disabled).
+#
+# It is possible to specify values for IPv4, IPv6 or both.
+#
+# Note that it is not currently possible to set different settings for IPv4 and
+# IPv6 but overlay specifications.
+#
+#
+# Here are a few example of rule definitions:
+#
+# rules = (
+# # Ignore localhost interface
+# {
+# match = {
+# interface_name = "lo";
+# };
+# override = {
+# ignore = true;
+# };
+# },
+# # Set tags for unknown tunnnel interface
+# {
+# match = {
+# interface_name = "utun1";
+# };
+# override = {
+# tags = ("WIRED", "TRUSTED");
+# };
+# },
+# # Force cellular connections to use manually specified overlay faces
+# {
+# match = {
+# interface_type = "cellular",
+# };
+# override = {
+# overlay = {
+# ipv4 = {
+# local_port = 9695;
+# remote_addr = "10.60.16.14";
+# remote_port = 9695;
+# };
+# ipv6 = {
+# local_port = 9695;
+# remote_addr = "2001:420:44f1:10:20c:29ff:fef3:8f8f";
+# remote_port = 9695;
+# };
+# };
+# };
+# }
+# );
+#
+#rules = (
+#);
+
+################################################################################
+# Logging
+################################################################################
+
+log:
+{
+ log_level = "DEBUG";
+}
diff --git a/ctrl/facemgr/config/facemgr.service b/ctrl/facemgr/config/facemgr.service
new file mode 100644
index 000000000..0f9e818ea
--- /dev/null
+++ b/ctrl/facemgr/config/facemgr.service
@@ -0,0 +1,24 @@
+# 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.
+
+[Unit]
+Description=hICN face manager
+
+[Service]
+Environment=CONFIG=/etc/facemgr/facemgr.conf
+Environment=LOGFILE=/var/log/facemgr.log
+ExecStart=/usr/bin/facemgr -c ${CONFIG} 1>${LOGFILE} 2>&1
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/ctrl/facemgr/config/post b/ctrl/facemgr/config/post
new file mode 100755
index 000000000..7b2fd57fe
--- /dev/null
+++ b/ctrl/facemgr/config/post
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+if pidof systemd; then
+ systemctl enable facemgr
+fi
diff --git a/ctrl/facemgr/config/postinst b/ctrl/facemgr/config/postinst
new file mode 100755
index 000000000..4113b0eca
--- /dev/null
+++ b/ctrl/facemgr/config/postinst
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+systemctl enable facemgr
diff --git a/ctrl/facemgr/config/prerm b/ctrl/facemgr/config/prerm
new file mode 100755
index 000000000..b5c486ea5
--- /dev/null
+++ b/ctrl/facemgr/config/prerm
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+systemctl disable facemgr
diff --git a/ctrl/facemgr/config/preun b/ctrl/facemgr/config/preun
new file mode 100755
index 000000000..b5c486ea5
--- /dev/null
+++ b/ctrl/facemgr/config/preun
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+systemctl disable facemgr
diff --git a/ctrl/facemgr/examples/mobility/Makefile b/ctrl/facemgr/examples/mobility/Makefile
new file mode 100644
index 000000000..3b92d9d5f
--- /dev/null
+++ b/ctrl/facemgr/examples/mobility/Makefile
@@ -0,0 +1,23 @@
+EXEC = $(shell basename $$(pwd))
+CC = gcc
+
+CFLAGS = -std=gnu11 -O3 -Wall -Wextra -Wpedantic -Wstrict-aliasing
+
+SRC = $(wildcard *.c)
+OBJ = $(SRC:.c=.o)
+
+all: $(EXEC)
+
+${EXEC}: $(OBJ)
+ $(CC) -o $@ $^ $(LDFLAGS)
+
+%.o: %.c
+ $(CC) -o $@ -c $< $(CFLAGS)
+
+.PHONY: clean mrproper
+
+clean:
+ @rm -rf *.o
+
+mrproper: clean
+ @rm -rf $(EXEC)
diff --git a/ctrl/facemgr/examples/mobility/mobility.c b/ctrl/facemgr/examples/mobility/mobility.c
new file mode 100644
index 000000000..528951446
--- /dev/null
+++ b/ctrl/facemgr/examples/mobility/mobility.c
@@ -0,0 +1,88 @@
+/*
+ * Dummy server sending alternating bytes to all clients.
+ *
+ * This program can be used to trigger mobility events in the hICN forwarder, to
+ * switch from WiFi to LTE and back, at regular intervals.
+ *
+ * Test server using nc: nc -4kvul localhost 9533
+ */
+
+#include <arpa/inet.h> // inet_ntop
+#include <errno.h> // EINTR,. ..
+#include <netinet/in.h> // INET_ADDRSTRLEN, INET6_ADDRSTRLEN
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/timerfd.h>
+#include <sys/un.h> // sockaddr_un
+#include <unistd.h> // fcntl
+#include <fcntl.h> // fcntl
+
+#define MS2US(x) (x * 1000)
+
+/**
+ * \brief Main function
+ */
+int main(int argc, char **argv)
+{
+ int rc;
+
+ if (argc != 4) {
+ fprintf(stderr, "Usage: %s IP PORT INTERVAL\n", argv[0]);
+ fprintf(stderr, "\n");
+ fprintf(stderr, " IP Target hostname\n");
+ fprintf(stderr, " PORT Target port\n");
+ fprintf(stderr, " INTERVAL Interval between mobility events (in ms)\n");
+ fprintf(stderr, "\n");
+ exit(EXIT_FAILURE);
+ }
+
+ int interval = atoi(argv[3]);
+
+ int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (fd < 0) {
+ perror("socket");
+ goto ERR_SOCKET;
+ }
+
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = inet_addr(argv[1]);
+ addr.sin_port = htons(atoi(argv[2]));
+
+ if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+ perror("connect");
+ goto ERR_CONNECT;
+ }
+
+ unsigned state = 0;
+ char buf[1];
+ for(;;) {
+ usleep(MS2US(interval));
+
+ buf[0] = state;
+ rc = send(fd, buf, 1, 0);
+ if (rc < 0) {
+ if (errno == ECONNREFUSED) {
+ continue;
+ }
+ perror("send");
+ goto ERR_SEND;
+ }
+
+ state = 1 - state;
+ }
+
+ close(fd);
+
+ exit(EXIT_SUCCESS);
+
+ERR_SEND:
+ERR_CONNECT:
+ close(fd);
+ERR_SOCKET:
+ exit(EXIT_FAILURE);
+}
diff --git a/ctrl/facemgr/src/CMakeLists.txt b/ctrl/facemgr/src/CMakeLists.txt
index 4bcad475d..cf5606e04 100644
--- a/ctrl/facemgr/src/CMakeLists.txt
+++ b/ctrl/facemgr/src/CMakeLists.txt
@@ -64,10 +64,12 @@ set(LIBRARIES
m
${HICN_LIBRARIES}
${LIBHICNCTRL_LIBRARIES}
- ${CONFIG_LIBRARY}
+ ${LIBCONFIG_LIBRARIES}
${LIBEVENT_LIBRARY}
)
+set(FACEMGR_LIBRARY_LIST "${LIBCONFIG_LIBRARIES};${LIBEVENT_LIBRARY}" CACHE INTERNAL "FACEMGR_LIBRARY_LIST")
+
add_subdirectory(interfaces)
@@ -106,7 +108,7 @@ if (DISABLE_SHARED_LIBRARIES)
LINK_LIBRARIES ${LIBRARIES}
COMPONENT ${FACEMGR}
INCLUDE_DIRS ${INCLUDE_DIRS}
- INSTALL_ROOT_DIR hicn
+ HEADER_ROOT_DIR hicn
DEFINITIONS ${COMPILER_DEFINITIONS}
)
else ()
@@ -118,7 +120,7 @@ else ()
LINK_LIBRARIES ${LIBRARIES}
COMPONENT ${FACEMGR}
INCLUDE_DIRS ${INCLUDE_DIRS}
- INSTALL_ROOT_DIR hicn
+ HEADER_ROOT_DIR hicn
DEFINITIONS ${COMPILER_DEFINITIONS}
)
endif ()
diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c
index 5d48e993f..b2e329e0a 100644
--- a/ctrl/facemgr/src/api.c
+++ b/ctrl/facemgr/src/api.c
@@ -21,12 +21,12 @@
#ifdef __ANDROID__
/*
- * Use AndroidUtility to determine interface types
+ * Use FacemgrUtility to determine interface types
*
* NOTE: this is currently disabled as SDK APIs do not allow to determine the
* type of interfaces that are DOWN
*/
-//#define WITH_ANDROID_UTILITY
+//#define WITH_FACEMGR_UTILITY
/*
* Use priority controller interface
@@ -34,6 +34,11 @@
#define WITH_PRIORITY_CONTROLLER
/*
+ * Dump facelets (debug)
+ */
+//#define WITH_DUMP
+
+/*
* Allow priority setting before interface is actually created
*/
#define WITH_DEFAULT_PRIORITIES
@@ -59,9 +64,11 @@
#include "interfaces/bonjour/bonjour.h"
#endif /* __linux__ */
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
#include "interfaces/android_utility/android_utility.h"
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
+
+#include "interfaces/priority_controller/priority_controller.h"
#include <hicn/face.h>
#include <hicn/facemgr/facelet.h>
@@ -100,9 +107,9 @@ extern interface_ops_t network_framework_ops;
extern interface_ops_t netlink_ops;
extern interface_ops_t bonjour_ops;
#endif
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
extern interface_ops_t android_utility_ops;
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
extern interface_ops_t priority_controller_ops;
#endif
@@ -162,9 +169,9 @@ struct facemgr_s {
interface_t * hl;
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
interface_t * au; /* android_utility */
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
interface_t * pc;
@@ -538,7 +545,7 @@ int facemgr_query_bonjour(facemgr_t * facemgr, netdevice_t * netdevice)
}
#endif /* __linux__ */
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
int facemgr_query_android_utility(facemgr_t * facemgr, netdevice_t netdevice)
{
/* Send an event to the interface */
@@ -564,7 +571,7 @@ ERR_ND:
ERR_MALLOC:
return -1;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
/**
@@ -640,7 +647,7 @@ facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
}
netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifndef WITH_ANDROID_UTILITY
+#ifndef WITH_FACEMGR_UTILITY
/*
* In addition to netdevice, netdevice_type should be present to correctly
* apply rules
@@ -650,7 +657,7 @@ facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
ERROR("[facemgr_facelet_satisfy_rules] Error retrieving netdevice_type from facelet");
return -2;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
/* Default ignore list */
if ((netdevice_type == NETDEVICE_TYPE_LOOPBACK) || (netdevice_type == NETDEVICE_TYPE_UNDEFINED)) {
@@ -705,7 +712,7 @@ facemgr_facelet_satisfy_rules(facemgr_t * facemgr, facelet_t * facelet)
return 0;
}
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
/**
* \brief Complements facelet information through Android Utility interface
* \return 0 if request was successful, -1 in case of error, and -2 if the
@@ -741,7 +748,7 @@ facemgr_complement_facelet_au(facemgr_t * facemgr, facelet_t * facelet)
facelet_set_au_done(facelet);
return 0;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef __linux__
/**
@@ -763,7 +770,7 @@ facemgr_complement_facelet_bj(facemgr_t * facemgr, facelet_t * facelet)
}
netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifndef WITH_ANDROID_UTILITY
+#ifndef WITH_FACEMGR_UTILITY
/*
* In addition to netdevice, netdevice_type should be present to correctly
* apply rules
@@ -773,7 +780,7 @@ facemgr_complement_facelet_bj(facemgr_t * facemgr, facelet_t * facelet)
ERROR("[facemgr_complement_facelet_bj] Error retrieving netdevice_type from facelet");
return -2;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
bool discovery;
if (facemgr_cfg_get_discovery(facemgr->cfg, &netdevice, netdevice_type,
@@ -835,7 +842,7 @@ facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet)
}
netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifndef WITH_ANDROID_UTILITY
+#ifndef WITH_FACEMGR_UTILITY
/*
* In addition to netdevice, netdevice_type should be present to correctly
* apply rules
@@ -845,7 +852,7 @@ facemgr_complement_facelet_manual(facemgr_t * facemgr, facelet_t * facelet)
ERROR("[facemgr_complement_facelet_manual] Error retrieving netdevice_type from facelet");
return -2;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
int family = AF_UNSPEC;
if (facelet_has_family(facelet)) {
@@ -957,11 +964,11 @@ facemgr_complement_facelet(facemgr_t * facemgr, facelet_t * facelet)
if (!facelet_has_key(facelet))
return -2;
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
rc = facemgr_complement_facelet_au(facemgr, facelet);
if (rc != -2)
return rc;
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#if 0
if (!facelet_has_netdevice_type(facelet)) {
@@ -1008,7 +1015,7 @@ int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet)
}
netdevice_type_t netdevice_type = NETDEVICE_TYPE_UNDEFINED;
-#ifndef WITH_ANDROID_UTILITY
+#ifndef WITH_FACEMGR_UTILITY
/*
* In addition to netdevice, netdevice_type should be present to correctly
* apply rules
@@ -1018,7 +1025,7 @@ int facemgr_assign_face_type(facemgr_t * facemgr, facelet_t * facelet)
ERROR("[facemgr_assign_face_type] Error retrieving netdevice_type from facelet");
return -2;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
facemgr_face_type_t face_type = FACEMGR_FACE_TYPE_UNDEFINED;
if (facemgr_cfg_get_face_type(facemgr->cfg, &netdevice, netdevice_type, &face_type) < 0)
@@ -1153,9 +1160,9 @@ facemgr_process_facelet(facemgr_t * facemgr, facelet_t * facelet)
facelet_unset_admin_state(facelet);
facelet_unset_state(facelet);
facelet_unset_bj_done(facelet);
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
facelet_unset_au_done(facelet);
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
facelet_set_status(facelet, FACELET_STATUS_DELETED);
#if 0
@@ -1416,9 +1423,9 @@ facemgr_consider_static_facelet(facemgr_t * facemgr, facelet_t * facelet)
facelet_unset_state(new_facelet);
facelet_unset_bj_done(new_facelet);
facelet_clear_routes(new_facelet);
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
facelet_unset_au_done(new_facelet);
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
/* We try to apply static_facelet over facelet */
if (!facelet_match(new_facelet, static_facelet)) {
@@ -1650,9 +1657,9 @@ facemgr_process_facelet_delete(facemgr_t * facemgr, facelet_t * facelet)
facelet_unset_admin_state(facelet);
facelet_unset_state(facelet);
facelet_unset_bj_done(facelet);
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
facelet_unset_au_done(facelet);
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
facelet_unset_error(facelet);
facelet_set_status(facelet, FACELET_STATUS_DELETED);
#if 0
@@ -1787,7 +1794,9 @@ int
facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
{
bool remove_facelet = true;
+#if WITH_DUMP
bool dump = true;
+#endif /* WITH_DUMP */
int ret = 0;
int rc;
assert(facelet_in);
@@ -1877,7 +1886,9 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
rc = facemgr_process_facelet_get(facemgr, facelet_in);
if (rc == 0)
remove_facelet = false;
+#if WITH_DUMP
dump = false;
+#endif
if (rc == -1) {
ERROR("[facemgr_on_event] Error processing GET event");
goto ERR;
@@ -1985,7 +1996,9 @@ facemgr_on_event(facemgr_t * facemgr, facelet_t * facelet_in)
//DEBUG("[facemgr_on_event] GET EXISTING %s", facelet_old_s);
//DEBUG(" WITH %s", facelet_s);
//ERROR("[facemgr_on_event] GET event for a face that already exists...");
+#ifdef WITH_DUMP
dump = false;
+#endif /* WITH_DUMP */
continue;
case FACELET_EVENT_UPDATE:
@@ -2066,7 +2079,7 @@ ERR:
ret = -1;
DUMP_CACHE:
-#if 1
+#if WITH_DUMP
if (dump) {
DEBUG(" <CACHE>");
facelet_set_dump(facemgr->facelet_cache);
@@ -2074,7 +2087,7 @@ DUMP_CACHE:
DEBUG("</EVENT ret=%d>", ret);
DEBUG("----------------------------------");
}
-#endif
+#endif /* WITH_DUMP */
free(cached_facelets);
@@ -2188,13 +2201,13 @@ facemgr_bootstrap(facemgr_t * facemgr)
}
#endif /* __linux__ */
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
rc = interface_register(&android_utility_ops);
if (rc < 0) {
ERROR("[facemgr_bootstrap] Error registering android_utility interface");
goto ERR_REGISTER;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
INFO("[facemgr_bootstrap] registering priority_controller interface");
@@ -2245,7 +2258,7 @@ facemgr_bootstrap(facemgr_t * facemgr)
}
#endif /* __linux__ */
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
android_utility_cfg_t au_cfg = {
.jvm = facemgr->jvm,
};
@@ -2254,11 +2267,16 @@ facemgr_bootstrap(facemgr_t * facemgr)
ERROR("Error creating 'Android Utility' interface\n");
goto ERR_AU_CREATE;
}
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
INFO("[facemgr_bootstrap] creating priority_controller interface");
- rc = facemgr_create_interface(facemgr, "pc", "priority_controller", NULL, &facemgr->pc);
+ priority_controller_cfg_t pc_cfg = {
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+ .jvm = facemgr->jvm,
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
+ };
+ rc = facemgr_create_interface(facemgr, "pc", "priority_controller", &pc_cfg, &facemgr->pc);
if (rc < 0) {
ERROR("Error creating 'Priority Controller' interface\n");
goto ERR_PC_CREATE;
@@ -2293,10 +2311,10 @@ ERR_UPDOWN_CREATE:
facemgr_delete_interface(facemgr, facemgr->dummy);
ERR_DUMMY_CREATE:
#endif
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
facemgr_delete_interface(facemgr, facemgr->au);
ERR_AU_CREATE:
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
facemgr_delete_interface(facemgr, facemgr->pc);
ERR_PC_CREATE:
@@ -2346,9 +2364,9 @@ void facemgr_stop(facemgr_t * facemgr)
}
#endif /* __linux__ */
-#ifdef WITH_ANDROID_UTILITY
+#ifdef WITH_FACEMGR_UTILITY
facemgr_delete_interface(facemgr, facemgr->au);
-#endif /* WITH_ANDROID_UTILITY */
+#endif /* WITH_FACEMGR_UTILITY */
#ifdef WITH_PRIORITY_CONTROLLER
facemgr_delete_interface(facemgr, facemgr->pc);
diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c
index 1958749ae..f51f5802b 100644
--- a/ctrl/facemgr/src/facelet.c
+++ b/ctrl/facemgr/src/facelet.c
@@ -356,8 +356,10 @@ facelet_create_from_face(face_t * face)
facelet->error = 0;
/* TODO Consistency check between face type and found attributes */
- if (facelet_validate_face(facelet) < 0)
+ if (facelet_validate_face(facelet) < 0) {
+ ERROR("[facelet_create_from_face] Cannot validate face");
goto ERR_FACE;
+ }
facelet->bj_done = false;
facelet->au_done = false;
@@ -367,7 +369,7 @@ facelet_create_from_face(face_t * face)
/* We need to get route set */
facelet->routes = route_set_create();
if (!facelet->routes) {
- ERROR("[facelet_create] Cannot create route set");
+ ERROR("[facelet_create_from_face] Cannot create route set");
goto ERR_ROUTE_SET;
}
facelet->routes_done = false;
diff --git a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
index 55468baf8..d8e20659a 100644
--- a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
+++ b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c
@@ -20,15 +20,15 @@
#include <assert.h>
-#include <hicn/face.h>
#include <hicn/facemgr.h>
+#include <hicn/ctrl/face.h>
#include <hicn/util/log.h>
#include "../../common.h"
#include "../../interface.h"
#include "android_utility.h"
-#define FACEMGR_ANDROID_UTILITY_CLASS "com/cisco/hicn/forwarder/supportlibrary/AndroidUtility"
+#define FACEMGR_UTILITY_CLASS "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility"
#define AU_INTERFACE_TYPE_UNDEFINED 0
@@ -89,7 +89,7 @@ int au_on_event(interface_t * interface, facelet_t * facelet)
JNIEnv *env;
JavaVM *jvm = data->cfg.jvm;
(*jvm)->AttachCurrentThread(jvm, &env, NULL);
- jclass cls = (*env)->FindClass(env, FACEMGR_ANDROID_UTILITY_CLASS);
+ jclass cls = (*env)->FindClass(env, FACEMGR_UTILITY_CLASS);
jmethodID getNetworkType = (*env)->GetStaticMethodID(env, cls,
"getNetworkType", "(Ljava/lang/String;)I");
jint interface_type = (*env)->CallStaticIntMethod(env, cls, getNetworkType,
diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
index 508c0713b..8d3e18cdb 100644
--- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
+++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c
@@ -327,13 +327,12 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
switch(facelet_get_event(facelet)) {
case FACELET_EVENT_CREATE:
-
- /* Create face */
{
+ /* Create face */
char buf[MAXSZ_FACELET];
facelet_snprintf(buf, MAXSZ_FACELET, facelet);
DEBUG("Create facelet %s", buf);
- }
+
hc_face.face = *face;
rc = hc_face_create(data->s, &hc_face);
if (rc < 0) {
@@ -341,7 +340,8 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
goto ERR;
}
- INFO("Created face id=%d", hc_face.id);
+ INFO("Created face id=%d - %s", hc_face.id, buf);
+ }
hicn_route_t ** route_array;
int n = facelet_get_route_array(facelet, &route_array);
@@ -413,7 +413,6 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
case FACELET_EVENT_DELETE:
/* Removing a face should also remove associated routes */
- /* Create face */
hc_face.face = *face;
rc = hc_face_delete(data->s, &hc_face);
if (rc < 0) {
@@ -421,6 +420,11 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR;
goto ERR;
}
+
+ char buf[MAXSZ_FACELET];
+ facelet_snprintf(buf, MAXSZ_FACELET, facelet);
+ INFO("Deleted face id=%d", hc_face.id);
+
break;
case FACELET_EVENT_UPDATE:
@@ -457,7 +461,8 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
goto ERR;
}
facelet_set_admin_state_status(facelet, FACELET_ATTR_STATUS_CLEAN);
- INFO("Admin state updated");
+ INFO("Updated face id=%d - admin_state=%s", hc_face.id,
+ face_state_str(admin_state));
}
#ifdef WITH_POLICY
if (facelet_get_netdevice_type_status(facelet) == FACELET_ATTR_STATUS_DIRTY) {
@@ -517,7 +522,8 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
goto ERR;
}
facelet_set_netdevice_type_status(facelet, FACELET_ATTR_STATUS_CLEAN);
- INFO("Tags updated");
+ INFO("Updated face id=%d - netdevice_type=%s", hc_face.id,
+ netdevice_type_str(netdevice_type));
}
if (facelet_get_priority_status(facelet) == FACELET_ATTR_STATUS_DIRTY) {
INFO("Updating priority...");
@@ -549,7 +555,8 @@ int hl_on_event(interface_t * interface, facelet_t * facelet)
goto ERR;
}
facelet_set_priority_status(facelet, FACELET_ATTR_STATUS_CLEAN);
- INFO("Priority updated");
+
+ INFO("Updated face id=%d - priority=%d", hc_face.id, priority);
}
#endif /* WITH_POLICY */
break;
@@ -642,6 +649,11 @@ int hl_callback(interface_t * interface, int fd, void * unused)
/* We can ignore faces on localhost */
facelet_t * facelet = facelet_create_from_face(&f->face);
+ if (!facelet) {
+ ERROR("[hl_callback] Could not create facelet... skipping");
+ continue;
+ }
+
foreach_route(r, data->polled_routes) {
if (r->face_id != f->id)
continue;
diff --git a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c
index 76538185f..67edc5e39 100644
--- a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c
+++ b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -27,19 +27,110 @@
#include <hicn/facemgr.h>
+#include "priority_controller.h"
#include "../../common.h"
#include "../../interface.h"
#define PC_DEFAULT_PORT 9533
typedef struct {
+ priority_controller_cfg_t cfg;
int fd;
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+ unsigned state;
+ JNIEnv * env;
+ jclass cls;
+ jmethodID mid;
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
} pc_data_t;
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+#include <jni.h>
+
+#define ERR_STR_JAVA "Java VM parameters are required in the interface configuration."
+
+#define PREFER_CELLULAR 0
+#define PREFER_WIFI 1
+#define PREFER_BOTH 2
+
+#define INTERVAL_MS 500
+
+const char * prefer_str[] = { "Cellular", "WiFi", "both" };
+
+jclass find_class_global(JNIEnv* env, const char *name){
+ jclass c = (*env)->FindClass(env, name);
+ jclass c_global = 0;
+ if (c){
+ c_global = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ }
+ return c_global;
+}
+
+
+int priority_controller_tick(interface_t * interface, int fd, void * unused)
+{
+ pc_data_t * data = (pc_data_t*)interface->data;
+ unsigned new_state = PREFER_BOTH;
+
+ jint rssi = (*data->env)->CallStaticIntMethod(data->env, data->cls, data->mid);
+ DEBUG("[priority_controller_tick] rssi=%d\n", rssi);
+ if (rssi > -67) {
+ new_state = PREFER_WIFI;
+
+#if 0
+ } else if ((rssi < -67) && (rssi > -70)) {
+ new_state = PREFER_BOTH;
+#endif
+
+ } else { /* rssi < -70 */
+ new_state = PREFER_CELLULAR;
+ }
+
+ if (new_state == data->state)
+ return 0;
+
+ ERROR("[priority_controller_tick] Setting priority to %s", prefer_str[new_state]);
+
+ /* XXX Factor this */
+
+ facelet_t * facelet_w = facelet_create();
+ facelet_t * facelet_c = facelet_create();
+ facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI);
+ facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR);
+ facelet_set_attr_clean(facelet_w);
+ facelet_set_attr_clean(facelet_c);
+
+ switch(new_state) {
+ case PREFER_CELLULAR:
+ facelet_set_priority(facelet_w, 0);
+ facelet_set_priority(facelet_c, 10);
+ break;
+ case PREFER_WIFI:
+ facelet_set_priority(facelet_w, 10);
+ facelet_set_priority(facelet_c, 0);
+ break;
+ case PREFER_BOTH:
+ facelet_set_priority(facelet_w, 0);
+ facelet_set_priority(facelet_c, 0);
+ break;
+ }
+
+ facelet_set_event(facelet_w, FACELET_EVENT_UPDATE);
+ facelet_set_event(facelet_c, FACELET_EVENT_UPDATE);
+
+ interface_raise_event(interface, facelet_w);
+ interface_raise_event(interface, facelet_c);
+
+ data->state = new_state;
+
+ return 0;
+}
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
+
int priority_controller_initialize(interface_t * interface, void * cfg)
{
INFO("Initializing priority controller");
- struct sockaddr_in addr;
pc_data_t * data = malloc(sizeof(pc_data_t));
if (!data) {
@@ -49,6 +140,33 @@ int priority_controller_initialize(interface_t * interface, void * cfg)
interface->data = data;
+ data->cfg = * (priority_controller_cfg_t *) cfg;
+
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+
+ if (!cfg) {
+ ERROR(ERR_STR_JAVA);
+ goto ERR_CFG;
+ }
+
+ /* Retrieve RSSI information from SDK through AndroidUtility class */
+ (*data->cfg.jvm)->AttachCurrentThread(data->cfg.jvm, &data->env, NULL);
+ data->cls = find_class_global(data->env, FACEMGR_ANDROID_UTILITY_CLASS);
+ if (data->cls == 0)
+ goto ERR_JAVA;
+ data->mid = (*data->env)->GetStaticMethodID(data->env, data->cls, "getWifiRSSI", "()I");
+
+ data->fd = interface_register_timer(interface, INTERVAL_MS,
+ priority_controller_tick, interface);
+ if (data->fd < 0) {
+ ERROR("[priority_controller_initialize] Could not initialize timer");
+ goto ERR_FD;
+ }
+ data->state = PREFER_BOTH;
+
+#else /* PRIORITY_CONTROLLER_INTERNAL */
+ struct sockaddr_in addr;
+
data->fd = socket(AF_INET, SOCK_DGRAM, 0);
//data->fd = socket(AF_INET, SOCK_STREAM, 0);
if (data->fd < 0) {
@@ -67,18 +185,28 @@ int priority_controller_initialize(interface_t * interface, void * cfg)
perror("bind error");
goto ERR_BIND;
}
+
+ DEBUG("[priority_controller_initialize] register fd");
if (interface_register_fd(interface, data->fd, NULL) < 0) {
ERROR("[priority_controller_initialize] Error registering fd");
goto ERR_FD;
}
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
+
INFO("Priority controller successfully initialized");
return 0;
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+ERR_CFG:
+ERR_JAVA:
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
ERR_FD:
+#ifndef PRIORITY_CONTROLLER_INTERNAL
ERR_BIND:
close(data->fd);
ERR_SOCKET:
+#endif /* ! PRIORITY_CONTROLLER_INTERNAL */
free(data);
ERR_MALLOC:
return -1;
@@ -88,12 +216,21 @@ int priority_controller_finalize(interface_t * interface)
{
pc_data_t * data = (pc_data_t*)interface->data;
- if (data->fd > 0) {close(data->fd);}
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+ DEBUG("[priority_controller_finalize] unregister timer");
+ interface_unregister_timer(interface, data->fd);
+#else
+ if (data->fd > 0) {
+ interface_unregister_fd(interface, data->fd);
+ close(data->fd);
+ }
free(data);
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
return 0;
}
+#ifndef PRIORITY_CONTROLLER_INTERNAL
int priority_controller_callback(interface_t * interface, int fd, void * unused)
{
pc_data_t * data = (pc_data_t*)interface->data;
@@ -148,10 +285,13 @@ int priority_controller_callback(interface_t * interface, int fd, void * unused)
return 0;
}
+#endif /* ! PRIORITY_CONTROLLER_INTERNAL */
interface_ops_t priority_controller_ops = {
.type = "priority_controller",
.initialize = priority_controller_initialize,
.finalize = priority_controller_finalize,
+#ifndef PRIORITY_CONTROLLER_INTERNAL
.callback = priority_controller_callback,
+#endif /* ! PRIORITY_CONTROLLER_INTERNAL */
};
diff --git a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h
new file mode 100644
index 000000000..247fc3c57
--- /dev/null
+++ b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h
@@ -0,0 +1,45 @@
+/*
+ * 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 priority_controller.h
+ * \brief Priority Controller interface
+ */
+
+#ifndef FACEMGR_INTERFACE_PRIORITY_CONTROLLER
+#define FACEMGR_INTERFACE_PRIORITY_CONTROLLER
+
+#define FACEMGR_UTILITY_CLASS "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility"
+
+/*
+ * Uncomment this line to use a Priority controller interface internal to the
+ * face manager (only available in Android).
+ */
+// #define PRIORITY_CONTROLLER_INTERNAL
+
+#ifdef __ANDROID__
+#include <jni.h>
+#endif /* __ANDROID__ */
+
+typedef struct {
+#ifdef __ANDROID__
+#ifdef PRIORITY_CONTROLLER_INTERNAL
+ JavaVM * jvm;
+#endif /* PRIORITY_CONTROLLER_INTERNAL */
+#endif /* __ANDROID__ */
+} priority_controller_cfg_t;
+
+
+#endif /* FACEMGR_INTERFACE_PRIORITY_CONTROLLER */
diff --git a/ctrl/facemgr/src/main.c b/ctrl/facemgr/src/main.c
index da5e55943..344b034ae 100644
--- a/ctrl/facemgr/src/main.c
+++ b/ctrl/facemgr/src/main.c
@@ -186,7 +186,7 @@ MAIN_LOOP:
facemgr_set_callback(facemgr, loop, (void*)loop_callback);
#ifdef __ANDROID__
- facemgr_set_jvm(facemgr, NULL, NULL); // FIXME
+ facemgr_set_jvm(facemgr, NULL);
#endif /* __ ANDROID__ */
DEBUG("Bootstrap...");
diff --git a/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake b/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake
index 92e9d4adb..bf0a4d504 100644
--- a/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake
+++ b/ctrl/libhicnctrl/cmake/Modules/Packaging.cmake
@@ -32,7 +32,7 @@ if (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
)
set(${LIBHICNCTRL_COMPONENT}-dev_DEB_DEPENDENCIES
- "${LIBHICNCTRL_COMPONENT} (>= stable_version), hicn-plugin-dev (>= stable_version-release), hicn-plugin-dev (<< next_version-release)"
+ "${LIBHICNCTRL_COMPONENT} (>= stable_version), hicn-plugin-dev (>= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
@@ -42,7 +42,7 @@ if (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
)
set(${LIBHICNCTRL_COMPONENT}-dev_RPM_DEPENDENCIES
- "${LIBHICNCTRL_COMPONENT} >= stable_version, hicn-plugin-dev >= stable_version-release, hicn-plugin-dev < next_version-release"
+ "${LIBHICNCTRL_COMPONENT} >= stable_version, hicn-plugin-dev >= stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
index 3771b3abd..ebb4ee007 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -636,6 +636,7 @@ typedef struct {
ip_address_t remote_addr; /* krw */
u8 len; /* krw */
u16 cost; /* .rw */
+ // XXX hc_face_t face;
} hc_route_t;
int hc_route_parse(void *in, hc_route_t *route);
@@ -743,7 +744,7 @@ typedef struct {
int family; /* Krw */
ip_address_t remote_addr; /* krw */
u8 len; /* krw */
- policy_t policy; /* .rw */
+ hicn_policy_t policy; /* .rw */
} hc_policy_t;
int hc_policy_parse(void *in, hc_policy_t *policy);
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
index 767ef98a3..472c237b4 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/commands.h
@@ -20,8 +20,8 @@
* Header and payload in binary format.
*/
-#ifndef commands_h
-#define commands_h
+#ifndef HICN_CTRL_COMMANDS_H
+#define HICN_CTRL_COMMANDS_H
#ifndef _WIN32
#include <netinet/in.h>
@@ -31,31 +31,14 @@
#include <stdint.h>
#include <stdlib.h>
-#include <hicn/util/ip_address.h>
#ifdef WITH_POLICY
#include <hicn/policy.h>
#endif /* WITH_POLICY */
+#include <hicn/strategy.h>
+#include <hicn/util/ip_address.h>
-#define SYMBOLIC_NAME_LEN 16
-#define MAX_FWD_STRATEGY_RELATED_PREFIXES 10
-
-typedef struct in6_addr ipv6_addr_t;
-typedef uint32_t ipv4_addr_t;
-
-typedef enum {
- ADDR_INET = 1,
- ADDR_INET6,
- ADDR_LINK,
- ADDR_IFACE,
- ADDR_UNIX /* PF_UNIX */
-} address_type;
-typedef enum {
- UDP_CONN,
- TCP_CONN,
- GRE_CONN, // not implemented
- HICN_CONN
-} connection_type;
+#define SYMBOLIC_NAME_LEN 16
typedef struct in6_addr ipv6_addr_t;
typedef uint32_t ipv4_addr_t;
@@ -118,14 +101,12 @@ typedef enum {
#define command_type_from_uchar(x) \
(((x) >= COMMAND_TYPE_N) ? COMMAND_TYPE_N : (command_type_t)(x))
-/* Header */
-
/* Should be at least 8 bytes */
typedef struct {
- uint8_t messageType;
- uint8_t commandID ;
+ uint8_t message_type;
+ uint8_t command_id;
uint16_t length; /* Number of structures in the payload */
- uint32_t seqNum;
+ uint32_t seq_num;
} cmd_header_t;
typedef struct {
@@ -134,19 +115,13 @@ typedef struct {
/* Listener */
-typedef enum { ETHER_MODE, IP_MODE, HICN_MODE } listener_mode;
-
typedef struct {
char symbolic[SYMBOLIC_NAME_LEN];
- char interfaceName[SYMBOLIC_NAME_LEN];
+ char interface_name[SYMBOLIC_NAME_LEN];
ip_address_t address;
uint16_t port;
- // uint16_t etherType;
- uint8_t addressType;
- uint8_t listenerMode;
- uint8_t connectionType;
uint8_t family;
- uint8_t listenerType;
+ uint8_t type;
} cmd_listener_add_t;
typedef struct {
@@ -154,13 +129,6 @@ typedef struct {
} cmd_listener_remove_t;
typedef struct {
- ip_address_t address;
- char listenerName[SYMBOLIC_NAME_LEN];
- char interfaceName[SYMBOLIC_NAME_LEN];
- uint32_t connid;
- uint16_t port;
- uint8_t addressType;
- uint8_t encapType;
} cmd_listener_list_t;
typedef struct {
@@ -184,7 +152,6 @@ typedef struct {
uint16_t local_port;
uint8_t family;
uint8_t type;
- uint8_t connection_type;
uint8_t admin_state;
#ifdef WITH_POLICY
uint32_t priority;
@@ -196,27 +163,7 @@ typedef struct {
char symbolicOrConnid[SYMBOLIC_NAME_LEN];
} cmd_connection_remove_t;
-typedef enum {
- CONN_GRE,
- CONN_TCP,
- CONN_UDP,
- CONN_MULTICAST,
- CONN_L2,
- CONN_HICN
-} list_connections_type;
-
-typedef enum {
- IFACE_UP = 0,
- IFACE_DOWN = 1,
- IFACE_UNKNOWN = 2 // not used actually
-} connection_state;
-
typedef struct {
- cmd_connection_add_t connectionData;
- uint32_t connid;
- uint8_t state;
- char interfaceName[SYMBOLIC_NAME_LEN];
- char connectionName[SYMBOLIC_NAME_LEN];
} cmd_connection_list_t;
typedef struct {
@@ -236,7 +183,7 @@ typedef struct {
uint32_t id;
uint8_t state;
char interface_name[SYMBOLIC_NAME_LEN];
- char name[SYMBOLIC_NAME_LEN];
+ char name[SYMBOLIC_NAME_LEN]; // XXX what is this ?
} cmd_connection_list_item_t;
typedef struct {
@@ -268,7 +215,6 @@ typedef struct {
char symbolicOrConnid[SYMBOLIC_NAME_LEN];
ip_address_t address;
uint16_t cost;
- uint8_t addressType;
uint8_t family;
uint8_t len;
} cmd_route_add_t;
@@ -276,17 +222,11 @@ typedef struct {
typedef struct {
char symbolicOrConnid[SYMBOLIC_NAME_LEN];
ip_address_t address;
- uint8_t addressType;
uint8_t family;
uint8_t len;
} cmd_route_remove_t;
typedef struct {
- ip_address_t address;
- uint32_t connid;
- uint16_t cost;
- uint8_t addressType;
- uint8_t len;
} cmd_route_list_t;
typedef struct {
@@ -322,7 +262,6 @@ typedef struct {
typedef struct {
ip_address_t address;
uint8_t strategy_type;
- uint8_t address_type;
uint8_t family;
uint8_t len;
uint8_t related_prefixes;
@@ -340,7 +279,6 @@ typedef struct {
typedef struct {
char symbolicOrConnid[SYMBOLIC_NAME_LEN];
ip_address_t address;
- uint8_t addressType;
uint8_t family;
uint8_t len;
} cmd_punting_add_t;
@@ -367,40 +305,31 @@ typedef struct {
uint8_t len;
} cmd_mapme_send_update_t;
-#ifdef WITH_POLICY
/* Policy */
typedef struct {
ip_address_t address;
- uint8_t addressType;
uint8_t family;
uint8_t len;
- policy_t policy;
+ hicn_policy_t policy;
} cmd_policy_add_t;
typedef struct {
ip_address_t address;
- uint8_t addressType;
uint8_t family;
uint8_t len;
} cmd_policy_remove_t;
typedef struct {
- ip_address_t address;
- uint8_t addressType;
- uint8_t len;
- policy_t policy;
} cmd_policy_list_t;
typedef struct {
ip_address_t address;
uint8_t family;
uint8_t len;
- policy_t policy;
+ hicn_policy_t policy;
} cmd_policy_list_item_t;
-#endif /* WITH_POLICY */
-
/* Full messages */
#define _(l, u) \
diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt
index 1a64296e8..054ae3bd8 100644
--- a/ctrl/libhicnctrl/src/CMakeLists.txt
+++ b/ctrl/libhicnctrl/src/CMakeLists.txt
@@ -16,6 +16,8 @@ list(APPEND COMPILER_DEFINITIONS
)
set(HEADER_FILES
+ api.h
+ cli.h
commands.h
)
@@ -24,8 +26,8 @@ set(UTIL_HEADER_FILES
set(SOURCE_FILES
hicnctrl.c
- cli.c
route.c
+ cli.c
)
if(BUILD_HICNPLUGIN)
@@ -67,7 +69,7 @@ build_library(${LIBHICNCTRL}
DEPENDS ${DEPENDENCIES}
COMPONENT ${LIBHICNCTRL_COMPONENT}
INCLUDE_DIRS ${INCLUDE_DIRS}
- INSTALL_ROOT_DIR hicn
+ HEADER_ROOT_DIR hicn
DEFINITIONS ${COMPILER_DEFINITIONS}
)
@@ -75,7 +77,7 @@ if (NOT DISABLE_EXECUTABLES)
set(LIBRARIES ${LIBRARIES} ${LIBHICN_SHARED} ${LIBHICNCTRL_SHARED})
list(APPEND DAEMON_SRC
- cli.c
+ hicnctrl.c
)
build_executable(${HICNCTRL}
diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c
index ef9f4af65..83c493fe3 100644
--- a/ctrl/libhicnctrl/src/api.c
+++ b/ctrl/libhicnctrl/src/api.c
@@ -56,7 +56,7 @@ typedef struct {
} hc_sock_request_t;
/**
- * Messages to the forwarder might be multiplexed thanks to the seqNum fields in
+ * Messages to the forwarder might be multiplexed thanks to the seq_num fields in
* the cmd_header_t structure. The forwarder simply answers back the
* original sequence number. We maintain a map of such sequence number to
* outgoing queries so that replied can be demultiplexed and treated
@@ -184,6 +184,7 @@ connection_type_from_str(const char * str)
#define IS_VALID_LIST_CONNECTIONS_TYPE(x) ((x >= CONN_GRE) && (x <= CONN_HICN))
+#if 0
static const hc_connection_type_t map_from_list_connections_type[] = {
[CONN_GRE] = CONNECTION_TYPE_UNDEFINED,
[CONN_TCP] = CONNECTION_TYPE_TCP,
@@ -224,6 +225,7 @@ static const listener_mode map_to_listener_mode[] = {
};
#define IS_VALID_LIST_CONNECTIONS_STATE(x) ((x >= IFACE_UP) && (x <= IFACE_UNKNOWN))
+#endif
/* /!\ Please update constants in header file upon changes */
const char * connection_state_str[] = {
@@ -242,11 +244,13 @@ static const connection_state map_to_connection_state[] = {
*/
+#if 0
static const hc_connection_state_t map_from_list_connections_state[] = {
[IFACE_UP] = HC_CONNECTION_STATE_UP,
[IFACE_DOWN] = HC_CONNECTION_STATE_DOWN,
[IFACE_UNKNOWN] = HC_CONNECTION_STATE_UNDEFINED,
};
+#endif
#define connection_state_to_face_state(x) ((face_state_t)(x))
@@ -254,6 +258,7 @@ static const hc_connection_state_t map_from_list_connections_state[] = {
#define IS_VALID_ADDR_TYPE(x) ((x >= ADDR_INET) && (x <= ADDR_UNIX))
+#if 0
static const int map_from_addr_type[] = {
[ADDR_INET] = AF_INET,
[ADDR_INET6] = AF_INET6,
@@ -266,6 +271,15 @@ static const address_type map_to_addr_type[] = {
[AF_INET] = ADDR_INET,
[AF_INET6] = ADDR_INET6,
};
+#endif
+
+// XXX Those are always true
+//
+#define IS_VALID_ADDRESS(x) (1)
+#define IS_VALID_CONNECTION_ID(x) (1)
+#define IS_VALID_ROUTE_COST(x) (1)
+#define IS_VALID_PREFIX_LEN(x) (1)
+#define IS_VALID_POLICY(x) (1)
/******************************************************************************
* Message helper types and aliases
@@ -588,7 +602,7 @@ int
hc_sock_send(hc_sock_t * s, hc_msg_t * msg, size_t msglen, int seq)
{
int rc;
- msg->hdr.seqNum = seq;
+ msg->hdr.seq_num = seq;
rc = (int)send(s->fd, msg, msglen, 0);
if (rc < 0) {
perror("hc_sock_send");
@@ -657,7 +671,7 @@ hc_sock_process(hc_sock_t * s, hc_data_t ** data)
}
hc_sock_request_t * request = NULL;
- if (hc_sock_map_get(s->map, hdr.seqNum, &request) < 0) {
+ if (hc_sock_map_get(s->map, hdr.seq_num, &request) < 0) {
ERROR("[hc_sock_process] Error searching for matching request");
return -99;
}
@@ -667,7 +681,7 @@ hc_sock_process(hc_sock_t * s, hc_data_t ** data)
}
s->remaining = hdr.length;
- switch(hdr.messageType) {
+ switch(hdr.message_type) {
case ACK_LIGHT:
DEBUG("ack received");
assert(s->remaining == 1);
@@ -971,19 +985,16 @@ _hc_listener_create(hc_sock_t * s, hc_listener_t * listener, bool async)
msg_listener_add_t msg = {
.header = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_LISTENER_ADD,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_LISTENER_ADD,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
.payload = {
.address = listener->local_addr,
.port = htons(listener->local_port),
- .addressType = (u8)map_to_addr_type[listener->family],
- .listenerMode = (u8)map_to_listener_mode[listener->type],
- .connectionType = (u8)map_to_connection_type[listener->type],
.family = listener->family,
- .listenerType = listener->type,
+ .type = listener->type,
}
};
@@ -991,7 +1002,7 @@ _hc_listener_create(hc_sock_t * s, hc_listener_t * listener, bool async)
if (rc >= SYMBOLIC_NAME_LEN)
WARN("[_hc_listener_create] Unexpected truncation of symbolic name string");
- rc = snprintf(msg.payload.interfaceName, INTERFACE_LEN, "%s", listener->interface_name);
+ rc = snprintf(msg.payload.interface_name, INTERFACE_LEN, "%s", listener->interface_name);
if (rc >= INTERFACE_LEN)
WARN("[_hc_listener_create] Unexpected truncation of interface name string");
@@ -1074,10 +1085,10 @@ _hc_listener_delete(hc_sock_t * s, hc_listener_t * listener, bool async)
cmd_listener_remove_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_LISTENER_REMOVE,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_LISTENER_REMOVE,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
};
@@ -1136,17 +1147,17 @@ _hc_listener_list(hc_sock_t * s, hc_data_t ** pdata, bool async)
cmd_header_t hdr;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_LISTENER_LIST,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_LISTENER_LIST,
.length = 0,
- .seqNum = 0,
+ .seq_num = 0,
},
};
hc_command_params_t params = {
.cmd = ACTION_LIST,
.cmd_id = COMMAND_TYPE_LISTENER_LIST,
- .size_in = sizeof(cmd_listener_list_t),
+ .size_in = sizeof(cmd_listener_list_item_t),
.size_out = sizeof(hc_listener_t),
.parse = (HC_PARSE)hc_listener_parse,
};
@@ -1217,33 +1228,31 @@ hc_listener_parse(void * in, hc_listener_t * listener)
{
int rc;
- cmd_listener_list_t * cmd = (cmd_listener_list_t *)in;
+ cmd_listener_list_item_t * item = (cmd_listener_list_item_t *)in;
- if (!IS_VALID_LIST_LISTENERS_TYPE(cmd->encapType))
- return -1;
-
- hc_connection_type_t type = map_from_encap_type[cmd->encapType];
- if (type == CONNECTION_TYPE_UNDEFINED)
- return -1;
+ // XXX TODO validate what we received from hicnlight
+ // address
+ // name
+ // interface_name
+ // port
- if (!IS_VALID_ADDR_TYPE(cmd->addressType))
+ if (!(IS_VALID_CONNECTION_TYPE(item->type)))
return -1;
- int family = map_from_addr_type[cmd->addressType];
- if (!IS_VALID_FAMILY(family))
+ if (!IS_VALID_FAMILY(item->family))
return -1;
*listener = (hc_listener_t) {
- .id = cmd->connid,
- .type = type,
- .family = family,
- .local_addr = UNION_CAST(cmd->address, ip_address_t),
- .local_port = ntohs(cmd->port),
+ .id = item->id,
+ .type = item->type,
+ .family = item->family,
+ .local_addr = UNION_CAST(item->address, ip_address_t),
+ .local_port = ntohs(item->port),
};
- rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "%s", cmd->listenerName);
+ rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "%s", item->name);
if (rc >= SYMBOLIC_NAME_LEN)
WARN("[hc_listener_parse] Unexpected truncation of symbolic name string");
- rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", cmd->interfaceName);
+ rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", item->interface_name);
if (rc >= INTERFACE_LEN)
WARN("[hc_listener_parse] Unexpected truncation of interface name string");
return 0;
@@ -1293,18 +1302,19 @@ _hc_connection_create(hc_sock_t * s, hc_connection_t * connection, bool async)
cmd_connection_add_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_CONNECTION_ADD,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_ADD,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
.payload = {
+ // symbolic
.remote_ip = connection->remote_addr,
.local_ip = connection->local_addr,
.remote_port = htons(connection->remote_port),
.local_port = htons(connection->local_port),
- .type = (u8)map_to_addr_type[connection->family],
- .connection_type = (u8)map_to_connection_type[connection->type],
+ .family = connection->family,
+ .type = connection->type,
.admin_state = connection->admin_state,
#ifdef WITH_POLICY
.priority = connection->priority,
@@ -1315,7 +1325,7 @@ _hc_connection_create(hc_sock_t * s, hc_connection_t * connection, bool async)
rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", connection->name);
if (rc >= SYMBOLIC_NAME_LEN)
WARN("[_hc_connection_create] Unexpected truncation of symbolic name string");
- //snprintf(msg.payload.interfaceName, INTERFACE_NAME_LEN, "%s", connection->interface_name);
+ //snprintf(msg.payload.interface_name, INTERFACE_NAME_LEN, "%s", connection->interface_name);
hc_command_params_t params = {
.cmd = ACTION_CREATE,
@@ -1395,10 +1405,10 @@ _hc_connection_delete(hc_sock_t * s, hc_connection_t * connection, bool async)
cmd_connection_remove_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_CONNECTION_REMOVE,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_REMOVE,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
};
@@ -1456,17 +1466,17 @@ _hc_connection_list(hc_sock_t * s, hc_data_t ** pdata, bool async)
cmd_header_t hdr;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_CONNECTION_LIST,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_LIST,
.length = 0,
- .seqNum = 0,
+ .seq_num = 0,
},
};
hc_command_params_t params = {
.cmd = ACTION_LIST,
.cmd_id = COMMAND_TYPE_CONNECTION_LIST,
- .size_in = sizeof(cmd_connection_list_t),
+ .size_in = sizeof(cmd_connection_list_item_t),
.size_out = sizeof(hc_connection_t),
.parse = (HC_PARSE)hc_connection_parse,
};
@@ -1550,50 +1560,46 @@ int
hc_connection_parse(void * in, hc_connection_t * connection)
{
int rc;
- cmd_connection_list_t * cmd = (cmd_connection_list_t *)in;
+ cmd_connection_list_item_t * item = (cmd_connection_list_item_t *)in;
- if (!IS_VALID_LIST_CONNECTIONS_TYPE(cmd->connectionData.connection_type))
- return -1;
+ // XXX validation
+ // symbolic
+ // remote_ip
+ // local_ip
+ // remote_port
+ // local_port
- hc_connection_type_t type = map_from_list_connections_type[cmd->connectionData.connection_type];
- if (type == CONNECTION_TYPE_UNDEFINED)
+ if (!IS_VALID_FAMILY(item->family))
return -1;
- if (!IS_VALID_LIST_CONNECTIONS_STATE(cmd->state))
- return -1;
-
- hc_connection_state_t state = map_from_list_connections_state[cmd->state];
- if (state == HC_CONNECTION_STATE_UNDEFINED)
- return -1;
-
- if (!IS_VALID_ADDR_TYPE(cmd->connectionData.type))
- return -1;
-
- int family = map_from_addr_type[cmd->connectionData.type];
- if (!IS_VALID_FAMILY(family))
- return -1;
+ // type
+ // admin_state
+ // priority
+ // tags
+ // id
+ // state
+ // interface_name
+ // name ???
*connection = (hc_connection_t) {
- .id = cmd->connid,
- .type = type,
- .family = family,
- .local_addr = cmd->connectionData.local_ip,
- //.local_addr = UNION_CAST(cmd->connectionData.localIp, ip_address_t),
- .local_port = ntohs(cmd->connectionData.local_port),
- .remote_addr = cmd->connectionData.remote_ip,
- //.remote_addr = UNION_CAST(cmd->connectionData.remoteIp, ip_address_t),
- .remote_port = ntohs(cmd->connectionData.remote_port),
- .admin_state = cmd->connectionData.admin_state,
+ .id = item->id,
+ .type = item->type,
+ .family = item->family,
+ .local_addr = item->local_ip,
+ .local_port = ntohs(item->local_port),
+ .remote_addr = item->remote_ip,
+ .remote_port = ntohs(item->remote_port),
+ .admin_state = item->admin_state,
#ifdef WITH_POLICY
- .priority = cmd->connectionData.priority,
- .tags = cmd->connectionData.tags,
+ .priority = item->priority,
+ .tags = item->tags,
#endif /* WITH_POLICY */
- .state = state,
+ .state = item->state,
};
- rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", cmd->connectionData.symbolic);
+ rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", item->symbolic);
if (rc >= SYMBOLIC_NAME_LEN)
WARN("[hc_connection_parse] Unexpected truncation of symbolic name string");
- rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s", cmd->interfaceName);
+ rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s", item->interface_name);
if (rc >= INTERFACE_LEN)
WARN("[hc_connection_parse] Unexpected truncation of interface name string");
return 0;
@@ -1648,10 +1654,10 @@ _hc_connection_set_admin_state(hc_sock_t * s, const char * conn_id_or_name,
cmd_connection_set_admin_state_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_CONNECTION_SET_ADMIN_STATE,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_SET_ADMIN_STATE,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
.payload = {
.admin_state = state,
@@ -1698,10 +1704,10 @@ _hc_connection_set_priority(hc_sock_t * s, const char * conn_id_or_name,
cmd_connection_set_priority_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_CONNECTION_SET_PRIORITY,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_SET_PRIORITY,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
.payload = {
.priority = priority,
@@ -1748,10 +1754,10 @@ _hc_connection_set_tags(hc_sock_t * s, const char * conn_id_or_name,
cmd_connection_set_tags_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_CONNECTION_SET_TAGS,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_SET_TAGS,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
.payload = {
.tags = tags,
@@ -1812,15 +1818,15 @@ _hc_route_create(hc_sock_t * s, hc_route_t * route, bool async)
cmd_route_add_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_ROUTE_ADD,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_ROUTE_ADD,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
.payload = {
.address = route->remote_addr,
.cost = route->cost,
- .addressType = (u8)map_to_addr_type[route->family],
+ .family = route->family,
.len = route->len,
}
};
@@ -1875,14 +1881,14 @@ _hc_route_delete(hc_sock_t * s, hc_route_t * route, bool async)
cmd_route_remove_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_ROUTE_REMOVE,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_ROUTE_REMOVE,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
.payload = {
.address = route->remote_addr,
- .addressType = (u8)map_to_addr_type[route->family],
+ .family = route->family,
.len = route->len,
}
};
@@ -1927,17 +1933,17 @@ _hc_route_list(hc_sock_t * s, hc_data_t ** pdata, bool async)
cmd_header_t hdr;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_ROUTE_LIST,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_ROUTE_LIST,
.length = 0,
- .seqNum = 0,
+ .seq_num = 0,
},
};
hc_command_params_t params = {
.cmd = ACTION_LIST,
.cmd_id = COMMAND_TYPE_ROUTE_LIST,
- .size_in = sizeof(cmd_route_list_t),
+ .size_in = sizeof(cmd_route_list_item_t),
.size_out = sizeof(hc_route_t),
.parse = (HC_PARSE)hc_route_parse,
};
@@ -1962,25 +1968,35 @@ hc_route_list_async(hc_sock_t * s)
int
hc_route_parse(void * in, hc_route_t * route)
{
- cmd_route_list_t * cmd = (cmd_route_list_t *) in;
+ cmd_route_list_item_t * item = (cmd_route_list_item_t *) in;
- if (!IS_VALID_ADDR_TYPE(cmd->addressType)) {
- ERROR("[hc_route_parse] Invalid address type");
+ if (!IS_VALID_ADDRESS(item->address)) {
+ ERROR("[hc_route_parse] Invalid address");
return -1;
}
-
- int family = map_from_addr_type[cmd->addressType];
- if (!IS_VALID_FAMILY(family)) {
+ if (!IS_VALID_CONNECTION_ID(item->connection_id)) {
+ ERROR("[hc_route_parse] Invalid connection id");
+ return -1;
+ }
+ if (!IS_VALID_ROUTE_COST(item->cost)) {
+ ERROR("[hc_route_parse] Invalid cost");
+ return -1;
+ }
+ if (!IS_VALID_FAMILY(item->family)) {
ERROR("[hc_route_parse] Invalid address family");
return -1;
}
+ if (!IS_VALID_PREFIX_LEN(item->len)) {
+ ERROR("[hc_route_parse] Invalid len");
+ return -1;
+ }
*route = (hc_route_t) {
- .face_id = cmd->connid,
- .family = family,
- .remote_addr = UNION_CAST(cmd->address, ip_address_t),
- .len = cmd->len,
- .cost = cmd->cost,
+ .face_id = item->connection_id,
+ .family = item->family,
+ .remote_addr = item->address,
+ .len = item->len,
+ .cost = item->cost,
};
return 0;
}
@@ -2521,17 +2537,17 @@ hc_face_list_async(hc_sock_t * s)
cmd_header_t hdr;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
+ .message_type = REQUEST_LIGHT,
COMMAND_TYPE_CONNECTION_LIST,
.length = 0,
- .seqNum = 0,
+ .seq_num = 0,
},
};
hc_command_params_t params = {
.cmd = ACTION_LIST,
.cmd_id = COMMAND_TYPE_CONNECTION_LIST,
- .size_in = sizeof(cmd_connection_list_t),
+ .size_in = sizeof(cmd_connection_list_item_t),
.size_out = sizeof(hc_face_t),
.parse = (HC_PARSE)hc_connection_parse_to_face,
};
@@ -2662,14 +2678,14 @@ _hc_punting_create(hc_sock_t * s, hc_punting_t * punting, bool async)
cmd_punting_add_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_PUNTING_ADD,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_PUNTING_ADD,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
.payload = {
.address = punting->prefix,
- .addressType = (u8)map_to_addr_type[punting->family],
+ .family = punting->family,
.len = punting->prefix_len,
}
};
@@ -2783,10 +2799,10 @@ _hc_cache_set_store(hc_sock_t * s, int enabled, bool async)
cmd_cache_set_store_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_CACHE_SET_STORE,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CACHE_SET_STORE,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
.payload = {
.activate = enabled,
@@ -2824,10 +2840,10 @@ _hc_cache_set_serve(hc_sock_t * s, int enabled, bool async)
cmd_cache_set_serve_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_CACHE_SET_SERVE,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CACHE_SET_SERVE,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
.payload = {
.activate = enabled,
@@ -2961,14 +2977,14 @@ _hc_policy_create(hc_sock_t * s, hc_policy_t * policy, bool async)
cmd_policy_add_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
+ .message_type = REQUEST_LIGHT,
COMMAND_TYPE_POLICY_ADD,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
.payload = {
.address = policy->remote_addr,
- .addressType = (u8)map_to_addr_type[policy->family],
+ .family = policy->family,
.len = policy->len,
.policy = policy->policy,
}
@@ -3010,14 +3026,14 @@ _hc_policy_delete(hc_sock_t * s, hc_policy_t * policy, bool async)
cmd_policy_remove_t payload;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_POLICY_REMOVE,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_POLICY_REMOVE,
.length = 1,
- .seqNum = 0,
+ .seq_num = 0,
},
.payload = {
.address = policy->remote_addr,
- .addressType = (u8)map_to_addr_type[policy->family],
+ .family = policy->family,
.len = policy->len,
}
};
@@ -3054,17 +3070,17 @@ _hc_policy_list(hc_sock_t * s, hc_data_t ** pdata, bool async)
cmd_header_t hdr;
} msg = {
.hdr = {
- .messageType = REQUEST_LIGHT,
- .commandID = COMMAND_TYPE_POLICY_LIST,
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_POLICY_LIST,
.length = 0,
- .seqNum = 0,
+ .seq_num = 0,
},
};
hc_command_params_t params = {
.cmd = ACTION_LIST,
.cmd_id = COMMAND_TYPE_POLICY_LIST,
- .size_in = sizeof(cmd_policy_list_t),
+ .size_in = sizeof(cmd_policy_list_item_t),
.size_out = sizeof(hc_policy_t),
.parse = (HC_PARSE)hc_policy_parse,
};
@@ -3089,20 +3105,30 @@ hc_policy_list_async(hc_sock_t * s, hc_data_t ** pdata)
int
hc_policy_parse(void * in, hc_policy_t * policy)
{
- cmd_policy_list_t * cmd = (cmd_policy_list_t *) in;
-
- if (!IS_VALID_ADDR_TYPE(cmd->addressType))
- return -1;
+ cmd_policy_list_item_t * item = (cmd_policy_list_item_t *) in;
- int family = map_from_addr_type[cmd->addressType];
- if (!IS_VALID_FAMILY(family))
- return -1;
+ if (!IS_VALID_ADDRESS(item->address)) {
+ ERROR("[hc_policy_parse] Invalid address");
+ return -1;
+ }
+ if (!IS_VALID_FAMILY(item->family)) {
+ ERROR("[hc_policy_parse] Invalid family");
+ return -1;
+ }
+ if (!IS_VALID_PREFIX_LEN(item->len)) {
+ ERROR("[hc_policy_parse] Invalid len");
+ return -1;
+ }
+ if (!IS_VALID_POLICY(item->policy)) {
+ ERROR("[hc_policy_parse] Invalid policy");
+ return -1;
+ }
*policy = (hc_policy_t) {
- .family = family,
- .remote_addr = UNION_CAST(cmd->address, ip_address_t),
- .len = cmd->len,
- .policy = cmd->policy,
+ .family = item->family,
+ .remote_addr = item->address,
+ .len = item->len,
+ .policy = item->policy,
};
return 0;
}
@@ -3159,4 +3185,3 @@ object_from_str(const char * object_str)
#undef _
return OBJECT_UNDEFINED;
}
-
diff --git a/ctrl/libhicnctrl/src/hicn_plugin_api.c b/ctrl/libhicnctrl/src/hicn_plugin_api.c
index 04d01e2a6..231c491ba 100644
--- a/ctrl/libhicnctrl/src/hicn_plugin_api.c
+++ b/ctrl/libhicnctrl/src/hicn_plugin_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -34,13 +34,24 @@
#include <strings.h>
#include <vapi/hicn.api.vapi.h>
#include <vapi/ip.api.vapi.h>
+#include <vapi/udp.api.vapi.h>
#include <vapi/interface.api.vapi.h>
#include <hicn/util/log.h>
#include <hicn/util/map.h>
#include <hicn/error.h>
#include <vnet/ip/ip6_packet.h>
+
+
+#if __GNUC__ >= 9
+#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
+#endif
+
#include <vnet/ip/ip46_address.h>
+#if __GNUC__ >= 9
+#pragma GCC diagnostic pop
+#endif
+
#define APP_NAME "hicn_plugin"
#define MAX_OUTSTANDING_REQUESTS 4
#define RESPONSE_QUEUE_SIZE 2
@@ -48,6 +59,7 @@
DEFINE_VAPI_MSG_IDS_HICN_API_JSON
DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON
DEFINE_VAPI_MSG_IDS_IP_API_JSON
+DEFINE_VAPI_MSG_IDS_UDP_API_JSON
typedef struct {
vapi_ctx_t g_vapi_ctx_instance;
@@ -61,7 +73,7 @@ vapi_skc_ctx_t vapi_skc = {
/**
* Messages to the forwarder might be multiplexed thanks to the seqNum fields in
- * the cmd_header_t structure. The forwarder simply answers back the
+ * the header_control_message structure. The forwarder simply answers back the
* original sequence number. We maintain a map of such sequence number to
* outgoing queries so that replied can be demultiplexed and treated
* appropriately.
@@ -94,20 +106,10 @@ struct hc_sock_s {
_(hicn_api_node_params_set_reply) \
_(hicn_api_node_params_get_reply) \
_(hicn_api_node_stats_get_reply) \
- _(hicn_api_face_add) \
- _(hicn_api_face_add_reply) \
- _(hicn_api_face_del) \
- _(hicn_api_face_del_reply) \
_(hicn_api_face_get) \
_(hicn_api_faces_details) \
_(hicn_api_face_stats_details) \
_(hicn_api_face_get_reply) \
- _(hicn_api_route_nhops_add) \
- _(hicn_api_route_nhops_add_reply) \
- _(hicn_api_route_del) \
- _(hicn_api_route_del_reply) \
- _(hicn_api_route_nhop_del) \
- _(hicn_api_route_nhop_del_reply) \
_(hicn_api_route_get) \
_(hicn_api_route_get_reply) \
_(hicn_api_routes_details) \
@@ -115,6 +117,7 @@ struct hc_sock_s {
_(hicn_api_strategy_get) \
_(hicn_api_strategy_get_reply)
+
typedef vapi_type_msg_header2_t hc_msg_header_t;
typedef union {
@@ -622,12 +625,29 @@ int hc_connection_set_admin_state_async(hc_sock_t *s,
* Routes
*----------------------------------------------------------------------------*/
+vapi_error_e create_udp_tunnel_cb( vapi_ctx_t ctx,
+ void *callback_ctx,
+ vapi_error_e rv,
+ bool is_last,
+ vapi_payload_hicn_api_udp_tunnel_add_del_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK)
+ return rv;
+
+ if (reply->retval != VAPI_OK)
+ return reply->retval;
+
+ u32 * uei = (u32*) callback_ctx;
+ *uei = reply->uei;
+
+ return reply->retval;
+}
+
/* ROUTE CREATE */
vapi_error_e parse_route_create( vapi_ctx_t ctx,
void *callback_ctx,
vapi_error_e rv,
bool is_last,
- vapi_payload_hicn_api_route_nhops_add_reply *reply) {
+ vapi_payload_ip_route_add_del_reply *reply) {
if (reply == NULL || rv != VAPI_OK)
return rv;
@@ -637,31 +657,133 @@ vapi_error_e parse_route_create( vapi_ctx_t ctx,
return reply->retval;
}
+vapi_error_e hicn_enable_cb( vapi_ctx_t ctx,
+ void *callback_ctx,
+ vapi_error_e rv,
+ bool is_last,
+ vapi_payload_hicn_api_enable_disable_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK)
+ return rv;
+
+ return reply->retval;
+}
+
int _hc_route_create(hc_sock_t *s, hc_route_t *route, bool async) {
if (!IS_VALID_FAMILY(route->family)) return -1;
+ int ret;
vapi_lock();
- vapi_msg_hicn_api_route_nhops_add *hicnp_msg;
- hicnp_msg = vapi_alloc_hicn_api_route_nhops_add(s->g_vapi_ctx_instance);
- if (!hicnp_msg) return VAPI_ENOMEM;
+ vapi_msg_ip_route_add_del *hicnp_msg = vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1);
+
+ hicnp_msg->payload.is_add = 1;
+ if (route->family == AF_INET) {
+ memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0], &route->remote_addr.v4, 4);
+ hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP4;
+ }
+ else {
+ memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0], &route->remote_addr.v6, 16);
+ hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP6;
+ }
+
+ hicnp_msg->payload.route.prefix.len = route->len;
+
+ hicnp_msg->payload.route.paths[0].sw_if_index = ~0;
+ hicnp_msg->payload.route.paths[0].table_id = 0;
+
+ hc_face_t *face = &(route->face);
+ switch (face->face.type) {
+ case FACE_TYPE_HICN:
+ {
+ if (ip46_address_is_ip4((ip46_address_t *)(&(face->face.remote_addr)))) {
+ memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4), &face->face.remote_addr.v4, sizeof(ip4_address_t));
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
+ }
+ else{
+ memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6), &face->face.remote_addr.v6, sizeof(ip6_address_t));
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
+ }
+
+ hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE;
+ hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
+
+ break;
+ }
+ case FACE_TYPE_UDP:
+ {
+ vapi_msg_hicn_api_udp_tunnel_add_del *msg = NULL;
+ u32 uei = ~0;
+
+ if (ip46_address_is_ip4((ip46_address_t *)(&(face->face.remote_addr))) &&
+ ip46_address_is_ip4((ip46_address_t *)(&(face->face.local_addr)))) {
+
+ msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance);
+ memcpy(msg->payload.src_addr.un.ip4, &face->face.local_addr.v4, sizeof(ip4_address_t));
+ msg->payload.src_addr.af = ADDRESS_IP4;
+
+ memcpy(msg->payload.dst_addr.un.ip4, &face->face.remote_addr.v4, sizeof(ip4_address_t));
+ msg->payload.dst_addr.af = ADDRESS_IP4;
+
+ } else if (!ip46_address_is_ip4((ip46_address_t *)(&(route->face.face.remote_addr))) &&
+ !ip46_address_is_ip4((ip46_address_t *)(&(route->face.face.local_addr)))) {
+
+ msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance);
+ memcpy(msg->payload.src_addr.un.ip6, &face->face.local_addr.v6, sizeof(ip6_address_t));
+ msg->payload.src_addr.af = ADDRESS_IP4;
+
+ memcpy(msg->payload.dst_addr.un.ip6, &face->face.remote_addr.v6, sizeof(ip6_address_t));
+ msg->payload.dst_addr.af = ADDRESS_IP6;
+
+ } else {
+ //NOT IMPLEMENTED
+ ret = -1;
+ goto done;
+ }
+
+ msg->payload.src_port = face->face.local_port;
+ msg->payload.dst_port = face->face.remote_port;
+ msg->payload.is_add = 1;
+
+ int ret = vapi_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance, msg, create_udp_tunnel_cb, &uei);
+
+ if(ret) {
+ vapi_msg_free(s->g_vapi_ctx_instance, hicnp_msg);
+ goto done;
+ }
+
+ hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP;
+ hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
+ hicnp_msg->payload.route.paths[0].nh.obj_id = uei;
+ break;
+ }
+ default:
+ ret = -1;
+ goto done;
+ }
+
+ ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg, parse_route_create, NULL);
+
+ if (ret)
+ goto done;
+
+ vapi_msg_hicn_api_enable_disable *msg = vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance);
if (route->family == AF_INET) {
- memcpy(&hicnp_msg->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4);
+ memcpy(&msg->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4);
+ msg->payload.prefix.address.af = ADDRESS_IP4;
}
else {
- memcpy(&hicnp_msg->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16);
+ memcpy(&msg->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16);
+ msg->payload.prefix.address.af = ADDRESS_IP6;
}
- hicnp_msg->payload.prefix.address.af =
- route->family == AF_INET ? ADDRESS_IP4 : ADDRESS_IP6;
- hicnp_msg->payload.prefix.len = route->len;
- hicnp_msg->payload.face_ids[0] = route->face_id;
- hicnp_msg->payload.n_faces = 1;
- vapi_error_e ret = vapi_hicn_api_route_nhops_add(s->g_vapi_ctx_instance, hicnp_msg, parse_route_create, NULL);
+ msg->payload.prefix.len = route->len;
+ msg->payload.enable_disable = 1;
+
+ ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg, hicn_enable_cb, NULL);
+done:
vapi_unlock();
return ret;
-
}
int hc_route_create(hc_sock_t *s, hc_route_t *route) {
@@ -677,13 +799,10 @@ vapi_error_e parse_route_delete( vapi_ctx_t ctx,
void *callback_ctx,
vapi_error_e rv,
bool is_last,
- vapi_payload_hicn_api_route_nhop_del_reply *reply) {
+ vapi_payload_ip_route_add_del_reply *reply) {
if (reply == NULL || rv != VAPI_OK)
return rv;
- if (reply->retval != VAPI_OK)
- return reply->retval;
-
return reply->retval;
}
@@ -691,20 +810,56 @@ int _hc_route_delete(hc_sock_t *s, hc_route_t *route, bool async) {
if (!IS_VALID_FAMILY(route->family)) return -1;
vapi_lock();
- vapi_msg_hicn_api_route_nhop_del *hicnp_msg;
- hicnp_msg = vapi_alloc_hicn_api_route_nhop_del(s->g_vapi_ctx_instance);
+ vapi_msg_ip_route_add_del *hicnp_msg = vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1);
- if (!hicnp_msg) return VAPI_ENOMEM;
+ hicnp_msg->payload.is_add = 0;
+ if (route->family == AF_INET) {
+ memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0], &route->remote_addr.v4, 4);
+ hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP4;
+ }
+ else {
+ memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0], &route->remote_addr.v6, 16);
+ hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP6;
+ }
+
+ hicnp_msg->payload.route.prefix.len = route->len;
+
+ hicnp_msg->payload.route.paths[0].sw_if_index = ~0;
+ hicnp_msg->payload.route.paths[0].table_id = 0;
- memcpy(&hicnp_msg->payload.prefix.address.un.ip6[0], &route->remote_addr, 16);
- hicnp_msg->payload.prefix.address.af =
- route->family == AF_INET ? ADDRESS_IP4 : ADDRESS_IP6;
- hicnp_msg->payload.prefix.len = route->len;
- hicnp_msg->payload.faceid = route->face_id;
+ hc_face_t *face = &(route->face);
+ switch (face->face.type) {
+ case FACE_TYPE_HICN:
+ {
+ if (ip46_address_is_ip4((ip46_address_t *)(&(face->face.remote_addr)))) {
+ memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4), &face->face.remote_addr.v4, sizeof(ip4_address_t));
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
+ }
+ else{
+ memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6), &face->face.remote_addr.v6, sizeof(ip6_address_t));
+ hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
+ }
+
+ hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE;
+ hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
+
+ break;
+ }
+ case FACE_TYPE_UDP:
+ {
+ hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP;
+ hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
+ hicnp_msg->payload.route.paths[0].nh.obj_id = face->face.netdevice.index;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ vapi_error_e ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg, parse_route_delete, NULL);
- int retval = vapi_hicn_api_route_nhop_del(s->g_vapi_ctx_instance, hicnp_msg, parse_route_delete, NULL);
vapi_unlock();
- return retval;
+ return ret;
}
int hc_route_delete(hc_sock_t *s, hc_route_t *route) {
@@ -715,18 +870,121 @@ int hc_route_delete_async(hc_sock_t *s, hc_route_t *route) {
return _hc_route_delete(s, route, true);
}
+vapi_error_e parse_udp_encap_list( vapi_ctx_t ctx,
+ void *callback_ctx,
+ vapi_error_e rv,
+ bool is_last,
+ vapi_payload_udp_encap_details *reply) {
+ if (reply == NULL || rv != VAPI_OK)
+ return rv;
+
+ hc_face_t * face = (hc_face_t *)callback_ctx;
+
+ if (face->face.netdevice.index == reply->udp_encap.id)
+ {
+ switch(reply->udp_encap.src_ip.af) {
+ case ADDRESS_IP4:
+ {
+ memcpy(&face->face.local_addr.v4, &(reply->udp_encap.src_ip.un.ip4), sizeof(ip4_address_t));
+ memcpy(&face->face.remote_addr.v4, &(reply->udp_encap.dst_ip.un.ip4), sizeof(ip4_address_t));
+ break;
+ }
+ case ADDRESS_IP6:
+ {
+ memcpy(&face->face.local_addr.v6, &(reply->udp_encap.src_ip.un.ip6), sizeof(ip6_address_t));
+ memcpy(&face->face.remote_addr.v6, &(reply->udp_encap.dst_ip.un.ip6), sizeof(ip6_address_t));
+ break;
+ }
+ default:
+ break;
+ }
+
+ face->face.local_port = reply->udp_encap.src_port;
+ face->face.remote_port = reply->udp_encap.dst_port;
+ }
+ return rv;
+}
+
+int fill_face_with_info(hc_face_t * face, vapi_type_fib_path *path, hc_sock_t *s) {
+ switch(path->type){
+ case FIB_API_PATH_FLAG_NONE:
+ {
+ face->face.type = FACE_TYPE_HICN;
+ switch(path->proto){
+ case FIB_API_PATH_NH_PROTO_IP4:
+ memcpy(&face->face.remote_addr.v4, &(path->nh.address.ip4), sizeof(ip4_address_t));
+ break;
+ case FIB_API_PATH_NH_PROTO_IP6:
+ memcpy(&face->face.remote_addr.v6, &(path->nh.address.ip6), sizeof(ip6_address_t));
+ break;
+ default:
+ break;
+ }
+ face->face.netdevice.index = path->sw_if_index;
+ }
+ break;
+ case FIB_API_PATH_TYPE_UDP_ENCAP:
+ {
+ face->face.type = FACE_TYPE_UDP;
+ face->face.netdevice.index = clib_net_to_host_u32(path->nh.obj_id);
+ //vapi_msg_udp_encap_dump *msg;
+ //msg = vapi_alloc_udp_encap_dump(s->g_vapi_ctx_instance);
+ //vapi_udp_encap_dump(s->g_vapi_ctx_instance, msg, parse_udp_encap_list, face);
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
/* ROUTE LIST */
+typedef struct hicn_route_socket_s {
+ hc_data_t *data;
+ hc_sock_t *s;
+} hicn_route_socket_t;
+
vapi_error_e parse_route_list( vapi_ctx_t ctx,
void *callback_ctx,
vapi_error_e rv,
bool is_last,
- vapi_payload_hicn_api_routes_details *reply) {
+ vapi_payload_ip_route_details *reply) {
if (reply == NULL || rv != VAPI_OK)
return rv;
- if (reply->retval != VAPI_OK)
- return reply->retval;
+ hicn_route_socket_t *rs = (hicn_route_socket_t *)callback_ctx;
+ hc_data_t *data = rs->data;
+
+ u8 found = false;
+ for (int j = 0; j < reply->route.n_paths; j++){
+ for (int i = 0; i < data->size && !found; i++) {
+ hc_route_t * route = &((hc_route_t*)(data->buffer))[i];
+
+ if(ip46_address_is_ip4((ip46_address_t *)&(route->remote_addr)) &&
+ memcmp(route->remote_addr.v4.as_u8, reply->route.prefix.address.un.ip4, sizeof(ip4_address_t)) == 0 &&
+ route->len == reply->route.prefix.len && route->face_id == ~0) {
+ fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
+ found = true;
+ } else if (memcmp(route->remote_addr.v6.as_u8, reply->route.prefix.address.un.ip6, sizeof(ip6_address_t)) == 0 &&
+ route->len == reply->route.prefix.len && route->face_id == ~0) {
+ fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s);
+ found = true;
+ }
+ }
+ }
+
+ return rv;
+}
+
+vapi_error_e parse_hicn_route_list( vapi_ctx_t ctx,
+ void *callback_ctx,
+ vapi_error_e rv,
+ bool is_last,
+ vapi_payload_hicn_api_routes_details *reply) {
+
+ if (reply == NULL || rv != VAPI_OK)
+ return rv;
hc_data_t *data = (hc_data_t *)callback_ctx;
@@ -742,7 +1000,7 @@ vapi_error_e parse_route_list( vapi_ctx_t ctx,
for (int i = 0; i < reply->nfaces; i++) {
hc_route_t * route = &((hc_route_t*)(data->buffer))[data->current];
- route->face_id = reply->faceids[i];
+ route->face_id = ~0;
route->cost = 1;
route->len = reply->prefix.len;
if (reply->prefix.address.af == ADDRESS_IP6)
@@ -757,13 +1015,14 @@ vapi_error_e parse_route_list( vapi_ctx_t ctx,
data->current++;
}
- return reply->retval;
+ return rv;
}
int _hc_route_list(hc_sock_t *s, hc_data_t **pdata, bool async) {
vapi_lock();
- vapi_msg_hicn_api_routes_dump *hicnp_msg;
- hicnp_msg = vapi_alloc_hicn_api_routes_dump(s->g_vapi_ctx_instance);
+
+ vapi_msg_hicn_api_routes_dump *msg;
+ msg = vapi_alloc_hicn_api_routes_dump(s->g_vapi_ctx_instance);
hc_data_t *data = hc_data_create(0, sizeof(hc_route_t),NULL);
int ret = VAPI_OK;
@@ -781,7 +1040,28 @@ int _hc_route_list(hc_sock_t *s, hc_data_t **pdata, bool async) {
goto err_free;
}
- ret = vapi_hicn_api_routes_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list, data);
+ ret = vapi_hicn_api_routes_dump(s->g_vapi_ctx_instance, msg, parse_hicn_route_list, data);
+
+ if (ret != VAPI_OK)
+ goto err_free;
+
+ vapi_msg_ip_route_dump *hicnp_msg;
+ hicnp_msg = vapi_alloc_ip_route_dump(s->g_vapi_ctx_instance);
+ hicnp_msg->payload.table.table_id = 0;
+ hicnp_msg->payload.table.is_ip6 = 1;
+
+ hicn_route_socket_t ctx = {
+ .data = data,
+ .s = s,
+ };
+
+ ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list, &ctx);
+
+ hicnp_msg = vapi_alloc_ip_route_dump(s->g_vapi_ctx_instance);
+ hicnp_msg->payload.table.table_id = 0;
+ hicnp_msg->payload.table.is_ip6 = 0;
+
+ ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list, &ctx);
if (ret != VAPI_OK)
goto err_free;
@@ -880,278 +1160,23 @@ int hc_connection_to_local_listener(const hc_connection_t *connection,
return 0;
}
-/* FACE CREATE */
-vapi_error_e parse_face_create( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_face_add_reply *reply) {
-
- if (reply == NULL || rv != VAPI_OK)
- return rv;
-
- if (reply->retval != VAPI_OK)
- return reply->retval;
-
- hc_data_t *data = (hc_data_t *)callback_ctx;
-
- hc_face_t *output = (hc_face_t *)data->buffer;
-
- output->id = reply->faceid;
- return reply->retval;
-}
-
int hc_face_create(hc_sock_t *s, hc_face_t *face) {
-
- vapi_lock();
- vapi_msg_hicn_api_face_add *hicnp_msg;
- hicnp_msg = vapi_alloc_hicn_api_face_add(s->g_vapi_ctx_instance);
-
- int retval = VAPI_OK;
- if (!hicnp_msg) {
- retval = VAPI_ENOMEM;
- goto END;
- }
-
- switch(face->face.type) {
- case FACE_TYPE_HICN:
- {
- u8 check = ip46_address_is_ip4((ip46_address_t *)&(face->face.local_addr)) == ip46_address_is_ip4((ip46_address_t *)&(face->face.remote_addr));
- if (!check) {
- retval = -1;
- goto END;
- }
-
- hicnp_msg->payload.type = IP_FACE;
- if (ip46_address_is_ip4((ip46_address_t *)&(face->face.local_addr)))
- {
- memcpy(hicnp_msg->payload.face.ip.local_addr.un.ip4, face->face.local_addr.v4.as_u8, 4);
- memcpy(hicnp_msg->payload.face.ip.remote_addr.un.ip4, face->face.remote_addr.v4.as_u8, 4);
- hicnp_msg->payload.face.ip.local_addr.af = ADDRESS_IP4;
- hicnp_msg->payload.face.ip.remote_addr.af = ADDRESS_IP4;
- }
- else
- {
- memcpy(hicnp_msg->payload.face.ip.local_addr.un.ip6, face->face.local_addr.v6.as_u8, 16);
- memcpy(hicnp_msg->payload.face.ip.remote_addr.un.ip6, face->face.remote_addr.v6.as_u8, 16);
- hicnp_msg->payload.face.ip.local_addr.af = ADDRESS_IP6;
- hicnp_msg->payload.face.ip.remote_addr.af = ADDRESS_IP6;
- }
- hicnp_msg->payload.face.ip.swif = face->face.netdevice.index;
- memcpy(hicnp_msg->payload.face.ip.if_name, face->face.netdevice.name, IFNAMSIZ);
- break;
- }
- case FACE_TYPE_UDP:
- {
- u8 check = ip46_address_is_ip4((ip46_address_t *)&(face->face.local_addr)) == ip46_address_is_ip4((ip46_address_t *)&(face->face.remote_addr));
- if (!check) {
- retval = -1;
- goto END;
- }
-
- hicnp_msg->payload.type = UDP_FACE;
- if (ip46_address_is_ip4((ip46_address_t *)&(face->face.local_addr)))
- {
- memcpy(hicnp_msg->payload.face.udp.local_addr.un.ip4, face->face.local_addr.v4.as_u8, 4);
- memcpy(hicnp_msg->payload.face.udp.remote_addr.un.ip4, face->face.remote_addr.v4.as_u8, 4);
- hicnp_msg->payload.face.udp.local_addr.af = ADDRESS_IP4;
- hicnp_msg->payload.face.udp.remote_addr.af = ADDRESS_IP4;
- }
- else
- {
- memcpy(hicnp_msg->payload.face.udp.local_addr.un.ip6, face->face.local_addr.v6.as_u8, 16);
- memcpy(hicnp_msg->payload.face.udp.remote_addr.un.ip6, face->face.remote_addr.v6.as_u8, 16);
- hicnp_msg->payload.face.udp.local_addr.af = ADDRESS_IP6;
- hicnp_msg->payload.face.udp.remote_addr.af = ADDRESS_IP6;
- }
- hicnp_msg->payload.face.udp.lport = face->face.local_port;
- hicnp_msg->payload.face.udp.rport = face->face.remote_port;
- hicnp_msg->payload.face.udp.swif = face->face.netdevice.index;
- memcpy(hicnp_msg->payload.face.udp.if_name, face->face.netdevice.name, IFNAMSIZ);
- break;
- }
- default:
- {
- retval = -1;
- goto END;
- }
- }
-
- hc_data_t *data = hc_data_create(0, sizeof(hc_face_t),NULL);
-
- if (!data) {
- retval = -1;
- goto END;
- }
-
- data->buffer = malloc(sizeof(hc_face_t));
- data->out_element_size = sizeof(hc_face_t);
-
- if (!data->buffer) {
- free (data);
- retval = -1;
- goto END;
- }
-
- retval = vapi_hicn_api_face_add(s->g_vapi_ctx_instance, hicnp_msg, parse_face_create, data);
-
- if (retval != VAPI_OK)
- goto END;
-
- face->id = ((hc_face_t *)data->buffer)->id;
-
- END:
- vapi_unlock();
- return retval;
-}
-
-vapi_error_e parse_face_delete( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_face_del_reply *reply) {
-
- if (reply == NULL || rv != VAPI_OK)
- return rv;
-
- return reply->retval;
+ ERROR("Face creation implemented.");
+ return -1;
}
int hc_face_delete(hc_sock_t *s, hc_face_t *face) {
- vapi_msg_hicn_api_face_del *hicnp_msg;
- vapi_lock();
- hicnp_msg = vapi_alloc_hicn_api_face_del(s->g_vapi_ctx_instance);
-
- if (!hicnp_msg) return VAPI_ENOMEM;
-
- hicnp_msg->payload.faceid = face->id;
-
- int retval = vapi_hicn_api_face_del(s->g_vapi_ctx_instance, hicnp_msg, parse_face_delete, NULL);
- vapi_unlock();
- return retval;
+ ERROR("Face deletion not implemented.");
+ return -1;
}
/* FACE LIST */
-vapi_error_e parse_face_list( vapi_ctx_t ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_faces_details *reply) {
-
- if (reply == NULL || rv != VAPI_OK)
- return rv;
-
- if (reply->retval != VAPI_OK)
- return reply->retval;
-
- hc_data_t *data = (hc_data_t *)callback_ctx;
-
- if (data->size == data->current) {
- int new_size = data->size *2;
- data->buffer = realloc(data->buffer, sizeof(hc_face_t) * (new_size));
- if (!data->buffer)
- return VAPI_ENOMEM;
-
- data->size =new_size;
- }
-
- int retval = VAPI_OK;
-
- hc_face_t * face = &((hc_face_t *)(data->buffer))[data->current];
- switch(reply->type)
- {
- case IP_FACE:
- {
- if (reply->face.ip.local_addr.af == ADDRESS_IP4)
- {
- memcpy(face->face.local_addr.v4.as_u8, reply->face.ip.local_addr.un.ip4, IPV4_ADDR_LEN);
- memcpy(face->face.remote_addr.v4.as_u8, reply->face.ip.remote_addr.un.ip4, IPV4_ADDR_LEN);
- }
- else
- {
- memcpy(face->face.local_addr.v6.as_u8, reply->face.ip.local_addr.un.ip6, IPV6_ADDR_LEN);
- memcpy(face->face.remote_addr.v6.as_u8, reply->face.ip.remote_addr.un.ip6, IPV6_ADDR_LEN);
- }
- face->face.type = FACE_TYPE_HICN;
- face->id = reply->faceid;
- face->face.netdevice.index = reply->face.ip.swif;
- memcpy(face->face.netdevice.name, reply->face.ip.if_name, IFNAMSIZ);
- break;
- }
- case UDP_FACE:
- {
- if (reply->face.ip.local_addr.af == ADDRESS_IP4)
- {
- memcpy(face->face.local_addr.v4.as_u8, reply->face.udp.local_addr.un.ip4, IPV4_ADDR_LEN);
- memcpy(face->face.remote_addr.v4.as_u8, reply->face.udp.remote_addr.un.ip4, IPV4_ADDR_LEN);
- }
- else
- {
- memcpy(face->face.local_addr.v6.as_u8, reply->face.udp.local_addr.un.ip6, IPV6_ADDR_LEN);
- memcpy(face->face.remote_addr.v6.as_u8, reply->face.udp.remote_addr.un.ip6, IPV6_ADDR_LEN);
- }
- face->face.local_port = reply->face.udp.lport;
- face->face.remote_port = reply->face.udp.rport;
- face->face.type = FACE_TYPE_UDP;
- face->id = reply->faceid;
- face->face.netdevice.index = reply->face.udp.swif;
- memcpy(face->face.netdevice.name, reply->face.udp.if_name, IFNAMSIZ);
- break;
- }
- default:
- retval = -1;
- }
- if (!retval)
- data->current++;
-
- return reply->retval;
-}
-
int hc_face_list(hc_sock_t *s, hc_data_t **pdata) {
- vapi_lock();
- vapi_msg_hicn_api_faces_dump *hicnp_msg;
- hicnp_msg = vapi_alloc_hicn_api_faces_dump(s->g_vapi_ctx_instance);
-
- int retval = 0;
- if (!hicnp_msg) {
- retval = VAPI_ENOMEM;
- goto END;
- }
- hc_data_t *data = hc_data_create(0, sizeof(hc_face_t),NULL);
-
- if (!data) {
- retval = -1;
- goto END;
- }
-
- data->buffer = malloc(sizeof(hc_face_t));
- data->size = 1;
-
- if (!data->buffer) {
- free (data);
- retval = -1;
- goto err;
- }
-
-
- retval = vapi_hicn_api_faces_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_face_list, data);
- *pdata = data;
-
- if (retval != VAPI_OK)
- goto err;
-
- data->size = data->current;
- vapi_unlock();
- return retval;
-
- err:
- free(data);
- END:
- vapi_unlock();
- return retval;
+ERROR("Face list not implemented.");
+return -1;
}
int hc_connection_parse_to_face(void *in, hc_face_t *face) { return 0; }
diff --git a/ctrl/libhicnctrl/src/hicnctrl.c b/ctrl/libhicnctrl/src/hicnctrl.c
index 4be9f196c..e95b9b0eb 100644
--- a/ctrl/libhicnctrl/src/hicnctrl.c
+++ b/ctrl/libhicnctrl/src/hicnctrl.c
@@ -354,7 +354,7 @@ parse_options(int argc, char *argv[], hc_command_t * command)
switch(command->action) {
case ACTION_CREATE:
if ((argc - optind != 5) && (argc - optind != 6)) {
- usage_face_create(argv[0], true, false);
+ usage_face_create(argv[0], true, false);
goto ERR_PARAM;
}
/* NAME will be autogenerated (and currently not used) */
diff --git a/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt b/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt
index 3739663b5..6be257656 100644
--- a/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt
+++ b/ctrl/sysrepo-plugins/hicn-light/CMakeLists.txt
@@ -20,7 +20,7 @@ set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O2")
set(CMAKE_C_FLAGS_DEBUG "-g -O0")
set (CMAKE_INSTALL_LIBDIR "/usr/lib")
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.5)
project(sysrepo-light-plugins)
# Cmake find modules
diff --git a/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt b/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt
index e1d3dd39a..220809d71 100644
--- a/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt
+++ b/ctrl/sysrepo-plugins/hicn-light/plugin/CMakeLists.txt
@@ -20,7 +20,7 @@ set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O2")
set(CMAKE_C_FLAGS_DEBUG "-g -O0")
set (CMAKE_INSTALL_LIBDIR "/usr/lib")
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.5)
project(sysrepo-light-plugins)
# Cmake find modules
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt b/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt
index 705bd3cee..a89936776 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt
+++ b/ctrl/sysrepo-plugins/hicn-plugin/CMakeLists.txt
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 3.5)
# Cmake find modules
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../cmake/Modules"
@@ -31,11 +31,13 @@ set(SOURCE_FILES
list(APPEND SYSREPO_PLUGIN_INCLUDE_DIRS
${VPP_INCLUDE_DIRS}
${HICNPLUGIN_INCLUDE_DIRS}
+ ${SYSREPO_INCLUDE_DIRS}
)
list(APPEND LIBRARIES
${SYSREPO_LIBRARIES}
- ${VPP_LIBRARIES})
+ ${VPP_LIBRARIES}
+)
build_library(sysrepohicn
SHARED
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c
index dc3ac16d4..bbcc2e9bf 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Cisco and/or its affiliates.
+ * Copyright (c) 2019-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:
@@ -38,8 +38,10 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx) {
// HICN subscribe
hicn_subscribe_events(session, &subscription);
+ //sr_subscription_ctx_t *subscription2 = NULL;
+
// IETF subscribe
- ietf_subscribe_events(session, &subscription);
+ //ietf_subscribe_events(session, &subscription2);
/* set subscription as our private context */
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c
index b46b38b89..3e0c90cf9 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Copyright (c) 2016-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:
@@ -442,7 +442,7 @@ ietf_interface_ipv46_address_change_cb(sr_session_ctx_t *session, const char *mo
sr_change_oper_t op = SR_OP_CREATED;
sr_val_t *old_val = NULL;
sr_val_t *new_val = NULL;
- sr_xpath_ctx_t xpath_ctx = { 0, };
+ sr_xpath_ctx_t xpath_ctx = { 0 };
bool is_ipv6 = false, has_addr = false, has_prefix = false;
uint8_t addr[16] = { 0, };
uint8_t prefix = 0;
@@ -570,7 +570,8 @@ int ietf_subscribe_events(sr_session_ctx_t *session,
goto error;
}
- rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address", ietf_interface_ipv46_address_change_cb,
+ //rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address", ietf_interface_ipv46_address_change_cb,
+ rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces", ietf_interface_ipv46_address_change_cb,
NULL,
99, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription);
@@ -579,9 +580,9 @@ int ietf_subscribe_events(sr_session_ctx_t *session,
goto error;
}
- rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address", ietf_interface_ipv46_address_change_cb,
- NULL,
- 98, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription);
+ //rc = sr_module_change_subscribe(session, "ietf-interfaces","/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address", ietf_interface_ipv46_address_change_cb,
+ // NULL,
+ // 98, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription);
if (rc != SR_ERR_OK) {
SRP_LOG_DBGMSG("Problem in subscription /ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address\n");
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/mainpage.dox b/ctrl/sysrepo-plugins/hicn-plugin/plugin/mainpage.dox
index dc4289379..978578039 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/mainpage.dox
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/mainpage.dox
@@ -29,47 +29,13 @@ fi
*Here you can find different examples to run RPC in the yang-model.
```
-<face-ip-add xmlns="urn:sysrepo:hicn">
- <lip4>192.168.1.10</lip4>
- <lip6>-1</lip6>
- <rip4>192.168.1.1</rip4>
- <rip6>-1</rip6>
- <swif>0</swif>
-</face-ip-add>
-
-<route-nhops-add xmlns="urn:sysrepo:hicn">
- <ip4>192.168.1.1</ip4>
- <ip6>-1</ip6>
- <len>24</len>
- <face_ids0>0</face_ids0>
- <face_ids1>0</face_ids1>
- <face_ids2>0</face_ids2>
- <face_ids3>0</face_ids3>
- <face_ids4>0</face_ids4>
- <face_ids5>0</face_ids5>
- <face_ids6>0</face_ids6>
- <n_faces>1</n_faces>
-</route-nhops-add>
-
-<route-nhops-del xmlns="urn:sysrepo:hicn">
- <ip4>192.168.1.1</ip4>
- <ip6>-1</ip6>
- <len>24</len>
- <faceid>0</faceid>
-</route-nhops-del>
-
-
-<face-ip-del xmlns="urn:sysrepo:hicn">
- <faceid>0</faceid>
-</face-ip-del>
-
-
-<punting-del-ip xmlns="urn:sysrepo:hicn">
- <ip4>192.168.0.1</ip4>
- <ip6>-1</ip6>
- <len>24</len>
- <swif>0</swif>
-</punting-del-ip>
+<hicn-enable xmlns="urn:sysrepo:hicn">
+ <prefix>b001::/64</prefix>
+</hicn-enable>
+
+<hicn-disable xmlns="urn:sysrepo:hicn">
+ <prefix>b001::/64</prefix>
+</hicn-disable>
```
*/
diff --git a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c
index 2a486f599..63685e10a 100644
--- a/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c
+++ b/ctrl/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c
@@ -1,1134 +1,875 @@
/*
-* Copyright (c) 2019-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) 2019-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 hicn_model.c
* @brief This file contains implementations of the main calls
*/
-
#define _GNU_SOURCE
-#include <stdio.h>
-#include <malloc.h>
-#include <sysrepo/xpath.h>
#include <inttypes.h>
-#include <unistd.h>
+#include <malloc.h>
#include <pthread.h>
-
-
-
#include <sched.h>
+#include <stdio.h>
+#include <string.h>
+#include <sysrepo/xpath.h>
+#include <unistd.h>
/* Hicn headers */
#include <hicn/util/ip_address.h>
+
#include "../hicn_plugin.h"
#include "../hicn_vpp_comm.h"
#include "hicn_model.h"
#include "tlock.h"
-
DEFINE_VAPI_MSG_IDS_HICN_API_JSON
-
// Shared local variables between state and RPCs
/**
* @brief this shared variable keeps the hicn state
*/
-volatile hicn_state_t * hicn_state = NULL;
+volatile hicn_state_t *hicn_state = NULL;
/**
* @brief this shared variable keeps hicn strategies
*/
-volatile hicn_strategies_t * hicn_strategies =NULL;
+volatile hicn_strategies_t *hicn_strategies = NULL;
/**
* @brief this shared variable keeps statistics of hicn faces
*/
-volatile hicn_faces_t * hicn_faces = NULL;
+volatile hicn_faces_t *hicn_faces = NULL;
/**
* @brief this shared variable keeps routes information in hicn
*/
-volatile hicn_routes_t * hicn_routes = NULL;
+volatile hicn_routes_t *hicn_routes = NULL;
/**
- * @brief this shared variable is the link list to maintain all the faces (up to MAX_FACES)
+ * @brief this shared variable is the link list to maintain all the faces (up to
+ * MAX_FACES)
*/
-struct hicn_faces_s * fcurrent = NULL;
+struct hicn_faces_s *fcurrent = NULL;
/**
* @brief this shared variable is the link list to maintain all the routes
*/
-struct hicn_routes_s * rcurrent = NULL;
-
-
-static int init_buffer(void){
-
- hicn_state = memalign(MEM_ALIGN, sizeof(hicn_state_t) );
- memset((hicn_state_t *)hicn_state, 0 , sizeof(hicn_state_t) );
+struct hicn_routes_s *rcurrent = NULL;
- hicn_strategies = memalign(MEM_ALIGN, sizeof(hicn_strategies_t) );
- memset((hicn_strategies_t *) hicn_strategies, 0 , sizeof(hicn_strategies_t) );
+static int init_buffer(void) {
+ hicn_state = memalign(MEM_ALIGN, sizeof(hicn_state_t));
+ memset((hicn_state_t *)hicn_state, 0, sizeof(hicn_state_t));
- hicn_faces = memalign(MEM_ALIGN, sizeof(hicn_faces_t) );
- hicn_faces->next=memalign(MEM_ALIGN, sizeof(struct hicn_faces_s));
- fcurrent=hicn_faces->next;
+ hicn_strategies = memalign(MEM_ALIGN, sizeof(hicn_strategies_t));
+ memset((hicn_strategies_t *)hicn_strategies, 0, sizeof(hicn_strategies_t));
+ hicn_faces = memalign(MEM_ALIGN, sizeof(hicn_faces_t));
+ hicn_faces->next = memalign(MEM_ALIGN, sizeof(struct hicn_faces_s));
+ fcurrent = hicn_faces->next;
- hicn_routes = memalign(MEM_ALIGN, sizeof(hicn_routes_t) );
- hicn_routes->next=memalign(MEM_ALIGN, sizeof(struct hicn_routes_s));
- rcurrent=hicn_routes->next;
+ hicn_routes = memalign(MEM_ALIGN, sizeof(hicn_routes_t));
+ hicn_routes->next = memalign(MEM_ALIGN, sizeof(struct hicn_routes_s));
+ rcurrent = hicn_routes->next;
+ int retval = -1;
+ ARG_CHECK5(retval, hicn_state, hicn_strategies, fcurrent, hicn_faces,
+ hicn_routes);
+ hicn_routes->nroute = 0;
+ hicn_faces->nface = 0;
+ retval = 0;
- int retval=-1;
- ARG_CHECK5(retval, hicn_state, hicn_strategies, fcurrent, hicn_faces, hicn_routes);
- hicn_routes->nroute=0;
- hicn_faces->nface=0;
- retval=0;
-
- return retval;
+ return retval;
}
-static int init_face_pool(struct hicn_faces_s * head){
-
- for(int i=0; i<MAX_FACE_POOL; i++){
- head->next=memalign(MEM_ALIGN, sizeof(struct hicn_faces_s));
- head=head->next;
- }
- SRP_LOG_DBGMSG("Face memory pool allocated\n");
- head->next=NULL;
- return 0;
-
+static int init_face_pool(struct hicn_faces_s *head) {
+ for (int i = 0; i < MAX_FACE_POOL; i++) {
+ head->next = memalign(MEM_ALIGN, sizeof(struct hicn_faces_s));
+ head = head->next;
+ }
+ SRP_LOG_DBGMSG("Face memory pool allocated\n");
+ head->next = NULL;
+ return 0;
}
-static int init_route_pool(struct hicn_routes_s * head){
-
- for(int i=0; i<MAX_ROUTE_POOL; i++){
- head->next=memalign(MEM_ALIGN, sizeof(struct hicn_routes_s));
- head=head->next;
- }
- SRP_LOG_DBGMSG("Route memory pool allocated\n");
- head->next=NULL;
- return 0;
-
+static int init_route_pool(struct hicn_routes_s *head) {
+ for (int i = 0; i < MAX_ROUTE_POOL; i++) {
+ head->next = memalign(MEM_ALIGN, sizeof(struct hicn_routes_s));
+ head = head->next;
+ }
+ SRP_LOG_DBGMSG("Route memory pool allocated\n");
+ head->next = NULL;
+ return 0;
}
/* VAPI CALLBACKS */
-static vapi_error_e call_hicn_api_strategies_get(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_strategies_get_reply *reply){
-if(!reply->retval){
- SRP_LOG_DBGMSG("Successfully done");
- return VAPI_OK;
- }else
- return VAPI_EUSER;
-}
-
-static vapi_error_e call_hicn_api_route_nhops_add(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_route_nhops_add_reply *reply){
-if(!reply->retval){
- SRP_LOG_DBGMSG("Successfully done");
- return VAPI_OK;
- }else
- return VAPI_EUSER;
-}
-
-static vapi_error_e call_hicn_api_route_del(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_route_del_reply *reply){
-
-if(!reply->retval){
- SRP_LOG_DBGMSG("Successfully done");
- return VAPI_OK;
- }else
- return VAPI_EUSER;
-}
-
-static vapi_error_e call_hicn_api_face_ip_params_get(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_face_ip_params_get_reply *reply){
-if(!reply->retval){
- if (callback_ctx!=NULL){
- struct hicn_faces_s * tmp;
- tmp = (struct hicn_faces_s *) callback_ctx;
+static vapi_error_e call_hicn_api_strategies_get(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_strategies_get_reply *reply) {
+ if (!reply->retval) {
+ SRP_LOG_DBGMSG("Successfully done");
+ return VAPI_OK;
+ } else
+ return VAPI_EUSER;
+}
+
+static vapi_error_e call_hicn_api_face_params_get(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_face_params_get_reply *reply) {
+ if (!reply->retval) {
+ if (callback_ctx != NULL) {
+ struct hicn_faces_s *tmp;
+ tmp = (struct hicn_faces_s *)callback_ctx;
tmp->face.intfc = reply->swif;
+ }
+ return VAPI_OK;
+ } else
+ return VAPI_EUSER;
+}
+
+static vapi_error_e call_vapi_hicn_api_node_stats_get(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_node_stats_get_reply *reply) {
+ if (!reply->retval) {
+ hicn_state->pkts_processed = reply->pkts_processed;
+ hicn_state->pkts_interest_count = reply->pkts_interest_count;
+ hicn_state->pkts_data_count = reply->pkts_data_count;
+ hicn_state->pkts_from_cache_count = reply->pkts_from_cache_count;
+ hicn_state->pkts_no_pit_count = reply->pkts_no_pit_count;
+ hicn_state->pit_expired_count = reply->pit_expired_count;
+ hicn_state->cs_expired_count = reply->cs_expired_count;
+ hicn_state->cs_lru_count = reply->cs_lru_count;
+ hicn_state->pkts_drop_no_buf = reply->pkts_drop_no_buf;
+ hicn_state->interests_aggregated = reply->interests_aggregated;
+ hicn_state->interests_retx = reply->interests_retx;
+ hicn_state->pit_entries_count = reply->pit_entries_count;
+ hicn_state->cs_entries_count = reply->cs_entries_count;
+ hicn_state->cs_entries_ntw_count = reply->cs_entries_ntw_count;
+ return VAPI_OK;
+ } else
+ return VAPI_EUSER;
+}
+
+static inline void state_update(sr_val_t *vals, struct lyd_node **parent,
+ sr_session_ctx_t *session) {
+ char buf[20];
+
+ sr_val_set_xpath(&vals[0], "/hicn:hicn-state/states/pkts_processed");
+ vals[0].type = SR_UINT64_T;
+ vals[0].data.uint64_val = hicn_state->pkts_processed;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->pkts_processed);
+ *parent =
+ lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)),
+ vals[0].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[1], "/hicn:hicn-state/states/pkts_interest_count");
+ vals[1].type = SR_UINT64_T;
+ vals[1].data.uint64_val = hicn_state->pkts_interest_count;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->pkts_interest_count);
+ lyd_new_path(*parent, NULL, vals[1].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[2], "/hicn:hicn-state/states/pkts_data_count");
+ vals[2].type = SR_UINT64_T;
+ vals[2].data.uint64_val = hicn_state->pkts_data_count;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->pkts_data_count);
+ lyd_new_path(*parent, NULL, vals[2].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[3], "/hicn:hicn-state/states/pkts_from_cache_count");
+ vals[3].type = SR_UINT64_T;
+ vals[3].data.uint64_val = hicn_state->pkts_from_cache_count;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->pkts_from_cache_count);
+ lyd_new_path(*parent, NULL, vals[3].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[4], "/hicn:hicn-state/states/pkts_no_pit_count");
+ vals[4].type = SR_UINT64_T;
+ vals[4].data.uint64_val = hicn_state->pkts_no_pit_count;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->pkts_no_pit_count);
+ lyd_new_path(*parent, NULL, vals[4].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[5], "/hicn:hicn-state/states/pit_expired_count");
+ vals[5].type = SR_UINT64_T;
+ vals[5].data.uint64_val = hicn_state->pit_expired_count;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->pit_expired_count);
+ lyd_new_path(*parent, NULL, vals[5].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[6], "/hicn:hicn-state/states/cs_expired_count");
+ vals[6].type = SR_UINT64_T;
+ vals[6].data.uint64_val = hicn_state->cs_expired_count;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->cs_expired_count);
+ lyd_new_path(*parent, NULL, vals[6].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[7], "/hicn:hicn-state/states/cs_lru_count");
+ vals[7].type = SR_UINT64_T;
+ vals[7].data.uint64_val = hicn_state->cs_lru_count;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->cs_lru_count);
+ lyd_new_path(*parent, NULL, vals[7].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[8], "/hicn:hicn-state/states/pkts_drop_no_buf");
+ vals[8].type = SR_UINT64_T;
+ vals[8].data.uint64_val = hicn_state->pkts_drop_no_buf;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->pkts_drop_no_buf);
+ lyd_new_path(*parent, NULL, vals[8].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[9], "/hicn:hicn-state/states/interests_aggregated");
+ vals[9].type = SR_UINT64_T;
+ vals[9].data.uint64_val = hicn_state->interests_aggregated;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->interests_aggregated);
+ lyd_new_path(*parent, NULL, vals[9].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[10], "/hicn:hicn-state/states/interests_retx");
+ vals[10].type = SR_UINT64_T;
+ vals[10].data.uint64_val = hicn_state->interests_retx;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->interests_retx);
+ lyd_new_path(*parent, NULL, vals[10].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[11],
+ "/hicn:hicn-state/states/interests_hash_collision");
+ vals[11].type = SR_UINT64_T;
+ vals[11].data.uint64_val = hicn_state->interests_hash_collision;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->interests_hash_collision);
+ lyd_new_path(*parent, NULL, vals[11].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[12], "/hicn:hicn-state/states/pit_entries_count");
+ vals[12].type = SR_UINT64_T;
+ vals[12].data.uint64_val = hicn_state->pit_entries_count;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->pit_entries_count);
+ lyd_new_path(*parent, NULL, vals[12].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[13], "/hicn:hicn-state/states/cs_entries_count");
+ vals[13].type = SR_UINT64_T;
+ vals[13].data.uint64_val = hicn_state->cs_entries_count;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->cs_entries_count);
+ lyd_new_path(*parent, NULL, vals[13].xpath, buf, 0, 0);
+
+ sr_val_set_xpath(&vals[14], "/hicn:hicn-state/states/cs_entries_ntw_count");
+ vals[14].type = SR_UINT64_T;
+ vals[14].data.uint64_val = hicn_state->cs_entries_ntw_count;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, hicn_state->cs_entries_ntw_count);
+ lyd_new_path(*parent, NULL, vals[14].xpath, buf, 0, 0);
+}
+
+static inline int routes_update(sr_val_t *vals, uint32_t nleaves,
+ struct lyd_node **parent,
+ sr_session_ctx_t *session) {
+ struct hicn_routes_s *temp = hicn_routes->next;
+ char buf[20];
+ int route = 0;
+ for (int count = 0; count < nleaves; count++) {
+ sr_val_build_xpath(&vals[route], "%s[routeid='%d']/prefix",
+ "/hicn:hicn-state/routes/route", temp->route.route_id);
+ vals[route].type = SR_STRING_T;
+
+ memset(buf, 0x00, 20);
+ if (temp->route.prefix.address.af == ADDRESS_IP4) {
+ struct sockaddr_in sa;
+ memcpy(&sa.sin_addr.s_addr, temp->route.prefix.address.un.ip4,
+ IPV4_ADDR_LEN);
+ inet_ntop(AF_INET, &(sa.sin_addr), buf, INET_ADDRSTRLEN);
+ vals[route].data.string_val = buf;
+ } else {
+ struct sockaddr_in6 sa;
+ memcpy(&sa.sin6_addr, temp->route.prefix.address.un.ip6, IPV6_ADDR_LEN);
+ inet_ntop(AF_INET6, &(sa.sin6_addr), buf, INET6_ADDRSTRLEN);
+ vals[route].data.string_val = buf;
+ }
+
+ lyd_new_path(*parent, NULL, vals[route].xpath, buf, 0, 0);
+
+ route++;
+
+ sr_val_build_xpath(&vals[route], "%s[routeid='%d']/strategy_id",
+ "/hicn:hicn-state/routes/route", temp->route.route_id);
+ vals[route].type = SR_UINT32_T;
+ vals[route].data.uint32_val = temp->route.strategy_id;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%d", temp->route.strategy_id);
+ lyd_new_path(*parent, NULL, vals[route].xpath, buf, 0, 0);
+
+ route++;
+
+ temp = temp->next;
}
- return VAPI_OK;
- }else
- return VAPI_EUSER;
-}
-static vapi_error_e call_hicn_api_route_nhop_del(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_route_nhop_del_reply *reply){
-if(!reply->retval){
- SRP_LOG_DBGMSG("Successfully done");
- return VAPI_OK;
- }else
- return VAPI_EUSER;
-}
-
-static vapi_error_e call_hicn_api_face_ip_del(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_face_ip_del_reply *reply){
-if(!reply->retval){
- SRP_LOG_DBGMSG("Successfully done");
- return VAPI_OK;
- }else
- return VAPI_EUSER;
-}
-
-
-static vapi_error_e call_hicn_api_face_ip_add(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_face_ip_add_reply *reply){
-if(!reply->retval){
- SRP_LOG_DBGMSG("Successfully done");
- return VAPI_OK;
- }else
- return VAPI_EUSER;
-
-}
-
-static vapi_error_e call_vapi_hicn_api_node_stats_get(struct vapi_ctx_s *ctx,
- void *callback_ctx,
- vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_node_stats_get_reply *reply){
-
-
-if(!reply->retval){
- hicn_state->pkts_processed = reply->pkts_processed;
- hicn_state->pkts_interest_count = reply->pkts_interest_count;
- hicn_state->pkts_data_count = reply->pkts_data_count;
- hicn_state->pkts_from_cache_count = reply->pkts_from_cache_count;
- hicn_state->pkts_no_pit_count = reply->pkts_no_pit_count;
- hicn_state->pit_expired_count = reply->pit_expired_count;
- hicn_state->cs_expired_count = reply->cs_expired_count;
- hicn_state->cs_lru_count = reply->cs_lru_count;
- hicn_state->pkts_drop_no_buf = reply->pkts_drop_no_buf;
- hicn_state->interests_aggregated = reply->interests_aggregated;
- hicn_state->interests_retx = reply->interests_retx;
- hicn_state->pit_entries_count = reply->pit_entries_count;
- hicn_state->cs_entries_count = reply->cs_entries_count;
- hicn_state->cs_entries_ntw_count = reply->cs_entries_ntw_count;
- return VAPI_OK;
- }else
- return VAPI_EUSER;
-}
+ SRP_LOG_DBGMSG("Routes state updated \n");
+ return SR_ERR_OK;
+}
+
+static inline int faces_update(sr_val_t *vals, uint32_t nleaves,
+ struct lyd_node **parent,
+ sr_session_ctx_t *session) {
+ struct hicn_faces_s *temp = hicn_faces->next;
+ char buf[20];
+ int face = 0;
+
+ for (int count = 0; count < nleaves; count++) {
+ vapi_msg_hicn_api_face_params_get *msg;
+ msg = vapi_alloc_hicn_api_face_params_get(g_vapi_ctx_instance);
+
+ msg->payload.faceid = temp->face.faceid;
+
+ if (vapi_hicn_api_face_params_get(g_vapi_ctx_instance, msg,
+ call_hicn_api_face_params_get,
+ (void *)temp) != VAPI_OK) {
+ SRP_LOG_DBGMSG("Operation failed");
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ sr_val_build_xpath(&vals[face], "%s[faceid='%d']/intfc",
+ "/hicn:hicn-state/faces/face", temp->face.faceid);
+ vals[face].type = SR_UINT32_T;
+ vals[face].data.uint32_val = temp->face.intfc;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%u", temp->face.intfc);
+ lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
+
+ face++;
+
+ sr_val_build_xpath(&vals[face], "%s[faceid='%d']/irx_packets",
+ "/hicn:hicn-state/faces/face", temp->face.faceid);
+ vals[face].type = SR_UINT64_T;
+ vals[face].data.uint64_val = temp->face.irx_packets;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, temp->face.irx_packets);
+ lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
+
+ face++;
+
+ sr_val_build_xpath(&vals[face], "%s[faceid='%d']/irx_bytes",
+ "/hicn:hicn-state/faces/face", temp->face.faceid);
+ vals[face].type = SR_UINT64_T;
+ vals[face].data.uint64_val = temp->face.irx_bytes;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, temp->face.irx_bytes);
+ lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
+
+ face++;
+
+ sr_val_build_xpath(&vals[face], "%s[faceid='%d']/itx_packets",
+ "/hicn:hicn-state/faces/face", temp->face.faceid);
+ vals[face].type = SR_UINT64_T;
+ vals[face].data.uint64_val = temp->face.itx_packets;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, temp->face.itx_packets);
+ lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
+
+ face++;
+
+ sr_val_build_xpath(&vals[face], "%s[faceid='%d']/itx_bytes",
+ "/hicn:hicn-state/faces/face", temp->face.faceid);
+ vals[face].type = SR_UINT64_T;
+ vals[face].data.uint64_val = temp->face.itx_bytes;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, temp->face.itx_bytes);
+ lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
+
+ face++;
+
+ sr_val_build_xpath(&vals[face], "%s[faceid='%d']/drx_packets",
+ "/hicn:hicn-state/faces/face", temp->face.faceid);
+ vals[face].type = SR_UINT64_T;
+ vals[face].data.uint64_val = temp->face.drx_packets;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, temp->face.drx_packets);
+ lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
+
+ face++;
+
+ sr_val_build_xpath(&vals[face], "%s[faceid='%d']/drx_bytes",
+ "/hicn:hicn-state/faces/face", temp->face.faceid);
+ vals[face].type = SR_UINT64_T;
+ vals[face].data.uint64_val = temp->face.drx_bytes;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, temp->face.drx_packets);
+ lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
+
+ face++;
+
+ sr_val_build_xpath(&vals[face], "%s[faceid='%d']/dtx_packets",
+ "/hicn:hicn-state/faces/face", temp->face.faceid);
+ vals[face].type = SR_UINT64_T;
+ vals[face].data.uint64_val = temp->face.dtx_packets;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, temp->face.dtx_packets);
+ lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
+
+ face++;
+
+ sr_val_build_xpath(&vals[face], "%s[faceid='%d']/dtx_bytes",
+ "/hicn:hicn-state/faces/face", temp->face.faceid);
+ vals[face].type = SR_UINT64_T;
+ vals[face].data.uint64_val = temp->face.dtx_bytes;
+ memset(buf, 0x00, 20);
+ sprintf(buf, "%" PRIu64, temp->face.dtx_bytes);
+ lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
+
+ face++;
+
+ temp = temp->next;
+ }
+ SRP_LOG_DBGMSG("Faces state updated \n");
+ return SR_ERR_OK;
+}
+
+static int hicn_state_states_cb(sr_session_ctx_t *session,
+ const char *module_name, const char *path,
+ const char *request_xpath, uint32_t request_id,
+ struct lyd_node **parent, void *private_data) {
+ sr_val_t *vals;
+ int rc;
+ enum locks_name state;
+ state = lstate;
+ SRP_LOG_DBGMSG("Requesting state data");
+
+ rc = sr_new_values(NSTATE_LEAVES, &vals);
+ if (SR_ERR_OK != rc) {
+ return rc;
+ }
-static inline void state_update(sr_val_t * vals, struct lyd_node **parent, sr_session_ctx_t *session){
- char buf[20];
-
- sr_val_set_xpath(&vals[0], "/hicn:hicn-state/states/pkts_processed");
- vals[0].type = SR_UINT64_T;
- vals[0].data.uint64_val = hicn_state->pkts_processed;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->pkts_processed);
- * parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), vals[0].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[1], "/hicn:hicn-state/states/pkts_interest_count");
- vals[1].type = SR_UINT64_T;
- vals[1].data.uint64_val = hicn_state->pkts_interest_count;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->pkts_interest_count );
- lyd_new_path(*parent, NULL, vals[1].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[2], "/hicn:hicn-state/states/pkts_data_count");
- vals[2].type = SR_UINT64_T;
- vals[2].data.uint64_val = hicn_state->pkts_data_count;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->pkts_data_count );
- lyd_new_path(*parent, NULL, vals[2].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[3], "/hicn:hicn-state/states/pkts_from_cache_count");
- vals[3].type = SR_UINT64_T;
- vals[3].data.uint64_val = hicn_state->pkts_from_cache_count;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->pkts_from_cache_count );
- lyd_new_path(*parent, NULL, vals[3].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[4], "/hicn:hicn-state/states/pkts_no_pit_count");
- vals[4].type = SR_UINT64_T;
- vals[4].data.uint64_val = hicn_state->pkts_no_pit_count;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->pkts_no_pit_count );
- lyd_new_path(*parent, NULL, vals[4].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[5], "/hicn:hicn-state/states/pit_expired_count");
- vals[5].type = SR_UINT64_T;
- vals[5].data.uint64_val = hicn_state->pit_expired_count;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->pit_expired_count );
- lyd_new_path(*parent, NULL, vals[5].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[6], "/hicn:hicn-state/states/cs_expired_count");
- vals[6].type = SR_UINT64_T;
- vals[6].data.uint64_val = hicn_state->cs_expired_count;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->cs_expired_count );
- lyd_new_path(*parent, NULL, vals[6].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[7], "/hicn:hicn-state/states/cs_lru_count");
- vals[7].type = SR_UINT64_T;
- vals[7].data.uint64_val = hicn_state->cs_lru_count;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->cs_lru_count );
- lyd_new_path(*parent, NULL, vals[7].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[8], "/hicn:hicn-state/states/pkts_drop_no_buf");
- vals[8].type = SR_UINT64_T;
- vals[8].data.uint64_val = hicn_state->pkts_drop_no_buf;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->pkts_drop_no_buf );
- lyd_new_path(*parent, NULL, vals[8].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[9], "/hicn:hicn-state/states/interests_aggregated");
- vals[9].type = SR_UINT64_T;
- vals[9].data.uint64_val = hicn_state->interests_aggregated;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->interests_aggregated );
- lyd_new_path(*parent, NULL, vals[9].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[10], "/hicn:hicn-state/states/interests_retx");
- vals[10].type = SR_UINT64_T;
- vals[10].data.uint64_val = hicn_state->interests_retx;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->interests_retx );
- lyd_new_path(*parent, NULL, vals[10].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[11],
- "/hicn:hicn-state/states/interests_hash_collision");
- vals[11].type = SR_UINT64_T;
- vals[11].data.uint64_val = hicn_state->interests_hash_collision;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->interests_hash_collision );
- lyd_new_path(*parent, NULL, vals[11].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[12], "/hicn:hicn-state/states/pit_entries_count");
- vals[12].type = SR_UINT64_T;
- vals[12].data.uint64_val = hicn_state->pit_entries_count;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->pit_entries_count );
- lyd_new_path(*parent, NULL, vals[12].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[13], "/hicn:hicn-state/states/cs_entries_count");
- vals[13].type = SR_UINT64_T;
- vals[13].data.uint64_val = hicn_state->cs_entries_count;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->cs_entries_count );
- lyd_new_path(*parent, NULL, vals[13].xpath, buf, 0, 0);
-
- sr_val_set_xpath(&vals[14], "/hicn:hicn-state/states/cs_entries_ntw_count");
- vals[14].type = SR_UINT64_T;
- vals[14].data.uint64_val = hicn_state->cs_entries_ntw_count;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, hicn_state->cs_entries_ntw_count );
- lyd_new_path(*parent, NULL, vals[14].xpath, buf, 0, 0);
+ tlock(state);
+ state_update(vals, parent, session);
+ tunlock(state);
+ return SR_ERR_OK;
}
-static inline int routes_update(sr_val_t * vals, uint32_t nleaves, struct lyd_node **parent, sr_session_ctx_t *session){
-
- struct hicn_routes_s * temp = hicn_routes->next;
- char buf[20];
- int route =0;
- for(int count=0; count<nleaves; count++){
-
- sr_val_build_xpath(&vals[route], "%s[routeid='%d']/prefix", "/hicn:hicn-state/routes/route",
- temp->route.route_id);
- vals[route].type = SR_STRING_T;
-
- memset(buf, 0x00, 20);
- if (temp->route.prefix.address.af==ADDRESS_IP4){
- struct sockaddr_in sa;
- memcpy(&sa.sin_addr.s_addr, temp->route.prefix.address.un.ip4, IPV4_ADDR_LEN);
- inet_ntop(AF_INET, &(sa.sin_addr), buf, INET_ADDRSTRLEN);
- vals[route].data.string_val = buf;
- }else{
- struct sockaddr_in6 sa;
- memcpy(&sa.sin6_addr,temp->route.prefix.address.un.ip6, IPV6_ADDR_LEN);
- inet_ntop(AF_INET6, &(sa.sin6_addr), buf, INET6_ADDRSTRLEN);
- vals[route].data.string_val = buf;
- }
-
-
- lyd_new_path(*parent, NULL, vals[route].xpath, buf, 0, 0);
-
-
- route++;
+static int hicn_state_route_cb(sr_session_ctx_t *session,
+ const char *module_name, const char *path,
+ const char *request_xpath, uint32_t request_id,
+ struct lyd_node **parent, void *private_data) {
+ sr_val_t *vals;
+ int rc;
+ enum locks_name route;
+ route = lroute;
+ uint32_t NROUTE_NODES = hicn_routes->nroute * ROUTES_CHILDREN;
- sr_val_build_xpath(&vals[route], "%s[routeid='%d']/strategy_id", "/hicn:hicn-state/routes/route",
- temp->route.route_id);
- vals[route].type = SR_UINT32_T;
- vals[route].data.uint32_val = temp->route.strategy_id;
- memset(buf, 0x00, 20);
- sprintf( buf, "%d", temp->route.strategy_id);
- lyd_new_path(*parent, NULL, vals[route].xpath, buf, 0, 0);
-
- route++;
-
- temp=temp->next;
+ rc = sr_new_values(NROUTE_NODES, &vals);
+ if (SR_ERR_OK != rc) {
+ return rc;
+ }
-}
+ tlock(route);
+ routes_update(vals, NROUTE_NODES / ROUTES_CHILDREN, parent, session);
+ tunlock(route);
- SRP_LOG_DBGMSG("Routes state updated \n");
- return SR_ERR_OK;
+ return SR_ERR_OK;
}
-static inline int faces_update(sr_val_t * vals, uint32_t nleaves, struct lyd_node **parent, sr_session_ctx_t *session){
-
- struct hicn_faces_s * temp = hicn_faces->next;
- char buf[20];
- int face =0;
-
-
- for(int count=0; count<nleaves; count++){
-
- vapi_msg_hicn_api_face_ip_params_get *msg;
- msg = vapi_alloc_hicn_api_face_ip_params_get(g_vapi_ctx_instance);
-
-
- msg->payload.faceid = temp->face.faceid;
-
- if(vapi_hicn_api_face_ip_params_get(g_vapi_ctx_instance,msg,call_hicn_api_face_ip_params_get, (void *)temp)!=VAPI_OK){
- SRP_LOG_DBGMSG("Operation failed");
- return SR_ERR_OPERATION_FAILED;
- }
-
- sr_val_build_xpath(&vals[face], "%s[faceid='%d']/intfc", "/hicn:hicn-state/faces/face",
- temp->face.faceid);
- vals[face].type = SR_UINT32_T;
- vals[face].data.uint32_val = temp->face.intfc;
- memset(buf, 0x00, 20);
- sprintf( buf,"%u", temp->face.intfc);
- lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
-
-
- face++;
-
-
- sr_val_build_xpath(&vals[face], "%s[faceid='%d']/irx_packets", "/hicn:hicn-state/faces/face",
- temp->face.faceid);
- vals[face].type = SR_UINT64_T;
- vals[face].data.uint64_val = temp->face.irx_packets;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, temp->face.irx_packets);
- lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
-
- face++;
-
-
-
- sr_val_build_xpath(&vals[face], "%s[faceid='%d']/irx_bytes", "/hicn:hicn-state/faces/face",
- temp->face.faceid);
- vals[face].type = SR_UINT64_T;
- vals[face].data.uint64_val = temp->face.irx_bytes;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, temp->face.irx_bytes);
- lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
-
- face++;
-
-
-
- sr_val_build_xpath(&vals[face], "%s[faceid='%d']/itx_packets", "/hicn:hicn-state/faces/face",
- temp->face.faceid);
- vals[face].type = SR_UINT64_T;
- vals[face].data.uint64_val = temp->face.itx_packets;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, temp->face.itx_packets);
- lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
-
- face++;
-
-
+static int hicn_state_faces_cb(sr_session_ctx_t *session,
+ const char *module_name, const char *path,
+ const char *request_xpath, uint32_t request_id,
+ struct lyd_node **parent, void *private_data) {
+ sr_val_t *vals;
+ int rc;
+ enum locks_name faces;
+ faces = lfaces;
+ uint32_t NFACES_NODES = hicn_faces->nface * FACES_CHILDREN;
- sr_val_build_xpath(&vals[face], "%s[faceid='%d']/itx_bytes", "/hicn:hicn-state/faces/face",
- temp->face.faceid);
- vals[face].type = SR_UINT64_T;
- vals[face].data.uint64_val = temp->face.itx_bytes;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, temp->face.itx_bytes);
- lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
-
-
- face++;
-
-
- sr_val_build_xpath(&vals[face], "%s[faceid='%d']/drx_packets", "/hicn:hicn-state/faces/face",
- temp->face.faceid);
- vals[face].type = SR_UINT64_T;
- vals[face].data.uint64_val = temp->face.drx_packets;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, temp->face.drx_packets);
- lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
-
-
- face++;
-
-
-
- sr_val_build_xpath(&vals[face], "%s[faceid='%d']/drx_bytes", "/hicn:hicn-state/faces/face",
- temp->face.faceid);
- vals[face].type = SR_UINT64_T;
- vals[face].data.uint64_val = temp->face.drx_bytes;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, temp->face.drx_packets);
- lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
-
-
- face++;
-
-
- sr_val_build_xpath(&vals[face], "%s[faceid='%d']/dtx_packets", "/hicn:hicn-state/faces/face",
- temp->face.faceid);
- vals[face].type = SR_UINT64_T;
- vals[face].data.uint64_val = temp->face.dtx_packets;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, temp->face.dtx_packets);
- lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
-
- face++;
-
-
- sr_val_build_xpath(&vals[face], "%s[faceid='%d']/dtx_bytes", "/hicn:hicn-state/faces/face",
- temp->face.faceid);
- vals[face].type = SR_UINT64_T;
- vals[face].data.uint64_val = temp->face.dtx_bytes;
- memset(buf, 0x00, 20);
- sprintf( buf, "%" PRIu64, temp->face.dtx_bytes);
- lyd_new_path(*parent, NULL, vals[face].xpath, buf, 0, 0);
-
-
- face++;
+ rc = sr_new_values(NFACES_NODES, &vals);
+ if (SR_ERR_OK != rc) {
+ return rc;
+ }
- temp=temp->next;
+ tlock(faces);
+ faces_update(vals, NFACES_NODES / FACES_CHILDREN, parent, session);
+ tunlock(faces);
- }
- SRP_LOG_DBGMSG("Faces state updated \n");
- return SR_ERR_OK;
+ return SR_ERR_OK;
}
-static int hicn_state_states_cb(sr_session_ctx_t *session, const char *module_name, const char *path, const char *request_xpath,
- uint32_t request_id, struct lyd_node **parent, void *private_data) {
- sr_val_t *vals;
- int rc;
- enum locks_name state;
- state=lstate;
- SRP_LOG_DBGMSG("Requesting state data");
-
-
- rc = sr_new_values(NSTATE_LEAVES, &vals);
- if (SR_ERR_OK != rc) {
- return rc;
- }
+static int hicn_strategies_get_cb(sr_session_ctx_t *session, const char *path,
+ const sr_val_t *input, const size_t input_cnt,
+ sr_event_t event, uint32_t request_id,
+ sr_val_t **output, size_t *output_cnt,
+ void *private_data) {
+ SRP_LOG_DBGMSG("hicn strategies received successfully");
+ vapi_msg_hicn_api_strategies_get *msg;
+ msg = vapi_alloc_hicn_api_strategies_get(g_vapi_ctx_instance);
- tlock(state);
- state_update(vals,parent,session);
- tunlock(state);
-
-
- return SR_ERR_OK;
+ if (vapi_hicn_api_strategies_get(g_vapi_ctx_instance, msg,
+ call_hicn_api_strategies_get,
+ NULL) != VAPI_OK) {
+ SRP_LOG_DBGMSG("Operation failed");
+ return SR_ERR_OPERATION_FAILED;
+ }
+ return SR_ERR_OK;
}
-static int hicn_state_route_cb(sr_session_ctx_t *session, const char *module_name, const char *path, const char *request_xpath,
- uint32_t request_id, struct lyd_node **parent, void *private_data) {
- sr_val_t *vals;
- int rc;
- enum locks_name route;
- route=lroute;
- uint32_t NROUTE_NODES = hicn_routes->nroute * ROUTES_CHILDREN;
-
-
-
- rc = sr_new_values(NROUTE_NODES, &vals);
- if (SR_ERR_OK != rc) {
- return rc;
- }
+static int hicn_face_params_get_cb(sr_session_ctx_t *session, const char *path,
+ const sr_val_t *input,
+ const size_t input_cnt, sr_event_t event,
+ uint32_t request_id, sr_val_t **output,
+ size_t *output_cnt, void *private_data) {
+ SRP_LOG_DBGMSG("hicn face ip params get received successfully");
+ vapi_msg_hicn_api_face_params_get *msg;
- tlock(route);
- routes_update(vals,NROUTE_NODES/ROUTES_CHILDREN, parent, session);
- tunlock(route);
+ msg = vapi_alloc_hicn_api_face_params_get(g_vapi_ctx_instance);
+ msg->payload.faceid = input[0].data.uint32_val;
- return SR_ERR_OK;
-
- }
-
-
- static int hicn_state_faces_cb(sr_session_ctx_t *session, const char *module_name, const char *path, const char *request_xpath,
- uint32_t request_id, struct lyd_node **parent, void *private_data) {
-
-
- sr_val_t *vals;
- int rc;
- enum locks_name faces;
- faces=lfaces;
- uint32_t NFACES_NODES = hicn_faces->nface * FACES_CHILDREN;
-
- rc = sr_new_values(NFACES_NODES, &vals);
- if (SR_ERR_OK != rc) {
- return rc;
- }
-
- tlock(faces);
- faces_update(vals, NFACES_NODES/FACES_CHILDREN, parent, session);
- tunlock(faces);
-
- return SR_ERR_OK;
-
- }
-
-static int hicn_strategies_get_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt,
- sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
-
-SRP_LOG_DBGMSG("hicn strategies received successfully");
-vapi_msg_hicn_api_strategies_get *msg;
-
-msg = vapi_alloc_hicn_api_strategies_get(g_vapi_ctx_instance);
-
-if (vapi_hicn_api_strategies_get(g_vapi_ctx_instance, msg, call_hicn_api_strategies_get, NULL)!=VAPI_OK){
- SRP_LOG_DBGMSG("Operation failed");
- return SR_ERR_OPERATION_FAILED;
-}
-return SR_ERR_OK;
+ if (vapi_hicn_api_face_params_get(g_vapi_ctx_instance, msg,
+ call_hicn_api_face_params_get,
+ NULL) != VAPI_OK) {
+ SRP_LOG_DBGMSG("Operation failed");
+ return SR_ERR_OPERATION_FAILED;
+ }
+ return SR_ERR_OK;
}
-static int hicn_route_nhops_add_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt,
- sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
-
- SRP_LOG_DBGMSG("hicn route nhops add received successfully");
- vapi_msg_hicn_api_route_nhops_add *msg;
-
- msg = vapi_alloc_hicn_api_route_nhops_add(g_vapi_ctx_instance);
-
- if(strcmp(input[0].data.string_val,"-1")){
-
- struct sockaddr_in sa;
- inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr));
- unsigned char * tmp = (unsigned char *) &sa.sin_addr.s_addr;
- memcpy(&msg->payload.prefix.address.un.ip4[0],tmp,B32);
- msg->payload.prefix.address.af = ADDRESS_IP4;
-
- }else if(strcmp(input[1].data.string_val,"-1")){
-
- void *dst = malloc(sizeof(struct in6_addr));
- inet_pton(AF_INET6, input[1].data.string_val, dst);
- unsigned char * tmp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr;
- memcpy(&msg->payload.prefix.address.un.ip6[0],tmp,B128);
- msg->payload.prefix.address.af = ADDRESS_IP6;
-
- }else{
- SRP_LOG_DBGMSG("Invalid local IP address");
- return SR_ERR_OPERATION_FAILED;
- }
-
- msg->payload.prefix.len = input[2].data.uint8_val;
- msg->payload.face_ids[0] = input[3].data.uint32_val;
- msg->payload.face_ids[1] = input[4].data.uint32_val;
- msg->payload.face_ids[2] = input[5].data.uint32_val;
- msg->payload.face_ids[3] = input[6].data.uint32_val;
- msg->payload.face_ids[4] = input[7].data.uint32_val;
- msg->payload.face_ids[5] = input[8].data.uint32_val;
- msg->payload.face_ids[6] = input[9].data.uint32_val;
- msg->payload.n_faces = input[10].data.uint8_val;
-
-
-if(vapi_hicn_api_route_nhops_add(g_vapi_ctx_instance,msg,call_hicn_api_route_nhops_add,NULL)!=VAPI_OK){
- SRP_LOG_DBGMSG("Operation failed");
- return SR_ERR_OPERATION_FAILED;
+static vapi_error_e call_hicn_api_enable_disable(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_enable_disable_reply *reply) {
+ if (!reply->retval) {
+ SRP_LOG_DBGMSG("Successfully done");
+ return VAPI_OK;
+ } else
+ return VAPI_EUSER;
}
-return SR_ERR_OK;
-}
-
-static int hicn_route_del_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt,
- sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
-
- SRP_LOG_DBGMSG("hicn route del received successfully");
- vapi_msg_hicn_api_route_del *msg;
- msg = vapi_alloc_hicn_api_route_del(g_vapi_ctx_instance);
+static int hicn_enable_cb(sr_session_ctx_t *session, const char *path,
+ const sr_val_t *input, const size_t input_cnt,
+ sr_event_t event, uint32_t request_id,
+ sr_val_t **output, size_t *output_cnt,
+ void *private_data) {
+ SRP_LOG_DBGMSG("hicn enable received successfully");
+ vapi_msg_hicn_api_enable_disable *msg;
- if(strcmp(input[0].data.string_val,"-1")){
+ msg = vapi_alloc_hicn_api_enable_disable(g_vapi_ctx_instance);
- struct sockaddr_in sa;
- inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr));
- unsigned char * tmp = (unsigned char *) &sa.sin_addr.s_addr;
- memcpy(&msg->payload.prefix.address.un.ip4[0],tmp,B32);
- msg->payload.prefix.address.af = ADDRESS_IP4;
-
-
- }else if(strcmp(input[1].data.string_val,"-1")){
-
- void *dst = malloc(sizeof(struct in6_addr));
- inet_pton(AF_INET6, input[1].data.string_val, dst);
- unsigned char * tmp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr;
- memcpy(&msg->payload.prefix.address.un.ip6[0],tmp,B128);
- msg->payload.prefix.address.af = ADDRESS_IP6;
-
- }else{
- SRP_LOG_DBGMSG("Invalid local IP address");
- return SR_ERR_OPERATION_FAILED;
- }
+ const char *delim = "/";
+ if (input->type != SR_STRING_T) {
+ SRP_LOG_DBGMSG("Expected prefix of type string");
+ return SR_ERR_OPERATION_FAILED;
+ }
+ char *token;
+
+ /* get the first token */
+ token = strtok(input->data.string_val, delim);
+
+ /* if null the address is ipv4 else ipv6*/
+ if (strrchr(token, ':') == NULL) {
+ struct sockaddr_in sa;
+ inet_pton(AF_INET, token, &(sa.sin_addr));
+ unsigned char *tmp = (unsigned char *)&sa.sin_addr.s_addr;
+ memcpy(&msg->payload.prefix.address.un.ip4[0], tmp, B32);
+ msg->payload.prefix.address.af = ADDRESS_IP4;
+ } else {
+ void *dst = malloc(sizeof(struct in6_addr));
+ inet_pton(AF_INET6, token, dst);
+ unsigned char *tmp = (unsigned char *)((struct in6_addr *)dst)->s6_addr;
+ memcpy(&msg->payload.prefix.address.un.ip6[0], tmp, B128);
+ msg->payload.prefix.address.af = ADDRESS_IP6;
+ }
+ /* The second token is the prefix len*/
+ token = strtok(NULL, delim);
- msg->payload.prefix.len = input[2].data.uint8_val;
+ msg->payload.prefix.len = atoi(token);
+ msg->payload.enable_disable = 1;
+ if (vapi_hicn_api_enable_disable(g_vapi_ctx_instance, msg,
+ call_hicn_api_enable_disable,
+ NULL) != VAPI_OK) {
+ SRP_LOG_DBGMSG("Operation failed");
+ return SR_ERR_OPERATION_FAILED;
+ }
-if(vapi_hicn_api_route_del(g_vapi_ctx_instance,msg,call_hicn_api_route_del,NULL)!=VAPI_OK){
- SRP_LOG_DBGMSG("Operation failed");
- return SR_ERR_OPERATION_FAILED;
+ return SR_ERR_OK;
}
-return SR_ERR_OK;
-}
-
-static int hicn_face_ip_params_get_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt,
- sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
-
- SRP_LOG_DBGMSG("hicn face ip params get received successfully");
- vapi_msg_hicn_api_face_ip_params_get *msg;
-
- msg = vapi_alloc_hicn_api_face_ip_params_get(g_vapi_ctx_instance);
- msg->payload.faceid = input[0].data.uint32_val;
-
-if (vapi_hicn_api_face_ip_params_get(g_vapi_ctx_instance,msg,call_hicn_api_face_ip_params_get,NULL)!=VAPI_OK){
- SRP_LOG_DBGMSG("Operation failed");
- return SR_ERR_OPERATION_FAILED;
-}
-return SR_ERR_OK;
-}
+static int hicn_disable_cb(sr_session_ctx_t *session, const char *path,
+ const sr_val_t *input, const size_t input_cnt,
+ sr_event_t event, uint32_t request_id,
+ sr_val_t **output, size_t *output_cnt,
+ void *private_data) {
+ SRP_LOG_DBGMSG("hicn disable received successfully");
+ vapi_msg_hicn_api_enable_disable *msg;
-static int hicn_route_nhops_del_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt,
- sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
+ msg = vapi_alloc_hicn_api_enable_disable(g_vapi_ctx_instance);
- SRP_LOG_DBGMSG("hicn route nhop del received successfully");
- // allocate memory msg
- vapi_msg_hicn_api_route_nhop_del *msg;
-
- msg = vapi_alloc_hicn_api_route_nhop_del(g_vapi_ctx_instance);
-
-
- if(strcmp(input[0].data.string_val,"-1")){
-
- struct sockaddr_in sa;
- // store this IP address in sa:
- inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr));
- unsigned char * tmp = (unsigned char *) &sa.sin_addr.s_addr;
- memcpy(&msg->payload.prefix.address.un.ip4[0],tmp,B32);
- msg->payload.prefix.address.af = ADDRESS_IP4;
-
-
- }else if(strcmp(input[1].data.string_val,"-1")){
-
- void *dst = malloc(sizeof(struct in6_addr));
- inet_pton(AF_INET6, input[1].data.string_val, dst);
- unsigned char * tmp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr;
- memcpy(&msg->payload.prefix.address.un.ip6[0],tmp,B128);
- msg->payload.prefix.address.af = ADDRESS_IP6;
-
- }else{
- SRP_LOG_DBGMSG("Invalid local IP address");
- return SR_ERR_OPERATION_FAILED;
- }
-
-
- msg->payload.prefix.len = input[2].data.uint8_val;
- msg->payload.faceid = input[3].data.uint32_val;
-
-
-if (vapi_hicn_api_route_nhop_del(g_vapi_ctx_instance, msg, call_hicn_api_route_nhop_del,NULL)!=VAPI_OK){
- SRP_LOG_DBGMSG("Operation failed");
- return SR_ERR_OPERATION_FAILED;
-}
-return SR_ERR_OK;
-}
-
-static int hicn_face_ip_del_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt,
- sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
+ const char *delim = "/";
+ if (input->type != SR_STRING_T) {
+ SRP_LOG_DBGMSG("Expected prefix of type string");
+ return SR_ERR_OPERATION_FAILED;
+ }
+ char *token;
+
+ /* get the first token */
+ token = strtok(input->data.string_val, delim);
+
+ /* if null the address is ipv4 else ipv6*/
+ if (strrchr(token, ':') == NULL) {
+ struct sockaddr_in sa;
+ inet_pton(AF_INET, token, &(sa.sin_addr));
+ unsigned char *tmp = (unsigned char *)&sa.sin_addr.s_addr;
+ memcpy(&msg->payload.prefix.address.un.ip4[0], tmp, B32);
+ msg->payload.prefix.address.af = ADDRESS_IP4;
+ } else {
+ void *dst = malloc(sizeof(struct in6_addr));
+ inet_pton(AF_INET6, token, dst);
+ unsigned char *tmp = (unsigned char *)((struct in6_addr *)dst)->s6_addr;
+ memcpy(&msg->payload.prefix.address.un.ip6[0], tmp, B128);
+ msg->payload.prefix.address.af = ADDRESS_IP6;
+ }
- SRP_LOG_DBGMSG("hicn face ip del received successfully");
- // allocate memory msg
- vapi_msg_hicn_api_face_ip_del *msg;
+ /* The second token is the prefix len*/
+ token = strtok(NULL, delim);
- msg = vapi_alloc_hicn_api_face_ip_del(g_vapi_ctx_instance);
- msg->payload.faceid = input[0].data.uint32_val;
+ msg->payload.prefix.len = atoi(token);
+ msg->payload.enable_disable = 0;
+ if (vapi_hicn_api_enable_disable(g_vapi_ctx_instance, msg,
+ call_hicn_api_enable_disable,
+ NULL) != VAPI_OK) {
+ SRP_LOG_DBGMSG("Operation failed");
+ return SR_ERR_OPERATION_FAILED;
+ }
-if(vapi_hicn_api_face_ip_del(g_vapi_ctx_instance,msg, call_hicn_api_face_ip_del,NULL)!=VAPI_OK){
- SRP_LOG_DBGMSG("Operation failed");
- return SR_ERR_OPERATION_FAILED;
-}
-return SR_ERR_OK;
+ return SR_ERR_OK;
}
+static vapi_error_e hicn_api_routes_dump_cb(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_routes_details *reply) {
+ static int counter = 0;
-static int hicn_face_ip_add_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt,
- sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
-
- SRP_LOG_DBGMSG("hicn face ip add received successfully");
-
-
- vapi_msg_hicn_api_face_ip_add *msg;
-
- msg = vapi_alloc_hicn_api_face_ip_add(g_vapi_ctx_instance);
- if(strcmp(input[0].data.string_val,"-1")){
- struct sockaddr_in sa;
- inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr));
- unsigned char * tmp = (unsigned char *) &sa.sin_addr.s_addr;
- memcpy(&msg->payload.face.local_addr.un.ip4[0],tmp,B32);
- msg->payload.face.local_addr.af = ADDRESS_IP4;
-
- }else if(strcmp(input[1].data.string_val,"-1")){
-
- void *dst = malloc(sizeof(struct in6_addr));
- inet_pton(AF_INET6, input[1].data.string_val, dst);
- unsigned char * tmp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr;
- memcpy(&msg->payload.face.local_addr.un.ip6[0],tmp,B128);
- msg->payload.face.local_addr.af = ADDRESS_IP6;
-
- }else{
- SRP_LOG_DBGMSG("Invalid local IP address");
- return SR_ERR_OPERATION_FAILED;
- }
-
- if(strcmp(input[2].data.string_val,"-1")){
+ tlock(lroute);
+ if (reply != NULL) {
+ rcurrent->route.route_id = counter;
+ rcurrent->route.prefix = reply->prefix;
+ rcurrent->route.nfaces = reply->nfaces;
+ rcurrent->route.strategy_id = reply->strategy_id;
+ for (int cnt = 0; cnt < rcurrent->route.nfaces; cnt++)
+ rcurrent->route.faceids[cnt] = rcurrent->route.faceids[cnt];
- struct sockaddr_in sa;
- inet_pton(AF_INET, input[2].data.string_val, &(sa.sin_addr));
- unsigned char * tmp = (unsigned char *)&sa.sin_addr.s_addr;
- memcpy(&msg->payload.face.remote_addr.un.ip4[0],tmp,B32);
- msg->payload.face.remote_addr.af = ADDRESS_IP4;
+ counter++;
+ rcurrent = rcurrent->next;
+ SRP_LOG_DBG("nfaces %d", reply->nfaces);
+ SRP_LOG_DBG("strategy_id %d", reply->strategy_id);
- }else if(strcmp(input[3].data.string_val,"-1")){
-
- void *dst = malloc(sizeof(struct in6_addr));
- inet_pton(AF_INET6, input[3].data.string_val, dst);
- unsigned char * tmp =(unsigned char *) ((struct in6_addr *)dst)->s6_addr;
- memcpy(&msg->payload.face.remote_addr.un.ip6[0],tmp,B128);
- msg->payload.face.remote_addr.af = ADDRESS_IP6;
-
- }else{
- SRP_LOG_DBGMSG("Invalid local IP address");
- return SR_ERR_OPERATION_FAILED;
- }
-
- msg->payload.face.swif = input[4].data.uint32_val; // This is the idx number of interface
-
-
-if(vapi_hicn_api_face_ip_add(g_vapi_ctx_instance,msg,call_hicn_api_face_ip_add,NULL)!=VAPI_OK){
- SRP_LOG_DBGMSG("Operation failed");
- return SR_ERR_OPERATION_FAILED;
-}
-return SR_ERR_OK;
-}
-
-static vapi_error_e
-hicn_api_routes_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_hicn_api_routes_details *reply)
-{
-
- static int counter = 0;
-
- tlock(lroute);
- if (reply!=NULL){
- rcurrent->route.route_id = counter;
- rcurrent->route.prefix = reply->prefix;
- rcurrent->route.nfaces = reply->nfaces;
- rcurrent->route.strategy_id = reply->strategy_id;
- for(int cnt=0;cnt<rcurrent->route.nfaces;cnt++)
- rcurrent->route.faceids[cnt] = rcurrent->route.faceids[cnt];
-
- counter++;
- rcurrent = rcurrent->next;
-
- SRP_LOG_DBG("nfaces %d", reply->nfaces);
- SRP_LOG_DBG("strategy_id %d", reply->strategy_id);
-
- }else
- {
- SRP_LOG_DBGMSG("---------Routes------- \n");
- hicn_routes->nroute=counter;
- counter=0;
- rcurrent=hicn_routes->next;
- }
- tunlock(lroute);
- return SR_ERR_OK;
-
-}
-
-
-static vapi_error_e
-hicn_api_face_stats_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_hicn_api_face_stats_details *reply)
-{
-
- static int counter = 0;
-
- tlock(lfaces);
- if (reply!=NULL){
-
- fcurrent->face.faceid = reply->faceid;
- fcurrent->face.intfc = 1;
- fcurrent->face.irx_packets = reply->irx_packets;
- fcurrent->face.irx_bytes = reply->irx_bytes;
- fcurrent->face.itx_packets = reply->itx_packets;
- fcurrent->face.itx_bytes = reply->itx_bytes;
- fcurrent->face.drx_packets = reply->drx_packets;
- fcurrent->face.drx_bytes = reply->drx_bytes;
- fcurrent->face.dtx_packets = reply->dtx_packets;
- fcurrent->face.dtx_bytes = reply->dtx_bytes;
- counter++;
- fcurrent = fcurrent->next;
- SRP_LOG_DBG("faceid %d", reply->faceid);
- SRP_LOG_DBG("drxB %d", reply->drx_bytes);
- SRP_LOG_DBG("dtxB %d", reply->dtx_bytes);
-
- }else
- {
- SRP_LOG_DBGMSG("---------Faces------- \n");
- hicn_faces->nface=counter;
- counter=0;
- fcurrent=hicn_faces->next;
- }
- tunlock(lfaces);
- return SR_ERR_OK;
+ } else {
+ SRP_LOG_DBGMSG("---------Routes------- \n");
+ hicn_routes->nroute = counter;
+ counter = 0;
+ rcurrent = hicn_routes->next;
+ }
+ tunlock(lroute);
+ return SR_ERR_OK;
+}
+
+static vapi_error_e hicn_api_face_stats_dump_cb(
+ struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_face_stats_details *reply) {
+ static int counter = 0;
+
+ tlock(lfaces);
+ if (reply != NULL) {
+ fcurrent->face.faceid = reply->faceid;
+ fcurrent->face.intfc = 1;
+ fcurrent->face.irx_packets = reply->irx_packets;
+ fcurrent->face.irx_bytes = reply->irx_bytes;
+ fcurrent->face.itx_packets = reply->itx_packets;
+ fcurrent->face.itx_bytes = reply->itx_bytes;
+ fcurrent->face.drx_packets = reply->drx_packets;
+ fcurrent->face.drx_bytes = reply->drx_bytes;
+ fcurrent->face.dtx_packets = reply->dtx_packets;
+ fcurrent->face.dtx_bytes = reply->dtx_bytes;
+ counter++;
+ fcurrent = fcurrent->next;
+ SRP_LOG_DBG("faceid %d", reply->faceid);
+ SRP_LOG_DBG("drxB %d", reply->drx_bytes);
+ SRP_LOG_DBG("dtxB %d", reply->dtx_bytes);
+
+ } else {
+ SRP_LOG_DBGMSG("---------Faces------- \n");
+ hicn_faces->nface = counter;
+ counter = 0;
+ fcurrent = hicn_faces->next;
+ }
+ tunlock(lfaces);
+ return SR_ERR_OK;
}
-
static void *state_thread(void *arg) {
+ // mapping can be retrieved by cpuinfo
+ int map = 0;
+ cpu_set_t cpuset;
+ CPU_ZERO(&cpuset);
+ CPU_SET(map, &cpuset);
+
+ // pin the thread to a core
+ if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)) {
+ SRP_LOG_DBGMSG("Thread pining failed\n");
+ exit(1);
+ }
- // mapping can be retrieved by cpuinfo
- int map = 0;
- cpu_set_t cpuset;
- CPU_ZERO(&cpuset);
- CPU_SET(map, &cpuset);
-
- // pin the thread to a core
- if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset))
- {
- SRP_LOG_DBGMSG("Thread pining failed\n");
- exit(1);
- }
-
- vapi_msg_hicn_api_node_stats_get *msg=NULL;
- enum locks_name state;
- state=lstate;
-
- while(true){
-
- // dump faces
- vapi_msg_hicn_api_face_stats_dump *fmsg;
- fmsg = vapi_alloc_hicn_api_face_stats_dump(g_vapi_ctx_instance);
- vapi_hicn_api_face_stats_dump(g_vapi_ctx_instance, fmsg, hicn_api_face_stats_dump_cb, fcurrent);
-
- // dump routes
- vapi_msg_hicn_api_routes_dump *rmsg;
- rmsg = vapi_alloc_hicn_api_routes_dump(g_vapi_ctx_instance);
- vapi_hicn_api_routes_dump(g_vapi_ctx_instance, rmsg, hicn_api_routes_dump_cb, rcurrent);
+ vapi_msg_hicn_api_node_stats_get *msg = NULL;
+ enum locks_name state;
+ state = lstate;
+ while (true) {
+ tlock(state);
+ // dump faces
+ vapi_msg_hicn_api_face_stats_dump *fmsg;
+ fmsg = vapi_alloc_hicn_api_face_stats_dump(g_vapi_ctx_instance);
+ vapi_hicn_api_face_stats_dump(g_vapi_ctx_instance, fmsg,
+ hicn_api_face_stats_dump_cb, fcurrent);
+ // dump routes
+ vapi_msg_hicn_api_routes_dump *rmsg;
+ rmsg = vapi_alloc_hicn_api_routes_dump(g_vapi_ctx_instance);
+ vapi_hicn_api_routes_dump(g_vapi_ctx_instance, rmsg,
+ hicn_api_routes_dump_cb, rcurrent);
- msg = vapi_alloc_hicn_api_node_stats_get(g_vapi_ctx_instance);
+ msg = vapi_alloc_hicn_api_node_stats_get(g_vapi_ctx_instance);
+ if (vapi_hicn_api_node_stats_get(g_vapi_ctx_instance, msg,
+ call_vapi_hicn_api_node_stats_get,
+ NULL) != VAPI_OK) {
+ SRP_LOG_DBGMSG(" State operation failed");
+ }
- tlock(state);
+ tunlock(state);
+ sleep(1);
- if(vapi_hicn_api_node_stats_get(g_vapi_ctx_instance,msg,call_vapi_hicn_api_node_stats_get,NULL)!=VAPI_OK){
- SRP_LOG_DBGMSG(" State operation failed");
+ SRP_LOG_DBGMSG("state cached");
}
+ return NULL;
+}
+int hicn_subscribe_events(sr_session_ctx_t *session,
+ sr_subscription_ctx_t **subscription) {
+ int rc = SR_ERR_OK;
+ SRP_LOG_DBGMSG("Subscriging hicn.");
+
+ // Initializing the locks
+ for (int i = 0; i < NLOCKS; i++) ticket_init(i, LOCK_INIT);
+
+ // Initializing the buffer
+ rc = init_buffer();
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG("Problem in initializing the buffers\n");
+ goto error;
+ }
- tunlock(state);
- sleep(1);
-
- SRP_LOG_DBGMSG("state cached");
+ SRP_LOG_DBGMSG("buffer initialized successfully.");
- }
- return NULL;
-}
+ rc = init_face_pool(fcurrent);
+ if (rc) {
+ SRP_LOG_DBGMSG("Problem in initializing the pools\n");
+ goto error;
+ }
+ rc = init_route_pool(rcurrent);
+ if (rc) {
+ SRP_LOG_DBGMSG("Problem in initializing the pools\n");
+ goto error;
+ }
-int hicn_subscribe_events(sr_session_ctx_t *session,
- sr_subscription_ctx_t **subscription) {
- int rc = SR_ERR_OK;
- SRP_LOG_DBGMSG("Subscriging hicn.");
+ SRP_LOG_DBGMSG("pools created successfully.");
- //Initializing the locks
- for (int i=0; i<NLOCKS; i++)
- ticket_init(i,LOCK_INIT);
+ // Create state thread observation
+ pthread_t state_tid;
+ rc = pthread_create((pthread_t *)&state_tid, NULL, state_thread, NULL);
+ if (rc != 0) {
+ SRP_LOG_DBGMSG("Error making hicn state thread");
+ return SR_ERR_OPERATION_FAILED;
+ }
+ SRP_LOG_DBGMSG("State thread created successfully.");
- //Initializing the buffer
- rc=init_buffer();
- if(rc!= SR_ERR_OK){
- SRP_LOG_DBGMSG("Problem in initializing the buffers\n");
- goto error;
- }
+ // strategies subscriptions
- SRP_LOG_DBGMSG("buffer initialized successfully.");
+ rc = sr_rpc_subscribe(session, "/hicn:strategies-get", hicn_strategies_get_cb,
+ session, 98, SR_SUBSCR_CTX_REUSE, subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG("Problem in subscription strategies-get\n");
+ goto error;
+ }
+ // face ip subscriptions
- rc=init_face_pool(fcurrent);
- if(rc){
- SRP_LOG_DBGMSG("Problem in initializing the pools\n");
- goto error;
- }
+ rc = sr_rpc_subscribe(session, "/hicn:face-params-get",
+ hicn_face_params_get_cb, session, 93,
+ SR_SUBSCR_CTX_REUSE, subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG("Problem in subscription face-params-get\n");
+ goto error;
+ }
+ // hICN enable-disable subscriptions
- rc=init_route_pool(rcurrent);
- if(rc){
- SRP_LOG_DBGMSG("Problem in initializing the pools\n");
- goto error;
- }
+ rc = sr_rpc_subscribe(session, "/hicn:hicn-enable", hicn_enable_cb, session,
+ 94, SR_SUBSCR_CTX_REUSE, subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG("Problem in subscription hicn-enable\n");
+ goto error;
+ }
+ rc = sr_rpc_subscribe(session, "/hicn:hicn-disable", hicn_disable_cb, session,
+ 95, SR_SUBSCR_CTX_REUSE, subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG("Problem in subscription hicn-enable\n");
+ goto error;
+ }
- SRP_LOG_DBGMSG("pools created successfully.");
+ // subscribe as hicn state data provider
+ rc = sr_oper_get_items_subscribe(session, "hicn", "/hicn:hicn-state/states",
+ hicn_state_states_cb, NULL,
+ SR_SUBSCR_CTX_REUSE, subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG("Problem in subscription /hicn:hicn-state/states\n");
+ goto error;
+ }
- // Create state thread observation
- pthread_t state_tid;
- rc = pthread_create((pthread_t *)&state_tid, NULL, state_thread, NULL);
- if (rc != 0) {
- SRP_LOG_DBGMSG("Error making hicn state thread");
- return SR_ERR_OPERATION_FAILED;
- }
- SRP_LOG_DBGMSG("State thread created successfully.");
+ rc = sr_oper_get_items_subscribe(session, "hicn", "/hicn:hicn-state/routes",
+ hicn_state_route_cb, NULL,
+ SR_SUBSCR_CTX_REUSE, subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG("Problem in subscription /hicn:hicn-state/routes\n");
+ goto error;
+ }
+ rc = sr_oper_get_items_subscribe(session, "hicn", "/hicn:hicn-state/faces",
+ hicn_state_faces_cb, NULL,
+ SR_SUBSCR_CTX_REUSE, subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBGMSG("Problem in subscription /hicn:hicn-state/faces\n");
+ goto error;
+ }
-/*
- // subscripe for edit-config
- rc = sr_module_change_subscribe(
- session, "hicn","/hicn:hicn-conf", hicn_node_params_set_cb, g_vapi_ctx_instance,
- 0, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_ENABLED, subscription);
- if (SR_ERR_OK != rc) {
- //SRP_LOG_DBGMSG("Problem in subscription /hicn:hicn-conf\n");
- perror("Problem in subscription /hicn:hicn-conf\n");
- goto error;
- }
-*/
-
- // strategies subscriptions
-
- rc = sr_rpc_subscribe(session, "/hicn:strategies-get",
- hicn_strategies_get_cb, session, 98,SR_SUBSCR_CTX_REUSE, subscription);
- if (rc!= SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription strategies-get\n");
- goto error;
- }
-
- // route nhops subscriptions
-
- rc = sr_rpc_subscribe(session, "/hicn:route-nhops-add",
- hicn_route_nhops_add_cb, session, 95,SR_SUBSCR_CTX_REUSE, subscription);
- if (rc!= SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription route-nhops-add\n");
- goto error;
- }
-
- rc = sr_rpc_subscribe(session, "/hicn:route-nhops-del",
- hicn_route_nhops_del_cb, session, 94,SR_SUBSCR_CTX_REUSE, subscription);
- if (rc!= SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription route-nhops-del\n");
- goto error;
- }
-
- rc = sr_rpc_subscribe(session, "/hicn:route-del", hicn_route_del_cb,
- session, 96,SR_SUBSCR_CTX_REUSE, subscription);
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription route-del\n");
- goto error;
- }
-
- // face ip subscriptions
-
- rc = sr_rpc_subscribe(session, "/hicn:face-ip-params-get",
- hicn_face_ip_params_get_cb, session, 93,SR_SUBSCR_CTX_REUSE, subscription);
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription face-ip-params-get\n");
- goto error;
- }
-
-
- rc = sr_rpc_subscribe(session, "/hicn:face-ip-add", hicn_face_ip_add_cb,
- session, 92,SR_SUBSCR_CTX_REUSE, subscription);
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription face-ip-add\n");
- goto error;
- }
-
- rc = sr_rpc_subscribe(session, "/hicn:face-ip-del", hicn_face_ip_del_cb,
- session, 91,SR_SUBSCR_CTX_REUSE, subscription);
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription face-ip-del\n");
- goto error;
- }
-
- // subscribe as hicn state data provider
-
- rc = sr_oper_get_items_subscribe(session, "hicn","/hicn:hicn-state/states",
- hicn_state_states_cb, NULL, SR_SUBSCR_CTX_REUSE,
- subscription);
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription /hicn:hicn-state/states\n");
- goto error;
- }
-
-
- rc = sr_oper_get_items_subscribe(session, "hicn","/hicn:hicn-state/routes",
- hicn_state_route_cb, NULL, SR_SUBSCR_CTX_REUSE,
- subscription);
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription /hicn:hicn-state/routes\n");
- goto error;
- }
-
-
- rc = sr_oper_get_items_subscribe(session, "hicn","/hicn:hicn-state/faces",
- hicn_state_faces_cb, NULL, SR_SUBSCR_CTX_REUSE,
- subscription);
- if (rc != SR_ERR_OK) {
- SRP_LOG_DBGMSG("Problem in subscription /hicn:hicn-state/faces\n");
- goto error;
- }
-
-
- SRP_LOG_DBGMSG("hicn plugin initialized successfully.\n");
- return SR_ERR_OK;
+ SRP_LOG_DBGMSG("hicn plugin initialized successfully.\n");
+ return SR_ERR_OK;
error:
- SRP_LOG_ERRMSG("Error by initialization of the hicn plugin.");
- sr_plugin_cleanup_cb(session, &g_vapi_ctx_instance);
- return rc;
+ SRP_LOG_ERRMSG("Error by initialization of the hicn plugin.");
+ sr_plugin_cleanup_cb(session, &g_vapi_ctx_instance);
+ return rc;
}
diff --git a/ctrl/sysrepo-plugins/yang/hicn/hicn.yang b/ctrl/sysrepo-plugins/yang/hicn/hicn.yang
index de09fcdb9..0514a7a2a 100644
--- a/ctrl/sysrepo-plugins/yang/hicn/hicn.yang
+++ b/ctrl/sysrepo-plugins/yang/hicn/hicn.yang
@@ -1,426 +1,247 @@
module hicn {
-namespace "urn:sysrepo:hicn";
-prefix hcn;
+ namespace "urn:sysrepo:hicn";
+ prefix hcn;
-
-revision 2019-10-30{
- description "revised revision focus on telemetry.";
-}
-
-/* new data types and grouping definition to forward the remote request toward hicn controler--to-->hicn */
-
-typedef float {
- type decimal64 {
- fraction-digits 2;
- }
-}
-
-grouping face_ip_add {
-
-leaf lip4 {
- description "IP version 4 local address.";
- type string;
- }
-
-leaf lip6 {
- description "IP version 6 local address.";
- type string;
- }
-
-leaf rip4 {
- description "IP version 4 local address.";
- type string;
- }
-
-leaf rip6 {
- description "IP version 6 local address.";
- type string;
- }
-
-leaf swif {
- description "Interface Index.";
- type uint32;
- }
-}
-
-grouping route_nhops_add {
-
-leaf ip4 {
- description "ip4 to be added to the FIB.";
- type string;
- }
-
-leaf ip6 {
- description "ip6 to be added to the FIB.";
- type string;
- }
-
-leaf len {
- description "Length of the prefix.";
- type uint8;
- }
-
-leaf face_ids0 {
- description "A Face ID to the next hop forwarder for the specified prefix.";
- type uint32;
- }
-
-leaf face_ids1 {
- description "A Face ID to the next hop forwarder for the specified prefix.";
- type uint32;
- }
-
-leaf face_ids2 {
- description "A Face ID to the next hop forwarder for the specified prefix.";
- type uint32;
- }
-
-leaf face_ids3 {
- description "A Face ID to the next hop forwarder for the specified prefix.";
- type uint32;
- }
-
-leaf face_ids4 {
- description "A Face ID to the next hop forwarder for the specified prefix.";
- type uint32;
- }
-
-leaf face_ids5 {
- description "A Face ID to the next hop forwarder for the specified prefix.";
- type uint32;
- }
-
-leaf face_ids6 {
- description "A Face ID to the next hop forwarder for the specified prefix.";
- type uint32;
- }
-
-leaf n_faces {
- description "Number of face to add.";
- type uint8;
- }
-}
-
-
-grouping route_nhops_del {
-
-leaf ip4 {
- description "ip4 to be added to the FIB.";
- type string;
- }
-
-leaf ip6 {
- description "ip6 to be added to the FIB.";
- type string;
- }
-
-leaf len {
- description "Length of the prefix.";
- type uint8;
- }
-
-leaf faceid {
- description "A Face ID to the next hop forwarder for the specified prefix.";
- type uint32;
- }
-
-}
-
-grouping route_del {
-
-leaf ip4 {
- description "ip4 to be added to the FIB.";
- type string;
- }
-
-leaf ip6 {
- description "ip6 to be added to the FIB.";
- type string;
- }
-
-leaf len {
- description "Length of the prefix.";
- type uint8;
- }
-}
-
-grouping punting_add_ip {
-
-leaf ip4 {
- description "ip4 to be added to the FIB.";
- type string;
- }
-
-leaf ip6 {
- description "ip6 to be added to the FIB.";
- type string;
- }
-
-leaf len {
- description "Length of the prefix.";
- type uint8;
+ import ietf-inet-types {
+ prefix inet;
}
-leaf swif {
- description "Interface id.";
- type uint32;
+ revision 2020-04-29{
+ description "revised revision focus on telemetry.";
}
-}
-
-grouping states-reply {
-
- leaf pkts_processed {
- description "ICN packets processed.";
- type uint64;
- }
-
- leaf pkts_interest_count {
- description "PIT maximum size, otherwise -1 to assign default value.";
- type uint64;
- }
-
- leaf pkts_data_count {
- description "CS maximum size, otherwise -1 to assign default value.";
- type uint64;
- }
-
- leaf pkts_from_cache_count {
- description "Portion of CS reserved to application, otherwise -1 to assign default value.";
- type uint64;
- }
-
- leaf pkts_no_pit_count {
- description "Default PIT entry lifetime, otherwise -1 to assign default value.";
- type uint64;
- }
- leaf pit_expired_count {
- description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value.";
- type uint64;
- }
-
- leaf cs_expired_count {
- description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
- type uint64;
- }
-
- leaf cs_lru_count {
- description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
- type uint64;
- }
+ /* new data types and grouping definition to forward the remote request toward hicn controler--to-->hicn */
- leaf pkts_drop_no_buf {
- description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
- type uint64;
- }
-
- leaf interests_aggregated {
- description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
- type uint64;
- }
-
- leaf interests_retx {
- description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
- type uint64;
+ typedef float {
+ type decimal64 {
+ fraction-digits 2;
}
+ }
- leaf interests_hash_collision {
- description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
- type uint64;
- }
+ grouping states-reply {
- leaf pit_entries_count {
- description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
- type uint64;
- }
+ leaf pkts_processed {
+ description "ICN packets processed.";
+ type uint64;
+ }
- leaf cs_entries_count {
- description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
- type uint64;
- }
+ leaf pkts_interest_count {
+ description "PIT maximum size, otherwise -1 to assign default value.";
+ type uint64;
+ }
- leaf cs_entries_ntw_count {
- description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
- type uint64;
- }
+ leaf pkts_data_count {
+ description "CS maximum size, otherwise -1 to assign default value.";
+ type uint64;
+ }
-}
+ leaf pkts_from_cache_count {
+ description "Portion of CS reserved to application, otherwise -1 to assign default value.";
+ type uint64;
+ }
-grouping face-stats-reply {
- list face{
- key faceid;
- leaf faceid {
- description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
- type uint32;
+ leaf pkts_no_pit_count {
+ description "Default PIT entry lifetime, otherwise -1 to assign default value.";
+ type uint64;
}
- leaf intfc {
- description "This is the idx number of the faceid.";
- type uint32;
+ leaf pit_expired_count {
+ description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value.";
+ type uint64;
}
- leaf irx_packets {
+ leaf cs_expired_count {
description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
type uint64;
}
- leaf irx_bytes {
+ leaf cs_lru_count {
description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
type uint64;
}
- leaf itx_packets {
+ leaf pkts_drop_no_buf {
description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
type uint64;
}
- leaf itx_bytes {
+ leaf interests_aggregated {
description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
type uint64;
}
-
- leaf drx_packets {
+ leaf interests_retx {
description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
type uint64;
}
- leaf drx_bytes {
+ leaf interests_hash_collision {
description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
type uint64;
}
- leaf dtx_packets {
+ leaf pit_entries_count {
description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
type uint64;
}
+ leaf cs_entries_count {
+ description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
+ type uint64;
+ }
- leaf dtx_bytes {
+ leaf cs_entries_ntw_count {
description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
type uint64;
}
+
}
-}
-grouping route-reply {
+ grouping face-stats-reply {
+ list face{
+ key faceid;
+ leaf faceid {
+ description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
+ type uint32;
+ }
- list route{
- key routeid;
- leaf routeid {
- description "the unique key for each item.";
- type uint32;
- }
- leaf prefix {
- description "IP address.";
- type string;
-
- }
- leaf strategy_id {
- description "compile-time plugin features.";
- type uint32;
- }
- }
-}
+ leaf intfc {
+ description "This is the idx number of the faceid.";
+ type uint32;
+ }
-grouping strategies-reply {
- leaf n_strategies {
- description "Enable / disable ICN forwarder in VPP.";
- type uint8;
- }
- leaf strategy_id {
- description "Enable / disable ICN forwarder in VPP.";
- type uint32;
- }
+ leaf irx_packets {
+ description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
+ type uint64;
+ }
-}
+ leaf irx_bytes {
+ description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
+ type uint64;
+ }
+ leaf itx_packets {
+ description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
+ type uint64;
+ }
-/* Hicn operational data */
+ leaf itx_bytes {
+ description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
+ type uint64;
+ }
-container hicn-state {
- config false;
- description "operational data container for the hicn.";
- container faces{
- uses face-stats-reply;
- }
- container states{
- uses states-reply;
- }
- container routes{
- uses route-reply;
- }
-}
+ leaf drx_packets {
+ description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
+ type uint64;
+ }
+ leaf drx_bytes {
+ description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
+ type uint64;
+ }
-/* RPC Definitions */
+ leaf dtx_packets {
+ description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
+ type uint64;
+ }
-rpc strategies-get {
- description "Operation to get hicn strategies.";
-}
-rpc route-del {
- description "Operation to del hicn route.";
- input {
- uses route_del;
+ leaf dtx_bytes {
+ description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value .";
+ type uint64;
+ }
+ }
}
-}
-rpc route-nhops-add {
- description "Operation to add hicn route nhops.";
- input {
- uses route_nhops_add;
+ grouping route-reply {
+
+ list route{
+ key routeid;
+ leaf routeid {
+ description "the unique key for each item.";
+ type uint32;
+ }
+ leaf prefix {
+ description "IP address.";
+ type string;
+
+ }
+ leaf strategy_id {
+ description "compile-time plugin features.";
+ type uint32;
+ }
}
-}
+ }
+
+ grouping strategies-reply {
+ leaf n_strategies {
+ description "Enable / disable ICN forwarder in VPP.";
+ type uint8;
+ }
+ leaf strategy_id {
+ description "Enable / disable ICN forwarder in VPP.";
+ type uint32;
+ }
-rpc route-nhops-del {
- description "Operation to add hicn face ip punt.";
- input {
- uses route_nhops_del;
}
-}
-rpc face-ip-params-get {
- description "Operation to del hicn route.";
- input {
- leaf faceid {
- description "Face to be retrieved .";
- type uint32;
+ typedef hicn-prefix {
+ description "hICN prefix.";
+ type inet:ip-prefix;
+ }
+
+
+ /* Hicn operational data */
+
+ container hicn-state {
+
+ config false;
+ description "operational data container for the hicn.";
+ container faces{
+ uses face-stats-reply;
+ }
+ container states{
+ uses states-reply;
+ }
+ container routes{
+ uses route-reply;
}
}
-}
-rpc face-ip-add {
- description "Operation to add hicn face ip.";
- input {
- uses face_ip_add;
+
+ /* RPC Definitions */
+
+ rpc strategies-get {
+ description "Operation to get hicn strategies.";
}
-}
-rpc face-ip-del {
- description "Operation to del hicn face ip.";
- input {
- leaf faceid {
- description "Face to be deleted .";
- type uint32;
+ rpc face-params-get {
+ description "Operation to del hicn route.";
+ input {
+ leaf faceid {
+ description "Face to be retrieved .";
+ type uint32;
+ }
}
}
-}
-rpc punting-add-ip {
- description "Operation to add hicn punt.";
- input {
- uses punting_add_ip;
+ rpc hicn-enable {
+ description "Enable hicn on a gie prefix.";
+ input {
+ leaf prefix {
+ type hicn-prefix;
+ }
+ }
}
-}
-rpc punting-del-ip {
- description "Operation to del hicn punt.";
- input {
- uses punting_add_ip; /* It uses the same payload as the add*/
+ rpc hicn-disable {
+ description "Disable hicn on a gie prefix.";
+ input {
+ leaf prefix {
+ type hicn-prefix;
+ }
+ }
}
-}
-
}
diff --git a/lib/doc/CMakeLists.txt b/docs/doxygen/CMakeLists.txt
index 135addc09..8da74995b 100644
--- a/lib/doc/CMakeLists.txt
+++ b/docs/doxygen/CMakeLists.txt
@@ -7,7 +7,7 @@ if(BUILD_DOCUMENTATION)
message(FATAL_ERROR "Doxygen is needed to build the documentation.")
endif()
- set(doxy_main_page ${CMAKE_CURRENT_SOURCE_DIR}/../README.md)
+ set(doxy_main_page ${CMAKE_CURRENT_SOURCE_DIR}/../../README.md)
set(doxyfile_in ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
set(doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
diff --git a/lib/doc/Doxyfile.in b/docs/doxygen/Doxyfile.in
index a28fb3a1a..6f152323d 100644
--- a/lib/doc/Doxyfile.in
+++ b/docs/doxygen/Doxyfile.in
@@ -1,4 +1,4 @@
-PROJECT_NAME = "Hybrid ICN (hICN)"
+PROJECT_NAME = "Hybrid ICN (hICN) plugin"
PROJECT_NUMBER = @VERSION@
STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@ \
@PROJECT_BINARY_DIR@
@@ -7,6 +7,6 @@ INPUT = @doxy_main_page@ \
@PROJECT_BINARY_DIR@
FILE_PATTERNS = *.md \
*.h \
- *.cc
+ *.hpp
RECURSIVE = YES
USE_MDFILE_AS_MAINPAGE = @doxy_main_page@
diff --git a/docs/source/control.md b/docs/source/control.md
index 07010a8d1..9564a23af 100644
--- a/docs/source/control.md
+++ b/docs/source/control.md
@@ -149,60 +149,17 @@ controler_rpcs_instances.xml in the yang-model. Here you can find the content:
<len>30</len>
</route-get>
-<route-del xmlns="urn:sysrepo:hicn">
- <prefix0>10</prefix0>
- <prefix1>20</prefix1>
- <len>30</len>
-</route-del>
-
-<route-nhops-add xmlns="urn:sysrepo:hicn">
- <prefix0>10</prefix0>
- <prefix1>20</prefix1>
- <len>30</len>
- <face_ids0>40</face_ids0>
- <face_ids1>50</face_ids1>
- <face_ids2>60</face_ids2>
- <face_ids3>70</face_ids3>
- <face_ids4>80</face_ids4>
- <face_ids5>90</face_ids5>
- <face_ids6>100</face_ids6>
- <n_faces>110</n_faces>
-</route-nhops-add>
-
-<route-nhops-del xmlns="urn:sysrepo:hicn">
- <prefix0>10</prefix0>
- <prefix1>20</prefix1>
- <len>30</len>
- <faceid>40</faceid>
-</route-nhops-del>
-
-<face-ip-params-get xmlns="urn:sysrepo:hicn">
+<face-params-get xmlns="urn:sysrepo:hicn">
<faceid>10</faceid>
-</face-ip-params-get>
-
-<face-ip-add xmlns="urn:sysrepo:hicn">
- <nh_addr0>10</nh_addr0>
- <nh_addr1>20</nh_addr1>
- <swif>30</swif>
-</face-ip-add>
+</face-params-get>
-<face-ip-del xmlns="urn:sysrepo:hicn">
- <faceid>0</faceid>
-</face-ip-del>
+<hicn-enable xmlns="urn:sysrepo:hicn">
+ <prefix>b001::/64</prefix>
+</hicn-enable>
-<punting-add xmlns="urn:sysrepo:hicn">
- <prefix0>10</prefix0>
- <prefix1>20</prefix1>
- <len>30</len>
- <swif>40</swif>
-</punting-add>
-
-<punting-del xmlns="urn:sysrepo:hicn">
- <prefix0>10</prefix0>
- <prefix1>20</prefix1>
- <len>30</len>
- <swif>40</swif>
-</punting-del>
+<hicn-disable xmlns="urn:sysrepo:hicn">
+ <prefix>b001::/64</prefix>
+</hicn-disable>
```
#### Run the plugin
diff --git a/docs/source/packethicn.md b/docs/source/packethicn.md
new file mode 100644
index 000000000..cf4976837
--- /dev/null
+++ b/docs/source/packethicn.md
@@ -0,0 +1,127 @@
+HICN Plugin for Wireshark
+===================
+
+The `packethicn` plugin adds support to Wireshark to parse and dissect HICN traffic.
+
+`packethicn` can be compiled and installed in two ways:
+
+1. Alongside HICN, from the HICN root dir (see [Build with HICN](#Build-with-HICN))
+
+2. As a standalone component (see [Standalone build](#Standalone-build))
+
+The second one is preferred if HICN is already installed in the system.
+
+# Supported platforms
+`packethicn` has been tested in
+
+- Ubuntu 18.04
+- Ubuntu 20.04
+- macOS 11.2
+
+Other platforms and architectures may work.
+
+# Installation
+## Build with HICN
+
+### Dependencies
+
+```bash
+$ sudo add-apt-repository ppa:wireshark-dev/stable
+
+$ sudo apt install -y build-essential cmake wireshark wireshark-dev libgcrypt-dev libgnutls28-dev
+
+```
+
+### Build and install
+
+From the root HICN dir add the `-DBUILD_WSPLUGIN` flag to cmake.
+
+```bash
+$ cd hicn
+
+$ mkdir build; cd build
+
+$ cmake -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl\@1.1 -DBUILD_APPS=ON -DBUILD_WSPLUGIN=ON ..
+
+$ make -j`nproc`
+
+$ sudo make install
+
+```
+
+## Standalone build
+### Linux (Ubuntu)
+
+#### Install dependencies
+```bash
+$ sudo add-apt-repository ppa:wireshark-dev/stable
+
+$ curl -s https://packagecloud.io/install/repositories/fdio/release/script.deb.sh | sudo bash
+
+$ sudo apt install -y build-essential cmake libhicn-dev wireshark wireshark-dev libgcrypt-dev libgnutls28-dev
+
+```
+#### Compile and install HICN plugin
+```bash
+$ cd packethicn
+
+$ mkdir build; cd build
+
+$ cmake ..
+
+$ make
+
+$ sudo make install
+```
+
+
+### macOS
+If installing wireshark via brew use the `./install_macos.sh` script as shown below:
+
+```bash
+$ brew tap icn-team/hicn-tap
+
+$ brew install hicn
+
+$ brew install wireshark
+
+$ brew install cask wireshark
+
+$ cd packethicn
+
+$ ./install_macos.sh
+```
+
+Otherwise (if wireshark was compiled from sources) you can follow the setup for Linux:
+
+```bash
+$ cd packethicn
+
+$ mkdir build; cd build
+
+$ cmake ..
+
+$ make
+
+$ sudo make install
+```
+
+# Usage
+
+## Filters
+
+| Filter | Description | Example |
+| --- | --- | --- |
+| `hicn` | HICN traffic only | *hicn* |
+| `hicn.l3.src` | Source address / Name Prefix (of data) | *hicn.l3.src == b001::a8f:ae2a:bd5b:0:0* |
+| `hicn.l3.dst` | Destination address / Name Prefix (of interest) | *hicn.l3.dst == b001::a8f:ae2a:bd5b:1111:0* |
+| `hicn.l4.namesuffix ` | Name Suffix | *hicn.l4.namesuffix == 0x21* |
+| `hicn.l4.pathlabel ` | Path Label | *hicn.l4.pathlabel == 0xbb* |
+| `hicn.l4.timescale ` | Timescale | *hicn.l4.timescale == 4* |
+| `hicn.l4.flags ` | Flags | *hicn.l4.flags == 0x42* |
+| `hicn.l4.flags.id ` | ID Flag | *hicn.l4.flags.<span></span>id == 1* |
+| `hicn.l4.flags.man ` | MAN Flag | *hicn.l4.flags.man == 0* |
+| `hicn.l4.flags.sig ` | SIG Flag | *hicn.l4.flags.sig == 0* |
+| `hicn.l4.ldr ` | Loss Detection and Recovery | *hicn.l4.ldr > 0* |
+| `hicn.l4.csum ` | Checksum | *hicn.l4.csum > 0* |
+| `hicn.l4.lifetime ` | Lifetime | *hicn.l4.lifetime == 1000* |
diff --git a/docs/source/vpp-plugin.md b/docs/source/vpp-plugin.md
index f93479da8..7f49cd8b9 100644
--- a/docs/source/vpp-plugin.md
+++ b/docs/source/vpp-plugin.md
@@ -188,40 +188,6 @@ sudo vppctl
vpp# hicn ?
```
-`hicn control param`: configures the internal parameter of the hICN plugin.
-This command must be run before hicn control start.
-
-```bash
-hicn control param { pit { size <entries> | { dfltlife | minlife | maxlife } <seconds> } | cs {size <entries> | app <portion to reserved to app>} }
- <entries> :set the maximum number of entry in the PIT or CS. Default for PIT is 131072, for CS is 4096. CS size cannot be grater than PIT size. Moreover CS size must be smaller than (# of vlib buffer - 8196).
- <seconds> :set the default, maximum or minimum lifetime of pit entries. Default value 2s (default), 0.2s (minumum), 20s (maximum)
- <portion to reserved to app> :set the portion of CS to reserve to application running locally on the forwarder. Default is 30% of the cs size.
-```
-
-`hicn control start`: starts the hICN plugin in VPP.
-
-`hicn control stop` : stops the hICN plugin in VPP. Currently not supported.
-
-`hicn face app` : manipulates producer and consumer application faces in the forwarder.
-
-```bash
-hicn face app {add intfc <sw_if> {prod prefix <hicn_prefix> cs_size <size_in_packets>} {cons}} | {del <face_id>}
- <sw_if> :software interface existing in vpp on top of which to create an application face
- <hicn_prefix> :prefix to bound to the producer application face. Only content matching the prefix will be allowed through such face.
- <size_in_packets> :content store size associated to the producer face.
- <face_id> :id of the face to remove
-```
-
-`hicn face ip`: manipulates ip application faces in the forwarder.
-
-```bash
-hicn face ip {add [local <src_address>] remote <dst_address> intfc <sw_if>} | {del id <face_id>}
- <src_address> :the IPv4 or IPv6 local IP address to bind to (not mandatory, if not specified the local address is one of the address assigned to sw_if)
- <dst_address> :the IPv4 or IPv6 address of the remote system
- <sw_if> :software interface on thop of which we create the face
- <face_id> :id of the face to remove
-```
-
`hicn face show`: list the available faces in the forwarder.
```bash
@@ -230,28 +196,6 @@ hicn face show [<face_id>| type <ip/udp>]
<ip/udp> :shows all the ip or udp faces available
```
-`hicn face udp`: manipulates udp application faces in the forwarder.
-
-```bash
-hicn face udp {add src_addr <src_address> port <src_port > dst_addr <dst_address> port <dst_port>} intfc <sw_if> | {del id <face_id>}
- <src_address> :the IPv4 or IPv6 local IP address to bind to
- <src_port> :the local UDP port
- <dst_address> :the IPv4 or IPv6 address of the remote system
- <dst_port> :the remote UDP port
- <sw_if> :software interface on thop of which we create the face
- <face_id> :id of the face to remove
-
-```
-
-`hicn fib`: manipulates hicn fib entries.
-
-```bash
-hicn fib {{add | delete } prefix <prefix> face <face_id> } | set strategy <strategy_id> prefix <prefix>
- <prefix> :prefix to add to the FIB
- <face_id> :face id to add as nexto hop in the FIB entry
- <strategy_id> :set a strategy for the corresponding prefix
-```
-
`hicn pgen client`: set an vpp forwarder as an hicn packet generator client.
```bash
@@ -291,6 +235,21 @@ hicn strategy mw set prefix <prefix> face <face_id> weight <weight>
<weight> :weight
```
+`hicn enable`: enable hICN forwarding pipeline for an ip prefix.
+
+```bash
+hicn enable <prefix>
+ <prefix> :prefix for which the hICN forwarding pipeline is enabled
+```
+
+`hicn disable`: disable hICN forwarding pipeline for an ip prefix.
+
+```bash
+hicn enable <prefix>
+ <prefix> :prefix for which the hICN forwarding pipeline is disable
+```
+
+
#### hICN plugin configuration file
A configuration can be use to setup the hicn plugin when vpp starts.
@@ -328,10 +287,8 @@ forwarders are connected through a dpdk link.
sudo vppctl
vpp# set interface ip address TenGigabitEtherneta/0/0 2001::2/64
vpp# set interface state TenGigabitEtherneta/0/0 up
-vpp# hicn control start
-vpp# hicn face ip add local 2001::2 remote 2001::3 intfc TenGigabitEtherneta/0/0
-vpp# hicn fib add prefix b002::1/64 face 0
-vpp# hicn punting add prefix b002::1/64 intfc TenGigabitEtherneta/0/0 type ip
+vpp# ip route add b002::1/64 via remote 2001::3 TenGigabitEtherneta/0/0
+vpp# hicn enable b002::1/64
```
#### Forwarder B (server)
@@ -340,8 +297,6 @@ vpp# hicn punting add prefix b002::1/64 intfc TenGigabitEtherneta/0/0 type ip
sudo vppctl
vpp# set interface ip address TenGigabitEtherneta/0/1 2001::3/64
vpp# set interface state TenGigabitEtherneta/0/1 up
-vpp# hicn control start
-vpp# hicn punting add prefix b002::1/64 intfc TenGigabitEtherneta/0/1 type ip
```
Once the two forwarder are started, run the `ping_server` application on the
@@ -380,6 +335,7 @@ sudo vppctl
vpp# set interface ip address TenGigabitEtherneta/0/0 2001::2/64
vpp# set interface state TenGigabitEtherneta/0/0 up
vpp# ip route add b001::/64 via 2001::3 TenGigabitEtherneta/0/0
+vpp# ip route add 2001::3 via TenGigabitEtherneta/0/0
vpp# hicn pgen client src 2001::2 name b001::1/64 intfc TenGigabitEtherneta/0/0
vpp# exec /<path_to>pg.conf
vpp# packet-generator enable-stream hicn-pg
@@ -419,8 +375,8 @@ vpp# hicn pgen server name b001::1/64 intfc TenGigabitEtherneta/0/1
sudo vppctl
vpp# set interface ip address TenGigabitEtherneta/0/0 2001::2/64
vpp# set interface state TenGigabitEtherneta/0/0 up
-vpp# hicn face ip add remote 2001::3 intfc TenGigabitEtherneta/0/0
-vpp# hicn fib add prefix b001::/64 face 0
+vpp# ip route add b001::/64 via 2001::3 TenGigabitEtherneta/0/0
+vpp# hicn enable b001::/64
vpp# create loopback interface
vpp# set interface state loop0 up
vpp# set interface ip address loop0 5002::1/64
@@ -442,7 +398,7 @@ vpp# create loopback interface
vpp# set interface state loop0 up
vpp# set interface ip address loop0 2002::1/64
vpp# ip neighbor loop1 2002::2 de:ad:00:00:00:00
-vpp# hicn face ip add remote 2002::2 intfc loop0
-vpp# hicn fib add prefix b001::/64 face 0
+vpp# ip route add b001::/64 via 2002::2 loop0
+vpp# hicn enable b001::/64
vpp# hicn pgen server name b001::1/64 intfc loop0
```
diff --git a/extras/libmemif/CMakeLists.txt b/extras/libmemif/CMakeLists.txt
index 70388f139..3cb3a9875 100644
--- a/extras/libmemif/CMakeLists.txt
+++ b/extras/libmemif/CMakeLists.txt
@@ -25,7 +25,7 @@ include(ExternalProject)
ExternalProject_Add(libmemif
GIT_REPOSITORY https://github.com/FDio/vpp.git
- GIT_TAG v20.01
+ GIT_TAG v21.01
GIT_SHALLOW TRUE
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libmemif
PATCH_COMMAND bash -c "cp ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists1.patch ./extras/libmemif/CMakeLists.txt && cp ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists2.patch ./extras/libmemif/src/CMakeLists.txt"
@@ -34,8 +34,7 @@ ExternalProject_Add(libmemif
LIST_SEPARATOR |
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_MODULE_PATH=${MODULE_PATH}
SOURCE_SUBDIR ./extras/libmemif
- BUILD_COMMAND make package
- INSTALL_COMMAND make DESTDIR=${DESTDIR} install
+ BUILD_COMMAND ${CMAKE_COMMAND} --build . -- package
)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
diff --git a/extras/libmemif/CMakeLists1.patch b/extras/libmemif/CMakeLists1.patch
index 91da8a7c9..adf41a417 100644
--- a/extras/libmemif/CMakeLists1.patch
+++ b/extras/libmemif/CMakeLists1.patch
@@ -50,6 +50,7 @@ endif()
include_directories(src)
set(LIBMEMIF memif)
+set(COMPONENT libmemif)
set(LIBMEMIF_SHARED ${LIBMEMIF}.shared)
set(LIBMEMIF_INCLUDE_DIRS
@@ -64,6 +65,8 @@ set(LIBMEMIF_LIBRARIES
"" FORCE
)
+include (Packaging)
+
add_subdirectory(src)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
diff --git a/extras/libmemif/CMakeLists2.patch b/extras/libmemif/CMakeLists2.patch
index 69a7e773b..38d520bd9 100644
--- a/extras/libmemif/CMakeLists2.patch
+++ b/extras/libmemif/CMakeLists2.patch
@@ -37,6 +37,6 @@ build_library(${LIBMEMIF}
SOURCES ${MEMIF_SOURCES}
INSTALL_HEADERS ${MEMIF_HEADERS}
LINK_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}
- INSTALL_ROOT_DIR memif
- COMPONENT libmemif
+ HEADER_ROOT_DIR memif
+ COMPONENT ${COMPONENT}
) \ No newline at end of file
diff --git a/extras/libmemif/cmake/Modules/Packaging.cmake b/extras/libmemif/cmake/Modules/Packaging.cmake
index 50f820589..2b0f54200 100644
--- a/extras/libmemif/cmake/Modules/Packaging.cmake
+++ b/extras/libmemif/cmake/Modules/Packaging.cmake
@@ -15,30 +15,30 @@
# Packages section
######################
-set(${LIBMEMIF}_DESCRIPTION
+set(${COMPONENT}_DESCRIPTION
"Libmemif, shared memory interface"
CACHE STRING "Description for deb/rpm package."
)
-set(${LIBMEMIF}_DEB_DEPENDENCIES
+set(${COMPONENT}_DEB_DEPENDENCIES
"" CACHE STRING "Dependencies for deb/rpm package."
)
-set(${LIBMEMIF}_RPM_DEPENDENCIES
+set(${COMPONENT}_RPM_DEPENDENCIES
"" CACHE STRING "Dependencies for deb/rpm package."
)
-set(${LIBMEMIF}-dev_DESCRIPTION
+set(${COMPONENT}-dev_DESCRIPTION
"Libmemif, shared memory interface header files"
CACHE STRING "Description for deb/rpm package."
)
-set(${LIBMEMIF}-dev_DEB_DEPENDENCIES
- "libmemif (>= stable_version)"
+set(${COMPONENT}-dev_DEB_DEPENDENCIES
+ "${COMPONENT} (>= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
-set(${LIBMEMIF}-dev_RPM_DEPENDENCIES
- "libmemif (>= stable_version)"
+set(${COMPONENT}-dev_RPM_DEPENDENCIES
+ "${COMPONENT} >= stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
diff --git a/extras/packethicn/CMakeLists.txt b/extras/packethicn/CMakeLists.txt
new file mode 100644
index 000000000..cb168ae1f
--- /dev/null
+++ b/extras/packethicn/CMakeLists.txt
@@ -0,0 +1,104 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 3.5)
+cmake_policy(SET CMP0048 NEW)
+
+project(packethicn VERSION 0.0.1 DESCRIPTION "hICN protocol plugin" LANGUAGES C)
+
+set(CMAKE_MODULE_PATH
+ ${CMAKE_MODULE_PATH}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules
+)
+
+set(PACKETHICN packethicn)
+
+if(APPLE)
+ find_package(Wireshark CONFIG REQUIRED
+ PATHS /usr/local/opt/wireshark/lib/wireshark/cmake/ /usr/local/Cellar/wireshark/*/lib/wireshark/cmake
+ )
+else()
+ find_package(Wireshark CONFIG REQUIRED)
+endif()
+
+MATH(EXPR Wireshark_PATCH_NEXT_VERSION "${Wireshark_PATCH_VERSION}+1")
+set(Wireshark_NEXT_VERSION ${Wireshark_MAJOR_VERSION}.${Wireshark_MINOR_VERSION}.${Wireshark_PATCH_NEXT_VERSION})
+
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ find_package(Libhicn REQUIRED)
+else()
+ if(DISABLE_SHARED_LIBRARIES)
+ if(WIN32)
+ set(HICN_LIBRARIES ${LIBHICN_STATIC})
+ else()
+ set(HICN_LIBRARIES ${LIBHICN_STATIC} log)
+ endif()
+ list(APPEND DEPENDENCIES
+ ${LIBHICN_STATIC}
+ )
+ else()
+ set(HICN_LIBRARIES ${LIBHICN_SHARED})
+ list(APPEND DEPENDENCIES
+ ${LIBHICN_SHARED}
+ )
+ endif()
+endif()
+
+if(NOT Wireshark_PLUGINS_ENABLED)
+ message(FATAL_ERROR "Wireshark was compiled without support for plugins")
+endif()
+
+set(CMAKE_C_VISIBILITY_PRESET hidden)
+if (CMAKE_COMPILER_IS_GNUCC)
+ set(CMAKE_C_FLAGS "-Wall -Wextra ${CMAKE_C_FLAGS}")
+endif()
+
+set(COMPILER_DEFINITIONS -DVERSION=\"${PROJECT_VERSION}\")
+
+set(SOURCE_FILES
+ packet-hicn.c
+)
+
+list(APPEND PACKETHICN_INCLUDE_DIRS
+ ${HICN_INCLUDE_DIRS}
+)
+
+list(APPEND LIBRARIES
+ ${HICN_LIBRARIES}
+ epan
+)
+
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ set(LIBHICN hicn CACHE INTERNAL "" FORCE)
+endif()
+
+include(Packaging)
+include(BuildMacros)
+
+build_library(${PACKETHICN}
+ MODULE
+ SOURCES ${SOURCE_FILES}
+ LINK_LIBRARIES ${LIBRARIES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${PACKETHICN}
+ INCLUDE_DIRS ${PACKETHICN_INCLUDE_DIRS}
+ INSTALL_FULL_PATH_DIR ${Wireshark_PLUGIN_INSTALL_DIR}/epan
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ EMPTY_PREFIX true
+)
+
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ include(Packager)
+ make_packages()
+endif() \ No newline at end of file
diff --git a/extras/packethicn/cmake/Modules/Packaging.cmake b/extras/packethicn/cmake/Modules/Packaging.cmake
new file mode 100644
index 000000000..5bea05c3c
--- /dev/null
+++ b/extras/packethicn/cmake/Modules/Packaging.cmake
@@ -0,0 +1,31 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+######################
+# Packages section
+######################
+
+set(${PACKETHICN}_DESCRIPTION
+ "packethicn is a Wireshark plugin that dissects HICN traffic"
+ CACHE STRING "Description for deb/rpm package."
+)
+
+set(${PACKETHICN}_DEB_DEPENDENCIES
+ "lib${LIBHICN} (>= stable_version), wireshark (>= ${Wireshark_VERSION}), wireshark (<< ${Wireshark_NEXT_VERSION})"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
+
+set(${PACKETHICN}_RPM_DEPENDENCIES
+ "lib${LIBHICN} >= stable_version, wireshark >= ${Wireshark_VERSION}, wireshark < ${Wireshark_NEXT_VERSION}"
+ CACHE STRING "Dependencies for deb/rpm package."
+) \ No newline at end of file
diff --git a/extras/packethicn/install_macos.sh b/extras/packethicn/install_macos.sh
new file mode 100755
index 000000000..7aa6413ef
--- /dev/null
+++ b/extras/packethicn/install_macos.sh
@@ -0,0 +1,45 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/bash
+
+mkdir -p build
+pushd build
+
+cmake .. || exit 1
+make || exit 1
+
+echo "Installing..."
+sudo make install || exit 1
+popd
+
+BUILD_DIR="build/build-root/lib"
+SO_LIB="packethicn.so"
+
+WS_LIB_PATH_LIST=$(otool -L $BUILD_DIR/$SO_LIB | grep wireshark | awk '{print $1}')
+
+while IFS= read -r PATHL; do
+ LIB=$(echo $PATHL | cut -d / -f 7)
+ install_name_tool -change $PATHL @rpath/$LIB $BUILD_DIR/$SO_LIB
+done <<< "$WS_LIB_PATH_LIST"
+
+WS_GUI_PATH_LIST=$(find /usr/local -name Wireshark.app -print 2>/dev/null)
+if [ $? == 0 ]; then
+ while IFS= read -r PATHL; do
+ EPAN_PATH=$(find ${PATHL}/Contents -name epan)
+ cp $BUILD_DIR/$SO_LIB $EPAN_PATH
+ echo "Installed $BUILD_DIR/$SO_LIB in $EPAN_PATH"
+ done <<< "$WS_GUI_PATH_LIST"
+else
+ echo "Can't find the Wireshark GUI. Please copy $BUILD_DIR/$SO_LIB into the Wireshark plugin folder"
+fi
diff --git a/extras/packethicn/packet-hicn.c b/extras/packethicn/packet-hicn.c
new file mode 100644
index 000000000..c17252bb7
--- /dev/null
+++ b/extras/packethicn/packet-hicn.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <epan/packet.h>
+#include <gmodule.h>
+
+#define WS_BUILD_DLL
+#include "ws_symbol_export.h"
+#include "config.h"
+
+#include "epan/proto.h"
+#include "epan/etypes.h"
+
+#include <hicn/hicn.h>
+
+#define PATHLABEL_PAD_LEN 3 // To remove once fixed in libhicn
+
+// These should be defined in libhicn
+#define TIMESCALE_BITS_OFFSET 4
+#define TIMESCALE_BITS_LENGTH 4
+
+#define HICN_VERSION "0.0.1"
+
+/* TCP-HICN flags */
+#define FLAGS_BITS_LEN 8
+#define FLAGS_MASK 0xFF
+#define TH_FIN 0x01
+#define TH_SYN 0x02
+#define TH_RST 0x04
+#define TH_ACK 0x10
+#define TH_CWR 0x80
+#define TH_ID 0x40
+#define TH_MAN 0x20
+#define TH_SIG 0x08
+
+#define HICN_PORT 9695
+
+WS_DLL_PUBLIC_DEF const gchar plugin_version[] = HICN_VERSION;
+WS_DLL_PUBLIC_DEF const int plugin_want_major = VERSION_MAJOR;
+WS_DLL_PUBLIC_DEF const int plugin_want_minor = VERSION_MINOR;
+
+WS_DLL_PUBLIC void plugin_register(void);
+static void proto_register_hicn(void);
+static void proto_reg_handoff_hicn(void);
+
+static int proto_hicn = -1;
+
+static int hf_hicn_ipv6_src = -1;
+static int hf_hicn_ipv6_src_data = -1;
+static int hf_hicn_ipv6_dst = -1;
+static int hf_hicn_ipv6_dst_interest = -1;
+static int hf_hicn_tcp_namesuffix = -1;
+static int hf_hicn_tcp_pathlabel = -1;
+static int hf_hicn_tcp_hdrlen_timescale = -1;
+static int hf_hicn_tcp_hdrlen = -1;
+static int hf_hicn_tcp_timescale = -1;
+static int hf_hicn_tcp_flags = -1;
+static int hf_hicn_tcp_flags_cwr = -1;
+static int hf_hicn_tcp_flags_man = -1;
+static int hf_hicn_tcp_flags_id = -1;
+static int hf_hicn_tcp_flags_ack = -1;
+static int hf_hicn_tcp_flags_sig = -1;
+static int hf_hicn_tcp_flags_rst = -1;
+static int hf_hicn_tcp_flags_syn = -1;
+static int hf_hicn_tcp_flags_fin = -1;
+static int hf_hicn_tcp_ldr = -1;
+static int hf_hicn_tcp_csum = -1;
+static int hf_hicn_tcp_lifetime = -1;
+
+static gint ett_hicn = -1;
+static gint ett_hicn_l3 = -1;
+static gint ett_hicn_l4 = -1;
+static gint ett_hicn_l4_flags = -1;
+
+
+static uint8_t *_p_hdr = NULL;
+
+bool is_interest(const hicn_header_t *header) {
+ bool is_interest = false;
+
+ hicn_packet_test_ece(header, &is_interest);
+
+ return !is_interest;
+}
+
+// TODO: HANDLE ERRORS
+
+hicn_header_t *get_header(tvbuff_t *tvb, const gint offset, const gint length){
+ tvb_ensure_bytes_exist(tvb, offset, length);
+ hicn_header_t *pkt_hdr = (hicn_header_t *) tvb_get_ptr(tvb, offset, length);
+ _p_hdr = (uint8_t *) pkt_hdr;
+ return pkt_hdr;
+}
+
+uint32_t get_offset(uint8_t *data_addr){
+ return data_addr - _p_hdr;
+}
+
+static int
+dissect_hicn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ gint i = 0;
+ guint bpos;
+
+ hicn_header_t *pkt_hdr = get_header(tvb, 0, HICN_V6_TCP_HDRLEN);
+
+ wmem_strbuf_t *flags_strbuf = wmem_strbuf_new_label(wmem_packet_scope());
+ static const gchar *flags[] = {"_FIN", "_SYN", "_RST", "SIG", "_ACK", "MAN", "ID", "_CWR"};
+ wmem_strbuf_append(flags_strbuf, "<None>");
+
+ uint32_t flags_offset = get_offset((uint8_t *) &(pkt_hdr->v6.tcp.flags));
+
+ gboolean first_flag = TRUE;
+ for(i=0; i<9; i++) {
+ bpos = 1 << i;
+ if(pkt_hdr->v6.tcp.flags & bpos) {
+ if(first_flag) {
+ wmem_strbuf_truncate(flags_strbuf, 0);
+ }
+ wmem_strbuf_append_printf(flags_strbuf, "%s%s", first_flag ? "" : ", ", flags[i]);
+ first_flag = FALSE;
+ }
+ }
+
+ // DISPLAY SECTION
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "HICN");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ proto_item *ti = proto_tree_add_item(tree, proto_hicn, tvb, 0, HICN_V6_TCP_HDRLEN, ENC_NA);
+ proto_tree *hicn_tree = proto_item_add_subtree(ti, ett_hicn);
+
+ // L3
+ proto_item *ti_l3;
+ proto_tree *hicn_l3_tree = proto_tree_add_subtree(hicn_tree, tvb, 0, IPV6_HDRLEN, ett_hicn_l3, &ti_l3, "HICN Layer 3");
+
+ if(is_interest(pkt_hdr)){
+ proto_item_append_text(ti, ", Interest Packet");
+ col_set_str(pinfo->cinfo, COL_INFO, "Interest Packet");
+ proto_tree_add_item(hicn_l3_tree, hf_hicn_ipv6_src, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.ip.saddr)), sizeof(pkt_hdr->v6.ip.saddr), ENC_BIG_ENDIAN);
+ proto_tree_add_item(hicn_l3_tree, hf_hicn_ipv6_dst_interest, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.ip.daddr)), sizeof(pkt_hdr->v6.ip.daddr), ENC_BIG_ENDIAN);
+ } else {
+ // TODO: NEW LABEL FOR NACKS
+ proto_item_append_text(ti, ", Data Packet");
+ col_set_str(pinfo->cinfo, COL_INFO, "Data Packet");
+ proto_tree_add_item(hicn_l3_tree, hf_hicn_ipv6_src_data, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.ip.saddr)), sizeof(pkt_hdr->v6.ip.saddr), ENC_BIG_ENDIAN);
+ proto_tree_add_item(hicn_l3_tree, hf_hicn_ipv6_dst, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.ip.daddr)), sizeof(pkt_hdr->v6.ip.daddr), ENC_BIG_ENDIAN);
+ }
+
+ // L4
+ proto_item *ti_l4;
+ proto_tree *hicn_l4_tree = proto_tree_add_subtree(hicn_tree, tvb, IPV6_HDRLEN, TCP_HDRLEN, ett_hicn_l4, &ti_l4, "HICN Layer 4");
+
+ proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_namesuffix, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.tcp.name_suffix)), sizeof(pkt_hdr->v6.tcp.name_suffix), ENC_BIG_ENDIAN);
+ proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_pathlabel, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.tcp.pathlabel))+PATHLABEL_PAD_LEN, sizeof(pkt_hdr->v6.tcp.pathlabel), ENC_BIG_ENDIAN);
+ proto_item *ti_l4_ts = proto_tree_add_bits_item(hicn_l4_tree, hf_hicn_tcp_timescale, tvb,
+ get_offset((uint8_t *) &(pkt_hdr->v6.tcp.data_offset_and_reserved))*8 + TIMESCALE_BITS_OFFSET, TIMESCALE_BITS_LENGTH, ENC_BIG_ENDIAN);
+ proto_item_append_text(ti_l4_ts, " (Lifetime scaling factor: %dx)", pkt_hdr->v6.tcp.timescale+1);
+ proto_item *hicn_l4_flags_tree = proto_tree_add_uint_format_value(hicn_l4_tree, hf_hicn_tcp_flags, tvb,
+ get_offset((uint8_t *) &(pkt_hdr->v6.tcp.flags)), 1, pkt_hdr->v6.tcp.flags, "0x%02x (%s)", pkt_hdr->v6.tcp.flags, wmem_strbuf_get_str(flags_strbuf)
+ );
+ proto_tree *field_tree = proto_item_add_subtree(hicn_l4_flags_tree, ett_hicn_l4_flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_cwr, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_id, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_man, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_ack, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_sig, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_rst, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_syn, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_boolean(field_tree, hf_hicn_tcp_flags_fin, tvb, flags_offset, 1, pkt_hdr->v6.tcp.flags);
+ proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_ldr, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.tcp.ldr)), sizeof(pkt_hdr->v6.tcp.ldr), ENC_BIG_ENDIAN);
+ proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_csum, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.tcp.csum)), sizeof(pkt_hdr->v6.tcp.ldr), ENC_BIG_ENDIAN);
+ proto_item *ti_l4_lt = proto_tree_add_item(hicn_l4_tree, hf_hicn_tcp_lifetime, tvb, get_offset((uint8_t *) &(pkt_hdr->v6.tcp.lifetime)), sizeof(pkt_hdr->v6.tcp.ldr), ENC_BIG_ENDIAN);
+ proto_item_append_text(ti_l4_lt, " milliseconds");
+
+ dissector_handle_t data_handle = find_dissector("data");
+ call_dissector(data_handle, tvb_new_subset_remaining(tvb, HICN_V6_TCP_HDRLEN), pinfo, tree);
+ return tvb_captured_length(tvb);
+}
+
+static void
+proto_register_hicn(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_hicn_ipv6_src, { "Source Address", "hicn.l3.src", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_hicn_ipv6_src_data, { "Name Prefix", "hicn.l3.src", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_hicn_ipv6_dst, { "Destination Address", "hicn.l3.dst", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_hicn_ipv6_dst_interest, { "Name Prefix", "hicn.l3.dst", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+ { &hf_hicn_tcp_namesuffix, { "Name Suffix", "hicn.l4.namesuffix", FT_UINT32, BASE_HEX_DEC , NULL, 0x0, NULL, HFILL }},
+ { &hf_hicn_tcp_pathlabel, { "Path Label", "hicn.l4.pathlabel", FT_UINT8, BASE_HEX_DEC , NULL, 0x0, NULL, HFILL }},
+ { &hf_hicn_tcp_hdrlen_timescale, { "Header length and Timescale", "hicn.l4.hdrlen_ts", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+ { &hf_hicn_tcp_hdrlen, { "Header length", "hicn.l4.hdrlen", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_hicn_tcp_timescale, { "Timescale", "hicn.l4.timescale", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_hicn_tcp_flags, { "Flags", "hicn.l4.flags", FT_UINT8, BASE_HEX, NULL, FLAGS_MASK, NULL, HFILL }},
+ { &hf_hicn_tcp_flags_cwr, { "_CWR", "hicn.l4.flags.cwr", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_CWR, NULL, HFILL }},
+ { &hf_hicn_tcp_flags_id, { "ID", "hicn.l4.flags.id", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset),TH_ID, NULL, HFILL }},
+ { &hf_hicn_tcp_flags_man, { "MAN", "hicn.l4.flags.man", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_MAN, NULL, HFILL }},
+ { &hf_hicn_tcp_flags_ack, { "_ACK", "hicn.l4.flags.ack", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_ACK, NULL, HFILL }},
+ { &hf_hicn_tcp_flags_sig, { "SIG", "hicn.l4.flags.sig", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_SIG, NULL, HFILL }},
+ { &hf_hicn_tcp_flags_rst, { "_RST", "hicn.l4.flags.reset", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_RST, NULL, HFILL }},
+ { &hf_hicn_tcp_flags_syn, { "_SYN", "hicn.l4.flags.syn", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_SYN, NULL, HFILL }},
+ { &hf_hicn_tcp_flags_fin, { "_FIN", "hicn.l4.flags.fin", FT_BOOLEAN, FLAGS_BITS_LEN, TFS(&tfs_set_notset), TH_FIN, NULL, HFILL }},
+ { &hf_hicn_tcp_ldr, { "Loss Detection and Recovery", "hicn.l4.ldr", FT_UINT16, BASE_HEX , NULL, 0x0, NULL, HFILL }},
+ { &hf_hicn_tcp_csum, { "Checksum", "hicn.l4.csum", FT_UINT16, BASE_HEX , NULL, 0x0, NULL, HFILL }},
+ { &hf_hicn_tcp_lifetime, { "Lifetime", "hicn.l4.lifetime", FT_UINT16, BASE_DEC , NULL, 0x0, NULL, HFILL }}
+ };
+
+ static gint *ett[] = {
+ &ett_hicn,
+ &ett_hicn_l3,
+ &ett_hicn_l4,
+ &ett_hicn_l4_flags,
+ };
+
+ proto_hicn = proto_register_protocol ("Hybrid Information-Centric Networking Protocol", "HICN", "hicn");
+ proto_register_field_array(proto_hicn, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+static void
+proto_reg_handoff_hicn(void)
+{
+ static dissector_handle_t hicn_handle;
+
+ hicn_handle = create_dissector_handle(dissect_hicn, proto_hicn);
+
+ dissector_add_uint("udp.port", HICN_PORT, hicn_handle);
+ dissector_add_uint("ethertype", ETHERTYPE_IPv6, hicn_handle);
+}
+
+void plugin_register(void)
+{
+ static proto_plugin plug_hicn;
+ plug_hicn.register_protoinfo = proto_register_hicn;
+ plug_hicn.register_handoff = proto_reg_handoff_hicn;
+ proto_register_plugin(&plug_hicn);
+}
diff --git a/hicn-light/CMakeLists.txt b/hicn-light/CMakeLists.txt
index fa8c6664e..33caa5cdc 100644
--- a/hicn-light/CMakeLists.txt
+++ b/hicn-light/CMakeLists.txt
@@ -75,7 +75,7 @@ else()
${LIBHICNCTRL_STATIC}
)
else ()
- set(HICN_LIBRARIES ${LIBHICN_SHARED})
+ set(HICN_LIBRARIES ${LIBHICN_SHARED} ${LIBHICNCTRL_SHARED})
list(APPEND DEPENDENCIES
${LIBEVENT_SHARED}
${LIBHICN_SHARED}
@@ -123,8 +123,6 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
endif()
if (BUILD_TESTS)
- include (GTestImport)
-
if(${CMAKE_VERSION} VERSION_GREATER "3.10.0")
include (GoogleTest)
else()
diff --git a/hicn-light/src/hicn/cli/color.c b/hicn-light/src/hicn/cli/color.c
index 2fff2ead6..7fb25e6b2 100644
--- a/hicn-light/src/hicn/cli/color.c
+++ b/hicn-light/src/hicn/cli/color.c
@@ -32,6 +32,7 @@ vprintfc(color_t color, const char * fmt, va_list ap)
case COLOR_UNDEFINED:
case COLOR_N:
+ default: // XXX
color_s = "";
break;
}
diff --git a/hicn-light/src/hicn/config/configuration.c b/hicn-light/src/hicn/config/configuration.c
index f5ed231b2..92f3d6359 100644
--- a/hicn-light/src/hicn/config/configuration.c
+++ b/hicn-light/src/hicn/config/configuration.c
@@ -21,8 +21,6 @@
* @endcode
*/
-#include <hicn/ctrl/commands.h>
-
#ifndef _WIN32
#include <arpa/inet.h>
#include <unistd.h>
@@ -53,13 +51,13 @@
#define DEFAULT_COST 1
#define DEFAULT_PORT 1234
-#define make_ack(msg) ((msg_header_t *)msg)->header.messageType = ACK_LIGHT
-#define make_nack(msg) ((msg_header_t *)msg)->header.messageType = NACK_LIGHT
+#define make_ack(msg) ((msg_header_t *)msg)->header.message_type = ACK_LIGHT
+#define make_nack(msg) ((msg_header_t *)msg)->header.message_type = NACK_LIGHT
#define msg_malloc_list(msg, N) \
do { \
msg = malloc(sizeof((msg)->header) + N * sizeof((msg)->payload)); \
- (msg)->header.messageType = RESPONSE_LIGHT; \
+ (msg)->header.message_type = RESPONSE_LIGHT; \
(msg)->header.length = (uint16_t)(N); \
} while(0);
@@ -208,15 +206,23 @@ configuration_on_listener_add(configuration_t * config, uint8_t * packet,
control->port) < 0) {
WARN("Unsupported address type for HICN (ingress id %u): "
"must be either IPV4 or IPV6", ingress_id);
- return false;
+ goto NACK;
}
- // NOTE: interface_name is expected NULL for hICN listener
- face_type_t face_type = get_face_type_from_listener_type((hc_connection_type_t) control->listenerType);
+ if (!face_type_is_defined(control->type)) {
+ WARN("[configuration_on_listener_add] Invalid listener type");
+ goto NACK;
+ }
+
+ // XXX validate that we use face_type everywhere, as we use the untyped
+ // uint8_t for the control protocol
+ face_type_t face_type = get_face_type_from_listener_type((hc_connection_type_t) control->type);
if (!face_type_is_defined(face_type))
goto NACK;
- listener = listener_create(face_type, &address, control->interfaceName, control->symbolic, forwarder);
+ // NOTE: interface_name is expected NULL for hICN listener
+
+ listener = listener_create(face_type, &address, control->interface_name, control->symbolic, forwarder);
if (!listener)
goto NACK;
@@ -1422,7 +1428,7 @@ configuration_receive_command(configuration_t * config, msgbuf_t * msgbuf)
case COMMAND_TYPE_ROUTE_LIST:
case COMMAND_TYPE_POLICY_LIST:
/* Free replies that have been allocated (not NACK's) */
- if (((msg_header_t *)reply)->header.messageType != NACK_LIGHT)
+ if (((msg_header_t *)reply)->header.message_type != NACK_LIGHT)
free(reply);
break;
default:
@@ -1450,4 +1456,3 @@ face_type_t get_face_type_from_listener_type(hc_connection_type_t listener_type)
}
return face_type;
}
-
diff --git a/hicn-light/src/hicn/config/configuration.h b/hicn-light/src/hicn/config/configuration.h
index 1cf772b42..91f851a59 100644
--- a/hicn-light/src/hicn/config/configuration.h
+++ b/hicn-light/src/hicn/config/configuration.h
@@ -29,6 +29,7 @@
#include "../core/msgbuf.h"
#include "../core/strategy.h"
#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/commands.h>
typedef struct configuration_s configuration_t;
diff --git a/hicn-light/src/hicn/core/CMakeLists.txt b/hicn-light/src/hicn/core/CMakeLists.txt
index 32b546400..277bcedb2 100644
--- a/hicn-light/src/hicn/core/CMakeLists.txt
+++ b/hicn-light/src/hicn/core/CMakeLists.txt
@@ -78,4 +78,4 @@ set(TO_INSTALL_HEADER_FILES
if (BUILD_TESTS)
add_subdirectory(test)
-endif() \ No newline at end of file
+endif()
diff --git a/hicn-light/src/hicn/core/fib_entry.c b/hicn-light/src/hicn/core/fib_entry.c
index 5c6e28d5b..59e5f7e7c 100644
--- a/hicn-light/src/hicn/core/fib_entry.c
+++ b/hicn-light/src/hicn/core/fib_entry.c
@@ -20,7 +20,6 @@
//#include <hicn/core/connectionState.h>
#include <hicn/core/strategy_vft.h>
#include <hicn/core/nameBitvector.h>
-#include <hicn/utils/commands.h>
#ifdef WITH_MAPME
#include <hicn/core/ticks.h>
@@ -122,7 +121,7 @@ fib_entry_filter_nexthops(fib_entry_t * entry, nexthops_t * nexthops,
unsigned nexthop, i;
uint_fast32_t flags;
- policy_t policy = fib_entry_get_policy(entry);
+ hicn_policy_t policy = fib_entry_get_policy(entry);
nexthops_enumerate(nexthops, i, nexthop, {
conn = connection_table_at(table, nexthop);
@@ -325,14 +324,14 @@ fib_entry_get_available_nexthops(fib_entry_t * entry, unsigned ingress_id, nexth
return fib_entry_filter_nexthops(entry, fib_entry_get_nexthops(entry), ingress_id, true);
}
-policy_t
+hicn_policy_t
fib_entry_get_policy(const fib_entry_t * entry)
{
return entry->policy;
}
void
-fib_entry_set_policy(fib_entry_t * entry, policy_t policy)
+fib_entry_set_policy(fib_entry_t * entry, hicn_policy_t policy)
{
entry->policy = policy;
@@ -406,7 +405,7 @@ fib_entry_get_nexthops_from_strategy(fib_entry_t * entry,
* If multipath is disabled, we don't offer much choice to the forwarding
* strategy, but still go through it for accounting purposes.
*/
- policy_t policy = fib_entry_get_policy(entry);
+ hicn_policy_t policy = fib_entry_get_policy(entry);
if ((policy.tags[POLICY_TAG_MULTIPATH].state == POLICY_STATE_PROHIBIT) ||
(policy.tags[POLICY_TAG_MULTIPATH].state != POLICY_STATE_AVOID)) {
nexthops_select_one(nexthops);
diff --git a/hicn-light/src/hicn/core/fib_entry.h b/hicn-light/src/hicn/core/fib_entry.h
index 5ec0f29de..3b249a8fe 100644
--- a/hicn-light/src/hicn/core/fib_entry.h
+++ b/hicn-light/src/hicn/core/fib_entry.h
@@ -42,7 +42,6 @@
#include "msgbuf.h"
#include "nexthops.h"
#include "prefix_stats.h"
-//#include "../utils/commands.h" // strategy type
typedef struct {
Name *name;
@@ -53,7 +52,7 @@ typedef struct {
const void * forwarder;
#ifdef WITH_POLICY
- policy_t policy;
+ hicn_policy_t policy;
#endif /* WITH_POLICY */
prefix_counters_t prefix_counters;
@@ -114,9 +113,9 @@ void fib_entry_on_data(fib_entry_t * fib_entry, const nexthops_t * nexthops,
Ticks data_reception);
#ifdef WITH_POLICY
-policy_t fib_entry_get_policy(const fib_entry_t *fib_entry);
+hicn_policy_t fib_entry_get_policy(const fib_entry_t *fib_entry);
void fib_entry_reconsider_policy(fib_entry_t *fib_entry);
-void fib_entry_set_policy(fib_entry_t *fib_entry, policy_t policy);
+void fib_entry_set_policy(fib_entry_t *fib_entry, hicn_policy_t policy);
void fib_entry_update_stats(fib_entry_t *fib_entry, uint64_t now);
#endif /* WITH_POLICY */
diff --git a/hicn-light/src/hicn/core/forwarder.c b/hicn-light/src/hicn/core/forwarder.c
index 9954ecd0a..e1a7243ca 100644
--- a/hicn-light/src/hicn/core/forwarder.c
+++ b/hicn-light/src/hicn/core/forwarder.c
@@ -941,7 +941,7 @@ forwarder_remove_route(forwarder_t * forwarder, ip_prefix_t * prefix,
bool
forwarder_add_or_update_policy(forwarder_t * forwarder, ip_prefix_t * prefix,
- policy_t * policy)
+ hicn_policy_t * policy)
{
assert(forwarder);
assert(prefix);
@@ -1188,7 +1188,7 @@ forwarder_receive(forwarder_t * forwarder, listener_t * listener,
msgbuf->connection_id = listener_create_connection(listener, pair);
msg_header_t * msg = (msg_header_t*) packet;
- msgbuf->command.type = msg->header.commandID;
+ msgbuf->command.type = msg->header.command_id;
if (msgbuf->command.type >= COMMAND_TYPE_N || msgbuf->command.type == COMMAND_TYPE_UNDEFINED) {
ERROR("Invalid command");
return -msgbuf_get_len(msgbuf);
diff --git a/hicn-light/src/hicn/core/forwarder.h b/hicn-light/src/hicn/core/forwarder.h
index f5ac375da..17d8a1994 100644
--- a/hicn-light/src/hicn/core/forwarder.h
+++ b/hicn-light/src/hicn/core/forwarder.h
@@ -162,7 +162,7 @@ bool forwarder_remove_route(forwarder_t * forwarder, ip_prefix_t * prefix,
* @brief Adds or updates a policy on the message processor
*/
bool forwarder_add_or_update_policy(forwarder_t * forwarder,
- ip_prefix_t * prefix, policy_t * policy);
+ ip_prefix_t * prefix, hicn_policy_t * policy);
/**
* @brief Removes a policy from the message processor
diff --git a/hicn-light/src/hicn/core/mapme.h b/hicn-light/src/hicn/core/mapme.h
index d1d21079f..29b59faf5 100644
--- a/hicn-light/src/hicn/core/mapme.h
+++ b/hicn-light/src/hicn/core/mapme.h
@@ -26,12 +26,12 @@
#include <stdbool.h>
#include <stdint.h>
+#include <hicn/ctrl/commands.h>
#include <hicn/hicn.h>
#include "connection.h"
#include "fib_entry.h"
#include "msgbuf.h"
-#include "../utils/commands.h"
typedef struct mapme_s mapme_t;
diff --git a/hicn-light/src/hicn/core/messageHandler.h b/hicn-light/src/hicn/core/messageHandler.h
index 1df511a5c..c6a03eee4 100644
--- a/hicn-light/src/hicn/core/messageHandler.h
+++ b/hicn-light/src/hicn/core/messageHandler.h
@@ -50,6 +50,8 @@
#define CONTROL_PORT 9695
#define HTTP_PORT 8080
+// XXX Hardcoded packet format HF_INET6_TCP
+
#define IPV6_DEFAULT_VERSION 6
#define IPV6_DEFAULT_TRAFFIC_CLASS 0
#define IPV6_DEFAULT_FLOW_LABEL 0
@@ -183,7 +185,7 @@ static inline bool messageHandler_IsInterest(const uint8_t *message) {
if (!messageHandler_IsTCP(message)) return false;
bool flag;
- hicn_packet_test_ece((hicn_header_t *)message,
+ hicn_packet_test_ece(HF_INET6_TCP, (hicn_header_t *)message,
&flag); // ECE flag is set to 0 in interest packets
if (flag == false) return true;
return false;
@@ -193,7 +195,7 @@ static inline bool messageHandler_IsData(const uint8_t *message) {
if (!messageHandler_IsTCP(message)) return false;
bool flag;
- hicn_packet_test_ece((hicn_header_t *)message,
+ hicn_packet_test_ece(HF_INET6_TCP, (hicn_header_t *)message,
&flag); // ECE flag is set to 1 in data packets
if (flag == true) return true;
return false;
@@ -354,13 +356,10 @@ static inline uint32_t messageHandler_GetPathLabel(const uint8_t *message) {
}
static inline void messageHandler_SetPathLabel(uint8_t *message,
+ uint32_t old_path_label,
uint32_t new_path_label) {
if (!messageHandler_IsTCP(message)) return;
- uint32_t old_path_label;
- int res = hicn_data_get_path_label((hicn_header_t *)message, &old_path_label);
- if (res < 0) return;
-
hicn_data_set_path_label((hicn_header_t *)message, new_path_label);
messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&old_path_label,
@@ -376,20 +375,12 @@ static inline void messageHandler_UpdatePathLabel(uint8_t *message,
uint32_t pl_new_32bit =
(uint32_t)((((pl_old_8bit << 1) | (pl_old_8bit >> 7)) ^ outFace) << 24UL);
- hicn_data_set_path_label((hicn_header_t *)message, pl_new_32bit);
-
- messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&pl_old_32bit,
- (uint16_t *)&pl_new_32bit, 2);
+ // XXX path label should be 8 bits now ?
+ messageHandler_SetPathLabel(message, pl_old_32bit, pl_new_32bit);
}
static inline void messageHandler_ResetPathLabel(uint8_t *message) {
- if (!messageHandler_IsTCP(message)) return;
-
- uint32_t pl_old_32bit = messageHandler_GetPathLabel(message);
- uint32_t pl_new_32bit = 0;
- hicn_data_set_path_label((hicn_header_t *)message, pl_new_32bit);
- messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&pl_old_32bit,
- (uint16_t *)&pl_new_32bit, 2);
+ messageHandler_SetPathLabel(message, messageHandler_GetPathLabel(message), 0);
}
static inline uint16_t messageHandler_GetInterestLifetime(
@@ -555,7 +546,7 @@ static inline uint8_t * messageHandler_CreateProbePacket(hicn_format_t format,
hicn_packet_init_header(format, (hicn_header_t *) pkt);
- hicn_packet_set_dst_port((hicn_header_t *) pkt, BFD_PORT);
+ hicn_packet_set_dst_port(format, (hicn_header_t *) pkt, BFD_PORT);
hicn_interest_set_lifetime ((hicn_header_t *) pkt, probe_lifetime);
return pkt;
@@ -573,10 +564,10 @@ static inline void messageHandler_CreateProbeReply(uint8_t * probe,
uint16_t src_prt;
uint16_t dst_prt;
- hicn_packet_get_src_port((const hicn_header_t *) probe, &src_prt);
- hicn_packet_get_dst_port((const hicn_header_t *) probe, &dst_prt);
- hicn_packet_set_src_port((hicn_header_t *) probe, dst_prt);
- hicn_packet_set_dst_port((hicn_header_t *) probe, src_prt);
+ hicn_packet_get_src_port(format, (const hicn_header_t *) probe, &src_prt);
+ hicn_packet_get_dst_port(format, (const hicn_header_t *) probe, &dst_prt);
+ hicn_packet_set_src_port(format, (hicn_header_t *) probe, dst_prt);
+ hicn_packet_set_dst_port(format, (hicn_header_t *) probe, src_prt);
hicn_data_set_name (format, (hicn_header_t *) probe, &probe_name);
hicn_data_set_locator (format, (hicn_header_t *) probe, &probe_locator);
@@ -598,8 +589,8 @@ static inline void messageHandler_SetProbeName(uint8_t * probe, hicn_format_t fo
static inline bool messageHandler_IsAProbe(const uint8_t *packet){
uint16_t src_prt;
uint16_t dst_prt;
- hicn_packet_get_src_port ((const hicn_header_t *) packet, &src_prt);
- hicn_packet_get_dst_port ((const hicn_header_t *) packet, &dst_prt);
+ hicn_packet_get_src_port (HF_INET6_TCP, (const hicn_header_t *) packet, &src_prt);
+ hicn_packet_get_dst_port (HF_INET6_TCP, (const hicn_header_t *) packet, &dst_prt);
if(dst_prt == BFD_PORT){
//interest probe
diff --git a/hicn-light/src/hicn/core/msgbuf.h b/hicn-light/src/hicn/core/msgbuf.h
index a52e6b298..f3125a2e7 100644
--- a/hicn-light/src/hicn/core/msgbuf.h
+++ b/hicn-light/src/hicn/core/msgbuf.h
@@ -24,7 +24,7 @@
#include "name.h"
#include "ticks.h"
#include "messageHandler.h"
-#include "../utils/commands.h"
+#include <hicn/ctrl/commands.h>
struct name_s;
@@ -84,8 +84,8 @@ typedef struct {
/* Path label */
#define msgbuf_get_pathlabel(M) (messageHandler_GetPathLabel((M)->packet))
-#define msgbuf_set_pathlabel(M, label) (messageHandler_SetPathLabel((M)->packet, label))
-#define msgbuf_update_pathlabel(M, outface) (messageHandler_SetPathLabel((M)->packet, outface))
+#define msgbuf_set_pathlabel(M, label) (messageHandler_SetPathLabel((M)->packet, msgbuf_get_pathlabel(M), label))
+#define msgbuf_update_pathlabel(M, outface) (messageHandler_UpdatePathLabel((M)->packet, outface))
#define msgbuf_reset_pathlabel(M) (messageHandler_ResetPathLabel((M)->packet))
/* WLDR */
diff --git a/hicn-light/src/hicn/core/nameBitvector.c b/hicn-light/src/hicn/core/nameBitvector.c
index d3dc8c0ee..999f7a928 100644
--- a/hicn-light/src/hicn/core/nameBitvector.c
+++ b/hicn-light/src/hicn/core/nameBitvector.c
@@ -21,7 +21,7 @@
#include <hicn/core/nameBitvector.h>
#include <hicn/common.h> // hash32
-#include <hicn/utils/commands.h>
+#include <hicn/ctrl/commands.h>
#define DEFAULT_PORT 1234
#define NAME_LEN 2
diff --git a/hicn-light/src/hicn/core/strategy.h b/hicn-light/src/hicn/core/strategy.h
index 67630bbab..c684750f1 100644
--- a/hicn-light/src/hicn/core/strategy.h
+++ b/hicn-light/src/hicn/core/strategy.h
@@ -24,17 +24,6 @@
#include "../strategies/low_latency.h"
#include "../strategies/random.h"
-typedef enum {
- STRATEGY_TYPE_UNDEFINED,
- STRATEGY_TYPE_LOADBALANCER,
- STRATEGY_TYPE_LOW_LATENCY,
- STRATEGY_TYPE_RANDOM,
- STRATEGY_TYPE_N
-} strategy_type_t;
-
-#define STRATEGY_TYPE_VALID(type) \
- ((type != STRATEGY_TYPE_UNDEFINED) && (type != STRATEGY_TYPE_N))
-
typedef union {
strategy_load_balancer_options_t load_balancer;
strategy_low_latency_options_t low_latency;
diff --git a/hicn-light/src/hicn/io/tcp.c b/hicn-light/src/hicn/io/tcp.c
index e4f5d196f..7c9d19729 100644
--- a/hicn-light/src/hicn/io/tcp.c
+++ b/hicn-light/src/hicn/io/tcp.c
@@ -38,7 +38,6 @@
#include "../core/msgbuf.h"
#include "../core/forwarder.h"
#include "../core/messageHandler.h"
-#include "../utils/commands.h"
// 128 KB output queue
#define OUTPUT_QUEUE_BYTES (128 * 1024)
diff --git a/hicn-light/src/hicn/strategies/low_latency.h b/hicn-light/src/hicn/strategies/low_latency.h
index ff8255eae..47e9a202b 100644
--- a/hicn-light/src/hicn/strategies/low_latency.h
+++ b/hicn-light/src/hicn/strategies/low_latency.h
@@ -20,10 +20,10 @@
#ifndef HICNLIGHT_STRATEGY_LOW_LATENCY_H
#define HICNLIGHT_STRATEGY_LOW_LATENCY_H
-#define MAX_FWD_STRATEGY_RELATED_PREFIXES 10
-
struct name_s;
+#include <hicn/strategy.h>
+
typedef struct {
} strategy_low_latency_nexthop_state_t;
diff --git a/hicn-light/src/hicn/utils/CMakeLists.txt b/hicn-light/src/hicn/utils/CMakeLists.txt
index 99592b31d..1fdfdee9f 100644
--- a/hicn-light/src/hicn/utils/CMakeLists.txt
+++ b/hicn-light/src/hicn/utils/CMakeLists.txt
@@ -13,8 +13,9 @@
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+# XXX This is installed in hicn/utils...
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/commands.h
+# ${CMAKE_CURRENT_SOURCE_DIR}/commands.h
# ${CMAKE_CURRENT_SOURCE_DIR}/interface.h
# ${CMAKE_CURRENT_SOURCE_DIR}/interfaceSet.h
${CMAKE_CURRENT_SOURCE_DIR}/punting.h
diff --git a/hicn-light/src/hicn/utils/commands.h b/hicn-light/src/hicn/utils/commands.h
deleted file mode 100644
index ede6177f4..000000000
--- a/hicn-light/src/hicn/utils/commands.h
+++ /dev/null
@@ -1,378 +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.
- */
-
-/*
- * @file commands.h
- * @brief All hicn-light commands: 14 in total.
- *
- * Header and payload in binary format.
- */
-
-#ifndef commands_h
-#define commands_h
-
-#ifndef _WIN32
-#include <netinet/in.h>
-#include <sys/socket.h>
-#endif
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#ifdef WITH_POLICY
-#include <hicn/policy.h>
-#endif /* WITH_POLICY */
-#include <hicn/util/ip_address.h>
-
-#include "../core/strategy.h" // to be moved in libhicn
-
-#define SYMBOLIC_NAME_LEN 16
-
-typedef struct in6_addr ipv6_addr_t;
-typedef uint32_t ipv4_addr_t;
-
-typedef enum {
- MESSAGE_COMMAND_SUBTYPE_UNDEFINED,
- REQUEST_LIGHT = 0xc0, // this is a command
- RESPONSE_LIGHT,
- ACK_LIGHT,
- NACK_LIGHT,
- MESSAGE_COMMAND_SUBTYPE_N
-} message_command_subtype_t;
-
-#define message_type_is_valid(message_type) \
- ((message_type != MESSAGE_TYPE_UNDEFINED) && (message_type != MESSAGE_COMMAND_SUBTYPE_N))
-
-#define message_type_from_uchar(x) \
- (((x) < REQUEST_LIGHT) || (((x) >= MESSAGE_COMMAND_SUBTYPE_N)) ? MESSAGE_COMMAND_SUBTYPE_N : (message_command_subtype_t)(x))
-
-#define foreach_command_type \
- _(listener_add, LISTENER_ADD) \
- _(listener_remove, LISTENER_REMOVE) \
- _(listener_list, LISTENER_LIST) \
- _(connection_add, CONNECTION_ADD) \
- _(connection_remove, CONNECTION_REMOVE) \
- _(connection_list, CONNECTION_LIST) \
- _(connection_set_admin_state, CONNECTION_SET_ADMIN_STATE) \
- _(connection_update, CONNECTION_UPDATE) \
- _(connection_set_priority, CONNECTION_SET_PRIORITY) \
- _(connection_set_tags, CONNECTION_SET_TAGS) \
- _(route_add, ROUTE_ADD) \
- _(route_remove, ROUTE_REMOVE) \
- _(route_list, ROUTE_LIST) \
- _(cache_set_store, CACHE_SET_STORE) \
- _(cache_set_serve, CACHE_SET_SERVE) \
- _(cache_clear, CACHE_CLEAR) \
- _(strategy_set, STRATEGY_SET) \
- _(wldr_set, WLDR_SET) \
- _(punting_add, PUNTING_ADD) \
- _(mapme_enable, MAPME_ENABLE) \
- _(mapme_set_discovery, MAPME_SET_DISCOVERY) \
- _(mapme_set_timescale, MAPME_SET_TIMESCALE) \
- _(mapme_set_retx, MAPME_SET_RETX) \
- _(mapme_send_update, MAPME_SEND_UPDATE) \
- _(policy_add, POLICY_ADD) \
- _(policy_remove, POLICY_REMOVE) \
- _(policy_list, POLICY_LIST) \
-
-typedef enum {
- COMMAND_TYPE_UNDEFINED,
-#define _(l, u) COMMAND_TYPE_ ## u,
- foreach_command_type
-#undef _
- COMMAND_TYPE_N,
-} command_type_t;
-
-#define command_type_is_valid(command_type) \
- ((command_type != COMMAND_TYPE_UNDEFINED) && (command_type != COMMAND_TYPE_N))
-
-#define command_type_from_uchar(x) \
- (((x) >= COMMAND_TYPE_N) ? COMMAND_TYPE_N : (command_type_t)(x))
-
-/* Should be at least 8 bytes */
-typedef struct {
- uint8_t messageType;
- uint8_t commandID;
- uint16_t length; /* Number of structures in the payload */
- uint32_t seqNum;
-} cmd_header_t;
-
-typedef struct {
- cmd_header_t header;
-} msg_header_t;
-
-/* Listener */
-
-typedef struct {
- char symbolic[SYMBOLIC_NAME_LEN];
- char interface_name[SYMBOLIC_NAME_LEN];
- ip_address_t address;
- uint16_t port;
- uint8_t family;
- uint8_t listener_type;
-} cmd_listener_add_t;
-
-typedef struct {
- char symbolicOrListenerid[SYMBOLIC_NAME_LEN];
-} cmd_listener_remove_t;
-
-typedef struct {
-} cmd_listener_list_t;
-
-typedef struct {
- ip_address_t address;
- char name[SYMBOLIC_NAME_LEN];
- char interface_name[SYMBOLIC_NAME_LEN];
- uint32_t id;
- uint16_t port;
- uint8_t family;
- uint8_t type;
-} cmd_listener_list_item_t;
-
-/* Connection */
-
-typedef struct {
- char symbolic[SYMBOLIC_NAME_LEN];
- //char interface_name[SYMBOLIC_NAME_LEN];
- ip_address_t remote_ip;
- ip_address_t local_ip;
- uint16_t remote_port;
- uint16_t local_port;
- uint8_t family;
- uint8_t type;
- uint8_t admin_state;
-#ifdef WITH_POLICY
- uint32_t priority;
- policy_tags_t tags;
-#endif /* WITH_POLICY */
-} cmd_connection_add_t;
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
-} cmd_connection_remove_t;
-
-typedef struct {
-} cmd_connection_list_t;
-
-typedef struct {
- char symbolic[SYMBOLIC_NAME_LEN];
- //char interface_name[SYMBOLIC_NAME_LEN];
- ip_address_t remote_ip;
- ip_address_t local_ip;
- uint16_t remote_port;
- uint16_t local_port;
- uint8_t family;
- uint8_t type;
- uint8_t admin_state;
-#ifdef WITH_POLICY
- uint32_t priority;
- policy_tags_t tags;
-#endif /* WITH_POLICY */
- uint32_t id;
- uint8_t state;
- char interface_name[SYMBOLIC_NAME_LEN];
- char name[SYMBOLIC_NAME_LEN];
-} cmd_connection_list_item_t;
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- uint8_t admin_state;
- uint8_t pad8[3];
-} cmd_connection_set_admin_state_t;
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- uint8_t admin_state;
- uint32_t priority;
- policy_tags_t tags;
-} cmd_connection_update_t;
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- uint32_t priority;
-} cmd_connection_set_priority_t;
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- policy_tags_t tags;
-} cmd_connection_set_tags_t;
-
-/* Route */
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- ip_address_t address;
- uint16_t cost;
- uint8_t family;
- uint8_t len;
-} cmd_route_add_t;
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- ip_address_t address;
- uint8_t family;
- uint8_t len;
-} cmd_route_remove_t;
-
-typedef struct {
-} cmd_route_list_t;
-
-typedef struct {
- ip_address_t address;
- uint32_t connection_id;
- uint16_t cost;
- uint8_t family;
- uint8_t len;
-} cmd_route_list_item_t;
-
-/* Cache */
-
-typedef struct {
- uint8_t activate;
-} cmd_cache_set_store_t;
-
-typedef struct {
- uint8_t activate;
-} cmd_cache_set_serve_t;
-
-typedef struct {
-} cmd_cache_clear_t;
-
-/* WLDR */
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- uint8_t activate;
-} cmd_wldr_set_t;
-
-/* Strategy */
-
-typedef struct {
- ip_address_t address;
- uint8_t strategy_type;
- uint8_t family;
- uint8_t len;
- uint8_t related_prefixes;
- union {
- struct {
- ip_address_t addresses[MAX_FWD_STRATEGY_RELATED_PREFIXES];
- uint8_t lens[MAX_FWD_STRATEGY_RELATED_PREFIXES];
- uint8_t families[MAX_FWD_STRATEGY_RELATED_PREFIXES];
- } low_latency;
- };
-} cmd_strategy_set_t;
-
-/* Punting */
-
-typedef struct {
- char symbolicOrConnid[SYMBOLIC_NAME_LEN];
- ip_address_t address;
- uint8_t family;
- uint8_t len;
-} cmd_punting_add_t;
-
-/* MAP-Me */
-
-typedef struct {
- uint8_t activate;
-} cmd_mapme_activator_t;
-
-typedef cmd_mapme_activator_t cmd_mapme_enable_t;
-typedef cmd_mapme_activator_t cmd_mapme_set_discovery_t;
-
-typedef struct {
- uint32_t timePeriod;
-} cmd_mapme_timing_t;
-
-typedef cmd_mapme_timing_t cmd_mapme_set_timescale_t;
-typedef cmd_mapme_timing_t cmd_mapme_set_retx_t;
-
-typedef struct {
- ip_address_t address;
- uint8_t family;
- uint8_t len;
-} cmd_mapme_send_update_t;
-
-/* Policy */
-
-typedef struct {
- ip_address_t address;
- uint8_t family;
- uint8_t len;
- policy_t policy;
-} cmd_policy_add_t;
-
-typedef struct {
- ip_address_t address;
- uint8_t family;
- uint8_t len;
-} cmd_policy_remove_t;
-
-typedef struct {
-} cmd_policy_list_t;
-
-typedef struct {
- ip_address_t address;
- uint8_t family;
- uint8_t len;
- policy_t policy;
-} cmd_policy_list_item_t;
-
-/* Full messages */
-
-#define _(l, u) \
-typedef struct { \
- cmd_header_t header; \
- cmd_ ## l ## _t payload; \
-} msg_ ## l ## _t;
- foreach_command_type
-#undef _
-
-typedef struct {
- cmd_header_t header;
- cmd_listener_list_item_t payload;
-} msg_listener_list_reply_t;
-
-typedef struct {
- cmd_header_t header;
- cmd_connection_list_item_t payload;
-} msg_connection_list_reply_t;
-
-typedef struct {
- cmd_header_t header;
- cmd_route_list_item_t payload;
-} msg_route_list_reply_t;
-
-typedef struct {
- cmd_header_t header;
- cmd_policy_list_item_t payload;
-} msg_policy_list_reply_t;
-
-//===== size of commands ======
-// REMINDER: when a new_command is added, the following switch has to be
-// updated.
-static inline int command_get_payload_len(command_type_t command_type) {
- switch (command_type) {
-#define _(l, u) \
- case COMMAND_TYPE_ ## u: \
- return sizeof(cmd_## l ## _t);
- foreach_command_type
-#undef _
- case COMMAND_TYPE_UNDEFINED:
- case COMMAND_TYPE_N:
- return 0;
- }
-}
-#endif
diff --git a/hicn-light/src/hicn/utils/utils.h b/hicn-light/src/hicn/utils/utils.h
index 368a93f5a..ee94250bb 100644
--- a/hicn-light/src/hicn/utils/utils.h
+++ b/hicn-light/src/hicn/utils/utils.h
@@ -17,7 +17,8 @@
#define utils_h
//#include <hicn/config/controlState.h>
-#include <hicn/utils/commands.h>
+//#include <hicn/utils/commands.h>
+#include <hicn/util/ip_address.h>
/**
* Return true if string is purely an integer
@@ -30,6 +31,8 @@ bool utils_IsNumber(const char *string);
*/
bool utils_ValidateSymbolicName(const char *symbolic);
+// XXX cf IS_VALID_xxx in libhicntrl
+
/**
*Convert IPv4/IPv6 address from binary to text string. `uint8_t *ipAddress` has
*to be a `in_addr_t * or `a struct in6_addr *.
diff --git a/hicn-plugin/.clang-format b/hicn-plugin/.clang-format
new file mode 100644
index 000000000..8b5c955ce
--- /dev/null
+++ b/hicn-plugin/.clang-format
@@ -0,0 +1,21 @@
+# Minimal clang-format version is 8
+
+BasedOnStyle: GNU
+UseTab: Always
+SpaceAfterCStyleCast: true
+SortIncludes: false
+AlignConsecutiveMacros: true
+BreakBeforeTernaryOperators: false
+BreakBeforeBinaryOperators: None
+ContinuationIndentWidth: 2
+
+ForEachMacros:
+ - 'clib_bitmap_foreach'
+ - 'pool_foreach'
+ - 'pool_foreach_index'
+ - 'vec_foreach'
+ - 'vec_foreach_backwards'
+ - 'vec_foreach_index'
+ - 'vec_foreach_index_backwards'
+ - 'vlib_foreach_rx_tx'
+
diff --git a/hicn-plugin/cmake/Modules/Packaging.cmake b/hicn-plugin/cmake/Modules/Packaging.cmake
index 61453d6fd..c0176e78f 100644
--- a/hicn-plugin/cmake/Modules/Packaging.cmake
+++ b/hicn-plugin/cmake/Modules/Packaging.cmake
@@ -25,11 +25,21 @@ set(${HICN_PLUGIN}_DEB_DEPENDENCIES
CACHE STRING "Dependencies for deb/rpm package."
)
+set(${HICN_PLUGIN}-dev_DEB_DEPENDENCIES
+ "vpp-dev (>= stable_version-release), vpp-dev (<< next_version-release), libvppinfra-dev (>= stable_version-release), libvppinfra-dev (<< next_version-release)"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
+
set(${HICN_PLUGIN}_RPM_DEPENDENCIES
"vpp >= stable_version-release, vpp < next_version-release, vpp-plugins >= stable_version-release, vpp-plugins < next_version-release"
CACHE STRING "Dependencies for deb/rpm package."
)
+set(${HICN_PLUGIN}-dev_RPM_DEPENDENCIES
+ "vpp-devel >= stable_version-release, vpp-devel < next_version-release"
+ CACHE STRING "Dependencies for deb/rpm package."
+)
+
set(${HICN_PLUGIN}_DEB_PACKAGE_CONTROL_EXTRA
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/postinst"
CACHE STRING "Control scripts conffiles, postinst, postrm, prerm."
diff --git a/hicn-plugin/src/CMakeLists.txt b/hicn-plugin/src/CMakeLists.txt
index 6852b95bb..d81ed22b7 100644
--- a/hicn-plugin/src/CMakeLists.txt
+++ b/hicn-plugin/src/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# 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:
@@ -75,20 +75,11 @@ set(HICN_PLUGIN_SOURCE_FILES
${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/ip/face_ip.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/ip/face_ip_cli.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/ip/face_ip_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/ip/iface_ip_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/ip/dpo_ip.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/udp/face_udp.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/udp/face_udp_cli.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/udp/face_udp_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/udp/iface_udp_node.c
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/udp/dpo_udp.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
@@ -104,6 +95,8 @@ set(HICN_PLUGIN_SOURCE_FILES
${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
@@ -130,14 +123,10 @@ set(HICN_PLUGIN_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/error.h
${CMAKE_CURRENT_SOURCE_DIR}/face_db.h
${CMAKE_CURRENT_SOURCE_DIR}/faces/face.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/ip/face_ip.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/ip/face_ip_node.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/ip/iface_ip_node.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/ip/dpo_ip.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/udp/face_udp.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/udp/face_udp_node.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/udp/iface_udp_node.h
- ${CMAKE_CURRENT_SOURCE_DIR}/faces/udp/dpo_udp.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_node.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/iface_node.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/inlines.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
@@ -152,6 +141,7 @@ set(HICN_PLUGIN_HEADER_FILES
${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
@@ -165,7 +155,10 @@ set(HICN_API_HEADER_FILES
${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.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
@@ -184,48 +177,50 @@ 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)
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vpp_plugins)
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_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/2001/src/vpp-api/vapi/vapi_json_parser.py -o ${CMAKE_CURRENT_BINARY_DIR}/vapi_json_parser.py;
+ 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;
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;
+ 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;
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;
+ 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;
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;
+ 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;
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;
+ 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;
+ 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;
+ 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;
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}/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/
+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/
)
-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
+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
)
include_directories(SYSTEM)
@@ -257,12 +252,19 @@ set_target_properties(hicn_plugin
PROPERTIES
LINKER_LANGUAGE C
INSTALL_RPATH ${VPP_INSTALL_PLUGIN}
+ COMPILE_FLAGS "-march=native -Wno-address-of-packed-member"
PREFIX "")
set_target_properties(hicn_api_test_plugin
PROPERTIES
LINKER_LANGUAGE C
+ COMPILE_FLAGS "-march=native -Wno-address-of-packed-member"
PREFIX "")
+if (${CMAKE_BUILD_TYPE} MATCHES "Debug")
+ target_compile_definitions(hicn_plugin PRIVATE "CLIB_DEBUG")
+ target_compile_definitions(hicn_api_test_plugin PRIVATE "CLIB_DEBUG")
+endif()
+
message (STATUS "hicn-plugin variable ${HICN_PLUGIN}")
install(DIRECTORY
diff --git a/hicn-plugin/src/cache_policies/cs_lru.h b/hicn-plugin/src/cache_policies/cs_lru.h
index 0a58912d6..3bd18060d 100644
--- a/hicn-plugin/src/cache_policies/cs_lru.h
+++ b/hicn-plugin/src/cache_policies/cs_lru.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,6 +20,13 @@
#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;
/*
diff --git a/hicn-plugin/src/cache_policies/cs_policy.h b/hicn-plugin/src/cache_policies/cs_policy.h
index c1a9a44c9..0bf745915 100644
--- a/hicn-plugin/src/cache_policies/cs_policy.h
+++ b/hicn-plugin/src/cache_policies/cs_policy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,6 +18,13 @@
#include "../hashtb.h"
+/**
+ * @file cs_policy.h
+ *
+ * This file provides the needed structures to implement a CS policy
+ */
+
+
/*
* Structure
*/
@@ -41,7 +48,12 @@ struct hicn_cs_policy_s;
/**
* @brief Definition of the virtual functin table for a cache policy.
*
- * A cache policy must implement three functions: insert, update, delete, trim.
+ * 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
{
diff --git a/hicn-plugin/src/cli.c b/hicn-plugin/src/cli.c
index 15ea90c96..81a97c604 100644
--- a/hicn-plugin/src/cli.c
+++ b/hicn-plugin/src/cli.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -19,7 +19,7 @@
#include <vlibmemory/api.h>
#include <vnet/udp/udp.h> // port registration
-#include <vnet/ip/ip6_packet.h> // ip46_address_t
+#include <vnet/ip/ip6_packet.h> // ip46_address_t
#include <vnet/ip/format.h>
#include <vnet/fib/fib_types.h>
@@ -39,7 +39,6 @@ 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,
- .cs_reserved_app = -1,
};
typedef enum
@@ -52,34 +51,31 @@ typedef enum
* 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)
+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,
- node_ctl_params.cs_reserved_app);
+ 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));
+ 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)
+hicn_cli_node_ctl_stop_set_command_fn (vlib_main_t *vm,
+ unformat_input_t *main_input,
+ vlib_cli_command_t *cmd)
{
int ret;
@@ -102,53 +98,47 @@ hicn_cli_node_ctl_stop_set_command_fn (vlib_main_t * vm,
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,
- node_ctl_params.cs_reserved_app);
+ 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));
+ 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); \
-})
+#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)
+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;
- int cs_reserved_app;
if (hicn_main.is_enabled)
{
- return (clib_error_return
- (0, "params cannot be altered once hicn started"));
+ 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));
+ return clib_error_return (
+ 0, get_error_string (HICN_ERROR_FWD_ALREADY_ENABLED));
}
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
@@ -166,9 +156,9 @@ hicn_cli_node_ctl_param_set_command_fn (vlib_main_t * vm,
}
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))
+ 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;
@@ -193,15 +183,6 @@ hicn_cli_node_ctl_param_set_command_fn (vlib_main_t * vm,
}
node_ctl_params.cs_max_size = table_size;
}
- else if (unformat (line_input, "app %d", &cs_reserved_app))
- {
- if (!DFLTD_RANGE_OK (cs_reserved_app, 0, 100))
- {
- rv = HICN_ERROR_CS_CONFIG_SIZE_OOB;
- break;
- }
- node_ctl_params.cs_reserved_app = cs_reserved_app;
- }
else
{
rv = HICN_ERROR_CLI_INVAL;
@@ -216,25 +197,24 @@ hicn_cli_node_ctl_param_set_command_fn (vlib_main_t * vm,
}
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);
+ 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)
+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;
+ 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;
@@ -278,8 +258,7 @@ hicn_cli_show_command_fn (vlib_main_t * vm, unformat_input_t * main_input,
{
if (node_ctl_params.pit_max_size == -1 &&
node_ctl_params.pit_max_lifetime_sec == -1 &&
- node_ctl_params.cs_max_size == -1 &&
- node_ctl_params.cs_reserved_app == -1)
+ node_ctl_params.cs_max_size == -1)
{
ret = HICN_ERROR_FWD_NOT_ENABLED;
goto done;
@@ -302,11 +281,6 @@ hicn_cli_show_command_fn (vlib_main_t * vm, unformat_input_t * main_input,
vlib_cli_output (vm, " CS:: max entries:%d\n",
node_ctl_params.cs_max_size);
}
- if (node_ctl_params.cs_reserved_app != -1)
- {
- vlib_cli_output (vm, " CS:: reserved to app:%d\n",
- node_ctl_params.cs_reserved_app);
- }
goto done;
}
/* Globals */
@@ -314,40 +288,35 @@ hicn_cli_show_command_fn (vlib_main_t * vm, unformat_input_t * main_input,
"Forwarder: %sabled\n"
" PIT:: max entries:%d,"
" lifetime default: max:%05.3f\n"
- " CS:: max entries:%d, network entries:%d, app entries:%d (allocated %d, free %d)\n",
- hicn_main.is_enabled ? "en" : "dis",
- hicn_infra_pit_size,
+ " 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,
- hicn_infra_cs_size - hicn_main.pitcs.pcs_app_max,
- hicn_main.pitcs.pcs_app_max,
- hicn_main.pitcs.pcs_app_count,
- hicn_main.pitcs.pcs_app_max -
- hicn_main.pitcs.pcs_app_count);
+ 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));
+ 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)
{
@@ -355,7 +324,6 @@ hicn_cli_show_command_fn (vlib_main_t * vm, unformat_input_t * main_input,
strbuf = format_hicn_face_all (strbuf, 1, 0);
vlib_cli_output (vm, "%s", strbuf);
-
}
if (strategies_p || all_p)
{
@@ -369,7 +337,8 @@ done:
{
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",
+ "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,
@@ -377,28 +346,27 @@ done:
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));
+ 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_fib_set_command_fn (vlib_main_t * vm, unformat_input_t * main_input,
- vlib_cli_command_t * cmd)
+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;
- hicn_face_id_t faceid = HICN_FACE_NULL;
u32 strategy_id;
- u8 plen = 0;
+ u32 plen = 0;
fib_prefix_t prefix;
/* Get a line of input. */
@@ -409,25 +377,15 @@ hicn_cli_fib_set_command_fn (vlib_main_t * vm, unformat_input_t * main_input,
}
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
- if (addpfx == -1 && unformat (line_input, "add"))
- {
- addpfx = 1;
- }
- else if (addpfx == -1 && unformat (line_input, "delete"))
- {
- addpfx = 0;
- }
- else if (unformat (line_input, "set strategy %d", &strategy_id))
+ 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 if (addpfx <= 1 && unformat (line_input, "face %u", &faceid))
- {;
+ else if (addpfx != -1 &&
+ unformat (line_input, "prefix %U/%d", unformat_ip46_address,
+ &address, IP46_TYPE_ANY, &plen))
+ {
+ ;
}
else
{
@@ -441,63 +399,17 @@ hicn_cli_fib_set_command_fn (vlib_main_t * vm, unformat_input_t * main_input,
fib_prefix_from_ip46_addr (&address, &prefix);
prefix.fp_len = plen;
/* Check parse */
- if (addpfx <= 1
- && ((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;
- }
- /* Check parse */
- if ((ip46_address_is_zero (&prefix.fp_addr))
- || (addpfx == 2 && hicn_dpo_strategy_id_is_valid (strategy_id)))
+ if (hicn_dpo_strategy_id_is_valid (strategy_id) ==
+ HICN_ERROR_DPO_MGR_ID_NOT_VALID)
{
- cl_err = clib_error_return (0,
- "Please specify prefix and strategy_id...");
+ cl_err = clib_error_return (0, "Please specify a valid strategy...");
goto done;
}
- if (addpfx == 0)
- {
- if (ip46_address_is_zero (&prefix.fp_addr))
- {
- cl_err = clib_error_return (0, "Please specify prefix");
- goto done;
- }
- if (faceid == HICN_FACE_NULL)
- {
- rv = hicn_route_del (&prefix);
- }
- else
- {
- rv = hicn_route_del_nhop (&prefix, faceid);
- }
- cl_err =
- (rv == HICN_ERROR_NONE) ? NULL : clib_error_return (0,
- get_error_string
- (rv));
- }
- else if (addpfx == 1)
- {
- rv = hicn_route_add (&faceid, 1, &prefix);
- if (rv == HICN_ERROR_ROUTE_ALREADY_EXISTS)
- {
- rv = hicn_route_add_nhops (&faceid, 1, &prefix);
- }
- cl_err =
- (rv == HICN_ERROR_NONE) ? NULL : clib_error_return (0,
- get_error_string
- (rv));
- }
- else if (addpfx == 2)
- {
- rv = hicn_route_set_strategy (&prefix, strategy_id);
- cl_err =
- (rv == HICN_ERROR_NONE) ? NULL : clib_error_return (0,
- get_error_string
- (rv));
- }
+ 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);
@@ -507,9 +419,9 @@ done:
* 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)
+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;
@@ -528,14 +440,13 @@ hicn_cli_pgen_client_set_command_fn (vlib_main_t * vm,
{
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
- if (unformat
- (line_input, "intfc %U", unformat_vnet_sw_interface, vnm,
- &sw_if_index))
+ 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, "src %U", unformat_ip46_address,
+ &src_addr))
{
;
}
@@ -543,9 +454,8 @@ hicn_cli_pgen_client_set_command_fn (vlib_main_t * vm,
{
;
}
- 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, "name %U/%d", unformat_ip46_address,
+ &prefix->fp_addr, IP46_TYPE_ANY, &prefix->fp_len))
{
;
}
@@ -563,9 +473,8 @@ hicn_cli_pgen_client_set_command_fn (vlib_main_t * vm,
}
else
{
- return (clib_error_return
- (0, "Unknown input '%U'", format_unformat_error,
- line_input));
+ return (clib_error_return (0, "Unknown input '%U'",
+ format_unformat_error, line_input));
break;
}
}
@@ -577,7 +486,7 @@ hicn_cli_pgen_client_set_command_fn (vlib_main_t * vm,
return (clib_error_return (0, "Packet generator interface missing"));
}
- //Remove bits that are out of the subnet
+ // Remove bits that are out of the subnet
if (ip46_address_is_ip4 (&prefix->fp_addr))
{
ip4_address_t mask;
@@ -599,34 +508,32 @@ hicn_cli_pgen_client_set_command_fn (vlib_main_t * vm,
/*
* 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.
+ * 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))
+ 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);
+ 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);
-
+ 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))
+ 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);
+ 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,
@@ -638,12 +545,11 @@ hicn_cli_pgen_client_set_command_fn (vlib_main_t * vm,
}
else
{
- return (clib_error_return
- (0,
- "pg interface source address, source address and hicn name must be of the same type IPv4 or IPv6"));
+ 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;
@@ -673,9 +579,9 @@ hicn_cli_pgen_client_set_command_fn (vlib_main_t * vm,
* 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)
+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;
@@ -692,46 +598,43 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t * vm,
/* 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))
- {;
+ 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..."));
+ 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 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));
+ 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)
+ 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");
+ return clib_error_return (0, "Error: must supply local port, payload "
+ "size and incoming hICN prefix");
}
- //Remove bits that are out of the subnet
+ // Remove bits that are out of the subnet
if (ip46_address_is_ip4 (&prefix->fp_addr))
{
ip4_address_t mask;
@@ -751,7 +654,13 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t * vm,
}
/* Allocate the buffer with the actual content payload TLV */
- vlib_buffer_alloc (vm, &pg_main->pgen_svr_buffer_idx, 1);
+ 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);
@@ -761,10 +670,10 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t * vm,
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);
+ 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)
{
@@ -783,77 +692,174 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t * vm,
return cl_err;
}
-/* cli declaration for 'control start' */
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND(hicn_cli_node_ctl_start_set_command, static)=
+static clib_error_t *
+hicn_enable_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
+ vlib_cli_command_t *cmd)
{
- .path = "hicn control start",
- .short_help = "hicn control start",
- .function = hicn_cli_node_ctl_start_set_command_fn,
-};
+ clib_error_t *cl_err = 0;
+ int rv = HICN_ERROR_NONE;
+ fib_prefix_t pfx;
-/* cli declaration for 'control stop' */
-VLIB_CLI_COMMAND(hicn_cli_node_ctl_stop_set_command, static)=
+ /* 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)
{
- .path = "hicn control stop",
- .short_help = "hicn control stop",
- .function = hicn_cli_node_ctl_stop_set_command_fn,
+ 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' */
+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 <entries> | { dfltlife | minlife | maxlife } <seconds> } | fib size <entries> | cs {size <entries> | app <portion to reserved to app>} }\n",
- .function = hicn_cli_node_ctl_param_set_command_fn,
+VLIB_CLI_COMMAND (hicn_cli_node_ctl_param_set_command, static) = {
+ .path = "hicn control param",
+ .short_help = "hicn control param { pit { size <entries> | { dfltlife | "
+ "minlife | maxlife } <seconds> } | fib size <entries> | cs "
+ "{size <entries> | app <portion to reserved to 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"
-};
+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_fib_set_command, static)=
-{
- .path = "hicn fib",
- .short_help = "hicn fib {{add | delete } prefix <prefix> face <facei_d> }"
- " | set strategy <strategy_id> prefix <prefix>",
- .function = hicn_cli_fib_set_command_fn,
+VLIB_CLI_COMMAND (hicn_cli_strategy_set_command, static) = {
+ .path = "hicn strategy",
+ .short_help = "hicn strategy set <strategy_id> prefix <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,
+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 <src_addr> name <prefix> { n_ifaces <n_ifaces> lifetime <interest-lifetime> intfc <data in-interface> max_seq <max sequence number> n_flows <number of flows>}",
- .long_help = "Run hicn in packet-gen client mode\n",
- .function = hicn_cli_pgen_client_set_command_fn,
+VLIB_CLI_COMMAND (hicn_cli_pgen_client_set_command, static) = {
+ .path = "hicn pgen client",
+ .short_help =
+ "hicn pgen client src <src_addr> name <prefix> { n_ifaces <n_ifaces> "
+ "lifetime <interest-lifetime> intfc <data in-interface> max_seq <max "
+ "sequence number> n_flows <number of 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 <prefix> intfc <interest in-interface> size <payload_size>",
- .long_help = "Run hicn in packet-gen server mode\n",
- .function = hicn_cli_pgen_server_set_command_fn,
+VLIB_CLI_COMMAND (hicn_cli_pgen_server_set_command, static) = {
+ .path = "hicn pgen server",
+ .short_help = "hicn pgen server name <prefix> intfc <interest in-interface> "
+ "size <payload_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 <prefix>",
+ .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 <prefix>",
+ .long_help = "Disable hicn for the give prefix\n",
+ .function = hicn_disable_command_fn,
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/data_fwd.h b/hicn-plugin/src/data_fwd.h
index 55434a024..d95f564c3 100644
--- a/hicn-plugin/src/data_fwd.h
+++ b/hicn-plugin/src/data_fwd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,6 +20,27 @@
#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
{
@@ -33,13 +54,14 @@ typedef enum
{
HICN_DATA_FWD_NEXT_V4_LOOKUP,
HICN_DATA_FWD_NEXT_V6_LOOKUP,
- HICN_DATA_FWD_NEXT_PUSH,
+ 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
+ * @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.
diff --git a/hicn-plugin/src/data_fwd_node.c b/hicn-plugin/src/data_fwd_node.c
index 1bb064fcf..a91439662 100644
--- a/hicn-plugin/src/data_fwd_node.c
+++ b/hicn-plugin/src/data_fwd_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -32,34 +32,26 @@ static char *hicn_data_fwd_error_strings[] = {
};
/* Declarations */
-always_inline void
-drop_packet (vlib_main_t * vm, u32 bi0,
- u32 * n_left_to_next, u32 * next0, u32 ** to_next,
- u32 * next_index, vlib_node_runtime_t * node);
-
-always_inline void
-push_in_cache (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 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);
+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);
-
+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);
+always_inline u8 *hicn_data_fwd_format_trace (u8 *s, va_list *args);
vlib_node_registration_t hicn_data_fwd_node;
@@ -68,8 +60,8 @@ vlib_node_registration_t hicn_data_fwd_node;
* - 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)
+hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
{
u32 n_left_from, *from, *to_next;
@@ -139,20 +131,22 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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)))
+ 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);
+ dpo_id_t hicn_dpo_id0 = { .dpoi_type =
+ dpo_vft0->hicn_dpo_get_type (),
+ .dpoi_proto = 0,
+ .dpoi_next_node = 0,
+ .dpoi_index = dpo_ctx_id0 };
+ hicn_pcs_remove_lock (pitcs, &pitp, &node0, vm, hash_entry0,
+ dpo_vft0, &hicn_dpo_id0);
drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next,
&next_index, node);
@@ -168,29 +162,19 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
* not changed from the lookup.
*/
- if (tnow > pitp->shared.expire_time
- || (hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED))
+ 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);
+ dpo_id_t hicn_dpo_id0 = { .dpoi_type =
+ dpo_vft0->hicn_dpo_get_type (),
+ .dpoi_proto = 0,
+ .dpoi_next_node = 0,
+ .dpoi_index = dpo_ctx_id0 };
+ hicn_pcs_delete (pitcs, &pitp, &node0, vm, hash_entry0, dpo_vft0,
+ &hicn_dpo_id0);
-#if HICN_FEATURE_CS
- if (hicnb0->flags & HICN_BUFFER_FLAGS_FACE_IS_APP)
- {
- push_in_cache (vm, bi0, &n_left_to_next, &next0, &to_next,
- &next_index, node);
- }
- else
- {
- drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next,
- &next_index, node);
- }
-#else
- drop_packet (vm, bi0, &n_left_to_next, &next0, &to_next,
- &next_index, node);
-#endif
+ 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) &&
@@ -201,15 +185,14 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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),
+ 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);
+ ASSERT ((hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED) ==
+ 0);
data_received++;
/*
@@ -218,18 +201,20 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
*/
/* Prepare the buffer for the cloning */
- ret = hicn_satisfy_faces (vm, bi0, pitp, &n_left_to_next,
- &to_next, &next_index, node,
- isv6, &stats);
+ 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
- };
+ dpo_id_t hicn_dpo_id0 = { .dpoi_type =
+ dpo_vft0->hicn_dpo_get_type (),
+ .dpoi_proto = 0,
+ .dpoi_next_node = 0,
+ .dpoi_index = dpo_ctx_id0 };
if (PREDICT_FALSE (ret != HICN_ERROR_NONE))
{
- hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm,
- hash_entry0, dpo_vft0, &hicn_dpo_id0);
+ hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, hash_entry0,
+ dpo_vft0, &hicn_dpo_id0);
continue;
}
/*
@@ -252,18 +237,18 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
* 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);
+ 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);
+ 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 the packet is copied and not cloned, we need to free
+ * the vlib_buffer
*/
if (hicnb0->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL)
{
@@ -273,20 +258,21 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
{
/*
* 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.
+ * 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);
+ 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 the packet is copied and not cloned, we need to free the
+ * vlib_buffer
*/
if (hicnb0->flags & HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL)
{
@@ -303,8 +289,8 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
}
/* Delete the PIT entry */
- hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm,
- hash_entry0, dpo_vft0, &hicn_dpo_id0);
+ hicn_pcs_pit_delete (pitcs, &pitp, &node0, vm, hash_entry0,
+ dpo_vft0, &hicn_dpo_id0);
#endif
}
end_processing:
@@ -321,11 +307,10 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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_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);
@@ -334,9 +319,8 @@ hicn_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
}
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)
+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;
@@ -344,38 +328,22 @@ drop_packet (vlib_main_t * vm, u32 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 void
-push_in_cache (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_PUSH;
-
- (*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);
+ 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)
+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;
+ u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP,
+ next1 = HICN_DATA_FWD_NEXT_ERROR_DROP;
word buffer_advance = CLIB_CACHE_LINE_BYTES * 2;
/*
@@ -396,30 +364,31 @@ hicn_satisfy_faces (vlib_main_t * vm, u32 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.
+ * 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.
+ /* 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 == 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);
+ 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);
@@ -429,12 +398,12 @@ hicn_satisfy_faces (vlib_main_t * vm, u32 bi0,
while (n_left_from > 0)
{
- //Dual loop, X2
+ // Dual loop, X2
while (n_left_from >= 4 && *n_left_to_next >= 2)
{
vlib_buffer_t *h0, *h1;
u32 hi0, hi1;
- dpo_id_t *face0, *face1;
+ hicn_face_id_t face0, face1;
/* Prefetch for next iteration. */
{
@@ -458,10 +427,13 @@ hicn_satisfy_faces (vlib_main_t * vm, u32 bi0,
n_left_from -= 2;
clones += 2;
- next0 = face0->dpoi_next_node;
- next1 = face1->dpoi_next_node;
- vnet_buffer (h0)->ip.adj_index[VLIB_TX] = face0->dpoi_index;
- vnet_buffer (h1)->ip.adj_index[VLIB_TX] = face1->dpoi_index;
+ 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;
@@ -473,8 +445,7 @@ hicn_satisfy_faces (vlib_main_t * vm, u32 bi0,
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),
+ clib_memcpy (t->packet_data, vlib_buffer_get_current (h0),
sizeof (t->packet_data));
}
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
@@ -485,21 +456,19 @@ hicn_satisfy_faces (vlib_main_t * vm, u32 bi0,
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),
+ 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);
+ 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;
- dpo_id_t *face0;
+ hicn_face_id_t face0;
face0 = hicn_face_db_get_dpo_face (i++, &pitp->u.pit.faces);
@@ -511,8 +480,9 @@ hicn_satisfy_faces (vlib_main_t * vm, u32 bi0,
n_left_from -= 1;
clones += 1;
- next0 = face0->dpoi_next_node;
- vnet_buffer (h0)->ip.adj_index[VLIB_TX] = face0->dpoi_index;
+ 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++;
@@ -524,8 +494,7 @@ hicn_satisfy_faces (vlib_main_t * vm, u32 bi0,
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),
+ clib_memcpy (t->packet_data, vlib_buffer_get_current (h0),
sizeof (t->packet_data));
}
/*
@@ -536,10 +505,8 @@ hicn_satisfy_faces (vlib_main_t * vm, u32 bi0,
* 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);
-
+ 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) */
@@ -557,20 +524,19 @@ hicn_satisfy_faces (vlib_main_t * vm, u32 bi0,
if (PREDICT_FALSE (!found))
{
ASSERT (0);
- drop_packet (vm, bi0, n_left_to_next, &next0, to_next, next_index,
- node);
+ 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)
+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
@@ -584,13 +550,13 @@ clone_data_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
*/
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_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)
+ if (dmsg_lifetime < HICN_PARAM_CS_LIFETIME_MIN ||
+ dmsg_lifetime > HICN_PARAM_CS_LIFETIME_MAX)
{
dmsg_lifetime = HICN_PARAM_CS_LIFETIME_DFLT;
}
@@ -602,7 +568,7 @@ clone_data_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
/* packet trace format function */
always_inline u8 *
-hicn_data_fwd_format_trace (u8 * s, va_list * args)
+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 *);
@@ -612,15 +578,14 @@ hicn_data_fwd_format_trace (u8 * s, va_list * args)
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));
+ 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,
@@ -635,11 +600,11 @@ VLIB_REGISTER_NODE(hicn_data_fwd_node) =
.next_nodes = {
[HICN_DATA_FWD_NEXT_V4_LOOKUP] = "ip4-lookup",
[HICN_DATA_FWD_NEXT_V6_LOOKUP] = "ip6-lookup",
- [HICN_DATA_FWD_NEXT_PUSH] = "hicn-data-push",
+ [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
diff --git a/hicn-plugin/src/data_input_node.c b/hicn-plugin/src/data_input_node.c
index b8c19757c..c94443a6b 100644
--- a/hicn-plugin/src/data_input_node.c
+++ b/hicn-plugin/src/data_input_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Copyright (c) 2020-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -16,8 +16,8 @@
#include <vnet/vnet.h>
#include <vnet/ip/ip.h>
#include <vnet/fib/ip6_fib.h>
-#include <vnet/fib/fib_table.h> /* for FIB table and entry creation */
-#include <vnet/fib/fib_entry.h> /* for FIB table and entry creation */
+#include <vnet/fib/fib_table.h> /* for FIB table and entry creation */
+#include <vnet/fib/fib_entry.h> /* for FIB table and entry creation */
#include <vnet/fib/ip4_fib.h>
#include <vnet/dpo/load_balance.h>
@@ -61,7 +61,7 @@ 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)
+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 *);
@@ -69,16 +69,15 @@ format_hicn_data_input_trace (u8 * s, va_list * args)
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);
+ 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)
+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;
@@ -146,7 +145,7 @@ hicn_data_input_ip6_fn (vlib_main_t * vm,
vnet_buffer (p0)->ip.flow_hash = vnet_buffer (p1)->ip.flow_hash = 0;
- //No vpp loadbalancing. Missing header file to exploit it
+ // 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);
@@ -180,11 +179,10 @@ hicn_data_input_ip6_fn (vlib_main_t * vm,
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));
+ 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;
@@ -253,7 +251,7 @@ hicn_data_input_ip6_fn (vlib_main_t * vm,
ASSERT (lb0->lb_n_buckets > 0);
ASSERT (is_pow2 (lb0->lb_n_buckets));
- //No vpp loadbalancing. Missing header file to exploit it
+ // No vpp loadbalancing. Missing header file to exploit it
dpo0 = load_balance_get_bucket_i (lb0, 0);
if (dpo_is_hicn (dpo0))
@@ -271,8 +269,8 @@ hicn_data_input_ip6_fn (vlib_main_t * vm,
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, lbi0, 1, vlib_buffer_length_in_chain (vm, p0));
from += 1;
to_next += 1;
@@ -297,39 +295,29 @@ hicn_data_input_ip6_fn (vlib_main_t * vm,
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] = "hicn-face-ip6-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* */
-
+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" },
+};
+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"),
+};
always_inline uword
-hicn_data_input_ip4_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
+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;
@@ -449,7 +437,6 @@ hicn_data_input_ip4_fn (vlib_main_t * vm,
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))
{
@@ -490,18 +477,14 @@ hicn_data_input_ip4_fn (vlib_main_t * vm,
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]));
+ 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;
@@ -595,13 +578,10 @@ hicn_data_input_ip4_fn (vlib_main_t * vm,
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_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;
@@ -652,8 +632,7 @@ hicn_data_input_ip4_fn (vlib_main_t * vm,
}
vlib_increment_combined_counter (cm, thread_index, lbi0, 1,
- vlib_buffer_length_in_chain (vm,
- b[0]));
+ vlib_buffer_length_in_chain (vm, b[0]));
b += 1;
next += 1;
@@ -668,30 +647,22 @@ hicn_data_input_ip4_fn (vlib_main_t * vm,
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] = "hicn-face-ip4-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* */
+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" },
+};
+
+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"),
+};
diff --git a/hicn-plugin/src/data_pcslookup.h b/hicn-plugin/src/data_pcslookup.h
index fa75c3ac3..e3050c31c 100644
--- a/hicn-plugin/src/data_pcslookup.h
+++ b/hicn-plugin/src/data_pcslookup.h
@@ -18,6 +18,15 @@
#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
*/
@@ -37,9 +46,6 @@ typedef struct
typedef enum
{
- HICN_DATA_PCSLOOKUP_NEXT_V4_LOOKUP,
- HICN_DATA_PCSLOOKUP_NEXT_V6_LOOKUP,
- HICN_DATA_PCSLOOKUP_NEXT_STORE_DATA,
HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD, /* This must be one position
* before the error drop!! */
HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP,
diff --git a/hicn-plugin/src/data_pcslookup_node.c b/hicn-plugin/src/data_pcslookup_node.c
index cbea07871..073d06c96 100644
--- a/hicn-plugin/src/data_pcslookup_node.c
+++ b/hicn-plugin/src/data_pcslookup_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -29,7 +29,7 @@ static char *hicn_data_pcslookup_error_strings[] = {
};
/* packet trace format function */
-always_inline u8 *hicn_data_pcslookup_format_trace (u8 * s, va_list * args);
+always_inline u8 *hicn_data_pcslookup_format_trace (u8 *s, va_list *args);
vlib_node_registration_t hicn_data_pcslookup_node;
@@ -37,8 +37,8 @@ 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)
+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;
@@ -63,7 +63,6 @@ hicn_data_pcslookup_node_fn (vlib_main_t * vm,
while (n_left_from > 0 && n_left_to_next > 0)
{
vlib_buffer_t *b0;
- hicn_buffer_t *hb0;
u8 isv6;
u8 *nameptr;
u16 namelen;
@@ -100,7 +99,6 @@ hicn_data_pcslookup_node_fn (vlib_main_t * vm,
n_left_to_next -= 1;
b0 = vlib_get_buffer (vm, bi0);
- hb0 = hicn_get_buffer (b0);
next0 = HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP;
/* Incr packet counter */
@@ -109,41 +107,21 @@ hicn_data_pcslookup_node_fn (vlib_main_t * vm,
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))
+ 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);
+ 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 HICN_FEATURE_CS
- if ((res == HICN_ERROR_HASHTB_HASH_NOT_FOUND ||
- (res == HICN_ERROR_NONE && is_cs0)) &&
- ((hb0->flags & HICN_BUFFER_FLAGS_FACE_IS_APP)))
- {
- next0 = HICN_DATA_PCSLOOKUP_NEXT_STORE_DATA;
- }
- else 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;
- }
- }
-#else
if (res == HICN_ERROR_NONE)
{
/*
@@ -154,7 +132,6 @@ hicn_data_pcslookup_node_fn (vlib_main_t * vm,
next0 = HICN_DATA_PCSLOOKUP_NEXT_DATA_FWD + is_cs0;
}
}
-#endif
hicn_store_internal_state (b0, name_hash, node_id0, dpo_ctx_id0,
vft_id0, hash_entry_id, bucket_id,
@@ -203,7 +180,7 @@ hicn_data_pcslookup_node_fn (vlib_main_t * vm,
/* packet trace format function */
static u8 *
-hicn_data_pcslookup_format_trace (u8 * s, va_list * args)
+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 *);
@@ -218,7 +195,6 @@ hicn_data_pcslookup_format_trace (u8 * s, va_list * args)
/*
* Node registration for the data forwarder node
*/
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE(hicn_data_pcslookup_node) =
{
.function = hicn_data_pcslookup_node_fn,
@@ -231,14 +207,10 @@ VLIB_REGISTER_NODE(hicn_data_pcslookup_node) =
.error_strings = hicn_data_pcslookup_error_strings,
.n_next_nodes = HICN_DATA_PCSLOOKUP_N_NEXT,
.next_nodes = {
- [HICN_DATA_PCSLOOKUP_NEXT_V4_LOOKUP] = "ip4-lookup",
- [HICN_DATA_PCSLOOKUP_NEXT_V6_LOOKUP] = "ip6-lookup",
- [HICN_DATA_PCSLOOKUP_NEXT_STORE_DATA] = "hicn-data-push",
[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
diff --git a/hicn-plugin/src/data_push_node.c b/hicn-plugin/src/data_push_node.c
deleted file mode 100644
index fc19362f9..000000000
--- a/hicn-plugin/src/data_push_node.c
+++ /dev/null
@@ -1,326 +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 <vlib/vlib.h>
-#include <vnet/vnet.h>
-
-#include "hicn.h"
-#include "parser.h"
-#include "strategy_dpo_ctx.h"
-#include "infra.h"
-#include "mgmt.h"
-#include "pcs.h"
-#include "state.h"
-
-/*
- * Node context data (to be used in all the strategy nodes); we think this is
- * per-thread/instance
- */
-typedef struct hicn_data_push_runtime_s
-{
- int id;
- hicn_pit_cs_t *pitcs;
-} hicn_data_push_runtime_t;
-
-/* Stats string values */
-static char *hicn_data_push_error_strings[] = {
-#define _(sym, string) string,
- foreach_hicnfwd_error
-#undef _
-};
-
-typedef enum
-{
- HICN_DATA_PUSH_NEXT_FWD,
- HICN_DATA_PUSH_NEXT_ERROR_DROP,
- HICN_DATA_PUSH_N_NEXT,
-} hicn_data_push_next_t;
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
-} hicn_data_push_trace_t;
-
-vlib_node_registration_t hicn_data_push_node;
-
-always_inline void
-prep_buffer_for_cs (vlib_main_t * vm, vlib_buffer_t * b0, u8 isv6)
-{
- word buffer_advance = CLIB_CACHE_LINE_BYTES * 2;
- hicn_buffer_t *hicnb = hicn_get_buffer (b0);
-
- if (PREDICT_TRUE (b0->next_buffer == 0))
- {
- b0->total_length_not_including_first_buffer = 0;
- b0->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
- }
-
- /*
- * 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
- {
- vlib_buffer_advance (b0, buffer_advance);
- }
-}
-
-always_inline int
-hicn_new_data (vlib_main_t * vm, hicn_data_push_runtime_t * rt,
- vlib_buffer_t * b0, u32 ** to_forward, u32 * n_to_forward,
- f64 tnow, u8 * nameptr, u16 namelen, u8 isv6)
-{
- int ret;
- u32 bi0 = vlib_get_buffer_index (vm, b0);
- hicn_hash_node_t *nodep;
- hicn_pcs_entry_t *pitp;
- hicn_header_t *hicn0 = vlib_buffer_get_current (b0);
- hicn_buffer_t *hicnb0 = hicn_get_buffer (b0);
- u32 node_id0 = 0;
- index_t dpo_ctx_id0 = ~0;
- u8 vft_id0 = default_dpo.hicn_dpo_get_type ();
- u8 is_cs0 = 1;
- u8 hash_entry_id = 0;
- u32 bucket_id = ~0;
- u8 bucket_is_overflow = 0;
- hicn_lifetime_t dmsg_lifetime;
-
- hicnb0 = hicn_get_buffer (b0);
- hicn_type_t type = hicnb0->type;
- hicn_ops_vft[type.l1]->get_lifetime (type, &hicn0->protocol,
- &dmsg_lifetime);
-
- if (!dmsg_lifetime)
- {
- vlib_buffer_free_one (vm, bi0);
- return HICN_ERROR_NONE;
- }
-
- /* Create PIT node and init PIT entry */
- nodep = hicn_hashtb_alloc_node (rt->pitcs->pcs_table);
- if (PREDICT_FALSE (nodep == NULL))
- {
- vlib_buffer_free_one (vm, bi0);
- /* Nothing we can do - no mem */
- return HICN_ERROR_HASHTB_NOMEM;
- }
-
- pitp = hicn_pit_get_data (nodep);
- hicn_cs_init_data (pitp);
- 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);
-
- /* Set up the hash node and insert it */
- hicn_hashtb_init_node (rt->pitcs->pcs_table, nodep, nameptr, namelen);
-
-
- hicn_hash_entry_t *hash_entry;
- ret =
- hicn_pcs_cs_insert_update (vm, 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, &(hicnb0->face_dpo_id));
-
- if (ret != HICN_ERROR_NONE)
- {
- hicn_hashtb_free_node (rt->pitcs->pcs_table, nodep);
- }
-
- if (ret != HICN_ERROR_HASHTB_NOMEM)
- {
- if (!is_cs0)
- {
- ASSERT (ret != HICN_ERROR_NONE);
- hicn_store_internal_state (b0, hicnb0->name_hash, node_id0,
- dpo_ctx_id0, vft_id0, hash_entry_id,
- bucket_id, bucket_is_overflow);
-
- (*to_forward)[0] = bi0;
- *to_forward += 1;
- *n_to_forward += 1;
- }
- else
- {
- prep_buffer_for_cs (vm, b0, isv6);
- }
- }
-
- return (ret);
-
-}
-
-/*
- * ICN strategy later node for interests: - 1 packet at a time - ipv4/tcp
- * ipv6/tcp
- */
-uword
-hicn_data_push_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_data_push_next_t next_index;
- hicn_data_push_runtime_t *rt;
- vl_api_hicn_api_node_stats_get_reply_t stats = { 0 };
- f64 tnow;
- u32 *to_forward = NULL, *header = NULL, n_to_forward = 0;
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = (hicn_data_push_next_t) node->cached_next_index;
- rt = vlib_node_get_runtime_data (vm, hicn_data_push_node.index);
- rt->pitcs = &hicn_main.pitcs;
-
- vec_alloc (to_forward, n_left_from);
- header = to_forward;
- /* Capture time in vpp terms */
- tnow = vlib_time_now (vm);
-
- while (n_left_from > 0)
- {
- u8 isv6;
- u8 *nameptr;
- u16 namelen;
- hicn_name_t name;
- hicn_header_t *hicn0;
- vlib_buffer_t *b0;
- u32 bi0;
- int ret0;
-
- /* Prefetch for next iteration. */
- if (n_left_from > 1)
- {
- vlib_buffer_t *b1;
- //hicn_buffer_t * hicnb1;
- 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;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- ret0 = hicn_data_parse_pkt (b0, &name, &namelen, &hicn0, &isv6);
- nameptr = (u8 *) (&name);
-
- if (PREDICT_TRUE (ret0 == HICN_ERROR_NONE))
- {
- hicn_new_data (vm, rt, b0, &to_forward, &n_to_forward, tnow,
- nameptr, namelen, isv6);
- stats.pkts_data_count++;
- }
-
- /* Maybe trace */
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
- (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- hicn_data_push_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 = HICN_DATA_PUSH_NEXT_ERROR_DROP;
- }
- }
-
- to_forward -= n_to_forward;
- next_index = HICN_DATA_PUSH_NEXT_FWD;
-
- while (n_to_forward > 0)
- {
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
- while (n_to_forward > 0 && n_left_to_next > 0)
- {
- to_next[0] = to_forward[0];
- to_forward++;
- n_to_forward--;
- to_next++;
- n_left_to_next--;
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- vec_free (header);
-
- vlib_node_increment_counter (vm, hicn_data_push_node.index,
- HICNFWD_ERROR_CACHED, stats.pkts_data_count);
-
- return (frame->n_vectors);
-}
-
-/* packet trace format function */
-always_inline u8 *
-hicn_data_push_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_push_trace_t *t = va_arg (*args, hicn_data_push_trace_t *);
-
- s = format (s, "DATA-STORE: pkt: %d, sw_if_index %d, next index %d\n",
- (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_push_node) =
-{
- .function = hicn_data_push_fn,
- .name = "hicn-data-push",
- .vector_size = sizeof(u32),
- .runtime_data_bytes = sizeof(hicn_data_push_runtime_t),
- .format_trace = hicn_data_push_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(hicn_data_push_error_strings),
- .error_strings = hicn_data_push_error_strings,
- .n_next_nodes = HICN_DATA_PUSH_N_NEXT,
- .next_nodes = {
- [HICN_DATA_PUSH_NEXT_FWD] = "hicn-data-fwd",
- [HICN_DATA_PUSH_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.h b/hicn-plugin/src/error.h
index 2124e63c5..59ebce61c 100644
--- a/hicn-plugin/src/error.h
+++ b/hicn-plugin/src/error.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,6 +16,13 @@
#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") \
@@ -69,8 +76,9 @@
_(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")
-
+ _(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
{
diff --git a/hicn-plugin/src/face_db.h b/hicn-plugin/src/face_db.h
index 17c28959a..4dd8b2f32 100644
--- a/hicn-plugin/src/face_db.h
+++ b/hicn-plugin/src/face_db.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,7 +20,7 @@
#include "faces/face.h"
/**
- * @File
+ * @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
@@ -28,7 +28,7 @@
*/
/* Must be power of two */
-#define HICN_FACE_DB_INLINE_FACES 4
+#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
@@ -38,7 +38,7 @@
typedef struct hicn_face_bucket_s
{
/* Array of indexes of virtual faces */
- dpo_id_t faces[HICN_PIT_N_HOP_BUCKET];
+ hicn_face_id_t faces[HICN_PIT_N_HOP_BUCKET];
/* Used to check if interests are retransmission */
u8 bitmap[HICN_PIT_BITMAP_SIZE_BYTE];
@@ -60,7 +60,7 @@ typedef struct __attribute__ ((packed)) hicn_face_db_s
/* 24B + 32B (8*4) = 56B */
/* Array of indexes of virtual faces */
- dpo_id_t inline_faces[HICN_FACE_DB_INLINE_FACES];
+ hicn_face_id_t inline_faces[HICN_FACE_DB_INLINE_FACES];
/* 56B + 4B = 60B */
u32 next_bucket;
@@ -71,13 +71,13 @@ typedef struct __attribute__ ((packed)) hicn_face_db_s
} hicn_face_db_t;
-always_inline dpo_id_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
+ 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)]);
}
@@ -94,23 +94,23 @@ hicn_face_db_get_bucket (u32 bucket_index)
}
always_inline void
-hicn_face_db_add_face_dpo (dpo_id_t * dpo, hicn_face_db_t * face_db)
+hicn_face_db_add_face (hicn_face_id_t face_id, hicn_face_db_t * face_db)
{
- ASSERT (dpo->dpoi_index != ~0);
+ //ASSERT (dpo->dpoi_index != ~0);
hicn_face_bucket_t *faces_bkt =
pool_elt_at_index (hicn_face_bucket_pool, face_db->next_bucket);
- dpo_id_t *face =
+ 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)]);
- clib_memcpy (face, dpo, sizeof (dpo_id_t));
+ *element = face_id;
- u32 bitmap_index = dpo->dpoi_index % HICN_PIT_N_HOP_BITMAP_SIZE;
+ 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);
@@ -119,11 +119,11 @@ hicn_face_db_add_face_dpo (dpo_id_t * dpo, hicn_face_db_t * face_db)
}
always_inline u8
-hicn_face_search (dpo_id_t * dpo, hicn_face_db_t * face_db)
+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 = dpo->dpoi_index % HICN_PIT_N_HOP_BITMAP_SIZE;
+ u32 bitmap_index = index % HICN_PIT_N_HOP_BITMAP_SIZE;
u32 position_array = bitmap_index / 8;
u8 bit_index = bitmap_index - position_array * 8;
diff --git a/hicn-plugin/src/faces/app/address_mgr.c b/hicn-plugin/src/faces/app/address_mgr.c
index 1674379c4..2d5894ab8 100644
--- a/hicn-plugin/src/faces/app/address_mgr.c
+++ b/hicn-plugin/src/faces/app/address_mgr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -36,7 +36,6 @@
#include "../../infra.h"
#include "../../error.h"
#include "../face.h"
-#include "../ip/face_ip.h"
#include "../../strategy_dpo_ctx.h"
#include "../../route.h"
@@ -134,26 +133,25 @@ get_two_ip6_addresses (ip6_address_t * appif_addr, ip6_address_t * nh_addr)
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_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);
+ //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);
+ // fib_table_unlock (fib_index, fib_pfx.fp_proto,
+ // FIB_SOURCE_PRIORITY_HI);
}
if (fib_entry_index != FIB_NODE_INDEX_INVALID)
{
diff --git a/hicn-plugin/src/faces/app/face_app_cli.c b/hicn-plugin/src/faces/app/face_app_cli.c
index 1e8eb6a5b..36f8bf3f7 100644
--- a/hicn-plugin/src/faces/app/face_app_cli.c
+++ b/hicn-plugin/src/faces/app/face_app_cli.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -18,20 +18,19 @@
#include <vlib/vlib.h>
#include <vnet/ip/ip6_packet.h>
-#include "../ip/face_ip.h"
-#include "../ip/dpo_ip.h"
+//#include "../face_dpo.h"
#include "../face.h"
#include "face_prod.h"
#include "face_cons.h"
-#define HICN_FACE_NONE 0
+#define HICN_FACE_NONE 0
#define HICN_FACE_DELETE 1
-#define HICN_FACE_ADD 2
+#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)
+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;
@@ -43,7 +42,6 @@ hicn_face_app_cli_set_command_fn (vlib_main_t * vm,
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))
@@ -57,8 +55,8 @@ hicn_face_app_cli_set_command_fn (vlib_main_t * vm,
{
face_op = HICN_FACE_DELETE;
}
- else if (face_op == HICN_FACE_DELETE
- && unformat (line_input, "id %d", &face_id1))
+ else if (face_op == HICN_FACE_DELETE &&
+ unformat (line_input, "id %d", &face_id1))
;
else if (unformat (line_input, "add"))
{
@@ -66,13 +64,12 @@ hicn_face_app_cli_set_command_fn (vlib_main_t * vm,
}
else if (face_op == HICN_FACE_ADD)
{
- if (unformat (line_input, "intfc %U",
- unformat_vnet_sw_interface, vnm, &sw_if))
+ 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))
+ else if (unformat (line_input, "prod prefix %U/%d",
+ unformat_ip46_address, &prefix.fp_addr,
+ IP46_TYPE_ANY, &prefix.fp_len))
{
prod = 1;
}
@@ -82,10 +79,9 @@ hicn_face_app_cli_set_command_fn (vlib_main_t * vm,
;
else
{
- return clib_error_return (0, "%s '%U'",
- get_error_string
- (HICN_ERROR_CLI_INVAL),
- format_unformat_error, line_input);
+ return clib_error_return (
+ 0, "%s '%U'", get_error_string (HICN_ERROR_CLI_INVAL),
+ format_unformat_error, line_input);
}
}
else
@@ -117,20 +113,17 @@ hicn_face_app_cli_set_command_fn (vlib_main_t * vm,
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);
+ 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 */ );
+ 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
@@ -140,17 +133,16 @@ hicn_face_app_cli_set_command_fn (vlib_main_t * vm,
}
else
{
- rv =
- hicn_face_cons_add (&cons_addr4, &cons_addr6, sw_if, &face_id1,
- &face_id2);
+ 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);
+ 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
@@ -164,7 +156,7 @@ hicn_face_app_cli_set_command_fn (vlib_main_t * vm,
{
hicn_face_t *face = hicn_dpoi_get_from_idx (face_id1);
- if (face->shared.flags & HICN_FACE_FLAGS_APPFACE_CONS)
+ if (face->flags & HICN_FACE_FLAGS_APPFACE_CONS)
rv = hicn_face_cons_del (face_id1);
else
rv = hicn_face_prod_del (face_id1);
@@ -182,20 +174,18 @@ hicn_face_app_cli_set_command_fn (vlib_main_t * vm,
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));
+ 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) =
-{
+VLIB_CLI_COMMAND (hicn_face_app_cli_set_command, static) = {
.path = "hicn face app",
- .short_help = "hicn face app {add intfc <sw_if> { prod prefix <hicn_prefix> cs_size <size_in_packets>} {cons} | {del <face_id>}",
+ .short_help = "hicn face app {add intfc <sw_if> { prod prefix <hicn_prefix> "
+ "cs_size <size_in_packets>} {cons} | {del <face_id>}",
.function = hicn_face_app_cli_set_command_fn,
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/faces/app/face_cons.c b/hicn-plugin/src/faces/app/face_cons.c
index e51201c21..d44ba1a2b 100644
--- a/hicn-plugin/src/faces/app/face_cons.c
+++ b/hicn-plugin/src/faces/app/face_cons.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -57,10 +57,12 @@ hicn_face_cons_add (ip4_address_t * nh_addr4, ip6_address_t * nh_addr6,
ip46_address_t nh_addr = to_ip46 (0, (u8 *) nh_addr4);
- hicn_iface_ip_add (&if_ip, &nh_addr, swif, faceid1);
+ 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->shared.flags |= HICN_FACE_FLAGS_APPFACE_CONS;
+ face->flags |= HICN_FACE_FLAGS_APPFACE_CONS;
get_two_ip6_addresses (&(if_ip.ip6), nh_addr6);
ip6_add_del_interface_address (vm,
@@ -68,10 +70,12 @@ hicn_face_cons_add (ip4_address_t * nh_addr4, ip6_address_t * nh_addr6,
&(if_ip.ip6),
ADDR_MGR_IP6_CONS_LEN, 0 /* is_del */ );
- hicn_iface_ip_add (&if_ip, (ip46_address_t *) nh_addr6, swif, faceid2);
+ 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->shared.flags |= HICN_FACE_FLAGS_APPFACE_CONS;
+ face->flags |= HICN_FACE_FLAGS_APPFACE_CONS;
return HICN_ERROR_NONE;
}
@@ -84,9 +88,9 @@ hicn_face_cons_del (hicn_face_id_t face_id)
hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
- if (face->shared.flags & HICN_FACE_FLAGS_APPFACE_CONS)
+ if (face->flags & HICN_FACE_FLAGS_APPFACE_CONS)
{
- return hicn_face_ip_del (face_id);
+ return hicn_face_del (face_id);
}
else
{
diff --git a/hicn-plugin/src/faces/app/face_prod.c b/hicn-plugin/src/faces/app/face_prod.c
index ae59719ce..16b6e6158 100644
--- a/hicn-plugin/src/faces/app/face_prod.c
+++ b/hicn-plugin/src/faces/app/face_prod.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -30,28 +30,23 @@ hicn_face_prod_state_t *face_state_vec;
u32 *face_state_pool;
static int
-hicn_app_state_create (u32 swif, fib_prefix_t * prefix)
+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* */
+ pool_foreach (swif_app, face_state_pool)
+ if (*swif_app == swif)
+ {
+ found = 1;
+ }
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));
@@ -63,15 +58,13 @@ hicn_app_state_create (u32 swif, fib_prefix_t * 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, 1, 0, 0);
+ 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);
+ 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;
@@ -87,33 +80,28 @@ hicn_app_state_del (u32 swif)
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* */
+ pool_foreach (temp, face_state_pool)
+ if (*temp == swif)
+ {
+ found = 1;
+ swif_app = temp;
+ }
- prefix = &(face_state_vec[swif].prefix);
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);
+ 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);
+ ret = vnet_feature_enable_disable ("ip6-unicast", "hicn-face-prod-input",
+ swif, 0, 0, 0);
}
pool_put (face_state_pool, swif_app);
@@ -123,8 +111,8 @@ hicn_app_state_del (u32 swif)
}
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)
+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 ();
@@ -132,7 +120,7 @@ hicn_face_prod_add (fib_prefix_t * prefix, u32 sw_if, u32 * cs_reserved,
hicn_main_t *hm = &hicn_main;
ip46_address_t local_app_ip;
- ip46_address_t remote_app_ip;
+ CLIB_UNUSED (ip46_address_t remote_app_ip);
u32 if_flags = 0;
if (!hm->is_enabled)
@@ -160,28 +148,22 @@ hicn_face_prod_add (fib_prefix_t * prefix, u32 sw_if, u32 * cs_reserved,
{
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
*/
- if (ip46_address_is_ip4 (&prefix->fp_addr))
- {
- face =
- hicn_face_ip4_get (&(prefix->fp_addr.ip4), sw_if,
- &hicn_face_ip_remote_hashtb);
- }
- else
- {
- face =
- hicn_face_ip6_get (&(prefix->fp_addr.ip6), sw_if,
- &hicn_face_ip_remote_hashtb);
- if (face != NULL)
- return HICN_ERROR_FACE_ALREADY_CREATED;
- }
+ face =
+ hicn_face_get (&(prefix->fp_addr), sw_if, &hicn_face_hashtb, adj_index);
if (face != NULL)
{
- if (!(face->shared.flags & HICN_FACE_FLAGS_DELETED))
+ if (!(face->flags & HICN_FACE_FLAGS_DELETED))
return HICN_ERROR_FACE_ALREADY_CREATED;
/*
@@ -189,19 +171,17 @@ hicn_face_prod_add (fib_prefix_t * prefix, u32 sw_if, u32 * cs_reserved,
* producer's prefix.
*/
/* It should never happens, this is a safety check. */
- if (face->shared.flags & HICN_FACE_FLAGS_APPFACE_CONS)
+ 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->shared.flags & HICN_FACE_FLAGS_DELETED)
+ if (face->flags & HICN_FACE_FLAGS_DELETED)
{
/*
* remove the deleted flag and retrieve the face
* local addr
*/
- face->shared.flags &= HICN_FACE_FLAGS_DELETED;
- hicn_face_prod_t *prod_face = (hicn_face_prod_t *) face->data;
- local_app_ip = prod_face->ip_face.local_addr;
+ face->flags &= HICN_FACE_FLAGS_DELETED;
}
}
else
@@ -216,15 +196,13 @@ hicn_face_prod_add (fib_prefix_t * prefix, u32 sw_if, u32 * cs_reserved,
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);
-
- ret =
- hicn_face_ip_add (&local_app_ip, &remote_app_ip, sw_if, faceid,
- HICN_FACE_FLAGS_APPFACE_PROD);
+ 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
{
@@ -236,72 +214,82 @@ hicn_face_prod_add (fib_prefix_t * prefix, u32 sw_if, u32 * cs_reserved,
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);
-
- ret =
- hicn_face_ip_add (&local_app_ip, &remote_app_ip, sw_if, faceid,
- HICN_FACE_FLAGS_APPFACE_PROD);
+ 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);
}
-
- face = hicn_dpoi_get_from_idx (*faceid);
-
- face->shared.flags |= HICN_FACE_FLAGS_APPFACE_PROD;
-
- hicn_face_prod_t *prod_face = (hicn_face_prod_t *) face->data;
-
- /*
- * For the moment we keep them here although it would be good
- * to create a different face for appface
- */
- prod_face->policy_vft.hicn_cs_insert = hicn_cs_lru.hicn_cs_insert;
- prod_face->policy_vft.hicn_cs_update = hicn_cs_lru.hicn_cs_update;
- prod_face->policy_vft.hicn_cs_dequeue = hicn_cs_lru.hicn_cs_dequeue;
- prod_face->policy_vft.hicn_cs_delete_get =
- hicn_cs_lru.hicn_cs_delete_get;
- prod_face->policy_vft.hicn_cs_trim = hicn_cs_lru.hicn_cs_trim;
- prod_face->policy_vft.hicn_cs_flush = hicn_cs_lru.hicn_cs_flush;
-
}
- if (ret == HICN_ERROR_NONE
- && hicn_face_prod_set_lru_max (*faceid, cs_reserved) == HICN_ERROR_NONE)
+ if (ret == HICN_ERROR_NONE)
+ // && hicn_face_prod_set_lru_max (*faceid, cs_reserved) ==
+ // HICN_ERROR_NONE)
{
- 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;
- }
+ 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;
- }
+ {
+ 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);
- ret = hicn_route_add (faceid, 1, 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);
-
- if (*faceid != HICN_FACE_NULL)
- hicn_face_ip_del (*faceid);
}
return ret;
}
@@ -314,110 +302,47 @@ hicn_face_prod_del (hicn_face_id_t face_id)
hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
- if (face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD)
+ if (face->flags & HICN_FACE_FLAGS_APPFACE_PROD)
{
- hicn_face_prod_t *prod_face = (hicn_face_prod_t *) face->data;
- /* Free the CS reserved for the face */
- hicn_main.pitcs.pcs_app_count -= prod_face->policy.max;
- prod_face->policy.max = 0;
-
/* Remove the face from the fib */
- hicn_route_del_nhop (&(face_state_vec[face->shared.sw_if].prefix),
- face_id);
+ hicn_route_disable (&(face_state_vec[face->sw_if].prefix));
+ // hicn_route_del_nhop (&(face_state_vec[face->sw_if].prefix),
+ // face_id);
- /*
- * Delete the content in the CS before deleting the face.
- * Mandatory to prevent hitting the CS and not having the lru list
- * due to a early deletion of the face.
- */
- vlib_main_t *vm = vlib_get_main ();
- prod_face->policy_vft.hicn_cs_flush (vm, &(hicn_main.pitcs),
- &(prod_face->policy));
-
- int ret = hicn_face_ip_del (face_id);
- return ret ==
- HICN_ERROR_NONE ? hicn_app_state_del (face->shared.sw_if) : ret;
+ // 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;
}
-}
-int
-hicn_face_prod_set_lru_max (hicn_face_id_t face_id, u32 * requested_size)
-{
- int ret = HICN_ERROR_NONE;
- vlib_main_t *vm = vlib_get_main ();
- hicn_face_t *face;
- hicn_face_prod_t *face_prod;
-
- if (!hicn_infra_fwdr_initialized)
- {
- ret = HICN_ERROR_FWD_NOT_ENABLED;
- vlib_cli_output (vm, "hicn: %s\n", get_error_string (ret));
- return ret;
- }
- face = hicn_dpoi_get_from_idx (face_id);
- face_prod = (hicn_face_prod_t *) face->data;
-
- if (face == NULL)
- return HICN_ERROR_FACE_NOT_FOUND;
-
- if (*requested_size > HICN_PARAM_FACE_MAX_CS_RESERVED)
- *requested_size = HICN_PARAM_FACE_MAX_CS_RESERVED;
-
- uint32_t available =
- hicn_main.pitcs.pcs_app_max - hicn_main.pitcs.pcs_app_count;
-
- if (*requested_size > available)
- *requested_size = available;
-
- face_prod->policy.max = *requested_size;
- face_prod->policy.count = 0;
- face_prod->policy.head = face_prod->policy.tail = 0;
-
- hicn_main.pitcs.pcs_app_count += *requested_size;
-
- return ret;
+ return HICN_ERROR_NONE;
}
u8 *
-format_hicn_face_prod (u8 * s, va_list * args)
+format_hicn_face_prod (u8 *s, va_list *args)
{
- index_t index = va_arg (*args, index_t);
+ CLIB_UNUSED (index_t index) = va_arg (*args, index_t);
CLIB_UNUSED (u32 indent) = va_arg (*args, u32);
- hicn_face_t *face;
- hicn_face_prod_t *prod_face;
-
- face = hicn_dpoi_get_from_idx (index);
- prod_face = (hicn_face_prod_t *) face->data;
- s =
- format (s, " (producer face: CS size %d, data cached %d)",
- prod_face->policy.max, prod_face->policy.count);
+ s = format (s, " (producer)");
return s;
}
-/* *INDENT-OFF* */
-VNET_FEATURE_INIT(hicn_prod_app_input_ip6, static)=
-{
+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"),
+ .runs_before = VNET_FEATURES ("ip6-inacl"),
};
-/* *INDENT-ON* */
-/* *INDENT-OFF* */
-VNET_FEATURE_INIT(hicn_prod_app_input_ip4, static)=
-{
+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"),
+ .runs_before = VNET_FEATURES ("ip4-inacl"),
};
-/* *INDENT-ON* */
-
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/faces/app/face_prod.h b/hicn-plugin/src/faces/app/face_prod.h
index 33e2a4199..4cb2e3fbf 100644
--- a/hicn-plugin/src/faces/app/face_prod.h
+++ b/hicn-plugin/src/faces/app/face_prod.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -17,7 +17,7 @@
#define _FACE_PRODUCER_H_
#include "../../cache_policies/cs_policy.h"
-#include "../ip/face_ip.h"
+#include "../face.h"
/**
* @file
@@ -56,15 +56,6 @@ extern hicn_face_prod_state_t *face_state_vec;
#define DEFAULT_PROBING_PORT 3784
-typedef struct __attribute__ ((packed)) hicn_face_prod_t_
-{
- hicn_face_ip_t ip_face;
-
- hicn_cs_policy_t policy;
- hicn_cs_policy_vft_t policy_vft;
-
-} hicn_face_prod_t;
-
/**
* @brief Add a new producer application face
*
diff --git a/hicn-plugin/src/faces/app/face_prod_node.c b/hicn-plugin/src/faces/app/face_prod_node.c
index 0ef25fe94..a843a01ef 100644
--- a/hicn-plugin/src/faces/app/face_prod_node.c
+++ b/hicn-plugin/src/faces/app/face_prod_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -19,8 +19,8 @@
* @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)
+ * 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"
@@ -56,7 +56,7 @@ typedef enum
vlib_node_registration_t hicn_face_prod_input_node;
static __clib_unused u8 *
-format_face_prod_input_trace (u8 * s, va_list * args)
+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 *);
@@ -64,13 +64,13 @@ format_face_prod_input_trace (u8 * s, va_list * args)
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);
+ 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)
+match_ip4_name (u32 *name, fib_prefix_t *prefix)
{
u32 xor = 0;
@@ -80,7 +80,7 @@ match_ip4_name (u32 * name, fib_prefix_t * prefix)
}
static_always_inline int
-match_ip6_name (u8 * name, fib_prefix_t * prefix)
+match_ip6_name (u8 *name, fib_prefix_t *prefix)
{
union
{
@@ -93,12 +93,12 @@ match_ip6_name (u8 * name, fib_prefix_t * prefix)
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]);
+ (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)
+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;
@@ -106,21 +106,20 @@ hicn_face_prod_next_from_data_hdr (vlib_node_runtime_t * node,
if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr)))
{
- match_res = match_ip4_name ((u32 *) & (ptr[12]), prefix);
+ 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);
+ 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;
+ 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)
+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)))
@@ -133,9 +132,8 @@ hicn_face_prod_trace_buffer (vlib_main_t * vm, vlib_node_runtime_t * node,
}
static uword
-hicn_face_prod_input_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+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;
@@ -192,14 +190,10 @@ hicn_face_prod_input_node_fn (vlib_main_t * vm,
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]];
+ 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);
@@ -212,18 +206,14 @@ hicn_face_prod_input_node_fn (vlib_main_t * vm,
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);
+ 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,
@@ -231,7 +221,6 @@ hicn_face_prod_input_node_fn (vlib_main_t * vm,
next0, next1, next2, next3);
stats.pkts_processed += 4;
-
}
while (n_left_from > 0 && n_left_to_next > 0)
@@ -264,30 +253,27 @@ hicn_face_prod_input_node_fn (vlib_main_t * vm,
stats.pkts_data_count++;
/* 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 (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_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,
@@ -300,13 +286,12 @@ VLIB_REGISTER_NODE(hicn_face_prod_input_node) =
.n_next_nodes = HICN_FACE_PROD_N_NEXT,
.next_nodes =
{
- [HICN_FACE_PROD_NEXT_DATA_IP4] = "hicn-face-ip4-input",
- [HICN_FACE_PROD_NEXT_DATA_IP6] = "hicn-face-ip6-input",
+ [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
*
diff --git a/hicn-plugin/src/faces/face.c b/hicn-plugin/src/faces/face.c
index f2dcdd151..d62054365 100644
--- a/hicn-plugin/src/faces/face.c
+++ b/hicn-plugin/src/faces/face.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -12,20 +12,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <vnet/fib/fib_entry_track.h>
#include "face.h"
-#include "ip/face_ip.h"
-#include "ip/face_ip_node.h"
-#include "ip/iface_ip_node.h"
-#include "ip/dpo_ip.h"
-#include "udp/face_udp.h"
-#include "udp/face_udp_node.h"
-#include "udp/iface_udp_node.h"
-#include "udp/dpo_udp.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;
+u8 pl_index = 1;
hicn_face_t *hicn_dpoi_face_pool;
@@ -33,65 +32,209 @@ 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,
+#define _(a, b, c) c,
foreach_hicn_face_counter
#undef _
};
u8 *
-face_show (u8 * s, int face_id, u32 indent)
+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);
- }
+ {
+ 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);
}
-void
-register_face_type (hicn_face_type_t face_type, hicn_face_vft_t * vft,
- char *name)
+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)
{
- if (first_type == DPO_FIRST)
- first_type = face_type;
-
- int idx = face_type - first_type;
- ASSERT (idx >= 0);
- vec_validate (face_vft_vec, idx);
- vec_validate (face_type_names_vec, idx);
-
- /* Copy the null char as well */
- char *name_str = (char *) malloc ((strlen (name) + 1) * sizeof (char));
- strcpy (name_str, name);
- face_vft_vec[idx] = *vft;
- face_type_names_vec[idx] = name_str;
+
+ 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)
+hicn_face_module_init (vlib_main_t *vm)
{
pool_validate (hicn_dpoi_face_pool);
pool_alloc (hicn_dpoi_face_pool, 1024);
- hicn_face_ip_init (vm);
- hicn_iface_ip_init (vm);
- hicn_face_udp_init (vm);
- hicn_iface_udp_init (vm);
- counters =
- vec_new (vlib_combined_counter_main_t,
- HICN_PARAM_FACES_MAX * HICN_N_COUNTER);
+ 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, ...)
+format_hicn_face_all (u8 *s, int n, ...)
{
va_list ap;
va_start (ap, n);
@@ -101,42 +244,62 @@ format_hicn_face_all (u8 * s, int n, ...)
hicn_face_t *face;
- /* *INDENT-OFF* */
- pool_foreach ( face, hicn_dpoi_face_pool,
- {
- hicn_face_vft_t * vft = hicn_face_get_vft(face->shared.face_type);
- hicn_face_id_t face_id = hicn_dpoi_get_index(face);
- s = format(s, "%U\n", vft->format_face, face_id, indent);
- });
- /* *INDENT-ON* */
+ pool_foreach (face, hicn_dpoi_face_pool)
+ {
+ s = format (s, "%U\n", format_hicn_face, hicn_dpoi_get_index (face),
+ indent);
+ }
return s;
}
-hicn_face_vft_t *
-hicn_face_get_vft (hicn_face_type_t face_type)
-{
- int idx = face_type - first_type;
- if (idx >= 0)
- return &face_vft_vec[idx];
- else
- return NULL;
-
-}
-
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->shared.locks--;
- if (face->shared.locks == 0)
+ face->locks--;
+ if (face->locks == 0)
pool_put_index (hicn_dpoi_face_pool, face_id);
else
- face->shared.flags |= HICN_FACE_FLAGS_DELETED;
+ face->flags |= HICN_FACE_FLAGS_DELETED;
}
else
ret = HICN_ERROR_FACE_NOT_FOUND;
@@ -144,6 +307,151 @@ hicn_face_del (hicn_face_id_t face_id)
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));
+
+ *retx = (retx_t){
+ .face_id = *pfaceid,
+ };
+
+ return HICN_ERROR_NONE;
+}
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/hicn-plugin/src/faces/face.h b/hicn-plugin/src/faces/face.h
index b758ece06..95c78b206 100644
--- a/hicn-plugin/src/faces/face.h
+++ b/hicn-plugin/src/faces/face.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,35 +16,66 @@
#ifndef __HICN_FACE_H__
#define __HICN_FACE_H__
+#include <vnet/fib/fib_node.h>
#include <vnet/vnet.h>
#include <vlib/vlib.h>
+#include <vnet/ip/ip46_address.h>
#include <vnet/dpo/dpo.h>
#include <vnet/adj/adj_types.h>
-#include "../hicn.h"
+#include <vppinfra/bihash_8_8.h>
+#include <vnet/adj/adj_midchain.h>
+
+#include "../error.h"
typedef u8 hicn_face_flags_t;
typedef index_t hicn_face_id_t;
-typedef dpo_type_t hicn_face_type_t;
/**
- * @file
+ * @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).
*
- * @brief Face
+ * 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.
*
- * This file implements a general face type. A face is carried through nodes as a
- * dpo. The face state (hicn_face_t) is the object pointed by the
- * dpoi_index in the dpo_id_t (see
- * https://docs.fd.io/vpp/18.07/d0/d37/dpo_8h_source.html).
- * A face state that does not contain the indication of the l2 adjacency is an
- * incomplete face (iface), otherwise it is considered to be complete. Each face type
- * provide specific node for processing packets in input or output of complete
- * and incomplete faces.
+ * 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 Fields shared among all the different types of faces
+ * @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_shared_s
+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) */
@@ -59,34 +90,24 @@ typedef struct __attribute__ ((packed)) hicn_face_shared_s
/* Number of dpo holding a reference to the dpoi (4B) */
u32 locks;
- /* Adjacency for the neighbor (4B) */
- adj_index_t adj;
+ /* 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;
- /* Face id corresponding to the global face pool (4B) */
- union
- {
- hicn_face_type_t face_type;
- u32 int_face_type; //To force the face_type_t to be 4B
- };
+ fib_node_t fib_node;
-} hicn_face_shared_t;
+ fib_node_index_t fib_entry_index;
-/**
- * @brief Structure holding the face state. 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
-{
- /* Additional space to fill with face_type specific information */
- u8 data[2 * CLIB_CACHE_LINE_BYTES - sizeof (hicn_face_shared_t)];
- hicn_face_shared_t shared;
-}
-
-hicn_face_t;
+ u32 fib_sibling;
+} hicn_face_t;
/* Pool of faces */
extern hicn_face_t *hicn_dpoi_face_pool;
@@ -107,6 +128,10 @@ extern hicn_face_t *hicn_dpoi_face_pool;
#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");
@@ -127,11 +152,6 @@ STATIC_ASSERT ((HICN_FACE_FLAGS_APPFACE_CONS >>
/**
* @brief Definition of the virtual functin table for an hICN FACE DPO.
- *
- * An hICN dpo is a combination of a dpo context (hicn_dpo_ctx or struct that
- * extends a hicn_dpo_ctx) and a strategy node. The following virtual function table
- * template that glues together the fuction to interact with the context and the
- * creating the dpo
*/
typedef struct hicn_face_vft_s
{
@@ -155,6 +175,8 @@ typedef enum
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])
@@ -167,6 +189,9 @@ extern hicn_face_vft_t *face_vft_vec;
/* Vector holding the set of face names */
extern char **face_type_names_vec;
+/* Pathlabel counter */
+extern u8 pl_index;
+
/* First face type registered in the sytem.*/
extern dpo_type_t first_type;
@@ -174,7 +199,7 @@ extern dpo_type_t first_type;
extern vlib_combined_counter_main_t *counters;
/**
- * @brief Return the face id from the face state
+ * @brief Return the face id from the face object
*
* @param Pointer to the face state
* @return face id
@@ -186,6 +211,22 @@ hicn_dpoi_get_index (hicn_face_t * face_dpoi)
}
/**
+ * @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
@@ -207,17 +248,18 @@ hicn_dpoi_idx_is_valid (hicn_face_id_t 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 (dpo_id_t * dpo)
+hicn_face_lock_with_id (hicn_face_id_t face_id)
{
hicn_face_t *face;
- face = hicn_dpoi_get_from_idx (dpo->dpoi_index);
- face->shared.locks++;
+ face = hicn_dpoi_get_from_idx (face_id);
+ face->locks++;
}
/**
@@ -226,13 +268,36 @@ hicn_face_lock (dpo_id_t * dpo)
* @param dpo Pointer to the face dpo
*/
always_inline void
-hicn_face_unlock (dpo_id_t * dpo)
+hicn_face_unlock_with_id (hicn_face_id_t face_id)
{
hicn_face_t *face;
- face = hicn_dpoi_get_from_idx (dpo->dpoi_index);
- face->shared.locks--;
+ 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
*
@@ -240,6 +305,9 @@ hicn_face_unlock (dpo_id_t * dpo)
*/
void hicn_face_module_init (vlib_main_t * vm);
+u8 * format_hicn_face (u8 * s, va_list * args);
+
+
/**
* @brief Format all the existing faces
*
@@ -259,21 +327,469 @@ u8 *format_hicn_face_all (u8 * s, int n, ...);
int hicn_face_del (hicn_face_id_t face_id);
/**
- * @brief Return the virtual function table corresponding to the face type
+ * @bried vector of faces used to collect faces having the same local address
*
- * @param face_type Type of the face
- * @return NULL if the face type does not exist
*/
-hicn_face_vft_t *hicn_face_get_vft (hicn_face_type_t face_type);
+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;
/**
- * @brief Register a new face type
+ * 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 face_type Type of the face
- * @param vft Virtual Function table for the new face type
+ * @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
*/
-void register_face_type (hicn_face_type_t face_type, hicn_face_vft_t * vft,
- char *name);
+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 = pl_index++;
+ 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__
/*
diff --git a/hicn-plugin/src/faces/face_cli.c b/hicn-plugin/src/faces/face_cli.c
index b0ed7ddae..a4092e6f4 100644
--- a/hicn-plugin/src/faces/face_cli.c
+++ b/hicn-plugin/src/faces/face_cli.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -19,9 +19,8 @@
#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_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;
@@ -46,9 +45,8 @@ hicn_face_cli_show_command_fn (vlib_main_t * vm,
deleted = 1;
else
{
- return clib_error_return (0, "%s",
- get_error_string
- (HICN_ERROR_CLI_INVAL));
+ return clib_error_return (
+ 0, "%s", get_error_string (HICN_ERROR_CLI_INVAL));
}
}
@@ -56,49 +54,43 @@ hicn_face_cli_show_command_fn (vlib_main_t * vm,
{
int idx = 0;
vec_foreach_index (idx, face_type_names_vec)
- {
- if (!strcmp (face_type_names_vec[idx], face_type_name))
- found = idx;
- }
+ {
+ 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));
+ 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);
- hicn_face_vft_t *vft = hicn_face_get_vft (face->shared.face_type);
- vlib_cli_output (vm, "%U\n", vft->format_face, face_id, 0 /*indent */ );
+ 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]);
+ 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);
+ 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);
+ s = format (s, "\n%U%-16v%16Ld\n", format_white_space, indent + 30,
+ n, v.bytes);
}
vlib_cli_output (vm, "%s\n", s);
}
@@ -107,72 +99,79 @@ hicn_face_cli_show_command_fn (vlib_main_t * vm,
if (found != ~0)
{
hicn_face_t *face;
- dpo_type_t type = (dpo_type_t) (found + first_type);
- hicn_face_vft_t *vft = hicn_face_get_vft (type);
- /* *INDENT-OFF* */
- pool_foreach(face, hicn_dpoi_face_pool,
- {
- if (!((face->shared.flags & HICN_FACE_FLAGS_DELETED) && !deleted))
- {
- if ((face->shared.face_type == type) && (face->shared.flags))
- {
- vlib_cli_output(vm, "%U\n", vft->format_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* */
+ 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);
+ }
+ }
+ }
}
else
{
hicn_face_t *face;
- /* *INDENT-OFF* */
- pool_foreach(face, hicn_dpoi_face_pool,
- {
- if (!((face->shared.flags & HICN_FACE_FLAGS_DELETED) && !deleted))
- {
- hicn_face_vft_t * vft = hicn_face_get_vft(face->shared.face_type);
- vlib_cli_output(vm, "%U\n", vft->format_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* */
+ 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);
+ }
+ }
}
}
@@ -180,14 +179,11 @@ hicn_face_cli_show_command_fn (vlib_main_t * vm,
}
/* cli declaration for 'show faces' */
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (hicn_face_cli_show_command, static) =
-{
+VLIB_CLI_COMMAND (hicn_face_cli_show_command, static) = {
.path = "hicn face show",
- .short_help = "hicn face show [<face_id>| type <ip/udp>]",
+ .short_help = "hicn face show [<face_id>]",
.function = hicn_face_cli_show_command_fn,
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/faces/face_node.c b/hicn-plugin/src/faces/face_node.c
new file mode 100644
index 000000000..5fe682bd0
--- /dev/null
+++ b/hicn-plugin/src/faces/face_node.c
@@ -0,0 +1,881 @@
+/*
+ * Copyright (c) 2020-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vnet/adj/adj.h>
+
+#include "face.h"
+#include "inlines.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
+ */
+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",
+ },
+};
+
+/**
+ * @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
+ */
+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",
+ },
+};
+
+/**** 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;
+ int ret = hicn_ops_vft[type.l1]->rewrite_interest (
+ type, &hicn->protocol, &face->nat_addr, &temp_addr);
+
+ if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED)
+ {
+ ensure_offload_flags (b0, ip46_address_is_ip4 (&face->nat_addr));
+ }
+
+ 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
+ */
+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" }
+};
+
+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
+ */
+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" }
+};
+
+/*
+ * 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
new file mode 100644
index 000000000..f5a8bf5ae
--- /dev/null
+++ b/hicn-plugin/src/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 <vlib/vlib.h>
+#include <vnet/vnet.h>
+
+/**
+ * @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
new file mode 100644
index 000000000..82c0f75b2
--- /dev/null
+++ b/hicn-plugin/src/faces/iface_node.c
@@ -0,0 +1,876 @@
+/*
+ * Copyright (c) 2020-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "face.h"
+#include "inlines.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
+ */
+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",
+ },
+};
+
+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
+ */
+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",
+ },
+};
+
+/**** 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;
+ u8 flags = hicn_get_buffer (b0)->flags;
+ u8 reset_pl = flags & HICN_BUFFER_FLAGS_FROM_CS;
+ int ret = hicn_ops_vft[type.l1]->rewrite_data (
+ type, &hicn->protocol, &(iface->nat_addr), &(temp_addr),
+ iface->pl_id, reset_pl);
+ if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED)
+ {
+ ensure_offload_flags (b0, 1 /* is_v4 */);
+ }
+}
+
+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;
+ u8 flags = hicn_get_buffer (b0)->flags;
+ u8 reset_pl = flags & HICN_BUFFER_FLAGS_FROM_CS;
+ int ret = hicn_ops_vft[type.l1]->rewrite_data (
+ type, &hicn->protocol, &(iface->nat_addr), &(temp_addr),
+ iface->pl_id, reset_pl);
+
+ if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED)
+ {
+ ensure_offload_flags (b0, 0 /* is_v4 */);
+ }
+}
+
+#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
+ */
+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" },
+};
+
+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
+ */
+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"
+
+ },
+};
+
+/*
+ * 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
new file mode 100644
index 000000000..1a7c4291b
--- /dev/null
+++ b/hicn-plugin/src/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 <vlib/vlib.h>
+#include <vnet/vnet.h>
+
+/**
+ * @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/faces/inlines.h b/hicn-plugin/src/faces/inlines.h
new file mode 100644
index 000000000..bfe56c8e6
--- /dev/null
+++ b/hicn-plugin/src/faces/inlines.h
@@ -0,0 +1,42 @@
+/*
+ * 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_INLINES_H__
+#define __HICN_FACE_INLINES_H__
+
+#include <vlib/buffer.h>
+
+always_inline void
+ensure_offload_flags (vlib_buffer_t * b, int is_v4)
+{
+ b->flags |= VNET_BUFFER_F_OFFLOAD_TCP_CKSUM;
+ b->flags |= is_v4 * VNET_BUFFER_F_OFFLOAD_IP_CKSUM;
+ size_t l3_header_size = is_v4 * sizeof(ip4_header_t) + (!is_v4) * sizeof(ip6_header_t);
+
+ /* Make sure l3_hdr_offset and l4_hdr_offset are set */
+ if (!(b->flags & VNET_BUFFER_F_L3_HDR_OFFSET_VALID))
+ {
+ b->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
+ vnet_buffer(b)->l3_hdr_offset = b->current_data;
+ }
+ if (!(b->flags & VNET_BUFFER_F_L4_HDR_OFFSET_VALID))
+ {
+ b->flags |= VNET_BUFFER_F_L4_HDR_OFFSET_VALID;
+ vnet_buffer(b)->l4_hdr_offset =
+ vnet_buffer(b)->l3_hdr_offset + l3_header_size;
+ }
+}
+
+#endif /* __HICN_FACE_INLINES_H__ */ \ No newline at end of file
diff --git a/hicn-plugin/src/faces/ip/dpo_ip.c b/hicn-plugin/src/faces/ip/dpo_ip.c
deleted file mode 100644
index d05fec1a0..000000000
--- a/hicn-plugin/src/faces/ip/dpo_ip.c
+++ /dev/null
@@ -1,90 +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 "dpo_ip.h"
-
-mhash_t hicn_face_ip_local_hashtb;
-mhash_t hicn_face_ip_remote_hashtb;
-dpo_type_t hicn_face_ip_type;
-
-hicn_face_ip_vec_t * hicn_vec_pool;
-
-const static char *const hicn_face_ip4dpoi_nodes[] = {
- "hicn-face-ip4-input",
- "hicn-face-ip4-output",
- "hicn-iface-ip4-input",
- "hicn-iface-ip4-output",
- NULL,
-};
-
-const static char *const hicn_face_ip6dpoi_nodes[] = {
- "hicn-face-ip6-input",
- "hicn-face-ip6-output",
- "hicn-iface-ip6-input",
- "hicn-iface-ip6-output",
- NULL,
-};
-
-const static char *const *const hicn_ip_nodes[DPO_PROTO_NUM] = {
- [DPO_PROTO_IP4] = hicn_face_ip4dpoi_nodes,
- [DPO_PROTO_IP6] = hicn_face_ip6dpoi_nodes
-};
-
-const static dpo_vft_t hicn_face_ip_vft = {
- .dv_lock = hicn_face_lock,
- .dv_unlock = hicn_face_unlock,
- .dv_format = format_hicn_face_ip,
-};
-
-/* Must be executed after all the strategy nodes are created */
-void
-hicn_dpo_ip_module_init (void)
-{
- mhash_init (&hicn_face_ip_local_hashtb,
- sizeof (hicn_face_ip_input_faces_t) /* value */ ,
- sizeof (hicn_face_ip_key_t) /* key */ );
- mhash_init (&hicn_face_ip_remote_hashtb,
- sizeof (hicn_face_id_t) /* value */ ,
- sizeof (hicn_face_ip_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_ip_type =
- dpo_register_new_type (&hicn_face_ip_vft, hicn_ip_nodes);
-}
-
-void
-hicn_dpo_ip_create_from_face (hicn_face_t * face, dpo_id_t * dpo,
- u16 dpoi_next_node)
-{
- hicn_face_id_t face_dpoi_id = hicn_dpoi_get_index (face);
- hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data;
- dpo_set (dpo, face->shared.face_type,
- ip46_address_is_ip4 (&ip_face->local_addr) ? DPO_PROTO_IP4 :
- DPO_PROTO_IP6, face_dpoi_id);
- dpo->dpoi_next_node = dpoi_next_node;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/hicn-plugin/src/faces/ip/dpo_ip.h b/hicn-plugin/src/faces/ip/dpo_ip.h
deleted file mode 100644
index c893c8be4..000000000
--- a/hicn-plugin/src/faces/ip/dpo_ip.h
+++ /dev/null
@@ -1,288 +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_DPO_IP_H__
-#define __HICN_DPO_IP_H__
-
-#include <vnet/vnet.h>
-#include <vnet/ip/ip4_packet.h>
-
-#include "face_ip.h"
-#include "../face.h"
-
-/**
- * @brief Initialize the internal structures of the dpo ip face module.
- */
-void hicn_dpo_ip_module_init (void);
-
-
-/**
- * @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 local 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_dpo_ip4_lock_from_local (dpo_id_t * dpo,
- u32 * in_faces_vec_id,
- u8 * hicnb_flags,
- const ip4_address_t * local_addr, u32 sw_if)
-{
- dpo->dpoi_type = DPO_FIRST;
- dpo->dpoi_proto = DPO_PROTO_NONE;
- dpo->dpoi_index = INDEX_INVALID;
- dpo->dpoi_next_node = 0;
- hicn_face_ip_input_faces_t *in_faces_vec =
- hicn_face_ip4_get_vec (local_addr, sw_if, &hicn_face_ip_local_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->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD) >>
- HICN_FACE_FLAGS_APPFACE_PROD_BIT;
-
- dpo_set (dpo, hicn_face_ip_type, DPO_PROTO_IP4, in_faces_vec->face_id);
- dpo->dpoi_next_node = ~0;
- dpo_unlock (dpo);
-
- 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 local_addr: Ip v6 local 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_dpo_ip6_lock_from_local (dpo_id_t * dpo,
- u32 * in_faces_vec_id,
- u8 * hicnb_flags,
- const ip6_address_t * local_addr, u32 sw_if)
-{
- dpo->dpoi_type = DPO_FIRST;
- dpo->dpoi_proto = DPO_PROTO_NONE;
- dpo->dpoi_index = INDEX_INVALID;
- dpo->dpoi_next_node = 0;
- hicn_face_ip_input_faces_t *in_faces_vec =
- hicn_face_ip6_get_vec (local_addr, sw_if, &hicn_face_ip_local_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->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD) >>
- HICN_FACE_FLAGS_APPFACE_PROD_BIT;
-
- dpo_set (dpo, hicn_face_ip_type, DPO_PROTO_IP6, in_faces_vec->face_id);
- dpo->dpoi_next_node = ~0;
- dpo_unlock (dpo);
-
- return HICN_ERROR_NONE;
-}
-
-
-/**
- * @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 local_addr: Ip v4 local address of the face
- * @param remote_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_dpo_ip4_add_and_lock_from_remote (dpo_id_t * dpo,
- u8 * hicnb_flags,
- const ip4_address_t * local_addr,
- const ip4_address_t * remote_addr,
- u32 sw_if, u32 node_index)
-{
- dpo->dpoi_type = DPO_FIRST;
- dpo->dpoi_proto = DPO_PROTO_NONE;
- dpo->dpoi_index = INDEX_INVALID;
- dpo->dpoi_next_node = 0;
- /*All (complete) faces are indexed by remote addess as well */
- hicn_face_t *face =
- hicn_face_ip4_get (remote_addr, sw_if, &hicn_face_ip_remote_hashtb);
-
- if (face == NULL)
- {
- hicn_face_id_t dpoi_index;
- ip46_address_t local_addr46 = to_ip46 (0, (u8 *) local_addr);
- ip46_address_t remote_addr46 = to_ip46 (0, (u8 *) remote_addr);
- hicn_iface_ip_add (&local_addr46, &remote_addr46, sw_if, &dpoi_index);
-
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
-
- dpo_set (dpo, hicn_face_ip_type, DPO_PROTO_IP4, dpoi_index);
- dpo->dpoi_next_node = node_index;
- dpo_unlock (dpo);
-
- return;
- }
-
- /* Code replicated on purpose */
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
- *hicnb_flags |=
- (face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD) >>
- HICN_FACE_FLAGS_APPFACE_PROD_BIT;
-
- hicn_face_id_t dpoi_index = hicn_dpoi_get_index (face);
- dpo_set (dpo, hicn_face_ip_type, DPO_PROTO_IP4, dpoi_index);
- dpo->dpoi_next_node = node_index;
- dpo_unlock (dpo);
-}
-
-/**
- * @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 local_addr: Ip v6 local address of the face
- * @param remote_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_dpo_ip6_add_and_lock_from_remote (dpo_id_t * dpo,
- u8 * hicnb_flags,
- const ip6_address_t * local_addr,
- const ip6_address_t * remote_addr,
- u32 sw_if, u32 node_index)
-{
- dpo->dpoi_type = DPO_FIRST;
- dpo->dpoi_proto = DPO_PROTO_NONE;
- dpo->dpoi_index = INDEX_INVALID;
- dpo->dpoi_next_node = 0;
- /*All (complete) faces are indexed by remote addess as well */
- hicn_face_t *face =
- hicn_face_ip6_get (remote_addr, sw_if, &hicn_face_ip_remote_hashtb);
-
- if (face == NULL)
- {
- hicn_face_id_t dpoi_index;
- hicn_iface_ip_add ((ip46_address_t *) local_addr,
- (ip46_address_t *) remote_addr, sw_if, &dpoi_index);
-
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
-
- dpo_set (dpo, hicn_face_ip_type, DPO_PROTO_IP4, dpoi_index);
- dpo->dpoi_next_node = node_index;
- dpo_unlock (dpo);
-
- return;
- }
- /* Code replicated on purpose */
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
- *hicnb_flags |=
- (face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD) >>
- HICN_FACE_FLAGS_APPFACE_PROD_BIT;
-
- index_t dpoi_index = hicn_dpoi_get_index (face);
- dpo_set (dpo, hicn_face_ip_type, DPO_PROTO_IP6, dpoi_index);
- dpo->dpoi_next_node = node_index;
- dpo_unlock (dpo);
-}
-
-
-/* /\** */
-/* * @brief Create an ip face and its corresponding dpo. Meant to be used for the */
-/* * control plane. */
-/* * */
-/* * @param dpo: Data plane object that point to the face created. */
-/* * @param local_addr: Ip v4 local address of the face */
-/* * @param remote_addr: Ip v4 remote address of the face */
-/* * @param sw_if: software interface id of the face */
-/* * @param adj: Ip adjacency corresponding to the remote address in the face */
-/* * @param node_index: vlib edge index to use in the packet processing */
-/* * @param flags: Flags of the face */
-/* * @param face_id: Identifier for the face (dpoi_index) */
-/* * @return HICN_ERROR_FACE_ALREADY_CREATED if the face exists, otherwise HICN_ERROR_NONE */
-/* *\/ */
-/* int hicn_dpo_ip4_create (dpo_id_t * dpo, */
-/* const ip4_address_t * local_addr, */
-/* const ip4_address_t * remote_addr, */
-/* u32 sw_if, */
-/* adj_index_t adj, */
-/* u32 node_index, */
-/* hicn_face_flags_t flags, hicn_face_id_t * face_id); */
-
-/* /\** */
-/* * @brief Create an ip face and its corresponding dpo. Meant to be used for the */
-/* * control plane. */
-/* * */
-/* * @param dpo: Data plane object that point to the face created. */
-/* * @param local_addr: Ip v6 local address of the face */
-/* * @param remote_addr: Ip v6 remote address of the face */
-/* * @param sw_if: software interface id of the face */
-/* * @param adj: Ip adjacency corresponding to the remote address in the face */
-/* * @param node_index: vlib edge index to use in the packet processing */
-/* * @param flags: Flags of the face */
-/* * @param face_id: Identifier for the face (dpoi_index) */
-/* * @return HICN_ERROR_FACE_ALREADY_CREATED if the face exists, otherwise HICN_ERROR_NONE */
-/* *\/ */
-/* int hicn_dpo_ip6_create (dpo_id_t * dpo, */
-/* const ip6_address_t * local_addr, */
-/* const ip6_address_t * remote_addr, */
-/* u32 sw_if, */
-/* adj_index_t adj, */
-/* u32 node_index, */
-/* hicn_face_flags_t flags, hicn_face_id_t * face_id); */
-
-/**
- * @brief Create a dpo from an ip face
- *
- * @param face Face from which to create the dpo
- * @param dpoi_next_node Edge index that connects a node to the iface or face nodes
- * @return the dpo
- */
-void hicn_dpo_ip_create_from_face (hicn_face_t * face, dpo_id_t * dpo,
- u16 dpoi_next_node);
-
-#endif // __HICN_DPO_IP_H__
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/hicn-plugin/src/faces/ip/face_ip.c b/hicn-plugin/src/faces/ip/face_ip.c
deleted file mode 100644
index 72599f3b3..000000000
--- a/hicn-plugin/src/faces/ip/face_ip.c
+++ /dev/null
@@ -1,571 +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 <vnet/adj/adj_midchain.h>
-#include <vnet/adj/adj.h>
-
-#include "face_ip.h"
-#include "face_ip_node.h"
-#include "dpo_ip.h"
-#include "../../strategy_dpo_manager.h"
-#include "../face.h"
-#include "../../cache_policies/cs_lru.h"
-#include "../../infra.h"
-#include "../../hicn.h"
-#include "../app/face_prod.h"
-#include "../app/face_cons.h"
-
-#include "../../mapme.h" // HICN_MAPME_EVENT_*
-#include "../../mapme_eventmgr.h" // hicn_mapme_eventmgr_process_node
-
-extern vlib_node_registration_t hicn_mapme_eventmgr_process_node;
-
-u32 strategy_face_ip4_vlib_edge;
-u32 strategy_face_ip6_vlib_edge;
-
-void
-hicn_face_ip_init (vlib_main_t * vm)
-{
- int strategy_nodes_n = hicn_strategy_get_all_available ();
-
- /* Default Strategy has index 0 and it always exists */
- strategy_face_ip4_vlib_edge = vlib_node_add_next (vm,
- hicn_strategy_node.index,
- hicn_face_ip4_output_node.index);
-
- strategy_face_ip6_vlib_edge = vlib_node_add_next (vm,
- hicn_strategy_node.index,
- hicn_face_ip6_output_node.index);
- /*
- * Create and edge between al the other strategy nodes and the
- * ip_encap nodes.
- */
- for (int i = 1; i < strategy_nodes_n; i++)
- {
- u32 temp_index4 = vlib_node_add_next (vm,
- hicn_strategy_node.index,
- hicn_face_ip4_output_node.index);
- u32 temp_index6 = vlib_node_add_next (vm,
- hicn_strategy_node.index,
- hicn_face_ip6_output_node.index);
- ASSERT (temp_index4 == strategy_face_ip4_vlib_edge);
- ASSERT (temp_index6 == strategy_face_ip6_vlib_edge);
- }
-
- u32 temp_index4 = vlib_node_add_next (vm,
- hicn_interest_hitpit_node.index,
- hicn_face_ip4_output_node.index);
- u32 temp_index6 = vlib_node_add_next (vm,
- hicn_interest_hitpit_node.index,
- hicn_face_ip6_output_node.index);
-
- ASSERT (temp_index4 == strategy_face_ip4_vlib_edge);
- ASSERT (temp_index6 == strategy_face_ip6_vlib_edge);
-
-
- hicn_dpo_ip_module_init ();
-
- register_face_type (hicn_face_ip_type, &ip_vft, "ip");
-}
-
-int
-hicn_face_ip_del (hicn_face_id_t face_id)
-{
- hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
- hicn_face_ip_t *face_ip = (hicn_face_ip_t *) face->data;
- hicn_face_ip_key_t key;
- hicn_face_ip_key_t old_key;
- hicn_face_ip_key_t old_key2;
-
- if (ip46_address_is_ip4 (&face_ip->local_addr))
- {
- hicn_face_ip4_get_key (&(face_ip->local_addr.ip4), face->shared.sw_if,
- &key);
- hicn_face_ip_input_faces_t *in_faces_vec =
- hicn_face_ip4_get_vec (&(face_ip->local_addr.ip4), face->shared.sw_if,
- &hicn_face_ip_local_hashtb);
- if (in_faces_vec != NULL)
- {
- hicn_face_ip_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_ip_local_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];
- }
- }
- hicn_face_ip4_get_key (&(face_ip->remote_addr.ip4),
- face->shared.sw_if, &key);
- mhash_unset (&hicn_face_ip_remote_hashtb, &key,
- (uword *) & old_key2);
- }
- }
- else
- {
- hicn_face_ip6_get_key (&(face_ip->local_addr.ip6), face->shared.sw_if,
- &key);
-
- hicn_face_ip_input_faces_t *in_faces_vec =
- hicn_face_ip6_get_vec (&(face_ip->local_addr.ip6), face->shared.sw_if,
- &hicn_face_ip_local_hashtb);
- if (in_faces_vec != NULL)
- {
- hicn_face_ip_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 (hicn_vec_pool, vec);
- mhash_unset (&hicn_face_ip_local_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];
- }
- }
- hicn_face_ip6_get_key (&(face_ip->remote_addr.ip6),
- face->shared.sw_if, &key);
- mhash_unset (&hicn_face_ip_remote_hashtb, &key,
- (uword *) & old_key);
- }
- }
- return hicn_face_del (face_id);
-}
-
-/**
- * @brief Helper for handling midchain adjacencies
- */
-void
-face_midchain_fixup_t (vlib_main_t * vm,
- const struct ip_adjacency_t_ *adj,
- vlib_buffer_t * b0, const void *data)
-{
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = 0;
-};
-
-/**
- * @brief Build a rewrite string for the face.
- */
-static u8 *
-face_build_rewrite_i (void)
-{
- /*
- * passing the adj code a NULL rewrite means 'i don't have one cos
- * t'other end is unresolved'. That's not the case here. For the mpls
- * tunnel there are just no bytes of encap to apply in the adj. We'll impose
- * the label stack once we choose a path. So return a zero length rewrite.
- */
- u8 *rewrite = NULL;
-
- vec_validate (rewrite, 0);
- vec_reset_length (rewrite);
-
- return (rewrite);
-}
-
-always_inline int
-hicn_face_ip_find_adj (const ip46_address_t * remote_addr,
- int sw_if, adj_index_t * adj)
-{
- fib_prefix_t fib_pfx;
- fib_node_index_t fib_entry_index;
- fib_prefix_from_ip46_addr (remote_addr, &fib_pfx);
- fib_pfx.fp_len = ip46_address_is_ip4 (remote_addr) ? 32 : 128;
- vnet_link_t link_type =
- ip46_address_is_ip4 (&fib_pfx.fp_addr) ? VNET_LINK_IP4 : VNET_LINK_IP6;
- *adj = adj_nbr_find (fib_pfx.fp_proto, link_type, &fib_pfx.fp_addr, sw_if);
-
- if (*adj == ADJ_INDEX_INVALID)
- {
- u32 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 (fib_index, &fib_pfx);
-
- if (fib_entry_index == (FIB_NODE_INDEX_INVALID))
- return HICN_ERROR_FACE_IP_ADJ_NOT_FOUND;
-
- *adj = fib_entry_get_adj (fib_entry_index);
- ip_adjacency_t *temp = NULL;
- if (*adj != ~0)
- temp = adj_get (*adj);
-
- if (temp == NULL || temp->lookup_next_index <= IP_LOOKUP_NEXT_MIDCHAIN)
- {
- if (sw_if != ~0)
- *adj =
- adj_nbr_add_or_lock (fib_pfx.fp_proto, link_type, remote_addr,
- sw_if);
- else
- return HICN_ERROR_FACE_IP_ADJ_NOT_FOUND;
- }
- else
- {
- adj_nbr_midchain_update_rewrite (*adj, &face_midchain_fixup_t, NULL,
- ADJ_FLAG_NONE,
- face_build_rewrite_i ());
- adj_midchain_delegate_stack (*adj, fib_index, &fib_pfx);
- }
- }
-
- return HICN_ERROR_NONE;
-}
-
-/*
- * 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_ip_add (const ip46_address_t * local_addr,
- const ip46_address_t * remote_addr,
- int sw_if, hicn_face_id_t * pfaceid, u8 is_app_prod)
-{
- dpo_proto_t dpo_proto;
-
- /* Check if we found at least one ip address */
- if (ip46_address_is_zero (remote_addr))
- return HICN_ERROR_FACE_NO_GLOBAL_IP;
-
- hicn_face_flags_t flags = (hicn_face_flags_t) 0;
- flags |= HICN_FACE_FLAGS_FACE;
-
- hicn_face_t *face;
- if (ip46_address_is_ip4 (local_addr))
- {
- face =
- hicn_face_ip4_get (&(remote_addr->ip4), sw_if,
- &hicn_face_ip_remote_hashtb);
-
- /* If remote matches the face we need to check if it is an incomplete face */
- if (face == NULL)
- {
- hicn_iface_ip_add (local_addr, remote_addr, sw_if, pfaceid);
- face = hicn_dpoi_get_from_idx (*pfaceid);
- }
- else
- {
- *pfaceid = hicn_dpoi_get_index (face);
- }
-
- if (!(face->shared.flags & HICN_FACE_FLAGS_IFACE))
- return HICN_ERROR_FACE_ALREADY_CREATED;
-
- hicn_face_ip_key_t key;
- hicn_face_ip4_get_key (&(local_addr->ip4), sw_if, &key);
-
- hicn_face_ip_input_faces_t *in_faces =
- hicn_face_ip4_get_vec (&(local_addr->ip4), sw_if,
- &hicn_face_ip_local_hashtb);
-
- if (in_faces == NULL)
- {
- adj_index_t adj;
- int ret = hicn_face_ip_find_adj (remote_addr, sw_if, &adj);
- if (ret != HICN_ERROR_NONE)
- return ret;
-
- hicn_face_ip_input_faces_t in_faces_temp;
- hicn_face_ip_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);
-
- hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data;
- clib_memcpy (&ip_face->local_addr, local_addr,
- sizeof (ip4_address_t));
- clib_memcpy (&ip_face->remote_addr, remote_addr,
- sizeof (ip4_address_t));
- face->shared.sw_if = sw_if;
- face->shared.flags = flags;
- face->shared.adj = adj;
-
- dpo_proto = DPO_PROTO_IP4;
-
- in_faces_temp.face_id = *pfaceid;
-
- mhash_set_mem (&hicn_face_ip_local_hashtb, &key,
- (uword *) & in_faces_temp, 0);
- }
- else
- {
- hicn_face_ip_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;
-
- adj_index_t adj;
- int ret = hicn_face_ip_find_adj (remote_addr, sw_if, &adj);
- if (ret != HICN_ERROR_NONE)
- return ret;
-
- vec_add1 (*vec, *pfaceid);
-
- hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data;
- clib_memcpy (&ip_face->local_addr, local_addr,
- sizeof (ip4_address_t));
- clib_memcpy (&ip_face->remote_addr, remote_addr,
- sizeof (ip4_address_t));
- face->shared.sw_if = sw_if;
- face->shared.flags = flags;
- face->shared.adj = adj;
-
- dpo_proto = DPO_PROTO_IP4;
-
- mhash_set_mem (&hicn_face_ip_local_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;
- }
- }
- }
- else
- {
- face =
- hicn_face_ip6_get (&(remote_addr->ip6), sw_if,
- &hicn_face_ip_remote_hashtb);
-
- /* If remote matches the face is a iface */
- if (face == NULL)
- {
- hicn_iface_ip_add (local_addr, remote_addr, sw_if, pfaceid);
- face = hicn_dpoi_get_from_idx (*pfaceid);
- }
- else
- {
- *pfaceid = hicn_dpoi_get_index (face);
- }
-
- if (!(face->shared.flags & HICN_FACE_FLAGS_IFACE))
- return HICN_ERROR_FACE_ALREADY_CREATED;
-
- hicn_face_ip_key_t key;
- hicn_face_ip6_get_key (&(local_addr->ip6), sw_if, &key);
-
- hicn_face_ip_input_faces_t *in_faces =
- hicn_face_ip6_get_vec (&(local_addr->ip6), sw_if,
- &hicn_face_ip_local_hashtb);
-
- if (in_faces == NULL)
- {
- adj_index_t adj;
- int ret = hicn_face_ip_find_adj (remote_addr, sw_if, &adj);
- if (ret != HICN_ERROR_NONE)
- return ret;
-
- hicn_face_ip_input_faces_t in_faces_temp;
- hicn_face_ip_vec_t *vec;
- pool_get (hicn_vec_pool, vec);
- vec_alloc (*vec, 1);
- u32 index = vec - hicn_vec_pool;
- in_faces_temp.vec_id = index;
- vec_add1 (*vec, *pfaceid);
-
- hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data;
- clib_memcpy (&ip_face->local_addr, local_addr,
- sizeof (ip6_address_t));
- clib_memcpy (&ip_face->remote_addr, remote_addr,
- sizeof (ip6_address_t));
- face->shared.sw_if = sw_if;
- face->shared.flags = flags;
- face->shared.adj = adj;
-
- dpo_proto = DPO_PROTO_IP6;
-
- in_faces_temp.face_id = *pfaceid;
-
- mhash_set_mem (&hicn_face_ip_local_hashtb, &key,
- (uword *) & in_faces_temp, 0);
- }
- else
- {
- hicn_face_ip_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;
-
- adj_index_t adj;
- int ret = hicn_face_ip_find_adj (remote_addr, sw_if, &adj);
- if (ret != HICN_ERROR_NONE)
- return ret;
-
- vec_add1 (*vec, *pfaceid);
-
- hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data;
- clib_memcpy (&ip_face->local_addr, local_addr,
- sizeof (ip6_address_t));
- clib_memcpy (&ip_face->remote_addr, remote_addr,
- sizeof (ip6_address_t));
- face->shared.sw_if = sw_if;
- face->shared.flags = flags;
- face->shared.adj = adj;
-
- dpo_proto = DPO_PROTO_IP6;
-
- mhash_set_mem (&hicn_face_ip_local_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)
- {
- .prefix = 0,
- .dpo = (dpo_id_t)
- {
- .dpoi_type = hicn_face_ip_type,
- .dpoi_proto = dpo_proto,
- .dpoi_next_node = 0,
- .dpoi_index = *pfaceid,
- }
- };
- /* *INDENT-ON* */
-
- return HICN_ERROR_NONE;
-}
-
-u8 *
-format_hicn_face_ip (u8 * s, va_list * args)
-{
- index_t index = va_arg (*args, index_t);
- CLIB_UNUSED (u32 indent) = va_arg (*args, u32);
- hicn_face_t *face;
- hicn_face_ip_t *ip_face;
- ip_adjacency_t *adj;
- vnet_main_t *vnm = vnet_get_main ();
-
- face = hicn_dpoi_get_from_idx (index);
- ip_face = (hicn_face_ip_t *) face->data;
-
- if (face->shared.flags & HICN_FACE_FLAGS_FACE)
- {
- ASSERT (face->shared.adj != (adj_index_t) ~ 0);
- adj = adj_get (face->shared.adj);
-
- 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, "type IP local %U ",
- format_ip46_address, &ip_face->local_addr, IP46_TYPE_ANY);
- s =
- format (s, "remote %U ", format_ip46_address, &ip_face->remote_addr,
- IP46_TYPE_ANY);
- s = format (s, "%U", format_vnet_link, adj->ia_link);
-
- vnet_sw_interface_t *sw_int =
- vnet_get_sw_interface_or_null (vnm, face->shared.sw_if);
- if (sw_int != NULL)
- s = format (s, " dev %U", format_vnet_sw_interface_name, vnm, sw_int);
-
-
- if ((face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD))
- s = format (s, " %U", format_hicn_face_prod, face_id, 0);
- else if ((face->shared.flags & HICN_FACE_FLAGS_APPFACE_CONS))
- s = format (s, " %U", format_hicn_face_cons, face_id, 0);
-
- if ((face->shared.flags & HICN_FACE_FLAGS_DELETED))
- s = format (s, " (deleted)");
- }
- 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, "type IP local %U remote %U",
- format_ip46_address, &ip_face->local_addr, IP46_TYPE_ANY,
- format_ip46_address, &ip_face->remote_addr, IP46_TYPE_ANY);
-
- vnet_sw_interface_t *sw_int =
- vnet_get_sw_interface_or_null (vnm, face->shared.sw_if);
- if (sw_int != NULL)
- s = format (s, " dev %U", format_vnet_sw_interface_name, vnm, sw_int);
-
- if ((face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD))
- s = format (s, " %U", format_hicn_face_prod, face_id, 0);
- else if ((face->shared.flags & HICN_FACE_FLAGS_APPFACE_CONS))
- s = format (s, " %U", format_hicn_face_cons, face_id, 0);
-
- if ((face->shared.flags & HICN_FACE_FLAGS_DELETED))
- s = format (s, " (deleted)");
- }
-
- return s;
-}
-
-void
-hicn_face_ip_get_dpo (hicn_face_t * face, dpo_id_t * dpo)
-{
-
- hicn_face_ip_t *face_ip = (hicn_face_ip_t *) face->data;
- return hicn_dpo_ip_create_from_face (face, dpo,
- ip46_address_is_ip4
- (&face_ip->remote_addr) ?
- strategy_face_ip4_vlib_edge :
- strategy_face_ip6_vlib_edge);
-}
-
-hicn_face_vft_t ip_vft = {
- .format_face = format_hicn_face_ip,
- .hicn_face_del = hicn_face_ip_del,
- .hicn_face_get_dpo = hicn_face_ip_get_dpo,
-};
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/hicn-plugin/src/faces/ip/face_ip.h b/hicn-plugin/src/faces/ip/face_ip.h
deleted file mode 100644
index 74f3a83dc..000000000
--- a/hicn-plugin/src/faces/ip/face_ip.h
+++ /dev/null
@@ -1,310 +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_FACE_IP_H__
-#define __HICN_FACE_IP_H__
-
-#include <vlib/vlib.h>
-#include <vnet/vnet.h>
-#include "../face.h"
-#include "../../cache_policies/cs_policy.h"
-
-/**
- * @file
- *
- * @brief IP face
- *
- * A face is carried through nodes as a dpo. The face state is the object
- * pointed by the dpoi_index in the dpo_id_t (see
- * https://docs.fd.io/vpp/18.07/d0/d37/dpo_8h_source.html)
- */
-typedef struct hicn_ip_face_t_
-{
- /**
- * The headers to paint, in packet painting order
- */
- /* Local address of the interface sw_if */
- ip46_address_t local_addr;
-
- /* Remote address of neighbor */
- ip46_address_t remote_addr;
-
-} hicn_face_ip_t;
-
-/**
- * @bried vector of faces used to collect faces having the same local address
- *
- */
-typedef hicn_face_id_t *hicn_face_ip_vec_t;
-
-typedef struct hicn_ip_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_ip_input_faces_t;
-
-/**
- * Hash tables that indexes a face by local address. For fast lookup when an
- * data arrives.
- */
-extern mhash_t hicn_face_ip_local_hashtb;
-
-/**
- * Hash tables that indexes a face by remote address. For fast lookup when an
- * interest arrives.
- */
-extern mhash_t hicn_face_ip_remote_hashtb;
-
-/**
- * Pool containing the vector of possible incoming faces.
- */
-extern hicn_face_ip_vec_t *hicn_vec_pool;
-
-/**
- * Key definition for the mhash table. An ip face is uniquely identified by ip
- * address and the interface id. 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.
- */
-typedef struct hicn_face_ip_key_s
-{
- ip46_address_t addr;
- u32 sw_if;
-} hicn_face_ip_key_t;
-
-
-extern hicn_face_type_t hicn_face_ip_type;
-extern hicn_face_vft_t ip_vft;
-
-/**
- * @brief Create the key object for the mhash. Fill in the key object with the
- * expected values.
- *
- * @param addr Local or remote ip v6 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_ip6_get_key (const ip6_address_t * addr,
- u32 sw_if, hicn_face_ip_key_t * key)
-{
- key->addr.ip6 = *addr;
- key->sw_if = sw_if;
-}
-
-
-/**
- * @brief Create the key object for the mhash. Fill in the key object with the
- * expected values.
- *
- * @param addr Local or remote ip v4 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_ip4_get_key (const ip4_address_t * addr,
- u32 sw_if, hicn_face_ip_key_t * key)
-{
- ip46_address_set_ip4 (&(key->addr), addr);
- key->sw_if = sw_if;
-}
-
-/**
- * @brief Get the dpoi 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_t *
-hicn_face_ip4_get (const ip4_address_t * addr, u32 sw_if, mhash_t * hashtb)
-{
- hicn_face_ip_key_t key;
-
- hicn_face_ip4_get_key (addr, sw_if, &key);
-
- hicn_face_id_t *dpoi_index = (hicn_face_id_t *) mhash_get (hashtb,
- &key);
-
- return dpoi_index == NULL ? NULL : hicn_dpoi_get_from_idx (*dpoi_index);
-}
-
-/**
- * @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_ip_input_faces_t *
-hicn_face_ip4_get_vec (const ip4_address_t * addr, u32 sw_if,
- mhash_t * hashtb)
-{
- hicn_face_ip_key_t key;
-
- hicn_face_ip4_get_key (addr, sw_if, &key);
- return (hicn_face_ip_input_faces_t *) mhash_get (hashtb, &key);
-}
-
-/**
- * @brief Get the vector of faces from the ip v6 address. Does not add any lock.
- *
- * @param addr Ip v6 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_ip_input_faces_t *
-hicn_face_ip6_get_vec (const ip6_address_t * addr, u32 sw_if,
- mhash_t * hashtb)
-{
- hicn_face_ip_key_t key;
-
- hicn_face_ip6_get_key (addr, sw_if, &key);
- return (hicn_face_ip_input_faces_t *) mhash_get (hashtb, &key);
-}
-
-/**
- * @brief Get the dpoi from the ip v6 address. Does not add any lock.
- *
- * @param addr Ip v6 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_ip6_get (const ip6_address_t * addr, u32 sw_if, mhash_t * hashtb)
-{
- hicn_face_ip_key_t key;
-
- hicn_face_ip6_get_key (addr, sw_if, &key);
-
- hicn_face_id_t *dpoi_index = (hicn_face_id_t *) mhash_get (hashtb,
- &key);
-
- return dpoi_index == NULL ? NULL : hicn_dpoi_get_from_idx (*dpoi_index);
-}
-
-/**
- * @brief Create a new face ip. API for other modules (e.g., routing)
- *
- * @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 is_app_face Boolean to set the face as an application 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_ip_add (const ip46_address_t * local_addr,
- const ip46_address_t * remote_addr,
- int swif, 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_ip_add (const ip46_address_t * local_addr,
- const ip46_address_t * remote_addr,
- int sw_if, hicn_face_id_t * pfaceid)
-{
- hicn_face_t *face;
- pool_get (hicn_dpoi_face_pool, face);
-
- hicn_face_ip_t *ip_face = (hicn_face_ip_t *) (face->data);
-
- clib_memcpy (&(ip_face->local_addr.ip6), local_addr,
- sizeof (ip6_address_t));
- clib_memcpy (&(ip_face->remote_addr.ip6), remote_addr,
- sizeof (ip6_address_t));
- face->shared.sw_if = sw_if;
-
- face->shared.adj = ADJ_INDEX_INVALID;
- face->shared.pl_id = (u16) 0;
- face->shared.face_type = hicn_face_ip_type;
- face->shared.flags = HICN_FACE_FLAGS_IFACE;
- face->shared.locks = 1;
-
- hicn_face_ip_key_t key;
- hicn_face_ip6_get_key (&(remote_addr->ip6), sw_if, &key);
- *pfaceid = hicn_dpoi_get_index (face);
-
- mhash_set_mem (&hicn_face_ip_remote_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);
- }
-}
-
-/**
- * @brief Delete an ip 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_ip_del (hicn_face_id_t face_id);
-
-/**
- * @brief Format a IP 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_ip (u8 * s, va_list * args);
-
-/**
- * @brief Create a dpo from an ip face
- *
- * @param face Face from which to create the dpo
- * @return the dpo
- */
-void hicn_face_ip_get_dpo (hicn_face_t * face, dpo_id_t * dpo);
-
-#endif // __HICN_FACE_IP_H__
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/hicn-plugin/src/faces/ip/face_ip_cli.c b/hicn-plugin/src/faces/ip/face_ip_cli.c
deleted file mode 100644
index 4c4986f97..000000000
--- a/hicn-plugin/src/faces/ip/face_ip_cli.c
+++ /dev/null
@@ -1,208 +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 <vnet/vnet.h>
-#include <vnet/dpo/dpo.h>
-#include <vlib/vlib.h>
-
-#include "face_ip.h"
-#include "dpo_ip.h"
-#include "../face.h"
-
-#define HICN_FACE_NONE 0
-#define HICN_FACE_DELETE 1
-#define HICN_FACE_ADD 2
-
-static clib_error_t *
-hicn_face_ip_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 ();
- ip46_address_t local_addr;
- ip46_address_t remote_addr;
- hicn_face_id_t face_id = HICN_FACE_NULL;
- int ret = HICN_ERROR_NONE;
- int sw_if;
- int face_op = HICN_FACE_NONE;
-
- ip46_address_reset (&local_addr);
- /* 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"))
- {
- if (unformat (line_input, "id %d", &face_id))
- face_op = HICN_FACE_DELETE;
- else
- {
- return clib_error_return (0, "missing face id");
- }
- }
- else if (unformat (line_input, "add"))
- {
- face_op = HICN_FACE_ADD;
- if (unformat (line_input, "local %U",
- unformat_ip46_address, &local_addr, IP46_TYPE_ANY));
-
- if (unformat (line_input, "remote %U intfc %U",
- unformat_ip46_address, &remote_addr,
- IP46_TYPE_ANY, unformat_vnet_sw_interface, vnm,
- &sw_if));
- 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_id != HICN_FACE_NULL)
- {
-
- if (!hicn_dpoi_idx_is_valid (face_id))
- {
- return clib_error_return (0, "%s, face_id %d not valid",
- get_error_string (ret), face_id);
- }
- }
-
- int rv;
- switch (face_op)
- {
- case HICN_FACE_ADD:
-
- /* Check for presence of next hop address */
- if ((remote_addr.as_u64[0] == (u64) 0)
- && (remote_addr.as_u64[1] == (u64) 0))
- {
- return clib_error_return (0, "next hop address not specified");
- }
-
- if (ip46_address_is_zero (&local_addr))
- {
- if (!vnet_sw_interface_is_valid (vnm, sw_if))
- return clib_error_return (0, "interface not valid");
-
- if (ip46_address_is_ip4 (&remote_addr))
- {
- ip_interface_address_t *interface_address;
- ip4_address_t *addr =
- ip4_interface_address_matching_destination (&ip4_main,
- &remote_addr.ip4,
- sw_if,
- &interface_address);
-
- if (addr == NULL)
- addr = ip4_interface_first_address (&ip4_main,
- sw_if,
- &interface_address);
-
- if (addr == NULL)
- return clib_error_return (0,
- "no valid ip address on interface %d",
- sw_if);
-
- ip46_address_set_ip4 (&local_addr, addr);
- }
- else
- {
- ip_interface_address_t *interface_address;
- ip6_interface_address_matching_destination (&ip6_main,
- &remote_addr.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)
- return clib_error_return (0,
- "no valid ip address on interface %d",
- sw_if);
-
- ip46_address_set_ip6 (&local_addr, addr);
- }
- }
-
- rv = hicn_face_ip_add (&local_addr, &remote_addr, sw_if, &face_id, 0);
-
- if (rv == HICN_ERROR_NONE)
- {
- vlib_cli_output (vm, "Face id: %d", face_id);
- }
- else
- {
- return clib_error_return (0, get_error_string (rv));
- }
- break;
- case HICN_FACE_DELETE:
- rv = hicn_face_ip_del (face_id);
- if (rv == HICN_ERROR_NONE)
- {
- vlib_cli_output (vm, "Face %d deleted", face_id);
- }
- 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_ip_cli_set_command, static) =
-{
- .path = "hicn face ip",
- .short_help = "hicn face ip {add [local <src_address>] remote <dst_address> intfc <sw_if>} | {del id <face_id>}",
- .function = hicn_face_ip_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/ip/face_ip_node.c b/hicn-plugin/src/faces/ip/face_ip_node.c
deleted file mode 100644
index 0eeeab6fb..000000000
--- a/hicn-plugin/src/faces/ip/face_ip_node.c
+++ /dev/null
@@ -1,993 +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 <vnet/adj/adj.h>
-
-#include "face_ip.h"
-#include "face_ip_node.h"
-#include "dpo_ip.h"
-#include "../app/face_prod.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 hicn_face_ip4_input_node;
-vlib_node_registration_t hicn_face_ip4_output_node;
-vlib_node_registration_t hicn_face_ip6_input_node;
-vlib_node_registration_t hicn_face_ip6_output_node;
-
-#define ip_v4 4
-#define ip_v6 6
-
-static char *hicn_face_ip4_input_error_strings[] = {
-#define _(sym, string) string,
- foreach_hicnfwd_error
-#undef _
-};
-
-static char *hicn_face_ip6_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];
-}
-hicn_face_ip4_input_trace_t;
-
-typedef enum
-{
- HICN_FACE_IP4_INPUT_NEXT_DATA,
- HICN_FACE_IP4_INPUT_NEXT_MAPME,
- HICN_FACE_IP4_INPUT_NEXT_ERROR_DROP,
- HICN_FACE_IP4_INPUT_N_NEXT,
-} hicn_face_ip4_input_next_t;
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
- u8 packet_data[60];
-}
-hicn_face_ip6_input_trace_t;
-
-typedef enum
-{
- HICN_FACE_IP6_INPUT_NEXT_DATA,
- HICN_FACE_IP6_INPUT_NEXT_MAPME,
- HICN_FACE_IP6_INPUT_NEXT_ERROR_DROP,
- HICN_FACE_IP6_INPUT_N_NEXT,
-} hicn_face_ip6_input_next_t;
-
-#define NEXT_MAPME_IP4 HICN_FACE_IP4_INPUT_NEXT_MAPME
-#define NEXT_MAPME_IP6 HICN_FACE_IP6_INPUT_NEXT_MAPME
-#define NEXT_DATA_IP4 HICN_FACE_IP4_INPUT_NEXT_DATA
-#define NEXT_DATA_IP6 HICN_FACE_IP6_INPUT_NEXT_DATA
-
-#define NEXT_ERROR_DROP_IP4 HICN_FACE_IP4_INPUT_NEXT_ERROR_DROP
-#define NEXT_ERROR_DROP_IP6 HICN_FACE_IP6_INPUT_NEXT_ERROR_DROP
-
-#define IP_HEADER_4 ip4_header_t
-#define IP_HEADER_6 ip6_header_t
-
-#define LOCK_FROM_LOCAL_IP4 hicn_dpo_ip4_lock_from_local
-#define LOCK_FROM_LOCAL_IP6 hicn_dpo_ip6_lock_from_local
-
-#define TRACE_INPUT_PKT_IP4 hicn_face_ip4_input_trace_t
-#define TRACE_INPUT_PKT_IP6 hicn_face_ip6_input_trace_t
-
-/*
- * NOTE: Both hicn_face_ip4_input_node_fn and hicn_face_ip6_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_FROM_LOCAL_IP##ipv \
- (&(hicnb0->face_dpo_id), \
- &(hicnb0->in_faces_vec_id), \
- &hicnb0->flags, \
- &(ip_hdr->dst_address), \
- vnet_buffer (b0)->sw_if_index[VLIB_RX]); \
- \
- if ( PREDICT_FALSE(ret != HICN_ERROR_NONE) ) \
- next0 = NEXT_ERROR_DROP_IP##ipv; \
- else \
- { \
- vlib_increment_combined_counter ( \
- &counters[hicnb0->face_dpo_id.dpoi_index \
- * 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_FROM_LOCAL_IP##ipv \
- (&(hicnb0->face_dpo_id), \
- &(hicnb0->in_faces_vec_id), \
- &hicnb0->flags, \
- &(ip_hdr0->dst_address), \
- vnet_buffer (b0)->sw_if_index[VLIB_RX]); \
- \
- ret1 = LOCK_FROM_LOCAL_IP##ipv \
- (&(hicnb1->face_dpo_id), \
- &(hicnb1->in_faces_vec_id), \
- &hicnb1->flags, \
- &(ip_hdr1->dst_address), \
- vnet_buffer (b1)->sw_if_index[VLIB_RX]); \
- \
- if ( PREDICT_FALSE(ret0 != HICN_ERROR_NONE) ) \
- next0 = NEXT_ERROR_DROP_IP##ipv; \
- else \
- { \
- vlib_increment_combined_counter ( \
- &counters[hicnb0->face_dpo_id.dpoi_index \
- * 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_dpo_id.dpoi_index \
- * 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
-hicn_face_ip4_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 *
-hicn_face_ip4_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 *);
- hicn_face_ip4_input_trace_t *t =
- va_arg (*args, hicn_face_ip4_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(hicn_face_ip4_input_node) =
-{
- .function = hicn_face_ip4_input_node_fn,
- .name = "hicn-face-ip4-input",
- .vector_size = sizeof(u32),
- .format_trace = hicn_face_ip4_input_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(hicn_face_ip4_input_error_strings),
- .error_strings = hicn_face_ip4_input_error_strings,
- .n_next_nodes = HICN_FACE_IP4_INPUT_N_NEXT,
- /* edit / add dispositions here */
- .next_nodes =
- {
- [HICN_FACE_IP4_INPUT_NEXT_DATA] = "hicn-data-pcslookup",
- [HICN_FACE_IP4_INPUT_NEXT_MAPME] = "hicn-mapme-ack",
- [HICN_FACE_IP4_INPUT_NEXT_ERROR_DROP] = "error-drop",
- },
-};
-/* *INDENT-ON* */
-
-/**
- * @brief IPv6 face input node function
- * @see hicn_face_ip4_input_node_fn
- */
-static uword
-hicn_face_ip6_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 *
-hicn_face_ip6_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 *);
- hicn_face_ip6_input_trace_t *t =
- va_arg (*args, hicn_face_ip6_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(hicn_face_ip6_input_node) =
-{
- .function = hicn_face_ip6_input_node_fn,
- .name = "hicn-face-ip6-input",
- .vector_size = sizeof(u32),
- .format_trace = hicn_face_ip6_input_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(hicn_face_ip6_input_error_strings),
- .error_strings = hicn_face_ip6_input_error_strings,
- .n_next_nodes = HICN_FACE_IP6_INPUT_N_NEXT,
- /* edit / add dispositions here */
- .next_nodes =
- {
- [HICN_FACE_IP6_INPUT_NEXT_DATA] = "hicn-data-pcslookup",
- [HICN_FACE_IP6_INPUT_NEXT_MAPME] = "hicn-mapme-ack",
- [HICN_FACE_IP6_INPUT_NEXT_ERROR_DROP] = "error-drop",
- },
-};
-/* *INDENT-ON* */
-
-/**** FACE OUTPUT *****/
-
-typedef enum
-{
- HICN_FACE_IP4_NEXT_ECHO_REPLY = IP4_LOOKUP_N_NEXT,
- HICN_FACE_IP4_N_NEXT,
-} hicn_face_ip4_next_t;
-
-typedef enum
-{
- HICN_FACE_IP6_NEXT_ECHO_REPLY = IP6_LOOKUP_N_NEXT,
- HICN_FACE_IP6_N_NEXT,
-} hicn_face_ip6_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 = HICN_FACE_IP4_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 = HICN_FACE_IP6_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->shared.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,
- &ip_face->local_addr, &temp_addr);
-
- int is_iface = 0;
- ip_adjacency_t *adj;
- if (PREDICT_FALSE (face->shared.adj == ~0))
- is_iface = 1;
- else
- adj = adj_get (face->shared.adj);
-
- /* In case the adj is not complete, we look if a better one exists, otherwise we send an arp request
- * This is necessary to account for the case in which when we create a face, there isn't a /128(/32) adjacency and we match with a more general route which is in glean state
- * In this case in fact, the general route will not be update upone receiving of a arp or neighbour responde, but a new /128(/32) will be created
- */
- if (PREDICT_FALSE
- (is_iface || adj->lookup_next_index < IP_LOOKUP_NEXT_REWRITE))
- {
- fib_prefix_t fib_pfx;
- fib_node_index_t fib_entry_index;
- fib_prefix_from_ip46_addr (&ip_face->remote_addr, &fib_pfx);
- fib_pfx.fp_len = ip46_address_is_ip4(&ip_face->remote_addr)? 32 : 128;
-
- u32 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 (fib_index, &fib_pfx);
-
- face->shared.adj = fib_entry_get_adj (fib_entry_index);
- face->shared.flags &= ~HICN_FACE_FLAGS_IFACE;
- face->shared.flags |= HICN_FACE_FLAGS_FACE;
-
- adj = adj_get (face->shared.adj);
-
- hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol,
- &ip_face->remote_addr, &temp_addr,
- 0);
- }
-
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = face->shared.adj;
- *next = adj->lookup_next_index;
-
-
-}
-
-static char *hicn_face_ip4_output_error_strings[] = {
-#define _(sym, string) string,
- foreach_hicnfwd_error
-#undef _
-};
-
-static char *hicn_face_ip6_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];
-}
-hicn_face_ip4_output_trace_t;
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
- u8 packet_data[60];
-}
-hicn_face_ip6_output_trace_t;
-
-#define TRACE_OUTPUT_PKT_IP4 hicn_face_ip4_output_trace_t
-#define TRACE_OUTPUT_PKT_IP6 hicn_face_ip6_output_trace_t
-
-#define face_output_x1(ipv) \
- do { \
- vlib_buffer_t *b0; \
- u32 bi0; \
- u32 next0 = IP_LOOKUP_NEXT_DROP; \
- 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 = IP_LOOKUP_NEXT_DROP; \
- u32 next1 = IP_LOOKUP_NEXT_DROP; \
- 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
-hicn_face_ip4_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 *
-hicn_face_ip4_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 *);
- hicn_face_ip4_output_trace_t *t =
- va_arg (*args, hicn_face_ip4_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(hicn_face_ip4_output_node) =
-{
- .function = hicn_face_ip4_output_node_fn,
- .name = "hicn-face-ip4-output",
- .vector_size = sizeof(u32),
- .format_trace = hicn_face_ip4_output_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(hicn_face_ip4_output_error_strings),
- .error_strings = hicn_face_ip4_output_error_strings,
- .n_next_nodes = HICN_FACE_IP4_N_NEXT,
- /* Reusing the list of nodes from lookup to be compatible with arp */
- .next_nodes =
- {
- [IP_LOOKUP_NEXT_DROP] = "ip4-drop",
- [IP_LOOKUP_NEXT_PUNT] = "ip4-punt",
- [IP_LOOKUP_NEXT_LOCAL] = "ip4-local",
- [IP_LOOKUP_NEXT_ARP] = "ip4-arp",
- [IP_LOOKUP_NEXT_GLEAN] = "ip4-glean",
- [IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite",
- [IP_LOOKUP_NEXT_MCAST] = "ip4-rewrite-mcast",
- [IP_LOOKUP_NEXT_BCAST] = "ip4-rewrite-bcast",
- [IP_LOOKUP_NEXT_MIDCHAIN] = "ip4-midchain",
- [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip4-mcast-midchain",
- [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error",
- [HICN_FACE_IP4_NEXT_ECHO_REPLY] = "hicn-face-ip4-input",
- }
-};
-/* *INDENT-ON* */
-
-
-static uword
-hicn_face_ip6_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 *
-hicn_face_ip6_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 *);
- hicn_face_ip6_output_trace_t *t =
- va_arg (*args, hicn_face_ip6_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(hicn_face_ip6_output_node) =
-{
- .function = hicn_face_ip6_output_node_fn,
- .name = "hicn-face-ip6-output",
- .vector_size = sizeof(u32),
- .format_trace = hicn_face_ip6_output_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(hicn_face_ip6_output_error_strings),
- .error_strings = hicn_face_ip6_output_error_strings,
- .n_next_nodes = HICN_FACE_IP6_N_NEXT,
- /* Reusing the list of nodes from lookup to be compatible with neighbour discovery */
- .next_nodes =
- {
- [IP_LOOKUP_NEXT_DROP] = "ip6-drop",
- [IP_LOOKUP_NEXT_PUNT] = "ip6-punt",
- [IP_LOOKUP_NEXT_LOCAL] = "ip6-local",
- [IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor",
- [IP_LOOKUP_NEXT_GLEAN] = "ip6-glean",
- [IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite",
- [IP_LOOKUP_NEXT_BCAST] = "ip6-rewrite-bcast",
- [IP_LOOKUP_NEXT_MCAST] = "ip6-rewrite-mcast",
- [IP_LOOKUP_NEXT_MIDCHAIN] = "ip6-midchain",
- [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip6-mcast-midchain",
- [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip6-icmp-error",
- [IP6_LOOKUP_NEXT_HOP_BY_HOP] = "ip6-hop-by-hop",
- [IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip6-add-hop-by-hop",
- [IP6_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip6-pop-hop-by-hop",
- [HICN_FACE_IP6_NEXT_ECHO_REPLY] = "hicn-face-ip6-input"
- }
-};
-/* *INDENT-ON* */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/hicn-plugin/src/faces/ip/iface_ip_node.c b/hicn-plugin/src/faces/ip/iface_ip_node.c
deleted file mode 100644
index 8adef50d9..000000000
--- a/hicn-plugin/src/faces/ip/iface_ip_node.c
+++ /dev/null
@@ -1,919 +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 "face_ip.h"
-#include "dpo_ip.h"
-#include "../../strategy_dpo_manager.h"
-#include "../face.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 hicn_iface_ip4_input_node;
-vlib_node_registration_t hicn_iface_ip4_output_node;
-vlib_node_registration_t hicn_iface_ip6_input_node;
-vlib_node_registration_t hicn_iface_ip6_output_node;
-
-u32 data_fwd_iface_ip4_vlib_edge;
-u32 data_fwd_iface_ip6_vlib_edge;
-
-void
-hicn_iface_ip_init (vlib_main_t * vm)
-{
- u32 temp_index4 = vlib_node_add_next (vm,
- hicn_interest_hitcs_node.index,
- hicn_iface_ip4_output_node.index);
- u32 temp_index6 = vlib_node_add_next (vm,
- hicn_interest_hitcs_node.index,
- hicn_iface_ip6_output_node.index);
-
- data_fwd_iface_ip4_vlib_edge = vlib_node_add_next (vm,
- hicn_data_fwd_node.index,
- hicn_iface_ip4_output_node.index);
-
- data_fwd_iface_ip6_vlib_edge = vlib_node_add_next (vm,
- hicn_data_fwd_node.index,
- hicn_iface_ip6_output_node.index);
-
- ASSERT (temp_index4 == data_fwd_iface_ip4_vlib_edge);
- ASSERT (temp_index6 == data_fwd_iface_ip6_vlib_edge);
-}
-
-static char *hicn_iface_ip4_input_error_strings[] = {
-#define _(sym, string) string,
- foreach_hicnfwd_error
-#undef _
-};
-
-static char *hicn_iface_ip6_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];
-} hicn_iface_ip4_input_trace_t;
-
-typedef enum
-{
- HICN_IFACE_IP4_INPUT_NEXT_INTEREST,
- HICN_IFACE_IP4_INPUT_NEXT_MAPME,
- HICN_IFACE_IP4_INPUT_NEXT_ERROR_DROP,
- HICN_IFACE_IP4_INPUT_N_NEXT,
-} hicn_iface_ip4_input_next_t;
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
- u8 packet_data[60];
-} hicn_iface_ip6_input_trace_t;
-
-typedef enum
-{
- HICN_IFACE_IP6_INPUT_NEXT_INTEREST,
- HICN_IFACE_IP6_INPUT_NEXT_MAPME,
- HICN_IFACE_IP6_INPUT_NEXT_ERROR_DROP,
- HICN_IFACE_IP6_INPUT_N_NEXT,
-} hicn_iface_ip6_input_next_t;
-
-#define NEXT_MAPME_IP4 HICN_IFACE_IP4_INPUT_NEXT_MAPME
-#define NEXT_MAPME_IP6 HICN_IFACE_IP6_INPUT_NEXT_MAPME
-
-#define NEXT_INTEREST_IP4 HICN_IFACE_IP6_INPUT_NEXT_INTEREST
-#define NEXT_INTEREST_IP6 HICN_IFACE_IP6_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_IP4 hicn_dpo_ip4_add_and_lock_from_remote
-#define DPO_ADD_LOCK_IP6 hicn_dpo_ip6_add_and_lock_from_remote
-
-#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 hicn_iface_ip4_input_trace_t
-#define TRACE_INPUT_PKT_IP6 hicn_iface_ip6_input_trace_t
-
-#define iface_input_x1(ipv) \
- do { \
- vlib_buffer_t *b0; \
- u32 bi0, next0; \
- IP_HEADER_##ipv * ip_hdr = NULL; \
- hicn_buffer_t * hicnb0; \
- u32 swif; \
- /* 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; \
- \
- swif = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
- \
- ADDRESS_IP##ipv; \
- \
- DPO_ADD_LOCK_IP##ipv \
- (&(hicnb0->face_dpo_id), \
- &hicnb0->flags, \
- local_address, \
- &(ip_hdr->src_address), \
- vnet_buffer(b0)->sw_if_index[VLIB_RX], \
- VLIB_EDGE_IP##ipv); \
- \
- 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_dpo_id.dpoi_index \
- * 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; \
- IP_HEADER_##ipv * ip_hdr0 = NULL; \
- IP_HEADER_##ipv * ip_hdr1 = NULL; \
- hicn_buffer_t *hicnb0, *hicnb1; \
- u32 swif0, swif1; \
- \
- /* 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; \
- \
- swif0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
- swif1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \
- \
- ADDRESSX2_IP##ipv; \
- \
- DPO_ADD_LOCK_IP##ipv \
- (&(hicnb0->face_dpo_id), \
- &hicnb0->flags, \
- local_address0, \
- &(ip_hdr0->src_address), \
- vnet_buffer(b0)->sw_if_index[VLIB_RX], \
- VLIB_EDGE_IP##ipv); \
- \
- DPO_ADD_LOCK_IP##ipv \
- (&(hicnb1->face_dpo_id), \
- &hicnb1->flags, \
- local_address1, \
- &(ip_hdr1->src_address), \
- vnet_buffer(b1)->sw_if_index[VLIB_RX], \
- VLIB_EDGE_IP##ipv); \
- \
- 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_dpo_id.dpoi_index \
- * 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_dpo_id.dpoi_index \
- * 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
-hicn_iface_ip4_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 *
-hicn_iface_ip4_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 *);
- hicn_iface_ip4_input_trace_t *t =
- va_arg (*args, hicn_iface_ip4_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 (hicn_iface_ip4_input_node) =
-{
- .function = hicn_iface_ip4_input_node_fn,
- .name = "hicn-iface-ip4-input",
- .vector_size = sizeof (u32),
- .format_trace = hicn_iface_ip4_input_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicn_iface_ip4_input_error_strings),
- .error_strings = hicn_iface_ip4_input_error_strings,
- .n_next_nodes = HICN_IFACE_IP4_INPUT_N_NEXT,
- /* edit / add dispositions*/
- .next_nodes =
- {
- [HICN_IFACE_IP4_INPUT_NEXT_INTEREST] = "hicn-interest-pcslookup",
- [HICN_IFACE_IP4_INPUT_NEXT_MAPME] = "hicn-mapme-ctrl",
- [HICN_IFACE_IP4_INPUT_NEXT_ERROR_DROP] = "error-drop",
- },
-};
-/* *INDENT-ON* */
-
-static uword
-hicn_iface_ip6_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 *
-hicn_iface_ip6_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 *);
- hicn_iface_ip6_input_trace_t *t =
- va_arg (*args, hicn_iface_ip6_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 (hicn_iface_ip6_input_node) =
-{
- .function = hicn_iface_ip6_input_node_fn,
- .name = "hicn-iface-ip6-input",
- .vector_size = sizeof (u32),
- .format_trace = hicn_iface_ip6_input_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicn_iface_ip6_input_error_strings),
- .error_strings = hicn_iface_ip6_input_error_strings,
- .n_next_nodes = HICN_IFACE_IP6_INPUT_N_NEXT,
- /* edit / add dispositions*/
- .next_nodes =
- {
- [HICN_IFACE_IP6_INPUT_NEXT_INTEREST] = "hicn-interest-pcslookup",
- [HICN_IFACE_IP6_INPUT_NEXT_MAPME] = "hicn-mapme-ctrl",
- [HICN_IFACE_IP6_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)
-{
- 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] = ~0;
- hicn_header_t *hicn = vlib_buffer_get_current (b0);
-
- ip46_address_t temp_addr;
- ip46_address_reset (&temp_addr);
- hicn_face_ip_t *iface_ip = (hicn_face_ip_t *) iface->data;
- hicn_type_t type = hicn_get_buffer (b0)->type;
- hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol,
- &(iface_ip->remote_addr), &(temp_addr),
- iface->shared.pl_id);
-}
-
-static inline void
-hicn_rewrite_iface_data6 (vlib_main_t * vm, vlib_buffer_t * b0,
- const hicn_face_t * iface)
-{
- 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] = ~0;
- hicn_header_t *hicn = vlib_buffer_get_current (b0);
-
- ip46_address_t temp_addr;
- ip46_address_reset (&temp_addr);
- hicn_face_ip_t *iface_ip = (hicn_face_ip_t *) iface->data;
- hicn_type_t type = hicn_get_buffer (b0)->type;
- hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol,
- &(iface_ip->remote_addr), &(temp_addr),
- iface->shared.pl_id);
-}
-
-static char *hicn_iface_ip4_output_error_strings[] = {
-#define _(sym, string) string,
- foreach_hicnfwd_error
-#undef _
-};
-
-static char *hicn_iface_ip6_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];
-} hicn_iface_ip4_output_trace_t;
-
-typedef enum
-{
- HICN_IFACE_IP4_OUTPUT_NEXT_LOOKUP,
- HICN_IFACE_IP4_OUTPUT_NEXT_ERROR_DROP,
- HICN_IFACE_IP4_OUTPUT_N_NEXT,
-} hicn_iface_ip4_output_next_t;
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
- u8 packet_data[60];
-} hicn_iface_ip6_output_trace_t;
-
-typedef enum
-{
- HICN_IFACE_IP6_OUTPUT_NEXT_LOOKUP,
- HICN_IFACE_IP6_OUTPUT_NEXT_ERROR_DROP,
- HICN_IFACE_IP6_OUTPUT_N_NEXT,
-} hicn_iface_ip6_output_next_t;
-
-#define ERROR_OUTPUT_IP4 HICN_IFACE_IP4_OUTPUT_NEXT_ERROR_DROP
-#define ERROR_OUTPUT_IP6 HICN_IFACE_IP6_OUTPUT_NEXT_ERROR_DROP
-
-#define NEXT_DATA_LOOKUP_IP4 HICN_IFACE_IP4_OUTPUT_NEXT_LOOKUP
-#define NEXT_DATA_LOOKUP_IP6 HICN_IFACE_IP6_OUTPUT_NEXT_LOOKUP
-
-#define HICN_REWRITE_DATA_IP4 hicn_rewrite_iface_data4
-#define HICN_REWRITE_DATA_IP6 hicn_rewrite_iface_data6
-
-#define TRACE_OUTPUT_PKT_IP4 hicn_iface_ip4_output_trace_t
-#define TRACE_OUTPUT_PKT_IP6 hicn_iface_ip6_output_trace_t
-
-#define iface_output_x1(ipv) \
- do { \
- vlib_buffer_t *b0; \
- u32 bi0; \
- u32 next0 = ERROR_OUTPUT_IP##ipv; \
- 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 = NEXT_DATA_LOOKUP_IP##ipv; \
- 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 = ERROR_OUTPUT_IP##ipv; \
- u32 next1 = ERROR_OUTPUT_IP##ipv; \
- 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 = NEXT_DATA_LOOKUP_IP##ipv; \
- 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 = NEXT_DATA_LOOKUP_IP##ipv; \
- 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
-hicn_iface_ip4_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 *
-hicn_iface_ip4_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 *);
- hicn_iface_ip4_output_trace_t *t =
- va_arg (*args, hicn_iface_ip4_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 (hicn_iface_ip4_output_node) =
-{
- .function = hicn_iface_ip4_output_node_fn,
- .name = "hicn-iface-ip4-output",
- .vector_size = sizeof (u32),
- .format_trace = hicn_iface_ip4_output_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicn_iface_ip4_output_error_strings),
- .error_strings = hicn_iface_ip4_output_error_strings,
- .n_next_nodes = HICN_IFACE_IP4_OUTPUT_N_NEXT,
- /* edit / add dispositions here */
- .next_nodes =
- {
- [HICN_IFACE_IP4_OUTPUT_NEXT_LOOKUP] = "ip4-lookup",
- [HICN_IFACE_IP4_OUTPUT_NEXT_ERROR_DROP] = "error-drop",
- },
-};
-/* *INDENT-ON* */
-
-
-static uword
-hicn_iface_ip6_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 *
-hicn_iface_ip6_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 *);
- hicn_iface_ip6_output_trace_t *t =
- va_arg (*args, hicn_iface_ip6_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 (hicn_iface_ip6_output_node) =
-{
- .function = hicn_iface_ip6_output_node_fn,
- .name = "hicn-iface-ip6-output",
- .vector_size = sizeof (u32),
- .format_trace = hicn_iface_ip6_output_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicn_iface_ip6_output_error_strings),
- .error_strings = hicn_iface_ip6_output_error_strings,
- .n_next_nodes = HICN_IFACE_IP6_OUTPUT_N_NEXT,
- /* edit / add dispositions here */
- .next_nodes =
- {
- [HICN_IFACE_IP6_OUTPUT_NEXT_LOOKUP] = "ip6-lookup",
- [HICN_IFACE_IP6_OUTPUT_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/udp/dpo_udp.c b/hicn-plugin/src/faces/udp/dpo_udp.c
deleted file mode 100644
index 987d52bb7..000000000
--- a/hicn-plugin/src/faces/udp/dpo_udp.c
+++ /dev/null
@@ -1,157 +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 "dpo_udp.h"
-
-#include <vnet/ip/format.h>
-#include <vnet/adj/adj.h>
-#include <vnet/vnet.h>
-#include <vlib/vlib.h>
-
-const static char *const hicn_face_ip4udp_nodes[] = {
- "hicn-face-encap-udp4",
- "hicn-face-decap-udp4",
- "hicn-iface-decap-udp4",
- "hicn-iface-encap-udp4",
- NULL,
-};
-
-const static char *const hicn_face_ip6udp_nodes[] = {
- "hicn-face-encap-udp6",
- "hicn-face-decap-udp6",
- "hicn-iface-decap-udp6",
- "hicn-iface-encap-udp6",
- NULL,
-};
-
-const static char *const *const hicn_ipudp_nodes[DPO_PROTO_NUM] = {
- [DPO_PROTO_IP4] = hicn_face_ip4udp_nodes,
- [DPO_PROTO_IP6] = hicn_face_ip6udp_nodes
-};
-
-
-const static dpo_vft_t hicn_dpoi_udp_vft = {
- .dv_lock = hicn_face_lock,
- .dv_unlock = hicn_face_unlock,
- .dv_format = format_hicn_face_udp,
-};
-
-/* Must be executed after all the strategy nodes are created */
-void
-hicn_dpo_udp_module_init (void)
-{
- mhash_init (&hicn_face_udp_hashtb, sizeof (hicn_face_id_t) /* value */ ,
- sizeof (hicn_face_udp_key_t) /* key */ );
-
- /*
- * How much useful is the following registration?
- * So far it seems that we need it only for setting the dpo_type.
- */
- hicn_face_udp_type =
- dpo_register_new_type (&hicn_dpoi_udp_vft, hicn_ipudp_nodes);
-}
-
-
-/* Here udp ports are in host order, move them to network order to do the lookup */
-int
-hicn_dpo_udp4_create (dpo_id_t * dpo,
- const ip4_address_t * src_ip,
- const ip4_address_t * dst_ip,
- u16 src_port, u16 dst_port,
- u32 sw_if,
- adj_index_t ip_adj,
- u32 node_index,
- hicn_face_flags_t flags, hicn_face_id_t * face_id)
-{
- u16 net_src_port = clib_host_to_net_u16 (src_port);
- u16 net_dst_port = clib_host_to_net_u16 (dst_port);
- hicn_face_t *face =
- hicn_face_udp4_get (src_ip, dst_ip, net_src_port, net_dst_port);
-
- u8 hicnb_flags;
- /* ip_csum_t sum0; */
-
- if (face != NULL)
- return HICN_ERROR_FACE_ALREADY_CREATED;
-
- hicn_dpo_udp4_add_and_lock (dpo, src_ip, dst_ip, net_src_port, net_dst_port,
- node_index, &hicnb_flags, sw_if);
-
- face = hicn_dpoi_get_from_idx (dpo->dpoi_index);
-
- hicn_face_udp_t *udp_face = (hicn_face_udp_t *) face->data;
-
- udp_face->hdrs.ip4.ip.checksum =
- ip4_header_checksum (&(udp_face->hdrs.ip4.ip));
-
- face->shared.flags = flags;
- face->shared.adj = ip_adj;
- *face_id = hicn_dpoi_get_index (face);
-
- return HICN_ERROR_NONE;
-}
-
-
-int
-hicn_dpo_udp6_create (dpo_id_t * dpo,
- const ip6_address_t * src_ip,
- const ip6_address_t * dst_ip,
- u16 src_port, u16 dst_port,
- u32 sw_if,
- adj_index_t ip_adj,
- u32 node_index,
- hicn_face_flags_t flags, hicn_face_id_t * face_id)
-{
- u16 net_src_port = clib_host_to_net_u16 (src_port);
- u16 net_dst_port = clib_host_to_net_u16 (dst_port);
- hicn_face_t *face =
- hicn_face_udp6_get (src_ip, dst_ip, net_src_port, net_dst_port);
- u8 hicnb_flags;
-
- if (face != NULL)
- return HICN_ERROR_FACE_ALREADY_CREATED;
-
- hicn_dpo_udp6_add_and_lock (dpo, src_ip, dst_ip, net_src_port, net_dst_port,
- node_index, &hicnb_flags, sw_if);
-
- face = hicn_dpoi_get_from_idx (dpo->dpoi_index);
-
- face->shared.flags = flags;
- face->shared.adj = ip_adj;
- *face_id = hicn_dpoi_get_index (face);
-
- return HICN_ERROR_NONE;
-}
-
-void
-hicn_dpo_udp_create_from_face (hicn_face_t * face, dpo_id_t * dpo,
- u16 dpoi_next_node)
-{
- hicn_face_id_t face_dpoi_id = hicn_dpoi_get_index (face);
- hicn_face_udp_t *face_udp = (hicn_face_udp_t *) face->data;
- u8 version =
- (face_udp->hdrs.ip4.ip.ip_version_and_header_length & 0xf0) >> 4;
- dpo_set (dpo, face->shared.face_type,
- version == 4 ? DPO_PROTO_IP4 : DPO_PROTO_IP6, face_dpoi_id);
- dpo->dpoi_next_node = dpoi_next_node;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/hicn-plugin/src/faces/udp/dpo_udp.h b/hicn-plugin/src/faces/udp/dpo_udp.h
deleted file mode 100644
index 98abf3d29..000000000
--- a/hicn-plugin/src/faces/udp/dpo_udp.h
+++ /dev/null
@@ -1,289 +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_DPO_UDP_H__
-#define __HICN_DPO_UDP_H__
-
-#include <vnet/adj/adj_types.h>
-#include <vnet/ip/ip4_packet.h>
-#include <vnet/ip/ip6_packet.h>
-
-#include "face_udp.h"
-#include "../face.h"
-#include "../../error.h"
-
-extern u32 strategy_face_udp4_vlib_edge;
-extern u32 strategy_face_udp6_vlib_edge;
-
-
-/**
- * @brief Initialize the internal structures of the dpo udp face module.
- */
-void hicn_dpo_udp_module_init (void);
-
-/**
- * @brief Create a udp face and its corresponding dpo. Meant to be used for the
- * control plane.
- *
- * @param dpo: Data plane object that point to the face created.
- * @param local_addr: Local address of the UDP tunnel
- * @param remote_addr: Remote address of the UDP tunnel
- * @param local_port: Local port of the UDP tunnel
- * @param remote_port: Remote port of the UDP tunnel
- * @param adj: Ip adjacency corresponding to the remote address in the face
- * @param node_index: vlib edge index to use in the packet processing
- * @param flags: Flags of the face
- * @param face_id: Identifier for the face (dpoi_index)
- * @return HICN_ERROR_FACE_ALREADY_CREATED if the face exists, otherwise HICN_ERROR_NONE
- */
-int
-hicn_dpo_udp4_create (dpo_id_t * dpo,
- const ip4_address_t * local_addr,
- const ip4_address_t * remote_addr,
- u16 local_port, u16 remote_port,
- u32 sw_if,
- adj_index_t adj,
- u32 node_index,
- hicn_face_flags_t flags, hicn_face_id_t * face_id);
-
-/**
- * @brief Retrieve a face using the face identifier, i.e., the quadruplet (local_addr, remote_addr,
- * local_port, remote_port). This method adds a lock on the face state.
- *
- * @param dpo: Result of the lookup. If the face doesn't exist dpo = NULL
- * @param local_addr: Local address of the UDP tunnel
- * @param remote_addr: Remote address of the UDP tunnel
- * @param local_port: Local port of the UDP tunnel
- * @param remote_port: Remote port of the UDP tunnel
- * @param hicnb_flags: Flags that indicate whether the face is an application
- * face or not in the hicn_buffer. (Currently only IP faces can be appface)
- *
- * @result HICN_ERROR_FACE_NOT_FOUND if the face does not exist, otherwise HICN_ERROR_NONE.
- */
-always_inline int
-hicn_dpo_udp4_lock (dpo_id_t * dpo,
- const ip4_address_t * local_addr,
- const ip4_address_t * remote_addr,
- u16 local_port, u16 remote_port, u8 * hicnb_flags)
-{
- dpo->dpoi_type = DPO_FIRST;
- dpo->dpoi_proto = DPO_PROTO_NONE;
- dpo->dpoi_index = INDEX_INVALID;
- dpo->dpoi_next_node = 0;
-
- hicn_face_t *face =
- hicn_face_udp4_get (local_addr, remote_addr, local_port, remote_port);
-
- if (PREDICT_FALSE (face == NULL))
- return HICN_ERROR_FACE_NOT_FOUND;
-
- index_t dpoi_index = hicn_dpoi_get_index (face);
- dpo_set (dpo, hicn_face_udp_type, DPO_PROTO_IP4, dpoi_index);
- dpo->dpoi_next_node = strategy_face_udp4_vlib_edge;
- dpo_unlock (dpo);
-
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
-
- return HICN_ERROR_NONE;
-}
-
-/**
- * @brief Retrieve, or create if it doesn't exist, a face from the face
- * identifier (local_addr, remote_addr, local_port, remote_port) and returns its
- * dpo. This method adds a lock on the face state.
- *
- * @param dpo: Result of the lookup
- * @param local_addr: Local address of the UDP tunnel
- * @param remote_addr: Remote address of the UDP tunnel
- * @param local_port: Local port of the UDP tunnel
- * @param remote_port: Remote port of the UDP tunnel
- * @param hicnb_flags: Flags that indicate whether the face is an application
- * face or not. (Currently only IP faces can be appface)
- * @param node_index: vlib edge index to use in the packet processing
- */
-always_inline void
-hicn_dpo_udp4_add_and_lock (dpo_id_t * dpo,
- const ip4_address_t * local_addr,
- const ip4_address_t * remote_addr,
- u16 local_port, u16 remote_port,
- u32 node_index, u8 * hicnb_flags, u32 sw_if)
-{
- dpo->dpoi_type = DPO_FIRST;
- dpo->dpoi_proto = DPO_PROTO_NONE;
- dpo->dpoi_index = INDEX_INVALID;
- dpo->dpoi_next_node = 0;
-
- hicn_face_t *face =
- hicn_face_udp4_get (local_addr, remote_addr, local_port, remote_port);
-
- if (face == NULL)
- {
-
- hicn_face_id_t dpoi_index;
- hicn_iface_udp4_add (local_addr, remote_addr, local_port, remote_port,
- sw_if, &dpoi_index);
-
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
- dpo_set (dpo, hicn_face_udp_type, DPO_PROTO_IP4, dpoi_index);
- dpo->dpoi_next_node = node_index;
- dpo_unlock (dpo);
-
- return;
- }
-
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
-
- hicn_face_id_t dpoi_index = hicn_dpoi_get_index (face);
- dpo_set (dpo, hicn_face_udp_type, DPO_PROTO_IP4, dpoi_index);
- dpo->dpoi_next_node = node_index;
- dpo_unlock (dpo);
-}
-
-/**
- * @brief Create a udp face and its corresponding dpo. Meant to be used for the
- * control plane.
- *
- * @param dpo: Data plane object that point to the face created.
- * @param local_addr: Local address of the UDP tunnel
- * @param remote_addr: Remote address of the UDP tunnel
- * @param local_port: Local port of the UDP tunnel
- * @param remote_port: Remote port of the UDP tunnel
- * @param adj: Ip adjacency corresponding to the remote address in the face
- * @param node_index: vlib edge index to use in the packet processing
- * @param flags: Flags of the face
- * @param face_id: Identifier for the face (dpoi_index)
- * @return HICN_ERROR_FACE_ALREADY_CREATED if the face exists, otherwise HICN_ERROR_NONE
- */
-int
-hicn_dpo_udp6_create (dpo_id_t * dpo,
- const ip6_address_t * local_addr,
- const ip6_address_t * remote_addr,
- u16 local_port, u16 remote_port,
- u32 sw_if,
- adj_index_t adj,
- u32 node_index,
- hicn_face_flags_t flags, hicn_face_id_t * face_id);
-
-
-/**
- * @brief Retrieve a face using the face identifier, i.e., the quadruplet (local_addr, remote_addr,
- * local_port, remote_port). This method adds a lock on the face state.
- *
- * @param dpo: Result of the lookup. If the face doesn't exist dpo = NULL
- * @param local_addr: Local address of the UDP tunnel
- * @param remote_addr: Remote address of the UDP tunnel
- * @param local_port: Local port of the UDP tunnel
- * @param remote_port: Remote port of the UDP tunnel
- * @param hicnb_flags: Flags that indicate whether the face is an application
- * face or not. (Currently only IP faces can be appface)
- *
- * @result HICN_ERROR_FACE_NOT_FOUND if the face does not exist, otherwise HICN_ERROR_NONE.
- */
-always_inline int
-hicn_dpo_udp6_lock (dpo_id_t * dpo,
- const ip6_address_t * local_addr,
- const ip6_address_t * remote_addr,
- u16 local_port, u16 remote_port, u8 * hicnb_flags)
-{
- dpo->dpoi_type = DPO_FIRST;
- dpo->dpoi_proto = DPO_PROTO_NONE;
- dpo->dpoi_index = INDEX_INVALID;
- dpo->dpoi_next_node = 0;
-
- hicn_face_t *face =
- hicn_face_udp6_get (local_addr, remote_addr, local_port, remote_port);
-
-
- if (PREDICT_FALSE (face == NULL))
- return HICN_ERROR_FACE_NOT_FOUND;
-
- hicn_face_id_t dpoi_index = hicn_dpoi_get_index (face);
- dpo_set (dpo, hicn_face_udp_type, DPO_PROTO_IP6, dpoi_index);
- dpo->dpoi_next_node = strategy_face_udp6_vlib_edge;
- dpo_unlock (dpo);
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
-
- return HICN_ERROR_NONE;
-}
-
-/**
- * @brief Retrieve, or create if it doesn't exist, a face from the face
- * identifier (local_addr, remote_addr, local_port, remote_port) and returns its
- * dpo. This method adds a lock on the face state.
- *
- * @param dpo: Result of the lookup
- * @param local_addr: Local address of the UDP tunnel
- * @param remote_addr: Remote address of the UDP tunnel
- * @param local_port: Local port of the UDP tunnel
- * @param remote_port: Remote port of the UDP tunnel
- * @param hicnb_flags: Flags that indicate whether the face is an application
- * face or not. (Currently only IP faces can be appface)
- * @param node_index: vlib edge index to use in the packet processing
- */
-always_inline void
-hicn_dpo_udp6_add_and_lock (dpo_id_t * dpo,
- const ip6_address_t * local_addr,
- const ip6_address_t * remote_addr,
- u16 local_port, u16 remote_port,
- u32 node_index, u8 * hicnb_flags, u32 sw_if)
-{
- dpo->dpoi_type = DPO_FIRST;
- dpo->dpoi_proto = DPO_PROTO_NONE;
- dpo->dpoi_index = INDEX_INVALID;
- dpo->dpoi_next_node = 0;
-
- hicn_face_t *face =
- hicn_face_udp6_get (local_addr, remote_addr, local_port, remote_port);
-
- if (face == NULL)
- {
- hicn_face_id_t dpoi_index;
- hicn_iface_udp6_add (local_addr, remote_addr, local_port, remote_port,
- sw_if, &dpoi_index);
-
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
- dpo_set (dpo, hicn_face_udp_type, DPO_PROTO_IP6, dpoi_index);
- dpo->dpoi_next_node = node_index;
- dpo_unlock (dpo);
-
- return;
- }
-
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
-
- hicn_face_id_t dpoi_index = hicn_dpoi_get_index (face);
- dpo_set (dpo, hicn_face_udp_type, DPO_PROTO_IP6, dpoi_index);
- dpo->dpoi_next_node = node_index;
- dpo_unlock (dpo);
-}
-
-/**
- * @brief Create a dpo from a udp face
- *
- * @param face Face from which to create the dpo
- * @return the dpo
- */
-void hicn_dpo_udp_create_from_face (hicn_face_t * face, dpo_id_t * dpo,
- u16 dpoi_next_node);
-
-#endif // __HICN_DPO_UDP_H__
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/hicn-plugin/src/faces/udp/face_udp.c b/hicn-plugin/src/faces/udp/face_udp.c
deleted file mode 100644
index e610cbd14..000000000
--- a/hicn-plugin/src/faces/udp/face_udp.c
+++ /dev/null
@@ -1,449 +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 <vlib/vlib.h>
-#include <vnet/vnet.h>
-
-#include "face_udp.h"
-#include "face_udp_node.h"
-#include "dpo_udp.h"
-#include "../face.h"
-#include "../../infra.h"
-#include "../../strategy.h"
-#include "../../strategy_dpo_manager.h"
-#include "../../hicn.h"
-
-#include "../../mapme.h" // HICN_MAPME_EVENT_*
-#include "../../mapme_eventmgr.h" // hicn_mapme_eventmgr_process_node
-extern vlib_node_registration_t hicn_mapme_eventmgr_process_node;
-
-mhash_t hicn_face_udp_hashtb;
-
-dpo_type_t hicn_face_udp_type;
-
-ip4_header_t ip4_header_skl = {
- .ip_version_and_header_length = IP4_VERSION_AND_HEADER_LENGTH_NO_OPTIONS,
- .tos = 0x00,
- .length = (u16) 0,
- .fragment_id = (u16) 0,
- .flags_and_fragment_offset = (u16) 0,
- .ttl = 254,
- .protocol = IP_PROTOCOL_UDP,
- .checksum = 0,
- .src_address = {{0}},
- .dst_address = {{0}},
-};
-
-ip6_header_t ip6_header_skl = {
-#if CLIB_ARCH_IS_BIG_ENDIAN
- .ip_version_traffic_class_and_flow_label = 0x60000000,
-#else
- .ip_version_traffic_class_and_flow_label = 0x00000060,
-#endif
- .payload_length = (u16) 0,
- .protocol = IP_PROTOCOL_UDP,
- .hop_limit = 254,
- .src_address = {{0}},
- .dst_address = {{0}}
-};
-
-u32 strategy_face_udp4_vlib_edge;
-u32 strategy_face_udp6_vlib_edge;
-
-/*
- * Separated from the hicn_face_udp_init because it cannot be called by the
- * init macro due to dependencies with other modules not yet initialied
- */
-void
-hicn_face_udp_init_internal ()
-{
- ip4_header_t *ip4_hdr = &ip4_header_skl;
- ip4_header_skl.checksum = ip4_header_checksum (ip4_hdr);
-}
-
-void
-hicn_face_udp_init (vlib_main_t * vm)
-{
- int strategy_nodes_n = hicn_strategy_get_all_available ();
-
- /* Default Strategy has index 0 and it always exists */
- strategy_face_udp4_vlib_edge = vlib_node_add_next (vm,
- hicn_strategy_node.index,
- hicn_face_udp4_output_node.
- index);
- strategy_face_udp6_vlib_edge =
- vlib_node_add_next (vm, hicn_strategy_node.index,
- hicn_face_udp6_output_node.index);
-
- /*
- * Create and edge between al the other strategy nodes and the
- * udp_output nodes.
- */
- for (int i = 1; i < strategy_nodes_n; i++)
- {
- u32 temp_index4 = vlib_node_add_next (vm,
- hicn_strategy_node.index,
- hicn_face_udp4_output_node.index);
- u32 temp_index6 = vlib_node_add_next (vm,
- hicn_strategy_node.index,
- hicn_face_udp6_output_node.index);
- ASSERT (temp_index4 == strategy_face_udp4_vlib_edge);
- ASSERT (temp_index6 == strategy_face_udp6_vlib_edge);
- }
-
- u32 temp_index4 = vlib_node_add_next (vm,
- hicn_interest_hitpit_node.index,
- hicn_face_udp4_output_node.index);
- u32 temp_index6 = vlib_node_add_next (vm,
- hicn_interest_hitpit_node.index,
- hicn_face_udp6_output_node.index);
-
- ASSERT (temp_index4 == strategy_face_udp4_vlib_edge);
- ASSERT (temp_index6 == strategy_face_udp6_vlib_edge);
-
- hicn_dpo_udp_module_init ();
-
- register_face_type (hicn_face_udp_type, &udp_vft, "udp");;
-}
-
-int
-hicn_face_udp_add (const ip46_address_t * local_addr,
- const ip46_address_t * remote_addr, u16 local_port,
- u16 remote_port, u32 swif, hicn_face_id_t * pfaceid)
-{
- adj_index_t ip_adj;
- int ret = HICN_ERROR_NONE;
- dpo_proto_t dpo_proto;
-
- hicn_face_flags_t flags = (hicn_face_flags_t) 0;
- flags |= HICN_FACE_FLAGS_FACE;
-
-
- if (ip46_address_is_ip4 (local_addr) && ip46_address_is_ip4 (remote_addr))
- {
- fib_prefix_t fib_pfx;
- fib_node_index_t fib_entry_index;
- fib_prefix_from_ip46_addr (remote_addr, &fib_pfx);
- fib_pfx.fp_len = ip46_address_is_ip4 (remote_addr) ? 32 : 128;
-
- u32 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 (fib_index, &fib_pfx);
-
- ip_adj = fib_entry_get_adj (fib_entry_index);
-
- if (ip_adj == ~0)
- return HICN_ERROR_FACE_IP_ADJ_NOT_FOUND;
-
- hicn_face_t *face =
- hicn_face_udp4_get (&local_addr->ip4, &remote_addr->ip4, local_port,
- remote_port);
-
- if (face == NULL)
- pool_get (hicn_dpoi_face_pool, face);
-
- hicn_face_udp_t *udp_face = (hicn_face_udp_t *) face->data;
-
- clib_memcpy (&(udp_face->hdrs.ip4.ip), &ip4_header_skl,
- sizeof (ip4_header_t));
- clib_memcpy (&(udp_face->hdrs.ip4.ip.src_address), &(local_addr->ip4),
- sizeof (ip4_address_t));
- clib_memcpy (&(udp_face->hdrs.ip4.ip.dst_address), &(remote_addr->ip4),
- sizeof (ip4_address_t));
-
- udp_face->hdrs.ip4.udp.src_port = local_port;
- udp_face->hdrs.ip4.udp.dst_port = remote_port;
-
- ip_csum_t csum = udp_face->hdrs.ip4.ip.checksum;
- csum = ip_csum_sub_even (csum, ip4_header_skl.src_address.as_u32);
- csum = ip_csum_sub_even (csum, ip4_header_skl.dst_address.as_u32);
- csum =
- ip_csum_add_even (csum, udp_face->hdrs.ip4.ip.src_address.as_u32);
- csum =
- ip_csum_add_even (csum, udp_face->hdrs.ip4.ip.dst_address.as_u32);
- udp_face->hdrs.ip4.ip.checksum = ip_csum_fold (csum);
-
- face->shared.adj = ip_adj;
- face->shared.sw_if = swif;
- face->shared.pl_id = (u16) 0;
- face->shared.face_type = hicn_face_udp_type;
- face->shared.flags = flags;
- face->shared.locks = 0;
-
- hicn_face_udp_key_t key;
- hicn_face_udp4_get_key (&local_addr->ip4, &remote_addr->ip4, local_port,
- remote_port, &key);
- hicn_face_id_t dpoi_index = hicn_dpoi_get_index (face);
-
- mhash_set_mem (&hicn_face_udp_hashtb, &key, (uword *) & dpoi_index, 0);
-
- *pfaceid = hicn_dpoi_get_index (face);
- dpo_proto = DPO_PROTO_IP4;
- fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PRIORITY_HI);
- }
- else if (!ip46_address_is_ip4 (local_addr)
- && !ip46_address_is_ip4 (remote_addr))
- {
- fib_prefix_t fib_pfx;
- fib_node_index_t fib_entry_index;
- fib_prefix_from_ip46_addr (remote_addr, &fib_pfx);
- fib_pfx.fp_len = ip46_address_is_ip4 (remote_addr) ? 32 : 128;
-
- u32 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 (fib_index, &fib_pfx);
-
- ip_adj = fib_entry_get_adj (fib_entry_index);
-
- if (ip_adj == ~0)
- return HICN_ERROR_FACE_IP_ADJ_NOT_FOUND;
-
- hicn_face_t *face =
- hicn_face_udp6_get (&local_addr->ip6, &remote_addr->ip6, local_port,
- remote_port);
-
- if (face == NULL)
- pool_get (hicn_dpoi_face_pool, face);
-
- hicn_face_udp_t *udp_face = (hicn_face_udp_t *) face->data;
-
- clib_memcpy (&(udp_face->hdrs.ip6.ip), &ip6_header_skl,
- sizeof (ip6_header_t));
- clib_memcpy (&(udp_face->hdrs.ip6.ip.src_address), local_addr,
- sizeof (ip6_address_t));
- clib_memcpy (&(udp_face->hdrs.ip6.ip.dst_address), remote_addr,
- sizeof (ip6_address_t));
-
- udp_face->hdrs.ip6.udp.src_port = local_port;
- udp_face->hdrs.ip6.udp.dst_port = remote_port;
-
- face->shared.adj = ip_adj;
- face->shared.sw_if = swif;
- face->shared.pl_id = (u16) 0;
- face->shared.face_type = hicn_face_udp_type;
- face->shared.flags = flags;
- face->shared.locks = 0;
-
- hicn_face_udp_key_t key;
- hicn_face_udp6_get_key (&local_addr->ip6, &remote_addr->ip6, local_port,
- remote_port, &key);
- hicn_face_id_t dpoi_index = hicn_dpoi_get_index (face);
-
- mhash_set_mem (&hicn_face_udp_hashtb, &key, (uword *) & dpoi_index, 0);
-
- *pfaceid = hicn_dpoi_get_index (face);
- dpo_proto = DPO_PROTO_IP6;
- fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PRIORITY_HI);
- }
- else
- {
- return HICN_ERROR_IPS_ADDR_TYPE_NONUNIFORM;
- }
-
- 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);
- }
-
- 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)
- {
- .prefix = 0,
- .dpo = (dpo_id_t)
- {
- .dpoi_type = hicn_face_udp_type,
- .dpoi_proto = dpo_proto,
- .dpoi_next_node = 0,
- .dpoi_index = *pfaceid,
- }
- };
- /* *INDENT-ON* */
-
- //Take a lock on the face which will be removed when the face is deleted
- hicn_face_lock (&(retx->dpo));
-
- return ret;
-}
-
-int
-hicn_face_udp_del (u32 faceid)
-{
- hicn_face_t *face = hicn_dpoi_get_from_idx (faceid);
- hicn_face_udp_t *face_udp = (hicn_face_udp_t *) face->data;
- hicn_face_udp_key_t key;
- hicn_face_udp_key_t old_key;
-
- if (face_udp->hdrs.ip4.ip.ip_version_and_header_length ==
- IP4_VERSION_AND_HEADER_LENGTH_NO_OPTIONS)
- {
- hicn_face_udp4_get_key (&face_udp->hdrs.ip4.ip.src_address,
- &face_udp->hdrs.ip4.ip.dst_address,
- face_udp->hdrs.ip4.udp.src_port,
- face_udp->hdrs.ip4.udp.dst_port, &key);
- mhash_unset (&hicn_face_udp_hashtb, &key, (uword *) & old_key);
- }
- else
- {
- hicn_face_udp6_get_key (&face_udp->hdrs.ip6.ip.src_address,
- &face_udp->hdrs.ip6.ip.dst_address,
- face_udp->hdrs.ip6.udp.src_port,
- face_udp->hdrs.ip6.udp.dst_port, &key);
- mhash_unset (&hicn_face_udp_hashtb, &key, (uword *) & old_key);
- }
- return hicn_face_del (faceid);
-}
-
-u8 *
-format_hicn_face_udp (u8 * s, va_list * args)
-{
- hicn_face_id_t face_id = va_arg (*args, index_t);
- CLIB_UNUSED (u32 indent) = va_arg (*args, u32);
- hicn_face_t *face;
- hicn_face_udp_t *udp_face;
- ip_adjacency_t *adj;
- u8 ipv = IP4_VERSION_AND_HEADER_LENGTH_NO_OPTIONS;
- vnet_main_t *vnm = vnet_get_main ();
-
-
- face = hicn_dpoi_get_from_idx (face_id);
- udp_face = (hicn_face_udp_t *) (face->data);
-
- if (face->shared.flags & HICN_FACE_FLAGS_FACE)
- {
- ASSERT (face->shared.adj != (adj_index_t) ~ 0);
- adj = adj_get (face->shared.adj);
-
- s = format (s, "%U Face %d: ", format_white_space, indent, face_id);
- if (udp_face->hdrs.ip4.ip.ip_version_and_header_length == ipv)
- {
- s = format (s, "type UDP local %U|%u ",
- format_ip4_address, &udp_face->hdrs.ip4.ip.src_address,
- clib_net_to_host_u16 (udp_face->hdrs.ip4.udp.src_port));
- s =
- format (s, "remote %U|%u ", format_ip4_address,
- &udp_face->hdrs.ip4.ip.dst_address,
- clib_net_to_host_u16 (udp_face->hdrs.ip4.udp.dst_port));
- s = format (s, "%U", format_vnet_link, adj->ia_link);
-
- vnet_sw_interface_t *sw_int =
- vnet_get_sw_interface_or_null (vnm, face->shared.sw_if);
- if (sw_int != NULL)
- s = format (s, " dev %U", format_vnet_sw_interface_name, vnm,
- sw_int);
-
- if ((face->shared.flags & HICN_FACE_FLAGS_DELETED))
- s = format (s, " (deleted)");
- }
- else
- {
- s = format (s, "type UDP local %U|%u ",
- format_ip6_address, &udp_face->hdrs.ip6.ip.src_address,
- clib_net_to_host_u16 (udp_face->hdrs.ip6.udp.src_port));
- s =
- format (s, "remote %U|%u ", format_ip6_address,
- &udp_face->hdrs.ip6.ip.dst_address,
- clib_net_to_host_u16 (udp_face->hdrs.ip6.udp.dst_port));
- s = format (s, "%U", format_vnet_link, adj->ia_link);
-
- vnet_sw_interface_t *sw_int =
- vnet_get_sw_interface_or_null (vnm, face->shared.sw_if);
- if (sw_int != NULL)
- s = format (s, " dev %U", format_vnet_sw_interface_name, vnm,
- sw_int);
-
- if ((face->shared.flags & HICN_FACE_FLAGS_DELETED))
- s = format (s, " (deleted)");
- }
- }
- else
- {
- s = format (s, "%U iFace %d: ", format_white_space, indent, face_id);
- if (udp_face->hdrs.ip4.ip.ip_version_and_header_length == ipv)
- {
- s = format (s, "type UDP local %U|%u",
- format_ip4_address, &udp_face->hdrs.ip4.ip.src_address,
- clib_net_to_host_u16 (udp_face->hdrs.ip4.udp.src_port));
- s =
- format (s, " local %U|%u", format_ip4_address,
- &udp_face->hdrs.ip4.ip.dst_address,
- clib_net_to_host_u16 (udp_face->hdrs.ip4.udp.dst_port));
-
- vnet_sw_interface_t *sw_int =
- vnet_get_sw_interface_or_null (vnm, face->shared.sw_if);
- if (sw_int != NULL)
- s = format (s, " dev %U", format_vnet_sw_interface_name, vnm,
- sw_int);
-
- if ((face->shared.flags & HICN_FACE_FLAGS_DELETED))
- s = format (s, " (deleted)");
- }
- else
- {
- s = format (s, "type UDP local %U|%u",
- format_ip6_address, &udp_face->hdrs.ip6.ip.src_address,
- clib_net_to_host_u16 (udp_face->hdrs.ip6.udp.src_port));
- s =
- format (s, " remote %U|%u", format_ip6_address,
- &udp_face->hdrs.ip6.ip.dst_address,
- clib_net_to_host_u16 (udp_face->hdrs.ip6.udp.dst_port));
-
- vnet_sw_interface_t *sw_int =
- vnet_get_sw_interface_or_null (vnm, face->shared.sw_if);
- if (sw_int != NULL)
- s = format (s, " dev %U", format_vnet_sw_interface_name, vnm,
- sw_int);
-
- if ((face->shared.flags & HICN_FACE_FLAGS_DELETED))
- s = format (s, " (deleted)");
- }
- }
-
- return s;
-}
-
-void
-hicn_face_udp_get_dpo (hicn_face_t * face, dpo_id_t * dpo)
-{
- hicn_face_udp_t *face_udp = (hicn_face_udp_t *) face->data;
- u8 version =
- (face_udp->hdrs.ip4.ip.ip_version_and_header_length & 0xf0) >> 4;
- return hicn_dpo_udp_create_from_face (face, dpo,
- version ==
- (u8) 4 ? strategy_face_udp4_vlib_edge
- : strategy_face_udp6_vlib_edge);
-}
-
-hicn_face_vft_t udp_vft = {
- .format_face = format_hicn_face_udp,
- .hicn_face_del = hicn_face_udp_del,
- .hicn_face_get_dpo = hicn_face_udp_get_dpo,
-};
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/hicn-plugin/src/faces/udp/face_udp.h b/hicn-plugin/src/faces/udp/face_udp.h
deleted file mode 100644
index 5dfc76e22..000000000
--- a/hicn-plugin/src/faces/udp/face_udp.h
+++ /dev/null
@@ -1,356 +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_FACE_UDP_H__
-#define __HICN_FACE_UDP_H__
-
-#include <vlib/vlib.h>
-#include <vnet/vnet.h>
-#include <vnet/ip/ip6_packet.h>
-#include <vnet/udp/udp_packet.h>
-
-#include "../face.h"
-
-/**
- * @file
- * @brief UDP face
- *
- * This file containes the definition of UDP faces.
- * UDP faces encap and decap an hicn packet into a UDP tunnel.
- * Src and dst address in interest and data packets are not considered and
- * should be set to 0 (not checked in the forwarder).
- */
-
-/* Pre-instantiated ip header to fast fill an newly encapsulated packet */
-extern ip4_header_t ip4_header_skl;
-extern ip6_header_t ip6_header_skl;
-
-#define INVALID_UDP_DPO_INDEX ~0
-
-/**
- * @brief UDP face representation. The following is stored in the data field of
- * an hicn_face_t object (see hicn_face.h). A UDP face is identifies by the
- * quadruplet (src addr, dst addr, src port, dst port).
- */
-typedef struct hicn_face_udp_t_
-{
- /**
- * The headers to paint, in packet painting order
- */
- union
- {
- struct
- {
- ip4_header_t ip;
- udp_header_t udp;
- } __attribute__ ((packed)) ip4;
- struct
- {
- ip6_header_t ip;
- udp_header_t udp;
- } __attribute__ ((packed)) ip6;
- } __attribute__ ((packed)) hdrs;
-} hicn_face_udp_t;
-
-/* Hast table mapping the udp key with the face id (dpoi_index pointing to and
- element in the face pool defined in hicn_face.h)*/
-extern mhash_t hicn_face_udp_hashtb;
-
-/**
- * @brief Hash table key.
- */
-typedef struct hicn_face_udp_key_s
-{
- ip46_address_t local_addr;
- ip46_address_t remote_addr;
- u16 local_port;
- u16 remote_port;
-} hicn_face_udp_key_t;
-
-/* DPO type for the udp face */
-extern dpo_type_t hicn_face_udp_type;
-
-/* VFT table for the udp face. Mainly used to format the face in the right way */
-extern hicn_face_vft_t udp_vft;
-
-/**
- * @brief Create the key object for the mhash. Fill in the key object with the
- * expected values.
- *
- * @param local_addr Local address of the UDP tunnel
- * @param remote_addr Remote address of the UDP tunnel
- * @param local_port Local port of the UDP tunnel
- * @param remote_port Remote port of the UDP tunnel
- * @param key Pointer to an allocated hicn_face_udp_key_t object
- */
-always_inline void
-hicn_face_udp4_get_key (const ip4_address_t * local_addr,
- const ip4_address_t * remote_addr,
- u16 local_port, u16 remote_port,
- hicn_face_udp_key_t * key)
-{
-
- ip46_address_set_ip4 (&(key->local_addr), local_addr);
- ip46_address_set_ip4 (&(key->remote_addr), remote_addr);
- key->local_port = local_port;
- key->remote_port = remote_port;
-}
-
-/**
- * @brief Create the key object for the mhash. Fill in the key object with the
- * expected values.
- *
- * @param local_addr Local address of the UDP tunnel
- * @param remote_addr Remote address of the UDP tunnel
- * @param local_port Local port of the UDP tunnel
- * @param remote_port Remote port of the UDP tunnel
- * @param key Pointer to an allocated hicn_face_udp_key_t object
- */
-always_inline void
-hicn_face_udp6_get_key (const ip6_address_t * local_addr,
- const ip6_address_t * remote_addr,
- u16 local_port, u16 remote_port,
- hicn_face_udp_key_t * key)
-{
- key->local_addr.ip6 = *local_addr;
- key->remote_addr.ip6 = *remote_addr;
- key->local_port = local_port;
- key->remote_port = remote_port;
-}
-
-/**
- * @brief Get the dpoi from the quadruplet that identifies the face. Does not add any lock.
- *
- * @param local_addr Local address of the UDP tunnel
- * @param remote_addr Remote address of the UDP tunnel
- * @param local_port Local port of the UDP tunnel
- * @param remote_port Remote port of the UDP tunnel
- *
- * @result Pointer to the face.
- */
-always_inline hicn_face_t *
-hicn_face_udp4_get (const ip4_address_t * local_addr,
- const ip4_address_t * remote_addr,
- u16 local_port, u16 remote_port)
-{
- hicn_face_udp_key_t key;
-
- hicn_face_udp4_get_key (local_addr, remote_addr, local_port, remote_port,
- &key);
-
- hicn_face_id_t *dpoi_index =
- (hicn_face_id_t *) mhash_get (&hicn_face_udp_hashtb,
- &key);
-
- return dpoi_index == NULL ? NULL : hicn_dpoi_get_from_idx (*dpoi_index);
-}
-
-/**
- * @brief Get the dpoi from the quadruplet that identifies the face. Does not add any lock.
- *
- * @param local_addr Local address of the UDP tunnel (network order)
- * @param remote_addr Remote address of the UDP tunnel (network order)
- * @param local_port Local port of the UDP tunnel (network order)
- * @param remote_port Remote port of the UDP tunnel (network order)
- *
- * @result Pointer to the face.
- */
-always_inline hicn_face_t *
-hicn_face_udp6_get (const ip6_address_t * local_addr,
- const ip6_address_t * remote_addr,
- u16 local_port, u16 remote_port)
-{
- hicn_face_udp_key_t key;
-
- hicn_face_udp6_get_key (local_addr, remote_addr, local_port, remote_port,
- &key);
-
- hicn_face_id_t *dpoi_index =
- (hicn_face_id_t *) mhash_get (&hicn_face_udp_hashtb,
- &key);
-
- return dpoi_index == NULL ? NULL : hicn_dpoi_get_from_idx (*dpoi_index);
-}
-
-
-/**
- * @brief Initialize the udp face module
- */
-void hicn_face_udp_init (vlib_main_t * vm);
-
-/**
- * @brief Create a new face ip. API for other modules (e.g., routing)
- *
- * @param local_addr Local ip v4 or v6 address of the face (network order)
- * @param remote_addr Remote ip v4 or v6 address of the face (network order)
- * @param local_port Local udp port of the face (network order)
- * @param remote_port Remote udp port of the face (network order)
- * @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
- */
-int hicn_face_udp_add (const ip46_address_t * local_addr,
- const ip46_address_t * remote_addr, u16 local_port,
- u16 remote_port, u32 swif, hicn_face_id_t * pfaceid);
-
-/**
- * @brief Create a new incomplete face udp. (Meant to be used by the data plane)
- *
- * @param local_addr Local ip v6 address of the face
- * @param remote_addr Remote ip 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_udp6_add (const ip6_address_t * local_addr,
- const ip6_address_t * remote_addr, u16 local_port,
- u16 remote_port, int sw_if, hicn_face_id_t * pfaceid)
-{
- hicn_face_t *face;
- pool_get (hicn_dpoi_face_pool, face);
-
- hicn_face_udp_t *udp_face = (hicn_face_udp_t *) face->data;
-
- clib_memcpy (&(udp_face->hdrs.ip6.ip), &ip6_header_skl,
- sizeof (ip6_header_t));
- clib_memcpy (&(udp_face->hdrs.ip6.ip.src_address), local_addr,
- sizeof (ip6_address_t));
- clib_memcpy (&(udp_face->hdrs.ip6.ip.dst_address), remote_addr,
- sizeof (ip6_address_t));
-
- udp_face->hdrs.ip6.udp.src_port = local_port;
- udp_face->hdrs.ip6.udp.dst_port = remote_port;
-
- face->shared.adj = ADJ_INDEX_INVALID;
- face->shared.pl_id = (u16) 0;
- face->shared.face_type = hicn_face_udp_type;
- face->shared.flags = HICN_FACE_FLAGS_IFACE;
- face->shared.locks = 0;
- face->shared.sw_if = sw_if;
-
- hicn_face_udp_key_t key;
- hicn_face_udp6_get_key (local_addr, remote_addr, local_port,
- remote_port, &key);
- *pfaceid = hicn_dpoi_get_index (face);
-
- hicn_face_id_t dpoi_index = hicn_dpoi_get_index (face);
-
- mhash_set_mem (&hicn_face_udp_hashtb, &key, (uword *) & dpoi_index, 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);
- }
-}
-
-/**
- * @brief Create a new incomplete face udp. (Meant to be used by the data plane)
- *
- * @param local_addr Local ip v4 address of the face
- * @param remote_addr Remote ip v4 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_udp4_add (const ip4_address_t * local_addr,
- const ip4_address_t * remote_addr, u16 local_port,
- u16 remote_port, int sw_if, hicn_face_id_t * pfaceid)
-{
- hicn_face_t *face;
- pool_get (hicn_dpoi_face_pool, face);
-
- hicn_face_udp_t *udp_face = (hicn_face_udp_t *) face->data;
-
- clib_memcpy (&(udp_face->hdrs.ip4.ip), &ip4_header_skl,
- sizeof (ip4_header_t));
- clib_memcpy (&(udp_face->hdrs.ip4.ip.src_address), local_addr,
- sizeof (ip4_address_t));
- clib_memcpy (&(udp_face->hdrs.ip4.ip.dst_address), remote_addr,
- sizeof (ip4_address_t));
-
- udp_face->hdrs.ip4.udp.src_port = local_port;
- udp_face->hdrs.ip4.udp.dst_port = remote_port;
-
- face->shared.adj = ADJ_INDEX_INVALID;
- face->shared.pl_id = (u16) 0;
- face->shared.face_type = hicn_face_udp_type;
- face->shared.flags = HICN_FACE_FLAGS_IFACE;
- face->shared.locks = 1;
- face->shared.sw_if = sw_if;
-
- hicn_face_udp_key_t key;
- hicn_face_udp4_get_key (local_addr, remote_addr, local_port,
- remote_port, &key);
- *pfaceid = hicn_dpoi_get_index (face);
-
- hicn_face_id_t dpoi_index = hicn_dpoi_get_index (face);
-
- mhash_set_mem (&hicn_face_udp_hashtb, &key, (uword *) & dpoi_index, 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);
- }
-}
-
-/**
- * @brief Delete an ip 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_udp_del (hicn_face_id_t faceid);
-
-/**
- * @brief Format a UDP face
- *
- * @param s Pointer to a previous string. If null it will be initialize
- * @param args Array storing input values. Expected u32 indent and u32 face_id
- * @return String with the formatted face
- */
-u8 *format_hicn_face_udp (u8 * s, va_list * args);
-
-/**
- * @brief Create a dpo from a udp face
- *
- * @param face Face from which to create the dpo
- * @return the dpo
- */
-void hicn_face_udp_get_dpo (hicn_face_t * face, dpo_id_t * dpo);
-
-/**
- * @brief Init some internal structures
- */
-void hicn_face_udp_init_internal (void);
-
-#endif // __HICN_FACE_UDP_H__
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/hicn-plugin/src/faces/udp/face_udp_cli.c b/hicn-plugin/src/faces/udp/face_udp_cli.c
deleted file mode 100644
index 7bb172ce8..000000000
--- a/hicn-plugin/src/faces/udp/face_udp_cli.c
+++ /dev/null
@@ -1,164 +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 "face_udp.h"
-#include "dpo_udp.h"
-
-#include <vnet/vnet.h>
-#include <vnet/dpo/dpo.h>
-#include <vlib/vlib.h>
-#include <vnet/ip/format.h>
-
-#define HICN_FACE_NONE 0
-#define HICN_FACE_DELETE 1
-#define HICN_FACE_ADD 2
-
-
-static clib_error_t *
-hicn_face_udp_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 ();
- ip46_address_t src_addr;
- u32 src_port = 0;
- ip46_address_t dst_addr;
- u32 dst_port = 0;
- hicn_face_id_t face_id = HICN_FACE_NULL;
- int ret = HICN_ERROR_NONE;
- int sw_if;
- int face_op = HICN_FACE_NONE;
-
- ip46_address_reset (&src_addr);
- ip46_address_reset (&dst_addr);
- /* 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"))
- {
- if (unformat (line_input, "id %d", &face_id))
- face_op = HICN_FACE_DELETE;
- else
- {
- return clib_error_return (0, "missing face id");
- }
- }
- else if (unformat (line_input, "add"))
- {
- face_op = HICN_FACE_ADD;
- if (unformat
- (line_input, "src_addr %U port %u dst_addr %U port %u intfc %U",
- unformat_ip46_address, &src_addr, IP46_TYPE_ANY, &src_port,
- unformat_ip46_address, &dst_addr, IP46_TYPE_ANY, &dst_port,
- unformat_vnet_sw_interface, vnm, &sw_if));
- 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_id != HICN_FACE_NULL)
- {
- if (!hicn_dpoi_idx_is_valid (face_id))
- {
- return clib_error_return (0, "%s, face_id %d not valid",
- get_error_string (ret), face_id);
- }
- }
-
- int rv;
- switch (face_op)
- {
- case HICN_FACE_ADD:
-
- /* Check for presence of next hop address */
- if (((dst_addr.as_u64[0] == (u64) 0) && (dst_addr.as_u64[1] == (u64) 0))
- || dst_port == 0)
- {
- return clib_error_return (0, "dst address and port not specified");
- }
-
- if (((src_addr.as_u64[0] == (u64) 0) && (src_addr.as_u64[1] == (u64) 0))
- || src_port == 0)
- {
- return clib_error_return (0, "src address not specified");
- }
-
- rv =
- hicn_face_udp_add (&src_addr, &dst_addr,
- clib_host_to_net_u16 (src_port),
- clib_host_to_net_u16 (dst_port), sw_if, &face_id);
- if (rv == HICN_ERROR_NONE)
- {
- vlib_cli_output (vm, "Face id: %d", face_id);
- }
- else
- {
- return clib_error_return (0, get_error_string (rv));
- }
- break;
- case HICN_FACE_DELETE:
- rv = hicn_face_udp_del (face_id);
- if (rv == HICN_ERROR_NONE)
- {
- vlib_cli_output (vm, "Face %d deleted", face_id);
- }
- 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_udp_cli_set_command, static) =
-{
- .path = "hicn face udp",
- .short_help = "hicn face udp {add src_addr <src_address> port <src_port > dst_addr <dst_address> port <dst_port>} intfc <interface> | {del id <face_id>}",
- .function = hicn_face_udp_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/udp/face_udp_node.c b/hicn-plugin/src/faces/udp/face_udp_node.c
deleted file mode 100644
index c82336659..000000000
--- a/hicn-plugin/src/faces/udp/face_udp_node.c
+++ /dev/null
@@ -1,1030 +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 <vlib/vlib.h>
-#include <vnet/vnet.h>
-#include <vnet/ip/ip_packet.h>
-
-#include "face_udp.h"
-#include "face_udp_node.h"
-#include "dpo_udp.h"
-#include "../face.h"
-#include "../../strategy.h"
-#include "../../strategy_dpo_manager.h"
-#include "../../hicn.h"
-
-/**
- * @File
- *
- * Definition of the nodes for udp faces.
- */
-
-vlib_node_registration_t hicn_face_udp4_input_node;
-vlib_node_registration_t hicn_face_udp6_input_node;
-vlib_node_registration_t hicn_face_udp4_output_node;
-vlib_node_registration_t hicn_face_udp6_output_node;
-
-static char *hicn_face_udp4_input_error_strings[] = {
-#define _(sym, string) string,
- foreach_hicnfwd_error
-#undef _
-};
-
-static char *hicn_face_udp6_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];
-}
-hicn_face_udp4_input_trace_t;
-
-typedef enum
-{
- HICN_FACE_UDP4_INPUT_NEXT_DATA,
- HICN_FACE_UDP4_INPUT_NEXT_MAPME,
- HICN_FACE_UDP4_INPUT_NEXT_ERROR_DROP,
- HICN_FACE_UDP4_INPUT_N_NEXT,
-} hicn_face_udp4_input_next_t;
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
- u8 packet_data[60];
-}
-hicn_face_udp6_input_trace_t;
-
-typedef enum
-{
- HICN_FACE_UDP6_INPUT_NEXT_DATA,
- HICN_FACE_UDP6_INPUT_NEXT_MAPME,
- HICN_FACE_UDP6_INPUT_NEXT_ERROR_DROP,
- HICN_FACE_UDP6_INPUT_N_NEXT,
-} hicn_face_udp6_input_next_t;
-
-#define ERROR_INPUT_UDP4 HICN_FACE_UDP4_INPUT_NEXT_ERROR_DROP
-#define ERROR_INPUT_UDP6 HICN_FACE_UDP6_INPUT_NEXT_ERROR_DROP
-
-#define NEXT_MAPME_UDP4 HICN_FACE_UDP4_INPUT_NEXT_MAPME
-#define NEXT_MAPME_UDP6 HICN_FACE_UDP6_INPUT_NEXT_MAPME
-#define NEXT_DATA_UDP4 HICN_FACE_UDP4_INPUT_NEXT_DATA
-#define NEXT_DATA_UDP6 HICN_FACE_UDP6_INPUT_NEXT_DATA
-
-#define IP_HEADER_4 ip4_header_t
-#define IP_HEADER_6 ip6_header_t
-
-#define HICN_DPO_UDP_LOCK_IP4 hicn_dpo_udp4_lock
-#define HICN_DPO_UDP_LOCK_IP6 hicn_dpo_udp6_lock
-
-#define TRACE_INPUT_PKT_UDP4 hicn_face_udp4_input_trace_t
-#define TRACE_INPUT_PKT_UDP6 hicn_face_udp6_input_trace_t
-
-#define SIZE_HICN_HEADER4 sizeof(ip4_header_t) + sizeof(udp_header_t)
-#define SIZE_HICN_HEADER6 sizeof(ip6_header_t) + sizeof(udp_header_t)
-
-
-#define face_input_x1(ipv) \
- do { \
- int ret; \
- vlib_buffer_t *b0; \
- u32 bi0; \
- u32 next0 = ERROR_INPUT_UDP##ipv; \
- IP_HEADER_##ipv * ip_hdr = NULL; \
- u8 * inner_ip_hdr = NULL; \
- udp_header_t * udp_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, 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); \
- ip_hdr = (IP_HEADER_##ipv *) vlib_buffer_get_current(b0); \
- udp_hdr = (udp_header_t *) (ip_hdr + 1); \
- hicnb0 = hicn_get_buffer(b0); \
- \
- inner_ip_hdr = (u8 *)(udp_hdr + 1); \
- u8 is_v6 = hicn_is_v6((hicn_header_t *)inner_ip_hdr); \
- u8 is_icmp = is_v6*(inner_ip_hdr[6] == IPPROTO_ICMPV6) + \
- (1 - is_v6)*(inner_ip_hdr[9] == IPPROTO_ICMPV4); \
- \
- ret = HICN_DPO_UDP_LOCK_IP##ipv \
- (&(hicnb0->face_dpo_id), \
- &(ip_hdr->dst_address), \
- &(ip_hdr->src_address), \
- (udp_hdr->dst_port), \
- (udp_hdr->src_port), \
- &hicnb0->flags); \
- \
- if ( PREDICT_FALSE(ret != HICN_ERROR_NONE) ) \
- { \
- next0 = ERROR_INPUT_UDP##ipv; \
- } \
- else \
- { \
- next0 = is_icmp*NEXT_MAPME_UDP##ipv + \
- (1-is_icmp)*NEXT_DATA_UDP##ipv; \
- stats.pkts_data_count += 1; \
- \
- vlib_buffer_advance(b0, sizeof(IP_HEADER_##ipv) + \
- sizeof(udp_header_t)); \
- vlib_increment_combined_counter ( \
- &counters[hicnb0->face_dpo_id.dpoi_index \
- * HICN_N_COUNTER], thread_index, \
- HICN_FACE_COUNTERS_DATA_RX, \
- 1, \
- vlib_buffer_length_in_chain(vm, b0)); \
- } \
- \
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \
- (b0->flags & VLIB_BUFFER_IS_TRACED))) \
- { \
- TRACE_INPUT_PKT_UDP##ipv *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_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 { \
- int ret0, ret1; \
- vlib_buffer_t *b0, *b1; \
- u32 bi0, bi1; \
- u32 next0 = ERROR_INPUT_UDP##ipv; \
- u32 next1 = ERROR_INPUT_UDP##ipv; \
- IP_HEADER_##ipv * ip_hdr0 = NULL; \
- IP_HEADER_##ipv * ip_hdr1 = NULL; \
- u8 * inner_ip_hdr0 = NULL; \
- u8 * inner_ip_hdr1 = NULL; \
- udp_header_t * udp_hdr0 = NULL; \
- udp_header_t * udp_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, CLIB_CACHE_LINE_BYTES, STORE); \
- CLIB_PREFETCH (b3, 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); \
- ip_hdr0 = (IP_HEADER_##ipv *) vlib_buffer_get_current(b0); \
- ip_hdr1 = (IP_HEADER_##ipv *) vlib_buffer_get_current(b1); \
- udp_hdr0 = (udp_header_t *) (ip_hdr0 + 1); \
- udp_hdr1 = (udp_header_t *) (ip_hdr1 + 1); \
- hicnb0 = hicn_get_buffer(b0); \
- hicnb1 = hicn_get_buffer(b1); \
- \
- inner_ip_hdr0 = (u8 *)(udp_hdr0 + 1); \
- u8 is_v6_0 = hicn_is_v6((hicn_header_t *)inner_ip_hdr0); \
- u8 is_icmp0 = is_v6_0*(inner_ip_hdr0[6] == IPPROTO_ICMPV6) + \
- (1 - is_v6_0)*(inner_ip_hdr0[9] == IPPROTO_ICMPV4); \
- \
- inner_ip_hdr1 = (u8 *)(udp_hdr1 + 1); \
- u8 is_v6_1 = hicn_is_v6((hicn_header_t *)inner_ip_hdr1); \
- u8 is_icmp1 = is_v6_1*(inner_ip_hdr1[6] == IPPROTO_ICMPV6) + \
- (1 - is_v6_1)*(inner_ip_hdr1[9] == IPPROTO_ICMPV4); \
- \
- ret0 = HICN_DPO_UDP_LOCK_IP##ipv \
- (&(hicnb0->face_dpo_id), \
- &(ip_hdr0->dst_address), \
- &(ip_hdr0->src_address), \
- (udp_hdr0->dst_port), \
- (udp_hdr0->src_port), \
- &hicnb0->flags); \
- \
- ret1 = HICN_DPO_UDP_LOCK_IP##ipv \
- (&(hicnb1->face_dpo_id), \
- &(ip_hdr1->dst_address), \
- &(ip_hdr1->src_address), \
- (udp_hdr1->dst_port), \
- (udp_hdr1->src_port), \
- &hicnb1->flags); \
- \
- if ( PREDICT_FALSE(ret0 != HICN_ERROR_NONE) ) \
- { \
- next0 = ERROR_INPUT_UDP##ipv; \
- } \
- else \
- { \
- stats.pkts_data_count += 1; \
- next0 = is_icmp0*NEXT_MAPME_UDP##ipv + \
- (1-is_icmp0)*NEXT_DATA_UDP##ipv; \
- \
- vlib_buffer_advance(b0, sizeof(IP_HEADER_##ipv) + \
- sizeof(udp_header_t)); \
- vlib_increment_combined_counter ( \
- &counters[hicnb0->face_dpo_id.dpoi_index \
- * HICN_N_COUNTER], thread_index, \
- HICN_FACE_COUNTERS_DATA_RX, \
- 1, \
- vlib_buffer_length_in_chain(vm, b0)); \
- } \
- \
- if ( PREDICT_FALSE(ret1 != HICN_ERROR_NONE) ) \
- { \
- next1 = ERROR_INPUT_UDP##ipv; \
- } \
- else \
- { \
- stats.pkts_data_count += 1; \
- next1 = is_icmp1*NEXT_MAPME_UDP##ipv + \
- (1-is_icmp1)*NEXT_DATA_UDP##ipv; \
- \
- vlib_buffer_advance(b1, sizeof(IP_HEADER_##ipv) + \
- sizeof(udp_header_t)); \
- vlib_increment_combined_counter ( \
- &counters[hicnb1->face_dpo_id.dpoi_index \
- * HICN_N_COUNTER], thread_index,\
- HICN_FACE_COUNTERS_DATA_RX, \
- 1, \
- vlib_buffer_length_in_chain(vm, b1)); \
- } \
- \
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \
- (b0->flags & VLIB_BUFFER_IS_TRACED))) \
- { \
- TRACE_INPUT_PKT_UDP##ipv *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_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_UDP##ipv *t = \
- vlib_add_trace (vm, node, b1, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_CONTENT; \
- 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
-hicn_face_udp4_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 *
-hicn_face_udp4_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 *);
- hicn_face_udp4_input_trace_t *t =
- va_arg (*args, hicn_face_udp4_input_trace_t *);
-
- s =
- format (s, "FACE_UDP4_INPUT: pkt: %d, sw_if_index %d, next index %d\n%U",
- (int) t->pkt_type, t->sw_if_index, t->next_index,
- (t->packet_data[0] & 0xf0) ==
- 0x40 ? format_ip4_header : format_ip6_header, t->packet_data,
- sizeof (t->packet_data));
- return (s);
-}
-
-/*
- * Node registration for the interest forwarder node
- */
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (hicn_face_udp4_input_node) =
-{
- .function = hicn_face_udp4_input_node_fn,
- .name = "hicn-face-udp4-input",
- .vector_size = sizeof (u32),
- .format_trace = hicn_face_udp4_input_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicn_face_udp4_input_error_strings),
- .error_strings = hicn_face_udp4_input_error_strings,
- .n_next_nodes = HICN_FACE_UDP4_INPUT_N_NEXT,
- /* edit / add dispositions here */
- .next_nodes =
- {
- [HICN_FACE_UDP4_INPUT_NEXT_DATA] = "hicn-data-pcslookup",
- [HICN_FACE_UDP4_INPUT_NEXT_MAPME] = "hicn-mapme-ack",
- [HICN_FACE_UDP4_INPUT_NEXT_ERROR_DROP] = "error-drop",
- },
-};
-/* *INDENT-ON* */
-
-
-static uword
-hicn_face_udp6_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_PROCESSED, stats.pkts_processed);
-
- 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 *
-hicn_face_udp6_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 *);
- hicn_face_udp6_input_trace_t *t =
- va_arg (*args, hicn_face_udp6_input_trace_t *);
-
- s =
- format (s, "FACE_UDP6_INPUT: pkt: %d, sw_if_index %d, next index %d\n%U",
- (int) t->pkt_type, t->sw_if_index, t->next_index,
- (t->packet_data[0] & 0xf0) ==
- 0x40 ? format_ip4_header : format_ip6_header, t->packet_data,
- sizeof (t->packet_data));
- return (s);
-}
-
-/*
- * Node registration for the interest forwarder node
- */
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (hicn_face_udp6_input_node) =
-{
- .function = hicn_face_udp6_input_node_fn,
- .name = "hicn-face-udp6-input",
- .vector_size = sizeof (u32),
- .format_trace = hicn_face_udp6_input_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicn_face_udp6_input_error_strings),
- .error_strings = hicn_face_udp6_input_error_strings,
- .n_next_nodes = HICN_FACE_UDP6_INPUT_N_NEXT,
- /* edit / add dispositions here */
- .next_nodes =
- {
- [HICN_FACE_UDP6_INPUT_NEXT_DATA] = "hicn-data-pcslookup",
- [HICN_FACE_UDP6_INPUT_NEXT_MAPME] = "hicn-mapme-ack",
- [HICN_FACE_UDP6_INPUT_NEXT_ERROR_DROP] = "error-drop",
- },
-};
-/* *INDENT-ON* */
-
-/******* Face Output *******/
-
-always_inline void
-hicn_face_udp4_encap (vlib_main_t * vm,
- vlib_buffer_t * outer_b0,
- hicn_face_t * face, u32 * next)
-{
- u16 old_l0 = 0, new_l0;
- ip_csum_t sum0;
- ip4_header_t *ip0;
- udp_header_t *udp0;
- hicn_face_udp_t *face_udp = (hicn_face_udp_t *) face->data;
-
- /* ip */
- ip0 = vlib_buffer_get_current (outer_b0);
- clib_memcpy (ip0, &(face_udp->hdrs.ip4.ip), sizeof (ip4_header_t) +
- sizeof (udp_header_t));
-
- /* Fix UDP length */
- udp0 = (udp_header_t *) (ip0 + 1);
-
- new_l0 =
- clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, outer_b0) -
- sizeof (*ip0));
- udp0->length = new_l0;
-
- old_l0 = ip0->length;
- ip0->length =
- clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, outer_b0));
-
- sum0 = ip0->checksum;
-
- //old_l0 always 0, see the rewrite setup
- new_l0 = ip0->length;
-
- sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
- length /* changed member */ );
- ip0->checksum = sum0;
-
- int is_iface = 0;
- ip_adjacency_t *adj;
- if (PREDICT_FALSE (face->shared.adj == ~0))
- is_iface = 1;
- else
- adj = adj_get (face->shared.adj);
-
- /* In case the adj is not complete, we look if a better one exists, otherwise we send an arp request
- * This is necessary to account for the case in which when we create a face, there isn't a /128(/32) adjacency and we match with a more general route which is in glean state
- * In this case in fact, the general route will not be update upone receiving of a arp or neighbour responde, but a new /128(/32) will be created
- */
- if (PREDICT_FALSE
- (is_iface || adj->lookup_next_index < IP_LOOKUP_NEXT_REWRITE))
- {
- fib_prefix_t fib_pfx;
- fib_node_index_t fib_entry_index;
- ip46_address_t ip46 =
- to_ip46 (0, (u8 *) & (face_udp->hdrs.ip4.ip.dst_address));
- fib_prefix_from_ip46_addr (&ip46, &fib_pfx);
- fib_pfx.fp_len = 32;
-
- u32 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 (fib_index, &fib_pfx);
-
- face->shared.adj = fib_entry_get_adj (fib_entry_index);
- face->shared.flags &= ~HICN_FACE_FLAGS_IFACE;
- face->shared.flags |= HICN_FACE_FLAGS_FACE;
-
- adj = adj_get (face->shared.adj);
- }
-
- vnet_buffer (outer_b0)->ip.adj_index[VLIB_TX] = face->shared.adj;
- *next = adj->lookup_next_index;
-}
-
-always_inline void
-hicn_face_udp6_encap (vlib_main_t * vm,
- vlib_buffer_t * outer_b0,
- hicn_face_t * face, u32 * next)
-{
- int bogus0;
- u16 new_l0;
- ip6_header_t *ip0;
- udp_header_t *udp0;
- hicn_face_udp_t *face_udp = (hicn_face_udp_t *) face->data;
-
- /* ip */
- ip0 = vlib_buffer_get_current (outer_b0);
- clib_memcpy (ip0, &(face_udp->hdrs.ip6.ip), sizeof (ip6_header_t) +
- sizeof (udp_header_t));
- new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, outer_b0)
- - sizeof (*ip0));
- ip0->payload_length = new_l0;
-
- /* Fix UDP length */
- udp0 = (udp_header_t *) (ip0 + 1);
- udp0->length = new_l0;
-
- udp0->checksum =
- ip6_tcp_udp_icmp_compute_checksum (vm, outer_b0, ip0, &bogus0);
-
- ASSERT (bogus0 == 0);
-
- if (udp0->checksum == 0)
- udp0->checksum = 0xffff;
-
- int is_iface = 0;
- ip_adjacency_t *adj;
- if (PREDICT_FALSE (face->shared.adj == ~0))
- is_iface = 1;
- else
- adj = adj_get (face->shared.adj);
-
- /* In case the adj is not complete, we look if a better one exists, otherwise we send an arp request
- * This is necessary to account for the case in which when we create a face, there isn't a /128(/32) adjacency and we match with a more general route which is in glean state
- * In this case in fact, the general route will not be update upone receiving of a arp or neighbour responde, but a new /128(/32) will be created
- */
- if (PREDICT_FALSE (is_iface || adj->lookup_next_index < IP_LOOKUP_NEXT_REWRITE))
- {
- fib_prefix_t fib_pfx;
- fib_node_index_t fib_entry_index;
- ip46_address_t ip46 =
- to_ip46 (1, (u8 *) & (face_udp->hdrs.ip6.ip.dst_address));
- fib_prefix_from_ip46_addr (&ip46, &fib_pfx);
- fib_pfx.fp_len = 128;
-
- u32 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 (fib_index, &fib_pfx);
-
- face->shared.adj = fib_entry_get_adj (fib_entry_index);
- face->shared.flags &= ~HICN_FACE_FLAGS_IFACE;
- face->shared.flags |= HICN_FACE_FLAGS_FACE;
-
- adj = adj_get (face->shared.adj);
- }
-
- vnet_buffer (outer_b0)->ip.adj_index[VLIB_TX] = face->shared.adj;
-
- *next = adj->lookup_next_index;
-}
-
-static char *hicn_face_udp4_output_error_strings[] = {
-#define _(sym, string) string,
- foreach_hicnfwd_error
-#undef _
-};
-
-static char *hicn_face_udp6_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];
-}
-hicn_face_udp4_output_trace_t;
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
- u8 packet_data[60];
-}
-hicn_face_udp6_output_trace_t;
-
-#define HICN_FACE_UDP_ENCAP_IP4 hicn_face_udp4_encap
-#define HICN_FACE_UDP_ENCAP_IP6 hicn_face_udp6_encap
-
-#define TRACE_OUTPUT_PKT_UDP4 hicn_face_udp4_output_trace_t
-#define TRACE_OUTPUT_PKT_UDP6 hicn_face_udp6_output_trace_t
-
-#define IP_HEADER_4 ip4_header_t
-#define IP_HEADER_6 ip6_header_t
-
-#define face_output_x1(ipv) \
- do { \
- vlib_buffer_t *b0; \
- u32 bi0; \
- u32 next0 = IP_LOOKUP_NEXT_DROP; \
- 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 , LOAD); \
- } \
- /* Dequeue a packet buffer */ \
- bi0 = from[0]; \
- from += 1; \
- n_left_from -= 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)) \
- { \
- /* Adjust vlib buffer. Create space for the udp tunnel. */ \
- vlib_buffer_advance(b0, -(sizeof (IP_HEADER_##ipv) + \
- sizeof (udp_header_t))); \
- \
- \
- HICN_FACE_UDP_ENCAP_IP##ipv \
- (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_UDP##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) + \
- SIZE_HICN_HEADER##ipv, \
- sizeof (t->packet_data)); \
- } \
- \
- to_next[0] = bi0; \
- to_next += 1; \
- n_left_to_next -= 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); \
- } while(0) \
-
-
-#define face_output_x2(ipv) \
- do { \
- vlib_buffer_t *b0, *b1; \
- u32 bi0, bi1; \
- u32 next0 = IP_LOOKUP_NEXT_DROP; \
- u32 next1 = IP_LOOKUP_NEXT_DROP; \
- 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 , 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); \
- \
- 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(vnet_buffer (b0)->ip.adj_index[VLIB_TX]); \
- face1 = \
- hicn_dpoi_get_from_idx(vnet_buffer (b1)->ip.adj_index[VLIB_TX]); \
- \
- if (PREDICT_TRUE(face0 != NULL)) \
- { \
- /* Adjust vlib buffer. Create space for the udp tunnel. */ \
- vlib_buffer_advance(b0, -(sizeof (IP_HEADER_##ipv) + \
- sizeof (udp_header_t))); \
- \
- \
- HICN_FACE_UDP_ENCAP_IP##ipv \
- (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)) \
- { \
- /* Adjust vlib buffer. Create space for the udp tunnel. */ \
- vlib_buffer_advance(b1, -(sizeof (IP_HEADER_##ipv) + \
- sizeof (udp_header_t))); \
- \
- \
- HICN_FACE_UDP_ENCAP_IP##ipv \
- (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_UDP##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) + \
- SIZE_HICN_HEADER##ipv, \
- sizeof (t->packet_data)); \
- } \
- \
- \
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \
- (b1->flags & VLIB_BUFFER_IS_TRACED))) \
- { \
- TRACE_OUTPUT_PKT_UDP##ipv *t = \
- vlib_add_trace (vm, node, b0, 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) + \
- SIZE_HICN_HEADER##ipv, \
- 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
-hicn_face_udp4_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 *
-hicn_face_udp4_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 *);
- hicn_face_udp4_output_trace_t *t =
- va_arg (*args, hicn_face_udp4_output_trace_t *);
-
- s =
- format (s, "FACE_UDP4_OUTPUT: pkt: %d, sw_if_index %d, next index %d\n%U",
- (int) t->pkt_type, t->sw_if_index, t->next_index,
- (t->packet_data[0] & 0xf0) ==
- 0x40 ? format_ip4_header : format_ip6_header, t->packet_data,
- sizeof (t->packet_data));
- return (s);
-}
-
-/* *INDENT-OFF* */
-/*
- * Node registration for the interest forwarder node
- */
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (hicn_face_udp4_output_node) =
-{
- .function = hicn_face_udp4_output_node_fn,
- .name = "hicn-face-udp4-output",
- .vector_size = sizeof (u32),
- .format_trace = hicn_face_udp4_output_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicn_face_udp4_output_error_strings),
- .error_strings = hicn_face_udp4_output_error_strings,
- .n_next_nodes = IP4_LOOKUP_N_NEXT,
- /* Reusing the list of nodes from lookup to be compatible with arp */
- .next_nodes = IP4_LOOKUP_NEXT_NODES,
-};
-/* *INDENT-ON* */
-
-/* *INDENT-ON* */
-
-static uword
-hicn_face_udp6_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);
- }
-
- 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 *
-hicn_face_udp6_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 *);
- hicn_face_udp6_output_trace_t *t =
- va_arg (*args, hicn_face_udp6_output_trace_t *);
-
- s =
- format (s, "FACE_UDP6_OUTPUT: pkt: %d, sw_if_index %d, next index %d\n%u",
- (int) t->pkt_type, t->sw_if_index, t->next_index,
- (t->packet_data[0] & 0xf0) ==
- 0x40 ? format_ip4_header : format_ip6_header, t->packet_data,
- sizeof (t->packet_data));
- return (s);
-}
-
-/* *INDENT-OFF* */
-/*
- * Node registration for the interest forwarder node
- */
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (hicn_face_udp6_output_node) =
-{
- .function = hicn_face_udp6_output_node_fn,
- .name = "hicn-face-udp6-output",
- .vector_size = sizeof (u32),
- .format_trace = hicn_face_udp6_output_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicn_face_udp6_output_error_strings),
- .error_strings = hicn_face_udp6_output_error_strings,
- .n_next_nodes = IP6_LOOKUP_N_NEXT,
- /* Reusing the list of nodes from lookup to be compatible with neighbour discovery */
- .next_nodes = IP6_LOOKUP_NEXT_NODES,
-};
-/* *INDENT-ON* */
-
-/* *INDENT-ON* */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/hicn-plugin/src/faces/udp/iface_udp_node.c b/hicn-plugin/src/faces/udp/iface_udp_node.c
deleted file mode 100644
index 1fdd68f0b..000000000
--- a/hicn-plugin/src/faces/udp/iface_udp_node.c
+++ /dev/null
@@ -1,987 +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 "iface_udp_node.h"
-#include "dpo_udp.h"
-#include "../face.h"
-
-#include "../../infra.h"
-#include "../../hicn.h"
-
-/**
- * @File
- *
- * Definition of the nodes for udp incomplete faces.
- */
-
-vlib_node_registration_t hicn_iface_udp4_input_node;
-vlib_node_registration_t hicn_iface_udp6_input_node;
-vlib_node_registration_t hicn_iface_udp4_output_node;
-vlib_node_registration_t hicn_iface_udp6_output_node;
-
-u32 data_fwd_face_udp4_vlib_edge;
-u32 data_fwd_face_udp6_vlib_edge;
-
-void
-hicn_iface_udp_init (vlib_main_t * vm)
-{
- data_fwd_face_udp4_vlib_edge = vlib_node_add_next (vm,
- hicn_data_fwd_node.index,
- hicn_iface_udp4_output_node.index);
-
- data_fwd_face_udp6_vlib_edge = vlib_node_add_next (vm,
- hicn_data_fwd_node.index,
- hicn_iface_udp6_output_node.index);
-
- u32 temp_index4 = vlib_node_add_next (vm,
- hicn_interest_hitcs_node.index,
- hicn_iface_udp4_output_node.index);
- u32 temp_index6 = vlib_node_add_next (vm,
- hicn_interest_hitcs_node.index,
- hicn_iface_udp6_output_node.index);
-
- ASSERT (temp_index4 == data_fwd_face_udp4_vlib_edge);
- ASSERT (temp_index6 == data_fwd_face_udp6_vlib_edge);
-}
-
-static char *hicn_iface_udp4_input_error_strings[] = {
-#define _(sym, string) string,
- foreach_hicnfwd_error
-#undef _
-};
-
-static char *hicn_iface_udp6_input_error_strings[] = {
-#define _(sym, string) string,
- foreach_hicnfwd_error
-#undef _
-};
-
-u32
-get_face_udp4_output_node (void)
-{
- return data_fwd_face_udp4_vlib_edge;
-}
-
-u32
-get_face_udp6_output_node (void)
-{
- return data_fwd_face_udp6_vlib_edge;
-}
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
- u8 packet_data[60];
-}
-hicn_iface_udp4_input_trace_t;
-
-typedef enum
-{
- HICN_IFACE_UDP4_INPUT_NEXT_INTEREST,
- HICN_IFACE_UDP4_INPUT_NEXT_MAPME,
- HICN_IFACE_UDP4_INPUT_NEXT_ERROR_DROP,
- HICN_IFACE_UDP4_INPUT_N_NEXT,
-} hicn_iface_udp4_input_next_t;
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
- u8 packet_data[60];
-}
-hicn_iface_udp6_input_trace_t;
-
-typedef enum
-{
- HICN_IFACE_UDP6_INPUT_NEXT_INTEREST,
- HICN_IFACE_UDP6_INPUT_NEXT_MAPME,
- HICN_IFACE_UDP6_INPUT_NEXT_ERROR_DROP,
- HICN_IFACE_UDP6_INPUT_N_NEXT,
-} hicn_iface_udp6_input_next_t;
-
-#define ERROR_INPUT_UDP4 HICN_IFACE_UDP4_INPUT_NEXT_ERROR_DROP
-#define ERROR_INPUT_UDP6 HICN_IFACE_UDP6_INPUT_NEXT_ERROR_DROP
-
-#define IP_HEADER_4 ip4_header_t
-#define IP_HEADER_6 ip6_header_t
-
-#define NEXT_MAPME_UDP4 HICN_IFACE_UDP4_INPUT_NEXT_MAPME
-#define NEXT_MAPME_UDP6 HICN_IFACE_UDP6_INPUT_NEXT_MAPME
-
-#define NEXT_INTEREST_UDP4 HICN_IFACE_UDP4_INPUT_NEXT_INTEREST
-#define NEXT_INTEREST_UDP6 HICN_IFACE_UDP6_INPUT_NEXT_INTEREST
-
-#define HICN_IFACE_UDP_ADD_LOCK_IP4 hicn_dpo_udp4_add_and_lock
-#define HICN_IFACE_UDP_ADD_LOCK_IP6 hicn_dpo_udp6_add_and_lock
-
-#define GET_FACE_UDP4 get_face_udp4_output_node
-#define GET_FACE_UDP6 get_face_udp6_output_node
-
-#define TRACE_INPUT_PKT_UDP4 hicn_iface_udp4_input_trace_t
-#define TRACE_INPUT_PKT_UDP6 hicn_iface_udp6_input_trace_t
-
-#define iface_input_x1(ipv) \
- do { \
- vlib_buffer_t *b0; \
- u32 bi0; \
- u32 next0 = ERROR_INPUT_UDP##ipv; \
- IP_HEADER_##ipv * ip_hdr = NULL; \
- u8 * inner_ip_hdr = NULL; \
- udp_header_t * udp_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, 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); \
- ip_hdr = (IP_HEADER_##ipv *) vlib_buffer_get_current(b0); \
- udp_hdr = (udp_header_t *) (ip_hdr + 1); \
- hicnb0 = hicn_get_buffer(b0); \
- \
- stats.pkts_interest_count += 1; \
- \
- inner_ip_hdr = (u8 *)(udp_hdr + 1); \
- u8 is_v6 = hicn_is_v6((hicn_header_t *)inner_ip_hdr); \
- u8 is_icmp = is_v6*(inner_ip_hdr[6] == IPPROTO_ICMPV6) + \
- (1 - is_v6)*(inner_ip_hdr[9] == IPPROTO_ICMPV4); \
- \
- next0 = is_icmp*NEXT_MAPME_UDP##ipv + \
- (1-is_icmp)*NEXT_INTEREST_UDP##ipv; \
- \
- HICN_IFACE_UDP_ADD_LOCK_IP##ipv \
- (&(hicnb0->face_dpo_id), \
- &(ip_hdr->dst_address), \
- &(ip_hdr->src_address), \
- udp_hdr->dst_port, \
- udp_hdr->src_port, \
- GET_FACE_UDP##ipv \
- (), \
- &hicnb0->flags, \
- vnet_buffer(b0)->sw_if_index[VLIB_RX]); \
- \
- vlib_buffer_advance(b0, sizeof(IP_HEADER_##ipv) + \
- sizeof(udp_header_t)); \
- \
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \
- (b0->flags & VLIB_BUFFER_IS_TRACED))) \
- { \
- TRACE_INPUT_PKT_UDP##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_dpo_id.dpoi_index \
- * 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; \
- u32 next0, next1 = ERROR_INPUT_UDP##ipv; \
- IP_HEADER_##ipv * ip_hdr0 = NULL, *ip_hdr1 = NULL; \
- u8 * inner_ip_hdr0 = NULL, *inner_ip_hdr1 = NULL; \
- udp_header_t * udp_hdr0 = NULL, *udp_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, CLIB_CACHE_LINE_BYTES, STORE); \
- CLIB_PREFETCH (b3, 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); \
- ip_hdr0 = (IP_HEADER_##ipv *) vlib_buffer_get_current(b0); \
- ip_hdr1 = (IP_HEADER_##ipv *) vlib_buffer_get_current(b1); \
- udp_hdr0 = (udp_header_t *) (ip_hdr0 + 1); \
- udp_hdr1 = (udp_header_t *) (ip_hdr1 + 1); \
- hicnb0 = hicn_get_buffer(b0); \
- hicnb1 = hicn_get_buffer(b1); \
- \
- stats.pkts_interest_count += 2; \
- \
- inner_ip_hdr0 = (u8 *)(udp_hdr0 + 1); \
- inner_ip_hdr1 = (u8 *)(udp_hdr1 + 1); \
- u8 is_v6_0 = hicn_is_v6((hicn_header_t *)inner_ip_hdr0); \
- u8 is_v6_1 = hicn_is_v6((hicn_header_t *)inner_ip_hdr1); \
- u8 is_icmp0 = is_v6_0*(inner_ip_hdr0[6] == IPPROTO_ICMPV6) + \
- (1 - is_v6_0)*(inner_ip_hdr0[9] == IPPROTO_ICMPV4); \
- u8 is_icmp1 = is_v6_1*(inner_ip_hdr1[6] == IPPROTO_ICMPV6) + \
- (1 - is_v6_1)*(inner_ip_hdr1[9] == IPPROTO_ICMPV4); \
- \
- next0 = is_icmp0*NEXT_MAPME_UDP##ipv + \
- (1-is_icmp0)*NEXT_INTEREST_UDP##ipv; \
- next1 = is_icmp1*NEXT_MAPME_UDP##ipv + \
- (1-is_icmp1)*NEXT_INTEREST_UDP##ipv; \
- \
- HICN_IFACE_UDP_ADD_LOCK_IP##ipv \
- (&(hicnb0->face_dpo_id), \
- &(ip_hdr0->dst_address), \
- &(ip_hdr0->src_address), \
- udp_hdr0->dst_port, \
- udp_hdr0->src_port, \
- GET_FACE_UDP##ipv \
- (), \
- &hicnb0->flags, \
- vnet_buffer(b0)->sw_if_index[VLIB_RX]); \
- \
- \
- HICN_IFACE_UDP_ADD_LOCK_IP##ipv \
- (&(hicnb1->face_dpo_id), \
- &(ip_hdr1->dst_address), \
- &(ip_hdr1->src_address), \
- udp_hdr1->dst_port, \
- udp_hdr1->src_port, \
- GET_FACE_UDP##ipv \
- (), \
- &hicnb1->flags, \
- vnet_buffer(b1)->sw_if_index[VLIB_RX]); \
- \
- vlib_buffer_advance(b0, sizeof(IP_HEADER_##ipv) + \
- sizeof(udp_header_t)); \
- \
- vlib_buffer_advance(b1, sizeof(IP_HEADER_##ipv) + \
- sizeof(udp_header_t)); \
- \
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \
- (b0->flags & VLIB_BUFFER_IS_TRACED))) \
- { \
- TRACE_INPUT_PKT_UDP##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_UDP##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_dpo_id.dpoi_index \
- * 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_dpo_id.dpoi_index \
- * 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
-hicn_iface_udp4_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;
- 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)
- {
- 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 *
-hicn_iface_udp4_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 *);
- hicn_iface_udp4_input_trace_t *t =
- va_arg (*args, hicn_iface_udp4_input_trace_t *);
-
- s =
- format (s, "IFACE_UDP4_INPUT: pkt: %d, sw_if_index %d, next index %d\n%U",
- (int) t->pkt_type, t->sw_if_index, t->next_index,
- (t->packet_data[0] & 0xf0) ==
- 0x40 ? format_ip4_header : format_ip6_header, t->packet_data,
- sizeof (t->packet_data));
- return (s);
-}
-
-/*
- * Node registration for the interest forwarder node
- */
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (hicn_iface_udp4_input_node) =
-
-{
- .function = hicn_iface_udp4_input_node_fn,
- .name = "hicn-iface-udp4-input",
- .vector_size = sizeof (u32),
- .format_trace = hicn_iface_udp4_input_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicn_iface_udp4_input_error_strings),
- .error_strings = hicn_iface_udp4_input_error_strings,
- .n_next_nodes = HICN_IFACE_UDP4_INPUT_N_NEXT,
- .next_nodes =
- {
- [HICN_IFACE_UDP4_INPUT_NEXT_INTEREST] = "hicn-interest-pcslookup",
- [HICN_IFACE_UDP4_INPUT_NEXT_MAPME] = "hicn-mapme-ctrl",
- [HICN_IFACE_UDP4_INPUT_NEXT_ERROR_DROP] = "error-drop",
- },
-};
-/* *INDENT-ON* */
-
-
-static uword
-hicn_iface_udp6_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;
- 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)
- {
- 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 *
-hicn_iface_udp6_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 *);
- hicn_iface_udp6_input_trace_t *t =
- va_arg (*args, hicn_iface_udp6_input_trace_t *);
-
- s =
- format (s, "IFACE_UDP6_INPUT: pkt: %d, sw_if_index %d, next index %d\n%U",
- (int) t->pkt_type, t->sw_if_index, t->next_index,
- (t->packet_data[0] & 0xf0) ==
- 0x40 ? format_ip4_header : format_ip6_header, t->packet_data,
- sizeof (t->packet_data));
- return (s);
-}
-
-/*
- * Node registration for the interest forwarder node
- */
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (hicn_iface_udp6_input_node) =
-{
- .function = hicn_iface_udp6_input_node_fn,
- .name = "hicn-iface-udp6-input",
- .vector_size = sizeof (u32),
- .format_trace = hicn_iface_udp6_input_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicn_iface_udp6_input_error_strings),
- .error_strings = hicn_iface_udp6_input_error_strings,
- .n_next_nodes = HICN_IFACE_UDP6_INPUT_N_NEXT,
- .next_nodes =
- {
- [HICN_IFACE_UDP6_INPUT_NEXT_INTEREST] = "hicn-interest-pcslookup",
- [HICN_IFACE_UDP6_INPUT_NEXT_MAPME] = "hicn-mapme-ctrl",
- [HICN_IFACE_UDP6_INPUT_NEXT_ERROR_DROP] = "error-drop",
- },
-};
-/* *INDENT-ON* */
-
-/******* Iface Output *******/
-
-always_inline void
-hicn_iface_udp4_encap (vlib_main_t * vm,
- vlib_buffer_t * b0, hicn_face_t * face)
-{
- u16 new_l0 = 0;
- ip4_header_t *ip0;
- udp_header_t *udp0;
- hicn_face_udp_t *face_udp = (hicn_face_udp_t *) face->data;
-
- /* Adjust vlib buffers */
- /* Set the right length on the header buffer */
- /* Move the next buffer current data pointer back to the ip+tcp header (hicn header) */
- word offset = sizeof (ip4_header_t) + sizeof (udp_header_t);
- vlib_buffer_advance (b0, -offset);
-
- /* ip */
- ip0 = vlib_buffer_get_current (b0);
- clib_memcpy (ip0, &(face_udp->hdrs.ip4.ip), sizeof (ip4_header_t) +
- sizeof (udp_header_t));
-
- /* Fix UDP length */
- udp0 = (udp_header_t *) (ip0 + 1);
-
- new_l0 =
- clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) -
- sizeof (*ip0));
- udp0->length = new_l0;
-
- ip0->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
- ip0->checksum = ip4_header_checksum (ip0);
-}
-
-always_inline void
-hicn_iface_udp6_encap (vlib_main_t * vm,
- vlib_buffer_t * b0, hicn_face_t * face)
-{
- int bogus0;
- u16 new_l0;
- ip6_header_t *ip0;
- udp_header_t *udp0;
- hicn_face_udp_t *face_udp = (hicn_face_udp_t *) face->data;
-
- /* Adjust vlib buffer */
- word offset = sizeof (ip6_header_t) + sizeof (udp_header_t);
- vlib_buffer_advance (b0, -offset);
-
- /* ip */
- ip0 = vlib_buffer_get_current (b0);
- clib_memcpy (ip0, &(face_udp->hdrs.ip6.ip), sizeof (ip6_header_t) +
- sizeof (udp_header_t));
-
- new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
- - sizeof (*ip0));
-
- ip0->payload_length = new_l0;
-
- /* Fix UDP length */
- udp0 = (udp_header_t *) (ip0 + 1);
- udp0->length = new_l0;
-
- udp0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, &bogus0);
-
- ASSERT (bogus0 == 0);
-
- if (udp0->checksum == 0)
- udp0->checksum = 0xffff;
-}
-
-static char *hicn_iface_udp4_output_error_strings[] = {
-#define _(sym, string) string,
- foreach_hicnfwd_error
-#undef _
-};
-
-static char *hicn_iface_udp6_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];
-}
-hicn_iface_udp4_output_trace_t;
-
-typedef enum
-{
- HICN_IFACE_UDP4_OUTPUT_NEXT_LOOKUP,
- HICN_IFACE_UDP4_OUTPUT_NEXT_ERROR_DROP,
- HICN_IFACE_UDP4_OUTPUT_N_NEXT,
-} hicn_iface_udp4_output_next_t;
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
- u8 packet_data[60];
-}
-hicn_iface_udp6_output_trace_t;
-
-typedef enum
-{
- HICN_IFACE_UDP6_OUTPUT_NEXT_LOOKUP,
- HICN_IFACE_UDP6_OUTPUT_NEXT_ERROR_DROP,
- HICN_IFACE_UDP6_OUTPUT_N_NEXT,
-} hicn_iface_udp6_output_next_t;
-
-#define ERROR_OUTPUT_UDP4 HICN_IFACE_UDP4_OUTPUT_NEXT_ERROR_DROP
-#define ERROR_OUTPUT_UDP6 HICN_IFACE_UDP6_OUTPUT_NEXT_ERROR_DROP
-
-#define IP_HEADER_4 ip4_header_t
-#define IP_HEADER_6 ip6_header_t
-
-#define NEXT_LOOKUP_UDP4 HICN_IFACE_UDP4_OUTPUT_NEXT_LOOKUP
-#define NEXT_LOOKUP_UDP6 HICN_IFACE_UDP6_OUTPUT_NEXT_LOOKUP
-
-#define HICN_IFACE_UDP_ADD_LOCK_IP4 hicn_dpo_udp4_add_and_lock
-#define HICN_IFACE_UDP_ADD_LOCK_IP6 hicn_dpo_udp6_add_and_lock
-
-#define HICN_FACE_UDP_ENCAP_IP4 hicn_iface_udp4_encap
-#define HICN_FACE_UDP_ENCAP_IP6 hicn_iface_udp6_encap
-
-#define TRACE_OUTPUT_PKT_UDP4 hicn_iface_udp4_output_trace_t
-#define TRACE_OUTPUT_PKT_UDP6 hicn_iface_udp6_output_trace_t
-
-#define SIZE_HICN_HEADER4 sizeof(ip4_header_t) + sizeof(udp_header_t)
-#define SIZE_HICN_HEADER6 sizeof(ip6_header_t) + sizeof(udp_header_t)
-
-#define iface_output_x1(ipv) \
- do { \
- vlib_buffer_t *b0; \
- u32 bi0; \
- u32 next0 = ERROR_OUTPUT_UDP##ipv; \
- 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 , 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); \
- \
- 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_UDP_ENCAP_IP##ipv \
- (vm, b0, face); \
- next0 = NEXT_LOOKUP_UDP##ipv; \
- 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_UDP##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) + \
- SIZE_HICN_HEADER##ipv, \
- 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 = ERROR_OUTPUT_UDP##ipv, next1 = ERROR_OUTPUT_UDP##ipv; \
- 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 , LOAD); \
- CLIB_PREFETCH (b3->data, CLIB_CACHE_LINE_BYTES , LOAD); \
- } \
- \
- /* Dequeue packets buffers */ \
- 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_UDP_ENCAP_IP##ipv \
- (vm, b0, face0); \
- next0 = NEXT_LOOKUP_UDP##ipv; \
- 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_FACE_UDP_ENCAP_IP##ipv \
- (vm, b1, face1); \
- next1 = NEXT_LOOKUP_UDP##ipv; \
- 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_UDP##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) + \
- SIZE_HICN_HEADER##ipv, \
- sizeof (t->packet_data)); \
- } \
- \
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \
- (b1->flags & VLIB_BUFFER_IS_TRACED))) \
- { \
- TRACE_OUTPUT_PKT_UDP##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) + \
- SIZE_HICN_HEADER##ipv, \
- 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
-hicn_iface_udp4_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 *
-hicn_iface_udp4_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 *);
- hicn_iface_udp4_output_trace_t *t =
- va_arg (*args, hicn_iface_udp4_output_trace_t *);
-
- s =
- format (s,
- "IFACE_UDP4_OUTPUT: pkt: %d, out face %d, next index %d\n%U",
- (int) t->pkt_type, t->sw_if_index, t->next_index,
- (t->packet_data[0] & 0xf0) ==
- 0x40 ? format_ip4_header : format_ip6_header, t->packet_data,
- sizeof (t->packet_data));
- return (s);
-}
-
-
-/*
- * Node registration for the interest forwarder node
- */
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (hicn_iface_udp4_output_node) =
-{
- .function = hicn_iface_udp4_output_node_fn,
- .name = "hicn-iface-udp4-output",
- .vector_size = sizeof (u32),
- .format_trace = hicn_iface_udp4_output_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicn_iface_udp4_output_error_strings),
- .error_strings = hicn_iface_udp4_output_error_strings,
- .n_next_nodes = HICN_IFACE_UDP4_OUTPUT_N_NEXT,
- /* edit / add dispositions here */
- .next_nodes =
- {
- [HICN_IFACE_UDP4_OUTPUT_NEXT_LOOKUP] = "ip4-lookup",
- [HICN_IFACE_UDP4_OUTPUT_NEXT_ERROR_DROP] = "error-drop",
- },
-};
-/* *INDENT-ON* */
-
-
-static uword
-hicn_iface_udp6_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 *
-hicn_iface_udp6_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 *);
- hicn_iface_udp6_output_trace_t *t =
- va_arg (*args, hicn_iface_udp6_output_trace_t *);
-
- s =
- format (s,
- "IFACE_UDP6_OUTPUT: pkt: %d, out face %d, next index %d\n%U",
- (int) t->pkt_type, t->sw_if_index, t->next_index,
- (t->packet_data[0] & 0xf0) ==
- 0x40 ? format_ip4_header : format_ip6_header, t->packet_data,
- sizeof (t->packet_data));
- return (s);
-}
-
-/*
- * Node registration for the interest forwarder node
- */
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (hicn_iface_udp6_output_node) =
-{
- .function = hicn_iface_udp6_output_node_fn,
- .name = "hicn-iface-udp6-output",
- .vector_size = sizeof (u32),
- .format_trace = hicn_iface_udp6_output_format_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicn_iface_udp6_output_error_strings),
- .error_strings = hicn_iface_udp6_output_error_strings,
- .n_next_nodes = HICN_IFACE_UDP6_OUTPUT_N_NEXT,
- /* edit / add dispositions here */
- .next_nodes =
- {
- [HICN_IFACE_UDP6_OUTPUT_NEXT_LOOKUP] = "ip6-lookup",
- [HICN_IFACE_UDP6_OUTPUT_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/hashtb.h b/hicn-plugin/src/hashtb.h
index 756f247b7..3c72fda65 100644
--- a/hicn-plugin/src/hashtb.h
+++ b/hicn-plugin/src/hashtb.h
@@ -24,47 +24,35 @@
#include "parser.h"
#include "error.h"
-/* Handy abbreviations for success status, and for boolean values */
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-/*
+/**
+ * @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 is 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) With siphash, two names hashing to the same 64-bit
- * value is quite rare. - the name which, on the hash table side, is stored
- * as a list of htkb_t (key buffers). [In some cases, the full name is not
- * compared, and a match is assumed based on hash value match. Read cost: -
- * htnode_t, in one cache line, holds hash value and index for the htkb at
- * the head of the key buffer list - each key buffer (htkb_t) is cache line
- * aligned/sized, and holds 60 bytes of the name and requires a cache line
- * read. Simplification is that a fib lookup requires 3 cache lines: - bucket
- * - htnode - single key buffer (for cases where a name comparision is done)
+ * 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
@@ -73,6 +61,15 @@
* 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
diff --git a/hicn-plugin/src/hicn.api b/hicn-plugin/src/hicn.api
index 01e4da213..9643f2098 100644
--- a/hicn-plugin/src/hicn.api
+++ b/hicn-plugin/src/hicn.api
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,43 +16,16 @@
option version = "5.1.0";
import "vnet/ip/ip_types.api";
-enum hicn_face_type
+enum hicn_action_type
{
- IP_FACE = 0,
- UDP_FACE,
+ HICN_DISABLE = 0,
+ HICN_ENABLE,
};
-typedef hicn_face_ip
+typedef hicn_face
{
/* IP local address */
- vl_api_address_t local_addr;
-
- /* IP remote address */
- vl_api_address_t remote_addr;
-
- /* IPv4 local port number */
- u32 swif;
-
- /* Face flags */
- u32 flags;
-
- /* Name of the interface */
- u8 if_name[30];
-};
-
-typedef hicn_face_udp
-{
- /* IP local address */
- vl_api_address_t local_addr;
-
- /* IP remote address */
- vl_api_address_t remote_addr;
-
- /* Local port */
- u16 lport;
-
- /* Remote port */
- u16 rport;
+ vl_api_address_t nat_addr;
/* IPv4 local port number */
u32 swif;
@@ -64,12 +37,6 @@ typedef hicn_face_udp
u8 if_name[30];
};
-typedef hicn_face_union
-{
- vl_api_hicn_face_ip_t ip;
- vl_api_hicn_face_udp_t udp;
-};
-
define hicn_api_node_params_set
{
/* Client identifier, set from api_main.my_client_index */
@@ -87,9 +54,6 @@ define hicn_api_node_params_set
/* CS maximum size, otherwise -1 to assign default value */
i32 cs_max_size;
- /* Portion of CS reserved to application, otherwise -1 to assign default value */
- i32 cs_reserved_app;
-
/* Upper bound on PIT entry lifetime, otherwise -1 to assign default value */
f64 pit_max_lifetime_sec;
};
@@ -205,51 +169,6 @@ define hicn_api_node_stats_get_reply
u64 cs_entries_ntw_count;
};
-define hicn_api_face_ip_add
-{
- /* Client identifier, set from api_main.my_client_index */
- u32 client_index;
-
- /* Arbitrary context, so client can match reply to request */
- u32 context;
-
- /* IP local address */
- vl_api_hicn_face_ip_t face;
-};
-
-define hicn_api_face_ip_add_reply
-{
- /* From the request */
- u32 context;
-
- /* Return value: new Face ID, ~0 means no Face was created */
- u32 faceid;
-
- /* Return value, zero means all OK */
- i32 retval;
-};
-
-define hicn_api_face_ip_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_face_ip_del_reply
-{
- /* From the request */
- u32 context;
-
- /* Return value, zero means all OK */
- i32 retval;
-};
-
define hicn_api_face_stats_details
{
/* From the request */
@@ -291,7 +210,7 @@ define hicn_api_face_stats_dump
u32 context;
};
-define hicn_api_face_ip_params_get
+define hicn_api_face_params_get
{
/* Client identifier, set from api_main.my_client_index */
u32 client_index;
@@ -303,7 +222,7 @@ define hicn_api_face_ip_params_get
u32 faceid;
};
-define hicn_api_face_ip_params_get_reply
+define hicn_api_face_params_get_reply
{
/* From the request */
u32 context;
@@ -315,10 +234,7 @@ define hicn_api_face_ip_params_get_reply
u32 faceid;
/* IP local address */
- vl_api_address_t local_addr;
-
- /* IP remote address */
- vl_api_address_t remote_addr;
+ vl_api_address_t nat_addr;
/* VPP interface (index) associated with the face */
u32 swif;
@@ -327,54 +243,6 @@ define hicn_api_face_ip_params_get_reply
u32 flags;
};
-define hicn_api_face_add
-{
- /* Client identifier, set from api_main.my_client_index */
- u32 client_index;
-
- /* Arbitrary context, so client can match reply to request */
- u32 context;
-
- /* Type of face to add */
- vl_api_hicn_face_type_t type;
-
- /* Face to add */
- vl_api_hicn_face_union_t face;
-};
-
-define hicn_api_face_add_reply
-{
- /* From the request */
- u32 context;
-
- /* Return value: new Face ID, ~0 means no Face was created */
- u32 faceid;
-
- /* Return value, zero means all OK */
- i32 retval;
-};
-
-define hicn_api_face_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_face_del_reply
-{
- /* From the request */
- u32 context;
-
- /* Return value, zero means all OK */
- i32 retval;
-};
-
define hicn_api_faces_details
{
/* From the request */
@@ -386,11 +254,8 @@ define hicn_api_faces_details
/* Id of the face */
u32 faceid;
- /* Type of face to add */
- vl_api_hicn_face_type_t type;
-
/* Face to add */
- vl_api_hicn_face_union_t face;
+ vl_api_hicn_face_t face;
};
define hicn_api_faces_dump
@@ -425,83 +290,8 @@ define hicn_api_face_get_reply
/* Id of the face */
u32 faceid;
- /* Type of face to add */
- vl_api_hicn_face_type_t type;
-
/* Face to add */
- vl_api_hicn_face_union_t face;
-};
-
-define hicn_api_route_nhops_add
-{
- /* 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 be added to the FIB */
- vl_api_prefix_t prefix;
-
- /* A Face ID to the next hop forwarder for the specified prefix */
- u32 face_ids[5];
-
- /* Number of face to add */
- u8 n_faces;
-};
-
-define hicn_api_route_nhops_add_reply
-{
- /* From the request */
- u32 context;
-
- /* Return value, zero means all OK */
- i32 retval;
-};
-
-define hicn_api_route_del
-{
- /* 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 be added to the FIB */
- vl_api_prefix_t prefix;
-};
-
-define hicn_api_route_del_reply
-{
- /* From the request */
- u32 context;
-
- /* Return value, zero means all OK */
- i32 retval;
-};
-
-define hicn_api_route_nhop_del
-{
- /* 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 be added to the FIB */
- vl_api_prefix_t prefix;
-
- /* Specific next-hop to be removed */
- u32 faceid;
-};
-
-define hicn_api_route_nhop_del_reply
-{
- /* From the request */
- u32 context;
-
- /* Return value, zero means all OK */
- i32 retval;
+ vl_api_hicn_face_t face;
};
define hicn_api_route_get
@@ -624,6 +414,33 @@ define hicn_api_strategy_get_reply
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 */
@@ -717,6 +534,42 @@ autoreply define hicn_api_face_cons_del
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
*
diff --git a/hicn-plugin/src/hicn.c b/hicn-plugin/src/hicn.c
index 7c2776869..f66514dbf 100644
--- a/hicn-plugin/src/hicn.c
+++ b/hicn-plugin/src/hicn.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -16,6 +16,7 @@
#include <vnet/vnet.h>
#include <vnet/plugin/plugin.h>
#include <vlib/vlib.h>
+#include <vnet/interface.h>
#include "hicn.h"
#include "params.h"
@@ -25,7 +26,7 @@
#include "error.h"
#include "faces/app/address_mgr.h"
#include "face_db.h"
-#include "faces/udp/face_udp.h"
+#include "udp_tunnels/udp_tunnel.h"
#include "route.h"
hicn_main_t hicn_main;
@@ -36,8 +37,8 @@ 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 */
+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;
@@ -45,8 +46,7 @@ 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,
- uint32_t cs_reserved)
+hicn_infra_fwdr_init (uint32_t shard_pit_size, uint32_t shard_cs_size)
{
int ret = 0;
@@ -64,12 +64,7 @@ hicn_infra_fwdr_init (uint32_t shard_pit_size, uint32_t shard_cs_size,
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 -
- (hicn_infra_cs_size * cs_reserved / 100));
- hicn_pit_set_lru_app_max (&hicn_main.pitcs,
- hicn_infra_cs_size * cs_reserved / 100);
-
+ hicn_pit_set_lru_max (&hicn_main.pitcs, hicn_infra_cs_size);
done:
if ((ret == HICN_ERROR_NONE) && !hicn_infra_fwdr_initialized)
{
@@ -83,15 +78,14 @@ done:
* only 'enabling' now
*/
int
-hicn_infra_plugin_enable_disable (int enable_disable,
- int pit_size_req,
+hicn_infra_plugin_enable_disable (int enable_disable, int pit_size_req,
f64 pit_max_lifetime_sec_req,
- int cs_size_req, int cs_reserved_app)
+ int cs_size_req, vnet_link_t link)
{
int ret = 0;
hicn_main_t *sm = &hicn_main;
- uint32_t pit_size, cs_size, cs_reserved;
+ uint32_t pit_size, cs_size;
/* Notice if we're already enabled... */
if (sm->is_enabled)
@@ -152,34 +146,24 @@ hicn_infra_plugin_enable_disable (int enable_disable,
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;
+ // 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");
-
+ "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;
}
- if (cs_reserved_app < 0)
- {
- cs_reserved = HICN_PARAM_CS_RESERVED_APP;
- }
- else
- {
- if (cs_reserved_app >= 100)
- ret = HICN_ERROR_CS_CONFIG_RESERVED_OOB;
- cs_reserved = cs_reserved_app;
- }
-
- ret = hicn_infra_fwdr_init (pit_size, cs_size, cs_reserved);
+ ret = hicn_infra_fwdr_init (pit_size, cs_size);
hicn_face_db_init (pit_size);
@@ -188,8 +172,8 @@ hicn_infra_plugin_enable_disable (int enable_disable,
goto done;
}
sm->is_enabled = 1;
-
- hicn_face_udp_init_internal ();
+ sm->link = link;
+ // hicn_face_udp_init_internal ();
done:
@@ -197,12 +181,13 @@ done:
}
static clib_error_t *
-hicn_configure (vlib_main_t * vm, unformat_input_t * input)
+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;
- int cs_reserved = HICN_PARAM_CS_RESERVED_APP;
+
+ vnet_link_t link;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
@@ -212,20 +197,16 @@ hicn_configure (vlib_main_t * vm, unformat_input_t * input)
;
else if (unformat (input, "pit-lifetime-max %u", &pit_lifetime_max_sec))
;
- else if (unformat (input, "cs-reserved-app %u", &cs_reserved))
- ;
+ else if (unformat (input, "grab mpls-tunnels"))
+ link = VNET_LINK_MPLS;
else
break;
-// clib_error_return (0,
-// "hICN parameter unknown");
}
unformat_free (input);
- hicn_infra_plugin_enable_disable (1, pit_size,
- pit_lifetime_max_sec,
- cs_size, cs_reserved);
-
+ hicn_infra_plugin_enable_disable (1, pit_size, pit_lifetime_max_sec, cs_size,
+ link);
return 0;
}
@@ -236,7 +217,7 @@ VLIB_CONFIG_FUNCTION (hicn_configure, "hicn");
* Init entry-point for the icn plugin
*/
static clib_error_t *
-hicn_init (vlib_main_t * vm)
+hicn_init (vlib_main_t *vm)
{
clib_error_t *error = 0;
@@ -258,17 +239,14 @@ hicn_init (vlib_main_t * 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* */
+VLIB_PLUGIN_REGISTER () = { .description = "hICN forwarder" };
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/hicn.h b/hicn-plugin/src/hicn.h
index b469a7ed9..437f91144 100644
--- a/hicn-plugin/src/hicn.h
+++ b/hicn-plugin/src/hicn.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -30,6 +30,8 @@
#undef ip_prefix_len
#define ip_prefix_len(_a) (_a)->len
+#include "faces/face.h"
+
#include <netinet/in.h>
#include <vnet/ip/ip.h>
#include <vnet/tcp/tcp_packet.h>
@@ -37,6 +39,10 @@
#include <vnet/ip/ip4_packet.h>
#include <vnet/buffer.h>
+/**
+ * @file
+ */
+
/* Helper for avoiding warnings about type-punning */
#define UNION_CAST(x, destType) \
(((union {__typeof__(x) a; destType b;})x).b)
@@ -54,11 +60,12 @@ typedef u8 weight_t;
#define VLIB_BUFFER_MIN_CHAIN_SEG_SIZE (128)
#endif
-#define HICN_BUFFER_FLAGS_DEFAULT 0x00
-#define HICN_BUFFER_FLAGS_FACE_IS_APP 0x01
/* 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
+#define HICN_BUFFER_FLAGS_FROM_CS 0x10
/* The following is stored in the opaque2 field in the vlib_buffer_t */
typedef struct
@@ -76,8 +83,7 @@ typedef struct
u8 dpo_ctx_id; /* used for data path */
u8 vft_id; /* " */
- dpo_id_t face_dpo_id; /* ingress iface, sizeof(dpo_id_t)
- * <= sizeof(u64) */
+ 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;
diff --git a/hicn-plugin/src/hicn_api.c b/hicn-plugin/src/hicn_api.c
index 7a6babeb2..f26af1e82 100644
--- a/hicn-plugin/src/hicn_api.c
+++ b/hicn-plugin/src/hicn_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -25,8 +25,8 @@
#include <vnet/ip/ip_types_api.h>
#include <vnet/ip/ip_format_fns.h>
-#include "faces/ip/face_ip.h"
-#include "faces/udp/face_udp.h"
+#include "faces/face.h"
+#include "udp_tunnels/udp_tunnel.h"
#include "infra.h"
#include "parser.h"
#include "mgmt.h"
@@ -57,19 +57,16 @@
* 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_ip_params_get_reply_t
- * reply);
-
+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_t_handler (
+ vl_api_hicn_api_node_params_set_t *mp)
{
vl_api_hicn_api_node_params_set_reply_t *rmp;
int rv;
@@ -81,337 +78,82 @@ vl_api_hicn_api_node_params_set_t_handler (vl_api_hicn_api_node_params_set_t *
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;
+ 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;
- int cs_reserved_app = clib_net_to_host_i32 (mp->cs_reserved_app);
- cs_reserved_app = cs_reserved_app >= 0
- && cs_reserved_app < 100 ? cs_reserved_app : HICN_PARAM_CS_RESERVED_APP;
-
- rv = hicn_infra_plugin_enable_disable ((int) (mp->enable_disable),
- pit_max_size,
- pit_max_lifetime_sec,
- cs_max_size, cs_reserved_app);
+ 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 */ );
+ 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_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* */
+ 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);
+ }));
}
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_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* */
-}
-
-
-/****** FACE *******/
-static hicn_error_t
-hicn_api_face_ip_add (vl_api_hicn_face_ip_t * mp, hicn_face_id_t * face_id)
-{
- hicn_error_t rv = HICN_ERROR_NONE;
-
- vnet_main_t *vnm = vnet_get_main ();
-
- ip46_address_t local_addr;
- ip46_address_t remote_addr;
- ip_address_decode (&mp->local_addr, &local_addr);
- ip_address_decode (&mp->remote_addr, &remote_addr);
-
- u32 sw_if = clib_net_to_host_u32 (mp->swif);
-
- if (ip46_address_is_zero (&local_addr))
- {
- if (!vnet_sw_interface_is_valid (vnm, sw_if))
- {
- rv = HICN_ERROR_UNSPECIFIED;
- }
-
- if ((rv == HICN_ERROR_NONE) && ip46_address_is_ip4 (&remote_addr))
- {
- ip_interface_address_t *interface_address;
- ip4_address_t *addr =
- ip4_interface_address_matching_destination (&ip4_main,
- &remote_addr.ip4,
- sw_if,
- &interface_address);
- if (addr == NULL)
- addr = ip4_interface_first_address (&ip4_main,
- sw_if, &interface_address);
-
- if (addr == NULL)
- rv = HICN_ERROR_UNSPECIFIED;
- else
- ip46_address_set_ip4 (&local_addr, addr);
- }
- else
- {
- ip_interface_address_t *interface_address;
- ip6_interface_address_matching_destination (&ip6_main,
- &remote_addr.ip6, sw_if,
- &interface_address);
- ip6_address_t *addr = NULL;
- if (rv == HICN_ERROR_NONE && interface_address != NULL)
- {
- addr =
- (ip6_address_t *)
- ip_interface_address_get_address (&ip6_main.lookup_main,
- interface_address);
- }
- else
- {
- addr = ip6_interface_first_address (&ip6_main, sw_if);
- }
-
- if (addr == NULL)
- rv = HICN_ERROR_UNSPECIFIED;
- else
- ip46_address_set_ip6 (&local_addr, addr);
- }
- }
-
- if (rv == HICN_ERROR_NONE)
- rv = hicn_face_ip_add (&local_addr, &remote_addr, sw_if, face_id, 0);
-
- return rv;
-}
-
-static void
-vl_api_hicn_api_face_ip_add_t_handler (vl_api_hicn_api_face_ip_add_t * mp)
-{
- vl_api_hicn_api_face_ip_add_reply_t *rmp;
- hicn_error_t rv = HICN_ERROR_NONE;
-
- hicn_main_t *sm = &hicn_main;
- hicn_face_id_t face_id = HICN_FACE_NULL;
- rv = hicn_api_face_ip_add (&(mp->face), &face_id);
-
- /* *INDENT-OFF* */
- REPLY_MACRO2 (VL_API_HICN_API_FACE_IP_ADD_REPLY /* , rmp, mp, rv */ ,(
- {
- rmp->faceid = clib_host_to_net_u32 ((u32) face_id);
- rmp->retval = rv;
- }));
- /* *INDENT-ON* */
-}
-
-static void
-vl_api_hicn_api_face_ip_del_t_handler (vl_api_hicn_api_face_ip_del_t * mp)
-{
- vl_api_hicn_api_face_ip_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);
- if (hicn_dpoi_idx_is_valid (faceid))
- {
- rv = hicn_face_ip_del (faceid);
- }
-
- REPLY_MACRO (VL_API_HICN_API_FACE_IP_DEL_REPLY /* , rmp, mp, rv */ );
-
+ 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);
+ }));
}
static void
- vl_api_hicn_api_face_ip_params_get_t_handler
- (vl_api_hicn_api_face_ip_params_get_t * mp)
+vl_api_hicn_api_face_params_get_t_handler (
+ vl_api_hicn_api_face_params_get_t *mp)
{
- vl_api_hicn_api_face_ip_params_get_reply_t *rmp;
+ 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_IP_PARAMS_GET_REPLY, (
- {
- rv = hicn_face_api_entry_params_serialize(faceid, rmp);
- rmp->retval = clib_host_to_net_u32(rv);
- }));
- /* *INDENT-ON* */
-}
-
-static hicn_error_t
-hicn_api_face_udp_add (vl_api_hicn_face_udp_t * mp, hicn_face_id_t * face_id)
-{
- hicn_error_t rv = HICN_ERROR_NONE;
-
- ip46_address_t local_addr = ip46_address_initializer;
- ip46_address_t remote_addr = ip46_address_initializer;
- u16 lport;
- u16 rport;
- u32 sw_if;
- ip_address_decode (&mp->local_addr, &local_addr);
- ip_address_decode (&mp->remote_addr, &remote_addr);
- //Do not byteswap. We store ports in network order
- lport = mp->lport;
- rport = mp->rport;
- sw_if = clib_net_to_host_u32 (mp->swif);
-
- int input_is_ok = !ip46_address_is_zero (&local_addr)
- && !ip46_address_is_zero (&remote_addr)
- &&
- ((ip46_address_is_ip4 (&local_addr) && ip46_address_is_ip4 (&remote_addr))
- || (!ip46_address_is_ip4 (&local_addr)
- && !ip46_address_is_ip4 (&remote_addr))) && lport != 0 && rport != 0;
-
- if (!input_is_ok)
- {
- rv = HICN_ERROR_UNSPECIFIED;
- }
- else
- {
- rv = hicn_face_udp_add (&local_addr,
- &remote_addr, lport, rport, sw_if, face_id);
- }
- return rv;
-}
-
-static void
-vl_api_hicn_api_face_add_t_handler (vl_api_hicn_api_face_add_t * mp)
-{
- vl_api_hicn_api_face_add_reply_t *rmp;
- hicn_error_t rv = HICN_ERROR_NONE;
-
- hicn_main_t *sm = &hicn_main;
- hicn_face_id_t face_id;
- vl_api_hicn_face_type_t face_type = clib_net_to_host_u32 (mp->type);
-
- switch (face_type)
- {
- case IP_FACE:
- rv = hicn_api_face_ip_add (&(mp->face.ip), &face_id);
- break;
- case UDP_FACE:
- rv = hicn_api_face_udp_add (&(mp->face.udp), &face_id);
- break;
- default:
- rv = HICN_ERROR_UNSPECIFIED;
- break;
- }
-
- /* *INDENT-OFF* */
- REPLY_MACRO2 (VL_API_HICN_API_FACE_ADD_REPLY /* , rmp, mp, rv */ ,(
- {
- rmp->faceid = clib_host_to_net_u32 ((u32) face_id);
- rmp->retval = clib_host_to_net_u32 (rv);
- }));
- /* *INDENT-ON* */
-}
-
-static void
-vl_api_hicn_api_face_del_t_handler (vl_api_hicn_api_face_del_t * mp)
-{
- vl_api_hicn_api_face_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);
- if (hicn_dpoi_idx_is_valid (faceid))
- {
- hicn_face_t *face = hicn_dpoi_get_from_idx (faceid);
- hicn_face_vft_t *vft = hicn_face_get_vft (face->shared.face_type);
- rv = vft->hicn_face_del (faceid);
- }
-
- REPLY_MACRO (VL_API_HICN_API_FACE_DEL_REPLY /* , rmp, mp, rv */ );
+ 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);
+ }));
}
static void
-send_face_ip_details (hicn_face_t * face, vl_api_hicn_face_ip_t * mp)
+send_face_details (hicn_face_t *face, vl_api_hicn_face_t *mp)
{
vnet_main_t *vnm = vnet_get_main ();
- hicn_face_ip_t *face_ip = (hicn_face_ip_t *) face->data;
- ip_address_encode (&face_ip->local_addr, IP46_TYPE_ANY, &mp->local_addr);
- ip_address_encode (&face_ip->remote_addr, IP46_TYPE_ANY, &mp->remote_addr);
- mp->flags = clib_host_to_net_u32 (face->shared.flags);
- mp->swif = clib_net_to_host_u32 (face->shared.sw_if);
- vnet_sw_interface_t *sw_interface =
- vnet_get_sw_interface_or_null (vnm, face->shared.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_face_udp_details (hicn_face_t * face, vl_api_hicn_face_udp_t * mp)
-{
- vnet_main_t *vnm = vnet_get_main ();
- hicn_face_udp_t *face_udp = (hicn_face_udp_t *) face->data;
- if (face_udp->hdrs.ip4.ip.ip_version_and_header_length == 0x45)
- {
- ip46_address_t src_addr = { 0 };
- ip46_address_t dst_addr = { 0 };
- ip46_address_set_ip4 (&src_addr, &(face_udp->hdrs.ip4.ip.src_address));
- ip46_address_set_ip4 (&dst_addr, &(face_udp->hdrs.ip4.ip.dst_address));
-
- ip_address_encode (&src_addr, IP46_TYPE_ANY, &(mp->local_addr));
- ip_address_encode (&dst_addr, IP46_TYPE_ANY, &(mp->remote_addr));
- //Do not swap, they are already in network order
- mp->lport = face_udp->hdrs.ip4.udp.src_port;
- mp->rport = face_udp->hdrs.ip4.udp.dst_port;
- }
- else
- {
- ip46_address_t src_addr = { 0 };
- ip46_address_t dst_addr = { 0 };
- ip46_address_set_ip6 (&src_addr, &(face_udp->hdrs.ip6.ip.src_address));
- ip46_address_set_ip6 (&dst_addr, &(face_udp->hdrs.ip6.ip.dst_address));
-
- ip_address_encode (&src_addr, IP46_TYPE_ANY, &(mp->local_addr));
- ip_address_encode (&dst_addr, IP46_TYPE_ANY, &(mp->remote_addr));
- //Do not swap, they are already in network order
- mp->lport = face_udp->hdrs.ip6.udp.src_port;
- mp->rport = face_udp->hdrs.ip6.udp.dst_port;
- }
- mp->flags = clib_host_to_net_u32 (face->shared.flags);
- mp->swif = clib_net_to_host_u32 (face->shared.sw_if);
+ 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->shared.sw_if);
+ vnet_get_sw_interface_or_null (vnm, face->sw_if);
u8 *sbuf = 0;
if (sw_interface != NULL)
{
@@ -422,8 +164,7 @@ send_face_udp_details (hicn_face_t * face, vl_api_hicn_face_udp_t * mp)
}
static void
-send_faces_details (vl_api_registration_t * reg,
- hicn_face_t * face, u32 context)
+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;
@@ -433,23 +174,13 @@ send_faces_details (vl_api_registration_t * reg,
mp->_vl_msg_id = htons (VL_API_HICN_API_FACES_DETAILS + hm->msg_id_base);
mp->context = context;
- if (face->shared.face_type == hicn_face_ip_type)
- {
- mp->type = clib_host_to_net_u32 (IP_FACE);
- send_face_ip_details (face, &(mp->face.ip));
- }
- else if (face->shared.face_type == hicn_face_udp_type)
- {
- mp->type = clib_host_to_net_u32 (UDP_FACE);
- send_face_udp_details (face, &(mp->face.udp));
- }
-
+ 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)
+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;
@@ -458,16 +189,14 @@ vl_api_hicn_api_faces_dump_t_handler (vl_api_hicn_api_faces_dump_t * mp)
if (!reg)
return;
- /* *INDENT-OFF* */
- pool_foreach (face, hicn_dpoi_face_pool,
- ({
- send_faces_details (reg, face, mp->context);
- }));
- /* *INDENT-ON* */
+ pool_foreach (face, hicn_dpoi_face_pool)
+ {
+ send_faces_details (reg, face, mp->context);
+ }
}
static void
-vl_api_hicn_api_face_get_t_handler (vl_api_hicn_api_face_get_t * mp)
+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;
@@ -476,37 +205,25 @@ vl_api_hicn_api_face_get_t_handler (vl_api_hicn_api_face_get_t * mp)
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);
- if (face->shared.face_type == hicn_face_ip_type)
- {
- rmp->type = IP_FACE;
- send_face_ip_details(face, &(rmp->face.ip));
- }
- else if (face->shared.face_type == hicn_face_udp_type)
- {
- rmp->type = UDP_FACE;
- send_face_udp_details(face, &(rmp->face.udp));
- }
- rv = HICN_ERROR_NONE;
- }
- else
- {
- rv = HICN_ERROR_FACE_NOT_FOUND;
- }
- rmp->retval = clib_host_to_net_u32(rv);
- }));
- /* *INDENT-ON* */
+ 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);
+ }));
}
static void
-send_face_stats_details (vl_api_registration_t * reg,
- hicn_face_t * face, u32 context)
+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;
@@ -519,27 +236,27 @@ send_face_stats_details (vl_api_registration_t * reg,
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);
+ 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);
+ 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);
+ 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);
+ 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);
@@ -547,8 +264,8 @@ send_face_stats_details (vl_api_registration_t * reg,
}
static void
- vl_api_hicn_api_face_stats_dump_t_handler
- (vl_api_hicn_api_face_stats_dump_t * mp)
+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;
@@ -557,90 +274,16 @@ static void
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_nhops_add_t_handler (vl_api_hicn_api_route_nhops_add_t
- * mp)
-{
- vl_api_hicn_api_route_nhops_add_reply_t *rmp;
- int rv = HICN_ERROR_NONE;
- hicn_face_id_t face_ids[HICN_PARAM_FIB_ENTRY_NHOPS_MAX];
-
- hicn_main_t *sm = &hicn_main;
-
- fib_prefix_t prefix;
- ip_prefix_decode (&mp->prefix, &prefix);
-
- u8 n_faces = mp->n_faces;
-
- for (int i = 0; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; i++)
+ pool_foreach (face, hicn_dpoi_face_pool)
{
- face_ids[i] = clib_net_to_host_u32 (mp->face_ids[i]);
+ send_face_stats_details (reg, face, mp->context);
}
-
- if ((face_ids == NULL) || (n_faces > HICN_PARAM_FIB_ENTRY_NHOPS_MAX))
- {
- rv = VNET_API_ERROR_INVALID_ARGUMENT;
- }
- if (rv == HICN_ERROR_NONE)
- {
- rv = hicn_route_add (face_ids, n_faces, &prefix);
-
- if (rv == HICN_ERROR_ROUTE_ALREADY_EXISTS)
- {
- rv = hicn_route_add_nhops (face_ids, n_faces, &prefix);
- }
- }
- REPLY_MACRO (VL_API_HICN_API_ROUTE_NHOPS_ADD_REPLY /* , rmp, mp, rv */ );
}
+/****** ROUTE *******/
-static void vl_api_hicn_api_route_del_t_handler
- (vl_api_hicn_api_route_del_t * mp)
-{
- vl_api_hicn_api_route_del_reply_t *rmp;
- int rv = HICN_ERROR_NONE;
-
- hicn_main_t *sm = &hicn_main;
-
- fib_prefix_t prefix;
- ip_prefix_decode (&mp->prefix, &prefix);
-
- rv = hicn_route_del (&prefix);
-
- REPLY_MACRO (VL_API_HICN_API_ROUTE_DEL_REPLY /* , rmp, mp, rv */ );
-}
-
-static void vl_api_hicn_api_route_nhop_del_t_handler
- (vl_api_hicn_api_route_nhop_del_t * mp)
-{
- vl_api_hicn_api_route_nhop_del_reply_t *rmp;
- int rv = HICN_ERROR_NONE;
-
- hicn_main_t *sm = &hicn_main;
-
- fib_prefix_t prefix;
- ip_prefix_decode (&mp->prefix, &prefix);
- hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid);
-
-
- rv = hicn_route_del_nhop (&prefix, faceid);
-
- REPLY_MACRO (VL_API_HICN_API_ROUTE_NHOP_DEL_REPLY /* , rmp, mp, rv */ );
-}
-
-static void vl_api_hicn_api_route_get_t_handler
- (vl_api_hicn_api_route_get_t * mp)
+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;
@@ -655,26 +298,25 @@ static void vl_api_hicn_api_route_get_t_handler
rv = hicn_route_get_dpo (&prefix, &hicn_dpo_id, &fib_index);
- /* *INDENT-OFF* */
- REPLY_MACRO2 (VL_API_HICN_API_ROUTE_GET_REPLY, (
- {
+ 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++)
+ 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++)
{
- if (dpo_id_is_valid(&hicn_dpo_ctx->next_hops[i]))
- {
- rmp->faceids[i] =((dpo_id_t *) &hicn_dpo_ctx->next_hops[i])->dpoi_index;}
+ 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));}
+ 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)
+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;
@@ -699,14 +341,8 @@ send_route_details (vl_api_registration_t * reg,
for (int i = 0; hicn_dpo_ctx != NULL && i < hicn_dpo_ctx->entry_count;
i++)
{
- if (dpo_id_is_valid (&hicn_dpo_ctx->next_hops[i]))
- {
- mp->faceids[i] =
- clib_host_to_net_u32 (((dpo_id_t *) &
- hicn_dpo_ctx->
- next_hops[i])->dpoi_index);
- mp->nfaces++;
- }
+ 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));
@@ -753,7 +389,7 @@ vl_api_hicn_api_route_dump_walk (fib_node_index_t fei, void *arg)
}
static void
-vl_api_hicn_api_routes_dump_t_handler (vl_api_hicn_api_routes_dump_t * mp)
+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;
@@ -769,34 +405,29 @@ vl_api_hicn_api_routes_dump_t_handler (vl_api_hicn_api_routes_dump_t * mp)
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);}
- ));
+ 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);
- }
+ {
+ 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)
+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;
@@ -805,23 +436,22 @@ static void vl_api_hicn_api_strategies_get_t_handler
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* */
+ 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;
+ }));
}
-static void vl_api_hicn_api_strategy_get_t_handler
- (vl_api_hicn_api_strategy_get_t * mp)
+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;
@@ -831,22 +461,22 @@ static void vl_api_hicn_api_strategy_get_t_handler
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* */
+ 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);
+ }
+ }));
}
/************* APP FACE ****************/
-static void vl_api_hicn_api_register_prod_app_t_handler
- (vl_api_hicn_api_register_prod_app_t * mp)
+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;
@@ -863,18 +493,16 @@ static void vl_api_hicn_api_register_prod_app_t_handler
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* */
+ 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);
+ }));
}
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_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;
@@ -884,11 +512,12 @@ vl_api_hicn_api_face_prod_del_t_handler (vl_api_hicn_api_face_prod_del_t * mp)
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 */ );
+ 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)
+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;
@@ -901,23 +530,20 @@ static void vl_api_hicn_api_register_cons_app_t_handler
u32 faceid1;
u32 faceid2;
- rv =
- hicn_face_cons_add (&src_addr4.ip4, &src_addr6.ip6, swif, &faceid1,
- &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);
+ 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_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;
@@ -927,9 +553,82 @@ vl_api_hicn_api_face_cons_del_t_handler (vl_api_hicn_api_face_cons_del_t * mp)
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 */ );
+ 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:
+
+ REPLY_MACRO2 (VL_API_HICN_API_UDP_TUNNEL_ADD_DEL_REPLY,
+ ({ rmp->uei = clib_host_to_net_u32 (uei); }));
+}
/************************************************************************************/
@@ -937,7 +636,7 @@ vl_api_hicn_api_face_cons_del_t_handler (vl_api_hicn_api_face_cons_del_t * mp)
/* Set up the API message handling tables */
clib_error_t *
-hicn_api_plugin_hookup (vlib_main_t * vm)
+hicn_api_plugin_hookup (vlib_main_t *vm)
{
hicn_main_t *hm = &hicn_main;
@@ -945,8 +644,6 @@ hicn_api_plugin_hookup (vlib_main_t * vm)
return 0;
}
-
-
/******************* SUPPORTING FUNCTIONS *******************/
/*
@@ -954,9 +651,8 @@ hicn_api_plugin_hookup (vlib_main_t * vm)
* 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_ip_params_get_reply_t
- * reply)
+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;
@@ -967,15 +663,12 @@ hicn_face_api_entry_params_serialize (hicn_face_id_t faceid,
}
hicn_face_t *face = hicn_dpoi_get_from_idx (faceid);
- if (face != NULL && face->shared.face_type == hicn_face_ip_type)
+ if (face != NULL)
{
- hicn_face_ip_t *face_ip = (hicn_face_ip_t *) face->data;
- ip_address_encode (&face_ip->local_addr, IP46_TYPE_ANY,
- &reply->local_addr);
- ip_address_encode (&face_ip->remote_addr, IP46_TYPE_ANY,
- &reply->remote_addr);
- reply->swif = clib_host_to_net_u32 (face->shared.sw_if);
- reply->flags = clib_host_to_net_u32 (face->shared.flags);
+ 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
diff --git a/hicn-plugin/src/hicn_api.h b/hicn-plugin/src/hicn_api.h
index 79b561be4..ec10a6bbd 100644
--- a/hicn-plugin/src/hicn_api.h
+++ b/hicn-plugin/src/hicn_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -16,7 +16,13 @@
#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
diff --git a/hicn-plugin/src/hicn_api_test.c b/hicn-plugin/src/hicn_api_test.c
index 08a579914..e4704e8ea 100644
--- a/hicn-plugin/src/hicn_api_test.c
+++ b/hicn-plugin/src/hicn_api_test.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -222,11 +222,7 @@ hicn_test_main_t hicn_test_main;
#define foreach_standard_reply_retval_handler \
_(hicn_api_node_params_set_reply) \
-_(hicn_api_face_ip_del_reply) \
-_(hicn_api_face_del_reply) \
-_(hicn_api_route_nhops_add_reply) \
-_(hicn_api_route_del_reply) \
-_(hicn_api_route_nhop_del_reply)
+_(hicn_api_enable_disable_reply)
#define _(n) \
static void vl_api_##n##_t_handler \
@@ -253,26 +249,16 @@ foreach_standard_reply_retval_handler;
_(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_IP_DEL_REPLY, hicn_api_face_ip_del_reply) \
-_(HICN_API_FACE_IP_ADD_REPLY, hicn_api_face_ip_add_reply) \
-_(HICN_API_FACE_ADD_REPLY, hicn_api_face_add_reply) \
-_(HICN_API_FACE_DEL_REPLY, hicn_api_face_del_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_ROUTE_NHOPS_ADD_REPLY, hicn_api_route_nhops_add_reply) \
-_(HICN_API_FACE_IP_PARAMS_GET_REPLY, hicn_api_face_ip_params_get_reply) \
+_(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_ROUTE_DEL_REPLY, hicn_api_route_del_reply) \
-_(HICN_API_ROUTE_NHOP_DEL_REPLY, hicn_api_route_nhop_del_reply) \
_(HICN_API_STRATEGIES_GET_REPLY, hicn_api_strategies_get_reply) \
_(HICN_API_STRATEGY_GET_REPLY, hicn_api_strategy_get_reply) \
-_(HICN_API_REGISTER_PROD_APP_REPLY, hicn_api_register_prod_app_reply) \
-_(HICN_API_FACE_PROD_DEL_REPLY, hicn_api_face_prod_del_reply) \
-_(HICN_API_REGISTER_CONS_APP_REPLY, hicn_api_register_cons_app_reply) \
-_(HICN_API_FACE_CONS_DEL_REPLY, hicn_api_face_cons_del_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)
@@ -309,7 +295,7 @@ api_hicn_api_node_params_set (vat_main_t * vam)
/* Construct the API message */
M (HICN_API_NODE_PARAMS_SET, mp);
- mp->enable_disable = enable_disable;
+ 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;
@@ -451,263 +437,10 @@ static void
}
static int
-api_hicn_api_face_ip_add (vat_main_t * vam)
+api_hicn_api_face_params_get (vat_main_t * vam)
{
unformat_input_t *input = vam->input;
- ip46_address_t local_addr = { 0 };
- ip46_address_t remote_addr = { 0 };
- int ret = HICN_ERROR_NONE;
- int sw_if = 0;
- vl_api_hicn_api_face_add_t *mp;
-
- /* Parse args required to build the message */
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat
- (input, "local %U", unformat_ip46_address, &local_addr,
- IP46_TYPE_ANY));
- else
- if (unformat
- (input, "remote %U", unformat_ip46_address, &remote_addr,
- IP46_TYPE_ANY));
- else if (unformat (input, "intfc %d", &sw_if));
- else
- {
- break;
- }
- }
-
- /* Check for presence of both addresses */
- if (ip46_address_is_zero (&remote_addr))
- {
- clib_warning ("Incomplete IP face. Please specify remote address");
- return (1);
- }
- /* Construct the API message */
- M (HICN_API_FACE_ADD, mp);
- mp->type = clib_host_to_net_u32 (IP_FACE);
- ip_address_encode (&local_addr, IP46_TYPE_ANY, &mp->face.ip.local_addr);
- ip_address_encode (&remote_addr, IP46_TYPE_ANY, &mp->face.ip.remote_addr);
- mp->face.ip.swif = clib_host_to_net_u32 (sw_if);
-
- /* send it... */
- S (mp);
-
- /* Wait for a reply... */
- W (ret);
-
- return ret;
-}
-
-static void
- vl_api_hicn_api_face_ip_add_reply_t_handler
- (vl_api_hicn_api_face_ip_add_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;
- }
- fformat (vam->ofp, "New Face ID: %d\n", ntohl (rmp->faceid));
-}
-
-static int
-api_hicn_api_face_udp_add (vat_main_t * vam)
-{
- unformat_input_t *input = vam->input;
- ip46_address_t local_addr = ip46_address_initializer;
- ip46_address_t remote_addr = ip46_address_initializer;
- u32 sport = 0;
- u32 dport = 0;
- int ret = HICN_ERROR_NONE;
- int sw_if = ~0;
- vl_api_hicn_api_face_add_t *mp;
-
- /* Parse args required to build the message */
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat
- (input, "local %U port %u", unformat_ip46_address, &local_addr,
- IP46_TYPE_ANY, &sport));
- else
- if (unformat
- (input, "remote %U port %u", unformat_ip46_address, &remote_addr,
- IP46_TYPE_ANY, &dport));
- else if (unformat (input, "intfc %d", &sw_if));
- else
- {
- break;
- }
- }
-
- /* Check for presence of both addresses */
- if (ip46_address_is_zero (&remote_addr)
- || ip46_address_is_zero (&local_addr) || sport == 0 || dport == 0)
- {
- clib_warning
- ("Incomplete UDP face. Please specify local and remote address and port");
- return (1);
- }
- /* Construct the API message */
- M (HICN_API_FACE_ADD, mp);
- mp->type = clib_host_to_net_u32 (UDP_FACE);
- ip_address_encode (&local_addr, IP46_TYPE_ANY, &mp->face.udp.local_addr);
- ip_address_encode (&remote_addr, IP46_TYPE_ANY, &mp->face.udp.remote_addr);
- mp->face.udp.lport = clib_host_to_net_u16 (sport);
- mp->face.udp.rport = clib_host_to_net_u16 (dport);
- mp->face.udp.swif = clib_host_to_net_u32 (sw_if);
-
- /* send it... */
- S (mp);
-
- /* Wait for a reply... */
- W (ret);
-
- return ret;
-}
-
-static int
-api_hicn_api_face_add (vat_main_t * vam)
-{
- unformat_input_t *input = vam->input;
- int ret = HICN_ERROR_NONE;
- u32 type = ~0;
-
- /* Parse args required to build the message */
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "type %d", &type));
- else
- {
- break;
- }
- }
-
- vam->input = input;
-
- if (type == IP_FACE)
- ret = api_hicn_api_face_ip_add (vam);
- else if (type == UDP_FACE)
- ret = api_hicn_api_face_udp_add (vam);
-
- return ret;
-}
-
-static void
- vl_api_hicn_api_face_add_reply_t_handler
- (vl_api_hicn_api_face_add_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;
- }
- fformat (vam->ofp, "New Face ID: %d\n", ntohl (rmp->faceid));
-}
-
-static int
-api_hicn_api_face_ip_del (vat_main_t * vam)
-{
- unformat_input_t *input = vam->input;
- vl_api_hicn_api_face_ip_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_IP_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_face_del (vat_main_t * vam)
-{
- unformat_input_t *input = vam->input;
- vl_api_hicn_api_face_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_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_face_ip_params_get (vat_main_t * vam)
-{
- unformat_input_t *input = vam->input;
- vl_api_hicn_api_face_ip_params_get_t *mp;
+ vl_api_hicn_api_face_params_get_t *mp;
u32 faceid = HICN_FACE_NULL, ret;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
@@ -728,7 +461,7 @@ api_hicn_api_face_ip_params_get (vat_main_t * vam)
return 1;
}
//Construct the API message
- M (HICN_API_FACE_IP_PARAMS_GET, mp);
+ M (HICN_API_FACE_PARAMS_GET, mp);
mp->faceid = clib_host_to_net_u32 (faceid);
//send it...
@@ -741,14 +474,13 @@ api_hicn_api_face_ip_params_get (vat_main_t * vam)
}
static void
- vl_api_hicn_api_face_ip_params_get_reply_t_handler
- (vl_api_hicn_api_face_ip_params_get_reply_t * rmp)
+ 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 remote_addr;
- ip46_address_t local_addr;
+ ip46_address_t nat_addr;
if (vam->async_mode)
{
@@ -765,12 +497,10 @@ static void
return;
}
vec_reset_length (sbuf);
- ip_address_decode (&rmp->local_addr, &local_addr);
- ip_address_decode (&rmp->remote_addr, &remote_addr);
+ ip_address_decode (&rmp->nat_addr, &nat_addr);
sbuf =
- format (0, "local_addr %U remote_addr %U", format_ip46_address,
- &local_addr, 0 /*IP46_ANY_TYPE */ , format_ip46_address,
- &remote_addr, 0 /*IP46_ANY_TYPE */ );
+ format (0, "nat_addr %U", format_ip46_address,
+ &nat_addr, 0 /*IP46_ANY_TYPE */);
fformat (vam->ofp, "%s swif %d flags %d\n",
sbuf,
@@ -779,48 +509,23 @@ static void
}
static void
-format_ip_face (vl_api_hicn_face_ip_t * rmp)
+format_face (vl_api_hicn_face_t * rmp)
{
vat_main_t *vam = hicn_test_main.vat_main;
u8 *sbuf = 0;
- ip46_address_t remote_addr;
+ ip46_address_t nat_addr;
ip46_address_t local_addr;
vec_reset_length (sbuf);
- ip_address_decode (&rmp->local_addr, &local_addr);
- ip_address_decode (&rmp->remote_addr, &remote_addr);
- sbuf =
- format (0, "local_addr %U remote_addr %U", format_ip46_address,
- &local_addr, 0 /*IP46_ANY_TYPE */ , format_ip46_address,
- &remote_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 void
-format_udp_face (vl_api_hicn_face_udp_t * rmp)
-{
- vat_main_t *vam = hicn_test_main.vat_main;
- u8 *sbuf = 0;
- ip46_address_t remote_addr;
- ip46_address_t local_addr;
+ ip_address_decode (&rmp->nat_addr, &nat_addr);
- vec_reset_length (sbuf);
- ip_address_decode (&rmp->local_addr, &local_addr);
- ip_address_decode (&rmp->remote_addr, &remote_addr);
- u16 lport = clib_net_to_host_u16 (rmp->lport);
- u16 rport = clib_net_to_host_u16 (rmp->rport);;
sbuf =
- format (0, "local_addr %U port %u remote_addr %U port %u",
- format_ip46_address, &local_addr, 0 /*IP46_ANY_TYPE */ , lport,
- format_ip46_address, &remote_addr, 0 /*IP46_ANY_TYPE */ , rport);
+ 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_u16 (rmp->swif),
+ clib_net_to_host_u32 (rmp->swif),
clib_net_to_host_i32 (rmp->flags), rmp->if_name);
}
@@ -841,6 +546,9 @@ api_hicn_api_faces_dump (vat_main_t * vam)
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);
@@ -859,14 +567,7 @@ static void
vl_api_hicn_api_faces_details_t_handler
(vl_api_hicn_api_faces_details_t * mp)
{
- if (mp->type == IP_FACE)
- {
- format_ip_face (&(mp->face.ip));
- }
- else
- {
- format_udp_face (&(mp->face.udp));
- }
+ format_face (&(mp->face));
}
static int
@@ -929,15 +630,7 @@ static void
fformat (vam->ofp, " (API call error: %d)\n", vam->retval);
return;
}
-
- if (rmp->type == IP_FACE)
- {
- format_ip_face (&(rmp->face.ip));
- }
- else
- {
- format_udp_face (&(rmp->face.udp));
- }
+ format_face (&(rmp->face));
}
@@ -959,6 +652,9 @@ api_hicn_api_face_stats_dump (vat_main_t * vam)
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);
@@ -1061,6 +757,9 @@ api_hicn_api_routes_dump (vat_main_t * vam)
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);
@@ -1151,152 +850,6 @@ static void
}
static int
-api_hicn_api_route_nhops_add (vat_main_t * vam)
-{
- unformat_input_t *input = vam->input;
- vl_api_hicn_api_route_nhops_add_t *mp;
-
- fib_prefix_t prefix;
- u32 faceid = 0;
- int ret;
-
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "add prefix %U/%d", unformat_ip46_address,
- &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len))
- {;
- }
- else if (unformat (input, "face %d", &faceid))
- {;
- }
- else
- {
- break;
- }
- }
-
- /* Check parse */
- if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0))
- || (prefix.fp_len == 0) || (faceid == 0))
- {
- clib_warning ("Please specify prefix and faceid...");
- return 1;
- }
- /* Construct the API message */
- M (HICN_API_ROUTE_NHOPS_ADD, mp);
- ip_prefix_encode (&prefix, &mp->prefix);
-
- if (!ip46_address_is_ip4 (&(prefix.fp_addr)))
- prefix.fp_proto = fib_proto_from_ip46 (IP46_TYPE_IP6);
-
- mp->face_ids[0] = clib_host_to_net_u32 (faceid);
- mp->n_faces = 1;
-
- /* send it... */
- S (mp);
-
- /* Wait for a reply... */
- W (ret);
-
- return ret;
-}
-
-static int
-api_hicn_api_route_del (vat_main_t * vam)
-{
- unformat_input_t *input = vam->input;
- vl_api_hicn_api_route_del_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 prefix...");
- return 1;
- }
- /* Construct the API message */
- M (HICN_API_ROUTE_DEL, mp);
- ip_prefix_encode (&prefix, &mp->prefix);
-
- if (!ip46_address_is_ip4 (&(prefix.fp_addr)))
- prefix.fp_proto = fib_proto_from_ip46 (IP46_TYPE_IP6);
-
- /* send it... */
- S (mp);
-
- /* Wait for a reply... */
- W (ret);
-
- return ret;
-
-}
-
-static int
-api_hicn_api_route_nhop_del (vat_main_t * vam)
-{
- unformat_input_t *input = vam->input;
- vl_api_hicn_api_route_nhop_del_t *mp;
-
- fib_prefix_t prefix;
- int faceid = 0, ret;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "del prefix %U/%d", unformat_ip46_address,
- &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len))
- {;
- }
- else if (unformat (input, "face %d", &faceid))
- {;
- }
- else
- {
- break;
- }
- }
-
- /* Check parse */
- if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0))
- || (prefix.fp_len == 0) || (faceid == HICN_FACE_NULL))
- {
- clib_warning ("Please specify prefix and faceid...");
- return 1;
- }
- /* Construct the API message */
- M (HICN_API_ROUTE_NHOP_DEL, mp);
- ip_prefix_encode (&prefix, &mp->prefix);
-
- if (!ip46_address_is_ip4 (&(prefix.fp_addr)))
- prefix.fp_proto = fib_proto_from_ip46 (IP46_TYPE_IP6);
-
- 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_strategies_get (vat_main_t * vam)
{
vl_api_hicn_api_strategies_get_t *mp;
@@ -1415,6 +968,58 @@ static void
}
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;
@@ -1607,12 +1212,104 @@ static void
fformat (vam->ofp,
"ip4 address %U\n"
- "ip6 address :%U\n"
- "appif id :%d\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 <hicn/hicn.api_test.c>
/*
diff --git a/hicn-plugin/src/hicn_msg_enum.h b/hicn-plugin/src/hicn_msg_enum.h
index 291e6226c..fcf2a1e87 100644
--- a/hicn-plugin/src/hicn_msg_enum.h
+++ b/hicn-plugin/src/hicn_msg_enum.h
@@ -18,6 +18,9 @@
#include <vppinfra/byte_order.h>
+/**
+ * @file
+ */
#define vl_msg_id(n, h) n,
typedef enum
{
diff --git a/hicn-plugin/src/infra.h b/hicn-plugin/src/infra.h
index b859b8e46..ff76de4e4 100644
--- a/hicn-plugin/src/infra.h
+++ b/hicn-plugin/src/infra.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,12 +18,17 @@
#include <vlib/vlib.h>
#include <vnet/vnet.h>
+#include <vnet/interface.h>
#include "pcs.h"
/**
- * hICN plugin global state: see also
- * - fib and pits
+ * @file infra.h
+ *
+ */
+
+/**
+ * @brief hICN plugin global state.
*/
typedef struct hicn_main_s
{
@@ -43,6 +48,8 @@ typedef struct hicn_main_s
*/
u64 pit_lifetime_max_ms;
+ vnet_link_t link;
+
} hicn_main_t;
extern hicn_main_t hicn_main;
@@ -67,7 +74,8 @@ int
hicn_infra_plugin_enable_disable (int enable_disable,
int pit_max_size,
f64 pit_max_lifetime_sec_req,
- int cs_max_size, int cs_reserved_app);
+ int cs_max_size,
+ vnet_link_t link);
/* vlib nodes that compose the hICN forwarder */
@@ -80,6 +88,9 @@ 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__ */
diff --git a/hicn-plugin/src/interest_hitcs.h b/hicn-plugin/src/interest_hitcs.h
index c69564452..94fa3e6f5 100644
--- a/hicn-plugin/src/interest_hitcs.h
+++ b/hicn-plugin/src/interest_hitcs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -21,6 +21,16 @@
#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
*/
@@ -41,9 +51,9 @@ typedef struct
typedef enum
{
HICN_INTEREST_HITCS_NEXT_STRATEGY,
- HICN_INTEREST_HITCS_NEXT_PUSH,
+ HICN_INTEREST_HITCS_NEXT_IFACE4_OUT,
+ HICN_INTEREST_HITCS_NEXT_IFACE6_OUT,
HICN_INTEREST_HITCS_NEXT_ERROR_DROP,
- HICN_INTEREST_HITCS_NEXT_EMPTY,
HICN_INTEREST_HITCS_N_NEXT,
} hicn_interest_hitcs_next_t;
diff --git a/hicn-plugin/src/interest_hitcs_node.c b/hicn-plugin/src/interest_hitcs_node.c
index d10f15afa..0212fa5f9 100644
--- a/hicn-plugin/src/interest_hitcs_node.c
+++ b/hicn-plugin/src/interest_hitcs_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -25,8 +25,7 @@
#include "error.h"
/* packet trace format function */
-static u8 *hicn_interest_hitcs_format_trace (u8 * s, va_list * args);
-
+static u8 *hicn_interest_hitcs_format_trace (u8 *s, va_list *args);
/* Stats string values */
static char *hicn_interest_hitcs_error_strings[] = {
@@ -37,10 +36,10 @@ static char *hicn_interest_hitcs_error_strings[] = {
vlib_node_registration_t hicn_interest_hitcs_node;
-always_inline void drop_packet (u32 * next0);
+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)
+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);
@@ -77,11 +76,14 @@ clone_from_cs (vlib_main_t * vm, u32 * bi0_cs, vlib_buffer_t * dest, u8 isv6)
vlib_buffer_advance (cs_buf, buffer_advance);
vlib_buffer_attach_clone (vm, dest, cs_buf);
}
+
+ /* Set fag for packet coming from CS */
+ hicn_get_buffer (dest)->flags |= HICN_BUFFER_FLAGS_FROM_CS;
}
static uword
-hicn_interest_hitcs_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+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;
@@ -152,12 +154,14 @@ hicn_interest_hitcs_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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 };
+ dpo_id_t hicn_dpo_id0 = { .dpoi_type =
+ dpo_vft0->hicn_dpo_get_type (),
+ .dpoi_proto = 0,
+ .dpoi_next_node = 0,
+ .dpoi_index = dpo_ctx_id0 };
- if (PREDICT_FALSE
- (ret != HICN_ERROR_NONE ||
- !hicn_node_compare (nameptr, namelen, node0)))
+ 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,
@@ -176,17 +180,17 @@ hicn_interest_hitcs_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
}
else
{
- if (PREDICT_TRUE
- (!(hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_DELETED)))
+ 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 = hicnb0->face_dpo_id.dpoi_next_node;
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
- hicnb0->face_dpo_id.dpoi_index;
+ 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);
@@ -216,9 +220,8 @@ hicn_interest_hitcs_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
* 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_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);
}
@@ -239,14 +242,14 @@ hicn_interest_hitcs_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
}
always_inline void
-drop_packet (u32 * next0)
+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)
+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 *);
@@ -261,28 +264,22 @@ hicn_interest_hitcs_format_trace (u8 * s, va_list * args)
/*
* Node registration for the interest forwarder node
*/
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE(hicn_interest_hitcs_node) =
-{
+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),
+ .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),
+ .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_PUSH] = "hicn-data-push",
- [HICN_INTEREST_HITCS_NEXT_ERROR_DROP] = "error-drop",
- [HICN_INTEREST_HITCS_NEXT_EMPTY] = "ip6-lookup"
- },
+ .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
diff --git a/hicn-plugin/src/interest_hitpit.h b/hicn-plugin/src/interest_hitpit.h
index fc4cfc3ea..ffdc61c8f 100644
--- a/hicn-plugin/src/interest_hitpit.h
+++ b/hicn-plugin/src/interest_hitpit.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -21,6 +21,17 @@
#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
*/
@@ -42,6 +53,8 @@ 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;
diff --git a/hicn-plugin/src/interest_hitpit_node.c b/hicn-plugin/src/interest_hitpit_node.c
index a346dcc7e..5367c71f8 100644
--- a/hicn-plugin/src/interest_hitpit_node.c
+++ b/hicn-plugin/src/interest_hitpit_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -28,7 +28,7 @@
#include "face_db.h"
/* packet trace format function */
-static u8 *hicn_interest_hitpit_format_trace (u8 * s, va_list * args);
+static u8 *hicn_interest_hitpit_format_trace (u8 *s, va_list *args);
/* Stats string values */
static char *hicn_interest_hitpit_error_strings[] = {
@@ -39,14 +39,14 @@ static char *hicn_interest_hitpit_error_strings[] = {
vlib_node_registration_t hicn_interest_hitpit_node;
-always_inline void drop_packet (u32 * next0);
+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)
+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;
@@ -88,7 +88,7 @@ hicn_interest_hitpit_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
u8 dpo_ctx_id0;
u8 found = 0;
int nh_idx;
- dpo_id_t *outface;
+ hicn_face_id_t outface;
hicn_hash_entry_t *hash_entry0;
hicn_buffer_t *hicnb0;
int ret;
@@ -117,20 +117,21 @@ hicn_interest_hitpit_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
hicn_get_internal_state (hicnb0, rt->pitcs, &node0, &strategy_vft0,
&dpo_vft0, &dpo_ctx_id0, &hash_entry0);
-
ret = hicn_interest_parse_pkt (b0, &name, &namelen, &hicn0, &isv6);
nameptr = (u8 *) (&name);
pitp = hicn_pit_get_data (node0);
- dpo_id_t hicn_dpo_id0 =
- { dpo_vft0->hicn_dpo_get_type (), 0, 0, dpo_ctx_id0 };
+ dpo_id_t hicn_dpo_id0 = { .dpoi_type =
+ dpo_vft0->hicn_dpo_get_type (),
+ .dpoi_proto = 0,
+ .dpoi_next_node = 0,
+ .dpoi_index = dpo_ctx_id0 };
/*
* Check if the hit is instead a collision in the
* hash table. Unlikely to happen.
*/
- if (PREDICT_FALSE
- (ret != HICN_ERROR_NONE
- || !hicn_node_compare (nameptr, namelen, node0)))
+ if (PREDICT_FALSE (ret != HICN_ERROR_NONE ||
+ !hicn_node_compare (nameptr, namelen, node0)))
{
stats.interests_hash_collision++;
/* Remove lock from the entry */
@@ -166,8 +167,7 @@ hicn_interest_hitpit_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
*/
found =
- hicn_face_search (&(hicnb0->face_dpo_id),
- &(pitp->u.pit.faces));
+ hicn_face_search (hicnb0->face_id, &(pitp->u.pit.faces));
if (found)
{
@@ -178,9 +178,9 @@ hicn_interest_hitpit_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
* Prepare the packet for the
* forwarding
*/
- next0 = outface->dpoi_next_node;
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] =
- outface->dpoi_index;
+ 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
@@ -191,8 +191,8 @@ hicn_interest_hitpit_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
}
else
{
- hicn_face_db_add_face_dpo (&hicnb0->face_dpo_id,
- &pitp->u.pit.faces);
+ hicn_face_db_add_face (hicnb0->face_id,
+ &pitp->u.pit.faces);
/* Aggregation */
drop_packet (&next0);
@@ -201,7 +201,6 @@ hicn_interest_hitpit_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
/* Remove lock from the entry */
hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm,
hash_entry0, dpo_vft0, &hicn_dpo_id0);
-
}
}
end_processing:
@@ -223,15 +222,13 @@ hicn_interest_hitpit_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
* 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_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,
@@ -255,7 +252,7 @@ hicn_interest_hitpit_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
/* packet trace format function */
static u8 *
-hicn_interest_hitpit_format_trace (u8 * s, va_list * args)
+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 *);
@@ -268,7 +265,7 @@ hicn_interest_hitpit_format_trace (u8 * s, va_list * args)
}
void
-drop_packet (u32 * next0)
+drop_packet (u32 *next0)
{
*next0 = HICN_INTEREST_HITPIT_NEXT_ERROR_DROP;
}
@@ -276,7 +273,6 @@ drop_packet (u32 * next0)
/*
* Node registration for the interest forwarder node
*/
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE(hicn_interest_hitpit_node) =
{
.function = hicn_interest_hitpit_node_fn,
@@ -293,10 +289,11 @@ VLIB_REGISTER_NODE(hicn_interest_hitpit_node) =
{
[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
diff --git a/hicn-plugin/src/interest_pcslookup.h b/hicn-plugin/src/interest_pcslookup.h
index 5a5a6a7a8..cbc9dde51 100644
--- a/hicn-plugin/src/interest_pcslookup.h
+++ b/hicn-plugin/src/interest_pcslookup.h
@@ -21,6 +21,17 @@
#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
*/
diff --git a/hicn-plugin/src/interest_pcslookup_node.c b/hicn-plugin/src/interest_pcslookup_node.c
index 6ac2aa3a0..d3f6c7bca 100644
--- a/hicn-plugin/src/interest_pcslookup_node.c
+++ b/hicn-plugin/src/interest_pcslookup_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -24,7 +24,8 @@
#include "state.h"
/**
- * @FILE This node performs a lookup in the PIT and CS for a received interest packet.
+ * @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.
@@ -33,8 +34,7 @@
/* Functions declarations */
/* packet trace format function */
-static u8 *hicn_interest_pcslookup_format_trace (u8 * s, va_list * args);
-
+static u8 *hicn_interest_pcslookup_format_trace (u8 *s, va_list *args);
/* Stats string values */
static char *hicn_interest_pcslookup_error_strings[] = {
@@ -50,8 +50,8 @@ vlib_node_registration_t hicn_interest_pcslookup_node;
* 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)
+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;
@@ -118,22 +118,20 @@ hicn_interest_pcslookup_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
nameptr = (u8 *) (&name);
stats.pkts_processed++;
- if (PREDICT_FALSE (ret != HICN_ERROR_NONE ||
- hicn_hashtb_fullhash (nameptr, namelen,
- &name_hash) !=
- HICN_ERROR_NONE))
+ 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)
+ 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;
@@ -159,10 +157,8 @@ hicn_interest_pcslookup_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
* 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_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);
}
@@ -170,7 +166,6 @@ hicn_interest_pcslookup_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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);
@@ -192,7 +187,7 @@ hicn_interest_pcslookup_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
/* packet trace format function */
static u8 *
-hicn_interest_pcslookup_format_trace (u8 * s, va_list * args)
+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 *);
@@ -204,11 +199,9 @@ hicn_interest_pcslookup_format_trace (u8 * s, va_list * args)
return (s);
}
-
/*
* Node registration for the interest forwarder node
*/
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE(hicn_interest_pcslookup_node) =
{
.function = hicn_interest_pcslookup_node_fn,
@@ -228,7 +221,6 @@ VLIB_REGISTER_NODE(hicn_interest_pcslookup_node) =
[HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP] = "error-drop",
},
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/mapme.h b/hicn-plugin/src/mapme.h
index 071590ede..17bd9a766 100644
--- a/hicn-plugin/src/mapme.h
+++ b/hicn-plugin/src/mapme.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,13 +18,34 @@
#include <vnet/dpo/load_balance.h>
#include <vnet/buffer.h>
-//#include <hicn/hicn.h>
#include <hicn/mapme.h>
#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
@@ -34,6 +55,9 @@
#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;
@@ -43,6 +67,9 @@ typedef struct hicn_mapme_conf_s
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) \
@@ -72,13 +99,24 @@ typedef hicn_dpo_ctx_t hicn_mapme_tfib_t;
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) ((hicn_mapme_tfib_t*)(dpo))
+#define TFIB(dpo_ctx) ((hicn_mapme_tfib_t*)(dpo_ctx))
static_always_inline int
-hicn_mapme_nh_set (hicn_mapme_tfib_t * tfib, dpo_id_t * face_id)
+hicn_mapme_nh_set (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id)
{
- tfib->next_hops[0] = *face_id;
- tfib->entry_count = 1;
+ 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;
}
@@ -86,12 +124,18 @@ hicn_mapme_nh_set (hicn_mapme_tfib_t * tfib, dpo_id_t * face_id)
* @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, dpo_id_t * face_id)
+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 (dpo_cmp (&tfib->next_hops[pos], face_id) == 0)
+ if (tfib->next_hops[pos] == face_id)
return 0;
- tfib->next_hops[tfib->entry_count++] = *face_id;
+
+ /* 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;
}
@@ -101,30 +145,36 @@ hicn_mapme_nh_add (hicn_mapme_tfib_t * tfib, dpo_id_t * face_id)
* 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, dpo_id_t * face_id)
+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 (dpo_cmp (&tfib->next_hops[pos2], face_id) == 0)
+ 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->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)
{
- dpo_id_t invalid = NEXT_HOP_INVALID;
+ hicn_face_id_t invalid = NEXT_HOP_INVALID;
/*
* We need to do a linear scan of TFIB entries to find the one to
* remove
@@ -133,7 +183,7 @@ hicn_mapme_tfib_clear (hicn_mapme_tfib_t * tfib)
u8 pos = ~0;
for (pos = start_pos; pos < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos++)
{
- hicn_face_unlock (&tfib->next_hops[pos]);
+ hicn_face_unlock_with_id (tfib->next_hops[pos]);
tfib->next_hops[pos] = invalid;
break;
}
@@ -144,9 +194,9 @@ hicn_mapme_tfib_clear (hicn_mapme_tfib_t * tfib)
}
static_always_inline int
-hicn_mapme_tfib_del (hicn_mapme_tfib_t * tfib, dpo_id_t * face_id)
+hicn_mapme_tfib_del (hicn_mapme_tfib_t * tfib, hicn_face_id_t face_id)
{
- dpo_id_t invalid = NEXT_HOP_INVALID;
+ hicn_face_id_t invalid = NEXT_HOP_INVALID;
/*
* We need to do a linear scan of TFIB entries to find the one to
* remove
@@ -154,9 +204,9 @@ hicn_mapme_tfib_del (hicn_mapme_tfib_t * tfib, dpo_id_t * face_id)
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 (dpo_cmp (&tfib->next_hops[pos], face_id) == 0)
+ if (tfib->next_hops[pos] == face_id)
{
- hicn_face_unlock (&tfib->next_hops[pos]);
+ hicn_face_unlock_with_id (tfib->next_hops[pos]);
tfib->next_hops[pos] = invalid;
break;
}
@@ -168,8 +218,8 @@ hicn_mapme_tfib_del (hicn_mapme_tfib_t * tfib, dpo_id_t * face_id)
/* 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, tfib->next_hops + start_pos + 1,
- (pos - start_pos) * sizeof (dpo_id_t));
+ memmove (tfib->next_hops + start_pos +1 , tfib->next_hops + start_pos,
+ (pos - start_pos) * sizeof (hicn_face_id_t));
return 0;
}
@@ -287,34 +337,17 @@ hicn_mapme_get_dpo_vlib_edge (dpo_id_t * dpo)
* @brief Returns the next hop node on which we can send an Update packet
*/
always_inline char *
-hicn_mapme_get_dpo_face_node (dpo_id_t * dpo)
+hicn_mapme_get_dpo_face_node (hicn_face_id_t face_id)
{
- if (dpo->dpoi_type == hicn_face_ip_type)
- {
- switch (dpo->dpoi_proto)
- {
- case DPO_PROTO_IP4:
- return "hicn-face-ip4-output";
- case DPO_PROTO_IP6:
- return "hicn-face-ip6-output";
- default:
- return NULL;
- }
- }
- else if (dpo->dpoi_type == hicn_face_udp_type)
- {
- switch (dpo->dpoi_proto)
- {
- case DPO_PROTO_IP4:
- return "hicn-face-udp4-output";
- case DPO_PROTO_IP6:
- return "hicn-face-udp6-output";
- default:
- return NULL;
- }
- }
- else
+ 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;
}
}
diff --git a/hicn-plugin/src/mapme_ack.h b/hicn-plugin/src/mapme_ack.h
index 98a219982..821baf203 100644
--- a/hicn-plugin/src/mapme_ack.h
+++ b/hicn-plugin/src/mapme_ack.h
@@ -24,6 +24,11 @@
#include <vlib/vlib.h>
#include <vnet/vnet.h>
+/**
+ * @file
+ *
+ */
+
/* Node context data */
typedef struct hicn_mapme_ack_runtime_s
{
diff --git a/hicn-plugin/src/mapme_ack_node.c b/hicn-plugin/src/mapme_ack_node.c
index 557fb0ad7..fad344b73 100644
--- a/hicn-plugin/src/mapme_ack_node.c
+++ b/hicn-plugin/src/mapme_ack_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -30,8 +30,7 @@
extern hicn_mapme_main_t mapme_main;
/* packet trace format function */
-static u8 *hicn_mapme_ack_format_trace (u8 * s, va_list * args);
-
+static u8 *hicn_mapme_ack_format_trace (u8 *s, va_list *args);
/* Stats string values */
static char *hicn_mapme_ack_error_strings[] = {
@@ -47,8 +46,8 @@ static char *hicn_mapme_ack_error_strings[] = {
* @param face_id Ingress face id
*/
bool
-hicn_mapme_process_ack (vlib_main_t * vm, vlib_buffer_t * b,
- dpo_id_t * in_face)
+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;
@@ -57,8 +56,7 @@ hicn_mapme_process_ack (vlib_main_t * vm, vlib_buffer_t * b,
int rc;
/* Parse incoming message */
- rc =
- hicn_mapme_parse_packet (vlib_buffer_get_current (b), &prefix, &params);
+ rc = hicn_mapme_parse_packet (vlib_buffer_get_current (b), &prefix, &params);
if (rc < 0)
goto ERR_PARSE;
@@ -73,14 +71,12 @@ hicn_mapme_process_ack (vlib_main_t * vm, vlib_buffer_t * b,
{
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));
+ hicn_mapme_tfib_t *tfib = TFIB (hicn_strategy_dpo_ctx_get (dpo->dpoi_index));
if (tfib == NULL)
{
@@ -106,15 +102,11 @@ hicn_mapme_process_ack (vlib_main_t * vm, vlib_buffer_t * b,
* 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};
+ 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:
@@ -124,8 +116,8 @@ ERR_PARSE:
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_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;
@@ -136,12 +128,11 @@ hicn_mapme_ack_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
n_left_from = frame->n_vectors;
next_index = node->cached_next_index;
- while (n_left_from > 0) // buffers in the current frame
+ 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;
@@ -159,13 +150,13 @@ hicn_mapme_ack_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_cli_output (vm, "Received IUAck");
hb = hicn_get_buffer (b0);
- hicn_mapme_process_ack (vm, b0, &hb->face_dpo_id);
+ 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)))
+ 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));
@@ -175,20 +166,19 @@ hicn_mapme_ack_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
/* $$$$$ 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_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);
+ // 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)
+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 *);
@@ -199,11 +189,9 @@ hicn_mapme_ack_format_trace (u8 * s, va_list * args)
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,
@@ -220,7 +208,6 @@ VLIB_REGISTER_NODE (hicn_mapme_ack_node) =
[HICN_MAPME_ACK_NEXT_ERROR_DROP] = "error-drop",
},
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/mapme_ctrl.h b/hicn-plugin/src/mapme_ctrl.h
index e7c1cdf64..9af4beccc 100644
--- a/hicn-plugin/src/mapme_ctrl.h
+++ b/hicn-plugin/src/mapme_ctrl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -24,6 +24,11 @@
#include <vlib/vlib.h>
#include <vnet/vnet.h>
+/**
+ * @file mapme_ctrl.h
+ *
+ */
+
/* Node context data */
typedef struct hicn_mapme_ctrl_runtime_s
{
@@ -42,8 +47,6 @@ typedef enum
{
HICN_MAPME_CTRL_NEXT_IP4_OUTPUT,
HICN_MAPME_CTRL_NEXT_IP6_OUTPUT,
- HICN_MAPME_CTRL_NEXT_UDP46_OUTPUT,
- HICN_MAPME_CTRL_NEXT_UDP66_OUTPUT,
HICN_MAPME_CTRL_NEXT_ERROR_DROP,
HICN_MAPME_CTRL_N_NEXT,
} hicn_mapme_ctrl_next_t;
@@ -51,34 +54,17 @@ typedef enum
* @brief Returns the next hop node on which we can send an ACK packet
*/
always_inline hicn_mapme_ctrl_next_t
-hicn_mapme_get_dpo_iface_node (dpo_id_t * dpo)
+hicn_mapme_ctrl_get_iface_node (hicn_face_id_t face_id)
{
- if (dpo->dpoi_type == hicn_face_ip_type)
- {
- switch (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;
- }
- }
- else if (dpo->dpoi_type == hicn_face_udp_type)
- {
- switch (dpo->dpoi_proto)
- {
- case DPO_PROTO_IP4:
- return HICN_MAPME_CTRL_NEXT_UDP46_OUTPUT;
- case DPO_PROTO_IP6:
- return HICN_MAPME_CTRL_NEXT_UDP66_OUTPUT;
- default:
- return HICN_MAPME_CTRL_NEXT_ERROR_DROP;
- }
- }
- else
+ 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;
}
}
diff --git a/hicn-plugin/src/mapme_ctrl_node.c b/hicn-plugin/src/mapme_ctrl_node.c
index 182fbabd3..613958d9c 100644
--- a/hicn-plugin/src/mapme_ctrl_node.c
+++ b/hicn-plugin/src/mapme_ctrl_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -38,8 +38,7 @@ extern hicn_mapme_main_t mapme_main;
/* Functions declarations */
/* packet trace format function */
-static u8 *hicn_mapme_ctrl_format_trace (u8 * s, va_list * args);
-
+static u8 *hicn_mapme_ctrl_format_trace (u8 *s, va_list *args);
/* Stats string values */
static char *hicn_mapme_ctrl_error_strings[] = {
@@ -48,18 +47,6 @@ static char *hicn_mapme_ctrl_error_strings[] = {
#undef _
};
-/**
- * Preprocess the ingress face so as to make it a candidate next hop, which is
- * what MAP-Me will handle
- */
-static_always_inline void
-preprocess_in_face (hicn_type_t type, dpo_id_t * in, dpo_id_t * out)
-{
- u32 vlib_edge = hicn_mapme_get_dpo_vlib_edge (in);
- *out = *in;
- out->dpoi_next_node = vlib_edge;
-}
-
/*
* @brief Process incoming control messages (Interest Update)
* @param vm vlib main data structure
@@ -69,12 +56,12 @@ preprocess_in_face (hicn_type_t type, dpo_id_t * in, dpo_id_t * out)
* 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.
+ * 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,
- dpo_id_t * in_face)
+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;
@@ -83,8 +70,7 @@ hicn_mapme_process_ctrl (vlib_main_t * vm, vlib_buffer_t * b,
int rc;
/* Parse incoming message */
- rc =
- hicn_mapme_parse_packet (vlib_buffer_get_current (b), &prefix, &params);
+ rc = hicn_mapme_parse_packet (vlib_buffer_get_current (b), &prefix, &params);
if (rc < 0)
goto ERR_PARSE;
@@ -114,10 +100,9 @@ hicn_mapme_process_ctrl (vlib_main_t * vm, vlib_buffer_t * b,
DEBUG ("Re-creating FIB entry with next hop on connection")
#error "not implemented"
#else
- //ERROR("Received IU for non-existing FIB entry");
+ // ERROR("Received IU for non-existing FIB entry");
return false;
#endif /* HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY */
-
}
#ifdef HICN_MAPME_ALLOW_LOCATORS
@@ -130,8 +115,7 @@ hicn_mapme_process_ctrl (vlib_main_t * vm, vlib_buffer_t * b,
#endif
/* Process the hICN DPO */
- hicn_mapme_tfib_t * tfib =
- TFIB (hicn_strategy_dpo_ctx_get (dpo->dpoi_index));
+ hicn_mapme_tfib_t *tfib = TFIB (hicn_strategy_dpo_ctx_get (dpo->dpoi_index));
if (tfib == NULL)
{
@@ -143,9 +127,9 @@ hicn_mapme_process_ctrl (vlib_main_t * vm, vlib_buffer_t * b,
if (params.seq > fib_seq)
{
- DEBUG
- ("Higher sequence number than FIB %d > %d, updating seq and next hops",
- 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;
@@ -153,38 +137,34 @@ hicn_mapme_process_ctrl (vlib_main_t * vm, vlib_buffer_t * b,
// 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);
+ 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++)
{
- // XXX BUG
- if (dpo_cmp (&tfib->next_hops[pos], in_face) == 0)
+ 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))
{
- tfib->entry_count = 0;
- break;
+ 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->dpoi_index, tfib->next_hops[pos].dpoi_index);
- hicn_mapme_tfib_add (tfib, &tfib->next_hops[pos]);
+ 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]);
}
- /* ... and set ingress face as next_hop */
- in_face->dpoi_next_node = hicn_mapme_get_dpo_vlib_edge (in_face);
- hicn_mapme_nh_set (tfib, in_face);
-
- /* 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
- };
+ 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)
{
@@ -192,47 +172,36 @@ hicn_mapme_process_ctrl (vlib_main_t * vm, vlib_buffer_t * b,
params.seq, fib_seq);
/* Remove ingress face from TFIB in case it was present */
- hicn_mapme_tfib_del (tfib, in_face);
+ hicn_mapme_tfib_del (tfib, in_face_id);
/* Add ingress face to next hops */
- hicn_mapme_nh_add (tfib, in_face);
+ 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};
+ 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
+ else // params.seq < fib_seq
{
/*
* face is propagating outdated information, we can just consider it as a
* prevHops
*/
- // XXX BUG
- hicn_mapme_tfib_add (tfib, in_face);
-
- 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};
+ 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_ACK_CREATE:
ERR_PARSE:
return false;
}
@@ -240,25 +209,24 @@ ERR_PARSE:
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_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;
- dpo_id_t in_face;
+ // 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
+ 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;
@@ -274,32 +242,28 @@ hicn_mapme_ctrl_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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_get_dpo_iface_node (&hb->face_dpo_id);
-
- /* Preprocessing is needed to precompute in the dpo the next node
- * that will have to be followed by regular interests when being
- * forwarder on a given next hop
+ /* This determines the next node on which the ack will be sent back
*/
- preprocess_in_face (hb->type, &hb->face_dpo_id, &in_face);
- hicn_mapme_process_ctrl (vm, b0, &in_face);
+ u32 next0 = hicn_mapme_ctrl_get_iface_node (hb->face_id);
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = in_face.dpoi_index;
+ 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);
+ // 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)
+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 *);
@@ -310,11 +274,9 @@ hicn_mapme_ctrl_format_trace (u8 * s, va_list * args)
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,
@@ -333,14 +295,11 @@ VLIB_REGISTER_NODE (hicn_mapme_ctrl_node) =
* 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] = "hicn-iface-ip4-output",
- [HICN_MAPME_CTRL_NEXT_IP6_OUTPUT] = "hicn-iface-ip6-output",
- [HICN_MAPME_CTRL_NEXT_UDP46_OUTPUT] = "hicn-iface-udp4-output",
- [HICN_MAPME_CTRL_NEXT_UDP66_OUTPUT] = "hicn-iface-udp6-output",
+ [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
diff --git a/hicn-plugin/src/mapme_eventmgr.c b/hicn-plugin/src/mapme_eventmgr.c
index f35a9909a..69740ba0a 100644
--- a/hicn-plugin/src/mapme_eventmgr.c
+++ b/hicn-plugin/src/mapme_eventmgr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -22,7 +22,7 @@
#include <vnet/fib/ip4_fib.h>
#include <vnet/fib/ip6_fib.h>
-#define DEFAULT_TIMEOUT 1.0 /* s */
+#define DEFAULT_TIMEOUT 1.0 /* s */
hicn_mapme_main_t mapme_main;
@@ -30,7 +30,7 @@ hicn_prefix_t *retx_pool;
uword *retx_hash;
void
-hicn_mapme_init (vlib_main_t * vm)
+hicn_mapme_init (vlib_main_t *vm)
{
mapme_main.vm = vm;
mapme_main.log_class = vlib_log_register_class ("hicn_mapme", 0);
@@ -71,8 +71,8 @@ ip6_fib_table_show_walk (fib_node_index_t fib_entry_index, void *arg)
}
void
-hicn_mapme_process_fib_entry (vlib_main_t * vm, dpo_id_t face,
- const fib_node_index_t * fib_entry_index)
+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;
@@ -103,42 +103,40 @@ hicn_mapme_process_fib_entry (vlib_main_t * vm, dpo_id_t face,
}
void
-hicn_mapme_process_ip4_fib (vlib_main_t * vm, dpo_id_t face)
+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);
+ 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;
+ 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,
- };
+ 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);
+ 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_foreach (fib_entry_index, ctx.ifsw_indicies)
+ {
+ hicn_mapme_process_fib_entry (vm, face, fib_entry_index);
+ }
- vec_free(ctx.ifsw_indicies);
- }));
- /* *INDENT-ON* */
+ vec_free (ctx.ifsw_indicies);
+ }
}
void
-hicn_mapme_process_ip6_fib (vlib_main_t * vm, dpo_id_t face)
+hicn_mapme_process_ip6_fib (vlib_main_t *vm, hicn_face_id_t face)
{
/* Walk IPv6 FIB */
ip6_main_t *im6 = &ip6_main;
@@ -146,43 +144,39 @@ hicn_mapme_process_ip6_fib (vlib_main_t * vm, dpo_id_t face)
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;
+ pool_foreach (fib_table, im6->fibs)
+ {
+ fib = pool_elt_at_index (im6->v6_fibs, fib_table->ft_index);
- fib_node_index_t *fib_entry_index;
- ip6_fib_show_ctx_t ctx = {
- .entries = NULL,
- };
+ 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;
- ip6_fib_table_walk(fib->index, ip6_fib_table_show_walk, &ctx);
- //vec_sort_with_function(ctx.entries, fib_entry_cmp_for_sort);
+ fib_node_index_t *fib_entry_index;
+ ip6_fib_show_ctx_t ctx = {
+ .entries = NULL,
+ };
- vec_foreach(fib_entry_index, ctx.entries)
- {
- hicn_mapme_process_fib_entry(vm, face, fib_entry_index);
- }
+ ip6_fib_table_walk (fib->index, ip6_fib_table_show_walk, &ctx);
+ // vec_sort_with_function(ctx.entries, fib_entry_cmp_for_sort);
- vec_free(ctx.entries);
+ vec_foreach (fib_entry_index, ctx.entries)
+ {
+ hicn_mapme_process_fib_entry (vm, face, fib_entry_index);
+ }
- }));
- /* *INDENT-ON* */
+ vec_free (ctx.entries);
+ }
}
-
/**
* Callback called everytime a new face is created (not including app faces)
*/
void
-hicn_mapme_on_face_added (vlib_main_t * vm, dpo_id_t face)
+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);
@@ -194,19 +188,19 @@ hicn_mapme_on_face_added (vlib_main_t * vm, dpo_id_t face)
* 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)]
+#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)
+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
+ vlib_buffer_t *b; // for newly created packet
u32 *to_next;
u32 bi;
u8 *buffer;
@@ -241,8 +235,8 @@ get_packet_buffer (vlib_main_t * vm, u32 node_index, u32 dpoi_index,
}
static_always_inline bool
-hicn_mapme_send_message (vlib_main_t * vm, const hicn_prefix_t * prefix,
- mapme_params_t * params, dpo_id_t * face)
+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;
@@ -253,19 +247,17 @@ hicn_mapme_send_message (vlib_main_t * vm, const hicn_prefix_t * prefix,
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");
+ 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->dpoi_index,
- (ip46_address_t *) prefix,
- (params->protocol ==
- IPPROTO_IPV6) ? HICN_TYPE_IPV6_ICMP :
- HICN_TYPE_IPV4_ICMP);
+ 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)
{
@@ -277,8 +269,8 @@ hicn_mapme_send_message (vlib_main_t * vm, const hicn_prefix_t * prefix,
}
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_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)
@@ -290,41 +282,38 @@ hicn_mapme_send_updates (vlib_main_t * vm, hicn_prefix_t * prefix,
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,
+ .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++)
+ for (u8 pos = tfib_last_idx; pos < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; pos++)
{
- hicn_mapme_send_message (vm, prefix, &params,
- &tfib->next_hops[pos]);
+ hicn_mapme_send_message (vm, prefix, &params, tfib->next_hops[pos]);
}
}
else
{
- // XXX BUG are we sure it is always the last ??
hicn_mapme_send_message (vm, prefix, &params,
- &tfib->next_hops[tfib_last_idx]);
+ 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)
+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 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 */
+ u8 cur = 0; /* current slot */
hicn_mapme_init (vm);
@@ -334,8 +323,8 @@ hicn_mapme_eventmgr_process (vlib_main_t * vm,
* 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
+ * The most probable event. For simplicity, for new faces, we pass the
+ * same retx_t with no prefix
*/
if (timeout != 0)
{
@@ -347,9 +336,8 @@ hicn_mapme_eventmgr_process (vlib_main_t * vm,
* 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;
+ timeout = (due_time > current_time) ? due_time - current_time :
+ DEFAULT_TIMEOUT;
due_time = current_time + timeout;
}
else
@@ -366,14 +354,15 @@ hicn_mapme_eventmgr_process (vlib_main_t * vm,
{
/*
* A face has been added:
- * - In case of a local app face, we need to advertise a new prefix
+ * - 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].dpo);
+ hicn_mapme_on_face_added (vm, retx_events[i].face_id);
}
idle = 0;
}
@@ -388,8 +377,8 @@ hicn_mapme_eventmgr_process (vlib_main_t * vm,
/*
* 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
+ * 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 */
@@ -414,7 +403,7 @@ hicn_mapme_eventmgr_process (vlib_main_t * vm,
* 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_t *retx = (retx_t *) &retx_events[i];
retx->rtx_count = 0;
/*
@@ -423,11 +412,12 @@ hicn_mapme_eventmgr_process (vlib_main_t * vm,
*/
hicn_mapme_send_updates (vm, &retx->prefix, retx->dpo, true);
- /* Delete entry_id from retransmissions in the current slot (if present) ... */
+ /* 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 */
+ CUR[j].dpo.dpoi_index = ~0; /* sufficient */
}
/* ... and schedule it for next slot (if not already) */
@@ -435,7 +425,7 @@ hicn_mapme_eventmgr_process (vlib_main_t * vm,
for (j = 0; j < NXTLEN; j++)
if (!dpo_cmp (&NXT[j].dpo, &retx->dpo))
break;
- if (j == NXTLEN) /* not found */
+ if (j == NXTLEN) /* not found */
NXT[NXTLEN++] = *retx;
}
idle = 0;
@@ -448,9 +438,9 @@ hicn_mapme_eventmgr_process (vlib_main_t * vm,
* 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
+ * 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.
*/
@@ -496,7 +486,7 @@ hicn_mapme_eventmgr_process (vlib_main_t * vm,
{
retx_t *retx = &CUR[pos];
- if (retx->dpo.dpoi_index == ~0) /* deleted entry */
+ if (retx->dpo.dpoi_index == ~0) /* deleted entry */
continue;
hicn_mapme_tfib_t *tfib =
@@ -511,12 +501,14 @@ hicn_mapme_eventmgr_process (vlib_main_t * vm,
hicn_mapme_send_updates (vm, &retx->prefix, retx->dpo, true);
retx->rtx_count++;
- // If we exceed the numver of retransmission it means that all tfib entries have seens at least HICN_PARAM_RTX_MAX of retransmission
+ // 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
+ * We did some retransmissions, so let's reschedule a check
+ * in the next slot
*/
NXT[NXTLEN++] = CUR[pos];
idle = 0;
@@ -542,7 +534,6 @@ hicn_mapme_eventmgr_process (vlib_main_t * vm,
timeout = (idle > 1) ? 0 : DEFAULT_TIMEOUT;
// if (vlib_process_suspend_time_is_zero (timeout)) { ... }
-
}
/* NOTREACHED */
@@ -550,14 +541,13 @@ hicn_mapme_eventmgr_process (vlib_main_t * vm,
}
/* 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,
+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
diff --git a/hicn-plugin/src/mapme_eventmgr.h b/hicn-plugin/src/mapme_eventmgr.h
index b715ae847..b63d16805 100644
--- a/hicn-plugin/src/mapme_eventmgr.h
+++ b/hicn-plugin/src/mapme_eventmgr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -15,6 +15,13 @@
#include <vlib/vlib.h> // vlib_node_registration_t (vlib/node.h)
+#include <hicn/name.h>
+
+/**
+ * @file mapme_eventmgr.h
+ *
+ */
+
/*
* Structure carrying all necessary information for managing Special Interest
* (re)transmissions.
@@ -23,12 +30,11 @@ 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;
-#if 0
#define HASH32(x) ((u16)x ^ (x << 16))
-#endif
/**
* @brief This is a process node reacting to face events.
diff --git a/hicn-plugin/src/mgmt.h b/hicn-plugin/src/mgmt.h
index 326922a01..6db0fe0c1 100644
--- a/hicn-plugin/src/mgmt.h
+++ b/hicn-plugin/src/mgmt.h
@@ -20,6 +20,11 @@
#include "faces/face.h"
#include "hicn_api.h"
+/**
+ * @file mgmt.h
+ *
+ */
+
typedef struct icn_stats_s
{
u32 pkts_processed;
diff --git a/hicn-plugin/src/params.h b/hicn-plugin/src/params.h
index 606d42992..606d50771 100644
--- a/hicn-plugin/src/params.h
+++ b/hicn-plugin/src/params.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,6 +18,12 @@
#include <math.h>
+/**
+ * @file params.h
+ *
+ */
+
+
/*
* Features
*/
@@ -37,7 +43,7 @@ STATIC_ASSERT ((HICN_PARAM_FACES_MAX & (HICN_PARAM_FACES_MAX - 1)) == 0,
#define HICN_PARAM_HICN_NAME_LEN_MAX 20 //bytes
// Max next - hops supported in a FIB entry
-#define HICN_PARAM_FIB_ENTRY_NHOPS_MAX 5
+#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
diff --git a/hicn-plugin/src/parser.h b/hicn-plugin/src/parser.h
index 0d72780ae..e79d65831 100644
--- a/hicn-plugin/src/parser.h
+++ b/hicn-plugin/src/parser.h
@@ -21,6 +21,9 @@
#include "hicn.h"
#include "error.h"
+/**
+ * @file parser.h
+ */
/*
* Key type codes for header, header tlvs, body tlvs, and child tlvs
@@ -33,6 +36,15 @@ enum hicn_pkt_type_e
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)
@@ -61,6 +73,15 @@ hicn_interest_parse_pkt (vlib_buffer_t * pkt, hicn_name_t * name,
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)
diff --git a/hicn-plugin/src/pcs.c b/hicn-plugin/src/pcs.c
index 4355aaeb0..6c44b9d83 100644
--- a/hicn-plugin/src/pcs.c
+++ b/hicn-plugin/src/pcs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -34,7 +34,6 @@ hicn_pit_create (hicn_pit_cs_t * p, u32 num_elems)
(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->pcs_app_max = HICN_PARAM_CS_LRU_DEFAULT - p->policy_state.max;
p->policy_vft.hicn_cs_insert = hicn_cs_lru.hicn_cs_insert;
p->policy_vft.hicn_cs_update = hicn_cs_lru.hicn_cs_update;
diff --git a/hicn-plugin/src/pcs.h b/hicn-plugin/src/pcs.h
index fc63bd0a6..083efa901 100644
--- a/hicn-plugin/src/pcs.h
+++ b/hicn-plugin/src/pcs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -22,27 +22,36 @@
#include "error.h"
#include "cache_policies/cs_policy.h"
#include "faces/face.h"
-#include "faces/ip/dpo_ip.h"
-#include "faces/app/face_prod.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
+#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.
+ * Counters are maintained by the background process. TODO.
*/
-#define SEC_MS 1000
+#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)
/*
- * Max number of incoming (interest) faces supported, for now. Note that
- * changing this may change alignment within the PIT struct, so be careful.
+ * Note that changing this may change alignment within the PIT struct, so be
+ * careful.
*/
typedef struct __attribute__ ((packed)) hicn_pcs_shared_s
{
@@ -72,51 +81,43 @@ typedef struct __attribute__ ((packed)) hicn_pit_entry_s
/*
* Egress next hop (containes the egress face) This id refers to the
- * nh
- */
- /* choosen in the next_hops array of the dpo */
+ * position of the choosen face in the next_hops array of the dpo */
/* 18B + 1B = 19B */
u8 pe_txnh;
- /* Array of faces */
+ /* 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 - 40
+#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
{
- /* 22B + 2B = 24B */
+ /* 18B + 2B = 20B */
u16 align;
/* Packet buffer, if held */
- /* 18B + 4B = 22B */
+ /* 20B + 4B = 24B */
u32 cs_pkt_buf;
/* Ingress face */
- /* 24B + 8B = 32B */
- //Fix alignment issues
- union
- {
- dpo_id_t cs_rxface;
- u64 cs_rxface_u64;
- };
+ /* 24B + 4B = 28B */
+ hicn_face_id_t cs_rxface;
/* Linkage for LRU, in the form of hashtable node indexes */
- /* 32B + 8B = 40B */
+ /* 28B + 8B = 36B */
u32 cs_lru_prev;
u32 cs_lru_next;
/* Reserved for implementing cache policy different than LRU */
- /* 40B + (64 - 40)B = 64B */
+ /* 36B + (64 - 36)B = 64B */
u8 opaque[HICN_CS_ENTRY_OPAQUE_SIZE];
-
} __attribute__ ((packed)) hicn_cs_entry_t;
/*
@@ -136,7 +137,6 @@ typedef struct hicn_pcs_entry_s
} u;
} hicn_pcs_entry_t;
-
/*
* Overall PIT/CS table, based on the common hashtable
*/
@@ -154,100 +154,98 @@ typedef struct hicn_pit_cs_s
/* Total size of PCS */
u32 pcs_size;
- /* Memory reserved for appfaces */
- u32 pcs_app_max;
- u32 pcs_app_count;
-
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, dpo_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);
+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);
+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_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, dpo_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);
+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_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);
+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);
+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);
+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)
+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)
+hicn_pit_init_data (hicn_pcs_entry_t *p)
{
p->shared.entry_flags = 0;
p->u.pit.faces.n_faces = 0;
@@ -260,14 +258,13 @@ hicn_pit_init_data (hicn_pcs_entry_t * p)
/* Init pit/cs data block (usually inside hash table node) */
static inline void
-hicn_cs_init_data (hicn_pcs_entry_t * p)
+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)
{
@@ -279,26 +276,16 @@ hicn_pcs_get_exp_time (f64 cur_time_sec, u64 lifetime_msec)
* good choice.
*/
static inline void
-hicn_pit_set_lru_max (hicn_pit_cs_t * p, u32 limit)
+hicn_pit_set_lru_max (hicn_pit_cs_t *p, u32 limit)
{
p->policy_state.max = limit;
}
/*
- * Configure CS LRU limit. Zero is accepted, means 'no limit', probably not a
- * good choice.
- */
-static inline void
-hicn_pit_set_lru_app_max (hicn_pit_cs_t * p, u32 limit)
-{
- p->pcs_app_max = limit;
-}
-
-/*
* Accessor for PIT interest counter.
*/
static inline u32
-hicn_pit_get_int_count (const hicn_pit_cs_t * pitcs)
+hicn_pit_get_int_count (const hicn_pit_cs_t *pitcs)
{
return (pitcs->pcs_pit_count);
}
@@ -307,25 +294,25 @@ hicn_pit_get_int_count (const hicn_pit_cs_t * pitcs)
* Accessor for PIT cs entries counter.
*/
static inline u32
-hicn_pit_get_cs_count (const hicn_pit_cs_t * pitcs)
+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)
+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)
+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)
+hicn_cs_enabled (hicn_pit_cs_t *pit)
{
switch (HICN_FEATURE_CS)
{
@@ -344,12 +331,10 @@ hicn_cs_enabled (hicn_pit_cs_t * pit)
* 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_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;
@@ -361,8 +346,8 @@ hicn_pcs_delete_internal (hicn_pit_cs_t * pitcs,
/* 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));
+ ASSERT ((pcs->u.cs.cs_lru_prev == 0) &&
+ (pcs->u.cs.cs_lru_prev == pcs->u.cs.cs_lru_next));
}
else
{
@@ -382,10 +367,10 @@ hicn_pcs_delete_internal (hicn_pit_cs_t * pitcs,
* 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, dpo_id_t * inface_id, u8 is_appface)
+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)
{
/*
@@ -401,25 +386,14 @@ hicn_pit_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
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;
+ 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;
- if (is_appface)
- {
- dpo_id_t *face_dpo = (dpo_id_t *) & (pcs_entry->u.cs.cs_rxface);
- hicn_face_t *face = hicn_dpoi_get_from_idx (face_dpo->dpoi_index);
- hicn_face_prod_t *prod_face = (hicn_face_prod_t *) face->data;
- policy_state = &prod_face->policy;
- policy_vft = &prod_face->policy_vft;
- }
- else
- {
- policy_state = &pitcs->policy_state;
- policy_vft = &pitcs->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++;
@@ -429,9 +403,8 @@ hicn_pit_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
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);
-
+ 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
@@ -449,49 +422,25 @@ hicn_pit_to_cs (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
/* 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_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;
- dpo_id_t *face_dpo = (dpo_id_t *) & (old_entry->u.cs.cs_rxface);
policy_state = &pitcs->policy_state;
policy_vft = &pitcs->policy_vft;
- if (face_dpo->dpoi_type == hicn_face_ip_type)
- {
- hicn_face_t *face = hicn_dpoi_get_from_idx (face_dpo->dpoi_index);
- if (face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD)
- {
- hicn_face_prod_t *prod_face = (hicn_face_prod_t *) face->data;
- policy_state = &prod_face->policy;
- policy_vft = &prod_face->policy_vft;
- }
- }
-
- if (dpo_cmp (&entry->u.cs.cs_rxface, &old_entry->u.cs.cs_rxface) != 0)
+ 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);
- dpo_copy (&old_entry->u.cs.cs_rxface, &entry->u.cs.cs_rxface);
- face_dpo = (dpo_id_t *) & (old_entry->u.cs.cs_rxface);
+ old_entry->u.cs.cs_rxface = entry->u.cs.cs_rxface;
policy_state = &pitcs->policy_state;
policy_vft = &pitcs->policy_vft;
- if (face_dpo->dpoi_type == hicn_face_ip_type)
- {
- hicn_face_t *face = hicn_dpoi_get_from_idx (face_dpo->dpoi_index);
- if (face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD)
- {
- hicn_face_prod_t *prod_face = (hicn_face_prod_t *) face->data;
- policy_state = &prod_face->policy;
- policy_vft = &prod_face->policy_vft;
- }
- }
-
policy_vft->hicn_cs_insert (pitcs, node, old_entry, policy_state);
if (policy_state->count > policy_state->max)
@@ -499,8 +448,8 @@ hicn_pcs_cs_update (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
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);
+ 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
@@ -520,30 +469,19 @@ hicn_pcs_cs_update (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
}
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)
+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;
- dpo_id_t *face_dpo = (dpo_id_t *) & ((*pcs_entryp)->u.cs.cs_rxface);
policy_state = &pitcs->policy_state;
policy_vft = &pitcs->policy_vft;
- if (face_dpo->dpoi_type == hicn_face_ip_type)
- {
- hicn_face_t *face = hicn_dpoi_get_from_idx (face_dpo->dpoi_index);
- if (face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD)
- {
- hicn_face_prod_t *prod_face = (hicn_face_prod_t *) face->data;
- policy_state = &prod_face->policy;
- policy_vft = &prod_face->policy_vft;
- }
- }
policy_vft->hicn_cs_dequeue (pitcs, (*nodep), (*pcs_entryp),
policy_state);
@@ -551,12 +489,13 @@ hicn_pcs_cs_delete (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
pitcs->pcs_cs_count--;
}
- /* A data could have been inserted in the CS through a push. In this case locks == 0 */
+ /* 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);
+ hicn_pcs_delete_internal (pitcs, pcs_entryp, hash_entry, nodep, vm,
+ dpo_vft, hicn_dpo_id);
}
else
{
@@ -565,19 +504,17 @@ hicn_pcs_cs_delete (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
}
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)
+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);
+ 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))
{
@@ -589,20 +526,9 @@ hicn_pcs_cs_insert (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
hicn_cs_policy_t *policy_state;
hicn_cs_policy_vft_t *policy_vft;
- dpo_id_t *face_dpo = (dpo_id_t *) & (entry->u.cs.cs_rxface);
policy_state = &pitcs->policy_state;
policy_vft = &pitcs->policy_vft;
- if (face_dpo->dpoi_type == hicn_face_ip_type)
- {
- hicn_face_t *face = hicn_dpoi_get_from_idx (face_dpo->dpoi_index);
- if (face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD)
- {
- hicn_face_prod_t *prod_face = (hicn_face_prod_t *) face->data;
- policy_state = &prod_face->policy;
- policy_vft = &prod_face->policy_vft;
- }
- }
policy_vft->hicn_cs_insert (pitcs, node, entry, policy_state);
pitcs->pcs_cs_count++;
@@ -611,8 +537,8 @@ hicn_pcs_cs_insert (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
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);
+ 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
@@ -634,22 +560,21 @@ hicn_pcs_cs_insert (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
* 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, dpo_id_t * inface)
+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);
+ 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)
@@ -678,18 +603,17 @@ hicn_pcs_cs_insert_update (vlib_main_t * vm, hicn_pit_cs_t * pitcs,
* 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)
+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);
+ 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++;
@@ -698,17 +622,17 @@ hicn_pcs_pit_insert (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t * entry,
}
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)
+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);
+ hicn_pcs_delete_internal (pitcs, pcs_entryp, hash_entry, node, vm,
+ dpo_vft, hicn_dpo_id);
}
else
{
@@ -716,7 +640,6 @@ hicn_pcs_pit_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp,
}
}
-
/* Generic functions for PIT/CS */
/*
@@ -724,42 +647,39 @@ hicn_pcs_pit_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp,
* 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)
+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);
+ 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);
+ 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)
+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
@@ -767,13 +687,13 @@ hicn_pcs_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp,
*/
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);
+ 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);
+ hicn_pcs_pit_delete (pitcs, pcs_entryp, nodep, vm, hash_entry, dpo_vft,
+ hicn_dpo_id);
}
}
@@ -782,17 +702,17 @@ hicn_pcs_delete (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp,
* 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)
+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))
+ 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);
+ hicn_pcs_delete_internal (pitcs, pcs_entryp, hash_entry, node, vm,
+ dpo_vft, hicn_dpo_id);
}
}
@@ -800,20 +720,21 @@ hicn_pcs_remove_lock (hicn_pit_cs_t * pitcs, hicn_pcs_entry_t ** pcs_entryp,
* 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)
+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 };
+ dpo_id_t hicn_dpo_id = { .dpoi_type = dpo_vft->hicn_dpo_get_type (),
+ .dpoi_proto = 0,
+ .dpoi_next_node = 0,
+ .dpoi_index = hash_entry->dpo_ctx_id };
- hicn_pcs_delete_internal
- (pitcs, pcs_entryp, hash_entry, node, vm, dpo_vft, &hicn_dpo_id);
+ hicn_pcs_delete_internal (pitcs, pcs_entryp, hash_entry, node, vm,
+ dpo_vft, &hicn_dpo_id);
}
else
{
@@ -866,16 +787,15 @@ 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 */
+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
+// convert time in msec to time in clicks
always_inline u16
hicn_infra_ms2clicks (u64 time_ms, u64 ms_per_click)
{
diff --git a/hicn-plugin/src/pg.c b/hicn-plugin/src/pg.c
index 9938e85ba..972bedc59 100644
--- a/hicn-plugin/src/pg.c
+++ b/hicn-plugin/src/pg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -29,22 +29,22 @@ 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")
+#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,
+#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,
+#define _(sym, string) string,
foreach_hicnpg_error
#undef _
};
@@ -70,15 +70,13 @@ typedef struct
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_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,
@@ -86,47 +84,47 @@ hicnpg_server_main_t hicnpg_server_main = {
/* packet trace format function */
static u8 *
-format_hicnpg_trace (u8 * s, va_list * args)
+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);
+ (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_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 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_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 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_v4 (vlib_main_t *vm,
+ vlib_buffer_t *b0);
-always_inline void
-calculate_tcp_checksum_v6 (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)
+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;
@@ -194,8 +192,8 @@ hicnpg_client_interest_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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)
+ if (hicn_interest_parse_pkt (b0, &name0, &namelen0, &hicn0,
+ &isv6_0) == HICN_ERROR_NONE)
{
/* this node grabs only interests */
@@ -204,29 +202,24 @@ hicnpg_client_interest_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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);
+ 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;
+ 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)
+ if (hicn_interest_parse_pkt (b1, &name1, &namelen1, &hicn1,
+ &isv6_1) == HICN_ERROR_NONE)
{
/* this node grabs only interests */
@@ -235,26 +228,21 @@ hicnpg_client_interest_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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);
+ 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;
+ 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;
@@ -295,9 +283,9 @@ hicnpg_client_interest_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
* 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);
+ 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)
@@ -320,8 +308,8 @@ hicnpg_client_interest_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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)
+ if (hicn_interest_parse_pkt (b0, &name0, &namelen0, &hicn0,
+ &isv6_0) == HICN_ERROR_NONE)
{
/* this node grabs only interests */
@@ -331,32 +319,27 @@ hicnpg_client_interest_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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);
+ 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;
+ 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)))
+ 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;
@@ -374,9 +357,8 @@ hicnpg_client_interest_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
* 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_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);
@@ -394,7 +376,7 @@ hicnpg_client_interest_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
}
void
-hicn_rewrite_interestv4 (vlib_main_t * vm, vlib_buffer_t * b0, u32 seq_number,
+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);
@@ -440,7 +422,7 @@ hicn_rewrite_interestv4 (vlib_main_t * vm, vlib_buffer_t * b0, u32 seq_number,
* Destination is used to iterate on the content.
*/
void
-hicn_rewrite_interestv6 (vlib_main_t * vm, vlib_buffer_t * b0, u32 seq_number,
+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);
@@ -468,10 +450,8 @@ hicn_rewrite_interestv6 (vlib_main_t * vm, vlib_buffer_t * b0, u32 seq_number,
calculate_tcp_checksum_v6 (vm, b0);
}
-
-
void
-calculate_tcp_checksum_v4 (vlib_main_t * vm, vlib_buffer_t * b0)
+calculate_tcp_checksum_v4 (vlib_main_t *vm, vlib_buffer_t *b0)
{
ip4_header_t *ip0;
tcp_header_t *tcp0;
@@ -488,14 +468,13 @@ calculate_tcp_checksum_v4 (vlib_main_t * vm, vlib_buffer_t * b0)
{
sum0 = clib_mem_unaligned (&ip0->src_address, u32);
sum0 =
- ip_csum_with_carry (sum0,
- clib_mem_unaligned (&ip0->dst_address, u32));
+ 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)));
+ sum0 = ip_csum_with_carry (
+ sum0, clib_host_to_net_u32 (tcp_len0 + (ip0->protocol << 16)));
/* Invalidate possibly old checksum. */
tcp0->checksum = 0;
@@ -507,7 +486,7 @@ calculate_tcp_checksum_v4 (vlib_main_t * vm, vlib_buffer_t * b0)
}
void
-calculate_tcp_checksum_v6 (vlib_main_t * vm, vlib_buffer_t * b0)
+calculate_tcp_checksum_v6 (vlib_main_t *vm, vlib_buffer_t *b0)
{
ip6_header_t *ip0;
tcp_header_t *tcp0;
@@ -524,14 +503,13 @@ calculate_tcp_checksum_v6 (vlib_main_t * vm, vlib_buffer_t * b0)
{
sum0 = clib_mem_unaligned (&ip0->src_address, u32);
sum0 =
- ip_csum_with_carry (sum0,
- clib_mem_unaligned (&ip0->dst_address, u32));
+ 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)));
+ sum0 = ip_csum_with_carry (
+ sum0, clib_host_to_net_u32 (tcp_len0 + (ip0->protocol << 16)));
/* Invalidate possibly old checksum. */
tcp0->checksum = 0;
@@ -542,24 +520,19 @@ calculate_tcp_checksum_v6 (vlib_main_t * vm, vlib_buffer_t * b0)
tcp0->checksum = ~ip_csum_fold (sum0);
}
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE(hicn_pg_interest_node) ={
+VLIB_REGISTER_NODE (hicn_pg_interest_node) = {
.function = hicnpg_client_interest_node_fn,
.name = "hicnpg-interest",
- .vector_size = sizeof(u32),
+ .vector_size = sizeof (u32),
.format_trace = format_hicnpg_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(hicnpg_error_strings),
+ .n_errors = ARRAY_LEN (hicnpg_error_strings),
.error_strings = hicnpg_error_strings,
.n_next_nodes = HICNPG_N_NEXT,
- .next_nodes =
- {
- [HICNPG_INTEREST_NEXT_V4_LOOKUP] = "ip4-lookup",
- [HICNPG_INTEREST_NEXT_V6_LOOKUP] = "ip6-lookup",
- [HICNPG_INTEREST_NEXT_DROP] = "error-drop"
- },
+ .next_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
@@ -584,21 +557,20 @@ typedef struct
/* packet trace format function */
static u8 *
-format_hicnpg_data_trace (u8 * s, va_list * args)
+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);
+ (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)
+match_ip4_name (u32 *name, fib_prefix_t *prefix)
{
u32 xor = 0;
@@ -608,7 +580,7 @@ match_ip4_name (u32 * name, fib_prefix_t * prefix)
}
static_always_inline int
-match_ip6_name (u8 * name, fib_prefix_t * prefix)
+match_ip6_name (u8 *name, fib_prefix_t *prefix)
{
union
{
@@ -621,10 +593,9 @@ match_ip6_name (u8 * name, fib_prefix_t * prefix)
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]);
+ (xor_sum.as_u64[1] == prefix->fp_addr.ip6.as_u64[1]);
}
-
/*
* Return 0,1,2.
* 0 matches
@@ -632,7 +603,7 @@ match_ip6_name (u8 * name, fib_prefix_t * prefix)
* 2 does not match and the prefix is ip6
*/
static_always_inline u32
-match_data (vlib_buffer_t * b, fib_prefix_t * prefix)
+match_data (vlib_buffer_t *b, fib_prefix_t *prefix)
{
u8 *ptr = vlib_buffer_get_current (b);
u8 v = *ptr & 0xf0;
@@ -640,11 +611,10 @@ match_data (vlib_buffer_t * b, fib_prefix_t * prefix)
if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr)))
{
- if (!match_ip4_name ((u32 *) & (ptr[12]), prefix))
+ if (!match_ip4_name ((u32 *) &(ptr[12]), prefix))
next = 1;
}
- else
- if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr)))
+ else if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr)))
{
if (!match_ip6_name (&(ptr[8]), prefix))
next = 2;
@@ -660,7 +630,7 @@ match_data (vlib_buffer_t * b, fib_prefix_t * prefix)
* 2 does not match and the prefix is ip6
*/
static_always_inline u32
-match_interest (vlib_buffer_t * b, fib_prefix_t * prefix)
+match_interest (vlib_buffer_t *b, fib_prefix_t *prefix)
{
u8 *ptr = vlib_buffer_get_current (b);
u8 v = *ptr & 0xf0;
@@ -668,11 +638,10 @@ match_interest (vlib_buffer_t * b, fib_prefix_t * prefix)
if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr)))
{
- if (!match_ip4_name ((u32 *) & (ptr[16]), prefix))
+ if (!match_ip4_name ((u32 *) &(ptr[16]), prefix))
next = 1;
}
- else
- if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr)))
+ else if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr)))
{
if (!match_ip6_name (&(ptr[24]), prefix))
next = 2;
@@ -681,17 +650,14 @@ match_interest (vlib_buffer_t * b, fib_prefix_t * prefix)
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)
+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;
@@ -754,17 +720,16 @@ hicnpg_client_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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))
+ 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))
+ 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 */
@@ -799,9 +764,9 @@ hicnpg_client_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
}
}
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
- to_next, n_left_to_next,
- bi0, bi1, next0, next1);
+ vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, bi1, next0,
+ next1);
pkts_processed += 2;
}
@@ -825,9 +790,9 @@ hicnpg_client_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
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))
+ 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)
@@ -836,8 +801,8 @@ hicnpg_client_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
content_msgs_received++;
}
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ 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));
@@ -863,7 +828,6 @@ hicnpg_client_data_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
return (frame->n_vectors);
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE(hicn_pg_data_node) =
{
.function = hicnpg_client_data_node_fn,
@@ -881,27 +845,18 @@ VLIB_REGISTER_NODE(hicn_pg_data_node) =
[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* */
+VNET_FEATURE_INIT (hicn_data_input_ip4_arc, static) = {
+ .arc_name = "ip4-unicast",
+ .node_name = "hicnpg-data",
+ .runs_before = VNET_FEATURES ("ip4-inacl"),
+};
+VNET_FEATURE_INIT (hicn_data_input_ip6_arc, static) = {
+ .arc_name = "ip6-unicast",
+ .node_name = "hicnpg-data",
+ .runs_before = VNET_FEATURES ("ip6-inacl"),
+};
/*
* End of packet-generator client node
@@ -915,20 +870,20 @@ VNET_FEATURE_INIT(hicn_data_input_ip6_arc, static)=
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")
+#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,
+#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,
+#define _(sym, string) string,
foreach_icnpg_server_error
#undef _
};
@@ -956,17 +911,15 @@ typedef struct
/* packet trace format function */
static u8 *
-format_icnpg_server_trace (u8 * s, va_list * args)
+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);
+ 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);
}
@@ -974,8 +927,8 @@ format_icnpg_server_trace (u8 * s, va_list * args)
* 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)
+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;
@@ -1001,7 +954,6 @@ hicnpg_node_server_fn (vlib_main_t * vm,
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;
@@ -1051,42 +1003,36 @@ hicnpg_node_server_fn (vlib_main_t * vm,
{
next0 = match0 - 1;
}
- else
- if (hicn_interest_parse_pkt
- (b0, &name0, &namelen0, &hicn0, &isv6_0) == HICN_ERROR_NONE)
+ 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);
+ 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;
+ 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)
+ 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);
+ 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;
+ next1 = isv6_1 ? HICNPG_SERVER_NEXT_V6_LOOKUP :
+ HICNPG_SERVER_NEXT_V4_LOOKUP;
}
pkts_processed += 2;
@@ -1123,9 +1069,9 @@ hicnpg_node_server_fn (vlib_main_t * vm,
* 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);
+ 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)
@@ -1153,24 +1099,21 @@ hicnpg_node_server_fn (vlib_main_t * vm,
{
next0 = match0 - 1;
}
- else
- if (hicn_interest_parse_pkt
- (b0, &name0, &namelen0, &hicn0, &isv6_0) == HICN_ERROR_NONE)
+ 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);
+ 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;
+ 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)))
+ 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));
@@ -1189,9 +1132,8 @@ hicnpg_node_server_fn (vlib_main_t * vm,
* 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_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);
@@ -1206,8 +1148,8 @@ hicnpg_node_server_fn (vlib_main_t * vm,
}
void
-convert_interest_to_data_v4 (vlib_main_t * vm, vlib_buffer_t * b0,
- vlib_buffer_t * rb, u32 bi0)
+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);
@@ -1234,13 +1176,13 @@ convert_interest_to_data_v4 (vlib_main_t * vm, vlib_buffer_t * b0,
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));
+ 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)
+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);
@@ -1268,15 +1210,14 @@ convert_interest_to_data_v6 (vlib_main_t * vm, vlib_buffer_t * b0,
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.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,
@@ -1295,25 +1236,18 @@ VLIB_REGISTER_NODE(hicn_pg_server_node) =
[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* */
+VNET_FEATURE_INIT (hicn_pg_server_ip6, static) = {
+ .arc_name = "ip6-unicast",
+ .node_name = "hicnpg-server",
+ .runs_before = VNET_FEATURES ("ip6-inacl"),
+};
-/* *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* */
+VNET_FEATURE_INIT (hicn_pg_server_ip4, static) = {
+ .arc_name = "ip4-unicast",
+ .node_name = "hicnpg-server",
+ .runs_before = VNET_FEATURES ("ip4-inacl"),
+};
/*
* End of packet-generator server node
diff --git a/hicn-plugin/src/pg.h b/hicn-plugin/src/pg.h
index 9ec3eeabc..84a391d43 100644
--- a/hicn-plugin/src/pg.h
+++ b/hicn-plugin/src/pg.h
@@ -18,7 +18,7 @@
/**
- * @File Packet generator for hICN
+ * @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
diff --git a/hicn-plugin/src/route.c b/hicn-plugin/src/route.c
index c208dd4c1..6db52f2fd 100644
--- a/hicn-plugin/src/route.c
+++ b/hicn-plugin/src/route.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -15,9 +15,14 @@
#include <vnet/fib/fib_entry.h>
#include <vnet/fib/fib_table.h>
+#include <vnet/fib/fib_entry_track.h>
#include <vnet/ip/ip6_packet.h>
+#include <vnet/ip/ip.h>
#include <vnet/dpo/dpo.h>
+#include <vnet/dpo/drop_dpo.h>
#include <vnet/dpo/load_balance.h>
+#include <vnet/udp/udp.h>
+#include <vnet/udp/udp_encap.h>
#include <vlib/global_funcs.h>
#include "strategy_dpo_ctx.h"
@@ -26,11 +31,18 @@
#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)
@@ -91,134 +103,326 @@ hicn_route_get_dpo (const fib_prefix_t * prefix,
}
int
-hicn_route_add_nhops (hicn_face_id_t * face_id, u32 len,
- const fib_prefix_t * prefix)
+hicn_route_set_strategy (fib_prefix_t * prefix, u8 strategy_id)
{
const dpo_id_t *hicn_dpo_id;
- int ret = HICN_ERROR_NONE;
- dpo_id_t faces_dpo_tmp[HICN_PARAM_FIB_ENTRY_NHOPS_MAX];
- int n_face_dpo = 0;
- const hicn_dpo_vft_t *dpo_vft;
+ 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;
- vlib_main_t *vm = vlib_get_main ();
- hicn_face_vft_t *face_vft = NULL;
- if (face_id == NULL)
+ ret = hicn_route_get_dpo (prefix, &hicn_dpo_id, &fib_index);
+
+ if (ret == HICN_ERROR_NONE)
{
- return HICN_ERROR_ROUTE_INVAL;
+ 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;
}
- /*
- * Check is the faces are available, otherwise skip the face
- * id_adjacency existance is not checked. It should be checked before
- * sending a packet out
- */
- for (int i = 0; i < clib_min (HICN_PARAM_FIB_ENTRY_NHOPS_MAX, len); i++)
+ //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)
{
- hicn_face_t *face = hicn_dpoi_get_from_idx (face_id[i]);
- face_vft = hicn_face_get_vft (face->shared.face_type);
- dpo_id_t face_dpo = DPO_INVALID;
- face_vft->hicn_face_get_dpo (face, &face_dpo);
+ 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);
+ }
- if (!dpo_id_is_valid (&face_dpo))
- {
- vlib_cli_output (vm, "Face %d not found, skip...\n", face_id[i]);
- return ret;
- }
+ 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;
+
+#define ADD_FACE(nh) \
+ do { \
+ /* 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); \
+ } while (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);
+ ADD_FACE(nh);
+ }
+ 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;
+ ip46_address_t _nh = {0};
+ nh = &_nh;
+ switch (dpo->dpoi_proto)
+ {
+ case FIB_PROTOCOL_IP6:
+ case FIB_PROTOCOL_IP4:
+ /**
+ * Independently of the type of tunnel, encapsulated packet
+ * can be either v6 or v4, so we need to create 2 faces for each
+ * version. Tunneled hicn packet MUST have locator set to the loopback
+ * address, so ::1 for IPv6 and 127.0.0.1 for IPv4.
+ */
+ ip46_address_set_ip6(nh, &localhost6);
+ ADD_FACE(nh);
+ ip46_address_set_ip4(nh, &localhost4);
+ ADD_FACE(nh);
+ break;
+ default:
+ continue;
+ }
+ udp_tunnel_add_existing (dpo->dpoi_index, proto);
+ }
+ }
+
+ 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
- {
- faces_dpo_tmp[n_face_dpo++] = face_dpo;
- }
- }
+ {
+ vec_del1(vec_faces, idx_nh);
- ret = hicn_route_get_dpo (prefix, &hicn_dpo_id, &fib_index);
+ /* Remove the lock added by hicn_face_add */
+ hicn_face_unlock_with_id (fib_entry->next_hops[i]);
+ i++;
+ }
+ }
- if (ret == HICN_ERROR_NONE)
+ hicn_face_id_t *face_id;
+ vec_foreach(face_id, vec_faces)
{
- for (int i = 0; i < n_face_dpo && (ret == HICN_ERROR_NONE); i++)
- {
- u32 vft_id = hicn_dpo_get_vft_id (hicn_dpo_id);
- dpo_vft = hicn_dpo_get_vft (vft_id);
-
- hicn_face_t *face =
- hicn_dpoi_get_from_idx (faces_dpo_tmp[i].dpoi_index);
- //Disable feature on the interface
- if (prefix->fp_proto == FIB_PROTOCOL_IP4)
- vnet_feature_enable_disable ("ip4-local", "hicn-data-input-ip4",
- face->shared.sw_if, 1, 0, 0);
- else if (prefix->fp_proto == FIB_PROTOCOL_IP6)
- vnet_feature_enable_disable ("ip6-local", "hicn-data-input-ip6",
- face->shared.sw_if, 1, 0, 0);
-
- ret = dpo_vft->hicn_dpo_add_update_nh (&faces_dpo_tmp[i],
- hicn_dpo_id->dpoi_index);
- }
+ 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);
+
}
- return ret;
+ vec_free(vec_faces);
}
-/* Add a new route for a name prefix */
-int
-hicn_route_add (hicn_face_id_t * face_id, u32 len,
- const fib_prefix_t * prefix)
+static void
+enable_disable_data_receiving (fib_protocol_t proto, u32 sw_if, u8 is_enable)
{
- dpo_id_t dpo = DPO_INVALID;
- const dpo_id_t *hicn_dpo_id;
- int ret = HICN_ERROR_NONE;
- dpo_id_t face_dpo_tmp[HICN_PARAM_FIB_ENTRY_NHOPS_MAX];
- int n_face_dpo = 0;
- index_t dpo_idx;
- u32 fib_index;
- vlib_main_t *vm = vlib_get_main ();
- hicn_face_vft_t *face_vft = NULL;
+ 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);
- if (face_id == NULL || !hicn_dpoi_idx_is_valid (*face_id))
- {
- return HICN_ERROR_ROUTE_INVAL;
+}
+
+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 */
/*
- * Check is the faces are available, otherwise skip the face
- * id_adjacency existance is not checked. It should be checked before
- * sending a packet out
+ * ASSUMPTION: we use table 0 which is the default table and it is
+ * already existing and locked
*/
- for (int i = 0; i < clib_min (HICN_PARAM_FIB_ENTRY_NHOPS_MAX, len); i++)
+ 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)
{
- hicn_face_t *face = hicn_dpoi_get_from_idx (face_id[i]);
- face_vft = hicn_face_get_vft (face->shared.face_type);
- dpo_id_t face_dpo = DPO_INVALID;
- face_vft->hicn_face_get_dpo (face, &face_dpo);
+ fib_entry_index = fib_table_lookup (fib_index, prefix);
- if (!dpo_id_is_valid (&face_dpo))
- {
- vlib_cli_output (vm, "Face %d not found, skip...\n", face_id[i]);
- return ret;
- }
- else
- {
- face_dpo_tmp[n_face_dpo++] = face_dpo;
- }
+ 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);
}
- ret = hicn_route_get_dpo (prefix, &hicn_dpo_id, &fib_index);
+ /* Check if the prefix is already enabled */
+ u32 fib_hicn_index = fib_table_find(prefix->fp_proto, HICN_FIB_TABLE);
- if (ret == HICN_ERROR_ROUTE_NOT_FOUND)
- {
- dpo_id_t nhops[HICN_PARAM_FIB_ENTRY_NHOPS_MAX];
- for (int i = 0; i < n_face_dpo; i++)
- {
- clib_memcpy (&nhops[i], &face_dpo_tmp[i], sizeof (dpo_id_t));
- hicn_face_t *face =
- hicn_dpoi_get_from_idx (face_dpo_tmp[i].dpoi_index);
- //Disable feature on the interface
- if (prefix->fp_proto == FIB_PROTOCOL_IP4)
- vnet_feature_enable_disable ("ip4-local", "hicn-data-input-ip4",
- face->shared.sw_if, 1, 0, 0);
- else if (prefix->fp_proto == FIB_PROTOCOL_IP6)
- vnet_feature_enable_disable ("ip6-local", "hicn-data-input-ip6",
- face->shared.sw_if, 1, 0, 0);
- }
+ fib_node_index_t fib_hicn_entry_index = fib_table_lookup_exact_match (fib_hicn_index, prefix);
- default_dpo.hicn_dpo_create (prefix->fp_proto, nhops, n_face_dpo,
- &dpo_idx);
+ 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 */
/*
@@ -226,9 +430,20 @@ hicn_route_add (hicn_face_id_t * face_id, u32 len,
* 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);
+ 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 */
/*
@@ -236,163 +451,310 @@ hicn_route_add (hicn_face_id_t * face_id, u32 len,
* 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_fib_src,
- (FIB_ENTRY_FLAG_EXCLUSIVE |
- FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT),
- &dpo);
+ 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);
- dpo_unlock (&dpo);
- ret =
- (new_fib_node_index !=
- FIB_NODE_INDEX_INVALID) ? HICN_ERROR_NONE :
- HICN_ERROR_ROUTE_NO_INSERT;
-
- /*
- * TODO: we might want to store the fib index in the face.
- * This will help to update the fib entries when a face is
- * deleted. Fib_index_t is returned from
- * fib_table_entry_special_dpo_add.
+ /* 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 if (ret == HICN_ERROR_NONE)
+ else
{
- ret = hicn_route_add_nhops (face_id, len, prefix);
+ 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_del (fib_prefix_t * prefix)
-{
- const dpo_id_t *hicn_dpo_id;
+hicn_route_disable (fib_prefix_t *prefix) {
+
int ret = HICN_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);
+ /* Check if the prefix is already enabled */
+ u32 fib_hicn_index = fib_table_find(prefix->fp_proto, HICN_FIB_TABLE);
- if (ret == HICN_ERROR_NONE)
+ 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
{
- fib_table_entry_special_remove (HICN_FIB_TABLE, prefix, hicn_fib_src);
+ const dpo_id_t *load_balance_dpo_id;
+ const dpo_id_t *strategy_dpo_id;
+ hicn_dpo_ctx_t * hicn_fib_entry;
- /*
- * Remove the lock from the table. We keep one lock per route
- */
- fib_table_unlock (fib_index, prefix->fp_proto, hicn_fib_src);
+ /* 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));
}
- //Remember to remove the lock from the table when removing the entry
+
+ done:
return ret;
}
-int
-hicn_route_del_nhop (fib_prefix_t * prefix, hicn_face_id_t face_id)
+
+static fib_node_t *
+hicn_ctx_node_get (fib_node_index_t index)
{
- const dpo_id_t *hicn_dpo_id;
- int ret;
- u32 vft_id;
- const hicn_dpo_vft_t *dpo_vft;
- u32 fib_index;
+ hicn_dpo_ctx_t * hicn_ctx;
+ hicn_ctx = hicn_strategy_dpo_ctx_get(index);
- ret = hicn_route_get_dpo (prefix, &hicn_dpo_id, &fib_index);
+ return (&hicn_ctx->fib_node);
+}
- /* Check if the dpo is an hicn_dpo_t */
- if (ret == HICN_ERROR_NONE)
- {
- vft_id = hicn_dpo_get_vft_id (hicn_dpo_id);
- dpo_vft = hicn_dpo_get_vft (vft_id);
+static void
+hicn_fib_last_lock_gone (fib_node_t *node)
+{
+}
- hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
- //Disable feature on the interface
- if (prefix->fp_proto == FIB_PROTOCOL_IP4)
- vnet_feature_enable_disable ("ip4-local", "hicn-data-input-ip4",
- face->shared.sw_if, 0, 0, 0);
- else if (prefix->fp_proto == FIB_PROTOCOL_IP6)
- vnet_feature_enable_disable ("ip6-local", "hicn-data-input-ip6",
- face->shared.sw_if, 0, 0, 0);
+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)));
+}
- ret = dpo_vft->hicn_dpo_del_nh (face_id, hicn_dpo_id->dpoi_index);
+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 *dpo_ctx =
- hicn_strategy_dpo_ctx_get (hicn_dpo_id->dpoi_index);
+ hicn_dpo_ctx_t *fib_entry = hicn_ctx_from_fib_node (node);
+ sync_hicn_fib_entry(fib_entry);
- if (ret == HICN_ERROR_NONE && !dpo_ctx->entry_count)
- ret = hicn_route_del (prefix);
- }
- //Remember to remove the lock from the table when removing the entry
- return ret;
+ return (FIB_NODE_BACK_WALK_CONTINUE);
}
-int
-hicn_route_set_strategy (fib_prefix_t * prefix, u8 strategy_id)
+static void
+hicn_fib_show_memory (void)
{
- 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)
+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)
{
- old_hicn_dpo_ctx = hicn_strategy_dpo_ctx_get (hicn_dpo_id->dpoi_index);
+ goto done;
+ }
+ else
+ {
+ load_balance_t *lb =
+ load_balance_get (load_balance_dpo_id->dpoi_index);
- new_dpo_vft = hicn_dpo_get_vft_from_id (strategy_id);
+ strategy_dpo_id = load_balance_get_bucket_i (lb, 0);
- if (new_dpo_vft == NULL || old_hicn_dpo_ctx == NULL)
- return HICN_ERROR_STRATEGY_NOT_FOUND;
+ if (!dpo_is_hicn (strategy_dpo_id))
+ {
+ goto done;
+ }
- /* 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);
+ enable_disable_data_receiving (strategy_dpo_id->dpoi_proto, sw_if, 1);
+ }
- /* 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);
+ done:
+ return (FIB_TABLE_WALK_CONTINUE);
+}
- /* Here is where we create the "via" like route */
+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;
+
+ 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)
+ {
/*
- * 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…
+ * 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_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);
+ fib_table_walk(fib_index,
+ FIB_PROTOCOL_IP4,
+ enable_data_on_existing_hicn,
+ &sw_if_index);
+ }
- dpo_unlock (&new_dpo_id);
- ret =
- (new_fib_node_index !=
- FIB_NODE_INDEX_INVALID) ? HICN_ERROR_NONE :
- HICN_ERROR_ROUTE_NOT_UPDATED;
+ 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);
}
- //Remember to remove the lock from the table when removing the entry
- return ret;
+ 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);
}
/*
diff --git a/hicn-plugin/src/route.h b/hicn-plugin/src/route.h
index 5877f31a8..a1ba86b3d 100644
--- a/hicn-plugin/src/route.h
+++ b/hicn-plugin/src/route.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -21,36 +21,102 @@
#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.
+ */
+
/*
- * Retrieve the hicn dpo corresponding to a hicn prefix
+ * 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);
-/*
- * Add a new route for a name prefix
+
+/**
+ * @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_add (hicn_face_id_t * face_id, u32 len,
- const fib_prefix_t * prefix);
+hicn_route_set_strategy (fib_prefix_t * prefix, u32 strategy_id);
-/*
- * Add new next hops for a prefix route
+/**
+ * @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
-hicn_route_add_nhops (hicn_face_id_t * face_id, u32 len,
- const fib_prefix_t * prefix);
+ip_nh_add_helper (fib_protocol_t fib_proto, const fib_prefix_t * pfx, ip46_address_t * nh, u32 sw_if);
-/* Remove a route for a name prefix */
-int hicn_route_del (fib_prefix_t * prefix);
+/**
+ * @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);
-/* Remove a next hop route for a name prefix */
-int hicn_route_del_nhop (fib_prefix_t * prefix, u32 face_id);
+/**
+ * @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);
-/* Remove a next hop route for a name 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_set_strategy (fib_prefix_t * prefix, u32 strategy_id);
+hicn_route_disable (fib_prefix_t *prefix);
+
/* Init route internal strustures */
void
diff --git a/hicn-plugin/src/state.h b/hicn-plugin/src/state.h
index 7e984e6c3..37003d0ae 100644
--- a/hicn-plugin/src/state.h
+++ b/hicn-plugin/src/state.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -26,26 +26,26 @@
#include "strategy_dpo_ctx.h"
#include "strategy_dpo_manager.h"
-always_inline void
-hicn_prefetch_pcs_entry (hicn_buffer_t * hicnb, hicn_pit_cs_t * pitcs)
-{
- hicn_hash_node_t *node = pool_elt_at_index (pitcs->pcs_table->ht_nodes,
- hicnb->node_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);
+/**
+ * @file plugin_state
+ *
+ * Helper functions to hicn state (hash node, hash entry, strategy vft, dpo vft and dpo context id)
+ *
+ */
- CLIB_PREFETCH (node, CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (bucket, CLIB_CACHE_LINE_BYTES, STORE);
-}
+//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,
@@ -77,6 +77,19 @@ hicn_get_internal_state (hicn_buffer_t * hicnb, hicn_pit_cs_t * pitcs,
* 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,
diff --git a/hicn-plugin/src/strategies/dpo_mw.c b/hicn-plugin/src/strategies/dpo_mw.c
index eebb572c4..12c77bce8 100644
--- a/hicn-plugin/src/strategies/dpo_mw.c
+++ b/hicn-plugin/src/strategies/dpo_mw.c
@@ -76,8 +76,6 @@ format_hicn_strategy_mw_ctx (u8 * s, va_list * ap)
index_t index = va_arg (*ap, index_t);
hicn_dpo_ctx_t *dpo_ctx = NULL;
hicn_strategy_mw_ctx_t *mw_dpo_ctx = NULL;
- dpo_id_t *next_hop = NULL;
- hicn_face_vft_t *face_vft = NULL;
u32 indent = va_arg (*ap, u32);;
dpo_ctx = hicn_strategy_dpo_ctx_get (index);
@@ -97,24 +95,20 @@ format_hicn_strategy_mw_ctx (u8 * s, va_list * ap)
buf = format (NULL, "TFIB");
else
continue;
- next_hop = &dpo_ctx->next_hops[i];
- face_vft = hicn_face_get_vft (next_hop->dpoi_type);
- if (face_vft != NULL)
- {
- s = format (s, "\n");
- s =
- format (s, "%U ", face_vft->format_face, next_hop->dpoi_index,
- indent);
- s = format (s, "weight %u", mw_dpo_ctx->weight[i]);
- s = format (s, " %s", buf);
- }
+
+ 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 (dpo_proto_t proto, const dpo_id_t * next_hop,
+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;
@@ -126,13 +120,13 @@ hicn_strategy_mw_ctx_create (dpo_proto_t proto, const dpo_id_t * next_hop,
*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);
+ 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 (const dpo_id_t * nh, index_t dpo_idx)
+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;
diff --git a/hicn-plugin/src/strategies/dpo_mw.h b/hicn-plugin/src/strategies/dpo_mw.h
index ccc8d044f..433c415fb 100644
--- a/hicn-plugin/src/strategies/dpo_mw.h
+++ b/hicn-plugin/src/strategies/dpo_mw.h
@@ -19,6 +19,14 @@
#include <vnet/dpo/dpo.h>
#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
@@ -60,7 +68,7 @@ hicn_dpo_ctx_t *hicn_strategy_mw_ctx_get (index_t index);
* @return HICN_ERROR_NONE if the creation was fine, otherwise EINVAL
*/
void
-hicn_strategy_mw_ctx_create (dpo_proto_t proto, const dpo_id_t * next_hop,
+hicn_strategy_mw_ctx_create (fib_protocol_t proto, const hicn_face_id_t * next_hop,
int nh_len, index_t * dpo_idx);
/**
@@ -75,7 +83,7 @@ hicn_strategy_mw_ctx_create (dpo_proto_t proto, const dpo_id_t * 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 (const dpo_id_t * nh, index_t dpo_idx);
+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.
diff --git a/hicn-plugin/src/strategies/dpo_rr.c b/hicn-plugin/src/strategies/dpo_rr.c
index a67b06acb..adb7e1025 100644
--- a/hicn-plugin/src/strategies/dpo_rr.c
+++ b/hicn-plugin/src/strategies/dpo_rr.c
@@ -76,8 +76,6 @@ format_hicn_strategy_rr_ctx (u8 * s, va_list * ap)
index_t index = va_arg (*ap, index_t);
hicn_dpo_ctx_t *dpo_ctx = NULL;
hicn_strategy_rr_ctx_t *rr_dpo_ctx = NULL;
- dpo_id_t *next_hop = NULL;
- hicn_face_vft_t *face_vft = NULL;
u32 indent = va_arg (*ap, u32);
dpo_ctx = hicn_strategy_dpo_ctx_get (index);
@@ -88,7 +86,7 @@ format_hicn_strategy_rr_ctx (u8 * s, va_list * ap)
s =
format (s, "hicn-rr, next hop Face %d",
- dpo_ctx->next_hops[rr_dpo_ctx->current_nhop].dpoi_index);
+ dpo_ctx->next_hops[rr_dpo_ctx->current_nhop]);
for (i = 0; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; i++)
{
@@ -101,23 +99,18 @@ format_hicn_strategy_rr_ctx (u8 * s, va_list * ap)
else
continue;
- next_hop = &dpo_ctx->next_hops[i];
- face_vft = hicn_face_get_vft (next_hop->dpoi_type);
- if (face_vft != NULL)
- {
- s = format (s, "\n");
- s =
- format (s, "%U ", face_vft->format_face, next_hop->dpoi_index,
- indent);
- s = format (s, " %s", buf);
- }
+ 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 (dpo_proto_t proto, const dpo_id_t * next_hop,
+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;
@@ -129,13 +122,13 @@ hicn_strategy_rr_ctx_create (dpo_proto_t proto, const dpo_id_t * next_hop,
*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);
+ 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 (const dpo_id_t * nh, index_t dpo_idx)
+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;
diff --git a/hicn-plugin/src/strategies/dpo_rr.h b/hicn-plugin/src/strategies/dpo_rr.h
index 8afd0dabc..e4e5b5372 100644
--- a/hicn-plugin/src/strategies/dpo_rr.h
+++ b/hicn-plugin/src/strategies/dpo_rr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,6 +20,15 @@
#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
*/
@@ -62,7 +71,7 @@ hicn_dpo_ctx_t *hicn_strategy_rr_ctx_get (index_t index);
* @return HICN_ERROR_NONE if the creation was fine, otherwise EINVAL
*/
void
-hicn_strategy_rr_ctx_create (dpo_proto_t proto, const dpo_id_t * next_hop,
+hicn_strategy_rr_ctx_create (fib_protocol_t proto, const hicn_face_id_t * next_hop,
int nh_len, index_t * dpo_idx);
/**
@@ -77,7 +86,7 @@ hicn_strategy_rr_ctx_create (dpo_proto_t proto, const dpo_id_t * 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 (const dpo_id_t * nh, index_t dpo_idx);
+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.
diff --git a/hicn-plugin/src/strategies/strategy_mw.c b/hicn-plugin/src/strategies/strategy_mw.c
index 2422d4fed..9409ec856 100644
--- a/hicn-plugin/src/strategies/strategy_mw.c
+++ b/hicn-plugin/src/strategies/strategy_mw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -22,14 +22,13 @@
/* 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_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,
- dpo_id_t ** outface);
+ 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);
-
+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,
@@ -49,9 +48,10 @@ 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*/
+/* 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, dpo_id_t ** outface)
+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);
@@ -64,30 +64,26 @@ hicn_select_next_hop_mw (index_t dpo_idx, int *nh_idx, dpo_id_t ** outface)
u8 next_hop_index = 0;
for (int i = 0; i < dpo_ctx->entry_count; i++)
{
- if (dpo_id_is_valid (&dpo_ctx->next_hops[i]))
+ if (hicn_strategy_mw_ctx->weight[next_hop_index] <
+ hicn_strategy_mw_ctx->weight[i])
{
- if (hicn_strategy_mw_ctx->weight[next_hop_index] <
- hicn_strategy_mw_ctx->weight[i])
- {
- next_hop_index = i;
- }
+ next_hop_index = i;
}
}
- if (!dpo_id_is_valid (&dpo_ctx->next_hops[next_hop_index]))
- return HICN_ERROR_STRATEGY_NH_NOT_FOUND;
-
- *outface = (dpo_id_t *) & dpo_ctx->next_hops[next_hop_index];
+ *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)
+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 };
+ dpo_id_t hicn_dpo_id = { .dpoi_type = hicn_dpo_strategy_mw_get_type (),
+ .dpoi_proto = 0,
+ .dpoi_next_node = 0,
+ .dpoi_index = dpo_ctx_idx };
hicn_strategy_dpo_ctx_lock (&hicn_dpo_id);
hash_entry->vft_id = hicn_dpo_get_vft_id (&hicn_dpo_id);
}
@@ -103,10 +99,9 @@ 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)
+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);
@@ -114,14 +109,14 @@ hicn_strategy_format_trace_mw (u8 * s, hicn_strategy_trace_t * t)
}
u8 *
-hicn_strategy_format_mw (u8 * s, va_list * ap)
+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);
+ 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);
}
diff --git a/hicn-plugin/src/strategies/strategy_mw.h b/hicn-plugin/src/strategies/strategy_mw.h
index f64f1fdc7..9e0078b23 100644
--- a/hicn-plugin/src/strategies/strategy_mw.h
+++ b/hicn-plugin/src/strategies/strategy_mw.h
@@ -19,6 +19,13 @@
#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);
diff --git a/hicn-plugin/src/strategies/strategy_mw_cli.c b/hicn-plugin/src/strategies/strategy_mw_cli.c
index 701f96fa7..473ff0e19 100644
--- a/hicn-plugin/src/strategies/strategy_mw_cli.c
+++ b/hicn-plugin/src/strategies/strategy_mw_cli.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -26,9 +26,9 @@
#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)
+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;
@@ -54,19 +54,17 @@ hicn_mw_strategy_cli_set_weight_command_fn (vlib_main_t * vm,
;
else
{
- return clib_error_return (0, "%s",
- get_error_string
- (HICN_ERROR_CLI_INVAL));
+ 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);
+ 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;
}
@@ -77,35 +75,31 @@ hicn_mw_strategy_cli_set_weight_command_fn (vlib_main_t * vm,
goto done;
}
- prefix.fp_proto =
- ip46_address_is_ip4 (&prefix.
- fp_addr) ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
+ 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 ())
+ 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;
+ 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].dpoi_index == (index_t) faceid)
+ 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));
+ cl_err = clib_error_return (
+ 0, get_error_string (HICN_ERROR_STRATEGY_NH_NOT_FOUND));
goto done;
}
@@ -114,24 +108,21 @@ hicn_mw_strategy_cli_set_weight_command_fn (vlib_main_t * vm,
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)=
-{
+
+VLIB_CLI_COMMAND (hicn_mw_strategy_cli_set_weight_command, static) = {
.path = "hicn strategy mw set",
- .short_help = "hicn strategy mw set prefix <prefix> face <face_id> weight <weight>",
+ .short_help =
+ "hicn strategy mw set prefix <prefix> face <face_id> weight <weight>",
.function = hicn_mw_strategy_cli_set_weight_command_fn,
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/hicn-plugin/src/strategies/strategy_rr.c b/hicn-plugin/src/strategies/strategy_rr.c
index cdcca7f2a..9995191b7 100644
--- a/hicn-plugin/src/strategies/strategy_rr.c
+++ b/hicn-plugin/src/strategies/strategy_rr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -23,13 +23,12 @@
/* 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_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,
- dpo_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);
-
+ 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,
@@ -49,9 +48,10 @@ 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*/
+/* 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, dpo_id_t ** outface)
+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);
@@ -61,15 +61,7 @@ hicn_select_next_hop_rr (index_t dpo_idx, int *nh_idx, dpo_id_t ** outface)
hicn_strategy_rr_ctx_t *hicn_strategy_rr_ctx =
(hicn_strategy_rr_ctx_t *) dpo_ctx->data;
- if (dpo_id_is_valid
- (&dpo_ctx->next_hops[hicn_strategy_rr_ctx->current_nhop]))
- {
- *outface =
- (dpo_id_t *) & dpo_ctx->next_hops[hicn_strategy_rr_ctx->current_nhop];
-
- }
- else
- return HICN_ERROR_STRATEGY_NH_NOT_FOUND;
+ *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;
@@ -78,11 +70,13 @@ hicn_select_next_hop_rr (index_t dpo_idx, int *nh_idx, dpo_id_t ** outface)
}
void
-hicn_add_interest_rr (index_t dpo_ctx_idx, hicn_hash_entry_t * hash_entry)
+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 };
+ dpo_id_t hicn_dpo_id = { .dpoi_type = hicn_dpo_strategy_rr_get_type (),
+ .dpoi_proto = 0,
+ .dpoi_next_node = 0,
+ .dpoi_index = dpo_ctx_idx };
hicn_strategy_dpo_ctx_lock (&hicn_dpo_id);
hash_entry->vft_id = hicn_dpo_get_vft_id (&hicn_dpo_id);
}
@@ -98,10 +92,9 @@ 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)
+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);
@@ -109,14 +102,14 @@ hicn_strategy_format_trace_rr (u8 * s, hicn_strategy_trace_t * t)
}
u8 *
-hicn_strategy_format_rr (u8 * s, va_list * ap)
+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);
+ s = format (s,
+ "Round Robin: next hop is chosen ciclying between all the "
+ "available next hops, one after the other.\n",
+ indent);
return (s);
}
diff --git a/hicn-plugin/src/strategies/strategy_rr.h b/hicn-plugin/src/strategies/strategy_rr.h
index 3936845fe..4dfe76b43 100644
--- a/hicn-plugin/src/strategies/strategy_rr.h
+++ b/hicn-plugin/src/strategies/strategy_rr.h
@@ -19,6 +19,13 @@
#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);
diff --git a/hicn-plugin/src/strategy.h b/hicn-plugin/src/strategy.h
index c18ae4eea..d949f38a4 100644
--- a/hicn-plugin/src/strategy.h
+++ b/hicn-plugin/src/strategy.h
@@ -22,21 +22,20 @@
#include "faces/face.h"
/**
- * @File
+ * @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 identify a strategy and its vft. The strategy node will use 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)
- * - the base structure for a strategy node
- * (list of next vpp nodes, errors, tracing and the main function processing an
- * interest and calling hicn_select_next_hop)
+ * - a default implementation for the strategy node which will call the strategy
+ * functions while processing the interest packets
*/
/* Trace context struct */
@@ -54,7 +53,7 @@ typedef struct hicn_strategy_vft_s
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,
- dpo_id_t ** outface);
+ 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*/
@@ -64,10 +63,31 @@ 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__ */
diff --git a/hicn-plugin/src/strategy_dpo_ctx.c b/hicn-plugin/src/strategy_dpo_ctx.c
index 6ec1407fb..342c78bb5 100644
--- a/hicn-plugin/src/strategy_dpo_ctx.c
+++ b/hicn-plugin/src/strategy_dpo_ctx.c
@@ -97,7 +97,7 @@ hicn_strategy_dpo_ctx_alloc ()
}
int
-hicn_strategy_dpo_ctx_add_nh (const dpo_id_t * nh, hicn_dpo_ctx_t * dpo_ctx,
+hicn_strategy_dpo_ctx_add_nh (hicn_face_id_t nh, hicn_dpo_ctx_t * dpo_ctx,
u8 * pos)
{
@@ -106,12 +106,12 @@ hicn_strategy_dpo_ctx_add_nh (const dpo_id_t * nh, hicn_dpo_ctx_t * dpo_ctx,
/* 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 (!memcmp (nh, &dpo_ctx->next_hops[i], sizeof (dpo_id_t)))
+ 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].dpoi_index);
- if (face->shared.flags & HICN_FACE_FLAGS_DELETED)
+ hicn_dpoi_get_from_idx (dpo_ctx->next_hops[i]);
+ if (face->flags & HICN_FACE_FLAGS_DELETED)
{
continue;
}
@@ -125,7 +125,8 @@ hicn_strategy_dpo_ctx_add_nh (const dpo_id_t * nh, hicn_dpo_ctx_t * dpo_ctx,
return HICN_ERROR_DPO_CTX_NHOPS_NS;
}
- clib_memcpy (&dpo_ctx->next_hops[empty], nh, sizeof (dpo_id_t));
+ dpo_ctx->next_hops[empty] = nh;
+ hicn_face_lock_with_id (nh);
dpo_ctx->entry_count++;
*pos = empty;
@@ -137,13 +138,13 @@ 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;
- dpo_id_t invalid = NEXT_HOP_INVALID;
+ hicn_face_id_t invalid = NEXT_HOP_INVALID;
for (int i = 0; i < dpo_ctx->entry_count; i++)
{
- if (dpo_ctx->next_hops[i].dpoi_index == face_id)
+ if (dpo_ctx->next_hops[i] == face_id)
{
- hicn_face_unlock (&dpo_ctx->next_hops[i]);
+ 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;
diff --git a/hicn-plugin/src/strategy_dpo_ctx.h b/hicn-plugin/src/strategy_dpo_ctx.h
index 737071766..214ed88ad 100644
--- a/hicn-plugin/src/strategy_dpo_ctx.h
+++ b/hicn-plugin/src/strategy_dpo_ctx.h
@@ -22,27 +22,30 @@
#include "params.h"
#include "faces/face.h"
-//FIB table for hicn. 0 is the default one used by ip
-#define HICN_FIB_TABLE 0
-
-#define NEXT_HOP_INVALID DPO_INVALID
-
-#define INIT_SEQ 0
-
/**
- * @brief Definition of the general hICN DPO ctx (shared among all the strategies).
+ * @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 a dpo_id_t that refers to 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)
+ * 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);
- /* 8B*5 = 40B */
- dpo_id_t next_hops[HICN_PARAM_FIB_ENTRY_NHOPS_MAX];
+ /* 4B*10 = 40B */
+ hicn_face_id_t next_hops[HICN_PARAM_FIB_ENTRY_NHOPS_MAX];
/* 40B + 4B = 44B */
u32 locks;
/* 44B + 1B = 45B */
@@ -51,17 +54,30 @@ typedef struct __attribute__ ((packed)) hicn_dpo_ctx_s
/* 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 */
- u16 padding; /* To align to 8B */
+ u8 padding; /* To align to 8B */
/* 48 + 4B = 52; last sequence number */
- seq_t seq;
+ u32 seq;
- /* 48 + 1B = 53; last sequence number */
- dpo_type_t dpo_type;
+ /* 52 + 12 = 64 */
+ fib_node_t fib_node;
CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
- u8 data[CLIB_CACHE_LINE_BYTES];
+
+ 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;
@@ -76,10 +92,10 @@ extern hicn_dpo_ctx_t *hicn_strategy_dpo_ctx_pool;
* @param dpo_type Type of dpo. It identifies the strategy.
*/
always_inline void
-init_dpo_ctx (hicn_dpo_ctx_t * dpo_ctx, const dpo_id_t * next_hop,
- int nh_len, dpo_type_t dpo_type)
+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)
{
- dpo_id_t invalid = NEXT_HOP_INVALID;
+ hicn_face_id_t invalid = NEXT_HOP_INVALID;
dpo_ctx->entry_count = 0;
dpo_ctx->locks = 0;
@@ -89,9 +105,11 @@ init_dpo_ctx (hicn_dpo_ctx_t * dpo_ctx, const dpo_id_t * next_hop,
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++)
{
- clib_memcpy (&dpo_ctx->next_hops[i], &next_hop[i], sizeof (dpo_id_t));
+ dpo_ctx->next_hops[i] = next_hop[i];
dpo_ctx->entry_count++;
}
@@ -151,7 +169,7 @@ void hicn_strategy_dpo_ctx_unlock (dpo_id_t * dpo);
* otherwise HICN_ERROR_DPO_CTX_NOT_FOUND
*/
int
-hicn_strategy_dpo_ctx_add_nh (const dpo_id_t * nh, hicn_dpo_ctx_t * dpo_ctx,
+hicn_strategy_dpo_ctx_add_nh (hicn_face_id_t nh, hicn_dpo_ctx_t * dpo_ctx,
u8 * pos);
/**
diff --git a/hicn-plugin/src/strategy_dpo_manager.h b/hicn-plugin/src/strategy_dpo_manager.h
index 63fcb930b..e96e050d9 100644
--- a/hicn-plugin/src/strategy_dpo_manager.h
+++ b/hicn-plugin/src/strategy_dpo_manager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,10 +20,26 @@
#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.
*
- * An hICN dpo is a combination of a dpo context (hicn_dpo_ctx or struct that
- * extends a hicn_dpo_ctx) and a strategy node. The following virtual function table
+ * The following virtual function table
* template that glues together the fuction to interact with the context and the
* creating the dpo
*/
@@ -35,8 +51,8 @@ typedef struct hicn_dpo_vft_s
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) (dpo_proto_t proto, const dpo_id_t * nh, int nh_len, index_t * dpo_idx); /**< Create the context of the hICN dpo */
- int (*hicn_dpo_add_update_nh) (const dpo_id_t * nh, index_t dpo_idx); /**< Add a next hop to the hICN dpo context */
+ 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*/
@@ -48,37 +64,18 @@ typedef struct hicn_dpo_vft_s
*/
extern hicn_dpo_vft_t default_dpo;
-const static char *const hicn_ip6_nodes[] = {
- "hicn-iface-ip6-input", // this is the name you give your node in VLIB_REGISTER_NODE
- NULL,
-};
-
-const static char *const hicn_ip4_nodes[] = {
- "hicn-iface-ip4-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,
-};
-
/**
* @brief Register a new hICN dpo to the manager.
*
- * 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 strategy containing: (i) the vpp node that processes Interest packets
- * subjected to such strategy, (ii) the definition of the vft that defines
- * the hICN strategy functions
- * Registering a hICN DPO allows the plugin to be aware of the new dpo an be
- * able to apply it to the FIB entries.
+ * 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).
+ * 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
diff --git a/hicn-plugin/src/strategy_node.c b/hicn-plugin/src/strategy_node.c
index 27d1e2a03..39232be73 100644
--- a/hicn-plugin/src/strategy_node.c
+++ b/hicn-plugin/src/strategy_node.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@@ -49,7 +49,7 @@ static char *hicn_strategy_error_strings[] = {
/* packet trace format function */
u8 *
-hicn_strategy_format_trace (u8 * s, va_list * args)
+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 *);
@@ -60,14 +60,12 @@ hicn_strategy_format_trace (u8 * s, va_list * args)
return vft->hicn_format_strategy_trace (s, t);
}
-
always_inline int
-hicn_new_interest (hicn_strategy_runtime_t * rt, vlib_buffer_t * b0,
- u32 * next, f64 tnow, u8 * nameptr,
- u16 namelen, dpo_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)
+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;
@@ -82,7 +80,6 @@ hicn_new_interest (hicn_strategy_runtime_t * rt, vlib_buffer_t * b0,
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))
@@ -98,8 +95,7 @@ hicn_new_interest (hicn_strategy_runtime_t * rt, vlib_buffer_t * b0,
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);
+ hicn_ops_vft[type.l1]->get_lifetime (type, &hicn0->protocol, &imsg_lifetime);
if (imsg_lifetime > sm->pit_lifetime_max_ms)
{
@@ -111,11 +107,10 @@ hicn_new_interest (hicn_strategy_runtime_t * rt, vlib_buffer_t * b0,
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);
+ 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)
{
@@ -123,15 +118,14 @@ hicn_new_interest (hicn_strategy_runtime_t * rt, vlib_buffer_t * b0,
hash_entry);
/* Add face */
- hicn_face_db_add_face_dpo (&hicnb0->face_dpo_id, &(pitp->u.pit.faces));
-
- /* Remove lock on the dpo stored in the vlib_buffer */
- //dpo_unlock (&hicnb0->face_dpo_id);
+ hicn_face_db_add_face (hicnb0->face_id, &(pitp->u.pit.faces));
- *next = outface->dpoi_next_node;
+ *next = isv6 ? HICN_STRATEGY_NEXT_INTEREST_FACE6 :
+ HICN_STRATEGY_NEXT_INTEREST_FACE4;
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = outface->dpoi_index;
+ vnet_buffer (b0)->ip.adj_index[VLIB_TX] = outface;
stats->pkts_interest_count++;
+ pitp->u.pit.pe_txnh = nh_idx;
}
else
{
@@ -144,9 +138,8 @@ hicn_new_interest (hicn_strategy_runtime_t * rt, vlib_buffer_t * b0,
// 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;
+ *next = is_cs0 ? HICN_STRATEGY_NEXT_INTEREST_HITCS :
+ HICN_STRATEGY_NEXT_INTEREST_HITPIT;
}
else
{
@@ -158,7 +151,6 @@ hicn_new_interest (hicn_strategy_runtime_t * rt, vlib_buffer_t * b0,
}
return (ret);
-
}
/*
@@ -166,8 +158,8 @@ hicn_new_interest (hicn_strategy_runtime_t * rt, vlib_buffer_t * b0,
* ipv6/tcp
*/
uword
-hicn_strategy_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
+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;
@@ -197,7 +189,7 @@ hicn_strategy_fn (vlib_main_t * vm,
hicn_header_t *hicn0;
vlib_buffer_t *b0;
u32 bi0;
- dpo_id_t *outface = NULL;
+ hicn_face_id_t outface;
int nh_idx;
u32 next0 = next_index;
int ret;
@@ -222,9 +214,8 @@ hicn_strategy_fn (vlib_main_t * vm,
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]);
+ 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);
@@ -236,13 +227,11 @@ hicn_strategy_fn (vlib_main_t * vm,
* 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))
+ 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
@@ -274,9 +263,8 @@ hicn_strategy_fn (vlib_main_t * vm,
* 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_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);
@@ -294,7 +282,6 @@ hicn_strategy_fn (vlib_main_t * vm,
/*
* Node registration for the forwarder node
*/
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (hicn_strategy_node) =
{
.name = "hicn-strategy",
@@ -310,11 +297,12 @@ VLIB_REGISTER_NODE (hicn_strategy_node) =
{
[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
*
diff --git a/hicn-plugin/src/udp_tunnels/udp_decap.h b/hicn-plugin/src/udp_tunnels/udp_decap.h
new file mode 100644
index 000000000..9ddb8a73b
--- /dev/null
+++ b/hicn-plugin/src/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/udp_tunnels/udp_decap_node.c b/hicn-plugin/src/udp_tunnels/udp_decap_node.c
new file mode 100644
index 000000000..84e4e5234
--- /dev/null
+++ b/hicn-plugin/src/udp_tunnels/udp_decap_node.c
@@ -0,0 +1,661 @@
+/*
+ * Copyright (c) 2020-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <vnet/fib/fib_table.h>
+
+#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
+ */
+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" },
+};
+
+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
+ */
+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" },
+};
+
+/*
+ * 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
new file mode 100644
index 000000000..58694d8e9
--- /dev/null
+++ b/hicn-plugin/src/udp_tunnels/udp_tunnel.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2020-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <vlib/vlib.h>
+#include <vnet/vnet.h>
+#include <vppinfra/bihash_40_8.h>
+#include <vnet/fib/fib_table.h>
+
+#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;
+}
+
+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,
+};
+
+/*
+ * 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
new file mode 100644
index 000000000..2ec92056c
--- /dev/null
+++ b/hicn-plugin/src/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 <vlib/vlib.h>
+#include <vppinfra/error.h>
+#include <vnet/udp/udp_encap.h>
+
+/**
+ * @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
index ecad47e9b..689942ab6 100644
--- a/hicn-plugin/src/utils.h
+++ b/hicn-plugin/src/utils.h
@@ -18,6 +18,17 @@
#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)
{
@@ -29,6 +40,11 @@ hicn_print_name6 (hicn_name_t * name)
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)
{
@@ -43,6 +59,11 @@ hicn_print6 (hicn_header_t * hicn0)
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)
{
diff --git a/hicn-plugin/vapi/CMakeLists.txt b/hicn-plugin/vapi/CMakeLists.txt
index 03fd489ca..9464cd944 100644
--- a/hicn-plugin/vapi/CMakeLists.txt
+++ b/hicn-plugin/vapi/CMakeLists.txt
@@ -42,7 +42,7 @@ build_library(${SAFE_VAPI}
LINK_LIBRARIES ${LIBRARIES}
COMPONENT ${HICN_PLUGIN}
INCLUDE_DIRS ${INCLUDE_DIRS}
- INSTALL_ROOT_DIR /
+ HEADER_ROOT_DIR /
DEFINITIONS ${COMPILER_DEFINITIONS}
)
diff --git a/hicn-plugin/vapi/vapi_safe.c b/hicn-plugin/vapi/vapi_safe.c
index c1d66c0ac..e9353497f 100644
--- a/hicn-plugin/vapi/vapi_safe.c
+++ b/hicn-plugin/vapi/vapi_safe.c
@@ -12,7 +12,7 @@ u32 count = 0;
int lock = 0;
vapi_error_e vapi_connect_safe(vapi_ctx_t *vapi_ctx_ret, int async) {
- vapi_error_e rv = VAPI_OK;
+ vapi_error_e rv = VAPI_OK;
while (!__sync_bool_compare_and_swap(&lock, 0, 1));
@@ -39,7 +39,7 @@ vapi_error_e vapi_connect_safe(vapi_ctx_t *vapi_ctx_ret, int async) {
async ? VAPI_MODE_NONBLOCKING : VAPI_MODE_BLOCKING, true);
if (rv != VAPI_OK)
- goto err_vapi;
+ goto err;
count++;
}
@@ -49,8 +49,6 @@ vapi_error_e vapi_connect_safe(vapi_ctx_t *vapi_ctx_ret, int async) {
while (!__sync_bool_compare_and_swap(&lock, 1, 0));
return rv;
- err_vapi:
- vapi_ctx_free(g_vapi_ctx_instance);
err_mutex_init:
free(mutex);
err_mutex_alloc:
diff --git a/lib/.clang-format b/lib/.clang-format
new file mode 100644
index 000000000..8b5c955ce
--- /dev/null
+++ b/lib/.clang-format
@@ -0,0 +1,21 @@
+# Minimal clang-format version is 8
+
+BasedOnStyle: GNU
+UseTab: Always
+SpaceAfterCStyleCast: true
+SortIncludes: false
+AlignConsecutiveMacros: true
+BreakBeforeTernaryOperators: false
+BreakBeforeBinaryOperators: None
+ContinuationIndentWidth: 2
+
+ForEachMacros:
+ - 'clib_bitmap_foreach'
+ - 'pool_foreach'
+ - 'pool_foreach_index'
+ - 'vec_foreach'
+ - 'vec_foreach_backwards'
+ - 'vec_foreach_index'
+ - 'vec_foreach_index_backwards'
+ - 'vlib_foreach_rx_tx'
+
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 3cc40bb7f..0512b7c64 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -48,5 +48,4 @@ endif ()
add_subdirectory(includes)
add_subdirectory (src)
-add_subdirectory (doc)
diff --git a/lib/includes/CMakeLists.txt b/lib/includes/CMakeLists.txt
index 6184f4708..0f1bf80d3 100644
--- a/lib/includes/CMakeLists.txt
+++ b/lib/includes/CMakeLists.txt
@@ -27,9 +27,10 @@ set(LIBHICN_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/hicn/header.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/mapme.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/name.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ops.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/policy.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ops.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/strategy.h
PARENT_SCOPE
)
@@ -55,3 +56,5 @@ set(LIBHICN_HEADER_FILES_UTIL
PARENT_SCOPE
)
+set_property(GLOBAL PROPERTY LIBHICN_HEADER_FILES_UTIL_PROPERTY "${LIBHICN_HEADER_FILES_UTIL}")
+
diff --git a/lib/includes/hicn/base.h b/lib/includes/hicn/base.h
index 3112d1140..1061724ce 100644
--- a/lib/includes/hicn/base.h
+++ b/lib/includes/hicn/base.h
@@ -22,12 +22,16 @@
#define HICN_BASE_H
#include "common.h"
-
+#ifdef _WIN32
+#include <Winsock2.h>
+#else
+#include <netinet/in.h>
+#endif
/* Default header fields */
#define HICN_DEFAULT_TTL 254
typedef u32 hicn_faceid_t;
-typedef u32 hicn_pathlabel_t;
+typedef u8 hicn_pathlabel_t;
typedef u32 hicn_lifetime_t;
#define HICN_MAX_LIFETIME_SCALED 0xFFFF
@@ -95,20 +99,27 @@ HICN_TYPE(int x, int y, int z, int t)
#endif
#define HICN_TYPE_IPV4_TCP HICN_TYPE(IPPROTO_IP, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV4_UDP HICN_TYPE(IPPROTO_IP, IPPROTO_UDP, IPPROTO_NONE, IPPROTO_NONE)
#define HICN_TYPE_IPV4_ICMP HICN_TYPE(IPPROTO_IP, IPPROTO_ICMP, IPPROTO_NONE, IPPROTO_NONE)
#define HICN_TYPE_IPV6_TCP HICN_TYPE(IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV6_UDP HICN_TYPE(IPPROTO_IPV6, IPPROTO_UDP, IPPROTO_NONE, IPPROTO_NONE)
#define HICN_TYPE_IPV6_ICMP HICN_TYPE(IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV4_TCP_AH HICN_TYPE(IPPROTO_IP, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV4_UDP_AH HICN_TYPE(IPPROTO_IP, IPPROTO_UDP, IPPROTO_NONE, IPPROTO_NONE)
-#define HICN_TYPE_IPV4_ICMP_AH HICN_TYPE(IPPROTO_IP, IPPROTO_ICMP, IPPROTO_NONE, IPPROTO_NONE)
+#define HICN_TYPE_IPV4_TCP_AH HICN_TYPE(IPPROTO_IP, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE)
+#define HICN_TYPE_IPV4_ICMP_AH HICN_TYPE(IPPROTO_IP, IPPROTO_ICMP, IPPROTO_AH, IPPROTO_NONE)
#define HICN_TYPE_IPV6_TCP_AH HICN_TYPE(IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE)
-#define HICN_TYPE_IPV6_UDP_AH HICN_TYPE(IPPROTO_IPV6, IPPROTO_UDP, IPPROTO_AH, IPPROTO_NONE)
#define HICN_TYPE_IPV6_ICMP_AH HICN_TYPE(IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_AH, IPPROTO_NONE)
#define HICN_TYPE_NONE HICN_TYPE(IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE)
/**
+ * @brief Check if type is none.
+ * @return 1 if none, 0 otherwise
+ */
+always_inline int
+hicn_type_is_none(hicn_type_t type)
+{
+ return (type.l1 == IPPROTO_NONE) && (type.l2 == IPPROTO_NONE) &&
+ (type.l3 == IPPROTO_NONE) && (type.l4 == IPPROTO_NONE);
+}
+
+/**
* @brief hICN Payload type
*
* This type distinguishes several types of data packet, which can either carry
@@ -131,9 +142,8 @@ typedef enum
* NOTE: this computation is not (yet) part of the hICN specification.
*/
-// XXX TODO deprecate TODO XXX
-#define HICN_PATH_LABEL_MASK 0xF000 /* 1000 0000 0000 0000 */
-#define HICN_PATH_LABEL_SIZE 8 /* XXX in bits ? */
+#define HICN_PATH_LABEL_MASK 0x000000ff
+#define HICN_PATH_LABEL_SIZE 8
/**
* @brief Path label update
@@ -148,8 +158,8 @@ update_pathlabel (hicn_pathlabel_t current_label, hicn_faceid_t face_id,
hicn_pathlabel_t * new_label)
{
hicn_pathlabel_t pl_face_id =
- (hicn_pathlabel_t) ((face_id & HICN_PATH_LABEL_MASK) >>
- (16 - HICN_PATH_LABEL_SIZE));
+ (hicn_pathlabel_t) (face_id & HICN_PATH_LABEL_MASK);
+
*new_label =
((current_label << 1) | (current_label >> (HICN_PATH_LABEL_SIZE - 1))) ^
pl_face_id;
diff --git a/lib/includes/hicn/common.h b/lib/includes/hicn/common.h
index 30f370241..05f8ad95f 100644
--- a/lib/includes/hicn/common.h
+++ b/lib/includes/hicn/common.h
@@ -104,6 +104,9 @@ typedef uword ip_csum_t;
/* Windows compatibility headers */
#define WIN32_LEAN_AND_MEAN
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
#include <windows.h>
#include <winsock2.h>
#include <ws2ipdef.h>
@@ -143,8 +146,17 @@ struct iovec
#include <vnet/ip/ip4_packet.h> // ip4_address_t
#include <vnet/ip/ip6_packet.h> // ip6_address_t
+
+#if __GNUC__ >= 9
+#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
+#endif
+
#include <vnet/ip/ip46_address.h>
+#if __GNUC__ >= 9
+#pragma GCC diagnostic pop
+#endif
+
#else
@@ -250,7 +262,7 @@ u32 cumulative_hash32 (const void *data, size_t len, u32 lastValue);
u32 hash32 (const void *data, size_t len);
u64 cumulative_hash64 (const void *data, size_t len, u64 lastValue);
u64 hash64 (const void *data, size_t len);
-void hicn_packet_dump (uint8_t * buffer, size_t len);
+void hicn_packet_dump (const uint8_t * buffer, size_t len);
#endif /* ! HICN_VPP_PLUGIN */
diff --git a/lib/includes/hicn/compat.h b/lib/includes/hicn/compat.h
index 2796983c6..35b6e6fc5 100644
--- a/lib/includes/hicn/compat.h
+++ b/lib/includes/hicn/compat.h
@@ -34,15 +34,15 @@
/* HICN format options */
#define HFO_INET 1 << 0
#define HFO_INET6 1 << 1
-#define HFO_TCP 1 << 2
+#define HFO_TCP 1 << 2
#define HFO_ICMP 1 << 3
-#define HFO_AH 1 << 4
+#define HFO_AH 1 << 4
#define _is_ipv4(format) ((format & HFO_INET))
#define _is_ipv6(format) ((format & HFO_INET6) >> 1)
-#define _is_tcp(format) ((format & HFO_TCP) >> 2)
-#define _is_icmp(format) ((format & HFO_ICMP) >> 3)
-#define _is_ah(format) ((format & HFO_AH) >> 4)
+#define _is_tcp(format) ((format & HFO_TCP) >> 2)
+#define _is_icmp(format) ((format & HFO_ICMP) >> 3)
+#define _is_ah(format) ((format & HFO_AH) >> 4)
typedef enum
{
@@ -54,28 +54,30 @@ typedef enum
HF_INET_TCP_AH = HFO_INET | HFO_TCP | HFO_AH,
HF_INET6_TCP_AH = HFO_INET6 | HFO_TCP | HFO_AH,
HF_INET_ICMP_AH = HFO_INET | HFO_ICMP | HFO_AH,
- HF_INET6_ICMP_AH = HFO_INET6 | HFO_ICMP | HFO_AH
+ HF_INET6_ICMP_AH = HFO_INET6 | HFO_ICMP | HFO_AH,
} hicn_format_t;
/**
- * Minimum required header length to determine the type and length of a supposed
- * hICN packet.
- * This should be equal to the maximum value over all possible hICN packet
- * formats, and less than the minimum possible IP packet size.
+ * Minimum required header length to determine the type and length of a
+ * supposed hICN packet. This should be equal to the maximum value over all
+ * possible hICN packet formats, and less than the minimum possible IP packet
+ * size.
*/
-#define HICN_V6_MIN_HDR_LEN 6 /* bytes */
-#define HICN_V4_MIN_HDR_LEN 4 /* bytes */
+#define HICN_V6_MIN_HDR_LEN 6 /* bytes */
+#define HICN_V4_MIN_HDR_LEN 4 /* bytes */
-// #define HICN_MIN_HDR_LEN ((HICN_V6_MIN_HDR_LEN > HICN_V4_MIN_HDR_LEN) ? HICN_V6_MIN_HDR_LEN : HICN_V4_MIN_HDR_LEN)
+// #define HICN_MIN_HDR_LEN ((HICN_V6_MIN_HDR_LEN > HICN_V4_MIN_HDR_LEN) ?
+// HICN_V6_MIN_HDR_LEN : HICN_V4_MIN_HDR_LEN)
#define HICN_MIN_HDR_LEN HICN_V6_MIN_HDR_LEN
/**
* @brief Parse packet headers and return hICN format
* @param [in] format - hICN Format
- * @param [in, out] packet - Buffer containing the hICN header to be initialized
+ * @param [in, out] packet - Buffer containing the hICN header to be
+ * initialized
* @return hICN error code
*/
-int hicn_packet_init_header (hicn_format_t format, hicn_header_t * packet);
+int hicn_packet_init_header (hicn_format_t format, hicn_header_t *packet);
/**
* @brief Parse packet headers and return hICN format
@@ -83,8 +85,8 @@ int hicn_packet_init_header (hicn_format_t format, hicn_header_t * packet);
* @param [out] format - hICN format
* @return hICN error code
*/
-int hicn_packet_get_format (const hicn_header_t * packet,
- hicn_format_t * format);
+int hicn_packet_get_format (const hicn_header_t *packet,
+ hicn_format_t *format);
/**
* @brief Update checksums in packet headers
@@ -92,19 +94,18 @@ int hicn_packet_get_format (const hicn_header_t * packet,
* @param [in,out] packet - packet header
* @return hICN error code
*/
-int hicn_packet_compute_checksum (hicn_format_t format,
- hicn_header_t * packet);
+int hicn_packet_compute_checksum (hicn_format_t format, hicn_header_t *packet);
/**
- * @brief compute the checksum of the packet header, adding init_sum to the final value
+ * @brief compute the checksum of the packet header, adding init_sum to the
+ * final value
* @param [in] format - hICN format
* @param [in,out] packet - packet header
* @param [in] init_sum - value to add to the final checksum
* @return hICN error code
*/
int hicn_packet_compute_header_checksum (hicn_format_t format,
- hicn_header_t * packet,
- u16 init_sum);
+ hicn_header_t *packet, u16 init_sum);
/**
* @brief Verify checksums in packet headers
@@ -112,8 +113,9 @@ int hicn_packet_compute_header_checksum (hicn_format_t format,
* @param [in,out] packet - packet header
* @return hICN error code
*/
-int hicn_packet_check_integrity (hicn_format_t format,
- hicn_header_t * packet);
+int hicn_packet_check_integrity_no_payload (hicn_format_t format,
+ hicn_header_t *packet,
+ u16 init_sum);
// this is not accounted here
/**
@@ -123,7 +125,7 @@ int hicn_packet_check_integrity (hicn_format_t format,
* @return hICN error code
*/
int hicn_packet_get_header_length_from_format (hicn_format_t format,
- size_t * header_length);
+ size_t *header_length);
/**
* @brief Return total length of hicn headers (before payload)
@@ -133,8 +135,8 @@ int hicn_packet_get_header_length_from_format (hicn_format_t format,
* @return hICN error code
*/
int hicn_packet_get_header_length (hicn_format_t format,
- const hicn_header_t * packet,
- size_t * header_length);
+ const hicn_header_t *packet,
+ size_t *header_length);
/**
* @brief Return payload length
@@ -144,8 +146,8 @@ int hicn_packet_get_header_length (hicn_format_t format,
* @return hICN error code
*/
int hicn_packet_get_payload_length (hicn_format_t format,
- const hicn_header_t * packet,
- size_t * payload_length);
+ const hicn_header_t *packet,
+ size_t *payload_length);
/**
* @brief Sets payload length
@@ -155,7 +157,7 @@ int hicn_packet_get_payload_length (hicn_format_t format,
* @return hICN error code
*/
int hicn_packet_set_payload_length (hicn_format_t format,
- hicn_header_t * packet,
+ hicn_header_t *packet,
const size_t payload_length);
/**
@@ -164,8 +166,8 @@ int hicn_packet_set_payload_length (hicn_format_t format,
* @param [in] packet_2 - Second packet
* @return 0 if both packets are considered equal, any other value otherwise.
*/
-int hicn_packet_compare (const hicn_header_t * packet1,
- const hicn_header_t * packet2);
+int hicn_packet_compare (const hicn_header_t *packet1,
+ const hicn_header_t *packet2);
/**
* @brief Retrieve the name of an interest/data packet
@@ -176,8 +178,8 @@ int hicn_packet_compare (const hicn_header_t * packet1,
* data packet (0)
* @return hICN error code
*/
-int hicn_packet_get_name (hicn_format_t format, const hicn_header_t * packet,
- hicn_name_t * name, u8 is_interest);
+int hicn_packet_get_name (hicn_format_t format, const hicn_header_t *packet,
+ hicn_name_t *name, u8 is_interest);
/**
* @brief Sets the name of an interest/data packet
@@ -188,8 +190,8 @@ int hicn_packet_get_name (hicn_format_t format, const hicn_header_t * packet,
* data packet (0)
* @return hICN error code
*/
-int hicn_packet_set_name (hicn_format_t format, hicn_header_t * packet,
- const hicn_name_t * name, u8 is_interest);
+int hicn_packet_set_name (hicn_format_t format, hicn_header_t *packet,
+ const hicn_name_t *name, u8 is_interest);
/**
* @brief Sets the payload of a packet
@@ -203,8 +205,8 @@ int hicn_packet_set_name (hicn_format_t format, hicn_header_t * packet,
* - The buffer holding payload is assumed sufficiently large
* - This function updates header fields with the new length, but no checksum.
*/
-int hicn_packet_set_payload (hicn_format_t format, hicn_header_t * packet,
- const u8 * payload, u16 payload_length);
+int hicn_packet_set_payload (hicn_format_t format, hicn_header_t *packet,
+ const u8 *payload, u16 payload_length);
/**
* @brief Retrieves the payload of a packet
@@ -212,16 +214,17 @@ int hicn_packet_set_payload (hicn_format_t format, hicn_header_t * packet,
* @param [in] packet - packet header
* @param [out] payload - pointer to buffer for storing the result
* @param [out] payload_length - size of the retreived payload
- * @param [in] hard_copy - Flag : if true (eg. 1), a copy of the payload is made
- * into the payload buffer, otherwise (0) the pointer is changed to point to the payload offset in the packet.
+ * @param [in] hard_copy - Flag : if true (eg. 1), a copy of the payload is
+ * made into the payload buffer, otherwise (0) the pointer is changed to point
+ * to the payload offset in the packet.
* @return hICN error code
*
* NOTE:
* - The buffer holding payload is assumed sufficiently large
*/
-int hicn_packet_get_payload (hicn_format_t format,
- const hicn_header_t * packet, u8 ** payload,
- size_t * payload_size, bool hard_copy);
+int hicn_packet_get_payload (hicn_format_t format, const hicn_header_t *packet,
+ u8 **payload, size_t *payload_size,
+ bool hard_copy);
/**
* @brief Retrieve the locator of an interest / data packet
@@ -232,9 +235,8 @@ int hicn_packet_get_payload (hicn_format_t format,
* data packet (0)
* @return hICN error code
*/
-int hicn_packet_get_locator (hicn_format_t format,
- const hicn_header_t * packet,
- ip_address_t * prefix, bool is_interest);
+int hicn_packet_get_locator (hicn_format_t format, const hicn_header_t *packet,
+ ip_address_t *prefix, bool is_interest);
/**
* @brief Sets the locator of an interest / data packet
@@ -245,9 +247,8 @@ int hicn_packet_get_locator (hicn_format_t format,
* data packet (0)
* @return hICN error code
*/
-int hicn_packet_set_locator (hicn_format_t format, hicn_header_t * packet,
- const ip_address_t * prefix,
- bool is_interest);
+int hicn_packet_set_locator (hicn_format_t format, hicn_header_t *packet,
+ const ip_address_t *prefix, bool is_interest);
/**
* @brief Retrieves the signature size
@@ -257,8 +258,8 @@ int hicn_packet_set_locator (hicn_format_t format, hicn_header_t * packet,
* @return hICN error code
*/
int hicn_packet_get_signature_size (hicn_format_t format,
- const hicn_header_t * packet,
- size_t * bytes);
+ const hicn_header_t *packet,
+ size_t *bytes);
/**
* @brief Sets the signature size
@@ -268,7 +269,7 @@ int hicn_packet_get_signature_size (hicn_format_t format,
* @return hICN error code
*/
int hicn_packet_set_signature_size (hicn_format_t format,
- hicn_header_t * packet, size_t bytes);
+ hicn_header_t *packet, size_t bytes);
/**
* @brief Sets the signature size
@@ -278,7 +279,7 @@ int hicn_packet_set_signature_size (hicn_format_t format,
* @return hICN error code
*/
int hicn_packet_set_signature_timestamp (hicn_format_t format,
- hicn_header_t * h,
+ hicn_header_t *h,
uint64_t signature_timestamp);
/**
@@ -289,8 +290,8 @@ int hicn_packet_set_signature_timestamp (hicn_format_t format,
* @return hICN error code
*/
int hicn_packet_get_signature_timestamp (hicn_format_t format,
- const hicn_header_t * h,
- uint64_t * signature_timestamp);
+ const hicn_header_t *h,
+ uint64_t *signature_timestamp);
/**
* @brief Sets the signature size
@@ -300,7 +301,7 @@ int hicn_packet_get_signature_timestamp (hicn_format_t format,
* @return hICN error code
*/
int hicn_packet_set_validation_algorithm (hicn_format_t format,
- hicn_header_t * h,
+ hicn_header_t *h,
uint8_t validation_algorithm);
/**
@@ -311,8 +312,8 @@ int hicn_packet_set_validation_algorithm (hicn_format_t format,
* @return hICN error code
*/
int hicn_packet_get_validation_algorithm (hicn_format_t format,
- const hicn_header_t * h,
- uint8_t * validation_algorithm);
+ const hicn_header_t *h,
+ uint8_t *validation_algorithm);
/**
* @brief Sets the signature size
@@ -321,8 +322,8 @@ int hicn_packet_get_validation_algorithm (hicn_format_t format,
* @param [in] key_id - Key id to set
* @return hICN error code
*/
-int hicn_packet_set_key_id (hicn_format_t format, hicn_header_t * h,
- uint8_t * key_id);
+int hicn_packet_set_key_id (hicn_format_t format, hicn_header_t *h,
+ uint8_t *key_id);
/**
* @brief Sets the signature size
@@ -331,8 +332,8 @@ int hicn_packet_set_key_id (hicn_format_t format, hicn_header_t * h,
* @param [out] key_id - Retrieved key id
* @return hICN error code
*/
-int hicn_packet_get_key_id (hicn_format_t format, hicn_header_t * h,
- uint8_t ** key_id, uint8_t * key_id_length);
+int hicn_packet_get_key_id (hicn_format_t format, hicn_header_t *h,
+ uint8_t **key_id, uint8_t *key_id_length);
/**
* @brief Retrieves the packet hop limit
@@ -340,7 +341,7 @@ int hicn_packet_get_key_id (hicn_format_t format, hicn_header_t * h,
* @param [out] hops - Retrieved hop limit
* @return hICN error code
*/
-int hicn_packet_get_hoplimit (const hicn_header_t * packet, u8 * hops);
+int hicn_packet_get_hoplimit (const hicn_header_t *packet, u8 *hops);
/**
* @brief Sets the packet hop limit
@@ -348,107 +349,111 @@ int hicn_packet_get_hoplimit (const hicn_header_t * packet, u8 * hops);
* @param [in] hops - Hop limit to set
* @return hICN error code
*/
-int hicn_packet_set_hoplimit (hicn_header_t * packet, u8 hops);
+int hicn_packet_set_hoplimit (hicn_header_t *packet, u8 hops);
-int hicn_packet_copy_header (hicn_format_t format,
- const hicn_header_t * packet,
- hicn_header_t * destination, bool copy_ah);
+int hicn_packet_copy_header (hicn_format_t format, const hicn_header_t *packet,
+ hicn_header_t *destination, bool copy_ah);
-int hicn_packet_get_lifetime (const hicn_header_t * packet, u32 * lifetime);
-int hicn_packet_set_lifetime (hicn_header_t * packet, u32 lifetime);
-int hicn_packet_get_reserved_bits (const hicn_header_t * packet,
- u8 * reserved_bits);
-int hicn_packet_set_reserved_bits (hicn_header_t * packet,
+int hicn_packet_get_lifetime (const hicn_header_t *packet, u32 *lifetime);
+int hicn_packet_set_lifetime (hicn_header_t *packet, u32 lifetime);
+int hicn_packet_get_reserved_bits (const hicn_header_t *packet,
+ u8 *reserved_bits);
+int hicn_packet_set_reserved_bits (hicn_header_t *packet,
const u8 reserved_bits);
-int hicn_packet_get_payload_type (const hicn_header_t * packet,
- hicn_payload_type_t * payload_type);
-int hicn_packet_set_payload_type (hicn_header_t * packet,
+int hicn_packet_get_payload_type (const hicn_header_t *packet,
+ hicn_payload_type_t *payload_type);
+int hicn_packet_set_payload_type (hicn_header_t *packet,
const hicn_payload_type_t payload_type);
-int hicn_packet_set_syn (hicn_header_t * packet);
-int hicn_packet_reset_syn (hicn_header_t * packet);
-int hicn_packet_test_syn (const hicn_header_t * packet, bool * flag);
-int hicn_packet_set_ack (hicn_header_t * packet);
-int hicn_packet_reset_ack (hicn_header_t * packet);
-int hicn_packet_test_ack (const hicn_header_t * packet, bool * flag);
-int hicn_packet_set_rst (hicn_header_t * packet);
-int hicn_packet_reset_rst (hicn_header_t * packet);
-int hicn_packet_test_rst (const hicn_header_t * packet, bool * flag);
-int hicn_packet_set_fin (hicn_header_t * packet);
-int hicn_packet_reset_fin (hicn_header_t * packet);
-int hicn_packet_test_fin (const hicn_header_t * packet, bool * flag);
-int hicn_packet_set_ece (hicn_header_t * packet);
-int hicn_packet_reset_ece (hicn_header_t * packet);
-int hicn_packet_test_ece (const hicn_header_t * packet, bool * flag);
-
-int hicn_packet_set_src_port (hicn_header_t * packet, u16 src_port);
-int hicn_packet_get_src_port (const hicn_header_t * packet, u16 * src_port);
-int hicn_packet_set_dst_port (hicn_header_t * packet, u16 dst_port);
-int hicn_packet_get_dst_port (const hicn_header_t * packet, u16 * dst_port);
-int hicn_packet_get_signature (hicn_format_t format, hicn_header_t * packet,
- uint8_t ** sign_buf);
+int hicn_packet_set_syn (hicn_format_t format, hicn_header_t *packet);
+int hicn_packet_reset_syn (hicn_format_t format, hicn_header_t *packet);
+int hicn_packet_test_syn (hicn_format_t format, const hicn_header_t *packet,
+ bool *flag);
+int hicn_packet_set_ack (hicn_format_t format, hicn_header_t *packet);
+int hicn_packet_reset_ack (hicn_format_t format, hicn_header_t *packet);
+int hicn_packet_test_ack (hicn_format_t format, const hicn_header_t *packet,
+ bool *flag);
+int hicn_packet_set_rst (hicn_format_t format, hicn_header_t *packet);
+int hicn_packet_reset_rst (hicn_format_t format, hicn_header_t *packet);
+int hicn_packet_test_rst (hicn_format_t format, const hicn_header_t *packet,
+ bool *flag);
+int hicn_packet_set_fin (hicn_format_t format, hicn_header_t *packet);
+int hicn_packet_reset_fin (hicn_format_t format, hicn_header_t *packet);
+int hicn_packet_test_fin (hicn_format_t format, const hicn_header_t *packet,
+ bool *flag);
+int hicn_packet_set_ece (hicn_format_t format, hicn_header_t *packet);
+int hicn_packet_reset_ece (hicn_format_t format, hicn_header_t *packet);
+int hicn_packet_test_ece (hicn_format_t format, const hicn_header_t *packet,
+ bool *flag);
+
+int hicn_packet_set_src_port (hicn_format_t format, hicn_header_t *packet,
+ u16 src_port);
+int hicn_packet_get_src_port (hicn_format_t format,
+ const hicn_header_t *packet, u16 *src_port);
+int hicn_packet_set_dst_port (hicn_format_t format, hicn_header_t *packet,
+ u16 dst_port);
+int hicn_packet_get_dst_port (hicn_format_t format,
+ const hicn_header_t *packet, u16 *dst_port);
+int hicn_packet_get_signature (hicn_format_t format, hicn_header_t *packet,
+ uint8_t **sign_buf);
/* Interest */
int hicn_interest_get_name (hicn_format_t format,
- const hicn_header_t * interest,
- hicn_name_t * name);
-int hicn_interest_set_name (hicn_format_t format, hicn_header_t * interest,
- const hicn_name_t * name);
+ const hicn_header_t *interest, hicn_name_t *name);
+int hicn_interest_set_name (hicn_format_t format, hicn_header_t *interest,
+ const hicn_name_t *name);
int hicn_interest_get_locator (hicn_format_t format,
- const hicn_header_t * interest,
- ip_address_t * prefix);
-int hicn_interest_set_locator (hicn_format_t format, hicn_header_t * interest,
- const ip_address_t * prefix);
-int hicn_interest_compare (const hicn_header_t * interest_1,
- const hicn_header_t * interest_2);
-int hicn_interest_set_lifetime (hicn_header_t * interest, u32 lifetime);
-int hicn_interest_get_lifetime (const hicn_header_t * interest,
- u32 * lifetime);
+ const hicn_header_t *interest,
+ ip_address_t *prefix);
+int hicn_interest_set_locator (hicn_format_t format, hicn_header_t *interest,
+ const ip_address_t *prefix);
+int hicn_interest_compare (const hicn_header_t *interest_1,
+ const hicn_header_t *interest_2);
+int hicn_interest_set_lifetime (hicn_header_t *interest, u32 lifetime);
+int hicn_interest_get_lifetime (const hicn_header_t *interest, u32 *lifetime);
int hicn_interest_get_header_length (hicn_format_t format,
- const hicn_header_t * interest,
- size_t * header_length);
+ const hicn_header_t *interest,
+ size_t *header_length);
int hicn_interest_get_payload_length (hicn_format_t format,
- const hicn_header_t * interest,
- size_t * payload_length);
-int hicn_interest_set_payload (hicn_format_t format, hicn_header_t * interest,
- const u8 * payload, size_t payload_length);
+ const hicn_header_t *interest,
+ size_t *payload_length);
+int hicn_interest_set_payload (hicn_format_t format, hicn_header_t *interest,
+ const u8 *payload, size_t payload_length);
int hicn_interest_get_payload (hicn_format_t format,
- const hicn_header_t * interest, u8 ** payload,
- size_t * payload_size, bool hard_copy);
-int hicn_interest_reset_for_hash (hicn_format_t format,
- hicn_header_t * packet);
+ const hicn_header_t *interest, u8 **payload,
+ size_t *payload_size, bool hard_copy);
+int hicn_interest_reset_for_hash (hicn_format_t format, hicn_header_t *packet);
/* Data */
-int hicn_data_get_name (hicn_format_t format, const hicn_header_t * data,
- hicn_name_t * name);
-int hicn_data_set_name (hicn_format_t format, hicn_header_t * data,
- const hicn_name_t * name);
-int hicn_data_get_locator (hicn_format_t format, const hicn_header_t * data,
- ip_address_t * prefix);
-int hicn_data_set_locator (hicn_format_t format, hicn_header_t * data,
- const ip_address_t * prefix);
-int hicn_data_compare (const hicn_header_t * data_1,
- const hicn_header_t * data_2);
-int hicn_data_get_expiry_time (const hicn_header_t * data, u32 * expiry_time);
-int hicn_data_set_expiry_time (hicn_header_t * data, u32 expiry_time);
-int hicn_data_get_header_length (hicn_format_t format, hicn_header_t * data,
- size_t * header_length);
+int hicn_data_get_name (hicn_format_t format, const hicn_header_t *data,
+ hicn_name_t *name);
+int hicn_data_set_name (hicn_format_t format, hicn_header_t *data,
+ const hicn_name_t *name);
+int hicn_data_get_locator (hicn_format_t format, const hicn_header_t *data,
+ ip_address_t *prefix);
+int hicn_data_set_locator (hicn_format_t format, hicn_header_t *data,
+ const ip_address_t *prefix);
+int hicn_data_compare (const hicn_header_t *data_1,
+ const hicn_header_t *data_2);
+int hicn_data_get_expiry_time (const hicn_header_t *data, u32 *expiry_time);
+int hicn_data_set_expiry_time (hicn_header_t *data, u32 expiry_time);
+int hicn_data_get_header_length (hicn_format_t format, hicn_header_t *data,
+ size_t *header_length);
int hicn_data_get_payload_length (hicn_format_t format,
- const hicn_header_t * data,
- size_t * payload_length);
-int hicn_data_get_path_label (const hicn_header_t * data, u32 * path_label);
-int hicn_data_set_path_label (hicn_header_t * data, u32 path_label);
-int hicn_data_get_payload (hicn_format_t format, const hicn_header_t * data,
- u8 ** payload, size_t * payload_size,
- bool hard_copy);
-int hicn_data_set_payload (hicn_format_t format, hicn_header_t * data,
- const u8 * payload, size_t payload_length);
-int hicn_data_get_payload_type (const hicn_header_t * data,
- hicn_payload_type_t * payload_type);
-int hicn_data_set_payload_type (hicn_header_t * data,
+ const hicn_header_t *data,
+ size_t *payload_length);
+int hicn_data_get_path_label (const hicn_header_t *data, u32 *path_label);
+int hicn_data_set_path_label (hicn_header_t *data, u32 path_label);
+int hicn_data_get_payload (hicn_format_t format, const hicn_header_t *data,
+ u8 **payload, size_t *payload_size, bool hard_copy);
+int hicn_data_set_payload (hicn_format_t format, hicn_header_t *data,
+ const u8 *payload, size_t payload_length);
+int hicn_data_get_payload_type (const hicn_header_t *data,
+ hicn_payload_type_t *payload_type);
+int hicn_data_set_payload_type (hicn_header_t *data,
hicn_payload_type_t payload_type);
-int hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t * packet);
+int hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t *packet);
#endif /* HICN_COMPAT_H */
diff --git a/lib/includes/hicn/error.h b/lib/includes/hicn/error.h
index 3e027c4e5..9303aeb7e 100644
--- a/lib/includes/hicn/error.h
+++ b/lib/includes/hicn/error.h
@@ -24,16 +24,17 @@
* Error definitions
******************************************************************************/
-#define foreach_libhicn_error \
-_(NONE, 0, "OK") \
-_(UNSPECIFIED, 128, "Unspecified Error") \
-_(NOT_IMPLEMENTED, 180, "Function not yet implemented") \
-_(NOT_HICN, 202, "Non hICN packet") \
-_(UNKNOWN_ADDRESS, 210, "Unknown address") \
-_(INVALID_PARAMETER, 220, "Invalid parameter") \
-_(INVALID_IP_ADDRESS, 221, "Invalid IP address") \
-_(CORRUPTED_PACKET, 222, "Corrupted packet ") \
-_(UNEXPECTED, 298, "Unexpected error")
+#define foreach_libhicn_error \
+_(NONE, 0, "OK") \
+_(UNSPECIFIED, 128, "Unspecified Error") \
+_(NOT_IMPLEMENTED, 180, "Function not yet implemented") \
+_(NOT_HICN, 202, "Non hICN packet") \
+_(UNKNOWN_ADDRESS, 210, "Unknown address") \
+_(INVALID_PARAMETER, 220, "Invalid parameter") \
+_(INVALID_IP_ADDRESS, 221, "Invalid IP address") \
+_(CORRUPTED_PACKET, 222, "Corrupted packet ") \
+_(REWRITE_CKSUM_REQUIRED, 223, "Incremental csum calculation error: cksum required.") \
+_(UNEXPECTED, 298, "Unexpected error")
typedef enum
{
diff --git a/lib/includes/hicn/face.h b/lib/includes/hicn/face.h
index 0d116b64b..3438552ff 100644
--- a/lib/includes/hicn/face.h
+++ b/lib/includes/hicn/face.h
@@ -219,4 +219,3 @@ int face_set_tags(face_t * face, policy_tags_t tags);
face_protocol_t get_protocol(face_type_t face_type);
#endif /* HICN_FACE_H */
-
diff --git a/lib/includes/hicn/ops.h b/lib/includes/hicn/ops.h
index 47795efd5..7d4ae86d8 100644
--- a/lib/includes/hicn/ops.h
+++ b/lib/includes/hicn/ops.h
@@ -106,6 +106,22 @@ typedef struct hicn_ops_s
const hicn_name_suffix_t * suffix);
/**
+ * @brief Set flag to mark current packet as interest
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest packet
+ * @return hICN error code
+ */
+ int (*mark_packet_as_interest) (hicn_type_t type, hicn_protocol_t * h);
+
+ /**
+ * @brief Set flag to mark current packet as data
+ * @param [in] type - hICN packet type
+ * @param [in,out] h - Buffer holding the Interest packet
+ * @return hICN error code
+ */
+ int (*mark_packet_as_data) (hicn_type_t type, hicn_protocol_t * h);
+
+ /**
* @brief Clear the necessary Interest fields in order to hash it
* @param [in] type - hICN packet type
* @param [in,out] h - Buffer holding the Interest packet
@@ -237,7 +253,7 @@ typedef struct hicn_ops_s
* @param [in,out] h - Buffer holding the packet
* @param [in] partial_csum - Partial checksum (set to 0, used internally to
* carry intermediate values from IP pseudo-header)
- * @param [in] payload_length - Payload length (can be set to 0, retrieved
+ * @param [in] payload_length - Payload length (can be set to ~0, retrieved
* and used internally to carry payload length across protocol headers)
* @return hICN error code
*/
@@ -248,9 +264,8 @@ typedef struct hicn_ops_s
* @brief Validate all checksums in packet headers
* @param [in] type - hICN packet type
* @param [in] h - Buffer holding the packet
- * @param [in] partial_csum - Partial checksum (set to 0, used internally to
- * carry intermediate values from IP pseudo-header)
- * @param [in] payload_length - Payload length (can be set to 0, retrieved
+ * @param [in] partial_csum - Partial checksum, or zero if no partial checksum available
+ * @param [in] payload_length - Payload length (can be set to ~0, retrieved
* and used internally to carry payload length across protocol headers)
* @return hICN error code
*/
@@ -278,12 +293,15 @@ typedef struct hicn_ops_s
* @param [in] addr_old - Old locator (set to NULL, used internally to
* compute incremental checksums)
* @param [in] face_id - Face identifier used to update pathlabel
+ * @param [in] reset_pl - If not zero, reset the current pathlabel
+ * before update it
* @return hICN error code
*/
int (*rewrite_data) (hicn_type_t type, hicn_protocol_t * h,
const ip46_address_t * addr_new,
ip46_address_t * addr_old,
- const hicn_faceid_t face_id);
+ const hicn_faceid_t face_id,
+ u8 reset_pl);
/**
* @brief Return the packet length
@@ -438,6 +456,8 @@ typedef struct hicn_ops_s
ATTR_INIT(set_interest_name, protocol ## _set_interest_name), \
ATTR_INIT(get_interest_name_suffix, protocol ## _get_interest_name_suffix), \
ATTR_INIT(set_interest_name_suffix, protocol ## _set_interest_name_suffix), \
+ ATTR_INIT(mark_packet_as_interest, protocol ## _mark_packet_as_interest), \
+ ATTR_INIT(mark_packet_as_data, protocol ## _mark_packet_as_data), \
ATTR_INIT(reset_interest_for_hash, protocol ## _reset_interest_for_hash), \
ATTR_INIT(get_data_locator, protocol ## _get_data_locator), \
ATTR_INIT(set_data_locator, protocol ## _set_data_locator), \
@@ -537,6 +557,12 @@ PAYLOAD (hicn_type_t type, const hicn_protocol_t * h)
#define DECLARE_set_interest_name_suffix(protocol, error) \
int protocol ## _set_interest_name_suffix(hicn_type_t type, hicn_protocol_t * h, const hicn_name_suffix_t * suffix) { return HICN_LIB_ERROR_ ## error ; }
+#define DECLARE_mark_packet_as_interest(protocol, error) \
+ int protocol ## _mark_packet_as_interest(hicn_type_t type, hicn_protocol_t * h) { return HICN_LIB_ERROR_ ## error ; }
+
+#define DECLARE_mark_packet_as_data(protocol, error) \
+ int protocol ## _mark_packet_as_data(hicn_type_t type, hicn_protocol_t * h) { return HICN_LIB_ERROR_ ## error ; }
+
#define DECLARE_reset_interest_for_hash(protocol, error) \
int protocol ## _reset_interest_for_hash(hicn_type_t type, hicn_protocol_t * h) { return HICN_LIB_ERROR_ ## error ; }
@@ -586,7 +612,7 @@ PAYLOAD (hicn_type_t type, const hicn_protocol_t * h)
int protocol ## _rewrite_interest(hicn_type_t type, hicn_protocol_t * h, const ip46_address_t * addr_new, ip46_address_t * addr_old) { return HICN_LIB_ERROR_ ## error ; }
#define DECLARE_rewrite_data(protocol, error) \
- int protocol ## _rewrite_data(hicn_type_t type, hicn_protocol_t * h, const ip46_address_t * addr_new, ip46_address_t * addr_old, const hicn_faceid_t face_id) { return HICN_LIB_ERROR_ ## error ; }
+ int protocol ## _rewrite_data(hicn_type_t type, hicn_protocol_t * h, const ip46_address_t * addr_new, ip46_address_t * addr_old, const hicn_faceid_t face_id, u8 reset_pl) { return HICN_LIB_ERROR_ ## error ; }
#define DECLARE_get_length(protocol, error) \
int protocol ## _get_length(hicn_type_t type, const hicn_protocol_t * h, size_t * length) { return HICN_LIB_ERROR_ ## error ; }
diff --git a/lib/includes/hicn/policy.h b/lib/includes/hicn/policy.h
index 5a9a44467..d649630bd 100644
--- a/lib/includes/hicn/policy.h
+++ b/lib/includes/hicn/policy.h
@@ -159,12 +159,16 @@ int policy_tag_state_snprintf(char * s, size_t size, const policy_tag_state_t *
typedef struct {
char app_name[APP_NAME_LEN];
policy_tag_state_t tags[POLICY_TAG_N];
-} policy_t;
+} hicn_policy_t;
-static const policy_t POLICY_NONE = {
+static const hicn_policy_t POLICY_NONE = {
.app_name = { 0 },
.tags = {
+#ifdef __ANDROID__
+#define _(x, y) { POLICY_STATE_NEUTRAL, 0 },
+#else
#define _(x, y) [POLICY_TAG_ ## x] = { POLICY_STATE_NEUTRAL, 0 },
+#endif
foreach_policy_tag
#undef _
},
@@ -181,7 +185,7 @@ typedef struct {
char ipv4_prefix[INET_ADDRSTRLEN + PFX_STRLEN];
char ipv6_prefix[INET6_ADDRSTRLEN + PFX_STRLEN];
};
- policy_t policy;
+ hicn_policy_t policy;
} policy_description_t;
#endif /* HICN_POLICY_H */
diff --git a/lib/includes/hicn/protocol/tcp.h b/lib/includes/hicn/protocol/tcp.h
index 5cf1a3625..347682299 100644
--- a/lib/includes/hicn/protocol/tcp.h
+++ b/lib/includes/hicn/protocol/tcp.h
@@ -42,7 +42,11 @@ typedef struct
union
{
u32 seq_ack;
- hicn_pathlabel_t pathlabel;
+ struct
+ {
+ hicn_pathlabel_t pathlabel;
+ u8 pad[3];
+ };
};
union
@@ -124,8 +128,6 @@ typedef struct
static_assert (EXPECTED_TCP_HDRLEN == TCP_HDRLEN,
"Size of TCP struct does not match its expected size.");
-#ifndef HICN_VPP_PLUGIN
-
/* TCP flags bit 0 first. */
#define foreach_tcp_flag \
_ (FIN) /**< No more data from sender. */ \
@@ -152,12 +154,6 @@ enum
#undef _
};
-#endif /* HICN_VPP_PLUGIN */
-
-// get_data_name_suffix
-// name->ip4.suffix = h->v4.tcp.seq;
-
-
#endif /* HICN_PROTOCOL_TCP_H */
/*
diff --git a/lib/includes/hicn/strategy.h b/lib/includes/hicn/strategy.h
new file mode 100644
index 000000000..fe47ce547
--- /dev/null
+++ b/lib/includes/hicn/strategy.h
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+/**
+ * \file strategy.h
+ * \brief hICN forwarding strategy
+ */
+#ifndef HICN_STRATEGY_H
+#define HICN_STRATEGY_H
+
+typedef enum {
+ STRATEGY_TYPE_UNDEFINED,
+ STRATEGY_TYPE_LOADBALANCER,
+ STRATEGY_TYPE_LOW_LATENCY,
+ STRATEGY_TYPE_RANDOM,
+ STRATEGY_TYPE_N
+} strategy_type_t;
+
+#define STRATEGY_TYPE_VALID(type) \
+ ((type != STRATEGY_TYPE_UNDEFINED) && (type != STRATEGY_TYPE_N))
+
+#define MAX_FWD_STRATEGY_RELATED_PREFIXES 10
+
+#endif /* HICN_STRATEGY_H */
diff --git a/lib/includes/hicn/util/log.h b/lib/includes/hicn/util/log.h
index 6763d464f..5650a164e 100644
--- a/lib/includes/hicn/util/log.h
+++ b/lib/includes/hicn/util/log.h
@@ -34,7 +34,7 @@ typedef struct {
} log_conf_t;
#define DEFAULT_LOG_CONF { \
- .log_level = LOG_INFO, \
+ .log_level = LOG_TRACE, \
.debug = 0, \
.log_file = NULL, \
};
diff --git a/lib/includes/hicn/util/windows/dlfcn.h b/lib/includes/hicn/util/windows/dlfcn.h
new file mode 100644
index 000000000..7775226cd
--- /dev/null
+++ b/lib/includes/hicn/util/windows/dlfcn.h
@@ -0,0 +1,33 @@
+/* dlfcn.h */
+
+#ifndef DLFCN_H
+#define DLFCN_H
+#define RTLD_GLOBAL 0x100 /* do not hide entries in this module */
+#define RTLD_LOCAL 0x000 /* hide entries in this module */
+
+#define RTLD_LAZY 0x000 /* accept unresolved externs */
+#define RTLD_NOW 0x001 /* abort if module has unresolved externs */
+
+/*
+ How to call in Windows:
+
+ void *h = dlopen ("path\\library.dll", flags)
+ void (*fun)() = dlsym (h, "entry")
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ void *dlopen (const char *filename, int flag);
+ int dlclose (void *handle);
+
+ void *dlsym (void *handle, const char *name);
+
+const char *dlerror (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif \ No newline at end of file
diff --git a/lib/includes/hicn/util/windows/windows_utils.h b/lib/includes/hicn/util/windows/windows_utils.h
index c4662af5e..d24aaadbf 100755
--- a/lib/includes/hicn/util/windows/windows_utils.h
+++ b/lib/includes/hicn/util/windows/windows_utils.h
@@ -17,12 +17,16 @@
#define WINDOWS_UTILS_H
#define WIN32_LEAN_AND_MEAN
#define HAVE_STRUCT_TIMESPEC
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
#include <Windows.h>
#include <stdint.h>
#include <io.h>
#include <stdlib.h>
#include <winsock2.h>
#include <WS2tcpip.h>
+#include "dlfcn.h"
#ifndef IOVEC
#define IOVEC
@@ -152,3 +156,7 @@ int gettimeofday(struct timeval * tp, struct timezone * tzp);
((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) \
| (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24))
#endif
+
+#ifndef bzero
+#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
+#endif \ No newline at end of file
diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt
index 6eb4c9554..b8cfc3f6c 100644
--- a/lib/src/CMakeLists.txt
+++ b/lib/src/CMakeLists.txt
@@ -31,6 +31,11 @@ list(APPEND LIBHICN_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/util/log.c
)
+if (WIN32)
+ list(APPEND LIBHICN_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/util/windows/dlfcn.c
+ )
+endif ()
set (COMPILER_DEFINITIONS
"-DWITH_MAPME"
"-DWITH_POLICY"
@@ -46,7 +51,7 @@ if (DISABLE_SHARED_LIBRARIES)
COMPONENT lib${LIBHICN}
INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../includes
DEFINITIONS ${COMPILER_DEFINITIONS}
- INSTALL_ROOT_DIR hicn
+ HEADER_ROOT_DIR hicn
INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
LINK_LIBRARIES ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
)
@@ -57,7 +62,7 @@ else ()
COMPONENT lib${LIBHICN}
INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../includes
DEFINITIONS ${COMPILER_DEFINITIONS}
- INSTALL_ROOT_DIR hicn
+ HEADER_ROOT_DIR hicn
INSTALL_HEADERS ${LIBHICN_HEADER_FILES} ${LIBHICN_HEADER_FILES_PROTOCOL} ${LIBHICN_HEADER_FILES_UTIL}
LINK_LIBRARIES ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
)
diff --git a/lib/src/common.c b/lib/src/common.c
index 78d25b770..562771e09 100644
--- a/lib/src/common.c
+++ b/lib/src/common.c
@@ -29,6 +29,7 @@
#include <stdio.h>
#include <hicn/common.h>
+#include <hicn/util/log.h>
@@ -109,7 +110,7 @@ hash64 (const void *data, size_t len)
}
void
-hicn_packet_dump (uint8_t * buffer, size_t len)
+hicn_packet_dump (const uint8_t * buffer, size_t len)
{
int i;
unsigned char buff[17];
diff --git a/lib/src/compat.c b/lib/src/compat.c
index 615175e3b..779a47315 100644
--- a/lib/src/compat.c
+++ b/lib/src/compat.c
@@ -20,8 +20,8 @@
#ifndef _WIN32
#include <netinet/in.h>
#endif
-#include <string.h> // memset
-#include <stddef.h> // offsetof
+#include <string.h> // memset
+#include <stddef.h> // offsetof
#include <hicn/common.h>
#include <hicn/compat.h>
@@ -30,13 +30,13 @@
#include <hicn/name.h>
#include <hicn/ops.h>
-#define member_size(type, member) sizeof(((type *)0)->member)
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+#define member_size(type, member) sizeof (((type *) 0)->member)
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof (*(a)))
#define HICN_NAME_COMPONENT_SIZE 2
int
-hicn_packet_get_format (const hicn_header_t * h, hicn_format_t * format)
+hicn_packet_get_format (const hicn_header_t *h, hicn_format_t *format)
{
*format = HF_UNSPEC;
@@ -122,7 +122,7 @@ hicn_format_to_type (hicn_format_t format)
* This function is used to wrap old API calls to new ones
*/
hicn_type_t
-hicn_header_to_type (const hicn_header_t * h)
+hicn_header_to_type (const hicn_header_t *h)
{
hicn_format_t format;
hicn_packet_get_format (h, &format);
@@ -130,39 +130,47 @@ hicn_header_to_type (const hicn_header_t * h)
}
int
-hicn_packet_init_header (hicn_format_t format, hicn_header_t * packet)
+hicn_packet_init_header (hicn_format_t format, hicn_header_t *packet)
{
hicn_type_t type = hicn_format_to_type (format);
+
+ if (hicn_type_is_none (type))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
return hicn_ops_vft[type.l1]->init_packet_header (type, &packet->protocol);
}
int
-hicn_packet_compute_checksum (hicn_format_t format, hicn_header_t * h)
+hicn_packet_compute_checksum (hicn_format_t format, hicn_header_t *h)
{
hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->update_checksums (type, &h->protocol, 0, 0);
+ return hicn_ops_vft[type.l1]->update_checksums (type, &h->protocol, 0, ~0);
}
int
-hicn_packet_compute_header_checksum (hicn_format_t format, hicn_header_t * h,
+hicn_packet_compute_header_checksum (hicn_format_t format, hicn_header_t *h,
u16 init_sum)
{
hicn_type_t type = hicn_format_to_type (format);
- /* payload_length == ~0: ignore payload */
- return hicn_ops_vft[type.l1]->update_checksums (type, &h->protocol,
- init_sum, ~0);
+ /* payload_length == 0: ignore payload */
+ return hicn_ops_vft[type.l1]->update_checksums (type, &h->protocol, init_sum,
+ 0);
}
int
-hicn_packet_check_integrity (hicn_format_t format, hicn_header_t * h)
+hicn_packet_check_integrity_no_payload (hicn_format_t format, hicn_header_t *h,
+ u16 init_sum)
{
hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->verify_checksums (type, &h->protocol, 0, 0);
+ return hicn_ops_vft[type.l1]->verify_checksums (type, &h->protocol, init_sum,
+ 0);
}
int
hicn_packet_get_header_length_from_format (hicn_format_t format,
- size_t * header_length)
+ size_t *header_length)
{
*header_length = _is_ipv4 (format) * IPV4_HDRLEN;
*header_length += _is_ipv6 (format) * IPV6_HDRLEN;
@@ -174,8 +182,8 @@ hicn_packet_get_header_length_from_format (hicn_format_t format,
}
int
-hicn_packet_get_header_length (hicn_format_t format, const hicn_header_t * h,
- size_t * header_length)
+hicn_packet_get_header_length (hicn_format_t format, const hicn_header_t *h,
+ size_t *header_length)
{
hicn_packet_get_header_length_from_format (format, header_length);
int is_ah = _is_ah (format);
@@ -184,15 +192,15 @@ hicn_packet_get_header_length (hicn_format_t format, const hicn_header_t * h,
// The signature payload is expressed as number of 32 bits words
if (is_ah && is_ipv4)
*header_length += (h->v4ah.ah.payloadlen) << 2;
- else if(is_ah && is_ipv6)
+ else if (is_ah && is_ipv6)
*header_length += (h->v6ah.ah.payloadlen) << 2;
return HICN_LIB_ERROR_NONE;
}
int
-hicn_packet_get_payload_length (hicn_format_t format, const hicn_header_t * h,
- size_t * payload_length)
+hicn_packet_get_payload_length (hicn_format_t format, const hicn_header_t *h,
+ size_t *payload_length)
{
hicn_type_t type = hicn_format_to_type (format);
return hicn_ops_vft[type.l1]->get_payload_length (type, &h->protocol,
@@ -200,7 +208,7 @@ hicn_packet_get_payload_length (hicn_format_t format, const hicn_header_t * h,
}
int
-hicn_packet_set_payload_length (hicn_format_t format, hicn_header_t * h,
+hicn_packet_set_payload_length (hicn_format_t format, hicn_header_t *h,
const size_t payload_length)
{
hicn_type_t type = hicn_format_to_type (format);
@@ -209,8 +217,8 @@ hicn_packet_set_payload_length (hicn_format_t format, hicn_header_t * h,
}
int
-hicn_packet_compare (const hicn_header_t * packet1,
- const hicn_header_t * packet2)
+hicn_packet_compare (const hicn_header_t *packet1,
+ const hicn_header_t *packet2)
{
hicn_type_t type1 = hicn_header_to_type (packet1);
hicn_type_t type2 = hicn_header_to_type (packet2);
@@ -233,25 +241,23 @@ hicn_packet_compare (const hicn_header_t * packet1,
return HICN_LIB_ERROR_UNEXPECTED;
return memcmp ((u8 *) packet1, (u8 *) packet2, len1);
-
}
int
-hicn_packet_get_name (hicn_format_t format, const hicn_header_t * h,
- hicn_name_t * name, u8 is_interest)
+hicn_packet_get_name (hicn_format_t format, const hicn_header_t *h,
+ hicn_name_t *name, u8 is_interest)
{
hicn_type_t type = hicn_format_to_type (format);
if (is_interest)
- return hicn_ops_vft[type.l1]->get_interest_name (type, &h->protocol,
- name);
+ return hicn_ops_vft[type.l1]->get_interest_name (type, &h->protocol, name);
else
return hicn_ops_vft[type.l1]->get_data_name (type, &h->protocol, name);
}
int
-hicn_packet_set_name (hicn_format_t format, hicn_header_t * h,
- const hicn_name_t * name, u8 is_interest)
+hicn_packet_set_name (hicn_format_t format, hicn_header_t *h,
+ const hicn_name_t *name, u8 is_interest)
{
hicn_type_t type = hicn_format_to_type (format);
@@ -261,23 +267,21 @@ hicn_packet_set_name (hicn_format_t format, hicn_header_t * h,
#endif /* HICN_VPP_PLUGIN */
if (is_interest)
- return hicn_ops_vft[type.l1]->set_interest_name (type, &h->protocol,
- name);
+ return hicn_ops_vft[type.l1]->set_interest_name (type, &h->protocol, name);
else
return hicn_ops_vft[type.l1]->set_data_name (type, &h->protocol, name);
}
int
-hicn_packet_set_payload (hicn_format_t format, hicn_header_t * h,
- const u8 * payload, u16 payload_length)
+hicn_packet_set_payload (hicn_format_t format, hicn_header_t *h,
+ const u8 *payload, u16 payload_length)
{
hicn_type_t type = hicn_format_to_type (format);
size_t header_length;
int rc;
- rc =
- hicn_ops_vft[type.l1]->get_header_length (type, &h->protocol,
- &header_length);
+ rc = hicn_ops_vft[type.l1]->get_header_length (type, &h->protocol,
+ &header_length);
if (rc < 0)
return rc;
@@ -288,22 +292,20 @@ hicn_packet_set_payload (hicn_format_t format, hicn_header_t * h,
}
int
-hicn_packet_get_payload (hicn_format_t format, const hicn_header_t * h,
- u8 ** payload, size_t * payload_size, bool hard_copy)
+hicn_packet_get_payload (hicn_format_t format, const hicn_header_t *h,
+ u8 **payload, size_t *payload_size, bool hard_copy)
{
size_t header_length, payload_length;
int rc;
hicn_type_t type = hicn_format_to_type (format);
- rc =
- hicn_ops_vft[type.l1]->get_header_length (type, &h->protocol,
- &header_length);
+ rc = hicn_ops_vft[type.l1]->get_header_length (type, &h->protocol,
+ &header_length);
if (rc < 0)
return rc;
- rc =
- hicn_ops_vft[type.l1]->get_payload_length (type, &h->protocol,
- &payload_length);
+ rc = hicn_ops_vft[type.l1]->get_payload_length (type, &h->protocol,
+ &payload_length);
if (rc < 0)
return rc;
@@ -320,23 +322,21 @@ hicn_packet_get_payload (hicn_format_t format, const hicn_header_t * h,
}
int
-hicn_packet_get_locator (hicn_format_t format, const hicn_header_t * h,
- ip_address_t * address, bool is_interest)
+hicn_packet_get_locator (hicn_format_t format, const hicn_header_t *h,
+ ip_address_t *address, bool is_interest)
{
int is_ipv4 = (format & HFO_INET);
int is_ipv6 = (format & HFO_INET6) >> 1;
if (is_ipv4)
{
- address->v4.as_inaddr = is_interest
- ? h->v4.ip.saddr.as_inaddr
- : h->v4.ip.daddr.as_inaddr;
+ address->v4.as_inaddr =
+ is_interest ? h->v4.ip.saddr.as_inaddr : h->v4.ip.daddr.as_inaddr;
}
else if (is_ipv6)
{
- address->v6.as_in6addr = is_interest
- ? h->v6.ip.saddr.as_in6addr
- : h->v6.ip.daddr.as_in6addr;
+ address->v6.as_in6addr =
+ is_interest ? h->v6.ip.saddr.as_in6addr : h->v6.ip.daddr.as_in6addr;
}
else
{
@@ -347,25 +347,25 @@ hicn_packet_get_locator (hicn_format_t format, const hicn_header_t * h,
}
int
-hicn_packet_set_locator (hicn_format_t format, hicn_header_t * h,
- const ip_address_t * address, bool is_interest)
+hicn_packet_set_locator (hicn_format_t format, hicn_header_t *h,
+ const ip_address_t *address, bool is_interest)
{
int is_ipv4 = (format & HFO_INET);
int is_ipv6 = (format & HFO_INET6) >> 1;
if (is_ipv6)
{
- if (is_interest)
- h->v6.ip.saddr.as_in6addr = address->v6.as_in6addr;
- else
- h->v6.ip.daddr.as_in6addr = address->v6.as_in6addr;
+ if (is_interest)
+ h->v6.ip.saddr.as_in6addr = address->v6.as_in6addr;
+ else
+ h->v6.ip.daddr.as_in6addr = address->v6.as_in6addr;
}
else if (is_ipv4)
{
- if (is_interest)
- h->v4.ip.saddr.as_inaddr = address->v4.as_inaddr;
- else
- h->v4.ip.daddr.as_inaddr = address->v4.as_inaddr;
+ if (is_interest)
+ h->v4.ip.saddr.as_inaddr = address->v4.as_inaddr;
+ else
+ h->v4.ip.daddr.as_inaddr = address->v4.as_inaddr;
}
else
{
@@ -376,79 +376,78 @@ hicn_packet_set_locator (hicn_format_t format, hicn_header_t * h,
}
int
-hicn_packet_get_signature_size (hicn_format_t format, const hicn_header_t * h,
- size_t * bytes)
+hicn_packet_get_signature_size (hicn_format_t format, const hicn_header_t *h,
+ size_t *bytes)
{
hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->get_signature_size (type, &h->protocol,
- bytes);
+ return hicn_ops_vft[type.l1]->get_signature_size (type, &h->protocol, bytes);
}
int
-hicn_packet_set_signature_size (hicn_format_t format, hicn_header_t * h,
+hicn_packet_set_signature_size (hicn_format_t format, hicn_header_t *h,
size_t bytes)
{
hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->set_signature_size (type, &h->protocol,
- bytes);
+ return hicn_ops_vft[type.l1]->set_signature_size (type, &h->protocol, bytes);
}
int
-hicn_packet_set_signature_timestamp (hicn_format_t format, hicn_header_t * h,
- uint64_t signature_timestamp)
+hicn_packet_set_signature_timestamp (hicn_format_t format, hicn_header_t *h,
+ uint64_t signature_timestamp)
{
hicn_type_t type = hicn_format_to_type (format);
return hicn_ops_vft[type.l1]->set_signature_timestamp (type, &h->protocol,
- signature_timestamp);
+ signature_timestamp);
}
int
-hicn_packet_get_signature_timestamp (hicn_format_t format, const hicn_header_t * h,
- uint64_t *signature_timestamp)
+hicn_packet_get_signature_timestamp (hicn_format_t format,
+ const hicn_header_t *h,
+ uint64_t *signature_timestamp)
{
hicn_type_t type = hicn_format_to_type (format);
return hicn_ops_vft[type.l1]->get_signature_timestamp (type, &h->protocol,
- signature_timestamp);
+ signature_timestamp);
}
int
-hicn_packet_set_validation_algorithm (hicn_format_t format, hicn_header_t * h,
- uint8_t validation_algorithm)
+hicn_packet_set_validation_algorithm (hicn_format_t format, hicn_header_t *h,
+ uint8_t validation_algorithm)
{
hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->set_validation_algorithm (type, &h->protocol,
- validation_algorithm);
+ return hicn_ops_vft[type.l1]->set_validation_algorithm (
+ type, &h->protocol, validation_algorithm);
}
int
-hicn_packet_get_validation_algorithm (hicn_format_t format, const hicn_header_t * h,
- uint8_t * validation_algorithm)
+hicn_packet_get_validation_algorithm (hicn_format_t format,
+ const hicn_header_t *h,
+ uint8_t *validation_algorithm)
{
hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->get_validation_algorithm (type, &h->protocol,
- validation_algorithm);
+ return hicn_ops_vft[type.l1]->get_validation_algorithm (
+ type, &h->protocol, validation_algorithm);
}
int
-hicn_packet_set_key_id (hicn_format_t format, hicn_header_t * h,
- uint8_t *key_id)
+hicn_packet_set_key_id (hicn_format_t format, hicn_header_t *h,
+ uint8_t *key_id)
{
hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->set_key_id (type, &h->protocol,
- key_id);
+ return hicn_ops_vft[type.l1]->set_key_id (type, &h->protocol, key_id);
}
int
-hicn_packet_get_key_id (hicn_format_t format, hicn_header_t * h,
- uint8_t ** key_id, uint8_t *key_id_length)
+hicn_packet_get_key_id (hicn_format_t format, hicn_header_t *h,
+ uint8_t **key_id, uint8_t *key_id_length)
{
hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->get_key_id (type, &h->protocol,
- key_id, key_id_length);
+ return hicn_ops_vft[type.l1]->get_key_id (type, &h->protocol, key_id,
+ key_id_length);
}
int
-hicn_packet_get_hoplimit (const hicn_header_t * h, u8 * hops)
+hicn_packet_get_hoplimit (const hicn_header_t *h, u8 *hops)
{
switch (HICN_IP_VERSION (h))
{
@@ -466,7 +465,7 @@ hicn_packet_get_hoplimit (const hicn_header_t * h, u8 * hops)
}
int
-hicn_packet_set_hoplimit (hicn_header_t * h, u8 hops)
+hicn_packet_set_hoplimit (hicn_header_t *h, u8 hops)
{
switch (HICN_IP_VERSION (h))
{
@@ -483,9 +482,8 @@ hicn_packet_set_hoplimit (hicn_header_t * h, u8 hops)
return HICN_LIB_ERROR_NONE;
}
-
int
-hicn_packet_get_lifetime (const hicn_header_t * h, u32 * lifetime)
+hicn_packet_get_lifetime (const hicn_header_t *h, u32 *lifetime)
{
hicn_type_t type = hicn_header_to_type (h);
return hicn_ops_vft[type.l1]->get_lifetime (type, &h->protocol,
@@ -493,7 +491,7 @@ hicn_packet_get_lifetime (const hicn_header_t * h, u32 * lifetime)
}
int
-hicn_packet_set_lifetime (hicn_header_t * h, u32 lifetime)
+hicn_packet_set_lifetime (hicn_header_t *h, u32 lifetime)
{
hicn_type_t type = hicn_header_to_type (h);
return hicn_ops_vft[type.l1]->set_lifetime (type, &h->protocol,
@@ -501,15 +499,15 @@ hicn_packet_set_lifetime (hicn_header_t * h, u32 lifetime)
}
int
-hicn_packet_get_reserved_bits (const hicn_header_t * h, u8 * reserved_bits)
+hicn_packet_get_reserved_bits (const hicn_header_t *h, u8 *reserved_bits)
{
switch (HICN_IP_VERSION (h))
{
case 6:
- *reserved_bits = (u8)(h->v6.tcp.reserved);
+ *reserved_bits = (u8) (h->v6.tcp.reserved);
break;
case 4:
- *reserved_bits = (u8)(h->v4.tcp.reserved);
+ *reserved_bits = (u8) (h->v4.tcp.reserved);
break;
default:
return HICN_LIB_ERROR_UNEXPECTED;
@@ -519,7 +517,7 @@ hicn_packet_get_reserved_bits (const hicn_header_t * h, u8 * reserved_bits)
}
int
-hicn_packet_set_reserved_bits (hicn_header_t * h, const u8 reserved_bits)
+hicn_packet_set_reserved_bits (hicn_header_t *h, const u8 reserved_bits)
{
switch (HICN_IP_VERSION (h))
{
@@ -537,16 +535,18 @@ hicn_packet_set_reserved_bits (hicn_header_t * h, const u8 reserved_bits)
}
int
-hicn_packet_get_payload_type (const hicn_header_t * h,
- hicn_payload_type_t * payload_type)
+hicn_packet_get_payload_type (const hicn_header_t *h,
+ hicn_payload_type_t *payload_type)
{
switch (HICN_IP_VERSION (h))
{
case 6:
- *payload_type = ((h->v6.tcp.flags & HICN_TCP_FLAG_URG) == HICN_TCP_FLAG_URG);
+ *payload_type =
+ ((h->v6.tcp.flags & HICN_TCP_FLAG_URG) == HICN_TCP_FLAG_URG);
break;
case 4:
- *payload_type = ((h->v4.tcp.flags & HICN_TCP_FLAG_URG) == HICN_TCP_FLAG_URG);
+ *payload_type =
+ ((h->v4.tcp.flags & HICN_TCP_FLAG_URG) == HICN_TCP_FLAG_URG);
break;
default:
return HICN_LIB_ERROR_UNEXPECTED;
@@ -561,7 +561,7 @@ hicn_packet_get_payload_type (const hicn_header_t * h,
}
int
-hicn_packet_set_payload_type (hicn_header_t * h,
+hicn_packet_set_payload_type (hicn_header_t *h,
hicn_payload_type_t payload_type)
{
if (payload_type != HPT_DATA && payload_type != HPT_MANIFEST)
@@ -591,8 +591,13 @@ hicn_packet_set_payload_type (hicn_header_t * h,
}
int
-hicn_packet_set_syn (hicn_header_t * h)
+hicn_packet_set_syn (hicn_format_t format, hicn_header_t *h)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -608,8 +613,13 @@ hicn_packet_set_syn (hicn_header_t * h)
}
int
-hicn_packet_reset_syn (hicn_header_t * h)
+hicn_packet_reset_syn (hicn_format_t format, hicn_header_t *h)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -625,8 +635,13 @@ hicn_packet_reset_syn (hicn_header_t * h)
}
int
-hicn_packet_test_syn (const hicn_header_t * h, bool * flag)
+hicn_packet_test_syn (hicn_format_t format, const hicn_header_t *h, bool *flag)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -642,8 +657,13 @@ hicn_packet_test_syn (const hicn_header_t * h, bool * flag)
}
int
-hicn_packet_set_ack (hicn_header_t * h)
+hicn_packet_set_ack (hicn_format_t format, hicn_header_t *h)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -659,8 +679,13 @@ hicn_packet_set_ack (hicn_header_t * h)
}
int
-hicn_packet_reset_ack (hicn_header_t * h)
+hicn_packet_reset_ack (hicn_format_t format, hicn_header_t *h)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -676,8 +701,13 @@ hicn_packet_reset_ack (hicn_header_t * h)
}
int
-hicn_packet_test_ack (const hicn_header_t * h, bool * flag)
+hicn_packet_test_ack (hicn_format_t format, const hicn_header_t *h, bool *flag)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -693,8 +723,13 @@ hicn_packet_test_ack (const hicn_header_t * h, bool * flag)
}
int
-hicn_packet_set_rst (hicn_header_t * h)
+hicn_packet_set_rst (hicn_format_t format, hicn_header_t *h)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -710,8 +745,13 @@ hicn_packet_set_rst (hicn_header_t * h)
}
int
-hicn_packet_reset_rst (hicn_header_t * h)
+hicn_packet_reset_rst (hicn_format_t format, hicn_header_t *h)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -727,8 +767,13 @@ hicn_packet_reset_rst (hicn_header_t * h)
}
int
-hicn_packet_test_rst (const hicn_header_t * h, bool * flag)
+hicn_packet_test_rst (hicn_format_t format, const hicn_header_t *h, bool *flag)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -744,8 +789,13 @@ hicn_packet_test_rst (const hicn_header_t * h, bool * flag)
}
int
-hicn_packet_set_fin (hicn_header_t * h)
+hicn_packet_set_fin (hicn_format_t format, hicn_header_t *h)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -761,8 +811,13 @@ hicn_packet_set_fin (hicn_header_t * h)
}
int
-hicn_packet_reset_fin (hicn_header_t * h)
+hicn_packet_reset_fin (hicn_format_t format, hicn_header_t *h)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -778,8 +833,13 @@ hicn_packet_reset_fin (hicn_header_t * h)
}
int
-hicn_packet_test_fin (const hicn_header_t * h, bool * flag)
+hicn_packet_test_fin (hicn_format_t format, const hicn_header_t *h, bool *flag)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -795,8 +855,13 @@ hicn_packet_test_fin (const hicn_header_t * h, bool * flag)
}
int
-hicn_packet_set_ece (hicn_header_t * h)
+hicn_packet_set_ece (hicn_format_t format, hicn_header_t *h)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -812,8 +877,13 @@ hicn_packet_set_ece (hicn_header_t * h)
}
int
-hicn_packet_reset_ece (hicn_header_t * h)
+hicn_packet_reset_ece (hicn_format_t format, hicn_header_t *h)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -829,8 +899,13 @@ hicn_packet_reset_ece (hicn_header_t * h)
}
int
-hicn_packet_test_ece (const hicn_header_t * h, bool * flag)
+hicn_packet_test_ece (hicn_format_t format, const hicn_header_t *h, bool *flag)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -846,8 +921,13 @@ hicn_packet_test_ece (const hicn_header_t * h, bool * flag)
}
int
-hicn_packet_set_src_port (hicn_header_t * h, u16 src_port)
+hicn_packet_set_src_port (hicn_format_t format, hicn_header_t *h, u16 src_port)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -863,8 +943,14 @@ hicn_packet_set_src_port (hicn_header_t * h, u16 src_port)
}
int
-hicn_packet_get_src_port (const hicn_header_t * h, u16 * src_port)
+hicn_packet_get_src_port (hicn_format_t format, const hicn_header_t *h,
+ u16 *src_port)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -880,8 +966,13 @@ hicn_packet_get_src_port (const hicn_header_t * h, u16 * src_port)
}
int
-hicn_packet_set_dst_port (hicn_header_t * h, u16 dst_port)
+hicn_packet_set_dst_port (hicn_format_t format, hicn_header_t *h, u16 dst_port)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -897,8 +988,14 @@ hicn_packet_set_dst_port (hicn_header_t * h, u16 dst_port)
}
int
-hicn_packet_get_dst_port (const hicn_header_t * h, u16 * dst_port)
+hicn_packet_get_dst_port (hicn_format_t format, const hicn_header_t *h,
+ u16 *dst_port)
{
+ if (!_is_tcp (format))
+ {
+ return HICN_LIB_ERROR_UNEXPECTED;
+ }
+
switch (HICN_IP_VERSION (h))
{
case 6:
@@ -914,8 +1011,8 @@ hicn_packet_get_dst_port (const hicn_header_t * h, u16 * dst_port)
}
int
-hicn_packet_copy_header (hicn_format_t format, const hicn_header_t * packet,
- hicn_header_t * destination, bool copy_ah)
+hicn_packet_copy_header (hicn_format_t format, const hicn_header_t *packet,
+ hicn_header_t *destination, bool copy_ah)
{
size_t header_length = _is_ipv4 (format) * IPV4_HDRLEN;
header_length += _is_ipv6 (format) * IPV6_HDRLEN;
@@ -929,95 +1026,95 @@ hicn_packet_copy_header (hicn_format_t format, const hicn_header_t * packet,
}
#define _INTEREST 1
-#define _DATA 0
+#define _DATA 0
/* Interest */
int
-hicn_interest_get_name (hicn_format_t format, const hicn_header_t * interest,
- hicn_name_t * name)
+hicn_interest_get_name (hicn_format_t format, const hicn_header_t *interest,
+ hicn_name_t *name)
{
return hicn_packet_get_name (format, interest, name, _INTEREST);
}
int
-hicn_interest_set_name (hicn_format_t format, hicn_header_t * interest,
- const hicn_name_t * name)
+hicn_interest_set_name (hicn_format_t format, hicn_header_t *interest,
+ const hicn_name_t *name)
{
- int ret_err = hicn_packet_reset_ece (interest); //interest packet -> ece flag unset
+ int ret_err =
+ hicn_packet_reset_ece (format, interest); // interest packet -> ece flag unset
if (ret_err < 0)
return HICN_LIB_ERROR_UNEXPECTED;
return hicn_packet_set_name (format, interest, name, _INTEREST);
}
int
-hicn_interest_get_locator (hicn_format_t format,
- const hicn_header_t * interest,
- ip_address_t * address)
+hicn_interest_get_locator (hicn_format_t format, const hicn_header_t *interest,
+ ip_address_t *address)
{
return hicn_packet_get_locator (format, interest, address, _INTEREST);
}
int
-hicn_interest_set_locator (hicn_format_t format, hicn_header_t * interest,
- const ip_address_t * address)
+hicn_interest_set_locator (hicn_format_t format, hicn_header_t *interest,
+ const ip_address_t *address)
{
return hicn_packet_set_locator (format, interest, address, _INTEREST);
}
int
-hicn_interest_compare (const hicn_header_t * interest_1,
- const hicn_header_t * interest_2)
+hicn_interest_compare (const hicn_header_t *interest_1,
+ const hicn_header_t *interest_2)
{
return hicn_packet_compare (interest_1, interest_2);
}
int
-hicn_interest_get_lifetime (const hicn_header_t * interest, u32 * lifetime)
+hicn_interest_get_lifetime (const hicn_header_t *interest, u32 *lifetime)
{
return hicn_packet_get_lifetime (interest, lifetime);
}
int
-hicn_interest_set_lifetime (hicn_header_t * interest, u32 lifetime)
+hicn_interest_set_lifetime (hicn_header_t *interest, u32 lifetime)
{
return hicn_packet_set_lifetime (interest, lifetime);
}
int
hicn_interest_get_header_length (hicn_format_t format,
- const hicn_header_t * interest,
- size_t * header_length)
+ const hicn_header_t *interest,
+ size_t *header_length)
{
return hicn_packet_get_header_length (format, interest, header_length);
}
int
hicn_interest_get_payload_length (hicn_format_t format,
- const hicn_header_t * interest,
- size_t * payload_length)
+ const hicn_header_t *interest,
+ size_t *payload_length)
{
return hicn_packet_get_payload_length (format, interest, payload_length);
}
int
-hicn_interest_get_payload (hicn_format_t format,
- const hicn_header_t * interest, u8 ** payload,
- size_t * payload_size, bool hard_copy)
+hicn_interest_get_payload (hicn_format_t format, const hicn_header_t *interest,
+ u8 **payload, size_t *payload_size, bool hard_copy)
{
return hicn_packet_get_payload (format, interest, payload, payload_size,
hard_copy);
}
int
-hicn_interest_set_payload (hicn_format_t format, hicn_header_t * interest,
- const u8 * payload, size_t payload_length)
+hicn_interest_set_payload (hicn_format_t format, hicn_header_t *interest,
+ const u8 *payload, size_t payload_length)
{
- return hicn_packet_set_payload (format, interest, payload, (u16)payload_length);
+ return hicn_packet_set_payload (format, interest, payload,
+ (u16) payload_length);
}
int
-hicn_interest_reset_for_hash (hicn_format_t format, hicn_header_t * packet)
+hicn_interest_reset_for_hash (hicn_format_t format, hicn_header_t *packet)
{
hicn_type_t type = hicn_format_to_type (format);
return hicn_ops_vft[type.l1]->reset_interest_for_hash (type,
@@ -1027,85 +1124,84 @@ hicn_interest_reset_for_hash (hicn_format_t format, hicn_header_t * packet)
/* Data */
int
-hicn_data_get_name (hicn_format_t format, const hicn_header_t * data,
- hicn_name_t * name)
+hicn_data_get_name (hicn_format_t format, const hicn_header_t *data,
+ hicn_name_t *name)
{
return hicn_packet_get_name (format, data, name, _DATA);
}
int
-hicn_data_set_name (hicn_format_t format, hicn_header_t * data,
- const hicn_name_t * name)
+hicn_data_set_name (hicn_format_t format, hicn_header_t *data,
+ const hicn_name_t *name)
{
- int ret_err = hicn_packet_set_ece (data); //data packet -> ece flag set
+ int ret_err = hicn_packet_set_ece (format, data); // data packet -> ece flag set
if (ret_err < 0)
return HICN_LIB_ERROR_UNEXPECTED;
return hicn_packet_set_name (format, data, name, _DATA);
}
int
-hicn_data_get_locator (hicn_format_t format, const hicn_header_t * data,
- ip_address_t * address)
+hicn_data_get_locator (hicn_format_t format, const hicn_header_t *data,
+ ip_address_t *address)
{
return hicn_packet_get_locator (format, data, address, _DATA);
}
int
-hicn_data_set_locator (hicn_format_t format, hicn_header_t * data,
- const ip_address_t * address)
+hicn_data_set_locator (hicn_format_t format, hicn_header_t *data,
+ const ip_address_t *address)
{
return hicn_packet_set_locator (format, data, address, _DATA);
}
int
-hicn_data_compare (const hicn_header_t * data_1, const hicn_header_t * data_2)
+hicn_data_compare (const hicn_header_t *data_1, const hicn_header_t *data_2)
{
return hicn_packet_compare (data_1, data_2);
}
int
-hicn_data_get_expiry_time (const hicn_header_t * data, u32 * expiry_time)
+hicn_data_get_expiry_time (const hicn_header_t *data, u32 *expiry_time)
{
return hicn_packet_get_lifetime (data, expiry_time);
}
int
-hicn_data_set_expiry_time (hicn_header_t * data, u32 expiry_time)
+hicn_data_set_expiry_time (hicn_header_t *data, u32 expiry_time)
{
return hicn_packet_set_lifetime (data, (hicn_lifetime_t) expiry_time);
}
int
-hicn_data_get_header_length (hicn_format_t format, hicn_header_t * data,
- size_t * header_length)
+hicn_data_get_header_length (hicn_format_t format, hicn_header_t *data,
+ size_t *header_length)
{
return hicn_packet_get_header_length (format, data, header_length);
}
int
-hicn_data_get_payload_length (hicn_format_t format,
- const hicn_header_t * data,
- size_t * payload_length)
+hicn_data_get_payload_length (hicn_format_t format, const hicn_header_t *data,
+ size_t *payload_length)
{
return hicn_packet_get_payload_length (format, data, payload_length);
}
int
-hicn_data_set_payload_type (hicn_header_t * data,
+hicn_data_set_payload_type (hicn_header_t *data,
hicn_payload_type_t payload_type)
{
return hicn_packet_set_payload_type (data, payload_type);
}
int
-hicn_data_get_payload_type (const hicn_header_t * data,
- hicn_payload_type_t * payload_type)
+hicn_data_get_payload_type (const hicn_header_t *data,
+ hicn_payload_type_t *payload_type)
{
return hicn_packet_get_payload_type (data, payload_type);
}
int
-hicn_data_get_path_label (const hicn_header_t * data, u32 * path_label)
+hicn_data_get_path_label (const hicn_header_t *data, u32 *path_label)
{
hicn_type_t type = hicn_header_to_type (data);
return hicn_ops_vft[type.l1]->get_data_pathlabel (type, &data->protocol,
@@ -1113,7 +1209,7 @@ hicn_data_get_path_label (const hicn_header_t * data, u32 * path_label)
}
int
-hicn_data_set_path_label (hicn_header_t * data, u32 path_label)
+hicn_data_set_path_label (hicn_header_t *data, u32 path_label)
{
hicn_type_t type = hicn_header_to_type (data);
return hicn_ops_vft[type.l1]->set_data_pathlabel (type, &data->protocol,
@@ -1121,34 +1217,34 @@ hicn_data_set_path_label (hicn_header_t * data, u32 path_label)
}
int
-hicn_data_set_payload (hicn_format_t format, hicn_header_t * data,
- const u8 * payload, size_t payload_length)
+hicn_data_set_payload (hicn_format_t format, hicn_header_t *data,
+ const u8 *payload, size_t payload_length)
{
- return hicn_packet_set_payload (format, data, payload, (u16)payload_length);
+ return hicn_packet_set_payload (format, data, payload, (u16) payload_length);
}
int
-hicn_data_get_payload (hicn_format_t format, const hicn_header_t * data,
- u8 ** payload, size_t * payload_size, bool hard_copy)
+hicn_data_get_payload (hicn_format_t format, const hicn_header_t *data,
+ u8 **payload, size_t *payload_size, bool hard_copy)
{
return hicn_packet_get_payload (format, data, payload, payload_size,
hard_copy);
}
int
-hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t * packet)
+hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t *packet)
{
hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->reset_data_for_hash (type,
- &packet->protocol);
-
+ return hicn_ops_vft[type.l1]->reset_data_for_hash (type, &packet->protocol);
}
-int hicn_packet_get_signature(hicn_format_t format, hicn_header_t * packet, uint8_t ** sign_buf)
+int
+hicn_packet_get_signature (hicn_format_t format, hicn_header_t *packet,
+ uint8_t **sign_buf)
{
hicn_type_t type = hicn_format_to_type (format);
- return hicn_ops_vft[type.l1]->get_signature (type,
- &packet->protocol, sign_buf);
+ return hicn_ops_vft[type.l1]->get_signature (type, &packet->protocol,
+ sign_buf);
}
/*
diff --git a/lib/src/name.c b/lib/src/name.c
index 9388c35e7..54b2a76aa 100644
--- a/lib/src/name.c
+++ b/lib/src/name.c
@@ -242,7 +242,7 @@ hicn_name_hash (const hicn_name_t * name, u32 * hash, bool consider_suffix)
int
hicn_name_empty (hicn_name_t * name)
{
- return name->type == HNT_UNSPEC ? HICN_LIB_ERROR_NONE : 1;
+ return name->type == HNT_UNSPEC ? 1 : 0;
}
int
diff --git a/lib/src/ops.c b/lib/src/ops.c
index 9bb78be65..d49138398 100644
--- a/lib/src/ops.c
+++ b/lib/src/ops.c
@@ -40,6 +40,8 @@ DECLARE_get_interest_name (none, NONE);
DECLARE_set_interest_name (none, NONE);
DECLARE_get_interest_name_suffix (none, NONE);
DECLARE_set_interest_name_suffix (none, NONE);
+DECLARE_mark_packet_as_interest (none, NONE);
+DECLARE_mark_packet_as_data (none, NONE);
DECLARE_reset_interest_for_hash (none, NONE);
DECLARE_get_data_locator (none, NONE);
DECLARE_set_data_locator (none, NONE);
diff --git a/lib/src/protocol/ah.c b/lib/src/protocol/ah.c
index c2f3f552a..03f3af04a 100644
--- a/lib/src/protocol/ah.c
+++ b/lib/src/protocol/ah.c
@@ -31,6 +31,8 @@ DECLARE_get_interest_name (ah, UNEXPECTED);
DECLARE_set_interest_name (ah, UNEXPECTED);
DECLARE_get_interest_name_suffix (ah, UNEXPECTED);
DECLARE_set_interest_name_suffix (ah, UNEXPECTED);
+DECLARE_mark_packet_as_interest (ah, UNEXPECTED)
+DECLARE_mark_packet_as_data (ah, UNEXPECTED)
DECLARE_get_data_locator (ah, UNEXPECTED);
DECLARE_set_data_locator (ah, UNEXPECTED);
DECLARE_get_data_name (ah, UNEXPECTED);
@@ -111,7 +113,7 @@ ah_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
int
ah_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
const ip46_address_t * addr_new, ip46_address_t * addr_old,
- const hicn_faceid_t face_id)
+ const hicn_faceid_t face_id, u8 reset_pl)
{
/* Nothing to do on signature */
return HICN_LIB_ERROR_NONE;
diff --git a/lib/src/protocol/icmp.c b/lib/src/protocol/icmp.c
index 85605a2c3..a16353427 100644
--- a/lib/src/protocol/icmp.c
+++ b/lib/src/protocol/icmp.c
@@ -25,6 +25,8 @@ DECLARE_get_interest_name (icmp, UNEXPECTED)
DECLARE_set_interest_name (icmp, UNEXPECTED)
DECLARE_get_interest_name_suffix (icmp, UNEXPECTED)
DECLARE_set_interest_name_suffix (icmp, UNEXPECTED)
+DECLARE_mark_packet_as_interest (icmp, UNEXPECTED)
+DECLARE_mark_packet_as_data (icmp, UNEXPECTED)
DECLARE_get_data_locator (icmp, UNEXPECTED)
DECLARE_set_data_locator (icmp, UNEXPECTED)
DECLARE_get_data_name (icmp, UNEXPECTED)
@@ -116,7 +118,7 @@ icmp_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
int
icmp_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
const ip46_address_t * addr_new, ip46_address_t * addr_old,
- const hicn_faceid_t face_id)
+ const hicn_faceid_t face_id, u8 reset_pl)
{
return HICN_LIB_ERROR_NOT_IMPLEMENTED;
// u16 *icmp_checksum = &(h->icmp.csum);
diff --git a/lib/src/protocol/ipv4.c b/lib/src/protocol/ipv4.c
index d8d958350..73ce12ee0 100644
--- a/lib/src/protocol/ipv4.c
+++ b/lib/src/protocol/ipv4.c
@@ -109,6 +109,18 @@ ipv4_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t * h,
}
int
+ipv4_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t * h)
+{
+ return CHILD_OPS (mark_packet_as_interest, type, h);
+}
+
+int
+ipv4_mark_packet_as_data (hicn_type_t type, hicn_protocol_t * h)
+{
+ return CHILD_OPS (mark_packet_as_data, type, h);
+}
+
+int
ipv4_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
{
/* Sets everything to 0 up to IP destination address */
@@ -312,7 +324,7 @@ ipv4_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
int
ipv4_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
const ip46_address_t * addr_new, ip46_address_t * addr_old,
- const hicn_faceid_t face_id)
+ const hicn_faceid_t face_id, u8 reset_pl)
{
// ASSERT(addr_old == NULL);
addr_old->ip4 = h->ipv4.daddr;
@@ -324,7 +336,7 @@ ipv4_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
h->ipv4.csum = 0;
h->ipv4.csum = csum (&h->ipv4, IPV4_HDRLEN, 0);
- return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id);
+ return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id, reset_pl);
}
int
diff --git a/lib/src/protocol/ipv6.c b/lib/src/protocol/ipv6.c
index 622355294..bf8123497 100644
--- a/lib/src/protocol/ipv6.c
+++ b/lib/src/protocol/ipv6.c
@@ -99,6 +99,18 @@ ipv6_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t * h,
}
int
+ipv6_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t * h)
+{
+ return CHILD_OPS (mark_packet_as_interest, type, h);
+}
+
+int
+ipv6_mark_packet_as_data (hicn_type_t type, hicn_protocol_t * h)
+{
+ return CHILD_OPS (mark_packet_as_data, type, h);
+}
+
+int
ipv6_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
{
/* Sets everything to 0 up to IP destination address */
@@ -208,19 +220,13 @@ ipv6_update_checksums (hicn_type_t type, hicn_protocol_t * h,
u16 partial_csum, size_t payload_length)
{
/* Retrieve payload length if not specified */
- if (payload_length == 0)
+ if (payload_length == ~0)
{
int rc = ipv6_get_payload_length (type, h, &payload_length);
if (rc < 0)
return rc;
}
- /* Ignore the payload if payload_length = ~0 */
- if (payload_length == ~0)
- {
- payload_length = 0;
- }
-
/* Build pseudo-header */
ipv6_pseudo_header_t psh;
psh.ip_src = h->ipv6.saddr;
@@ -246,7 +252,7 @@ ipv6_verify_checksums (hicn_type_t type, hicn_protocol_t * h,
u16 partial_csum, size_t payload_length)
{
/* Retrieve payload length if not specified */
- if (payload_length == 0)
+ if (payload_length == ~0)
{
int rc = ipv6_get_payload_length (type, h, &payload_length);
if (rc < 0)
@@ -264,7 +270,11 @@ ipv6_verify_checksums (hicn_type_t type, hicn_protocol_t * h,
pseudo.protocol = h->ipv6.nxt;
/* Compute partial checksum based on pseudo-header */
- partial_csum = csum (&pseudo, IPV6_PSHDRLEN, 0);
+ if (partial_csum != 0)
+ {
+ partial_csum = ~partial_csum;
+ }
+ partial_csum = csum (&pseudo, IPV6_PSHDRLEN, partial_csum);
return CHILD_OPS (verify_checksums, type, h, partial_csum, payload_length);
}
@@ -284,13 +294,13 @@ ipv6_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
int
ipv6_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
const ip46_address_t * addr_new, ip46_address_t * addr_old,
- const hicn_faceid_t face_id)
+ const hicn_faceid_t face_id, u8 reset_pl)
{
// ASSERT(addr_old == NULL);
addr_old->ip6 = h->ipv6.daddr;
h->ipv6.daddr = addr_new->ip6;
- return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id);
+ return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id, reset_pl);
}
int
diff --git a/lib/src/protocol/tcp.c b/lib/src/protocol/tcp.c
index 0e3155020..95f93c6af 100644
--- a/lib/src/protocol/tcp.c
+++ b/lib/src/protocol/tcp.c
@@ -45,18 +45,45 @@ DECLARE_get_length (tcp, UNEXPECTED);
DECLARE_get_payload_length (tcp, UNEXPECTED);
DECLARE_set_payload_length (tcp, UNEXPECTED);
+always_inline int
+check_tcp_checksum(u16 csum)
+{
+ /* As per RFC1624
+ * In one's complement, there are two representations of zero: the all
+ * zero and the all one bit values, often referred to as +0 and -0.
+ * One's complement addition of non-zero inputs can produce -0 as a
+ * result, but never +0. Since there is guaranteed to be at least one
+ * non-zero field in the IP header, and the checksum field in the
+ * protocol header is the complement of the sum, the checksum field can
+ * never contain ~(+0), which is -0 (0xFFFF). It can, however, contain
+ * ~(-0), which is +0 (0x0000).
+ */
+ if (csum == 0xffff)
+ {
+ /* Invalid checksum, no need to compute incremental update */
+ return HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED;
+ }
+
+ return HICN_LIB_ERROR_NONE;
+}
+
int
tcp_init_packet_header (hicn_type_t type, hicn_protocol_t * h)
{
- h->tcp = (_tcp_header_t)
- {
- .sport = htons (TCP_DEFAULT_SRC_PORT),.dport =
- htons (TCP_DEFAULT_DST_PORT),.seq = 0,.seq_ack =
- 0,.data_offset_and_reserved = TCP_DEFAULT_DATA_OFFSET_RES,.flags =
+ h->tcp = (_tcp_header_t) {
+ .sport = htons (TCP_DEFAULT_SRC_PORT),
+ .dport = htons (TCP_DEFAULT_DST_PORT),
+ .seq = 0,
+ .seq_ack = 0,
+ .data_offset_and_reserved = TCP_DEFAULT_DATA_OFFSET_RES,
+ .flags =
TCP_DEFAULT_CWR << 7 | TCP_DEFAULT_ECE << 6 | TCP_DEFAULT_URG << 5 |
TCP_DEFAULT_ACK << 4 | TCP_DEFAULT_PSH << 3 | TCP_DEFAULT_RST << 2 |
- TCP_DEFAULT_SYN << 1 | TCP_DEFAULT_FIN << 0,.window =
- htons (TCP_DEFAULT_WINDOW_SIZE),.csum = 0,.urg_ptr = 65000,};
+ TCP_DEFAULT_SYN << 1 | TCP_DEFAULT_FIN << 0,
+ .window = htons (TCP_DEFAULT_WINDOW_SIZE),
+ .csum = 0xffff,
+ .urg_ptr = 65000,
+ };
uint8_t ah_flag = type.l2 == IPPROTO_AH ? AH_FLAG : 0;
@@ -83,6 +110,20 @@ tcp_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t * h,
}
int
+tcp_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t * h)
+{
+ h->tcp.flags &= ~HICN_TCP_FLAG_ECE;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_mark_packet_as_data (hicn_type_t type, hicn_protocol_t * h)
+{
+ h->tcp.flags |= HICN_TCP_FLAG_ECE;
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
tcp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t * h)
{
memset (&(h->tcp), 0, 4);
@@ -129,12 +170,12 @@ tcp_update_data_pathlabel (hicn_type_t type, hicn_protocol_t * h,
const hicn_faceid_t face_id)
{
hicn_pathlabel_t pl =
- (hicn_pathlabel_t) ((h->tcp.pathlabel & HICN_PATH_LABEL_MASK) >> (32 -
- HICN_PATH_LABEL_SIZE));
+ (hicn_pathlabel_t) (h->tcp.seq_ack >> (32 - HICN_PATH_LABEL_SIZE));
+
hicn_pathlabel_t new_pl;
update_pathlabel (pl, face_id, &new_pl);
- h->tcp.pathlabel = new_pl;
+ h->tcp.seq_ack = (new_pl << (32 - HICN_PATH_LABEL_SIZE));
return HICN_LIB_ERROR_NONE;
}
@@ -208,7 +249,12 @@ int
tcp_verify_checksums (hicn_type_t type, hicn_protocol_t * h, u16 partial_csum,
size_t payload_length)
{
- if (csum (h, TCP_HDRLEN + payload_length, ~partial_csum) != 0)
+ if (PREDICT_TRUE (partial_csum != 0))
+ {
+ partial_csum = ~partial_csum;
+ }
+
+ if (csum (h, TCP_HDRLEN + payload_length, partial_csum) != 0)
return HICN_LIB_ERROR_CORRUPTED_PACKET;
return CHILD_OPS (verify_checksums, type, h, 0, payload_length);
}
@@ -238,6 +284,12 @@ tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
ip46_address_t * addr_old)
{
u16 *tcp_checksum = &(h->tcp.csum);
+ int ret = check_tcp_checksum(*tcp_checksum);
+
+ if (ret)
+ {
+ return ret;
+ }
/*
* Padding fields are set to zero so we can apply checksum on the
@@ -260,9 +312,23 @@ tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t * h,
int
tcp_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
const ip46_address_t * addr_new, ip46_address_t * addr_old,
- const hicn_faceid_t face_id)
+ const hicn_faceid_t face_id, u8 reset_pl)
{
+
u16 *tcp_checksum = &(h->tcp.csum);
+ int ret = check_tcp_checksum(*tcp_checksum);
+
+ /*
+ * update path label
+ */
+ u16 old_pl = h->tcp.seq_ack;
+ if(reset_pl) h->tcp.seq_ack = 0;
+ tcp_update_data_pathlabel (type, h, face_id);
+
+ if (ret)
+ {
+ return ret;
+ }
/*
* Padding fields are set to zero so we can apply checksum on the
@@ -277,9 +343,8 @@ tcp_rewrite_data (hicn_type_t type, hicn_protocol_t * h,
csum = ip_csum_add_even (csum, (ip_csum_t) (addr_new->ip6.as_u64[0]));
csum = ip_csum_add_even (csum, (ip_csum_t) (addr_new->ip6.as_u64[1]));
- csum = ip_csum_sub_even (csum, h->tcp.pathlabel);
- tcp_update_data_pathlabel (type, h, face_id);
- csum = ip_csum_add_even (csum, h->tcp.pathlabel);
+ csum = ip_csum_sub_even (csum, old_pl);
+ csum = ip_csum_add_even (csum, h->tcp.seq_ack);
*tcp_checksum = ip_csum_fold (csum);
diff --git a/lib/src/strategy.c b/lib/src/strategy.c
new file mode 100644
index 000000000..66ab232b5
--- /dev/null
+++ b/lib/src/strategy.c
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+/**
+ * \file strategy.c
+ * \brief Implementation of hICN forwarding strategy
+ */
+
+#include <hicn/core/strategy_vft.h>
+
+#include <hicn/strategies/load_balancer.h>
+#include <hicn/strategies/random.h>
+#include <hicn/strategies/low_latency.h>
+
+extern const strategy_ops_t strategy_load_balancer;
+extern const strategy_ops_t strategy_random;
+extern const strategy_ops_t strategy_low_latency;
+
+const strategy_ops_t * const strategy_vft[] = {
+ [STRATEGY_TYPE_LOADBALANCER] = &strategy_load_balancer,
+ [STRATEGY_TYPE_RANDOM] = &strategy_random,
+#if 0
+ [STRATEGY_TYPE_LOW_LATENCY] = &strategy_low_latency,
+#endif
+};
+
+
diff --git a/lib/src/util/ip_address.c b/lib/src/util/ip_address.c
index d4b34dc0b..1d123d8cd 100644
--- a/lib/src/util/ip_address.c
+++ b/lib/src/util/ip_address.c
@@ -302,7 +302,10 @@ ip_prefix_ntop(const ip_prefix_t * ip_prefix, char *dst, size_t size)
}
if (!s)
return -1;
- return snprintf(dst, size, "%s/%d", ip_s, ip_prefix->len);
+ int rc = snprintf(dst, size, "%s/%d", ip_s, ip_prefix->len);
+ if (rc >= size)
+ return (int)size;
+ return rc;
}
int
diff --git a/lib/src/util/windows/dlfcn.c b/lib/src/util/windows/dlfcn.c
new file mode 100644
index 000000000..c8173cdb0
--- /dev/null
+++ b/lib/src/util/windows/dlfcn.c
@@ -0,0 +1,65 @@
+/* dlfcn.c */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+
+static struct {
+ long lasterror;
+ const char *err_rutin;
+} var = {
+ 0,
+ NULL
+};
+
+void *dlopen (const char *filename, int flags)
+{
+ HINSTANCE hInst;
+
+ hInst= LoadLibrary (filename);
+ if (hInst==NULL) {
+ var.lasterror = GetLastError ();
+ var.err_rutin = "dlopen";
+ }
+ return hInst;
+}
+
+int dlclose (void *handle)
+{
+ BOOL ok;
+ int rc= 0;
+
+ ok= FreeLibrary ((HINSTANCE)handle);
+ if (! ok) {
+ var.lasterror = GetLastError ();
+ var.err_rutin = "dlclose";
+ rc= -1;
+ }
+ return rc;
+}
+
+void *dlsym (void *handle, const char *name)
+{
+ FARPROC fp;
+
+ fp= GetProcAddress ((HINSTANCE)handle, name);
+ if (!fp) {
+ var.lasterror = GetLastError ();
+ var.err_rutin = "dlsym";
+ }
+ return (void *)(intptr_t)fp;
+}
+
+const char *dlerror (void)
+{
+static char errstr [88];
+
+ if (var.lasterror) {
+ sprintf (errstr, "%s error #%ld", var.err_rutin, var.lasterror);
+ return errstr;
+ } else {
+ return NULL;
+ }
+} \ No newline at end of file
diff --git a/libtransport/CMakeLists.txt b/libtransport/CMakeLists.txt
index c431ace04..d94f2859b 100644
--- a/libtransport/CMakeLists.txt
+++ b/libtransport/CMakeLists.txt
@@ -44,58 +44,29 @@ set(TRANSPORT_LOG_LEVEL "INFO" CACHE STRING "Set log level")
set(TRANSPORT_ROOT_PATH "src")
-set(TRANSPORT_CORE ${TRANSPORT_ROOT_PATH}/core)
-set(TRANSPORT_TRANSPORT ${TRANSPORT_ROOT_PATH}/transport)
-set(TRANSPORT_ERRORS ${TRANSPORT_ROOT_PATH}/errors)
-set(TRANSPORT_UTILS ${TRANSPORT_ROOT_PATH}/utils)
-set(TRANSPORT_HTTP ${TRANSPORT_ROOT_PATH}/http)
-set(TRANSPORT_PORTABILITY ${TRANSPORT_ROOT_PATH}/portability)
-set(TRANSPORT_INTERFACES ${TRANSPORT_ROOT_PATH}/interfaces)
-
-# Install includes
-set(INSTALL_INCLUDE_DIR include/hicn/transport)
-
set(LIBTRANSPORT hicntransport)
if ((BUILD_HICNPLUGIN OR BUILD_MEMIF_CONNECTOR) AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(__vpp__ 1)
- set(LIBTRANSPORT ${LIBTRANSPORT}-memif)
- find_package(Vpp REQUIRED)
-
- list(APPEND LIBTRANSPORT_INTERNAL_INCLUDE_DIRS
- ${VPP_INCLUDE_DIRS}
- )
endif ()
set(LIBTRANSPORT ${LIBTRANSPORT} CACHE INTERNAL "" FORCE)
+if (NOT WIN32)
set(LIBTRANSPORT_SHARED ${LIBTRANSPORT}.shared CACHE INTERNAL "" FORCE)
+endif ()
set(LIBTRANSPORT_STATIC ${LIBTRANSPORT}.static CACHE INTERNAL "" FORCE)
set(LIBTRANSPORT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src CACHE INTERNAL "" FORCE)
include(WindowsMacros)
include(IosMacros)
+
find_package_wrapper(Libparc REQUIRED)
find_package_wrapper(Asio REQUIRED)
find_package(OpenSSL REQUIRED)
-
-if (${OPENSSL_VERSION} VERSION_EQUAL "1.1.1a" OR ${OPENSSL_VERSION} VERSION_GREATER "1.1.1a")
- set(SECURE_HICNTRANSPORT 1)
-endif()
-
-if (__vpp__)
- find_package(Libmemif REQUIRED)
-endif()
+find_package(Threads REQUIRED)
+find_package(OpenSSL REQUIRED)
+find_package(Libconfig++ REQUIRED)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- if (__vpp__)
- find_package(HicnPlugin REQUIRED)
- find_package(SafeVapi REQUIRED)
-
- list(APPEND LIBRARIES
- ${LIBMEMIF_LIBRARIES}
- ${SAFE_VAPI_LIBRARIES}
- )
- endif()
-
find_package_wrapper(Libhicn REQUIRED)
else()
if (DISABLE_SHARED_LIBRARIES)
@@ -110,55 +81,32 @@ else()
else()
set(HICN_LIBRARIES ${LIBHICN_SHARED})
list(APPEND DEPENDENCIES
+
${LIBHICN_SHARED}
)
-
- if (__vpp__)
- list(APPEND DEPENDENCIES
- hicn_plugin
- ${SAFE_VAPI_SHARED}
- )
-
- list(APPEND LIBRARIES
- ${LIBMEMIF_LIBRARIES}
- ${SAFE_VAPI_LIBRARIES}
- )
- endif()
endif()
endif()
-
-list(APPEND LIBTRANSPORT_INTERNAL_INCLUDE_DIRS
- ${LIBMEMIF_INCLUDE_DIRS}
- ${SAFE_VAPI_INCLUDE_DIRS}
-)
-
-include(Packaging)
-
-find_package(Threads REQUIRED)
-
-if (${COMPILE_TESTS})
- include(TestMacros)
- find_package(GTest REQUIRED)
- list(APPEND LIBTRANSPORT_INTERNAL_INCLUDE_DIRS
- ${GTEST_INCLUDE_DIRS}
- )
-endif()
-
-if(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
- find_package(OpenSSL REQUIRED)
+if (WIN32)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4275 /wd4996 /wd4311 /wd4302")
+ if (CMAKE_BUILD_TYPE EQUAL "RELEASE")
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:\"MSVCRTD\"" )
+ endif ()
endif ()
+include(Packaging)
list(APPEND LIBRARIES
+ ${HICN_LIBRARIES}
${LIBPARC_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
- ${HICN_LIBRARIES}
${VPP_LIBRARIES}
${ANDROID_LIBRARIES}
${OPENSSL_LIBRARIES}
${WINDOWS_LIBRARIES}
- ${LIBHICNCTRL_LIBRARIES}
+ ${LIBCONFIG_CPP_LIBRARIES}
)
+set(LIBTRANSPORT_LIBRARIES_LIST "${LIBPARC_LIBRARIES};${CMAKE_THREAD_LIBS_INIT};${VPP_LIBRARIES};${ANDROID_LIBRARIES};${OPENSSL_LIBRARIES};${WINDOWS_LIBRARIES};${LIBCONFIG_CPP_LIBRARIES}" CACHE INTERNAL "LIBTRANSPORT_LIBRARIES_LIST")
+
# Include dirs -- Order does matter!
list(APPEND LIBTRANSPORT_INTERNAL_INCLUDE_DIRS
${HICN_INCLUDE_DIRS}
@@ -168,6 +116,7 @@ list(APPEND LIBTRANSPORT_INTERNAL_INCLUDE_DIRS
${ASIO_INCLUDE_DIRS}
${WINDOWS_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIR}
+ ${CONFIG_INCLUDE_DIRS}
)
add_subdirectory(includes/hicn/transport)
diff --git a/libtransport/cmake/Modules/DefaultConfiguration.cmake b/libtransport/cmake/Modules/DefaultConfiguration.cmake
index f0d535251..93dd90164 100644
--- a/libtransport/cmake/Modules/DefaultConfiguration.cmake
+++ b/libtransport/cmake/Modules/DefaultConfiguration.cmake
@@ -15,9 +15,6 @@
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_C_STANDARD 11)
-# Compilation options
-option(COMPILE_TESTS "Compile functional tests" OFF)
-
# Compilation flags
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
diff --git a/libtransport/cmake/Modules/Packaging.cmake b/libtransport/cmake/Modules/Packaging.cmake
index 274eb4c59..e24172661 100644
--- a/libtransport/cmake/Modules/Packaging.cmake
+++ b/libtransport/cmake/Modules/Packaging.cmake
@@ -32,22 +32,22 @@ set(lib${LIBTRANSPORT}-devel_DESCRIPTION ${lib${LIBTRANSPORT}_DESCRIPTION}
if ((BUILD_MEMIF_CONNECTOR OR BUILD_HICNPLUGIN) AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(lib${LIBTRANSPORT}_DEB_DEPENDENCIES
- "lib${LIBHICN} (>= stable_version), libparc (>= 1.0), libmemif (>= stable_version), vpp (>= stable_version-release), vpp (<< next_version-release), libhicnctrl-memif (>= stable_version-release), libhicnctrl-memif (<< next_version-release)"
+ "lib${LIBHICN} (>= stable_version), libparc (>= 1.0), libmemif (>= stable_version), vpp (>= stable_version-release), vpp (<< next_version-release), hicn-plugin (>= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(lib${LIBTRANSPORT}_RPM_DEPENDENCIES
- "lib${LIBHICN} >= stable_version, libparc >= 1.0, libmemif >= stable_version, vpp >= stable_version-release, vpp < next_version-release, libhicnctrl-memif >= stable_version-release, libhicnctrl-memif < stable_version-release"
+ "lib${LIBHICN} >= stable_version, libparc >= 1.0, libmemif >= stable_version, vpp >= stable_version-release, vpp < next_version-release, hicn-plugin >= stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
set(lib${LIBTRANSPORT}-dev_DEB_DEPENDENCIES
- "lib${LIBTRANSPORT} (>= stable_version), libasio-dev (>= 1.10), libhicn-dev (>= stable_version), libmemif-dev (>= stable_version), libparc-dev (>= 1.0), vpp-dev (>= stable_version-release), vpp-dev (<< next_version-release), hicn-plugin-dev (>= stable_version-release), hicn-plugin-dev (<< next_version-release)"
+ "lib${LIBTRANSPORT} (>= stable_version), libasio-dev (>= 1.10), libhicn-dev (>= stable_version), libmemif-dev (>= stable_version), libparc-dev (>= 1.0), vpp-dev (>= stable_version-release), vpp-dev (<< next_version-release), hicn-plugin-dev (>= stable_version)"
CACHE STRING "Dependencies for deb/rpm package."
)
set(lib${LIBTRANSPORT}-dev_RPM_DEPENDENCIES
- "lib${LIBTRANSPORT} >= stable_version, asio-devel >= 1.10, lib${LIBHICN}-devel >= stable_version, libmemif-devel >= stable_version, libparc-devel >= 1.0, vpp-devel >= stable_version-release, vpp-devel < next_version-release, hicn-plugin-dev >= stable_version-release, hicn-plugin-dev < next_version-release"
+ "lib${LIBTRANSPORT} >= stable_version, asio-devel >= 1.10, lib${LIBHICN}-devel >= stable_version, libmemif-devel >= stable_version, libparc-devel >= 1.0, vpp-devel >= stable_version-release, vpp-devel < next_version-release, hicn-plugin-dev >= stable_version"
CACHE STRING "Dependencies for deb/rpm package."
)
diff --git a/libtransport/includes/hicn/transport/CMakeLists.txt b/libtransport/includes/hicn/transport/CMakeLists.txt
index 1099e701d..ca53bdffd 100644
--- a/libtransport/includes/hicn/transport/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/CMakeLists.txt
@@ -22,7 +22,7 @@ add_subdirectory(errors)
add_subdirectory(http)
add_subdirectory(interfaces)
add_subdirectory(portability)
-add_subdirectory(security)
+add_subdirectory(auth)
add_subdirectory(utils)
set(LIBTRANSPORT_INCLUDE_DIRS
@@ -35,4 +35,4 @@ set(LIBHICNTRANSPORT_TO_INSTALL_HEADER_FILES
${HEADER_FILES} ""
CACHE INTERNAL
"" FORCE
-) \ No newline at end of file
+)
diff --git a/libtransport/includes/hicn/transport/auth/CMakeLists.txt b/libtransport/includes/hicn/transport/auth/CMakeLists.txt
new file mode 100644
index 000000000..d855125b0
--- /dev/null
+++ b/libtransport/includes/hicn/transport/auth/CMakeLists.txt
@@ -0,0 +1,29 @@
+# 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.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/common.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hash_type.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/crypto_hasher.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/crypto_suite.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/identity.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/key_id.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/policies.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/signer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/verifier.h
+)
+
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
diff --git a/hicn-plugin/src/faces/ip/iface_ip_node.h b/libtransport/includes/hicn/transport/auth/common.h
index 36923f069..911bcbc6a 100644
--- a/hicn-plugin/src/faces/ip/iface_ip_node.h
+++ b/libtransport/includes/hicn/transport/auth/common.h
@@ -13,23 +13,17 @@
* limitations under the License.
*/
-#ifndef __HICN_IFACE_IP_NODE_H__
-#define __HICN_IFACE_IP_NODE_H__
+#pragma once
-#include <vlib/vlib.h>
-#include <vnet/vnet.h>
+#include <hicn/transport/core/packet.h>
-/**
- * @brief Initialize the ip iface module
- */
-void hicn_iface_ip_init (vlib_main_t * vm);
+namespace transport {
+namespace auth {
-#endif // __HICN_IFACE_IP_NODE_H__
+using Hash = std::vector<uint8_t>;
+using HashEntry = std::pair<CryptoHashType, Hash>;
+using PacketPtr = core::Packet *;
+using Suffix = uint32_t;
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/auth/crypto_hash.h b/libtransport/includes/hicn/transport/auth/crypto_hash.h
new file mode 100644
index 000000000..26c251b38
--- /dev/null
+++ b/libtransport/includes/hicn/transport/auth/crypto_hash.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.
+ */
+
+#pragma once
+
+#include <hicn/transport/errors/runtime_exception.h>
+#include <hicn/transport/portability/portability.h>
+#include <hicn/transport/auth/crypto_hash_type.h>
+#include <hicn/transport/utils/array.h>
+
+extern "C" {
+#include <parc/security/parc_CryptoHash.h>
+};
+
+#include <cstring>
+#include <unordered_map>
+
+namespace transport {
+namespace auth {
+
+class CryptoHasher;
+
+struct EnumClassHash {
+ template <typename T>
+ std::size_t operator()(T t) const {
+ return static_cast<std::size_t>(t);
+ }
+};
+
+static std::unordered_map<CryptoHashType, std::size_t, EnumClassHash>
+ hash_size_map = {{CryptoHashType::SHA_256, 32},
+ {CryptoHashType::CRC32C, 4},
+ {CryptoHashType::SHA_512, 64}};
+
+class Signer;
+class Verifier;
+
+class CryptoHash {
+ friend class CryptoHasher;
+ friend class Signer;
+ friend class Verifier;
+
+ public:
+ CryptoHash() : hash_(nullptr) {}
+
+ CryptoHash(const CryptoHash& other) {
+ if (other.hash_) {
+ hash_ = parcCryptoHash_Acquire(other.hash_);
+ }
+ }
+
+ CryptoHash(CryptoHash&& other) {
+ if (other.hash_) {
+ hash_ = parcCryptoHash_Acquire(other.hash_);
+ }
+ }
+
+ template <typename T>
+ CryptoHash(const T* buffer, std::size_t length, CryptoHashType hash_type) {
+ hash_ = parcCryptoHash_CreateFromArray(
+ static_cast<PARCCryptoHashType>(hash_type), buffer, length);
+ }
+
+ ~CryptoHash() {
+ if (hash_) {
+ parcCryptoHash_Release(&hash_);
+ }
+ }
+
+ CryptoHash& operator=(const CryptoHash& other) {
+ if (other.hash_) {
+ hash_ = parcCryptoHash_Acquire(other.hash_);
+ }
+
+ return *this;
+ }
+
+ template <typename T>
+ utils::Array<T> getDigest() const {
+ return utils::Array<T>(
+ static_cast<T*>(parcBuffer_Overlay(parcCryptoHash_GetDigest(hash_), 0)),
+ parcBuffer_Remaining(parcCryptoHash_GetDigest(hash_)));
+ }
+
+ CryptoHashType getType() {
+ return static_cast<CryptoHashType>(parcCryptoHash_GetDigestType(hash_));
+ }
+
+ template <typename T>
+ static bool compareBinaryDigest(const T* digest1, const T* digest2,
+ CryptoHashType hash_type) {
+ if (hash_size_map.find(hash_type) == hash_size_map.end()) {
+ return false;
+ }
+
+ return !static_cast<bool>(
+ std::memcmp(digest1, digest2, hash_size_map[hash_type]));
+ }
+
+ TRANSPORT_ALWAYS_INLINE void display() {
+ parcBuffer_Display(parcCryptoHash_GetDigest(hash_), 2);
+ }
+
+ private:
+ PARCCryptoHash* hash_;
+};
+
+} // namespace auth
+} // namespace transport
diff --git a/hicn-plugin/src/faces/udp/iface_udp_node.h b/libtransport/includes/hicn/transport/auth/crypto_hash_type.h
index 957d19217..9d792624e 100644
--- a/hicn-plugin/src/faces/udp/iface_udp_node.h
+++ b/libtransport/includes/hicn/transport/auth/crypto_hash_type.h
@@ -13,24 +13,23 @@
* limitations under the License.
*/
-#ifndef __HICN_IFACE_UDP_H__
-#define __HICN_IFACE_UDP_H__
+#pragma once
-#include <vlib/vlib.h>
+extern "C" {
+#include <parc/security/parc_CryptoHashType.h>
+};
-extern vlib_node_registration_t hicn_iface_udp4_input_node;
-extern vlib_node_registration_t hicn_iface_udp6_input_node;
-extern vlib_node_registration_t hicn_iface_udp4_output_node;
-extern vlib_node_registration_t hicn_iface_udp6_output_node;
+#include <cstdint>
-void hicn_iface_udp_init (vlib_main_t * vm);
+namespace transport {
+namespace auth {
-#endif // __HICN_FACE_UDP_H__
+enum class CryptoHashType : uint8_t {
+ SHA_256 = PARCCryptoHashType_SHA256,
+ SHA_512 = PARCCryptoHashType_SHA512,
+ CRC32C = PARCCryptoHashType_CRC32C,
+ NULL_HASH = PARCCryptoHashType_NULL
+};
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/auth/crypto_hasher.h b/libtransport/includes/hicn/transport/auth/crypto_hasher.h
new file mode 100644
index 000000000..ada1a6ee8
--- /dev/null
+++ b/libtransport/includes/hicn/transport/auth/crypto_hasher.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/auth/crypto_hash.h>
+
+extern "C" {
+#include <parc/security/parc_CryptoHasher.h>
+};
+
+namespace transport {
+namespace auth {
+
+class CryptoHasher {
+ public:
+ CryptoHasher(CryptoHashType hash_type)
+ : hasher_(parcCryptoHasher_Create(
+ static_cast<PARCCryptoHashType>(hash_type))),
+ managed_(true) {}
+
+ CryptoHasher(PARCCryptoHasher* hasher) : hasher_(hasher), managed_(false) {}
+
+ ~CryptoHasher() {
+ if (managed_) {
+ parcCryptoHasher_Release(&hasher_);
+ }
+ }
+
+ CryptoHasher& init() {
+ if (parcCryptoHasher_Init(hasher_) == -1) {
+ throw errors::RuntimeException("Cryptohash init failed.");
+ }
+
+ return *this;
+ }
+
+ template <typename T>
+ CryptoHasher& updateBytes(const T* buffer, std::size_t length) {
+ if (parcCryptoHasher_UpdateBytes(hasher_, buffer, length) == -1) {
+ throw errors::RuntimeException("Cryptohash updateBytes failed.");
+ }
+ return *this;
+ }
+
+ CryptoHash finalize() {
+ CryptoHash hash;
+ hash.hash_ = parcCryptoHasher_Finalize(hasher_);
+ return hash;
+ }
+
+ private:
+ PARCCryptoHasher* hasher_;
+ bool managed_;
+};
+
+} // namespace auth
+} // namespace transport
diff --git a/hicn-plugin/src/faces/ip/face_ip_node.h b/libtransport/includes/hicn/transport/auth/crypto_suite.h
index 000395a04..11df6ac06 100644
--- a/hicn-plugin/src/faces/ip/face_ip_node.h
+++ b/libtransport/includes/hicn/transport/auth/crypto_suite.h
@@ -13,28 +13,27 @@
* limitations under the License.
*/
-#ifndef __HICN_FACE_IP_NODE_H__
-#define __HICN_FACE_IP_NODE_H__
+#pragma once
-#include <vlib/vlib.h>
-#include <vnet/vnet.h>
+extern "C" {
+#include <parc/security/parc_CryptoSuite.h>
+};
-extern vlib_node_registration_t hicn_face_ip4_input_node;
-extern vlib_node_registration_t hicn_face_ip4_output_node;
-extern vlib_node_registration_t hicn_face_ip6_input_node;
-extern vlib_node_registration_t hicn_face_ip6_output_node;
+#include <cstdint>
-/**
- * @brief Initialize the ip face module
- */
-void hicn_face_ip_init (vlib_main_t * vm);
+namespace transport {
+namespace auth {
-#endif // __HICN_FACE_IP_NODE_H__
+enum class CryptoSuite : uint8_t {
+ RSA_SHA256 = PARCCryptoSuite_RSA_SHA256,
+ DSA_SHA256 = PARCCryptoSuite_DSA_SHA256,
+ RSA_SHA512 = PARCCryptoSuite_RSA_SHA512,
+ HMAC_SHA256 = PARCCryptoSuite_HMAC_SHA256,
+ HMAC_SHA512 = PARCCryptoSuite_HMAC_SHA512,
+ NULL_CRC32C = PARCCryptoSuite_NULL_CRC32C,
+ ECDSA_256K1 = PARCCryptoSuite_ECDSA_SHA256,
+ UNKNOWN = PARCCryptoSuite_UNKNOWN
+};
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/auth/identity.h b/libtransport/includes/hicn/transport/auth/identity.h
new file mode 100644
index 000000000..19157952e
--- /dev/null
+++ b/libtransport/includes/hicn/transport/auth/identity.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/auth/signer.h>
+
+extern "C" {
+#include <parc/security/parc_Identity.h>
+#include <parc/security/parc_IdentityFile.h>
+#include <parc/security/parc_Pkcs12KeyStore.h>
+#include <parc/security/parc_Security.h>
+};
+
+namespace transport {
+namespace auth {
+
+class Identity {
+ // This class holds several information about a client, including its public
+ // key.
+ public:
+ // Generate a new identity from the given parameters. The identity will be
+ // saved in 'keystore_path' and encrypted using 'keystore_pwd'.
+ Identity(const std::string &keystore_path, const std::string &keystore_pwd,
+ CryptoSuite suite, unsigned int signature_len,
+ unsigned int validity_days, const std::string &subject_name);
+
+ // Create an identity from an already existing keystore path.
+ Identity(std::string &keystore_path, std::string &keystore_pwd,
+ CryptoHashType hash_type);
+
+ Identity(const Identity &other);
+ Identity(Identity &&other);
+ ~Identity();
+
+ // Return the asymmetric signer object created from the public key.
+ std::shared_ptr<AsymmetricSigner> getSigner() const;
+
+ // Return the key store filename.
+ std::string getFilename() const;
+
+ // Return the key store password.
+ std::string getPassword() const;
+
+ // Generate a new random identity.
+ static Identity generateIdentity(const std::string &subject_name = "");
+
+ private:
+ PARCIdentity *identity_;
+ std::shared_ptr<AsymmetricSigner> signer_;
+};
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/auth/key_id.h b/libtransport/includes/hicn/transport/auth/key_id.h
new file mode 100644
index 000000000..3aa09336f
--- /dev/null
+++ b/libtransport/includes/hicn/transport/auth/key_id.h
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <utility>
+
+namespace transport {
+namespace auth {
+
+using KeyId = std::pair<uint8_t *, uint8_t>;
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/auth/policies.h b/libtransport/includes/hicn/transport/auth/policies.h
new file mode 100644
index 000000000..00464d54b
--- /dev/null
+++ b/libtransport/includes/hicn/transport/auth/policies.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace transport {
+namespace auth {
+
+/**
+ * These policies allows the verifier to tell the transport what action to
+ * perform after verification.
+ */
+enum class VerificationPolicy {
+ ABORT,
+ ACCEPT,
+ DROP,
+ UNKNOWN,
+};
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/auth/signer.h b/libtransport/includes/hicn/transport/auth/signer.h
new file mode 100644
index 000000000..fd5c4e6c6
--- /dev/null
+++ b/libtransport/includes/hicn/transport/auth/signer.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/auth/common.h>
+#include <hicn/transport/errors/errors.h>
+
+extern "C" {
+#include <parc/security/parc_PublicKeySigner.h>
+#include <parc/security/parc_Security.h>
+#include <parc/security/parc_Signer.h>
+#include <parc/security/parc_SymmetricKeySigner.h>
+}
+
+namespace transport {
+namespace auth {
+
+class Signer {
+ // The base class from which all signer classes derive.
+ public:
+ Signer();
+
+ Signer(PARCSigner *signer);
+
+ virtual ~Signer();
+
+ // Sign a packet.
+ virtual void signPacket(PacketPtr packet);
+
+ // Set the signer object used to sign packets.
+ void setSigner(PARCSigner *signer);
+
+ // Return the signature size.
+ size_t getSignatureSize() const;
+
+ // Return the crypto suite associated to the signer.
+ CryptoSuite getCryptoSuite() const;
+
+ // Return the hash algorithm associated to the signer.
+ CryptoHashType getCryptoHashType() const;
+
+ // Return the PARC signer.
+ PARCSigner *getParcSigner() const;
+
+ // Return the PARC key store containing the signer key.
+ PARCKeyStore *getParcKeyStore() const;
+
+ protected:
+ PARCSigner *signer_;
+ PARCKeyId *key_id_;
+};
+
+class AsymmetricSigner : public Signer {
+ // This class uses asymmetric verification to sign packets. The public key
+ // must be given from a PARCKeyStore.
+ public:
+ AsymmetricSigner() = default;
+ AsymmetricSigner(PARCSigner *signer) : Signer(signer){};
+
+ // Construct an AsymmetricSigner from a key store and a given crypto suite.
+ AsymmetricSigner(CryptoSuite suite, PARCKeyStore *key_store);
+};
+
+class SymmetricSigner : public Signer {
+ // This class uses symmetric verification to sign packets. The symmetric
+ // key is derived from a passphrase.
+ public:
+ SymmetricSigner() = default;
+ SymmetricSigner(PARCSigner *signer) : Signer(signer){};
+
+ // Construct an SymmetricSigner from a key store and a given crypto suite.
+ SymmetricSigner(CryptoSuite suite, PARCKeyStore *key_store);
+
+ // Construct an AsymmetricSigner from a passphrase and a given crypto suite.
+ SymmetricSigner(CryptoSuite suite, const std::string &passphrase);
+};
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/auth/verifier.h b/libtransport/includes/hicn/transport/auth/verifier.h
new file mode 100644
index 000000000..e6e561918
--- /dev/null
+++ b/libtransport/includes/hicn/transport/auth/verifier.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/auth/common.h>
+#include <hicn/transport/auth/policies.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/errors/errors.h>
+#include <hicn/transport/interfaces/callbacks.h>
+
+#include <algorithm>
+
+extern "C" {
+#include <parc/security/parc_CertificateFactory.h>
+#include <parc/security/parc_InMemoryVerifier.h>
+#include <parc/security/parc_Security.h>
+#include <parc/security/parc_SymmetricKeySigner.h>
+#include <parc/security/parc_Verifier.h>
+}
+
+namespace transport {
+namespace auth {
+
+class Verifier {
+ // The base class from which all verifier classes derive.
+ public:
+ // The VerificationFailedCallback will be called by the transport if a data
+ // packet (either a manifest or a content object) cannot be verified. The
+ // application decides what to do then by returning a VerificationPolicy
+ // object.
+ using VerificationFailedCallback = std::function<auth::VerificationPolicy(
+ const core::ContentObject &content_object, std::error_code ec)>;
+
+ // The list of VerificationPolicy that will trigger the
+ // VerificationFailedCallback.
+ static const std::vector<VerificationPolicy> DEFAULT_FAILED_POLICIES;
+
+ Verifier();
+
+ virtual ~Verifier();
+
+ // Verify a single packet and return whether or not the packet signature is
+ // valid.
+ virtual bool verifyPacket(PacketPtr packet);
+
+ // Verify a batch of packets. Return a vector with the same size as the packet
+ // list, element i of that vector will contain the VerificationPolicy for
+ // packet i.
+ virtual std::vector<VerificationPolicy> verifyPackets(
+ const std::vector<PacketPtr> &packets);
+ VerificationPolicy verifyPackets(PacketPtr packet) {
+ return verifyPackets(std::vector<PacketPtr>{packet}).front();
+ }
+
+ // Verify that a batch of packets are valid using a map from packet suffixes
+ // to hashes. A packet is considered valid if its hash correspond to the hash
+ // present in the map. Return a vector with the same size as the packet list,
+ // element i of that vector will contain the VerificationPolicy for packet i.
+ virtual std::vector<VerificationPolicy> verifyPackets(
+ const std::vector<PacketPtr> &packets,
+ const std::unordered_map<Suffix, HashEntry> &suffix_map);
+ VerificationPolicy verifyPackets(
+ PacketPtr packet,
+ const std::unordered_map<Suffix, HashEntry> &suffix_map) {
+ return verifyPackets(std::vector<PacketPtr>{packet}, suffix_map).front();
+ }
+
+ // Add a general PARC key which can be used to verify packet signatures.
+ void addKey(PARCKey *key);
+
+ // Set the hasher object used to compute packet hashes.
+ void setHasher(PARCCryptoHasher *hasher);
+
+ // Set the callback for the case packet verification fails.
+ void setVerificationFailedCallback(
+ VerificationFailedCallback verification_failed_cb,
+ const std::vector<VerificationPolicy> &failed_policies =
+ DEFAULT_FAILED_POLICIES);
+
+ // Retrieve the VerificationFailedCallback function.
+ void getVerificationFailedCallback(
+ VerificationFailedCallback **verification_failed_cb);
+
+ static size_t getSignatureSize(const PacketPtr);
+
+ protected:
+ PARCCryptoHasher *hasher_;
+ PARCVerifier *verifier_;
+ VerificationFailedCallback verification_failed_cb_;
+ std::vector<VerificationPolicy> failed_policies_;
+
+ // Internally compute a packet hash using the hasher object.
+ virtual CryptoHash computeHash(PacketPtr packet);
+
+ // Call VerificationFailedCallback if it is set and update the packet policy.
+ void callVerificationFailedCallback(PacketPtr packet,
+ VerificationPolicy &policy);
+};
+
+class VoidVerifier : public Verifier {
+ // This class is the default socket verifier. It ignores completely the packet
+ // signature and always returns true.
+ public:
+ bool verifyPacket(PacketPtr packet) override;
+
+ std::vector<VerificationPolicy> verifyPackets(
+ const std::vector<PacketPtr> &packets) override;
+
+ std::vector<VerificationPolicy> verifyPackets(
+ const std::vector<PacketPtr> &packets,
+ const std::unordered_map<Suffix, HashEntry> &suffix_map) override;
+};
+
+class AsymmetricVerifier : public Verifier {
+ // This class uses asymmetric verification to validate packets. The public key
+ // can be set directly or extracted from a certificate.
+ public:
+ AsymmetricVerifier() = default;
+
+ // Add a public key to the verifier.
+ AsymmetricVerifier(PARCKey *pub_key);
+
+ // Construct an AsymmetricVerifier from a certificate file.
+ AsymmetricVerifier(const std::string &cert_path);
+
+ // Extract the public key of a certificate file.
+ void setCertificate(const std::string &cert_path);
+};
+
+class SymmetricVerifier : public Verifier {
+ // This class uses symmetric verification to validate packets. The symmetric
+ // key is derived from a passphrase.
+ public:
+ SymmetricVerifier() = default;
+
+ // Construct a SymmetricVerifier from a passphrase.
+ SymmetricVerifier(const std::string &passphrase);
+
+ ~SymmetricVerifier();
+
+ // Create and set a symmetric key from a passphrase.
+ void setPassphrase(const std::string &passphrase);
+
+ // Construct a signer object. Passphrase must be set beforehand.
+ void setSigner(const PARCCryptoSuite &suite);
+
+ virtual std::vector<VerificationPolicy> verifyPackets(
+ const std::vector<PacketPtr> &packets) override;
+
+ protected:
+ PARCBuffer *passphrase_;
+ PARCSigner *signer_;
+};
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/core/CMakeLists.txt b/libtransport/includes/hicn/transport/core/CMakeLists.txt
index cb10745ff..2553b7dcd 100644
--- a/libtransport/includes/hicn/transport/core/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/core/CMakeLists.txt
@@ -20,6 +20,10 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/packet.h
${CMAKE_CURRENT_SOURCE_DIR}/payload_type.h
${CMAKE_CURRENT_SOURCE_DIR}/prefix.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/io_module.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/connector.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/endpoint.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/global_object_pool.h
)
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/core/connector.h b/libtransport/includes/hicn/transport/core/connector.h
new file mode 100644
index 000000000..dcf38cdc8
--- /dev/null
+++ b/libtransport/includes/hicn/transport/core/connector.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/connector_stats.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/core/endpoint.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/core/interest.h>
+#include <hicn/transport/core/packet.h>
+#include <hicn/transport/portability/platform.h>
+#include <hicn/transport/utils/membuf.h>
+#include <hicn/transport/utils/object_pool.h>
+#include <hicn/transport/utils/ring_buffer.h>
+#include <hicn/transport/utils/shared_ptr_utils.h>
+
+#include <deque>
+#include <functional>
+
+namespace transport {
+
+namespace core {
+
+class Connector : public std::enable_shared_from_this<Connector> {
+ public:
+ enum class Type : uint8_t {
+ SOCKET_CONNECTOR,
+ MEMIF_CONNECTOR,
+ LOOPBACK_CONNECTOR,
+ };
+
+ enum class State : std::uint8_t {
+ CLOSED,
+ CONNECTING,
+ CONNECTED,
+ };
+
+ enum class Role : std::uint8_t { CONSUMER, PRODUCER };
+
+ public:
+ static constexpr std::size_t queue_size = 4096;
+ static constexpr std::uint32_t invalid_connector = ~0;
+
+#ifdef LINUX
+ static constexpr std::uint16_t max_burst = 256;
+#endif
+
+ using Ptr = std::shared_ptr<Connector>;
+ using PacketQueue = std::deque<Packet::Ptr>;
+ using PacketReceivedCallback = std::function<void(
+ Connector *, utils::MemBuf &, const std::error_code &)>;
+ using PacketSentCallback =
+ std::function<void(Connector *, const std::error_code &)>;
+ using OnCloseCallback = std::function<void(Connector *)>;
+ using OnReconnectCallback = std::function<void(Connector *)>;
+ using Id = std::uint64_t;
+
+ template <typename ReceiveCallback, typename SentCallback, typename OnClose,
+ typename OnReconnect>
+ Connector(ReceiveCallback &&receive_callback, SentCallback &&packet_sent,
+ OnClose &&close_callback, OnReconnect &&on_reconnect)
+ : receive_callback_(std::forward<ReceiveCallback &&>(receive_callback)),
+ sent_callback_(std::forward<SentCallback &&>(packet_sent)),
+ on_close_callback_(std::forward<OnClose &&>(close_callback)),
+ on_reconnect_callback_(std::forward<OnReconnect &&>(on_reconnect)),
+ state_(State::CLOSED),
+ connector_id_(invalid_connector) {}
+
+ virtual ~Connector(){};
+
+ template <typename ReceiveCallback>
+ void setReceiveCallback(ReceiveCallback &&callback) {
+ receive_callback_ = std::forward<ReceiveCallback &&>(callback);
+ }
+
+ template <typename SentCallback>
+ void setSentCallback(SentCallback &&callback) {
+ sent_callback_ = std::forward<SentCallback &&>(callback);
+ }
+
+ template <typename OnClose>
+ void setOnCloseCallback(OnClose &&callback) {
+ on_close_callback_ = std::forward<OnClose &&>(callback);
+ }
+
+ template <typename OnReconnect>
+ void setReconnectCallback(const OnReconnect &&callback) {
+ on_reconnect_callback_ = std::forward<OnReconnect>(callback);
+ }
+
+ const PacketReceivedCallback &getReceiveCallback() const {
+ return receive_callback_;
+ }
+
+ const PacketSentCallback &getSentCallback() { return sent_callback_; }
+
+ const OnCloseCallback &getOnCloseCallback() { return on_close_callback_; }
+
+ const OnReconnectCallback &getOnReconnectCallback() {
+ return on_reconnect_callback_;
+ }
+
+ virtual void send(Packet &packet) = 0;
+
+ virtual void send(const uint8_t *packet, std::size_t len) = 0;
+
+ virtual void close() = 0;
+
+ virtual State state() { return state_; };
+
+ virtual bool isConnected() { return state_ == State::CONNECTED; }
+
+ void setConnectorId(Id connector_id) { connector_id_ = connector_id; }
+
+ Id getConnectorId() { return connector_id_; }
+
+ void setConnectorName(std::string connector_name) {
+ connector_name_ = connector_name;
+ }
+
+ std::string getConnectorName() { return connector_name_; }
+
+ Endpoint getLocalEndpoint() { return local_endpoint_; }
+
+ Endpoint getRemoteEndpoint() { return remote_endpoint_; }
+
+ void setRole(Role r) { role_ = r; }
+
+ Role getRole() { return role_; }
+
+ static utils::MemBuf::Ptr getPacketFromBuffer(uint8_t *buffer,
+ std::size_t size) {
+ utils::MemBuf::Ptr ret;
+
+ auto format = Packet::getFormatFromBuffer(buffer, size);
+
+ if (TRANSPORT_EXPECT_TRUE(format != HF_UNSPEC && !_is_icmp(format))) {
+ if (Packet::isInterest(buffer)) {
+ ret = core::PacketManager<>::getInstance()
+ .getPacketFromExistingBuffer<Interest>(buffer, size);
+ } else {
+ ret = core::PacketManager<>::getInstance()
+ .getPacketFromExistingBuffer<ContentObject>(buffer, size);
+ }
+ } else {
+ ret = core::PacketManager<>::getInstance().getMemBuf(buffer, size);
+ }
+
+ return ret;
+ }
+
+ static std::pair<uint8_t *, std::size_t> getRawBuffer() {
+ return core::PacketManager<>::getInstance().getRawBuffer();
+ }
+
+ protected:
+ inline void sendSuccess(const utils::MemBuf &packet) {
+ stats_.tx_packets_.fetch_add(1, std::memory_order_relaxed);
+ stats_.tx_bytes_.fetch_add(packet.length(), std::memory_order_relaxed);
+ }
+
+ inline void receiveSuccess(const utils::MemBuf &packet) {
+ stats_.rx_packets_.fetch_add(1, std::memory_order_relaxed);
+ stats_.rx_bytes_.fetch_add(packet.length(), std::memory_order_relaxed);
+ }
+
+ inline void sendFailed() {
+ stats_.drops_.fetch_add(1, std::memory_order_relaxed);
+ }
+
+ protected:
+ PacketQueue output_buffer_;
+
+ // Connector events
+ PacketReceivedCallback receive_callback_;
+ PacketSentCallback sent_callback_;
+ OnCloseCallback on_close_callback_;
+ OnReconnectCallback on_reconnect_callback_;
+
+ // Connector state
+ std::atomic<State> state_;
+ Id connector_id_;
+
+ // Endpoints
+ Endpoint local_endpoint_;
+ Endpoint remote_endpoint_;
+
+ // Connector name
+ std::string connector_name_;
+
+ // Connector role
+ Role role_;
+
+ // Stats
+ AtomicConnectorStats stats_;
+};
+
+} // namespace core
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/core/connector_stats.h b/libtransport/includes/hicn/transport/core/connector_stats.h
new file mode 100644
index 000000000..1985331e9
--- /dev/null
+++ b/libtransport/includes/hicn/transport/core/connector_stats.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ */
+
+#pragma once
+
+#include <atomic>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace transport {
+namespace core {
+
+struct AtomicConnectorStats {
+ AtomicConnectorStats()
+ : tx_packets_(0), tx_bytes_(0), rx_packets_(0), rx_bytes_(0), drops_(0) {}
+ std::atomic<uint64_t> tx_packets_;
+ std::atomic<uint64_t> tx_bytes_;
+ std::atomic<uint64_t> rx_packets_;
+ std::atomic<uint64_t> rx_bytes_;
+ std::atomic<uint64_t> drops_;
+};
+
+struct ConnectorStats {
+ ConnectorStats()
+ : tx_packets_(0), tx_bytes_(0), rx_packets_(0), rx_bytes_(0), drops_(0) {}
+ std::uint64_t tx_packets_;
+ std::uint64_t tx_bytes_;
+ std::uint64_t rx_packets_;
+ std::uint64_t rx_bytes_;
+ std::uint64_t drops_;
+};
+
+using TableEntry = std::tuple<std::string, std::uint64_t, std::uint64_t,
+ std::uint64_t, std::uint64_t, std::uint64_t>;
+using StatisticTable = std::vector<TableEntry>;
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/core/content_object.h b/libtransport/includes/hicn/transport/core/content_object.h
index 822790e56..805bc814c 100644
--- a/libtransport/includes/hicn/transport/core/content_object.h
+++ b/libtransport/includes/hicn/transport/core/content_object.h
@@ -17,6 +17,7 @@
#include <hicn/transport/core/name.h>
#include <hicn/transport/core/packet.h>
+#include <hicn/transport/utils/shared_ptr_utils.h>
namespace transport {
@@ -27,24 +28,53 @@ namespace core {
class ContentObject : public Packet {
public:
- using Ptr = utils::ObjectPool<ContentObject>::Ptr;
+ using Ptr = std::shared_ptr<ContentObject>;
using HICNContentObject = hicn_header_t;
- ContentObject(Packet::Format format = HF_INET6_TCP);
+ ContentObject(Packet::Format format = HF_INET6_TCP,
+ std::size_t additional_header_size = 0);
- ContentObject(const Name &name, Packet::Format format = HF_INET6_TCP);
+ ContentObject(const Name &name, Packet::Format format = HF_INET6_TCP,
+ std::size_t additional_header_size = 0);
- ContentObject(const Name &name, hicn_format_t format, const uint8_t *payload,
+ ContentObject(const Name &name, hicn_format_t format,
+ std::size_t additional_header_size, const uint8_t *payload,
std::size_t payload_size);
- ContentObject(const uint8_t *buffer, std::size_t size);
- ContentObject(MemBufPtr &&buffer);
-
- ContentObject(const ContentObject &content_object) = delete;
+ template <typename... Args>
+ ContentObject(CopyBufferOp op, Args &&...args)
+ : Packet(op, std::forward<Args>(args)...) {
+ if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
+ 0) {
+ throw errors::MalformedPacketException();
+ }
+ }
+
+ template <typename... Args>
+ ContentObject(WrapBufferOp op, Args &&...args)
+ : Packet(op, std::forward<Args>(args)...) {
+ if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
+ 0) {
+ throw errors::MalformedPacketException();
+ }
+ }
+
+ template <typename... Args>
+ ContentObject(CreateOp op, Args &&...args)
+ : Packet(op, std::forward<Args>(args)...) {
+ if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
+ 0) {
+ throw errors::MalformedPacketException();
+ }
+ }
+
+ ContentObject(const ContentObject &content_object);
+
+ ContentObject &operator=(const ContentObject &other);
ContentObject(ContentObject &&content_object);
- ~ContentObject() override;
+ ~ContentObject();
const Name &getName() const override;
@@ -66,6 +96,8 @@ class ContentObject : public Packet {
uint32_t getLifetime() const override;
+ auto shared_from_this() { return utils::shared_from(this); }
+
private:
void resetForHash() override;
};
diff --git a/libtransport/includes/hicn/transport/core/endpoint.h b/libtransport/includes/hicn/transport/core/endpoint.h
new file mode 100644
index 000000000..4a19744a7
--- /dev/null
+++ b/libtransport/includes/hicn/transport/core/endpoint.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef ASIO_STANDALONE
+#define ASIO_STANDALONE
+#endif
+#include <asio.hpp>
+
+namespace transport {
+
+namespace core {
+
+const uint16_t INVALID_PORT = 0xffff;
+
+class Endpoint {
+ public:
+ Endpoint() : address_(), port_(INVALID_PORT) {}
+
+ Endpoint(const Endpoint &other)
+ : address_(other.address_), port_(other.port_) {}
+
+ Endpoint(Endpoint &&other)
+ : address_(std::move(other.address_)), port_(other.port_) {}
+
+ Endpoint(std::string ip_address, uint32_t port)
+ : address_(asio::ip::address::from_string(ip_address)), port_(port) {}
+
+ Endpoint(asio::ip::udp::endpoint endpoint)
+ : address_(endpoint.address()), port_(endpoint.port()) {}
+
+ ~Endpoint() = default;
+
+ Endpoint &operator=(const Endpoint &other) {
+ address_ = other.address_;
+ port_ = other.port_;
+ return *this;
+ }
+
+ Endpoint &operator=(Endpoint &&other) {
+ address_ = std::move(other.address_);
+ port_ = std::move(other.port_);
+ return *this;
+ }
+
+#if 0
+ template <typename Ip, typename Port>
+ Endpoint(Ip &&ip_address, Port &&port)
+ : address_(std::forward<Ip &&>(ip_address)),
+ port_(std::forward<Port &&>(port)) {}
+#endif
+
+ asio::ip::address getAddress() { return address_; }
+ uint16_t getPort() { return port_; }
+
+ void setAddress(uint32_t address) {
+ address_ = asio::ip::address(asio::ip::address_v4(address));
+ }
+
+ void setPort(uint16_t port) { port_ = port; }
+
+ private:
+ asio::ip::address address_;
+ uint16_t port_;
+};
+} // namespace core
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/core/global_object_pool.h b/libtransport/includes/hicn/transport/core/global_object_pool.h
new file mode 100644
index 000000000..e0b6e373f
--- /dev/null
+++ b/libtransport/includes/hicn/transport/core/global_object_pool.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/packet.h>
+#include <hicn/transport/utils/fixed_block_allocator.h>
+#include <hicn/transport/utils/singleton.h>
+
+#include <array>
+#include <mutex>
+
+namespace transport {
+
+namespace core {
+
+template <std::size_t packet_pool_size = 1024, std::size_t chunk_size = 2048>
+class PacketManager
+ : public utils::Singleton<PacketManager<packet_pool_size, chunk_size>> {
+ friend class utils::Singleton<PacketManager<packet_pool_size, chunk_size>>;
+
+ public:
+ using MemoryPool = utils::FixedBlockAllocator<chunk_size, packet_pool_size>;
+ using RawBuffer = std::pair<uint8_t *, std::size_t>;
+
+ struct PacketStorage {
+ std::array<uint8_t, 256> packet_and_shared_ptr;
+ std::max_align_t align;
+ };
+
+ utils::MemBuf::Ptr getMemBuf() {
+ utils::MemBuf *memory = nullptr;
+
+ memory = reinterpret_cast<utils::MemBuf *>(memory_pool_.allocateBlock());
+
+ utils::STLAllocator<utils::MemBuf, MemoryPool> allocator(memory,
+ &memory_pool_);
+ auto offset = offsetof(PacketStorage, align);
+ auto ret = std::allocate_shared<utils::MemBuf>(
+ allocator, utils::MemBuf::WRAP_BUFFER, (uint8_t *)memory + offset, 0,
+ chunk_size - offset);
+ ret->clear();
+
+ return ret;
+ }
+
+ utils::MemBuf::Ptr getMemBuf(uint8_t *buffer, std::size_t length) {
+ auto offset = offsetof(PacketStorage, align);
+ auto memory = buffer - offset;
+ utils::STLAllocator<utils::MemBuf, MemoryPool> allocator(
+ (utils::MemBuf *)memory, &memory_pool_);
+ auto ret = std::allocate_shared<utils::MemBuf>(
+ allocator, utils::MemBuf::WRAP_BUFFER, (uint8_t *)buffer, length,
+ chunk_size - offset);
+
+ return ret;
+ }
+
+ template <
+ typename PacketType, typename... Args,
+ typename = std::enable_if_t<std::is_base_of<Packet, PacketType>::value>>
+ typename PacketType::Ptr getPacket(Args &&...args) {
+ PacketType *memory = nullptr;
+
+ memory = reinterpret_cast<PacketType *>(memory_pool_.allocateBlock());
+ utils::STLAllocator<PacketType, MemoryPool> allocator(memory,
+ &memory_pool_);
+ auto offset = offsetof(PacketStorage, align);
+ auto ret = std::allocate_shared<PacketType>(
+ allocator, PacketType::CREATE, (uint8_t *)memory + offset, 0,
+ chunk_size - offset, std::forward<Args>(args)...);
+
+ return ret;
+ }
+
+ std::pair<uint8_t *, std::size_t> getRawBuffer() {
+ uint8_t *memory = nullptr;
+ memory = reinterpret_cast<uint8_t *>(memory_pool_.allocateBlock());
+
+ auto offset = offsetof(PacketStorage, align);
+ memory += offset;
+
+ return std::make_pair(memory, chunk_size - offset);
+ }
+
+ template <typename PacketType, typename... Args>
+ typename PacketType::Ptr getPacketFromExistingBuffer(uint8_t *buffer,
+ std::size_t length,
+ Args &&...args) {
+ auto offset = offsetof(PacketStorage, align);
+ auto memory = reinterpret_cast<PacketType *>(buffer - offset);
+ utils::STLAllocator<PacketType, MemoryPool> allocator(memory,
+ &memory_pool_);
+ auto ret = std::allocate_shared<PacketType>(
+ allocator, PacketType::WRAP_BUFFER, (uint8_t *)buffer, length,
+ chunk_size - offset, std::forward<Args>(args)...);
+
+ return ret;
+ }
+
+ private:
+ PacketManager(std::size_t size = packet_pool_size)
+ : memory_pool_(MemoryPool::getInstance()), size_(0) {}
+ MemoryPool &memory_pool_;
+ std::atomic<size_t> size_;
+};
+
+} // end namespace core
+
+} // end namespace transport
diff --git a/libtransport/includes/hicn/transport/core/interest.h b/libtransport/includes/hicn/transport/core/interest.h
index c572afbff..b41b0c94a 100644
--- a/libtransport/includes/hicn/transport/core/interest.h
+++ b/libtransport/includes/hicn/transport/core/interest.h
@@ -17,6 +17,9 @@
#include <hicn/transport/core/name.h>
#include <hicn/transport/core/packet.h>
+#include <hicn/transport/utils/shared_ptr_utils.h>
+
+#include <set>
namespace transport {
@@ -24,25 +27,57 @@ namespace core {
class Interest
: public Packet /*, public std::enable_shared_from_this<Interest>*/ {
- public:
- using Ptr = utils::ObjectPool<Interest>::Ptr;
-
- Interest(Packet::Format format = HF_INET6_TCP);
-
- Interest(const Name &interest_name, Packet::Format format = HF_INET6_TCP);
+ private:
+ struct InterestManifestHeader {
+ /* This can be 16 bits, but we use 32 bits for alignment */
+ uint32_t n_suffixes;
+ /* Followed by the list of prefixes to ask */
+ /* ... */
+ };
- Interest(const uint8_t *buffer, std::size_t size);
- Interest(MemBufPtr &&buffer);
+ public:
+ using Ptr = std::shared_ptr<Interest>;
+
+ Interest(Packet::Format format = HF_INET6_TCP,
+ std::size_t additional_header_size = 0);
+
+ Interest(const Name &interest_name, Packet::Format format = HF_INET6_TCP,
+ std::size_t additional_header_size = 0);
+
+ Interest(MemBuf &&buffer);
+
+ template <typename... Args>
+ Interest(CopyBufferOp op, Args &&...args)
+ : Packet(op, std::forward<Args>(args)...) {
+ if (hicn_interest_get_name(format_, packet_start_,
+ name_.getStructReference()) < 0) {
+ throw errors::MalformedPacketException();
+ }
+ }
+
+ template <typename... Args>
+ Interest(WrapBufferOp op, Args &&...args)
+ : Packet(op, std::forward<Args>(args)...) {
+ if (hicn_interest_get_name(format_, packet_start_,
+ name_.getStructReference()) < 0) {
+ throw errors::MalformedPacketException();
+ }
+ }
+
+ template <typename... Args>
+ Interest(CreateOp op, Args &&...args)
+ : Packet(op, std::forward<Args>(args)...) {}
+
+ /* Move constructor */
+ Interest(Interest &&other_interest);
- /*
- * Enforce zero-copy.
- */
- Interest(const Interest &other_interest) = delete;
- Interest &operator=(const Interest &other_interest) = delete;
+ /* Copy constructor */
+ Interest(const Interest &other_interest);
- Interest(Interest &&other_interest);
+ /* Assginemnt operator */
+ Interest &operator=(const Interest &other);
- ~Interest() override;
+ ~Interest();
const Name &getName() const override;
@@ -60,8 +95,21 @@ class Interest
uint32_t getLifetime() const override;
+ bool hasManifest();
+
+ void appendSuffix(std::uint32_t suffix);
+
+ void encodeSuffixes();
+
+ uint32_t *firstSuffix();
+
+ uint32_t numberOfSuffixes();
+
+ auto shared_from_this() { return utils::shared_from(this); }
+
private:
void resetForHash() override;
+ std::set<uint32_t> suffix_set_;
};
} // end namespace core
diff --git a/libtransport/includes/hicn/transport/core/io_module.h b/libtransport/includes/hicn/transport/core/io_module.h
new file mode 100644
index 000000000..d4c3bb03a
--- /dev/null
+++ b/libtransport/includes/hicn/transport/core/io_module.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/connector.h>
+#include <hicn/transport/core/packet.h>
+#include <hicn/transport/core/prefix.h>
+#include <hicn/transport/portability/portability.h>
+#include <hicn/transport/utils/chrono_typedefs.h>
+#include <hicn/transport/utils/membuf.h>
+
+#include <deque>
+
+#ifndef ASIO_STANDALONE
+#define ASIO_STANDALONE
+#endif
+#include <asio/io_service.hpp>
+
+namespace transport {
+
+namespace core {
+
+typedef struct {
+ uint64_t rx_packets;
+ uint64_t tx_packets;
+ uint64_t rx_bytes;
+ uint64_t tx_bytes;
+ uint64_t rx_errors;
+ uint64_t tx_errors;
+} Counters;
+
+class Connector;
+
+class IoModule {
+ protected:
+ IoModule()
+ : inet_address_({}),
+ inet6_address_({}),
+ mtu_(1500),
+ output_interface_(""),
+ content_store_reserved_(5000) {
+ inet_address_.v4.as_u32 = htonl(0x7f00001);
+ inet6_address_.v6.as_u8[15] = 0x01;
+ }
+
+ public:
+ static IoModule *load(const char *);
+ static bool unload(IoModule *);
+
+ public:
+ virtual ~IoModule();
+
+ virtual void connect(bool is_consumer = true) = 0;
+
+ virtual bool isConnected() = 0;
+
+ virtual void init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::OnReconnectCallback &&reconnect_callback,
+ asio::io_service &io_service,
+ const std::string &app_name = "Libtransport") = 0;
+
+ virtual void registerRoute(const Prefix &prefix) = 0;
+
+ virtual std::uint32_t getMtu() = 0;
+
+ virtual bool isControlMessage(const uint8_t *message) = 0;
+
+ virtual void processControlMessageReply(utils::MemBuf &packet_buffer) = 0;
+
+ virtual void closeConnection() = 0;
+
+ virtual void send(Packet &packet) {
+ counters_.tx_packets++;
+ counters_.tx_bytes += packet.payloadSize() + packet.headerSize();
+
+ if (_is_ipv4(packet.getFormat())) {
+ packet.setLocator(inet_address_);
+ } else {
+ packet.setLocator(inet6_address_);
+ }
+ }
+
+ virtual void send(const uint8_t *packet, std::size_t len) = 0;
+
+ void setContentStoreSize(uint32_t cs_size) {
+ content_store_reserved_ = cs_size;
+ }
+
+ uint32_t getContentStoreSize() const { return content_store_reserved_; }
+
+ void setOutputInterface(const std::string &interface) {
+ output_interface_ = interface;
+ }
+
+ const std::string &getOutputInterface() { return output_interface_; }
+
+#ifndef ANDROID
+ private:
+ void *handle_;
+#endif
+
+ protected:
+ ip_address_t inet_address_;
+ ip_address_t inet6_address_;
+ uint16_t mtu_;
+ std::string output_interface_;
+ uint32_t content_store_reserved_;
+ Counters counters_;
+};
+
+extern "C" IoModule *createModule();
+
+} // namespace core
+} // namespace transport
diff --git a/libtransport/includes/hicn/transport/core/name.h b/libtransport/includes/hicn/transport/core/name.h
index ea72797ad..033582289 100644
--- a/libtransport/includes/hicn/transport/core/name.h
+++ b/libtransport/includes/hicn/transport/core/name.h
@@ -77,6 +77,8 @@ class Name {
operator bool() const;
+ bool isValid() const;
+
std::string toString() const;
bool equals(const Name &name, bool consider_segment = true) const;
@@ -125,14 +127,14 @@ struct compare2 {};
template <>
struct compare2<transport::core::Name> {
- size_t operator()(const transport::core::Name &name1, const transport::core::Name &name2) const;
+ size_t operator()(const transport::core::Name &name1,
+ const transport::core::Name &name2) const;
};
} // end namespace core
} // end namespace transport
-
namespace std {
template <>
struct hash<transport::core::Name> {
diff --git a/libtransport/includes/hicn/transport/core/packet.h b/libtransport/includes/hicn/transport/core/packet.h
index e58e7962d..68daea841 100644
--- a/libtransport/includes/hicn/transport/core/packet.h
+++ b/libtransport/includes/hicn/transport/core/packet.h
@@ -19,20 +19,15 @@
#include <hicn/transport/core/payload_type.h>
#include <hicn/transport/errors/malformed_packet_exception.h>
#include <hicn/transport/portability/portability.h>
-#include <hicn/transport/security/crypto_hasher.h>
-#include <hicn/transport/security/crypto_suite.h>
-#include <hicn/transport/security/key_id.h>
+#include <hicn/transport/auth/crypto_hasher.h>
+#include <hicn/transport/auth/crypto_suite.h>
+#include <hicn/transport/auth/key_id.h>
#include <hicn/transport/utils/branch_prediction.h>
+#include <hicn/transport/utils/log.h>
#include <hicn/transport/utils/membuf.h>
#include <hicn/transport/utils/object_pool.h>
-namespace utils {
-class Signer;
-class Verifier;
-} // namespace utils
-
namespace transport {
-
namespace core {
/*
@@ -44,11 +39,13 @@ namespace core {
* \_______________________________________|
*/
-class Packet : public std::enable_shared_from_this<Packet> {
- friend class utils::Signer;
- friend class utils::Verifier;
+class Packet : public utils::MemBuf,
+ public std::enable_shared_from_this<Packet> {
+ friend class auth::Signer;
+ friend class auth::Verifier;
public:
+ using Ptr = std::shared_ptr<Packet>;
using MemBufPtr = std::shared_ptr<utils::MemBuf>;
using Format = hicn_format_t;
static constexpr size_t default_mtu = 1500;
@@ -58,24 +55,29 @@ class Packet : public std::enable_shared_from_this<Packet> {
* the eventual payload will be added by prepending the payload buffer
* to the buffer chain whose the fist buffer is the header itself.
*/
- Packet(Format format = HF_UNSPEC);
+ Packet(Format format = HF_INET6_TCP, std::size_t additional_header_size = 0);
/**
* Create new IP packet using raw buffer.
*/
- Packet(const uint8_t *buffer, std::size_t size);
- Packet(MemBufPtr &&buffer);
- /*
- * Enforce zero-copy lifestyle.
- */
- Packet(const Packet &other) = delete;
- Packet &operator=(const Packet &other) = delete;
+ /* Copy buffer */
+ Packet(CopyBufferOp, const uint8_t *buffer, std::size_t size);
+ /* Wrap buffer */
+ Packet(WrapBufferOp, uint8_t *buffer, std::size_t length, std::size_t size);
+ /* Create new using pre-allocated buffer */
+ Packet(CreateOp, uint8_t *buffer, std::size_t length, std::size_t size,
+ Format format = HF_INET6_TCP, std::size_t additional_header_size = 0);
+ /* Move MemBuf */
+ Packet(MemBuf &&buffer);
+
+ Packet(Packet &&other);
/*
- * Move constructor.
+ * Copy constructor and assignemnt operators.
*/
- Packet(Packet &&other);
+ Packet(const Packet &other);
+ Packet &operator=(const Packet &other);
friend bool operator==(const Packet &l_packet, const Packet &r_packet);
@@ -97,32 +99,35 @@ class Packet : public std::enable_shared_from_this<Packet> {
static bool isInterest(const uint8_t *buffer);
- static Format getFormatFromBuffer(const uint8_t *buffer) {
- Format format = HF_UNSPEC;
-
- if (TRANSPORT_EXPECT_FALSE(
- hicn_packet_get_format((const hicn_header_t *)buffer, &format) <
- 0)) {
- throw errors::MalformedPacketException();
- }
+ bool isInterest();
+ static Format getFormatFromBuffer(const uint8_t *buffer, std::size_t length) {
+ Format format = HF_UNSPEC;
+ hicn_packet_get_format((const hicn_header_t *)buffer, &format);
return format;
}
- TRANSPORT_ALWAYS_INLINE void replace(MemBufPtr &&buffer) {
- packet_ = std::move(buffer);
- packet_start_ = reinterpret_cast<hicn_header_t *>(packet_->writableData());
- header_head_ = packet_.get();
- payload_head_ = nullptr;
- format_ = getFormatFromBuffer(reinterpret_cast<uint8_t *>(packet_start_));
+ void reset() {
+ clear();
+ packet_start_ = reinterpret_cast<hicn_header_t *>(writableData());
+ header_offset_ = 0;
+ format_ = HF_UNSPEC;
+ payload_type_ = PayloadType::UNSPECIFIED;
name_.clear();
+
+ if (isChained()) {
+ separateChain(next(), prev());
+ }
}
+ void setFormat(Packet::Format format = HF_INET6_TCP,
+ std::size_t additional_header_size = 0);
+
std::size_t payloadSize() const;
std::size_t headerSize() const;
- const std::shared_ptr<utils::MemBuf> acquireMemBufReference() const;
+ std::shared_ptr<utils::MemBuf> acquireMemBufReference();
virtual const Name &getName() const = 0;
@@ -140,25 +145,8 @@ class Packet : public std::enable_shared_from_this<Packet> {
Packet &appendPayload(std::unique_ptr<utils::MemBuf> &&payload);
- Packet &appendHeader(std::unique_ptr<utils::MemBuf> &&header);
-
- Packet &appendHeader(const uint8_t *buffer, std::size_t length);
-
std::unique_ptr<utils::MemBuf> getPayload() const;
- std::pair<const uint8_t *, std::size_t> getPayloadReference() const {
- int signature_size = 0;
- if (_is_ah(format_)) {
- signature_size = (uint32_t)getSignatureSize();
- }
-
- auto header_size = getHeaderSizeFromFormat(format_, signature_size);
- auto payload_length = packet_->length() - header_size;
-
- return std::make_pair(packet_->data() + header_size,
- payload_length);
- }
-
Packet &updateLength(std::size_t length = 0);
PayloadType getPayloadType() const;
@@ -169,35 +157,38 @@ class Packet : public std::enable_shared_from_this<Packet> {
void dump() const;
+ static void dump(uint8_t *buffer, std::size_t length);
+
virtual void setLocator(const ip_address_t &locator) = 0;
virtual ip_address_t getLocator() const = 0;
- void setSignatureTimestamp(const uint64_t &timestamp);
+ /**
+ * @brief Set signature timestamp, in milliseconds.
+ */
+ void setSignatureTimestamp(const uint64_t &timestamp_milliseconds);
uint64_t getSignatureTimestamp() const;
- void setValidationAlgorithm(const utils::CryptoSuite &validation_algorithm);
+ void setValidationAlgorithm(const auth::CryptoSuite &validation_algorithm);
- utils::CryptoSuite getValidationAlgorithm() const;
+ auth::CryptoSuite getValidationAlgorithm() const;
- void setKeyId(const utils::KeyId &key_id);
+ void setKeyId(const auth::KeyId &key_id);
- utils::KeyId getKeyId() const;
+ auth::KeyId getKeyId() const;
- virtual utils::CryptoHash computeDigest(
- utils::CryptoHashType algorithm) const;
+ virtual auth::CryptoHash computeDigest(auth::CryptoHashType algorithm) const;
void setChecksum() {
- uint16_t partial_csum = 0;
-
- for (utils::MemBuf *current = header_head_->next();
- current && current != header_head_; current = current->next()) {
- if (partial_csum != 0) {
- partial_csum = ~partial_csum;
- }
- partial_csum = csum(current->data(), current->length(), partial_csum);
+ uint16_t partial_csum =
+ csum(data() + HICN_V6_TCP_HDRLEN, length() - HICN_V6_TCP_HDRLEN, 0);
+
+ for (utils::MemBuf *current = next(); current != this;
+ current = current->next()) {
+ partial_csum = csum(current->data(), current->length(), ~partial_csum);
}
+
if (hicn_packet_compute_header_checksum(format_, packet_start_,
partial_csum) < 0) {
throw errors::MalformedPacketException();
@@ -229,11 +220,12 @@ class Packet : public std::enable_shared_from_this<Packet> {
Packet &setTTL(uint8_t hops);
uint8_t getTTL() const;
- void resetPayload();
-
private:
virtual void resetForHash() = 0;
void setSignatureSize(std::size_t size_bytes);
+ void prependPayload(const uint8_t **buffer, std::size_t *size);
+
+ bool authenticationHeader() const { return _is_ah(format_); }
std::size_t getSignatureSize() const {
size_t size_bytes;
@@ -248,15 +240,13 @@ class Packet : public std::enable_shared_from_this<Packet> {
}
uint8_t *getSignature() const;
- void separateHeaderPayload();
protected:
- Name name_;
- MemBufPtr packet_;
hicn_header_t *packet_start_;
- utils::MemBuf *header_head_;
- utils::MemBuf *payload_head_;
+ std::size_t header_offset_;
mutable Format format_;
+ Name name_;
+ mutable PayloadType payload_type_;
static const core::Name base_name;
};
diff --git a/libtransport/includes/hicn/transport/core/payload_type.h b/libtransport/includes/hicn/transport/core/payload_type.h
index fa79db35a..8c918f792 100644
--- a/libtransport/includes/hicn/transport/core/payload_type.h
+++ b/libtransport/includes/hicn/transport/core/payload_type.h
@@ -20,8 +20,9 @@ namespace transport {
namespace core {
enum class PayloadType : uint16_t {
- CONTENT_OBJECT = HPT_DATA,
+ DATA = HPT_DATA,
MANIFEST = HPT_MANIFEST,
+ UNSPECIFIED = HPT_UNSPEC
};
} // end namespace core
diff --git a/libtransport/includes/hicn/transport/core/prefix.h b/libtransport/includes/hicn/transport/core/prefix.h
index c3805f13f..7ef667bc8 100644
--- a/libtransport/includes/hicn/transport/core/prefix.h
+++ b/libtransport/includes/hicn/transport/core/prefix.h
@@ -35,9 +35,9 @@ class Prefix {
Prefix(const core::Name &content_name, uint16_t prefix_length);
- std::unique_ptr<Sockaddr> toSockaddr();
+ std::unique_ptr<Sockaddr> toSockaddr() const;
- uint16_t getPrefixLength();
+ uint16_t getPrefixLength() const;
Prefix &setPrefixLength(uint16_t prefix_length);
@@ -58,13 +58,13 @@ class Prefix {
Prefix &setNetwork(std::string &network);
- int getAddressFamily();
+ int getAddressFamily() const;
Prefix &setAddressFamily(int address_family);
Name makeRandomName() const;
- ip_prefix_t &toIpPrefixStruct();
+ const ip_prefix_t &toIpPrefixStruct() const;
private:
static bool checkPrefixLengthAndAddressFamily(uint16_t prefix_length,
diff --git a/libtransport/includes/hicn/transport/errors/errors.h b/libtransport/includes/hicn/transport/errors/errors.h
index 512e35736..b659820fa 100644
--- a/libtransport/includes/hicn/transport/errors/errors.h
+++ b/libtransport/includes/hicn/transport/errors/errors.h
@@ -15,10 +15,13 @@
#pragma once
+#include <hicn/transport/errors/indexing_exception.h>
#include <hicn/transport/errors/invalid_ip_address_exception.h>
+#include <hicn/transport/errors/malformed_ahpacket_exception.h>
#include <hicn/transport/errors/malformed_name_exception.h>
#include <hicn/transport/errors/malformed_packet_exception.h>
#include <hicn/transport/errors/not_implemented_exception.h>
#include <hicn/transport/errors/null_pointer_exception.h>
#include <hicn/transport/errors/runtime_exception.h>
-#include <hicn/transport/errors/tokenizer_exception.h> \ No newline at end of file
+#include <hicn/transport/errors/tokenizer_exception.h>
+#include <hicn/transport/errors/unexpected_manifest_exception.h>
diff --git a/libtransport/includes/hicn/transport/http/client_connection.h b/libtransport/includes/hicn/transport/http/client_connection.h
index 262756a09..7e78e9c59 100644
--- a/libtransport/includes/hicn/transport/http/client_connection.h
+++ b/libtransport/includes/hicn/transport/http/client_connection.h
@@ -68,7 +68,7 @@ class HTTPClientConnection {
HTTPClientConnection &setTimeout(const std::chrono::seconds &timeout);
- HTTPClientConnection &setCertificate(const std::string &cert_path);
+ HTTPClientConnection &setVerifier(std::shared_ptr<auth::Verifier> verifier);
private:
class Implementation;
@@ -77,4 +77,4 @@ class HTTPClientConnection {
} // end namespace http
-} // end namespace transport \ No newline at end of file
+} // end namespace transport
diff --git a/libtransport/includes/hicn/transport/http/request.h b/libtransport/includes/hicn/transport/http/request.h
index 54904d696..b62f5b061 100644
--- a/libtransport/includes/hicn/transport/http/request.h
+++ b/libtransport/includes/hicn/transport/http/request.h
@@ -46,6 +46,11 @@ class HTTPRequest : public HTTPMessage {
std::string getRequestString() const;
+ static std::size_t parseHeaders(const uint8_t *buffer, std::size_t size,
+ HTTPHeaders &headers,
+ std::string &http_version,
+ std::string &method, std::string &url);
+
private:
std::string query_string_, path_, protocol_, locator_, port_;
std::string request_string_;
diff --git a/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt b/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt
index 7370ad1b0..08f880930 100644
--- a/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt
@@ -16,12 +16,11 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/socket_consumer.h
${CMAKE_CURRENT_SOURCE_DIR}/socket_producer.h
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc_socket_producer.h
${CMAKE_CURRENT_SOURCE_DIR}/publication_options.h
${CMAKE_CURRENT_SOURCE_DIR}/socket_options_default_values.h
${CMAKE_CURRENT_SOURCE_DIR}/socket_options_keys.h
${CMAKE_CURRENT_SOURCE_DIR}/callbacks.h
- ${CMAKE_CURRENT_SOURCE_DIR}/verification_policy.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/global_conf_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/statistics.h
${CMAKE_CURRENT_SOURCE_DIR}/portal.h
)
diff --git a/libtransport/includes/hicn/transport/interfaces/callbacks.h b/libtransport/includes/hicn/transport/interfaces/callbacks.h
index 6ae07797e..95b4d1977 100644
--- a/libtransport/includes/hicn/transport/interfaces/callbacks.h
+++ b/libtransport/includes/hicn/transport/interfaces/callbacks.h
@@ -16,7 +16,7 @@
#pragma once
#include <hicn/transport/interfaces/statistics.h>
-#include <hicn/transport/interfaces/verification_policy.h>
+#include <hicn/transport/auth/policies.h>
#include <functional>
#include <system_error>
@@ -75,25 +75,6 @@ using ConsumerContentObjectCallback =
std::function<void(ConsumerSocket &, const core::ContentObject &)>;
/**
- * The ConsumerContentObjectVerificationCallback will be called by the transport
- * if an application is willing to verify each content object. Note that a
- * better alternative is to instrument the transport to perform the verification
- * autonomously, without requiring the intervention of the application.
- */
-using ConsumerContentObjectVerificationCallback =
- std::function<bool(ConsumerSocket &, const core::ContentObject &)>;
-
-/**
- * The ConsumerContentObjectVerificationFailedCallback will be caled by the
- * transport if a data packet (either manifest or content object) cannot be
- * verified. The application here decides what to do by returning a
- * VerificationFailedPolicy object.
- */
-using ConsumerContentObjectVerificationFailedCallback =
- std::function<VerificationPolicy(
- ConsumerSocket &, const core::ContentObject &, std::error_code ec)>;
-
-/**
* The ProducerContentObjectCallback will be called in different parts of the
* consumer socket processing pipeline, with a ProducerSocket and an
* ContentObject as parameters.
diff --git a/libtransport/includes/hicn/transport/interfaces/global_conf_interface.h b/libtransport/includes/hicn/transport/interfaces/global_conf_interface.h
new file mode 100644
index 000000000..a9fe6fac6
--- /dev/null
+++ b/libtransport/includes/hicn/transport/interfaces/global_conf_interface.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+/**
+ * Global configuration interface.
+ */
+
+namespace transport {
+namespace interface {
+namespace global_config {
+
+static const constexpr char io_module_section[] = "io_module";
+void parseConfigurationFile(const std::string& path = "");
+
+class ConfigurationObject {
+ public:
+ /**
+ * Set configuration.
+ */
+ void set();
+
+ /**
+ * Get configuration.
+ */
+ void get();
+
+ /**
+ * Get configuration key
+ */
+ virtual std::string getKey() const = 0;
+};
+
+class IoModuleConfiguration : public ConfigurationObject {
+ public:
+ std::string getKey() const override { return io_module_section; }
+
+ std::string name;
+ std::vector<std::string> search_path;
+};
+
+} // namespace global_config
+} // namespace interface
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h
index 097b0a8c0..224493f00 100644
--- a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h
+++ b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h
@@ -23,10 +23,10 @@ namespace interface {
class P2PSecureConsumerSocket : public ConsumerSocket {
public:
- P2PSecureConsumerSocket(int handshake_protocol, int protocol);
+ P2PSecureConsumerSocket(int handshake_protocol, int transport_protocol);
~P2PSecureConsumerSocket() = default;
+ void registerPrefix(const Prefix &producer_namespace);
};
} // namespace interface
-
} // end namespace transport
diff --git a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h
index 6f0d48bb9..7b284c520 100644
--- a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h
+++ b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h
@@ -16,8 +16,7 @@
#pragma once
#include <hicn/transport/interfaces/socket_producer.h>
-
-#include <hicn/transport/security/identity.h>
+#include <hicn/transport/auth/identity.h>
namespace transport {
@@ -27,7 +26,7 @@ class P2PSecureProducerSocket : public ProducerSocket {
public:
P2PSecureProducerSocket();
P2PSecureProducerSocket(bool rtc,
- const std::shared_ptr<utils::Identity> &identity);
+ const std::shared_ptr<auth::Identity> &identity);
~P2PSecureProducerSocket() = default;
};
diff --git a/libtransport/includes/hicn/transport/interfaces/portal.h b/libtransport/includes/hicn/transport/interfaces/portal.h
index 724cd7592..22c8591f4 100644
--- a/libtransport/includes/hicn/transport/interfaces/portal.h
+++ b/libtransport/includes/hicn/transport/interfaces/portal.h
@@ -23,7 +23,6 @@
#define ASIO_STANDALONE
#endif
#include <asio/io_service.hpp>
-
#include <functional>
#define UNSET_CALLBACK 0
@@ -71,8 +70,7 @@ class Portal {
*/
class ConsumerCallback {
public:
- virtual void onContentObject(core::Interest::Ptr &&i,
- core::ContentObject::Ptr &&c) = 0;
+ virtual void onContentObject(core::Interest &i, core::ContentObject &c) = 0;
virtual void onTimeout(core::Interest::Ptr &&i) = 0;
virtual void onError(std::error_code ec) = 0;
};
@@ -83,12 +81,12 @@ class Portal {
*/
class ProducerCallback {
public:
- virtual void onInterest(core::Interest::Ptr &&i) = 0;
+ virtual void onInterest(core::Interest &i) = 0;
virtual void onError(std::error_code ec) = 0;
};
using OnContentObjectCallback =
- std::function<void(core::Interest::Ptr &&, core::ContentObject::Ptr &&)>;
+ std::function<void(core::Interest &, core::ContentObject &)>;
using OnInterestTimeoutCallback = std::function<void(core::Interest::Ptr &&)>;
Portal();
diff --git a/libtransport/includes/hicn/transport/interfaces/socket_consumer.h b/libtransport/includes/hicn/transport/interfaces/socket_consumer.h
index 0a6e9a43a..621e7ce6f 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_consumer.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_consumer.h
@@ -21,7 +21,7 @@
#include <hicn/transport/interfaces/callbacks.h>
#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <hicn/transport/interfaces/socket_options_keys.h>
-#include <hicn/transport/security/verifier.h>
+#include <hicn/transport/auth/verifier.h>
#ifndef ASIO_STANDALONE
#define ASIO_STANDALONE
@@ -106,7 +106,7 @@ class ConsumerSocket {
/**
* This method will be called by the transport for understanding how many
- * bytes it should read (at most) before notifying the application.
+ * bytes it should read before notifying the application.
*
* By default it reads 64 KB.
*/
@@ -145,7 +145,7 @@ class ConsumerSocket {
* @param protocol - The transport protocol to use. So far the following
* transport are supported:
* - CBR: Constant bitrate
- * - Raaqm: Based on paper: Optimal multipath congestion control and request
+ * - RAAQM: Based on paper: Optimal multipath congestion control and request
* forwarding in information-centric networks: Protocol design and
* experimentation. G Carofiglio, M Gallo, L Muscariello. Computer Networks
* 110, 104-117
@@ -154,6 +154,25 @@ class ConsumerSocket {
explicit ConsumerSocket(int protocol);
/**
+ * @brief Create a new consumer socket, passing an io_service to it.
+ * Passing an io_service means that the caller must explicitely call
+ * io_service.run() for the consumer to start. Any call to consume won't be
+ * blocking. This can be used in case we want to share a single thread
+ * among multiple consumer sockets. The caller MUST ensure the provided
+ * io_service will outlive the ConsumerSocket.
+ *
+ * @param protocol - The transport protocol to use. So far the following
+ * transport are supported:
+ * - CBR: Constant bitrate
+ * - RAAQM: Based on paper: Optimal multipath congestion control and request
+ * forwarding in information-centric networks: Protocol design and
+ * experimentation. G Carofiglio, M Gallo, L Muscariello. Computer Networks
+ * 110, 104-117
+ * - RTC: Real time communication
+ */
+ explicit ConsumerSocket(int protocol, asio::io_service &io_service);
+
+ /**
* @brief Destroy the consumer socket.
*/
~ConsumerSocket();
@@ -189,14 +208,6 @@ class ConsumerSocket {
int asyncConsume(const Name &name);
/**
- * Verify the packets containing a key after the origin of the key has been
- * validated by the client.
- *
- * @return true if all packets are valid, false otherwise
- */
- bool verifyKeyPackets();
-
- /**
* Stops the consumer socket. If several downloads are queued (using
* asyncConsume), this call stops just the current one.
*/
@@ -232,14 +243,6 @@ class ConsumerSocket {
int setSocketOption(int socket_option_key,
ConsumerContentObjectCallback socket_option_value);
- int setSocketOption(
- int socket_option_key,
- ConsumerContentObjectVerificationFailedCallback socket_option_value);
-
- int setSocketOption(
- int socket_option_key,
- ConsumerContentObjectVerificationCallback socket_option_value);
-
int setSocketOption(int socket_option_key,
ConsumerInterestCallback socket_option_value);
@@ -248,7 +251,7 @@ class ConsumerSocket {
int setSocketOption(
int socket_option_key,
- const std::shared_ptr<utils::Verifier> &socket_option_value);
+ const std::shared_ptr<auth::Verifier> &socket_option_value);
int setSocketOption(int socket_option_key,
const std::string &socket_option_value);
@@ -267,21 +270,13 @@ class ConsumerSocket {
int getSocketOption(int socket_option_key,
ConsumerContentObjectCallback **socket_option_value);
- int getSocketOption(
- int socket_option_key,
- ConsumerContentObjectVerificationFailedCallback **socket_option_value);
-
- int getSocketOption(
- int socket_option_key,
- ConsumerContentObjectVerificationCallback **socket_option_value);
-
int getSocketOption(int socket_option_key,
ConsumerInterestCallback **socket_option_value);
int getSocketOption(int socket_option_key, IcnObserver **socket_option_value);
int getSocketOption(int socket_option_key,
- std::shared_ptr<utils::Verifier> &socket_option_value);
+ std::shared_ptr<auth::Verifier> &socket_option_value);
int getSocketOption(int socket_option_key, std::string &socket_option_value);
diff --git a/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h b/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h
index bcf103b8c..f4945ac8a 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h
@@ -16,6 +16,7 @@
#pragma once
#include <hicn/base.h>
+
#include <chrono>
#include <cstdint>
diff --git a/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h b/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h
index 0b7a79c3d..00cd44075 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h
@@ -32,6 +32,11 @@ typedef enum {
} TransportProtocolAlgorithms;
typedef enum {
+ BYTE_STREAM = 10,
+ RTC_PROD = 11,
+} ProductionProtocolAlgorithms;
+
+typedef enum {
INPUT_BUFFER_SIZE = 101,
OUTPUT_BUFFER_SIZE = 102,
NETWORK_NAME = 103,
@@ -40,7 +45,6 @@ typedef enum {
DATA_PACKET_SIZE = 106,
INTEREST_LIFETIME = 107,
CONTENT_OBJECT_EXPIRY_TIME = 108,
- KEY_CONTENT = 110,
MIN_WINDOW_SIZE = 111,
MAX_WINDOW_SIZE = 112,
CURRENT_WINDOW_SIZE = 113,
@@ -50,12 +54,10 @@ typedef enum {
RUNNING = 117,
APPLICATION_BUFFER = 118,
HASH_ALGORITHM = 119,
- CRYPTO_SUITE = 120,
SIGNER = 121,
VERIFIER = 122,
- CERTIFICATE = 123,
- VERIFY_SIGNATURE = 124,
STATS_INTERVAL = 125,
+ SUFFIX_STRATEGY = 126
} GeneralTransportOptions;
typedef enum {
@@ -66,6 +68,7 @@ typedef enum {
MINIMUM_DROP_PROBABILITY = 205,
PATH_ID = 206,
RTT_STATS = 207,
+ PER_SESSION_CWINDOW_RESET = 208
} RaaqmTransportOptions;
typedef enum {
@@ -97,6 +100,7 @@ typedef enum {
CONTENT_OBJECT_READY = 510,
CONTENT_OBJECT_OUTPUT = 511,
CONTENT_PRODUCED = 512,
+ CONTENT_OBJECT_TO_SIGN = 513
} ProducerCallbacksOptions;
typedef enum { OUTPUT_INTERFACE = 601 } DataLinkOptions;
diff --git a/libtransport/includes/hicn/transport/interfaces/socket_producer.h b/libtransport/includes/hicn/transport/interfaces/socket_producer.h
index e269fb83d..302b03f3f 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_producer.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_producer.h
@@ -21,7 +21,7 @@
#include <hicn/transport/interfaces/callbacks.h>
#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <hicn/transport/interfaces/socket_options_keys.h>
-#include <hicn/transport/security/signer.h>
+#include <hicn/transport/auth/signer.h>
#ifndef ASIO_STANDALONE
#define ASIO_STANDALONE
@@ -40,7 +40,10 @@ using namespace core;
class ProducerSocket {
public:
- explicit ProducerSocket(int protocol = 0);
+ explicit ProducerSocket(
+ int protocol = ProductionProtocolAlgorithms::BYTE_STREAM);
+
+ explicit ProducerSocket(int protocol, asio::io_service &io_service);
virtual ~ProducerSocket();
@@ -48,22 +51,21 @@ class ProducerSocket {
bool isRunning();
- uint32_t produce(Name content_name, const uint8_t *buffer, size_t buffer_size,
- bool is_last = true, uint32_t start_offset = 0) {
- return produce(content_name, utils::MemBuf::copyBuffer(buffer, buffer_size),
- is_last, start_offset);
- }
+ void registerPrefix(const Prefix &producer_namespace);
- uint32_t produce(Name content_name, std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last = true, uint32_t start_offset = 0);
+ uint32_t produceStream(const Name &content_name, const uint8_t *buffer,
+ size_t buffer_size, bool is_last = true,
+ uint32_t start_offset = 0);
- void produce(ContentObject &content_object);
+ uint32_t produceStream(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer,
+ bool is_last = true, uint32_t start_offset = 0);
- void produce(const uint8_t *buffer, size_t buffer_size) {
- produce(utils::MemBuf::copyBuffer(buffer, buffer_size));
- }
+ uint32_t produceDatagram(const Name &content_name, const uint8_t *buffer,
+ size_t buffer_size);
- void produce(std::unique_ptr<utils::MemBuf> &&buffer);
+ uint32_t produceDatagram(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer);
void asyncProduce(const Name &suffix, const uint8_t *buf, size_t buffer_size,
bool is_last = true, uint32_t *start_offset = nullptr);
@@ -72,9 +74,7 @@ class ProducerSocket {
bool is_last, uint32_t offset,
uint32_t **last_segment = nullptr);
- void asyncProduce(ContentObject &content_object);
-
- void registerPrefix(const Prefix &producer_namespace);
+ void produce(ContentObject &content_object);
void serveForever();
@@ -104,14 +104,13 @@ class ProducerSocket {
ProducerContentCallback socket_option_value);
int setSocketOption(int socket_option_key,
- utils::CryptoHashType socket_option_value);
+ auth::CryptoHashType socket_option_value);
int setSocketOption(int socket_option_key,
- utils::CryptoSuite socket_option_value);
+ auth::CryptoSuite socket_option_value);
- int setSocketOption(
- int socket_option_key,
- const std::shared_ptr<utils::Signer> &socket_option_value);
+ int setSocketOption(int socket_option_key,
+ const std::shared_ptr<auth::Signer> &socket_option_value);
int setSocketOption(int socket_option_key,
const std::string &socket_option_value);
@@ -133,13 +132,13 @@ class ProducerSocket {
ProducerInterestCallback **socket_option_value);
int getSocketOption(int socket_option_key,
- utils::CryptoHashType &socket_option_value);
+ auth::CryptoHashType &socket_option_value);
int getSocketOption(int socket_option_key,
- utils::CryptoSuite &socket_option_value);
+ auth::CryptoSuite &socket_option_value);
int getSocketOption(int socket_option_key,
- std::shared_ptr<utils::Signer> &socket_option_value);
+ std::shared_ptr<auth::Signer> &socket_option_value);
int getSocketOption(int socket_option_key, std::string &socket_option_value);
diff --git a/libtransport/includes/hicn/transport/interfaces/statistics.h b/libtransport/includes/hicn/transport/interfaces/statistics.h
index 26831fbf1..92c58da23 100644
--- a/libtransport/includes/hicn/transport/interfaces/statistics.h
+++ b/libtransport/includes/hicn/transport/interfaces/statistics.h
@@ -31,6 +31,8 @@ class IcnObserver {
virtual void notifyDownloadTime(double downloadTime) = 0;
};
+class ProductionStatistics {};
+
class TransportStatistics {
static constexpr double default_alpha = 0.7;
@@ -43,7 +45,15 @@ class TransportStatistics {
interest_tx_(0),
alpha_(alpha),
loss_ratio_(0.0),
- queuing_delay_(0.0) {}
+ queuing_delay_(0.0),
+ interest_FEC_tx_(0),
+ bytes_FEC_received_(0),
+ lost_data_(0),
+ recovered_data_(0),
+ status_(-1),
+ // avg_data_rtt_(0),
+ avg_pending_pkt_(0.0),
+ received_nacks_(0) {}
TRANSPORT_ALWAYS_INLINE void updateRetxCount(uint64_t retx) {
retx_count_ += retx;
@@ -74,6 +84,32 @@ class TransportStatistics {
queuing_delay_ = queuing_delay;
}
+ TRANSPORT_ALWAYS_INLINE void updateInterestFecTx(uint64_t int_tx) {
+ interest_FEC_tx_ += int_tx;
+ }
+
+ TRANSPORT_ALWAYS_INLINE void updateBytesFecRecv(uint64_t bytes) {
+ bytes_FEC_received_ += bytes;
+ }
+
+ TRANSPORT_ALWAYS_INLINE void updateLostData(uint64_t pkt) {
+ lost_data_ += pkt;
+ }
+
+ TRANSPORT_ALWAYS_INLINE void updateRecoveredData(uint64_t bytes) {
+ recovered_data_ += bytes;
+ }
+
+ TRANSPORT_ALWAYS_INLINE void updateCCState(int status) { status_ = status; }
+
+ TRANSPORT_ALWAYS_INLINE void updateAveragePendingPktCount(double pkt) {
+ avg_pending_pkt_ = (alpha_ * avg_pending_pkt_) + ((1. - alpha_) * pkt);
+ }
+
+ TRANSPORT_ALWAYS_INLINE void updateReceivedNacks(uint32_t nacks) {
+ received_nacks_ += nacks;
+ }
+
TRANSPORT_ALWAYS_INLINE uint64_t getRetxCount() const { return retx_count_; }
TRANSPORT_ALWAYS_INLINE uint64_t getBytesRecv() const {
@@ -96,6 +132,32 @@ class TransportStatistics {
return queuing_delay_;
}
+ TRANSPORT_ALWAYS_INLINE uint64_t getInterestFecTxCount() const {
+ return interest_FEC_tx_;
+ }
+
+ TRANSPORT_ALWAYS_INLINE uint64_t getBytesFecRecv() const {
+ return bytes_FEC_received_;
+ }
+
+ TRANSPORT_ALWAYS_INLINE uint64_t getLostData() const { return lost_data_; }
+
+ TRANSPORT_ALWAYS_INLINE uint64_t getBytesRecoveredData() const {
+ return recovered_data_;
+ }
+
+ TRANSPORT_ALWAYS_INLINE int getCCStatus() const { return status_; }
+
+ TRANSPORT_ALWAYS_INLINE double getAveragePendingPktCount() const {
+ return avg_pending_pkt_;
+ }
+
+ TRANSPORT_ALWAYS_INLINE uint32_t getReceivedNacks() const {
+ return received_nacks_;
+ }
+
+ TRANSPORT_ALWAYS_INLINE void setAlpha(double val) { alpha_ = val; }
+
TRANSPORT_ALWAYS_INLINE void reset() {
retx_count_ = 0;
bytes_received_ = 0;
@@ -103,6 +165,14 @@ class TransportStatistics {
avg_window_size_ = 0;
interest_tx_ = 0;
loss_ratio_ = 0;
+ interest_FEC_tx_ = 0;
+ bytes_FEC_received_ = 0;
+ lost_data_ = 0;
+ recovered_data_ = 0;
+ status_ = 0;
+ // avg_data_rtt_ = 0;
+ avg_pending_pkt_ = 0;
+ received_nacks_ = 0;
}
private:
@@ -114,6 +184,13 @@ class TransportStatistics {
double alpha_;
double loss_ratio_;
double queuing_delay_;
+ uint64_t interest_FEC_tx_;
+ uint64_t bytes_FEC_received_;
+ uint64_t lost_data_;
+ uint64_t recovered_data_;
+ int status_; // transport status (e.g. sync status, congestion etc.)
+ double avg_pending_pkt_;
+ uint32_t received_nacks_;
};
} // namespace interface
diff --git a/libtransport/includes/hicn/transport/portability/c_portability.h b/libtransport/includes/hicn/transport/portability/c_portability.h
index 71e976a81..9fe9ef90a 100644
--- a/libtransport/includes/hicn/transport/portability/c_portability.h
+++ b/libtransport/includes/hicn/transport/portability/c_portability.h
@@ -33,4 +33,4 @@
#define TRANSPORT_ALWAYS_INLINE inline __attribute__((__always_inline__))
#else
#define TRANSPORT_ALWAYS_INLINE inline
-#endif \ No newline at end of file
+#endif
diff --git a/libtransport/includes/hicn/transport/portability/platform.h b/libtransport/includes/hicn/transport/portability/platform.h
new file mode 100644
index 000000000..282d27740
--- /dev/null
+++ b/libtransport/includes/hicn/transport/portability/platform.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/*
+ * Extract the "MACINTOSH" flag from the compiler.
+ */
+#if defined(__APPLE__)
+#define UNIX
+#define MACINTOSH
+#endif
+
+/*
+ * Extract the "SUNOS" flag from the compiler.
+ */
+#if defined(sun)
+#define UNIX
+#define SUNOS
+#endif
+
+/*
+ * Extract the "LINUX" flag from compiler.
+ */
+#ifdef __linux__
+#define UNIX
+#define LINUX
+#endif
+
+/*
+ * Extract the "ANDROID" flag from compiler.
+ */
+#ifdef __ANDROID__
+#define UNIX
+#define LINUX
+#ifndef ANDROID
+#define ANDROID
+#endif
+#endif
+
+/*
+ * Extract the "BSD" flag from compiler.
+ */
+#if defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || \
+ defined(__OpenBSD__)
+#define OS_BSD
+#define UNIX
+#endif
+
+/*
+ * Extract the "MSDOS" flag from the compiler.
+ */
+#ifdef __MSDOS__
+#define MSDOS
+#undef UNIX
+#endif
+
+/*
+ * Extract the "WINDOWS" flag from the compiler.
+ */
+#if defined(_Windows) || defined(__WINDOWS__) || defined(__WIN32__) || \
+ defined(WIN32) || defined(__WINNT__) || defined(__NT__) || \
+ defined(_WIN32) || defined(_WIN64)
+#define WINDOWS
+#ifdef _MSC_VER
+#define MSV
+#if defined(DEBUG) || defined(DEBUGTRACE)
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+#else
+#ifndef NDEBUG
+#define NDEBUG
+#endif
+#endif
+#else
+#undef MSV
+#endif
+#undef UNIX
+#undef MSDOS
+#endif
+
+/*
+ * Remove the WINDOWS flag when using MACINTOSH.
+ */
+#ifdef MACINTOSH
+#undef WINDOWS
+#endif
+
+/*
+ * Assume UNIX if not Windows, Macintosh or MSDOS.
+ */
+#if !defined(WINDOWS) && !defined(MACINTOSH) && !defined(MSDOS)
+#define UNIX
+#endif
diff --git a/libtransport/includes/hicn/transport/portability/portability.h b/libtransport/includes/hicn/transport/portability/portability.h
index 1d97a346e..539ce2d5a 100644
--- a/libtransport/includes/hicn/transport/portability/portability.h
+++ b/libtransport/includes/hicn/transport/portability/portability.h
@@ -22,8 +22,8 @@
#endif
#include <hicn/transport/portability/c_portability.h>
-
#include <string.h>
+
#include <cstddef>
namespace portability {
diff --git a/libtransport/includes/hicn/transport/portability/win_portability.h b/libtransport/includes/hicn/transport/portability/win_portability.h
index 65d949291..246b734ad 100644
--- a/libtransport/includes/hicn/transport/portability/win_portability.h
+++ b/libtransport/includes/hicn/transport/portability/win_portability.h
@@ -17,7 +17,9 @@
#pragma once
#define WIN32_LEAN_AND_MEAN
+#ifndef NOMINMAX
#define NOMINMAX
+#endif
#include <fcntl.h>
#include <io.h>
#include <parc/windows/parc_Utils.h>
@@ -31,6 +33,7 @@
#include <winsock2.h>
#include <ws2ipdef.h>
#include <ws2tcpip.h>
+
#include <algorithm>
#define __ORDER_LITTLE_ENDIAN__ 0x41424344UL
diff --git a/libtransport/includes/hicn/transport/utils/CMakeLists.txt b/libtransport/includes/hicn/transport/utils/CMakeLists.txt
index 38ecc3d37..7094601f4 100644
--- a/libtransport/includes/hicn/transport/utils/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/utils/CMakeLists.txt
@@ -29,6 +29,13 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/membuf.h
${CMAKE_CURRENT_SOURCE_DIR}/spinlock.h
${CMAKE_CURRENT_SOURCE_DIR}/fixed_block_allocator.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/event_thread.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/string_utils.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/file.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/shared_ptr_utils.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/move_wrapper.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/noncopyable.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/singleton.h
)
if(NOT WIN32)
diff --git a/libtransport/includes/hicn/transport/utils/conversions.h b/libtransport/includes/hicn/transport/utils/conversions.h
index 24b529206..52d3e3168 100644
--- a/libtransport/includes/hicn/transport/utils/conversions.h
+++ b/libtransport/includes/hicn/transport/utils/conversions.h
@@ -16,8 +16,8 @@
#pragma once
#include <hicn/transport/portability/portability.h>
-
#include <stdio.h>
+
#include <cstdint>
#include <string>
diff --git a/libtransport/includes/hicn/transport/utils/enum_iterator.h b/libtransport/includes/hicn/transport/utils/enum_iterator.h
new file mode 100644
index 000000000..5e108b088
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/enum_iterator.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <type_traits>
+
+template <typename C, C begin_val, C end_val>
+class Iterator {
+ typedef typename std::underlying_type<C>::type val_t;
+ int val;
+
+ public:
+ Iterator(const C& f) : val(static_cast<val_t>(f)) {}
+
+ Iterator() : val(static_cast<val_t>(begin_val)) {}
+
+ Iterator operator++() {
+ ++val;
+ return *this;
+ }
+
+ C operator*() { return static_cast<C>(val); }
+
+ Iterator begin() { return *this; } // default ctor is good
+
+ Iterator end() {
+ static const Iterator endIter = ++Iterator(end_val); // cache it
+ return endIter;
+ }
+
+ bool operator!=(const Iterator& i) { return val != i.val; }
+}; \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/event_thread.h b/libtransport/includes/hicn/transport/utils/event_thread.h
new file mode 100644
index 000000000..bb6ab90ef
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/event_thread.h
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/config.h>
+#include <hicn/transport/errors/runtime_exception.h>
+#include <hicn/transport/utils/log.h>
+
+#ifndef ASIO_STANDALONE
+#define ASIO_STANDALONE
+#endif
+#include <asio.hpp>
+#include <memory>
+#include <thread>
+
+namespace utils {
+
+class EventThread {
+ public:
+ EventThread(asio::io_service& io_service, bool detached = false)
+ : internal_io_service_(nullptr),
+ io_service_(std::ref(io_service)),
+ work_(std::make_unique<asio::io_service::work>(io_service_)),
+ thread_(nullptr),
+ detached_(detached) {
+ run();
+ }
+
+ EventThread(bool detached = false)
+ : internal_io_service_(std::make_unique<asio::io_service>()),
+ io_service_(std::ref(*internal_io_service_)),
+ work_(std::make_unique<asio::io_service::work>(io_service_)),
+ thread_(nullptr),
+ detached_(detached) {
+ run();
+ }
+
+ EventThread(const EventThread&) = delete;
+ EventThread& operator=(const EventThread&) = delete;
+
+ EventThread(EventThread&& other)
+ : internal_io_service_(std::move(other.internal_io_service_)),
+ io_service_(std::move(other.io_service_)),
+ work_(std::move(other.work_)),
+ thread_(std::move(other.thread_)),
+ detached_(std::move(other.detached_)) {}
+
+ EventThread& operator=(EventThread&& other) {
+ internal_io_service_ = std::move(other.internal_io_service_);
+ io_service_ = std::move(other.io_service_);
+ work_ = std::move(other.work_);
+ thread_ = std::move(other.thread_);
+ detached_ = other.detached_;
+
+ return *this;
+ }
+
+ ~EventThread() { stop(); }
+
+ void run() {
+ if (stopped()) {
+ io_service_.get().stopped();
+ }
+
+ thread_ =
+ std::make_unique<std::thread>([this]() { io_service_.get().run(); });
+
+ if (detached_) {
+ thread_->detach();
+ }
+ }
+
+ std::thread::id getThreadId() const {
+ if (thread_) {
+ return thread_->get_id();
+ } else {
+ throw errors::RuntimeException("Event thread is not running.");
+ }
+ }
+
+ template <typename Func>
+ void add(Func&& f) {
+ io_service_.get().post(std::forward<Func&&>(f));
+ }
+
+ template <typename Func>
+ void tryRunHandlerNow(Func&& f) {
+ io_service_.get().dispatch(std::forward<Func&&>(f));
+ }
+
+ void stop() {
+ work_.reset();
+
+ if (thread_ && thread_->joinable()) {
+ thread_->join();
+ }
+
+ thread_.reset();
+ }
+
+ bool stopped() { return io_service_.get().stopped(); }
+
+ asio::io_service& getIoService() { return io_service_; }
+
+ private:
+ std::unique_ptr<asio::io_service> internal_io_service_;
+ std::reference_wrapper<asio::io_service> io_service_;
+ std::unique_ptr<asio::io_service::work> work_;
+ std::unique_ptr<std::thread> thread_;
+ bool detached_;
+};
+
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/file.h b/libtransport/includes/hicn/transport/utils/file.h
new file mode 100644
index 000000000..4c73f33e8
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/file.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/stat.h>
+
+namespace utils {
+
+class File {
+ public:
+ static inline bool exists(const std::string& name) {
+ struct stat buffer;
+ return (stat(name.c_str(), &buffer) == 0);
+ }
+};
+
+} // namespace utils
diff --git a/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h b/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h
index 1ade1516e..b1df36493 100644
--- a/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h
+++ b/libtransport/includes/hicn/transport/utils/fixed_block_allocator.h
@@ -5,104 +5,99 @@
#pragma once
#include <hicn/transport/portability/c_portability.h>
+#include <hicn/transport/utils/singleton.h>
#include <hicn/transport/utils/spinlock.h>
-
#include <stdint.h>
+
+#include <cassert>
#include <cstdlib>
#include <memory>
-#include <cassert>
namespace utils {
-template <std::size_t DEFAULT_SIZE = 512, std::size_t OBJECTS = 4096>
-class FixedBlockAllocator {
- FixedBlockAllocator(std::size_t size = DEFAULT_SIZE,
- std::size_t objects = OBJECTS)
- : block_size_(size < sizeof(void*) ? sizeof(long*) : size),
- object_size_(size),
- max_objects_(objects),
- p_head_(NULL),
- pool_index_(0),
- block_count_(0),
- blocks_in_use_(0),
- allocations_(0),
- deallocations_(0) {
- p_pool_ = (uint8_t*)new uint8_t[block_size_ * max_objects_];
- }
+template <std::size_t SIZE = 512, std::size_t OBJECTS = 4096>
+class FixedBlockAllocator
+ : public utils::Singleton<FixedBlockAllocator<SIZE, OBJECTS>> {
+ friend class utils::Singleton<FixedBlockAllocator<SIZE, OBJECTS>>;
public:
- static FixedBlockAllocator* getInstance() {
- if (!instance_) {
- instance_ = std::unique_ptr<FixedBlockAllocator>(
- new FixedBlockAllocator(DEFAULT_SIZE, OBJECTS));
+ ~FixedBlockAllocator() {
+ for (auto& p : p_pools_) {
+ delete[] p;
}
-
- return instance_.get();
}
- ~FixedBlockAllocator() { delete[] p_pool_; }
-
- TRANSPORT_ALWAYS_INLINE void* allocateBlock(size_t size = DEFAULT_SIZE) {
- assert(size <= DEFAULT_SIZE);
+ void* allocateBlock(size_t size = SIZE) {
+ assert(size <= SIZE);
uint32_t index;
+ SpinLock::Acquire locked(lock_);
void* p_block = pop();
if (!p_block) {
- if (pool_index_ < max_objects_) {
- {
- SpinLock::Acquire locked(lock_);
- index = pool_index_++;
- }
- p_block = (void*)(p_pool_ + (index * block_size_));
- } else {
- // TODO Consider increasing pool here instead of throwing an exception
- throw std::runtime_error("No more memory available from packet pool!");
+ if (TRANSPORT_EXPECT_FALSE(current_pool_index_ >= max_objects_)) {
+ // Allocate new memory block
+ TRANSPORT_LOGV("Allocating new block of %zu size", SIZE * OBJECTS);
+ p_pools_.emplace_front(
+ new typename std::aligned_storage<SIZE>::type[max_objects_]);
+ // reset current_pool_index_
+ current_pool_index_ = 0;
}
- }
- blocks_in_use_++;
- allocations_++;
+ auto& latest = p_pools_.front();
+ index = current_pool_index_++;
+ blocks_in_use_++;
+ allocations_++;
+ p_block = (void*)&latest[index];
+ }
return p_block;
}
- TRANSPORT_ALWAYS_INLINE void deallocateBlock(void* pBlock) {
+ void deallocateBlock(void* pBlock) {
+ SpinLock::Acquire locked(lock_);
push(pBlock);
- {
- SpinLock::Acquire locked(lock_);
- blocks_in_use_--;
- deallocations_++;
- }
+ blocks_in_use_--;
+ deallocations_++;
}
- TRANSPORT_ALWAYS_INLINE std::size_t blockSize() { return block_size_; }
+ public:
+ std::size_t blockSize() { return block_size_; }
- TRANSPORT_ALWAYS_INLINE uint32_t blockCount() { return block_count_; }
+ uint32_t blockCount() { return block_count_; }
- TRANSPORT_ALWAYS_INLINE uint32_t blocksInUse() { return blocks_in_use_; }
+ uint32_t blocksInUse() { return blocks_in_use_; }
- TRANSPORT_ALWAYS_INLINE uint32_t allocations() { return allocations_; }
+ uint32_t allocations() { return allocations_; }
- TRANSPORT_ALWAYS_INLINE uint32_t deallocations() { return deallocations_; }
+ uint32_t deallocations() { return deallocations_; }
private:
- TRANSPORT_ALWAYS_INLINE void push(void* p_memory) {
+ FixedBlockAllocator()
+ : block_size_(SIZE),
+ object_size_(SIZE),
+ max_objects_(OBJECTS),
+ p_head_(NULL),
+ current_pool_index_(0),
+ block_count_(0),
+ blocks_in_use_(0),
+ allocations_(0),
+ deallocations_(0) {
+ static_assert(SIZE >= sizeof(long*), "SIZE must be at least 8 bytes");
+ p_pools_.emplace_front(
+ new typename std::aligned_storage<SIZE>::type[max_objects_]);
+ }
+
+ void push(void* p_memory) {
Block* p_block = (Block*)p_memory;
- {
- SpinLock::Acquire locked(lock_);
- p_block->p_next = p_head_;
- p_head_ = p_block;
- }
+ p_block->p_next = p_head_;
+ p_head_ = p_block;
}
- TRANSPORT_ALWAYS_INLINE void* pop() {
+ void* pop() {
Block* p_block = nullptr;
- {
- SpinLock::Acquire locked(lock_);
- if (p_head_) {
- p_block = p_head_;
- p_head_ = p_head_->p_next;
- }
+ if (p_head_) {
+ p_block = p_head_;
+ p_head_ = p_head_->p_next;
}
return (void*)p_block;
@@ -119,8 +114,8 @@ class FixedBlockAllocator {
const std::size_t max_objects_;
Block* p_head_;
- uint8_t* p_pool_;
- uint32_t pool_index_;
+ uint32_t current_pool_index_;
+ std::list<typename std::aligned_storage<SIZE>::type*> p_pools_;
uint32_t block_count_;
uint32_t blocks_in_use_;
uint32_t allocations_;
@@ -133,4 +128,88 @@ template <std::size_t A, std::size_t B>
std::unique_ptr<FixedBlockAllocator<A, B>>
FixedBlockAllocator<A, B>::instance_ = nullptr;
+/**
+ * STL Allocator trait to be used with allocate_shared.
+ */
+template <typename T, typename Pool>
+class STLAllocator {
+ /**
+ * If STLAllocator is rebound to another type (!= T) using copy constructor,
+ * we may need to access private members of the source allocator to copy
+ * memory and pool.
+ */
+ template <typename U, typename P>
+ friend class STLAllocator;
+
+ public:
+ using size_type = std::size_t;
+ using difference_type = ptrdiff_t;
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using value_type = T;
+
+ STLAllocator(pointer memory, Pool* memory_pool)
+ : memory_(memory), pool_(memory_pool) {
+ TRANSPORT_LOGV("Creating allocator. This: %p, memory: %p, memory_pool: %p",
+ this, memory, memory_pool);
+ }
+
+ ~STLAllocator() {}
+
+ template <typename U>
+ STLAllocator(const STLAllocator<U, Pool>& other) {
+ memory_ = other.memory_;
+ pool_ = other.pool_;
+ }
+
+ template <typename U>
+ struct rebind {
+ typedef STLAllocator<U, Pool> other;
+ };
+
+ pointer address(reference x) const { return &x; }
+ const_pointer address(const_reference x) const { return &x; }
+
+ pointer allocate(size_type n, pointer hint = 0) {
+ TRANSPORT_LOGV(
+ "Allocating memory (%zu). This: %p, memory: %p, memory_pool: %p", n,
+ this, memory_, pool_);
+ return static_cast<pointer>(memory_);
+ }
+
+ void deallocate(pointer p, size_type n) {
+ TRANSPORT_LOGV("Deallocating memory. This: %p, memory: %p, memory_pool: %p",
+ this, memory_, pool_);
+ pool_->deallocateBlock(memory_);
+ }
+
+ template <typename... Args>
+ void construct(pointer p, Args&&... args) {
+ new (static_cast<pointer>(p)) T(std::forward<Args>(args)...);
+ }
+
+ void destroy(pointer p) {
+ TRANSPORT_LOGV("Destroying object. This: %p, memory: %p, memory_pool: %p",
+ this, memory_, pool_);
+ p->~T();
+ }
+
+ private:
+ void* memory_;
+ Pool* pool_;
+};
+
+template <typename T, typename U, typename V>
+inline bool operator==(const STLAllocator<T, V>&, const STLAllocator<U, V>&) {
+ return true;
+}
+
+template <typename T, typename U, typename V>
+inline bool operator!=(const STLAllocator<T, V>& a,
+ const STLAllocator<U, V>& b) {
+ return !(a == b);
+}
+
} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/linux.h b/libtransport/includes/hicn/transport/utils/linux.h
index 5820528e1..105196fd2 100644
--- a/libtransport/includes/hicn/transport/utils/linux.h
+++ b/libtransport/includes/hicn/transport/utils/linux.h
@@ -17,14 +17,14 @@
#ifdef __linux__
+#include <arpa/inet.h>
#include <hicn/transport/portability/portability.h>
#include <hicn/transport/utils/log.h>
-
-#include <arpa/inet.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/socket.h>
+
#include <string>
#define LINK_LOCAL_PREFIX 0xfe80
diff --git a/libtransport/includes/hicn/transport/utils/membuf.h b/libtransport/includes/hicn/transport/utils/membuf.h
index 9fc37dd25..0db87e9dd 100644
--- a/libtransport/includes/hicn/transport/utils/membuf.h
+++ b/libtransport/includes/hicn/transport/utils/membuf.h
@@ -23,6 +23,7 @@
#include <hicn/transport/portability/portability.h>
#include <hicn/transport/utils/branch_prediction.h>
+#include <stdlib.h>
#include <atomic>
#include <cassert>
@@ -35,8 +36,6 @@
#include <type_traits>
#include <vector>
-#include <stdlib.h>
-
#ifndef _WIN32
TRANSPORT_GNU_DISABLE_WARNING("-Wshadow")
#endif
@@ -50,6 +49,8 @@ class MemBuf {
enum TakeOwnershipOp { TAKE_OWNERSHIP };
enum CopyBufferOp { COPY_BUFFER };
+ using Ptr = std::shared_ptr<MemBuf>;
+
typedef void (*FreeFunction)(void* buf, void* userData);
static std::unique_ptr<MemBuf> create(std::size_t capacity);
@@ -106,13 +107,14 @@ class MemBuf {
FreeFunction freeFn = nullptr, void* userData = nullptr,
bool freeOnError = true);
- static std::unique_ptr<MemBuf> wrapBuffer(const void* buf,
+ static std::unique_ptr<MemBuf> wrapBuffer(const void* buf, std::size_t length,
std::size_t capacity);
- static MemBuf wrapBufferAsValue(const void* buf,
+ static MemBuf wrapBufferAsValue(const void* buf, std::size_t length,
std::size_t capacity) noexcept;
- MemBuf(WrapBufferOp op, const void* buf, std::size_t capacity) noexcept;
+ MemBuf(WrapBufferOp op, const void* buf, std::size_t length,
+ std::size_t capacity) noexcept;
/**
* Convenience function to create a new MemBuf object that copies data from a
@@ -147,6 +149,8 @@ class MemBuf {
std::size_t length() const { return length_; }
+ void setLength(std::size_t length) { length_ = length; }
+
std::size_t headroom() const { return std::size_t(data_ - buffer()); }
std::size_t tailroom() const { return std::size_t(bufferEnd() - tail()); }
@@ -689,6 +693,18 @@ class MemBuf {
void* userData = nullptr,
bool freeOnError = true);
+ /**
+ * Ensure the current MemBuf can hold at least capacity bytes and its
+ * memory is contiguous
+ */
+ bool ensureCapacity(std::size_t capacity);
+
+ /**
+ * Ensure packet buffer can hold at least 1500 bytes in contiguous memory and
+ * fill unused memory with placeholder
+ */
+ bool ensureCapacityAndFillUnused(std::size_t capacity, uint8_t placeholder);
+
/*
* Overridden operator new and delete.
* These perform specialized memory management to help support
@@ -700,6 +716,12 @@ class MemBuf {
void operator delete(void* ptr);
void operator delete(void* ptr, void* placement);
+ /**
+ * Override operator == and !=
+ */
+ bool operator ==(const MemBuf &other);
+ bool operator !=(const MemBuf &other);
+
// /**
// * Iteration support: a chain of MemBufs may be iterated through using
// * STL-style iterators over const ByteRanges. Iterators are only
diff --git a/hicn-plugin/src/faces/udp/face_udp_node.h b/libtransport/includes/hicn/transport/utils/move_wrapper.h
index c759312c8..3aba345d6 100644
--- a/hicn-plugin/src/faces/udp/face_udp_node.h
+++ b/libtransport/includes/hicn/transport/utils/move_wrapper.h
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright 2017 Facebook, Inc.
+ *
* 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:
@@ -13,23 +15,25 @@
* limitations under the License.
*/
-#ifndef __HICN_FACE_UDP_NODE_H__
-#define __HICN_FACE_UDP_NODE_H__
+#pragma once
-#include <vlib/vlib.h>
-#include <vnet/vnet.h>
+#include <type_traits>
-extern vlib_node_registration_t hicn_face_udp4_input_node;
-extern vlib_node_registration_t hicn_face_udp6_input_node;
-extern vlib_node_registration_t hicn_face_udp4_output_node;
-extern vlib_node_registration_t hicn_face_udp6_output_node;
+namespace utils {
-#endif // __HICN_FACE_UDP_NODE_H__
+template <typename F>
+struct MoveWrapper : F {
+ MoveWrapper(F&& f) : F(std::move(f)) {}
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
+ MoveWrapper(MoveWrapper&&) = default;
+ MoveWrapper& operator=(MoveWrapper&&) = default;
+
+ MoveWrapper(const MoveWrapper&);
+ MoveWrapper& operator=(const MoveWrapper&);
+};
+
+template <typename T>
+auto moveHandler(T&& t) -> MoveWrapper<typename std::decay<T>::type> {
+ return std::move(t);
+}
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/noncopyable.h b/libtransport/includes/hicn/transport/utils/noncopyable.h
new file mode 100644
index 000000000..83923e647
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/noncopyable.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+namespace utils {
+
+class NonCopyable {
+ protected:
+ NonCopyable() = default;
+ ~NonCopyable() = default;
+
+ NonCopyable(const NonCopyable&) = delete;
+ NonCopyable& operator=(const NonCopyable&) = delete;
+};
+
+} // namespace utils
diff --git a/libtransport/includes/hicn/transport/utils/object_pool.h b/libtransport/includes/hicn/transport/utils/object_pool.h
index f78bd2aa2..a5e8b2eef 100644
--- a/libtransport/includes/hicn/transport/utils/object_pool.h
+++ b/libtransport/includes/hicn/transport/utils/object_pool.h
@@ -17,6 +17,7 @@
// TODO
#include <hicn/transport/utils/branch_prediction.h>
+#include <hicn/transport/utils/log.h>
#include <hicn/transport/utils/spinlock.h>
#include <deque>
@@ -33,6 +34,7 @@ class ObjectPool {
void operator()(T *t) {
if (pool_) {
+ TRANSPORT_LOGV("Back in pool");
pool_->add(t);
} else {
delete t;
@@ -44,10 +46,13 @@ class ObjectPool {
};
public:
- using Ptr = std::unique_ptr<T, ObjectDeleter>;
+ using Ptr = std::shared_ptr<T>;
ObjectPool() : destructor_(false) {}
+ // No copies
+ ObjectPool(const ObjectPool &other) = delete;
+
~ObjectPool() {
destructor_ = true;
for (auto &ptr : object_pool_) {
@@ -55,12 +60,17 @@ class ObjectPool {
}
}
+ bool empty() {
+ utils::SpinLock::Acquire locked(object_pool_lock_);
+ return object_pool_.empty();
+ }
+
std::pair<bool, Ptr> get() {
+ utils::SpinLock::Acquire locked(object_pool_lock_);
if (object_pool_.empty()) {
- return std::make_pair<bool, Ptr>(false, makePtr(nullptr));
+ return std::make_pair<bool, Ptr>(false, nullptr);
}
- utils::SpinLock::Acquire locked(object_pool_lock_);
auto ret = std::move(object_pool_.front());
object_pool_.pop_front();
return std::make_pair<bool, Ptr>(true, std::move(ret));
@@ -70,7 +80,7 @@ class ObjectPool {
utils::SpinLock::Acquire locked(object_pool_lock_);
if (TRANSPORT_EXPECT_TRUE(!destructor_)) {
- object_pool_.emplace_back(makePtr(object));
+ object_pool_.emplace_front(makePtr(object));
} else {
delete object;
}
@@ -79,12 +89,9 @@ class ObjectPool {
Ptr makePtr(T *object) { return Ptr(object, ObjectDeleter(this)); }
private:
- // No copies
- ObjectPool(const ObjectPool &other) = delete;
-
utils::SpinLock object_pool_lock_;
std::deque<Ptr> object_pool_;
- bool destructor_;
+ std::atomic<bool> destructor_;
};
-} // namespace utils \ No newline at end of file
+} // namespace utils
diff --git a/libtransport/includes/hicn/transport/utils/ring_buffer.h b/libtransport/includes/hicn/transport/utils/ring_buffer.h
index 9babe56bd..52629b82b 100644
--- a/libtransport/includes/hicn/transport/utils/ring_buffer.h
+++ b/libtransport/includes/hicn/transport/utils/ring_buffer.h
@@ -17,6 +17,7 @@
#include <atomic>
#include <cstddef>
+#include <utility>
namespace utils {
diff --git a/libtransport/includes/hicn/transport/utils/shared_ptr_utils.h b/libtransport/includes/hicn/transport/utils/shared_ptr_utils.h
new file mode 100644
index 000000000..3387997b5
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/shared_ptr_utils.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ */
+
+#pragma once
+
+#include <memory>
+
+namespace utils {
+
+template <typename Base>
+inline std::shared_ptr<Base> shared_from_base(
+ std::enable_shared_from_this<Base>* base) {
+ return base->shared_from_this();
+}
+
+template <typename Base>
+inline std::shared_ptr<const Base> shared_from_base(
+ std::enable_shared_from_this<Base> const* base) {
+ return base->shared_from_this();
+}
+
+template <typename That>
+inline std::shared_ptr<That> shared_from(That* that) {
+ return std::static_pointer_cast<That>(shared_from_base(that));
+}
+
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/singleton.h b/libtransport/includes/hicn/transport/utils/singleton.h
new file mode 100644
index 000000000..7fd8b912f
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/singleton.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.
+ */
+
+#pragma once
+
+#include <hicn/transport/utils/noncopyable.h>
+
+namespace utils {
+
+template <typename T>
+class Singleton {
+ public:
+ static T& getInstance() {
+ static T instance;
+ return instance;
+ }
+
+ protected:
+ Singleton() {}
+ ~Singleton() {}
+
+ public:
+ Singleton(Singleton const&) = delete;
+ Singleton& operator=(Singleton const&) = delete;
+};
+
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/string_utils.h b/libtransport/includes/hicn/transport/utils/string_utils.h
new file mode 100644
index 000000000..313c28cc6
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/string_utils.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <cctype>
+#include <locale>
+#include <string>
+
+namespace utils {
+
+/**
+ * Trim from start (in place)
+ */
+static inline void ltrim(std::string &s) {
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(),
+ [](int ch) { return !std::isspace(ch); }));
+}
+
+/**
+ * Trim from end (in place)
+ */
+static inline void rtrim(std::string &s) {
+ s.erase(std::find_if(s.rbegin(), s.rend(),
+ [](int ch) { return !std::isspace(ch); })
+ .base(),
+ s.end());
+}
+
+/**
+ * Trim from both ends (in place)
+ */
+static inline void trim(std::string &s) {
+ ltrim(s);
+ rtrim(s);
+}
+
+/**
+ * Trim from start (make a copy)
+ */
+static inline std::string ltrim_copy(std::string s) {
+ ltrim(s);
+ return s;
+}
+
+/**
+ * Trim from end (make a copy)
+ */
+static inline std::string rtrim_copy(std::string s) {
+ rtrim(s);
+ return s;
+}
+
+/**
+ * Trim from both ends (make a copy)
+ */
+static inline std::string trim_copy(std::string s) {
+ trim(s);
+ return s;
+}
+
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/src/CMakeLists.txt b/libtransport/src/CMakeLists.txt
index c92393775..079427fea 100644
--- a/libtransport/src/CMakeLists.txt
+++ b/libtransport/src/CMakeLists.txt
@@ -20,7 +20,7 @@ set(ASIO_STANDALONE 1)
add_subdirectory(core)
add_subdirectory(interfaces)
add_subdirectory(protocols)
-add_subdirectory(security)
+add_subdirectory(auth)
add_subdirectory(implementation)
add_subdirectory(utils)
add_subdirectory(http)
@@ -34,7 +34,16 @@ install(
COMPONENT lib${LIBTRANSPORT}-dev
)
-set (COMPILER_DEFINITIONS "-DTRANSPORT_LOG_DEF_LEVEL=TRANSPORT_LOG_${TRANSPORT_LOG_LEVEL}")
+install(
+ FILES "transport.config"
+ DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/hicn
+ COMPONENT lib${LIBTRANSPORT}
+)
+
+list(APPEND COMPILER_DEFINITIONS
+ "-DTRANSPORT_LOG_DEF_LEVEL=TRANSPORT_LOG_${TRANSPORT_LOG_LEVEL}"
+ "-DASIO_STANDALONE"
+)
list(INSERT LIBTRANSPORT_INTERNAL_INCLUDE_DIRS 0
${CMAKE_CURRENT_SOURCE_DIR}/
@@ -50,13 +59,15 @@ set(LIBTRANSPORT_INCLUDE_DIRS
if (NOT WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
else ()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4200")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4200 -D_WIN32_WINDOWS=0x0400")
if (CMAKE_BUILD_TYPE EQUAL "RELEASE")
- set(CMAKE_SHARED_LINKER_FLAGS "/NODEFAULTLIB:\"MSVCRTD\"" )
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:\"MSVCRTD\"" )
endif ()
endif ()
-if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
+
+if (${CMAKE_SYSTEM_NAME} MATCHES "Android")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -isystem -lm")
+ add_subdirectory(io_modules)
endif()
if (DISABLE_SHARED_LIBRARIES)
@@ -67,9 +78,10 @@ if (DISABLE_SHARED_LIBRARIES)
LINK_LIBRARIES ${LIBRARIES}
DEPENDS ${DEPENDENCIES}
COMPONENT lib${LIBTRANSPORT}
- INCLUDE_DIRS ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS} ${LIBTRANSPORT_INCLUDE_DIRS}
- INSTALL_ROOT_DIR hicn/transport
+ INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ HEADER_ROOT_DIR hicn/transport
DEFINITIONS ${COMPILER_DEFINITIONS}
+ VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}
)
else ()
build_library(${LIBTRANSPORT}
@@ -79,13 +91,18 @@ else ()
LINK_LIBRARIES ${LIBRARIES}
DEPENDS ${DEPENDENCIES}
COMPONENT lib${LIBTRANSPORT}
- INCLUDE_DIRS ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS} ${LIBTRANSPORT_INCLUDE_DIRS}
- INSTALL_ROOT_DIR hicn/transport
+ INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ HEADER_ROOT_DIR hicn/transport
DEFINITIONS ${COMPILER_DEFINITIONS}
+ VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}
)
endif ()
-if (${COMPILE_TESTS})
- add_subdirectory(core/test)
- add_subdirectory(transport/test)
+# io modules
+if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Android")
+ add_subdirectory(io_modules)
+endif()
+
+if (${BUILD_TESTS})
+ add_subdirectory(test)
endif()
diff --git a/libtransport/src/auth/CMakeLists.txt b/libtransport/src/auth/CMakeLists.txt
new file mode 100644
index 000000000..0e7b5832b
--- /dev/null
+++ b/libtransport/src/auth/CMakeLists.txt
@@ -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.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/signer.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/verifier.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/identity.cc
+)
+
+set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/auth/identity.cc b/libtransport/src/auth/identity.cc
new file mode 100644
index 000000000..bd787b9b6
--- /dev/null
+++ b/libtransport/src/auth/identity.cc
@@ -0,0 +1,116 @@
+/*
+ * 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 <hicn/transport/auth/identity.h>
+
+using namespace std;
+
+namespace transport {
+namespace auth {
+
+Identity::Identity(const string &keystore_path, const string &keystore_pwd,
+ CryptoSuite suite, unsigned int signature_len,
+ unsigned int validity_days, const string &subject_name)
+ : identity_(nullptr), signer_(nullptr) {
+ parcSecurity_Init();
+
+ bool success = parcPkcs12KeyStore_CreateFile(
+ keystore_path.c_str(), keystore_pwd.c_str(), subject_name.c_str(),
+ parcCryptoSuite_GetSigningAlgorithm(static_cast<PARCCryptoSuite>(suite)),
+ signature_len, validity_days);
+
+ parcAssertTrue(
+ success,
+ "parcPkcs12KeyStore_CreateFile('%s', '%s', '%s', %d, %d, %d) failed.",
+ keystore_path.c_str(), keystore_pwd.c_str(), subject_name.c_str(),
+ static_cast<int>(suite), static_cast<int>(signature_len), validity_days);
+
+ PARCIdentityFile *identity_file =
+ parcIdentityFile_Create(keystore_path.c_str(), keystore_pwd.c_str());
+
+ identity_ =
+ parcIdentity_Create(identity_file, PARCIdentityFileAsPARCIdentity);
+
+ PARCSigner *signer = parcIdentity_CreateSigner(
+ identity_,
+ parcCryptoSuite_GetCryptoHash(static_cast<PARCCryptoSuite>(suite)));
+
+ signer_ = make_shared<AsymmetricSigner>(signer);
+
+ parcSigner_Release(&signer);
+ parcIdentityFile_Release(&identity_file);
+}
+
+Identity::Identity(string &keystore_path, string &keystore_pwd,
+ CryptoHashType hash_type)
+ : identity_(nullptr), signer_(nullptr) {
+ parcSecurity_Init();
+
+ PARCIdentityFile *identity_file =
+ parcIdentityFile_Create(keystore_path.c_str(), keystore_pwd.c_str());
+
+ identity_ =
+ parcIdentity_Create(identity_file, PARCIdentityFileAsPARCIdentity);
+
+ PARCSigner *signer = parcIdentity_CreateSigner(
+ identity_, static_cast<PARCCryptoHashType>(hash_type));
+
+ signer_ = make_shared<AsymmetricSigner>(signer);
+
+ parcSigner_Release(&signer);
+ parcIdentityFile_Release(&identity_file);
+}
+
+Identity::Identity(const Identity &other)
+ : identity_(nullptr), signer_(other.signer_) {
+ parcSecurity_Init();
+ identity_ = parcIdentity_Acquire(other.identity_);
+}
+
+Identity::Identity(Identity &&other)
+ : identity_(nullptr), signer_(move(other.signer_)) {
+ parcSecurity_Init();
+ identity_ = parcIdentity_Acquire(other.identity_);
+ parcIdentity_Release(&other.identity_);
+}
+
+Identity::~Identity() {
+ if (identity_) parcIdentity_Release(&identity_);
+ parcSecurity_Fini();
+}
+
+shared_ptr<AsymmetricSigner> Identity::getSigner() const { return signer_; }
+
+string Identity::getFilename() const {
+ return string(parcIdentity_GetFileName(identity_));
+}
+
+string Identity::getPassword() const {
+ return string(parcIdentity_GetPassWord(identity_));
+}
+
+Identity Identity::generateIdentity(const string &subject_name) {
+ string keystore_name = "keystore";
+ string keystore_password = "password";
+ size_t key_length = 1024;
+ unsigned int validity_days = 30;
+ CryptoSuite suite = CryptoSuite::RSA_SHA256;
+
+ return Identity(keystore_name, keystore_password, suite,
+ (unsigned int)key_length, validity_days, subject_name);
+}
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/src/auth/signer.cc b/libtransport/src/auth/signer.cc
new file mode 100644
index 000000000..99c3d099d
--- /dev/null
+++ b/libtransport/src/auth/signer.cc
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/transport/auth/signer.h>
+
+extern "C" {
+#ifndef _WIN32
+TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat")
+#endif
+#include <hicn/hicn.h>
+}
+
+#include <chrono>
+
+#define ALLOW_UNALIGNED_READS 1
+
+using namespace std;
+
+namespace transport {
+namespace auth {
+
+Signer::Signer() : signer_(nullptr), key_id_(nullptr) { parcSecurity_Init(); }
+
+Signer::Signer(PARCSigner *signer) : Signer() { setSigner(signer); }
+
+Signer::~Signer() {
+ if (signer_) parcSigner_Release(&signer_);
+ if (key_id_) parcKeyId_Release(&key_id_);
+ parcSecurity_Fini();
+}
+
+void Signer::signPacket(PacketPtr packet) {
+ parcAssertNotNull(signer_, "Expected non-null signer");
+
+ const utils::MemBuf &header_chain = *packet;
+ core::Packet::Format format = packet->getFormat();
+ auto suite = getCryptoSuite();
+ size_t signature_len = getSignatureSize();
+
+ if (!packet->authenticationHeader()) {
+ throw errors::MalformedAHPacketException();
+ }
+
+ packet->setSignatureSize(signature_len);
+
+ // Copy IP+TCP / ICMP header before zeroing them
+ hicn_header_t header_copy;
+ hicn_packet_copy_header(format, packet->packet_start_, &header_copy, false);
+ packet->resetForHash();
+
+ // Fill in the HICN_AH header
+ auto now = chrono::duration_cast<chrono::milliseconds>(
+ chrono::system_clock::now().time_since_epoch())
+ .count();
+ packet->setSignatureTimestamp(now);
+ packet->setValidationAlgorithm(suite);
+
+ // Set the key ID
+ KeyId key_id;
+ key_id.first = static_cast<uint8_t *>(
+ parcBuffer_Overlay((PARCBuffer *)parcKeyId_GetKeyId(key_id_), 0));
+ packet->setKeyId(key_id);
+
+ // Calculate hash
+ CryptoHasher hasher(parcSigner_GetCryptoHasher(signer_));
+ const utils::MemBuf *current = &header_chain;
+
+ hasher.init();
+
+ do {
+ hasher.updateBytes(current->data(), current->length());
+ current = current->next();
+ } while (current != &header_chain);
+
+ CryptoHash hash = hasher.finalize();
+
+ // Compute signature
+ PARCSignature *signature = parcSigner_SignDigestNoAlloc(
+ signer_, hash.hash_, packet->getSignature(), (uint32_t)signature_len);
+ PARCBuffer *buffer = parcSignature_GetSignature(signature);
+ size_t bytes_len = parcBuffer_Remaining(buffer);
+
+ if (bytes_len > signature_len) {
+ throw errors::MalformedAHPacketException();
+ }
+
+ // Put signature in AH header
+ hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false);
+
+ // Release allocated objects
+ parcSignature_Release(&signature);
+}
+
+void Signer::setSigner(PARCSigner *signer) {
+ parcAssertNotNull(signer, "Expected non-null signer");
+
+ if (signer_) parcSigner_Release(&signer_);
+ if (key_id_) parcKeyId_Release(&key_id_);
+
+ signer_ = parcSigner_Acquire(signer);
+ key_id_ = parcSigner_CreateKeyId(signer_);
+}
+
+size_t Signer::getSignatureSize() const {
+ parcAssertNotNull(signer_, "Expected non-null signer");
+ return parcSigner_GetSignatureSize(signer_);
+}
+
+CryptoSuite Signer::getCryptoSuite() const {
+ parcAssertNotNull(signer_, "Expected non-null signer");
+ return static_cast<CryptoSuite>(parcSigner_GetCryptoSuite(signer_));
+}
+
+CryptoHashType Signer::getCryptoHashType() const {
+ parcAssertNotNull(signer_, "Expected non-null signer");
+ return static_cast<CryptoHashType>(parcSigner_GetCryptoHashType(signer_));
+}
+
+PARCSigner *Signer::getParcSigner() const { return signer_; }
+
+PARCKeyStore *Signer::getParcKeyStore() const {
+ parcAssertNotNull(signer_, "Expected non-null signer");
+ return parcSigner_GetKeyStore(signer_);
+}
+
+AsymmetricSigner::AsymmetricSigner(CryptoSuite suite, PARCKeyStore *key_store) {
+ parcAssertNotNull(key_store, "Expected non-null key_store");
+
+ auto crypto_suite = static_cast<PARCCryptoSuite>(suite);
+
+ switch (suite) {
+ case CryptoSuite::DSA_SHA256:
+ case CryptoSuite::RSA_SHA256:
+ case CryptoSuite::RSA_SHA512:
+ case CryptoSuite::ECDSA_256K1:
+ break;
+ default:
+ throw errors::RuntimeException(
+ "Invalid crypto suite for asymmetric signer");
+ }
+
+ setSigner(
+ parcSigner_Create(parcPublicKeySigner_Create(key_store, crypto_suite),
+ PARCPublicKeySignerAsSigner));
+}
+
+SymmetricSigner::SymmetricSigner(CryptoSuite suite, PARCKeyStore *key_store) {
+ parcAssertNotNull(key_store, "Expected non-null key_store");
+
+ auto crypto_suite = static_cast<PARCCryptoSuite>(suite);
+
+ switch (suite) {
+ case CryptoSuite::HMAC_SHA256:
+ case CryptoSuite::HMAC_SHA512:
+ break;
+ default:
+ throw errors::RuntimeException(
+ "Invalid crypto suite for symmetric signer");
+ }
+
+ setSigner(parcSigner_Create(parcSymmetricKeySigner_Create(
+ (PARCSymmetricKeyStore *)key_store,
+ parcCryptoSuite_GetCryptoHash(crypto_suite)),
+ PARCSymmetricKeySignerAsSigner));
+}
+
+SymmetricSigner::SymmetricSigner(CryptoSuite suite, const string &passphrase) {
+ auto crypto_suite = static_cast<PARCCryptoSuite>(suite);
+
+ switch (suite) {
+ case CryptoSuite::HMAC_SHA256:
+ case CryptoSuite::HMAC_SHA512:
+ break;
+ default:
+ throw errors::RuntimeException(
+ "Invalid crypto suite for symmetric signer");
+ }
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcBufferComposer_PutString(composer, passphrase.c_str());
+ PARCBuffer *key_buf = parcBufferComposer_ProduceBuffer(composer);
+ parcBufferComposer_Release(&composer);
+
+ PARCSymmetricKeyStore *key_store = parcSymmetricKeyStore_Create(key_buf);
+ PARCSymmetricKeySigner *key_signer = parcSymmetricKeySigner_Create(
+ key_store, parcCryptoSuite_GetCryptoHash(crypto_suite));
+
+ setSigner(parcSigner_Create(key_signer, PARCSymmetricKeySignerAsSigner));
+
+ parcSymmetricKeySigner_Release(&key_signer);
+ parcSymmetricKeyStore_Release(&key_store);
+ parcBuffer_Release(&key_buf);
+}
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/src/auth/verifier.cc b/libtransport/src/auth/verifier.cc
new file mode 100644
index 000000000..c6648a763
--- /dev/null
+++ b/libtransport/src/auth/verifier.cc
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/transport/auth/verifier.h>
+#include <protocols/errors.h>
+
+extern "C" {
+#ifndef _WIN32
+TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat")
+#endif
+#include <hicn/hicn.h>
+}
+
+#include <sys/stat.h>
+
+using namespace std;
+
+namespace transport {
+namespace auth {
+
+const std::vector<VerificationPolicy> Verifier::DEFAULT_FAILED_POLICIES = {
+ VerificationPolicy::DROP,
+ VerificationPolicy::ABORT,
+};
+
+Verifier::Verifier()
+ : hasher_(nullptr),
+ verifier_(nullptr),
+ verification_failed_cb_(interface::VOID_HANDLER),
+ failed_policies_(DEFAULT_FAILED_POLICIES) {
+ parcSecurity_Init();
+ PARCInMemoryVerifier *in_memory_verifier = parcInMemoryVerifier_Create();
+ verifier_ =
+ parcVerifier_Create(in_memory_verifier, PARCInMemoryVerifierAsVerifier);
+ parcInMemoryVerifier_Release(&in_memory_verifier);
+}
+
+Verifier::~Verifier() {
+ if (hasher_) parcCryptoHasher_Release(&hasher_);
+ if (verifier_) parcVerifier_Release(&verifier_);
+ parcSecurity_Fini();
+}
+
+bool Verifier::verifyPacket(PacketPtr packet) {
+ bool valid_packet = false;
+ core::Packet::Format format = packet->getFormat();
+
+ if (!packet->authenticationHeader()) {
+ throw errors::MalformedAHPacketException();
+ }
+
+ // Get crypto suite and hash type
+ auto suite = static_cast<PARCCryptoSuite>(packet->getValidationAlgorithm());
+ PARCCryptoHashType hash_type = parcCryptoSuite_GetCryptoHash(suite);
+
+ // Copy IP+TCP / ICMP header before zeroing them
+ hicn_header_t header_copy;
+ hicn_packet_copy_header(format, packet->packet_start_, &header_copy, false);
+
+ // Fetch packet signature
+ uint8_t *packet_signature = packet->getSignature();
+ size_t signature_len = Verifier::getSignatureSize(packet);
+ vector<uint8_t> signature_raw(packet_signature,
+ packet_signature + signature_len);
+
+ // Create a signature buffer from the raw packet signature
+ PARCBuffer *bits =
+ parcBuffer_Wrap(signature_raw.data(), signature_len, 0, signature_len);
+ parcBuffer_Rewind(bits);
+
+ // If the signature algo is ECDSA, the signature might be shorter than the
+ // signature field
+ PARCSigningAlgorithm algo = parcCryptoSuite_GetSigningAlgorithm(suite);
+ if (algo == PARCSigningAlgorithm_ECDSA) {
+ while (parcBuffer_HasRemaining(bits) && parcBuffer_GetUint8(bits) == 0)
+ ;
+ parcBuffer_SetPosition(bits, parcBuffer_Position(bits) - 1);
+ }
+
+ if (!parcBuffer_HasRemaining(bits)) {
+ parcBuffer_Release(&bits);
+ return false;
+ }
+
+ // Create a signature object from the signature buffer
+ PARCSignature *signature = parcSignature_Create(
+ parcCryptoSuite_GetSigningAlgorithm(suite), hash_type, bits);
+
+ // Fetch the key to verify the signature
+ KeyId key_buffer = packet->getKeyId();
+ PARCBuffer *buffer = parcBuffer_Wrap(key_buffer.first, key_buffer.second, 0,
+ key_buffer.second);
+ PARCKeyId *key_id = parcKeyId_Create(buffer);
+
+ // Reset fields that are not used to compute signature
+ packet->resetForHash();
+
+ // Compute the packet hash
+ if (!hasher_)
+ setHasher(parcVerifier_GetCryptoHasher(verifier_, key_id, hash_type));
+ CryptoHash local_hash = computeHash(packet);
+
+ // Compare the packet signature to the locally computed one
+ valid_packet = parcVerifier_VerifyDigestSignature(
+ verifier_, key_id, local_hash.hash_, suite, signature);
+
+ // Restore the fields that were reset
+ hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false);
+
+ // Release allocated objects
+ parcBuffer_Release(&buffer);
+ parcKeyId_Release(&key_id);
+ parcSignature_Release(&signature);
+ parcBuffer_Release(&bits);
+
+ return valid_packet;
+}
+
+vector<VerificationPolicy> Verifier::verifyPackets(
+ const vector<PacketPtr> &packets) {
+ vector<VerificationPolicy> policies(packets.size(), VerificationPolicy::DROP);
+
+ for (unsigned int i = 0; i < packets.size(); ++i) {
+ if (verifyPacket(packets[i])) {
+ policies[i] = VerificationPolicy::ACCEPT;
+ }
+
+ callVerificationFailedCallback(packets[i], policies[i]);
+ }
+
+ return policies;
+}
+
+vector<VerificationPolicy> Verifier::verifyPackets(
+ const vector<PacketPtr> &packets,
+ const unordered_map<Suffix, HashEntry> &suffix_map) {
+ vector<VerificationPolicy> policies(packets.size(),
+ VerificationPolicy::UNKNOWN);
+
+ for (unsigned int i = 0; i < packets.size(); ++i) {
+ uint32_t suffix = packets[i]->getName().getSuffix();
+ auto manifest_hash = suffix_map.find(suffix);
+
+ if (manifest_hash != suffix_map.end()) {
+ CryptoHashType hash_type = manifest_hash->second.first;
+ CryptoHash packet_hash = packets[i]->computeDigest(hash_type);
+
+ if (!CryptoHash::compareBinaryDigest(
+ packet_hash.getDigest<uint8_t>().data(),
+ manifest_hash->second.second.data(), hash_type)) {
+ policies[i] = VerificationPolicy::ABORT;
+ } else {
+ policies[i] = VerificationPolicy::ACCEPT;
+ }
+ }
+
+ callVerificationFailedCallback(packets[i], policies[i]);
+ }
+
+ return policies;
+}
+
+void Verifier::addKey(PARCKey *key) { parcVerifier_AddKey(verifier_, key); }
+
+void Verifier::setHasher(PARCCryptoHasher *hasher) {
+ parcAssertNotNull(hasher, "Expected non-null hasher");
+ if (hasher_) parcCryptoHasher_Release(&hasher_);
+ hasher_ = parcCryptoHasher_Acquire(hasher);
+}
+
+void Verifier::setVerificationFailedCallback(
+ VerificationFailedCallback verfication_failed_cb,
+ const vector<VerificationPolicy> &failed_policies) {
+ verification_failed_cb_ = verfication_failed_cb;
+ failed_policies_ = failed_policies;
+}
+
+void Verifier::getVerificationFailedCallback(
+ VerificationFailedCallback **verfication_failed_cb) {
+ *verfication_failed_cb = &verification_failed_cb_;
+}
+
+size_t Verifier::getSignatureSize(const PacketPtr packet) {
+ return packet->getSignatureSize();
+}
+
+CryptoHash Verifier::computeHash(PacketPtr packet) {
+ parcAssertNotNull(hasher_, "Expected non-null hasher");
+
+ CryptoHasher crypto_hasher(hasher_);
+ const utils::MemBuf &header_chain = *packet;
+ const utils::MemBuf *current = &header_chain;
+
+ crypto_hasher.init();
+
+ do {
+ crypto_hasher.updateBytes(current->data(), current->length());
+ current = current->next();
+ } while (current != &header_chain);
+
+ return crypto_hasher.finalize();
+}
+
+void Verifier::callVerificationFailedCallback(PacketPtr packet,
+ VerificationPolicy &policy) {
+ if (verification_failed_cb_ == interface::VOID_HANDLER) {
+ return;
+ }
+
+ if (find(failed_policies_.begin(), failed_policies_.end(), policy) !=
+ failed_policies_.end()) {
+ policy = verification_failed_cb_(
+ static_cast<const core::ContentObject &>(*packet),
+ make_error_code(
+ protocol::protocol_error::signature_verification_failed));
+ }
+}
+
+bool VoidVerifier::verifyPacket(PacketPtr packet) { return true; }
+
+vector<VerificationPolicy> VoidVerifier::verifyPackets(
+ const vector<PacketPtr> &packets) {
+ return vector<VerificationPolicy>(packets.size(), VerificationPolicy::ACCEPT);
+}
+
+vector<VerificationPolicy> VoidVerifier::verifyPackets(
+ const vector<PacketPtr> &packets,
+ const unordered_map<Suffix, HashEntry> &suffix_map) {
+ return vector<VerificationPolicy>(packets.size(), VerificationPolicy::ACCEPT);
+}
+
+AsymmetricVerifier::AsymmetricVerifier(PARCKey *pub_key) { addKey(pub_key); }
+
+AsymmetricVerifier::AsymmetricVerifier(const string &cert_path) {
+ setCertificate(cert_path);
+}
+
+void AsymmetricVerifier::setCertificate(const string &cert_path) {
+ PARCCertificateFactory *factory = parcCertificateFactory_Create(
+ PARCCertificateType_X509, PARCContainerEncoding_PEM);
+
+ struct stat buffer;
+ if (stat(cert_path.c_str(), &buffer) != 0) {
+ throw errors::RuntimeException("Certificate does not exist");
+ }
+
+ PARCCertificate *certificate =
+ parcCertificateFactory_CreateCertificateFromFile(factory,
+ cert_path.c_str(), NULL);
+ PARCKey *key = parcCertificate_GetPublicKey(certificate);
+
+ addKey(key);
+
+ parcKey_Release(&key);
+ parcCertificateFactory_Release(&factory);
+}
+
+SymmetricVerifier::SymmetricVerifier(const string &passphrase)
+ : passphrase_(nullptr), signer_(nullptr) {
+ setPassphrase(passphrase);
+}
+
+SymmetricVerifier::~SymmetricVerifier() {
+ if (passphrase_) parcBuffer_Release(&passphrase_);
+ if (signer_) parcSigner_Release(&signer_);
+}
+
+void SymmetricVerifier::setPassphrase(const string &passphrase) {
+ if (passphrase_) parcBuffer_Release(&passphrase_);
+
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcBufferComposer_PutString(composer, passphrase.c_str());
+ passphrase_ = parcBufferComposer_ProduceBuffer(composer);
+ parcBufferComposer_Release(&composer);
+}
+
+void SymmetricVerifier::setSigner(const PARCCryptoSuite &suite) {
+ parcAssertNotNull(passphrase_, "Expected non-null passphrase");
+
+ if (signer_) parcSigner_Release(&signer_);
+
+ PARCSymmetricKeyStore *key_store = parcSymmetricKeyStore_Create(passphrase_);
+ PARCSymmetricKeySigner *key_signer = parcSymmetricKeySigner_Create(
+ key_store, parcCryptoSuite_GetCryptoHash(suite));
+ signer_ = parcSigner_Create(key_signer, PARCSymmetricKeySignerAsSigner);
+
+ PARCKeyId *key_id = parcSigner_CreateKeyId(signer_);
+ PARCKey *key = parcKey_CreateFromSymmetricKey(
+ key_id, parcSigner_GetSigningAlgorithm(signer_), passphrase_);
+
+ addKey(key);
+ setHasher(parcSigner_GetCryptoHasher(signer_));
+
+ parcSymmetricKeyStore_Release(&key_store);
+ parcSymmetricKeySigner_Release(&key_signer);
+ parcKeyId_Release(&key_id);
+ parcKey_Release(&key);
+}
+
+vector<VerificationPolicy> SymmetricVerifier::verifyPackets(
+ const vector<PacketPtr> &packets) {
+ vector<VerificationPolicy> policies(packets.size(), VerificationPolicy::DROP);
+
+ for (unsigned int i = 0; i < packets.size(); ++i) {
+ auto suite =
+ static_cast<PARCCryptoSuite>(packets[i]->getValidationAlgorithm());
+
+ if (!signer_ || suite != parcSigner_GetCryptoSuite(signer_)) {
+ setSigner(suite);
+ }
+
+ if (verifyPacket(packets[i])) {
+ policies[i] = VerificationPolicy::ACCEPT;
+ }
+
+ callVerificationFailedCallback(packets[i], policies[i]);
+ }
+
+ return policies;
+}
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/src/config.h.in b/libtransport/src/config.h.in
index 4e9a0f262..ef47affda 100644
--- a/libtransport/src/config.h.in
+++ b/libtransport/src/config.h.in
@@ -25,10 +25,6 @@
#cmakedefine ASIO_STANDALONE
#endif
-#ifndef SECURE_HICNTRANSPORT
-#cmakedefine SECURE_HICNTRANSPORT
-#endif
-
#define RAAQM_CONFIG_PATH "@raaqm_config_path@"
#cmakedefine __vpp__
diff --git a/libtransport/src/core/CMakeLists.txt b/libtransport/src/core/CMakeLists.txt
index 5c8ab9270..4e3ac10ec 100644
--- a/libtransport/src/core/CMakeLists.txt
+++ b/libtransport/src/core/CMakeLists.txt
@@ -21,55 +21,27 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/manifest_format.h
${CMAKE_CURRENT_SOURCE_DIR}/pending_interest.h
${CMAKE_CURRENT_SOURCE_DIR}/portal.h
- ${CMAKE_CURRENT_SOURCE_DIR}/connector.h
- ${CMAKE_CURRENT_SOURCE_DIR}/tcp_socket_connector.h
- ${CMAKE_CURRENT_SOURCE_DIR}/udp_socket_connector.h
- ${CMAKE_CURRENT_SOURCE_DIR}/forwarder_interface.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_forwarder_interface.h
- ${CMAKE_CURRENT_SOURCE_DIR}/vpp_forwarder_interface.h
- ${CMAKE_CURRENT_SOURCE_DIR}/memif_connector.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/errors.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/global_configuration.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/local_connector.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rs.h
)
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/content_object.cc
${CMAKE_CURRENT_SOURCE_DIR}/interest.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/errors.cc
${CMAKE_CURRENT_SOURCE_DIR}/packet.cc
${CMAKE_CURRENT_SOURCE_DIR}/name.cc
${CMAKE_CURRENT_SOURCE_DIR}/prefix.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/tcp_socket_connector.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/udp_socket_connector.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_forwarder_interface.cc
${CMAKE_CURRENT_SOURCE_DIR}/manifest_format_fixed.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/connector.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/portal.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/global_configuration.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/io_module.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/local_connector.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/fec.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rs.cc
)
-if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
- if (BUILD_WITH_VPP OR BUILD_HICNPLUGIN)
- list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/vpp_forwarder_interface.h
- ${CMAKE_CURRENT_SOURCE_DIR}/memif_connector.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_vapi.h
- ${CMAKE_CURRENT_SOURCE_DIR}/memif_vapi.h
- )
-
- list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/vpp_forwarder_interface.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/memif_connector.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/hicn_vapi.c
- ${CMAKE_CURRENT_SOURCE_DIR}/memif_vapi.c
- )
- endif()
-
- list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/raw_socket_connector.h
- ${CMAKE_CURRENT_SOURCE_DIR}/raw_socket_interface.h
- )
-
- list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/raw_socket_connector.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/raw_socket_interface.cc
- )
-endif()
-
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file
diff --git a/libtransport/src/core/content_object.cc b/libtransport/src/core/content_object.cc
index f5cccf404..0c68ef559 100644
--- a/libtransport/src/core/content_object.cc
+++ b/libtransport/src/core/content_object.cc
@@ -32,8 +32,9 @@ namespace transport {
namespace core {
-ContentObject::ContentObject(const Name &name, Packet::Format format)
- : Packet(format) {
+ContentObject::ContentObject(const Name &name, Packet::Format format,
+ std::size_t additional_header_size)
+ : Packet(format, additional_header_size) {
if (TRANSPORT_EXPECT_FALSE(
hicn_data_set_name(format, packet_start_, &name.name_) < 0)) {
throw errors::RuntimeException("Error filling the packet name.");
@@ -47,41 +48,32 @@ ContentObject::ContentObject(const Name &name, Packet::Format format)
}
#ifdef __ANDROID__
-ContentObject::ContentObject(hicn_format_t format)
- : ContentObject(Name("0::0|0"), format) {}
+ContentObject::ContentObject(hicn_format_t format,
+ std::size_t additional_header_size)
+ : ContentObject(Name("0::0|0"), format, additional_header_size) {}
#else
-ContentObject::ContentObject(hicn_format_t format)
- : ContentObject(Packet::base_name, format) {}
+ContentObject::ContentObject(hicn_format_t format,
+ std::size_t additional_header_size)
+ : ContentObject(Packet::base_name, format, additional_header_size) {}
#endif
ContentObject::ContentObject(const Name &name, hicn_format_t format,
+ std::size_t additional_header_size,
const uint8_t *payload, std::size_t size)
- : ContentObject(name, format) {
+ : ContentObject(name, format, additional_header_size) {
appendPayload(payload, size);
}
-ContentObject::ContentObject(const uint8_t *buffer, std::size_t size)
- : Packet(buffer, size) {
- if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
- 0) {
- throw errors::RuntimeException("Error getting name from content object.");
- }
+ContentObject::ContentObject(ContentObject &&other) : Packet(std::move(other)) {
+ name_ = std::move(other.name_);
}
-ContentObject::ContentObject(MemBufPtr &&buffer) : Packet(std::move(buffer)) {
- if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
- 0) {
- throw errors::RuntimeException("Error getting name from content object.");
- }
+ContentObject::ContentObject(const ContentObject &other) : Packet(other) {
+ name_ = other.name_;
}
-ContentObject::ContentObject(ContentObject &&other) : Packet(std::move(other)) {
- name_ = std::move(other.name_);
-
- if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
- 0) {
- throw errors::MalformedPacketException();
- }
+ContentObject &ContentObject::operator=(const ContentObject &other) {
+ return (ContentObject &)Packet::operator=(other);
}
ContentObject::~ContentObject() {}
@@ -132,10 +124,11 @@ uint32_t ContentObject::getPathLabel() const {
"Error retrieving the path label from content object");
}
- return path_label;
+ return ntohl(path_label);
}
ContentObject &ContentObject::setPathLabel(uint32_t path_label) {
+ path_label = htonl(path_label);
if (hicn_data_set_path_label((hicn_header_t *)packet_start_, path_label) <
0) {
throw errors::RuntimeException(
diff --git a/libtransport/src/core/errors.cc b/libtransport/src/core/errors.cc
new file mode 100644
index 000000000..82647a60b
--- /dev/null
+++ b/libtransport/src/core/errors.cc
@@ -0,0 +1,49 @@
+/*
+ * 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 <core/errors.h>
+
+namespace transport {
+namespace core {
+
+const std::error_category& core_category() {
+ static core_category_impl instance;
+
+ return instance;
+}
+
+const char* core_category_impl::name() const throw() {
+ return "transport::protocol::error";
+}
+
+std::string core_category_impl::message(int ev) const {
+ switch (static_cast<core_error>(ev)) {
+ case core_error::success: {
+ return "Success";
+ }
+ case core_error::configuration_parse_failed: {
+ return "Error parsing configuration.";
+ }
+ case core_error::configuration_not_applied: {
+ return "Configuration was not applied due to wrong parameters.";
+ }
+ default: {
+ return "Unknown core error";
+ }
+ }
+}
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/core/errors.h b/libtransport/src/core/errors.h
new file mode 100644
index 000000000..a46f1dbcd
--- /dev/null
+++ b/libtransport/src/core/errors.h
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <system_error>
+
+namespace transport {
+namespace core {
+
+/**
+ * @brief Get the default server error category.
+ * @return The default server error category instance.
+ *
+ * @warning The first call to this function is thread-safe only starting with
+ * C++11.
+ */
+const std::error_category& core_category();
+
+/**
+ * The list of errors.
+ */
+enum class core_error {
+ success = 0,
+ configuration_parse_failed,
+ configuration_not_applied
+};
+
+/**
+ * @brief Create an error_code instance for the given error.
+ * @param error The error.
+ * @return The error_code instance.
+ */
+inline std::error_code make_error_code(core_error error) {
+ return std::error_code(static_cast<int>(error), core_category());
+}
+
+/**
+ * @brief Create an error_condition instance for the given error.
+ * @param error The error.
+ * @return The error_condition instance.
+ */
+inline std::error_condition make_error_condition(core_error error) {
+ return std::error_condition(static_cast<int>(error), core_category());
+}
+
+/**
+ * @brief A server error category.
+ */
+class core_category_impl : public std::error_category {
+ public:
+ /**
+ * @brief Get the name of the category.
+ * @return The name of the category.
+ */
+ virtual const char* name() const throw();
+
+ /**
+ * @brief Get the error message for a given error.
+ * @param ev The error numeric value.
+ * @return The message associated to the error.
+ */
+ virtual std::string message(int ev) const;
+};
+} // namespace core
+} // namespace transport
+
+namespace std {
+// namespace system {
+template <>
+struct is_error_code_enum<::transport::core::core_error>
+ : public std::true_type {};
+// } // namespace system
+} // namespace std \ No newline at end of file
diff --git a/libtransport/src/core/facade.h b/libtransport/src/core/facade.h
index 04f643f63..199081271 100644
--- a/libtransport/src/core/facade.h
+++ b/libtransport/src/core/facade.h
@@ -15,36 +15,14 @@
#pragma once
-#include <core/forwarder_interface.h>
-#include <core/hicn_forwarder_interface.h>
#include <core/manifest_format_fixed.h>
#include <core/manifest_inline.h>
#include <core/portal.h>
-#ifdef __linux__
-#ifndef __ANDROID__
-#include <core/raw_socket_interface.h>
-#ifdef __vpp__
-#include <core/vpp_forwarder_interface.h>
-#endif
-#endif
-#endif
-
namespace transport {
namespace core {
-using HicnForwarderPortal = Portal<HicnForwarderInterface>;
-
-#ifdef __linux__
-#ifndef __ANDROID__
-using RawSocketPortal = Portal<RawSocketInterface>;
-#endif
-#ifdef __vpp__
-using VPPForwarderPortal = Portal<VPPForwarderInterface>;
-#endif
-#endif
-
using ContentObjectManifest = core::ManifestInline<ContentObject, Fixed>;
using InterestManifest = core::ManifestInline<Interest, Fixed>;
diff --git a/libtransport/src/core/fec.cc b/libtransport/src/core/fec.cc
new file mode 100644
index 000000000..0ce9625a2
--- /dev/null
+++ b/libtransport/src/core/fec.cc
@@ -0,0 +1,880 @@
+/*
+ * fec.c -- forward error correction based on Vandermonde matrices
+ * 980624
+ * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it)
+ *
+ * Portions derived from code by Phil Karn (karn@ka9q.ampr.org),
+ * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari
+ * Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+/*
+ * The following parameter defines how many bits are used for
+ * field elements. The code supports any value from 2 to 16
+ * but fastest operation is achieved with 8 bit elements
+ * This is the only parameter you may want to change.
+ */
+#ifndef GF_BITS
+#define GF_BITS 8 /* code over GF(2**GF_BITS) - change to suit */
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <hicn/transport/portability/platform.h>
+#include "fec.h"
+
+/**
+ * XXX This disable a warning raising only in some platforms.
+ * TODO Check if this warning is a mistake or it is a real bug:
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83404
+ * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=88059
+ */
+#ifndef __clang__
+#ifndef _WIN32
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
+#endif
+
+/*
+ * compatibility stuff
+ */
+#if defined (MSDOS) || defined (_WIN32) /* but also for others, e.g. sun... */
+#define NEED_BCOPY
+#define bcmp(a,b,n) memcmp(a,b,n)
+#endif
+
+#ifdef ANDROID
+#define bcmp(a,b,n) memcmp(a,b,n)
+#endif
+
+#ifdef NEED_BCOPY
+#define bcopy(s, d, siz) memcpy((d), (s), (siz))
+#define bzero(d, siz) memset((d), '\0', (siz))
+#endif
+
+/*
+ * stuff used for testing purposes only
+ */
+
+#ifdef TEST
+#define DEB(x)
+#define DDB(x) x
+#define DEBUG 0 /* minimal debugging */
+#ifdef MSDOS
+#include <time.h>
+struct timeval {
+ unsigned long ticks;
+};
+#define gettimeofday(x, dummy) { (x)->ticks = clock() ; }
+#define DIFF_T(a,b) (1+ 1000000*(a.ticks - b.ticks) / CLOCKS_PER_SEC )
+typedef unsigned long u_long ;
+typedef unsigned short u_short ;
+#else /* typically, unix systems */
+#include <sys/time.h>
+#define DIFF_T(a,b) \
+ (1+ 1000000*(a.tv_sec - b.tv_sec) + (a.tv_usec - b.tv_usec) )
+#endif
+
+#define TICK(t) \
+ {struct timeval x ; \
+ gettimeofday(&x, NULL) ; \
+ t = x.tv_usec + 1000000* (x.tv_sec & 0xff ) ; \
+ }
+#define TOCK(t) \
+ { u_long t1 ; TICK(t1) ; \
+ if (t1 < t) t = 256000000 + t1 - t ; \
+ else t = t1 - t ; \
+ if (t == 0) t = 1 ;}
+
+u_long ticks[10]; /* vars for timekeeping */
+#else
+#define DEB(x)
+#define DDB(x)
+#define TICK(x)
+#define TOCK(x)
+#endif /* TEST */
+
+/*
+ * You should not need to change anything beyond this point.
+ * The first part of the file implements linear algebra in GF.
+ *
+ * gf is the type used to store an element of the Galois Field.
+ * Must constain at least GF_BITS bits.
+ *
+ * Note: unsigned char will work up to GF(256) but int seems to run
+ * faster on the Pentium. We use int whenever have to deal with an
+ * index, since they are generally faster.
+ */
+#if (GF_BITS < 2 && GF_BITS >16)
+#error "GF_BITS must be 2 .. 16"
+#endif
+
+
+#define GF_SIZE ((1 << GF_BITS) - 1) /* powers of \alpha */
+
+/*
+ * Primitive polynomials - see Lin & Costello, Appendix A,
+ * and Lee & Messerschmitt, p. 453.
+ */
+static const char *allPp[] = { /* GF_BITS polynomial */
+ NULL, /* 0 no code */
+ NULL, /* 1 no code */
+ "111", /* 2 1+x+x^2 */
+ "1101", /* 3 1+x+x^3 */
+ "11001", /* 4 1+x+x^4 */
+ "101001", /* 5 1+x^2+x^5 */
+ "1100001", /* 6 1+x+x^6 */
+ "10010001", /* 7 1 + x^3 + x^7 */
+ "101110001", /* 8 1+x^2+x^3+x^4+x^8 */
+ "1000100001", /* 9 1+x^4+x^9 */
+ "10010000001", /* 10 1+x^3+x^10 */
+ "101000000001", /* 11 1+x^2+x^11 */
+ "1100101000001", /* 12 1+x+x^4+x^6+x^12 */
+ "11011000000001", /* 13 1+x+x^3+x^4+x^13 */
+ "110000100010001", /* 14 1+x+x^6+x^10+x^14 */
+ "1100000000000001", /* 15 1+x+x^15 */
+ "11010000000010001" /* 16 1+x+x^3+x^12+x^16 */
+};
+
+
+/*
+ * To speed up computations, we have tables for logarithm, exponent
+ * and inverse of a number. If GF_BITS <= 8, we use a table for
+ * multiplication as well (it takes 64K, no big deal even on a PDA,
+ * especially because it can be pre-initialized an put into a ROM!),
+ * otherwhise we use a table of logarithms.
+ * In any case the macro gf_mul(x,y) takes care of multiplications.
+ */
+
+static gf gf_exp[2*GF_SIZE]; /* index->poly form conversion table */
+static int gf_log[GF_SIZE + 1]; /* Poly->index form conversion table */
+static gf inverse[GF_SIZE+1]; /* inverse of field elem. */
+ /* inv[\alpha**i]=\alpha**(GF_SIZE-i-1) */
+
+/*
+ * modnn(x) computes x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1,
+ * without a slow divide.
+ */
+static inline gf
+modnn(int x)
+{
+ while (x >= GF_SIZE) {
+ x -= GF_SIZE;
+ x = (x >> GF_BITS) + (x & GF_SIZE);
+ }
+ return x;
+}
+
+#define SWAP(a,b,t) {t tmp; tmp=a; a=b; b=tmp;}
+
+/*
+ * gf_mul(x,y) multiplies two numbers. If GF_BITS<=8, it is much
+ * faster to use a multiplication table.
+ *
+ * USE_GF_MULC, GF_MULC0(c) and GF_ADDMULC(x) can be used when multiplying
+ * many numbers by the same constant. In this case the first
+ * call sets the constant, and others perform the multiplications.
+ * A value related to the multiplication is held in a local variable
+ * declared with USE_GF_MULC . See usage in addmul1().
+ */
+#if (GF_BITS <= 8)
+static gf gf_mul_table[GF_SIZE + 1][GF_SIZE + 1];
+
+#define gf_mul(x,y) gf_mul_table[x][y]
+
+#define USE_GF_MULC gf * __gf_mulc_
+#define GF_MULC0(c) __gf_mulc_ = gf_mul_table[c]
+#define GF_ADDMULC(dst, x) dst ^= __gf_mulc_[x]
+
+static void
+init_mul_table()
+{
+ int i, j;
+ for (i=0; i< GF_SIZE+1; i++)
+ for (j=0; j< GF_SIZE+1; j++)
+ gf_mul_table[i][j] = gf_exp[modnn(gf_log[i] + gf_log[j]) ] ;
+
+ for (j=0; j< GF_SIZE+1; j++)
+ gf_mul_table[0][j] = gf_mul_table[j][0] = 0;
+}
+#else /* GF_BITS > 8 */
+static inline gf
+gf_mul(x,y)
+{
+ if ( (x) == 0 || (y)==0 ) return 0;
+
+ return gf_exp[gf_log[x] + gf_log[y] ] ;
+}
+#define init_mul_table()
+
+#define USE_GF_MULC register gf * __gf_mulc_
+#define GF_MULC0(c) __gf_mulc_ = &gf_exp[ gf_log[c] ]
+#define GF_ADDMULC(dst, x) { if (x) dst ^= __gf_mulc_[ gf_log[x] ] ; }
+#endif
+
+/*
+ * Generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]
+ * Lookup tables:
+ * index->polynomial form gf_exp[] contains j= \alpha^i;
+ * polynomial form -> index form gf_log[ j = \alpha^i ] = i
+ * \alpha=x is the primitive element of GF(2^m)
+ *
+ * For efficiency, gf_exp[] has size 2*GF_SIZE, so that a simple
+ * multiplication of two numbers can be resolved without calling modnn
+ */
+
+/*
+ * i use malloc so many times, it is easier to put checks all in
+ * one place.
+ */
+static void *
+my_malloc(int sz, const char *err_string)
+{
+ void *p = malloc( sz );
+ if (p == NULL) {
+ fprintf(stderr, "-- malloc failure allocating %s\n", err_string);
+ exit(1) ;
+ }
+ return p ;
+}
+
+#define NEW_GF_MATRIX(rows, cols) \
+ (gf *)my_malloc(rows * cols * sizeof(gf), " ## __LINE__ ## " )
+
+/*
+ * initialize the data structures used for computations in GF.
+ */
+static void
+generate_gf(void)
+{
+ int i;
+ gf mask;
+ const char *Pp = allPp[GF_BITS] ;
+
+ mask = 1; /* x ** 0 = 1 */
+ gf_exp[GF_BITS] = 0; /* will be updated at the end of the 1st loop */
+ /*
+ * first, generate the (polynomial representation of) powers of \alpha,
+ * which are stored in gf_exp[i] = \alpha ** i .
+ * At the same time build gf_log[gf_exp[i]] = i .
+ * The first GF_BITS powers are simply bits shifted to the left.
+ */
+ for (i = 0; i < GF_BITS; i++, mask <<= 1 ) {
+ gf_exp[i] = mask;
+ gf_log[gf_exp[i]] = i;
+ /*
+ * If Pp[i] == 1 then \alpha ** i occurs in poly-repr
+ * gf_exp[GF_BITS] = \alpha ** GF_BITS
+ */
+ if ( Pp[i] == '1' )
+ gf_exp[GF_BITS] ^= mask;
+ }
+ /*
+ * now gf_exp[GF_BITS] = \alpha ** GF_BITS is complete, so can als
+ * compute its inverse.
+ */
+ gf_log[gf_exp[GF_BITS]] = GF_BITS;
+ /*
+ * Poly-repr of \alpha ** (i+1) is given by poly-repr of
+ * \alpha ** i shifted left one-bit and accounting for any
+ * \alpha ** GF_BITS term that may occur when poly-repr of
+ * \alpha ** i is shifted.
+ */
+ mask = 1 << (GF_BITS - 1 ) ;
+ for (i = GF_BITS + 1; i < GF_SIZE; i++) {
+ if (gf_exp[i - 1] >= mask)
+ gf_exp[i] = gf_exp[GF_BITS] ^ ((gf_exp[i - 1] ^ mask) << 1);
+ else
+ gf_exp[i] = gf_exp[i - 1] << 1;
+ gf_log[gf_exp[i]] = i;
+ }
+ /*
+ * log(0) is not defined, so use a special value
+ */
+ gf_log[0] = GF_SIZE ;
+ /* set the extended gf_exp values for fast multiply */
+ for (i = 0 ; i < GF_SIZE ; i++)
+ gf_exp[i + GF_SIZE] = gf_exp[i] ;
+
+ /*
+ * again special cases. 0 has no inverse. This used to
+ * be initialized to GF_SIZE, but it should make no difference
+ * since noone is supposed to read from here.
+ */
+ inverse[0] = 0 ;
+ inverse[1] = 1;
+ for (i=2; i<=GF_SIZE; i++)
+ inverse[i] = gf_exp[GF_SIZE-gf_log[i]];
+}
+
+/*
+ * Various linear algebra operations that i use often.
+ */
+
+/*
+ * addmul() computes dst[] = dst[] + c * src[]
+ * This is used often, so better optimize it! Currently the loop is
+ * unrolled 16 times, a good value for 486 and pentium-class machines.
+ * The case c=0 is also optimized, whereas c=1 is not. These
+ * calls are unfrequent in my typical apps so I did not bother.
+ *
+ * Note that gcc on
+ */
+#define addmul(dst, src, c, sz) \
+ if (c != 0) addmul1(dst, src, c, sz)
+
+#define UNROLL 16 /* 1, 4, 8, 16 */
+static void
+addmul1(gf *dst1, gf *src1, gf c, int sz)
+{
+ USE_GF_MULC ;
+ gf *dst = dst1, *src = src1 ;
+ gf *lim = &dst[sz - UNROLL + 1] ;
+
+ GF_MULC0(c) ;
+
+#if (UNROLL > 1) /* unrolling by 8/16 is quite effective on the pentium */
+ for (; dst < lim ; dst += UNROLL, src += UNROLL ) {
+ GF_ADDMULC( dst[0] , src[0] );
+ GF_ADDMULC( dst[1] , src[1] );
+ GF_ADDMULC( dst[2] , src[2] );
+ GF_ADDMULC( dst[3] , src[3] );
+#if (UNROLL > 4)
+ GF_ADDMULC( dst[4] , src[4] );
+ GF_ADDMULC( dst[5] , src[5] );
+ GF_ADDMULC( dst[6] , src[6] );
+ GF_ADDMULC( dst[7] , src[7] );
+#endif
+#if (UNROLL > 8)
+ GF_ADDMULC( dst[8] , src[8] );
+ GF_ADDMULC( dst[9] , src[9] );
+ GF_ADDMULC( dst[10] , src[10] );
+ GF_ADDMULC( dst[11] , src[11] );
+ GF_ADDMULC( dst[12] , src[12] );
+ GF_ADDMULC( dst[13] , src[13] );
+ GF_ADDMULC( dst[14] , src[14] );
+ GF_ADDMULC( dst[15] , src[15] );
+#endif
+ }
+#endif
+ lim += UNROLL - 1 ;
+ for (; dst < lim; dst++, src++ ) /* final components */
+ GF_ADDMULC( *dst , *src );
+}
+
+/*
+ * computes C = AB where A is n*k, B is k*m, C is n*m
+ */
+static void
+matmul(gf *a, gf *b, gf *c, int n, int k, int m)
+{
+ int row, col, i ;
+
+ for (row = 0; row < n ; row++) {
+ for (col = 0; col < m ; col++) {
+ gf *pa = &a[ row * k ];
+ gf *pb = &b[ col ];
+ gf acc = 0 ;
+ for (i = 0; i < k ; i++, pa++, pb += m )
+ acc ^= gf_mul( *pa, *pb ) ;
+ c[ row * m + col ] = acc ;
+ }
+ }
+}
+
+#ifdef DEBUGG
+/*
+ * returns 1 if the square matrix is identiy
+ * (only for test)
+ */
+static int
+is_identity(gf *m, int k)
+{
+ int row, col ;
+ for (row=0; row<k; row++)
+ for (col=0; col<k; col++)
+ if ( (row==col && *m != 1) ||
+ (row!=col && *m != 0) )
+ return 0 ;
+ else
+ m++ ;
+ return 1 ;
+}
+#endif /* debug */
+
+/*
+ * invert_mat() takes a matrix and produces its inverse
+ * k is the size of the matrix.
+ * (Gauss-Jordan, adapted from Numerical Recipes in C)
+ * Return non-zero if singular.
+ */
+DEB( int pivloops=0; int pivswaps=0 ; /* diagnostic */)
+static int
+invert_mat(gf *src, int k)
+{
+ gf c, *p ;
+ int irow, icol, row, col, i, ix ;
+
+ int error = 1 ;
+ int *indxc = (int*)my_malloc(k*sizeof(int), "indxc");
+ int *indxr = (int*)my_malloc(k*sizeof(int), "indxr");
+ int *ipiv = (int*)my_malloc(k*sizeof(int), "ipiv");
+ gf *id_row = NEW_GF_MATRIX(1, k);
+ gf *temp_row = NEW_GF_MATRIX(1, k);
+
+ bzero(id_row, k*sizeof(gf));
+ DEB( pivloops=0; pivswaps=0 ; /* diagnostic */ )
+ /*
+ * ipiv marks elements already used as pivots.
+ */
+ for (i = 0; i < k ; i++)
+ ipiv[i] = 0 ;
+
+ for (col = 0; col < k ; col++) {
+ gf *pivot_row ;
+ /*
+ * Zeroing column 'col', look for a non-zero element.
+ * First try on the diagonal, if it fails, look elsewhere.
+ */
+ irow = icol = -1 ;
+ if (ipiv[col] != 1 && src[col*k + col] != 0) {
+ irow = col ;
+ icol = col ;
+ goto found_piv ;
+ }
+ for (row = 0 ; row < k ; row++) {
+ if (ipiv[row] != 1) {
+ for (ix = 0 ; ix < k ; ix++) {
+ DEB( pivloops++ ; )
+ if (ipiv[ix] == 0) {
+ if (src[row*k + ix] != 0) {
+ irow = row ;
+ icol = ix ;
+ goto found_piv ;
+ }
+ } else if (ipiv[ix] > 1) {
+ fprintf(stderr, "singular matrix\n");
+ goto fail ;
+ }
+ }
+ }
+ }
+ if (icol == -1) {
+ fprintf(stderr, "XXX pivot not found!\n");
+ goto fail ;
+ }
+found_piv:
+ ++(ipiv[icol]) ;
+ /*
+ * swap rows irow and icol, so afterwards the diagonal
+ * element will be correct. Rarely done, not worth
+ * optimizing.
+ */
+ if (irow != icol) {
+ for (ix = 0 ; ix < k ; ix++ ) {
+ SWAP( src[irow*k + ix], src[icol*k + ix], gf) ;
+ }
+ }
+ indxr[col] = irow ;
+ indxc[col] = icol ;
+ pivot_row = &src[icol*k] ;
+ c = pivot_row[icol] ;
+ if (c == 0) {
+ fprintf(stderr, "singular matrix 2\n");
+ goto fail ;
+ }
+ if (c != 1 ) { /* otherwhise this is a NOP */
+ /*
+ * this is done often , but optimizing is not so
+ * fruitful, at least in the obvious ways (unrolling)
+ */
+ DEB( pivswaps++ ; )
+ c = inverse[ c ] ;
+ pivot_row[icol] = 1 ;
+ for (ix = 0 ; ix < k ; ix++ )
+ pivot_row[ix] = gf_mul(c, pivot_row[ix] );
+ }
+ /*
+ * from all rows, remove multiples of the selected row
+ * to zero the relevant entry (in fact, the entry is not zero
+ * because we know it must be zero).
+ * (Here, if we know that the pivot_row is the identity,
+ * we can optimize the addmul).
+ */
+ id_row[icol] = 1;
+ if (bcmp(pivot_row, id_row, k*sizeof(gf)) != 0) {
+ for (p = src, ix = 0 ; ix < k ; ix++, p += k ) {
+ if (ix != icol) {
+ c = p[icol] ;
+ p[icol] = 0 ;
+ addmul(p, pivot_row, c, k );
+ }
+ }
+ }
+ id_row[icol] = 0;
+ } /* done all columns */
+ for (col = k-1 ; col >= 0 ; col-- ) {
+ if (indxr[col] <0 || indxr[col] >= k)
+ fprintf(stderr, "AARGH, indxr[col] %d\n", indxr[col]);
+ else if (indxc[col] <0 || indxc[col] >= k)
+ fprintf(stderr, "AARGH, indxc[col] %d\n", indxc[col]);
+ else
+ if (indxr[col] != indxc[col] ) {
+ for (row = 0 ; row < k ; row++ ) {
+ SWAP( src[row*k + indxr[col]], src[row*k + indxc[col]], gf) ;
+ }
+ }
+ }
+ error = 0 ;
+fail:
+ free(indxc);
+ free(indxr);
+ free(ipiv);
+ free(id_row);
+ free(temp_row);
+ return error ;
+}
+
+/*
+ * fast code for inverting a vandermonde matrix.
+ * XXX NOTE: It assumes that the matrix
+ * is not singular and _IS_ a vandermonde matrix. Only uses
+ * the second column of the matrix, containing the p_i's.
+ *
+ * Algorithm borrowed from "Numerical recipes in C" -- sec.2.8, but
+ * largely revised for my purposes.
+ * p = coefficients of the matrix (p_i)
+ * q = values of the polynomial (known)
+ */
+
+int
+invert_vdm(gf *src, int k)
+{
+ int i, j, row, col ;
+ gf *b, *c, *p;
+ gf t, xx ;
+
+ if (k == 1) /* degenerate case, matrix must be p^0 = 1 */
+ return 0 ;
+ /*
+ * c holds the coefficient of P(x) = Prod (x - p_i), i=0..k-1
+ * b holds the coefficient for the matrix inversion
+ */
+ c = NEW_GF_MATRIX(1, k);
+ b = NEW_GF_MATRIX(1, k);
+
+ p = NEW_GF_MATRIX(1, k);
+
+ for ( j=1, i = 0 ; i < k ; i++, j+=k ) {
+ c[i] = 0 ;
+ p[i] = src[j] ; /* p[i] */
+ }
+ /*
+ * construct coeffs. recursively. We know c[k] = 1 (implicit)
+ * and start P_0 = x - p_0, then at each stage multiply by
+ * x - p_i generating P_i = x P_{i-1} - p_i P_{i-1}
+ * After k steps we are done.
+ */
+ c[k-1] = p[0] ; /* really -p(0), but x = -x in GF(2^m) */
+ for (i = 1 ; i < k ; i++ ) {
+ gf p_i = p[i] ; /* see above comment */
+ for (j = k-1 - ( i - 1 ) ; j < k-1 ; j++ )
+ c[j] ^= gf_mul( p_i, c[j+1] ) ;
+ c[k-1] ^= p_i ;
+ }
+
+ for (row = 0 ; row < k ; row++ ) {
+ /*
+ * synthetic division etc.
+ */
+ xx = p[row] ;
+ t = 1 ;
+ b[k-1] = 1 ; /* this is in fact c[k] */
+ for (i = k-2 ; i >= 0 ; i-- ) {
+ b[i] = c[i+1] ^ gf_mul(xx, b[i+1]) ;
+ t = gf_mul(xx, t) ^ b[i] ;
+ }
+ for (col = 0 ; col < k ; col++ )
+ src[col*k + row] = gf_mul(inverse[t], b[col] );
+ }
+ free(c) ;
+ free(b) ;
+ free(p) ;
+ return 0 ;
+}
+
+static int fec_initialized = 0 ;
+static void
+init_fec()
+{
+ TICK(ticks[0]);
+ generate_gf();
+ TOCK(ticks[0]);
+ DDB(fprintf(stderr, "generate_gf took %ldus\n", ticks[0]);)
+ TICK(ticks[0]);
+ init_mul_table();
+ TOCK(ticks[0]);
+ DDB(fprintf(stderr, "init_mul_table took %ldus\n", ticks[0]);)
+ fec_initialized = 1 ;
+}
+
+/*
+ * This section contains the proper FEC encoding/decoding routines.
+ * The encoding matrix is computed starting with a Vandermonde matrix,
+ * and then transforming it into a systematic matrix.
+ */
+
+#define FEC_MAGIC 0xFECC0DEC
+
+void
+fec_free(struct fec_parms *p)
+{
+ if (p==NULL ||
+ p->magic != ( ( (FEC_MAGIC ^ p->k) ^ p->n) ^ (unsigned long)(p->enc_matrix)) ) {
+ fprintf(stderr, "bad parameters to fec_free\n");
+ return ;
+ }
+ free(p->enc_matrix);
+ free(p);
+}
+
+/*
+ * create a new encoder, returning a descriptor. This contains k,n and
+ * the encoding matrix.
+ */
+struct fec_parms *
+fec_new(int k, int n)
+{
+ int row, col ;
+ gf *p, *tmp_m ;
+
+ struct fec_parms *retval ;
+
+ if (fec_initialized == 0)
+ init_fec();
+
+ if (k > GF_SIZE + 1 || n > GF_SIZE + 1 || k > n ) {
+ fprintf(stderr, "Invalid parameters k %d n %d GF_SIZE %d\n",
+ k, n, GF_SIZE );
+ return NULL ;
+ }
+ retval = (struct fec_parms *)my_malloc(sizeof(struct fec_parms), "new_code");
+ retval->k = k ;
+ retval->n = n ;
+ retval->enc_matrix = NEW_GF_MATRIX(n, k);
+ retval->magic = ( ( FEC_MAGIC ^ k) ^ n) ^ (unsigned long)(retval->enc_matrix) ;
+ tmp_m = NEW_GF_MATRIX(n, k);
+ /*
+ * fill the matrix with powers of field elements, starting from 0.
+ * The first row is special, cannot be computed with exp. table.
+ */
+ tmp_m[0] = 1 ;
+ for (col = 1; col < k ; col++)
+ tmp_m[col] = 0 ;
+ for (p = tmp_m + k, row = 0; row < n-1 ; row++, p += k) {
+ for ( col = 0 ; col < k ; col ++ )
+ p[col] = gf_exp[modnn(row*col)];
+ }
+
+ /*
+ * quick code to build systematic matrix: invert the top
+ * k*k vandermonde matrix, multiply right the bottom n-k rows
+ * by the inverse, and construct the identity matrix at the top.
+ */
+ TICK(ticks[3]);
+ invert_vdm(tmp_m, k); /* much faster than invert_mat */
+ matmul(tmp_m + k*k, tmp_m, retval->enc_matrix + k*k, n - k, k, k);
+ /*
+ * the upper matrix is I so do not bother with a slow multiply
+ */
+ bzero(retval->enc_matrix, k*k*sizeof(gf) );
+ for (p = retval->enc_matrix, col = 0 ; col < k ; col++, p += k+1 )
+ *p = 1 ;
+ free(tmp_m);
+ TOCK(ticks[3]);
+
+ DDB(fprintf(stderr, "--- %ld us to build encoding matrix\n",
+ ticks[3]);)
+ DEB(pr_matrix(retval->enc_matrix, n, k, "encoding_matrix");)
+ return retval ;
+}
+
+/*
+ * fec_encode accepts as input pointers to n data packets of size sz,
+ * and produces as output a packet pointed to by fec, computed
+ * with index "index".
+ */
+void
+fec_encode(struct fec_parms *code, gf *src[], gf *fec, int index, int sz)
+{
+ int i, k = code->k ;
+ gf *p ;
+
+ if (GF_BITS > 8)
+ sz /= 2 ;
+
+ if (index < k)
+ bcopy(src[index], fec, sz*sizeof(gf) ) ;
+ else if (index < code->n) {
+ p = &(code->enc_matrix[index*k] );
+ bzero(fec, sz*sizeof(gf));
+ for (i = 0; i < k ; i++)
+ addmul(fec, src[i], p[i], sz ) ;
+ } else
+ fprintf(stderr, "Invalid index %d (max %d)\n",
+ index, code->n - 1 );
+}
+
+/*
+ * shuffle move src packets in their position
+ */
+static int
+shuffle(gf *pkt[], int index[], int k)
+{
+ int i;
+
+ for ( i = 0 ; i < k ; ) {
+ if (index[i] >= k || index[i] == i)
+ i++ ;
+ else {
+ /*
+ * put pkt in the right position (first check for conflicts).
+ */
+ int c = index[i] ;
+
+ if (index[c] == c) {
+ DEB(fprintf(stderr, "\nshuffle, error at %d\n", i);)
+ return 1 ;
+ }
+ SWAP(index[i], index[c], int) ;
+ SWAP(pkt[i], pkt[c], gf *) ;
+ }
+ }
+ DEB( /* just test that it works... */
+ for ( i = 0 ; i < k ; i++ ) {
+ if (index[i] < k && index[i] != i) {
+ fprintf(stderr, "shuffle: after\n");
+ for (i=0; i<k ; i++) fprintf(stderr, "%3d ", index[i]);
+ fprintf(stderr, "\n");
+ return 1 ;
+ }
+ }
+ )
+ return 0 ;
+}
+
+/*
+ * build_decode_matrix constructs the encoding matrix given the
+ * indexes. The matrix must be already allocated as
+ * a vector of k*k elements, in row-major order
+ */
+static gf *
+build_decode_matrix(struct fec_parms *code, gf *pkt[], int index[])
+{
+ int i , k = code->k ;
+ gf *p, *matrix = NEW_GF_MATRIX(k, k);
+
+ TICK(ticks[9]);
+ for (i = 0, p = matrix ; i < k ; i++, p += k ) {
+#if 1 /* this is simply an optimization, not very useful indeed */
+ if (index[i] < k) {
+ bzero(p, k*sizeof(gf) );
+ p[i] = 1 ;
+ } else
+#endif
+ if (index[i] < code->n )
+ bcopy( &(code->enc_matrix[index[i]*k]), p, k*sizeof(gf) );
+ else {
+ fprintf(stderr, "decode: invalid index %d (max %d)\n",
+ index[i], code->n - 1 );
+ free(matrix) ;
+ return NULL ;
+ }
+ }
+ TICK(ticks[9]);
+ if (invert_mat(matrix, k)) {
+ free(matrix);
+ matrix = NULL ;
+ }
+ TOCK(ticks[9]);
+ return matrix ;
+}
+
+/*
+ * fec_decode receives as input a vector of packets, the indexes of
+ * packets, and produces the correct vector as output.
+ *
+ * Input:
+ * code: pointer to code descriptor
+ * pkt: pointers to received packets. They are modified
+ * to store the output packets (in place)
+ * index: pointer to packet indexes (modified)
+ * sz: size of each packet
+ */
+int
+fec_decode(struct fec_parms *code, gf *pkt[], int index[], int sz)
+{
+ gf *m_dec ;
+ gf **new_pkt ;
+ int row, col , k = code->k ;
+
+ if (GF_BITS > 8)
+ sz /= 2 ;
+
+ if (shuffle(pkt, index, k)) /* error if true */
+ return 1 ;
+ m_dec = build_decode_matrix(code, pkt, index);
+
+ if (m_dec == NULL)
+ return 1 ; /* error */
+ /*
+ * do the actual decoding
+ */
+ new_pkt = (gf**)my_malloc (k * sizeof (gf * ), "new pkt pointers" );
+ for (row = 0 ; row < k ; row++ ) {
+ if (index[row] >= k) {
+ new_pkt[row] = (gf*) my_malloc (sz * sizeof (gf), "new pkt buffer" );
+ bzero(new_pkt[row], sz * sizeof(gf) ) ;
+ for (col = 0 ; col < k ; col++ )
+ addmul(new_pkt[row], pkt[col], m_dec[row*k + col], sz) ;
+ }
+ }
+ /*
+ * move pkts to their final destination
+ */
+ for (row = 0 ; row < k ; row++ ) {
+ if (index[row] >= k) {
+ bcopy(new_pkt[row], pkt[row], sz*sizeof(gf));
+ free(new_pkt[row]);
+ }
+ }
+ free(new_pkt);
+ free(m_dec);
+
+ return 0;
+}
diff --git a/libtransport/src/core/fec.h b/libtransport/src/core/fec.h
new file mode 100644
index 000000000..8234057a7
--- /dev/null
+++ b/libtransport/src/core/fec.h
@@ -0,0 +1,65 @@
+/*
+ * fec.c -- forward error correction based on Vandermonde matrices
+ * 980614
+ * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it)
+ *
+ * Portions derived from code by Phil Karn (karn@ka9q.ampr.org),
+ * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari
+ * Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+/*
+ * The following parameter defines how many bits are used for
+ * field elements. The code supports any value from 2 to 16
+ * but fastest operation is achieved with 8 bit elements
+ * This is the only parameter you may want to change.
+ */
+#ifndef GF_BITS
+#define GF_BITS 8 /* code over GF(2**GF_BITS) - change to suit */
+#endif
+
+#if (GF_BITS <= 8)
+typedef unsigned char gf;
+#else
+typedef unsigned short gf;
+#endif
+
+#define GF_SIZE ((1 << GF_BITS) - 1) /* powers of \alpha */
+
+struct fec_parms {
+ unsigned long magic ;
+ int k, n ; /* parameters of the code */
+ gf *enc_matrix ;
+};
+
+void fec_free(struct fec_parms *p) ;
+struct fec_parms *fec_new(int k, int n) ;
+
+void fec_encode(struct fec_parms *code, gf *src[], gf *fec, int index, int sz);
+int fec_decode(struct fec_parms *code, gf *pkt[], int index[], int sz);
+
+/* end of file */
diff --git a/libtransport/src/core/forwarder_interface.h b/libtransport/src/core/forwarder_interface.h
index 3b016c4bb..a94414d38 100644
--- a/libtransport/src/core/forwarder_interface.h
+++ b/libtransport/src/core/forwarder_interface.h
@@ -49,7 +49,10 @@ class ForwarderInterface {
inet6_address_({}),
mtu_(1500),
output_interface_(""),
- content_store_reserved_(standard_cs_reserved) {}
+ content_store_reserved_(standard_cs_reserved) {
+ inet_address_.v4.as_u32 = htonl(0x7f00001);
+ inet6_address_.v6.as_u8[15] = 0x01;
+ }
public:
virtual ~ForwarderInterface() {}
@@ -95,7 +98,10 @@ class ForwarderInterface {
packet.setLocator(inet6_address_);
}
+#ifndef __vpp__
+ /* In the case of VPP we try to offload checksum computation to hardware */
packet.setChecksum();
+#endif
connector_.send(packet.acquireMemBufReference());
}
diff --git a/libtransport/src/core/global_configuration.cc b/libtransport/src/core/global_configuration.cc
new file mode 100644
index 000000000..3e37a30a4
--- /dev/null
+++ b/libtransport/src/core/global_configuration.cc
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <core/global_configuration.h>
+#include <hicn/transport/core/connector.h>
+#include <hicn/transport/utils/log.h>
+
+#include <libconfig.h++>
+#include <map>
+
+namespace transport {
+namespace core {
+
+GlobalConfiguration::GlobalConfiguration() {}
+
+bool GlobalConfiguration::parseTransportConfig(const std::string& path) {
+ using namespace libconfig;
+ Config cfg;
+
+ try {
+ cfg.readFile(path.c_str());
+ } catch (const FileIOException& fioex) {
+ TRANSPORT_LOGE("I/O error while reading file: %s", fioex.what());
+ return false;
+ } catch (const ParseException& pex) {
+ TRANSPORT_LOGE("Parse error at %s:%d - %s", pex.getFile(), pex.getLine(),
+ pex.getError());
+ return false;
+ }
+
+ Setting& root = cfg.getRoot();
+
+ /**
+ * Iterate over sections. Best thing to do here would be to have other
+ * components of the program registering a callback here, to parse their
+ * section of the configuration file.
+ */
+ for (auto section = root.begin(); section != root.end(); section++) {
+ std::string name = section->getName();
+ std::error_code ec;
+ TRANSPORT_LOGD("Parsing Section: %s", name.c_str());
+
+ auto it = configuration_parsers_.find(name);
+ if (it != configuration_parsers_.end() && !it->second.first) {
+ TRANSPORT_LOGD("Found valid configuration parser");
+ it->second.second(*section, ec);
+ it->second.first = true;
+ }
+ }
+
+ return true;
+}
+
+void GlobalConfiguration::parseConfiguration(const std::string& path) {
+ // Check if an environment variable with the configuration path exists. COnf
+ // variable comes first.
+ std::unique_lock<std::mutex> lck(cp_mtx_);
+
+ if (const char* env_c = std::getenv(GlobalConfiguration::conf_file)) {
+ parseTransportConfig(env_c);
+ } else if (!path.empty()) {
+ conf_file_path_ = path;
+ parseTransportConfig(conf_file_path_);
+ } else {
+ TRANSPORT_LOGD(
+ "Called parseConfiguration but no configuration file was provided.");
+ }
+}
+
+void GlobalConfiguration::registerConfigurationSetter(
+ const std::string& key, const SetCallback& set_callback) {
+ std::unique_lock<std::mutex> lck(cp_mtx_);
+ if (configuration_setters_.find(key) != configuration_setters_.end()) {
+ TRANSPORT_LOGW(
+ "Trying to register configuration setter %s twice. Ignoring second "
+ "registration attempt.",
+ key.c_str());
+ } else {
+ configuration_setters_.emplace(key, set_callback);
+ }
+}
+
+void GlobalConfiguration::registerConfigurationGetter(
+ const std::string& key, const GetCallback& get_callback) {
+ std::unique_lock<std::mutex> lck(cp_mtx_);
+ if (configuration_getters_.find(key) != configuration_getters_.end()) {
+ TRANSPORT_LOGW(
+ "Trying to register configuration getter %s twice. Ignoring second "
+ "registration attempt.",
+ key.c_str());
+ } else {
+ configuration_getters_.emplace(key, get_callback);
+ }
+}
+
+void GlobalConfiguration::registerConfigurationParser(
+ const std::string& key, const ParserCallback& parser) {
+ std::unique_lock<std::mutex> lck(cp_mtx_);
+ if (configuration_parsers_.find(key) != configuration_parsers_.end()) {
+ TRANSPORT_LOGW(
+ "Trying to register configuration key %s twice. Ignoring second "
+ "registration attempt.",
+ key.c_str());
+ } else {
+ configuration_parsers_.emplace(key, std::make_pair(false, parser));
+
+ // Trigger a parsing of the configuration.
+ if (!conf_file_path_.empty()) {
+ parseTransportConfig(conf_file_path_);
+ }
+ }
+}
+
+void GlobalConfiguration::unregisterConfigurationParser(
+ const std::string& key) {
+ std::unique_lock<std::mutex> lck(cp_mtx_);
+ auto it = configuration_parsers_.find(key);
+ if (it != configuration_parsers_.end()) {
+ configuration_parsers_.erase(it);
+ }
+}
+
+void GlobalConfiguration::unregisterConfigurationSetter(
+ const std::string& key) {
+ std::unique_lock<std::mutex> lck(cp_mtx_);
+ auto it = configuration_setters_.find(key);
+ if (it != configuration_setters_.end()) {
+ configuration_setters_.erase(it);
+ }
+}
+
+void GlobalConfiguration::unregisterConfigurationGetter(
+ const std::string& key) {
+ std::unique_lock<std::mutex> lck(cp_mtx_);
+ auto it = configuration_getters_.find(key);
+ if (it != configuration_getters_.end()) {
+ configuration_getters_.erase(it);
+ }
+}
+
+void GlobalConfiguration::getConfiguration(
+ interface::global_config::ConfigurationObject& configuration_object,
+ std::error_code& ec) {
+ auto it = configuration_getters_.find(configuration_object.getKey());
+
+ if (it != configuration_getters_.end()) {
+ it->second(configuration_object, ec);
+ }
+}
+
+void GlobalConfiguration::setConfiguration(
+ const interface::global_config::ConfigurationObject& configuration_object,
+ std::error_code& ec) {
+ auto it = configuration_setters_.find(configuration_object.getKey());
+
+ if (it != configuration_setters_.end()) {
+ it->second(configuration_object, ec);
+ }
+}
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/core/global_configuration.h b/libtransport/src/core/global_configuration.h
new file mode 100644
index 000000000..dcc8d94e3
--- /dev/null
+++ b/libtransport/src/core/global_configuration.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/interfaces/global_conf_interface.h>
+#include <hicn/transport/utils/singleton.h>
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <system_error>
+
+namespace libconfig {
+class Setting;
+}
+
+namespace transport {
+namespace core {
+
+/**
+ * Class holding workflow for global configuration.
+ * This class does not contains the actual configuration, which is rather stored
+ * inside the modules to be configured. This class contains the handlers to call
+ * for getting/setting the configurations and to parse the corresponding
+ * sections of the configuration file. Each class register 3 callbacks: one to
+ * parse conf section and 2 to set/get the configuration through programming
+ * interface.
+ */
+class GlobalConfiguration : public utils::Singleton<GlobalConfiguration> {
+ static const constexpr char *conf_file = "TRANSPORT_CONFIG";
+ friend class utils::Singleton<GlobalConfiguration>;
+
+ public:
+ /**
+ * This callback will be called by GlobalConfiguration in
+ *
+ */
+ using ParserCallback = std::function<void(const libconfig::Setting &config,
+ std::error_code &ec)>;
+ using GetCallback =
+ std::function<void(interface::global_config::ConfigurationObject &object,
+ std::error_code &ec)>;
+
+ using SetCallback = std::function<void(
+ const interface::global_config::ConfigurationObject &object,
+ std::error_code &ec)>;
+
+ ~GlobalConfiguration() = default;
+
+ public:
+ void parseConfiguration(const std::string &path);
+
+ void registerConfigurationParser(const std::string &key,
+ const ParserCallback &parser);
+
+ void registerConfigurationSetter(const std::string &key,
+ const SetCallback &set_callback);
+ void registerConfigurationGetter(const std::string &key,
+ const GetCallback &get_callback);
+
+ void unregisterConfigurationParser(const std::string &key);
+
+ void unregisterConfigurationSetter(const std::string &key);
+
+ void unregisterConfigurationGetter(const std::string &key);
+
+ void getConfiguration(
+ interface::global_config::ConfigurationObject &configuration_object,
+ std::error_code &ec);
+ void setConfiguration(
+ const interface::global_config::ConfigurationObject &configuration_object,
+ std::error_code &ec);
+
+ private:
+ GlobalConfiguration();
+ std::string conf_file_path_;
+ bool parseTransportConfig(const std::string &path);
+
+ private:
+ std::mutex cp_mtx_;
+ using ParserPair = std::pair<bool, ParserCallback>;
+ std::map<std::string, ParserPair> configuration_parsers_;
+ std::map<std::string, GetCallback> configuration_getters_;
+ std::map<std::string, SetCallback> configuration_setters_;
+};
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/core/hicn_forwarder_interface.cc b/libtransport/src/core/hicn_forwarder_interface.cc
index 810daba3a..5a0faa360 100644
--- a/libtransport/src/core/hicn_forwarder_interface.cc
+++ b/libtransport/src/core/hicn_forwarder_interface.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/core/hicn_forwarder_interface.h b/libtransport/src/core/hicn_forwarder_interface.h
index 6969f4a6b..c4138c6c2 100644
--- a/libtransport/src/core/hicn_forwarder_interface.h
+++ b/libtransport/src/core/hicn_forwarder_interface.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
diff --git a/libtransport/src/core/hicn_vapi.c b/libtransport/src/core/hicn_vapi.c
index d19e36346..be556f3aa 100644
--- a/libtransport/src/core/hicn_vapi.c
+++ b/libtransport/src/core/hicn_vapi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -18,7 +18,6 @@
#ifdef __vpp__
#include <hicn/transport/utils/log.h>
-
#include <core/hicn_vapi.h>
#define HICN_VPP_PLUGIN
@@ -31,10 +30,10 @@
#include <vlibmemory/api.h>
#include <vppinfra/error.h>
-#include <vnet/fib/fib_types.h>
#include <vnet/ip/format.h>
#include <vnet/ip/ip4_packet.h>
#include <vnet/ip/ip6_packet.h>
+#include <vapi/ip.api.vapi.h>
#include <vapi/hicn.api.vapi.h>
#include <vpp_plugins/hicn/error.h>
@@ -54,6 +53,7 @@ u8 *format_vl_api_address_union(u8 *s, va_list *args) { return NULL; }
/*********************************************************************************/
DEFINE_VAPI_MSG_IDS_HICN_API_JSON
+DEFINE_VAPI_MSG_IDS_IP_API_JSON
static vapi_error_e register_prod_app_cb(
vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
@@ -184,7 +184,7 @@ int hicn_vapi_face_cons_del(vapi_ctx_t ctx,
static vapi_error_e reigster_route_cb(
vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
- vapi_payload_hicn_api_route_nhops_add_reply *reply) {
+ vapi_payload_ip_route_add_del_reply *reply) {
if (reply == NULL) return rv;
return reply->retval;
@@ -193,17 +193,36 @@ static vapi_error_e reigster_route_cb(
int hicn_vapi_register_route(vapi_ctx_t ctx,
hicn_producer_set_route_params *input_params) {
vapi_lock();
- vapi_msg_hicn_api_route_nhops_add *msg =
- vapi_alloc_hicn_api_route_nhops_add(ctx);
+ vapi_msg_ip_route_add_del *msg = vapi_alloc_ip_route_add_del(ctx, 1);
+
+ msg->payload.is_add = 1;
+ if (ip46_address_is_ip4((ip46_address_t *)(input_params->prod_addr))) {
+ memcpy(&msg->payload.route.prefix.address.un.ip4, &input_params->prefix->address.v4,
+ sizeof(ip4_address_t));
+ msg->payload.route.prefix.address.af = ADDRESS_IP4;
+ msg->payload.route.prefix.len = input_params->prefix->len;
+ } else {
+ memcpy(&msg->payload.route.prefix.address.un.ip6, &input_params->prefix->address.v6,
+ sizeof(ip6_address_t));
+ msg->payload.route.prefix.address.af = ADDRESS_IP6;
+ msg->payload.route.prefix.len = input_params->prefix->len;
+ }
+
+ msg->payload.route.paths[0].sw_if_index = ~0;
+ msg->payload.route.paths[0].table_id = 0;
+ if (ip46_address_is_ip4((ip46_address_t *)(input_params->prod_addr))) {
+ memcpy(&(msg->payload.route.paths[0].nh.address.ip4), input_params->prod_addr->v4.as_u8, sizeof(ip4_address_t));
+ msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
+ }
+ else{
+ memcpy(&(msg->payload.route.paths[0].nh.address.ip6), input_params->prod_addr->v6.as_u8, sizeof(ip6_address_t));
+ msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
+ }
- fib_prefix_t prefix;
- memcpy(&prefix.fp_addr, &input_params->prefix->address,
- sizeof(ip46_address_t));
- prefix.fp_len = input_params->prefix->len;
- msg->payload.face_ids[0] = input_params->face_id;
- msg->payload.n_faces = 1;
+ msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE;
+ msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
- int ret = vapi_hicn_api_route_nhops_add(ctx, msg, reigster_route_cb, NULL);
+ int ret = vapi_ip_route_add_del(ctx, msg, reigster_route_cb, NULL);
vapi_unlock();
return ret;
diff --git a/libtransport/src/core/hicn_vapi.h b/libtransport/src/core/hicn_vapi.h
index f2718e6f5..f5d61e7ef 100644
--- a/libtransport/src/core/hicn_vapi.h
+++ b/libtransport/src/core/hicn_vapi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -20,6 +20,8 @@
#ifdef __vpp__
+
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -57,7 +59,7 @@ typedef struct {
typedef struct {
ip_prefix_t* prefix;
- uint32_t face_id;
+ ip_address_t* prod_addr;
} hicn_producer_set_route_params;
int hicn_vapi_register_prod_app(
diff --git a/libtransport/src/core/interest.cc b/libtransport/src/core/interest.cc
index 9ee662615..b4a74762d 100644
--- a/libtransport/src/core/interest.cc
+++ b/libtransport/src/core/interest.cc
@@ -31,8 +31,9 @@ namespace transport {
namespace core {
-Interest::Interest(const Name &interest_name, Packet::Format format)
- : Packet(format) {
+Interest::Interest(const Name &interest_name, Packet::Format format,
+ std::size_t additional_header_size)
+ : Packet(format, additional_header_size) {
if (hicn_interest_set_name(format_, packet_start_,
interest_name.getConstStructReference()) < 0) {
throw errors::MalformedPacketException();
@@ -45,20 +46,14 @@ Interest::Interest(const Name &interest_name, Packet::Format format)
}
#ifdef __ANDROID__
-Interest::Interest(hicn_format_t format) : Interest(Name("0::0|0"), format) {}
+Interest::Interest(hicn_format_t format, std::size_t additional_header_size)
+ : Interest(Name("0::0|0"), format, additional_header_size) {}
#else
-Interest::Interest(hicn_format_t format) : Interest(base_name, format) {}
+Interest::Interest(hicn_format_t format, std::size_t additional_header_size)
+ : Interest(base_name, format, additional_header_size) {}
#endif
-Interest::Interest(const uint8_t *buffer, std::size_t size)
- : Packet(buffer, size) {
- if (hicn_interest_get_name(format_, packet_start_,
- name_.getStructReference()) < 0) {
- throw errors::MalformedPacketException();
- }
-}
-
-Interest::Interest(MemBufPtr &&buffer) : Packet(std::move(buffer)) {
+Interest::Interest(MemBuf &&buffer) : Packet(std::move(buffer)) {
if (hicn_interest_get_name(format_, packet_start_,
name_.getStructReference()) < 0) {
throw errors::MalformedPacketException();
@@ -70,6 +65,14 @@ Interest::Interest(Interest &&other_interest)
name_ = std::move(other_interest.name_);
}
+Interest::Interest(const Interest &other_interest) : Packet(other_interest) {
+ name_ = other_interest.name_;
+}
+
+Interest &Interest::operator=(const Interest &other) {
+ return (Interest &)Packet::operator=(other);
+}
+
Interest::~Interest() {}
const Name &Interest::getName() const {
@@ -152,6 +155,59 @@ void Interest::resetForHash() {
}
}
+bool Interest::hasManifest() {
+ return (getPayloadType() == PayloadType::MANIFEST);
+}
+
+void Interest::appendSuffix(std::uint32_t suffix) {
+ if (TRANSPORT_EXPECT_FALSE(suffix_set_.empty())) {
+ setPayloadType(PayloadType::MANIFEST);
+ }
+
+ suffix_set_.emplace(suffix);
+}
+
+void Interest::encodeSuffixes() {
+ if (!hasManifest()) {
+ return;
+ }
+
+ // We assume interest does not hold signature for the moment.
+ auto int_manifest_header =
+ (InterestManifestHeader *)(writableData() + headerSize());
+ int_manifest_header->n_suffixes = (uint32_t)suffix_set_.size();
+ std::size_t additional_length =
+ int_manifest_header->n_suffixes * sizeof(uint32_t);
+
+ uint32_t *suffix = (uint32_t *)(int_manifest_header + 1);
+ for (auto it = suffix_set_.begin(); it != suffix_set_.end(); it++, suffix++) {
+ *suffix = *it;
+ }
+
+ updateLength(additional_length);
+}
+
+uint32_t *Interest::firstSuffix() {
+ if (!hasManifest()) {
+ return nullptr;
+ }
+
+ auto ret = (InterestManifestHeader *)(writableData() + headerSize());
+ ret += 1;
+
+ return (uint32_t *)ret;
+}
+
+uint32_t Interest::numberOfSuffixes() {
+ if (!hasManifest()) {
+ return 0;
+ }
+
+ auto header = (InterestManifestHeader *)(writableData() + headerSize());
+
+ return header->n_suffixes;
+}
+
} // end namespace core
} // end namespace transport
diff --git a/libtransport/src/core/io_module.cc b/libtransport/src/core/io_module.cc
new file mode 100644
index 000000000..7c2ec2cab
--- /dev/null
+++ b/libtransport/src/core/io_module.cc
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WIN32
+#include <dlfcn.h>
+#endif
+#include <hicn/transport/core/io_module.h>
+#include <hicn/transport/utils/log.h>
+
+#ifdef ANDROID
+#include <io_modules/udp/hicn_forwarder_module.h>
+#elif _WIN32
+#include <hicn/util/windows/windows_utils.h>
+#endif
+
+#include <deque>
+
+namespace transport {
+namespace core {
+
+IoModule::~IoModule() {}
+
+IoModule *IoModule::load(const char *module_name) {
+#ifdef ANDROID
+ return new HicnForwarderModule();
+#else
+ void *handle = 0;
+ IoModule *module = 0;
+ IoModule *(*creator)(void) = 0;
+ const char *error = 0;
+
+ // open module
+ handle = dlopen(module_name, RTLD_NOW);
+ if (!handle) {
+ if ((error = dlerror()) != 0) {
+ TRANSPORT_LOGE("%s", error);
+ }
+ return 0;
+ }
+
+ // link factory method
+ creator = (IoModule * (*)(void)) dlsym(handle, "create_module");
+ if (!creator) {
+ if ((error = dlerror()) != 0) {
+ TRANSPORT_LOGE("%s", error);
+ return 0;
+ }
+ }
+
+ // create object and return it
+ module = (*creator)();
+ module->handle_ = handle;
+
+ return module;
+#endif
+}
+
+bool IoModule::unload(IoModule *module) {
+ if (!module) {
+ return false;
+ }
+
+#ifdef ANDROID
+ delete module;
+#else
+ // destroy object and close module
+ void *handle = module->handle_;
+ delete module;
+ dlclose(handle);
+#endif
+
+ return true;
+}
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/core/local_connector.cc b/libtransport/src/core/local_connector.cc
new file mode 100644
index 000000000..f0e36a3d7
--- /dev/null
+++ b/libtransport/src/core/local_connector.cc
@@ -0,0 +1,47 @@
+/*
+ * 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 <core/local_connector.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/core/interest.h>
+#include <hicn/transport/errors/not_implemented_exception.h>
+#include <hicn/transport/utils/log.h>
+
+#include <asio/io_service.hpp>
+
+namespace transport {
+namespace core {
+
+LocalConnector::~LocalConnector() {}
+
+void LocalConnector::close() { state_ = State::CLOSED; }
+
+void LocalConnector::send(Packet &packet) {
+ if (!isConnected()) {
+ return;
+ }
+
+ TRANSPORT_LOGD("Sending packet to local socket.");
+ io_service_.get().post([this, p{packet.shared_from_this()}]() mutable {
+ receive_callback_(this, *p, std::make_error_code(std::errc(0)));
+ });
+}
+
+void LocalConnector::send(const uint8_t *packet, std::size_t len) {
+ throw errors::NotImplementedException();
+}
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/core/local_connector.h b/libtransport/src/core/local_connector.h
new file mode 100644
index 000000000..b0daa4f53
--- /dev/null
+++ b/libtransport/src/core/local_connector.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/connector.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/utils/move_wrapper.h>
+#include <hicn/transport/utils/shared_ptr_utils.h>
+#include <io_modules/forwarder/errors.h>
+
+#ifndef ASIO_STANDALONE
+#define ASIO_STANDALONE
+#endif
+#include <asio/io_service.hpp>
+
+namespace transport {
+namespace core {
+
+class LocalConnector : public Connector {
+ public:
+ template <typename ReceiveCallback, typename SentCallback, typename OnClose,
+ typename OnReconnect>
+ LocalConnector(asio::io_service &io_service,
+ ReceiveCallback &&receive_callback, SentCallback &&packet_sent,
+ OnClose &&close_callback, OnReconnect &&on_reconnect)
+ : Connector(receive_callback, packet_sent, close_callback, on_reconnect),
+ io_service_(io_service),
+ io_service_work_(io_service_.get()) {
+ state_ = State::CONNECTED;
+ }
+
+ ~LocalConnector() override;
+
+ void send(Packet &packet) override;
+
+ void send(const uint8_t *packet, std::size_t len) override;
+
+ void close() override;
+
+ auto shared_from_this() { return utils::shared_from(this); }
+
+ private:
+ std::reference_wrapper<asio::io_service> io_service_;
+ asio::io_service::work io_service_work_;
+ std::string name_;
+};
+
+} // namespace core
+} // namespace transport
diff --git a/libtransport/src/core/manifest.h b/libtransport/src/core/manifest.h
index eadfed752..9b25ebd67 100644
--- a/libtransport/src/core/manifest.h
+++ b/libtransport/src/core/manifest.h
@@ -15,11 +15,10 @@
#pragma once
+#include <core/manifest_format.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/name.h>
-#include <core/manifest_format.h>
-
#include <set>
namespace transport {
@@ -36,18 +35,20 @@ class Manifest : public Base {
"Base must inherit from packet!");
public:
+ // core::ContentObjectManifest::Ptr
+
using Encoder = typename FormatTraits::Encoder;
using Decoder = typename FormatTraits::Decoder;
Manifest(std::size_t signature_size = 0)
- : Base(HF_INET6_TCP_AH),
+ : Base(HF_INET6_TCP_AH, signature_size),
encoder_(*this, signature_size),
decoder_(*this) {
Base::setPayloadType(PayloadType::MANIFEST);
}
Manifest(const core::Name &name, std::size_t signature_size = 0)
- : Base(name, HF_INET6_TCP_AH),
+ : Base(name, HF_INET6_TCP_AH, signature_size),
encoder_(*this, signature_size),
decoder_(*this) {
Base::setPayloadType(PayloadType::MANIFEST);
@@ -55,7 +56,9 @@ class Manifest : public Base {
template <typename T>
Manifest(T &&base)
- : Base(std::forward<T &&>(base)), encoder_(*this), decoder_(*this) {
+ : Base(std::forward<T &&>(base)),
+ encoder_(*this, 0, false),
+ decoder_(*this) {
Base::setPayloadType(PayloadType::MANIFEST);
}
@@ -96,13 +99,13 @@ class Manifest : public Base {
return *this;
}
- Manifest &setHashAlgorithm(utils::CryptoHashType hash_algorithm) {
+ Manifest &setHashAlgorithm(auth::CryptoHashType hash_algorithm) {
hash_algorithm_ = hash_algorithm;
encoder_.setHashAlgorithm(hash_algorithm_);
return *this;
}
- utils::CryptoHashType getHashAlgorithm() { return hash_algorithm_; }
+ auth::CryptoHashType getHashAlgorithm() { return hash_algorithm_; }
ManifestType getManifestType() const { return manifest_type_; }
@@ -138,7 +141,7 @@ class Manifest : public Base {
protected:
ManifestType manifest_type_;
- utils::CryptoHashType hash_algorithm_;
+ auth::CryptoHashType hash_algorithm_;
bool is_last_;
Encoder encoder_;
diff --git a/libtransport/src/core/manifest_format.h b/libtransport/src/core/manifest_format.h
index 36d23f99b..b759942cb 100644
--- a/libtransport/src/core/manifest_format.h
+++ b/libtransport/src/core/manifest_format.h
@@ -15,8 +15,8 @@
#pragma once
+#include <hicn/transport/auth/crypto_hasher.h>
#include <hicn/transport/core/name.h>
-#include <hicn/transport/security/crypto_hasher.h>
#include <cinttypes>
#include <type_traits>
@@ -63,8 +63,10 @@ template <typename T>
struct format_traits {
using Encoder = typename T::Encoder;
using Decoder = typename T::Decoder;
+ using Hash = typename T::Hash;
using HashType = typename T::HashType;
- using HashList = typename T::HashList;
+ using Suffix = typename T::Suffix;
+ using SuffixList = typename T::SuffixList;
};
class Packet;
@@ -86,7 +88,7 @@ class ManifestEncoder {
return static_cast<Implementation &>(*this).setManifestTypeImpl(type);
}
- ManifestEncoder &setHashAlgorithm(utils::CryptoHashType hash) {
+ ManifestEncoder &setHashAlgorithm(auth::CryptoHashType hash) {
return static_cast<Implementation &>(*this).setHashAlgorithmImpl(hash);
}
@@ -160,7 +162,7 @@ class ManifestDecoder {
return static_cast<const Implementation &>(*this).getManifestTypeImpl();
}
- utils::CryptoHashType getHashAlgorithm() const {
+ auth::CryptoHashType getHashAlgorithm() const {
return static_cast<const Implementation &>(*this).getHashAlgorithmImpl();
}
diff --git a/libtransport/src/core/manifest_format_fixed.cc b/libtransport/src/core/manifest_format_fixed.cc
index ca80c38b1..7076a4c90 100644
--- a/libtransport/src/core/manifest_format_fixed.cc
+++ b/libtransport/src/core/manifest_format_fixed.cc
@@ -13,49 +13,50 @@
* limitations under the License.
*/
+#include <core/manifest_format_fixed.h>
#include <hicn/transport/core/packet.h>
#include <hicn/transport/utils/literals.h>
-#include <core/manifest_format_fixed.h>
-
namespace transport {
namespace core {
// TODO use preallocated pool of membufs
FixedManifestEncoder::FixedManifestEncoder(Packet &packet,
- std::size_t signature_size)
+ std::size_t signature_size,
+ bool clear)
: packet_(packet),
- max_size_(Packet::default_mtu - packet_.headerSize() - signature_size),
- manifest_(
- utils::MemBuf::create(Packet::default_mtu - packet_.headerSize())),
- manifest_header_(
- reinterpret_cast<ManifestHeader *>(manifest_->writableData())),
- manifest_entries_(reinterpret_cast<ManifestEntry *>(
- manifest_->writableData() + sizeof(ManifestHeader))),
+ max_size_(Packet::default_mtu - packet_.headerSize()),
+ manifest_header_(reinterpret_cast<ManifestHeader *>(
+ packet_.writableData() + packet_.headerSize())),
+ manifest_entries_(
+ reinterpret_cast<ManifestEntry *>(manifest_header_ + 1)),
current_entry_(0),
signature_size_(signature_size) {
- *manifest_header_ = {0};
+ if (clear) {
+ memset(manifest_header_, 0, sizeof(*manifest_header_));
+ }
}
FixedManifestEncoder::~FixedManifestEncoder() {}
FixedManifestEncoder &FixedManifestEncoder::encodeImpl() {
- manifest_->append(sizeof(ManifestHeader) +
- manifest_header_->number_of_entries *
- sizeof(ManifestEntry));
- packet_.appendPayload(std::move(manifest_));
+ packet_.append(sizeof(ManifestHeader) +
+ manifest_header_->number_of_entries * sizeof(ManifestEntry));
+ packet_.updateLength();
return *this;
}
FixedManifestEncoder &FixedManifestEncoder::clearImpl() {
- manifest_ = utils::MemBuf::create(Packet::default_mtu - packet_.headerSize() -
- signature_size_);
+ packet_.trimEnd(sizeof(ManifestHeader) +
+ manifest_header_->number_of_entries * sizeof(ManifestEntry));
+ current_entry_ = 0;
+ memset(manifest_header_, 0, sizeof(*manifest_header_));
return *this;
}
FixedManifestEncoder &FixedManifestEncoder::setHashAlgorithmImpl(
- utils::CryptoHashType algorithm) {
+ auth::CryptoHashType algorithm) {
manifest_header_->hash_algorithm = static_cast<uint8_t>(algorithm);
return *this;
}
@@ -83,7 +84,7 @@ FixedManifestEncoder &FixedManifestEncoder::setBaseNameImpl(
}
FixedManifestEncoder &FixedManifestEncoder::addSuffixAndHashImpl(
- uint32_t suffix, const utils::CryptoHash &hash) {
+ uint32_t suffix, const auth::CryptoHash &hash) {
auto _hash = hash.getDigest<std::uint8_t>();
addSuffixHashBytes(suffix, _hash.data(), _hash.length());
return *this;
@@ -170,8 +171,8 @@ ManifestType FixedManifestDecoder::getManifestTypeImpl() const {
return static_cast<ManifestType>(manifest_header_->manifest_type);
}
-utils::CryptoHashType FixedManifestDecoder::getHashAlgorithmImpl() const {
- return static_cast<utils::CryptoHashType>(manifest_header_->hash_algorithm);
+auth::CryptoHashType FixedManifestDecoder::getHashAlgorithmImpl() const {
+ return static_cast<auth::CryptoHashType>(manifest_header_->hash_algorithm);
}
NextSegmentCalculationStrategy
diff --git a/libtransport/src/core/manifest_format_fixed.h b/libtransport/src/core/manifest_format_fixed.h
index 1d7cd7d32..56ad4ef6d 100644
--- a/libtransport/src/core/manifest_format_fixed.h
+++ b/libtransport/src/core/manifest_format_fixed.h
@@ -15,9 +15,8 @@
#pragma once
-#include <hicn/transport/core/packet.h>
-
#include <core/manifest_format.h>
+#include <hicn/transport/core/packet.h>
#include <string>
@@ -53,8 +52,10 @@ class Packet;
struct Fixed {
using Encoder = FixedManifestEncoder;
using Decoder = FixedManifestDecoder;
- using HashType = utils::CryptoHash;
- using SuffixList = std::list<std::pair<std::uint32_t, std::uint8_t *>>;
+ using Hash = auth::CryptoHash;
+ using HashType = auth::CryptoHashType;
+ using Suffix = uint32_t;
+ using SuffixList = std::list<std::pair<uint32_t, uint8_t *>>;
};
struct Flags {
@@ -84,7 +85,8 @@ static const constexpr std::uint8_t manifest_version = 1;
class FixedManifestEncoder : public ManifestEncoder<FixedManifestEncoder> {
public:
- FixedManifestEncoder(Packet &packet, std::size_t signature_size = 0);
+ FixedManifestEncoder(Packet &packet, std::size_t signature_size = 0,
+ bool clear = true);
~FixedManifestEncoder();
@@ -94,7 +96,7 @@ class FixedManifestEncoder : public ManifestEncoder<FixedManifestEncoder> {
FixedManifestEncoder &setManifestTypeImpl(ManifestType manifest_type);
- FixedManifestEncoder &setHashAlgorithmImpl(utils::CryptoHashType algorithm);
+ FixedManifestEncoder &setHashAlgorithmImpl(Fixed::HashType algorithm);
FixedManifestEncoder &setNextSegmentCalculationStrategyImpl(
NextSegmentCalculationStrategy strategy);
@@ -102,7 +104,7 @@ class FixedManifestEncoder : public ManifestEncoder<FixedManifestEncoder> {
FixedManifestEncoder &setBaseNameImpl(const core::Name &base_name);
FixedManifestEncoder &addSuffixAndHashImpl(uint32_t suffix,
- const utils::CryptoHash &hash);
+ const Fixed::Hash &hash);
FixedManifestEncoder &setIsFinalManifestImpl(bool is_last);
@@ -125,7 +127,6 @@ class FixedManifestEncoder : public ManifestEncoder<FixedManifestEncoder> {
Packet &packet_;
std::size_t max_size_;
- std::unique_ptr<utils::MemBuf> manifest_;
ManifestHeader *manifest_header_;
ManifestEntry *manifest_entries_;
std::size_t current_entry_;
@@ -144,7 +145,7 @@ class FixedManifestDecoder : public ManifestDecoder<FixedManifestDecoder> {
ManifestType getManifestTypeImpl() const;
- utils::CryptoHashType getHashAlgorithmImpl() const;
+ Fixed::HashType getHashAlgorithmImpl() const;
NextSegmentCalculationStrategy getNextSegmentCalculationStrategyImpl() const;
diff --git a/libtransport/src/core/manifest_inline.h b/libtransport/src/core/manifest_inline.h
index 0227fa93a..fcb1d214f 100644
--- a/libtransport/src/core/manifest_inline.h
+++ b/libtransport/src/core/manifest_inline.h
@@ -15,10 +15,10 @@
#pragma once
-#include <hicn/transport/portability/portability.h>
-
#include <core/manifest.h>
#include <core/manifest_format.h>
+#include <hicn/transport/portability/portability.h>
+
#include <set>
namespace transport {
@@ -30,8 +30,12 @@ class ManifestInline
: public Manifest<Base, FormatTraits, ManifestInline<Base, FormatTraits>> {
using ManifestBase =
Manifest<Base, FormatTraits, ManifestInline<Base, FormatTraits>>;
+
+ using Hash = typename FormatTraits::Hash;
using HashType = typename FormatTraits::HashType;
+ using Suffix = typename FormatTraits::Suffix;
using SuffixList = typename FormatTraits::SuffixList;
+ using HashEntry = std::pair<auth::CryptoHashType, std::vector<uint8_t>>;
public:
ManifestInline() : ManifestBase() {}
@@ -44,7 +48,7 @@ class ManifestInline
static TRANSPORT_ALWAYS_INLINE ManifestInline *createManifest(
const core::Name &manifest_name, ManifestVersion version,
- ManifestType type, utils::CryptoHashType algorithm, bool is_last,
+ ManifestType type, auth::CryptoHashType algorithm, bool is_last,
const Name &base_name, NextSegmentCalculationStrategy strategy,
std::size_t signature_size) {
auto manifest = new ManifestInline(manifest_name, signature_size);
@@ -84,7 +88,7 @@ class ManifestInline
const Name &getBaseName() { return base_name_; }
- ManifestInline &addSuffixHash(uint32_t suffix, const HashType &hash) {
+ ManifestInline &addSuffixHash(Suffix suffix, const Hash &hash) {
ManifestBase::encoder_.addSuffixAndHash(suffix, hash);
return *this;
}
@@ -104,12 +108,35 @@ class ManifestInline
return next_segment_strategy_;
}
+ // Convert several manifests into a single map from suffixes to packet hashes.
+ // All manifests must have been decoded beforehand.
+ static std::unordered_map<Suffix, HashEntry> getSuffixMap(
+ const std::vector<ManifestInline *> &manifests) {
+ std::unordered_map<Suffix, HashEntry> suffix_map;
+
+ for (auto manifest_ptr : manifests) {
+ HashType hash_algorithm = manifest_ptr->getHashAlgorithm();
+ SuffixList suffix_list = manifest_ptr->getSuffixList();
+
+ for (auto it = suffix_list.begin(); it != suffix_list.end(); ++it) {
+ std::vector<uint8_t> hash(
+ it->second, it->second + auth::hash_size_map[hash_algorithm]);
+ suffix_map[it->first] = {hash_algorithm, hash};
+ }
+ }
+
+ return suffix_map;
+ }
+ static std::unordered_map<Suffix, HashEntry> getSuffixMap(
+ ManifestInline *manifest) {
+ return getSuffixMap(std::vector<ManifestInline *>{manifest});
+ }
+
private:
core::Name base_name_;
NextSegmentCalculationStrategy next_segment_strategy_;
SuffixList suffix_hash_map_;
};
-} // end namespace core
-
-} // end namespace transport \ No newline at end of file
+} // namespace core
+} // namespace transport
diff --git a/libtransport/src/core/memif_connector.cc b/libtransport/src/core/memif_connector.cc
index 49f262ec8..087e8cba8 100644
--- a/libtransport/src/core/memif_connector.cc
+++ b/libtransport/src/core/memif_connector.cc
@@ -13,13 +13,13 @@
* limitations under the License.
*/
-#include <hicn/transport/errors/not_implemented_exception.h>
-
#include <core/memif_connector.h>
+#include <hicn/transport/errors/not_implemented_exception.h>
#ifdef __vpp__
#include <sys/epoll.h>
+
#include <cstdlib>
extern "C" {
@@ -267,6 +267,7 @@ int MemifConnector::bufferAlloc(long n, uint16_t qid) {
if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
TRANSPORT_LOGE("memif_buffer_alloc: %s", memif_strerror(err));
+ return -1;
}
c->tx_buf_num += r;
@@ -441,7 +442,7 @@ void MemifConnector::send(const Packet::MemBufPtr &packet) {
int MemifConnector::doSend() {
std::size_t max = 0;
- uint16_t n = 0;
+ int32_t n = 0;
std::size_t size = 0;
{
@@ -451,9 +452,9 @@ int MemifConnector::doSend() {
do {
max = size < MAX_MEMIF_BUFS ? size : MAX_MEMIF_BUFS;
+ n = bufferAlloc(max, memif_connection_->tx_qid);
- if (TRANSPORT_EXPECT_FALSE(
- (n = bufferAlloc(max, memif_connection_->tx_qid)) < 0)) {
+ if (TRANSPORT_EXPECT_FALSE(n < 0)) {
TRANSPORT_LOGE("Error allocating buffers.");
return -1;
}
diff --git a/libtransport/src/core/memif_connector.h b/libtransport/src/core/memif_connector.h
index 693efd14c..8a0e9efad 100644
--- a/libtransport/src/core/memif_connector.h
+++ b/libtransport/src/core/memif_connector.h
@@ -15,11 +15,10 @@
#pragma once
+#include <core/connector.h>
#include <hicn/transport/config.h>
#include <hicn/transport/portability/portability.h>
#include <hicn/transport/utils/ring_buffer.h>
-
-#include <core/connector.h>
//#include <hicn/transport/core/hicn_vapi.h>
#include <utils/epoll_event_reactor.h>
#include <utils/fd_deadline_timer.h>
@@ -43,7 +42,7 @@ typedef struct memif_connection memif_connection_t;
#define IF_NAME "vpp_connection"
#define MEMIF_BUF_SIZE 2048
-#define MEMIF_LOG2_RING_SIZE 11
+#define MEMIF_LOG2_RING_SIZE 13
#define MAX_MEMIF_BUFS (1 << MEMIF_LOG2_RING_SIZE)
class MemifConnector : public Connector {
diff --git a/libtransport/src/core/name.cc b/libtransport/src/core/name.cc
index 811e93b87..795c8a697 100644
--- a/libtransport/src/core/name.cc
+++ b/libtransport/src/core/name.cc
@@ -13,14 +13,13 @@
* limitations under the License.
*/
+#include <core/manifest_format.h>
#include <hicn/transport/core/name.h>
#include <hicn/transport/errors/errors.h>
#include <hicn/transport/errors/tokenizer_exception.h>
#include <hicn/transport/utils/hash.h>
#include <hicn/transport/utils/string_tokenizer.h>
-#include <core/manifest_format.h>
-
namespace transport {
namespace core {
@@ -98,7 +97,12 @@ bool Name::operator!=(const Name &name) const {
}
Name::operator bool() const {
- return bool(hicn_name_empty((hicn_name_t *)&name_));
+ auto ret = isValid();
+ return ret;
+}
+
+bool Name::isValid() const {
+ return bool(!hicn_name_empty((hicn_name_t *)&name_));
}
bool Name::equals(const Name &name, bool consider_segment) const {
diff --git a/libtransport/src/core/packet.cc b/libtransport/src/core/packet.cc
index 6815868f0..6f237729a 100644
--- a/libtransport/src/core/packet.cc
+++ b/libtransport/src/core/packet.cc
@@ -31,58 +31,94 @@ namespace core {
const core::Name Packet::base_name("0::0|0");
-Packet::Packet(Format format)
- : packet_(utils::MemBuf::create(getHeaderSizeFromFormat(format, 256))
- .release()),
- packet_start_(reinterpret_cast<hicn_header_t *>(packet_->writableData())),
- header_head_(packet_.get()),
- payload_head_(nullptr),
- format_(format) {
- if (hicn_packet_init_header(format, packet_start_) < 0) {
- throw errors::RuntimeException("Unexpected error initializing the packet.");
- }
-
- packet_->append(getHeaderSizeFromFormat(format_));
-}
-
-Packet::Packet(MemBufPtr &&buffer)
- : packet_(std::move(buffer)),
- packet_start_(reinterpret_cast<hicn_header_t *>(packet_->writableData())),
- header_head_(packet_.get()),
- payload_head_(nullptr),
- format_(getFormatFromBuffer(packet_->writableData())) {}
-
-Packet::Packet(const uint8_t *buffer, std::size_t size)
- : Packet(MemBufPtr(utils::MemBuf::copyBuffer(buffer, size).release())) {}
+Packet::Packet(Format format, std::size_t additional_header_size)
+ : utils::MemBuf(utils::MemBuf(CREATE, 2048)),
+ packet_start_(reinterpret_cast<hicn_header_t *>(writableData())),
+ header_offset_(0),
+ format_(format),
+ payload_type_(PayloadType::UNSPECIFIED) {
+ setFormat(format_, additional_header_size);
+}
+
+Packet::Packet(MemBuf &&buffer)
+ : utils::MemBuf(std::move(buffer)),
+ packet_start_(reinterpret_cast<hicn_header_t *>(writableData())),
+ header_offset_(0),
+ format_(getFormatFromBuffer(data(), length())),
+ payload_type_(PayloadType::UNSPECIFIED) {}
+
+Packet::Packet(CopyBufferOp, const uint8_t *buffer, std::size_t size)
+ : utils::MemBuf(COPY_BUFFER, buffer, size),
+ packet_start_(reinterpret_cast<hicn_header_t *>(writableData())),
+ header_offset_(0),
+ format_(getFormatFromBuffer(data(), length())),
+ payload_type_(PayloadType::UNSPECIFIED) {}
+
+Packet::Packet(WrapBufferOp, uint8_t *buffer, std::size_t length,
+ std::size_t size)
+ : utils::MemBuf(WRAP_BUFFER, buffer, length, size),
+ packet_start_(reinterpret_cast<hicn_header_t *>(writableData())),
+ header_offset_(0),
+ format_(getFormatFromBuffer(this->data(), this->length())),
+ payload_type_(PayloadType::UNSPECIFIED) {}
+
+Packet::Packet(CreateOp, uint8_t *buffer, std::size_t length, std::size_t size,
+ Format format, std::size_t additional_header_size)
+ : utils::MemBuf(WRAP_BUFFER, buffer, length, size),
+ packet_start_(reinterpret_cast<hicn_header_t *>(writableData())),
+ header_offset_(0),
+ format_(format),
+ payload_type_(PayloadType::UNSPECIFIED) {
+ clear();
+ setFormat(format_, additional_header_size);
+}
+
+Packet::Packet(const Packet &other)
+ : utils::MemBuf(other),
+ packet_start_(reinterpret_cast<hicn_header_t *>(writableData())),
+ header_offset_(other.header_offset_),
+ format_(other.format_),
+ payload_type_(PayloadType::UNSPECIFIED) {}
Packet::Packet(Packet &&other)
- : packet_(std::move(other.packet_)),
+ : utils::MemBuf(std::move(other)),
packet_start_(other.packet_start_),
- header_head_(other.header_head_),
- payload_head_(other.payload_head_),
- format_(other.format_) {
+ header_offset_(other.header_offset_),
+ format_(other.format_),
+ payload_type_(PayloadType::UNSPECIFIED) {
other.packet_start_ = nullptr;
- other.header_head_ = nullptr;
- other.payload_head_ = nullptr;
other.format_ = HF_UNSPEC;
+ other.header_offset_ = 0;
}
Packet::~Packet() {}
+Packet &Packet::operator=(const Packet &other) {
+ if (this != &other) {
+ *this = other;
+ packet_start_ = reinterpret_cast<hicn_header_t *>(writableData());
+ }
+
+ return *this;
+}
+
std::size_t Packet::getHeaderSizeFromBuffer(Format format,
const uint8_t *buffer) {
size_t header_length;
+
if (hicn_packet_get_header_length(format, (hicn_header_t *)buffer,
&header_length) < 0) {
throw errors::MalformedPacketException();
}
+
return header_length;
}
bool Packet::isInterest(const uint8_t *buffer) {
bool is_interest = false;
- if (TRANSPORT_EXPECT_FALSE(hicn_packet_test_ece((const hicn_header_t *)buffer,
+ if (TRANSPORT_EXPECT_FALSE(hicn_packet_test_ece(HF_INET6_TCP,
+ (const hicn_header_t *)buffer,
&is_interest) < 0)) {
throw errors::RuntimeException(
"Impossible to retrieve ece flag from packet");
@@ -91,6 +127,25 @@ bool Packet::isInterest(const uint8_t *buffer) {
return !is_interest;
}
+void Packet::setFormat(Packet::Format format,
+ std::size_t additional_header_size) {
+ format_ = format;
+ if (hicn_packet_init_header(format_, packet_start_) < 0) {
+ throw errors::RuntimeException("Unexpected error initializing the packet.");
+ }
+
+ auto header_size = getHeaderSizeFromFormat(format_);
+ assert(header_size <= tailroom());
+ append(header_size);
+
+ assert(additional_header_size <= tailroom());
+ append(additional_header_size);
+
+ header_offset_ = length();
+}
+
+bool Packet::isInterest() { return Packet::isInterest(data()); }
+
std::size_t Packet::getPayloadSizeFromBuffer(Format format,
const uint8_t *buffer) {
std::size_t payload_length;
@@ -104,67 +159,58 @@ std::size_t Packet::getPayloadSizeFromBuffer(Format format,
}
std::size_t Packet::payloadSize() const {
- return getPayloadSizeFromBuffer(format_,
- reinterpret_cast<uint8_t *>(packet_start_));
+ std::size_t ret = 0;
+
+ if (length()) {
+ ret = getPayloadSizeFromBuffer(format_,
+ reinterpret_cast<uint8_t *>(packet_start_));
+ }
+
+ return ret;
}
std::size_t Packet::headerSize() const {
- return getHeaderSizeFromBuffer(format_,
- reinterpret_cast<uint8_t *>(packet_start_));
+ if (header_offset_ == 0 && length()) {
+ const_cast<Packet *>(this)->header_offset_ = getHeaderSizeFromBuffer(
+ format_, reinterpret_cast<uint8_t *>(packet_start_));
+ }
+
+ return header_offset_;
}
Packet &Packet::appendPayload(std::unique_ptr<utils::MemBuf> &&payload) {
- separateHeaderPayload();
-
- if (!payload_head_) {
- payload_head_ = payload.get();
- }
-
- header_head_->prependChain(std::move(payload));
+ prependChain(std::move(payload));
updateLength();
return *this;
}
Packet &Packet::appendPayload(const uint8_t *buffer, std::size_t length) {
- return appendPayload(utils::MemBuf::copyBuffer(buffer, length));
-}
+ prependPayload(&buffer, &length);
-Packet &Packet::appendHeader(std::unique_ptr<utils::MemBuf> &&header) {
- separateHeaderPayload();
-
- if (!payload_head_) {
- header_head_->prependChain(std::move(header));
- } else {
- payload_head_->prependChain(std::move(header));
+ if (length) {
+ appendPayload(utils::MemBuf::copyBuffer(buffer, length));
}
updateLength();
return *this;
}
-Packet &Packet::appendHeader(const uint8_t *buffer, std::size_t length) {
- return appendHeader(utils::MemBuf::copyBuffer(buffer, length));
-}
-
std::unique_ptr<utils::MemBuf> Packet::getPayload() const {
- const_cast<Packet *>(this)->separateHeaderPayload();
-
- // Hopefully the payload is contiguous
- if (TRANSPORT_EXPECT_FALSE(payload_head_ &&
- payload_head_->next() != header_head_)) {
- payload_head_->gather(payloadSize());
- }
-
- return payload_head_->cloneOne();
+ auto ret = clone();
+ ret->trimStart(headerSize());
+ return ret;
}
Packet &Packet::updateLength(std::size_t length) {
std::size_t total_length = length;
- for (utils::MemBuf *current = payload_head_;
- current && current != header_head_; current = current->next()) {
+ const utils::MemBuf *current = this;
+ do {
total_length += current->length();
- }
+ current = current->next();
+ } while (current != this);
+
+ total_length -= headerSize();
if (hicn_packet_set_payload_length(format_, packet_start_, total_length) <
0) {
@@ -175,13 +221,16 @@ Packet &Packet::updateLength(std::size_t length) {
}
PayloadType Packet::getPayloadType() const {
- hicn_payload_type_t ret = HPT_UNSPEC;
+ if (payload_type_ == PayloadType::UNSPECIFIED) {
+ hicn_payload_type_t ret;
+ if (hicn_packet_get_payload_type(packet_start_, &ret) < 0) {
+ throw errors::RuntimeException("Impossible to retrieve payload type.");
+ }
- if (hicn_packet_get_payload_type(packet_start_, &ret) < 0) {
- throw errors::RuntimeException("Impossible to retrieve payload type.");
+ payload_type_ = (PayloadType)ret;
}
- return PayloadType(ret);
+ return payload_type_;
}
Packet &Packet::setPayloadType(PayloadType payload_type) {
@@ -190,60 +239,76 @@ Packet &Packet::setPayloadType(PayloadType payload_type) {
throw errors::RuntimeException("Error setting payload type of the packet.");
}
+ payload_type_ = payload_type;
+
return *this;
}
Packet::Format Packet::getFormat() const {
- if (format_ == HF_UNSPEC) {
+ /**
+ * We check packet start because after a movement it will result in a nullptr
+ */
+ if (format_ == HF_UNSPEC && length()) {
if (hicn_packet_get_format(packet_start_, &format_) < 0) {
- throw errors::MalformedPacketException();
+ TRANSPORT_LOGE("Unexpected packet format.");
}
}
return format_;
}
-const std::shared_ptr<utils::MemBuf> Packet::acquireMemBufReference() const {
- return packet_;
+std::shared_ptr<utils::MemBuf> Packet::acquireMemBufReference() {
+ return std::static_pointer_cast<utils::MemBuf>(shared_from_this());
}
void Packet::dump() const {
- const_cast<Packet *>(this)->separateHeaderPayload();
+ TRANSPORT_LOGI("HEADER -- Length: %zu", headerSize());
+ TRANSPORT_LOGI("PAYLOAD -- Length: %zu", payloadSize());
- std::cout << "HEADER -- Length: " << headerSize() << std::endl;
- hicn_packet_dump((uint8_t *)header_head_->data(), headerSize());
+ const utils::MemBuf *current = this;
+ do {
+ TRANSPORT_LOGI("MemBuf Length: %zu", current->length());
+ dump((uint8_t *)current->data(), current->length());
+ current = current->next();
+ } while (current != this);
+}
- std::cout << std::endl << "PAYLOAD -- Length: " << payloadSize() << std::endl;
- for (utils::MemBuf *current = payload_head_;
- current && current != header_head_; current = current->next()) {
- std::cout << "MemBuf Length: " << current->length() << std::endl;
- hicn_packet_dump((uint8_t *)current->data(), current->length());
- }
+void Packet::dump(uint8_t *buffer, std::size_t length) {
+ hicn_packet_dump(buffer, length);
}
void Packet::setSignatureSize(std::size_t size_bytes) {
+ if (!authenticationHeader()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
int ret = hicn_packet_set_signature_size(format_, packet_start_, size_bytes);
if (ret < 0) {
- throw errors::RuntimeException("Packet without Authentication Header.");
+ throw errors::RuntimeException("Error setting signature size.");
}
-
- packet_->append(size_bytes);
- updateLength();
}
uint8_t *Packet::getSignature() const {
+ if (!authenticationHeader()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
uint8_t *signature;
int ret = hicn_packet_get_signature(format_, packet_start_, &signature);
if (ret < 0) {
- throw errors::RuntimeException("Packet without Authentication Header.");
+ throw errors::RuntimeException("Error getting signature.");
}
return signature;
}
void Packet::setSignatureTimestamp(const uint64_t &timestamp) {
+ if (!authenticationHeader()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
int ret =
hicn_packet_set_signature_timestamp(format_, packet_start_, timestamp);
@@ -253,6 +318,10 @@ void Packet::setSignatureTimestamp(const uint64_t &timestamp) {
}
uint64_t Packet::getSignatureTimestamp() const {
+ if (!authenticationHeader()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
uint64_t return_value;
int ret = hicn_packet_get_signature_timestamp(format_, packet_start_,
&return_value);
@@ -265,7 +334,11 @@ uint64_t Packet::getSignatureTimestamp() const {
}
void Packet::setValidationAlgorithm(
- const utils::CryptoSuite &validation_algorithm) {
+ const auth::CryptoSuite &validation_algorithm) {
+ if (!authenticationHeader()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
int ret = hicn_packet_set_validation_algorithm(format_, packet_start_,
uint8_t(validation_algorithm));
@@ -274,7 +347,11 @@ void Packet::setValidationAlgorithm(
}
}
-utils::CryptoSuite Packet::getValidationAlgorithm() const {
+auth::CryptoSuite Packet::getValidationAlgorithm() const {
+ if (!authenticationHeader()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
uint8_t return_value;
int ret = hicn_packet_get_validation_algorithm(format_, packet_start_,
&return_value);
@@ -283,10 +360,14 @@ utils::CryptoSuite Packet::getValidationAlgorithm() const {
throw errors::RuntimeException("Error getting the validation algorithm.");
}
- return utils::CryptoSuite(return_value);
+ return auth::CryptoSuite(return_value);
}
-void Packet::setKeyId(const utils::KeyId &key_id) {
+void Packet::setKeyId(const auth::KeyId &key_id) {
+ if (!authenticationHeader()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
int ret = hicn_packet_set_key_id(format_, packet_start_, key_id.first);
if (ret < 0) {
@@ -294,8 +375,12 @@ void Packet::setKeyId(const utils::KeyId &key_id) {
}
}
-utils::KeyId Packet::getKeyId() const {
- utils::KeyId return_value;
+auth::KeyId Packet::getKeyId() const {
+ if (!authenticationHeader()) {
+ throw errors::RuntimeException("Packet without Authentication Header.");
+ }
+
+ auth::KeyId return_value;
int ret = hicn_packet_get_key_id(format_, packet_start_, &return_value.first,
&return_value.second);
@@ -306,8 +391,8 @@ utils::KeyId Packet::getKeyId() const {
return return_value;
}
-utils::CryptoHash Packet::computeDigest(utils::CryptoHashType algorithm) const {
- utils::CryptoHasher hasher(static_cast<utils::CryptoHashType>(algorithm));
+auth::CryptoHash Packet::computeDigest(auth::CryptoHashType algorithm) const {
+ auth::CryptoHasher hasher(static_cast<auth::CryptoHashType>(algorithm));
hasher.init();
// Copy IP+TCP/ICMP header before zeroing them
@@ -317,11 +402,11 @@ utils::CryptoHash Packet::computeDigest(utils::CryptoHashType algorithm) const {
const_cast<Packet *>(this)->resetForHash();
- auto current = header_head_;
+ const utils::MemBuf *current = this;
do {
hasher.updateBytes(current->data(), current->length());
current = current->next();
- } while (current != header_head_);
+ } while (current != this);
hicn_packet_copy_header(format_, &header_copy, packet_start_, false);
@@ -329,15 +414,33 @@ utils::CryptoHash Packet::computeDigest(utils::CryptoHashType algorithm) const {
}
bool Packet::checkIntegrity() const {
- if (hicn_packet_check_integrity(format_, packet_start_) < 0) {
+ uint16_t partial_csum =
+ csum(data() + HICN_V6_TCP_HDRLEN, length() - HICN_V6_TCP_HDRLEN, 0);
+
+ for (const utils::MemBuf *current = next(); current != this;
+ current = current->next()) {
+ partial_csum = csum(current->data(), current->length(), ~partial_csum);
+ }
+
+ if (hicn_packet_check_integrity_no_payload(format_, packet_start_,
+ partial_csum) < 0) {
return false;
}
return true;
}
+void Packet::prependPayload(const uint8_t **buffer, std::size_t *size) {
+ auto last = prev();
+ auto to_copy = std::min(*size, last->tailroom());
+ std::memcpy(last->writableTail(), *buffer, to_copy);
+ last->append(to_copy);
+ *size -= to_copy;
+ *buffer += to_copy;
+}
+
Packet &Packet::setSyn() {
- if (hicn_packet_set_syn(packet_start_) < 0) {
+ if (hicn_packet_set_syn(format_, packet_start_) < 0) {
throw errors::RuntimeException("Error setting syn bit in the packet.");
}
@@ -345,7 +448,7 @@ Packet &Packet::setSyn() {
}
Packet &Packet::resetSyn() {
- if (hicn_packet_reset_syn(packet_start_) < 0) {
+ if (hicn_packet_reset_syn(format_, packet_start_) < 0) {
throw errors::RuntimeException("Error resetting syn bit in the packet.");
}
@@ -354,7 +457,7 @@ Packet &Packet::resetSyn() {
bool Packet::testSyn() const {
bool res = false;
- if (hicn_packet_test_syn(packet_start_, &res) < 0) {
+ if (hicn_packet_test_syn(format_, packet_start_, &res) < 0) {
throw errors::RuntimeException("Error testing syn bit in the packet.");
}
@@ -362,7 +465,7 @@ bool Packet::testSyn() const {
}
Packet &Packet::setAck() {
- if (hicn_packet_set_ack(packet_start_) < 0) {
+ if (hicn_packet_set_ack(format_, packet_start_) < 0) {
throw errors::RuntimeException("Error setting ack bit in the packet.");
}
@@ -370,7 +473,7 @@ Packet &Packet::setAck() {
}
Packet &Packet::resetAck() {
- if (hicn_packet_reset_ack(packet_start_) < 0) {
+ if (hicn_packet_reset_ack(format_, packet_start_) < 0) {
throw errors::RuntimeException("Error resetting ack bit in the packet.");
}
@@ -379,7 +482,7 @@ Packet &Packet::resetAck() {
bool Packet::testAck() const {
bool res = false;
- if (hicn_packet_test_ack(packet_start_, &res) < 0) {
+ if (hicn_packet_test_ack(format_, packet_start_, &res) < 0) {
throw errors::RuntimeException("Error testing ack bit in the packet.");
}
@@ -387,7 +490,7 @@ bool Packet::testAck() const {
}
Packet &Packet::setRst() {
- if (hicn_packet_set_rst(packet_start_) < 0) {
+ if (hicn_packet_set_rst(format_, packet_start_) < 0) {
throw errors::RuntimeException("Error setting rst bit in the packet.");
}
@@ -395,7 +498,7 @@ Packet &Packet::setRst() {
}
Packet &Packet::resetRst() {
- if (hicn_packet_reset_rst(packet_start_) < 0) {
+ if (hicn_packet_reset_rst(format_, packet_start_) < 0) {
throw errors::RuntimeException("Error resetting rst bit in the packet.");
}
@@ -404,7 +507,7 @@ Packet &Packet::resetRst() {
bool Packet::testRst() const {
bool res = false;
- if (hicn_packet_test_rst(packet_start_, &res) < 0) {
+ if (hicn_packet_test_rst(format_, packet_start_, &res) < 0) {
throw errors::RuntimeException("Error testing rst bit in the packet.");
}
@@ -412,7 +515,7 @@ bool Packet::testRst() const {
}
Packet &Packet::setFin() {
- if (hicn_packet_set_fin(packet_start_) < 0) {
+ if (hicn_packet_set_fin(format_, packet_start_) < 0) {
throw errors::RuntimeException("Error setting fin bit in the packet.");
}
@@ -420,7 +523,7 @@ Packet &Packet::setFin() {
}
Packet &Packet::resetFin() {
- if (hicn_packet_reset_fin(packet_start_) < 0) {
+ if (hicn_packet_reset_fin(format_, packet_start_) < 0) {
throw errors::RuntimeException("Error resetting fin bit in the packet.");
}
@@ -429,7 +532,7 @@ Packet &Packet::resetFin() {
bool Packet::testFin() const {
bool res = false;
- if (hicn_packet_test_fin(packet_start_, &res) < 0) {
+ if (hicn_packet_test_fin(format_, packet_start_, &res) < 0) {
throw errors::RuntimeException("Error testing fin bit in the packet.");
}
@@ -446,24 +549,29 @@ Packet &Packet::resetFlags() {
}
std::string Packet::printFlags() const {
- std::string flags = "";
+ std::string flags;
+
if (testSyn()) {
flags += "S";
}
+
if (testAck()) {
flags += "A";
}
+
if (testRst()) {
flags += "R";
}
+
if (testFin()) {
flags += "F";
}
+
return flags;
}
Packet &Packet::setSrcPort(uint16_t srcPort) {
- if (hicn_packet_set_src_port(packet_start_, srcPort) < 0) {
+ if (hicn_packet_set_src_port(format_, packet_start_, srcPort) < 0) {
throw errors::RuntimeException("Error setting source port in the packet.");
}
@@ -471,7 +579,7 @@ Packet &Packet::setSrcPort(uint16_t srcPort) {
}
Packet &Packet::setDstPort(uint16_t dstPort) {
- if (hicn_packet_set_dst_port(packet_start_, dstPort) < 0) {
+ if (hicn_packet_set_dst_port(format_, packet_start_, dstPort) < 0) {
throw errors::RuntimeException(
"Error setting destination port in the packet.");
}
@@ -482,7 +590,7 @@ Packet &Packet::setDstPort(uint16_t dstPort) {
uint16_t Packet::getSrcPort() const {
uint16_t port = 0;
- if (hicn_packet_get_src_port(packet_start_, &port) < 0) {
+ if (hicn_packet_get_src_port(format_, packet_start_, &port) < 0) {
throw errors::RuntimeException("Error reading source port in the packet.");
}
@@ -492,7 +600,7 @@ uint16_t Packet::getSrcPort() const {
uint16_t Packet::getDstPort() const {
uint16_t port = 0;
- if (hicn_packet_get_dst_port(packet_start_, &port) < 0) {
+ if (hicn_packet_get_dst_port(format_, packet_start_, &port) < 0) {
throw errors::RuntimeException(
"Error reading destination port in the packet.");
}
@@ -517,37 +625,6 @@ uint8_t Packet::getTTL() const {
return hops;
}
-void Packet::separateHeaderPayload() {
- if (payload_head_) {
- return;
- }
-
- int signature_size = 0;
- if (_is_ah(format_)) {
- signature_size = (uint32_t)getSignatureSize();
- }
-
- auto header_size = getHeaderSizeFromFormat(format_, signature_size);
- auto payload_length = packet_->length() - header_size;
-
- packet_->trimEnd(packet_->length());
-
- auto payload = packet_->cloneOne();
- payload_head_ = payload.get();
- payload_head_->advance(header_size);
- payload_head_->append(payload_length);
- packet_->prependChain(std::move(payload));
- packet_->append(header_size);
-}
-
-void Packet::resetPayload() {
- if (packet_->isChained()) {
- packet_->separateChain(packet_->next(), packet_->prev());
- payload_head_ = nullptr;
- updateLength();
- }
-}
-
} // end namespace core
} // end namespace transport
diff --git a/libtransport/src/core/pending_interest.h b/libtransport/src/core/pending_interest.h
index aeff78ea2..ca6411ddf 100644
--- a/libtransport/src/core/pending_interest.h
+++ b/libtransport/src/core/pending_interest.h
@@ -21,7 +21,6 @@
#include <hicn/transport/core/name.h>
#include <hicn/transport/interfaces/portal.h>
#include <hicn/transport/portability/portability.h>
-
#include <utils/deadline_timer.h>
#include <asio/steady_timer.hpp>
@@ -34,24 +33,21 @@ class HicnForwarderInterface;
class VPPForwarderInterface;
class RawSocketInterface;
-template <typename ForwarderInt>
class Portal;
using OnContentObjectCallback = interface::Portal::OnContentObjectCallback;
using OnInterestTimeoutCallback = interface::Portal::OnInterestTimeoutCallback;
class PendingInterest {
- friend class Portal<HicnForwarderInterface>;
- friend class Portal<VPPForwarderInterface>;
- friend class Portal<RawSocketInterface>;
+ friend class Portal;
public:
using Ptr = utils::ObjectPool<PendingInterest>::Ptr;
- PendingInterest()
- : interest_(nullptr, nullptr),
- timer_(),
- on_content_object_callback_(),
- on_interest_timeout_callback_() {}
+ // PendingInterest()
+ // : interest_(nullptr, nullptr),
+ // timer_(),
+ // on_content_object_callback_(),
+ // on_interest_timeout_callback_() {}
PendingInterest(Interest::Ptr &&interest,
std::unique_ptr<asio::steady_timer> &&timer)
diff --git a/libtransport/src/core/portal.cc b/libtransport/src/core/portal.cc
new file mode 100644
index 000000000..33335e542
--- /dev/null
+++ b/libtransport/src/core/portal.cc
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <core/errors.h>
+#include <core/global_configuration.h>
+#include <core/portal.h>
+#include <hicn/transport/interfaces/global_conf_interface.h>
+#include <hicn/transport/portability/platform.h>
+#include <hicn/transport/utils/file.h>
+
+#include <libconfig.h++>
+
+using namespace transport::interface::global_config;
+
+namespace transport {
+namespace core {
+
+#ifdef ANDROID
+static const constexpr char default_module[] = "";
+#elif defined(MACINTOSH)
+static const constexpr char default_module[] = "hicnlight_module.dylib";
+#elif defined(LINUX)
+static const constexpr char default_module[] = "hicnlight_module.so";
+#elif defined(WINDOWS)
+static const constexpr char default_module[] = "hicnlight_module.lib";
+#endif
+
+IoModuleConfiguration Portal::conf_;
+std::string Portal::io_module_path_ = defaultIoModule();
+
+std::string Portal::defaultIoModule() {
+ using namespace std::placeholders;
+ GlobalConfiguration::getInstance().registerConfigurationParser(
+ io_module_section,
+ std::bind(&Portal::parseIoModuleConfiguration, _1, _2));
+ GlobalConfiguration::getInstance().registerConfigurationGetter(
+ io_module_section, std::bind(&Portal::getModuleConfiguration, _1, _2));
+ GlobalConfiguration::getInstance().registerConfigurationSetter(
+ io_module_section, std::bind(&Portal::setModuleConfiguration, _1, _2));
+
+ // return default
+ conf_.name = default_module;
+ return default_module;
+}
+
+void Portal::getModuleConfiguration(ConfigurationObject& object,
+ std::error_code& ec) {
+ assert(object.getKey() == io_module_section);
+
+ auto conf = dynamic_cast<const IoModuleConfiguration&>(object);
+ conf = conf_;
+ ec = std::error_code();
+}
+
+std::string getIoModulePath(const std::string& name,
+ const std::vector<std::string>& paths,
+ std::error_code& ec) {
+#ifdef LINUX
+ std::string extension = ".so";
+#elif defined(MACINTOSH)
+ std::string extension = ".dylib";
+#elif defined(WINDOWS)
+ std::string extension = ".lib";
+#else
+#error "Platform not supported.";
+#endif
+
+ std::string complete_path = name;
+
+ if (name.empty()) {
+ ec = make_error_code(core_error::configuration_parse_failed);
+ return "";
+ }
+
+ complete_path += extension;
+
+ for (auto& p : paths) {
+ if (p.at(0) != '/') {
+ TRANSPORT_LOGW("Path %s is not an absolute path. Ignoring it.",
+ p.c_str());
+ continue;
+ }
+
+ if (utils::File::exists(p + "/" + complete_path)) {
+ complete_path = p + "/" + complete_path;
+ break;
+ }
+ }
+
+ return complete_path;
+}
+
+void Portal::setModuleConfiguration(const ConfigurationObject& object,
+ std::error_code& ec) {
+ assert(object.getKey() == io_module_section);
+
+ const IoModuleConfiguration& conf =
+ dynamic_cast<const IoModuleConfiguration&>(object);
+ auto path = getIoModulePath(conf.name, conf.search_path, ec);
+ if (!ec) {
+ conf_ = conf;
+ io_module_path_ = path;
+ }
+}
+
+void Portal::parseIoModuleConfiguration(const libconfig::Setting& io_config,
+ std::error_code& ec) {
+ using namespace libconfig;
+ // path property: the list of paths where to look for the module.
+ std::vector<std::string> paths;
+ std::string name;
+
+ if (io_config.exists("path")) {
+ // get path where looking for modules
+ const Setting& path_list = io_config.lookup("path");
+ auto count = path_list.getLength();
+
+ for (int i = 0; i < count; i++) {
+ paths.emplace_back(path_list[i].c_str());
+ }
+ }
+
+ if (io_config.exists("name")) {
+ io_config.lookupValue("name", name);
+ } else {
+ ec = make_error_code(core_error::configuration_parse_failed);
+ return;
+ }
+
+ auto path = getIoModulePath(name, paths, ec);
+ if (!ec) {
+ conf_.name = name;
+ conf_.search_path = paths;
+ io_module_path_ = path;
+ }
+}
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/core/portal.h b/libtransport/src/core/portal.h
index 05715543a..59254cf7b 100644
--- a/libtransport/src/core/portal.h
+++ b/libtransport/src/core/portal.h
@@ -15,24 +15,19 @@
#pragma once
+#include <core/pending_interest.h>
#include <hicn/transport/config.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
+#include <hicn/transport/core/io_module.h>
#include <hicn/transport/core/name.h>
#include <hicn/transport/core/prefix.h>
#include <hicn/transport/errors/errors.h>
+#include <hicn/transport/interfaces/global_conf_interface.h>
#include <hicn/transport/interfaces/portal.h>
#include <hicn/transport/portability/portability.h>
-#include <hicn/transport/utils/log.h>
#include <hicn/transport/utils/fixed_block_allocator.h>
-
-#include <core/forwarder_interface.h>
-#include <core/pending_interest.h>
-#include <core/udp_socket_connector.h>
-
-#ifdef __vpp__
-#include <core/memif_connector.h>
-#endif
+#include <hicn/transport/utils/log.h>
#include <asio.hpp>
#include <asio/steady_timer.hpp>
@@ -41,17 +36,19 @@
#include <queue>
#include <unordered_map>
+namespace libconfig {
+class Setting;
+}
+
namespace transport {
namespace core {
namespace portal_details {
-static constexpr uint32_t pool_size = 2048;
+static constexpr uint32_t pit_size = 1024;
class HandlerMemory {
#ifdef __vpp__
- static constexpr std::size_t memory_size = 1024 * 1024;
-
public:
HandlerMemory() {}
@@ -59,12 +56,11 @@ class HandlerMemory {
HandlerMemory &operator=(const HandlerMemory &) = delete;
TRANSPORT_ALWAYS_INLINE void *allocate(std::size_t size) {
- return utils::FixedBlockAllocator<128, 4096>::getInstance()
- ->allocateBlock();
+ return utils::FixedBlockAllocator<128, 8192>::getInstance().allocateBlock();
}
TRANSPORT_ALWAYS_INLINE void deallocate(void *pointer) {
- utils::FixedBlockAllocator<128, 4096>::getInstance()->deallocateBlock(
+ utils::FixedBlockAllocator<128, 8192>::getInstance().deallocateBlock(
pointer);
}
#else
@@ -97,13 +93,13 @@ class HandlerAllocator {
HandlerAllocator(const HandlerAllocator<U> &other) noexcept
: memory_(other.memory_) {}
- TRANSPORT_ALWAYS_INLINE bool operator==(const HandlerAllocator &other) const
- noexcept {
+ TRANSPORT_ALWAYS_INLINE bool operator==(
+ const HandlerAllocator &other) const noexcept {
return &memory_ == &other.memory_;
}
- TRANSPORT_ALWAYS_INLINE bool operator!=(const HandlerAllocator &other) const
- noexcept {
+ TRANSPORT_ALWAYS_INLINE bool operator!=(
+ const HandlerAllocator &other) const noexcept {
return &memory_ != &other.memory_;
}
@@ -140,7 +136,7 @@ class CustomAllocatorHandler {
}
template <typename... Args>
- void operator()(Args &&... args) {
+ void operator()(Args &&...args) {
handler_(std::forward<Args>(args)...);
}
@@ -160,33 +156,16 @@ class Pool {
public:
Pool(asio::io_service &io_service) : io_service_(io_service) {
increasePendingInterestPool();
- increaseInterestPool();
- increaseContentObjectPool();
}
TRANSPORT_ALWAYS_INLINE void increasePendingInterestPool() {
// Create pool of pending interests to reuse
- for (uint32_t i = 0; i < pool_size; i++) {
+ for (uint32_t i = 0; i < pit_size; i++) {
pending_interests_pool_.add(new PendingInterest(
Interest::Ptr(nullptr),
std::make_unique<asio::steady_timer>(io_service_)));
}
}
-
- TRANSPORT_ALWAYS_INLINE void increaseInterestPool() {
- // Create pool of interests to reuse
- for (uint32_t i = 0; i < pool_size; i++) {
- interest_pool_.add(new Interest());
- }
- }
-
- TRANSPORT_ALWAYS_INLINE void increaseContentObjectPool() {
- // Create pool of content object to reuse
- for (uint32_t i = 0; i < pool_size; i++) {
- content_object_pool_.add(new ContentObject());
- }
- }
-
PendingInterest::Ptr getPendingInterest() {
auto res = pending_interests_pool_.get();
while (TRANSPORT_EXPECT_FALSE(!res.first)) {
@@ -197,35 +176,15 @@ class Pool {
return std::move(res.second);
}
- TRANSPORT_ALWAYS_INLINE ContentObject::Ptr getContentObject() {
- auto res = content_object_pool_.get();
- while (TRANSPORT_EXPECT_FALSE(!res.first)) {
- increaseContentObjectPool();
- res = content_object_pool_.get();
- }
-
- return std::move(res.second);
- }
-
- TRANSPORT_ALWAYS_INLINE Interest::Ptr getInterest() {
- auto res = interest_pool_.get();
- while (TRANSPORT_EXPECT_FALSE(!res.first)) {
- increaseInterestPool();
- res = interest_pool_.get();
- }
-
- return std::move(res.second);
- }
-
private:
utils::ObjectPool<PendingInterest> pending_interests_pool_;
- utils::ObjectPool<ContentObject> content_object_pool_;
- utils::ObjectPool<Interest> interest_pool_;
asio::io_service &io_service_;
};
} // namespace portal_details
+class PortalConfiguration;
+
using PendingInterestHashTable =
std::unordered_map<uint32_t, PendingInterest::Ptr>;
@@ -251,32 +210,32 @@ using interface::BindConfig;
* The portal class is not thread safe, appropriate locking is required by the
* users of this class.
*/
-template <typename ForwarderInt>
-class Portal {
- static_assert(
- std::is_base_of<ForwarderInterface<ForwarderInt,
- typename ForwarderInt::ConnectorType>,
- ForwarderInt>::value,
- "ForwarderInt must inherit from ForwarderInterface!");
+class Portal {
public:
using ConsumerCallback = interface::Portal::ConsumerCallback;
using ProducerCallback = interface::Portal::ProducerCallback;
+ friend class PortalConfiguration;
+
Portal() : Portal(internal_io_service_) {}
Portal(asio::io_service &io_service)
- : io_service_(io_service),
+ : io_module_(nullptr, [](IoModule *module) { IoModule::unload(module); }),
+ io_service_(io_service),
packet_pool_(io_service),
app_name_("libtransport_application"),
consumer_callback_(nullptr),
producer_callback_(nullptr),
- connector_(std::bind(&Portal::processIncomingMessages, this,
- std::placeholders::_1),
- std::bind(&Portal::setLocalRoutes, this), io_service_,
- app_name_),
- forwarder_interface_(connector_) {}
-
+ is_consumer_(false) {
+ /**
+ * This workaroung allows to initialize memory for packet buffers *before*
+ * any static variables that may be initialized in the io_modules. In this
+ * way static variables in modules will be destroyed before the packet
+ * memory.
+ */
+ PacketManager<>::getInstance();
+ }
/**
* Set the consumer callback.
*
@@ -305,7 +264,7 @@ class Portal {
*/
TRANSPORT_ALWAYS_INLINE void setOutputInterface(
const std::string &output_interface) {
- forwarder_interface_.setOutputInterface(output_interface);
+ io_module_->setOutputInterface(output_interface);
}
/**
@@ -315,8 +274,19 @@ class Portal {
* is a consumer or a producer.
*/
TRANSPORT_ALWAYS_INLINE void connect(bool is_consumer = true) {
- pending_interest_hash_table_.reserve(portal_details::pool_size);
- forwarder_interface_.connect(is_consumer);
+ if (!io_module_) {
+ pending_interest_hash_table_.reserve(portal_details::pit_size);
+ io_module_.reset(IoModule::load(io_module_path_.c_str()));
+ assert(io_module_);
+
+ io_module_->init(std::bind(&Portal::processIncomingMessages, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3),
+ std::bind(&Portal::setLocalRoutes, this), io_service_,
+ app_name_);
+ io_module_->connect(is_consumer);
+ is_consumer_ = is_consumer;
+ }
}
/**
@@ -325,13 +295,19 @@ class Portal {
~Portal() { killConnection(); }
/**
+ * Compute name hash
+ */
+ TRANSPORT_ALWAYS_INLINE uint32_t getHash(const Name &name) {
+ return name.getHash32() + name.getSuffix();
+ }
+
+ /**
* Check if there is already a pending interest for a given name.
*
* @param name - The interest name.
*/
TRANSPORT_ALWAYS_INLINE bool interestIsPending(const Name &name) {
- auto it =
- pending_interest_hash_table_.find(name.getHash32() + name.getSuffix());
+ auto it = pending_interest_hash_table_.find(getHash(name));
if (it != pending_interest_hash_table_.end()) {
return true;
}
@@ -358,31 +334,46 @@ class Portal {
OnContentObjectCallback &&on_content_object_callback = UNSET_CALLBACK,
OnInterestTimeoutCallback &&on_interest_timeout_callback =
UNSET_CALLBACK) {
- uint32_t hash =
- interest->getName().getHash32() + interest->getName().getSuffix();
// Send it
- forwarder_interface_.send(*interest);
-
- auto pending_interest = packet_pool_.getPendingInterest();
- pending_interest->setInterest(std::move(interest));
- pending_interest->setOnContentObjectCallback(
- std::move(on_content_object_callback));
- pending_interest->setOnTimeoutCallback(
- std::move(on_interest_timeout_callback));
- pending_interest->startCountdown(portal_details::makeCustomAllocatorHandler(
- async_callback_memory_, std::bind(&Portal<ForwarderInt>::timerHandler,
- this, std::placeholders::_1, hash)));
+ interest->encodeSuffixes();
+ io_module_->send(*interest);
+
+ uint32_t initial_hash = interest->getName().getHash32();
+ auto hash = initial_hash + interest->getName().getSuffix();
+ uint32_t *suffix = interest->firstSuffix();
+ auto n_suffixes = interest->numberOfSuffixes();
+ uint32_t counter = 0;
+ // Set timers
+ do {
+ auto pending_interest = packet_pool_.getPendingInterest();
+ pending_interest->setInterest(std::move(interest));
+ pending_interest->setOnContentObjectCallback(
+ std::move(on_content_object_callback));
+ pending_interest->setOnTimeoutCallback(
+ std::move(on_interest_timeout_callback));
+
+ pending_interest->startCountdown(
+ portal_details::makeCustomAllocatorHandler(
+ async_callback_memory_, std::bind(&Portal::timerHandler, this,
+ std::placeholders::_1, hash)));
+
+ auto it = pending_interest_hash_table_.find(hash);
+ if (it != pending_interest_hash_table_.end()) {
+ it->second->cancelTimer();
- auto it = pending_interest_hash_table_.find(hash);
- if (it != pending_interest_hash_table_.end()) {
- it->second->cancelTimer();
+ // Get reference to interest packet in order to have it destroyed.
+ auto _int = it->second->getInterest();
+ it->second = std::move(pending_interest);
+ } else {
+ pending_interest_hash_table_[hash] = std::move(pending_interest);
+ }
- // Get reference to interest packet in order to have it destroyed.
- auto _int = it->second->getInterest();
- it->second = std::move(pending_interest);
- } else {
- pending_interest_hash_table_[hash] = std::move(pending_interest);
- }
+ if (suffix) {
+ hash = initial_hash + *suffix;
+ suffix++;
+ }
+
+ } while (counter++ < n_suffixes);
}
/**
@@ -424,9 +415,9 @@ class Portal {
* @param config - The configuration for the local forwarder binding.
*/
TRANSPORT_ALWAYS_INLINE void bind(const BindConfig &config) {
- forwarder_interface_.setContentStoreSize(config.csReserved());
+ assert(io_module_);
+ io_module_->setContentStoreSize(config.csReserved());
served_namespaces_.push_back(config.prefix());
-
setLocalRoutes();
}
@@ -461,7 +452,7 @@ class Portal {
*/
TRANSPORT_ALWAYS_INLINE void sendContentObject(
ContentObject &content_object) {
- forwarder_interface_.send(content_object);
+ io_module_->send(content_object);
}
/**
@@ -483,7 +474,7 @@ class Portal {
* Disconnect the transport from the local forwarder.
*/
TRANSPORT_ALWAYS_INLINE void killConnection() {
- forwarder_interface_.closeConnection();
+ io_module_->closeConnection();
}
/**
@@ -498,6 +489,17 @@ class Portal {
}
/**
+ * Remove one pending interest.
+ */
+ TRANSPORT_ALWAYS_INLINE void clearOne(const Name &name) {
+ if (!io_service_.stopped()) {
+ io_service_.dispatch(std::bind(&Portal::doClearOne, this, name));
+ } else {
+ doClearOne(name);
+ }
+ }
+
+ /**
* Get a reference to the io_service object.
*/
TRANSPORT_ALWAYS_INLINE asio::io_service &getIoService() {
@@ -509,8 +511,8 @@ class Portal {
*/
TRANSPORT_ALWAYS_INLINE void registerRoute(Prefix &prefix) {
served_namespaces_.push_back(prefix);
- if (connector_.isConnected()) {
- forwarder_interface_.registerRoute(prefix);
+ if (io_module_->isConnected()) {
+ io_module_->registerRoute(prefix);
}
}
@@ -531,35 +533,49 @@ class Portal {
}
/**
+ * Remove one pending interest.
+ */
+ TRANSPORT_ALWAYS_INLINE void doClearOne(const Name &name) {
+ auto it = pending_interest_hash_table_.find(getHash(name));
+
+ if (it != pending_interest_hash_table_.end()) {
+ it->second->cancelTimer();
+
+ // Get interest packet from pending interest and do nothing with it. It
+ // will get destroyed as it goes out of scope.
+ auto _int = it->second->getInterest();
+
+ pending_interest_hash_table_.erase(it);
+ }
+ }
+
+ /**
* Callback called by the underlying connector upon reception of a packet from
* the local forwarder.
*
* @param packet_buffer - The bytes of the packet.
*/
TRANSPORT_ALWAYS_INLINE void processIncomingMessages(
- Packet::MemBufPtr &&packet_buffer) {
+ Connector *c, utils::MemBuf &buffer, const std::error_code &ec) {
bool is_stopped = io_service_.stopped();
if (TRANSPORT_EXPECT_FALSE(is_stopped)) {
return;
}
- if (TRANSPORT_EXPECT_FALSE(
- ForwarderInt::isControlMessage(packet_buffer->data()))) {
- processControlMessage(std::move(packet_buffer));
+ if (TRANSPORT_EXPECT_FALSE(io_module_->isControlMessage(buffer.data()))) {
+ processControlMessage(buffer);
return;
}
- Packet::Format format = Packet::getFormatFromBuffer(packet_buffer->data());
+ // The buffer is a base class for an interest or a content object
+ Packet &packet_buffer = static_cast<Packet &>(buffer);
+ auto format = packet_buffer.getFormat();
if (TRANSPORT_EXPECT_TRUE(_is_tcp(format))) {
- if (!Packet::isInterest(packet_buffer->data())) {
- auto content_object = packet_pool_.getContentObject();
- content_object->replace(std::move(packet_buffer));
- processContentObject(std::move(content_object));
+ if (is_consumer_) {
+ processContentObject(static_cast<ContentObject &>(packet_buffer));
} else {
- auto interest = packet_pool_.getInterest();
- interest->replace(std::move(packet_buffer));
- processInterest(std::move(interest));
+ processInterest(static_cast<Interest &>(packet_buffer));
}
} else {
TRANSPORT_LOGE("Received not supported packet. Ignoring it.");
@@ -573,16 +589,16 @@ class Portal {
*/
TRANSPORT_ALWAYS_INLINE void setLocalRoutes() {
for (auto &prefix : served_namespaces_) {
- if (connector_.isConnected()) {
- forwarder_interface_.registerRoute(prefix);
+ if (io_module_->isConnected()) {
+ io_module_->registerRoute(prefix);
}
}
}
- TRANSPORT_ALWAYS_INLINE void processInterest(Interest::Ptr &&interest) {
+ TRANSPORT_ALWAYS_INLINE void processInterest(Interest &interest) {
// Interest for a producer
if (TRANSPORT_EXPECT_TRUE(producer_callback_ != nullptr)) {
- producer_callback_->onInterest(std::move(interest));
+ producer_callback_->onInterest(interest);
}
}
@@ -595,24 +611,27 @@ class Portal {
* @param content_object - The data packet
*/
TRANSPORT_ALWAYS_INLINE void processContentObject(
- ContentObject::Ptr &&content_object) {
- uint32_t hash = content_object->getName().getHash32() +
- content_object->getName().getSuffix();
+ ContentObject &content_object) {
+ TRANSPORT_LOGD("processContentObject %s",
+ content_object.getName().toString().c_str());
+ uint32_t hash = getHash(content_object.getName());
auto it = pending_interest_hash_table_.find(hash);
if (it != pending_interest_hash_table_.end()) {
+ TRANSPORT_LOGD("Found pending interest.");
+
PendingInterest::Ptr interest_ptr = std::move(it->second);
pending_interest_hash_table_.erase(it);
interest_ptr->cancelTimer();
auto _int = interest_ptr->getInterest();
if (interest_ptr->getOnDataCallback() != UNSET_CALLBACK) {
- interest_ptr->on_content_object_callback_(std::move(_int),
- std::move(content_object));
+ interest_ptr->on_content_object_callback_(*_int, content_object);
} else if (consumer_callback_) {
- consumer_callback_->onContentObject(std::move(_int),
- std::move(content_object));
+ consumer_callback_->onContentObject(*_int, content_object);
}
+ } else {
+ TRANSPORT_LOGD("No interest pending for received content object.");
}
}
@@ -622,12 +641,13 @@ class Portal {
* them.
*/
TRANSPORT_ALWAYS_INLINE void processControlMessage(
- Packet::MemBufPtr &&packet_buffer) {
- forwarder_interface_.processControlMessageReply(std::move(packet_buffer));
+ utils::MemBuf &packet_buffer) {
+ io_module_->processControlMessageReply(packet_buffer);
}
private:
portal_details::HandlerMemory async_callback_memory_;
+ std::unique_ptr<IoModule, void (*)(IoModule *)> io_module_;
asio::io_service &io_service_;
asio::io_service internal_io_service_;
@@ -641,8 +661,19 @@ class Portal {
ConsumerCallback *consumer_callback_;
ProducerCallback *producer_callback_;
- typename ForwarderInt::ConnectorType connector_;
- ForwarderInt forwarder_interface_;
+ bool is_consumer_;
+
+ private:
+ static std::string defaultIoModule();
+ static void parseIoModuleConfiguration(const libconfig::Setting &io_config,
+ std::error_code &ec);
+ static void getModuleConfiguration(
+ interface::global_config::ConfigurationObject &conf, std::error_code &ec);
+ static void setModuleConfiguration(
+ const interface::global_config::ConfigurationObject &conf,
+ std::error_code &ec);
+ static interface::global_config::IoModuleConfiguration conf_;
+ static std::string io_module_path_;
};
} // namespace core
diff --git a/libtransport/src/core/prefix.cc b/libtransport/src/core/prefix.cc
index 30f780461..d598cff75 100644
--- a/libtransport/src/core/prefix.cc
+++ b/libtransport/src/core/prefix.cc
@@ -25,12 +25,12 @@ extern "C" {
#include <hicn/transport/portability/win_portability.h>
#endif
+#include <openssl/rand.h>
+
#include <cstring>
#include <memory>
#include <random>
-#include <openssl/rand.h>
-
namespace transport {
namespace core {
@@ -69,7 +69,7 @@ Prefix::Prefix(const core::Name &content_name, uint16_t prefix_length) {
}
ip_prefix_ = content_name.toIpAddress();
- ip_prefix_.len = prefix_length;
+ ip_prefix_.len = (u8)prefix_length;
ip_prefix_.family = family;
}
@@ -95,11 +95,11 @@ void Prefix::buildPrefix(std::string &prefix, uint16_t prefix_length,
throw errors::InvalidIpAddressException();
}
- ip_prefix_.len = prefix_length;
+ ip_prefix_.len = (u8)prefix_length;
ip_prefix_.family = family;
}
-std::unique_ptr<Sockaddr> Prefix::toSockaddr() {
+std::unique_ptr<Sockaddr> Prefix::toSockaddr() const {
Sockaddr *ret = nullptr;
switch (ip_prefix_.family) {
@@ -120,14 +120,14 @@ std::unique_ptr<Sockaddr> Prefix::toSockaddr() {
return std::unique_ptr<Sockaddr>(ret);
}
-uint16_t Prefix::getPrefixLength() { return ip_prefix_.len; }
+uint16_t Prefix::getPrefixLength() const { return ip_prefix_.len; }
Prefix &Prefix::setPrefixLength(uint16_t prefix_length) {
- ip_prefix_.len = prefix_length;
+ ip_prefix_.len = (u8)prefix_length;
return *this;
}
-int Prefix::getAddressFamily() { return ip_prefix_.family; }
+int Prefix::getAddressFamily() const { return ip_prefix_.family; }
Prefix &Prefix::setAddressFamily(int address_family) {
ip_prefix_.family = address_family;
@@ -211,8 +211,8 @@ Name Prefix::getName(const core::Name &mask, const core::Name &components,
}
}
- if (this->contains(name_ip))
- throw errors::RuntimeException("Mask overrides the prefix");
+ // if (this->contains(name_ip))
+ // throw errors::RuntimeException("Mask overrides the prefix");
return Name(ip_prefix_.family, (uint8_t *)&name_ip);
}
@@ -226,9 +226,9 @@ Name Prefix::getRandomName() const {
ip_prefix_.len;
size_t size = (size_t)ceil((float)addr_len / 8.0);
- uint8_t *buffer = (uint8_t *) malloc(sizeof(uint8_t) * size);
+ uint8_t *buffer = (uint8_t *)malloc(sizeof(uint8_t) * size);
- RAND_bytes(buffer, size);
+ RAND_bytes(buffer, (int)size);
int j = 0;
for (uint8_t i = (uint8_t)ceil((float)ip_prefix_.len / 8.0);
@@ -332,7 +332,7 @@ bool Prefix::checkPrefixLengthAndAddressFamily(uint16_t prefix_length,
return true;
}
-ip_prefix_t &Prefix::toIpPrefixStruct() { return ip_prefix_; }
+const ip_prefix_t &Prefix::toIpPrefixStruct() const { return ip_prefix_; }
} // namespace core
diff --git a/libtransport/src/core/rs.cc b/libtransport/src/core/rs.cc
new file mode 100644
index 000000000..33270736d
--- /dev/null
+++ b/libtransport/src/core/rs.cc
@@ -0,0 +1,370 @@
+
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <core/fec.h>
+#include <core/rs.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/utils/log.h>
+
+#include <cassert>
+
+namespace transport {
+namespace core {
+namespace fec {
+
+BlockCode::BlockCode(uint32_t k, uint32_t n, struct fec_parms *code)
+ : Packets(),
+ k_(k),
+ n_(n),
+ code_(code),
+ max_buffer_size_(0),
+ current_block_size_(0),
+ to_decode_(false) {
+ sorted_index_.reserve(n);
+}
+
+bool BlockCode::addRepairSymbol(const fec::buffer &packet, uint32_t i) {
+ // Get index
+ to_decode_ = true;
+ TRANSPORT_LOGD("adding symbol of size %zu", packet->length());
+ return addSymbol(packet, i, packet->length() - sizeof(fec_header));
+}
+
+bool BlockCode::addSourceSymbol(const fec::buffer &packet, uint32_t i) {
+ return addSymbol(packet, i, packet->length());
+}
+
+bool BlockCode::addSymbol(const fec::buffer &packet, uint32_t i,
+ std::size_t size) {
+ if (size > max_buffer_size_) {
+ max_buffer_size_ = size;
+ }
+
+ operator[](current_block_size_++) = std::make_pair(i, packet);
+
+ if (current_block_size_ >= k_) {
+ if (to_decode_) {
+ decode();
+ } else {
+ encode();
+ }
+
+ clear();
+ return false;
+ }
+
+ return true;
+}
+
+void BlockCode::encode() {
+ gf **data = new gf*[k_];
+ uint32_t *old_values = new uint32_t[k_];
+ uint32_t base = operator[](0).first;
+
+ // Set packet length in first 2 bytes
+ for (uint32_t i = 0; i < k_; i++) {
+ auto &packet = operator[](i).second;
+
+ TRANSPORT_LOGD("Current buffer size: %zu", packet->length());
+
+ auto ret = packet->ensureCapacityAndFillUnused(max_buffer_size_, 0);
+ if (TRANSPORT_EXPECT_FALSE(ret == false)) {
+ throw errors::RuntimeException(
+ "Provided packet is not suitable to be used as FEC source packet. "
+ "Aborting.");
+ }
+
+ // Buffers should hold 2 bytes before the starting pointer, in order to be
+ // able to set the length for the encoding operation
+ packet->prepend(2);
+ uint16_t *length = reinterpret_cast<uint16_t *>(packet->writableData());
+
+ old_values[i] = *length;
+ *length = htons(u_short(packet->length() - LEN_SIZE_BYTES));
+
+ data[i] = packet->writableData();
+
+ }
+
+ // Finish to fill source block with the buffers to hold the repair symbols
+ for (uint32_t i = k_; i < n_; i++) {
+ // For the moment we get a packet from the pool here.. later we'll need to
+ // require a packet from the caller with a callback.
+ auto packet = PacketManager<>::getInstance().getMemBuf();
+ packet->append(max_buffer_size_ + sizeof(fec_header) + LEN_SIZE_BYTES);
+ fec_header *fh = reinterpret_cast<fec_header *>(packet->writableData());
+
+ fh->setSeqNumberBase(base);
+ fh->setNFecSymbols(n_ - k_);
+ fh->setEncodedSymbolId(i);
+ fh->setSourceBlockLen(n_);
+
+ packet->trimStart(sizeof(fec_header));
+
+ data[i] = packet->writableData();
+ operator[](i) = std::make_pair(i, std::move(packet));
+ }
+
+ // Generate repair symbols and put them in corresponding buffers
+ TRANSPORT_LOGD("Calling encode with max_buffer_size_ = %zu",
+ max_buffer_size_);
+ for (uint32_t i = k_; i < n_; i++) {
+ fec_encode(code_, data, data[i], i, (int)(max_buffer_size_ + LEN_SIZE_BYTES));
+ }
+
+ // Restore original content of buffer space used to store the length
+ for (uint32_t i = 0; i < k_; i++) {
+ auto &packet = operator[](i).second;
+ uint16_t *length = reinterpret_cast<uint16_t *>(packet->writableData());
+ *length = old_values[i];
+ packet->trimStart(2);
+ }
+
+ // Re-include header in repair packets
+ for (uint32_t i = k_; i < n_; i++) {
+ auto &packet = operator[](i).second;
+ TRANSPORT_LOGD("Produced repair symbol of size = %zu", packet->length());
+ packet->prepend(sizeof(fec_header));
+ }
+ delete [] data;
+ delete [] old_values;
+}
+
+void BlockCode::decode() {
+ gf **data = new gf*[k_];
+ uint32_t *index = new uint32_t[k_];
+
+ for (uint32_t i = 0; i < k_; i++) {
+ auto &packet = operator[](i).second;
+ index[i] = operator[](i).first;
+ sorted_index_[i] = index[i];
+
+ if (index[i] < k_) {
+ TRANSPORT_LOGD("DECODE SOURCE - index %u - Current buffer size: %zu",
+ index[i], packet->length());
+ // This is a source packet. We need to prepend the length and fill
+ // additional space to 0
+
+ // Buffers should hold 2 bytes before the starting pointer, in order to be
+ // able to set the length for the encoding operation
+ packet->prepend(LEN_SIZE_BYTES);
+ packet->ensureCapacityAndFillUnused(max_buffer_size_, 0);
+ uint16_t *length = reinterpret_cast<uint16_t *>(packet->writableData());
+
+ *length = htons(u_short(packet->length() - LEN_SIZE_BYTES));
+ } else {
+ TRANSPORT_LOGD("DECODE SYMBOL - index %u - Current buffer size: %zu",
+ index[i], packet->length());
+ packet->trimStart(sizeof(fec_header));
+ }
+
+ data[i] = packet->writableData();
+ delete [] data;
+ delete [] index;
+ }
+
+ // We decode the source block
+ TRANSPORT_LOGD("Calling decode with max_buffer_size_ = %zu",
+ max_buffer_size_);
+ fec_decode(code_, data, reinterpret_cast<int *>(index), (int)max_buffer_size_);
+
+ // Find the index in the block for recovered packets
+ for (uint32_t i = 0; i < k_; i++) {
+ if (index[i] != i) {
+ for (uint32_t j = 0; j < k_; j++)
+ if (sorted_index_[j] == uint32_t(index[i])) {
+ sorted_index_[j] = i;
+ }
+ }
+ }
+
+ // Reorder block by index with in-place sorting
+ for (uint32_t i = 0; i < k_; i++) {
+ for (uint32_t j = sorted_index_[i]; j != i; j = sorted_index_[i]) {
+ std::swap(sorted_index_[j], sorted_index_[i]);
+ std::swap(operator[](j), operator[](i));
+ }
+ }
+
+ // Adjust length according to the one written in the source packet
+ for (uint32_t i = 0; i < k_; i++) {
+ auto &packet = operator[](i).second;
+ uint16_t *length = reinterpret_cast<uint16_t *>(packet->writableData());
+ packet->trimStart(2);
+ packet->setLength(ntohs(*length));
+ }
+}
+
+void BlockCode::clear() {
+ current_block_size_ = 0;
+ max_buffer_size_ = 0;
+ sorted_index_.clear();
+ to_decode_ = false;
+}
+
+void rs::MatrixDeleter::operator()(struct fec_parms *params) {
+ fec_free(params);
+}
+
+rs::Codes rs::createCodes() {
+ Codes ret;
+
+ ret.emplace(std::make_pair(1, 3), Matrix(fec_new(1, 3), MatrixDeleter()));
+ ret.emplace(std::make_pair(6, 10), Matrix(fec_new(6, 10), MatrixDeleter()));
+ ret.emplace(std::make_pair(8, 32), Matrix(fec_new(8, 32), MatrixDeleter()));
+ ret.emplace(std::make_pair(10, 30), Matrix(fec_new(10, 30), MatrixDeleter()));
+ ret.emplace(std::make_pair(16, 24), Matrix(fec_new(16, 24), MatrixDeleter()));
+ ret.emplace(std::make_pair(10, 40), Matrix(fec_new(10, 40), MatrixDeleter()));
+ ret.emplace(std::make_pair(10, 60), Matrix(fec_new(10, 60), MatrixDeleter()));
+ ret.emplace(std::make_pair(10, 90), Matrix(fec_new(10, 90), MatrixDeleter()));
+
+ return ret;
+}
+
+rs::Codes rs::codes_ = createCodes();
+
+rs::rs(uint32_t k, uint32_t n) : k_(k), n_(n) {}
+
+void rs::setFECCallback(const PacketsReady &callback) {
+ fec_callback_ = callback;
+}
+
+encoder::encoder(uint32_t k, uint32_t n)
+ : rs(k, n),
+ current_code_(codes_[std::make_pair(k, n)].get()),
+ source_block_(k_, n_, current_code_) {}
+
+void encoder::consume(const fec::buffer &packet, uint32_t index) {
+ if (!source_block_.addSourceSymbol(packet, index)) {
+ std::vector<buffer> repair_packets;
+ for (uint32_t i = k_; i < n_; i++) {
+ repair_packets.emplace_back(std::move(source_block_[i].second));
+ }
+ fec_callback_(repair_packets);
+ }
+}
+
+decoder::decoder(uint32_t k, uint32_t n) : rs(k, n) {}
+
+void decoder::recoverPackets(SourceBlocks::iterator &src_block_it) {
+ TRANSPORT_LOGD("recoverPackets for %u", k_);
+ auto &src_block = src_block_it->second;
+ std::vector<buffer> source_packets(k_);
+ for (uint32_t i = 0; i < src_block.getK(); i++) {
+ source_packets[i] = std::move(src_block[i].second);
+ }
+
+ fec_callback_(source_packets);
+ processed_source_blocks_.emplace(src_block_it->first);
+
+ auto it = parked_packets_.find(src_block_it->first);
+ if (it != parked_packets_.end()) {
+ parked_packets_.erase(it);
+ }
+
+ src_blocks_.erase(src_block_it);
+}
+
+void decoder::consume(const fec::buffer &packet, uint32_t index) {
+ // Normalize index
+ auto i = index % n_;
+
+ // Get base
+ uint32_t base = index - i;
+
+ TRANSPORT_LOGD(
+ "Decoder consume called for source symbol. BASE = %u, index = %u and i = "
+ "%u",
+ base, index, i);
+
+ // check if a source block already exist for this symbol. If it does not
+ // exist, we lazily park this packet until we receive a repair symbol for the
+ // same block. This is done for 2 reason:
+ // 1) If we receive all the source packets of a block, we do not need to
+ // recover anything.
+ // 2) Sender may change n and k at any moment, so we construct the source
+ // block based on the (n, k) values written in the fec header. This is
+ // actually not used right now, since we use fixed value of n and k passed
+ // at construction time, but it paves the ground for a more dynamic
+ // protocol that may come in the future.
+ auto it = src_blocks_.find(base);
+ if (it != src_blocks_.end()) {
+ auto ret = it->second.addSourceSymbol(packet, i);
+ if (!ret) {
+ recoverPackets(it);
+ }
+ } else {
+ TRANSPORT_LOGD("Adding to parked source packets");
+ auto ret = parked_packets_.emplace(
+ base, std::vector<std::pair<buffer, uint32_t> >());
+ ret.first->second.emplace_back(packet, i);
+ }
+}
+
+void decoder::consume(const fec::buffer &packet) {
+ // Repair symbol! Get index and base source block.
+ fec_header *h = reinterpret_cast<fec_header *>(packet->writableData());
+ auto i = h->getEncodedSymbolId();
+ auto base = h->getSeqNumberBase();
+ auto n = h->getSourceBlockLen();
+ auto k = n - h->getNFecSymbols();
+
+ TRANSPORT_LOGD(
+ "Decoder consume called for repair symbol. BASE = %u, index = %u and i = "
+ "%u",
+ base, base + i, i);
+
+ // check if a source block already exist for this symbol
+ auto it = src_blocks_.find(base);
+ if (it == src_blocks_.end()) {
+ // Create new source block
+ auto code_it = codes_.find(std::make_pair(k, n));
+ if (code_it == codes_.end()) {
+ TRANSPORT_LOGE("Code for k = %u and n = %u does not exist.", k_, n_);
+ return;
+ }
+
+ auto emplace_result =
+ src_blocks_.emplace(base, BlockCode(k, n, code_it->second.get()));
+ it = emplace_result.first;
+
+ // Check in the parked packets and insert any packet that is part of this
+ // source block
+
+ auto it2 = parked_packets_.find(base);
+ if (it2 != parked_packets_.end()) {
+ for (auto &packet_index : it2->second) {
+ auto ret =
+ it->second.addSourceSymbol(packet_index.first, packet_index.second);
+ if (!ret) {
+ recoverPackets(it);
+ // Finish to delete packets in same source block that were
+ // eventually not used
+ return;
+ }
+ }
+ }
+ }
+
+ auto ret = it->second.addRepairSymbol(packet, i);
+ if (!ret) {
+ recoverPackets(it);
+ }
+}
+
+} // namespace fec
+} // namespace core
+} // namespace transport
diff --git a/libtransport/src/core/rs.h b/libtransport/src/core/rs.h
new file mode 100644
index 000000000..9a8c43e4d
--- /dev/null
+++ b/libtransport/src/core/rs.h
@@ -0,0 +1,340 @@
+
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#endif
+#include <hicn/transport/utils/membuf.h>
+#include <protocols/fec_base.h>
+
+#include <array>
+#include <cstdint>
+#include <map>
+#include <unordered_set>
+#include <vector>
+
+namespace transport {
+namespace core {
+
+namespace fec {
+
+static const constexpr uint16_t MAX_SOURCE_BLOCK_SIZE = 128;
+
+using buffer = typename utils::MemBuf::Ptr;
+/**
+ * We use a std::array in place of std::vector to avoid to allocate a new vector
+ * in the heap every time we build a new source block, which would be bad if
+ * the decoder has to allocate several source blocks for many concurrent bases.
+ * std::array allows to be constructed in place, saving the allocation at the
+ * price os knowing in advance its size.
+ */
+using Packets = std::array<std::pair<uint32_t, buffer>, MAX_SOURCE_BLOCK_SIZE>;
+
+/**
+ * FEC Header, prepended to symbol packets.
+ */
+struct fec_header {
+ /**
+ * The base source packet seq_number this FES symbol refers to
+ */
+ uint32_t seq_number;
+
+ /**
+ * The index of the symbol inside the source block, between k and n - 1
+ */
+ uint8_t encoded_symbol_id;
+
+ /**
+ * Total length of source block (n)
+ */
+ uint8_t source_block_len;
+
+ /**
+ * Total number of symbols (n - k)
+ */
+ uint8_t n_fec_symbols;
+
+ /**
+ * Align header to 64 bits
+ */
+ uint8_t padding;
+
+ void setSeqNumberBase(uint32_t suffix) { seq_number = htonl(suffix); }
+ uint32_t getSeqNumberBase() { return ntohl(seq_number); }
+ void setEncodedSymbolId(uint8_t esi) { encoded_symbol_id = esi; }
+ uint8_t getEncodedSymbolId() { return encoded_symbol_id; }
+ void setSourceBlockLen(uint8_t k) { source_block_len = k; }
+ uint8_t getSourceBlockLen() { return source_block_len; }
+ void setNFecSymbols(uint8_t n_r) { n_fec_symbols = n_r; }
+ uint8_t getNFecSymbols() { return n_fec_symbols; }
+};
+
+/**
+ * This class models the source block itself.
+ */
+class BlockCode : public Packets {
+ /**
+ * For variable length packet we need to prepend to the padded payload the
+ * real length of the packet. This is *not* sent over the network.
+ */
+ static constexpr std::size_t LEN_SIZE_BYTES = 2;
+
+ public:
+ BlockCode(uint32_t k, uint32_t n, struct fec_parms *code);
+
+ /**
+ * Add a repair symbol to the dource block.
+ */
+ bool addRepairSymbol(const fec::buffer &packet, uint32_t i);
+
+ /**
+ * Add a source symbol to the source block.
+ */
+ bool addSourceSymbol(const fec::buffer &packet, uint32_t i);
+
+ /**
+ * Get current length of source block.
+ */
+ std::size_t length() { return current_block_size_; }
+
+ /**
+ * Get N
+ */
+ uint32_t getN() { return n_; }
+
+ /**
+ * Get K
+ */
+ uint32_t getK() { return k_; }
+
+ /**
+ * Clear source block
+ */
+ void clear();
+
+ private:
+ /**
+ * Add symbol to source block
+ **/
+ bool addSymbol(const fec::buffer &packet, uint32_t i, std::size_t size);
+
+ /**
+ * Starting from k source symbols, get the n - k repair symbols
+ */
+ void encode();
+
+ /**
+ * Starting from k symbols (mixed repair and source), get k source symbols.
+ * NOTE: It does not make sense to retrieve the k source symbols using the
+ * very same k source symbols. With the current implementation that case can
+ * never happen.
+ */
+ void decode();
+
+ private:
+ uint32_t k_;
+ uint32_t n_;
+ struct fec_parms *code_;
+ std::size_t max_buffer_size_;
+ std::size_t current_block_size_;
+ std::vector<uint32_t> sorted_index_;
+ bool to_decode_;
+};
+
+/**
+ * This class contains common parameters between the fec encoder and decoder.
+ * In particular it contains:
+ * - The callback to be called when symbols are encoded / decoded
+ * - The reference to the static reed-solomon parameters, allocated at program
+ * startup
+ * - N and K. Ideally they are useful only for the encoder (the decoder can
+ * retrieve them from the FEC header). However right now we assume sender and
+ * receiver agreed on the parameters k and n to use. We will introduce a control
+ * message later to negotiate them, so that decoder cah dynamically change them
+ * during the download.
+ */
+class rs {
+ /**
+ * Deleter for static preallocated reed-solomon parameters.
+ */
+ struct MatrixDeleter {
+ void operator()(struct fec_parms *params);
+ };
+
+ /**
+ * unique_ptr to reed-solomon parameters, with custom deleter to call fec_free
+ * at the end of the program
+ */
+ using Matrix = std::unique_ptr<struct fec_parms, MatrixDeleter>;
+
+ /**
+ * Key to retrieve static preallocated reed-solomon parameters. It is pair of
+ * k and n
+ */
+ using Code = std::pair<std::uint32_t /* k */, std::uint32_t /* n */>;
+
+ /**
+ * Custom hash function for (k, n) pair.
+ */
+ struct CodeHasher {
+ std::size_t operator()(const transport::core::fec::rs::Code &code) const {
+ uint64_t ret = uint64_t(code.first) << 32 | uint64_t(code.second);
+ return std::hash<uint64_t>{}(ret);
+ }
+ };
+
+ protected:
+ /**
+ * Callback to be called after the encode or the decode operations. In the
+ * former case it will contain the symbols, while in the latter the sources.
+ */
+ using PacketsReady = std::function<void(std::vector<buffer> &)>;
+
+ /**
+ * The sequence number base.
+ */
+ using SNBase = std::uint32_t;
+
+ /**
+ * The map of source blocks, used at the decoder side. For the encoding
+ * operation we can use one source block only, since packet are produced in
+ * order.
+ */
+ using SourceBlocks = std::unordered_map<SNBase, BlockCode>;
+
+ /**
+ * Map (k, n) -> reed-solomon parameter
+ */
+ using Codes = std::unordered_map<Code, Matrix, CodeHasher>;
+
+ public:
+ rs(uint32_t k, uint32_t n);
+ ~rs() = default;
+
+ /**
+ * Set callback to call after packet encoding / decoding
+ */
+ void setFECCallback(const PacketsReady &callback);
+
+ virtual void clear() { processed_source_blocks_.clear(); }
+
+ private:
+ /**
+ * Create reed-solomon codes at program startup.
+ */
+ static Codes createCodes();
+
+ protected:
+ bool processed(SNBase seq_base) {
+ return processed_source_blocks_.find(seq_base) !=
+ processed_source_blocks_.end();
+ }
+
+ std::uint32_t k_;
+ std::uint32_t n_;
+ PacketsReady fec_callback_;
+
+ /**
+ * Keep track of processed source blocks
+ */
+ std::unordered_set<SNBase> processed_source_blocks_;
+
+ static Codes codes_;
+};
+
+/**
+ * The reed-solomon encoder. It is feeded with source symbols and it provide
+ * repair-symbols through the fec_callback_
+ */
+class encoder : public rs {
+ public:
+ encoder(uint32_t k, uint32_t n);
+ /**
+ * Always consume source symbols.
+ */
+ void consume(const fec::buffer &packet, uint32_t index);
+
+ void clear() override {
+ rs::clear();
+ source_block_.clear();
+ }
+
+ private:
+ struct fec_parms *current_code_;
+ /**
+ * The source block. As soon as it is filled with k source symbols, the
+ * encoder calls the callback fec_callback_ and the resets the block 0, ready
+ * to accept another batch of k source symbols.
+ */
+ BlockCode source_block_;
+};
+
+/**
+ * The reed-solomon encoder. It is feeded with source/repair symbols and it
+ * provides the original source symbols through the fec_callback_
+ */
+class decoder : public rs {
+ public:
+ decoder(uint32_t k, uint32_t n);
+
+ /**
+ * Consume source symbol
+ */
+ void consume(const fec::buffer &packet, uint32_t i);
+
+ /**
+ * Consume repair symbol
+ */
+ void consume(const fec::buffer &packet);
+
+ /**
+ * Clear decoder to reuse
+ */
+ void clear() override {
+ rs::clear();
+ src_blocks_.clear();
+ parked_packets_.clear();
+ }
+
+ private:
+ void recoverPackets(SourceBlocks::iterator &src_block_it);
+
+ private:
+ /**
+ * Map of source blocks. We use a map because we may receive symbols belonging
+ * to diffreent source blocks at the same time, so we need to be able to
+ * decode many source symbols at the same time.
+ */
+ SourceBlocks src_blocks_;
+
+ /**
+ * Unordered Map of source symbols for which we did not receive any repair
+ * symbol in the same source block. Notably this happens when:
+ *
+ * - We receive the source symbols first and the repair symbols after
+ * - We received only source symbols for a given block. In that case it does
+ * not make any sense to build the source block, since we received all the
+ * source packet of the block.
+ */
+ std::unordered_map<uint32_t, std::vector<std::pair<buffer, uint32_t>>>
+ parked_packets_;
+};
+
+} // namespace fec
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/core/tcp_socket_connector.cc b/libtransport/src/core/tcp_socket_connector.cc
index 20b3d6ce6..fa029c6fc 100644
--- a/libtransport/src/core/tcp_socket_connector.cc
+++ b/libtransport/src/core/tcp_socket_connector.cc
@@ -33,6 +33,8 @@ namespace {
class NetworkMessage {
public:
static constexpr std::size_t fixed_header_length = 10;
+ static constexpr std::uint8_t ccnx_flag = 102;
+ static constexpr std::size_t ccnx_packet_length = 44;
static std::size_t decodeHeader(const uint8_t *packet) {
// General checks
@@ -40,11 +42,12 @@ class NetworkMessage {
uint8_t first_byte = packet[0];
uint8_t ip_format = (packet[0] & 0xf0) >> 4;
- if (TRANSPORT_EXPECT_FALSE(first_byte == 102)) {
+ if (TRANSPORT_EXPECT_FALSE(first_byte == ccnx_flag)) {
// Get packet length
- return 44;
+ return ccnx_packet_length;
} else if (TRANSPORT_EXPECT_TRUE(ip_format == 6 || ip_format == 4)) {
- Packet::Format format = Packet::getFormatFromBuffer(packet);
+ Packet::Format format =
+ Packet::getFormatFromBuffer(packet, fixed_header_length);
return Packet::getHeaderSizeFromBuffer(format, packet) +
Packet::getPayloadSizeFromBuffer(format, packet);
}
diff --git a/libtransport/src/core/tcp_socket_connector.h b/libtransport/src/core/tcp_socket_connector.h
index c57123e9f..9dbd250d1 100644
--- a/libtransport/src/core/tcp_socket_connector.h
+++ b/libtransport/src/core/tcp_socket_connector.h
@@ -15,12 +15,11 @@
#pragma once
+#include <core/connector.h>
#include <hicn/transport/config.h>
#include <hicn/transport/core/name.h>
#include <hicn/transport/utils/branch_prediction.h>
-#include <core/connector.h>
-
#include <asio.hpp>
#include <asio/steady_timer.hpp>
#include <deque>
diff --git a/libtransport/src/core/test/CMakeLists.txt b/libtransport/src/core/test/CMakeLists.txt
deleted file mode 100644
index 48c50e9b0..000000000
--- a/libtransport/src/core/test/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-# Enable gcov output for the tests
-add_definitions(--coverage)
-set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage")
-
-set(TestsExpectedToPass
- test_core_manifest)
-
-foreach(test ${TestsExpectedToPass})
- AddTest(${test})
-endforeach() \ No newline at end of file
diff --git a/libtransport/src/core/vpp_forwarder_interface.cc b/libtransport/src/core/vpp_forwarder_interface.cc
index 7b4298592..9f7beeb37 100644
--- a/libtransport/src/core/vpp_forwarder_interface.cc
+++ b/libtransport/src/core/vpp_forwarder_interface.cc
@@ -36,8 +36,6 @@ namespace transport {
namespace core {
-std::mutex VPPForwarderInterface::global_lock_;
-
VPPForwarderInterface::VPPForwarderInterface(MemifConnector &connector)
: ForwarderInterface<VPPForwarderInterface, MemifConnector>(connector),
sw_if_index_(~0),
@@ -112,9 +110,24 @@ void VPPForwarderInterface::producerConnection() {
}
void VPPForwarderInterface::connect(bool is_consumer) {
- std::lock_guard<std::mutex> connection_lock(global_lock_);
+ int retry = 20;
+
+ TRANSPORT_LOGI("Connecting to VPP through vapi.");
+ vapi_error_e ret = vapi_connect_safe(&sock_, 0);
+
+ while (ret != VAPI_OK && retry > 0) {
+ TRANSPORT_LOGE("Error connecting to VPP through vapi. Retrying..");
+ --retry;
+ ret = vapi_connect_safe(&sock_, 0);
+ }
+
+ if (ret != VAPI_OK) {
+ throw std::runtime_error(
+ "Impossible to connect to forwarder. Is VPP running?");
+ }
+
- vapi_connect_safe(&sock_, 0);
+ TRANSPORT_LOGI("Connected to VPP through vapi.");
sw_if_index_ = getMemifConfiguration();
@@ -167,7 +180,7 @@ void VPPForwarderInterface::registerRoute(Prefix &prefix) {
params.prefix->address = addr.address;
params.prefix->family = addr.family;
params.prefix->len = addr.len;
- params.face_id = face_id1_;
+ params.prod_addr = &producer_locator;
int ret = hicn_vapi_register_route(VPPForwarderInterface::sock_, &params);
diff --git a/libtransport/src/core/vpp_forwarder_interface.h b/libtransport/src/core/vpp_forwarder_interface.h
index eb759f8bc..31d23b40d 100644
--- a/libtransport/src/core/vpp_forwarder_interface.h
+++ b/libtransport/src/core/vpp_forwarder_interface.h
@@ -21,6 +21,7 @@
#include <hicn/transport/core/prefix.h>
+
#ifdef always_inline
#undef always_inline
#endif
@@ -78,7 +79,6 @@ class VPPForwarderInterface
uint32_t face_id2_;
bool is_consumer_;
vapi_ctx_t sock_;
- static std::mutex global_lock_;
};
} // namespace core
diff --git a/libtransport/src/http/client_connection.cc b/libtransport/src/http/client_connection.cc
index 7a3a636fe..a24a821e7 100644
--- a/libtransport/src/http/client_connection.cc
+++ b/libtransport/src/http/client_connection.cc
@@ -43,12 +43,6 @@ class HTTPClientConnection::Implementation
read_buffer_(nullptr),
response_(std::make_shared<HTTPResponse>()),
timer_(nullptr) {
- consumer_.setSocketOption(
- ConsumerCallbacksOptions::CONTENT_OBJECT_TO_VERIFY,
- (ConsumerContentObjectVerificationCallback)std::bind(
- &Implementation::verifyData, this, std::placeholders::_1,
- std::placeholders::_2));
-
consumer_.setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK, this);
consumer_.connect();
@@ -124,10 +118,10 @@ class HTTPClientConnection::Implementation
return *http_client_;
}
- HTTPClientConnection &setCertificate(const std::string &cert_path) {
- if (consumer_.setSocketOption(GeneralTransportOptions::CERTIFICATE,
- cert_path) == SOCKET_OPTION_NOT_SET) {
- throw errors::RuntimeException("Error setting the certificate.");
+ HTTPClientConnection &setVerifier(std::shared_ptr<auth::Verifier> verifier) {
+ if (consumer_.setSocketOption(GeneralTransportOptions::VERIFIER,
+ verifier) == SOCKET_OPTION_NOT_SET) {
+ throw errors::RuntimeException("Error setting the verifier.");
}
return *http_client_;
@@ -177,17 +171,6 @@ class HTTPClientConnection::Implementation
consumer_.stop();
}
- bool verifyData(interface::ConsumerSocket &c,
- const core::ContentObject &contentObject) {
- if (contentObject.getPayloadType() == PayloadType::CONTENT_OBJECT) {
- TRANSPORT_LOGI("VERIFY CONTENT\n");
- } else if (contentObject.getPayloadType() == PayloadType::MANIFEST) {
- TRANSPORT_LOGI("VERIFY MANIFEST\n");
- }
-
- return true;
- }
-
void processLeavingInterest(interface::ConsumerSocket &c,
const core::Interest &interest) {
if (interest.payloadSize() == 0) {
@@ -307,9 +290,9 @@ HTTPClientConnection &HTTPClientConnection::setTimeout(
return implementation_->setTimeout(timeout);
}
-HTTPClientConnection &HTTPClientConnection::setCertificate(
- const std::string &cert_path) {
- return implementation_->setCertificate(cert_path);
+HTTPClientConnection &HTTPClientConnection::setVerifier(
+ std::shared_ptr<auth::Verifier> verifier) {
+ return implementation_->setVerifier(verifier);
}
} // namespace http
diff --git a/libtransport/src/http/request.cc b/libtransport/src/http/request.cc
index 09f709642..29118fd88 100644
--- a/libtransport/src/http/request.cc
+++ b/libtransport/src/http/request.cc
@@ -69,6 +69,72 @@ std::string HTTPRequest::getQueryString() const { return query_string_; }
std::string HTTPRequest::getRequestString() const { return request_string_; }
+std::size_t HTTPRequest::parseHeaders(const uint8_t *buffer, std::size_t size,
+ HTTPHeaders &headers,
+ std::string &http_version,
+ std::string &method, std::string &url) {
+ const char *crlf2 = "\r\n\r\n";
+ const char *begin = (const char *)buffer;
+ const char *end = begin + size;
+ const char *begincrlf2 = (const char *)crlf2;
+ const char *endcrlf2 = begincrlf2 + strlen(crlf2);
+ auto it = std::search(begin, end, begincrlf2, endcrlf2);
+
+ if (it != end) {
+ std::stringstream ss;
+ ss.str(std::string(begin, it + 2));
+
+ std::string line;
+ getline(ss, line);
+ std::istringstream line_s(line);
+ std::string _http_version;
+
+ line_s >> method;
+ line_s >> url;
+ line_s >> _http_version;
+ std::size_t separator;
+ if ((separator = _http_version.find('/')) != std::string::npos) {
+ if (_http_version.substr(0, separator) != "HTTP") {
+ return 0;
+ }
+ http_version = _http_version.substr(
+ separator + 1, _http_version.length() - separator - 1);
+ } else {
+ return 0;
+ }
+
+ std::size_t param_end;
+ std::size_t value_start;
+ std::string header_key, header_value;
+ while (getline(ss, line)) {
+ if ((param_end = line.find(':')) != std::string::npos) {
+ value_start = param_end + 1;
+ if ((value_start) < line.size()) {
+ if (line[value_start] == ' ') {
+ value_start++;
+ }
+ if (value_start < line.size()) {
+ header_key = line.substr(0, param_end);
+ header_value =
+ line.substr(value_start, line.size() - value_start - 1);
+ std::transform(header_key.begin(), header_key.end(),
+ header_key.begin(),
+ [](unsigned char c) { return std::tolower(c); });
+ std::transform(header_value.begin(), header_value.end(),
+ header_value.begin(),
+ [](unsigned char c) { return std::tolower(c); });
+ headers[header_key] = header_value;
+ }
+ }
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ return it + strlen(crlf2) - begin;
+}
+
} // namespace http
} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/http/response.cc b/libtransport/src/http/response.cc
index 409992835..c665fbc5f 100644
--- a/libtransport/src/http/response.cc
+++ b/libtransport/src/http/response.cc
@@ -17,9 +17,8 @@
#include <hicn/transport/http/response.h>
#include <algorithm>
-#include <functional>
-
#include <cstring>
+#include <functional>
namespace transport {
@@ -67,7 +66,7 @@ std::size_t HTTPResponse::parseHeaders(const uint8_t *buffer, std::size_t size,
auto it = std::search(begin, end, begincrlf2, endcrlf2);
if (it != end) {
std::stringstream ss;
- ss.str(std::string(begin, it));
+ ss.str(std::string(begin, it + 2));
std::string line;
getline(ss, line);
@@ -86,15 +85,8 @@ std::size_t HTTPResponse::parseHeaders(const uint8_t *buffer, std::size_t size,
return 0;
}
- std::string _status_string;
-
line_s >> status_code;
- line_s >> _status_string;
-
- auto _it = std::search(line.begin(), line.end(), status_string.begin(),
- status_string.end());
-
- status_string = std::string(_it, line.end() - 1);
+ line_s >> status_string;
std::size_t param_end;
std::size_t value_start;
@@ -106,7 +98,10 @@ std::size_t HTTPResponse::parseHeaders(const uint8_t *buffer, std::size_t size,
value_start++;
}
if (value_start < line.size()) {
- headers[line.substr(0, param_end)] =
+ auto header = line.substr(0, param_end);
+ std::transform(header.begin(), header.end(), header.begin(),
+ [](unsigned char c) { return std::tolower(c); });
+ headers[header] =
line.substr(value_start, line.size() - value_start - 1);
}
}
diff --git a/libtransport/src/implementation/CMakeLists.txt b/libtransport/src/implementation/CMakeLists.txt
index 5423a7697..392c99e15 100644
--- a/libtransport/src/implementation/CMakeLists.txt
+++ b/libtransport/src/implementation/CMakeLists.txt
@@ -13,13 +13,8 @@
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc_socket_producer.cc
-)
-
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/socket.h
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc_socket_producer.h
${CMAKE_CURRENT_SOURCE_DIR}/socket_producer.h
${CMAKE_CURRENT_SOURCE_DIR}/socket_consumer.h
)
@@ -27,15 +22,16 @@ list(APPEND HEADER_FILES
if (${OPENSSL_VERSION} VERSION_EQUAL "1.1.1a" OR ${OPENSSL_VERSION} VERSION_GREATER "1.1.1a")
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_producer.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/tls_rtc_socket_producer.cc
+ # ${CMAKE_CURRENT_SOURCE_DIR}/tls_rtc_socket_producer.cc
${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_producer.cc
${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_consumer.cc
${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_consumer.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/socket.cc
)
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_producer.h
- ${CMAKE_CURRENT_SOURCE_DIR}/tls_rtc_socket_producer.h
+ # ${CMAKE_CURRENT_SOURCE_DIR}/tls_rtc_socket_producer.h
${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_producer.h
${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_consumer.h
${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_consumer.h
diff --git a/libtransport/src/implementation/p2psecure_socket_consumer.cc b/libtransport/src/implementation/p2psecure_socket_consumer.cc
index 40ab58161..0b5966e71 100644
--- a/libtransport/src/implementation/p2psecure_socket_consumer.cc
+++ b/libtransport/src/implementation/p2psecure_socket_consumer.cc
@@ -15,7 +15,6 @@
#include <implementation/p2psecure_socket_consumer.h>
#include <interfaces/tls_socket_consumer.h>
-
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/tls1.h>
@@ -33,10 +32,6 @@ void P2PSecureConsumerSocket::setInterestPayload(
if (payload_ != NULL) int2.appendPayload(std::move(payload_));
}
-// implement void readBufferAvailable(), size_t maxBufferSize() const override,
-// void readError(), void readSuccess(). getReadBuffer() and readDataAvailable()
-// must be implemented even if empty.
-
/* Return the number of read bytes in the return param */
int readOld(BIO *b, char *buf, int size) {
if (size < 0) return size;
@@ -51,11 +46,13 @@ int readOld(BIO *b, char *buf, int size) {
socket->network_name_.setSuffix(socket->random_suffix_);
socket->ConsumerSocket::asyncConsume(socket->network_name_);
}
+
if (!socket->something_to_read_) socket->cv_.wait(lck);
}
size_t size_to_read, read;
size_t chain_size = socket->head_->length();
+
if (socket->head_->isChained())
chain_size = socket->head_->computeChainDataLength();
@@ -79,7 +76,7 @@ int readOld(BIO *b, char *buf, int size) {
}
}
- return read;
+ return (int)read;
}
/* Return the number of read bytes in readbytes */
@@ -106,6 +103,7 @@ int writeOld(BIO *b, const char *buf, int num) {
socket = (P2PSecureConsumerSocket *)BIO_get_data(b);
socket->payload_ = utils::MemBuf::copyBuffer(buf, num);
+
socket->ConsumerSocket::setSocketOption(
ConsumerCallbacksOptions::INTEREST_OUTPUT,
(ConsumerInterestCallback)std::bind(
@@ -173,10 +171,9 @@ int P2PSecureConsumerSocket::parseHicnKeyIdCb(SSL *s, unsigned int ext_type,
P2PSecureConsumerSocket::P2PSecureConsumerSocket(
interface::ConsumerSocket *consumer, int handshake_protocol,
int transport_protocol)
- : ConsumerSocket(consumer, transport_protocol),
+ : ConsumerSocket(consumer, handshake_protocol),
name_(),
- tls_consumer_(),
- buf_pool_(),
+ tls_consumer_(nullptr),
decrypted_content_(),
payload_(),
head_(),
@@ -224,12 +221,6 @@ P2PSecureConsumerSocket::P2PSecureConsumerSocket(
BIO_set_data(bio, this);
SSL_set_bio(ssl_, bio, bio);
- ConsumerSocket::getSocketOption(MAX_WINDOW_SIZE, old_max_win_);
- ConsumerSocket::setSocketOption(MAX_WINDOW_SIZE, (double)1.0);
-
- ConsumerSocket::getSocketOption(CURRENT_WINDOW_SIZE, old_current_win_);
- ConsumerSocket::setSocketOption(CURRENT_WINDOW_SIZE, (double)1.0);
-
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(
1, std::numeric_limits<uint32_t>::max());
@@ -244,76 +235,29 @@ P2PSecureConsumerSocket::~P2PSecureConsumerSocket() {
SSL_shutdown(ssl_);
}
-int P2PSecureConsumerSocket::consume(const Name &name) {
- if (transport_protocol_->isRunning()) {
- return CONSUMER_BUSY;
- }
+int P2PSecureConsumerSocket::handshake() {
+ int result = 1;
- if ((SSL_in_before(this->ssl_) || SSL_in_init(this->ssl_))) {
- ConsumerSocket::setSocketOption(MAX_WINDOW_SIZE, (double)1.0);
- network_name_ = producer_namespace_.getRandomName();
- network_name_.setSuffix(0);
- int result = SSL_connect(this->ssl_);
- ConsumerSocket::setSocketOption(MAX_WINDOW_SIZE, old_max_win_);
- ConsumerSocket::setSocketOption(CURRENT_WINDOW_SIZE, old_current_win_);
- if (result != 1)
- throw errors::RuntimeException("Unable to perform client handshake");
+ if (!(SSL_in_before(this->ssl_) || SSL_in_init(this->ssl_))) {
+ return 1;
}
- std::shared_ptr<Name> prefix_name = std::make_shared<Name>(
- secure_prefix_.family,
- ip_address_get_buffer(&(secure_prefix_.address), secure_prefix_.family));
- std::shared_ptr<Prefix> prefix =
- std::make_shared<Prefix>(*prefix_name, secure_prefix_.len);
- TLSConsumerSocket tls_consumer(nullptr, this->protocol_, this->ssl_);
- tls_consumer.setInterface(new interface::TLSConsumerSocket(&tls_consumer));
- ConsumerTimerCallback *stats_summary_callback = nullptr;
- this->getSocketOption(ConsumerCallbacksOptions::STATS_SUMMARY,
- &stats_summary_callback);
+ ConsumerSocket::getSocketOption(MAX_WINDOW_SIZE, old_max_win_);
+ ConsumerSocket::getSocketOption(CURRENT_WINDOW_SIZE, old_current_win_);
- uint32_t lifetime;
- this->getSocketOption(GeneralTransportOptions::INTEREST_LIFETIME, lifetime);
- tls_consumer.setSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
- lifetime);
- tls_consumer.setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK,
- read_callback_decrypted_);
- tls_consumer.setSocketOption(ConsumerCallbacksOptions::STATS_SUMMARY,
- *stats_summary_callback);
- tls_consumer.setSocketOption(GeneralTransportOptions::STATS_INTERVAL,
- this->timer_interval_milliseconds_);
- tls_consumer.setSocketOption(MAX_WINDOW_SIZE, old_max_win_);
- tls_consumer.setSocketOption(CURRENT_WINDOW_SIZE, old_current_win_);
- tls_consumer.connect();
+ ConsumerSocket::setSocketOption(MAX_WINDOW_SIZE, (double)1.0);
+ ConsumerSocket::setSocketOption(CURRENT_WINDOW_SIZE, (double)1.0);
- if (payload_ != NULL)
- return tls_consumer.consume((prefix->mapName(name)), std::move(payload_));
- else
- return tls_consumer.consume((prefix->mapName(name)));
-}
+ network_name_ = producer_namespace_.getRandomName();
+ network_name_.setSuffix(0);
-int P2PSecureConsumerSocket::asyncConsume(const Name &name) {
- if ((SSL_in_before(this->ssl_) || SSL_in_init(this->ssl_))) {
- ConsumerSocket::setSocketOption(CURRENT_WINDOW_SIZE, (double)1.0);
- ConsumerSocket::setSocketOption(MAX_WINDOW_SIZE, (double)1.0);
- network_name_ = producer_namespace_.getRandomName();
- network_name_.setSuffix(0);
- TRANSPORT_LOGD("Start handshake at %s", network_name_.toString().c_str());
- interface::ConsumerSocket::ReadCallback *on_payload = VOID_HANDLER;
- this->getSocketOption(ConsumerCallbacksOptions::READ_CALLBACK, &on_payload);
- int result = SSL_connect(this->ssl_);
- ConsumerSocket::setSocketOption(MAX_WINDOW_SIZE, old_max_win_);
- ConsumerSocket::setSocketOption(CURRENT_WINDOW_SIZE, old_current_win_);
- if (result != 1)
- throw errors::RuntimeException("Unable to perform client handshake");
- TRANSPORT_LOGD("Handshake performed!");
- }
+ TRANSPORT_LOGD("Start handshake at %s", network_name_.toString().c_str());
+ result = SSL_connect(this->ssl_);
- std::shared_ptr<Name> prefix_name = std::make_shared<Name>(
- secure_prefix_.family,
- ip_address_get_buffer(&(secure_prefix_.address), secure_prefix_.family));
- std::shared_ptr<Prefix> prefix =
- std::make_shared<Prefix>(*prefix_name, secure_prefix_.len);
+ return result;
+}
+void P2PSecureConsumerSocket::initSessionSocket() {
tls_consumer_ =
std::make_shared<TLSConsumerSocket>(nullptr, this->protocol_, this->ssl_);
tls_consumer_->setInterface(
@@ -325,6 +269,7 @@ int P2PSecureConsumerSocket::asyncConsume(const Name &name) {
uint32_t lifetime;
this->getSocketOption(GeneralTransportOptions::INTEREST_LIFETIME, lifetime);
+
tls_consumer_->setSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
lifetime);
tls_consumer_->setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK,
@@ -336,6 +281,59 @@ int P2PSecureConsumerSocket::asyncConsume(const Name &name) {
tls_consumer_->setSocketOption(MAX_WINDOW_SIZE, old_max_win_);
tls_consumer_->setSocketOption(CURRENT_WINDOW_SIZE, old_current_win_);
tls_consumer_->connect();
+}
+
+int P2PSecureConsumerSocket::consume(const Name &name) {
+ if (transport_protocol_->isRunning()) {
+ return CONSUMER_BUSY;
+ }
+
+ if (handshake() != 1) {
+ throw errors::RuntimeException("Unable to perform client handshake");
+ } else {
+ TRANSPORT_LOGD("Handshake performed!");
+ }
+
+ initSessionSocket();
+
+ if (tls_consumer_ == nullptr) {
+ throw errors::RuntimeException("TLS socket does not exist");
+ }
+
+ std::shared_ptr<Name> prefix_name = std::make_shared<Name>(
+ secure_prefix_.family,
+ ip_address_get_buffer(&(secure_prefix_.address), secure_prefix_.family));
+ std::shared_ptr<Prefix> prefix =
+ std::make_shared<Prefix>(*prefix_name, secure_prefix_.len);
+
+ if (payload_ != nullptr)
+ return tls_consumer_->consume((prefix->mapName(name)), std::move(payload_));
+ else
+ return tls_consumer_->consume((prefix->mapName(name)));
+}
+
+int P2PSecureConsumerSocket::asyncConsume(const Name &name) {
+ if (transport_protocol_->isRunning()) {
+ return CONSUMER_BUSY;
+ }
+
+ if (handshake() != 1) {
+ throw errors::RuntimeException("Unable to perform client handshake");
+ } else {
+ TRANSPORT_LOGD("Handshake performed!");
+ }
+
+ initSessionSocket();
+
+ if (tls_consumer_ == nullptr) {
+ throw errors::RuntimeException("TLS socket does not exist");
+ }
+
+ std::shared_ptr<Name> prefix_name = std::make_shared<Name>(
+ secure_prefix_.family,
+ ip_address_get_buffer(&(secure_prefix_.address), secure_prefix_.family));
+ std::shared_ptr<Prefix> prefix =
+ std::make_shared<Prefix>(*prefix_name, secure_prefix_.len);
if (payload_ != NULL)
return tls_consumer_->asyncConsume((prefix->mapName(name)),
@@ -399,5 +397,4 @@ void P2PSecureConsumerSocket::readSuccess(std::size_t total_size) noexcept {
bool P2PSecureConsumerSocket::isBufferMovable() noexcept { return true; }
} // namespace implementation
-
} // namespace transport
diff --git a/libtransport/src/implementation/p2psecure_socket_consumer.h b/libtransport/src/implementation/p2psecure_socket_consumer.h
index e2ebaf94e..a35a50352 100644
--- a/libtransport/src/implementation/p2psecure_socket_consumer.h
+++ b/libtransport/src/implementation/p2psecure_socket_consumer.h
@@ -16,7 +16,6 @@
#pragma once
#include <hicn/transport/interfaces/socket_consumer.h>
-
#include <implementation/tls_socket_consumer.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
@@ -69,39 +68,25 @@ class P2PSecureConsumerSocket : public ConsumerSocket,
private:
Name name_;
std::shared_ptr<TLSConsumerSocket> tls_consumer_;
-
/* SSL handle */
SSL *ssl_;
SSL_CTX *ctx_;
BIO_METHOD *bio_meth_;
-
/* Chain of MemBuf to be used as a temporary buffer to pass descypted data
* from the underlying layer to the application */
- utils::ObjectPool<utils::MemBuf> buf_pool_;
std::unique_ptr<utils::MemBuf> decrypted_content_;
-
/* Chain of MemBuf holding the payload to be written into interest or data */
std::unique_ptr<utils::MemBuf> payload_;
-
/* Chain of MemBuf holding the data retrieved from the underlying layer */
std::unique_ptr<utils::MemBuf> head_;
-
bool something_to_read_;
-
bool content_downloaded_;
-
double old_max_win_;
-
double old_current_win_;
-
uint32_t random_suffix_;
-
ip_prefix_t secure_prefix_;
-
Prefix producer_namespace_;
-
interface::ConsumerSocket::ReadCallback *read_callback_decrypted_;
-
std::mutex mtx_;
/* Condition variable for the wait */
@@ -138,9 +123,12 @@ class P2PSecureConsumerSocket : public ConsumerSocket,
virtual void readError(const std::error_code ec) noexcept override;
virtual void readSuccess(std::size_t total_size) noexcept override;
+
virtual bool isBufferMovable() noexcept override;
- int download_content(const Name &name);
+ int handshake();
+
+ void initSessionSocket();
};
} // namespace implementation
diff --git a/libtransport/src/implementation/p2psecure_socket_producer.cc b/libtransport/src/implementation/p2psecure_socket_producer.cc
index d0852539a..aa14f9e37 100644
--- a/libtransport/src/implementation/p2psecure_socket_producer.cc
+++ b/libtransport/src/implementation/p2psecure_socket_producer.cc
@@ -14,13 +14,11 @@
*/
#include <hicn/transport/core/interest.h>
-
#include <implementation/p2psecure_socket_producer.h>
-#include <implementation/tls_rtc_socket_producer.h>
+// #include <implementation/tls_rtc_socket_producer.h>
#include <implementation/tls_socket_producer.h>
#include <interfaces/tls_rtc_socket_producer.h>
#include <interfaces/tls_socket_producer.h>
-
#include <openssl/bio.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
@@ -34,33 +32,31 @@ namespace implementation {
P2PSecureProducerSocket::P2PSecureProducerSocket(
interface::ProducerSocket *producer_socket)
- : ProducerSocket(producer_socket),
+ : ProducerSocket(producer_socket,
+ ProductionProtocolAlgorithms::BYTE_STREAM),
mtx_(),
cv_(),
- map_secure_producers(),
- map_secure_rtc_producers(),
- list_secure_producers() {}
+ map_producers(),
+ list_producers() {}
P2PSecureProducerSocket::P2PSecureProducerSocket(
interface::ProducerSocket *producer_socket, bool rtc,
- const std::shared_ptr<utils::Identity> &identity)
- : ProducerSocket(producer_socket),
+ const std::shared_ptr<auth::Identity> &identity)
+ : ProducerSocket(producer_socket,
+ ProductionProtocolAlgorithms::BYTE_STREAM),
rtc_(rtc),
mtx_(),
cv_(),
- map_secure_producers(),
- map_secure_rtc_producers(),
- list_secure_producers() {
- /*
- * Setup SSL context (identity and parameter to use TLS 1.3)
- */
+ map_producers(),
+ list_producers() {
+ /* Setup SSL context (identity and parameter to use TLS 1.3) */
der_cert_ = parcKeyStore_GetDEREncodedCertificate(
- (identity->getSigner()->getKeyStore()));
+ (identity->getSigner()->getParcKeyStore()));
der_prk_ = parcKeyStore_GetDEREncodedPrivateKey(
- (identity->getSigner()->getKeyStore()));
+ (identity->getSigner()->getParcKeyStore()));
- int cert_size = parcBuffer_Limit(der_cert_);
- int prk_size = parcBuffer_Limit(der_prk_);
+ int cert_size = (int)parcBuffer_Limit(der_cert_);
+ int prk_size = (int)parcBuffer_Limit(der_prk_);
const uint8_t *cert =
reinterpret_cast<uint8_t *>(parcBuffer_Overlay(der_cert_, cert_size));
const uint8_t *prk =
@@ -68,10 +64,8 @@ P2PSecureProducerSocket::P2PSecureProducerSocket(
cert_509_ = d2i_X509(NULL, &cert, cert_size);
pkey_rsa_ = d2i_AutoPrivateKey(NULL, &prk, prk_size);
- /*
- * Set the callback so that when an interest is received we catch it and we
- * decrypt the payload before passing it to the application.
- */
+ /* Set the callback so that when an interest is received we catch it and we
+ * decrypt the payload before passing it to the application. */
ProducerSocket::setSocketOption(
ProducerCallbacksOptions::INTEREST_INPUT,
(ProducerInterestCallback)std::bind(
@@ -84,58 +78,76 @@ P2PSecureProducerSocket::~P2PSecureProducerSocket() {
if (der_prk_) parcBuffer_Release(&der_prk_);
}
+void P2PSecureProducerSocket::initSessionSocket(
+ std::unique_ptr<TLSProducerSocket> &producer) {
+ producer->on_content_produced_application_ =
+ this->on_content_produced_application_;
+ producer->setSocketOption(CONTENT_OBJECT_EXPIRY_TIME,
+ this->content_object_expiry_time_);
+ producer->setSocketOption(SIGNER, this->signer_);
+ producer->setSocketOption(MAKE_MANIFEST, this->making_manifest_);
+ producer->setSocketOption(DATA_PACKET_SIZE,
+ (uint32_t)(this->data_packet_size_));
+ uint32_t output_buffer_size = 0;
+ this->getSocketOption(GeneralTransportOptions::OUTPUT_BUFFER_SIZE,
+ output_buffer_size);
+ producer->setSocketOption(GeneralTransportOptions::OUTPUT_BUFFER_SIZE,
+ output_buffer_size);
+
+ if (!rtc_) {
+ producer->setInterface(new interface::TLSProducerSocket(producer.get()));
+ } else {
+ // TODO
+ // TLSRTCProducerSocket *rtc_producer =
+ // dynamic_cast<TLSRTCProducerSocket *>(producer.get());
+ // rtc_producer->setInterface(
+ // new interface::TLSRTCProducerSocket(rtc_producer));
+ }
+}
+
void P2PSecureProducerSocket::onInterestCallback(interface::ProducerSocket &p,
Interest &interest) {
std::unique_lock<std::mutex> lck(mtx_);
+ std::unique_ptr<TLSProducerSocket> tls_producer;
+ auto it = map_producers.find(interest.getName());
+
+ if (it != map_producers.end()) {
+ return;
+ }
+
+ if (!rtc_) {
+ tls_producer =
+ std::make_unique<TLSProducerSocket>(nullptr, this, interest.getName());
+ } else {
+ // TODO
+ // tls_producer = std::make_unique<TLSRTCProducerSocket>(nullptr, this,
+ // interest.getName());
+ }
+
+ initSessionSocket(tls_producer);
+ TLSProducerSocket *tls_producer_ptr = tls_producer.get();
+ map_producers.insert({interest.getName(), move(tls_producer)});
TRANSPORT_LOGD("Start handshake at %s",
interest.getName().toString().c_str());
+
if (!rtc_) {
- auto it = map_secure_producers.find(interest.getName());
- if (it != map_secure_producers.end()) return;
- TLSProducerSocket *tls_producer =
- new TLSProducerSocket(nullptr, this, interest.getName());
- tls_producer->setInterface(new interface::TLSProducerSocket(tls_producer));
-
- tls_producer->on_content_produced_application_ =
- this->on_content_produced_application_;
- tls_producer->setSocketOption(CONTENT_OBJECT_EXPIRY_TIME,
- this->content_object_expiry_time_);
- tls_producer->setSocketOption(SIGNER, this->signer_);
- tls_producer->setSocketOption(MAKE_MANIFEST, this->making_manifest_);
- tls_producer->setSocketOption(DATA_PACKET_SIZE,
- (uint32_t)(this->data_packet_size_));
- tls_producer->output_buffer_.setLimit(this->output_buffer_.getLimit());
- map_secure_producers.insert(
- {interest.getName(), std::unique_ptr<TLSProducerSocket>(tls_producer)});
- tls_producer->onInterest(*tls_producer, interest);
- tls_producer->async_accept();
+ tls_producer_ptr->onInterest(*tls_producer_ptr, interest);
+ tls_producer_ptr->async_accept();
} else {
- auto it = map_secure_rtc_producers.find(interest.getName());
- if (it != map_secure_rtc_producers.end()) return;
- TLSRTCProducerSocket *tls_producer =
- new TLSRTCProducerSocket(nullptr, this, interest.getName());
- tls_producer->setInterface(
- new interface::TLSRTCProducerSocket(tls_producer));
- tls_producer->on_content_produced_application_ =
- this->on_content_produced_application_;
- tls_producer->setSocketOption(CONTENT_OBJECT_EXPIRY_TIME,
- this->content_object_expiry_time_);
- tls_producer->setSocketOption(SIGNER, this->signer_);
- tls_producer->setSocketOption(MAKE_MANIFEST, this->making_manifest_);
- tls_producer->setSocketOption(DATA_PACKET_SIZE,
- (uint32_t)(this->data_packet_size_));
- tls_producer->output_buffer_.setLimit(this->output_buffer_.getLimit());
- map_secure_rtc_producers.insert(
- {interest.getName(),
- std::unique_ptr<TLSRTCProducerSocket>(tls_producer)});
- tls_producer->onInterest(*tls_producer, interest);
- tls_producer->async_accept();
+ // TODO
+ // TLSRTCProducerSocket *rtc_producer_ptr =
+ // dynamic_cast<TLSRTCProducerSocket *>(tls_producer_ptr);
+ // rtc_producer_ptr->onInterest(*rtc_producer_ptr, interest);
+ // rtc_producer_ptr->async_accept();
}
}
-void P2PSecureProducerSocket::produce(const uint8_t *buffer,
- size_t buffer_size) {
+uint32_t P2PSecureProducerSocket::produceDatagram(
+ const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer) {
+ // TODO
+ throw errors::NotImplementedException();
+
if (!rtc_) {
throw errors::RuntimeException(
"RTC must be the transport protocol to start the production of current "
@@ -143,17 +155,23 @@ void P2PSecureProducerSocket::produce(const uint8_t *buffer,
}
std::unique_lock<std::mutex> lck(mtx_);
- if (list_secure_rtc_producers.empty()) cv_.wait(lck);
- for (auto it = list_secure_rtc_producers.cbegin();
- it != list_secure_rtc_producers.cend(); it++) {
- (*it)->produce(utils::MemBuf::copyBuffer(buffer, buffer_size));
- }
+ if (list_producers.empty()) cv_.wait(lck);
+
+ // TODO
+ // for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
+ // {
+ // TLSRTCProducerSocket *rtc_producer =
+ // dynamic_cast<TLSRTCProducerSocket *>(it->get());
+ // rtc_producer->produce(utils::MemBuf::copyBuffer(buffer, buffer_size));
+ // }
+
+ return 0;
}
-uint32_t P2PSecureProducerSocket::produce(
- Name content_name, std::unique_ptr<utils::MemBuf> &&buffer, bool is_last,
- uint32_t start_offset) {
+uint32_t P2PSecureProducerSocket::produceStream(
+ const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer,
+ bool is_last, uint32_t start_offset) {
if (rtc_) {
throw errors::RuntimeException(
"RTC transport protocol is not compatible with the production of "
@@ -162,19 +180,21 @@ uint32_t P2PSecureProducerSocket::produce(
std::unique_lock<std::mutex> lck(mtx_);
uint32_t segments = 0;
- if (list_secure_producers.empty()) cv_.wait(lck);
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
- segments +=
- (*it)->produce(content_name, buffer->clone(), is_last, start_offset);
+ if (list_producers.empty()) cv_.wait(lck);
+
+ for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
+ segments += (*it)->produceStream(content_name, buffer->clone(), is_last,
+ start_offset);
+
return segments;
}
-uint32_t P2PSecureProducerSocket::produce(Name content_name,
- const uint8_t *buffer,
- size_t buffer_size, bool is_last,
- uint32_t start_offset) {
+uint32_t P2PSecureProducerSocket::produceStream(const Name &content_name,
+ const uint8_t *buffer,
+ size_t buffer_size,
+ bool is_last,
+ uint32_t start_offset) {
if (rtc_) {
throw errors::RuntimeException(
"RTC transport protocol is not compatible with the production of "
@@ -183,33 +203,34 @@ uint32_t P2PSecureProducerSocket::produce(Name content_name,
std::unique_lock<std::mutex> lck(mtx_);
uint32_t segments = 0;
- if (list_secure_producers.empty()) cv_.wait(lck);
+ if (list_producers.empty()) cv_.wait(lck);
+
+ for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
+ segments += (*it)->produceStream(content_name, buffer, buffer_size, is_last,
+ start_offset);
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
- segments += (*it)->produce(content_name, buffer, buffer_size, is_last,
- start_offset);
return segments;
}
-void P2PSecureProducerSocket::asyncProduce(const Name &content_name,
- const uint8_t *buf,
- size_t buffer_size, bool is_last,
- uint32_t *start_offset) {
- if (rtc_) {
- throw errors::RuntimeException(
- "RTC transport protocol is not compatible with the production of "
- "current data. Aborting.");
- }
-
- std::unique_lock<std::mutex> lck(mtx_);
- if (list_secure_producers.empty()) cv_.wait(lck);
-
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++) {
- (*it)->asyncProduce(content_name, buf, buffer_size, is_last, start_offset);
- }
-}
+// void P2PSecureProducerSocket::asyncProduce(const Name &content_name,
+// const uint8_t *buf,
+// size_t buffer_size, bool is_last,
+// uint32_t *start_offset) {
+// if (rtc_) {
+// throw errors::RuntimeException(
+// "RTC transport protocol is not compatible with the production of "
+// "current data. Aborting.");
+// }
+
+// std::unique_lock<std::mutex> lck(mtx_);
+// if (list_producers.empty()) cv_.wait(lck);
+
+// for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
+// {
+// (*it)->asyncProduce(content_name, buf, buffer_size, is_last,
+// start_offset);
+// }
+// }
void P2PSecureProducerSocket::asyncProduce(
Name content_name, std::unique_ptr<utils::MemBuf> &&buffer, bool is_last,
@@ -221,22 +242,19 @@ void P2PSecureProducerSocket::asyncProduce(
}
std::unique_lock<std::mutex> lck(mtx_);
- if (list_secure_producers.empty()) cv_.wait(lck);
+ if (list_producers.empty()) cv_.wait(lck);
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++) {
+ for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++) {
(*it)->asyncProduce(content_name, buffer->clone(), is_last, offset,
last_segment);
}
}
-// Socket Option Redefinition to avoid name hiding
-
+/* Redefinition of socket options to avoid name hiding */
int P2PSecureProducerSocket::setSocketOption(
int socket_option_key, ProducerInterestCallback socket_option_value) {
- if (!list_secure_producers.empty()) {
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
+ if (!list_producers.empty()) {
+ for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
(*it)->setSocketOption(socket_option_key, socket_option_value);
}
@@ -268,10 +286,9 @@ int P2PSecureProducerSocket::setSocketOption(
int P2PSecureProducerSocket::setSocketOption(
int socket_option_key,
- const std::shared_ptr<utils::Signer> &socket_option_value) {
- if (!list_secure_producers.empty())
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
+ const std::shared_ptr<auth::Signer> &socket_option_value) {
+ if (!list_producers.empty())
+ for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
(*it)->setSocketOption(socket_option_key, socket_option_value);
switch (socket_option_key) {
@@ -288,9 +305,8 @@ int P2PSecureProducerSocket::setSocketOption(
int P2PSecureProducerSocket::setSocketOption(int socket_option_key,
uint32_t socket_option_value) {
- if (!list_secure_producers.empty()) {
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
+ if (!list_producers.empty()) {
+ for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
(*it)->setSocketOption(socket_option_key, socket_option_value);
}
switch (socket_option_key) {
@@ -305,9 +321,8 @@ int P2PSecureProducerSocket::setSocketOption(int socket_option_key,
int P2PSecureProducerSocket::setSocketOption(int socket_option_key,
bool socket_option_value) {
- if (!list_secure_producers.empty())
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
+ if (!list_producers.empty())
+ for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
(*it)->setSocketOption(socket_option_key, socket_option_value);
return ProducerSocket::setSocketOption(socket_option_key,
@@ -316,20 +331,8 @@ int P2PSecureProducerSocket::setSocketOption(int socket_option_key,
int P2PSecureProducerSocket::setSocketOption(int socket_option_key,
Name *socket_option_value) {
- if (!list_secure_producers.empty())
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
- (*it)->setSocketOption(socket_option_key, socket_option_value);
-
- return ProducerSocket::setSocketOption(socket_option_key,
- socket_option_value);
-}
-
-int P2PSecureProducerSocket::setSocketOption(
- int socket_option_key, std::list<Prefix> socket_option_value) {
- if (!list_secure_producers.empty())
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
+ if (!list_producers.empty())
+ for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
(*it)->setSocketOption(socket_option_key, socket_option_value);
return ProducerSocket::setSocketOption(socket_option_key,
@@ -338,9 +341,8 @@ int P2PSecureProducerSocket::setSocketOption(
int P2PSecureProducerSocket::setSocketOption(
int socket_option_key, ProducerContentObjectCallback socket_option_value) {
- if (!list_secure_producers.empty())
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
+ if (!list_producers.empty())
+ for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
(*it)->setSocketOption(socket_option_key, socket_option_value);
return ProducerSocket::setSocketOption(socket_option_key,
@@ -349,9 +351,8 @@ int P2PSecureProducerSocket::setSocketOption(
int P2PSecureProducerSocket::setSocketOption(
int socket_option_key, ProducerContentCallback socket_option_value) {
- if (!list_secure_producers.empty())
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
+ if (!list_producers.empty())
+ for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
(*it)->setSocketOption(socket_option_key, socket_option_value);
switch (socket_option_key) {
@@ -367,21 +368,9 @@ int P2PSecureProducerSocket::setSocketOption(
}
int P2PSecureProducerSocket::setSocketOption(
- int socket_option_key, utils::CryptoHashType socket_option_value) {
- if (!list_secure_producers.empty())
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
- (*it)->setSocketOption(socket_option_key, socket_option_value);
-
- return ProducerSocket::setSocketOption(socket_option_key,
- socket_option_value);
-}
-
-int P2PSecureProducerSocket::setSocketOption(
- int socket_option_key, utils::CryptoSuite socket_option_value) {
- if (!list_secure_producers.empty())
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
+ int socket_option_key, auth::CryptoHashType socket_option_value) {
+ if (!list_producers.empty())
+ for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
(*it)->setSocketOption(socket_option_key, socket_option_value);
return ProducerSocket::setSocketOption(socket_option_key,
@@ -390,9 +379,8 @@ int P2PSecureProducerSocket::setSocketOption(
int P2PSecureProducerSocket::setSocketOption(
int socket_option_key, const std::string &socket_option_value) {
- if (!list_secure_producers.empty())
- for (auto it = list_secure_producers.cbegin();
- it != list_secure_producers.cend(); it++)
+ if (!list_producers.empty())
+ for (auto it = list_producers.cbegin(); it != list_producers.cend(); it++)
(*it)->setSocketOption(socket_option_key, socket_option_value);
return ProducerSocket::setSocketOption(socket_option_key,
@@ -400,5 +388,4 @@ int P2PSecureProducerSocket::setSocketOption(
}
} // namespace implementation
-
} // namespace transport
diff --git a/libtransport/src/implementation/p2psecure_socket_producer.h b/libtransport/src/implementation/p2psecure_socket_producer.h
index 33339deba..b7c3d1958 100644
--- a/libtransport/src/implementation/p2psecure_socket_producer.h
+++ b/libtransport/src/implementation/p2psecure_socket_producer.h
@@ -15,15 +15,14 @@
#pragma once
-#include <hicn/transport/security/identity.h>
-#include <hicn/transport/security/signer.h>
-
+#include <hicn/transport/auth/identity.h>
+#include <hicn/transport/auth/signer.h>
#include <implementation/socket_producer.h>
-#include <implementation/tls_rtc_socket_producer.h>
+// #include <implementation/tls_rtc_socket_producer.h>
#include <implementation/tls_socket_producer.h>
+#include <openssl/ssl.h>
#include <utils/content_store.h>
-#include <openssl/ssl.h>
#include <condition_variable>
#include <forward_list>
#include <mutex>
@@ -33,37 +32,40 @@ namespace implementation {
class P2PSecureProducerSocket : public ProducerSocket {
friend class TLSProducerSocket;
- friend class TLSRTCProducerSocket;
+ // TODO
+ // friend class TLSRTCProducerSocket;
public:
explicit P2PSecureProducerSocket(interface::ProducerSocket *producer_socket);
+
explicit P2PSecureProducerSocket(
interface::ProducerSocket *producer_socket, bool rtc,
- const std::shared_ptr<utils::Identity> &identity);
+ const std::shared_ptr<auth::Identity> &identity);
+
~P2PSecureProducerSocket();
- void produce(const uint8_t *buffer, size_t buffer_size) override;
+ uint32_t produceDatagram(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer) override;
- uint32_t produce(Name content_name, const uint8_t *buffer, size_t buffer_size,
- bool is_last = true, uint32_t start_offset = 0) override;
+ uint32_t produceStream(const Name &content_name, const uint8_t *buffer,
+ size_t buffer_size, bool is_last = true,
+ uint32_t start_offset = 0) override;
- uint32_t produce(Name content_name, std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last = true, uint32_t start_offset = 0) override;
+ uint32_t produceStream(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer,
+ bool is_last = true,
+ uint32_t start_offset = 0) override;
void asyncProduce(Name content_name, std::unique_ptr<utils::MemBuf> &&buffer,
bool is_last, uint32_t offset,
uint32_t **last_segment = nullptr) override;
- void asyncProduce(const Name &suffix, const uint8_t *buf, size_t buffer_size,
- bool is_last = true,
- uint32_t *start_offset = nullptr) override;
-
int setSocketOption(int socket_option_key,
ProducerInterestCallback socket_option_value) override;
int setSocketOption(
int socket_option_key,
- const std::shared_ptr<utils::Signer> &socket_option_value) override;
+ const std::shared_ptr<auth::Signer> &socket_option_value) override;
int setSocketOption(int socket_option_key,
uint32_t socket_option_value) override;
@@ -73,9 +75,6 @@ class P2PSecureProducerSocket : public ProducerSocket {
int setSocketOption(int socket_option_key,
Name *socket_option_value) override;
- int setSocketOption(int socket_option_key,
- std::list<Prefix> socket_option_value) override;
-
int setSocketOption(
int socket_option_key,
ProducerContentObjectCallback socket_option_value) override;
@@ -84,19 +83,15 @@ class P2PSecureProducerSocket : public ProducerSocket {
ProducerContentCallback socket_option_value) override;
int setSocketOption(int socket_option_key,
- utils::CryptoHashType socket_option_value) override;
-
- int setSocketOption(int socket_option_key,
- utils::CryptoSuite socket_option_value) override;
+ auth::CryptoHashType socket_option_value) override;
int setSocketOption(int socket_option_key,
const std::string &socket_option_value) override;
using ProducerSocket::getSocketOption;
- using ProducerSocket::onInterest;
+ // using ProducerSocket::onInterest;
protected:
- bool rtc_;
/* Callback invoked once an interest has been received and its payload
* decrypted */
ProducerInterestCallback on_interest_input_decrypted_;
@@ -104,27 +99,23 @@ class P2PSecureProducerSocket : public ProducerSocket {
ProducerContentCallback on_content_produced_application_;
private:
+ bool rtc_;
std::mutex mtx_;
-
/* Condition variable for the wait */
std::condition_variable cv_;
-
PARCBuffer *der_cert_;
PARCBuffer *der_prk_;
X509 *cert_509_;
EVP_PKEY *pkey_rsa_;
std::unordered_map<core::Name, std::unique_ptr<TLSProducerSocket>,
core::hash<core::Name>, core::compare2<core::Name>>
- map_secure_producers;
- std::unordered_map<core::Name, std::unique_ptr<TLSRTCProducerSocket>,
- core::hash<core::Name>, core::compare2<core::Name>>
- map_secure_rtc_producers;
- std::list<std::unique_ptr<TLSProducerSocket>> list_secure_producers;
- std::list<std::unique_ptr<TLSRTCProducerSocket>> list_secure_rtc_producers;
+ map_producers;
+ std::list<std::unique_ptr<TLSProducerSocket>> list_producers;
void onInterestCallback(interface::ProducerSocket &p, Interest &interest);
+
+ void initSessionSocket(std::unique_ptr<TLSProducerSocket> &producer);
};
} // namespace implementation
-
} // namespace transport
diff --git a/libtransport/src/implementation/socket.cc b/libtransport/src/implementation/socket.cc
new file mode 100644
index 000000000..2e21f2bc3
--- /dev/null
+++ b/libtransport/src/implementation/socket.cc
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <core/global_configuration.h>
+#include <implementation/socket.h>
+
+namespace transport {
+namespace implementation {
+
+Socket::Socket(std::shared_ptr<core::Portal> &&portal)
+ : portal_(std::move(portal)), is_async_(false) {}
+
+} // namespace implementation
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/implementation/socket.h b/libtransport/src/implementation/socket.h
index 2e51f3027..cf22c03e1 100644
--- a/libtransport/src/implementation/socket.h
+++ b/libtransport/src/implementation/socket.h
@@ -15,13 +15,12 @@
#pragma once
+#include <core/facade.h>
#include <hicn/transport/config.h>
#include <hicn/transport/interfaces/callbacks.h>
#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <hicn/transport/interfaces/socket_options_keys.h>
-#include <core/facade.h>
-
#define SOCKET_OPTION_GET 0
#define SOCKET_OPTION_NOT_GET 1
#define SOCKET_OPTION_SET 2
@@ -32,56 +31,23 @@ namespace transport {
namespace implementation {
// Forward Declarations
-template <typename PortalType>
class Socket;
-// Define the portal and its connector, depending on the compilation options
-// passed by the build tool.
-using HicnForwarderPortal = core::HicnForwarderPortal;
-
-#ifdef __linux__
-#ifndef __ANDROID__
-using RawSocketPortal = core::RawSocketPortal;
-#endif
-#endif
-
-#ifdef __vpp__
-using VPPForwarderPortal = core::VPPForwarderPortal;
-using BaseSocket = Socket<VPPForwarderPortal>;
-using BasePortal = VPPForwarderPortal;
-#else
-using BaseSocket = Socket<HicnForwarderPortal>;
-using BasePortal = HicnForwarderPortal;
-#endif
-
-template <typename PortalType>
class Socket {
- static_assert(std::is_same<PortalType, HicnForwarderPortal>::value
-#ifdef __linux__
-#ifndef __ANDROID__
- || std::is_same<PortalType, RawSocketPortal>::value
-#ifdef __vpp__
- || std::is_same<PortalType, VPPForwarderPortal>::value
-#endif
-#endif
- ,
-#else
- ,
-
-#endif
- "This class is not allowed as Portal");
-
public:
- using Portal = PortalType;
-
- virtual asio::io_service &getIoService() = 0;
-
virtual void connect() = 0;
-
virtual bool isRunning() = 0;
+ virtual asio::io_service &getIoService() { return portal_->getIoService(); }
+
protected:
+ Socket(std::shared_ptr<core::Portal> &&portal);
+
virtual ~Socket(){};
+
+ protected:
+ std::shared_ptr<core::Portal> portal_;
+ bool is_async_;
};
} // namespace implementation
diff --git a/libtransport/src/implementation/socket_consumer.h b/libtransport/src/implementation/socket_consumer.h
index 488f238ba..a7b6ac4e7 100644
--- a/libtransport/src/implementation/socket_consumer.h
+++ b/libtransport/src/implementation/socket_consumer.h
@@ -13,16 +13,17 @@
* limitations under the License.
*/
+#pragma once
+
#include <hicn/transport/interfaces/socket_consumer.h>
#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <hicn/transport/interfaces/statistics.h>
-#include <hicn/transport/security/verifier.h>
-
+#include <hicn/transport/auth/verifier.h>
+#include <hicn/transport/utils/event_thread.h>
#include <protocols/cbr.h>
-#include <protocols/protocol.h>
#include <protocols/raaqm.h>
-#include <protocols/rtc.h>
-#include <utils/event_thread.h>
+#include <protocols/rtc/rtc.h>
+#include <protocols/transport_protocol.h>
namespace transport {
namespace implementation {
@@ -31,11 +32,12 @@ using namespace core;
using namespace interface;
using ReadCallback = interface::ConsumerSocket::ReadCallback;
-class ConsumerSocket : public Socket<BasePortal> {
- public:
- ConsumerSocket(interface::ConsumerSocket *consumer, int protocol)
- : consumer_interface_(consumer),
- portal_(std::make_shared<Portal>()),
+class ConsumerSocket : public Socket {
+ private:
+ ConsumerSocket(interface::ConsumerSocket *consumer, int protocol,
+ std::shared_ptr<core::Portal> &&portal)
+ : Socket(std::move(portal)),
+ consumer_interface_(consumer),
async_downloader_(),
interest_lifetime_(default_values::interest_lifetime),
min_window_size_(default_values::min_window_size),
@@ -54,14 +56,13 @@ class ConsumerSocket : public Socket<BasePortal> {
rate_estimation_observer_(nullptr),
rate_estimation_batching_parameter_(default_values::batch),
rate_estimation_choice_(0),
- verifier_(std::make_shared<utils::Verifier>()),
+ verifier_(std::make_shared<auth::VoidVerifier>()),
verify_signature_(false),
- key_content_(false),
+ reset_window_(false),
on_interest_output_(VOID_HANDLER),
on_interest_timeout_(VOID_HANDLER),
on_interest_satisfied_(VOID_HANDLER),
on_content_object_input_(VOID_HANDLER),
- on_content_object_verification_(VOID_HANDLER),
stats_summary_(VOID_HANDLER),
read_callback_(nullptr),
timer_interval_milliseconds_(0),
@@ -73,7 +74,7 @@ class ConsumerSocket : public Socket<BasePortal> {
break;
case TransportProtocolAlgorithms::RTC:
transport_protocol_ =
- std::make_unique<protocol::RTCTransportProtocol>(this);
+ std::make_unique<protocol::rtc::RTCTransportProtocol>(this);
break;
case TransportProtocolAlgorithms::RAAQM:
default:
@@ -83,6 +84,17 @@ class ConsumerSocket : public Socket<BasePortal> {
}
}
+ public:
+ ConsumerSocket(interface::ConsumerSocket *consumer, int protocol)
+ : ConsumerSocket(consumer, protocol, std::make_shared<core::Portal>()) {}
+
+ ConsumerSocket(interface::ConsumerSocket *consumer, int protocol,
+ asio::io_service &io_service)
+ : ConsumerSocket(consumer, protocol,
+ std::make_shared<core::Portal>(io_service)) {
+ is_async_ = true;
+ }
+
~ConsumerSocket() {
stop();
async_downloader_.stop();
@@ -110,7 +122,7 @@ class ConsumerSocket : public Socket<BasePortal> {
transport_protocol_->start();
- return CONSUMER_FINISHED;
+ return is_async_ ? CONSUMER_RUNNING : CONSUMER_FINISHED;
}
virtual int asyncConsume(const Name &name) {
@@ -125,8 +137,6 @@ class ConsumerSocket : public Socket<BasePortal> {
return CONSUMER_RUNNING;
}
- bool verifyKeyPackets() { return transport_protocol_->verifyKeyPackets(); }
-
void stop() {
if (transport_protocol_->isRunning()) {
transport_protocol_->stop();
@@ -139,8 +149,6 @@ class ConsumerSocket : public Socket<BasePortal> {
}
}
- asio::io_service &getIoService() { return portal_->getIoService(); }
-
virtual int setSocketOption(int socket_option_key,
ReadCallback *socket_option_value) {
// Reschedule the function on the io_service to avoid race condition in
@@ -303,12 +311,6 @@ class ConsumerSocket : public Socket<BasePortal> {
break;
}
- case ConsumerCallbacksOptions::CONTENT_OBJECT_TO_VERIFY:
- if (socket_option_value == VOID_HANDLER) {
- on_content_object_verification_ = VOID_HANDLER;
- break;
- }
-
default:
return SOCKET_OPTION_NOT_SET;
}
@@ -321,13 +323,8 @@ class ConsumerSocket : public Socket<BasePortal> {
int result = SOCKET_OPTION_NOT_SET;
if (!transport_protocol_->isRunning()) {
switch (socket_option_key) {
- case GeneralTransportOptions::VERIFY_SIGNATURE:
- verify_signature_ = socket_option_value;
- result = SOCKET_OPTION_SET;
- break;
-
- case GeneralTransportOptions::KEY_CONTENT:
- key_content_ = socket_option_value;
+ case RaaqmTransportOptions::PER_SESSION_CWINDOW_RESET:
+ reset_window_ = socket_option_value;
result = SOCKET_OPTION_SET;
break;
@@ -359,29 +356,6 @@ class ConsumerSocket : public Socket<BasePortal> {
});
}
- int setSocketOption(
- int socket_option_key,
- ConsumerContentObjectVerificationCallback socket_option_value) {
- // Reschedule the function on the io_service to avoid race condition in
- // case setSocketOption is called while the io_service is running.
- return rescheduleOnIOService(
- socket_option_key, socket_option_value,
- [this](int socket_option_key,
- ConsumerContentObjectVerificationCallback socket_option_value)
- -> int {
- switch (socket_option_key) {
- case ConsumerCallbacksOptions::CONTENT_OBJECT_TO_VERIFY:
- on_content_object_verification_ = socket_option_value;
- break;
-
- default:
- return SOCKET_OPTION_NOT_SET;
- }
-
- return SOCKET_OPTION_SET;
- });
- }
-
int setSocketOption(int socket_option_key,
ConsumerInterestCallback socket_option_value) {
// Reschedule the function on the io_service to avoid race condition in
@@ -415,51 +389,6 @@ class ConsumerSocket : public Socket<BasePortal> {
});
}
- int setSocketOption(
- int socket_option_key,
- ConsumerContentObjectVerificationFailedCallback socket_option_value) {
- return rescheduleOnIOService(
- socket_option_key, socket_option_value,
- [this](
- int socket_option_key,
- ConsumerContentObjectVerificationFailedCallback socket_option_value)
- -> int {
- switch (socket_option_key) {
- case ConsumerCallbacksOptions::VERIFICATION_FAILED:
- verification_failed_callback_ = socket_option_value;
- break;
-
- default:
- return SOCKET_OPTION_NOT_SET;
- }
-
- return SOCKET_OPTION_SET;
- });
- }
-
- // int setSocketOption(
- // int socket_option_key,
- // ConsumerContentObjectVerificationFailedCallback socket_option_value) {
- // return rescheduleOnIOService(
- // socket_option_key, socket_option_value,
- // [this](
- // int socket_option_key,
- // ConsumerContentObjectVerificationFailedCallback
- // socket_option_value)
- // -> int {
- // switch (socket_option_key) {
- // case ConsumerCallbacksOptions::VERIFICATION_FAILED:
- // verification_failed_callback_ = socket_option_value;
- // break;
-
- // default:
- // return SOCKET_OPTION_NOT_SET;
- // }
-
- // return SOCKET_OPTION_SET;
- // });
- // }
-
int setSocketOption(int socket_option_key, IcnObserver *socket_option_value) {
utils::SpinLock::Acquire locked(guard_raaqm_params_);
switch (socket_option_key) {
@@ -476,7 +405,7 @@ class ConsumerSocket : public Socket<BasePortal> {
int setSocketOption(
int socket_option_key,
- const std::shared_ptr<utils::Verifier> &socket_option_value) {
+ const std::shared_ptr<auth::Verifier> &socket_option_value) {
int result = SOCKET_OPTION_NOT_SET;
if (!transport_protocol_->isRunning()) {
switch (socket_option_key) {
@@ -498,14 +427,6 @@ class ConsumerSocket : public Socket<BasePortal> {
int result = SOCKET_OPTION_NOT_SET;
if (!transport_protocol_->isRunning()) {
switch (socket_option_key) {
- case GeneralTransportOptions::CERTIFICATE:
- key_id_ = verifier_->addKeyFromCertificate(socket_option_value);
-
- if (key_id_ != nullptr) {
- result = SOCKET_OPTION_SET;
- }
- break;
-
case DataLinkOptions::OUTPUT_INTERFACE:
output_interface_ = socket_option_value;
portal_->setOutputInterface(output_interface_);
@@ -624,12 +545,12 @@ class ConsumerSocket : public Socket<BasePortal> {
socket_option_value = transport_protocol_->isRunning();
break;
- case GeneralTransportOptions::VERIFY_SIGNATURE:
- socket_option_value = verify_signature_;
+ case GeneralTransportOptions::ASYNC_MODE:
+ socket_option_value = is_async_;
break;
- case GeneralTransportOptions::KEY_CONTENT:
- socket_option_value = key_content_;
+ case RaaqmTransportOptions::PER_SESSION_CWINDOW_RESET:
+ socket_option_value = reset_window_;
break;
default:
@@ -673,29 +594,6 @@ class ConsumerSocket : public Socket<BasePortal> {
});
}
- int getSocketOption(
- int socket_option_key,
- ConsumerContentObjectVerificationCallback **socket_option_value) {
- // Reschedule the function on the io_service to avoid race condition in
- // case setSocketOption is called while the io_service is running.
- return rescheduleOnIOService(
- socket_option_key, socket_option_value,
- [this](int socket_option_key,
- ConsumerContentObjectVerificationCallback **socket_option_value)
- -> int {
- switch (socket_option_key) {
- case ConsumerCallbacksOptions::CONTENT_OBJECT_TO_VERIFY:
- *socket_option_value = &on_content_object_verification_;
- break;
-
- default:
- return SOCKET_OPTION_NOT_GET;
- }
-
- return SOCKET_OPTION_GET;
- });
- }
-
int getSocketOption(int socket_option_key,
ConsumerInterestCallback **socket_option_value) {
// Reschedule the function on the io_service to avoid race condition in
@@ -729,30 +627,8 @@ class ConsumerSocket : public Socket<BasePortal> {
});
}
- int getSocketOption(
- int socket_option_key,
- ConsumerContentObjectVerificationFailedCallback **socket_option_value) {
- // Reschedule the function on the io_service to avoid race condition in
- // case setSocketOption is called while the io_service is running.
- return rescheduleOnIOService(
- socket_option_key, socket_option_value,
- [this](int socket_option_key,
- ConsumerContentObjectVerificationFailedCallback *
- *socket_option_value) -> int {
- switch (socket_option_key) {
- case ConsumerCallbacksOptions::VERIFICATION_FAILED:
- *socket_option_value = &verification_failed_callback_;
- break;
- default:
- return SOCKET_OPTION_NOT_GET;
- }
-
- return SOCKET_OPTION_GET;
- });
- }
-
int getSocketOption(int socket_option_key,
- std::shared_ptr<Portal> &socket_option_value) {
+ std::shared_ptr<core::Portal> &socket_option_value) {
switch (socket_option_key) {
case PORTAL:
socket_option_value = portal_;
@@ -781,7 +657,7 @@ class ConsumerSocket : public Socket<BasePortal> {
}
int getSocketOption(int socket_option_key,
- std::shared_ptr<utils::Verifier> &socket_option_value) {
+ std::shared_ptr<auth::Verifier> &socket_option_value) {
switch (socket_option_key) {
case GeneralTransportOptions::VERIFIER:
socket_option_value = verifier_;
@@ -845,7 +721,7 @@ class ConsumerSocket : public Socket<BasePortal> {
// To enforce type check
std::function<int(int, arg2)> func = lambda_func;
int result = SOCKET_OPTION_SET;
- if (transport_protocol_->isRunning()) {
+ if (transport_protocol_ && transport_protocol_->isRunning()) {
std::mutex mtx;
/* Condition variable for the wait */
std::condition_variable cv;
@@ -872,7 +748,6 @@ class ConsumerSocket : public Socket<BasePortal> {
protected:
interface::ConsumerSocket *consumer_interface_;
- std::shared_ptr<Portal> portal_;
utils::EventThread async_downloader_;
// No need to protect from multiple accesses in the async consumer
@@ -900,22 +775,18 @@ class ConsumerSocket : public Socket<BasePortal> {
int rate_estimation_batching_parameter_;
int rate_estimation_choice_;
- bool is_async_;
-
// Verification parameters
- std::shared_ptr<utils::Verifier> verifier_;
+ std::shared_ptr<auth::Verifier> verifier_;
PARCKeyId *key_id_;
std::atomic_bool verify_signature_;
- bool key_content_;
+ bool reset_window_;
ConsumerInterestCallback on_interest_retransmission_;
ConsumerInterestCallback on_interest_output_;
ConsumerInterestCallback on_interest_timeout_;
ConsumerInterestCallback on_interest_satisfied_;
ConsumerContentObjectCallback on_content_object_input_;
- ConsumerContentObjectVerificationCallback on_content_object_verification_;
ConsumerTimerCallback stats_summary_;
- ConsumerContentObjectVerificationFailedCallback verification_failed_callback_;
ReadCallback *read_callback_;
@@ -932,4 +803,4 @@ class ConsumerSocket : public Socket<BasePortal> {
};
} // namespace implementation
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/src/implementation/socket_producer.h b/libtransport/src/implementation/socket_producer.h
index 9ccc59d9e..f511f7743 100644
--- a/libtransport/src/implementation/socket_producer.h
+++ b/libtransport/src/implementation/socket_producer.h
@@ -15,12 +15,12 @@
#pragma once
-#include <hicn/transport/security/signer.h>
-
+#include <hicn/transport/auth/signer.h>
+#include <hicn/transport/utils/event_thread.h>
#include <implementation/socket.h>
-
+#include <protocols/prod_protocol_bytestream.h>
+#include <protocols/prod_protocol_rtc.h>
#include <utils/content_store.h>
-#include <utils/event_thread.h>
#include <utils/suffix_strategy.h>
#include <atomic>
@@ -41,21 +41,17 @@ namespace implementation {
using namespace core;
using namespace interface;
-class ProducerSocket : public Socket<BasePortal>,
- public BasePortal::ProducerCallback {
- static constexpr uint32_t burst_size = 256;
-
- public:
- explicit ProducerSocket(interface::ProducerSocket *producer_socket)
- : producer_interface_(producer_socket),
- portal_(std::make_shared<Portal>(io_service_)),
+class ProducerSocket : public Socket {
+ private:
+ ProducerSocket(interface::ProducerSocket *producer_socket, int protocol,
+ std::shared_ptr<core::Portal> &&portal)
+ : Socket(std::move(portal)),
+ producer_interface_(producer_socket),
data_packet_size_(default_values::content_object_packet_size),
content_object_expiry_time_(default_values::content_object_expiry_time),
- output_buffer_(default_values::producer_socket_output_buffer_size),
async_thread_(),
- registration_status_(REGISTRATION_NOT_ATTEMPTED),
making_manifest_(false),
- hash_algorithm_(utils::CryptoHashType::SHA_256),
+ hash_algorithm_(auth::CryptoHashType::SHA_256),
suffix_strategy_(core::NextSegmentCalculationStrategy::INCREMENTAL),
on_interest_input_(VOID_HANDLER),
on_interest_dropped_input_buffer_(VOID_HANDLER),
@@ -67,15 +63,33 @@ class ProducerSocket : public Socket<BasePortal>,
on_content_object_in_output_buffer_(VOID_HANDLER),
on_content_object_output_(VOID_HANDLER),
on_content_object_evicted_from_output_buffer_(VOID_HANDLER),
- on_content_produced_(VOID_HANDLER) {}
-
- virtual ~ProducerSocket() {
- stop();
- if (listening_thread_.joinable()) {
- listening_thread_.join();
+ on_content_produced_(VOID_HANDLER) {
+ switch (protocol) {
+ case ProductionProtocolAlgorithms::RTC_PROD:
+ production_protocol_ =
+ std::make_unique<protocol::RTCProductionProtocol>(this);
+ break;
+ case ProductionProtocolAlgorithms::BYTE_STREAM:
+ default:
+ production_protocol_ =
+ std::make_unique<protocol::ByteStreamProductionProtocol>(this);
+ break;
}
}
+ public:
+ ProducerSocket(interface::ProducerSocket *producer, int protocol)
+ : ProducerSocket(producer, protocol, std::make_shared<core::Portal>()) {}
+
+ ProducerSocket(interface::ProducerSocket *producer, int protocol,
+ asio::io_service &io_service)
+ : ProducerSocket(producer, protocol,
+ std::make_shared<core::Portal>(io_service)) {
+ is_async_ = true;
+ }
+
+ virtual ~ProducerSocket() {}
+
interface::ProducerSocket *getInterface() {
return producer_interface_;
}
@@ -86,293 +100,10 @@ class ProducerSocket : public Socket<BasePortal>,
void connect() override {
portal_->connect(false);
- listening_thread_ = std::thread(std::bind(&ProducerSocket::listen, this));
- }
-
- bool isRunning() override { return !io_service_.stopped(); };
-
- virtual uint32_t produce(Name content_name, const uint8_t *buffer,
- size_t buffer_size, bool is_last = true,
- uint32_t start_offset = 0) {
- return ProducerSocket::produce(
- content_name, utils::MemBuf::copyBuffer(buffer, buffer_size), is_last,
- start_offset);
- }
-
- virtual uint32_t produce(Name content_name,
- std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last = true, uint32_t start_offset = 0) {
- if (TRANSPORT_EXPECT_FALSE(buffer->length() == 0)) {
- return 0;
- }
-
- // Copy the atomic variables to ensure they keep the same value
- // during the production
- std::size_t data_packet_size = data_packet_size_;
- uint32_t content_object_expiry_time = content_object_expiry_time_;
- utils::CryptoHashType hash_algo = hash_algorithm_;
- bool making_manifest = making_manifest_;
- auto suffix_strategy = utils::SuffixStrategyFactory::getSuffixStrategy(
- suffix_strategy_, start_offset);
- std::shared_ptr<utils::Signer> signer;
- getSocketOption(GeneralTransportOptions::SIGNER, signer);
-
- auto buffer_size = buffer->length();
- int bytes_segmented = 0;
- std::size_t header_size;
- std::size_t manifest_header_size = 0;
- std::size_t signature_length = 0;
- std::uint32_t final_block_number = start_offset;
- uint64_t free_space_for_content = 0;
-
- core::Packet::Format format;
- std::shared_ptr<ContentObjectManifest> manifest;
- bool is_last_manifest = false;
-
- // TODO Manifest may still be used for indexing
- if (making_manifest && !signer) {
- TRANSPORT_LOGD("Making manifests without setting producer identity.");
- }
-
- core::Packet::Format hf_format = core::Packet::Format::HF_UNSPEC;
- core::Packet::Format hf_format_ah = core::Packet::Format::HF_UNSPEC;
- if (content_name.getType() == HNT_CONTIGUOUS_V4 ||
- content_name.getType() == HNT_IOV_V4) {
- hf_format = core::Packet::Format::HF_INET_TCP;
- hf_format_ah = core::Packet::Format::HF_INET_TCP_AH;
- } else if (content_name.getType() == HNT_CONTIGUOUS_V6 ||
- content_name.getType() == HNT_IOV_V6) {
- hf_format = core::Packet::Format::HF_INET6_TCP;
- hf_format_ah = core::Packet::Format::HF_INET6_TCP_AH;
- } else {
- throw errors::RuntimeException("Unknown name format.");
- }
-
- format = hf_format;
- if (making_manifest) {
- manifest_header_size = core::Packet::getHeaderSizeFromFormat(
- signer ? hf_format_ah : hf_format,
- signer ? signer->getSignatureLength() : 0);
- } else if (signer) {
- format = hf_format_ah;
- signature_length = signer->getSignatureLength();
- }
-
- header_size =
- core::Packet::getHeaderSizeFromFormat(format, signature_length);
- free_space_for_content = data_packet_size - header_size;
- uint32_t number_of_segments = uint32_t(
- std::ceil(double(buffer_size) / double(free_space_for_content)));
- if (free_space_for_content * number_of_segments < buffer_size) {
- number_of_segments++;
- }
-
- // TODO allocate space for all the headers
- if (making_manifest) {
- uint32_t segment_in_manifest = static_cast<uint32_t>(
- std::floor(double(data_packet_size - manifest_header_size -
- ContentObjectManifest::getManifestHeaderSize()) /
- ContentObjectManifest::getManifestEntrySize()) -
- 1.0);
- uint32_t number_of_manifests = static_cast<uint32_t>(
- std::ceil(float(number_of_segments) / segment_in_manifest));
- final_block_number += number_of_segments + number_of_manifests - 1;
-
- manifest.reset(ContentObjectManifest::createManifest(
- content_name.setSuffix(suffix_strategy->getNextManifestSuffix()),
- core::ManifestVersion::VERSION_1, core::ManifestType::INLINE_MANIFEST,
- hash_algo, is_last_manifest, content_name, suffix_strategy_,
- signer ? signer->getSignatureLength() : 0));
- manifest->setLifetime(content_object_expiry_time);
-
- if (is_last) {
- manifest->setFinalBlockNumber(final_block_number);
- } else {
- manifest->setFinalBlockNumber(utils::SuffixStrategy::INVALID_SUFFIX);
- }
- }
-
- TRANSPORT_LOGD("--------- START PRODUCE ----------");
- for (unsigned int packaged_segments = 0;
- packaged_segments < number_of_segments; packaged_segments++) {
- if (making_manifest) {
- if (manifest->estimateManifestSize(2) >
- data_packet_size - manifest_header_size) {
- // Send the current manifest
- manifest->encode();
-
- // If identity set, sign manifest
- if (signer) {
- signer->sign(*manifest);
- }
-
- passContentObjectToCallbacks(manifest);
- TRANSPORT_LOGD("Send manifest %u", manifest->getName().getSuffix());
-
- // Send content objects stored in the queue
- while (!content_queue_.empty()) {
- passContentObjectToCallbacks(content_queue_.front());
- TRANSPORT_LOGD("Send content %u",
- content_queue_.front()->getName().getSuffix());
- content_queue_.pop();
- }
-
- // Create new manifest. The reference to the last manifest has been
- // acquired in the passContentObjectToCallbacks function, so we can
- // safely release this reference
- manifest.reset(ContentObjectManifest::createManifest(
- content_name.setSuffix(suffix_strategy->getNextManifestSuffix()),
- core::ManifestVersion::VERSION_1,
- core::ManifestType::INLINE_MANIFEST, hash_algo, is_last_manifest,
- content_name, suffix_strategy_,
- signer ? signer->getSignatureLength() : 0));
-
- manifest->setLifetime(content_object_expiry_time);
- manifest->setFinalBlockNumber(
- is_last ? final_block_number
- : utils::SuffixStrategy::INVALID_SUFFIX);
- }
- }
-
- auto content_suffix = suffix_strategy->getNextContentSuffix();
- auto content_object = std::make_shared<ContentObject>(
- content_name.setSuffix(content_suffix), format);
- content_object->setLifetime(content_object_expiry_time);
-
- auto b = buffer->cloneOne();
- b->trimStart(free_space_for_content * packaged_segments);
- b->trimEnd(b->length());
-
- if (TRANSPORT_EXPECT_FALSE(packaged_segments == number_of_segments - 1)) {
- b->append(buffer_size - bytes_segmented);
- bytes_segmented += (int)(buffer_size - bytes_segmented);
-
- if (is_last && making_manifest) {
- is_last_manifest = true;
- } else if (is_last) {
- content_object->setRst();
- }
-
- } else {
- b->append(free_space_for_content);
- bytes_segmented += (int)(free_space_for_content);
- }
-
- content_object->appendPayload(std::move(b));
-
- if (making_manifest) {
- using namespace std::chrono_literals;
- utils::CryptoHash hash = content_object->computeDigest(hash_algo);
- manifest->addSuffixHash(content_suffix, hash);
- content_queue_.push(content_object);
- } else {
- if (signer) {
- signer->sign(*content_object);
- }
- passContentObjectToCallbacks(content_object);
- TRANSPORT_LOGD("Send content %u",
- content_object->getName().getSuffix());
- }
- }
-
- if (making_manifest) {
- if (is_last_manifest) {
- manifest->setFinalManifest(is_last_manifest);
- }
-
- manifest->encode();
- if (signer) {
- signer->sign(*manifest);
- }
-
- passContentObjectToCallbacks(manifest);
- TRANSPORT_LOGD("Send manifest %u", manifest->getName().getSuffix());
- while (!content_queue_.empty()) {
- passContentObjectToCallbacks(content_queue_.front());
- TRANSPORT_LOGD("Send content %u",
- content_queue_.front()->getName().getSuffix());
- content_queue_.pop();
- }
- }
-
- io_service_.post([this]() {
- std::shared_ptr<ContentObject> co;
- while (object_queue_for_callbacks_.pop(co)) {
- if (on_new_segment_) {
- on_new_segment_(*producer_interface_, *co);
- }
-
- if (on_content_object_to_sign_) {
- on_content_object_to_sign_(*producer_interface_, *co);
- }
-
- if (on_content_object_in_output_buffer_) {
- on_content_object_in_output_buffer_(*producer_interface_, *co);
- }
-
- if (on_content_object_output_) {
- on_content_object_output_(*producer_interface_, *co);
- }
- }
- });
-
- io_service_.dispatch([this, buffer_size]() {
- if (on_content_produced_) {
- on_content_produced_(*producer_interface_,
- std::make_error_code(std::errc(0)), buffer_size);
- }
- });
-
- return suffix_strategy->getTotalCount();
- }
-
- virtual void produce(ContentObject &content_object) {
- io_service_.dispatch([this, &content_object]() {
- if (on_content_object_in_output_buffer_) {
- on_content_object_in_output_buffer_(*producer_interface_,
- content_object);
- }
- });
-
- output_buffer_.insert(std::static_pointer_cast<ContentObject>(
- content_object.shared_from_this()));
-
- io_service_.dispatch([this, &content_object]() {
- if (on_content_object_output_) {
- on_content_object_output_(*producer_interface_, content_object);
- }
- });
-
- portal_->sendContentObject(content_object);
- }
-
- virtual void produce(const uint8_t *buffer, size_t buffer_size) {
- produce(utils::MemBuf::copyBuffer(buffer, buffer_size));
- }
-
- virtual void produce(std::unique_ptr<utils::MemBuf> &&buffer) {
- // This API is meant to be used just with the RTC producer.
- // Here it cannot be used since no name for the content is specified.
- throw errors::NotImplementedException();
+ production_protocol_->start();
}
- virtual void asyncProduce(const Name &suffix, const uint8_t *buf,
- size_t buffer_size, bool is_last = true,
- uint32_t *start_offset = nullptr) {
- if (!async_thread_.stopped()) {
- async_thread_.add([this, suffix, buffer = buf, size = buffer_size,
- is_last, start_offset]() {
- if (start_offset != nullptr) {
- *start_offset = ProducerSocket::produce(suffix, buffer, size, is_last,
- *start_offset);
- } else {
- ProducerSocket::produce(suffix, buffer, size, is_last, 0);
- }
- });
- }
- }
-
- void asyncProduce(const Name &suffix);
+ bool isRunning() override { return !production_protocol_->isRunning(); };
virtual void asyncProduce(Name content_name,
std::unique_ptr<utils::MemBuf> &&buffer,
@@ -380,75 +111,56 @@ class ProducerSocket : public Socket<BasePortal>,
uint32_t **last_segment = nullptr) {
if (!async_thread_.stopped()) {
auto a = buffer.release();
- async_thread_.add(
- [this, content_name, a, is_last, offset, last_segment]() {
- auto buf = std::unique_ptr<utils::MemBuf>(a);
- if (last_segment != NULL) {
- **last_segment =
- offset + ProducerSocket::produce(content_name, std::move(buf),
- is_last, offset);
- } else {
- ProducerSocket::produce(content_name, std::move(buf), is_last,
- offset);
- }
- });
- }
- }
-
- virtual void asyncProduce(ContentObject &content_object) {
- if (!async_thread_.stopped()) {
- auto co_ptr = std::static_pointer_cast<ContentObject>(
- content_object.shared_from_this());
- async_thread_.add([this, content_object = std::move(co_ptr)]() {
- ProducerSocket::produce(*content_object);
+ async_thread_.add([this, content_name, a, is_last, offset,
+ last_segment]() {
+ auto buf = std::unique_ptr<utils::MemBuf>(a);
+ if (last_segment != NULL) {
+ **last_segment = offset + produceStream(content_name, std::move(buf),
+ is_last, offset);
+ } else {
+ produceStream(content_name, std::move(buf), is_last, offset);
+ }
});
}
}
- virtual void registerPrefix(const Prefix &producer_namespace) {
- served_namespaces_.push_back(producer_namespace);
+ virtual uint32_t produceStream(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer,
+ bool is_last = true,
+ uint32_t start_offset = 0) {
+ return production_protocol_->produceStream(content_name, std::move(buffer),
+ is_last, start_offset);
}
- void serveForever() {
- if (listening_thread_.joinable()) {
- listening_thread_.join();
- }
+ virtual uint32_t produceStream(const Name &content_name,
+ const uint8_t *buffer, size_t buffer_size,
+ bool is_last = true,
+ uint32_t start_offset = 0) {
+ return production_protocol_->produceStream(
+ content_name, buffer, buffer_size, is_last, start_offset);
}
- void stop() { portal_->stopEventsLoop(); }
-
- asio::io_service &getIoService() override { return portal_->getIoService(); };
-
- virtual void onInterest(Interest &interest) {
- if (on_interest_input_) {
- on_interest_input_(*producer_interface_, interest);
- }
-
- const std::shared_ptr<ContentObject> content_object =
- output_buffer_.find(interest);
-
- if (content_object) {
- if (on_interest_satisfied_output_buffer_) {
- on_interest_satisfied_output_buffer_(*producer_interface_, interest);
- }
+ virtual uint32_t produceDatagram(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer) {
+ return production_protocol_->produceDatagram(content_name,
+ std::move(buffer));
+ }
- if (on_content_object_output_) {
- on_content_object_output_(*producer_interface_, *content_object);
- }
+ virtual uint32_t produceDatagram(const Name &content_name,
+ const uint8_t *buffer, size_t buffer_size) {
+ return production_protocol_->produceDatagram(content_name, buffer,
+ buffer_size);
+ }
- portal_->sendContentObject(*content_object);
- } else {
- if (on_interest_process_) {
- on_interest_process_(*producer_interface_, interest);
- }
- }
+ void produce(ContentObject &content_object) {
+ production_protocol_->produce(content_object);
}
- virtual void onInterest(Interest::Ptr &&interest) override {
- onInterest(*interest);
- };
+ void registerPrefix(const Prefix &producer_namespace) {
+ production_protocol_->registerNamespaceWithNetwork(producer_namespace);
+ }
- virtual void onError(std::error_code ec) override {}
+ void stop() { production_protocol_->stop(); }
virtual int setSocketOption(int socket_option_key,
uint32_t socket_option_value) {
@@ -461,7 +173,7 @@ class ProducerSocket : public Socket<BasePortal>,
break;
case GeneralTransportOptions::OUTPUT_BUFFER_SIZE:
- output_buffer_.setLimit(socket_option_value);
+ production_protocol_->setOutputBufferSize(socket_option_value);
break;
case GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME:
@@ -532,6 +244,12 @@ class ProducerSocket : public Socket<BasePortal>,
break;
}
+ case ProducerCallbacksOptions::CONTENT_OBJECT_TO_SIGN:
+ if (socket_option_value == VOID_HANDLER) {
+ on_content_object_to_sign_ = VOID_HANDLER;
+ break;
+ }
+
default:
return SOCKET_OPTION_NOT_SET;
}
@@ -558,19 +276,6 @@ class ProducerSocket : public Socket<BasePortal>,
return SOCKET_OPTION_NOT_SET;
}
- virtual int setSocketOption(int socket_option_key,
- std::list<Prefix> socket_option_value) {
- switch (socket_option_key) {
- case GeneralTransportOptions::NETWORK_NAME:
- served_namespaces_ = socket_option_value;
- break;
- default:
- return SOCKET_OPTION_NOT_SET;
- }
-
- return SOCKET_OPTION_SET;
- }
-
virtual int setSocketOption(
int socket_option_key,
interface::ProducerContentObjectCallback socket_option_value) {
@@ -593,6 +298,10 @@ class ProducerSocket : public Socket<BasePortal>,
on_content_object_output_ = socket_option_value;
break;
+ case ProducerCallbacksOptions::CONTENT_OBJECT_TO_SIGN:
+ on_content_object_to_sign_ = socket_option_value;
+ break;
+
default:
return SOCKET_OPTION_NOT_SET;
}
@@ -662,7 +371,7 @@ class ProducerSocket : public Socket<BasePortal>,
}
virtual int setSocketOption(int socket_option_key,
- utils::CryptoHashType socket_option_value) {
+ auth::CryptoHashType socket_option_value) {
switch (socket_option_key) {
case GeneralTransportOptions::HASH_ALGORITHM:
hash_algorithm_ = socket_option_value;
@@ -674,11 +383,12 @@ class ProducerSocket : public Socket<BasePortal>,
return SOCKET_OPTION_SET;
}
- virtual int setSocketOption(int socket_option_key,
- utils::CryptoSuite socket_option_value) {
+ virtual int setSocketOption(
+ int socket_option_key,
+ core::NextSegmentCalculationStrategy socket_option_value) {
switch (socket_option_key) {
- case GeneralTransportOptions::CRYPTO_SUITE:
- crypto_suite_ = socket_option_value;
+ case GeneralTransportOptions::SUFFIX_STRATEGY:
+ suffix_strategy_ = socket_option_value;
break;
default:
return SOCKET_OPTION_NOT_SET;
@@ -689,7 +399,7 @@ class ProducerSocket : public Socket<BasePortal>,
virtual int setSocketOption(
int socket_option_key,
- const std::shared_ptr<utils::Signer> &socket_option_value) {
+ const std::shared_ptr<auth::Signer> &socket_option_value) {
switch (socket_option_key) {
case GeneralTransportOptions::SIGNER: {
utils::SpinLock::Acquire locked(signer_lock_);
@@ -707,7 +417,7 @@ class ProducerSocket : public Socket<BasePortal>,
uint32_t &socket_option_value) {
switch (socket_option_key) {
case GeneralTransportOptions::OUTPUT_BUFFER_SIZE:
- socket_option_value = (uint32_t)output_buffer_.getLimit();
+ socket_option_value = (uint32_t)production_protocol_->getOutputBufferSize();
break;
case GeneralTransportOptions::DATA_PACKET_SIZE:
@@ -732,18 +442,8 @@ class ProducerSocket : public Socket<BasePortal>,
socket_option_value = making_manifest_;
break;
- default:
- return SOCKET_OPTION_NOT_GET;
- }
-
- return SOCKET_OPTION_GET;
- }
-
- virtual int getSocketOption(int socket_option_key,
- std::list<Prefix> &socket_option_value) {
- switch (socket_option_key) {
- case GeneralTransportOptions::NETWORK_NAME:
- socket_option_value = served_namespaces_;
+ case GeneralTransportOptions::ASYNC_MODE:
+ socket_option_value = is_async_;
break;
default:
@@ -775,6 +475,10 @@ class ProducerSocket : public Socket<BasePortal>,
*socket_option_value = &on_content_object_output_;
break;
+ case ProducerCallbacksOptions::CONTENT_OBJECT_TO_SIGN:
+ *socket_option_value = &on_content_object_to_sign_;
+ break;
+
default:
return SOCKET_OPTION_NOT_GET;
}
@@ -827,11 +531,11 @@ class ProducerSocket : public Socket<BasePortal>,
*socket_option_value = &on_interest_inserted_input_buffer_;
break;
- case CACHE_HIT:
+ case ProducerCallbacksOptions::CACHE_HIT:
*socket_option_value = &on_interest_satisfied_output_buffer_;
break;
- case CACHE_MISS:
+ case ProducerCallbacksOptions::CACHE_MISS:
*socket_option_value = &on_interest_process_;
break;
@@ -843,8 +547,9 @@ class ProducerSocket : public Socket<BasePortal>,
});
}
- virtual int getSocketOption(int socket_option_key,
- std::shared_ptr<Portal> &socket_option_value) {
+ virtual int getSocketOption(
+ int socket_option_key,
+ std::shared_ptr<core::Portal> &socket_option_value) {
switch (socket_option_key) {
case PORTAL:
socket_option_value = portal_;
@@ -858,7 +563,7 @@ class ProducerSocket : public Socket<BasePortal>,
}
virtual int getSocketOption(int socket_option_key,
- utils::CryptoHashType &socket_option_value) {
+ auth::CryptoHashType &socket_option_value) {
switch (socket_option_key) {
case GeneralTransportOptions::HASH_ALGORITHM:
socket_option_value = hash_algorithm_;
@@ -870,22 +575,22 @@ class ProducerSocket : public Socket<BasePortal>,
return SOCKET_OPTION_GET;
}
- virtual int getSocketOption(int socket_option_key,
- utils::CryptoSuite &socket_option_value) {
+ virtual int getSocketOption(
+ int socket_option_key,
+ core::NextSegmentCalculationStrategy &socket_option_value) {
switch (socket_option_key) {
- case GeneralTransportOptions::HASH_ALGORITHM:
- socket_option_value = crypto_suite_;
+ case GeneralTransportOptions::SUFFIX_STRATEGY:
+ socket_option_value = suffix_strategy_;
break;
default:
return SOCKET_OPTION_NOT_GET;
}
-
return SOCKET_OPTION_GET;
}
virtual int getSocketOption(
int socket_option_key,
- std::shared_ptr<utils::Signer> &socket_option_value) {
+ std::shared_ptr<auth::Signer> &socket_option_value) {
switch (socket_option_key) {
case GeneralTransportOptions::SIGNER: {
utils::SpinLock::Acquire locked(signer_lock_);
@@ -906,19 +611,21 @@ class ProducerSocket : public Socket<BasePortal>,
// If the thread calling lambda_func is not the same of io_service, this
// function reschedule the function on it
template <typename Lambda, typename arg2>
- int rescheduleOnIOService(int socket_option_key, arg2 socket_option_value,
- Lambda lambda_func) {
+ int rescheduleOnIOServiceWithReference(int socket_option_key,
+ arg2 &socket_option_value,
+ Lambda lambda_func) {
// To enforce type check
- std::function<int(int, arg2)> func = lambda_func;
+ std::function<int(int, arg2 &)> func = lambda_func;
int result = SOCKET_OPTION_SET;
- if (listening_thread_.joinable() &&
- std::this_thread::get_id() != listening_thread_.get_id()) {
+ if (production_protocol_ && production_protocol_->isRunning()) {
std::mutex mtx;
/* Condition variable for the wait */
std::condition_variable cv;
+
bool done = false;
- io_service_.dispatch([&socket_option_key, &socket_option_value, &mtx, &cv,
- &result, &done, &func]() {
+ portal_->getIoService().dispatch([&socket_option_key,
+ &socket_option_value, &mtx, &cv,
+ &result, &done, &func]() {
std::unique_lock<std::mutex> lck(mtx);
done = true;
result = func(socket_option_key, socket_option_value);
@@ -938,29 +645,28 @@ class ProducerSocket : public Socket<BasePortal>,
// If the thread calling lambda_func is not the same of io_service, this
// function reschedule the function on it
template <typename Lambda, typename arg2>
- int rescheduleOnIOServiceWithReference(int socket_option_key,
- arg2 &socket_option_value,
- Lambda lambda_func) {
+ int rescheduleOnIOService(int socket_option_key, arg2 socket_option_value,
+ Lambda lambda_func) {
// To enforce type check
- std::function<int(int, arg2 &)> func = lambda_func;
+ std::function<int(int, arg2)> func = lambda_func;
int result = SOCKET_OPTION_SET;
- if (listening_thread_.joinable() &&
- std::this_thread::get_id() != this->listening_thread_.get_id()) {
+ if (production_protocol_ && production_protocol_->isRunning()) {
std::mutex mtx;
/* Condition variable for the wait */
std::condition_variable cv;
- std::unique_lock<std::mutex> lck(mtx);
bool done = false;
- io_service_.dispatch([&socket_option_key, &socket_option_value, &mtx, &cv,
- &result, &done, &func]() {
+ portal_->getIoService().dispatch([&socket_option_key,
+ &socket_option_value, &mtx, &cv,
+ &result, &done, &func]() {
std::unique_lock<std::mutex> lck(mtx);
done = true;
result = func(socket_option_key, socket_option_value);
-
- if (!done) {
- cv.wait(lck);
- }
+ cv.notify_all();
});
+ std::unique_lock<std::mutex> lck(mtx);
+ if (!done) {
+ cv.wait(lck);
+ }
} else {
result = func(socket_option_key, socket_option_value);
}
@@ -971,39 +677,20 @@ class ProducerSocket : public Socket<BasePortal>,
// Threads
protected:
interface::ProducerSocket *producer_interface_;
- std::thread listening_thread_;
asio::io_service io_service_;
- std::shared_ptr<Portal> portal_;
std::atomic<size_t> data_packet_size_;
- std::list<Prefix>
- served_namespaces_; // No need to be threadsafe, this is always modified
- // by the application thread
std::atomic<uint32_t> content_object_expiry_time_;
- utils::CircularFifo<std::shared_ptr<ContentObject>, 2048>
- object_queue_for_callbacks_;
-
- // buffers
- // ContentStore is thread-safe
- utils::ContentStore output_buffer_;
-
utils::EventThread async_thread_;
- int registration_status_;
std::atomic<bool> making_manifest_;
-
- // map for storing sequence numbers for several calls of the publish
- // function
- std::unordered_map<Name, std::unordered_map<int, uint32_t>> seq_number_map_;
-
- std::atomic<utils::CryptoHashType> hash_algorithm_;
- std::atomic<utils::CryptoSuite> crypto_suite_;
+ std::atomic<auth::CryptoHashType> hash_algorithm_;
+ std::atomic<auth::CryptoSuite> crypto_suite_;
utils::SpinLock signer_lock_;
- std::shared_ptr<utils::Signer> signer_;
+ std::shared_ptr<auth::Signer> signer_;
core::NextSegmentCalculationStrategy suffix_strategy_;
- // While manifests are being built, contents are stored in a queue
- std::queue<std::shared_ptr<ContentObject>> content_queue_;
+ std::unique_ptr<protocol::ProductionProtocol> production_protocol_;
// callbacks
ProducerInterestCallback on_interest_input_;
@@ -1019,63 +706,6 @@ class ProducerSocket : public Socket<BasePortal>,
ProducerContentObjectCallback on_content_object_evicted_from_output_buffer_;
ProducerContentCallback on_content_produced_;
-
- private:
- void listen() {
- bool first = true;
-
- for (core::Prefix &producer_namespace : served_namespaces_) {
- if (first) {
- core::BindConfig bind_config(producer_namespace, 1000);
- portal_->bind(bind_config);
- portal_->setProducerCallback(this);
- first = !first;
- } else {
- portal_->registerRoute(producer_namespace);
- }
- }
-
- portal_->runEventsLoop();
- }
-
- void scheduleSendBurst() {
- io_service_.post([this]() {
- std::shared_ptr<ContentObject> co;
-
- for (uint32_t i = 0; i < burst_size; i++) {
- if (object_queue_for_callbacks_.pop(co)) {
- if (on_new_segment_) {
- on_new_segment_(*producer_interface_, *co);
- }
-
- if (on_content_object_to_sign_) {
- on_content_object_to_sign_(*producer_interface_, *co);
- }
-
- if (on_content_object_in_output_buffer_) {
- on_content_object_in_output_buffer_(*producer_interface_, *co);
- }
-
- if (on_content_object_output_) {
- on_content_object_output_(*producer_interface_, *co);
- }
- } else {
- break;
- }
- }
- });
- }
-
- void passContentObjectToCallbacks(
- const std::shared_ptr<ContentObject> &content_object) {
- output_buffer_.insert(content_object);
- portal_->sendContentObject(*content_object);
- object_queue_for_callbacks_.push(std::move(content_object));
-
- if (object_queue_for_callbacks_.size() >= burst_size) {
- scheduleSendBurst();
- }
- }
};
} // namespace implementation
diff --git a/libtransport/src/implementation/tls_rtc_socket_producer.cc b/libtransport/src/implementation/tls_rtc_socket_producer.cc
index 3b3152993..9a62c8683 100644
--- a/libtransport/src/implementation/tls_rtc_socket_producer.cc
+++ b/libtransport/src/implementation/tls_rtc_socket_producer.cc
@@ -15,10 +15,8 @@
#include <hicn/transport/core/interest.h>
#include <hicn/transport/interfaces/p2psecure_socket_producer.h>
-
#include <implementation/p2psecure_socket_producer.h>
#include <implementation/tls_rtc_socket_producer.h>
-
#include <openssl/bio.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
@@ -53,7 +51,7 @@ int TLSRTCProducerSocket::readOld(BIO *b, char *buf, int size) {
(socket->cv_).wait(lck);
}
- utils::MemBuf *membuf = socket->packet_->next();
+ utils::MemBuf *membuf = socket->handshake_packet_->next();
int size_to_read;
if ((int)membuf->length() > size) {
@@ -91,10 +89,10 @@ int TLSRTCProducerSocket::writeOld(BIO *b, const char *buf, int num) {
TLSRTCProducerSocket *socket;
socket = (TLSRTCProducerSocket *)BIO_get_data(b);
- if ((SSL_in_before(socket->ssl_) || SSL_in_init(socket->ssl_)) &&
- socket->first_) {
- socket->tls_chunks_--;
+ if (socket->getHandshakeState() != SERVER_FINISHED && socket->first_) {
bool making_manifest = socket->parent_->making_manifest_;
+
+ socket->tls_chunks_--;
socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
false);
socket->parent_->ProducerSocket::produce(
@@ -107,13 +105,17 @@ int TLSRTCProducerSocket::writeOld(BIO *b, const char *buf, int num) {
std::unique_ptr<utils::MemBuf> mbuf =
utils::MemBuf::copyBuffer(buf, (std::size_t)num, 0, 0);
auto a = mbuf.release();
+
socket->async_thread_.add([socket = socket, a]() {
socket->to_call_oncontentproduced_--;
auto mbuf = std::unique_ptr<utils::MemBuf>(a);
+
socket->RTCProducerSocket::produce(std::move(mbuf));
+
ProducerContentCallback on_content_produced_application;
socket->getSocketOption(ProducerCallbacksOptions::CONTENT_PRODUCED,
on_content_produced_application);
+
if (socket->to_call_oncontentproduced_ == 0 &&
on_content_produced_application) {
on_content_produced_application(
@@ -144,24 +146,28 @@ TLSRTCProducerSocket::TLSRTCProducerSocket(
}
void TLSRTCProducerSocket::accept() {
- if (SSL_in_before(ssl_) || SSL_in_init(ssl_)) {
+ HandshakeState handshake_state = getHandshakeState();
+
+ if (handshake_state == UNINITIATED || handshake_state == CLIENT_HELLO) {
tls_chunks_ = 1;
int result = SSL_accept(ssl_);
+
if (result != 1)
throw errors::RuntimeException("Unable to perform client handshake");
}
TRANSPORT_LOGD("Handshake performed!");
- parent_->list_secure_rtc_producers.push_front(
- std::move(parent_->map_secure_rtc_producers[handshake_name_]));
- parent_->map_secure_rtc_producers.erase(handshake_name_);
+
+ parent_->list_producers.push_front(
+ std::move(parent_->map_producers[handshake_name_]));
+ parent_->map_producers.erase(handshake_name_);
ProducerInterestCallback on_interest_process_decrypted;
getSocketOption(ProducerCallbacksOptions::CACHE_MISS,
on_interest_process_decrypted);
if (on_interest_process_decrypted) {
- Interest inter(std::move(packet_));
+ Interest inter(std::move(handshake_packet_));
on_interest_process_decrypted(
(transport::interface::ProducerSocket &)(*getInterface()), inter);
}
@@ -181,7 +187,9 @@ int TLSRTCProducerSocket::async_accept() {
}
void TLSRTCProducerSocket::produce(std::unique_ptr<utils::MemBuf> &&buffer) {
- if (SSL_in_before(ssl_) || SSL_in_init(ssl_)) {
+ HandshakeState handshake_state = getHandshakeState();
+
+ if (handshake_state != SERVER_FINISHED) {
throw errors::RuntimeException(
"New handshake on the same P2P secure producer socket not supported");
}
@@ -197,5 +205,4 @@ void TLSRTCProducerSocket::produce(std::unique_ptr<utils::MemBuf> &&buffer) {
}
} // namespace implementation
-
} // namespace transport
diff --git a/libtransport/src/implementation/tls_rtc_socket_producer.h b/libtransport/src/implementation/tls_rtc_socket_producer.h
index 685c91244..92c657afc 100644
--- a/libtransport/src/implementation/tls_rtc_socket_producer.h
+++ b/libtransport/src/implementation/tls_rtc_socket_producer.h
@@ -15,7 +15,6 @@
#pragma once
-#include <implementation/rtc_socket_producer.h>
#include <implementation/tls_socket_producer.h>
namespace transport {
@@ -23,8 +22,7 @@ namespace implementation {
class P2PSecureProducerSocket;
-class TLSRTCProducerSocket : public RTCProducerSocket,
- public TLSProducerSocket {
+class TLSRTCProducerSocket : public TLSProducerSocket {
friend class P2PSecureProducerSocket;
public:
@@ -34,7 +32,8 @@ class TLSRTCProducerSocket : public RTCProducerSocket,
~TLSRTCProducerSocket() = default;
- void produce(std::unique_ptr<utils::MemBuf> &&buffer) override;
+ uint32_t produceDatagram(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer) override;
void accept() override;
diff --git a/libtransport/src/implementation/tls_socket_consumer.cc b/libtransport/src/implementation/tls_socket_consumer.cc
index 95b287aa6..65472b41d 100644
--- a/libtransport/src/implementation/tls_socket_consumer.cc
+++ b/libtransport/src/implementation/tls_socket_consumer.cc
@@ -14,7 +14,6 @@
*/
#include <implementation/tls_socket_consumer.h>
-
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/tls1.h>
@@ -46,11 +45,13 @@ int readOldTLS(BIO *b, char *buf, int size) {
socket->network_name_.setSuffix(socket->random_suffix_);
socket->ConsumerSocket::asyncConsume(socket->network_name_);
}
+
if (!socket->something_to_read_) socket->cv_.wait(lck);
}
size_t size_to_read, read;
size_t chain_size = socket->head_->length();
+
if (socket->head_->isChained())
chain_size = socket->head_->computeChainDataLength();
@@ -74,7 +75,7 @@ int readOldTLS(BIO *b, char *buf, int size) {
}
}
- return read;
+ return (int)read;
}
/* Return the number of read bytes in readbytes */
@@ -101,6 +102,7 @@ int writeOldTLS(BIO *b, const char *buf, int num) {
socket = (TLSConsumerSocket *)BIO_get_data(b);
socket->payload_ = utils::MemBuf::copyBuffer(buf, num);
+
socket->ConsumerSocket::setSocketOption(
ConsumerCallbacksOptions::INTEREST_OUTPUT,
(ConsumerInterestCallback)std::bind(
@@ -134,7 +136,6 @@ TLSConsumerSocket::TLSConsumerSocket(interface::ConsumerSocket *consumer_socket,
int protocol, SSL *ssl)
: ConsumerSocket(consumer_socket, protocol),
name_(),
- buf_pool_(),
decrypted_content_(),
payload_(),
head_(),
@@ -176,12 +177,6 @@ TLSConsumerSocket::TLSConsumerSocket(interface::ConsumerSocket *consumer_socket,
BIO_set_data(bio, this);
SSL_set_bio(ssl_, bio, bio);
- ConsumerSocket::getSocketOption(MAX_WINDOW_SIZE, old_max_win_);
- ConsumerSocket::setSocketOption(MAX_WINDOW_SIZE, (double)1.0);
-
- ConsumerSocket::getSocketOption(CURRENT_WINDOW_SIZE, old_current_win_);
- ConsumerSocket::setSocketOption(CURRENT_WINDOW_SIZE, (double)1.0);
-
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(
1, std::numeric_limits<uint32_t>::max());
@@ -191,10 +186,8 @@ TLSConsumerSocket::TLSConsumerSocket(interface::ConsumerSocket *consumer_socket,
this);
};
-/*
- * The producer interface is not owned by the application, so is TLSSocket task
- * to deallocate the memory
- */
+/* The producer interface is not owned by the application, so is TLSSocket task
+ * to deallocate the memory */
TLSConsumerSocket::~TLSConsumerSocket() { delete consumer_interface_; }
int TLSConsumerSocket::consume(const Name &name,
@@ -228,22 +221,16 @@ int TLSConsumerSocket::download_content(const Name &name) {
something_to_read_ = false;
content_downloaded_ = false;
- decrypted_content_ = utils::MemBuf::createCombined(SSL3_RT_MAX_PLAIN_LENGTH);
- uint8_t *buf = decrypted_content_->writableData();
- size_t size = 0;
+ std::size_t max_buffer_size = read_callback_decrypted_->maxBufferSize();
+ std::size_t buffer_size =
+ read_callback_decrypted_->maxBufferSize() + SSL3_RT_MAX_PLAIN_LENGTH;
+ decrypted_content_ = utils::MemBuf::createCombined(buffer_size);
int result = -1;
+ std::size_t size = 0;
while (!content_downloaded_ || something_to_read_) {
- if (decrypted_content_->tailroom() < SSL3_RT_MAX_PLAIN_LENGTH) {
- decrypted_content_->appendChain(
- utils::MemBuf::createCombined(SSL3_RT_MAX_PLAIN_LENGTH));
- // decrypted_content_->computeChainDataLength();
- buf = decrypted_content_->prev()->writableData();
- } else {
- buf = decrypted_content_->writableTail();
- }
-
- result = SSL_read(this->ssl_, buf, SSL3_RT_MAX_PLAIN_LENGTH);
+ result = SSL_read(this->ssl_, decrypted_content_->writableTail(),
+ SSL3_RT_MAX_PLAIN_LENGTH);
/* SSL_read returns the data only if there were SSL3_RT_MAX_PLAIN_LENGTH of
* the data has been fully downloaded */
@@ -253,20 +240,20 @@ int TLSConsumerSocket::download_content(const Name &name) {
if (result >= 0) {
size += result;
- decrypted_content_->prepend(result);
- } else
+ decrypted_content_->append(result);
+ } else {
throw errors::RuntimeException("Unable to download content");
+ }
- if (size >= read_callback_decrypted_->maxBufferSize()) {
+ if (decrypted_content_->length() >= max_buffer_size) {
if (read_callback_decrypted_->isBufferMovable()) {
- // No need to perform an additional copy. The whole buffer will be
- // tranferred to the application.
-
+ /* No need to perform an additional copy. The whole buffer will be
+ * tranferred to the application. */
read_callback_decrypted_->readBufferAvailable(
std::move(decrypted_content_));
- decrypted_content_ = utils::MemBuf::create(SSL3_RT_MAX_PLAIN_LENGTH);
+ decrypted_content_ = utils::MemBuf::create(buffer_size);
} else {
- // The buffer will be copied into the application-provided buffer
+ /* The buffer will be copied into the application-provided buffer */
uint8_t *buffer;
std::size_t length;
std::size_t total_length = decrypted_content_->length();
@@ -316,10 +303,7 @@ int TLSConsumerSocket::asyncConsume(const Name &name) {
}
if (!async_downloader_tls_.stopped()) {
- async_downloader_tls_.add([this, name]() {
- is_async_ = true;
- download_content(name);
- });
+ async_downloader_tls_.add([this, name]() { download_content(name); });
}
return CONSUMER_RUNNING;
@@ -358,6 +342,7 @@ size_t TLSConsumerSocket::maxBufferSize() const {
void TLSConsumerSocket::readBufferAvailable(
std::unique_ptr<utils::MemBuf> &&buffer) noexcept {
std::unique_lock<std::mutex> lck(this->mtx_);
+
if (head_) {
head_->prependChain(std::move(buffer));
} else {
@@ -380,5 +365,4 @@ void TLSConsumerSocket::readSuccess(std::size_t total_size) noexcept {
bool TLSConsumerSocket::isBufferMovable() noexcept { return true; }
} // namespace implementation
-
} // namespace transport
diff --git a/libtransport/src/implementation/tls_socket_consumer.h b/libtransport/src/implementation/tls_socket_consumer.h
index 2e88dc47e..be08ec47d 100644
--- a/libtransport/src/implementation/tls_socket_consumer.h
+++ b/libtransport/src/implementation/tls_socket_consumer.h
@@ -16,9 +16,7 @@
#pragma once
#include <hicn/transport/interfaces/socket_consumer.h>
-
#include <implementation/socket_consumer.h>
-
#include <openssl/ssl.h>
namespace transport {
@@ -69,42 +67,24 @@ class TLSConsumerSocket : public ConsumerSocket,
private:
Name name_;
-
/* SSL handle */
SSL *ssl_;
SSL_CTX *ctx_;
-
/* Chain of MemBuf to be used as a temporary buffer to pass descypted data
* from the underlying layer to the application */
- utils::ObjectPool<utils::MemBuf> buf_pool_;
std::unique_ptr<utils::MemBuf> decrypted_content_;
-
- /* Chain of MemBuf holding the payload to be written into interest or data
- */
+ /* Chain of MemBuf holding the payload to be written into interest or data */
std::unique_ptr<utils::MemBuf> payload_;
-
/* Chain of MemBuf holding the data retrieved from the underlying layer */
std::unique_ptr<utils::MemBuf> head_;
-
bool something_to_read_;
-
bool content_downloaded_;
-
- double old_max_win_;
-
- double old_current_win_;
-
uint32_t random_suffix_;
-
Prefix producer_namespace_;
-
interface::ConsumerSocket::ReadCallback *read_callback_decrypted_;
-
std::mutex mtx_;
-
/* Condition variable for the wait */
std::condition_variable cv_;
-
utils::EventThread async_downloader_tls_;
void setInterestPayload(interface::ConsumerSocket &c,
@@ -123,11 +103,11 @@ class TLSConsumerSocket : public ConsumerSocket,
virtual void readError(const std::error_code ec) noexcept override;
virtual void readSuccess(std::size_t total_size) noexcept override;
+
virtual bool isBufferMovable() noexcept override;
int download_content(const Name &name);
};
} // namespace implementation
-
-} // end namespace transport \ No newline at end of file
+} // end namespace transport
diff --git a/libtransport/src/implementation/tls_socket_producer.cc b/libtransport/src/implementation/tls_socket_producer.cc
index 9a5b94a1c..dd92e58cf 100644
--- a/libtransport/src/implementation/tls_socket_producer.cc
+++ b/libtransport/src/implementation/tls_socket_producer.cc
@@ -14,10 +14,8 @@
*/
#include <hicn/transport/interfaces/socket_producer.h>
-
#include <implementation/p2psecure_socket_producer.h>
#include <implementation/tls_socket_producer.h>
-
#include <openssl/bio.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
@@ -48,22 +46,25 @@ int TLSProducerSocket::readOld(BIO *b, char *buf, int size) {
TLSProducerSocket *socket;
socket = (TLSProducerSocket *)BIO_get_data(b);
- /* take a lock on the mutex. It will be unlocked by */
std::unique_lock<std::mutex> lck(socket->mtx_);
+
+ TRANSPORT_LOGD("Start wait on the CV.");
+
if (!socket->something_to_read_) {
(socket->cv_).wait(lck);
}
- /* Either there already is something to read, or the thread has been waken up
- */
- /* must return the payload in the interest */
+ TRANSPORT_LOGD("CV unlocked.");
- utils::MemBuf *membuf = socket->packet_->next();
+ /* Either there already is something to read, or the thread has been waken up.
+ * We must return the payload in the interest anyway */
+ utils::MemBuf *membuf = socket->handshake_packet_->next();
int size_to_read;
+
if ((int)membuf->length() > size) {
size_to_read = size;
} else {
- size_to_read = membuf->length();
+ size_to_read = (int)membuf->length();
socket->something_to_read_ = false;
}
@@ -97,14 +98,14 @@ int TLSProducerSocket::writeOld(BIO *b, const char *buf, int num) {
TLSProducerSocket *socket;
socket = (TLSProducerSocket *)BIO_get_data(b);
- if ((SSL_in_before(socket->ssl_) || SSL_in_init(socket->ssl_)) &&
- socket->first_) {
+ if (socket->getHandshakeState() != SERVER_FINISHED && socket->first_) {
+ bool making_manifest = socket->parent_->making_manifest_;
+
//! socket->tls_chunks_ corresponds to is_last
socket->tls_chunks_--;
- bool making_manifest = socket->parent_->making_manifest_;
socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
false);
- socket->parent_->ProducerSocket::produce(
+ socket->parent_->ProducerSocket::produceStream(
socket->name_, (const uint8_t *)buf, num, socket->tls_chunks_ == 0,
socket->last_segment_);
socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
@@ -116,20 +117,25 @@ int TLSProducerSocket::writeOld(BIO *b, const char *buf, int num) {
std::unique_ptr<utils::MemBuf> mbuf =
utils::MemBuf::copyBuffer(buf, (std::size_t)num, 0, 0);
auto a = mbuf.release();
+
socket->async_thread_.add([socket = socket, a]() {
+ auto mbuf = std::unique_ptr<utils::MemBuf>(a);
+
socket->tls_chunks_--;
socket->to_call_oncontentproduced_--;
- auto mbuf = std::unique_ptr<utils::MemBuf>(a);
- socket->last_segment_ += socket->ProducerSocket::produce(
+
+ socket->last_segment_ += socket->ProducerSocket::produceStream(
socket->name_, std::move(mbuf), socket->tls_chunks_ == 0,
socket->last_segment_);
- ProducerContentCallback on_content_produced_application;
+
+ ProducerContentCallback *on_content_produced_application;
socket->getSocketOption(ProducerCallbacksOptions::CONTENT_PRODUCED,
- on_content_produced_application);
+ &on_content_produced_application);
+
if (socket->to_call_oncontentproduced_ == 0 &&
on_content_produced_application) {
- on_content_produced_application(*socket->getInterface(),
- std::error_code(), 0);
+ on_content_produced_application->operator()(*socket->getInterface(),
+ std::error_code(), 0);
}
});
}
@@ -140,12 +146,15 @@ int TLSProducerSocket::writeOld(BIO *b, const char *buf, int num) {
TLSProducerSocket::TLSProducerSocket(interface::ProducerSocket *producer_socket,
P2PSecureProducerSocket *parent,
const Name &handshake_name)
- : ProducerSocket(producer_socket),
+ : ProducerSocket(producer_socket,
+ ProductionProtocolAlgorithms::BYTE_STREAM),
on_content_produced_application_(),
mtx_(),
cv_(),
- something_to_read_(),
+ something_to_read_(false),
+ handshake_state_(UNINITIATED),
name_(),
+ handshake_packet_(),
last_segment_(0),
parent_(parent),
first_(true),
@@ -157,9 +166,7 @@ TLSProducerSocket::TLSProducerSocket(interface::ProducerSocket *producer_socket,
const SSL_METHOD *meth = TLS_server_method();
ctx_ = SSL_CTX_new(meth);
- /*
- * Setup SSL context (identity and parameter to use TLS 1.3)
- */
+ /* Setup SSL context (identity and parameter to use TLS 1.3) */
SSL_CTX_use_certificate(ctx_, parent->cert_509_);
SSL_CTX_use_PrivateKey(ctx_, parent->pkey_rsa_);
@@ -167,6 +174,7 @@ TLSProducerSocket::TLSProducerSocket(interface::ProducerSocket *producer_socket,
SSL_CTX_set_ciphersuites(ctx_,
"TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_"
"SHA256:TLS_AES_128_GCM_SHA256");
+
if (result != 1) {
throw errors::RuntimeException(
"Unable to set cipher list on TLS subsystem. Aborting.");
@@ -184,10 +192,9 @@ TLSProducerSocket::TLSProducerSocket(interface::ProducerSocket *producer_socket,
this, TLSProducerSocket::parseHicnKeyIdCb, NULL);
ssl_ = SSL_new(ctx_);
- /*
- * Setup this producer socker as the bio that TLS will use to write and read
- * data (in stream mode)
- */
+
+ /* Setup this producer socker as the bio that TLS will use to write and read
+ * data (in stream mode) */
BIO_METHOD *bio_meth =
BIO_meth_new(BIO_TYPE_ACCEPT, "secure producer socket");
BIO_meth_set_read(bio_meth, TLSProducerSocket::readOld);
@@ -197,15 +204,15 @@ TLSProducerSocket::TLSProducerSocket(interface::ProducerSocket *producer_socket,
BIO_set_init(bio, 1);
BIO_set_data(bio, this);
SSL_set_bio(ssl_, bio, bio);
- /*
- * Set the callback so that when an interest is received we catch it and we
- * decrypt the payload before passing it to the application.
- */
+
+ /* Set the callback so that when an interest is received we catch it and we
+ * decrypt the payload before passing it to the application. */
this->ProducerSocket::setSocketOption(
ProducerCallbacksOptions::CACHE_MISS,
(ProducerInterestCallback)std::bind(&TLSProducerSocket::cacheMiss, this,
std::placeholders::_1,
std::placeholders::_2));
+
this->ProducerSocket::setSocketOption(
ProducerCallbacksOptions::CONTENT_PRODUCED,
(ProducerContentCallback)bind(
@@ -213,35 +220,40 @@ TLSProducerSocket::TLSProducerSocket(interface::ProducerSocket *producer_socket,
std::placeholders::_2, std::placeholders::_3));
}
-/*
- * The producer interface is not owned by the application, so is TLSSocket task
- * to deallocate the memory
- */
+/* The producer interface is not owned by the application, so is TLSSocket task
+ * to deallocate the memory */
TLSProducerSocket::~TLSProducerSocket() { delete producer_interface_; }
void TLSProducerSocket::accept() {
- if (SSL_in_before(ssl_) || SSL_in_init(ssl_)) {
+ HandshakeState handshake_state = getHandshakeState();
+
+ if (handshake_state == UNINITIATED || handshake_state == CLIENT_HELLO) {
tls_chunks_ = 1;
int result = SSL_accept(ssl_);
+
if (result != 1)
throw errors::RuntimeException("Unable to perform client handshake");
}
- TRANSPORT_LOGD("Handshake performed!");
- parent_->list_secure_producers.push_front(
- std::move(parent_->map_secure_producers[handshake_name_]));
- parent_->map_secure_producers.erase(handshake_name_);
- ProducerInterestCallback on_interest_process_decrypted;
+ parent_->list_producers.push_front(
+ std::move(parent_->map_producers[handshake_name_]));
+ parent_->map_producers.erase(handshake_name_);
+
+ ProducerInterestCallback *on_interest_process_decrypted;
getSocketOption(ProducerCallbacksOptions::CACHE_MISS,
- on_interest_process_decrypted);
+ &on_interest_process_decrypted);
- if (on_interest_process_decrypted) {
- Interest inter(std::move(packet_));
- on_interest_process_decrypted(*getInterface(), inter);
+ if (*on_interest_process_decrypted) {
+ Interest inter(std::move(*handshake_packet_));
+ handshake_packet_.reset();
+ on_interest_process_decrypted->operator()(*getInterface(), inter);
} else {
throw errors::RuntimeException(
- "On interest process unset. Unable to perform handshake");
+ "On interest process unset: unable to perform handshake");
}
+
+ handshake_state_ = SERVER_FINISHED;
+ TRANSPORT_LOGD("Handshake performed!");
}
int TLSProducerSocket::async_accept() {
@@ -249,87 +261,106 @@ int TLSProducerSocket::async_accept() {
async_thread_.add([this]() { this->accept(); });
} else {
throw errors::RuntimeException(
- "Async thread not running, impossible to perform handshake");
+ "Async thread not running: unable to perform handshake");
}
return 1;
}
void TLSProducerSocket::onInterest(ProducerSocket &p, Interest &interest) {
- /* Based on the state machine of (D)TLS, we know what action to do */
- if (SSL_in_before(ssl_) || SSL_in_init(ssl_)) {
+ HandshakeState handshake_state = getHandshakeState();
+
+ if (handshake_state == UNINITIATED || handshake_state == CLIENT_HELLO) {
std::unique_lock<std::mutex> lck(mtx_);
+
name_ = interest.getName();
+ // interest.separateHeaderPayload();
+ handshake_packet_ = interest.acquireMemBufReference();
something_to_read_ = true;
- packet_ = interest.acquireMemBufReference();
- if (head_) {
- payload_->prependChain(interest.getPayload());
- } else {
- payload_ = interest.getPayload(); // std::move(interest.getPayload());
- }
+
cv_.notify_one();
- } else {
- name_ = interest.getName();
- packet_ = interest.acquireMemBufReference();
- payload_ = interest.getPayload();
+ return;
+ } else if (handshake_state == SERVER_FINISHED) {
+ // interest.separateHeaderPayload();
+ handshake_packet_ = interest.acquireMemBufReference();
something_to_read_ = true;
- if (interest.getPayload()->length() > 0)
+ if (interest.getPayload()->length() > 0) {
SSL_read(
ssl_,
const_cast<unsigned char *>(interest.getPayload()->writableData()),
- interest.getPayload()->length());
- }
+ (int)interest.getPayload()->length());
+ }
+
+ ProducerInterestCallback *on_interest_input_decrypted;
+ getSocketOption(ProducerCallbacksOptions::INTEREST_INPUT,
+ &on_interest_input_decrypted);
- ProducerInterestCallback on_interest_input_decrypted;
- getSocketOption(ProducerCallbacksOptions::INTEREST_INPUT,
- on_interest_input_decrypted);
- if (on_interest_input_decrypted)
- (on_interest_input_decrypted)(*getInterface(), interest);
+ if (*on_interest_input_decrypted)
+ (*on_interest_input_decrypted)(*getInterface(), interest);
+ }
}
void TLSProducerSocket::cacheMiss(interface::ProducerSocket &p,
Interest &interest) {
- if (SSL_in_before(ssl_) || SSL_in_init(ssl_)) {
+ HandshakeState handshake_state = getHandshakeState();
+
+ TRANSPORT_LOGD("On cache miss in TLS socket producer.");
+
+ if (handshake_state == CLIENT_HELLO) {
std::unique_lock<std::mutex> lck(mtx_);
- name_ = interest.getName();
+
+ // interest.separateHeaderPayload();
+ handshake_packet_ = interest.acquireMemBufReference();
something_to_read_ = true;
- packet_ = interest.acquireMemBufReference();
- payload_ = interest.getPayload();
+ handshake_state_ = CLIENT_FINISHED;
+
cv_.notify_one();
- } else {
- name_ = interest.getName();
- packet_ = interest.acquireMemBufReference();
- payload_ = interest.getPayload();
+ } else if (handshake_state == SERVER_FINISHED) {
+ // interest.separateHeaderPayload();
+ handshake_packet_ = interest.acquireMemBufReference();
something_to_read_ = true;
- if (interest.getPayload()->length() > 0)
+ if (interest.getPayload()->length() > 0) {
SSL_read(
ssl_,
const_cast<unsigned char *>(interest.getPayload()->writableData()),
- interest.getPayload()->length());
+ (int)interest.getPayload()->length());
+ }
if (on_interest_process_decrypted_ != VOID_HANDLER)
on_interest_process_decrypted_(*getInterface(), interest);
}
}
+TLSProducerSocket::HandshakeState TLSProducerSocket::getHandshakeState() {
+ if (SSL_in_before(ssl_)) {
+ handshake_state_ = UNINITIATED;
+ }
+
+ if (SSL_in_init(ssl_) && handshake_state_ == UNINITIATED) {
+ handshake_state_ = CLIENT_HELLO;
+ }
+
+ return handshake_state_;
+}
+
void TLSProducerSocket::onContentProduced(interface::ProducerSocket &p,
const std::error_code &err,
uint64_t bytes_written) {}
-uint32_t TLSProducerSocket::produce(Name content_name,
- std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last, uint32_t start_offset) {
- if (SSL_in_before(ssl_) || SSL_in_init(ssl_)) {
+uint32_t TLSProducerSocket::produceStream(
+ const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer,
+ bool is_last, uint32_t start_offset) {
+ if (getHandshakeState() != SERVER_FINISHED) {
throw errors::RuntimeException(
"New handshake on the same P2P secure producer socket not supported");
}
- size_t buf_size = buffer->length();
- name_ = served_namespaces_.front().mapName(content_name);
+ size_t buf_size = buffer->length();
+ name_ = production_protocol_->getNamespaces().front().mapName(content_name);
tls_chunks_ = to_call_oncontentproduced_ =
- ceil((float)buf_size / (float)SSL3_RT_MAX_PLAIN_LENGTH);
+ (int)ceil((float)buf_size / (float)SSL3_RT_MAX_PLAIN_LENGTH);
if (!is_last) {
tls_chunks_++;
@@ -337,7 +368,7 @@ uint32_t TLSProducerSocket::produce(Name content_name,
last_segment_ = start_offset;
- SSL_write(ssl_, buffer->data(), buf_size);
+ SSL_write(ssl_, buffer->data(), (int)buf_size);
BIO *wbio = SSL_get_wbio(ssl_);
int i = BIO_flush(wbio);
(void)i; // To shut up gcc 5
@@ -345,49 +376,10 @@ uint32_t TLSProducerSocket::produce(Name content_name,
return 0;
}
-void TLSProducerSocket::asyncProduce(const Name &content_name,
- const uint8_t *buf, size_t buffer_size,
- bool is_last, uint32_t *start_offset) {
- if (!encryption_thread_.stopped()) {
- encryption_thread_.add([this, content_name, buffer = buf,
- size = buffer_size, is_last, start_offset]() {
- if (start_offset != NULL) {
- produce(content_name, buffer, size, is_last, *start_offset);
- } else {
- produce(content_name, buffer, size, is_last, 0);
- }
- });
- }
-}
-
-void TLSProducerSocket::asyncProduce(Name content_name,
- std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last, uint32_t offset,
- uint32_t **last_segment) {
- if (!encryption_thread_.stopped()) {
- auto a = buffer.release();
- encryption_thread_.add(
- [this, content_name, a, is_last, offset, last_segment]() {
- auto buf = std::unique_ptr<utils::MemBuf>(a);
- if (last_segment != NULL) {
- *last_segment = &last_segment_;
- }
- produce(content_name, std::move(buf), is_last, offset);
- });
- }
-}
-
-void TLSProducerSocket::asyncProduce(ContentObject &content_object) {
- throw errors::RuntimeException("API not supported");
-}
-
-void TLSProducerSocket::produce(ContentObject &content_object) {
- throw errors::RuntimeException("API not supported");
-}
-
long TLSProducerSocket::ctrl(BIO *b, int cmd, long num, void *ptr) {
if (cmd == BIO_CTRL_FLUSH) {
}
+
return 1;
}
@@ -397,13 +389,15 @@ int TLSProducerSocket::addHicnKeyIdCb(SSL *s, unsigned int ext_type,
X509 *x, size_t chainidx, int *al,
void *add_arg) {
TLSProducerSocket *socket = reinterpret_cast<TLSProducerSocket *>(add_arg);
+
+ TRANSPORT_LOGD("On addHicnKeyIdCb, for the prefix registration.");
+
if (ext_type == 100) {
- ip_prefix_t ip_prefix =
- socket->parent_->served_namespaces_.front().toIpPrefixStruct();
- int inet_family =
- socket->parent_->served_namespaces_.front().getAddressFamily();
- uint16_t prefix_len_bits =
- socket->parent_->served_namespaces_.front().getPrefixLength();
+ auto &prefix =
+ socket->parent_->production_protocol_->getNamespaces().front();
+ const ip_prefix_t &ip_prefix = prefix.toIpPrefixStruct();
+ int inet_family = prefix.getAddressFamily();
+ uint16_t prefix_len_bits = prefix.getPrefixLength();
uint8_t prefix_len_bytes = prefix_len_bits / 8;
uint8_t prefix_len_u32 = prefix_len_bits / 32;
@@ -425,6 +419,7 @@ int TLSProducerSocket::addHicnKeyIdCb(SSL *s, unsigned int ext_type,
ip_address_t keyId_component = {};
u32 *mask_buf;
u32 *keyId_component_buf;
+
switch (inet_family) {
case AF_INET:
mask_buf = &(mask.v4.as_u32);
@@ -451,10 +446,9 @@ int TLSProducerSocket::addHicnKeyIdCb(SSL *s, unsigned int ext_type,
socket->parent_->on_interest_process_decrypted_;
socket->registerPrefix(
- Prefix(socket->parent_->served_namespaces_.front().getName(
- Name(inet_family, (uint8_t *)&mask),
- Name(inet_family, (uint8_t *)&keyId_component),
- socket->parent_->served_namespaces_.front().getName()),
+ Prefix(prefix.getName(Name(inet_family, (uint8_t *)&mask),
+ Name(inet_family, (uint8_t *)&keyId_component),
+ prefix.getName()),
out_ip->len));
socket->connect();
}
@@ -483,6 +477,7 @@ int TLSProducerSocket::setSocketOption(
[this](int socket_option_key,
ProducerInterestCallback socket_option_value) -> int {
int result = SOCKET_OPTION_SET;
+
switch (socket_option_key) {
case ProducerCallbacksOptions::INTEREST_INPUT:
on_interest_input_decrypted_ = socket_option_value;
@@ -508,6 +503,7 @@ int TLSProducerSocket::setSocketOption(
result = SOCKET_OPTION_NOT_SET;
break;
}
+
return result;
});
}
@@ -550,62 +546,5 @@ int TLSProducerSocket::getSocketOption(
});
}
-int TLSProducerSocket::getSocketOption(
- int socket_option_key, ProducerContentCallback &socket_option_value) {
- return rescheduleOnIOServiceWithReference(
- socket_option_key, socket_option_value,
- [this](int socket_option_key,
- ProducerContentCallback &socket_option_value) -> int {
- switch (socket_option_key) {
- case ProducerCallbacksOptions::CONTENT_PRODUCED:
- socket_option_value = on_content_produced_application_;
- break;
-
- default:
- return SOCKET_OPTION_NOT_GET;
- }
-
- return SOCKET_OPTION_GET;
- });
-}
-
-int TLSProducerSocket::getSocketOption(
- int socket_option_key, ProducerInterestCallback &socket_option_value) {
- // Reschedule the function on the io_service to avoid race condition in case
- // setSocketOption is called while the io_service is running.
- return rescheduleOnIOServiceWithReference(
- socket_option_key, socket_option_value,
- [this](int socket_option_key,
- ProducerInterestCallback &socket_option_value) -> int {
- switch (socket_option_key) {
- case ProducerCallbacksOptions::INTEREST_INPUT:
- socket_option_value = on_interest_input_decrypted_;
- break;
-
- case ProducerCallbacksOptions::INTEREST_DROP:
- socket_option_value = on_interest_dropped_input_buffer_;
- break;
-
- case ProducerCallbacksOptions::INTEREST_PASS:
- socket_option_value = on_interest_inserted_input_buffer_;
- break;
-
- case ProducerCallbacksOptions::CACHE_HIT:
- socket_option_value = on_interest_satisfied_output_buffer_;
- break;
-
- case ProducerCallbacksOptions::CACHE_MISS:
- socket_option_value = on_interest_process_decrypted_;
- break;
-
- default:
- return SOCKET_OPTION_NOT_GET;
- }
-
- return SOCKET_OPTION_GET;
- });
-}
-
} // namespace implementation
-
} // namespace transport
diff --git a/libtransport/src/implementation/tls_socket_producer.h b/libtransport/src/implementation/tls_socket_producer.h
index e910c8259..a542a4d9f 100644
--- a/libtransport/src/implementation/tls_socket_producer.h
+++ b/libtransport/src/implementation/tls_socket_producer.h
@@ -16,8 +16,8 @@
#pragma once
#include <implementation/socket_producer.h>
-
#include <openssl/ssl.h>
+
#include <condition_variable>
#include <mutex>
@@ -36,26 +36,18 @@ class TLSProducerSocket : virtual public ProducerSocket {
~TLSProducerSocket();
- uint32_t produce(Name content_name, const uint8_t *buffer, size_t buffer_size,
- bool is_last = true, uint32_t start_offset = 0) override {
- return produce(content_name, utils::MemBuf::copyBuffer(buffer, buffer_size),
- is_last, start_offset);
+ uint32_t produceStream(const Name &content_name, const uint8_t *buffer,
+ size_t buffer_size, bool is_last = true,
+ uint32_t start_offset = 0) override {
+ return produceStream(content_name,
+ utils::MemBuf::copyBuffer(buffer, buffer_size),
+ is_last, start_offset);
}
- uint32_t produce(Name content_name, std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last = true, uint32_t start_offset = 0) override;
-
- void produce(ContentObject &content_object) override;
-
- void asyncProduce(const Name &suffix, const uint8_t *buf, size_t buffer_size,
- bool is_last = true,
- uint32_t *start_offset = nullptr) override;
-
- void asyncProduce(Name content_name, std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last, uint32_t offset,
- uint32_t **last_segment = nullptr) override;
-
- void asyncProduce(ContentObject &content_object) override;
+ uint32_t produceStream(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer,
+ bool is_last = true,
+ uint32_t start_offset = 0) override;
virtual void accept();
@@ -80,51 +72,49 @@ class TLSProducerSocket : virtual public ProducerSocket {
ProducerInterestCallback &socket_option_value);
using ProducerSocket::getSocketOption;
- using ProducerSocket::onInterest;
+ // using ProducerSocket::onInterest;
using ProducerSocket::setSocketOption;
protected:
+ enum HandshakeState {
+ UNINITIATED,
+ CLIENT_HELLO, // when CLIENT_HELLO interest has been received
+ CLIENT_FINISHED, // when CLIENT_FINISHED interest has been received
+ SERVER_FINISHED, // when handshake is done
+ };
/* Callback invoked once an interest has been received and its payload
* decrypted */
ProducerInterestCallback on_interest_input_decrypted_;
ProducerInterestCallback on_interest_process_decrypted_;
ProducerContentCallback on_content_produced_application_;
-
std::mutex mtx_;
-
/* Condition variable for the wait */
std::condition_variable cv_;
-
/* Bool variable, true if there is something to read (an interest arrived) */
bool something_to_read_;
-
+ /* Bool variable, true if CLIENT_FINISHED interest has been received */
+ HandshakeState handshake_state_;
/* First interest that open a secure connection */
transport::core::Name name_;
-
/* SSL handle */
SSL *ssl_;
SSL_CTX *ctx_;
-
- Packet::MemBufPtr packet_;
-
+ Packet::MemBufPtr handshake_packet_;
std::unique_ptr<utils::MemBuf> head_;
std::uint32_t last_segment_;
- std::shared_ptr<utils::MemBuf> payload_;
std::uint32_t key_id_;
-
std::thread *handshake;
P2PSecureProducerSocket *parent_;
-
bool first_;
Name handshake_name_;
int tls_chunks_;
int to_call_oncontentproduced_;
-
bool still_writing_;
-
utils::EventThread encryption_thread_;
+ utils::EventThread async_thread_;
void onInterest(ProducerSocket &p, Interest &interest);
+
void cacheMiss(interface::ProducerSocket &p, Interest &interest);
/* Return the number of read bytes in readbytes */
@@ -156,8 +146,9 @@ class TLSProducerSocket : virtual public ProducerSocket {
void onContentProduced(interface::ProducerSocket &p,
const std::error_code &err, uint64_t bytes_written);
+
+ HandshakeState getHandshakeState();
};
} // namespace implementation
-
} // end namespace transport
diff --git a/libtransport/src/interfaces/CMakeLists.txt b/libtransport/src/interfaces/CMakeLists.txt
index e1d144596..0284aa412 100644
--- a/libtransport/src/interfaces/CMakeLists.txt
+++ b/libtransport/src/interfaces/CMakeLists.txt
@@ -14,24 +14,24 @@
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc_socket_producer.cc
${CMAKE_CURRENT_SOURCE_DIR}/socket_producer.cc
${CMAKE_CURRENT_SOURCE_DIR}/socket_consumer.cc
${CMAKE_CURRENT_SOURCE_DIR}/portal.cc
${CMAKE_CURRENT_SOURCE_DIR}/callbacks.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/global_configuration.cc
)
if (${OPENSSL_VERSION} VERSION_EQUAL "1.1.1a" OR ${OPENSSL_VERSION} VERSION_GREATER "1.1.1a")
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_producer.cc
${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_consumer.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/tls_rtc_socket_producer.cc
+ # ${CMAKE_CURRENT_SOURCE_DIR}/tls_rtc_socket_producer.cc
${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_producer.cc
${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_consumer.cc
)
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/tls_rtc_socket_producer.h
+ # ${CMAKE_CURRENT_SOURCE_DIR}/tls_rtc_socket_producer.h
${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_producer.h
${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_consumer.h
)
diff --git a/libtransport/src/interfaces/global_configuration.cc b/libtransport/src/interfaces/global_configuration.cc
new file mode 100644
index 000000000..8fb6601f3
--- /dev/null
+++ b/libtransport/src/interfaces/global_configuration.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <core/global_configuration.h>
+#include <hicn/transport/interfaces/global_conf_interface.h>
+#include <hicn/transport/utils/log.h>
+
+#include <system_error>
+
+namespace transport {
+namespace interface {
+namespace global_config {
+
+void parseConfigurationFile(const std::string& path) {
+ core::GlobalConfiguration::getInstance().parseConfiguration(path);
+}
+
+void ConfigurationObject::get() {
+ std::error_code ec;
+ core::GlobalConfiguration::getInstance().getConfiguration(*this, ec);
+
+ if (ec) {
+ TRANSPORT_LOGE("Error setting global config: %s", ec.message().c_str());
+ }
+}
+
+void ConfigurationObject::set() {
+ std::error_code ec;
+ core::GlobalConfiguration::getInstance().setConfiguration(*this, ec);
+
+ if (ec) {
+ TRANSPORT_LOGE("Error setting global config: %s", ec.message().c_str());
+ }
+}
+
+} // namespace global_config
+} // namespace interface
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/interfaces/p2psecure_socket_consumer.cc b/libtransport/src/interfaces/p2psecure_socket_consumer.cc
index 2fa8bb6e3..e473a1e2e 100644
--- a/libtransport/src/interfaces/p2psecure_socket_consumer.cc
+++ b/libtransport/src/interfaces/p2psecure_socket_consumer.cc
@@ -14,18 +14,23 @@
*/
#include <hicn/transport/interfaces/p2psecure_socket_consumer.h>
-
#include <implementation/p2psecure_socket_consumer.h>
namespace transport {
namespace interface {
P2PSecureConsumerSocket::P2PSecureConsumerSocket(int handshake_protocol,
- int protocol)
+ int transport_protocol)
: ConsumerSocket() {
socket_ = std::unique_ptr<implementation::ConsumerSocket>(
new implementation::P2PSecureConsumerSocket(this, handshake_protocol,
- protocol));
+ transport_protocol));
+}
+
+void P2PSecureConsumerSocket::registerPrefix(const Prefix &producer_namespace) {
+ implementation::P2PSecureConsumerSocket &secure_consumer_socket =
+ *(static_cast<implementation::P2PSecureConsumerSocket *>(socket_.get()));
+ secure_consumer_socket.registerPrefix(producer_namespace);
}
} // namespace interface
diff --git a/libtransport/src/interfaces/p2psecure_socket_producer.cc b/libtransport/src/interfaces/p2psecure_socket_producer.cc
index 37352259c..10d8a1367 100644
--- a/libtransport/src/interfaces/p2psecure_socket_producer.cc
+++ b/libtransport/src/interfaces/p2psecure_socket_producer.cc
@@ -14,7 +14,6 @@
*/
#include <hicn/transport/interfaces/p2psecure_socket_producer.h>
-
#include <implementation/p2psecure_socket_producer.h>
namespace transport {
@@ -25,7 +24,7 @@ P2PSecureProducerSocket::P2PSecureProducerSocket() {
}
P2PSecureProducerSocket::P2PSecureProducerSocket(
- bool rtc, const std::shared_ptr<utils::Identity> &identity) {
+ bool rtc, const std::shared_ptr<auth::Identity> &identity) {
socket_ = std::make_unique<implementation::P2PSecureProducerSocket>(this, rtc,
identity);
}
diff --git a/libtransport/src/interfaces/portal.cc b/libtransport/src/interfaces/portal.cc
index 36cbd0c3b..2ab51c4b9 100644
--- a/libtransport/src/interfaces/portal.cc
+++ b/libtransport/src/interfaces/portal.cc
@@ -14,38 +14,35 @@
*/
#include <hicn/transport/interfaces/portal.h>
-
#include <implementation/socket.h>
namespace transport {
namespace interface {
-using implementation::BasePortal;
-
-Portal::Portal() { implementation_ = new implementation::BasePortal(); }
+Portal::Portal() { implementation_ = new core::Portal(); }
Portal::Portal(asio::io_service &io_service) {
- implementation_ = new BasePortal(io_service);
+ implementation_ = new core::Portal(io_service);
}
-Portal::~Portal() { delete reinterpret_cast<BasePortal *>(implementation_); }
+Portal::~Portal() { delete reinterpret_cast<core::Portal *>(implementation_); }
void Portal::setConsumerCallback(ConsumerCallback *consumer_callback) {
- reinterpret_cast<BasePortal *>(implementation_)
+ reinterpret_cast<core::Portal *>(implementation_)
->setConsumerCallback(consumer_callback);
}
void Portal::setProducerCallback(ProducerCallback *producer_callback) {
- reinterpret_cast<BasePortal *>(implementation_)
+ reinterpret_cast<core::Portal *>(implementation_)
->setProducerCallback(producer_callback);
}
void Portal::connect(bool is_consumer) {
- reinterpret_cast<BasePortal *>(implementation_)->connect(is_consumer);
+ reinterpret_cast<core::Portal *>(implementation_)->connect(is_consumer);
}
bool Portal::interestIsPending(const core::Name &name) {
- return reinterpret_cast<BasePortal *>(implementation_)
+ return reinterpret_cast<core::Portal *>(implementation_)
->interestIsPending(name);
}
@@ -53,46 +50,46 @@ void Portal::sendInterest(
core::Interest::Ptr &&interest,
OnContentObjectCallback &&on_content_object_callback,
OnInterestTimeoutCallback &&on_interest_timeout_callback) {
- reinterpret_cast<BasePortal *>(implementation_)
+ reinterpret_cast<core::Portal *>(implementation_)
->sendInterest(std::move(interest), std::move(on_content_object_callback),
std::move(on_interest_timeout_callback));
}
void Portal::bind(const BindConfig &config) {
- reinterpret_cast<BasePortal *>(implementation_)->bind(config);
+ reinterpret_cast<core::Portal *>(implementation_)->bind(config);
}
void Portal::runEventsLoop() {
- reinterpret_cast<BasePortal *>(implementation_)->runEventsLoop();
+ reinterpret_cast<core::Portal *>(implementation_)->runEventsLoop();
}
void Portal::runOneEvent() {
- reinterpret_cast<BasePortal *>(implementation_)->runOneEvent();
+ reinterpret_cast<core::Portal *>(implementation_)->runOneEvent();
}
void Portal::sendContentObject(core::ContentObject &content_object) {
- reinterpret_cast<BasePortal *>(implementation_)
+ reinterpret_cast<core::Portal *>(implementation_)
->sendContentObject(content_object);
}
void Portal::stopEventsLoop() {
- reinterpret_cast<BasePortal *>(implementation_)->stopEventsLoop();
+ reinterpret_cast<core::Portal *>(implementation_)->stopEventsLoop();
}
void Portal::killConnection() {
- reinterpret_cast<BasePortal *>(implementation_)->killConnection();
+ reinterpret_cast<core::Portal *>(implementation_)->killConnection();
}
void Portal::clear() {
- reinterpret_cast<BasePortal *>(implementation_)->clear();
+ reinterpret_cast<core::Portal *>(implementation_)->clear();
}
asio::io_service &Portal::getIoService() {
- return reinterpret_cast<BasePortal *>(implementation_)->getIoService();
+ return reinterpret_cast<core::Portal *>(implementation_)->getIoService();
}
void Portal::registerRoute(core::Prefix &prefix) {
- reinterpret_cast<BasePortal *>(implementation_)->registerRoute(prefix);
+ reinterpret_cast<core::Portal *>(implementation_)->registerRoute(prefix);
}
} // namespace interface
diff --git a/libtransport/src/interfaces/socket_consumer.cc b/libtransport/src/interfaces/socket_consumer.cc
index b4be16ade..4eee73cab 100644
--- a/libtransport/src/interfaces/socket_consumer.cc
+++ b/libtransport/src/interfaces/socket_consumer.cc
@@ -14,7 +14,6 @@
*/
#include <hicn/transport/interfaces/socket_consumer.h>
-
#include <implementation/socket_consumer.h>
namespace transport {
@@ -24,6 +23,11 @@ ConsumerSocket::ConsumerSocket(int protocol) {
socket_ = std::make_unique<implementation::ConsumerSocket>(this, protocol);
}
+ConsumerSocket::ConsumerSocket(int protocol, asio::io_service &io_service) {
+ socket_ = std::make_unique<implementation::ConsumerSocket>(this, protocol,
+ io_service);
+}
+
ConsumerSocket::ConsumerSocket() {}
ConsumerSocket::~ConsumerSocket() { socket_->stop(); }
@@ -42,8 +46,6 @@ void ConsumerSocket::stop() { socket_->stop(); }
void ConsumerSocket::resume() { socket_->resume(); }
-bool ConsumerSocket::verifyKeyPackets() { return socket_->verifyKeyPackets(); }
-
asio::io_service &ConsumerSocket::getIoService() {
return socket_->getIoService();
}
@@ -84,22 +86,10 @@ int ConsumerSocket::setSocketOption(
}
int ConsumerSocket::setSocketOption(
- int socket_option_key,
- ConsumerContentObjectVerificationCallback socket_option_value) {
- return socket_->setSocketOption(socket_option_key, socket_option_value);
-}
-
-int ConsumerSocket::setSocketOption(
int socket_option_key, ConsumerInterestCallback socket_option_value) {
return socket_->setSocketOption(socket_option_key, socket_option_value);
}
-int ConsumerSocket::setSocketOption(
- int socket_option_key,
- ConsumerContentObjectVerificationFailedCallback socket_option_value) {
- return socket_->setSocketOption(socket_option_key, socket_option_value);
-}
-
int ConsumerSocket::setSocketOption(int socket_option_key,
IcnObserver *socket_option_value) {
return socket_->setSocketOption(socket_option_key, socket_option_value);
@@ -107,7 +97,7 @@ int ConsumerSocket::setSocketOption(int socket_option_key,
int ConsumerSocket::setSocketOption(
int socket_option_key,
- const std::shared_ptr<utils::Verifier> &socket_option_value) {
+ const std::shared_ptr<auth::Verifier> &socket_option_value) {
return socket_->setSocketOption(socket_option_key, socket_option_value);
}
@@ -148,22 +138,10 @@ int ConsumerSocket::getSocketOption(
}
int ConsumerSocket::getSocketOption(
- int socket_option_key,
- ConsumerContentObjectVerificationCallback **socket_option_value) {
- return socket_->setSocketOption(socket_option_key, socket_option_value);
-}
-
-int ConsumerSocket::getSocketOption(
int socket_option_key, ConsumerInterestCallback **socket_option_value) {
return socket_->setSocketOption(socket_option_key, socket_option_value);
}
-int ConsumerSocket::getSocketOption(
- int socket_option_key,
- ConsumerContentObjectVerificationFailedCallback **socket_option_value) {
- return socket_->setSocketOption(socket_option_key, socket_option_value);
-}
-
int ConsumerSocket::getSocketOption(int socket_option_key,
IcnObserver **socket_option_value) {
return socket_->getSocketOption(socket_option_key, socket_option_value);
@@ -171,7 +149,7 @@ int ConsumerSocket::getSocketOption(int socket_option_key,
int ConsumerSocket::getSocketOption(
int socket_option_key,
- std::shared_ptr<utils::Verifier> &socket_option_value) {
+ std::shared_ptr<auth::Verifier> &socket_option_value) {
return socket_->getSocketOption(socket_option_key, socket_option_value);
}
diff --git a/libtransport/src/interfaces/socket_producer.cc b/libtransport/src/interfaces/socket_producer.cc
index d030fe756..b04947dfd 100644
--- a/libtransport/src/interfaces/socket_producer.cc
+++ b/libtransport/src/interfaces/socket_producer.cc
@@ -14,7 +14,6 @@
*/
#include <hicn/transport/interfaces/socket_producer.h>
-
#include <implementation/socket_producer.h>
#include <atomic>
@@ -31,11 +30,12 @@ namespace interface {
using namespace core;
ProducerSocket::ProducerSocket(int protocol) {
- if (protocol != 0) {
- throw std::runtime_error("Production protocol must be 0.");
- }
+ socket_ = std::make_unique<implementation::ProducerSocket>(this, protocol);
+}
- socket_ = std::make_unique<implementation::ProducerSocket>(this);
+ProducerSocket::ProducerSocket(int protocol, asio::io_service &io_service) {
+ socket_ = std::make_unique<implementation::ProducerSocket>(this, protocol,
+ io_service);
}
ProducerSocket::ProducerSocket(bool) {}
@@ -46,19 +46,34 @@ void ProducerSocket::connect() { socket_->connect(); }
bool ProducerSocket::isRunning() { return socket_->isRunning(); }
-uint32_t ProducerSocket::produce(Name content_name,
- std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last, uint32_t start_offset) {
- return socket_->produce(content_name, std::move(buffer), is_last,
- start_offset);
+uint32_t ProducerSocket::produceStream(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer,
+ bool is_last, uint32_t start_offset) {
+ return socket_->produceStream(content_name, std::move(buffer), is_last,
+ start_offset);
}
-void ProducerSocket::produce(ContentObject &content_object) {
- return socket_->produce(content_object);
+uint32_t ProducerSocket::produceStream(const Name &content_name,
+ const uint8_t *buffer,
+ size_t buffer_size, bool is_last,
+ uint32_t start_offset) {
+ return socket_->produceStream(content_name, buffer, buffer_size, is_last,
+ start_offset);
}
-void ProducerSocket::produce(std::unique_ptr<utils::MemBuf> &&buffer) {
- socket_->produce(std::move(buffer));
+uint32_t ProducerSocket::produceDatagram(
+ const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer) {
+ return socket_->produceDatagram(content_name, std::move(buffer));
+}
+
+uint32_t ProducerSocket::produceDatagram(const Name &content_name,
+ const uint8_t *buffer,
+ size_t buffer_size) {
+ return socket_->produceDatagram(content_name, buffer, buffer_size);
+}
+
+void ProducerSocket::produce(ContentObject &content_object) {
+ return socket_->produce(content_object);
}
void ProducerSocket::asyncProduce(Name content_name,
@@ -69,16 +84,10 @@ void ProducerSocket::asyncProduce(Name content_name,
last_segment);
}
-void ProducerSocket::asyncProduce(ContentObject &content_object) {
- return socket_->asyncProduce(content_object);
-}
-
void ProducerSocket::registerPrefix(const Prefix &producer_namespace) {
return socket_->registerPrefix(producer_namespace);
}
-void ProducerSocket::serveForever() { return socket_->serveForever(); }
-
void ProducerSocket::stop() { return socket_->stop(); }
asio::io_service &ProducerSocket::getIoService() {
@@ -105,11 +114,6 @@ int ProducerSocket::setSocketOption(int socket_option_key,
return socket_->setSocketOption(socket_option_key, socket_option_value);
}
-int ProducerSocket::setSocketOption(int socket_option_key,
- std::list<Prefix> socket_option_value) {
- return socket_->setSocketOption(socket_option_key, socket_option_value);
-}
-
int ProducerSocket::setSocketOption(
int socket_option_key, ProducerContentObjectCallback socket_option_value) {
return socket_->setSocketOption(socket_option_key, socket_option_value);
@@ -126,18 +130,13 @@ int ProducerSocket::setSocketOption(
}
int ProducerSocket::setSocketOption(int socket_option_key,
- utils::CryptoHashType socket_option_value) {
- return socket_->setSocketOption(socket_option_key, socket_option_value);
-}
-
-int ProducerSocket::setSocketOption(int socket_option_key,
- utils::CryptoSuite socket_option_value) {
+ auth::CryptoHashType socket_option_value) {
return socket_->setSocketOption(socket_option_key, socket_option_value);
}
int ProducerSocket::setSocketOption(
int socket_option_key,
- const std::shared_ptr<utils::Signer> &socket_option_value) {
+ const std::shared_ptr<auth::Signer> &socket_option_value) {
return socket_->setSocketOption(socket_option_key, socket_option_value);
}
@@ -156,11 +155,6 @@ int ProducerSocket::getSocketOption(int socket_option_key,
return socket_->getSocketOption(socket_option_key, socket_option_value);
}
-int ProducerSocket::getSocketOption(int socket_option_key,
- std::list<Prefix> &socket_option_value) {
- return socket_->getSocketOption(socket_option_key, socket_option_value);
-}
-
int ProducerSocket::getSocketOption(
int socket_option_key,
ProducerContentObjectCallback **socket_option_value) {
@@ -177,19 +171,13 @@ int ProducerSocket::getSocketOption(
return socket_->getSocketOption(socket_option_key, socket_option_value);
}
-int ProducerSocket::getSocketOption(
- int socket_option_key, utils::CryptoHashType &socket_option_value) {
- return socket_->getSocketOption(socket_option_key, socket_option_value);
-}
-
int ProducerSocket::getSocketOption(int socket_option_key,
- utils::CryptoSuite &socket_option_value) {
+ auth::CryptoHashType &socket_option_value) {
return socket_->getSocketOption(socket_option_key, socket_option_value);
}
int ProducerSocket::getSocketOption(
- int socket_option_key,
- std::shared_ptr<utils::Signer> &socket_option_value) {
+ int socket_option_key, std::shared_ptr<auth::Signer> &socket_option_value) {
return socket_->getSocketOption(socket_option_key, socket_option_value);
}
diff --git a/libtransport/src/interfaces/tls_rtc_socket_producer.cc b/libtransport/src/interfaces/tls_rtc_socket_producer.cc
index 132f34721..7326fcbcb 100644
--- a/libtransport/src/interfaces/tls_rtc_socket_producer.cc
+++ b/libtransport/src/interfaces/tls_rtc_socket_producer.cc
@@ -13,9 +13,8 @@
* limitations under the License.
*/
-#include <interfaces/tls_rtc_socket_producer.h>
-
#include <implementation/tls_rtc_socket_producer.h>
+#include <interfaces/tls_rtc_socket_producer.h>
namespace transport {
namespace interface {
diff --git a/libtransport/src/interfaces/tls_rtc_socket_producer.h b/libtransport/src/interfaces/tls_rtc_socket_producer.h
index 434edb522..3ea84095b 100644
--- a/libtransport/src/interfaces/tls_rtc_socket_producer.h
+++ b/libtransport/src/interfaces/tls_rtc_socket_producer.h
@@ -28,9 +28,9 @@ namespace interface {
class TLSRTCProducerSocket : public ProducerSocket {
public:
TLSRTCProducerSocket(implementation::TLSRTCProducerSocket *implementation);
+
~TLSRTCProducerSocket();
};
} // namespace interface
-
-} // end namespace transport \ No newline at end of file
+} // end namespace transport
diff --git a/libtransport/src/interfaces/tls_socket_consumer.cc b/libtransport/src/interfaces/tls_socket_consumer.cc
index d87642f73..6c1c535b5 100644
--- a/libtransport/src/interfaces/tls_socket_consumer.cc
+++ b/libtransport/src/interfaces/tls_socket_consumer.cc
@@ -13,9 +13,8 @@
* limitations under the License.
*/
-#include <interfaces/tls_socket_consumer.h>
-
#include <implementation/tls_socket_consumer.h>
+#include <interfaces/tls_socket_consumer.h>
namespace transport {
namespace interface {
diff --git a/libtransport/src/interfaces/tls_socket_producer.cc b/libtransport/src/interfaces/tls_socket_producer.cc
index 44aa0cf8b..037702f72 100644
--- a/libtransport/src/interfaces/tls_socket_producer.cc
+++ b/libtransport/src/interfaces/tls_socket_producer.cc
@@ -13,9 +13,8 @@
* limitations under the License.
*/
-#include <interfaces/tls_socket_producer.h>
-
#include <implementation/tls_socket_producer.h>
+#include <interfaces/tls_socket_producer.h>
namespace transport {
namespace interface {
diff --git a/libtransport/src/io_modules/CMakeLists.txt b/libtransport/src/io_modules/CMakeLists.txt
new file mode 100644
index 000000000..cf466721f
--- /dev/null
+++ b/libtransport/src/io_modules/CMakeLists.txt
@@ -0,0 +1,38 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+if (${CMAKE_SYSTEM_NAME} MATCHES "^(iOS|Android|Windows)$")
+
+ list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp/hicn_forwarder_module.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp/udp_socket_connector.cc
+ )
+
+ list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp/hicn_forwarder_module.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp/udp_socket_connector.h
+ )
+
+ set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
+ set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
+else ()
+ add_subdirectory(udp)
+ add_subdirectory(loopback)
+ add_subdirectory(forwarder)
+
+ if (__vpp__)
+ add_subdirectory(memif)
+ endif()
+endif() \ No newline at end of file
diff --git a/libtransport/src/io_modules/forwarder/CMakeLists.txt b/libtransport/src/io_modules/forwarder/CMakeLists.txt
new file mode 100644
index 000000000..92662bc4c
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/CMakeLists.txt
@@ -0,0 +1,44 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+
+list(APPEND MODULE_HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/connector.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/endpoint.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/errors.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/forwarder_module.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/forwarder.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnel_listener.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnel.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/global_counter.h
+)
+
+list(APPEND MODULE_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/errors.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/forwarder_module.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/forwarder.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnel_listener.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnel.cc
+)
+
+build_module(forwarder_module
+ SHARED
+ SOURCES ${MODULE_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT lib${LIBTRANSPORT}
+ INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILE_FLAGS}
+)
diff --git a/libtransport/src/io_modules/forwarder/configuration.h b/libtransport/src/io_modules/forwarder/configuration.h
new file mode 100644
index 000000000..fcaa5530d
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/configuration.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace transport {
+namespace core {
+
+struct ListenerConfig {
+ std::string address;
+ std::uint16_t port;
+ std::string name;
+};
+
+struct ConnectorConfig {
+ std::string local_address;
+ std::uint16_t local_port;
+ std::string remote_address;
+ std::uint16_t remote_port;
+ std::string name;
+};
+
+struct RouteConfig {
+ std::string prefix;
+ uint16_t weight;
+ std::string connector;
+ std::string name;
+};
+
+class Configuration {
+ public:
+ Configuration() : n_threads_(1) {}
+
+ bool empty() {
+ return listeners_.empty() && connectors_.empty() && routes_.empty();
+ }
+
+ Configuration& setThreadNumber(std::size_t threads) {
+ n_threads_ = threads;
+ return *this;
+ }
+
+ std::size_t getThreadNumber() { return n_threads_; }
+
+ template <typename... Args>
+ Configuration& addListener(Args&&... args) {
+ listeners_.emplace_back(std::forward<Args>(args)...);
+ return *this;
+ }
+
+ template <typename... Args>
+ Configuration& addConnector(Args&&... args) {
+ connectors_.emplace_back(std::forward<Args>(args)...);
+ return *this;
+ }
+
+ template <typename... Args>
+ Configuration& addRoute(Args&&... args) {
+ routes_.emplace_back(std::forward<Args>(args)...);
+ return *this;
+ }
+
+ std::vector<ListenerConfig>& getListeners() { return listeners_; }
+
+ std::vector<ConnectorConfig>& getConnectors() { return connectors_; }
+
+ std::vector<RouteConfig>& getRoutes() { return routes_; }
+
+ private:
+ std::vector<ListenerConfig> listeners_;
+ std::vector<ConnectorConfig> connectors_;
+ std::vector<RouteConfig> routes_;
+ std::size_t n_threads_;
+};
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/io_modules/forwarder/errors.cc b/libtransport/src/io_modules/forwarder/errors.cc
new file mode 100644
index 000000000..b5f131499
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/errors.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019 Cisco and/or its affiliates.
+ */
+
+#include <io_modules/forwarder/errors.h>
+
+namespace transport {
+namespace core {
+
+const std::error_category& forwarder_category() {
+ static forwarder_category_impl instance;
+
+ return instance;
+}
+
+const char* forwarder_category_impl::name() const throw() {
+ return "proxy::connector::error";
+}
+
+std::string forwarder_category_impl::message(int ev) const {
+ switch (static_cast<forwarder_error>(ev)) {
+ case forwarder_error::success: {
+ return "Success";
+ }
+ case forwarder_error::disconnected: {
+ return "Connector is disconnected";
+ }
+ case forwarder_error::receive_failed: {
+ return "Packet reception failed";
+ }
+ case forwarder_error::send_failed: {
+ return "Packet send failed";
+ }
+ case forwarder_error::memory_allocation_error: {
+ return "Impossible to allocate memory for packet pool";
+ }
+ case forwarder_error::invalid_connector_type: {
+ return "Invalid type specified for connector.";
+ }
+ case forwarder_error::invalid_connector: {
+ return "Created connector was invalid.";
+ }
+ case forwarder_error::interest_cache_miss: {
+ return "interest cache miss.";
+ }
+ default: {
+ return "Unknown connector error";
+ }
+ }
+}
+} // namespace core
+} // namespace transport
diff --git a/libtransport/src/io_modules/forwarder/errors.h b/libtransport/src/io_modules/forwarder/errors.h
new file mode 100644
index 000000000..dd5cc8fe7
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/errors.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <system_error>
+
+namespace transport {
+namespace core {
+/**
+ * @brief Get the default server error category.
+ * @return The default server error category instance.
+ *
+ * @warning The first call to this function is thread-safe only starting with
+ * C++11.
+ */
+const std::error_category& forwarder_category();
+
+/**
+ * The list of errors.
+ */
+enum class forwarder_error {
+ success = 0,
+ send_failed,
+ receive_failed,
+ disconnected,
+ memory_allocation_error,
+ invalid_connector_type,
+ invalid_connector,
+ interest_cache_miss
+};
+
+/**
+ * @brief Create an error_code instance for the given error.
+ * @param error The error.
+ * @return The error_code instance.
+ */
+inline std::error_code make_error_code(forwarder_error error) {
+ return std::error_code(static_cast<int>(error), forwarder_category());
+}
+
+/**
+ * @brief Create an error_condition instance for the given error.
+ * @param error The error.
+ * @return The error_condition instance.
+ */
+inline std::error_condition make_error_condition(forwarder_error error) {
+ return std::error_condition(static_cast<int>(error), forwarder_category());
+}
+
+/**
+ * @brief A server error category.
+ */
+class forwarder_category_impl : public std::error_category {
+ public:
+ /**
+ * @brief Get the name of the category.
+ * @return The name of the category.
+ */
+ virtual const char* name() const throw();
+
+ /**
+ * @brief Get the error message for a given error.
+ * @param ev The error numeric value.
+ * @return The message associated to the error.
+ */
+ virtual std::string message(int ev) const;
+};
+} // namespace core
+} // namespace transport
+
+namespace std {
+// namespace system {
+template <>
+struct is_error_code_enum<::transport::core::forwarder_error>
+ : public std::true_type {};
+// } // namespace system
+} // namespace std
diff --git a/libtransport/src/io_modules/forwarder/forwarder.cc b/libtransport/src/io_modules/forwarder/forwarder.cc
new file mode 100644
index 000000000..7e89e2f9f
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/forwarder.cc
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <core/global_configuration.h>
+#include <core/local_connector.h>
+#include <io_modules/forwarder/forwarder.h>
+#include <io_modules/forwarder/global_id_counter.h>
+#include <io_modules/forwarder/udp_tunnel.h>
+#include <io_modules/forwarder/udp_tunnel_listener.h>
+
+namespace transport {
+
+namespace core {
+
+constexpr char Forwarder::forwarder_config_section[];
+
+Forwarder::Forwarder() : config_() {
+ using namespace std::placeholders;
+ GlobalConfiguration::getInstance().registerConfigurationParser(
+ forwarder_config_section,
+ std::bind(&Forwarder::parseForwarderConfiguration, this, _1, _2));
+
+ if (!config_.empty()) {
+ initThreads();
+ initListeners();
+ initConnectors();
+ }
+}
+
+Forwarder::~Forwarder() {
+ for (auto &l : listeners_) {
+ l->close();
+ }
+
+ for (auto &c : remote_connectors_) {
+ c.second->close();
+ }
+
+ GlobalConfiguration::getInstance().unregisterConfigurationParser(
+ forwarder_config_section);
+}
+
+void Forwarder::initThreads() {
+ for (unsigned i = 0; i < config_.getThreadNumber(); i++) {
+ thread_pool_.emplace_back(io_service_, /* detached */ false);
+ }
+}
+
+void Forwarder::initListeners() {
+ using namespace std::placeholders;
+ for (auto &l : config_.getListeners()) {
+ listeners_.emplace_back(std::make_shared<UdpTunnelListener>(
+ io_service_,
+ std::bind(&Forwarder::onPacketFromListener, this, _1, _2, _3),
+ asio::ip::udp::endpoint(asio::ip::address::from_string(l.address),
+ l.port)));
+ }
+}
+
+void Forwarder::initConnectors() {
+ using namespace std::placeholders;
+ for (auto &c : config_.getConnectors()) {
+ auto id = GlobalCounter<Connector::Id>::getInstance().getNext();
+ auto conn = new UdpTunnelConnector(
+ io_service_, std::bind(&Forwarder::onPacketReceived, this, _1, _2, _3),
+ std::bind(&Forwarder::onPacketSent, this, _1, _2),
+ std::bind(&Forwarder::onConnectorClosed, this, _1),
+ std::bind(&Forwarder::onConnectorReconnected, this, _1));
+ conn->setConnectorId(id);
+ remote_connectors_.emplace(id, conn);
+ conn->connect(c.remote_address, c.remote_port, c.local_address,
+ c.local_port);
+ }
+}
+
+Connector::Id Forwarder::registerLocalConnector(
+ asio::io_service &io_service,
+ Connector::PacketReceivedCallback &&receive_callback,
+ Connector::OnReconnectCallback &&reconnect_callback) {
+ utils::SpinLock::Acquire locked(connector_lock_);
+ auto id = GlobalCounter<Connector::Id>::getInstance().getNext();
+ auto connector = std::make_shared<LocalConnector>(
+ io_service, receive_callback, nullptr, nullptr, reconnect_callback);
+ connector->setConnectorId(id);
+ local_connectors_.emplace(id, std::move(connector));
+ return id;
+}
+
+Forwarder &Forwarder::deleteConnector(Connector::Id id) {
+ utils::SpinLock::Acquire locked(connector_lock_);
+ auto it = local_connectors_.find(id);
+ if (it != local_connectors_.end()) {
+ it->second->close();
+ local_connectors_.erase(it);
+ }
+
+ return *this;
+}
+
+Connector::Ptr Forwarder::getConnector(Connector::Id id) {
+ utils::SpinLock::Acquire locked(connector_lock_);
+ auto it = local_connectors_.find(id);
+ if (it != local_connectors_.end()) {
+ return it->second;
+ }
+
+ return nullptr;
+}
+
+void Forwarder::onPacketFromListener(Connector *connector,
+ utils::MemBuf &packet_buffer,
+ const std::error_code &ec) {
+ // Create connector
+ connector->setReceiveCallback(
+ std::bind(&Forwarder::onPacketReceived, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3));
+
+ TRANSPORT_LOGD("Packet received from listener.");
+
+ {
+ utils::SpinLock::Acquire locked(connector_lock_);
+ remote_connectors_.emplace(connector->getConnectorId(),
+ connector->shared_from_this());
+ }
+ // TODO Check if control packet or not. For the moment it is not.
+ onPacketReceived(connector, packet_buffer, ec);
+}
+
+void Forwarder::onPacketReceived(Connector *connector,
+ utils::MemBuf &packet_buffer,
+ const std::error_code &ec) {
+ // Figure out the type of packet we received
+ bool is_interest = Packet::isInterest(packet_buffer.data());
+
+ Packet *packet = nullptr;
+ if (is_interest) {
+ packet = static_cast<Interest *>(&packet_buffer);
+ } else {
+ packet = static_cast<ContentObject *>(&packet_buffer);
+ }
+
+ for (auto &c : local_connectors_) {
+ auto role = c.second->getRole();
+ auto is_producer = role == Connector::Role::PRODUCER;
+ if ((is_producer && is_interest) || (!is_producer && !is_interest)) {
+ c.second->send(*packet);
+ } else {
+ TRANSPORT_LOGD(
+ "Error sending packet to local connector. is_interest = %d - "
+ "is_producer = %d",
+ (int)is_interest, (int)is_producer);
+ }
+ }
+
+ // PCS Lookup + FIB lookup. Skip for now
+
+ // Forward packet to local connectors
+}
+
+void Forwarder::send(Packet &packet) {
+ // TODo Here a nice PIT/CS / FIB would be required:)
+ // For now let's just forward the packet on the remote connector we get
+ if (remote_connectors_.begin() == remote_connectors_.end()) {
+ return;
+ }
+
+ auto remote_endpoint =
+ remote_connectors_.begin()->second->getRemoteEndpoint();
+ TRANSPORT_LOGD("Sending packet to: %s:%u",
+ remote_endpoint.getAddress().to_string().c_str(),
+ remote_endpoint.getPort());
+ remote_connectors_.begin()->second->send(packet);
+}
+
+void Forwarder::onPacketSent(Connector *connector, const std::error_code &ec) {}
+
+void Forwarder::onConnectorClosed(Connector *connector) {}
+
+void Forwarder::onConnectorReconnected(Connector *connector) {}
+
+void Forwarder::parseForwarderConfiguration(
+ const libconfig::Setting &forwarder_config, std::error_code &ec) {
+ using namespace libconfig;
+
+ // n_thread
+ if (forwarder_config.exists("n_threads")) {
+ // Get number of threads
+ int n_threads = 1;
+ forwarder_config.lookupValue("n_threads", n_threads);
+ TRANSPORT_LOGD("Forwarder threads from config file: %u", n_threads);
+ config_.setThreadNumber(n_threads);
+ }
+
+ // listeners
+ if (forwarder_config.exists("listeners")) {
+ // get path where looking for modules
+ const Setting &listeners = forwarder_config.lookup("listeners");
+ auto count = listeners.getLength();
+
+ for (int i = 0; i < count; i++) {
+ const Setting &listener = listeners[i];
+ ListenerConfig list;
+ unsigned port;
+
+ list.name = listener.getName();
+ listener.lookupValue("local_address", list.address);
+ listener.lookupValue("local_port", port);
+ list.port = (uint16_t)(port);
+
+ TRANSPORT_LOGD("Adding listener %s, (%s:%u)", list.name.c_str(),
+ list.address.c_str(), list.port);
+ config_.addListener(std::move(list));
+ }
+ }
+
+ // connectors
+ if (forwarder_config.exists("connectors")) {
+ // get path where looking for modules
+ const Setting &connectors = forwarder_config.lookup("connectors");
+ auto count = connectors.getLength();
+
+ for (int i = 0; i < count; i++) {
+ const Setting &connector = connectors[i];
+ ConnectorConfig conn;
+
+ conn.name = connector.getName();
+ unsigned port = 0;
+
+ if (!connector.lookupValue("local_address", conn.local_address)) {
+ conn.local_address = "";
+ }
+
+ if (!connector.lookupValue("local_port", port)) {
+ port = 0;
+ }
+
+ conn.local_port = (uint16_t)(port);
+
+ if (!connector.lookupValue("remote_address", conn.remote_address)) {
+ throw errors::RuntimeException(
+ "Error in configuration file: remote_address is a mandatory field "
+ "of Connectors.");
+ }
+
+ if (!connector.lookupValue("remote_port", port)) {
+ throw errors::RuntimeException(
+ "Error in configuration file: remote_port is a mandatory field "
+ "of Connectors.");
+ }
+
+ conn.remote_port = (uint16_t)(port);
+
+ TRANSPORT_LOGD("Adding connector %s, (%s:%u %s:%u)", conn.name.c_str(),
+ conn.local_address.c_str(), conn.local_port,
+ conn.remote_address.c_str(), conn.remote_port);
+ config_.addConnector(std::move(conn));
+ }
+ }
+
+ // Routes
+ if (forwarder_config.exists("routes")) {
+ const Setting &routes = forwarder_config.lookup("routes");
+ auto count = routes.getLength();
+
+ for (int i = 0; i < count; i++) {
+ const Setting &route = routes[i];
+ RouteConfig r;
+ unsigned weight;
+
+ r.name = route.getName();
+ route.lookupValue("prefix", r.prefix);
+ route.lookupValue("weight", weight);
+ route.lookupValue("connector", r.connector);
+ r.weight = (uint16_t)(weight);
+
+ TRANSPORT_LOGD("Adding route %s %s (%s %u)", r.name.c_str(),
+ r.prefix.c_str(), r.connector.c_str(), r.weight);
+ config_.addRoute(std::move(r));
+ }
+ }
+}
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/io_modules/forwarder/forwarder.h b/libtransport/src/io_modules/forwarder/forwarder.h
new file mode 100644
index 000000000..5b564bb5e
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/forwarder.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/io_module.h>
+#include <hicn/transport/core/prefix.h>
+#include <hicn/transport/utils/event_thread.h>
+#include <hicn/transport/utils/singleton.h>
+#include <hicn/transport/utils/spinlock.h>
+#include <io_modules/forwarder/configuration.h>
+#include <io_modules/forwarder/udp_tunnel_listener.h>
+
+#include <atomic>
+#include <libconfig.h++>
+#include <unordered_map>
+
+namespace transport {
+
+namespace core {
+
+class Forwarder : public utils::Singleton<Forwarder> {
+ static constexpr char forwarder_config_section[] = "forwarder";
+ friend class utils::Singleton<Forwarder>;
+
+ public:
+ Forwarder();
+
+ ~Forwarder();
+
+ void initThreads();
+ void initListeners();
+ void initConnectors();
+
+ Connector::Id registerLocalConnector(
+ asio::io_service &io_service,
+ Connector::PacketReceivedCallback &&receive_callback,
+ Connector::OnReconnectCallback &&reconnect_callback);
+
+ Forwarder &deleteConnector(Connector::Id id);
+
+ Connector::Ptr getConnector(Connector::Id id);
+
+ void send(Packet &packet);
+
+ void stop();
+
+ private:
+ void onPacketFromListener(Connector *connector, utils::MemBuf &packet_buffer,
+ const std::error_code &ec);
+ void onPacketReceived(Connector *connector, utils::MemBuf &packet_buffer,
+ const std::error_code &ec);
+ void onPacketSent(Connector *connector, const std::error_code &ec);
+ void onConnectorClosed(Connector *connector);
+ void onConnectorReconnected(Connector *connector);
+
+ void parseForwarderConfiguration(const libconfig::Setting &io_config,
+ std::error_code &ec);
+
+ asio::io_service io_service_;
+ utils::SpinLock connector_lock_;
+
+ /**
+ * Connectors and listeners must be declares *before* thread_pool_, so that
+ * threads destructors will wait for them to gracefully close before being
+ * destroyed.
+ */
+ std::unordered_map<Connector::Id, Connector::Ptr> remote_connectors_;
+ std::unordered_map<Connector::Id, Connector::Ptr> local_connectors_;
+ std::vector<UdpTunnelListener::Ptr> listeners_;
+
+ std::vector<utils::EventThread> thread_pool_;
+
+ Configuration config_;
+};
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/io_modules/forwarder/forwarder_module.cc b/libtransport/src/io_modules/forwarder/forwarder_module.cc
new file mode 100644
index 000000000..356b42d3b
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/forwarder_module.cc
@@ -0,0 +1,87 @@
+/*
+ * 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/transport/errors/not_implemented_exception.h>
+#include <hicn/transport/utils/log.h>
+#include <io_modules/forwarder/forwarder_module.h>
+
+namespace transport {
+
+namespace core {
+
+ForwarderModule::ForwarderModule()
+ : IoModule(),
+ name_(""),
+ connector_id_(Connector::invalid_connector),
+ forwarder_(Forwarder::getInstance()) {}
+
+ForwarderModule::~ForwarderModule() {
+ forwarder_.deleteConnector(connector_id_);
+}
+
+bool ForwarderModule::isConnected() { return true; }
+
+void ForwarderModule::send(Packet &packet) {
+ IoModule::send(packet);
+ forwarder_.send(packet);
+ // TRANSPORT_LOGD("ForwarderModule: sending from %u to %d", local_id_,
+ // 1 - local_id_);
+
+ // local_faces_.at(1 - local_id_).onPacket(packet);
+}
+
+void ForwarderModule::send(const uint8_t *packet, std::size_t len) {
+ // not supported
+ throw errors::NotImplementedException();
+}
+
+void ForwarderModule::registerRoute(const Prefix &prefix) {
+ // For the moment we route packets from one socket to the other.
+ // Next step will be to introduce a FIB
+ return;
+}
+
+void ForwarderModule::closeConnection() {
+ forwarder_.deleteConnector(connector_id_);
+}
+
+void ForwarderModule::init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::OnReconnectCallback &&reconnect_callback,
+ asio::io_service &io_service,
+ const std::string &app_name) {
+ connector_id_ = forwarder_.registerLocalConnector(
+ io_service, std::move(receive_callback), std::move(reconnect_callback));
+ name_ = app_name;
+}
+
+void ForwarderModule::processControlMessageReply(utils::MemBuf &packet_buffer) {
+ return;
+}
+
+void ForwarderModule::connect(bool is_consumer) {
+ forwarder_.getConnector(connector_id_)
+ ->setRole(is_consumer ? Connector::Role::CONSUMER
+ : Connector::Role::PRODUCER);
+}
+
+std::uint32_t ForwarderModule::getMtu() { return interface_mtu; }
+
+bool ForwarderModule::isControlMessage(const uint8_t *message) { return false; }
+
+extern "C" IoModule *create_module(void) { return new ForwarderModule(); }
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/forwarder/forwarder_module.h b/libtransport/src/io_modules/forwarder/forwarder_module.h
new file mode 100644
index 000000000..58bfb7996
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/forwarder_module.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/io_module.h>
+#include <hicn/transport/core/prefix.h>
+#include <io_modules/forwarder/forwarder.h>
+
+#include <atomic>
+
+namespace transport {
+
+namespace core {
+
+class Forwarder;
+
+class ForwarderModule : public IoModule {
+ static constexpr std::uint16_t interface_mtu = 1500;
+
+ public:
+ ForwarderModule();
+
+ ~ForwarderModule();
+
+ void connect(bool is_consumer) override;
+
+ void send(Packet &packet) override;
+ void send(const uint8_t *packet, std::size_t len) override;
+
+ bool isConnected() override;
+
+ void init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::OnReconnectCallback &&reconnect_callback,
+ asio::io_service &io_service,
+ const std::string &app_name = "Libtransport") override;
+
+ void registerRoute(const Prefix &prefix) override;
+
+ std::uint32_t getMtu() override;
+
+ bool isControlMessage(const uint8_t *message) override;
+
+ void processControlMessageReply(utils::MemBuf &packet_buffer) override;
+
+ void closeConnection() override;
+
+ private:
+ std::string name_;
+ Connector::Id connector_id_;
+ Forwarder &forwarder_;
+};
+
+extern "C" IoModule *create_module(void);
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/forwarder/global_id_counter.h b/libtransport/src/io_modules/forwarder/global_id_counter.h
new file mode 100644
index 000000000..fe8d76730
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/global_id_counter.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <atomic>
+#include <mutex>
+
+namespace transport {
+
+namespace core {
+
+template <typename T = uint64_t>
+class GlobalCounter {
+ public:
+ static GlobalCounter& getInstance() {
+ std::lock_guard<std::mutex> lock(global_mutex_);
+
+ if (!instance_) {
+ instance_.reset(new GlobalCounter());
+ }
+
+ return *instance_;
+ }
+
+ T getNext() { return counter_++; }
+
+ private:
+ GlobalCounter() : counter_(0) {}
+ static std::unique_ptr<GlobalCounter<T>> instance_;
+ static std::mutex global_mutex_;
+ std::atomic<T> counter_;
+};
+
+template <typename T>
+std::unique_ptr<GlobalCounter<T>> GlobalCounter<T>::instance_ = nullptr;
+
+template <typename T>
+std::mutex GlobalCounter<T>::global_mutex_;
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/io_modules/forwarder/udp_tunnel.cc b/libtransport/src/io_modules/forwarder/udp_tunnel.cc
new file mode 100644
index 000000000..dc725fc4e
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/udp_tunnel.cc
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ */
+
+#include <hicn/transport/utils/branch_prediction.h>
+#include <io_modules/forwarder/errors.h>
+#include <io_modules/forwarder/udp_tunnel.h>
+
+#include <iostream>
+#include <thread>
+#include <vector>
+
+namespace transport {
+namespace core {
+
+UdpTunnelConnector::~UdpTunnelConnector() {}
+
+void UdpTunnelConnector::connect(const std::string &hostname, uint16_t port,
+ const std::string &bind_address,
+ uint16_t bind_port) {
+ if (state_ == State::CLOSED) {
+ state_ = State::CONNECTING;
+ endpoint_iterator_ = resolver_.resolve({hostname, std::to_string(port)});
+ remote_endpoint_send_ = *endpoint_iterator_;
+ socket_->open(remote_endpoint_send_.protocol());
+
+ if (!bind_address.empty() && bind_port != 0) {
+ using namespace asio::ip;
+ socket_->bind(
+ udp::endpoint(address::from_string(bind_address), bind_port));
+ }
+
+ state_ = State::CONNECTED;
+
+ remote_endpoint_ = Endpoint(remote_endpoint_send_);
+ local_endpoint_ = Endpoint(socket_->local_endpoint());
+
+ doRecvPacket();
+
+#ifdef LINUX
+ send_timer_.expires_from_now(std::chrono::microseconds(50));
+ send_timer_.async_wait(std::bind(&UdpTunnelConnector::writeHandler, this,
+ std::placeholders::_1));
+#endif
+ }
+}
+
+void UdpTunnelConnector::send(Packet &packet) {
+ strand_->post([this, pkt{packet.shared_from_this()}]() {
+ bool write_in_progress = !output_buffer_.empty();
+ output_buffer_.push_back(std::move(pkt));
+ if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
+ if (!write_in_progress) {
+ doSendPacket();
+ }
+ } else {
+ data_available_ = true;
+ }
+ });
+}
+
+void UdpTunnelConnector::send(const uint8_t *packet, std::size_t len) {}
+
+void UdpTunnelConnector::close() {
+ TRANSPORT_LOGD("UDPTunnelConnector::close");
+ state_ = State::CLOSED;
+ bool is_socket_owned = socket_.use_count() == 1;
+ if (is_socket_owned) {
+ io_service_.dispatch([this]() {
+ this->socket_->close();
+ // on_close_callback_(shared_from_this());
+ });
+ }
+}
+
+void UdpTunnelConnector::doSendPacket() {
+#ifdef LINUX
+ send_timer_.expires_from_now(std::chrono::microseconds(50));
+ send_timer_.async_wait(std::bind(&UdpTunnelConnector::writeHandler, this,
+ std::placeholders::_1));
+#else
+ auto packet = output_buffer_.front().get();
+ auto array = std::vector<asio::const_buffer>();
+
+ const ::utils::MemBuf *current = packet;
+ do {
+ array.push_back(asio::const_buffer(current->data(), current->length()));
+ current = current->next();
+ } while (current != packet);
+
+ socket_->async_send_to(
+ std::move(array), remote_endpoint_send_,
+ strand_->wrap([this](std::error_code ec, std::size_t length) {
+ if (TRANSPORT_EXPECT_TRUE(!ec)) {
+ sent_callback_(this, make_error_code(forwarder_error::success));
+ } else if (ec.value() ==
+ static_cast<int>(std::errc::operation_canceled)) {
+ // The connection has been closed by the application.
+ return;
+ } else {
+ sendFailed();
+ sent_callback_(this, ec);
+ }
+
+ output_buffer_.pop_front();
+ if (!output_buffer_.empty()) {
+ doSendPacket();
+ }
+ }));
+#endif
+}
+
+#ifdef LINUX
+void UdpTunnelConnector::writeHandler(std::error_code ec) {
+ if (TRANSPORT_EXPECT_FALSE(state_ != State::CONNECTED)) {
+ return;
+ }
+
+ auto len = std::min(output_buffer_.size(), std::size_t(Connector::max_burst));
+
+ if (len) {
+ int m = 0;
+ for (auto &p : output_buffer_) {
+ auto packet = p.get();
+ ::utils::MemBuf *current = packet;
+ int b = 0;
+ do {
+ // array.push_back(asio::const_buffer(current->data(),
+ // current->length()));
+ tx_iovecs_[m][b].iov_base = current->writableData();
+ tx_iovecs_[m][b].iov_len = current->length();
+ current = current->next();
+ b++;
+ } while (current != packet);
+
+ tx_msgs_[m].msg_hdr.msg_iov = tx_iovecs_[m];
+ tx_msgs_[m].msg_hdr.msg_iovlen = b;
+ tx_msgs_[m].msg_hdr.msg_name = remote_endpoint_send_.data();
+ tx_msgs_[m].msg_hdr.msg_namelen = remote_endpoint_send_.size();
+ m++;
+
+ if (--len == 0) {
+ break;
+ }
+ }
+
+ int retval = sendmmsg(socket_->native_handle(), tx_msgs_, m, MSG_DONTWAIT);
+ if (retval > 0) {
+ while (retval--) {
+ output_buffer_.pop_front();
+ }
+ } else if (retval != EWOULDBLOCK && retval != EAGAIN) {
+ TRANSPORT_LOGE("Error sending messages! %s %d\n", strerror(errno),
+ retval);
+ return;
+ }
+ }
+
+ if (!output_buffer_.empty()) {
+ send_timer_.expires_from_now(std::chrono::microseconds(50));
+ send_timer_.async_wait(std::bind(&UdpTunnelConnector::writeHandler, this,
+ std::placeholders::_1));
+ }
+}
+
+void UdpTunnelConnector::readHandler(std::error_code ec) {
+ TRANSPORT_LOGD("UdpTunnelConnector receive packet");
+
+ // TRANSPORT_LOGD("UdpTunnelConnector received packet length=%lu", length);
+ if (TRANSPORT_EXPECT_TRUE(!ec)) {
+ if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
+ if (current_position_ == 0) {
+ for (int i = 0; i < max_burst; i++) {
+ auto read_buffer = getRawBuffer();
+ rx_iovecs_[i][0].iov_base = read_buffer.first;
+ rx_iovecs_[i][0].iov_len = read_buffer.second;
+ rx_msgs_[i].msg_hdr.msg_iov = rx_iovecs_[i];
+ rx_msgs_[i].msg_hdr.msg_iovlen = 1;
+ }
+ }
+
+ int res = recvmmsg(socket_->native_handle(), rx_msgs_ + current_position_,
+ max_burst - current_position_, MSG_DONTWAIT, nullptr);
+ if (res < 0) {
+ TRANSPORT_LOGE("Error receiving messages! %s %d\n", strerror(errno),
+ res);
+ return;
+ }
+
+ for (int i = 0; i < res; i++) {
+ auto packet = getPacketFromBuffer(
+ reinterpret_cast<uint8_t *>(
+ rx_msgs_[current_position_].msg_hdr.msg_iov[0].iov_base),
+ rx_msgs_[current_position_].msg_len);
+ receiveSuccess(*packet);
+ receive_callback_(this, *packet,
+ make_error_code(forwarder_error::success));
+ ++current_position_;
+ }
+
+ doRecvPacket();
+ } else {
+ TRANSPORT_LOGE(
+ "Error in UDP: Receiving packets from a not connected socket.");
+ }
+ } else if (ec.value() == static_cast<int>(std::errc::operation_canceled)) {
+ TRANSPORT_LOGE("The connection has been closed by the application.");
+ return;
+ } else {
+ if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
+ // receive_callback_(this, *read_msg_, ec);
+ TRANSPORT_LOGE("Error in UDP connector: %d %s", ec.value(),
+ ec.message().c_str());
+ } else {
+ TRANSPORT_LOGE("Error while not connector");
+ }
+ }
+}
+#endif
+
+void UdpTunnelConnector::doRecvPacket() {
+#ifdef LINUX
+ if (state_ == State::CONNECTED) {
+#if ((ASIO_VERSION / 100 % 1000) < 11)
+ socket_->async_receive(asio::null_buffers(),
+#else
+ socket_->async_wait(asio::ip::tcp::socket::wait_read,
+#endif
+ std::bind(&UdpTunnelConnector::readHandler, this,
+ std::placeholders::_1));
+ }
+#else
+ TRANSPORT_LOGD("UdpTunnelConnector receive packet");
+ read_msg_ = getRawBuffer();
+ socket_->async_receive_from(
+ asio::buffer(read_msg_.first, read_msg_.second), remote_endpoint_recv_,
+ [this](std::error_code ec, std::size_t length) {
+ TRANSPORT_LOGD("UdpTunnelConnector received packet length=%lu", length);
+ if (TRANSPORT_EXPECT_TRUE(!ec)) {
+ if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
+ auto packet = getPacketFromBuffer(read_msg_.first, length);
+ receiveSuccess(*packet);
+ receive_callback_(this, *packet,
+ make_error_code(forwarder_error::success));
+ doRecvPacket();
+ } else {
+ TRANSPORT_LOGE(
+ "Error in UDP: Receiving packets from a not connected socket.");
+ }
+ } else if (ec.value() ==
+ static_cast<int>(std::errc::operation_canceled)) {
+ TRANSPORT_LOGE("The connection has been closed by the application.");
+ return;
+ } else {
+ if (TRANSPORT_EXPECT_TRUE(state_ == State::CONNECTED)) {
+ TRANSPORT_LOGE("Error in UDP connector: %d %s", ec.value(),
+ ec.message().c_str());
+ } else {
+ TRANSPORT_LOGE("Error while not connector");
+ }
+ }
+ });
+#endif
+}
+
+void UdpTunnelConnector::doConnect() {
+ asio::async_connect(
+ *socket_, endpoint_iterator_,
+ [this](std::error_code ec, asio::ip::udp::resolver::iterator) {
+ if (!ec) {
+ state_ = State::CONNECTED;
+ doRecvPacket();
+
+ if (data_available_) {
+ data_available_ = false;
+ doSendPacket();
+ }
+ } else {
+ TRANSPORT_LOGE("[Hproxy] - UDP Connection failed!!!");
+ timer_.expires_from_now(std::chrono::milliseconds(500));
+ timer_.async_wait(std::bind(&UdpTunnelConnector::doConnect, this));
+ }
+ });
+}
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/forwarder/udp_tunnel.h b/libtransport/src/io_modules/forwarder/udp_tunnel.h
new file mode 100644
index 000000000..df472af91
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/udp_tunnel.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/connector.h>
+#include <hicn/transport/portability/platform.h>
+#include <io_modules/forwarder/errors.h>
+
+#include <asio.hpp>
+#include <asio/steady_timer.hpp>
+#include <iostream>
+#include <memory>
+
+namespace transport {
+namespace core {
+
+class UdpTunnelListener;
+
+class UdpTunnelConnector : public Connector {
+ friend class UdpTunnelListener;
+
+ public:
+ template <typename ReceiveCallback, typename SentCallback, typename OnClose,
+ typename OnReconnect>
+ UdpTunnelConnector(asio::io_service &io_service,
+ ReceiveCallback &&receive_callback,
+ SentCallback &&packet_sent, OnClose &&on_close_callback,
+ OnReconnect &&on_reconnect)
+ : Connector(receive_callback, packet_sent, on_close_callback,
+ on_reconnect),
+ io_service_(io_service),
+ strand_(std::make_shared<asio::io_service::strand>(io_service_)),
+ socket_(std::make_shared<asio::ip::udp::socket>(io_service_)),
+ resolver_(io_service_),
+ timer_(io_service_),
+#ifdef LINUX
+ send_timer_(io_service_),
+ tx_iovecs_{0},
+ tx_msgs_{0},
+ rx_iovecs_{0},
+ rx_msgs_{0},
+ current_position_(0),
+#else
+ read_msg_(nullptr, 0),
+#endif
+ data_available_(false) {
+ }
+
+ template <typename ReceiveCallback, typename SentCallback, typename OnClose,
+ typename OnReconnect, typename EndpointType>
+ UdpTunnelConnector(std::shared_ptr<asio::ip::udp::socket> &socket,
+ std::shared_ptr<asio::io_service::strand> &strand,
+ ReceiveCallback &&receive_callback,
+ SentCallback &&packet_sent, OnClose &&on_close_callback,
+ OnReconnect &&on_reconnect, EndpointType &&remote_endpoint)
+ : Connector(receive_callback, packet_sent, on_close_callback,
+ on_reconnect),
+#if ((ASIO_VERSION / 100 % 1000) < 12)
+ io_service_(socket->get_io_service()),
+#else
+ io_service_((asio::io_context &)(socket->get_executor().context())),
+#endif
+ strand_(strand),
+ socket_(socket),
+ resolver_(io_service_),
+ remote_endpoint_send_(std::forward<EndpointType &&>(remote_endpoint)),
+ timer_(io_service_),
+#ifdef LINUX
+ send_timer_(io_service_),
+ tx_iovecs_{0},
+ tx_msgs_{0},
+ rx_iovecs_{0},
+ rx_msgs_{0},
+ current_position_(0),
+#else
+ read_msg_(nullptr, 0),
+#endif
+ data_available_(false) {
+ if (socket_->is_open()) {
+ state_ = State::CONNECTED;
+ remote_endpoint_ = Endpoint(remote_endpoint_send_);
+ local_endpoint_ = socket_->local_endpoint();
+ }
+ }
+
+ ~UdpTunnelConnector() override;
+
+ void send(Packet &packet) override;
+
+ void send(const uint8_t *packet, std::size_t len) override;
+
+ void close() override;
+
+ void connect(const std::string &hostname, std::uint16_t port,
+ const std::string &bind_address = "",
+ std::uint16_t bind_port = 0);
+
+ auto shared_from_this() { return utils::shared_from(this); }
+
+ private:
+ void doConnect();
+ void doRecvPacket();
+
+ void doRecvPacket(utils::MemBuf &buffer) {
+ receive_callback_(this, buffer, make_error_code(forwarder_error::success));
+ }
+
+#ifdef LINUX
+ void readHandler(std::error_code ec);
+ void writeHandler(std::error_code ec);
+#endif
+
+ void setConnected() { state_ = State::CONNECTED; }
+
+ void doSendPacket();
+ void doClose();
+
+ private:
+ asio::io_service &io_service_;
+ std::shared_ptr<asio::io_service::strand> strand_;
+ std::shared_ptr<asio::ip::udp::socket> socket_;
+ asio::ip::udp::resolver resolver_;
+ asio::ip::udp::resolver::iterator endpoint_iterator_;
+ asio::ip::udp::endpoint remote_endpoint_send_;
+ asio::ip::udp::endpoint remote_endpoint_recv_;
+
+ asio::steady_timer timer_;
+
+#ifdef LINUX
+ asio::steady_timer send_timer_;
+ struct iovec tx_iovecs_[max_burst][8];
+ struct mmsghdr tx_msgs_[max_burst];
+ struct iovec rx_iovecs_[max_burst][8];
+ struct mmsghdr rx_msgs_[max_burst];
+ std::uint8_t current_position_;
+#else
+ std::pair<uint8_t *, std::size_t> read_msg_;
+#endif
+
+ bool data_available_;
+};
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/forwarder/udp_tunnel_listener.cc b/libtransport/src/io_modules/forwarder/udp_tunnel_listener.cc
new file mode 100644
index 000000000..12246c3cf
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/udp_tunnel_listener.cc
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ */
+
+#include <hicn/transport/utils/hash.h>
+#include <hicn/transport/utils/log.h>
+#include <io_modules/forwarder/udp_tunnel.h>
+#include <io_modules/forwarder/udp_tunnel_listener.h>
+
+#ifndef LINUX
+namespace std {
+size_t hash<asio::ip::udp::endpoint>::operator()(
+ const asio::ip::udp::endpoint &endpoint) const {
+ auto hash_ip = endpoint.address().is_v4()
+ ? endpoint.address().to_v4().to_ulong()
+ : utils::hash::fnv32_buf(
+ endpoint.address().to_v6().to_bytes().data(), 16);
+ uint16_t port = endpoint.port();
+ return utils::hash::fnv32_buf(&port, 2, hash_ip);
+}
+} // namespace std
+#endif
+
+namespace transport {
+namespace core {
+
+UdpTunnelListener::~UdpTunnelListener() {}
+
+void UdpTunnelListener::close() {
+ strand_->post([this]() {
+ if (socket_->is_open()) {
+ socket_->close();
+ }
+ });
+}
+
+#ifdef LINUX
+void UdpTunnelListener::readHandler(std::error_code ec) {
+ TRANSPORT_LOGD("UdpTunnelConnector receive packet");
+
+ // TRANSPORT_LOGD("UdpTunnelConnector received packet length=%lu", length);
+ if (TRANSPORT_EXPECT_TRUE(!ec)) {
+ if (current_position_ == 0) {
+ for (int i = 0; i < Connector::max_burst; i++) {
+ auto read_buffer = Connector::getRawBuffer();
+ iovecs_[i][0].iov_base = read_buffer.first;
+ iovecs_[i][0].iov_len = read_buffer.second;
+ msgs_[i].msg_hdr.msg_iov = iovecs_[i];
+ msgs_[i].msg_hdr.msg_iovlen = 1;
+ msgs_[i].msg_hdr.msg_name = &remote_endpoints_[i];
+ msgs_[i].msg_hdr.msg_namelen = sizeof(remote_endpoints_[i]);
+ }
+ }
+
+ int res = recvmmsg(socket_->native_handle(), msgs_ + current_position_,
+ Connector::max_burst - current_position_, MSG_DONTWAIT,
+ nullptr);
+ if (res < 0) {
+ TRANSPORT_LOGE("Error in recvmmsg.");
+ }
+
+ for (int i = 0; i < res; i++) {
+ auto packet = Connector::getPacketFromBuffer(
+ reinterpret_cast<uint8_t *>(
+ msgs_[current_position_].msg_hdr.msg_iov[0].iov_base),
+ msgs_[current_position_].msg_len);
+ auto connector_id =
+ utils::hash::fnv64_buf(msgs_[current_position_].msg_hdr.msg_name,
+ msgs_[current_position_].msg_hdr.msg_namelen);
+
+ auto connector = connectors_.find(connector_id);
+ if (connector == connectors_.end()) {
+ // Create new connector corresponding to new client
+
+ /*
+ * Get the remote endpoint for this particular message
+ */
+ using namespace asio::ip;
+ if (local_endpoint_.address().is_v4()) {
+ auto addr = reinterpret_cast<struct sockaddr_in *>(
+ &remote_endpoints_[current_position_]);
+ address_v4::bytes_type address_bytes;
+ std::copy_n(reinterpret_cast<uint8_t *>(&addr->sin_addr),
+ address_bytes.size(), address_bytes.begin());
+ address_v4 address(address_bytes);
+ remote_endpoint_ = udp::endpoint(address, ntohs(addr->sin_port));
+ } else {
+ auto addr = reinterpret_cast<struct sockaddr_in6 *>(
+ &remote_endpoints_[current_position_]);
+ address_v6::bytes_type address_bytes;
+ std::copy_n(reinterpret_cast<uint8_t *>(&addr->sin6_addr),
+ address_bytes.size(), address_bytes.begin());
+ address_v6 address(address_bytes);
+ remote_endpoint_ = udp::endpoint(address, ntohs(addr->sin6_port));
+ }
+
+ /**
+ * Create new connector sharing the same socket of this listener.
+ */
+ auto ret = connectors_.emplace(
+ connector_id,
+ std::make_shared<UdpTunnelConnector>(
+ socket_, strand_, receive_callback_,
+ [](Connector *, const std::error_code &) {}, [](Connector *) {},
+ [](Connector *) {}, std::move(remote_endpoint_)));
+ connector = ret.first;
+ connector->second->setConnectorId(connector_id);
+ }
+
+ /**
+ * Use connector callback to process incoming message.
+ */
+ UdpTunnelConnector *c =
+ dynamic_cast<UdpTunnelConnector *>(connector->second.get());
+ c->doRecvPacket(*packet);
+
+ ++current_position_;
+ }
+
+ doRecvPacket();
+ } else if (ec.value() == static_cast<int>(std::errc::operation_canceled)) {
+ TRANSPORT_LOGE("The connection has been closed by the application.");
+ return;
+ } else {
+ TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ }
+}
+#endif
+
+void UdpTunnelListener::doRecvPacket() {
+#ifdef LINUX
+#if ((ASIO_VERSION / 100 % 1000) < 11)
+ socket_->async_receive(
+ asio::null_buffers(),
+#else
+ socket_->async_wait(
+ asio::ip::tcp::socket::wait_read,
+#endif
+ std::bind(&UdpTunnelListener::readHandler, this, std::placeholders::_1));
+#else
+ read_msg_ = Connector::getRawBuffer();
+ socket_->async_receive_from(
+ asio::buffer(read_msg_.first, read_msg_.second), remote_endpoint_,
+ [this](std::error_code ec, std::size_t length) {
+ if (TRANSPORT_EXPECT_TRUE(!ec)) {
+ auto packet = Connector::getPacketFromBuffer(read_msg_.first, length);
+ auto connector_id =
+ std::hash<asio::ip::udp::endpoint>{}(remote_endpoint_);
+ auto connector = connectors_.find(connector_id);
+ if (connector == connectors_.end()) {
+ // Create new connector corresponding to new client
+ auto ret = connectors_.emplace(
+ connector_id, std::make_shared<UdpTunnelConnector>(
+ socket_, strand_, receive_callback_,
+ [](Connector *, const std::error_code &) {},
+ [](Connector *) {}, [](Connector *) {},
+ std::move(remote_endpoint_)));
+ connector = ret.first;
+ connector->second->setConnectorId(connector_id);
+ }
+
+ UdpTunnelConnector *c =
+ dynamic_cast<UdpTunnelConnector *>(connector->second.get());
+ c->doRecvPacket(*packet);
+ doRecvPacket();
+ } else if (ec.value() ==
+ static_cast<int>(std::errc::operation_canceled)) {
+ TRANSPORT_LOGE("The connection has been closed by the application.");
+ return;
+ } else {
+ TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ }
+ });
+#endif
+}
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/io_modules/forwarder/udp_tunnel_listener.h b/libtransport/src/io_modules/forwarder/udp_tunnel_listener.h
new file mode 100644
index 000000000..0ee40a400
--- /dev/null
+++ b/libtransport/src/io_modules/forwarder/udp_tunnel_listener.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/connector.h>
+#include <hicn/transport/portability/platform.h>
+
+#include <asio.hpp>
+#include <asio/steady_timer.hpp>
+#include <unordered_map>
+
+namespace std {
+template <>
+struct hash<asio::ip::udp::endpoint> {
+ size_t operator()(const asio::ip::udp::endpoint &endpoint) const;
+};
+} // namespace std
+
+namespace transport {
+namespace core {
+
+class UdpTunnelListener
+ : public std::enable_shared_from_this<UdpTunnelListener> {
+ using PacketReceivedCallback = Connector::PacketReceivedCallback;
+ using EndpointId = std::pair<uint32_t, uint16_t>;
+
+ static constexpr uint16_t default_port = 5004;
+
+ public:
+ using Ptr = std::shared_ptr<UdpTunnelListener>;
+
+ template <typename ReceiveCallback>
+ UdpTunnelListener(asio::io_service &io_service,
+ ReceiveCallback &&receive_callback,
+ asio::ip::udp::endpoint endpoint = asio::ip::udp::endpoint(
+ asio::ip::udp::v4(), default_port))
+ : io_service_(io_service),
+ strand_(std::make_shared<asio::io_service::strand>(io_service_)),
+ socket_(std::make_shared<asio::ip::udp::socket>(io_service_,
+ endpoint.protocol())),
+ local_endpoint_(endpoint),
+ receive_callback_(std::forward<ReceiveCallback &&>(receive_callback)),
+#ifndef LINUX
+ read_msg_(nullptr, 0)
+#else
+ iovecs_{0},
+ msgs_{0},
+ current_position_(0)
+#endif
+ {
+ if (endpoint.protocol() == asio::ip::udp::v6()) {
+ std::error_code ec;
+ socket_->set_option(asio::ip::v6_only(false), ec);
+ // Call succeeds only on dual stack systems.
+ }
+ socket_->bind(local_endpoint_);
+ io_service_.post(std::bind(&UdpTunnelListener::doRecvPacket, this));
+ }
+
+ ~UdpTunnelListener();
+
+ void close();
+
+ int deleteConnector(Connector *connector) {
+ return connectors_.erase(connector->getConnectorId());
+ }
+
+ template <typename ReceiveCallback>
+ void setReceiveCallback(ReceiveCallback &&callback) {
+ receive_callback_ = std::forward<ReceiveCallback &&>(callback);
+ }
+
+ Connector *findConnector(Connector::Id connId) {
+ auto it = connectors_.find(connId);
+ if (it != connectors_.end()) {
+ return it->second.get();
+ }
+
+ return nullptr;
+ }
+
+ private:
+ void doRecvPacket();
+
+ void readHandler(std::error_code ec);
+
+ asio::io_service &io_service_;
+ std::shared_ptr<asio::io_service::strand> strand_;
+ std::shared_ptr<asio::ip::udp::socket> socket_;
+ asio::ip::udp::endpoint local_endpoint_;
+ asio::ip::udp::endpoint remote_endpoint_;
+ std::unordered_map<Connector::Id, std::shared_ptr<Connector>> connectors_;
+
+ PacketReceivedCallback receive_callback_;
+
+#ifdef LINUX
+ struct iovec iovecs_[Connector::max_burst][8];
+ struct mmsghdr msgs_[Connector::max_burst];
+ struct sockaddr_storage remote_endpoints_[Connector::max_burst];
+ std::uint8_t current_position_;
+#else
+ std::pair<uint8_t *, std::size_t> read_msg_;
+#endif
+};
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/loopback/CMakeLists.txt b/libtransport/src/io_modules/loopback/CMakeLists.txt
new file mode 100644
index 000000000..ac6dc8068
--- /dev/null
+++ b/libtransport/src/io_modules/loopback/CMakeLists.txt
@@ -0,0 +1,34 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+
+list(APPEND MODULE_HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/loopback_module.h
+)
+
+list(APPEND MODULE_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/loopback_module.cc
+)
+
+build_module(loopback_module
+ SHARED
+ SOURCES ${MODULE_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT lib${LIBTRANSPORT}
+ INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ # LIBRARY_ROOT_DIR "vpp_plugins"
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILE_FLAGS}
+)
diff --git a/libtransport/src/io_modules/loopback/local_face.cc b/libtransport/src/io_modules/loopback/local_face.cc
new file mode 100644
index 000000000..a59dab235
--- /dev/null
+++ b/libtransport/src/io_modules/loopback/local_face.cc
@@ -0,0 +1,69 @@
+/*
+ * 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/transport/core/content_object.h>
+#include <hicn/transport/core/interest.h>
+#include <hicn/transport/utils/log.h>
+#include <io_modules/loopback/local_face.h>
+
+#include <asio/io_service.hpp>
+
+namespace transport {
+namespace core {
+
+Face::Face(Connector::PacketReceivedCallback &&receive_callback,
+ asio::io_service &io_service, const std::string &app_name)
+ : receive_callback_(std::move(receive_callback)),
+ io_service_(io_service),
+ name_(app_name) {}
+
+Face::Face(const Face &other)
+ : receive_callback_(other.receive_callback_),
+ io_service_(other.io_service_),
+ name_(other.name_) {}
+
+Face::Face(Face &&other)
+ : receive_callback_(std::move(other.receive_callback_)),
+ io_service_(other.io_service_),
+ name_(std::move(other.name_)) {}
+
+Face &Face::operator=(const Face &other) {
+ receive_callback_ = other.receive_callback_;
+ io_service_ = other.io_service_;
+ name_ = other.name_;
+
+ return *this;
+}
+
+Face &Face::operator=(Face &&other) {
+ receive_callback_ = std::move(other.receive_callback_);
+ io_service_ = std::move(other.io_service_);
+ name_ = std::move(other.name_);
+
+ return *this;
+}
+
+void Face::onPacket(const Packet &packet) {
+ TRANSPORT_LOGD("Sending content to local socket.");
+
+ if (Packet::isInterest(packet.data())) {
+ rescheduleOnIoService<Interest>(packet);
+ } else {
+ rescheduleOnIoService<ContentObject>(packet);
+ }
+}
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/io_modules/loopback/local_face.h b/libtransport/src/io_modules/loopback/local_face.h
new file mode 100644
index 000000000..1cbcc2c72
--- /dev/null
+++ b/libtransport/src/io_modules/loopback/local_face.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/connector.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/utils/move_wrapper.h>
+
+#include <asio/io_service.hpp>
+
+namespace transport {
+namespace core {
+
+class Face {
+ public:
+ Face(Connector::PacketReceivedCallback &&receive_callback,
+ asio::io_service &io_service, const std::string &app_name);
+
+ Face(const Face &other);
+ Face(Face &&other);
+ void onPacket(const Packet &packet);
+ Face &operator=(Face &&other);
+ Face &operator=(const Face &other);
+
+ private:
+ template <typename T>
+ void rescheduleOnIoService(const Packet &packet) {
+ auto p = core::PacketManager<T>::getInstance().getPacket();
+ p->replace(packet.data(), packet.length());
+ io_service_.get().post([this, p]() mutable {
+ receive_callback_(nullptr, *p, make_error_code(0));
+ });
+ }
+
+ Connector::PacketReceivedCallback receive_callback_;
+ std::reference_wrapper<asio::io_service> io_service_;
+ std::string name_;
+};
+
+} // namespace core
+} // namespace transport
diff --git a/libtransport/src/io_modules/loopback/loopback_module.cc b/libtransport/src/io_modules/loopback/loopback_module.cc
new file mode 100644
index 000000000..0bdbf8c8e
--- /dev/null
+++ b/libtransport/src/io_modules/loopback/loopback_module.cc
@@ -0,0 +1,84 @@
+/*
+ * 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/transport/errors/not_implemented_exception.h>
+#include <hicn/transport/utils/log.h>
+#include <io_modules/loopback/loopback_module.h>
+
+namespace transport {
+
+namespace core {
+
+std::vector<std::unique_ptr<LocalConnector>> LoopbackModule::local_faces_;
+std::atomic<uint32_t> LoopbackModule::global_counter_(0);
+
+LoopbackModule::LoopbackModule() : IoModule(), local_id_(~0) {}
+
+LoopbackModule::~LoopbackModule() {}
+
+void LoopbackModule::connect(bool is_consumer) {}
+
+bool LoopbackModule::isConnected() { return true; }
+
+void LoopbackModule::send(Packet &packet) {
+ IoModule::send(packet);
+
+ TRANSPORT_LOGD("LoopbackModule: sending from %u to %d", local_id_,
+ 1 - local_id_);
+
+ local_faces_.at(1 - local_id_)->send(packet);
+}
+
+void LoopbackModule::send(const uint8_t *packet, std::size_t len) {
+ // not supported
+ throw errors::NotImplementedException();
+}
+
+void LoopbackModule::registerRoute(const Prefix &prefix) {
+ // For the moment we route packets from one socket to the other.
+ // Next step will be to introduce a FIB
+ return;
+}
+
+void LoopbackModule::closeConnection() {
+ local_faces_.erase(local_faces_.begin() + local_id_);
+}
+
+void LoopbackModule::init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::OnReconnectCallback &&reconnect_callback,
+ asio::io_service &io_service,
+ const std::string &app_name) {
+ if (local_id_ == uint32_t(~0) && global_counter_ < 2) {
+ local_id_ = global_counter_++;
+ local_faces_.emplace(
+ local_faces_.begin() + local_id_,
+ new LocalConnector(io_service, std::move(receive_callback), nullptr,
+ nullptr, std::move(reconnect_callback)));
+ }
+}
+
+void LoopbackModule::processControlMessageReply(utils::MemBuf &packet_buffer) {
+ return;
+}
+
+std::uint32_t LoopbackModule::getMtu() { return interface_mtu; }
+
+bool LoopbackModule::isControlMessage(const uint8_t *message) { return false; }
+
+extern "C" IoModule *create_module(void) { return new LoopbackModule(); }
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/loopback/loopback_module.h b/libtransport/src/io_modules/loopback/loopback_module.h
new file mode 100644
index 000000000..219fa8841
--- /dev/null
+++ b/libtransport/src/io_modules/loopback/loopback_module.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <core/local_connector.h>
+#include <hicn/transport/core/io_module.h>
+#include <hicn/transport/core/prefix.h>
+
+#include <atomic>
+
+namespace transport {
+
+namespace core {
+
+class LoopbackModule : public IoModule {
+ static constexpr std::uint16_t interface_mtu = 1500;
+
+ public:
+ LoopbackModule();
+
+ ~LoopbackModule();
+
+ void connect(bool is_consumer) override;
+
+ void send(Packet &packet) override;
+ void send(const uint8_t *packet, std::size_t len) override;
+
+ bool isConnected() override;
+
+ void init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::OnReconnectCallback &&reconnect_callback,
+ asio::io_service &io_service,
+ const std::string &app_name = "Libtransport") override;
+
+ void registerRoute(const Prefix &prefix) override;
+
+ std::uint32_t getMtu() override;
+
+ bool isControlMessage(const uint8_t *message) override;
+
+ void processControlMessageReply(utils::MemBuf &packet_buffer) override;
+
+ void closeConnection() override;
+
+ private:
+ static std::vector<std::unique_ptr<LocalConnector>> local_faces_;
+ static std::atomic<uint32_t> global_counter_;
+
+ private:
+ uint32_t local_id_;
+};
+
+extern "C" IoModule *create_module(void);
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/memif/CMakeLists.txt b/libtransport/src/io_modules/memif/CMakeLists.txt
new file mode 100644
index 000000000..c8a930e7b
--- /dev/null
+++ b/libtransport/src/io_modules/memif/CMakeLists.txt
@@ -0,0 +1,56 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+find_package(Vpp REQUIRED)
+find_package(Libmemif REQUIRED)
+
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ find_package(HicnPlugin REQUIRED)
+ find_package(SafeVapi REQUIRED)
+else()
+ list(APPEND DEPENDENCIES
+ ${SAFE_VAPI_SHARED}
+ )
+endif()
+
+list(APPEND MODULE_HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_vapi.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/memif_connector.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/memif_vapi.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/vpp_forwarder_module.h
+)
+
+list(APPEND MODULE_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_vapi.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/memif_connector.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/memif_vapi.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/vpp_forwarder_module.cc
+)
+
+build_module(memif_module
+ SHARED
+ SOURCES ${MODULE_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT lib${LIBTRANSPORT}
+ LINK_LIBRARIES ${LIBMEMIF_LIBRARIES} ${SAFE_VAPI_LIBRARIES}
+ INCLUDE_DIRS
+ ${LIBTRANSPORT_INCLUDE_DIRS}
+ ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ ${VPP_INCLUDE_DIRS}
+ ${LIBMEMIF_INCLUDE_DIRS}
+ ${SAFE_VAPI_INCLUDE_DIRS}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILE_FLAGS}
+)
diff --git a/libtransport/src/io_modules/memif/hicn_vapi.c b/libtransport/src/io_modules/memif/hicn_vapi.c
new file mode 100644
index 000000000..b83a36b47
--- /dev/null
+++ b/libtransport/src/io_modules/memif/hicn_vapi.c
@@ -0,0 +1,229 @@
+/*
+ * 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/transport/config.h>
+#include <hicn/transport/utils/log.h>
+#include <io_modules/memif/hicn_vapi.h>
+
+#define HICN_VPP_PLUGIN
+#include <hicn/name.h>
+#undef HICN_VPP_PLUGIN
+
+#include <vapi/hicn.api.vapi.h>
+#include <vapi/ip.api.vapi.h>
+#include <vapi/vapi_safe.h>
+#include <vlib/vlib.h>
+#include <vlibapi/api.h>
+#include <vlibmemory/api.h>
+#include <vnet/ip/format.h>
+#include <vnet/ip/ip4_packet.h>
+#include <vnet/ip/ip6_packet.h>
+#include <vpp_plugins/hicn/error.h>
+#include <vppinfra/error.h>
+
+/////////////////////////////////////////////////////
+const char *HICN_ERROR_STRING[] = {
+#define _(a, b, c) c,
+ foreach_hicn_error
+#undef _
+};
+/////////////////////////////////////////////////////
+
+/*********************** Missing Symbol in vpp libraries
+ * *************************/
+u8 *format_vl_api_address_union(u8 *s, va_list *args) { return NULL; }
+
+/*********************************************************************************/
+
+DEFINE_VAPI_MSG_IDS_HICN_API_JSON
+DEFINE_VAPI_MSG_IDS_IP_API_JSON
+
+static vapi_error_e register_prod_app_cb(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_register_prod_app_reply *reply) {
+ hicn_producer_output_params *output_params =
+ (hicn_producer_output_params *)callback_ctx;
+
+ if (reply == NULL) return rv;
+
+ output_params->cs_reserved = reply->cs_reserved;
+ output_params->prod_addr = (ip_address_t *)malloc(sizeof(ip_address_t));
+ memset(output_params->prod_addr, 0, sizeof(ip_address_t));
+ if (reply->prod_addr.af == ADDRESS_IP6)
+ memcpy(&output_params->prod_addr->v6, reply->prod_addr.un.ip6,
+ sizeof(ip6_address_t));
+ else
+ memcpy(&output_params->prod_addr->v4, reply->prod_addr.un.ip4,
+ sizeof(ip4_address_t));
+ output_params->face_id = reply->faceid;
+
+ return reply->retval;
+}
+
+int hicn_vapi_register_prod_app(vapi_ctx_t ctx,
+ hicn_producer_input_params *input_params,
+ hicn_producer_output_params *output_params) {
+ vapi_lock();
+ vapi_msg_hicn_api_register_prod_app *msg =
+ vapi_alloc_hicn_api_register_prod_app(ctx);
+
+ if (ip46_address_is_ip4((ip46_address_t *)&input_params->prefix->address)) {
+ memcpy(&msg->payload.prefix.address.un.ip4, &input_params->prefix->address,
+ sizeof(ip4_address_t));
+ msg->payload.prefix.address.af = ADDRESS_IP4;
+ } else {
+ memcpy(&msg->payload.prefix.address.un.ip6, &input_params->prefix->address,
+ sizeof(ip6_address_t));
+ msg->payload.prefix.address.af = ADDRESS_IP6;
+ }
+ msg->payload.prefix.len = input_params->prefix->len;
+
+ msg->payload.swif = input_params->swif;
+ msg->payload.cs_reserved = input_params->cs_reserved;
+
+ int ret = vapi_hicn_api_register_prod_app(ctx, msg, register_prod_app_cb,
+ output_params);
+ vapi_unlock();
+ return ret;
+}
+
+static vapi_error_e face_prod_del_cb(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_face_prod_del_reply *reply) {
+ if (reply == NULL) return rv;
+
+ return reply->retval;
+}
+
+int hicn_vapi_face_prod_del(vapi_ctx_t ctx,
+ hicn_del_face_app_input_params *input_params) {
+ vapi_lock();
+ vapi_msg_hicn_api_face_prod_del *msg = vapi_alloc_hicn_api_face_prod_del(ctx);
+
+ msg->payload.faceid = input_params->face_id;
+
+ int ret = vapi_hicn_api_face_prod_del(ctx, msg, face_prod_del_cb, NULL);
+ vapi_unlock();
+ return ret;
+}
+
+static vapi_error_e register_cons_app_cb(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_register_cons_app_reply *reply) {
+ hicn_consumer_output_params *output_params =
+ (hicn_consumer_output_params *)callback_ctx;
+
+ if (reply == NULL) return rv;
+
+ output_params->src6 = (ip_address_t *)malloc(sizeof(ip_address_t));
+ output_params->src4 = (ip_address_t *)malloc(sizeof(ip_address_t));
+ memset(output_params->src6, 0, sizeof(ip_address_t));
+ memset(output_params->src4, 0, sizeof(ip_address_t));
+ memcpy(&output_params->src6->v6, &reply->src_addr6.un.ip6,
+ sizeof(ip6_address_t));
+ memcpy(&output_params->src4->v4, &reply->src_addr4.un.ip4,
+ sizeof(ip4_address_t));
+
+ output_params->face_id1 = reply->faceid1;
+ output_params->face_id2 = reply->faceid2;
+
+ return reply->retval;
+}
+
+int hicn_vapi_register_cons_app(vapi_ctx_t ctx,
+ hicn_consumer_input_params *input_params,
+ hicn_consumer_output_params *output_params) {
+ vapi_lock();
+ vapi_msg_hicn_api_register_cons_app *msg =
+ vapi_alloc_hicn_api_register_cons_app(ctx);
+
+ msg->payload.swif = input_params->swif;
+
+ int ret = vapi_hicn_api_register_cons_app(ctx, msg, register_cons_app_cb,
+ output_params);
+ vapi_unlock();
+ return ret;
+}
+
+static vapi_error_e face_cons_del_cb(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_face_cons_del_reply *reply) {
+ if (reply == NULL) return rv;
+
+ return reply->retval;
+}
+
+int hicn_vapi_face_cons_del(vapi_ctx_t ctx,
+ hicn_del_face_app_input_params *input_params) {
+ vapi_lock();
+ vapi_msg_hicn_api_face_cons_del *msg = vapi_alloc_hicn_api_face_cons_del(ctx);
+
+ msg->payload.faceid = input_params->face_id;
+
+ int ret = vapi_hicn_api_face_cons_del(ctx, msg, face_cons_del_cb, NULL);
+ vapi_unlock();
+ return ret;
+}
+
+static vapi_error_e reigster_route_cb(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_ip_route_add_del_reply *reply) {
+ if (reply == NULL) return rv;
+
+ return reply->retval;
+}
+
+int hicn_vapi_register_route(vapi_ctx_t ctx,
+ hicn_producer_set_route_params *input_params) {
+ vapi_lock();
+ vapi_msg_ip_route_add_del *msg = vapi_alloc_ip_route_add_del(ctx, 1);
+
+ msg->payload.is_add = 1;
+ if (ip46_address_is_ip4((ip46_address_t *)(input_params->prod_addr))) {
+ memcpy(&msg->payload.route.prefix.address.un.ip4,
+ &input_params->prefix->address.v4, sizeof(ip4_address_t));
+ msg->payload.route.prefix.address.af = ADDRESS_IP4;
+ msg->payload.route.prefix.len = input_params->prefix->len;
+ } else {
+ memcpy(&msg->payload.route.prefix.address.un.ip6,
+ &input_params->prefix->address.v6, sizeof(ip6_address_t));
+ msg->payload.route.prefix.address.af = ADDRESS_IP6;
+ msg->payload.route.prefix.len = input_params->prefix->len;
+ }
+
+ msg->payload.route.paths[0].sw_if_index = ~0;
+ msg->payload.route.paths[0].table_id = 0;
+ if (ip46_address_is_ip4((ip46_address_t *)(input_params->prod_addr))) {
+ memcpy(&(msg->payload.route.paths[0].nh.address.ip4),
+ input_params->prod_addr->v4.as_u8, sizeof(ip4_address_t));
+ msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
+ } else {
+ memcpy(&(msg->payload.route.paths[0].nh.address.ip6),
+ input_params->prod_addr->v6.as_u8, sizeof(ip6_address_t));
+ msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
+ }
+
+ msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE;
+ msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
+
+ int ret = vapi_ip_route_add_del(ctx, msg, reigster_route_cb, NULL);
+
+ vapi_unlock();
+ return ret;
+}
+
+char *hicn_vapi_get_error_string(int ret_val) {
+ return get_error_string(ret_val);
+}
diff --git a/libtransport/src/io_modules/memif/hicn_vapi.h b/libtransport/src/io_modules/memif/hicn_vapi.h
new file mode 100644
index 000000000..e94c97749
--- /dev/null
+++ b/libtransport/src/io_modules/memif/hicn_vapi.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/config.h>
+#include <hicn/util/ip_address.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <vapi/vapi.h>
+
+#include "stdint.h"
+
+typedef struct {
+ ip_prefix_t* prefix;
+ uint32_t swif;
+ uint32_t cs_reserved;
+} hicn_producer_input_params;
+
+typedef struct {
+ uint32_t swif;
+} hicn_consumer_input_params;
+
+typedef struct {
+ uint32_t face_id;
+} hicn_del_face_app_input_params;
+
+typedef struct {
+ uint32_t cs_reserved;
+ ip_address_t* prod_addr;
+ uint32_t face_id;
+} hicn_producer_output_params;
+
+typedef struct {
+ ip_address_t* src4;
+ ip_address_t* src6;
+ uint32_t face_id1;
+ uint32_t face_id2;
+} hicn_consumer_output_params;
+
+typedef struct {
+ ip_prefix_t* prefix;
+ ip_address_t* prod_addr;
+} hicn_producer_set_route_params;
+
+int hicn_vapi_register_prod_app(vapi_ctx_t ctx,
+ hicn_producer_input_params* input_params,
+ hicn_producer_output_params* output_params);
+
+int hicn_vapi_register_cons_app(vapi_ctx_t ctx,
+ hicn_consumer_input_params* input_params,
+ hicn_consumer_output_params* output_params);
+
+int hicn_vapi_register_route(vapi_ctx_t ctx,
+ hicn_producer_set_route_params* input_params);
+
+int hicn_vapi_face_cons_del(vapi_ctx_t ctx,
+ hicn_del_face_app_input_params* input_params);
+
+int hicn_vapi_face_prod_del(vapi_ctx_t ctx,
+ hicn_del_face_app_input_params* input_params);
+
+char* hicn_vapi_get_error_string(int ret_val);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libtransport/src/io_modules/memif/memif_connector.cc b/libtransport/src/io_modules/memif/memif_connector.cc
new file mode 100644
index 000000000..4a688d68f
--- /dev/null
+++ b/libtransport/src/io_modules/memif/memif_connector.cc
@@ -0,0 +1,493 @@
+/*
+ * 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 <hicn/transport/errors/not_implemented_exception.h>
+#include <io_modules/memif/memif_connector.h>
+#include <sys/epoll.h>
+
+#include <cstdlib>
+
+extern "C" {
+#include <memif/libmemif.h>
+};
+
+#define CANCEL_TIMER 1
+
+namespace transport {
+
+namespace core {
+
+struct memif_connection {
+ uint16_t index;
+ /* memif conenction handle */
+ memif_conn_handle_t conn;
+ /* transmit queue id */
+ uint16_t tx_qid;
+ /* tx buffers */
+ memif_buffer_t *tx_bufs;
+ /* allocated tx buffers counter */
+ /* number of tx buffers pointing to shared memory */
+ uint16_t tx_buf_num;
+ /* rx buffers */
+ memif_buffer_t *rx_bufs;
+ /* allcoated rx buffers counter */
+ /* number of rx buffers pointing to shared memory */
+ uint16_t rx_buf_num;
+ /* interface ip address */
+ uint8_t ip_addr[4];
+};
+
+std::once_flag MemifConnector::flag_;
+utils::EpollEventReactor MemifConnector::main_event_reactor_;
+
+MemifConnector::MemifConnector(PacketReceivedCallback &&receive_callback,
+ PacketSentCallback &&packet_sent,
+ OnCloseCallback &&close_callback,
+ OnReconnectCallback &&on_reconnect,
+ asio::io_service &io_service,
+ std::string app_name)
+ : Connector(std::move(receive_callback), std::move(packet_sent),
+ std::move(close_callback), std::move(on_reconnect)),
+ memif_worker_(nullptr),
+ timer_set_(false),
+ send_timer_(std::make_unique<utils::FdDeadlineTimer>(event_reactor_)),
+ disconnect_timer_(
+ std::make_unique<utils::FdDeadlineTimer>(event_reactor_)),
+ io_service_(io_service),
+ memif_connection_(std::make_unique<memif_connection_t>()),
+ tx_buf_counter_(0),
+ is_reconnection_(false),
+ data_available_(false),
+ app_name_(app_name),
+ socket_filename_("") {
+ std::call_once(MemifConnector::flag_, &MemifConnector::init, this);
+}
+
+MemifConnector::~MemifConnector() { close(); }
+
+void MemifConnector::init() {
+ /* initialize memory interface */
+ int err = memif_init(controlFdUpdate, const_cast<char *>(app_name_.c_str()),
+ nullptr, nullptr, nullptr);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ TRANSPORT_LOGE("memif_init: %s", memif_strerror(err));
+ }
+}
+
+void MemifConnector::connect(uint32_t memif_id, long memif_mode) {
+ state_ = State::CONNECTING;
+
+ memif_id_ = memif_id;
+ socket_filename_ = "/run/vpp/memif.sock";
+
+ createMemif(memif_id, memif_mode, nullptr);
+
+ work_ = std::make_unique<asio::io_service::work>(io_service_);
+
+ while (state_ != State::CONNECTED) {
+ MemifConnector::main_event_reactor_.runOneEvent();
+ }
+
+ int err;
+
+ /* get interrupt queue id */
+ int fd = -1;
+ err = memif_get_queue_efd(memif_connection_->conn, 0, &fd);
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ TRANSPORT_LOGE("memif_get_queue_efd: %s", memif_strerror(err));
+ return;
+ }
+
+ // Remove fd from main epoll
+ main_event_reactor_.delFileDescriptor(fd);
+
+ // Add fd to epoll of instance
+ event_reactor_.addFileDescriptor(
+ fd, EPOLLIN, [this](const utils::Event &evt) -> int {
+ return onInterrupt(memif_connection_->conn, this, 0);
+ });
+
+ memif_worker_ = std::make_unique<std::thread>(
+ std::bind(&MemifConnector::threadMain, this));
+}
+
+int MemifConnector::createMemif(uint32_t index, uint8_t mode, char *s) {
+ memif_connection_t *c = memif_connection_.get();
+
+ /* setting memif connection arguments */
+ memif_conn_args_t args;
+ memset(&args, 0, sizeof(args));
+
+ args.is_master = mode;
+ args.log2_ring_size = MEMIF_LOG2_RING_SIZE;
+ args.buffer_size = MEMIF_BUF_SIZE;
+ args.num_s2m_rings = 1;
+ args.num_m2s_rings = 1;
+ strncpy((char *)args.interface_name, IF_NAME, strlen(IF_NAME) + 1);
+ args.mode = memif_interface_mode_t::MEMIF_INTERFACE_MODE_IP;
+
+ int err;
+
+ err = memif_create_socket(&args.socket, socket_filename_.c_str(), nullptr);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ throw errors::RuntimeException(memif_strerror(err));
+ }
+
+ args.interface_id = index;
+ /* last argument for memif_create (void * private_ctx) is used by user
+ to identify connection. this context is returned with callbacks */
+
+ /* default interrupt */
+ if (s == nullptr) {
+ err = memif_create(&c->conn, &args, onConnect, onDisconnect, onInterrupt,
+ this);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ throw errors::RuntimeException(memif_strerror(err));
+ }
+ }
+
+ c->index = (uint16_t)index;
+ c->tx_qid = 0;
+ /* alloc memif buffers */
+ c->rx_buf_num = 0;
+ c->rx_bufs = static_cast<memif_buffer_t *>(
+ malloc(sizeof(memif_buffer_t) * MAX_MEMIF_BUFS));
+ c->tx_buf_num = 0;
+ c->tx_bufs = static_cast<memif_buffer_t *>(
+ malloc(sizeof(memif_buffer_t) * MAX_MEMIF_BUFS));
+
+ // memif_set_rx_mode (c->conn, MEMIF_RX_MODE_POLLING, 0);
+
+ return 0;
+}
+
+int MemifConnector::deleteMemif() {
+ memif_connection_t *c = memif_connection_.get();
+
+ if (c->rx_bufs) {
+ free(c->rx_bufs);
+ }
+
+ c->rx_bufs = nullptr;
+ c->rx_buf_num = 0;
+
+ if (c->tx_bufs) {
+ free(c->tx_bufs);
+ }
+
+ c->tx_bufs = nullptr;
+ c->tx_buf_num = 0;
+
+ int err;
+ /* disconenct then delete memif connection */
+ err = memif_delete(&c->conn);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ TRANSPORT_LOGE("memif_delete: %s", memif_strerror(err));
+ }
+
+ if (TRANSPORT_EXPECT_FALSE(c->conn != nullptr)) {
+ TRANSPORT_LOGE("memif delete fail");
+ }
+
+ return 0;
+}
+
+int MemifConnector::controlFdUpdate(int fd, uint8_t events, void *private_ctx) {
+ /* convert memif event definitions to epoll events */
+ if (events & MEMIF_FD_EVENT_DEL) {
+ return MemifConnector::main_event_reactor_.delFileDescriptor(fd);
+ }
+
+ uint32_t evt = 0;
+
+ if (events & MEMIF_FD_EVENT_READ) {
+ evt |= EPOLLIN;
+ }
+
+ if (events & MEMIF_FD_EVENT_WRITE) {
+ evt |= EPOLLOUT;
+ }
+
+ if (events & MEMIF_FD_EVENT_MOD) {
+ return MemifConnector::main_event_reactor_.modFileDescriptor(fd, evt);
+ }
+
+ return MemifConnector::main_event_reactor_.addFileDescriptor(
+ fd, evt, [](const utils::Event &evt) -> int {
+ uint32_t event = 0;
+ int memif_err = 0;
+
+ if (evt.events & EPOLLIN) {
+ event |= MEMIF_FD_EVENT_READ;
+ }
+
+ if (evt.events & EPOLLOUT) {
+ event |= MEMIF_FD_EVENT_WRITE;
+ }
+
+ if (evt.events & EPOLLERR) {
+ event |= MEMIF_FD_EVENT_ERROR;
+ }
+
+ memif_err = memif_control_fd_handler(evt.data.fd, event);
+
+ if (TRANSPORT_EXPECT_FALSE(memif_err != MEMIF_ERR_SUCCESS)) {
+ TRANSPORT_LOGE("memif_control_fd_handler: %s",
+ memif_strerror(memif_err));
+ }
+
+ return 0;
+ });
+}
+
+int MemifConnector::bufferAlloc(long n, uint16_t qid) {
+ memif_connection_t *c = memif_connection_.get();
+ int err;
+ uint16_t r;
+ /* set data pointer to shared memory and set buffer_len to shared mmeory
+ * buffer len */
+ err = memif_buffer_alloc(c->conn, qid, c->tx_bufs, n, &r, 2000);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ TRANSPORT_LOGE("memif_buffer_alloc: %s", memif_strerror(err));
+ return -1;
+ }
+
+ c->tx_buf_num += r;
+ return r;
+}
+
+int MemifConnector::txBurst(uint16_t qid) {
+ memif_connection_t *c = memif_connection_.get();
+ int err;
+ uint16_t r;
+ /* inform peer memif interface about data in shared memory buffers */
+ /* mark memif buffers as free */
+ err = memif_tx_burst(c->conn, qid, c->tx_bufs, c->tx_buf_num, &r);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ TRANSPORT_LOGE("memif_tx_burst: %s", memif_strerror(err));
+ }
+
+ // err = memif_refill_queue(c->conn, qid, r, 0);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ TRANSPORT_LOGE("memif_tx_burst: %s", memif_strerror(err));
+ c->tx_buf_num -= r;
+ return -1;
+ }
+
+ c->tx_buf_num -= r;
+ return 0;
+}
+
+void MemifConnector::sendCallback(const std::error_code &ec) {
+ timer_set_ = false;
+
+ if (TRANSPORT_EXPECT_TRUE(!ec && state_ == State::CONNECTED)) {
+ doSend();
+ }
+}
+
+void MemifConnector::processInputBuffer(std::uint16_t total_packets) {
+ utils::MemBuf::Ptr ptr;
+
+ for (; total_packets > 0; total_packets--) {
+ if (input_buffer_.pop(ptr)) {
+ receive_callback_(this, *ptr, std::make_error_code(std::errc(0)));
+ }
+ }
+}
+
+/* informs user about connected status. private_ctx is used by user to identify
+ connection (multiple connections WIP) */
+int MemifConnector::onConnect(memif_conn_handle_t conn, void *private_ctx) {
+ MemifConnector *connector = (MemifConnector *)private_ctx;
+ connector->state_ = State::CONNECTED;
+ memif_refill_queue(conn, 0, -1, 0);
+
+ return 0;
+}
+
+/* informs user about disconnected status. private_ctx is used by user to
+ identify connection (multiple connections WIP) */
+int MemifConnector::onDisconnect(memif_conn_handle_t conn, void *private_ctx) {
+ MemifConnector *connector = (MemifConnector *)private_ctx;
+ connector->state_ = State::CLOSED;
+ return 0;
+}
+
+void MemifConnector::threadMain() { event_reactor_.runEventLoop(1000); }
+
+int MemifConnector::onInterrupt(memif_conn_handle_t conn, void *private_ctx,
+ uint16_t qid) {
+ MemifConnector *connector = (MemifConnector *)private_ctx;
+
+ memif_connection_t *c = connector->memif_connection_.get();
+ int err = MEMIF_ERR_SUCCESS, ret_val;
+ uint16_t total_packets = 0;
+ uint16_t rx;
+
+ do {
+ err = memif_rx_burst(conn, qid, c->rx_bufs, MAX_MEMIF_BUFS, &rx);
+ ret_val = err;
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS &&
+ err != MEMIF_ERR_NOBUF)) {
+ TRANSPORT_LOGE("memif_rx_burst: %s", memif_strerror(err));
+ goto error;
+ }
+
+ c->rx_buf_num += rx;
+
+ if (TRANSPORT_EXPECT_FALSE(connector->io_service_.stopped())) {
+ TRANSPORT_LOGE("socket stopped: ignoring %u packets", rx);
+ goto error;
+ }
+
+ std::size_t packet_length;
+ for (int i = 0; i < rx; i++) {
+ auto buffer = connector->getRawBuffer();
+ packet_length = (c->rx_bufs + i)->len;
+ std::memcpy(buffer.first, (c->rx_bufs + i)->data, packet_length);
+ auto packet = connector->getPacketFromBuffer(buffer.first, packet_length);
+
+ if (!connector->input_buffer_.push(std::move(packet))) {
+ TRANSPORT_LOGE("Error pushing packet. Ring buffer full.");
+
+ // TODO Here we should consider the possibility to signal the congestion
+ // to the application, that would react properly (e.g. slow down
+ // message)
+ }
+ }
+
+ /* mark memif buffers and shared memory buffers as free */
+ /* free processed buffers */
+
+ err = memif_refill_queue(conn, qid, rx, 0);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ TRANSPORT_LOGE("memif_buffer_free: %s", memif_strerror(err));
+ }
+
+ c->rx_buf_num -= rx;
+ total_packets += rx;
+
+ } while (ret_val == MEMIF_ERR_NOBUF);
+
+ connector->io_service_.post(
+ std::bind(&MemifConnector::processInputBuffer, connector, total_packets));
+
+ return 0;
+
+error:
+ err = memif_refill_queue(c->conn, qid, rx, 0);
+
+ if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
+ TRANSPORT_LOGE("memif_buffer_free: %s", memif_strerror(err));
+ }
+ c->rx_buf_num -= rx;
+
+ return 0;
+}
+
+void MemifConnector::close() {
+ if (state_ != State::CLOSED) {
+ disconnect_timer_->expiresFromNow(std::chrono::microseconds(50));
+ disconnect_timer_->asyncWait([this](const std::error_code &ec) {
+ deleteMemif();
+ event_reactor_.stop();
+ work_.reset();
+ });
+
+ if (memif_worker_ && memif_worker_->joinable()) {
+ memif_worker_->join();
+ }
+ }
+}
+
+void MemifConnector::send(Packet &packet) {
+ {
+ utils::SpinLock::Acquire locked(write_msgs_lock_);
+ output_buffer_.push_back(packet.shared_from_this());
+ }
+#if CANCEL_TIMER
+ if (!timer_set_) {
+ timer_set_ = true;
+ send_timer_->expiresFromNow(std::chrono::microseconds(50));
+ send_timer_->asyncWait(
+ std::bind(&MemifConnector::sendCallback, this, std::placeholders::_1));
+ }
+#endif
+}
+
+int MemifConnector::doSend() {
+ std::size_t max = 0;
+ int32_t n = 0;
+ std::size_t size = 0;
+
+ {
+ utils::SpinLock::Acquire locked(write_msgs_lock_);
+ size = output_buffer_.size();
+ }
+
+ do {
+ max = size < MAX_MEMIF_BUFS ? size : MAX_MEMIF_BUFS;
+ n = bufferAlloc(max, memif_connection_->tx_qid);
+
+ if (TRANSPORT_EXPECT_FALSE(n < 0)) {
+ TRANSPORT_LOGE("Error allocating buffers.");
+ return -1;
+ }
+
+ for (uint16_t i = 0; i < n; i++) {
+ utils::SpinLock::Acquire locked(write_msgs_lock_);
+
+ auto packet = output_buffer_.front().get();
+ const utils::MemBuf *current = packet;
+ std::size_t offset = 0;
+ uint8_t *shared_buffer =
+ reinterpret_cast<uint8_t *>(memif_connection_->tx_bufs[i].data);
+ do {
+ std::memcpy(shared_buffer + offset, current->data(), current->length());
+ offset += current->length();
+ current = current->next();
+ } while (current != packet);
+
+ memif_connection_->tx_bufs[i].len = uint32_t(offset);
+
+ output_buffer_.pop_front();
+ }
+
+ txBurst(memif_connection_->tx_qid);
+
+ utils::SpinLock::Acquire locked(write_msgs_lock_);
+ size = output_buffer_.size();
+ } while (size > 0);
+
+ return 0;
+}
+
+void MemifConnector::send(const uint8_t *packet, std::size_t len) {
+ throw errors::NotImplementedException();
+}
+
+} // end namespace core
+
+} // end namespace transport
diff --git a/libtransport/src/io_modules/memif/memif_connector.h b/libtransport/src/io_modules/memif/memif_connector.h
new file mode 100644
index 000000000..bed3516dc
--- /dev/null
+++ b/libtransport/src/io_modules/memif/memif_connector.h
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/config.h>
+#include <hicn/transport/core/connector.h>
+#include <hicn/transport/portability/portability.h>
+#include <hicn/transport/utils/ring_buffer.h>
+//#include <hicn/transport/core/hicn_vapi.h>
+#include <utils/epoll_event_reactor.h>
+#include <utils/fd_deadline_timer.h>
+
+#include <asio.hpp>
+#include <deque>
+#include <mutex>
+#include <thread>
+
+#define _Static_assert static_assert
+
+namespace transport {
+
+namespace core {
+
+typedef struct memif_connection memif_connection_t;
+
+#define APP_NAME "libtransport"
+#define IF_NAME "vpp_connection"
+
+#define MEMIF_BUF_SIZE 2048
+#define MEMIF_LOG2_RING_SIZE 13
+#define MAX_MEMIF_BUFS (1 << MEMIF_LOG2_RING_SIZE)
+
+class MemifConnector : public Connector {
+ using memif_conn_handle_t = void *;
+ using PacketRing = utils::CircularFifo<utils::MemBuf::Ptr, queue_size>;
+
+ public:
+ MemifConnector(PacketReceivedCallback &&receive_callback,
+ PacketSentCallback &&packet_sent,
+ OnCloseCallback &&close_callback,
+ OnReconnectCallback &&on_reconnect,
+ asio::io_service &io_service,
+ std::string app_name = "Libtransport");
+
+ ~MemifConnector() override;
+
+ void send(Packet &packet) override;
+
+ void send(const uint8_t *packet, std::size_t len) override;
+
+ void close() override;
+
+ void connect(uint32_t memif_id, long memif_mode);
+
+ TRANSPORT_ALWAYS_INLINE uint32_t getMemifId() { return memif_id_; };
+
+ private:
+ void init();
+
+ int doSend();
+
+ int createMemif(uint32_t index, uint8_t mode, char *s);
+
+ uint32_t getMemifConfiguration();
+
+ int deleteMemif();
+
+ static int controlFdUpdate(int fd, uint8_t events, void *private_ctx);
+
+ static int onConnect(memif_conn_handle_t conn, void *private_ctx);
+
+ static int onDisconnect(memif_conn_handle_t conn, void *private_ctx);
+
+ static int onInterrupt(memif_conn_handle_t conn, void *private_ctx,
+ uint16_t qid);
+
+ void threadMain();
+
+ int txBurst(uint16_t qid);
+
+ int bufferAlloc(long n, uint16_t qid);
+
+ void sendCallback(const std::error_code &ec);
+
+ void processInputBuffer(std::uint16_t total_packets);
+
+ private:
+ static utils::EpollEventReactor main_event_reactor_;
+ static std::unique_ptr<std::thread> main_worker_;
+
+ int epfd;
+ std::unique_ptr<std::thread> memif_worker_;
+ utils::EpollEventReactor event_reactor_;
+ std::atomic_bool timer_set_;
+ std::unique_ptr<utils::FdDeadlineTimer> send_timer_;
+ std::unique_ptr<utils::FdDeadlineTimer> disconnect_timer_;
+ asio::io_service &io_service_;
+ std::unique_ptr<asio::io_service::work> work_;
+ std::unique_ptr<memif_connection_t> memif_connection_;
+ uint16_t tx_buf_counter_;
+
+ PacketRing input_buffer_;
+ bool is_reconnection_;
+ bool data_available_;
+ uint32_t memif_id_;
+ uint8_t memif_mode_;
+ std::string app_name_;
+ uint16_t transmission_index_;
+ utils::SpinLock write_msgs_lock_;
+ std::string socket_filename_;
+
+ static std::once_flag flag_;
+};
+
+} // end namespace core
+
+} // end namespace transport
diff --git a/libtransport/src/io_modules/memif/memif_vapi.c b/libtransport/src/io_modules/memif/memif_vapi.c
new file mode 100644
index 000000000..b3da2b012
--- /dev/null
+++ b/libtransport/src/io_modules/memif/memif_vapi.c
@@ -0,0 +1,127 @@
+/*
+ * 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 <fcntl.h>
+#include <hicn/transport/config.h>
+#include <inttypes.h>
+#include <io_modules/memif/memif_vapi.h>
+#include <semaphore.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <vapi/vapi_safe.h>
+#include <vppinfra/clib.h>
+
+DEFINE_VAPI_MSG_IDS_MEMIF_API_JSON
+
+static vapi_error_e memif_details_cb(vapi_ctx_t ctx, void *callback_ctx,
+ vapi_error_e rv, bool is_last,
+ vapi_payload_memif_details *reply) {
+ uint32_t *last_memif_id = (uint32_t *)callback_ctx;
+ uint32_t current_memif_id = 0;
+ if (reply != NULL) {
+ current_memif_id = reply->id;
+ } else {
+ return rv;
+ }
+
+ if (current_memif_id >= *last_memif_id) {
+ *last_memif_id = current_memif_id + 1;
+ }
+
+ return rv;
+}
+
+int memif_vapi_get_next_memif_id(vapi_ctx_t ctx, uint32_t *memif_id) {
+ vapi_lock();
+ vapi_msg_memif_dump *msg = vapi_alloc_memif_dump(ctx);
+ int ret = vapi_memif_dump(ctx, msg, memif_details_cb, memif_id);
+ vapi_unlock();
+ return ret;
+}
+
+static vapi_error_e memif_create_cb(vapi_ctx_t ctx, void *callback_ctx,
+ vapi_error_e rv, bool is_last,
+ vapi_payload_memif_create_reply *reply) {
+ memif_output_params_t *output_params = (memif_output_params_t *)callback_ctx;
+
+ if (reply == NULL) return rv;
+
+ output_params->sw_if_index = reply->sw_if_index;
+
+ return rv;
+}
+
+int memif_vapi_create_memif(vapi_ctx_t ctx, memif_create_params_t *input_params,
+ memif_output_params_t *output_params) {
+ vapi_lock();
+ vapi_msg_memif_create *msg = vapi_alloc_memif_create(ctx);
+
+ int ret = 0;
+ if (input_params->socket_id == ~0) {
+ // invalid socket-id
+ ret = -1;
+ goto END;
+ }
+
+ if (!is_pow2(input_params->ring_size)) {
+ // ring size must be power of 2
+ ret = -1;
+ goto END;
+ }
+
+ if (input_params->rx_queues > 255 || input_params->rx_queues < 1) {
+ // rx queue must be between 1 - 255
+ ret = -1;
+ goto END;
+ }
+
+ if (input_params->tx_queues > 255 || input_params->tx_queues < 1) {
+ // tx queue must be between 1 - 255
+ ret = -1;
+ goto END;
+ }
+
+ msg->payload.role = input_params->role;
+ msg->payload.mode = input_params->mode;
+ msg->payload.rx_queues = input_params->rx_queues;
+ msg->payload.tx_queues = input_params->tx_queues;
+ msg->payload.id = input_params->id;
+ msg->payload.socket_id = input_params->socket_id;
+ msg->payload.ring_size = input_params->ring_size;
+ msg->payload.buffer_size = input_params->buffer_size;
+
+ ret = vapi_memif_create(ctx, msg, memif_create_cb, output_params);
+END:
+ vapi_unlock();
+ return ret;
+}
+
+static vapi_error_e memif_delete_cb(vapi_ctx_t ctx, void *callback_ctx,
+ vapi_error_e rv, bool is_last,
+ vapi_payload_memif_delete_reply *reply) {
+ if (reply == NULL) return rv;
+
+ return reply->retval;
+}
+
+int memif_vapi_delete_memif(vapi_ctx_t ctx, uint32_t sw_if_index) {
+ vapi_lock();
+ vapi_msg_memif_delete *msg = vapi_alloc_memif_delete(ctx);
+
+ msg->payload.sw_if_index = sw_if_index;
+
+ int ret = vapi_memif_delete(ctx, msg, memif_delete_cb, NULL);
+ vapi_unlock();
+ return ret;
+}
diff --git a/libtransport/src/io_modules/memif/memif_vapi.h b/libtransport/src/io_modules/memif/memif_vapi.h
new file mode 100644
index 000000000..bcf06ed43
--- /dev/null
+++ b/libtransport/src/io_modules/memif/memif_vapi.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/config.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <vapi/memif.api.vapi.h>
+
+#include "stdint.h"
+
+typedef struct memif_create_params_s {
+ uint8_t role;
+ uint8_t mode;
+ uint8_t rx_queues;
+ uint8_t tx_queues;
+ uint32_t id;
+ uint32_t socket_id;
+ uint8_t secret[24];
+ uint32_t ring_size;
+ uint16_t buffer_size;
+ uint8_t hw_addr[6];
+} memif_create_params_t;
+
+typedef struct memif_output_params_s {
+ uint32_t sw_if_index;
+} memif_output_params_t;
+
+int memif_vapi_get_next_memif_id(vapi_ctx_t ctx, uint32_t *memif_id);
+
+int memif_vapi_create_memif(vapi_ctx_t ctx, memif_create_params_t *input_params,
+ memif_output_params_t *output_params);
+
+int memif_vapi_delete_memif(vapi_ctx_t ctx, uint32_t sw_if_index);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libtransport/src/io_modules/memif/vpp_forwarder_module.cc b/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
new file mode 100644
index 000000000..dcbcd7ed0
--- /dev/null
+++ b/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
@@ -0,0 +1,263 @@
+/*
+ * 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 <hicn/transport/config.h>
+#include <hicn/transport/errors/not_implemented_exception.h>
+#include <io_modules/memif/hicn_vapi.h>
+#include <io_modules/memif/memif_connector.h>
+#include <io_modules/memif/memif_vapi.h>
+#include <io_modules/memif/vpp_forwarder_module.h>
+
+extern "C" {
+#include <memif/libmemif.h>
+};
+
+typedef enum { MASTER = 0, SLAVE = 1 } memif_role_t;
+
+#define MEMIF_DEFAULT_RING_SIZE 2048
+#define MEMIF_DEFAULT_RX_QUEUES 1
+#define MEMIF_DEFAULT_TX_QUEUES 1
+#define MEMIF_DEFAULT_BUFFER_SIZE 2048
+
+namespace transport {
+
+namespace core {
+
+VPPForwarderModule::VPPForwarderModule()
+ : IoModule(),
+ connector_(nullptr),
+ sw_if_index_(~0),
+ face_id1_(~0),
+ face_id2_(~0),
+ is_consumer_(false) {}
+
+VPPForwarderModule::~VPPForwarderModule() { delete connector_; }
+
+void VPPForwarderModule::init(
+ Connector::PacketReceivedCallback &&receive_callback,
+ Connector::OnReconnectCallback &&reconnect_callback,
+ asio::io_service &io_service, const std::string &app_name) {
+ if (!connector_) {
+ connector_ =
+ new MemifConnector(std::move(receive_callback), 0, 0,
+ std::move(reconnect_callback), io_service, app_name);
+ }
+}
+
+void VPPForwarderModule::processControlMessageReply(
+ utils::MemBuf &packet_buffer) {
+ throw errors::NotImplementedException();
+}
+
+bool VPPForwarderModule::isControlMessage(const uint8_t *message) {
+ return false;
+}
+
+bool VPPForwarderModule::isConnected() { return connector_->isConnected(); };
+
+void VPPForwarderModule::send(Packet &packet) {
+ IoModule::send(packet);
+ connector_->send(packet);
+}
+
+void VPPForwarderModule::send(const uint8_t *packet, std::size_t len) {
+ counters_.tx_packets++;
+ counters_.tx_bytes += len;
+
+ // Perfect forwarding
+ connector_->send(packet, len);
+}
+
+std::uint32_t VPPForwarderModule::getMtu() { return interface_mtu; }
+
+/**
+ * @brief Create a memif interface in the local VPP forwarder.
+ */
+uint32_t VPPForwarderModule::getMemifConfiguration() {
+ memif_create_params_t input_params = {0};
+
+ int ret = memif_vapi_get_next_memif_id(VPPForwarderModule::sock_, &memif_id_);
+
+ if (ret < 0) {
+ throw errors::RuntimeException(
+ "Error getting next memif id. Could not create memif interface.");
+ }
+
+ input_params.id = memif_id_;
+ input_params.role = memif_role_t::MASTER;
+ input_params.mode = memif_interface_mode_t::MEMIF_INTERFACE_MODE_IP;
+ input_params.rx_queues = MEMIF_DEFAULT_RX_QUEUES;
+ input_params.tx_queues = MEMIF_DEFAULT_TX_QUEUES;
+ input_params.ring_size = MEMIF_DEFAULT_RING_SIZE;
+ input_params.buffer_size = MEMIF_DEFAULT_BUFFER_SIZE;
+
+ memif_output_params_t output_params = {0};
+
+ ret = memif_vapi_create_memif(VPPForwarderModule::sock_, &input_params,
+ &output_params);
+
+ if (ret < 0) {
+ throw errors::RuntimeException(
+ "Error creating memif interface in the local VPP forwarder.");
+ }
+
+ return output_params.sw_if_index;
+}
+
+void VPPForwarderModule::consumerConnection() {
+ hicn_consumer_input_params input = {0};
+ hicn_consumer_output_params output = {0};
+ ip_address_t ip4_address;
+ ip_address_t ip6_address;
+
+ output.src4 = &ip4_address;
+ output.src6 = &ip6_address;
+ input.swif = sw_if_index_;
+
+ int ret =
+ hicn_vapi_register_cons_app(VPPForwarderModule::sock_, &input, &output);
+
+ if (ret < 0) {
+ throw errors::RuntimeException(hicn_vapi_get_error_string(ret));
+ }
+
+ face_id1_ = output.face_id1;
+ face_id2_ = output.face_id2;
+
+ std::memcpy(inet_address_.v4.as_u8, output.src4->v4.as_u8, IPV4_ADDR_LEN);
+
+ std::memcpy(inet6_address_.v6.as_u8, output.src6->v6.as_u8, IPV6_ADDR_LEN);
+}
+
+void VPPForwarderModule::producerConnection() {
+ // Producer connection will be set when we set the first route.
+}
+
+void VPPForwarderModule::connect(bool is_consumer) {
+ int retry = 20;
+
+ TRANSPORT_LOGI("Connecting to VPP through vapi.");
+ vapi_error_e ret = vapi_connect_safe(&sock_, 0);
+
+ while (ret != VAPI_OK && retry > 0) {
+ TRANSPORT_LOGE("Error connecting to VPP through vapi. Retrying..");
+ --retry;
+ ret = vapi_connect_safe(&sock_, 0);
+ }
+
+ if (ret != VAPI_OK) {
+ throw std::runtime_error(
+ "Impossible to connect to forwarder. Is VPP running?");
+ }
+
+ TRANSPORT_LOGI("Connected to VPP through vapi.");
+
+ sw_if_index_ = getMemifConfiguration();
+
+ is_consumer_ = is_consumer;
+ if (is_consumer_) {
+ consumerConnection();
+ }
+
+ connector_->connect(memif_id_, 0);
+ connector_->setRole(is_consumer_ ? Connector::Role::CONSUMER
+ : Connector::Role::PRODUCER);
+}
+
+void VPPForwarderModule::registerRoute(const Prefix &prefix) {
+ const ip_prefix_t &addr = prefix.toIpPrefixStruct();
+
+ ip_prefix_t producer_prefix;
+ ip_address_t producer_locator;
+
+ if (face_id1_ == uint32_t(~0)) {
+ hicn_producer_input_params input;
+ std::memset(&input, 0, sizeof(input));
+
+ hicn_producer_output_params output;
+ std::memset(&output, 0, sizeof(output));
+
+ input.prefix = &producer_prefix;
+ output.prod_addr = &producer_locator;
+
+ // Here we have to ask to the actual connector what is the
+ // memif_id, since this function should be called after the
+ // memif creation.n
+ input.swif = sw_if_index_;
+ input.prefix->address = addr.address;
+ input.prefix->family = addr.family;
+ input.prefix->len = addr.len;
+ input.cs_reserved = content_store_reserved_;
+
+ int ret =
+ hicn_vapi_register_prod_app(VPPForwarderModule::sock_, &input, &output);
+
+ if (ret < 0) {
+ throw errors::RuntimeException(hicn_vapi_get_error_string(ret));
+ }
+
+ inet6_address_ = *output.prod_addr;
+
+ face_id1_ = output.face_id;
+ } else {
+ hicn_producer_set_route_params params;
+ params.prefix = &producer_prefix;
+ params.prefix->address = addr.address;
+ params.prefix->family = addr.family;
+ params.prefix->len = addr.len;
+ params.prod_addr = &producer_locator;
+
+ int ret = hicn_vapi_register_route(VPPForwarderModule::sock_, &params);
+
+ if (ret < 0) {
+ throw errors::RuntimeException(hicn_vapi_get_error_string(ret));
+ }
+ }
+}
+
+void VPPForwarderModule::closeConnection() {
+ if (VPPForwarderModule::sock_) {
+ connector_->close();
+
+ if (is_consumer_) {
+ hicn_del_face_app_input_params params;
+ params.face_id = face_id1_;
+ hicn_vapi_face_cons_del(VPPForwarderModule::sock_, &params);
+ params.face_id = face_id2_;
+ hicn_vapi_face_cons_del(VPPForwarderModule::sock_, &params);
+ } else {
+ hicn_del_face_app_input_params params;
+ params.face_id = face_id1_;
+ hicn_vapi_face_prod_del(VPPForwarderModule::sock_, &params);
+ }
+
+ if (sw_if_index_ != uint32_t(~0)) {
+ int ret =
+ memif_vapi_delete_memif(VPPForwarderModule::sock_, sw_if_index_);
+ if (ret < 0) {
+ TRANSPORT_LOGE("Error deleting memif with sw idx %u.", sw_if_index_);
+ }
+ }
+
+ vapi_disconnect_safe();
+ VPPForwarderModule::sock_ = nullptr;
+ }
+}
+
+extern "C" IoModule *create_module(void) { return new VPPForwarderModule(); }
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/memif/vpp_forwarder_module.h b/libtransport/src/io_modules/memif/vpp_forwarder_module.h
new file mode 100644
index 000000000..8c4114fed
--- /dev/null
+++ b/libtransport/src/io_modules/memif/vpp_forwarder_module.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/io_module.h>
+#include <hicn/transport/core/prefix.h>
+
+#ifdef always_inline
+#undef always_inline
+#endif
+extern "C" {
+#include <vapi/vapi_safe.h>
+};
+
+namespace transport {
+
+namespace core {
+
+class MemifConnector;
+
+class VPPForwarderModule : public IoModule {
+ static constexpr std::uint16_t interface_mtu = 1500;
+
+ public:
+ VPPForwarderModule();
+ ~VPPForwarderModule();
+
+ void connect(bool is_consumer) override;
+
+ void send(Packet &packet) override;
+ void send(const uint8_t *packet, std::size_t len) override;
+
+ bool isConnected() override;
+
+ void init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::OnReconnectCallback &&reconnect_callback,
+ asio::io_service &io_service,
+ const std::string &app_name = "Libtransport") override;
+
+ void registerRoute(const Prefix &prefix) override;
+
+ std::uint32_t getMtu() override;
+
+ bool isControlMessage(const uint8_t *message) override;
+
+ void processControlMessageReply(utils::MemBuf &packet_buffer) override;
+
+ void closeConnection() override;
+
+ private:
+ uint32_t getMemifConfiguration();
+ void consumerConnection();
+ void producerConnection();
+
+ private:
+ MemifConnector *connector_;
+ uint32_t memif_id_;
+ uint32_t sw_if_index_;
+ // A consumer socket in vpp has two faces (ipv4 and ipv6)
+ uint32_t face_id1_;
+ uint32_t face_id2_;
+ bool is_consumer_;
+ vapi_ctx_t sock_;
+};
+
+extern "C" IoModule *create_module(void);
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/raw_socket/raw_socket_connector.cc b/libtransport/src/io_modules/raw_socket/raw_socket_connector.cc
new file mode 100644
index 000000000..0bfcc2a58
--- /dev/null
+++ b/libtransport/src/io_modules/raw_socket/raw_socket_connector.cc
@@ -0,0 +1,201 @@
+/*
+ * 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 <core/raw_socket_connector.h>
+#include <hicn/transport/utils/conversions.h>
+#include <hicn/transport/utils/log.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#define MY_DEST_MAC0 0x0a
+#define MY_DEST_MAC1 0x7b
+#define MY_DEST_MAC2 0x7c
+#define MY_DEST_MAC3 0x1c
+#define MY_DEST_MAC4 0x4a
+#define MY_DEST_MAC5 0x14
+
+namespace transport {
+
+namespace core {
+
+RawSocketConnector::RawSocketConnector(
+ PacketReceivedCallback &&receive_callback,
+ OnReconnect &&on_reconnect_callback, asio::io_service &io_service,
+ std::string app_name)
+ : Connector(std::move(receive_callback), std::move(on_reconnect_callback)),
+ io_service_(io_service),
+ socket_(io_service_, raw_protocol(PF_PACKET, SOCK_RAW)),
+ // resolver_(io_service_),
+ timer_(io_service_),
+ read_msg_(packet_pool_.makePtr(nullptr)),
+ data_available_(false),
+ app_name_(app_name) {
+ memset(&link_layer_address_, 0, sizeof(link_layer_address_));
+}
+
+RawSocketConnector::~RawSocketConnector() {}
+
+void RawSocketConnector::connect(const std::string &interface_name,
+ const std::string &mac_address_str) {
+ state_ = ConnectorState::CONNECTING;
+ memset(&ethernet_header_, 0, sizeof(ethernet_header_));
+ struct ifreq ifr;
+ struct ifreq if_mac;
+ uint8_t mac_address[6];
+
+ utils::convertStringToMacAddress(mac_address_str, mac_address);
+
+ // Get interface mac address
+ int fd = static_cast<int>(socket_.native_handle());
+
+ /* Get the index of the interface to send on */
+ memset(&ifr, 0, sizeof(struct ifreq));
+ strncpy(ifr.ifr_name, interface_name.c_str(), interface_name.size());
+
+ // if (ioctl(fd, SIOCGIFINDEX, &if_idx) < 0) {
+ // perror("SIOCGIFINDEX");
+ // }
+
+ /* Get the MAC address of the interface to send on */
+ memset(&if_mac, 0, sizeof(struct ifreq));
+ strncpy(if_mac.ifr_name, interface_name.c_str(), interface_name.size());
+ if (ioctl(fd, SIOCGIFHWADDR, &if_mac) < 0) {
+ perror("SIOCGIFHWADDR");
+ throw errors::RuntimeException("Interface does not exist");
+ }
+
+ /* Ethernet header */
+ for (int i = 0; i < 6; i++) {
+ ethernet_header_.ether_shost[i] =
+ ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[i];
+ ethernet_header_.ether_dhost[i] = mac_address[i];
+ }
+
+ /* Ethertype field */
+ ethernet_header_.ether_type = htons(ETH_P_IPV6);
+
+ strcpy(ifr.ifr_name, interface_name.c_str());
+
+ if (0 == ioctl(fd, SIOCGIFHWADDR, &ifr)) {
+ memcpy(link_layer_address_.sll_addr, ifr.ifr_hwaddr.sa_data, 6);
+ }
+
+ // memset(&ifr, 0, sizeof(ifr));
+ // ioctl(fd, SIOCGIFFLAGS, &ifr);
+ // ifr.ifr_flags |= IFF_PROMISC;
+ // ioctl(fd, SIOCSIFFLAGS, &ifr);
+
+ link_layer_address_.sll_family = AF_PACKET;
+ link_layer_address_.sll_protocol = htons(ETH_P_ALL);
+ link_layer_address_.sll_ifindex = if_nametoindex(interface_name.c_str());
+ link_layer_address_.sll_hatype = 1;
+ link_layer_address_.sll_halen = 6;
+
+ // startConnectionTimer();
+ doConnect();
+ doRecvPacket();
+}
+
+void RawSocketConnector::send(const uint8_t *packet, std::size_t len,
+ const PacketSentCallback &packet_sent) {
+ if (packet_sent != 0) {
+ socket_.async_send(
+ asio::buffer(packet, len),
+ [packet_sent](std::error_code ec, std::size_t /*length*/) {
+ packet_sent();
+ });
+ } else {
+ if (state_ == ConnectorState::CONNECTED) {
+ socket_.send(asio::buffer(packet, len));
+ }
+ }
+}
+
+void RawSocketConnector::send(const Packet::MemBufPtr &packet) {
+ io_service_.post([this, packet]() {
+ bool write_in_progress = !output_buffer_.empty();
+ output_buffer_.push_back(std::move(packet));
+ if (TRANSPORT_EXPECT_TRUE(state_ == ConnectorState::CONNECTED)) {
+ if (!write_in_progress) {
+ doSendPacket();
+ } else {
+ // Tell the handle connect it has data to write
+ data_available_ = true;
+ }
+ }
+ });
+}
+
+void RawSocketConnector::close() {
+ io_service_.post([this]() { socket_.close(); });
+}
+
+void RawSocketConnector::doSendPacket() {
+ auto packet = output_buffer_.front().get();
+ auto array = std::vector<asio::const_buffer>();
+
+ const utils::MemBuf *current = packet;
+ do {
+ array.push_back(asio::const_buffer(current->data(), current->length()));
+ current = current->next();
+ } while (current != packet);
+
+ socket_.async_send(
+ std::move(array),
+ [this /*, packet*/](std::error_code ec, std::size_t bytes_transferred) {
+ if (TRANSPORT_EXPECT_TRUE(!ec)) {
+ output_buffer_.pop_front();
+ if (!output_buffer_.empty()) {
+ doSendPacket();
+ }
+ } else {
+ TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ }
+ });
+}
+
+void RawSocketConnector::doRecvPacket() {
+ read_msg_ = getPacket();
+ socket_.async_receive(
+ asio::buffer(read_msg_->writableData(), packet_size),
+ [this](std::error_code ec, std::size_t bytes_transferred) mutable {
+ if (!ec) {
+ // Ignore packets that are not for us
+ uint8_t *dst_mac_address = const_cast<uint8_t *>(read_msg_->data());
+ if (!std::memcmp(dst_mac_address, ethernet_header_.ether_shost,
+ ETHER_ADDR_LEN)) {
+ read_msg_->append(bytes_transferred);
+ read_msg_->trimStart(sizeof(struct ether_header));
+ receive_callback_(std::move(read_msg_));
+ }
+ } else {
+ TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ }
+ doRecvPacket();
+ });
+}
+
+void RawSocketConnector::doConnect() {
+ state_ = ConnectorState::CONNECTED;
+ socket_.bind(raw_endpoint(&link_layer_address_, sizeof(link_layer_address_)));
+}
+
+} // end namespace core
+
+} // end namespace transport
diff --git a/libtransport/src/io_modules/raw_socket/raw_socket_connector.h b/libtransport/src/io_modules/raw_socket/raw_socket_connector.h
new file mode 100644
index 000000000..aba4b1105
--- /dev/null
+++ b/libtransport/src/io_modules/raw_socket/raw_socket_connector.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <core/connector.h>
+#include <hicn/transport/config.h>
+#include <hicn/transport/core/name.h>
+#include <linux/if_packet.h>
+#include <net/ethernet.h>
+#include <sys/socket.h>
+
+#include <asio.hpp>
+#include <asio/steady_timer.hpp>
+#include <deque>
+
+namespace transport {
+
+namespace core {
+
+using asio::generic::raw_protocol;
+using raw_endpoint = asio::generic::basic_endpoint<raw_protocol>;
+
+class RawSocketConnector : public Connector {
+ public:
+ RawSocketConnector(PacketReceivedCallback &&receive_callback,
+ OnReconnect &&reconnect_callback,
+ asio::io_service &io_service,
+ std::string app_name = "Libtransport");
+
+ ~RawSocketConnector() override;
+
+ void send(const Packet::MemBufPtr &packet) override;
+
+ void send(const uint8_t *packet, std::size_t len,
+ const PacketSentCallback &packet_sent = 0) override;
+
+ void close() override;
+
+ void connect(const std::string &interface_name,
+ const std::string &mac_address_str);
+
+ private:
+ void doConnect();
+
+ void doRecvPacket();
+
+ void doSendPacket();
+
+ private:
+ asio::io_service &io_service_;
+ raw_protocol::socket socket_;
+
+ struct ether_header ethernet_header_;
+
+ struct sockaddr_ll link_layer_address_;
+
+ asio::steady_timer timer_;
+
+ utils::ObjectPool<utils::MemBuf>::Ptr read_msg_;
+
+ bool data_available_;
+ std::string app_name_;
+};
+
+} // end namespace core
+
+} // end namespace transport
diff --git a/libtransport/src/io_modules/raw_socket/raw_socket_interface.cc b/libtransport/src/io_modules/raw_socket/raw_socket_interface.cc
new file mode 100644
index 000000000..dcf489f59
--- /dev/null
+++ b/libtransport/src/io_modules/raw_socket/raw_socket_interface.cc
@@ -0,0 +1,56 @@
+/*
+ * 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 <core/raw_socket_interface.h>
+#include <hicn/transport/utils/linux.h>
+
+#include <fstream>
+
+namespace transport {
+
+namespace core {
+
+static std::string config_folder_path = "/etc/transport/interface.conf.d";
+
+RawSocketInterface::RawSocketInterface(RawSocketConnector &connector)
+ : ForwarderInterface<RawSocketInterface, RawSocketConnector>(connector) {}
+
+RawSocketInterface::~RawSocketInterface() {}
+
+void RawSocketInterface::connect(bool is_consumer) {
+ std::string complete_filename =
+ config_folder_path + std::string("/") + output_interface_;
+
+ std::ifstream is(complete_filename);
+ std::string interface;
+
+ if (is) {
+ is >> remote_mac_address_;
+ }
+
+ // Get interface ip address
+ struct sockaddr_in6 address = {0};
+ utils::retrieveInterfaceAddress(output_interface_, &address);
+
+ std::memcpy(&inet6_address_.v6.as_u8, &address.sin6_addr,
+ sizeof(address.sin6_addr));
+ connector_.connect(output_interface_, remote_mac_address_);
+}
+
+void RawSocketInterface::registerRoute(Prefix &prefix) { return; }
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/raw_socket/raw_socket_interface.h b/libtransport/src/io_modules/raw_socket/raw_socket_interface.h
new file mode 100644
index 000000000..7036cac7e
--- /dev/null
+++ b/libtransport/src/io_modules/raw_socket/raw_socket_interface.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.
+ */
+
+#pragma once
+
+#include <core/forwarder_interface.h>
+#include <core/raw_socket_connector.h>
+#include <hicn/transport/core/prefix.h>
+
+#include <atomic>
+#include <deque>
+
+namespace transport {
+
+namespace core {
+
+class RawSocketInterface
+ : public ForwarderInterface<RawSocketInterface, RawSocketConnector> {
+ public:
+ typedef RawSocketConnector ConnectorType;
+
+ RawSocketInterface(RawSocketConnector &connector);
+
+ ~RawSocketInterface();
+
+ void connect(bool is_consumer);
+
+ void registerRoute(Prefix &prefix);
+
+ std::uint16_t getMtu() { return interface_mtu; }
+
+ TRANSPORT_ALWAYS_INLINE static bool isControlMessageImpl(
+ const uint8_t *message) {
+ return false;
+ }
+
+ TRANSPORT_ALWAYS_INLINE void processControlMessageReplyImpl(
+ Packet::MemBufPtr &&packet_buffer) {}
+
+ TRANSPORT_ALWAYS_INLINE void closeConnection(){};
+
+ private:
+ static constexpr std::uint16_t interface_mtu = 1500;
+ std::string remote_mac_address_;
+};
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/udp/CMakeLists.txt b/libtransport/src/io_modules/udp/CMakeLists.txt
new file mode 100644
index 000000000..93518d0a2
--- /dev/null
+++ b/libtransport/src/io_modules/udp/CMakeLists.txt
@@ -0,0 +1,46 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+
+list(APPEND MODULE_HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_forwarder_module.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_socket_connector.h
+)
+
+list(APPEND MODULE_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_forwarder_module.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_socket_connector.cc
+)
+
+# add_executable(hicnlight_module MACOSX_BUNDLE ${MODULE_SOURCE_FILES})
+# target_include_directories(hicnlight_module PRIVATE ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS})
+# set_target_properties(hicnlight_module PROPERTIES
+# BUNDLE True
+# MACOSX_BUNDLE_GUI_IDENTIFIER my.domain.style.identifier.hicnlight_module
+# MACOSX_BUNDLE_BUNDLE_NAME hicnlight_module
+# MACOSX_BUNDLE_BUNDLE_VERSION "0.1"
+# MACOSX_BUNDLE_SHORT_VERSION_STRING "0.1"
+# # MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/customtemplate.plist.in
+# )
+build_module(hicnlight_module
+ SHARED
+ SOURCES ${MODULE_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT lib${LIBTRANSPORT}
+ INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ # LIBRARY_ROOT_DIR "vpp_plugins"
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILE_FLAGS}
+)
diff --git a/libtransport/src/io_modules/udp/hicn_forwarder_module.cc b/libtransport/src/io_modules/udp/hicn_forwarder_module.cc
new file mode 100644
index 000000000..ba08dd8c0
--- /dev/null
+++ b/libtransport/src/io_modules/udp/hicn_forwarder_module.cc
@@ -0,0 +1,181 @@
+/*
+ * 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 <io_modules/udp/hicn_forwarder_module.h>
+#include <io_modules/udp/udp_socket_connector.h>
+
+union AddressLight {
+ uint32_t ipv4;
+ struct in6_addr ipv6;
+};
+
+typedef struct {
+ uint8_t message_type;
+ uint8_t command_id;
+ uint16_t length;
+ uint32_t seq_num;
+} CommandHeader;
+
+typedef struct {
+ uint8_t message_type;
+ uint8_t command_id;
+ uint16_t length;
+ uint32_t seq_num;
+ char symbolic_or_connid[16];
+ union AddressLight address;
+ uint16_t cost;
+ uint8_t address_type;
+ uint8_t len;
+} RouteToSelfCommand;
+
+typedef struct {
+ uint8_t message_type;
+ uint8_t command_id;
+ uint16_t length;
+ uint32_t seq_num;
+ char symbolic_or_connid[16];
+} DeleteSelfConnectionCommand;
+
+namespace {
+static constexpr uint8_t addr_inet = 1;
+static constexpr uint8_t addr_inet6 = 2;
+static constexpr uint8_t add_route_command = 3;
+static constexpr uint8_t delete_connection_command = 5;
+static constexpr uint8_t request_light = 0xc0;
+static constexpr char identifier[] = "SELF";
+
+void fillCommandHeader(CommandHeader *header) {
+ // Allocate and fill the header
+ header->message_type = request_light;
+ header->length = 1;
+}
+
+RouteToSelfCommand createCommandRoute(std::unique_ptr<sockaddr> &&addr,
+ uint8_t prefix_length) {
+ RouteToSelfCommand command = {0};
+
+ // check and set IP address
+ if (addr->sa_family == AF_INET) {
+ command.address_type = addr_inet;
+ command.address.ipv4 = ((sockaddr_in *)addr.get())->sin_addr.s_addr;
+ } else if (addr->sa_family == AF_INET6) {
+ command.address_type = addr_inet6;
+ command.address.ipv6 = ((sockaddr_in6 *)addr.get())->sin6_addr;
+ }
+
+ // Fill remaining payload fields
+#ifndef _WIN32
+ strcpy(command.symbolic_or_connid, identifier);
+#else
+ strcpy_s(command.symbolic_or_connid, 16, identifier);
+#endif
+ command.cost = 1;
+ command.len = (uint8_t)prefix_length;
+
+ // Allocate and fill the header
+ command.command_id = add_route_command;
+ fillCommandHeader((CommandHeader *)&command);
+
+ return command;
+}
+
+DeleteSelfConnectionCommand createCommandDeleteConnection() {
+ DeleteSelfConnectionCommand command = {0};
+ fillCommandHeader((CommandHeader *)&command);
+ command.command_id = delete_connection_command;
+
+#ifndef _WIN32
+ strcpy(command.symbolic_or_connid, identifier);
+#else
+ strcpy_s(command.symbolic_or_connid, 16, identifier);
+#endif
+
+ return command;
+}
+
+} // namespace
+
+namespace transport {
+
+namespace core {
+
+HicnForwarderModule::HicnForwarderModule() : IoModule(), connector_(nullptr) {}
+
+HicnForwarderModule::~HicnForwarderModule() {}
+
+void HicnForwarderModule::connect(bool is_consumer) {
+ connector_->connect();
+ connector_->setRole(is_consumer ? Connector::Role::CONSUMER
+ : Connector::Role::PRODUCER);
+}
+
+bool HicnForwarderModule::isConnected() { return connector_->isConnected(); }
+
+void HicnForwarderModule::send(Packet &packet) {
+ IoModule::send(packet);
+ packet.setChecksum();
+ connector_->send(packet);
+}
+
+void HicnForwarderModule::send(const uint8_t *packet, std::size_t len) {
+ counters_.tx_packets++;
+ counters_.tx_bytes += len;
+
+ // Perfect forwarding
+ connector_->send(packet, len);
+}
+
+void HicnForwarderModule::registerRoute(const Prefix &prefix) {
+ auto command = createCommandRoute(prefix.toSockaddr(),
+ (uint8_t)prefix.getPrefixLength());
+ send((uint8_t *)&command, sizeof(RouteToSelfCommand));
+}
+
+void HicnForwarderModule::closeConnection() {
+ auto command = createCommandDeleteConnection();
+ send((uint8_t *)&command, sizeof(DeleteSelfConnectionCommand));
+ connector_->close();
+}
+
+void HicnForwarderModule::init(
+ Connector::PacketReceivedCallback &&receive_callback,
+ Connector::OnReconnectCallback &&reconnect_callback,
+ asio::io_service &io_service, const std::string &app_name) {
+ if (!connector_) {
+ connector_ = new UdpSocketConnector(std::move(receive_callback), nullptr,
+ nullptr, std::move(reconnect_callback),
+ io_service, app_name);
+ }
+}
+
+void HicnForwarderModule::processControlMessageReply(
+ utils::MemBuf &packet_buffer) {
+ if (packet_buffer.data()[0] == nack_code) {
+ throw errors::RuntimeException(
+ "Received Nack message from hicn light forwarder.");
+ }
+}
+
+std::uint32_t HicnForwarderModule::getMtu() { return interface_mtu; }
+
+bool HicnForwarderModule::isControlMessage(const uint8_t *message) {
+ return message[0] == ack_code || message[0] == nack_code;
+}
+
+extern "C" IoModule *create_module(void) { return new HicnForwarderModule(); }
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/udp/hicn_forwarder_module.h b/libtransport/src/io_modules/udp/hicn_forwarder_module.h
new file mode 100644
index 000000000..845db73bf
--- /dev/null
+++ b/libtransport/src/io_modules/udp/hicn_forwarder_module.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/io_module.h>
+#include <hicn/transport/core/prefix.h>
+
+namespace transport {
+
+namespace core {
+
+class UdpSocketConnector;
+
+class HicnForwarderModule : public IoModule {
+ static constexpr uint8_t ack_code = 0xc2;
+ static constexpr uint8_t nack_code = 0xc3;
+ static constexpr std::uint16_t interface_mtu = 1500;
+
+ public:
+ union addressLight {
+ uint32_t ipv4;
+ struct in6_addr ipv6;
+ };
+
+ struct route_to_self_command {
+ uint8_t messageType;
+ uint8_t commandID;
+ uint16_t length;
+ uint32_t seqNum;
+ char symbolicOrConnid[16];
+ union addressLight address;
+ uint16_t cost;
+ uint8_t addressType;
+ uint8_t len;
+ };
+
+ using route_to_self_command = struct route_to_self_command;
+
+ HicnForwarderModule();
+
+ ~HicnForwarderModule();
+
+ void connect(bool is_consumer) override;
+
+ void send(Packet &packet) override;
+ void send(const uint8_t *packet, std::size_t len) override;
+
+ bool isConnected() override;
+
+ void init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::OnReconnectCallback &&reconnect_callback,
+ asio::io_service &io_service,
+ const std::string &app_name = "Libtransport") override;
+
+ void registerRoute(const Prefix &prefix) override;
+
+ std::uint32_t getMtu() override;
+
+ bool isControlMessage(const uint8_t *message) override;
+
+ void processControlMessageReply(utils::MemBuf &packet_buffer) override;
+
+ void closeConnection() override;
+
+ private:
+ UdpSocketConnector *connector_;
+};
+
+extern "C" IoModule *create_module(void);
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/udp/udp_socket_connector.cc b/libtransport/src/io_modules/udp/udp_socket_connector.cc
new file mode 100644
index 000000000..456886a54
--- /dev/null
+++ b/libtransport/src/io_modules/udp/udp_socket_connector.cc
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+
+#ifdef _WIN32
+#include <hicn/transport/portability/win_portability.h>
+#endif
+
+#include <hicn/transport/errors/errors.h>
+#include <hicn/transport/utils/log.h>
+#include <hicn/transport/utils/object_pool.h>
+#include <io_modules/udp/udp_socket_connector.h>
+
+#include <thread>
+#include <vector>
+
+namespace transport {
+
+namespace core {
+
+UdpSocketConnector::UdpSocketConnector(
+ PacketReceivedCallback &&receive_callback, PacketSentCallback &&packet_sent,
+ OnCloseCallback &&close_callback, OnReconnectCallback &&on_reconnect,
+ asio::io_service &io_service, std::string app_name)
+ : Connector(std::move(receive_callback), std::move(packet_sent),
+ std::move(close_callback), std::move(on_reconnect)),
+ io_service_(io_service),
+ socket_(io_service_),
+ resolver_(io_service_),
+ connection_timer_(io_service_),
+ read_msg_(std::make_pair(nullptr, 0)),
+ is_reconnection_(false),
+ data_available_(false),
+ app_name_(app_name) {}
+
+UdpSocketConnector::~UdpSocketConnector() {}
+
+void UdpSocketConnector::connect(std::string ip_address, std::string port) {
+ endpoint_iterator_ = resolver_.resolve(
+ {ip_address, port, asio::ip::resolver_query_base::numeric_service});
+
+ state_ = Connector::State::CONNECTING;
+ doConnect();
+}
+
+void UdpSocketConnector::send(const uint8_t *packet, std::size_t len) {
+ socket_.async_send(asio::buffer(packet, len),
+ [this](std::error_code ec, std::size_t /*length*/) {
+ if (sent_callback_) {
+ sent_callback_(this, ec);
+ }
+ });
+}
+
+void UdpSocketConnector::send(Packet &packet) {
+ io_service_.post([this, _packet{packet.shared_from_this()}]() {
+ bool write_in_progress = !output_buffer_.empty();
+ output_buffer_.push_back(std::move(_packet));
+ if (TRANSPORT_EXPECT_TRUE(state_ == Connector::State::CONNECTED)) {
+ if (!write_in_progress) {
+ doWrite();
+ }
+ } else {
+ // Tell the handle connect it has data to write
+ data_available_ = true;
+ }
+ });
+}
+
+void UdpSocketConnector::close() {
+ if (io_service_.stopped()) {
+ doClose();
+ } else {
+ io_service_.dispatch(std::bind(&UdpSocketConnector::doClose, this));
+ }
+}
+
+void UdpSocketConnector::doClose() {
+ if (state_ != Connector::State::CLOSED) {
+ state_ = Connector::State::CLOSED;
+ if (socket_.is_open()) {
+ socket_.shutdown(asio::ip::tcp::socket::shutdown_type::shutdown_both);
+ socket_.close();
+ }
+ }
+}
+
+void UdpSocketConnector::doWrite() {
+ auto packet = output_buffer_.front().get();
+ auto array = std::vector<asio::const_buffer>();
+
+ const utils::MemBuf *current = packet;
+ do {
+ array.push_back(asio::const_buffer(current->data(), current->length()));
+ current = current->next();
+ } while (current != packet);
+
+ socket_.async_send(std::move(array), [this](std::error_code ec,
+ std::size_t length) {
+ if (TRANSPORT_EXPECT_TRUE(!ec)) {
+ output_buffer_.pop_front();
+ if (!output_buffer_.empty()) {
+ doWrite();
+ }
+ } else if (ec.value() == static_cast<int>(std::errc::operation_canceled)) {
+ // The connection has been closed by the application.
+ return;
+ } else {
+ TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ tryReconnect();
+ }
+ });
+}
+
+void UdpSocketConnector::doRead() {
+ read_msg_ = getRawBuffer();
+ socket_.async_receive(
+ asio::buffer(read_msg_.first, read_msg_.second),
+ [this](std::error_code ec, std::size_t length) {
+ if (TRANSPORT_EXPECT_TRUE(!ec)) {
+ auto packet = getPacketFromBuffer(read_msg_.first, length);
+ receive_callback_(this, *packet, std::make_error_code(std::errc(0)));
+ doRead();
+ } else if (ec.value() ==
+ static_cast<int>(std::errc::operation_canceled)) {
+ // The connection has been closed by the application.
+ return;
+ } else {
+ TRANSPORT_LOGE("%d %s", ec.value(), ec.message().c_str());
+ tryReconnect();
+ }
+ });
+}
+
+void UdpSocketConnector::tryReconnect() {
+ if (state_ == Connector::State::CONNECTED) {
+ TRANSPORT_LOGE("Connection lost. Trying to reconnect...\n");
+ state_ = Connector::State::CONNECTING;
+ is_reconnection_ = true;
+ io_service_.post([this]() {
+ if (socket_.is_open()) {
+ socket_.shutdown(asio::ip::tcp::socket::shutdown_type::shutdown_both);
+ socket_.close();
+ }
+
+ doConnect();
+ startConnectionTimer();
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+ });
+ }
+}
+
+void UdpSocketConnector::doConnect() {
+ asio::async_connect(
+ socket_, endpoint_iterator_,
+ [this](std::error_code ec, udp::resolver::iterator) {
+ if (!ec) {
+ connection_timer_.cancel();
+ state_ = Connector::State::CONNECTED;
+ doRead();
+
+ if (data_available_) {
+ data_available_ = false;
+ doWrite();
+ }
+
+ if (is_reconnection_) {
+ is_reconnection_ = false;
+ }
+
+ on_reconnect_callback_(this);
+ } else {
+ doConnect();
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+ }
+ });
+}
+
+bool UdpSocketConnector::checkConnected() {
+ return state_ == Connector::State::CONNECTED;
+}
+
+void UdpSocketConnector::startConnectionTimer() {
+ connection_timer_.expires_from_now(std::chrono::seconds(60));
+ connection_timer_.async_wait(std::bind(&UdpSocketConnector::handleDeadline,
+ this, std::placeholders::_1));
+}
+
+void UdpSocketConnector::handleDeadline(const std::error_code &ec) {
+ if (!ec) {
+ io_service_.post([this]() {
+ socket_.close();
+ TRANSPORT_LOGE("Error connecting. Is the forwarder running?\n");
+ });
+ }
+}
+
+} // end namespace core
+
+} // end namespace transport
diff --git a/libtransport/src/io_modules/udp/udp_socket_connector.h b/libtransport/src/io_modules/udp/udp_socket_connector.h
new file mode 100644
index 000000000..8ab08e17a
--- /dev/null
+++ b/libtransport/src/io_modules/udp/udp_socket_connector.h
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/config.h>
+#include <hicn/transport/core/connector.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/core/interest.h>
+#include <hicn/transport/core/name.h>
+#include <hicn/transport/core/packet.h>
+#include <hicn/transport/utils/branch_prediction.h>
+
+#include <asio.hpp>
+#include <asio/steady_timer.hpp>
+#include <deque>
+
+namespace transport {
+namespace core {
+
+using asio::ip::udp;
+
+class UdpSocketConnector : public Connector {
+ public:
+ UdpSocketConnector(PacketReceivedCallback &&receive_callback,
+ PacketSentCallback &&packet_sent,
+ OnCloseCallback &&close_callback,
+ OnReconnectCallback &&on_reconnect,
+ asio::io_service &io_service,
+ std::string app_name = "Libtransport");
+
+ ~UdpSocketConnector() override;
+
+ void send(Packet &packet) override;
+
+ void send(const uint8_t *packet, std::size_t len) override;
+
+ void close() override;
+
+ void connect(std::string ip_address = "127.0.0.1", std::string port = "9695");
+
+ private:
+ void doConnect();
+
+ void doRead();
+
+ void doWrite();
+
+ void doClose();
+
+ bool checkConnected();
+
+ private:
+ void handleDeadline(const std::error_code &ec);
+
+ void startConnectionTimer();
+
+ void tryReconnect();
+
+ asio::io_service &io_service_;
+ asio::ip::udp::socket socket_;
+ asio::ip::udp::resolver resolver_;
+ asio::ip::udp::resolver::iterator endpoint_iterator_;
+ asio::steady_timer connection_timer_;
+
+ std::pair<uint8_t *, std::size_t> read_msg_;
+
+ bool is_reconnection_;
+ bool data_available_;
+
+ std::string app_name_;
+};
+
+} // end namespace core
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/CMakeLists.txt b/libtransport/src/protocols/CMakeLists.txt
index 8bfbdd6ad..eba8d1aab 100644
--- a/libtransport/src/protocols/CMakeLists.txt
+++ b/libtransport/src/protocols/CMakeLists.txt
@@ -21,16 +21,15 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/datagram_reassembly.h
${CMAKE_CURRENT_SOURCE_DIR}/byte_stream_reassembly.h
${CMAKE_CURRENT_SOURCE_DIR}/congestion_window_protocol.h
- ${CMAKE_CURRENT_SOURCE_DIR}/packet_manager.h
${CMAKE_CURRENT_SOURCE_DIR}/rate_estimation.h
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/transport_protocol.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/production_protocol.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/prod_protocol_bytestream.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/prod_protocol_rtc.h
${CMAKE_CURRENT_SOURCE_DIR}/raaqm.h
${CMAKE_CURRENT_SOURCE_DIR}/raaqm_data_path.h
${CMAKE_CURRENT_SOURCE_DIR}/cbr.h
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc.h
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc_data_path.h
${CMAKE_CURRENT_SOURCE_DIR}/errors.h
- ${CMAKE_CURRENT_SOURCE_DIR}/verification_manager.h
${CMAKE_CURRENT_SOURCE_DIR}/data_processing_events.h
)
@@ -41,15 +40,15 @@ list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/reassembly.cc
${CMAKE_CURRENT_SOURCE_DIR}/datagram_reassembly.cc
${CMAKE_CURRENT_SOURCE_DIR}/byte_stream_reassembly.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/transport_protocol.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/production_protocol.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/prod_protocol_bytestream.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/prod_protocol_rtc.cc
${CMAKE_CURRENT_SOURCE_DIR}/raaqm.cc
${CMAKE_CURRENT_SOURCE_DIR}/rate_estimation.cc
${CMAKE_CURRENT_SOURCE_DIR}/raaqm_data_path.cc
${CMAKE_CURRENT_SOURCE_DIR}/cbr.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/rtc_data_path.cc
${CMAKE_CURRENT_SOURCE_DIR}/errors.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/verification_manager.cc
)
set(RAAQM_CONFIG_INSTALL_PREFIX
@@ -71,5 +70,7 @@ install(
COMPONENT lib${LIBTRANSPORT}
)
+add_subdirectory(rtc)
+
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
-set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/protocols/byte_stream_reassembly.cc b/libtransport/src/protocols/byte_stream_reassembly.cc
index 12631637e..d2bc961c4 100644
--- a/libtransport/src/protocols/byte_stream_reassembly.cc
+++ b/libtransport/src/protocols/byte_stream_reassembly.cc
@@ -16,12 +16,11 @@
#include <hicn/transport/interfaces/socket_consumer.h>
#include <hicn/transport/utils/array.h>
#include <hicn/transport/utils/membuf.h>
-
#include <implementation/socket_consumer.h>
#include <protocols/byte_stream_reassembly.h>
#include <protocols/errors.h>
#include <protocols/indexer.h>
-#include <protocols/protocol.h>
+#include <protocols/transport_protocol.h>
namespace transport {
@@ -46,11 +45,11 @@ void ByteStreamReassembly::reassemble(
}
}
-void ByteStreamReassembly::reassemble(ContentObject::Ptr &&content_object) {
- if (TRANSPORT_EXPECT_TRUE(content_object != nullptr) &&
- read_buffer_->capacity()) {
- received_packets_.emplace(std::make_pair(
- content_object->getName().getSuffix(), std::move(content_object)));
+void ByteStreamReassembly::reassemble(ContentObject &content_object) {
+ if (TRANSPORT_EXPECT_TRUE(read_buffer_->capacity())) {
+ received_packets_.emplace(
+ std::make_pair(content_object.getName().getSuffix(),
+ content_object.shared_from_this()));
assembleContent();
}
}
@@ -67,7 +66,9 @@ void ByteStreamReassembly::assembleContent() {
while (it != received_packets_.end()) {
// Check if valid packet
if (it->second) {
- copyContent(*it->second);
+ if (TRANSPORT_EXPECT_FALSE(copyContent(*it->second))) {
+ return;
+ }
}
received_packets_.erase(it);
@@ -80,32 +81,44 @@ void ByteStreamReassembly::assembleContent() {
}
}
-void ByteStreamReassembly::copyContent(const ContentObject &content_object) {
- auto payload = content_object.getPayloadReference();
- auto payload_length = payload.second;
- auto write_size = std::min(payload_length, read_buffer_->tailroom());
- auto additional_bytes = payload_length > read_buffer_->tailroom()
- ? payload_length - read_buffer_->tailroom()
- : 0;
+bool ByteStreamReassembly::copyContent(ContentObject &content_object) {
+ bool ret = false;
- std::memcpy(read_buffer_->writableTail(), payload.first, write_size);
- read_buffer_->append(write_size);
+ content_object.trimStart(content_object.headerSize());
- if (!read_buffer_->tailroom()) {
- notifyApplication();
- std::memcpy(read_buffer_->writableTail(), payload.first + write_size,
- additional_bytes);
- read_buffer_->append(additional_bytes);
- }
+ utils::MemBuf *current = &content_object;
+
+ do {
+ auto payload_length = current->length();
+ auto write_size = std::min(payload_length, read_buffer_->tailroom());
+ auto additional_bytes = payload_length > read_buffer_->tailroom()
+ ? payload_length - read_buffer_->tailroom()
+ : 0;
+
+ std::memcpy(read_buffer_->writableTail(), current->data(), write_size);
+ read_buffer_->append(write_size);
+
+ if (!read_buffer_->tailroom()) {
+ notifyApplication();
+ std::memcpy(read_buffer_->writableTail(), current->data() + write_size,
+ additional_bytes);
+ read_buffer_->append(additional_bytes);
+ }
+
+ current = current->next();
+ } while (current != &content_object);
download_complete_ =
index_manager_->getFinalSuffix() == content_object.getName().getSuffix();
if (TRANSPORT_EXPECT_FALSE(download_complete_)) {
+ ret = download_complete_;
notifyApplication();
transport_protocol_->onContentReassembled(
make_error_code(protocol_error::success));
}
+
+ return ret;
}
void ByteStreamReassembly::reInitialize() {
diff --git a/libtransport/src/protocols/byte_stream_reassembly.h b/libtransport/src/protocols/byte_stream_reassembly.h
index 5e5c9ec6b..c682d58cb 100644
--- a/libtransport/src/protocols/byte_stream_reassembly.h
+++ b/libtransport/src/protocols/byte_stream_reassembly.h
@@ -27,12 +27,12 @@ class ByteStreamReassembly : public Reassembly {
TransportProtocol *transport_protocol);
protected:
- virtual void reassemble(core::ContentObject::Ptr &&content_object) override;
+ virtual void reassemble(core::ContentObject &content_object) override;
virtual void reassemble(
std::unique_ptr<core::ContentObjectManifest> &&manifest) override;
- virtual void copyContent(const core::ContentObject &content_object);
+ bool copyContent(core::ContentObject &content_object);
virtual void reInitialize() override;
diff --git a/libtransport/src/protocols/cbr.cc b/libtransport/src/protocols/cbr.cc
index 5df55bd5c..0bffd7d18 100644
--- a/libtransport/src/protocols/cbr.cc
+++ b/libtransport/src/protocols/cbr.cc
@@ -14,7 +14,6 @@
*/
#include <implementation/socket_consumer.h>
-
#include <protocols/cbr.h>
namespace transport {
diff --git a/libtransport/src/protocols/consumer.conf b/libtransport/src/protocols/consumer.conf
index 1a366f32f..d0eab75ac 100644
--- a/libtransport/src/protocols/consumer.conf
+++ b/libtransport/src/protocols/consumer.conf
@@ -1,4 +1,4 @@
-; this file contais the parameters for RAAQM
+; This file contains the parameters for RAAQM
autotune = no
lifetime = 500
retransmissions = 128
diff --git a/libtransport/src/protocols/data_processing_events.h b/libtransport/src/protocols/data_processing_events.h
index 8975c2b4a..5c8c16157 100644
--- a/libtransport/src/protocols/data_processing_events.h
+++ b/libtransport/src/protocols/data_processing_events.h
@@ -24,8 +24,7 @@ namespace protocol {
class ContentObjectProcessingEventCallback {
public:
virtual ~ContentObjectProcessingEventCallback() = default;
- virtual void onPacketDropped(core::Interest::Ptr &&i,
- core::ContentObject::Ptr &&c) = 0;
+ virtual void onPacketDropped(core::Interest &i, core::ContentObject &c) = 0;
virtual void onReassemblyFailed(std::uint32_t missing_segment) = 0;
};
diff --git a/libtransport/src/protocols/datagram_reassembly.cc b/libtransport/src/protocols/datagram_reassembly.cc
index abd7e984d..962c1e020 100644
--- a/libtransport/src/protocols/datagram_reassembly.cc
+++ b/libtransport/src/protocols/datagram_reassembly.cc
@@ -24,8 +24,8 @@ DatagramReassembly::DatagramReassembly(
TransportProtocol* transport_protocol)
: Reassembly(icn_socket, transport_protocol) {}
-void DatagramReassembly::reassemble(core::ContentObject::Ptr&& content_object) {
- read_buffer_ = content_object->getPayload();
+void DatagramReassembly::reassemble(core::ContentObject& content_object) {
+ read_buffer_ = content_object.getPayload();
Reassembly::notifyApplication();
}
diff --git a/libtransport/src/protocols/datagram_reassembly.h b/libtransport/src/protocols/datagram_reassembly.h
index 2427ae62f..3462212d3 100644
--- a/libtransport/src/protocols/datagram_reassembly.h
+++ b/libtransport/src/protocols/datagram_reassembly.h
@@ -26,7 +26,7 @@ class DatagramReassembly : public Reassembly {
DatagramReassembly(implementation::ConsumerSocket *icn_socket,
TransportProtocol *transport_protocol);
- virtual void reassemble(core::ContentObject::Ptr &&content_object) override;
+ virtual void reassemble(core::ContentObject &content_object) override;
virtual void reInitialize() override;
virtual void reassemble(
std::unique_ptr<core::ContentObjectManifest> &&manifest) override {
diff --git a/libtransport/src/protocols/errors.cc b/libtransport/src/protocols/errors.cc
index eefb6f957..ae7b6e634 100644
--- a/libtransport/src/protocols/errors.cc
+++ b/libtransport/src/protocols/errors.cc
@@ -52,7 +52,9 @@ std::string protocol_category_impl::message(int ev) const {
case protocol_error::session_aborted: {
return "The session has been aborted by the application.";
}
- default: { return "Unknown protocol error"; }
+ default: {
+ return "Unknown protocol error";
+ }
}
}
diff --git a/libtransport/src/protocols/fec_base.h b/libtransport/src/protocols/fec_base.h
new file mode 100644
index 000000000..a135c474f
--- /dev/null
+++ b/libtransport/src/protocols/fec_base.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/content_object.h>
+
+#include <functional>
+
+namespace transport {
+namespace protocol {
+
+/**
+ * Interface classes to integrate FEC inside any producer transport protocol
+ */
+class ProducerFECBase {
+ public:
+ /**
+ * Callback, to be called by implementations as soon as a repair packet is
+ * ready.
+ */
+ using RepairPacketsReady =
+ std::function<void(std::vector<core::ContentObject::Ptr> &)>;
+
+ /**
+ * Producers will call this function upon production of a new packet.
+ */
+ virtual void onPacketProduced(const core::ContentObject &content_object) = 0;
+
+ /**
+ * Set callback to signal production protocol the repair packet is ready.
+ */
+ void setFECCallback(const RepairPacketsReady &on_repair_packet) {
+ rep_packet_ready_callback_ = on_repair_packet;
+ }
+
+ protected:
+ RepairPacketsReady rep_packet_ready_callback_;
+};
+
+/**
+ * Interface classes to integrate FEC inside any consumer transport protocol
+ */
+class ConsumerFECBase {
+ public:
+ /**
+ * Callback, to be called by implemrntations as soon as a packet is recovered.
+ */
+ using OnPacketsRecovered =
+ std::function<void(std::vector<core::ContentObject::Ptr> &)>;
+
+ /**
+ * Consumers will call this function when they receive a FEC packet.
+ */
+ virtual void onFECPacket(const core::ContentObject &content_object) = 0;
+
+ /**
+ * Consumers will call this function when they receive a data packet
+ */
+ virtual void onDataPacket(const core::ContentObject &content_object) = 0;
+
+ /**
+ * Set callback to signal consumer protocol the repair packet is ready.
+ */
+ void setFECCallback(const OnPacketsRecovered &on_repair_packet) {
+ packet_recovered_callback_ = on_repair_packet;
+ }
+
+ protected:
+ OnPacketsRecovered packet_recovered_callback_;
+};
+
+} // namespace protocol
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/protocols/incremental_indexer.cc b/libtransport/src/protocols/incremental_indexer.cc
index e590b4fee..95daa0a3e 100644
--- a/libtransport/src/protocols/incremental_indexer.cc
+++ b/libtransport/src/protocols/incremental_indexer.cc
@@ -13,35 +13,38 @@
* limitations under the License.
*/
-#include <protocols/incremental_indexer.h>
-
#include <hicn/transport/interfaces/socket_consumer.h>
-#include <protocols/protocol.h>
+#include <protocols/errors.h>
+#include <protocols/incremental_indexer.h>
+#include <protocols/transport_protocol.h>
namespace transport {
namespace protocol {
-void IncrementalIndexer::onContentObject(
- core::Interest::Ptr &&interest, core::ContentObject::Ptr &&content_object) {
+void IncrementalIndexer::onContentObject(core::Interest &interest,
+ core::ContentObject &content_object) {
using namespace interface;
- if (TRANSPORT_EXPECT_FALSE(content_object->testRst())) {
- final_suffix_ = content_object->getName().getSuffix();
+ TRANSPORT_LOGD("Received content %s",
+ content_object.getName().toString().c_str());
+
+ if (TRANSPORT_EXPECT_FALSE(content_object.testRst())) {
+ final_suffix_ = content_object.getName().getSuffix();
}
- auto ret = verification_manager_->onPacketToVerify(*content_object);
+ auto ret = verifier_->verifyPackets(&content_object);
switch (ret) {
- case VerificationPolicy::ACCEPT_PACKET: {
- reassembly_->reassemble(std::move(content_object));
+ case auth::VerificationPolicy::ACCEPT: {
+ reassembly_->reassemble(content_object);
break;
}
- case VerificationPolicy::DROP_PACKET: {
- transport_protocol_->onPacketDropped(std::move(interest),
- std::move(content_object));
+ case auth::VerificationPolicy::UNKNOWN:
+ case auth::VerificationPolicy::DROP: {
+ transport_protocol_->onPacketDropped(interest, content_object);
break;
}
- case VerificationPolicy::ABORT_SESSION: {
+ case auth::VerificationPolicy::ABORT: {
transport_protocol_->onContentReassembled(
make_error_code(protocol_error::session_aborted));
break;
@@ -50,4 +53,4 @@ void IncrementalIndexer::onContentObject(
}
} // namespace protocol
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/src/protocols/incremental_indexer.h b/libtransport/src/protocols/incremental_indexer.h
index 20c5e4759..d7760f8e6 100644
--- a/libtransport/src/protocols/incremental_indexer.h
+++ b/libtransport/src/protocols/incremental_indexer.h
@@ -15,13 +15,13 @@
#pragma once
-#include <hicn/transport/errors/runtime_exception.h>
-#include <hicn/transport/errors/unexpected_manifest_exception.h>
+#include <hicn/transport/errors/errors.h>
+#include <hicn/transport/interfaces/callbacks.h>
+#include <hicn/transport/auth/verifier.h>
#include <hicn/transport/utils/literals.h>
-
+#include <implementation/socket_consumer.h>
#include <protocols/indexer.h>
#include <protocols/reassembly.h>
-#include <protocols/verification_manager.h>
#include <deque>
@@ -47,11 +47,12 @@ class IncrementalIndexer : public Indexer {
first_suffix_(0),
next_download_suffix_(0),
next_reassembly_suffix_(0),
- verification_manager_(
- std::make_unique<SignatureVerificationManager>(icn_socket)) {
+ verifier_(nullptr) {
if (reassembly_) {
reassembly_->setIndexer(this);
}
+ socket_->getSocketOption(implementation::GeneralTransportOptions::VERIFIER,
+ verifier_);
}
IncrementalIndexer(const IncrementalIndexer &) = delete;
@@ -64,15 +65,14 @@ class IncrementalIndexer : public Indexer {
first_suffix_(other.first_suffix_),
next_download_suffix_(other.next_download_suffix_),
next_reassembly_suffix_(other.next_reassembly_suffix_),
- verification_manager_(std::move(other.verification_manager_)) {
+ verifier_(nullptr) {
if (reassembly_) {
reassembly_->setIndexer(this);
}
+ socket_->getSocketOption(implementation::GeneralTransportOptions::VERIFIER,
+ verifier_);
}
- /**
- *
- */
virtual ~IncrementalIndexer() {}
TRANSPORT_ALWAYS_INLINE virtual void reset(
@@ -112,8 +112,8 @@ class IncrementalIndexer : public Indexer {
return final_suffix_;
}
- void onContentObject(core::Interest::Ptr &&interest,
- core::ContentObject::Ptr &&content_object) override;
+ void onContentObject(core::Interest &interest,
+ core::ContentObject &content_object) override;
TRANSPORT_ALWAYS_INLINE void setReassembly(Reassembly *reassembly) {
reassembly_ = reassembly;
@@ -123,10 +123,6 @@ class IncrementalIndexer : public Indexer {
}
}
- TRANSPORT_ALWAYS_INLINE bool onKeyToVerify() override {
- return verification_manager_->onKeyToVerify();
- }
-
protected:
implementation::ConsumerSocket *socket_;
Reassembly *reassembly_;
@@ -135,9 +131,8 @@ class IncrementalIndexer : public Indexer {
uint32_t first_suffix_;
uint32_t next_download_suffix_;
uint32_t next_reassembly_suffix_;
- std::unique_ptr<VerificationManager> verification_manager_;
+ std::shared_ptr<auth::Verifier> verifier_;
};
-} // end namespace protocol
-
-} // end namespace transport
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/protocols/indexer.cc b/libtransport/src/protocols/indexer.cc
index ca12330a6..1379a609c 100644
--- a/libtransport/src/protocols/indexer.cc
+++ b/libtransport/src/protocols/indexer.cc
@@ -14,11 +14,9 @@
*/
#include <hicn/transport/utils/branch_prediction.h>
-
#include <protocols/incremental_indexer.h>
#include <protocols/indexer.h>
#include <protocols/manifest_incremental_indexer.h>
-#include <protocols/protocol.h>
namespace transport {
namespace protocol {
@@ -32,16 +30,16 @@ IndexManager::IndexManager(implementation::ConsumerSocket *icn_socket,
transport_(transport),
reassembly_(reassembly) {}
-void IndexManager::onContentObject(core::Interest::Ptr &&interest,
- core::ContentObject::Ptr &&content_object) {
+void IndexManager::onContentObject(core::Interest &interest,
+ core::ContentObject &content_object) {
if (first_segment_received_) {
- indexer_->onContentObject(std::move(interest), std::move(content_object));
+ indexer_->onContentObject(interest, content_object);
} else {
- std::uint32_t segment_number = interest->getName().getSuffix();
+ std::uint32_t segment_number = interest.getName().getSuffix();
if (segment_number == 0) {
// Check if manifest
- if (content_object->getPayloadType() == PayloadType::MANIFEST) {
+ if (content_object.getPayloadType() == core::PayloadType::MANIFEST) {
IncrementalIndexer *indexer =
static_cast<IncrementalIndexer *>(indexer_.release());
indexer_ =
@@ -49,25 +47,21 @@ void IndexManager::onContentObject(core::Interest::Ptr &&interest,
delete indexer;
}
- indexer_->onContentObject(std::move(interest), std::move(content_object));
+ indexer_->onContentObject(interest, content_object);
auto it = interest_data_set_.begin();
while (it != interest_data_set_.end()) {
- indexer_->onContentObject(
- std::move(const_cast<core::Interest::Ptr &&>(it->first)),
- std::move(const_cast<core::ContentObject::Ptr &&>(it->second)));
+ indexer_->onContentObject(*it->first, *it->second);
it = interest_data_set_.erase(it);
}
first_segment_received_ = true;
} else {
- interest_data_set_.emplace(std::move(interest),
- std::move(content_object));
+ interest_data_set_.emplace(interest.shared_from_this(),
+ content_object.shared_from_this());
}
}
}
-bool IndexManager::onKeyToVerify() { return indexer_->onKeyToVerify(); }
-
void IndexManager::reset(std::uint32_t offset) {
indexer_ = std::make_unique<IncrementalIndexer>(icn_socket_, transport_,
reassembly_);
diff --git a/libtransport/src/protocols/indexer.h b/libtransport/src/protocols/indexer.h
index 8213a1503..49e22a4cf 100644
--- a/libtransport/src/protocols/indexer.h
+++ b/libtransport/src/protocols/indexer.h
@@ -33,10 +33,8 @@ class TransportProtocol;
class Indexer {
public:
- /**
- *
- */
virtual ~Indexer() = default;
+
/**
* Retrieve from the manifest the next suffix to retrieve.
*/
@@ -55,10 +53,8 @@ class Indexer {
virtual void reset(std::uint32_t offset = 0) = 0;
- virtual void onContentObject(core::Interest::Ptr &&interest,
- core::ContentObject::Ptr &&content_object) = 0;
-
- virtual bool onKeyToVerify() = 0;
+ virtual void onContentObject(core::Interest &interest,
+ core::ContentObject &content_object) = 0;
};
class IndexManager : Indexer {
@@ -86,10 +82,8 @@ class IndexManager : Indexer {
void reset(std::uint32_t offset = 0) override;
- void onContentObject(core::Interest::Ptr &&interest,
- core::ContentObject::Ptr &&content_object) override;
-
- bool onKeyToVerify() override;
+ void onContentObject(core::Interest &interest,
+ core::ContentObject &content_object) override;
private:
std::unique_ptr<Indexer> indexer_;
diff --git a/libtransport/src/protocols/manifest_incremental_indexer.cc b/libtransport/src/protocols/manifest_incremental_indexer.cc
index 1a2f9dec3..a6312ca90 100644
--- a/libtransport/src/protocols/manifest_incremental_indexer.cc
+++ b/libtransport/src/protocols/manifest_incremental_indexer.cc
@@ -14,9 +14,9 @@
*/
#include <implementation/socket_consumer.h>
-
+#include <protocols/errors.h>
#include <protocols/manifest_incremental_indexer.h>
-#include <protocols/protocol.h>
+#include <protocols/transport_protocol.h>
#include <cmath>
#include <deque>
@@ -36,39 +36,46 @@ ManifestIncrementalIndexer::ManifestIncrementalIndexer(
0)) {}
void ManifestIncrementalIndexer::onContentObject(
- core::Interest::Ptr &&interest, core::ContentObject::Ptr &&content_object) {
- // Check if mainfiest or not
- if (content_object->getPayloadType() == PayloadType::MANIFEST) {
- onUntrustedManifest(std::move(interest), std::move(content_object));
- } else if (content_object->getPayloadType() == PayloadType::CONTENT_OBJECT) {
- onUntrustedContentObject(std::move(interest), std::move(content_object));
- }
-}
-
-void ManifestIncrementalIndexer::onUntrustedManifest(
- core::Interest::Ptr &&interest, core::ContentObject::Ptr &&content_object) {
- auto ret = verification_manager_->onPacketToVerify(*content_object);
-
- switch (ret) {
- case VerificationPolicy::ACCEPT_PACKET: {
- processTrustedManifest(std::move(content_object));
+ core::Interest &interest, core::ContentObject &content_object) {
+ switch (content_object.getPayloadType()) {
+ case PayloadType::DATA: {
+ TRANSPORT_LOGD("Received content %s",
+ content_object.getName().toString().c_str());
+ onUntrustedContentObject(interest, content_object);
break;
}
- case VerificationPolicy::DROP_PACKET:
- case VerificationPolicy::ABORT_SESSION: {
- transport_protocol_->onContentReassembled(
- make_error_code(protocol_error::session_aborted));
+ case PayloadType::MANIFEST: {
+ TRANSPORT_LOGD("Received manifest %s",
+ content_object.getName().toString().c_str());
+ onUntrustedManifest(interest, content_object);
break;
}
+ default: {
+ return;
+ }
}
}
-void ManifestIncrementalIndexer::processTrustedManifest(
- ContentObject::Ptr &&content_object) {
+void ManifestIncrementalIndexer::onUntrustedManifest(
+ core::Interest &interest, core::ContentObject &content_object) {
auto manifest =
- std::make_unique<ContentObjectManifest>(std::move(*content_object));
+ std::make_unique<ContentObjectManifest>(std::move(content_object));
+
+ auth::VerificationPolicy policy = verifier_->verifyPackets(manifest.get());
+
manifest->decode();
+ if (policy != auth::VerificationPolicy::ACCEPT) {
+ transport_protocol_->onContentReassembled(
+ make_error_code(protocol_error::session_aborted));
+ return;
+ }
+
+ processTrustedManifest(interest, std::move(manifest));
+}
+
+void ManifestIncrementalIndexer::processTrustedManifest(
+ core::Interest &interest, std::unique_ptr<ContentObjectManifest> manifest) {
if (TRANSPORT_EXPECT_FALSE(manifest->getVersion() !=
core::ManifestVersion::VERSION_1)) {
throw errors::RuntimeException("Received manifest with unknown version.");
@@ -76,23 +83,45 @@ void ManifestIncrementalIndexer::processTrustedManifest(
switch (manifest->getManifestType()) {
case core::ManifestType::INLINE_MANIFEST: {
- auto _it = manifest->getSuffixList().begin();
- auto _end = manifest->getSuffixList().end();
-
suffix_strategy_->setFinalSuffix(manifest->getFinalBlockNumber());
- for (; _it != _end; _it++) {
- auto hash =
- std::make_pair(std::vector<uint8_t>(_it->second, _it->second + 32),
- manifest->getHashAlgorithm());
+ // The packets to verify with the received manifest
+ std::vector<auth::PacketPtr> packets;
+
+ // Convert the received manifest to a map of packet suffixes to hashes
+ std::unordered_map<auth::Suffix, auth::HashEntry> current_manifest =
+ core::ContentObjectManifest::getSuffixMap(manifest.get());
+
+ // Update 'suffix_map_' with new hashes from the received manifest and
+ // build 'packets'
+ for (auto it = current_manifest.begin(); it != current_manifest.end();) {
+ if (unverified_segments_.find(it->first) ==
+ unverified_segments_.end()) {
+ suffix_map_[it->first] = std::move(it->second);
+ current_manifest.erase(it++);
+ continue;
+ }
- if (!checkUnverifiedSegments(_it->first, hash)) {
- suffix_hash_map_[_it->first] = std::move(hash);
+ packets.push_back(unverified_segments_[it->first].second.get());
+ it++;
+ }
+
+ // Verify unverified segments using the received manifest
+ std::vector<auth::VerificationPolicy> policies =
+ verifier_->verifyPackets(packets, current_manifest);
+
+ for (unsigned int i = 0; i < packets.size(); ++i) {
+ auth::Suffix suffix = packets[i]->getName().getSuffix();
+
+ if (policies[i] != auth::VerificationPolicy::UNKNOWN) {
+ unverified_segments_.erase(suffix);
}
+
+ applyPolicy(*unverified_segments_[suffix].first,
+ *unverified_segments_[suffix].second, policies[i]);
}
reassembly_->reassemble(std::move(manifest));
-
break;
}
case core::ManifestType::FLIC_MANIFEST: {
@@ -104,89 +133,47 @@ void ManifestIncrementalIndexer::processTrustedManifest(
}
}
-bool ManifestIncrementalIndexer::checkUnverifiedSegments(
- std::uint32_t suffix, const HashEntry &hash) {
- auto it = unverified_segments_.find(suffix);
-
- if (it != unverified_segments_.end()) {
- auto ret = verifyContentObject(hash, *it->second.second);
-
- switch (ret) {
- case VerificationPolicy::ACCEPT_PACKET: {
- reassembly_->reassemble(std::move(it->second.second));
- break;
- }
- case VerificationPolicy::DROP_PACKET: {
- transport_protocol_->onPacketDropped(std::move(it->second.first),
- std::move(it->second.second));
- break;
- }
- case VerificationPolicy::ABORT_SESSION: {
- transport_protocol_->onContentReassembled(
- make_error_code(protocol_error::session_aborted));
- break;
- }
+void ManifestIncrementalIndexer::onUntrustedContentObject(
+ Interest &interest, ContentObject &content_object) {
+ auth::Suffix suffix = content_object.getName().getSuffix();
+ auth::VerificationPolicy policy =
+ verifier_->verifyPackets(&content_object, suffix_map_);
+
+ switch (policy) {
+ case auth::VerificationPolicy::UNKNOWN: {
+ unverified_segments_[suffix] = std::make_pair(
+ interest.shared_from_this(), content_object.shared_from_this());
+ break;
+ }
+ default: {
+ suffix_map_.erase(suffix);
+ break;
}
-
- unverified_segments_.erase(it);
- return true;
- }
-
- return false;
-}
-
-VerificationPolicy ManifestIncrementalIndexer::verifyContentObject(
- const HashEntry &manifest_hash, const ContentObject &content_object) {
- VerificationPolicy ret;
-
- auto hash_type = static_cast<utils::CryptoHashType>(manifest_hash.second);
- auto data_packet_digest = content_object.computeDigest(manifest_hash.second);
- auto data_packet_digest_bytes =
- data_packet_digest.getDigest<uint8_t>().data();
- const std::vector<uint8_t> &manifest_digest_bytes = manifest_hash.first;
-
- if (utils::CryptoHash::compareBinaryDigest(
- data_packet_digest_bytes, manifest_digest_bytes.data(), hash_type)) {
- ret = VerificationPolicy::ACCEPT_PACKET;
- } else {
- ConsumerContentObjectVerificationFailedCallback
- *verification_failed_callback = VOID_HANDLER;
- socket_->getSocketOption(ConsumerCallbacksOptions::VERIFICATION_FAILED,
- &verification_failed_callback);
- ret = (*verification_failed_callback)(
- *socket_->getInterface(), content_object,
- make_error_code(protocol_error::integrity_verification_failed));
}
- return ret;
+ applyPolicy(interest, content_object, policy);
}
-void ManifestIncrementalIndexer::onUntrustedContentObject(
- Interest::Ptr &&i, ContentObject::Ptr &&c) {
- auto suffix = c->getName().getSuffix();
- auto it = suffix_hash_map_.find(suffix);
-
- if (it != suffix_hash_map_.end()) {
- auto ret = verifyContentObject(it->second, *c);
-
- switch (ret) {
- case VerificationPolicy::ACCEPT_PACKET: {
- suffix_hash_map_.erase(it);
- reassembly_->reassemble(std::move(c));
- break;
- }
- case VerificationPolicy::DROP_PACKET: {
- transport_protocol_->onPacketDropped(std::move(i), std::move(c));
- break;
- }
- case VerificationPolicy::ABORT_SESSION: {
- transport_protocol_->onContentReassembled(
- make_error_code(protocol_error::session_aborted));
- break;
- }
+void ManifestIncrementalIndexer::applyPolicy(
+ core::Interest &interest, core::ContentObject &content_object,
+ auth::VerificationPolicy policy) {
+ switch (policy) {
+ case auth::VerificationPolicy::ACCEPT: {
+ reassembly_->reassemble(content_object);
+ break;
+ }
+ case auth::VerificationPolicy::DROP: {
+ transport_protocol_->onPacketDropped(interest, content_object);
+ break;
+ }
+ case auth::VerificationPolicy::ABORT: {
+ transport_protocol_->onContentReassembled(
+ make_error_code(protocol_error::session_aborted));
+ break;
+ }
+ default: {
+ break;
}
- } else {
- unverified_segments_[suffix] = std::make_pair(std::move(i), std::move(c));
}
}
@@ -222,7 +209,7 @@ uint32_t ManifestIncrementalIndexer::getNextReassemblySegment() {
void ManifestIncrementalIndexer::reset(std::uint32_t offset) {
IncrementalIndexer::reset(offset);
- suffix_hash_map_.clear();
+ suffix_map_.clear();
unverified_segments_.clear();
SuffixQueue empty;
std::swap(suffix_queue_, empty);
diff --git a/libtransport/src/protocols/manifest_incremental_indexer.h b/libtransport/src/protocols/manifest_incremental_indexer.h
index 38b01533e..1bb76eb87 100644
--- a/libtransport/src/protocols/manifest_incremental_indexer.h
+++ b/libtransport/src/protocols/manifest_incremental_indexer.h
@@ -15,6 +15,7 @@
#pragma once
+#include <hicn/transport/auth/common.h>
#include <implementation/socket.h>
#include <protocols/incremental_indexer.h>
#include <utils/suffix_strategy.h>
@@ -22,7 +23,6 @@
#include <list>
namespace transport {
-
namespace protocol {
class ManifestIncrementalIndexer : public IncrementalIndexer {
@@ -30,7 +30,8 @@ class ManifestIncrementalIndexer : public IncrementalIndexer {
public:
using SuffixQueue = std::queue<uint32_t>;
- using HashEntry = std::pair<std::vector<uint8_t>, utils::CryptoHashType>;
+ using InterestContentPair =
+ std::pair<core::Interest::Ptr, core::ContentObject::Ptr>;
ManifestIncrementalIndexer(implementation::ConsumerSocket *icn_socket,
TransportProtocol *transport,
@@ -50,8 +51,8 @@ class ManifestIncrementalIndexer : public IncrementalIndexer {
void reset(std::uint32_t offset = 0) override;
- void onContentObject(core::Interest::Ptr &&interest,
- core::ContentObject::Ptr &&content_object) override;
+ void onContentObject(core::Interest &interest,
+ core::ContentObject &content_object) override;
uint32_t getNextSuffix() override;
@@ -61,30 +62,24 @@ class ManifestIncrementalIndexer : public IncrementalIndexer {
uint32_t getFinalSuffix() override;
- private:
- void onUntrustedManifest(core::Interest::Ptr &&interest,
- core::ContentObject::Ptr &&content_object);
- void onUntrustedContentObject(core::Interest::Ptr &&interest,
- core::ContentObject::Ptr &&content_object);
- void processTrustedManifest(core::ContentObject::Ptr &&content_object);
- void onManifestReceived(core::Interest::Ptr &&i,
- core::ContentObject::Ptr &&c);
- void onManifestTimeout(core::Interest::Ptr &&i);
- VerificationPolicy verifyContentObject(
- const HashEntry &manifest_hash,
- const core::ContentObject &content_object);
- bool checkUnverifiedSegments(std::uint32_t suffix, const HashEntry &hash);
-
protected:
std::unique_ptr<utils::SuffixStrategy> suffix_strategy_;
SuffixQueue suffix_queue_;
// Hash verification
- std::unordered_map<uint32_t, HashEntry> suffix_hash_map_;
+ std::unordered_map<auth::Suffix, auth::HashEntry> suffix_map_;
+ std::unordered_map<auth::Suffix, InterestContentPair> unverified_segments_;
- std::unordered_map<uint32_t,
- std::pair<core::Interest::Ptr, core::ContentObject::Ptr>>
- unverified_segments_;
+ private:
+ void onUntrustedManifest(core::Interest &interest,
+ core::ContentObject &content_object);
+ void processTrustedManifest(core::Interest &interest,
+ std::unique_ptr<ContentObjectManifest> manifest);
+ void onUntrustedContentObject(core::Interest &interest,
+ core::ContentObject &content_object);
+ void applyPolicy(core::Interest &interest,
+ core::ContentObject &content_object,
+ auth::VerificationPolicy policy);
};
} // end namespace protocol
diff --git a/libtransport/src/protocols/prod_protocol_bytestream.cc b/libtransport/src/protocols/prod_protocol_bytestream.cc
new file mode 100644
index 000000000..6bd989fe4
--- /dev/null
+++ b/libtransport/src/protocols/prod_protocol_bytestream.cc
@@ -0,0 +1,390 @@
+/*
+ * 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 <implementation/socket_producer.h>
+#include <protocols/prod_protocol_bytestream.h>
+
+#include <atomic>
+
+namespace transport {
+
+namespace protocol {
+
+using namespace core;
+using namespace implementation;
+
+ByteStreamProductionProtocol::ByteStreamProductionProtocol(
+ implementation::ProducerSocket *icn_socket)
+ : ProductionProtocol(icn_socket) {}
+
+ByteStreamProductionProtocol::~ByteStreamProductionProtocol() {
+ stop();
+ if (listening_thread_.joinable()) {
+ listening_thread_.join();
+ }
+}
+
+uint32_t ByteStreamProductionProtocol::produceDatagram(
+ const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer) {
+ throw errors::NotImplementedException();
+}
+
+uint32_t ByteStreamProductionProtocol::produceDatagram(const Name &content_name,
+ const uint8_t *buffer,
+ size_t buffer_size) {
+ throw errors::NotImplementedException();
+}
+
+uint32_t ByteStreamProductionProtocol::produceStream(const Name &content_name,
+ const uint8_t *buffer,
+ size_t buffer_size,
+ bool is_last,
+ uint32_t start_offset) {
+ if (!buffer_size) {
+ return 0;
+ }
+
+ return produceStream(content_name,
+ utils::MemBuf::copyBuffer(buffer, buffer_size), is_last,
+ start_offset);
+}
+
+uint32_t ByteStreamProductionProtocol::produceStream(
+ const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer,
+ bool is_last, uint32_t start_offset) {
+ if (TRANSPORT_EXPECT_FALSE(buffer->length() == 0)) {
+ return 0;
+ }
+
+ Name name(content_name);
+
+ // Get the atomic variables to ensure they keep the same value
+ // during the production
+
+ // Total size of the data packet
+ uint32_t data_packet_size;
+ socket_->getSocketOption(GeneralTransportOptions::DATA_PACKET_SIZE,
+ data_packet_size);
+
+ // Expiry time
+ uint32_t content_object_expiry_time;
+ socket_->getSocketOption(GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
+ content_object_expiry_time);
+
+ // Hash algorithm
+ auth::CryptoHashType hash_algo;
+ socket_->getSocketOption(GeneralTransportOptions::HASH_ALGORITHM, hash_algo);
+
+ // Use manifest
+ bool making_manifest;
+ socket_->getSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
+ making_manifest);
+
+ // Suffix calculation strategy
+ core::NextSegmentCalculationStrategy _suffix_strategy;
+ socket_->getSocketOption(GeneralTransportOptions::SUFFIX_STRATEGY,
+ _suffix_strategy);
+ auto suffix_strategy = utils::SuffixStrategyFactory::getSuffixStrategy(
+ _suffix_strategy, start_offset);
+
+ std::shared_ptr<auth::Signer> signer;
+ socket_->getSocketOption(GeneralTransportOptions::SIGNER, signer);
+
+ auto buffer_size = buffer->length();
+ int bytes_segmented = 0;
+ std::size_t header_size;
+ std::size_t manifest_header_size = 0;
+ std::size_t signature_length = 0;
+ std::uint32_t final_block_number = start_offset;
+ uint64_t free_space_for_content = 0;
+
+ core::Packet::Format format;
+ std::shared_ptr<core::ContentObjectManifest> manifest;
+ bool is_last_manifest = false;
+
+ // TODO Manifest may still be used for indexing
+ if (making_manifest && !signer) {
+ TRANSPORT_LOGE("Making manifests without setting producer identity.");
+ }
+
+ core::Packet::Format hf_format = core::Packet::Format::HF_UNSPEC;
+ core::Packet::Format hf_format_ah = core::Packet::Format::HF_UNSPEC;
+
+ if (name.getType() == HNT_CONTIGUOUS_V4 || name.getType() == HNT_IOV_V4) {
+ hf_format = core::Packet::Format::HF_INET_TCP;
+ hf_format_ah = core::Packet::Format::HF_INET_TCP_AH;
+ } else if (name.getType() == HNT_CONTIGUOUS_V6 ||
+ name.getType() == HNT_IOV_V6) {
+ hf_format = core::Packet::Format::HF_INET6_TCP;
+ hf_format_ah = core::Packet::Format::HF_INET6_TCP_AH;
+ } else {
+ throw errors::RuntimeException("Unknown name format.");
+ }
+
+ format = hf_format;
+ if (making_manifest) {
+ manifest_header_size = core::Packet::getHeaderSizeFromFormat(
+ signer ? hf_format_ah : hf_format,
+ signer ? signer->getSignatureSize() : 0);
+ } else if (signer) {
+ format = hf_format_ah;
+ signature_length = signer->getSignatureSize();
+ }
+
+ header_size = core::Packet::getHeaderSizeFromFormat(format, signature_length);
+ free_space_for_content = data_packet_size - header_size;
+ uint32_t number_of_segments =
+ uint32_t(std::ceil(double(buffer_size) / double(free_space_for_content)));
+ if (free_space_for_content * number_of_segments < buffer_size) {
+ number_of_segments++;
+ }
+
+ // TODO allocate space for all the headers
+ if (making_manifest) {
+ uint32_t segment_in_manifest = static_cast<uint32_t>(
+ std::floor(double(data_packet_size - manifest_header_size -
+ ContentObjectManifest::getManifestHeaderSize()) /
+ ContentObjectManifest::getManifestEntrySize()) -
+ 1.0);
+ uint32_t number_of_manifests = static_cast<uint32_t>(
+ std::ceil(float(number_of_segments) / segment_in_manifest));
+ final_block_number += number_of_segments + number_of_manifests - 1;
+
+ manifest.reset(ContentObjectManifest::createManifest(
+ name.setSuffix(suffix_strategy->getNextManifestSuffix()),
+ core::ManifestVersion::VERSION_1, core::ManifestType::INLINE_MANIFEST,
+ hash_algo, is_last_manifest, name, _suffix_strategy,
+ signer ? signer->getSignatureSize() : 0));
+ manifest->setLifetime(content_object_expiry_time);
+
+ if (is_last) {
+ manifest->setFinalBlockNumber(final_block_number);
+ } else {
+ manifest->setFinalBlockNumber(utils::SuffixStrategy::INVALID_SUFFIX);
+ }
+ }
+
+ for (unsigned int packaged_segments = 0;
+ packaged_segments < number_of_segments; packaged_segments++) {
+ if (making_manifest) {
+ if (manifest->estimateManifestSize(2) >
+ data_packet_size - manifest_header_size) {
+ manifest->encode();
+
+ // If identity set, sign manifest
+ if (signer) {
+ signer->signPacket(manifest.get());
+ }
+
+ // Send the current manifest
+ passContentObjectToCallbacks(manifest);
+
+ TRANSPORT_LOGD("Send manifest %s",
+ manifest->getName().toString().c_str());
+
+ // Send content objects stored in the queue
+ while (!content_queue_.empty()) {
+ passContentObjectToCallbacks(content_queue_.front());
+ TRANSPORT_LOGD("Send content %s",
+ content_queue_.front()->getName().toString().c_str());
+ content_queue_.pop();
+ }
+
+ // Create new manifest. The reference to the last manifest has been
+ // acquired in the passContentObjectToCallbacks function, so we can
+ // safely release this reference
+ manifest.reset(ContentObjectManifest::createManifest(
+ name.setSuffix(suffix_strategy->getNextManifestSuffix()),
+ core::ManifestVersion::VERSION_1,
+ core::ManifestType::INLINE_MANIFEST, hash_algo, is_last_manifest,
+ name, _suffix_strategy, signer ? signer->getSignatureSize() : 0));
+
+ manifest->setLifetime(content_object_expiry_time);
+ manifest->setFinalBlockNumber(
+ is_last ? final_block_number
+ : utils::SuffixStrategy::INVALID_SUFFIX);
+ }
+ }
+
+ auto content_suffix = suffix_strategy->getNextContentSuffix();
+ auto content_object = std::make_shared<ContentObject>(
+ name.setSuffix(content_suffix), format,
+ signer && !making_manifest ? signer->getSignatureSize() : 0);
+ content_object->setLifetime(content_object_expiry_time);
+
+ auto b = buffer->cloneOne();
+ b->trimStart(free_space_for_content * packaged_segments);
+ b->trimEnd(b->length());
+
+ if (TRANSPORT_EXPECT_FALSE(packaged_segments == number_of_segments - 1)) {
+ b->append(buffer_size - bytes_segmented);
+ bytes_segmented += (int)(buffer_size - bytes_segmented);
+
+ if (is_last && making_manifest) {
+ is_last_manifest = true;
+ } else if (is_last) {
+ content_object->setRst();
+ }
+
+ } else {
+ b->append(free_space_for_content);
+ bytes_segmented += (int)(free_space_for_content);
+ }
+
+ content_object->appendPayload(std::move(b));
+
+ if (making_manifest) {
+ using namespace std::chrono_literals;
+ auth::CryptoHash hash = content_object->computeDigest(hash_algo);
+ manifest->addSuffixHash(content_suffix, hash);
+ content_queue_.push(content_object);
+ } else {
+ if (signer) {
+ signer->signPacket(content_object.get());
+ }
+ passContentObjectToCallbacks(content_object);
+ TRANSPORT_LOGD("Send content %s",
+ content_object->getName().toString().c_str());
+ }
+ }
+
+ if (making_manifest) {
+ if (is_last_manifest) {
+ manifest->setFinalManifest(is_last_manifest);
+ }
+
+ manifest->encode();
+
+ if (signer) {
+ signer->signPacket(manifest.get());
+ }
+
+ passContentObjectToCallbacks(manifest);
+ TRANSPORT_LOGD("Send manifest %s", manifest->getName().toString().c_str());
+
+ while (!content_queue_.empty()) {
+ passContentObjectToCallbacks(content_queue_.front());
+ TRANSPORT_LOGD("Send content %s",
+ content_queue_.front()->getName().toString().c_str());
+ content_queue_.pop();
+ }
+ }
+
+ portal_->getIoService().post([this]() {
+ std::shared_ptr<ContentObject> co;
+ while (object_queue_for_callbacks_.pop(co)) {
+ if (*on_new_segment_) {
+ on_new_segment_->operator()(*socket_->getInterface(), *co);
+ }
+
+ if (*on_content_object_to_sign_) {
+ on_content_object_to_sign_->operator()(*socket_->getInterface(), *co);
+ }
+
+ if (*on_content_object_in_output_buffer_) {
+ on_content_object_in_output_buffer_->operator()(
+ *socket_->getInterface(), *co);
+ }
+
+ if (*on_content_object_output_) {
+ on_content_object_output_->operator()(*socket_->getInterface(), *co);
+ }
+ }
+ });
+
+ portal_->getIoService().dispatch([this, buffer_size]() {
+ if (*on_content_produced_) {
+ on_content_produced_->operator()(*socket_->getInterface(),
+ std::make_error_code(std::errc(0)),
+ buffer_size);
+ }
+ });
+
+ return suffix_strategy->getTotalCount();
+}
+
+void ByteStreamProductionProtocol::scheduleSendBurst() {
+ portal_->getIoService().post([this]() {
+ std::shared_ptr<ContentObject> co;
+
+ for (uint32_t i = 0; i < burst_size; i++) {
+ if (object_queue_for_callbacks_.pop(co)) {
+ if (*on_new_segment_) {
+ on_new_segment_->operator()(*socket_->getInterface(), *co);
+ }
+
+ if (*on_content_object_to_sign_) {
+ on_content_object_to_sign_->operator()(*socket_->getInterface(), *co);
+ }
+
+ if (*on_content_object_in_output_buffer_) {
+ on_content_object_in_output_buffer_->operator()(
+ *socket_->getInterface(), *co);
+ }
+
+ if (*on_content_object_output_) {
+ on_content_object_output_->operator()(*socket_->getInterface(), *co);
+ }
+ } else {
+ break;
+ }
+ }
+ });
+}
+
+void ByteStreamProductionProtocol::passContentObjectToCallbacks(
+ const std::shared_ptr<ContentObject> &content_object) {
+ output_buffer_.insert(content_object);
+ portal_->sendContentObject(*content_object);
+ object_queue_for_callbacks_.push(std::move(content_object));
+
+ if (object_queue_for_callbacks_.size() >= burst_size) {
+ scheduleSendBurst();
+ }
+}
+
+void ByteStreamProductionProtocol::onInterest(Interest &interest) {
+ TRANSPORT_LOGD("Received interest for %s",
+ interest.getName().toString().c_str());
+ if (*on_interest_input_) {
+ on_interest_input_->operator()(*socket_->getInterface(), interest);
+ }
+
+ const std::shared_ptr<ContentObject> content_object =
+ output_buffer_.find(interest);
+
+ if (content_object) {
+ if (*on_interest_satisfied_output_buffer_) {
+ on_interest_satisfied_output_buffer_->operator()(*socket_->getInterface(),
+ interest);
+ }
+
+ if (*on_content_object_output_) {
+ on_content_object_output_->operator()(*socket_->getInterface(),
+ *content_object);
+ }
+
+ portal_->sendContentObject(*content_object);
+ } else {
+ if (*on_interest_process_) {
+ on_interest_process_->operator()(*socket_->getInterface(), interest);
+ }
+ }
+}
+
+void ByteStreamProductionProtocol::onError(std::error_code ec) {}
+
+} // namespace protocol
+} // end namespace transport
diff --git a/libtransport/src/protocols/prod_protocol_bytestream.h b/libtransport/src/protocols/prod_protocol_bytestream.h
new file mode 100644
index 000000000..cf36b90a5
--- /dev/null
+++ b/libtransport/src/protocols/prod_protocol_bytestream.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/utils/ring_buffer.h>
+#include <protocols/production_protocol.h>
+
+#include <atomic>
+#include <queue>
+
+namespace transport {
+
+namespace protocol {
+
+using namespace core;
+
+class ByteStreamProductionProtocol : public ProductionProtocol {
+ static constexpr uint32_t burst_size = 256;
+
+ public:
+ ByteStreamProductionProtocol(implementation::ProducerSocket *icn_socket);
+
+ ~ByteStreamProductionProtocol() override;
+
+ using ProductionProtocol::start;
+ using ProductionProtocol::stop;
+
+ uint32_t produceStream(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer,
+ bool is_last = true,
+ uint32_t start_offset = 0) override;
+ uint32_t produceStream(const Name &content_name, const uint8_t *buffer,
+ size_t buffer_size, bool is_last = true,
+ uint32_t start_offset = 0) override;
+ uint32_t produceDatagram(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer) override;
+ uint32_t produceDatagram(const Name &content_name, const uint8_t *buffer,
+ size_t buffer_size) override;
+
+ protected:
+ // Consumer Callback
+ // void reset() override;
+ void onInterest(core::Interest &i) override;
+ void onError(std::error_code ec) override;
+
+ private:
+ void passContentObjectToCallbacks(
+ const std::shared_ptr<ContentObject> &content_object);
+ void scheduleSendBurst();
+
+ private:
+ // While manifests are being built, contents are stored in a queue
+ std::queue<std::shared_ptr<ContentObject>> content_queue_;
+ utils::CircularFifo<std::shared_ptr<ContentObject>, 2048>
+ object_queue_for_callbacks_;
+};
+
+} // end namespace protocol
+} // end namespace transport
diff --git a/libtransport/src/protocols/prod_protocol_rtc.cc b/libtransport/src/protocols/prod_protocol_rtc.cc
new file mode 100644
index 000000000..049752876
--- /dev/null
+++ b/libtransport/src/protocols/prod_protocol_rtc.cc
@@ -0,0 +1,481 @@
+/*
+ * 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 <hicn/transport/core/global_object_pool.h>
+#include <implementation/socket_producer.h>
+#include <protocols/prod_protocol_rtc.h>
+#include <protocols/rtc/rtc_consts.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <unordered_set>
+
+namespace transport {
+namespace protocol {
+
+RTCProductionProtocol::RTCProductionProtocol(
+ implementation::ProducerSocket *icn_socket)
+ : ProductionProtocol(icn_socket),
+ current_seg_(1),
+ produced_bytes_(0),
+ produced_packets_(0),
+ max_packet_production_(1),
+ bytes_production_rate_(0),
+ packets_production_rate_(0),
+ last_round_(std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count()),
+ allow_delayed_nacks_(false),
+ queue_timer_on_(false),
+ consumer_in_sync_(false),
+ on_consumer_in_sync_(nullptr) {
+ srand((unsigned int)time(NULL));
+ prod_label_ = rand() % 256;
+ interests_queue_timer_ =
+ std::make_unique<asio::steady_timer>(portal_->getIoService());
+ round_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService());
+ setOutputBufferSize(10000);
+ scheduleRoundTimer();
+}
+
+RTCProductionProtocol::~RTCProductionProtocol() {}
+
+void RTCProductionProtocol::registerNamespaceWithNetwork(
+ const Prefix &producer_namespace) {
+ ProductionProtocol::registerNamespaceWithNetwork(producer_namespace);
+
+ flow_name_ = producer_namespace.getName();
+ auto family = flow_name_.getAddressFamily();
+
+ switch (family) {
+ case AF_INET6:
+ header_size_ = (uint32_t)Packet::getHeaderSizeFromFormat(HF_INET6_TCP);
+ break;
+ case AF_INET:
+ header_size_ = (uint32_t)Packet::getHeaderSizeFromFormat(HF_INET_TCP);
+ break;
+ default:
+ throw errors::RuntimeException("Unknown name format.");
+ }
+}
+
+void RTCProductionProtocol::scheduleRoundTimer() {
+ round_timer_->expires_from_now(
+ std::chrono::milliseconds(rtc::PRODUCER_STATS_INTERVAL));
+ round_timer_->async_wait([this](std::error_code ec) {
+ if (ec) return;
+ updateStats();
+ });
+}
+
+void RTCProductionProtocol::updateStats() {
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+ uint64_t duration = now - last_round_;
+ if (duration == 0) duration = 1;
+ double per_second = rtc::MILLI_IN_A_SEC / duration;
+
+ uint32_t prev_packets_production_rate = packets_production_rate_;
+
+ bytes_production_rate_ = (uint32_t)ceil((double)produced_bytes_ * per_second);
+ packets_production_rate_ = (uint32_t)ceil((double)produced_packets_ * per_second);
+
+ TRANSPORT_LOGD("Updating production rate: produced_bytes_ = %u bps = %u",
+ produced_bytes_, bytes_production_rate_);
+
+ // update the production rate as soon as it increases by 10% with respect to
+ // the last round
+ max_packet_production_ =
+ produced_packets_ + (uint32_t)ceil((double)produced_packets_ * 0.1);
+ if (max_packet_production_ < rtc::WIN_MIN)
+ max_packet_production_ = rtc::WIN_MIN;
+
+ if (packets_production_rate_ != 0) {
+ allow_delayed_nacks_ = false;
+ } else if (prev_packets_production_rate == 0) {
+ // at least 2 rounds with production rate = 0
+ allow_delayed_nacks_ = true;
+ }
+
+ // check if the production rate is decreased. if yes send nacks if needed
+ if (prev_packets_production_rate < packets_production_rate_) {
+ sendNacksForPendingInterests();
+ }
+
+ produced_bytes_ = 0;
+ produced_packets_ = 0;
+ last_round_ = now;
+ scheduleRoundTimer();
+}
+
+uint32_t RTCProductionProtocol::produceStream(
+ const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer,
+ bool is_last, uint32_t start_offset) {
+ throw errors::NotImplementedException();
+}
+
+uint32_t RTCProductionProtocol::produceStream(const Name &content_name,
+ const uint8_t *buffer,
+ size_t buffer_size, bool is_last,
+ uint32_t start_offset) {
+ throw errors::NotImplementedException();
+}
+
+void RTCProductionProtocol::produce(ContentObject &content_object) {
+ throw errors::NotImplementedException();
+}
+
+uint32_t RTCProductionProtocol::produceDatagram(
+ const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer) {
+ std::size_t buffer_size = buffer->length();
+ if (TRANSPORT_EXPECT_FALSE(buffer_size == 0)) return 0;
+
+ uint32_t data_packet_size;
+ socket_->getSocketOption(interface::GeneralTransportOptions::DATA_PACKET_SIZE,
+ data_packet_size);
+
+ if (TRANSPORT_EXPECT_FALSE((buffer_size + header_size_ +
+ rtc::DATA_HEADER_SIZE) > data_packet_size)) {
+ return 0;
+ }
+
+ auto content_object =
+ core::PacketManager<>::getInstance().getPacket<ContentObject>();
+ // add rtc header to the payload
+ struct rtc::data_packet_t header;
+ content_object->appendPayload((const uint8_t *)&header,
+ rtc::DATA_HEADER_SIZE);
+ content_object->appendPayload(buffer->data(), buffer->length());
+
+ std::shared_ptr<ContentObject> co = std::move(content_object);
+
+ // schedule actual sending on internal thread
+ portal_->getIoService().dispatch(
+ [this, content_object{std::move(co)}, content_name]() mutable {
+ produceInternal(std::move(content_object), content_name);
+ });
+
+ return 1;
+}
+
+void RTCProductionProtocol::produceInternal(
+ std::shared_ptr<ContentObject> &&content_object, const Name &content_name) {
+ // set rtc header
+ struct rtc::data_packet_t *data_pkt =
+ (struct rtc::data_packet_t *)content_object->getPayload()->data();
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+ data_pkt->setTimestamp(now);
+ data_pkt->setProductionRate(bytes_production_rate_);
+
+ // set hicn stuff
+ Name n(content_name);
+ content_object->setName(n.setSuffix(current_seg_));
+ content_object->setLifetime(500); // XXX this should be set by the APP
+ content_object->setPathLabel(prod_label_);
+
+ // update stats
+ produced_bytes_ += (uint32_t)(
+ content_object->headerSize() + content_object->payloadSize());
+ produced_packets_++;
+
+ if (produced_packets_ >= max_packet_production_) {
+ // in this case all the pending interests may be used to accomodate the
+ // sudden increase in the production rate. calling the updateStats we will
+ // notify all the clients
+ round_timer_->cancel();
+ updateStats();
+ }
+
+ TRANSPORT_LOGD("Sending content object: %s", n.toString().c_str());
+
+ output_buffer_.insert(content_object);
+
+ if (*on_content_object_in_output_buffer_) {
+ on_content_object_in_output_buffer_->operator()(*socket_->getInterface(),
+ *content_object);
+ }
+
+ portal_->sendContentObject(*content_object);
+
+ if (*on_content_object_output_) {
+ on_content_object_output_->operator()(*socket_->getInterface(),
+ *content_object);
+ }
+
+ // remove interests from the interest cache if it exists
+ removeFromInterestQueue(current_seg_);
+
+ current_seg_ = (current_seg_ + 1) % rtc::MIN_PROBE_SEQ;
+}
+
+void RTCProductionProtocol::onInterest(Interest &interest) {
+ uint32_t interest_seg = interest.getName().getSuffix();
+ uint32_t lifetime = interest.getLifetime();
+
+ if (interest_seg == 0) {
+ // first packet from the consumer, reset sync state
+ consumer_in_sync_ = false;
+ }
+
+ if (*on_interest_input_) {
+ on_interest_input_->operator()(*socket_->getInterface(), interest);
+ }
+
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+
+ if (interest_seg > rtc::MIN_PROBE_SEQ) {
+ TRANSPORT_LOGD("received probe %u", interest_seg);
+ sendNack(interest_seg);
+ return;
+ }
+
+ TRANSPORT_LOGD("received interest %u", interest_seg);
+
+ const std::shared_ptr<ContentObject> content_object =
+ output_buffer_.find(interest);
+
+ if (content_object) {
+ if (*on_interest_satisfied_output_buffer_) {
+ on_interest_satisfied_output_buffer_->operator()(*socket_->getInterface(),
+ interest);
+ }
+
+ if (*on_content_object_output_) {
+ on_content_object_output_->operator()(*socket_->getInterface(),
+ *content_object);
+ }
+
+ TRANSPORT_LOGD("Send content %u (onInterest)",
+ content_object->getName().getSuffix());
+ portal_->sendContentObject(*content_object);
+ return;
+ } else {
+ if (*on_interest_process_) {
+ on_interest_process_->operator()(*socket_->getInterface(), interest);
+ }
+ }
+
+ // if the production rate 0 use delayed nacks
+ if (allow_delayed_nacks_ && interest_seg >= current_seg_) {
+ uint64_t next_timer = ~0;
+ if (!timers_map_.empty()) {
+ next_timer = timers_map_.begin()->first;
+ }
+
+ uint64_t expiration = now + rtc::SENTINEL_TIMER_INTERVAL;
+ addToInterestQueue(interest_seg, expiration);
+
+ // here we have at least one interest in the queue, we need to start or
+ // update the timer
+ if (!queue_timer_on_) {
+ // set timeout
+ queue_timer_on_ = true;
+ scheduleQueueTimer(timers_map_.begin()->first - now);
+ } else {
+ // re-schedule the timer because a new interest will expires sooner
+ if (next_timer > timers_map_.begin()->first) {
+ interests_queue_timer_->cancel();
+ scheduleQueueTimer(timers_map_.begin()->first - now);
+ }
+ }
+ return;
+ }
+
+ if (queue_timer_on_) {
+ // the producer is producing. Send nacks to packets that will expire before
+ // the data production and remove the timer
+ queue_timer_on_ = false;
+ interests_queue_timer_->cancel();
+ sendNacksForPendingInterests();
+ }
+
+ uint32_t max_gap = (uint32_t)floor(
+ (double)((double)((double)lifetime *
+ rtc::INTEREST_LIFETIME_REDUCTION_FACTOR /
+ rtc::MILLI_IN_A_SEC) *
+ (double)packets_production_rate_));
+
+ if (interest_seg < current_seg_ || interest_seg > (max_gap + current_seg_)) {
+ sendNack(interest_seg);
+ } else {
+ if (!consumer_in_sync_ && on_consumer_in_sync_) {
+ // we consider the remote consumer to be in sync as soon as it covers 70%
+ // of the production window with interests
+ uint32_t perc = (uint32_t)ceil((double)max_gap * 0.7);
+ if (interest_seg > (perc + current_seg_)) {
+ consumer_in_sync_ = true;
+ on_consumer_in_sync_(*socket_->getInterface(), interest);
+ }
+ }
+ uint64_t expiration =(uint32_t)(
+ now + floor((double)lifetime * rtc::INTEREST_LIFETIME_REDUCTION_FACTOR));
+ addToInterestQueue(interest_seg, expiration);
+ }
+}
+
+void RTCProductionProtocol::onError(std::error_code ec) {}
+
+void RTCProductionProtocol::scheduleQueueTimer(uint64_t wait) {
+ interests_queue_timer_->expires_from_now(std::chrono::milliseconds(wait));
+ interests_queue_timer_->async_wait([this](std::error_code ec) {
+ if (ec) return;
+ interestQueueTimer();
+ });
+}
+
+void RTCProductionProtocol::addToInterestQueue(uint32_t interest_seg,
+ uint64_t expiration) {
+ // check if the seq number exists already
+ auto it_seqs = seqs_map_.find(interest_seg);
+ if (it_seqs != seqs_map_.end()) {
+ // the seq already exists
+ if (expiration < it_seqs->second) {
+ // we need to update the timer becasue we got a smaller one
+ // 1) remove the entry from the multimap
+ // 2) update this entry
+ auto range = timers_map_.equal_range(it_seqs->second);
+ for (auto it_timers = range.first; it_timers != range.second;
+ it_timers++) {
+ if (it_timers->second == it_seqs->first) {
+ timers_map_.erase(it_timers);
+ break;
+ }
+ }
+ timers_map_.insert(
+ std::pair<uint64_t, uint32_t>(expiration, interest_seg));
+ it_seqs->second = expiration;
+ } else {
+ // nothing to do here
+ return;
+ }
+ } else {
+ // add the new seq
+ timers_map_.insert(std::pair<uint64_t, uint32_t>(expiration, interest_seg));
+ seqs_map_.insert(std::pair<uint32_t, uint64_t>(interest_seg, expiration));
+ }
+}
+
+void RTCProductionProtocol::sendNacksForPendingInterests() {
+ std::unordered_set<uint32_t> to_remove;
+
+ uint32_t packet_gap = 100000; // set it to a high value (100sec)
+ if (packets_production_rate_ != 0)
+ packet_gap = (uint32_t)ceil(rtc::MILLI_IN_A_SEC / (double)packets_production_rate_);
+
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+
+ for (auto it = seqs_map_.begin(); it != seqs_map_.end(); it++) {
+ if (it->first > current_seg_) {
+ uint64_t production_time =
+ ((it->first - current_seg_) * packet_gap) + now;
+ if (production_time >= it->second) {
+ sendNack(it->first);
+ to_remove.insert(it->first);
+ }
+ }
+ }
+
+ // delete nacked interests
+ for (auto it = to_remove.begin(); it != to_remove.end(); it++) {
+ removeFromInterestQueue(*it);
+ }
+}
+
+void RTCProductionProtocol::removeFromInterestQueue(uint32_t interest_seg) {
+ auto seq_it = seqs_map_.find(interest_seg);
+ if (seq_it != seqs_map_.end()) {
+ auto range = timers_map_.equal_range(seq_it->second);
+ for (auto it_timers = range.first; it_timers != range.second; it_timers++) {
+ if (it_timers->second == seq_it->first) {
+ timers_map_.erase(it_timers);
+ break;
+ }
+ }
+ seqs_map_.erase(seq_it);
+ }
+}
+
+void RTCProductionProtocol::interestQueueTimer() {
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+
+ for (auto it_timers = timers_map_.begin(); it_timers != timers_map_.end();) {
+ uint64_t expire = it_timers->first;
+ if (expire <= now) {
+ uint32_t seq = it_timers->second;
+ sendNack(seq);
+ // remove the interest from the other map
+ seqs_map_.erase(seq);
+ it_timers = timers_map_.erase(it_timers);
+ } else {
+ // stop, we are done!
+ break;
+ }
+ }
+ if (timers_map_.empty()) {
+ queue_timer_on_ = false;
+ } else {
+ queue_timer_on_ = true;
+ scheduleQueueTimer(timers_map_.begin()->first - now);
+ }
+}
+
+void RTCProductionProtocol::sendNack(uint32_t sequence) {
+ auto nack = core::PacketManager<>::getInstance().getPacket<ContentObject>();
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+ uint32_t next_packet = current_seg_;
+ uint32_t prod_rate = bytes_production_rate_;
+
+ struct rtc::nack_packet_t header;
+ header.setTimestamp(now);
+ header.setProductionRate(prod_rate);
+ header.setProductionSegement(next_packet);
+ nack->appendPayload((const uint8_t *)&header, rtc::NACK_HEADER_SIZE);
+
+ Name n(flow_name_);
+ n.setSuffix(sequence);
+ nack->setName(n);
+ nack->setLifetime(0);
+ nack->setPathLabel(prod_label_);
+
+ if (!consumer_in_sync_ && on_consumer_in_sync_ &&
+ sequence < rtc::MIN_PROBE_SEQ && sequence > next_packet) {
+ consumer_in_sync_ = true;
+ auto interest = core::PacketManager<>::getInstance().getPacket<Interest>();
+ interest->setName(n);
+ on_consumer_in_sync_(*socket_->getInterface(), *interest);
+ }
+
+ if (*on_content_object_output_) {
+ on_content_object_output_->operator()(*socket_->getInterface(), *nack);
+ }
+
+ TRANSPORT_LOGD("Send nack %u", sequence);
+ portal_->sendContentObject(*nack);
+}
+
+} // namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/prod_protocol_rtc.h b/libtransport/src/protocols/prod_protocol_rtc.h
new file mode 100644
index 000000000..f3584f74a
--- /dev/null
+++ b/libtransport/src/protocols/prod_protocol_rtc.h
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/core/name.h>
+#include <protocols/production_protocol.h>
+
+#include <atomic>
+#include <map>
+#include <mutex>
+
+namespace transport {
+namespace protocol {
+
+class RTCProductionProtocol : public ProductionProtocol {
+ public:
+ RTCProductionProtocol(implementation::ProducerSocket *icn_socket);
+ ~RTCProductionProtocol() override;
+
+ using ProductionProtocol::start;
+ using ProductionProtocol::stop;
+
+ void produce(ContentObject &content_object) override;
+ uint32_t produceStream(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer,
+ bool is_last = true,
+ uint32_t start_offset = 0) override;
+ uint32_t produceStream(const Name &content_name, const uint8_t *buffer,
+ size_t buffer_size, bool is_last = true,
+ uint32_t start_offset = 0) override;
+ uint32_t produceDatagram(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer) override;
+ uint32_t produceDatagram(const Name &content_name, const uint8_t *buffer,
+ size_t buffer_size) override {
+ return produceDatagram(content_name, utils::MemBuf::wrapBuffer(
+ buffer, buffer_size, buffer_size));
+ }
+
+ void registerNamespaceWithNetwork(const Prefix &producer_namespace) override;
+
+ void setConsumerInSyncCallback(
+ interface::ProducerInterestCallback &&callback) {
+ on_consumer_in_sync_ = std::move(callback);
+ }
+
+ private:
+ // packet handlers
+ void onInterest(Interest &interest) override;
+ void onError(std::error_code ec) override;
+ void produceInternal(std::shared_ptr<ContentObject> &&content_object,
+ const Name &content_name);
+ void sendNack(uint32_t sequence);
+
+ // stats
+ void updateStats();
+ void scheduleRoundTimer();
+
+ // pending intersts functions
+ void addToInterestQueue(uint32_t interest_seg, uint64_t expiration);
+ void sendNacksForPendingInterests();
+ void removeFromInterestQueue(uint32_t interest_seg);
+ void scheduleQueueTimer(uint64_t wait);
+ void interestQueueTimer();
+
+ core::Name flow_name_;
+
+ uint32_t current_seg_; // seq id of the next packet produced
+ uint32_t prod_label_; // path lable of the producer
+ uint16_t header_size_; // hicn header size
+
+ uint32_t produced_bytes_; // bytes produced in the last round
+ uint32_t produced_packets_; // packet produed in the last round
+
+ uint32_t max_packet_production_; // never exceed this number of packets
+ // without update stats
+
+ uint32_t bytes_production_rate_; // bytes per sec
+ uint32_t packets_production_rate_; // pps
+
+ std::unique_ptr<asio::steady_timer> round_timer_;
+ uint64_t last_round_;
+
+ // delayed nacks are used by the producer to avoid to send too
+ // many nacks we the producer rate is 0. however, if the producer moves
+ // from a production rate higher than 0 to 0 the first round the dealyed
+ // should be avoided in order to notify the consumer as fast as possible
+ // of the new rate.
+ bool allow_delayed_nacks_;
+
+ // queue for the received interests
+ // this map maps the expiration time of an interest to
+ // its sequence number. the map is sorted by timeouts
+ // the same timeout may be used for multiple sequence numbers
+ // but for each sequence number we store only the smallest
+ // expiry time. In this way the mapping from seqs_map_ to
+ // timers_map_ is unique
+ std::multimap<uint64_t, uint32_t> timers_map_;
+
+ // this map does the opposite, this map is not ordered
+ std::unordered_map<uint32_t, uint64_t> seqs_map_;
+ bool queue_timer_on_;
+ std::unique_ptr<asio::steady_timer> interests_queue_timer_;
+
+ // this callback is called when the remote consumer is in sync with high
+ // probability. it is called only the first time that the switch happen.
+ // XXX this makes sense only in P2P mode, while in standard mode is
+ // impossible to know the state of the consumers so it should not be used.
+ bool consumer_in_sync_;
+ interface::ProducerInterestCallback on_consumer_in_sync_;
+};
+
+} // namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/production_protocol.cc b/libtransport/src/protocols/production_protocol.cc
new file mode 100644
index 000000000..8addf52d1
--- /dev/null
+++ b/libtransport/src/protocols/production_protocol.cc
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <implementation/socket_producer.h>
+#include <protocols/production_protocol.h>
+
+namespace transport {
+
+namespace protocol {
+
+using namespace interface;
+
+ProductionProtocol::ProductionProtocol(
+ implementation::ProducerSocket *icn_socket)
+ : socket_(icn_socket),
+ is_running_(false),
+ on_interest_input_(VOID_HANDLER),
+ on_interest_dropped_input_buffer_(VOID_HANDLER),
+ on_interest_inserted_input_buffer_(VOID_HANDLER),
+ on_interest_satisfied_output_buffer_(VOID_HANDLER),
+ on_interest_process_(VOID_HANDLER),
+ on_new_segment_(VOID_HANDLER),
+ on_content_object_to_sign_(VOID_HANDLER),
+ on_content_object_in_output_buffer_(VOID_HANDLER),
+ on_content_object_output_(VOID_HANDLER),
+ on_content_object_evicted_from_output_buffer_(VOID_HANDLER),
+ on_content_produced_(VOID_HANDLER) {
+ socket_->getSocketOption(GeneralTransportOptions::PORTAL, portal_);
+ // TODO add statistics for producer
+ // socket_->getSocketOption(OtherOptions::STATISTICS, &stats_);
+}
+
+ProductionProtocol::~ProductionProtocol() {
+ if (!is_async_ && is_running_) {
+ stop();
+ }
+
+ if (listening_thread_.joinable()) {
+ listening_thread_.join();
+ }
+}
+
+int ProductionProtocol::start() {
+ socket_->getSocketOption(ProducerCallbacksOptions::INTEREST_INPUT,
+ &on_interest_input_);
+ socket_->getSocketOption(ProducerCallbacksOptions::INTEREST_DROP,
+ &on_interest_dropped_input_buffer_);
+ socket_->getSocketOption(ProducerCallbacksOptions::INTEREST_PASS,
+ &on_interest_inserted_input_buffer_);
+ socket_->getSocketOption(ProducerCallbacksOptions::CACHE_HIT,
+ &on_interest_satisfied_output_buffer_);
+ socket_->getSocketOption(ProducerCallbacksOptions::CACHE_MISS,
+ &on_interest_process_);
+ socket_->getSocketOption(ProducerCallbacksOptions::NEW_CONTENT_OBJECT,
+ &on_new_segment_);
+ socket_->getSocketOption(ProducerCallbacksOptions::CONTENT_OBJECT_READY,
+ &on_content_object_in_output_buffer_);
+ socket_->getSocketOption(ProducerCallbacksOptions::CONTENT_OBJECT_OUTPUT,
+ &on_content_object_output_);
+ socket_->getSocketOption(ProducerCallbacksOptions::CONTENT_OBJECT_TO_SIGN,
+ &on_content_object_to_sign_);
+ socket_->getSocketOption(ProducerCallbacksOptions::CONTENT_PRODUCED,
+ &on_content_produced_);
+
+ socket_->getSocketOption(GeneralTransportOptions::ASYNC_MODE, is_async_);
+
+ bool first = true;
+
+ for (core::Prefix &producer_namespace : served_namespaces_) {
+ if (first) {
+ core::BindConfig bind_config(producer_namespace, 1000);
+ portal_->bind(bind_config);
+ portal_->setProducerCallback(this);
+ first = !first;
+ } else {
+ portal_->registerRoute(producer_namespace);
+ }
+ }
+
+ is_running_ = true;
+
+ if (!is_async_) {
+ listening_thread_ = std::thread([this]() { portal_->runEventsLoop(); });
+ }
+
+ return 0;
+}
+
+void ProductionProtocol::stop() {
+ is_running_ = false;
+
+ if (!is_async_) {
+ portal_->stopEventsLoop();
+ } else {
+ portal_->clear();
+ }
+}
+
+void ProductionProtocol::produce(ContentObject &content_object) {
+ if (*on_content_object_in_output_buffer_) {
+ on_content_object_in_output_buffer_->operator()(*socket_->getInterface(),
+ content_object);
+ }
+
+ output_buffer_.insert(std::static_pointer_cast<ContentObject>(
+ content_object.shared_from_this()));
+
+ if (*on_content_object_output_) {
+ on_content_object_output_->operator()(*socket_->getInterface(),
+ content_object);
+ }
+
+ portal_->sendContentObject(content_object);
+}
+
+void ProductionProtocol::registerNamespaceWithNetwork(
+ const Prefix &producer_namespace) {
+ served_namespaces_.push_back(producer_namespace);
+}
+
+} // namespace protocol
+
+} // namespace transport
diff --git a/libtransport/src/protocols/production_protocol.h b/libtransport/src/protocols/production_protocol.h
new file mode 100644
index 000000000..780972321
--- /dev/null
+++ b/libtransport/src/protocols/production_protocol.h
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/interfaces/callbacks.h>
+#include <hicn/transport/interfaces/socket_producer.h>
+#include <hicn/transport/interfaces/statistics.h>
+#include <hicn/transport/utils/object_pool.h>
+#include <implementation/socket.h>
+#include <utils/content_store.h>
+
+#include <atomic>
+#include <thread>
+
+namespace transport {
+
+namespace protocol {
+
+using namespace core;
+
+class ProductionProtocol : public Portal::ProducerCallback {
+ public:
+ ProductionProtocol(implementation::ProducerSocket *icn_socket);
+ virtual ~ProductionProtocol();
+
+ bool isRunning() { return is_running_; }
+
+ virtual int start();
+ virtual void stop();
+
+ virtual void produce(ContentObject &content_object);
+ virtual uint32_t produceStream(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer,
+ bool is_last = true,
+ uint32_t start_offset = 0) = 0;
+ virtual uint32_t produceStream(const Name &content_name,
+ const uint8_t *buffer, size_t buffer_size,
+ bool is_last = true,
+ uint32_t start_offset = 0) = 0;
+ virtual uint32_t produceDatagram(const Name &content_name,
+ std::unique_ptr<utils::MemBuf> &&buffer) = 0;
+ virtual uint32_t produceDatagram(const Name &content_name,
+ const uint8_t *buffer,
+ size_t buffer_size) = 0;
+
+ void setOutputBufferSize(std::size_t size) { output_buffer_.setLimit(size); }
+ std::size_t getOutputBufferSize() { return output_buffer_.getLimit(); }
+
+ virtual void registerNamespaceWithNetwork(const Prefix &producer_namespace);
+ const std::list<Prefix> &getNamespaces() const { return served_namespaces_; }
+
+ protected:
+ // Producer callback
+ virtual void onInterest(core::Interest &i) override = 0;
+ virtual void onError(std::error_code ec) override{};
+
+ protected:
+ implementation::ProducerSocket *socket_;
+
+ // Thread pool responsible for IO operations (send data / receive interests)
+ std::vector<utils::EventThread> io_threads_;
+
+ // TODO remove this thread
+ std::thread listening_thread_;
+ std::shared_ptr<Portal> portal_;
+ std::atomic<bool> is_running_;
+ interface::ProductionStatistics *stats_;
+
+ // Callbacks
+ interface::ProducerInterestCallback *on_interest_input_;
+ interface::ProducerInterestCallback *on_interest_dropped_input_buffer_;
+ interface::ProducerInterestCallback *on_interest_inserted_input_buffer_;
+ interface::ProducerInterestCallback *on_interest_satisfied_output_buffer_;
+ interface::ProducerInterestCallback *on_interest_process_;
+
+ interface::ProducerContentObjectCallback *on_new_segment_;
+ interface::ProducerContentObjectCallback *on_content_object_to_sign_;
+ interface::ProducerContentObjectCallback *on_content_object_in_output_buffer_;
+ interface::ProducerContentObjectCallback *on_content_object_output_;
+ interface::ProducerContentObjectCallback
+ *on_content_object_evicted_from_output_buffer_;
+
+ interface::ProducerContentCallback *on_content_produced_;
+
+ // Output buffer
+ utils::ContentStore output_buffer_;
+
+ // List ot routes served by current producer protocol
+ std::list<Prefix> served_namespaces_;
+
+ bool is_async_;
+};
+
+} // end namespace protocol
+} // end namespace transport
diff --git a/libtransport/src/protocols/protocol.cc b/libtransport/src/protocols/protocol.cc
index 8463f84f9..451fef80d 100644
--- a/libtransport/src/protocols/protocol.cc
+++ b/libtransport/src/protocols/protocol.cc
@@ -14,7 +14,6 @@
*/
#include <hicn/transport/interfaces/socket_consumer.h>
-
#include <implementation/socket_consumer.h>
#include <protocols/protocol.h>
@@ -49,12 +48,6 @@ int TransportProtocol::start() {
// If the protocol is already running, return otherwise set as running
if (is_running_) return -1;
- // Reset the protocol state machine
- reset();
-
- // Set it is the first time we schedule an interest
- is_first_ = true;
-
// Get all callbacks references before starting
socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_RETRANSMISSION,
&on_interest_retransmission_);
@@ -74,7 +67,13 @@ int TransportProtocol::start() {
&verification_failed_callback_);
socket_->getSocketOption(ConsumerCallbacksOptions::READ_CALLBACK,
&on_payload_);
+ socket_->getSocketOption(GeneralTransportOptions::ASYNC_MODE, is_async_);
+ // Set it is the first time we schedule an interest
+ is_first_ = true;
+
+ // Reset the protocol state machine
+ reset();
// Schedule next interests
scheduleNextInterests();
@@ -83,18 +82,25 @@ int TransportProtocol::start() {
// Set the protocol as running
is_running_ = true;
- // Start Event loop
- portal_->runEventsLoop();
+ if (!is_async_) {
+ // Start Event loop
+ portal_->runEventsLoop();
- // Not running anymore
- is_running_ = false;
+ // Not running anymore
+ is_running_ = false;
+ }
return 0;
}
void TransportProtocol::stop() {
is_running_ = false;
- portal_->stopEventsLoop();
+
+ if (!is_async_) {
+ portal_->stopEventsLoop();
+ } else {
+ portal_->clear();
+ }
}
void TransportProtocol::resume() {
@@ -110,6 +116,8 @@ void TransportProtocol::resume() {
}
void TransportProtocol::onContentReassembled(std::error_code ec) {
+ stop();
+
if (!on_payload_) {
throw errors::RuntimeException(
"The read callback must be installed in the transport before "
@@ -122,8 +130,6 @@ void TransportProtocol::onContentReassembled(std::error_code ec) {
} else {
on_payload_->readError(ec);
}
-
- stop();
}
} // end namespace protocol
diff --git a/libtransport/src/protocols/protocol.h b/libtransport/src/protocols/protocol.h
index db4524133..73a0a2c64 100644
--- a/libtransport/src/protocols/protocol.h
+++ b/libtransport/src/protocols/protocol.h
@@ -15,19 +15,18 @@
#pragma once
-#include <atomic>
-
#include <hicn/transport/interfaces/callbacks.h>
#include <hicn/transport/interfaces/socket_consumer.h>
#include <hicn/transport/interfaces/statistics.h>
#include <hicn/transport/utils/object_pool.h>
-
#include <implementation/socket.h>
#include <protocols/data_processing_events.h>
#include <protocols/indexer.h>
#include <protocols/packet_manager.h>
#include <protocols/reassembly.h>
+#include <atomic>
+
namespace transport {
namespace protocol {
@@ -107,6 +106,8 @@ class TransportProtocol : public implementation::BasePortal::ConsumerCallback,
interface::ConsumerContentObjectVerificationFailedCallback
*verification_failed_callback_;
ReadCallback *on_payload_;
+
+ bool is_async_;
};
} // end namespace protocol
diff --git a/libtransport/src/protocols/raaqm.cc b/libtransport/src/protocols/raaqm.cc
index 0a93dec44..bc8500227 100644
--- a/libtransport/src/protocols/raaqm.cc
+++ b/libtransport/src/protocols/raaqm.cc
@@ -13,8 +13,8 @@
* limitations under the License.
*/
+#include <hicn/transport/core/global_object_pool.h>
#include <hicn/transport/interfaces/socket_consumer.h>
-
#include <implementation/socket_consumer.h>
#include <protocols/errors.h>
#include <protocols/indexer.h>
@@ -36,7 +36,8 @@ RaaqmTransportProtocol::RaaqmTransportProtocol(
interests_in_flight_(0),
cur_path_(nullptr),
t0_(utils::SteadyClock::now()),
- rate_estimator_(nullptr) {
+ rate_estimator_(nullptr),
+ schedule_interests_(true) {
init();
}
@@ -116,10 +117,14 @@ void RaaqmTransportProtocol::reset() {
// Reset protocol variables
interests_in_flight_ = 0;
t0_ = utils::SteadyClock::now();
-}
-bool RaaqmTransportProtocol::verifyKeyPackets() {
- return index_manager_->onKeyToVerify();
+ // Optionally reset congestion window
+ bool reset_window;
+ socket_->getSocketOption(RaaqmTransportOptions::PER_SESSION_CWINDOW_RESET,
+ reset_window);
+ if (reset_window) {
+ current_window_size_ = 1;
+ }
}
void RaaqmTransportProtocol::increaseWindow() {
@@ -317,8 +322,8 @@ void RaaqmTransportProtocol::init() {
is.close();
}
-void RaaqmTransportProtocol::onContentObject(
- Interest::Ptr &&interest, ContentObject::Ptr &&content_object) {
+void RaaqmTransportProtocol::onContentObject(Interest &interest,
+ ContentObject &content_object) {
// Check whether makes sense to continue
if (TRANSPORT_EXPECT_FALSE(!is_running_)) {
return;
@@ -326,54 +331,53 @@ void RaaqmTransportProtocol::onContentObject(
// Call application-defined callbacks
if (*on_content_object_input_) {
- (*on_content_object_input_)(*socket_->getInterface(), *content_object);
+ (*on_content_object_input_)(*socket_->getInterface(), content_object);
}
if (*on_interest_satisfied_) {
- (*on_interest_satisfied_)(*socket_->getInterface(), *interest);
+ (*on_interest_satisfied_)(*socket_->getInterface(), interest);
}
- if (content_object->getPayloadType() == PayloadType::CONTENT_OBJECT) {
- stats_->updateBytesRecv(content_object->payloadSize());
+ if (content_object.getPayloadType() == PayloadType::DATA) {
+ stats_->updateBytesRecv(content_object.payloadSize());
}
- onContentSegment(std::move(interest), std::move(content_object));
+ onContentSegment(interest, content_object);
scheduleNextInterests();
}
-void RaaqmTransportProtocol::onContentSegment(
- Interest::Ptr &&interest, ContentObject::Ptr &&content_object) {
- uint32_t incremental_suffix = content_object->getName().getSuffix();
+void RaaqmTransportProtocol::onContentSegment(Interest &interest,
+ ContentObject &content_object) {
+ uint32_t incremental_suffix = content_object.getName().getSuffix();
// Decrease in-flight interests
interests_in_flight_--;
// Update stats
if (!interest_retransmissions_[incremental_suffix & mask]) {
- afterContentReception(*interest, *content_object);
+ afterContentReception(interest, content_object);
}
- index_manager_->onContentObject(std::move(interest),
- std::move(content_object));
+ index_manager_->onContentObject(interest, content_object);
}
-void RaaqmTransportProtocol::onPacketDropped(
- Interest::Ptr &&interest, ContentObject::Ptr &&content_object) {
+void RaaqmTransportProtocol::onPacketDropped(Interest &interest,
+ ContentObject &content_object) {
uint32_t max_rtx = 0;
socket_->getSocketOption(GeneralTransportOptions::MAX_INTEREST_RETX, max_rtx);
- uint64_t segment = interest->getName().getSuffix();
+ uint64_t segment = interest.getName().getSuffix();
if (TRANSPORT_EXPECT_TRUE(interest_retransmissions_[segment & mask] <
max_rtx)) {
stats_->updateRetxCount(1);
if (*on_interest_retransmission_) {
- (*on_interest_retransmission_)(*socket_->getInterface(), *interest);
+ (*on_interest_retransmission_)(*socket_->getInterface(), interest);
}
if (*on_interest_output_) {
- (*on_interest_output_)(*socket_->getInterface(), *interest);
+ (*on_interest_output_)(*socket_->getInterface(), interest);
}
if (!is_running_) {
@@ -381,7 +385,7 @@ void RaaqmTransportProtocol::onPacketDropped(
}
interest_retransmissions_[segment & mask]++;
- interest_to_retransmit_.push(std::move(interest));
+ interest_to_retransmit_.push(interest.shared_from_this());
} else {
TRANSPORT_LOGE(
"Stop: received not trusted packet %llu times",
@@ -432,10 +436,6 @@ void RaaqmTransportProtocol::onTimeout(Interest::Ptr &&interest) {
(*on_interest_retransmission_)(*socket_->getInterface(), *interest);
}
- if (*on_interest_output_) {
- (*on_interest_output_)(*socket_->getInterface(), *interest);
- }
-
if (!is_running_) {
return;
}
@@ -451,7 +451,9 @@ void RaaqmTransportProtocol::onTimeout(Interest::Ptr &&interest) {
}
void RaaqmTransportProtocol::scheduleNextInterests() {
- if (TRANSPORT_EXPECT_FALSE(!is_running_ && !is_first_)) {
+ bool cancel = (!is_running_ && !is_first_) || !schedule_interests_;
+ if (TRANSPORT_EXPECT_FALSE(cancel)) {
+ schedule_interests_ = true;
return;
}
@@ -460,7 +462,6 @@ void RaaqmTransportProtocol::scheduleNextInterests() {
// send at least one interest if there are retransmissions to perform and
// there is no space left in the window
sendInterest(std::move(interest_to_retransmit_.front()));
- TRANSPORT_LOGD("Window full, retransmit one content interest");
interest_to_retransmit_.pop();
}
@@ -470,22 +471,25 @@ void RaaqmTransportProtocol::scheduleNextInterests() {
while (interests_in_flight_ < current_window_size_) {
if (interest_to_retransmit_.size() > 0) {
sendInterest(std::move(interest_to_retransmit_.front()));
- TRANSPORT_LOGD("Retransmit content interest");
interest_to_retransmit_.pop();
} else {
+ if (TRANSPORT_EXPECT_FALSE(!is_running_ && !is_first_)) {
+ TRANSPORT_LOGI("Adios");
+ break;
+ }
+
index = index_manager_->getNextSuffix();
if (index == IndexManager::invalid_index) {
break;
}
sendInterest(index);
- TRANSPORT_LOGD("Send content interest %u", index);
}
}
}
-bool RaaqmTransportProtocol::sendInterest(std::uint64_t next_suffix) {
- auto interest = getPacket();
+void RaaqmTransportProtocol::sendInterest(std::uint64_t next_suffix) {
+ auto interest = core::PacketManager<>::getInstance().getPacket<Interest>();
core::Name *name;
socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME, &name);
name->setSuffix((uint32_t)next_suffix);
@@ -499,30 +503,26 @@ bool RaaqmTransportProtocol::sendInterest(std::uint64_t next_suffix) {
if (*on_interest_output_) {
on_interest_output_->operator()(*socket_->getInterface(), *interest);
}
-
- if (TRANSPORT_EXPECT_FALSE(!is_running_ && !is_first_)) {
- return false;
- }
-
// This is set to ~0 so that the next interest_retransmissions_ + 1,
// performed by sendInterest, will result in 0
interest_retransmissions_[next_suffix & mask] = ~0;
interest_timepoints_[next_suffix & mask] = utils::SteadyClock::now();
- sendInterest(std::move(interest));
- return true;
+ sendInterest(std::move(interest));
}
void RaaqmTransportProtocol::sendInterest(Interest::Ptr &&interest) {
interests_in_flight_++;
interest_retransmissions_[interest->getName().getSuffix() & mask]++;
+ TRANSPORT_LOGD("Send interest %s", interest->getName().toString().c_str());
portal_->sendInterest(std::move(interest));
}
void RaaqmTransportProtocol::onContentReassembled(std::error_code ec) {
rate_estimator_->onDownloadFinished();
TransportProtocol::onContentReassembled(ec);
+ schedule_interests_ = false;
}
void RaaqmTransportProtocol::updateRtt(uint64_t segment) {
diff --git a/libtransport/src/protocols/raaqm.h b/libtransport/src/protocols/raaqm.h
index ecc466755..be477d39f 100644
--- a/libtransport/src/protocols/raaqm.h
+++ b/libtransport/src/protocols/raaqm.h
@@ -16,12 +16,11 @@
#pragma once
#include <hicn/transport/utils/chrono_typedefs.h>
-
#include <protocols/byte_stream_reassembly.h>
#include <protocols/congestion_window_protocol.h>
-#include <protocols/protocol.h>
#include <protocols/raaqm_data_path.h>
#include <protocols/rate_estimation.h>
+#include <protocols/transport_protocol.h>
#include <queue>
#include <vector>
@@ -43,8 +42,6 @@ class RaaqmTransportProtocol : public TransportProtocol,
void reset() override;
- virtual bool verifyKeyPackets() override;
-
protected:
static constexpr uint32_t buffer_size =
1 << interface::default_values::log_2_default_buffer_size;
@@ -65,13 +62,12 @@ class RaaqmTransportProtocol : public TransportProtocol,
private:
void init();
- void onContentObject(Interest::Ptr &&i, ContentObject::Ptr &&c) override;
+ void onContentObject(Interest &i, ContentObject &c) override;
- void onContentSegment(Interest::Ptr &&interest,
- ContentObject::Ptr &&content_object);
+ void onContentSegment(Interest &interest, ContentObject &content_object);
- void onPacketDropped(Interest::Ptr &&interest,
- ContentObject::Ptr &&content_object) override;
+ void onPacketDropped(Interest &interest,
+ ContentObject &content_object) override;
void onReassemblyFailed(std::uint32_t missing_segment) override;
@@ -79,7 +75,7 @@ class RaaqmTransportProtocol : public TransportProtocol,
virtual void scheduleNextInterests() override;
- bool sendInterest(std::uint64_t next_suffix);
+ void sendInterest(std::uint64_t next_suffix);
void sendInterest(Interest::Ptr &&interest);
@@ -135,6 +131,8 @@ class RaaqmTransportProtocol : public TransportProtocol,
double drop_lte_;
unsigned int wifi_delay_;
unsigned int lte_delay_;
+
+ bool schedule_interests_;
};
} // end namespace protocol
diff --git a/libtransport/src/protocols/raaqm_data_path.cc b/libtransport/src/protocols/raaqm_data_path.cc
index 8bbbadcf2..f2c21b9ef 100644
--- a/libtransport/src/protocols/raaqm_data_path.cc
+++ b/libtransport/src/protocols/raaqm_data_path.cc
@@ -14,7 +14,6 @@
*/
#include <hicn/transport/utils/chrono_typedefs.h>
-
#include <protocols/raaqm_data_path.h>
namespace transport {
diff --git a/libtransport/src/protocols/raaqm_data_path.h b/libtransport/src/protocols/raaqm_data_path.h
index 3f037bc76..c0b53a690 100644
--- a/libtransport/src/protocols/raaqm_data_path.h
+++ b/libtransport/src/protocols/raaqm_data_path.h
@@ -16,7 +16,6 @@
#pragma once
#include <hicn/transport/utils/chrono_typedefs.h>
-
#include <utils/min_filter.h>
#include <chrono>
diff --git a/libtransport/src/protocols/rate_estimation.cc b/libtransport/src/protocols/rate_estimation.cc
index a2cf1aefe..5ca925760 100644
--- a/libtransport/src/protocols/rate_estimation.cc
+++ b/libtransport/src/protocols/rate_estimation.cc
@@ -15,7 +15,6 @@
#include <hicn/transport/interfaces/socket_options_default_values.h>
#include <hicn/transport/utils/log.h>
-
#include <protocols/rate_estimation.h>
#include <thread>
diff --git a/libtransport/src/protocols/rate_estimation.h b/libtransport/src/protocols/rate_estimation.h
index 17f39e0b9..42ae74194 100644
--- a/libtransport/src/protocols/rate_estimation.h
+++ b/libtransport/src/protocols/rate_estimation.h
@@ -16,7 +16,6 @@
#pragma once
#include <hicn/transport/interfaces/statistics.h>
-
#include <protocols/raaqm_data_path.h>
#include <chrono>
diff --git a/libtransport/src/protocols/reassembly.cc b/libtransport/src/protocols/reassembly.cc
index c6602153c..0e59832dc 100644
--- a/libtransport/src/protocols/reassembly.cc
+++ b/libtransport/src/protocols/reassembly.cc
@@ -16,7 +16,6 @@
#include <hicn/transport/interfaces/socket_consumer.h>
#include <hicn/transport/utils/array.h>
#include <hicn/transport/utils/membuf.h>
-
#include <implementation/socket_consumer.h>
#include <protocols/errors.h>
#include <protocols/indexer.h>
diff --git a/libtransport/src/protocols/reassembly.h b/libtransport/src/protocols/reassembly.h
index fdc9f2a05..385122c53 100644
--- a/libtransport/src/protocols/reassembly.h
+++ b/libtransport/src/protocols/reassembly.h
@@ -46,7 +46,7 @@ class Reassembly {
virtual ~Reassembly() = default;
- virtual void reassemble(core::ContentObject::Ptr &&content_object) = 0;
+ virtual void reassemble(core::ContentObject &content_object) = 0;
virtual void reassemble(
std::unique_ptr<core::ContentObjectManifest> &&manifest) = 0;
virtual void reInitialize() = 0;
diff --git a/libtransport/src/protocols/rtc.cc b/libtransport/src/protocols/rtc.cc
index 72abb599a..a01b8daa5 100644
--- a/libtransport/src/protocols/rtc.cc
+++ b/libtransport/src/protocols/rtc.cc
@@ -13,12 +13,11 @@
* limitations under the License.
*/
-#include <protocols/rtc.h>
-
#include <hicn/transport/interfaces/socket_consumer.h>
#include <implementation/socket_consumer.h>
-
#include <math.h>
+#include <protocols/rtc.h>
+
#include <random>
namespace transport {
@@ -39,40 +38,10 @@ RTCTransportProtocol::RTCTransportProtocol(
sentinel_timer_ =
std::make_unique<asio::steady_timer>(portal_->getIoService());
round_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService());
- reset();
+ initParams();
}
-RTCTransportProtocol::~RTCTransportProtocol() {
- if (is_running_) {
- stop();
- }
-}
-
-int RTCTransportProtocol::start() {
- if (is_running_) return -1;
-
- reset();
- is_first_ = true;
-
- probeRtt();
- sentinelTimer();
- newRound();
- scheduleNextInterests();
-
- is_first_ = false;
- is_running_ = true;
- portal_->runEventsLoop();
- is_running_ = false;
-
- return 0;
-}
-
-void RTCTransportProtocol::stop() {
- if (!is_running_) return;
-
- is_running_ = false;
- portal_->stopEventsLoop();
-}
+RTCTransportProtocol::~RTCTransportProtocol() {}
void RTCTransportProtocol::resume() {
if (is_running_) return;
@@ -90,7 +59,7 @@ void RTCTransportProtocol::resume() {
}
// private
-void RTCTransportProtocol::reset() {
+void RTCTransportProtocol::initParams() {
portal_->setConsumerCallback(this);
// controller var
currentState_ = HICN_RTC_SYNC_STATE;
@@ -143,7 +112,14 @@ void RTCTransportProtocol::reset() {
socket_->setSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
(uint32_t)HICN_RTC_INTEREST_LIFETIME);
- // XXX this should be done by the application
+}
+
+// private
+void RTCTransportProtocol::reset() {
+ initParams();
+ probeRtt();
+ sentinelTimer();
+ newRound();
}
uint32_t max(uint32_t a, uint32_t b) {
@@ -372,6 +348,8 @@ void RTCTransportProtocol::computeMaxWindow(uint32_t productionRate,
void RTCTransportProtocol::updateWindow() {
if (currentState_ == HICN_RTC_SYNC_STATE) return;
+ if (estimatedBw_ == 0) return;
+
if (currentCWin_ < maxCWin_ * 0.9) {
currentCWin_ =
min(maxCWin_, (uint32_t)(currentCWin_ * HICN_WIN_INCREASE_FACTOR));
diff --git a/libtransport/src/protocols/rtc.h b/libtransport/src/protocols/rtc.h
index f15cdd1eb..9f1bcc25b 100644
--- a/libtransport/src/protocols/rtc.h
+++ b/libtransport/src/protocols/rtc.h
@@ -93,9 +93,9 @@ class RTCTransportProtocol : public TransportProtocol,
~RTCTransportProtocol();
- int start() override;
+ using TransportProtocol::start;
- void stop() override;
+ using TransportProtocol::stop;
void resume() override;
@@ -103,6 +103,7 @@ class RTCTransportProtocol : public TransportProtocol,
private:
// algo functions
+ void initParams();
void reset() override;
// CC functions
diff --git a/libtransport/src/protocols/rtc/CMakeLists.txt b/libtransport/src/protocols/rtc/CMakeLists.txt
new file mode 100644
index 000000000..77f065d0e
--- /dev/null
+++ b/libtransport/src/protocols/rtc/CMakeLists.txt
@@ -0,0 +1,38 @@
+# 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.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+
+list(APPEND HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_state.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_ldr.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_data_path.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_consts.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc_queue.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/probe_handler.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_packet.h
+)
+
+list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_state.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_ldr.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_rc_queue.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/rtc_data_path.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/probe_handler.cc
+)
+
+set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
+set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/protocols/rtc/congestion_detection.cc b/libtransport/src/protocols/rtc/congestion_detection.cc
new file mode 100644
index 000000000..e2d44ae66
--- /dev/null
+++ b/libtransport/src/protocols/rtc/congestion_detection.cc
@@ -0,0 +1,101 @@
+/*
+ * 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 <hicn/transport/utils/log.h>
+#include <protocols/rtc/congestion_detection.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+CongestionDetection::CongestionDetection()
+ : cc_estimator_(), last_processed_chunk_() {}
+
+CongestionDetection::~CongestionDetection() {}
+
+void CongestionDetection::updateStats() {
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+
+ if (chunks_number_.empty()) return;
+
+ uint32_t chunk_number = chunks_number_.front();
+
+ while (chunks_[chunk_number].getReceivedTime() + HICN_CC_STATS_MAX_DELAY_MS <
+ now ||
+ chunks_[chunk_number].isComplete()) {
+ if (chunk_number == last_processed_chunk_.getFrameSeqNum() + 1) {
+ chunks_[chunk_number].setPreviousSentTime(
+ last_processed_chunk_.getSentTime());
+
+ chunks_[chunk_number].setPreviousReceivedTime(
+ last_processed_chunk_.getReceivedTime());
+ cc_estimator_.Update(chunks_[chunk_number].getReceivedDelta(),
+ chunks_[chunk_number].getSentDelta(),
+ chunks_[chunk_number].getSentTime(),
+ chunks_[chunk_number].getReceivedTime(),
+ chunks_[chunk_number].getFrameSize(), true);
+
+ } else {
+ TRANSPORT_LOGD(
+ "CongestionDetection::updateStats frame %u but not the \
+ previous one, last one was %u currentFrame %u",
+ chunk_number, last_processed_chunk_.getFrameSeqNum(),
+ chunks_[chunk_number].getFrameSeqNum());
+ }
+
+ last_processed_chunk_ = chunks_[chunk_number];
+
+ chunks_.erase(chunk_number);
+
+ chunks_number_.pop();
+ if (chunks_number_.empty()) break;
+
+ chunk_number = chunks_number_.front();
+ }
+}
+
+void CongestionDetection::addPacket(const core::ContentObject &content_object) {
+ auto payload = content_object.getPayload();
+ uint32_t payload_size = (uint32_t)payload->length();
+ uint32_t segmentNumber = content_object.getName().getSuffix();
+ // uint32_t pkt = segmentNumber & modMask_;
+ uint64_t *sentTimePtr = (uint64_t *)payload->data();
+
+ // this is just for testing with hiperf, assuming a frame is 10 pkts
+ // in the final version, the split should be based on the timestamp in the pkt
+ uint32_t frameNum = (int)(segmentNumber / HICN_CC_STATS_CHUNK_SIZE);
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+
+ if (chunks_.find(frameNum) == chunks_.end()) {
+ // new chunk of pkts or out of order
+ if (last_processed_chunk_.getFrameSeqNum() > frameNum)
+ return; // out of order and we already processed the chunk
+
+ chunks_[frameNum] = FrameStats(frameNum, HICN_CC_STATS_CHUNK_SIZE);
+ chunks_number_.push(frameNum);
+ }
+
+ chunks_[frameNum].addPacket(*sentTimePtr, now, payload_size);
+}
+
+} // namespace rtc
+} // namespace protocol
+} // namespace transport
diff --git a/libtransport/src/protocols/rtc/congestion_detection.h b/libtransport/src/protocols/rtc/congestion_detection.h
new file mode 100644
index 000000000..17f4aa54c
--- /dev/null
+++ b/libtransport/src/protocols/rtc/congestion_detection.h
@@ -0,0 +1,138 @@
+/*
+ * 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 <hicn/transport/core/content_object.h>
+#include <protocols/rtc/trendline_estimator.h>
+
+#include <map>
+#include <queue>
+
+#define HICN_CC_STATS_CHUNK_SIZE 10
+#define HICN_CC_STATS_MAX_DELAY_MS 100
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class FrameStats {
+ public:
+ FrameStats()
+ : frame_num_(0),
+ sent_time_(0),
+ received_time_(0),
+ previous_sent_time_(0),
+ previous_received_time_(0),
+ size_(0),
+ received_pkt_m(0),
+ burst_size_m(HICN_CC_STATS_CHUNK_SIZE){};
+
+ FrameStats(uint32_t burst_size)
+ : frame_num_(0),
+ sent_time_(0),
+ received_time_(0),
+ previous_sent_time_(0),
+ previous_received_time_(0),
+ size_(0),
+ received_pkt_m(0),
+ burst_size_m(burst_size){};
+
+ FrameStats(uint32_t frame_num, uint32_t burst_size)
+ : frame_num_(frame_num),
+ sent_time_(0),
+ received_time_(0),
+ previous_sent_time_(0),
+ previous_received_time_(0),
+ size_(0),
+ received_pkt_m(0),
+ burst_size_m(burst_size){};
+
+ FrameStats(uint32_t frame_num, uint64_t sent_time, uint64_t received_time,
+ uint32_t size, FrameStats previousFrame, uint32_t burst_size)
+ : frame_num_(frame_num),
+ sent_time_(sent_time),
+ received_time_(received_time),
+ previous_sent_time_(previousFrame.getSentTime()),
+ previous_received_time_(previousFrame.getReceivedTime()),
+ size_(size),
+ received_pkt_m(1),
+ burst_size_m(burst_size){};
+
+ void addPacket(uint64_t sent_time, uint64_t received_time, uint32_t size) {
+ size_ += size;
+ sent_time_ =
+ (sent_time_ == 0) ? sent_time : std::min(sent_time_, sent_time);
+ received_time_ = std::max(received_time, received_time_);
+ received_pkt_m++;
+ }
+
+ bool isComplete() { return received_pkt_m == burst_size_m; }
+
+ uint32_t getFrameSeqNum() const { return frame_num_; }
+ uint64_t getSentTime() const { return sent_time_; }
+ uint64_t getReceivedTime() const { return received_time_; }
+ uint32_t getFrameSize() const { return size_; }
+
+ void setPreviousReceivedTime(uint64_t time) {
+ previous_received_time_ = time;
+ }
+ void setPreviousSentTime(uint64_t time) { previous_sent_time_ = time; }
+
+ // todo manage first frame
+ double getReceivedDelta() {
+ return static_cast<double>(received_time_ - previous_received_time_);
+ }
+ double getSentDelta() {
+ return static_cast<double>(sent_time_ - previous_sent_time_);
+ }
+
+ private:
+ uint32_t frame_num_;
+ uint64_t sent_time_;
+ uint64_t received_time_;
+
+ uint64_t previous_sent_time_;
+ uint64_t previous_received_time_;
+ uint32_t size_;
+
+ uint32_t received_pkt_m;
+ uint32_t burst_size_m;
+};
+
+class CongestionDetection {
+ public:
+ CongestionDetection();
+ ~CongestionDetection();
+
+ void addPacket(const core::ContentObject &content_object);
+
+ BandwidthUsage getState() { return cc_estimator_.State(); }
+
+ void updateStats();
+
+ private:
+ TrendlineEstimator cc_estimator_;
+ std::map<uint32_t, FrameStats> chunks_;
+ std::queue<uint32_t> chunks_number_;
+
+ FrameStats last_processed_chunk_;
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/probe_handler.cc b/libtransport/src/protocols/rtc/probe_handler.cc
new file mode 100644
index 000000000..efba362d4
--- /dev/null
+++ b/libtransport/src/protocols/rtc/probe_handler.cc
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <protocols/rtc/probe_handler.h>
+#include <protocols/rtc/rtc_consts.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+ProbeHandler::ProbeHandler(SendProbeCallback &&send_callback,
+ asio::io_service &io_service)
+ : probe_interval_(0),
+ max_probes_(0),
+ sent_probes_(0),
+ probe_timer_(std::make_unique<asio::steady_timer>(io_service)),
+ rand_eng_((std::random_device())()),
+ distr_(MIN_RTT_PROBE_SEQ, MAX_RTT_PROBE_SEQ),
+ send_probe_callback_(std::move(send_callback)) {}
+
+ProbeHandler::~ProbeHandler() {}
+
+uint64_t ProbeHandler::getRtt(uint32_t seq) {
+ auto it = pending_probes_.find(seq);
+
+ if (it == pending_probes_.end()) return 0;
+
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+ uint64_t rtt = now - it->second;
+ if(rtt < 1) rtt = 1;
+
+ pending_probes_.erase(it);
+
+ return rtt;
+}
+
+void ProbeHandler::setProbes(uint32_t probe_interval, uint32_t max_probes) {
+ stopProbes();
+ probe_interval_ = probe_interval;
+ max_probes_ = max_probes;
+}
+
+void ProbeHandler::stopProbes() {
+ probe_interval_ = 0;
+ max_probes_ = 0;
+ sent_probes_ = 0;
+ probe_timer_->cancel();
+}
+
+void ProbeHandler::sendProbes() {
+ if (probe_interval_ == 0) return;
+ if (max_probes_ != 0 && sent_probes_ >= max_probes_) return;
+
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+
+ uint32_t seq = distr_(rand_eng_);
+ pending_probes_.insert(std::pair<uint32_t, uint64_t>(seq, now));
+ send_probe_callback_(seq);
+ sent_probes_++;
+
+ // clean up
+ // a probe may get lost. if the pending_probes_ size becomes bigger than
+ // MAX_PENDING_PROBES remove all the probes older than a seconds
+ if (pending_probes_.size() > MAX_PENDING_PROBES) {
+ for (auto it = pending_probes_.begin(); it != pending_probes_.end();) {
+ if ((now - it->second) > 1000)
+ it = pending_probes_.erase(it);
+ else
+ it++;
+ }
+ }
+
+ if (probe_interval_ == 0) return;
+
+ std::weak_ptr<ProbeHandler> self(shared_from_this());
+ probe_timer_->expires_from_now(std::chrono::microseconds(probe_interval_));
+ probe_timer_->async_wait([self](std::error_code ec) {
+ if (ec) return;
+ if (auto s = self.lock()) {
+ s->sendProbes();
+ }
+ });
+}
+
+} // namespace rtc
+
+} // namespace protocol
+
+} // namespace transport
diff --git a/libtransport/src/protocols/rtc/probe_handler.h b/libtransport/src/protocols/rtc/probe_handler.h
new file mode 100644
index 000000000..b8ed84445
--- /dev/null
+++ b/libtransport/src/protocols/rtc/probe_handler.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+#include <hicn/transport/config.h>
+
+#include <asio.hpp>
+#include <asio/steady_timer.hpp>
+#include <functional>
+#include <random>
+#include <unordered_map>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class ProbeHandler : public std::enable_shared_from_this<ProbeHandler> {
+ public:
+ using SendProbeCallback = std::function<void(uint32_t)>;
+
+ public:
+ ProbeHandler(SendProbeCallback &&send_callback,
+ asio::io_service &io_service);
+
+ ~ProbeHandler();
+
+ // if the function returns 0 the probe is not valaid
+ uint64_t getRtt(uint32_t seq);
+
+ // reset the probes parameters. it stop the current probing.
+ // to restar call sendProbes.
+ // probe_interval = 0 means that no event will be scheduled
+ // max_probe = 0 means no limit to the number of probe to send
+ void setProbes(uint32_t probe_interval, uint32_t max_probes);
+
+ // stop to schedule probes
+ void stopProbes();
+
+ void sendProbes();
+
+ private:
+ uint32_t probe_interval_; // us
+ uint32_t max_probes_; // packets
+ uint32_t sent_probes_; // packets
+
+ std::unique_ptr<asio::steady_timer> probe_timer_;
+
+ // map from seqnumber to timestamp
+ std::unordered_map<uint32_t, uint64_t> pending_probes_;
+
+ // random generator
+ std::default_random_engine rand_eng_;
+ std::uniform_int_distribution<uint32_t> distr_;
+
+ SendProbeCallback send_probe_callback_;
+};
+
+} // namespace rtc
+
+} // namespace protocol
+
+} // namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc.cc b/libtransport/src/protocols/rtc/rtc.cc
new file mode 100644
index 000000000..46659ac74
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc.cc
@@ -0,0 +1,607 @@
+/*
+ * 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 <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/interfaces/socket_consumer.h>
+#include <implementation/socket_consumer.h>
+#include <math.h>
+#include <protocols/rtc/rtc.h>
+#include <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_rc_queue.h>
+
+#include <algorithm>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+using namespace interface;
+
+RTCTransportProtocol::RTCTransportProtocol(
+ implementation::ConsumerSocket *icn_socket)
+ : TransportProtocol(icn_socket, nullptr),
+ DatagramReassembly(icn_socket, this),
+ number_(0) {
+ icn_socket->getSocketOption(PORTAL, portal_);
+ round_timer_ = std::make_unique<asio::steady_timer>(portal_->getIoService());
+ scheduler_timer_ =
+ std::make_unique<asio::steady_timer>(portal_->getIoService());
+}
+
+RTCTransportProtocol::~RTCTransportProtocol() {}
+
+void RTCTransportProtocol::resume() {
+ if (is_running_) return;
+
+ is_running_ = true;
+
+ newRound();
+
+ portal_->runEventsLoop();
+ is_running_ = false;
+}
+
+// private
+void RTCTransportProtocol::initParams() {
+ portal_->setConsumerCallback(this);
+
+ rc_ = std::make_shared<RTCRateControlQueue>();
+ ldr_ = std::make_shared<RTCLossDetectionAndRecovery>(
+ std::bind(&RTCTransportProtocol::sendRtxInterest, this,
+ std::placeholders::_1),
+ portal_->getIoService());
+
+ state_ = std::make_shared<RTCState>(
+ std::bind(&RTCTransportProtocol::sendProbeInterest, this,
+ std::placeholders::_1),
+ std::bind(&RTCTransportProtocol::discoveredRtt, this),
+ portal_->getIoService());
+
+ rc_->setState(state_);
+ // TODO: for the moment we keep the congestion control disabled
+ // rc_->tunrOnRateControl();
+ ldr_->setState(state_);
+
+ // protocol state
+ start_send_interest_ = false;
+ current_state_ = SyncState::catch_up;
+
+ // Cancel timer
+ number_++;
+ round_timer_->cancel();
+ scheduler_timer_->cancel();
+ scheduler_timer_on_ = false;
+
+ // delete all timeouts and future nacks
+ timeouts_or_nacks_.clear();
+
+ // cwin vars
+ current_sync_win_ = INITIAL_WIN;
+ max_sync_win_ = INITIAL_WIN_MAX;
+
+ // names/packets var
+ next_segment_ = 0;
+
+ socket_->setSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
+ RTC_INTEREST_LIFETIME);
+}
+
+// private
+void RTCTransportProtocol::reset() {
+ TRANSPORT_LOGD("reset called");
+ initParams();
+ newRound();
+}
+
+void RTCTransportProtocol::inactiveProducer() {
+ // when the producer is inactive we reset the consumer state
+ // cwin vars
+ current_sync_win_ = INITIAL_WIN;
+ max_sync_win_ = INITIAL_WIN_MAX;
+
+ TRANSPORT_LOGD("Current window: %u, max_sync_win_: %u", current_sync_win_,
+ max_sync_win_);
+
+ // names/packets var
+ next_segment_ = 0;
+
+ ldr_->clear();
+}
+
+void RTCTransportProtocol::newRound() {
+ round_timer_->expires_from_now(std::chrono::milliseconds(ROUND_LEN));
+ // TODO pass weak_ptr here
+ round_timer_->async_wait([this, n{number_}](std::error_code ec) {
+ if (ec) return;
+
+ if (n != number_) {
+ return;
+ }
+
+ // saving counters that will be reset on new round
+ uint32_t sent_retx = state_->getSentRtxInRound();
+ uint32_t received_bytes = state_->getReceivedBytesInRound();
+ uint32_t sent_interest = state_->getSentInterestInRound();
+ uint32_t lost_data = state_->getLostData();
+ uint32_t recovered_losses = state_->getRecoveredLosses();
+ uint32_t received_nacks = state_->getReceivedNacksInRound();
+
+ bool in_sync = (current_state_ == SyncState::in_sync);
+ state_->onNewRound((double)ROUND_LEN, in_sync);
+ rc_->onNewRound((double)ROUND_LEN);
+
+ // update sync state if needed
+ if (current_state_ == SyncState::in_sync) {
+ double cache_rate = state_->getPacketFromCacheRatio();
+ if (cache_rate > MAX_DATA_FROM_CACHE) {
+ current_state_ = SyncState::catch_up;
+ }
+ } else {
+ double target_rate = state_->getProducerRate() * PRODUCTION_RATE_FRACTION;
+ double received_rate = state_->getReceivedRate();
+ uint32_t round_without_nacks = state_->getRoundsWithoutNacks();
+ double cache_ratio = state_->getPacketFromCacheRatio();
+ if (round_without_nacks >= ROUNDS_IN_SYNC_BEFORE_SWITCH &&
+ received_rate >= target_rate && cache_ratio < MAX_DATA_FROM_CACHE) {
+ current_state_ = SyncState::in_sync;
+ }
+ }
+
+ TRANSPORT_LOGD("Calling updateSyncWindow in newRound function");
+ updateSyncWindow();
+
+ sendStatsToApp(sent_retx, received_bytes, sent_interest, lost_data,
+ recovered_losses, received_nacks);
+ newRound();
+ });
+}
+
+void RTCTransportProtocol::discoveredRtt() {
+ start_send_interest_ = true;
+ ldr_->turnOnRTX();
+ updateSyncWindow();
+}
+
+void RTCTransportProtocol::computeMaxSyncWindow() {
+ double production_rate = state_->getProducerRate();
+ double packet_size = state_->getAveragePacketSize();
+ if (production_rate == 0.0 || packet_size == 0.0) {
+ // the consumer has no info about the producer,
+ // keep the previous maxCWin
+ TRANSPORT_LOGD(
+ "Returning in computeMaxSyncWindow because: prod_rate: %d || "
+ "packet_size: %d",
+ (int)(production_rate == 0.0), (int)(packet_size == 0.0));
+ return;
+ }
+
+ uint32_t lifetime = default_values::interest_lifetime;
+ socket_->getSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
+ lifetime);
+ double lifetime_ms = (double)lifetime / MILLI_IN_A_SEC;
+
+
+ max_sync_win_ =
+ (uint32_t)ceil((production_rate * lifetime_ms *
+ INTEREST_LIFETIME_REDUCTION_FACTOR) / packet_size);
+
+ max_sync_win_ = std::min(max_sync_win_, rc_->getCongesionWindow());
+}
+
+void RTCTransportProtocol::updateSyncWindow() {
+ computeMaxSyncWindow();
+
+ if (max_sync_win_ == INITIAL_WIN_MAX) {
+ if (TRANSPORT_EXPECT_FALSE(!state_->isProducerActive())) return;
+
+ current_sync_win_ = INITIAL_WIN;
+ scheduleNextInterests();
+ return;
+ }
+
+ double prod_rate = state_->getProducerRate();
+ double rtt = (double)state_->getRTT() / MILLI_IN_A_SEC;
+ double packet_size = state_->getAveragePacketSize();
+
+ // if some of the info are not available do not update the current win
+ if (prod_rate != 0.0 && rtt != 0.0 && packet_size != 0.0) {
+ current_sync_win_ = (uint32_t)ceil(prod_rate * rtt / packet_size);
+ current_sync_win_ += (uint32_t)
+ ceil(prod_rate * (PRODUCER_BUFFER_MS / MILLI_IN_A_SEC) / packet_size);
+
+ if(current_state_ == SyncState::catch_up) {
+ current_sync_win_ = (uint32_t) (current_sync_win_ * CATCH_UP_WIN_INCREMENT);
+ }
+
+ current_sync_win_ = std::min(current_sync_win_, max_sync_win_);
+ current_sync_win_ = std::max(current_sync_win_, WIN_MIN);
+ }
+
+ scheduleNextInterests();
+}
+
+void RTCTransportProtocol::decreaseSyncWindow() {
+ // called on future nack
+ // we have a new sample of the production rate, so update max win first
+ computeMaxSyncWindow();
+ current_sync_win_--;
+ current_sync_win_ = std::max(current_sync_win_, WIN_MIN);
+ scheduleNextInterests();
+}
+
+void RTCTransportProtocol::sendInterest(Name *interest_name) {
+ TRANSPORT_LOGD("Sending interest for name %s",
+ interest_name->toString().c_str());
+
+ auto interest = core::PacketManager<>::getInstance().getPacket<Interest>();
+ interest->setName(*interest_name);
+
+ uint32_t lifetime = default_values::interest_lifetime;
+ socket_->getSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
+ lifetime);
+ interest->setLifetime(uint32_t(lifetime));
+
+ if (*on_interest_output_) {
+ (*on_interest_output_)(*socket_->getInterface(), *interest);
+ }
+
+ if (TRANSPORT_EXPECT_FALSE(!is_running_ && !is_first_)) {
+ return;
+ }
+
+ portal_->sendInterest(std::move(interest));
+}
+
+void RTCTransportProtocol::sendRtxInterest(uint32_t seq) {
+ if (!is_running_ && !is_first_) return;
+
+ if(!start_send_interest_) return;
+
+ Name *interest_name = nullptr;
+ socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
+ &interest_name);
+
+ TRANSPORT_LOGD("send rtx %u", seq);
+ interest_name->setSuffix(seq);
+ sendInterest(interest_name);
+}
+
+void RTCTransportProtocol::sendProbeInterest(uint32_t seq) {
+ if (!is_running_ && !is_first_) return;
+
+ Name *interest_name = nullptr;
+ socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
+ &interest_name);
+
+ TRANSPORT_LOGD("send probe %u", seq);
+ interest_name->setSuffix(seq);
+ sendInterest(interest_name);
+}
+
+void RTCTransportProtocol::scheduleNextInterests() {
+ TRANSPORT_LOGD("Schedule next interests");
+
+ if (!is_running_ && !is_first_) return;
+
+ if(!start_send_interest_) return; // RTT discovering phase is not finished so
+ // do not start to send interests
+
+ if (scheduler_timer_on_) return; // wait befor send other interests
+
+ if (TRANSPORT_EXPECT_FALSE(!state_->isProducerActive())) {
+ TRANSPORT_LOGD("Inactive producer.");
+ // here we keep seding the same interest until the producer
+ // does not start again
+ if (next_segment_ != 0) {
+ // the producer just become inactive, reset the state
+ inactiveProducer();
+ }
+
+ Name *interest_name = nullptr;
+ socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
+ &interest_name);
+
+ TRANSPORT_LOGD("send interest %u", next_segment_);
+ interest_name->setSuffix(next_segment_);
+
+ if (portal_->interestIsPending(*interest_name)) {
+ // if interest 0 is already pending we return
+ return;
+ }
+
+ sendInterest(interest_name);
+ state_->onSendNewInterest(interest_name);
+ return;
+ }
+
+ TRANSPORT_LOGD("Pending interest number: %d -- current_sync_win_: %d",
+ state_->getPendingInterestNumber(), current_sync_win_);
+
+ // skip nacked pacekts
+ if (next_segment_ <= state_->getLastSeqNacked()) {
+ next_segment_ = state_->getLastSeqNacked() + 1;
+ }
+
+ // skipe received packets
+ if (next_segment_ <= state_->getHighestSeqReceivedInOrder()) {
+ next_segment_ = state_->getHighestSeqReceivedInOrder() + 1;
+ }
+
+ uint32_t sent_interests = 0;
+ while ((state_->getPendingInterestNumber() < current_sync_win_) &&
+ (sent_interests < MAX_INTERESTS_IN_BATCH)) {
+ TRANSPORT_LOGD("In while loop. Window size: %u", current_sync_win_);
+ Name *interest_name = nullptr;
+ socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
+ &interest_name);
+
+ interest_name->setSuffix(next_segment_);
+
+ // send the packet only if:
+ // 1) it is not pending yet (not true for rtx)
+ // 2) the packet is not received or lost
+ // 3) is not in the rtx list
+ if (portal_->interestIsPending(*interest_name) ||
+ state_->isReceivedOrLost(next_segment_) != PacketState::UNKNOWN ||
+ ldr_->isRtx(next_segment_)) {
+ TRANSPORT_LOGD(
+ "skip interest %u because: pending %u, recv %u, rtx %u",
+ next_segment_, (portal_->interestIsPending(*interest_name)),
+ (state_->isReceivedOrLost(next_segment_) != PacketState::UNKNOWN),
+ (ldr_->isRtx(next_segment_)));
+ next_segment_ = (next_segment_ + 1) % MIN_PROBE_SEQ;
+ continue;
+ }
+
+
+ sent_interests++;
+ TRANSPORT_LOGD("send interest %u", next_segment_);
+ sendInterest(interest_name);
+ state_->onSendNewInterest(interest_name);
+
+ next_segment_ = (next_segment_ + 1) % MIN_PROBE_SEQ;
+ }
+
+ if (state_->getPendingInterestNumber() < current_sync_win_) {
+ // we still have space in the window but we already sent a batch of
+ // MAX_INTERESTS_IN_BATCH interest. for the following ones wait one
+ // WAIT_BETWEEN_INTEREST_BATCHES to avoid local packets drop
+
+ scheduler_timer_on_ = true;
+ scheduler_timer_->expires_from_now(
+ std::chrono::microseconds(WAIT_BETWEEN_INTEREST_BATCHES));
+ scheduler_timer_->async_wait([this](std::error_code ec) {
+ if (ec) return;
+ if (!scheduler_timer_on_) return;
+
+ scheduler_timer_on_ = false;
+ scheduleNextInterests();
+ });
+ }
+}
+
+void RTCTransportProtocol::onTimeout(Interest::Ptr &&interest) {
+ uint32_t segment_number = interest->getName().getSuffix();
+
+ TRANSPORT_LOGD("timeout for packet %u", segment_number);
+
+ if (segment_number >= MIN_PROBE_SEQ) {
+ // this is a timeout on a probe, do nothing
+ return;
+ }
+
+ timeouts_or_nacks_.insert(segment_number);
+
+ if (TRANSPORT_EXPECT_TRUE(state_->isProducerActive()) &&
+ segment_number <= state_->getHighestSeqReceivedInOrder()) {
+ // we retransmit packets only if the producer is active, otherwise we
+ // use timeouts to avoid to send too much traffic
+ //
+ // a timeout is sent using RTX only if it is an old packet. if it is for a
+ // seq number that we didn't reach yet, we send the packet using the normal
+ // schedule next interest
+ TRANSPORT_LOGD("handle timeout for packet %u using rtx", segment_number);
+ ldr_->onTimeout(segment_number);
+ state_->onTimeout(segment_number);
+ scheduleNextInterests();
+ return;
+ }
+
+ TRANSPORT_LOGD("handle timeout for packet %u using normal interests",
+ segment_number);
+
+ if (segment_number < next_segment_) {
+ // this is a timeout for a packet that will be generated in the future but
+ // we are asking for higher sequence numbers. we need to go back like in the
+ // case of future nacks
+ TRANSPORT_LOGD("on timeout next seg = %u, jump to %u",
+ next_segment_, segment_number);
+ next_segment_ = segment_number;
+ }
+
+ state_->onTimeout(segment_number);
+ scheduleNextInterests();
+}
+
+void RTCTransportProtocol::onNack(const ContentObject &content_object) {
+ struct nack_packet_t *nack =
+ (struct nack_packet_t *)content_object.getPayload()->data();
+ uint32_t production_seg = nack->getProductionSegement();
+ uint32_t nack_segment = content_object.getName().getSuffix();
+ bool is_rtx = ldr_->isRtx(nack_segment);
+
+ // check if the packet got a timeout
+
+ TRANSPORT_LOGD("Nack received %u. Production segment: %u", nack_segment,
+ production_seg);
+
+ bool compute_stats = true;
+ auto tn_it = timeouts_or_nacks_.find(nack_segment);
+ if (tn_it != timeouts_or_nacks_.end() || is_rtx) {
+ compute_stats = false;
+ // remove packets from timeouts_or_nacks only in case of a past nack
+ }
+
+ state_->onNackPacketReceived(content_object, compute_stats);
+ ldr_->onNackPacketReceived(content_object);
+
+ // both in case of past and future nack we set next_segment_ equal to the
+ // production segment in the nack. In case of past nack we will skip unneded
+ // interest (this is already done in the scheduleNextInterest in any case)
+ // while in case of future nacks we can go back in time and ask again for the
+ // content that generated the nack
+ TRANSPORT_LOGD("on nack next seg = %u, jump to %u",
+ next_segment_, production_seg);
+ next_segment_ = production_seg;
+
+ if (production_seg > nack_segment) {
+ // remove the nack is it exists
+ if (tn_it != timeouts_or_nacks_.end()) timeouts_or_nacks_.erase(tn_it);
+
+ // the client is asking for content in the past
+ // switch to catch up state and increase the window
+ // this is true only if the packet is not an RTX
+ if (!is_rtx) current_state_ = SyncState::catch_up;
+
+ updateSyncWindow();
+ } else {
+ // if production_seg == nack_segment we consider this a future nack, since
+ // production_seg is not yet created. this may happen in case of low
+ // production rate (e.g. ping at 1pps)
+
+ // if a future nack was also retransmitted add it to the timeout_or_nacks
+ // set
+ if (is_rtx) timeouts_or_nacks_.insert(nack_segment);
+
+ // the client is asking for content in the future
+ // switch to in sync state and decrease the window
+ current_state_ = SyncState::in_sync;
+ decreaseSyncWindow();
+ }
+}
+
+void RTCTransportProtocol::onProbe(const ContentObject &content_object) {
+ bool valid = state_->onProbePacketReceived(content_object);
+ if(!valid) return;
+
+ struct nack_packet_t *probe =
+ (struct nack_packet_t *)content_object.getPayload()->data();
+ uint32_t production_seg = probe->getProductionSegement();
+
+ // as for the nacks set next_segment_
+ TRANSPORT_LOGD("on probe next seg = %u, jump to %u",
+ next_segment_, production_seg);
+ next_segment_ = production_seg;
+
+ ldr_->onProbePacketReceived(content_object);
+ updateSyncWindow();
+}
+
+void RTCTransportProtocol::onContentObject(Interest &interest,
+ ContentObject &content_object) {
+ TRANSPORT_LOGD("Received content object of size: %zu",
+ content_object.payloadSize());
+ uint32_t payload_size = (uint32_t) content_object.payloadSize();
+ uint32_t segment_number = content_object.getName().getSuffix();
+
+ if (segment_number >= MIN_PROBE_SEQ) {
+ TRANSPORT_LOGD("Received probe %u", segment_number);
+ if (*on_content_object_input_) {
+ (*on_content_object_input_)(*socket_->getInterface(), content_object);
+ }
+ onProbe(content_object);
+ return;
+ }
+
+ if (payload_size == NACK_HEADER_SIZE) {
+ TRANSPORT_LOGD("Received nack %u", segment_number);
+ if (*on_content_object_input_) {
+ (*on_content_object_input_)(*socket_->getInterface(), content_object);
+ }
+ onNack(content_object);
+ return;
+ }
+
+ TRANSPORT_LOGD("Received content %u", segment_number);
+
+ rc_->onDataPacketReceived(content_object);
+ bool compute_stats = true;
+ auto tn_it = timeouts_or_nacks_.find(segment_number);
+ if (tn_it != timeouts_or_nacks_.end()) {
+ compute_stats = false;
+ timeouts_or_nacks_.erase(tn_it);
+ }
+ if (ldr_->isRtx(segment_number)) {
+ compute_stats = false;
+ }
+
+ // check if the packet was already received
+ PacketState state = state_->isReceivedOrLost(segment_number);
+ state_->onDataPacketReceived(content_object, compute_stats);
+ ldr_->onDataPacketReceived(content_object);
+
+ // if the stat for this seq number is received do not send the packet to app
+ if (state != PacketState::RECEIVED) {
+ if (*on_content_object_input_) {
+ (*on_content_object_input_)(*socket_->getInterface(), content_object);
+ }
+ reassemble(content_object);
+ } else {
+ TRANSPORT_LOGD("Received duplicated content %u, drop it", segment_number);
+ }
+
+ updateSyncWindow();
+}
+
+void RTCTransportProtocol::sendStatsToApp(
+ uint32_t retx_count, uint32_t received_bytes, uint32_t sent_interests,
+ uint32_t lost_data, uint32_t recovered_losses, uint32_t received_nacks) {
+ if (*stats_summary_) {
+ // Send the stats to the app
+ stats_->updateQueuingDelay(state_->getQueuing());
+
+ // stats_->updateInterestFecTx(0); //todo must be implemented
+ // stats_->updateBytesFecRecv(0); //todo must be implemented
+
+ stats_->updateRetxCount(retx_count);
+ stats_->updateBytesRecv(received_bytes);
+ stats_->updateInterestTx(sent_interests);
+ stats_->updateReceivedNacks(received_nacks);
+
+ stats_->updateAverageWindowSize(current_sync_win_);
+ stats_->updateLossRatio(state_->getLossRate());
+ stats_->updateAverageRtt(state_->getRTT());
+ stats_->updateLostData(lost_data);
+ stats_->updateRecoveredData(recovered_losses);
+ stats_->updateCCState((unsigned int)current_state_ ? 1 : 0);
+ (*stats_summary_)(*socket_->getInterface(), *stats_);
+ }
+}
+
+void RTCTransportProtocol::reassemble(ContentObject &content_object) {
+ auto read_buffer = content_object.getPayload();
+ TRANSPORT_LOGD("Size of payload: %zu", read_buffer->length());
+ read_buffer->trimStart(DATA_HEADER_SIZE);
+ Reassembly::read_buffer_ = std::move(read_buffer);
+ Reassembly::notifyApplication();
+}
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc.h b/libtransport/src/protocols/rtc/rtc.h
new file mode 100644
index 000000000..596887067
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <protocols/datagram_reassembly.h>
+#include <protocols/rtc/rtc_ldr.h>
+#include <protocols/rtc/rtc_rc.h>
+#include <protocols/rtc/rtc_state.h>
+#include <protocols/transport_protocol.h>
+
+#include <unordered_set>
+#include <vector>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RTCTransportProtocol : public TransportProtocol,
+ public DatagramReassembly {
+ public:
+ RTCTransportProtocol(implementation::ConsumerSocket *icnet_socket);
+
+ ~RTCTransportProtocol();
+
+ using TransportProtocol::start;
+
+ using TransportProtocol::stop;
+
+ void resume() override;
+
+ private:
+ enum class SyncState { catch_up = 0, in_sync = 1, last };
+
+ private:
+ // setup functions
+ void initParams();
+ void reset() override;
+
+ void inactiveProducer();
+
+ // protocol functions
+ void discoveredRtt();
+ void newRound();
+
+ // window functions
+ void computeMaxSyncWindow();
+ void updateSyncWindow();
+ void decreaseSyncWindow();
+
+ // packet functions
+ void sendInterest(Name *interest_name);
+ void sendRtxInterest(uint32_t seq);
+ void sendProbeInterest(uint32_t seq);
+ void scheduleNextInterests() override;
+ void onTimeout(Interest::Ptr &&interest) override;
+ void onNack(const ContentObject &content_object);
+ void onProbe(const ContentObject &content_object);
+ void reassemble(ContentObject &content_object) override;
+ void onContentObject(Interest &interest,
+ ContentObject &content_object) override;
+ void onPacketDropped(Interest &interest,
+ ContentObject &content_object) override {}
+ void onReassemblyFailed(std::uint32_t missing_segment) override {}
+
+ // interaction with app functions
+ void sendStatsToApp(uint32_t retx_count, uint32_t received_bytes,
+ uint32_t sent_interests, uint32_t lost_data,
+ uint32_t recovered_losses, uint32_t received_nacks);
+ // protocol state
+ bool start_send_interest_;
+ SyncState current_state_;
+ // cwin vars
+ uint32_t current_sync_win_;
+ uint32_t max_sync_win_;
+
+ // controller var
+ std::unique_ptr<asio::steady_timer> round_timer_;
+ std::unique_ptr<asio::steady_timer> scheduler_timer_;
+ bool scheduler_timer_on_;
+
+ // timeouts
+ std::unordered_set<uint32_t> timeouts_or_nacks_;
+
+ // names/packets var
+ uint32_t next_segment_;
+
+ std::shared_ptr<RTCState> state_;
+ std::shared_ptr<RTCRateControl> rc_;
+ std::shared_ptr<RTCLossDetectionAndRecovery> ldr_;
+
+ uint32_t number_;
+};
+
+} // namespace rtc
+
+} // namespace protocol
+
+} // namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_consts.h b/libtransport/src/protocols/rtc/rtc_consts.h
new file mode 100644
index 000000000..e172fc7a1
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_consts.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <protocols/rtc/rtc_packet.h>
+#include <stdint.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+// used in rtc
+// protocol consts
+const uint32_t ROUND_LEN = 200;
+// ms interval of time on which
+// we take decisions / measurements
+const double INTEREST_LIFETIME_REDUCTION_FACTOR = 0.8;
+// how big (in ms) should be the buffer at the producer.
+// increasing this number we increase the time that an
+// interest will wait for the data packet to be produced
+// at the producer socket
+const uint32_t PRODUCER_BUFFER_MS = 200; // ms
+
+// interest scheduler
+const uint32_t MAX_INTERESTS_IN_BATCH = 5;
+const uint32_t WAIT_BETWEEN_INTEREST_BATCHES = 1000; // usec
+
+// packet const
+const uint32_t HICN_HEADER_SIZE = 40 + 20; // IPv6 + TCP bytes
+const uint32_t RTC_INTEREST_LIFETIME = 1000;
+
+// probes sequence range
+const uint32_t MIN_PROBE_SEQ = 0xefffffff;
+const uint32_t MIN_RTT_PROBE_SEQ = MIN_PROBE_SEQ;
+const uint32_t MAX_RTT_PROBE_SEQ = 0xffffffff - 1;
+// RTT_PROBE_INTERVAL will be used during the section while
+// INIT_RTT_PROBE_INTERVAL is used at the beginning to
+// quickily estimate the RTT
+const uint32_t RTT_PROBE_INTERVAL = 200000; // us
+const uint32_t INIT_RTT_PROBE_INTERVAL = 500; // us
+const uint32_t INIT_RTT_PROBES = 40; // number of probes to init RTT
+// if the produdcer is not yet started we need to probe multple times
+// to get an answer. we wait 100ms between each try
+const uint32_t INIT_RTT_PROBE_RESTART = 100; // ms
+// once we get the first probe we wait at most 60ms for the others
+const uint32_t INIT_RTT_PROBE_WAIT = 30; // ms
+// we reuires at least 5 probes to be recevied
+const uint32_t INIT_RTT_MIN_PROBES_TO_RECV = 5; //ms
+const uint32_t MAX_PENDING_PROBES = 10;
+
+
+// congestion
+const double MAX_QUEUING_DELAY = 100.0; // ms
+
+// data from cache
+const double MAX_DATA_FROM_CACHE = 0.25; // 25%
+
+// window const
+const uint32_t INITIAL_WIN = 5; // pkts
+const uint32_t INITIAL_WIN_MAX = 1000000; // pkts
+const uint32_t WIN_MIN = 5; // pkts
+const double CATCH_UP_WIN_INCREMENT = 1.2;
+// used in rate control
+const double WIN_DECREASE_FACTOR = 0.5;
+const double WIN_INCREASE_FACTOR = 1.5;
+
+// round in congestion
+const double ROUNDS_BEFORE_TAKE_ACTION = 5;
+
+// used in state
+const uint8_t ROUNDS_IN_SYNC_BEFORE_SWITCH = 3;
+const double PRODUCTION_RATE_FRACTION = 0.8;
+
+const uint32_t INIT_PACKET_SIZE = 1200;
+
+const double MOVING_AVG_ALPHA = 0.8;
+
+const double MILLI_IN_A_SEC = 1000.0;
+const double MICRO_IN_A_SEC = 1000000.0;
+
+const double MAX_CACHED_PACKETS = 262144; // 2^18
+ // about 50 sec of traffic at 50Mbps
+ // with 1200 bytes packets
+
+const uint32_t MAX_ROUND_WHIOUT_PACKETS = (const uint32_t)
+ (20 * MILLI_IN_A_SEC) / ROUND_LEN; // 20 sec in rounds;
+
+// used in ldr
+const uint32_t RTC_MAX_RTX = 100;
+const uint32_t RTC_MAX_AGE = 60000; // in ms
+const uint64_t MAX_TIMER_RTX = ~0;
+const uint32_t SENTINEL_TIMER_INTERVAL = 100; // ms
+const uint32_t MAX_RTX_WITH_SENTINEL = 10; // packets
+const double CATCH_UP_RTT_INCREMENT = 1.2;
+
+// used by producer
+const uint32_t PRODUCER_STATS_INTERVAL = 200; // ms
+const uint32_t MIN_PRODUCTION_RATE = 10; // pps
+ // min prod rate
+ // set running several test
+
+} // namespace rtc
+
+} // namespace protocol
+
+} // namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_data_path.cc b/libtransport/src/protocols/rtc/rtc_data_path.cc
new file mode 100644
index 000000000..a545225cb
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_data_path.cc
@@ -0,0 +1,197 @@
+/*
+ * 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 <protocols/rtc/rtc_data_path.h>
+#include <stdlib.h>
+
+#include <algorithm>
+#include <cfloat>
+#include <chrono>
+
+#define MAX_ROUNDS_WITHOUT_PKTS 10 // 2sec
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RTCDataPath::RTCDataPath(uint32_t path_id)
+ : path_id_(path_id),
+ min_rtt(UINT_MAX),
+ prev_min_rtt(UINT_MAX),
+ min_owd(INT_MAX), // this is computed like in LEDBAT, so it is not the
+ // real OWD, but the measured one, that depends on the
+ // clock of sender and receiver. the only meaningful
+ // value is is the queueing delay. for this reason we
+ // keep both RTT (for the windowd calculation) and OWD
+ // (for congestion/quality control)
+ prev_min_owd(INT_MAX),
+ avg_owd(DBL_MAX),
+ queuing_delay(DBL_MAX),
+ jitter_(0.0),
+ last_owd_(0),
+ largest_recv_seq_(0),
+ largest_recv_seq_time_(0),
+ avg_inter_arrival_(DBL_MAX),
+ received_nacks_(false),
+ received_packets_(false),
+ rounds_without_packets_(0),
+ last_received_data_packet_(0),
+ RTT_history_(HISTORY_LEN),
+ OWD_history_(HISTORY_LEN){};
+
+void RTCDataPath::insertRttSample(uint64_t rtt) {
+ // for the rtt we only keep track of the min one
+ if (rtt < min_rtt) min_rtt = rtt;
+ last_received_data_packet_ =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+}
+
+void RTCDataPath::insertOwdSample(int64_t owd) {
+ // for owd we use both min and avg
+ if (owd < min_owd) min_owd = owd;
+
+ if (avg_owd != DBL_MAX)
+ avg_owd = (avg_owd * (1 - ALPHA_RTC)) + (owd * ALPHA_RTC);
+ else {
+ avg_owd = (double)owd;
+ }
+
+ int64_t queueVal = owd - std::min(getMinOwd(), min_owd);
+
+ if (queuing_delay != DBL_MAX)
+ queuing_delay = (queuing_delay * (1 - ALPHA_RTC)) + (queueVal * ALPHA_RTC);
+ else {
+ queuing_delay = (double)queueVal;
+ }
+
+ // keep track of the jitter computed as for RTP (RFC 3550)
+ int64_t diff = std::abs(owd - last_owd_);
+ last_owd_ = owd;
+ jitter_ += (1.0 / 16.0) * ((double)diff - jitter_);
+
+ // owd is computed only for valid data packets so we count only
+ // this for decide if we recevie traffic or not
+ received_packets_ = true;
+}
+
+void RTCDataPath::computeInterArrivalGap(uint32_t segment_number) {
+ // got packet in sequence, compute gap
+ if (largest_recv_seq_ == (segment_number - 1)) {
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+ uint64_t delta = now - largest_recv_seq_time_;
+ largest_recv_seq_ = segment_number;
+ largest_recv_seq_time_ = now;
+ if (avg_inter_arrival_ == DBL_MAX)
+ avg_inter_arrival_ = (double)delta;
+ else
+ avg_inter_arrival_ =
+ (avg_inter_arrival_ * (1 - ALPHA_RTC)) + (delta * ALPHA_RTC);
+ return;
+ }
+
+ // ooo packet, update the stasts if needed
+ if (largest_recv_seq_ <= segment_number) {
+ largest_recv_seq_ = segment_number;
+ largest_recv_seq_time_ =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+ }
+}
+
+void RTCDataPath::receivedNack() { received_nacks_ = true; }
+
+double RTCDataPath::getInterArrivalGap() {
+ if (avg_inter_arrival_ == DBL_MAX) return 0;
+ return avg_inter_arrival_;
+}
+
+bool RTCDataPath::isActive() {
+ if (received_nacks_ && rounds_without_packets_ < MAX_ROUNDS_WITHOUT_PKTS)
+ return true;
+ return false;
+}
+
+bool RTCDataPath::pathToProducer() {
+ if (received_nacks_) return true;
+ return false;
+}
+
+void RTCDataPath::roundEnd() {
+ // reset min_rtt and add it to the history
+ if (min_rtt != UINT_MAX) {
+ prev_min_rtt = min_rtt;
+ } else {
+ // this may happen if we do not receive any packet
+ // from this path in the last round. in this case
+ // we use the measure from the previuos round
+ min_rtt = prev_min_rtt;
+ }
+
+ if (min_rtt == 0) min_rtt = 1;
+
+ RTT_history_.pushBack(min_rtt);
+ min_rtt = UINT_MAX;
+
+ // do the same for min owd
+ if (min_owd != INT_MAX) {
+ prev_min_owd = min_owd;
+ } else {
+ min_owd = prev_min_owd;
+ }
+
+ if (min_owd != INT_MAX) {
+ OWD_history_.pushBack(min_owd);
+ min_owd = INT_MAX;
+ }
+
+ if (!received_packets_)
+ rounds_without_packets_++;
+ else
+ rounds_without_packets_ = 0;
+ received_packets_ = false;
+}
+
+uint32_t RTCDataPath::getPathId() { return path_id_; }
+
+double RTCDataPath::getQueuingDealy() { return queuing_delay; }
+
+uint64_t RTCDataPath::getMinRtt() {
+ if (RTT_history_.size() != 0) return RTT_history_.begin();
+ return 0;
+}
+
+int64_t RTCDataPath::getMinOwd() {
+ if (OWD_history_.size() != 0) return OWD_history_.begin();
+ return 0;
+}
+
+double RTCDataPath::getJitter() { return jitter_; }
+
+uint64_t RTCDataPath::getLastPacketTS() { return last_received_data_packet_; }
+
+void RTCDataPath::clearRtt() { RTT_history_.clear(); }
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_data_path.h b/libtransport/src/protocols/rtc/rtc_data_path.h
new file mode 100644
index 000000000..c5c37fc0d
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_data_path.h
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <utils/min_filter.h>
+
+#include <climits>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+const double ALPHA_RTC = 0.125;
+const uint32_t HISTORY_LEN = 20; // 4 sec
+
+class RTCDataPath {
+ public:
+ RTCDataPath(uint32_t path_id);
+
+ public:
+ void insertRttSample(uint64_t rtt);
+ void insertOwdSample(int64_t owd);
+ void computeInterArrivalGap(uint32_t segment_number);
+ void receivedNack();
+
+ uint32_t getPathId();
+ uint64_t getMinRtt();
+ double getQueuingDealy();
+ double getInterArrivalGap();
+ double getJitter();
+ bool isActive();
+ bool pathToProducer();
+ uint64_t getLastPacketTS();
+
+ void clearRtt();
+
+ void roundEnd();
+
+ private:
+ uint32_t path_id_;
+
+ int64_t getMinOwd();
+
+ uint64_t min_rtt;
+ uint64_t prev_min_rtt;
+
+ int64_t min_owd;
+ int64_t prev_min_owd;
+
+ double avg_owd;
+
+ double queuing_delay;
+
+ double jitter_;
+ int64_t last_owd_;
+
+ uint32_t largest_recv_seq_;
+ uint64_t largest_recv_seq_time_;
+ double avg_inter_arrival_;
+
+ // flags to check if a path is active
+ // we considere a path active if it reaches a producer
+ //(not a cache) --aka we got at least one nack on this path--
+ // and if we receives packets
+ bool received_nacks_;
+ bool received_packets_;
+ uint8_t rounds_without_packets_; // if we don't get any packet
+ // for MAX_ROUNDS_WITHOUT_PKTS
+ // we consider the path inactive
+ uint64_t last_received_data_packet_; // timestamp for the last data received
+ // on this path
+
+ utils::MinFilter<uint64_t> RTT_history_;
+ utils::MinFilter<int64_t> OWD_history_;
+};
+
+} // namespace rtc
+
+} // namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_ldr.cc b/libtransport/src/protocols/rtc/rtc_ldr.cc
new file mode 100644
index 000000000..0ef381fe1
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_ldr.cc
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_ldr.h>
+
+#include <algorithm>
+#include <unordered_set>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RTCLossDetectionAndRecovery::RTCLossDetectionAndRecovery(
+ SendRtxCallback &&callback, asio::io_service &io_service)
+ : rtx_on_(false),
+ next_rtx_timer_(MAX_TIMER_RTX),
+ last_event_(0),
+ sentinel_timer_interval_(MAX_TIMER_RTX),
+ send_rtx_callback_(std::move(callback)) {
+ timer_ = std::make_unique<asio::steady_timer>(io_service);
+ sentinel_timer_ = std::make_unique<asio::steady_timer>(io_service);
+}
+
+RTCLossDetectionAndRecovery::~RTCLossDetectionAndRecovery() {}
+
+void RTCLossDetectionAndRecovery::turnOnRTX() {
+ rtx_on_ = true;
+ scheduleSentinelTimer((uint32_t)(state_->getRTT() * CATCH_UP_RTT_INCREMENT));
+}
+
+void RTCLossDetectionAndRecovery::turnOffRTX() {
+ rtx_on_ = false;
+ clear();
+}
+
+void RTCLossDetectionAndRecovery::onTimeout(uint32_t seq) {
+ // always add timeouts to the RTX list to avoid to send the same packet as if
+ // it was not a rtx
+ addToRetransmissions(seq, seq + 1);
+ last_event_ = getNow();
+}
+
+void RTCLossDetectionAndRecovery::onDataPacketReceived(
+ const core::ContentObject &content_object) {
+ last_event_ = getNow();
+
+ uint32_t seq = content_object.getName().getSuffix();
+ if (deleteRtx(seq)) {
+ state_->onPacketRecovered(seq);
+ } else {
+ if (TRANSPORT_EXPECT_FALSE(!rtx_on_)) return; // do not add if RTX is off
+ TRANSPORT_LOGD("received data. add from %u to %u ",
+ state_->getHighestSeqReceivedInOrder() + 1, seq);
+ addToRetransmissions(state_->getHighestSeqReceivedInOrder() + 1, seq);
+ }
+}
+
+void RTCLossDetectionAndRecovery::onNackPacketReceived(
+ const core::ContentObject &nack) {
+ last_event_ = getNow();
+
+ uint32_t seq = nack.getName().getSuffix();
+
+ if (TRANSPORT_EXPECT_FALSE(!rtx_on_)) return; // do not add if RTX is off
+
+ struct nack_packet_t *nack_pkt =
+ (struct nack_packet_t *)nack.getPayload()->data();
+ uint32_t production_seq = nack_pkt->getProductionSegement();
+
+ if (production_seq > seq) {
+ // this is a past nack, all data before productionSeq are lost. if
+ // productionSeq > state_->getHighestSeqReceivedInOrder() is impossible to
+ // recover any packet. If this is not the case we can try to recover the
+ // packets between state_->getHighestSeqReceivedInOrder() and productionSeq.
+ // e.g.: the client receives packets 8 10 11 9 where 9 is a nack with
+ // productionSeq = 14. 9 is lost but we can try to recover packets 12 13 and
+ // 14 that are not arrived yet
+ deleteRtx(seq);
+ TRANSPORT_LOGD("received past nack. add from %u to %u ",
+ state_->getHighestSeqReceivedInOrder() + 1, production_seq);
+ addToRetransmissions(state_->getHighestSeqReceivedInOrder() + 1,
+ production_seq);
+ } else {
+ // future nack. here there should be a gap between the last data received
+ // and this packet and is it possible to recover the packets between the
+ // last received data and the production seq. we should not use the seq
+ // number of the nack since we know that is too early to ask for this seq
+ // number
+ // e.g.: // e.g.: the client receives packets 10 11 12 20 where 20 is a nack
+ // with productionSeq = 18. this says that all the packets between 12 and 18
+ // may got lost and we should ask them
+ deleteRtx(seq);
+ TRANSPORT_LOGD("received futrue nack. add from %u to %u ",
+ state_->getHighestSeqReceivedInOrder() + 1, production_seq);
+ addToRetransmissions(state_->getHighestSeqReceivedInOrder() + 1,
+ production_seq);
+ }
+}
+
+void RTCLossDetectionAndRecovery::onProbePacketReceived(
+ const core::ContentObject &probe) {
+ // we don't log the reception of a probe packet for the sentinel timer because
+ // probes are not taken into account into the sync window. we use them as
+ // future nacks to detect possible packets lost
+ if (TRANSPORT_EXPECT_FALSE(!rtx_on_)) return; // do not add if RTX is off
+ struct nack_packet_t *probe_pkt =
+ (struct nack_packet_t *)probe.getPayload()->data();
+ uint32_t production_seq = probe_pkt->getProductionSegement();
+ TRANSPORT_LOGD("received probe. add from %u to %u ",
+ state_->getHighestSeqReceivedInOrder() + 1, production_seq);
+ addToRetransmissions(state_->getHighestSeqReceivedInOrder() + 1,
+ production_seq);
+}
+
+void RTCLossDetectionAndRecovery::clear() {
+ rtx_state_.clear();
+ rtx_timers_.clear();
+ sentinel_timer_->cancel();
+ if (next_rtx_timer_ != MAX_TIMER_RTX) {
+ next_rtx_timer_ = MAX_TIMER_RTX;
+ timer_->cancel();
+ }
+}
+
+void RTCLossDetectionAndRecovery::addToRetransmissions(uint32_t start,
+ uint32_t stop) {
+ // skip nacked packets
+ if (start <= state_->getLastSeqNacked()) {
+ start = state_->getLastSeqNacked() + 1;
+ }
+
+ // skip received or lost packets
+ if (start <= state_->getHighestSeqReceivedInOrder()) {
+ start = state_->getHighestSeqReceivedInOrder() + 1;
+ }
+
+ for (uint32_t seq = start; seq < stop; seq++) {
+ if (!isRtx(seq) && // is not already an rtx
+ // is not received or lost
+ state_->isReceivedOrLost(seq) == PacketState::UNKNOWN) {
+ // add rtx
+ rtxState state;
+ state.first_send_ = state_->getInterestSentTime(seq);
+ if (state.first_send_ == 0) // this interest was never sent before
+ state.first_send_ = getNow();
+ state.next_send_ = computeNextSend(seq, true);
+ state.rtx_count_ = 0;
+ TRANSPORT_LOGD("add %u to retransmissions. next rtx is %lu ", seq,
+ (state.next_send_ - getNow()));
+ rtx_state_.insert(std::pair<uint32_t, rtxState>(seq, state));
+ rtx_timers_.insert(std::pair<uint64_t, uint32_t>(state.next_send_, seq));
+ }
+ }
+ scheduleNextRtx();
+}
+
+uint64_t RTCLossDetectionAndRecovery::computeNextSend(uint32_t seq,
+ bool new_rtx) {
+ uint64_t now = getNow();
+ if (new_rtx) {
+ // for the new rtx we wait one estimated IAT after the loss detection. this
+ // is bacause, assuming that packets arrive with a constant IAT, we should
+ // get a new packet every IAT
+ double prod_rate = state_->getProducerRate();
+ uint32_t estimated_iat = SENTINEL_TIMER_INTERVAL;
+ uint32_t jitter = 0;
+
+ if (prod_rate != 0) {
+ double packet_size = state_->getAveragePacketSize();
+ estimated_iat = (uint32_t)ceil(1000.0 / (prod_rate / packet_size));
+ jitter = (uint32_t)ceil(state_->getJitter());
+ }
+
+ uint32_t wait = estimated_iat + jitter;
+ TRANSPORT_LOGD("first rtx for %u in %u ms, rtt = %lu ait = %u jttr = %u",
+ seq, wait, state_->getRTT(), estimated_iat, jitter);
+
+ return now + wait;
+ } else {
+ // wait one RTT
+ // however if the IAT is larger than the RTT, wait one IAT
+ uint32_t wait = SENTINEL_TIMER_INTERVAL;
+
+ double prod_rate = state_->getProducerRate();
+ if (prod_rate == 0) {
+ return now + SENTINEL_TIMER_INTERVAL;
+ }
+
+ double packet_size = state_->getAveragePacketSize();
+ uint32_t estimated_iat = (uint32_t)ceil(1000.0 / (prod_rate / packet_size));
+
+ uint64_t rtt = state_->getRTT();
+ if (rtt == 0) rtt = SENTINEL_TIMER_INTERVAL;
+ wait = (uint32_t)rtt;
+
+ if (estimated_iat > rtt) wait = estimated_iat;
+
+ uint32_t jitter = (uint32_t)ceil(state_->getJitter());
+ wait += jitter;
+
+ // it may happen that the channel is congested and we have some additional
+ // queuing delay to take into account
+ uint32_t queue = (uint32_t)ceil(state_->getQueuing());
+ wait += queue;
+
+ TRANSPORT_LOGD(
+ "next rtx for %u in %u ms, rtt = %lu ait = %u jttr = %u queue = %u",
+ seq, wait, state_->getRTT(), estimated_iat, jitter, queue);
+
+ return now + wait;
+ }
+}
+
+void RTCLossDetectionAndRecovery::retransmit() {
+ if (rtx_timers_.size() == 0) return;
+
+ uint64_t now = getNow();
+
+ auto it = rtx_timers_.begin();
+ std::unordered_set<uint32_t> lost_pkt;
+ uint32_t sent_counter = 0;
+ while (it != rtx_timers_.end() && it->first <= now &&
+ sent_counter < MAX_INTERESTS_IN_BATCH) {
+ uint32_t seq = it->second;
+ auto rtx_it =
+ rtx_state_.find(seq); // this should always return a valid iter
+ if (rtx_it->second.rtx_count_ >= RTC_MAX_RTX ||
+ (now - rtx_it->second.first_send_) >= RTC_MAX_AGE ||
+ seq < state_->getLastSeqNacked()) {
+ // max rtx reached or packet too old or packet nacked, this packet is lost
+ TRANSPORT_LOGD(
+ "packet %u lost because 1) max rtx: %u 2) max age: %u 3) naked: %u",
+ seq, (rtx_it->second.rtx_count_ >= RTC_MAX_RTX),
+ ((now - rtx_it->second.first_send_) >= RTC_MAX_AGE),
+ (seq < state_->getLastSeqNacked()));
+ lost_pkt.insert(seq);
+ it++;
+ } else {
+ // resend the packet
+ state_->onRetransmission(seq);
+ double prod_rate = state_->getProducerRate();
+ if (prod_rate != 0) rtx_it->second.rtx_count_++;
+ rtx_it->second.next_send_ = computeNextSend(seq, false);
+ it = rtx_timers_.erase(it);
+ rtx_timers_.insert(
+ std::pair<uint64_t, uint32_t>(rtx_it->second.next_send_, seq));
+ TRANSPORT_LOGD("send rtx for sequence %u, next send in %lu", seq,
+ (rtx_it->second.next_send_ - now));
+ send_rtx_callback_(seq);
+ sent_counter++;
+ }
+ }
+
+ // remove packets if needed
+ for (auto lost_it = lost_pkt.begin(); lost_it != lost_pkt.end(); lost_it++) {
+ uint32_t seq = *lost_it;
+ state_->onPacketLost(seq);
+ deleteRtx(seq);
+ }
+}
+
+void RTCLossDetectionAndRecovery::scheduleNextRtx() {
+ if (rtx_timers_.size() == 0) {
+ // all the rtx were removed, reset timer
+ next_rtx_timer_ = MAX_TIMER_RTX;
+ return;
+ }
+
+ // check if timer is alreay set
+ if (next_rtx_timer_ != MAX_TIMER_RTX) {
+ // a new check for rtx is already scheduled
+ if (next_rtx_timer_ > rtx_timers_.begin()->first) {
+ // we need to re-schedule it
+ timer_->cancel();
+ } else {
+ // wait for the next timer
+ return;
+ }
+ }
+
+ // set a new timer
+ next_rtx_timer_ = rtx_timers_.begin()->first;
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+ uint64_t wait = 1;
+ if (next_rtx_timer_ != MAX_TIMER_RTX && next_rtx_timer_ > now)
+ wait = next_rtx_timer_ - now;
+
+ std::weak_ptr<RTCLossDetectionAndRecovery> self(shared_from_this());
+ timer_->expires_from_now(std::chrono::milliseconds(wait));
+ timer_->async_wait([self](std::error_code ec) {
+ if (ec) return;
+ if (auto s = self.lock()) {
+ s->retransmit();
+ s->next_rtx_timer_ = MAX_TIMER_RTX;
+ s->scheduleNextRtx();
+ }
+ });
+}
+
+bool RTCLossDetectionAndRecovery::deleteRtx(uint32_t seq) {
+ auto it_rtx = rtx_state_.find(seq);
+ if (it_rtx == rtx_state_.end()) return false; // rtx not found
+
+ uint64_t ts = it_rtx->second.next_send_;
+ auto it_timers = rtx_timers_.find(ts);
+ while (it_timers != rtx_timers_.end() && it_timers->first == ts) {
+ if (it_timers->second == seq) {
+ rtx_timers_.erase(it_timers);
+ break;
+ }
+ it_timers++;
+ }
+
+ bool lost = it_rtx->second.rtx_count_ > 0;
+ rtx_state_.erase(it_rtx);
+
+ return lost;
+}
+
+void RTCLossDetectionAndRecovery::scheduleSentinelTimer(
+ uint64_t expires_from_now) {
+ std::weak_ptr<RTCLossDetectionAndRecovery> self(shared_from_this());
+ sentinel_timer_->expires_from_now(
+ std::chrono::milliseconds(expires_from_now));
+ sentinel_timer_->async_wait([self](std::error_code ec) {
+ if (ec) return;
+ if (auto s = self.lock()) {
+ s->sentinelTimer();
+ }
+ });
+}
+
+void RTCLossDetectionAndRecovery::sentinelTimer() {
+ uint64_t now = getNow();
+
+ bool expired = false;
+ bool sent = false;
+ if ((now - last_event_) >= sentinel_timer_interval_) {
+ // at least a sentinel_timer_interval_ elapsed since last event
+ expired = true;
+ if (TRANSPORT_EXPECT_FALSE(!state_->isProducerActive())) {
+ // this happens at the beginning (or if the producer stops for some
+ // reason) we need to keep sending interest 0 until we get an answer
+ TRANSPORT_LOGD(
+ "sentinel timer: the producer is not active, send packet 0");
+ state_->onRetransmission(0);
+ send_rtx_callback_(0);
+ } else {
+ TRANSPORT_LOGD(
+ "sentinel timer: the producer is active, send the 10 oldest packets");
+ sent = true;
+ uint32_t rtx = 0;
+ auto it = state_->getPendingInterestsMapBegin();
+ auto end = state_->getPendingInterestsMapEnd();
+ while (it != end && rtx < MAX_RTX_WITH_SENTINEL) {
+ uint32_t seq = it->first;
+ TRANSPORT_LOGD("sentinel timer, add %u to the rtx list", seq);
+ addToRetransmissions(seq, seq + 1);
+ rtx++;
+ it++;
+ }
+ }
+ } else {
+ // sentinel timer did not expire because we registered at least one event
+ }
+
+ uint32_t next_timer;
+ double prod_rate = state_->getProducerRate();
+ if (TRANSPORT_EXPECT_FALSE(!state_->isProducerActive()) || prod_rate == 0) {
+ TRANSPORT_LOGD("next timer in %u", SENTINEL_TIMER_INTERVAL);
+ next_timer = SENTINEL_TIMER_INTERVAL;
+ } else {
+ double prod_rate = state_->getProducerRate();
+ double packet_size = state_->getAveragePacketSize();
+ uint32_t estimated_iat = (uint32_t)ceil(1000.0 / (prod_rate / packet_size));
+ uint32_t jitter = (uint32_t)ceil(state_->getJitter());
+
+ // try to reduce the number of timers if the estimated IAT is too small
+ next_timer = std::max((estimated_iat + jitter) * 20, (uint32_t)1);
+ TRANSPORT_LOGD("next sentinel in %u ms, rate: %f, iat: %u, jitter: %u",
+ next_timer, ((prod_rate * 8.0) / 1000000.0), estimated_iat,
+ jitter);
+
+ if (!expired) {
+ // discount the amout of time that is already passed
+ uint32_t discount = (uint32_t)(now - last_event_);
+ if (next_timer > discount) {
+ next_timer = next_timer - discount;
+ } else {
+ // in this case we trigger the timer in 1 ms
+ next_timer = 1;
+ }
+ TRANSPORT_LOGD("timer after discout: %u", next_timer);
+ } else if (sent) {
+ // wait at least one producer stats interval + owd to check if the
+ // production rate is reducing.
+ uint32_t min_wait = PRODUCER_STATS_INTERVAL + (uint32_t)ceil(state_->getQueuing());
+ next_timer = std::max(next_timer, min_wait);
+ TRANSPORT_LOGD("wait for updates from prod, next timer: %u", next_timer);
+ }
+ }
+
+ scheduleSentinelTimer(next_timer);
+}
+
+} // namespace rtc
+
+} // namespace protocol
+
+} // namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_ldr.h b/libtransport/src/protocols/rtc/rtc_ldr.h
new file mode 100644
index 000000000..c0912303b
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_ldr.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <hicn/transport/config.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/core/name.h>
+#include <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_state.h>
+
+#include <asio.hpp>
+#include <asio/steady_timer.hpp>
+#include <functional>
+#include <map>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RTCLossDetectionAndRecovery
+ : public std::enable_shared_from_this<RTCLossDetectionAndRecovery> {
+ struct rtx_state_ {
+ uint64_t first_send_;
+ uint64_t next_send_;
+ uint32_t rtx_count_;
+ };
+
+ using rtxState = struct rtx_state_;
+ using SendRtxCallback = std::function<void(uint32_t)>;
+
+ public:
+ RTCLossDetectionAndRecovery(SendRtxCallback &&callback,
+ asio::io_service &io_service);
+
+ ~RTCLossDetectionAndRecovery();
+
+ void setState(std::shared_ptr<RTCState> state) { state_ = state; }
+ void turnOnRTX();
+ void turnOffRTX();
+
+ void onTimeout(uint32_t seq);
+ void onDataPacketReceived(const core::ContentObject &content_object);
+ void onNackPacketReceived(const core::ContentObject &nack);
+ void onProbePacketReceived(const core::ContentObject &probe);
+
+ void clear();
+
+ bool isRtx(uint32_t seq) {
+ if (rtx_state_.find(seq) != rtx_state_.end()) return true;
+ return false;
+ }
+
+ private:
+ void addToRetransmissions(uint32_t start, uint32_t stop);
+ uint64_t computeNextSend(uint32_t seq, bool new_rtx);
+ void retransmit();
+ void scheduleNextRtx();
+ bool deleteRtx(uint32_t seq);
+ void scheduleSentinelTimer(uint64_t expires_from_now);
+ void sentinelTimer();
+
+ uint64_t getNow() {
+ using namespace std::chrono;
+ uint64_t now =
+ duration_cast<milliseconds>(steady_clock::now().time_since_epoch())
+ .count();
+ return now;
+ }
+
+ // this map keeps track of the retransmitted interest, ordered from the oldest
+ // to the newest one. the state contains the timer of the first send of the
+ // interest (from pendingIntetests_), the timer of the next send (key of the
+ // multimap) and the number of rtx
+ std::map<uint32_t, rtxState> rtx_state_;
+ // this map stored the rtx by timer. The key is the time at which the rtx
+ // should be sent, and the val is the interest seq number
+ std::multimap<uint64_t, uint32_t> rtx_timers_;
+
+ bool rtx_on_;
+ uint64_t next_rtx_timer_;
+ uint64_t last_event_;
+ uint64_t sentinel_timer_interval_;
+ std::unique_ptr<asio::steady_timer> timer_;
+ std::unique_ptr<asio::steady_timer> sentinel_timer_;
+ std::shared_ptr<RTCState> state_;
+
+ SendRtxCallback send_rtx_callback_;
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_packet.h b/libtransport/src/protocols/rtc/rtc_packet.h
new file mode 100644
index 000000000..2f2b19fb9
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_packet.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ */
+
+/* data packet
+ * +-----------------------------------------+
+ * | uint64_t: timestamp |
+ * | |
+ * +-----------------------------------------+
+ * | uint32_t: prod rate (bytes per sec) |
+ * +-----------------------------------------+
+ * | payload |
+ * | ... |
+ */
+
+/* nack packet
+ * +-----------------------------------------+
+ * | uint64_t: timestamp |
+ * | |
+ * +-----------------------------------------+
+ * | uint32_t: prod rate (bytes per sec) |
+ * +-----------------------------------------+
+ * | uint32_t: current seg in production |
+ * +-----------------------------------------+
+ */
+
+#pragma once
+#ifndef _WIN32
+#include <arpa/inet.h>
+#else
+#include <hicn/transport/portability/win_portability.h>
+#endif
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+inline uint64_t _ntohll(const uint64_t *input) {
+ uint64_t return_val;
+ uint8_t *tmp = (uint8_t *)&return_val;
+
+ tmp[0] = (uint8_t)(*input >> 56);
+ tmp[1] = (uint8_t)(*input >> 48);
+ tmp[2] = (uint8_t)(*input >> 40);
+ tmp[3] = (uint8_t)(*input >> 32);
+ tmp[4] = (uint8_t)(*input >> 24);
+ tmp[5] = (uint8_t)(*input >> 16);
+ tmp[6] = (uint8_t)(*input >> 8);
+ tmp[7] = (uint8_t)(*input >> 0);
+
+ return return_val;
+}
+
+inline uint64_t _htonll(const uint64_t *input) { return (_ntohll(input)); }
+
+const uint32_t DATA_HEADER_SIZE = 12; // bytes
+ // XXX: sizeof(data_packet_t) is 16
+ // beacuse of padding
+const uint32_t NACK_HEADER_SIZE = 16;
+
+struct data_packet_t {
+ uint64_t timestamp;
+ uint32_t prod_rate;
+
+ inline uint64_t getTimestamp() const { return _ntohll(&timestamp); }
+ inline void setTimestamp(uint64_t time) { timestamp = _htonll(&time); }
+
+ inline uint32_t getProductionRate() const { return ntohl(prod_rate); }
+ inline void setProductionRate(uint32_t rate) { prod_rate = htonl(rate); }
+};
+
+struct nack_packet_t {
+ uint64_t timestamp;
+ uint32_t prod_rate;
+ uint32_t prod_seg;
+
+ inline uint64_t getTimestamp() const { return _ntohll(&timestamp); }
+ inline void setTimestamp(uint64_t time) { timestamp = _htonll(&time); }
+
+ inline uint32_t getProductionRate() const { return ntohl(prod_rate); }
+ inline void setProductionRate(uint32_t rate) { prod_rate = htonl(rate); }
+
+ inline uint32_t getProductionSegement() const { return ntohl(prod_seg); }
+ inline void setProductionSegement(uint32_t seg) { prod_seg = htonl(seg); }
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport \ No newline at end of file
diff --git a/libtransport/src/protocols/rtc/rtc_rc.h b/libtransport/src/protocols/rtc/rtc_rc.h
new file mode 100644
index 000000000..34d090092
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rc.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <protocols/rtc/rtc_state.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RTCRateControl : public std::enable_shared_from_this<RTCRateControl> {
+ public:
+ RTCRateControl()
+ : rc_on_(false),
+ congestion_win_(1000000), // init the win to a large number
+ congestion_state_(CongestionState::Normal),
+ protocol_state_(nullptr) {}
+
+ virtual ~RTCRateControl() = default;
+
+ void turnOnRateControl() { rc_on_ = true; }
+ void setState(std::shared_ptr<RTCState> state) { protocol_state_ = state; };
+ uint32_t getCongesionWindow() { return congestion_win_; };
+
+ virtual void onNewRound(double round_len) = 0;
+ virtual void onDataPacketReceived(
+ const core::ContentObject &content_object) = 0;
+
+ protected:
+ enum class CongestionState { Normal = 0, Underuse = 1, Congested = 2, Last };
+
+ protected:
+ bool rc_on_;
+ uint32_t congestion_win_;
+ CongestionState congestion_state_;
+
+ std::shared_ptr<RTCState> protocol_state_;
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rc_frame.cc b/libtransport/src/protocols/rtc/rtc_rc_frame.cc
new file mode 100644
index 000000000..b577b5bea
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rc_frame.cc
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_rc_frame.h>
+
+#include <algorithm>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RTCRateControlFrame::RTCRateControlFrame() : cc_detector_() {}
+
+RTCRateControlFrame::~RTCRateControlFrame() {}
+
+void RTCRateControlFrame::onNewRound(double round_len) {
+ if (!rc_on_) return;
+
+ CongestionState prev_congestion_state = congestion_state_;
+ cc_detector_.updateStats();
+ congestion_state_ = (CongestionState)cc_detector_.getState();
+
+ if (congestion_state_ == CongestionState::Congested) {
+ if (prev_congestion_state == CongestionState::Normal) {
+ // congestion detected, notify app and init congestion win
+ double prod_rate = protocol_state_->getReceivedRate();
+ double rtt = (double)protocol_state_->getRTT() / MILLI_IN_A_SEC;
+ double packet_size = protocol_state_->getAveragePacketSize();
+
+ if (prod_rate == 0.0 || rtt == 0.0 || packet_size == 0.0) {
+ // TODO do something
+ return;
+ }
+
+ congestion_win_ = (uint32_t)ceil(prod_rate * rtt / packet_size);
+ }
+ uint32_t win = congestion_win_ * WIN_DECREASE_FACTOR;
+ congestion_win_ = std::max(win, WIN_MIN);
+ return;
+ }
+}
+
+void RTCRateControlFrame::onDataPacketReceived(
+ const core::ContentObject &content_object) {
+ if (!rc_on_) return;
+
+ uint32_t seq = content_object.getName().getSuffix();
+ if (!protocol_state_->isPending(seq)) return;
+
+ cc_detector_.addPacket(content_object);
+}
+
+void RTCRateControlFrame::receivedBwProbeTrain(uint64_t firts_probe_ts,
+ uint64_t last_probe_ts,
+ uint32_t total_probes) {
+ // TODO
+ return;
+}
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rc_frame.h b/libtransport/src/protocols/rtc/rtc_rc_frame.h
new file mode 100644
index 000000000..25d5ddbb6
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rc_frame.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <protocols/rtc/congestion_detection.h>
+#include <protocols/rtc/rtc_rc.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RTCRateControlFrame : public RTCRateControl {
+ public:
+ RTCRateControlFrame();
+
+ ~RTCRateControlFrame();
+
+ void onNewRound(double round_len);
+ void onDataPacketReceived(const core::ContentObject &content_object);
+
+ void receivedBwProbeTrain(uint64_t firts_probe_ts, uint64_t last_probe_ts,
+ uint32_t total_probes);
+
+ private:
+ CongestionDetection cc_detector_;
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rc_queue.cc b/libtransport/src/protocols/rtc/rtc_rc_queue.cc
new file mode 100644
index 000000000..3c7318dae
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rc_queue.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_rc_queue.h>
+
+#include <algorithm>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RTCRateControlQueue::RTCRateControlQueue()
+ : rounds_since_last_drop_(0),
+ rounds_without_congestion_(0),
+ last_queue_(0) {}
+
+RTCRateControlQueue::~RTCRateControlQueue() {}
+
+void RTCRateControlQueue::onNewRound(double round_len) {
+ if (!rc_on_) return;
+
+ double received_rate = protocol_state_->getReceivedRate();
+ double target_rate =
+ protocol_state_->getProducerRate() * PRODUCTION_RATE_FRACTION;
+ double rtt = (double)protocol_state_->getRTT() / MILLI_IN_A_SEC;
+ double packet_size = protocol_state_->getAveragePacketSize();
+ double queue = protocol_state_->getQueuing();
+
+ if (rtt == 0.0) return; // no info from the producer
+
+ CongestionState prev_congestion_state = congestion_state_;
+
+ if (prev_congestion_state == CongestionState::Normal &&
+ received_rate >= target_rate) {
+ // if the queue is high in this case we are most likelly fighting with
+ // a TCP flow and there is enough bandwidth to match the producer rate
+ congestion_state_ = CongestionState::Normal;
+ } else if (queue > MAX_QUEUING_DELAY || last_queue_ == queue) {
+ // here we detect congestion. in the case that last_queue == queue
+ // the consumer didn't receive any packet from the producer so we
+ // consider this case as congestion
+ // TODO: wath happen in case of high loss rate?
+ congestion_state_ = CongestionState::Congested;
+ } else {
+ // nothing bad is happening
+ congestion_state_ = CongestionState::Normal;
+ }
+
+ last_queue_ = queue;
+
+ if (congestion_state_ == CongestionState::Congested) {
+ if (prev_congestion_state == CongestionState::Normal) {
+ // init the congetion window using the received rate
+ congestion_win_ = (uint32_t)ceil(received_rate * rtt / packet_size);
+ rounds_since_last_drop_ = (uint32_t)ROUNDS_BEFORE_TAKE_ACTION + 1;
+ }
+
+ if (rounds_since_last_drop_ >= ROUNDS_BEFORE_TAKE_ACTION) {
+ uint32_t win = congestion_win_ * (uint32_t)WIN_DECREASE_FACTOR;
+ congestion_win_ = std::max(win, WIN_MIN);
+ rounds_since_last_drop_ = 0;
+ return;
+ }
+
+ rounds_since_last_drop_++;
+ }
+
+ if (congestion_state_ == CongestionState::Normal) {
+ if (prev_congestion_state == CongestionState::Congested) {
+ rounds_without_congestion_ = 0;
+ }
+
+ rounds_without_congestion_++;
+ if (rounds_without_congestion_ < ROUNDS_BEFORE_TAKE_ACTION) return;
+
+ congestion_win_ = congestion_win_ * (uint32_t)WIN_INCREASE_FACTOR;
+ congestion_win_ = std::min(congestion_win_, INITIAL_WIN_MAX);
+ }
+}
+
+void RTCRateControlQueue::onDataPacketReceived(
+ const core::ContentObject &content_object) {
+ // nothing to do
+ return;
+}
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_rc_queue.h b/libtransport/src/protocols/rtc/rtc_rc_queue.h
new file mode 100644
index 000000000..407354d43
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_rc_queue.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <hicn/transport/utils/shared_ptr_utils.h>
+#include <protocols/rtc/rtc_rc.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class RTCRateControlQueue : public RTCRateControl {
+ public:
+ RTCRateControlQueue();
+
+ ~RTCRateControlQueue();
+
+ void onNewRound(double round_len);
+ void onDataPacketReceived(const core::ContentObject &content_object);
+
+ auto shared_from_this() { return utils::shared_from(this); }
+
+ private:
+ uint32_t rounds_since_last_drop_;
+ uint32_t rounds_without_congestion_;
+ double last_queue_;
+};
+
+} // end namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_state.cc b/libtransport/src/protocols/rtc/rtc_state.cc
new file mode 100644
index 000000000..9c965bfed
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_state.cc
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <protocols/rtc/rtc_consts.h>
+#include <protocols/rtc/rtc_state.h>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+RTCState::RTCState(ProbeHandler::SendProbeCallback &&rtt_probes_callback,
+ DiscoveredRttCallback &&discovered_rtt_callback,
+ asio::io_service &io_service)
+ : rtt_probes_(std::make_shared<ProbeHandler>(
+ std::move(rtt_probes_callback), io_service)),
+ discovered_rtt_callback_(std::move(discovered_rtt_callback)) {
+ init_rtt_timer_ = std::make_unique<asio::steady_timer>(io_service);
+ initParams();
+}
+
+RTCState::~RTCState() {}
+
+void RTCState::initParams() {
+ // packets counters (total)
+ sent_interests_ = 0;
+ sent_rtx_ = 0;
+ received_data_ = 0;
+ received_nacks_ = 0;
+ received_timeouts_ = 0;
+ received_probes_ = 0;
+
+ // loss counters
+ packets_lost_ = 0;
+ losses_recovered_ = 0;
+ first_seq_in_round_ = 0;
+ highest_seq_received_ = 0;
+ highest_seq_received_in_order_ = 0;
+ last_seq_nacked_ = 0;
+ loss_rate_ = 0.0;
+ residual_loss_rate_ = 0.0;
+
+ // bw counters
+ received_bytes_ = 0;
+ avg_packet_size_ = INIT_PACKET_SIZE;
+ production_rate_ = 0.0;
+ received_rate_ = 0.0;
+
+ // nack counter
+ nack_on_last_round_ = false;
+ received_nacks_last_round_ = 0;
+
+ // packets counter
+ received_packets_last_round_ = 0;
+ received_data_last_round_ = 0;
+ received_data_from_cache_ = 0;
+ data_from_cache_rate_ = 0;
+ sent_interests_last_round_ = 0;
+ sent_rtx_last_round_ = 0;
+
+ // round conunters
+ rounds_ = 0;
+ rounds_without_nacks_ = 0;
+ rounds_without_packets_ = 0;
+
+ last_production_seq_ = 0;
+ producer_is_active_ = false;
+ last_prod_update_ = 0;
+
+ // paths stats
+ path_table_.clear();
+ main_path_ = nullptr;
+
+ // packet received
+ received_or_lost_packets_.clear();
+
+ // pending interests
+ pending_interests_.clear();
+
+ // init rtt
+ first_interest_sent_ = ~0;
+ init_rtt_ = false;
+ rtt_probes_->setProbes(INIT_RTT_PROBE_INTERVAL, INIT_RTT_PROBES);
+ rtt_probes_->sendProbes();
+ setInitRttTimer(INIT_RTT_PROBE_RESTART);
+}
+
+// packet events
+void RTCState::onSendNewInterest(const core::Name *interest_name) {
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+ uint32_t seq = interest_name->getSuffix();
+ pending_interests_.insert(std::pair<uint32_t, uint64_t>(seq, now));
+
+ if(sent_interests_ == 0) first_interest_sent_ = now;
+
+ sent_interests_++;
+ sent_interests_last_round_++;
+}
+
+void RTCState::onTimeout(uint32_t seq) {
+ auto it = pending_interests_.find(seq);
+ if (it != pending_interests_.end()) {
+ pending_interests_.erase(it);
+ }
+ received_timeouts_++;
+}
+
+void RTCState::onRetransmission(uint32_t seq) {
+ // remove the interest for the pendingInterest map only after the first rtx.
+ // in this way we can handle the ooo packets that come in late as normla
+ // packet. we consider a packet lost only if we sent at least an RTX for it.
+ // XXX this may become problematic if we stop the RTX transmissions
+ auto it = pending_interests_.find(seq);
+ if (it != pending_interests_.end()) {
+ pending_interests_.erase(it);
+ packets_lost_++;
+ }
+ sent_rtx_++;
+ sent_rtx_last_round_++;
+}
+
+void RTCState::onDataPacketReceived(const core::ContentObject &content_object,
+ bool compute_stats) {
+ uint32_t seq = content_object.getName().getSuffix();
+ if (compute_stats) {
+ updatePathStats(content_object, false);
+ received_data_last_round_++;
+ }
+ received_data_++;
+
+ struct data_packet_t *data_pkt =
+ (struct data_packet_t *)content_object.getPayload()->data();
+ uint64_t production_time = data_pkt->getTimestamp();
+ if (last_prod_update_ < production_time) {
+ last_prod_update_ = production_time;
+ uint32_t production_rate = data_pkt->getProductionRate();
+ production_rate_ = (double)production_rate;
+ }
+
+ updatePacketSize(content_object);
+ updateReceivedBytes(content_object);
+ addRecvOrLost(seq, PacketState::RECEIVED);
+
+ if (seq > highest_seq_received_) highest_seq_received_ = seq;
+
+ // the producer is responding
+ // it is generating valid data packets so we consider it active
+ producer_is_active_ = true;
+
+ received_packets_last_round_++;
+}
+
+void RTCState::onNackPacketReceived(const core::ContentObject &nack,
+ bool compute_stats) {
+ uint32_t seq = nack.getName().getSuffix();
+ struct nack_packet_t *nack_pkt =
+ (struct nack_packet_t *)nack.getPayload()->data();
+ uint64_t production_time = nack_pkt->getTimestamp();
+ uint32_t production_seq = nack_pkt->getProductionSegement();
+ uint32_t production_rate = nack_pkt->getProductionRate();
+
+ if (TRANSPORT_EXPECT_FALSE(main_path_ == nullptr) ||
+ last_prod_update_ < production_time) {
+ // update production rate
+ last_prod_update_ = production_time;
+ last_production_seq_ = production_seq;
+ production_rate_ = (double)production_rate;
+ }
+
+ if (compute_stats) {
+ // this is not an RTX
+ updatePathStats(nack, true);
+ nack_on_last_round_ = true;
+ }
+
+ // for statistics pourpose we log all nacks, also the one received for
+ // retransmitted packets
+ received_nacks_++;
+ received_nacks_last_round_++;
+
+ if (production_seq > seq) {
+ // old nack, seq is lost
+ // update last nacked
+ if (last_seq_nacked_ < seq) last_seq_nacked_ = seq;
+ TRANSPORT_LOGD("lost packet %u beacuse of a past nack", seq);
+ onPacketLost(seq);
+ } else if (seq > production_seq) {
+ // future nack
+ // remove the nack from the pending interest map
+ // (the packet is not received/lost yet)
+ pending_interests_.erase(seq);
+ } else {
+ // this should be a quite rear event. simply remove the
+ // packet from the pending interest list
+ pending_interests_.erase(seq);
+ }
+
+ // the producer is responding
+ // we consider it active only if the production rate is not 0
+ // or the production sequence number is not 1
+ if (production_rate_ != 0 || production_seq != 1) {
+ producer_is_active_ = true;
+ }
+
+ received_packets_last_round_++;
+}
+
+void RTCState::onPacketLost(uint32_t seq) {
+ TRANSPORT_LOGD("packet %u is lost", seq);
+ auto it = pending_interests_.find(seq);
+ if (it != pending_interests_.end()) {
+ // this packet was never retransmitted so it does
+ // not appear in the loss count
+ packets_lost_++;
+ }
+ addRecvOrLost(seq, PacketState::LOST);
+}
+
+void RTCState::onPacketRecovered(uint32_t seq) {
+ losses_recovered_++;
+ addRecvOrLost(seq, PacketState::RECEIVED);
+}
+
+bool RTCState::onProbePacketReceived(const core::ContentObject &probe) {
+ uint32_t seq = probe.getName().getSuffix();
+ uint64_t rtt;
+
+ rtt = rtt_probes_->getRtt(seq);
+
+ if (rtt == 0) return false; // this is not a valid probe
+
+ // like for data and nacks update the path stats. Here the RTT is computed
+ // by the probe handler. Both probes for rtt and bw are good to esimate
+ // info on the path
+ uint32_t path_label = probe.getPathLabel();
+
+ auto path_it = path_table_.find(path_label);
+
+ // update production rate and last_seq_nacked like in case of a nack
+ struct nack_packet_t *probe_pkt =
+ (struct nack_packet_t *)probe.getPayload()->data();
+ uint64_t sender_timestamp = probe_pkt->getTimestamp();
+ uint32_t production_seq = probe_pkt->getProductionSegement();
+ uint32_t production_rate = probe_pkt->getProductionRate();
+
+
+ if (path_it == path_table_.end()) {
+ // found a new path
+ std::shared_ptr<RTCDataPath> newPath =
+ std::make_shared<RTCDataPath>(path_label);
+ auto ret = path_table_.insert(
+ std::pair<uint32_t, std::shared_ptr<RTCDataPath>>(path_label, newPath));
+ path_it = ret.first;
+ }
+
+ auto path = path_it->second;
+
+ path->insertRttSample(rtt);
+ path->receivedNack();
+
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+
+ int64_t OWD = now - sender_timestamp;
+ path->insertOwdSample(OWD);
+
+ if (last_prod_update_ < sender_timestamp) {
+ last_production_seq_ = production_seq;
+ last_prod_update_ = sender_timestamp;
+ production_rate_ = (double)production_rate;
+ }
+
+ // the producer is responding
+ // we consider it active only if the production rate is not 0
+ // or the production sequence numner is not 1
+ if (production_rate_ != 0 || production_seq != 1) {
+ producer_is_active_ = true;
+ }
+
+ // check for init RTT. if received_probes_ is equal to 0 schedule a timer to
+ // wait for the INIT_RTT_PROBES. in this way if some probes get lost we don't
+ // wait forever
+ received_probes_++;
+
+ if(!init_rtt_ && received_probes_ <= INIT_RTT_PROBES){
+ if(received_probes_ == 1){
+ // we got the first probe, wait at most INIT_RTT_PROBE_WAIT sec for the others
+ main_path_ = path;
+ setInitRttTimer(INIT_RTT_PROBE_WAIT);
+ }
+ if(received_probes_ == INIT_RTT_PROBES) {
+ // we are done
+ init_rtt_timer_->cancel();
+ checkInitRttTimer();
+ }
+ }
+
+ received_packets_last_round_++;
+
+ // ignore probes sent before the first interest
+ if((now - rtt) <= first_interest_sent_) return false;
+ return true;
+}
+
+void RTCState::onNewRound(double round_len, bool in_sync) {
+ // XXX
+ // here we take into account only the single path case so we assume that we
+ // don't use two paths in parellel for this single flow
+
+ if (path_table_.empty()) return;
+
+ double bytes_per_sec =
+ ((double)received_bytes_ * (MILLI_IN_A_SEC / round_len));
+ if(received_rate_ == 0)
+ received_rate_ = bytes_per_sec;
+ else
+ received_rate_ = (received_rate_ * MOVING_AVG_ALPHA) +
+ ((1 - MOVING_AVG_ALPHA) * bytes_per_sec);
+
+ // search for an active path. There should be only one active path (meaning a
+ // path that leads to the producer socket -no cache- and from which we are
+ // currently getting data packets) at any time. However it may happen that
+ // there are mulitple active paths in case of mobility (the old path will
+ // remain active for a short ammount of time). The main path is selected as
+ // the active path from where the consumer received the latest data packet
+
+ uint64_t last_packet_ts = 0;
+ main_path_ = nullptr;
+
+ for (auto it = path_table_.begin(); it != path_table_.end(); it++) {
+ it->second->roundEnd();
+ if (it->second->isActive()) {
+ uint64_t ts = it->second->getLastPacketTS();
+ if (ts > last_packet_ts) {
+ last_packet_ts = ts;
+ main_path_ = it->second;
+ }
+ }
+ }
+
+ if (in_sync) updateLossRate();
+
+ // handle nacks
+ if (!nack_on_last_round_ && received_bytes_ > 0) {
+ rounds_without_nacks_++;
+ } else {
+ rounds_without_nacks_ = 0;
+ }
+
+ // check if the producer is active
+ if (received_packets_last_round_ != 0) {
+ rounds_without_packets_ = 0;
+ } else {
+ rounds_without_packets_++;
+ if (rounds_without_packets_ >= MAX_ROUND_WHIOUT_PACKETS &&
+ producer_is_active_ != false) {
+ initParams();
+ }
+ }
+
+ // compute cache/producer ratio
+ if (received_data_last_round_ != 0) {
+ double new_rate =
+ (double)received_data_from_cache_ / (double)received_data_last_round_;
+ data_from_cache_rate_ = data_from_cache_rate_ * MOVING_AVG_ALPHA +
+ (new_rate * (1 - MOVING_AVG_ALPHA));
+ }
+
+ // reset counters
+ received_bytes_ = 0;
+ packets_lost_ = 0;
+ losses_recovered_ = 0;
+ first_seq_in_round_ = highest_seq_received_;
+
+ nack_on_last_round_ = false;
+ received_nacks_last_round_ = 0;
+
+ received_packets_last_round_ = 0;
+ received_data_last_round_ = 0;
+ received_data_from_cache_ = 0;
+ sent_interests_last_round_ = 0;
+ sent_rtx_last_round_ = 0;
+
+ rounds_++;
+}
+
+void RTCState::updateReceivedBytes(const core::ContentObject &content_object) {
+ received_bytes_ +=
+ (uint32_t)(content_object.headerSize() + content_object.payloadSize());
+}
+
+void RTCState::updatePacketSize(const core::ContentObject &content_object) {
+ uint32_t pkt_size =
+ (uint32_t)(content_object.headerSize() + content_object.payloadSize());
+ avg_packet_size_ = (MOVING_AVG_ALPHA * avg_packet_size_) +
+ ((1 - MOVING_AVG_ALPHA) * pkt_size);
+}
+
+void RTCState::updatePathStats(const core::ContentObject &content_object,
+ bool is_nack) {
+ // get packet path
+ uint32_t path_label = content_object.getPathLabel();
+ auto path_it = path_table_.find(path_label);
+
+ if (path_it == path_table_.end()) {
+ // found a new path
+ std::shared_ptr<RTCDataPath> newPath =
+ std::make_shared<RTCDataPath>(path_label);
+ auto ret = path_table_.insert(
+ std::pair<uint32_t, std::shared_ptr<RTCDataPath>>(path_label, newPath));
+ path_it = ret.first;
+ }
+
+ auto path = path_it->second;
+
+ // compute rtt
+ uint32_t seq = content_object.getName().getSuffix();
+ uint64_t interest_sent_time = getInterestSentTime(seq);
+ if (interest_sent_time == 0)
+ return; // this should not happen,
+ // it means that we are processing an interest
+ // that is not pending
+
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::steady_clock::now().time_since_epoch())
+ .count();
+
+ uint64_t RTT = now - interest_sent_time;
+
+ path->insertRttSample(RTT);
+
+ // compute OWD (the first part of the nack and data packet header are the
+ // same, so we cast to data data packet)
+ struct data_packet_t *packet =
+ (struct data_packet_t *)content_object.getPayload()->data();
+ uint64_t sender_timestamp = packet->getTimestamp();
+ int64_t OWD = now - sender_timestamp;
+ path->insertOwdSample(OWD);
+
+ // compute IAT or set path to producer
+ if (!is_nack) {
+ // compute the iat only for the content packets
+ uint32_t segment_number = content_object.getName().getSuffix();
+ path->computeInterArrivalGap(segment_number);
+ if (!path->pathToProducer()) received_data_from_cache_++;
+ } else {
+ path->receivedNack();
+ }
+}
+
+void RTCState::updateLossRate() {
+ loss_rate_ = 0.0;
+ residual_loss_rate_ = 0.0;
+
+ uint32_t number_theorically_received_packets_ =
+ highest_seq_received_ - first_seq_in_round_;
+
+ // in this case no new packet was recevied after the previuos round, avoid
+ // division by 0
+ if (number_theorically_received_packets_ == 0) return;
+
+ loss_rate_ = (double)((double)(packets_lost_) /
+ (double)number_theorically_received_packets_);
+
+ residual_loss_rate_ = (double)((double)(packets_lost_ - losses_recovered_) /
+ (double)number_theorically_received_packets_);
+
+ if (residual_loss_rate_ < 0) residual_loss_rate_ = 0;
+}
+
+void RTCState::addRecvOrLost(uint32_t seq, PacketState state) {
+ pending_interests_.erase(seq);
+ if (received_or_lost_packets_.size() >= MAX_CACHED_PACKETS) {
+ received_or_lost_packets_.erase(received_or_lost_packets_.begin());
+ }
+ // notice that it may happen that a packet that we consider lost arrives after
+ // some time, in this case we simply overwrite the packet state.
+ received_or_lost_packets_[seq] = state;
+
+ // keep track of the last packet received/lost
+ // without holes.
+ if (highest_seq_received_in_order_ < last_seq_nacked_) {
+ highest_seq_received_in_order_ = last_seq_nacked_;
+ }
+
+ if ((highest_seq_received_in_order_ + 1) == seq) {
+ highest_seq_received_in_order_ = seq;
+ } else if (seq <= highest_seq_received_in_order_) {
+ // here we do nothing
+ } else if (seq > highest_seq_received_in_order_) {
+ // 1) there is a gap in the sequence so we do not update largest_in_seq_
+ // 2) all the packets from largest_in_seq_ to seq are in
+ // received_or_lost_packets_ an we upate largest_in_seq_
+
+ for (uint32_t i = highest_seq_received_in_order_ + 1; i <= seq; i++) {
+ if (received_or_lost_packets_.find(i) ==
+ received_or_lost_packets_.end()) {
+ break;
+ }
+ // this packet is in order so we can update the
+ // highest_seq_received_in_order_
+ highest_seq_received_in_order_ = i;
+ }
+ }
+}
+
+void RTCState::setInitRttTimer(uint32_t wait){
+ init_rtt_timer_->cancel();
+ init_rtt_timer_->expires_from_now(std::chrono::milliseconds(wait));
+ init_rtt_timer_->async_wait([this](std::error_code ec) {
+ if(ec) return;
+ checkInitRttTimer();
+ });
+}
+
+void RTCState::checkInitRttTimer() {
+ if(received_probes_ < INIT_RTT_MIN_PROBES_TO_RECV){
+ // we didn't received enough probes, restart
+ received_probes_ = 0;
+ rtt_probes_->setProbes(INIT_RTT_PROBE_INTERVAL, INIT_RTT_PROBES);
+ rtt_probes_->sendProbes();
+ setInitRttTimer(INIT_RTT_PROBE_RESTART);
+ return;
+ }
+ init_rtt_ = true;
+ main_path_->roundEnd();
+ rtt_probes_->setProbes(RTT_PROBE_INTERVAL, 0);
+ rtt_probes_->sendProbes();
+
+ // init last_seq_nacked_. skip packets that may come from the cache
+ double prod_rate = getProducerRate();
+ double rtt = (double)getRTT() / MILLI_IN_A_SEC;
+ double packet_size = getAveragePacketSize();
+ uint32_t pkt_in_rtt_ = (uint32_t)std::floor(((prod_rate / packet_size) * rtt) * 0.8);
+ last_seq_nacked_ = last_production_seq_ + pkt_in_rtt_;
+
+ discovered_rtt_callback_();
+}
+
+} // namespace rtc
+
+} // namespace protocol
+
+} // namespace transport
diff --git a/libtransport/src/protocols/rtc/rtc_state.h b/libtransport/src/protocols/rtc/rtc_state.h
new file mode 100644
index 000000000..e4fefaffe
--- /dev/null
+++ b/libtransport/src/protocols/rtc/rtc_state.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2017-2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <hicn/transport/config.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/core/name.h>
+#include <protocols/rtc/probe_handler.h>
+#include <protocols/rtc/rtc_data_path.h>
+
+#include <asio.hpp>
+#include <asio/steady_timer.hpp>
+#include <map>
+#include <set>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+enum class PacketState : uint8_t { RECEIVED, LOST, UNKNOWN };
+
+class RTCState : std::enable_shared_from_this<RTCState> {
+ public:
+ using DiscoveredRttCallback = std::function<void()>;
+ public:
+ RTCState(ProbeHandler::SendProbeCallback &&rtt_probes_callback,
+ DiscoveredRttCallback &&discovered_rtt_callback,
+ asio::io_service &io_service);
+
+ ~RTCState();
+
+ // packet events
+ void onSendNewInterest(const core::Name *interest_name);
+ void onTimeout(uint32_t seq);
+ void onRetransmission(uint32_t seq);
+ void onDataPacketReceived(const core::ContentObject &content_object,
+ bool compute_stats);
+ void onNackPacketReceived(const core::ContentObject &nack,
+ bool compute_stats);
+ void onPacketLost(uint32_t seq);
+ void onPacketRecovered(uint32_t seq);
+ bool onProbePacketReceived(const core::ContentObject &probe);
+
+ // protocol state
+ void onNewRound(double round_len, bool in_sync);
+
+ // main path
+ uint32_t getProducerPath() const {
+ if (mainPathIsValid()) return main_path_->getPathId();
+ return 0;
+ }
+
+ // delay metrics
+ bool isRttDiscovered() const {
+ return init_rtt_;
+ }
+
+ uint64_t getRTT() const {
+ if (mainPathIsValid()) return main_path_->getMinRtt();
+ return 0;
+ }
+ void resetRttStats() {
+ if (mainPathIsValid()) main_path_->clearRtt();
+ }
+
+ double getQueuing() const {
+ if (mainPathIsValid()) return main_path_->getQueuingDealy();
+ return 0.0;
+ }
+ double getIAT() const {
+ if (mainPathIsValid()) return main_path_->getInterArrivalGap();
+ return 0.0;
+ }
+
+ double getJitter() const {
+ if (mainPathIsValid()) return main_path_->getJitter();
+ return 0.0;
+ }
+
+ // pending interests
+ uint64_t getInterestSentTime(uint32_t seq) {
+ auto it = pending_interests_.find(seq);
+ if (it != pending_interests_.end()) return it->second;
+ return 0;
+ }
+ bool isPending(uint32_t seq) {
+ if (pending_interests_.find(seq) != pending_interests_.end()) return true;
+ return false;
+ }
+ uint32_t getPendingInterestNumber() const {
+ return (uint32_t)pending_interests_.size();
+ }
+ PacketState isReceivedOrLost(uint32_t seq) {
+ auto it = received_or_lost_packets_.find(seq);
+ if (it != received_or_lost_packets_.end()) return it->second;
+ return PacketState::UNKNOWN;
+ }
+
+ // loss rate
+ double getLossRate() const { return loss_rate_; }
+ double getResidualLossRate() const { return residual_loss_rate_; }
+ uint32_t getHighestSeqReceivedInOrder() const {
+ return highest_seq_received_in_order_;
+ }
+ uint32_t getLostData() const { return packets_lost_; };
+ uint32_t getRecoveredLosses() const { return losses_recovered_; }
+
+ // generic stats
+ uint32_t getReceivedBytesInRound() const { return received_bytes_; }
+ uint32_t getReceivedNacksInRound() const {
+ return received_nacks_last_round_;
+ }
+ uint32_t getSentInterestInRound() const { return sent_interests_last_round_; }
+ uint32_t getSentRtxInRound() const { return sent_rtx_last_round_; }
+
+ // bandwidth/production metrics
+ double getAvailableBw() const { return 0.0; }; // TODO
+ double getProducerRate() const { return production_rate_; }
+ double getReceivedRate() const { return received_rate_; }
+ double getAveragePacketSize() const { return avg_packet_size_; }
+
+ // nacks
+ uint32_t getRoundsWithoutNacks() const { return rounds_without_nacks_; }
+ uint32_t getLastSeqNacked() const { return last_seq_nacked_; }
+
+ // producer state
+ bool isProducerActive() const { return producer_is_active_; }
+
+ // packets from cache
+ double getPacketFromCacheRatio() const { return data_from_cache_rate_; }
+
+ std::map<uint32_t, uint64_t>::iterator getPendingInterestsMapBegin() {
+ return pending_interests_.begin();
+ }
+ std::map<uint32_t, uint64_t>::iterator getPendingInterestsMapEnd() {
+ return pending_interests_.end();
+ }
+
+ private:
+ void initParams();
+
+ // update stats
+ void updateState();
+ void updateReceivedBytes(const core::ContentObject &content_object);
+ void updatePacketSize(const core::ContentObject &content_object);
+ void updatePathStats(const core::ContentObject &content_object, bool is_nack);
+ void updateLossRate();
+
+ void addRecvOrLost(uint32_t seq, PacketState state);
+
+ void setInitRttTimer(uint32_t wait);
+ void checkInitRttTimer();
+
+ bool mainPathIsValid() const {
+ if (main_path_ != nullptr)
+ return true;
+ else
+ return false;
+ }
+
+ // packets counters (total)
+ uint32_t sent_interests_;
+ uint32_t sent_rtx_;
+ uint32_t received_data_;
+ uint32_t received_nacks_;
+ uint32_t received_timeouts_;
+ uint32_t received_probes_;
+
+ // loss counters
+ int32_t packets_lost_;
+ int32_t losses_recovered_;
+ uint32_t first_seq_in_round_;
+ uint32_t highest_seq_received_;
+ uint32_t highest_seq_received_in_order_;
+ uint32_t last_seq_nacked_; // segment for which we got an oldNack
+ double loss_rate_;
+ double residual_loss_rate_;
+
+ // bw counters
+ uint32_t received_bytes_;
+ double avg_packet_size_;
+ double production_rate_; // rate communicated by the producer using nacks
+ double received_rate_; // rate recevied by the consumer
+
+ // nack counter
+ // the bool takes tracks only about the valid nacks (no rtx) and it is used to
+ // switch between the states. Instead received_nacks_last_round_ logs all the
+ // nacks for statistics
+ bool nack_on_last_round_;
+ uint32_t received_nacks_last_round_;
+
+ // packets counter
+ uint32_t received_packets_last_round_;
+ uint32_t received_data_last_round_;
+ uint32_t received_data_from_cache_;
+ double data_from_cache_rate_;
+ uint32_t sent_interests_last_round_;
+ uint32_t sent_rtx_last_round_;
+
+ // round conunters
+ uint32_t rounds_;
+ uint32_t rounds_without_nacks_;
+ uint32_t rounds_without_packets_;
+
+ // init rtt
+ uint64_t first_interest_sent_;
+
+ // producer state
+ bool
+ producer_is_active_; // the prodcuer is active if we receive some packets
+ uint32_t last_production_seq_; // last production seq received by the producer
+ uint64_t last_prod_update_; // timestamp of the last packets used to update
+ // stats from the producer
+
+ // paths stats
+ std::unordered_map<uint32_t, std::shared_ptr<RTCDataPath>> path_table_;
+ std::shared_ptr<RTCDataPath> main_path_;
+
+ // packet received
+ // cache where to store info about the last MAX_CACHED_PACKETS
+ std::map<uint32_t, PacketState> received_or_lost_packets_;
+
+ // pending interests
+ std::map<uint32_t, uint64_t> pending_interests_;
+
+ // probes
+ std::shared_ptr<ProbeHandler> rtt_probes_;
+ bool init_rtt_;
+ std::unique_ptr<asio::steady_timer> init_rtt_timer_;
+
+ // callbacks
+ DiscoveredRttCallback discovered_rtt_callback_;
+};
+
+} // namespace rtc
+
+} // namespace protocol
+
+} // namespace transport
diff --git a/libtransport/src/protocols/rtc/trendline_estimator.cc b/libtransport/src/protocols/rtc/trendline_estimator.cc
new file mode 100644
index 000000000..7a0803857
--- /dev/null
+++ b/libtransport/src/protocols/rtc/trendline_estimator.cc
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// FROM
+// https://source.chromium.org/chromium/chromium/src/+/master:third_party/webrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc
+
+#include "trendline_estimator.h"
+
+#include <math.h>
+
+#include <algorithm>
+#include <string>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+// Parameters for linear least squares fit of regression line to noisy data.
+constexpr double kDefaultTrendlineSmoothingCoeff = 0.9;
+constexpr double kDefaultTrendlineThresholdGain = 4.0;
+// const char kBweWindowSizeInPacketsExperiment[] =
+// "WebRTC-BweWindowSizeInPackets";
+
+/*size_t ReadTrendlineFilterWindowSize(
+ const WebRtcKeyValueConfig* key_value_config) {
+ std::string experiment_string =
+ key_value_config->Lookup(kBweWindowSizeInPacketsExperiment);
+ size_t window_size;
+ int parsed_values =
+ sscanf(experiment_string.c_str(), "Enabled-%zu", &window_size);
+ if (parsed_values == 1) {
+ if (window_size > 1)
+ return window_size;
+ RTC_LOG(WARNING) << "Window size must be greater than 1.";
+ }
+ RTC_LOG(LS_WARNING) << "Failed to parse parameters for BweWindowSizeInPackets"
+ " experiment from field trial string. Using default.";
+ return TrendlineEstimatorSettings::kDefaultTrendlineWindowSize;
+}
+*/
+
+OptionalDouble LinearFitSlope(
+ const std::deque<TrendlineEstimator::PacketTiming>& packets) {
+ // RTC_DCHECK(packets.size() >= 2);
+ // Compute the "center of mass".
+ double sum_x = 0;
+ double sum_y = 0;
+ for (const auto& packet : packets) {
+ sum_x += packet.arrival_time_ms;
+ sum_y += packet.smoothed_delay_ms;
+ }
+ double x_avg = sum_x / packets.size();
+ double y_avg = sum_y / packets.size();
+ // Compute the slope k = \sum (x_i-x_avg)(y_i-y_avg) / \sum (x_i-x_avg)^2
+ double numerator = 0;
+ double denominator = 0;
+ for (const auto& packet : packets) {
+ double x = packet.arrival_time_ms;
+ double y = packet.smoothed_delay_ms;
+ numerator += (x - x_avg) * (y - y_avg);
+ denominator += (x - x_avg) * (x - x_avg);
+ }
+ if (denominator == 0) return OptionalDouble();
+ return OptionalDouble(numerator / denominator);
+}
+
+OptionalDouble ComputeSlopeCap(
+ const std::deque<TrendlineEstimator::PacketTiming>& packets,
+ const TrendlineEstimatorSettings& settings) {
+ /*RTC_DCHECK(1 <= settings.beginning_packets &&
+ settings.beginning_packets < packets.size());
+ RTC_DCHECK(1 <= settings.end_packets &&
+ settings.end_packets < packets.size());
+ RTC_DCHECK(settings.beginning_packets + settings.end_packets <=
+ packets.size());*/
+ TrendlineEstimator::PacketTiming early = packets[0];
+ for (size_t i = 1; i < settings.beginning_packets; ++i) {
+ if (packets[i].raw_delay_ms < early.raw_delay_ms) early = packets[i];
+ }
+ size_t late_start = packets.size() - settings.end_packets;
+ TrendlineEstimator::PacketTiming late = packets[late_start];
+ for (size_t i = late_start + 1; i < packets.size(); ++i) {
+ if (packets[i].raw_delay_ms < late.raw_delay_ms) late = packets[i];
+ }
+ if (late.arrival_time_ms - early.arrival_time_ms < 1) {
+ return OptionalDouble();
+ }
+ return OptionalDouble((late.raw_delay_ms - early.raw_delay_ms) /
+ (late.arrival_time_ms - early.arrival_time_ms) +
+ settings.cap_uncertainty);
+}
+
+constexpr double kMaxAdaptOffsetMs = 15.0;
+constexpr double kOverUsingTimeThreshold = 10;
+constexpr int kMinNumDeltas = 60;
+constexpr int kDeltaCounterMax = 1000;
+
+//} // namespace
+
+constexpr char TrendlineEstimatorSettings::kKey[];
+
+TrendlineEstimatorSettings::TrendlineEstimatorSettings(
+ /*const WebRtcKeyValueConfig* key_value_config*/) {
+ /*if (absl::StartsWith(
+ key_value_config->Lookup(kBweWindowSizeInPacketsExperiment),
+ "Enabled")) {
+ window_size = ReadTrendlineFilterWindowSize(key_value_config);
+ }
+ Parser()->Parse(key_value_config->Lookup(TrendlineEstimatorSettings::kKey));*/
+ window_size = kDefaultTrendlineWindowSize;
+ enable_cap = false;
+ beginning_packets = end_packets = 0;
+ cap_uncertainty = 0.0;
+
+ /*if (window_size < 10 || 200 < window_size) {
+ RTC_LOG(LS_WARNING) << "Window size must be between 10 and 200 packets";
+ window_size = kDefaultTrendlineWindowSize;
+ }
+ if (enable_cap) {
+ if (beginning_packets < 1 || end_packets < 1 ||
+ beginning_packets > window_size || end_packets > window_size) {
+ RTC_LOG(LS_WARNING) << "Size of beginning and end must be between 1 and "
+ << window_size;
+ enable_cap = false;
+ beginning_packets = end_packets = 0;
+ cap_uncertainty = 0.0;
+ }
+ if (beginning_packets + end_packets > window_size) {
+ RTC_LOG(LS_WARNING)
+ << "Size of beginning plus end can't exceed the window size";
+ enable_cap = false;
+ beginning_packets = end_packets = 0;
+ cap_uncertainty = 0.0;
+ }
+ if (cap_uncertainty < 0.0 || 0.025 < cap_uncertainty) {
+ RTC_LOG(LS_WARNING) << "Cap uncertainty must be between 0 and 0.025";
+ cap_uncertainty = 0.0;
+ }
+ }*/
+}
+
+/*std::unique_ptr<StructParametersParser> TrendlineEstimatorSettings::Parser() {
+ return StructParametersParser::Create("sort", &enable_sort, //
+ "cap", &enable_cap, //
+ "beginning_packets",
+ &beginning_packets, //
+ "end_packets", &end_packets, //
+ "cap_uncertainty", &cap_uncertainty, //
+ "window_size", &window_size);
+}*/
+
+TrendlineEstimator::TrendlineEstimator(
+ /*const WebRtcKeyValueConfig* key_value_config,
+ NetworkStatePredictor* network_state_predictor*/)
+ : settings_(),
+ smoothing_coef_(kDefaultTrendlineSmoothingCoeff),
+ threshold_gain_(kDefaultTrendlineThresholdGain),
+ num_of_deltas_(0),
+ first_arrival_time_ms_(-1),
+ accumulated_delay_(0),
+ smoothed_delay_(0),
+ delay_hist_(),
+ k_up_(0.0087),
+ k_down_(0.039),
+ overusing_time_threshold_(kOverUsingTimeThreshold),
+ threshold_(12.5),
+ prev_modified_trend_(NAN),
+ last_update_ms_(-1),
+ prev_trend_(0.0),
+ time_over_using_(-1),
+ overuse_counter_(0),
+ hypothesis_(BandwidthUsage::kBwNormal){
+ // hypothesis_predicted_(BandwidthUsage::kBwNormal){//},
+ // network_state_predictor_(network_state_predictor) {
+ /* RTC_LOG(LS_INFO)
+ << "Using Trendline filter for delay change estimation with settings "
+ << settings_.Parser()->Encode() << " and "
+ // << (network_state_predictor_ ? "injected" : "no")
+ << " network state predictor";*/
+}
+
+TrendlineEstimator::~TrendlineEstimator() {}
+
+void TrendlineEstimator::UpdateTrendline(double recv_delta_ms,
+ double send_delta_ms,
+ int64_t send_time_ms,
+ int64_t arrival_time_ms,
+ size_t packet_size) {
+ const double delta_ms = recv_delta_ms - send_delta_ms;
+ ++num_of_deltas_;
+ num_of_deltas_ = std::min(num_of_deltas_, kDeltaCounterMax);
+ if (first_arrival_time_ms_ == -1) first_arrival_time_ms_ = arrival_time_ms;
+
+ // Exponential backoff filter.
+ accumulated_delay_ += delta_ms;
+ // BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms,
+ // accumulated_delay_);
+ smoothed_delay_ = smoothing_coef_ * smoothed_delay_ +
+ (1 - smoothing_coef_) * accumulated_delay_;
+ // BWE_TEST_LOGGING_PLOT(1, "smoothed_delay_ms", arrival_time_ms,
+ // smoothed_delay_);
+
+ // Maintain packet window
+ delay_hist_.emplace_back(
+ static_cast<double>(arrival_time_ms - first_arrival_time_ms_),
+ smoothed_delay_, accumulated_delay_);
+ if (settings_.enable_sort) {
+ for (size_t i = delay_hist_.size() - 1;
+ i > 0 &&
+ delay_hist_[i].arrival_time_ms < delay_hist_[i - 1].arrival_time_ms;
+ --i) {
+ std::swap(delay_hist_[i], delay_hist_[i - 1]);
+ }
+ }
+ if (delay_hist_.size() > settings_.window_size) delay_hist_.pop_front();
+
+ // Simple linear regression.
+ double trend = prev_trend_;
+ if (delay_hist_.size() == settings_.window_size) {
+ // Update trend_ if it is possible to fit a line to the data. The delay
+ // trend can be seen as an estimate of (send_rate - capacity)/capacity.
+ // 0 < trend < 1 -> the delay increases, queues are filling up
+ // trend == 0 -> the delay does not change
+ // trend < 0 -> the delay decreases, queues are being emptied
+ OptionalDouble trendO = LinearFitSlope(delay_hist_);
+ if (trendO.has_value()) trend = trendO.value();
+ if (settings_.enable_cap) {
+ OptionalDouble cap = ComputeSlopeCap(delay_hist_, settings_);
+ // We only use the cap to filter out overuse detections, not
+ // to detect additional underuses.
+ if (trend >= 0 && cap.has_value() && trend > cap.value()) {
+ trend = cap.value();
+ }
+ }
+ }
+ // BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trend);
+
+ Detect(trend, send_delta_ms, arrival_time_ms);
+}
+
+void TrendlineEstimator::Update(double recv_delta_ms, double send_delta_ms,
+ int64_t send_time_ms, int64_t arrival_time_ms,
+ size_t packet_size, bool calculated_deltas) {
+ if (calculated_deltas) {
+ UpdateTrendline(recv_delta_ms, send_delta_ms, send_time_ms, arrival_time_ms,
+ packet_size);
+ }
+ /*if (network_state_predictor_) {
+ hypothesis_predicted_ = network_state_predictor_->Update(
+ send_time_ms, arrival_time_ms, hypothesis_);
+ }*/
+}
+
+BandwidthUsage TrendlineEstimator::State() const {
+ return /*network_state_predictor_ ? hypothesis_predicted_ :*/ hypothesis_;
+}
+
+void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) {
+ /*if (num_of_deltas_ < 2) {
+ hypothesis_ = BandwidthUsage::kBwNormal;
+ return;
+ }*/
+
+ const double modified_trend =
+ std::min(num_of_deltas_, kMinNumDeltas) * trend * threshold_gain_;
+ prev_modified_trend_ = modified_trend;
+ // BWE_TEST_LOGGING_PLOT(1, "T", now_ms, modified_trend);
+ // BWE_TEST_LOGGING_PLOT(1, "threshold", now_ms, threshold_);
+ if (modified_trend > threshold_) {
+ if (time_over_using_ == -1) {
+ // Initialize the timer. Assume that we've been
+ // over-using half of the time since the previous
+ // sample.
+ time_over_using_ = ts_delta / 2;
+ } else {
+ // Increment timer
+ time_over_using_ += ts_delta;
+ }
+ overuse_counter_++;
+ if (time_over_using_ > overusing_time_threshold_ && overuse_counter_ > 1) {
+ if (trend >= prev_trend_) {
+ time_over_using_ = 0;
+ overuse_counter_ = 0;
+ hypothesis_ = BandwidthUsage::kBwOverusing;
+ }
+ }
+ } else if (modified_trend < -threshold_) {
+ time_over_using_ = -1;
+ overuse_counter_ = 0;
+ hypothesis_ = BandwidthUsage::kBwUnderusing;
+ } else {
+ time_over_using_ = -1;
+ overuse_counter_ = 0;
+ hypothesis_ = BandwidthUsage::kBwNormal;
+ }
+ prev_trend_ = trend;
+ UpdateThreshold(modified_trend, now_ms);
+}
+
+void TrendlineEstimator::UpdateThreshold(double modified_trend,
+ int64_t now_ms) {
+ if (last_update_ms_ == -1) last_update_ms_ = now_ms;
+
+ if (fabs(modified_trend) > threshold_ + kMaxAdaptOffsetMs) {
+ // Avoid adapting the threshold to big latency spikes, caused e.g.,
+ // by a sudden capacity drop.
+ last_update_ms_ = now_ms;
+ return;
+ }
+
+ const double k = fabs(modified_trend) < threshold_ ? k_down_ : k_up_;
+ const int64_t kMaxTimeDeltaMs = 100;
+ int64_t time_delta_ms = std::min(now_ms - last_update_ms_, kMaxTimeDeltaMs);
+ threshold_ += k * (fabs(modified_trend) - threshold_) * time_delta_ms;
+ if (threshold_ < 6.f) threshold_ = 6.f;
+ if (threshold_ > 600.f) threshold_ = 600.f;
+ // threshold_ = rtc::SafeClamp(threshold_, 6.f, 600.f);
+ last_update_ms_ = now_ms;
+}
+
+} // namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/rtc/trendline_estimator.h b/libtransport/src/protocols/rtc/trendline_estimator.h
new file mode 100644
index 000000000..372acbc67
--- /dev/null
+++ b/libtransport/src/protocols/rtc/trendline_estimator.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// FROM
+// https://source.chromium.org/chromium/chromium/src/+/master:third_party/webrtc/modules/congestion_controller/goog_cc/trendline_estimator.h
+
+#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_TRENDLINE_ESTIMATOR_H_
+#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_TRENDLINE_ESTIMATOR_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <deque>
+#include <memory>
+#include <utility>
+
+namespace transport {
+
+namespace protocol {
+
+namespace rtc {
+
+class OptionalDouble {
+ public:
+ OptionalDouble() : val(0), has_val(false){};
+ OptionalDouble(double val) : val(val), has_val(true){};
+
+ double value() { return val; }
+ bool has_value() { return has_val; }
+
+ private:
+ double val;
+ bool has_val;
+};
+
+enum class BandwidthUsage {
+ kBwNormal = 0,
+ kBwUnderusing = 1,
+ kBwOverusing = 2,
+ kLast
+};
+
+struct TrendlineEstimatorSettings {
+ static constexpr char kKey[] = "WebRTC-Bwe-TrendlineEstimatorSettings";
+ static constexpr unsigned kDefaultTrendlineWindowSize = 20;
+
+ // TrendlineEstimatorSettings() = delete;
+ TrendlineEstimatorSettings(
+ /*const WebRtcKeyValueConfig* key_value_config*/);
+
+ // Sort the packets in the window. Should be redundant,
+ // but then almost no cost.
+ bool enable_sort = false;
+
+ // Cap the trendline slope based on the minimum delay seen
+ // in the beginning_packets and end_packets respectively.
+ bool enable_cap = false;
+ unsigned beginning_packets = 7;
+ unsigned end_packets = 7;
+ double cap_uncertainty = 0.0;
+
+ // Size (in packets) of the window.
+ unsigned window_size = kDefaultTrendlineWindowSize;
+
+ // std::unique_ptr<StructParametersParser> Parser();
+};
+
+class TrendlineEstimator /*: public DelayIncreaseDetectorInterface */ {
+ public:
+ TrendlineEstimator(/*const WebRtcKeyValueConfig* key_value_config,
+ NetworkStatePredictor* network_state_predictor*/);
+
+ ~TrendlineEstimator();
+
+ // Update the estimator with a new sample. The deltas should represent deltas
+ // between timestamp groups as defined by the InterArrival class.
+ void Update(double recv_delta_ms, double send_delta_ms, int64_t send_time_ms,
+ int64_t arrival_time_ms, size_t packet_size,
+ bool calculated_deltas);
+
+ void UpdateTrendline(double recv_delta_ms, double send_delta_ms,
+ int64_t send_time_ms, int64_t arrival_time_ms,
+ size_t packet_size);
+
+ BandwidthUsage State() const;
+
+ struct PacketTiming {
+ PacketTiming(double arrival_time_ms, double smoothed_delay_ms,
+ double raw_delay_ms)
+ : arrival_time_ms(arrival_time_ms),
+ smoothed_delay_ms(smoothed_delay_ms),
+ raw_delay_ms(raw_delay_ms) {}
+ double arrival_time_ms;
+ double smoothed_delay_ms;
+ double raw_delay_ms;
+ };
+
+ private:
+ // friend class GoogCcStatePrinter;
+ void Detect(double trend, double ts_delta, int64_t now_ms);
+
+ void UpdateThreshold(double modified_offset, int64_t now_ms);
+
+ // Parameters.
+ TrendlineEstimatorSettings settings_;
+ const double smoothing_coef_;
+ const double threshold_gain_;
+ // Used by the existing threshold.
+ int num_of_deltas_;
+ // Keep the arrival times small by using the change from the first packet.
+ int64_t first_arrival_time_ms_;
+ // Exponential backoff filtering.
+ double accumulated_delay_;
+ double smoothed_delay_;
+ // Linear least squares regression.
+ std::deque<PacketTiming> delay_hist_;
+
+ const double k_up_;
+ const double k_down_;
+ double overusing_time_threshold_;
+ double threshold_;
+ double prev_modified_trend_;
+ int64_t last_update_ms_;
+ double prev_trend_;
+ double time_over_using_;
+ int overuse_counter_;
+ BandwidthUsage hypothesis_;
+ // BandwidthUsage hypothesis_predicted_;
+ // NetworkStatePredictor* network_state_predictor_;
+
+ // RTC_DISALLOW_COPY_AND_ASSIGN(TrendlineEstimator);
+};
+
+} // namespace rtc
+
+} // end namespace protocol
+
+} // end namespace transport
+#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_TRENDLINE_ESTIMATOR_H_
diff --git a/libtransport/src/protocols/test/CMakeLists.txt b/libtransport/src/protocols/test/CMakeLists.txt
deleted file mode 100644
index 6f9fdb9aa..000000000
--- a/libtransport/src/protocols/test/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-# Enable gcov output for the tests
-add_definitions(--coverage)
-set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} " --coverage")
-
-set(TestsExpectedToPass
- test_transport_producer)
-
-foreach(test ${TestsExpectedToPass})
- AddTest(${test})
-endforeach() \ No newline at end of file
diff --git a/libtransport/src/protocols/transport_protocol.cc b/libtransport/src/protocols/transport_protocol.cc
new file mode 100644
index 000000000..611c39212
--- /dev/null
+++ b/libtransport/src/protocols/transport_protocol.cc
@@ -0,0 +1,132 @@
+/*
+ * 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 <hicn/transport/interfaces/socket_consumer.h>
+#include <implementation/socket_consumer.h>
+#include <protocols/transport_protocol.h>
+
+namespace transport {
+
+namespace protocol {
+
+using namespace interface;
+
+TransportProtocol::TransportProtocol(implementation::ConsumerSocket *icn_socket,
+ Reassembly *reassembly_protocol)
+ : socket_(icn_socket),
+ reassembly_protocol_(reassembly_protocol),
+ index_manager_(
+ std::make_unique<IndexManager>(socket_, this, reassembly_protocol)),
+ is_running_(false),
+ is_first_(false),
+ on_interest_retransmission_(VOID_HANDLER),
+ on_interest_output_(VOID_HANDLER),
+ on_interest_timeout_(VOID_HANDLER),
+ on_interest_satisfied_(VOID_HANDLER),
+ on_content_object_input_(VOID_HANDLER),
+ stats_summary_(VOID_HANDLER),
+ on_payload_(VOID_HANDLER) {
+ socket_->getSocketOption(GeneralTransportOptions::PORTAL, portal_);
+ socket_->getSocketOption(OtherOptions::STATISTICS, &stats_);
+}
+
+int TransportProtocol::start() {
+ // If the protocol is already running, return otherwise set as running
+ if (is_running_) return -1;
+
+ // Get all callbacks references
+ socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_RETRANSMISSION,
+ &on_interest_retransmission_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_OUTPUT,
+ &on_interest_output_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_EXPIRED,
+ &on_interest_timeout_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::INTEREST_SATISFIED,
+ &on_interest_satisfied_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::CONTENT_OBJECT_INPUT,
+ &on_content_object_input_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::STATS_SUMMARY,
+ &stats_summary_);
+ socket_->getSocketOption(ConsumerCallbacksOptions::READ_CALLBACK,
+ &on_payload_);
+
+ socket_->getSocketOption(GeneralTransportOptions::ASYNC_MODE, is_async_);
+
+ // Set it is the first time we schedule an interest
+ is_first_ = true;
+
+ // Reset the protocol state machine
+ reset();
+ // Schedule next interests
+ scheduleNextInterests();
+
+ is_first_ = false;
+
+ // Set the protocol as running
+ is_running_ = true;
+
+ if (!is_async_) {
+ // Start Event loop
+ portal_->runEventsLoop();
+
+ // Not running anymore
+ is_running_ = false;
+ }
+
+ return 0;
+}
+
+void TransportProtocol::stop() {
+ is_running_ = false;
+
+ if (!is_async_) {
+ portal_->stopEventsLoop();
+ } else {
+ portal_->clear();
+ }
+}
+
+void TransportProtocol::resume() {
+ if (is_running_) return;
+
+ is_running_ = true;
+
+ scheduleNextInterests();
+
+ portal_->runEventsLoop();
+
+ is_running_ = false;
+}
+
+void TransportProtocol::onContentReassembled(std::error_code ec) {
+ stop();
+
+ if (!on_payload_) {
+ throw errors::RuntimeException(
+ "The read callback must be installed in the transport before "
+ "starting "
+ "the content retrieval.");
+ }
+
+ if (!ec) {
+ on_payload_->readSuccess(stats_->getBytesRecv());
+ } else {
+ on_payload_->readError(ec);
+ }
+}
+
+} // end namespace protocol
+
+} // end namespace transport
diff --git a/libtransport/src/protocols/transport_protocol.h b/libtransport/src/protocols/transport_protocol.h
new file mode 100644
index 000000000..124c57122
--- /dev/null
+++ b/libtransport/src/protocols/transport_protocol.h
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <hicn/transport/interfaces/callbacks.h>
+#include <hicn/transport/interfaces/socket_consumer.h>
+#include <hicn/transport/interfaces/statistics.h>
+#include <hicn/transport/utils/object_pool.h>
+#include <implementation/socket.h>
+#include <protocols/data_processing_events.h>
+#include <protocols/indexer.h>
+#include <protocols/reassembly.h>
+
+#include <atomic>
+
+namespace transport {
+
+namespace protocol {
+
+using namespace core;
+
+class IndexVerificationManager;
+
+using ReadCallback = interface::ConsumerSocket::ReadCallback;
+
+class TransportProtocolCallback {
+ virtual void onContentObject(const core::Interest &interest,
+ const core::ContentObject &content_object) = 0;
+ virtual void onTimeout(const core::Interest &interest) = 0;
+};
+
+class TransportProtocol : public core::Portal::ConsumerCallback,
+ public ContentObjectProcessingEventCallback {
+ static constexpr std::size_t interest_pool_size = 4096;
+
+ friend class ManifestIndexManager;
+
+ public:
+ TransportProtocol(implementation::ConsumerSocket *icn_socket,
+ Reassembly *reassembly_protocol);
+
+ virtual ~TransportProtocol() = default;
+
+ TRANSPORT_ALWAYS_INLINE bool isRunning() { return is_running_; }
+
+ virtual int start();
+
+ virtual void stop();
+
+ virtual void resume();
+
+ virtual void scheduleNextInterests() = 0;
+
+ // Events generated by the indexing
+ virtual void onContentReassembled(std::error_code ec);
+ virtual void onPacketDropped(Interest &interest,
+ ContentObject &content_object) override = 0;
+ virtual void onReassemblyFailed(std::uint32_t missing_segment) override = 0;
+
+ protected:
+ // Consumer Callback
+ virtual void reset() = 0;
+ virtual void onContentObject(Interest &i, ContentObject &c) override = 0;
+ virtual void onTimeout(Interest::Ptr &&i) override = 0;
+ virtual void onError(std::error_code ec) override {}
+
+ protected:
+ implementation::ConsumerSocket *socket_;
+ std::unique_ptr<Reassembly> reassembly_protocol_;
+ std::unique_ptr<IndexManager> index_manager_;
+ std::shared_ptr<core::Portal> portal_;
+ std::atomic<bool> is_running_;
+ // True if it si the first time we schedule an interest
+ std::atomic<bool> is_first_;
+ interface::TransportStatistics *stats_;
+
+ // Callbacks
+ interface::ConsumerInterestCallback *on_interest_retransmission_;
+ interface::ConsumerInterestCallback *on_interest_output_;
+ interface::ConsumerInterestCallback *on_interest_timeout_;
+ interface::ConsumerInterestCallback *on_interest_satisfied_;
+ interface::ConsumerContentObjectCallback *on_content_object_input_;
+ interface::ConsumerContentObjectCallback *on_content_object_;
+ interface::ConsumerTimerCallback *stats_summary_;
+ ReadCallback *on_payload_;
+
+ bool is_async_;
+};
+
+} // end namespace protocol
+} // end namespace transport
diff --git a/libtransport/src/security/verifier.cc b/libtransport/src/security/verifier.cc
index 39b815d40..4f6a2be4c 100644
--- a/libtransport/src/security/verifier.cc
+++ b/libtransport/src/security/verifier.cc
@@ -41,6 +41,7 @@ Verifier::Verifier() {
PARCInMemoryVerifier *in_memory_verifier = parcInMemoryVerifier_Create();
this->verifier_ =
parcVerifier_Create(in_memory_verifier, PARCInMemoryVerifierAsVerifier);
+ parcInMemoryVerifier_Release(&in_memory_verifier);
}
Verifier::~Verifier() {
diff --git a/libtransport/src/test/CMakeLists.txt b/libtransport/src/test/CMakeLists.txt
new file mode 100644
index 000000000..dd3d1d923
--- /dev/null
+++ b/libtransport/src/test/CMakeLists.txt
@@ -0,0 +1,39 @@
+# Copyright (c) 2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+include(BuildMacros)
+
+list(APPEND TESTS
+ test_auth
+ test_consumer_producer_rtc
+ test_core_manifest
+ test_event_thread
+ test_fec_reedsolomon
+ test_interest
+ test_packet
+)
+
+foreach(test ${TESTS})
+ build_executable(${test}
+ NO_INSTALL
+ SOURCES ${test}.cc
+ LINK_LIBRARIES ${LIBTRANSPORT_SHARED} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
+ INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
+ DEPENDS gtest ${LIBTRANSPORT_SHARED}
+ COMPONENT lib${LIBTRANSPORT}
+ DEFINITIONS "${COMPILER_DEFINITIONS}"
+ LINK_FLAGS ${LINK_FLAGS}
+ )
+
+ add_test_internal(${test})
+endforeach()
diff --git a/libtransport/src/test/fec_reed_solomon.cc b/libtransport/src/test/fec_reed_solomon.cc
new file mode 100644
index 000000000..36543c531
--- /dev/null
+++ b/libtransport/src/test/fec_reed_solomon.cc
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <hicn/transport/interfaces/socket_consumer.h>
+#include <hicn/transport/interfaces/socket_options_keys.h>
+#include <hicn/transport/interfaces/socket_producer.h>
+#include <hicn/transport/interfaces/global_conf_interface.h>
+
+#include <asio/io_service.hpp>
+#include <asio/steady_timer.hpp>
+#include <fec/rs.h>
+
+namespace transport {
+namespace interface {
+
+namespace {
+
+class ConsumerProducerTest : public ::testing::Test,
+ public ConsumerSocket::ReadCallback {
+ static const constexpr char prefix[] = "b001::1/128";
+ static const constexpr char name[] = "b001::1";
+ static const constexpr double prod_rate = 1.0e6;
+ static const constexpr size_t payload_size = 1200;
+ static constexpr std::size_t receive_buffer_size = 1500;
+ static const constexpr double prod_interval_microseconds =
+ double(payload_size) * 8 * 1e6 / prod_rate;
+
+ public:
+ ConsumerProducerTest()
+ : io_service_(),
+ rtc_timer_(io_service_),
+ consumer_(TransportProtocolAlgorithms::RTC, io_service_),
+ producer_(ProductionProtocolAlgorithms::RTC_PROD, io_service_),
+ producer_prefix_(prefix),
+ consumer_name_(name),
+ packets_sent_(0),
+ packets_received_(0) {
+ global_config::IoModuleConfiguration config;
+ config.name = "loopback_module";
+ config.set();
+ }
+
+ virtual ~ConsumerProducerTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() override {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+
+ auto ret = consumer_.setSocketOption(
+ ConsumerCallbacksOptions::READ_CALLBACK, this);
+ ASSERT_EQ(ret, SOCKET_OPTION_SET);
+
+ consumer_.connect();
+ producer_.registerPrefix(producer_prefix_);
+ producer_.connect();
+ }
+
+ virtual void TearDown() override {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ void setTimer() {
+ using namespace std::chrono;
+ rtc_timer_.expires_from_now(
+ microseconds(unsigned(prod_interval_microseconds)));
+ rtc_timer_.async_wait(std::bind(&ConsumerProducerTest::produceRTCPacket,
+ this, std::placeholders::_1));
+ }
+
+ void produceRTCPacket(const std::error_code &ec) {
+ if (ec) {
+ FAIL() << "Failed to schedule packet production";
+ io_service_.stop();
+ }
+
+ producer_.produceDatagram(consumer_name_, payload_, payload_size);
+ packets_sent_++;
+ setTimer();
+ }
+
+ // Consumer callback
+ bool isBufferMovable() noexcept override { return false; }
+
+ void getReadBuffer(uint8_t **application_buffer,
+ size_t *max_length) override {
+ *application_buffer = receive_buffer_;
+ *max_length = receive_buffer_size;
+ }
+
+ void readDataAvailable(std::size_t length) noexcept override {}
+
+ size_t maxBufferSize() const override { return receive_buffer_size; }
+
+ void readError(const std::error_code ec) noexcept override {
+ FAIL() << "Error while reading from RTC socket";
+ io_service_.stop();
+ }
+
+ void readSuccess(std::size_t total_size) noexcept override {
+ packets_received_++;
+ }
+
+ asio::io_service io_service_;
+ asio::steady_timer rtc_timer_;
+ ConsumerSocket consumer_;
+ ProducerSocket producer_;
+ core::Prefix producer_prefix_;
+ core::Name consumer_name_;
+ uint8_t payload_[payload_size];
+ uint8_t receive_buffer_[payload_size];
+
+ uint64_t packets_sent_;
+ uint64_t packets_received_;
+};
+
+const char ConsumerProducerTest::prefix[];
+const char ConsumerProducerTest::name[];
+
+} // namespace
+
+TEST_F(ConsumerProducerTest, EndToEnd) {
+ produceRTCPacket(std::error_code());
+ consumer_.consume(consumer_name_);
+
+ io_service_.run();
+}
+
+} // namespace interface
+
+} // namespace transport
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+} \ No newline at end of file
diff --git a/libtransport/src/test/fec_rely.cc b/libtransport/src/test/fec_rely.cc
new file mode 100644
index 000000000..e7745bae5
--- /dev/null
+++ b/libtransport/src/test/fec_rely.cc
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <hicn/transport/interfaces/socket_consumer.h>
+#include <hicn/transport/interfaces/socket_options_keys.h>
+#include <hicn/transport/interfaces/socket_producer.h>
+#include <hicn/transport/interfaces/global_conf_interface.h>
+
+#include <asio/io_service.hpp>
+#include <asio/steady_timer.hpp>
+
+#include <rely/encoder.hpp>
+#include <rely/decoder.hpp>
+
+namespace transport {
+namespace interface {
+
+namespace {
+
+class ConsumerProducerTest : public ::testing::Test,
+ public ConsumerSocket::ReadCallback {
+ static const constexpr char prefix[] = "b001::1/128";
+ static const constexpr char name[] = "b001::1";
+ static const constexpr double prod_rate = 1.0e6;
+ static const constexpr size_t payload_size = 1200;
+ static constexpr std::size_t receive_buffer_size = 1500;
+ static const constexpr double prod_interval_microseconds =
+ double(payload_size) * 8 * 1e6 / prod_rate;
+
+ public:
+ ConsumerProducerTest()
+ : io_service_(),
+ rtc_timer_(io_service_),
+ consumer_(TransportProtocolAlgorithms::RTC, io_service_),
+ producer_(ProductionProtocolAlgorithms::RTC_PROD, io_service_),
+ producer_prefix_(prefix),
+ consumer_name_(name),
+ packets_sent_(0),
+ packets_received_(0) {
+ global_config::IoModuleConfiguration config;
+ config.name = "loopback_module";
+ config.set();
+ }
+
+ virtual ~ConsumerProducerTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() override {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+
+ auto ret = consumer_.setSocketOption(
+ ConsumerCallbacksOptions::READ_CALLBACK, this);
+ ASSERT_EQ(ret, SOCKET_OPTION_SET);
+
+ consumer_.connect();
+ producer_.registerPrefix(producer_prefix_);
+ producer_.connect();
+ }
+
+ virtual void TearDown() override {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ void setTimer() {
+ using namespace std::chrono;
+ rtc_timer_.expires_from_now(
+ microseconds(unsigned(prod_interval_microseconds)));
+ rtc_timer_.async_wait(std::bind(&ConsumerProducerTest::produceRTCPacket,
+ this, std::placeholders::_1));
+ }
+
+ void produceRTCPacket(const std::error_code &ec) {
+ if (ec) {
+ FAIL() << "Failed to schedule packet production";
+ io_service_.stop();
+ }
+
+ producer_.produceDatagram(consumer_name_, payload_, payload_size);
+ packets_sent_++;
+ setTimer();
+ }
+
+ // Consumer callback
+ bool isBufferMovable() noexcept override { return false; }
+
+ void getReadBuffer(uint8_t **application_buffer,
+ size_t *max_length) override {
+ *application_buffer = receive_buffer_;
+ *max_length = receive_buffer_size;
+ }
+
+ void readDataAvailable(std::size_t length) noexcept override {}
+
+ size_t maxBufferSize() const override { return receive_buffer_size; }
+
+ void readError(const std::error_code ec) noexcept override {
+ FAIL() << "Error while reading from RTC socket";
+ io_service_.stop();
+ }
+
+ void readSuccess(std::size_t total_size) noexcept override {
+ packets_received_++;
+ }
+
+ asio::io_service io_service_;
+ asio::steady_timer rtc_timer_;
+ ConsumerSocket consumer_;
+ ProducerSocket producer_;
+ core::Prefix producer_prefix_;
+ core::Name consumer_name_;
+ uint8_t payload_[payload_size];
+ uint8_t receive_buffer_[payload_size];
+
+ uint64_t packets_sent_;
+ uint64_t packets_received_;
+};
+
+const char ConsumerProducerTest::prefix[];
+const char ConsumerProducerTest::name[];
+
+} // namespace
+
+TEST_F(ConsumerProducerTest, EndToEnd) {
+ produceRTCPacket(std::error_code());
+ consumer_.consume(consumer_name_);
+
+ io_service_.run();
+}
+
+} // namespace interface
+
+} // namespace transport
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+} \ No newline at end of file
diff --git a/libtransport/src/test/packet_samples.h b/libtransport/src/test/packet_samples.h
new file mode 100644
index 000000000..e98d06a18
--- /dev/null
+++ b/libtransport/src/test/packet_samples.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define TCP_PROTO 0x06
+#define ICMP_PROTO 0x01
+#define ICMP6_PROTO 0x3a
+
+#define IPV6_HEADER(next_header, payload_length) \
+ 0x60, 0x00, 0x00, 0x00, 0x00, payload_length, next_header, 0x40, 0xb0, 0x06, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xcd, 0xab, \
+ 0xcd, 0xef, 0xb0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xca
+
+#define IPV4_HEADER(next_header, payload_length) \
+ 0x45, 0x02, 0x00, payload_length + 20, 0x47, 0xc4, 0x40, 0x00, 0x25, \
+ next_header, 0x6e, 0x76, 0x03, 0x7b, 0xd9, 0xd0, 0xc0, 0xa8, 0x01, 0x5c
+
+#define TCP_HEADER(flags) \
+ 0x12, 0x34, 0x43, 0x21, 0x00, 0x00, 0x00, 0x01, 0xb2, 0x8c, 0x03, 0x1f, \
+ 0x80, flags, 0x00, 0x0a, 0xb9, 0xbb, 0x00, 0x00
+
+#define PAYLOAD \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x20, 0x00, 0x00
+
+#define PAYLOAD_SIZE 12
+
+#define ICMP_ECHO_REQUEST \
+ 0x08, 0x00, 0x87, 0xdb, 0x38, 0xa7, 0x00, 0x05, 0x60, 0x2b, 0xc2, 0xcb, \
+ 0x00, 0x02, 0x29, 0x7c, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, \
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, \
+ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, \
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, \
+ 0x34, 0x35, 0x36, 0x37
+
+#define ICMP6_ECHO_REQUEST \
+ 0x80, 0x00, 0x86, 0x3c, 0x11, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, \
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, \
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, \
+ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, \
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
+
+#define AH_HEADER \
+ 0x00, (128 >> 2), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
diff --git a/libtransport/src/test/test_auth.cc b/libtransport/src/test/test_auth.cc
new file mode 100644
index 000000000..976981cce
--- /dev/null
+++ b/libtransport/src/test/test_auth.cc
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <hicn/transport/auth/crypto_hash_type.h>
+#include <hicn/transport/auth/identity.h>
+#include <hicn/transport/auth/signer.h>
+#include <hicn/transport/auth/verifier.h>
+#include <hicn/transport/core/content_object.h>
+
+namespace transport {
+namespace auth {
+
+namespace {
+class AuthTest : public ::testing::Test {
+ protected:
+ const std::string PASSPHRASE = "hunter2";
+
+ AuthTest() = default;
+ ~AuthTest() {}
+ void SetUp() override {}
+ void TearDown() override {}
+};
+} // namespace
+
+TEST_F(AuthTest, VoidVerifier) {
+ // Create a content object
+ core::ContentObject packet(HF_INET6_TCP_AH);
+
+ // Fill it with bogus data
+ uint8_t buffer[256] = {0};
+ packet.appendPayload(buffer, 256);
+
+ // Verify that VoidVerifier validates the packet
+ std::shared_ptr<Verifier> verifier = std::make_shared<VoidVerifier>();
+ ASSERT_EQ(verifier->verifyPacket(&packet), true);
+ ASSERT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT);
+}
+
+TEST_F(AuthTest, RSAVerifier) {
+ // Create the RSA signer from an Identity object
+ Identity identity("test_rsa.p12", PASSPHRASE, CryptoSuite::RSA_SHA256, 1024u,
+ 30, "RSAVerifier");
+ std::shared_ptr<Signer> signer = identity.getSigner();
+
+ // Create a content object
+ core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize());
+
+ // Fill it with bogus data
+ uint8_t buffer[256] = {0};
+ packet.appendPayload(buffer, 256);
+
+ // Sign the packet
+ signer->signPacket(&packet);
+
+ // Create the RSA verifier
+ PARCKey *key = parcSigner_CreatePublicKey(signer->getParcSigner());
+ std::shared_ptr<Verifier> verifier =
+ std::make_shared<AsymmetricVerifier>(key);
+
+ ASSERT_EQ(packet.getFormat(), HF_INET6_TCP_AH);
+ ASSERT_EQ(signer->getCryptoHashType(), CryptoHashType::SHA_256);
+ ASSERT_EQ(signer->getCryptoSuite(), CryptoSuite::RSA_SHA256);
+ ASSERT_EQ(signer->getSignatureSize(), 128u);
+ ASSERT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT);
+
+ // Release PARC objects
+ parcKey_Release(&key);
+}
+
+TEST_F(AuthTest, HMACVerifier) {
+ // Create the HMAC signer from a passphrase
+ std::shared_ptr<Signer> signer =
+ std::make_shared<SymmetricSigner>(CryptoSuite::HMAC_SHA256, PASSPHRASE);
+
+ // Create a content object
+ core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize());
+
+ // Fill it with bogus data
+ uint8_t buffer[256] = {0};
+ packet.appendPayload(buffer, 256);
+
+ // Sign the packet
+ signer->signPacket(&packet);
+
+ // Create the HMAC verifier
+ std::shared_ptr<Verifier> verifier =
+ std::make_shared<SymmetricVerifier>(PASSPHRASE);
+
+ ASSERT_EQ(packet.getFormat(), HF_INET6_TCP_AH);
+ ASSERT_EQ(signer->getCryptoHashType(), CryptoHashType::SHA_256);
+ ASSERT_EQ(signer->getCryptoSuite(), CryptoSuite::HMAC_SHA256);
+ ASSERT_EQ(signer->getSignatureSize(), 32u);
+ ASSERT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT);
+}
+
+} // namespace auth
+} // namespace transport
diff --git a/libtransport/src/test/test_consumer_producer_rtc.cc b/libtransport/src/test/test_consumer_producer_rtc.cc
new file mode 100644
index 000000000..87385971a
--- /dev/null
+++ b/libtransport/src/test/test_consumer_producer_rtc.cc
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <hicn/transport/interfaces/global_conf_interface.h>
+#include <hicn/transport/interfaces/socket_consumer.h>
+#include <hicn/transport/interfaces/socket_options_keys.h>
+#include <hicn/transport/interfaces/socket_producer.h>
+
+#include <asio/io_service.hpp>
+#include <asio/steady_timer.hpp>
+
+namespace transport {
+namespace interface {
+
+namespace {
+
+class ConsumerProducerTest : public ::testing::Test,
+ public ConsumerSocket::ReadCallback {
+ static const constexpr char prefix[] = "b001::1/128";
+ static const constexpr char name[] = "b001::1";
+ static const constexpr double prod_rate = 1.0e6;
+ static const constexpr size_t payload_size = 1200;
+ static constexpr std::size_t receive_buffer_size = 1500;
+ static const constexpr double prod_interval_microseconds =
+ double(payload_size) * 8 * 1e6 / prod_rate;
+
+ public:
+ ConsumerProducerTest()
+ : io_service_(),
+ rtc_timer_(io_service_),
+ stop_timer_(io_service_),
+ consumer_(TransportProtocolAlgorithms::RTC, io_service_),
+ producer_(ProductionProtocolAlgorithms::RTC_PROD, io_service_),
+ producer_prefix_(prefix),
+ consumer_name_(name),
+ packets_sent_(0),
+ packets_received_(0) {
+ global_config::IoModuleConfiguration config;
+ config.name = "loopback_module";
+ config.set();
+ }
+
+ virtual ~ConsumerProducerTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() override {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+
+ auto ret = consumer_.setSocketOption(
+ ConsumerCallbacksOptions::READ_CALLBACK, this);
+ ASSERT_EQ(ret, SOCKET_OPTION_SET);
+
+ consumer_.connect();
+ producer_.registerPrefix(producer_prefix_);
+ producer_.connect();
+ }
+
+ virtual void TearDown() override {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ void setTimer() {
+ using namespace std::chrono;
+ rtc_timer_.expires_from_now(
+ microseconds(unsigned(prod_interval_microseconds)));
+ rtc_timer_.async_wait(std::bind(&ConsumerProducerTest::produceRTCPacket,
+ this, std::placeholders::_1));
+ }
+
+ void setStopTimer() {
+ using namespace std::chrono;
+ stop_timer_.expires_from_now(seconds(unsigned(10)));
+ stop_timer_.async_wait(
+ std::bind(&ConsumerProducerTest::stop, this, std::placeholders::_1));
+ }
+
+ void produceRTCPacket(const std::error_code &ec) {
+ if (ec) {
+ io_service_.stop();
+ }
+
+ producer_.produceDatagram(consumer_name_, payload_, payload_size);
+ packets_sent_++;
+ setTimer();
+ }
+
+ void stop(const std::error_code &ec) {
+ rtc_timer_.cancel();
+ producer_.stop();
+ consumer_.stop();
+ }
+
+ // Consumer callback
+ bool isBufferMovable() noexcept override { return false; }
+
+ void getReadBuffer(uint8_t **application_buffer,
+ size_t *max_length) override {
+ *application_buffer = receive_buffer_;
+ *max_length = receive_buffer_size;
+ }
+
+ void readDataAvailable(std::size_t length) noexcept override {}
+
+ size_t maxBufferSize() const override { return receive_buffer_size; }
+
+ void readError(const std::error_code ec) noexcept override {
+ FAIL() << "Error while reading from RTC socket";
+ io_service_.stop();
+ }
+
+ void readSuccess(std::size_t total_size) noexcept override {
+ packets_received_++;
+ std::cout << "Received something" << std::endl;
+ }
+
+ asio::io_service io_service_;
+ asio::steady_timer rtc_timer_;
+ asio::steady_timer stop_timer_;
+ ConsumerSocket consumer_;
+ ProducerSocket producer_;
+ core::Prefix producer_prefix_;
+ core::Name consumer_name_;
+ uint8_t payload_[payload_size];
+ uint8_t receive_buffer_[payload_size];
+
+ uint64_t packets_sent_;
+ uint64_t packets_received_;
+};
+
+const char ConsumerProducerTest::prefix[];
+const char ConsumerProducerTest::name[];
+
+} // namespace
+
+TEST_F(ConsumerProducerTest, EndToEnd) {
+ produceRTCPacket(std::error_code());
+ consumer_.consume(consumer_name_);
+ setStopTimer();
+
+ io_service_.run();
+
+ std::cout << "Packet received: " << packets_received_ << std::endl;
+ std::cout << "Packet sent: " << packets_sent_ << std::endl;
+}
+
+} // namespace interface
+
+} // namespace transport
+
+int main(int argc, char **argv) {
+#if 0
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+#else
+ return 0;
+#endif
+} \ No newline at end of file
diff --git a/libtransport/src/core/test/test_core_manifest.cc b/libtransport/src/test/test_core_manifest.cc
index 58563d8f9..f98147d43 100644
--- a/libtransport/src/core/test/test_core_manifest.cc
+++ b/libtransport/src/test/test_core_manifest.cc
@@ -13,12 +13,13 @@
* limitations under the License.
*/
+#include <core/manifest_format_fixed.h>
+#include <core/manifest_inline.h>
#include <gtest/gtest.h>
+#include <hicn/transport/auth/crypto_hash_type.h>
+#include <test/packet_samples.h>
-#include "../manifest_format_fixed.h"
-#include "../manifest_inline.h"
-
-#include <test.h>
+#include <climits>
#include <random>
#include <vector>
@@ -72,42 +73,34 @@ class ManifestTest : public ::testing::Test {
} // namespace
-TEST_F(ManifestTest, ManifestCreate) {
- ContentObjectManifest manifest2(name_);
- ContentObjectManifest manifest3 = manifest2;
-
- EXPECT_EQ(manifest1_, manifest2);
- EXPECT_EQ(manifest1_, manifest3);
-}
-
-TEST_F(ManifestTest, ManifestCreateFromBase) {
- ContentObject content_object(name_);
- content_object.setPayload(manifest_payload.data(), manifest_payload.size());
- ContentObjectManifest manifest(std::move(content_object));
-
- auto manifest4 = ContentObjectManifest::createManifest(
- name_, core::ManifestVersion::VERSION_1,
- core::ManifestType::INLINE_MANIFEST, HashAlgorithm::SHA_256, true,
- core::Name("b001::dead"),
- core::NextSegmentCalculationStrategy::INCREMENTAL, 128);
-
- manifest4->encode();
- manifest4->dump();
- manifest.dump();
-
- EXPECT_EQ(manifest1_, manifest);
- // EXPECT_EQ(manifest1_, manifest3);
+TEST_F(ManifestTest, MoveConstructor) {
+ // Create content object with manifest in payload
+ ContentObject co(HF_INET6_TCP_AH, 128);
+ co.appendPayload(&manifest_payload[0], manifest_payload.size());
+ uint8_t buffer[256];
+ co.appendPayload(buffer, 256);
+
+ // Copy packet payload
+ uint8_t packet[1500];
+ auto length = co.getPayload()->length();
+ std::memcpy(packet, co.getPayload()->data(), length);
+
+ // Create manifest
+ ContentObjectManifest m(std::move(co));
+
+ // Check manifest payload is exactly the same of content object
+ ASSERT_EQ(length, m.getPayload()->length());
+ auto ret = std::memcmp(packet, m.getPayload()->data(), length);
+ ASSERT_EQ(ret, 0);
}
TEST_F(ManifestTest, SetLastManifest) {
manifest1_.clear();
manifest1_.setFinalManifest(true);
- manifest1_.encode();
- manifest1_.decode();
bool fcn = manifest1_.isFinalManifest();
- ASSERT_TRUE(fcn);
+ ASSERT_TRUE(fcn == true);
}
TEST_F(ManifestTest, SetManifestType) {
@@ -117,15 +110,11 @@ TEST_F(ManifestTest, SetManifestType) {
ManifestType type2 = ManifestType::FLIC_MANIFEST;
manifest1_.setManifestType(type1);
- manifest1_.encode();
- manifest1_.decode();
ManifestType type_returned1 = manifest1_.getManifestType();
manifest1_.clear();
manifest1_.setManifestType(type2);
- manifest1_.encode();
- manifest1_.decode();
ManifestType type_returned2 = manifest1_.getManifestType();
ASSERT_EQ(type1, type_returned1);
@@ -135,28 +124,22 @@ TEST_F(ManifestTest, SetManifestType) {
TEST_F(ManifestTest, SetHashAlgorithm) {
manifest1_.clear();
- HashAlgorithm hash1 = HashAlgorithm::SHA_512;
- HashAlgorithm hash2 = HashAlgorithm::CRC32C;
- HashAlgorithm hash3 = HashAlgorithm::SHA_256;
+ auth::CryptoHashType hash1 = auth::CryptoHashType::SHA_512;
+ auth::CryptoHashType hash2 = auth::CryptoHashType::CRC32C;
+ auth::CryptoHashType hash3 = auth::CryptoHashType::SHA_256;
manifest1_.setHashAlgorithm(hash1);
- manifest1_.encode();
- manifest1_.decode();
- HashAlgorithm type_returned1 = manifest1_.getHashAlgorithm();
+ auto type_returned1 = manifest1_.getHashAlgorithm();
manifest1_.clear();
manifest1_.setHashAlgorithm(hash2);
- manifest1_.encode();
- manifest1_.decode();
- HashAlgorithm type_returned2 = manifest1_.getHashAlgorithm();
+ auto type_returned2 = manifest1_.getHashAlgorithm();
manifest1_.clear();
manifest1_.setHashAlgorithm(hash3);
- manifest1_.encode();
- manifest1_.decode();
- HashAlgorithm type_returned3 = manifest1_.getHashAlgorithm();
+ auto type_returned3 = manifest1_.getHashAlgorithm();
ASSERT_EQ(hash1, type_returned1);
ASSERT_EQ(hash2, type_returned2);
@@ -170,8 +153,6 @@ TEST_F(ManifestTest, SetNextSegmentCalculationStrategy) {
NextSegmentCalculationStrategy::INCREMENTAL;
manifest1_.setNextSegmentCalculationStrategy(strategy1);
- manifest1_.encode();
- manifest1_.decode();
NextSegmentCalculationStrategy type_returned1 =
manifest1_.getNextSegmentCalculationStrategy();
@@ -183,8 +164,6 @@ TEST_F(ManifestTest, SetBaseName) {
core::Name base_name("b001::dead");
manifest1_.setBaseName(base_name);
- manifest1_.encode();
- manifest1_.decode();
core::Name ret_name = manifest1_.getBaseName();
ASSERT_EQ(base_name, ret_name);
@@ -204,7 +183,7 @@ TEST_F(ManifestTest, SetSuffixList) {
std::uniform_int_distribution<uint64_t> idis(
0, std::numeric_limits<uint32_t>::max());
- auto entries = new std::pair<uint32_t, utils::CryptoHash>[3];
+ auto entries = new std::pair<uint32_t, auth::CryptoHash>[3];
uint32_t suffixes[3];
std::vector<unsigned char> data[3];
@@ -213,28 +192,25 @@ TEST_F(ManifestTest, SetSuffixList) {
std::generate(std::begin(data[i]), std::end(data[i]), std::ref(rbe));
suffixes[i] = idis(eng);
entries[i] = std::make_pair(
- suffixes[i], utils::CryptoHash(data[i].data(), data[i].size(),
- utils::CryptoHashType::SHA_256));
+ suffixes[i], auth::CryptoHash(data[i].data(), data[i].size(),
+ auth::CryptoHashType::SHA_256));
manifest1_.addSuffixHash(entries[i].first, entries[i].second);
}
manifest1_.setBaseName(base_name);
- manifest1_.encode();
- manifest1_.decode();
-
core::Name ret_name = manifest1_.getBaseName();
// auto & hash_list = manifest1_.getSuffixHashList();
- bool cond;
- int i = 0;
+ // bool cond;
+ // int i = 0;
// for (auto & item : manifest1_.getSuffixList()) {
// auto hash = manifest1_.getHash(suffixes[i]);
- // cond = utils::CryptoHash::compareBinaryDigest(hash,
- // entries[i].second.getDigest<uint8_t>().data(),
- // entries[i].second.getType());
+ // cond = auth::CryptoHash::compareBinaryDigest(hash,
+ // entries[i].second.getDigest<uint8_t>().data(),
+ // entries[i].second.getType());
// ASSERT_TRUE(cond);
// i++;
// }
@@ -244,48 +220,6 @@ TEST_F(ManifestTest, SetSuffixList) {
delete[] entries;
}
-TEST_F(ManifestTest, EstimateSize) {
- manifest1_.clear();
-
- HashAlgorithm hash1 = HashAlgorithm::SHA_256;
- NextSegmentCalculationStrategy strategy1 =
- NextSegmentCalculationStrategy::INCREMENTAL;
- ManifestType type1 = ManifestType::INLINE_MANIFEST;
- core::Name base_name1("b001:abcd:fede:baba:cece:d0d0:face:dead");
-
- manifest1_.setFinalManifest(true);
- manifest1_.setBaseName(base_name1);
- manifest1_.setNextSegmentCalculationStrategy(strategy1);
- manifest1_.setHashAlgorithm(hash1);
- manifest1_.setManifestType(type1);
-
- std::default_random_engine eng((std::random_device())());
- std::uniform_int_distribution<uint64_t> idis(
- 0, std::numeric_limits<uint64_t>::max());
-
- using random_bytes_engine =
- std::independent_bits_engine<std::default_random_engine, CHAR_BIT,
- unsigned char>;
- random_bytes_engine rbe;
-
- while (manifest1_.estimateManifestSize(1) < 1440) {
- uint32_t suffix = static_cast<std::uint32_t>(idis(eng));
- std::vector<unsigned char> data(32);
- std::generate(std::begin(data), std::end(data), std::ref(rbe));
- auto hash = utils::CryptoHash(data.data(), data.size(),
- utils::CryptoHashType::SHA_256);
- manifest1_.addSuffixHash(suffix, hash);
- }
-
- manifest1_.encode();
- manifest1_.decode();
-
- manifest1_.dump();
-
- ASSERT_GT(manifest1_.estimateManifestSize(), 0);
- ASSERT_LT(manifest1_.estimateManifestSize(), 1500);
-}
-
} // namespace core
} // namespace transport
@@ -293,4 +227,4 @@ TEST_F(ManifestTest, EstimateSize) {
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
-} \ No newline at end of file
+}
diff --git a/libtransport/src/test/test_event_thread.cc b/libtransport/src/test/test_event_thread.cc
new file mode 100644
index 000000000..e66b49f10
--- /dev/null
+++ b/libtransport/src/test/test_event_thread.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <hicn/transport/utils/event_thread.h>
+
+#include <cmath>
+
+namespace utils {
+
+namespace {
+
+class EventThreadTest : public ::testing::Test {
+ protected:
+ EventThreadTest() : event_thread_() {
+ // You can do set-up work for each test here.
+ }
+
+ virtual ~EventThreadTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ utils::EventThread event_thread_;
+};
+
+double average(const unsigned long samples[], int size) {
+ double sum = 0;
+
+ for (int i = 0; i < size; i++) {
+ sum += samples[i];
+ }
+
+ return sum / size;
+}
+
+double stdDeviation(const unsigned long samples[], int size) {
+ double avg = average(samples, size);
+ double var = 0;
+
+ for (int i = 0; i < size; i++) {
+ var += (samples[i] - avg) * (samples[i] - avg);
+ }
+
+ return sqrt(var / size);
+}
+
+} // namespace
+
+TEST_F(EventThreadTest, SchedulingDelay) {
+ using namespace std::chrono;
+ const size_t size = 1000000;
+ std::vector<unsigned long> samples(size);
+
+ for (unsigned int i = 0; i < size; i++) {
+ auto t0 = steady_clock::now();
+ event_thread_.add([t0, &samples, i]() {
+ auto t1 = steady_clock::now();
+ samples[i] = duration_cast<nanoseconds>(t1 - t0).count();
+ });
+ }
+
+ event_thread_.stop();
+
+ auto avg = average(&samples[0], size);
+ auto sd = stdDeviation(&samples[0], size);
+ (void)sd;
+
+ // Expect average to be less that 1 ms
+ EXPECT_LT(avg, 1000000);
+}
+
+} // namespace utils
+
+int main(int argc, char **argv) {
+#if 0
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+#else
+ return 0;
+#endif
+} \ No newline at end of file
diff --git a/libtransport/src/test/test_fec_reedsolomon.cc b/libtransport/src/test/test_fec_reedsolomon.cc
new file mode 100644
index 000000000..3b10b7307
--- /dev/null
+++ b/libtransport/src/test/test_fec_reedsolomon.cc
@@ -0,0 +1,291 @@
+
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <core/rs.h>
+#include <gtest/gtest.h>
+#include <hicn/transport/core/content_object.h>
+#include <hicn/transport/core/global_object_pool.h>
+
+#include <algorithm>
+#include <iostream>
+#include <random>
+
+namespace transport {
+namespace core {
+
+double ReedSolomonTest(int k, int n, int size) {
+ fec::encoder encoder(k, n);
+ fec::decoder decoder(k, n);
+
+ std::vector<fec::buffer> tx_block(k);
+ std::vector<fec::buffer> rx_block(k);
+ int count = 0;
+ int run = 0;
+
+ int iterations = 100;
+ auto &packet_manager = PacketManager<>::getInstance();
+
+ encoder.setFECCallback([&tx_block](std::vector<fec::buffer> &repair_packets) {
+ for (auto &p : repair_packets) {
+ // Append repair symbols to tx_block
+ tx_block.emplace_back(std::move(p));
+ }
+ });
+
+ decoder.setFECCallback([&](std::vector<fec::buffer> &source_packets) {
+ for (int i = 0; i < k; i++) {
+ // Compare decoded source packets with original transmitted packets.
+ if (*tx_block[i] != *source_packets[i]) {
+ count++;
+ }
+ }
+ });
+
+ do {
+ // Discard eventual packet appended in previous callback call
+ tx_block.erase(tx_block.begin() + k, tx_block.end());
+
+ // Initialization. Feed encoder with first k source packets
+ for (int i = 0; i < k; i++) {
+ // Get new buffer from pool
+ auto packet = packet_manager.getMemBuf();
+
+ // Let's append a bit less than size, so that the FEC class will take care
+ // of filling the rest with zeros
+ auto cur_size = size - (rand() % 100);
+
+ // Set payload, saving 2 bytes at the beginning of the buffer for encoding
+ // the length
+ packet->append(cur_size);
+ packet->trimStart(2);
+ std::generate(packet->writableData(), packet->writableTail(), rand);
+ std::fill(packet->writableData(), packet->writableTail(), i + 1);
+
+ // Set first byte of payload to i, to reorder at receiver side
+ packet->writableData()[0] = uint8_t(i);
+
+ // Store packet in tx buffer and clear rx buffer
+ tx_block[i] = std::move(packet);
+ }
+
+ // Create the repair packets
+ for (auto &tx : tx_block) {
+ encoder.consume(tx, tx->writableBuffer()[0]);
+ }
+
+ // Simulate transmission on lossy channel
+ unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
+ std::vector<bool> losses(n, false);
+ for (int i = 0; i < n - k; i++) losses[i] = true;
+
+ int rxi = 0;
+ std::shuffle(losses.begin(), losses.end(),
+ std::default_random_engine(seed));
+ for (int i = 0; i < n && rxi < k; i++)
+ if (losses[i] == false) {
+ rx_block[rxi++] = tx_block[i];
+ if (i < k) {
+ // Source packet
+ decoder.consume(rx_block[rxi - 1], rx_block[rxi - 1]->data()[0]);
+ } else {
+ // Repair packet
+ decoder.consume(rx_block[rxi - 1]);
+ }
+ }
+
+ decoder.clear();
+ encoder.clear();
+ } while (++run < iterations);
+
+ return count;
+}
+
+void ReedSolomonMultiBlockTest(int n_sourceblocks) {
+ int k = 16;
+ int n = 24;
+ int size = 1000;
+
+ fec::encoder encoder(k, n);
+ fec::decoder decoder(k, n);
+
+ auto &packet_manager = PacketManager<>::getInstance();
+
+ std::vector<std::pair<fec::buffer, uint32_t>> tx_block;
+ std::vector<std::pair<fec::buffer, uint32_t>> rx_block;
+ int count = 0;
+ int i = 0;
+
+ // Receiver will receive packet for n_sourceblocks in a random order.
+ int total_packets = n * n_sourceblocks;
+ int tx_packets = k * n_sourceblocks;
+ unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
+
+ encoder.setFECCallback([&](std::vector<fec::buffer> &repair_packets) {
+ for (auto &p : repair_packets) {
+ // Append repair symbols to tx_block
+ tx_block.emplace_back(std::move(p), ++i);
+ }
+
+ EXPECT_EQ(tx_block.size(), size_t(n));
+
+ // Select k packets to send, including at least one symbol. We start from
+ // the end for this reason.
+ for (int j = n - 1; j > n - k - 1; j--) {
+ rx_block.emplace_back(std::move(tx_block[j]));
+ }
+
+ // Clear tx block for next source block
+ tx_block.clear();
+ encoder.clear();
+ });
+
+ // The decode callback must be called exactly n_sourceblocks times
+ decoder.setFECCallback(
+ [&](std::vector<fec::buffer> &source_packets) { count++; });
+
+ // Produce n * n_sourceblocks
+ // - ( k ) * n_sourceblocks source packets
+ // - (n - k) * n_sourceblocks symbols)
+ for (i = 0; i < total_packets; i++) {
+ // Get new buffer from pool
+ auto packet = packet_manager.getMemBuf();
+
+ // Let's append a bit less than size, so that the FEC class will take care
+ // of filling the rest with zeros
+ auto cur_size = size - (rand() % 100);
+
+ // Set payload, saving 2 bytes at the beginning of the buffer for encoding
+ // the length
+ packet->append(cur_size);
+ packet->trimStart(2);
+ std::fill(packet->writableData(), packet->writableTail(), i + 1);
+
+ // Set first byte of payload to i, to reorder at receiver side
+ packet->writableData()[0] = uint8_t(i);
+
+ // Store packet in tx buffer
+ tx_block.emplace_back(packet, i);
+
+ // Feed encoder with packet
+ encoder.consume(packet, i);
+ }
+
+ // Here rx_block must contains k * n_sourceblocks packets
+ EXPECT_EQ(size_t(tx_packets), size_t(rx_block.size()));
+
+ // Lets shuffle the rx_block before starting feeding the decoder.
+ std::shuffle(rx_block.begin(), rx_block.end(),
+ std::default_random_engine(seed));
+
+ for (auto &p : rx_block) {
+ int index = p.second % n;
+ if (index < k) {
+ // Source packet
+ decoder.consume(p.first, p.second);
+ } else {
+ // Repair packet
+ decoder.consume(p.first);
+ }
+ }
+
+ // Simple test to check we get all the source packets
+ EXPECT_EQ(count, n_sourceblocks);
+}
+
+TEST(ReedSolomonTest, RSk1n3) {
+ int k = 1;
+ int n = 3;
+ int size = 1000;
+ EXPECT_LE(ReedSolomonTest(k, n, size), 0);
+}
+
+TEST(ReedSolomonTest, RSk6n10) {
+ int k = 6;
+ int n = 10;
+ int size = 1000;
+ EXPECT_LE(ReedSolomonTest(k, n, size), 0);
+}
+
+TEST(ReedSolomonTest, RSk8n32) {
+ int k = 8;
+ int n = 32;
+ int size = 1000;
+ EXPECT_LE(ReedSolomonTest(k, n, size), 0);
+}
+
+TEST(ReedSolomonTest, RSk16n24) {
+ int k = 16;
+ int n = 24;
+ int size = 1000;
+ EXPECT_LE(ReedSolomonTest(k, n, size), 0);
+}
+
+TEST(ReedSolomonTest, RSk10n30) {
+ int k = 10;
+ int n = 30;
+ int size = 1000;
+ EXPECT_LE(ReedSolomonTest(k, n, size), 0);
+}
+
+TEST(ReedSolomonTest, RSk10n40) {
+ int k = 10;
+ int n = 40;
+ int size = 1000;
+ EXPECT_LE(ReedSolomonTest(k, n, size), 0);
+}
+
+TEST(ReedSolomonTest, RSk10n60) {
+ int k = 10;
+ int n = 60;
+ int size = 1000;
+ EXPECT_LE(ReedSolomonTest(k, n, size), 0);
+}
+
+TEST(ReedSolomonTest, RSk10n90) {
+ int k = 10;
+ int n = 90;
+ int size = 1000;
+ EXPECT_LE(ReedSolomonTest(k, n, size), 0);
+}
+
+TEST(ReedSolomonMultiBlockTest, RSMB1) {
+ int blocks = 1;
+ ReedSolomonMultiBlockTest(blocks);
+}
+
+TEST(ReedSolomonMultiBlockTest, RSMB10) {
+ int blocks = 10;
+ ReedSolomonMultiBlockTest(blocks);
+}
+
+TEST(ReedSolomonMultiBlockTest, RSMB100) {
+ int blocks = 100;
+ ReedSolomonMultiBlockTest(blocks);
+}
+
+TEST(ReedSolomonMultiBlockTest, RSMB1000) {
+ int blocks = 1000;
+ ReedSolomonMultiBlockTest(blocks);
+}
+
+int main(int argc, char **argv) {
+ srand(time(0));
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+
+} // namespace core
+} // namespace transport
diff --git a/libtransport/src/test/test_interest.cc b/libtransport/src/test/test_interest.cc
new file mode 100644
index 000000000..0a835db24
--- /dev/null
+++ b/libtransport/src/test/test_interest.cc
@@ -0,0 +1,267 @@
+/*
+ * 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 <gtest/gtest.h>
+#include <hicn/transport/core/interest.h>
+#include <hicn/transport/errors/not_implemented_exception.h>
+#include <test/packet_samples.h>
+
+#include <climits>
+#include <random>
+#include <vector>
+
+namespace transport {
+
+namespace core {
+
+namespace {
+// The fixture for testing class Foo.
+class InterestTest : public ::testing::Test {
+ protected:
+ InterestTest() : name_("b001::123|321"), interest_() {
+ // You can do set-up work for each test here.
+ }
+
+ virtual ~InterestTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ Name name_;
+
+ Interest interest_;
+
+ std::vector<uint8_t> buffer_ = {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca
+ IPV6_HEADER(TCP_PROTO, 20 + PAYLOAD_SIZE),
+ // ICMP6 echo request
+ TCP_HEADER(0x00),
+ // Payload
+ PAYLOAD};
+};
+
+void testFormatConstructor(Packet::Format format = HF_UNSPEC) {
+ try {
+ Interest interest(format, 0);
+ } catch (...) {
+ FAIL() << "ERROR: Unexpected exception thrown for " << format;
+ }
+}
+
+void testFormatConstructorException(Packet::Format format = HF_UNSPEC) {
+ try {
+ Interest interest(format, 0);
+ FAIL() << "We expected an exception here";
+ } catch (errors::MalformedPacketException &exc) {
+ // Ok right exception
+ } catch (...) {
+ FAIL() << "Wrong exception thrown";
+ }
+}
+
+} // namespace
+
+TEST_F(InterestTest, ConstructorWithFormat) {
+ /**
+ * Without arguments it should be format = HF_UNSPEC.
+ * We expect a crash.
+ */
+
+ testFormatConstructor(Packet::Format::HF_INET_TCP);
+ testFormatConstructor(Packet::Format::HF_INET6_TCP);
+ testFormatConstructorException(Packet::Format::HF_INET_ICMP);
+ testFormatConstructorException(Packet::Format::HF_INET6_ICMP);
+ testFormatConstructor(Packet::Format::HF_INET_TCP_AH);
+ testFormatConstructor(Packet::Format::HF_INET6_TCP_AH);
+ testFormatConstructorException(Packet::Format::HF_INET_ICMP_AH);
+ testFormatConstructorException(Packet::Format::HF_INET6_ICMP_AH);
+}
+
+TEST_F(InterestTest, ConstructorWithName) {
+ /**
+ * Without arguments it should be format = HF_UNSPEC.
+ * We expect a crash.
+ */
+ Name n("b001::1|123");
+
+ try {
+ Interest interest(n);
+ } catch (...) {
+ FAIL() << "ERROR: Unexpected exception thrown";
+ }
+}
+
+TEST_F(InterestTest, ConstructorWithBuffer) {
+ // Ensure buffer is interest
+ auto ret = Interest::isInterest(&buffer_[0]);
+ EXPECT_TRUE(ret);
+
+ // Create interest from buffer
+ try {
+ Interest interest(Interest::COPY_BUFFER, &buffer_[0], buffer_.size());
+ } catch (...) {
+ FAIL() << "ERROR: Unexpected exception thrown";
+ }
+
+ std::vector<uint8_t> buffer2{// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca
+ IPV6_HEADER(ICMP6_PROTO, 60 + 44),
+ // ICMP6 echo request
+ TCP_HEADER(0x00),
+ // Payload
+ PAYLOAD};
+
+ // Ensure this throws an exception
+ try {
+ Interest interest(Interest::COPY_BUFFER, &buffer2[0], buffer2.size());
+ FAIL() << "We expected an exception here";
+ } catch (errors::MalformedPacketException &exc) {
+ // Ok right exception
+ } catch (...) {
+ FAIL() << "Wrong exception thrown";
+ }
+}
+
+TEST_F(InterestTest, SetGetName) {
+ // Create interest from buffer
+ Interest interest(Interest::COPY_BUFFER, &buffer_[0], buffer_.size());
+
+ // Get name
+ auto n = interest.getName();
+
+ // ensure name is b002::ca|1
+ Name n2("b002::ca|1");
+ auto ret = (n == n2);
+
+ EXPECT_TRUE(ret);
+
+ Name n3("b003::1234|1234");
+
+ // Change name to b003::1234|1234
+ interest.setName(n3);
+
+ // Check name was set
+ n = interest.getName();
+ ret = (n == n3);
+ EXPECT_TRUE(ret);
+}
+
+TEST_F(InterestTest, SetGetLocator) {
+ // Create interest from buffer
+ Interest interest(Interest::COPY_BUFFER, &buffer_[0], buffer_.size());
+
+ // Get locator
+ auto l = interest.getLocator();
+
+ ip_address_t address;
+ ip_address_pton("b006::ab:cdab:cdef", &address);
+ auto ret = !std::memcmp(&l, &address, sizeof(address));
+
+ EXPECT_TRUE(ret);
+
+ // Set different locator
+ ip_address_pton("2001::1234::4321::abcd::", &address);
+
+ // Set it on interest
+ interest.setLocator(address);
+
+ // Check it was set
+ l = interest.getLocator();
+ ret = !std::memcmp(&l, &address, sizeof(address));
+
+ EXPECT_TRUE(ret);
+}
+
+TEST_F(InterestTest, SetGetLifetime) {
+ // Create interest from buffer
+ Interest interest;
+ const constexpr uint32_t lifetime = 10000;
+
+ // Set lifetime
+ interest.setLifetime(lifetime);
+
+ // Get lifetime
+ auto l = interest.getLifetime();
+
+ // Ensure they are the same
+ EXPECT_EQ(l, lifetime);
+}
+
+TEST_F(InterestTest, HasManifest) {
+ // Create interest from buffer
+ Interest interest;
+
+ // Let's expect anexception here
+ try {
+ interest.setPayloadType(PayloadType::UNSPECIFIED);
+ FAIL() << "We expect an esception here";
+ } catch (errors::RuntimeException &exc) {
+ // Ok right exception
+ } catch (...) {
+ FAIL() << "Wrong exception thrown";
+ }
+
+ interest.setPayloadType(PayloadType::DATA);
+ EXPECT_FALSE(interest.hasManifest());
+
+ interest.setPayloadType(PayloadType::MANIFEST);
+ EXPECT_TRUE(interest.hasManifest());
+}
+
+TEST_F(InterestTest, AppendSuffixesEncodeAndIterate) {
+ // Create interest from buffer
+ Interest interest;
+
+ // Appenad some suffixes, with some duplicates
+ interest.appendSuffix(1);
+ interest.appendSuffix(2);
+ interest.appendSuffix(5);
+ interest.appendSuffix(3);
+ interest.appendSuffix(4);
+ interest.appendSuffix(5);
+ interest.appendSuffix(5);
+ interest.appendSuffix(5);
+ interest.appendSuffix(5);
+ interest.appendSuffix(5);
+
+ // Encode them in wire format
+ interest.encodeSuffixes();
+
+ // Iterate over them. They should be in order and without repetitions
+ auto suffix = interest.firstSuffix();
+ auto n_suffixes = interest.numberOfSuffixes();
+
+ for (uint32_t i = 0; i < n_suffixes; i++) {
+ EXPECT_EQ(*(suffix + i), (i + 1));
+ }
+}
+
+} // namespace core
+} // namespace transport
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+} \ No newline at end of file
diff --git a/libtransport/src/test/test_packet.cc b/libtransport/src/test/test_packet.cc
new file mode 100644
index 000000000..0ee140e2c
--- /dev/null
+++ b/libtransport/src/test/test_packet.cc
@@ -0,0 +1,1047 @@
+/*
+ * 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 <gtest/gtest.h>
+#include <hicn/transport/core/packet.h>
+#include <hicn/transport/errors/not_implemented_exception.h>
+#include <test/packet_samples.h>
+
+#include <climits>
+#include <random>
+#include <vector>
+
+namespace transport {
+
+namespace core {
+
+/**
+ * Since packet is an abstract class, we derive a concrete class to be used for
+ * the test.
+ */
+class PacketForTest : public Packet {
+ public:
+ template <typename... Args>
+ PacketForTest(Args &&... args) : Packet(std::forward<Args>(args)...) {}
+
+ virtual ~PacketForTest() {}
+
+ const Name &getName() const override {
+ throw errors::NotImplementedException();
+ }
+
+ Name &getWritableName() override { throw errors::NotImplementedException(); }
+
+ void setName(const Name &name) override {
+ throw errors::NotImplementedException();
+ }
+
+ void setName(Name &&name) override {
+ throw errors::NotImplementedException();
+ }
+
+ void setLifetime(uint32_t lifetime) override {
+ throw errors::NotImplementedException();
+ }
+
+ uint32_t getLifetime() const override {
+ throw errors::NotImplementedException();
+ }
+
+ void setLocator(const ip_address_t &locator) override {
+ throw errors::NotImplementedException();
+ }
+
+ void resetForHash() override { throw errors::NotImplementedException(); }
+
+ ip_address_t getLocator() const override {
+ throw errors::NotImplementedException();
+ }
+};
+
+namespace {
+// The fixture for testing class Foo.
+class PacketTest : public ::testing::Test {
+ protected:
+ PacketTest()
+ : name_("b001::123|321"),
+ packet(Packet::COPY_BUFFER, &raw_packets_[HF_INET6_TCP][0],
+ raw_packets_[HF_INET6_TCP].size()) {
+ // You can do set-up work for each test here.
+ }
+
+ virtual ~PacketTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ Name name_;
+
+ PacketForTest packet;
+
+ static std::map<Packet::Format, std::vector<uint8_t>> raw_packets_;
+
+ std::vector<uint8_t> payload = {
+ 0x11, 0x11, 0x01, 0x00, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xad // , 0x00, 0x00,
+ // 0x00, 0x45, 0xa3,
+ // 0xd1, 0xf2, 0x2b,
+ // 0x94, 0x41, 0x22,
+ // 0xc9, 0x00, 0x00,
+ // 0x00, 0x44, 0xa3,
+ // 0xd1, 0xf2, 0x2b,
+ // 0x94, 0x41, 0x22,
+ // 0xc8
+ };
+};
+
+std::map<Packet::Format, std::vector<uint8_t>> PacketTest::raw_packets_ = {
+ {Packet::Format::HF_INET6_TCP,
+
+ {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca
+ IPV6_HEADER(TCP_PROTO, 20 + PAYLOAD_SIZE),
+ // TCP src=0x1234 dst=0x4321, seq=0x0001
+ TCP_HEADER(0x00),
+ // Payload
+ PAYLOAD}},
+
+ {Packet::Format::HF_INET_TCP,
+ {// IPv4 src=3.13.127.8, dst=192.168.1.92
+ IPV4_HEADER(TCP_PROTO, 20 + PAYLOAD_SIZE),
+ // TCP src=0x1234 dst=0x4321, seq=0x0001
+ TCP_HEADER(0x00),
+ // Other
+ PAYLOAD}},
+
+ {Packet::Format::HF_INET_ICMP,
+ {// IPv4 src=3.13.127.8, dst=192.168.1.92
+ IPV4_HEADER(ICMP_PROTO, 64),
+ // ICMP echo request
+ ICMP_ECHO_REQUEST}},
+
+ {Packet::Format::HF_INET6_ICMP,
+ {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca
+ IPV6_HEADER(ICMP6_PROTO, 60),
+ // ICMP6 echo request
+ ICMP6_ECHO_REQUEST}},
+
+ {Packet::Format::HF_INET6_TCP_AH,
+ {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca
+ IPV6_HEADER(TCP_PROTO, 20 + 44 + 128),
+ // ICMP6 echo request
+ TCP_HEADER(0x18),
+ // hICN AH header
+ AH_HEADER}},
+
+ {Packet::Format::HF_INET_TCP_AH,
+ {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca
+ IPV4_HEADER(TCP_PROTO, 20 + 44 + 128),
+ // ICMP6 echo request
+ TCP_HEADER(0x18),
+ // hICN AH header
+ AH_HEADER}},
+
+ // XXX No flag defined in ICMP header to signal AH header.
+ {Packet::Format::HF_INET_ICMP_AH,
+ {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca
+ IPV4_HEADER(ICMP_PROTO, 64 + 44),
+ // ICMP6 echo request
+ ICMP_ECHO_REQUEST,
+ // hICN AH header
+ AH_HEADER}},
+
+ {Packet::Format::HF_INET6_ICMP_AH,
+ {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca
+ IPV6_HEADER(ICMP6_PROTO, 60 + 44),
+ // ICMP6 echo request
+ ICMP6_ECHO_REQUEST,
+ // hICN AH header
+ AH_HEADER}},
+
+};
+
+void testFormatConstructor(Packet::Format format = HF_UNSPEC) {
+ try {
+ PacketForTest packet(format);
+ } catch (...) {
+ FAIL() << "ERROR: Unexpected exception thrown for " << format;
+ }
+}
+
+void testFormatAndAdditionalHeaderConstructor(Packet::Format format,
+ std::size_t additional_header) {
+ PacketForTest packet(format, additional_header);
+ // Packet length should be the one of the normal header + the
+ // additional_header
+
+ EXPECT_EQ(packet.headerSize(),
+ Packet::getHeaderSizeFromFormat(format) + additional_header);
+}
+
+void testRawBufferConstructor(std::vector<uint8_t> packet,
+ Packet::Format format) {
+ try {
+ // Try to construct packet from correct buffer
+ PacketForTest p(Packet::WRAP_BUFFER, &packet[0], packet.size(),
+ packet.size());
+
+ // Check format is expected one.
+ EXPECT_EQ(p.getFormat(), format);
+
+ // // Try the same using a MemBuf
+ // auto buf = utils::MemBuf::wrapBuffer(&packet[0], packet.size());
+ // buf->append(packet.size());
+ // PacketForTest p2(std::move(buf));
+
+ // EXPECT_EQ(p2.getFormat(), format);
+ } catch (...) {
+ FAIL() << "ERROR: Unexpected exception thrown";
+ }
+
+ try {
+ // Try to construct packet from wrong buffer
+
+ // Modify next header to 0
+ /* ipv6 */
+ packet[6] = 0x00;
+ /* ipv4 */
+ packet[9] = 0x00;
+ PacketForTest p(Packet::WRAP_BUFFER, &packet[0], packet.size(),
+ packet.size());
+
+ // Format should fallback to HF_UNSPEC
+ EXPECT_EQ(p.getFormat(), HF_UNSPEC);
+ } catch (...) {
+ FAIL() << "ERROR: Unexpected exception thrown.";
+ }
+}
+
+void getHeaderSizeFromBuffer(Packet::Format format,
+ std::vector<uint8_t> &packet,
+ std::size_t expected) {
+ auto header_size = PacketForTest::getHeaderSizeFromBuffer(format, &packet[0]);
+ EXPECT_EQ(header_size, expected);
+}
+
+void getHeaderSizeFromFormat(Packet::Format format, std::size_t expected) {
+ auto header_size = PacketForTest::getHeaderSizeFromFormat(format);
+ EXPECT_EQ(header_size, expected);
+}
+
+void getPayloadSizeFromBuffer(Packet::Format format,
+ std::vector<uint8_t> &packet,
+ std::size_t expected) {
+ auto payload_size =
+ PacketForTest::getPayloadSizeFromBuffer(format, &packet[0]);
+ EXPECT_EQ(payload_size, expected);
+}
+
+void getFormatFromBuffer(Packet::Format expected,
+ std::vector<uint8_t> &packet) {
+ auto format = PacketForTest::getFormatFromBuffer(&packet[0], packet.size());
+ EXPECT_EQ(format, expected);
+}
+
+void getHeaderSize(std::size_t expected, const PacketForTest &packet) {
+ auto size = packet.headerSize();
+ EXPECT_EQ(size, expected);
+}
+
+void testGetFormat(Packet::Format expected, const Packet &packet) {
+ auto format = packet.getFormat();
+ EXPECT_EQ(format, expected);
+}
+
+} // namespace
+
+TEST_F(PacketTest, ConstructorWithFormat) {
+ testFormatConstructor(Packet::Format::HF_INET_TCP);
+ testFormatConstructor(Packet::Format::HF_INET6_TCP);
+ testFormatConstructor(Packet::Format::HF_INET_ICMP);
+ testFormatConstructor(Packet::Format::HF_INET6_ICMP);
+ testFormatConstructor(Packet::Format::HF_INET_TCP_AH);
+ testFormatConstructor(Packet::Format::HF_INET6_TCP_AH);
+ testFormatConstructor(Packet::Format::HF_INET_ICMP_AH);
+ testFormatConstructor(Packet::Format::HF_INET6_ICMP_AH);
+}
+
+TEST_F(PacketTest, ConstructorWithFormatAndAdditionalHeader) {
+ testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET_TCP, 123);
+ testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET6_TCP, 360);
+ testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET_ICMP, 21);
+ testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET6_ICMP, 444);
+ testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET_TCP_AH, 555);
+ testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET6_TCP_AH,
+ 321);
+ testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET_ICMP_AH,
+ 123);
+ testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET6_ICMP_AH,
+ 44);
+}
+
+TEST_F(PacketTest, ConstructorWithNew) {
+ auto &_packet = raw_packets_[HF_INET6_TCP];
+ auto packet_ptr = new PacketForTest(Packet::WRAP_BUFFER, &_packet[0],
+ _packet.size(), _packet.size());
+ (void)packet_ptr;
+}
+
+TEST_F(PacketTest, ConstructorWithRawBufferInet6Tcp) {
+ auto format = Packet::Format::HF_INET6_TCP;
+ testRawBufferConstructor(raw_packets_[format], format);
+}
+
+TEST_F(PacketTest, ConstructorWithRawBufferInetTcp) {
+ auto format = Packet::Format::HF_INET_TCP;
+ testRawBufferConstructor(raw_packets_[format], format);
+}
+
+TEST_F(PacketTest, ConstructorWithRawBufferInetIcmp) {
+ auto format = Packet::Format::HF_INET_ICMP;
+ testRawBufferConstructor(raw_packets_[format], format);
+}
+
+TEST_F(PacketTest, ConstructorWithRawBufferInet6Icmp) {
+ auto format = Packet::Format::HF_INET6_ICMP;
+ testRawBufferConstructor(raw_packets_[format], format);
+}
+
+TEST_F(PacketTest, ConstructorWithRawBufferInet6TcpAh) {
+ auto format = Packet::Format::HF_INET6_TCP_AH;
+ testRawBufferConstructor(raw_packets_[format], format);
+}
+
+TEST_F(PacketTest, ConstructorWithRawBufferInetTcpAh) {
+ auto format = Packet::Format::HF_INET_TCP_AH;
+ testRawBufferConstructor(raw_packets_[format], format);
+}
+
+TEST_F(PacketTest, MoveConstructor) {
+ PacketForTest p0(Packet::Format::HF_INET6_TCP);
+ PacketForTest p1(std::move(p0));
+ EXPECT_EQ(p0.getFormat(), Packet::Format::HF_UNSPEC);
+ EXPECT_EQ(p1.getFormat(), Packet::Format::HF_INET6_TCP);
+}
+
+TEST_F(PacketTest, TestGetHeaderSizeFromBuffer) {
+ getHeaderSizeFromBuffer(HF_INET6_TCP, raw_packets_[HF_INET6_TCP],
+ HICN_V6_TCP_HDRLEN);
+ getHeaderSizeFromBuffer(HF_INET_TCP, raw_packets_[HF_INET_TCP],
+ HICN_V4_TCP_HDRLEN);
+ getHeaderSizeFromBuffer(HF_INET6_ICMP, raw_packets_[HF_INET6_ICMP],
+ IPV6_HDRLEN + 4);
+ getHeaderSizeFromBuffer(HF_INET_ICMP, raw_packets_[HF_INET_ICMP],
+ IPV4_HDRLEN + 4);
+ getHeaderSizeFromBuffer(HF_INET6_TCP_AH, raw_packets_[HF_INET6_TCP_AH],
+ HICN_V6_TCP_AH_HDRLEN + 128);
+ getHeaderSizeFromBuffer(HF_INET_TCP_AH, raw_packets_[HF_INET_TCP_AH],
+ HICN_V4_TCP_AH_HDRLEN + 128);
+}
+
+TEST_F(PacketTest, TestGetHeaderSizeFromFormat) {
+ getHeaderSizeFromFormat(HF_INET6_TCP, HICN_V6_TCP_HDRLEN);
+ getHeaderSizeFromFormat(HF_INET_TCP, HICN_V4_TCP_HDRLEN);
+ getHeaderSizeFromFormat(HF_INET6_ICMP, IPV6_HDRLEN + 4);
+ getHeaderSizeFromFormat(HF_INET_ICMP, IPV4_HDRLEN + 4);
+ getHeaderSizeFromFormat(HF_INET6_TCP_AH, HICN_V6_TCP_AH_HDRLEN);
+ getHeaderSizeFromFormat(HF_INET_TCP_AH, HICN_V4_TCP_AH_HDRLEN);
+}
+
+TEST_F(PacketTest, TestGetPayloadSizeFromBuffer) {
+ getPayloadSizeFromBuffer(HF_INET6_TCP, raw_packets_[HF_INET6_TCP], 12);
+ getPayloadSizeFromBuffer(HF_INET_TCP, raw_packets_[HF_INET_TCP], 12);
+ getPayloadSizeFromBuffer(HF_INET6_ICMP, raw_packets_[HF_INET6_ICMP], 56);
+ getPayloadSizeFromBuffer(HF_INET_ICMP, raw_packets_[HF_INET_ICMP], 60);
+ getPayloadSizeFromBuffer(HF_INET6_TCP_AH, raw_packets_[HF_INET6_TCP_AH], 0);
+ getPayloadSizeFromBuffer(HF_INET_TCP_AH, raw_packets_[HF_INET_TCP_AH], 0);
+}
+
+TEST_F(PacketTest, TestIsInterest) {
+ auto ret = PacketForTest::isInterest(&raw_packets_[HF_INET6_TCP][0]);
+
+ EXPECT_TRUE(ret);
+}
+
+TEST_F(PacketTest, TestGetFormatFromBuffer) {
+ getFormatFromBuffer(HF_INET6_TCP, raw_packets_[HF_INET6_TCP]);
+ getFormatFromBuffer(HF_INET_TCP, raw_packets_[HF_INET_TCP]);
+ getFormatFromBuffer(HF_INET6_ICMP, raw_packets_[HF_INET6_ICMP]);
+ getFormatFromBuffer(HF_INET_ICMP, raw_packets_[HF_INET_ICMP]);
+ getFormatFromBuffer(HF_INET6_TCP_AH, raw_packets_[HF_INET6_TCP_AH]);
+ getFormatFromBuffer(HF_INET_TCP_AH, raw_packets_[HF_INET_TCP_AH]);
+}
+
+// TEST_F(PacketTest, TestReplace) {
+// PacketForTest packet(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_TCP][0],
+// raw_packets_[HF_INET6_TCP].size());
+
+// // Replace current packet with another one
+// packet.replace(&raw_packets_[HF_INET_TCP][0],
+// raw_packets_[HF_INET_TCP].size());
+
+// // Check new format
+// ASSERT_EQ(packet.getFormat(), HF_INET_TCP);
+// }
+
+TEST_F(PacketTest, TestPayloadSize) {
+ // Check payload size of existing packet
+ auto &_packet = raw_packets_[HF_INET6_TCP];
+ PacketForTest packet(Packet::WRAP_BUFFER, &_packet[0], _packet.size(),
+ _packet.size());
+
+ EXPECT_EQ(packet.payloadSize(), std::size_t(PAYLOAD_SIZE));
+
+ // Check for dynamic generated packet
+ std::string payload0(1024, 'X');
+
+ // Create the packet
+ PacketForTest packet2(HF_INET6_TCP);
+
+ // Payload size should now be zero
+ EXPECT_EQ(packet2.payloadSize(), std::size_t(0));
+
+ // Append payload 1 time
+ packet2.appendPayload((const uint8_t *)payload0.c_str(), payload0.size());
+
+ // size should now be 1024
+ EXPECT_EQ(packet2.payloadSize(), std::size_t(1024));
+
+ // Append second payload
+ std::string payload1(1024, 'X');
+ packet2.appendPayload((const uint8_t *)payload1.c_str(), payload1.size());
+
+ // Check size is 2048
+ EXPECT_EQ(packet2.payloadSize(), std::size_t(2048));
+
+ // Append Membuf
+ packet2.appendPayload(utils::MemBuf::copyBuffer(
+ (const uint8_t *)payload1.c_str(), payload1.size()));
+
+ // Check size is 3072
+ EXPECT_EQ(packet2.payloadSize(), std::size_t(3072));
+}
+
+TEST_F(PacketTest, TestHeaderSize) {
+ getHeaderSize(HICN_V6_TCP_HDRLEN,
+ PacketForTest(Packet::Format::HF_INET6_TCP));
+ getHeaderSize(HICN_V4_TCP_HDRLEN, PacketForTest(Packet::Format::HF_INET_TCP));
+ getHeaderSize(HICN_V6_ICMP_HDRLEN,
+ PacketForTest(Packet::Format::HF_INET6_ICMP));
+ getHeaderSize(HICN_V4_ICMP_HDRLEN,
+ PacketForTest(Packet::Format::HF_INET_ICMP));
+ getHeaderSize(HICN_V6_TCP_AH_HDRLEN,
+ PacketForTest(Packet::Format::HF_INET6_TCP_AH));
+ getHeaderSize(HICN_V4_TCP_AH_HDRLEN,
+ PacketForTest(Packet::Format::HF_INET_TCP_AH));
+}
+
+TEST_F(PacketTest, TestMemBufReference) {
+ // Create packet
+ auto &_packet = raw_packets_[HF_INET6_TCP];
+
+ // Packet was not created as a shared_ptr. If we try to get a membuf shared
+ // ptr we should get an exception.
+ // TODO test with c++ 17
+ // try {
+ // PacketForTest packet(&_packet[0], _packet.size());
+ // auto membuf_ref = packet.acquireMemBufReference();
+ // FAIL() << "The acquireMemBufReference() call should have throwed an "
+ // "exception!";
+ // } catch (const std::bad_weak_ptr &e) {
+ // // Ok
+ // } catch (...) {
+ // FAIL() << "Not expected exception.";
+ // }
+
+ auto packet_ptr = std::make_shared<PacketForTest>(
+ Packet::WRAP_BUFFER, &_packet[0], _packet.size(), _packet.size());
+ PacketForTest &packet = *packet_ptr;
+
+ // Acquire a reference to the membuf
+ auto membuf_ref = packet.acquireMemBufReference();
+
+ // Check refcount. It should be 2
+ EXPECT_EQ(membuf_ref.use_count(), 2);
+
+ // Now increment membuf references
+ Packet::MemBufPtr membuf = packet.acquireMemBufReference();
+
+ // Now reference count should be 2
+ EXPECT_EQ(membuf_ref.use_count(), 3);
+
+ // Copy again
+ Packet::MemBufPtr membuf2 = membuf;
+
+ // Now reference count should be 3
+ EXPECT_EQ(membuf_ref.use_count(), 4);
+}
+
+TEST_F(PacketTest, TestReset) {
+ // Check everything is ok
+ EXPECT_EQ(packet.getFormat(), HF_INET6_TCP);
+ EXPECT_EQ(packet.length(), raw_packets_[HF_INET6_TCP].size());
+ EXPECT_EQ(packet.headerSize(), HICN_V6_TCP_HDRLEN);
+ EXPECT_EQ(packet.payloadSize(), packet.length() - packet.headerSize());
+
+ // Reset the packet
+ packet.reset();
+
+ // Rerun test
+ EXPECT_EQ(packet.getFormat(), HF_UNSPEC);
+ EXPECT_EQ(packet.length(), std::size_t(0));
+ EXPECT_EQ(packet.headerSize(), std::size_t(0));
+ EXPECT_EQ(packet.payloadSize(), std::size_t(0));
+}
+
+TEST_F(PacketTest, TestAppendPayload) {
+ // Append payload with raw buffer
+ uint8_t raw_buffer[2048];
+ auto original_payload_length = packet.payloadSize();
+ packet.appendPayload(raw_buffer, 1024);
+
+ EXPECT_EQ(original_payload_length + 1024, packet.payloadSize());
+
+ for (int i = 0; i < 10; i++) {
+ // Append other payload 10 times
+ packet.appendPayload(raw_buffer, 1024);
+ EXPECT_EQ(original_payload_length + 1024 + (1024) * (i + 1),
+ packet.payloadSize());
+ }
+
+ // Append payload using membuf
+ packet.appendPayload(utils::MemBuf::copyBuffer(raw_buffer, 2048));
+ EXPECT_EQ(original_payload_length + 1024 + 1024 * 10 + 2048,
+ packet.payloadSize());
+
+ // Check the underlying MemBuf length is the expected one
+ utils::MemBuf *current = &packet;
+ size_t total = 0;
+ do {
+ total += current->length();
+ current = current->next();
+ } while (current != &packet);
+
+ EXPECT_EQ(total, packet.headerSize() + packet.payloadSize());
+
+ // LEt's try now to reset this packet
+ packet.reset();
+
+ // There should be no more bufferls left in the chain
+ EXPECT_EQ(&packet, packet.next());
+ EXPECT_EQ(packet.getFormat(), HF_UNSPEC);
+ EXPECT_EQ(packet.length(), std::size_t(0));
+ EXPECT_EQ(packet.headerSize(), std::size_t(0));
+ EXPECT_EQ(packet.payloadSize(), std::size_t(0));
+}
+
+TEST_F(PacketTest, GetPayload) {
+ // Append payload with raw buffer
+ uint8_t raw_buffer[2048];
+ auto original_payload_length = packet.payloadSize();
+ packet.appendPayload(raw_buffer, 2048);
+
+ // Get payload
+ auto payload = packet.getPayload();
+ // Check payload length is correct
+ utils::MemBuf *current = payload.get();
+ size_t total = 0;
+ do {
+ total += current->length();
+ current = current->next();
+ } while (current != payload.get());
+
+ ASSERT_EQ(total, packet.payloadSize());
+
+ // Linearize the payload
+ payload->gather(total);
+
+ // Check memory correspond
+ payload->trimStart(original_payload_length);
+ auto ret = memcmp(raw_buffer, payload->data(), 2048);
+ EXPECT_EQ(ret, 0);
+}
+
+TEST_F(PacketTest, UpdateLength) {
+ auto original_payload_size = packet.payloadSize();
+
+ // Add some fake payload without using the API
+ packet.append(200);
+
+ // payloadSize does not know about the new payload, yet
+ EXPECT_EQ(packet.payloadSize(), original_payload_size);
+
+ // Let's now update the packet length
+ packet.updateLength();
+
+ // Now payloadSize knows
+ EXPECT_EQ(packet.payloadSize(), std::size_t(original_payload_size + 200));
+
+ // We may also update the length without adding real content. This is only
+ // written in the packet header.
+ packet.updateLength(128);
+ EXPECT_EQ(packet.payloadSize(),
+ std::size_t(original_payload_size + 200 + 128));
+}
+
+TEST_F(PacketTest, SetGetPayloadType) {
+ auto payload_type = packet.getPayloadType();
+
+ // It should be normal content object by default
+ EXPECT_EQ(payload_type, PayloadType::DATA);
+
+ // Set it to be manifest
+ packet.setPayloadType(PayloadType::MANIFEST);
+
+ // Check it is manifest
+ payload_type = packet.getPayloadType();
+
+ EXPECT_EQ(payload_type, PayloadType::MANIFEST);
+}
+
+TEST_F(PacketTest, GetFormat) {
+ {
+ PacketForTest p0(Packet::WRAP_BUFFER,
+ &raw_packets_[Packet::Format::HF_INET_TCP][0],
+ raw_packets_[Packet::Format::HF_INET_TCP].size(),
+ raw_packets_[Packet::Format::HF_INET_TCP].size());
+ testGetFormat(Packet::Format::HF_INET_TCP, p0);
+
+ PacketForTest p1(Packet::WRAP_BUFFER,
+ &raw_packets_[Packet::Format::HF_INET6_TCP][0],
+ raw_packets_[Packet::Format::HF_INET6_TCP].size(),
+ raw_packets_[Packet::Format::HF_INET6_TCP].size());
+ testGetFormat(Packet::Format::HF_INET6_TCP, p1);
+
+ PacketForTest p2(Packet::WRAP_BUFFER,
+ &raw_packets_[Packet::Format::HF_INET_ICMP][0],
+ raw_packets_[Packet::Format::HF_INET_ICMP].size(),
+ raw_packets_[Packet::Format::HF_INET_ICMP].size());
+ testGetFormat(Packet::Format::HF_INET_ICMP, p2);
+
+ PacketForTest p3(Packet::WRAP_BUFFER,
+ &raw_packets_[Packet::Format::HF_INET6_ICMP][0],
+ raw_packets_[Packet::Format::HF_INET6_ICMP].size(),
+ raw_packets_[Packet::Format::HF_INET6_ICMP].size());
+ testGetFormat(Packet::Format::HF_INET6_ICMP, p3);
+
+ PacketForTest p4(Packet::WRAP_BUFFER,
+ &raw_packets_[Packet::Format::HF_INET_TCP_AH][0],
+ raw_packets_[Packet::Format::HF_INET_TCP_AH].size(),
+ raw_packets_[Packet::Format::HF_INET_TCP_AH].size());
+ testGetFormat(Packet::Format::HF_INET_TCP_AH, p4);
+
+ PacketForTest p5(Packet::WRAP_BUFFER,
+ &raw_packets_[Packet::Format::HF_INET6_TCP_AH][0],
+ raw_packets_[Packet::Format::HF_INET6_TCP_AH].size(),
+ raw_packets_[Packet::Format::HF_INET6_TCP_AH].size());
+ testGetFormat(Packet::Format::HF_INET6_TCP_AH, p5);
+ }
+
+ // Let's try now creating empty packets
+ {
+ PacketForTest p0(Packet::Format::HF_INET_TCP);
+ testGetFormat(Packet::Format::HF_INET_TCP, p0);
+
+ PacketForTest p1(Packet::Format::HF_INET6_TCP);
+ testGetFormat(Packet::Format::HF_INET6_TCP, p1);
+
+ PacketForTest p2(Packet::Format::HF_INET_ICMP);
+ testGetFormat(Packet::Format::HF_INET_ICMP, p2);
+
+ PacketForTest p3(Packet::Format::HF_INET6_ICMP);
+ testGetFormat(Packet::Format::HF_INET6_ICMP, p3);
+
+ PacketForTest p4(Packet::Format::HF_INET_TCP_AH);
+ testGetFormat(Packet::Format::HF_INET_TCP_AH, p4);
+
+ PacketForTest p5(Packet::Format::HF_INET6_TCP_AH);
+ testGetFormat(Packet::Format::HF_INET6_TCP_AH, p5);
+ }
+}
+
+TEST_F(PacketTest, SetGetTestSignatureTimestamp) {
+ // Let's try to set the signature timestamp in a packet without AH header. We
+ // expect an exception.
+ using namespace std::chrono;
+ uint64_t now =
+ duration_cast<milliseconds>(system_clock::now().time_since_epoch())
+ .count();
+
+ try {
+ packet.setSignatureTimestamp(now);
+ FAIL() << "We should not reach this point.";
+ } catch (const errors::RuntimeException &exc) {
+ /* ok right exception*/
+ } catch (...) {
+ FAIL() << "Unexpected exception";
+ }
+
+ // Same fot get method
+ try {
+ auto t = packet.getSignatureTimestamp();
+ // Let's make compiler happy
+ (void)t;
+ FAIL() << "We should not reach this point.";
+ } catch (const errors::RuntimeException &exc) {
+ /* ok right exception*/
+ } catch (...) {
+ FAIL() << "Unexpected exception";
+ }
+
+ // Now let's construct a AH packet, with no additional space for signature
+ PacketForTest p(HF_INET6_TCP_AH);
+ p.setSignatureTimestamp(now);
+ uint64_t now_get = p.getSignatureTimestamp();
+
+ // Check we got the right value
+ EXPECT_EQ(now_get, now);
+}
+
+TEST_F(PacketTest, TestSetGetValidationAlgorithm) {
+ // Let's try to set the validation algorithm in a packet without AH header. We
+ // expect an exception.
+
+ try {
+ packet.setValidationAlgorithm(auth::CryptoSuite::RSA_SHA256);
+ FAIL() << "We should not reach this point.";
+ } catch (const errors::RuntimeException &exc) {
+ /* ok right exception*/
+ } catch (...) {
+ FAIL() << "Unexpected exception";
+ }
+
+ // Same fot get method
+ try {
+ auto v = packet.getSignatureTimestamp();
+ // Let's make compiler happy
+ (void)v;
+ FAIL() << "We should not reach this point.";
+ } catch (const errors::RuntimeException &exc) {
+ /* ok right exception*/
+ } catch (...) {
+ FAIL() << "Unexpected exception";
+ }
+
+ // Now let's construct a AH packet, with no additional space for signature
+ PacketForTest p(HF_INET6_TCP_AH);
+ p.setValidationAlgorithm(auth::CryptoSuite::RSA_SHA256);
+ auto v_get = p.getValidationAlgorithm();
+
+ // Check we got the right value
+ EXPECT_EQ(v_get, auth::CryptoSuite::RSA_SHA256);
+}
+
+TEST_F(PacketTest, TestSetGetKeyId) {
+ uint8_t key[32];
+ auth::KeyId key_id = std::make_pair(key, sizeof(key));
+
+ try {
+ packet.setKeyId(key_id);
+ FAIL() << "We should not reach this point.";
+ } catch (const errors::RuntimeException &exc) {
+ /* ok right exception*/
+ } catch (...) {
+ FAIL() << "Unexpected exception";
+ }
+
+ // Same fot get method
+ try {
+ auto k = packet.getKeyId();
+ // Let's make compiler happy
+ (void)k;
+ FAIL() << "We should not reach this point.";
+ } catch (const errors::RuntimeException &exc) {
+ /* ok right exception*/
+ } catch (...) {
+ FAIL() << "Unexpected exception";
+ }
+
+ // Now let's construct a AH packet, with no additional space for signature
+ PacketForTest p(HF_INET6_TCP_AH);
+ p.setKeyId(key_id);
+ auto p_get = p.getKeyId();
+
+ // Check we got the right value
+ EXPECT_EQ(p_get.second, key_id.second);
+
+ auto ret = memcmp(p_get.first, key_id.first, p_get.second);
+ EXPECT_EQ(ret, 0);
+}
+
+TEST_F(PacketTest, DISABLED_TestChecksum) {
+ // Checksum should be wrong
+ bool integrity = packet.checkIntegrity();
+ EXPECT_FALSE(integrity);
+
+ // Let's fix it
+ packet.setChecksum();
+
+ // Check again
+ integrity = packet.checkIntegrity();
+ EXPECT_TRUE(integrity);
+
+ // Check with AH header and 300 bytes signature
+ PacketForTest p(HF_INET6_TCP_AH, 300);
+ std::string payload(5000, 'X');
+ p.appendPayload((const uint8_t *)payload.c_str(), payload.size() / 2);
+ p.appendPayload((const uint8_t *)(payload.c_str() + payload.size() / 2),
+ payload.size() / 2);
+
+ p.setChecksum();
+ integrity = p.checkIntegrity();
+ EXPECT_TRUE(integrity);
+}
+
+TEST_F(PacketTest, TestSetSyn) {
+ // Test syn of non-tcp format and check exception is thrown
+ try {
+ auto p = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0],
+ raw_packets_[HF_INET6_ICMP].size(),
+ raw_packets_[HF_INET6_ICMP].size());
+ // Let's make compiler happy
+ p.setSyn();
+ FAIL() << "We should not reach this point.";
+ } catch (const errors::RuntimeException &exc) {
+ /* ok right exception*/
+ } catch (...) {
+ FAIL() << "Unexpected exception";
+ }
+
+ packet.setSyn();
+ EXPECT_TRUE(packet.testSyn());
+
+ packet.resetSyn();
+ EXPECT_FALSE(packet.testSyn());
+}
+
+TEST_F(PacketTest, TestSetFin) {
+ // Test syn of non-tcp format and check exception is thrown
+ try {
+ auto p = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0],
+ raw_packets_[HF_INET6_ICMP].size(),
+ raw_packets_[HF_INET6_ICMP].size());
+ // Let's make compiler happy
+ p.setFin();
+ FAIL() << "We should not reach this point.";
+ } catch (const errors::RuntimeException &exc) {
+ /* ok right exception*/
+ } catch (...) {
+ FAIL() << "Unexpected exception";
+ }
+
+ packet.setFin();
+ EXPECT_TRUE(packet.testFin());
+
+ packet.resetFin();
+ EXPECT_FALSE(packet.testFin());
+}
+
+TEST_F(PacketTest, TestSetAck) {
+ // Test syn of non-tcp format and check exception is thrown
+ try {
+ auto p = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0],
+ raw_packets_[HF_INET6_ICMP].size(),
+ raw_packets_[HF_INET6_ICMP].size());
+ // Let's make compiler happy
+ p.setAck();
+ FAIL() << "We should not reach this point.";
+ } catch (const errors::RuntimeException &exc) {
+ /* ok right exception*/
+ } catch (...) {
+ FAIL() << "Unexpected exception";
+ }
+
+ packet.setAck();
+ EXPECT_TRUE(packet.testAck());
+
+ packet.resetAck();
+ EXPECT_FALSE(packet.testAck());
+}
+
+TEST_F(PacketTest, TestSetRst) {
+ // Test syn of non-tcp format and check exception is thrown
+ try {
+ auto p = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0],
+ raw_packets_[HF_INET6_ICMP].size(),
+ raw_packets_[HF_INET6_ICMP].size());
+ // Let's make compiler happy
+ p.setRst();
+ FAIL() << "We should not reach this point.";
+ } catch (const errors::RuntimeException &exc) {
+ /* ok right exception*/
+ } catch (...) {
+ FAIL() << "Unexpected exception";
+ }
+
+ packet.setRst();
+ EXPECT_TRUE(packet.testRst());
+
+ packet.resetRst();
+ EXPECT_FALSE(packet.testRst());
+}
+
+TEST_F(PacketTest, TestResetFlags) {
+ packet.setRst();
+ packet.setSyn();
+ packet.setAck();
+ packet.setFin();
+ EXPECT_TRUE(packet.testRst());
+ EXPECT_TRUE(packet.testAck());
+ EXPECT_TRUE(packet.testFin());
+ EXPECT_TRUE(packet.testSyn());
+
+ packet.resetFlags();
+ EXPECT_FALSE(packet.testRst());
+ EXPECT_FALSE(packet.testAck());
+ EXPECT_FALSE(packet.testFin());
+ EXPECT_FALSE(packet.testSyn());
+}
+
+TEST_F(PacketTest, TestSetGetSrcPort) {
+ try {
+ auto p = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0],
+ raw_packets_[HF_INET6_ICMP].size(),
+ raw_packets_[HF_INET6_ICMP].size());
+ // Let's make compiler happy
+ p.setSrcPort(12345);
+ FAIL() << "We should not reach this point.";
+ } catch (const errors::RuntimeException &exc) {
+ /* ok right exception*/
+ } catch (...) {
+ FAIL() << "Unexpected exception";
+ }
+
+ packet.setSrcPort(12345);
+ EXPECT_EQ(packet.getSrcPort(), 12345);
+}
+
+TEST_F(PacketTest, TestSetGetDstPort) {
+ try {
+ auto p = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0],
+ raw_packets_[HF_INET6_ICMP].size(),
+ raw_packets_[HF_INET6_ICMP].size());
+ // Let's make compiler happy
+ p.setDstPort(12345);
+ FAIL() << "We should not reach this point.";
+ } catch (const errors::RuntimeException &exc) {
+ /* ok right exception*/
+ } catch (...) {
+ FAIL() << "Unexpected exception";
+ }
+
+ packet.setDstPort(12345);
+ EXPECT_EQ(packet.getDstPort(), 12345);
+}
+
+TEST_F(PacketTest, TestEnsureCapacity) {
+ PacketForTest &p = packet;
+
+ // This shoul be false
+ auto ret = p.ensureCapacity(raw_packets_[HF_INET6_TCP].size() + 10);
+ EXPECT_FALSE(ret);
+
+ // This should be true
+ ret = p.ensureCapacity(raw_packets_[HF_INET6_TCP].size());
+ EXPECT_TRUE(ret);
+
+ // This should be true
+ ret = p.ensureCapacity(raw_packets_[HF_INET6_TCP].size() - 10);
+ EXPECT_TRUE(ret);
+
+ // Try to trim the packet start
+ p.trimStart(10);
+ // Now this should be false
+ ret = p.ensureCapacity(raw_packets_[HF_INET6_TCP].size());
+ EXPECT_FALSE(ret);
+
+ // Create a new packet
+ auto p2 = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0],
+ raw_packets_[HF_INET6_ICMP].size(),
+ raw_packets_[HF_INET6_ICMP].size());
+
+ p2.appendPayload(utils::MemBuf::createCombined(2000));
+
+ // This should be false, since the buffer is chained
+ ret = p2.ensureCapacity(raw_packets_[HF_INET6_TCP].size() - 10);
+ EXPECT_FALSE(ret);
+}
+
+TEST_F(PacketTest, TestEnsureCapacityAndFillUnused) {
+ // Create packet by excluding the payload (So only L3 + L4 headers). The
+ // payload will be trated as unused tailroom
+ PacketForTest p =
+ PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_TCP][0],
+ raw_packets_[HF_INET6_TCP].size() - PAYLOAD_SIZE,
+ raw_packets_[HF_INET6_TCP].size());
+
+ // Copy original packet payload, which is here trated as a unused tailroom
+ uint8_t original_payload[PAYLOAD_SIZE];
+ uint8_t *payload = &raw_packets_[HF_INET6_TCP][0] +
+ raw_packets_[HF_INET6_TCP].size() - PAYLOAD_SIZE;
+ std::memcpy(original_payload, payload, PAYLOAD_SIZE);
+
+ // This should be true and the unused tailroom should be unmodified
+ auto ret = p.ensureCapacityAndFillUnused(
+ raw_packets_[HF_INET6_TCP].size() - (PAYLOAD_SIZE + 10), 0);
+ EXPECT_TRUE(ret);
+ ret = std::memcmp(original_payload, payload, PAYLOAD_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ // This should fill the payload with zeros
+ ret = p.ensureCapacityAndFillUnused(raw_packets_[HF_INET6_TCP].size(), 0);
+ EXPECT_TRUE(ret);
+ uint8_t zeros[PAYLOAD_SIZE];
+ std::memset(zeros, 0, PAYLOAD_SIZE);
+ ret = std::memcmp(payload, zeros, PAYLOAD_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ // This should fill the payload with ones
+ ret = p.ensureCapacityAndFillUnused(raw_packets_[HF_INET6_TCP].size(), 1);
+ EXPECT_TRUE(ret);
+ uint8_t ones[PAYLOAD_SIZE];
+ std::memset(ones, 1, PAYLOAD_SIZE);
+ ret = std::memcmp(payload, ones, PAYLOAD_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ // This should return false and the payload should be unmodified
+ ret = p.ensureCapacityAndFillUnused(raw_packets_[HF_INET6_TCP].size() + 1, 1);
+ EXPECT_FALSE(ret);
+ ret = std::memcmp(payload, ones, PAYLOAD_SIZE);
+ EXPECT_EQ(ret, 0);
+}
+
+TEST_F(PacketTest, TestSetGetTTL) {
+ packet.setTTL(128);
+ EXPECT_EQ(packet.getTTL(), 128);
+}
+
+} // namespace core
+} // namespace transport
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/libtransport/src/protocols/test/test_transport_producer.cc b/libtransport/src/test/test_transport_producer.cc
index 204f2cbe2..f711fb4bb 100644
--- a/libtransport/src/protocols/test/test_transport_producer.cc
+++ b/libtransport/src/test/test_transport_producer.cc
@@ -15,21 +15,19 @@
#include <gtest/gtest.h>
-#include "../socket_producer.h"
-#include "literals.h"
-
-#include <test.h>
#include <random>
+#include "hicn/transport/interfaces/socket_producer.h"
+
namespace transport {
-namespace protocol {
+namespace interface {
namespace {
// The fixture for testing class Foo.
class ProducerTest : public ::testing::Test {
protected:
- ProducerTest() : name_("b001::123|321"), producer_(io_service_) {
+ ProducerTest() : name_("b001::123|321"), producer_() {
// You can do set-up work for each test here.
}
@@ -51,26 +49,14 @@ class ProducerTest : public ::testing::Test {
}
Name name_;
- asio::io_service io_service_;
ProducerSocket producer_;
};
} // namespace
-// Tests that the Foo::Bar() method does Abc.
-TEST_F(ProducerTest, ProduceContent) {
- std::string content(250000, '?');
-
- producer_.registerPrefix(Prefix("b001::/64"));
- producer_.produce(name_, reinterpret_cast<const uint8_t *>(content.data()),
- content.size(), true);
- producer_.setSocketOption(GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
- 500000000_U32);
- producer_.attach();
- producer_.serveForever();
-}
+TEST_F(ProducerTest, ProduceContent) { ASSERT_TRUE(true); }
-} // namespace protocol
+} // namespace interface
} // namespace transport
diff --git a/libtransport/src/transport.config b/libtransport/src/transport.config
new file mode 100644
index 000000000..a21175b8d
--- /dev/null
+++ b/libtransport/src/transport.config
@@ -0,0 +1,27 @@
+// Configuration for io_module
+
+io_module = {
+ path = [];
+ name = "forwarder_module";
+};
+
+forwarder = {
+ n_threads = 1;
+
+ listeners = {
+ l0 = {
+ local_address = "127.0.0.1";
+ local_port = 33436;
+ }
+ };
+
+ connectors = {
+ c0 = {
+ /* local_address and local_port are optional */
+ local_address = "127.0.0.1";
+ local_port = 33436;
+ remote_address = "10.20.30.40";
+ remote_port = 33436;
+ }
+ };
+}; \ No newline at end of file
diff --git a/libtransport/src/utils/CMakeLists.txt b/libtransport/src/utils/CMakeLists.txt
index 88d451b6b..1a23459b5 100644
--- a/libtransport/src/utils/CMakeLists.txt
+++ b/libtransport/src/utils/CMakeLists.txt
@@ -27,7 +27,6 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/min_filter.h
${CMAKE_CURRENT_SOURCE_DIR}/stream_buffer.h
${CMAKE_CURRENT_SOURCE_DIR}/suffix_strategy.h
- ${CMAKE_CURRENT_SOURCE_DIR}/event_thread.h
${CMAKE_CURRENT_SOURCE_DIR}/content_store.h
${CMAKE_CURRENT_SOURCE_DIR}/deadline_timer.h
)
diff --git a/libtransport/src/utils/content_store.cc b/libtransport/src/utils/content_store.cc
index cb3db6d94..c5cb91149 100644
--- a/libtransport/src/utils/content_store.cc
+++ b/libtransport/src/utils/content_store.cc
@@ -17,7 +17,6 @@
#include <hicn/transport/core/interest.h>
#include <hicn/transport/core/name.h>
#include <hicn/transport/utils/log.h>
-
#include <utils/content_store.h>
namespace utils {
@@ -60,8 +59,7 @@ void ContentStore::insert(
ObjectTimeEntry(content_object, std::chrono::steady_clock::now()), pos);
}
-const std::shared_ptr<ContentObject> ContentStore::find(
- const Interest &interest) {
+std::shared_ptr<ContentObject> ContentStore::find(const Interest &interest) {
utils::SpinLock::Acquire locked(cs_mutex_);
std::shared_ptr<ContentObject> ret = empty_reference_;
diff --git a/libtransport/src/utils/content_store.h b/libtransport/src/utils/content_store.h
index 03ce76f42..56cd2abb6 100644
--- a/libtransport/src/utils/content_store.h
+++ b/libtransport/src/utils/content_store.h
@@ -52,7 +52,7 @@ class ContentStore {
void insert(const std::shared_ptr<ContentObject> &content_object);
- const std::shared_ptr<ContentObject> find(const Interest &interest);
+ std::shared_ptr<ContentObject> find(const Interest &interest);
void erase(const Name &exact_name);
diff --git a/libtransport/src/utils/daemonizator.cc b/libtransport/src/utils/daemonizator.cc
index c51a68d14..bc7bae700 100644
--- a/libtransport/src/utils/daemonizator.cc
+++ b/libtransport/src/utils/daemonizator.cc
@@ -17,7 +17,6 @@
#include <hicn/transport/errors/runtime_exception.h>
#include <hicn/transport/utils/daemonizator.h>
#include <hicn/transport/utils/log.h>
-
#include <sys/stat.h>
#include <unistd.h>
diff --git a/libtransport/src/utils/epoll_event_reactor.cc b/libtransport/src/utils/epoll_event_reactor.cc
index 0e6590d0e..eb8c65352 100644
--- a/libtransport/src/utils/epoll_event_reactor.cc
+++ b/libtransport/src/utils/epoll_event_reactor.cc
@@ -14,12 +14,11 @@
*/
#include <hicn/transport/utils/branch_prediction.h>
-
+#include <signal.h>
+#include <unistd.h>
#include <utils/epoll_event_reactor.h>
#include <utils/fd_deadline_timer.h>
-#include <signal.h>
-#include <unistd.h>
#include <iostream>
namespace utils {
@@ -104,12 +103,15 @@ void EpollEventReactor::runEventLoop(int timeout) {
while (run_event_loop_) {
memset(&evt, 0, sizeof(evt));
-
en = epoll_pwait(epoll_fd_, evt, 128, timeout, &sigset);
if (TRANSPORT_EXPECT_FALSE(en < 0)) {
TRANSPORT_LOGE("epoll_pwait: %s", strerror(errno));
- return;
+ if (errno == EINTR) {
+ continue;
+ } else {
+ return;
+ }
}
for (int i = 0; i < en; i++) {
diff --git a/libtransport/src/utils/epoll_event_reactor.h b/libtransport/src/utils/epoll_event_reactor.h
index 4cb87ebd4..9ebfca937 100644
--- a/libtransport/src/utils/epoll_event_reactor.h
+++ b/libtransport/src/utils/epoll_event_reactor.h
@@ -16,9 +16,9 @@
#pragma once
#include <hicn/transport/utils/spinlock.h>
+#include <sys/epoll.h>
#include <utils/event_reactor.h>
-#include <sys/epoll.h>
#include <atomic>
#include <cstddef>
#include <functional>
diff --git a/libtransport/src/utils/event_thread.h b/libtransport/src/utils/event_thread.h
deleted file mode 100644
index e50ae9648..000000000
--- a/libtransport/src/utils/event_thread.h
+++ /dev/null
@@ -1,99 +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.
- */
-
-#pragma once
-
-#include <hicn/transport/errors/runtime_exception.h>
-#include <memory>
-
-#include <asio.hpp>
-
-namespace utils {
-
-class EventThread {
- private:
- // No copies
- EventThread(const EventThread&) = delete; // non construction-copyable
- EventThread& operator=(const EventThread&) = delete; // non copyable
-
- public:
- explicit EventThread(asio::io_service& io_service)
- : internal_io_service_(nullptr),
- io_service_(io_service),
- work_(io_service_),
- thread_(nullptr) {
- run();
- }
-
- explicit EventThread()
- : internal_io_service_(std::make_unique<asio::io_service>()),
- io_service_(*internal_io_service_),
- work_(io_service_),
- thread_(nullptr) {
- run();
- }
-
- ~EventThread() { stop(); }
-
- void run() {
- if (stopped()) {
- io_service_.reset();
- }
-
- thread_ = std::make_unique<std::thread>([this]() { io_service_.run(); });
- }
-
- std::thread::id getThreadId() const {
- if (thread_) {
- return thread_->get_id();
- } else {
- throw errors::RuntimeException("Event thread is not running.");
- }
- }
-
- template <typename Func>
- void add(Func&& f) {
- // If the function f
- // TODO USe post in mac os, asio->post in xenial
- io_service_.post(std::forward<Func&&>(f));
- }
-
- template <typename Func>
- void tryRunHandlerNow(Func&& f) {
- io_service_.dispatch(std::forward<Func&&>(f));
- }
-
- void stop() {
- io_service_.stop();
-
- if (thread_ && thread_->joinable()) {
- thread_->join();
- }
-
- thread_.reset();
- }
-
- bool stopped() { return io_service_.stopped(); }
-
- asio::io_service& getIoService() { return io_service_; }
-
- private:
- std::unique_ptr<asio::io_service> internal_io_service_;
- asio::io_service& io_service_;
- asio::io_service::work work_;
- std::unique_ptr<std::thread> thread_;
-};
-
-} // namespace utils \ No newline at end of file
diff --git a/libtransport/src/utils/fd_deadline_timer.h b/libtransport/src/utils/fd_deadline_timer.h
index 8bc3bbca3..38396e027 100644
--- a/libtransport/src/utils/fd_deadline_timer.h
+++ b/libtransport/src/utils/fd_deadline_timer.h
@@ -17,16 +17,14 @@
#include <hicn/transport/errors/runtime_exception.h>
#include <hicn/transport/utils/log.h>
-
+#include <sys/timerfd.h>
+#include <unistd.h>
#include <utils/deadline_timer.h>
#include <utils/epoll_event_reactor.h>
#include <chrono>
#include <cstddef>
-#include <sys/timerfd.h>
-#include <unistd.h>
-
namespace utils {
class FdDeadlineTimer : public DeadlineTimer<FdDeadlineTimer> {
diff --git a/libtransport/src/utils/membuf.cc b/libtransport/src/utils/membuf.cc
index 94e5b13a1..73c45cf6d 100644
--- a/libtransport/src/utils/membuf.cc
+++ b/libtransport/src/utils/membuf.cc
@@ -145,6 +145,18 @@ void MemBuf::operator delete(void* /* ptr */, void* /* placement */) {
// constructor.
}
+bool MemBuf::operator==(const MemBuf& other) {
+ if (length() != other.length()) {
+ return false;
+ }
+
+ return (memcmp(data(), other.data(), length()) == 0);
+}
+
+bool MemBuf::operator!=(const MemBuf& other) {
+ return !this->operator==(other);
+}
+
void MemBuf::releaseStorage(HeapStorage* storage, uint16_t freeFlags) {
// Use relaxed memory order here. If we are unlucky and happen to get
// out-of-date data the compare_exchange_weak() call below will catch
@@ -299,21 +311,23 @@ unique_ptr<MemBuf> MemBuf::takeOwnership(void* buf, std::size_t capacity,
}
}
-MemBuf::MemBuf(WrapBufferOp, const void* buf, std::size_t capacity) noexcept
+MemBuf::MemBuf(WrapBufferOp, const void* buf, std::size_t length,
+ std::size_t capacity) noexcept
: MemBuf(InternalConstructor(), 0,
// We cast away the const-ness of the buffer here.
// This is okay since MemBuf users must use unshare() to create a
// copy of this buffer before writing to the buffer.
static_cast<uint8_t*>(const_cast<void*>(buf)), capacity,
- static_cast<uint8_t*>(const_cast<void*>(buf)), capacity) {}
+ static_cast<uint8_t*>(const_cast<void*>(buf)), length) {}
-unique_ptr<MemBuf> MemBuf::wrapBuffer(const void* buf, std::size_t capacity) {
- return std::make_unique<MemBuf>(WRAP_BUFFER, buf, capacity);
+unique_ptr<MemBuf> MemBuf::wrapBuffer(const void* buf, std::size_t length,
+ std::size_t capacity) {
+ return std::make_unique<MemBuf>(WRAP_BUFFER, buf, length, capacity);
}
-MemBuf MemBuf::wrapBufferAsValue(const void* buf,
+MemBuf MemBuf::wrapBufferAsValue(const void* buf, std::size_t length,
std::size_t capacity) noexcept {
- return MemBuf(WrapBufferOp::WRAP_BUFFER, buf, capacity);
+ return MemBuf(WrapBufferOp::WRAP_BUFFER, buf, length, capacity);
}
MemBuf::MemBuf() noexcept {}
@@ -862,4 +876,22 @@ void MemBuf::initExtBuffer(uint8_t* buf, size_t mallocSize,
*infoReturn = sharedInfo;
}
+bool MemBuf::ensureCapacity(std::size_t capacity) {
+ return !isChained() && std::size_t((bufferEnd() - data())) >= capacity;
+}
+
+bool MemBuf::ensureCapacityAndFillUnused(std::size_t capacity,
+ uint8_t placeholder) {
+ auto ret = ensureCapacity(capacity);
+ if (!ret) {
+ return ret;
+ }
+
+ if (length() < capacity) {
+ std::memset(writableTail(), placeholder, capacity - length());
+ }
+
+ return ret;
+}
+
} // namespace utils \ No newline at end of file
diff --git a/libtransport/src/utils/memory_pool_allocator.h b/libtransport/src/utils/memory_pool_allocator.h
index adc1443ad..a960b91bb 100644
--- a/libtransport/src/utils/memory_pool_allocator.h
+++ b/libtransport/src/utils/memory_pool_allocator.h
@@ -149,4 +149,4 @@ class Allocator : private MemoryPool<T, growSize> {
void destroy(pointer p) { p->~T(); }
};
-} \ No newline at end of file
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/src/utils/min_filter.h b/libtransport/src/utils/min_filter.h
index dcfd5652d..f1aaea7a8 100644
--- a/libtransport/src/utils/min_filter.h
+++ b/libtransport/src/utils/min_filter.h
@@ -43,6 +43,11 @@ class MinFilter {
by_arrival_.push_front(by_order_.insert(std::forward<R>(value)));
}
+ TRANSPORT_ALWAYS_INLINE void clear() {
+ by_arrival_.clear();
+ by_order_.clear();
+ }
+
TRANSPORT_ALWAYS_INLINE const T& begin() { return *by_order_.cbegin(); }
TRANSPORT_ALWAYS_INLINE const T& rBegin() { return *by_order_.crbegin(); }
diff --git a/scripts/build-packages.sh b/scripts/build-packages.sh
index efc1b6717..781dbc9bd 100644
--- a/scripts/build-packages.sh
+++ b/scripts/build-packages.sh
@@ -30,9 +30,17 @@ function build_package() {
# Make the package
mkdir -p ${SCRIPT_PATH}/../build && pushd ${SCRIPT_PATH}/../build
rm -rf *
- # First round
- cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_APPS=ON ..
+
+ cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/usr \
+ -DBUILD_HICNPLUGIN=ON \
+ -DBUILD_LIBTRANSPORT=ON \
+ -DBUILD_APPS=ON \
+ -DBUILD_HICNLIGHT=ON \
+ -DBUILD_TELEMETRY=ON \
+ ${SCRIPT_PATH}/..
+
ninja -j8 package
+
find . -not -name '*.deb' -not -name '*.rpm' -print0 | xargs -0 rm -rf -- || true
rm *Unspecified* || true
popd
diff --git a/scripts/functions.sh b/scripts/functions.sh
index 7796935ef..9cb62b5cc 100644
--- a/scripts/functions.sh
+++ b/scripts/functions.sh
@@ -49,14 +49,22 @@ DEPS_UBUNTU=("build-essential"
"libmemif"
"libasio-dev"
"libconfig-dev"
+ "libconfig++-dev"
"libcurl4-openssl-dev"
"libevent-dev"
"libssl-dev"
"ninja-build"
+ "vpp=${VPP_VERSION_DEB}"
+ "vpp-dev=${VPP_VERSION_DEB}"
+ "libvppinfra=${VPP_VERSION_DEB}"
+ "libvppinfra-dev=${VPP_VERSION_DEB}"
+ "vpp-plugin-core=${VPP_VERSION_DEB}"
"python3-ply")
# BUILD_TOOLS_GROUP_CENTOS="'Development Tools'"
-DEPS_CENTOS=("libparc-devel"
+DEPS_CENTOS=("vpp-devel-${VPP_VERSION_RPM}"
+ "vpp-lib-${VPP_VERSION_RPM}"
+ "libparc-devel"
"curl"
"libmemif-devel"
"ninja-build"
diff --git a/telemetry/vpp-collectd/CMakeLists.txt b/telemetry/vpp-collectd/CMakeLists.txt
index ef09fb980..8f82745f2 100644
--- a/telemetry/vpp-collectd/CMakeLists.txt
+++ b/telemetry/vpp-collectd/CMakeLists.txt
@@ -13,7 +13,7 @@
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
-set (COLLECTD_PLUGINS hicn-collectd-plugins)
+set(COLLECTD_PLUGINS hicn-collectd-plugins)
project(hicn-collectd-plugins)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/" "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules/")
diff --git a/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt b/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt
index fc39b9385..3703515dc 100644
--- a/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt
+++ b/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt
@@ -18,7 +18,7 @@ find_package(Collectd REQUIRED)
find_package(Vpp REQUIRED)
if(${CMAKE_SOURCE_DIR}/vpp-collectd STREQUAL ${PROJECT_SOURCE_DIR})
- message (STATUS "not compiling in the same folder")
+ message (STATUS "not compiling in the same folder")
find_package(HicnPlugin REQUIRED)
find_package(VapiSafe REQUIRED)
else()
@@ -29,17 +29,16 @@ else()
endif()
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/vpp_hicn.c
-)
+ ${CMAKE_CURRENT_SOURCE_DIR}/vpp_hicn.c)
-list (APPEND INCLUDE_DIRS
+list(APPEND INCLUDE_DIRS
${COLLECTD_INCLUDE_DIRS}
${HICNPLUGIN_INCLUDE_DIRS}
${SAFE_VAPI_INCLUDE_DIRS}
${VPP_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR})
-list (APPEND LIBRARIES
+list(APPEND LIBRARIES
${VPP_LIBRARY_VAPICLIENT}
${SAFE_VAPI_LIBRARIES})
diff --git a/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c b/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
index 591b8f584..4228ac6e6 100644
--- a/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
+++ b/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
@@ -13,25 +13,9 @@
* limitations under the License.
*/
-#if !HAVE_CONFIG_H
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef __USE_ISOC99 /* required for NAN */
-#define DISABLE_ISOC99 1
-#define __USE_ISOC99 1
-#endif /* !defined(__USE_ISOC99) */
-
-#if DISABLE_ISOC99
-#undef DISABLE_ISOC99
-#undef __USE_ISOC99
-#endif /* DISABLE_ISOC99 */
-#endif /* ! HAVE_CONFIG */
-
/* Keep order as it is */
#include <config.h>
#include <collectd.h>
-#include <common.h>
#include <plugin.h>
#define counter_t vpp_counter_t
@@ -42,6 +26,15 @@
DEFINE_VAPI_MSG_IDS_HICN_API_JSON
vapi_ctx_t vapi_ctx;
+#define STATIC_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+
+#define IS_TRUE(s) \
+ ((strcasecmp("true", (s)) == 0) || (strcasecmp("yes", (s)) == 0) || \
+ (strcasecmp("on", (s)) == 0))
+#define IS_FALSE(s) \
+ ((strcasecmp("false", (s)) == 0) || (strcasecmp("no", (s)) == 0) || \
+ (strcasecmp("off", (s)) == 0))
+
/************** OPTIONS ***********************************/
static const char *config_keys[2] = {
"Verbose",
@@ -188,6 +181,11 @@ static data_set_t dtx_ds = {
/**********************************************************/
/********** UTILITY FUNCTIONS *****************************/
/**********************************************************/
+char *sstrncpy(char *dest, const char *src, size_t n) {
+ strncpy(dest, src, n);
+ dest[n - 1] = '\0';
+ return dest;
+}
/*
* Utility function used by the read callback to populate a
diff --git a/telemetry/vpp-collectd/vpp/CMakeLists.txt b/telemetry/vpp-collectd/vpp/CMakeLists.txt
index 36248b17a..464ab42d8 100644
--- a/telemetry/vpp-collectd/vpp/CMakeLists.txt
+++ b/telemetry/vpp-collectd/vpp/CMakeLists.txt
@@ -14,22 +14,20 @@
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
# Dependencies
-
-list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/vpp.c
-)
-
find_package(Vpp REQUIRED)
find_package(Collectd REQUIRED)
-list (APPEND INCLUDE_DIRS
- ${COLLECTD_INCLUDE_DIRS}
- ${VPP_INCLUDE_DIRS}
- ${CMAKE_CURRENT_SOURCE_DIR})
+list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/vpp.c)
+
+list(APPEND INCLUDE_DIRS
+ ${COLLECTD_INCLUDE_DIRS}
+ ${VPP_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_SOURCE_DIR})
-list (APPEND LIBRARIES
- ${VPP_LIBRARY_VPPAPICLIENT}
- ${VPP_LIBRARY_INFRA})
+list(APPEND LIBRARIES
+ ${VPP_LIBRARY_VPPAPICLIENT}
+ ${VPP_LIBRARY_INFRA})
build_library(vpp
SHARED
diff --git a/telemetry/vpp-collectd/vpp/vpp.c b/telemetry/vpp-collectd/vpp/vpp.c
index 679f8feb4..8bf5182a8 100644
--- a/telemetry/vpp-collectd/vpp/vpp.c
+++ b/telemetry/vpp-collectd/vpp/vpp.c
@@ -13,25 +13,9 @@
* limitations under the License.
*/
-#if !HAVE_CONFIG_H
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef __USE_ISOC99 /* required for NAN */
-#define DISABLE_ISOC99 1
-#define __USE_ISOC99 1
-#endif /* !defined(__USE_ISOC99) */
-
-#if DISABLE_ISOC99
-#undef DISABLE_ISOC99
-#undef __USE_ISOC99
-#endif /* DISABLE_ISOC99 */
-#endif /* ! HAVE_CONFIG */
-
/* Keep order as it is */
#include <config.h>
#include <collectd.h>
-#include <common.h>
#include <plugin.h>
#define counter_t vpp_counter_t
@@ -39,6 +23,15 @@
#include <vppinfra/vec.h>
#undef counter_t
+#define STATIC_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+
+#define IS_TRUE(s) \
+ ((strcasecmp("true", (s)) == 0) || (strcasecmp("yes", (s)) == 0) || \
+ (strcasecmp("on", (s)) == 0))
+#define IS_FALSE(s) \
+ ((strcasecmp("false", (s)) == 0) || (strcasecmp("no", (s)) == 0) || \
+ (strcasecmp("off", (s)) == 0))
+
/************** OPTIONS ***********************************/
static const char *config_keys[2] = {
"Verbose",
@@ -164,6 +157,11 @@ static data_set_t if_tx_broadcast_ds = {
/**********************************************************/
/********** UTILITY FUNCTIONS *****************************/
/**********************************************************/
+char *sstrncpy(char *dest, const char *src, size_t n) {
+ strncpy(dest, src, n);
+ dest[n - 1] = '\0';
+ return dest;
+}
/*
* Utility function used by the read callback to populate a
@@ -274,6 +272,9 @@ static int vpp_config(const char *key, const char *value) {
* This function is called once upon startup to initialize the plugin.
*/
static int vpp_init(void) {
+ /* Create a heap of 64MB */
+ clib_mem_init(0, 64ULL << 20);
+
u8 *stat_segment_name = (u8 *)STAT_SEGMENT_SOCKET_FILE;
int ret = stat_segment_connect((char *)stat_segment_name);
@@ -291,7 +292,6 @@ static int vpp_read(void) {
char **interfaces = {0};
vec_add1(patterns, (uint8_t *)"^/if");
- vec_add1(patterns, (uint8_t *)"ip4-input");
uint32_t *dir = stat_segment_ls(patterns);
stat_segment_data_t *res = stat_segment_dump(dir);
@@ -300,9 +300,7 @@ static int vpp_read(void) {
for (int k = 0; k < vec_len(res); k++) {
if (res[k].type == STAT_DIR_TYPE_NAME_VECTOR) {
for (int i = 0; i < vec_len(res[k].name_vector); i++) {
- if (res[k].name_vector[i]) {
- vec_add1(interfaces, (char *)res[k].name_vector[i]);
- }
+ vec_add1(interfaces, (char *)res[k].name_vector[i]);
}
break;
}
@@ -318,13 +316,17 @@ static int vpp_read(void) {
case STAT_DIR_TYPE_COUNTER_VECTOR_SIMPLE:
for (int k = 0; k < vec_len(res[i].simple_counter_vec); k++) {
for (int j = 0; j < vec_len(res[i].simple_counter_vec[k]); j++) {
- value_t values[1] = {
- (value_t){.derive = res[i].simple_counter_vec[k][j]}};
+ if (!interfaces[j]) {
+ continue;
+ }
if (get_data_set(res[i].name, &data_set)) {
continue;
}
+ value_t values[1] = {
+ (value_t){.derive = res[i].simple_counter_vec[k][j]}};
+
err = submit(interfaces[j], data_set.type, values, 1, &timestamp);
if (err)
@@ -336,15 +338,19 @@ static int vpp_read(void) {
case STAT_DIR_TYPE_COUNTER_VECTOR_COMBINED:
for (int k = 0; k < vec_len(res[i].combined_counter_vec); k++) {
for (int j = 0; j < vec_len(res[i].combined_counter_vec[k]); j++) {
- value_t values[2] = {
- (value_t){.derive = res[i].combined_counter_vec[k][j].packets},
- (value_t){.derive = res[i].combined_counter_vec[k][j].bytes},
- };
+ if (!interfaces[j]) {
+ continue;
+ }
if (get_data_set(res[i].name, &data_set)) {
continue;
}
+ value_t values[2] = {
+ (value_t){.derive = res[i].combined_counter_vec[k][j].packets},
+ (value_t){.derive = res[i].combined_counter_vec[k][j].bytes},
+ };
+
err = submit(interfaces[j], data_set.type, values, 2, &timestamp);
if (err)
diff --git a/utils/.clang-format b/utils/.clang-format
new file mode 100644
index 000000000..cd21e2017
--- /dev/null
+++ b/utils/.clang-format
@@ -0,0 +1,14 @@
+# Copyright (c) 2017-2021 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+BasedOnStyle: Google
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index d82425236..953b46339 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -16,6 +16,10 @@ set(CMAKE_CXX_STANDARD 14)
project(utils)
+if (WIN32)
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\"" )
+endif()
+
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules"
diff --git a/utils/src/hiperf.cc b/utils/src/hiperf.cc
index 151e4df3d..9a1cf6236 100644
--- a/utils/src/hiperf.cc
+++ b/utils/src/hiperf.cc
@@ -16,19 +16,16 @@
#include <hicn/transport/config.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
-#include <hicn/transport/interfaces/rtc_socket_producer.h>
+#include <hicn/transport/interfaces/global_conf_interface.h>
+#include <hicn/transport/interfaces/p2psecure_socket_consumer.h>
+#include <hicn/transport/interfaces/p2psecure_socket_producer.h>
#include <hicn/transport/interfaces/socket_consumer.h>
#include <hicn/transport/interfaces/socket_producer.h>
-#include <hicn/transport/security/identity.h>
-#include <hicn/transport/security/signer.h>
+#include <hicn/transport/auth/identity.h>
+#include <hicn/transport/auth/signer.h>
#include <hicn/transport/utils/chrono_typedefs.h>
#include <hicn/transport/utils/literals.h>
-#ifdef SECURE_HICNTRANSPORT
-#include <hicn/transport/interfaces/p2psecure_socket_consumer.h>
-#include <hicn/transport/interfaces/p2psecure_socket_producer.h>
-#endif
-
#ifndef _WIN32
#include <hicn/transport/utils/daemonizator.h>
#endif
@@ -37,6 +34,7 @@
#include <cmath>
#include <fstream>
#include <iomanip>
+#include <sstream>
#include <unordered_set>
#ifdef __linux__
@@ -50,7 +48,6 @@
#endif
namespace transport {
-
namespace interface {
#ifndef ERROR_SUCCESS
@@ -59,13 +56,50 @@ namespace interface {
#define ERROR_SETUP -5
#define MIN_PROBE_SEQ 0xefffffff
+struct packet_t {
+ uint64_t timestamp;
+ uint32_t size;
+};
+
+inline uint64_t _ntohll(const uint64_t *input) {
+ uint64_t return_val;
+ uint8_t *tmp = (uint8_t *)&return_val;
+
+ tmp[0] = (uint8_t)(*input >> 56);
+ tmp[1] = (uint8_t)(*input >> 48);
+ tmp[2] = (uint8_t)(*input >> 40);
+ tmp[3] = (uint8_t)(*input >> 32);
+ tmp[4] = (uint8_t)(*input >> 24);
+ tmp[5] = (uint8_t)(*input >> 16);
+ tmp[6] = (uint8_t)(*input >> 8);
+ tmp[7] = (uint8_t)(*input >> 0);
+
+ return return_val;
+}
+
+inline uint64_t _htonll(const uint64_t *input) { return (_ntohll(input)); }
+
+struct nack_packet_t {
+ uint64_t timestamp;
+ uint32_t prod_rate;
+ uint32_t prod_seg;
+
+ inline uint64_t getTimestamp() const { return _ntohll(&timestamp); }
+ inline void setTimestamp(uint64_t time) { timestamp = _htonll(&time); }
+
+ inline uint32_t getProductionRate() const { return ntohl(prod_rate); }
+ inline void setProductionRate(uint32_t rate) { prod_rate = htonl(rate); }
+
+ inline uint32_t getProductionSegement() const { return ntohl(prod_seg); }
+ inline void setProductionSegement(uint32_t seg) { prod_seg = htonl(seg); }
+};
+
/**
* Container for command line configuration for hiperf client.
*/
struct ClientConfiguration {
ClientConfiguration()
: name("b001::abcd", 0),
- verify(false),
beta(-1.f),
drop_factor(-1.f),
window(-1),
@@ -78,15 +112,11 @@ struct ClientConfiguration {
transport_protocol_(CBR),
rtc_(false),
test_mode_(false),
-#ifdef SECURE_HICNTRANSPORT
secure_(false),
-#endif
producer_prefix_(),
- interest_lifetime_(500) {
- }
+ interest_lifetime_(500) {}
Name name;
- bool verify;
double beta;
double drop_factor;
double window;
@@ -99,9 +129,7 @@ struct ClientConfiguration {
TransportProtocolAlgorithms transport_protocol_;
bool rtc_;
bool test_mode_;
-#ifdef SECURE_HICNTRANSPORT
bool secure_;
-#endif
Prefix producer_prefix_;
uint32_t interest_lifetime_;
};
@@ -155,23 +183,20 @@ struct ServerConfiguration {
live_production(false),
sign(false),
content_lifetime(600000000_U32),
- content_object_size(1440),
download_size(20 * 1024 * 1024),
- hash_algorithm(utils::CryptoHashType::SHA_256),
+ hash_algorithm(auth::CryptoHashType::SHA_256),
keystore_name(""),
passphrase(""),
keystore_password("cisco"),
multiphase_produce_(false),
rtc_(false),
interactive_(false),
+ trace_based_(false),
+ trace_index_(0),
+ trace_file_(nullptr),
production_rate_(std::string("2048kbps")),
- payload_size_(1440)
-#ifdef SECURE_HICNTRANSPORT
- ,
- secure_(false)
-#endif
- {
- }
+ payload_size_(1400),
+ secure_(false) {}
Prefix name;
bool virtual_producer;
@@ -179,20 +204,21 @@ struct ServerConfiguration {
bool live_production;
bool sign;
std::uint32_t content_lifetime;
- std::uint16_t content_object_size;
std::uint32_t download_size;
- utils::CryptoHashType hash_algorithm;
+ auth::CryptoHashType hash_algorithm;
std::string keystore_name;
std::string passphrase;
std::string keystore_password;
bool multiphase_produce_;
bool rtc_;
bool interactive_;
+ bool trace_based_;
+ std::uint32_t trace_index_;
+ char *trace_file_;
Rate production_rate_;
std::size_t payload_size_;
-#ifdef SECURE_HICNTRANSPORT
bool secure_;
-#endif
+ std::vector<struct packet_t> trace_;
};
/**
@@ -219,18 +245,26 @@ class HIperfClient {
: configuration_(conf),
total_duration_milliseconds_(0),
old_bytes_value_(0),
- signals_(io_service_, SIGINT),
+ old_interest_tx_value_(0),
+ old_fec_interest_tx_value_(0),
+ old_fec_data_rx_value_(0),
+ old_lost_data_value_(0),
+ old_bytes_recovered_value_(0),
+ old_retx_value_(0),
+ old_sent_int_value_(0),
+ old_received_nacks_value_(0),
+ avg_data_delay_(0),
+ delay_sample_(0),
+ received_bytes_(0),
+ received_data_pkt_(0),
+ signals_(io_service_),
expected_seg_(0),
lost_packets_(std::unordered_set<uint32_t>()),
- rtc_callback_(configuration_.rtc_ ? new RTCCallback(*this) : nullptr),
- callback_(configuration_.rtc_ ? nullptr : new Callback(*this)),
- key_callback_(configuration_.rtc_ ? nullptr : new KeyCallback(*this)) {}
-
- ~HIperfClient() {
- delete callback_;
- delete key_callback_;
- delete rtc_callback_;
- }
+ rtc_callback_(*this),
+ callback_(*this),
+ key_callback_(*this) {}
+
+ ~HIperfClient() {}
void checkReceivedRtcContent(ConsumerSocket &c,
const ContentObject &contentObject) {
@@ -239,11 +273,15 @@ class HIperfClient {
uint32_t receivedSeg = contentObject.getName().getSuffix();
auto payload = contentObject.getPayload();
- if ((uint32_t)payload->length() == 8) { // 8 is the size of the NACK
- // payload
- uint32_t *payloadPtr = (uint32_t *)payload->data();
- uint32_t productionSeg = *(payloadPtr);
- uint32_t productionRate = *(++payloadPtr);
+ if ((uint32_t)payload->length() == 16) { // 16 is the size of the NACK
+ struct nack_packet_t *nack_pkt =
+ (struct nack_packet_t *)contentObject.getPayload()->data();
+ uint32_t productionSeg = nack_pkt->getProductionSegement();
+ uint32_t productionRate = nack_pkt->getProductionRate();
+
+ // uint32_t *payloadPtr = (uint32_t *)payload->data();
+ // uint32_t productionSeg = *(payloadPtr);
+ // uint32_t productionRate = *(++payloadPtr);
if (productionRate == 0) {
std::cout << "[STOP] producer is not producing content" << std::endl;
@@ -256,7 +294,7 @@ class HIperfClient {
<< std::endl;
expected_seg_ = productionSeg;
} else if (receivedSeg > productionSeg && receivedSeg < MIN_PROBE_SEQ) {
- std::cout << "[WINDOW TO LARGE] received NACK for " << receivedSeg
+ std::cout << "[WINDOW TOO LARGE] received NACK for " << receivedSeg
<< ". Next expected packet " << productionSeg << std::endl;
} else if (receivedSeg >= MIN_PROBE_SEQ) {
std::cout << "[PROBE] probe number = " << receivedSeg << std::endl;
@@ -264,7 +302,24 @@ class HIperfClient {
return;
}
- if (receivedSeg > expected_seg_) {
+ received_bytes_ += (uint32_t)(payload->length() - 12);
+ received_data_pkt_++;
+
+ // collecting delay stats. Just for performance testing
+ // XXX we should probably get the transport header (12) somewhere
+ uint64_t *senderTimeStamp = (uint64_t *)(payload->data() + 12);
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+ double new_delay = (double)(now - *senderTimeStamp);
+ if (*senderTimeStamp > now)
+ new_delay = -1 * (double)(*senderTimeStamp - now);
+
+ delay_sample_++;
+ avg_data_delay_ =
+ avg_data_delay_ + (new_delay - avg_data_delay_) / delay_sample_;
+
+ if (receivedSeg > expected_seg_ && expected_seg_ != 0) {
for (uint32_t i = expected_seg_; i < receivedSeg; i++) {
std::cout << "[LOSS] lost packet " << i << std::endl;
lost_packets_.insert(i);
@@ -285,24 +340,12 @@ class HIperfClient {
expected_seg_ = receivedSeg + 1;
}
- bool verifyData(ConsumerSocket &c, const ContentObject &contentObject) {
- if (contentObject.getPayloadType() == PayloadType::CONTENT_OBJECT) {
- std::cout << "VERIFY CONTENT" << std::endl;
- } else if (contentObject.getPayloadType() == PayloadType::MANIFEST) {
- std::cout << "VERIFY MANIFEST" << std::endl;
- }
-
- return true;
- }
-
void processLeavingInterest(ConsumerSocket &c, const Interest &interest) {}
void handleTimerExpiration(ConsumerSocket &c,
const TransportStatistics &stats) {
- if (configuration_.rtc_) return;
-
const char separator = ' ';
- const int width = 20;
+ const int width = 15;
utils::TimePoint t2 = utils::SteadyClock::now();
auto exact_duration =
@@ -325,28 +368,125 @@ class HIperfClient {
std::stringstream window;
window << stats.getAverageWindowSize() << std::setfill(separator)
- << "[Interest]";
+ << "[Int]";
std::stringstream avg_rtt;
- avg_rtt << stats.getAverageRtt() << std::setfill(separator) << "[us]";
-
- std::cout << std::left << std::setw(width) << "Interval";
- std::cout << std::left << std::setw(width) << "Transfer";
- std::cout << std::left << std::setw(width) << "Bandwidth";
- std::cout << std::left << std::setw(width) << "Retr";
- std::cout << std::left << std::setw(width) << "Cwnd";
- std::cout << std::left << std::setw(width) << "AvgRtt" << std::endl;
-
- std::cout << std::left << std::setw(width) << interval.str();
- std::cout << std::left << std::setw(width) << bytes_transferred.str();
- std::cout << std::left << std::setw(width) << bandwidth.str();
- std::cout << std::left << std::setw(width) << stats.getRetxCount();
- std::cout << std::left << std::setw(width) << window.str();
- std::cout << std::left << std::setw(width) << avg_rtt.str() << std::endl;
- std::cout << std::endl;
+ avg_rtt << stats.getAverageRtt() << std::setfill(separator) << "[ms]";
+
+ if (configuration_.rtc_) {
+ // we get rtc stats more often, thus we need ms in the interval
+ std::stringstream interval_ms;
+ interval_ms << total_duration_milliseconds_ << "-"
+ << total_duration_milliseconds_ + exact_duration.count();
+
+ std::stringstream lost_data;
+ lost_data << stats.getLostData() - old_lost_data_value_
+ << std::setfill(separator) << "[pkt]";
+
+ std::stringstream bytes_recovered_data;
+ bytes_recovered_data << stats.getBytesRecoveredData() -
+ old_bytes_recovered_value_
+ << std::setfill(separator) << "[pkt]";
+
+ std::stringstream data_delay;
+ data_delay << avg_data_delay_ << std::setfill(separator) << "[ms]";
+
+ std::stringstream received_data_pkt;
+ received_data_pkt << received_data_pkt_ << std::setfill(separator)
+ << "[pkt]";
+
+ std::stringstream goodput;
+ goodput << (received_bytes_ * 8.0) / (exact_duration.count()) / 1000.0
+ << std::setfill(separator) << "[Mbps]";
+ std::stringstream loss_rate;
+ loss_rate << std::fixed << std::setprecision(2)
+ << stats.getLossRatio() * 100.0 << std::setfill(separator)
+ << "[%]";
+
+ std::stringstream retx_sent;
+ retx_sent << stats.getRetxCount() - old_retx_value_
+ << std::setfill(separator) << "[pkt]";
+
+ std::stringstream interest_sent;
+ interest_sent << stats.getInterestTx() - old_sent_int_value_
+ << std::setfill(separator) << "[pkt]";
+
+ std::stringstream nacks;
+ nacks << stats.getReceivedNacks() - old_received_nacks_value_
+ << std::setfill(separator) << "[pkt]";
+
+ // statistics not yet available in the transport
+ // std::stringstream interest_fec_tx;
+ // interest_fec_tx << stats.getInterestFecTxCount() -
+ // old_fec_interest_tx_value_ << std::setfill(separator) << "[pkt]";
+ // std::stringstream bytes_fec_recv;
+ // bytes_fec_recv << stats.getBytesFecRecv() - old_fec_data_rx_value_
+ // << std::setfill(separator) << "[bytes]";
+ std::cout << std::left << std::setw(width) << "Interval";
+ std::cout << std::left << std::setw(width) << "RecvData";
+ std::cout << std::left << std::setw(width) << "Bandwidth";
+ std::cout << std::left << std::setw(width) << "Goodput";
+ std::cout << std::left << std::setw(width) << "LossRate";
+ std::cout << std::left << std::setw(width) << "Retr";
+ std::cout << std::left << std::setw(width) << "InterestSent";
+ std::cout << std::left << std::setw(width) << "ReceivedNacks";
+ std::cout << std::left << std::setw(width) << "SyncWnd";
+ std::cout << std::left << std::setw(width) << "MinRtt";
+ std::cout << std::left << std::setw(width) << "LostData";
+ std::cout << std::left << std::setw(width) << "RecoveredData";
+ std::cout << std::left << std::setw(width) << "State";
+ std::cout << std::left << std::setw(width) << "DataDelay" << std::endl;
+
+ std::cout << std::left << std::setw(width) << interval_ms.str();
+ std::cout << std::left << std::setw(width) << received_data_pkt.str();
+ std::cout << std::left << std::setw(width) << bandwidth.str();
+ std::cout << std::left << std::setw(width) << goodput.str();
+ std::cout << std::left << std::setw(width) << loss_rate.str();
+ std::cout << std::left << std::setw(width) << retx_sent.str();
+ std::cout << std::left << std::setw(width) << interest_sent.str();
+ std::cout << std::left << std::setw(width) << nacks.str();
+ std::cout << std::left << std::setw(width) << window.str();
+ std::cout << std::left << std::setw(width) << avg_rtt.str();
+ std::cout << std::left << std::setw(width) << lost_data.str();
+ std::cout << std::left << std::setw(width) << bytes_recovered_data.str();
+ std::cout << std::left << std::setw(width) << stats.getCCStatus();
+ std::cout << std::left << std::setw(width) << data_delay.str();
+ std::cout << std::endl;
+
+ // statistics not yet available in the transport
+ // std::cout << std::left << std::setw(width) << interest_fec_tx.str();
+ // std::cout << std::left << std::setw(width) << bytes_fec_recv.str();
+ } else {
+ std::cout << std::left << std::setw(width) << "Interval";
+ std::cout << std::left << std::setw(width) << "Transfer";
+ std::cout << std::left << std::setw(width) << "Bandwidth";
+ std::cout << std::left << std::setw(width) << "Retr";
+ std::cout << std::left << std::setw(width) << "Cwnd";
+ std::cout << std::left << std::setw(width) << "AvgRtt" << std::endl;
+
+ std::cout << std::left << std::setw(width) << interval.str();
+ std::cout << std::left << std::setw(width) << bytes_transferred.str();
+ std::cout << std::left << std::setw(width) << bandwidth.str();
+ std::cout << std::left << std::setw(width) << stats.getRetxCount();
+ std::cout << std::left << std::setw(width) << window.str();
+ std::cout << std::left << std::setw(width) << avg_rtt.str() << std::endl;
+ std::cout << std::endl;
+ }
total_duration_milliseconds_ += (uint32_t)exact_duration.count();
old_bytes_value_ = stats.getBytesRecv();
+ old_lost_data_value_ = stats.getLostData();
+ old_bytes_recovered_value_ = stats.getBytesRecoveredData();
+ old_fec_interest_tx_value_ = stats.getInterestFecTxCount();
+ old_fec_data_rx_value_ = stats.getBytesFecRecv();
+ old_retx_value_ = (uint32_t)stats.getRetxCount();
+ old_sent_int_value_ = (uint32_t)stats.getInterestTx();
+ old_received_nacks_value_ = stats.getReceivedNacks();
+ delay_sample_ = 0;
+ avg_data_delay_ = 0;
+ received_bytes_ = 0;
+ received_data_pkt_ = 0;
+
t_stats_ = utils::SteadyClock::now();
}
@@ -361,7 +501,6 @@ class HIperfClient {
configuration_.transport_protocol_ = CBR;
}
-#ifdef SECURE_HICNSOCKET
if (configuration_.secure_) {
consumer_socket_ = std::make_shared<P2PSecureConsumerSocket>(
RAAQM, configuration_.transport_protocol_);
@@ -375,12 +514,9 @@ class HIperfClient {
secure_consumer_socket.registerPrefix(configuration_.producer_prefix_);
}
} else {
-#endif
consumer_socket_ =
std::make_shared<ConsumerSocket>(configuration_.transport_protocol_);
-#ifdef SECURE_HICNSOCKET
}
-#endif
consumer_socket_->setSocketOption(
GeneralTransportOptions::INTEREST_LIFETIME,
@@ -423,34 +559,21 @@ class HIperfClient {
}
}
- if (configuration_.verify) {
- std::shared_ptr<utils::Verifier> verifier =
- std::make_shared<utils::Verifier>();
- PARCKeyId *key_id_;
-
- if (!configuration_.producer_certificate.empty()) {
- key_id_ = verifier->addKeyFromCertificate(
- configuration_.producer_certificate);
- if (key_id_ == nullptr) return ERROR_SETUP;
- }
-
- if (!configuration_.passphrase.empty()) {
- key_id_ = verifier->addKeyFromPassphrase(
- configuration_.passphrase, utils::CryptoSuite::HMAC_SHA256);
- if (key_id_ == nullptr) return ERROR_SETUP;
- }
-
+ if (!configuration_.producer_certificate.empty()) {
+ std::shared_ptr<auth::Verifier> verifier =
+ std::make_shared<auth::AsymmetricVerifier>(
+ configuration_.producer_certificate);
if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
- verifier) ==
- SOCKET_OPTION_NOT_SET) {
+ verifier) == SOCKET_OPTION_NOT_SET)
return ERROR_SETUP;
- }
}
- if (consumer_socket_->setSocketOption(
- GeneralTransportOptions::VERIFY_SIGNATURE, configuration_.verify) ==
- SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
+ if (!configuration_.passphrase.empty()) {
+ std::shared_ptr<auth::Verifier> verifier =
+ std::make_shared<auth::SymmetricVerifier>(configuration_.passphrase);
+ if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
+ verifier) == SOCKET_OPTION_NOT_SET)
+ return ERROR_SETUP;
}
ret = consumer_socket_->setSocketOption(
@@ -464,16 +587,11 @@ class HIperfClient {
}
if (!configuration_.rtc_) {
- /* key_callback_->setConsumer(consumer_socket_); */
- /* consumer_socket_->setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK,
- * key_callback_); */
- /* consumer_socket_->setSocketOption(GeneralTransportOptions::KEY_CONTENT,
- * true); */
ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::READ_CALLBACK, callback_);
+ ConsumerCallbacksOptions::READ_CALLBACK, &callback_);
} else {
ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::READ_CALLBACK, rtc_callback_);
+ ConsumerCallbacksOptions::READ_CALLBACK, &rtc_callback_);
}
if (ret == SOCKET_OPTION_NOT_SET) {
@@ -491,6 +609,13 @@ class HIperfClient {
}
}
+ if (configuration_.rtc_) {
+ std::shared_ptr<TransportStatistics> transport_stats;
+ consumer_socket_->getSocketOption(
+ OtherOptions::STATISTICS, (TransportStatistics **)&transport_stats);
+ transport_stats->setAlpha(0.0);
+ }
+
ret = consumer_socket_->setSocketOption(
ConsumerCallbacksOptions::STATS_SUMMARY,
(ConsumerTimerCallback)std::bind(&HIperfClient::handleTimerExpiration,
@@ -516,15 +641,16 @@ class HIperfClient {
int run() {
std::cout << "Starting download of " << configuration_.name << std::endl;
- signals_.async_wait([this](const std::error_code &, const int &) {
- consumer_socket_->stop();
- io_service_.stop();
- });
+ signals_.add(SIGINT);
+ signals_.async_wait(
+ [this](const std::error_code &, const int &) { io_service_.stop(); });
t_download_ = t_stats_ = std::chrono::steady_clock::now();
consumer_socket_->asyncConsume(configuration_.name);
io_service_.run();
+ consumer_socket_->stop();
+
return ERROR_SUCCESS;
}
@@ -643,37 +769,10 @@ class HIperfClient {
client_.io_service_.stop();
}
- bool verifyKey() { return !key_->empty(); }
+ bool validateKey() { return !key_->empty(); }
void readSuccess(std::size_t total_size) noexcept override {
std::cout << "Key size: " << total_size << " bytes" << std::endl;
- afterRead();
- }
-
- void afterRead() {
- std::shared_ptr<utils::Verifier> verifier =
- std::make_shared<utils::Verifier>();
- verifier->addKeyFromPassphrase(*key_, utils::CryptoSuite::HMAC_SHA256);
-
- if (consumer_socket_) {
- consumer_socket_->setSocketOption(GeneralTransportOptions::KEY_CONTENT,
- false);
- consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
- verifier);
- } else {
- std::cout << "Could not set verifier" << std::endl;
- return;
- }
-
- if (consumer_socket_->verifyKeyPackets()) {
- std::cout << "Verification of packet signatures successful"
- << std::endl;
- } else {
- std::cout << "Could not verify packet signatures" << std::endl;
- return;
- }
-
- std::cout << "Key retrieval done" << std::endl;
}
void setConsumer(std::shared_ptr<ConsumerSocket> consumer_socket) {
@@ -691,14 +790,31 @@ class HIperfClient {
Time t_download_;
uint32_t total_duration_milliseconds_;
uint64_t old_bytes_value_;
+ uint64_t old_interest_tx_value_;
+ uint64_t old_fec_interest_tx_value_;
+ uint64_t old_fec_data_rx_value_;
+ uint64_t old_lost_data_value_;
+ uint64_t old_bytes_recovered_value_;
+ uint32_t old_retx_value_;
+ uint32_t old_sent_int_value_;
+ uint32_t old_received_nacks_value_;
+
+ // IMPORTANT: to be used only for performance testing, when consumer and
+ // producer are synchronized. Used for rtc only at the moment
+ double avg_data_delay_;
+ uint32_t delay_sample_;
+
+ uint32_t received_bytes_;
+ uint32_t received_data_pkt_;
+
asio::io_service io_service_;
asio::signal_set signals_;
- std::shared_ptr<ConsumerSocket> consumer_socket_;
uint32_t expected_seg_;
std::unordered_set<uint32_t> lost_packets_;
- RTCCallback *rtc_callback_;
- Callback *callback_;
- KeyCallback *key_callback_;
+ RTCCallback rtc_callback_;
+ Callback callback_;
+ KeyCallback key_callback_;
+ std::shared_ptr<ConsumerSocket> consumer_socket_;
}; // namespace interface
/**
@@ -711,7 +827,7 @@ class HIperfServer {
public:
HIperfServer(ServerConfiguration &conf)
: configuration_(conf),
- signals_(io_service_, SIGINT),
+ signals_(io_service_),
rtc_timer_(io_service_),
unsatisfied_interests_(),
content_objects_((std::uint16_t)(1 << log2_content_object_buffer_size)),
@@ -721,11 +837,11 @@ class HIperfServer {
#ifndef _WIN32
ptr_last_segment_(&last_segment_),
input_(io_service_),
- rtc_running_(false)
+ rtc_running_(false),
#else
- ptr_last_segment_(&last_segment_)
+ ptr_last_segment_(&last_segment_),
#endif
- {
+ flow_name_(configuration_.name.getName()) {
std::string buffer(configuration_.payload_size_, 'X');
std::cout << "Producing contents under name " << conf.name.getName()
<< std::endl;
@@ -736,9 +852,9 @@ class HIperfServer {
#endif
for (int i = 0; i < (1 << log2_content_object_buffer_size); i++) {
- content_objects_[i] = std::make_shared<ContentObject>(
- conf.name.getName(), HF_INET6_TCP, (const uint8_t *)buffer.data(),
- buffer.size());
+ content_objects_[i] = ContentObject::Ptr(
+ new ContentObject(conf.name.getName(), HF_INET6_TCP, 0,
+ (const uint8_t *)buffer.data(), buffer.size()));
content_objects_[i]->setLifetime(
default_values::content_object_expiry_time);
}
@@ -797,15 +913,16 @@ class HIperfServer {
produceContentAsync(p, interest.getName(), suffix);
}
- void produceContent(ProducerSocket &p, Name content_name, uint32_t suffix) {
+ void produceContent(ProducerSocket &p, const Name &content_name,
+ uint32_t suffix) {
auto b = utils::MemBuf::create(configuration_.download_size);
std::memset(b->writableData(), '?', configuration_.download_size);
b->append(configuration_.download_size);
uint32_t total;
utils::TimePoint t0 = utils::SteadyClock::now();
- total = p.produce(content_name, std::move(b),
- !configuration_.multiphase_produce_, suffix);
+ total = p.produceStream(content_name, std::move(b),
+ !configuration_.multiphase_produce_, suffix);
utils::TimePoint t1 = utils::SteadyClock::now();
std::cout
@@ -820,11 +937,6 @@ class HIperfServer {
auto b = utils::MemBuf::create(configuration_.download_size);
std::memset(b->writableData(), '?', configuration_.download_size);
b->append(configuration_.download_size);
- /* std::string passphrase = "hunter2"; */
- /* auto b = utils::MemBuf::create(passphrase.length() + 1); */
- /* std::memcpy(b->writableData(), passphrase.c_str(), passphrase.length() +
- * 1); */
- /* b->append(passphrase.length() + 1); */
p.asyncProduce(content_name, std::move(b),
!configuration_.multiphase_produce_, suffix,
@@ -843,23 +955,22 @@ class HIperfServer {
std::placeholders::_1, std::placeholders::_2));
}
- std::shared_ptr<utils::Identity> getProducerIdentity(
- std::string &keystore_name, std::string &keystore_password,
- utils::CryptoHashType &hash_algorithm) {
- if (access(keystore_name.c_str(), F_OK) != -1) {
- return std::make_shared<utils::Identity>(keystore_name, keystore_password,
- hash_algorithm);
- } else {
- return std::make_shared<utils::Identity>(keystore_name, keystore_password,
- utils::CryptoSuite::RSA_SHA256,
- 1024, 365, "producer-test");
+ std::shared_ptr<auth::Identity> getProducerIdentity(
+ std::string &keystore_path, std::string &keystore_pwd,
+ auth::CryptoHashType &hash_type) {
+ if (access(keystore_path.c_str(), F_OK) != -1) {
+ return std::make_shared<auth::Identity>(keystore_path, keystore_pwd,
+ hash_type);
}
+ return std::make_shared<auth::Identity>(keystore_path, keystore_pwd,
+ auth::CryptoSuite::RSA_SHA256, 1024,
+ 365, "producer-test");
}
int setup() {
int ret;
+ int production_protocol;
-#ifdef SECURE_HICNSOCKET
if (configuration_.secure_) {
auto identity = getProducerIdentity(configuration_.keystore_name,
configuration_.keystore_password,
@@ -867,22 +978,21 @@ class HIperfServer {
producer_socket_ = std::make_unique<P2PSecureProducerSocket>(
configuration_.rtc_, identity);
} else {
-#endif
- if (configuration_.rtc_) {
- producer_socket_ = std::make_unique<RTCProducerSocket>();
+ if (!configuration_.rtc_) {
+ production_protocol = ProductionProtocolAlgorithms::BYTE_STREAM;
} else {
- producer_socket_ = std::make_unique<ProducerSocket>();
+ production_protocol = ProductionProtocolAlgorithms::RTC_PROD;
}
-#ifdef SECURE_HICNSOCKET
+
+ producer_socket_ = std::make_unique<ProducerSocket>(production_protocol);
}
-#endif
if (configuration_.sign) {
- std::shared_ptr<utils::Signer> signer;
+ std::shared_ptr<auth::Signer> signer;
if (!configuration_.passphrase.empty()) {
- signer = std::make_shared<utils::Signer>(
- configuration_.passphrase, utils::CryptoSuite::HMAC_SHA256);
+ signer = std::make_shared<auth::SymmetricSigner>(
+ auth::CryptoSuite::HMAC_SHA256, configuration_.passphrase);
} else if (!configuration_.keystore_name.empty()) {
auto identity = getProducerIdentity(configuration_.keystore_name,
configuration_.keystore_password,
@@ -898,10 +1008,12 @@ class HIperfServer {
}
}
+ uint32_t rtc_header_size = 0;
+ if (configuration_.rtc_) rtc_header_size = 12;
producer_socket_->setSocketOption(
GeneralTransportOptions::DATA_PACKET_SIZE,
(uint32_t)(
- configuration_.payload_size_ +
+ configuration_.payload_size_ + rtc_header_size +
(configuration_.name.getAddressFamily() == AF_INET ? 40 : 60)));
producer_socket_->registerPrefix(configuration_.name);
producer_socket_->connect();
@@ -982,7 +1094,61 @@ class HIperfServer {
this, std::placeholders::_1));
auto payload =
content_objects_[content_objects_index_++ & mask_]->getPayload();
- producer_socket_->produce(payload->data(), payload->length());
+
+ // this is used to compute the data packet delay
+ // Used only for performance evaluation
+ // It requires clock synchronization between producer and consumer
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+
+ std::memcpy(payload->writableData(), &now, sizeof(uint64_t));
+
+ producer_socket_->produceDatagram(
+ flow_name_, payload->data(),
+ payload->length() < 1400 ? payload->length() : 1400);
+ }
+
+ void sendRTCContentObjectCallbackWithTrace(std::error_code ec) {
+ if (ec) return;
+
+ auto payload =
+ content_objects_[content_objects_index_++ & mask_]->getPayload();
+
+ uint32_t packet_len =
+ configuration_.trace_[configuration_.trace_index_].size;
+
+ // this is used to compute the data packet delay
+ // used only for performance evaluation
+ // it requires clock synchronization between producer and consumer
+ uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+
+ std::memcpy(payload->writableData(), &now, sizeof(uint64_t));
+
+ if (packet_len > payload->length()) packet_len = (uint32_t)payload->length();
+ if (packet_len > 1400) packet_len = 1400;
+
+ producer_socket_->produceDatagram(flow_name_, payload->data(), packet_len);
+
+ uint32_t next_index = configuration_.trace_index_ + 1;
+ uint64_t schedule_next;
+ if (next_index < configuration_.trace_.size()) {
+ schedule_next =
+ configuration_.trace_[next_index].timestamp -
+ configuration_.trace_[configuration_.trace_index_].timestamp;
+ } else {
+ // here we need to loop, schedule in a random time
+ schedule_next = 1000;
+ }
+
+ configuration_.trace_index_ =
+ (configuration_.trace_index_ + 1) % configuration_.trace_.size();
+ rtc_timer_.expires_from_now(std::chrono::microseconds(schedule_next));
+ rtc_timer_.async_wait(
+ std::bind(&HIperfServer::sendRTCContentObjectCallbackWithTrace, this,
+ std::placeholders::_1));
}
#ifndef _WIN32
@@ -1015,9 +1181,25 @@ class HIperfServer {
}
#endif
+ int parseTraceFile() {
+ std::ifstream trace(configuration_.trace_file_);
+ if (trace.fail()) {
+ return -1;
+ }
+ std::string line;
+ while (std::getline(trace, line)) {
+ std::istringstream iss(line);
+ struct packet_t packet;
+ iss >> packet.timestamp >> packet.size;
+ configuration_.trace_.push_back(packet);
+ }
+ return 0;
+ }
+
int run() {
std::cerr << "Starting to serve consumers" << std::endl;
+ signals_.add(SIGINT);
signals_.async_wait([this](const std::error_code &, const int &) {
std::cout << "STOPPING!!" << std::endl;
producer_socket_->stop();
@@ -1031,6 +1213,21 @@ class HIperfServer {
input_, input_buffer_, '\n',
std::bind(&HIperfServer::handleInput, this, std::placeholders::_1,
std::placeholders::_2));
+ } else if (configuration_.trace_based_) {
+ std::cout << "trace-based mode enabled" << std::endl;
+ if (configuration_.trace_file_ == nullptr) {
+ std::cout << "cannot find the trace file" << std::endl;
+ return ERROR_SETUP;
+ }
+ if (parseTraceFile() < 0) {
+ std::cout << "cannot parse the trace file" << std::endl;
+ return ERROR_SETUP;
+ }
+ rtc_running_ = true;
+ rtc_timer_.expires_from_now(std::chrono::milliseconds(1));
+ rtc_timer_.async_wait(
+ std::bind(&HIperfServer::sendRTCContentObjectCallbackWithTrace,
+ this, std::placeholders::_1));
} else {
rtc_running_ = true;
rtc_timer_.expires_from_now(
@@ -1071,7 +1268,9 @@ class HIperfServer {
asio::posix::stream_descriptor input_;
asio::streambuf input_buffer_;
bool rtc_running_;
+
#endif
+ core::Name flow_name_;
}; // namespace interface
void usage() {
@@ -1088,6 +1287,8 @@ void usage() {
<< "Run RTC protocol (client or server)" << std::endl;
std::cerr << "-f\t<filename>\t\t\t"
<< "Log file" << std::endl;
+ std::cerr << "-z\t<io_module>\t\t\t"
+ << "IO module to use. Default: hicnlight_module" << std::endl;
#endif
std::cerr << std::endl;
std::cerr << "SERVER SPECIFIC:" << std::endl;
@@ -1133,14 +1334,19 @@ void usage() {
"Interactive mode, start/stop real time content production "
"by pressing return. To be used with the -R option"
<< std::endl;
-#ifdef SECURE_HICNTRANSPORT
+ std::cerr
+ << "-T\t<filename>\t\t\t"
+ "Trace based mode, hiperf takes as input a file with a trace. "
+ "Each line of the file indicates the timestamp and the size of "
+ "the packet to generate. To be used with the -R option. -B and -I "
+ "will be ignored."
+ << std::endl;
std::cerr << "-E\t\t\t\t\t"
<< "Enable encrypted communication. Requires the path to a p12 "
"file containing the "
"crypto material used for the TLS handshake"
<< std::endl;
#endif
-#endif
std::cerr << std::endl;
std::cerr << "CLIENT SPECIFIC:" << std::endl;
std::cerr << "-b\t<beta_parameter>\t\t"
@@ -1162,26 +1368,21 @@ void usage() {
std::cerr << "-i\t<stats_interval>\t\t"
<< "Show the statistics every <stats_interval> milliseconds."
<< std::endl;
- std::cerr << "-v\t\t\t\t\t"
- << "Enable verification of received data" << std::endl;
std::cerr << "-c\t<certificate_path>\t\t"
<< "Path of the producer certificate to be used for verifying the "
- "origin of the packets received. Must be used with -v."
+ "origin of the packets received."
<< std::endl;
std::cerr << "-k\t<passphrase>\t\t\t"
<< "String from which is derived the symmetric key used by the "
- "producer to sign packets and by the consumer to verify them. "
- "Must be used with -v."
+ "producer to sign packets and by the consumer to verify them."
<< std::endl;
std::cerr << "-t\t\t\t\t\t"
"Test mode, check if the client is receiving the "
"correct data. This is an RTC specific option, to be "
"used with the -R (default false)"
<< std::endl;
-#ifdef SECURE_HICNTRANSPORT
std::cerr << "-P\t\t\t\t\t"
<< "Prefix of the producer where to do the handshake" << std::endl;
-#endif
}
int main(int argc, char *argv[]) {
@@ -1198,6 +1399,9 @@ int main(int argc, char *argv[]) {
int options = 0;
char *log_file = nullptr;
+ interface::global_config::IoModuleConfiguration config;
+ std::string conf_file;
+ config.name = "hicnlight_module";
// Consumer
ClientConfiguration client_configuration;
@@ -1207,9 +1411,9 @@ int main(int argc, char *argv[]) {
int opt;
#ifndef _WIN32
- while ((opt = getopt(argc, argv,
- "DSCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xE:P:B:ItL:")) !=
- -1) {
+ while ((opt = getopt(
+ argc, argv,
+ "DSCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xE:P:B:ItL:z:T:F:")) != -1) {
switch (opt) {
// Common
case 'D': {
@@ -1218,11 +1422,19 @@ int main(int argc, char *argv[]) {
}
case 'I': {
server_configuration.interactive_ = true;
+ server_configuration.trace_based_ = false;
+ break;
+ }
+ case 'T': {
+ server_configuration.interactive_ = false;
+ server_configuration.trace_based_ = true;
+ server_configuration.trace_file_ = optarg;
break;
}
#else
while ((opt = getopt(argc, argv,
- "SCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xB:E:P:tL:")) != -1) {
+ "SCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xB:E:P:tL:z:F:")) !=
+ -1) {
switch (opt) {
#endif
case 'f': {
@@ -1234,6 +1446,14 @@ int main(int argc, char *argv[]) {
server_configuration.rtc_ = true;
break;
}
+ case 'z': {
+ config.name = optarg;
+ break;
+ }
+ case 'F': {
+ conf_file = optarg;
+ break;
+ }
// Server or Client
case 'S': {
@@ -1248,7 +1468,6 @@ int main(int argc, char *argv[]) {
server_configuration.passphrase = std::string(optarg);
client_configuration.passphrase = std::string(optarg);
server_configuration.sign = true;
- options = -1;
break;
}
@@ -1273,23 +1492,16 @@ int main(int argc, char *argv[]) {
options = 1;
break;
}
-#ifdef SECURE_HICNTRANSPORT
case 'P': {
client_configuration.producer_prefix_ = Prefix(optarg);
client_configuration.secure_ = true;
break;
}
-#endif
case 'c': {
client_configuration.producer_certificate = std::string(optarg);
options = 1;
break;
}
- case 'v': {
- client_configuration.verify = true;
- options = 1;
- break;
- }
case 'i': {
client_configuration.report_interval_milliseconds_ = std::stoul(optarg);
options = 1;
@@ -1339,11 +1551,11 @@ int main(int argc, char *argv[]) {
}
case 'y': {
if (strncasecmp(optarg, "sha256", 6) == 0) {
- server_configuration.hash_algorithm = utils::CryptoHashType::SHA_256;
+ server_configuration.hash_algorithm = auth::CryptoHashType::SHA_256;
} else if (strncasecmp(optarg, "sha512", 6) == 0) {
- server_configuration.hash_algorithm = utils::CryptoHashType::SHA_512;
+ server_configuration.hash_algorithm = auth::CryptoHashType::SHA_512;
} else if (strncasecmp(optarg, "crc32", 5) == 0) {
- server_configuration.hash_algorithm = utils::CryptoHashType::CRC32C;
+ server_configuration.hash_algorithm = auth::CryptoHashType::CRC32C;
} else {
std::cerr << "Ignored unknown hash algorithm. Using SHA 256."
<< std::endl;
@@ -1368,13 +1580,11 @@ int main(int argc, char *argv[]) {
options = -1;
break;
}
-#ifdef SECURE_HICNTRANSPORT
case 'E': {
server_configuration.keystore_name = std::string(optarg);
server_configuration.secure_ = true;
break;
}
-#endif
case 'h':
default:
usage();
@@ -1388,7 +1598,6 @@ int main(int argc, char *argv[]) {
<< std::endl;
usage();
return EXIT_FAILURE;
-
} else if (options < 0 && role > 0) {
std::cerr << "Server options cannot be used when using the "
"software in client mode"
@@ -1436,6 +1645,14 @@ int main(int argc, char *argv[]) {
}
#endif
+ /**
+ * IO module configuration
+ */
+ config.set();
+
+ // Parse config file
+ transport::interface::global_config::parseConfigurationFile(conf_file);
+
if (role > 0) {
HIperfClient c(client_configuration);
if (c.setup() != ERROR_SETUP) {
@@ -1454,11 +1671,11 @@ int main(int argc, char *argv[]) {
#ifdef _WIN32
WSACleanup();
#endif
+
return 0;
}
} // end namespace interface
-
} // end namespace transport
int main(int argc, char *argv[]) {
diff --git a/utils/src/ping_client.cc b/utils/src/ping_client.cc
index 67440cdc1..e7a9228f2 100644
--- a/utils/src/ping_client.cc
+++ b/utils/src/ping_client.cc
@@ -13,9 +13,10 @@
* limitations under the License.
*/
+#include <hicn/transport/core/global_object_pool.h>
#include <hicn/transport/core/interest.h>
#include <hicn/transport/interfaces/portal.h>
-#include <hicn/transport/security/verifier.h>
+#include <hicn/transport/auth/verifier.h>
#include <hicn/transport/utils/log.h>
// Let's make the linker happy
@@ -40,7 +41,7 @@ namespace core {
namespace ping {
typedef std::map<uint64_t, uint64_t> SendTimeMap;
-typedef utils::Verifier Verifier;
+typedef auth::AsymmetricVerifier Verifier;
class Configuration {
public:
@@ -104,7 +105,7 @@ class Client : interface::Portal::ConsumerCallback {
received_ = 0;
timedout_ = 0;
if (!c->certificate_.empty()) {
- key_id_ = verifier_.addKeyFromCertificate(c->certificate_);
+ verifier_.setCertificate(c->certificate_);
}
}
@@ -116,13 +117,12 @@ class Client : interface::Portal::ConsumerCallback {
portal_.runEventsLoop();
}
- void onContentObject(Interest::Ptr &&interest,
- ContentObject::Ptr &&object) override {
+ void onContentObject(Interest &interest, ContentObject &object) override {
uint64_t rtt = 0;
if (!config_->certificate_.empty()) {
auto t0 = std::chrono::steady_clock::now();
- if (verifier_.verify(*object)) {
+ if (verifier_.verifyPacket(&object)) {
auto t1 = std::chrono::steady_clock::now();
auto dt =
std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0);
@@ -133,7 +133,7 @@ class Client : interface::Portal::ConsumerCallback {
}
}
- auto it = send_timestamps_.find(interest->getName().getSuffix());
+ auto it = send_timestamps_.find(interest.getName().getSuffix());
if (it != send_timestamps_.end()) {
rtt = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now().time_since_epoch())
@@ -144,40 +144,40 @@ class Client : interface::Portal::ConsumerCallback {
if (config_->verbose_) {
std::cout << "<<< recevied object. " << std::endl;
- std::cout << "<<< interest name: " << interest->getName()
- << " src port: " << interest->getSrcPort()
- << " dst port: " << interest->getDstPort()
- << " flags: " << interest->printFlags() << std::endl;
- std::cout << "<<< object name: " << object->getName()
- << " src port: " << object->getSrcPort()
- << " dst port: " << object->getDstPort()
- << " flags: " << object->printFlags() << " path label "
- << object->getPathLabel() << " ("
- << (object->getPathLabel() >> 24) << ")"
- << " TTL: " << (int)object->getTTL() << std::endl;
+ std::cout << "<<< interest name: " << interest.getName()
+ << " src port: " << interest.getSrcPort()
+ << " dst port: " << interest.getDstPort()
+ << " flags: " << interest.printFlags() << std::endl;
+ std::cout << "<<< object name: " << object.getName()
+ << " src port: " << object.getSrcPort()
+ << " dst port: " << object.getDstPort()
+ << " flags: " << object.printFlags() << " path label "
+ << object.getPathLabel() << " ("
+ << (object.getPathLabel() >> 24) << ")"
+ << " TTL: " << (int)object.getTTL() << std::endl;
} else if (!config_->quiet_) {
std::cout << "<<< received object. " << std::endl;
std::cout << "<<< round trip: " << rtt << " [us]" << std::endl;
- std::cout << "<<< interest name: " << interest->getName() << std::endl;
- std::cout << "<<< object name: " << object->getName() << std::endl;
+ std::cout << "<<< interest name: " << interest.getName() << std::endl;
+ std::cout << "<<< object name: " << object.getName() << std::endl;
std::cout << "<<< content object size: "
- << object->payloadSize() + object->headerSize() << " [bytes]"
+ << object.payloadSize() + object.headerSize() << " [bytes]"
<< std::endl;
}
if (config_->dump_) {
std::cout << "----- interest dump -----" << std::endl;
- interest->dump();
+ interest.dump();
std::cout << "-------------------------" << std::endl;
std::cout << "----- object dump -------" << std::endl;
- object->dump();
+ object.dump();
std::cout << "-------------------------" << std::endl;
}
if (!config_->quiet_) std::cout << std::endl;
if (!config_->always_syn_) {
- if (object->testSyn() && object->testAck() && state_ == SYN_STATE) {
+ if (object.testSyn() && object.testAck() && state_ == SYN_STATE) {
state_ = ACK_STATE;
}
}
@@ -217,7 +217,7 @@ class Client : interface::Portal::ConsumerCallback {
void onError(std::error_code ec) override {}
void doPing() {
- Name interest_name(config_->name_, (uint32_t)sequence_number_);
+ const Name interest_name(config_->name_, (uint32_t)sequence_number_);
hicn_format_t format;
if (interest_name.getAddressFamily() == AF_INET) {
format = HF_INET_TCP;
@@ -225,11 +225,9 @@ class Client : interface::Portal::ConsumerCallback {
format = HF_INET6_TCP;
}
- Interest::Ptr interest(new Interest(std::move(interest_name), format),
- nullptr);
+ auto interest = std::make_shared<Interest>(interest_name, format);
interest->setLifetime(uint32_t(config_->interestLifetime_));
-
interest->resetFlags();
if (config_->open_ || config_->always_syn_) {
@@ -313,7 +311,6 @@ class Client : interface::Portal::ConsumerCallback {
std::unique_ptr<asio::steady_timer> timer_;
Configuration *config_;
Verifier verifier_;
- PARCKeyId *key_id_;
};
void help() {
diff --git a/utils/src/ping_server.cc b/utils/src/ping_server.cc
index b1a6e1509..79c662231 100644
--- a/utils/src/ping_server.cc
+++ b/utils/src/ping_server.cc
@@ -23,11 +23,10 @@
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
-#include <hicn/transport/security/identity.h>
-#include <hicn/transport/security/signer.h>
+#include <hicn/transport/auth/identity.h>
+#include <hicn/transport/auth/signer.h>
#include <hicn/transport/utils/string_tokenizer.h>
-
#include <asio.hpp>
namespace transport {
@@ -35,16 +34,16 @@ namespace transport {
namespace interface {
using HashAlgorithm = core::HashAlgorithm;
-using CryptoSuite = utils::CryptoSuite;
+using CryptoSuite = auth::CryptoSuite;
-utils::Identity setProducerIdentity(std::string keystore_name,
- std::string keystore_password,
- utils::CryptoHashType hash_algorithm) {
+auth::Identity setProducerIdentity(std::string keystore_name,
+ std::string keystore_password,
+ auth::CryptoHashType hash_algorithm) {
if (access(keystore_name.c_str(), F_OK) != -1) {
- return utils::Identity(keystore_name, keystore_password, hash_algorithm);
+ return auth::Identity(keystore_name, keystore_password, hash_algorithm);
} else {
- return utils::Identity(keystore_name, keystore_password,
- CryptoSuite::RSA_SHA256, 1024, 365, "producer-test");
+ return auth::Identity(keystore_name, keystore_password,
+ CryptoSuite::RSA_SHA256, 1024, 365, "producer-test");
}
}
@@ -54,7 +53,7 @@ class CallbackContainer {
public:
CallbackContainer(const Name &prefix, uint32_t object_size, bool verbose,
bool dump, bool quite, bool flags, bool reset, uint8_t ttl,
- utils::Identity *identity, bool sign, uint32_t lifetime)
+ auth::Identity *identity, bool sign, uint32_t lifetime)
: buffer_(object_size, 'X'),
content_objects_((std::uint32_t)(1 << log2_content_object_buffer_size)),
mask_((std::uint16_t)(1 << log2_content_object_buffer_size) - 1),
@@ -83,7 +82,7 @@ class CallbackContainer {
for (int i = 0; i < (1 << log2_content_object_buffer_size); i++) {
content_objects_[i] = std::make_shared<ContentObject>(
- prefix, format, (const uint8_t *)buffer_.data(), buffer_.size());
+ prefix, format, 0, (const uint8_t *)buffer_.data(), buffer_.size());
content_objects_[i]->setLifetime(lifetime);
}
}
@@ -153,7 +152,7 @@ class CallbackContainer {
if (!quite_) std::cout << std::endl;
if (sign_) {
- identity_->getSigner()->sign(*content_object);
+ identity_->getSigner()->signPacket(content_object.get());
}
p.produce(*content_object);
@@ -171,7 +170,7 @@ class CallbackContainer {
bool flags_;
bool reset_;
uint8_t ttl_;
- utils::Identity *identity_;
+ auth::Identity *identity_;
bool sign_;
};
@@ -291,14 +290,14 @@ int main(int argc, char **argv) {
if (object_size > 1350) object_size = 1350;
CallbackContainer *stubs;
- utils::Identity identity = setProducerIdentity(
- keystore_path, keystore_password, utils::CryptoHashType::SHA_256);
+ auth::Identity identity = setProducerIdentity(
+ keystore_path, keystore_password, auth::CryptoHashType::SHA_256);
if (sign) {
stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags,
reset, ttl, &identity, sign, data_lifetime);
} else {
- utils::Identity *identity = nullptr;
+ auth::Identity *identity = nullptr;
stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags,
reset, ttl, identity, sign, data_lifetime);
}