aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Muscariello <lumuscar@cisco.com>2022-06-09 21:34:09 +0200
committerLuca Muscariello <muscariello@ieee.org>2022-06-30 10:47:50 +0200
commit6b94663b2455e212009a544ae23bb6a8c55407f8 (patch)
tree0af780ce5eeb1009fd24b8af8af08e8368eda3bd
parenta1ac96f497719b897793ac14b287cb8d840651c1 (diff)
refactor(lib, hicn-light, vpp, hiperf): HICN-723
- move infra data structure into the shared lib - new packet cache using double hashing and lookup on prefix suffix - testing updates - authenticated requests using interest manifests Co-authored-by: Mauro Sardara <msardara@cisco.com> Co-authored-by: Jordan Augé <jordan.auge+fdio@cisco.com> Co-authored-by: Michele Papalini <micpapal@cisco.com> Co-authored-by: Olivier Roques <oroques+fdio@cisco.com> Co-authored-by: Enrico Loparco <eloparco@cisco.com> Change-Id: Iaddebfe6aa5279ea8553433b0f519578f6b9ccd9 Signed-off-by: Luca Muscariello <muscariello@ieee.org>
-rw-r--r--.cz.toml2
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt26
-rw-r--r--Dockerfile.dev27
-rw-r--r--Makefile11
-rw-r--r--apps/hiperf/CMakeLists.txt1
-rw-r--r--apps/hiperf/src/client.cc1612
-rw-r--r--apps/hiperf/src/client.h12
-rw-r--r--apps/hiperf/src/common.h288
-rw-r--r--apps/hiperf/src/forwarder_config.h97
-rw-r--r--apps/hiperf/src/forwarder_interface.cc696
-rw-r--r--apps/hiperf/src/forwarder_interface.h143
-rw-r--r--apps/hiperf/src/main.cc159
-rw-r--r--apps/hiperf/src/server.cc816
-rw-r--r--apps/hiperf/src/server.h6
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h8
-rw-r--r--apps/http-proxy/includes/hicn/http-proxy/http_session.h7
-rw-r--r--apps/http-proxy/src/icn_receiver.cc6
-rw-r--r--apps/ping/src/ping_client.cc71
-rw-r--r--apps/ping/src/ping_server.cc162
-rw-r--r--ctrl/CMakeLists.txt2
-rw-r--r--ctrl/facemgr/includes/hicn/facemgr/cfg.h2
-rw-r--r--ctrl/facemgr/src/cfg.c5
-rw-r--r--ctrl/facemgr/src/interfaces/network_framework/network_framework.c1
-rw-r--r--ctrl/facemgr/src/loop_dispatcher.c2
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/api.h10
-rw-r--r--ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h35
-rw-r--r--ctrl/libhicnctrl/src/CMakeLists.txt3
-rw-r--r--ctrl/libhicnctrl/src/api.c35
-rw-r--r--ctrl/libhicnctrl/src/api_private.h3
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_light_common.c3
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_light_common.h5
-rw-r--r--ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c187
-rw-r--r--docs/source/telemetry.md2
-rw-r--r--docs/source/transport.md42
-rw-r--r--hicn-light/CMakeLists.txt1
-rw-r--r--hicn-light/src/hicn/base/CMakeLists.txt10
-rw-r--r--hicn-light/src/hicn/base/bitmap.h191
-rw-r--r--hicn-light/src/hicn/base/common.h62
-rw-r--r--hicn-light/src/hicn/base/hash.h349
-rw-r--r--hicn-light/src/hicn/base/khash.h748
-rw-r--r--hicn-light/src/hicn/base/pool.c158
-rw-r--r--hicn-light/src/hicn/base/ring.h201
-rw-r--r--hicn-light/src/hicn/cli/hicnc.c65
-rw-r--r--hicn-light/src/hicn/cli/hicnd.c2
-rw-r--r--hicn-light/src/hicn/config/CMakeLists.txt1
-rw-r--r--hicn-light/src/hicn/config/command_stats.c18
-rw-r--r--hicn-light/src/hicn/config/commands.c115
-rw-r--r--hicn-light/src/hicn/config/commands.h3
-rw-r--r--hicn-light/src/hicn/config/configuration.h2
-rw-r--r--hicn-light/src/hicn/core/CMakeLists.txt2
-rw-r--r--hicn-light/src/hicn/core/address_pair.h6
-rw-r--r--hicn-light/src/hicn/core/connection.c12
-rw-r--r--hicn-light/src/hicn/core/connection.h6
-rw-r--r--hicn-light/src/hicn/core/connection_table.c78
-rw-r--r--hicn-light/src/hicn/core/connection_table.h68
-rw-r--r--hicn-light/src/hicn/core/connection_vft.h4
-rw-r--r--hicn-light/src/hicn/core/content_store.c2
-rw-r--r--hicn-light/src/hicn/core/content_store.h4
-rw-r--r--hicn-light/src/hicn/core/fib_entry.c2
-rw-r--r--hicn-light/src/hicn/core/forwarder.c476
-rw-r--r--hicn-light/src/hicn/core/forwarder.h16
-rw-r--r--hicn-light/src/hicn/core/interest_manifest.c64
-rw-r--r--hicn-light/src/hicn/core/interest_manifest.h40
-rw-r--r--hicn-light/src/hicn/core/listener.c14
-rw-r--r--hicn-light/src/hicn/core/listener.h8
-rw-r--r--hicn-light/src/hicn/core/listener_table.c51
-rw-r--r--hicn-light/src/hicn/core/listener_table.h67
-rw-r--r--hicn-light/src/hicn/core/msgbuf_pool.c7
-rw-r--r--hicn-light/src/hicn/core/name.c3
-rw-r--r--hicn-light/src/hicn/core/nameBitvector.c2
-rw-r--r--hicn-light/src/hicn/core/nameBitvector.h8
-rw-r--r--hicn-light/src/hicn/core/packet_cache.c280
-rw-r--r--hicn-light/src/hicn/core/packet_cache.h161
-rw-r--r--hicn-light/src/hicn/core/policy_stats.h1
-rw-r--r--hicn-light/src/hicn/core/subscription.c2
-rw-r--r--hicn-light/src/hicn/io/base.c19
-rw-r--r--hicn-light/src/hicn/io/hicn.c8
-rw-r--r--hicn-light/src/hicn/io/tcp.c8
-rw-r--r--hicn-light/src/hicn/io/udp.c27
-rw-r--r--hicn-light/src/hicn/strategies/probe_generator.c2
-rw-r--r--hicn-light/src/hicn/strategies/probe_generator.h2
-rw-r--r--hicn-light/src/hicn/test/CMakeLists.txt1
-rw-r--r--hicn-light/src/hicn/test/test-bitmap.cc2
-rw-r--r--hicn-light/src/hicn/test/test-connection_table.cc48
-rw-r--r--hicn-light/src/hicn/test/test-hash.cc114
-rw-r--r--hicn-light/src/hicn/test/test-interest_manifest.cc79
-rw-r--r--hicn-light/src/hicn/test/test-khash.cc2
-rw-r--r--hicn-light/src/hicn/test/test-msgbuf_pool.cc2
-rw-r--r--hicn-light/src/hicn/test/test-packet_cache.cc312
-rw-r--r--hicn-light/src/hicn/test/test-pool.cc2
-rw-r--r--hicn-light/src/hicn/test/test-ring.cc2
-rw-r--r--hicn-light/src/hicn/test/test-subscription.cc2
-rw-r--r--hicn-light/src/hicn/test/test-utils.h26
-rw-r--r--hicn-light/src/hicn/test/test-vector.cc190
-rw-r--r--hicn-plugin/includes/vpp_plugins/hicn/error.h112
-rw-r--r--hicn-plugin/src/CMakeLists.txt3
-rw-r--r--hicn-plugin/src/cli.c90
-rw-r--r--hicn-plugin/src/data_fwd_node.c17
-rw-r--r--hicn-plugin/src/data_input_node.c8
-rw-r--r--hicn-plugin/src/data_pcslookup_node.c14
-rw-r--r--hicn-plugin/src/faces/app/face_prod_node.c150
-rw-r--r--hicn-plugin/src/faces/face.c6
-rw-r--r--hicn-plugin/src/faces/face.h69
-rw-r--r--hicn-plugin/src/faces/face_flags.h39
-rw-r--r--hicn-plugin/src/faces/face_node.c290
-rw-r--r--hicn-plugin/src/faces/iface_node.c316
-rw-r--r--hicn-plugin/src/hicn.c14
-rw-r--r--hicn-plugin/src/hicn.h58
-rw-r--r--hicn-plugin/src/hicn_buffer_flags.h35
-rw-r--r--hicn-plugin/src/interest_hitcs_node.c14
-rw-r--r--hicn-plugin/src/interest_hitpit.h4
-rw-r--r--hicn-plugin/src/interest_hitpit_node.c17
-rw-r--r--hicn-plugin/src/interest_pcslookup_node.c20
-rw-r--r--hicn-plugin/src/parser.h186
-rw-r--r--hicn-plugin/src/pg.c1340
-rw-r--r--hicn-plugin/src/pg.h142
-rw-r--r--hicn-plugin/src/pg_node.c1132
-rw-r--r--hicn-plugin/src/route.c10
-rw-r--r--hicn-plugin/src/strategy_node.c27
-rw-r--r--lib/includes/CMakeLists.txt6
-rw-r--r--lib/includes/hicn/base.h140
-rw-r--r--lib/includes/hicn/common.h80
-rw-r--r--lib/includes/hicn/compat.h2
-rw-r--r--lib/includes/hicn/header.h2
-rw-r--r--lib/includes/hicn/ops.h71
-rw-r--r--lib/includes/hicn/util/array.h4
-rw-r--r--lib/includes/hicn/util/bitmap.h212
-rw-r--r--lib/includes/hicn/util/hash.h367
-rw-r--r--lib/includes/hicn/util/khash.h826
-rw-r--r--lib/includes/hicn/util/pool.h (renamed from hicn-light/src/hicn/base/pool.h)98
-rw-r--r--lib/includes/hicn/util/ring.h227
-rw-r--r--lib/includes/hicn/util/vector.h (renamed from hicn-light/src/hicn/base/vector.h)265
-rw-r--r--lib/src/CMakeLists.txt3
-rw-r--r--lib/src/common.c73
-rw-r--r--lib/src/ops.c4
-rw-r--r--lib/src/protocol/ah.c4
-rw-r--r--lib/src/protocol/icmp.c4
-rw-r--r--lib/src/protocol/ipv4.c25
-rw-r--r--lib/src/protocol/ipv6.c25
-rw-r--r--lib/src/protocol/new.c5
-rw-r--r--lib/src/protocol/tcp.c29
-rw-r--r--lib/src/protocol/udp.c29
-rw-r--r--lib/src/util/log.c13
-rw-r--r--lib/src/util/pool.c174
-rw-r--r--lib/src/util/ring.c (renamed from hicn-light/src/hicn/base/ring.c)22
-rw-r--r--lib/src/util/vector.c (renamed from hicn-light/src/hicn/base/vector.c)76
-rw-r--r--libtransport/includes/hicn/transport/core/asio_wrapper.h3
-rw-r--r--libtransport/includes/hicn/transport/core/connector.h20
-rw-r--r--libtransport/includes/hicn/transport/core/content_object.h12
-rw-r--r--libtransport/includes/hicn/transport/core/interest.h18
-rw-r--r--libtransport/includes/hicn/transport/core/io_module.h10
-rw-r--r--libtransport/includes/hicn/transport/core/name.h7
-rw-r--r--libtransport/includes/hicn/transport/core/prefix.h28
-rw-r--r--libtransport/includes/hicn/transport/interfaces/CMakeLists.txt7
-rw-r--r--libtransport/includes/hicn/transport/interfaces/global_conf_interface.h16
-rw-r--r--libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h32
-rw-r--r--libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h34
-rw-r--r--libtransport/includes/hicn/transport/interfaces/portal.h2
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_consumer.h6
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h6
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_options_keys.h39
-rw-r--r--libtransport/includes/hicn/transport/interfaces/socket_producer.h7
-rw-r--r--libtransport/includes/hicn/transport/interfaces/statistics.h8
-rw-r--r--libtransport/includes/hicn/transport/portability/CMakeLists.txt2
-rw-r--r--libtransport/includes/hicn/transport/portability/cache.h87
-rw-r--r--libtransport/includes/hicn/transport/portability/endianess.h86
-rw-r--r--libtransport/includes/hicn/transport/portability/portability.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/chrono_typedefs.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/color.h95
-rw-r--r--libtransport/includes/hicn/transport/utils/event_thread.h34
-rw-r--r--libtransport/includes/hicn/transport/utils/linux.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/thread_pool.h3
-rw-r--r--libtransport/src/auth/signer.cc33
-rw-r--r--libtransport/src/auth/verifier.cc15
-rw-r--r--libtransport/src/core/CMakeLists.txt7
-rw-r--r--libtransport/src/core/constructor.cc36
-rw-r--r--libtransport/src/core/content_object.cc13
-rw-r--r--libtransport/src/core/facade.h6
-rw-r--r--libtransport/src/core/global_id_counter.h (renamed from libtransport/src/io_modules/forwarder/global_id_counter.h)0
-rw-r--r--libtransport/src/core/global_module_manager.h94
-rw-r--r--libtransport/src/core/global_workers.h2
-rw-r--r--libtransport/src/core/interest.cc79
-rw-r--r--libtransport/src/core/io_module.cc43
-rw-r--r--libtransport/src/core/local_connector.cc50
-rw-r--r--libtransport/src/core/local_connector.h47
-rw-r--r--libtransport/src/core/manifest.cc33
-rw-r--r--libtransport/src/core/manifest.h175
-rw-r--r--libtransport/src/core/manifest_format.h107
-rw-r--r--libtransport/src/core/manifest_format_fixed.cc236
-rw-r--r--libtransport/src/core/manifest_format_fixed.h54
-rw-r--r--libtransport/src/core/manifest_inline.h128
-rw-r--r--libtransport/src/core/name.cc3
-rw-r--r--libtransport/src/core/pending_interest.h24
-rw-r--r--libtransport/src/core/portal.cc12
-rw-r--r--libtransport/src/core/portal.h180
-rw-r--r--libtransport/src/core/prefix.cc190
-rw-r--r--libtransport/src/core/udp_connector.cc6
-rw-r--r--libtransport/src/core/udp_connector.h2
-rw-r--r--libtransport/src/core/udp_listener.cc9
-rw-r--r--libtransport/src/core/udp_listener.h6
-rw-r--r--libtransport/src/implementation/CMakeLists.txt13
-rw-r--r--libtransport/src/implementation/p2psecure_socket_consumer.cc370
-rw-r--r--libtransport/src/implementation/p2psecure_socket_consumer.h134
-rw-r--r--libtransport/src/implementation/p2psecure_socket_producer.cc347
-rw-r--r--libtransport/src/implementation/p2psecure_socket_producer.h114
-rw-r--r--libtransport/src/implementation/socket.cc4
-rw-r--r--libtransport/src/implementation/socket.h4
-rw-r--r--libtransport/src/implementation/socket_consumer.h90
-rw-r--r--libtransport/src/implementation/socket_producer.h43
-rw-r--r--libtransport/src/implementation/tls_rtc_socket_producer.cc208
-rw-r--r--libtransport/src/implementation/tls_rtc_socket_producer.h57
-rw-r--r--libtransport/src/implementation/tls_socket_consumer.cc343
-rw-r--r--libtransport/src/implementation/tls_socket_consumer.h110
-rw-r--r--libtransport/src/implementation/tls_socket_producer.cc550
-rw-r--r--libtransport/src/implementation/tls_socket_producer.h154
-rw-r--r--libtransport/src/interfaces/CMakeLists.txt16
-rw-r--r--libtransport/src/interfaces/global_configuration.cc22
-rw-r--r--libtransport/src/interfaces/p2psecure_socket_consumer.cc37
-rw-r--r--libtransport/src/interfaces/p2psecure_socket_producer.cc34
-rw-r--r--libtransport/src/interfaces/portal.cc8
-rw-r--r--libtransport/src/interfaces/socket_consumer.cc11
-rw-r--r--libtransport/src/interfaces/socket_producer.cc12
-rw-r--r--libtransport/src/interfaces/tls_rtc_socket_producer.cc31
-rw-r--r--libtransport/src/interfaces/tls_rtc_socket_producer.h36
-rw-r--r--libtransport/src/interfaces/tls_socket_consumer.cc30
-rw-r--r--libtransport/src/interfaces/tls_socket_consumer.h36
-rw-r--r--libtransport/src/interfaces/tls_socket_producer.cc30
-rw-r--r--libtransport/src/interfaces/tls_socket_producer.h36
-rw-r--r--libtransport/src/io_modules/CMakeLists.txt2
-rw-r--r--libtransport/src/io_modules/forwarder/CMakeLists.txt1
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder.cc39
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder.h1
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder_module.cc5
-rw-r--r--libtransport/src/io_modules/forwarder/forwarder_module.h1
-rw-r--r--libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.cc13
-rw-r--r--libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.h1
-rw-r--r--libtransport/src/io_modules/loopback/loopback_module.cc3
-rw-r--r--libtransport/src/io_modules/loopback/loopback_module.h1
-rw-r--r--libtransport/src/io_modules/memif/vpp_forwarder_module.cc5
-rw-r--r--libtransport/src/io_modules/memif/vpp_forwarder_module.h1
-rw-r--r--libtransport/src/protocols/byte_stream_reassembly.cc9
-rw-r--r--libtransport/src/protocols/byte_stream_reassembly.h3
-rw-r--r--libtransport/src/protocols/cbr.cc2
-rw-r--r--libtransport/src/protocols/datagram_reassembly.cc5
-rw-r--r--libtransport/src/protocols/datagram_reassembly.h4
-rw-r--r--libtransport/src/protocols/fec/rely.cc2
-rw-r--r--libtransport/src/protocols/fec/rely.h25
-rw-r--r--libtransport/src/protocols/fec/rs.cc7
-rw-r--r--libtransport/src/protocols/fec/rs.h33
-rw-r--r--libtransport/src/protocols/fec_base.h4
-rw-r--r--libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc31
-rw-r--r--libtransport/src/protocols/manifest_incremental_indexer_bytestream.h2
-rw-r--r--libtransport/src/protocols/prod_protocol_bytestream.cc72
-rw-r--r--libtransport/src/protocols/prod_protocol_rtc.cc426
-rw-r--r--libtransport/src/protocols/prod_protocol_rtc.h45
-rw-r--r--libtransport/src/protocols/production_protocol.cc4
-rw-r--r--libtransport/src/protocols/production_protocol.h3
-rw-r--r--libtransport/src/protocols/raaqm.cc8
-rw-r--r--libtransport/src/protocols/raaqm.h2
-rw-r--r--libtransport/src/protocols/raaqm_data_path.cc4
-rw-r--r--libtransport/src/protocols/raaqm_data_path.h2
-rw-r--r--libtransport/src/protocols/rate_estimation.cc10
-rw-r--r--libtransport/src/protocols/rate_estimation.h8
-rw-r--r--libtransport/src/protocols/reassembly.h6
-rw-r--r--libtransport/src/protocols/rtc/probe_handler.cc3
-rw-r--r--libtransport/src/protocols/rtc/rtc.cc125
-rw-r--r--libtransport/src/protocols/rtc/rtc.h3
-rw-r--r--libtransport/src/protocols/rtc/rtc_consts.h76
-rw-r--r--libtransport/src/protocols/rtc/rtc_data_path.cc13
-rw-r--r--libtransport/src/protocols/rtc/rtc_data_path.h5
-rw-r--r--libtransport/src/protocols/rtc/rtc_forwarding_strategy.cc106
-rw-r--r--libtransport/src/protocols/rtc/rtc_forwarding_strategy.h6
-rw-r--r--libtransport/src/protocols/rtc/rtc_ldr.cc73
-rw-r--r--libtransport/src/protocols/rtc/rtc_ldr.h4
-rw-r--r--libtransport/src/protocols/rtc/rtc_packet.h64
-rw-r--r--libtransport/src/protocols/rtc/rtc_reassembly.cc2
-rw-r--r--libtransport/src/protocols/rtc/rtc_recovery_strategy.cc197
-rw-r--r--libtransport/src/protocols/rtc/rtc_recovery_strategy.h35
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_delay.cc17
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_delay.h1
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_fec_only.cc3
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_fec_only.h1
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_low_rate.cc4
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_low_rate.h1
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_recovery_off.cc3
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_recovery_off.h1
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_rtx_only.cc3
-rw-r--r--libtransport/src/protocols/rtc/rtc_rs_rtx_only.h1
-rw-r--r--libtransport/src/protocols/rtc/rtc_state.cc80
-rw-r--r--libtransport/src/protocols/rtc/rtc_state.h24
-rw-r--r--libtransport/src/protocols/rtc/rtc_verifier.cc157
-rw-r--r--libtransport/src/protocols/rtc/rtc_verifier.h81
-rw-r--r--libtransport/src/protocols/transport_protocol.cc24
-rw-r--r--libtransport/src/protocols/transport_protocol.h5
-rw-r--r--libtransport/src/test/CMakeLists.txt2
-rw-r--r--libtransport/src/test/test_core_manifest.cc227
-rw-r--r--libtransport/src/test/test_interest.cc39
-rw-r--r--libtransport/src/test/test_memif_connector.cc4
-rw-r--r--libtransport/src/test/test_packet_allocator.cc25
-rw-r--r--libtransport/src/test/test_prefix.cc334
-rw-r--r--libtransport/src/test/test_quadloop.cc176
-rw-r--r--libtransport/src/utils/epoll_event_reactor.h2
-rw-r--r--libtransport/src/utils/fd_deadline_timer.h4
-rw-r--r--libtransport/src/utils/suffix_strategy.h6
-rw-r--r--telemetry/.clang-format3
-rw-r--r--telemetry/CMakeLists.txt61
-rw-r--r--telemetry/cmake/packaging.cmake (renamed from telemetry/vpp-collectd/cmake/packaging.cmake)4
-rw-r--r--telemetry/collectd.conf54
-rw-r--r--telemetry/data_model.h143
-rw-r--r--telemetry/hicn-light-collectd/CMakeLists.txt65
-rw-r--r--telemetry/hicn-light-collectd/hicn_light.c200
-rw-r--r--telemetry/kafka-collectd/CMakeLists.txt62
-rw-r--r--telemetry/kafka-collectd/format_influxdb.c190
-rw-r--r--telemetry/kafka-collectd/format_influxdb.h45
-rw-r--r--telemetry/kafka-collectd/write_kafka_line_protocol.c526
-rw-r--r--telemetry/third-party/CMakeLists.txt18
-rw-r--r--telemetry/vpp-collectd/CMakeLists.txt24
-rw-r--r--telemetry/vpp-collectd/common/README.md12
-rw-r--r--telemetry/vpp-collectd/common/common.h405
-rw-r--r--telemetry/vpp-collectd/common/meta_data.h71
-rw-r--r--telemetry/vpp-collectd/common/plugin.h483
-rw-r--r--telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt49
-rw-r--r--telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c175
-rw-r--r--telemetry/vpp-collectd/vpp/CMakeLists.txt26
-rw-r--r--telemetry/vpp-collectd/vpp/vpp.c101
-rw-r--r--tests/.env2
-rw-r--r--tests/2-nodes-hicn-light.yml6
-rw-r--r--tests/2-nodes-vpp-bridge.yml6
-rw-r--r--tests/2-nodes-vpp-memif-replication.yml6
-rw-r--r--tests/2-nodes-vpp-memif.yml6
-rw-r--r--tests/Makefile6
-rwxr-xr-xtests/config.sh4
-rw-r--r--tests/forwarder.robot45
-rw-r--r--tests/hiperf-local.sh21
-rw-r--r--tests/test_forwarder.sh437
-rw-r--r--versions.cmake2
337 files changed, 13090 insertions, 13478 deletions
diff --git a/.cz.toml b/.cz.toml
index 1f9d82df6..a131c41ac 100644
--- a/.cz.toml
+++ b/.cz.toml
@@ -1,5 +1,5 @@
[tool]
[tool.commitizen]
name = "cz_conventional_commits"
-version = "3.11.3"
+version = "3.13.0"
tag_format = "v$version"
diff --git a/.gitignore b/.gitignore
index 9099d8d0a..cbdd34811 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,4 @@ tests/**/*.xml
tests/**/*.html
tests/**/*.log
*.tar
+**/env \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 27afca29b..41ecda018 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,6 +11,32 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+
+##############################################################
+# Compiler preferences
+##############################################################
+set(CMAKE_C_COMPILER_NAMES
+ clang-13
+ clang-12
+ clang-11
+ clang-10
+ clang-9
+ gcc-10
+ gcc-9
+ cc
+)
+
+set(CMAKE_CXX_COMPILER_NAMES
+ clang++-13
+ clang++-12
+ clang++-11
+ clang++-10
+ clang++-9
+ g++-10
+ g++-9
+ c++
+)
+
##############################################################
# Project and cmake version
##############################################################
diff --git a/Dockerfile.dev b/Dockerfile.dev
index cfb75f1b4..9c96193a9 100644
--- a/Dockerfile.dev
+++ b/Dockerfile.dev
@@ -1,17 +1,16 @@
-FROM dockerhub.cisco.com/icn-docker/hicn-base-devel-focal:x86_64
+FROM ubuntu:focal
+ENV DEBIAN_FRONTEND=noninteractive
WORKDIR /hicn-build
-# Get versions from versions.cmake
-ARG VERSION_PATH=/tmp/versions.cmake
-COPY versions.cmake ${VERSION_PATH}
-ARG INSTALL_VPP_SCRIPT=/tmp/install-vpp.sh
-COPY scripts/install-vpp.sh ${INSTALL_VPP_SCRIPT}
+COPY Makefile versions.cmake ./
+COPY scripts scripts/
-RUN VERSION_PATH=${VERSION_PATH} bash -x ${INSTALL_VPP_SCRIPT}
-RUN apt update && apt-get install -y \
- libssl-dev \
- iproute2 \
- iperf3 \
- iputils-ping \
- tcpdump \
- gdb --no-install-recommends
+RUN apt update && apt-get install -y \
+ make \
+ sudo \
+ curl \
+ git
+
+RUN make deps debug-tools
+
+ENV DEBIAN_FRONTEND=
diff --git a/Makefile b/Makefile
index 3d74f9b72..1fb963292 100644
--- a/Makefile
+++ b/Makefile
@@ -47,15 +47,18 @@ endif
DEB_DEPENDS = cmake ninja-build unzip python3-ply libasio-dev
DEB_DEPENDS += libconfig-dev libconfig++-dev libevent-dev
DEB_DEPENDS += build-essential vpp-dev libvppinfra-dev
-DEB_DEPENDS += vpp-plugin-core libcurl4-openssl-dev
+DEB_DEPENDS += vpp-plugin-core libcurl4-openssl-dev libssl-dev
DEB_DEPENDS += doxygen
-MACOS_DEPENDS = asio libconfig ninja
+DEBUG_DEPENDS = iproute2 iperf3 iputils-ping tcpdump gdb
+
+MACOS_DEPENDS = asio libconfig ninja openssl@1.1
.PHONY = help
help:
@echo "Targets"
@echo " dep - install software dependencies"
+ @echo " debug-tools - install debug dependencies"
@echo " build - build debug binaries. Optional argument: INSTALL_DIR"
@echo " build-release - build release binaries"
@echo " build-coverage - build with coverage metainformation"
@@ -97,6 +100,10 @@ endif
.PHONY = deps
deps: dep
+.PHONY = debug-tools
+debug-tools:
+ @sudo -E apt-get $(APT_ARGS) -y install $(DEBUG_DEPENDS) --no-install-recommends
+
define build_folder
$(eval LOWER_BUILDTYPE=$(shell echo $(2) | tr A-Z a-z))
$(eval BUILD_FOLDER=$(or $(BUILD_PATH), build-$(LOWER_BUILDTYPE)-$(OS_ID)))
diff --git a/apps/hiperf/CMakeLists.txt b/apps/hiperf/CMakeLists.txt
index 6986c90aa..8a0c46ebc 100644
--- a/apps/hiperf/CMakeLists.txt
+++ b/apps/hiperf/CMakeLists.txt
@@ -19,7 +19,6 @@ if (NOT DISABLE_EXECUTABLES)
${CMAKE_CURRENT_SOURCE_DIR}/src/client.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/server.cc
- ${CMAKE_CURRENT_SOURCE_DIR}/src/forwarder_interface.cc
)
diff --git a/apps/hiperf/src/client.cc b/apps/hiperf/src/client.cc
index ba36cd20e..0e1f596c5 100644
--- a/apps/hiperf/src/client.cc
+++ b/apps/hiperf/src/client.cc
@@ -14,8 +14,7 @@
*/
#include <client.h>
-#include <forwarder_config.h>
-#include <forwarder_interface.h>
+#include <hicn/transport/portability/endianess.h>
#include <libconfig.h++>
@@ -31,1098 +30,831 @@ class Callback;
* Hiperf client class: configure and setup an hicn consumer following the
* ClientConfiguration.
*/
-class HIperfClient::Impl : ForwarderInterface::ICallback {
+class HIperfClient::Impl {
friend class Callback;
friend class RTCCallback;
- static const constexpr uint16_t log2_header_counter = 4;
-
- 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); }
- };
-
- public:
- Impl(const hiperf::ClientConfiguration &conf)
- : configuration_(conf),
- total_duration_milliseconds_(0),
- old_bytes_value_(0),
- 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_definitely_lost_data_value_(0),
- old_retx_value_(0),
- old_sent_int_value_(0),
- old_received_nacks_value_(0),
- old_fec_pkt_(0),
- avg_data_delay_(0),
- delay_sample_(0),
- received_bytes_(0),
- received_data_pkt_(0),
- auth_alerts_(0),
- data_delays_(""),
- signals_(io_service_),
- rtc_callback_(*this),
- callback_(*this),
- socket_(io_service_),
- // switch_threshold_(~0),
- fwd_connected_(false),
- use_bestpath_(false),
- rtt_threshold_(~0),
- loss_threshold_(~0),
- prefix_name_(""),
- prefix_len_(0),
- // done_(false),
- header_counter_mask_((1 << log2_header_counter) - 1),
- header_counter_(0),
- print_headers_(configuration_.print_headers_),
- first_(true),
- forwarder_interface_(io_service_) {
- setForwarderConnection(conf.forwarder_type_);
+ static inline constexpr uint16_t klog2_header_counter() { return 4; }
+ static inline constexpr uint16_t kheader_counter_mask() {
+ return (1 << klog2_header_counter()) - 1;
}
- virtual ~Impl() {}
-
- void checkReceivedRtcContent(ConsumerSocket &c,
- const ContentObject &contentObject) {}
-
- void processLeavingInterest(ConsumerSocket &c, const Interest &interest) {}
-
- void addFace(const std::string &local_address, uint16_t local_port,
- const std::string &remote_address, uint16_t remote_port,
- std::string interface);
-
- void handleTimerExpiration(ConsumerSocket &c,
- const TransportStatistics &stats) {
- const char separator = ' ';
- const int width = 18;
-
- utils::SteadyTime::TimePoint t2 = utils::SteadyTime::Clock::now();
- auto exact_duration = utils::SteadyTime::getDurationMs(t_stats_, t2);
-
- std::stringstream interval_ms;
- interval_ms << total_duration_milliseconds_ << "-"
- << total_duration_milliseconds_ + exact_duration.count();
-
- std::stringstream bytes_transferred;
- bytes_transferred << std::fixed << std::setprecision(3)
- << (stats.getBytesRecv() - old_bytes_value_) / 1000000.0
- << std::setfill(separator);
-
- std::stringstream bandwidth;
- bandwidth << ((stats.getBytesRecv() - old_bytes_value_) * 8) /
- (exact_duration.count()) / 1000.0
- << std::setfill(separator);
-
- std::stringstream window;
- window << stats.getAverageWindowSize() << std::setfill(separator);
+ class ConsumerContext
+ : public Base<ConsumerContext, ClientConfiguration, Impl>,
+ private ConsumerSocket::ReadCallback {
+ static inline const std::size_t kmtu = HIPERF_MTU;
- std::stringstream avg_rtt;
- avg_rtt << stats.getAverageRtt() << std::setfill(separator);
-
- if (configuration_.rtc_) {
- std::stringstream lost_data;
- lost_data << stats.getLostData() - old_lost_data_value_
- << std::setfill(separator);
-
- std::stringstream bytes_recovered_data;
- bytes_recovered_data << stats.getBytesRecoveredData() -
- old_bytes_recovered_value_
- << std::setfill(separator);
-
- std::stringstream definitely_lost_data;
- definitely_lost_data << stats.getDefinitelyLostData() -
- old_definitely_lost_data_value_
- << std::setfill(separator);
-
- std::stringstream data_delay;
- data_delay << std::fixed << std::setprecision(3) << avg_data_delay_
- << std::setfill(separator);
-
- std::stringstream received_data_pkt;
- received_data_pkt << received_data_pkt_ << std::setfill(separator);
-
- std::stringstream goodput;
- goodput << std::fixed << std::setprecision(3)
- << (received_bytes_ * 8.0) / (exact_duration.count()) / 1000.0
- << std::setfill(separator);
-
- 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);
-
- std::stringstream interest_sent;
- interest_sent << stats.getInterestTx() - old_sent_int_value_
- << std::setfill(separator);
+ public:
+ using ConfType = ClientConfiguration;
+ using ParentType = typename HIperfClient::Impl;
+ static inline auto getContextType() -> std::string {
+ return "ConsumerContext";
+ }
+
+ ConsumerContext(Impl &client, int consumer_identifier)
+ : Base(client, client.io_service_, consumer_identifier),
+ receive_buffer_(
+ utils::MemBuf::create(client.config_.receive_buffer_size_)),
+ socket_(client.io_service_),
+ payload_size_max_(PayloadSize(client.config_.packet_format_)
+ .getPayloadSizeMax(RTC_HEADER_SIZE)),
+ nb_iterations_(client.config_.nb_iterations_) {}
+
+ ConsumerContext(ConsumerContext &&other) noexcept
+ : Base(std::move(other)),
+ receive_buffer_(std::move(other.receive_buffer_)),
+ socket_(std::move(other.socket_)),
+ payload_size_max_(other.payload_size_max_),
+ remote_(std::move(other.remote_)),
+ nb_iterations_(other.nb_iterations_),
+ saved_stats_(std::move(other.saved_stats_)),
+ header_counter_(other.header_counter_),
+ first_(other.first_),
+ consumer_socket_(std::move(other.consumer_socket_)),
+ producer_socket_(std::move(other.producer_socket_)) {}
+
+ ~ConsumerContext() override = default;
+
+ /***************************************************************
+ * ConsumerSocket::ReadCallback implementation
+ ***************************************************************/
- std::stringstream nacks;
- nacks << stats.getReceivedNacks() - old_received_nacks_value_
- << std::setfill(separator);
+ bool isBufferMovable() noexcept override { return false; }
- std::stringstream fec_pkt;
- fec_pkt << stats.getReceivedFEC() - old_fec_pkt_
- << std::setfill(separator);
+ void getReadBuffer(uint8_t **application_buffer,
+ size_t *max_length) override {
+ *application_buffer = receive_buffer_->writableData();
- std::stringstream queuing_delay;
- queuing_delay << std::fixed << std::setprecision(3)
- << stats.getQueuingDelay() << std::setfill(separator);
+ if (configuration_.rtc_) {
+ *max_length = kmtu;
+ } else {
+ *max_length = configuration_.receive_buffer_size_;
+ }
+ }
- std::stringstream residual_losses;
- double rl_perc = stats.getResidualLossRate() * 100;
- residual_losses << std::fixed << std::setprecision(2) << rl_perc
- << std::setfill(separator);
+ void readBufferAvailable(
+ std::unique_ptr<utils::MemBuf> &&buffer) noexcept override {
+ // Nothing to do here
+ auto ret = std::move(buffer);
+ }
- std::stringstream quality_score;
- quality_score << std::fixed << (int)stats.getQualityScore()
- << std::setfill(separator);
+ void readDataAvailable(std::size_t length) noexcept override {
+ if (configuration_.rtc_) {
+ saved_stats_.received_bytes_ += length;
+ saved_stats_.received_data_pkt_++;
- std::stringstream alerts;
- alerts << stats.getAlerts() << std::setfill(separator);
+ // collecting delay stats. Just for performance testing
+ auto senderTimeStamp =
+ *reinterpret_cast<uint64_t *>(receive_buffer_->writableData());
- std::stringstream auth_alerts;
- auth_alerts << auth_alerts_ << std::setfill(separator);
+ auto now = utils::SystemTime::nowMs().count();
+ auto new_delay = double(now - senderTimeStamp);
- if (fwd_connected_ && use_bestpath_ &&
- ((stats.getAverageRtt() > rtt_threshold_) ||
- ((stats.getResidualLossRate() * 100) > loss_threshold_))) {
- forwarder_interface_.setStrategy(prefix_name_, prefix_len_, "bestpath");
- }
+ if (senderTimeStamp > now)
+ new_delay = -1 * double(senderTimeStamp - now);
- if ((header_counter_ == 0 && print_headers_) || first_) {
- std::cout << std::right << std::setw(width) << "Interval[ms]";
- std::cout << std::right << std::setw(width) << "RecvData[pkt]";
- std::cout << std::right << std::setw(width) << "Bandwidth[Mbps]";
- std::cout << std::right << std::setw(width) << "Goodput[Mbps]";
- std::cout << std::right << std::setw(width) << "LossRate[%]";
- std::cout << std::right << std::setw(width) << "Retr[pkt]";
- std::cout << std::right << std::setw(width) << "InterestSent";
- std::cout << std::right << std::setw(width) << "ReceivedNacks";
- std::cout << std::right << std::setw(width) << "SyncWnd[pkt]";
- std::cout << std::right << std::setw(width) << "MinRtt[ms]";
- std::cout << std::right << std::setw(width) << "QueuingDelay[ms]";
- std::cout << std::right << std::setw(width) << "LostData[pkt]";
- std::cout << std::right << std::setw(width) << "RecoveredData";
- std::cout << std::right << std::setw(width) << "DefinitelyLost";
- std::cout << std::right << std::setw(width) << "State";
- std::cout << std::right << std::setw(width) << "DataDelay[ms]";
- std::cout << std::right << std::setw(width) << "FecPkt";
- std::cout << std::right << std::setw(width) << "Congestion";
- std::cout << std::right << std::setw(width) << "ResidualLosses";
- std::cout << std::right << std::setw(width) << "QualityScore";
- std::cout << std::right << std::setw(width) << "Alerts";
- std::cout << std::right << std::setw(width) << "AuthAlerts"
- << std::endl;
-
- first_ = false;
- }
+ saved_stats_.delay_sample_++;
+ saved_stats_.avg_data_delay_ =
+ saved_stats_.avg_data_delay_ +
+ (double(new_delay) - saved_stats_.avg_data_delay_) /
+ saved_stats_.delay_sample_;
- std::cout << std::right << std::setw(width) << interval_ms.str();
- std::cout << std::right << std::setw(width) << received_data_pkt.str();
- std::cout << std::right << std::setw(width) << bandwidth.str();
- std::cout << std::right << std::setw(width) << goodput.str();
- std::cout << std::right << std::setw(width) << loss_rate.str();
- std::cout << std::right << std::setw(width) << retx_sent.str();
- std::cout << std::right << std::setw(width) << interest_sent.str();
- std::cout << std::right << std::setw(width) << nacks.str();
- std::cout << std::right << std::setw(width) << window.str();
- std::cout << std::right << std::setw(width) << avg_rtt.str();
- std::cout << std::right << std::setw(width) << queuing_delay.str();
- std::cout << std::right << std::setw(width) << lost_data.str();
- std::cout << std::right << std::setw(width) << bytes_recovered_data.str();
- std::cout << std::right << std::setw(width) << definitely_lost_data.str();
- std::cout << std::right << std::setw(width) << stats.getCCStatus();
- std::cout << std::right << std::setw(width) << data_delay.str();
- std::cout << std::right << std::setw(width) << fec_pkt.str();
- std::cout << std::right << std::setw(width) << stats.isCongested();
- std::cout << std::right << std::setw(width) << residual_losses.str();
- std::cout << std::right << std::setw(width) << quality_score.str();
- std::cout << std::right << std::setw(width) << alerts.str();
- std::cout << std::right << std::setw(width) << auth_alerts.str();
- std::cout << std::endl;
-
- if (configuration_.test_mode_) {
- if (data_delays_.size() > 0) data_delays_.pop_back();
-
- auto now = utils::SteadyTime::nowMs();
- std::cout << std::fixed << std::setprecision(0) << now.count()
- << " DATA-DELAYS:[" << data_delays_ << "]" << std::endl;
- }
+ if (configuration_.test_mode_) {
+ saved_stats_.data_delays_ += std::to_string(int(new_delay));
+ saved_stats_.data_delays_ += ",";
+ }
- // statistics not yet available in the transport
- // std::cout << std::right << std::setw(width) << interest_fec_tx.str();
- // std::cout << std::right << std::setw(width) << bytes_fec_recv.str();
- } else {
- if ((header_counter_ == 0 && print_headers_) || first_) {
- std::cout << std::right << std::setw(width) << "Interval[ms]";
- std::cout << std::right << std::setw(width) << "Transfer[MB]";
- std::cout << std::right << std::setw(width) << "Bandwidth[Mbps]";
- std::cout << std::right << std::setw(width) << "Retr[pkt]";
- std::cout << std::right << std::setw(width) << "Cwnd[Int]";
- std::cout << std::right << std::setw(width) << "AvgRtt[ms]"
- << std::endl;
-
- first_ = false;
+ if (configuration_.relay_ && configuration_.parallel_flows_ == 1) {
+ producer_socket_->produceDatagram(
+ configuration_.relay_name_.makeName(),
+ receive_buffer_->writableData(),
+ length < payload_size_max_ ? length : payload_size_max_);
+ }
+ if (configuration_.output_stream_mode_ &&
+ configuration_.parallel_flows_ == 1) {
+ const uint8_t *start = receive_buffer_->writableData();
+ start += sizeof(uint64_t);
+ std::size_t pkt_len = length - sizeof(uint64_t);
+ socket_.send_to(asio::buffer(start, pkt_len), remote_);
+ }
}
-
- std::cout << std::right << std::setw(width) << interval_ms.str();
- std::cout << std::right << std::setw(width) << bytes_transferred.str();
- std::cout << std::right << std::setw(width) << bandwidth.str();
- std::cout << std::right << std::setw(width) << stats.getRetxCount();
- std::cout << std::right << std::setw(width) << window.str();
- std::cout << std::right << std::setw(width) << avg_rtt.str() << 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_definitely_lost_data_value_ = stats.getDefinitelyLostData();
- old_fec_interest_tx_value_ = stats.getInterestFecTxCount();
- old_fec_data_rx_value_ = stats.getBytesFecRecv();
- old_retx_value_ = stats.getRetxCount();
- old_sent_int_value_ = stats.getInterestTx();
- old_received_nacks_value_ = stats.getReceivedNacks();
- old_fec_pkt_ = stats.getReceivedFEC();
- delay_sample_ = 0;
- avg_data_delay_ = 0;
- received_bytes_ = 0;
- received_data_pkt_ = 0;
- data_delays_ = "";
-
- t_stats_ = utils::SteadyTime::Clock::now();
-
- header_counter_ = (header_counter_ + 1) & header_counter_mask_;
-
- if (--configuration_.nb_iterations_ == 0) {
- // We reached the maximum nb of runs. Stop now.
- io_service_.stop();
- }
- }
-
- bool setForwarderConnection(forwarder_type_t forwarder_type) {
- using namespace libconfig;
- Config cfg;
-
- const char *conf_file = getenv("FORWARDER_CONFIG");
- if (!conf_file) return false;
-
- if ((forwarder_type != HICNLIGHT) && (forwarder_type != HICNLIGHT_NG))
- return false;
-
- try {
- cfg.readFile(conf_file);
- } catch (const FileIOException &fioex) {
- std::cerr << "I/O error while reading file." << std::endl;
- return false;
- } catch (const ParseException &pex) {
- std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
- << " - " << pex.getError() << std::endl;
- return false;
}
- Setting &config = cfg.getRoot();
-
- /* conf file example
- *
- * use_bestpath = "ON | OFF"
- * rtt_threshold = 200 //ms
- * loss_threshold = 20 //%
- * name = "b001::/16"
- */
-
- if (config.exists("use_bestpath")) {
- std::string val;
- config.lookupValue("use_bestpath", val);
- if (val.compare("ON") == 0) use_bestpath_ = true;
+ size_t maxBufferSize() const override {
+ return configuration_.rtc_ ? kmtu : configuration_.receive_buffer_size_;
}
- if (config.exists("rtt_threshold")) {
- unsigned val;
- config.lookupValue("rtt_threshold", val);
- rtt_threshold_ = val;
+ void readError(const std::error_code &ec) noexcept override {
+ getOutputStream() << "Error " << ec.message()
+ << " while reading from socket" << std::endl;
+ parent_.io_service_.stop();
}
- if (config.exists("loss_threshold")) {
- unsigned val;
- config.lookupValue("loss_threshold", val);
- loss_threshold_ = val;
- }
+ void readSuccess(std::size_t total_size) noexcept override {
+ if (configuration_.rtc_) {
+ getOutputStream() << "Data successfully read" << std::endl;
+ } else {
+ auto t2 = utils::SteadyTime::now();
+ auto dt =
+ utils::SteadyTime::getDurationUs(saved_stats_.t_download_, t2);
+ auto usec = dt.count();
- if (config.exists("name")) {
- std::string route;
- config.lookupValue("name", route);
+ getOutputStream() << "Content retrieved. Size: " << total_size
+ << " [Bytes]" << std::endl;
- std::string delimiter = "/";
- size_t pos = 0;
+ getOutputStream() << "Elapsed Time: " << usec / 1000000.0
+ << " seconds -- "
+ << double(total_size * 8) * 1.0 / double(usec) * 1.0
+ << " [Mbps]" << std::endl;
- if ((pos = route.find(delimiter)) != std::string::npos) {
- prefix_name_ = route.substr(0, pos);
- route.erase(0, pos + delimiter.length());
- prefix_len_ = std::stoul(route.substr(0));
+ parent_.io_service_.stop();
}
}
- forwarder_interface_.initForwarderInterface(this, forwarder_type);
-
- return true;
- }
+ /***************************************************************
+ * End of ConsumerSocket::ReadCallback implementation
+ ***************************************************************/
- void onHicnServiceReady() override {
- std::cout << "Successfully connected to local forwarder!" << std::endl;
- fwd_connected_ = true;
- }
+ private:
+ struct SavedStatistics {
+ utils::SteadyTime::TimePoint t_stats_{};
+ utils::SteadyTime::TimePoint t_download_{};
+ uint32_t total_duration_milliseconds_{0};
+ uint64_t old_bytes_value_{0};
+ uint64_t old_interest_tx_value_{0};
+ uint64_t old_fec_interest_tx_value_{0};
+ uint64_t old_fec_data_rx_value_{0};
+ uint64_t old_lost_data_value_{0};
+ uint64_t old_bytes_recovered_value_{0};
+ uint64_t old_definitely_lost_data_value_{0};
+ uint64_t old_retx_value_{0};
+ uint64_t old_sent_int_value_{0};
+ uint64_t old_received_nacks_value_{0};
+ uint32_t old_fec_pkt_{0};
+ // 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_{0};
+ uint32_t delay_sample_{0};
+ uint32_t received_bytes_{0};
+ uint32_t received_data_pkt_{0};
+ uint32_t auth_alerts_{0};
+ std::string data_delays_{""};
+ };
+
+ /***************************************************************
+ * Transport callbacks
+ ***************************************************************/
+
+ void checkReceivedRtcContent(
+ [[maybe_unused]] const ConsumerSocket &c,
+ [[maybe_unused]] const ContentObject &content_object) const {
+ // Nothing to do here
+ }
+
+ void processLeavingInterest(const ConsumerSocket & /*c*/,
+ const Interest & /*interest*/) const {
+ // Nothing to do here
+ }
+
+ transport::auth::VerificationPolicy onAuthFailed(
+ transport::auth::Suffix /*suffix*/,
+ transport::auth::VerificationPolicy /*policy*/) {
+ saved_stats_.auth_alerts_++;
+ return transport::auth::VerificationPolicy::ACCEPT;
+ }
+
+ void handleTimerExpiration([[maybe_unused]] const ConsumerSocket &c,
+ const TransportStatistics &stats) {
+ const char separator = ' ';
+ const int width = 18;
+
+ utils::SteadyTime::TimePoint t2 = utils::SteadyTime::Clock::now();
+ auto exact_duration =
+ utils::SteadyTime::getDurationMs(saved_stats_.t_stats_, t2);
+
+ std::stringstream interval_ms;
+ interval_ms << saved_stats_.total_duration_milliseconds_ << "-"
+ << saved_stats_.total_duration_milliseconds_ +
+ exact_duration.count();
+
+ std::stringstream bytes_transferred;
+ bytes_transferred << std::fixed << std::setprecision(3)
+ << double(stats.getBytesRecv() -
+ saved_stats_.old_bytes_value_) /
+ 1000000.0
+ << std::setfill(separator);
+
+ std::stringstream bandwidth;
+ bandwidth << (double(stats.getBytesRecv() -
+ saved_stats_.old_bytes_value_) *
+ 8) /
+ (exact_duration.count()) / 1000.0
+ << std::setfill(separator);
- void onRouteConfigured(
- std::vector<ForwarderInterface::RouteInfoPtr> &route_info) override {
- std::cout << "Routes successfully configured!" << std::endl;
- }
+ std::stringstream window;
+ window << stats.getAverageWindowSize() << std::setfill(separator);
-#ifdef FORWARDER_INTERFACE
- bool parseConfig(const char *conf_file) {
- using namespace libconfig;
- Config cfg;
-
- try {
- cfg.readFile(conf_file);
- } catch (const FileIOException &fioex) {
- std::cerr << "I/O error while reading file." << std::endl;
- return false;
- } catch (const ParseException &pex) {
- std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
- << " - " << pex.getError() << std::endl;
- return false;
- }
+ std::stringstream avg_rtt;
+ avg_rtt << std::setprecision(3) << std::fixed << stats.getAverageRtt()
+ << std::setfill(separator);
- Setting &config = cfg.getRoot();
+ if (configuration_.rtc_) {
+ std::stringstream lost_data;
+ lost_data << stats.getLostData() - saved_stats_.old_lost_data_value_
+ << std::setfill(separator);
+
+ std::stringstream bytes_recovered_data;
+ bytes_recovered_data << stats.getBytesRecoveredData() -
+ saved_stats_.old_bytes_recovered_value_
+ << std::setfill(separator);
+
+ std::stringstream definitely_lost_data;
+ definitely_lost_data << stats.getDefinitelyLostData() -
+ saved_stats_.old_definitely_lost_data_value_
+ << std::setfill(separator);
+
+ std::stringstream data_delay;
+ data_delay << std::fixed << std::setprecision(3)
+ << saved_stats_.avg_data_delay_ << std::setfill(separator);
+
+ std::stringstream received_data_pkt;
+ received_data_pkt << saved_stats_.received_data_pkt_
+ << std::setfill(separator);
+
+ std::stringstream goodput;
+ goodput << std::fixed << std::setprecision(3)
+ << (saved_stats_.received_bytes_ * 8.0) /
+ (exact_duration.count()) / 1000.0
+ << std::setfill(separator);
- if (config.exists("switch_threshold")) {
- unsigned threshold;
- config.lookupValue("switch_threshold", threshold);
- switch_threshold_ = threshold;
- }
+ std::stringstream loss_rate;
+ loss_rate << std::fixed << std::setprecision(2)
+ << stats.getLossRatio() * 100.0 << std::setfill(separator);
- // listeners
- if (config.exists("listeners")) {
- // get path where looking for modules
- const Setting &listeners = config.lookup("listeners");
- auto count = listeners.getLength();
-
- for (int i = 0; i < count; i++) {
- const Setting &listener = listeners[i];
- ListenerConfig list;
- unsigned port;
- std::string interface;
-
- list.name = listener.getName();
- listener.lookupValue("local_address", list.address);
- listener.lookupValue("local_port", port);
- listener.lookupValue("interface", list.interface);
- list.port = (uint16_t)(port);
-
- std::cout << "Adding listener " << list.name << ", ( " << list.address
- << ":" << list.port << ")" << std::endl;
- config_.addListener(std::move(list));
- }
- }
+ std::stringstream retx_sent;
+ retx_sent << stats.getRetxCount() - saved_stats_.old_retx_value_
+ << std::setfill(separator);
- // connectors
- if (config.exists("connectors")) {
- // get path where looking for modules
- const Setting &connectors = config.lookup("connectors");
- auto count = connectors.getLength();
+ std::stringstream interest_sent;
+ interest_sent << stats.getInterestTx() -
+ saved_stats_.old_sent_int_value_
+ << std::setfill(separator);
- for (int i = 0; i < count; i++) {
- const Setting &connector = connectors[i];
- ConnectorConfig conn;
+ std::stringstream nacks;
+ nacks << stats.getReceivedNacks() -
+ saved_stats_.old_received_nacks_value_
+ << std::setfill(separator);
- conn.name = connector.getName();
- unsigned port = 0;
+ std::stringstream fec_pkt;
+ fec_pkt << stats.getReceivedFEC() - saved_stats_.old_fec_pkt_
+ << std::setfill(separator);
- if (!connector.lookupValue("local_address", conn.local_address)) {
- conn.local_address = "";
- }
+ std::stringstream queuing_delay;
+ queuing_delay << std::fixed << std::setprecision(3)
+ << stats.getQueuingDelay() << std::setfill(separator);
- if (!connector.lookupValue("local_port", port)) {
- port = 0;
- }
+ std::stringstream residual_losses;
+ double rl_perc = stats.getResidualLossRate() * 100;
+ residual_losses << std::fixed << std::setprecision(2) << rl_perc
+ << std::setfill(separator);
- conn.local_port = (uint16_t)(port);
+ std::stringstream quality_score;
+ quality_score << std::fixed << (int)stats.getQualityScore()
+ << std::setfill(separator);
- if (!connector.lookupValue("remote_address", conn.remote_address)) {
- std::cerr
- << "Error in configuration file: remote_address is a mandatory "
- "field of Connectors."
- << std::endl;
- return false;
+ std::stringstream alerts;
+ alerts << stats.getAlerts() << std::setfill(separator);
+
+ std::stringstream auth_alerts;
+ auth_alerts << saved_stats_.auth_alerts_ << std::setfill(separator);
+
+ if ((header_counter_ == 0 && configuration_.print_headers_) || first_) {
+ getOutputStream() << std::right << std::setw(width) << "Interval[ms]";
+ getOutputStream()
+ << std::right << std::setw(width) << "RecvData[pkt]";
+ getOutputStream()
+ << std::right << std::setw(width) << "Bandwidth[Mbps]";
+ getOutputStream()
+ << std::right << std::setw(width) << "Goodput[Mbps]";
+ getOutputStream() << std::right << std::setw(width) << "LossRate[%]";
+ getOutputStream() << std::right << std::setw(width) << "Retr[pkt]";
+ getOutputStream() << std::right << std::setw(width) << "InterestSent";
+ getOutputStream()
+ << std::right << std::setw(width) << "ReceivedNacks";
+ getOutputStream() << std::right << std::setw(width) << "SyncWnd[pkt]";
+ getOutputStream() << std::right << std::setw(width) << "MinRtt[ms]";
+ getOutputStream()
+ << std::right << std::setw(width) << "QueuingDelay[ms]";
+ getOutputStream()
+ << std::right << std::setw(width) << "LostData[pkt]";
+ getOutputStream()
+ << std::right << std::setw(width) << "RecoveredData";
+ getOutputStream()
+ << std::right << std::setw(width) << "DefinitelyLost";
+ getOutputStream() << std::right << std::setw(width) << "State";
+ getOutputStream()
+ << std::right << std::setw(width) << "DataDelay[ms]";
+ getOutputStream() << std::right << std::setw(width) << "FecPkt";
+ getOutputStream() << std::right << std::setw(width) << "Congestion";
+ getOutputStream()
+ << std::right << std::setw(width) << "ResidualLosses";
+ getOutputStream() << std::right << std::setw(width) << "QualityScore";
+ getOutputStream() << std::right << std::setw(width) << "Alerts";
+ getOutputStream()
+ << std::right << std::setw(width) << "AuthAlerts" << std::endl;
+
+ first_ = false;
}
- if (!connector.lookupValue("remote_port", port)) {
- std::cerr << "Error in configuration file: remote_port is a "
- "mandatory field of Connectors."
- << std::endl;
- return false;
+ getOutputStream() << std::right << std::setw(width)
+ << interval_ms.str();
+ getOutputStream() << std::right << std::setw(width)
+ << received_data_pkt.str();
+ getOutputStream() << std::right << std::setw(width) << bandwidth.str();
+ getOutputStream() << std::right << std::setw(width) << goodput.str();
+ getOutputStream() << std::right << std::setw(width) << loss_rate.str();
+ getOutputStream() << std::right << std::setw(width) << retx_sent.str();
+ getOutputStream() << std::right << std::setw(width)
+ << interest_sent.str();
+ getOutputStream() << std::right << std::setw(width) << nacks.str();
+ getOutputStream() << std::right << std::setw(width) << window.str();
+ getOutputStream() << std::right << std::setw(width) << avg_rtt.str();
+ getOutputStream() << std::right << std::setw(width)
+ << queuing_delay.str();
+ getOutputStream() << std::right << std::setw(width) << lost_data.str();
+ getOutputStream() << std::right << std::setw(width)
+ << bytes_recovered_data.str();
+ getOutputStream() << std::right << std::setw(width)
+ << definitely_lost_data.str();
+ getOutputStream() << std::right << std::setw(width)
+ << stats.getCCStatus();
+ getOutputStream() << std::right << std::setw(width) << data_delay.str();
+ getOutputStream() << std::right << std::setw(width) << fec_pkt.str();
+ getOutputStream() << std::right << std::setw(width)
+ << stats.isCongested();
+ getOutputStream() << std::right << std::setw(width)
+ << residual_losses.str();
+ getOutputStream() << std::right << std::setw(width)
+ << quality_score.str();
+ getOutputStream() << std::right << std::setw(width) << alerts.str();
+ getOutputStream() << std::right << std::setw(width) << auth_alerts.str()
+ << std::endl;
+
+ if (configuration_.test_mode_) {
+ if (saved_stats_.data_delays_.size() > 0)
+ saved_stats_.data_delays_.pop_back();
+
+ auto now = utils::SteadyTime::nowMs();
+ getOutputStream() << std::fixed << std::setprecision(0) << now.count()
+ << " DATA-DELAYS:[" << saved_stats_.data_delays_
+ << "]" << std::endl;
}
-
- if (!connector.lookupValue("interface", conn.interface)) {
- std::cerr << "Error in configuration file: interface is a "
- "mandatory field of Connectors."
- << std::endl;
- return false;
+ } else {
+ if ((header_counter_ == 0 && configuration_.print_headers_) || first_) {
+ getOutputStream() << std::right << std::setw(width) << "Interval[ms]";
+ getOutputStream() << std::right << std::setw(width) << "Transfer[MB]";
+ getOutputStream()
+ << std::right << std::setw(width) << "Bandwidth[Mbps]";
+ getOutputStream() << std::right << std::setw(width) << "Retr[pkt]";
+ getOutputStream() << std::right << std::setw(width) << "Cwnd[Int]";
+ getOutputStream()
+ << std::right << std::setw(width) << "AvgRtt[ms]" << std::endl;
+
+ first_ = false;
}
- conn.remote_port = (uint16_t)(port);
-
- std::cout << "Adding connector " << conn.name << ", ("
- << conn.local_address << ":" << conn.local_port << " "
- << conn.remote_address << ":" << conn.remote_port << ")"
- << std::endl;
- config_.addConnector(conn.name, std::move(conn));
+ getOutputStream() << std::right << std::setw(width)
+ << interval_ms.str();
+ getOutputStream() << std::right << std::setw(width)
+ << bytes_transferred.str();
+ getOutputStream() << std::right << std::setw(width) << bandwidth.str();
+ getOutputStream() << std::right << std::setw(width)
+ << stats.getRetxCount();
+ getOutputStream() << std::right << std::setw(width) << window.str();
+ getOutputStream() << std::right << std::setw(width) << avg_rtt.str()
+ << std::endl;
}
- }
- // Routes
- if (config.exists("routes")) {
- const Setting &routes = 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("main_connector", r.main_connector);
- route.lookupValue("backup_connector", r.backup_connector);
- r.weight = (uint16_t)(weight);
-
- std::cout << "Adding route " << r.name << " " << r.prefix << " ("
- << r.main_connector << " " << r.backup_connector << " "
- << r.weight << ")" << std::endl;
- config_.addRoute(std::move(r));
+ saved_stats_.total_duration_milliseconds_ +=
+ (uint32_t)exact_duration.count();
+ saved_stats_.old_bytes_value_ = stats.getBytesRecv();
+ saved_stats_.old_lost_data_value_ = stats.getLostData();
+ saved_stats_.old_bytes_recovered_value_ = stats.getBytesRecoveredData();
+ saved_stats_.old_definitely_lost_data_value_ =
+ stats.getDefinitelyLostData();
+ saved_stats_.old_fec_interest_tx_value_ = stats.getInterestFecTxCount();
+ saved_stats_.old_fec_data_rx_value_ = stats.getBytesFecRecv();
+ saved_stats_.old_retx_value_ = stats.getRetxCount();
+ saved_stats_.old_sent_int_value_ = stats.getInterestTx();
+ saved_stats_.old_received_nacks_value_ = stats.getReceivedNacks();
+ saved_stats_.old_fec_pkt_ = stats.getReceivedFEC();
+ saved_stats_.delay_sample_ = 0;
+ saved_stats_.avg_data_delay_ = 0;
+ saved_stats_.received_bytes_ = 0;
+ saved_stats_.received_data_pkt_ = 0;
+ saved_stats_.data_delays_ = "";
+ saved_stats_.t_stats_ = utils::SteadyTime::Clock::now();
+
+ header_counter_ = (header_counter_ + 1) & kheader_counter_mask();
+
+ if (--nb_iterations_ == 0) {
+ // We reached the maximum nb of runs. Stop now.
+ parent_.io_service_.stop();
}
}
- std::cout << "Ok" << std::endl;
+ /***************************************************************
+ * Setup functions
+ ***************************************************************/
- return true;
- }
+ int setupRTCSocket() {
+ int ret = ERROR_SUCCESS;
- bool splitRoute(std::string route, std::string &prefix,
- uint8_t &prefix_length) {
- std::string delimiter = "/";
-
- size_t pos = 0;
- if ((pos = route.find(delimiter)) != std::string::npos) {
- prefix = route.substr(0, pos);
- route.erase(0, pos + delimiter.length());
- } else {
- return false;
- }
+ configuration_.transport_protocol_ = RTC;
- prefix_length = std::stoul(route.substr(0));
- return true;
- }
+ if (configuration_.relay_ && configuration_.parallel_flows_ == 1) {
+ int production_protocol = ProductionProtocolAlgorithms::RTC_PROD;
+ producer_socket_ =
+ std::make_unique<ProducerSocket>(production_protocol);
+ producer_socket_->registerPrefix(configuration_.relay_name_);
+ producer_socket_->connect();
+ producer_socket_->start();
+ }
- void onHicnServiceReady() override {
- std::cout << "Successfully connected to local forwarder!" << std::endl;
+ if (configuration_.output_stream_mode_ &&
+ configuration_.parallel_flows_ == 1) {
+ remote_ = asio::ip::udp::endpoint(
+ asio::ip::address::from_string("127.0.0.1"), configuration_.port_);
+ socket_.open(asio::ip::udp::v4());
+ }
- std::cout << "Setting up listeners" << std::endl;
- const char *config = getenv("FORWARDER_CONFIG");
+ consumer_socket_ =
+ std::make_unique<ConsumerSocket>(configuration_.transport_protocol_);
- if (config) {
- if (!parseConfig(config)) {
- return;
+ RtcTransportRecoveryStrategies recovery_strategy =
+ RtcTransportRecoveryStrategies::RTX_ONLY;
+ switch (configuration_.recovery_strategy_) {
+ case 1:
+ recovery_strategy = RtcTransportRecoveryStrategies::RECOVERY_OFF;
+ break;
+ case 2:
+ recovery_strategy = RtcTransportRecoveryStrategies::RTX_ONLY;
+ break;
+ case 3:
+ recovery_strategy = RtcTransportRecoveryStrategies::FEC_ONLY;
+ break;
+ case 4:
+ recovery_strategy = RtcTransportRecoveryStrategies::DELAY_BASED;
+ break;
+ case 5:
+ recovery_strategy = RtcTransportRecoveryStrategies::LOW_RATE;
+ break;
+ case 6:
+ recovery_strategy =
+ RtcTransportRecoveryStrategies::LOW_RATE_AND_BESTPATH;
+ break;
+ case 7:
+ recovery_strategy =
+ RtcTransportRecoveryStrategies::LOW_RATE_AND_REPLICATION;
+ break;
+ case 8:
+ recovery_strategy =
+ RtcTransportRecoveryStrategies::LOW_RATE_AND_ALL_FWD_STRATEGIES;
+ break;
+ case 9:
+ recovery_strategy =
+ RtcTransportRecoveryStrategies::FEC_ONLY_LOW_RES_LOSSES;
+ break;
+ case 10:
+ recovery_strategy =
+ RtcTransportRecoveryStrategies::DELAY_AND_BESTPATH;
+ break;
+ case 11:
+ recovery_strategy =
+ RtcTransportRecoveryStrategies::DELAY_AND_REPLICATION;
+ break;
+ default:
+ break;
}
- // Create faces and route using first face in the list.
- auto &routes = config_.getRoutes();
- auto &connectors = config_.getConnectors();
+ ret = consumer_socket_->setSocketOption(
+ RtcTransportOptions::RECOVERY_STRATEGY,
+ static_cast<uint32_t>(recovery_strategy));
- if (routes.size() == 0 || connectors.size() == 0) {
- std::cerr << "Nothing to configure" << std::endl;
- return;
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
}
- for (auto &route : routes) {
- auto the_connector_it = connectors.find(route.main_connector);
- if (the_connector_it == connectors.end()) {
- std::cerr << "No valid main connector found for route " << route.name
- << std::endl;
- continue;
- }
-
- auto &the_connector = the_connector_it->second;
- auto route_info = std::make_shared<ForwarderInterface::RouteInfo>();
- route_info->family = AF_INET;
- route_info->local_addr = the_connector.local_address;
- route_info->local_port = the_connector.local_port;
- route_info->remote_addr = the_connector.remote_address;
- route_info->remote_port = the_connector.remote_port;
- route_info->interface = the_connector.interface;
- route_info->name = the_connector.name;
-
- std::string prefix;
- uint8_t prefix_length;
- auto ret = splitRoute(route.prefix, prefix, prefix_length);
-
- if (!ret) {
- std::cerr << "Error parsing route" << std::endl;
- return;
- }
+ ret = consumer_socket_->setSocketOption(
+ RtcTransportOptions::AGGREGATED_DATA,
+ configuration_.aggregated_data_);
- route_info->route_addr = prefix;
- route_info->route_len = prefix_length;
-
- main_routes_.emplace_back(route_info);
-
- if (!route.backup_connector.empty()) {
- // Add also the backup route
- auto the_backup_connector_it =
- connectors.find(route.backup_connector);
- if (the_backup_connector_it == connectors.end()) {
- std::cerr << "No valid backup connector found for route "
- << route.name << std::endl;
- continue;
- }
-
- auto &the_backup_connector = the_backup_connector_it->second;
- auto backup_route_info =
- std::make_shared<ForwarderInterface::RouteInfo>();
- backup_route_info->family = AF_INET;
- backup_route_info->local_addr = the_backup_connector.local_address;
- backup_route_info->local_port = the_backup_connector.local_port;
- backup_route_info->remote_addr = the_backup_connector.remote_address;
- backup_route_info->remote_port = the_backup_connector.remote_port;
- backup_route_info->interface = the_backup_connector.interface;
- backup_route_info->name = the_backup_connector.name;
-
- std::string prefix;
- uint8_t prefix_length;
- auto ret = splitRoute(route.prefix, prefix, prefix_length);
-
- if (!ret) {
- std::cerr << "Error parsing route" << std::endl;
- return;
- }
-
- backup_route_info->route_addr = prefix;
- backup_route_info->route_len = prefix_length;
-
- backup_routes_.emplace_back(backup_route_info);
- }
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
}
- // Create main routes
- std::cout << "Creating main routes" << std::endl;
- forwarder_interface_.createFaceAndRoutes(main_routes_);
- }
- }
+ ret = consumer_socket_->setSocketOption(
+ RtcTransportOptions::CONTENT_SHARING_MODE,
+ configuration_.content_sharing_mode_);
- void onRouteConfigured(
- std::vector<ForwarderInterface::RouteInfoPtr> &route_info) override {
- std::cout << "Routes successfully configured!" << std::endl;
- }
-#endif
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
- transport::auth::VerificationPolicy onAuthFailed(
- transport::auth::Suffix suffix,
- transport::auth::VerificationPolicy policy) {
- auth_alerts_++;
- return transport::auth::VerificationPolicy::ACCEPT;
- }
+ ret = consumer_socket_->setSocketOption(
+ ConsumerCallbacksOptions::CONTENT_OBJECT_INPUT,
+ (ConsumerContentObjectCallback)std::bind(
+ &Impl::ConsumerContext::checkReceivedRtcContent, this,
+ std::placeholders::_1, std::placeholders::_2));
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
- int setup() {
- int ret;
+ std::shared_ptr<TransportStatistics> transport_stats;
+ ret = consumer_socket_->getSocketOption(
+ OtherOptions::STATISTICS, (TransportStatistics **)&transport_stats);
+ transport_stats->setAlpha(0.0);
- if (configuration_.rtc_) {
- configuration_.transport_protocol_ = RTC;
- } else if (configuration_.window < 0) {
- configuration_.transport_protocol_ = RAAQM;
- } else {
- configuration_.transport_protocol_ = CBR;
- }
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
- if (configuration_.relay_ && configuration_.rtc_) {
- int production_protocol = ProductionProtocolAlgorithms::RTC_PROD;
- producer_socket_ = std::make_unique<ProducerSocket>(production_protocol);
- producer_socket_->registerPrefix(configuration_.relay_name_);
- producer_socket_->connect();
- producer_socket_->start();
+ return ERROR_SUCCESS;
}
- if (configuration_.output_stream_mode_ && configuration_.rtc_) {
- remote_ = asio::ip::udp::endpoint(
- asio::ip::address::from_string("127.0.0.1"), configuration_.port_);
- socket_.open(asio::ip::udp::v4());
- }
+ int setupRAAQMSocket() {
+ int ret = ERROR_SUCCESS;
+
+ configuration_.transport_protocol_ = RAAQM;
- if (configuration_.secure_) {
- consumer_socket_ = std::make_unique<P2PSecureConsumerSocket>(
- RAAQM, configuration_.transport_protocol_);
- if (configuration_.producer_prefix_.getPrefixLength() == 0) {
- std::cerr << "ERROR -- Missing producer prefix on which perform the "
- "handshake."
- << std::endl;
- } else {
- P2PSecureConsumerSocket &secure_consumer_socket =
- *(static_cast<P2PSecureConsumerSocket *>(consumer_socket_.get()));
- secure_consumer_socket.registerPrefix(configuration_.producer_prefix_);
- }
- } else {
consumer_socket_ =
std::make_unique<ConsumerSocket>(configuration_.transport_protocol_);
- }
- consumer_socket_->setSocketOption(
- GeneralTransportOptions::INTEREST_LIFETIME,
- configuration_.interest_lifetime_);
-
- consumer_socket_->setSocketOption(
- GeneralTransportOptions::UNVERIFIED_INTERVAL,
- configuration_.unverified_interval_);
-
- consumer_socket_->setSocketOption(GeneralTransportOptions::UNVERIFIED_RATIO,
- configuration_.unverified_ratio_);
-
- if (consumer_socket_->setSocketOption(
- GeneralTransportOptions::PACKET_FORMAT,
- configuration_.packet_format_) == SOCKET_OPTION_NOT_SET) {
- std::cerr << "ERROR -- Impossible to set the packet format." << std::endl;
- return ERROR_SETUP;
- }
-
-#if defined(DEBUG) && defined(__linux__)
- std::shared_ptr<transport::BasePortal> portal;
- consumer_socket_->getSocketOption(GeneralTransportOptions::PORTAL, portal);
- signals_ =
- std::make_unique<asio::signal_set>(portal->getIoService(), SIGUSR1);
- signals_->async_wait([this](const std::error_code &, const int &) {
- std::cout << "Signal SIGUSR1!" << std::endl;
- mtrace();
- });
-
- ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::FWD_STRATEGY_CHANGE,
- [this](notification::Strategy strategy) {
- std::cout << "Forwarder strategy callback" << std::endl;
- });
- if (ret == SOCKET_OPTION_NOT_SET) return ERROR_SETUP;
-
- ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::REC_STRATEGY_CHANGE,
- [this](notification::Strategy strategy) {
- std::cout << "Recovery strategy callback" << std::endl;
- });
- if (ret == SOCKET_OPTION_NOT_SET) return ERROR_SETUP;
-#endif
-
- if (consumer_socket_->setSocketOption(CURRENT_WINDOW_SIZE,
- configuration_.window) ==
- SOCKET_OPTION_NOT_SET) {
- std::cerr << "ERROR -- Impossible to set the size of the window."
- << std::endl;
- return ERROR_SETUP;
- }
-
- if (configuration_.transport_protocol_ == RAAQM &&
- configuration_.beta != -1.f) {
- if (consumer_socket_->setSocketOption(RaaqmTransportOptions::BETA_VALUE,
- configuration_.beta) ==
- SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
+ if (configuration_.beta_ != -1.f) {
+ ret = consumer_socket_->setSocketOption(
+ RaaqmTransportOptions::BETA_VALUE, configuration_.beta_);
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
}
- }
- if (configuration_.transport_protocol_ == RAAQM &&
- configuration_.drop_factor != -1.f) {
- if (consumer_socket_->setSocketOption(RaaqmTransportOptions::DROP_FACTOR,
- configuration_.drop_factor) ==
- SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
+ if (configuration_.drop_factor_ != -1.f) {
+ ret = consumer_socket_->setSocketOption(
+ RaaqmTransportOptions::DROP_FACTOR, configuration_.drop_factor_);
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
}
- }
-
- std::shared_ptr<Verifier> verifier = std::make_shared<VoidVerifier>();
- if (!configuration_.producer_certificate.empty()) {
- verifier = std::make_shared<AsymmetricVerifier>(
- configuration_.producer_certificate);
+ return ERROR_SUCCESS;
}
- if (!configuration_.passphrase.empty()) {
- verifier = std::make_shared<SymmetricVerifier>(configuration_.passphrase);
- }
+ int setupCBRSocket() {
+ configuration_.transport_protocol_ = CBR;
- verifier->setVerificationFailedCallback(
- std::bind(&HIperfClient::Impl::onAuthFailed, this,
- std::placeholders::_1, std::placeholders::_2));
+ consumer_socket_ =
+ std::make_unique<ConsumerSocket>(configuration_.transport_protocol_);
- if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
- verifier) == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
+ return ERROR_SUCCESS;
}
- ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::INTEREST_OUTPUT,
- (ConsumerInterestCallback)std::bind(&Impl::processLeavingInterest, this,
- std::placeholders::_1,
- std::placeholders::_2));
+ public:
+ int setup() {
+ int ret;
+ std::shared_ptr<Verifier> verifier = std::make_shared<VoidVerifier>();
+
+ if (configuration_.rtc_) {
+ ret = setupRTCSocket();
+ } else if (configuration_.window_ < 0) {
+ ret = setupRAAQMSocket();
+ } else {
+ ret = setupCBRSocket();
+ }
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
+ if (ret != ERROR_SUCCESS) {
+ return ret;
+ }
- if (!configuration_.rtc_) {
ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::READ_CALLBACK, &callback_);
- } else {
- ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::READ_CALLBACK, &rtc_callback_);
- }
-
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
-
- if (configuration_.rtc_) {
- if (configuration_.recovery_strategy_ == 1) { // unreliable
- ret = consumer_socket_->setSocketOption(
- RtcTransportOptions::RECOVERY_STRATEGY,
- (uint32_t)RtcTransportRecoveryStrategies::RECOVERY_OFF);
- } else if (configuration_.recovery_strategy_ == 2) { // rtx only
- ret = consumer_socket_->setSocketOption(
- RtcTransportOptions::RECOVERY_STRATEGY,
- (uint32_t)RtcTransportRecoveryStrategies::RTX_ONLY);
- } else if (configuration_.recovery_strategy_ == 3) { // fec only
- ret = consumer_socket_->setSocketOption(
- RtcTransportOptions::RECOVERY_STRATEGY,
- (uint32_t)RtcTransportRecoveryStrategies::FEC_ONLY);
- } else if (configuration_.recovery_strategy_ == 4) { // delay based
- ret = consumer_socket_->setSocketOption(
- RtcTransportOptions::RECOVERY_STRATEGY,
- (uint32_t)RtcTransportRecoveryStrategies::DELAY_BASED);
- } else if (configuration_.recovery_strategy_ == 5) { // low rate flow
- ret = consumer_socket_->setSocketOption(
- RtcTransportOptions::RECOVERY_STRATEGY,
- (uint32_t)RtcTransportRecoveryStrategies::LOW_RATE);
- } else if (configuration_.recovery_strategy_ ==
- 6) { // low rate + bestpath
- ret = consumer_socket_->setSocketOption(
- RtcTransportOptions::RECOVERY_STRATEGY,
- (uint32_t)RtcTransportRecoveryStrategies::LOW_RATE_AND_BESTPATH);
- } else if (configuration_.recovery_strategy_ ==
- 7) { // low rate + replication
- ret = consumer_socket_->setSocketOption(
- RtcTransportOptions::RECOVERY_STRATEGY,
- (uint32_t)RtcTransportRecoveryStrategies::LOW_RATE_AND_REPLICATION);
- } else if (configuration_.recovery_strategy_ ==
- 8) { // low rate + bestpath or replication
- ret = consumer_socket_->setSocketOption(
- RtcTransportOptions::RECOVERY_STRATEGY,
- (uint32_t)RtcTransportRecoveryStrategies::
- LOW_RATE_AND_ALL_FWD_STRATEGIES);
- } else {
- // default
- ret = consumer_socket_->setSocketOption(
- RtcTransportOptions::RECOVERY_STRATEGY,
- (uint32_t)RtcTransportRecoveryStrategies::RTX_ONLY);
+ GeneralTransportOptions::INTEREST_LIFETIME,
+ configuration_.interest_lifetime_);
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
}
+ ret = consumer_socket_->setSocketOption(
+ GeneralTransportOptions::MANIFEST_FACTOR_RELEVANT,
+ configuration_.manifest_factor_relevant_);
if (ret == SOCKET_OPTION_NOT_SET) {
return ERROR_SETUP;
}
- }
- if (configuration_.rtc_) {
ret = consumer_socket_->setSocketOption(
- RtcTransportOptions::AGGREGATED_DATA,
- configuration_.aggregated_data_);
+ GeneralTransportOptions::MANIFEST_FACTOR_ALERT,
+ configuration_.manifest_factor_alert_);
if (ret == SOCKET_OPTION_NOT_SET) {
return ERROR_SETUP;
}
- }
- if (configuration_.rtc_) {
ret = consumer_socket_->setSocketOption(
- ConsumerCallbacksOptions::CONTENT_OBJECT_INPUT,
- (ConsumerContentObjectCallback)std::bind(
- &Impl::checkReceivedRtcContent, this, std::placeholders::_1,
- std::placeholders::_2));
+ GeneralTransportOptions::PACKET_FORMAT,
+ configuration_.packet_format_);
if (ret == SOCKET_OPTION_NOT_SET) {
+ getOutputStream() << "ERROR -- Impossible to set the packet format."
+ << std::endl;
return ERROR_SETUP;
}
- }
-
- 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(&Impl::handleTimerExpiration, this,
- std::placeholders::_1,
- std::placeholders::_2));
-
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
-
- if (consumer_socket_->setSocketOption(
- GeneralTransportOptions::STATS_INTERVAL,
- configuration_.report_interval_milliseconds_) ==
- SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
-
- consumer_socket_->connect();
- return ERROR_SUCCESS;
- }
+ ret = consumer_socket_->setSocketOption(
+ ConsumerCallbacksOptions::FWD_STRATEGY_CHANGE,
+ (StrategyCallback)[](
+ [[maybe_unused]] notification::Strategy strategy){
+ // nothing to do
+ });
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
- int run() {
- std::cout << "Starting download of " << configuration_.name << std::endl;
+ ret = consumer_socket_->setSocketOption(
+ ConsumerCallbacksOptions::REC_STRATEGY_CHANGE,
+ (StrategyCallback)[](
+ [[maybe_unused]] notification::Strategy strategy){
+ // nothing to do
+ });
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
- signals_.add(SIGINT);
- signals_.async_wait(
- [this](const std::error_code &, const int &) { io_service_.stop(); });
+ ret = consumer_socket_->setSocketOption(CURRENT_WINDOW_SIZE,
+ configuration_.window_);
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ getOutputStream()
+ << "ERROR -- Impossible to set the size of the window."
+ << std::endl;
+ return ERROR_SETUP;
+ }
- t_download_ = t_stats_ = utils::SteadyTime::now();
- consumer_socket_->consume(configuration_.name);
+ if (!configuration_.producer_certificate_.empty()) {
+ verifier = std::make_shared<AsymmetricVerifier>(
+ configuration_.producer_certificate_);
+ }
- io_service_.run();
- consumer_socket_->stop();
+ if (!configuration_.passphrase_.empty()) {
+ verifier =
+ std::make_shared<SymmetricVerifier>(configuration_.passphrase_);
+ }
- return ERROR_SUCCESS;
- }
+ verifier->setVerificationFailedCallback(
+ std::bind(&HIperfClient::Impl::ConsumerContext::onAuthFailed, this,
+ std::placeholders::_1, std::placeholders::_2));
- private:
- class RTCCallback : public ConsumerSocket::ReadCallback {
- static constexpr std::size_t mtu = HIPERF_MTU;
+ ret = consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
+ verifier);
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
- public:
- RTCCallback(Impl &hiperf_client) : client_(hiperf_client) {
- client_.configuration_.receive_buffer = utils::MemBuf::create(mtu);
- Packet::Format format =
- PayloadSize::getFormatFromName(client_.configuration_.name, false);
- payload_size_max_ =
- PayloadSize(format).getPayloadSizeMax(RTC_HEADER_SIZE);
- }
+ // Signer for aggregatd interests
+ std::shared_ptr<Signer> signer = std::make_shared<VoidSigner>();
+ if (!configuration_.aggr_interest_passphrase_.empty()) {
+ signer = std::make_shared<SymmetricSigner>(
+ CryptoSuite::HMAC_SHA256, configuration_.aggr_interest_passphrase_);
+ }
+ ret = consumer_socket_->setSocketOption(GeneralTransportOptions::SIGNER,
+ signer);
+ if (ret == SOCKET_OPTION_NOT_SET) return ERROR_SETUP;
- bool isBufferMovable() noexcept override { return false; }
+ if (configuration_.aggregated_interests_) {
+ ret = consumer_socket_->setSocketOption(
+ RtcTransportOptions::AGGREGATED_INTERESTS, true);
- void getReadBuffer(uint8_t **application_buffer,
- size_t *max_length) override {
- *application_buffer =
- client_.configuration_.receive_buffer->writableData();
- *max_length = mtu;
- }
+ if (ret == SOCKET_OPTION_NOT_SET) return ERROR_SETUP;
+ }
- void readDataAvailable(std::size_t length) noexcept override {
- client_.received_bytes_ += length;
- client_.received_data_pkt_++;
+ ret = consumer_socket_->setSocketOption(
+ ConsumerCallbacksOptions::INTEREST_OUTPUT,
+ (ConsumerInterestCallback)std::bind(
+ &ConsumerContext::processLeavingInterest, this,
+ std::placeholders::_1, std::placeholders::_2));
- // collecting delay stats. Just for performance testing
- uint64_t *senderTimeStamp =
- (uint64_t *)client_.configuration_.receive_buffer->writableData();
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
- auto now = utils::SystemTime::nowMs().count();
- double new_delay = (double)(now - *senderTimeStamp);
+ ret = consumer_socket_->setSocketOption(
+ ConsumerCallbacksOptions::READ_CALLBACK, this);
- if (*senderTimeStamp > now)
- new_delay = -1 * (double)(*senderTimeStamp - now);
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
- client_.delay_sample_++;
- client_.avg_data_delay_ =
- client_.avg_data_delay_ +
- (new_delay - client_.avg_data_delay_) / client_.delay_sample_;
+ ret = consumer_socket_->setSocketOption(
+ ConsumerCallbacksOptions::STATS_SUMMARY,
+ (ConsumerTimerCallback)std::bind(
+ &Impl::ConsumerContext::handleTimerExpiration, this,
+ std::placeholders::_1, std::placeholders::_2));
- if (client_.configuration_.test_mode_) {
- client_.data_delays_ += std::to_string(int(new_delay));
- client_.data_delays_ += ",";
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
}
- if (client_.configuration_.relay_) {
- client_.producer_socket_->produceDatagram(
- client_.configuration_.relay_name_.getName(),
- client_.configuration_.receive_buffer->writableData(),
- length < payload_size_max_ ? length : payload_size_max_);
- }
- if (client_.configuration_.output_stream_mode_) {
- uint8_t *start =
- (uint8_t *)client_.configuration_.receive_buffer->writableData();
- start += sizeof(uint64_t);
- std::size_t pkt_len = length - sizeof(uint64_t);
- client_.socket_.send_to(asio::buffer(start, pkt_len), client_.remote_);
+ if (consumer_socket_->setSocketOption(
+ GeneralTransportOptions::STATS_INTERVAL,
+ configuration_.report_interval_milliseconds_) ==
+ SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
}
- }
- size_t maxBufferSize() const override { return mtu; }
+ consumer_socket_->connect();
- void readError(const std::error_code &ec) noexcept override {
- std::cerr << "Error while reading from RTC socket" << std::endl;
- client_.io_service_.stop();
+ return ERROR_SUCCESS;
}
- void readSuccess(std::size_t total_size) noexcept override {
- std::cout << "Data successfully read" << std::endl;
+ /***************************************************************
+ * Run functions
+ ***************************************************************/
+
+ int run() {
+ getOutputStream() << "Starting download of " << flow_name_ << std::endl;
+
+ saved_stats_.t_download_ = saved_stats_.t_stats_ =
+ utils::SteadyTime::now();
+ consumer_socket_->consume(flow_name_);
+
+ return ERROR_SUCCESS;
}
- private:
- Impl &client_;
+ // Members initialized by the constructor
+ std::shared_ptr<utils::MemBuf> receive_buffer_;
+ asio::ip::udp::socket socket_;
std::size_t payload_size_max_;
+ asio::ip::udp::endpoint remote_;
+ std::uint32_t nb_iterations_;
+
+ // Members initialized by in-class initializer
+ SavedStatistics saved_stats_{};
+ uint16_t header_counter_{0};
+ bool first_{true};
+ std::unique_ptr<ConsumerSocket> consumer_socket_;
+ std::unique_ptr<ProducerSocket> producer_socket_;
};
- class Callback : public ConsumerSocket::ReadCallback {
- public:
- Callback(Impl &hiperf_client) : client_(hiperf_client) {
- client_.configuration_.receive_buffer =
- utils::MemBuf::create(client_.configuration_.receive_buffer_size_);
- }
+ public:
+ explicit Impl(const hiperf::ClientConfiguration &conf)
+ : config_(conf), signals_(io_service_) {}
- bool isBufferMovable() noexcept override { return false; }
+ virtual ~Impl() = default;
- void getReadBuffer(uint8_t **application_buffer,
- size_t *max_length) override {
- *application_buffer =
- client_.configuration_.receive_buffer->writableData();
- *max_length = client_.configuration_.receive_buffer_size_;
+ int setup() {
+ int ret = ensureFlows(config_.name_, config_.parallel_flows_);
+ if (ret != ERROR_SUCCESS) {
+ return ret;
}
- void readDataAvailable(std::size_t length) noexcept override {}
-
- void readBufferAvailable(
- std::unique_ptr<utils::MemBuf> &&buffer) noexcept override {}
+ consumer_contexts_.reserve(config_.parallel_flows_);
+ for (uint32_t i = 0; i < config_.parallel_flows_; i++) {
+ auto &ctx = consumer_contexts_.emplace_back(*this, i);
+ ret = ctx.setup();
- size_t maxBufferSize() const override {
- return client_.configuration_.receive_buffer_size_;
- }
-
- void readError(const std::error_code &ec) noexcept override {
- std::cerr << "Error " << ec.message() << " while reading from socket"
- << std::endl;
- client_.io_service_.stop();
+ if (ret) {
+ break;
+ }
}
- void readSuccess(std::size_t total_size) noexcept override {
- auto t2 = utils::SteadyTime::now();
- auto dt = utils::SteadyTime::getDurationUs(client_.t_download_, t2);
- long usec = (long)dt.count();
-
- std::cout << "Content retrieved. Size: " << total_size << " [Bytes]"
- << std::endl;
+ return ret;
+ }
- std::cerr << "Elapsed Time: " << usec / 1000000.0 << " seconds -- "
- << (total_size * 8) * 1.0 / usec * 1.0 << " [Mbps]"
- << std::endl;
+ int run() {
+ signals_.add(SIGINT);
+ signals_.async_wait(
+ [this](const std::error_code &, const int &) { io_service_.stop(); });
- client_.io_service_.stop();
+ for (auto &consumer_context : consumer_contexts_) {
+ consumer_context.run();
}
- private:
- Impl &client_;
- };
+ io_service_.run();
- hiperf::ClientConfiguration configuration_;
- utils::SteadyTime::TimePoint t_stats_;
- utils::SteadyTime::TimePoint 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_;
- uint64_t old_definitely_lost_data_value_;
- uint32_t old_retx_value_;
- uint32_t old_sent_int_value_;
- uint32_t old_received_nacks_value_;
- uint32_t old_fec_pkt_;
-
- // 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_;
- uint32_t auth_alerts_;
-
- std::string data_delays_;
+ return ERROR_SUCCESS;
+ }
+ ClientConfiguration &getConfig() { return config_; }
+
+ private:
asio::io_service io_service_;
+ hiperf::ClientConfiguration config_;
asio::signal_set signals_;
- RTCCallback rtc_callback_;
- Callback callback_;
- std::unique_ptr<ConsumerSocket> consumer_socket_;
- std::unique_ptr<ProducerSocket> producer_socket_;
- asio::ip::udp::socket socket_;
- asio::ip::udp::endpoint remote_;
-
- ForwarderConfiguration config_;
- // uint16_t switch_threshold_; /* ms */
- bool fwd_connected_;
- bool use_bestpath_;
- uint32_t rtt_threshold_; /* ms */
- uint32_t loss_threshold_; /* ms */
- std::string prefix_name_; // bestpath route
- uint32_t prefix_len_;
- // bool done_;
-
- std::vector<ForwarderInterface::RouteInfoPtr> main_routes_;
- std::vector<ForwarderInterface::RouteInfoPtr> backup_routes_;
- uint16_t header_counter_mask_;
- uint16_t header_counter_;
-
- bool print_headers_;
- bool first_;
-
- ForwarderInterface forwarder_interface_;
+ std::vector<ConsumerContext> consumer_contexts_;
};
-HIperfClient::HIperfClient(const ClientConfiguration &conf) {
- impl_ = new Impl(conf);
-}
-
-HIperfClient::HIperfClient(HIperfClient &&other) {
- impl_ = other.impl_;
- other.impl_ = nullptr;
-}
-
-HIperfClient &HIperfClient::operator=(HIperfClient &&other) {
- if (this != &other) {
- impl_ = other.impl_;
- other.impl_ = nullptr;
- }
-
- return *this;
-}
+HIperfClient::HIperfClient(const ClientConfiguration &conf)
+ : impl_(std::make_unique<Impl>(conf)) {}
-HIperfClient::~HIperfClient() { delete impl_; }
+HIperfClient::~HIperfClient() = default;
-int HIperfClient::setup() { return impl_->setup(); }
+int HIperfClient::setup() const { return impl_->setup(); }
-void HIperfClient::run() { impl_->run(); }
+void HIperfClient::run() const { impl_->run(); }
} // namespace hiperf
diff --git a/apps/hiperf/src/client.h b/apps/hiperf/src/client.h
index bc80c874c..c4c6bc2ae 100644
--- a/apps/hiperf/src/client.h
+++ b/apps/hiperf/src/client.h
@@ -20,19 +20,17 @@
namespace hiperf {
-class HIperfClient : ::utils::NonCopyable {
+class HIperfClient : private ::utils::NonCopyable {
public:
- HIperfClient(const ClientConfiguration &conf);
- HIperfClient(HIperfClient &&other);
- HIperfClient &operator=(HIperfClient &&other);
+ explicit HIperfClient(const ClientConfiguration &conf);
~HIperfClient();
- int setup();
- void run();
+ int setup() const;
+ void run() const;
private:
class Impl;
- Impl *impl_;
+ std::unique_ptr<Impl> impl_;
};
} // namespace hiperf \ No newline at end of file
diff --git a/apps/hiperf/src/common.h b/apps/hiperf/src/common.h
index 3a90f3732..5143afe31 100644
--- a/apps/hiperf/src/common.h
+++ b/apps/hiperf/src/common.h
@@ -15,17 +15,15 @@
#pragma once
-#include <forwarder_interface.h>
#include <hicn/transport/auth/signer.h>
#include <hicn/transport/config.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.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/utils/chrono_typedefs.h>
+#include <hicn/transport/utils/color.h>
#include <hicn/transport/utils/literals.h>
#ifndef _WIN32
@@ -36,6 +34,7 @@
#include <cmath>
#include <fstream>
#include <iomanip>
+#include <iostream>
#include <sstream>
#include <string>
#include <unordered_set>
@@ -53,27 +52,112 @@ using namespace transport::interface;
using namespace transport::auth;
using namespace transport::core;
-static inline uint64_t _ntohll(const uint64_t *input) {
- uint64_t return_val;
- uint8_t *tmp = (uint8_t *)&return_val;
+namespace hiperf {
- tmp[0] = *input >> 56;
- tmp[1] = *input >> 48;
- tmp[2] = *input >> 40;
- tmp[3] = *input >> 32;
- tmp[4] = *input >> 24;
- tmp[5] = *input >> 16;
- tmp[6] = *input >> 8;
- tmp[7] = *input >> 0;
+/**
+ * Logger
+ */
+static std::ostream &Logger() { return std::cout; }
- return return_val;
-}
+template <typename D, typename ConfType, typename ParentType>
+class Base : protected std::stringbuf, protected std::ostream {
+ protected:
+ static inline const char separator[] = "| ";
-static inline uint64_t _htonll(const uint64_t *input) {
- return (_ntohll(input));
-}
+ Base(ParentType &parent, asio::io_service &io_service, int identifier)
+ : std::stringbuf(),
+ std::ostream(this),
+ parent_(parent),
+ configuration_(parent_.getConfig()),
+ io_service_(io_service),
+ identifier_(identifier),
+ name_id_(D::getContextType() + std::to_string(identifier_)),
+ flow_name_(configuration_.name_.makeNameWithIndex(identifier_)) {
+ std::stringstream begin;
+ std::stringstream end;
+ if (configuration_.colored_) {
+ begin << color_mod_ << bold_mod_;
+ end << end_mod_;
+ } else {
+ begin << "";
+ end << "";
+ }
-namespace hiperf {
+ begin << "|" << name_id_ << separator;
+ begin_ = begin.str();
+ end_ = end.str();
+ }
+
+ Base(Base &&other)
+ : parent_(other.parent_),
+ configuration_(other.configuration_),
+ io_service_(other.io_service_),
+ identifier_(other.identifier_),
+ name_id_(std::move(other.name_id_)),
+ flow_name_(other.flow_name_) {}
+
+ /***************************************************************
+ * std::stringbuf sync override
+ ***************************************************************/
+
+ int sync() override {
+ auto string = str();
+ asio::post(io_service_,
+ [this, string]() { Logger() << begin_ << string << end_; });
+ str("");
+
+ return 0;
+ }
+
+ std::ostream &getOutputStream() { return *this; }
+
+ // Members initialized by the constructor
+ ParentType &parent_;
+ ConfType &configuration_;
+ asio::io_service &io_service_;
+ int identifier_;
+ std::string name_id_;
+ transport::core::Name flow_name_;
+ std::string begin_;
+ std::string end_;
+
+ // Members initialized by the in-class initializer
+ utils::ColorModifier color_mod_;
+ utils::ColorModifier bold_mod_{utils::ColorModifier::Code::BOLD};
+ utils::ColorModifier end_mod_{utils::ColorModifier::Code::RESET};
+};
+
+static inline int ensureFlows(const Prefix &prefix, std::size_t flows) {
+ int ret = ERROR_SUCCESS;
+
+ // Make sure the provided prefix length not allows to accomodate the
+ // provided number of flows.
+ uint16_t max_ip_addr_len_bits;
+ uint16_t log2_n_flow;
+ u64 max_n_flow;
+ if (prefix.getAddressFamily() == AF_INET) {
+ max_ip_addr_len_bits = IPV4_ADDR_LEN_BITS;
+ } else if (prefix.getAddressFamily() == AF_INET6) {
+ max_ip_addr_len_bits = IPV6_ADDR_LEN_BITS;
+ } else {
+ Logger() << "Error: unknown address family." << std::endl;
+ ret = ERROR_SETUP;
+ goto end;
+ }
+
+ log2_n_flow = max_ip_addr_len_bits - prefix.getPrefixLength();
+ max_n_flow = log2_n_flow < 64 ? (1 << log2_n_flow) : ~0ULL;
+
+ if (flows > max_n_flow) {
+ Logger() << "Error: the provided prefix length does not allow to "
+ "accomodate the provided number of flows ("
+ << flows << " > " << max_n_flow << ")." << std::endl;
+ ret = ERROR_SETUP;
+ }
+
+end:
+ return ret;
+}
/**
* Class to retrieve the maximum payload size given the MTU and packet headers.
@@ -90,8 +174,9 @@ class PayloadSize {
transport_size - fec_size;
}
- static Packet::Format getFormatFromName(Name name, bool ah = false) {
- switch (name.getAddressFamily()) {
+ static Packet::Format getFormatFromPrefix(const Prefix &prefix,
+ bool ah = false) {
+ switch (prefix.getAddressFamily()) {
case AF_INET:
return ah ? HF_INET_TCP_AH : HF_INET_TCP;
case AF_INET6:
@@ -158,124 +243,69 @@ struct packet_t {
uint32_t size;
};
+struct Configuration {
+ Prefix name_{"b001::abcd/64"};
+ std::string passphrase_;
+ std::string aggr_interest_passphrase_;
+ bool rtc_{false};
+ uint16_t port_{0};
+ bool aggregated_data_{false};
+ Packet::Format packet_format_{default_values::packet_format};
+ uint32_t parallel_flows_{1};
+ bool colored_{true};
+};
+
/**
* Container for command line configuration for hiperf client.
*/
-struct ClientConfiguration {
- ClientConfiguration()
- : name("b001::abcd", 0),
- beta(-1.f),
- drop_factor(-1.f),
- window(-1),
- producer_certificate(""),
- passphrase(""),
- receive_buffer(nullptr),
- receive_buffer_size_(128 * 1024),
- download_size(0),
- report_interval_milliseconds_(1000),
- transport_protocol_(CBR),
- rtc_(false),
- test_mode_(false),
- relay_(false),
- secure_(false),
- producer_prefix_(),
- interest_lifetime_(500),
- unverified_interval_(10000),
- unverified_ratio_(0.2),
- relay_name_("c001::abcd/64"),
- output_stream_mode_(false),
- port_(0),
- recovery_strategy_(4),
- aggregated_data_(false),
- packet_format_(default_values::packet_format),
- print_headers_(true),
- nb_iterations_(std::numeric_limits<decltype(nb_iterations_)>::max()) {}
-
- Name name;
- double beta;
- double drop_factor;
- double window;
- std::string producer_certificate;
- std::string passphrase;
- std::shared_ptr<utils::MemBuf> receive_buffer;
- std::size_t receive_buffer_size_;
- std::size_t download_size;
- std::uint32_t report_interval_milliseconds_;
- TransportProtocolAlgorithms transport_protocol_;
- bool rtc_;
- bool test_mode_;
- bool relay_;
- bool secure_;
+struct ClientConfiguration : public Configuration {
+ double beta_{-1.f};
+ double drop_factor_{-1.f};
+ double window_{-1.f};
+ std::string producer_certificate_;
+ std::string passphrase_;
+ std::size_t receive_buffer_size_{128 * 1024};
+ std::uint32_t report_interval_milliseconds_{1000};
+ TransportProtocolAlgorithms transport_protocol_{CBR};
+ bool test_mode_{false};
+ bool relay_{false};
Prefix producer_prefix_;
- uint32_t interest_lifetime_;
- uint32_t unverified_interval_;
- double unverified_ratio_;
- Prefix relay_name_;
- bool output_stream_mode_;
- uint16_t port_;
- uint32_t recovery_strategy_;
- bool aggregated_data_;
- Packet::Format packet_format_;
- bool print_headers_;
- std::uint32_t nb_iterations_;
- forwarder_type_t forwarder_type_;
+ uint32_t interest_lifetime_{500};
+ uint32_t manifest_factor_relevant_{100};
+ uint32_t manifest_factor_alert_{20};
+ Prefix relay_name_{"c001::abcd/64"};
+ bool output_stream_mode_{false};
+ uint32_t recovery_strategy_{4};
+ bool print_headers_{true};
+ std::uint32_t nb_iterations_{
+ std::numeric_limits<decltype(nb_iterations_)>::max()};
+ bool content_sharing_mode_{false};
+ bool aggregated_interests_{false};
};
/**
* Container for command line configuration for hiperf server.
*/
-struct ServerConfiguration {
- ServerConfiguration()
- : name("b001::abcd/64"),
- virtual_producer(true),
- manifest(0),
- live_production(false),
- content_lifetime(600000000_U32),
- download_size(20 * 1024 * 1024),
- hash_algorithm_(CryptoHashType::SHA256),
- 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_(1384),
- secure_(false),
- input_stream_mode_(false),
- port_(0),
- aggregated_data_(false),
- fec_type_(""),
- packet_format_(default_values::packet_format) {}
-
- Prefix name;
- bool virtual_producer;
- std::uint32_t manifest;
- bool live_production;
- std::uint32_t content_lifetime;
- std::uint32_t download_size;
- 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_;
- bool secure_;
- bool input_stream_mode_;
- uint16_t port_;
+struct ServerConfiguration : public Configuration {
+ bool virtual_producer_{true};
+ std::uint32_t manifest_max_capacity_{0};
+ bool live_production_{false};
+ std::uint32_t content_lifetime_{
+ transport::interface::default_values::content_object_expiry_time};
+ std::uint32_t download_size_{20 * 1024 * 1024};
+ CryptoHashType hash_algorithm_{CryptoHashType::SHA256};
+ std::string keystore_name_;
+ std::string keystore_password_{"cisco"};
+ bool multiphase_produce_{false};
+ bool interactive_{false};
+ bool trace_based_{false};
+ std::uint32_t trace_index_{0};
+ char *trace_file_{nullptr};
+ Rate production_rate_{"2048kbps"};
+ std::size_t payload_size_{1384};
+ bool input_stream_mode_{false};
std::vector<struct packet_t> trace_;
- bool aggregated_data_;
std::string fec_type_;
- Packet::Format packet_format_;
};
} // namespace hiperf
diff --git a/apps/hiperf/src/forwarder_config.h b/apps/hiperf/src/forwarder_config.h
deleted file mode 100644
index aaac14839..000000000
--- a/apps/hiperf/src/forwarder_config.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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 <unordered_map>
-#include <vector>
-
-namespace hiperf {
-
-struct ListenerConfig {
- std::string address;
- std::uint16_t port;
- std::string interface;
- 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 interface;
- std::string name;
-};
-
-struct RouteConfig {
- std::string prefix;
- uint16_t weight;
- std::string main_connector;
- std::string backup_connector;
- std::string name;
-};
-
-class ForwarderConfiguration {
- public:
- ForwarderConfiguration() : n_threads_(1) {}
-
- bool empty() {
- return listeners_.empty() && connectors_.empty() && routes_.empty();
- }
-
- ForwarderConfiguration &setThreadNumber(std::size_t threads) {
- n_threads_ = threads;
- return *this;
- }
-
- std::size_t getThreadNumber() { return n_threads_; }
-
- template <typename... Args>
- ForwarderConfiguration &addListener(Args &&...args) {
- listeners_.emplace_back(std::forward<Args>(args)...);
- return *this;
- }
-
- template <typename... Args>
- ForwarderConfiguration &addConnector(const std::string &name,
- Args &&...args) {
- connectors_.emplace(name, std::forward<Args>(args)...);
- return *this;
- }
-
- template <typename... Args>
- ForwarderConfiguration &addRoute(Args &&...args) {
- routes_.emplace_back(std::forward<Args>(args)...);
- return *this;
- }
-
- std::vector<ListenerConfig> &getListeners() { return listeners_; }
-
- std::unordered_map<std::string, ConnectorConfig> &getConnectors() {
- return connectors_;
- }
-
- std::vector<RouteConfig> &getRoutes() { return routes_; }
-
- private:
- std::vector<ListenerConfig> listeners_;
- std::unordered_map<std::string, ConnectorConfig> connectors_;
- std::vector<RouteConfig> routes_;
- std::size_t n_threads_;
-};
-
-} // namespace hiperf \ No newline at end of file
diff --git a/apps/hiperf/src/forwarder_interface.cc b/apps/hiperf/src/forwarder_interface.cc
deleted file mode 100644
index e87a5953d..000000000
--- a/apps/hiperf/src/forwarder_interface.cc
+++ /dev/null
@@ -1,696 +0,0 @@
-/*
- * 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 <arpa/inet.h>
-#include <forwarder_interface.h>
-#include <hicn/transport/utils/log.h>
-
-#include <chrono>
-#include <iostream>
-#include <thread>
-#include <unordered_set>
-
-extern "C" {
-#include <hicn/error.h>
-#include <hicn/util/ip_address.h>
-#include <hicn/util/sstrncpy.h>
-}
-
-// XXX the main listener should be retrieve in this class at initialization, aka
-// when hICN becomes avialable
-//
-// XXX the main listener port will be retrieved in the forwarder
-// interface... everything else will be delayed until we have this
-// information
-
-namespace hiperf {
-
-ForwarderInterface::ForwarderInterface(asio::io_service &io_service)
- : external_ioservice_(io_service), timer_(io_service) {}
-
-ForwarderInterface::ForwarderInterface(asio::io_service &io_service,
- ICallback *callback,
- forwarder_type_t fwd_type)
- : external_ioservice_(io_service), timer_(io_service) {
- initForwarderInterface(callback, fwd_type);
-}
-
-ForwarderInterface::~ForwarderInterface() {
- if (thread_ && thread_->joinable()) {
- internal_ioservice_.dispatch([this]() {
- if (sock_) {
- hc_sock_free(sock_);
- sock_ = nullptr;
- }
-
- work_.reset();
- });
-
- thread_->join();
- }
-}
-
-void ForwarderInterface::initForwarderInterface(ICallback *callback,
- forwarder_type_t fwd_type) {
- forwarder_interface_callback_ = callback;
- work_ = std::make_unique<asio::io_service::work>(internal_ioservice_);
- sock_ = nullptr;
- thread_ = std::make_unique<std::thread>([this]() {
- std::cout << "Starting Forwarder Interface thread" << std::endl;
- internal_ioservice_.run();
- std::cout << "Stopping Forwarder Interface thread" << std::endl;
- });
- check_routes_timer_ = nullptr;
- pending_add_route_counter_ = 0;
- hicn_listen_port_ = 9695;
- /* We start in disabled state even when a forwarder is always available */
- state_ = State::Disabled;
- fwd_type_ = fwd_type;
- num_reattempts = 0;
- std::cout << "Forwarder interface created... connecting to forwarder...\n";
- internal_ioservice_.post([this]() { onHicnServiceAvailable(true); });
-}
-
-void ForwarderInterface::onHicnServiceAvailable(bool flag) {
- if (flag) {
- switch (state_) {
- case State::Disabled:
- case State::Requested:
- state_ = State::Available;
- case State::Available:
- connectToForwarder();
- /* Synchronous */
- if (state_ != State::Connected) {
- std::cout << "ConnectToForwarder failed" << std::endl;
- goto REATTEMPT;
- }
- state_ = State::Ready;
-
- std::cout << "Connected to forwarder... cancelling reconnection timer"
- << std::endl;
-
- timer_.cancel();
- num_reattempts = 0;
-
- std::cout << "Forwarder interface is ready... communicate to controller"
- << std::endl;
-
- forwarder_interface_callback_->onHicnServiceReady();
- case State::Connected:
- case State::Ready:
- break;
- }
- } else {
- if (sock_) {
- hc_sock_free(sock_);
- sock_ = nullptr;
- }
- state_ = State::Disabled; // XXX to be checked upon callback to prevent the
- // state from going forward (used to manage
- // concurrency)
- }
- return;
-
-REATTEMPT:
- /* Schedule reattempt */
- std::cout << "Failed to connect, scheduling reattempt" << std::endl;
- num_reattempts++;
-
- timer_.expires_from_now(
- std::chrono::milliseconds(ForwarderInterface::REATTEMPT_DELAY_MS));
- // timer_.async_wait(std::bind(&ForwarderInterface::onHicnServiceAvailable,
- // this, flag, std::placeholders::_1));
- timer_.async_wait([this, flag](const std::error_code &ec) {
- if (ec) return;
- onHicnServiceAvailable(flag);
- });
-}
-
-int ForwarderInterface::connectToForwarder() {
- sock_ = hc_sock_create_forwarder(fwd_type_);
- if (!sock_) {
- std::cout << "Could not create socket" << std::endl;
- goto ERR_SOCK;
- }
-
- if (hc_sock_connect(sock_) < 0) {
- std::cout << "Could not connect to forwarder" << std::endl;
- goto ERR;
- }
-
- std::cout << "Forwarder interface connected" << std::endl;
- state_ = State::Connected;
- return 0;
-
-ERR:
- hc_sock_free(sock_);
- sock_ = nullptr;
-ERR_SOCK:
- return -1;
-}
-
-int ForwarderInterface::checkListener() {
- 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) {
- hicn_listen_port_ = l->local_port;
- state_ = State::Ready;
- ret = 0;
- std::cout << "Got listener port" << std::endl;
- break;
- }
- }
-
- hc_data_free(data);
- return ret;
-}
-
-void ForwarderInterface::close() {
- std::cout << "ForwarderInterface::close" << std::endl;
-
- state_ = State::Disabled;
- /* Cancelling eventual reattempts */
- timer_.cancel();
-
- if (sock_) {
- hc_sock_free(sock_);
- sock_ = nullptr;
- }
-
- internal_ioservice_.post([this]() { work_.reset(); });
-
- if (thread_->joinable()) {
- thread_->join();
- }
-}
-
-#if 0
-void ForwarderInterface::enableCheckRoutesTimer() {
- if (check_routes_timer_ != nullptr) return;
-
- check_routes_timer_ =
- std::make_unique<asio::steady_timer>(internal_ioservice_);
- checkRoutesLoop();
-}
-
-void ForwarderInterface::removeConnectedUserNow(ProtocolPtr protocol) {
- internalRemoveConnectedUser(protocol);
-}
-
-void ForwarderInterface::scheduleRemoveConnectedUser(ProtocolPtr protocol) {
- internal_ioservice_.post(
- [this, protocol]() { internalRemoveConnectedUser(protocol); });
-}
-#endif
-
-void ForwarderInterface::createFaceAndRoute(const RouteInfoPtr &route_info) {
- std::vector<RouteInfoPtr> routes;
- routes.push_back(std::move(route_info));
- createFaceAndRoutes(routes);
-}
-
-void ForwarderInterface::createFaceAndRoutes(
- const std::vector<RouteInfoPtr> &routes_info) {
- pending_add_route_counter_++;
- auto timer = new asio::steady_timer(internal_ioservice_);
- internal_ioservice_.post([this, routes_info, timer]() {
- internalCreateFaceAndRoutes(routes_info, ForwarderInterface::MAX_REATTEMPT,
- timer);
- });
-}
-
-void ForwarderInterface::deleteFaceAndRoute(const RouteInfoPtr &route_info) {
- std::vector<RouteInfoPtr> routes;
- routes.push_back(std::move(route_info));
- deleteFaceAndRoutes(routes);
-}
-
-void ForwarderInterface::deleteFaceAndRoutes(
- const std::vector<RouteInfoPtr> &routes_info) {
- internal_ioservice_.post([this, routes_info]() {
- for (auto &route : routes_info) {
- internalDeleteFaceAndRoute(route);
- }
- });
-}
-
-void ForwarderInterface::setStrategy(std::string prefix, uint32_t prefix_len,
- std::string strategy) {
- if (!sock_) return;
-
- ip_address_t ip_prefix;
- if (ip_address_pton(prefix.c_str(), &ip_prefix) < 0) {
- return;
- }
-
- strategy_type_t strategy_type = strategy_type_from_str(strategy.c_str());
- if (strategy_type == STRATEGY_TYPE_UNDEFINED) return;
-
- hc_strategy_t strategy_conf;
- strategy_conf.address = ip_prefix;
- strategy_conf.len = prefix_len;
- strategy_conf.family = AF_INET6;
- strategy_conf.type = strategy_type;
-
- hc_strategy_set(sock_, &strategy_conf);
-}
-
-void ForwarderInterface::internalDeleteFaceAndRoute(
- const RouteInfoPtr &route_info) {
- if (!sock_) return;
-
- 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(route_info->route_addr) == 0 &&
- r->len == route_info->route_len) {
- // route found
- routes_to_remove.push_back(r);
- }
- }
-
- 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) {
- std::cout << "Error removing route from forwarder." << std::endl;
- }
- }
-
- // 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) {
- std::cout << "Error removing connection from forwarder." << std::endl;
- }
- }
-
- hc_data_free(data);
-}
-
-void ForwarderInterface::internalCreateFaceAndRoutes(
- const std::vector<RouteInfoPtr> &route_info, uint8_t max_try,
- asio::steady_timer *timer) {
- uint32_t face_id;
-
- std::vector<RouteInfoPtr> failed;
- for (auto &route : route_info) {
- int ret = tryToCreateFace(route.get(), &face_id);
- if (ret >= 0) {
- auto ret = tryToCreateRoute(route.get(), face_id);
- if (ret < 0) {
- failed.push_back(route);
- std::cerr << "Error creating route and face" << std::endl;
- continue;
- }
- }
- }
-
- if (failed.size() > 0) {
- if (max_try == 0) {
- /* All attempts failed */
- goto RESULT;
- }
- max_try--;
- timer->expires_from_now(std::chrono::milliseconds(500));
- timer->async_wait(
- [this, failed, max_try, timer](const std::error_code &ec) {
- if (ec) return;
- internalCreateFaceAndRoutes(failed, max_try, timer);
- });
- return;
- }
-
-#if 0
- // route_status_[protocol] = std::move(route_info);
- for (size_t i = 0; i < route_info.size(); i++) {
- route_status_.insert(
- std::pair<ClientId, RouteInfoPtr>(protocol, std::move(route_info[i])));
- }
-#endif
-
-RESULT:
- std::cout << "Face / Route create ok, now calling back protocol" << std::endl;
- pending_add_route_counter_--;
- external_ioservice_.post([this, r = std::move(route_info)]() mutable {
- forwarder_interface_callback_->onRouteConfigured(r);
- });
- delete timer;
-}
-
-int ForwarderInterface::tryToCreateFace(RouteInfo *route_info,
- uint32_t *face_id) {
- bool found = false;
-
- // check connection with the forwarder
- if (!sock_) {
- std::cout << "[ForwarderInterface::tryToCreateFace] socket error"
- << std::endl;
- goto ERR_SOCK;
- }
-
- // get listeners list
- hc_data_t *data;
- if (hc_listener_list(sock_, &data) < 0) {
- std::cout << "[ForwarderInterface::tryToCreateFace] cannot list listeners";
- goto ERR_LIST;
- }
-
- char _local_address[128];
- foreach_listener(l, data) {
- std::cout << "Processing " << l->interface_name << std::endl;
- std::string interface = std::string(l->interface_name);
- int ret = ip_address_ntop(&l->local_addr, _local_address, 128, AF_INET);
- if (ret < 0) {
- std::cerr << "Error in ip_address_ntop" << std::endl;
- goto ERR;
- }
-
- std::string local_address = std::string(_local_address);
- uint16_t local_port = l->local_port;
-
- if (interface.compare(route_info->interface) == 0 &&
- local_address.compare(route_info->local_addr) == 0 &&
- local_port == route_info->local_port) {
- found = true;
- break;
- }
- }
-
- std::cout << route_info->remote_addr << std::endl;
-
- ip_address_t local_address, remote_address;
- ip_address_pton(route_info->local_addr.c_str(), &local_address);
- ip_address_pton(route_info->remote_addr.c_str(), &remote_address);
-
- if (!found) {
- // Create listener
- hc_listener_t listener;
- memset(&listener, 0, sizeof(hc_listener_t));
-
- std::string name = "l_" + route_info->name;
- listener.local_addr = local_address;
- listener.type = FACE_TYPE_UDP;
- listener.family = AF_INET;
- listener.local_port = route_info->local_port;
- int ret = strcpy_s(listener.name, SYMBOLIC_NAME_LEN - 1, name.c_str());
- if (ret < EOK) goto ERR;
- ret = strcpy_s(listener.interface_name, INTERFACE_LEN - 1,
- route_info->interface.c_str());
- if (ret < EOK) goto ERR;
-
- std::cout << "------------> " << route_info->interface << std::endl;
-
- ret = hc_listener_create(sock_, &listener);
-
- if (ret < 0) {
- std::cerr << "Error creating listener." << std::endl;
- return -1;
- } else {
- std::cout << "Listener " << listener.id << " created." << std::endl;
- }
- }
-
- // Create face
- hc_face_t face;
- memset(&face, 0, sizeof(hc_face_t));
-
- // crate face with the local interest
- face.face.type = FACE_TYPE_UDP;
- face.face.family = route_info->family;
- face.face.local_addr = local_address;
- face.face.remote_addr = remote_address;
- face.face.local_port = route_info->local_port;
- face.face.remote_port = route_info->remote_port;
-
- if (netdevice_set_name(&face.face.netdevice, route_info->interface.c_str()) <
- 0) {
- std::cout << "[ForwarderInterface::tryToCreateFaceAndRoute] "
- "netdevice_set_name "
- "("
- << face.face.netdevice.name << ", "
- << route_info->interface << ") error" << std::endl;
- goto ERR;
- }
-
- // create face
- if (hc_face_create(sock_, &face) < 0) {
- std::cout << "[ForwarderInterface::tryToCreateFace] error creating face";
- goto ERR;
- }
-
- std::cout << "Face created successfully" << std::endl;
-
- // assing face to the return value
- *face_id = face.id;
-
- hc_data_free(data);
- return 0;
-
-ERR:
- hc_data_free(data);
-ERR_LIST:
-ERR_SOCK:
- return -1;
-}
-
-int ForwarderInterface::tryToCreateRoute(RouteInfo *route_info,
- uint32_t face_id) {
- std::cout << "Trying to create route" << std::endl;
-
- // check connection with the forwarder
- if (!sock_) {
- std::cout << "[ForwarderInterface::tryToCreateRoute] socket error";
- return -1;
- }
-
- ip_address_t route_ip;
- hc_route_t route;
-
- if (ip_address_pton(route_info->route_addr.c_str(), &route_ip) < 0) {
- std::cout << "[ForwarderInterface::tryToCreateRoute] ip_address_pton error";
- 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) {
- std::cout << "[ForwarderInterface::tryToCreateRoute] error creating route";
- return -1;
- }
-
- std::cout << "[ForwarderInterface::tryToCreateRoute] OK" << std::endl;
- return 0;
-}
-
-#if 0 // not used
-void ForwarderInterface::checkRoutesLoop() {
- check_routes_timer_->expires_from_now(std::chrono::milliseconds(1000));
- check_routes_timer_->async_wait([this](const std::error_code &ec) {
- if (ec) return;
- if (pending_add_route_counter_ == 0) checkRoutes();
- });
-}
-
-void ForwarderInterface::checkRoutes() {
- std::cout << "someone called the checkRoutes function" << std::endl;
- if (!sock_) return;
-
- hc_data_t *data;
- if (hc_route_list(sock_, &data) < 0) {
- return;
- }
-
- std::unordered_set<std::string> routes_set;
- 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(std::string(remote_addr) + "/" + std::to_string(r->len));
- routes_set.insert(route);
- }
-
- for (auto it = route_status_.begin(); it != route_status_.end(); it++) {
- std::string route(it->second->route_addr + "/" +
- std::to_string(it->second->route_len));
- if (routes_set.find(route) == routes_set.end()) {
- // the route is missing
- createFaceAndRoute(it->second, it->first);
- break;
- }
- }
-
- hc_data_free(data);
-}
-#endif
-
-#if 0
- using ListenerRetrievedCallback =
- std::function<void(std::error_code, uint32_t)>;
-
- ListenerRetrievedCallback listener_retrieved_callback_;
-
-#ifdef __ANDROID__
- hicn_listen_port_(9695),
-#else
- hicn_listen_port_(0),
-#endif
- timer_(forward_engine_.getIoService()),
-
- void initConfigurationProtocol(void)
- {
- // We need the configuration, which is different for every protocol...
- // so we move this step down towards the protocol implementation itself.
- if (!permanent_hicn) {
- doInitConfigurationProtocol();
- } else {
- // XXX This should be moved somewhere else
- getMainListener(
- [this](const std::error_code &ec, uint32_t hicn_listen_port) {
- if (!ec)
- {
- hicn_listen_port_ = hicn_listen_port;
- doInitConfigurationProtocol();
- }
- });
- }
- }
-
- template <typename Callback>
- void getMainListener(Callback &&callback)
- {
- listener_retrieved_callback_ = std::forward<Callback &&>(callback);
- tryToConnectToForwarder();
- }
- private:
- void doGetMainListener(const 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.
- std::cout <<
- "Could not retrieve main listener port from the forwarder. "
- "Retrying.";
-
- timer_.expires_from_now(std::chrono::milliseconds(RETRY_INTERVAL));
- timer_.async_wait(std::bind(&Protocol::doGetMainListener, this,
- std::placeholders::_1));
- }
- else
- {
- timer_.cancel();
- retx_count_ = 0;
- hicn_listen_port_ = uint16_t(ret);
- listener_retrieved_callback_(
- make_error_code(configuration_error::success), hicn_listen_port_);
- }
- }
- else
- {
- std::cout << "Timer for retrieving main hicn listener canceled." << std::endl;
- }
- }
-
- void tryToConnectToForwarder()
- {
- doTryToConnectToForwarder(std::make_error_code(std::errc(0)));
- }
-
- void doTryToConnectToForwarder(const std::error_code &ec)
- {
- if (!ec)
- {
- // ec == 0 --> timer expired
- int ret = forwarder_interface_.connect();
- if (ret < 0)
- {
- // We were not able to connect to the local forwarder. Do not give up
- // and retry.
- std::cout << "Could not connect to local forwarder. Retrying." << std::endl;
-
- timer_.expires_from_now(std::chrono::milliseconds(RETRY_INTERVAL));
- timer_.async_wait(std::bind(&Protocol::doTryToConnectToForwarder, this,
- std::placeholders::_1));
- }
- else
- {
- timer_.cancel();
- retx_count_ = 0;
- doGetMainListener(std::make_error_code(std::errc(0)));
- }
- }
- else
- {
- std::cout << "Timer for re-trying forwarder connection canceled." << std::endl;
- }
- }
-
-
- template <typename ProtocolImplementation>
- constexpr uint32_t Protocol<ProtocolImplementation>::RETRY_INTERVAL;
-
-#endif
-
-constexpr uint32_t ForwarderInterface::REATTEMPT_DELAY_MS;
-constexpr uint32_t ForwarderInterface::MAX_REATTEMPT;
-
-} // namespace hiperf
diff --git a/apps/hiperf/src/forwarder_interface.h b/apps/hiperf/src/forwarder_interface.h
deleted file mode 100644
index e58989295..000000000
--- a/apps/hiperf/src/forwarder_interface.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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/utils/noncopyable.h>
-
-extern "C" {
-#ifndef WITH_POLICY
-#define WITH_POLICY
-#endif
-#include <hicn/ctrl/api.h>
-#include <hicn/util/ip_address.h>
-}
-
-#ifndef ASIO_STANDALONE
-#define ASIO_STANDALONE
-#endif
-#include <asio.hpp>
-#include <functional>
-#include <thread>
-#include <unordered_map>
-
-namespace hiperf {
-
-class ForwarderInterface : ::utils::NonCopyable {
- static const uint32_t REATTEMPT_DELAY_MS = 500;
- static const uint32_t MAX_REATTEMPT = 10;
-
- public:
- struct RouteInfo {
- int family;
- std::string local_addr;
- uint16_t local_port;
- std::string remote_addr;
- uint16_t remote_port;
- std::string route_addr;
- uint8_t route_len;
- std::string interface;
- std::string name;
- };
-
- using RouteInfoPtr = std::shared_ptr<RouteInfo>;
-
- class ICallback {
- public:
- virtual void onHicnServiceReady() = 0;
- virtual void onRouteConfigured(std::vector<RouteInfoPtr> &route_info) = 0;
- };
-
- enum class State {
- Disabled, /* Stack is stopped */
- Requested, /* Stack is starting */
- Available, /* Forwarder is running */
- Connected, /* Control socket connected */
- Ready, /* Listener present */
- };
-
- public:
- explicit ForwarderInterface(asio::io_service &io_service);
- explicit ForwarderInterface(asio::io_service &io_service, ICallback *callback,
- forwarder_type_t fwd_type);
-
- ~ForwarderInterface();
-
- void initForwarderInterface(ICallback *callback, forwarder_type_t fwd_type);
-
- State getState();
-
- void setState(State state);
-
- void onHicnServiceAvailable(bool flag);
-
- void enableCheckRoutesTimer();
-
- void createFaceAndRoutes(const std::vector<RouteInfoPtr> &routes_info);
-
- void createFaceAndRoute(const RouteInfoPtr &route_info);
-
- void deleteFaceAndRoutes(const std::vector<RouteInfoPtr> &routes_info);
-
- void deleteFaceAndRoute(const RouteInfoPtr &route_info);
-
- void setStrategy(std::string prefix, uint32_t prefix_len,
- std::string strategy);
-
- void close();
-
- uint16_t getHicnListenerPort() { return hicn_listen_port_; }
-
- private:
- ForwarderInterface &operator=(const ForwarderInterface &other) = delete;
-
- int connectToForwarder();
-
- int checkListener();
-
- void internalCreateFaceAndRoutes(const std::vector<RouteInfoPtr> &route_info,
- uint8_t max_try, asio::steady_timer *timer);
-
- void internalDeleteFaceAndRoute(const RouteInfoPtr &routes_info);
-
- int tryToCreateFace(RouteInfo *RouteInfo, uint32_t *face_id);
- int tryToCreateRoute(RouteInfo *RouteInfo, uint32_t face_id);
-
- void checkRoutesLoop();
-
- void checkRoutes();
-
- asio::io_service &external_ioservice_;
- asio::io_service internal_ioservice_;
- ICallback *forwarder_interface_callback_;
- std::unique_ptr<asio::io_service::work> work_;
- hc_sock_t *sock_;
- std::unique_ptr<std::thread> thread_;
- // SetRouteCallback set_route_callback_;
- // std::unordered_multimap<ProtocolPtr, RouteInfoPtr> route_status_;
- std::unique_ptr<asio::steady_timer> check_routes_timer_;
- uint32_t pending_add_route_counter_;
- uint16_t hicn_listen_port_;
-
- State state_;
-
- forwarder_type_t fwd_type_;
-
- /* Reattempt timer */
- asio::steady_timer timer_;
- unsigned num_reattempts;
-};
-
-} // namespace hiperf
diff --git a/apps/hiperf/src/main.cc b/apps/hiperf/src/main.cc
index 9c0f0a140..85cadd677 100644
--- a/apps/hiperf/src/main.cc
+++ b/apps/hiperf/src/main.cc
@@ -14,7 +14,6 @@
*/
#include <client.h>
-#include <forwarder_interface.h>
#include <server.h>
namespace hiperf {
@@ -44,6 +43,11 @@ void usage() {
std::cerr << "-X\t<param>\t\t\t\t"
<< "Set FEC params. Options are Rely_K#_N# or RS_K#_N#"
<< std::endl;
+ std::cerr
+ << "-J\t<passphrase>\t\t\t"
+ << "Set the passphrase used to sign/verify aggregated interests. "
+ "If set on the client, aggregated interests are enable automatically."
+ << std::endl;
#endif
std::cerr << std::endl;
std::cerr << "SERVER SPECIFIC:" << std::endl;
@@ -51,11 +55,17 @@ void usage() {
"Sends an application data unit in bytes that is published once "
"before exit"
<< std::endl;
+ std::cerr << "-E\t<expiry_time>\t\t\t"
+ "Expiration time for data packets generated by the producer "
+ "socket"
+ << std::endl;
std::cerr << "-s\t<packet_size>\t\t\tData packet payload size." << std::endl;
std::cerr << "-r\t\t\t\t\t"
<< "Produce real content of <content_size> bytes" << std::endl;
- std::cerr << "-m\t<manifest_capacity>\t\t"
- << "Produce transport manifest" << std::endl;
+ std::cerr << "-m\t<manifest_max_capacity>\t\t"
+ << "The maximum number of entries a manifest can contain. Set it "
+ "to 0 to disable manifests. Default is 30, max is 255."
+ << std::endl;
std::cerr << "-l\t\t\t\t\t"
<< "Start producing content upon the reception of the "
"first interest"
@@ -92,11 +102,6 @@ void usage() {
"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;
std::cerr << "-G\t<port>\t\t\t\t"
<< "Input stream from localhost at the specified port" << std::endl;
#endif
@@ -110,12 +115,27 @@ void usage() {
<< std::endl;
std::cerr << "-L\t<interest lifetime>\t\t"
<< "Set interest lifetime." << std::endl;
- std::cerr << "-u\t<delay>\t\t\t\t"
- << "Set max lifetime of unverified packets." << std::endl;
+ std::cerr << "-U\t<factor>\t\t\t"
+ << "Update the relevance threshold: if an unverified packet has "
+ "been received before the last U * manifest_max_capacity_ "
+ "packets received (verified or not), it will be flushed out. "
+ "Should be > 1, default is 100."
+ << std::endl;
+ std::cerr << "-u\t<factor>\t\t\t"
+ << "Update the alert threshold: if the "
+ "number of unverified packet is > u * manifest_max_capacity_, "
+ "an alert is raised. Should be set such that U > u >= 1, "
+ "default is 20. If u >= U, no alert will ever be raised."
+ << std::endl;
std::cerr << "-M\t<input_buffer_size>\t\t"
<< "Size of consumer input buffer. If 0, reassembly of packets "
"will be disabled."
<< std::endl;
+ std::cerr << "-N\t\t\t\t\t"
+ << "Enable aggregated interests; the number of suffixes (including "
+ "the one in the header) can be set through the env variable "
+ "`MAX_AGGREGATED_INTERESTS`."
+ << std::endl;
std::cerr << "-W\t<window_size>\t\t\t"
<< "Use a fixed congestion window "
"for retrieving the data."
@@ -137,7 +157,10 @@ void usage() {
"used with the -R (default: false)"
<< std::endl;
std::cerr << "-P\t\t\t\t\t"
- << "Prefix of the producer where to do the handshake" << std::endl;
+ << "Number of parallel streams. For hiperf client, this is the "
+ "number of consumer to create, while for hiperf server this is "
+ "the number of producers to create."
+ << std::endl;
std::cerr << "-j\t<relay_name>\t\t\t"
<< "Publish received content under the name relay_name."
"This is an RTC specific option, to be "
@@ -145,13 +168,25 @@ void usage() {
<< std::endl;
std::cerr << "-g\t<port>\t\t\t\t"
<< "Output stream to localhost at the specified port" << std::endl;
+ std::cerr << "-o\t\t\t\t\t"
+ << "Content sharing mode: if set the socket work in content sharing"
+ << "mode. It works only in RTC mode" << std::endl;
std::cerr << "-e\t<strategy>\t\t\t"
- << "Enhance the network with a reliability strategy. Options 1:"
- << " unreliable, 2: rtx only, 3: fec only, "
- << "4: delay based, 5: low rate, 6: low rate and best path "
- << "7: low rate and replication, 8: low rate and best"
- << " path/replication"
- << "(default: 2 = rtx only) " << std::endl;
+ << "Enhance the network with a reliability strategy. Options"
+ << std::endl;
+ std::cerr << "\t\t\t\t\t\t1: unreliable " << std::endl;
+ std::cerr << "\t\t\t\t\t\t2: rtx only " << std::endl;
+ std::cerr << "\t\t\t\t\t\t3: fec only " << std::endl;
+ std::cerr << "\t\t\t\t\t\t4: delay based " << std::endl;
+ std::cerr << "\t\t\t\t\t\t5: low rate " << std::endl;
+ std::cerr << "\t\t\t\t\t\t6: low rate and best path " << std::endl;
+ std::cerr << "\t\t\t\t\t\t7: low rate and replication" << std::endl;
+ std::cerr << "\t\t\t\t\t\t8: low rate and best path/replication "
+ << std::endl;
+ std::cerr << "\t\t\t\t\t\t9: only fec low residual losses " << std::endl;
+ std::cerr << "\t\t\t\t\t\t10: delay and best path " << std::endl;
+ std::cerr << "\t\t\t\t\t\t11: delay and replication " << std::endl;
+ std::cerr << "\t\t\t\t\t\t(default: 2 = rtx only) " << std::endl;
std::cerr << "-H\t\t\t\t\t"
<< "Disable periodic print headers in stats report." << std::endl;
std::cerr << "-n\t<nb_iterations>\t\t\t"
@@ -170,6 +205,8 @@ int main(int argc, char *argv[]) {
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
+ transport::interface::global_config::GlobalConfigInterface global_conf;
+
// -1 server, 0 undefined, 1 client
int role = 0;
int options = 0;
@@ -188,9 +225,10 @@ int main(int argc, char *argv[]) {
int opt;
#ifndef _WIN32
// Please keep in alphabetical order.
- while ((opt = getopt(argc, argv,
- "A:B:CDE:F:G:HIK:L:M:P:RST:U:W:X:ab:c:d:e:f:g:hi:j:k:lm:"
- "n:p:rs:tu:vwxy:z:")) != -1) {
+ while (
+ (opt = getopt(argc, argv,
+ "A:B:CDE:F:G:HIJ:K:L:M:NP:RST:U:W:X:ab:c:d:e:f:g:hi:j:k:lm:"
+ "n:op:qrs:tu:vwxy:z:")) != -1) {
switch (opt) {
// Common
case 'D': {
@@ -225,10 +263,14 @@ int main(int argc, char *argv[]) {
#else
// Please keep in alphabetical order.
while ((opt = getopt(argc, argv,
- "A:B:CE:F:HK:L:M:P:RSU:W:X:ab:c:d:e:f:hi:j:k:lm:n:p:rs:"
+ "A:B:CE:F:HK:L:M:P:RSU:W:X:ab:c:d:e:f:hi:j:k:lm:n:op:rs:"
"tu:vwxy:z:")) != -1) {
switch (opt) {
#endif
+ case 'E': {
+ server_configuration.content_lifetime_ = std::stoul(optarg);
+ break;
+ }
case 'f': {
log_file = optarg;
break;
@@ -243,14 +285,18 @@ int main(int argc, char *argv[]) {
server_configuration.aggregated_data_ = true;
break;
}
+ case 'o': {
+ client_configuration.content_sharing_mode_ = true;
+ break;
+ }
case 'w': {
client_configuration.packet_format_ = Packet::Format::HF_INET6_UDP;
server_configuration.packet_format_ = Packet::Format::HF_INET6_UDP;
break;
}
case 'k': {
- server_configuration.passphrase = std::string(optarg);
- client_configuration.passphrase = std::string(optarg);
+ server_configuration.passphrase_ = std::string(optarg);
+ client_configuration.passphrase_ = std::string(optarg);
break;
}
case 'z': {
@@ -271,20 +317,31 @@ int main(int argc, char *argv[]) {
role += 1;
break;
}
-
+ case 'q': {
+ client_configuration.colored_ = server_configuration.colored_ = false;
+ break;
+ }
+ case 'J': {
+ client_configuration.aggr_interest_passphrase_ = optarg;
+ server_configuration.aggr_interest_passphrase_ = optarg;
+ // Consumer signature is only used with aggregated interests,
+ // hence enabling it also forces usage of aggregated interests
+ client_configuration.aggregated_interests_ = true;
+ break;
+ }
// Client specifc
case 'b': {
- client_configuration.beta = std::stod(optarg);
+ client_configuration.beta_ = std::stod(optarg);
options = 1;
break;
}
case 'd': {
- client_configuration.drop_factor = std::stod(optarg);
+ client_configuration.drop_factor_ = std::stod(optarg);
options = 1;
break;
}
case 'W': {
- client_configuration.window = std::stod(optarg);
+ client_configuration.window_ = std::stod(optarg);
options = 1;
break;
}
@@ -293,13 +350,17 @@ int main(int argc, char *argv[]) {
options = 1;
break;
}
+ case 'N': {
+ client_configuration.aggregated_interests_ = true;
+ break;
+ }
case 'P': {
- client_configuration.producer_prefix_ = Prefix(optarg);
- client_configuration.secure_ = true;
+ client_configuration.parallel_flows_ =
+ server_configuration.parallel_flows_ = std::stoull(optarg);
break;
}
case 'c': {
- client_configuration.producer_certificate = std::string(optarg);
+ client_configuration.producer_certificate_ = std::string(optarg);
options = 1;
break;
}
@@ -318,13 +379,13 @@ int main(int argc, char *argv[]) {
options = 1;
break;
}
- case 'u': {
- client_configuration.unverified_interval_ = std::stoul(optarg);
+ case 'U': {
+ client_configuration.manifest_factor_relevant_ = std::stoul(optarg);
options = 1;
break;
}
- case 'U': {
- client_configuration.unverified_ratio_ = std::stod(optarg);
+ case 'u': {
+ client_configuration.manifest_factor_alert_ = std::stoul(optarg);
options = 1;
break;
}
@@ -346,7 +407,7 @@ int main(int argc, char *argv[]) {
}
// Server specific
case 'A': {
- server_configuration.download_size = std::stoul(optarg);
+ server_configuration.download_size_ = std::stoul(optarg);
options = -1;
break;
}
@@ -356,22 +417,22 @@ int main(int argc, char *argv[]) {
break;
}
case 'r': {
- server_configuration.virtual_producer = false;
+ server_configuration.virtual_producer_ = false;
options = -1;
break;
}
case 'm': {
- server_configuration.manifest = std::stoul(optarg);
+ server_configuration.manifest_max_capacity_ = std::stoul(optarg);
options = -1;
break;
}
case 'l': {
- server_configuration.live_production = true;
+ server_configuration.live_production_ = true;
options = -1;
break;
}
case 'K': {
- server_configuration.keystore_name = std::string(optarg);
+ server_configuration.keystore_name_ = std::string(optarg);
options = -1;
break;
}
@@ -393,7 +454,7 @@ int main(int argc, char *argv[]) {
break;
}
case 'p': {
- server_configuration.keystore_password = std::string(optarg);
+ server_configuration.keystore_password_ = std::string(optarg);
options = -1;
break;
}
@@ -409,11 +470,6 @@ int main(int argc, char *argv[]) {
options = -1;
break;
}
- case 'E': {
- server_configuration.keystore_name = std::string(optarg);
- server_configuration.secure_ = true;
- break;
- }
case 'e': {
client_configuration.recovery_strategy_ = std::stoul(optarg);
options = 1;
@@ -457,9 +513,9 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
} else {
if (role > 0) {
- client_configuration.name = Name(argv[optind]);
+ client_configuration.name_ = Prefix(argv[optind]);
} else {
- server_configuration.name = Prefix(argv[optind]);
+ server_configuration.name_ = Prefix(argv[optind]);
}
}
@@ -490,16 +546,9 @@ int main(int argc, char *argv[]) {
config.set();
// Parse config file
- transport::interface::global_config::parseConfigurationFile(conf_file);
+ global_conf.parseConfigurationFile(conf_file);
if (role > 0) {
- // set forwarder type
- client_configuration.forwarder_type_ = UNDEFINED;
- if (config.name.compare("hicnlightng_module") == 0)
- client_configuration.forwarder_type_ = HICNLIGHT;
- else if (config.name.compare("hicnlightng_module") == 0)
- client_configuration.forwarder_type_ = HICNLIGHT_NG;
-
HIperfClient c(client_configuration);
if (c.setup() != ERROR_SETUP) {
c.run();
diff --git a/apps/hiperf/src/server.cc b/apps/hiperf/src/server.cc
index 7101e7a4a..afaf5423b 100644
--- a/apps/hiperf/src/server.cc
+++ b/apps/hiperf/src/server.cc
@@ -21,156 +21,79 @@ namespace hiperf {
* Hiperf server class: configure and setup an hicn producer following the
* ServerConfiguration.
*/
-class HIperfServer::Impl : public ProducerSocket::Callback {
- const std::size_t log2_content_object_buffer_size = 8;
-
- public:
- Impl(const hiperf::ServerConfiguration &conf)
- : configuration_(conf),
- signals_(io_service_),
- rtc_timer_(io_service_),
- unsatisfied_interests_(),
- content_objects_((std::uint16_t)(1 << log2_content_object_buffer_size)),
- content_objects_index_(0),
- mask_((std::uint16_t)(1 << log2_content_object_buffer_size) - 1),
- last_segment_(0),
-#ifndef _WIN32
- input_(io_service_),
- rtc_running_(false),
-#endif
- flow_name_(configuration_.name.getName()),
- socket_(io_service_),
- recv_buffer_(nullptr, 0) {
- std::string buffer(configuration_.payload_size_, 'X');
- std::cout << "Producing contents under name " << conf.name.getName()
- << std::endl;
-#ifndef _WIN32
- if (configuration_.interactive_) {
- input_.assign(::dup(STDIN_FILENO));
- }
-#endif
-
- for (int i = 0; i < (1 << log2_content_object_buffer_size); i++) {
- content_objects_[i] = ContentObject::Ptr(new ContentObject(
- configuration_.name.getName(), configuration_.packet_format_, 0,
- (const uint8_t *)buffer.data(), buffer.size()));
- content_objects_[i]->setLifetime(
- default_values::content_object_expiry_time);
- }
+class HIperfServer::Impl {
+ static inline constexpr std::size_t klog2_content_object_buffer_size() {
+ return 8;
}
-
- virtual ~Impl() {}
-
- void virtualProcessInterest(ProducerSocket &p, const Interest &interest) {
- content_objects_[content_objects_index_ & mask_]->setName(
- interest.getName());
- producer_socket_->produce(
- *content_objects_[content_objects_index_++ & mask_]);
+ static inline constexpr std::size_t kcontent_object_buffer_size() {
+ return (1 << klog2_content_object_buffer_size());
}
-
- void processInterest(ProducerSocket &p, const Interest &interest) {
- p.setSocketOption(ProducerCallbacksOptions::CACHE_MISS,
- (ProducerInterestCallback)VOID_HANDLER);
- p.setSocketOption(GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
- 5000000_U32);
-
- produceContent(p, interest.getName(), interest.getName().getSuffix());
- std::cout << "Received interest " << interest.getName().getSuffix()
- << std::endl;
+ static inline constexpr std::size_t kmask() {
+ return (kcontent_object_buffer_size() - 1);
}
- void asyncProcessInterest(ProducerSocket &p, const Interest &interest) {
- p.setSocketOption(ProducerCallbacksOptions::CACHE_MISS,
- (ProducerInterestCallback)bind(&Impl::cacheMiss, this,
- std::placeholders::_1,
- std::placeholders::_2));
- p.setSocketOption(GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
- 5000000_U32);
- uint32_t suffix = interest.getName().getSuffix();
-
- if (suffix == 0) {
- last_segment_ = 0;
- unsatisfied_interests_.clear();
- }
-
- // The suffix will either come from the received interest or will be set to
- // the smallest suffix of a previous interest not satisfied
- if (!unsatisfied_interests_.empty()) {
- auto it = std::lower_bound(unsatisfied_interests_.begin(),
- unsatisfied_interests_.end(), last_segment_);
- if (it != unsatisfied_interests_.end()) {
- suffix = *it;
+ /**
+ * @brief As we can (potentially) setup many producer sockets, we need to keep
+ * a separate context for each one of them. The context contains parameters
+ * and variable that are specific to a single producer socket.
+ */
+ class ProducerContext
+ : public Base<ProducerContext, ServerConfiguration, Impl>,
+ public ProducerSocket::Callback {
+ public:
+ using ConfType = ServerConfiguration;
+ using ParentType = typename HIperfServer::Impl;
+ static inline const auto getContextType() { return "ProducerContext"; }
+
+ ProducerContext(HIperfServer::Impl &server, int producer_identifier)
+ : Base(server, server.io_service_, producer_identifier) {
+ // Allocate buffer to copy as content objects payload
+ std::string buffer(configuration_.payload_size_, 'X');
+
+ // Allocate array of content objects. They are share_ptr so that the
+ // transport will only capture a reference to them instead of performing
+ // an hard copy.
+ for (std::size_t i = 0; i < kcontent_object_buffer_size(); i++) {
+ const auto &element =
+ content_objects_.emplace_back(std::make_shared<ContentObject>(
+ configuration_.name_.makeName(), configuration_.packet_format_,
+ 0, (const uint8_t *)buffer.data(), buffer.size()));
+ element->setLifetime(default_values::content_object_expiry_time);
}
- unsatisfied_interests_.erase(unsatisfied_interests_.begin(), it);
}
- std::cout << "Received interest " << interest.getName().getSuffix()
- << ", starting production at " << suffix << std::endl;
- std::cout << unsatisfied_interests_.size() << " interests still unsatisfied"
- << std::endl;
- produceContentAsync(p, interest.getName(), suffix);
- }
+ // To make vector happy (move or copy constructor is needed when vector
+ // resizes)
+ ProducerContext(ProducerContext &&other) noexcept
+ : Base(std::move(other)),
+ content_objects_(std::move(other.content_objects_)),
+ unsatisfied_interests_(std::move(other.unsatisfied_interests_)),
+ last_segment_(other.last_segment_),
+ producer_socket_(std::move(other.producer_socket_)),
+ content_objects_index_(other.content_objects_index_),
+ payload_size_max_(other.payload_size_max_) {}
- 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::SteadyTime::TimePoint t0 = utils::SteadyTime::Clock::now();
- total = p.produceStream(content_name, std::move(b),
- !configuration_.multiphase_produce_, suffix);
- utils::SteadyTime::TimePoint t1 = utils::SteadyTime::Clock::now();
-
- std::cout << "Written " << total
- << " data packets in output buffer (Segmentation time: "
- << utils::SteadyTime::getDurationUs(t0, t1).count() << " us)"
- << std::endl;
- }
+ virtual ~ProducerContext() = default;
- void produceContentAsync(ProducerSocket &p, Name content_name,
- uint32_t suffix) {
- produce_thread_.add([this, suffix, content_name]() {
- auto b = utils::MemBuf::create(configuration_.download_size);
- std::memset(b->writableData(), '?', configuration_.download_size);
- b->append(configuration_.download_size);
-
- last_segment_ = suffix + producer_socket_->produceStream(
- content_name, std::move(b),
- !configuration_.multiphase_produce_, suffix);
- });
- }
+ /**
+ * @brief Produce datagram
+ */
+ void produceDatagram(const uint8_t *buffer, std::size_t buffer_size) const {
+ assert(producer_socket_);
- void cacheMiss(ProducerSocket &p, const Interest &interest) {
- unsatisfied_interests_.push_back(interest.getName().getSuffix());
- }
+ auto size = std::min(buffer_size, payload_size_max_);
- void onContentProduced(ProducerSocket &p, const std::error_code &err,
- uint64_t bytes_written) {
- p.setSocketOption(ProducerCallbacksOptions::CACHE_MISS,
- (ProducerInterestCallback)bind(
- &Impl::asyncProcessInterest, this,
- std::placeholders::_1, std::placeholders::_2));
- }
+ producer_socket_->produceDatagram(flow_name_, buffer, size);
+ }
- void produceError(const std::error_code &err) noexcept override {
- std::cerr << "Error from producer transport: " << err.message()
- << std::endl;
- producer_socket_->stop();
- io_service_.stop();
- }
+ /**
+ * @brief Create and setup the producer socket
+ */
+ int setup() {
+ int ret;
+ int production_protocol;
+ std::shared_ptr<Signer> signer = std::make_shared<VoidSigner>();
- int setup() {
- int ret;
- int production_protocol;
- std::shared_ptr<Signer> signer = std::make_shared<VoidSigner>();
-
- if (configuration_.secure_) {
- producer_socket_ = std::make_unique<P2PSecureProducerSocket>(
- configuration_.rtc_, configuration_.keystore_name,
- configuration_.keystore_password);
- } else {
if (!configuration_.rtc_) {
production_protocol = ProductionProtocolAlgorithms::BYTE_STREAM;
} else {
@@ -178,255 +101,466 @@ class HIperfServer::Impl : public ProducerSocket::Callback {
}
producer_socket_ = std::make_unique<ProducerSocket>(production_protocol);
- }
-
- if (producer_socket_->setSocketOption(
- ProducerCallbacksOptions::PRODUCER_CALLBACK, this) ==
- SOCKET_OPTION_NOT_SET) {
- std::cerr << "Failed to set producer callback." << std::endl;
- return ERROR_SETUP;
- }
-
- if (producer_socket_->setSocketOption(
- GeneralTransportOptions::MAKE_MANIFEST, configuration_.manifest) ==
- SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
- if (producer_socket_->setSocketOption(
- GeneralTransportOptions::HASH_ALGORITHM,
- configuration_.hash_algorithm_) == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
-
- if (producer_socket_->setSocketOption(PACKET_FORMAT,
- configuration_.packet_format_) ==
- SOCKET_OPTION_NOT_SET) {
- std::cerr << "ERROR -- Impossible to set the packet format." << std::endl;
- return ERROR_SETUP;
- }
+ if (producer_socket_->setSocketOption(
+ ProducerCallbacksOptions::PRODUCER_CALLBACK, this) ==
+ SOCKET_OPTION_NOT_SET) {
+ getOutputStream() << "Failed to set producer callback." << std::endl;
+ return ERROR_SETUP;
+ }
- if (!configuration_.passphrase.empty()) {
- signer = std::make_shared<SymmetricSigner>(CryptoSuite::HMAC_SHA256,
- configuration_.passphrase);
- }
+ if (producer_socket_->setSocketOption(
+ GeneralTransportOptions::HASH_ALGORITHM,
+ configuration_.hash_algorithm_) == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
- if (!configuration_.keystore_name.empty()) {
- signer = std::make_shared<AsymmetricSigner>(
- configuration_.keystore_name, configuration_.keystore_password);
- }
+ if (producer_socket_->setSocketOption(
+ GeneralTransportOptions::MANIFEST_MAX_CAPACITY,
+ configuration_.manifest_max_capacity_) == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
- producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER, signer);
+ if (producer_socket_->setSocketOption(PACKET_FORMAT,
+ configuration_.packet_format_) ==
+ SOCKET_OPTION_NOT_SET) {
+ getOutputStream() << "ERROR -- Impossible to set the packet format."
+ << std::endl;
+ return ERROR_SETUP;
+ }
- // Compute maximum payload size
- Packet::Format format = PayloadSize::getFormatFromName(
- configuration_.name.getName(), !configuration_.manifest);
- payload_size_max_ = PayloadSize(format).getPayloadSizeMax(
- configuration_.rtc_ ? RTC_HEADER_SIZE : 0,
- configuration_.fec_type_.empty() ? 0 : FEC_HEADER_MAX_SIZE,
- !configuration_.manifest ? signer->getSignatureFieldSize() : 0);
+ if (!configuration_.passphrase_.empty()) {
+ signer = std::make_shared<SymmetricSigner>(CryptoSuite::HMAC_SHA256,
+ configuration_.passphrase_);
+ }
- if (configuration_.payload_size_ > payload_size_max_) {
- std::cerr << "WARNING: Payload has size " << configuration_.payload_size_
- << ", maximum is " << payload_size_max_
- << ". Payload will be truncated to fit." << std::endl;
- }
+ if (!configuration_.keystore_name_.empty()) {
+ signer = std::make_shared<AsymmetricSigner>(
+ configuration_.keystore_name_, configuration_.keystore_password_);
+ }
- if (configuration_.rtc_) {
- ret = producer_socket_->setSocketOption(
- RtcTransportOptions::AGGREGATED_DATA,
- configuration_.aggregated_data_);
+ producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER,
+ signer);
+
+ // Compute maximum payload size
+ Packet::Format format = PayloadSize::getFormatFromPrefix(
+ configuration_.name_, !configuration_.manifest_max_capacity_);
+ payload_size_max_ = PayloadSize(format).getPayloadSizeMax(
+ configuration_.rtc_ ? RTC_HEADER_SIZE : 0,
+ configuration_.fec_type_.empty() ? 0 : FEC_HEADER_MAX_SIZE,
+ !configuration_.manifest_max_capacity_
+ ? signer->getSignatureFieldSize()
+ : 0);
+
+ if (configuration_.payload_size_ > payload_size_max_) {
+ getOutputStream() << "WARNING: Payload has size "
+ << configuration_.payload_size_ << ", maximum is "
+ << payload_size_max_
+ << ". Payload will be truncated to fit." << std::endl;
+ }
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
+ // Verifier for aggregated interests
+ std::shared_ptr<Verifier> verifier = std::make_shared<VoidVerifier>();
+ if (!configuration_.aggr_interest_passphrase_.empty()) {
+ verifier = std::make_unique<SymmetricVerifier>(
+ configuration_.aggr_interest_passphrase_);
}
- }
+ ret = producer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER,
+ verifier);
+ if (ret == SOCKET_OPTION_NOT_SET) return ERROR_SETUP;
- if (configuration_.rtc_) {
- ret = producer_socket_->setSocketOption(GeneralTransportOptions::FEC_TYPE,
- configuration_.fec_type_);
+ if (configuration_.rtc_) {
+ ret = producer_socket_->setSocketOption(
+ RtcTransportOptions::AGGREGATED_DATA,
+ configuration_.aggregated_data_);
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
- }
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
- producer_socket_->registerPrefix(configuration_.name);
- producer_socket_->connect();
- producer_socket_->start();
+ ret = producer_socket_->setSocketOption(
+ GeneralTransportOptions::FEC_TYPE, configuration_.fec_type_);
- if (configuration_.rtc_) {
- std::cout << "Running RTC producer: the prefix length will be ignored."
- " Use /128 by default in RTC mode"
- << std::endl;
- return ERROR_SUCCESS;
- }
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+ }
- if (!configuration_.virtual_producer) {
if (producer_socket_->setSocketOption(
GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
- configuration_.content_lifetime) == SOCKET_OPTION_NOT_SET) {
+ configuration_.content_lifetime_) == SOCKET_OPTION_NOT_SET) {
return ERROR_SETUP;
}
- if (producer_socket_->setSocketOption(
- GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 200000U) ==
- SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
- }
+ producer_socket_->registerPrefix(Prefix(flow_name_, 128));
+ producer_socket_->connect();
+ producer_socket_->start();
- if (producer_socket_->setSocketOption(
- GeneralTransportOptions::MAX_SEGMENT_SIZE,
- static_cast<uint32_t>(configuration_.payload_size_)) ==
- SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
+ if (configuration_.rtc_) {
+ return ERROR_SUCCESS;
}
- if (!configuration_.live_production) {
- produceContent(*producer_socket_, configuration_.name.getName(), 0);
+ if (!configuration_.virtual_producer_) {
+ if (producer_socket_->setSocketOption(
+ GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 200000U) ==
+ SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+
+ if (producer_socket_->setSocketOption(
+ GeneralTransportOptions::MAX_SEGMENT_SIZE,
+ static_cast<uint32_t>(configuration_.payload_size_)) ==
+ SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+
+ if (!configuration_.live_production_) {
+ produceContent(*producer_socket_, configuration_.name_.makeName(), 0);
+ } else {
+ ret = producer_socket_->setSocketOption(
+ ProducerCallbacksOptions::CACHE_MISS,
+ (ProducerInterestCallback)bind(
+ &ProducerContext::asyncProcessInterest, this,
+ std::placeholders::_1, std::placeholders::_2));
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+ }
} else {
ret = producer_socket_->setSocketOption(
+ GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 0U);
+
+ if (ret == SOCKET_OPTION_NOT_SET) {
+ return ERROR_SETUP;
+ }
+
+ ret = producer_socket_->setSocketOption(
ProducerCallbacksOptions::CACHE_MISS,
- (ProducerInterestCallback)bind(&Impl::asyncProcessInterest, this,
- std::placeholders::_1,
- std::placeholders::_2));
+ (ProducerInterestCallback)bind(
+ &ProducerContext::virtualProcessInterest, this,
+ std::placeholders::_1, std::placeholders::_2));
if (ret == SOCKET_OPTION_NOT_SET) {
return ERROR_SETUP;
}
}
- } else {
- ret = producer_socket_->setSocketOption(
- GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 0U);
+ ret = producer_socket_->setSocketOption(
+ ProducerCallbacksOptions::CONTENT_PRODUCED,
+ (ProducerContentCallback)bind(
+ &ProducerContext::onContentProduced, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3));
if (ret == SOCKET_OPTION_NOT_SET) {
return ERROR_SETUP;
}
- ret = producer_socket_->setSocketOption(
- ProducerCallbacksOptions::CACHE_MISS,
- (ProducerInterestCallback)bind(&Impl::virtualProcessInterest, this,
- std::placeholders::_1,
- std::placeholders::_2));
+ return ERROR_SUCCESS;
+ }
- if (ret == SOCKET_OPTION_NOT_SET) {
- return ERROR_SETUP;
+ int run() {
+ getOutputStream() << "started to serve consumers with name " << flow_name_
+ << std::endl;
+ return ERROR_SUCCESS;
+ }
+
+ void stop() {
+ getOutputStream() << "stopped to serve consumers" << std::endl;
+ producer_socket_->stop();
+ }
+
+ private:
+ /**
+ * @brief Produce an existing content object. Set the name as the
+ * interest.
+ */
+ void virtualProcessInterest(ProducerSocket &p, const Interest &interest) {
+ content_objects_[content_objects_index_ & kmask()]->setName(
+ interest.getName());
+ p.produce(*content_objects_[content_objects_index_++ & kmask()]);
+ }
+
+ /**
+ * @brief Create and produce a buffer of configuration_.download_size_
+ * length.
+ */
+ void produceContent(ProducerSocket &p, const Name &content_name,
+ uint32_t suffix) const {
+ uint32_t total;
+
+ auto b = utils::MemBuf::create(configuration_.download_size_);
+ std::memset(b->writableData(), '?', configuration_.download_size_);
+ b->append(configuration_.download_size_);
+
+ utils::SteadyTime::TimePoint t0 = utils::SteadyTime::Clock::now();
+ total = p.produceStream(content_name, std::move(b),
+ !configuration_.multiphase_produce_, suffix);
+ utils::SteadyTime::TimePoint t1 = utils::SteadyTime::Clock::now();
+
+ Logger() << "Written " << total
+ << " data packets in output buffer (Segmentation time: "
+ << utils::SteadyTime::getDurationUs(t0, t1).count() << " us)"
+ << std::endl;
+ }
+
+ /**
+ * @brief Synchronously produce content upon reception of one interest
+ */
+ void processInterest(ProducerSocket &p, const Interest &interest) const {
+ p.setSocketOption(ProducerCallbacksOptions::CACHE_MISS,
+ (ProducerInterestCallback)VOID_HANDLER);
+ p.setSocketOption(GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
+ configuration_.content_lifetime_);
+
+ produceContent(p, interest.getName(), interest.getName().getSuffix());
+ Logger() << "Received interest " << interest.getName().getSuffix()
+ << std::endl;
+ }
+
+ /**
+ * @brief Async create and produce a buffer of
+ * configuration_.download_size_ length.
+ */
+ void produceContentAsync(ProducerSocket &p, Name content_name,
+ uint32_t suffix) {
+ parent_.produce_thread_.add([this, suffix, content_name, &p]() {
+ auto b = utils::MemBuf::create(configuration_.download_size_);
+ std::memset(b->writableData(), '?', configuration_.download_size_);
+ b->append(configuration_.download_size_);
+
+ last_segment_ =
+ suffix + p.produceStream(content_name, std::move(b),
+ !configuration_.multiphase_produce_,
+ suffix);
+ });
+ }
+
+ /**
+ * @brief Asynchronously produce content upon reception of one interest
+ */
+ void asyncProcessInterest(ProducerSocket &p, const Interest &interest) {
+ p.setSocketOption(ProducerCallbacksOptions::CACHE_MISS,
+ (ProducerInterestCallback)bind(
+ &ProducerContext::cacheMiss, this,
+ std::placeholders::_1, std::placeholders::_2));
+ p.setSocketOption(GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
+ configuration_.content_lifetime_);
+ uint32_t suffix = interest.getName().getSuffix();
+
+ if (suffix == 0) {
+ last_segment_ = 0;
+ unsatisfied_interests_.clear();
+ }
+
+ // The suffix will either come from the received interest or will be set
+ // to the smallest suffix of a previous interest not satisfied
+ if (!unsatisfied_interests_.empty()) {
+ auto it = std::lower_bound(unsatisfied_interests_.begin(),
+ unsatisfied_interests_.end(), last_segment_);
+ if (it != unsatisfied_interests_.end()) {
+ suffix = *it;
+ }
+ unsatisfied_interests_.erase(unsatisfied_interests_.begin(), it);
}
+
+ getOutputStream() << " Received interest "
+ << interest.getName().getSuffix()
+ << ", starting production at " << suffix << end_mod_
+ << std::endl;
+ getOutputStream() << unsatisfied_interests_.size()
+ << " interests still unsatisfied" << end_mod_
+ << std::endl;
+ produceContentAsync(p, interest.getName(), suffix);
}
- ret = producer_socket_->setSocketOption(
- ProducerCallbacksOptions::CONTENT_PRODUCED,
- (ProducerContentCallback)bind(
- &Impl::onContentProduced, this, std::placeholders::_1,
- std::placeholders::_2, std::placeholders::_3));
+ /**
+ * @brief Register cache miss events
+ */
+ void cacheMiss([[maybe_unused]] const ProducerSocket &p,
+ const Interest &interest) {
+ unsatisfied_interests_.push_back(interest.getName().getSuffix());
+ }
- return ERROR_SUCCESS;
+ /**
+ * @brief When content is produced, set cache miss callback so that we can
+ * register any cache miss happening after the production.
+ */
+ void onContentProduced(ProducerSocket &p,
+ [[maybe_unused]] const std::error_code &err,
+ [[maybe_unused]] uint64_t bytes_written) {
+ p.setSocketOption(ProducerCallbacksOptions::CACHE_MISS,
+ (ProducerInterestCallback)bind(
+ &ProducerContext::asyncProcessInterest, this,
+ std::placeholders::_1, std::placeholders::_2));
+ }
+
+ /**
+ * @brief Internal producer error. When this callback is triggered
+ * something important happened. Here we stop the program.
+ */
+ void produceError(const std::error_code &err) noexcept override {
+ getOutputStream() << "Error from producer transport: " << err.message()
+ << std::endl;
+ parent_.stop();
+ }
+
+ // Members initialized in constructor
+ std::vector<ContentObject::Ptr> content_objects_;
+
+ // Members initialized by in-class initializer
+ std::vector<uint32_t> unsatisfied_interests_;
+ std::uint32_t last_segment_{0};
+ std::unique_ptr<ProducerSocket> producer_socket_{nullptr};
+ std::uint16_t content_objects_index_{0};
+ std::size_t payload_size_max_{0};
+ };
+
+ public:
+ explicit Impl(const hiperf::ServerConfiguration &conf) : config_(conf) {
+#ifndef _WIN32
+ if (config_.interactive_) {
+ input_.assign(::dup(STDIN_FILENO));
+ }
+#endif
+
+ std::memset(rtc_payload_.data(), 'X', rtc_payload_.size());
+ }
+
+ ~Impl() = default;
+
+ int setup() {
+ int ret = ensureFlows(config_.name_, config_.parallel_flows_);
+ if (ret != ERROR_SUCCESS) {
+ return ret;
+ }
+
+ producer_contexts_.reserve(config_.parallel_flows_);
+ for (uint32_t i = 0; i < config_.parallel_flows_; i++) {
+ auto &ctx = producer_contexts_.emplace_back(*this, i);
+ ret = ctx.setup();
+
+ if (ret) {
+ break;
+ }
+ }
+
+ return ret;
}
void receiveStream() {
socket_.async_receive_from(
- asio::buffer(recv_buffer_.first, recv_buffer_.second), remote_,
- [this](const std::error_code &ec, std::size_t length) {
+ asio::buffer(recv_buffer_.writableData(), recv_buffer_.capacity()),
+ remote_, [this](const std::error_code &ec, std::size_t length) {
if (ec) return;
- sendRTCContentFromStream(recv_buffer_.first, length);
+ sendRTCContentFromStream(recv_buffer_.writableData(), length);
receiveStream();
});
}
- void sendRTCContentFromStream(uint8_t *buff, std::size_t len) {
- auto payload =
- content_objects_[content_objects_index_++ & mask_]->getPayload();
+ void sendRTCContentFromStream(const uint8_t *buff, std::size_t len) {
// 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 = utils::SystemTime::nowMs().count();
+ auto now = utils::SystemTime::nowMs().count();
- uint8_t *start = (uint8_t *)payload->writableData();
+ auto start = rtc_payload_.data();
std::memcpy(start, &now, sizeof(uint64_t));
std::memcpy(start + sizeof(uint64_t), buff, len);
- producer_socket_->produceDatagram(flow_name_, start,
- len + sizeof(uint64_t));
+
+ for (const auto &producer_context : producer_contexts_) {
+ producer_context.produceDatagram(start, len + sizeof(uint64_t));
+ }
}
void sendRTCContentObjectCallback(const std::error_code &ec) {
if (ec) return;
rtc_timer_.expires_from_now(
- configuration_.production_rate_.getMicrosecondsForPacket(
- configuration_.payload_size_));
+ config_.production_rate_.getMicrosecondsForPacket(
+ config_.payload_size_));
rtc_timer_.async_wait(std::bind(&Impl::sendRTCContentObjectCallback, this,
std::placeholders::_1));
- auto payload =
- content_objects_[content_objects_index_++ & mask_]->getPayload();
+
+ auto start = rtc_payload_.data();
// 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 = utils::SystemTime::nowMs().count();
-
- std::memcpy(payload->writableData(), &now, sizeof(uint64_t));
+ auto now = utils::SystemTime::nowMs().count();
+ std::memcpy(start, &now, sizeof(uint64_t));
- producer_socket_->produceDatagram(flow_name_, payload->data(),
- payload->length() < payload_size_max_
- ? payload->length()
- : payload_size_max_);
+ for (const auto &producer_context : producer_contexts_) {
+ producer_context.produceDatagram(start, config_.payload_size_);
+ }
}
void sendRTCContentObjectCallbackWithTrace(const 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;
+ std::size_t packet_len = config_.trace_[config_.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 = utils::SystemTime::nowMs().count();
- std::memcpy(payload->writableData(), &now, sizeof(uint64_t));
+ auto now = utils::SystemTime::nowMs().count();
+ auto start = rtc_payload_.data();
+ std::memcpy(start, &now, sizeof(uint64_t));
- if (packet_len > payload->length()) packet_len = payload->length();
- if (packet_len > payload_size_max_) packet_len = payload_size_max_;
+ if (packet_len > config_.payload_size_) {
+ packet_len = config_.payload_size_;
+ }
- producer_socket_->produceDatagram(flow_name_, payload->data(), packet_len);
+ for (const auto &producer_context : producer_contexts_) {
+ producer_context.produceDatagram(start, packet_len);
+ }
- uint32_t next_index = configuration_.trace_index_ + 1;
+ uint32_t next_index = config_.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;
+ if (next_index < config_.trace_.size()) {
+ schedule_next = config_.trace_[next_index].timestamp -
+ config_.trace_[config_.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();
+ config_.trace_index_ = (config_.trace_index_ + 1) % config_.trace_.size();
rtc_timer_.expires_from_now(std::chrono::microseconds(schedule_next));
rtc_timer_.async_wait(
std::bind(&Impl::sendRTCContentObjectCallbackWithTrace, this,
std::placeholders::_1));
}
+ int parseTraceFile() {
+ std::ifstream trace(config_.trace_file_);
+ if (trace.fail()) {
+ return -1;
+ }
+ std::string line;
+ while (std::getline(trace, line)) {
+ std::istringstream iss(line);
+ hiperf::packet_t packet;
+ iss >> packet.timestamp >> packet.size;
+ config_.trace_.push_back(packet);
+ }
+ return 0;
+ }
+
#ifndef _WIN32
void handleInput(const std::error_code &error, std::size_t length) {
if (error) {
- producer_socket_->stop();
- io_service_.stop();
+ stop();
}
if (rtc_running_) {
- std::cout << "stop real time content production" << std::endl;
+ Logger() << "stop real time content production" << std::endl;
rtc_running_ = false;
rtc_timer_.cancel();
} else {
- std::cout << "start real time content production" << std::endl;
+ Logger() << "start real time content production" << std::endl;
rtc_running_ = true;
rtc_timer_.expires_from_now(
- configuration_.production_rate_.getMicrosecondsForPacket(
- configuration_.payload_size_));
+ config_.production_rate_.getMicrosecondsForPacket(
+ config_.payload_size_));
rtc_timer_.async_wait(std::bind(&Impl::sendRTCContentObjectCallback, this,
std::placeholders::_1));
}
@@ -439,46 +573,33 @@ class HIperfServer::Impl : public ProducerSocket::Callback {
}
#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);
- hiperf::packet_t packet;
- iss >> packet.timestamp >> packet.size;
- configuration_.trace_.push_back(packet);
+ void stop() {
+ for (auto &producer_context : producer_contexts_) {
+ producer_context.stop();
}
- return 0;
+
+ io_service_.stop();
}
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();
- io_service_.stop();
- });
+ signals_.async_wait(
+ [this](const std::error_code &, const int &) { stop(); });
- if (configuration_.rtc_) {
-#ifndef _WIN32
- if (configuration_.interactive_) {
+ if (config_.rtc_) {
+ if (config_.interactive_) {
asio::async_read_until(
input_, input_buffer_, '\n',
std::bind(&Impl::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;
+ } else if (config_.trace_based_) {
+ Logger() << "trace-based mode enabled" << std::endl;
+ if (config_.trace_file_ == nullptr) {
+ Logger() << "cannot find the trace file" << std::endl;
return ERROR_SETUP;
}
if (parseTraceFile() < 0) {
- std::cout << "cannot parse the trace file" << std::endl;
+ Logger() << "cannot parse the trace file" << std::endl;
return ERROR_SETUP;
}
rtc_running_ = true;
@@ -486,31 +607,26 @@ class HIperfServer::Impl : public ProducerSocket::Callback {
rtc_timer_.async_wait(
std::bind(&Impl::sendRTCContentObjectCallbackWithTrace, this,
std::placeholders::_1));
- } else if (configuration_.input_stream_mode_) {
+ } else if (config_.input_stream_mode_) {
rtc_running_ = true;
// create socket
remote_ = asio::ip::udp::endpoint(
- asio::ip::address::from_string("127.0.0.1"), configuration_.port_);
+ asio::ip::address::from_string("127.0.0.1"), config_.port_);
socket_.open(asio::ip::udp::v4());
socket_.bind(remote_);
- recv_buffer_.first = (uint8_t *)malloc(HIPERF_MTU);
- recv_buffer_.second = HIPERF_MTU;
receiveStream();
} else {
rtc_running_ = true;
rtc_timer_.expires_from_now(
- configuration_.production_rate_.getMicrosecondsForPacket(
- configuration_.payload_size_));
+ config_.production_rate_.getMicrosecondsForPacket(
+ config_.payload_size_));
rtc_timer_.async_wait(std::bind(&Impl::sendRTCContentObjectCallback,
this, std::placeholders::_1));
}
-#else
- rtc_timer_.expires_from_now(
- configuration_.production_rate_.getMicrosecondsForPacket(
- configuration_.payload_size_));
- rtc_timer_.async_wait(std::bind(&Impl::sendRTCContentObjectCallback, this,
- std::placeholders::_1));
-#endif
+ }
+
+ for (auto &producer_context : producer_contexts_) {
+ producer_context.run();
}
io_service_.run();
@@ -518,49 +634,31 @@ class HIperfServer::Impl : public ProducerSocket::Callback {
return ERROR_SUCCESS;
}
+ ServerConfiguration &getConfig() { return config_; }
+
private:
- hiperf::ServerConfiguration configuration_;
+ // Variables initialized by the constructor.
+ ServerConfiguration config_;
+
+ // Variable initialized in the in-class initializer list.
asio::io_service io_service_;
- asio::signal_set signals_;
- asio::steady_timer rtc_timer_;
- std::vector<uint32_t> unsatisfied_interests_;
- std::vector<std::shared_ptr<ContentObject>> content_objects_;
- std::uint16_t content_objects_index_;
- std::uint16_t mask_;
- std::uint32_t last_segment_;
- std::unique_ptr<ProducerSocket> producer_socket_;
+ asio::signal_set signals_{io_service_};
+ asio::steady_timer rtc_timer_{io_service_};
+ asio::posix::stream_descriptor input_{io_service_};
+ asio::ip::udp::socket socket_{io_service_};
+ std::vector<ProducerContext> producer_contexts_;
::utils::EventThread produce_thread_;
- std::size_t payload_size_max_;
-#ifndef _WIN32
- asio::posix::stream_descriptor input_;
asio::streambuf input_buffer_;
- bool rtc_running_;
- Name flow_name_;
- asio::ip::udp::socket socket_;
+ bool rtc_running_{false};
asio::ip::udp::endpoint remote_;
- std::pair<uint8_t *, std::size_t> recv_buffer_;
-#endif
+ utils::MemBuf recv_buffer_{utils::MemBuf::CREATE, HIPERF_MTU};
+ std::array<uint8_t, HIPERF_MTU> rtc_payload_;
};
-HIperfServer::HIperfServer(const ServerConfiguration &conf) {
- impl_ = new Impl(conf);
-}
-
-HIperfServer::HIperfServer(HIperfServer &&other) {
- impl_ = other.impl_;
- other.impl_ = nullptr;
-}
-
-HIperfServer &HIperfServer::operator=(HIperfServer &&other) {
- if (this != &other) {
- impl_ = other.impl_;
- other.impl_ = nullptr;
- }
-
- return *this;
-}
+HIperfServer::HIperfServer(const ServerConfiguration &conf)
+ : impl_(std::make_unique<Impl>(conf)) {}
-HIperfServer::~HIperfServer() { delete impl_; }
+HIperfServer::~HIperfServer() = default;
int HIperfServer::setup() { return impl_->setup(); }
diff --git a/apps/hiperf/src/server.h b/apps/hiperf/src/server.h
index 73ac72123..d7420da48 100644
--- a/apps/hiperf/src/server.h
+++ b/apps/hiperf/src/server.h
@@ -21,9 +21,7 @@ namespace hiperf {
class HIperfServer {
public:
- HIperfServer(const ServerConfiguration &conf);
- HIperfServer(HIperfServer &&other);
- HIperfServer &operator=(HIperfServer &&other);
+ explicit HIperfServer(const ServerConfiguration &conf);
~HIperfServer();
int setup();
@@ -31,7 +29,7 @@ class HIperfServer {
private:
class Impl;
- Impl *impl_;
+ std::unique_ptr<Impl> impl_;
};
} // namespace hiperf \ 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
index 1741aedc6..0741099df 100644
--- a/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h
@@ -23,8 +23,16 @@ extern "C" {
#ifndef ASIO_STANDALONE
#define ASIO_STANDALONE 1
#endif
+
+#ifdef __APPLE__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wshorten-64-to-32"
+#endif
#include <asio.hpp>
#include <asio/steady_timer.hpp>
+#ifdef __APPLE__
+#pragma clang diagnostic pop
+#endif
#include <functional>
#include <thread>
#include <unordered_map>
diff --git a/apps/http-proxy/includes/hicn/http-proxy/http_session.h b/apps/http-proxy/includes/hicn/http-proxy/http_session.h
index ee9380a8c..43d10e156 100644
--- a/apps/http-proxy/includes/hicn/http-proxy/http_session.h
+++ b/apps/http-proxy/includes/hicn/http-proxy/http_session.h
@@ -17,7 +17,14 @@
#include <hicn/transport/core/packet.h>
+#ifdef __APPLE__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wshorten-64-to-32"
+#endif
#include <asio.hpp>
+#ifdef __APPLE__
+#pragma clang diagnostic pop
+#endif
#include <deque>
#include <functional>
diff --git a/apps/http-proxy/src/icn_receiver.cc b/apps/http-proxy/src/icn_receiver.cc
index 954861e3a..f15851915 100644
--- a/apps/http-proxy/src/icn_receiver.cc
+++ b/apps/http-proxy/src/icn_receiver.cc
@@ -37,8 +37,8 @@ AsyncConsumerProducer::AsyncConsumerProducer(
producer_socket_(),
ip_address_(origin_address),
port_(origin_port),
- cache_size_(std::stoul(cache_size)),
- mtu_(std::stoul(mtu)),
+ cache_size_((uint32_t)std::stoul(cache_size)),
+ mtu_((uint32_t)std::stoul(mtu)),
request_counter_(0),
connector_(io_service_, ip_address_, port_,
std::bind(&AsyncConsumerProducer::publishContent, this,
@@ -59,7 +59,7 @@ AsyncConsumerProducer::AsyncConsumerProducer(
}
ret = producer_socket_.setSocketOption(
- interface::GeneralTransportOptions::MAKE_MANIFEST, manifest);
+ interface::GeneralTransportOptions::MANIFEST_MAX_CAPACITY, manifest);
if (ret != SOCKET_OPTION_SET) {
TRANSPORT_LOG_WARNING << "Warning: impossible to enable signatures.";
diff --git a/apps/ping/src/ping_client.cc b/apps/ping/src/ping_client.cc
index 0217f2f8c..2371e4453 100644
--- a/apps/ping/src/ping_client.cc
+++ b/apps/ping/src/ping_client.cc
@@ -13,6 +13,7 @@
* limitations under the License.
*/
+#include <hicn/transport/auth/signer.h>
#include <hicn/transport/auth/verifier.h>
#include <hicn/transport/core/global_object_pool.h>
#include <hicn/transport/core/interest.h>
@@ -39,12 +40,14 @@ typedef auth::AsymmetricVerifier Verifier;
class Configuration {
public:
+ uint64_t num_int_manifest_suffixes_;
uint64_t interestLifetime_;
uint64_t pingInterval_;
uint64_t maxPing_;
uint64_t first_suffix_;
std::string name_;
std::string certificate_;
+ std::string passphrase_;
uint16_t srcPort_;
uint16_t dstPort_;
bool verbose_;
@@ -59,9 +62,10 @@ class Configuration {
uint8_t ttl_;
Configuration() {
- interestLifetime_ = 500; // ms
- pingInterval_ = 1000000; // us
- maxPing_ = 10; // number of interests
+ num_int_manifest_suffixes_ = 0; // Number of suffixes in interest manifest
+ interestLifetime_ = 500; // ms
+ pingInterval_ = 1000000; // us
+ maxPing_ = 10; // number of interests
first_suffix_ = 0;
name_ = "b001::1"; // string
srcPort_ = 9695;
@@ -96,6 +100,13 @@ class Client : interface::Portal::TransportCallback {
if (!c->certificate_.empty()) {
verifier_.useCertificate(c->certificate_);
}
+
+ // If interst manifest, sign it
+ if (c->num_int_manifest_suffixes_ != 0) {
+ assert(!c->passphrase_.empty());
+ signer_ = std::make_unique<auth::SymmetricSigner>(
+ auth::CryptoSuite::HMAC_SHA256, c->passphrase_);
+ }
}
virtual ~Client() {}
@@ -142,6 +153,7 @@ class Client : interface::Portal::TransportCallback {
if (config_->verbose_) {
std::cout << "<<< recevied object. " << std::endl;
std::cout << "<<< interest name: " << interest.getName()
+ << " (n_suffixes=" << interest.numberOfSuffixes() << ")"
<< " src port: " << interest.getSrcPort()
<< " dst port: " << interest.getDstPort()
<< " flags: " << interest.printFlags() << std::endl;
@@ -221,15 +233,18 @@ class Client : interface::Portal::TransportCallback {
const Name interest_name(config_->name_, (uint32_t)sequence_number_);
hicn_format_t format;
if (interest_name.getAddressFamily() == AF_INET) {
- format = HF_INET_TCP;
+ format = signer_ ? HF_INET_TCP_AH : HF_INET_TCP;
} else {
- format = HF_INET6_TCP;
+ format = signer_ ? HF_INET6_TCP_AH : HF_INET6_TCP;
}
- auto interest = std::make_shared<Interest>(interest_name, format);
+ size_t additional_header_size = 0;
+ if (signer_) additional_header_size = signer_->getSignatureFieldSize();
+ auto interest = std::make_shared<Interest>(interest_name, format,
+ additional_header_size);
interest->setLifetime(uint32_t(config_->interestLifetime_));
- interest->resetFlags();
+ if (!signer_) interest->resetFlags();
if (config_->open_ || config_->always_syn_) {
if (state_ == SYN_STATE) {
@@ -244,13 +259,21 @@ class Client : interface::Portal::TransportCallback {
interest->setSrcPort(config_->srcPort_);
interest->setDstPort(config_->dstPort_);
interest->setTTL(config_->ttl_);
+ uint64_t seq_offset = 1;
+ while (seq_offset <= config_->num_int_manifest_suffixes_ &&
+ sequence_number_ + seq_offset < config_->maxPing_) {
+ interest->appendSuffix(sequence_number_ + seq_offset);
+ seq_offset++;
+ }
if (config_->verbose_) {
std::cout << ">>> send interest " << interest->getName()
<< " src port: " << interest->getSrcPort()
<< " dst port: " << interest->getDstPort()
<< " flags: " << interest->printFlags()
- << " TTL: " << (int)interest->getTTL() << std::endl;
+ << " TTL: " << (int)interest->getTTL()
+ << " suffixes in manifest: "
+ << config_->num_int_manifest_suffixes_ << std::endl;
} else if (!config_->quiet_) {
std::cout << ">>> send interest " << interest->getName() << std::endl;
}
@@ -264,11 +287,16 @@ class Client : interface::Portal::TransportCallback {
if (!config_->quiet_) std::cout << std::endl;
send_timestamps_[sequence_number_] = utils::SteadyTime::now();
+ for (uint64_t i = 1; i < seq_offset; i++)
+ send_timestamps_[sequence_number_ + i] = utils::SteadyTime::now();
- portal_.sendInterest(std::move(interest));
+ interest->encodeSuffixes();
+ if (signer_) signer_->signPacket(interest.get());
- sequence_number_++;
- sent_++;
+ portal_.sendInterest(interest, interest->getLifetime());
+
+ sequence_number_ += seq_offset;
+ sent_ += seq_offset;
if (sent_ < config_->maxPing_) {
this->timer_->expires_from_now(
@@ -314,6 +342,7 @@ class Client : interface::Portal::TransportCallback {
std::unique_ptr<asio::steady_timer> timer_;
Configuration *config_;
Verifier verifier_;
+ std::unique_ptr<auth::Signer> signer_;
};
void help() {
@@ -327,6 +356,12 @@ void help() {
std::cout << "-s <val> sorce port (default 9695)" << std::endl;
std::cout << "-d <val> destination port (default 8080)" << std::endl;
std::cout << "-t <val> set packet ttl (default 64)" << std::endl;
+ std::cout << "-a <val> <pass> set the passphrase and the number of "
+ "suffixes in interest manifest (default 0);"
+ << std::endl;
+ std::cout << " e.g. '-m 6 -a -2' sends two interest (0 and "
+ "3) with 2 suffixes each (1,2 and 4,5 respectively)"
+ << std::endl;
std::cout << "-O open tcp connection (three way handshake) "
"(default false)"
<< std::endl;
@@ -362,6 +397,8 @@ int main(int argc, char *argv[]) {
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
+ transport::interface::global_config::GlobalConfigInterface global_conf;
+
Configuration *c = new Configuration();
int opt;
std::string producer_certificate = "";
@@ -370,8 +407,13 @@ int main(int argc, char *argv[]) {
transport::interface::global_config::IoModuleConfiguration io_config;
io_config.name = "hicnlightng_module";
- while ((opt = getopt(argc, argv, "j::t:i:m:s:d:n:l:f:c:SAOqVDHz:F:")) != -1) {
+ while ((opt = getopt(argc, argv, "a:j::t:i:m:s:d:n:l:f:c:SAOqVDHz:F:")) !=
+ -1) {
switch (opt) {
+ case 'a':
+ c->num_int_manifest_suffixes_ = std::stoi(optarg);
+ c->passphrase_ = argv[optind];
+ break;
case 't':
c->ttl_ = (uint8_t)std::stoi(optarg);
break;
@@ -447,7 +489,7 @@ int main(int argc, char *argv[]) {
/**
* Parse config file
*/
- transport::interface::global_config::parseConfigurationFile(conf_file);
+ global_conf.parseConfigurationFile(conf_file);
auto ping = std::make_unique<Client>(c);
@@ -456,7 +498,8 @@ int main(int argc, char *argv[]) {
auto t1 = std::chrono::steady_clock::now();
std::cout << "Elapsed time: "
- << utils::SteadyTime::getDurationUs(t0, t1).count() << std::endl;
+ << utils::SteadyTime::getDurationMs(t0, t1).count() << "ms"
+ << std::endl;
#ifdef _WIN32
WSACleanup();
diff --git a/apps/ping/src/ping_server.cc b/apps/ping/src/ping_server.cc
index 3ffbc7325..dd7d23b5e 100644
--- a/apps/ping/src/ping_server.cc
+++ b/apps/ping/src/ping_server.cc
@@ -22,6 +22,7 @@
#endif
#include <hicn/transport/auth/signer.h>
+#include <hicn/transport/auth/verifier.h>
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/core/interest.h>
#include <hicn/transport/interfaces/global_conf_interface.h>
@@ -42,7 +43,8 @@ class CallbackContainer {
public:
CallbackContainer(const Name &prefix, uint32_t object_size, bool verbose,
bool dump, bool quite, bool flags, bool reset, uint8_t ttl,
- auth::Signer *signer, bool sign, uint32_t lifetime)
+ auth::Signer *signer, bool sign, std::string passphrase,
+ 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),
@@ -55,8 +57,11 @@ class CallbackContainer {
ttl_(ttl),
signer_(signer),
sign_(sign) {
- core::Packet::Format format;
+ // Verifier for interest manifests
+ if (!passphrase.empty())
+ verifier_ = std::make_unique<auth::SymmetricVerifier>(passphrase);
+ core::Packet::Format format;
if (prefix.getAddressFamily() == AF_INET) {
format = core::Packet::Format::HF_INET_TCP;
if (sign_) {
@@ -76,14 +81,28 @@ class CallbackContainer {
}
}
- void processInterest(ProducerSocket &p, const Interest &interest,
+ void processInterest(ProducerSocket &p, Interest &interest,
uint32_t lifetime) {
+ if (verifier_ && interest.hasManifest()) {
+ auto t0 = utils::SteadyTime::now();
+ if (verifier_->verifyPacket(&interest)) {
+ auto t1 = utils::SteadyTime::now();
+ auto dt = utils::SteadyTime::getDurationUs(t0, t1);
+ std::cout << "Verification time: " << dt.count() << std::endl;
+ std::cout << "<<< Signature Ok." << std::endl;
+ } else {
+ std::cout << "<<< Signature verification failed!" << std::endl;
+ }
+ }
+
if (verbose_) {
std::cout << "<<< received interest " << interest.getName()
<< " src port: " << interest.getSrcPort()
<< " dst port: " << interest.getDstPort()
<< " flags: " << interest.printFlags()
- << "TTL: " << (int)interest.getTTL() << std::endl;
+ << "TTL: " << (int)interest.getTTL()
+ << " suffixes in manifest: " << interest.numberOfSuffixes()
+ << std::endl;
} else if (!quite_) {
std::cout << "<<< received interest " << interest.getName() << std::endl;
}
@@ -97,54 +116,74 @@ class CallbackContainer {
if (interest.testRst()) {
std::cout << "!!!got a reset, I don't reply" << std::endl;
} else {
- auto &content_object = content_objects_[content_objects_index_++ & mask_];
-
- content_object->setName(interest.getName());
- content_object->setLifetime(lifetime);
- content_object->setLocator(interest.getLocator());
- content_object->setSrcPort(interest.getDstPort());
- content_object->setDstPort(interest.getSrcPort());
- content_object->setTTL(ttl_);
-
- if (!sign_) {
- content_object->resetFlags();
- }
-
- if (flags_) {
- if (interest.testSyn()) {
- content_object->setSyn();
- content_object->setAck();
- } else if (interest.testAck()) {
- content_object->setAck();
- } // here I may need to handle the FIN flag;
- } else if (reset_) {
- content_object->setRst();
- }
-
- if (verbose_) {
- std::cout << ">>> send object " << content_object->getName()
- << " src port: " << content_object->getSrcPort()
- << " dst port: " << content_object->getDstPort()
- << " flags: " << content_object->printFlags()
- << " TTL: " << (int)content_object->getTTL() << std::endl;
- } else if (!quite_) {
- std::cout << ">>> send object " << content_object->getName()
- << std::endl;
- }
-
- if (dump_) {
- std::cout << "----- object dump -----" << std::endl;
- content_object->dump();
- std::cout << "-----------------------" << std::endl;
- }
+ uint32_t *suffix = interest.firstSuffix();
+ uint32_t n_suffixes_in_manifest = interest.numberOfSuffixes();
+ uint32_t *request_bitmap = interest.getRequestBitmap();
+ if (!interest.isValid()) throw std::runtime_error("Bad interest format");
+
+ Name name = interest.getName();
+ uint32_t pos = 0; // Position of current suffix in manifest
+ do {
+ // If suffix can be processed, i.e. no manifest with bitmap excluding it
+ if (!interest.hasManifest() || is_bit_set(request_bitmap, pos)) {
+ auto &content_object =
+ content_objects_[content_objects_index_++ & mask_];
+
+ content_object->setName(interest.getName());
+ content_object->setLifetime(lifetime);
+ content_object->setLocator(interest.getLocator());
+ content_object->setSrcPort(interest.getDstPort());
+ content_object->setDstPort(interest.getSrcPort());
+ content_object->setTTL(ttl_);
+
+ if (!sign_) {
+ content_object->resetFlags();
+ }
+
+ if (flags_) {
+ if (interest.testSyn()) {
+ content_object->setSyn();
+ content_object->setAck();
+ } else if (interest.testAck()) {
+ content_object->setAck();
+ } // here I may need to handle the FIN flag;
+ } else if (reset_) {
+ content_object->setRst();
+ }
+
+ if (verbose_) {
+ std::cout << ">>> send object " << content_object->getName()
+ << " src port: " << content_object->getSrcPort()
+ << " dst port: " << content_object->getDstPort()
+ << " flags: " << content_object->printFlags()
+ << " TTL: " << (int)content_object->getTTL() << std::endl;
+ } else if (!quite_) {
+ std::cout << ">>> send object " << content_object->getName()
+ << std::endl;
+ }
+
+ if (dump_) {
+ std::cout << "----- object dump -----" << std::endl;
+ content_object->dump();
+ std::cout << "-----------------------" << std::endl;
+ }
+
+ if (sign_ && signer_) {
+ signer_->signPacket(content_object.get());
+ }
+
+ p.produce(*content_object);
+ }
+
+ if (interest.hasManifest()) {
+ uint32_t seq = *suffix;
+ suffix++;
+
+ interest.setName(name.setSuffix(seq));
+ }
+ } while (pos++ < n_suffixes_in_manifest);
if (!quite_) std::cout << std::endl;
-
- if (sign_ && signer_) {
- signer_->signPacket(content_object.get());
- }
-
- p.produce(*content_object);
}
}
@@ -161,6 +200,7 @@ class CallbackContainer {
uint8_t ttl_;
auth::Signer *signer_;
bool sign_;
+ std::unique_ptr<auth::Verifier> verifier_;
};
void help() {
@@ -199,6 +239,7 @@ void help() {
}
int main(int argc, char **argv) {
+ transport::interface::global_config::GlobalConfigInterface global_conf;
#ifdef _WIN32
WSADATA wsaData = {0};
WSAStartup(MAKEWORD(2, 2), &wsaData);
@@ -216,6 +257,7 @@ int main(int argc, char **argv) {
uint8_t ttl = 64;
std::string keystore_path = "./rsa_crypto_material.p12";
std::string keystore_password = "cisco";
+ std::string passphrase = "";
bool sign = false;
uint32_t data_lifetime = default_values::content_object_expiry_time;
@@ -225,11 +267,14 @@ int main(int argc, char **argv) {
int opt;
#ifndef _WIN32
- while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDdHk:p:z:F:")) != -1) {
+ while ((opt = getopt(argc, argv, "a:s:n:t:l:qfrVDdHk:p:z:F:")) != -1) {
#else
while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDHk:p:z:F:")) != -1) {
#endif
switch (opt) {
+ case 'a':
+ passphrase = optarg;
+ break;
case 's':
object_size = std::stoi(optarg);
break;
@@ -298,7 +343,7 @@ int main(int argc, char **argv) {
/**
* Parse config file
*/
- transport::interface::global_config::parseConfigurationFile(conf_file);
+ global_conf.parseConfigurationFile(conf_file);
core::Prefix producer_namespace(name_prefix);
@@ -309,24 +354,25 @@ int main(int argc, char **argv) {
if (object_size > 1350) object_size = 1350;
CallbackContainer *stubs;
- std::unique_ptr<auth::AsymmetricSigner> signer;
+ std::unique_ptr<auth::Signer> signer;
if (sign) {
signer = std::make_unique<auth::AsymmetricSigner>(keystore_path,
keystore_password);
- stubs =
- new CallbackContainer(n, object_size, verbose, dump, quite, flags,
- reset, ttl, signer.get(), sign, data_lifetime);
+ stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags,
+ reset, ttl, signer.get(), sign, passphrase,
+ data_lifetime);
} else {
auth::Signer *signer = nullptr;
stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags,
- reset, ttl, signer, sign, data_lifetime);
+ reset, ttl, signer, sign, passphrase,
+ data_lifetime);
}
ProducerSocket p;
p.registerPrefix(producer_namespace);
- p.setSocketOption(GeneralTransportOptions::MAKE_MANIFEST, false);
+ p.setSocketOption(GeneralTransportOptions::MANIFEST_MAX_CAPACITY, 0U);
p.setSocketOption(GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 0U);
p.setSocketOption(
ProducerCallbacksOptions::CACHE_MISS,
diff --git a/ctrl/CMakeLists.txt b/ctrl/CMakeLists.txt
index d6fe72d3e..221121818 100644
--- a/ctrl/CMakeLists.txt
+++ b/ctrl/CMakeLists.txt
@@ -21,6 +21,6 @@ project(ctrl)
# Subdirectories
##############################################################
add_subdirectory(libhicnctrl)
-if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Android")
+if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Android" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "iOS")
add_subdirectory(facemgr)
endif () \ No newline at end of file
diff --git a/ctrl/facemgr/includes/hicn/facemgr/cfg.h b/ctrl/facemgr/includes/hicn/facemgr/cfg.h
index fee38daf1..bbbe81825 100644
--- a/ctrl/facemgr/includes/hicn/facemgr/cfg.h
+++ b/ctrl/facemgr/includes/hicn/facemgr/cfg.h
@@ -163,8 +163,6 @@ int facemgr_cfg_rule_get_overlay_remote_port(const facemgr_cfg_rule_t* rule,
int family, uint16_t* port);
int facemgr_cfg_add_static_facelet(facemgr_cfg_t* cfg, facelet_t* facelet);
-int facemgr_cfg_remove_static_facelet(facemgr_cfg_t* cfg, facelet_t* facelet,
- facelet_t** removed_facelet);
int facemgr_cfg_get_static_facelet_array(const facemgr_cfg_t* cfg,
facelet_t*** array);
diff --git a/ctrl/facemgr/src/cfg.c b/ctrl/facemgr/src/cfg.c
index 9c374388a..76e1f5e72 100644
--- a/ctrl/facemgr/src/cfg.c
+++ b/ctrl/facemgr/src/cfg.c
@@ -1120,11 +1120,6 @@ int facemgr_cfg_add_static_facelet(facemgr_cfg_t *cfg, facelet_t *facelet) {
return facelet_array_add(cfg->static_facelets, facelet);
}
-int facemgr_cfg_remove_static_facelet(facemgr_cfg_t *cfg, facelet_t *facelet,
- facelet_t **removed_facelet) {
- return facelet_array_remove(cfg->static_facelets, facelet, removed_facelet);
-}
-
int facemgr_cfg_get_static_facelet_array(const facemgr_cfg_t *cfg,
facelet_t ***array) {
if (facelet_array_get_elements(cfg->static_facelets, array) < 0) {
diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
index 3adba0969..e1f5575d3 100644
--- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
+++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c
@@ -171,6 +171,7 @@ void dump_endpoint(nw_endpoint_t endpoint, int indent) {
free(s);
}
}
+}
void dump_path(nw_path_t path, int indent) {
/* nw_path_enumerate_interfaces : not interesting */
diff --git a/ctrl/facemgr/src/loop_dispatcher.c b/ctrl/facemgr/src/loop_dispatcher.c
index ed4540f5c..88e197492 100644
--- a/ctrl/facemgr/src/loop_dispatcher.c
+++ b/ctrl/facemgr/src/loop_dispatcher.c
@@ -28,7 +28,7 @@
#include <stdlib.h>
-#include <Dispatch/Dispatch.h>
+#include <dispatch/dispatch.h>
#include <hicn/facemgr/loop.h>
#include <hicn/util/log.h>
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
index 8a59cf4d8..c259fc10c 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h
@@ -72,6 +72,7 @@
#include <hicn/util/ip_address.h>
#include <hicn/face.h>
#include <hicn/strategy.h>
+#include <hicn/base.h>
/*
* This has to be common between hicn-light and hicn-plugin. We now we keep the
* minimum of the two
@@ -120,6 +121,7 @@
_(SERVE) \
_(STORE) \
_(CLEAR) \
+ _(GET) \
_(N)
typedef enum {
@@ -150,6 +152,7 @@ hc_action_t action_from_str(const char *action_str);
_(LOCAL_PREFIX) \
_(PROBE) \
_(SUBSCRIPTION) \
+ _(STATS) \
_(N)
typedef enum {
@@ -930,6 +933,13 @@ typedef struct {
flag_interface_type_t interface_type;
} hc_event_interface_update_t;
+/*----------------------------------------------------------------------------*
+ * Statistics
+ *----------------------------------------------------------------------------*/
+int hc_stats_get(hc_sock_t *s, hc_data_t **pdata); // General stats
+int hc_stats_list(hc_sock_t *s, hc_data_t **pdata); // Per-face stats
+int hc_stats_snprintf(char *s, size_t size, const hicn_light_stats_t *stats);
+
/* Result */
hc_msg_t *hc_result_get_msg(hc_sock_t *s, hc_result_t *result);
diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h
index 7d105a84b..783eab086 100644
--- a/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h
+++ b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h
@@ -90,7 +90,9 @@ typedef enum {
_(policy_remove, POLICY_REMOVE) \
_(policy_list, POLICY_LIST) \
_(subscription_add, SUBSCRIPTION_ADD) \
- _(subscription_remove, SUBSCRIPTION_REMOVE)
+ _(subscription_remove, SUBSCRIPTION_REMOVE) \
+ _(stats_get, STATS_GET) \
+ _(stats_list, STATS_LIST)
typedef enum {
COMMAND_TYPE_UNDEFINED,
@@ -282,6 +284,33 @@ typedef struct {
cmd_cache_list_reply_t payload;
} msg_cache_list_reply_t;
+/* Statistics */
+
+// General stats
+typedef struct {
+ void *_;
+} cmd_stats_get_t;
+
+typedef struct {
+ cmd_header_t header;
+ hicn_light_stats_t payload;
+} msg_stats_get_reply_t;
+
+// Per-face stats
+typedef struct {
+ void *_;
+} cmd_stats_list_t;
+
+typedef struct {
+ uint32_t id;
+ connection_stats_t stats;
+} cmd_stats_list_item_t;
+
+typedef struct {
+ cmd_header_t header;
+ cmd_stats_list_item_t payload;
+} msg_stats_list_reply_t;
+
/* WLDR */
typedef struct {
@@ -388,10 +417,10 @@ typedef struct {
cmd_header_t header; \
cmd_##l##_t payload; \
} msg_##l##_t;
-foreach_command_type
+foreach_command_type;
#undef _
- typedef struct {
+typedef struct {
cmd_header_t header;
cmd_listener_list_item_t payload;
} msg_listener_list_reply_t;
diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt
index c8a93c56c..1bec03d50 100644
--- a/ctrl/libhicnctrl/src/CMakeLists.txt
+++ b/ctrl/libhicnctrl/src/CMakeLists.txt
@@ -60,7 +60,8 @@ endif ()
##############################################################
# Do not use modules if Android
##############################################################
-if (${CMAKE_SYSTEM_NAME} MATCHES Android)
+
+if (${CMAKE_SYSTEM_NAME} MATCHES Android OR ${CMAKE_SYSTEM_NAME} MATCHES iOS)
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light_common.c
${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light_ng_api.c
diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c
index 472e07bc4..d68dc830e 100644
--- a/ctrl/libhicnctrl/src/api.c
+++ b/ctrl/libhicnctrl/src/api.c
@@ -440,7 +440,7 @@ GENERATE_FIND(connection);
/* CONNECTION VALIDATE */
int hc_connection_validate(const hc_connection_t *connection) {
- if (!IS_VALID_NAME(connection->name)) {
+ if (connection->name[0] != '\0' && !IS_VALID_NAME(connection->name)) {
ERROR("[hc_connection_validate] Invalid name specified");
return -1;
}
@@ -1060,6 +1060,28 @@ int hc_cache_snprintf(char *s, size_t size, const hc_cache_info_t *cache_info) {
(unsigned long)cache_info->num_stale_entries);
}
+int hc_stats_snprintf(char *s, size_t size, const hicn_light_stats_t *stats) {
+ return snprintf(
+ s, size,
+ "pkts processed: %u\n\tinterests: %u\n\t"
+ "data: %u\npkts from cache count: %u\npkts no pit count: "
+ "%u\nexpired:\n\t interests: "
+ "%u\n\t data: %u\ninterests aggregated: "
+ "%u\nlru evictions: "
+ "%u\ndropped: "
+ "%u\ninterests retx: "
+ "%u\npit entries: %u\ncs entries: %u",
+ stats->forwarder.countReceived, stats->forwarder.countInterestsReceived,
+ stats->forwarder.countObjectsReceived,
+ stats->forwarder.countInterestsSatisfiedFromStore,
+ stats->forwarder.countDroppedNoReversePath,
+ stats->forwarder.countInterestsExpired, stats->forwarder.countDataExpired,
+ stats->pkt_cache.n_lru_evictions, stats->forwarder.countDropped,
+ stats->forwarder.countInterestsAggregated,
+ stats->forwarder.countInterestsRetransmitted,
+ stats->pkt_cache.n_pit_entries, stats->pkt_cache.n_cs_entries);
+}
+
/*----------------------------------------------------------------------------*
* Strategy
*----------------------------------------------------------------------------*/
@@ -1161,6 +1183,17 @@ hc_result_t *hc_subscription_delete_conf(hc_sock_t *s,
}
/*----------------------------------------------------------------------------*
+ * STATISTICS
+ *----------------------------------------------------------------------------*/
+int hc_stats_get(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_stats_get(s, pdata);
+}
+
+int hc_stats_list(hc_sock_t *s, hc_data_t **pdata) {
+ return s->hc_stats_list(s, pdata);
+}
+
+/*----------------------------------------------------------------------------*
* Result
*----------------------------------------------------------------------------*/
diff --git a/ctrl/libhicnctrl/src/api_private.h b/ctrl/libhicnctrl/src/api_private.h
index 65b175810..c708e1eb5 100644
--- a/ctrl/libhicnctrl/src/api_private.h
+++ b/ctrl/libhicnctrl/src/api_private.h
@@ -242,6 +242,9 @@ struct hc_sock_s {
int (*hc_subscription_create)(hc_sock_t *s, hc_subscription_t *subscription);
int (*hc_subscription_delete)(hc_sock_t *s, hc_subscription_t *subscription);
+ int (*hc_stats_get)(hc_sock_t *s, hc_data_t **data);
+ int (*hc_stats_list)(hc_sock_t *s, hc_data_t **data);
+
hc_result_t *(*hc_listener_create_conf)(hc_sock_t *s,
hc_listener_t *listener);
hc_result_t *(*hc_listener_list_conf)(hc_sock_t *s, hc_data_t **pdata);
diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_common.c b/ctrl/libhicnctrl/src/modules/hicn_light_common.c
index bc04404bf..d1fb33993 100644
--- a/ctrl/libhicnctrl/src/modules/hicn_light_common.c
+++ b/ctrl/libhicnctrl/src/modules/hicn_light_common.c
@@ -15,9 +15,6 @@
#include "hicn_light_common.h"
-TYPEDEF_MAP(hc_sock_map, int, hc_sock_request_t *, int_cmp, int_snprintf,
- generic_snprintf);
-
hc_sock_request_t *hc_sock_request_create(int seq, hc_data_t *data,
HC_PARSE parse) {
assert(data);
diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_common.h b/ctrl/libhicnctrl/src/modules/hicn_light_common.h
index 4749474c8..d24b5bb2d 100644
--- a/ctrl/libhicnctrl/src/modules/hicn_light_common.h
+++ b/ctrl/libhicnctrl/src/modules/hicn_light_common.h
@@ -17,6 +17,7 @@
#include <assert.h> // assert
+#include <hicn/util/khash.h>
#include "api_private.h"
#define PORT 9695
@@ -39,7 +40,7 @@ typedef struct {
* outgoing queries so that replied can be demultiplexed and treated
* appropriately.
*/
-TYPEDEF_MAP_H(hc_sock_map, int, hc_sock_request_t *);
+KHASH_MAP_INIT_INT(sock_map, hc_sock_request_t *);
struct hc_sock_light_s {
/* This must be the first element of the struct */
@@ -69,7 +70,7 @@ struct hc_sock_light_s {
hc_sock_request_t *cur_request;
bool async;
- hc_sock_map_t *map;
+ kh_sock_map_t *map;
};
typedef struct hc_sock_light_s hc_sock_light_t;
diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c b/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c
index a58ee909e..488b2edbf 100644
--- a/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c
+++ b/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c
@@ -88,7 +88,9 @@
_(mapme_activator) \
_(mapme_timing) \
_(subscription_add) \
- _(subscription_remove)
+ _(subscription_remove) \
+ _(stats_get) \
+ _(stats_list)
const char *command_type_str[] = {
#define _(l, u) [COMMAND_TYPE_##u] = STRINGIZE(u),
@@ -169,21 +171,13 @@ static int _hcng_sock_light_reset(hc_sock_t *socket) {
void _hcng_sock_light_free(hc_sock_t *socket) {
hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket);
- hc_sock_request_t **request_array = NULL;
- int n = hc_sock_map_get_value_array(s->map, &request_array);
- if (n < 0) {
- ERROR("Could not retrieve pending request array for freeing up resources");
- } else {
- for (unsigned i = 0; i < n; i++) {
- hc_sock_request_t *request = request_array[i];
- if (hc_sock_map_remove(s->map, request->seq, NULL) < 0)
- ERROR("[hc_sock_light_process] Error removing request from map");
- hc_sock_light_request_free(request);
- }
- free(request_array);
- }
- hc_sock_map_free(s->map);
+ unsigned k_seq;
+ hc_sock_request_t *v_request;
+ kh_foreach(s->map, k_seq, v_request,
+ { hc_sock_light_request_free(v_request); });
+
+ kh_destroy_sock_map(s->map);
if (s->url) free(s->url);
close(s->fd);
free(s);
@@ -292,9 +286,13 @@ static void _hcng_sock_light_mark_complete(hc_sock_light_t *s,
hc_data_t **pdata) {
hc_data_t *data = s->cur_request->data;
- if (hc_sock_map_remove(s->map, s->cur_request->seq, NULL) < 0) {
+ khiter_t k = kh_get_sock_map(s->map, s->cur_request->seq);
+ if (k == kh_end(s->map)) {
ERROR("[hc_sock_light_mark_complete] Error removing request from map");
+ } else {
+ kh_del_sock_map(s->map, k);
}
+
hc_data_set_complete(data);
if (pdata) *pdata = data;
@@ -323,7 +321,7 @@ static int _hcng_sock_light_process_notification(hc_sock_light_t *s,
/* Copy the packet payload as the single entry in hc_data_t */
hc_data_push_many(*pdata, s->buf + s->roff, 1);
- return notification_size;
+ return (int)notification_size;
}
/*
@@ -333,12 +331,16 @@ static hc_sock_request_t *_hcng_sock_light_get_request(hc_sock_light_t *s,
int seq) {
hc_sock_request_t *request;
/* Retrieve request from sock map */
- if (hc_sock_map_get(s->map, seq, &request) < 0) {
- ERROR("[hc_sock_light_process] Error searching for matching request");
+ khiter_t k = kh_get_sock_map(s->map, seq);
+ if (k == kh_end(s->map)) {
+ ERROR(
+ "[_hcng_sock_light_get_request] Error searching for matching request");
return NULL;
}
+ request = kh_val(s->map, k);
+
if (!request) {
- ERROR("[hc_sock_light_process] No request matching sequence number");
+ ERROR("[_hcng_sock_light_get_request] No request matching sequence number");
return NULL;
}
return request;
@@ -593,7 +595,7 @@ int _hcng_sock_prepare_send(hc_sock_t *socket, hc_result_t *result,
hc_data_t *data =
hc_data_create(result->params.size_in, result->params.size_out, NULL);
if (!data) {
- ERROR("[_hcng_execute_command] Could not create data storage");
+ ERROR("[_hcng_sock_prepare_send] Could not create data storage");
goto ERR_DATA;
}
hc_data_set_callback(data, complete_cb, complete_cb_data);
@@ -606,15 +608,17 @@ int _hcng_sock_prepare_send(hc_sock_t *socket, hc_result_t *result,
hc_sock_request_t *request = NULL;
request = hc_sock_request_create(seq, data, result->params.parse);
if (!request) {
- ERROR("[_hcng_execute_command] Could not create request state");
+ ERROR("[_hcng_sock_prepare_send] Could not create request state");
goto ERR_REQUEST;
}
- // Add state to map
- if (hc_sock_map_add(s->map, seq, request) < 0) {
- ERROR("[_hcng_execute_command] Error adding request state to map");
+ int rc;
+ khiter_t k = kh_put_sock_map(s->map, seq, &rc);
+ if (rc != KH_ADDED && rc != KH_RESET) {
+ ERROR("[_hcng_sock_prepare_send] Error adding request state to map");
goto ERR_MAP;
}
+ kh_value(s->map, k) = request;
return sizeof(result->msg);
@@ -631,7 +635,7 @@ int _hcng_sock_set_recv_timeout_ms(hc_sock_t *socket, long timeout_ms) {
struct timeval tv;
tv.tv_sec = 0;
- tv.tv_usec = timeout_ms * 1000; // Convert ms into us
+ tv.tv_usec = (int)(timeout_ms * 1000); // Convert ms into us
if (setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
perror("setsockopt");
return -1;
@@ -659,10 +663,13 @@ static int _hcng_execute_command(hc_sock_t *socket, hc_msg_t *msg,
assert(params->size_out == 0);
assert(params->parse == NULL);
break;
+ case ACTION_GET:
case ACTION_LIST:
assert(params->size_in != 0);
assert(params->size_out != 0);
- assert(params->parse != NULL);
+ // TODO(eloparco): Parsing should not be necessary after
+ // (pending) refatoring
+ // assert(params->parse != NULL);
break;
case ACTION_SET:
case ACTION_SERVE:
@@ -701,10 +708,13 @@ static int _hcng_execute_command(hc_sock_t *socket, hc_msg_t *msg,
}
/* Add state to map */
- if (hc_sock_map_add(s->map, seq, request) < 0) {
+ int rc;
+ khiter_t k = kh_put_sock_map(s->map, seq, &rc);
+ if (rc != KH_ADDED && rc != KH_RESET) {
ERROR("[_hcng_execute_command] Error adding request state to map");
goto ERR_MAP;
}
+ kh_value(s->map, k) = request;
if (_hcng_sock_light_send(socket, msg, msg_len, seq) < 0) {
ERROR("[_hcng_execute_command] Error sending message");
@@ -1823,7 +1833,7 @@ static int _hcng_face_create(hc_sock_t *socket, hc_face_t *face) {
case FACE_TYPE_HICN:
case FACE_TYPE_TCP:
case FACE_TYPE_UDP:
- if (hc_face_to_connection(face, &connection, true) < 0) {
+ if (hc_face_to_connection(face, &connection, false) < 0) {
ERROR("[hc_face_create] Could not convert face to connection.");
return -1;
}
@@ -2955,6 +2965,120 @@ static int _hcng_subscription_delete(hc_sock_t *socket,
return ret;
}
+/*----------------------------------------------------------------------------*
+ * Statistics
+ *----------------------------------------------------------------------------*/
+
+/* STATS GET */
+
+static hc_result_t *_hcng_stats_get_serialize(hc_sock_t *socket,
+ hc_data_t **pdata, bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ DEBUG("[hc_stats_get] async=%s", BOOLSTR(async));
+
+ msg_stats_get_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_STATS_GET,
+ .length = 0,
+ .seq_num = 0,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_GET,
+ .cmd_id = COMMAND_TYPE_STATS_GET,
+ .size_in = sizeof(hicn_light_stats_t),
+ .size_out = sizeof(hicn_light_stats_t),
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.stats_get = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static int _hcng_stats_get_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
+ hc_result_t *result = _hcng_stats_get_serialize(socket, pdata, async);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, pdata,
+ result->async);
+ }
+
+ hc_result_free(result);
+ DEBUG("[_hcng_stats_get] done or error");
+ return ret;
+}
+
+static int _hcng_stats_get(hc_sock_t *s, hc_data_t **pdata) {
+ DEBUG("[_hcng_stats_get]");
+ return _hcng_stats_get_internal(s, pdata, false);
+}
+
+/* STATS LIST */
+
+static hc_result_t *_hcng_stats_list_serialize(hc_sock_t *socket,
+ hc_data_t **pdata, bool async) {
+ hc_result_t *res = malloc(sizeof(*res));
+ DEBUG("[hc_stats_list] async=%s", BOOLSTR(async));
+
+ msg_stats_list_t msg = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_STATS_LIST,
+ .length = 0,
+ .seq_num = 0,
+ }};
+
+ hc_command_params_t params = {
+ .cmd = ACTION_LIST,
+ .cmd_id = COMMAND_TYPE_STATS_LIST,
+ .size_in = sizeof(cmd_stats_list_item_t),
+ .size_out = sizeof(cmd_stats_list_item_t),
+ };
+
+ *res = (hc_result_t){
+ .msg =
+ (hc_msg_t){
+ .hdr = msg.header,
+ .payload.stats_list = msg.payload,
+ },
+ .params = params,
+ .async = async,
+ .success = true,
+ };
+ return res;
+}
+
+static int _hcng_stats_list_internal(hc_sock_t *socket, hc_data_t **pdata,
+ bool async) {
+ hc_result_t *result = _hcng_stats_list_serialize(socket, pdata, async);
+
+ int ret = INPUT_ERROR;
+ if (result->success) {
+ ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg,
+ sizeof(result->msg), &result->params, pdata,
+ result->async);
+ }
+
+ hc_result_free(result);
+ DEBUG("[_hcng_stats_list] done or error");
+ return ret;
+}
+
+static int _hcng_stats_list(hc_sock_t *s, hc_data_t **pdata) {
+ DEBUG("[_hcng_stats_list]");
+ return _hcng_stats_list_internal(s, pdata, false);
+}
+
/* RESULT */
hc_msg_t *_hcng_result_get_msg(hc_result_t *result) { return &result->msg; }
int _hcng_result_get_cmd_id(hc_result_t *result) {
@@ -3018,6 +3142,9 @@ static hc_sock_t hc_sock_light_ng_interface = (hc_sock_t){
.hc_subscription_create = _hcng_subscription_create,
.hc_subscription_delete = _hcng_subscription_delete,
+ .hc_stats_get = _hcng_stats_get,
+ .hc_stats_list = _hcng_stats_list,
+
.hc_route_create = _hcng_route_create,
.hc_route_create_async = _hcng_route_create_async,
.hc_route_delete = _hcng_route_delete,
@@ -3094,7 +3221,7 @@ hc_sock_t *_hc_sock_create_url(const char *url) {
s->seq = 0;
s->cur_request = NULL;
- s->map = hc_sock_map_create();
+ s->map = kh_init_sock_map();
if (!s->map) goto ERR_MAP;
return (hc_sock_t *)(s);
diff --git a/docs/source/telemetry.md b/docs/source/telemetry.md
index f81d21ee1..b4d538d76 100644
--- a/docs/source/telemetry.md
+++ b/docs/source/telemetry.md
@@ -43,7 +43,7 @@ VPP 22.02, Debian packages can be found on
- libvppinfra-dev
- vpp-dev
- hicn-plugin-dev
-- `collectd` and `collectd-dev`: `sudo apt install collectd collectd-dev`
+- `collectd` and `collectd-dev`: `sudo apt install collectd collectd-dev libyajl-dev`
## Getting started
diff --git a/docs/source/transport.md b/docs/source/transport.md
index eb5b9d71a..c5250023a 100644
--- a/docs/source/transport.md
+++ b/docs/source/transport.md
@@ -202,7 +202,7 @@ hICN has built-in authentication and integrity features by either:
To enable per-packet signature with asymmetric signing:
* On the producer, disable manifests (which are ON by default):
```cpp
- producer_socket->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST, 0);
+ producer_socket->setSocketOption(GeneralTransportOptions::MANIFEST_MAX_CAPACITY, 0u);
```
* On the producer, instantiate an `AsymmetricSigner` object by passing either an
asymmetric pair of keys as
@@ -244,25 +244,49 @@ available suites.
### Enabling manifests
* Follow steps 2-5 in [Per-packet signatures](#per-packet-signatures).
-* By default, a manifest holds the digest of 30 packets. To change this value:
+* By default, a manifest has a maximum capacity `C_max` of 30 packets. To change
+ this value:
```cpp
- producer_socket->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST, 20);
+ producer_socket->setSocketOption(GeneralTransportOptions::MANIFEST_MAX_CAPACITY, 20u);
```
In the case of RTC, manifests are sent after the data they contain and on the
consumer side, data packets are immediately forwarded to the application, *even
if they weren't authenticated yet via a manifest*. This is to minimize latency.
The digest of incoming data packets are kept in a buffer while waiting for
-manifests to arrive. When that buffer goes above a threshold `T`, an alert is
-raised by the verifier object. That threshold is computed as follows:
+manifests to arrive. When the buffer size goes above a threshold `T`, an alert
+is raised by the verifier object. That alert threshold is computed as follows:
```
-T(t) = producer_rate(t) * max_unverified_time
+T = manifest_factor_alert * C_max
```
-`max_unverified_time` is a consumer socket option, in milliseconds. It is set
-to `2000` by default. To change it:
+The value of `C_max` is passed by the producer to the consumer at the start of
+the connection. `manifest_factor_alert` is a consumer socket option. It
+basically acts on the resilience of manifests against networks losses and
+reflects the application's tolerance to unverified packets: a higher value gives
+the transport the time needed to recover from several manifest losses but
+potentially allows a larger number of unverified packet to go the application
+before alerts are triggered. It is set to `20` by default and should always be
+`>= 1`. To change it:
```cpp
-consumer_socket_->setSocketOption(GeneralTransportOptions::MAX_UNVERIFIED_TIME, 4000);
+consumer_socket_->setSocketOption(GeneralTransportOptions::MANIFEST_FACTOR_ALERT, 10u);
+```
+
+The buffer does not keep unverified packets indefinitely. After a certain amount
+of packets have been received and processed (and were verified or not), older
+packets still unverified are flushed out. This is to prevent the buffer to grow
+uncontrollably and to raise alerts for packets that are not relevant to the
+application anymore. That threshold of relevance is computed as follows:
+```
+T = manifest_factor_relevant * C_max
+```
+
+`manifest_factor_relevant` is a consumer socket option. It is set to `100` by
+default. Its value must be set so that `manifest_factor_relevant >
+manifest_factor_alert >= 1`. If `manifest_factor_relevant <=
+manifest_factor_alert`, no alert will ever be raised. To change it:
+```cpp
+consumer_socket_->setSocketOption(GeneralTransportOptions::MANIFEST_FACTOR_RELEVANT, 200u);
```
### Handling authentication failures
diff --git a/hicn-light/CMakeLists.txt b/hicn-light/CMakeLists.txt
index 337e22b7f..241cae7f2 100644
--- a/hicn-light/CMakeLists.txt
+++ b/hicn-light/CMakeLists.txt
@@ -93,6 +93,7 @@ else()
${LIBHICNCTRL_STATIC}
)
else ()
+ message("qui2!!!")
set(HICN_LIBRARIES
${LIBHICN_SHARED}
${LIBHICNCTRL_SHARED}
diff --git a/hicn-light/src/hicn/base/CMakeLists.txt b/hicn-light/src/hicn/base/CMakeLists.txt
index 1180ed05b..2541ed830 100644
--- a/hicn-light/src/hicn/base/CMakeLists.txt
+++ b/hicn-light/src/hicn/base/CMakeLists.txt
@@ -12,21 +12,11 @@
# limitations under the License.
list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/bitmap.h
- ${CMAKE_CURRENT_SOURCE_DIR}/common.h
- ${CMAKE_CURRENT_SOURCE_DIR}/hash.h
- ${CMAKE_CURRENT_SOURCE_DIR}/khash.h
${CMAKE_CURRENT_SOURCE_DIR}/loop.h
- ${CMAKE_CURRENT_SOURCE_DIR}/pool.h
- ${CMAKE_CURRENT_SOURCE_DIR}/ring.h
- ${CMAKE_CURRENT_SOURCE_DIR}/vector.h
)
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/loop.c
- ${CMAKE_CURRENT_SOURCE_DIR}/pool.c
- ${CMAKE_CURRENT_SOURCE_DIR}/ring.c
- ${CMAKE_CURRENT_SOURCE_DIR}/vector.c
)
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/hicn-light/src/hicn/base/bitmap.h b/hicn-light/src/hicn/base/bitmap.h
deleted file mode 100644
index 060fd5be0..000000000
--- a/hicn-light/src/hicn/base/bitmap.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * \file bitmap.h
- * \brief Bitmap
- *
- * A bitmap is implemented as a wrapper over a vector made of bit elements
- */
-
-#ifndef UTIL_BITMAP_H
-#define UTIL_BITMAP_H
-
-#include <assert.h>
-#include <string.h>
-#include <sys/param.h> // MIN, MAX
-
-#include <hicn/util/log.h>
-
-#include "common.h"
-#include "vector.h"
-
-typedef uint_fast32_t bitmap_t;
-
-#define BITMAP_WIDTH(bitmap) (sizeof((bitmap)[0]) * 8)
-
-/**
- * @brief Allocate and initialize a bitmap
- *
- * @param[in,out] bitmap Bitmap to allocate and initialize
- * @param[in] max_size Bitmap max_size
- */
-#define bitmap_init(bitmap, init_size, max_size) \
- vector_init( \
- bitmap, next_pow2((init_size) / BITMAP_WIDTH(bitmap)), \
- max_size == 0 ? 0 : next_pow2((max_size) / BITMAP_WIDTH(bitmap)))
-
-/*
- * @brief Ensures a bitmap is sufficiently large to hold an element at the
- * given position.
- *
- * @param[in] bitmap The bitmap for which to validate the position.
- * @param[in] pos The position to validate.
- *
- * NOTE:
- * - This function should always be called before writing to a bitmap element
- * to eventually make room for it (the bitmap will eventually be resized).
- */
-static inline int bitmap_ensure_pos(bitmap_t** bitmap, off_t pos) {
- size_t offset = pos / BITMAP_WIDTH(*bitmap);
- return vector_ensure_pos(*bitmap, offset);
-}
-
-/**
- * @brief Returns the allocated size of a bitmap.
- *
- * @see listener_table_get_by_id
- */
-#define bitmap_get_alloc_size(bitmap) vector_get_alloc_size(bitmap)
-
-/**
- * @brief Retrieve the state of the i-th bit in the bitmap.
- *
- * @param[in] bitmap The bitmap to access.
- * @param[in] i The bit position.
- */
-static inline int bitmap_get(const bitmap_t* bitmap, off_t i) {
- size_t offset = i / BITMAP_WIDTH(bitmap);
- assert(offset < bitmap_get_alloc_size(bitmap));
- size_t pos = i % BITMAP_WIDTH(bitmap);
- size_t shift = BITMAP_WIDTH(bitmap) - pos - 1;
- return (bitmap[offset] >> shift) & 1;
-}
-
-/*
- * @brief Returns whether the i-th bit is set (equal to 1) in a bitmap.
- *
- * @param[in] bitmap The bitmap to access.
- * @param[in] i The bit position.
- *
- * @return bool
- */
-#define bitmap_is_set(bitmap, i) (bitmap_get((bitmap), (i)) == 1)
-#define bitmap_is_unset(bitmap, i) (bitmap_get((bitmap), (i)) == 0)
-
-/*
- * @brief Returns whether the i-th bit is unset (equal to 0) in a bitmap.
- *
- * @param[in] bitmap The bitmap to access.
- * @param[in] i The bit position.
- *
- * @return bool
- */
-#define bitmap_set(bitmap, i) _bitmap_set((bitmap_t**)&bitmap, i)
-
-/*
- * @brief Returns whether the i-th bit is unset (equal to 0) in a bitmap
- * (helper).
- *
- * @param[in] bitmap The bitmap to access.
- * @param[in] i The bit position.
- *
- * @return bool
- */
-static inline int _bitmap_set(bitmap_t** bitmap_ptr, off_t i) {
- if (bitmap_ensure_pos(bitmap_ptr, i) < 0) return -1;
-
- bitmap_t* bitmap = *bitmap_ptr;
- size_t offset = i / BITMAP_WIDTH(bitmap);
- size_t pos = i % BITMAP_WIDTH(bitmap);
- size_t shift = BITMAP_WIDTH(bitmap) - pos - 1;
-
- bitmap[offset] |= (bitmap_t)1 << shift;
- return 0;
-}
-
-static inline int bitmap_unset(bitmap_t* bitmap, off_t i) {
- if (bitmap_ensure_pos(&bitmap, i) < 0) return -1;
- size_t offset = i / BITMAP_WIDTH(bitmap);
- size_t pos = i % BITMAP_WIDTH(bitmap);
- size_t shift = BITMAP_WIDTH(bitmap) - pos - 1;
- bitmap[offset] &= ~(1ul << shift);
- return 0;
-}
-
-static inline int bitmap_set_range(bitmap_t* bitmap, off_t from, off_t to) {
- assert(from <= to);
- ssize_t offset_from = from / BITMAP_WIDTH(bitmap);
- ssize_t offset_to = to / BITMAP_WIDTH(bitmap);
- size_t pos_from = from % BITMAP_WIDTH(bitmap);
- size_t pos_to = to % BITMAP_WIDTH(bitmap);
-
- /*
- * First block initialization is needed if <from> is not aligned with the
- * bitmap element size or if to is within the same one.
- */
- if ((pos_from != 0) ||
- ((offset_to == offset_from) && (pos_to != BITMAP_WIDTH(bitmap) - 1))) {
- size_t from_end = MIN(to, (offset_from + 1) * BITMAP_WIDTH(bitmap));
- for (size_t k = from; k < from_end; k++) {
- if (bitmap_set(bitmap, k) < 0) goto END;
- }
- }
-
- /*
- * Second block is needed if <to> is not aligned with the bitmap element
- * size
- */
- if ((pos_to != BITMAP_WIDTH(bitmap) - 1) && (offset_to != offset_from)) {
- size_t to_start = MAX(from, offset_to * BITMAP_WIDTH(bitmap));
- for (size_t k = to_start; k < (size_t)to; k++) {
- if (bitmap_set(bitmap, k) < 0) goto END;
- }
- }
-
- if (pos_from != 0) offset_from += 1;
- if (pos_to != BITMAP_WIDTH(bitmap) - 1) offset_to -= 1;
-
- /*
- * We need to cover both elements at position offset_from and offset_to
- * provided that offset_from is not bigger
- */
- if (offset_to >= offset_from) {
- memset(&bitmap[offset_from], 0xFF,
- (offset_to - offset_from + 1) * sizeof(bitmap[0]));
- }
-
- return 0;
-
-END:
- ERROR("Error setting bitmap range\n");
- return -1;
-}
-
-#define bitmap_set_to(bitmap, to) bitmap_set_range((bitmap), 0, (to))
-
-#define bitmap_free(bitmap) vector_free(bitmap)
-
-#endif /* UTIL_BITMAP_H */
diff --git a/hicn-light/src/hicn/base/common.h b/hicn-light/src/hicn/base/common.h
deleted file mode 100644
index 9f7e3beec..000000000
--- a/hicn-light/src/hicn/base/common.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * \file array.h
- * \brief Fixed-size pool allocator
- */
-
-#ifndef UTIL_COMMON_H
-#define UTIL_COMMON_H
-
-#define round_pow2(x, pow2) ((x + pow2 - 1) & ~(pow2 - 1))
-
-#define _SIZEOF_ALIGNED(x, size) round_pow2(sizeof(x), size)
-#define SIZEOF_ALIGNED(x) _SIZEOF_ALIGNED(x, sizeof(void*))
-
-/* Definitions for builtins unavailable on MSVC */
-#if defined(_MSC_VER) && !defined(__clang__)
-#include <intrin.h>
-
-uint32_t __inline __builtin_ctz(uint32_t value) {
- uint32_t trailing_zero = 0;
- if (_BitScanForward(&trailing_zero, value))
- return trailing_zero;
- else
- return 32;
-}
-
-uint32_t __inline __builtin_clz(uint32_t value) {
- uint32_t leading_zero = 0;
- if (_BitScanReverse(&leading_zero, value))
- return 31 - leading_zero;
- else
- return 32;
-}
-
-uint32_t __inline __builtin_clzl2(uint64_t value) {
- uint32_t leading_zero = 0;
- if (_BitScanReverse64(&leading_zero, value))
- return 63 - leading_zero;
- else
- return 64;
-}
-
-#define __builtin_clzl __builtin_clzll
-#endif
-
-#define next_pow2(x) (x <= 1 ? 1 : 1ul << (64 - __builtin_clzl(x - 1)))
-
-#endif /* UTIL_COMMON_H */
diff --git a/hicn-light/src/hicn/base/hash.h b/hicn-light/src/hicn/base/hash.h
deleted file mode 100644
index 3c54feb29..000000000
--- a/hicn-light/src/hicn/base/hash.h
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * \file hash.h
- * \brief Simple non-cryptographic hash implementation.
- *
- * Two helpers are provided :
- * hash(buf, len) : hash a buffer <buf> of length <len>
- * hash_struct(buf) : hash a buffer corresponding to an allocated struct
- *
- * This file consists in excerpts from Jenkins hash (public domain).
- * http://www.burtleburtle.net/bob/c/lookup3.c
- */
-#ifndef UTIL_HASH_H
-#define UTIL_HASH_H
-
-#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
- __BYTE_ORDER == __LITTLE_ENDIAN) || \
- (defined(i386) || defined(__i386__) || defined(__i486__) || \
- defined(__i586__) || defined(__i686__) || defined(vax) || \
- defined(MIPSEL))
-#define HASH_LITTLE_ENDIAN 1
-#define HASH_BIG_ENDIAN 0
-#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
- __BYTE_ORDER == __BIG_ENDIAN) || \
- (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
-#define HASH_LITTLE_ENDIAN 0
-#define HASH_BIG_ENDIAN 1
-#else
-#define HASH_LITTLE_ENDIAN 0
-#define HASH_BIG_ENDIAN 0
-#endif
-
-#define hashsize(n) ((uint32_t)1 << (n))
-#define hashmask(n) (hashsize(n) - 1)
-#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
-
-#define mix(a, b, c) \
- { \
- a -= c; \
- a ^= rot(c, 4); \
- c += b; \
- b -= a; \
- b ^= rot(a, 6); \
- a += c; \
- c -= b; \
- c ^= rot(b, 8); \
- b += a; \
- a -= c; \
- a ^= rot(c, 16); \
- c += b; \
- b -= a; \
- b ^= rot(a, 19); \
- a += c; \
- c -= b; \
- c ^= rot(b, 4); \
- b += a; \
- }
-
-#define final(a, b, c) \
- { \
- c ^= b; \
- c -= rot(b, 14); \
- a ^= c; \
- a -= rot(c, 11); \
- b ^= a; \
- b -= rot(a, 25); \
- c ^= b; \
- c -= rot(b, 16); \
- a ^= c; \
- a -= rot(c, 4); \
- b ^= a; \
- b -= rot(a, 14); \
- c ^= b; \
- c -= rot(b, 24); \
- }
-
-static inline uint32_t hashlittle(const void *key, size_t length,
- uint32_t initval) {
- uint32_t a, b, c; /* internal state */
- union {
- const void *ptr;
- size_t i;
- } u; /* needed for Mac Powerbook G4 */
-
- /* Set up the internal state */
- a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
-
- u.ptr = key;
- if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
- const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
-
- /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
- while (length > 12) {
- a += k[0];
- b += k[1];
- c += k[2];
- mix(a, b, c);
- length -= 12;
- k += 3;
- }
-
- /*----------------------------- handle the last (probably partial) block */
- /*
- * "k[2]&0xffffff" actually reads beyond the end of the string, but
- * then masks off the part it's not allowed to read. Because the
- * string is aligned, the masked-off tail is in the same word as the
- * rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
- * still catch it and complain. The masking trick does make the hash
- * noticably faster for short strings (like English words).
- */
-#ifndef VALGRIND
-
- switch (length) {
- case 12:
- c += k[2];
- b += k[1];
- a += k[0];
- break;
- case 11:
- c += k[2] & 0xffffff;
- b += k[1];
- a += k[0];
- break;
- case 10:
- c += k[2] & 0xffff;
- b += k[1];
- a += k[0];
- break;
- case 9:
- c += k[2] & 0xff;
- b += k[1];
- a += k[0];
- break;
- case 8:
- b += k[1];
- a += k[0];
- break;
- case 7:
- b += k[1] & 0xffffff;
- a += k[0];
- break;
- case 6:
- b += k[1] & 0xffff;
- a += k[0];
- break;
- case 5:
- b += k[1] & 0xff;
- a += k[0];
- break;
- case 4:
- a += k[0];
- break;
- case 3:
- a += k[0] & 0xffffff;
- break;
- case 2:
- a += k[0] & 0xffff;
- break;
- case 1:
- a += k[0] & 0xff;
- break;
- case 0:
- return c; /* zero length strings require no mixing */
- }
-
-#else /* make valgrind happy */
-
- k8 = (const uint8_t *)k;
- switch (length) {
- case 12:
- c += k[2];
- b += k[1];
- a += k[0];
- break;
- case 11:
- c += ((uint32_t)k8[10]) << 16; /* fall through */
- case 10:
- c += ((uint32_t)k8[9]) << 8; /* fall through */
- case 9:
- c += k8[8]; /* fall through */
- case 8:
- b += k[1];
- a += k[0];
- break;
- case 7:
- b += ((uint32_t)k8[6]) << 16; /* fall through */
- case 6:
- b += ((uint32_t)k8[5]) << 8; /* fall through */
- case 5:
- b += k8[4]; /* fall through */
- case 4:
- a += k[0];
- break;
- case 3:
- a += ((uint32_t)k8[2]) << 16; /* fall through */
- case 2:
- a += ((uint32_t)k8[1]) << 8; /* fall through */
- case 1:
- a += k8[0];
- break;
- case 0:
- return c;
- }
-
-#endif /* !valgrind */
-
- } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
- const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
- const uint8_t *k8;
-
- /*--------------- all but last block: aligned reads and different mixing */
- while (length > 12) {
- a += k[0] + (((uint32_t)k[1]) << 16);
- b += k[2] + (((uint32_t)k[3]) << 16);
- c += k[4] + (((uint32_t)k[5]) << 16);
- mix(a, b, c);
- length -= 12;
- k += 6;
- }
-
- /*----------------------------- handle the last (probably partial) block */
- k8 = (const uint8_t *)k;
- switch (length) {
- case 12:
- c += k[4] + (((uint32_t)k[5]) << 16);
- b += k[2] + (((uint32_t)k[3]) << 16);
- a += k[0] + (((uint32_t)k[1]) << 16);
- break;
- case 11:
- c += ((uint32_t)k8[10]) << 16; /* fall through */
- case 10:
- c += k[4];
- b += k[2] + (((uint32_t)k[3]) << 16);
- a += k[0] + (((uint32_t)k[1]) << 16);
- break;
- case 9:
- c += k8[8]; /* fall through */
- case 8:
- b += k[2] + (((uint32_t)k[3]) << 16);
- a += k[0] + (((uint32_t)k[1]) << 16);
- break;
- case 7:
- b += ((uint32_t)k8[6]) << 16; /* fall through */
- case 6:
- b += k[2];
- a += k[0] + (((uint32_t)k[1]) << 16);
- break;
- case 5:
- b += k8[4]; /* fall through */
- case 4:
- a += k[0] + (((uint32_t)k[1]) << 16);
- break;
- case 3:
- a += ((uint32_t)k8[2]) << 16; /* fall through */
- case 2:
- a += k[0];
- break;
- case 1:
- a += k8[0];
- break;
- case 0:
- return c; /* zero length requires no mixing */
- }
-
- } else { /* need to read the key one byte at a time */
- const uint8_t *k = (const uint8_t *)key;
-
- /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
- while (length > 12) {
- a += k[0];
- a += ((uint32_t)k[1]) << 8;
- a += ((uint32_t)k[2]) << 16;
- a += ((uint32_t)k[3]) << 24;
- b += k[4];
- b += ((uint32_t)k[5]) << 8;
- b += ((uint32_t)k[6]) << 16;
- b += ((uint32_t)k[7]) << 24;
- c += k[8];
- c += ((uint32_t)k[9]) << 8;
- c += ((uint32_t)k[10]) << 16;
- c += ((uint32_t)k[11]) << 24;
- mix(a, b, c);
- length -= 12;
- k += 12;
- }
-
- /*-------------------------------- last block: affect all 32 bits of (c) */
- switch (length) /* all the case statements fall through */
- {
- case 12:
- c += ((uint32_t)k[11]) << 24;
- case 11:
- c += ((uint32_t)k[10]) << 16;
- case 10:
- c += ((uint32_t)k[9]) << 8;
- case 9:
- c += k[8];
- case 8:
- b += ((uint32_t)k[7]) << 24;
- case 7:
- b += ((uint32_t)k[6]) << 16;
- case 6:
- b += ((uint32_t)k[5]) << 8;
- case 5:
- b += k[4];
- case 4:
- a += ((uint32_t)k[3]) << 24;
- case 3:
- a += ((uint32_t)k[2]) << 16;
- case 2:
- a += ((uint32_t)k[1]) << 8;
- case 1:
- a += k[0];
- break;
- case 0:
- return c;
- }
- }
-
- final(a, b, c);
- return c;
-}
-
-/* Helpers */
-
-#define HASH_INITVAL 1
-//#define hash(buf, len) (hash_t)hashlittle(buf, len, HASH_INITVAL)
-#define hash(buf, len) hashlittle(buf, len, HASH_INITVAL)
-#define hash_struct(buf) hash(buf, sizeof(*buf))
-
-#define str_hash(str) (hash(str, strlen(str)))
-#define str_hash_eq(a, b) (str_hash(b) - str_hash(a))
-
-#endif /* UTIL_JENKINS_HASH_H */
diff --git a/hicn-light/src/hicn/base/khash.h b/hicn-light/src/hicn/base/khash.h
deleted file mode 100644
index 4c62b0260..000000000
--- a/hicn-light/src/hicn/base/khash.h
+++ /dev/null
@@ -1,748 +0,0 @@
-/* The MIT License
-
- Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk>
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-*/
-
-/*
- An example:
-
-#include "khash.h"
-KHASH_MAP_INIT_INT(32, char)
-int main() {
- int ret, is_missing;
- khiter_t k;
- khash_t(32) *h = kh_init(32);
- k = kh_put(32, h, 5, &ret);
- kh_value(h, k) = 10;
- k = kh_get(32, h, 10);
- is_missing = (k == kh_end(h));
- k = kh_get(32, h, 5);
- kh_del(32, h, k);
- for (k = kh_begin(h); k != kh_end(h); ++k)
- if (kh_exist(h, k)) kh_value(h, k) = 1;
- kh_destroy(32, h);
- return 0;
-}
-*/
-
-/*
- 2013-05-02 (0.2.8):
-
- * Use quadratic probing. When the capacity is power of 2, stepping
- function i*(i+1)/2 guarantees to traverse each bucket. It is better than
- double hashing on cache performance and is more robust than linear probing.
-
- In theory, double hashing should be more robust than quadratic
- probing. However, my implementation is probably not for large hash tables,
- because the second hash function is closely tied to the first hash function,
- which reduce the effectiveness of double hashing.
-
- Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php
-
- 2011-12-29 (0.2.7):
-
- * Minor code clean up; no actual effect.
-
- 2011-09-16 (0.2.6):
-
- * The capacity is a power of 2. This seems to dramatically improve the
- speed for simple keys. Thank Zilong Tan for the suggestion. Reference:
-
- - http://code.google.com/p/ulib/
- - http://nothings.org/computer/judy/
-
- * Allow to optionally use linear probing which usually has better
- performance for random input. Double hashing is still the default as
- it is more robust to certain non-random input.
-
- * Added Wang's integer hash function (not used by default). This hash
- function is more robust to certain non-random input.
-
- 2011-02-14 (0.2.5):
-
- * Allow to declare global functions.
-
- 2009-09-26 (0.2.4):
-
- * Improve portability
-
- 2008-09-19 (0.2.3):
-
- * Corrected the example
- * Improved interfaces
-
- 2008-09-11 (0.2.2):
-
- * Improved speed a little in kh_put()
-
- 2008-09-10 (0.2.1):
-
- * Added kh_clear()
- * Fixed a compiling error
-
- 2008-09-02 (0.2.0):
-
- * Changed to token concatenation which increases flexibility.
-
- 2008-08-31 (0.1.2):
-
- * Fixed a bug in kh_get(), which has not been tested previously.
-
- 2008-08-31 (0.1.1):
-
- * Added destructor
-*/
-
-#ifndef __AC_KHASH_H
-#define __AC_KHASH_H
-
-/*!
- @header
-
- Generic hash table library.
- */
-
-#define AC_VERSION_KHASH_H "0.2.8"
-
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-/* compiler specific configuration */
-
-#if UINT_MAX == 0xffffffffu
-typedef unsigned int khint32_t;
-#elif ULONG_MAX == 0xffffffffu
-typedef unsigned long khint32_t;
-#endif
-
-#if ULONG_MAX == ULLONG_MAX
-typedef unsigned long khint64_t;
-#else
-typedef unsigned long long khint64_t;
-#endif
-
-#ifndef kh_inline
-#ifdef _MSC_VER
-#define kh_inline __inline
-#else
-#define kh_inline inline
-#endif
-#endif /* kh_inline */
-
-#ifndef klib_unused
-#if (defined __clang__ && __clang_major__ >= 3) || \
- (defined __GNUC__ && __GNUC__ >= 3)
-#define klib_unused __attribute__((__unused__))
-#else
-#define klib_unused
-#endif
-#endif /* klib_unused */
-
-typedef khint32_t khint_t;
-typedef khint_t khiter_t;
-
-#define __ac_isempty(flag, i) ((flag[i >> 4] >> ((i & 0xfU) << 1)) & 2)
-#define __ac_isdel(flag, i) ((flag[i >> 4] >> ((i & 0xfU) << 1)) & 1)
-#define __ac_iseither(flag, i) ((flag[i >> 4] >> ((i & 0xfU) << 1)) & 3)
-#define __ac_set_isdel_false(flag, i) \
- (flag[i >> 4] &= ~(1ul << ((i & 0xfU) << 1)))
-#define __ac_set_isempty_false(flag, i) \
- (flag[i >> 4] &= ~(2ul << ((i & 0xfU) << 1)))
-#define __ac_set_isboth_false(flag, i) \
- (flag[i >> 4] &= ~(3ul << ((i & 0xfU) << 1)))
-#define __ac_set_isdel_true(flag, i) (flag[i >> 4] |= 1ul << ((i & 0xfU) << 1))
-
-#define __ac_fsize(m) ((m) < 16 ? 1 : (m) >> 4)
-
-#ifndef kroundup32
-#define kroundup32(x) \
- (--(x), (x) |= (x) >> 1, (x) |= (x) >> 2, (x) |= (x) >> 4, (x) |= (x) >> 8, \
- (x) |= (x) >> 16, ++(x))
-#endif
-
-#ifndef kcalloc
-#define kcalloc(N, Z) calloc(N, Z)
-#endif
-#ifndef kmalloc
-#define kmalloc(Z) malloc(Z)
-#endif
-#ifndef krealloc
-#define krealloc(P, Z) realloc(P, Z)
-#endif
-#ifndef kfree
-#define kfree(P) free(P)
-#endif
-
-static const double __ac_HASH_UPPER = 0.77;
-
-#define __KHASH_TYPE(name, khkey_t, khval_t) \
- typedef struct kh_##name##_s { \
- khint_t n_buckets, size, n_occupied, upper_bound; \
- khint32_t *flags; \
- khkey_t *keys; \
- khval_t *vals; \
- } kh_##name##_t;
-
-#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
- extern kh_##name##_t *kh_init_##name(void); \
- extern void kh_destroy_##name(kh_##name##_t *h); \
- extern void kh_clear_##name(kh_##name##_t *h); \
- extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \
- extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
- extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
- extern void kh_del_##name(kh_##name##_t *h, khint_t x);
-
-#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \
- __hash_equal) \
- SCOPE kh_##name##_t *kh_init_##name(void) { \
- return (kh_##name##_t *)kcalloc(1, sizeof(kh_##name##_t)); \
- } \
- SCOPE void kh_destroy_##name(kh_##name##_t *h) { \
- if (h) { \
- kfree((void *)h->keys); \
- kfree(h->flags); \
- kfree((void *)h->vals); \
- kfree(h); \
- } \
- } \
- SCOPE void kh_clear_##name(kh_##name##_t *h) { \
- if (h && h->flags) { \
- memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \
- h->size = h->n_occupied = 0; \
- } \
- } \
- SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) { \
- if (h->n_buckets) { \
- khint_t k, i, last, mask, step = 0; \
- mask = h->n_buckets - 1; \
- k = __hash_func(key); \
- i = k & mask; \
- last = i; \
- while (!__ac_isempty(h->flags, i) && \
- (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
- i = (i + (++step)) & mask; \
- if (i == last) return h->n_buckets; \
- } \
- return __ac_iseither(h->flags, i) ? h->n_buckets : i; \
- } else \
- return 0; \
- } \
- SCOPE int kh_resize_##name( \
- kh_##name##_t *h, \
- khint_t new_n_buckets) { /* This function uses 0.25*n_buckets bytes of \
- working space instead of \
- [sizeof(key_t+val_t)+.25]*n_buckets. */ \
- khint32_t *new_flags = 0; \
- khint_t j = 1; \
- { \
- kroundup32(new_n_buckets); \
- if (new_n_buckets < 4) new_n_buckets = 4; \
- if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) \
- j = 0; /* requested size is too small */ \
- else { /* hash table size to be changed (shrink or expand); rehash */ \
- new_flags = (khint32_t *)kmalloc(__ac_fsize(new_n_buckets) * \
- sizeof(khint32_t)); \
- if (!new_flags) return -1; \
- memset(new_flags, 0xaa, \
- __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
- if (h->n_buckets < new_n_buckets) { /* expand */ \
- khkey_t *new_keys = (khkey_t *)krealloc( \
- (void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
- if (!new_keys) { \
- kfree(new_flags); \
- return -1; \
- } \
- h->keys = new_keys; \
- if (kh_is_map) { \
- khval_t *new_vals = (khval_t *)krealloc( \
- (void *)h->vals, new_n_buckets * sizeof(khval_t)); \
- if (!new_vals) { \
- kfree(new_flags); \
- return -1; \
- } \
- h->vals = new_vals; \
- } \
- } /* otherwise shrink */ \
- } \
- } \
- if (j) { /* rehashing is needed */ \
- for (j = 0; j != h->n_buckets; ++j) { \
- if (__ac_iseither(h->flags, j) == 0) { \
- khkey_t key = h->keys[j]; \
- khval_t val; \
- khint_t new_mask; \
- new_mask = new_n_buckets - 1; \
- if (kh_is_map) val = h->vals[j]; \
- __ac_set_isdel_true(h->flags, j); \
- while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \
- khint_t k, i, step = 0; \
- k = __hash_func(key); \
- i = k & new_mask; \
- while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \
- __ac_set_isempty_false(new_flags, i); \
- if (i < h->n_buckets && \
- __ac_iseither(h->flags, i) == \
- 0) { /* kick out the existing element */ \
- { \
- khkey_t tmp = h->keys[i]; \
- h->keys[i] = key; \
- key = tmp; \
- } \
- if (kh_is_map) { \
- khval_t tmp = h->vals[i]; \
- h->vals[i] = val; \
- val = tmp; \
- } \
- __ac_set_isdel_true( \
- h->flags, i); /* mark it as deleted in the old hash table */ \
- } else { /* write the element and jump out of the loop */ \
- h->keys[i] = key; \
- if (kh_is_map) h->vals[i] = val; \
- break; \
- } \
- } \
- } \
- } \
- if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \
- h->keys = (khkey_t *)krealloc((void *)h->keys, \
- new_n_buckets * sizeof(khkey_t)); \
- if (kh_is_map) \
- h->vals = (khval_t *)krealloc((void *)h->vals, \
- new_n_buckets * sizeof(khval_t)); \
- } \
- kfree(h->flags); /* free the working space */ \
- h->flags = new_flags; \
- h->n_buckets = new_n_buckets; \
- h->n_occupied = h->size; \
- h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \
- } \
- return 0; \
- } \
- SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) { \
- khint_t x; \
- if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \
- if (h->n_buckets > (h->size << 1)) { \
- if (kh_resize_##name(h, h->n_buckets - 1) < \
- 0) { /* clear "deleted" elements */ \
- *ret = -1; \
- return h->n_buckets; \
- } \
- } else if (kh_resize_##name(h, h->n_buckets + 1) < \
- 0) { /* expand the hash table */ \
- *ret = -1; \
- return h->n_buckets; \
- } \
- } /* TODO: to implement automatically shrinking; resize() already support \
- shrinking */ \
- { \
- khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \
- x = site = h->n_buckets; \
- k = __hash_func(key); \
- i = k & mask; \
- if (__ac_isempty(h->flags, i)) \
- x = i; /* for speed up */ \
- else { \
- last = i; \
- while (!__ac_isempty(h->flags, i) && \
- (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
- if (__ac_isdel(h->flags, i)) site = i; \
- i = (i + (++step)) & mask; \
- if (i == last) { \
- x = site; \
- break; \
- } \
- } \
- if (x == h->n_buckets) { \
- if (__ac_isempty(h->flags, i) && site != h->n_buckets) \
- x = site; \
- else \
- x = i; \
- } \
- } \
- } \
- if (__ac_isempty(h->flags, x)) { /* not present at all */ \
- h->keys[x] = key; \
- __ac_set_isboth_false(h->flags, x); \
- ++h->size; \
- ++h->n_occupied; \
- *ret = 1; \
- } else if (__ac_isdel(h->flags, x)) { /* deleted */ \
- h->keys[x] = key; \
- __ac_set_isboth_false(h->flags, x); \
- ++h->size; \
- *ret = 2; \
- } else \
- *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \
- return x; \
- } \
- SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) { \
- if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \
- __ac_set_isdel_true(h->flags, x); \
- --h->size; \
- } \
- }
-
-#define KHASH_DECLARE(name, khkey_t, khval_t) \
- __KHASH_TYPE(name, khkey_t, khval_t) \
- __KHASH_PROTOTYPES(name, khkey_t, khval_t)
-
-#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \
- __hash_equal) \
- __KHASH_TYPE(name, khkey_t, khval_t) \
- __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \
- __hash_equal)
-
-#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, \
- __hash_equal) \
- KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, \
- __hash_func, __hash_equal)
-
-/* --- BEGIN OF HASH FUNCTIONS --- */
-
-/*! @function
- @abstract Integer hash function
- @param key The integer [khint32_t]
- @return The hash value [khint_t]
- */
-#define kh_int_hash_func(key) (khint32_t)(key)
-/*! @function
- @abstract Integer comparison function
- */
-#define kh_int_hash_equal(a, b) ((a) == (b))
-/*! @function
- @abstract 64-bit integer hash function
- @param key The integer [khint64_t]
- @return The hash value [khint_t]
- */
-#define kh_int64_hash_func(key) (khint32_t)((key) >> 33 ^ (key) ^ (key) << 11)
-/*! @function
- @abstract 64-bit integer comparison function
- */
-#define kh_int64_hash_equal(a, b) ((a) == (b))
-/*! @function
- @abstract const char* hash function
- @param s Pointer to a null terminated string
- @return The hash value
- */
-static kh_inline khint_t __ac_X31_hash_string(const char *s) {
- khint_t h = (khint_t)*s;
- if (h)
- for (++s; *s; ++s) h = (h << 5) - h + (khint_t)*s;
- return h;
-}
-/*! @function
- @abstract Another interface to const char* hash function
- @param key Pointer to a null terminated string [const char*]
- @return The hash value [khint_t]
- */
-#define kh_str_hash_func(key) __ac_X31_hash_string(key)
-/*! @function
- @abstract Const char* comparison function
- */
-#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
-
-static kh_inline khint_t __ac_Wang_hash(khint_t key) {
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
- return key;
-}
-#define kh_int_hash_func2(key) __ac_Wang_hash((khint_t)key)
-
-/* --- END OF HASH FUNCTIONS --- */
-
-/* Other convenient macros... */
-
-/*!
- @abstract Type of the hash table.
- @param name Name of the hash table [symbol]
- */
-#define khash_t(name) kh_##name##_t
-
-/*! @function
- @abstract Initiate a hash table.
- @param name Name of the hash table [symbol]
- @return Pointer to the hash table [khash_t(name)*]
- */
-#define kh_init(name) kh_init_##name()
-
-/*! @function
- @abstract Destroy a hash table.
- @param name Name of the hash table [symbol]
- @param h Pointer to the hash table [khash_t(name)*]
- */
-#define kh_destroy(name, h) kh_destroy_##name(h)
-
-/*! @function
- @abstract Reset a hash table without deallocating memory.
- @param name Name of the hash table [symbol]
- @param h Pointer to the hash table [khash_t(name)*]
- */
-#define kh_clear(name, h) kh_clear_##name(h)
-
-/*! @function
- @abstract Resize a hash table.
- @param name Name of the hash table [symbol]
- @param h Pointer to the hash table [khash_t(name)*]
- @param s New size [khint_t]
- */
-#define kh_resize(name, h, s) kh_resize_##name(h, s)
-
-/*! @function
- @abstract Insert a key to the hash table.
- @param name Name of the hash table [symbol]
- @param h Pointer to the hash table [khash_t(name)*]
- @param k Key [type of keys]
- @param r Extra return code: -1 if the operation failed;
- 0 if the key is present in the hash table;
- 1 if the bucket is empty (never used); 2 if the element in
- the bucket has been deleted [int*]
- @return Iterator to the inserted element [khint_t]
- */
-#define kh_put(name, h, k, r) kh_put_##name(h, k, r)
-
-/*! @function
- @abstract Retrieve a key from the hash table.
- @param name Name of the hash table [symbol]
- @param h Pointer to the hash table [khash_t(name)*]
- @param k Key [type of keys]
- @return Iterator to the found element, or kh_end(h) if the element is
- absent [khint_t]
- */
-#define kh_get(name, h, k) kh_get_##name(h, k)
-
-/*! @function
- @abstract Remove a key from the hash table.
- @param name Name of the hash table [symbol]
- @param h Pointer to the hash table [khash_t(name)*]
- @param k Iterator to the element to be deleted [khint_t]
- */
-#define kh_del(name, h, k) kh_del_##name(h, k)
-
-/*! @function
- @abstract Test whether a bucket contains data.
- @param h Pointer to the hash table [khash_t(name)*]
- @param x Iterator to the bucket [khint_t]
- @return 1 if containing data; 0 otherwise [int]
- */
-#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x)))
-
-/*! @function
- @abstract Get key given an iterator
- @param h Pointer to the hash table [khash_t(name)*]
- @param x Iterator to the bucket [khint_t]
- @return Key [type of keys]
- */
-#define kh_key(h, x) ((h)->keys[x])
-
-/*! @function
- @abstract Get value given an iterator
- @param h Pointer to the hash table [khash_t(name)*]
- @param x Iterator to the bucket [khint_t]
- @return Value [type of values]
- @discussion For hash sets, calling this results in segfault.
- */
-#define kh_val(h, x) ((h)->vals[x])
-
-/*! @function
- @abstract Alias of kh_val()
- */
-#define kh_value(h, x) ((h)->vals[x])
-
-/*! @function
- @abstract Get the start iterator
- @param h Pointer to the hash table [khash_t(name)*]
- @return The start iterator [khint_t]
- */
-#define kh_begin(h) (khint_t)(0)
-
-/*! @function
- @abstract Get the end iterator
- @param h Pointer to the hash table [khash_t(name)*]
- @return The end iterator [khint_t]
- */
-#define kh_end(h) ((h)->n_buckets)
-
-/*! @function
- @abstract Get the number of elements in the hash table
- @param h Pointer to the hash table [khash_t(name)*]
- @return Number of elements in the hash table [khint_t]
- */
-#define kh_size(h) ((h)->size)
-
-/*! @function
- @abstract Get the number of buckets in the hash table
- @param h Pointer to the hash table [khash_t(name)*]
- @return Number of buckets in the hash table [khint_t]
- */
-#define kh_n_buckets(h) ((h)->n_buckets)
-
-/*! @function
- @abstract Iterate over the entries in the hash table
- @param h Pointer to the hash table [khash_t(name)*]
- @param kvar Variable to which key will be assigned
- @param vvar Variable to which value will be assigned
- @param code Block of code to execute
- */
-#define kh_foreach(h, kvar, vvar, code) \
- { \
- khint_t __i; \
- for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
- if (!kh_exist(h, __i)) continue; \
- (kvar) = kh_key(h, __i); \
- (vvar) = kh_val(h, __i); \
- code; \
- } \
- }
-
-/*! @function
- @abstract Iterate over the values in the hash table
- @param h Pointer to the hash table [khash_t(name)*]
- @param vvar Variable to which value will be assigned
- @param code Block of code to execute
- */
-#define kh_foreach_value(h, vvar, code) \
- { \
- khint_t __i; \
- for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
- if (!kh_exist(h, __i)) continue; \
- (vvar) = kh_val(h, __i); \
- code; \
- } \
- }
-
-/* More convenient interfaces */
-
-/*! @function
- @abstract Instantiate a hash set containing integer keys
- @param name Name of the hash table [symbol]
- */
-#define KHASH_SET_INIT_INT(name) \
- KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
-
-/*! @function
- @abstract Instantiate a hash map containing integer keys
- @param name Name of the hash table [symbol]
- @param khval_t Type of values [type]
- */
-#define KHASH_MAP_INIT_INT(name, khval_t) \
- KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
-
-/*! @function
- @abstract Instantiate a hash set containing 64-bit integer keys
- @param name Name of the hash table [symbol]
- */
-#define KHASH_SET_INIT_INT64(name) \
- KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal)
-
-/*! @function
- @abstract Instantiate a hash map containing 64-bit integer keys
- @param name Name of the hash table [symbol]
- @param khval_t Type of values [type]
- */
-#define KHASH_MAP_INIT_INT64(name, khval_t) \
- KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, \
- kh_int64_hash_equal)
-
-typedef const char *kh_cstr_t;
-/*! @function
- @abstract Instantiate a hash map containing const char* keys
- @param name Name of the hash table [symbol]
- */
-#define KHASH_SET_INIT_STR(name) \
- KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
-
-/*! @function
- @abstract Instantiate a hash map containing const char* keys
- @param name Name of the hash table [symbol]
- @param khval_t Type of values [type]
- */
-#define KHASH_MAP_INIT_STR(name, khval_t) \
- KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
-
-/******************************************************************************
- * Custom
- *high-level interface
- ******************************************************************************/
-
-#define _kh_var(x) _kh_var_##x
-
-/**
- * @brief Return the value corresponding to a key in the hashtable.
- * @return The value associated with the key or null if not found
- */
-#define kh_get_val(kname, hashtable, key, default_val) \
- ({ \
- khiter_t _kh_var(k) = kh_get(kname, hashtable, key); \
- (_kh_var(k) != kh_end(hashtable) ? kh_val(hashtable, _kh_var(k)) \
- : default_val); \
- })
-
-/**
- * @brief Add key/value pair in the hashtable.
- * @return 0 if an existing value (corresponding to the provided key)
- * has been replaced; 1 if a new key/value pair has been added
- * (the key was not already present in the hash table);
- * 2 if a new key/value pair has been added in correspondence
- * of a key previously deleted key
- */
-#define kh_put_val(kname, hashtable, key, val) \
- ({ \
- int _kh_var(ret); \
- khiter_t _kh_var(k) = kh_put(kname, hashtable, key, &_kh_var(ret)); \
- kh_value(hashtable, _kh_var(k)) = val; \
- _kh_var(ret); \
- })
-
-/**
- * @brief Remove a key/value pair from the hashtable.
- * @return void
- */
-#define kh_remove_val(kname, hashtable, key) \
- ({ \
- khiter_t _kh_var(k) = kh_get(kname, hashtable, key); \
- if (_kh_var(k) != kh_end(hashtable)) { \
- free((void *)kh_key(hashtable, _kh_var(k))); \
- kh_del(kname, hashtable, _kh_var(k)); \
- } \
- })
-
-/**
- * @brief Free the hashtable.
- * @return void
- */
-#define kh_free(kname, hashtable) \
- ({ \
- const void *_kh_var(key); \
- unsigned _kh_var(val); \
- (void)_kh_var(val); \
- \
- kh_foreach(hashtable, _kh_var(key), _kh_var(val), \
- { free((void *)_kh_var(key)); }) kh_destroy(kname, hashtable); \
- })
-
-#endif /* __AC_KHASH_H */
diff --git a/hicn-light/src/hicn/base/pool.c b/hicn-light/src/hicn/base/pool.c
deleted file mode 100644
index e5fb7d6ac..000000000
--- a/hicn-light/src/hicn/base/pool.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * \file pool.c
- * \brief Implementation of fixed-size pool allocator.
- *
- * NOTE:
- * - Ideally, we should have a single realloc per resize, that would encompass
- * both the free indices vector and bitmap, by nesting data structures. Because
- * of the added complexity, and by lack of evidence of the need for this, we
- * currently rely on a simpler implementation.
- */
-
-#include <assert.h>
-#include <stdlib.h> // calloc
-
-#include "common.h"
-#include "pool.h"
-
-#include <stdio.h> // XXX
-
-void _pool_init(void** pool_ptr, size_t elt_size, size_t init_size,
- size_t max_size) {
- assert(pool_ptr);
- assert(elt_size);
-
- init_size = next_pow2(init_size);
-
- if (max_size && init_size > max_size) goto ERR_MAX_SIZE;
-
- /* The initial pool size is rounded to the next power of two */
- size_t alloc_size = next_pow2(init_size);
-
- pool_hdr_t* ph = calloc(POOL_HDRLEN + alloc_size * elt_size, 1);
- if (!ph) goto ERR_MALLOC;
-
- ph->elt_size = elt_size;
- ph->alloc_size = alloc_size;
- ph->max_size = max_size;
-
- /* Free indices */
- off_t* free_indices;
- vector_init(free_indices, init_size, max_size);
- for (unsigned i = 0; i < init_size; i++)
- free_indices[i] = (init_size - 1) - i;
- vector_len(free_indices) = init_size;
- ph->free_indices = free_indices;
-
- /* Free bitmap */
- bitmap_t* fb = ph->free_bitmap;
- bitmap_init(fb, init_size, max_size);
- bitmap_set_to(fb, init_size);
- ph->free_bitmap = fb;
-
- *pool_ptr = (uint8_t*)ph + POOL_HDRLEN;
-
- return;
-
-ERR_MALLOC:
-ERR_MAX_SIZE:
- *pool_ptr = NULL;
- return;
-}
-
-void _pool_free(void** pool_ptr) {
- pool_hdr_t* ph = pool_hdr(*pool_ptr);
- vector_free(ph->free_indices);
- bitmap_free(ph->free_bitmap);
-
- free(pool_hdr(*pool_ptr));
- *pool_ptr = NULL;
-}
-
-bool _pool_validate_id(void** pool_ptr, off_t id) {
- pool_hdr_t* ph = pool_hdr(*pool_ptr);
- size_t pool_size = pool_get_alloc_size(*pool_ptr);
- if (id >= pool_size || !bitmap_is_unset(ph->free_bitmap, id)) return false;
-
- return true;
-}
-
-void _pool_resize(void** pool_ptr, size_t elt_size) {
- pool_hdr_t* ph = pool_hdr(*pool_ptr);
- size_t old_size = ph->alloc_size;
- size_t new_size = old_size * 2;
-
- TRACE("pool_resize to %lu", new_size);
-
- if (ph->max_size && new_size > ph->max_size) goto ERR_MAX_SIZE;
-
- /* Double pool storage */
- ph = realloc(ph, POOL_HDRLEN + new_size * elt_size);
- if (!ph) goto ERR_REALLOC;
- ph->elt_size = elt_size;
- ph->alloc_size = new_size;
-
- /*
- * After resize, the pool will have new free indices, ranging from
- * old_size to (new_size - 1)
- */
- vector_ensure_pos(ph->free_indices, old_size);
- for (unsigned i = 0; i < old_size; i++)
- ph->free_indices[i] = new_size - 1 - i;
- vector_len(ph->free_indices) = old_size;
-
- /* We also need to update the bitmap */
- bitmap_ensure_pos(&(ph->free_bitmap), new_size - 1);
- bitmap_set_range(ph->free_bitmap, old_size, new_size - 1);
-
- /* Reassign pool pointer */
- *pool_ptr = (uint8_t*)ph + POOL_HDRLEN;
-
- return;
-
-ERR_REALLOC:
-ERR_MAX_SIZE:
- *pool_ptr = NULL;
- return;
-}
-
-off_t _pool_get(void** pool_ptr, void** elt, size_t elt_size) {
- pool_hdr_t* ph = pool_hdr(*pool_ptr);
- uint64_t l = vector_len(ph->free_indices);
- if (l == 0) {
- _pool_resize(pool_ptr, elt_size);
- ph = pool_hdr(*pool_ptr);
- l = vector_len(ph->free_indices);
- }
- off_t free_id = ph->free_indices[l - 1];
- vector_len(ph->free_indices)--;
- bitmap_unset(ph->free_bitmap, free_id);
- *elt = *pool_ptr + free_id * elt_size;
- memset(*elt, 0, elt_size);
- return free_id;
-}
-
-void _pool_put(void** pool_ptr, void** elt, size_t elt_size) {
- pool_hdr_t* ph = pool_hdr(*pool_ptr);
- uint64_t l = vector_len(ph->free_indices);
- vector_ensure_pos(ph->free_indices, l);
- off_t freed_id = (*elt - *pool_ptr) / elt_size;
- ph->free_indices[l] = freed_id;
- vector_len(ph->free_indices)++;
- bitmap_set(ph->free_bitmap, freed_id);
-}
diff --git a/hicn-light/src/hicn/base/ring.h b/hicn-light/src/hicn/base/ring.h
deleted file mode 100644
index 492a8fdac..000000000
--- a/hicn-light/src/hicn/base/ring.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * \file ring.h
- * \brief Fixed-size pool allocator.
- */
-
-#ifndef UTIL_RING_H
-#define UTIL_RING_H
-
-#include <assert.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/param.h> // MIN
-#include <sys/types.h>
-
-#include <stdio.h> // XXX debug
-
-#include "common.h"
-
-/******************************************************************************/
-/* Ring header */
-
-typedef struct {
- size_t roff;
- size_t woff;
- size_t size;
- size_t max_size;
-} ring_hdr_t;
-
-/* Make sure elements following the header are aligned */
-#define RING_HDRLEN SIZEOF_ALIGNED(ring_hdr_t)
-
-/* This header actually prepends the actual content of the vector */
-#define ring_hdr(ring) ((ring_hdr_t *)((uint8_t *)ring - RING_HDRLEN))
-
-/******************************************************************************/
-/* Helpers */
-
-/** Local variable naming macro. */
-#define _ring_var(v) _ring_##v
-
-/**
- * @brief Allocate and initialize a ring data structure (helper function).
- *
- * @param[in,out] ring_ptr Ring buffer to allocate and initialize.
- * @param[in] elt_size Size of a ring element.
- * @param[in] max_size Maximum vector size (O = unlimited).
- */
-void _ring_init(void **ring_ptr, size_t elt_size, size_t max_size);
-
-/**
- * @brief Free a ring data structure.
- *
- * @param ring_ptr[in] Pointer to the ring data structure to free.
- */
-void _ring_free(void **ring_ptr);
-
-static inline int _ring_add(void **ring_ptr, size_t elt_size, void *eltp) {
- assert(*ring_ptr);
- ring_hdr_t *rh = ring_hdr(*ring_ptr);
-
- /* We always write ! */
- memcpy((uint8_t *)*ring_ptr + rh->woff * elt_size, eltp, elt_size);
- rh->woff++;
- if (rh->woff == rh->max_size) rh->woff = 0;
- if (rh->size < rh->max_size) {
- rh->size++;
- } else {
- /* One packet was dropped */
- rh->roff++;
- if (rh->roff == rh->max_size) rh->roff = 0;
- }
- return 0;
-}
-
-static inline unsigned _ring_get_fullness(void **ring_ptr) {
- assert(*ring_ptr);
- ring_hdr_t *rh = ring_hdr(*ring_ptr);
- return rh->size * 100 / rh->max_size;
-}
-
-static inline unsigned _ring_is_full(void **ring_ptr) {
- assert(*ring_ptr);
- ring_hdr_t *rh = ring_hdr(*ring_ptr);
- return rh->size == rh->max_size;
-}
-
-static inline size_t _ring_get_size(void **ring_ptr) {
- assert(*ring_ptr);
- ring_hdr_t *rh = ring_hdr(*ring_ptr);
- return rh->size;
-}
-
-static inline int _ring_advance(void **ring_ptr, unsigned n) {
- assert(*ring_ptr);
- ring_hdr_t *rh = ring_hdr(*ring_ptr);
- assert(n <= rh->size);
-
- rh->roff += n;
- rh->size -= n;
- while (rh->roff >= rh->max_size) rh->roff -= rh->max_size;
- return 0;
-}
-
-static inline int _ring_get(void **ring_ptr, size_t elt_size, unsigned i,
- void *eltp) {
- assert(*ring_ptr);
- ring_hdr_t *rh = ring_hdr(*ring_ptr);
- assert(i <= rh->size);
- size_t pos = rh->roff + i;
- if (pos >= rh->max_size) pos -= rh->max_size;
- memcpy(eltp, (uint8_t *)*ring_ptr + pos * elt_size, elt_size);
- return 0;
-}
-
-/******************************************************************************/
-/* Public API */
-
-/**
- * @brief Allocate and initialize a ring data structure.
- *
- * @param[in,out] ring Ring to allocate and initialize.
- * @param[in] max_size Maximum ring size (nonzero).
- *
- * NOTE:
- * - Allocated memory is set to 0 (used by bitmap)
- */
-
-#define ring_init(RING, MAX_SIZE) \
- _ring_init((void **)&(RING), sizeof((RING)[0]), (MAX_SIZE))
-
-#define ring_free(RING) _ring_free((void **)&(RING))
-
-#define ring_get_fullness(RING) _ring_get_fullness((void **)&(RING))
-
-#define ring_is_full(RING) _ring_is_full((void **)&(RING))
-
-#define ring_get_size(RING) _ring_get_size((void **)&(RING))
-
-#define ring_add(RING, ELT) _ring_add((void **)&(RING), sizeof(RING[0]), ELT)
-
-#define ring_add_value(RING, VALUE) \
- do { \
- typeof(VALUE) _ring_var(v) = VALUE; \
- _ring_add((void **)&(RING), sizeof(RING[0]), &_ring_var(v)); \
- } while (0)
-
-#define ring_advance(RING, N) _ring_advance((void **)&(RING), (N))
-
-#define ring_get(RING, I, ELTP) \
- _ring_get((void **)&RING, sizeof(RING[0]), (I), (ELTP))
-
-/**
- * @brief Helper function used by ring_foreach().
- */
-#define ring_enumerate_n(RING, I, ELTP, COUNT, BODY) \
- ({ \
- for ((I) = 0; (I) < MIN(ring_get_size(RING), (COUNT)); (I)++) { \
- ring_get((RING), (I), (ELTP)); \
- { BODY; } \
- } \
- })
-
-#define ring_enumerate(ring, i, eltp, BODY) \
- ring_enumerate_n((ring), (i), (eltp), 1, (BODY))
-
-/**
- * @brief Iterate over elements in a ring.
- *
- * @param[in] pool The ring data structure to iterate over
- * @param[in, out] eltp A pointer to the element that will be used for
- * iteration
- * @param[in] BODY Block to execute during iteration
- *
- * @note Iteration will execute BODY with eltp corresponding successively to all
- * elements found in the ring. It is implemented using the more generic
- * enumeration function.
- */
-#define ring_foreach_n(ring, eltp, count, BODY) \
- ({ \
- unsigned _ring_var(i); \
- ring_enumerate_n((ring), _ring_var(i), (eltp), (count), BODY); \
- })
-
-#define ring_foreach(ring, eltp, BODY) ring_foreach_n((ring), (eltp), 1, (BODY))
-
-#endif /* UTIL_RING_H */
diff --git a/hicn-light/src/hicn/cli/hicnc.c b/hicn-light/src/hicn/cli/hicnc.c
index d14093b6b..3074016c5 100644
--- a/hicn-light/src/hicn/cli/hicnc.c
+++ b/hicn-light/src/hicn/cli/hicnc.c
@@ -25,6 +25,7 @@
#include "../config/parse.h"
#include <hicn/util/log.h>
#include <hicn/util/sstrncpy.h>
+#include <hicn/ctrl/hicn-light-ng.h>
#define PORT 9695
@@ -359,6 +360,70 @@ int main(int argc, char *const *argv) {
rc = hc_subscription_delete(s, &command.object.subscription);
break;
+ case OBJECT_STATS:
+ switch (command.action) {
+ case ACTION_GET:
+ rc = hc_stats_get(s, &data);
+ if (rc < 0) break;
+
+ hc_stats_snprintf(buf, MAX_LEN, (hicn_light_stats_t *)data->buffer);
+ INFO("\n%s", buf);
+ break;
+
+ case ACTION_LIST:
+ rc = hc_stats_list(s, &data);
+ if (rc < 0) break;
+
+ cmd_stats_list_item_t *conn_stats =
+ (cmd_stats_list_item_t *)data->buffer;
+ cmd_stats_list_item_t *end =
+ (cmd_stats_list_item_t *)(data->buffer +
+ data->size * data->out_element_size);
+ while (conn_stats < end) {
+ INFO("Connection #%d:", conn_stats->id);
+ INFO("\tinterests received: %d pkts (%d bytes)",
+ conn_stats->stats.interests.rx_pkts,
+ conn_stats->stats.interests.rx_bytes);
+ INFO("\tinterests transmitted: %d pkts (%d bytes)",
+ conn_stats->stats.interests.tx_pkts,
+ conn_stats->stats.interests.tx_bytes);
+ INFO("\tdata received: %d pkts (%d bytes)",
+ conn_stats->stats.data.rx_pkts,
+ conn_stats->stats.data.rx_bytes);
+ INFO("\tdata transmitted: %d pkts (%d bytes)",
+ conn_stats->stats.data.tx_pkts,
+ conn_stats->stats.data.tx_bytes);
+
+ conn_stats++;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+#ifdef TEST_FACE_CREATION
+ case OBJECT_FACE:
+ switch (command.action) {
+ case ACTION_CREATE: {
+ hc_face_t face = {0};
+ face.face.type = FACE_TYPE_UDP;
+ face.face.family = AF_INET;
+ face.face.local_addr = IPV4_LOOPBACK;
+ face.face.remote_addr = IPV4_LOOPBACK;
+ face.face.local_port = 9696;
+ face.face.remote_port = 9696;
+
+ rc = hc_face_create(s, &face);
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+#endif
+
default:
break;
}
diff --git a/hicn-light/src/hicn/cli/hicnd.c b/hicn-light/src/hicn/cli/hicnd.c
index e73517e4c..fa1b1c024 100644
--- a/hicn-light/src/hicn/cli/hicnd.c
+++ b/hicn-light/src/hicn/cli/hicnd.c
@@ -26,9 +26,9 @@
#include <sys/stat.h>
#include <hicn/util/log.h>
+#include <hicn/base/loop.h>
#include "logo.h"
-#include "../base/loop.h"
#include "../core/forwarder.h"
#include "../config/configuration.h" // XXX needed ?
#include "../config/configuration_file.h"
diff --git a/hicn-light/src/hicn/config/CMakeLists.txt b/hicn-light/src/hicn/config/CMakeLists.txt
index 00ee24077..90d0a2229 100644
--- a/hicn-light/src/hicn/config/CMakeLists.txt
+++ b/hicn-light/src/hicn/config/CMakeLists.txt
@@ -29,6 +29,7 @@ list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/command_policy.c
${CMAKE_CURRENT_SOURCE_DIR}/command_punting.c
${CMAKE_CURRENT_SOURCE_DIR}/command_route.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/command_stats.c
${CMAKE_CURRENT_SOURCE_DIR}/command_strategy.c
${CMAKE_CURRENT_SOURCE_DIR}/command_subscription.c
${CMAKE_CURRENT_SOURCE_DIR}/command.c
diff --git a/hicn-light/src/hicn/config/command_stats.c b/hicn-light/src/hicn/config/command_stats.c
new file mode 100644
index 000000000..70f74fd8c
--- /dev/null
+++ b/hicn-light/src/hicn/config/command_stats.c
@@ -0,0 +1,18 @@
+#include <math.h>
+#include "command.h"
+
+/* Commands */
+
+static const command_parser_t command_stats_get = {
+ .action = ACTION_GET,
+ .object = OBJECT_STATS,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_stats_get);
+
+static const command_parser_t command_stats_list = {
+ .action = ACTION_LIST,
+ .object = OBJECT_STATS,
+ .nparams = 0,
+};
+COMMAND_REGISTER(command_stats_list); \ No newline at end of file
diff --git a/hicn-light/src/hicn/config/commands.c b/hicn-light/src/hicn/config/commands.c
index e99e0b8f5..be00575d7 100644
--- a/hicn-light/src/hicn/config/commands.c
+++ b/hicn-light/src/hicn/config/commands.c
@@ -90,7 +90,8 @@ static inline unsigned _symbolic_to_conn_id(forwarder_t *forwarder,
}
} else {
// case for symbolic as input: check if symbolic name can be resolved
- conn_id = connection_table_get_id_by_name(table, symbolic_or_connid);
+ conn_id = (unsigned int)connection_table_get_id_by_name(table,
+ symbolic_or_connid);
if (connection_id_is_valid(conn_id)) {
DEBUG("Resolved symbolic name '%s' to conn_id %u", symbolic_or_connid,
conn_id);
@@ -151,6 +152,7 @@ uint8_t *configuration_on_listener_add(forwarder_t *forwarder, uint8_t *packet,
}
address_t address;
+ memset(&address, 0, sizeof(address_t));
if (address_from_ip_port(&address, control->family, &control->address,
control->port) < 0) {
WARN(
@@ -206,7 +208,8 @@ unsigned symbolic_to_listener_id(forwarder_t *forwarder,
}
} else {
// case for symbolic as input: check if symbolic name can be resolved
- listener_id = listener_table_get_id_by_name(table, symbolic_or_listener_id);
+ listener_id = (unsigned int)listener_table_get_id_by_name(
+ table, symbolic_or_listener_id);
if (listener_id_is_valid(listener_id)) {
DEBUG("Resolved symbolic name '%s' to conn_id %u",
symbolic_or_listener_id, listener_id);
@@ -262,7 +265,8 @@ uint8_t *configuration_on_listener_remove(forwarder_t *forwarder,
address_pair_get_local(pair)))
continue;
- unsigned conn_id = connection_table_get_connection_id(table, connection);
+ unsigned conn_id =
+ (unsigned int)connection_table_get_connection_id(table, connection);
/* Remove connection from the FIB */
forwarder_remove_connection_id_from_routes(forwarder, conn_id);
@@ -335,8 +339,9 @@ uint8_t *configuration_on_listener_list(forwarder_t *forwarder, uint8_t *packet,
uint8_t command_id = msg_received->header.command_id;
uint32_t seq_num = msg_received->header.seq_num;
- msg_listener_list_reply_t *msg;
- msg_malloc_list(msg, command_id, n, seq_num) if (!msg) goto NACK;
+ msg_listener_list_reply_t *msg = NULL;
+ msg_malloc_list(msg, command_id, n, seq_num);
+ if (!msg) goto NACK;
cmd_listener_list_item_t *payload = &msg->payload;
listener_t *listener;
@@ -376,14 +381,23 @@ uint8_t *configuration_on_connection_add(forwarder_t *forwarder,
goto NACK;
}
- const char *symbolic_name = control->symbolic;
-
if (!face_type_is_defined(control->type)) goto NACK;
connection_table_t *table = forwarder_get_connection_table(forwarder);
- if (connection_table_get_by_name(table, symbolic_name)) {
- ERROR("Connection symbolic name already exists");
- goto NACK;
+ char *symbolic_name = control->symbolic;
+
+ // Generate connection name if not specified
+ if (symbolic_name[0] == '\0') {
+ int rc = connection_table_get_random_name(table, symbolic_name);
+ if (rc < 0) {
+ ERROR("Unable to generate new connection name");
+ goto NACK;
+ }
+ } else {
+ if (connection_table_get_by_name(table, symbolic_name)) {
+ ERROR("Connection symbolic name already exists");
+ goto NACK;
+ }
}
address_pair_t pair;
@@ -561,6 +575,14 @@ static inline void fill_connections_command(forwarder_t *forwarder,
}
}
+static inline void fill_connection_stats_command(connection_t *connection,
+ cmd_stats_list_item_t *cmd) {
+ assert(connection && cmd);
+
+ cmd->id = connection->id;
+ cmd->stats = connection->stats;
+}
+
uint8_t *configuration_on_connection_list(forwarder_t *forwarder,
uint8_t *packet, unsigned ingress_id,
size_t *reply_size) {
@@ -576,8 +598,9 @@ uint8_t *configuration_on_connection_list(forwarder_t *forwarder,
uint8_t command_id = msg_received->header.command_id;
uint32_t seq_num = msg_received->header.seq_num;
- msg_connection_list_reply_t *msg;
- msg_malloc_list(msg, command_id, n, seq_num) if (!msg) goto NACK;
+ msg_connection_list_reply_t *msg = NULL;
+ msg_malloc_list(msg, command_id, n, seq_num);
+ if (!msg) goto NACK;
cmd_connection_list_item_t *payload = &msg->payload;
connection_t *connection;
@@ -807,7 +830,7 @@ uint8_t *configuration_on_route_list(forwarder_t *forwarder, uint8_t *packet,
n += nexthops_get_len(nexthops);
});
- msg_route_list_reply_t *msg;
+ msg_route_list_reply_t *msg = NULL;
msg_malloc_list(msg, command_id, n, seq_num);
if (!msg) goto NACK;
@@ -938,8 +961,9 @@ uint8_t *configuration_on_cache_list(forwarder_t *forwarder, uint8_t *packet,
.payload = {
.store_in_cs = forwarder_cs_get_store(forwarder),
.serve_from_cs = forwarder_cs_get_serve(forwarder),
- .cs_size = forwarder_cs_get_size(forwarder),
- .num_stale_entries = forwarder_cs_get_num_stale_entries(forwarder)}};
+ .cs_size = (unsigned int)forwarder_cs_get_size(forwarder),
+ .num_stale_entries =
+ (unsigned int)forwarder_cs_get_num_stale_entries(forwarder)}};
*reply_size = sizeof(*msg);
return (uint8_t *)msg;
@@ -1068,6 +1092,65 @@ NACK:
return (uint8_t *)msg;
}
+/* Statistics */
+
+uint8_t *configuration_on_stats_get(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size) {
+ assert(forwarder && packet);
+ INFO("CMD: stats get (ingress=%d)", ingress_id);
+
+ msg_stats_get_t *msg_received = (msg_stats_get_t *)packet;
+ uint32_t seq_num = msg_received->header.seq_num;
+
+ msg_stats_get_reply_t *msg = malloc(sizeof(*msg));
+ *msg = (msg_stats_get_reply_t){
+ .header = {.message_type = RESPONSE_LIGHT,
+ .length = 1,
+ .seq_num = seq_num},
+ .payload = {.forwarder = forwarder_get_stats(forwarder),
+ .pkt_cache =
+ pkt_cache_get_stats(forwarder_get_pkt_cache(forwarder))}
+
+ };
+
+ *reply_size = sizeof(*msg);
+ return (uint8_t *)msg;
+}
+
+uint8_t *configuration_on_stats_list(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size) {
+ assert(forwarder && packet);
+ INFO("CMD: stats list (ingress=%d)", ingress_id);
+
+ connection_table_t *table = forwarder_get_connection_table(forwarder);
+ // -1 since current connection (i.e. the one used to send
+ // the command) is not considered
+ size_t n = connection_table_len(table) - 1;
+ msg_stats_list_t *msg_received = (msg_stats_list_t *)packet;
+ uint8_t command_id = msg_received->header.command_id;
+ uint32_t seq_num = msg_received->header.seq_num;
+
+ msg_stats_list_reply_t *msg = NULL;
+ msg_malloc_list(msg, command_id, n, seq_num);
+ if (!msg) goto NACK;
+
+ cmd_stats_list_item_t *payload = &msg->payload;
+ connection_t *connection;
+ connection_table_foreach(table, connection, {
+ if (connection->id == ingress_id) continue;
+ fill_connection_stats_command(connection, payload);
+ payload++;
+ });
+
+ *reply_size = sizeof(msg->header) + n * sizeof(msg->payload);
+ return (uint8_t *)msg;
+
+NACK:
+ *reply_size = sizeof(msg_header_t);
+ make_nack(msg);
+ return (uint8_t *)msg;
+}
+
/* WLDR */
uint8_t *configuration_on_wldr_set(forwarder_t *forwarder, uint8_t *packet,
@@ -1365,7 +1448,7 @@ uint8_t *configuration_on_policy_list(forwarder_t *forwarder, uint8_t *packet,
uint8_t command_id = msg_received->header.command_id;
uint32_t seq_num = msg_received->header.seq_num;
- msg_policy_list_reply_t *msg;
+ msg_policy_list_reply_t *msg = NULL;
msg_malloc_list(msg, command_id, n, seq_num);
if (!msg) goto NACK;
diff --git a/hicn-light/src/hicn/config/commands.h b/hicn-light/src/hicn/config/commands.h
index cedf4de01..3852a76ac 100644
--- a/hicn-light/src/hicn/config/commands.h
+++ b/hicn-light/src/hicn/config/commands.h
@@ -149,4 +149,7 @@ uint8_t *configuration_on_policy_remove(forwarder_t *forwarder, uint8_t *packet,
uint8_t *configuration_on_policy_list(forwarder_t *forwarder, uint8_t *packet,
unsigned ingress_id, size_t *reply_size);
+uint8_t *configuration_on_stats_list(forwarder_t *forwarder, uint8_t *packet,
+ unsigned ingress_id, size_t *reply_size);
+
#endif // HICNLIGHT_COMMANDS_H
diff --git a/hicn-light/src/hicn/config/configuration.h b/hicn-light/src/hicn/config/configuration.h
index 9861b6c9f..93b4cf7c3 100644
--- a/hicn-light/src/hicn/config/configuration.h
+++ b/hicn-light/src/hicn/config/configuration.h
@@ -26,7 +26,7 @@
#ifndef HICNLIGHT_CONFIGURATION_H
#define HICNLIGHT_CONFIGURATION_H
-#include "../base/khash.h"
+#include <hicn/util/khash.h>
#include "../core/msgbuf.h"
#include "../core/strategy.h"
#include <hicn/ctrl/api.h>
diff --git a/hicn-light/src/hicn/core/CMakeLists.txt b/hicn-light/src/hicn/core/CMakeLists.txt
index 57ffb780f..9516a6a72 100644
--- a/hicn-light/src/hicn/core/CMakeLists.txt
+++ b/hicn-light/src/hicn/core/CMakeLists.txt
@@ -21,6 +21,7 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/fib_entry.h
${CMAKE_CURRENT_SOURCE_DIR}/fib.h
${CMAKE_CURRENT_SOURCE_DIR}/forwarder.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/interest_manifest.h
${CMAKE_CURRENT_SOURCE_DIR}/listener.h
${CMAKE_CURRENT_SOURCE_DIR}/listener_table.h
${CMAKE_CURRENT_SOURCE_DIR}/listener_vft.h
@@ -52,6 +53,7 @@ list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/fib.c
${CMAKE_CURRENT_SOURCE_DIR}/fib_entry.c
${CMAKE_CURRENT_SOURCE_DIR}/forwarder.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/interest_manifest.c
${CMAKE_CURRENT_SOURCE_DIR}/listener.c
${CMAKE_CURRENT_SOURCE_DIR}/listener_table.c
${CMAKE_CURRENT_SOURCE_DIR}/listener_vft.c
diff --git a/hicn-light/src/hicn/core/address_pair.h b/hicn-light/src/hicn/core/address_pair.h
index 72b92d6b5..2fd207d34 100644
--- a/hicn-light/src/hicn/core/address_pair.h
+++ b/hicn-light/src/hicn/core/address_pair.h
@@ -43,6 +43,12 @@ int address_pair_from_ip_port(address_pair_t* pair, int family,
ip_address_t* local_addr, uint16_t local_port,
ip_address_t* remote_addr, uint16_t remote_port);
+static inline int address_pair_equals(const address_pair_t* pair1,
+ const address_pair_t* pair2) {
+ return address_equals(&pair1->local, &pair2->local) &&
+ address_equals(&pair1->remote, &pair2->remote);
+}
+
#define address_pair_get_local(pair) (&(pair)->local)
#define address_pair_get_remote(pair) (&(pair)->remote)
diff --git a/hicn-light/src/hicn/core/connection.c b/hicn-light/src/hicn/core/connection.c
index c8cc1d0b9..2108d30af 100644
--- a/hicn-light/src/hicn/core/connection.c
+++ b/hicn-light/src/hicn/core/connection.c
@@ -28,8 +28,6 @@
#include "connection.h"
#include "connection_vft.h"
-#define _conn_var(x) _connection_##x
-
// This is called by configuration
connection_t *connection_create(face_type_t type, const char *name,
const address_pair_t *pair,
@@ -212,18 +210,16 @@ int connection_send_packet(const connection_t *connection,
connection, packet, size);
}
-bool _connection_send(const connection_t *connection, msgbuf_t *msgbuf,
- bool queue) {
+bool _connection_send(connection_t *connection, msgbuf_t *msgbuf, bool queue) {
return connection_vft[get_protocol(connection->type)]->send(connection,
msgbuf, queue);
}
-bool connection_flush(const connection_t *connection) {
+bool connection_flush(connection_t *connection) {
return connection_vft[get_protocol(connection->type)]->flush(connection);
}
-bool connection_send(const connection_t *connection, off_t msgbuf_id,
- bool queue) {
+bool connection_send(connection_t *connection, off_t msgbuf_id, bool queue) {
assert(connection);
assert(msgbuf_id_is_valid(msgbuf_id));
@@ -254,7 +250,7 @@ bool connection_send(const connection_t *connection, off_t msgbuf_id,
* handled inside the MessageProcessor. This is specific to WLDR
* retransmittions. This is done only for data packets
*/
-bool connection_resend(const connection_t *connection, msgbuf_t *msgbuf,
+bool connection_resend(connection_t *connection, msgbuf_t *msgbuf,
bool notification) {
assert(connection);
assert(msgbuf);
diff --git a/hicn-light/src/hicn/core/connection.h b/hicn-light/src/hicn/core/connection.h
index 05dc1d6e2..ac75428dd 100644
--- a/hicn-light/src/hicn/core/connection.h
+++ b/hicn-light/src/hicn/core/connection.h
@@ -84,6 +84,7 @@ typedef struct {
*/
struct wldr_s* wldr;
+ connection_stats_t stats;
} connection_t;
#if 1
@@ -209,10 +210,9 @@ int connection_finalize(connection_t* connection);
int connection_send_packet(const connection_t* connection,
const uint8_t* packet, size_t size);
-bool connection_flush(const connection_t* connection);
+bool connection_flush(connection_t* connection);
-bool connection_send(const connection_t* connection, off_t msgbuf_id,
- bool queue);
+bool connection_send(connection_t* connection, off_t msgbuf_id, bool queue);
size_t connection_process_buffer(connection_t* connection,
const uint8_t* buffer, size_t size);
diff --git a/hicn-light/src/hicn/core/connection_table.c b/hicn-light/src/hicn/core/connection_table.c
index 09236ae8e..c723073a1 100644
--- a/hicn-light/src/hicn/core/connection_table.c
+++ b/hicn-light/src/hicn/core/connection_table.c
@@ -74,6 +74,54 @@ void connection_table_free(connection_table_t *table) {
free(table);
}
+connection_t *connection_table_allocate(const connection_table_t *table,
+ const address_pair_t *pair,
+ const char *name) {
+ connection_t *conn = NULL;
+ pool_get(table->connections, conn);
+ if (!conn) return NULL;
+
+ off_t id = conn - table->connections;
+ int rc;
+
+ // Add in name hash table
+ khiter_t k = kh_put_ct_name(table->id_by_name, strdup(name), &rc);
+ assert(rc == KH_ADDED || rc == KH_RESET);
+ kh_value(table->id_by_name, k) = (unsigned int)id;
+
+ // Add in pair hash table
+ address_pair_t *pair_copy = (address_pair_t *)malloc(sizeof(address_pair_t));
+ memcpy(pair_copy, pair, sizeof(address_pair_t));
+
+ k = kh_put_ct_pair(table->id_by_pair, pair_copy, &rc);
+ assert(rc == KH_ADDED || rc == KH_RESET);
+ kh_value(table->id_by_pair, k) = (unsigned int)id;
+
+ assert(kh_size(table->id_by_name) == kh_size(table->id_by_pair));
+ return conn;
+}
+
+void connection_table_deallocate(const connection_table_t *table,
+ const connection_t *conn) {
+ const char *name = connection_get_name(conn);
+ const address_pair_t *pair = connection_get_pair(conn);
+
+ // Remove from name hash table
+ khiter_t k = kh_get_ct_name(table->id_by_name, name);
+ assert(k != kh_end(table->id_by_name));
+ free((char *)kh_key(table->id_by_name, k));
+ kh_del_ct_name(table->id_by_name, k);
+
+ // Remove from pair hash table
+ k = kh_get_ct_pair(table->id_by_pair, pair);
+ assert(k != kh_end(table->id_by_pair));
+ free((address_pair_t *)kh_key(table->id_by_pair, k));
+ kh_del_ct_pair(table->id_by_pair, k);
+
+ assert(kh_size(table->id_by_name) == kh_size(table->id_by_pair));
+ pool_put(table->connections, conn);
+}
+
connection_t *connection_table_get_by_pair(const connection_table_t *table,
const address_pair_t *pair) {
khiter_t k = kh_get_ct_pair(table->id_by_pair, pair);
@@ -90,7 +138,7 @@ off_t connection_table_get_id_by_name(const connection_table_t *table,
connection_t *connection_table_get_by_name(const connection_table_t *table,
const char *name) {
- unsigned conn_id = connection_table_get_id_by_name(table, name);
+ unsigned conn_id = (unsigned int)connection_table_get_id_by_name(table, name);
if (!connection_id_is_valid(conn_id)) return NULL;
return connection_table_at(table, conn_id);
}
@@ -141,22 +189,24 @@ connection_t *_connection_table_get_by_id(connection_table_t *table, off_t id) {
return connection_table_get_by_id(table, id);
}
-#define RANDBYTE() (u8)(rand() & 0xFF)
-
-char *connection_table_get_random_name(const connection_table_t *table) {
- char *connection_name = malloc(SYMBOLIC_NAME_LEN * sizeof(char));
- u8 rand_num;
+static inline u16 RAND16() { return rand() & 0xFFFF; }
- /* Generate a random connection name */
- while (1) {
- rand_num = RANDBYTE();
- int rc = snprintf(connection_name, SYMBOLIC_NAME_LEN, "conn%u", rand_num);
- _ASSERT(rc < SYMBOLIC_NAME_LEN);
+int connection_table_get_random_name(const connection_table_t *table,
+ char *name) {
+ int i, n_attempts = 2 * USHRT_MAX;
+ for (i = 0; i < n_attempts; i++) {
+ int rc = snprintf(name, SYMBOLIC_NAME_LEN, "conn%u", RAND16());
+ if (rc >= SYMBOLIC_NAME_LEN) continue;
- // Return if connection name does not already exist
- khiter_t k = kh_get_ct_name(table->id_by_name, connection_name);
+ // Check if generated connection name is a duplicate
+ khiter_t k = kh_get_ct_name(table->id_by_name, name);
if (k == kh_end(table->id_by_name)) break;
}
- return connection_name;
+ if (i == n_attempts) {
+ ERROR("Unable to generate new unique connection name");
+ return -1;
+ }
+
+ return 0;
} \ No newline at end of file
diff --git a/hicn-light/src/hicn/core/connection_table.h b/hicn-light/src/hicn/core/connection_table.h
index 4c03aa642..7d4bad761 100644
--- a/hicn-light/src/hicn/core/connection_table.h
+++ b/hicn-light/src/hicn/core/connection_table.h
@@ -30,22 +30,18 @@
#ifndef HICNLIGHT_CONNECTION_TABLE_H
#define HICNLIGHT_CONNECTION_TABLE_H
+#include <hicn/util/khash.h>
+#include <hicn/util/hash.h>
#include "address_pair.h"
#include "connection.h"
-#include "../base/hash.h"
-#include "../base/khash.h"
-#include "../base/pool.h"
-
-#define _ct_var(x) _ct_var_##x
+#include <hicn/util/pool.h>
/* Hash functions for indices. */
#define address_pair_hash(pair) (hash_struct(pair))
-#define address_pair_hash_eq(a, b) \
- (address_pair_hash(b) == address_pair_hash(a))
/* Hash table types for indices. */
KHASH_INIT(ct_pair, const address_pair_t *, unsigned, 1, address_pair_hash,
- address_pair_hash_eq);
+ address_pair_equals);
KHASH_MAP_INIT_STR(ct_name, unsigned);
typedef struct {
@@ -72,34 +68,9 @@ typedef struct {
* - You should always check that the returned connection is not NULL, which
* would signal that the pool is exhausted and could not be extended.
*/
-static inline connection_t *connection_table_allocate(
- const connection_table_t *table, const address_pair_t *pair,
- const char *name) {
- connection_t *conn;
- pool_get(table->connections, conn);
-
- if (conn) {
- off_t id = conn - table->connections;
- int res;
- khiter_t k;
-
- // Add in name hash table
- k = kh_put_ct_name(table->id_by_name, strdup(name), &res);
- kh_value(table->id_by_name, k) = id;
-
- // Add in pair hash table
- address_pair_t *pair_copy =
- (address_pair_t *)malloc(sizeof(address_pair_t));
- memcpy(pair_copy, pair, sizeof(address_pair_t));
-
- k = kh_put_ct_pair(table->id_by_pair, pair_copy, &res);
- assert(res != -1);
- kh_value(table->id_by_pair, k) = id;
- }
-
- return conn;
-}
-
+connection_t *connection_table_allocate(const connection_table_t *table,
+ const address_pair_t *pair,
+ const char *name);
/**
* @brief Deallocate a connection and return it to the connection table pool.
*
@@ -110,26 +81,8 @@ static inline connection_t *connection_table_allocate(
* - Upon returning a connection to the pool, all indices pointing to that
* connection are also cleared.
*/
-static inline void connection_table_deallocate(const connection_table_t *table,
- const connection_t *conn) {
- const char *name = connection_get_name(conn);
- const address_pair_t *pair = connection_get_pair(conn);
- khiter_t k;
-
- // Remove from name hash table
- k = kh_get_ct_name(table->id_by_name, name);
- assert(k != kh_end(table->id_by_name));
- free((char *)kh_key(table->id_by_name, k));
- kh_del_ct_name(table->id_by_name, k);
-
- // Remove from pair hash table
- k = kh_get_ct_pair(table->id_by_pair, pair);
- assert(k != kh_end(table->id_by_pair));
- free((address_pair_t *)kh_key(table->id_by_pair, k));
- kh_del_ct_pair(table->id_by_pair, k);
-
- pool_put(table->connections, conn);
-}
+void connection_table_deallocate(const connection_table_t *table,
+ const connection_t *conn);
/**
* @brief Returns the length of the connection table, the number of active
@@ -292,6 +245,7 @@ void connection_table_print_by_pair(const connection_table_t *table);
void connection_table_print_by_name(const connection_table_t *table);
-char *connection_table_get_random_name(const connection_table_t *table);
+int connection_table_get_random_name(const connection_table_t *table,
+ char *name);
#endif /* HICNLIGHT_CONNECTION_TABLE_H */
diff --git a/hicn-light/src/hicn/core/connection_vft.h b/hicn-light/src/hicn/core/connection_vft.h
index e6290cdd4..1a6ecbb78 100644
--- a/hicn-light/src/hicn/core/connection_vft.h
+++ b/hicn-light/src/hicn/core/connection_vft.h
@@ -28,8 +28,8 @@ typedef struct {
void (*finalize)(connection_t* connection);
int (*get_socket)(const listener_t* listener, const address_t* local,
const address_t* remote, const char* interface_name);
- bool (*flush)(const connection_t* connection);
- bool (*send)(const connection_t* connection, msgbuf_t* msgbuf, bool queue);
+ bool (*flush)(connection_t* connection);
+ bool (*send)(connection_t* connection, msgbuf_t* msgbuf, bool queue);
int (*send_packet)(const connection_t* connection, const uint8_t* packet,
size_t size);
// void (*read_callback)(connection_t * connection, int fd, void * data);
diff --git a/hicn-light/src/hicn/core/content_store.c b/hicn-light/src/hicn/core/content_store.c
index edbdc5ac1..360e6d333 100644
--- a/hicn-light/src/hicn/core/content_store.c
+++ b/hicn-light/src/hicn/core/content_store.c
@@ -84,3 +84,5 @@ void cs_log(cs_t *cs) {
cs->stats.lru.countUpdates, cs->stats.lru.countLruDeletions,
cs->stats.lru.countLruEvictions);
}
+
+cs_lru_stats_t cs_get_lru_stats(cs_t *cs) { return cs->stats.lru; }
diff --git a/hicn-light/src/hicn/core/content_store.h b/hicn-light/src/hicn/core/content_store.h
index d47d603be..ceaf05e6b 100644
--- a/hicn-light/src/hicn/core/content_store.h
+++ b/hicn-light/src/hicn/core/content_store.h
@@ -1,7 +1,7 @@
#ifndef HICNLIGHT_CS_H
#define HICNLIGHT_CS_H
-#include "../base/pool.h"
+#include <hicn/util/pool.h>
#include "../content_store/lru.h"
#include "msgbuf_pool.h"
@@ -103,4 +103,6 @@ void cs_miss(cs_t *cs);
*/
void cs_log(cs_t *cs);
+cs_lru_stats_t cs_get_lru_stats(cs_t *cs);
+
#endif /* HICNLIGHT_CS_H */
diff --git a/hicn-light/src/hicn/core/fib_entry.c b/hicn-light/src/hicn/core/fib_entry.c
index 616f12961..80d337884 100644
--- a/hicn-light/src/hicn/core/fib_entry.c
+++ b/hicn-light/src/hicn/core/fib_entry.c
@@ -378,7 +378,7 @@ nexthops_t *fib_entry_get_available_nexthops(fib_entry_t *entry,
connection_table_foreach(table, connection, {
if (connection_is_local(connection)) continue;
new_nexthops->elts[nexthops_get_len(new_nexthops)] =
- connection_table_get_connection_id(table, connection);
+ (unsigned int)connection_table_get_connection_id(table, connection);
nexthops_inc(new_nexthops);
});
diff --git a/hicn-light/src/hicn/core/forwarder.c b/hicn-light/src/hicn/core/forwarder.c
index 37502f3ac..74be6431a 100644
--- a/hicn-light/src/hicn/core/forwarder.c
+++ b/hicn-light/src/hicn/core/forwarder.c
@@ -69,45 +69,9 @@
#endif /* WITH_POLICY_STATS */
#include <hicn/core/wldr.h>
+#include <hicn/core/interest_manifest.h>
#include <hicn/util/log.h>
-typedef struct {
- // Packets processed
- uint32_t countReceived; // Interest and data only
- uint32_t countInterestsReceived;
- uint32_t countObjectsReceived;
-
- // Packets Dropped
- uint32_t countDropped;
- uint32_t countInterestsDropped;
- uint32_t countObjectsDropped;
- uint32_t countOtherDropped;
-
- // Forwarding
- uint32_t countInterestForwarded;
- uint32_t countObjectsForwarded;
-
- // Errors while forwarding
- uint32_t countDroppedConnectionNotFound;
- uint32_t countSendFailures;
- uint32_t countDroppedNoRoute;
-
- // Interest processing
- uint32_t countInterestsAggregated;
- uint32_t countInterestsRetransmitted;
- uint32_t countInterestsSatisfiedFromStore;
- uint32_t countInterestsExpired;
- uint32_t countDataExpired;
-
- // Data processing
- uint32_t countDroppedNoReversePath;
-
- // TODO(eloparco): Currently not used
- // uint32_t countDroppedNoHopLimit;
- // uint32_t countDroppedZeroHopLimitFromRemote;
- // uint32_t countDroppedZeroHopLimitToRemote;
-} forwarder_stats_t;
-
struct forwarder_s {
// uint16_t server_port;
@@ -138,13 +102,12 @@ struct forwarder_s {
* The message forwarder has to decide whether to queue incoming packets for
* batching, or trigger the transmission on the connection
*/
- unsigned pending_conn[MAX_MSG];
- size_t num_pending_conn;
-
- // msgbuf_t msgbuf; /* Storage for msgbuf, which are currently processed 1 by
- // 1 */
+ unsigned *pending_conn;
subscription_table_t *subscriptions;
+
+ // Used to store the msgbufs that need to be released
+ off_t *acquired_msgbuf_ids;
};
/**
@@ -223,8 +186,12 @@ forwarder_t *forwarder_create(configuration_t *configuration) {
#endif /* WITH_POLICY_STATS */
memset(&forwarder->stats, 0, sizeof(forwarder_stats_t));
+ vector_init(forwarder->pending_conn, MAX_MSG, 0);
+ vector_init(forwarder->acquired_msgbuf_ids, MAX_MSG, 0);
- forwarder->num_pending_conn = 0;
+ char *n_suffixes_per_split_str = getenv("N_SUFFIXES_PER_SPIT");
+ if (n_suffixes_per_split_str)
+ N_SUFFIXES_PER_SPIT = atoi(n_suffixes_per_split_str);
return forwarder;
@@ -267,6 +234,8 @@ void forwarder_free(forwarder_t *forwarder) {
listener_table_free(forwarder->listener_table);
subscription_table_free(forwarder->subscriptions);
configuration_free(forwarder->config);
+ vector_free(forwarder->pending_conn);
+ vector_free(forwarder->acquired_msgbuf_ids);
free(forwarder);
}
@@ -295,6 +264,11 @@ listener_table_t *forwarder_get_listener_table(forwarder_t *forwarder) {
return forwarder->listener_table;
}
+pkt_cache_t *forwarder_get_pkt_cache(const forwarder_t *forwarder) {
+ assert(forwarder);
+ return forwarder->pkt_cache;
+}
+
void forwarder_cs_set_store(forwarder_t *forwarder, bool val) {
assert(forwarder);
forwarder->store_in_cs = val;
@@ -393,7 +367,7 @@ static ssize_t forwarder_forward_via_connection(forwarder_t *forwarder,
const msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
- const connection_t *conn = connection_table_get_by_id(table, conn_id);
+ connection_t *conn = connection_table_get_by_id(table, conn_id);
if (!conn) {
forwarder->stats.countDroppedConnectionNotFound++;
@@ -429,12 +403,8 @@ static ssize_t forwarder_forward_via_connection(forwarder_t *forwarder,
#endif
/* ... and mark the connection as pending if this is not yet the case */
- unsigned i;
- for (i = 0; i < forwarder->num_pending_conn; i++) {
- if (forwarder->pending_conn[i] == conn_id) break;
- }
- if (i == forwarder->num_pending_conn) // Not found
- forwarder->pending_conn[forwarder->num_pending_conn++] = conn_id;
+ if (!vector_contains(forwarder->pending_conn, conn_id))
+ vector_push(forwarder->pending_conn, conn_id);
if (!success) {
forwarder->stats.countSendFailures++;
@@ -457,7 +427,8 @@ static ssize_t forwarder_forward_via_connection(forwarder_t *forwarder,
break;
}
- TRACE("forward msgbuf %p to interface %u", msgbuf, conn_id);
+ TRACE("forward msgbuf %p (size=%u) to interface %u", msgbuf,
+ msgbuf_get_len(msgbuf), conn_id);
return msgbuf_get_len(msgbuf);
}
@@ -496,8 +467,7 @@ static unsigned forwarder_forward_to_nexthops(forwarder_t *forwarder,
static bool forwarder_forward_via_fib(forwarder_t *forwarder, off_t msgbuf_id,
pkt_cache_verdict_t verdict,
pkt_cache_entry_t *entry) {
- assert(forwarder);
- assert(msgbuf_id_is_valid(msgbuf_id));
+ assert(forwarder && entry && msgbuf_id_is_valid(msgbuf_id));
const msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
@@ -515,15 +485,8 @@ static bool forwarder_forward_via_fib(forwarder_t *forwarder, off_t msgbuf_id,
return false;
}
- // if this is the first time that we sent this interest the pit entry would be
- // NULL. in that case we add the interest to the pit
- if (entry == NULL) {
- entry = pkt_cache_add_to_pit(forwarder->pkt_cache, msgbuf);
- }
pit_entry_t *pit_entry = &entry->u.pit_entry;
- if (!pit_entry) {
- return false;
- }
+ if (!pit_entry) return false;
pit_entry_set_fib_entry(pit_entry, fib_entry);
@@ -547,21 +510,19 @@ static bool forwarder_forward_via_fib(forwarder_t *forwarder, off_t msgbuf_id,
#endif /* ! BYPASS_FIB */
-ssize_t _forwarder_forward_upon_interest(forwarder_t *forwarder,
- msgbuf_pool_t *msgbuf_pool,
- off_t data_msgbuf_id,
- off_t interest_msgbuf_id,
- pkt_cache_entry_t *entry,
- pkt_cache_verdict_t verdict) {
+int _forwarder_forward_upon_interest(
+ forwarder_t *forwarder, msgbuf_pool_t *msgbuf_pool, off_t data_msgbuf_id,
+ off_t interest_msgbuf_id, pkt_cache_entry_t *entry,
+ pkt_cache_verdict_t verdict, bool is_aggregated) {
msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, interest_msgbuf_id);
+ // - Aggregation can be perfomed, do not forward
if (verdict == PKT_CACHE_VERDICT_AGGREGATE_INTEREST) {
- // the packet shuold not be forwarder
forwarder_drop(forwarder, interest_msgbuf_id);
return msgbuf_get_len(msgbuf);
}
- // - Forward reply if a data packet matching the interest was found
+ // - Data packet matching the interest was found, forward reply
if (verdict == PKT_CACHE_VERDICT_FORWARD_DATA) {
assert(forwarder->serve_from_cs == true);
@@ -569,19 +530,26 @@ ssize_t _forwarder_forward_upon_interest(forwarder_t *forwarder,
msgbuf_t *data_msgbuf = msgbuf_pool_at(msgbuf_pool, data_msgbuf_id);
msgbuf_reset_pathlabel(data_msgbuf);
-
forwarder_forward_via_connection(forwarder, data_msgbuf_id,
msgbuf_get_connection_id(interest_msgbuf));
+ return msgbuf_get_len(msgbuf);
+ }
+
+ // - For aggregated interest, the interest forwarding is done in
+ // `_forwarder_forward_aggregated_interest()`
+ if (is_aggregated) return msgbuf_get_len(msgbuf);
- // - Try to forward the interest
- } else if (!forwarder_forward_via_fib(forwarder, interest_msgbuf_id, verdict,
- entry)) {
+ // - Try to forward the interest
+ int rc =
+ forwarder_forward_via_fib(forwarder, interest_msgbuf_id, verdict, entry);
+ if (!rc) {
+ // - Not able to forward, drop the packet
forwarder->stats.countDroppedNoRoute++;
INFO("Message %lu did not match FIB, no route (count %u)",
interest_msgbuf_id, forwarder->stats.countDroppedNoRoute);
- // - Drop the packet (no forwarding)
forwarder_drop(forwarder, interest_msgbuf_id);
+ return -1;
}
return msgbuf_get_len(msgbuf);
@@ -590,19 +558,12 @@ ssize_t _forwarder_forward_upon_interest(forwarder_t *forwarder,
static void _forwarder_update_interest_stats(forwarder_t *forwarder,
pkt_cache_verdict_t verdict,
msgbuf_t *msgbuf,
- pkt_cache_entry_t *entry) {
- long expiration = -1;
- if (entry == NULL)
- expiration = ticks_now() + msgbuf_get_interest_lifetime(msgbuf);
- else if (entry->has_expire_ts)
- expiration = entry->expire_ts;
-
+ bool has_expire_ts,
+ uint64_t expire_ts) {
+ long expiration = has_expire_ts ? expire_ts : -1;
switch (verdict) {
case PKT_CACHE_VERDICT_FORWARD_INTEREST:
- DEBUG(
- "Message will be added to PIT (expiration=%ld), "
- "if nexthops are available",
- expiration);
+ DEBUG("Message added to PIT (expiration=%ld)", expiration);
break;
case PKT_CACHE_VERDICT_AGGREGATE_INTEREST:
@@ -632,7 +593,7 @@ static void _forwarder_update_interest_stats(forwarder_t *forwarder,
break;
case PKT_CACHE_VERDICT_ERROR:
- ERROR("Inivalid packet cache content");
+ ERROR("Invalid packet cache content");
break;
default:
@@ -640,6 +601,234 @@ static void _forwarder_update_interest_stats(forwarder_t *forwarder,
}
}
+static interest_manifest_header_t *_forwarder_get_interest_manifest(
+ msgbuf_t *msgbuf) {
+ uint8_t *packet = msgbuf_get_packet(msgbuf);
+ hicn_header_t *header = (hicn_header_t *)packet;
+ hicn_type_t type = hicn_header_to_type(header);
+
+ hicn_payload_type_t payload_type;
+ int rc = hicn_ops_vft[type.l1]->get_payload_type(type, &header->protocol,
+ &payload_type);
+ _ASSERT(rc == HICN_LIB_ERROR_NONE);
+ if (payload_type != HPT_MANIFEST) return NULL;
+
+ size_t header_length, payload_length;
+ rc = hicn_ops_vft[type.l1]->get_header_length(type, &header->protocol,
+ &header_length);
+ assert(rc == HICN_LIB_ERROR_NONE);
+
+ rc = hicn_ops_vft[type.l1]->get_payload_length(type, &header->protocol,
+ &payload_length);
+ assert(rc == HICN_LIB_ERROR_NONE);
+
+ u8 *payload = (u8 *)header + header_length;
+ interest_manifest_header_t *int_manifest_header =
+ (interest_manifest_header_t *)payload;
+ if (!interest_manifest_is_valid(int_manifest_header, payload_length))
+ return NULL;
+
+ return int_manifest_header;
+}
+
+// Manifest is split using splitting strategy, then every
+// sub-manifest is sent using the forwarding strategy defined for the prefix
+int _forwarder_forward_aggregated_interest(
+ forwarder_t *forwarder, interest_manifest_header_t *int_manifest_header,
+ int n_suffixes_to_fwd, msgbuf_t *msgbuf, off_t msgbuf_id,
+ pkt_cache_entry_t **entries) {
+ assert(msgbuf_id_is_valid(msgbuf_id) &&
+ msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
+
+ fib_entry_t *fib_entry = fib_match_message(forwarder->fib, msgbuf);
+ if (!fib_entry) return -1;
+
+ int n_suffixes_per_split = N_SUFFIXES_PER_SPIT;
+ switch (disaggregation_strategy) {
+ case INT_MANIFEST_SPLIT_NONE:
+ n_suffixes_per_split = int_manifest_header->n_suffixes + 1;
+
+ case INT_MANIFEST_SPLIT_MAX_N_SUFFIXES: {
+ // Generate sub-manifests: same as original manifest,
+ // but different suffix in the header and different bitmap
+
+ int total_len = 0;
+ // Suffixes in manifest plus the one in the header
+ int total_suffixes = int_manifest_header->n_suffixes + 1;
+
+ // Save copy of original bitmap to use as a reference
+ // to generate bitmaps for sub-manifests
+ u32 original_bitmap[BITMAP_SIZE] = {0};
+ memcpy(&original_bitmap, int_manifest_header->request_bitmap,
+ BITMAP_SIZE * sizeof(u32));
+
+ int suffix_index = 0; // Position of suffix in initial manifest
+ while (suffix_index < total_suffixes) {
+ // If more than one sub-manifest,
+ // clone original interest manifest and update suffix
+ if (suffix_index > 0) {
+ msgbuf_t *clone;
+ off_t clone_id =
+ msgbuf_pool_clone(forwarder->msgbuf_pool, &clone, msgbuf_id);
+ msgbuf_pool_acquire(clone);
+ forwarder_acquired_msgbuf_ids_push(forwarder, clone_id);
+
+ msgbuf_id = clone_id;
+ msgbuf = clone;
+ }
+
+ u32 curr_bitmap[BITMAP_SIZE] = {0};
+ int first_suffix_index_in_submanifest = suffix_index;
+ suffix_index = interest_manifest_update_bitmap(
+ original_bitmap, curr_bitmap, suffix_index, total_suffixes,
+ n_suffixes_per_split);
+ int first_suffix_index_in_next_submanifest = suffix_index;
+
+ // Update manifest bitmap in current msgbuf
+ interest_manifest_header_t *manifest =
+ _forwarder_get_interest_manifest(msgbuf);
+ assert(manifest != NULL);
+ memcpy(manifest->request_bitmap, curr_bitmap,
+ BITMAP_SIZE * sizeof(u32));
+ WITH_TRACE({
+ bitmap_print(manifest->request_bitmap, BITMAP_SIZE);
+ printf("\n");
+ });
+
+ // Update PIT entries for suffixes in current sub-manifest
+ nexthops_t *nexthops =
+ fib_entry_get_nexthops_from_strategy(fib_entry, msgbuf, false);
+ if (nexthops_get_curlen(nexthops) == 0) return -1;
+
+ for (int i = first_suffix_index_in_submanifest;
+ i < first_suffix_index_in_next_submanifest; i++) {
+ if (!is_bit_set(manifest->request_bitmap, i)) continue;
+
+ pit_entry_t *pit_entry = &(entries[i]->u.pit_entry);
+ if (!pit_entry) return -1;
+
+ pit_entry_set_fib_entry(pit_entry, fib_entry);
+ unsigned nexthop;
+ nexthops_foreach(nexthops, nexthop,
+ { pit_entry_egress_add(pit_entry, nexthop); });
+ }
+
+ if (forwarder_forward_to_nexthops(forwarder, msgbuf_id, nexthops) <=
+ 0) {
+ ERROR("Message %p returned an empty next hop set", msgbuf);
+ continue;
+ }
+
+ total_len += msgbuf_get_len(msgbuf);
+ }
+
+ return total_len;
+ }
+
+ default:
+ return -1;
+ }
+}
+
+static ssize_t forwarder_process_single_interest(forwarder_t *forwarder,
+ msgbuf_pool_t *msgbuf_pool,
+ msgbuf_t *msgbuf,
+ off_t msgbuf_id) {
+ pkt_cache_verdict_t verdict = PKT_CACHE_VERDICT_ERROR;
+ off_t data_msgbuf_id = INVALID_MSGBUF_ID;
+ pkt_cache_entry_t *entry = NULL;
+
+ // Update packet cache
+ pkt_cache_on_interest(forwarder->pkt_cache, msgbuf_pool, msgbuf_id, &verdict,
+ &data_msgbuf_id, &entry, msgbuf_get_name(msgbuf),
+ forwarder->serve_from_cs);
+ _forwarder_update_interest_stats(forwarder, verdict, msgbuf,
+ entry->has_expire_ts, entry->expire_ts);
+
+ int rc = _forwarder_forward_upon_interest(
+ forwarder, msgbuf_pool, data_msgbuf_id, msgbuf_id, entry, verdict, false);
+
+ // No route when trying to forward interest, remove from PIT
+ if (rc == -1)
+ pkt_cache_pit_remove_entry(forwarder->pkt_cache, entry,
+ msgbuf_get_name(msgbuf));
+
+ return msgbuf_get_len(msgbuf);
+}
+
+static ssize_t forwarder_process_aggregated_interest(
+ forwarder_t *forwarder, interest_manifest_header_t *int_manifest_header,
+ msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf, off_t msgbuf_id) {
+ pkt_cache_verdict_t verdict = PKT_CACHE_VERDICT_ERROR;
+ off_t data_msgbuf_id = INVALID_MSGBUF_ID;
+ pkt_cache_entry_t *entry = NULL;
+ // Save PIT entries to avoid re-doing pkt cache lookup in
+ // `_forwarder_forward_aggregated_interest()`
+ pkt_cache_entry_t *entries[BITMAP_SIZE * WORD_WIDTH];
+
+ int pos = 0; // Position of current suffix in manifest
+ int n_suffixes_to_fwd = 0;
+ u32 *suffix = (u32 *)(int_manifest_header + 1);
+ u32 seq = name_GetSegment(msgbuf_get_name(msgbuf));
+
+ Name name_copy = EMPTY_NAME;
+ name_Copy(msgbuf_get_name(msgbuf), &name_copy);
+
+ // The fist loop iteration handles the suffix in the header,
+ // the following ones handle the suffiexes in the manifest
+ while (true) {
+ if (!is_bit_set(int_manifest_header->request_bitmap, pos)) goto NEXT_SUFFIX;
+
+ // Update packet cache
+ pkt_cache_on_interest(forwarder->pkt_cache, msgbuf_pool, msgbuf_id,
+ &verdict, &data_msgbuf_id, &entry, &name_copy,
+ forwarder->serve_from_cs);
+ entries[pos] = entry;
+ _forwarder_update_interest_stats(forwarder, verdict, msgbuf,
+ entry->has_expire_ts, entry->expire_ts);
+
+ // Here only data forwarding is performed, interest forwarding is done
+ // in '_forwarder_forward_aggregated_interest()'
+ int rc =
+ _forwarder_forward_upon_interest(forwarder, msgbuf_pool, data_msgbuf_id,
+ msgbuf_id, entry, verdict, true);
+
+ // No route when trying to forward interest, remove from PIT
+ if (rc == -1)
+ pkt_cache_pit_remove_entry(forwarder->pkt_cache, entry, &name_copy);
+
+ // Unset in bitmap if no interest forwarding needed,
+ // otherwise increase count of suffixes to forward
+ if (rc == -1 || verdict == PKT_CACHE_VERDICT_AGGREGATE_INTEREST ||
+ verdict == PKT_CACHE_VERDICT_FORWARD_DATA) {
+ unset_bit(int_manifest_header->request_bitmap, pos);
+ } else {
+ n_suffixes_to_fwd++;
+ }
+
+ NEXT_SUFFIX:
+ if (pos++ >= int_manifest_header->n_suffixes) break;
+
+ // Use next segment in manifest
+ seq = *suffix;
+ suffix++;
+ name_SetSegment(&name_copy, seq);
+
+ WITH_DEBUG({
+ char *nameString = name_ToString(&name_copy);
+ DEBUG("Next in manifest: %s", nameString);
+ free(nameString);
+ });
+ }
+
+ // Return if nothing in the manifest to forward
+ if (n_suffixes_to_fwd == 0) return msgbuf_get_len(msgbuf);
+
+ return _forwarder_forward_aggregated_interest(forwarder, int_manifest_header,
+ n_suffixes_to_fwd, msgbuf,
+ msgbuf_id, entries);
+}
+
/**
* @function forwarder_process_interest
* @abstract Receive an interest from the network
@@ -657,29 +846,39 @@ static ssize_t forwarder_process_interest(forwarder_t *forwarder,
msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
+ const connection_table_t *table = forwarder_get_connection_table(forwarder);
+ connection_t *conn =
+ connection_table_get_by_id(table, msgbuf_get_connection_id(msgbuf));
assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST);
- forwarder->stats.countReceived++;
+ u32 n_suffixes = 0;
+ interest_manifest_header_t *int_manifest_header =
+ _forwarder_get_interest_manifest(msgbuf);
+ if (int_manifest_header) n_suffixes = int_manifest_header->n_suffixes;
+
+ // Update stats
forwarder->stats.countInterestsReceived++;
+ conn->stats.interests.rx_pkts++;
+ conn->stats.interests.rx_bytes += msgbuf_get_len(msgbuf);
WITH_DEBUG({
char *nameString = name_ToString(msgbuf_get_name(msgbuf));
- DEBUG("INTEREST (%s) msgbuf_id=%lu ingress=%u length=%u", nameString,
- msgbuf_id, msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf));
+ DEBUG("INTEREST (%s) suffixes=%u msgbuf_id=%lu ingress=%u length=%u",
+ nameString, n_suffixes, msgbuf_id, msgbuf_get_connection_id(msgbuf),
+ msgbuf_get_len(msgbuf));
free(nameString);
- })
-
- pkt_cache_verdict_t verdict = PKT_CACHE_VERDICT_ERROR;
- off_t data_msgbuf_id = INVALID_MSGBUF_ID;
- pkt_cache_entry_t *entry = NULL;
- pkt_cache_on_interest(forwarder->pkt_cache, msgbuf_pool, msgbuf_id, &verdict,
- &data_msgbuf_id, &entry, forwarder->serve_from_cs);
+ });
- _forwarder_update_interest_stats(forwarder, verdict, msgbuf, entry);
+ // Cache suffixes for current prefix to (possibly) avoid double lookups
+ pkt_cache_save_suffixes_for_prefix(
+ forwarder->pkt_cache, name_GetContentName(msgbuf_get_name(msgbuf)));
- return _forwarder_forward_upon_interest(
- forwarder, msgbuf_pool, data_msgbuf_id, msgbuf_id, entry, verdict);
+ if (!int_manifest_header)
+ return forwarder_process_single_interest(forwarder, msgbuf_pool, msgbuf,
+ msgbuf_id);
+ return forwarder_process_aggregated_interest(forwarder, int_manifest_header,
+ msgbuf_pool, msgbuf, msgbuf_id);
}
static void _forwarder_log_on_data(forwarder_t *forwarder,
@@ -700,7 +899,7 @@ static void _forwarder_log_on_data(forwarder_t *forwarder,
DEBUG("Message not stored in CS");
break;
case PKT_CACHE_VERDICT_ERROR:
- ERROR("Inivalid packet cache content");
+ ERROR("Invalid packet cache content");
break;
default:
break;
@@ -726,24 +925,31 @@ static ssize_t forwarder_process_data(forwarder_t *forwarder, off_t msgbuf_id) {
DEBUG("DATA (%s) msgbuf_id=%lu ingress=%u length=%u", nameString, msgbuf_id,
msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf));
free(nameString);
- )}
-
- forwarder->stats.countReceived++;
- forwarder->stats.countObjectsReceived++;
+ });
const connection_table_t *table = forwarder_get_connection_table(forwarder);
- const connection_t *conn =
+ connection_t *conn =
connection_table_get_by_id(table, msgbuf_get_connection_id(msgbuf));
+ // Update stats
+ forwarder->stats.countObjectsReceived++;
+ conn->stats.data.rx_pkts++;
+ conn->stats.data.rx_bytes += msgbuf_get_len(msgbuf);
+
+ // Cache suffixes for current prefix to (possibly) avoid double lookups
+ pkt_cache_save_suffixes_for_prefix(
+ forwarder->pkt_cache, name_GetContentName(msgbuf_get_name(msgbuf)));
+
pkt_cache_verdict_t verdict = PKT_CACHE_VERDICT_ERROR;
bool wrong_egress;
- nexthops_t *ingressSetUnion =
- pkt_cache_on_data(forwarder->pkt_cache, msgbuf_pool, msgbuf_id,
- forwarder->store_in_cs, connection_is_local(conn), &wrong_egress, &verdict);
+ nexthops_t *ingressSetUnion = pkt_cache_on_data(
+ forwarder->pkt_cache, msgbuf_pool, msgbuf_id, forwarder->store_in_cs,
+ connection_is_local(conn), &wrong_egress, &verdict);
_forwarder_log_on_data(forwarder, verdict);
- if (wrong_egress) { // Interest sent via a connection but received from another
+ if (wrong_egress) { // Interest sent via a connection but received from
+ // another
WARN("Data coming from unexpected connection, discarded");
} else if (!ingressSetUnion) { // No match in the PIT
forwarder->stats.countDroppedNoReversePath++;
@@ -776,15 +982,15 @@ void forwarder_flush_connections(forwarder_t *forwarder) {
// DEBUG("[forwarder_flush_connections]");
const connection_table_t *table = forwarder_get_connection_table(forwarder);
- for (unsigned i = 0; i < forwarder->num_pending_conn; i++) {
+ for (unsigned i = 0; i < vector_len(forwarder->pending_conn); i++) {
unsigned conn_id = forwarder->pending_conn[i];
- const connection_t *conn = connection_table_at(table, conn_id);
+ connection_t *conn = connection_table_at(table, conn_id);
if (!connection_flush(conn)) {
WARN("Could not flush connection queue");
// XXX keep track of non flushed connections...
}
}
- forwarder->num_pending_conn = 0;
+ vector_reset(forwarder->pending_conn);
// DEBUG("[forwarder_flush_connections] done");
}
@@ -957,6 +1163,23 @@ cs_t *forwarder_get_cs(const forwarder_t *forwarder) {
return pkt_cache_get_cs(forwarder->pkt_cache);
}
+// IMPORTANT: Use this function ONLY for read-only operations since a realloc
+// would otherwise modify the returned copy but not the original msgbuf ids
+// vector in the forwarder. This constraint cannot be enforced by returning a
+// (const off_t *) because the vector_t macros still cast to (void **).
+off_t *forwarder_get_acquired_msgbuf_ids(const forwarder_t *forwarder) {
+ return forwarder->acquired_msgbuf_ids;
+}
+
+void forwarder_acquired_msgbuf_ids_reset(const forwarder_t *forwarder) {
+ vector_reset(forwarder->acquired_msgbuf_ids);
+}
+
+void forwarder_acquired_msgbuf_ids_push(const forwarder_t *forwarder,
+ off_t msgbuf_id) {
+ vector_push(forwarder->acquired_msgbuf_ids, msgbuf_id);
+}
+
// =======================================================
fib_t *forwarder_get_fib(forwarder_t *forwarder) { return forwarder->fib; }
@@ -1052,14 +1275,15 @@ ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener,
const connection_table_t *table =
forwarder_get_connection_table(listener->forwarder);
connection_t *connection = connection_table_get_by_pair(table, pair);
- unsigned conn_id = connection
- ? connection_table_get_connection_id(table, connection)
- : CONNECTION_ID_UNDEFINED;
+ unsigned conn_id = connection ? (unsigned)connection_table_get_connection_id(
+ table, connection)
+ : CONNECTION_ID_UNDEFINED;
assert((conn_id != CONNECTION_ID_UNDEFINED) || listener);
msgbuf_type_t type = get_type_from_packet(msgbuf_get_packet(msgbuf));
+ forwarder->stats.countReceived++;
msgbuf->type = type;
msgbuf->connection_id = conn_id;
msgbuf->recv_ts = now;
@@ -1067,12 +1291,14 @@ ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener,
switch (type) {
case MSGBUF_TYPE_INTEREST:
if (!connection_id_is_valid(msgbuf->connection_id)) {
- char *conn_name = connection_table_get_random_name(table);
+ char conn_name[SYMBOLIC_NAME_LEN];
+ int rc = connection_table_get_random_name(table, conn_name);
+ if (rc < 0) return 0;
+
unsigned connection_id =
listener_create_connection(listener, conn_name, pair);
msgbuf->connection_id = connection_id;
connection = connection_table_get_by_id(table, connection_id);
- free(conn_name);
}
msgbuf->path_label = 0; // not used for interest packets
name_create_from_interest(packet, msgbuf_get_name(msgbuf));
@@ -1102,10 +1328,12 @@ ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener,
case MSGBUF_TYPE_MAPME:
// XXX what about acks ?
if (!connection_id_is_valid(msgbuf->connection_id)) {
- char *conn_name = connection_table_get_random_name(table);
+ char conn_name[SYMBOLIC_NAME_LEN];
+ int rc = connection_table_get_random_name(table, conn_name);
+ if (rc < 0) return 0;
+
msgbuf->connection_id =
listener_create_connection(listener, conn_name, pair);
- free(conn_name);
}
mapme_process(forwarder->mapme, msgbuf);
return size;
@@ -1113,12 +1341,14 @@ ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener,
case MSGBUF_TYPE_COMMAND:
// Create the connection to send the ack back
if (!connection_id_is_valid(msgbuf->connection_id)) {
- char *conn_name = connection_table_get_random_name(table);
+ char conn_name[SYMBOLIC_NAME_LEN];
+ int rc = connection_table_get_random_name(table, conn_name);
+ if (rc < 0) return 0;
+
unsigned connection_id =
listener_create_connection(listener, conn_name, pair);
msgbuf->connection_id = connection_id;
connection = connection_table_get_by_id(table, connection_id);
- free(conn_name);
}
msg_header_t *msg = (msg_header_t *)packet;
@@ -1163,3 +1393,7 @@ void forwarder_log(forwarder_t *forwarder) {
forwarder->stats.countInterestsExpired, forwarder->stats.countDataExpired,
forwarder->stats.countDroppedNoReversePath);
}
+
+forwarder_stats_t forwarder_get_stats(forwarder_t *forwarder) {
+ return forwarder->stats;
+} \ No newline at end of file
diff --git a/hicn-light/src/hicn/core/forwarder.h b/hicn-light/src/hicn/core/forwarder.h
index 76c12368a..2f940cf15 100644
--- a/hicn-light/src/hicn/core/forwarder.h
+++ b/hicn-light/src/hicn/core/forwarder.h
@@ -98,6 +98,8 @@ listener_table_t *forwarder_get_listener_table(forwarder_t *forwarder);
connection_table_t *forwarder_get_connection_table(
const forwarder_t *forwarder);
+pkt_cache_t *forwarder_get_pkt_cache(const forwarder_t *forwarder);
+
void forwarder_cs_set_store(forwarder_t *forwarder, bool val);
bool forwarder_cs_get_store(forwarder_t *forwarder);
@@ -159,6 +161,18 @@ void forwarder_set_strategy(forwarder_t *forwarder, Name *name_prefix,
cs_t *forwarder_get_cs(const forwarder_t *forwarder);
+off_t *forwarder_get_acquired_msgbuf_ids(const forwarder_t *forwarder);
+
+/**
+ * @note Acquire msgbuf ids vector ONLY for read-only operations.
+ */
+off_t *forwarder_get_acquired_msgbuf_ids(const forwarder_t *forwarder);
+
+void forwarder_acquired_msgbuf_ids_reset(const forwarder_t *forwarder);
+
+void forwarder_acquired_msgbuf_ids_push(const forwarder_t *forwarder,
+ off_t msgbuf_id);
+
/**
* @brief Returns the forwarder's FIB.
* @param[in] forwarder - Pointer to the forwarder.
@@ -226,4 +240,6 @@ ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener,
*/
void forwarder_log(forwarder_t *forwarder);
+forwarder_stats_t forwarder_get_stats(forwarder_t *forwarder);
+
#endif // HICNLIGHT_FORWARDER_H
diff --git a/hicn-light/src/hicn/core/interest_manifest.c b/hicn-light/src/hicn/core/interest_manifest.c
new file mode 100644
index 000000000..1be8a3fb5
--- /dev/null
+++ b/hicn-light/src/hicn/core/interest_manifest.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "interest_manifest.h"
+
+int_manifest_split_strategy_t disaggregation_strategy =
+ INT_MANIFEST_SPLIT_MAX_N_SUFFIXES;
+unsigned N_SUFFIXES_PER_SPIT = 256;
+
+bool interest_manifest_is_valid(interest_manifest_header_t *int_manifest_header,
+ size_t payload_length) {
+ if (int_manifest_header->n_suffixes == 0 ||
+ int_manifest_header->n_suffixes > MAX_SUFFIXES_IN_MANIFEST) {
+ ERROR("Manifest with invalid number of suffixes (%d)",
+ int_manifest_header->n_suffixes);
+ return false;
+ }
+
+ uint32_t empty_bitmap[BITMAP_SIZE] = {0};
+ if (memcmp(empty_bitmap, int_manifest_header->request_bitmap,
+ sizeof(empty_bitmap)) == 0) {
+ ERROR("Manifest with empty bitmap");
+ return false;
+ }
+
+ if (payload_length - sizeof(interest_manifest_header_t) !=
+ int_manifest_header->n_suffixes * sizeof(u32)) {
+ ERROR("Size of suffixes in intereset manifest (%d) is not equal to %d",
+ payload_length - sizeof(interest_manifest_header_t),
+ int_manifest_header->n_suffixes * sizeof(u32));
+ return false;
+ }
+
+ return true;
+}
+
+int interest_manifest_update_bitmap(const u32 *initial_bitmap,
+ u32 *bitmap_to_update, int start, int n,
+ int max_suffixes) {
+ int i = start, n_ones = 0;
+ while (i < n) {
+ if (is_bit_set(initial_bitmap, i)) {
+ set_bit(bitmap_to_update, i);
+ n_ones++;
+ }
+ i++;
+
+ if (n_ones == max_suffixes) break;
+ }
+
+ return i;
+}
diff --git a/hicn-light/src/hicn/core/interest_manifest.h b/hicn-light/src/hicn/core/interest_manifest.h
new file mode 100644
index 000000000..fcb2b9897
--- /dev/null
+++ b/hicn-light/src/hicn/core/interest_manifest.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 HICNLIGHT_INTEREST_MANIFEST_H
+#define HICNLIGHT_INTEREST_MANIFEST_H
+
+#include <string.h>
+#include <stdbool.h>
+
+#include <hicn/util/log.h>
+#include <hicn/base.h>
+
+typedef enum {
+ INT_MANIFEST_SPLIT_NONE,
+ INT_MANIFEST_SPLIT_MAX_N_SUFFIXES
+} int_manifest_split_strategy_t;
+
+extern int_manifest_split_strategy_t disaggregation_strategy;
+extern unsigned N_SUFFIXES_PER_SPIT;
+
+bool interest_manifest_is_valid(interest_manifest_header_t *int_manifest_header,
+ size_t payload_length);
+
+int interest_manifest_update_bitmap(const u32 *initial_bitmap,
+ u32 *bitmap_to_update, int start, int n,
+ int max_suffixes);
+
+#endif /* HICNLIGHT_INTEREST_MANIFEST_H */
diff --git a/hicn-light/src/hicn/core/listener.c b/hicn-light/src/hicn/core/listener.c
index ecdfc38f4..188f0c317 100644
--- a/hicn-light/src/hicn/core/listener.c
+++ b/hicn-light/src/hicn/core/listener.c
@@ -24,7 +24,6 @@
#include "forwarder.h"
#include "listener_vft.h"
-#include "../base/loop.h"
#include "../io/base.h"
listener_key_t listener_key_factory(address_t address, face_type_t type) {
@@ -44,7 +43,8 @@ listener_t *listener_create(face_type_t type, const address_t *address,
listener_key_t key = listener_key_factory(*address, type);
listener_t *listener = listener_table_allocate(table, &key, name);
- unsigned listener_id = listener_table_get_listener_id(table, listener);
+ unsigned listener_id =
+ (unsigned int)listener_table_get_listener_id(table, listener);
int ret = listener_initialize(listener, type, name, listener_id, address,
interface_name, forwarder);
@@ -194,7 +194,7 @@ unsigned listener_create_connection(listener_t *listener,
connection_t *connection =
connection_table_allocate(table, pair, connection_name);
unsigned connection_id =
- connection_table_get_connection_id(table, connection);
+ (unsigned int)connection_table_get_connection_id(table, connection);
/*
* We create a connected connection with its own fd, instead of returning
@@ -337,11 +337,10 @@ ssize_t listener_read_batch(listener_t *listener, int fd) {
size_t total_processed_bytes = 0;
ssize_t num_msg_received = 0;
- off_t *acquired_msgbuf_ids;
- vector_init(acquired_msgbuf_ids, MAX_MSG, 0);
forwarder_t *forwarder = listener->forwarder;
msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
+ forwarder_acquired_msgbuf_ids_reset(forwarder);
/* Receive messages in the loop as long as we manage to fill the buffers */
do {
@@ -381,7 +380,7 @@ ssize_t listener_read_batch(listener_t *listener, int fd) {
}
msgbuf_pool_acquire(msgbufs[i]);
- vector_push(acquired_msgbuf_ids, msgbuf_ids[i]);
+ forwarder_acquired_msgbuf_ids_push(forwarder, msgbuf_ids[i]);
}
if (num_msg_received < 0) break;
@@ -403,11 +402,12 @@ ssize_t listener_read_batch(listener_t *listener, int fd) {
*/
forwarder_flush_connections(forwarder);
+ const off_t *acquired_msgbuf_ids =
+ forwarder_get_acquired_msgbuf_ids(forwarder);
for (int i = 0; i < vector_len(acquired_msgbuf_ids); i++) {
msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, acquired_msgbuf_ids[i]);
msgbuf_pool_release(msgbuf_pool, &msgbuf);
}
- vector_free(acquired_msgbuf_ids);
return total_processed_bytes;
}
diff --git a/hicn-light/src/hicn/core/listener.h b/hicn-light/src/hicn/core/listener.h
index 346c874c0..5d0384329 100644
--- a/hicn-light/src/hicn/core/listener.h
+++ b/hicn-light/src/hicn/core/listener.h
@@ -25,7 +25,7 @@
#include "address_pair.h"
#include "msgbuf.h"
-#include "../base/loop.h"
+#include <hicn/base/loop.h>
#define LISTENER_ID_UNDEFINED ~0
@@ -36,6 +36,12 @@ typedef struct {
face_type_t type;
} listener_key_t;
+static inline int listener_key_equals(const listener_key_t *key1,
+ const listener_key_t *key2) {
+ return address_equals(&key1->address, &key2->address) &&
+ (key1->type == key2->type);
+}
+
/**
* @brief Create a listener key starting from an address and a face type.
*
diff --git a/hicn-light/src/hicn/core/listener_table.c b/hicn-light/src/hicn/core/listener_table.c
index 32b8e9d45..220b738bb 100644
--- a/hicn-light/src/hicn/core/listener_table.c
+++ b/hicn-light/src/hicn/core/listener_table.c
@@ -72,6 +72,54 @@ void listener_table_free(listener_table_t *table) {
free(table);
}
+listener_t *listener_table_allocate(const listener_table_t *table,
+ const listener_key_t *key,
+ const char *name) {
+ listener_t *listener = NULL;
+ pool_get(table->listeners, listener);
+ if (!listener) return NULL;
+
+ off_t id = listener - table->listeners;
+ int rc;
+
+ // Add in name hash table
+ khiter_t k = kh_put_lt_name(table->id_by_name, strdup(name), &rc);
+ assert(rc == KH_ADDED || rc == KH_RESET);
+ kh_value(table->id_by_name, k) = (unsigned int)id;
+
+ // Add in key hash table
+ listener_key_t *key_copy = (listener_key_t *)malloc(sizeof(listener_key_t));
+ memcpy(key_copy, key, sizeof(listener_key_t));
+
+ k = kh_put_lt_key(table->id_by_key, key_copy, &rc);
+ assert(rc == KH_ADDED || rc == KH_RESET);
+ kh_value(table->id_by_key, k) = (unsigned int)id;
+
+ assert(kh_size(table->id_by_name) == kh_size(table->id_by_key));
+ return listener;
+}
+
+void listener_table_deallocate(const listener_table_t *table,
+ listener_t *listener) {
+ const char *name = listener_get_name(listener);
+ listener_key_t *key = listener_get_key(listener);
+
+ // Remove from name hash table
+ khiter_t k = kh_get_lt_name(table->id_by_name, name);
+ assert(k != kh_end(table->id_by_name));
+ free((char *)kh_key(table->id_by_name, k));
+ kh_del_lt_name(table->id_by_name, k);
+
+ // Remove from key hash table
+ k = kh_get_lt_key(table->id_by_key, key);
+ assert(k != kh_end(table->id_by_key));
+ free((listener_key_t *)kh_key(table->id_by_key, k));
+ kh_del_lt_key(table->id_by_key, k);
+
+ assert(kh_size(table->id_by_name) == kh_size(table->id_by_key));
+ pool_put(table->listeners, listener);
+}
+
listener_t *listener_table_get_by_address(listener_table_t *table,
face_type_t type,
const address_t *address) {
@@ -104,7 +152,8 @@ off_t listener_table_get_id_by_name(const listener_table_t *table,
listener_t *listener_table_get_by_name(listener_table_t *table,
const char *name) {
- unsigned listener_id = listener_table_get_id_by_name(table, name);
+ unsigned listener_id =
+ (unsigned int)listener_table_get_id_by_name(table, name);
if (!listener_id_is_valid(listener_id)) return NULL;
return listener_table_at(table, listener_id);
}
diff --git a/hicn-light/src/hicn/core/listener_table.h b/hicn-light/src/hicn/core/listener_table.h
index 5fed638e8..7e2e99d7f 100644
--- a/hicn-light/src/hicn/core/listener_table.h
+++ b/hicn-light/src/hicn/core/listener_table.h
@@ -30,22 +30,19 @@
#ifndef HICNLIGHT_LISTENER_TABLE_H
#define HICNLIGHT_LISTENER_TABLE_H
+#include <hicn/util/khash.h>
+#include <hicn/util/hash.h>
#include "address.h"
#include "listener.h"
-#include "../base/common.h"
-#include "../base/hash.h"
-#include "../base/khash.h"
-#include "../base/pool.h"
-
-#define _lt_var(x) _lt_var_##x
+#include <hicn/util/pool.h>
/* Hash functions for indices */
#define key_hash(key) (hash_struct(key))
-#define key_hash_eq(a, b) (key_hash(b) == key_hash(a))
/* Hash table types for indices */
KHASH_MAP_INIT_STR(lt_name, unsigned);
-KHASH_INIT(lt_key, const listener_key_t *, unsigned, 1, key_hash, key_hash_eq);
+KHASH_INIT(lt_key, const listener_key_t *, unsigned, 1, key_hash,
+ listener_key_equals);
typedef struct {
size_t max_size;
@@ -70,34 +67,9 @@ typedef struct {
* - You should always check that the returned listener is not NULL, which
* would signal that the pool is exhausted and could not be extended.
*/
-
-static inline listener_t *listener_table_allocate(const listener_table_t *table,
- const listener_key_t *key,
- const char *name) {
- listener_t *listener;
- pool_get(table->listeners, listener);
-
- if (listener) {
- off_t id = listener - table->listeners;
- int res;
- khiter_t k;
-
- // Add in name hash table
- k = kh_put_lt_name(table->id_by_name, strdup(name), &res);
- assert(res > 0);
- kh_value(table->id_by_name, k) = id;
-
- // Add in key hash table
- listener_key_t *key_copy = (listener_key_t *)malloc(sizeof(listener_key_t));
- memcpy(key_copy, key, sizeof(listener_key_t));
-
- k = kh_put_lt_key(table->id_by_key, key_copy, &res);
- assert(res > 0);
- kh_value(table->id_by_key, k) = id;
- }
-
- return listener;
-}
+listener_t *listener_table_allocate(const listener_table_t *table,
+ const listener_key_t *key,
+ const char *name);
/**
* @brief Deallocate a listener and return it to the listener table pool.
@@ -109,27 +81,8 @@ static inline listener_t *listener_table_allocate(const listener_table_t *table,
* - Upon returning a listener to the pool, all indices pointing to that
* listener are also cleared.
*/
-
-static inline void listener_table_deallocate(const listener_table_t *table,
- listener_t *listener) {
- const char *name = listener_get_name(listener);
- listener_key_t *key = listener_get_key(listener);
- khiter_t k;
-
- // Remove from name hash table
- k = kh_get_lt_name(table->id_by_name, name);
- assert(k != kh_end(table->id_by_name));
- free((char *)kh_key(table->id_by_name, k));
- kh_del_lt_name(table->id_by_name, k);
-
- // Remove from key hash table
- k = kh_get_lt_key(table->id_by_key, key);
- assert(k != kh_end(table->id_by_key));
- free((listener_key_t *)kh_key(table->id_by_key, k));
- kh_del_lt_key(table->id_by_key, k);
-
- pool_put(table->listeners, listener);
-}
+void listener_table_deallocate(const listener_table_t *table,
+ listener_t *listener);
/**
* @brief Returns the length of the listener table, the number of active
diff --git a/hicn-light/src/hicn/core/msgbuf_pool.c b/hicn-light/src/hicn/core/msgbuf_pool.c
index fb5d0a07c..a2092aaf6 100644
--- a/hicn-light/src/hicn/core/msgbuf_pool.c
+++ b/hicn-light/src/hicn/core/msgbuf_pool.c
@@ -18,9 +18,8 @@
* @brief Implementation of hICN packet pool.
*/
-#include "../base/pool.h"
+#include <hicn/util/pool.h>
#include "msgbuf_pool.h"
-#include "../core/name.h" // name_Release
msgbuf_pool_t *_msgbuf_pool_create(size_t init_size, size_t max_size) {
msgbuf_pool_t *msgbuf_pool = malloc(sizeof(msgbuf_pool_t));
@@ -38,7 +37,9 @@ void msgbuf_pool_free(msgbuf_pool_t *msgbuf_pool) {
}
off_t msgbuf_pool_get(msgbuf_pool_t *msgbuf_pool, msgbuf_t **msgbuf) {
- return pool_get(msgbuf_pool->buffers, *msgbuf);
+ off_t id = pool_get(msgbuf_pool->buffers, *msgbuf);
+ (*msgbuf)->refs = 0;
+ return id;
}
void msgbuf_pool_put(msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf) {
diff --git a/hicn-light/src/hicn/core/name.c b/hicn-light/src/hicn/core/name.c
index 8886cc929..d30cebefc 100644
--- a/hicn-light/src/hicn/core/name.c
+++ b/hicn-light/src/hicn/core/name.c
@@ -20,11 +20,10 @@
#include <stdio.h>
#include <string.h>
-#include <hicn/common.h> // cumulative_hash32
#include <hicn/core/messageHandler.h>
#include <hicn/core/name.h>
#include <hicn/util/log.h>
-#include <hicn/base/hash.h>
+#include <hicn/util/hash.h>
#define IPv6_TYPE 6
#define IPv4_TYPE 4
diff --git a/hicn-light/src/hicn/core/nameBitvector.c b/hicn-light/src/hicn/core/nameBitvector.c
index 1314671db..aa431879c 100644
--- a/hicn-light/src/hicn/core/nameBitvector.c
+++ b/hicn-light/src/hicn/core/nameBitvector.c
@@ -20,7 +20,7 @@
#include <hicn/core/messageHandler.h>
#include <hicn/core/nameBitvector.h>
-#include <hicn/base/hash.h>
+#include <hicn/util/hash.h>
#include <hicn/ctrl/hicn-light-ng.h>
#define DEFAULT_PORT 1234
diff --git a/hicn-light/src/hicn/core/nameBitvector.h b/hicn-light/src/hicn/core/nameBitvector.h
index e3cc108ac..549b26679 100644
--- a/hicn-light/src/hicn/core/nameBitvector.h
+++ b/hicn-light/src/hicn/core/nameBitvector.h
@@ -23,11 +23,13 @@
#include "address.h"
#define NAME_LEN 2
-typedef struct {
+typedef struct __attribute__((__packed__)) {
uint64_t bits[NAME_LEN];
- uint8_t len;
- uint8_t IPversion;
+ uint32_t len;
+ uint32_t IPversion;
} NameBitvector;
+static_assert(sizeof(NameBitvector) == 24,
+ "Name prefix should be stored on 24 bytes");
#define EMPTY_NAME_BITVECTOR \
(NameBitvector) { .bits[0] = 0, .bits[1] = 0, .len = 0, .IPversion = 0, }
diff --git a/hicn-light/src/hicn/core/packet_cache.c b/hicn-light/src/hicn/core/packet_cache.c
index 203ad4a63..8bd188c8b 100644
--- a/hicn-light/src/hicn/core/packet_cache.c
+++ b/hicn-light/src/hicn/core/packet_cache.c
@@ -20,6 +20,111 @@
#include "packet_cache.h"
+/******************************************************************************
+ * Low-level operations on the hash table
+ ******************************************************************************/
+
+void _prefix_map_free(kh_pkt_cache_prefix_t *prefix_to_suffixes) {
+ const NameBitvector *key;
+ kh_pkt_cache_suffix_t *value;
+ kh_foreach(prefix_to_suffixes, key, value, {
+ free((NameBitvector *)key);
+ kh_destroy_pkt_cache_suffix(value);
+ });
+ kh_destroy_pkt_cache_prefix(prefix_to_suffixes);
+}
+
+kh_pkt_cache_suffix_t *_get_suffixes(kh_pkt_cache_prefix_t *prefix_to_suffixes,
+ const NameBitvector *prefix) {
+ khiter_t k = kh_get_pkt_cache_prefix(prefix_to_suffixes, prefix);
+
+ // Return suffixes found
+ if (k != kh_end(prefix_to_suffixes)) {
+ kh_pkt_cache_suffix_t *suffixes = kh_val(prefix_to_suffixes, k);
+ return suffixes;
+ }
+
+ kh_pkt_cache_suffix_t *suffixes = kh_init_pkt_cache_suffix();
+ NameBitvector *nb_copy = (NameBitvector *)malloc(sizeof(NameBitvector));
+ *nb_copy = *prefix;
+
+ int rc;
+ k = kh_put_pkt_cache_prefix(prefix_to_suffixes, nb_copy, &rc);
+ assert(rc == KH_ADDED || rc == KH_RESET);
+ kh_value(prefix_to_suffixes, k) = suffixes;
+ return suffixes;
+}
+
+void _remove_suffix(kh_pkt_cache_prefix_t *prefixes,
+ const NameBitvector *prefix, uint32_t suffix) {
+ kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix);
+ assert(suffixes != NULL);
+
+ khiter_t k = kh_get_pkt_cache_suffix(suffixes, suffix);
+ assert(k != kh_end(suffixes));
+ kh_del_pkt_cache_suffix(suffixes, k);
+
+ // TODO(eloparco): Remove prefix if no associated suffixes?
+}
+
+void __add_suffix(kh_pkt_cache_suffix_t *suffixes, uint32_t suffix,
+ unsigned val) {
+ int rc;
+ khiter_t k = kh_put_pkt_cache_suffix(suffixes, suffix, &rc);
+ assert(rc == KH_ADDED || rc == KH_RESET);
+ kh_value(suffixes, k) = val;
+}
+
+void _add_suffix(kh_pkt_cache_prefix_t *prefixes, const NameBitvector *prefix,
+ uint32_t suffix, unsigned val) {
+ kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix);
+ assert(suffixes != NULL);
+
+ __add_suffix(suffixes, suffix, val);
+}
+
+unsigned __get_suffix(kh_pkt_cache_suffix_t *suffixes, uint32_t suffix,
+ int *rc) {
+ *rc = KH_FOUND;
+ khiter_t k = kh_get_pkt_cache_suffix(suffixes, suffix);
+
+ // Not Found
+ if (k == kh_end(suffixes)) {
+ *rc = KH_NOT_FOUND;
+ return -1;
+ }
+
+ unsigned index = kh_val(suffixes, k);
+ return index;
+}
+
+void pkt_cache_save_suffixes_for_prefix(pkt_cache_t *pkt_cache,
+ const NameBitvector *prefix) {
+ // Cached prefix matches the current one
+ if (nameBitvector_Compare(&pkt_cache->cached_prefix, prefix) == 0) return;
+
+ // Update cached prefix information
+ pkt_cache->cached_prefix = *prefix;
+ pkt_cache->cached_suffixes =
+ _get_suffixes(pkt_cache->prefix_to_suffixes, prefix);
+}
+
+void pkt_cache_reset_suffixes_for_prefix(pkt_cache_t *pkt_cache) {
+ pkt_cache->cached_suffixes = NULL;
+}
+
+unsigned _get_suffix(kh_pkt_cache_prefix_t *prefixes,
+ const NameBitvector *prefix, uint32_t suffix, int *rc) {
+ kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix);
+ assert(suffixes != NULL);
+
+ return __get_suffix(suffixes, suffix, rc);
+}
+
+/******************************************************************************
+ * Public API
+ ******************************************************************************/
+
pkt_cache_t *pkt_cache_create(size_t cs_size) {
pkt_cache_t *pkt_cache = (pkt_cache_t *)malloc(sizeof(pkt_cache_t));
@@ -28,23 +133,20 @@ pkt_cache_t *pkt_cache_create(size_t cs_size) {
pkt_cache->cs = cs_create(cs_size);
if (!pkt_cache->cs) return NULL;
- pkt_cache->index_by_name = kh_init(pkt_cache_name);
+ pkt_cache->prefix_to_suffixes = kh_init_pkt_cache_prefix();
pool_init(pkt_cache->entries, DEFAULT_PKT_CACHE_SIZE, 0);
+ pkt_cache->cached_prefix = EMPTY_NAME_BITVECTOR;
+ pkt_cache->cached_suffixes = NULL;
+
return pkt_cache;
}
void pkt_cache_free(pkt_cache_t *pkt_cache) {
assert(pkt_cache);
- // Free hashmap
- const Name *k_name;
- unsigned v;
- (void)v;
- kh_foreach(pkt_cache->index_by_name, k_name, v, { free((Name *)k_name); });
- kh_destroy(pkt_cache_name, pkt_cache->index_by_name);
-
- // Free pool
+ // Free prefix hash table and pool
+ _prefix_map_free(pkt_cache->prefix_to_suffixes);
pool_free(pkt_cache->entries);
// Free PIT and CS
@@ -54,6 +156,30 @@ void pkt_cache_free(pkt_cache_t *pkt_cache) {
free(pkt_cache);
}
+kh_pkt_cache_suffix_t *pkt_cache_get_suffixes(const pkt_cache_t *pkt_cache,
+ const NameBitvector *prefix) {
+ return _get_suffixes(pkt_cache->prefix_to_suffixes, prefix);
+}
+
+pkt_cache_entry_t *pkt_cache_allocate(pkt_cache_t *pkt_cache,
+ const Name *name) {
+ pkt_cache_entry_t *entry = NULL;
+ pool_get(pkt_cache->entries, entry);
+ if (!entry) return NULL;
+
+ off_t id = entry - pkt_cache->entries;
+
+ if (pkt_cache->cached_suffixes) {
+ __add_suffix(pkt_cache->cached_suffixes, name_GetSegment(name),
+ (unsigned int)id);
+ } else {
+ _add_suffix(pkt_cache->prefix_to_suffixes, name_GetContentName(name),
+ name_GetSegment(name), (unsigned int)id);
+ }
+
+ return entry;
+}
+
pit_t *pkt_cache_get_pit(pkt_cache_t *pkt_cache) { return pkt_cache->pit; }
cs_t *pkt_cache_get_cs(pkt_cache_t *pkt_cache) { return pkt_cache->cs; }
@@ -63,14 +189,22 @@ pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, const Name *name,
pkt_cache_lookup_t *lookup_result,
off_t *entry_id,
bool is_serve_from_cs_enabled) {
- Name name_key = name_key_factory(name);
- khiter_t k = kh_get_pkt_cache_name(pkt_cache->index_by_name, &name_key);
- if (k == kh_end(pkt_cache->index_by_name)) {
+ int rc;
+
+ unsigned index = -1;
+ if (pkt_cache->cached_suffixes) {
+ index =
+ __get_suffix(pkt_cache->cached_suffixes, name_GetSegment(name), &rc);
+ } else {
+ index = _get_suffix(pkt_cache->prefix_to_suffixes,
+ name_GetContentName(name), name_GetSegment(name), &rc);
+ }
+
+ if (rc == KH_NOT_FOUND) {
*lookup_result = PKT_CACHE_LU_NONE;
return NULL;
}
- off_t index = kh_val(pkt_cache->index_by_name, k);
pkt_cache_entry_t *entry = pkt_cache_at(pkt_cache, index);
assert(entry);
bool expired = false;
@@ -103,11 +237,9 @@ void pkt_cache_cs_remove_entry(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
off_t msgbuf_id = entry->u.cs_entry.msgbuf_id;
msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
- Name name_key = name_key_factory(msgbuf_get_name(msgbuf));
- khiter_t k = kh_get_pkt_cache_name(pkt_cache->index_by_name, &name_key);
- assert(k != kh_end(pkt_cache->index_by_name));
- free((Name *)kh_key(pkt_cache->index_by_name, k));
- kh_del(pkt_cache_name, pkt_cache->index_by_name, k);
+ const Name *name = msgbuf_get_name(msgbuf);
+ _remove_suffix(pkt_cache->prefix_to_suffixes, name_GetContentName(name),
+ name_GetSegment(name));
// Do not update the LRU cache for evicted entries
if (!is_evicted) cs_vft[pkt_cache->cs->type]->remove_entry(pkt_cache, entry);
@@ -130,12 +262,8 @@ void pkt_cache_pit_remove_entry(pkt_cache_t *pkt_cache,
assert(entry);
assert(entry->entry_type == PKT_CACHE_PIT_TYPE);
- Name name_key = name_key_factory(name);
- khiter_t k = kh_get_pkt_cache_name(pkt_cache->index_by_name, &name_key);
- assert(k != kh_end(pkt_cache->index_by_name));
- free((Name *)kh_key(pkt_cache->index_by_name, k));
- kh_del(pkt_cache_name, pkt_cache->index_by_name, k);
-
+ _remove_suffix(pkt_cache->prefix_to_suffixes, name_GetContentName(name),
+ name_GetSegment(name));
pool_put(pkt_cache->entries, entry);
WITH_DEBUG({
@@ -158,7 +286,7 @@ void _pkt_cache_add_to_cs(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
pkt_cache->cs->num_entries++;
- int tail_id = pkt_cache->cs->lru.tail;
+ int tail_id = (int)(pkt_cache->cs->lru.tail);
int result = cs_vft[pkt_cache->cs->type]->add_entry(pkt_cache, entry_id);
if (result == LRU_EVICTION) {
// Remove tail (already removed from LRU cache)
@@ -237,11 +365,11 @@ void pkt_cache_update_cs(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
}
pkt_cache_entry_t *pkt_cache_add_to_pit(pkt_cache_t *pkt_cache,
- const msgbuf_t *msgbuf) {
+ const msgbuf_t *msgbuf,
+ const Name *name) {
assert(pkt_cache);
- pkt_cache_entry_t *entry =
- pkt_cache_allocate(pkt_cache, msgbuf_get_name(msgbuf));
+ pkt_cache_entry_t *entry = pkt_cache_allocate(pkt_cache, name);
_pkt_cache_add_to_pit(pkt_cache, entry, msgbuf);
return entry;
}
@@ -276,7 +404,7 @@ void pkt_cache_update_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache,
pkt_cache_entry_t *entry,
- const msgbuf_t *msgbuf) {
+ const msgbuf_t *msgbuf, const Name *name) {
assert(pkt_cache);
assert(entry);
assert(entry->entry_type == PKT_CACHE_PIT_TYPE);
@@ -294,7 +422,7 @@ bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache,
if (is_aggregated) pit_entry_ingress_add(pit_entry, connection_id);
WITH_DEBUG({
- char *name_str = name_ToString(msgbuf_get_name(msgbuf));
+ char *name_str = name_ToString(name);
if (is_aggregated) {
DEBUG("Interest %s already existing (expiry %lu): aggregate", name_str,
entry->expire_ts);
@@ -407,7 +535,7 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache,
return NULL;
default:
- ERROR("Inivalid packet cache content");
+ ERROR("Invalid packet cache content");
return NULL;
}
}
@@ -415,7 +543,7 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache,
void pkt_cache_on_interest(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
off_t msgbuf_id, pkt_cache_verdict_t *verdict,
off_t *data_msgbuf_id, pkt_cache_entry_t **entry_ptr,
- bool is_serve_from_cs_enabled) {
+ const Name *name, bool is_serve_from_cs_enabled) {
assert(pkt_cache);
assert(msgbuf_id_is_valid(msgbuf_id));
@@ -425,8 +553,8 @@ void pkt_cache_on_interest(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
off_t entry_id;
pkt_cache_lookup_t lookup_result;
pkt_cache_entry_t *entry =
- pkt_cache_lookup(pkt_cache, msgbuf_get_name(msgbuf), msgbuf_pool,
- &lookup_result, &entry_id, is_serve_from_cs_enabled);
+ pkt_cache_lookup(pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id,
+ is_serve_from_cs_enabled);
*entry_ptr = entry;
cs_entry_t *cs_entry = NULL;
@@ -434,6 +562,9 @@ void pkt_cache_on_interest(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
bool is_aggregated;
switch (lookup_result) {
case PKT_CACHE_LU_NONE:
+ entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name);
+ *entry_ptr = entry;
+
*verdict = PKT_CACHE_VERDICT_FORWARD_INTEREST;
break;
@@ -448,7 +579,8 @@ void pkt_cache_on_interest(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
break;
case PKT_CACHE_LU_INTEREST_NOT_EXPIRED:
- is_aggregated = pkt_cache_try_aggregate_in_pit(pkt_cache, entry, msgbuf);
+ is_aggregated =
+ pkt_cache_try_aggregate_in_pit(pkt_cache, entry, msgbuf, name);
*verdict = is_aggregated ? PKT_CACHE_VERDICT_AGGREGATE_INTEREST
: PKT_CACHE_VERDICT_RETRANSMIT_INTEREST;
@@ -477,36 +609,30 @@ void pkt_cache_on_interest(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
void pkt_cache_cs_clear(pkt_cache_t *pkt_cache) {
assert(pkt_cache);
- const Name *k_name;
- unsigned v_pool_pos;
- kh_foreach(pkt_cache->index_by_name, k_name, v_pool_pos,
- {
- khiter_t k =
- kh_get_pkt_cache_name(pkt_cache->index_by_name, k_name);
- assert(k != kh_end(pkt_cache->index_by_name));
-
- pkt_cache_entry_t *entry = pkt_cache_at(pkt_cache, v_pool_pos);
- if (entry->entry_type == PKT_CACHE_CS_TYPE) {
- // Remove from hashmap
- free((Name *)kh_key(pkt_cache->index_by_name, k));
- kh_del(pkt_cache_name, pkt_cache->index_by_name, k);
-
- // Remove from pool
- pool_put(pkt_cache->entries, entry);
- }
- })
-
- // Re-create CS
- cs_clear(pkt_cache->cs);
-}
+ kh_pkt_cache_suffix_t *v_suffixes;
+ u32 k_suffix;
+ u32 v_pkt_cache_entry_id;
+ kh_foreach_value(pkt_cache->prefix_to_suffixes, v_suffixes, {
+ kh_foreach(v_suffixes, k_suffix, v_pkt_cache_entry_id, {
+ pkt_cache_entry_t *entry = pkt_cache_at(pkt_cache, v_pkt_cache_entry_id);
+ if (entry->entry_type == PKT_CACHE_CS_TYPE) {
+ // Remove from hash table
+ khiter_t k = kh_get_pkt_cache_suffix(v_suffixes, k_suffix);
+ assert(k != kh_end(v_suffixes));
+ kh_del_pkt_cache_suffix(v_suffixes, k);
+
+ // Remove from pool
+ pool_put(pkt_cache->entries, entry);
+ }
+ });
+ });
-size_t pkt_cache_get_size(pkt_cache_t *pkt_cache) {
- uint64_t hashmap_size = kh_size(pkt_cache->index_by_name);
- return hashmap_size;
-}
+ // Reset cached prefix
+ pkt_cache->cached_prefix = EMPTY_NAME_BITVECTOR;
+ pkt_cache->cached_suffixes = NULL;
-size_t pkt_cache_get_cs_size(pkt_cache_t *pkt_cache) {
- return pkt_cache->cs->num_entries;
+ // Re-create CS
+ cs_clear(pkt_cache->cs);
}
size_t pkt_cache_get_num_cs_stale_entries(pkt_cache_t *pkt_cache) {
@@ -531,17 +657,35 @@ int pkt_cache_set_cs_size(pkt_cache_t *pkt_cache, size_t size) {
return 0;
}
+size_t pkt_cache_get_size(pkt_cache_t *pkt_cache) {
+ return pool_len(pkt_cache->entries);
+}
+
+size_t pkt_cache_get_cs_size(pkt_cache_t *pkt_cache) {
+ return pkt_cache->cs->num_entries;
+}
+
size_t pkt_cache_get_pit_size(pkt_cache_t *pkt_cache) {
- uint64_t hashmap_size = kh_size(pkt_cache->index_by_name);
- uint64_t pit_size = hashmap_size - pkt_cache->cs->num_entries;
+ uint64_t pkt_cache_size = pkt_cache_get_size(pkt_cache);
+ uint64_t pit_size = pkt_cache_size - pkt_cache_get_cs_size(pkt_cache);
return pit_size;
}
void pkt_cache_log(pkt_cache_t *pkt_cache) {
- uint64_t hashmap_size = kh_size(pkt_cache->index_by_name);
- uint64_t pit_size = hashmap_size - pkt_cache->cs->num_entries;
DEBUG("Packet cache: total size = %lu, PIT size = %lu, CS size = %u",
- hashmap_size, pit_size, pkt_cache->cs->num_entries);
+ pkt_cache_get_size(pkt_cache), pkt_cache_get_pit_size(pkt_cache),
+ pkt_cache_get_cs_size(pkt_cache));
cs_log(pkt_cache->cs);
}
+
+pkt_cache_stats_t pkt_cache_get_stats(pkt_cache_t *pkt_cache) {
+ cs_lru_stats_t lru_stats = cs_get_lru_stats(pkt_cache_get_cs(pkt_cache));
+ pkt_cache_stats_t stats = {
+ .n_pit_entries = (uint32_t)pkt_cache_get_pit_size(pkt_cache),
+ .n_cs_entries = (uint32_t)pkt_cache_get_cs_size(pkt_cache),
+ .n_lru_evictions = (uint32_t)lru_stats.countLruEvictions,
+ };
+
+ return stats;
+}
diff --git a/hicn-light/src/hicn/core/packet_cache.h b/hicn-light/src/hicn/core/packet_cache.h
index ccfc83b97..47926fcdc 100644
--- a/hicn-light/src/hicn/core/packet_cache.h
+++ b/hicn-light/src/hicn/core/packet_cache.h
@@ -19,7 +19,7 @@
*
* The packet cache is a data structure that merges together the PIT and the CS,
* to which it holds a reference.
- * It contains PIT and CS entries, indexed in a hashtable by hICN packet names.
+ * It contains PIT and CS entries, indexed in a two-level hash table.
*
* Each entry has shared fields, e.g. entry type (PIT or CS) and timestamps,
* which are used by both PIT and CS entries. In addition, a C union holds
@@ -27,41 +27,64 @@
*
* Having a single entry that can hold PIT or CS entries allows to reduce
* the number of lookups.
+ *
+ * A prefix hash table <prefix, suffix_hashtable> stores the suffixes associated
+ * to each prefix, where each value in the map points to a separate hash
+ * table <suffix, packet_cache_reference> that can be used to retrieved the
+ * packet cache entry.
+ * When an interest/data packet is received, the prefix and the associated
+ * suffixes are saved; if the next packet cache operation involves the same
+ * prefix, no additional lookups in the prefix hash hashtable are needed.
*/
#ifndef HICNLIGHT_PACKET_CACHE_H
#define HICNLIGHT_PACKET_CACHE_H
+#include <hicn/util/khash.h>
#include "content_store.h"
#include "pit.h"
#include "msgbuf_pool.h"
-#include "../base/khash.h"
#include "../content_store/lru.h"
#define DEFAULT_PKT_CACHE_SIZE 2048
typedef enum { PKT_CACHE_PIT_TYPE, PKT_CACHE_CS_TYPE } pkt_cache_entry_type_t;
-/**
- * @brief Return a Name that can be used as key for hash table lookups.
- * The returned Name is a copy of the input one but it is "memsetted"
- * to ensure successful hash calculation.
- */
-static inline Name name_key_factory(const Name *name) {
- NameBitvector *content_name = name_GetContentName(name);
+#define foreach_kh_verdict \
+ _(FORWARD_INTEREST) \
+ _(AGGREGATE_INTEREST) \
+ _(RETRANSMIT_INTEREST) \
+ _(FORWARD_DATA) \
+ _(INTEREST_EXPIRED_FORWARD_INTEREST) \
+ _(DATA_EXPIRED_FORWARD_INTEREST) \
+ _(STORE_DATA) \
+ _(CLEAR_DATA) \
+ _(UPDATE_DATA) \
+ _(IGNORE_DATA) \
+ _(ERROR)
- Name name_key;
- memset(&name_key, 0, sizeof(Name));
+typedef enum {
+#define _(x) PKT_CACHE_VERDICT_##x,
+ foreach_kh_verdict
+#undef _
+} pkt_cache_verdict_t;
- name_key.content_name = *content_name;
- name_key.segment = name_GetSegment(name);
- name_key.name_hash = name_HashCode(name);
+#define foreach_kh_lookup \
+ _(INTEREST_NOT_EXPIRED) \
+ _(INTEREST_EXPIRED) \
+ _(DATA_NOT_EXPIRED) \
+ _(DATA_EXPIRED) \
+ _(NONE)
- return name_key;
-}
+typedef enum {
+#define _(x) PKT_CACHE_LU_##x,
+ foreach_kh_lookup
+#undef _
+} pkt_cache_lookup_t;
-KHASH_INIT(pkt_cache_name, const Name *, unsigned, 1, name_HashCode,
- name_Equals);
+KHASH_MAP_INIT_INT(pkt_cache_suffix, unsigned);
+KHASH_INIT(pkt_cache_prefix, const NameBitvector *, kh_pkt_cache_suffix_t *, 1,
+ nameBitvector_GetHash32, nameBitvector_Equals);
typedef struct {
pkt_cache_entry_type_t entry_type;
@@ -82,7 +105,12 @@ typedef struct {
pit_t *pit;
cs_t *cs;
pkt_cache_entry_t *entries;
- kh_pkt_cache_name_t *index_by_name;
+ kh_pkt_cache_prefix_t *prefix_to_suffixes;
+
+ // Cached prefix info to avoid double lookups,
+ // used for both single interest speculation and interest manifest
+ NameBitvector cached_prefix;
+ kh_pkt_cache_suffix_t *cached_suffixes;
} pkt_cache_t;
/**
@@ -92,7 +120,6 @@ typedef struct {
*/
pkt_cache_t *pkt_cache_create(size_t cs_size);
-#define _pc_var(x) _pkt_cache_##x
/**
* @brief Add an entry with the specified name to the packet cache.
*
@@ -101,29 +128,7 @@ pkt_cache_t *pkt_cache_create(size_t cs_size);
* allocated one from the msgbuf pool.
* * @param[in] name Name to use
*/
-static inline pkt_cache_entry_t *pkt_cache_allocate(
- const pkt_cache_t *pkt_cache, const Name *name) {
- pkt_cache_entry_t *entry = NULL;
- pool_get(pkt_cache->entries, entry);
- assert(entry);
-
- off_t id = entry - pkt_cache->entries;
- int res;
-
- // Generate the key (starting from the name) to use in the name hash table
- NameBitvector *nb = name_GetContentName(name);
- Name *name_copy = (Name *)calloc(1, sizeof(Name));
- name_copy->content_name = *nb;
- name_copy->segment = name_GetSegment(name);
- name_copy->name_hash = name_HashCode(name);
-
- // Add in name hash table
- khiter_t k = kh_put_pkt_cache_name(pkt_cache->index_by_name, name_copy, &res);
- assert(res != -1);
- kh_value(pkt_cache->index_by_name, k) = id;
-
- return entry;
-}
+pkt_cache_entry_t *pkt_cache_allocate(pkt_cache_t *pkt_cache, const Name *name);
/**
* @brief Free a packet cache data structure.
@@ -189,28 +194,6 @@ size_t pkt_cache_get_cs_size(pkt_cache_t *pkt_cache);
*/
size_t pkt_cache_get_pit_size(pkt_cache_t *pkt_cache);
-typedef enum {
- PKT_CACHE_LU_INTEREST_NOT_EXPIRED,
- PKT_CACHE_LU_INTEREST_EXPIRED,
- PKT_CACHE_LU_DATA_NOT_EXPIRED,
- PKT_CACHE_LU_DATA_EXPIRED,
- PKT_CACHE_LU_NONE
-} pkt_cache_lookup_t;
-
-typedef enum {
- PKT_CACHE_VERDICT_FORWARD_INTEREST,
- PKT_CACHE_VERDICT_AGGREGATE_INTEREST,
- PKT_CACHE_VERDICT_RETRANSMIT_INTEREST,
- PKT_CACHE_VERDICT_FORWARD_DATA,
- PKT_CACHE_VERDICT_INTEREST_EXPIRED_FORWARD_INTEREST,
- PKT_CACHE_VERDICT_DATA_EXPIRED_FORWARD_INTEREST,
- PKT_CACHE_VERDICT_STORE_DATA,
- PKT_CACHE_VERDICT_CLEAR_DATA,
- PKT_CACHE_VERDICT_UPDATE_DATA,
- PKT_CACHE_VERDICT_IGNORE_DATA,
- PKT_CACHE_VERDICT_ERROR
-} pkt_cache_verdict_t;
-
#define pkt_cache_entry_get_create_ts(E) ((E)->create_ts)
#define pkt_cache_entry_get_expire_ts(E) ((E)->expire_ts)
#define pkt_cache_entry_set_expire_ts(E, EXPIRY_TIME) \
@@ -241,7 +224,7 @@ pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, const Name *name,
bool is_serve_from_cs_enabled);
/**
- * @brief Clear the content of the CS.
+ * @brief Clear the content of the CS (PIT entries are left unmodified).
*
* @param pkt_cache Pointer to the packet cache data structure to use
*/
@@ -254,6 +237,8 @@ void pkt_cache_cs_clear(pkt_cache_t *pkt_cache);
*/
void pkt_cache_log(pkt_cache_t *pkt_cache);
+pkt_cache_stats_t pkt_cache_get_stats(pkt_cache_t *pkt_cache);
+
// TODO(eloparco): To implement
void pkt_cache_print(const pkt_cache_t *pkt_cache);
@@ -320,10 +305,13 @@ void pkt_cache_cs_to_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry,
* @param[in] pkt_cache Pointer to the packet cache data structure to use
* @param[in] msgbuf Pointer to the msgbuf associated with the PIT entry to
* insert
+ * @param[in] name Interest name to use; in case of aggregated interests, it is
+ * different from the name stored in the msgbuf
* @return pkt_cache_entry_t* Pointer to the packet cache (PIT) entry created
*/
pkt_cache_entry_t *pkt_cache_add_to_pit(pkt_cache_t *pkt_cache,
- const msgbuf_t *msgbuf);
+ const msgbuf_t *msgbuf,
+ const Name *name);
/**
* @brief Add CS entry to the packet cache.
@@ -374,6 +362,8 @@ void pkt_cache_update_cs(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
* @param[in, out] entry Pointer to the PIT entry to update
* @param[in] msgbuf Pointer to the msgbuf associated with the PIT entry to
* update
+ * @param[in] name Interest name to use; in case of aggregated interests, it is
+ * different from the name stored in the msgbuf
* @return true If aggregation (interest sent from a connection not stored in
* the PIT entry)
* @return false If retransmission (interest sent from a connection already
@@ -381,7 +371,23 @@ void pkt_cache_update_cs(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
*/
bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache,
pkt_cache_entry_t *entry,
- const msgbuf_t *msgbuf);
+ const msgbuf_t *msgbuf, const Name *name);
+
+/**
+ * @brief Cache prefix info (prefix + associated suffixes) to speed up lookups.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ * @param[in] prefix Name prefix to cache
+ */
+void pkt_cache_save_suffixes_for_prefix(pkt_cache_t *pkt_cache,
+ const NameBitvector *prefix);
+
+/**
+ * @brief Reset cached prefix info to force double lookups.
+ *
+ * @param[in] pkt_cache Pointer to the packet cache data structure to use
+ */
+void pkt_cache_reset_suffixes_for_prefix(pkt_cache_t *pkt_cache);
/************ Handle data/interest packets received *******/
@@ -413,7 +419,24 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache,
void pkt_cache_on_interest(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool,
off_t msgbuf_id, pkt_cache_verdict_t *verdict,
off_t *data_msgbuf_id, pkt_cache_entry_t **entry_ptr,
- bool is_serve_from_cs_enabled);
+ const Name *name, bool is_serve_from_cs_enabled);
+
+/********* Low-level operations on the hash table *********/
+#ifdef WITH_TESTS
+unsigned __get_suffix(kh_pkt_cache_suffix_t *suffixes, uint32_t suffix,
+ int *rc);
+unsigned _get_suffix(kh_pkt_cache_prefix_t *prefixes,
+ const NameBitvector *prefix, uint32_t suffix, int *rc);
+void __add_suffix(kh_pkt_cache_suffix_t *suffixes, uint32_t suffix,
+ unsigned val);
+void _add_suffix(kh_pkt_cache_prefix_t *prefixes, const NameBitvector *prefix,
+ uint32_t suffix, unsigned val);
+void _remove_suffix(kh_pkt_cache_prefix_t *prefixes,
+ const NameBitvector *prefix, uint32_t suffix);
+void _prefix_map_free(kh_pkt_cache_prefix_t *prefix_to_suffixes);
+kh_pkt_cache_suffix_t *_get_suffixes(kh_pkt_cache_prefix_t *prefix_to_suffixes,
+ const NameBitvector *prefix);
+#endif
/************** Content Store *****************************/
diff --git a/hicn-light/src/hicn/core/policy_stats.h b/hicn-light/src/hicn/core/policy_stats.h
index fa12b51cb..aee68e515 100644
--- a/hicn-light/src/hicn/core/policy_stats.h
+++ b/hicn-light/src/hicn/core/policy_stats.h
@@ -5,7 +5,6 @@
#ifdef WITH_POLICY_STATS
#include <hicn/policy.h>
-#include "../base/loop.h"
typedef struct policy_stats_mgr_s {
void* forwarder;
diff --git a/hicn-light/src/hicn/core/subscription.c b/hicn-light/src/hicn/core/subscription.c
index 0c4949f26..ad4006531 100644
--- a/hicn-light/src/hicn/core/subscription.c
+++ b/hicn-light/src/hicn/core/subscription.c
@@ -3,7 +3,7 @@
*/
#include "subscription.h"
-#include <hicn/base/vector.h>
+#include <hicn/util/vector.h>
#include <hicn/util/log.h>
/*----------------------------------------------------------------------------*
diff --git a/hicn-light/src/hicn/io/base.c b/hicn-light/src/hicn/io/base.c
index 71d10021e..cd7362956 100644
--- a/hicn-light/src/hicn/io/base.c
+++ b/hicn-light/src/hicn/io/base.c
@@ -42,7 +42,7 @@ ssize_t io_read_single_fd(int fd, msgbuf_t *msgbuf, address_t *address) {
return -1;
}
- msgbuf->length = n;
+ msgbuf->length = (unsigned int)n;
*address = ADDRESS_ANY(AF_UNSPEC, 0); // XXX placeholder, see hicn.c
}
@@ -55,7 +55,7 @@ ssize_t io_read_single_socket(int fd, msgbuf_t *msgbuf, address_t *address) {
uint8_t *packet = msgbuf_get_packet(msgbuf);
ssize_t n = recvfrom(fd, packet, MTU, 0, (struct sockaddr *)sa, &sa_len);
- msgbuf->length = n;
+ msgbuf->length = (unsigned int)n;
return n;
}
@@ -114,21 +114,6 @@ ssize_t io_read_batch_socket(int fd, msgbuf_t **msgbuf, address_t **address,
struct mmsghdr *msg = &msghdr[i];
msgbuf[i]->length = msg->msg_len;
- /*
- * As is, the address we put in the array has uninitialized
- * memory in it:
- * *address[i] = *(address_t*)msg->msg_hdr.msg_name;
- *
- * This can be confirmed by testing with the following
- * memset which removes the valgrind errors:
- * memset(address[i], 0, sizeof(address_t));
- *
- * The solution is to copy only the part which we know is
- * initialized (we have compatible types, since the destination, an
- * address_t, is effectively a struct sockaddr_storage). We might
- * eventually provide a helper for this to avoid similar mistakes.
- */
- //*address[i] = *(address_t*)msg->msg_hdr.msg_name;
memcpy(address[i], msg->msg_hdr.msg_name, msg->msg_hdr.msg_namelen);
}
break;
diff --git a/hicn-light/src/hicn/io/hicn.c b/hicn-light/src/hicn/io/hicn.c
index 8b4ad2e00..d019a49c1 100644
--- a/hicn-light/src/hicn/io/hicn.c
+++ b/hicn-light/src/hicn/io/hicn.c
@@ -401,12 +401,10 @@ static void connection_hicn_finalize(connection_t *connection) {
return;
}
-static bool connection_hicn_flush(const connection_t *connection) {
- return false;
-}
+static bool connection_hicn_flush(connection_t *connection) { return false; }
-static bool connection_hicn_send(const connection_t *connection,
- msgbuf_t *msgbuf, bool queue) {
+static bool connection_hicn_send(connection_t *connection, msgbuf_t *msgbuf,
+ bool queue) {
assert(connection);
/* msgbuf can be NULL */
diff --git a/hicn-light/src/hicn/io/tcp.c b/hicn-light/src/hicn/io/tcp.c
index 69ad32d16..50591c3fc 100644
--- a/hicn-light/src/hicn/io/tcp.c
+++ b/hicn-light/src/hicn/io/tcp.c
@@ -287,9 +287,7 @@ connection_tcp_sendv(connnection_t * connection, struct iovec * iov,
}
#endif
-static bool connection_tcp_flush(const connection_t *connection) {
- return true;
-}
+static bool connection_tcp_flush(connection_t *connection) { return true; }
/**
* @function streamConnection_Send
@@ -303,8 +301,8 @@ static bool connection_tcp_flush(const connection_t *connection) {
*/
// XXX address not used anywhere
// XXX too much repeated code with sendv here
-static bool connection_tcp_send(const connection_t *connection,
- msgbuf_t *msgbuf, bool queue) {
+static bool connection_tcp_send(connection_t *connection, msgbuf_t *msgbuf,
+ bool queue) {
assert(connection);
assert(msgbuf);
diff --git a/hicn-light/src/hicn/io/udp.c b/hicn-light/src/hicn/io/udp.c
index 3301e2178..149d53aea 100644
--- a/hicn-light/src/hicn/io/udp.c
+++ b/hicn-light/src/hicn/io/udp.c
@@ -49,10 +49,9 @@
#include <hicn/util/log.h>
#include <hicn/util/sstrncpy.h>
+#include <hicn/util/ring.h>
#include "base.h"
-#include "../base/loop.h"
-#include "../base/ring.h"
#include "../core/address_pair.h"
#include "../core/connection.h"
#include "../core/connection_vft.h"
@@ -344,7 +343,7 @@ static void connection_udp_finalize(connection_t *connection) {
ring_free(data->ring);
}
-static bool connection_udp_flush(const connection_t *connection) {
+static bool connection_udp_flush(connection_t *connection) {
#ifdef __linux__
int retry = 0;
off_t msgbuf_id = 0;
@@ -375,9 +374,16 @@ SEND:
msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id);
// update path label
- if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA)
+ if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA) {
msgbuf_update_pathlabel(msgbuf, connection_get_id(connection));
+ connection->stats.data.tx_pkts++;
+ connection->stats.data.tx_bytes += msgbuf_get_len(msgbuf);
+ } else {
+ connection->stats.interests.tx_pkts++;
+ connection->stats.interests.tx_bytes += msgbuf_get_len(msgbuf);
+ }
+
data->iovecs[i].iov_base = msgbuf_get_packet(msgbuf);
data->iovecs[i].iov_len = msgbuf_get_len(msgbuf);
cpt++;
@@ -430,8 +436,8 @@ SENDMMSG:
* @param dummy is ignored. A udp connection has only one peer.
* @return <#return#>
*/
-static bool connection_udp_send(const connection_t *connection,
- msgbuf_t *msgbuf, bool queue) {
+static bool connection_udp_send(connection_t *connection, msgbuf_t *msgbuf,
+ bool queue) {
assert(connection);
assert(msgbuf);
@@ -454,9 +460,16 @@ static bool connection_udp_send(const connection_t *connection,
#endif /* __linux__ */
/* Send one */
// update the path label befor send the packet
- if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA)
+ if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA) {
msgbuf_update_pathlabel(msgbuf, connection_get_id(connection));
+ connection->stats.data.tx_pkts++;
+ connection->stats.data.tx_bytes += msgbuf_get_len(msgbuf);
+ } else {
+ connection->stats.interests.tx_pkts++;
+ connection->stats.interests.tx_bytes += msgbuf_get_len(msgbuf);
+ }
+
ssize_t writeLength = write(connection->fd, msgbuf_get_packet(msgbuf),
msgbuf_get_len(msgbuf));
diff --git a/hicn-light/src/hicn/strategies/probe_generator.c b/hicn-light/src/hicn/strategies/probe_generator.c
index 439de0a12..bc141e518 100644
--- a/hicn-light/src/hicn/strategies/probe_generator.c
+++ b/hicn-light/src/hicn/strategies/probe_generator.c
@@ -78,7 +78,7 @@ int generate_probe(probe_generator_t *pg, const msgbuf_t *msgbuf,
const forwarder_t *forwarder, nexthop_t nexthop) {
msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder);
connection_table_t *table = forwarder_get_connection_table(forwarder);
- const connection_t *conn = connection_table_get_by_id(table, nexthop);
+ connection_t *conn = connection_table_get_by_id(table, nexthop);
if (!conn) return -1;
msgbuf_t *probe;
diff --git a/hicn-light/src/hicn/strategies/probe_generator.h b/hicn-light/src/hicn/strategies/probe_generator.h
index 26d6a3a22..7a9f3a58a 100644
--- a/hicn-light/src/hicn/strategies/probe_generator.h
+++ b/hicn-light/src/hicn/strategies/probe_generator.h
@@ -16,7 +16,7 @@
#ifndef HICNLIGHT_PROBE_GENERATOR
#define HICNLIGHT_PROBE_GENERATOR
-#include "../base/khash.h"
+#include <hicn/util/khash.h>
#include <hicn/core/ticks.h>
#include <hicn/core/msgbuf.h>
diff --git a/hicn-light/src/hicn/test/CMakeLists.txt b/hicn-light/src/hicn/test/CMakeLists.txt
index 0ded4253d..65e216c1e 100644
--- a/hicn-light/src/hicn/test/CMakeLists.txt
+++ b/hicn-light/src/hicn/test/CMakeLists.txt
@@ -13,6 +13,7 @@ list(APPEND TESTS_SRC
test-ctrl.cc
test-ring.cc
test-vector.cc
+ test-interest_manifest.cc
test-msgbuf_pool.cc
test-nexthops.cc
test-connection_table.cc
diff --git a/hicn-light/src/hicn/test/test-bitmap.cc b/hicn-light/src/hicn/test/test-bitmap.cc
index f9cd4024f..1fd21a1bb 100644
--- a/hicn-light/src/hicn/test/test-bitmap.cc
+++ b/hicn-light/src/hicn/test/test-bitmap.cc
@@ -25,7 +25,7 @@
extern "C" {
#define WITH_TESTS
-#include <hicn/base/bitmap.h>
+#include <hicn/util/bitmap.h>
}
#define DEFAULT_SIZE 10
diff --git a/hicn-light/src/hicn/test/test-connection_table.cc b/hicn-light/src/hicn/test/test-connection_table.cc
index 6bbf478e2..d17de7c2c 100644
--- a/hicn-light/src/hicn/test/test-connection_table.cc
+++ b/hicn-light/src/hicn/test/test-connection_table.cc
@@ -35,7 +35,7 @@ extern "C" {
class ConnectionTableTest : public ::testing::Test {
protected:
ConnectionTableTest() {
- log_conf.log_level = LOG_INFO;
+ log_conf.log_level = LOG_WARN;
conn_table_ = connection_table_create();
pair_ =
@@ -164,6 +164,10 @@ TEST_F(ConnectionTableTest, RemoveConnection) {
}
TEST_F(ConnectionTableTest, PrintTable) {
+ // Set verbose log level
+ int old_log_level = log_conf.log_level;
+ log_conf.log_level = LOG_INFO;
+
connection_ = connection_table_allocate(conn_table_, &pair_, CONNECTION_NAME);
connection_->type = FACE_TYPE_TCP;
@@ -184,6 +188,8 @@ TEST_F(ConnectionTableTest, PrintTable) {
EXPECT_THAT(std_out, testing::HasSubstr("127.0.0.1:2"));
EXPECT_THAT(std_out, testing::HasSubstr("127.0.0.1:3"));
EXPECT_THAT(std_out, testing::HasSubstr("127.0.0.1:4"));
+
+ log_conf.log_level = old_log_level; // Restore old log level
}
TEST_F(ConnectionTableTest, AddMultipleConnections) {
@@ -248,3 +254,43 @@ TEST_F(ConnectionTableTest, Iterate) {
EXPECT_THAT(std_out, testing::HasSubstr("127.0.0.1:3"));
EXPECT_THAT(std_out, testing::HasSubstr("127.0.0.1:4"));
}
+
+TEST_F(ConnectionTableTest, GenerateConnName) {
+ char conn_name[SYMBOLIC_NAME_LEN];
+ int rc = connection_table_get_random_name(conn_table_, conn_name);
+ EXPECT_EQ(rc, 0);
+
+ connection_ = connection_table_allocate(conn_table_, &pair_, conn_name);
+ connection_->type = FACE_TYPE_TCP;
+ connection_->pair = pair_;
+
+ char conn_name2[SYMBOLIC_NAME_LEN];
+ rc = connection_table_get_random_name(conn_table_, conn_name2);
+ EXPECT_EQ(rc, 0);
+ EXPECT_NE(strncmp(conn_name, conn_name2, SYMBOLIC_NAME_LEN), 0);
+}
+
+TEST_F(ConnectionTableTest, GenerateConnNameExhaustion) {
+ char conn_name[SYMBOLIC_NAME_LEN];
+ bool unable_to_allocate = false;
+
+ // Force name exhaustion
+ int i, n_connections = 1 + USHRT_MAX;
+ for (int i = 0; i <= n_connections; i++) {
+ int rc = connection_table_get_random_name(conn_table_, conn_name);
+ if (rc < 0) {
+ unable_to_allocate = true;
+ break;
+ }
+
+ address_pair_t pair =
+ address_pair_factory(_ADDRESS4_LOCALHOST(1), _ADDRESS4_LOCALHOST(i));
+ connection_t *conn =
+ connection_table_allocate(conn_table_, &pair, conn_name);
+ memset(conn, 0, sizeof(connection_t));
+ conn->type = FACE_TYPE_TCP;
+ conn->pair = pair;
+ }
+
+ EXPECT_TRUE(unable_to_allocate);
+} \ No newline at end of file
diff --git a/hicn-light/src/hicn/test/test-hash.cc b/hicn-light/src/hicn/test/test-hash.cc
index 2b72e194a..3b03a08a6 100644
--- a/hicn-light/src/hicn/test/test-hash.cc
+++ b/hicn-light/src/hicn/test/test-hash.cc
@@ -22,14 +22,18 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
-// #include <hicn/transport/utils/hash.h>
+#include <unordered_set>
+#include <hicn/test/test-utils.h>
extern "C" {
-#include <hicn/base/hash.h>
+#include <hicn/util/hash.h>
#include <hicn/core/address_pair.h>
#include <hicn/core/listener.h>
}
+static constexpr uint32_t init_val = 2166136261UL;
+static constexpr int N_HASHES = 50000;
+
TEST(HashTest, MultipleHashesForSameAddrPair) {
address_pair_t pair =
address_pair_factory(_ADDRESS4_LOCALHOST(1), _ADDRESS4_LOCALHOST(2));
@@ -108,16 +112,106 @@ TEST(HashTest, SameListenerKeys) {
}
TEST(HashTest, Collisions) {
- uint32_t init_val = 2166136261UL;
- (void)init_val;
-
- std::map<u32, uint32_t> hashes;
+ std::unordered_set<uint32_t> hashes;
+ int n_collisions = 0;
for (int i = 0; i < 50000; i++) {
uint32_t seg = i;
- // u32 h = utils::hash::fnv32_buf (&seg, sizeof (seg));
- // u32 h = cumulative_hash32 (&seg, sizeof (seg), init_val);
+ // u32 h = utils::hash::fnv32_buf(&seg, sizeof(seg));
+ // u32 h = cumulative_hash32(&seg, sizeof(uint32_t), init_val);
u32 h = hash(&seg, sizeof(seg));
- EXPECT_FALSE(hashes.find(h) != hashes.end()) << seg << " - " << hashes[h];
- hashes[h] = seg;
+
+ if (hashes.find(h) != hashes.end()) n_collisions++;
+ hashes.insert(h);
}
+ EXPECT_EQ(n_collisions, 0);
+}
+
+/*** Compare FNV with Jenkins ***/
+
+typedef struct {
+ uint32_t data[6];
+} small_struct_t; // Same size as 'NameBitvector'
+
+typedef struct {
+ uint64_t data[32];
+} big_struct_t; // Same size as 'address_pair_t'
+
+TEST(HashTest, PerformanceComparisonSmallStruct) {
+ small_struct_t small_struct;
+
+ // FNV
+ auto time_fnv = get_execution_time([&]() {
+ for (int i = 0; i < N_HASHES; i++) {
+ small_struct.data[0] = i;
+ cumulative_hash32(&small_struct, sizeof(small_struct_t), init_val);
+ }
+ });
+
+ // Jenkins
+ auto time_jenkins = get_execution_time([&]() {
+ for (int i = 0; i < N_HASHES; i++) {
+ small_struct.data[0] = i;
+ hash(&small_struct, sizeof(small_struct_t));
+ }
+ });
+
+ std::cout << "Small struct (size = " << sizeof(small_struct_t) << " bytes)\n";
+ std::cout << "FNV: " << time_fnv << "ms\n";
+ std::cout << "Jenkins: " << time_jenkins << "ms\n";
+}
+
+TEST(HashTest, PerformanceComparisonBigStruct) {
+ big_struct_t big_struct;
+
+ // FNV
+ auto time_fnv = get_execution_time([&]() {
+ for (int i = 0; i < N_HASHES; i++) {
+ big_struct.data[0] = i;
+ cumulative_hash32(&big_struct, sizeof(big_struct_t), init_val);
+ }
+ });
+
+ // Jenkins
+ auto time_jenkins = get_execution_time([&]() {
+ for (int i = 0; i < N_HASHES; i++) {
+ big_struct.data[0] = i;
+ hash(&big_struct, sizeof(big_struct_t));
+ }
+ });
+
+ std::cout << "Big struct (size = " << sizeof(big_struct_t) << " bytes)\n";
+ std::cout << "FNV: " << time_fnv << "ms\n";
+ std::cout << "Jenkins: " << time_jenkins << "ms\n";
+}
+
+TEST(HashTest, CollisionsComparison) {
+ small_struct_t small_struct = {0};
+ std::unordered_set<uint32_t> hashes;
+ int n_collisions_fnv = 0, n_collisions_jenkins = 0, n_collisions_murmur = 0,
+ n_collisions_xxhash = 0;
+
+ // FNV
+ for (int i = 0; i < 10 * N_HASHES; i++) {
+ small_struct.data[0] = i;
+ uint32_t h =
+ cumulative_hash32(&small_struct, sizeof(small_struct_t), init_val);
+
+ if (hashes.find(h) != hashes.end()) n_collisions_fnv++;
+ hashes.insert(h);
+ }
+
+ hashes.clear();
+
+ // Jenkins
+ for (int i = 0; i < 10 * N_HASHES; i++) {
+ small_struct.data[0] = i;
+ uint32_t h = hash(&small_struct, sizeof(small_struct_t));
+
+ if (hashes.find(h) != hashes.end()) n_collisions_jenkins++;
+ hashes.insert(h);
+ }
+
+ std::cout << "Small struct (size = " << sizeof(small_struct_t) << " bytes)\n";
+ std::cout << "FNV: " << n_collisions_fnv << " collision/s\n";
+ std::cout << "Jenkins: " << n_collisions_jenkins << " collision/s\n";
} \ No newline at end of file
diff --git a/hicn-light/src/hicn/test/test-interest_manifest.cc b/hicn-light/src/hicn/test/test-interest_manifest.cc
new file mode 100644
index 000000000..6408a3f2a
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-interest_manifest.cc
@@ -0,0 +1,79 @@
+/*
+ * 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>
+
+extern "C" {
+#include <hicn/core/interest_manifest.h>
+}
+
+static constexpr size_t WORD_SIZE = 32;
+
+class InterestManifestTest : public ::testing::Test {
+ protected:
+ InterestManifestTest() {}
+ virtual ~InterestManifestTest() {}
+};
+
+TEST_F(InterestManifestTest, OneWordBitmapUpdate) {
+ u32 initial_bitmap[1];
+ u32 curr_bitmap[1] = {0};
+ initial_bitmap[0] = 0x00000b07; // 000000000000000000000101100000111
+
+ // Consume first 4 'one' bits (i.e. suffixes), reaching position 9
+ int pos = 0, max_suffixes = 4;
+ pos = interest_manifest_update_bitmap(initial_bitmap, curr_bitmap, pos,
+ WORD_SIZE, max_suffixes);
+ EXPECT_EQ(pos, 9);
+ EXPECT_EQ(curr_bitmap[0], 0x00000107);
+
+ // Consume the remaining 2 'one' bits, reaching end of bitmap
+ u32 curr_bitmap2[1] = {0};
+ pos = interest_manifest_update_bitmap(initial_bitmap, curr_bitmap2, pos,
+ WORD_SIZE, max_suffixes);
+ EXPECT_EQ(pos, WORD_SIZE);
+ EXPECT_EQ(curr_bitmap2[0], 0x00000a00);
+
+ // Consume all suffixes at once
+ u32 curr_bitmap3[1] = {0};
+ max_suffixes = 16;
+ pos = interest_manifest_update_bitmap(initial_bitmap, curr_bitmap3, 0,
+ WORD_SIZE, max_suffixes);
+ EXPECT_EQ(pos, WORD_SIZE);
+ EXPECT_EQ(curr_bitmap3[0], initial_bitmap[0]);
+}
+
+TEST_F(InterestManifestTest, TwoWordBitmapUpdate) {
+ u32 initial_bitmap[2];
+ initial_bitmap[0] = 0x00000b07;
+ initial_bitmap[1] = 0x00000b07;
+ // -> 100000000000000000000101100000111000000000000000000000101100000111
+
+ int expected_pos[] = {34, 64};
+ u32 expected_bitmap[][2] = {{0x00000b07, 0x00000003}, {0x0, 0x00000b04}};
+
+ // Loop to consume all suffixes
+ int pos = 0, max_suffixes = 8, i = 0, len = WORD_SIZE * 2;
+ while (pos != len) {
+ u32 curr_bitmap[2] = {0};
+ pos = interest_manifest_update_bitmap(initial_bitmap, curr_bitmap, pos, len,
+ max_suffixes);
+
+ EXPECT_EQ(pos, expected_pos[i]);
+ EXPECT_EQ(curr_bitmap[0], expected_bitmap[i][0]);
+ EXPECT_EQ(curr_bitmap[1], expected_bitmap[i][1]);
+ i++;
+ }
+} \ No newline at end of file
diff --git a/hicn-light/src/hicn/test/test-khash.cc b/hicn-light/src/hicn/test/test-khash.cc
index 4fcb48c31..f437f8858 100644
--- a/hicn-light/src/hicn/test/test-khash.cc
+++ b/hicn-light/src/hicn/test/test-khash.cc
@@ -24,7 +24,7 @@
#include <netinet/in.h>
extern "C" {
-#include <hicn/base/khash.h>
+#include <hicn/util/khash.h>
}
KHASH_MAP_INIT_INT(int, unsigned char)
diff --git a/hicn-light/src/hicn/test/test-msgbuf_pool.cc b/hicn-light/src/hicn/test/test-msgbuf_pool.cc
index 5537aa216..e9c8e6424 100644
--- a/hicn-light/src/hicn/test/test-msgbuf_pool.cc
+++ b/hicn-light/src/hicn/test/test-msgbuf_pool.cc
@@ -26,7 +26,7 @@
extern "C" {
#define WITH_TESTS
#include <hicn/core/msgbuf_pool.h>
-#include <hicn/base/pool.h>
+#include <hicn/util/pool.h>
}
class MsgbufPoolTest : public ::testing::Test {
diff --git a/hicn-light/src/hicn/test/test-packet_cache.cc b/hicn-light/src/hicn/test/test-packet_cache.cc
index bb24daeb8..0b4b214f0 100644
--- a/hicn-light/src/hicn/test/test-packet_cache.cc
+++ b/hicn-light/src/hicn/test/test-packet_cache.cc
@@ -15,23 +15,26 @@
#include <gtest/gtest.h>
-#include <thread>
#include <optional>
+#include <random>
+#include <hicn/test/test-utils.h>
extern "C" {
#define WITH_TESTS
#include <hicn/core/packet_cache.h>
}
-const unsigned CS_SIZE = 100;
-const unsigned CONN_ID = 0;
-const unsigned CONN_ID_2 = 1;
-const unsigned MSGBUF_ID = 0;
-const unsigned MSGBUF_ID_2 = 1;
-const unsigned MSGBUF_ID_3 = 2;
-const unsigned FIVE_SECONDS = 5000;
-const unsigned IPV4_LEN = 32;
-const unsigned IPV6_LEN = 128;
+static constexpr unsigned CS_SIZE = 100;
+static constexpr unsigned CONN_ID = 0;
+static constexpr unsigned CONN_ID_2 = 1;
+static constexpr unsigned MSGBUF_ID = 0;
+static constexpr unsigned MSGBUF_ID_2 = 1;
+static constexpr unsigned MSGBUF_ID_3 = 2;
+static constexpr unsigned FIVE_SECONDS = 5000;
+static constexpr unsigned IPV4_LEN = 32;
+static constexpr unsigned IPV6_LEN = 128;
+
+static constexpr int N_OPS = 50000;
class PacketCacheTest : public ::testing::Test {
protected:
@@ -40,33 +43,78 @@ class PacketCacheTest : public ::testing::Test {
name = (Name *)malloc(sizeof(Name));
name_CreateFromAddress(name, AF_INET, IPV4_ANY, IPV4_LEN);
msgbuf_pool = msgbuf_pool_create();
+ msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, name);
}
+
virtual ~PacketCacheTest() {
- pkt_cache_free(pkt_cache);
+ free(name);
msgbuf_pool_free(msgbuf_pool);
+ pkt_cache_free(pkt_cache);
+ }
+
+ msgbuf_t *msgbuf_create(msgbuf_pool_t *msgbuf_pool, unsigned conn_id,
+ Name *name,
+ std::optional<Ticks> lifetime = FIVE_SECONDS) {
+ msgbuf_t *msgbuf;
+ msgbuf_pool_get(msgbuf_pool, &msgbuf);
+
+ msgbuf->connection_id = conn_id;
+ name_Copy(name, msgbuf_get_name(msgbuf));
+ hicn_packet_init_header(HF_INET6_TCP,
+ (hicn_header_t *)msgbuf_get_packet(msgbuf));
+ msgbuf_set_interest_lifetime(msgbuf, *lifetime);
+
+ return msgbuf;
+ }
+
+ Name get_name_from_prefix(const char *prefix_str) {
+ ip_address_t prefix;
+ inet_pton(AF_INET6, prefix_str, (struct in6_addr *)&prefix);
+
+ Name name;
+ name_CreateFromAddress(&name, AF_INET6, prefix, IPV6_LEN);
+
+ return name;
}
pkt_cache_t *pkt_cache;
pkt_cache_entry_t *entry = nullptr;
msgbuf_pool_t *msgbuf_pool;
Name *name;
-};
-
-msgbuf_t *msgbuf_factory(msgbuf_pool_t *msgbuf_pool, unsigned conn_id,
- Name *name,
- std::optional<Ticks> lifetime = FIVE_SECONDS) {
msgbuf_t *msgbuf;
- msgbuf_pool_get(msgbuf_pool, &msgbuf);
-
- msgbuf->connection_id = conn_id;
- name_Copy(name, msgbuf_get_name(msgbuf));
- hicn_packet_init_header(HF_INET6_TCP,
- (hicn_header_t *)msgbuf_get_packet(msgbuf));
- // Same as 'msgbuf_set_data_expiry_time',
- // it would write in the same field
- msgbuf_set_interest_lifetime(msgbuf, *lifetime);
+};
- return msgbuf;
+TEST_F(PacketCacheTest, LowLevelOperations) {
+ int rc;
+ kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix();
+ NameBitvector *prefix = name_GetContentName(name);
+ _add_suffix(prefix_to_suffixes, prefix, 1, 11);
+ _add_suffix(prefix_to_suffixes, prefix, 2, 22);
+
+ unsigned id = _get_suffix(prefix_to_suffixes, prefix, 1, &rc);
+ EXPECT_EQ(rc, KH_FOUND);
+ EXPECT_EQ(id, 11);
+
+ id = _get_suffix(prefix_to_suffixes, prefix, 2, &rc);
+ EXPECT_EQ(rc, KH_FOUND);
+ EXPECT_EQ(id, 22);
+
+ id = _get_suffix(prefix_to_suffixes, prefix, 5, &rc);
+ EXPECT_EQ(rc, KH_NOT_FOUND);
+ EXPECT_EQ(id, -1);
+
+ _add_suffix(prefix_to_suffixes, prefix, 5, 55);
+ id = _get_suffix(prefix_to_suffixes, prefix, 5, &rc);
+ EXPECT_EQ(rc, KH_FOUND);
+ EXPECT_EQ(id, 55);
+
+ _remove_suffix(prefix_to_suffixes, prefix, 2);
+ _add_suffix(prefix_to_suffixes, prefix, 2, 222);
+ id = _get_suffix(prefix_to_suffixes, prefix, 2, &rc);
+ EXPECT_EQ(rc, KH_FOUND);
+ EXPECT_EQ(id, 222);
+
+ _prefix_map_free(prefix_to_suffixes);
}
TEST_F(PacketCacheTest, CreatePacketCache) {
@@ -89,10 +137,12 @@ TEST_F(PacketCacheTest, AddPacketCacheEntry) {
EXPECT_NE(entry, nullptr);
ASSERT_EQ(pkt_cache_get_size(pkt_cache), 1u);
- // // Get entry by name
- Name name_key = name_key_factory(name);
- khiter_t k = kh_get_pkt_cache_name(pkt_cache->index_by_name, &name_key);
- EXPECT_NE(k, kh_end(pkt_cache->index_by_name));
+ // Get entry by name
+ pkt_cache_lookup_t lookup_result;
+ off_t entry_id;
+ pkt_cache_entry_t *entry = pkt_cache_lookup(pkt_cache, name, msgbuf_pool,
+ &lookup_result, &entry_id, true);
+ EXPECT_NE(lookup_result, PKT_CACHE_LU_NONE);
}
TEST_F(PacketCacheTest, GetCS) {
@@ -141,14 +191,11 @@ TEST_F(PacketCacheTest, AddEntryAndLookup) {
}
TEST_F(PacketCacheTest, AddToPIT) {
- // Prepare msgbuf
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
-
// Check if entry properly created
- pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf);
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name);
ASSERT_NE(entry, nullptr);
EXPECT_EQ(entry->entry_type, PKT_CACHE_PIT_TYPE);
- EXPECT_EQ(pit_entry_ingress_contains(&entry->u.pit_entry, CONN_ID), true);
+ EXPECT_TRUE(pit_entry_ingress_contains(&entry->u.pit_entry, CONN_ID));
ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
@@ -162,9 +209,6 @@ TEST_F(PacketCacheTest, AddToPIT) {
}
TEST_F(PacketCacheTest, AddToCS) {
- // Prepare msgbuf
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
-
// Check if entry properly created
pkt_cache_entry_t *entry =
pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
@@ -191,9 +235,8 @@ TEST_F(PacketCacheTest, AddToCS) {
}
TEST_F(PacketCacheTest, PitToCS) {
- // Prepare msgbuf and PIT entry
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
- pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf);
+ // Prepare PIT entry
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name);
off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
@@ -224,8 +267,7 @@ TEST_F(PacketCacheTest, PitToCS) {
}
TEST_F(PacketCacheTest, CsToPIT) {
- // Prepare msgbuf and CS entry
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
+ // Prepare CS entry
pkt_cache_entry_t *entry =
pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
@@ -237,7 +279,7 @@ TEST_F(PacketCacheTest, CsToPIT) {
entry_id);
ASSERT_NE(entry, nullptr);
EXPECT_EQ(entry->entry_type, PKT_CACHE_PIT_TYPE);
- EXPECT_EQ(pit_entry_ingress_contains(&entry->u.pit_entry, CONN_ID), true);
+ EXPECT_TRUE(pit_entry_ingress_contains(&entry->u.pit_entry, CONN_ID));
ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
@@ -250,14 +292,13 @@ TEST_F(PacketCacheTest, CsToPIT) {
}
TEST_F(PacketCacheTest, UpdateInPIT) {
- // Prepare msgbuf and PIT entry
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
- pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf);
+ // Prepare PIT entry
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name);
off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
Name new_name;
name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN);
- msgbuf_t *new_msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID_2, &new_name);
+ msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name);
// Check if entry properly updated
pkt_cache_update_pit(pkt_cache, entry, new_msgbuf);
@@ -276,15 +317,14 @@ TEST_F(PacketCacheTest, UpdateInPIT) {
}
TEST_F(PacketCacheTest, UpdateInCS) {
- // Prepare msgbuf and CS entry
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
+ // Prepare CS entry
pkt_cache_entry_t *entry =
pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry);
Name new_name;
name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN);
- msgbuf_t *new_msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID_2, &new_name);
+ msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name);
// Check if entry properly updated
pkt_cache_update_cs(pkt_cache, msgbuf_pool, entry, new_msgbuf, MSGBUF_ID_2);
@@ -304,9 +344,8 @@ TEST_F(PacketCacheTest, UpdateInCS) {
}
TEST_F(PacketCacheTest, RemoveFromPIT) {
- // Prepare msgbuf and PIT entry
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
- pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf);
+ // Prepare PIT entry
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name);
ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
@@ -324,8 +363,7 @@ TEST_F(PacketCacheTest, RemoveFromPIT) {
}
TEST_F(PacketCacheTest, RemoveFromCS) {
- // Prepare msgbuf and CS entry
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
+ // Prepare CS entry
pkt_cache_entry_t *entry =
pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u);
@@ -351,11 +389,10 @@ TEST_F(PacketCacheTest, RemoveFromCS) {
}
TEST_F(PacketCacheTest, AddTwoEntriesToCS) {
- // Prepare msgbufs
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
+ // Prepare another msgbuf
Name new_name;
name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN);
- msgbuf_t *new_msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID_2, &new_name);
+ msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name);
pkt_cache_entry_t *entry_1 =
pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
@@ -374,18 +411,17 @@ TEST_F(PacketCacheTest, AddTwoEntriesToCS) {
}
TEST_F(PacketCacheTest, AggregateInPIT) {
- // Prepare msgbufs
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
+ // Prepare another msgbuf
Name new_name;
name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN);
- msgbuf_t *new_msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID_2, &new_name);
+ msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name);
// Check if entry properly created (use sleep to get an updated ts)
- pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf);
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name);
Ticks old_lifetime = entry->expire_ts;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
bool is_aggregated =
- pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf);
+ pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf, name);
Ticks new_lifetime = entry->expire_ts;
ASSERT_NE(entry, nullptr);
@@ -403,18 +439,17 @@ TEST_F(PacketCacheTest, AggregateInPIT) {
}
TEST_F(PacketCacheTest, RetransmissionInPIT) {
- // Prepare msgbufs (using same connection ID)
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name);
+ // Prepare another msgbuf (using same connection ID)
Name new_name;
name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN);
- msgbuf_t *new_msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, &new_name);
+ msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &new_name);
// Check if entry properly created (use sleep to get an updated ts)
- pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf);
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name);
Ticks old_lifetime = entry->expire_ts;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
bool is_aggregated =
- pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf);
+ pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf, name);
Ticks new_lifetime = entry->expire_ts;
ASSERT_NE(entry, nullptr);
@@ -433,10 +468,10 @@ TEST_F(PacketCacheTest, RetransmissionInPIT) {
TEST_F(PacketCacheTest, LookupExpiredInterest) {
// Prepare msgbuf with 0 as interest lifetime
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name, 0);
+ msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, name, 0);
// Add to PIT
- pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf);
+ pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name);
ASSERT_NE(entry, nullptr);
// Wait to make the interest expire
@@ -451,7 +486,7 @@ TEST_F(PacketCacheTest, LookupExpiredInterest) {
TEST_F(PacketCacheTest, LookupExpiredData) {
// Prepare msgbuf with 0 as data expiry time
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name, 0);
+ msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, name, 0);
// Add to CS
pkt_cache_entry_t *entry =
@@ -470,20 +505,20 @@ TEST_F(PacketCacheTest, LookupExpiredData) {
TEST_F(PacketCacheTest, GetStaleEntries) {
// Add to CS a msgbuf with immediate expiration (i.e. stale)
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, CONN_ID, name, 0);
+ msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, name, 0);
pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
// Add to CS another msgbuf with immediate expiration (i.e. stale)
Name name_2;
name_CreateFromAddress(&name_2, AF_INET, IPV4_LOOPBACK, IPV4_LEN);
- msgbuf_t *msgbuf_2 = msgbuf_factory(msgbuf_pool, CONN_ID, &name_2, 0);
+ msgbuf_t *msgbuf_2 = msgbuf_create(msgbuf_pool, CONN_ID, &name_2, 0);
pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf_2, MSGBUF_ID_2);
// Add to CS a msgbuf with 5-seconds expiration (i.e. not stale)
Name name_3;
name_CreateFromAddress(&name_3, AF_INET6, IPV6_LOOPBACK, IPV6_LEN);
msgbuf_t *msgbuf_3 =
- msgbuf_factory(msgbuf_pool, CONN_ID, &name_3, FIVE_SECONDS);
+ msgbuf_create(msgbuf_pool, CONN_ID, &name_3, FIVE_SECONDS);
pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf_3, MSGBUF_ID_3);
size_t num_stale_entries = pkt_cache_get_num_cs_stale_entries(pkt_cache);
@@ -502,7 +537,7 @@ TEST_F(PacketCacheTest, GetMultipleStaleEntries) {
inet_pton(AF_INET6, name, (struct in6_addr *)&addr);
Name name;
name_CreateFromAddress(&name, AF_INET6, addr, IPV6_LEN);
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, i, &name, 0);
+ msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, i, &name, 0);
pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, i);
}
@@ -514,7 +549,7 @@ TEST_F(PacketCacheTest, GetMultipleStaleEntries) {
inet_pton(AF_INET6, name, (struct in6_addr *)&addr);
Name name;
name_CreateFromAddress(&name, AF_INET6, addr, IPV6_LEN);
- msgbuf_t *msgbuf = msgbuf_factory(msgbuf_pool, i, &name, FIVE_SECONDS);
+ msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, i, &name, FIVE_SECONDS);
pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, i);
}
@@ -522,3 +557,126 @@ TEST_F(PacketCacheTest, GetMultipleStaleEntries) {
size_t num_stale_entries = pkt_cache_get_num_cs_stale_entries(pkt_cache);
EXPECT_EQ(num_stale_entries, (size_t)NUM_STALES);
}
+
+TEST_F(PacketCacheTest, PerformanceDoubleLookup) {
+ Name tmp = get_name_from_prefix("b001::0");
+
+ auto elapsed_time_double = get_execution_time([&]() {
+ kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix();
+
+ // Add to hash table
+ for (int seq = 0; seq < N_OPS; seq++) {
+ name_SetSegment(&tmp, seq);
+ _add_suffix(prefix_to_suffixes, name_GetContentName(&tmp),
+ name_GetSegment(&tmp), name_GetSegment(&tmp));
+ }
+
+ // Read from hash table
+ int rc;
+ for (int seq = 0; seq < N_OPS; seq++) {
+ name_SetSegment(&tmp, seq);
+ _get_suffix(prefix_to_suffixes, name_GetContentName(&tmp), seq, &rc);
+ }
+
+ _prefix_map_free(prefix_to_suffixes);
+ });
+ std::cout << "Double lookup: " << elapsed_time_double << " ms\n";
+}
+
+TEST_F(PacketCacheTest, PerformanceCachedLookup) {
+ Name tmp = get_name_from_prefix("b001::0");
+
+ auto elapsed_time_single = get_execution_time([&]() {
+ kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix();
+ kh_pkt_cache_suffix_t *suffixes =
+ _get_suffixes(prefix_to_suffixes, name_GetContentName(&tmp));
+
+ // Add to hash table
+ for (int seq = 0; seq < N_OPS; seq++) {
+ name_SetSegment(&tmp, seq);
+ __add_suffix(suffixes, name_GetSegment(&tmp), name_GetSegment(&tmp));
+ }
+
+ // Read from hash table
+ int rc;
+ for (int seq = 0; seq < N_OPS; seq++) {
+ name_SetSegment(&tmp, seq);
+ __get_suffix(suffixes, name_GetSegment(&tmp), &rc);
+ }
+
+ _prefix_map_free(prefix_to_suffixes);
+ });
+ std::cout << "Cached lookup: " << elapsed_time_single << " ms\n";
+}
+
+TEST_F(PacketCacheTest, PerformanceCachedLookupRandom) {
+ Name tmp = get_name_from_prefix("b001::0");
+
+ // Prepare random sequence numbers
+ std::random_device rd;
+ std::mt19937 gen(rd());
+ uint32_t seqs[N_OPS];
+ for (int seq = 0; seq < N_OPS; seq++) seqs[seq] = seq;
+ std::shuffle(std::begin(seqs), std::end(seqs), gen);
+
+ auto elapsed_time_single_rand = get_execution_time([&]() {
+ kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix();
+ kh_pkt_cache_suffix_t *suffixes =
+ _get_suffixes(prefix_to_suffixes, name_GetContentName(&tmp));
+
+ // Add to hash table
+ for (int seq = 0; seq < N_OPS; seq++) {
+ name_SetSegment(&tmp, seqs[seq]);
+ __add_suffix(suffixes, name_GetSegment(&tmp), name_GetSegment(&tmp));
+ }
+
+ // Read from hash table
+ int rc;
+ for (int seq = 0; seq < N_OPS; seq++) {
+ name_SetSegment(&tmp, seqs[seq]);
+ __get_suffix(suffixes, name_GetSegment(&tmp), &rc);
+ }
+
+ _prefix_map_free(prefix_to_suffixes);
+ });
+ std::cout << "Cached lookup (rand): " << elapsed_time_single_rand << " ms\n";
+}
+
+TEST_F(PacketCacheTest, Clear) {
+ Name tmp_name1, tmp_name2;
+ cs_t *cs = pkt_cache_get_cs(pkt_cache);
+
+ // Create name and add to msgbuf pool
+ name_Copy(name, &tmp_name1);
+ name_SetSegment(&tmp_name1, 1);
+ msgbuf_t *tmp_msgbuf1 = msgbuf_create(msgbuf_pool, CONN_ID_2, &tmp_name1);
+
+ // Create (another) name and add to msgbuf pool
+ name_Copy(name, &tmp_name2);
+ name_SetSegment(&tmp_name2, 2);
+ msgbuf_t *tmp_msgbuf2 = msgbuf_create(msgbuf_pool, CONN_ID_2, &tmp_name2);
+
+ // Add to packet cache (2 entries in the CS, 1 in the PIT)
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID);
+ pkt_cache_add_to_pit(pkt_cache, tmp_msgbuf1, &tmp_name1);
+ pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, tmp_msgbuf2, MSGBUF_ID_2);
+
+ // Check stats (before clearing the packet cache)
+ ASSERT_EQ(pkt_cache_get_size(pkt_cache), 3u);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 2u);
+ ASSERT_EQ(cs->num_entries, 2u);
+ ASSERT_EQ(cs->stats.lru.countAdds, 2u);
+
+ // Clear packet cache (i.e. remove content packets from packet cache):
+ // PIT entry should still be there while CS entries are cleared
+ pkt_cache_cs_clear(pkt_cache);
+ cs = pkt_cache_get_cs(pkt_cache);
+
+ // Check stats (after clearing the packet cache)
+ ASSERT_EQ(pkt_cache_get_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u);
+ ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u);
+ ASSERT_EQ(cs->num_entries, 0u);
+ ASSERT_EQ(cs->stats.lru.countAdds, 0u);
+} \ No newline at end of file
diff --git a/hicn-light/src/hicn/test/test-pool.cc b/hicn-light/src/hicn/test/test-pool.cc
index c631415ca..8cd891d6a 100644
--- a/hicn-light/src/hicn/test/test-pool.cc
+++ b/hicn-light/src/hicn/test/test-pool.cc
@@ -25,7 +25,7 @@
extern "C" {
#define WITH_TESTS
-#include <hicn/base/pool.h>
+#include <hicn/util/pool.h>
}
/*
diff --git a/hicn-light/src/hicn/test/test-ring.cc b/hicn-light/src/hicn/test/test-ring.cc
index 51f1f5327..ab96d76c0 100644
--- a/hicn-light/src/hicn/test/test-ring.cc
+++ b/hicn-light/src/hicn/test/test-ring.cc
@@ -25,7 +25,7 @@
extern "C" {
#define WITH_TESTS
-#include <hicn/base/ring.h>
+#include <hicn/util/ring.h>
}
#define DEFAULT_SIZE 10UL
diff --git a/hicn-light/src/hicn/test/test-subscription.cc b/hicn-light/src/hicn/test/test-subscription.cc
index 18ef60c0d..f89254e67 100644
--- a/hicn-light/src/hicn/test/test-subscription.cc
+++ b/hicn-light/src/hicn/test/test-subscription.cc
@@ -6,7 +6,7 @@
extern "C" {
#include <hicn/core/subscription.h>
-#include <hicn/base/vector.h>
+#include <hicn/util/vector.h>
}
static inline unsigned CONN_ID = 1;
diff --git a/hicn-light/src/hicn/test/test-utils.h b/hicn-light/src/hicn/test/test-utils.h
new file mode 100644
index 000000000..577629584
--- /dev/null
+++ b/hicn-light/src/hicn/test/test-utils.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <vector>
+#include <thread>
+#include <numeric>
+
+static constexpr int N_RUNS = 100;
+
+// Utility function for time execution calculation
+template <typename F, typename... Args>
+double get_execution_time(F func, Args &&...args) {
+ std::vector<float> execution_times;
+
+ for (int i = 0; i < N_RUNS; i++) {
+ auto start = std::chrono::high_resolution_clock::now();
+ func(std::forward<Args>(args)...);
+ auto end = std::chrono::high_resolution_clock::now();
+
+ std::chrono::duration<double, std::milli> ms = end - start;
+ execution_times.emplace_back(ms.count());
+ }
+
+ // Calculate average
+ return std::reduce(execution_times.begin(), execution_times.end()) /
+ execution_times.size();
+} \ No newline at end of file
diff --git a/hicn-light/src/hicn/test/test-vector.cc b/hicn-light/src/hicn/test/test-vector.cc
index fb30a8228..dda71fd0c 100644
--- a/hicn-light/src/hicn/test/test-vector.cc
+++ b/hicn-light/src/hicn/test/test-vector.cc
@@ -15,26 +15,12 @@
#include <gtest/gtest.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-#include <netinet/in.h>
-
extern "C" {
-#define WITH_TESTS
-#include <hicn/base/vector.h>
+#include <hicn/util/vector.h>
}
-/*
- * TODO
- * - test max_size
- */
-
-#define DEFAULT_SIZE 10
-const size_t N_ELEMENTS = 5;
+static constexpr size_t DEFAULT_SIZE = 10;
+static constexpr size_t N_ELEMENTS = 5;
class VectorTest : public ::testing::Test {
protected:
@@ -44,58 +30,62 @@ class VectorTest : public ::testing::Test {
int *vector = NULL;
};
-/* TEST: Vector allocation and initialization */
-TEST_F(VectorTest, VectorAllocate) {
- /* Allocated size should be the next power of two */
+TEST_F(VectorTest, VectorAllocateAndResize) {
+ // Allocated size should be the next power of two
EXPECT_EQ(vector_get_alloc_size(vector), 16UL);
- /* Setting elements within the allocated size should not trigger a resize */
+ // Setting elements within the allocated size should not trigger a resize
vector_ensure_pos(vector, 15);
EXPECT_EQ(vector_get_alloc_size(vector), 16UL);
- /* Setting elements after should through */
+ // Setting elements after should through
vector_ensure_pos(vector, 16);
EXPECT_EQ(vector_get_alloc_size(vector), 32UL);
-
- /* Check that free indices and bitmaps are correctly updated */
}
TEST_F(VectorTest, VectorSize) {
- vector_push(vector, 109);
- int size = vector_len(vector);
- EXPECT_EQ(size, 1);
- vector_push(vector, 109);
- size = vector_len(vector);
- EXPECT_EQ(size, 2);
- vector_push(vector, 109);
- size = vector_len(vector);
- EXPECT_EQ(size, 3);
+ EXPECT_EQ(vector_len(vector), 0);
+
+ // Check size after pushing one element
+ vector_push(vector, 1);
+ EXPECT_EQ(vector_len(vector), 1);
+
+ // Check size after pushing additional elements
+ vector_push(vector, 2);
+ vector_push(vector, 3);
+ EXPECT_EQ(vector_len(vector), 3);
+
+ // Try adding multiple elements
+ const int n_elements_to_add = 5;
+ size_t expected_new_len = vector_len(vector) + n_elements_to_add;
+ for (int i = 0; i < n_elements_to_add; i++) vector_push(vector, i);
+ EXPECT_EQ(vector_len(vector), expected_new_len);
}
TEST_F(VectorTest, VectorCheckValue) {
+ // Add elements
vector_push(vector, 109);
vector_push(vector, 200);
- EXPECT_EQ(vector[0], 109);
- EXPECT_EQ(vector[1], 200);
-}
-
-TEST_F(VectorTest, VectorEnsurePos) {
- printf(" %p\n", vector);
- vector_ensure_pos(vector, 1025);
- for (int i = 0; i < 1025; i++) {
- // printf("i %d\n", i);
- // printf (" %p\n", vector);
- vector_push(vector, i);
- }
- int size = vector_len(vector);
- EXPECT_EQ(size, 1025);
+ EXPECT_EQ(vector_at(vector, 0), 109);
+ EXPECT_EQ(vector_at(vector, 1), 200);
+
+ // Update element
+ vector_set(vector, 1, 400);
+ EXPECT_EQ(vector_at(vector, 1), 400);
+
+ // Add at last available position
+ size_t prev_size = vector_len(vector);
+ vector_set(vector, vector_len(vector) - 1, 123);
+ EXPECT_EQ(vector_at(vector, vector_len(vector) - 1), 123);
+ EXPECT_EQ(prev_size, vector_len(vector)) << "Size should not have changed";
}
TEST_F(VectorTest, RemoveElement) {
// Populate vector
for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(vector, i);
EXPECT_EQ(vector_len(vector), N_ELEMENTS);
- for (size_t i = 0; i < vector_len(vector); i++) EXPECT_EQ(vector[i], (int)i);
+ for (size_t i = 0; i < vector_len(vector); i++)
+ EXPECT_EQ(vector_at(vector, i), (int)i);
// Remove element
int value_to_remove = 3;
@@ -104,15 +94,30 @@ TEST_F(VectorTest, RemoveElement) {
EXPECT_EQ(vector_len(vector), N_ELEMENTS - 1);
EXPECT_EQ(num_removed, 1);
for (size_t i = 0; i < vector_len(vector); i++)
- EXPECT_NE(vector[i], value_to_remove);
+ EXPECT_NE(vector_at(vector, i), value_to_remove);
+}
+
+TEST_F(VectorTest, RemoveNonExistingElement) {
+ // Push some initial values
+ vector_push(vector, 1);
+ vector_push(vector, 2);
+ vector_push(vector, 3);
+ EXPECT_EQ(vector_len(vector), 3);
+
+ // Remove non-existing element
+ int num_removed = vector_remove_unordered(vector, 5);
+ EXPECT_EQ(num_removed, 0);
+ size_t prev_size = vector_len(vector);
+ EXPECT_EQ(prev_size, vector_len(vector)) << "Size should not have changed";
}
TEST_F(VectorTest, RemoveDuplicatedElement) {
// Populate vector
for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(vector, i);
EXPECT_EQ(vector_len(vector), N_ELEMENTS);
- for (size_t i = 0; i < vector_len(vector); i++) EXPECT_EQ(vector[i], (int)i);
- vector[0] = 3; // Duplicate element
+ for (size_t i = 0; i < vector_len(vector); i++)
+ EXPECT_EQ(vector_at(vector, i), (int)i);
+ vector_set(vector, 0, 3); // Duplicate element
// Remove (duplicated) elements
int value_to_remove = 3;
@@ -121,7 +126,7 @@ TEST_F(VectorTest, RemoveDuplicatedElement) {
EXPECT_EQ(vector_len(vector), N_ELEMENTS - 2);
EXPECT_EQ(num_removed, 2);
for (size_t i = 0; i < vector_len(vector); i++)
- EXPECT_NE(vector[i], value_to_remove);
+ EXPECT_NE(vector_at(vector, i), value_to_remove);
}
TEST_F(VectorTest, Iterate) {
@@ -139,10 +144,89 @@ TEST_F(VectorTest, MultipleResize) {
for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(small_vector, i);
- for (size_t i = 0; i < N_ELEMENTS; i++) EXPECT_EQ(small_vector[i], (int)i);
+ for (size_t i = 0; i < N_ELEMENTS; i++)
+ EXPECT_EQ(vector_at(small_vector, i), (int)i);
EXPECT_EQ(vector_len(small_vector), 5UL);
EXPECT_EQ(vector_get_alloc_size(small_vector), 8UL);
vector_free(small_vector);
+}
+
+TEST_F(VectorTest, MaxSize) {
+ const int max_size = 4;
+
+ // Fill the vector until max size is reached
+ int *small_vector;
+ vector_init(small_vector, 2, max_size);
+ for (int i = 0; i < max_size; i++) vector_push(small_vector, i);
+
+ // Try expanding or appending elements should fail
+ int rc = vector_ensure_pos(small_vector, max_size);
+ EXPECT_EQ(rc, -1);
+ rc = vector_push(small_vector, 123);
+ EXPECT_EQ(rc, -1);
+
+ vector_free(small_vector);
+}
+
+TEST_F(VectorTest, Contains) {
+ // No elements
+ EXPECT_EQ(vector_contains(vector, 1), false);
+
+ // Push one element
+ vector_push(vector, 1);
+ EXPECT_EQ(vector_contains(vector, 1), true);
+
+ // Update element
+ vector_set(vector, 0, 2);
+ EXPECT_EQ(vector_contains(vector, 1), false);
+ EXPECT_EQ(vector_contains(vector, 2), true);
+}
+
+TEST_F(VectorTest, Remove) {
+ // Remove element at invalid position
+ int rc = vector_remove_at(vector, 2);
+ EXPECT_EQ(rc, -1); // Failure
+
+ // Push two elements and remove the second one
+ vector_push(vector, 1);
+ vector_push(vector, 2);
+ rc = vector_remove_at(vector, 1);
+ EXPECT_EQ(rc, 0); // Success
+ EXPECT_EQ(vector_len(vector), 1);
+
+ // Push another element: it should replace the previous one
+ vector_push(vector, 3);
+ EXPECT_EQ(vector_len(vector), 2);
+ EXPECT_EQ(vector_at(vector, 1), 3);
+}
+
+TEST_F(VectorTest, RemoveInTheMiddle) {
+ for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(vector, i);
+
+ // Remove element in central position
+ int rc = vector_remove_at(vector, 2);
+ EXPECT_EQ(rc, 0); // Success
+ EXPECT_EQ(vector_contains(vector, 2), false);
+ EXPECT_EQ(vector_len(vector), N_ELEMENTS - 1);
+
+ // Check if elements have been shifted (preserving the order)
+ int expected[] = {0, 1, 3, 4};
+ for (int i = 0; i < vector_len(vector); i++)
+ EXPECT_EQ(vector_at(vector, i), expected[i]);
+}
+
+TEST_F(VectorTest, Reset) {
+ vector_push(vector, 1);
+ vector_push(vector, 2);
+ EXPECT_EQ(vector_len(vector), 2);
+
+ vector_reset(vector);
+ EXPECT_EQ(vector_len(vector), 0);
+
+ vector_push(vector, 5);
+ EXPECT_EQ(vector_len(vector), 1);
+ EXPECT_EQ(vector_contains(vector, 5), true);
+ EXPECT_EQ(vector_at(vector, 0), 5);
} \ No newline at end of file
diff --git a/hicn-plugin/includes/vpp_plugins/hicn/error.h b/hicn-plugin/includes/vpp_plugins/hicn/error.h
index a8a941a79..af9f5da46 100644
--- a/hicn-plugin/includes/vpp_plugins/hicn/error.h
+++ b/hicn-plugin/includes/vpp_plugins/hicn/error.h
@@ -25,67 +25,69 @@
#define foreach_hicn_error \
_ (NONE, 0, "Ok") \
_ (UNSPECIFIED, -128, "Unspecified Error") \
- _ (FACE_NOT_FOUND, -129, "Face not found in Face table") \
- _ (FACE_NULL, -130, "Face null") \
- _ (FACE_IP_ADJ_NOT_FOUND, -131, "Ip adjacecny for face not found") \
- _ (FACE_HW_INT_NOT_FOUND, -132, "Hardware interface not found") \
- _ (FACE_NOMEM, -133, "Face table is full") \
- _ (FACE_NO_GLOBAL_IP, -134, "No global ip address for face") \
- _ (FACE_NOT_FOUND_IN_ENTRY, -135, "Face not found in entry") \
- _ (FACE_ALREADY_DELETED, -136, "Face alredy deleted") \
- _ (FACE_ALREADY_CREATED, -137, "Face alredy created") \
- _ (FWD_NOT_ENABLED, -138, "hICN forwarder not enabled") \
- _ (FWD_ALREADY_ENABLED, -139, "hICN forwarder alredy enabled") \
- _ (PARSER_UNSUPPORTED_PROTO, -140, "Unsupported protocol") \
- _ (PARSER_PKT_INVAL, -141, "Packet null") \
- _ (PIT_CONFIG_MINLT_OOB, -142, "Min lifetime ouf of bounds") \
- _ (PIT_CONFIG_MAXLT_OOB, -143, "Max lifetime ouf of bounds") \
- _ (PIT_CONFIG_MINMAXLT, -144, "Min lifetime grater than max lifetime") \
- _ (PIT_CONFIG_DFTLT_OOB, -145, "Default lifetime ouf of bounds") \
- _ (PIT_CONFIG_SIZE_OOB, -146, "Pit size ouf of bounds") \
- _ (CS_CONFIG_SIZE_OOB, -147, "CS size ouf of bounds") \
- _ (CS_CONFIG_RESERVED_OOB, -148, \
+ _ (FACE_NOT_FOUND, -1000, "Face not found in Face table") \
+ _ (FACE_NULL, -1001, "Face null") \
+ _ (FACE_IP_ADJ_NOT_FOUND, -1002, "Ip adjacecny for face not found") \
+ _ (FACE_HW_INT_NOT_FOUND, -1003, "Hardware interface not found") \
+ _ (FACE_NOMEM, -1004, "Face table is full") \
+ _ (FACE_NO_GLOBAL_IP, -1005, "No global ip address for face") \
+ _ (FACE_NOT_FOUND_IN_ENTRY, -1006, "Face not found in entry") \
+ _ (FACE_ALREADY_DELETED, -1007, "Face alredy deleted") \
+ _ (FACE_ALREADY_CREATED, -1008, "Face alredy created") \
+ _ (FWD_NOT_ENABLED, -2000, "hICN forwarder not enabled") \
+ _ (FWD_ALREADY_ENABLED, -2001, "hICN forwarder alredy enabled") \
+ _ (PARSER_UNSUPPORTED_PROTO, -3000, "Unsupported protocol") \
+ _ (PARSER_PKT_INVAL, -3001, "Packet null") \
+ _ (PARSER_MAPME_PACKET, -3002, "Packet is mapme") \
+ _ (PIT_CONFIG_MINLT_OOB, -4000, "Min lifetime ouf of bounds") \
+ _ (PIT_CONFIG_MAXLT_OOB, -4001, "Max lifetime ouf of bounds") \
+ _ (PIT_CONFIG_MINMAXLT, -4002, "Min lifetime grater than max lifetime") \
+ _ (PIT_CONFIG_DFTLT_OOB, -4003, "Default lifetime ouf of bounds") \
+ _ (PIT_CONFIG_SIZE_OOB, -4004, "Pit size ouf of bounds") \
+ _ (CS_CONFIG_SIZE_OOB, -5000, "CS size ouf of bounds") \
+ _ (CS_CONFIG_RESERVED_OOB, -5001, \
"Reseved CS must be between 0 and 100 (excluded)") \
- _ (DPO_CTX_NHOPS_NS, -149, "No space for additional next hop") \
- _ (DPO_CTX_NHOPS_EXISTS, -150, "Next hop already in the route") \
- _ (DPO_CTX_NOT_FOUND, -151, "Dpo context not found") \
- _ (DPO_MGR_ID_NOT_VALID, -152, "Dpo id for strategy and context not valid") \
- _ (HASHTB_HASH_NOT_FOUND, -153, "Hash not found in hash table") \
- _ (HASHTB_HASH_INVAL, -154, "Error while calculating the hash") \
- _ (HASHTB_NOMEM, -155, "Unable to allocate new buckets or nodes") \
- _ (HASHTB_INVAL, -156, "Invalid argument") \
- _ (HASHTB_KEY_INVAL, -157, "Invalid hashtb key") \
- _ (HASHTB_EXIST, -158, "Hash already in hashtable") \
- _ (ROUTE_INVAL, -159, "Invalid face id and weight") \
- _ (ROUTE_NO_LD, -160, "Expected load balance dpo") \
- _ (ROUTE_MLT_LD, -161, "Unexpected mulitple buckets in load balance dpo") \
- _ (ROUTE_NO_INSERT, -162, "Unable to insert a new FIB entry") \
- _ (ROUTE_DPO_NO_HICN, -163, "Dpo is not of type hICN") \
- _ (ROUTE_NOT_FOUND, -164, "Route not found in FIB") \
- _ (ROUTE_NOT_UPDATED, -165, "Unable to update route") \
- _ (ROUTE_ALREADY_EXISTS, -166, "Route already in FIB") \
- _ (CLI_INVAL, -167, "Invalid input") \
- _ (IPS_ADDR_TYPE_NONUNIFORM, -168, \
+ _ (DPO_CTX_NHOPS_NS, -6000, "No space for additional next hop") \
+ _ (DPO_CTX_NHOPS_EXISTS, -6001, "Next hop already in the route") \
+ _ (DPO_CTX_NOT_FOUND, -6002, "Dpo context not found") \
+ _ (DPO_MGR_ID_NOT_VALID, -6003, \
+ "Dpo id for strategy and context not valid") \
+ _ (HASHTB_HASH_NOT_FOUND, -7000, "Hash not found in hash table") \
+ _ (HASHTB_HASH_INVAL, -7001, "Error while calculating the hash") \
+ _ (HASHTB_NOMEM, -7002, "Unable to allocate new buckets or nodes") \
+ _ (HASHTB_INVAL, -7003, "Invalid argument") \
+ _ (HASHTB_KEY_INVAL, -7004, "Invalid hashtb key") \
+ _ (HASHTB_EXIST, -7005, "Hash already in hashtable") \
+ _ (ROUTE_INVAL, -8000, "Invalid face id and weight") \
+ _ (ROUTE_NO_LD, -8001, "Expected load balance dpo") \
+ _ (ROUTE_MLT_LD, -8002, "Unexpected mulitple buckets in load balance dpo") \
+ _ (ROUTE_NO_INSERT, -8003, "Unable to insert a new FIB entry") \
+ _ (ROUTE_DPO_NO_HICN, -8004, "Dpo is not of type hICN") \
+ _ (ROUTE_NOT_FOUND, -8005, "Route not found in FIB") \
+ _ (ROUTE_NOT_UPDATED, -8006, "Unable to update route") \
+ _ (ROUTE_ALREADY_EXISTS, -8007, "Route already in FIB") \
+ _ (CLI_INVAL, -9000, "Invalid input") \
+ _ (IPS_ADDR_TYPE_NONUNIFORM, -10000, \
"Src and dst addr have different ip types") \
- _ (FACE_TYPE_EXISTS, -169, "Face type already registered") \
- _ (NO_BUFFERS, -170, "No vlib_buffer available for packet cloning.") \
- _ (NOT_IMPLEMENTED, -171, "Function not yet implemented") \
- _ (IFACE_IP_ADJ_NOT_FOUND, -172, \
+ _ (FACE_TYPE_EXISTS, -11000, "Face type already registered") \
+ _ (NO_BUFFERS, -12000, "No vlib_buffer available for packet cloning.") \
+ _ (NOT_IMPLEMENTED, -13000, "Function not yet implemented") \
+ _ (IFACE_IP_ADJ_NOT_FOUND, -14000, \
"IP adjacency on incomplete face not available") \
- _ (APPFACE_ALREADY_ENABLED, -173, \
+ _ (APPFACE_ALREADY_ENABLED, -15000, \
"Application face already enabled on interface") \
- _ (APPFACE_FEATURE, -174, "Error while enabling app face feature") \
- _ (APPFACE_NOT_FOUND, -175, "Application face not found") \
- _ (APPFACE_PROD_PREFIX_NULL, -176, \
+ _ (APPFACE_FEATURE, -15001, "Error while enabling app face feature") \
+ _ (APPFACE_NOT_FOUND, -15002, "Application face not found") \
+ _ (APPFACE_PROD_PREFIX_NULL, -15003, \
"Prefix must not be null for producer face") \
- _ (STRATEGY_NH_NOT_FOUND, -177, "Next hop not found") \
- _ (MW_STRATEGY_SET, -178, "Error while setting weight for next hop") \
- _ (STRATEGY_NOT_FOUND, -179, "Strategy not found") \
- _ (UDP_TUNNEL_NOT_FOUND, -180, "Udp tunnel not found") \
- _ (UDP_TUNNEL_SRC_DST_TYPE, -181, \
+ _ (STRATEGY_NH_NOT_FOUND, -16000, "Next hop not found") \
+ _ (MW_STRATEGY_SET, -16001, "Error while setting weight for next hop") \
+ _ (STRATEGY_NOT_FOUND, -16002, "Strategy not found") \
+ _ (UDP_TUNNEL_NOT_FOUND, -17000, "Udp tunnel not found") \
+ _ (UDP_TUNNEL_SRC_DST_TYPE, -17001, \
"Src and dst addresses have different type (ipv4 and ipv6)") \
- _ (MAPME_NEXT_HOP_ADDED, -182, "Next hop added to mapme") \
- _ (MAPME_NEXT_HOP_NOT_ADDED, -183, "Next hop added to mapme")
+ _ (MAPME_NEXT_HOP_ADDED, -18000, "Next hop added to mapme") \
+ _ (MAPME_NEXT_HOP_NOT_ADDED, -18001, "Next hop added to mapme")
typedef enum
{
diff --git a/hicn-plugin/src/CMakeLists.txt b/hicn-plugin/src/CMakeLists.txt
index 2141ec596..e071b3b9d 100644
--- a/hicn-plugin/src/CMakeLists.txt
+++ b/hicn-plugin/src/CMakeLists.txt
@@ -59,6 +59,7 @@ set(HICN_PLUGIN_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_prod_node.c
${CMAKE_CURRENT_SOURCE_DIR}/faces/app/face_app_cli.c
${CMAKE_CURRENT_SOURCE_DIR}/pg.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/pg_node.c
${CMAKE_CURRENT_SOURCE_DIR}/strategies/dpo_mw.c
${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw.c
${CMAKE_CURRENT_SOURCE_DIR}/strategies/strategy_mw_cli.c
@@ -83,6 +84,7 @@ set(HICN_PLUGIN_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/pcs.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn_api.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_buffer_flags.h
${CMAKE_CURRENT_SOURCE_DIR}/state.h
${CMAKE_CURRENT_SOURCE_DIR}/infra.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn_msg_enum.h
@@ -99,6 +101,7 @@ set(HICN_PLUGIN_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/error.h
${CMAKE_CURRENT_SOURCE_DIR}/face_db.h
${CMAKE_CURRENT_SOURCE_DIR}/faces/face.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/faces/face_flags.h
${CMAKE_CURRENT_SOURCE_DIR}/faces/face_node.h
${CMAKE_CURRENT_SOURCE_DIR}/faces/iface_node.h
${CMAKE_CURRENT_SOURCE_DIR}/faces/inlines.h
diff --git a/hicn-plugin/src/cli.c b/hicn-plugin/src/cli.c
index cd45607ca..f743f6362 100644
--- a/hicn-plugin/src/cli.c
+++ b/hicn-plugin/src/cli.c
@@ -585,13 +585,15 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t *vm,
unformat_input_t *main_input,
vlib_cli_command_t *cmd)
{
- clib_error_t *cl_err;
- int rv = HICN_ERROR_NONE;
- hicnpg_server_main_t *pg_main = &hicnpg_server_main;
int payload_size = 1440;
u32 sw_if_index = ~0;
vnet_main_t *vnm = vnet_get_main ();
- fib_prefix_t *prefix = calloc (1, sizeof (fib_prefix_t));
+ fib_prefix_t prefix;
+ u32 hicnpg_server_index;
+ ip46_address_t locator;
+
+ locator.as_u64[0] = 0;
+ locator.as_u64[1] = 0;
/* Get a line of input. */
unformat_input_t _line_input, *line_input = &_line_input;
@@ -601,7 +603,7 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t *vm,
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (line_input, "name %U/%d", unformat_ip46_address,
- &prefix->fp_addr, IP46_TYPE_ANY, &prefix->fp_len))
+ &prefix.fp_addr, IP46_TYPE_ANY, &prefix.fp_len))
{
;
}
@@ -618,6 +620,11 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t *vm,
{
;
}
+ else if (unformat (line_input, "dst %U", unformat_ip46_address,
+ &locator, IP46_TYPE_ANY))
+ {
+ ;
+ }
else
{
return (clib_error_return (0, "Unknown input '%U'",
@@ -628,70 +635,45 @@ hicn_cli_pgen_server_set_command_fn (vlib_main_t *vm,
}
/* Attach our packet-gen node for ip4 udp local traffic */
- if ((prefix->fp_addr.ip6.as_u64[0] == (u64) 0 &&
- prefix->fp_addr.ip6.as_u64[1] == 0) ||
- payload_size == 0 || sw_if_index == ~0)
+ if ((prefix.fp_addr.ip6.as_u64[0] == (u64) 0 &&
+ prefix.fp_addr.ip6.as_u64[1] == 0) ||
+ payload_size == 0 || sw_if_index == ~0 ||
+ ip46_address_is_zero (&locator))
{
- return clib_error_return (0, "Error: must supply local port, payload "
+ return clib_error_return (0, "Error: must supply locator, payload "
"size and incoming hICN prefix");
}
// Remove bits that are out of the subnet
- if (ip46_address_is_ip4 (&prefix->fp_addr))
+ if (ip46_address_is_ip4 (&prefix.fp_addr))
{
ip4_address_t mask;
- ip4_preflen_to_mask (prefix->fp_len, &mask);
- prefix->fp_addr.ip4.as_u32 = prefix->fp_addr.ip4.as_u32 & mask.as_u32;
- prefix->fp_proto = FIB_PROTOCOL_IP4;
+ ip4_preflen_to_mask (prefix.fp_len, &mask);
+ prefix.fp_addr.ip4.as_u32 = prefix.fp_addr.ip4.as_u32 & mask.as_u32;
+ prefix.fp_proto = FIB_PROTOCOL_IP4;
}
else
{
ip6_address_t mask;
- ip6_preflen_to_mask (prefix->fp_len, &mask);
- prefix->fp_addr.ip6.as_u64[0] =
- prefix->fp_addr.ip6.as_u64[0] & mask.as_u64[0];
- prefix->fp_addr.ip6.as_u64[1] =
- prefix->fp_addr.ip6.as_u64[1] & mask.as_u64[1];
- prefix->fp_proto = FIB_PROTOCOL_IP6;
+ ip6_preflen_to_mask (prefix.fp_len, &mask);
+ prefix.fp_addr.ip6.as_u64[0] =
+ prefix.fp_addr.ip6.as_u64[0] & mask.as_u64[0];
+ prefix.fp_addr.ip6.as_u64[1] =
+ prefix.fp_addr.ip6.as_u64[1] & mask.as_u64[1];
+ prefix.fp_proto = FIB_PROTOCOL_IP6;
}
- /* Allocate the buffer with the actual content payload TLV */
- int n_buf = vlib_buffer_alloc (vm, &pg_main->pgen_svr_buffer_idx, 1);
-
- if (n_buf == 0)
+ fib_protocol_t dest_proto =
+ ip46_address_is_ip4 (&locator) ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
+ if (prefix.fp_proto != dest_proto)
{
- return (clib_error_return (0, "Impossible to allocate paylod buffer."));
+ return clib_error_return (0, "Error: prefix and locator must be of the "
+ "same protocol");
}
- vlib_buffer_t *rb = NULL;
- rb = vlib_get_buffer (vm, pg_main->pgen_svr_buffer_idx);
-
- pg_main->pgen_srv_hicn_name = prefix;
-
- /* Initialize the buffer data with zeros */
- memset (rb->data, 0, payload_size);
- rb->current_length = payload_size;
-
- vnet_feature_enable_disable ("ip4-unicast", "hicnpg-server", sw_if_index, 1,
- 0, 0);
- vnet_feature_enable_disable ("ip6-unicast", "hicnpg-server", sw_if_index, 1,
- 0, 0);
-
- switch (rv)
- {
- case 0:
- cl_err = 0;
- break;
-
- case VNET_API_ERROR_UNIMPLEMENTED:
- cl_err = clib_error_return (0, "Unimplemented, NYI");
- break;
-
- default:
- cl_err = clib_error_return (0, "hicn pgen server returned %d", rv);
- }
-
- return cl_err;
+ // Create hicnpg_server
+ return hicnpg_server_add_and_lock (&prefix, &hicnpg_server_index, &locator,
+ payload_size);
}
static clib_error_t *
@@ -855,7 +837,7 @@ VLIB_CLI_COMMAND (hicn_cli_pgen_client_set_command, static) = {
VLIB_CLI_COMMAND (hicn_cli_pgen_server_set_command, static) = {
.path = "hicn pgen server",
.short_help = "hicn pgen server name <prefix> intfc <interest in-interface> "
- "size <payload_size>",
+ "dst <ip_address> size <payload_size>",
.long_help = "Run hicn in packet-gen server mode\n",
.function = hicn_cli_pgen_server_set_command_fn,
};
diff --git a/hicn-plugin/src/data_fwd_node.c b/hicn-plugin/src/data_fwd_node.c
index 6acb5915b..a3f1a592f 100644
--- a/hicn-plugin/src/data_fwd_node.c
+++ b/hicn-plugin/src/data_fwd_node.c
@@ -91,7 +91,6 @@ hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
u16 namelen;
u32 bi0;
u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP;
- hicn_name_t name;
hicn_header_t *hicn0;
hicn_buffer_t *hicnb0;
hicn_hash_node_t *node0;
@@ -124,15 +123,15 @@ hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
/* Get hicn buffer and state */
hicnb0 = hicn_get_buffer (b0);
+ hicn0 = (hicn_header_t *) (vlib_buffer_get_current (b0));
hicn_get_internal_state (hicnb0, pitcs, &node0, &strategy_vft0,
&dpo_vft0, &dpo_ctx_id0, &hash_entry0);
- ret = hicn_data_parse_pkt (b0, &name, &namelen, &hicn0, &isv6);
+ hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen);
+ isv6 = hicn_buffer_is_v6 (b0);
pitp = hicn_pit_get_data (node0);
- nameptr = (u8 *) (&name);
if (PREDICT_FALSE (
- ret != HICN_ERROR_NONE ||
!hicn_node_compare (nameptr, namelen, node0) ||
(hash_entry0->he_flags & HICN_HASH_ENTRY_FLAG_CS_ENTRY)))
{
@@ -182,7 +181,7 @@ hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
{
hicn_data_fwd_trace_t *t =
vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = HICN_PKT_TYPE_CONTENT;
+ t->pkt_type = HICN_PACKET_TYPE_DATA;
t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
t->next_index = next0;
clib_memcpy (t->packet_data, vlib_buffer_get_current (b0),
@@ -442,7 +441,7 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp,
{
hicn_data_fwd_trace_t *t =
vlib_add_trace (vm, node, h0, sizeof (*t));
- t->pkt_type = HICN_PKT_TYPE_CONTENT;
+ t->pkt_type = HICN_PACKET_TYPE_DATA;
t->sw_if_index = vnet_buffer (h0)->sw_if_index[VLIB_RX];
t->next_index = next0;
clib_memcpy (t->packet_data, vlib_buffer_get_current (h0),
@@ -453,7 +452,7 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp,
{
hicn_data_fwd_trace_t *t =
vlib_add_trace (vm, node, h1, sizeof (*t));
- t->pkt_type = HICN_PKT_TYPE_CONTENT;
+ t->pkt_type = HICN_PACKET_TYPE_DATA;
t->sw_if_index = vnet_buffer (h1)->sw_if_index[VLIB_RX];
t->next_index = next1;
clib_memcpy (t->packet_data, vlib_buffer_get_current (h1),
@@ -491,7 +490,7 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp,
{
hicn_data_fwd_trace_t *t =
vlib_add_trace (vm, node, h0, sizeof (*t));
- t->pkt_type = HICN_PKT_TYPE_CONTENT;
+ t->pkt_type = HICN_PACKET_TYPE_DATA;
t->sw_if_index = vnet_buffer (h0)->sw_if_index[VLIB_RX];
t->next_index = next0;
clib_memcpy (t->packet_data, vlib_buffer_get_current (h0),
@@ -607,4 +606,4 @@ VLIB_REGISTER_NODE(hicn_data_fwd_node) =
* fd.io coding-style-patch-verification: ON
*
* Local Variables: eval: (c-set-style "gnu") End:
- */
+ */ \ No newline at end of file
diff --git a/hicn-plugin/src/data_input_node.c b/hicn-plugin/src/data_input_node.c
index 46fda1080..65bba7b1b 100644
--- a/hicn-plugin/src/data_input_node.c
+++ b/hicn-plugin/src/data_input_node.c
@@ -80,6 +80,7 @@ hicn_data_input_set_adj_index (vlib_buffer_t *b,
const ip46_address_t *dst_addr,
const hicn_dpo_ctx_t *dpo_ctx)
{
+ CLIB_UNUSED (u8 set) = 0;
for (u8 pos = 0; pos < dpo_ctx->entry_count; pos++)
{
hicn_face_t *face = hicn_dpoi_get_from_idx (dpo_ctx->next_hops[pos]);
@@ -87,9 +88,12 @@ hicn_data_input_set_adj_index (vlib_buffer_t *b,
if (ip46_address_cmp (&(face->nat_addr), dst_addr) == 0)
{
vnet_buffer (b)->ip.adj_index[VLIB_RX] = face->dpo.dpoi_index;
+ set = 1;
break;
}
}
+
+ ASSERT (set == 1);
}
static uword
@@ -147,7 +151,7 @@ hicn_data_input_ip6_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
src_addr1 = &ip1->src_address;
ip46_address_set_ip6 (&dst_addr0, &ip0->dst_address);
- ip46_address_set_ip6 (&dst_addr0, &ip1->dst_address);
+ ip46_address_set_ip6 (&dst_addr1, &ip1->dst_address);
ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, p0);
ip_lookup_set_buffer_fib_index (im->fib_index_by_sw_if_index, p1);
@@ -701,4 +705,4 @@ VNET_FEATURE_INIT (hicn_data_input_ip4_arc, static) = {
.arc_name = "ip4-local",
.node_name = "hicn-data-input-ip4",
.runs_before = VNET_FEATURES ("ip4-local-end-of-arc"),
-};
+}; \ No newline at end of file
diff --git a/hicn-plugin/src/data_pcslookup_node.c b/hicn-plugin/src/data_pcslookup_node.c
index 69278c306..95db66f54 100644
--- a/hicn-plugin/src/data_pcslookup_node.c
+++ b/hicn-plugin/src/data_pcslookup_node.c
@@ -63,17 +63,13 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
while (n_left_from > 0 && n_left_to_next > 0)
{
vlib_buffer_t *b0;
- u8 isv6;
u8 *nameptr;
u16 namelen;
u32 bi0;
u32 next0 = HICN_DATA_PCSLOOKUP_NEXT_ERROR_DROP;
u64 name_hash = 0;
- hicn_name_t name;
- hicn_header_t *hicn0 = NULL;
u32 node_id0 = 0;
index_t dpo_ctx_id0 = 0;
- int ret0;
u8 vft_id0 = 0;
u8 is_cs0;
u8 hash_entry_id = 0;
@@ -104,13 +100,11 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
/* Incr packet counter */
stats.pkts_processed += 1;
- ret0 = hicn_data_parse_pkt (b0, &name, &namelen, &hicn0, &isv6);
- nameptr = (u8 *) (&name);
+ hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen);
if (PREDICT_TRUE (
- ret0 == HICN_ERROR_NONE &&
hicn_hashtb_fullhash (nameptr, namelen, &name_hash) ==
- HICN_ERROR_NONE))
+ HICN_ERROR_NONE))
{
int res = hicn_hashtb_lookup_node (
rt->pitcs->pcs_table, nameptr, namelen, name_hash,
@@ -154,7 +148,7 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
{
hicn_data_pcslookup_trace_t *t =
vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = HICN_PKT_TYPE_CONTENT;
+ t->pkt_type = HICN_PACKET_TYPE_DATA;
t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
t->next_index = next0;
}
@@ -216,4 +210,4 @@ VLIB_REGISTER_NODE(hicn_data_pcslookup_node) =
* fd.io coding-style-patch-verification: ON
*
* Local Variables: eval: (c-set-style "gnu") End:
- */
+ */ \ No newline at end of file
diff --git a/hicn-plugin/src/faces/app/face_prod_node.c b/hicn-plugin/src/faces/app/face_prod_node.c
index 5d2b54040..e3241e477 100644
--- a/hicn-plugin/src/faces/app/face_prod_node.c
+++ b/hicn-plugin/src/faces/app/face_prod_node.c
@@ -42,12 +42,12 @@ typedef struct
{
u32 next_index;
u32 sw_if_index;
+ hicn_error_t error;
} hicn_face_prod_input_trace_t;
typedef enum
{
- HICN_FACE_PROD_NEXT_DATA_IP4,
- HICN_FACE_PROD_NEXT_DATA_IP6,
+ HICN_FACE_PROD_NEXT_PCS,
HICN_FACE_PROD_NEXT_ERROR_DROP,
HICN_FACE_PROD_N_NEXT,
} hicn_face_prod_next_t;
@@ -65,11 +65,14 @@ format_face_prod_input_trace (u8 *s, va_list *args)
s = format (s, "prod-face: sw_if_index %d next-index %d", t->sw_if_index,
t->next_index);
+
+ if (t->error != HICN_ERROR_NONE)
+ s = format (s, " error %s", get_error_string (t->error));
return s;
}
static_always_inline int
-match_ip4_name (u32 *name, fib_prefix_t *prefix)
+match_ip4_name (u32 *name, const fib_prefix_t *prefix)
{
u32 xor = 0;
@@ -79,7 +82,7 @@ match_ip4_name (u32 *name, fib_prefix_t *prefix)
}
static_always_inline int
-match_ip6_name (u8 *name, fib_prefix_t *prefix)
+match_ip6_name (u8 *name, const fib_prefix_t *prefix)
{
union
{
@@ -96,24 +99,42 @@ match_ip6_name (u8 *name, fib_prefix_t *prefix)
}
static_always_inline u32
-hicn_face_prod_next_from_data_hdr (vlib_node_runtime_t *node, vlib_buffer_t *b,
- fib_prefix_t *prefix)
+hicn_face_prod_next_from_data_hdr (vlib_buffer_t *b)
{
- u8 *ptr = vlib_buffer_get_current (b);
- u8 v = *ptr & 0xf0;
+ u8 is_v6;
int match_res = 1;
+ int ret = 0;
+ hicn_name_t *name;
+ hicn_face_prod_state_t *prod_face = NULL;
+
+ // 1 - ensure the packet is hicn and its format is correct
+ ret = hicn_data_parse_pkt (b);
+ if (PREDICT_FALSE (ret))
+ {
+ return HICN_FACE_PROD_NEXT_ERROR_DROP;
+ }
- if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr)))
+ // 2 - make sure the packet refers to a valid producer app state and
+ // retrieve app state information
+ prod_face = &face_state_vec[vnet_buffer (b)->sw_if_index[VLIB_RX]];
+ vnet_buffer (b)->ip.adj_index[VLIB_RX] = prod_face->adj_index;
+
+ // 3 - make sure the address in the packet belongs to the producer prefix
+ // of this face
+ const fib_prefix_t *prefix = &prod_face->prefix;
+ is_v6 = hicn_buffer_is_v6 (b);
+ name = &hicn_get_buffer (b)->name;
+ if (PREDICT_TRUE (!is_v6 && ip46_address_is_ip4 (&prefix->fp_addr)))
{
- match_res = match_ip4_name ((u32 *) &(ptr[12]), prefix);
+ match_res = match_ip4_name (&name->prefix.ip4.as_u32, prefix);
}
- else if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr)))
+ else if (PREDICT_TRUE (is_v6 && !ip46_address_is_ip4 (&prefix->fp_addr)))
{
- match_res = match_ip6_name (&(ptr[8]), prefix);
+ match_res = match_ip6_name (name->prefix.ip6.as_u8, prefix);
}
- return match_res ? HICN_FACE_PROD_NEXT_DATA_IP4 + (v == 0x60) :
- HICN_FACE_PROD_NEXT_ERROR_DROP;
+ // 4 - if match found, forward data to next hicn node
+ return match_res ? HICN_FACE_PROD_NEXT_PCS : HICN_FACE_PROD_NEXT_ERROR_DROP;
}
static_always_inline void
@@ -137,6 +158,7 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
u32 n_left_from, *from, *to_next;
hicn_face_prod_next_t next_index;
vl_api_hicn_api_node_stats_get_reply_t stats = { 0 };
+ u32 thread_index = vm->thread_index;
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
@@ -152,22 +174,28 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_buffer_t *b0, *b1, *b2, *b3;
hicn_buffer_t *hicnb0, *hicnb1, *hicnb2, *hicnb3;
u32 bi0, bi1, bi2, bi3;
- hicn_face_prod_state_t *prod_face0 = NULL;
- hicn_face_prod_state_t *prod_face1 = NULL;
- hicn_face_prod_state_t *prod_face2 = NULL;
- hicn_face_prod_state_t *prod_face3 = NULL;
u32 next0, next1, next2, next3;
+ // Prefetch next iteration
{
vlib_buffer_t *b4, *b5, *b6, *b7;
b4 = vlib_get_buffer (vm, from[4]);
b5 = vlib_get_buffer (vm, from[5]);
b6 = vlib_get_buffer (vm, from[6]);
b7 = vlib_get_buffer (vm, from[7]);
- CLIB_PREFETCH (b4, CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (b5, CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (b6, CLIB_CACHE_LINE_BYTES, STORE);
- CLIB_PREFETCH (b7, CLIB_CACHE_LINE_BYTES, STORE);
+ CLIB_PREFETCH (b4, 2 * CLIB_CACHE_LINE_BYTES, WRITE);
+ CLIB_PREFETCH (b5, 2 * CLIB_CACHE_LINE_BYTES, WRITE);
+ CLIB_PREFETCH (b6, 2 * CLIB_CACHE_LINE_BYTES, WRITE);
+ CLIB_PREFETCH (b7, 2 * CLIB_CACHE_LINE_BYTES, WRITE);
+
+ CLIB_PREFETCH (vlib_buffer_get_current (b4),
+ 2 * CLIB_CACHE_LINE_BYTES, WRITE);
+ CLIB_PREFETCH (vlib_buffer_get_current (b5),
+ 2 * CLIB_CACHE_LINE_BYTES, WRITE);
+ CLIB_PREFETCH (vlib_buffer_get_current (b6),
+ 2 * CLIB_CACHE_LINE_BYTES, WRITE);
+ CLIB_PREFETCH (vlib_buffer_get_current (b7),
+ 2 * CLIB_CACHE_LINE_BYTES, WRITE);
}
bi0 = from[0];
@@ -200,31 +228,39 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hicnb2->flags = HICN_FACE_FLAGS_DEFAULT;
hicnb3->flags = HICN_FACE_FLAGS_DEFAULT;
- prod_face0 = &face_state_vec[vnet_buffer (b0)->sw_if_index[VLIB_RX]];
- prod_face1 = &face_state_vec[vnet_buffer (b1)->sw_if_index[VLIB_RX]];
- prod_face2 = &face_state_vec[vnet_buffer (b2)->sw_if_index[VLIB_RX]];
- prod_face3 = &face_state_vec[vnet_buffer (b3)->sw_if_index[VLIB_RX]];
-
- vnet_buffer (b0)->ip.adj_index[VLIB_RX] =
- face_state_vec[vnet_buffer (b0)->sw_if_index[VLIB_RX]].adj_index;
- vnet_buffer (b1)->ip.adj_index[VLIB_RX] =
- face_state_vec[vnet_buffer (b1)->sw_if_index[VLIB_RX]].adj_index;
- vnet_buffer (b2)->ip.adj_index[VLIB_RX] =
- face_state_vec[vnet_buffer (b2)->sw_if_index[VLIB_RX]].adj_index;
- vnet_buffer (b3)->ip.adj_index[VLIB_RX] =
- face_state_vec[vnet_buffer (b3)->sw_if_index[VLIB_RX]].adj_index;
-
- next0 =
- hicn_face_prod_next_from_data_hdr (node, b0, &prod_face0->prefix);
- next1 =
- hicn_face_prod_next_from_data_hdr (node, b1, &prod_face1->prefix);
- next2 =
- hicn_face_prod_next_from_data_hdr (node, b2, &prod_face2->prefix);
- next3 =
- hicn_face_prod_next_from_data_hdr (node, b3, &prod_face3->prefix);
+ // parse packets and get next node
+ next0 = hicn_face_prod_next_from_data_hdr (b0);
+ next1 = hicn_face_prod_next_from_data_hdr (b1);
+ next2 = hicn_face_prod_next_from_data_hdr (b2);
+ next3 = hicn_face_prod_next_from_data_hdr (b3);
stats.pkts_data_count += 4;
- /* trace */
+ // counters
+ vlib_increment_combined_counter (
+ &counters[hicnb0->face_id * HICN_N_COUNTER], thread_index,
+ HICN_FACE_COUNTERS_DATA_RX, 1,
+ vlib_buffer_length_in_chain (vm, b0));
+ stats.pkts_data_count += 1;
+
+ vlib_increment_combined_counter (
+ &counters[hicnb1->face_id * HICN_N_COUNTER], thread_index,
+ HICN_FACE_COUNTERS_DATA_RX, 1,
+ vlib_buffer_length_in_chain (vm, b0));
+ stats.pkts_data_count += 1;
+
+ vlib_increment_combined_counter (
+ &counters[hicnb2->face_id * HICN_N_COUNTER], thread_index,
+ HICN_FACE_COUNTERS_DATA_RX, 1,
+ vlib_buffer_length_in_chain (vm, b0));
+ stats.pkts_data_count += 1;
+
+ vlib_increment_combined_counter (
+ &counters[hicnb3->face_id * HICN_N_COUNTER], thread_index,
+ HICN_FACE_COUNTERS_DATA_RX, 1,
+ vlib_buffer_length_in_chain (vm, b0));
+ stats.pkts_data_count += 1;
+
+ // trace
hicn_face_prod_trace_buffer (
vm, node, vnet_buffer (b0)->sw_if_index[VLIB_RX], b0, next0);
hicn_face_prod_trace_buffer (
@@ -234,7 +270,7 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hicn_face_prod_trace_buffer (
vm, node, vnet_buffer (b3)->sw_if_index[VLIB_RX], b3, next3);
- /* enqueue */
+ // enqueue
vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next,
n_left_to_next, bi0, bi1, bi2, bi3,
next0, next1, next2, next3);
@@ -246,8 +282,7 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
{
vlib_buffer_t *b0;
hicn_buffer_t *hicnb0;
- u32 bi0, swif;
- hicn_face_prod_state_t *prod_face = NULL;
+ u32 bi0;
u32 next0;
if (n_left_from > 1)
@@ -267,15 +302,17 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
b0 = vlib_get_buffer (vm, bi0);
hicnb0 = hicn_get_buffer (b0);
hicnb0->flags = HICN_FACE_FLAGS_DEFAULT;
- swif = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- prod_face = &face_state_vec[swif];
- next0 =
- hicn_face_prod_next_from_data_hdr (node, b0, &prod_face->prefix);
- vnet_buffer (b0)->ip.adj_index[VLIB_RX] =
- face_state_vec[swif].adj_index;
+ next0 = hicn_face_prod_next_from_data_hdr (b0);
stats.pkts_data_count++;
+ // counters
+ vlib_increment_combined_counter (
+ &counters[hicnb0->face_id * HICN_N_COUNTER], thread_index,
+ HICN_FACE_COUNTERS_DATA_RX, 1,
+ vlib_buffer_length_in_chain (vm, b0));
+ stats.pkts_data_count += 1;
+
/* trace */
hicn_face_prod_trace_buffer (
vm, node, vnet_buffer (b0)->sw_if_index[VLIB_RX], b0, next0);
@@ -310,8 +347,7 @@ VLIB_REGISTER_NODE(hicn_face_prod_input_node) =
.n_next_nodes = HICN_FACE_PROD_N_NEXT,
.next_nodes =
{
- [HICN_FACE_PROD_NEXT_DATA_IP4] = "hicn4-face-input",
- [HICN_FACE_PROD_NEXT_DATA_IP6] = "hicn6-face-input",
+ [HICN_FACE_PROD_NEXT_PCS] = "hicn-data-pcslookup",
[HICN_FACE_PROD_NEXT_ERROR_DROP] = "error-drop",
},
};
@@ -320,4 +356,4 @@ VLIB_REGISTER_NODE(hicn_face_prod_input_node) =
* fd.io coding-style-patch-verification: ON
*
* Local Variables: eval: (c-set-style "gnu") End:
- */
+ */ \ No newline at end of file
diff --git a/hicn-plugin/src/faces/face.c b/hicn-plugin/src/faces/face.c
index 854fd81d3..4ee1c283f 100644
--- a/hicn-plugin/src/faces/face.c
+++ b/hicn-plugin/src/faces/face.c
@@ -62,16 +62,12 @@ mhash_t hicn_face_hashtb;
const static char *const hicn_face6_nodes[] = {
"hicn6-face-output", // this is the name you give your node in
// VLIB_REGISTER_NODE
- "hicn6-iface-output", // this is the name you give your node in
- // VLIB_REGISTER_NODE
NULL,
};
const static char *const hicn_face4_nodes[] = {
"hicn4-face-output", // this is the name you give your node in
// VLIB_REGISTER_NODE
- "hicn4-iface-output", // this is the name you give your node in
- // VLIB_REGISTER_NODE
NULL,
};
@@ -304,7 +300,7 @@ hicn_iface_to_face (hicn_face_t *face, const dpo_id_t *dpo)
*/
int
hicn_face_add (const dpo_id_t *dpo_nh, ip46_address_t *nat_address, int sw_if,
- hicn_face_id_t *pfaceid, u8 is_app_prod)
+ hicn_face_id_t *pfaceid)
{
hicn_face_flags_t flags = (hicn_face_flags_t) 0;
diff --git a/hicn-plugin/src/faces/face.h b/hicn-plugin/src/faces/face.h
index 39505c942..e4b759bec 100644
--- a/hicn-plugin/src/faces/face.h
+++ b/hicn-plugin/src/faces/face.h
@@ -27,6 +27,8 @@
#include <vpp_plugins/hicn/error.h>
+#include "face_flags.h"
+#include "../hicn_buffer_flags.h"
#include "../udp_tunnels/udp_tunnel.h"
#include "../hicn_logging.h"
@@ -117,40 +119,8 @@ typedef struct __attribute__ ((packed)) hicn_face_s
/* Pool of faces */
extern hicn_face_t *hicn_dpoi_face_pool;
-/* Flags */
-/* A face is complete and it stores all the information. A iface lacks of the
- adj index, therefore sending a packet through a iface require a lookup in
- the FIB. */
-#define HICN_FACE_FLAGS_DEFAULT 0x00
-#define HICN_FACE_FLAGS_FACE 0x01
-#define HICN_FACE_FLAGS_IFACE 0x02
-#define HICN_FACE_FLAGS_APPFACE_PROD \
- 0x04 /* Currently only IP face can be appface */
-#define HICN_FACE_FLAGS_APPFACE_CONS \
- 0x08 /* Currently only IP face can be appface */
-#define HICN_FACE_FLAGS_DELETED 0x10
-#define HICN_FACE_FLAGS_UDP 0x20
-
#define HICN_FACE_NULL (hicn_face_id_t) ~0
-#define HICN_FACE_FLAGS_APPFACE_PROD_BIT 2
-#define HICN_FACE_FLAGS_APPFACE_CONS_BIT 3
-
-#define HICN_BUFFER_FLAGS_DEFAULT 0x00
-#define HICN_BUFFER_FLAGS_NEW_FACE 0x02
-#define HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL 0x04
-#define HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL 0x08
-
-STATIC_ASSERT ((1 << HICN_FACE_FLAGS_APPFACE_PROD_BIT) ==
- HICN_FACE_FLAGS_APPFACE_PROD,
- "HICN_FACE_FLAGS_APPFACE_PROD_BIT and "
- "HICN_FACE_FLAGS_APPFACE_PROD must correspond");
-
-STATIC_ASSERT ((1 << HICN_FACE_FLAGS_APPFACE_CONS_BIT) ==
- HICN_FACE_FLAGS_APPFACE_CONS,
- "HICN_FACE_FLAGS_APPFACE_CONS_BIT and "
- "HICN_FACE_FLAGS_APPFACE_CONS must correspond");
-
/**
* @brief Definition of the virtual functin table for an hICN FACE DPO.
*/
@@ -484,7 +454,7 @@ hicn_face_get_with_dpo (const ip46_address_t *addr, u32 sw_if,
* reachable ip address, otherwise HICN_ERROR_NONE
*/
int hicn_face_add (const dpo_id_t *dpo_nh, ip46_address_t *nat_address,
- int sw_if, hicn_face_id_t *pfaceid, u8 is_app_prod);
+ int sw_if, hicn_face_id_t *pfaceid);
/**
* @brief Create a new incomplete face ip. (Meant to be used by the data plane)
@@ -497,7 +467,7 @@ int hicn_face_add (const dpo_id_t *dpo_nh, ip46_address_t *nat_address,
* reachable ip address, otherwise HICN_ERROR_NONE
*/
always_inline void
-hicn_iface_add (ip46_address_t *nat_address, int sw_if,
+hicn_iface_add (const ip46_address_t *nat_address, int sw_if,
hicn_face_id_t *pfaceid, u32 adj_index, u8 flags)
{
hicn_face_t *face;
@@ -615,7 +585,6 @@ hicn_face_ip4_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
*hicnb_flags |= HICN_BUFFER_FLAGS_NEW_FACE;
*index = idx;
- return ret;
}
else
{
@@ -623,15 +592,10 @@ hicn_face_ip4_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
hicn_face_id_t face_id = hicn_dpoi_get_index (face);
hicn_face_unlock_with_id (face_id);
ret = HICN_ERROR_FACE_ALREADY_CREATED;
+ *index = hicn_dpoi_get_index (face);
+ *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
}
- /* Code replicated on purpose */
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
- *hicnb_flags |= (face->flags & HICN_FACE_FLAGS_APPFACE_PROD) >>
- HICN_FACE_FLAGS_APPFACE_PROD_BIT;
-
- *index = hicn_dpoi_get_index (face);
-
return ret;
}
@@ -676,7 +640,7 @@ hicn_face_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
/*All (complete) faces are indexed by remote addess as well */
/* if the face exists, it adds a lock */
- hicn_face_t *face = hicn_face_get ((ip46_address_t *) nat_addr, sw_if,
+ hicn_face_t *face = hicn_face_get ((const ip46_address_t *) nat_addr, sw_if,
&hicn_face_hashtb, adj_index);
if (face == NULL)
@@ -684,8 +648,8 @@ hicn_face_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
hicn_face_id_t idx;
u8 face_flags = 0;
- hicn_iface_add ((ip46_address_t *) nat_addr, sw_if, &idx, adj_index,
- face_flags);
+ hicn_iface_add ((const ip46_address_t *) nat_addr, sw_if, &idx,
+ adj_index, face_flags);
face = hicn_dpoi_get_from_idx (idx);
@@ -712,12 +676,8 @@ hicn_face_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
adj_nbr_walk (face->sw_if, FIB_PROTOCOL_IP6, hicn6_iface_adj_walk_cb,
face);
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
- *hicnb_flags |= HICN_BUFFER_FLAGS_NEW_FACE;
-
+ *hicnb_flags = HICN_BUFFER_FLAGS_NEW_FACE;
*index = idx;
-
- return ret;
}
else
{
@@ -725,15 +685,10 @@ hicn_face_ip6_add_and_lock (hicn_face_id_t *index, u8 *hicnb_flags,
hicn_face_id_t face_id = hicn_dpoi_get_index (face);
hicn_face_unlock_with_id (face_id);
ret = HICN_ERROR_FACE_ALREADY_CREATED;
+ *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
+ *index = hicn_dpoi_get_index (face);
}
- /* Code replicated on purpose */
- *hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
- *hicnb_flags |= (face->flags & HICN_FACE_FLAGS_APPFACE_PROD) >>
- HICN_FACE_FLAGS_APPFACE_PROD_BIT;
-
- *index = hicn_dpoi_get_index (face);
-
return ret;
}
diff --git a/hicn-plugin/src/faces/face_flags.h b/hicn-plugin/src/faces/face_flags.h
new file mode 100644
index 000000000..61dee5465
--- /dev/null
+++ b/hicn-plugin/src/faces/face_flags.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HICN_FACE_FLAGS_H__
+#define __HICN_FACE_FLAGS_H__
+
+/* Flags */
+/* A face is complete and it stores all the information. A iface lacks of the
+ adj index, therefore sending a packet through a iface require a lookup in
+ the FIB. */
+#define foreach_face_flag \
+ _ (0, FACE, "face") \
+ _ (1, IFACE, "iface") \
+ _ (2, APPFACE_PROD, "face is consumer face") \
+ _ (3, APPFACE_CONS, "face is consumer face") \
+ _ (4, DELETED, "face is deleted") \
+ _ (5, UDP, "face is udp")
+
+enum
+{
+ HICN_FACE_FLAGS_DEFAULT = 0,
+#define _(a, b, c) HICN_FACE_FLAGS_##b = (1 << a),
+ foreach_face_flag
+#undef _
+};
+
+#endif /* __HICN_FACE_FLAGS_H__ */ \ No newline at end of file
diff --git a/hicn-plugin/src/faces/face_node.c b/hicn-plugin/src/faces/face_node.c
index dc9bfffd0..6dedbe1c4 100644
--- a/hicn-plugin/src/faces/face_node.c
+++ b/hicn-plugin/src/faces/face_node.c
@@ -56,6 +56,7 @@ typedef struct
u32 next_index;
u32 sw_if_index;
u8 pkt_type;
+ hicn_error_t error;
u8 packet_data[60];
} hicn4_face_input_trace_t;
@@ -73,6 +74,7 @@ typedef struct
u32 next_index;
u32 sw_if_index;
u8 pkt_type;
+ hicn_error_t error;
u8 packet_data[60];
} hicn6_face_input_trace_t;
@@ -86,8 +88,9 @@ typedef enum
#define NEXT_MAPME_IP4 HICN4_FACE_INPUT_NEXT_MAPME
#define NEXT_MAPME_IP6 HICN6_FACE_INPUT_NEXT_MAPME
-#define NEXT_DATA_IP4 HICN4_FACE_INPUT_NEXT_DATA
-#define NEXT_DATA_IP6 HICN6_FACE_INPUT_NEXT_DATA
+
+#define NEXT_DATA_IP4 HICN4_FACE_INPUT_NEXT_DATA
+#define NEXT_DATA_IP6 HICN6_FACE_INPUT_NEXT_DATA
#define NEXT_ERROR_DROP_IP4 HICN4_FACE_INPUT_NEXT_ERROR_DROP
#define NEXT_ERROR_DROP_IP6 HICN6_FACE_INPUT_NEXT_ERROR_DROP
@@ -110,10 +113,11 @@ typedef enum
vlib_buffer_t *b0; \
u32 bi0, sw_if0; \
u32 next0 = NEXT_ERROR_DROP_IP##ipv; \
+ u8 is_icmp0; \
IP_HEADER_##ipv *ip_hdr = NULL; \
hicn_buffer_t *hicnb0; \
int from_tunnel0; \
- int ret0; \
+ int ret0 = HICN_ERROR_NONE; \
/* Prefetch for next iteration. */ \
if (n_left_from > 1) \
{ \
@@ -134,23 +138,35 @@ typedef enum
hicnb0 = hicn_get_buffer (b0); \
ip_hdr = (IP_HEADER_##ipv *) vlib_buffer_get_current (b0); \
\
- u8 is_icmp = ip_hdr->protocol == IPPROTO_ICMPV##ipv; \
- \
- from_tunnel0 = \
- (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \
- hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \
- sw_if0 = (from_tunnel0) * ~0 + \
- (1 - from_tunnel0) * vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
- \
- ret0 = hicn_face_ip##ipv##_add_and_lock ( \
- &hicnb0->face_id, &hicnb0->flags, &ip_hdr->dst_address, sw_if0, \
- vnet_buffer (b0)->ip.adj_index[VLIB_RX], \
- /* Should not be used */ ~0); \
- /* Make sure the face is not created here */ \
- ASSERT (ret0 == HICN_ERROR_FACE_ALREADY_CREATED); \
+ /* Parse packet and cache useful info in opaque2 */ \
+ ret0 = hicn_data_parse_pkt (b0); \
+ is_icmp0 = ret0 == HICN_ERROR_PARSER_MAPME_PACKET; \
+ ret0 = (ret0 == HICN_ERROR_NONE) || \
+ (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \
\
- next0 = \
- is_icmp * NEXT_MAPME_IP##ipv + (1 - is_icmp) * NEXT_DATA_IP##ipv; \
+ /* If parsing is ok, send packet to next node */ \
+ if (PREDICT_FALSE (!ret0)) \
+ { \
+ next0 = HICN##ipv##_FACE_INPUT_NEXT_ERROR_DROP; \
+ } \
+ else \
+ { \
+ next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \
+ (1 - is_icmp0) * NEXT_DATA_IP##ipv; \
+ from_tunnel0 = \
+ (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \
+ hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \
+ sw_if0 = \
+ (from_tunnel0) * ~0 + \
+ (1 - from_tunnel0) * vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
+ \
+ ret0 = hicn_face_ip##ipv##_add_and_lock ( \
+ &hicnb0->face_id, &hicnb0->flags, &ip_hdr->dst_address, sw_if0, \
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX], \
+ /* Should not be used */ ~0); \
+ /* Make sure the face is not created here */ \
+ ASSERT (ret0 == HICN_ERROR_FACE_ALREADY_CREATED); \
+ } \
\
vlib_increment_combined_counter ( \
&counters[hicnb0->face_id * HICN_N_COUNTER], thread_index, \
@@ -162,8 +178,9 @@ typedef enum
{ \
TRACE_INPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b0, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_INTEREST; \
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST; \
t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
+ t->error = ret0; \
t->next_index = next0; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \
sizeof (t->packet_data)); \
@@ -182,6 +199,7 @@ typedef enum
u32 bi0, bi1, sw_if0, sw_if1; \
u32 next0 = NEXT_ERROR_DROP_IP##ipv; \
u32 next1 = NEXT_ERROR_DROP_IP##ipv; \
+ u8 is_icmp0, is_icmp1; \
IP_HEADER_##ipv *ip_hdr0 = NULL; \
IP_HEADER_##ipv *ip_hdr1 = NULL; \
hicn_buffer_t *hicnb0; \
@@ -215,40 +233,95 @@ typedef enum
ip_hdr0 = (IP_HEADER_##ipv *) vlib_buffer_get_current (b0); \
ip_hdr1 = (IP_HEADER_##ipv *) vlib_buffer_get_current (b1); \
\
- u8 is_icmp0 = ip_hdr0->protocol == IPPROTO_ICMPV##ipv; \
- u8 is_icmp1 = ip_hdr1->protocol == IPPROTO_ICMPV##ipv; \
- \
- from_tunnel0 = \
- (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \
- hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \
- sw_if0 = (from_tunnel0) * ~0 + \
- (1 - from_tunnel0) * vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
- \
- ret0 = hicn_face_ip##ipv##_add_and_lock ( \
- &hicnb0->face_id, &hicnb0->flags, &ip_hdr0->dst_address, sw_if0, \
- vnet_buffer (b0)->ip.adj_index[VLIB_RX], \
- /* Should not be used */ ~0); \
- /* Make sure the face is not created here */ \
- ASSERT (ret0 == HICN_ERROR_FACE_ALREADY_CREATED); \
- \
- from_tunnel1 = \
- (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \
- hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \
- sw_if1 = (from_tunnel1) * ~0 + \
- (1 - from_tunnel1) * vnet_buffer (b1)->sw_if_index[VLIB_RX]; \
- \
- ret1 = hicn_face_ip##ipv##_add_and_lock ( \
- &hicnb1->face_id, &hicnb1->flags, &ip_hdr1->dst_address, sw_if1, \
- vnet_buffer (b1)->ip.adj_index[VLIB_RX], \
- /* Should not be used */ ~0); \
- /* Make sure the face is not created here */ \
- ASSERT (ret1 == HICN_ERROR_FACE_ALREADY_CREATED); \
- \
- next0 = \
- is_icmp0 * NEXT_MAPME_IP##ipv + (1 - is_icmp0) * NEXT_DATA_IP##ipv; \
- \
- next1 = \
- is_icmp1 * NEXT_MAPME_IP##ipv + (1 - is_icmp1) * NEXT_DATA_IP##ipv; \
+ /* Parse packet and cache useful info in opaque2 */ \
+ /* Parse packet and cache useful info in opaque2 */ \
+ ret0 = hicn_data_parse_pkt (b0); \
+ ret1 = hicn_data_parse_pkt (b1); \
+ is_icmp0 = ret0 == HICN_ERROR_PARSER_MAPME_PACKET; \
+ is_icmp1 = ret1 == HICN_ERROR_PARSER_MAPME_PACKET; \
+ ret0 = (ret0 == HICN_ERROR_NONE) || \
+ (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \
+ ret1 = (ret1 == HICN_ERROR_NONE) || \
+ (ret1 == HICN_ERROR_PARSER_MAPME_PACKET); \
+ if (PREDICT_TRUE (ret0 && ret1)) \
+ { \
+ next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \
+ (1 - is_icmp0) * NEXT_DATA_IP##ipv; \
+ \
+ next1 = is_icmp1 * NEXT_MAPME_IP##ipv + \
+ (1 - is_icmp1) * NEXT_DATA_IP##ipv; \
+ \
+ from_tunnel0 = \
+ (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \
+ hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \
+ sw_if0 = \
+ (from_tunnel0) * ~0 + \
+ (1 - from_tunnel0) * vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
+ \
+ ret0 = hicn_face_ip##ipv##_add_and_lock ( \
+ &hicnb0->face_id, &hicnb0->flags, &ip_hdr0->dst_address, sw_if0, \
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX], \
+ /* Should not be used */ ~0); \
+ /* Make sure the face is not created here */ \
+ ASSERT (ret0 == HICN_ERROR_FACE_ALREADY_CREATED); \
+ \
+ from_tunnel1 = \
+ (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \
+ hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \
+ sw_if1 = \
+ (from_tunnel1) * ~0 + \
+ (1 - from_tunnel1) * vnet_buffer (b1)->sw_if_index[VLIB_RX]; \
+ \
+ ret1 = hicn_face_ip##ipv##_add_and_lock ( \
+ &hicnb1->face_id, &hicnb1->flags, &ip_hdr1->dst_address, sw_if1, \
+ vnet_buffer (b1)->ip.adj_index[VLIB_RX], \
+ /* Should not be used */ ~0); \
+ /* Make sure the face is not created here */ \
+ ASSERT (ret1 == HICN_ERROR_FACE_ALREADY_CREATED); \
+ } \
+ else if (ret0 && !ret1) \
+ { \
+ next1 = HICN##ipv##_FACE_INPUT_NEXT_ERROR_DROP; \
+ from_tunnel0 = \
+ (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \
+ hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \
+ sw_if0 = \
+ (from_tunnel0) * ~0 + \
+ (1 - from_tunnel0) * vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
+ \
+ ret0 = hicn_face_ip##ipv##_add_and_lock ( \
+ &hicnb0->face_id, &hicnb0->flags, &ip_hdr0->dst_address, sw_if0, \
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX], \
+ /* Should not be used */ ~0); \
+ /* Make sure the face is not created here */ \
+ ASSERT (ret0 == HICN_ERROR_FACE_ALREADY_CREATED); \
+ next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \
+ (1 - is_icmp0) * NEXT_DATA_IP##ipv; \
+ } \
+ else if (!ret0 && ret1) \
+ { \
+ next0 = HICN##ipv##_FACE_INPUT_NEXT_ERROR_DROP; \
+ from_tunnel1 = \
+ (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL || \
+ hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) > 0; \
+ sw_if1 = \
+ (from_tunnel1) * ~0 + \
+ (1 - from_tunnel1) * vnet_buffer (b1)->sw_if_index[VLIB_RX]; \
+ \
+ ret1 = hicn_face_ip##ipv##_add_and_lock ( \
+ &hicnb1->face_id, &hicnb1->flags, &ip_hdr1->dst_address, sw_if1, \
+ vnet_buffer (b1)->ip.adj_index[VLIB_RX], \
+ /* Should not be used */ ~0); \
+ /* Make sure the face is not created here */ \
+ ASSERT (ret1 == HICN_ERROR_FACE_ALREADY_CREATED); \
+ next1 = is_icmp1 * NEXT_MAPME_IP##ipv + \
+ (1 - is_icmp1) * NEXT_DATA_IP##ipv; \
+ } \
+ else \
+ { \
+ next0 = HICN##ipv##_FACE_INPUT_NEXT_ERROR_DROP; \
+ next1 = HICN##ipv##_FACE_INPUT_NEXT_ERROR_DROP; \
+ } \
\
vlib_increment_combined_counter ( \
&counters[hicnb0->face_id * HICN_N_COUNTER], thread_index, \
@@ -265,8 +338,9 @@ typedef enum
{ \
TRACE_INPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b0, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_INTEREST; \
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST; \
t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
+ t->error = ret0; \
t->next_index = next0; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \
sizeof (t->packet_data)); \
@@ -277,8 +351,9 @@ typedef enum
{ \
TRACE_INPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b1, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_INTEREST; \
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST; \
t->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \
+ t->error = ret1; \
t->next_index = next1; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b1), \
sizeof (t->packet_data)); \
@@ -461,80 +536,6 @@ typedef enum
HICN6_FACE_OUTPUT_N_NEXT,
} hicn6_face_output_next_t;
-/* static_always_inline void */
-/* hicn_reply_probe_v4 (vlib_buffer_t * b, hicn_face_t * face) */
-/* { */
-/* hicn_header_t *h0 = vlib_buffer_get_current (b); */
-/* hicn_face_ip_t * face_ip = (hicn_face_ip_t *)(&face->data); */
-/* h0->v4.ip.saddr = h0->v4.ip.daddr; */
-/* h0->v4.ip.daddr = face_ip->local_addr.ip4; */
-/* vnet_buffer (b)->sw_if_index[VLIB_RX] = face->shared.sw_if; */
-
-/* u16 * dst_port_ptr = (u16 *)(((u8*)h0) + sizeof(ip4_header_t) +
- * sizeof(u16)); */
-/* u16 dst_port = *dst_port_ptr; */
-/* u16 * src_port_ptr = (u16 *)(((u8*)h0) + sizeof(ip4_header_t)); */
-
-/* *dst_port_ptr = *src_port_ptr; */
-/* *src_port_ptr = dst_port; */
-
-/* hicn_type_t type = hicn_get_buffer (b)->type; */
-/* hicn_ops_vft[type.l1]->set_lifetime (type, &h0->protocol, 0); */
-/* } */
-
-/* static_always_inline void */
-/* hicn_reply_probe_v6 (vlib_buffer_t * b, hicn_face_t * face) */
-/* { */
-/* hicn_header_t *h0 = vlib_buffer_get_current (b); */
-/* hicn_face_ip_t * face_ip = (hicn_face_ip_t *)(&face->data); */
-/* h0->v6.ip.saddr = h0->v6.ip.daddr; */
-/* h0->v6.ip.daddr = face_ip->local_addr.ip6; */
-/* vnet_buffer (b)->sw_if_index[VLIB_RX] = face->shared.sw_if; */
-
-/* u16 * dst_port_ptr = (u16 *)(((u8*)h0) + sizeof(ip6_header_t) +
- * sizeof(u16)); */
-/* u16 dst_port = *dst_port_ptr; */
-/* u16 * src_port_ptr = (u16 *)(((u8*)h0) + sizeof(ip6_header_t)); */
-
-/* *dst_port_ptr = *src_port_ptr; */
-/* *src_port_ptr = dst_port; */
-
-/* hicn_type_t type = hicn_get_buffer (b)->type; */
-/* hicn_ops_vft[type.l1]->set_lifetime (type, &h0->protocol, 0); */
-
-/* } */
-
-/* static_always_inline u32 */
-/* hicn_face_match_probe (vlib_buffer_t * b, hicn_face_t * face, u32 * next) */
-/* { */
-
-/* u8 *ptr = vlib_buffer_get_current (b); */
-/* u8 v = *ptr & 0xf0; */
-/* u8 res = 0; */
-
-/* if ( v == 0x40 ) */
-/* { */
-/* u16 * dst_port = (u16 *)(ptr + sizeof(ip4_header_t) + sizeof(u16)); */
-/* if (*dst_port == clib_net_to_host_u16(DEFAULT_PROBING_PORT)) */
-/* { */
-/* hicn_reply_probe_v6(b, face); */
-/* *next = HICN4_FACE_NEXT_ECHO_REPLY; */
-/* res = 1; */
-/* } */
-/* } */
-/* else if ( v == 0x60 ) */
-/* { */
-/* u16 * dst_port = (u16 *)(ptr + sizeof(ip6_header_t) + sizeof(u16)); */
-/* if (*dst_port == clib_net_to_host_u16(DEFAULT_PROBING_PORT)) */
-/* { */
-/* hicn_reply_probe_v6(b, face); */
-/* *next = HICN6_FACE_NEXT_ECHO_REPLY; */
-/* res = 1; */
-/* } */
-/* } */
-/* return res; */
-/* } */
-
static inline void
hicn_face_rewrite_interest (vlib_main_t *vm, vlib_buffer_t *b0,
hicn_face_t *face, u32 *next)
@@ -546,6 +547,9 @@ hicn_face_rewrite_interest (vlib_main_t *vm, vlib_buffer_t *b0,
hicn_header_t *hicn = vlib_buffer_get_current (b0);
+ u8 is_v4 = ip46_address_is_ip4 (&face->nat_addr) &&
+ !ip6_address_is_loopback (&face->nat_addr.ip6);
+
// hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data;
ip46_address_t temp_addr;
@@ -553,11 +557,8 @@ hicn_face_rewrite_interest (vlib_main_t *vm, vlib_buffer_t *b0,
hicn_type_t type = hicn_get_buffer (b0)->type;
int ret = hicn_ops_vft[type.l1]->rewrite_interest (
type, &hicn->protocol, &face->nat_addr, &temp_addr);
-
if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED)
{
- u8 is_v4 = ip46_address_is_ip4 (&face->nat_addr) &&
- !ip6_address_is_loopback (&face->nat_addr.ip6);
ensure_offload_flags (b0, is_v4);
}
@@ -645,7 +646,7 @@ typedef struct
{ \
TRACE_OUTPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b0, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_INTEREST; \
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST; \
t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
t->next_index = next0; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \
@@ -724,7 +725,7 @@ typedef struct
{ \
TRACE_OUTPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b0, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_INTEREST; \
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST; \
t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
t->next_index = next0; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \
@@ -736,7 +737,7 @@ typedef struct
{ \
TRACE_OUTPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b1, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_INTEREST; \
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST; \
t->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \
t->next_index = next1; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b1), \
@@ -812,12 +813,7 @@ VLIB_REGISTER_NODE (hicn4_face_output_node) = {
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = ARRAY_LEN (hicn4_face_output_error_strings),
.error_strings = hicn4_face_output_error_strings,
- .n_next_nodes = HICN4_FACE_OUTPUT_N_NEXT,
- /* Reusing the list of nodes from lookup to be compatible with arp */
- .next_nodes = { [HICN4_FACE_OUTPUT_NEXT_ERROR_DROP] = "error-drop",
- [HICN4_FACE_OUTPUT_NEXT_ECHO_REPLY] = "hicn4-face-input",
- [HICN4_FACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap",
- [HICN4_FACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" }
+ .sibling_of = "ip4-lookup",
};
static uword
@@ -882,13 +878,7 @@ VLIB_REGISTER_NODE (hicn6_face_output_node) = {
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = ARRAY_LEN (hicn6_face_output_error_strings),
.error_strings = hicn6_face_output_error_strings,
- .n_next_nodes = HICN6_FACE_OUTPUT_N_NEXT,
- /* Reusing the list of nodes from lookup to be compatible with neighbour
- discovery */
- .next_nodes = { [HICN6_FACE_OUTPUT_NEXT_ERROR_DROP] = "error-drop",
- [HICN6_FACE_OUTPUT_NEXT_ECHO_REPLY] = "hicn6-face-input",
- [HICN6_FACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap",
- [HICN6_FACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" }
+ .sibling_of = "ip6-lookup",
};
/*
@@ -897,4 +887,4 @@ VLIB_REGISTER_NODE (hicn6_face_output_node) = {
* Local Variables:
* eval: (c-set-style "gnu")
* End:
- */
+ */ \ No newline at end of file
diff --git a/hicn-plugin/src/faces/iface_node.c b/hicn-plugin/src/faces/iface_node.c
index 84205af9b..3b6634d77 100644
--- a/hicn-plugin/src/faces/iface_node.c
+++ b/hicn-plugin/src/faces/iface_node.c
@@ -52,6 +52,7 @@ typedef struct
u32 next_index;
u32 sw_if_index;
u8 pkt_type;
+ hicn_error_t error;
u8 packet_data[60];
} hicn4_iface_input_trace_t;
@@ -69,6 +70,7 @@ typedef struct
u32 next_index;
u32 sw_if_index;
u8 pkt_type;
+ hicn_error_t error;
u8 packet_data[60];
} hicn6_iface_input_trace_t;
@@ -86,33 +88,9 @@ typedef enum
#define NEXT_INTEREST_IP4 HICN4_IFACE_INPUT_NEXT_INTEREST
#define NEXT_INTEREST_IP6 HICN6_IFACE_INPUT_NEXT_INTEREST
-#define ADDRESS_IP4 \
- ip_interface_address_t *ia = 0; \
- ip4_address_t *local_address = \
- ip4_interface_first_address (&ip4_main, swif, &ia)
-#define ADDRESS_IP6 \
- ip6_address_t *local_address = ip6_interface_first_address (&ip6_main, swif)
-
-#define ADDRESSX2_IP4 \
- ip_interface_address_t *ia0, *ia1; \
- ia0 = ia1 = 0; \
- ip4_address_t *local_address0 = \
- ip4_interface_first_address (&ip4_main, swif0, &ia0); \
- ip4_address_t *local_address1 = \
- ip4_interface_first_address (&ip4_main, swif1, &ia1);
-
-#define ADDRESSX2_IP6 \
- ip6_address_t *local_address0 = \
- ip6_interface_first_address (&ip6_main, swif0); \
- ip6_address_t *local_address1 = \
- ip6_interface_first_address (&ip6_main, swif1);
-
#define DPO_ADD_LOCK_FACE_IP4 hicn_face_ip4_add_and_lock
#define DPO_ADD_LOCK_FACE_IP6 hicn_face_ip6_add_and_lock
-//#define VLIB_EDGE_IP4 data_fwd_iface_ip4_vlib_edge
-//#define VLIB_EDGE_IP6 data_fwd_iface_ip6_vlib_edge
-
#define IP_HEADER_4 ip4_header_t
#define IP_HEADER_6 ip6_header_t
@@ -148,6 +126,7 @@ typedef enum
HICN4_IFACE_OUTPUT_NEXT_LOOKUP,
HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP,
HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP,
+ HICN4_IFACE_OUTPUT_NEXT_PG,
HICN4_IFACE_OUTPUT_N_NEXT,
} hicn4_iface_output_next_t;
@@ -166,6 +145,7 @@ typedef enum
HICN6_IFACE_OUTPUT_NEXT_LOOKUP,
HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP,
HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP,
+ HICN6_IFACE_OUTPUT_NEXT_PG,
HICN6_IFACE_OUTPUT_N_NEXT,
} hicn6_iface_output_next_t;
@@ -178,6 +158,9 @@ typedef enum
#define NEXT_UDP_ENCAP_IP4 HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP
#define NEXT_UDP_ENCAP_IP6 HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP
+#define NEXT_PG4 HICN4_IFACE_OUTPUT_NEXT_PG
+#define NEXT_PG6 HICN6_IFACE_OUTPUT_NEXT_PG
+
#define HICN_REWRITE_DATA_IP4 hicn_rewrite_iface_data4
#define HICN_REWRITE_DATA_IP6 hicn_rewrite_iface_data6
@@ -190,9 +173,11 @@ typedef enum
do \
{ \
vlib_buffer_t *b0; \
- u32 bi0, next0, next_iface0, sw_if0; \
+ u32 bi0, next0, next_iface0, sw_if0 = ~0; \
IP_HEADER_##ipv *ip_hdr = NULL; \
hicn_buffer_t *hicnb0; \
+ int ret0 = HICN_ERROR_NONE; \
+ u8 is_icmp0; \
/* Prefetch for next iteration. */ \
if (n_left_from > 1) \
{ \
@@ -213,41 +198,55 @@ typedef enum
hicnb0 = hicn_get_buffer (b0); \
ip_hdr = (IP_HEADER_##ipv *) vlib_buffer_get_current (b0); \
\
- stats.pkts_interest_count += 1; \
- \
- u8 is_icmp = ip_hdr->protocol == IPPROTO_ICMPV##ipv; \
- \
- next0 = \
- is_icmp * NEXT_MAPME_IP##ipv + (1 - is_icmp) * NEXT_INTEREST_IP##ipv; \
- \
- next_iface0 = NEXT_DATA_LOOKUP_IP##ipv; \
- sw_if0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
- \
- if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \
- vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \
+ /* Parse packet and cache useful info in opaque2 */ \
+ ret0 = hicn_interest_parse_pkt (b0); \
+ is_icmp0 = (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \
+ ret0 = (ret0 == HICN_ERROR_NONE) || \
+ (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \
+ if (PREDICT_FALSE (!ret0)) \
{ \
- next_iface0 = NEXT_UDP_ENCAP_IP4; \
- sw_if0 = ~0; \
+ next0 = HICN##ipv##_IFACE_INPUT_NEXT_ERROR_DROP; \
} \
- else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \
- vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \
+ else \
{ \
- next_iface0 = NEXT_UDP_ENCAP_IP6; \
- sw_if0 = ~0; \
+ next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \
+ (1 - is_icmp0) * NEXT_INTEREST_IP##ipv; \
+ \
+ next_iface0 = NEXT_DATA_LOOKUP_IP##ipv; \
+ sw_if0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
+ \
+ if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \
+ { \
+ next_iface0 = NEXT_UDP_ENCAP_IP4; \
+ sw_if0 = ~0; \
+ } \
+ else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX] != \
+ ADJ_INDEX_INVALID) \
+ { \
+ next_iface0 = NEXT_UDP_ENCAP_IP6; \
+ sw_if0 = ~0; \
+ } \
+ else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_PG) \
+ { \
+ next_iface0 = NEXT_PG##ipv; \
+ } \
+ \
+ DPO_ADD_LOCK_FACE_IP##ipv ( \
+ &(hicnb0->face_id), &hicnb0->flags, &(ip_hdr->src_address), \
+ sw_if0, vnet_buffer (b0)->ip.adj_index[VLIB_RX], next_iface0); \
} \
\
- DPO_ADD_LOCK_FACE_IP##ipv ( \
- &(hicnb0->face_id), &hicnb0->flags, &(ip_hdr->src_address), sw_if0, \
- vnet_buffer (b0)->ip.adj_index[VLIB_RX], next_iface0); \
- \
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \
(b0->flags & VLIB_BUFFER_IS_TRACED))) \
{ \
TRACE_INPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b0, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_INTEREST; \
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST; \
t->sw_if_index = sw_if0; \
t->next_index = next0; \
+ t->error = ret0; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \
sizeof (t->packet_data)); \
} \
@@ -267,9 +266,12 @@ typedef enum
do \
{ \
vlib_buffer_t *b0, *b1; \
- u32 bi0, bi1, next0, next1, next_iface0, next_iface1, sw_if0, sw_if1; \
+ u32 bi0, bi1, next0, next1; \
+ u32 next_iface0, next_iface1, sw_if0 = ~0, sw_if1 = ~0; \
+ u8 is_icmp0, is_icmp1; \
IP_HEADER_##ipv *ip_hdr0 = NULL; \
IP_HEADER_##ipv *ip_hdr1 = NULL; \
+ int ret0 = HICN_ERROR_NONE, ret1 = HICN_ERROR_NONE; \
hicn_buffer_t *hicnb0, *hicnb1; \
\
/* Prefetch for next iteration. */ \
@@ -300,63 +302,149 @@ typedef enum
\
stats.pkts_interest_count += 2; \
\
- u8 is_icmp0 = ip_hdr0->protocol == IPPROTO_ICMPV##ipv; \
- u8 is_icmp1 = ip_hdr1->protocol == IPPROTO_ICMPV##ipv; \
- \
- next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \
- (1 - is_icmp0) * NEXT_INTEREST_IP##ipv; \
- \
- next1 = is_icmp1 * NEXT_MAPME_IP##ipv + \
- (1 - is_icmp1) * NEXT_INTEREST_IP##ipv; \
- \
- next_iface0 = NEXT_DATA_LOOKUP_IP##ipv; \
- sw_if0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
- \
- if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \
- vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \
+ /* Parse packet and cache useful info in opaque2 */ \
+ ret0 = hicn_interest_parse_pkt (b0); \
+ ret1 = hicn_interest_parse_pkt (b1); \
+ is_icmp0 = ret0 == HICN_ERROR_PARSER_MAPME_PACKET; \
+ is_icmp1 = ret1 == HICN_ERROR_PARSER_MAPME_PACKET; \
+ ret0 = (ret0 == HICN_ERROR_NONE) || \
+ (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \
+ ret1 = (ret1 == HICN_ERROR_NONE) || \
+ (ret1 == HICN_ERROR_PARSER_MAPME_PACKET); \
+ \
+ if (PREDICT_TRUE (ret0 && ret1)) \
{ \
- next_iface0 = NEXT_UDP_ENCAP_IP4; \
- sw_if0 = ~0; \
+ next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \
+ (1 - is_icmp0) * NEXT_INTEREST_IP##ipv; \
+ \
+ next1 = is_icmp1 * NEXT_MAPME_IP##ipv + \
+ (1 - is_icmp1) * NEXT_INTEREST_IP##ipv; \
+ \
+ next_iface0 = NEXT_DATA_LOOKUP_IP##ipv; \
+ sw_if0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
+ \
+ if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \
+ { \
+ next_iface0 = NEXT_UDP_ENCAP_IP4; \
+ sw_if0 = ~0; \
+ } \
+ else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX] != \
+ ADJ_INDEX_INVALID) \
+ { \
+ next_iface0 = NEXT_UDP_ENCAP_IP6; \
+ sw_if0 = ~0; \
+ } \
+ else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_PG) \
+ { \
+ next_iface0 = NEXT_PG##ipv; \
+ } \
+ \
+ next_iface1 = NEXT_DATA_LOOKUP_IP##ipv; \
+ sw_if1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \
+ \
+ if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \
+ vnet_buffer (b1)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \
+ { \
+ next_iface1 = NEXT_UDP_ENCAP_IP4; \
+ sw_if1 = ~0; \
+ } \
+ else if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \
+ vnet_buffer (b1)->ip.adj_index[VLIB_RX] != \
+ ADJ_INDEX_INVALID) \
+ { \
+ next_iface1 = NEXT_UDP_ENCAP_IP6; \
+ sw_if1 = ~0; \
+ } \
+ else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_PG) \
+ { \
+ next_iface1 = NEXT_PG##ipv; \
+ } \
+ \
+ DPO_ADD_LOCK_FACE_IP##ipv ( \
+ &(hicnb0->face_id), &hicnb0->flags, &(ip_hdr0->src_address), \
+ sw_if0, vnet_buffer (b0)->ip.adj_index[VLIB_RX], next_iface0); \
+ \
+ DPO_ADD_LOCK_FACE_IP##ipv ( \
+ &(hicnb1->face_id), &hicnb1->flags, &(ip_hdr1->src_address), \
+ sw_if1, vnet_buffer (b1)->ip.adj_index[VLIB_RX], next_iface1); \
} \
- else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \
- vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \
+ else if (ret0 && !ret1) \
{ \
- next_iface0 = NEXT_UDP_ENCAP_IP6; \
- sw_if0 = ~0; \
+ next1 = HICN##ipv##_IFACE_INPUT_NEXT_ERROR_DROP; \
+ next0 = is_icmp0 * NEXT_MAPME_IP##ipv + \
+ (1 - is_icmp0) * NEXT_INTEREST_IP##ipv; \
+ next_iface0 = NEXT_DATA_LOOKUP_IP##ipv; \
+ sw_if0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
+ \
+ if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \
+ { \
+ next_iface0 = NEXT_UDP_ENCAP_IP4; \
+ sw_if0 = ~0; \
+ } \
+ else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX] != \
+ ADJ_INDEX_INVALID) \
+ { \
+ next_iface0 = NEXT_UDP_ENCAP_IP6; \
+ sw_if0 = ~0; \
+ } \
+ else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_PG) \
+ { \
+ next_iface0 = NEXT_PG##ipv; \
+ } \
+ \
+ DPO_ADD_LOCK_FACE_IP##ipv ( \
+ &(hicnb0->face_id), &hicnb0->flags, &(ip_hdr0->src_address), \
+ sw_if0, vnet_buffer (b0)->ip.adj_index[VLIB_RX], next_iface0); \
} \
- \
- next_iface1 = NEXT_DATA_LOOKUP_IP##ipv; \
- sw_if1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \
- \
- if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \
- vnet_buffer (b1)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \
+ else if (!ret0 && ret1) \
{ \
- next_iface1 = NEXT_UDP_ENCAP_IP4; \
- sw_if1 = ~0; \
+ next0 = HICN##ipv##_IFACE_INPUT_NEXT_ERROR_DROP; \
+ next_iface1 = NEXT_DATA_LOOKUP_IP##ipv; \
+ sw_if1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \
+ next1 = is_icmp1 * NEXT_MAPME_IP##ipv + \
+ (1 - is_icmp1) * NEXT_INTEREST_IP##ipv; \
+ \
+ if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL && \
+ vnet_buffer (b1)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \
+ { \
+ next_iface1 = NEXT_UDP_ENCAP_IP4; \
+ sw_if1 = ~0; \
+ } \
+ else if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \
+ vnet_buffer (b1)->ip.adj_index[VLIB_RX] != \
+ ADJ_INDEX_INVALID) \
+ { \
+ next_iface1 = NEXT_UDP_ENCAP_IP6; \
+ sw_if1 = ~0; \
+ } \
+ else if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_PG) \
+ { \
+ next_iface1 = NEXT_PG##ipv; \
+ } \
+ \
+ DPO_ADD_LOCK_FACE_IP##ipv ( \
+ &(hicnb1->face_id), &hicnb1->flags, &(ip_hdr1->src_address), \
+ sw_if1, vnet_buffer (b1)->ip.adj_index[VLIB_RX], next_iface1); \
} \
- else if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL && \
- vnet_buffer (b1)->ip.adj_index[VLIB_RX] != ADJ_INDEX_INVALID) \
+ else \
{ \
- next_iface1 = NEXT_UDP_ENCAP_IP6; \
- sw_if1 = ~0; \
+ next0 = HICN##ipv##_IFACE_INPUT_NEXT_ERROR_DROP; \
+ next1 = HICN##ipv##_IFACE_INPUT_NEXT_ERROR_DROP; \
} \
\
- DPO_ADD_LOCK_FACE_IP##ipv ( \
- &(hicnb0->face_id), &hicnb0->flags, &(ip_hdr0->src_address), sw_if0, \
- vnet_buffer (b0)->ip.adj_index[VLIB_RX], next_iface0); \
- \
- DPO_ADD_LOCK_FACE_IP##ipv ( \
- &(hicnb1->face_id), &hicnb1->flags, &(ip_hdr1->src_address), sw_if1, \
- vnet_buffer (b1)->ip.adj_index[VLIB_RX], next_iface1); \
- \
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \
(b0->flags & VLIB_BUFFER_IS_TRACED))) \
{ \
TRACE_INPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b0, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_INTEREST; \
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST; \
t->sw_if_index = sw_if0; \
t->next_index = next0; \
+ t->error = ret0; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \
sizeof (t->packet_data)); \
} \
@@ -366,9 +454,10 @@ typedef enum
{ \
TRACE_INPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b1, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_INTEREST; \
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST; \
t->sw_if_index = sw_if1; \
t->next_index = next1; \
+ t->error = ret1; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b1), \
sizeof (t->packet_data)); \
} \
@@ -435,9 +524,17 @@ hicn4_iface_input_format_trace (u8 *s, va_list *args)
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
hicn4_iface_input_trace_t *t = va_arg (*args, hicn4_iface_input_trace_t *);
- s = format (s, "IFACE_IP4_INPUT: pkt: %d, sw_if_index %d, next index %d\n%U",
- (int) t->pkt_type, t->sw_if_index, t->next_index,
- format_ip4_header, t->packet_data, sizeof (t->packet_data));
+ s = format (s, "IFACE_IP4_INPUT: pkt: %d, sw_if_index %d, next index %d",
+ (int) t->pkt_type, t->sw_if_index, t->next_index);
+
+ if (t->error)
+ {
+ s = format (s, " drop reason: %s", get_error_string (t->error));
+ }
+
+ s = format (s, "\n%U", format_ip4_header, t->packet_data,
+ sizeof (t->packet_data));
+
return (s);
}
@@ -544,6 +641,7 @@ hicn_rewrite_iface_data4 (vlib_main_t *vm, vlib_buffer_t *b0,
const hicn_face_t *iface, u32 *next)
{
ip4_header_t *ip0;
+ int ret = HICN_ERROR_NONE;
/* Get the pointer to the old ip and tcp header */
ip0 = vlib_buffer_get_current (b0);
@@ -563,9 +661,11 @@ hicn_rewrite_iface_data4 (vlib_main_t *vm, vlib_buffer_t *b0,
hicn_type_t type = hicn_get_buffer (b0)->type;
u8 flags = hicn_get_buffer (b0)->flags;
u8 reset_pl = flags & HICN_BUFFER_FLAGS_FROM_CS;
- int ret = hicn_ops_vft[type.l1]->rewrite_data (
- type, &hicn->protocol, &(iface->nat_addr), &(temp_addr), iface->pl_id,
- reset_pl);
+
+ ret = hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol,
+ &(iface->nat_addr), &(temp_addr),
+ iface->pl_id, reset_pl);
+
if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED)
{
ensure_offload_flags (b0, 1 /* is_v4 */);
@@ -577,6 +677,7 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0,
const hicn_face_t *iface, u32 *next)
{
ip6_header_t *ip0;
+ int ret = HICN_ERROR_NONE;
/* Get the pointer to the old ip and tcp header */
/* Copy the previous ip and tcp header to the new portion of memory */
@@ -598,9 +699,10 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0,
hicn_type_t type = hicn_get_buffer (b0)->type;
u8 flags = hicn_get_buffer (b0)->flags;
u8 reset_pl = flags & HICN_BUFFER_FLAGS_FROM_CS;
- int ret = hicn_ops_vft[type.l1]->rewrite_data (
- type, &hicn->protocol, &(iface->nat_addr), &(temp_addr), iface->pl_id,
- reset_pl);
+
+ ret = hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol,
+ &(iface->nat_addr), &(temp_addr),
+ iface->pl_id, reset_pl);
if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED)
{
@@ -653,7 +755,7 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0,
{ \
TRACE_OUTPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b0, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_INTEREST; \
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST; \
t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
t->next_index = next0; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \
@@ -731,7 +833,7 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0,
{ \
TRACE_OUTPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b0, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_INTEREST; \
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST; \
t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \
t->next_index = next0; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b0), \
@@ -743,7 +845,7 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0,
{ \
TRACE_OUTPUT_PKT_IP##ipv *t = \
vlib_add_trace (vm, node, b1, sizeof (*t)); \
- t->pkt_type = HICN_PKT_TYPE_INTEREST; \
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST; \
t->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \
t->next_index = next1; \
clib_memcpy_fast (t->packet_data, vlib_buffer_get_current (b1), \
@@ -824,7 +926,8 @@ VLIB_REGISTER_NODE (hicn4_iface_output_node) = {
.next_nodes = { [HICN4_IFACE_OUTPUT_NEXT_DROP] = "error-drop",
[HICN4_IFACE_OUTPUT_NEXT_LOOKUP] = "ip4-lookup",
[HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap",
- [HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" },
+ [HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap",
+ [HICN4_IFACE_OUTPUT_NEXT_PG] = "hicnpg-data" },
};
static uword
@@ -893,7 +996,8 @@ VLIB_REGISTER_NODE (hicn6_iface_output_node) = {
.next_nodes = { [HICN6_IFACE_OUTPUT_NEXT_DROP] = "error-drop",
[HICN6_IFACE_OUTPUT_NEXT_LOOKUP] = "ip6-lookup",
[HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap",
- [HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap" },
+ [HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap",
+ [HICN6_IFACE_OUTPUT_NEXT_PG] = "hicnpg-data" },
};
/*
@@ -902,4 +1006,4 @@ VLIB_REGISTER_NODE (hicn6_iface_output_node) = {
* Local Variables:
* eval: (c-set-style "gnu")
* End:
- */
+ */ \ No newline at end of file
diff --git a/hicn-plugin/src/hicn.c b/hicn-plugin/src/hicn.c
index 1131d4339..1789f5407 100644
--- a/hicn-plugin/src/hicn.c
+++ b/hicn-plugin/src/hicn.c
@@ -28,6 +28,7 @@
#include "face_db.h"
#include "udp_tunnels/udp_tunnel.h"
#include "route.h"
+#include "pg.h"
hicn_main_t hicn_main;
/* Module vars */
@@ -223,24 +224,29 @@ hicn_init (vlib_main_t *vm)
hicn_main_t *sm = &hicn_main;
- /* Init other elements in the 'main' struct */
+ // Init other elements in the 'main' struct
sm->is_enabled = 0;
error = hicn_api_plugin_hookup (vm);
- /* Init the dpo module */
+ // Init the dpo module
hicn_dpos_init ();
- /* Init the app manager */
+ // Init the app manager
address_mgr_init ();
+ // Init the face module
hicn_face_module_init (vm);
- /* Init the route module */
+ // Init the route module
hicn_route_init ();
+ // Init the UDP tunnels module
udp_tunnel_init ();
+ // Init the packet generator module
+ hicn_pg_init (vm);
+
return error;
}
diff --git a/hicn-plugin/src/hicn.h b/hicn-plugin/src/hicn.h
index aaf16c917..22309e3e5 100644
--- a/hicn-plugin/src/hicn.h
+++ b/hicn-plugin/src/hicn.h
@@ -57,32 +57,44 @@ typedef u8 weight_t;
#define VLIB_BUFFER_MIN_CHAIN_SEG_SIZE (128)
#endif
-/* vlib_buffer cloning utilities impose that current_lentgh is more that
- * 2*CLIB_CACHE_LINE_BYTES. */
-/* This flag is used to mark packets whose lenght is less that
- * 2*CLIB_CACHE_LINE_BYTES. */
-#define HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL 0x02
-#define HICN_BUFFER_FLAGS_FROM_CS 0x10
-
/* The following is stored in the opaque2 field in the vlib_buffer_t */
typedef struct
{
- /* hash of the name */
+ /**
+ * Hash of the name (8)
+ */
u64 name_hash;
- /* ids to prefetch a PIT/CS entry */
+ /**
+ * IDs to prefetch a PIT/CS entry (4+4+1+1)
+ */
u32 node_id;
u32 bucket_id;
u8 hash_entry_id;
u8 hash_bucket_flags;
+ /**
+ * hICN buffer flags (1)
+ */
u8 flags;
- u8 dpo_ctx_id; /* used for data path */
- u8 vft_id; /* " */
- hicn_face_id_t face_id; /* ingress iface, sizeof(u32) */
+ /**
+ * used for data path (1+1)
+ */
+ u8 dpo_ctx_id;
+ u8 vft_id;
+
+ /**
+ * Ingress face (4)
+ */
+ hicn_face_id_t face_id;
+ /**
+ * Cached packet info
+ */
hicn_type_t type;
+ hicn_name_t name;
+ u16 port;
} hicn_buffer_t;
STATIC_ASSERT (sizeof (hicn_buffer_t) <=
@@ -101,6 +113,28 @@ hicn_is_v6 (hicn_header_t *pkt_hdr)
return ((pkt_hdr->v4.ip.version_ihl >> 4) != 4);
}
+always_inline void
+hicn_buffer_get_name_and_namelen (vlib_buffer_t *b0, u8 **nameptr,
+ u16 *namelen)
+{
+ *nameptr = (u8 *) (&hicn_get_buffer (b0)->name);
+ *namelen = ip_address_is_v4 (&hicn_get_buffer (b0)->name.prefix) ?
+ HICN_V4_NAME_LEN :
+ HICN_V6_NAME_LEN;
+}
+
+always_inline u8
+hicn_buffer_is_v6 (vlib_buffer_t *b0)
+{
+ return hicn_get_buffer (b0)->type.l1 == IPPROTO_IPV6;
+}
+
+always_inline void
+hicn_buffer_set_flags (vlib_buffer_t *b, u8 flags)
+{
+ hicn_buffer_t *hb = hicn_get_buffer (b);
+ hb->flags |= flags;
+}
#endif /* __HICN_H__ */
/*
diff --git a/hicn-plugin/src/hicn_buffer_flags.h b/hicn-plugin/src/hicn_buffer_flags.h
new file mode 100644
index 000000000..7d99e6d33
--- /dev/null
+++ b/hicn-plugin/src/hicn_buffer_flags.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HICN_BUFFER_FLAGS_H__
+#define __HICN_BUFFER_FLAGS_H__
+
+#define foreach_hicn_buffer_flag \
+ _ (0, NEW_FACE, "new face") \
+ _ (1, PKT_LESS_TWO_CL, "packet is less that 2 cache lines length") \
+ _ (2, FROM_UDP4_TUNNEL, "packet is from udp4 tunnel") \
+ _ (3, FROM_UDP6_TUNNEL, "packet is from udp6 tunnel") \
+ _ (4, FROM_CS, "packet is from cs") \
+ _ (5, FROM_PG, "packet is from packet generator")
+
+enum
+{
+ HICN_BUFFER_FLAGS_DEFAULT = 0,
+#define _(a, b, c) HICN_BUFFER_FLAGS_##b = (1 << a),
+ foreach_hicn_buffer_flag
+#undef _
+};
+
+#endif /* __HICN_BUFFER_FLAGS_H__ */ \ No newline at end of file
diff --git a/hicn-plugin/src/interest_hitcs_node.c b/hicn-plugin/src/interest_hitcs_node.c
index 947b4cb68..1af21191c 100644
--- a/hicn-plugin/src/interest_hitcs_node.c
+++ b/hicn-plugin/src/interest_hitcs_node.c
@@ -90,7 +90,6 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hicn_interest_hitcs_runtime_t *rt;
vl_api_hicn_api_node_stats_get_reply_t stats = { 0 };
f64 tnow;
- int ret;
rt = vlib_node_get_runtime_data (vm, hicn_interest_hitcs_node.index);
@@ -116,8 +115,6 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
u16 namelen;
u32 bi0;
u32 next0 = HICN_INTEREST_HITCS_NEXT_ERROR_DROP;
- hicn_name_t name;
- hicn_header_t *hicn0;
hicn_buffer_t *hicnb0;
hicn_hash_node_t *node0;
hicn_pcs_entry_t *pitp;
@@ -150,8 +147,8 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hicn_get_internal_state (hicnb0, rt->pitcs, &node0, &strategy_vft0,
&dpo_vft0, &dpo_ctx_id0, &hash_entry0);
- ret = hicn_interest_parse_pkt (b0, &name, &namelen, &hicn0, &isv6);
- nameptr = (u8 *) (&name);
+ hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen);
+ isv6 = hicn_buffer_is_v6 (b0);
pitp = hicn_pit_get_data (node0);
dpo_id_t hicn_dpo_id0 = { .dpoi_type =
@@ -160,8 +157,7 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
.dpoi_next_node = 0,
.dpoi_index = dpo_ctx_id0 };
- if (PREDICT_FALSE (ret != HICN_ERROR_NONE ||
- !hicn_node_compare (nameptr, namelen, node0)))
+ if (PREDICT_FALSE (!hicn_node_compare (nameptr, namelen, node0)))
{
/* Remove lock from the entry */
hicn_pcs_remove_lock (rt->pitcs, &pitp, &node0, vm, hash_entry0,
@@ -209,7 +205,7 @@ hicn_interest_hitcs_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
{
hicn_interest_hitcs_trace_t *t =
vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = HICN_PKT_TYPE_INTEREST;
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST;
t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
t->next_index = next0;
}
@@ -285,4 +281,4 @@ VLIB_REGISTER_NODE (hicn_interest_hitcs_node) = {
* fd.io coding-style-patch-verification: ON
*
* Local Variables: eval: (c-set-style "gnu") End:
- */
+ */ \ No newline at end of file
diff --git a/hicn-plugin/src/interest_hitpit.h b/hicn-plugin/src/interest_hitpit.h
index 18ef94aa7..46659e67c 100644
--- a/hicn-plugin/src/interest_hitpit.h
+++ b/hicn-plugin/src/interest_hitpit.h
@@ -46,7 +46,7 @@ typedef struct
{
u32 next_index;
u32 sw_if_index;
- u8 pkt_type;
+ u32 pkt_type;
} hicn_interest_hitpit_trace_t;
typedef enum
@@ -65,4 +65,4 @@ typedef enum
* fd.io coding-style-patch-verification: ON
*
* Local Variables: eval: (c-set-style "gnu") End:
- */
+ */ \ No newline at end of file
diff --git a/hicn-plugin/src/interest_hitpit_node.c b/hicn-plugin/src/interest_hitpit_node.c
index 33dc782cd..c98baf7e9 100644
--- a/hicn-plugin/src/interest_hitpit_node.c
+++ b/hicn-plugin/src/interest_hitpit_node.c
@@ -79,8 +79,6 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
u16 namelen;
u32 bi0;
u32 next0 = HICN_INTEREST_HITPIT_NEXT_ERROR_DROP;
- hicn_name_t name;
- hicn_header_t *hicn0;
hicn_hash_node_t *node0;
const hicn_strategy_vft_t *strategy_vft0;
const hicn_dpo_vft_t *dpo_vft0;
@@ -92,7 +90,6 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
u32 outfaces_len;
hicn_hash_entry_t *hash_entry0;
hicn_buffer_t *hicnb0;
- int ret;
/* Prefetch for next iteration. */
if (n_left_from > 1)
@@ -118,8 +115,9 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hicn_get_internal_state (hicnb0, rt->pitcs, &node0, &strategy_vft0,
&dpo_vft0, &dpo_ctx_id0, &hash_entry0);
- ret = hicn_interest_parse_pkt (b0, &name, &namelen, &hicn0, &isv6);
- nameptr = (u8 *) (&name);
+ hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen);
+ isv6 = hicn_buffer_is_v6 (b0);
+
pitp = hicn_pit_get_data (node0);
dpo_id_t hicn_dpo_id0 = { .dpoi_type =
dpo_vft0->hicn_dpo_get_type (),
@@ -131,8 +129,7 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
* Check if the hit is instead a collision in the
* hash table. Unlikely to happen.
*/
- if (PREDICT_FALSE (ret != HICN_ERROR_NONE ||
- !hicn_node_compare (nameptr, namelen, node0)))
+ if (PREDICT_FALSE (!hicn_node_compare (nameptr, namelen, node0)))
{
stats.interests_hash_collision++;
/* Remove lock from the entry */
@@ -227,7 +224,7 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hicn_interest_hitpit_trace_t *t =
vlib_add_trace (vm, node, local_b0,
sizeof (*t));
- t->pkt_type = HICN_PKT_TYPE_INTEREST;
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST;
t->sw_if_index = vnet_buffer (local_b0)
->sw_if_index[VLIB_RX];
t->next_index = next0;
@@ -266,7 +263,7 @@ hicn_interest_hitpit_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
{
hicn_interest_hitpit_trace_t *t =
vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = HICN_PKT_TYPE_INTEREST;
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST;
t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
t->next_index = next0;
}
@@ -354,4 +351,4 @@ VLIB_REGISTER_NODE(hicn_interest_hitpit_node) =
* fd.io coding-style-patch-verification: ON
*
* Local Variables: eval: (c-set-style "gnu") End:
- */
+ */ \ No newline at end of file
diff --git a/hicn-plugin/src/interest_pcslookup_node.c b/hicn-plugin/src/interest_pcslookup_node.c
index ff0da12d7..e569573b7 100644
--- a/hicn-plugin/src/interest_pcslookup_node.c
+++ b/hicn-plugin/src/interest_pcslookup_node.c
@@ -57,7 +57,6 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
hicn_interest_pcslookup_next_t next_index;
hicn_interest_pcslookup_runtime_t *rt;
vl_api_hicn_api_node_stats_get_reply_t stats = { 0 };
- int ret;
rt = vlib_node_get_runtime_data (vm, hicn_interest_pcslookup_node.index);
@@ -76,14 +75,11 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
while (n_left_from > 0 && n_left_to_next > 0)
{
vlib_buffer_t *b0;
- u8 isv6;
u8 *nameptr;
u16 namelen;
u32 bi0;
u32 next0 = HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP;
u64 name_hash = 0;
- hicn_name_t name;
- hicn_header_t *hicn0;
u32 node_id0 = 0;
index_t dpo_ctx_id0 = 0;
u8 vft_id0 = 0;
@@ -109,19 +105,15 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
n_left_to_next -= 1;
b0 = vlib_get_buffer (vm, bi0);
- ret = hicn_interest_parse_pkt (b0, &name, &namelen, &hicn0, &isv6);
- if (PREDICT_TRUE (ret == HICN_ERROR_NONE))
- {
- next0 = HICN_INTEREST_PCSLOOKUP_NEXT_STRATEGY;
- }
- nameptr = (u8 *) (&name);
+ hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen);
+
+ next0 = HICN_INTEREST_PCSLOOKUP_NEXT_STRATEGY;
stats.pkts_processed++;
if (PREDICT_FALSE (
- ret != HICN_ERROR_NONE ||
hicn_hashtb_fullhash (nameptr, namelen, &name_hash) !=
- HICN_ERROR_NONE))
+ HICN_ERROR_NONE))
{
next0 = HICN_INTEREST_PCSLOOKUP_NEXT_ERROR_DROP;
}
@@ -149,7 +141,7 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
{
hicn_interest_pcslookup_trace_t *t =
vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = HICN_PKT_TYPE_INTEREST;
+ t->pkt_type = HICN_PACKET_TYPE_INTEREST;
t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
t->next_index = next0;
}
@@ -226,4 +218,4 @@ VLIB_REGISTER_NODE(hicn_interest_pcslookup_node) =
* fd.io coding-style-patch-verification: ON
*
* Local Variables: eval: (c-set-style "gnu") End:
- */
+ */ \ No newline at end of file
diff --git a/hicn-plugin/src/parser.h b/hicn-plugin/src/parser.h
index 0e60c526f..29405ebec 100644
--- a/hicn-plugin/src/parser.h
+++ b/hicn-plugin/src/parser.h
@@ -25,93 +25,149 @@
* @file parser.h
*/
-/*
- * Key type codes for header, header tlvs, body tlvs, and child tlvs
- */
-
-// FIXME(reuse lib struct, no more control ?)
-enum hicn_pkt_type_e
-{
- HICN_PKT_TYPE_INTEREST = 0,
- HICN_PKT_TYPE_CONTENT = 1,
-};
-
/**
- * @brief Parse an interest packet
+ * @brief Parse a interest packet
*
* @param pkt vlib buffer holding the interest
- * @param name return variable that will point to the hicn name
- * @param namelen return valiable that will hold the length of the name
- * @param pkt_hdrp return valiable that will point to the packet header
- * @param isv6 return variable that will be equale to 1 is the header is ipv6
+ * @param name [RETURNED] variable that will point to the hicn name
+ * @param namelen [RETURNED] variable that will hold the length of the name
+ * @param port [RETURNED] variable that will hold the source port of the packet
+ * @param pkt_hdrp [RETURNED] valiable that will point to the packet header
+ * @param isv6 [RETURNED] variable that will be equale to 1 is the header is
+ * ipv6
*/
always_inline int
-hicn_interest_parse_pkt (vlib_buffer_t *pkt, hicn_name_t *name, u16 *namelen,
- hicn_header_t **pkt_hdrp, u8 *isv6)
+hicn_interest_parse_pkt (vlib_buffer_t *pkt)
{
if (pkt == NULL)
return HICN_ERROR_PARSER_PKT_INVAL;
- hicn_header_t *pkt_hdr = vlib_buffer_get_current (pkt);
- *pkt_hdrp = pkt_hdr;
- u8 *ip_pkt = vlib_buffer_get_current (pkt);
- *isv6 = hicn_is_v6 (pkt_hdr);
- u8 ip_proto = (*isv6) * IPPROTO_IPV6;
- u8 next_proto_offset = 6 + (1 - *isv6) * 3;
- // in the ipv6 header the next header field is at byte 6
- // in the ipv4 header the protocol field is at byte 9
- hicn_type_t type =
- (hicn_type_t){ { .l4 = IPPROTO_NONE,
- .l3 = ip_pkt[next_proto_offset] == IPPROTO_UDP ?
- IPPROTO_ENCAP :
- IPPROTO_NONE,
- .l2 = ip_pkt[next_proto_offset],
- .l1 = ip_proto } };
+
+ int ret = HICN_LIB_ERROR_NONE;
+
+ hicn_header_t *pkt_hdr;
+ u8 *ip_pkt;
+ u8 ip_proto;
+ u8 next_proto_offset;
+ hicn_type_t type;
+ hicn_name_t *name;
+ u16 *port;
+ int isv6;
+
+ // start parsing first fields to get the protocols
+ pkt_hdr = vlib_buffer_get_current (pkt);
+ isv6 = hicn_is_v6 (pkt_hdr);
+
+ ip_pkt = vlib_buffer_get_current (pkt);
+ ip_proto = (1 - isv6) * IPPROTO_IP + (isv6) *IPPROTO_IPV6;
+
+ // in the ipv6 header the next header field is at byte 6 in the ipv4
+ // header the protocol field is at byte 9
+ next_proto_offset = 6 + (1 - isv6) * 3;
+
+ // get type info
+ type.l4 = IPPROTO_NONE;
+ type.l3 =
+ ip_pkt[next_proto_offset] == IPPROTO_UDP ? IPPROTO_ENCAP : IPPROTO_NONE;
+ type.l2 = ip_pkt[next_proto_offset];
+ type.l1 = ip_proto;
+
+ // cache hicn packet type in opaque2
hicn_get_buffer (pkt)->type = type;
- hicn_ops_vft[type.l1]->get_interest_name (type, &pkt_hdr->protocol, name);
- *namelen = (1 - (*isv6)) * HICN_V4_NAME_LEN + (*isv6) * HICN_V6_NAME_LEN;
+ // get name and name length
+ name = &hicn_get_buffer (pkt)->name;
+ ret =
+ hicn_ops_vft[type.l1]->get_interest_name (type, &pkt_hdr->protocol, name);
+ if (PREDICT_FALSE (ret))
+ {
+ if (type.l2 == IPPROTO_ICMPV4 || type.l2 == IPPROTO_ICMPV6)
+ {
+ return HICN_ERROR_PARSER_MAPME_PACKET;
+ }
+ return HICN_ERROR_PARSER_PKT_INVAL;
+ }
- return HICN_ERROR_NONE;
+ // get source port
+ port = &hicn_get_buffer (pkt)->port;
+ hicn_ops_vft[type.l1]->get_source_port (type, &pkt_hdr->protocol, port);
+ if (PREDICT_FALSE (ret))
+ {
+ return HICN_ERROR_PARSER_PKT_INVAL;
+ }
+
+ return ret;
}
/**
* @brief Parse a data packet
*
- * @param pkt vlib buffer holding the interest
- * @param name return variable that will point to the hicn name
- * @param namelen return valiable that will hold the length of the name
- * @param pkt_hdrp return valiable that will point to the packet header
- * @param isv6 return variable that will be equale to 1 is the header is ipv6
+ * @param pkt vlib buffer holding the data
+ * @param name [RETURNED] variable that will point to the hicn name
+ * @param namelen [RETURNED] variable that will hold the length of the name
+ * @param port [RETURNED] variable that will hold the source port of the packet
+ * @param pkt_hdrp [RETURNED] valiable that will point to the packet header
+ * @param isv6 [RETURNED] variable that will be equale to 1 is the header is
+ * ipv6
*/
always_inline int
-hicn_data_parse_pkt (vlib_buffer_t *pkt, hicn_name_t *name, u16 *namelen,
- hicn_header_t **pkt_hdrp, u8 *isv6)
+hicn_data_parse_pkt (vlib_buffer_t *pkt)
{
if (pkt == NULL)
return HICN_ERROR_PARSER_PKT_INVAL;
- hicn_header_t *pkt_hdr = vlib_buffer_get_current (pkt);
- *pkt_hdrp = pkt_hdr;
- *pkt_hdrp = pkt_hdr;
- u8 *ip_pkt = vlib_buffer_get_current (pkt);
- *isv6 = hicn_is_v6 (pkt_hdr);
- u8 ip_proto = (*isv6) * IPPROTO_IPV6;
- /*
- * in the ipv6 header the next header field is at byte 6 in the ipv4
- * header the protocol field is at byte 9
- */
- u8 next_proto_offset = 6 + (1 - *isv6) * 3;
- hicn_type_t type =
- (hicn_type_t){ { .l4 = IPPROTO_NONE,
- .l3 = ip_pkt[next_proto_offset] == IPPROTO_UDP ?
- IPPROTO_ENCAP :
- IPPROTO_NONE,
- .l2 = ip_pkt[next_proto_offset],
- .l1 = ip_proto } };
+
+ int ret = HICN_LIB_ERROR_NONE;
+
+ hicn_header_t *pkt_hdr;
+ u8 *ip_pkt;
+ u8 ip_proto;
+ int isv6;
+ u8 next_proto_offset;
+ hicn_type_t type;
+ hicn_name_t *name;
+ u16 *port;
+
+ // start parsing first fields to get the protocols
+ pkt_hdr = vlib_buffer_get_current (pkt);
+ isv6 = hicn_is_v6 (pkt_hdr);
+
+ ip_pkt = vlib_buffer_get_current (pkt);
+ ip_proto = (1 - isv6) * IPPROTO_IP + (isv6) *IPPROTO_IPV6;
+
+ // in the ipv6 header the next header field is at byte 6 in the ipv4
+ // header the protocol field is at byte 9
+ next_proto_offset = 6 + (1 - isv6) * 3;
+
+ // get type info
+ type.l4 = IPPROTO_NONE;
+ type.l3 =
+ ip_pkt[next_proto_offset] == IPPROTO_UDP ? IPPROTO_ENCAP : IPPROTO_NONE;
+ type.l2 = ip_pkt[next_proto_offset];
+ type.l1 = ip_proto;
+
+ // cache hicn packet type in opaque2
hicn_get_buffer (pkt)->type = type;
- hicn_ops_vft[type.l1]->get_data_name (type, &pkt_hdr->protocol, name);
- *namelen = (1 - (*isv6)) * HICN_V4_NAME_LEN + (*isv6) * HICN_V6_NAME_LEN;
- return HICN_ERROR_NONE;
+ // get name and name length
+ name = &hicn_get_buffer (pkt)->name;
+ ret = hicn_ops_vft[type.l1]->get_data_name (type, &pkt_hdr->protocol, name);
+ if (PREDICT_FALSE (ret))
+ {
+ if (type.l2 == IPPROTO_ICMPV4 || type.l2 == IPPROTO_ICMPV6)
+ {
+ return HICN_ERROR_PARSER_MAPME_PACKET;
+ }
+ return HICN_ERROR_PARSER_PKT_INVAL;
+ }
+
+ // get source port
+ port = &hicn_get_buffer (pkt)->port;
+ hicn_ops_vft[type.l1]->get_source_port (type, &pkt_hdr->protocol, port);
+ if (PREDICT_FALSE (ret))
+ {
+ return HICN_ERROR_PARSER_PKT_INVAL;
+ }
+
+ return ret;
}
#endif /* // __HICN_PARSER_H__ */
@@ -120,4 +176,4 @@ hicn_data_parse_pkt (vlib_buffer_t *pkt, hicn_name_t *name, u16 *namelen,
* fd.io coding-style-patch-verification: ON
*
* Local Variables: eval: (c-set-style "gnu") End:
- */
+ */ \ No newline at end of file
diff --git a/hicn-plugin/src/pg.c b/hicn-plugin/src/pg.c
index b77e8fcac..05172345b 100644
--- a/hicn-plugin/src/pg.c
+++ b/hicn-plugin/src/pg.c
@@ -18,57 +18,13 @@
#include <vnet/pg/pg.h>
#include <vnet/ip/ip.h>
#include <vnet/ethernet/ethernet.h>
+#include <vnet/fib/fib_entry_track.h>
#include "hicn.h"
#include "pg.h"
#include "parser.h"
#include "infra.h"
-
-/* Registration struct for a graph node */
-vlib_node_registration_t hicn_pg_interest_node;
-vlib_node_registration_t hicn_pg_data_node;
-
-/* Stats, which end up called "error" even though they aren't... */
-#define foreach_hicnpg_error \
- _ (PROCESSED, "hICN PG packets processed") \
- _ (DROPPED, "hICN PG packets dropped") \
- _ (INTEREST_MSGS_GENERATED, "hICN PG Interests generated") \
- _ (CONTENT_MSGS_RECEIVED, "hICN PG Content msgs received")
-
-typedef enum
-{
-#define _(sym, str) HICNPG_ERROR_##sym,
- foreach_hicnpg_error
-#undef _
- HICNPG_N_ERROR,
-} hicnpg_error_t;
-
-static char *hicnpg_error_strings[] = {
-#define _(sym, string) string,
- foreach_hicnpg_error
-#undef _
-};
-
-/*
- * Next graph nodes, which reference the list in the actual registration
- * block below
- */
-typedef enum
-{
- HICNPG_INTEREST_NEXT_V4_LOOKUP,
- HICNPG_INTEREST_NEXT_V6_LOOKUP,
- HICNPG_INTEREST_NEXT_DROP,
- HICNPG_N_NEXT,
-} hicnpg_interest_next_t;
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
- u16 msg_type;
-} hicnpg_trace_t;
+#include "route.h"
hicnpg_main_t hicnpg_main = { .index = (u32) 0,
.index_ifaces = (u32) 1,
@@ -78,1183 +34,281 @@ hicnpg_main_t hicnpg_main = { .index = (u32) 0,
.n_ifaces = (u32) 1,
.sw_if = (u32) 0 };
-hicnpg_server_main_t hicnpg_server_main = {
- .node_index = 0,
-};
-
-/* packet trace format function */
-static u8 *
-format_hicnpg_trace (u8 *s, va_list *args)
-{
- CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
- CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
- hicnpg_trace_t *t = va_arg (*args, hicnpg_trace_t *);
-
- s = format (s, "HICNPG: pkt: %d, msg %d, sw_if_index %d, next index %d",
- (int) t->pkt_type, (int) t->msg_type, t->sw_if_index,
- t->next_index);
- return (s);
-}
-
-always_inline void hicn_rewrite_interestv4 (vlib_main_t *vm, vlib_buffer_t *b0,
- u32 seq_number, u16 lifetime,
- u32 next_flow, u32 iface);
-
-always_inline void hicn_rewrite_interestv6 (vlib_main_t *vm, vlib_buffer_t *b0,
- u32 seq_number, u16 lifetime,
- u32 next_flow, u32 iface);
-
-always_inline void convert_interest_to_data_v4 (vlib_main_t *vm,
- vlib_buffer_t *b0,
- vlib_buffer_t *rb, u32 bi0);
-
-always_inline void convert_interest_to_data_v6 (vlib_main_t *vm,
- vlib_buffer_t *b0,
- vlib_buffer_t *rb, u32 bi0);
-
-always_inline void calculate_tcp_checksum_v4 (vlib_main_t *vm,
- vlib_buffer_t *b0);
+/**
+ * Pool of hicnpg_server_t
+ */
+hicnpg_server_t *hicnpg_server_pool;
-always_inline void calculate_tcp_checksum_v6 (vlib_main_t *vm,
- vlib_buffer_t *b0);
/*
- * Node function for the icn packet-generator client. The goal here is to
- * manipulate/tweak a stream of packets that have been injected by the vpp
- * packet generator to generate icn request traffic.
+ * hicnph servrer FIB node type
*/
-static uword
-hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
- vlib_frame_t *frame)
-{
- u32 n_left_from, *from, *to_next;
- hicnpg_interest_next_t next_index;
- u32 pkts_processed = 0, pkts_dropped = 0;
- u32 interest_msgs_generated = 0;
- u32 bi0, bi1;
- vlib_buffer_t *b0, *b1;
- u8 pkt_type0 = 0, pkt_type1 = 0;
- u16 msg_type0 = 0, msg_type1 = 0;
- hicn_header_t *hicn0 = NULL, *hicn1 = NULL;
- hicn_name_t name0, name1;
- u16 namelen0, namelen1;
- hicnpg_main_t *hpgm = &hicnpg_main;
- int iface = 0;
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- u32 next0 = HICNPG_INTEREST_NEXT_DROP;
- u32 next1 = HICNPG_INTEREST_NEXT_DROP;
- u32 sw_if_index0 = ~0, sw_if_index1 = ~0;
- u8 isv6_0;
- u8 isv6_1;
-
- /* Prefetch next iteration. */
- {
- vlib_buffer_t *p2, *p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, (2 * CLIB_CACHE_LINE_BYTES), STORE);
- CLIB_PREFETCH (p3->data, (2 * CLIB_CACHE_LINE_BYTES), STORE);
- }
-
- /*
- * speculatively enqueue b0 and b1 to the current
- * next frame
- */
- to_next[0] = bi0 = from[0];
- to_next[1] = bi1 = from[1];
- from += 2;
- to_next += 2;
- n_left_from -= 2;
- n_left_to_next -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
- vnet_buffer (b0)->sw_if_index[VLIB_RX] = hpgm->sw_if;
- vnet_buffer (b1)->sw_if_index[VLIB_RX] = hpgm->sw_if;
-
- /* Check icn packets, locate names */
- if (hicn_interest_parse_pkt (b0, &name0, &namelen0, &hicn0,
- &isv6_0) == HICN_ERROR_NONE)
- {
- /* this node grabs only interests */
-
- /* Increment the appropriate message counter */
- interest_msgs_generated++;
-
- iface = (hpgm->index_ifaces % hpgm->n_ifaces);
- /* Rewrite and send */
- isv6_0 ?
- hicn_rewrite_interestv6 (
- vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
- hpgm->interest_lifetime, hpgm->index % hpgm->n_flows,
- iface) :
- hicn_rewrite_interestv4 (
- vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
- hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface);
-
- hpgm->index_ifaces++;
- if (iface == (hpgm->n_ifaces - 1))
- hpgm->index++;
-
- next0 = isv6_0 ? HICNPG_INTEREST_NEXT_V6_LOOKUP :
- HICNPG_INTEREST_NEXT_V4_LOOKUP;
- }
- if (hicn_interest_parse_pkt (b1, &name1, &namelen1, &hicn1,
- &isv6_1) == HICN_ERROR_NONE)
- {
- /* this node grabs only interests */
-
- /* Increment the appropriate message counter */
- interest_msgs_generated++;
-
- iface = (hpgm->index_ifaces % hpgm->n_ifaces);
- /* Rewrite and send */
- isv6_1 ?
- hicn_rewrite_interestv6 (
- vm, b1, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
- hpgm->interest_lifetime, hpgm->index % hpgm->n_flows,
- iface) :
- hicn_rewrite_interestv4 (
- vm, b1, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
- hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface);
-
- hpgm->index_ifaces++;
- if (iface == (hpgm->n_ifaces - 1))
- hpgm->index++;
-
- next1 = isv6_1 ? HICNPG_INTEREST_NEXT_V6_LOOKUP :
- HICNPG_INTEREST_NEXT_V4_LOOKUP;
- }
- /* Send pkt to next node */
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
- vnet_buffer (b1)->sw_if_index[VLIB_TX] = ~0;
-
- pkts_processed += 2;
-
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
- {
- if (b0->flags & VLIB_BUFFER_IS_TRACED)
- {
- hicnpg_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = pkt_type0;
- t->msg_type = msg_type0;
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- }
- if (b1->flags & VLIB_BUFFER_IS_TRACED)
- {
- hicnpg_trace_t *t =
- vlib_add_trace (vm, node, b1, sizeof (*t));
- t->pkt_type = pkt_type1;
- t->msg_type = msg_type1;
- t->sw_if_index = sw_if_index1;
- t->next_index = next1;
- }
- }
- if (next0 == HICNPG_INTEREST_NEXT_DROP)
- {
- pkts_dropped++;
- }
- if (next1 == HICNPG_INTEREST_NEXT_DROP)
- {
- pkts_dropped++;
- }
- /*
- * verify speculative enqueues, maybe switch current
- * next frame
- */
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
- n_left_to_next, bi0, bi1, next0,
- next1);
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 next0 = HICNPG_INTEREST_NEXT_DROP;
- u32 sw_if_index0;
- u8 isv6_0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- vnet_buffer (b0)->sw_if_index[VLIB_RX] = hpgm->sw_if;
-
- /* Check icn packets, locate names */
- if (hicn_interest_parse_pkt (b0, &name0, &namelen0, &hicn0,
- &isv6_0) == HICN_ERROR_NONE)
- {
- /* this node grabs only interests */
-
- /* Increment the appropriate message counter */
- interest_msgs_generated++;
-
- iface = (hpgm->index_ifaces % hpgm->n_ifaces);
-
- /* Rewrite and send */
- isv6_0 ?
- hicn_rewrite_interestv6 (
- vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
- hpgm->interest_lifetime, hpgm->index % hpgm->n_flows,
- iface) :
- hicn_rewrite_interestv4 (
- vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
- hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface);
-
- hpgm->index_ifaces++;
- if (iface == (hpgm->n_ifaces - 1))
- hpgm->index++;
-
- next0 = isv6_0 ? HICNPG_INTEREST_NEXT_V6_LOOKUP :
- HICNPG_INTEREST_NEXT_V4_LOOKUP;
- }
- /* Send pkt to ip lookup */
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
+fib_node_type_t hicnpg_server_fib_node_type;
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
- (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- hicnpg_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = pkt_type0;
- t->msg_type = msg_type0;
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- }
- pkts_processed += 1;
-
- if (next0 == HICNPG_INTEREST_NEXT_DROP)
- {
- pkts_dropped++;
- }
- /*
- * verify speculative enqueue, maybe switch current
- * next frame
- */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- vlib_node_increment_counter (vm, hicn_pg_interest_node.index,
- HICNPG_ERROR_PROCESSED, pkts_processed);
- vlib_node_increment_counter (vm, hicn_pg_interest_node.index,
- HICNPG_ERROR_DROPPED, pkts_dropped);
- vlib_node_increment_counter (vm, hicn_pg_interest_node.index,
- HICNPG_ERROR_INTEREST_MSGS_GENERATED,
- interest_msgs_generated);
+/**
+ * Registered DPO type.
+ */
+dpo_type_t hicnpg_server_dpo_type;
- return (frame->n_vectors);
+static void
+hicnpg_server_restack (hicnpg_server_t *hicnpg_server)
+{
+ dpo_stack (
+ hicnpg_server_dpo_type, fib_proto_to_dpo (hicnpg_server->prefix.fp_proto),
+ &hicnpg_server->dpo,
+ fib_entry_contribute_ip_forwarding (hicnpg_server->fib_entry_index));
}
-void
-hicn_rewrite_interestv4 (vlib_main_t *vm, vlib_buffer_t *b0, u32 seq_number,
- u16 interest_lifetime, u32 next_flow, u32 iface)
+static hicnpg_server_t *
+hicnpg_server_from_fib_node (fib_node_t *node)
{
- hicn_header_t *h0 = vlib_buffer_get_current (b0);
-
- /* Generate the right src and dst corresponding to flow and iface */
- ip46_address_t src_addr = {
- .ip4 = hicnpg_main.pgen_clt_src_addr.ip4,
- };
- hicn_name_t dst_name = {
- .prefix.ip4 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip4,
- .suffix = seq_number,
- };
-
- src_addr.ip4.as_u32 += clib_host_to_net_u32 (iface);
- dst_name.prefix.ip4.as_u32 += clib_net_to_host_u32 (next_flow);
-
- /* Update locator and name */
- hicn_type_t type = hicn_get_buffer (b0)->type;
- HICN_OPS4->set_interest_locator (type, &h0->protocol, &src_addr);
- HICN_OPS4->set_interest_name (type, &h0->protocol, &dst_name);
-
- /* Update lifetime (currently L4 checksum is not updated) */
- HICN_OPS4->set_lifetime (type, &h0->protocol, interest_lifetime);
-
- /* Update checksums */
- HICN_OPS4->update_checksums (type, &h0->protocol, 0, 0);
+ ASSERT (hicnpg_server_fib_node_type == node->fn_type);
+ return ((hicnpg_server_t *) (((char *) node) -
+ STRUCT_OFFSET_OF (hicnpg_server_t, fib_node)));
}
/**
- * @brief Rewrite the IPv6 header as the next generated packet
- *
- * Set up a name prefix
- * - etiher generate interest in which the name varies only after the prefix
- * (inc : seq_number), then the flow acts on the prefix (CHECK)
- * seq_number => TCP, FLOW =>
- *
- * SRC : pgen_clt_src_addr.ip6 DST = generate name (pgen_clt_hicn_name.ip6)
- * ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff
- * \__/ \__/
- * +iface + flow
- * Source is used to emulate different consumers.
- * FIXME iface is ill-named, better name it consumer id
- * Destination is used to iterate on the content.
+ * Function definition to backwalk a FIB node
*/
-void
-hicn_rewrite_interestv6 (vlib_main_t *vm, vlib_buffer_t *b0, u32 seq_number,
- u16 interest_lifetime, u32 next_flow, u32 iface)
+static fib_node_back_walk_rc_t
+hicnpg_server_fib_back_walk (fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
{
- hicn_header_t *h0 = vlib_buffer_get_current (b0);
-
- /* Generate the right src and dst corresponding to flow and iface */
- ip46_address_t src_addr = {
- .ip6 = hicnpg_main.pgen_clt_src_addr.ip6,
- };
- hicn_name_t dst_name = {
- .prefix.ip6 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip6,
- .suffix = seq_number,
- };
- src_addr.ip6.as_u32[3] += clib_host_to_net_u32 (iface);
- dst_name.prefix.ip6.as_u32[3] += clib_net_to_host_u32 (next_flow);
+ hicnpg_server_restack (hicnpg_server_from_fib_node (node));
- /* Update locator and name */
- hicn_type_t type = hicn_get_buffer (b0)->type;
- HICN_OPS6->set_interest_locator (type, &h0->protocol, &src_addr);
- HICN_OPS6->set_interest_name (type, &h0->protocol, &dst_name);
-
- /* Update lifetime */
- HICN_OPS6->set_lifetime (type, &h0->protocol, interest_lifetime);
-
- /* Update checksums */
- calculate_tcp_checksum_v6 (vm, b0);
+ return FIB_NODE_BACK_WALK_CONTINUE;
}
-void
-calculate_tcp_checksum_v4 (vlib_main_t *vm, vlib_buffer_t *b0)
+/**
+ * Function definition to get a FIB node from its index
+ */
+static fib_node_t *
+hicnpg_server_fib_node_get (fib_node_index_t index)
{
- ip4_header_t *ip0;
- tcp_header_t *tcp0;
- ip_csum_t sum0;
- u32 tcp_len0;
-
- ip0 = (ip4_header_t *) (vlib_buffer_get_current (b0));
- tcp0 =
- (tcp_header_t *) (vlib_buffer_get_current (b0) + sizeof (ip4_header_t));
- tcp_len0 = clib_net_to_host_u16 (ip0->length) - sizeof (ip4_header_t);
-
- /* Initialize checksum with header. */
- if (BITS (sum0) == 32)
- {
- sum0 = clib_mem_unaligned (&ip0->src_address, u32);
- sum0 =
- ip_csum_with_carry (sum0, clib_mem_unaligned (&ip0->dst_address, u32));
- }
- else
- sum0 = clib_mem_unaligned (&ip0->src_address, u64);
-
- sum0 = ip_csum_with_carry (
- sum0, clib_host_to_net_u32 (tcp_len0 + (ip0->protocol << 16)));
-
- /* Invalidate possibly old checksum. */
- tcp0->checksum = 0;
+ hicnpg_server_t *hpg_server;
- u32 tcp_offset = sizeof (ip4_header_t);
- sum0 = ip_incremental_checksum_buffer (vm, b0, tcp_offset, tcp_len0, sum0);
+ hpg_server = pool_elt_at_index (hicnpg_server_pool, index);
- tcp0->checksum = ~ip_csum_fold (sum0);
+ return (&hpg_server->fib_node);
}
-void
-calculate_tcp_checksum_v6 (vlib_main_t *vm, vlib_buffer_t *b0)
+/**
+ * Function definition to inform the FIB node that its last lock has gone.
+ */
+static void
+hicnpg_server_fib_last_lock_gone (fib_node_t *node)
{
- ip6_header_t *ip0;
- tcp_header_t *tcp0;
- ip_csum_t sum0;
- u32 tcp_len0;
-
- ip0 = (ip6_header_t *) (vlib_buffer_get_current (b0));
- tcp0 =
- (tcp_header_t *) (vlib_buffer_get_current (b0) + sizeof (ip6_header_t));
- tcp_len0 = clib_net_to_host_u16 (ip0->payload_length);
+ hicnpg_server_t *hpg_server;
- /* Initialize checksum with header. */
- if (BITS (sum0) == 32)
- {
- sum0 = clib_mem_unaligned (&ip0->src_address, u32);
- sum0 =
- ip_csum_with_carry (sum0, clib_mem_unaligned (&ip0->dst_address, u32));
- }
- else
- sum0 = clib_mem_unaligned (&ip0->src_address, u64);
-
- sum0 = ip_csum_with_carry (
- sum0, clib_host_to_net_u32 (tcp_len0 + (ip0->protocol << 16)));
+ hpg_server = hicnpg_server_from_fib_node (node);
- /* Invalidate possibly old checksum. */
- tcp0->checksum = 0;
-
- u32 tcp_offset = sizeof (ip6_header_t);
- sum0 = ip_incremental_checksum_buffer (vm, b0, tcp_offset, tcp_len0, sum0);
+ /**
+ * reset the stacked DPO to unlock it
+ */
+ dpo_reset (&hpg_server->dpo);
- tcp0->checksum = ~ip_csum_fold (sum0);
+ pool_put (hicnpg_server_pool, hpg_server);
}
-VLIB_REGISTER_NODE (hicn_pg_interest_node) = {
- .function = hicnpg_client_interest_node_fn,
- .name = "hicnpg-interest",
- .vector_size = sizeof (u32),
- .format_trace = format_hicnpg_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN (hicnpg_error_strings),
- .error_strings = hicnpg_error_strings,
- .n_next_nodes = HICNPG_N_NEXT,
- .next_nodes = { [HICNPG_INTEREST_NEXT_V4_LOOKUP] = "ip4-lookup",
- [HICNPG_INTEREST_NEXT_V6_LOOKUP] = "ip6-lookup",
- [HICNPG_INTEREST_NEXT_DROP] = "error-drop" },
-};
-
-/*
- * Next graph nodes, which reference the list in the actual registration
- * block below
- */
-typedef enum
-{
- HICNPG_DATA_NEXT_DROP,
- HICNPG_DATA_NEXT_LOOKUP4,
- HICNPG_DATA_NEXT_LOOKUP6,
- HICNPG_DATA_N_NEXT,
-} hicnpg_data_next_t;
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
- u16 msg_type;
-} icnpg_data_trace_t;
-
-/* packet trace format function */
-static u8 *
-format_hicnpg_data_trace (u8 *s, va_list *args)
+static void
+hicnpg_server_dpo_lock (dpo_id_t *dpo)
{
- CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
- CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
- hicnpg_trace_t *t = va_arg (*args, hicnpg_trace_t *);
-
- s = format (s, "HICNPG: pkt: %d, msg %d, sw_if_index %d, next index %d",
- (int) t->pkt_type, (int) t->msg_type, t->sw_if_index,
- t->next_index);
- return (s);
+ hicnpg_server_t *hpg_server;
+ hpg_server = hicnpg_server_get (dpo->dpoi_index);
+ fib_node_lock (&hpg_server->fib_node);
}
-static_always_inline int
-match_ip4_name (u32 *name, fib_prefix_t *prefix)
+static void
+hicnpg_server_dpo_unlock (dpo_id_t *dpo)
{
- u32 xor = 0;
-
- xor = *name & prefix->fp_addr.ip4.data_u32;
-
- return xor == prefix->fp_addr.ip4.data_u32;
+ hicnpg_server_t *hpg_server;
+ hpg_server = hicnpg_server_get (dpo->dpoi_index);
+ fib_node_unlock (&hpg_server->fib_node);
}
-static_always_inline int
-match_ip6_name (u8 *name, fib_prefix_t *prefix)
+static u8 *
+format_hicnpg_server_i (u8 *s, va_list *args)
{
- union
- {
- u32x4 as_u32x4;
- u64 as_u64[2];
- u32 as_u32[4];
- } xor_sum __attribute__ ((aligned (sizeof (u32x4))));
+ index_t hicnpg_server_i = va_arg (*args, index_t);
+ // u32 indent = va_arg (*args, u32);
+ u32 details = va_arg (*args, u32);
+ // vlib_counter_t to;
+ hicnpg_server_t *hpg;
- xor_sum.as_u64[0] = ((u64 *) name)[0] & prefix->fp_addr.ip6.as_u64[0];
- xor_sum.as_u64[1] = ((u64 *) name)[1] & prefix->fp_addr.ip6.as_u64[1];
+ hpg = hicnpg_server_get (hicnpg_server_i);
- return (xor_sum.as_u64[0] == prefix->fp_addr.ip6.as_u64[0]) &&
- (xor_sum.as_u64[1] == prefix->fp_addr.ip6.as_u64[1]);
-}
-
-/*
- * Return 0,1,2.
- * 0 matches
- * 1 does not match and the prefix is ip4
- * 2 does not match and the prefix is ip6
- */
-static_always_inline u32
-match_data (vlib_buffer_t *b, fib_prefix_t *prefix)
-{
- u8 *ptr = vlib_buffer_get_current (b);
- u8 v = *ptr & 0xf0;
- u32 next = 0;
+ // FIXME
+ s = format (s, "dpo-hicnpg-server:[%d]: ip-fib-index:%d ", hicnpg_server_i,
+ hpg->fib_index);
- if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr)))
+ if (FIB_PROTOCOL_IP4 == hpg->prefix.fp_proto)
{
- if (!match_ip4_name ((u32 *) &(ptr[12]), prefix))
- next = 1;
+ s = format (s, "protocol:FIB_PROTOCOL_IP4 prefix: %U",
+ format_fib_prefix, &hpg->prefix);
}
- else if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr)))
+ else
{
- if (!match_ip6_name (&(ptr[8]), prefix))
- next = 2;
+ s = format (s, "protocol:FIB_PROTOCOL_IP6 prefix: %U",
+ format_fib_prefix, &hpg->prefix);
}
- return next;
-}
-
-/*
- * Return 0,1,2.
- * 0 matches
- * 1 does not match and the prefix is ip4
- * 2 does not match and the prefix is ip6
- */
-static_always_inline u32
-match_interest (vlib_buffer_t *b, fib_prefix_t *prefix)
-{
- u8 *ptr = vlib_buffer_get_current (b);
- u8 v = *ptr & 0xf0;
- u32 next = 0;
+#if 0
+ vlib_get_combined_counter (&(udp_encap_counters), uei, &to);
+ s = format (s, " to:[%Ld:%Ld]]", to.packets, to.bytes);s
+#endif
- if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->fp_addr)))
- {
- if (!match_ip4_name ((u32 *) &(ptr[16]), prefix))
- next = 1;
- }
- else if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->fp_addr)))
+ if (details)
{
- if (!match_ip6_name (&(ptr[24]), prefix))
- next = 2;
+ s = format (s, " locks:%d", hpg->fib_node.fn_locks);
+ // s = format (s, "\n%UStacked on:", format_white_space, indent +
+ // 1); s = format (s, "\n%U%U", format_white_space, indent + 2,
+ // format_dpo_id,
+ // &hpg->dpo, indent + 3);
}
- return next;
+ return s;
}
-/*
- * Node function for the icn packet-generator client. The goal here is to
- * manipulate/tweak a stream of packets that have been injected by the vpp
- * packet generator to generate icn request traffic.
- */
-static uword
-hicnpg_client_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
- vlib_frame_t *frame)
+static u8 *
+format_hicnpg_server_dpo (u8 *s, va_list *args)
{
- u32 n_left_from, *from, *to_next;
- hicnpg_data_next_t next_index;
- u32 pkts_processed = 0;
- u32 content_msgs_received = 0;
- u32 bi0, bi1;
- vlib_buffer_t *b0, *b1;
- u8 pkt_type0 = 0, pkt_type1 = 0;
- u16 msg_type0 = 1, msg_type1 = 1;
- hicnpg_main_t *hpgm = &hicnpg_main;
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- u32 next0 = HICNPG_DATA_NEXT_DROP;
- u32 next1 = HICNPG_DATA_NEXT_DROP;
- u32 sw_if_index0, sw_if_index1;
-
- /* Prefetch next iteration. */
- {
- vlib_buffer_t *p2, *p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, (2 * CLIB_CACHE_LINE_BYTES), STORE);
- CLIB_PREFETCH (p3->data, (2 * CLIB_CACHE_LINE_BYTES), STORE);
- }
-
- /*
- * speculatively enqueue b0 and b1 to the current
- * next frame
- */
- to_next[0] = bi0 = from[0];
- to_next[1] = bi1 = from[1];
- from += 2;
- to_next += 2;
- n_left_from -= 2;
- n_left_to_next -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
-
- next0 =
- HICNPG_DATA_NEXT_DROP + match_data (b0, hpgm->pgen_clt_hicn_name);
- next1 =
- HICNPG_DATA_NEXT_DROP + match_data (b1, hpgm->pgen_clt_hicn_name);
-
- if (PREDICT_FALSE (vnet_get_feature_count (
- vnet_buffer (b0)->feature_arc_index,
- vnet_buffer (b0)->sw_if_index[VLIB_RX]) > 1))
- vnet_feature_next (&next0, b0);
-
- if (PREDICT_FALSE (vnet_get_feature_count (
- vnet_buffer (b1)->feature_arc_index,
- vnet_buffer (b1)->sw_if_index[VLIB_RX]) > 1))
- vnet_feature_next (&next1, b1);
-
- if (next0 == HICNPG_DATA_NEXT_DROP)
- {
- /* Increment a counter */
- content_msgs_received++;
- }
-
- if (next1 == HICNPG_DATA_NEXT_DROP)
- {
- /* Increment a counter */
- content_msgs_received++;
- }
-
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
- {
- if (b0->flags & VLIB_BUFFER_IS_TRACED)
- {
- icnpg_data_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = pkt_type0;
- t->msg_type = msg_type0;
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- }
- if (b1->flags & VLIB_BUFFER_IS_TRACED)
- {
- icnpg_data_trace_t *t =
- vlib_add_trace (vm, node, b1, sizeof (*t));
- t->pkt_type = pkt_type1;
- t->msg_type = msg_type1;
- t->sw_if_index = sw_if_index1;
- t->next_index = next1;
- }
- }
-
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
- n_left_to_next, bi0, bi1, next0,
- next1);
- pkts_processed += 2;
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 next0 = HICNPG_DATA_NEXT_DROP;
- u32 sw_if_index0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
-
- next0 =
- HICNPG_DATA_NEXT_DROP + match_data (b0, hpgm->pgen_clt_hicn_name);
-
- if (PREDICT_FALSE (vnet_get_feature_count (
- vnet_buffer (b0)->feature_arc_index,
- vnet_buffer (b0)->sw_if_index[VLIB_RX]) > 1))
- vnet_feature_next (&next0, b0);
+ index_t hpg_server_i = va_arg (*args, index_t);
+ u32 indent = va_arg (*args, u32);
- if (next0 == HICNPG_DATA_NEXT_DROP)
- {
- /* Increment a counter */
- content_msgs_received++;
- }
-
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
- (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- icnpg_data_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = pkt_type0;
- t->msg_type = msg_type0;
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- }
-
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
-
- pkts_processed++;
- }
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- vlib_node_increment_counter (vm, hicn_pg_data_node.index,
- HICNPG_ERROR_PROCESSED, pkts_processed);
- vlib_node_increment_counter (vm, hicn_pg_data_node.index,
- HICNPG_ERROR_CONTENT_MSGS_RECEIVED,
- content_msgs_received);
- return (frame->n_vectors);
+ return (format (s, "%U", format_hicnpg_server_i, hpg_server_i, indent, 1));
}
-VLIB_REGISTER_NODE(hicn_pg_data_node) =
-{
- .function = hicnpg_client_data_node_fn,
- .name = "hicnpg-data",
- .vector_size = sizeof(u32),
- .format_trace = format_hicnpg_data_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(hicnpg_error_strings),
- .error_strings = hicnpg_error_strings,
- .n_next_nodes = HICNPG_DATA_N_NEXT,
- .next_nodes =
- {
- [HICNPG_DATA_NEXT_DROP] = "error-drop",
- [HICNPG_DATA_NEXT_LOOKUP4] = "ip4-lookup",
- [HICNPG_DATA_NEXT_LOOKUP6] = "ip6-lookup",
- },
+/*
+ * Virtual function table registered by hicn pg server
+ * for participation in the FIB object graph.
+ */
+const static fib_node_vft_t hicnpg_server_fib_vft = {
+ .fnv_get = hicnpg_server_fib_node_get,
+ .fnv_last_lock = hicnpg_server_fib_last_lock_gone,
+ .fnv_back_walk = hicnpg_server_fib_back_walk,
};
-VNET_FEATURE_INIT (hicn_data_input_ip4_arc, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "hicnpg-data",
- .runs_before = VNET_FEATURES ("ip4-inacl"),
+const static dpo_vft_t hicnpg_server_dpo_vft = {
+ .dv_lock = hicnpg_server_dpo_lock,
+ .dv_unlock = hicnpg_server_dpo_unlock,
+ .dv_format = format_hicnpg_server_dpo,
};
-VNET_FEATURE_INIT (hicn_data_input_ip6_arc, static) = {
- .arc_name = "ip6-unicast",
- .node_name = "hicnpg-data",
- .runs_before = VNET_FEATURES ("ip6-inacl"),
+const static char *const hicnpg_server_ip4_nodes[] = {
+ "hicnpg-server-4",
+ NULL,
};
-/*
- * End of packet-generator client node
- */
-
-/*
- * Beginning of packet-generation server node
- */
-
-/* Registration struct for a graph node */
-vlib_node_registration_t hicn_pg_server_node;
-
-/* Stats, which end up called "error" even though they aren't... */
-#define foreach_icnpg_server_error \
- _ (PROCESSED, "hICN PG Server packets processed") \
- _ (DROPPED, "hICN PG Server packets dropped")
-
-typedef enum
-{
-#define _(sym, str) HICNPG_SERVER_ERROR_##sym,
- foreach_icnpg_server_error
-#undef _
- HICNPG_SERVER_N_ERROR,
-} icnpg_server_error_t;
-
-static char *icnpg_server_error_strings[] = {
-#define _(sym, string) string,
- foreach_icnpg_server_error
-#undef _
+const static char *const hicnpg_server_ip6_nodes[] = {
+ "hicnpg-server-6",
+ NULL,
};
-/*
- * Next graph nodes, which reference the list in the actual registration
- * block below
- */
-typedef enum
-{
- HICNPG_SERVER_NEXT_V4_LOOKUP,
- HICNPG_SERVER_NEXT_V6_LOOKUP,
- HICNPG_SERVER_NEXT_DROP,
- HICNPG_SERVER_N_NEXT,
-} icnpg_server_next_t;
-
-/* Trace context struct */
-typedef struct
-{
- u32 next_index;
- u32 sw_if_index;
- u8 pkt_type;
- u16 msg_type;
-} hicnpg_server_trace_t;
+const static char *const *const hicnpg_server_nodes[DPO_PROTO_NUM] = {
+ [DPO_PROTO_IP4] = hicnpg_server_ip4_nodes,
+ [DPO_PROTO_IP6] = hicnpg_server_ip6_nodes
+};
-/* packet trace format function */
-static u8 *
-format_icnpg_server_trace (u8 *s, va_list *args)
+clib_error_t *
+hicnpg_server_add_and_lock (fib_prefix_t *prefix, u32 *hicnpg_server_index,
+ ip46_address_t *locator, size_t payload_size)
{
- CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
- CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
- hicnpg_server_trace_t *t = va_arg (*args, hicnpg_server_trace_t *);
+ hicnpg_server_t *hpg;
+ index_t hpgi;
+ u32 fib_index;
+ fib_node_index_t fib_entry_index;
+ u32 buffer_index;
+ vlib_buffer_t *rb = NULL;
- s = format (
- s, "HICNPG SERVER: pkt: %d, msg %d, sw_if_index %d, next index %d",
- (int) t->pkt_type, (int) t->msg_type, t->sw_if_index, t->next_index);
- return (s);
-}
+ // Retrieve hicn fib table
+ fib_index =
+ fib_table_find_or_create_and_lock (prefix->fp_proto, 0, hicn_fib_src);
-/*
- * Node function for the icn packet-generator server.
- */
-static uword
-hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
- vlib_frame_t *frame)
-{
- u32 n_left_from, *from, *to_next;
- icnpg_server_next_t next_index;
- u32 pkts_processed = 0, pkts_dropped = 0;
- u32 bi0, bi1;
- vlib_buffer_t *b0, *b1;
- u8 pkt_type0 = 0, pkt_type1 = 0;
- u16 msg_type0 = 0, msg_type1 = 0;
- hicn_header_t *hicn0 = NULL, *hicn1 = NULL;
- hicn_name_t name0, name1;
- u16 namelen0, namelen1;
+ // Check the prefix we are adding is not already in the table
+ fib_entry_index = fib_table_lookup_exact_match (fib_index, prefix);
- hicnpg_server_main_t *hpgsm = &hicnpg_server_main;
-
- from = vlib_frame_vector_args (frame);
-
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
+ if (fib_entry_index != FIB_NODE_INDEX_INVALID)
{
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- u32 next0 = HICNPG_SERVER_NEXT_DROP;
- u32 next1 = HICNPG_SERVER_NEXT_DROP;
- u8 isv6_0 = 0;
- u8 isv6_1 = 0;
- u32 sw_if_index0, sw_if_index1;
-
- /* Prefetch next iteration. */
- {
- vlib_buffer_t *p2, *p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, (2 * CLIB_CACHE_LINE_BYTES), STORE);
- CLIB_PREFETCH (p3->data, (2 * CLIB_CACHE_LINE_BYTES), STORE);
- }
-
- /*
- * speculatively enqueue b0 and b1 to the current
- * next frame
- */
- to_next[0] = bi0 = from[0];
- to_next[1] = bi1 = from[1];
- from += 2;
- to_next += 2;
- n_left_from -= 2;
- n_left_to_next -= 2;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
-
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
- vnet_buffer (b1)->sw_if_index[VLIB_TX] = ~0;
-
- u32 match0 = match_interest (b0, hpgsm->pgen_srv_hicn_name);
- u32 match1 = match_interest (b1, hpgsm->pgen_srv_hicn_name);
-
- if (match0)
- {
- next0 = match0 - 1;
- }
- else if (hicn_interest_parse_pkt (b0, &name0, &namelen0, &hicn0,
- &isv6_0) == HICN_ERROR_NONE)
- {
- /* this node grabs only interests */
- vlib_buffer_t *rb = NULL;
- rb = vlib_get_buffer (vm, hpgsm->pgen_svr_buffer_idx);
-
- isv6_0 ? convert_interest_to_data_v6 (vm, b0, rb, bi0) :
- convert_interest_to_data_v4 (vm, b0, rb, bi0);
-
- next0 = isv6_0 ? HICNPG_SERVER_NEXT_V6_LOOKUP :
- HICNPG_SERVER_NEXT_V4_LOOKUP;
- }
-
- if (match1)
- {
- next1 = match1 - 1;
- }
- else if (hicn_interest_parse_pkt (b1, &name1, &namelen1, &hicn1,
- &isv6_1) == HICN_ERROR_NONE)
- {
- /* this node grabs only interests */
- vlib_buffer_t *rb = NULL;
- rb = vlib_get_buffer (vm, hpgsm->pgen_svr_buffer_idx);
-
- isv6_1 ? convert_interest_to_data_v6 (vm, b1, rb, bi1) :
- convert_interest_to_data_v4 (vm, b1, rb, bi1);
-
- next1 = isv6_1 ? HICNPG_SERVER_NEXT_V6_LOOKUP :
- HICNPG_SERVER_NEXT_V4_LOOKUP;
- }
- pkts_processed += 2;
-
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
- {
- if (b0->flags & VLIB_BUFFER_IS_TRACED)
- {
- hicnpg_server_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = pkt_type0;
- t->msg_type = msg_type0;
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- }
- if (b1->flags & VLIB_BUFFER_IS_TRACED)
- {
- hicnpg_server_trace_t *t =
- vlib_add_trace (vm, node, b1, sizeof (*t));
- t->pkt_type = pkt_type1;
- t->msg_type = msg_type1;
- t->sw_if_index = sw_if_index1;
- t->next_index = next1;
- }
- }
- if (next0 == HICNPG_SERVER_NEXT_DROP)
- {
- pkts_dropped++;
- }
- if (next1 == HICNPG_SERVER_NEXT_DROP)
- {
- pkts_dropped++;
- }
- /*
- * verify speculative enqueues, maybe switch current
- * next frame
- */
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
- n_left_to_next, bi0, bi1, next0,
- next1);
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 next0 = HICNPG_SERVER_NEXT_DROP;
- u32 sw_if_index0 = ~0;
- u8 isv6_0 = 0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
-
- u32 match0 = match_interest (b0, hpgsm->pgen_srv_hicn_name);
-
- if (match0)
- {
- next0 = match0 - 1;
- }
- else if (hicn_interest_parse_pkt (b0, &name0, &namelen0, &hicn0,
- &isv6_0) == HICN_ERROR_NONE)
- {
- /* this node grabs only interests */
- vlib_buffer_t *rb = NULL;
- rb = vlib_get_buffer (vm, hpgsm->pgen_svr_buffer_idx);
-
- isv6_0 ? convert_interest_to_data_v6 (vm, b0, rb, bi0) :
- convert_interest_to_data_v4 (vm, b0, rb, bi0);
-
- next0 = isv6_0 ? HICNPG_SERVER_NEXT_V6_LOOKUP :
- HICNPG_SERVER_NEXT_V4_LOOKUP;
- }
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
- (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- hicnpg_server_trace_t *t =
- vlib_add_trace (vm, node, b0, sizeof (*t));
- t->pkt_type = pkt_type0;
- t->msg_type = msg_type0;
- t->sw_if_index = sw_if_index0;
- t->next_index = next0;
- }
- pkts_processed += 1;
-
- if (next0 == HICNPG_SERVER_NEXT_DROP)
- {
- pkts_dropped++;
- }
- /*
- * verify speculative enqueue, maybe switch current
- * next frame
- */
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ // Route already existing.
+ return clib_error_return (0, "Route exist already.");
}
- vlib_node_increment_counter (vm, hicn_pg_server_node.index,
- HICNPG_SERVER_ERROR_PROCESSED, pkts_processed);
- vlib_node_increment_counter (vm, hicn_pg_server_node.index,
- HICNPG_SERVER_ERROR_DROPPED, pkts_dropped);
-
- return (frame->n_vectors);
-}
-
-void
-convert_interest_to_data_v4 (vlib_main_t *vm, vlib_buffer_t *b0,
- vlib_buffer_t *rb, u32 bi0)
-{
- hicn_header_t *h0 = vlib_buffer_get_current (b0);
-
- /* Get the packet length */
- u16 pkt_len = clib_net_to_host_u16 (h0->v4.ip.len);
+ // Allocate packet buffer
+ int n_buf = vlib_buffer_alloc (vlib_get_main (), &buffer_index, 1);
- /*
- * Rule of thumb: We want the size of the IP packet to be <= 1500 bytes
- */
- u16 bytes_to_copy = rb->current_length;
- if ((bytes_to_copy + pkt_len) > 1500)
+ if (n_buf == 0)
{
- bytes_to_copy = 1500 - pkt_len;
+ return clib_error_return (0, "Impossible to allocate paylod buffer.");
}
- /* Add content to the data packet */
- vlib_buffer_add_data (vm, &bi0, rb->data, bytes_to_copy);
- b0 = vlib_get_buffer (vm, bi0);
-
- h0 = vlib_buffer_get_current (b0);
-
- ip4_address_t src_addr = h0->v4.ip.saddr;
- h0->v4.ip.saddr = h0->v4.ip.daddr;
- h0->v4.ip.daddr = src_addr;
-
- h0->v4.ip.len = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
- h0->v4.ip.csum = ip4_header_checksum ((ip4_header_t *) &(h0->v4.ip));
- calculate_tcp_checksum_v4 (vm, b0);
+ // Initialize the buffer data with zeros
+ rb = vlib_get_buffer (vlib_get_main (), buffer_index);
+ memset (rb->data, 0, payload_size);
+ rb->current_length = payload_size;
+
+ // We can proceed. Get a new hicnpg_server_t
+ pool_get_aligned_zero (hicnpg_server_pool, hpg, 2 * CLIB_CACHE_LINE_BYTES);
+ hpgi = hpg - hicnpg_server_pool;
+
+ // Set DPO
+ dpo_set (
+ &hpg->dpo, hicnpg_server_dpo_type,
+ (ip46_address_is_ip4 (&prefix->fp_addr) ? DPO_PROTO_IP4 : DPO_PROTO_IP6),
+ hpgi);
+
+ // Add the route via the hicnpg_server_dpo_type. In this way packets will
+ // endup in the hicnpg_server node
+ CLIB_UNUSED (fib_node_index_t new_fib_node_index) =
+ fib_table_entry_special_dpo_add (
+ fib_index, prefix, hicn_fib_src,
+ (FIB_ENTRY_FLAG_EXCLUSIVE | FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT),
+ &hpg->dpo);
+
+#if 0
+ vlib_validate_combined_counter (&(udp_encap_counters), uei);
+ vlib_zero_combined_counter (&(udp_encap_counters), uei);
+#endif
+
+ // Init remaining struct fields
+ fib_node_init (&hpg->fib_node, hicnpg_server_fib_node_type);
+ fib_node_lock (&hpg->fib_node);
+ hpg->fib_index = fib_index;
+ hpg->prefix = *prefix;
+ hpg->buffer_index = buffer_index;
+ hpg->fib_entry_index = fib_entry_index;
+ hpg->hicn_locator = *locator;
+
+ // track the destination address
+ // hpg->fib_entry_index =
+ // fib_entry_track (fib_index, &hpg->prefix,
+ // hicnpg_server_fib_node_type, hpgi, &hpg->fib_sibling);
+ // hicnpg_server_restack (hpg);
+
+ HICN_DEBUG ("Calling hicn enable for pg-server face");
+
+ hicn_face_id_t *vec_faces = NULL;
+ hicn_route_enable (prefix, &vec_faces);
+ if (vec_faces != NULL)
+ vec_free (vec_faces);
+
+ // Return the index of the hicnpg_server_t
+ *hicnpg_server_index = hpgi;
+
+ return NULL;
}
-void
-convert_interest_to_data_v6 (vlib_main_t *vm, vlib_buffer_t *b0,
- vlib_buffer_t *rb, u32 bi0)
+clib_error_t *
+hicn_pg_init (vlib_main_t *vm)
{
- hicn_header_t *h0 = vlib_buffer_get_current (b0);
-
- /* Get the packet length */
- uint16_t pkt_len =
- clib_net_to_host_u16 (h0->v6.ip.len) + sizeof (ip6_header_t);
+ hicnpg_server_fib_node_type = fib_node_register_new_type (
+ "hicnpg_server_fib_node", &hicnpg_server_fib_vft);
- /*
- * Figure out how many bytes we can add to the content
- *
- * Rule of thumb: We want the size of the IP packet to be <= 1400 bytes
- */
- u16 bytes_to_copy = rb->current_length;
- if ((bytes_to_copy + pkt_len) > 1500)
- {
- bytes_to_copy = 1500 - pkt_len;
- }
- /* Add content to the data packet */
- vlib_buffer_add_data (vm, &bi0, rb->data, bytes_to_copy);
+ hicnpg_server_dpo_type =
+ dpo_register_new_type (&hicnpg_server_dpo_vft, hicnpg_server_nodes);
- b0 = vlib_get_buffer (vm, bi0);
-
- h0 = vlib_buffer_get_current (b0);
- ip6_address_t src_addr = h0->v6.ip.saddr;
- h0->v6.ip.saddr = h0->v6.ip.daddr;
- h0->v6.ip.daddr = src_addr;
-
- h0->v6.ip.len = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) -
- sizeof (ip6_header_t));
- h0->v6.tcp.data_offset_and_reserved |= 0x0f;
- h0->v6.tcp.urg_ptr = htons (0xffff);
-
- calculate_tcp_checksum_v6 (vm, b0);
+ return NULL;
}
-VLIB_REGISTER_NODE(hicn_pg_server_node) =
-{
- .function = hicnpg_node_server_fn,
- .name = "hicnpg-server",
- .vector_size = sizeof(u32),
- .format_trace = format_icnpg_server_trace,
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(icnpg_server_error_strings),
- .error_strings = icnpg_server_error_strings,
- .n_next_nodes = HICNPG_SERVER_N_NEXT,
- /* edit / add dispositions here */
- .next_nodes =
- {
- [HICNPG_SERVER_NEXT_V4_LOOKUP] = "ip4-lookup",
- [HICNPG_SERVER_NEXT_V6_LOOKUP] = "ip6-lookup",
- [HICNPG_SERVER_NEXT_DROP] = "error-drop",
- },
-};
-
-VNET_FEATURE_INIT (hicn_pg_server_ip6, static) = {
- .arc_name = "ip6-unicast",
- .node_name = "hicnpg-server",
- .runs_before = VNET_FEATURES ("ip6-inacl"),
-};
-
-VNET_FEATURE_INIT (hicn_pg_server_ip4, static) = {
- .arc_name = "ip4-unicast",
- .node_name = "hicnpg-server",
- .runs_before = VNET_FEATURES ("ip4-inacl"),
-};
-
-/*
- * End of packet-generator server node
- */
-
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables: eval: (c-set-style "gnu") End:
- */
+ */ \ No newline at end of file
diff --git a/hicn-plugin/src/pg.h b/hicn-plugin/src/pg.h
index 7855248e6..deb585714 100644
--- a/hicn-plugin/src/pg.h
+++ b/hicn-plugin/src/pg.h
@@ -16,6 +16,8 @@
#ifndef __HICN_PG_H__
#define __HICN_PG_H__
+#include <vppinfra/pool.h>
+
/**
* @file pg.h
*
@@ -57,23 +59,58 @@
*/
typedef struct hicnpg_main_s
{
- u32 index; // used to compute the sequence number
- fib_prefix_t *pgen_clt_hicn_name; // hICN name to put in the destiantion
- // addess of an interest
- u32
- index_ifaces; /* used to mimic interests coming from different consumer */
- u32 n_ifaces; /* The source address will change from interest to interest */
- /* index_ifaces is used to keep a global reference to the iface used */
- /* and it is incremented when we want to change "consumer" */
- /* n_ifaces identifies how many consumers to simulate */
- u32 max_seq_number; // Use to limit the max sequence number
- u32 n_flows; // Use to simulate multiple flows (a flow always have the same
- // hICN name)
- ip46_address_t pgen_clt_src_addr; // Source addess base to use in the
- // interest
-
- u16 interest_lifetime; // Interest lifetime
- u32 sw_if; // Interface where to send interest and receives data
+ /*
+ * used to compute the sequence number
+ */
+ u32 index;
+
+ /*
+ * hICN name to put in the destination addess of an interest
+ */
+ fib_prefix_t *pgen_clt_hicn_name;
+
+ /*
+ * Used to mimic interests coming from different consumer. The source address
+ * will change from interest to interest index_ifaces is used to keep a
+ * global reference to the iface used and it is incremented when we want to
+ * change "consumer"
+ */
+ u32 index_ifaces;
+
+ /*
+ * n_ifaces identifies how many consumers to simulate
+ */
+ u32 n_ifaces;
+
+ /*
+ * Use to limit the max sequence number
+ */
+ u32 max_seq_number;
+
+ /*
+ * Use to simulate multiple flows (a flow always have the same hICN name)
+ */
+ u32 n_flows;
+
+ /*
+ * Source addess base to use in the interest
+ */
+ ip46_address_t pgen_clt_src_addr;
+
+ /*
+ * Interest lifetime
+ */
+ u16 interest_lifetime;
+
+ /*
+ * Interface where to send interest and receives data.
+ */
+ u32 sw_if;
+
+ /*
+ * Fib node type
+ */
+ fib_node_type_t hicn_fib_node_type;
} hicnpg_main_t;
extern hicnpg_main_t hicnpg_main;
@@ -83,18 +120,75 @@ extern hicnpg_main_t hicnpg_main;
*
* It stores the configuration and make it availables to the pg server node.
*/
-typedef struct hicnpg_server_main_s
+typedef struct hicnpg_server_s
{
- u32 node_index;
- /* Arbitrary content */
- u32 pgen_svr_buffer_idx;
- fib_prefix_t *pgen_srv_hicn_name;
-} hicnpg_server_main_t;
+ /*
+ * Prefix served by this packet generator server
+ */
+ fib_prefix_t prefix;
+
+ /*
+ * IP address to put in the destination addess of the data
+ */
+ ip46_address_t hicn_locator;
+
+ /*
+ * Buffer index
+ */
+ u32 buffer_index;
+
+ /**
+ * The DPO used to forward to the next node in the VLIB graph
+ */
+ dpo_id_t dpo;
-extern hicnpg_server_main_t hicnpg_server_main;
+ /*
+ * linkage into the FIB graph
+ */
+ fib_node_t fib_node;
+ /*
+ * Tracking information for the IP destination
+ */
+ fib_node_index_t fib_entry_index;
+
+ /*
+ * The FIB index
+ */
+ index_t fib_index;
+} hicnpg_server_t;
+
+STATIC_ASSERT (sizeof (hicnpg_server_t) <= 2 * CLIB_CACHE_LINE_BYTES,
+ "hicnpg_server_t is too large");
+
+extern hicnpg_server_t hicnpg_server_main;
extern vlib_node_registration_t hicn_pg_interest_node;
extern vlib_node_registration_t hicn_pg_data_node;
+extern dpo_type_t hicnpg_server_dpo_type;
+
+/**
+ * Pool of hicnpg_servers
+ */
+extern hicnpg_server_t *hicnpg_server_pool;
+
+always_inline hicnpg_server_t *
+hicnpg_server_get (index_t hpgi)
+{
+ return pool_elt_at_index (hicnpg_server_pool, hpgi);
+}
+
+always_inline u8
+dpo_is_pgserver (const dpo_id_t *dpo)
+{
+ return (dpo->dpoi_type == hicnpg_server_dpo_type);
+}
+
+clib_error_t *hicnpg_server_add_and_lock (fib_prefix_t *prefix,
+ u32 *hicnpg_server_index,
+ ip46_address_t *locator,
+ size_t payload_size);
+
+clib_error_t *hicn_pg_init (vlib_main_t *vm);
#endif // __HICN_PG_H__
diff --git a/hicn-plugin/src/pg_node.c b/hicn-plugin/src/pg_node.c
new file mode 100644
index 000000000..3672a6b72
--- /dev/null
+++ b/hicn-plugin/src/pg_node.c
@@ -0,0 +1,1132 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vlib/vlib.h>
+#include <vnet/vnet.h>
+#include <vnet/pg/pg.h>
+#include <vnet/ip/ip.h>
+#include <vnet/ethernet/ethernet.h>
+
+#include "hicn.h"
+#include "pg.h"
+#include "parser.h"
+#include "infra.h"
+
+/* Registration struct for a graph node */
+vlib_node_registration_t hicn_pg_interest_node;
+vlib_node_registration_t hicn_pg_data_node;
+
+/* Stats, which end up called "error" even though they aren't... */
+#define foreach_hicnpg_error \
+ _ (PROCESSED, "hICN PG packets processed") \
+ _ (DROPPED, "hICN PG packets dropped") \
+ _ (INTEREST_MSGS_GENERATED, "hICN PG Interests generated") \
+ _ (CONTENT_MSGS_RECEIVED, "hICN PG Content msgs received")
+
+typedef enum
+{
+#define _(sym, str) HICNPG_ERROR_##sym,
+ foreach_hicnpg_error
+#undef _
+ HICNPG_N_ERROR,
+} hicnpg_error_t;
+
+static char *hicnpg_error_strings[] = {
+#define _(sym, string) string,
+ foreach_hicnpg_error
+#undef _
+};
+
+/*
+ * Next graph nodes, which reference the list in the actual registration
+ * block below
+ */
+typedef enum
+{
+ HICNPG_INTEREST_NEXT_V4_LOOKUP,
+ HICNPG_INTEREST_NEXT_V6_LOOKUP,
+ HICNPG_INTEREST_NEXT_DROP,
+ HICNPG_N_NEXT,
+} hicnpg_interest_next_t;
+
+/* Trace context struct */
+typedef struct
+{
+ u32 next_index;
+ u32 sw_if_index;
+ u8 pkt_type;
+ u16 msg_type;
+} hicnpg_trace_t;
+
+/* packet trace format function */
+static u8 *
+format_hicnpg_trace (u8 *s, va_list *args)
+{
+ CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
+ CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
+ hicnpg_trace_t *t = va_arg (*args, hicnpg_trace_t *);
+
+ s = format (s, "HICNPG: pkt: %d, msg %d, sw_if_index %d, next index %d",
+ (int) t->pkt_type, (int) t->msg_type, t->sw_if_index,
+ t->next_index);
+ return (s);
+}
+
+always_inline void hicn_rewrite_interestv4 (vlib_main_t *vm, vlib_buffer_t *b0,
+ u32 seq_number, u16 lifetime,
+ u32 next_flow, u32 iface);
+
+always_inline void hicn_rewrite_interestv6 (vlib_main_t *vm, vlib_buffer_t *b0,
+ u32 seq_number, u16 lifetime,
+ u32 next_flow, u32 iface);
+
+always_inline void convert_interest_to_data_v4 (vlib_main_t *vm,
+ vlib_buffer_t *b0,
+ vlib_buffer_t *rb, u32 bi0);
+
+always_inline void convert_interest_to_data_v6 (vlib_main_t *vm,
+ vlib_buffer_t *b0,
+ vlib_buffer_t *rb, u32 bi0);
+
+always_inline void calculate_tcp_checksum_v4 (vlib_main_t *vm,
+ vlib_buffer_t *b0);
+
+always_inline void calculate_tcp_checksum_v6 (vlib_main_t *vm,
+ vlib_buffer_t *b0);
+/*
+ * Node function for the icn packet-generator client. The goal here is to
+ * manipulate/tweak a stream of packets that have been injected by the vpp
+ * packet generator to generate icn request traffic.
+ */
+static uword
+hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
+{
+ u32 n_left_from, *from, *to_next;
+ hicnpg_interest_next_t next_index;
+ u32 pkts_processed = 0, pkts_dropped = 0;
+ u32 interest_msgs_generated = 0;
+ u32 bi0, bi1;
+ vlib_buffer_t *b0, *b1;
+ u8 pkt_type0 = 0, pkt_type1 = 0;
+ u16 msg_type0 = 0, msg_type1 = 0;
+ hicnpg_main_t *hpgm = &hicnpg_main;
+ int iface = 0;
+
+ from = vlib_frame_vector_args (frame);
+ n_left_from = frame->n_vectors;
+ next_index = node->cached_next_index;
+
+ while (n_left_from > 0)
+ {
+ u32 n_left_to_next;
+
+ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
+
+ while (n_left_from >= 4 && n_left_to_next >= 2)
+ {
+ u32 next0 = HICNPG_INTEREST_NEXT_DROP;
+ u32 next1 = HICNPG_INTEREST_NEXT_DROP;
+ u32 sw_if_index0 = ~0, sw_if_index1 = ~0;
+ u8 isv6_0;
+ u8 isv6_1;
+
+ /* Prefetch next iteration. */
+ {
+ vlib_buffer_t *p2, *p3;
+
+ p2 = vlib_get_buffer (vm, from[2]);
+ p3 = vlib_get_buffer (vm, from[3]);
+
+ vlib_prefetch_buffer_header (p2, LOAD);
+ vlib_prefetch_buffer_header (p3, LOAD);
+
+ CLIB_PREFETCH (p2->data, (2 * CLIB_CACHE_LINE_BYTES), STORE);
+ CLIB_PREFETCH (p3->data, (2 * CLIB_CACHE_LINE_BYTES), STORE);
+ }
+
+ /*
+ * speculatively enqueue b0 and b1 to the current
+ * next frame
+ */
+ to_next[0] = bi0 = from[0];
+ to_next[1] = bi1 = from[1];
+ from += 2;
+ to_next += 2;
+ n_left_from -= 2;
+ n_left_to_next -= 2;
+
+ b0 = vlib_get_buffer (vm, bi0);
+ b1 = vlib_get_buffer (vm, bi1);
+
+ hicn_buffer_set_flags (b0, HICN_BUFFER_FLAGS_FROM_PG);
+ hicn_buffer_set_flags (b1, HICN_BUFFER_FLAGS_FROM_PG);
+
+ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
+ vnet_buffer (b0)->sw_if_index[VLIB_RX] = hpgm->sw_if;
+ vnet_buffer (b1)->sw_if_index[VLIB_RX] = hpgm->sw_if;
+
+ /* Check icn packets, locate names */
+ if (hicn_interest_parse_pkt (b0) == HICN_ERROR_NONE)
+ {
+ /* this node grabs only interests */
+ isv6_0 = hicn_buffer_is_v6 (b0);
+
+ /* Increment the appropriate message counter */
+ interest_msgs_generated++;
+
+ iface = (hpgm->index_ifaces % hpgm->n_ifaces);
+ /* Rewrite and send */
+ isv6_0 ?
+ hicn_rewrite_interestv6 (
+ vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
+ hpgm->interest_lifetime, hpgm->index % hpgm->n_flows,
+ iface) :
+ hicn_rewrite_interestv4 (
+ vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
+ hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface);
+
+ hpgm->index_ifaces++;
+ if (iface == (hpgm->n_ifaces - 1))
+ hpgm->index++;
+
+ next0 = isv6_0 ? HICNPG_INTEREST_NEXT_V6_LOOKUP :
+ HICNPG_INTEREST_NEXT_V4_LOOKUP;
+ }
+ if (hicn_interest_parse_pkt (b1) == HICN_ERROR_NONE)
+ {
+ /* this node grabs only interests */
+ isv6_1 = hicn_buffer_is_v6 (b1);
+
+ /* Increment the appropriate message counter */
+ interest_msgs_generated++;
+
+ iface = (hpgm->index_ifaces % hpgm->n_ifaces);
+ /* Rewrite and send */
+ isv6_1 ?
+ hicn_rewrite_interestv6 (
+ vm, b1, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
+ hpgm->interest_lifetime, hpgm->index % hpgm->n_flows,
+ iface) :
+ hicn_rewrite_interestv4 (
+ vm, b1, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
+ hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface);
+
+ hpgm->index_ifaces++;
+ if (iface == (hpgm->n_ifaces - 1))
+ hpgm->index++;
+
+ next1 = isv6_1 ? HICNPG_INTEREST_NEXT_V6_LOOKUP :
+ HICNPG_INTEREST_NEXT_V4_LOOKUP;
+ }
+ /* Send pkt to next node */
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
+ vnet_buffer (b1)->sw_if_index[VLIB_TX] = ~0;
+
+ pkts_processed += 2;
+
+ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
+ {
+ if (b0->flags & VLIB_BUFFER_IS_TRACED)
+ {
+ hicnpg_trace_t *t =
+ vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->pkt_type = pkt_type0;
+ t->msg_type = msg_type0;
+ t->sw_if_index = sw_if_index0;
+ t->next_index = next0;
+ }
+ if (b1->flags & VLIB_BUFFER_IS_TRACED)
+ {
+ hicnpg_trace_t *t =
+ vlib_add_trace (vm, node, b1, sizeof (*t));
+ t->pkt_type = pkt_type1;
+ t->msg_type = msg_type1;
+ t->sw_if_index = sw_if_index1;
+ t->next_index = next1;
+ }
+ }
+ if (next0 == HICNPG_INTEREST_NEXT_DROP)
+ {
+ pkts_dropped++;
+ }
+ if (next1 == HICNPG_INTEREST_NEXT_DROP)
+ {
+ pkts_dropped++;
+ }
+ /*
+ * verify speculative enqueues, maybe switch current
+ * next frame
+ */
+ vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, bi1, next0,
+ next1);
+ }
+
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ u32 next0 = HICNPG_INTEREST_NEXT_DROP;
+ u32 sw_if_index0;
+ u8 isv6_0;
+
+ /* speculatively enqueue b0 to the current next frame */
+ bi0 = from[0];
+ to_next[0] = bi0;
+ from += 1;
+ to_next += 1;
+ n_left_from -= 1;
+ n_left_to_next -= 1;
+
+ b0 = vlib_get_buffer (vm, bi0);
+
+ hicn_buffer_set_flags (b0, HICN_BUFFER_FLAGS_FROM_PG);
+
+ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ vnet_buffer (b0)->sw_if_index[VLIB_RX] = hpgm->sw_if;
+
+ /* Check icn packets, locate names */
+ if (hicn_interest_parse_pkt (b0) == HICN_ERROR_NONE)
+ {
+ /* this node grabs only interests */
+ isv6_0 = hicn_buffer_is_v6 (b0);
+
+ /* Increment the appropriate message counter */
+ interest_msgs_generated++;
+
+ iface = (hpgm->index_ifaces % hpgm->n_ifaces);
+
+ /* Rewrite and send */
+ isv6_0 ?
+ hicn_rewrite_interestv6 (
+ vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
+ hpgm->interest_lifetime, hpgm->index % hpgm->n_flows,
+ iface) :
+ hicn_rewrite_interestv4 (
+ vm, b0, (hpgm->index / hpgm->n_flows) % hpgm->max_seq_number,
+ hpgm->interest_lifetime, hpgm->index % hpgm->n_flows, iface);
+
+ hpgm->index_ifaces++;
+ if (iface == (hpgm->n_ifaces - 1))
+ hpgm->index++;
+
+ next0 = isv6_0 ? HICNPG_INTEREST_NEXT_V6_LOOKUP :
+ HICNPG_INTEREST_NEXT_V4_LOOKUP;
+ }
+ /* Send pkt to ip lookup */
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
+
+ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
+ (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ hicnpg_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->pkt_type = pkt_type0;
+ t->msg_type = msg_type0;
+ t->sw_if_index = sw_if_index0;
+ t->next_index = next0;
+ }
+ pkts_processed += 1;
+
+ if (next0 == HICNPG_INTEREST_NEXT_DROP)
+ {
+ pkts_dropped++;
+ }
+ /*
+ * verify speculative enqueue, maybe switch current
+ * next frame
+ */
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, next0);
+ }
+
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+
+ vlib_node_increment_counter (vm, hicn_pg_interest_node.index,
+ HICNPG_ERROR_PROCESSED, pkts_processed);
+ vlib_node_increment_counter (vm, hicn_pg_interest_node.index,
+ HICNPG_ERROR_DROPPED, pkts_dropped);
+ vlib_node_increment_counter (vm, hicn_pg_interest_node.index,
+ HICNPG_ERROR_INTEREST_MSGS_GENERATED,
+ interest_msgs_generated);
+
+ return (frame->n_vectors);
+}
+
+void
+hicn_rewrite_interestv4 (vlib_main_t *vm, vlib_buffer_t *b0, u32 seq_number,
+ u16 interest_lifetime, u32 next_flow, u32 iface)
+{
+ hicn_header_t *h0 = vlib_buffer_get_current (b0);
+
+ /* Generate the right src and dst corresponding to flow and iface */
+ ip46_address_t src_addr = {
+ .ip4 = hicnpg_main.pgen_clt_src_addr.ip4,
+ };
+ hicn_name_t dst_name = {
+ .prefix.ip4 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip4,
+ .suffix = seq_number,
+ };
+
+ src_addr.ip4.as_u32 += clib_host_to_net_u32 (iface);
+ dst_name.prefix.ip4.as_u32 += clib_net_to_host_u32 (next_flow);
+
+ /* Update locator and name */
+ hicn_type_t type = hicn_get_buffer (b0)->type;
+ HICN_OPS4->set_interest_locator (type, &h0->protocol, &src_addr);
+ HICN_OPS4->set_interest_name (type, &h0->protocol, &dst_name);
+
+ /* Update lifetime (currently L4 checksum is not updated) */
+ HICN_OPS4->set_lifetime (type, &h0->protocol, interest_lifetime);
+
+ /* Update checksums */
+ HICN_OPS4->update_checksums (type, &h0->protocol, 0, 0);
+}
+
+/**
+ * @brief Rewrite the IPv6 header as the next generated packet
+ *
+ * Set up a name prefix
+ * - etiher generate interest in which the name varies only after the prefix
+ * (inc : seq_number), then the flow acts on the prefix (CHECK)
+ * seq_number => TCP, FLOW =>
+ *
+ * SRC : pgen_clt_src_addr.ip6 DST = generate name (pgen_clt_hicn_name.ip6)
+ * ffff:ffff:ffff:ffff ffff:ffff:ffff:ffff
+ * \__/ \__/
+ * +iface + flow
+ * Source is used to emulate different consumers.
+ * FIXME iface is ill-named, better name it consumer id
+ * Destination is used to iterate on the content.
+ */
+void
+hicn_rewrite_interestv6 (vlib_main_t *vm, vlib_buffer_t *b0, u32 seq_number,
+ u16 interest_lifetime, u32 next_flow, u32 iface)
+{
+ hicn_header_t *h0 = vlib_buffer_get_current (b0);
+
+ /* Generate the right src and dst corresponding to flow and iface */
+ ip46_address_t src_addr = {
+ .ip6 = hicnpg_main.pgen_clt_src_addr.ip6,
+ };
+ hicn_name_t dst_name = {
+ .prefix.ip6 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip6,
+ .suffix = seq_number,
+ };
+ src_addr.ip6.as_u32[3] += clib_host_to_net_u32 (iface);
+ dst_name.prefix.ip6.as_u32[3] += clib_net_to_host_u32 (next_flow);
+
+ /* Update locator and name */
+ hicn_type_t type = hicn_get_buffer (b0)->type;
+ HICN_OPS6->set_interest_locator (type, &h0->protocol, &src_addr);
+ HICN_OPS6->set_interest_name (type, &h0->protocol, &dst_name);
+
+ /* Update lifetime */
+ HICN_OPS6->set_lifetime (type, &h0->protocol, interest_lifetime);
+
+ /* Update checksums */
+ calculate_tcp_checksum_v6 (vm, b0);
+}
+
+void
+calculate_tcp_checksum_v4 (vlib_main_t *vm, vlib_buffer_t *b0)
+{
+ ip4_header_t *ip0;
+ tcp_header_t *tcp0;
+ ip_csum_t sum0;
+ u32 tcp_len0;
+
+ ip0 = (ip4_header_t *) (vlib_buffer_get_current (b0));
+ tcp0 =
+ (tcp_header_t *) (vlib_buffer_get_current (b0) + sizeof (ip4_header_t));
+ tcp_len0 = clib_net_to_host_u16 (ip0->length) - sizeof (ip4_header_t);
+
+ /* Initialize checksum with header. */
+ if (BITS (sum0) == 32)
+ {
+ sum0 = clib_mem_unaligned (&ip0->src_address, u32);
+ sum0 =
+ ip_csum_with_carry (sum0, clib_mem_unaligned (&ip0->dst_address, u32));
+ }
+ else
+ sum0 = clib_mem_unaligned (&ip0->src_address, u64);
+
+ sum0 = ip_csum_with_carry (
+ sum0, clib_host_to_net_u32 (tcp_len0 + (ip0->protocol << 16)));
+
+ /* Invalidate possibly old checksum. */
+ tcp0->checksum = 0;
+
+ u32 tcp_offset = sizeof (ip4_header_t);
+ sum0 = ip_incremental_checksum_buffer (vm, b0, tcp_offset, tcp_len0, sum0);
+
+ tcp0->checksum = ~ip_csum_fold (sum0);
+}
+
+void
+calculate_tcp_checksum_v6 (vlib_main_t *vm, vlib_buffer_t *b0)
+{
+ ip6_header_t *ip0;
+ tcp_header_t *tcp0;
+ ip_csum_t sum0;
+ u32 tcp_len0;
+
+ ip0 = (ip6_header_t *) (vlib_buffer_get_current (b0));
+ tcp0 =
+ (tcp_header_t *) (vlib_buffer_get_current (b0) + sizeof (ip6_header_t));
+ tcp_len0 = clib_net_to_host_u16 (ip0->payload_length);
+
+ /* Initialize checksum with header. */
+ if (BITS (sum0) == 32)
+ {
+ sum0 = clib_mem_unaligned (&ip0->src_address, u32);
+ sum0 =
+ ip_csum_with_carry (sum0, clib_mem_unaligned (&ip0->dst_address, u32));
+ }
+ else
+ sum0 = clib_mem_unaligned (&ip0->src_address, u64);
+
+ sum0 = ip_csum_with_carry (
+ sum0, clib_host_to_net_u32 (tcp_len0 + (ip0->protocol << 16)));
+
+ /* Invalidate possibly old checksum. */
+ tcp0->checksum = 0;
+
+ u32 tcp_offset = sizeof (ip6_header_t);
+ sum0 = ip_incremental_checksum_buffer (vm, b0, tcp_offset, tcp_len0, sum0);
+
+ tcp0->checksum = ~ip_csum_fold (sum0);
+}
+
+VLIB_REGISTER_NODE (hicn_pg_interest_node) = {
+ .function = hicnpg_client_interest_node_fn,
+ .name = "hicnpg-interest",
+ .vector_size = sizeof (u32),
+ .format_trace = format_hicnpg_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = ARRAY_LEN (hicnpg_error_strings),
+ .error_strings = hicnpg_error_strings,
+ .n_next_nodes = HICNPG_N_NEXT,
+ .next_nodes = { [HICNPG_INTEREST_NEXT_V4_LOOKUP] = "ip4-lookup",
+ [HICNPG_INTEREST_NEXT_V6_LOOKUP] = "ip6-lookup",
+ [HICNPG_INTEREST_NEXT_DROP] = "error-drop" },
+};
+
+/*
+ * Next graph nodes, which reference the list in the actual registration
+ * block below
+ */
+typedef enum
+{
+ HICNPG_DATA_NEXT_DROP,
+ HICNPG_DATA_NEXT_LOOKUP4,
+ HICNPG_DATA_NEXT_LOOKUP6,
+ HICNPG_DATA_N_NEXT,
+} hicnpg_data_next_t;
+
+/* Trace context struct */
+typedef struct
+{
+ u32 next_index;
+ u32 sw_if_index;
+ u8 pkt_type;
+ u16 msg_type;
+} icnpg_data_trace_t;
+
+/* packet trace format function */
+static u8 *
+format_hicnpg_data_trace (u8 *s, va_list *args)
+{
+ CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
+ CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
+ hicnpg_trace_t *t = va_arg (*args, hicnpg_trace_t *);
+
+ s = format (s, "HICNPG: pkt: %d, msg %d, sw_if_index %d, next index %d",
+ (int) t->pkt_type, (int) t->msg_type, t->sw_if_index,
+ t->next_index);
+ return (s);
+}
+
+/*
+ * Node function for the icn packet-generator client. The goal here is to
+ * manipulate/tweak a stream of packets that have been injected by the vpp
+ * packet generator to generate icn request traffic.
+ */
+static uword
+hicnpg_client_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
+{
+ u32 n_left_from, *from, *to_next;
+ hicnpg_data_next_t next_index;
+ u32 pkts_processed = 0;
+ u32 content_msgs_received = 0;
+ u32 bi0, bi1;
+ vlib_buffer_t *b0, *b1;
+ u8 pkt_type0 = 0, pkt_type1 = 0;
+ u16 msg_type0 = 1, msg_type1 = 1;
+
+ from = vlib_frame_vector_args (frame);
+ n_left_from = frame->n_vectors;
+ next_index = node->cached_next_index;
+
+ while (n_left_from > 0)
+ {
+ u32 n_left_to_next;
+ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
+
+ while (n_left_from >= 4 && n_left_to_next >= 2)
+ {
+ u32 next0 = HICNPG_DATA_NEXT_DROP;
+ u32 next1 = HICNPG_DATA_NEXT_DROP;
+ u32 sw_if_index0, sw_if_index1;
+
+ /* Prefetch next iteration. */
+ {
+ vlib_buffer_t *p2, *p3;
+
+ p2 = vlib_get_buffer (vm, from[2]);
+ p3 = vlib_get_buffer (vm, from[3]);
+
+ vlib_prefetch_buffer_header (p2, LOAD);
+ vlib_prefetch_buffer_header (p3, LOAD);
+
+ CLIB_PREFETCH (p2->data, (2 * CLIB_CACHE_LINE_BYTES), STORE);
+ CLIB_PREFETCH (p3->data, (2 * CLIB_CACHE_LINE_BYTES), STORE);
+ }
+
+ /*
+ * speculatively enqueue b0 and b1 to the current
+ * next frame
+ */
+ to_next[0] = bi0 = from[0];
+ to_next[1] = bi1 = from[1];
+ from += 2;
+ to_next += 2;
+ n_left_from -= 2;
+ n_left_to_next -= 2;
+
+ b0 = vlib_get_buffer (vm, bi0);
+ b1 = vlib_get_buffer (vm, bi1);
+
+ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
+
+ next0 = HICNPG_DATA_NEXT_DROP;
+ next1 = HICNPG_DATA_NEXT_DROP;
+
+ // Increment counter
+ content_msgs_received += 2;
+
+ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
+ {
+ if (b0->flags & VLIB_BUFFER_IS_TRACED)
+ {
+ icnpg_data_trace_t *t =
+ vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->pkt_type = pkt_type0;
+ t->msg_type = msg_type0;
+ t->sw_if_index = sw_if_index0;
+ t->next_index = next0;
+ }
+ if (b1->flags & VLIB_BUFFER_IS_TRACED)
+ {
+ icnpg_data_trace_t *t =
+ vlib_add_trace (vm, node, b1, sizeof (*t));
+ t->pkt_type = pkt_type1;
+ t->msg_type = msg_type1;
+ t->sw_if_index = sw_if_index1;
+ t->next_index = next1;
+ }
+ }
+
+ vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, bi1, next0,
+ next1);
+ pkts_processed += 2;
+ }
+
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ u32 next0 = HICNPG_DATA_NEXT_DROP;
+ u32 sw_if_index0;
+
+ /* speculatively enqueue b0 to the current next frame */
+ bi0 = from[0];
+ to_next[0] = bi0;
+ from += 1;
+ to_next += 1;
+ n_left_from -= 1;
+ n_left_to_next -= 1;
+
+ b0 = vlib_get_buffer (vm, bi0);
+
+ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+
+ next0 = HICNPG_DATA_NEXT_DROP;
+
+ // Increment a counter
+ content_msgs_received += 1;
+
+ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
+ (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ icnpg_data_trace_t *t =
+ vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->pkt_type = pkt_type0;
+ t->msg_type = msg_type0;
+ t->sw_if_index = sw_if_index0;
+ t->next_index = next0;
+ }
+
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, next0);
+
+ pkts_processed++;
+ }
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+
+ vlib_node_increment_counter (vm, hicn_pg_data_node.index,
+ HICNPG_ERROR_PROCESSED, pkts_processed);
+ vlib_node_increment_counter (vm, hicn_pg_data_node.index,
+ HICNPG_ERROR_CONTENT_MSGS_RECEIVED,
+ content_msgs_received);
+ return (frame->n_vectors);
+}
+
+VLIB_REGISTER_NODE(hicn_pg_data_node) =
+{
+ .function = hicnpg_client_data_node_fn,
+ .name = "hicnpg-data",
+ .vector_size = sizeof(u32),
+ .format_trace = format_hicnpg_data_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = ARRAY_LEN(hicnpg_error_strings),
+ .error_strings = hicnpg_error_strings,
+ .n_next_nodes = HICNPG_DATA_N_NEXT,
+ .next_nodes =
+ {
+ [HICNPG_DATA_NEXT_DROP] = "error-drop",
+ [HICNPG_DATA_NEXT_LOOKUP4] = "ip4-lookup",
+ [HICNPG_DATA_NEXT_LOOKUP6] = "ip6-lookup",
+ },
+};
+
+VNET_FEATURE_INIT (hicn_data_input_ip4_arc, static) = {
+ .arc_name = "ip4-unicast",
+ .node_name = "hicnpg-data",
+ .runs_before = VNET_FEATURES ("ip4-inacl"),
+};
+
+VNET_FEATURE_INIT (hicn_data_input_ip6_arc, static) = {
+ .arc_name = "ip6-unicast",
+ .node_name = "hicnpg-data",
+ .runs_before = VNET_FEATURES ("ip6-inacl"),
+};
+
+/*
+ * End of packet-generator client node
+ */
+
+/*
+ * Beginning of packet-generation server node
+ */
+
+/* Registration struct for a graph node */
+vlib_node_registration_t hicn_pg_server_node;
+
+/* Stats, which end up called "error" even though they aren't... */
+#define foreach_icnpg_server_error \
+ _ (PROCESSED, "hICN PG Server packets processed") \
+ _ (DROPPED, "hICN PG Server packets dropped")
+
+typedef enum
+{
+#define _(sym, str) HICNPG_SERVER_ERROR_##sym,
+ foreach_icnpg_server_error
+#undef _
+ HICNPG_SERVER_N_ERROR,
+} icnpg_server_error_t;
+
+static char *icnpg_server_error_strings[] = {
+#define _(sym, string) string,
+ foreach_icnpg_server_error
+#undef _
+};
+
+/*
+ * Next graph nodes, which reference the list in the actual registration
+ * block below
+ */
+typedef enum
+{
+ HICNPG_SERVER_NEXT_V4_LOOKUP,
+ HICNPG_SERVER_NEXT_V6_LOOKUP,
+ HICNPG_SERVER_NEXT_DROP,
+ HICNPG_SERVER_N_NEXT,
+} icnpg_server_next_t;
+
+/* Trace context struct */
+typedef struct
+{
+ u32 next_index;
+ u32 sw_if_index;
+ u8 pkt_type;
+ u16 msg_type;
+} hicnpg_server_trace_t;
+
+/* packet trace format function */
+static u8 *
+format_icnpg_server_trace (u8 *s, va_list *args)
+{
+ CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
+ CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
+ hicnpg_server_trace_t *t = va_arg (*args, hicnpg_server_trace_t *);
+
+ s = format (
+ s, "HICNPG SERVER: pkt: %d, msg %d, sw_if_index %d, next index %d",
+ (int) t->pkt_type, (int) t->msg_type, t->sw_if_index, t->next_index);
+ return (s);
+}
+
+/*
+ * Node function for the icn packet-generator server.
+ */
+static uword
+hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame, int isv6)
+{
+ u32 n_left_from, *from, *to_next;
+ icnpg_server_next_t next_index;
+ u32 pkts_processed = 0, pkts_dropped = 0;
+ u32 bi0, bi1;
+ vlib_buffer_t *b0, *b1;
+ u8 pkt_type0 = 0, pkt_type1 = 0;
+ u16 msg_type0 = 0, msg_type1 = 0;
+
+ from = vlib_frame_vector_args (frame);
+
+ n_left_from = frame->n_vectors;
+ next_index = node->cached_next_index;
+
+ while (n_left_from > 0)
+ {
+ u32 n_left_to_next;
+
+ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
+
+ while (n_left_from >= 4 && n_left_to_next >= 2)
+ {
+ u32 next0 = HICNPG_SERVER_NEXT_DROP;
+ u32 next1 = HICNPG_SERVER_NEXT_DROP;
+ u32 sw_if_index0, sw_if_index1;
+ u32 hpgi0, hpgi1;
+ hicnpg_server_t *hpg0, *hpg1;
+
+ /* Prefetch next iteration. */
+ {
+ vlib_buffer_t *p2, *p3;
+
+ p2 = vlib_get_buffer (vm, from[2]);
+ p3 = vlib_get_buffer (vm, from[3]);
+
+ vlib_prefetch_buffer_header (p2, LOAD);
+ vlib_prefetch_buffer_header (p3, LOAD);
+
+ CLIB_PREFETCH (p2->data, (2 * CLIB_CACHE_LINE_BYTES), STORE);
+ CLIB_PREFETCH (p3->data, (2 * CLIB_CACHE_LINE_BYTES), STORE);
+ }
+
+ /*
+ * speculatively enqueue b0 and b1 to the current
+ * next frame
+ */
+ to_next[0] = bi0 = from[0];
+ to_next[1] = bi1 = from[1];
+ from += 2;
+ to_next += 2;
+ n_left_from -= 2;
+ n_left_to_next -= 2;
+
+ b0 = vlib_get_buffer (vm, bi0);
+ b1 = vlib_get_buffer (vm, bi1);
+
+ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
+
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
+ vnet_buffer (b1)->sw_if_index[VLIB_TX] = ~0;
+
+ hpgi0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
+ hpgi1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX];
+
+ hpg0 = hicnpg_server_get (hpgi0);
+ hpg1 = hicnpg_server_get (hpgi1);
+
+ if (hicn_interest_parse_pkt (b0) == HICN_ERROR_NONE)
+ {
+ vlib_buffer_t *rb = NULL;
+ rb = vlib_get_buffer (vm, hpg0->buffer_index);
+
+ isv6 ? convert_interest_to_data_v6 (vm, b0, rb, bi0) :
+ convert_interest_to_data_v4 (vm, b0, rb, bi0);
+
+ next0 = isv6 ? HICNPG_SERVER_NEXT_V6_LOOKUP :
+ HICNPG_SERVER_NEXT_V4_LOOKUP;
+ }
+
+ if (hicn_interest_parse_pkt (b1) == HICN_ERROR_NONE)
+ {
+ vlib_buffer_t *rb = NULL;
+ rb = vlib_get_buffer (vm, hpg1->buffer_index);
+
+ isv6 ? convert_interest_to_data_v6 (vm, b1, rb, bi1) :
+ convert_interest_to_data_v4 (vm, b1, rb, bi1);
+
+ next1 = isv6 ? HICNPG_SERVER_NEXT_V6_LOOKUP :
+ HICNPG_SERVER_NEXT_V4_LOOKUP;
+ }
+ pkts_processed += 2;
+
+ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
+ {
+ if (b0->flags & VLIB_BUFFER_IS_TRACED)
+ {
+ hicnpg_server_trace_t *t =
+ vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->pkt_type = pkt_type0;
+ t->msg_type = msg_type0;
+ t->sw_if_index = sw_if_index0;
+ t->next_index = next0;
+ }
+ if (b1->flags & VLIB_BUFFER_IS_TRACED)
+ {
+ hicnpg_server_trace_t *t =
+ vlib_add_trace (vm, node, b1, sizeof (*t));
+ t->pkt_type = pkt_type1;
+ t->msg_type = msg_type1;
+ t->sw_if_index = sw_if_index1;
+ t->next_index = next1;
+ }
+ }
+ if (next0 == HICNPG_SERVER_NEXT_DROP)
+ {
+ pkts_dropped++;
+ }
+ if (next1 == HICNPG_SERVER_NEXT_DROP)
+ {
+ pkts_dropped++;
+ }
+ /*
+ * verify speculative enqueues, maybe switch current
+ * next frame
+ */
+ vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, bi1, next0,
+ next1);
+ }
+
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ u32 next0 = HICNPG_SERVER_NEXT_DROP;
+ u32 sw_if_index0 = ~0;
+ u32 hpgi0;
+ hicnpg_server_t *hpg0;
+
+ /* speculatively enqueue b0 to the current next frame */
+ bi0 = from[0];
+ to_next[0] = bi0;
+ from += 1;
+ to_next += 1;
+ n_left_from -= 1;
+ n_left_to_next -= 1;
+
+ b0 = vlib_get_buffer (vm, bi0);
+
+ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
+
+ hpgi0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
+ hpg0 = hicnpg_server_get (hpgi0);
+
+ if (hicn_interest_parse_pkt (b0) == HICN_ERROR_NONE)
+ {
+ /* this node grabs only interests */
+ vlib_buffer_t *rb = NULL;
+ rb = vlib_get_buffer (vm, hpg0->buffer_index);
+
+ isv6 ? convert_interest_to_data_v6 (vm, b0, rb, bi0) :
+ convert_interest_to_data_v4 (vm, b0, rb, bi0);
+
+ next0 = isv6 ? HICNPG_SERVER_NEXT_V6_LOOKUP :
+ HICNPG_SERVER_NEXT_V4_LOOKUP;
+ }
+ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
+ (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ hicnpg_server_trace_t *t =
+ vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->pkt_type = pkt_type0;
+ t->msg_type = msg_type0;
+ t->sw_if_index = sw_if_index0;
+ t->next_index = next0;
+ }
+ pkts_processed += 1;
+
+ if (next0 == HICNPG_SERVER_NEXT_DROP)
+ {
+ pkts_dropped++;
+ }
+ /*
+ * verify speculative enqueue, maybe switch current
+ * next frame
+ */
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, next0);
+ }
+
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+
+ vlib_node_increment_counter (vm, hicn_pg_server_node.index,
+ HICNPG_SERVER_ERROR_PROCESSED, pkts_processed);
+ vlib_node_increment_counter (vm, hicn_pg_server_node.index,
+ HICNPG_SERVER_ERROR_DROPPED, pkts_dropped);
+
+ return (frame->n_vectors);
+}
+
+void
+convert_interest_to_data_v4 (vlib_main_t *vm, vlib_buffer_t *b0,
+ vlib_buffer_t *rb, u32 bi0)
+{
+ hicn_header_t *h0 = vlib_buffer_get_current (b0);
+
+ /* Get the packet length */
+ u16 pkt_len = clib_net_to_host_u16 (h0->v4.ip.len);
+
+ /*
+ * Rule of thumb: We want the size of the IP packet to be <= 1500 bytes
+ */
+ u16 bytes_to_copy = rb->current_length;
+ if ((bytes_to_copy + pkt_len) > 1500)
+ {
+ bytes_to_copy = 1500 - pkt_len;
+ }
+ /* Add content to the data packet */
+ vlib_buffer_add_data (vm, &bi0, rb->data, bytes_to_copy);
+
+ b0 = vlib_get_buffer (vm, bi0);
+
+ h0 = vlib_buffer_get_current (b0);
+
+ ip4_address_t src_addr = h0->v4.ip.saddr;
+ h0->v4.ip.saddr = h0->v4.ip.daddr;
+ h0->v4.ip.daddr = src_addr;
+
+ h0->v4.ip.len = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
+ h0->v4.ip.csum = ip4_header_checksum ((ip4_header_t *) &(h0->v4.ip));
+ calculate_tcp_checksum_v4 (vm, b0);
+}
+
+void
+convert_interest_to_data_v6 (vlib_main_t *vm, vlib_buffer_t *b0,
+ vlib_buffer_t *rb, u32 bi0)
+{
+ hicn_header_t *h0 = vlib_buffer_get_current (b0);
+
+ /* Get the packet length */
+ uint16_t pkt_len =
+ clib_net_to_host_u16 (h0->v6.ip.len) + sizeof (ip6_header_t);
+
+ /*
+ * Figure out how many bytes we can add to the content
+ *
+ * Rule of thumb: We want the size of the IP packet to be <= 1400 bytes
+ */
+ u16 bytes_to_copy = rb->current_length;
+ if ((bytes_to_copy + pkt_len) > 1500)
+ {
+ bytes_to_copy = 1500 - pkt_len;
+ }
+ /* Add content to the data packet */
+ vlib_buffer_add_data (vm, &bi0, rb->data, bytes_to_copy);
+
+ b0 = vlib_get_buffer (vm, bi0);
+
+ h0 = vlib_buffer_get_current (b0);
+ ip6_address_t src_addr = h0->v6.ip.saddr;
+ h0->v6.ip.saddr = h0->v6.ip.daddr;
+ h0->v6.ip.daddr = src_addr;
+
+ h0->v6.ip.len = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) -
+ sizeof (ip6_header_t));
+ h0->v6.tcp.data_offset_and_reserved |= 0x0f;
+ h0->v6.tcp.urg_ptr = htons (0xffff);
+
+ calculate_tcp_checksum_v6 (vm, b0);
+}
+
+VLIB_NODE_FN (hicn_pg_server6_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
+{
+ return hicnpg_node_server_fn (vm, node, frame, 1 /* is_v6 */);
+}
+
+VLIB_NODE_FN (hicn_pg_server4_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
+{
+ return hicnpg_node_server_fn (vm, node, frame, 0 /* is_v6 */);
+}
+
+VLIB_REGISTER_NODE(hicn_pg_server6_node) =
+{
+ .name = "hicnpg-server-6",
+ .vector_size = sizeof(u32),
+ .format_trace = format_icnpg_server_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = ARRAY_LEN(icnpg_server_error_strings),
+ .error_strings = icnpg_server_error_strings,
+ .n_next_nodes = HICNPG_SERVER_N_NEXT,
+ /* edit / add dispositions here */
+ .next_nodes =
+ {
+ [HICNPG_SERVER_NEXT_V4_LOOKUP] = "ip4-lookup",
+ [HICNPG_SERVER_NEXT_V6_LOOKUP] = "ip6-lookup",
+ [HICNPG_SERVER_NEXT_DROP] = "error-drop",
+ },
+};
+
+VLIB_REGISTER_NODE(hicn_pg_server4_node) =
+{
+ .name = "hicnpg-server-4",
+ .vector_size = sizeof(u32),
+ .format_trace = format_icnpg_server_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = ARRAY_LEN(icnpg_server_error_strings),
+ .error_strings = icnpg_server_error_strings,
+ .n_next_nodes = HICNPG_SERVER_N_NEXT,
+ /* edit / add dispositions here */
+ .next_nodes =
+ {
+ [HICNPG_SERVER_NEXT_V4_LOOKUP] = "ip4-lookup",
+ [HICNPG_SERVER_NEXT_V6_LOOKUP] = "ip6-lookup",
+ [HICNPG_SERVER_NEXT_DROP] = "error-drop",
+ },
+};
+
+/*
+ * End of packet-generator server node
+ */ \ No newline at end of file
diff --git a/hicn-plugin/src/route.c b/hicn-plugin/src/route.c
index a84891b9a..0c96e1412 100644
--- a/hicn-plugin/src/route.c
+++ b/hicn-plugin/src/route.c
@@ -34,6 +34,7 @@
#include "infra.h"
#include "udp_tunnels/udp_tunnel.h"
#include "mapme.h"
+#include "pg.h"
#define FIB_SOURCE_HICN 0x04 // Right after the FIB_SOURCE_INTERFACE priority
@@ -234,7 +235,7 @@ sync_hicn_fib_entry (hicn_dpo_ctx_t *fib_entry, hicn_face_id_t **pvec_faces)
do \
{ \
/* Careful, this adds a lock on the face if it exists */ \
- hicn_face_add (dpo, nh, sw_if, &face_id, 0); \
+ hicn_face_add (dpo, nh, sw_if, &face_id); \
vec_validate (vec_faces, index); \
vec_faces[index] = face_id; \
(index)++; \
@@ -294,10 +295,15 @@ sync_hicn_fib_entry (hicn_dpo_ctx_t *fib_entry, hicn_face_id_t **pvec_faces)
default:
continue;
}
- HICN_DEBUG ("Added new UDP face: %d because of route prefix %s",
+ HICN_DEBUG ("Added new UDP face: %d because of route prefix %U",
face_id, format_ip_prefix, &_fib_entry->fe_prefix);
udp_tunnel_add_existing (dpo->dpoi_index, proto);
}
+ else if (dpo_is_pgserver (dpo))
+ {
+ hicnpg_server_t *pg_server = hicnpg_server_get (dpo->dpoi_index);
+ ADD_FACE (&pg_server->hicn_locator);
+ }
}
const hicn_dpo_vft_t *strategy_vft = hicn_dpo_get_vft (fib_entry->dpo_type);
diff --git a/hicn-plugin/src/strategy_node.c b/hicn-plugin/src/strategy_node.c
index 66d9c2dbb..3ff2d0209 100644
--- a/hicn-plugin/src/strategy_node.c
+++ b/hicn-plugin/src/strategy_node.c
@@ -66,7 +66,7 @@ hicn_new_interest (hicn_strategy_runtime_t *rt, vlib_buffer_t *b0, u32 *next,
f64 tnow, u8 *nameptr, u16 namelen, hicn_face_id_t outface,
int nh_idx, index_t dpo_ctx_id0,
const hicn_strategy_vft_t *strategy, dpo_type_t dpo_type,
- u8 isv6, vl_api_hicn_api_node_stats_get_reply_t *stats,
+ vl_api_hicn_api_node_stats_get_reply_t *stats,
u8 is_replication)
{
int ret;
@@ -81,6 +81,7 @@ hicn_new_interest (hicn_strategy_runtime_t *rt, vlib_buffer_t *b0, u32 *next,
u8 hash_entry_id = 0;
u8 bucket_is_overflow = 0;
u32 bucket_id = ~0;
+ u8 isv6 = hicn_buffer_is_v6 (b0);
if (is_replication)
{
@@ -202,27 +203,22 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
while (n_left_from > 0 && n_left_to_next > 0)
{
- u8 isv6;
u8 *nameptr;
u16 namelen;
- hicn_name_t name;
- hicn_header_t *hicn0;
vlib_buffer_t *b0;
u32 bi0;
hicn_face_id_t outfaces[MAX_OUT_FACES];
u32 outfaces_len;
int nh_idx;
u32 next0 = next_index;
- int ret;
/* Prefetch for next iteration. */
if (n_left_from > 1)
{
vlib_buffer_t *b1;
b1 = vlib_get_buffer (vm, from[1]);
- CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (&b1->trace_handle, 2 * CLIB_CACHE_LINE_BYTES,
- STORE);
+ CLIB_PREFETCH (b1, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
+ CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, LOAD);
}
/* Dequeue a packet buffer */
bi0 = from[0];
@@ -248,7 +244,8 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
const hicn_strategy_vft_t *strategy =
hicn_dpo_get_strategy_vft (dpo_ctx->dpo_type);
- ret = hicn_interest_parse_pkt (b0, &name, &namelen, &hicn0, &isv6);
+ hicn_buffer_get_name_and_namelen (b0, &nameptr, &namelen);
+
stats.pkts_processed++;
/* Select next hop */
/*
@@ -256,8 +253,7 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
* the interest-pcslookup node due to misconfiguration in
* the punting rules.
*/
- if (PREDICT_TRUE (ret == HICN_ERROR_NONE &&
- HICN_IS_NAMEHASH_CACHED (b0) &&
+ if (PREDICT_TRUE (HICN_IS_NAMEHASH_CACHED (b0) &&
strategy->hicn_select_next_hop (
vnet_buffer (b0)->ip.adj_index[VLIB_TX], &nh_idx,
outfaces, &outfaces_len) == HICN_ERROR_NONE))
@@ -267,7 +263,6 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
* here. Already checked in the interest_pcslookup
* node
*/
- nameptr = (u8 *) (&name);
u32 clones[outfaces_len];
if (outfaces_len > 1)
{
@@ -295,7 +290,7 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
rt, local_b0, &next0, tnow, nameptr, namelen,
outfaces[nh], nh_idx,
vnet_buffer (local_b0)->ip.adj_index[VLIB_TX],
- strategy, dpo_ctx->dpo_type, isv6, &stats, 0);
+ strategy, dpo_ctx->dpo_type, &stats, 0);
}
else
{
@@ -304,7 +299,7 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
rt, local_b0, &next0, tnow, nameptr, namelen,
outfaces[nh], nh_idx,
vnet_buffer (local_b0)->ip.adj_index[VLIB_TX],
- strategy, dpo_ctx->dpo_type, isv6, &stats, 1);
+ strategy, dpo_ctx->dpo_type, &stats, 1);
}
/* Maybe trace */
@@ -314,7 +309,7 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node,
{
hicn_strategy_trace_t *t =
vlib_add_trace (vm, node, local_b0, sizeof (*t));
- t->pkt_type = HICN_PKT_TYPE_CONTENT;
+ t->pkt_type = HICN_PACKET_TYPE_DATA;
t->sw_if_index =
vnet_buffer (local_b0)->sw_if_index[VLIB_RX];
t->next_index = next0;
@@ -376,4 +371,4 @@ VLIB_REGISTER_NODE (hicn_strategy_node) =
* fd.io coding-style-patch-verification: ON
*
* Local Variables: eval: (c-set-style "gnu") End:
- */
+ */ \ No newline at end of file
diff --git a/lib/includes/CMakeLists.txt b/lib/includes/CMakeLists.txt
index 821feb2bb..392c2c94e 100644
--- a/lib/includes/CMakeLists.txt
+++ b/lib/includes/CMakeLists.txt
@@ -48,12 +48,18 @@ set(LIBHICN_HEADER_FILES_PROTOCOL
${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/udp.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/new.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/array.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/bitmap.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/hash.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/ip_address.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/khash.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/log.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/map.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/pool.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/ring.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/set.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/sstrncpy.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/token.h
${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/vector.h
PARENT_SCOPE
)
diff --git a/lib/includes/hicn/base.h b/lib/includes/hicn/base.h
index 844814d57..b825619b7 100644
--- a/lib/includes/hicn/base.h
+++ b/lib/includes/hicn/base.h
@@ -21,6 +21,8 @@
#ifndef HICN_BASE_H
#define HICN_BASE_H
+#include <stdio.h>
+#include <stdbool.h>
#include "common.h"
#ifdef _WIN32
#include <Winsock2.h>
@@ -148,6 +150,16 @@ hicn_type_is_none (hicn_type_t type)
}
/**
+ * @brief hICN Packet type
+ */
+typedef enum
+{
+ HICN_PACKET_TYPE_INTEREST,
+ HICN_PACKET_TYPE_DATA,
+ HICN_PACKET_N_TYPE,
+} hicn_packet_type_t;
+
+/**
* @brief hICN Payload type
*
* This type distinguishes several types of data packet, which can either carry
@@ -160,6 +172,61 @@ typedef enum
HPT_UNSPEC = 999
} hicn_payload_type_t;
+/***************************************************************
+ * Interest Manifest
+ ***************************************************************/
+
+#define MAX_SUFFIXES_IN_MANIFEST 255
+#define WORD_WIDTH (sizeof (uint32_t) * 8)
+#define BITMAP_SIZE ((MAX_SUFFIXES_IN_MANIFEST + 1) / WORD_WIDTH)
+
+typedef struct
+{
+ /* This can be 16 bits, but we use 32 bits for alignment */
+ uint32_t n_suffixes;
+
+ uint32_t request_bitmap[BITMAP_SIZE];
+
+ /* Followed by the list of prefixes to ask */
+ /* ... */
+} interest_manifest_header_t;
+
+// Bitmap operations
+
+static inline void
+set_bit (uint32_t *bitmap, int i)
+{
+ size_t offset = i / WORD_WIDTH;
+ size_t pos = i % WORD_WIDTH;
+ bitmap[offset] |= ((uint32_t) 1 << pos);
+}
+
+static inline void
+unset_bit (uint32_t *bitmap, int i)
+{
+ size_t offset = i / WORD_WIDTH;
+ size_t pos = i % WORD_WIDTH;
+ bitmap[offset] &= ~((uint32_t) 1 << pos);
+}
+
+static inline bool
+is_bit_set (const uint32_t *bitmap, int i)
+{
+ size_t offset = i / WORD_WIDTH;
+ size_t pos = i % WORD_WIDTH;
+ return bitmap[offset] & ((uint32_t) 1 << pos);
+}
+
+static inline void
+bitmap_print (u32 *bitmap, size_t n_words)
+{
+ for (size_t word = 0; word < n_words; word++)
+ {
+ for (int bit = 31; bit >= 0; bit--)
+ (is_bit_set (&bitmap[word], bit)) ? printf ("1") : printf ("0");
+ }
+}
+
/**
* @brief Path label computations
*
@@ -194,6 +261,79 @@ update_pathlabel (hicn_pathlabel_t current_label, hicn_faceid_t face_id,
pl_face_id;
}
+/***************************************************************
+ * Statistics
+ ***************************************************************/
+
+typedef struct
+{
+ // Packets processed
+ uint32_t countReceived; // Interest and data only
+ uint32_t countInterestsReceived;
+ uint32_t countObjectsReceived;
+
+ // Packets Dropped
+ uint32_t countDropped;
+ uint32_t countInterestsDropped;
+ uint32_t countObjectsDropped;
+ uint32_t countOtherDropped;
+
+ // Forwarding
+ uint32_t countInterestForwarded;
+ uint32_t countObjectsForwarded;
+
+ // Errors while forwarding
+ uint32_t countDroppedConnectionNotFound;
+ uint32_t countSendFailures;
+ uint32_t countDroppedNoRoute;
+
+ // Interest processing
+ uint32_t countInterestsAggregated;
+ uint32_t countInterestsRetransmitted;
+ uint32_t countInterestsSatisfiedFromStore;
+ uint32_t countInterestsExpired;
+
+ // Data processing
+ uint32_t countDroppedNoReversePath;
+ uint32_t countDataExpired;
+
+ // TODO(eloparco): Currently not used
+ // uint32_t countDroppedNoHopLimit;
+ // uint32_t countDroppedZeroHopLimitFromRemote;
+ // uint32_t countDroppedZeroHopLimitToRemote;
+} forwarder_stats_t;
+
+typedef struct
+{
+ uint32_t n_pit_entries;
+ uint32_t n_cs_entries;
+ uint32_t n_lru_evictions;
+} pkt_cache_stats_t;
+
+typedef struct
+{
+ forwarder_stats_t forwarder;
+ pkt_cache_stats_t pkt_cache;
+} hicn_light_stats_t;
+
+typedef struct
+{
+ struct
+ {
+ uint32_t rx_pkts;
+ uint32_t rx_bytes;
+ uint32_t tx_pkts;
+ uint32_t tx_bytes;
+ } interests;
+ struct
+ {
+ uint32_t rx_pkts;
+ uint32_t rx_bytes;
+ uint32_t tx_pkts;
+ uint32_t tx_bytes;
+ } data;
+} connection_stats_t;
+
#endif /* HICN_BASE_H */
/*
diff --git a/lib/includes/hicn/common.h b/lib/includes/hicn/common.h
index b0898ce1f..1998099db 100644
--- a/lib/includes/hicn/common.h
+++ b/lib/includes/hicn/common.h
@@ -224,8 +224,6 @@ ip_csum_sub_even (ip_csum_t c, ip_csum_t x)
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 (const uint8_t *buffer, size_t len);
/**
@@ -270,23 +268,75 @@ csum (const void *addr, size_t size, u16 init)
#define HICN_IP_VERSION(packet) \
((hicn_header_t *) packet)->protocol.ipv4.version
-/*
- * ntohll / htonll allows byte swapping for 64 bits integers
- */
-#ifndef htonll
-#define htonll(x) \
- ((1 == htonl (1)) ? \
- (x) : \
- ((uint64_t) htonl ((x) &0xFFFFFFFF) << 32) | htonl ((x) >> 32))
+#ifndef ntohll
+static inline uint64_t
+ntohll (uint64_t input)
+{
+ uint64_t return_val = input;
+#if (__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)
+ 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);
#endif
-#ifndef ntohll
-#define ntohll(x) \
- ((1 == ntohl (1)) ? \
- (x) : \
- ((uint64_t) ntohl ((x) &0xFFFFFFFF) << 32) | ntohl ((x) >> 32))
+ return return_val;
+}
+
+static inline uint64_t
+htonll (uint64_t input)
+{
+ return (ntohll (input));
+}
+#endif
+
+#define round_pow2(x, pow2) (((x) + (pow2) -1) & ~((pow2) -1))
+
+#define _SIZEOF_ALIGNED(x, size) round_pow2 (sizeof (x), size)
+#define SIZEOF_ALIGNED(x) _SIZEOF_ALIGNED (x, sizeof (void *))
+
+/* Definitions for builtins unavailable on MSVC */
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <intrin.h>
+
+uint32_t __inline __builtin_ctz (uint32_t value)
+{
+ uint32_t trailing_zero = 0;
+ if (_BitScanForward (&trailing_zero, value))
+ return trailing_zero;
+ else
+ return 32;
+}
+
+uint32_t __inline __builtin_clz (uint32_t value)
+{
+ uint32_t leading_zero = 0;
+ if (_BitScanReverse (&leading_zero, value))
+ return 31 - leading_zero;
+ else
+ return 32;
+}
+
+uint32_t __inline __builtin_clzl2 (uint64_t value)
+{
+ uint32_t leading_zero = 0;
+ if (_BitScanReverse64 (&leading_zero, value))
+ return 63 - leading_zero;
+ else
+ return 64;
+}
+
+#define __builtin_clzl __builtin_clzll
#endif
+#define next_pow2(x) (x <= 1 ? 1 : 1ul << (64 - __builtin_clzl (x - 1)))
+
#endif /* HICN_COMMON_H */
/*
diff --git a/lib/includes/hicn/compat.h b/lib/includes/hicn/compat.h
index 8de3f9d7e..98c035b57 100644
--- a/lib/includes/hicn/compat.h
+++ b/lib/includes/hicn/compat.h
@@ -93,6 +93,8 @@ hicn_get_ah_format (hicn_format_t format)
// HICN_V6_MIN_HDR_LEN : HICN_V4_MIN_HDR_LEN)
#define HICN_MIN_HDR_LEN HICN_V6_MIN_HDR_LEN
+hicn_type_t hicn_header_to_type (const hicn_header_t *h);
+
/**
* @brief Parse packet headers and return hICN format
* @param [in] format - hICN Format
diff --git a/lib/includes/hicn/header.h b/lib/includes/hicn/header.h
index 8af9170f8..208e35d68 100644
--- a/lib/includes/hicn/header.h
+++ b/lib/includes/hicn/header.h
@@ -135,6 +135,8 @@ typedef union
#define HICN_V4_TCP_AH_HDRLEN (HICN_V4_TCP_HDRLEN + AH_HDRLEN)
#define HICN_V4_ICMP_AH_HDRLEN (HICN_V4_ICMP_HDRLEN + AH_HDRLEN)
+#define HICN_DEFAULT_PORT 9695
+
#endif /* HICN_HEADER_H */
/*
diff --git a/lib/includes/hicn/ops.h b/lib/includes/hicn/ops.h
index e9eebc76c..4efef6523 100644
--- a/lib/includes/hicn/ops.h
+++ b/lib/includes/hicn/ops.h
@@ -257,6 +257,45 @@ typedef struct hicn_ops_s
const hicn_lifetime_t lifetime);
/**
+ * @brief Get the source port of the hicn packet.
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest or Data packet
+ * @param [out] source_port - Retrieved source port
+ * @return hICN error code
+ */
+ int (*get_source_port) (hicn_type_t type, const hicn_protocol_t *h,
+ u16 *source_port);
+
+ /**
+ * @brief Get the destination port of the hicn packet.
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest or Data packet
+ * @param [out] source_port - Retrieved destination port
+ * @return hICN error code
+ */
+ int (*get_dest_port) (hicn_type_t type, const hicn_protocol_t *h,
+ u16 *dest_port);
+
+ /**
+ * @brief Set the source port of the hicn packet.
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest or Data packet
+ * @param [out] source_port - Source port to set
+ * @return hICN error code
+ */
+ int (*set_source_port) (hicn_type_t type, hicn_protocol_t *h,
+ u16 source_port);
+
+ /**
+ * @brief Set the destination port of the hicn packet.
+ * @param [in] type - hICN packet type
+ * @param [in] h - Buffer holding the Interest or Data packet
+ * @param [out] source_port - Destination port to set
+ * @return hICN error code
+ */
+ int (*set_dest_port) (hicn_type_t type, hicn_protocol_t *h, u16 dest_port);
+
+ /**
* @brief Update all checksums in packet headers
* @param [in] type - hICN packet type
* @param [in,out] h - Buffer holding the packet
@@ -540,6 +579,10 @@ typedef struct hicn_ops_s
ATTR_INIT (reset_data_for_hash, protocol##_reset_data_for_hash), \
ATTR_INIT (get_lifetime, protocol##_get_lifetime), \
ATTR_INIT (set_lifetime, protocol##_set_lifetime), \
+ ATTR_INIT (get_source_port, protocol##_get_source_port), \
+ ATTR_INIT (get_dest_port, protocol##_get_dest_port), \
+ ATTR_INIT (set_source_port, protocol##_set_source_port), \
+ ATTR_INIT (set_dest_port, protocol##_set_dest_port), \
ATTR_INIT (update_checksums, protocol##_update_checksums), \
ATTR_INIT (verify_checksums, protocol##_verify_checksums), \
ATTR_INIT (rewrite_interest, protocol##_rewrite_interest), \
@@ -775,6 +818,34 @@ PAYLOAD (hicn_type_t type, const hicn_protocol_t *h)
return HICN_LIB_ERROR_##error; \
}
+#define DECLARE_get_source_port(protocol, error) \
+ int protocol##_get_source_port (hicn_type_t type, const hicn_protocol_t *h, \
+ u16 *source_port) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_get_dest_port(protocol, error) \
+ int protocol##_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, \
+ u16 *dest_port) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_source_port(protocol, error) \
+ int protocol##_set_source_port (hicn_type_t type, hicn_protocol_t *h, \
+ u16 source_port) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
+#define DECLARE_set_dest_port(protocol, error) \
+ int protocol##_set_dest_port (hicn_type_t type, hicn_protocol_t *h, \
+ u16 dest_port) \
+ { \
+ return HICN_LIB_ERROR_##error; \
+ }
+
#define DECLARE_update_checksums(protocol, error) \
int protocol##_update_checksums (hicn_type_t type, hicn_protocol_t *h, \
u16 partial_csum, size_t payload_length) \
diff --git a/lib/includes/hicn/util/array.h b/lib/includes/hicn/util/array.h
index 46d60976e..f56c13140 100644
--- a/lib/includes/hicn/util/array.h
+++ b/lib/includes/hicn/util/array.h
@@ -28,8 +28,6 @@
#define BUFSIZE 1024
-typedef int (*cmp_t) (const void *x, const void *y);
-
#define TYPEDEF_ARRAY_H(NAME, T) \
\
typedef struct \
@@ -151,7 +149,7 @@ typedef int (*cmp_t) (const void *x, const void *y);
for (unsigned i = 0; i < array->size; i++) \
{ \
if (CMP (search, array->elements[i]) == 0) \
- return facelet_array_remove_index (array, i, element); \
+ return NAME##_remove_index (array, i, element); \
} \
/* Not found */ \
if (element) \
diff --git a/lib/includes/hicn/util/bitmap.h b/lib/includes/hicn/util/bitmap.h
new file mode 100644
index 000000000..11eb7870b
--- /dev/null
+++ b/lib/includes/hicn/util/bitmap.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.
+ */
+
+/**
+ * \file bitmap.h
+ * \brief Bitmap
+ *
+ * A bitmap is implemented as a wrapper over a vector made of bit elements
+ */
+
+#ifndef UTIL_BITMAP_H
+#define UTIL_BITMAP_H
+
+#include <assert.h>
+#include <string.h>
+#include <sys/param.h> // MIN, MAX
+
+#include <hicn/util/log.h>
+
+#include <hicn/common.h>
+#include <hicn/util/vector.h>
+
+typedef uint_fast32_t bitmap_t;
+
+#define BITMAP_WIDTH(bitmap) (sizeof ((bitmap)[0]) * 8)
+
+/**
+ * @brief Allocate and initialize a bitmap
+ *
+ * @param[in,out] bitmap Bitmap to allocate and initialize
+ * @param[in] max_size Bitmap max_size
+ */
+#define bitmap_init(bitmap, init_size, max_size) \
+ vector_init ( \
+ bitmap, next_pow2 ((init_size) / BITMAP_WIDTH (bitmap)), \
+ max_size == 0 ? 0 : next_pow2 ((max_size) / BITMAP_WIDTH (bitmap)))
+
+/*
+ * @brief Ensures a bitmap is sufficiently large to hold an element at the
+ * given position.
+ *
+ * @param[in] bitmap The bitmap for which to validate the position.
+ * @param[in] pos The position to validate.
+ *
+ * NOTE:
+ * - This function should always be called before writing to a bitmap element
+ * to eventually make room for it (the bitmap will eventually be resized).
+ */
+static inline int
+bitmap_ensure_pos (bitmap_t **bitmap, off_t pos)
+{
+ size_t offset = pos / BITMAP_WIDTH (*bitmap);
+ return vector_ensure_pos (*bitmap, offset);
+}
+
+/**
+ * @brief Returns the allocated size of a bitmap.
+ *
+ * @see listener_table_get_by_id
+ */
+#define bitmap_get_alloc_size(bitmap) vector_get_alloc_size (bitmap)
+
+/**
+ * @brief Retrieve the state of the i-th bit in the bitmap.
+ *
+ * @param[in] bitmap The bitmap to access.
+ * @param[in] i The bit position.
+ */
+static inline int
+bitmap_get (const bitmap_t *bitmap, off_t i)
+{
+ size_t offset = i / BITMAP_WIDTH (bitmap);
+ assert (offset < bitmap_get_alloc_size (bitmap));
+ size_t pos = i % BITMAP_WIDTH (bitmap);
+ size_t shift = BITMAP_WIDTH (bitmap) - pos - 1;
+ return (bitmap[offset] >> shift) & 1;
+}
+
+/*
+ * @brief Returns whether the i-th bit is set (equal to 1) in a bitmap.
+ *
+ * @param[in] bitmap The bitmap to access.
+ * @param[in] i The bit position.
+ *
+ * @return bool
+ */
+#define bitmap_is_set(bitmap, i) (bitmap_get ((bitmap), (i)) == 1)
+#define bitmap_is_unset(bitmap, i) (bitmap_get ((bitmap), (i)) == 0)
+
+/*
+ * @brief Returns whether the i-th bit is unset (equal to 0) in a bitmap.
+ *
+ * @param[in] bitmap The bitmap to access.
+ * @param[in] i The bit position.
+ *
+ * @return bool
+ */
+#define bitmap_set(bitmap, i) _bitmap_set ((bitmap_t **) &bitmap, i)
+
+/*
+ * @brief Returns whether the i-th bit is unset (equal to 0) in a bitmap
+ * (helper).
+ *
+ * @param[in] bitmap The bitmap to access.
+ * @param[in] i The bit position.
+ *
+ * @return bool
+ */
+static inline int
+_bitmap_set (bitmap_t **bitmap_ptr, off_t i)
+{
+ if (bitmap_ensure_pos (bitmap_ptr, i) < 0)
+ return -1;
+
+ bitmap_t *bitmap = *bitmap_ptr;
+ size_t offset = i / BITMAP_WIDTH (bitmap);
+ size_t pos = i % BITMAP_WIDTH (bitmap);
+ size_t shift = BITMAP_WIDTH (bitmap) - pos - 1;
+
+ bitmap[offset] |= (bitmap_t) 1 << shift;
+ return 0;
+}
+
+static inline int
+bitmap_unset (bitmap_t *bitmap, off_t i)
+{
+ if (bitmap_ensure_pos (&bitmap, i) < 0)
+ return -1;
+ size_t offset = i / BITMAP_WIDTH (bitmap);
+ size_t pos = i % BITMAP_WIDTH (bitmap);
+ size_t shift = BITMAP_WIDTH (bitmap) - pos - 1;
+ bitmap[offset] &= ~(1ul << shift);
+ return 0;
+}
+
+static inline int
+bitmap_set_range (bitmap_t *bitmap, off_t from, off_t to)
+{
+ assert (from <= to);
+ ssize_t offset_from = from / BITMAP_WIDTH (bitmap);
+ ssize_t offset_to = to / BITMAP_WIDTH (bitmap);
+ size_t pos_from = from % BITMAP_WIDTH (bitmap);
+ size_t pos_to = to % BITMAP_WIDTH (bitmap);
+
+ /*
+ * First block initialization is needed if <from> is not aligned with the
+ * bitmap element size or if to is within the same one.
+ */
+ if ((pos_from != 0) ||
+ ((offset_to == offset_from) && (pos_to != BITMAP_WIDTH (bitmap) - 1)))
+ {
+ size_t from_end = MIN (to, (offset_from + 1) * BITMAP_WIDTH (bitmap));
+ for (size_t k = from; k < from_end; k++)
+ {
+ if (bitmap_set (bitmap, k) < 0)
+ goto END;
+ }
+ }
+
+ /*
+ * Second block is needed if <to> is not aligned with the bitmap element
+ * size
+ */
+ if ((pos_to != BITMAP_WIDTH (bitmap) - 1) && (offset_to != offset_from))
+ {
+ size_t to_start = MAX (from, offset_to * BITMAP_WIDTH (bitmap));
+ for (size_t k = to_start; k < (size_t) to; k++)
+ {
+ if (bitmap_set (bitmap, k) < 0)
+ goto END;
+ }
+ }
+
+ if (pos_from != 0)
+ offset_from += 1;
+ if (pos_to != BITMAP_WIDTH (bitmap) - 1)
+ offset_to -= 1;
+
+ /*
+ * We need to cover both elements at position offset_from and offset_to
+ * provided that offset_from is not bigger
+ */
+ if (offset_to >= offset_from)
+ {
+ memset (&bitmap[offset_from], 0xFF,
+ (offset_to - offset_from + 1) * sizeof (bitmap[0]));
+ }
+
+ return 0;
+
+END:
+ ERROR ("Error setting bitmap range\n");
+ return -1;
+}
+
+#define bitmap_set_to(bitmap, to) bitmap_set_range ((bitmap), 0, (to))
+
+#define bitmap_free(bitmap) vector_free (bitmap)
+
+#endif /* UTIL_BITMAP_H */
diff --git a/lib/includes/hicn/util/hash.h b/lib/includes/hicn/util/hash.h
new file mode 100644
index 000000000..ded8fc370
--- /dev/null
+++ b/lib/includes/hicn/util/hash.h
@@ -0,0 +1,367 @@
+/*
+ * 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.
+ */
+
+/*
+ * \file hash.h
+ * \brief Simple non-cryptographic hash implementation.
+ *
+ * Two helpers are provided :
+ * hash(buf, len) : hash a buffer <buf> of length <len>
+ * hash_struct(buf) : hash a buffer corresponding to an allocated struct
+ *
+ * This file consists in excerpts from Jenkins hash (public domain).
+ * http://www.burtleburtle.net/bob/c/lookup3.c
+ */
+#ifndef UTIL_HASH_H
+#define UTIL_HASH_H
+
+#include <stdint.h>
+
+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
+ __BYTE_ORDER == __LITTLE_ENDIAN) || \
+ (defined(i386) || defined(__i386__) || defined(__i486__) || \
+ defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
+#define HASH_LITTLE_ENDIAN 1
+#define HASH_BIG_ENDIAN 0
+#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
+ __BYTE_ORDER == __BIG_ENDIAN) || \
+ (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
+#define HASH_LITTLE_ENDIAN 0
+#define HASH_BIG_ENDIAN 1
+#else
+#define HASH_LITTLE_ENDIAN 0
+#define HASH_BIG_ENDIAN 0
+#endif
+
+#define hashsize(n) ((uint32_t) 1 << (n))
+#define hashmask(n) (hashsize (n) - 1)
+#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
+
+#define mix(a, b, c) \
+ { \
+ a -= c; \
+ a ^= rot (c, 4); \
+ c += b; \
+ b -= a; \
+ b ^= rot (a, 6); \
+ a += c; \
+ c -= b; \
+ c ^= rot (b, 8); \
+ b += a; \
+ a -= c; \
+ a ^= rot (c, 16); \
+ c += b; \
+ b -= a; \
+ b ^= rot (a, 19); \
+ a += c; \
+ c -= b; \
+ c ^= rot (b, 4); \
+ b += a; \
+ }
+
+#define final(a, b, c) \
+ { \
+ c ^= b; \
+ c -= rot (b, 14); \
+ a ^= c; \
+ a -= rot (c, 11); \
+ b ^= a; \
+ b -= rot (a, 25); \
+ c ^= b; \
+ c -= rot (b, 16); \
+ a ^= c; \
+ a -= rot (c, 4); \
+ b ^= a; \
+ b -= rot (a, 14); \
+ c ^= b; \
+ c -= rot (b, 24); \
+ }
+
+static inline uint32_t
+hashlittle (const void *key, size_t length, uint32_t initval)
+{
+ uint32_t a, b, c; /* internal state */
+ union
+ {
+ const void *ptr;
+ size_t i;
+ } u; /* needed for Mac Powerbook G4 */
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t) length) + initval;
+
+ u.ptr = key;
+ if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0))
+ {
+ const uint32_t *k = (const uint32_t *) key; /* read 32-bit chunks */
+
+ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c)
+ */
+ while (length > 12)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix (a, b, c);
+ length -= 12;
+ k += 3;
+ }
+
+ /*----------------------------- handle the last (probably partial)
+ * block */
+ /*
+ * "k[2]&0xffffff" actually reads beyond the end of the string, but
+ * then masks off the part it's not allowed to read. Because the
+ * string is aligned, the masked-off tail is in the same word as the
+ * rest of the string. Every machine with memory protection I've seen
+ * does it on word boundaries, so is OK with this. But VALGRIND will
+ * still catch it and complain. The masking trick does make the hash
+ * noticably faster for short strings (like English words).
+ */
+#ifndef VALGRIND
+
+ switch (length)
+ {
+ case 12:
+ c += k[2];
+ b += k[1];
+ a += k[0];
+ break;
+ case 11:
+ c += k[2] & 0xffffff;
+ b += k[1];
+ a += k[0];
+ break;
+ case 10:
+ c += k[2] & 0xffff;
+ b += k[1];
+ a += k[0];
+ break;
+ case 9:
+ c += k[2] & 0xff;
+ b += k[1];
+ a += k[0];
+ break;
+ case 8:
+ b += k[1];
+ a += k[0];
+ break;
+ case 7:
+ b += k[1] & 0xffffff;
+ a += k[0];
+ break;
+ case 6:
+ b += k[1] & 0xffff;
+ a += k[0];
+ break;
+ case 5:
+ b += k[1] & 0xff;
+ a += k[0];
+ break;
+ case 4:
+ a += k[0];
+ break;
+ case 3:
+ a += k[0] & 0xffffff;
+ break;
+ case 2:
+ a += k[0] & 0xffff;
+ break;
+ case 1:
+ a += k[0] & 0xff;
+ break;
+ case 0:
+ return c; /* zero length strings require no mixing */
+ }
+
+#else /* make valgrind happy */
+
+ k8 = (const uint8_t *) k;
+ switch (length)
+ {
+ case 12:
+ c += k[2];
+ b += k[1];
+ a += k[0];
+ break;
+ case 11:
+ c += ((uint32_t) k8[10]) << 16; /* fall through */
+ case 10:
+ c += ((uint32_t) k8[9]) << 8; /* fall through */
+ case 9:
+ c += k8[8]; /* fall through */
+ case 8:
+ b += k[1];
+ a += k[0];
+ break;
+ case 7:
+ b += ((uint32_t) k8[6]) << 16; /* fall through */
+ case 6:
+ b += ((uint32_t) k8[5]) << 8; /* fall through */
+ case 5:
+ b += k8[4]; /* fall through */
+ case 4:
+ a += k[0];
+ break;
+ case 3:
+ a += ((uint32_t) k8[2]) << 16; /* fall through */
+ case 2:
+ a += ((uint32_t) k8[1]) << 8; /* fall through */
+ case 1:
+ a += k8[0];
+ break;
+ case 0:
+ return c;
+ }
+
+#endif /* !valgrind */
+ }
+ else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0))
+ {
+ const uint16_t *k = (const uint16_t *) key; /* read 16-bit chunks */
+ const uint8_t *k8;
+
+ /*--------------- all but last block: aligned reads and different mixing
+ */
+ while (length > 12)
+ {
+ a += k[0] + (((uint32_t) k[1]) << 16);
+ b += k[2] + (((uint32_t) k[3]) << 16);
+ c += k[4] + (((uint32_t) k[5]) << 16);
+ mix (a, b, c);
+ length -= 12;
+ k += 6;
+ }
+
+ /*----------------------------- handle the last (probably partial) block
+ */
+ k8 = (const uint8_t *) k;
+ switch (length)
+ {
+ case 12:
+ c += k[4] + (((uint32_t) k[5]) << 16);
+ b += k[2] + (((uint32_t) k[3]) << 16);
+ a += k[0] + (((uint32_t) k[1]) << 16);
+ break;
+ case 11:
+ c += ((uint32_t) k8[10]) << 16; /* fall through */
+ case 10:
+ c += k[4];
+ b += k[2] + (((uint32_t) k[3]) << 16);
+ a += k[0] + (((uint32_t) k[1]) << 16);
+ break;
+ case 9:
+ c += k8[8]; /* fall through */
+ case 8:
+ b += k[2] + (((uint32_t) k[3]) << 16);
+ a += k[0] + (((uint32_t) k[1]) << 16);
+ break;
+ case 7:
+ b += ((uint32_t) k8[6]) << 16; /* fall through */
+ case 6:
+ b += k[2];
+ a += k[0] + (((uint32_t) k[1]) << 16);
+ break;
+ case 5:
+ b += k8[4]; /* fall through */
+ case 4:
+ a += k[0] + (((uint32_t) k[1]) << 16);
+ break;
+ case 3:
+ a += ((uint32_t) k8[2]) << 16; /* fall through */
+ case 2:
+ a += k[0];
+ break;
+ case 1:
+ a += k8[0];
+ break;
+ case 0:
+ return c; /* zero length requires no mixing */
+ }
+ }
+ else
+ { /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *) key;
+
+ /*--------------- all but the last block: affect some 32 bits of (a,b,c)
+ */
+ while (length > 12)
+ {
+ a += k[0];
+ a += ((uint32_t) k[1]) << 8;
+ a += ((uint32_t) k[2]) << 16;
+ a += ((uint32_t) k[3]) << 24;
+ b += k[4];
+ b += ((uint32_t) k[5]) << 8;
+ b += ((uint32_t) k[6]) << 16;
+ b += ((uint32_t) k[7]) << 24;
+ c += k[8];
+ c += ((uint32_t) k[9]) << 8;
+ c += ((uint32_t) k[10]) << 16;
+ c += ((uint32_t) k[11]) << 24;
+ mix (a, b, c);
+ length -= 12;
+ k += 12;
+ }
+
+ /*-------------------------------- last block: affect all 32 bits of (c)
+ */
+ switch (length) /* all the case statements fall through */
+ {
+ case 12:
+ c += ((uint32_t) k[11]) << 24;
+ case 11:
+ c += ((uint32_t) k[10]) << 16;
+ case 10:
+ c += ((uint32_t) k[9]) << 8;
+ case 9:
+ c += k[8];
+ case 8:
+ b += ((uint32_t) k[7]) << 24;
+ case 7:
+ b += ((uint32_t) k[6]) << 16;
+ case 6:
+ b += ((uint32_t) k[5]) << 8;
+ case 5:
+ b += k[4];
+ case 4:
+ a += ((uint32_t) k[3]) << 24;
+ case 3:
+ a += ((uint32_t) k[2]) << 16;
+ case 2:
+ a += ((uint32_t) k[1]) << 8;
+ case 1:
+ a += k[0];
+ break;
+ case 0:
+ return c;
+ }
+ }
+
+ final (a, b, c);
+ return c;
+}
+
+/* Helpers */
+
+#define HASH_INITVAL 1
+//#define hash(buf, len) (hash_t)hashlittle(buf, len, HASH_INITVAL)
+#define hash(buf, len) hashlittle (buf, len, HASH_INITVAL)
+#define hash_struct(buf) hash (buf, sizeof (*buf))
+
+#define str_hash(str) (hash (str, strlen (str)))
+#define str_hash_eq(a, b) (str_hash (b) - str_hash (a))
+
+#endif /* UTIL_JENKINS_HASH_H */
diff --git a/lib/includes/hicn/util/khash.h b/lib/includes/hicn/util/khash.h
new file mode 100644
index 000000000..17401091f
--- /dev/null
+++ b/lib/includes/hicn/util/khash.h
@@ -0,0 +1,826 @@
+/* The MIT License
+
+ Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+/*
+ An example:
+
+#include "khash.h"
+KHASH_MAP_INIT_INT(32, char)
+int main() {
+ int ret, is_missing;
+ khiter_t k;
+ khash_t(32) *h = kh_init(32);
+ k = kh_put(32, h, 5, &ret);
+ kh_value(h, k) = 10;
+ k = kh_get(32, h, 10);
+ is_missing = (k == kh_end(h));
+ k = kh_get(32, h, 5);
+ kh_del(32, h, k);
+ for (k = kh_begin(h); k != kh_end(h); ++k)
+ if (kh_exist(h, k)) kh_value(h, k) = 1;
+ kh_destroy(32, h);
+ return 0;
+}
+*/
+
+/*
+ 2013-05-02 (0.2.8):
+
+ * Use quadratic probing. When the capacity is power of 2, stepping
+ function i*(i+1)/2 guarantees to traverse each bucket. It is better than
+ double hashing on cache performance and is more robust than linear probing.
+
+ In theory, double hashing should be more robust than quadratic
+ probing. However, my implementation is probably not for large hash tables,
+ because the second hash function is closely tied to the first hash function,
+ which reduce the effectiveness of double hashing.
+
+ Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php
+
+ 2011-12-29 (0.2.7):
+
+ * Minor code clean up; no actual effect.
+
+ 2011-09-16 (0.2.6):
+
+ * The capacity is a power of 2. This seems to dramatically improve the
+ speed for simple keys. Thank Zilong Tan for the suggestion.
+ Reference:
+
+ - http://code.google.com/p/ulib/
+ - http://nothings.org/computer/judy/
+
+ * Allow to optionally use linear probing which usually has better
+ performance for random input. Double hashing is still the default as
+ it is more robust to certain non-random input.
+
+ * Added Wang's integer hash function (not used by default). This hash
+ function is more robust to certain non-random input.
+
+ 2011-02-14 (0.2.5):
+
+ * Allow to declare global functions.
+
+ 2009-09-26 (0.2.4):
+
+ * Improve portability
+
+ 2008-09-19 (0.2.3):
+
+ * Corrected the example
+ * Improved interfaces
+
+ 2008-09-11 (0.2.2):
+
+ * Improved speed a little in kh_put()
+
+ 2008-09-10 (0.2.1):
+
+ * Added kh_clear()
+ * Fixed a compiling error
+
+ 2008-09-02 (0.2.0):
+
+ * Changed to token concatenation which increases flexibility.
+
+ 2008-08-31 (0.1.2):
+
+ * Fixed a bug in kh_get(), which has not been tested previously.
+
+ 2008-08-31 (0.1.1):
+
+ * Added destructor
+*/
+
+#ifndef __AC_KHASH_H
+#define __AC_KHASH_H
+
+/*!
+ @header
+
+ Generic hash table library.
+ */
+
+#define AC_VERSION_KHASH_H "0.2.8"
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+/* compiler specific configuration */
+
+#if UINT_MAX == 0xffffffffu
+typedef unsigned int khint32_t;
+#elif ULONG_MAX == 0xffffffffu
+typedef unsigned long khint32_t;
+#endif
+
+#if ULONG_MAX == ULLONG_MAX
+typedef unsigned long khint64_t;
+#else
+typedef unsigned long long khint64_t;
+#endif
+
+#ifndef kh_inline
+#ifdef _MSC_VER
+#define kh_inline __inline
+#else
+#define kh_inline inline
+#endif
+#endif /* kh_inline */
+
+#ifndef klib_unused
+#if (defined __clang__ && __clang_major__ >= 3) || \
+ (defined __GNUC__ && __GNUC__ >= 3)
+#define klib_unused __attribute__ ((__unused__))
+#else
+#define klib_unused
+#endif
+#endif /* klib_unused */
+
+typedef khint32_t khint_t;
+typedef khint_t khiter_t;
+
+#define __ac_isempty(flag, i) ((flag[i >> 4] >> ((i & 0xfU) << 1)) & 2)
+#define __ac_isdel(flag, i) ((flag[i >> 4] >> ((i & 0xfU) << 1)) & 1)
+#define __ac_iseither(flag, i) ((flag[i >> 4] >> ((i & 0xfU) << 1)) & 3)
+#define __ac_set_isdel_false(flag, i) \
+ (flag[i >> 4] &= ~(1ul << ((i & 0xfU) << 1)))
+#define __ac_set_isempty_false(flag, i) \
+ (flag[i >> 4] &= ~(2ul << ((i & 0xfU) << 1)))
+#define __ac_set_isboth_false(flag, i) \
+ (flag[i >> 4] &= ~(3ul << ((i & 0xfU) << 1)))
+#define __ac_set_isdel_true(flag, i) (flag[i >> 4] |= 1ul << ((i & 0xfU) << 1))
+
+#define __ac_fsize(m) ((m) < 16 ? 1 : (m) >> 4)
+
+#ifndef kroundup32
+#define kroundup32(x) \
+ (--(x), (x) |= (x) >> 1, (x) |= (x) >> 2, (x) |= (x) >> 4, (x) |= (x) >> 8, \
+ (x) |= (x) >> 16, ++(x))
+#endif
+
+#ifndef kcalloc
+#define kcalloc(N, Z) calloc (N, Z)
+#endif
+#ifndef kmalloc
+#define kmalloc(Z) malloc (Z)
+#endif
+#ifndef krealloc
+#define krealloc(P, Z) realloc (P, Z)
+#endif
+#ifndef kfree
+#define kfree(P) free (P)
+#endif
+
+static const double __ac_HASH_UPPER = 0.77;
+
+#define __KHASH_TYPE(name, khkey_t, khval_t) \
+ typedef struct kh_##name##_s \
+ { \
+ khint_t n_buckets, size, n_occupied, upper_bound; \
+ khint32_t *flags; \
+ khkey_t *keys; \
+ khval_t *vals; \
+ } kh_##name##_t;
+
+#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
+ extern kh_##name##_t *kh_init_##name (void); \
+ extern void kh_destroy_##name (kh_##name##_t *h); \
+ extern void kh_clear_##name (kh_##name##_t *h); \
+ extern khint_t kh_get_##name (const kh_##name##_t *h, khkey_t key); \
+ extern int kh_resize_##name (kh_##name##_t *h, khint_t new_n_buckets); \
+ extern khint_t kh_put_##name (kh_##name##_t *h, khkey_t key, int *ret); \
+ extern void kh_del_##name (kh_##name##_t *h, khint_t x);
+
+#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \
+ __hash_equal) \
+ SCOPE kh_##name##_t *kh_init_##name (void) \
+ { \
+ return (kh_##name##_t *) kcalloc (1, sizeof (kh_##name##_t)); \
+ } \
+ SCOPE void kh_destroy_##name (kh_##name##_t *h) \
+ { \
+ if (h) \
+ { \
+ kfree ((void *) h->keys); \
+ kfree (h->flags); \
+ kfree ((void *) h->vals); \
+ kfree (h); \
+ } \
+ } \
+ SCOPE void kh_clear_##name (kh_##name##_t *h) \
+ { \
+ if (h && h->flags) \
+ { \
+ memset (h->flags, 0xaa, \
+ __ac_fsize (h->n_buckets) * sizeof (khint32_t)); \
+ h->size = h->n_occupied = 0; \
+ } \
+ } \
+ SCOPE khint_t kh_get_##name (const kh_##name##_t *h, khkey_t key) \
+ { \
+ if (h->n_buckets) \
+ { \
+ khint_t k, i, last, mask, step = 0; \
+ mask = h->n_buckets - 1; \
+ k = __hash_func (key); \
+ i = k & mask; \
+ last = i; \
+ while (!__ac_isempty (h->flags, i) && \
+ (__ac_isdel (h->flags, i) || !__hash_equal (h->keys[i], key))) \
+ { \
+ i = (i + (++step)) & mask; \
+ if (i == last) \
+ return h->n_buckets; \
+ } \
+ return __ac_iseither (h->flags, i) ? h->n_buckets : i; \
+ } \
+ else \
+ return 0; \
+ } \
+ SCOPE int kh_resize_##name (kh_##name##_t *h, khint_t new_n_buckets) \
+ { /* This function uses 0.25*n_buckets bytes of \
+ working space instead of \
+ [sizeof(key_t+val_t)+.25]*n_buckets. */ \
+ khint32_t *new_flags = 0; \
+ khint_t j = 1; \
+ { \
+ kroundup32 (new_n_buckets); \
+ if (new_n_buckets < 4) \
+ new_n_buckets = 4; \
+ if (h->size >= (khint_t) (new_n_buckets * __ac_HASH_UPPER + 0.5)) \
+ j = 0; /* requested size is too small */ \
+ else \
+ { /* hash table size to be changed (shrink or expand); rehash */ \
+ new_flags = (khint32_t *) kmalloc (__ac_fsize (new_n_buckets) * \
+ sizeof (khint32_t)); \
+ if (!new_flags) \
+ return -1; \
+ memset (new_flags, 0xaa, \
+ __ac_fsize (new_n_buckets) * sizeof (khint32_t)); \
+ if (h->n_buckets < new_n_buckets) \
+ { /* expand */ \
+ khkey_t *new_keys = (khkey_t *) krealloc ( \
+ (void *) h->keys, new_n_buckets * sizeof (khkey_t)); \
+ if (!new_keys) \
+ { \
+ kfree (new_flags); \
+ return -1; \
+ } \
+ h->keys = new_keys; \
+ if (kh_is_map) \
+ { \
+ khval_t *new_vals = (khval_t *) krealloc ( \
+ (void *) h->vals, new_n_buckets * sizeof (khval_t)); \
+ if (!new_vals) \
+ { \
+ kfree (new_flags); \
+ return -1; \
+ } \
+ h->vals = new_vals; \
+ } \
+ } /* otherwise shrink */ \
+ } \
+ } \
+ if (j) \
+ { /* rehashing is needed */ \
+ for (j = 0; j != h->n_buckets; ++j) \
+ { \
+ if (__ac_iseither (h->flags, j) == 0) \
+ { \
+ khkey_t key = h->keys[j]; \
+ khval_t val; \
+ khint_t new_mask; \
+ new_mask = new_n_buckets - 1; \
+ if (kh_is_map) \
+ val = h->vals[j]; \
+ __ac_set_isdel_true (h->flags, j); \
+ while (1) \
+ { /* kick-out process; sort of like in Cuckoo hashing */ \
+ khint_t k, i, step = 0; \
+ k = __hash_func (key); \
+ i = k & new_mask; \
+ while (!__ac_isempty (new_flags, i)) \
+ i = (i + (++step)) & new_mask; \
+ __ac_set_isempty_false (new_flags, i); \
+ if (i < h->n_buckets && __ac_iseither (h->flags, i) == 0) \
+ { /* kick out the existing element */ \
+ { \
+ khkey_t tmp = h->keys[i]; \
+ h->keys[i] = key; \
+ key = tmp; \
+ } \
+ if (kh_is_map) \
+ { \
+ khval_t tmp = h->vals[i]; \
+ h->vals[i] = val; \
+ val = tmp; \
+ } \
+ __ac_set_isdel_true ( \
+ h->flags, \
+ i); /* mark it as deleted in the old hash table */ \
+ } \
+ else \
+ { /* write the element and jump out of the loop */ \
+ h->keys[i] = key; \
+ if (kh_is_map) \
+ h->vals[i] = val; \
+ break; \
+ } \
+ } \
+ } \
+ } \
+ if (h->n_buckets > new_n_buckets) \
+ { /* shrink the hash table */ \
+ h->keys = (khkey_t *) krealloc ( \
+ (void *) h->keys, new_n_buckets * sizeof (khkey_t)); \
+ if (kh_is_map) \
+ h->vals = (khval_t *) krealloc ( \
+ (void *) h->vals, new_n_buckets * sizeof (khval_t)); \
+ } \
+ kfree (h->flags); /* free the working space */ \
+ h->flags = new_flags; \
+ h->n_buckets = new_n_buckets; \
+ h->n_occupied = h->size; \
+ h->upper_bound = (khint_t) (h->n_buckets * __ac_HASH_UPPER + 0.5); \
+ } \
+ return 0; \
+ } \
+ SCOPE khint_t kh_put_##name (kh_##name##_t *h, khkey_t key, int *ret) \
+ { \
+ khint_t x; \
+ if (h->n_occupied >= h->upper_bound) \
+ { /* update the hash table */ \
+ if (h->n_buckets > (h->size << 1)) \
+ { \
+ if (kh_resize_##name (h, h->n_buckets - 1) < 0) \
+ { /* clear "deleted" elements */ \
+ *ret = -1; \
+ return h->n_buckets; \
+ } \
+ } \
+ else if (kh_resize_##name (h, h->n_buckets + 1) < 0) \
+ { /* expand the hash table */ \
+ *ret = -1; \
+ return h->n_buckets; \
+ } \
+ } /* TODO: to implement automatically shrinking; resize() already \
+ support shrinking */ \
+ { \
+ khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \
+ x = site = h->n_buckets; \
+ k = __hash_func (key); \
+ i = k & mask; \
+ if (__ac_isempty (h->flags, i)) \
+ x = i; /* for speed up */ \
+ else \
+ { \
+ last = i; \
+ while ( \
+ !__ac_isempty (h->flags, i) && \
+ (__ac_isdel (h->flags, i) || !__hash_equal (h->keys[i], key))) \
+ { \
+ if (__ac_isdel (h->flags, i)) \
+ site = i; \
+ i = (i + (++step)) & mask; \
+ if (i == last) \
+ { \
+ x = site; \
+ break; \
+ } \
+ } \
+ if (x == h->n_buckets) \
+ { \
+ if (__ac_isempty (h->flags, i) && site != h->n_buckets) \
+ x = site; \
+ else \
+ x = i; \
+ } \
+ } \
+ } \
+ if (__ac_isempty (h->flags, x)) \
+ { /* not present at all */ \
+ h->keys[x] = key; \
+ __ac_set_isboth_false (h->flags, x); \
+ ++h->size; \
+ ++h->n_occupied; \
+ *ret = 1; \
+ } \
+ else if (__ac_isdel (h->flags, x)) \
+ { /* deleted */ \
+ h->keys[x] = key; \
+ __ac_set_isboth_false (h->flags, x); \
+ ++h->size; \
+ *ret = 2; \
+ } \
+ else \
+ *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \
+ return x; \
+ } \
+ SCOPE void kh_del_##name (kh_##name##_t *h, khint_t x) \
+ { \
+ if (x != h->n_buckets && !__ac_iseither (h->flags, x)) \
+ { \
+ __ac_set_isdel_true (h->flags, x); \
+ --h->size; \
+ } \
+ }
+
+#define KHASH_DECLARE(name, khkey_t, khval_t) \
+ __KHASH_TYPE (name, khkey_t, khval_t) \
+ __KHASH_PROTOTYPES (name, khkey_t, khval_t)
+
+#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \
+ __hash_equal) \
+ __KHASH_TYPE (name, khkey_t, khval_t) \
+ __KHASH_IMPL (name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, \
+ __hash_equal)
+
+#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, \
+ __hash_equal) \
+ KHASH_INIT2 (name, static kh_inline klib_unused, khkey_t, khval_t, \
+ kh_is_map, __hash_func, __hash_equal)
+
+/* --- BEGIN OF HASH FUNCTIONS --- */
+
+/*! @function
+ @abstract Integer hash function
+ @param key The integer [khint32_t]
+ @return The hash value [khint_t]
+ */
+#define kh_int_hash_func(key) (khint32_t) (key)
+/*! @function
+ @abstract Integer comparison function
+ */
+#define kh_int_hash_equal(a, b) ((a) == (b))
+/*! @function
+ @abstract 64-bit integer hash function
+ @param key The integer [khint64_t]
+ @return The hash value [khint_t]
+ */
+#define kh_int64_hash_func(key) (khint32_t) ((key) >> 33 ^ (key) ^ (key) << 11)
+/*! @function
+ @abstract 64-bit integer comparison function
+ */
+#define kh_int64_hash_equal(a, b) ((a) == (b))
+/*! @function
+ @abstract const char* hash function
+ @param s Pointer to a null terminated string
+ @return The hash value
+ */
+static kh_inline khint_t
+__ac_X31_hash_string (const char *s)
+{
+ khint_t h = (khint_t) *s;
+ if (h)
+ for (++s; *s; ++s)
+ h = (h << 5) - h + (khint_t) *s;
+ return h;
+}
+/*! @function
+ @abstract Another interface to const char* hash function
+ @param key Pointer to a null terminated string [const char*]
+ @return The hash value [khint_t]
+ */
+#define kh_str_hash_func(key) __ac_X31_hash_string (key)
+/*! @function
+ @abstract Const char* comparison function
+ */
+#define kh_str_hash_equal(a, b) (strcmp (a, b) == 0)
+
+static kh_inline khint_t
+__ac_Wang_hash (khint_t key)
+{
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+}
+#define kh_int_hash_func2(key) __ac_Wang_hash ((khint_t) key)
+
+/* --- END OF HASH FUNCTIONS --- */
+
+/* Other convenient macros... */
+
+/*!
+ @abstract Type of the hash table.
+ @param name Name of the hash table [symbol]
+ */
+#define khash_t(name) kh_##name##_t
+
+/*! @function
+ @abstract Initiate a hash table.
+ @param name Name of the hash table [symbol]
+ @return Pointer to the hash table [khash_t(name)*]
+ */
+#define kh_init(name) kh_init_##name ()
+
+/*! @function
+ @abstract Destroy a hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ */
+#define kh_destroy(name, h) kh_destroy_##name (h)
+
+/*! @function
+ @abstract Reset a hash table without deallocating memory.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ */
+#define kh_clear(name, h) kh_clear_##name (h)
+
+/*! @function
+ @abstract Resize a hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param s New size [khint_t]
+ */
+#define kh_resize(name, h, s) kh_resize_##name (h, s)
+
+/*! @function
+ @abstract Insert a key to the hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param k Key [type of keys]
+ @param r Extra return code: -1 if the operation failed;
+ 0 if the key is present in the hash table;
+ 1 if the bucket is empty (never used); 2 if the element in
+ the bucket has been deleted [int*]
+ @return Iterator to the inserted element [khint_t]
+ */
+#define kh_put(name, h, k, r) kh_put_##name (h, k, r)
+
+/*! @function
+ @abstract Retrieve a key from the hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param k Key [type of keys]
+ @return Iterator to the found element, or kh_end(h) if the element is
+ absent [khint_t]
+ */
+#define kh_get(name, h, k) kh_get_##name (h, k)
+
+/*! @function
+ @abstract Remove a key from the hash table.
+ @param name Name of the hash table [symbol]
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param k Iterator to the element to be deleted [khint_t]
+ */
+#define kh_del(name, h, k) kh_del_##name (h, k)
+
+/*! @function
+ @abstract Test whether a bucket contains data.
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param x Iterator to the bucket [khint_t]
+ @return 1 if containing data; 0 otherwise [int]
+ */
+#define kh_exist(h, x) (!__ac_iseither ((h)->flags, (x)))
+
+/*! @function
+ @abstract Get key given an iterator
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param x Iterator to the bucket [khint_t]
+ @return Key [type of keys]
+ */
+#define kh_key(h, x) ((h)->keys[x])
+
+/*! @function
+ @abstract Get value given an iterator
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param x Iterator to the bucket [khint_t]
+ @return Value [type of values]
+ @discussion For hash sets, calling this results in segfault.
+ */
+#define kh_val(h, x) ((h)->vals[x])
+
+/*! @function
+ @abstract Alias of kh_val()
+ */
+#define kh_value(h, x) ((h)->vals[x])
+
+/*! @function
+ @abstract Get the start iterator
+ @param h Pointer to the hash table [khash_t(name)*]
+ @return The start iterator [khint_t]
+ */
+#define kh_begin(h) (khint_t) (0)
+
+/*! @function
+ @abstract Get the end iterator
+ @param h Pointer to the hash table [khash_t(name)*]
+ @return The end iterator [khint_t]
+ */
+#define kh_end(h) ((h)->n_buckets)
+
+/*! @function
+ @abstract Get the number of elements in the hash table
+ @param h Pointer to the hash table [khash_t(name)*]
+ @return Number of elements in the hash table [khint_t]
+ */
+#define kh_size(h) ((h)->size)
+
+/*! @function
+ @abstract Get the number of buckets in the hash table
+ @param h Pointer to the hash table [khash_t(name)*]
+ @return Number of buckets in the hash table [khint_t]
+ */
+#define kh_n_buckets(h) ((h)->n_buckets)
+
+/*! @function
+ @abstract Iterate over the entries in the hash table
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param kvar Variable to which key will be assigned
+ @param vvar Variable to which value will be assigned
+ @param code Block of code to execute
+ */
+#define kh_foreach(h, kvar, vvar, code) \
+ { \
+ khint_t __i; \
+ for (__i = kh_begin (h); __i != kh_end (h); ++__i) \
+ { \
+ if (!kh_exist (h, __i)) \
+ continue; \
+ (kvar) = kh_key (h, __i); \
+ (vvar) = kh_val (h, __i); \
+ code; \
+ } \
+ }
+
+/*! @function
+ @abstract Iterate over the values in the hash table
+ @param h Pointer to the hash table [khash_t(name)*]
+ @param vvar Variable to which value will be assigned
+ @param code Block of code to execute
+ */
+#define kh_foreach_value(h, vvar, code) \
+ { \
+ khint_t __i; \
+ for (__i = kh_begin (h); __i != kh_end (h); ++__i) \
+ { \
+ if (!kh_exist (h, __i)) \
+ continue; \
+ (vvar) = kh_val (h, __i); \
+ code; \
+ } \
+ }
+
+/* More convenient interfaces */
+
+/*! @function
+ @abstract Instantiate a hash set containing integer keys
+ @param name Name of the hash table [symbol]
+ */
+#define KHASH_SET_INIT_INT(name) \
+ KHASH_INIT (name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
+
+/*! @function
+ @abstract Instantiate a hash map containing integer keys
+ @param name Name of the hash table [symbol]
+ @param khval_t Type of values [type]
+ */
+#define KHASH_MAP_INIT_INT(name, khval_t) \
+ KHASH_INIT (name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
+
+/*! @function
+ @abstract Instantiate a hash set containing 64-bit integer keys
+ @param name Name of the hash table [symbol]
+ */
+#define KHASH_SET_INIT_INT64(name) \
+ KHASH_INIT (name, khint64_t, char, 0, kh_int64_hash_func, \
+ kh_int64_hash_equal)
+
+/*! @function
+ @abstract Instantiate a hash map containing 64-bit integer keys
+ @param name Name of the hash table [symbol]
+ @param khval_t Type of values [type]
+ */
+#define KHASH_MAP_INIT_INT64(name, khval_t) \
+ KHASH_INIT (name, khint64_t, khval_t, 1, kh_int64_hash_func, \
+ kh_int64_hash_equal)
+
+typedef const char *kh_cstr_t;
+/*! @function
+ @abstract Instantiate a hash map containing const char* keys
+ @param name Name of the hash table [symbol]
+ */
+#define KHASH_SET_INIT_STR(name) \
+ KHASH_INIT (name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
+
+/*! @function
+ @abstract Instantiate a hash map containing const char* keys
+ @param name Name of the hash table [symbol]
+ @param khval_t Type of values [type]
+ */
+#define KHASH_MAP_INIT_STR(name, khval_t) \
+ KHASH_INIT (name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
+
+/******************************************************************************
+ * Custom return codes
+ ******************************************************************************/
+
+// RESET: same as added, but the key was already added in the past
+#define foreach_kh_rc \
+ _ (REPLACED) \
+ _ (ADDED) \
+ _ (RESET) \
+ _ (NOT_FOUND) \
+ _ (FOUND) \
+ _ (FAIL)
+
+typedef enum
+{
+#define _(x) KH_##x,
+ foreach_kh_rc
+#undef _
+} kh_rc;
+
+/******************************************************************************
+ * Custom
+ *high-level interface
+ ******************************************************************************/
+
+#define _kh_var(x) _kh_var_##x
+
+/**
+ * @brief Return the value corresponding to a key in the hashtable.
+ * @return The value associated with the key or null if not found
+ */
+#define kh_get_val(kname, hashtable, key, default_val) \
+ ({ \
+ khiter_t _kh_var (k) = kh_get (kname, hashtable, key); \
+ (_kh_var (k) != kh_end (hashtable) ? kh_val (hashtable, _kh_var (k)) : \
+ default_val); \
+ })
+
+/**
+ * @brief Add key/value pair in the hashtable.
+ * @return 0 if an existing value (corresponding to the provided key)
+ * has been replaced; 1 if a new key/value pair has been added
+ * (the key was not already present in the hash table);
+ * 2 if a new key/value pair has been added in correspondence
+ * of a key previously deleted key
+ */
+#define kh_put_val(kname, hashtable, key, val) \
+ ({ \
+ int _kh_var (ret); \
+ khiter_t _kh_var (k) = kh_put (kname, hashtable, key, &_kh_var (ret)); \
+ kh_value (hashtable, _kh_var (k)) = val; \
+ _kh_var (ret); \
+ })
+
+/**
+ * @brief Remove a key/value pair from the hashtable.
+ * @return void
+ */
+#define kh_remove_val(kname, hashtable, key) \
+ ({ \
+ khiter_t _kh_var (k) = kh_get (kname, hashtable, key); \
+ if (_kh_var (k) != kh_end (hashtable)) \
+ { \
+ free ((void *) kh_key (hashtable, _kh_var (k))); \
+ kh_del (kname, hashtable, _kh_var (k)); \
+ } \
+ })
+
+/**
+ * @brief Free the hashtable.
+ * @return void
+ */
+#define kh_free(kname, hashtable) \
+ ({ \
+ const void *_kh_var (key); \
+ unsigned _kh_var (val); \
+ (void) _kh_var (val); \
+ \
+ kh_foreach (hashtable, _kh_var (key), _kh_var (val), { \
+ free ((void *) _kh_var (key)); \
+ }) kh_destroy (kname, hashtable); \
+ })
+
+#endif /* __AC_KHASH_H */
diff --git a/hicn-light/src/hicn/base/pool.h b/lib/includes/hicn/util/pool.h
index b6573195c..7488e08fd 100644
--- a/hicn-light/src/hicn/base/pool.h
+++ b/lib/includes/hicn/util/pool.h
@@ -47,22 +47,24 @@
#include <stdbool.h>
#include "bitmap.h"
-#include "vector.h"
+#include <hicn/util/vector.h>
+#include "../common.h"
/* Pool header */
-typedef struct {
+typedef struct
+{
size_t elt_size;
size_t alloc_size;
size_t max_size;
bitmap_t *free_bitmap; /* bitmap of free indices */
- off_t *free_indices; /* vector of free indices */
+ off_t *free_indices; /* vector of free indices */
} pool_hdr_t;
-#define POOL_HDRLEN SIZEOF_ALIGNED(pool_hdr_t)
+#define POOL_HDRLEN SIZEOF_ALIGNED (pool_hdr_t)
/* This header actually prepends the actual content of the pool. */
-#define pool_hdr(pool) ((pool_hdr_t *)((uint8_t *)(pool)-POOL_HDRLEN))
+#define pool_hdr(pool) ((pool_hdr_t *) ((uint8_t *) (pool) -POOL_HDRLEN))
/******************************************************************************/
/* Helpers */
@@ -79,15 +81,15 @@ typedef struct {
*
* NOTE: that an empty pool might be equal to NULL.
*/
-void _pool_init(void **pool_ptr, size_t elt_size, size_t init_size,
- size_t max_size);
+void _pool_init (void **pool_ptr, size_t elt_size, size_t init_size,
+ size_t max_size);
/**
* @brief Free a pool data structure (helper).
*
* @param[in] pool_ptr Pointer to the pool data structure.
*/
-void _pool_free(void **pool_ptr);
+void _pool_free (void **pool_ptr);
/**
* @brief Resize a pool data structure (helper).
@@ -97,7 +99,7 @@ void _pool_free(void **pool_ptr);
* This function should only be called internally, as the resize is implicitly
* done (if allowed by the maximum size) when the user tries to get a new slot.
*/
-void _pool_resize(void **pool_ptr, size_t elt_size);
+void _pool_resize (void **pool_ptr, size_t elt_size);
/**
* @brief Get a free element from the pool data structure (helper).
@@ -109,7 +111,7 @@ void _pool_resize(void **pool_ptr, size_t elt_size);
* NOTES:
* - The memory chunk is cleared upon attribution
*/
-off_t _pool_get(void **pool, void **elt, size_t elt_size);
+off_t _pool_get (void **pool, void **elt, size_t elt_size);
/**
* @brief Put an element back into the pool data structure (helper).
@@ -117,7 +119,7 @@ off_t _pool_get(void **pool, void **elt, size_t elt_size);
* @param[in] pool_ptr Pointer to the pool data structure to use.
* @param[in] elt Pointer to the pool element to put back.
*/
-void _pool_put(void **pool, void **elt, size_t elt_size);
+void _pool_put (void **pool, void **elt, size_t elt_size);
/**
* @brief Validate a pool element by index (helper).
@@ -127,7 +129,7 @@ void _pool_put(void **pool, void **elt, size_t elt_size);
*
* @return bool A flag indicating whether the index is valid or not.
*/
-bool _pool_validate_id(void **pool_ptr, off_t id);
+bool _pool_validate_id (void **pool_ptr, off_t id);
/******************************************************************************/
/* Public API */
@@ -140,15 +142,15 @@ bool _pool_validate_id(void **pool_ptr, off_t id);
*
* NOTE: that an empty pool might be equal to NULL.
*/
-#define pool_init(pool, init_size, max_size) \
- _pool_init((void **)&pool, sizeof(pool[0]), init_size, max_size);
+#define pool_init(pool, init_size, max_size) \
+ _pool_init ((void **) &pool, sizeof (pool[0]), init_size, max_size);
/**
* @brief Free a pool data structure.
*
* @param[in] pool The pool data structure to free.
*/
-#define pool_free(pool) _pool_free((void **)&pool);
+#define pool_free(pool) _pool_free ((void **) &pool);
/**
* @brief Get a free element from the pool data structure.
@@ -160,8 +162,8 @@ bool _pool_validate_id(void **pool_ptr, off_t id);
* NOTES:
* - The memory chunk is cleared upon attribution
*/
-#define pool_get(pool, elt) \
- _pool_get((void **)&pool, (void **)&elt, sizeof(*elt))
+#define pool_get(pool, elt) \
+ _pool_get ((void **) &pool, (void **) &elt, sizeof (*elt))
/**
* @brief Put an element back into the pool data structure.
@@ -169,8 +171,8 @@ bool _pool_validate_id(void **pool_ptr, off_t id);
* @param[in] pool The pool data structure to use.
* @param[in] elt The pool element to put back.
*/
-#define pool_put(pool, elt) \
- _pool_put((void **)&pool, (void **)&elt, sizeof(*elt))
+#define pool_put(pool, elt) \
+ _pool_put ((void **) &pool, (void **) &elt, sizeof (*elt))
/**
* @brief Validate a pool element by index.
@@ -180,10 +182,10 @@ bool _pool_validate_id(void **pool_ptr, off_t id);
*
* @return bool A flag indicating whether the index is valid or not.
*/
-#define pool_validate_id(pool, id) _pool_validate_id((void **)&pool, (id))
+#define pool_validate_id(pool, id) _pool_validate_id ((void **) &pool, (id))
-#define pool_get_free_indices_size(pool) \
- vector_len(pool_hdr(pool)->free_indices)
+#define pool_get_free_indices_size(pool) \
+ vector_len (pool_hdr (pool)->free_indices)
/**
* @brief Returns the current length of the pool.
@@ -196,8 +198,8 @@ bool _pool_validate_id(void **pool_ptr, off_t id);
* - The pool length corresponds to the number of allocated elements, not the
* size of the pool.
*/
-#define pool_len(pool) \
- (pool_hdr(pool)->alloc_size - pool_get_free_indices_size(pool))
+#define pool_len(pool) \
+ (pool_hdr (pool)->alloc_size - pool_get_free_indices_size (pool))
/**
* @brief Enumerate elements from a pool.
@@ -213,18 +215,24 @@ bool _pool_validate_id(void **pool_ptr, off_t id);
*
* NOTE: i stars at 0.
*/
-#define pool_enumerate(pool, i, eltp, BODY) \
- do { \
- pool_hdr_t *_pool_var(ph) = pool_hdr(pool); \
- bitmap_t *_pool_var(fb) = _pool_var(ph)->free_bitmap; \
- for ((i) = 0; (i) < _pool_var(ph)->alloc_size; (i)++) { \
- if (bitmap_is_set(_pool_var(fb), (i))) continue; \
- eltp = (pool) + (i); \
- do { \
- BODY; \
- } while (0); \
- } \
- } while (0)
+#define pool_enumerate(pool, i, eltp, BODY) \
+ do \
+ { \
+ pool_hdr_t *_pool_var (ph) = pool_hdr (pool); \
+ bitmap_t *_pool_var (fb) = _pool_var (ph)->free_bitmap; \
+ for ((i) = 0; (i) < _pool_var (ph)->alloc_size; (i)++) \
+ { \
+ if (bitmap_is_set (_pool_var (fb), (i))) \
+ continue; \
+ eltp = (pool) + (i); \
+ do \
+ { \
+ BODY; \
+ } \
+ while (0); \
+ } \
+ } \
+ while (0)
/**
* @brief Iterate over elements in a pool.
@@ -238,17 +246,19 @@ bool _pool_validate_id(void **pool_ptr, off_t id);
* elements found in the pool. It is implemented using the more generic
* enumeration function.
*/
-#define pool_foreach(pool, eltp, BODY) \
- do { \
- unsigned _pool_var(i); \
- pool_enumerate((pool), _pool_var(i), (eltp), BODY); \
- } while (0)
+#define pool_foreach(pool, eltp, BODY) \
+ do \
+ { \
+ unsigned _pool_var (i); \
+ pool_enumerate ((pool), _pool_var (i), (eltp), BODY); \
+ } \
+ while (0)
-#define pool_get_alloc_size(pool) pool_hdr(pool)->alloc_size
+#define pool_get_alloc_size(pool) pool_hdr (pool)->alloc_size
#ifdef WITH_TESTS
-#define pool_get_free_indices(pool) pool_hdr(pool)->free_indices
-#define pool_get_free_bitmap(pool) pool_hdr(pool)->free_bitmap
+#define pool_get_free_indices(pool) pool_hdr (pool)->free_indices
+#define pool_get_free_bitmap(pool) pool_hdr (pool)->free_bitmap
#endif /* WITH_TESTS */
#endif /* UTIL_POOL_H */
diff --git a/lib/includes/hicn/util/ring.h b/lib/includes/hicn/util/ring.h
new file mode 100644
index 000000000..9510672b3
--- /dev/null
+++ b/lib/includes/hicn/util/ring.h
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+/**
+ * \file ring.h
+ * \brief Fixed-size pool allocator.
+ */
+
+#ifndef UTIL_RING_H
+#define UTIL_RING_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/param.h> // MIN
+#include <sys/types.h>
+
+#include <stdio.h> // XXX debug
+
+#include "../common.h"
+
+/******************************************************************************/
+/* Ring header */
+
+typedef struct
+{
+ size_t roff;
+ size_t woff;
+ size_t size;
+ size_t max_size;
+} ring_hdr_t;
+
+/* Make sure elements following the header are aligned */
+#define RING_HDRLEN SIZEOF_ALIGNED (ring_hdr_t)
+
+/* This header actually prepends the actual content of the vector */
+#define ring_hdr(ring) ((ring_hdr_t *) ((uint8_t *) ring - RING_HDRLEN))
+
+/******************************************************************************/
+/* Helpers */
+
+/** Local variable naming macro. */
+#define _ring_var(v) _ring_##v
+
+/**
+ * @brief Allocate and initialize a ring data structure (helper function).
+ *
+ * @param[in,out] ring_ptr Ring buffer to allocate and initialize.
+ * @param[in] elt_size Size of a ring element.
+ * @param[in] max_size Maximum vector size (O = unlimited).
+ */
+void _ring_init (void **ring_ptr, size_t elt_size, size_t max_size);
+
+/**
+ * @brief Free a ring data structure.
+ *
+ * @param ring_ptr[in] Pointer to the ring data structure to free.
+ */
+void _ring_free (void **ring_ptr);
+
+static inline int
+_ring_add (void **ring_ptr, size_t elt_size, void *eltp)
+{
+ assert (*ring_ptr);
+ ring_hdr_t *rh = ring_hdr (*ring_ptr);
+
+ /* We always write ! */
+ memcpy ((uint8_t *) *ring_ptr + rh->woff * elt_size, eltp, elt_size);
+ rh->woff++;
+ if (rh->woff == rh->max_size)
+ rh->woff = 0;
+ if (rh->size < rh->max_size)
+ {
+ rh->size++;
+ }
+ else
+ {
+ /* One packet was dropped */
+ rh->roff++;
+ if (rh->roff == rh->max_size)
+ rh->roff = 0;
+ }
+ return 0;
+}
+
+static inline unsigned
+_ring_get_fullness (void **ring_ptr)
+{
+ assert (*ring_ptr);
+ ring_hdr_t *rh = ring_hdr (*ring_ptr);
+ return (unsigned int) (rh->size * 100 / rh->max_size);
+}
+
+static inline unsigned
+_ring_is_full (void **ring_ptr)
+{
+ assert (*ring_ptr);
+ ring_hdr_t *rh = ring_hdr (*ring_ptr);
+ return rh->size == rh->max_size;
+}
+
+static inline size_t
+_ring_get_size (void **ring_ptr)
+{
+ assert (*ring_ptr);
+ ring_hdr_t *rh = ring_hdr (*ring_ptr);
+ return rh->size;
+}
+
+static inline int
+_ring_advance (void **ring_ptr, unsigned n)
+{
+ assert (*ring_ptr);
+ ring_hdr_t *rh = ring_hdr (*ring_ptr);
+ assert (n <= rh->size);
+
+ rh->roff += n;
+ rh->size -= n;
+ while (rh->roff >= rh->max_size)
+ rh->roff -= rh->max_size;
+ return 0;
+}
+
+static inline int
+_ring_get (void **ring_ptr, size_t elt_size, unsigned i, void *eltp)
+{
+ assert (*ring_ptr);
+ ring_hdr_t *rh = ring_hdr (*ring_ptr);
+ assert (i <= rh->size);
+ size_t pos = rh->roff + i;
+ if (pos >= rh->max_size)
+ pos -= rh->max_size;
+ memcpy (eltp, (uint8_t *) *ring_ptr + pos * elt_size, elt_size);
+ return 0;
+}
+
+/******************************************************************************/
+/* Public API */
+
+/**
+ * @brief Allocate and initialize a ring data structure.
+ *
+ * @param[in,out] ring Ring to allocate and initialize.
+ * @param[in] max_size Maximum ring size (nonzero).
+ *
+ * NOTE:
+ * - Allocated memory is set to 0 (used by bitmap)
+ */
+
+#define ring_init(RING, MAX_SIZE) \
+ _ring_init ((void **) &(RING), sizeof ((RING)[0]), (MAX_SIZE))
+
+#define ring_free(RING) _ring_free ((void **) &(RING))
+
+#define ring_get_fullness(RING) _ring_get_fullness ((void **) &(RING))
+
+#define ring_is_full(RING) _ring_is_full ((void **) &(RING))
+
+#define ring_get_size(RING) _ring_get_size ((void **) &(RING))
+
+#define ring_add(RING, ELT) \
+ _ring_add ((void **) &(RING), sizeof (RING[0]), ELT)
+
+#define ring_add_value(RING, VALUE) \
+ do \
+ { \
+ typeof (VALUE) _ring_var (v) = VALUE; \
+ _ring_add ((void **) &(RING), sizeof (RING[0]), &_ring_var (v)); \
+ } \
+ while (0)
+
+#define ring_advance(RING, N) _ring_advance ((void **) &(RING), (N))
+
+#define ring_get(RING, I, ELTP) \
+ _ring_get ((void **) &RING, sizeof (RING[0]), (I), (ELTP))
+
+/**
+ * @brief Helper function used by ring_foreach().
+ */
+#define ring_enumerate_n(RING, I, ELTP, COUNT, BODY) \
+ ({ \
+ for ((I) = 0; (I) < MIN (ring_get_size (RING), (COUNT)); (I)++) \
+ { \
+ ring_get ((RING), (I), (ELTP)); \
+ { \
+ BODY; \
+ } \
+ } \
+ })
+
+#define ring_enumerate(ring, i, eltp, BODY) \
+ ring_enumerate_n ((ring), (i), (eltp), 1, (BODY))
+
+/**
+ * @brief Iterate over elements in a ring.
+ *
+ * @param[in] pool The ring data structure to iterate over
+ * @param[in, out] eltp A pointer to the element that will be used for
+ * iteration
+ * @param[in] BODY Block to execute during iteration
+ *
+ * @note Iteration will execute BODY with eltp corresponding successively to
+ * all elements found in the ring. It is implemented using the more generic
+ * enumeration function.
+ */
+#define ring_foreach_n(ring, eltp, count, BODY) \
+ ({ \
+ unsigned _ring_var (i); \
+ ring_enumerate_n ((ring), _ring_var (i), (eltp), (count), BODY); \
+ })
+
+#define ring_foreach(ring, eltp, BODY) \
+ ring_foreach_n ((ring), (eltp), 1, (BODY))
+
+#endif /* UTIL_RING_H */
diff --git a/hicn-light/src/hicn/base/vector.h b/lib/includes/hicn/util/vector.h
index 0b7a74aeb..46f195c6d 100644
--- a/hicn-light/src/hicn/base/vector.h
+++ b/lib/includes/hicn/util/vector.h
@@ -50,24 +50,27 @@
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
+#include <stdbool.h>
-#include "common.h"
+#include "../common.h"
/******************************************************************************/
/* Vector header */
-typedef struct {
+typedef struct
+{
size_t cur_size; /** Vector current size (corresponding to the highest used
- element). */
+ element). */
size_t alloc_size; /** The currently allocated size. */
size_t max_size; /** The maximum allowed size (0 = no limit) */
} vector_hdr_t;
/* Make sure elements following the header are aligned */
-#define VECTOR_HDRLEN SIZEOF_ALIGNED(vector_hdr_t)
+#define VECTOR_HDRLEN SIZEOF_ALIGNED (vector_hdr_t)
/* This header actually prepends the actual content of the vector */
-#define vector_hdr(vector) ((vector_hdr_t *)((uint8_t *)vector - VECTOR_HDRLEN))
+#define vector_hdr(vector) \
+ ((vector_hdr_t *) ((uint8_t *) vector - VECTOR_HDRLEN))
/******************************************************************************/
/* Helpers */
@@ -82,16 +85,17 @@ typedef struct {
* @param[in] elt_size Size of a vector element.
* @param[in] init_size Initial vector size.
* @param[in] max_size Maximum vector size (O = unlimited).
+ * @return int 0 if successful, -1 otherwise
*/
-void _vector_init(void **vector_ptr, size_t elt_size, size_t init_size,
- size_t max_size);
+int _vector_init (void **vector_ptr, size_t elt_size, size_t init_size,
+ size_t max_size);
/**
* @brief Free a vector data structure.
*
* @param vector_ptr[in] Pointer to the vector data structure to free.
*/
-void _vector_free(void **vector_ptr);
+void _vector_free (void **vector_ptr);
/**
* @brief Resize a vector data structure.
@@ -109,7 +113,7 @@ void _vector_free(void **vector_ptr);
* position. This allows the caller not to care about doing successive calls to
* this API while the vector is growing in size.
*/
-int _vector_resize(void **vector_ptr, size_t elt_size, off_t pos);
+int _vector_resize (void **vector_ptr, size_t elt_size, off_t pos);
/**
* @brief Ensures a vector is sufficiently large to hold an element at the
@@ -127,11 +131,12 @@ int _vector_resize(void **vector_ptr, size_t elt_size, off_t pos);
* - This function can fail if the vector is full and for any reason it cannot
* be resized.
*/
-static inline int _vector_ensure_pos(void **vector_ptr, size_t elt_size,
- off_t pos) {
- vector_hdr_t *vh = vector_hdr(*vector_ptr);
- if (pos >= (off_t)vh->alloc_size)
- return _vector_resize(vector_ptr, elt_size, pos + 1);
+static inline int
+_vector_ensure_pos (void **vector_ptr, size_t elt_size, off_t pos)
+{
+ vector_hdr_t *vh = vector_hdr (*vector_ptr);
+ if (pos >= (off_t) vh->alloc_size)
+ return _vector_resize (vector_ptr, elt_size, pos + 1);
return 0;
}
@@ -147,14 +152,17 @@ static inline int _vector_ensure_pos(void **vector_ptr, size_t elt_size,
* and evenutually resizes the vector to make room for it (if allowed by
* maximum size).
*/
-static inline int _vector_push(void **vector_ptr, size_t elt_size, void *elt) {
- vector_hdr_t *vh = vector_hdr(*vector_ptr);
- if (_vector_ensure_pos(vector_ptr, elt_size, vh->cur_size) < 0) return -1;
+static inline int
+_vector_push (void **vector_ptr, size_t elt_size, void *elt)
+{
+ vector_hdr_t *vh = vector_hdr (*vector_ptr);
+ if (_vector_ensure_pos (vector_ptr, elt_size, vh->cur_size) < 0)
+ return -1;
/* Always get header after a potential resize */
- vh = vector_hdr(*vector_ptr);
- memcpy((uint8_t *)*vector_ptr + vh->cur_size * elt_size, elt, elt_size);
- vh = vector_hdr(*vector_ptr);
+ vh = vector_hdr (*vector_ptr);
+ memcpy ((uint8_t *) *vector_ptr + vh->cur_size * elt_size, elt, elt_size);
+ vh = vector_hdr (*vector_ptr);
vh->cur_size++;
return 0;
}
@@ -168,19 +176,91 @@ static inline int _vector_push(void **vector_ptr, size_t elt_size, void *elt) {
* @param[in] elt The element to remove
* @return int Number of elemets (equal to 'elt') removed from the vector
*/
-static inline int _vector_remove_unordered(void *vector, size_t elt_size,
- void *elt) {
+static inline int
+_vector_remove_unordered (void *vector, size_t elt_size, void *elt)
+{
size_t num_removed = 0;
- vector_hdr_t *vh = vector_hdr(vector);
- for (size_t i = 0; i < vector_hdr(vector)->cur_size; i++) {
- if (memcmp((uint8_t *)vector + i * elt_size, elt, elt_size) == 0) {
- vh->cur_size--;
- memcpy((uint8_t *)vector + i * elt_size,
- (uint8_t *)vector + vh->cur_size * elt_size, elt_size);
- num_removed++;
+ vector_hdr_t *vh = vector_hdr (vector);
+ for (size_t i = 0; i < vector_hdr (vector)->cur_size; i++)
+ {
+ if (memcmp ((uint8_t *) vector + i * elt_size, elt, elt_size) == 0)
+ {
+ vh->cur_size--;
+ // Copy last element to current position (hence order is not
+ // maintained)
+ memcpy ((uint8_t *) vector + i * elt_size,
+ (uint8_t *) vector + vh->cur_size * elt_size, elt_size);
+ num_removed++;
+ }
}
- }
- return num_removed;
+ return (int) num_removed;
+}
+
+/**
+ * @brief Get the element at the specified position and store in 'elt'.
+ *
+ * @param[in] vector Pointer to the vector data structure to use
+ * @param[in] pos Position of the element to retrieve
+ * @param[in] elt_size The size of a vector element
+ * @param[in] elt The element where the result is stored
+ * @return int 0 if successful, -1 otherwise
+ */
+static inline int
+_vector_get (void *vector, off_t pos, size_t elt_size, void *elt)
+{
+ vector_hdr_t *vh = vector_hdr (vector);
+ if (pos >= vh->alloc_size)
+ return -1;
+
+ memcpy (elt, (uint8_t *) vector + pos * elt_size, elt_size);
+ return 0;
+}
+
+/**
+ * @brief Check if specified element is present in vector.
+ *
+ * @param[in] vector Pointer to the vector data structure to use
+ * @param[in] elt_size The size of a vector element
+ * @param[in] elt The element to search for
+ * @return true If specified element is contained in the vector
+ * @return false
+ */
+static inline bool
+_vector_contains (void *vector, size_t elt_size, void *elt)
+{
+ for (int i = 0; i < vector_hdr (vector)->cur_size; i++)
+ {
+ if (memcmp ((uint8_t *) vector + i * elt_size, elt, elt_size) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * @brief Remove the element at the specified position from the vector.
+ * Relative element order is preserved by shifting left the elements after the
+ * target.
+ *
+ * @param[in, out] vector Pointer to the vector data structure to use
+ * @param[in] elt_size The size of a vector element
+ * @param[in] pos Position of the element to remove
+ * @return int 0 if successful, -1 otherwise
+ */
+static inline int
+_vector_remove_at (void **vector_ptr, size_t elt_size, off_t pos)
+{
+ vector_hdr_t *vh = vector_hdr (*vector_ptr);
+ if (pos >= vh->cur_size)
+ return -1;
+
+ // Shift backward by one position all the elements after the one specified
+ memmove ((uint8_t *) (*vector_ptr) + pos * elt_size,
+ (uint8_t *) (*vector_ptr) + (pos + 1) * elt_size,
+ (vh->cur_size - 1 - pos) * elt_size);
+ vh->cur_size--;
+
+ return 0;
}
/******************************************************************************/
@@ -197,15 +277,15 @@ static inline int _vector_remove_unordered(void *vector, size_t elt_size,
* - Allocated memory is set to 0 (used by bitmap)
*/
-#define vector_init(vector, init_size, max_size) \
- _vector_init((void **)&vector, sizeof(vector[0]), init_size, max_size)
+#define vector_init(vector, init_size, max_size) \
+ _vector_init ((void **) &vector, sizeof (vector[0]), init_size, max_size)
/**
* @brief Free a vector data structure.
*
* @param[in] vector The vector data structure to free.
*/
-#define vector_free(vector) _vector_free((void **)&vector)
+#define vector_free(vector) _vector_free ((void **) &vector)
/**
* @brief Resize a vector data structure.
@@ -225,8 +305,8 @@ static inline int _vector_remove_unordered(void *vector, size_t elt_size,
* vector will be truncated.
* - Newly allocated memory is set to 0 (used by bitmap)
*/
-#define vector_resize(vector) \
- _vector_resize((void **)&(vector), sizeof((vector)[0]), 0)
+#define vector_resize(vector) \
+ _vector_resize ((void **) &(vector), sizeof ((vector)[0]), 0)
/**
* @brief Ensures a vector is sufficiently large to hold an element at the
@@ -239,8 +319,8 @@ static inline int _vector_remove_unordered(void *vector, size_t elt_size,
* - This function should always be called before writing to a vector element
* to eventually make room for it (the vector will eventually be resized).
*/
-#define vector_ensure_pos(vector, pos) \
- _vector_ensure_pos((void **)&(vector), sizeof((vector)[0]), pos);
+#define vector_ensure_pos(vector, pos) \
+ _vector_ensure_pos ((void **) &(vector), sizeof ((vector)[0]), pos);
/**
* @brief Push an element at the end of a vector.
@@ -253,13 +333,73 @@ static inline int _vector_remove_unordered(void *vector, size_t elt_size,
* and evenutually resizes the vector to make room for it (if allowed by
* maximum size).
*/
-#define vector_push(vector, elt) \
- ({ \
- typeof(elt) x = elt; \
- _vector_push((void **)&(vector), sizeof((vector)[0]), (void *)(&x)); \
+#define vector_push(vector, elt) \
+ ({ \
+ typeof (elt) _vector_var (x) = elt; \
+ _vector_push ((void **) &(vector), sizeof ((vector)[0]), \
+ (void *) (&_vector_var (x))); \
+ })
+
+#define vector_at(vector, pos) \
+ ({ \
+ assert (pos < vector_hdr (vector)->cur_size); \
+ (vector)[(pos)]; \
+ })
+
+#define vector_set(vector, pos, elt) \
+ ({ \
+ assert (pos < vector_hdr (vector)->cur_size); \
+ (vector)[(pos)] = elt; \
})
/**
+ * @brief Clear the vector content, i.e. new pushes will insert starting from
+ * position 0.
+ *
+ * @param[in, out] vector The vector to reset
+ */
+#define vector_reset(vector) (vector_len (vector) = 0)
+
+/**
+ * @brief Get the element at the specified position and store in 'elt'.
+ *
+ * @param[in] vector The vector data structure to use
+ * @param[in] pos Position of the element to retrieve
+ * @param[in] elt The element where the result is stored
+ * @return int 0 if successful, -1 otherwise
+ */
+#define vector_get(vector, pos, elt) \
+ _vector_get ((void *) (vector), (pos), sizeof ((vector)[0]), \
+ (void *) (&elt));
+
+/**
+ * @brief Check if specified element is present in vector.
+ *
+ * @param[in] vector The vector data structure to use
+ * @param[in] elt The element to search for
+ * @return true If specified element is contained in the vector
+ * @return false
+ */
+#define vector_contains(vector, elt) \
+ ({ \
+ typeof (elt) _vector_var (x) = elt; \
+ _vector_contains ((void *) (vector), sizeof ((vector)[0]), \
+ (void *) (&_vector_var (x))); \
+ })
+
+/**
+ * @brief Remove the element at the specified position from the vector.
+ * Relative element order is preserved by shifting left the elements after the
+ * target.
+ *
+ * @param[in, out] vector The vector data structure to use
+ * @param[in] pos Position of the element to remove
+ * @return int 0 if successful, -1 otherwise
+ */
+#define vector_remove_at(vector, pos) \
+ _vector_remove_at ((void **) &(vector), sizeof ((vector)[0]), (pos))
+
+/**
* @brief Remove all the occurrencies of an element from the vector.
* The order of the elements is NOT maintained.
*
@@ -267,11 +407,11 @@ static inline int _vector_remove_unordered(void *vector, size_t elt_size,
* @param[in] elt The element to remove
* @return int Number of elemets (equal to 'elt') removed from the vector
*/
-#define vector_remove_unordered(vector, elt) \
- ({ \
- typeof(elt) x = elt; \
- _vector_remove_unordered((void *)(vector), sizeof((vector)[0]), \
- (void *)(&x)); \
+#define vector_remove_unordered(vector, elt) \
+ ({ \
+ typeof (elt) x = elt; \
+ _vector_remove_unordered ((void *) (vector), sizeof ((vector)[0]), \
+ (void *) (&x)); \
})
/**
@@ -288,12 +428,12 @@ static inline int _vector_remove_unordered(void *vector, size_t elt_size,
* - A user should always call vector_ensure_pos to ensure the vector is
* sufficiently large to hold an element at the specified position.
*/
-#define vector_len(vector) vector_hdr(vector)->cur_size
+#define vector_len(vector) vector_hdr (vector)->cur_size
/**
* @brief Returns the allocated size of a vector.
*/
-#define vector_get_alloc_size(vector) vector_hdr(vector)->alloc_size
+#define vector_get_alloc_size(vector) vector_hdr (vector)->alloc_size
/**
* @brief Iterate over elements in a vector.
@@ -303,25 +443,28 @@ static inline int _vector_remove_unordered(void *vector, size_t elt_size,
* iteration
* @param[in] BODY Block to execute during iteration
*
- * @note Iteration will execute BODY with eltp corresponding successively to all
- * elements found in the vector. It is implemented using the more generic
+ * @note Iteration will execute BODY with eltp corresponding successively to
+ * all elements found in the vector. It is implemented using the more generic
* enumeration function.
*/
-#define vector_foreach(vector, eltp, BODY) \
- ({ \
- unsigned _vector_var(i); \
- vector_enumerate((vector), _vector_var(i), (eltp), BODY); \
+#define vector_foreach(vector, eltp, BODY) \
+ ({ \
+ unsigned _vector_var (i); \
+ vector_enumerate ((vector), _vector_var (i), (eltp), BODY); \
})
/**
* @brief Helper function used by vector_foreach().
*/
-#define vector_enumerate(vector, i, eltp, BODY) \
- ({ \
- for ((i) = 0; (i) < vector_len(vector); (i)++) { \
- eltp = (vector) + (i); \
- { BODY; } \
- } \
+#define vector_enumerate(vector, i, eltp, BODY) \
+ ({ \
+ for ((i) = 0; (i) < vector_len (vector); (i)++) \
+ { \
+ eltp = (vector) + (i); \
+ { \
+ BODY; \
+ } \
+ } \
})
#endif /* UTIL_VECTOR_H */
diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt
index ef74127cc..8e81aa442 100644
--- a/lib/src/CMakeLists.txt
+++ b/lib/src/CMakeLists.txt
@@ -33,6 +33,9 @@ list(APPEND LIBHICN_SOURCE_FILES
protocol/new.c
util/ip_address.c
util/log.c
+ util/pool.c
+ util/ring.c
+ util/vector.c
)
if (WIN32)
diff --git a/lib/src/common.c b/lib/src/common.c
index c4cb8bc3e..362034942 100644
--- a/lib/src/common.c
+++ b/lib/src/common.c
@@ -54,61 +54,44 @@ get_addr_family (const char *ip_address)
/* hashes */
-u32
-cumulative_hash32 (const void *data, size_t len, u32 lastValue)
+// FNV-1a 32-bit http://www.isthe.com/chongo/tech/comp/fnv/
+typedef u_int32_t Fnv32_t;
+#define FNV_32_PRIME ((Fnv32_t) 0x01000193)
+#define FNV1_32_INIT ((Fnv32_t) 0x811c9dc5)
+#define FNV1_32A_INIT FNV1_32_INIT
+
+Fnv32_t
+cumulative_hash32 (const void *buf, size_t len, Fnv32_t hval)
{
- // Standard FNV 32-bit prime: see
- // http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
- const u32 fnv1a_prime = 0x01000193;
- u32 hash = lastValue;
- size_t i;
-
- const char *chardata = data;
+ unsigned char *bp = (unsigned char *) buf; /* start of buffer */
+ unsigned char *be = bp + len; /* beyond end of buffer */
- for (i = 0; i < len; i++)
+ /*
+ * FNV-1a hash each octet in the buffer
+ */
+ while (bp < be)
{
- hash = hash ^ chardata[i];
- hash = hash * fnv1a_prime;
- }
- return hash;
-}
+ /* xor the bottom with the current octet */
+ hval ^= (Fnv32_t) *bp++;
-u32
-hash32 (const void *data, size_t len)
-{
- // Standard FNV 32-bit offset: see
- // http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
- const u32 fnv1a_offset = 0x811C9DC5;
- return cumulative_hash32 (data, len, fnv1a_offset);
-}
-
-u64
-cumulative_hash64 (const void *data, size_t len, u64 lastValue)
-{
- // Standard FNV 64-bit prime: see
- // http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
- const u64 fnv1a_prime = 0x00000100000001B3ULL;
- u64 hash = lastValue;
- const char *chardata = data;
- size_t i;
-
- for (i = 0; i < len; i++)
- {
- hash = hash ^ chardata[i];
- hash = hash * fnv1a_prime;
+ /* multiply by the 32 bit FNV magic prime mod 2^32 */
+#if defined(NO_FNV_GCC_OPTIMIZATION)
+ hval *= FNV_32_PRIME;
+#else
+ hval +=
+ (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
+#endif
}
- return hash;
+ /* return our new hash value */
+ return hval;
}
-u64
-hash64 (const void *data, size_t len)
+u32
+hash32 (const void *data, size_t len)
{
- // Standard FNV 64-bit offset: see
- // http://www.isthe.com/chongo/tech/comp/fnv/#FNV-param
- const u64 fnv1a_offset = 0xCBF29CE484222325ULL;
- return cumulative_hash64 (data, len, fnv1a_offset);
+ return cumulative_hash32 (data, len, FNV1_32A_INIT);
}
void
diff --git a/lib/src/ops.c b/lib/src/ops.c
index 80ffcf3c5..20362d69d 100644
--- a/lib/src/ops.c
+++ b/lib/src/ops.c
@@ -57,6 +57,10 @@ DECLARE_update_data_pathlabel (none, NONE);
DECLARE_reset_data_for_hash (none, NONE);
DECLARE_get_lifetime (none, NONE);
DECLARE_set_lifetime (none, NONE);
+DECLARE_get_source_port (none, NONE);
+DECLARE_get_dest_port (none, NONE);
+DECLARE_set_source_port (none, NONE);
+DECLARE_set_dest_port (none, NONE);
DECLARE_update_checksums (none, NONE);
DECLARE_verify_checksums (none, NONE);
DECLARE_rewrite_interest (none, NONE);
diff --git a/lib/src/protocol/ah.c b/lib/src/protocol/ah.c
index b3d24161d..c9ed40179 100644
--- a/lib/src/protocol/ah.c
+++ b/lib/src/protocol/ah.c
@@ -45,6 +45,10 @@ DECLARE_set_data_pathlabel (ah, UNEXPECTED);
DECLARE_update_data_pathlabel (ah, UNEXPECTED);
DECLARE_get_lifetime (ah, UNEXPECTED);
DECLARE_set_lifetime (ah, UNEXPECTED);
+DECLARE_get_source_port (ah, UNEXPECTED);
+DECLARE_get_dest_port (ah, UNEXPECTED);
+DECLARE_set_source_port (ah, UNEXPECTED);
+DECLARE_set_dest_port (ah, UNEXPECTED);
DECLARE_get_payload_length (ah, UNEXPECTED);
DECLARE_set_payload_length (ah, UNEXPECTED);
DECLARE_get_payload_type (ah, UNEXPECTED);
diff --git a/lib/src/protocol/icmp.c b/lib/src/protocol/icmp.c
index 0452e4fbb..1fc6c7d2f 100644
--- a/lib/src/protocol/icmp.c
+++ b/lib/src/protocol/icmp.c
@@ -38,6 +38,10 @@ DECLARE_set_data_pathlabel (icmp, UNEXPECTED);
DECLARE_update_data_pathlabel (icmp, UNEXPECTED);
DECLARE_get_lifetime (icmp, UNEXPECTED);
DECLARE_set_lifetime (icmp, UNEXPECTED);
+DECLARE_get_source_port (icmp, UNEXPECTED);
+DECLARE_get_dest_port (icmp, UNEXPECTED);
+DECLARE_set_source_port (icmp, UNEXPECTED);
+DECLARE_set_dest_port (icmp, UNEXPECTED);
DECLARE_get_length (icmp, UNEXPECTED);
DECLARE_get_payload_length (icmp, UNEXPECTED);
DECLARE_set_payload_length (icmp, UNEXPECTED);
diff --git a/lib/src/protocol/ipv4.c b/lib/src/protocol/ipv4.c
index 5d445f018..840fbe34b 100644
--- a/lib/src/protocol/ipv4.c
+++ b/lib/src/protocol/ipv4.c
@@ -228,6 +228,31 @@ ipv4_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
}
int
+ipv4_get_source_port (hicn_type_t type, const hicn_protocol_t *h,
+ u16 *source_port)
+{
+ return CHILD_OPS (get_source_port, type, h, source_port);
+}
+
+int
+ipv4_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, u16 *dest_port)
+{
+ return CHILD_OPS (get_dest_port, type, h, dest_port);
+}
+
+int
+ipv4_set_source_port (hicn_type_t type, hicn_protocol_t *h, u16 source_port)
+{
+ return CHILD_OPS (set_source_port, type, h, source_port);
+}
+
+int
+ipv4_set_dest_port (hicn_type_t type, hicn_protocol_t *h, u16 dest_port)
+{
+ return CHILD_OPS (set_dest_port, type, h, dest_port);
+}
+
+int
ipv4_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
size_t payload_length)
{
diff --git a/lib/src/protocol/ipv6.c b/lib/src/protocol/ipv6.c
index b3a107a13..b3c543249 100644
--- a/lib/src/protocol/ipv6.c
+++ b/lib/src/protocol/ipv6.c
@@ -212,6 +212,31 @@ ipv6_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
}
int
+ipv6_get_source_port (hicn_type_t type, const hicn_protocol_t *h,
+ u16 *source_port)
+{
+ return CHILD_OPS (get_source_port, type, h, source_port);
+}
+
+int
+ipv6_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, u16 *dest_port)
+{
+ return CHILD_OPS (get_dest_port, type, h, dest_port);
+}
+
+int
+ipv6_set_source_port (hicn_type_t type, hicn_protocol_t *h, u16 source_port)
+{
+ return CHILD_OPS (set_source_port, type, h, source_port);
+}
+
+int
+ipv6_set_dest_port (hicn_type_t type, hicn_protocol_t *h, u16 dest_port)
+{
+ return CHILD_OPS (set_dest_port, type, h, dest_port);
+}
+
+int
ipv6_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
size_t payload_length)
{
diff --git a/lib/src/protocol/new.c b/lib/src/protocol/new.c
index 8c79963ad..07c1d0d76 100644
--- a/lib/src/protocol/new.c
+++ b/lib/src/protocol/new.c
@@ -22,6 +22,11 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
+DECLARE_get_source_port (new, UNEXPECTED);
+DECLARE_get_dest_port (new, UNEXPECTED);
+DECLARE_set_source_port (new, UNEXPECTED);
+DECLARE_set_dest_port (new, UNEXPECTED);
+
static int
is_interest (u8 flags)
{
diff --git a/lib/src/protocol/tcp.c b/lib/src/protocol/tcp.c
index 8097cfd12..82fc461ea 100644
--- a/lib/src/protocol/tcp.c
+++ b/lib/src/protocol/tcp.c
@@ -251,6 +251,35 @@ tcp_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
}
int
+tcp_get_source_port (hicn_type_t type, const hicn_protocol_t *h,
+ u16 *source_port)
+{
+ *source_port = ntohs (h->tcp.sport);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, u16 *dest_port)
+{
+ *dest_port = ntohs (h->tcp.dport);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_set_source_port (hicn_type_t type, hicn_protocol_t *h, u16 source_port)
+{
+ h->tcp.sport = htons (source_port);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+tcp_set_dest_port (hicn_type_t type, hicn_protocol_t *h, u16 dest_port)
+{
+ h->tcp.dport = htons (dest_port);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
tcp_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
size_t payload_length)
{
diff --git a/lib/src/protocol/udp.c b/lib/src/protocol/udp.c
index ee46b8e9d..7a14b09c2 100644
--- a/lib/src/protocol/udp.c
+++ b/lib/src/protocol/udp.c
@@ -143,6 +143,35 @@ udp_set_lifetime (hicn_type_t type, hicn_protocol_t *h,
}
int
+udp_get_source_port (hicn_type_t type, const hicn_protocol_t *h,
+ u16 *source_port)
+{
+ *source_port = ntohs (h->udp.src_port);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+udp_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, u16 *dest_port)
+{
+ *dest_port = ntohs (h->udp.dst_port);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+udp_set_source_port (hicn_type_t type, hicn_protocol_t *h, u16 source_port)
+{
+ h->udp.src_port = htons (source_port);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
+udp_set_dest_port (hicn_type_t type, hicn_protocol_t *h, u16 dest_port)
+{
+ h->udp.dst_port = htons (dest_port);
+ return HICN_LIB_ERROR_NONE;
+}
+
+int
udp_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum,
size_t payload_length)
{
diff --git a/lib/src/util/log.c b/lib/src/util/log.c
index 975762603..91a87e848 100644
--- a/lib/src/util/log.c
+++ b/lib/src/util/log.c
@@ -30,6 +30,10 @@ log_conf_t log_conf = DEFAULT_LOG_CONF;
#define FMT_DATETIME_LEN 20
#define snprintf_nowarn(...) (snprintf (__VA_ARGS__) < 0 ? abort () : (void) 0)
+#define COLOR_RED "\033[31m"
+#define COLOR_YELLOW "\033[33m"
+#define COLOR_RESET "\033[0m"
+
static char ts[FMT_DATETIME_LEN];
static char *
@@ -104,7 +108,7 @@ _log_va (int level, const char *fmt, va_list ap)
}
else
{
- __android_log_vprint (ANDROID_LOG_INFO, "HICN FACEMGR", fmt, ap);
+ __android_log_vprint (prio, "HICN FACEMGR", fmt, ap);
}
#else
@@ -112,6 +116,7 @@ _log_va (int level, const char *fmt, va_list ap)
if (level > log_conf.log_level)
return;
+ char *color = COLOR_RESET;
switch (level)
{
case LOG_FATAL:
@@ -119,9 +124,11 @@ _log_va (int level, const char *fmt, va_list ap)
break;
case LOG_ERROR:
prefix = "ERROR: ";
+ color = COLOR_RED;
break;
case LOG_WARN:
prefix = "WARNING: ";
+ color = COLOR_YELLOW;
break;
case LOG_INFO:
prefix = "";
@@ -137,9 +144,9 @@ _log_va (int level, const char *fmt, va_list ap)
break;
}
FILE *f = log_conf.log_file ? log_conf.log_file : stdout;
- fprintf (f, "%s %s", timestamp (), prefix);
+ fprintf (f, "%s%s %s", color, timestamp (), prefix);
vfprintf (f, fmt, ap);
- fprintf (f, "\n");
+ fprintf (f, "%s\n", COLOR_RESET);
#ifdef DEBUG
fflush (f);
#endif
diff --git a/lib/src/util/pool.c b/lib/src/util/pool.c
new file mode 100644
index 000000000..c6be92ce8
--- /dev/null
+++ b/lib/src/util/pool.c
@@ -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.
+ */
+
+/**
+ * \file pool.c
+ * \brief Implementation of fixed-size pool allocator.
+ *
+ * NOTE:
+ * - Ideally, we should have a single realloc per resize, that would encompass
+ * both the free indices vector and bitmap, by nesting data structures.
+ * Because of the added complexity, and by lack of evidence of the need for
+ * this, we currently rely on a simpler implementation.
+ */
+
+#include <assert.h>
+#include <stdlib.h> // calloc
+
+#include <hicn/util/pool.h>
+
+#include <stdio.h> // XXX
+
+void
+_pool_init (void **pool_ptr, size_t elt_size, size_t init_size,
+ size_t max_size)
+{
+ assert (pool_ptr);
+ assert (elt_size);
+
+ init_size = next_pow2 (init_size);
+
+ if (max_size && init_size > max_size)
+ goto ERR_MAX_SIZE;
+
+ /* The initial pool size is rounded to the next power of two */
+ size_t alloc_size = next_pow2 (init_size);
+
+ pool_hdr_t *ph = calloc (POOL_HDRLEN + alloc_size * elt_size, 1);
+ if (!ph)
+ goto ERR_MALLOC;
+
+ ph->elt_size = elt_size;
+ ph->alloc_size = alloc_size;
+ ph->max_size = max_size;
+
+ /* Free indices */
+ off_t *free_indices;
+ vector_init (free_indices, init_size, max_size);
+ for (unsigned i = 0; i < init_size; i++)
+ free_indices[i] = (init_size - 1) - i;
+ vector_len (free_indices) = init_size;
+ ph->free_indices = free_indices;
+
+ /* Free bitmap */
+ bitmap_t *fb = ph->free_bitmap;
+ bitmap_init (fb, init_size, max_size);
+ bitmap_set_to (fb, init_size);
+ ph->free_bitmap = fb;
+
+ *pool_ptr = (uint8_t *) ph + POOL_HDRLEN;
+
+ return;
+
+ERR_MALLOC:
+ERR_MAX_SIZE:
+ *pool_ptr = NULL;
+ return;
+}
+
+void
+_pool_free (void **pool_ptr)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ vector_free (ph->free_indices);
+ bitmap_free (ph->free_bitmap);
+
+ free (pool_hdr (*pool_ptr));
+ *pool_ptr = NULL;
+}
+
+bool
+_pool_validate_id (void **pool_ptr, off_t id)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ size_t pool_size = pool_get_alloc_size (*pool_ptr);
+ if (id >= pool_size || !bitmap_is_unset (ph->free_bitmap, id))
+ return false;
+
+ return true;
+}
+
+void
+_pool_resize (void **pool_ptr, size_t elt_size)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ size_t old_size = ph->alloc_size;
+ size_t new_size = old_size * 2;
+
+ WARN ("pool_resize to %lu", new_size);
+
+ if (ph->max_size && new_size > ph->max_size)
+ goto ERR_MAX_SIZE;
+
+ /* Double pool storage */
+ ph = realloc (ph, POOL_HDRLEN + new_size * elt_size);
+ if (!ph)
+ goto ERR_REALLOC;
+ ph->elt_size = elt_size;
+ ph->alloc_size = new_size;
+
+ /*
+ * After resize, the pool will have new free indices, ranging from
+ * old_size to (new_size - 1)
+ */
+ vector_ensure_pos (ph->free_indices, old_size);
+ for (unsigned i = 0; i < old_size; i++)
+ ph->free_indices[i] = new_size - 1 - i;
+ vector_len (ph->free_indices) = old_size;
+
+ /* We also need to update the bitmap */
+ bitmap_ensure_pos (&(ph->free_bitmap), new_size - 1);
+ bitmap_set_range (ph->free_bitmap, old_size, new_size - 1);
+
+ /* Reassign pool pointer */
+ *pool_ptr = (uint8_t *) ph + POOL_HDRLEN;
+
+ return;
+
+ERR_REALLOC:
+ERR_MAX_SIZE:
+ *pool_ptr = NULL;
+ return;
+}
+
+off_t
+_pool_get (void **pool_ptr, void **elt, size_t elt_size)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ uint64_t l = vector_len (ph->free_indices);
+ if (l == 0)
+ {
+ _pool_resize (pool_ptr, elt_size);
+ ph = pool_hdr (*pool_ptr);
+ l = vector_len (ph->free_indices);
+ }
+ off_t free_id = ph->free_indices[l - 1];
+ vector_len (ph->free_indices)--;
+ bitmap_unset (ph->free_bitmap, free_id);
+ *elt = *pool_ptr + free_id * elt_size;
+ return free_id;
+}
+
+void
+_pool_put (void **pool_ptr, void **elt, size_t elt_size)
+{
+ pool_hdr_t *ph = pool_hdr (*pool_ptr);
+ uint64_t l = vector_len (ph->free_indices);
+ vector_ensure_pos (ph->free_indices, l);
+ off_t freed_id = (*elt - *pool_ptr) / elt_size;
+ ph->free_indices[l] = freed_id;
+ vector_len (ph->free_indices)++;
+ bitmap_set (ph->free_bitmap, freed_id);
+}
diff --git a/hicn-light/src/hicn/base/ring.c b/lib/src/util/ring.c
index 29727886a..2c722a842 100644
--- a/hicn-light/src/hicn/base/ring.c
+++ b/lib/src/util/ring.c
@@ -21,25 +21,29 @@
#include <stdlib.h>
-#include "ring.h"
+#include <hicn/util/ring.h>
-void _ring_init(void** ring_ptr, size_t elt_size, size_t max_size) {
- assert(ring_ptr);
- assert(elt_size > 0);
+void
+_ring_init (void **ring_ptr, size_t elt_size, size_t max_size)
+{
+ assert (ring_ptr);
+ assert (elt_size > 0);
// we use a static array, not a vector (for now)
- assert(max_size != 0);
+ assert (max_size != 0);
- ring_hdr_t* rh = malloc(RING_HDRLEN + max_size * elt_size);
+ ring_hdr_t *rh = malloc (RING_HDRLEN + max_size * elt_size);
rh->roff = 0;
rh->woff = 0;
rh->size = 0;
rh->max_size = max_size;
- *ring_ptr = (uint8_t*)rh + RING_HDRLEN;
+ *ring_ptr = (uint8_t *) rh + RING_HDRLEN;
}
-void _ring_free(void** ring_ptr) {
- free(ring_hdr(*ring_ptr));
+void
+_ring_free (void **ring_ptr)
+{
+ free (ring_hdr (*ring_ptr));
*ring_ptr = NULL;
}
diff --git a/hicn-light/src/hicn/base/vector.c b/lib/src/util/vector.c
index 36d808932..1f5cd0269 100644
--- a/hicn-light/src/hicn/base/vector.c
+++ b/lib/src/util/vector.c
@@ -19,67 +19,83 @@
*/
#include <assert.h>
-#include <stddef.h> // size_t
-#include <stdlib.h> // calloc
+#include <stddef.h> // size_t
+#include <stdlib.h> // calloc
#include <stdio.h>
-#include "vector.h"
+#include <hicn/util/vector.h>
#define DEFAULT_VECTOR_SIZE 64
-void _vector_init(void** vector_ptr, size_t elt_size, size_t init_size,
- size_t max_size) {
- assert(vector_ptr);
- assert(max_size == 0 || init_size < max_size);
+int
+_vector_init (void **vector_ptr, size_t elt_size, size_t init_size,
+ size_t max_size)
+{
+ assert (vector_ptr);
+ assert (max_size == 0 || init_size < max_size);
- if (init_size == 0) init_size = DEFAULT_VECTOR_SIZE;
+ if (init_size == 0)
+ init_size = DEFAULT_VECTOR_SIZE;
*vector_ptr = NULL;
- _vector_resize(vector_ptr, elt_size, init_size);
+ int rc = _vector_resize (vector_ptr, elt_size, init_size);
+ if (rc < 0)
+ return -1;
- vector_hdr_t* vh = vector_hdr(*vector_ptr);
+ vector_hdr_t *vh = vector_hdr (*vector_ptr);
vh->cur_size = 0;
vh->max_size = max_size;
+
+ return 0;
}
-void _vector_free(void** vector_ptr) {
- free(vector_hdr(*vector_ptr));
+void
+_vector_free (void **vector_ptr)
+{
+ free (vector_hdr (*vector_ptr));
*vector_ptr = NULL;
}
-int _vector_resize(void** vector_ptr, size_t elt_size, off_t pos) {
- vector_hdr_t* vh;
-
+int
+_vector_resize (void **vector_ptr, size_t elt_size, off_t pos)
+{
+ vector_hdr_t *vh;
size_t old_size;
- if (*vector_ptr) {
- vh = vector_hdr(*vector_ptr);
- old_size = vh->alloc_size;
- } else {
- vh = NULL;
- old_size = 0;
- }
+ if (*vector_ptr)
+ {
+ vh = vector_hdr (*vector_ptr);
+ old_size = vh->alloc_size;
+ }
+ else
+ {
+ vh = NULL;
+ old_size = 0;
+ }
/* Round the allocated size to the next power of 2 of the requested position
*/
- size_t new_size = next_pow2(pos);
+ size_t new_size = next_pow2 (pos);
/* Don't grow the vector back */
- if (new_size < old_size) return 0;
+ if (new_size < old_size)
+ return 0;
/* Don't exceed maximum size (for init, check is done beforehand) */
- if (vh && vh->max_size && new_size > vh->max_size) return -1;
+ if (vh && vh->max_size && new_size > vh->max_size)
+ return -1;
- vh = realloc(vh, VECTOR_HDRLEN + new_size * elt_size);
- if (!vh) return -1;
+ vh = realloc (vh, VECTOR_HDRLEN + new_size * elt_size);
+ if (!vh)
+ return -1;
vh->alloc_size = new_size;
/* Zero out the newly allocated memory (except headers) */
- memset((uint8_t*)vh + VECTOR_HDRLEN + old_size * elt_size, 0,
- (new_size - old_size) * elt_size);
+ memset ((uint8_t *) vh + VECTOR_HDRLEN + old_size * elt_size, 0,
+ (new_size - old_size) * elt_size);
/* Reassign vector pointer */
- *vector_ptr = (uint8_t*)vh + VECTOR_HDRLEN;
+ *vector_ptr = (uint8_t *) vh + VECTOR_HDRLEN;
return 0;
}
diff --git a/libtransport/includes/hicn/transport/core/asio_wrapper.h b/libtransport/includes/hicn/transport/core/asio_wrapper.h
index 78cad35dc..41b660587 100644
--- a/libtransport/includes/hicn/transport/core/asio_wrapper.h
+++ b/libtransport/includes/hicn/transport/core/asio_wrapper.h
@@ -23,6 +23,9 @@ TRANSPORT_CLANG_DISABLE_WARNING("-Wdeprecated-declarations")
#ifndef ASIO_STANDALONE
#define ASIO_STANDALONE
#endif
+#ifdef __APPLE__
+TRANSPORT_CLANG_DISABLE_WARNING("-Wshorten-64-to-32")
+#endif
#include <asio.hpp>
TRANSPORT_POP_WARNING
diff --git a/libtransport/includes/hicn/transport/core/connector.h b/libtransport/includes/hicn/transport/core/connector.h
index b671a7d89..ad0d4f09d 100644
--- a/libtransport/includes/hicn/transport/core/connector.h
+++ b/libtransport/includes/hicn/transport/core/connector.h
@@ -30,6 +30,7 @@
#include <deque>
#include <functional>
+#include <system_error>
namespace transport {
@@ -57,10 +58,10 @@ class Connector : public std::enable_shared_from_this<Connector> {
static constexpr std::uint16_t max_burst = 256;
using Ptr = std::shared_ptr<Connector>;
+ using ReceptionBuffer = std::vector<utils::MemBuf::Ptr>;
using PacketQueue = std::deque<utils::MemBuf::Ptr>;
- using PacketReceivedCallback =
- std::function<void(Connector *, const std::vector<utils::MemBuf::Ptr> &,
- const std::error_code &)>;
+ using PacketReceivedCallback = std::function<void(
+ Connector *, const ReceptionBuffer &, const std::error_code &)>;
using PacketSentCallback =
std::function<void(Connector *, const std::error_code &)>;
using OnCloseCallback = std::function<void(Connector *)>;
@@ -118,6 +119,14 @@ class Connector : public std::enable_shared_from_this<Connector> {
virtual void send(const utils::MemBuf::Ptr &buffer) = 0;
+ virtual void receive(const std::vector<utils::MemBuf::Ptr> &buffers) {
+ receive_callback_(this, buffers, std::make_error_code(std::errc()));
+ }
+
+ virtual void reconnect() {
+ on_reconnect_callback_(this, std::make_error_code(std::errc()));
+ }
+
virtual void close() = 0;
virtual State state() { return state_; };
@@ -134,6 +143,11 @@ class Connector : public std::enable_shared_from_this<Connector> {
std::string getConnectorName() { return connector_name_; }
+ template <typename EP>
+ void setLocalEndpoint(EP &&endpoint) {
+ local_endpoint_ = std::forward<EP>(endpoint);
+ }
+
Endpoint getLocalEndpoint() { return local_endpoint_; }
Endpoint getRemoteEndpoint() { return remote_endpoint_; }
diff --git a/libtransport/includes/hicn/transport/core/content_object.h b/libtransport/includes/hicn/transport/core/content_object.h
index a8df1e8e3..f8d95846e 100644
--- a/libtransport/includes/hicn/transport/core/content_object.h
+++ b/libtransport/includes/hicn/transport/core/content_object.h
@@ -43,8 +43,8 @@ class ContentObject : public Packet {
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) {
+ if (hicn_data_get_name(format_, packet_start_,
+ &name_.getStructReference()) < 0) {
throw errors::MalformedPacketException();
}
}
@@ -52,8 +52,8 @@ class ContentObject : public Packet {
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) {
+ if (hicn_data_get_name(format_, packet_start_,
+ &name_.getStructReference()) < 0) {
throw errors::MalformedPacketException();
}
}
@@ -65,8 +65,8 @@ class ContentObject : public Packet {
throw errors::MalformedPacketException();
}
- if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
- 0) {
+ if (hicn_data_get_name(format_, packet_start_,
+ &name_.getStructReference()) < 0) {
throw errors::MalformedPacketException();
}
}
diff --git a/libtransport/includes/hicn/transport/core/interest.h b/libtransport/includes/hicn/transport/core/interest.h
index b7ce3c3a0..9e6cdccb9 100644
--- a/libtransport/includes/hicn/transport/core/interest.h
+++ b/libtransport/includes/hicn/transport/core/interest.h
@@ -29,14 +29,6 @@ const uint32_t MAX_AGGREGATED_INTEREST = 128;
class Interest
: public Packet /*, public std::enable_shared_from_this<Interest>*/ {
- 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 */
- /* ... */
- };
-
public:
using Ptr = std::shared_ptr<Interest>;
@@ -51,7 +43,7 @@ class Interest
Interest(CopyBufferOp op, Args &&...args)
: Packet(op, std::forward<Args>(args)...) {
if (hicn_interest_get_name(format_, packet_start_,
- name_.getStructReference()) < 0) {
+ &name_.getStructReference()) < 0) {
throw errors::MalformedPacketException();
}
}
@@ -60,7 +52,7 @@ class Interest
Interest(WrapBufferOp op, Args &&...args)
: Packet(op, std::forward<Args>(args)...) {
if (hicn_interest_get_name(format_, packet_start_,
- name_.getStructReference()) < 0) {
+ &name_.getStructReference()) < 0) {
throw errors::MalformedPacketException();
}
}
@@ -108,6 +100,12 @@ class Interest
uint32_t numberOfSuffixes();
+ uint32_t *getRequestBitmap();
+
+ void setRequestBitmap(const uint32_t *request_bitmap);
+
+ bool isValid();
+
auto shared_from_this() { return utils::shared_from(this); }
private:
diff --git a/libtransport/includes/hicn/transport/core/io_module.h b/libtransport/includes/hicn/transport/core/io_module.h
index 817d96d00..31da0b882 100644
--- a/libtransport/includes/hicn/transport/core/io_module.h
+++ b/libtransport/includes/hicn/transport/core/io_module.h
@@ -19,6 +19,7 @@
#include <hicn/transport/core/connector.h>
#include <hicn/transport/core/packet.h>
#include <hicn/transport/core/prefix.h>
+#include <hicn/transport/portability/endianess.h>
#include <hicn/transport/portability/portability.h>
#include <hicn/transport/utils/chrono_typedefs.h>
#include <hicn/transport/utils/membuf.h>
@@ -48,13 +49,12 @@ class IoModule : utils::NonCopyable {
mtu_(1500),
output_interface_(""),
content_store_reserved_(5000) {
- inet_address_.v4.as_u32 = htonl(0x7f00001);
+ inet_address_.v4.as_u32 = portability::host_to_net(0x7f00001);
inet6_address_.v6.as_u8[15] = 0x01;
}
public:
static IoModule *load(const char *);
- static bool unload(IoModule *);
public:
virtual ~IoModule();
@@ -65,6 +65,7 @@ class IoModule : utils::NonCopyable {
virtual void init(Connector::PacketReceivedCallback &&receive_callback,
Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name = "Libtransport") = 0;
@@ -108,11 +109,6 @@ class IoModule : utils::NonCopyable {
const std::string &getOutputInterface() { return output_interface_; }
-#ifndef ANDROID
- private:
- void *handle_;
-#endif
-
protected:
ip_address_t inet_address_;
ip_address_t inet6_address_;
diff --git a/libtransport/includes/hicn/transport/core/name.h b/libtransport/includes/hicn/transport/core/name.h
index 5cb4efd10..cf6d3097c 100644
--- a/libtransport/includes/hicn/transport/core/name.h
+++ b/libtransport/includes/hicn/transport/core/name.h
@@ -46,6 +46,7 @@ class Name {
friend class Packet;
friend class ContentObject;
friend class Interest;
+ friend class Prefix;
static const uint32_t standard_name_string_length = 100;
@@ -102,11 +103,11 @@ class Name {
int getAddressFamily() const;
private:
- TRANSPORT_ALWAYS_INLINE const NameStruct *getConstStructReference() const {
- return &name_;
+ TRANSPORT_ALWAYS_INLINE const NameStruct &getConstStructReference() const {
+ return name_;
}
- TRANSPORT_ALWAYS_INLINE NameStruct *getStructReference() { return &name_; }
+ TRANSPORT_ALWAYS_INLINE NameStruct &getStructReference() { return name_; }
NameStruct name_;
};
diff --git a/libtransport/includes/hicn/transport/core/prefix.h b/libtransport/includes/hicn/transport/core/prefix.h
index 13401e1a8..778491a31 100644
--- a/libtransport/includes/hicn/transport/core/prefix.h
+++ b/libtransport/includes/hicn/transport/core/prefix.h
@@ -25,13 +25,9 @@ class Prefix {
public:
Prefix();
- Prefix(const char *prefix);
-
Prefix(const std::string &prefix);
- Prefix(std::string &&prefix);
-
- Prefix(std::string &prefix, uint16_t prefix_length);
+ Prefix(const std::string &prefix, uint16_t prefix_length);
Prefix(const core::Name &content_name, uint16_t prefix_length);
@@ -39,6 +35,8 @@ class Prefix {
bool operator==(const Prefix &prefix) const;
+ bool operator!=(const Prefix &prefix) const { return !operator==(prefix); }
+
std::unique_ptr<Sockaddr> toSockaddr() const;
uint16_t getPrefixLength() const;
@@ -47,26 +45,22 @@ class Prefix {
std::string getNetwork() const;
- int contains(const ip_address_t &content_name) const;
+ Prefix &setNetwork(const std::string &network);
- int contains(const core::Name &content_name) const;
+ int getAddressFamily() const;
- Name getName() const;
+ bool contains(const ip_address_t &content_name) const;
- Name getRandomName() const;
+ bool contains(const core::Name &content_name) const;
Name getName(const core::Name &mask, const core::Name &components,
const core::Name &content_name) const;
Name mapName(const core::Name &content_name) const;
- Prefix &setNetwork(std::string &network);
-
- int getAddressFamily() const;
-
- Prefix &setAddressFamily(int address_family);
-
+ Name makeName() const;
Name makeRandomName() const;
+ Name makeNameWithIndex(std::uint64_t index) const;
const ip_prefix_t &toIpPrefixStruct() const;
@@ -74,8 +68,10 @@ class Prefix {
static bool checkPrefixLengthAndAddressFamily(uint16_t prefix_length,
int family);
- void buildPrefix(std::string &prefix, uint16_t prefix_length, int family);
+ void buildPrefix(const std::string &prefix, uint16_t prefix_length,
+ int family);
+ private:
ip_prefix_t ip_prefix_;
};
diff --git a/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt b/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt
index 1acaadcf0..43f95a466 100644
--- a/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/interfaces/CMakeLists.txt
@@ -24,11 +24,4 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/notification.h
)
-if (${OPENSSL_VERSION} VERSION_EQUAL "1.1.1a" OR ${OPENSSL_VERSION} VERSION_GREATER "1.1.1a")
- list(APPEND HEADER_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_producer.h
- ${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_consumer.h
- )
-endif()
-
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
diff --git a/libtransport/includes/hicn/transport/interfaces/global_conf_interface.h b/libtransport/includes/hicn/transport/interfaces/global_conf_interface.h
index a9fe6fac6..e1465d375 100644
--- a/libtransport/includes/hicn/transport/interfaces/global_conf_interface.h
+++ b/libtransport/includes/hicn/transport/interfaces/global_conf_interface.h
@@ -26,8 +26,16 @@ namespace transport {
namespace interface {
namespace global_config {
-static const constexpr char io_module_section[] = "io_module";
-void parseConfigurationFile(const std::string& path = "");
+class GlobalConfigInterface {
+ public:
+ GlobalConfigInterface();
+ ~GlobalConfigInterface();
+ void parseConfigurationFile(const std::string& path = "") const;
+
+ private:
+ void libtransportConfigInit() const;
+ void libtransportConfigTerminate() const;
+};
class ConfigurationObject {
public:
@@ -49,7 +57,9 @@ class ConfigurationObject {
class IoModuleConfiguration : public ConfigurationObject {
public:
- std::string getKey() const override { return io_module_section; }
+ static inline char section[] = "io_module";
+
+ std::string getKey() const override { return section; }
std::string name;
std::vector<std::string> search_path;
diff --git a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h b/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h
deleted file mode 100644
index a67634c1e..000000000
--- a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_consumer.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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/socket_consumer.h>
-
-namespace transport {
-
-namespace interface {
-
-class P2PSecureConsumerSocket : public ConsumerSocket {
- public:
- 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
deleted file mode 100644
index e197a3658..000000000
--- a/libtransport/includes/hicn/transport/interfaces/p2psecure_socket_producer.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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/socket_producer.h>
-
-namespace transport {
-
-namespace interface {
-
-class P2PSecureProducerSocket : public ProducerSocket {
- public:
- P2PSecureProducerSocket();
- P2PSecureProducerSocket(bool rtc, std::string &keystore_path,
- std::string &keystore_pwd);
- ~P2PSecureProducerSocket() = default;
-};
-
-} // namespace interface
-
-} // end namespace transport
diff --git a/libtransport/includes/hicn/transport/interfaces/portal.h b/libtransport/includes/hicn/transport/interfaces/portal.h
index 1a22b1f1d..bca78cb3b 100644
--- a/libtransport/includes/hicn/transport/interfaces/portal.h
+++ b/libtransport/includes/hicn/transport/interfaces/portal.h
@@ -95,7 +95,7 @@ class Portal : private utils::NonCopyable {
* parameter. Otherwise ConsumerCallback::onTimeout will be used.
*/
void sendInterest(
- core::Interest::Ptr &&interest,
+ core::Interest::Ptr &interest, uint32_t lifetime,
OnContentObjectCallback &&on_content_object_callback = UNSET_CALLBACK,
OnInterestTimeoutCallback &&on_interest_timeout_callback =
UNSET_CALLBACK);
diff --git a/libtransport/includes/hicn/transport/interfaces/socket_consumer.h b/libtransport/includes/hicn/transport/interfaces/socket_consumer.h
index e26fe5a85..d997634da 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_consumer.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_consumer.h
@@ -250,6 +250,9 @@ class ConsumerSocket : private utils::NonCopyable {
int setSocketOption(int socket_option_key,
interface::IcnObserver *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::shared_ptr<auth::Verifier> &socket_option_value);
@@ -283,6 +286,9 @@ class ConsumerSocket : private utils::NonCopyable {
int getSocketOption(int socket_option_key, IcnObserver **socket_option_value);
int getSocketOption(int socket_option_key,
+ std::shared_ptr<auth::Signer> &socket_option_value);
+
+ int getSocketOption(int socket_option_key,
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 0e19ae629..da8eafcd9 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h
@@ -53,9 +53,9 @@ static constexpr uint32_t key_locator_size = 60; // bytes
static constexpr uint32_t limit_guard = 80; // bytes
static constexpr uint32_t digest_size = 34; // bytes
static constexpr uint32_t max_out_of_order_segments = 3; // content object
-static constexpr uint32_t unverified_interval = 60000; // milliseconds
-static constexpr double unverified_ratio = 0.2;
-static constexpr uint32_t manifest_capacity = 20;
+static constexpr uint32_t manifest_max_capacity = 30;
+static constexpr uint32_t manifest_factor_relevant = 100;
+static constexpr uint32_t manifest_factor_alert = 20;
// RAAQM
static constexpr int sample_number = 30;
diff --git a/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h b/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h
index 6cba50d8b..a14c8414c 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_options_keys.h
@@ -46,6 +46,9 @@ typedef enum {
LOW_RATE_AND_BESTPATH = 25,
LOW_RATE_AND_REPLICATION = 26,
LOW_RATE_AND_ALL_FWD_STRATEGIES = 27,
+ FEC_ONLY_LOW_RES_LOSSES = 28,
+ DELAY_AND_BESTPATH = 29,
+ DELAY_AND_REPLICATION = 30,
} RtcTransportRecoveryStrategies;
typedef enum {
@@ -58,23 +61,23 @@ typedef enum {
INTEREST_LIFETIME = 107,
CONTENT_OBJECT_EXPIRY_TIME = 108,
MAX_SEGMENT_SIZE = 109,
- MIN_WINDOW_SIZE = 111,
- MAX_WINDOW_SIZE = 112,
- CURRENT_WINDOW_SIZE = 113,
- ASYNC_MODE = 114,
- MAKE_MANIFEST = 115,
- PORTAL = 116,
- RUNNING = 117,
- APPLICATION_BUFFER = 118,
- HASH_ALGORITHM = 119,
- SIGNER = 121,
- VERIFIER = 122,
- UNVERIFIED_INTERVAL = 123,
- UNVERIFIED_RATIO = 124,
- STATS_INTERVAL = 125,
- SUFFIX_STRATEGY = 126,
- PACKET_FORMAT = 127,
- FEC_TYPE = 128,
+ MIN_WINDOW_SIZE = 110,
+ MAX_WINDOW_SIZE = 111,
+ CURRENT_WINDOW_SIZE = 112,
+ ASYNC_MODE = 113,
+ PORTAL = 114,
+ RUNNING = 115,
+ APPLICATION_BUFFER = 116,
+ HASH_ALGORITHM = 117,
+ SIGNER = 118,
+ VERIFIER = 119,
+ MANIFEST_MAX_CAPACITY = 120,
+ MANIFEST_FACTOR_RELEVANT = 121,
+ MANIFEST_FACTOR_ALERT = 122,
+ STATS_INTERVAL = 123,
+ SUFFIX_STRATEGY = 124,
+ PACKET_FORMAT = 125,
+ FEC_TYPE = 126,
} GeneralTransportOptions;
typedef enum {
@@ -139,6 +142,8 @@ typedef enum {
typedef enum {
RECOVERY_STRATEGY = 901,
AGGREGATED_DATA = 902,
+ CONTENT_SHARING_MODE = 903,
+ AGGREGATED_INTERESTS = 904,
} RtcTransportOptions;
} // namespace interface
diff --git a/libtransport/includes/hicn/transport/interfaces/socket_producer.h b/libtransport/includes/hicn/transport/interfaces/socket_producer.h
index 77b89742a..be08c9a0b 100644
--- a/libtransport/includes/hicn/transport/interfaces/socket_producer.h
+++ b/libtransport/includes/hicn/transport/interfaces/socket_producer.h
@@ -123,6 +123,10 @@ class ProducerSocket : private utils::NonCopyable {
int setSocketOption(int socket_option_key,
const std::shared_ptr<auth::Signer> &socket_option_value);
+ int setSocketOption(
+ int socket_option_key,
+ const std::shared_ptr<auth::Verifier> &socket_option_value);
+
int setSocketOption(int socket_option_key,
const std::string &socket_option_value);
@@ -154,6 +158,9 @@ class ProducerSocket : private utils::NonCopyable {
int getSocketOption(int socket_option_key,
std::shared_ptr<auth::Signer> &socket_option_value);
+ int getSocketOption(int socket_option_key,
+ std::shared_ptr<auth::Verifier> &socket_option_value);
+
int getSocketOption(int socket_option_key, std::string &socket_option_value);
int getSocketOption(int socket_option_key,
diff --git a/libtransport/includes/hicn/transport/interfaces/statistics.h b/libtransport/includes/hicn/transport/interfaces/statistics.h
index 4d9e1bfe2..e83aa9a27 100644
--- a/libtransport/includes/hicn/transport/interfaces/statistics.h
+++ b/libtransport/includes/hicn/transport/interfaces/statistics.h
@@ -73,10 +73,10 @@ class TransportStatistics {
}
TRANSPORT_ALWAYS_INLINE void updateAverageRtt(
- const utils::SteadyTime::Milliseconds &rtt) {
- auto rtt_milliseconds = rtt.count();
- average_rtt_ =
- (alpha_ * average_rtt_) + ((1. - alpha_) * double(rtt_milliseconds));
+ const utils::SteadyTime::Microseconds &rtt) {
+ double rtt_milliseconds = double(rtt.count()) / 1000.0;
+
+ average_rtt_ = (alpha_ * average_rtt_) + ((1. - alpha_) * rtt_milliseconds);
}
TRANSPORT_ALWAYS_INLINE void updateAverageWindowSize(double current_window) {
diff --git a/libtransport/includes/hicn/transport/portability/CMakeLists.txt b/libtransport/includes/hicn/transport/portability/CMakeLists.txt
index 7a688b1f1..d29ec737c 100644
--- a/libtransport/includes/hicn/transport/portability/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/portability/CMakeLists.txt
@@ -15,6 +15,8 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/c_portability.h
${CMAKE_CURRENT_SOURCE_DIR}/portability.h
${CMAKE_CURRENT_SOURCE_DIR}/cpu.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/cache.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/endianess.h
)
list(APPEND SOURCE_FILES
diff --git a/libtransport/includes/hicn/transport/portability/cache.h b/libtransport/includes/hicn/transport/portability/cache.h
new file mode 100644
index 000000000..ae113c7d6
--- /dev/null
+++ b/libtransport/includes/hicn/transport/portability/cache.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/platform.h>
+
+namespace transport {
+namespace portability {
+namespace cache {
+
+/**
+ * @Prefetch utilities
+ */
+
+/* Default cache line size of 64 bytes. */
+#ifndef LOG2_CACHE_LINE_BYTES
+static constexpr const std::size_t klog2_cache_line_bytes = 6;
+#else
+static constexpr const std::size_t klog2_cache_line_bytes =
+ LOG2_CACHE_LINE_BYTES;
+#endif
+
+/* How much data prefetch instruction prefetches */
+#ifndef LOG2_CACHE_PREFETCH_BYTES
+static constexpr const std::size_t klog2_cache_prefetch_bytes =
+ klog2_cache_line_bytes;
+#else
+static constexpr const std::size_t klog2_cache_prefetch_bytes =
+ LOG2_CACHE_PREFETCH_BYTES;
+#endif
+
+/* Default cache line fill buffers. */
+#ifndef N_PREFETCHES
+static constexpr const std::size_t kn_prefetches = 16;
+#else
+static constexpr const std::size_t kn_prefetches = N_PREFETCHES;
+#endif
+
+static constexpr const std::size_t kcache_line_bytes =
+ (1 << klog2_cache_line_bytes);
+static constexpr const std::size_t kcache_prefetch_bytes =
+ (1 << klog2_cache_prefetch_bytes);
+
+static constexpr const int READ = 0;
+static constexpr const int LOAD = 0; /* alias for read */
+static constexpr const int WRITE = 1;
+static constexpr const int STORE = 1; /* alias for write */
+
+#if defined(__GNUC__) || defined(__clang__)
+// Clang & GCC
+
+template <int type>
+static inline void _prefetch(uint8_t *addr, std::size_t n, std::size_t size) {
+ if (size > n * kcache_prefetch_bytes) {
+ __builtin_prefetch(addr + n * kcache_prefetch_bytes, type,
+ /* locality */ 3);
+ }
+}
+
+template <typename T, int type>
+static inline void prefetch(T *addr, std::size_t size) {
+ uint8_t *_addr = reinterpret_cast<uint8_t *>(addr);
+
+ _prefetch<type>(_addr, 0, size);
+ _prefetch<type>(_addr, 1, size);
+ _prefetch<type>(_addr, 2, size);
+ _prefetch<type>(_addr, 3, size);
+}
+#endif
+
+} // namespace cache
+} // namespace portability
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/portability/endianess.h b/libtransport/includes/hicn/transport/portability/endianess.h
new file mode 100644
index 000000000..c18ac82cf
--- /dev/null
+++ b/libtransport/includes/hicn/transport/portability/endianess.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/errors.h>
+
+namespace transport {
+namespace portability {
+
+#if (__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)
+static constexpr const bool kIsBigEndian = false;
+static constexpr const bool kIsLittleEndian = true;
+#else
+static constexpr const bool kIsBigEndian = true;
+static constexpr const bool kIsLittleEndian = false;
+#endif
+
+template <typename T>
+inline T bswap(T value) {
+ throw errors::RuntimeException("Not implemented");
+}
+
+template <>
+inline int16_t bswap(int16_t value) {
+ return __builtin_bswap16(value);
+}
+
+template <>
+inline int32_t bswap(int32_t value) {
+ return __builtin_bswap32(value);
+}
+
+template <>
+inline int64_t bswap(int64_t value) {
+ return __builtin_bswap64(value);
+}
+
+template <>
+inline uint16_t bswap(uint16_t value) {
+ return __builtin_bswap16(value);
+}
+
+template <>
+inline uint32_t bswap(uint32_t value) {
+ return __builtin_bswap32(value);
+}
+
+template <>
+inline uint64_t bswap(uint64_t value) {
+ return __builtin_bswap64(value);
+}
+
+template <typename T>
+inline T host_to_net(T value) {
+ if constexpr (kIsLittleEndian) {
+ return bswap(value);
+ }
+
+ return value;
+}
+
+template <typename T>
+inline T net_to_host(T value) {
+ if constexpr (kIsLittleEndian) {
+ return bswap(value);
+ }
+
+ return value;
+}
+
+} // namespace portability
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/portability/portability.h b/libtransport/includes/hicn/transport/portability/portability.h
index b093f8892..fd6eca4de 100644
--- a/libtransport/includes/hicn/transport/portability/portability.h
+++ b/libtransport/includes/hicn/transport/portability/portability.h
@@ -26,6 +26,7 @@
#include <cstddef>
+namespace transport {
namespace portability {
// Generalize warning push/pop.
@@ -66,3 +67,4 @@ namespace portability {
#endif
} // namespace portability
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/includes/hicn/transport/utils/chrono_typedefs.h b/libtransport/includes/hicn/transport/utils/chrono_typedefs.h
index ddfbd00cd..14234eaa1 100644
--- a/libtransport/includes/hicn/transport/utils/chrono_typedefs.h
+++ b/libtransport/includes/hicn/transport/utils/chrono_typedefs.h
@@ -79,7 +79,7 @@ class Time {
public:
using Clock = T;
using TimePoint = typename Clock::time_point;
- using Rep = double;
+ using Rep = uint64_t;
using Seconds = std::chrono::duration<Rep>;
using Milliseconds = std::chrono::duration<Rep, std::milli>;
using Microseconds = std::chrono::duration<Rep, std::micro>;
diff --git a/libtransport/includes/hicn/transport/utils/color.h b/libtransport/includes/hicn/transport/utils/color.h
new file mode 100644
index 000000000..3e8d93e14
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/color.h
@@ -0,0 +1,95 @@
+/*
+ * 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 <array>
+#include <ostream>
+#include <random>
+#include <sstream>
+
+namespace utils {
+
+#define foreach_modifier \
+ _(RESET, 0) \
+ _(BOLD, 1) \
+ _(FG_DEFAULT, 39) \
+ _(FG_BLACK, 30) \
+ _(FG_RED, 31) \
+ _(FG_GREEN, 32) \
+ _(FG_YELLOW, 33) \
+ _(FG_BLUE, 34) \
+ _(FG_MAGENTA, 35) \
+ _(FG_CYAN, 36) \
+ _(FG_LIGHT_GRAY, 37) \
+ _(FG_DARK_GRAY, 90) \
+ _(FG_LIGHT_RED, 91) \
+ _(FG_LIGHT_GREEN, 92) \
+ _(FG_LIGHT_YELLOW, 93) \
+ _(FG_LIGHT_BLUE, 94) \
+ _(FG_LIGHT_MAGENTA, 95) \
+ _(FG_LIGHT_CYAN, 96) \
+ _(FG_WHITE, 97) \
+ _(BG_RED, 41) \
+ _(BG_GREEN, 42) \
+ _(BG_BLUE, 44) \
+ _(BG_DEFAULT, 49)
+
+class ColorModifier {
+ static inline const std::size_t n_modifiers = 23;
+ static inline const char format_string_start[] = "\033[";
+ static inline const char format_string_end[] = "m";
+
+ public:
+ enum class Code {
+#define _(name, value) name = value,
+ foreach_modifier
+#undef _
+ };
+
+ static inline std::array<Code, n_modifiers> code_array = {
+#define _(name, value) Code::name,
+ foreach_modifier
+#undef _
+ };
+
+ static Code getRandomModifier() {
+ static std::random_device rd;
+ static std::mt19937 gen(rd());
+ static std::uniform_int_distribution<> distr(4, 17);
+
+ return code_array[distr(gen)];
+ }
+
+ ColorModifier(Code code) : code_(code), color_string_() {
+ std::stringstream ss;
+ if (std::getenv("COLORTERM") != nullptr) {
+ ss << format_string_start << static_cast<int>(code_) << format_string_end;
+ color_string_ = ss.str();
+ }
+ }
+
+ ColorModifier() : ColorModifier(getRandomModifier()) {}
+
+ friend std::ostream& operator<<(std::ostream& os, const ColorModifier& mod) {
+ return os << mod.color_string_;
+ }
+
+ private:
+ Code code_;
+ std::string color_string_;
+};
+
+} // namespace utils \ 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
index 2cd2f3aca..164c853a5 100644
--- a/libtransport/includes/hicn/transport/utils/event_thread.h
+++ b/libtransport/includes/hicn/transport/utils/event_thread.h
@@ -29,16 +29,16 @@ class EventThread {
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_)),
+ work_guard_(asio::make_work_guard(io_service_.get())),
thread_(nullptr),
detached_(detached) {
run();
}
- EventThread(bool detached = false)
+ explicit 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_)),
+ work_guard_(asio::make_work_guard(io_service_.get())),
thread_(nullptr),
detached_(detached) {
run();
@@ -47,22 +47,12 @@ class EventThread {
EventThread(const EventThread&) = delete;
EventThread& operator=(const EventThread&) = delete;
- EventThread(EventThread&& other)
+ EventThread(EventThread&& other) noexcept
: internal_io_service_(std::move(other.internal_io_service_)),
io_service_(std::move(other.io_service_)),
- work_(std::move(other.work_)),
+ work_guard_(std::move(other.work_guard_)),
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;
- }
+ detached_(other.detached_) {}
~EventThread() { stop(); }
@@ -89,16 +79,16 @@ class EventThread {
template <typename Func>
void add(Func&& f) {
- io_service_.get().post(std::forward<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));
+ io_service_.get().dispatch(std::forward<Func>(f));
}
template <typename Func>
- void addAndWaitForExecution(Func&& f) {
+ void addAndWaitForExecution(Func&& f) const {
auto promise = std::promise<void>();
auto future = promise.get_future();
@@ -111,7 +101,7 @@ class EventThread {
}
void stop() {
- work_.reset();
+ add([this]() { work_guard_.reset(); });
if (thread_ && thread_->joinable()) {
thread_->join();
@@ -120,14 +110,14 @@ class EventThread {
thread_.reset();
}
- bool stopped() { return io_service_.get().stopped(); }
+ bool stopped() const { 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_;
+ asio::executor_work_guard<asio::io_context::executor_type> work_guard_;
std::unique_ptr<std::thread> thread_;
bool detached_;
};
diff --git a/libtransport/includes/hicn/transport/utils/linux.h b/libtransport/includes/hicn/transport/utils/linux.h
index 03d29c1db..14ef179ac 100644
--- a/libtransport/includes/hicn/transport/utils/linux.h
+++ b/libtransport/includes/hicn/transport/utils/linux.h
@@ -44,7 +44,7 @@ static TRANSPORT_ALWAYS_INLINE int retrieveInterfaceAddress(
uint16_t prefix = 0;
memcpy(&prefix, tmp->sin6_addr.s6_addr, sizeof(uint16_t));
- if (htons(LINK_LOCAL_PREFIX) != prefix) {
+ if (portability::host_to_net(LINK_LOCAL_PREFIX) != prefix) {
*address = *(struct sockaddr_in6 *)ifa->ifa_addr;
getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), addr,
sizeof(addr), NULL, 0, NI_NUMERICHOST);
diff --git a/libtransport/includes/hicn/transport/utils/thread_pool.h b/libtransport/includes/hicn/transport/utils/thread_pool.h
index e4e47209c..76218ff09 100644
--- a/libtransport/includes/hicn/transport/utils/thread_pool.h
+++ b/libtransport/includes/hicn/transport/utils/thread_pool.h
@@ -29,8 +29,11 @@ class ThreadPool : public NonCopyable {
std::size_t n_threads = std::thread::hardware_concurrency())
: workers_(n_threads > 0 ? n_threads : 1) {}
+ ~ThreadPool() = default;
+
std::size_t getNThreads() const { return workers_.size(); }
EventThread &getWorker(std::size_t i) { return workers_.at(i); }
+ std::vector<EventThread> &getWorkers() { return workers_; }
private:
std::vector<EventThread> workers_;
diff --git a/libtransport/src/auth/signer.cc b/libtransport/src/auth/signer.cc
index 918e271f5..f13df53eb 100644
--- a/libtransport/src/auth/signer.cc
+++ b/libtransport/src/auth/signer.cc
@@ -15,6 +15,7 @@
#include <glog/logging.h>
#include <hicn/transport/auth/signer.h>
+#include <hicn/transport/core/interest.h>
#include <hicn/transport/utils/chrono_typedefs.h>
#include "hicn/transport/core/global_object_pool.h"
@@ -50,6 +51,15 @@ void Signer::signPacket(PacketPtr packet) {
hicn_header_t header_copy;
hicn_packet_copy_header(format, packet->packet_start_, &header_copy, false);
+ // Copy bitmap from interest manifest
+ uint32_t request_bitmap[BITMAP_SIZE] = {0};
+ if (packet->isInterest()) {
+ core::Interest *interest = dynamic_cast<core::Interest *>(packet);
+ if (interest->hasManifest())
+ memcpy(request_bitmap, interest->getRequestBitmap(),
+ BITMAP_SIZE * sizeof(uint32_t));
+ }
+
// Fill in the hICN AH header
auto now = utils::SteadyTime::nowMs().count();
packet->setSignatureTimestamp(now);
@@ -69,6 +79,12 @@ void Signer::signPacket(PacketPtr packet) {
// Restore header
hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false);
+
+ // Restore bitmap in interest manifest
+ if (packet->isInterest()) {
+ core::Interest *interest = dynamic_cast<core::Interest *>(packet);
+ interest->setRequestBitmap(request_bitmap);
+ }
}
void Signer::signBuffer(const std::vector<uint8_t> &buffer) {
@@ -241,16 +257,23 @@ void AsymmetricSigner::setKey(CryptoSuite suite, std::shared_ptr<EVP_PKEY> key,
std::shared_ptr<EVP_PKEY> pub_key) {
suite_ = suite;
key_ = key;
- signature_len_ = EVP_PKEY_size(key.get());
+
+ signature_len_ = EVP_PKEY_size(key_.get());
DCHECK(signature_len_ <= signature_->tailroom());
+
signature_->setLength(signature_len_);
- std::vector<uint8_t> pbk(i2d_PublicKey(pub_key.get(), nullptr));
- uint8_t *pbk_ptr = pbk.data();
- int len = i2d_PublicKey(pub_key.get(), &pbk_ptr);
+ size_t enc_pbk_len = i2d_PublicKey(pub_key.get(), nullptr);
+ DCHECK(enc_pbk_len >= 0);
+
+ uint8_t *enc_pbkey_raw = nullptr;
+ i2d_PublicKey(pub_key.get(), &enc_pbkey_raw);
+ DCHECK(enc_pbkey_raw != nullptr);
key_id_ = CryptoHash(getHashType());
- key_id_.computeDigest(pbk_ptr, len);
+ key_id_.computeDigest(enc_pbkey_raw, enc_pbk_len);
+
+ OPENSSL_free(enc_pbkey_raw);
}
size_t AsymmetricSigner::getSignatureFieldSize() const {
diff --git a/libtransport/src/auth/verifier.cc b/libtransport/src/auth/verifier.cc
index 5d5f01711..e257582f6 100644
--- a/libtransport/src/auth/verifier.cc
+++ b/libtransport/src/auth/verifier.cc
@@ -15,6 +15,7 @@
#include <hicn/transport/auth/verifier.h>
#include <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/core/interest.h>
#include <protocols/errors.h>
#include "glog/logging.h"
@@ -51,6 +52,14 @@ bool Verifier::verifyPacket(PacketPtr packet) {
hicn_header_t header_copy;
hicn_packet_copy_header(format, packet->packet_start_, &header_copy, false);
+ // Copy bitmap from interest manifest
+ uint32_t request_bitmap[BITMAP_SIZE] = {0};
+ if (packet->isInterest()) {
+ core::Interest *interest = dynamic_cast<core::Interest *>(packet);
+ memcpy(request_bitmap, interest->getRequestBitmap(),
+ BITMAP_SIZE * sizeof(uint32_t));
+ }
+
// Retrieve packet signature
utils::MemBuf::Ptr signature_raw = packet->getSignature();
std::size_t signature_len = packet->getSignatureSize();
@@ -69,6 +78,12 @@ bool Verifier::verifyPacket(PacketPtr packet) {
packet->setSignature(signature_raw);
packet->setSignatureSize(signature_raw->length());
+ // Restore bitmap in interest manifest
+ if (packet->isInterest()) {
+ core::Interest *interest = dynamic_cast<core::Interest *>(packet);
+ interest->setRequestBitmap(request_bitmap);
+ }
+
return valid_packet;
}
diff --git a/libtransport/src/core/CMakeLists.txt b/libtransport/src/core/CMakeLists.txt
index b9b024d60..777772a04 100644
--- a/libtransport/src/core/CMakeLists.txt
+++ b/libtransport/src/core/CMakeLists.txt
@@ -14,17 +14,18 @@
list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/facade.h
${CMAKE_CURRENT_SOURCE_DIR}/manifest.h
- ${CMAKE_CURRENT_SOURCE_DIR}/manifest_inline.h
${CMAKE_CURRENT_SOURCE_DIR}/manifest_format_fixed.h
${CMAKE_CURRENT_SOURCE_DIR}/manifest_format.h
${CMAKE_CURRENT_SOURCE_DIR}/pending_interest.h
${CMAKE_CURRENT_SOURCE_DIR}/portal.h
${CMAKE_CURRENT_SOURCE_DIR}/errors.h
${CMAKE_CURRENT_SOURCE_DIR}/global_configuration.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/global_id_counter.h
${CMAKE_CURRENT_SOURCE_DIR}/local_connector.h
${CMAKE_CURRENT_SOURCE_DIR}/global_workers.h
${CMAKE_CURRENT_SOURCE_DIR}/udp_connector.h
${CMAKE_CURRENT_SOURCE_DIR}/udp_listener.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/global_module_manager.h
)
list(APPEND SOURCE_FILES
@@ -38,9 +39,9 @@ list(APPEND SOURCE_FILES
${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}/udp_connector.cc
${CMAKE_CURRENT_SOURCE_DIR}/udp_listener.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/constructor.cc
)
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES Android)
@@ -56,4 +57,4 @@ if (NOT ${CMAKE_SYSTEM_NAME} MATCHES Android)
endif()
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/core/constructor.cc b/libtransport/src/core/constructor.cc
new file mode 100644
index 000000000..0c7f0dfa8
--- /dev/null
+++ b/libtransport/src/core/constructor.cc
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/global_module_manager.h>
+#include <core/global_workers.h>
+#include <hicn/transport/core/global_object_pool.h>
+
+namespace transport {
+namespace core {
+
+void __attribute__((constructor)) libtransportInit() {
+ // First the global module manager is initialized
+ GlobalModuleManager::getInstance();
+ // Then the packet allocator is initialized
+ PacketManager<>::getInstance();
+ // Then the global configuration is initialized
+ GlobalConfiguration::getInstance();
+ // Then the global workers are initialized
+ GlobalWorkers::getInstance();
+}
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/core/content_object.cc b/libtransport/src/core/content_object.cc
index 643e0388e..e66b2a6cd 100644
--- a/libtransport/src/core/content_object.cc
+++ b/libtransport/src/core/content_object.cc
@@ -15,6 +15,7 @@
#include <hicn/transport/core/content_object.h>
#include <hicn/transport/errors/errors.h>
+#include <hicn/transport/portability/endianess.h>
#include <hicn/transport/utils/branch_prediction.h>
extern "C" {
@@ -46,7 +47,7 @@ ContentObject::ContentObject(const Name &name, Packet::Format format,
}
if (TRANSPORT_EXPECT_FALSE(hicn_data_get_name(format_, packet_start_,
- name_.getStructReference()) <
+ &name_.getStructReference()) <
0)) {
throw errors::MalformedPacketException();
}
@@ -91,7 +92,7 @@ ContentObject::~ContentObject() {}
const Name &ContentObject::getName() const {
if (!name_) {
if (hicn_data_get_name(format_, packet_start_,
- (hicn_name_t *)name_.getConstStructReference()) <
+ (hicn_name_t *)&name_.getConstStructReference()) <
0) {
throw errors::MalformedPacketException();
}
@@ -104,11 +105,11 @@ Name &ContentObject::getWritableName() { return const_cast<Name &>(getName()); }
void ContentObject::setName(const Name &name) {
if (hicn_data_set_name(format_, packet_start_,
- name.getConstStructReference()) < 0) {
+ &name.getConstStructReference()) < 0) {
throw errors::RuntimeException("Error setting content object name.");
}
- if (hicn_data_get_name(format_, packet_start_, name_.getStructReference()) <
+ if (hicn_data_get_name(format_, packet_start_, &name_.getStructReference()) <
0) {
throw errors::MalformedPacketException();
}
@@ -121,11 +122,11 @@ uint32_t ContentObject::getPathLabel() const {
"Error retrieving the path label from content object");
}
- return ntohl(path_label);
+ return portability::net_to_host(path_label);
}
ContentObject &ContentObject::setPathLabel(uint32_t path_label) {
- path_label = htonl(path_label);
+ path_label = portability::host_to_net(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/facade.h b/libtransport/src/core/facade.h
index 1ad4437e2..77c1d16d2 100644
--- a/libtransport/src/core/facade.h
+++ b/libtransport/src/core/facade.h
@@ -15,16 +15,16 @@
#pragma once
+#include <core/manifest.h>
#include <core/manifest_format_fixed.h>
-#include <core/manifest_inline.h>
#include <core/portal.h>
namespace transport {
namespace core {
-using ContentObjectManifest = core::ManifestInline<ContentObject, Fixed>;
-using InterestManifest = core::ManifestInline<Interest, Fixed>;
+using ContentObjectManifest = core::Manifest<Fixed>;
+using InterestManifest = core::Manifest<Fixed>;
} // namespace core
diff --git a/libtransport/src/io_modules/forwarder/global_id_counter.h b/libtransport/src/core/global_id_counter.h
index 0a67b76d5..0a67b76d5 100644
--- a/libtransport/src/io_modules/forwarder/global_id_counter.h
+++ b/libtransport/src/core/global_id_counter.h
diff --git a/libtransport/src/core/global_module_manager.h b/libtransport/src/core/global_module_manager.h
new file mode 100644
index 000000000..c9d272cdb
--- /dev/null
+++ b/libtransport/src/core/global_module_manager.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <glog/logging.h>
+#include <hicn/transport/utils/singleton.h>
+
+#ifndef _WIN32
+#include <dlfcn.h>
+#endif
+
+#include <atomic>
+#include <iostream>
+#include <mutex>
+#include <unordered_map>
+
+namespace transport {
+namespace core {
+
+class GlobalModuleManager : public utils::Singleton<GlobalModuleManager> {
+ public:
+ friend class utils::Singleton<GlobalModuleManager>;
+
+ ~GlobalModuleManager() {
+ for (const auto &[key, value] : modules_) {
+ unload(value);
+ }
+ }
+
+ void *loadModule(const std::string &module_name) {
+ void *handle = nullptr;
+ const char *error = nullptr;
+
+ // Lock
+ std::unique_lock lck(mtx_);
+
+ auto it = modules_.find(module_name);
+ if (it != modules_.end()) {
+ return it->second;
+ }
+
+ // open module
+ handle = dlopen(module_name.c_str(), RTLD_NOW);
+ if (!handle) {
+ if ((error = dlerror()) != nullptr) {
+ LOG(ERROR) << error;
+ }
+ return nullptr;
+ }
+
+ auto ret = modules_.try_emplace(module_name, handle);
+ DCHECK(ret.second);
+
+ return handle;
+ }
+
+ void unload(void *handle) {
+ // destroy object and close module
+ dlclose(handle);
+ }
+
+ bool unloadModule(const std::string &module_name) {
+ // Lock
+ std::unique_lock lck(mtx_);
+ auto it = modules_.find(module_name);
+ if (it != modules_.end()) {
+ unload(it->second);
+ return true;
+ }
+
+ return false;
+ }
+
+ private:
+ GlobalModuleManager() = default;
+ std::mutex mtx_;
+ std::unordered_map<std::string, void *> modules_;
+};
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/core/global_workers.h b/libtransport/src/core/global_workers.h
index 1ac254188..c5d794ef2 100644
--- a/libtransport/src/core/global_workers.h
+++ b/libtransport/src/core/global_workers.h
@@ -32,6 +32,8 @@ class GlobalWorkers : public utils::Singleton<GlobalWorkers> {
return thread_pool_.getWorker(counter_++ % thread_pool_.getNThreads());
}
+ auto& getWorkers() { return thread_pool_.getWorkers(); }
+
private:
GlobalWorkers() : counter_(0), thread_pool_() {}
diff --git a/libtransport/src/core/interest.cc b/libtransport/src/core/interest.cc
index b7719b3ed..8b9dcf256 100644
--- a/libtransport/src/core/interest.cc
+++ b/libtransport/src/core/interest.cc
@@ -21,6 +21,7 @@ extern "C" {
#ifndef _WIN32
TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat")
#endif
+#include <hicn/base.h>
#include <hicn/hicn.h>
}
@@ -39,12 +40,12 @@ Interest::Interest(const Name &interest_name, Packet::Format format,
}
if (hicn_interest_set_name(format_, packet_start_,
- interest_name.getConstStructReference()) < 0) {
+ &interest_name.getConstStructReference()) < 0) {
throw errors::MalformedPacketException();
}
if (hicn_interest_get_name(format_, packet_start_,
- name_.getStructReference()) < 0) {
+ &name_.getStructReference()) < 0) {
throw errors::MalformedPacketException();
}
}
@@ -64,7 +65,7 @@ Interest::Interest(hicn_format_t format, std::size_t additional_header_size)
Interest::Interest(MemBuf &&buffer) : Packet(std::move(buffer)) {
if (hicn_interest_get_name(format_, packet_start_,
- name_.getStructReference()) < 0) {
+ &name_.getStructReference()) < 0) {
throw errors::MalformedPacketException();
}
}
@@ -86,9 +87,9 @@ Interest::~Interest() {}
const Name &Interest::getName() const {
if (!name_) {
- if (hicn_interest_get_name(format_, packet_start_,
- (hicn_name_t *)name_.getConstStructReference()) <
- 0) {
+ if (hicn_interest_get_name(
+ format_, packet_start_,
+ (hicn_name_t *)&name_.getConstStructReference()) < 0) {
throw errors::MalformedPacketException();
}
}
@@ -100,12 +101,12 @@ Name &Interest::getWritableName() { return const_cast<Name &>(getName()); }
void Interest::setName(const Name &name) {
if (hicn_interest_set_name(format_, packet_start_,
- name.getConstStructReference()) < 0) {
+ &name.getConstStructReference()) < 0) {
throw errors::RuntimeException("Error setting interest name.");
}
if (hicn_interest_get_name(format_, packet_start_,
- name_.getStructReference()) < 0) {
+ &name_.getStructReference()) < 0) {
throw errors::MalformedPacketException();
}
}
@@ -150,6 +151,13 @@ void Interest::resetForHash() {
throw errors::RuntimeException(
"Error resetting interest fields for hash computation.");
}
+
+ // Reset request bitmap in manifest
+ if (hasManifest()) {
+ auto int_manifest_header =
+ (interest_manifest_header_t *)(writableData() + headerSize());
+ memset(int_manifest_header->request_bitmap, 0, BITMAP_SIZE * sizeof(u32));
+ }
}
bool Interest::hasManifest() {
@@ -171,19 +179,21 @@ void Interest::encodeSuffixes() {
// We assume interest does not hold signature for the moment.
auto int_manifest_header =
- (InterestManifestHeader *)(writableData() + headerSize());
- int_manifest_header->n_suffixes = suffix_set_.size();
- std::size_t additional_length =
- sizeof(InterestManifestHeader) +
- int_manifest_header->n_suffixes * sizeof(uint32_t);
+ (interest_manifest_header_t *)(writableData() + headerSize());
+ int_manifest_header->n_suffixes = (uint32_t)suffix_set_.size();
+ memset(int_manifest_header->request_bitmap, 0xFFFFFFFF,
+ BITMAP_SIZE * sizeof(u32));
uint32_t *suffix = (uint32_t *)(int_manifest_header + 1);
for (auto it = suffix_set_.begin(); it != suffix_set_.end(); it++, suffix++) {
*suffix = *it;
}
+ std::size_t additional_length =
+ sizeof(interest_manifest_header_t) +
+ int_manifest_header->n_suffixes * sizeof(uint32_t);
append(additional_length);
- updateLength(additional_length);
+ updateLength();
}
uint32_t *Interest::firstSuffix() {
@@ -191,7 +201,7 @@ uint32_t *Interest::firstSuffix() {
return nullptr;
}
- auto ret = (InterestManifestHeader *)(writableData() + headerSize());
+ auto ret = (interest_manifest_header_t *)(writableData() + headerSize());
ret += 1;
return (uint32_t *)ret;
@@ -202,11 +212,48 @@ uint32_t Interest::numberOfSuffixes() {
return 0;
}
- auto header = (InterestManifestHeader *)(writableData() + headerSize());
+ auto header = (interest_manifest_header_t *)(writableData() + headerSize());
return header->n_suffixes;
}
+uint32_t *Interest::getRequestBitmap() {
+ if (!hasManifest()) return nullptr;
+
+ auto header = (interest_manifest_header_t *)(writableData() + headerSize());
+ return header->request_bitmap;
+}
+
+void Interest::setRequestBitmap(const uint32_t *request_bitmap) {
+ if (!hasManifest()) return;
+
+ auto header = (interest_manifest_header_t *)(writableData() + headerSize());
+ memcpy(header->request_bitmap, request_bitmap,
+ BITMAP_SIZE * sizeof(uint32_t));
+}
+
+bool Interest::isValid() {
+ if (!hasManifest()) return true;
+
+ auto header = (interest_manifest_header_t *)(writableData() + headerSize());
+
+ if (header->n_suffixes == 0 ||
+ header->n_suffixes > MAX_SUFFIXES_IN_MANIFEST) {
+ std::cerr << "Manifest with invalid number of suffixes "
+ << header->n_suffixes;
+ return false;
+ }
+
+ uint32_t empty_bitmap[BITMAP_SIZE];
+ memset(empty_bitmap, 0, sizeof(empty_bitmap));
+ if (memcmp(empty_bitmap, header->request_bitmap, sizeof(empty_bitmap)) == 0) {
+ std::cerr << "Manifest with empty bitmap";
+ return false;
+ }
+
+ return true;
+}
+
} // end namespace core
} // end namespace transport
diff --git a/libtransport/src/core/io_module.cc b/libtransport/src/core/io_module.cc
index 69e4e8bcf..0f92cc47c 100644
--- a/libtransport/src/core/io_module.cc
+++ b/libtransport/src/core/io_module.cc
@@ -16,6 +16,7 @@
#ifndef _WIN32
#include <dlfcn.h>
#endif
+#include <core/global_module_manager.h>
#include <glog/logging.h>
#include <hicn/transport/core/io_module.h>
@@ -38,54 +39,28 @@ 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;
+ IoModule *iomodule = nullptr;
+ IoModule *(*creator)(void) = nullptr;
+ const char *error = nullptr;
- // open module
- handle = dlopen(module_name, RTLD_NOW);
- if (!handle) {
- if ((error = dlerror()) != 0) {
- LOG(ERROR) << error;
- }
- return 0;
- }
+ auto handle = GlobalModuleManager::getInstance().loadModule(module_name);
// get factory method
creator = (IoModule * (*)(void)) dlsym(handle, "create_module");
if (!creator) {
- if ((error = dlerror()) != 0) {
+ if ((error = dlerror()) != nullptr) {
LOG(ERROR) << error;
}
- return 0;
+ return nullptr;
}
// create object and return it
- module = (*creator)();
- module->handle_ = handle;
+ iomodule = (*creator)();
- return module;
+ return iomodule;
#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
diff --git a/libtransport/src/core/local_connector.cc b/libtransport/src/core/local_connector.cc
deleted file mode 100644
index f27be2e5c..000000000
--- a/libtransport/src/core/local_connector.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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/local_connector.h>
-#include <glog/logging.h>
-#include <hicn/transport/core/asio_wrapper.h>
-#include <hicn/transport/core/content_object.h>
-#include <hicn/transport/core/interest.h>
-#include <hicn/transport/errors/not_implemented_exception.h>
-
-namespace transport {
-namespace core {
-
-LocalConnector::~LocalConnector() {}
-
-void LocalConnector::close() { state_ = State::CLOSED; }
-
-void LocalConnector::send(Packet &packet) {
- if (!isConnected()) {
- return;
- }
-
- auto buffer =
- std::static_pointer_cast<utils::MemBuf>(packet.shared_from_this());
-
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "Sending packet to local socket.";
- io_service_.get().post([this, buffer]() mutable {
- std::vector<utils::MemBuf::Ptr> v{std::move(buffer)};
- receive_callback_(this, v, std::make_error_code(std::errc(0)));
- });
-}
-
-void LocalConnector::send(const utils::MemBuf::Ptr &buffer) {
- 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
index eede89e74..963f455e6 100644
--- a/libtransport/src/core/local_connector.h
+++ b/libtransport/src/core/local_connector.h
@@ -15,9 +15,11 @@
#pragma once
+#include <core/errors.h>
#include <hicn/transport/core/asio_wrapper.h>
#include <hicn/transport/core/connector.h>
#include <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/errors/not_implemented_exception.h>
#include <hicn/transport/utils/move_wrapper.h>
#include <hicn/transport/utils/shared_ptr_utils.h>
#include <io_modules/forwarder/errors.h>
@@ -34,19 +36,48 @@ class LocalConnector : public Connector {
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;
- }
+ io_service_work_(io_service_.get()) {}
- ~LocalConnector() override;
+ ~LocalConnector() override = default;
- void send(Packet &packet) override;
+ auto shared_from_this() { return utils::shared_from(this); }
- void send(const utils::MemBuf::Ptr &buffer) override;
+ void send(Packet &packet) override { send(packet.shared_from_this()); }
- void close() override;
+ void send(const utils::MemBuf::Ptr &buffer) override {
+ throw errors::NotImplementedException();
+ }
- auto shared_from_this() { return utils::shared_from(this); }
+ void receive(const std::vector<utils::MemBuf::Ptr> &buffers) override {
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Sending packet to local socket.";
+ std::weak_ptr<LocalConnector> self = shared_from_this();
+ io_service_.get().post([self, _buffers{std::move(buffers)}]() mutable {
+ if (auto ptr = self.lock()) {
+ ptr->receive_callback_(ptr.get(), _buffers,
+ make_error_code(core_error::success));
+ }
+ });
+ }
+
+ void reconnect() override {
+ state_ = State::CONNECTED;
+ std::weak_ptr<LocalConnector> self = shared_from_this();
+ io_service_.get().post([self]() {
+ if (auto ptr = self.lock()) {
+ ptr->on_reconnect_callback_(ptr.get(),
+ make_error_code(core_error::success));
+ }
+ });
+ }
+
+ void close() override {
+ std::weak_ptr<LocalConnector> self = shared_from_this();
+ io_service_.get().post([self]() mutable {
+ if (auto ptr = self.lock()) {
+ ptr->on_close_callback_(ptr.get());
+ }
+ });
+ }
private:
std::reference_wrapper<asio::io_service> io_service_;
diff --git a/libtransport/src/core/manifest.cc b/libtransport/src/core/manifest.cc
deleted file mode 100644
index da2689426..000000000
--- a/libtransport/src/core/manifest.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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 <hicn/transport/core/manifest.h>
-
-namespace transport {
-
-namespace core {
-
-std::string ManifestEncoding::manifest_type = std::string("manifest_type");
-
-std::map<ManifestType, std::string> ManifestEncoding::manifest_types = {
- {FINAL_CHUNK_NUMBER, "FinalChunkNumber"}, {NAME_LIST, "NameList"}};
-
-std::string ManifestEncoding::final_chunk_number =
- std::string("final_chunk_number");
-std::string ManifestEncoding::content_name = std::string("content_name");
-
-} // end namespace core
-
-} // end namespace transport \ No newline at end of file
diff --git a/libtransport/src/core/manifest.h b/libtransport/src/core/manifest.h
index 5bdbfc6ff..40832bb6b 100644
--- a/libtransport/src/core/manifest.h
+++ b/libtransport/src/core/manifest.h
@@ -17,165 +17,72 @@
#include <core/manifest_format.h>
#include <glog/logging.h>
-#include <hicn/transport/core/content_object.h>
-#include <hicn/transport/core/name.h>
-
-#include <set>
+#include <hicn/transport/auth/verifier.h>
+#include <hicn/transport/core/global_object_pool.h>
+#include <hicn/transport/core/packet.h>
namespace transport {
-
namespace core {
-using typename core::Name;
-using typename core::Packet;
-using typename core::PayloadType;
-
-template <typename Base, typename FormatTraits, typename ManifestImpl>
-class Manifest : public Base {
- static_assert(std::is_base_of<Packet, Base>::value,
- "Base must inherit from packet!");
-
+template <typename FormatTraits>
+class Manifest : public FormatTraits::Encoder, public FormatTraits::Decoder {
public:
- // core::ContentObjectManifest::Ptr
+ using Ptr = std::shared_ptr<Manifest>;
using Encoder = typename FormatTraits::Encoder;
using Decoder = typename FormatTraits::Decoder;
- Manifest(Packet::Format format, std::size_t signature_size = 0)
- : Base(format, signature_size),
- encoder_(*this, signature_size),
- decoder_(*this) {
- DCHECK(_is_ah(format));
- Base::setPayloadType(PayloadType::MANIFEST);
- }
+ 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>>;
- Manifest(Packet::Format format, const core::Name &name,
- std::size_t signature_size = 0)
- : Base(name, format, signature_size),
- encoder_(*this, signature_size),
- decoder_(*this) {
- DCHECK(_is_ah(format));
- Base::setPayloadType(PayloadType::MANIFEST);
+ Manifest(Packet::Ptr packet, bool clear = false)
+ : Encoder(packet, clear), Decoder(packet), packet_(packet) {
+ packet->setPayloadType(PayloadType::MANIFEST);
}
- template <typename T>
- Manifest(T &&base)
- : Base(std::forward<T &&>(base)),
- encoder_(*this, 0, false),
- decoder_(*this) {
- Base::setPayloadType(PayloadType::MANIFEST);
- }
-
- // Useful for decoding manifests while avoiding packet copy
- template <typename T>
- Manifest(T &base)
- : Base(base.getFormat()), encoder_(base, 0, false), decoder_(base) {}
-
virtual ~Manifest() = default;
- std::size_t estimateManifestSize(std::size_t additional_entries = 0) {
- return static_cast<ManifestImpl &>(*this).estimateManifestSizeImpl(
- additional_entries);
- }
-
- /*
- * After the call to encode, users MUST call clear before adding data
- * to the manifest.
- */
- Manifest &encode() { return static_cast<ManifestImpl &>(*this).encodeImpl(); }
-
- Manifest &decode() {
- Manifest::decoder_.decode();
-
- manifest_type_ = decoder_.getType();
- manifest_transport_type_ = decoder_.getTransportType();
- hash_algorithm_ = decoder_.getHashAlgorithm();
- is_last_ = decoder_.getIsLast();
+ Packet::Ptr getPacket() const { return packet_; }
- return static_cast<ManifestImpl &>(*this).decodeImpl();
+ void setHeaders(ManifestType type, uint8_t max_capacity, HashType hash_algo,
+ bool is_last, const Name &base_name) {
+ Encoder::setType(type);
+ Encoder::setMaxCapacity(max_capacity);
+ Encoder::setHashAlgorithm(hash_algo);
+ Encoder::setIsLast(is_last);
+ Encoder::setBaseName(base_name);
}
- static std::size_t manifestHeaderSize(
- interface::ProductionProtocolAlgorithms transport_type =
- interface::ProductionProtocolAlgorithms::UNKNOWN) {
- return Encoder::manifestHeaderSize(transport_type);
- }
+ auth::Verifier::SuffixMap getSuffixMap() const {
+ auth::Verifier::SuffixMap suffix_map;
- static std::size_t manifestEntrySize() {
- return Encoder::manifestEntrySize();
- }
+ HashType hash_algo = Decoder::getHashAlgorithm();
+ SuffixList suffix_list = Decoder::getEntries();
- Manifest &setType(ManifestType type) {
- manifest_type_ = type;
- encoder_.setType(manifest_type_);
- return *this;
- }
+ for (auto it = suffix_list.begin(); it != suffix_list.end(); ++it) {
+ Hash hash(it->second, Hash::getSize(hash_algo), hash_algo);
+ suffix_map[it->first] = hash;
+ }
- Manifest &setHashAlgorithm(auth::CryptoHashType hash_algorithm) {
- hash_algorithm_ = hash_algorithm;
- encoder_.setHashAlgorithm(hash_algorithm_);
- return *this;
+ return suffix_map;
}
- auth::CryptoHashType getHashAlgorithm() const { return hash_algorithm_; }
-
- ManifestType getType() const { return manifest_type_; }
-
- interface::ProductionProtocolAlgorithms getTransportType() const {
- return manifest_transport_type_;
- }
-
- bool getIsLast() const { return is_last_; }
-
- Manifest &setVersion(ManifestVersion version) {
- encoder_.setVersion(version);
- return *this;
- }
-
- Manifest &setParamsBytestream(const ParamsBytestream &params) {
- manifest_transport_type_ =
- interface::ProductionProtocolAlgorithms::BYTE_STREAM;
- encoder_.setParamsBytestream(params);
- return *this;
- }
-
- Manifest &setParamsRTC(const ParamsRTC &params) {
- manifest_transport_type_ =
- interface::ProductionProtocolAlgorithms::RTC_PROD;
- encoder_.setParamsRTC(params);
- return *this;
- }
-
- ParamsBytestream getParamsBytestream() const {
- return decoder_.getParamsBytestream();
- }
-
- ParamsRTC getParamsRTC() const { return decoder_.getParamsRTC(); }
-
- ManifestVersion getVersion() const { return decoder_.getVersion(); }
-
- Manifest &setIsLast(bool is_last) {
- encoder_.setIsLast(is_last);
- is_last_ = is_last;
- return *this;
- }
-
- Manifest &clear() {
- encoder_.clear();
- decoder_.clear();
- return *this;
- }
+ static Manifest::Ptr createContentManifest(Packet::Format format,
+ const core::Name &manifest_name,
+ std::size_t signature_size) {
+ ContentObject::Ptr content_object =
+ core::PacketManager<>::getInstance().getPacket<ContentObject>(
+ format, signature_size);
+ content_object->setName(manifest_name);
+ return std::make_shared<Manifest>(content_object, true);
+ };
protected:
- ManifestType manifest_type_;
- interface::ProductionProtocolAlgorithms manifest_transport_type_;
- auth::CryptoHashType hash_algorithm_;
- bool is_last_;
-
- Encoder encoder_;
- Decoder decoder_;
+ Packet::Ptr packet_;
};
} // end namespace core
-
} // end namespace transport
diff --git a/libtransport/src/core/manifest_format.h b/libtransport/src/core/manifest_format.h
index caee210cd..89412316a 100644
--- a/libtransport/src/core/manifest_format.h
+++ b/libtransport/src/core/manifest_format.h
@@ -25,13 +25,8 @@
#include <unordered_map>
namespace transport {
-
namespace core {
-enum class ManifestVersion : uint8_t {
- VERSION_1 = 1,
-};
-
enum class ManifestType : uint8_t {
INLINE_MANIFEST = 1,
FINAL_CHUNK_NUMBER = 2,
@@ -83,14 +78,27 @@ class ManifestEncoder {
return static_cast<Implementation &>(*this).clearImpl();
}
+ bool isEncoded() const {
+ return static_cast<const Implementation &>(*this).isEncodedImpl();
+ }
+
ManifestEncoder &setType(ManifestType type) {
return static_cast<Implementation &>(*this).setTypeImpl(type);
}
+ ManifestEncoder &setMaxCapacity(uint8_t max_capacity) {
+ return static_cast<Implementation &>(*this).setMaxCapacityImpl(
+ max_capacity);
+ }
+
ManifestEncoder &setHashAlgorithm(auth::CryptoHashType hash) {
return static_cast<Implementation &>(*this).setHashAlgorithmImpl(hash);
}
+ ManifestEncoder &setIsLast(bool is_last) {
+ return static_cast<Implementation &>(*this).setIsLastImpl(is_last);
+ }
+
template <
typename T,
typename = std::enable_if_t<std::is_same<
@@ -99,45 +107,36 @@ class ManifestEncoder {
return static_cast<Implementation &>(*this).setBaseNameImpl(name);
}
- template <typename Hash>
- ManifestEncoder &addSuffixAndHash(uint32_t suffix, Hash &&hash) {
- return static_cast<Implementation &>(*this).addSuffixAndHashImpl(
- suffix, std::forward<Hash &&>(hash));
+ ManifestEncoder &setParamsBytestream(const ParamsBytestream &params) {
+ return static_cast<Implementation &>(*this).setParamsBytestreamImpl(params);
}
- ManifestEncoder &setIsLast(bool is_last) {
- return static_cast<Implementation &>(*this).setIsLastImpl(is_last);
+ ManifestEncoder &setParamsRTC(const ParamsRTC &params) {
+ return static_cast<Implementation &>(*this).setParamsRTCImpl(params);
}
- ManifestEncoder &setVersion(ManifestVersion version) {
- return static_cast<Implementation &>(*this).setVersionImpl(version);
+ template <typename Hash>
+ ManifestEncoder &addEntry(uint32_t suffix, Hash &&hash) {
+ return static_cast<Implementation &>(*this).addEntryImpl(
+ suffix, std::forward<Hash>(hash));
}
- std::size_t estimateSerializedLength(std::size_t number_of_entries) {
- return static_cast<Implementation &>(*this).estimateSerializedLengthImpl(
- number_of_entries);
+ ManifestEncoder &removeEntry(uint32_t suffix) {
+ return static_cast<Implementation &>(*this).removeEntryImpl(suffix);
}
- ManifestEncoder &update() {
- return static_cast<Implementation &>(*this).updateImpl();
+ std::size_t manifestHeaderSize() const {
+ return static_cast<const Implementation &>(*this).manifestHeaderSizeImpl();
}
- ManifestEncoder &setParamsBytestream(const ParamsBytestream &params) {
- return static_cast<Implementation &>(*this).setParamsBytestreamImpl(params);
+ std::size_t manifestPayloadSize(size_t additional_entries = 0) const {
+ return static_cast<const Implementation &>(*this).manifestPayloadSizeImpl(
+ additional_entries);
}
- ManifestEncoder &setParamsRTC(const ParamsRTC &params) {
- return static_cast<Implementation &>(*this).setParamsRTCImpl(params);
- }
-
- static std::size_t manifestHeaderSize(
- interface::ProductionProtocolAlgorithms transport_type =
- interface::ProductionProtocolAlgorithms::UNKNOWN) {
- return Implementation::manifestHeaderSizeImpl(transport_type);
- }
-
- static std::size_t manifestEntrySize() {
- return Implementation::manifestEntrySizeImpl();
+ std::size_t manifestSize(size_t additional_entries = 0) const {
+ return static_cast<const Implementation &>(*this).manifestSizeImpl(
+ additional_entries);
}
};
@@ -146,11 +145,17 @@ class ManifestDecoder {
public:
virtual ~ManifestDecoder() = default;
+ ManifestDecoder &decode() {
+ return static_cast<Implementation &>(*this).decodeImpl();
+ }
+
ManifestDecoder &clear() {
return static_cast<Implementation &>(*this).clearImpl();
}
- void decode() { static_cast<Implementation &>(*this).decodeImpl(); }
+ bool isDecoded() const {
+ return static_cast<const Implementation &>(*this).isDecodedImpl();
+ }
ManifestType getType() const {
return static_cast<const Implementation &>(*this).getTypeImpl();
@@ -160,40 +165,48 @@ class ManifestDecoder {
return static_cast<const Implementation &>(*this).getTransportTypeImpl();
}
+ uint8_t getMaxCapacity() const {
+ return static_cast<const Implementation &>(*this).getMaxCapacityImpl();
+ }
+
auth::CryptoHashType getHashAlgorithm() const {
return static_cast<const Implementation &>(*this).getHashAlgorithmImpl();
}
+ bool getIsLast() const {
+ return static_cast<const Implementation &>(*this).getIsLastImpl();
+ }
+
core::Name getBaseName() const {
return static_cast<const Implementation &>(*this).getBaseNameImpl();
}
- auto getSuffixHashList() {
- return static_cast<Implementation &>(*this).getSuffixHashListImpl();
+ ParamsBytestream getParamsBytestream() const {
+ return static_cast<const Implementation &>(*this).getParamsBytestreamImpl();
}
- bool getIsLast() const {
- return static_cast<const Implementation &>(*this).getIsLastImpl();
+ ParamsRTC getParamsRTC() const {
+ return static_cast<const Implementation &>(*this).getParamsRTCImpl();
}
- ManifestVersion getVersion() const {
- return static_cast<const Implementation &>(*this).getVersionImpl();
+ auto getEntries() const {
+ return static_cast<const Implementation &>(*this).getEntriesImpl();
}
- std::size_t estimateSerializedLength(std::size_t number_of_entries) const {
- return static_cast<const Implementation &>(*this)
- .estimateSerializedLengthImpl(number_of_entries);
+ std::size_t manifestHeaderSize() const {
+ return static_cast<const Implementation &>(*this).manifestHeaderSizeImpl();
}
- ParamsBytestream getParamsBytestream() const {
- return static_cast<const Implementation &>(*this).getParamsBytestreamImpl();
+ std::size_t manifestPayloadSize(size_t additional_entries = 0) const {
+ return static_cast<const Implementation &>(*this).manifestPayloadSizeImpl(
+ additional_entries);
}
- ParamsRTC getParamsRTC() const {
- return static_cast<const Implementation &>(*this).getParamsRTCImpl();
+ std::size_t manifestSize(size_t additional_entries = 0) const {
+ return static_cast<const Implementation &>(*this).manifestSizeImpl(
+ additional_entries);
}
};
} // namespace core
-
} // namespace transport
diff --git a/libtransport/src/core/manifest_format_fixed.cc b/libtransport/src/core/manifest_format_fixed.cc
index 428d6ad12..668169642 100644
--- a/libtransport/src/core/manifest_format_fixed.cc
+++ b/libtransport/src/core/manifest_format_fixed.cc
@@ -18,22 +18,42 @@
#include <hicn/transport/utils/literals.h>
namespace transport {
-
namespace core {
-// TODO use preallocated pool of membufs
-FixedManifestEncoder::FixedManifestEncoder(Packet &packet,
- std::size_t signature_size,
- bool clear)
+// ---------------------------------------------------------
+// FixedManifest
+// ---------------------------------------------------------
+size_t FixedManifest::manifestHeaderSize(
+ interface::ProductionProtocolAlgorithms transport_type) {
+ uint32_t params_size = 0;
+
+ switch (transport_type) {
+ case interface::ProductionProtocolAlgorithms::BYTE_STREAM:
+ params_size = MANIFEST_PARAMS_BYTESTREAM_SIZE;
+ break;
+ case interface::ProductionProtocolAlgorithms::RTC_PROD:
+ params_size = MANIFEST_PARAMS_RTC_SIZE;
+ break;
+ default:
+ break;
+ }
+
+ return MANIFEST_META_SIZE + MANIFEST_ENTRY_META_SIZE + params_size;
+}
+
+size_t FixedManifest::manifestPayloadSize(size_t nb_entries) {
+ return nb_entries * MANIFEST_ENTRY_SIZE;
+}
+
+// ---------------------------------------------------------
+// FixedManifestEncoder
+// ---------------------------------------------------------
+FixedManifestEncoder::FixedManifestEncoder(Packet::Ptr packet, bool clear)
: packet_(packet),
- max_size_(Packet::default_mtu - packet_.headerSize()),
- signature_size_(signature_size),
transport_type_(interface::ProductionProtocolAlgorithms::UNKNOWN),
- encoded_(false),
- params_bytestream_({0}),
- params_rtc_({0}) {
- manifest_meta_ = reinterpret_cast<ManifestMeta *>(packet_.writableData() +
- packet_.headerSize());
+ encoded_(false) {
+ manifest_meta_ = reinterpret_cast<ManifestMeta *>(packet_->writableData() +
+ packet_->headerSize());
manifest_entry_meta_ =
reinterpret_cast<ManifestEntryMeta *>(manifest_meta_ + 1);
@@ -50,32 +70,34 @@ FixedManifestEncoder &FixedManifestEncoder::encodeImpl() {
return *this;
}
+ // Copy manifest header
manifest_meta_->transport_type = static_cast<uint8_t>(transport_type_);
manifest_entry_meta_->nb_entries = manifest_entries_.size();
- packet_.append(FixedManifestEncoder::manifestHeaderSizeImpl());
- packet_.updateLength();
+ packet_->append(manifestHeaderSizeImpl());
+ packet_->updateLength();
+ auto params = reinterpret_cast<uint8_t *>(manifest_entry_meta_ + 1);
switch (transport_type_) {
- case interface::ProductionProtocolAlgorithms::BYTE_STREAM:
- packet_.appendPayload(
- reinterpret_cast<const uint8_t *>(&params_bytestream_),
- MANIFEST_PARAMS_BYTESTREAM_SIZE);
+ case interface::ProductionProtocolAlgorithms::BYTE_STREAM: {
+ auto bytestream = reinterpret_cast<const uint8_t *>(&params_bytestream_);
+ std::memcpy(params, bytestream, MANIFEST_PARAMS_BYTESTREAM_SIZE);
break;
- case interface::ProductionProtocolAlgorithms::RTC_PROD:
- packet_.appendPayload(reinterpret_cast<const uint8_t *>(&params_rtc_),
- MANIFEST_PARAMS_RTC_SIZE);
+ }
+ case interface::ProductionProtocolAlgorithms::RTC_PROD: {
+ auto rtc = reinterpret_cast<const uint8_t *>(&params_rtc_);
+ std::memcpy(params, rtc, MANIFEST_PARAMS_RTC_SIZE);
break;
+ }
default:
break;
}
- packet_.appendPayload(
- reinterpret_cast<const uint8_t *>(manifest_entries_.data()),
- manifest_entries_.size() * FixedManifestEncoder::manifestEntrySizeImpl());
+ // Copy manifest entries
+ auto payload = reinterpret_cast<const uint8_t *>(manifest_entries_.data());
+ packet_->appendPayload(payload, manifestPayloadSizeImpl());
- if (TRANSPORT_EXPECT_FALSE(packet_.payloadSize() <
- estimateSerializedLengthImpl())) {
+ if (TRANSPORT_EXPECT_FALSE(packet_->payloadSize() < manifestSizeImpl())) {
throw errors::RuntimeException("Error encoding the manifest");
}
@@ -85,32 +107,21 @@ FixedManifestEncoder &FixedManifestEncoder::encodeImpl() {
FixedManifestEncoder &FixedManifestEncoder::clearImpl() {
if (encoded_) {
- packet_.trimEnd(FixedManifestEncoder::manifestHeaderSizeImpl() +
- manifest_entries_.size() *
- FixedManifestEncoder::manifestEntrySizeImpl());
+ packet_->trimEnd(manifestSizeImpl());
}
transport_type_ = interface::ProductionProtocolAlgorithms::UNKNOWN;
encoded_ = false;
- params_bytestream_ = {0};
- params_rtc_ = {0};
*manifest_meta_ = {0};
*manifest_entry_meta_ = {0};
+ params_bytestream_ = {0};
+ params_rtc_ = {0};
manifest_entries_.clear();
return *this;
}
-FixedManifestEncoder &FixedManifestEncoder::updateImpl() {
- max_size_ = Packet::default_mtu - packet_.headerSize() - signature_size_;
- return *this;
-}
-
-FixedManifestEncoder &FixedManifestEncoder::setVersionImpl(
- ManifestVersion version) {
- manifest_meta_->version = static_cast<uint8_t>(version);
- return *this;
-}
+bool FixedManifestEncoder::isEncodedImpl() const { return encoded_; }
FixedManifestEncoder &FixedManifestEncoder::setTypeImpl(
ManifestType manifest_type) {
@@ -118,6 +129,12 @@ FixedManifestEncoder &FixedManifestEncoder::setTypeImpl(
return *this;
}
+FixedManifestEncoder &FixedManifestEncoder::setMaxCapacityImpl(
+ uint8_t max_capacity) {
+ manifest_meta_->max_capacity = max_capacity;
+ return *this;
+}
+
FixedManifestEncoder &FixedManifestEncoder::setHashAlgorithmImpl(
auth::CryptoHashType algorithm) {
manifest_meta_->hash_algorithm = static_cast<uint8_t>(algorithm);
@@ -159,61 +176,68 @@ FixedManifestEncoder &FixedManifestEncoder::setParamsRTCImpl(
return *this;
}
-FixedManifestEncoder &FixedManifestEncoder::addSuffixAndHashImpl(
+FixedManifestEncoder &FixedManifestEncoder::addEntryImpl(
uint32_t suffix, const auth::CryptoHash &hash) {
- manifest_entries_.push_back(ManifestEntry{
- .suffix = htonl(suffix),
+ ManifestEntry last_entry = {
+ .suffix = portability::host_to_net(suffix),
.hash = {0},
- });
+ };
- std::memcpy(reinterpret_cast<uint8_t *>(manifest_entries_.back().hash),
- hash.getDigest()->data(), hash.getSize());
-
- if (TRANSPORT_EXPECT_FALSE(estimateSerializedLengthImpl() > max_size_)) {
- throw errors::RuntimeException("Manifest size exceeded the packet MTU!");
- }
+ auto last_hash = reinterpret_cast<uint8_t *>(last_entry.hash);
+ std::memcpy(last_hash, hash.getDigest()->data(), hash.getSize());
+ manifest_entries_.push_back(last_entry);
return *this;
}
-std::size_t FixedManifestEncoder::estimateSerializedLengthImpl(
- std::size_t additional_entries) {
- return FixedManifestEncoder::manifestHeaderSizeImpl(transport_type_) +
- (manifest_entries_.size() + additional_entries) *
- FixedManifestEncoder::manifestEntrySizeImpl();
+FixedManifestEncoder &FixedManifestEncoder::removeEntryImpl(uint32_t suffix) {
+ for (auto it = manifest_entries_.begin(); it != manifest_entries_.end();) {
+ if (it->suffix == suffix)
+ it = manifest_entries_.erase(it);
+ else
+ ++it;
+ }
+ return *this;
}
-std::size_t FixedManifestEncoder::manifestHeaderSizeImpl(
- interface::ProductionProtocolAlgorithms transport_type) {
- uint32_t params_size = 0;
-
- switch (transport_type) {
- case interface::ProductionProtocolAlgorithms::BYTE_STREAM:
- params_size = MANIFEST_PARAMS_BYTESTREAM_SIZE;
- break;
- case interface::ProductionProtocolAlgorithms::RTC_PROD:
- params_size = MANIFEST_PARAMS_RTC_SIZE;
- break;
- default:
- break;
- }
+size_t FixedManifestEncoder::manifestHeaderSizeImpl() const {
+ return FixedManifest::manifestHeaderSize(transport_type_);
+}
- return MANIFEST_META_SIZE + MANIFEST_ENTRY_META_SIZE + params_size;
+size_t FixedManifestEncoder::manifestPayloadSizeImpl(
+ size_t additional_entries) const {
+ return FixedManifest::manifestPayloadSize(manifest_entries_.size() +
+ additional_entries);
}
-std::size_t FixedManifestEncoder::manifestEntrySizeImpl() {
- return MANIFEST_ENTRY_SIZE;
+size_t FixedManifestEncoder::manifestSizeImpl(size_t additional_entries) const {
+ return manifestHeaderSizeImpl() + manifestPayloadSizeImpl(additional_entries);
}
-FixedManifestDecoder::FixedManifestDecoder(Packet &packet)
+// ---------------------------------------------------------
+// FixedManifestDecoder
+// ---------------------------------------------------------
+FixedManifestDecoder::FixedManifestDecoder(Packet::Ptr packet)
: packet_(packet), decoded_(false) {
manifest_meta_ =
- reinterpret_cast<ManifestMeta *>(packet_.getPayload()->writableData());
+ reinterpret_cast<ManifestMeta *>(packet_->getPayload()->writableData());
manifest_entry_meta_ =
reinterpret_cast<ManifestEntryMeta *>(manifest_meta_ + 1);
- transport_type_ = getTransportTypeImpl();
+}
- switch (transport_type_) {
+FixedManifestDecoder::~FixedManifestDecoder() {}
+
+FixedManifestDecoder &FixedManifestDecoder::decodeImpl() {
+ if (decoded_) {
+ return *this;
+ }
+
+ if (packet_->payloadSize() < manifestSizeImpl()) {
+ throw errors::RuntimeException(
+ "The packet payload size does not match expected manifest size");
+ }
+
+ switch (getTransportTypeImpl()) {
case interface::ProductionProtocolAlgorithms::BYTE_STREAM:
params_bytestream_ = reinterpret_cast<TransportParamsBytestream *>(
manifest_entry_meta_ + 1);
@@ -230,25 +254,9 @@ FixedManifestDecoder::FixedManifestDecoder(Packet &packet)
reinterpret_cast<ManifestEntry *>(manifest_entry_meta_ + 1);
break;
}
-}
-
-FixedManifestDecoder::~FixedManifestDecoder() {}
-
-void FixedManifestDecoder::decodeImpl() {
- if (decoded_) {
- return;
- }
-
- std::size_t packet_size = packet_.payloadSize();
-
- if (packet_size <
- FixedManifestEncoder::manifestHeaderSizeImpl(transport_type_) ||
- packet_size < estimateSerializedLengthImpl()) {
- throw errors::RuntimeException(
- "The packet does not match expected manifest size.");
- }
decoded_ = true;
+ return *this;
}
FixedManifestDecoder &FixedManifestDecoder::clearImpl() {
@@ -256,20 +264,22 @@ FixedManifestDecoder &FixedManifestDecoder::clearImpl() {
return *this;
}
+bool FixedManifestDecoder::isDecodedImpl() const { return decoded_; }
+
ManifestType FixedManifestDecoder::getTypeImpl() const {
return static_cast<ManifestType>(manifest_meta_->type);
}
-ManifestVersion FixedManifestDecoder::getVersionImpl() const {
- return static_cast<ManifestVersion>(manifest_meta_->version);
-}
-
interface::ProductionProtocolAlgorithms
FixedManifestDecoder::getTransportTypeImpl() const {
return static_cast<interface::ProductionProtocolAlgorithms>(
manifest_meta_->transport_type);
}
+uint8_t FixedManifestDecoder::getMaxCapacityImpl() const {
+ return manifest_meta_->max_capacity;
+}
+
auth::CryptoHashType FixedManifestDecoder::getHashAlgorithmImpl() const {
return static_cast<auth::CryptoHashType>(manifest_meta_->hash_algorithm);
}
@@ -303,26 +313,34 @@ ParamsRTC FixedManifestDecoder::getParamsRTCImpl() const {
};
}
-typename Fixed::SuffixList FixedManifestDecoder::getSuffixHashListImpl() {
+typename Fixed::SuffixList FixedManifestDecoder::getEntriesImpl() const {
typename Fixed::SuffixList hash_list;
for (int i = 0; i < manifest_entry_meta_->nb_entries; i++) {
- hash_list.insert(hash_list.end(),
- std::make_pair(ntohl(manifest_entries_[i].suffix),
- reinterpret_cast<uint8_t *>(
- &manifest_entries_[i].hash[0])));
+ hash_list.insert(
+ hash_list.end(),
+ std::make_pair(
+ portability::net_to_host(manifest_entries_[i].suffix),
+ reinterpret_cast<uint8_t *>(&manifest_entries_[i].hash[0])));
}
return hash_list;
}
-std::size_t FixedManifestDecoder::estimateSerializedLengthImpl(
- std::size_t additional_entries) const {
- return FixedManifestEncoder::manifestHeaderSizeImpl(transport_type_) +
- (manifest_entry_meta_->nb_entries + additional_entries) *
- FixedManifestEncoder::manifestEntrySizeImpl();
+size_t FixedManifestDecoder::manifestHeaderSizeImpl() const {
+ interface::ProductionProtocolAlgorithms type = getTransportTypeImpl();
+ return FixedManifest::manifestHeaderSize(type);
}
-} // end namespace core
+size_t FixedManifestDecoder::manifestPayloadSizeImpl(
+ size_t additional_entries) const {
+ size_t nb_entries = manifest_entry_meta_->nb_entries + additional_entries;
+ return FixedManifest::manifestPayloadSize(nb_entries);
+}
+size_t FixedManifestDecoder::manifestSizeImpl(size_t additional_entries) const {
+ return manifestHeaderSizeImpl() + manifestPayloadSizeImpl(additional_entries);
+}
+
+} // end namespace core
} // end namespace transport
diff --git a/libtransport/src/core/manifest_format_fixed.h b/libtransport/src/core/manifest_format_fixed.h
index 5fd2a673d..7ab371974 100644
--- a/libtransport/src/core/manifest_format_fixed.h
+++ b/libtransport/src/core/manifest_format_fixed.h
@@ -28,7 +28,7 @@ namespace core {
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// |Version| Type | Transport Type| Hash Algorithm|L| Reserved |
+// | Type | TTYpe | Max Capacity | Hash Algo |L| Reserved |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// Manifest Entry Metadata:
@@ -106,9 +106,9 @@ struct Fixed {
const size_t MANIFEST_META_SIZE = 4;
struct __attribute__((__packed__)) ManifestMeta {
- std::uint8_t version : 4;
std::uint8_t type : 4;
- std::uint8_t transport_type;
+ std::uint8_t transport_type : 4;
+ std::uint8_t max_capacity;
std::uint8_t hash_algorithm;
std::uint8_t is_last;
};
@@ -146,22 +146,26 @@ struct __attribute__((__packed__)) ManifestEntry {
};
static_assert(sizeof(ManifestEntry) == MANIFEST_ENTRY_SIZE);
-static const constexpr std::uint8_t manifest_version = 1;
+class FixedManifest {
+ public:
+ static size_t manifestHeaderSize(
+ interface::ProductionProtocolAlgorithms transport_type);
+ static size_t manifestPayloadSize(size_t nb_entries);
+};
class FixedManifestEncoder : public ManifestEncoder<FixedManifestEncoder> {
public:
- FixedManifestEncoder(Packet &packet, std::size_t signature_size = 0,
- bool clear = true);
+ FixedManifestEncoder(Packet::Ptr packet, bool clear = false);
~FixedManifestEncoder();
FixedManifestEncoder &encodeImpl();
FixedManifestEncoder &clearImpl();
- FixedManifestEncoder &updateImpl();
+ bool isEncodedImpl() const;
// ManifestMeta
- FixedManifestEncoder &setVersionImpl(ManifestVersion version);
FixedManifestEncoder &setTypeImpl(ManifestType manifest_type);
+ FixedManifestEncoder &setMaxCapacityImpl(uint8_t max_capacity);
FixedManifestEncoder &setHashAlgorithmImpl(Fixed::HashType algorithm);
FixedManifestEncoder &setIsLastImpl(bool is_last);
@@ -173,20 +177,15 @@ class FixedManifestEncoder : public ManifestEncoder<FixedManifestEncoder> {
FixedManifestEncoder &setParamsRTCImpl(const ParamsRTC &params);
// ManifestEntry
- FixedManifestEncoder &addSuffixAndHashImpl(uint32_t suffix,
- const Fixed::Hash &hash);
+ FixedManifestEncoder &addEntryImpl(uint32_t suffix, const Fixed::Hash &hash);
+ FixedManifestEncoder &removeEntryImpl(uint32_t suffix);
- std::size_t estimateSerializedLengthImpl(std::size_t additional_entries = 0);
-
- static std::size_t manifestHeaderSizeImpl(
- interface::ProductionProtocolAlgorithms transport_type =
- interface::ProductionProtocolAlgorithms::UNKNOWN);
- static std::size_t manifestEntrySizeImpl();
+ size_t manifestHeaderSizeImpl() const;
+ size_t manifestPayloadSizeImpl(size_t additional_entries = 0) const;
+ size_t manifestSizeImpl(size_t additional_entries = 0) const;
private:
- Packet &packet_;
- std::size_t max_size_;
- std::size_t signature_size_;
+ Packet::Ptr packet_;
interface::ProductionProtocolAlgorithms transport_type_;
bool encoded_;
@@ -202,17 +201,18 @@ class FixedManifestEncoder : public ManifestEncoder<FixedManifestEncoder> {
class FixedManifestDecoder : public ManifestDecoder<FixedManifestDecoder> {
public:
- FixedManifestDecoder(Packet &packet);
+ FixedManifestDecoder(Packet::Ptr packet);
~FixedManifestDecoder();
- void decodeImpl();
+ FixedManifestDecoder &decodeImpl();
FixedManifestDecoder &clearImpl();
+ bool isDecodedImpl() const;
// ManifestMeta
- ManifestVersion getVersionImpl() const;
ManifestType getTypeImpl() const;
interface::ProductionProtocolAlgorithms getTransportTypeImpl() const;
+ uint8_t getMaxCapacityImpl() const;
Fixed::HashType getHashAlgorithmImpl() const;
bool getIsLastImpl() const;
@@ -224,14 +224,14 @@ class FixedManifestDecoder : public ManifestDecoder<FixedManifestDecoder> {
ParamsRTC getParamsRTCImpl() const;
// ManifestEntry
- typename Fixed::SuffixList getSuffixHashListImpl();
+ typename Fixed::SuffixList getEntriesImpl() const;
- std::size_t estimateSerializedLengthImpl(
- std::size_t additional_entries = 0) const;
+ size_t manifestHeaderSizeImpl() const;
+ size_t manifestPayloadSizeImpl(size_t additional_entries = 0) const;
+ size_t manifestSizeImpl(size_t additional_entries = 0) const;
private:
- Packet &packet_;
- interface::ProductionProtocolAlgorithms transport_type_;
+ Packet::Ptr packet_;
bool decoded_;
// Manifest Header
diff --git a/libtransport/src/core/manifest_inline.h b/libtransport/src/core/manifest_inline.h
deleted file mode 100644
index ca48a4a79..000000000
--- a/libtransport/src/core/manifest_inline.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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 <core/manifest.h>
-#include <core/manifest_format.h>
-#include <hicn/transport/portability/portability.h>
-
-#include <set>
-
-namespace transport {
-
-namespace core {
-
-template <typename Base, typename FormatTraits>
-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() {}
-
- ManifestInline(Packet::Format format, const core::Name &name,
- std::size_t signature_size = 0)
- : ManifestBase(format, name, signature_size) {}
-
- template <typename T>
- ManifestInline(T &&base) : ManifestBase(std::forward<T &&>(base)) {}
-
- template <typename T>
- ManifestInline(T &base) : ManifestBase(base) {}
-
- static TRANSPORT_ALWAYS_INLINE ManifestInline *createManifest(
- Packet::Format format, const core::Name &manifest_name,
- ManifestVersion version, ManifestType type, bool is_last,
- const Name &base_name, HashType hash_algo, std::size_t signature_size) {
- auto manifest = new ManifestInline(format, manifest_name, signature_size);
- manifest->setVersion(version);
- manifest->setType(type);
- manifest->setHashAlgorithm(hash_algo);
- manifest->setIsLast(is_last);
- manifest->setBaseName(base_name);
- return manifest;
- }
-
- ManifestInline &encodeImpl() {
- ManifestBase::encoder_.encode();
- return *this;
- }
-
- ManifestInline &decodeImpl() {
- base_name_ = ManifestBase::decoder_.getBaseName();
- suffix_hash_map_ = ManifestBase::decoder_.getSuffixHashList();
-
- return *this;
- }
-
- std::size_t estimateManifestSizeImpl(std::size_t additional_entries = 0) {
- return ManifestBase::encoder_.estimateSerializedLength(additional_entries);
- }
-
- ManifestInline &setBaseName(const Name &name) {
- base_name_ = name;
- ManifestBase::encoder_.setBaseName(base_name_);
- return *this;
- }
-
- const Name &getBaseName() { return base_name_; }
-
- ManifestInline &addSuffixHash(Suffix suffix, const Hash &hash) {
- ManifestBase::encoder_.addSuffixAndHash(suffix, hash);
- return *this;
- }
-
- // Call this function only after the decode function!
- const SuffixList &getSuffixList() { return suffix_hash_map_; }
-
- // Convert several manifests into a single map from suffixes to packet hashes.
- // All manifests must have been decoded beforehand.
- static std::unordered_map<Suffix, Hash> getSuffixMap(
- const std::vector<ManifestInline *> &manifests) {
- std::unordered_map<Suffix, Hash> suffix_map;
-
- for (auto manifest_ptr : manifests) {
- HashType hash_type = manifest_ptr->getHashAlgorithm();
- SuffixList suffix_list = manifest_ptr->getSuffixList();
-
- for (auto it = suffix_list.begin(); it != suffix_list.end(); ++it) {
- Hash hash(it->second, Hash::getSize(hash_type), hash_type);
- suffix_map[it->first] = hash;
- }
- }
-
- return suffix_map;
- }
-
- static std::unordered_map<Suffix, Hash> getSuffixMap(
- ManifestInline *manifest) {
- return getSuffixMap(std::vector<ManifestInline *>{manifest});
- }
-
- private:
- core::Name base_name_;
- SuffixList suffix_hash_map_;
-};
-
-} // namespace core
-} // namespace transport
diff --git a/libtransport/src/core/name.cc b/libtransport/src/core/name.cc
index 98091eea5..960947cb9 100644
--- a/libtransport/src/core/name.cc
+++ b/libtransport/src/core/name.cc
@@ -24,7 +24,7 @@ namespace transport {
namespace core {
-Name::Name() { name_ = {}; }
+Name::Name() { std::memset(&name_, 0, sizeof(name_)); }
/**
* XXX This function does not use the name API provided by libhicn
@@ -47,6 +47,7 @@ Name::Name(int family, const uint8_t *ip_address, std::uint32_t suffix)
std::memcpy(dst, ip_address, length);
name_.suffix = suffix;
}
+
Name::Name(const char *name, uint32_t segment) {
if (hicn_name_create(name, segment, &name_) < 0) {
throw errors::InvalidIpAddressException();
diff --git a/libtransport/src/core/pending_interest.h b/libtransport/src/core/pending_interest.h
index f8a4ba10e..fb10405d3 100644
--- a/libtransport/src/core/pending_interest.h
+++ b/libtransport/src/core/pending_interest.h
@@ -42,17 +42,9 @@ class PendingInterest {
public:
using Ptr = utils::ObjectPool<PendingInterest>::Ptr;
- // PendingInterest()
- // : interest_(nullptr, nullptr),
- // timer_(),
- // on_content_object_callback_(),
- // on_interest_timeout_callback_() {}
PendingInterest(asio::io_service &io_service, const Interest::Ptr &interest)
- : interest_(interest),
- timer_(io_service),
- on_content_object_callback_(),
- on_interest_timeout_callback_() {}
+ : interest_(interest), timer_(io_service) {}
PendingInterest(asio::io_service &io_service, const Interest::Ptr &interest,
OnContentObjectCallback &&on_content_object,
@@ -65,10 +57,9 @@ class PendingInterest {
~PendingInterest() = default;
template <typename Handler>
- TRANSPORT_ALWAYS_INLINE void startCountdown(Handler &&cb) {
- timer_.expires_from_now(
- std::chrono::milliseconds(interest_->getLifetime()));
- timer_.async_wait(std::forward<Handler &&>(cb));
+ TRANSPORT_ALWAYS_INLINE void startCountdown(uint32_t lifetime, Handler &&cb) {
+ timer_.expires_from_now(std::chrono::milliseconds(lifetime));
+ timer_.async_wait(std::forward<Handler>(cb));
}
TRANSPORT_ALWAYS_INLINE void cancelTimer() { timer_.cancel(); }
@@ -77,7 +68,7 @@ class PendingInterest {
return std::move(interest_);
}
- TRANSPORT_ALWAYS_INLINE void setInterest(Interest::Ptr &interest) {
+ TRANSPORT_ALWAYS_INLINE void setInterest(const Interest::Ptr &interest) {
interest_ = interest;
}
@@ -88,7 +79,7 @@ class PendingInterest {
TRANSPORT_ALWAYS_INLINE void setOnContentObjectCallback(
OnContentObjectCallback &&on_content_object) {
- PendingInterest::on_content_object_callback_ = on_content_object;
+ PendingInterest::on_content_object_callback_ = std::move(on_content_object);
}
TRANSPORT_ALWAYS_INLINE const OnInterestTimeoutCallback &
@@ -98,7 +89,8 @@ class PendingInterest {
TRANSPORT_ALWAYS_INLINE void setOnTimeoutCallback(
OnInterestTimeoutCallback &&on_interest_timeout) {
- PendingInterest::on_interest_timeout_callback_ = on_interest_timeout;
+ PendingInterest::on_interest_timeout_callback_ =
+ std::move(on_interest_timeout);
}
private:
diff --git a/libtransport/src/core/portal.cc b/libtransport/src/core/portal.cc
index d8e8d78ea..c06969f19 100644
--- a/libtransport/src/core/portal.cc
+++ b/libtransport/src/core/portal.cc
@@ -43,12 +43,14 @@ std::string Portal::io_module_path_ = defaultIoModule();
std::string Portal::defaultIoModule() {
using namespace std::placeholders;
GlobalConfiguration::getInstance().registerConfigurationParser(
- io_module_section,
+ IoModuleConfiguration::section,
std::bind(&Portal::parseIoModuleConfiguration, _1, _2));
GlobalConfiguration::getInstance().registerConfigurationGetter(
- io_module_section, std::bind(&Portal::getModuleConfiguration, _1, _2));
+ IoModuleConfiguration::section,
+ std::bind(&Portal::getModuleConfiguration, _1, _2));
GlobalConfiguration::getInstance().registerConfigurationSetter(
- io_module_section, std::bind(&Portal::setModuleConfiguration, _1, _2));
+ IoModuleConfiguration::section,
+ std::bind(&Portal::setModuleConfiguration, _1, _2));
// return default
conf_.name = default_module;
@@ -57,7 +59,7 @@ std::string Portal::defaultIoModule() {
void Portal::getModuleConfiguration(ConfigurationObject& object,
std::error_code& ec) {
- DCHECK(object.getKey() == io_module_section);
+ DCHECK(object.getKey() == IoModuleConfiguration::section);
auto conf = dynamic_cast<const IoModuleConfiguration&>(object);
conf = conf_;
@@ -103,7 +105,7 @@ std::string getIoModulePath(const std::string& name,
void Portal::setModuleConfiguration(const ConfigurationObject& object,
std::error_code& ec) {
- DCHECK(object.getKey() == io_module_section);
+ DCHECK(object.getKey() == IoModuleConfiguration::section);
const IoModuleConfiguration& conf =
dynamic_cast<const IoModuleConfiguration&>(object);
diff --git a/libtransport/src/core/portal.h b/libtransport/src/core/portal.h
index aae4c573e..6f3a48e83 100644
--- a/libtransport/src/core/portal.h
+++ b/libtransport/src/core/portal.h
@@ -32,6 +32,10 @@
#include <hicn/transport/utils/event_thread.h>
#include <hicn/transport/utils/fixed_block_allocator.h>
+extern "C" {
+#include <hicn/header.h>
+}
+
#include <future>
#include <memory>
#include <queue>
@@ -179,19 +183,11 @@ class Portal : public ::utils::NonCopyable,
Portal() : Portal(GlobalWorkers::getInstance().getWorker()) {}
Portal(::utils::EventThread &worker)
- : io_module_(nullptr, [](IoModule *module) { IoModule::unload(module); }),
+ : io_module_(nullptr),
worker_(worker),
app_name_("libtransport_application"),
transport_callback_(nullptr),
- 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();
- }
+ is_consumer_(false) {}
public:
using TransportCallback = interface::Portal::TransportCallback;
@@ -275,6 +271,7 @@ class Portal : public ::utils::NonCopyable,
ptr->transport_callback_->onError(ec);
}
},
+ [self]([[maybe_unused]] Connector *c) { /* Nothing to do here */ },
[self](Connector *c, const std::error_code &ec) {
auto ptr = self.lock();
if (ptr) {
@@ -315,76 +312,113 @@ class Portal : public ::utils::NonCopyable,
}
/**
- * Send an interest through to the local forwarder.
- *
- * @param interest - The pointer to the interest. The ownership of the
- * interest is transferred by the caller to portal.
- *
- * @param on_content_object_callback - If the caller wishes to use a
- * different callback to be called for this interest, it can set this
- * parameter. Otherwise ConsumerCallback::onContentObject will be used.
+ * @brief Add interest to PIT
*
- * @param on_interest_timeout_callback - If the caller wishes to use a
- * different callback to be called for this interest, it can set this
- * parameter. Otherwise ConsumerCallback::onTimeout will be used.
*/
- void sendInterest(
- Interest::Ptr &&interest,
+ void addInterestToPIT(
+ const Interest::Ptr &interest, uint32_t lifetime,
OnContentObjectCallback &&on_content_object_callback = UNSET_CALLBACK,
OnInterestTimeoutCallback &&on_interest_timeout_callback =
UNSET_CALLBACK) {
- DCHECK(std::this_thread::get_id() == worker_.getThreadId());
-
- // Send it
- interest->encodeSuffixes();
- io_module_->send(*interest);
-
uint32_t initial_hash = interest->getName().getHash32(false);
auto hash = initial_hash + interest->getName().getSuffix();
uint32_t seq = interest->getName().getSuffix();
- uint32_t *suffix = interest->firstSuffix();
+ const uint32_t *suffix = interest->firstSuffix();
auto n_suffixes = interest->numberOfSuffixes();
uint32_t counter = 0;
// Set timers
do {
+ auto pend_int = pending_interest_hash_table_.try_emplace(
+ hash, worker_.getIoService(), interest);
+ PendingInterest &pending_interest = pend_int.first->second;
+ if (!pend_int.second) {
+ // element was already in map
+ pend_int.first->second.cancelTimer();
+ pending_interest.setInterest(interest);
+ }
+
+ pending_interest.setOnContentObjectCallback(
+ std::move(on_content_object_callback));
+ pending_interest.setOnTimeoutCallback(
+ std::move(on_interest_timeout_callback));
+
+ if (is_consumer_) {
+ auto self = weak_from_this();
+ pending_interest.startCountdown(
+ lifetime, portal_details::makeCustomAllocatorHandler(
+ async_callback_memory_,
+ [self, hash, seq](const std::error_code &ec) {
+ if (TRANSPORT_EXPECT_FALSE(ec.operator bool())) {
+ return;
+ }
+
+ if (auto ptr = self.lock()) {
+ ptr->timerHandler(hash, seq);
+ }
+ }));
+ }
+
if (suffix) {
hash = initial_hash + *suffix;
seq = *suffix;
suffix++;
}
+ } while (counter++ < n_suffixes);
+ }
- auto it = pending_interest_hash_table_.find(hash);
- PendingInterest *pending_interest = nullptr;
- if (it != pending_interest_hash_table_.end()) {
- it->second.cancelTimer();
- pending_interest = &it->second;
- pending_interest->setInterest(interest);
- } else {
- auto pend_int = pending_interest_hash_table_.try_emplace(
- hash, worker_.getIoService(), interest);
- pending_interest = &pend_int.first->second;
- }
+ void matchContentObjectInPIT(ContentObject &content_object) {
+ uint32_t hash = getHash(content_object.getName());
+ auto it = pending_interest_hash_table_.find(hash);
+ if (it != pending_interest_hash_table_.end()) {
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Found pending interest.";
- pending_interest->setOnContentObjectCallback(
- std::move(on_content_object_callback));
- pending_interest->setOnTimeoutCallback(
- std::move(on_interest_timeout_callback));
+ PendingInterest &pend_interest = it->second;
+ pend_interest.cancelTimer();
+ auto _int = pend_interest.getInterest();
+ auto callback = pend_interest.getOnDataCallback();
+ pending_interest_hash_table_.erase(it);
- auto self = weak_from_this();
- pending_interest->startCountdown(
- portal_details::makeCustomAllocatorHandler(
- async_callback_memory_,
- [self, hash, seq](const std::error_code &ec) {
- if (TRANSPORT_EXPECT_FALSE(ec.operator bool())) {
- return;
- }
+ if (is_consumer_) {
+ // Send object is for the app
+ if (callback != UNSET_CALLBACK) {
+ callback(*_int, content_object);
+ } else if (transport_callback_) {
+ transport_callback_->onContentObject(*_int, content_object);
+ }
+ } else {
+ // Send content object to the network
+ io_module_->send(content_object);
+ }
+ } else if (is_consumer_) {
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "No interest pending for received content object.";
+ }
+ }
- if (auto ptr = self.lock()) {
- ptr->timerHandler(hash, seq);
- }
- }));
+ /**
+ * Send an interest through to the local forwarder.
+ *
+ * @param interest - The pointer to the interest. The ownership of the
+ * interest is transferred by the caller to portal.
+ *
+ * @param on_content_object_callback - If the caller wishes to use a
+ * different callback to be called for this interest, it can set this
+ * parameter. Otherwise ConsumerCallback::onContentObject will be used.
+ *
+ * @param on_interest_timeout_callback - If the caller wishes to use a
+ * different callback to be called for this interest, it can set this
+ * parameter. Otherwise ConsumerCallback::onTimeout will be used.
+ */
+ void sendInterest(
+ Interest::Ptr &interest, uint32_t lifetime,
+ OnContentObjectCallback &&on_content_object_callback = UNSET_CALLBACK,
+ OnInterestTimeoutCallback &&on_interest_timeout_callback =
+ UNSET_CALLBACK) {
+ DCHECK(std::this_thread::get_id() == worker_.getThreadId());
- } while (counter++ < n_suffixes);
+ io_module_->send(*interest);
+ addInterestToPIT(interest, lifetime, std::move(on_content_object_callback),
+ std::move(on_interest_timeout_callback));
}
/**
@@ -423,8 +457,7 @@ class Portal : public ::utils::NonCopyable,
void sendContentObject(ContentObject &content_object) {
DCHECK(io_module_);
DCHECK(std::this_thread::get_id() == worker_.getThreadId());
-
- io_module_->send(content_object);
+ matchContentObjectInPIT(content_object);
}
/**
@@ -582,6 +615,9 @@ class Portal : public ::utils::NonCopyable,
void processInterest(Interest &interest) {
// Interest for a producer
DLOG_IF(INFO, VLOG_IS_ON(3)) << "processInterest " << interest.getName();
+
+ // Save interest in PIT
+ addInterestToPIT(interest.shared_from_this(), interest.getLifetime());
if (TRANSPORT_EXPECT_TRUE(transport_callback_ != nullptr)) {
transport_callback_->onInterest(interest);
}
@@ -598,27 +634,7 @@ class Portal : public ::utils::NonCopyable,
void processContentObject(ContentObject &content_object) {
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "processContentObject " << content_object.getName();
- uint32_t hash = getHash(content_object.getName());
-
- auto it = pending_interest_hash_table_.find(hash);
- if (it != pending_interest_hash_table_.end()) {
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "Found pending interest.";
-
- PendingInterest &pend_interest = it->second;
- pend_interest.cancelTimer();
- auto _int = pend_interest.getInterest();
- auto callback = pend_interest.getOnDataCallback();
- pending_interest_hash_table_.erase(it);
-
- if (callback != UNSET_CALLBACK) {
- callback(*_int, content_object);
- } else if (transport_callback_) {
- transport_callback_->onContentObject(*_int, content_object);
- }
- } else {
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "No interest pending for received content object.";
- }
+ matchContentObjectInPIT(content_object);
}
/**
@@ -632,7 +648,7 @@ class Portal : public ::utils::NonCopyable,
private:
portal_details::HandlerMemory async_callback_memory_;
- std::unique_ptr<IoModule, void (*)(IoModule *)> io_module_;
+ std::unique_ptr<IoModule> io_module_;
::utils::EventThread &worker_;
diff --git a/libtransport/src/core/prefix.cc b/libtransport/src/core/prefix.cc
index 4c1e191e9..00748148f 100644
--- a/libtransport/src/core/prefix.cc
+++ b/libtransport/src/core/prefix.cc
@@ -13,8 +13,10 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <hicn/transport/core/prefix.h>
#include <hicn/transport/errors/errors.h>
+#include <hicn/transport/portability/endianess.h>
#include <hicn/transport/utils/string_tokenizer.h>
#ifndef _WIN32
@@ -37,10 +39,6 @@ namespace core {
Prefix::Prefix() { std::memset(&ip_prefix_, 0, sizeof(ip_prefix_t)); }
-Prefix::Prefix(const char *prefix) : Prefix(std::string(prefix)) {}
-
-Prefix::Prefix(std::string &&prefix) : Prefix(prefix) {}
-
Prefix::Prefix(const std::string &prefix) {
utils::StringTokenizer st(prefix, "/");
@@ -56,7 +54,7 @@ Prefix::Prefix(const std::string &prefix) {
buildPrefix(ip_address, uint16_t(atoi(prefix_length.c_str())), family);
}
-Prefix::Prefix(std::string &prefix, uint16_t prefix_length) {
+Prefix::Prefix(const std::string &prefix, uint16_t prefix_length) {
int family = get_addr_family(prefix.c_str());
buildPrefix(prefix, prefix_length, family);
}
@@ -73,12 +71,14 @@ Prefix::Prefix(const core::Name &content_name, uint16_t prefix_length) {
ip_prefix_.family = family;
}
-void Prefix::buildPrefix(std::string &prefix, uint16_t prefix_length,
+void Prefix::buildPrefix(const std::string &prefix, uint16_t prefix_length,
int family) {
if (!checkPrefixLengthAndAddressFamily(prefix_length, family)) {
throw errors::InvalidIpAddressException();
}
+ std::memset(&ip_prefix_, 0, sizeof(ip_prefix_t));
+
int ret;
switch (family) {
case AF_INET:
@@ -131,62 +131,67 @@ std::unique_ptr<Sockaddr> Prefix::toSockaddr() const {
uint16_t Prefix::getPrefixLength() const { return ip_prefix_.len; }
Prefix &Prefix::setPrefixLength(uint16_t prefix_length) {
+ if (!checkPrefixLengthAndAddressFamily(prefix_length, ip_prefix_.family)) {
+ throw errors::InvalidIpAddressException();
+ }
+
ip_prefix_.len = (u8)prefix_length;
return *this;
}
int Prefix::getAddressFamily() const { return ip_prefix_.family; }
-Prefix &Prefix::setAddressFamily(int address_family) {
- ip_prefix_.family = address_family;
- return *this;
-}
-
std::string Prefix::getNetwork() const {
if (!checkPrefixLengthAndAddressFamily(ip_prefix_.len, ip_prefix_.family)) {
throw errors::InvalidIpAddressException();
}
- std::size_t size =
- ip_prefix_.family == 4 + AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN;
-
- std::string network(size, 0);
+ char buffer[INET6_ADDRSTRLEN];
- if (ip_prefix_ntop_short(&ip_prefix_, (char *)network.c_str(), size) < 0) {
+ if (ip_prefix_ntop_short(&ip_prefix_, buffer, INET6_ADDRSTRLEN) < 0) {
throw errors::RuntimeException(
"Impossible to retrieve network from ip address.");
}
- return network;
+ return buffer;
}
-int Prefix::contains(const ip_address_t &content_name) const {
- int res =
- ip_address_cmp(&content_name, &(ip_prefix_.address), ip_prefix_.family);
+bool Prefix::contains(const ip_address_t &content_name) const {
+ uint64_t mask[2] = {0, 0};
+ auto content_name_copy = content_name;
+ auto network_copy = ip_prefix_.address;
- if (ip_prefix_.len != (ip_prefix_.family == AF_INET6 ? IPV6_ADDR_LEN_BITS
- : IPV4_ADDR_LEN_BITS)) {
- const u8 *ip_prefix_buffer =
- ip_address_get_buffer(&(ip_prefix_.address), ip_prefix_.family);
- const u8 *content_name_buffer =
- ip_address_get_buffer(&content_name, ip_prefix_.family);
- uint8_t mask = 0xFF >> (ip_prefix_.len % 8);
- mask = ~mask;
+ auto prefix_length = getPrefixLength();
+ if (ip_prefix_.family == AF_INET) {
+ prefix_length += 3 * IPV4_ADDR_LEN_BITS;
+ }
- res += (ip_prefix_buffer[ip_prefix_.len] & mask) ==
- (content_name_buffer[ip_prefix_.len] & mask);
+ if (prefix_length == 0) {
+ mask[0] = mask[1] = 0;
+ } else if (prefix_length <= 64) {
+ mask[0] = portability::host_to_net((uint64_t)(~0) << (64 - prefix_length));
+ mask[1] = 0;
+ } else if (prefix_length == 128) {
+ mask[0] = mask[1] = 0xffffffffffffffff;
+ } else {
+ prefix_length -= 64;
+ mask[0] = 0xffffffffffffffff;
+ mask[1] = portability::host_to_net((uint64_t)(~0) << (64 - prefix_length));
}
- return res;
-}
+ // Apply mask
+ content_name_copy.v6.as_u64[0] &= mask[0];
+ content_name_copy.v6.as_u64[1] &= mask[1];
-int Prefix::contains(const core::Name &content_name) const {
- return contains(content_name.toIpAddress().address);
+ network_copy.v6.as_u64[0] &= mask[0];
+ network_copy.v6.as_u64[1] &= mask[1];
+
+ return ip_address_cmp(&network_copy, &content_name_copy, ip_prefix_.family) ==
+ 0;
}
-Name Prefix::getName() const {
- std::string s(getNetwork());
- return Name(s);
+bool Prefix::contains(const core::Name &content_name) const {
+ return contains(content_name.toIpAddress().address);
}
/*
@@ -199,8 +204,8 @@ Name Prefix::getName(const core::Name &mask, const core::Name &components,
ip_prefix_.family != components.getAddressFamily() ||
ip_prefix_.family != content_name.getAddressFamily())
throw errors::RuntimeException(
- "Prefix, mask, components and content name are not of the same address "
- "family");
+ "Prefix, mask, components and content name are not of the same"
+ "address family");
ip_address_t mask_ip = mask.toIpAddress().address;
ip_address_t component_ip = components.toIpAddress().address;
@@ -222,32 +227,6 @@ Name Prefix::getName(const core::Name &mask, const core::Name &components,
return Name(ip_prefix_.family, (uint8_t *)&name_ip);
}
-Name Prefix::getRandomName() const {
- ip_address_t name_ip = ip_prefix_.address;
- u8 *name_ip_buffer =
- const_cast<u8 *>(ip_address_get_buffer(&name_ip, ip_prefix_.family));
-
- int addr_len =
- (ip_prefix_.family == AF_INET6 ? IPV6_ADDR_LEN * 8 : IPV4_ADDR_LEN * 8) -
- ip_prefix_.len;
-
- size_t size = (size_t)ceil((float)addr_len / 8.0);
- uint8_t *buffer = (uint8_t *)malloc(sizeof(uint8_t) * size);
-
- RAND_bytes(buffer, (int)size);
-
- int j = 0;
- for (uint8_t i = (uint8_t)ceil((float)ip_prefix_.len / 8.0);
- i < (ip_prefix_.family == AF_INET6 ? IPV6_ADDR_LEN : IPV4_ADDR_LEN);
- i++) {
- name_ip_buffer[i] = buffer[j];
- j++;
- }
- free(buffer);
-
- return Name(ip_prefix_.family, (uint8_t *)&name_ip);
-}
-
/*
* Map a name in a different name prefix to this name prefix
*/
@@ -276,47 +255,66 @@ Name Prefix::mapName(const core::Name &content_name) const {
return Name(ip_prefix_.family, (uint8_t *)&name_ip);
}
-Prefix &Prefix::setNetwork(std::string &network) {
- if (!inet_pton(AF_INET6, network.c_str(), ip_prefix_.address.v6.buffer)) {
+Prefix &Prefix::setNetwork(const std::string &network) {
+ if (!ip_address_pton(network.c_str(), &ip_prefix_.address)) {
throw errors::RuntimeException("The network name is not valid.");
}
return *this;
}
+Name Prefix::makeName() const { return makeNameWithIndex(0); }
+
Name Prefix::makeRandomName() const {
- if (ip_prefix_.family == AF_INET6) {
- std::default_random_engine eng((std::random_device())());
- std::uniform_int_distribution<uint32_t> idis(
- 0, std::numeric_limits<uint32_t>::max());
- uint64_t random_number = idis(eng);
-
- uint32_t hash_size_bits = IPV6_ADDR_LEN_BITS - ip_prefix_.len;
- uint64_t ip_address[2];
- memcpy(ip_address, ip_prefix_.address.v6.buffer, sizeof(uint64_t));
- memcpy(ip_address + 1, ip_prefix_.address.v6.buffer + 8, sizeof(uint64_t));
- std::string network(IPV6_ADDR_LEN * 3, 0);
-
- // Let's do the magic ;)
- int shift_size = hash_size_bits > sizeof(random_number) * 8
- ? sizeof(random_number) * 8
- : hash_size_bits;
-
- ip_address[1] >>= shift_size;
- ip_address[1] <<= shift_size;
-
- ip_address[1] |= random_number >> (sizeof(uint64_t) * 8 - shift_size);
-
- if (!inet_ntop(ip_prefix_.family, ip_address, (char *)network.c_str(),
- IPV6_ADDR_LEN * 3)) {
- throw errors::RuntimeException(
- "Impossible to retrieve network from ip address.");
- }
+ std::default_random_engine eng((std::random_device())());
+ std::uniform_int_distribution<uint32_t> idis(
+ 0, std::numeric_limits<uint32_t>::max());
+ uint64_t random_number = idis(eng);
+
+ return makeNameWithIndex(random_number);
+}
+
+Name Prefix::makeNameWithIndex(std::uint64_t index) const {
+ uint16_t prefix_length = getPrefixLength();
- return Name(network);
+ Name ret;
+
+ // Adjust prefix length depending on the address family
+ if (getAddressFamily() == AF_INET) {
+ // Sanity check
+ DCHECK(prefix_length <= 32);
+ // Convert prefix length to ip46_address_t prefix length
+ prefix_length += IPV4_ADDR_LEN_BITS * 3;
+ }
+
+ std::memcpy(ret.getStructReference().prefix.v6.as_u8,
+ ip_prefix_.address.v6.as_u8, sizeof(ip_address_t));
+
+ // Convert index in network byte order
+ index = portability::host_to_net(index);
+
+ // Apply mask
+ uint64_t mask;
+ if (prefix_length == 0) {
+ mask = 0;
+ } else if (prefix_length <= 64) {
+ mask = 0;
+ } else if (prefix_length == 128) {
+ mask = 0xffffffffffffffff;
+ } else {
+ prefix_length -= 64;
+ mask = portability::host_to_net((uint64_t)(~0) << (64 - prefix_length));
}
- return Name();
+ ret.getStructReference().prefix.v6.as_u64[1] &= mask;
+ // Eventually truncate index if too big
+ index &= ~mask;
+
+ // Apply index
+ ret.getStructReference().prefix.v6.as_u64[1] |= index;
+
+ // Done
+ return ret;
}
bool Prefix::checkPrefixLengthAndAddressFamily(uint16_t prefix_length,
diff --git a/libtransport/src/core/udp_connector.cc b/libtransport/src/core/udp_connector.cc
index ee0c7ea9c..5d8e76bb1 100644
--- a/libtransport/src/core/udp_connector.cc
+++ b/libtransport/src/core/udp_connector.cc
@@ -56,9 +56,9 @@ void UdpTunnelConnector::send(Packet &packet) {
void UdpTunnelConnector::send(const utils::MemBuf::Ptr &buffer) {
auto self = shared_from_this();
- io_service_.post([self, pkt{buffer}]() {
+ io_service_.post([self, buffer]() {
bool write_in_progress = !self->output_buffer_.empty();
- self->output_buffer_.push_back(std::move(pkt));
+ self->output_buffer_.push_back(std::move(buffer));
if (TRANSPORT_EXPECT_TRUE(self->state_ == State::CONNECTED)) {
if (!write_in_progress) {
self->doSendPacket(self);
@@ -201,6 +201,8 @@ void UdpTunnelConnector::writeHandler() {
ptr->writeHandler();
}
});
+ } else {
+ sent_callback_(this, make_error_code(core_error::success));
}
}
diff --git a/libtransport/src/core/udp_connector.h b/libtransport/src/core/udp_connector.h
index 65821852d..002f4ca9f 100644
--- a/libtransport/src/core/udp_connector.h
+++ b/libtransport/src/core/udp_connector.h
@@ -62,7 +62,7 @@ class UdpTunnelConnector : public Connector {
#endif
socket_(socket),
resolver_(io_service_),
- remote_endpoint_send_(std::forward<EndpointType &&>(remote_endpoint)),
+ remote_endpoint_send_(std::forward<EndpointType>(remote_endpoint)),
timer_(io_service_),
#ifdef LINUX
send_timer_(io_service_),
diff --git a/libtransport/src/core/udp_listener.cc b/libtransport/src/core/udp_listener.cc
index c67673392..caa97e0ee 100644
--- a/libtransport/src/core/udp_listener.cc
+++ b/libtransport/src/core/udp_listener.cc
@@ -5,6 +5,7 @@
#include <core/udp_connector.h>
#include <core/udp_listener.h>
#include <glog/logging.h>
+#include <hicn/transport/portability/endianess.h>
#include <hicn/transport/utils/hash.h>
#ifndef LINUX
@@ -16,7 +17,7 @@ size_t hash<asio::ip::udp::endpoint>::operator()(
: 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);
+ return utils::hash::fnv32_buf(&port, 2, (unsigned int)hash_ip);
}
} // namespace std
#endif
@@ -83,7 +84,8 @@ void UdpTunnelListener::readHandler(const std::error_code &ec) {
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));
+ remote_endpoint_ =
+ udp::endpoint(address, portability::net_to_host(addr->sin_port));
} else {
auto addr = reinterpret_cast<struct sockaddr_in6 *>(
&remote_endpoints_[current_position_]);
@@ -91,7 +93,8 @@ void UdpTunnelListener::readHandler(const std::error_code &ec) {
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));
+ remote_endpoint_ =
+ udp::endpoint(address, portability::net_to_host(addr->sin6_port));
}
/**
diff --git a/libtransport/src/core/udp_listener.h b/libtransport/src/core/udp_listener.h
index 813520309..d8095a262 100644
--- a/libtransport/src/core/udp_listener.h
+++ b/libtransport/src/core/udp_listener.h
@@ -40,7 +40,7 @@ class UdpTunnelListener
socket_(std::make_shared<asio::ip::udp::socket>(io_service_,
endpoint.protocol())),
local_endpoint_(endpoint),
- receive_callback_(std::forward<ReceiveCallback &&>(receive_callback)),
+ receive_callback_(std::forward<ReceiveCallback>(receive_callback)),
#ifndef LINUX
read_msg_(nullptr, 0)
#else
@@ -63,12 +63,12 @@ class UdpTunnelListener
void close();
int deleteConnector(Connector *connector) {
- return connectors_.erase(connector->getConnectorId());
+ return (int)connectors_.erase(connector->getConnectorId());
}
template <typename ReceiveCallback>
void setReceiveCallback(ReceiveCallback &&callback) {
- receive_callback_ = std::forward<ReceiveCallback &&>(callback);
+ receive_callback_ = std::forward<ReceiveCallback>(callback);
}
Connector *findConnector(Connector::Id connId) {
diff --git a/libtransport/src/implementation/CMakeLists.txt b/libtransport/src/implementation/CMakeLists.txt
index 1f2a33a4c..c759dd964 100644
--- a/libtransport/src/implementation/CMakeLists.txt
+++ b/libtransport/src/implementation/CMakeLists.txt
@@ -19,21 +19,8 @@ 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}/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}/p2psecure_socket_producer.h
- ${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_consumer.h
- ${CMAKE_CURRENT_SOURCE_DIR}/p2psecure_socket_consumer.h
- )
endif()
set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/implementation/p2psecure_socket_consumer.cc b/libtransport/src/implementation/p2psecure_socket_consumer.cc
deleted file mode 100644
index 6b67a5487..000000000
--- a/libtransport/src/implementation/p2psecure_socket_consumer.cc
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * 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/p2psecure_socket_consumer.h>
-#include <interfaces/tls_socket_consumer.h>
-#include <openssl/bio.h>
-#include <openssl/ssl.h>
-#include <openssl/tls1.h>
-
-#include <random>
-
-namespace transport {
-namespace implementation {
-
-void P2PSecureConsumerSocket::setInterestPayload(
- interface::ConsumerSocket &c, const core::Interest &interest) {
- Interest &int2 = const_cast<Interest &>(interest);
- random_suffix_ = int2.getName().getSuffix();
-
- if (payload_ != NULL) int2.appendPayload(std::move(payload_));
-}
-
-/* Return the number of read bytes in the return param */
-int readOld(BIO *b, char *buf, int size) {
- if (size < 0) return size;
-
- P2PSecureConsumerSocket *socket;
- socket = (P2PSecureConsumerSocket *)BIO_get_data(b);
-
- std::unique_lock<std::mutex> lck(socket->mtx_);
-
- if (!socket->something_to_read_) {
- if (!socket->transport_protocol_->isRunning()) {
- socket->network_name_.setSuffix(socket->random_suffix_);
- socket->ConsumerSocket::consume(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();
-
- if (chain_size > (size_t)size) {
- read = size_to_read = (size_t)size;
- } else {
- read = size_to_read = chain_size;
- socket->something_to_read_ = false;
- }
-
- while (size_to_read) {
- if (socket->head_->length() < size_to_read) {
- std::memcpy(buf, socket->head_->data(), socket->head_->length());
- size_to_read -= socket->head_->length();
- buf += socket->head_->length();
- socket->head_ = socket->head_->pop();
- } else {
- std::memcpy(buf, socket->head_->data(), size_to_read);
- socket->head_->trimStart(size_to_read);
- size_to_read = 0;
- }
- }
-
- return (int)read;
-}
-
-/* Return the number of read bytes in readbytes */
-int read(BIO *b, char *buf, size_t size, size_t *readbytes) {
- int ret;
-
- if (size > INT_MAX) size = INT_MAX;
-
- ret = readOld(b, buf, (int)size);
-
- if (ret <= 0) {
- *readbytes = 0;
- return ret;
- }
-
- *readbytes = (size_t)ret;
-
- return 1;
-}
-
-/* Return the number of written bytes in the return param */
-int writeOld(BIO *b, const char *buf, int num) {
- P2PSecureConsumerSocket *socket;
- socket = (P2PSecureConsumerSocket *)BIO_get_data(b);
-
- socket->payload_ = utils::MemBuf::copyBuffer(buf, num);
-
- socket->ConsumerSocket::setSocketOption(
- ConsumerCallbacksOptions::INTEREST_OUTPUT,
- (ConsumerInterestCallback)std::bind(
- &P2PSecureConsumerSocket::setInterestPayload, socket,
- std::placeholders::_1, std::placeholders::_2));
-
- return num;
-}
-
-/* Return the number of written bytes in written */
-int write(BIO *b, const char *buf, size_t size, size_t *written) {
- int ret;
-
- if (size > INT_MAX) size = INT_MAX;
-
- ret = writeOld(b, buf, (int)size);
-
- if (ret <= 0) {
- *written = 0;
- return ret;
- }
-
- *written = (size_t)ret;
-
- return 1;
-}
-
-long ctrl(BIO *b, int cmd, long num, void *ptr) { return 1; }
-
-int P2PSecureConsumerSocket::addHicnKeyIdCb(SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char **out,
- size_t *outlen, X509 *x,
- size_t chainidx, int *al,
- void *add_arg) {
- if (ext_type == 100) {
- *out = (unsigned char *)malloc(4);
- *(uint32_t *)*out = 10;
- *outlen = 4;
- }
- return 1;
-}
-
-void P2PSecureConsumerSocket::freeHicnKeyIdCb(SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char *out,
- void *add_arg) {
- free(const_cast<unsigned char *>(out));
-}
-
-int P2PSecureConsumerSocket::parseHicnKeyIdCb(SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char *in,
- size_t inlen, X509 *x,
- size_t chainidx, int *al,
- void *add_arg) {
- P2PSecureConsumerSocket *socket =
- reinterpret_cast<P2PSecureConsumerSocket *>(add_arg);
- if (ext_type == 100) {
- memcpy(&socket->secure_prefix_, in, sizeof(ip_prefix_t));
- }
- return 1;
-}
-
-P2PSecureConsumerSocket::P2PSecureConsumerSocket(
- interface::ConsumerSocket *consumer, int handshake_protocol,
- int transport_protocol)
- : ConsumerSocket(consumer, handshake_protocol),
- name_(),
- tls_consumer_(nullptr),
- decrypted_content_(),
- payload_(),
- head_(),
- something_to_read_(false),
- content_downloaded_(false),
- random_suffix_(),
- secure_prefix_(),
- producer_namespace_(),
- read_callback_decrypted_(),
- mtx_(),
- cv_(),
- protocol_(transport_protocol) {
- /* Create the (d)TLS state */
- const SSL_METHOD *meth = TLS_client_method();
- ctx_ = SSL_CTX_new(meth);
-
- int result =
- 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.");
- }
-
- SSL_CTX_set_min_proto_version(ctx_, TLS1_3_VERSION);
- SSL_CTX_set_max_proto_version(ctx_, TLS1_3_VERSION);
- SSL_CTX_set_verify(ctx_, SSL_VERIFY_NONE, NULL);
- SSL_CTX_set_ssl_version(ctx_, meth);
-
- result = SSL_CTX_add_custom_ext(
- ctx_, 100, SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
- P2PSecureConsumerSocket::addHicnKeyIdCb,
- P2PSecureConsumerSocket::freeHicnKeyIdCb, NULL,
- P2PSecureConsumerSocket::parseHicnKeyIdCb, this);
-
- ssl_ = SSL_new(ctx_);
-
- bio_meth_ = BIO_meth_new(BIO_TYPE_CONNECT, "secure consumer socket");
- BIO_meth_set_read(bio_meth_, readOld);
- BIO_meth_set_write(bio_meth_, writeOld);
- BIO_meth_set_ctrl(bio_meth_, ctrl);
- BIO *bio = BIO_new(bio_meth_);
- BIO_set_init(bio, 1);
- BIO_set_data(bio, this);
- SSL_set_bio(ssl_, bio, bio);
-
- std::default_random_engine generator;
- std::uniform_int_distribution<int> distribution(
- 1, std::numeric_limits<uint32_t>::max());
- random_suffix_ = 0;
-
- this->ConsumerSocket::setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK,
- this);
-};
-
-P2PSecureConsumerSocket::~P2PSecureConsumerSocket() {
- BIO_meth_free(bio_meth_);
- SSL_shutdown(ssl_);
-}
-
-int P2PSecureConsumerSocket::handshake() {
- int result = 1;
-
- if (!(SSL_in_before(this->ssl_) || SSL_in_init(this->ssl_))) {
- return 1;
- }
-
- ConsumerSocket::getSocketOption(MAX_WINDOW_SIZE, old_max_win_);
- ConsumerSocket::getSocketOption(CURRENT_WINDOW_SIZE, old_current_win_);
-
- ConsumerSocket::setSocketOption(MAX_WINDOW_SIZE, (double)1.0);
- ConsumerSocket::setSocketOption(CURRENT_WINDOW_SIZE, (double)1.0);
-
- network_name_ = producer_namespace_.getRandomName();
- network_name_.setSuffix(0);
-
- DLOG_IF(INFO, VLOG_IS_ON(2)) << "Start handshake at " << network_name_;
- result = SSL_connect(this->ssl_);
-
- return result;
-}
-
-void P2PSecureConsumerSocket::initSessionSocket() {
- tls_consumer_ =
- std::make_shared<TLSConsumerSocket>(nullptr, this->protocol_, this->ssl_);
- tls_consumer_->setInterface(
- new interface::TLSConsumerSocket(tls_consumer_.get()));
-
- ConsumerTimerCallback *stats_summary_callback = nullptr;
- this->getSocketOption(ConsumerCallbacksOptions::STATS_SUMMARY,
- &stats_summary_callback);
-
- 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();
-}
-
-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 {
- DLOG_IF(INFO, VLOG_IS_ON(2)) << "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)));
-}
-
-void P2PSecureConsumerSocket::registerPrefix(const Prefix &producer_namespace) {
- producer_namespace_ = producer_namespace;
-}
-
-int P2PSecureConsumerSocket::setSocketOption(
- int socket_option_key, ReadCallback *socket_option_value) {
- return rescheduleOnIOService(
- socket_option_key, socket_option_value,
- [this](int socket_option_key, ReadCallback *socket_option_value) -> int {
- switch (socket_option_key) {
- case ConsumerCallbacksOptions::READ_CALLBACK:
- read_callback_decrypted_ = socket_option_value;
- break;
- default:
- return SOCKET_OPTION_NOT_SET;
- }
-
- return SOCKET_OPTION_SET;
- });
-}
-
-void P2PSecureConsumerSocket::getReadBuffer(uint8_t **application_buffer,
- size_t *max_length){};
-
-void P2PSecureConsumerSocket::readDataAvailable(size_t length) noexcept {};
-
-size_t P2PSecureConsumerSocket::maxBufferSize() const {
- return SSL3_RT_MAX_PLAIN_LENGTH;
-}
-
-void P2PSecureConsumerSocket::readBufferAvailable(
- std::unique_ptr<utils::MemBuf> &&buffer) noexcept {
- std::unique_lock<std::mutex> lck(this->mtx_);
- if (head_) {
- head_->prependChain(std::move(buffer));
- } else {
- head_ = std::move(buffer);
- }
-
- something_to_read_ = true;
- cv_.notify_one();
-}
-
-void P2PSecureConsumerSocket::readError(const std::error_code &ec) noexcept {};
-
-void P2PSecureConsumerSocket::readSuccess(std::size_t total_size) noexcept {
- std::unique_lock<std::mutex> lck(this->mtx_);
- content_downloaded_ = true;
- something_to_read_ = true;
- cv_.notify_one();
-}
-
-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
deleted file mode 100644
index a5e69f611..000000000
--- a/libtransport/src/implementation/p2psecure_socket_consumer.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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/socket_consumer.h>
-#include <implementation/tls_socket_consumer.h>
-#include <openssl/bio.h>
-#include <openssl/ssl.h>
-
-namespace transport {
-namespace implementation {
-
-class P2PSecureConsumerSocket : public ConsumerSocket,
- public interface::ConsumerSocket::ReadCallback {
- /* Return the number of read bytes in readbytes */
- friend int read(BIO *b, char *buf, size_t size, size_t *readbytes);
-
- /* Return the number of read bytes in the return param */
- friend int readOld(BIO *h, char *buf, int size);
-
- /* Return the number of written bytes in written */
- friend int write(BIO *b, const char *buf, size_t size, size_t *written);
-
- /* Return the number of written bytes in the return param */
- friend int writeOld(BIO *h, const char *buf, int num);
-
- friend long ctrl(BIO *b, int cmd, long num, void *ptr);
-
- public:
- explicit P2PSecureConsumerSocket(interface::ConsumerSocket *consumer,
- int handshake_protocol,
- int transport_protocol);
-
- ~P2PSecureConsumerSocket();
-
- int consume(const Name &name) override;
-
- void registerPrefix(const Prefix &producer_namespace);
-
- int setSocketOption(
- int socket_option_key,
- interface::ConsumerSocket::ReadCallback *socket_option_value) override;
-
- using ConsumerSocket::getSocketOption;
- using ConsumerSocket::setSocketOption;
-
- protected:
- /* Callback invoked once an interest has been received and its payload
- * decrypted */
- ConsumerInterestCallback on_interest_input_decrypted_;
- ConsumerInterestCallback on_interest_process_decrypted_;
-
- 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 */
- 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 */
- std::condition_variable cv_;
-
- int protocol_;
-
- void setInterestPayload(interface::ConsumerSocket &c,
- const core::Interest &interest);
-
- static int addHicnKeyIdCb(SSL *s, unsigned int ext_type, unsigned int context,
- const unsigned char **out, size_t *outlen, X509 *x,
- size_t chainidx, int *al, void *add_arg);
-
- static void freeHicnKeyIdCb(SSL *s, unsigned int ext_type,
- unsigned int context, const unsigned char *out,
- void *add_arg);
-
- static int parseHicnKeyIdCb(SSL *s, unsigned int ext_type,
- unsigned int context, const unsigned char *in,
- size_t inlen, X509 *x, size_t chainidx, int *al,
- void *add_arg);
-
- virtual void getReadBuffer(uint8_t **application_buffer,
- size_t *max_length) override;
-
- virtual void readDataAvailable(size_t length) noexcept override;
-
- virtual size_t maxBufferSize() const override;
-
- virtual void readBufferAvailable(
- std::unique_ptr<utils::MemBuf> &&buffer) noexcept override;
-
- 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 handshake();
-
- void initSessionSocket();
-};
-
-} // namespace implementation
-
-} // end namespace transport
diff --git a/libtransport/src/implementation/p2psecure_socket_producer.cc b/libtransport/src/implementation/p2psecure_socket_producer.cc
deleted file mode 100644
index ee78ea53b..000000000
--- a/libtransport/src/implementation/p2psecure_socket_producer.cc
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * 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 <hicn/transport/core/interest.h>
-#include <implementation/p2psecure_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/pkcs12.h>
-#include <openssl/rand.h>
-#include <openssl/ssl.h>
-
-namespace transport {
-namespace implementation {
-
-/* Workaround to prevent content with expiry time equal to 0 to be lost when
- * pushed in the forwarder */
-#define HICN_HANDSHAKE_CONTENT_EXPIRY_TIME 100;
-
-P2PSecureProducerSocket::P2PSecureProducerSocket(
- interface::ProducerSocket *producer_socket)
- : ProducerSocket(producer_socket,
- ProductionProtocolAlgorithms::BYTE_STREAM),
- mtx_(),
- cv_(),
- map_producers(),
- list_producers() {}
-
-P2PSecureProducerSocket::P2PSecureProducerSocket(
- interface::ProducerSocket *producer_socket, bool rtc,
- std::string &keystore_path, std::string &keystore_pwd)
- : ProducerSocket(producer_socket,
- ProductionProtocolAlgorithms::BYTE_STREAM),
- rtc_(rtc),
- mtx_(),
- cv_(),
- map_producers(),
- list_producers() {
- /* Setup SSL context (identity and parameter to use TLS 1.3) */
- FILE *p12file = fopen(keystore_path.c_str(), "r");
- if (p12file == NULL)
- throw errors::RuntimeException("impossible open keystore");
- std::unique_ptr<PKCS12, decltype(&::PKCS12_free)> p12(
- d2i_PKCS12_fp(p12file, NULL), ::PKCS12_free);
- // now we parse the file to get the first key and certificate
- if (1 != PKCS12_parse(p12.get(), keystore_pwd.c_str(), &pkey_rsa_, &cert_509_,
- NULL))
- throw errors::RuntimeException("impossible to get the private key");
- fclose(p12file);
-
- /* 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(
- &P2PSecureProducerSocket::onInterestCallback, this,
- std::placeholders::_1, std::placeholders::_2));
-}
-
-P2PSecureProducerSocket::~P2PSecureProducerSocket() {}
-
-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)});
-
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "Start handshake at " << interest.getName();
-
- if (!rtc_) {
- tls_producer_ptr->onInterest(*tls_producer_ptr, interest);
- tls_producer_ptr->async_accept();
- } else {
- // TODO
- // TLSRTCProducerSocket *rtc_producer_ptr =
- // dynamic_cast<TLSRTCProducerSocket *>(tls_producer_ptr);
- // rtc_producer_ptr->onInterest(*rtc_producer_ptr, interest);
- // rtc_producer_ptr->async_accept();
- }
-}
-
-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 " "data. Aborting.");
- // }
-
- // std::unique_lock<std::mutex> lck(mtx_);
-
- // 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::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 "
- "current data. Aborting.");
- }
-
- std::unique_lock<std::mutex> lck(mtx_);
- uint32_t segments = 0;
-
- 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::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 "
- "current data. Aborting.");
- }
-
- std::unique_lock<std::mutex> lck(mtx_);
- uint32_t segments = 0;
- 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);
-
- return segments;
-}
-
-/* Redefinition of socket options to avoid name hiding */
-int P2PSecureProducerSocket::setSocketOption(
- int socket_option_key, ProducerInterestCallback 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) {
- case ProducerCallbacksOptions::INTEREST_INPUT:
- on_interest_input_decrypted_ = socket_option_value;
- return SOCKET_OPTION_SET;
-
- case ProducerCallbacksOptions::INTEREST_DROP:
- on_interest_dropped_input_buffer_ = socket_option_value;
- return SOCKET_OPTION_SET;
-
- case ProducerCallbacksOptions::INTEREST_PASS:
- on_interest_inserted_input_buffer_ = socket_option_value;
- return SOCKET_OPTION_SET;
-
- case ProducerCallbacksOptions::CACHE_HIT:
- on_interest_satisfied_output_buffer_ = socket_option_value;
- return SOCKET_OPTION_SET;
-
- case ProducerCallbacksOptions::CACHE_MISS:
- on_interest_process_decrypted_ = socket_option_value;
- return SOCKET_OPTION_SET;
-
- default:
- return SOCKET_OPTION_NOT_SET;
- }
-}
-
-int P2PSecureProducerSocket::setSocketOption(
- int socket_option_key,
- 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) {
- case GeneralTransportOptions::SIGNER: {
- signer_.reset();
- signer_ = socket_option_value;
-
- return SOCKET_OPTION_SET;
- }
- default:
- return SOCKET_OPTION_NOT_SET;
- }
-}
-
-int P2PSecureProducerSocket::setSocketOption(int socket_option_key,
- uint32_t 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) {
- case GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME:
- content_object_expiry_time_ =
- socket_option_value; // HICN_HANDSHAKE_CONTENT_EXPIRY_TIME;
- return SOCKET_OPTION_SET;
- }
- return ProducerSocket::setSocketOption(socket_option_key,
- socket_option_value);
-}
-
-int P2PSecureProducerSocket::setSocketOption(int socket_option_key,
- bool 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,
- socket_option_value);
-}
-
-int P2PSecureProducerSocket::setSocketOption(int socket_option_key,
- Name *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,
- socket_option_value);
-}
-
-int P2PSecureProducerSocket::setSocketOption(
- int socket_option_key, ProducerContentObjectCallback 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,
- socket_option_value);
-}
-
-int P2PSecureProducerSocket::setSocketOption(
- int socket_option_key, ProducerContentCallback 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) {
- case ProducerCallbacksOptions::CONTENT_PRODUCED:
- on_content_produced_application_ = socket_option_value;
- break;
-
- default:
- return SOCKET_OPTION_NOT_SET;
- }
-
- return SOCKET_OPTION_SET;
-}
-
-int P2PSecureProducerSocket::setSocketOption(
- 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,
- socket_option_value);
-}
-
-int P2PSecureProducerSocket::setSocketOption(
- int socket_option_key, const std::string &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,
- socket_option_value);
-}
-
-} // namespace implementation
-} // namespace transport
diff --git a/libtransport/src/implementation/p2psecure_socket_producer.h b/libtransport/src/implementation/p2psecure_socket_producer.h
deleted file mode 100644
index 00f407a75..000000000
--- a/libtransport/src/implementation/p2psecure_socket_producer.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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/auth/signer.h>
-#include <implementation/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 <condition_variable>
-#include <forward_list>
-#include <mutex>
-
-namespace transport {
-namespace implementation {
-
-class P2PSecureProducerSocket : public ProducerSocket {
- friend class TLSProducerSocket;
- // TODO
- // friend class TLSRTCProducerSocket;
-
- public:
- explicit P2PSecureProducerSocket(interface::ProducerSocket *producer_socket);
-
- explicit P2PSecureProducerSocket(interface::ProducerSocket *producer_socket,
- bool rtc, std::string &keystore_path,
- std::string &keystore_pwd);
-
- ~P2PSecureProducerSocket();
-
- uint32_t produceDatagram(const Name &content_name,
- std::unique_ptr<utils::MemBuf> &&buffer) 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 produceStream(const Name &content_name,
- std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last = true,
- uint32_t start_offset = 0) override;
-
- int setSocketOption(int socket_option_key,
- ProducerInterestCallback socket_option_value) override;
-
- int setSocketOption(
- int socket_option_key,
- const std::shared_ptr<auth::Signer> &socket_option_value) override;
-
- int setSocketOption(int socket_option_key,
- uint32_t socket_option_value) override;
-
- int setSocketOption(int socket_option_key, bool socket_option_value) override;
-
- int setSocketOption(int socket_option_key,
- Name *socket_option_value) override;
-
- int setSocketOption(
- int socket_option_key,
- ProducerContentObjectCallback socket_option_value) override;
-
- int setSocketOption(int socket_option_key,
- ProducerContentCallback socket_option_value) override;
-
- int setSocketOption(int socket_option_key,
- 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;
-
- protected:
- /* 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_;
-
- private:
- bool rtc_;
- std::mutex mtx_;
- /* Condition variable for the wait */
- std::condition_variable cv_;
- 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_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
index 95941da07..b80fbb58c 100644
--- a/libtransport/src/implementation/socket.cc
+++ b/libtransport/src/implementation/socket.cc
@@ -23,7 +23,9 @@ namespace implementation {
Socket::Socket(std::shared_ptr<core::Portal> &&portal)
: portal_(std::move(portal)),
is_async_(false),
- packet_format_(interface::default_values::packet_format) {}
+ packet_format_(interface::default_values::packet_format),
+ signer_(std::make_shared<auth::VoidSigner>()),
+ verifier_(std::make_shared<auth::VoidVerifier>()) {}
int Socket::setSocketOption(int socket_option_key,
hicn_format_t packet_format) {
diff --git a/libtransport/src/implementation/socket.h b/libtransport/src/implementation/socket.h
index 11c9a704d..3eb93cff6 100644
--- a/libtransport/src/implementation/socket.h
+++ b/libtransport/src/implementation/socket.h
@@ -16,6 +16,8 @@
#pragma once
#include <core/facade.h>
+#include <hicn/transport/auth/signer.h>
+#include <hicn/transport/auth/verifier.h>
#include <hicn/transport/config.h>
#include <hicn/transport/interfaces/callbacks.h>
#include <hicn/transport/interfaces/socket_options_default_values.h>
@@ -68,6 +70,8 @@ class Socket {
std::shared_ptr<core::Portal> portal_;
bool is_async_;
hicn_format_t packet_format_;
+ std::shared_ptr<auth::Signer> signer_;
+ std::shared_ptr<auth::Verifier> verifier_;
};
} // namespace implementation
diff --git a/libtransport/src/implementation/socket_consumer.h b/libtransport/src/implementation/socket_consumer.h
index 33e70888f..4721f426c 100644
--- a/libtransport/src/implementation/socket_consumer.h
+++ b/libtransport/src/implementation/socket_consumer.h
@@ -56,8 +56,8 @@ class ConsumerSocket : public Socket {
rate_estimation_observer_(nullptr),
rate_estimation_batching_parameter_(default_values::batch),
rate_estimation_choice_(0),
- unverified_interval_(default_values::unverified_interval),
- unverified_ratio_(default_values::unverified_ratio),
+ manifest_factor_relevant_(default_values::manifest_factor_relevant),
+ manifest_factor_alert_(default_values::manifest_factor_alert),
verifier_(std::make_shared<auth::VoidVerifier>()),
verify_signature_(false),
reset_window_(false),
@@ -72,6 +72,8 @@ class ConsumerSocket : public Socket {
timer_interval_milliseconds_(0),
recovery_strategy_(RtcTransportRecoveryStrategies::RTX_ONLY),
aggregated_data_(false),
+ content_sharing_mode_(false),
+ aggregated_interests_(false),
guard_raaqm_params_() {
switch (protocol) {
case TransportProtocolAlgorithms::CBR:
@@ -197,10 +199,6 @@ class ConsumerSocket : public Socket {
current_window_size_ = socket_option_value;
break;
- case UNVERIFIED_RATIO:
- unverified_ratio_ = socket_option_value;
- break;
-
case GAMMA_VALUE:
gamma_ = socket_option_value;
break;
@@ -242,10 +240,6 @@ class ConsumerSocket : public Socket {
interest_lifetime_ = socket_option_value;
break;
- case GeneralTransportOptions::UNVERIFIED_INTERVAL:
- unverified_interval_ = socket_option_value;
- break;
-
case RateEstimationOptions::RATE_ESTIMATION_BATCH_PARAMETER:
if (socket_option_value > 0) {
rate_estimation_batching_parameter_ = socket_option_value;
@@ -271,6 +265,14 @@ class ConsumerSocket : public Socket {
(RtcTransportRecoveryStrategies)socket_option_value;
break;
+ case MANIFEST_FACTOR_RELEVANT:
+ manifest_factor_relevant_ = socket_option_value;
+ break;
+
+ case MANIFEST_FACTOR_ALERT:
+ manifest_factor_alert_ = socket_option_value;
+ break;
+
default:
return SOCKET_OPTION_NOT_SET;
}
@@ -339,6 +341,16 @@ class ConsumerSocket : public Socket {
result = SOCKET_OPTION_SET;
break;
+ case RtcTransportOptions::CONTENT_SHARING_MODE:
+ content_sharing_mode_ = socket_option_value;
+ result = SOCKET_OPTION_SET;
+ break;
+
+ case RtcTransportOptions::AGGREGATED_INTERESTS:
+ aggregated_interests_ = socket_option_value;
+ result = SOCKET_OPTION_SET;
+ break;
+
default:
return result;
}
@@ -416,6 +428,22 @@ class ConsumerSocket : public Socket {
int setSocketOption(
int socket_option_key,
+ const std::shared_ptr<auth::Signer> &socket_option_value) {
+ if (!transport_protocol_->isRunning()) {
+ switch (socket_option_key) {
+ case GeneralTransportOptions::SIGNER:
+ signer_.reset();
+ signer_ = socket_option_value;
+ break;
+ default:
+ return SOCKET_OPTION_NOT_SET;
+ }
+ }
+ return SOCKET_OPTION_SET;
+ }
+
+ int setSocketOption(
+ int socket_option_key,
const std::shared_ptr<auth::Verifier> &socket_option_value) {
if (!transport_protocol_->isRunning()) {
switch (socket_option_key) {
@@ -506,10 +534,6 @@ class ConsumerSocket : public Socket {
socket_option_value = current_window_size_;
break;
- case GeneralTransportOptions::UNVERIFIED_RATIO:
- socket_option_value = unverified_ratio_;
- break;
-
// RAAQM parameters
case RaaqmTransportOptions::GAMMA_VALUE:
@@ -550,10 +574,6 @@ class ConsumerSocket : public Socket {
socket_option_value = interest_lifetime_;
break;
- case GeneralTransportOptions::UNVERIFIED_INTERVAL:
- socket_option_value = unverified_interval_;
- break;
-
case RaaqmTransportOptions::SAMPLE_NUMBER:
socket_option_value = sample_number_;
break;
@@ -574,6 +594,14 @@ class ConsumerSocket : public Socket {
socket_option_value = recovery_strategy_;
break;
+ case GeneralTransportOptions::MANIFEST_FACTOR_RELEVANT:
+ socket_option_value = manifest_factor_relevant_;
+ break;
+
+ case GeneralTransportOptions::MANIFEST_FACTOR_ALERT:
+ socket_option_value = manifest_factor_alert_;
+ break;
+
default:
return SOCKET_OPTION_NOT_GET;
}
@@ -599,6 +627,14 @@ class ConsumerSocket : public Socket {
socket_option_value = aggregated_data_;
break;
+ case RtcTransportOptions::CONTENT_SHARING_MODE:
+ socket_option_value = content_sharing_mode_;
+ break;
+
+ case RtcTransportOptions::AGGREGATED_INTERESTS:
+ socket_option_value = aggregated_interests_;
+ break;
+
default:
return SOCKET_OPTION_NOT_GET;
}
@@ -689,6 +725,18 @@ class ConsumerSocket : public Socket {
}
int getSocketOption(int socket_option_key,
+ std::shared_ptr<auth::Signer> &socket_option_value) {
+ switch (socket_option_key) {
+ case GeneralTransportOptions::SIGNER:
+ socket_option_value = signer_;
+ return SOCKET_OPTION_GET;
+
+ default:
+ return SOCKET_OPTION_NOT_GET;
+ }
+ }
+
+ int getSocketOption(int socket_option_key,
std::shared_ptr<auth::Verifier> &socket_option_value) {
switch (socket_option_key) {
case GeneralTransportOptions::VERIFIER:
@@ -827,8 +875,8 @@ class ConsumerSocket : public Socket {
int rate_estimation_choice_;
// Verification parameters
- uint32_t unverified_interval_;
- double unverified_ratio_;
+ uint32_t manifest_factor_relevant_;
+ uint32_t manifest_factor_alert_;
std::shared_ptr<auth::Verifier> verifier_;
transport::auth::KeyId *key_id_;
std::atomic_bool verify_signature_;
@@ -856,6 +904,8 @@ class ConsumerSocket : public Socket {
// RTC protocol
RtcTransportRecoveryStrategies recovery_strategy_;
bool aggregated_data_;
+ bool content_sharing_mode_;
+ bool aggregated_interests_;
utils::SpinLock guard_raaqm_params_;
std::string output_interface_;
diff --git a/libtransport/src/implementation/socket_producer.h b/libtransport/src/implementation/socket_producer.h
index 37151d497..53ce28766 100644
--- a/libtransport/src/implementation/socket_producer.h
+++ b/libtransport/src/implementation/socket_producer.h
@@ -51,9 +51,8 @@ class ProducerSocket : public Socket {
data_packet_size_(default_values::content_object_packet_size),
max_segment_size_(default_values::content_object_packet_size),
content_object_expiry_time_(default_values::content_object_expiry_time),
- making_manifest_(default_values::manifest_capacity),
+ manifest_max_capacity_(default_values::manifest_max_capacity),
hash_algorithm_(auth::CryptoHashType::SHA256),
- signer_(std::make_shared<auth::VoidSigner>()),
suffix_strategy_(std::make_shared<utils::IncrementalSuffixStrategy>(0)),
aggregated_data_(false),
fec_setting_(""),
@@ -181,8 +180,8 @@ class ProducerSocket : public Socket {
}
break;
- case GeneralTransportOptions::MAKE_MANIFEST:
- making_manifest_ = socket_option_value;
+ case GeneralTransportOptions::MANIFEST_MAX_CAPACITY:
+ manifest_max_capacity_ = socket_option_value;
break;
case GeneralTransportOptions::MAX_SEGMENT_SIZE:
@@ -433,6 +432,20 @@ class ProducerSocket : public Socket {
return SOCKET_OPTION_SET;
}
+ virtual int setSocketOption(
+ int socket_option_key,
+ const std::shared_ptr<auth::Verifier> &socket_option_value) {
+ switch (socket_option_key) {
+ case GeneralTransportOptions::VERIFIER:
+ verifier_.reset();
+ verifier_ = socket_option_value;
+ return SOCKET_OPTION_SET;
+
+ default:
+ return SOCKET_OPTION_NOT_SET;
+ }
+ }
+
int getSocketOption(int socket_option_key,
ProducerCallback **socket_option_value) {
// Reschedule the function on the io_service to avoid race condition in
@@ -456,12 +469,13 @@ class ProducerSocket : public Socket {
virtual int getSocketOption(int socket_option_key,
uint32_t &socket_option_value) {
switch (socket_option_key) {
- case GeneralTransportOptions::MAKE_MANIFEST:
- socket_option_value = making_manifest_;
+ case GeneralTransportOptions::MANIFEST_MAX_CAPACITY:
+ socket_option_value = (uint32_t)manifest_max_capacity_;
break;
case GeneralTransportOptions::OUTPUT_BUFFER_SIZE:
- socket_option_value = production_protocol_->getOutputBufferSize();
+ socket_option_value =
+ (uint32_t)production_protocol_->getOutputBufferSize();
break;
case GeneralTransportOptions::DATA_PACKET_SIZE:
@@ -636,6 +650,18 @@ class ProducerSocket : public Socket {
return SOCKET_OPTION_GET;
}
+ int getSocketOption(int socket_option_key,
+ std::shared_ptr<auth::Verifier> &socket_option_value) {
+ switch (socket_option_key) {
+ case GeneralTransportOptions::VERIFIER:
+ socket_option_value = verifier_;
+ return SOCKET_OPTION_GET;
+
+ default:
+ return SOCKET_OPTION_NOT_GET;
+ }
+ }
+
int getSocketOption(int socket_option_key, std::string &socket_option_value) {
switch (socket_option_key) {
case GeneralTransportOptions::FEC_TYPE:
@@ -736,11 +762,10 @@ class ProducerSocket : public Socket {
std::atomic<size_t> max_segment_size_;
std::atomic<uint32_t> content_object_expiry_time_;
- std::atomic<uint32_t> making_manifest_;
+ std::atomic<uint32_t> manifest_max_capacity_;
std::atomic<auth::CryptoHashType> hash_algorithm_;
std::atomic<auth::CryptoSuite> crypto_suite_;
utils::SpinLock signer_lock_;
- std::shared_ptr<auth::Signer> signer_;
std::shared_ptr<utils::SuffixStrategy> suffix_strategy_;
std::shared_ptr<protocol::ProductionProtocol> production_protocol_;
diff --git a/libtransport/src/implementation/tls_rtc_socket_producer.cc b/libtransport/src/implementation/tls_rtc_socket_producer.cc
deleted file mode 100644
index 06d613ef0..000000000
--- a/libtransport/src/implementation/tls_rtc_socket_producer.cc
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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 <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>
-
-namespace transport {
-namespace implementation {
-
-int TLSRTCProducerSocket::read(BIO *b, char *buf, size_t size,
- size_t *readbytes) {
- int ret;
-
- if (size > INT_MAX) size = INT_MAX;
-
- ret = TLSRTCProducerSocket::readOld(b, buf, (int)size);
-
- if (ret <= 0) {
- *readbytes = 0;
- return ret;
- }
-
- *readbytes = (size_t)ret;
-
- return 1;
-}
-
-int TLSRTCProducerSocket::readOld(BIO *b, char *buf, int size) {
- TLSRTCProducerSocket *socket;
- socket = (TLSRTCProducerSocket *)BIO_get_data(b);
-
- std::unique_lock<std::mutex> lck(socket->mtx_);
- if (!socket->something_to_read_) {
- (socket->cv_).wait(lck);
- }
-
- 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();
- socket->something_to_read_ = false;
- }
-
- std::memcpy(buf, membuf->data(), size_to_read);
- membuf->trimStart(size_to_read);
-
- return size_to_read;
-}
-
-int TLSRTCProducerSocket::write(BIO *b, const char *buf, size_t size,
- size_t *written) {
- int ret;
-
- if (size > INT_MAX) size = INT_MAX;
-
- ret = TLSRTCProducerSocket::writeOld(b, buf, (int)size);
-
- if (ret <= 0) {
- *written = 0;
- return ret;
- }
-
- *written = (size_t)ret;
-
- return 1;
-}
-
-int TLSRTCProducerSocket::writeOld(BIO *b, const char *buf, int num) {
- TLSRTCProducerSocket *socket;
- socket = (TLSRTCProducerSocket *)BIO_get_data(b);
-
- if (socket->getHandshakeState() != SERVER_FINISHED && socket->first_) {
- uint32_t making_manifest = socket->parent_->making_manifest_;
-
- socket->tls_chunks_--;
- socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
- 0U);
- socket->parent_->ProducerSocket::produce(
- socket->name_, (const uint8_t *)buf, num, socket->tls_chunks_ == 0, 0);
- socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
- making_manifest);
- socket->first_ = false;
-
- } else {
- 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(
- (transport::interface::ProducerSocket &)(*socket->getInterface()),
- std::error_code(), 0);
- }
- });
- }
-
- return num;
-}
-
-TLSRTCProducerSocket::TLSRTCProducerSocket(
- interface::ProducerSocket *producer_socket, P2PSecureProducerSocket *parent,
- const Name &handshake_name)
- : ProducerSocket(producer_socket),
- RTCProducerSocket(producer_socket),
- TLSProducerSocket(producer_socket, parent, handshake_name) {
- BIO_METHOD *bio_meth =
- BIO_meth_new(BIO_TYPE_ACCEPT, "secure rtc producer socket");
- BIO_meth_set_read(bio_meth, TLSRTCProducerSocket::readOld);
- BIO_meth_set_write(bio_meth, TLSRTCProducerSocket::writeOld);
- BIO_meth_set_ctrl(bio_meth, TLSProducerSocket::ctrl);
- BIO *bio = BIO_new(bio_meth);
- BIO_set_init(bio, 1);
- BIO_set_data(bio, this);
- SSL_set_bio(ssl_, bio, bio);
-}
-
-void TLSRTCProducerSocket::accept() {
- 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");
- }
-
- DLOG_IF(INFO, VLOG_IS_ON(2)) << "Handshake performed!";
-
- 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(handshake_packet_));
- on_interest_process_decrypted(
- (transport::interface::ProducerSocket &)(*getInterface()), inter);
- }
-
- parent_->cv_.notify_one();
-}
-
-int TLSRTCProducerSocket::async_accept() {
- if (!async_thread_.stopped()) {
- async_thread_.add([this]() { this->TLSRTCProducerSocket::accept(); });
- } else {
- throw errors::RuntimeException(
- "Async thread not running, impossible to perform handshake");
- }
-
- return 1;
-}
-
-void TLSRTCProducerSocket::produce(std::unique_ptr<utils::MemBuf> &&buffer) {
- HandshakeState handshake_state = getHandshakeState();
-
- if (handshake_state != SERVER_FINISHED) {
- throw errors::RuntimeException(
- "New handshake on the same P2P secure producer socket not supported");
- }
-
- size_t buf_size = buffer->length();
- tls_chunks_ = ceil((float)buf_size / (float)SSL3_RT_MAX_PLAIN_LENGTH);
- to_call_oncontentproduced_ = tls_chunks_;
-
- SSL_write(ssl_, buffer->data(), buf_size);
- BIO *wbio = SSL_get_wbio(ssl_);
- int i = BIO_flush(wbio);
- (void)i; // To shut up gcc 5
-}
-
-} // namespace implementation
-} // namespace transport
diff --git a/libtransport/src/implementation/tls_rtc_socket_producer.h b/libtransport/src/implementation/tls_rtc_socket_producer.h
deleted file mode 100644
index f6dc425e4..000000000
--- a/libtransport/src/implementation/tls_rtc_socket_producer.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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 <implementation/tls_socket_producer.h>
-
-namespace transport {
-namespace implementation {
-
-class P2PSecureProducerSocket;
-
-class TLSRTCProducerSocket : public TLSProducerSocket {
- friend class P2PSecureProducerSocket;
-
- public:
- explicit TLSRTCProducerSocket(interface::ProducerSocket *producer_socket,
- P2PSecureProducerSocket *parent,
- const Name &handshake_name);
-
- ~TLSRTCProducerSocket() = default;
-
- uint32_t produceDatagram(const Name &content_name,
- std::unique_ptr<utils::MemBuf> &&buffer) override;
-
- void accept() override;
-
- int async_accept() override;
-
- using TLSProducerSocket::onInterest;
- using TLSProducerSocket::produce;
-
- protected:
- static int read(BIO *b, char *buf, size_t size, size_t *readbytes);
-
- static int readOld(BIO *h, char *buf, int size);
-
- static int write(BIO *b, const char *buf, size_t size, size_t *written);
-
- static int writeOld(BIO *h, const char *buf, int num);
-};
-
-} // namespace implementation
-
-} // end namespace transport
diff --git a/libtransport/src/implementation/tls_socket_consumer.cc b/libtransport/src/implementation/tls_socket_consumer.cc
deleted file mode 100644
index b368c4b88..000000000
--- a/libtransport/src/implementation/tls_socket_consumer.cc
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * 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/tls_socket_consumer.h>
-#include <openssl/bio.h>
-#include <openssl/ssl.h>
-#include <openssl/tls1.h>
-
-#include <random>
-
-namespace transport {
-namespace implementation {
-
-void TLSConsumerSocket::setInterestPayload(interface::ConsumerSocket &c,
- const core::Interest &interest) {
- Interest &int2 = const_cast<Interest &>(interest);
- random_suffix_ = int2.getName().getSuffix();
-
- if (payload_ != NULL) int2.appendPayload(std::move(payload_));
-}
-
-/* Return the number of read bytes in the return param */
-int readOldTLS(BIO *b, char *buf, int size) {
- if (size < 0) return size;
-
- TLSConsumerSocket *socket;
- socket = (TLSConsumerSocket *)BIO_get_data(b);
-
- std::unique_lock<std::mutex> lck(socket->mtx_);
-
- if (!socket->something_to_read_) {
- if (!socket->transport_protocol_->isRunning()) {
- socket->network_name_.setSuffix(socket->random_suffix_);
- socket->ConsumerSocket::consume(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();
-
- if (chain_size > (size_t)size) {
- read = size_to_read = (size_t)size;
- } else {
- read = size_to_read = chain_size;
- socket->something_to_read_ = false;
- }
-
- while (size_to_read) {
- if (socket->head_->length() < size_to_read) {
- std::memcpy(buf, socket->head_->data(), socket->head_->length());
- size_to_read -= socket->head_->length();
- buf += socket->head_->length();
- socket->head_ = socket->head_->pop();
- } else {
- std::memcpy(buf, socket->head_->data(), size_to_read);
- socket->head_->trimStart(size_to_read);
- size_to_read = 0;
- }
- }
-
- return (int)read;
-}
-
-/* Return the number of read bytes in readbytes */
-int readTLS(BIO *b, char *buf, size_t size, size_t *readbytes) {
- int ret;
-
- if (size > INT_MAX) size = INT_MAX;
-
- ret = readOldTLS(b, buf, (int)size);
-
- if (ret <= 0) {
- *readbytes = 0;
- return ret;
- }
-
- *readbytes = (size_t)ret;
-
- return 1;
-}
-
-/* Return the number of written bytes in the return param */
-int writeOldTLS(BIO *b, const char *buf, int num) {
- TLSConsumerSocket *socket;
- socket = (TLSConsumerSocket *)BIO_get_data(b);
-
- socket->payload_ = utils::MemBuf::copyBuffer(buf, num);
-
- socket->ConsumerSocket::setSocketOption(
- ConsumerCallbacksOptions::INTEREST_OUTPUT,
- (ConsumerInterestCallback)std::bind(
- &TLSConsumerSocket::setInterestPayload, socket, std::placeholders::_1,
- std::placeholders::_2));
-
- return num;
-}
-
-/* Return the number of written bytes in written */
-int writeTLS(BIO *b, const char *buf, size_t size, size_t *written) {
- int ret;
-
- if (size > INT_MAX) size = INT_MAX;
-
- ret = writeOldTLS(b, buf, (int)size);
-
- if (ret <= 0) {
- *written = 0;
- return ret;
- }
-
- *written = (size_t)ret;
-
- return 1;
-}
-
-long ctrlTLS(BIO *b, int cmd, long num, void *ptr) { return 1; }
-
-TLSConsumerSocket::TLSConsumerSocket(interface::ConsumerSocket *consumer_socket,
- int protocol, SSL *ssl)
- : ConsumerSocket(consumer_socket, protocol),
- name_(),
- decrypted_content_(),
- payload_(),
- head_(),
- something_to_read_(false),
- content_downloaded_(false),
- random_suffix_(),
- producer_namespace_(),
- read_callback_decrypted_(),
- mtx_(),
- cv_(),
- async_downloader_tls_() {
- /* Create the (d)TLS state */
- const SSL_METHOD *meth = TLS_client_method();
- ctx_ = SSL_CTX_new(meth);
-
- int result =
- 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.");
- }
-
- SSL_CTX_set_min_proto_version(ctx_, TLS1_3_VERSION);
- SSL_CTX_set_max_proto_version(ctx_, TLS1_3_VERSION);
- SSL_CTX_set_verify(ctx_, SSL_VERIFY_NONE, NULL);
- SSL_CTX_set_ssl_version(ctx_, meth);
-
- ssl_ = ssl;
-
- BIO_METHOD *bio_meth =
- BIO_meth_new(BIO_TYPE_CONNECT, "secure consumer socket");
- BIO_meth_set_read(bio_meth, readOldTLS);
- BIO_meth_set_write(bio_meth, writeOldTLS);
- BIO_meth_set_ctrl(bio_meth, ctrlTLS);
- BIO *bio = BIO_new(bio_meth);
- BIO_set_init(bio, 1);
- BIO_set_data(bio, this);
- SSL_set_bio(ssl_, bio, bio);
-
- std::default_random_engine generator;
- std::uniform_int_distribution<int> distribution(
- 1, std::numeric_limits<uint32_t>::max());
- random_suffix_ = 0;
-
- this->ConsumerSocket::setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK,
- this);
-};
-
-/* 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,
- std::unique_ptr<utils::MemBuf> &&buffer) {
- this->payload_ = std::move(buffer);
-
- this->ConsumerSocket::setSocketOption(
- ConsumerCallbacksOptions::INTEREST_OUTPUT,
- (ConsumerInterestCallback)std::bind(
- &TLSConsumerSocket::setInterestPayload, this, std::placeholders::_1,
- std::placeholders::_2));
-
- return consume(name);
-}
-
-int TLSConsumerSocket::consume(const Name &name) {
- if (transport_protocol_->isRunning()) {
- return CONSUMER_BUSY;
- }
-
- if ((SSL_in_before(this->ssl_) || SSL_in_init(this->ssl_))) {
- throw errors::RuntimeException("Handshake not performed");
- }
-
- return download_content(name);
-}
-
-int TLSConsumerSocket::download_content(const Name &name) {
- network_name_ = name;
- network_name_.setSuffix(0);
- something_to_read_ = false;
- content_downloaded_ = false;
-
- 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_) {
- 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 */
-
- /* ASSERT((result < SSL3_RT_MAX_PLAIN_LENGTH && content_downloaded_) || */
- /* result == SSL3_RT_MAX_PLAIN_LENGTH); */
-
- if (result >= 0) {
- size += result;
- decrypted_content_->append(result);
- } else {
- throw errors::RuntimeException("Unable to download content");
- }
-
- 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. */
- read_callback_decrypted_->readBufferAvailable(
- std::move(decrypted_content_));
- decrypted_content_ = utils::MemBuf::create(buffer_size);
- } else {
- /* 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();
-
- while (decrypted_content_->length()) {
- buffer = nullptr;
- length = 0;
- read_callback_decrypted_->getReadBuffer(&buffer, &length);
-
- if (!buffer || !length) {
- throw errors::RuntimeException(
- "Invalid buffer provided by the application.");
- }
-
- auto to_copy = std::min(decrypted_content_->length(), length);
- std::memcpy(buffer, decrypted_content_->data(), to_copy);
- decrypted_content_->trimStart(to_copy);
- }
-
- read_callback_decrypted_->readDataAvailable(total_length);
- decrypted_content_->clear();
- }
- }
- }
-
- read_callback_decrypted_->readSuccess(size);
-
- return CONSUMER_FINISHED;
-}
-
-void TLSConsumerSocket::registerPrefix(const Prefix &producer_namespace) {
- producer_namespace_ = producer_namespace;
-}
-
-int TLSConsumerSocket::setSocketOption(int socket_option_key,
- ReadCallback *socket_option_value) {
- return rescheduleOnIOService(
- socket_option_key, socket_option_value,
- [this](int socket_option_key, ReadCallback *socket_option_value) -> int {
- switch (socket_option_key) {
- case ConsumerCallbacksOptions::READ_CALLBACK:
- read_callback_decrypted_ = socket_option_value;
- break;
- default:
- return SOCKET_OPTION_NOT_SET;
- }
-
- return SOCKET_OPTION_SET;
- });
-}
-
-void TLSConsumerSocket::getReadBuffer(uint8_t **application_buffer,
- size_t *max_length) {}
-
-void TLSConsumerSocket::readDataAvailable(size_t length) noexcept {}
-
-size_t TLSConsumerSocket::maxBufferSize() const {
- return SSL3_RT_MAX_PLAIN_LENGTH;
-}
-
-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 {
- head_ = std::move(buffer);
- }
-
- something_to_read_ = true;
- cv_.notify_one();
-}
-
-void TLSConsumerSocket::readError(const std::error_code &ec) noexcept {}
-
-void TLSConsumerSocket::readSuccess(std::size_t total_size) noexcept {
- std::unique_lock<std::mutex> lck(this->mtx_);
- content_downloaded_ = true;
- something_to_read_ = true;
- cv_.notify_one();
-}
-
-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
deleted file mode 100644
index a74f1ee10..000000000
--- a/libtransport/src/implementation/tls_socket_consumer.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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/socket_consumer.h>
-#include <implementation/socket_consumer.h>
-#include <openssl/ssl.h>
-
-namespace transport {
-namespace implementation {
-
-class TLSConsumerSocket : public ConsumerSocket,
- public interface::ConsumerSocket::ReadCallback {
- /* Return the number of read bytes in readbytes */
- friend int readTLS(BIO *b, char *buf, size_t size, size_t *readbytes);
-
- /* Return the number of read bytes in the return param */
- friend int readOldTLS(BIO *h, char *buf, int size);
-
- /* Return the number of written bytes in written */
- friend int writeTLS(BIO *b, const char *buf, size_t size, size_t *written);
-
- /* Return the number of written bytes in the return param */
- friend int writeOldTLS(BIO *h, const char *buf, int num);
-
- friend long ctrlTLS(BIO *b, int cmd, long num, void *ptr);
-
- public:
- explicit TLSConsumerSocket(interface::ConsumerSocket *consumer_socket,
- int protocol, SSL *ssl_);
-
- ~TLSConsumerSocket();
-
- int consume(const Name &name, std::unique_ptr<utils::MemBuf> &&buffer);
- int consume(const Name &name) override;
-
- void registerPrefix(const Prefix &producer_namespace);
-
- int setSocketOption(
- int socket_option_key,
- interface::ConsumerSocket::ReadCallback *socket_option_value) override;
-
- using ConsumerSocket::getSocketOption;
- using ConsumerSocket::setSocketOption;
-
- protected:
- /* Callback invoked once an interest has been received and its payload
- * decrypted */
- ConsumerInterestCallback on_interest_input_decrypted_;
- ConsumerInterestCallback on_interest_process_decrypted_;
-
- 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 */
- 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_;
- 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,
- const core::Interest &interest);
-
- virtual void getReadBuffer(uint8_t **application_buffer,
- size_t *max_length) override;
-
- virtual void readDataAvailable(size_t length) noexcept override;
-
- virtual size_t maxBufferSize() const override;
-
- virtual void readBufferAvailable(
- std::unique_ptr<utils::MemBuf> &&buffer) noexcept override;
-
- 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
diff --git a/libtransport/src/implementation/tls_socket_producer.cc b/libtransport/src/implementation/tls_socket_producer.cc
deleted file mode 100644
index 47f3b43a6..000000000
--- a/libtransport/src/implementation/tls_socket_producer.cc
+++ /dev/null
@@ -1,550 +0,0 @@
-/*
- * 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 <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>
-
-namespace transport {
-namespace implementation {
-
-/* Return the number of read bytes in readbytes */
-int TLSProducerSocket::read(BIO *b, char *buf, size_t size, size_t *readbytes) {
- int ret;
-
- if (size > INT_MAX) size = INT_MAX;
-
- ret = TLSProducerSocket::readOld(b, buf, (int)size);
-
- if (ret <= 0) {
- *readbytes = 0;
- return ret;
- }
-
- *readbytes = (size_t)ret;
-
- return 1;
-}
-
-/* Return the number of read bytes in the return param */
-int TLSProducerSocket::readOld(BIO *b, char *buf, int size) {
- TLSProducerSocket *socket;
- socket = (TLSProducerSocket *)BIO_get_data(b);
-
- std::unique_lock<std::mutex> lck(socket->mtx_);
-
- DLOG_IF(INFO, VLOG_IS_ON(4)) << "Start wait on the CV.";
-
- if (!socket->something_to_read_) {
- (socket->cv_).wait(lck);
- }
-
- DLOG_IF(INFO, VLOG_IS_ON(4)) << "CV unlocked.";
-
- /* 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 = (int)membuf->length();
- socket->something_to_read_ = false;
- }
-
- std::memcpy(buf, membuf->data(), size_to_read);
- membuf->trimStart(size_to_read);
-
- return size_to_read;
-}
-
-/* Return the number of written bytes in written */
-int TLSProducerSocket::write(BIO *b, const char *buf, size_t size,
- size_t *written) {
- int ret;
-
- if (size > INT_MAX) size = INT_MAX;
-
- ret = TLSProducerSocket::writeOld(b, buf, (int)size);
-
- if (ret <= 0) {
- *written = 0;
- return ret;
- }
-
- *written = (size_t)ret;
-
- return 1;
-}
-
-/* Return the number of written bytes in the return param */
-int TLSProducerSocket::writeOld(BIO *b, const char *buf, int num) {
- TLSProducerSocket *socket;
- socket = (TLSProducerSocket *)BIO_get_data(b);
-
- if (socket->getHandshakeState() != SERVER_FINISHED && socket->first_) {
- uint32_t making_manifest = socket->parent_->making_manifest_;
-
- //! socket->tls_chunks_ corresponds to is_last
- socket->tls_chunks_--;
- socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
- 0U);
- socket->parent_->ProducerSocket::produceStream(
- socket->name_, (const uint8_t *)buf, num, socket->tls_chunks_ == 0,
- socket->last_segment_);
- socket->parent_->setSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
- making_manifest);
- socket->first_ = false;
- } else {
- socket->still_writing_ = true;
-
- 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_--;
-
- socket->last_segment_ += socket->ProducerSocket::produceStream(
- socket->name_, std::move(mbuf), socket->tls_chunks_ == 0,
- socket->last_segment_);
-
- 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->operator()(*socket->getInterface(),
- std::error_code(), 0);
- }
- });
- }
-
- return num;
-}
-
-TLSProducerSocket::TLSProducerSocket(interface::ProducerSocket *producer_socket,
- P2PSecureProducerSocket *parent,
- const Name &handshake_name)
- : ProducerSocket(producer_socket,
- ProductionProtocolAlgorithms::BYTE_STREAM),
- on_content_produced_application_(),
- mtx_(),
- cv_(),
- something_to_read_(false),
- handshake_state_(UNINITIATED),
- name_(),
- handshake_packet_(),
- last_segment_(0),
- parent_(parent),
- first_(true),
- handshake_name_(handshake_name),
- tls_chunks_(0),
- to_call_oncontentproduced_(0),
- still_writing_(false),
- encryption_thread_() {
- const SSL_METHOD *meth = TLS_server_method();
- ctx_ = SSL_CTX_new(meth);
-
- /* 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_);
-
- int result =
- 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.");
- }
-
- // We force it to be TLS 1.3
- SSL_CTX_set_min_proto_version(ctx_, TLS1_3_VERSION);
- SSL_CTX_set_max_proto_version(ctx_, TLS1_3_VERSION);
- SSL_CTX_set_verify(ctx_, SSL_VERIFY_NONE, NULL);
- SSL_CTX_set_num_tickets(ctx_, 0);
-
- result = SSL_CTX_add_custom_ext(
- ctx_, 100, SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
- TLSProducerSocket::addHicnKeyIdCb, TLSProducerSocket::freeHicnKeyIdCb,
- 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) */
- BIO_METHOD *bio_meth =
- BIO_meth_new(BIO_TYPE_ACCEPT, "secure producer socket");
- BIO_meth_set_read(bio_meth, TLSProducerSocket::readOld);
- BIO_meth_set_write(bio_meth, TLSProducerSocket::writeOld);
- BIO_meth_set_ctrl(bio_meth, TLSProducerSocket::ctrl);
- BIO *bio = BIO_new(bio_meth);
- 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. */
- 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(
- &TLSProducerSocket::onContentProduced, this, std::placeholders::_1,
- std::placeholders::_2, std::placeholders::_3));
-}
-
-/* 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() {
- 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");
- }
-
- 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(*handshake_packet_));
- handshake_packet_.reset();
- on_interest_process_decrypted->operator()(*getInterface(), inter);
- } else {
- throw errors::RuntimeException(
- "On interest process unset: unable to perform handshake");
- }
-
- handshake_state_ = SERVER_FINISHED;
- DLOG_IF(INFO, VLOG_IS_ON(2)) << "Handshake performed!";
-}
-
-int TLSProducerSocket::async_accept() {
- if (!async_thread_.stopped()) {
- async_thread_.add([this]() { this->accept(); });
- } else {
- throw errors::RuntimeException(
- "Async thread not running: unable to perform handshake");
- }
-
- return 1;
-}
-
-void TLSProducerSocket::onInterest(ProducerSocket &p, Interest &interest) {
- 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;
-
- cv_.notify_one();
- return;
- } else if (handshake_state == SERVER_FINISHED) {
- // interest.separateHeaderPayload();
- handshake_packet_ = interest.acquireMemBufReference();
- something_to_read_ = true;
-
- if (interest.getPayload()->length() > 0) {
- SSL_read(
- ssl_,
- const_cast<unsigned char *>(interest.getPayload()->writableData()),
- (int)interest.getPayload()->length());
- }
-
- ProducerInterestCallback *on_interest_input_decrypted;
- getSocketOption(ProducerCallbacksOptions::INTEREST_INPUT,
- &on_interest_input_decrypted);
-
- if (*on_interest_input_decrypted)
- (*on_interest_input_decrypted)(*getInterface(), interest);
- }
-}
-
-void TLSProducerSocket::cacheMiss(interface::ProducerSocket &p,
- Interest &interest) {
- HandshakeState handshake_state = getHandshakeState();
-
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "On cache miss in TLS socket producer.";
-
- if (handshake_state == CLIENT_HELLO) {
- std::unique_lock<std::mutex> lck(mtx_);
-
- // interest.separateHeaderPayload();
- handshake_packet_ = interest.acquireMemBufReference();
- something_to_read_ = true;
- handshake_state_ = CLIENT_FINISHED;
-
- cv_.notify_one();
- } else if (handshake_state == SERVER_FINISHED) {
- // interest.separateHeaderPayload();
- handshake_packet_ = interest.acquireMemBufReference();
- something_to_read_ = true;
-
- if (interest.getPayload()->length() > 0) {
- SSL_read(
- ssl_,
- const_cast<unsigned char *>(interest.getPayload()->writableData()),
- (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::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_ = portal_->getServedNamespaces().begin()->mapName(content_name);
- tls_chunks_ = to_call_oncontentproduced_ =
- (int)ceil((float)buf_size / (float)SSL3_RT_MAX_PLAIN_LENGTH);
-
- if (!is_last) {
- tls_chunks_++;
- }
-
- last_segment_ = start_offset;
-
- 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
-
- return 0;
-}
-
-long TLSProducerSocket::ctrl(BIO *b, int cmd, long num, void *ptr) {
- if (cmd == BIO_CTRL_FLUSH) {
- }
-
- return 1;
-}
-
-int TLSProducerSocket::addHicnKeyIdCb(SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char **out, size_t *outlen,
- X509 *x, size_t chainidx, int *al,
- void *add_arg) {
- TLSProducerSocket *socket = reinterpret_cast<TLSProducerSocket *>(add_arg);
-
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "On addHicnKeyIdCb, for the prefix registration.";
-
- if (ext_type == 100) {
- auto &prefix = *socket->parent_->portal_->getServedNamespaces().begin();
- 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;
-
- ip_prefix_t *out_ip = (ip_prefix_t *)malloc(sizeof(ip_prefix_t));
- out_ip->family = inet_family;
- out_ip->len = prefix_len_bits + 32;
- u8 *out_ip_buf = const_cast<u8 *>(
- ip_address_get_buffer(&(out_ip->address), inet_family));
- *out = reinterpret_cast<unsigned char *>(out_ip);
-
- RAND_bytes((unsigned char *)&socket->key_id_, 4);
-
- memcpy(out_ip_buf, ip_address_get_buffer(&(ip_prefix.address), inet_family),
- prefix_len_bytes);
- memcpy((out_ip_buf + prefix_len_bytes), &socket->key_id_, 4);
- *outlen = sizeof(ip_prefix_t);
-
- ip_address_t mask = {};
- ip_address_t keyId_component = {};
- u32 *mask_buf;
- u32 *keyId_component_buf;
-
- switch (inet_family) {
- case AF_INET:
- mask_buf = &(mask.v4.as_u32);
- keyId_component_buf = &(keyId_component.v4.as_u32);
- break;
- case AF_INET6:
- mask_buf = mask.v6.as_u32;
- keyId_component_buf = keyId_component.v6.as_u32;
- break;
- default:
- throw errors::RuntimeException("Unknown protocol");
- }
-
- if (prefix_len_bits > (inet_family == AF_INET6 ? IPV6_ADDR_LEN_BITS - 32
- : IPV4_ADDR_LEN_BITS - 32))
- throw errors::RuntimeException(
- "Not enough space in the content name to add key_id");
-
- mask_buf[prefix_len_u32] = 0xffffffff;
- keyId_component_buf[prefix_len_u32] = socket->key_id_;
- socket->last_segment_ = 0;
-
- socket->on_interest_process_decrypted_ =
- socket->parent_->on_interest_process_decrypted_;
-
- socket->registerPrefix(
- Prefix(prefix.getName(Name(inet_family, (uint8_t *)&mask),
- Name(inet_family, (uint8_t *)&keyId_component),
- prefix.getName()),
- out_ip->len));
- socket->connect();
- }
- return 1;
-}
-
-void TLSProducerSocket::freeHicnKeyIdCb(SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char *out,
- void *add_arg) {
- free(const_cast<unsigned char *>(out));
-}
-
-int TLSProducerSocket::parseHicnKeyIdCb(SSL *s, unsigned int ext_type,
- unsigned int context,
- const unsigned char *in, size_t inlen,
- X509 *x, size_t chainidx, int *al,
- void *add_arg) {
- return 1;
-}
-
-int TLSProducerSocket::setSocketOption(
- int socket_option_key, ProducerInterestCallback socket_option_value) {
- return rescheduleOnIOService(
- socket_option_key, socket_option_value,
- [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;
- break;
-
- case ProducerCallbacksOptions::INTEREST_DROP:
- on_interest_dropped_input_buffer_ = socket_option_value;
- break;
-
- case ProducerCallbacksOptions::INTEREST_PASS:
- on_interest_inserted_input_buffer_ = socket_option_value;
- break;
-
- case ProducerCallbacksOptions::CACHE_HIT:
- on_interest_satisfied_output_buffer_ = socket_option_value;
- break;
-
- case ProducerCallbacksOptions::CACHE_MISS:
- on_interest_process_decrypted_ = socket_option_value;
- break;
-
- default:
- result = SOCKET_OPTION_NOT_SET;
- break;
- }
-
- return result;
- });
-}
-
-int TLSProducerSocket::setSocketOption(
- int socket_option_key, ProducerContentCallback socket_option_value) {
- return rescheduleOnIOService(
- socket_option_key, socket_option_value,
- [this](int socket_option_key,
- ProducerContentCallback socket_option_value) -> int {
- switch (socket_option_key) {
- case ProducerCallbacksOptions::CONTENT_PRODUCED:
- on_content_produced_application_ = socket_option_value;
- break;
-
- default:
- return SOCKET_OPTION_NOT_SET;
- }
-
- return SOCKET_OPTION_SET;
- });
-}
-
-int TLSProducerSocket::getSocketOption(
- int socket_option_key, ProducerContentCallback **socket_option_value) {
- return rescheduleOnIOService(
- 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;
- });
-}
-
-} // namespace implementation
-} // namespace transport
diff --git a/libtransport/src/implementation/tls_socket_producer.h b/libtransport/src/implementation/tls_socket_producer.h
deleted file mode 100644
index 0e958b321..000000000
--- a/libtransport/src/implementation/tls_socket_producer.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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 <implementation/socket_producer.h>
-#include <openssl/ssl.h>
-
-#include <condition_variable>
-#include <mutex>
-
-namespace transport {
-namespace implementation {
-
-class P2PSecureProducerSocket;
-
-class TLSProducerSocket : virtual public ProducerSocket {
- friend class P2PSecureProducerSocket;
-
- public:
- explicit TLSProducerSocket(interface::ProducerSocket *producer_socket,
- P2PSecureProducerSocket *parent,
- const Name &handshake_name);
-
- ~TLSProducerSocket();
-
- 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 produceStream(const Name &content_name,
- std::unique_ptr<utils::MemBuf> &&buffer,
- bool is_last = true,
- uint32_t start_offset = 0) override;
-
- virtual void accept();
-
- virtual int async_accept();
-
- virtual int setSocketOption(
- int socket_option_key,
- ProducerInterestCallback socket_option_value) override;
-
- virtual int setSocketOption(
- int socket_option_key,
- ProducerContentCallback socket_option_value) override;
-
- virtual int getSocketOption(
- int socket_option_key,
- ProducerContentCallback **socket_option_value) override;
-
- int getSocketOption(int socket_option_key,
- ProducerContentCallback &socket_option_value);
-
- int getSocketOption(int socket_option_key,
- ProducerInterestCallback &socket_option_value);
-
- using ProducerSocket::getSocketOption;
- // 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 handshake_packet_;
- std::unique_ptr<utils::MemBuf> head_;
- std::uint32_t last_segment_;
- 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 */
- static int read(BIO *b, char *buf, size_t size, size_t *readbytes);
-
- /* Return the number of read bytes in the return param */
- static int readOld(BIO *h, char *buf, int size);
-
- /* Return the number of written bytes in written */
- static int write(BIO *b, const char *buf, size_t size, size_t *written);
-
- /* Return the number of written bytes in the return param */
- static int writeOld(BIO *h, const char *buf, int num);
-
- static long ctrl(BIO *b, int cmd, long num, void *ptr);
-
- static int addHicnKeyIdCb(SSL *s, unsigned int ext_type, unsigned int context,
- const unsigned char **out, size_t *outlen, X509 *x,
- size_t chainidx, int *al, void *add_arg);
-
- static void freeHicnKeyIdCb(SSL *s, unsigned int ext_type,
- unsigned int context, const unsigned char *out,
- void *add_arg);
-
- static int parseHicnKeyIdCb(SSL *s, unsigned int ext_type,
- unsigned int context, const unsigned char *in,
- size_t inlen, X509 *x, size_t chainidx, int *al,
- void *add_arg);
-
- 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 0a0603ac8..bf8f8dcf8 100644
--- a/libtransport/src/interfaces/CMakeLists.txt
+++ b/libtransport/src/interfaces/CMakeLists.txt
@@ -19,20 +19,4 @@ list(APPEND SOURCE_FILES
${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_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_socket_producer.h
- ${CMAKE_CURRENT_SOURCE_DIR}/tls_socket_consumer.h
- )
-endif()
-
set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE)
diff --git a/libtransport/src/interfaces/global_configuration.cc b/libtransport/src/interfaces/global_configuration.cc
index cecdacc07..f8e7a90c3 100644
--- a/libtransport/src/interfaces/global_configuration.cc
+++ b/libtransport/src/interfaces/global_configuration.cc
@@ -14,6 +14,7 @@
*/
#include <core/global_configuration.h>
+#include <core/global_workers.h>
#include <glog/logging.h>
#include <hicn/transport/interfaces/global_conf_interface.h>
@@ -23,10 +24,29 @@ namespace transport {
namespace interface {
namespace global_config {
-void parseConfigurationFile(const std::string& path) {
+GlobalConfigInterface::GlobalConfigInterface() { libtransportConfigInit(); }
+
+GlobalConfigInterface::~GlobalConfigInterface() {
+ libtransportConfigTerminate();
+}
+
+void GlobalConfigInterface::parseConfigurationFile(
+ const std::string &path) const {
core::GlobalConfiguration::getInstance().parseConfiguration(path);
}
+void GlobalConfigInterface::libtransportConfigInit() const {
+ // nothing to do
+}
+
+void GlobalConfigInterface::libtransportConfigTerminate() const {
+ // cleanup workers
+ auto &workers = core::GlobalWorkers::getInstance().getWorkers();
+ for (auto &worker : workers) {
+ worker.stop();
+ }
+}
+
void ConfigurationObject::get() {
std::error_code ec;
core::GlobalConfiguration::getInstance().getConfiguration(*this, ec);
diff --git a/libtransport/src/interfaces/p2psecure_socket_consumer.cc b/libtransport/src/interfaces/p2psecure_socket_consumer.cc
deleted file mode 100644
index e329a50f1..000000000
--- a/libtransport/src/interfaces/p2psecure_socket_consumer.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 <hicn/transport/interfaces/p2psecure_socket_consumer.h>
-#include <implementation/p2psecure_socket_consumer.h>
-
-namespace transport {
-namespace interface {
-
-P2PSecureConsumerSocket::P2PSecureConsumerSocket(int handshake_protocol,
- int transport_protocol)
- : ConsumerSocket() {
- socket_ = std::unique_ptr<implementation::ConsumerSocket>(
- new implementation::P2PSecureConsumerSocket(this, handshake_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
-} // namespace transport
diff --git a/libtransport/src/interfaces/p2psecure_socket_producer.cc b/libtransport/src/interfaces/p2psecure_socket_producer.cc
deleted file mode 100644
index 5f98302d0..000000000
--- a/libtransport/src/interfaces/p2psecure_socket_producer.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 <hicn/transport/interfaces/p2psecure_socket_producer.h>
-#include <implementation/p2psecure_socket_producer.h>
-
-namespace transport {
-namespace interface {
-
-P2PSecureProducerSocket::P2PSecureProducerSocket() {
- socket_ = std::make_unique<implementation::P2PSecureProducerSocket>(this);
-}
-
-P2PSecureProducerSocket::P2PSecureProducerSocket(bool rtc,
- std::string &keystore_path,
- std::string &keystore_pwd) {
- socket_ = std::make_unique<implementation::P2PSecureProducerSocket>(
- this, rtc, keystore_path, keystore_pwd);
-}
-
-} // namespace interface
-} // namespace transport
diff --git a/libtransport/src/interfaces/portal.cc b/libtransport/src/interfaces/portal.cc
index 84634a282..898766c50 100644
--- a/libtransport/src/interfaces/portal.cc
+++ b/libtransport/src/interfaces/portal.cc
@@ -35,10 +35,10 @@ class Portal::Impl {
return portal_->interestIsPending(name);
}
- void sendInterest(core::Interest::Ptr &&interest,
+ void sendInterest(core::Interest::Ptr &interest, uint32_t lifetime,
OnContentObjectCallback &&on_content_object_callback,
OnInterestTimeoutCallback &&on_interest_timeout_callback) {
- portal_->sendInterest(std::move(interest),
+ portal_->sendInterest(interest, lifetime,
std::move(on_content_object_callback),
std::move(on_interest_timeout_callback));
}
@@ -86,10 +86,10 @@ bool Portal::interestIsPending(const core::Name &name) {
}
void Portal::sendInterest(
- core::Interest::Ptr &&interest,
+ core::Interest::Ptr &interest, uint32_t lifetime,
OnContentObjectCallback &&on_content_object_callback,
OnInterestTimeoutCallback &&on_interest_timeout_callback) {
- implementation_->sendInterest(std::move(interest),
+ implementation_->sendInterest(interest, lifetime,
std::move(on_content_object_callback),
std::move(on_interest_timeout_callback));
}
diff --git a/libtransport/src/interfaces/socket_consumer.cc b/libtransport/src/interfaces/socket_consumer.cc
index 747dc0974..cc496c8a5 100644
--- a/libtransport/src/interfaces/socket_consumer.cc
+++ b/libtransport/src/interfaces/socket_consumer.cc
@@ -102,6 +102,12 @@ int ConsumerSocket::setSocketOption(int socket_option_key,
int ConsumerSocket::setSocketOption(
int socket_option_key,
+ const std::shared_ptr<auth::Signer> &socket_option_value) {
+ return socket_->setSocketOption(socket_option_key, socket_option_value);
+}
+
+int ConsumerSocket::setSocketOption(
+ int socket_option_key,
const std::shared_ptr<auth::Verifier> &socket_option_value) {
return socket_->setSocketOption(socket_option_key, socket_option_value);
}
@@ -163,6 +169,11 @@ int ConsumerSocket::getSocketOption(int socket_option_key,
}
int ConsumerSocket::getSocketOption(
+ int socket_option_key, std::shared_ptr<auth::Signer> &socket_option_value) {
+ return socket_->getSocketOption(socket_option_key, socket_option_value);
+}
+
+int ConsumerSocket::getSocketOption(
int socket_option_key,
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 10613c0e1..2155ebd78 100644
--- a/libtransport/src/interfaces/socket_producer.cc
+++ b/libtransport/src/interfaces/socket_producer.cc
@@ -148,6 +148,12 @@ int ProducerSocket::setSocketOption(
return socket_->setSocketOption(socket_option_key, socket_option_value);
}
+int ProducerSocket::setSocketOption(
+ int socket_option_key,
+ const std::shared_ptr<auth::Verifier> &socket_option_value) {
+ return socket_->setSocketOption(socket_option_key, socket_option_value);
+}
+
int ProducerSocket::setSocketOption(int socket_option_key,
Packet::Format socket_option_value) {
return socket_->setSocketOption(socket_option_key, socket_option_value);
@@ -194,6 +200,12 @@ int ProducerSocket::getSocketOption(
return socket_->getSocketOption(socket_option_key, socket_option_value);
}
+int ProducerSocket::getSocketOption(
+ int socket_option_key,
+ std::shared_ptr<auth::Verifier> &socket_option_value) {
+ return socket_->getSocketOption(socket_option_key, socket_option_value);
+}
+
int ProducerSocket::getSocketOption(int socket_option_key,
Packet::Format &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
deleted file mode 100644
index 6bf1b011c..000000000
--- a/libtransport/src/interfaces/tls_rtc_socket_producer.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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/tls_rtc_socket_producer.h>
-#include <interfaces/tls_rtc_socket_producer.h>
-
-namespace transport {
-namespace interface {
-
-TLSRTCProducerSocket::TLSRTCProducerSocket(
- implementation::TLSRTCProducerSocket *implementation) {
- socket_ =
- std::unique_ptr<implementation::TLSRTCProducerSocket>(implementation);
-}
-
-TLSRTCProducerSocket::~TLSRTCProducerSocket() { socket_.release(); }
-
-} // namespace interface
-} // namespace transport
diff --git a/libtransport/src/interfaces/tls_rtc_socket_producer.h b/libtransport/src/interfaces/tls_rtc_socket_producer.h
deleted file mode 100644
index b8b6ec298..000000000
--- a/libtransport/src/interfaces/tls_rtc_socket_producer.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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/socket_producer.h>
-
-namespace transport {
-
-namespace implementation {
-class TLSRTCProducerSocket;
-}
-
-namespace interface {
-
-class TLSRTCProducerSocket : public ProducerSocket {
- public:
- TLSRTCProducerSocket(implementation::TLSRTCProducerSocket *implementation);
-
- ~TLSRTCProducerSocket();
-};
-
-} // namespace interface
-} // end namespace transport
diff --git a/libtransport/src/interfaces/tls_socket_consumer.cc b/libtransport/src/interfaces/tls_socket_consumer.cc
deleted file mode 100644
index 24060d1d8..000000000
--- a/libtransport/src/interfaces/tls_socket_consumer.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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/tls_socket_consumer.h>
-#include <interfaces/tls_socket_consumer.h>
-
-namespace transport {
-namespace interface {
-
-TLSConsumerSocket::TLSConsumerSocket(
- implementation::TLSConsumerSocket *implementation) {
- socket_ = std::unique_ptr<implementation::TLSConsumerSocket>(implementation);
-}
-
-TLSConsumerSocket::~TLSConsumerSocket() { socket_.release(); }
-
-} // namespace interface
-} // namespace transport
diff --git a/libtransport/src/interfaces/tls_socket_consumer.h b/libtransport/src/interfaces/tls_socket_consumer.h
deleted file mode 100644
index 242dc91a5..000000000
--- a/libtransport/src/interfaces/tls_socket_consumer.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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/socket_consumer.h>
-
-namespace transport {
-
-namespace implementation {
-class TLSConsumerSocket;
-}
-
-namespace interface {
-
-class TLSConsumerSocket : public ConsumerSocket {
- public:
- TLSConsumerSocket(implementation::TLSConsumerSocket *implementation);
- ~TLSConsumerSocket();
-};
-
-} // namespace interface
-
-} // end namespace transport
diff --git a/libtransport/src/interfaces/tls_socket_producer.cc b/libtransport/src/interfaces/tls_socket_producer.cc
deleted file mode 100644
index b2b9e723a..000000000
--- a/libtransport/src/interfaces/tls_socket_producer.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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/tls_socket_producer.h>
-#include <interfaces/tls_socket_producer.h>
-
-namespace transport {
-namespace interface {
-
-TLSProducerSocket::TLSProducerSocket(
- implementation::TLSProducerSocket *implementation) {
- socket_ = std::unique_ptr<implementation::TLSProducerSocket>(implementation);
-}
-
-TLSProducerSocket::~TLSProducerSocket() { socket_.release(); }
-
-} // namespace interface
-} // namespace transport
diff --git a/libtransport/src/interfaces/tls_socket_producer.h b/libtransport/src/interfaces/tls_socket_producer.h
deleted file mode 100644
index 9b31cb483..000000000
--- a/libtransport/src/interfaces/tls_socket_producer.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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/socket_producer.h>
-
-namespace transport {
-
-namespace implementation {
-class TLSProducerSocket;
-}
-
-namespace interface {
-
-class TLSProducerSocket : public ProducerSocket {
- public:
- TLSProducerSocket(implementation::TLSProducerSocket *implementation);
- ~TLSProducerSocket();
-};
-
-} // namespace interface
-
-} // end namespace transport
diff --git a/libtransport/src/io_modules/CMakeLists.txt b/libtransport/src/io_modules/CMakeLists.txt
index f4143de04..f1a27d3cb 100644
--- a/libtransport/src/io_modules/CMakeLists.txt
+++ b/libtransport/src/io_modules/CMakeLists.txt
@@ -15,7 +15,7 @@
##############################################################
# Android case: no submodules
##############################################################
-if (${CMAKE_SYSTEM_NAME} MATCHES Android)
+if (${CMAKE_SYSTEM_NAME} MATCHES Android OR ${CMAKE_SYSTEM_NAME} MATCHES iOS)
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/hicn-light-ng/hicn_forwarder_module.cc
)
diff --git a/libtransport/src/io_modules/forwarder/CMakeLists.txt b/libtransport/src/io_modules/forwarder/CMakeLists.txt
index 3922316d3..2235d842e 100644
--- a/libtransport/src/io_modules/forwarder/CMakeLists.txt
+++ b/libtransport/src/io_modules/forwarder/CMakeLists.txt
@@ -17,7 +17,6 @@ list(APPEND MODULE_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/errors.h
${CMAKE_CURRENT_SOURCE_DIR}/forwarder_module.h
${CMAKE_CURRENT_SOURCE_DIR}/forwarder.h
- ${CMAKE_CURRENT_SOURCE_DIR}/global_counter.h
)
list(APPEND MODULE_SOURCE_FILES
diff --git a/libtransport/src/io_modules/forwarder/forwarder.cc b/libtransport/src/io_modules/forwarder/forwarder.cc
index 3ae5bf397..bfe4dd5de 100644
--- a/libtransport/src/io_modules/forwarder/forwarder.cc
+++ b/libtransport/src/io_modules/forwarder/forwarder.cc
@@ -14,12 +14,12 @@
*/
#include <core/global_configuration.h>
+#include <core/global_id_counter.h>
#include <core/local_connector.h>
#include <core/udp_connector.h>
#include <core/udp_listener.h>
#include <glog/logging.h>
#include <io_modules/forwarder/forwarder.h>
-#include <io_modules/forwarder/global_id_counter.h>
namespace transport {
@@ -90,11 +90,13 @@ Connector::Id Forwarder::registerLocalConnector(
asio::io_service &io_service,
Connector::PacketReceivedCallback &&receive_callback,
Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_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, sent_callback, nullptr, reconnect_callback);
+ io_service, std::move(receive_callback), std::move(sent_callback),
+ std::move(close_callback), std::move(reconnect_callback));
connector->setConnectorId(id);
local_connectors_.emplace(id, std::move(connector));
return id;
@@ -150,34 +152,13 @@ void Forwarder::onPacketReceived(Connector *connector,
return;
}
- for (auto &packet_buffer_ptr : packets) {
- auto &packet_buffer = *packet_buffer_ptr;
-
- // 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 {
- LOG(ERROR) << "Error sending packet to local connector. is_interest = "
- << is_interest << " - is_producer = " << is_producer;
- }
- }
+ for (auto &c : local_connectors_) {
+ c.second->receive(packets);
+ }
- // PCS Lookup + FIB lookup. Skip for now
+ // PCS Lookup + FIB lookup. Skip for now
- // Forward packet to local connectors
- }
+ // Forward packet to local connectors
}
void Forwarder::send(Packet &packet) {
@@ -304,4 +285,4 @@ void Forwarder::parseForwarderConfiguration(
}
} // namespace core
-} // namespace transport \ No newline at end of file
+} // namespace transport
diff --git a/libtransport/src/io_modules/forwarder/forwarder.h b/libtransport/src/io_modules/forwarder/forwarder.h
index 38b4260b3..9ad989fcd 100644
--- a/libtransport/src/io_modules/forwarder/forwarder.h
+++ b/libtransport/src/io_modules/forwarder/forwarder.h
@@ -47,6 +47,7 @@ class Forwarder {
asio::io_service &io_service,
Connector::PacketReceivedCallback &&receive_callback,
Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_callback,
Connector::OnReconnectCallback &&reconnect_callback);
Forwarder &deleteConnector(Connector::Id id);
diff --git a/libtransport/src/io_modules/forwarder/forwarder_module.cc b/libtransport/src/io_modules/forwarder/forwarder_module.cc
index 0ced84ab4..77d2b5e6a 100644
--- a/libtransport/src/io_modules/forwarder/forwarder_module.cc
+++ b/libtransport/src/io_modules/forwarder/forwarder_module.cc
@@ -37,8 +37,6 @@ void ForwarderModule::send(Packet &packet) {
forwarder_.send(packet);
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "Sending from " << connector_id_ << " to " << 1 - connector_id_;
-
- // local_faces_.at(1 - local_id_).onPacket(packet);
}
void ForwarderModule::send(const utils::MemBuf::Ptr &buffer) {
@@ -58,12 +56,13 @@ void ForwarderModule::closeConnection() {
void ForwarderModule::init(Connector::PacketReceivedCallback &&receive_callback,
Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_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(sent_callback),
- std::move(reconnect_callback));
+ std::move(close_callback), std::move(reconnect_callback));
name_ = app_name;
}
diff --git a/libtransport/src/io_modules/forwarder/forwarder_module.h b/libtransport/src/io_modules/forwarder/forwarder_module.h
index 52a12b67e..a48701161 100644
--- a/libtransport/src/io_modules/forwarder/forwarder_module.h
+++ b/libtransport/src/io_modules/forwarder/forwarder_module.h
@@ -44,6 +44,7 @@ class ForwarderModule : public IoModule {
void init(Connector::PacketReceivedCallback &&receive_callback,
Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name = "Libtransport") override;
diff --git a/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.cc b/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.cc
index f67bd9447..95f04822f 100644
--- a/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.cc
+++ b/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.cc
@@ -100,12 +100,13 @@ void HicnForwarderModule::closeConnection() {
void HicnForwarderModule::init(
Connector::PacketReceivedCallback &&receive_callback,
Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service, const std::string &app_name) {
if (!connector_) {
connector_.reset(new UdpTunnelConnector(
io_service, std::move(receive_callback), std::move(sent_callback),
- nullptr, std::move(reconnect_callback)));
+ std::move(close_callback), std::move(reconnect_callback)));
}
}
@@ -130,7 +131,7 @@ bool HicnForwarderModule::isControlMessage(utils::MemBuf &packet_buffer) {
*/
utils::MemBuf::Ptr HicnForwarderModule::createCommandRoute(
std::unique_ptr<sockaddr> &&addr, uint8_t prefix_length) {
- utils::MemBuf::Ptr ret = utils::MemBuf::create(sizeof(msg_route_add_t));
+ auto ret = PacketManager<>::getInstance().getMemBuf();
auto command = reinterpret_cast<msg_route_add_t *>(ret->writableData());
ret->append(sizeof(msg_route_add_t));
std::memset(command, 0, sizeof(*command));
@@ -170,8 +171,7 @@ utils::MemBuf::Ptr HicnForwarderModule::createCommandRoute(
}
utils::MemBuf::Ptr HicnForwarderModule::createCommandDeleteConnection() {
- utils::MemBuf::Ptr ret =
- utils::MemBuf::create(sizeof(msg_connection_remove_t));
+ auto ret = PacketManager<>::getInstance().getMemBuf();
auto command =
reinterpret_cast<msg_connection_remove_t *>(ret->writableData());
ret->append(sizeof(msg_connection_remove_t));
@@ -194,8 +194,7 @@ utils::MemBuf::Ptr HicnForwarderModule::createCommandDeleteConnection() {
}
utils::MemBuf::Ptr HicnForwarderModule::createCommandMapmeSendUpdate() {
- utils::MemBuf::Ptr ret =
- utils::MemBuf::create(sizeof(msg_mapme_send_update_t));
+ auto ret = PacketManager<>::getInstance().getMemBuf();
auto command =
reinterpret_cast<msg_mapme_send_update_t *>(ret->writableData());
ret->append(sizeof(msg_mapme_send_update_t));
@@ -217,7 +216,7 @@ utils::MemBuf::Ptr HicnForwarderModule::createCommandMapmeSendUpdate() {
utils::MemBuf::Ptr HicnForwarderModule::createCommandSetForwardingStrategy(
std::unique_ptr<sockaddr> &&addr, uint32_t prefix_len,
std::string strategy) {
- utils::MemBuf::Ptr ret = utils::MemBuf::create(sizeof(msg_strategy_set_t));
+ auto ret = PacketManager<>::getInstance().getMemBuf();
auto command = reinterpret_cast<msg_strategy_set_t *>(ret->writableData());
ret->append(sizeof(msg_strategy_set_t));
std::memset(command, 0, sizeof(*command));
diff --git a/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.h b/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.h
index 0bf82757d..7f0e7aca8 100644
--- a/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.h
+++ b/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.h
@@ -64,6 +64,7 @@ class HicnForwarderModule : public IoModule {
void init(Connector::PacketReceivedCallback &&receive_callback,
Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name = "Libtransport") override;
diff --git a/libtransport/src/io_modules/loopback/loopback_module.cc b/libtransport/src/io_modules/loopback/loopback_module.cc
index 5b7ed5f61..a7f30eb26 100644
--- a/libtransport/src/io_modules/loopback/loopback_module.cc
+++ b/libtransport/src/io_modules/loopback/loopback_module.cc
@@ -58,6 +58,7 @@ void LoopbackModule::closeConnection() {
void LoopbackModule::init(Connector::PacketReceivedCallback &&receive_callback,
Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name) {
@@ -66,7 +67,7 @@ void LoopbackModule::init(Connector::PacketReceivedCallback &&receive_callback,
local_faces_.emplace(
local_faces_.begin() + local_id_,
new LocalConnector(io_service, std::move(receive_callback),
- std::move(sent_callback), nullptr,
+ std::move(sent_callback), std::move(close_callback),
std::move(reconnect_callback)));
}
}
diff --git a/libtransport/src/io_modules/loopback/loopback_module.h b/libtransport/src/io_modules/loopback/loopback_module.h
index 2779ae7e3..d51f237f4 100644
--- a/libtransport/src/io_modules/loopback/loopback_module.h
+++ b/libtransport/src/io_modules/loopback/loopback_module.h
@@ -42,6 +42,7 @@ class LoopbackModule : public IoModule {
void init(Connector::PacketReceivedCallback &&receive_callback,
Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name = "Libtransport") override;
diff --git a/libtransport/src/io_modules/memif/vpp_forwarder_module.cc b/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
index 65260077a..c096a71b8 100644
--- a/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
+++ b/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
@@ -50,13 +50,14 @@ VPPForwarderModule::~VPPForwarderModule() {}
void VPPForwarderModule::init(
Connector::PacketReceivedCallback &&receive_callback,
Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service, const std::string &app_name) {
if (!connector_) {
connector_ = std::make_unique<MemifConnector>(
std::move(receive_callback), std::move(sent_callback),
- Connector::OnCloseCallback(0), std::move(reconnect_callback),
- io_service, app_name);
+ std::move(close_callback), std::move(reconnect_callback), io_service,
+ app_name);
}
}
diff --git a/libtransport/src/io_modules/memif/vpp_forwarder_module.h b/libtransport/src/io_modules/memif/vpp_forwarder_module.h
index 162ee0ca5..5a5358078 100644
--- a/libtransport/src/io_modules/memif/vpp_forwarder_module.h
+++ b/libtransport/src/io_modules/memif/vpp_forwarder_module.h
@@ -48,6 +48,7 @@ class VPPForwarderModule : public IoModule {
void init(Connector::PacketReceivedCallback &&receive_callback,
Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name = "Libtransport") override;
diff --git a/libtransport/src/protocols/byte_stream_reassembly.cc b/libtransport/src/protocols/byte_stream_reassembly.cc
index 3278595b7..b9eaf3bec 100644
--- a/libtransport/src/protocols/byte_stream_reassembly.cc
+++ b/libtransport/src/protocols/byte_stream_reassembly.cc
@@ -36,15 +36,6 @@ ByteStreamReassembly::ByteStreamReassembly(
index_(Indexer::invalid_index),
download_complete_(false) {}
-void ByteStreamReassembly::reassemble(
- std::unique_ptr<ContentObjectManifest> &&manifest) {
- if (TRANSPORT_EXPECT_TRUE(manifest != nullptr) && read_buffer_->capacity()) {
- received_packets_.emplace(
- std::make_pair(manifest->getName().getSuffix(), nullptr));
- assembleContent();
- }
-}
-
void ByteStreamReassembly::reassemble(ContentObject &content_object) {
if (TRANSPORT_EXPECT_TRUE(read_buffer_->capacity())) {
received_packets_.emplace(
diff --git a/libtransport/src/protocols/byte_stream_reassembly.h b/libtransport/src/protocols/byte_stream_reassembly.h
index bfcac3181..a1f965d5c 100644
--- a/libtransport/src/protocols/byte_stream_reassembly.h
+++ b/libtransport/src/protocols/byte_stream_reassembly.h
@@ -29,9 +29,6 @@ class ByteStreamReassembly : public Reassembly {
protected:
void reassemble(core::ContentObject &content_object) override;
- void reassemble(
- std::unique_ptr<core::ContentObjectManifest> &&manifest) override;
-
void reassemble(utils::MemBuf &buffer, uint32_t suffix) override;
bool copyContent(core::ContentObject &content_object);
diff --git a/libtransport/src/protocols/cbr.cc b/libtransport/src/protocols/cbr.cc
index 446ea8b99..e3f0f1336 100644
--- a/libtransport/src/protocols/cbr.cc
+++ b/libtransport/src/protocols/cbr.cc
@@ -38,7 +38,7 @@ void CbrTransportProtocol::afterContentReception(
const Interest &interest, const ContentObject &content_object) {
auto segment = content_object.getName().getSuffix();
auto now = utils::SteadyTime::Clock::now();
- auto rtt = utils::SteadyTime::getDurationMs(
+ auto rtt = utils::SteadyTime::getDurationUs(
interest_timepoints_[segment & mask], now);
// Update stats
updateStats(segment, rtt, now);
diff --git a/libtransport/src/protocols/datagram_reassembly.cc b/libtransport/src/protocols/datagram_reassembly.cc
index 3a32c81f5..a04b0eecf 100644
--- a/libtransport/src/protocols/datagram_reassembly.cc
+++ b/libtransport/src/protocols/datagram_reassembly.cc
@@ -29,8 +29,9 @@ void DatagramReassembly::reassemble(core::ContentObject& content_object) {
auto read_buffer = content_object.getPayload();
DLOG_IF(INFO, VLOG_IS_ON(4))
<< "Size of payload: " << read_buffer->length() << ". Trimming "
- << transport_protocol_->transportHeaderLength();
- read_buffer->trimStart(transport_protocol_->transportHeaderLength());
+ << transport_protocol_->transportHeaderLength(false);
+ // here we have only src data packet
+ read_buffer->trimStart(transport_protocol_->transportHeaderLength(false));
Reassembly::read_buffer_ = std::move(read_buffer);
Reassembly::notifyApplication();
}
diff --git a/libtransport/src/protocols/datagram_reassembly.h b/libtransport/src/protocols/datagram_reassembly.h
index 0def32dd2..cefdca93b 100644
--- a/libtransport/src/protocols/datagram_reassembly.h
+++ b/libtransport/src/protocols/datagram_reassembly.h
@@ -29,10 +29,6 @@ class DatagramReassembly : public Reassembly {
virtual void reassemble(core::ContentObject &content_object) override;
void reassemble(utils::MemBuf &buffer, uint32_t suffix) override;
virtual void reInitialize() override;
- virtual void reassemble(
- std::unique_ptr<core::ContentObjectManifest> &&manifest) override {
- return;
- }
bool reassembleUnverified() override { return true; }
};
diff --git a/libtransport/src/protocols/fec/rely.cc b/libtransport/src/protocols/fec/rely.cc
index d4d98a90b..9e0a06dd8 100644
--- a/libtransport/src/protocols/fec/rely.cc
+++ b/libtransport/src/protocols/fec/rely.cc
@@ -79,7 +79,7 @@ void RelyEncoder::onPacketProduced(core::ContentObject &content_object,
// Check new payload size and make sure it fits in packet buffer
auto new_payload_size = produce_bytes();
- int difference = new_payload_size - length;
+ int difference = (int)(new_payload_size - length);
DCHECK(difference > 0);
DCHECK(content_object.ensureCapacity(difference));
diff --git a/libtransport/src/protocols/fec/rely.h b/libtransport/src/protocols/fec/rely.h
index 001a26002..cc81222b2 100644
--- a/libtransport/src/protocols/fec/rely.h
+++ b/libtransport/src/protocols/fec/rely.h
@@ -15,6 +15,7 @@
#pragma once
+#include <hicn/transport/portability/endianess.h>
#include <hicn/transport/utils/chrono_typedefs.h>
#include <hicn/transport/utils/membuf.h>
#include <protocols/fec/fec_info.h>
@@ -80,11 +81,19 @@ class RelyBase : public virtual FECBase {
*/
class fec_metadata {
public:
- void setSeqNumberBase(uint32_t suffix) { seq_number = htonl(suffix); }
- uint32_t getSeqNumberBase() const { return ntohl(seq_number); }
-
- void setMetadataBase(uint32_t value) { metadata = htonl(value); }
- uint32_t getMetadataBase() const { return ntohl(metadata); }
+ void setSeqNumberBase(uint32_t suffix) {
+ seq_number = portability::host_to_net(suffix);
+ }
+ uint32_t getSeqNumberBase() const {
+ return portability::net_to_host(seq_number);
+ }
+
+ void setMetadataBase(uint32_t value) {
+ metadata = portability::host_to_net(value);
+ }
+ uint32_t getMetadataBase() const {
+ return portability::net_to_host(metadata);
+ }
private:
uint32_t seq_number;
@@ -162,8 +171,9 @@ class RelyEncoder : RelyBase, rely::encoder, public ProducerFEC {
/**
* @brief Get the fec header size, if added to source packets
+ * there is not need to distinguish between source and FEC packets here
*/
- std::size_t getFecHeaderSize() override {
+ std::size_t getFecHeaderSize(bool isFEC) override {
return header_bytes() + sizeof(fec_metadata) + 4;
}
@@ -184,8 +194,9 @@ class RelyDecoder : RelyBase, rely::decoder, public ConsumerFEC {
/**
* @brief Get the fec header size, if added to source packets
+ * there is not need to distinguish between source and FEC packets here
*/
- std::size_t getFecHeaderSize() override {
+ std::size_t getFecHeaderSize(bool isFEC) override {
return header_bytes() + sizeof(fec_metadata);
}
diff --git a/libtransport/src/protocols/fec/rs.cc b/libtransport/src/protocols/fec/rs.cc
index 9c0a3d4fb..d42740c32 100644
--- a/libtransport/src/protocols/fec/rs.cc
+++ b/libtransport/src/protocols/fec/rs.cc
@@ -146,7 +146,8 @@ void BlockCode::encode() {
DLOG_IF(INFO, VLOG_IS_ON(4))
<< "Calling encode with max_buffer_size_ = " << max_buffer_size_;
for (uint32_t i = k_; i < n_; i++) {
- fec_encode(code_, data, data[i], i, max_buffer_size_ + METADATA_BYTES);
+ fec_encode(code_, data, data[i], i,
+ (int)(max_buffer_size_ + METADATA_BYTES));
}
// Re-include header in repair packets
@@ -213,7 +214,8 @@ void BlockCode::decode() {
DLOG_IF(INFO, VLOG_IS_ON(4))
<< "Calling decode with max_buffer_size_ = " << max_buffer_size_;
- fec_decode(code_, data, reinterpret_cast<int *>(index), 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, j = 0; i < k_; i++) {
@@ -228,6 +230,7 @@ void BlockCode::decode() {
auto &packet = operator[](i).getBuffer();
fec_metadata *metadata = reinterpret_cast<fec_metadata *>(
packet->writableData() + max_buffer_size_ - METADATA_BYTES);
+ DCHECK(metadata->getPacketLength() <= packet->capacity());
// Adjust buffer length
packet->setLength(metadata->getPacketLength());
// Adjust metadata
diff --git a/libtransport/src/protocols/fec/rs.h b/libtransport/src/protocols/fec/rs.h
index 034c32bdc..6672eaa6b 100644
--- a/libtransport/src/protocols/fec/rs.h
+++ b/libtransport/src/protocols/fec/rs.h
@@ -18,6 +18,7 @@
#include <arpa/inet.h>
#include <hicn/transport/portability/c_portability.h>
+#include <hicn/transport/portability/endianess.h>
#include <hicn/transport/utils/membuf.h>
#include <protocols/fec/fec_info.h>
#include <protocols/fec_base.h>
@@ -153,8 +154,10 @@ struct fec_header {
*/
uint8_t padding;
- void setSeqNumberBase(uint32_t suffix) { seq_number = htonl(suffix); }
- uint32_t getSeqNumberBase() { return ntohl(seq_number); }
+ void setSeqNumberBase(uint32_t suffix) {
+ seq_number = portability::host_to_net(suffix);
+ }
+ uint32_t getSeqNumberBase() { return portability::net_to_host(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; }
@@ -163,6 +166,8 @@ struct fec_header {
uint8_t getNFecSymbols() { return n_fec_symbols; }
};
+static_assert(sizeof(fec_header) <= 8, "fec_header is too large");
+
class rs;
/**
@@ -177,11 +182,17 @@ class BlockCode : public Packets {
*/
class __attribute__((__packed__)) fec_metadata {
public:
- void setPacketLength(uint16_t length) { packet_length = htons(length); }
- uint32_t getPacketLength() { return ntohs(packet_length); }
+ void setPacketLength(uint16_t length) {
+ packet_length = portability::host_to_net(length);
+ }
+ uint32_t getPacketLength() {
+ return portability::net_to_host(packet_length);
+ }
- void setMetadataBase(uint32_t value) { metadata = htonl(value); }
- uint32_t getMetadataBase() { return ntohl(metadata); }
+ void setMetadataBase(uint32_t value) {
+ metadata = portability::host_to_net(value);
+ }
+ uint32_t getMetadataBase() { return portability::net_to_host(metadata); }
private:
uint16_t packet_length; /* Used to get the real size of the packet after we
@@ -388,8 +399,11 @@ class RSEncoder : public rs, public ProducerFEC {
/**
* @brief Get the fec header size, if added to source packets
+ * in RS the source packets do not transport any FEC header
*/
- std::size_t getFecHeaderSize() override { return 0; }
+ std::size_t getFecHeaderSize(bool isFEC) override {
+ return isFEC ? sizeof(fec_header) : 0;
+ }
void clear() override {
rs::clear();
@@ -435,8 +449,11 @@ class RSDecoder : public rs, public ConsumerFEC {
/**
* @brief Get the fec header size, if added to source packets
+ * in RS the source packets do not transport any FEC header
*/
- std::size_t getFecHeaderSize() override { return 0; }
+ std::size_t getFecHeaderSize(bool isFEC) override {
+ return isFEC ? sizeof(fec_header) : 0;
+ }
/**
* Clear decoder to reuse
diff --git a/libtransport/src/protocols/fec_base.h b/libtransport/src/protocols/fec_base.h
index bda3ee756..28f6a820a 100644
--- a/libtransport/src/protocols/fec_base.h
+++ b/libtransport/src/protocols/fec_base.h
@@ -101,8 +101,10 @@ class FECBase {
/**
* @brief Get size of FEC header.
+ * the fec header size may be different if a packet is a data packet or a FEC
+ * packet
*/
- virtual std::size_t getFecHeaderSize() = 0;
+ virtual std::size_t getFecHeaderSize(bool isFEC) = 0;
/**
* Set callback to call after packet encoding / decoding
diff --git a/libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc b/libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc
index b5ab8184f..0b15559a4 100644
--- a/libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc
+++ b/libtransport/src/protocols/manifest_incremental_indexer_bytestream.cc
@@ -66,40 +66,33 @@ void ManifestIncrementalIndexer::onUntrustedManifest(
return;
}
- auto manifest =
- std::make_unique<ContentObjectManifest>(std::move(content_object));
- manifest->decode();
+ core::ContentObjectManifest manifest(content_object.shared_from_this());
+ manifest.decode();
- processTrustedManifest(interest, std::move(manifest), reassembly);
+ processTrustedManifest(interest, manifest, reassembly);
}
void ManifestIncrementalIndexer::processTrustedManifest(
- core::Interest &interest, std::unique_ptr<ContentObjectManifest> manifest,
+ core::Interest &interest, core::ContentObjectManifest &manifest,
bool reassembly) {
- if (TRANSPORT_EXPECT_FALSE(manifest->getVersion() !=
- core::ManifestVersion::VERSION_1)) {
- throw errors::RuntimeException("Received manifest with unknown version.");
- }
-
- switch (manifest->getType()) {
+ switch (manifest.getType()) {
case core::ManifestType::INLINE_MANIFEST: {
suffix_strategy_->setFinalSuffix(
- manifest->getParamsBytestream().final_segment);
+ manifest.getParamsBytestream().final_segment);
// 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
- auth::Verifier::SuffixMap current_manifest =
- core::ContentObjectManifest::getSuffixMap(manifest.get());
+ auth::Verifier::SuffixMap suffix_map = manifest.getSuffixMap();
// Update 'suffix_map_' with new hashes from the received manifest and
// build 'packets'
- for (auto it = current_manifest.begin(); it != current_manifest.end();) {
+ for (auto it = suffix_map.begin(); it != suffix_map.end();) {
if (unverified_segments_.find(it->first) ==
unverified_segments_.end()) {
suffix_map_[it->first] = std::move(it->second);
- current_manifest.erase(it++);
+ suffix_map.erase(it++);
continue;
}
@@ -109,7 +102,7 @@ void ManifestIncrementalIndexer::processTrustedManifest(
// Verify unverified segments using the received manifest
auth::Verifier::PolicyMap policies =
- verifier_->verifyPackets(packets, current_manifest);
+ verifier_->verifyPackets(packets, suffix_map);
for (unsigned int i = 0; i < packets.size(); ++i) {
auth::Suffix suffix = packets[i]->getName().getSuffix();
@@ -126,7 +119,9 @@ void ManifestIncrementalIndexer::processTrustedManifest(
}
if (reassembly) {
- reassembly_->reassemble(std::move(manifest));
+ auto manifest_co =
+ std::dynamic_pointer_cast<ContentObject>(manifest.getPacket());
+ reassembly_->reassemble(*manifest_co);
}
break;
}
diff --git a/libtransport/src/protocols/manifest_incremental_indexer_bytestream.h b/libtransport/src/protocols/manifest_incremental_indexer_bytestream.h
index 12876f35c..8527b55c1 100644
--- a/libtransport/src/protocols/manifest_incremental_indexer_bytestream.h
+++ b/libtransport/src/protocols/manifest_incremental_indexer_bytestream.h
@@ -76,7 +76,7 @@ class ManifestIncrementalIndexer : public IncrementalIndexer {
core::ContentObject &content_object,
bool reassembly);
void processTrustedManifest(core::Interest &interest,
- std::unique_ptr<ContentObjectManifest> manifest,
+ core::ContentObjectManifest &manifest,
bool reassembly);
void onUntrustedContentObject(core::Interest &interest,
core::ContentObject &content_object,
diff --git a/libtransport/src/protocols/prod_protocol_bytestream.cc b/libtransport/src/protocols/prod_protocol_bytestream.cc
index 2a3ec07e1..7f103e12b 100644
--- a/libtransport/src/protocols/prod_protocol_bytestream.cc
+++ b/libtransport/src/protocols/prod_protocol_bytestream.cc
@@ -111,18 +111,18 @@ uint32_t ByteStreamProductionProtocol::produceStream(
uint64_t manifest_free_space;
uint32_t nb_manifests;
std::shared_ptr<core::ContentObjectManifest> manifest;
- uint32_t manifest_capacity = making_manifest_;
+ uint32_t manifest_capacity = manifest_max_capacity_;
bool is_last_manifest = false;
ParamsBytestream transport_params;
manifest_format = Packet::toAHFormat(default_format);
- content_format =
- !making_manifest_ ? Packet::toAHFormat(default_format) : default_format;
+ content_format = !manifest_max_capacity_ ? Packet::toAHFormat(default_format)
+ : default_format;
- content_header_size =
- core::Packet::getHeaderSizeFromFormat(content_format, signature_length);
- manifest_header_size =
- core::Packet::getHeaderSizeFromFormat(manifest_format, signature_length);
+ content_header_size = (uint32_t)core::Packet::getHeaderSizeFromFormat(
+ content_format, signature_length);
+ manifest_header_size = (uint32_t)core::Packet::getHeaderSizeFromFormat(
+ manifest_format, signature_length);
content_free_space =
std::min(max_segment_size, data_packet_size - content_header_size);
manifest_free_space =
@@ -135,34 +135,39 @@ uint32_t ByteStreamProductionProtocol::produceStream(
nb_segments++;
}
- if (making_manifest_) {
+ if (manifest_max_capacity_) {
nb_manifests = static_cast<uint32_t>(
std::ceil(float(nb_segments) / manifest_capacity));
final_block_number += nb_segments + nb_manifests - 1;
transport_params.final_segment =
is_last ? final_block_number : utils::SuffixStrategy::MAX_SUFFIX;
- manifest.reset(ContentObjectManifest::createManifest(
+ manifest = ContentObjectManifest::createContentManifest(
manifest_format,
name.setSuffix(suffix_strategy->getNextManifestSuffix()),
- core::ManifestVersion::VERSION_1, core::ManifestType::INLINE_MANIFEST,
- is_last_manifest, name, hash_algo, signature_length));
-
- manifest->setLifetime(content_object_expiry_time);
+ signature_length);
+ manifest->setHeaders(core::ManifestType::INLINE_MANIFEST,
+ manifest_max_capacity_, hash_algo, is_last_manifest,
+ name);
manifest->setParamsBytestream(transport_params);
+ manifest->getPacket()->setLifetime(content_object_expiry_time);
}
auto self = shared_from_this();
for (unsigned int packaged_segments = 0; packaged_segments < nb_segments;
packaged_segments++) {
- if (making_manifest_) {
- if (manifest->estimateManifestSize(1) > manifest_free_space) {
+ if (manifest_max_capacity_) {
+ if (manifest->Encoder::manifestSize(1) > manifest_free_space) {
manifest->encode();
- signer_->signPacket(manifest.get());
+ auto manifest_co =
+ std::dynamic_pointer_cast<ContentObject>(manifest->getPacket());
+
+ signer_->signPacket(manifest_co.get());
// Send the current manifest
- passContentObjectToCallbacks(manifest, self);
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send manifest " << manifest->getName();
+ passContentObjectToCallbacks(manifest_co, self);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Send manifest " << manifest_co->getName();
// Send content objects stored in the queue
while (!content_queue_.empty()) {
@@ -175,15 +180,15 @@ uint32_t ByteStreamProductionProtocol::produceStream(
// 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(
+ manifest = ContentObjectManifest::createContentManifest(
manifest_format,
name.setSuffix(suffix_strategy->getNextManifestSuffix()),
- core::ManifestVersion::VERSION_1,
- core::ManifestType::INLINE_MANIFEST, is_last_manifest, name,
- hash_algo, signature_length));
-
- manifest->setLifetime(content_object_expiry_time);
+ signature_length);
+ manifest->setHeaders(core::ManifestType::INLINE_MANIFEST,
+ manifest_max_capacity_, hash_algo,
+ is_last_manifest, name);
manifest->setParamsBytestream(transport_params);
+ manifest->getPacket()->setLifetime(content_object_expiry_time);
}
}
@@ -191,7 +196,7 @@ uint32_t ByteStreamProductionProtocol::produceStream(
uint32_t content_suffix = suffix_strategy->getNextContentSuffix();
auto content_object = std::make_shared<ContentObject>(
name.setSuffix(content_suffix), content_format,
- !making_manifest_ ? signature_length : 0);
+ !manifest_max_capacity_ ? signature_length : 0);
content_object->setLifetime(content_object_expiry_time);
auto b = buffer->cloneOne();
@@ -203,7 +208,7 @@ uint32_t ByteStreamProductionProtocol::produceStream(
b->append(buffer_size - bytes_segmented);
bytes_segmented += (int)(buffer_size - bytes_segmented);
- if (is_last && making_manifest_) {
+ if (is_last && manifest_max_capacity_) {
is_last_manifest = true;
} else if (is_last) {
content_object->setLast();
@@ -219,9 +224,9 @@ uint32_t ByteStreamProductionProtocol::produceStream(
// Either we sign the content object or we save its hash into the current
// manifest
- if (making_manifest_) {
+ if (manifest_max_capacity_) {
auth::CryptoHash hash = content_object->computeDigest(hash_algo);
- manifest->addSuffixHash(content_suffix, hash);
+ manifest->addEntry(content_suffix, hash);
content_queue_.push(content_object);
} else {
signer_->signPacket(content_object.get());
@@ -232,16 +237,19 @@ uint32_t ByteStreamProductionProtocol::produceStream(
}
// We send the manifest that hasn't been fully filled yet
- if (making_manifest_) {
+ if (manifest_max_capacity_) {
if (is_last_manifest) {
manifest->setIsLast(is_last_manifest);
}
manifest->encode();
- signer_->signPacket(manifest.get());
+ auto manifest_co =
+ std::dynamic_pointer_cast<ContentObject>(manifest->getPacket());
+
+ signer_->signPacket(manifest_co.get());
- passContentObjectToCallbacks(manifest, self);
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send manifest " << manifest->getName();
+ passContentObjectToCallbacks(manifest_co, self);
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send manifest " << manifest_co->getName();
while (!content_queue_.empty()) {
passContentObjectToCallbacks(content_queue_.front(), self);
diff --git a/libtransport/src/protocols/prod_protocol_rtc.cc b/libtransport/src/protocols/prod_protocol_rtc.cc
index e49f58167..cb8dff6e4 100644
--- a/libtransport/src/protocols/prod_protocol_rtc.cc
+++ b/libtransport/src/protocols/prod_protocol_rtc.cc
@@ -43,9 +43,6 @@ RTCProductionProtocol::RTCProductionProtocol(
last_produced_data_ts_(0),
last_round_(utils::SteadyTime::nowMs().count()),
allow_delayed_nacks_(false),
- queue_timer_on_(false),
- consumer_in_sync_(false),
- on_consumer_in_sync_(nullptr),
pending_fec_pace_(false),
max_len_(0),
queue_len_(0),
@@ -54,8 +51,6 @@ RTCProductionProtocol::RTCProductionProtocol(
std::uniform_int_distribution<> dis(0, 255);
prod_label_ = dis(gen_);
cache_label_ = (prod_label_ + 1) % 256;
- interests_queue_timer_ =
- std::make_unique<asio::steady_timer>(portal_->getThread().getIoService());
round_timer_ =
std::make_unique<asio::steady_timer>(portal_->getThread().getIoService());
fec_pacing_timer_ =
@@ -69,16 +64,7 @@ RTCProductionProtocol::~RTCProductionProtocol() {}
void RTCProductionProtocol::setProducerParam() {
// Flow name: here we assume there is only one prefix registered in the portal
- flow_name_ = portal_->getServedNamespaces().begin()->getName();
-
- // Manifest
- uint32_t making_manifest;
- socket_->getSocketOption(interface::GeneralTransportOptions::MAKE_MANIFEST,
- making_manifest);
-
- // Signer
- std::shared_ptr<auth::Signer> signer;
- socket_->getSocketOption(interface::GeneralTransportOptions::SIGNER, signer);
+ flow_name_ = portal_->getServedNamespaces().begin()->makeName();
// Default format
core::Packet::Format default_format;
@@ -94,15 +80,22 @@ void RTCProductionProtocol::setProducerParam() {
socket_->getSocketOption(interface::RtcTransportOptions::AGGREGATED_DATA,
data_aggregation_);
- size_t signature_size = signer->getSignatureFieldSize();
- data_header_format_ = {
- !making_manifest ? Packet::toAHFormat(default_format) : default_format,
- !making_manifest ? signature_size : 0};
+ size_t signature_size = signer_->getSignatureFieldSize();
+ data_header_format_ = {!manifest_max_capacity_
+ ? Packet::toAHFormat(default_format)
+ : default_format,
+ !manifest_max_capacity_ ? signature_size : 0};
manifest_header_format_ = {Packet::toAHFormat(default_format),
signature_size};
nack_header_format_ = {Packet::toAHFormat(default_format), signature_size};
fec_header_format_ = {Packet::toAHFormat(default_format), signature_size};
+ // Initialize verifier for aggregated interests
+ std::shared_ptr<auth::Verifier> verifier;
+ socket_->getSocketOption(implementation::GeneralTransportOptions::VERIFIER,
+ verifier);
+ verifier_ = std::make_shared<rtc::RTCVerifier>(verifier, 0, 0);
+
// Schedule round timer
scheduleRoundTimer();
}
@@ -143,15 +136,17 @@ void RTCProductionProtocol::updateStats(bool new_round) {
packets_production_rate_ =
ceil((double)(produced_packets_ + prev_produced_packets_) * per_second);
- // add fec packets looking at the fec code. we don't use directly the number
- // of fec packets produced in 1 round because it may happen that different
- // numbers of blocks are generated during the rounds and this creates
- // inconsistencies in the estimation of the production rate
- uint32_t k = fec::FECUtils::getSourceSymbols(fec_type_);
- uint32_t n = fec::FECUtils::getBlockSymbols(fec_type_);
+ if (fec_encoder_ && fec_type_ != fec::FECType::UNKNOWN) {
+ // add fec packets looking at the fec code. we don't use directly the number
+ // of fec packets produced in 1 round because it may happen that different
+ // numbers of blocks are generated during the rounds and this creates
+ // inconsistencies in the estimation of the production rate
+ uint32_t k = fec::FECUtils::getSourceSymbols(fec_type_);
+ uint32_t n = fec::FECUtils::getBlockSymbols(fec_type_);
- packets_production_rate_ +=
- ceil((double)packets_production_rate_ / (double)k) * (n - k);
+ packets_production_rate_ +=
+ ceil((double)packets_production_rate_ / (double)k) * (n - k);
+ }
// update the production rate as soon as it increases by 10% with respect to
// the last round
@@ -168,11 +163,6 @@ void RTCProductionProtocol::updateStats(bool new_round) {
allow_delayed_nacks_ = false;
}
- // check if the production rate is decreased. if yes send nacks if needed
- if (prev_packets_production_rate < packets_production_rate_) {
- sendNacksForPendingInterests();
- }
-
if (new_round) {
prev_produced_bytes_ = produced_bytes_;
prev_produced_packets_ = produced_packets_;
@@ -203,16 +193,25 @@ void RTCProductionProtocol::produce(ContentObject &content_object) {
uint32_t RTCProductionProtocol::produceDatagram(
const Name &content_name, std::unique_ptr<utils::MemBuf> &&buffer) {
std::size_t buffer_size = buffer->length();
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Maybe Sending content object: " << content_name;
+
if (TRANSPORT_EXPECT_FALSE(buffer_size == 0)) return 0;
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "Sending content object: " << content_name;
+
uint32_t data_packet_size;
socket_->getSocketOption(interface::GeneralTransportOptions::DATA_PACKET_SIZE,
data_packet_size);
-
- if (TRANSPORT_EXPECT_FALSE(
- (Packet::getHeaderSizeFromFormat(data_header_format_.first,
- data_header_format_.second) +
- rtc::DATA_HEADER_SIZE + buffer_size) > data_packet_size)) {
+ // this is a source packet but we check the fec header size of FEC packet in
+ // order to leave room for the header when FEC packets will be generated
+ uint32_t fec_header = 0;
+ if (fec_encoder_) fec_encoder_->getFecHeaderSize(true);
+ uint32_t headers_size =
+ (uint32_t)Packet::getHeaderSizeFromFormat(data_header_format_.first,
+ data_header_format_.second) +
+ rtc::DATA_HEADER_SIZE + fec_header;
+ if (TRANSPORT_EXPECT_FALSE((headers_size + buffer_size) > data_packet_size)) {
return 0;
}
@@ -338,47 +337,42 @@ void RTCProductionProtocol::emptyQueue() {
}
void RTCProductionProtocol::sendManifest(const Name &name) {
- if (!making_manifest_) {
+ if (!manifest_max_capacity_) {
return;
}
- Name manifest_name(name);
-
- uint32_t data_packet_size;
- socket_->getSocketOption(interface::GeneralTransportOptions::DATA_PACKET_SIZE,
- data_packet_size);
-
- // The maximum number of entries a manifest can hold
- uint32_t manifest_capacity = making_manifest_;
+ Name manifest_name = name;
// If there is not enough hashes to fill a manifest, return early
- if (manifest_entries_.size() < manifest_capacity) {
+ if (manifest_entries_.size() < manifest_max_capacity_) {
return;
}
// Create a new manifest
std::shared_ptr<core::ContentObjectManifest> manifest =
createManifest(manifest_name.setSuffix(current_seg_));
+ auto manifest_co =
+ std::dynamic_pointer_cast<ContentObject>(manifest->getPacket());
// Fill the manifest with packet hashes that were previously saved
uint32_t nb_entries;
- for (nb_entries = 0; nb_entries < manifest_capacity; ++nb_entries) {
+ for (nb_entries = 0; nb_entries < manifest_max_capacity_; ++nb_entries) {
if (manifest_entries_.empty()) {
break;
}
std::pair<uint32_t, auth::CryptoHash> front = manifest_entries_.front();
- manifest->addSuffixHash(front.first, front.second);
+ manifest->addEntry(front.first, front.second);
manifest_entries_.pop();
}
DLOG_IF(INFO, VLOG_IS_ON(3))
- << "Sending manifest " << manifest->getName().getSuffix() << " of size "
- << nb_entries;
+ << "Sending manifest " << manifest_co->getName().getSuffix()
+ << " of size " << nb_entries;
// Encode and send the manifest
manifest->encode();
portal_->getThread().tryRunHandlerNow(
- [this, content_object{std::move(manifest)}, manifest_name]() mutable {
+ [this, content_object{std::move(manifest_co)}, manifest_name]() mutable {
produceInternal(std::move(content_object), manifest_name);
});
}
@@ -394,11 +388,12 @@ RTCProductionProtocol::createManifest(const Name &content_name) const {
uint64_t now = utils::SteadyTime::nowMs().count();
// Create a new manifest
- std::shared_ptr<core::ContentObjectManifest> manifest(
- ContentObjectManifest::createManifest(
- manifest_header_format_.first, name, core::ManifestVersion::VERSION_1,
- core::ManifestType::INLINE_MANIFEST, false, name, hash_algo,
- manifest_header_format_.second));
+ std::shared_ptr<core::ContentObjectManifest> manifest =
+ ContentObjectManifest::createContentManifest(
+ manifest_header_format_.first, name, manifest_header_format_.second);
+ manifest->setHeaders(core::ManifestType::INLINE_MANIFEST,
+ manifest_max_capacity_, hash_algo, false /* is_last */,
+ name);
// Set connection parameters
manifest->setParamsRTC(ParamsRTC{
@@ -444,7 +439,15 @@ void RTCProductionProtocol::producePktInternal(
// 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
+
+ uint32_t expiry_time = 0;
+ socket_->getSocketOption(
+ interface::GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME,
+ expiry_time);
+ if (expiry_time == interface::default_values::content_object_expiry_time)
+ expiry_time = 500; // the data expiration time should be set by the App. if
+ // the App does not specify it the default is 500ms
+ content_object->setLifetime(expiry_time);
content_object->setPathLabel(prod_label_);
// update stats
@@ -466,9 +469,9 @@ void RTCProductionProtocol::producePktInternal(
// pass packet to FEC encoder
if (fec_encoder_ && !fec) {
- uint32_t offset =
- is_manifest ? content_object->headerSize()
- : content_object->headerSize() + rtc::DATA_HEADER_SIZE;
+ uint32_t offset = is_manifest ? (uint32_t)content_object->headerSize()
+ : (uint32_t)content_object->headerSize() +
+ rtc::DATA_HEADER_SIZE;
uint32_t metadata = static_cast<uint32_t>(content_object->getPayloadType());
fec_encoder_->onPacketProduced(*content_object, offset, metadata);
@@ -481,19 +484,14 @@ void RTCProductionProtocol::producePktInternal(
*content_object);
}
- auto seq_it = seqs_map_.find(current_seg_);
- if (seq_it != seqs_map_.end()) {
- sendContentObject(content_object, false, fec);
- }
+ // TODO we may want to send FEC only if an interest is pending in the pit in
+ sendContentObject(content_object, false, fec);
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_);
-
if (!fec) last_produced_data_ts_ = now;
// Update current segment
@@ -563,59 +561,65 @@ void RTCProductionProtocol::onInterest(Interest &interest) {
on_interest_input_->operator()(*socket_->getInterface(), interest);
}
- auto suffix = interest.firstSuffix();
- // numberOfSuffixes returns only the prefixes in the payalod
- // we add + 1 to count also the seq in the name
- auto n_suffixes = interest.numberOfSuffixes() + 1;
- Name name = interest.getName();
- bool prev_consumer_state = consumer_in_sync_;
-
- for (uint32_t i = 0; i < n_suffixes; i++) {
- if (i > 0) {
- name.setSuffix(*(suffix + (i - 1)));
- }
+ if (!interest.isValid()) throw std::runtime_error("Bad interest format");
+ if (interest.hasManifest() &&
+ verifier_->verify(interest) != auth::VerificationPolicy::ACCEPT)
+ throw std::runtime_error("Interset manifest verification failed");
- DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received interest " << name;
+ uint32_t *suffix = interest.firstSuffix();
+ uint32_t n_suffixes_in_manifest = interest.numberOfSuffixes();
+ uint32_t *request_bitmap = interest.getRequestBitmap();
- const std::shared_ptr<ContentObject> content_object =
- output_buffer_.find(name);
+ Name name = interest.getName();
+ uint32_t pos = 0; // Position of current suffix in manifest
- if (content_object) {
- if (*on_interest_satisfied_output_buffer_) {
- on_interest_satisfied_output_buffer_->operator()(
- *socket_->getInterface(), interest);
- }
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Received interest " << name << " (" << n_suffixes_in_manifest
+ << " suffixes in manifest)";
+
+ // Process the suffix in the interest header
+ // (first loop iteration), then suffixes in the manifest
+ do {
+ if (!interest.hasManifest() || is_bit_set(request_bitmap, pos)) {
+ const std::shared_ptr<ContentObject> content_object =
+ output_buffer_.find(name);
+
+ 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);
- }
+ if (*on_content_object_output_) {
+ on_content_object_output_->operator()(*socket_->getInterface(),
+ *content_object);
+ }
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "Send content %u (onInterest) " << content_object->getName();
- content_object->setPathLabel(cache_label_);
- sendContentObject(content_object);
- } else {
- if (*on_interest_process_) {
- on_interest_process_->operator()(*socket_->getInterface(), interest);
+ DLOG_IF(INFO, VLOG_IS_ON(3))
+ << "Send content %u (onInterest) " << content_object->getName();
+ content_object->setPathLabel(cache_label_);
+ sendContentObject(content_object);
+ } else {
+ if (*on_interest_process_) {
+ on_interest_process_->operator()(*socket_->getInterface(), interest);
+ }
+ processInterest(name.getSuffix(), interest.getLifetime());
}
- processInterest(name.getSuffix(), interest.getLifetime());
}
- }
- if (prev_consumer_state != consumer_in_sync_ && consumer_in_sync_)
- on_consumer_in_sync_(*socket_->getInterface(), interest);
+ // Retrieve next suffix in the manifest
+ if (interest.hasManifest()) {
+ uint32_t seq = *suffix;
+ suffix++;
+
+ name.setSuffix(seq);
+ interest.setName(name);
+ }
+ } while (pos++ < n_suffixes_in_manifest);
}
void RTCProductionProtocol::processInterest(uint32_t interest_seg,
uint32_t lifetime) {
- if (interest_seg == 0) {
- // first packet from the consumer, reset sync state
- consumer_in_sync_ = false;
- }
-
- uint64_t now = utils::SteadyTime::nowMs().count();
-
switch (rtc::ProbeHandler::getProbeType(interest_seg)) {
case rtc::ProbeType::INIT:
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Received init probe " << interest_seg;
@@ -629,183 +633,7 @@ void RTCProductionProtocol::processInterest(uint32_t interest_seg,
break;
}
- // if the production rate 0 use delayed nacks
- if (allow_delayed_nacks_ && interest_seg >= current_seg_) {
- uint64_t next_timer = UINT64_MAX;
- if (!timers_map_.empty()) {
- next_timer = timers_map_.begin()->first;
- }
-
- uint64_t expiration = now + rtc::NACK_DELAY;
- 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 = 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 =
- now + floor((double)lifetime * rtc::INTEREST_LIFETIME_REDUCTION_FACTOR);
- addToInterestQueue(interest_seg, expiration);
- }
-}
-
-void RTCProductionProtocol::scheduleQueueTimer(uint64_t wait) {
- interests_queue_timer_->expires_from_now(std::chrono::milliseconds(wait));
- std::weak_ptr<RTCProductionProtocol> self = shared_from_this();
- interests_queue_timer_->async_wait([self](const std::error_code &ec) {
- if (ec) {
- return;
- }
-
- auto sp = self.lock();
- if (sp && sp->isRunning()) {
- sp->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 pps = ceil((double)(packets_production_rate_)*rtc::
- INTEREST_LIFETIME_REDUCTION_FACTOR);
-
- uint64_t now = utils::SteadyTime::nowMs().count();
- for (auto it = seqs_map_.begin(); it != seqs_map_.end(); it++) {
- if (it->first > current_seg_ && it->second > now) {
- double exp_time_in_sec =
- (double)(it->second - now) / (double)rtc::MILLI_IN_A_SEC;
- uint32_t packets_prod_before_expire = ceil((double)pps * exp_time_in_sec);
-
- if (it->first > (current_seg_ + packets_prod_before_expire)) {
- sendNack(it->first);
- to_remove.insert(it->first);
- }
- } else if (TRANSPORT_EXPECT_FALSE(it->first < current_seg_ ||
- it->second <= now)) {
- // this branch should never be execcuted
- // first condition: the packet was already prdocued and we have and old
- // interest pending. send a nack to notify the consumer if needed. the
- // case it->first = current_seg_ is not handled because
- // the interest will be satified by the next data packet.
- // second condition: the interest is expired.
- 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 = utils::SteadyTime::nowMs().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);
- }
+ if (interest_seg < current_seg_) sendNack(interest_seg);
}
void RTCProductionProtocol::sendManifestProbe(uint32_t sequence) {
@@ -814,18 +642,20 @@ void RTCProductionProtocol::sendManifestProbe(uint32_t sequence) {
std::shared_ptr<core::ContentObjectManifest> manifest_probe =
createManifest(manifest_name);
+ auto manifest_probe_co =
+ std::dynamic_pointer_cast<ContentObject>(manifest_probe->getPacket());
- manifest_probe->setLifetime(0);
- manifest_probe->setPathLabel(prod_label_);
+ manifest_probe_co->setLifetime(0);
+ manifest_probe_co->setPathLabel(prod_label_);
manifest_probe->encode();
if (*on_content_object_output_) {
on_content_object_output_->operator()(*socket_->getInterface(),
- *manifest_probe);
+ *manifest_probe_co);
}
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Send init probe " << sequence;
- sendContentObject(manifest_probe, true, false);
+ sendContentObject(manifest_probe_co, true, false);
}
void RTCProductionProtocol::sendNack(uint32_t sequence) {
@@ -847,20 +677,6 @@ void RTCProductionProtocol::sendNack(uint32_t sequence) {
nack->setLifetime(0);
nack->setPathLabel(prod_label_);
- if (!consumer_in_sync_ && on_consumer_in_sync_ &&
- rtc::ProbeHandler::getProbeType(sequence) == rtc::ProbeType::NOT_PROBE &&
- sequence > next_packet) {
- consumer_in_sync_ = true;
- Packet::Format format;
- socket_->getSocketOption(interface::GeneralTransportOptions::PACKET_FORMAT,
- format);
-
- auto interest =
- core::PacketManager<>::getInstance().getPacket<Interest>(format);
- interest->setName(n);
- on_consumer_in_sync_(*socket_->getInterface(), *interest);
- }
-
if (*on_content_object_output_) {
on_content_object_output_->operator()(*socket_->getInterface(), *nack);
}
@@ -881,7 +697,7 @@ void RTCProductionProtocol::sendContentObject(
portal_->sendContentObject(*content_object);
// Compute and save data packet digest
- if (making_manifest_ && !is_ah) {
+ if (manifest_max_capacity_ && !is_ah) {
auth::CryptoHashType hash_algo;
socket_->getSocketOption(interface::GeneralTransportOptions::HASH_ALGORITHM,
hash_algo);
diff --git a/libtransport/src/protocols/prod_protocol_rtc.h b/libtransport/src/protocols/prod_protocol_rtc.h
index c0424a39c..285ccb646 100644
--- a/libtransport/src/protocols/prod_protocol_rtc.h
+++ b/libtransport/src/protocols/prod_protocol_rtc.h
@@ -17,6 +17,7 @@
#include <hicn/transport/core/name.h>
#include <protocols/production_protocol.h>
+#include <protocols/rtc/rtc_verifier.h>
#include <atomic>
#include <map>
@@ -50,11 +51,6 @@ class RTCProductionProtocol : public ProductionProtocol {
buffer, buffer_size, buffer_size));
}
- void setConsumerInSyncCallback(
- interface::ProducerInterestCallback &&callback) {
- on_consumer_in_sync_ = std::move(callback);
- }
-
auto shared_from_this() { return utils::shared_from(this); }
private:
@@ -80,13 +76,6 @@ class RTCProductionProtocol : public ProductionProtocol {
void updateStats(bool new_round);
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();
-
// FEC functions
void onFecPackets(fec::BufferArray &packets);
fec::buffer getBuffer(std::size_t size);
@@ -111,14 +100,14 @@ class RTCProductionProtocol : public ProductionProtocol {
uint32_t prev_produced_bytes_; // XXX clearly explain all these new vars
uint32_t prev_produced_packets_;
- uint32_t produced_bytes_; // bytes produced in the last round
- uint32_t produced_packets_; // packet produed in the last round
+ 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
+ uint32_t bytes_production_rate_; // bytes per sec
+ uint32_t packets_production_rate_; // pps
uint64_t last_produced_data_ts_; // ms
@@ -134,27 +123,6 @@ class RTCProductionProtocol : public ProductionProtocol {
// 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_;
-
// Save FEC packets here before sending them
std::queue<ContentObject::Ptr> pending_fec_packets_;
std::queue<std::pair<uint64_t, ContentObject::Ptr>> paced_fec_packets_;
@@ -172,6 +140,9 @@ class RTCProductionProtocol : public ProductionProtocol {
// Manifest
std::queue<std::pair<uint32_t, auth::CryptoHash>>
manifest_entries_; // map a packet suffix to a packet hash
+
+ // Verifier for aggregated interests
+ std::shared_ptr<rtc::RTCVerifier> verifier_;
};
} // namespace protocol
diff --git a/libtransport/src/protocols/production_protocol.cc b/libtransport/src/protocols/production_protocol.cc
index 8b781e38a..039a6a55a 100644
--- a/libtransport/src/protocols/production_protocol.cc
+++ b/libtransport/src/protocols/production_protocol.cc
@@ -78,8 +78,8 @@ int ProductionProtocol::start() {
socket_->getSocketOption(GeneralTransportOptions::ASYNC_MODE, is_async_);
socket_->getSocketOption(GeneralTransportOptions::SIGNER, signer_);
- socket_->getSocketOption(GeneralTransportOptions::MAKE_MANIFEST,
- making_manifest_);
+ socket_->getSocketOption(GeneralTransportOptions::MANIFEST_MAX_CAPACITY,
+ manifest_max_capacity_);
std::string fec_type_str = "";
socket_->getSocketOption(GeneralTransportOptions::FEC_TYPE, fec_type_str);
diff --git a/libtransport/src/protocols/production_protocol.h b/libtransport/src/protocols/production_protocol.h
index 8e10d2f40..09718631f 100644
--- a/libtransport/src/protocols/production_protocol.h
+++ b/libtransport/src/protocols/production_protocol.h
@@ -79,6 +79,7 @@ class ProductionProtocol
if (fec_str && (fec_type_ == fec::FECType::UNKNOWN)) {
LOG(INFO) << "Using FEC " << fec_str;
fec_type_ = fec::FECUtils::fecTypeFromString(fec_str);
+ CHECK(fec_type_ != fec::FECType::UNKNOWN);
}
if (fec_type_ == fec::FECType::UNKNOWN) {
@@ -123,7 +124,7 @@ class ProductionProtocol
// Signature and manifest
std::shared_ptr<auth::Signer> signer_;
- uint32_t making_manifest_;
+ uint32_t manifest_max_capacity_;
bool is_async_;
fec::FECType fec_type_;
diff --git a/libtransport/src/protocols/raaqm.cc b/libtransport/src/protocols/raaqm.cc
index 131367d78..bcbc15aef 100644
--- a/libtransport/src/protocols/raaqm.cc
+++ b/libtransport/src/protocols/raaqm.cc
@@ -371,7 +371,7 @@ void RaaqmTransportProtocol::onPacketDropped(Interest &interest,
}
interest_retransmissions_[segment & mask]++;
- interest_to_retransmit_.push(segment);
+ interest_to_retransmit_.push((unsigned int)segment);
} else {
LOG(ERROR) << "Stop: received not trusted packet "
<< interest_retransmissions_[segment & mask] << " times";
@@ -429,7 +429,7 @@ void RaaqmTransportProtocol::onInterestTimeout(Interest::Ptr &interest,
return;
}
- interest_to_retransmit_.push(segment);
+ interest_to_retransmit_.push((unsigned int)segment);
scheduleNextInterests();
} else {
LOG(ERROR) << "Stop: reached max retx limit.";
@@ -491,7 +491,7 @@ void RaaqmTransportProtocol::updateRtt(uint64_t segment) {
throw std::runtime_error("RAAQM ERROR: no current path found, exit");
} else {
auto now = utils::SteadyTime::Clock::now();
- utils::SteadyTime::Milliseconds rtt = utils::SteadyTime::getDurationMs(
+ auto rtt = utils::SteadyTime::getDurationUs(
interest_timepoints_[segment & mask], now);
// Update stats
@@ -525,7 +525,7 @@ void RaaqmTransportProtocol::RAAQM() {
}
void RaaqmTransportProtocol::updateStats(
- uint32_t suffix, const utils::SteadyTime::Milliseconds &rtt,
+ uint32_t suffix, const utils::SteadyTime::Microseconds &rtt,
utils::SteadyTime::TimePoint &now) {
// Update RTT statistics
stats_->updateAverageRtt(rtt);
diff --git a/libtransport/src/protocols/raaqm.h b/libtransport/src/protocols/raaqm.h
index ec344c23a..a7ef23b68 100644
--- a/libtransport/src/protocols/raaqm.h
+++ b/libtransport/src/protocols/raaqm.h
@@ -57,7 +57,7 @@ class RaaqmTransportProtocol : public TransportProtocol,
virtual void afterDataUnsatisfied(uint64_t segment);
virtual void updateStats(uint32_t suffix,
- const utils::SteadyTime::Milliseconds &rtt,
+ const utils::SteadyTime::Microseconds &rtt,
utils::SteadyTime::TimePoint &now);
private:
diff --git a/libtransport/src/protocols/raaqm_data_path.cc b/libtransport/src/protocols/raaqm_data_path.cc
index d06fee918..b8e6e6285 100644
--- a/libtransport/src/protocols/raaqm_data_path.cc
+++ b/libtransport/src/protocols/raaqm_data_path.cc
@@ -50,9 +50,9 @@ RaaqmDataPath::RaaqmDataPath(double drop_factor,
alpha_(ALPHA) {}
RaaqmDataPath &RaaqmDataPath::insertNewRtt(
- const utils::SteadyTime::Milliseconds &new_rtt,
+ const utils::SteadyTime::Microseconds &new_rtt,
const utils::SteadyTime::TimePoint &now) {
- rtt_ = new_rtt.count();
+ rtt_ = new_rtt.count() / 1000;
rtt_samples_.pushBack(rtt_);
rtt_max_ = rtt_samples_.rBegin();
diff --git a/libtransport/src/protocols/raaqm_data_path.h b/libtransport/src/protocols/raaqm_data_path.h
index b6f7c5ac1..dd24dad51 100644
--- a/libtransport/src/protocols/raaqm_data_path.h
+++ b/libtransport/src/protocols/raaqm_data_path.h
@@ -49,7 +49,7 @@ class RaaqmDataPath {
* max of RTT.
* @param new_rtt is the value of the new RTT
*/
- RaaqmDataPath &insertNewRtt(const utils::SteadyTime::Milliseconds &new_rtt,
+ RaaqmDataPath &insertNewRtt(const utils::SteadyTime::Microseconds &new_rtt,
const utils::SteadyTime::TimePoint &now);
/**
diff --git a/libtransport/src/protocols/rate_estimation.cc b/libtransport/src/protocols/rate_estimation.cc
index d834b53e6..01c18c6cb 100644
--- a/libtransport/src/protocols/rate_estimation.cc
+++ b/libtransport/src/protocols/rate_estimation.cc
@@ -107,9 +107,9 @@ InterRttEstimator::~InterRttEstimator() {
}
void InterRttEstimator::onRttUpdate(
- const utils::SteadyTime::Milliseconds &rtt) {
+ const utils::SteadyTime::Microseconds &rtt) {
pthread_mutex_lock(&(this->mutex_));
- this->rtt_ = rtt.count();
+ this->rtt_ = rtt.count() / 1000.0;
this->number_of_packets_++;
this->avg_rtt_ += this->rtt_;
pthread_mutex_unlock(&(this->mutex_));
@@ -256,7 +256,7 @@ void SimpleEstimator::onDataReceived(int packet_size) {
this->total_size_ += packet_size;
}
-void SimpleEstimator::onRttUpdate(const utils::SteadyTime::Milliseconds &rtt) {
+void SimpleEstimator::onRttUpdate(const utils::SteadyTime::Microseconds &rtt) {
this->number_of_packets_++;
if (this->number_of_packets_ == this->batching_param_) {
@@ -300,9 +300,9 @@ BatchingPacketsEstimator::BatchingPacketsEstimator(double alpha_arg,
}
void BatchingPacketsEstimator::onRttUpdate(
- const utils::SteadyTime::Milliseconds &rtt) {
+ const utils::SteadyTime::Microseconds &rtt) {
this->number_of_packets_++;
- this->avg_rtt_ += rtt.count();
+ this->avg_rtt_ += rtt.count() / 1000.0;
if (number_of_packets_ == this->batching_param_) {
if (estimation_ == 0) {
diff --git a/libtransport/src/protocols/rate_estimation.h b/libtransport/src/protocols/rate_estimation.h
index b71de12e4..d809b2b7c 100644
--- a/libtransport/src/protocols/rate_estimation.h
+++ b/libtransport/src/protocols/rate_estimation.h
@@ -31,7 +31,7 @@ class IcnRateEstimator : utils::NonCopyable {
virtual ~IcnRateEstimator(){};
- virtual void onRttUpdate(const utils::SteadyTime::Milliseconds &rtt){};
+ virtual void onRttUpdate(const utils::SteadyTime::Microseconds &rtt){};
virtual void onDataReceived(int packetSize){};
@@ -66,7 +66,7 @@ class InterRttEstimator : public IcnRateEstimator {
~InterRttEstimator();
- void onRttUpdate(const utils::SteadyTime::Milliseconds &rtt);
+ void onRttUpdate(const utils::SteadyTime::Microseconds &rtt);
void onDataReceived(int packet_size) {
if (packet_size > this->max_packet_size_) {
@@ -101,7 +101,7 @@ class BatchingPacketsEstimator : public IcnRateEstimator {
public:
BatchingPacketsEstimator(double alpha_arg, int batchingParam);
- void onRttUpdate(const utils::SteadyTime::Milliseconds &rtt);
+ void onRttUpdate(const utils::SteadyTime::Microseconds &rtt);
void onDataReceived(int packet_size) {
if (packet_size > this->max_packet_size_) {
@@ -148,7 +148,7 @@ class SimpleEstimator : public IcnRateEstimator {
public:
SimpleEstimator(double alpha, int batching_param);
- void onRttUpdate(const utils::SteadyTime::Milliseconds &rtt);
+ void onRttUpdate(const utils::SteadyTime::Microseconds &rtt);
void onDataReceived(int packet_size);
diff --git a/libtransport/src/protocols/reassembly.h b/libtransport/src/protocols/reassembly.h
index b0879201d..c0c4de3d8 100644
--- a/libtransport/src/protocols/reassembly.h
+++ b/libtransport/src/protocols/reassembly.h
@@ -57,12 +57,6 @@ class Reassembly {
virtual void reassemble(utils::MemBuf &buffer, uint32_t suffix) = 0;
/**
- * Handle reassembly of manifest
- */
- virtual void reassemble(
- std::unique_ptr<core::ContentObjectManifest> &&manifest) = 0;
-
- /**
* Reset reassembler for new round
*/
virtual void reInitialize() = 0;
diff --git a/libtransport/src/protocols/rtc/probe_handler.cc b/libtransport/src/protocols/rtc/probe_handler.cc
index 6a84914ab..60eceeb19 100644
--- a/libtransport/src/protocols/rtc/probe_handler.cc
+++ b/libtransport/src/protocols/rtc/probe_handler.cc
@@ -13,6 +13,7 @@
* limitations under the License.
*/
+#include <glog/logging.h>
#include <hicn/transport/utils/chrono_typedefs.h>
#include <protocols/rtc/probe_handler.h>
#include <protocols/rtc/rtc_consts.h>
@@ -64,7 +65,7 @@ double ProbeHandler::getProbeLossRate() {
}
void ProbeHandler::setSuffixRange(uint32_t min, uint32_t max) {
- assert(min <= max && min >= MIN_PROBE_SEQ);
+ DCHECK(min <= max && min >= MIN_PROBE_SEQ);
distr_ = std::uniform_int_distribution<uint32_t>(min, max);
}
diff --git a/libtransport/src/protocols/rtc/rtc.cc b/libtransport/src/protocols/rtc/rtc.cc
index d2682edfa..9a56269f3 100644
--- a/libtransport/src/protocols/rtc/rtc.cc
+++ b/libtransport/src/protocols/rtc/rtc.cc
@@ -38,6 +38,7 @@ RTCTransportProtocol::RTCTransportProtocol(
implementation::ConsumerSocket *icn_socket)
: TransportProtocol(icn_socket, new RtcIndexer<>(icn_socket, this),
new RtcReassembly(icn_socket, this)),
+ max_aggregated_interest_(1),
number_(0) {
icn_socket->getSocketOption(PORTAL, portal_);
round_timer_ =
@@ -55,9 +56,9 @@ void RTCTransportProtocol::resume() {
TransportProtocol::resume();
}
-std::size_t RTCTransportProtocol::transportHeaderLength() {
+std::size_t RTCTransportProtocol::transportHeaderLength(bool isFEC) {
return DATA_HEADER_SIZE +
- (fec_decoder_ != nullptr ? fec_decoder_->getFecHeaderSize() : 0);
+ (fec_decoder_ != nullptr ? fec_decoder_->getFecHeaderSize(isFEC) : 0);
}
// private
@@ -75,13 +76,13 @@ void RTCTransportProtocol::initParams() {
std::shared_ptr<auth::Verifier> verifier;
socket_->getSocketOption(GeneralTransportOptions::VERIFIER, verifier);
- uint32_t unverified_interval;
- socket_->getSocketOption(GeneralTransportOptions::UNVERIFIED_INTERVAL,
- unverified_interval);
+ uint32_t factor_relevant;
+ socket_->getSocketOption(GeneralTransportOptions::MANIFEST_FACTOR_RELEVANT,
+ factor_relevant);
- double unverified_ratio;
- socket_->getSocketOption(GeneralTransportOptions::UNVERIFIED_RATIO,
- unverified_ratio);
+ uint32_t factor_alert;
+ socket_->getSocketOption(GeneralTransportOptions::MANIFEST_FACTOR_ALERT,
+ factor_alert);
rc_ = std::make_shared<RTCRateControlCongestionDetection>();
ldr_ = std::make_shared<RTCLossDetectionAndRecovery>(
@@ -100,8 +101,8 @@ void RTCTransportProtocol::initParams() {
}
});
- verifier_ = std::make_shared<RTCVerifier>(verifier, unverified_interval,
- unverified_ratio);
+ verifier_ =
+ std::make_shared<RTCVerifier>(verifier, factor_relevant, factor_alert);
state_ = std::make_shared<RTCState>(
indexer_verifier_.get(),
@@ -138,19 +139,20 @@ void RTCTransportProtocol::initParams() {
last_interest_sent_time_ = 0;
last_interest_sent_seq_ = 0;
-#if 0
- if(portal_->isConnectedToFwd()){
- max_aggregated_interest_ = 1;
- }else{
- max_aggregated_interest_ = MAX_INTERESTS_IN_BATCH;
- }
-#else
- max_aggregated_interest_ = 1;
- if (const char *max_aggr = std::getenv("MAX_AGGREGATED_INTERESTS")) {
- LOG(INFO) << "Max Aggregated: " << max_aggr;
- max_aggregated_interest_ = std::stoul(std::string(max_aggr));
+ // Aggregated interests setup
+ bool aggregated_interests_on;
+ socket_->getSocketOption(RtcTransportOptions::AGGREGATED_INTERESTS,
+ aggregated_interests_on);
+ if (aggregated_interests_on) {
+ if (const char *max_aggr = std::getenv("MAX_AGGREGATED_INTERESTS"))
+ max_aggregated_interest_ = (uint32_t)std::stoul(std::string(max_aggr));
+ else
+ max_aggregated_interest_ = MAX_INTERESTS_IN_BATCH;
+
+ max_aggregated_interest_ = std::min<uint32_t>(max_aggregated_interest_,
+ 1 + MAX_SUFFIXES_IN_MANIFEST);
}
-#endif
+ LOG(INFO) << "Max Aggregated: " << max_aggregated_interest_;
max_sent_int_ =
std::ceil((double)MAX_PACING_BATCH / (double)max_aggregated_interest_);
@@ -263,6 +265,11 @@ void RTCTransportProtocol::discoveredRtt() {
socket_->getSocketOption(RtcTransportOptions::RECOVERY_STRATEGY, strategy);
ldr_->changeRecoveryStrategy(
(interface::RtcTransportRecoveryStrategies)strategy);
+
+ bool content_sharing_mode;
+ socket_->getSocketOption(RtcTransportOptions::CONTENT_SHARING_MODE,
+ content_sharing_mode);
+ if (content_sharing_mode) ldr_->setContentSharingMode();
ldr_->turnOnRecovery();
ldr_->onNewRound(false);
@@ -270,22 +277,9 @@ void RTCTransportProtocol::discoveredRtt() {
Name *name = nullptr;
socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME, &name);
Prefix prefix(*name, 128);
- if ((interface::RtcTransportRecoveryStrategies)strategy ==
- interface::RtcTransportRecoveryStrategies::LOW_RATE_AND_BESTPATH) {
- fwd_strategy_.initFwdStrategy(portal_, prefix, state_.get(),
- RTCForwardingStrategy::BEST_PATH);
- } else if ((interface::RtcTransportRecoveryStrategies)strategy ==
- interface::RtcTransportRecoveryStrategies::
- LOW_RATE_AND_REPLICATION) {
- fwd_strategy_.initFwdStrategy(portal_, prefix, state_.get(),
- RTCForwardingStrategy::REPLICATION);
- } else if ((interface::RtcTransportRecoveryStrategies)strategy ==
- interface::RtcTransportRecoveryStrategies::
- LOW_RATE_AND_ALL_FWD_STRATEGIES) {
- fwd_strategy_.initFwdStrategy(portal_, prefix, state_.get(),
- RTCForwardingStrategy::BOTH);
- }
-
+ fwd_strategy_.initFwdStrategy(
+ portal_, prefix, state_.get(),
+ (interface::RtcTransportRecoveryStrategies)strategy);
updateSyncWindow();
}
@@ -302,6 +296,12 @@ void RTCTransportProtocol::computeMaxSyncWindow() {
return;
}
+ bool content_sharing_mode;
+ socket_->getSocketOption(RtcTransportOptions::CONTENT_SHARING_MODE,
+ content_sharing_mode);
+ if (content_sharing_mode && (production_rate < MIN_PROD_RATE_SHARING_MODE))
+ production_rate = MIN_PROD_RATE_SHARING_MODE;
+
production_rate += (production_rate * indexer_verifier_->getMaxFecOverhead());
uint32_t lifetime = default_values::interest_lifetime;
@@ -330,6 +330,11 @@ void RTCTransportProtocol::updateSyncWindow() {
double prod_rate = state_->getProducerRate();
double rtt = (double)state_->getMinRTT() / MILLI_IN_A_SEC;
double packet_size = state_->getAveragePacketSize();
+ bool content_sharing_mode;
+ socket_->getSocketOption(RtcTransportOptions::CONTENT_SHARING_MODE,
+ content_sharing_mode);
+ if (content_sharing_mode && (prod_rate < MIN_PROD_RATE_SHARING_MODE))
+ prod_rate = MIN_PROD_RATE_SHARING_MODE;
// 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) {
@@ -385,6 +390,19 @@ void RTCTransportProtocol::sendProbeInterest(uint32_t seq) {
sendInterest(*interest_name);
}
+void RTCTransportProtocol::sendInterestForTimeout(uint32_t seq) {
+ if (!isRunning() && !is_first_) return;
+
+ Name *interest_name = nullptr;
+ socket_->getSocketOption(GeneralTransportOptions::NETWORK_NAME,
+ &interest_name);
+
+ // we got a timeout for this packet so it is not pending anymore
+ interest_name->setSuffix(seq);
+ state_->onSendNewInterest(interest_name);
+ sendInterest(*interest_name);
+}
+
void RTCTransportProtocol::scheduleNextInterests() {
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Schedule next interests";
@@ -475,9 +493,9 @@ void RTCTransportProtocol::scheduleNextInterests() {
}
// skip received packets
- if (indexer_verifier_->checkNextSuffix() <=
- state_->getHighestSeqReceivedInOrder()) {
- indexer_verifier_->jumpToIndex(state_->getHighestSeqReceivedInOrder() + 1);
+ uint32_t max_received = state_->getHighestSeqReceivedInOrder();
+ if (indexer_verifier_->checkNextSuffix() <= max_received) {
+ indexer_verifier_->jumpToIndex(max_received + 1);
}
uint32_t sent_interests = 0;
@@ -495,7 +513,6 @@ void RTCTransportProtocol::scheduleNextInterests() {
<< "In while loop. Window size: " << current_sync_win_;
uint32_t next_seg = indexer_verifier_->getNextSuffix();
-
name->setSuffix(next_seg);
// send the packet only if:
@@ -586,7 +603,6 @@ void RTCTransportProtocol::onInterestTimeout(Interest::Ptr &interest,
}
timeouts_or_nacks_.insert(segment_number);
-
if (TRANSPORT_EXPECT_TRUE(state_->isProducerActive()) &&
segment_number <= state_->getHighestSeqReceived()) {
// we retransmit packets only if the producer is active, otherwise we
@@ -627,11 +643,11 @@ void RTCTransportProtocol::onInterestTimeout(Interest::Ptr &interest,
<< "On timeout next seg = " << indexer_verifier_->checkNextSuffix()
<< ", jump to " << segment_number;
// add an extra space in the window
- current_sync_win_++;
indexer_verifier_->jumpToIndex(segment_number);
}
state_->onTimeout(segment_number, false);
+ sendInterestForTimeout(segment_number);
scheduleNextInterests();
}
@@ -672,7 +688,6 @@ void RTCTransportProtocol::onNack(const ContentObject &content_object) {
if (tn_it != timeouts_or_nacks_.end()) timeouts_or_nacks_.erase(tn_it);
state_->onJumpForward(production_seg);
- verifier_->onJumpForward(production_seg);
// 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
@@ -821,7 +836,8 @@ void RTCTransportProtocol::onContentObjectReceived(
// Check if the packet is a retransmission
if (ldr_->isRtx(segment_number) && state != PacketState::RECEIVED) {
if (is_data || is_manifest) {
- state_->onPacketRecoveredRtx(segment_number);
+ uint64_t rtt = ldr_->getRtxRtt(segment_number);
+ state_->onPacketRecoveredRtx(content_object, rtt);
if (*on_content_object_input_) {
(*on_content_object_input_)(*socket_->getInterface(), content_object);
@@ -842,7 +858,7 @@ void RTCTransportProtocol::onContentObjectReceived(
}
if (is_fec) {
- state_->onFecPacketRecoveredRtx(segment_number);
+ state_->onFecPacketRecoveredRtx(content_object);
}
}
@@ -920,7 +936,7 @@ void RTCTransportProtocol::sendStatsToApp(
stats_->updateAverageWindowSize(state_->getPendingInterestNumber());
stats_->updateLossRatio(state_->getPerSecondLossRate());
uint64_t rtt = state_->getAvgRTT();
- stats_->updateAverageRtt(utils::SteadyTime::Milliseconds(rtt));
+ stats_->updateAverageRtt(utils::SteadyTime::Microseconds(rtt * 1000));
stats_->updateQueuingDelay(state_->getQueuing());
stats_->updateLostData(lost_data);
@@ -960,9 +976,10 @@ void RTCTransportProtocol::decodePacket(ContentObject &content_object,
DLOG_IF(INFO, VLOG_IS_ON(4))
<< "Send packet " << content_object.getName() << " to FEC decoder";
- uint32_t offset = is_manifest
- ? content_object.headerSize()
- : content_object.headerSize() + rtc::DATA_HEADER_SIZE;
+ uint32_t offset =
+ is_manifest
+ ? (uint32_t)content_object.headerSize()
+ : (uint32_t)(content_object.headerSize() + rtc::DATA_HEADER_SIZE);
uint32_t metadata = static_cast<uint32_t>(content_object.getPayloadType());
fec_decoder_->onDataPacket(content_object, offset, metadata);
@@ -1016,7 +1033,7 @@ void RTCTransportProtocol::onFecPackets(fec::BufferArray &packets) {
processManifest(*interest, *content_object);
}
- state_->onPacketRecoveredFec(seq_number, buffer->length());
+ state_->onPacketRecoveredFec(seq_number, (uint32_t)buffer->length());
ldr_->onPacketRecoveredFec(seq_number);
if (payload_type == PayloadType::DATA) {
@@ -1038,11 +1055,11 @@ void RTCTransportProtocol::processManifest(Interest &interest,
ContentObject::Ptr RTCTransportProtocol::removeFecHeader(
const ContentObject &content_object) {
- if (!fec_decoder_ || !fec_decoder_->getFecHeaderSize()) {
+ if (!fec_decoder_ || !fec_decoder_->getFecHeaderSize(false)) {
return nullptr;
}
- size_t fec_header_size = fec_decoder_->getFecHeaderSize();
+ size_t fec_header_size = fec_decoder_->getFecHeaderSize(false);
const uint8_t *payload =
content_object.data() + content_object.headerSize() + fec_header_size;
size_t payload_size = content_object.payloadSize() - fec_header_size;
diff --git a/libtransport/src/protocols/rtc/rtc.h b/libtransport/src/protocols/rtc/rtc.h
index 3763f33c7..a8a474216 100644
--- a/libtransport/src/protocols/rtc/rtc.h
+++ b/libtransport/src/protocols/rtc/rtc.h
@@ -44,7 +44,7 @@ class RTCTransportProtocol : public TransportProtocol {
void resume() override;
- std::size_t transportHeaderLength() override;
+ std::size_t transportHeaderLength(bool isFEC) override;
auto shared_from_this() { return utils::shared_from(this); }
@@ -69,6 +69,7 @@ class RTCTransportProtocol : public TransportProtocol {
// packet functions
void sendRtxInterest(uint32_t seq);
void sendProbeInterest(uint32_t seq);
+ void sendInterestForTimeout(uint32_t seq);
void scheduleNextInterests() override;
void onInterestTimeout(Interest::Ptr &interest, const Name &name) override;
void onNack(const ContentObject &content_object);
diff --git a/libtransport/src/protocols/rtc/rtc_consts.h b/libtransport/src/protocols/rtc/rtc_consts.h
index 96e39d07e..29b5a3a12 100644
--- a/libtransport/src/protocols/rtc/rtc_consts.h
+++ b/libtransport/src/protocols/rtc/rtc_consts.h
@@ -54,7 +54,7 @@ const uint32_t PACING_WAIT = 1000; // usec to wait betwing two pacing batch. As
const uint32_t MAX_RTX_IN_BATCH = 10; // max rtx to send in loop
// packet const
-const uint32_t RTC_INTEREST_LIFETIME = 2000;
+const uint32_t RTC_INTEREST_LIFETIME = 4000;
// probes sequence range
const uint32_t MIN_PROBE_SEQ = 0xefffffff;
@@ -93,6 +93,7 @@ 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;
+const uint32_t MIN_PROD_RATE_SHARING_MODE = 125000; // 1Mbps in bytes
// round in congestion
const double ROUNDS_BEFORE_TAKE_ACTION = 5;
@@ -120,14 +121,14 @@ 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;
-const double MAX_RESIDUAL_LOSS_RATE = 2.0; // %
-const uint32_t WAIT_BEFORE_FEC_UPDATE = ROUNDS_PER_SEC * 5;
+const double MAX_RESIDUAL_LOSS_RATE = 1.0; // %
+const uint32_t WAIT_BEFORE_FEC_UPDATE = ROUNDS_PER_SEC;
+const uint32_t MAX_RTT_BEFORE_FEC = 60; // ms
// used by producer
const uint32_t PRODUCER_STATS_INTERVAL = 200; // ms
const uint32_t MIN_PRODUCTION_RATE = 25; // pps, equal to min window *
// rounds in a second
-const uint32_t NACK_DELAY = 1500; // ms
const uint32_t FEC_PACING_TIME = 5; // ms
// aggregated data consts
@@ -139,6 +140,73 @@ const uint32_t AGGREGATED_PACKETS_TIMER = 2; // ms
const uint32_t MAX_RTT = 200; // ms
const double MAX_RESIDUAL_LOSSES = 0.05; // %
+const uint8_t FEC_MATRIX[64][10] = {
+ {1, 2, 2, 2, 3, 3, 4, 5, 5, 6}, // k = 1
+ {1, 2, 3, 3, 4, 5, 5, 6, 7, 9},
+ {2, 2, 3, 4, 5, 6, 7, 8, 9, 11},
+ {2, 3, 4, 5, 5, 7, 8, 9, 11, 13},
+ {2, 3, 4, 5, 6, 7, 9, 10, 12, 14}, // k = 5
+ {2, 3, 4, 6, 7, 8, 10, 12, 14, 16},
+ {2, 4, 5, 6, 8, 9, 11, 13, 15, 18},
+ {3, 4, 5, 7, 8, 10, 12, 14, 16, 19},
+ {3, 4, 6, 7, 9, 11, 13, 15, 18, 21},
+ {3, 4, 6, 8, 9, 11, 14, 16, 19, 23}, // k = 10
+ {3, 5, 6, 8, 10, 12, 14, 17, 20, 24},
+ {3, 5, 7, 8, 10, 13, 15, 18, 21, 26},
+ {3, 5, 7, 9, 11, 13, 16, 19, 23, 27},
+ {3, 5, 7, 9, 12, 14, 17, 20, 24, 28},
+ {4, 6, 8, 10, 12, 15, 18, 21, 25, 30}, // k = 15
+ {4, 6, 8, 10, 13, 15, 19, 22, 26, 31},
+ {4, 6, 8, 11, 13, 16, 19, 23, 27, 33},
+ {4, 6, 9, 11, 14, 17, 20, 24, 29, 34},
+ {4, 6, 9, 11, 14, 17, 21, 25, 30, 35},
+ {4, 7, 9, 12, 15, 18, 22, 26, 31, 37}, // k = 20
+ {4, 7, 9, 12, 15, 19, 22, 27, 32, 38},
+ {4, 7, 10, 13, 16, 19, 23, 28, 33, 40},
+ {5, 7, 10, 13, 16, 20, 24, 29, 34, 41},
+ {5, 7, 10, 13, 17, 20, 25, 30, 35, 42},
+ {5, 8, 11, 14, 17, 21, 26, 31, 37, 44}, // k = 25
+ {5, 8, 11, 14, 18, 22, 26, 31, 38, 45},
+ {5, 8, 11, 15, 18, 22, 27, 32, 39, 46},
+ {5, 8, 11, 15, 19, 23, 28, 33, 40, 48},
+ {5, 8, 12, 15, 19, 24, 28, 34, 41, 49},
+ {5, 9, 12, 16, 20, 24, 29, 35, 42, 50}, // k = 30
+ {5, 9, 12, 16, 20, 25, 30, 36, 43, 51},
+ {5, 9, 13, 16, 21, 25, 31, 37, 44, 53},
+ {6, 9, 13, 17, 21, 26, 31, 38, 45, 54},
+ {6, 9, 13, 17, 22, 26, 32, 39, 46, 55},
+ {6, 10, 13, 17, 22, 27, 33, 40, 47, 57}, // k = 35
+ {6, 10, 14, 18, 22, 28, 34, 40, 48, 58},
+ {6, 10, 14, 18, 23, 28, 34, 41, 49, 59},
+ {6, 10, 14, 19, 23, 29, 35, 42, 50, 60},
+ {6, 10, 14, 19, 24, 29, 36, 43, 52, 62},
+ {6, 10, 15, 19, 24, 30, 36, 44, 53, 63}, // k = 40
+ {6, 11, 15, 20, 25, 31, 37, 45, 54, 64},
+ {6, 11, 15, 20, 25, 31, 38, 46, 55, 65},
+ {7, 11, 15, 20, 26, 32, 39, 46, 56, 67},
+ {7, 11, 16, 21, 26, 32, 39, 47, 57, 68},
+ {7, 11, 16, 21, 27, 33, 40, 48, 58, 69}, // k = 45
+ {7, 11, 16, 21, 27, 33, 41, 49, 59, 70},
+ {7, 12, 16, 22, 27, 34, 41, 50, 60, 72},
+ {7, 12, 17, 22, 28, 34, 42, 51, 61, 73},
+ {7, 12, 17, 22, 28, 35, 43, 52, 62, 74},
+ {7, 12, 17, 23, 29, 36, 43, 52, 63, 75}, // k = 50
+ {7, 12, 17, 23, 29, 36, 44, 53, 64, 77},
+ {7, 12, 18, 23, 30, 37, 45, 54, 65, 78},
+ {7, 13, 18, 24, 30, 37, 45, 55, 66, 79},
+ {8, 13, 18, 24, 31, 38, 46, 56, 67, 80},
+ {8, 13, 18, 24, 31, 38, 47, 57, 68, 82}, // k = 55
+ {8, 13, 19, 25, 31, 39, 47, 57, 69, 83},
+ {8, 13, 19, 25, 32, 39, 48, 58, 70, 84},
+ {8, 13, 19, 25, 32, 40, 49, 59, 71, 85},
+ {8, 14, 19, 26, 33, 41, 50, 60, 72, 86},
+ {8, 14, 20, 26, 33, 41, 50, 61, 73, 88}, // k = 60
+ {8, 14, 20, 26, 34, 42, 51, 61, 74, 89},
+ {8, 14, 20, 27, 34, 42, 52, 62, 75, 90},
+ {8, 14, 20, 27, 34, 43, 52, 63, 76, 91},
+ {8, 14, 21, 27, 35, 43, 53, 64, 77, 92}, // k = 64
+};
+
} // namespace rtc
} // namespace protocol
diff --git a/libtransport/src/protocols/rtc/rtc_data_path.cc b/libtransport/src/protocols/rtc/rtc_data_path.cc
index b3abf5ea8..a421396b1 100644
--- a/libtransport/src/protocols/rtc/rtc_data_path.cc
+++ b/libtransport/src/protocols/rtc/rtc_data_path.cc
@@ -91,6 +91,8 @@ void RTCDataPath::insertRttSample(
rtt_samples_ = 0;
last_avg_rtt_compute_ = now;
}
+
+ received_packets_++;
}
void RTCDataPath::insertOwdSample(int64_t owd) {
@@ -115,10 +117,6 @@ void RTCDataPath::insertOwdSample(int64_t owd) {
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_++;
}
void RTCDataPath::computeInterArrivalGap(uint32_t segment_number) {
@@ -150,12 +148,17 @@ double RTCDataPath::getInterArrivalGap() {
return avg_inter_arrival_;
}
-bool RTCDataPath::isActive() {
+bool RTCDataPath::isValidProducer() {
if (received_nacks_ && rounds_without_packets_ < MAX_ROUNDS_WITHOUT_PKTS)
return true;
return false;
}
+bool RTCDataPath::isActive() {
+ if (rounds_without_packets_ < MAX_ROUNDS_WITHOUT_PKTS) return true;
+ return false;
+}
+
bool RTCDataPath::pathToProducer() {
if (received_nacks_) return true;
return false;
diff --git a/libtransport/src/protocols/rtc/rtc_data_path.h b/libtransport/src/protocols/rtc/rtc_data_path.h
index 5afbbb87f..ba5201fe8 100644
--- a/libtransport/src/protocols/rtc/rtc_data_path.h
+++ b/libtransport/src/protocols/rtc/rtc_data_path.h
@@ -49,8 +49,9 @@ class RTCDataPath {
double getQueuingDealy();
double getInterArrivalGap();
double getJitter();
- bool isActive();
- bool pathToProducer();
+ bool isActive(); // pakets recevied from this path in the last rounds
+ bool pathToProducer(); // path from a producer
+ bool isValidProducer(); // path from a producer that is also active
uint64_t getLastPacketTS();
uint32_t getPacketsLastRound();
diff --git a/libtransport/src/protocols/rtc/rtc_forwarding_strategy.cc b/libtransport/src/protocols/rtc/rtc_forwarding_strategy.cc
index c6bc751e6..4bbd7eac0 100644
--- a/libtransport/src/protocols/rtc/rtc_forwarding_strategy.cc
+++ b/libtransport/src/protocols/rtc/rtc_forwarding_strategy.cc
@@ -14,6 +14,7 @@
*/
#include <hicn/transport/interfaces/notification.h>
+#include <protocols/rtc/rtc_consts.h>
#include <protocols/rtc/rtc_forwarding_strategy.h>
namespace transport {
@@ -24,8 +25,13 @@ namespace rtc {
using namespace transport::interface;
+const double FWD_MAX_QUEUE = 30.0; // ms
+const double FWD_MAX_RTT = MAX_RTT_BEFORE_FEC; // ms
+const double FWD_MAX_LOSS_RATE = 0.1;
+
RTCForwardingStrategy::RTCForwardingStrategy()
- : init_(false),
+ : low_rate_app_(false),
+ init_(false),
forwarder_set_(false),
selected_strategy_(NONE),
current_strategy_(NONE),
@@ -42,17 +48,56 @@ void RTCForwardingStrategy::setCallback(
void RTCForwardingStrategy::initFwdStrategy(
std::shared_ptr<core::Portal> portal, core::Prefix& prefix, RTCState* state,
- strategy_t strategy) {
- init_ = true;
- selected_strategy_ = strategy;
- if (strategy == BOTH)
- current_strategy_ = BEST_PATH;
- else
- current_strategy_ = strategy;
- rounds_since_last_set_ = 0;
- prefix_ = prefix;
- portal_ = portal;
- state_ = state;
+ interface::RtcTransportRecoveryStrategies strategy) {
+ switch (strategy) {
+ case interface::RtcTransportRecoveryStrategies::LOW_RATE_AND_BESTPATH:
+ init_ = true;
+ low_rate_app_ = true;
+ selected_strategy_ = BEST_PATH;
+ current_strategy_ = BEST_PATH;
+ break;
+ case interface::RtcTransportRecoveryStrategies::LOW_RATE_AND_REPLICATION:
+ init_ = true;
+ low_rate_app_ = true;
+ selected_strategy_ = REPLICATION;
+ current_strategy_ = REPLICATION;
+ break;
+ case interface::RtcTransportRecoveryStrategies::
+ LOW_RATE_AND_ALL_FWD_STRATEGIES:
+ init_ = true;
+ low_rate_app_ = true;
+ selected_strategy_ = BEST_PATH;
+ current_strategy_ = BEST_PATH;
+ break;
+ case interface::RtcTransportRecoveryStrategies::DELAY_AND_BESTPATH:
+ init_ = true;
+ low_rate_app_ = false;
+ selected_strategy_ = BEST_PATH;
+ current_strategy_ = BEST_PATH;
+ break;
+ case interface::RtcTransportRecoveryStrategies::DELAY_AND_REPLICATION:
+ init_ = true;
+ low_rate_app_ = false;
+ selected_strategy_ = REPLICATION;
+ current_strategy_ = REPLICATION;
+ break;
+ case interface::RtcTransportRecoveryStrategies::RECOVERY_OFF:
+ case interface::RtcTransportRecoveryStrategies::RTX_ONLY:
+ case interface::RtcTransportRecoveryStrategies::FEC_ONLY:
+ case interface::RtcTransportRecoveryStrategies::DELAY_BASED:
+ case interface::RtcTransportRecoveryStrategies::LOW_RATE:
+ case interface::RtcTransportRecoveryStrategies::FEC_ONLY_LOW_RES_LOSSES:
+ default:
+ // fwd strategies are not used
+ init_ = false;
+ }
+
+ if (init_) {
+ rounds_since_last_set_ = 0;
+ prefix_ = prefix;
+ portal_ = portal;
+ state_ = state;
+ }
}
void RTCForwardingStrategy::checkStrategy() {
@@ -99,16 +144,35 @@ void RTCForwardingStrategy::checkStrategyBestPath() {
return;
}
- uint8_t qs = state_->getQualityScore();
+ if (low_rate_app_) {
+ // this is used for gaming
+ uint8_t qs = state_->getQualityScore();
- if (qs >= 4 || rounds_since_last_set_ < 25) { // wait a least 5 sec
- // between each switch
- rounds_since_last_set_++;
- return;
- }
+ if (qs >= 4 || rounds_since_last_set_ < 25) { // wait a least 5 sec
+ // between each switch
+ rounds_since_last_set_++;
+ return;
+ }
- // try to switch path
- setStrategy(BEST_PATH);
+ // try to switch path
+ setStrategy(BEST_PATH);
+ } else {
+ if (rounds_since_last_set_ < 25) { // wait a least 5 sec
+ // between each switch
+ rounds_since_last_set_++;
+ return;
+ }
+
+ double queue = state_->getQueuing();
+ double rtt = state_->getAvgRTT();
+ double loss_rate = state_->getPerSecondLossRate();
+
+ if (queue >= FWD_MAX_QUEUE || rtt >= FWD_MAX_RTT ||
+ loss_rate > FWD_MAX_LOSS_RATE) {
+ // try to switch path
+ setStrategy(BEST_PATH);
+ }
+ }
}
void RTCForwardingStrategy::checkStrategyReplication() {
@@ -133,7 +197,7 @@ void RTCForwardingStrategy::checkStrategyBoth() {
// TODO
// for the moment we use only best path.
- // but later:
+ // for later:
// 1. if both paths are bad use replication
// 2. while using replication compute the effectiveness. if the majority of
// the packets are coming from a single path, try to use bestpath
diff --git a/libtransport/src/protocols/rtc/rtc_forwarding_strategy.h b/libtransport/src/protocols/rtc/rtc_forwarding_strategy.h
index 9825877fd..c2227e09f 100644
--- a/libtransport/src/protocols/rtc/rtc_forwarding_strategy.h
+++ b/libtransport/src/protocols/rtc/rtc_forwarding_strategy.h
@@ -41,7 +41,7 @@ class RTCForwardingStrategy {
void initFwdStrategy(std::shared_ptr<core::Portal> portal,
core::Prefix& prefix, RTCState* state,
- strategy_t strategy);
+ interface::RtcTransportRecoveryStrategies strategy);
void checkStrategy();
void setCallback(interface::StrategyCallback&& callback);
@@ -56,6 +56,10 @@ class RTCForwardingStrategy {
std::array<std::string, 4> string_strategies_ = {"bestpath", "replication",
"both", "none"};
+ bool low_rate_app_; // if set to true the best path strategy will
+ // trigger a path switch based on the quality
+ // score, otherwise it will use the RTT,
+ // queuing delay and loss rate
bool init_; // true if all val are initializes
bool forwarder_set_; // true if the strategy is been set at least
// once
diff --git a/libtransport/src/protocols/rtc/rtc_ldr.cc b/libtransport/src/protocols/rtc/rtc_ldr.cc
index abf6cda2c..6e88a8636 100644
--- a/libtransport/src/protocols/rtc/rtc_ldr.cc
+++ b/libtransport/src/protocols/rtc/rtc_ldr.cc
@@ -37,16 +37,24 @@ RTCLossDetectionAndRecovery::RTCLossDetectionAndRecovery(
interface::RtcTransportRecoveryStrategies type,
RecoveryStrategy::SendRtxCallback &&callback,
interface::StrategyCallback &&external_callback) {
- rs_type_ = type;
if (type == interface::RtcTransportRecoveryStrategies::RECOVERY_OFF) {
rs_ = std::make_shared<RecoveryStrategyRecoveryOff>(
- indexer, std::move(callback), io_service, std::move(external_callback));
- } else if (type == interface::RtcTransportRecoveryStrategies::DELAY_BASED) {
+ indexer, std::move(callback), io_service, type,
+ std::move(external_callback));
+ } else if (type == interface::RtcTransportRecoveryStrategies::DELAY_BASED ||
+ type == interface::RtcTransportRecoveryStrategies::
+ DELAY_AND_BESTPATH ||
+ type == interface::RtcTransportRecoveryStrategies::
+ DELAY_AND_REPLICATION) {
rs_ = std::make_shared<RecoveryStrategyDelayBased>(
- indexer, std::move(callback), io_service, std::move(external_callback));
- } else if (type == interface::RtcTransportRecoveryStrategies::FEC_ONLY) {
+ indexer, std::move(callback), io_service, type,
+ std::move(external_callback));
+ } else if (type == interface::RtcTransportRecoveryStrategies::FEC_ONLY ||
+ type == interface::RtcTransportRecoveryStrategies::
+ FEC_ONLY_LOW_RES_LOSSES) {
rs_ = std::make_shared<RecoveryStrategyFecOnly>(
- indexer, std::move(callback), io_service, std::move(external_callback));
+ indexer, std::move(callback), io_service, type,
+ std::move(external_callback));
} else if (type == interface::RtcTransportRecoveryStrategies::LOW_RATE ||
type == interface::RtcTransportRecoveryStrategies::
LOW_RATE_AND_BESTPATH ||
@@ -55,12 +63,14 @@ RTCLossDetectionAndRecovery::RTCLossDetectionAndRecovery(
type == interface::RtcTransportRecoveryStrategies::
LOW_RATE_AND_ALL_FWD_STRATEGIES) {
rs_ = std::make_shared<RecoveryStrategyLowRate>(
- indexer, std::move(callback), io_service, std::move(external_callback));
+ indexer, std::move(callback), io_service, type,
+ std::move(external_callback));
} else {
// default
- rs_type_ = interface::RtcTransportRecoveryStrategies::RTX_ONLY;
+ type = interface::RtcTransportRecoveryStrategies::RTX_ONLY;
rs_ = std::make_shared<RecoveryStrategyRtxOnly>(
- indexer, std::move(callback), io_service, std::move(external_callback));
+ indexer, std::move(callback), io_service, type,
+ std::move(external_callback));
}
}
@@ -68,15 +78,21 @@ RTCLossDetectionAndRecovery::~RTCLossDetectionAndRecovery() {}
void RTCLossDetectionAndRecovery::changeRecoveryStrategy(
interface::RtcTransportRecoveryStrategies type) {
- if (type == rs_type_) return;
+ if (type == rs_->getType()) return;
- rs_type_ = type;
+ rs_->updateType(type);
if (type == interface::RtcTransportRecoveryStrategies::RECOVERY_OFF) {
rs_ =
std::make_shared<RecoveryStrategyRecoveryOff>(std::move(*(rs_.get())));
- } else if (type == interface::RtcTransportRecoveryStrategies::DELAY_BASED) {
+ } else if (type == interface::RtcTransportRecoveryStrategies::DELAY_BASED ||
+ type == interface::RtcTransportRecoveryStrategies::
+ DELAY_AND_BESTPATH ||
+ type == interface::RtcTransportRecoveryStrategies::
+ DELAY_AND_REPLICATION) {
rs_ = std::make_shared<RecoveryStrategyDelayBased>(std::move(*(rs_.get())));
- } else if (type == interface::RtcTransportRecoveryStrategies::FEC_ONLY) {
+ } else if (type == interface::RtcTransportRecoveryStrategies::FEC_ONLY ||
+ type == interface::RtcTransportRecoveryStrategies::
+ FEC_ONLY_LOW_RES_LOSSES) {
rs_ = std::make_shared<RecoveryStrategyFecOnly>(std::move(*(rs_.get())));
} else if (type == interface::RtcTransportRecoveryStrategies::LOW_RATE ||
type == interface::RtcTransportRecoveryStrategies::
@@ -116,14 +132,15 @@ bool RTCLossDetectionAndRecovery::onDataPacketReceived(
uint32_t seq = content_object.getName().getSuffix();
bool is_rtx = rs_->isRtx(seq);
rs_->receivedPacket(seq);
+ bool ret = false;
DLOG_IF(INFO, VLOG_IS_ON(3))
<< "received data. add from "
- << rs_->getState()->getHighestSeqReceivedInOrder() + 1 << " to " << seq;
+ << rs_->getState()->getHighestSeqReceived() + 1 << " to " << seq;
if (!is_rtx)
- return detectLoss(rs_->getState()->getHighestSeqReceivedInOrder() + 1, seq,
- false);
+ ret = detectLoss(rs_->getState()->getHighestSeqReceived() + 1, seq, false);
- return false;
+ rs_->getState()->updateHighestSeqReceived(seq);
+ return ret;
}
bool RTCLossDetectionAndRecovery::onNackPacketReceived(
@@ -141,10 +158,9 @@ bool RTCLossDetectionAndRecovery::onNackPacketReceived(
// may got lost and we should ask them
rs_->receivedPacket(seq);
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "received nack. add from "
- << rs_->getState()->getHighestSeqReceivedInOrder() + 1 << " to "
- << production_seq;
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "received nack. add from "
+ << rs_->getState()->getHighestSeqReceived() + 1
+ << " to " << production_seq;
// if it is a future nack store it in the list set of nacked seq
if (production_seq <= seq) rs_->receivedFutureNack(seq);
@@ -152,7 +168,7 @@ bool RTCLossDetectionAndRecovery::onNackPacketReceived(
// call the detectLoss function using the probe flag = true. in fact the
// losses detected using nacks are the same as the one detected using probes,
// we should not increase the loss counter
- return detectLoss(rs_->getState()->getHighestSeqReceivedInOrder() + 1,
+ return detectLoss(rs_->getState()->getHighestSeqReceived() + 1,
production_seq, true);
}
@@ -164,12 +180,11 @@ bool RTCLossDetectionAndRecovery::onProbePacketReceived(
uint32_t production_seq = RTCState::getProbeParams(probe).prod_seg;
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "received probe. add from "
- << rs_->getState()->getHighestSeqReceivedInOrder() + 1 << " to "
- << production_seq;
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "received probe. add from "
+ << rs_->getState()->getHighestSeqReceived() + 1
+ << " to " << production_seq;
- return detectLoss(rs_->getState()->getHighestSeqReceivedInOrder() + 1,
+ return detectLoss(rs_->getState()->getHighestSeqReceived() + 1,
production_seq, true);
}
@@ -183,8 +198,8 @@ bool RTCLossDetectionAndRecovery::detectLoss(uint32_t start, uint32_t stop,
}
// skip received or lost packets
- if (start <= rs_->getState()->getHighestSeqReceivedInOrder()) {
- start = rs_->getState()->getHighestSeqReceivedInOrder() + 1;
+ if (start <= rs_->getState()->getHighestSeqReceived()) {
+ start = rs_->getState()->getHighestSeqReceived() + 1;
}
bool loss_detected = false;
diff --git a/libtransport/src/protocols/rtc/rtc_ldr.h b/libtransport/src/protocols/rtc/rtc_ldr.h
index 7f683eaa6..24f22ffed 100644
--- a/libtransport/src/protocols/rtc/rtc_ldr.h
+++ b/libtransport/src/protocols/rtc/rtc_ldr.h
@@ -47,6 +47,7 @@ class RTCLossDetectionAndRecovery
void setFecParams(uint32_t n, uint32_t k) { rs_->setFecParams(n, k); }
+ void setContentSharingMode() { rs_->setContentSharingMode(); }
void turnOnRecovery() { rs_->turnOnRecovery(); }
bool isRtxOn() { return rs_->isRtxOn(); }
@@ -68,11 +69,12 @@ class RTCLossDetectionAndRecovery
return rs_->isPossibleLossWithNoRtx(seq);
}
+ uint64_t getRtxRtt(uint32_t seq) { return rs_->getRtxRtt(seq); }
+
private:
// returns true if a loss is detected, false otherwise
bool detectLoss(uint32_t start, uint32_t stop, bool recv_probe);
- interface::RtcTransportRecoveryStrategies rs_type_;
std::shared_ptr<RecoveryStrategy> rs_;
};
diff --git a/libtransport/src/protocols/rtc/rtc_packet.h b/libtransport/src/protocols/rtc/rtc_packet.h
index 391aedfc6..ffbbd78fd 100644
--- a/libtransport/src/protocols/rtc/rtc_packet.h
+++ b/libtransport/src/protocols/rtc/rtc_packet.h
@@ -52,6 +52,8 @@
#include <hicn/transport/portability/win_portability.h>
#endif
+#include <hicn/transport/portability/endianess.h>
+
#include <cstring>
namespace transport {
@@ -60,24 +62,6 @@ 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
@@ -87,11 +71,19 @@ 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 uint64_t getTimestamp() const {
+ return portability::net_to_host(timestamp);
+ }
+ inline void setTimestamp(uint64_t time) {
+ timestamp = portability::host_to_net(time);
+ }
- inline uint32_t getProductionRate() const { return ntohl(prod_rate); }
- inline void setProductionRate(uint32_t rate) { prod_rate = htonl(rate); }
+ inline uint32_t getProductionRate() const {
+ return portability::net_to_host(prod_rate);
+ }
+ inline void setProductionRate(uint32_t rate) {
+ prod_rate = portability::host_to_net(rate);
+ }
};
struct nack_packet_t {
@@ -99,14 +91,26 @@ struct nack_packet_t {
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 uint64_t getTimestamp() const {
+ return portability::net_to_host(timestamp);
+ }
+ inline void setTimestamp(uint64_t time) {
+ timestamp = portability::host_to_net(time);
+ }
- inline uint32_t getProductionRate() const { return ntohl(prod_rate); }
- inline void setProductionRate(uint32_t rate) { prod_rate = htonl(rate); }
+ inline uint32_t getProductionRate() const {
+ return portability::net_to_host(prod_rate);
+ }
+ inline void setProductionRate(uint32_t rate) {
+ prod_rate = portability::host_to_net(rate);
+ }
- inline uint32_t getProductionSegment() const { return ntohl(prod_seg); }
- inline void setProductionSegment(uint32_t seg) { prod_seg = htonl(seg); }
+ inline uint32_t getProductionSegment() const {
+ return portability::net_to_host(prod_seg);
+ }
+ inline void setProductionSegment(uint32_t seg) {
+ prod_seg = portability::host_to_net(seg);
+ }
};
class AggrPktHeader {
@@ -225,7 +229,7 @@ class AggrPktHeader {
return (uint16_t) * (buf_ + pkt_index);
} else { // 16 bits
uint16_t *buf_16 = (uint16_t *)buf_;
- return ntohs(*(buf_16 + pkt_index));
+ return portability::net_to_host(*(buf_16 + pkt_index));
}
}
@@ -235,7 +239,7 @@ class AggrPktHeader {
*(buf_ + pkt_index) = (uint8_t)len;
} else { // 16 bits
uint16_t *buf_16 = (uint16_t *)buf_;
- *(buf_16 + pkt_index) = htons(len);
+ *(buf_16 + pkt_index) = portability::host_to_net(len);
}
}
diff --git a/libtransport/src/protocols/rtc/rtc_reassembly.cc b/libtransport/src/protocols/rtc/rtc_reassembly.cc
index 992bab50e..b1b0fcaba 100644
--- a/libtransport/src/protocols/rtc/rtc_reassembly.cc
+++ b/libtransport/src/protocols/rtc/rtc_reassembly.cc
@@ -40,7 +40,7 @@ void RtcReassembly::reassemble(core::ContentObject& content_object) {
auto read_buffer = content_object.getPayload();
DLOG_IF(INFO, VLOG_IS_ON(3)) << "Size of payload: " << read_buffer->length();
- read_buffer->trimStart(transport_protocol_->transportHeaderLength());
+ read_buffer->trimStart(transport_protocol_->transportHeaderLength(false));
if (data_aggregation_) {
rtc::AggrPktHeader hdr((uint8_t*)read_buffer->data());
diff --git a/libtransport/src/protocols/rtc/rtc_recovery_strategy.cc b/libtransport/src/protocols/rtc/rtc_recovery_strategy.cc
index 66ae5086c..257fdd09b 100644
--- a/libtransport/src/protocols/rtc/rtc_recovery_strategy.cc
+++ b/libtransport/src/protocols/rtc/rtc_recovery_strategy.cc
@@ -29,8 +29,12 @@ using namespace transport::interface;
RecoveryStrategy::RecoveryStrategy(
Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service,
- bool use_rtx, bool use_fec, interface::StrategyCallback &&external_callback)
- : recovery_on_(false),
+ bool use_rtx, bool use_fec,
+ interface::RtcTransportRecoveryStrategies rs_type,
+ interface::StrategyCallback &&external_callback)
+ : rs_type_(rs_type),
+ recovery_on_(false),
+ content_sharing_mode_(false),
rtx_during_fec_(0),
next_rtx_timer_(MAX_TIMER_RTX),
send_rtx_callback_(std::move(callback)),
@@ -43,7 +47,9 @@ RecoveryStrategy::RecoveryStrategy(
}
RecoveryStrategy::RecoveryStrategy(RecoveryStrategy &&rs)
- : rtx_during_fec_(0),
+ : rs_type_(rs.rs_type_),
+ content_sharing_mode_(rs.content_sharing_mode_),
+ rtx_during_fec_(0),
rtx_state_(std::move(rs.rtx_state_)),
rtx_timers_(std::move(rs.rtx_timers_)),
recover_with_fec_(std::move(rs.recover_with_fec_)),
@@ -64,25 +70,52 @@ RecoveryStrategy::RecoveryStrategy(RecoveryStrategy &&rs)
RecoveryStrategy::~RecoveryStrategy() {}
void RecoveryStrategy::setFecParams(uint32_t n, uint32_t k) {
+ // if rs_type == FEC_ONLY_LOW_RES_LOSSES max k == 64
n_ = n;
k_ = k;
// XXX for the moment we go in steps of 5% loss rate.
- // max loss rate = 95%
+ uint32_t i = 0;
for (uint32_t loss_rate = 5; loss_rate < 100; loss_rate += 5) {
- double dec_loss_rate = (double)(loss_rate + 5) / 100.0;
- double exp_losses = (double)k_ * dec_loss_rate;
- uint32_t fec_to_ask = ceil(exp_losses / (1 - dec_loss_rate));
-
- fec_state_ f;
- f.fec_to_ask = std::min(fec_to_ask, (n_ - k_));
- f.last_update = round_id_;
- f.avg_residual_losses = 0.0;
- f.consecutive_use = 0;
- fec_per_loss_rate_.push_back(f);
+ uint32_t fec_to_ask = 0;
+ if (n_ != 0 && k_ != 0) {
+ if (rs_type_ ==
+ interface::RtcTransportRecoveryStrategies::FEC_ONLY_LOW_RES_LOSSES) {
+ // the max loss rate in the matrix is 50%
+ uint32_t index = i;
+ if (i > 9) index = 9;
+ fec_to_ask = FEC_MATRIX[k_ - 1][index];
+ } else {
+ double dec_loss_rate = (double)(loss_rate + 5);
+ if (dec_loss_rate == 100.0) dec_loss_rate = 95.0;
+ dec_loss_rate = dec_loss_rate / 100.0;
+ double exp_losses = ceil((double)k_ * dec_loss_rate);
+ fec_to_ask = ceil((exp_losses / (1 - dec_loss_rate)) * 1.25);
+ }
+ }
+ fec_to_ask = std::min(fec_to_ask, (n_ - k_));
+ fec_per_loss_rate_.push_back(fec_to_ask);
+
+ i++;
}
}
+uint64_t RecoveryStrategy::getRtxRtt(uint32_t seq) {
+ auto it = rtx_state_.find(seq);
+
+ if (it == rtx_state_.end()) return 0;
+
+ // we can compute the RTT of an RTX only if it was send once. Infact if the
+ // RTX was sent twice or more the data may be alredy in flight and the RTT
+ // will be underestimated. This may happen also for packets that we
+ // retransmitted too soon. in that case the RTT will be filtered out by
+ // checking the path label
+ if (it->second.rtx_count_ != 1) return 0;
+
+ // this a potentialy valid packet, compute the RTT
+ return (utils::SteadyTime::nowMs().count() - it->second.last_send_);
+}
+
bool RecoveryStrategy::lossDetected(uint32_t seq) {
if (isRtx(seq)) {
// this packet is already in the list of rtx
@@ -141,8 +174,10 @@ void RecoveryStrategy::addNewRtx(uint32_t seq, bool force) {
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.last_send_ = state.first_send_; // we didn't send an RTX for this
+ // packet yet
state.rtx_count_ = 0;
+ state.next_send_ = computeNextSend(seq, state.rtx_count_);
DLOG_IF(INFO, VLOG_IS_ON(4))
<< "Add " << seq << " to retransmissions. next rtx is in "
<< state.next_send_ - getNow() << " ms";
@@ -158,66 +193,50 @@ void RecoveryStrategy::addNewRtx(uint32_t seq, bool force) {
}
}
-uint64_t RecoveryStrategy::computeNextSend(uint32_t seq, bool new_rtx) {
+uint64_t RecoveryStrategy::computeNextSend(uint32_t seq, uint32_t rtx_counter) {
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 (rtx_counter == 0) {
+ uint32_t wait = 1;
+ if (content_sharing_mode_) return now + wait;
- if (prod_rate != 0) {
- double packet_size = state_->getAveragePacketSize();
- estimated_iat = ceil(1000.0 / (prod_rate / packet_size));
- jitter = ceil(state_->getJitter());
- }
+ uint32_t jitter = SENTINEL_TIMER_INTERVAL;
+ double prod_rate = state_->getProducerRate();
+ if (prod_rate != 0) jitter = ceil(state_->getJitter());
- uint32_t wait = 1;
- if (estimated_iat < 18) {
- // for low rate app we do not wait to send a RTX
- // we consider low rate stream with less than 50pps (iat >= 20ms)
- // (e.g. audio in videoconf, mobile games).
- // in the check we use 18ms to accomodate for measurements errors
- // for flows with higher rate wait 1 ait + jitter
- wait = estimated_iat + jitter;
- }
+ wait += jitter;
- DLOG_IF(INFO, VLOG_IS_ON(3))
- << "first rtx for " << seq << " in " << wait
- << " ms, rtt = " << state_->getMinRTT() << " ait = " << estimated_iat
- << " jttr = " << jitter;
+ DLOG_IF(INFO, VLOG_IS_ON(3)) << "first rtx for " << seq << " in " << wait
+ << " ms, jitter = " << jitter;
return now + wait;
} else {
- // wait one RTT
- uint32_t wait = SENTINEL_TIMER_INTERVAL;
-
+ // wait one RTT. if an edge is known use the edge RTT for the first 5 rtx
double prod_rate = state_->getProducerRate();
if (prod_rate == 0) {
return now + SENTINEL_TIMER_INTERVAL;
}
- double packet_size = state_->getAveragePacketSize();
- uint32_t estimated_iat = ceil(1000.0 / (prod_rate / packet_size));
+ uint64_t rtt = 0;
+ // if the transport detects an edge we try first to get the RTX from the
+ // edge. if no interest get a reply we move to the full RTT
+ if (rtx_counter < 5 && (state_->getEdgeRtt() != 0)) {
+ rtt = state_->getEdgeRtt();
+ } else {
+ rtt = state_->getAvgRTT();
+ }
- uint64_t rtt = state_->getMinRTT();
if (rtt == 0) rtt = SENTINEL_TIMER_INTERVAL;
- wait = rtt;
+
+ if (content_sharing_mode_) return now + rtt;
+
+ uint32_t wait = (uint32_t)rtt;
uint32_t jitter = 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 = ceil(state_->getQueuing());
- wait += queue;
-
DLOG_IF(INFO, VLOG_IS_ON(3))
- << "next rtx for " << seq << " in " << wait
- << " ms, rtt = " << state_->getMinRTT() << " ait = " << estimated_iat
- << " jttr = " << jitter << " queue = " << queue;
+ << "next rtx for " << seq << " in " << wait << " ms, rtt = " << rtt
+ << " jtter = " << jitter;
return now + wait;
}
@@ -252,7 +271,9 @@ void RecoveryStrategy::retransmit() {
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);
+ rtx_it->second.last_send_ = now;
+ rtx_it->second.next_send_ =
+ computeNextSend(seq, rtx_it->second.rtx_count_);
it = rtx_timers_.erase(it);
rtx_timers_.insert(
std::pair<uint64_t, uint32_t>(rtx_it->second.next_send_, seq));
@@ -327,6 +348,7 @@ void RecoveryStrategy::deleteRtx(uint32_t seq) {
}
it_timers++;
}
+
// remove rtx
rtx_state_.erase(it_rtx);
}
@@ -339,53 +361,13 @@ uint32_t RecoveryStrategy::computeFecPacketsToAsk() {
if (loss_rate == 0) return 0;
- // once per minute try to reduce the fec rate. it may happen that for some bin
- // we ask too many fec packet. here we try to reduce this values gently
- if (round_id_ % ROUNDS_PER_MIN == 0) {
- reduceFec();
- }
-
// keep track of the last used fec. if we use a new bin on this round reset
// consecutive use and avg loss in the prev bin
uint32_t bin = ceil(loss_rate / 5.0) - 1;
- if (bin > fec_per_loss_rate_.size() - 1) bin = fec_per_loss_rate_.size() - 1;
+ if (bin > fec_per_loss_rate_.size() - 1)
+ bin = (uint32_t)fec_per_loss_rate_.size() - 1;
- if (bin != last_fec_used_) {
- fec_per_loss_rate_[last_fec_used_].consecutive_use = 0;
- fec_per_loss_rate_[last_fec_used_].avg_residual_losses = 0.0;
- }
- last_fec_used_ = bin;
- fec_per_loss_rate_[last_fec_used_].consecutive_use++;
-
- // we update the stats only once very 5 rounds (1sec) that is the rate at
- // which we compute residual losses
- if (round_id_ % ROUNDS_PER_SEC == 0) {
- double residual_losses = state_->getResidualLossRate() * 100;
- // update residual loss rate
- fec_per_loss_rate_[bin].avg_residual_losses =
- (fec_per_loss_rate_[bin].avg_residual_losses * MOVING_AVG_ALPHA) +
- (1 - MOVING_AVG_ALPHA) * residual_losses;
-
- if ((fec_per_loss_rate_[bin].last_update - round_id_) <
- WAIT_BEFORE_FEC_UPDATE) {
- // this bin is been updated recently so don't modify it and
- // return the current state
- return fec_per_loss_rate_[bin].fec_to_ask;
- }
-
- // if the residual loss rate is too high and we can ask more fec packets and
- // we are using this configuration since at least 5 sec update fec
- if (fec_per_loss_rate_[bin].avg_residual_losses > MAX_RESIDUAL_LOSS_RATE &&
- fec_per_loss_rate_[bin].fec_to_ask < (n_ - k_) &&
- fec_per_loss_rate_[bin].consecutive_use > WAIT_BEFORE_FEC_UPDATE) {
- // so increase the number of fec packets to ask
- fec_per_loss_rate_[bin].fec_to_ask++;
- fec_per_loss_rate_[bin].last_update = round_id_;
- fec_per_loss_rate_[bin].avg_residual_losses = 0.0;
- }
- }
-
- return fec_per_loss_rate_[bin].fec_to_ask;
+ return fec_per_loss_rate_[bin];
}
void RecoveryStrategy::setRtxFec(std::optional<bool> rtx_on,
@@ -431,21 +413,6 @@ void RecoveryStrategy::removePacketState(uint32_t seq) {
deleteRtx(seq);
}
-// private methods
-
-void RecoveryStrategy::reduceFec() {
- for (uint32_t loss_rate = 5; loss_rate < 100; loss_rate += 5) {
- double dec_loss_rate = (double)loss_rate / 100.0;
- double exp_losses = (double)k_ * dec_loss_rate;
- uint32_t fec_to_ask = ceil(exp_losses / (1 - dec_loss_rate));
-
- uint32_t bin = ceil(loss_rate / 5.0) - 1;
- if (fec_per_loss_rate_[bin].fec_to_ask > fec_to_ask) {
- fec_per_loss_rate_[bin].fec_to_ask--;
- }
- }
-}
-
} // end namespace rtc
} // end namespace protocol
diff --git a/libtransport/src/protocols/rtc/rtc_recovery_strategy.h b/libtransport/src/protocols/rtc/rtc_recovery_strategy.h
index 482aedc9d..aceb85888 100644
--- a/libtransport/src/protocols/rtc/rtc_recovery_strategy.h
+++ b/libtransport/src/protocols/rtc/rtc_recovery_strategy.h
@@ -32,9 +32,10 @@ namespace rtc {
class RecoveryStrategy : public std::enable_shared_from_this<RecoveryStrategy> {
protected:
struct rtx_state_ {
- uint64_t first_send_;
- uint64_t next_send_;
- uint32_t rtx_count_;
+ uint64_t first_send_; // first time this interest was sent
+ uint64_t last_send_; // last time this rtx was sent
+ uint64_t next_send_; // next retransmission time
+ uint32_t rtx_count_; // number or rtx
};
using rtxState = struct rtx_state_;
@@ -44,6 +45,7 @@ class RecoveryStrategy : public std::enable_shared_from_this<RecoveryStrategy> {
RecoveryStrategy(Indexer *indexer, SendRtxCallback &&callback,
asio::io_service &io_service, bool use_rtx, bool use_fec,
+ interface::RtcTransportRecoveryStrategies rs_type,
interface::StrategyCallback &&external_callback);
RecoveryStrategy(RecoveryStrategy &&rs);
@@ -55,6 +57,7 @@ class RecoveryStrategy : public std::enable_shared_from_this<RecoveryStrategy> {
void setState(RTCState *state) { state_ = state; }
void setRateControl(RTCRateControl *rateControl) { rc_ = rateControl; }
void setFecParams(uint32_t n, uint32_t k);
+ void setContentSharingMode() { content_sharing_mode_ = true; }
bool isRtx(uint32_t seq) {
if (rtx_state_.find(seq) != rtx_state_.end()) return true;
@@ -71,10 +74,20 @@ class RecoveryStrategy : public std::enable_shared_from_this<RecoveryStrategy> {
return false;
}
+ interface::RtcTransportRecoveryStrategies getType() {
+ return rs_type_;
+ }
+ void updateType(interface::RtcTransportRecoveryStrategies type) {
+ rs_type_ = type;
+ }
bool isRtxOn() { return rtx_on_; }
bool isFecOn() { return fec_on_; }
RTCState *getState() { return state_; }
+
+ // if the function returns 0 it means that the packet is not an RTX or it is
+ // not a valid packet to safely compute the RTT
+ uint64_t getRtxRtt(uint32_t seq);
bool lossDetected(uint32_t seq);
void notifyNewLossDetedcted(uint32_t seq);
void requestPossibleLostPacket(uint32_t seq);
@@ -98,7 +111,7 @@ class RecoveryStrategy : public std::enable_shared_from_this<RecoveryStrategy> {
protected:
// rtx functions
void addNewRtx(uint32_t seq, bool force);
- uint64_t computeNextSend(uint32_t seq, bool new_rtx);
+ uint64_t computeNextSend(uint32_t seq, uint32_t rtx_counter);
void retransmit();
void scheduleNextRtx();
void deleteRtx(uint32_t seq);
@@ -109,9 +122,11 @@ class RecoveryStrategy : public std::enable_shared_from_this<RecoveryStrategy> {
// common functons
void removePacketState(uint32_t seq);
+ interface::RtcTransportRecoveryStrategies rs_type_;
bool recovery_on_;
bool rtx_on_;
bool fec_on_;
+ bool content_sharing_mode_;
// number of RTX sent after fec turned on
// this is used to take into account jitter and out of order packets
@@ -152,19 +167,9 @@ class RecoveryStrategy : public std::enable_shared_from_this<RecoveryStrategy> {
RTCRateControl *rc_;
private:
- struct fec_state_ {
- uint32_t fec_to_ask;
- uint32_t last_update; // round id of the last update
- // (wait 10 ruonds (2sec) between updates)
- uint32_t consecutive_use; // consecutive ruonds where this fec was used
- double avg_residual_losses;
- };
-
- void reduceFec();
-
uint32_t round_id_; // number of rounds
uint32_t last_fec_used_;
- std::vector<fec_state_> fec_per_loss_rate_;
+ std::vector<uint32_t> fec_per_loss_rate_;
interface::StrategyCallback callback_;
};
diff --git a/libtransport/src/protocols/rtc/rtc_rs_delay.cc b/libtransport/src/protocols/rtc/rtc_rs_delay.cc
index 4be751ec9..7d7a01133 100644
--- a/libtransport/src/protocols/rtc/rtc_rs_delay.cc
+++ b/libtransport/src/protocols/rtc/rtc_rs_delay.cc
@@ -25,8 +25,10 @@ namespace rtc {
RecoveryStrategyDelayBased::RecoveryStrategyDelayBased(
Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service,
+ interface::RtcTransportRecoveryStrategies rs_type,
interface::StrategyCallback &&external_callback)
: RecoveryStrategy(indexer, std::move(callback), io_service, true, false,
+ rs_type,
std::move(external_callback)), // start with rtx
congestion_state_(false),
probing_state_(false),
@@ -48,7 +50,7 @@ void RecoveryStrategyDelayBased::turnOnRecovery() {
recovery_on_ = true;
uint64_t rtt = state_->getMinRTT();
uint32_t fec_to_ask = computeFecPacketsToAsk();
- if (rtt > 80 && fec_to_ask != 0) {
+ if (rtt > MAX_RTT_BEFORE_FEC && fec_to_ask > 0) {
// we need to start FEC (see fec only strategy for more details)
setRtxFec(true, true);
rtx_during_fec_ = 1; // avoid to stop fec
@@ -84,16 +86,16 @@ void RecoveryStrategyDelayBased::onNewRound(bool in_sync) {
return;
}
- uint64_t rtt = state_->getMinRTT();
+ uint64_t rtt = state_->getAvgRTT();
- bool congestion = false;
// XXX at the moment we are not looking at congestion events
- // congestion = rc_->inCongestionState();
+ // bool congestion = rc_->inCongestionState();
- if ((!fec_on_ && rtt >= 100) || (fec_on_ && rtt > 80) || congestion) {
+ if ((!fec_on_ && rtt >= MAX_RTT_BEFORE_FEC) ||
+ (fec_on_ && rtt > (MAX_RTT_BEFORE_FEC - 10))) {
// switch from rtx to fec or keep use fec. Notice that if some rtx are
// waiting to be scheduled, they will be sent normally, but no new rtx will
- // be created If the loss rate is 0 keep to use RTX.
+ // be created if the loss rate is 0 keep to use RTX.
uint32_t fec_to_ask = computeFecPacketsToAsk();
softSwitchToFec(fec_to_ask);
if (rtx_during_fec_ == 0) // if we do not send any RTX the losses
@@ -104,7 +106,8 @@ void RecoveryStrategyDelayBased::onNewRound(bool in_sync) {
return;
}
- if ((fec_on_ && rtt <= 80) || (!rtx_on_ && rtt <= 100)) {
+ if ((fec_on_ && rtt <= (MAX_RTT_BEFORE_FEC - 10)) ||
+ (!rtx_on_ && rtt <= MAX_RTT_BEFORE_FEC)) {
// turn on rtx
softSwitchToFec(0);
indexer_->setNFec(0);
diff --git a/libtransport/src/protocols/rtc/rtc_rs_delay.h b/libtransport/src/protocols/rtc/rtc_rs_delay.h
index 5ca90f4cb..9e1c41388 100644
--- a/libtransport/src/protocols/rtc/rtc_rs_delay.h
+++ b/libtransport/src/protocols/rtc/rtc_rs_delay.h
@@ -26,6 +26,7 @@ class RecoveryStrategyDelayBased : public RecoveryStrategy {
public:
RecoveryStrategyDelayBased(Indexer *indexer, SendRtxCallback &&callback,
asio::io_service &io_service,
+ interface::RtcTransportRecoveryStrategies rs_type,
interface::StrategyCallback &&external_callback);
RecoveryStrategyDelayBased(RecoveryStrategy &&rs);
diff --git a/libtransport/src/protocols/rtc/rtc_rs_fec_only.cc b/libtransport/src/protocols/rtc/rtc_rs_fec_only.cc
index c44212bda..5b10823ec 100644
--- a/libtransport/src/protocols/rtc/rtc_rs_fec_only.cc
+++ b/libtransport/src/protocols/rtc/rtc_rs_fec_only.cc
@@ -25,9 +25,10 @@ namespace rtc {
RecoveryStrategyFecOnly::RecoveryStrategyFecOnly(
Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service,
+ interface::RtcTransportRecoveryStrategies rs_type,
interface::StrategyCallback &&external_callback)
: RecoveryStrategy(indexer, std::move(callback), io_service, true, false,
- std::move(external_callback)),
+ rs_type, std::move(external_callback)),
congestion_state_(false),
probing_state_(false),
switch_rounds_(0) {}
diff --git a/libtransport/src/protocols/rtc/rtc_rs_fec_only.h b/libtransport/src/protocols/rtc/rtc_rs_fec_only.h
index 1ab78b842..42df25bd9 100644
--- a/libtransport/src/protocols/rtc/rtc_rs_fec_only.h
+++ b/libtransport/src/protocols/rtc/rtc_rs_fec_only.h
@@ -26,6 +26,7 @@ class RecoveryStrategyFecOnly : public RecoveryStrategy {
public:
RecoveryStrategyFecOnly(Indexer *indexer, SendRtxCallback &&callback,
asio::io_service &io_service,
+ interface::RtcTransportRecoveryStrategies rs_type,
interface::StrategyCallback &&external_callback);
RecoveryStrategyFecOnly(RecoveryStrategy &&rs);
diff --git a/libtransport/src/protocols/rtc/rtc_rs_low_rate.cc b/libtransport/src/protocols/rtc/rtc_rs_low_rate.cc
index 48dd3e34f..dbad563cd 100644
--- a/libtransport/src/protocols/rtc/rtc_rs_low_rate.cc
+++ b/libtransport/src/protocols/rtc/rtc_rs_low_rate.cc
@@ -25,8 +25,10 @@ namespace rtc {
RecoveryStrategyLowRate::RecoveryStrategyLowRate(
Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service,
+ interface::RtcTransportRecoveryStrategies rs_type,
interface::StrategyCallback &&external_callback)
: RecoveryStrategy(indexer, std::move(callback), io_service, false, true,
+ rs_type,
std::move(external_callback)), // start with fec
fec_consecutive_rounds_((MILLI_IN_A_SEC / ROUND_LEN) * 5), // 5 sec
rtx_allowed_consecutive_rounds_(0) {
@@ -75,7 +77,7 @@ void RecoveryStrategyLowRate::selectRecoveryStrategy(bool in_sync) {
}
uint32_t loss_rate = std::round(state_->getPerSecondLossRate() * 100);
- uint32_t rtt = state_->getAvgRTT();
+ uint32_t rtt = (uint32_t)state_->getAvgRTT();
bool use_rtx = false;
for (size_t i = 0; i < switch_vector.size(); i++) {
diff --git a/libtransport/src/protocols/rtc/rtc_rs_low_rate.h b/libtransport/src/protocols/rtc/rtc_rs_low_rate.h
index d66b197e2..0e76efaca 100644
--- a/libtransport/src/protocols/rtc/rtc_rs_low_rate.h
+++ b/libtransport/src/protocols/rtc/rtc_rs_low_rate.h
@@ -34,6 +34,7 @@ class RecoveryStrategyLowRate : public RecoveryStrategy {
public:
RecoveryStrategyLowRate(Indexer *indexer, SendRtxCallback &&callback,
asio::io_service &io_service,
+ interface::RtcTransportRecoveryStrategies rs_type,
interface::StrategyCallback &&external_callback);
RecoveryStrategyLowRate(RecoveryStrategy &&rs);
diff --git a/libtransport/src/protocols/rtc/rtc_rs_recovery_off.cc b/libtransport/src/protocols/rtc/rtc_rs_recovery_off.cc
index 16b14eff6..00c6a0504 100644
--- a/libtransport/src/protocols/rtc/rtc_rs_recovery_off.cc
+++ b/libtransport/src/protocols/rtc/rtc_rs_recovery_off.cc
@@ -25,9 +25,10 @@ namespace rtc {
RecoveryStrategyRecoveryOff::RecoveryStrategyRecoveryOff(
Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service,
+ interface::RtcTransportRecoveryStrategies rs_type,
interface::StrategyCallback &&external_callback)
: RecoveryStrategy(indexer, std::move(callback), io_service, false, false,
- std::move(external_callback)) {}
+ rs_type, std::move(external_callback)) {}
RecoveryStrategyRecoveryOff::RecoveryStrategyRecoveryOff(RecoveryStrategy &&rs)
: RecoveryStrategy(std::move(rs)) {
diff --git a/libtransport/src/protocols/rtc/rtc_rs_recovery_off.h b/libtransport/src/protocols/rtc/rtc_rs_recovery_off.h
index 3a9e71e7d..3d59cc473 100644
--- a/libtransport/src/protocols/rtc/rtc_rs_recovery_off.h
+++ b/libtransport/src/protocols/rtc/rtc_rs_recovery_off.h
@@ -26,6 +26,7 @@ class RecoveryStrategyRecoveryOff : public RecoveryStrategy {
public:
RecoveryStrategyRecoveryOff(Indexer *indexer, SendRtxCallback &&callback,
asio::io_service &io_service,
+ interface::RtcTransportRecoveryStrategies rs_type,
interface::StrategyCallback &&external_callback);
RecoveryStrategyRecoveryOff(RecoveryStrategy &&rs);
diff --git a/libtransport/src/protocols/rtc/rtc_rs_rtx_only.cc b/libtransport/src/protocols/rtc/rtc_rs_rtx_only.cc
index 8e5db5439..4d7cf7a82 100644
--- a/libtransport/src/protocols/rtc/rtc_rs_rtx_only.cc
+++ b/libtransport/src/protocols/rtc/rtc_rs_rtx_only.cc
@@ -25,9 +25,10 @@ namespace rtc {
RecoveryStrategyRtxOnly::RecoveryStrategyRtxOnly(
Indexer *indexer, SendRtxCallback &&callback, asio::io_service &io_service,
+ interface::RtcTransportRecoveryStrategies rs_type,
interface::StrategyCallback &&external_callback)
: RecoveryStrategy(indexer, std::move(callback), io_service, true, false,
- std::move(external_callback)) {}
+ rs_type, std::move(external_callback)) {}
RecoveryStrategyRtxOnly::RecoveryStrategyRtxOnly(RecoveryStrategy &&rs)
: RecoveryStrategy(std::move(rs)) {
diff --git a/libtransport/src/protocols/rtc/rtc_rs_rtx_only.h b/libtransport/src/protocols/rtc/rtc_rs_rtx_only.h
index e90e5ba13..03dbed1c7 100644
--- a/libtransport/src/protocols/rtc/rtc_rs_rtx_only.h
+++ b/libtransport/src/protocols/rtc/rtc_rs_rtx_only.h
@@ -26,6 +26,7 @@ class RecoveryStrategyRtxOnly : public RecoveryStrategy {
public:
RecoveryStrategyRtxOnly(Indexer *indexer, SendRtxCallback &&callback,
asio::io_service &io_service,
+ interface::RtcTransportRecoveryStrategies rs_type,
interface::StrategyCallback &&external_callback);
RecoveryStrategyRtxOnly(RecoveryStrategy &&rs);
diff --git a/libtransport/src/protocols/rtc/rtc_state.cc b/libtransport/src/protocols/rtc/rtc_state.cc
index 5b3b5e4c3..82ac0b9c1 100644
--- a/libtransport/src/protocols/rtc/rtc_state.cc
+++ b/libtransport/src/protocols/rtc/rtc_state.cc
@@ -106,6 +106,7 @@ void RTCState::initParams() {
// paths stats
path_table_.clear();
main_path_ = nullptr;
+ edge_path_ = nullptr;
// packet cache (not pending anymore)
packet_cache_.clear();
@@ -231,11 +232,9 @@ void RTCState::onDataPacketReceived(const core::ContentObject &content_object,
}
updatePacketSize(content_object);
- updateReceivedBytes(content_object);
+ updateReceivedBytes(content_object, false);
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;
@@ -245,11 +244,7 @@ void RTCState::onDataPacketReceived(const core::ContentObject &content_object,
void RTCState::onFecPacketReceived(const core::ContentObject &content_object) {
uint32_t seq = content_object.getName().getSuffix();
- // updateReceivedBytes(content_object);
- received_fec_bytes_ +=
- (uint32_t)(content_object.headerSize() + content_object.payloadSize());
-
- if (seq > highest_seq_received_) highest_seq_received_ = seq;
+ updateReceivedBytes(content_object, true);
PacketState state = getPacketState(seq);
if (state != PacketState::LOST) {
@@ -328,12 +323,14 @@ void RTCState::onPacketLost(uint32_t seq) {
DLOG_IF(INFO, VLOG_IS_ON(4)) << "packet " << seq << " is lost";
}
}
+
addRecvOrLost(seq, PacketState::DEFINITELY_LOST);
}
-void RTCState::onPacketRecoveredRtx(uint32_t seq) {
+void RTCState::onPacketRecoveredRtx(const core::ContentObject &content_object,
+ uint64_t rtt) {
+ uint32_t seq = content_object.getName().getSuffix();
packets_sent_to_app_++;
- if (seq > highest_seq_received_) highest_seq_received_ = seq;
// increase the recovered packet counter only if the packet was marked as LOST
// before.
@@ -341,13 +338,37 @@ void RTCState::onPacketRecoveredRtx(uint32_t seq) {
if (state == PacketState::LOST) losses_recovered_++;
addRecvOrLost(seq, PacketState::RECEIVED);
+ updateReceivedBytes(content_object, false);
+
+ if (rtt == 0) return; // nothing to do
+
+ uint32_t path_label = content_object.getPathLabel();
+ auto path_it = path_table_.find(path_label);
+ if (path_it == path_table_.end()) {
+ // this is a new path and it must be a cache
+ 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;
+ if (path->pathToProducer())
+ return; // this packet is coming from a producer
+ // even if we sent an RTX. this may happen
+ // for RTX that are sent too fast or in
+ // case of multipath
+
+ path->insertRttSample(utils::SteadyTime::Milliseconds(rtt), true);
}
-void RTCState::onFecPacketRecoveredRtx(uint32_t seq) {
+void RTCState::onFecPacketRecoveredRtx(
+ const core::ContentObject &content_object) {
// This is the same as onPacketRecoveredRtx, but in this is case the
// pkt is also a FEC pkt, the addRecvOrLost will be called afterwards
- if (seq > highest_seq_received_) highest_seq_received_ = seq;
losses_recovered_++;
+ updateReceivedBytes(content_object, true);
}
void RTCState::onPacketRecoveredFec(uint32_t seq, uint32_t size) {
@@ -355,8 +376,6 @@ void RTCState::onPacketRecoveredFec(uint32_t seq, uint32_t size) {
packets_sent_to_app_++;
recovered_bytes_with_fec_ += size;
- if (seq > highest_seq_received_) highest_seq_received_ = seq;
-
// adding header to the count
recovered_bytes_with_fec_ += 60; // XXX get header size some where
@@ -487,21 +506,32 @@ void RTCState::onNewRound(double round_len, bool in_sync) {
// channel losses
uint32_t last_round_packets = 0;
+ uint64_t min_edge_rtt = UINT_MAX;
std::shared_ptr<RTCDataPath> old_main_path = main_path_;
main_path_ = nullptr;
+ edge_path_ = nullptr;
for (auto it = path_table_.begin(); it != path_table_.end(); it++) {
- if (it->second->isActive()) {
+ if (it->second->isValidProducer()) {
uint32_t pkt = it->second->getPacketsLastRound();
if (pkt > last_round_packets) {
last_round_packets = pkt;
main_path_ = it->second;
}
+ } else if (it->second->isActive() && !it->second->pathToProducer()) {
+ // this is a path to a cache from where we are receiving content
+ if (it->second->getMinRtt() < min_edge_rtt) {
+ min_edge_rtt = it->second->getMinRtt();
+ edge_path_ = it->second;
+ }
}
it->second->roundEnd();
}
if (main_path_ == nullptr) main_path_ = old_main_path;
+ if (edge_path_ == nullptr) edge_path_ = main_path_;
+ if (edge_path_->getMinRtt() >= main_path_->getMinRtt())
+ edge_path_ = main_path_;
// in case we get a new main path we reset the stats of the old one. this is
// beacuse, in case we need to switch back we don't what to take decisions on
@@ -551,9 +581,15 @@ void RTCState::onNewRound(double round_len, bool in_sync) {
rounds_++;
}
-void RTCState::updateReceivedBytes(const core::ContentObject &content_object) {
- received_bytes_ +=
- (uint32_t)(content_object.headerSize() + content_object.payloadSize());
+void RTCState::updateReceivedBytes(const core::ContentObject &content_object,
+ bool isFec) {
+ if (isFec) {
+ received_fec_bytes_ +=
+ (uint32_t)(content_object.headerSize() + content_object.payloadSize());
+ } else {
+ received_bytes_ +=
+ (uint32_t)(content_object.headerSize() + content_object.payloadSize());
+ }
}
void RTCState::updatePacketSize(const core::ContentObject &content_object) {
@@ -703,6 +739,10 @@ void RTCState::dataToBeReceived(uint32_t seq) {
addToPacketCache(seq, PacketState::TO_BE_RECEIVED);
}
+void RTCState::updateHighestSeqReceived(uint32_t seq) {
+ if (seq > highest_seq_received_) highest_seq_received_ = seq;
+}
+
void RTCState::addRecvOrLost(uint32_t seq, PacketState state) {
auto it = pending_interests_.find(seq);
if (it != pending_interests_.end()) {
@@ -803,7 +843,7 @@ core::ParamsRTC RTCState::getProbeParams(const core::ContentObject &probe) {
switch (ProbeHandler::getProbeType(seq)) {
case ProbeType::INIT: {
core::ContentObjectManifest manifest(
- const_cast<core::ContentObject &>(probe));
+ const_cast<core::ContentObject &>(probe).shared_from_this());
manifest.decode();
params = manifest.getParamsRTC();
break;
@@ -841,7 +881,7 @@ core::ParamsRTC RTCState::getDataParams(const core::ContentObject &data) {
}
case core::PayloadType::MANIFEST: {
core::ContentObjectManifest manifest(
- const_cast<core::ContentObject &>(data));
+ const_cast<core::ContentObject &>(data).shared_from_this());
manifest.decode();
params = manifest.getParamsRTC();
break;
diff --git a/libtransport/src/protocols/rtc/rtc_state.h b/libtransport/src/protocols/rtc/rtc_state.h
index 4bd2f76a0..ac3cc621f 100644
--- a/libtransport/src/protocols/rtc/rtc_state.h
+++ b/libtransport/src/protocols/rtc/rtc_state.h
@@ -84,8 +84,9 @@ class RTCState : public std::enable_shared_from_this<RTCState> {
void onNackPacketReceived(const core::ContentObject &nack,
bool compute_stats);
void onPacketLost(uint32_t seq);
- void onPacketRecoveredRtx(uint32_t seq);
- void onFecPacketRecoveredRtx(uint32_t seq);
+ void onPacketRecoveredRtx(const core::ContentObject &content_object,
+ uint64_t rtt);
+ void onFecPacketRecoveredRtx(const core::ContentObject &content_object);
void onPacketRecoveredFec(uint32_t seq, uint32_t size);
bool onProbePacketReceived(const core::ContentObject &probe);
void onJumpForward(uint32_t next_seq);
@@ -117,6 +118,11 @@ class RTCState : public std::enable_shared_from_this<RTCState> {
return 0;
}
+ uint64_t getEdgeRtt() const {
+ if (edge_path_ != nullptr) return edge_path_->getMinRtt();
+ return 0;
+ }
+
void resetRttStats() {
if (mainPathIsValid()) main_path_->clearRtt();
}
@@ -149,7 +155,7 @@ class RTCState : public std::enable_shared_from_this<RTCState> {
}
uint32_t getPendingInterestNumber() const {
- return pending_interests_.size();
+ return (uint32_t)pending_interests_.size();
}
PacketState getPacketState(uint32_t seq) {
@@ -242,6 +248,8 @@ class RTCState : public std::enable_shared_from_this<RTCState> {
// set it as TO_BE_RECEIVED.
void dataToBeReceived(uint32_t seq);
+ void updateHighestSeqReceived(uint32_t seq);
+
// Extract RTC parameters from probes (init or RTT probes) and data packets.
static core::ParamsRTC getProbeParams(const core::ContentObject &probe);
static core::ParamsRTC getDataParams(const core::ContentObject &data);
@@ -259,7 +267,8 @@ class RTCState : public std::enable_shared_from_this<RTCState> {
// update stats
void updateState();
- void updateReceivedBytes(const core::ContentObject &content_object);
+ void updateReceivedBytes(const core::ContentObject &content_object,
+ bool isFec);
void updatePacketSize(const core::ContentObject &content_object);
void updatePathStats(const core::ContentObject &content_object, bool is_nack);
void updateLossRate(bool in_sycn);
@@ -360,7 +369,12 @@ class RTCState : public std::enable_shared_from_this<RTCState> {
// paths stats
std::unordered_map<uint32_t, std::shared_ptr<RTCDataPath>> path_table_;
- std::shared_ptr<RTCDataPath> main_path_;
+ std::shared_ptr<RTCDataPath> main_path_; // this is the path that connects
+ // the consumer to the producer. in
+ // case of multipath the trasnport
+ // uses the most active path
+ std::shared_ptr<RTCDataPath> edge_path_; // path to the closest cache if it
+ // exists
// packet received
// cache where to store info about the last MAX_CACHED_PACKETS
diff --git a/libtransport/src/protocols/rtc/rtc_verifier.cc b/libtransport/src/protocols/rtc/rtc_verifier.cc
index 7b6330a1f..861ceee89 100644
--- a/libtransport/src/protocols/rtc/rtc_verifier.cc
+++ b/libtransport/src/protocols/rtc/rtc_verifier.cc
@@ -22,11 +22,11 @@ namespace protocol {
namespace rtc {
RTCVerifier::RTCVerifier(std::shared_ptr<auth::Verifier> verifier,
- uint32_t max_unverified_interval,
- double max_unverified_ratio)
+ uint32_t factor_relevant, uint32_t factor_alert)
: verifier_(verifier),
- max_unverified_interval_(max_unverified_interval),
- max_unverified_ratio_(max_unverified_ratio) {}
+ factor_relevant_(factor_relevant),
+ factor_alert_(factor_alert),
+ manifest_max_capacity_(std::numeric_limits<uint8_t>::max()) {}
void RTCVerifier::setState(std::shared_ptr<RTCState> rtc_state) {
rtc_state_ = rtc_state;
@@ -36,12 +36,16 @@ void RTCVerifier::setVerifier(std::shared_ptr<auth::Verifier> verifier) {
verifier_ = verifier;
}
-void RTCVerifier::setMaxUnverifiedInterval(uint32_t max_unverified_interval) {
- max_unverified_interval_ = max_unverified_interval;
+void RTCVerifier::setFactorRelevant(uint32_t factor_relevant) {
+ factor_relevant_ = factor_relevant;
}
-void RTCVerifier::setMaxUnverifiedRatio(double max_unverified_ratio) {
- max_unverified_ratio_ = max_unverified_ratio;
+void RTCVerifier::setFactorAlert(uint32_t factor_alert) {
+ factor_alert_ = factor_alert;
+}
+
+auth::VerificationPolicy RTCVerifier::verify(core::Interest &interest) {
+ return verifier_->verifyPackets(&interest);
}
auth::VerificationPolicy RTCVerifier::verify(
@@ -108,19 +112,27 @@ auth::VerificationPolicy RTCVerifier::verifyData(
auth::Suffix suffix = content_object.getName().getSuffix();
auth::VerificationPolicy policy = auth::VerificationPolicy::ABORT;
- Timestamp now = utils::SteadyTime::nowMs().count();
- // Flush old packets
- Timestamp oldest = flush_packets(now);
+ uint32_t threshold_relevant = factor_relevant_ * manifest_max_capacity_;
+ uint32_t threshold_alert = factor_alert_ * manifest_max_capacity_;
- // Add packet to map of unverified packets
- packets_unverif_.add(
- {.suffix = suffix, .timestamp = now, .size = content_object.length()},
- content_object.computeDigest(manifest_hash_algo_));
+ // Flush packets outside relevance window
+ for (auto it = packets_unverif_.set().begin();
+ it != packets_unverif_.set().end();) {
+ if (it->first > current_index_ - threshold_relevant) {
+ break;
+ }
+ packets_unverif_erased_.insert((unsigned int)it->first);
+ it = packets_unverif_.remove(it);
+ }
+
+ // Add packet to set of unverified packets
+ packets_unverif_.add({current_index_, suffix},
+ content_object.computeDigest(manifest_hash_algo_));
+ current_index_++;
- // Check that the ratio of unverified packets stays below the limit
- if (now - oldest < max_unverified_interval_ ||
- getBufferRatio() < max_unverified_ratio_) {
+ // Check that the number of unverified packets is below the alert threshold
+ if (packets_unverif_.set().size() <= threshold_alert) {
policy = auth::VerificationPolicy::ACCEPT;
}
@@ -139,18 +151,13 @@ auth::VerificationPolicy RTCVerifier::processManifest(
auth::VerificationPolicy accept_policy = auth::VerificationPolicy::ACCEPT;
// Decode manifest
- core::ContentObjectManifest manifest(content_object);
+ core::ContentObjectManifest manifest(content_object.shared_from_this());
manifest.decode();
- // Update last manifest
- if (suffix > last_manifest_) {
- last_manifest_ = suffix;
- }
-
- // Extract hash algorithm and hashes
+ // Extract manifest data
+ manifest_max_capacity_ = manifest.getMaxCapacity();
manifest_hash_algo_ = manifest.getHashAlgorithm();
- auth::Verifier::SuffixMap suffix_map =
- core::ContentObjectManifest::getSuffixMap(&manifest);
+ auth::Verifier::SuffixMap suffix_map = manifest.getSuffixMap();
// Return early if the manifest is empty
if (suffix_map.empty()) {
@@ -186,10 +193,7 @@ auth::VerificationPolicy RTCVerifier::processManifest(
for (const auto &p : policies) {
switch (p.second) {
case auth::VerificationPolicy::ACCEPT: {
- auto packet_unverif_it = packets_unverif_.packetIt(p.first);
- Packet packet_verif = *packet_unverif_it;
- packets_unverif_.remove(packet_unverif_it);
- packets_verif_.add(packet_verif);
+ packets_unverif_.remove(packets_unverif_.packet(p.first));
manifest_digests_.erase(p.first);
break;
}
@@ -209,69 +213,20 @@ void RTCVerifier::onDataRecoveredFec(uint32_t suffix) {
manifest_digests_.erase(suffix);
}
-void RTCVerifier::onJumpForward(uint32_t next_suffix) {
- if (next_suffix <= last_manifest_ + 1) {
- return;
- }
-
- // When we jump forward in the suffix sequence, we remove packets that won't
- // be verified. Those packets have a suffix in the range [last_manifest_ + 1,
- // next_suffix[.
- for (auth::Suffix suffix = last_manifest_ + 1; suffix < next_suffix;
- ++suffix) {
- auto packet_it = packets_unverif_.packetIt(suffix);
- if (packet_it != packets_unverif_.set().end()) {
- packets_unverif_.remove(packet_it);
- }
- }
-}
-
-double RTCVerifier::getBufferRatio() const {
- size_t total = packets_verif_.size() + packets_unverif_.size();
- double total_unverified = static_cast<double>(packets_unverif_.size());
- return total ? total_unverified / total : 0.0;
-}
-
-RTCVerifier::Timestamp RTCVerifier::flush_packets(Timestamp now) {
- Timestamp oldest_verified = packets_verif_.set().empty()
- ? now
- : packets_verif_.set().begin()->timestamp;
- Timestamp oldest_unverified = packets_unverif_.set().empty()
- ? now
- : packets_unverif_.set().begin()->timestamp;
-
- // Prune verified packets older than the unverified interval
- for (auto it = packets_verif_.set().begin();
- it != packets_verif_.set().end();) {
- if (now - it->timestamp < max_unverified_interval_) {
- break;
- }
- it = packets_verif_.remove(it);
- }
-
- // Prune unverified packets older than the unverified interval
- for (auto it = packets_unverif_.set().begin();
- it != packets_unverif_.set().end();) {
- if (now - it->timestamp < max_unverified_interval_) {
- break;
- }
- packets_unverif_erased_.insert(it->suffix);
- it = packets_unverif_.remove(it);
- }
-
- return std::min(oldest_verified, oldest_unverified);
-}
-
std::pair<RTCVerifier::PacketSet::iterator, bool> RTCVerifier::Packets::add(
- const Packet &packet) {
+ const Packet &packet, const auth::CryptoHash &digest) {
auto inserted = packets_.insert(packet);
- size_ += inserted.second ? packet.size : 0;
+ if (inserted.second) {
+ packets_map_[packet.second] = inserted.first;
+ suffix_map_[packet.second] = digest;
+ }
return inserted;
}
RTCVerifier::PacketSet::iterator RTCVerifier::Packets::remove(
PacketSet::iterator packet_it) {
- size_ -= packet_it->size;
+ packets_map_.erase(packet_it->second);
+ suffix_map_.erase(packet_it->second);
return packets_.erase(packet_it);
}
@@ -279,35 +234,13 @@ const std::set<RTCVerifier::Packet> &RTCVerifier::Packets::set() const {
return packets_;
};
-size_t RTCVerifier::Packets::size() const { return size_; };
-
-std::pair<RTCVerifier::PacketSet::iterator, bool>
-RTCVerifier::PacketsUnverif::add(const Packet &packet,
- const auth::CryptoHash &digest) {
- auto inserted = add(packet);
- if (inserted.second) {
- packets_map_[packet.suffix] = inserted.first;
- digests_map_[packet.suffix] = digest;
- }
- return inserted;
-}
-
-RTCVerifier::PacketSet::iterator RTCVerifier::PacketsUnverif::remove(
- PacketSet::iterator packet_it) {
- size_ -= packet_it->size;
- packets_map_.erase(packet_it->suffix);
- digests_map_.erase(packet_it->suffix);
- return packets_.erase(packet_it);
-}
-
-RTCVerifier::PacketSet::iterator RTCVerifier::PacketsUnverif::packetIt(
+RTCVerifier::PacketSet::iterator RTCVerifier::Packets::packet(
auth::Suffix suffix) {
return packets_map_.at(suffix);
};
-const auth::Verifier::SuffixMap &RTCVerifier::PacketsUnverif::suffixMap()
- const {
- return digests_map_;
+const auth::Verifier::SuffixMap &RTCVerifier::Packets::suffixMap() const {
+ return suffix_map_;
}
} // end namespace rtc
diff --git a/libtransport/src/protocols/rtc/rtc_verifier.h b/libtransport/src/protocols/rtc/rtc_verifier.h
index 098984057..c83faf08a 100644
--- a/libtransport/src/protocols/rtc/rtc_verifier.h
+++ b/libtransport/src/protocols/rtc/rtc_verifier.h
@@ -27,19 +27,16 @@ namespace rtc {
class RTCVerifier {
public:
explicit RTCVerifier(std::shared_ptr<auth::Verifier> verifier,
- uint32_t max_unverified_interval,
- double max_unverified_ratio);
+ uint32_t factor_relevant, uint32_t factor_alert);
virtual ~RTCVerifier() = default;
void setState(std::shared_ptr<RTCState> rtc_state);
-
void setVerifier(std::shared_ptr<auth::Verifier> verifier);
+ void setFactorRelevant(uint32_t factor_relevant);
+ void setFactorAlert(uint32_t factor_alert);
- void setMaxUnverifiedInterval(uint32_t max_unverified_interval);
-
- void setMaxUnverifiedRatio(double max_unverified_ratio);
-
+ auth::VerificationPolicy verify(core::Interest &interest);
auth::VerificationPolicy verify(core::ContentObject &content_object,
bool is_fec = false);
auth::VerificationPolicy verifyProbe(core::ContentObject &content_object);
@@ -51,81 +48,47 @@ class RTCVerifier {
auth::VerificationPolicy processManifest(core::ContentObject &content_object);
void onDataRecoveredFec(uint32_t suffix);
- void onJumpForward(uint32_t next_suffix);
-
- double getBufferRatio() const;
protected:
- struct Packet;
- using Timestamp = uint64_t;
+ using Index = uint64_t;
+ using Packet = std::pair<Index, auth::Suffix>;
using PacketSet = std::set<Packet>;
- struct Packet {
- auth::Suffix suffix;
- Timestamp timestamp;
- size_t size;
-
- bool operator==(const Packet &b) const {
- return timestamp == b.timestamp && suffix == b.suffix;
- }
- bool operator<(const Packet &b) const {
- return timestamp == b.timestamp ? suffix < b.suffix
- : timestamp < b.timestamp;
- }
- };
-
class Packets {
public:
- virtual std::pair<PacketSet::iterator, bool> add(const Packet &packet);
- virtual PacketSet::iterator remove(PacketSet::iterator packet_it);
- const PacketSet &set() const;
- size_t size() const;
-
- protected:
- PacketSet packets_;
- size_t size_;
- };
-
- class PacketsVerif : public Packets {};
-
- class PacketsUnverif : public Packets {
- public:
- using Packets::add;
std::pair<PacketSet::iterator, bool> add(const Packet &packet,
const auth::CryptoHash &digest);
- PacketSet::iterator remove(PacketSet::iterator packet_it) override;
- PacketSet::iterator packetIt(auth::Suffix suffix);
+ PacketSet::iterator remove(PacketSet::iterator packet_it);
+ const PacketSet &set() const;
+ PacketSet::iterator packet(auth::Suffix suffix);
const auth::Verifier::SuffixMap &suffixMap() const;
private:
+ PacketSet packets_;
std::unordered_map<auth::Suffix, PacketSet::iterator> packets_map_;
- auth::Verifier::SuffixMap digests_map_;
+ auth::Verifier::SuffixMap suffix_map_;
};
// The RTC state.
std::shared_ptr<RTCState> rtc_state_;
// The verifier instance.
std::shared_ptr<auth::Verifier> verifier_;
- // Window to consider when verifying packets.
- uint32_t max_unverified_interval_;
- // Ratio of unverified packets over which an alert is triggered.
- double max_unverified_ratio_;
- // The suffix of the last processed manifest.
- auth::Suffix last_manifest_;
+ // Used to compute the relevance windows size (in packets).
+ uint32_t factor_relevant_;
+ // Used to compute the alert threshold (in packets).
+ uint32_t factor_alert_;
+ // The maximum number of entries a manifest can contain.
+ uint8_t manifest_max_capacity_;
// Hash algorithm used by manifests.
auth::CryptoHashType manifest_hash_algo_;
// Digests extracted from all manifests received.
auth::Verifier::SuffixMap manifest_digests_;
- // Verified packets with timestamp >= now - max_unverified_interval_.
- PacketsVerif packets_verif_;
- // Unverified packets with timestamp >= now - max_unverified_interval_.
- PacketsUnverif packets_unverif_;
- // Unverified erased packets with timestamp < now - max_unverified_interval_.
+ // The number of data packets processed.
+ Index current_index_;
+ // Unverified packets with index in relevance window.
+ Packets packets_unverif_;
+ // Unverified erased packets with index outside relevance window.
std::unordered_set<auth::Suffix> packets_unverif_erased_;
-
- // Flushes all packets with timestamp < now - max_unverified_interval_.
- // Returns the timestamp of the oldest packet, verified or not.
- Timestamp flush_packets(Timestamp now);
};
} // namespace rtc
diff --git a/libtransport/src/protocols/transport_protocol.cc b/libtransport/src/protocols/transport_protocol.cc
index a73b9fb7b..b1803709b 100644
--- a/libtransport/src/protocols/transport_protocol.cc
+++ b/libtransport/src/protocols/transport_protocol.cc
@@ -79,6 +79,7 @@ int TransportProtocol::start() {
&on_payload_);
socket_->getSocketOption(GeneralTransportOptions::ASYNC_MODE, is_async_);
+ socket_->getSocketOption(GeneralTransportOptions::SIGNER, signer_);
// Set it is the first time we schedule an interest
is_first_ = true;
@@ -143,14 +144,22 @@ void TransportProtocol::sendInterest(
Packet::Format format;
socket_->getSocketOption(interface::GeneralTransportOptions::PACKET_FORMAT,
format);
+ size_t signature_size = 0;
- auto interest =
- core::PacketManager<>::getInstance().getPacket<Interest>(format);
+ // If aggregated interest, add spapce for signature
+ if (len > 0) {
+ format = Packet::toAHFormat(format);
+ signature_size = signer_->getSignatureFieldSize();
+ }
+
+ auto interest = core::PacketManager<>::getInstance().getPacket<Interest>(
+ format, signature_size);
interest->setName(interest_name);
for (uint32_t i = 0; i < len; i++) {
interest->appendSuffix(additional_suffixes->at(i));
}
+ interest->encodeSuffixes();
uint32_t lifetime = default_values::interest_lifetime;
socket_->getSocketOption(GeneralTransportOptions::INTEREST_LIFETIME,
@@ -165,7 +174,16 @@ void TransportProtocol::sendInterest(
return;
}
- portal_->sendInterest(std::move(interest));
+ bool content_sharing_mode;
+ socket_->getSocketOption(RtcTransportOptions::CONTENT_SHARING_MODE,
+ content_sharing_mode);
+ if (content_sharing_mode) lifetime = ceil((double)lifetime * 0.9);
+
+ // Compute signature
+ bool is_ah = _is_ah(interest->getFormat());
+ if (is_ah) signer_->signPacket(interest.get());
+
+ portal_->sendInterest(interest, lifetime);
}
void TransportProtocol::onError(const std::error_code &ec) {
diff --git a/libtransport/src/protocols/transport_protocol.h b/libtransport/src/protocols/transport_protocol.h
index ad8cf0346..e71992561 100644
--- a/libtransport/src/protocols/transport_protocol.h
+++ b/libtransport/src/protocols/transport_protocol.h
@@ -64,7 +64,7 @@ class TransportProtocol
*
* @return The header length in bytes.
*/
- virtual std::size_t transportHeaderLength() { return 0; }
+ virtual std::size_t transportHeaderLength(bool isFEC) { return 0; }
virtual void scheduleNextInterests() = 0;
@@ -141,6 +141,9 @@ class TransportProtocol
bool is_async_;
fec::FECType fec_type_;
+
+ // Signer for aggregated interests
+ std::shared_ptr<auth::Signer> signer_;
};
} // end namespace protocol
diff --git a/libtransport/src/test/CMakeLists.txt b/libtransport/src/test/CMakeLists.txt
index e7018ceed..b7f14766e 100644
--- a/libtransport/src/test/CMakeLists.txt
+++ b/libtransport/src/test/CMakeLists.txt
@@ -31,6 +31,8 @@ list(APPEND TESTS_SRC
test_quality_score.cc
test_sessions.cc
test_thread_pool.cc
+ test_quadloop.cc
+ test_prefix.cc
)
if (ENABLE_RELY)
diff --git a/libtransport/src/test/test_core_manifest.cc b/libtransport/src/test/test_core_manifest.cc
index b998ce96b..e3d66c1cd 100644
--- a/libtransport/src/test/test_core_manifest.cc
+++ b/libtransport/src/test/test_core_manifest.cc
@@ -13,8 +13,8 @@
* limitations under the License.
*/
+#include <core/manifest.h>
#include <core/manifest_format_fixed.h>
-#include <core/manifest_inline.h>
#include <gtest/gtest.h>
#include <hicn/transport/auth/crypto_hash.h>
#include <hicn/transport/auth/signer.h>
@@ -33,10 +33,12 @@ namespace {
// The fixture for testing class Foo.
class ManifestTest : public ::testing::Test {
protected:
- using ContentObjectManifest = ManifestInline<ContentObject, Fixed>;
+ using ContentObjectManifest = Manifest<Fixed>;
- ManifestTest() : name_("b001::123|321"), manifest1_(HF_INET6_TCP_AH, name_) {
- // You can do set-up work for each test here.
+ ManifestTest()
+ : format_(HF_INET6_TCP_AH), name_("b001::123|321"), signature_size_(0) {
+ manifest_ = ContentObjectManifest::createContentManifest(format_, name_,
+ signature_size_);
}
virtual ~ManifestTest() {
@@ -56,10 +58,11 @@ class ManifestTest : public ::testing::Test {
// before the destructor).
}
+ Packet::Format format_;
Name name_;
- ContentObjectManifest manifest1_;
-
- std::vector<uint8_t> manifest_payload = {
+ std::size_t signature_size_;
+ std::shared_ptr<ContentObjectManifest> manifest_;
+ std::vector<uint8_t> manifest_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,
@@ -75,169 +78,200 @@ class ManifestTest : public ::testing::Test {
} // namespace
-TEST_F(ManifestTest, MoveConstructor) {
+TEST_F(ManifestTest, ManifestConstructor) {
// 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);
+ ContentObject::Ptr co =
+ core::PacketManager<>::getInstance().getPacket<ContentObject>(
+ format_, signature_size_);
+ co->setName(name_);
+ co->appendPayload(manifest_payload_.data(), manifest_payload_.size());
+
+ uint8_t buffer[256] = {0};
+ co->appendPayload(buffer, 256);
// Copy packet payload
uint8_t packet[1500];
- auto length = co.getPayload()->length();
- std::memcpy(packet, co.getPayload()->data(), length);
+ auto length = co->getPayload()->length();
+ std::memcpy(packet, co->getPayload()->data(), length);
// Create manifest
- ContentObjectManifest m(std::move(co));
+ ContentObjectManifest manifest(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(length, manifest.getPacket()->getPayload()->length());
+ auto ret =
+ std::memcmp(packet, manifest.getPacket()->getPayload()->data(), length);
ASSERT_EQ(ret, 0);
}
-TEST_F(ManifestTest, SetLastManifest) {
- manifest1_.clear();
-
- manifest1_.setIsLast(true);
- bool fcn = manifest1_.getIsLast();
-
- ASSERT_TRUE(fcn == true);
-}
-
TEST_F(ManifestTest, SetManifestType) {
- manifest1_.clear();
+ manifest_->Encoder::clear();
ManifestType type1 = ManifestType::INLINE_MANIFEST;
ManifestType type2 = ManifestType::FLIC_MANIFEST;
- manifest1_.setType(type1);
- ManifestType type_returned1 = manifest1_.getType();
+ manifest_->setType(type1);
+ ManifestType type_returned1 = manifest_->getType();
- manifest1_.clear();
+ manifest_->Encoder::clear();
- manifest1_.setType(type2);
- ManifestType type_returned2 = manifest1_.getType();
+ manifest_->setType(type2);
+ ManifestType type_returned2 = manifest_->getType();
ASSERT_EQ(type1, type_returned1);
ASSERT_EQ(type2, type_returned2);
}
+TEST_F(ManifestTest, SetMaxCapacity) {
+ manifest_->Encoder::clear();
+
+ uint8_t max_capacity1 = 0;
+ uint8_t max_capacity2 = 20;
+
+ manifest_->setMaxCapacity(max_capacity1);
+ uint8_t max_capacity_returned1 = manifest_->getMaxCapacity();
+
+ manifest_->Encoder::clear();
+
+ manifest_->setMaxCapacity(max_capacity2);
+ uint8_t max_capacity_returned2 = manifest_->getMaxCapacity();
+
+ ASSERT_EQ(max_capacity1, max_capacity_returned1);
+ ASSERT_EQ(max_capacity2, max_capacity_returned2);
+}
+
TEST_F(ManifestTest, SetHashAlgorithm) {
- manifest1_.clear();
+ manifest_->Encoder::clear();
- auth::CryptoHashType hash1 = auth::CryptoHashType::SHA512;
- auth::CryptoHashType hash2 = auth::CryptoHashType::BLAKE2B512;
- auth::CryptoHashType hash3 = auth::CryptoHashType::SHA256;
+ auth::CryptoHashType hash1 = auth::CryptoHashType::SHA256;
+ auth::CryptoHashType hash2 = auth::CryptoHashType::SHA512;
+ auth::CryptoHashType hash3 = auth::CryptoHashType::BLAKE2B512;
- manifest1_.setHashAlgorithm(hash1);
- auto type_returned1 = manifest1_.getHashAlgorithm();
+ manifest_->setHashAlgorithm(hash1);
+ auto type_returned1 = manifest_->getHashAlgorithm();
- manifest1_.clear();
+ manifest_->Encoder::clear();
- manifest1_.setHashAlgorithm(hash2);
- auto type_returned2 = manifest1_.getHashAlgorithm();
+ manifest_->setHashAlgorithm(hash2);
+ auto type_returned2 = manifest_->getHashAlgorithm();
- manifest1_.clear();
+ manifest_->Encoder::clear();
- manifest1_.setHashAlgorithm(hash3);
- auto type_returned3 = manifest1_.getHashAlgorithm();
+ manifest_->setHashAlgorithm(hash3);
+ auto type_returned3 = manifest_->getHashAlgorithm();
ASSERT_EQ(hash1, type_returned1);
ASSERT_EQ(hash2, type_returned2);
ASSERT_EQ(hash3, type_returned3);
}
+TEST_F(ManifestTest, SetLastManifest) {
+ manifest_->Encoder::clear();
+
+ manifest_->setIsLast(true);
+ bool is_last = manifest_->getIsLast();
+
+ ASSERT_TRUE(is_last);
+}
+
+TEST_F(ManifestTest, SetBaseName) {
+ manifest_->Encoder::clear();
+
+ core::Name base_name("b001::dead");
+
+ manifest_->setBaseName(base_name);
+ core::Name ret_name = manifest_->getBaseName();
+
+ ASSERT_EQ(base_name, ret_name);
+}
+
TEST_F(ManifestTest, setParamsBytestream) {
- manifest1_.clear();
+ manifest_->Encoder::clear();
ParamsBytestream params{
- .final_segment = 1,
+ .final_segment = 0x0a,
};
- manifest1_.setParamsBytestream(params);
- manifest1_.encode();
+ manifest_->setParamsBytestream(params);
+ auth::CryptoHash hash(auth::CryptoHashType::SHA256);
+ hash.computeDigest({0x01, 0x02, 0x03, 0x04});
+ manifest_->addEntry(1, hash);
+
+ manifest_->encode();
+ manifest_->decode();
- ContentObjectManifest manifest(manifest1_);
- manifest.decode();
+ auto transport_type_returned = manifest_->getTransportType();
+ auto params_returned = manifest_->getParamsBytestream();
ASSERT_EQ(interface::ProductionProtocolAlgorithms::BYTE_STREAM,
- manifest.getTransportType());
- ASSERT_EQ(params, manifest.getParamsBytestream());
+ transport_type_returned);
+ ASSERT_EQ(params, params_returned);
}
TEST_F(ManifestTest, SetParamsRTC) {
- manifest1_.clear();
+ manifest_->Encoder::clear();
ParamsRTC params{
- .timestamp = 1,
- .prod_rate = 2,
- .prod_seg = 3,
+ .timestamp = 0x0a,
+ .prod_rate = 0x0b,
+ .prod_seg = 0x0c,
.fec_type = protocol::fec::FECType::UNKNOWN,
};
- manifest1_.setParamsRTC(params);
- manifest1_.encode();
+ manifest_->setParamsRTC(params);
+ auth::CryptoHash hash(auth::CryptoHashType::SHA256);
+ hash.computeDigest({0x01, 0x02, 0x03, 0x04});
+ manifest_->addEntry(1, hash);
- ContentObjectManifest manifest(manifest1_);
- manifest.decode();
+ manifest_->encode();
+ manifest_->decode();
+
+ auto transport_type_returned = manifest_->getTransportType();
+ auto params_returned = manifest_->getParamsRTC();
ASSERT_EQ(interface::ProductionProtocolAlgorithms::RTC_PROD,
- manifest.getTransportType());
- ASSERT_EQ(params, manifest.getParamsRTC());
+ transport_type_returned);
+ ASSERT_EQ(params, params_returned);
}
TEST_F(ManifestTest, SignManifest) {
- Name name("b001::", 0);
auto signer = std::make_shared<auth::SymmetricSigner>(
auth::CryptoSuite::HMAC_SHA256, "hunter2");
auto verifier = std::make_shared<auth::SymmetricVerifier>("hunter2");
- std::shared_ptr<ContentObjectManifest> manifest;
- // Instantiate Manifest
- manifest.reset(ContentObjectManifest::createManifest(
- HF_INET6_TCP_AH, name, ManifestVersion::VERSION_1,
- ManifestType::INLINE_MANIFEST, false, name, signer->getHashType(),
- signer->getSignatureFieldSize()));
+ // Instantiate manifest
+ uint8_t max_capacity = 30;
+ std::shared_ptr<ContentObjectManifest> manifest =
+ ContentObjectManifest::createContentManifest(
+ format_, name_, signer->getSignatureFieldSize());
+ manifest->setHeaders(ManifestType::INLINE_MANIFEST, max_capacity,
+ signer->getHashType(), false /* is_last */, name_);
- // Add Manifest entry
+ // Add manifest entry
auth::CryptoHash hash(signer->getHashType());
- hash.computeDigest(std::vector<uint8_t>{0x01, 0x02, 0x03, 0x04});
- manifest->addSuffixHash(1, hash);
+ hash.computeDigest({0x01, 0x02, 0x03, 0x04});
+ manifest->addEntry(1, hash);
// Encode manifest
manifest->encode();
+ auto manifest_co =
+ std::dynamic_pointer_cast<ContentObject>(manifest->getPacket());
// Sign manifest
- signer->signPacket(manifest.get());
+ signer->signPacket(manifest_co.get());
// Check size
- ASSERT_EQ(manifest->payloadSize(), manifest->estimateManifestSize());
- ASSERT_EQ(manifest->length(),
- manifest->headerSize() + manifest->payloadSize());
- ASSERT_EQ(ContentObjectManifest::manifestHeaderSize(
- interface::ProductionProtocolAlgorithms::UNKNOWN),
- manifest->manifestHeaderSize());
+ ASSERT_EQ(manifest_co->payloadSize(), manifest->Encoder::manifestSize());
+ ASSERT_EQ(manifest_co->length(),
+ manifest_co->headerSize() + manifest_co->payloadSize());
// Verify manifest
- auth::VerificationPolicy policy = verifier->verifyPackets(manifest.get());
+ auth::VerificationPolicy policy = verifier->verifyPackets(manifest_co.get());
ASSERT_EQ(auth::VerificationPolicy::ACCEPT, policy);
}
-TEST_F(ManifestTest, SetBaseName) {
- manifest1_.clear();
-
- core::Name base_name("b001::dead");
- manifest1_.setBaseName(base_name);
- core::Name ret_name = manifest1_.getBaseName();
-
- ASSERT_EQ(base_name, ret_name);
-}
-
TEST_F(ManifestTest, SetSuffixList) {
- manifest1_.clear();
-
- core::Name base_name("b001::dead");
+ manifest_->Encoder::clear();
using random_bytes_engine =
std::independent_bits_engine<std::default_random_engine, CHAR_BIT,
@@ -259,12 +293,13 @@ TEST_F(ManifestTest, SetSuffixList) {
entries[i] = std::make_pair(suffixes[i],
auth::CryptoHash(data[i].data(), data[i].size(),
auth::CryptoHashType::SHA256));
- manifest1_.addSuffixHash(entries[i].first, entries[i].second);
+ manifest_->addEntry(entries[i].first, entries[i].second);
}
- manifest1_.setBaseName(base_name);
- core::Name ret_name = manifest1_.getBaseName();
+ core::Name base_name("b001::dead");
+ manifest_->setBaseName(base_name);
+ core::Name ret_name = manifest_->getBaseName();
ASSERT_EQ(base_name, ret_name);
delete[] entries;
diff --git a/libtransport/src/test/test_interest.cc b/libtransport/src/test/test_interest.cc
index d9c535881..e36ca0f93 100644
--- a/libtransport/src/test/test_interest.cc
+++ b/libtransport/src/test/test_interest.cc
@@ -258,5 +258,44 @@ TEST_F(InterestTest, AppendSuffixesEncodeAndIterate) {
}
}
+TEST_F(InterestTest, AppendSuffixesWithGaps) {
+ // Create interest from buffer
+ Interest interest(HF_INET6_TCP);
+
+ // Appenad some suffixes, out of order and with gaps
+ interest.appendSuffix(6);
+ interest.appendSuffix(2);
+ interest.appendSuffix(5);
+ interest.appendSuffix(1);
+
+ // Encode them in wire format
+ interest.encodeSuffixes();
+ EXPECT_TRUE(interest.hasManifest());
+
+ // Check first suffix correctness
+ auto suffix = interest.firstSuffix();
+ EXPECT_NE(suffix, nullptr);
+ EXPECT_EQ(*suffix, 1U);
+
+ // Iterate over them. They should be in order and without repetitions
+ std::vector<uint32_t> expected = {1, 2, 5, 6};
+ EXPECT_EQ(interest.numberOfSuffixes(), expected.size());
+
+ for (uint32_t seq : expected) {
+ EXPECT_EQ(*suffix, seq);
+ suffix++;
+ }
+}
+
+TEST_F(InterestTest, InterestWithoutManifest) {
+ // Create interest without manifest
+ Interest interest(HF_INET6_TCP);
+ auto suffix = interest.firstSuffix();
+
+ EXPECT_FALSE(interest.hasManifest());
+ EXPECT_EQ(interest.numberOfSuffixes(), 0U);
+ EXPECT_EQ(suffix, nullptr);
+}
+
} // namespace core
} // namespace transport
diff --git a/libtransport/src/test/test_memif_connector.cc b/libtransport/src/test/test_memif_connector.cc
index 562a12c88..40f4df927 100644
--- a/libtransport/src/test/test_memif_connector.cc
+++ b/libtransport/src/test/test_memif_connector.cc
@@ -83,8 +83,8 @@ class Memif {
recv_counter_ += buffers.size();
if (recv_counter_ == total_packets) {
auto t1 = utils::SteadyTime::now();
- auto delta = utils::SteadyTime::getDurationS(t0_, t1);
- auto rate = recv_counter_ / delta.count();
+ auto delta = utils::SteadyTime::getDurationUs(t0_, t1);
+ double rate = double(recv_counter_) * 1.0e6 / double(delta.count());
LOG(INFO) << "rate: " << rate << " packets/s";
io_service_.stop();
}
diff --git a/libtransport/src/test/test_packet_allocator.cc b/libtransport/src/test/test_packet_allocator.cc
index b63ddde8d..744f1bd24 100644
--- a/libtransport/src/test/test_packet_allocator.cc
+++ b/libtransport/src/test/test_packet_allocator.cc
@@ -21,6 +21,7 @@
#define ALLOCATION_CHECKS
#include <hicn/transport/core/global_object_pool.h>
#undef ALLOCATION_CHECKS
+#include <hicn/transport/utils/chrono_typedefs.h>
#include <hicn/transport/utils/event_thread.h>
namespace transport {
@@ -30,6 +31,8 @@ class PacketAllocatorTest : public ::testing::Test {
protected:
static inline const std::size_t default_size = 2048;
static inline const std::size_t default_n_buffer = 1024;
+ static inline const std::size_t counter = 1024;
+ static inline const std::size_t total_packets = 1024 * counter;
// Get fixed block allocator_ of 1024 buffers of size 2048 bytes
PacketAllocatorTest() : allocator_(PacketManager<>::getInstance()) {
@@ -102,5 +105,27 @@ TEST_F(PacketAllocatorTest, CheckAllocationIsCorrect) {
PacketManager<>::PacketStorage::packet_and_shared_ptr)));
}
+TEST_F(PacketAllocatorTest, CheckAllocationSpeed) {
+ // Check time needed to allocate 1 million packeauto &packet_manager =
+ auto &packet_manager = core::PacketManager<>::getInstance();
+
+ // Send 1 million packets
+ std::array<utils::MemBuf::Ptr, counter> packets;
+ auto t0 = utils::SteadyTime::now();
+ std::size_t sum = 0;
+ for (std::size_t j = 0; j < counter; j++) {
+ for (std::size_t i = 0; i < counter; i++) {
+ packets[i] = packet_manager.getMemBuf();
+ sum++;
+ }
+ }
+ auto t1 = utils::SteadyTime::now();
+
+ auto delta = utils::SteadyTime::getDurationUs(t0, t1);
+ auto rate = double(sum) * 1000000.0 / double(delta.count());
+
+ LOG(INFO) << "rate: " << rate << " packets/s";
+}
+
} // namespace core
} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/test/test_prefix.cc b/libtransport/src/test/test_prefix.cc
new file mode 100644
index 000000000..5de737566
--- /dev/null
+++ b/libtransport/src/test/test_prefix.cc
@@ -0,0 +1,334 @@
+/*
+ * 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 <glog/logging.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hicn/transport/core/prefix.h>
+#include <hicn/transport/errors/invalid_ip_address_exception.h>
+#include <hicn/transport/portability/endianess.h>
+
+#include <cstring>
+#include <memory>
+#include <vector>
+
+namespace transport {
+namespace core {
+
+namespace {
+class PrefixTest : public ::testing::Test {
+ protected:
+ static inline const char prefix_str0[] = "2001:db8:1::/64";
+ static inline const char prefix_str1[] = "10.11.12.0/24";
+ static inline const char prefix_str2[] = "2001:db8:1::abcd/64";
+ static inline const char prefix_str3[] = "10.11.12.245/27";
+ static inline const char wrong_prefix_str0[] = "10.11.12.245/45";
+ static inline const char wrong_prefix_str1[] = "10.400.12.13/8";
+ static inline const char wrong_prefix_str2[] = "2001:db8:1::/640";
+ static inline const char wrong_prefix_str3[] = "20011::db8:1::/16";
+ static inline const char wrong_prefix_str4[] = "2001::db8:1::fffff/96";
+
+ PrefixTest() = default;
+
+ ~PrefixTest() override = default;
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ void SetUp() override {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ void TearDown() override {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+};
+
+TEST_F(PrefixTest, ConstructorRightString) {
+ // Create empty prefix
+ Prefix p;
+
+ // Create prefix from string
+ Prefix p0(prefix_str0);
+ // Reconstruct string and check it is equal to original address
+ std::string network = p0.getNetwork();
+ std::uint16_t prefix_length = p0.getPrefixLength();
+ EXPECT_THAT(network + "/" + std::to_string(prefix_length),
+ ::testing::StrEq(prefix_str0));
+
+ // Create prefix from string
+ Prefix p1(prefix_str1);
+ // Reconstruct string and check it is equal to original address
+ network = p1.getNetwork();
+ prefix_length = p1.getPrefixLength();
+ EXPECT_THAT(network + "/" + std::to_string(prefix_length),
+ ::testing::StrEq(prefix_str1));
+
+ // Create prefix from string
+ Prefix p2(prefix_str2);
+ // Reconstruct string and check it is equal to original address
+ network = p2.getNetwork();
+ prefix_length = p2.getPrefixLength();
+ EXPECT_THAT(network + "/" + std::to_string(prefix_length),
+ ::testing::StrEq(prefix_str2));
+
+ // Create prefix from string
+ Prefix p3(prefix_str3);
+ // Reconstruct string and check it is equal to original address
+ network = p3.getNetwork();
+ prefix_length = p3.getPrefixLength();
+ EXPECT_THAT(network + "/" + std::to_string(prefix_length),
+ ::testing::StrEq(prefix_str3));
+
+ // Create prefix from string and prefix length
+ Prefix p4("2001::1234", 66);
+ // Reconstruct string and check it is equal to original address
+ network = p4.getNetwork();
+ prefix_length = p4.getPrefixLength();
+ auto af = p4.getAddressFamily();
+ EXPECT_THAT(network, ::testing::StrEq("2001::1234"));
+ EXPECT_THAT(prefix_length, ::testing::Eq(66));
+ EXPECT_THAT(af, ::testing::Eq(AF_INET6));
+}
+
+TEST_F(PrefixTest, ConstructorWrongString) {
+ try {
+ Prefix p0(wrong_prefix_str0);
+ FAIL() << "Expected exception";
+ } catch (const errors::InvalidIpAddressException &) {
+ // Expected exception
+ }
+
+ try {
+ Prefix p1(wrong_prefix_str1);
+ FAIL() << "Expected exception";
+ } catch (const errors::InvalidIpAddressException &) {
+ // Expected exception
+ }
+
+ try {
+ Prefix p2(wrong_prefix_str2);
+ FAIL() << "Expected exception";
+ } catch (const errors::InvalidIpAddressException &) {
+ // Expected exception
+ }
+
+ try {
+ Prefix p3(wrong_prefix_str3);
+ FAIL() << "Expected exception";
+ } catch (const errors::InvalidIpAddressException &) {
+ // Expected exception
+ }
+
+ try {
+ Prefix p4(wrong_prefix_str4);
+ FAIL() << "Expected exception";
+ } catch (const errors::InvalidIpAddressException &) {
+ // Expected exception
+ }
+}
+
+TEST_F(PrefixTest, Comparison) {
+ Prefix p0(prefix_str0);
+ Prefix p1(prefix_str1);
+
+ // Expect they are different
+ EXPECT_THAT(p0, ::testing::Ne(p1));
+
+ auto p2 = p1;
+ // Expect they are equal
+ EXPECT_THAT(p1, ::testing::Eq(p2));
+}
+
+TEST_F(PrefixTest, ToSockAddress) {
+ Prefix p0(prefix_str3);
+
+ auto ret = p0.toSockaddr();
+ auto sockaddr = reinterpret_cast<sockaddr_in *>(ret.get());
+
+ EXPECT_THAT(sockaddr->sin_family, ::testing::Eq(AF_INET));
+ EXPECT_THAT(sockaddr->sin_addr.s_addr, portability::host_to_net(0x0a0b0cf5));
+}
+
+TEST_F(PrefixTest, GetPrefixLength) {
+ Prefix p0(prefix_str3);
+ EXPECT_THAT(p0.getPrefixLength(), ::testing::Eq(27));
+}
+
+TEST_F(PrefixTest, SetPrefixLength) {
+ Prefix p0(prefix_str3);
+ EXPECT_THAT(p0.getPrefixLength(), ::testing::Eq(27));
+ p0.setPrefixLength(20);
+ EXPECT_THAT(p0.getPrefixLength(), ::testing::Eq(20));
+
+ try {
+ p0.setPrefixLength(33);
+ FAIL() << "Expected exception";
+ } catch ([[maybe_unused]] const errors::InvalidIpAddressException &) {
+ // Expected exception
+ }
+}
+
+TEST_F(PrefixTest, SetGetNetwork) {
+ Prefix p0(prefix_str0);
+ EXPECT_THAT(p0.getPrefixLength(), ::testing::Eq(64));
+ p0.setNetwork("b001::1234");
+ EXPECT_THAT(p0.getNetwork(), ::testing::StrEq("b001::1234"));
+ EXPECT_THAT(p0.getPrefixLength(), ::testing::Eq(64));
+}
+
+TEST_F(PrefixTest, Contains) {
+ // IPv6 prefix
+ Prefix p0(prefix_str0);
+ ip_address_t ip0, ip1;
+
+ ip_address_pton("2001:db8:1::1234", &ip0);
+ ip_address_pton("2001:db9:1::1234", &ip1);
+
+ EXPECT_TRUE(p0.contains(ip0));
+ EXPECT_FALSE(p0.contains(ip1));
+
+ Prefix p1(prefix_str1);
+ ip_address_pton("10.11.12.12", &ip0);
+ ip_address_pton("10.12.12.13", &ip1);
+
+ EXPECT_TRUE(p1.contains(ip0));
+ EXPECT_FALSE(p1.contains(ip1));
+
+ Prefix p2(prefix_str2);
+ ip_address_pton("2001:db8:1::dbca", &ip0);
+ ip_address_pton("10.12.12.12", &ip1);
+
+ EXPECT_TRUE(p2.contains(ip0));
+ EXPECT_FALSE(p2.contains(ip1));
+
+ Prefix p3(prefix_str3);
+ ip_address_pton("10.11.12.245", &ip0);
+ ip_address_pton("10.11.12.1", &ip1);
+
+ EXPECT_TRUE(p3.contains(ip0));
+ EXPECT_FALSE(p3.contains(ip1));
+
+ // Corner cases
+ Prefix p4("::/0");
+ ip_address_pton("7001:db8:1::1234", &ip0);
+ ip_address_pton("8001:db8:1::1234", &ip1);
+
+ EXPECT_TRUE(p4.contains(ip0));
+ EXPECT_TRUE(p4.contains(ip1));
+
+ // Corner cases
+ Prefix p5("b001:a:b:c:d:e:f:1/128");
+ ip_address_pton("b001:a:b:c:d:e:f:1", &ip0);
+ ip_address_pton("b001:a:b:c:d:e:f:2", &ip1);
+
+ EXPECT_TRUE(p5.contains(ip0));
+ EXPECT_FALSE(p5.contains(ip1));
+}
+
+TEST_F(PrefixTest, GetAddressFamily) {
+ Prefix p0(prefix_str0);
+ auto af = p0.getAddressFamily();
+ EXPECT_THAT(af, ::testing::Eq(AF_INET6));
+
+ Prefix p1(prefix_str1);
+ af = p1.getAddressFamily();
+ EXPECT_THAT(af, ::testing::Eq(AF_INET));
+}
+
+TEST_F(PrefixTest, MakeName) {
+ Prefix p0(prefix_str0);
+ auto name0 = p0.makeName();
+ EXPECT_THAT(name0.toString(), ::testing::StrEq("2001:db8:1::|0"));
+
+ Prefix p1(prefix_str1);
+ auto name1 = p1.makeName();
+ EXPECT_THAT(name1.toString(), ::testing::StrEq("10.11.12.0|0"));
+
+ Prefix p2(prefix_str2);
+ auto name2 = p2.makeName();
+ EXPECT_THAT(name2.toString(), ::testing::StrEq("2001:db8:1::|0"));
+
+ Prefix p3(prefix_str3);
+ auto name3 = p3.makeName();
+ EXPECT_THAT(name3.toString(), ::testing::StrEq("10.11.12.224|0"));
+
+ Prefix p4("b001:a:b:c:d:e:f:1/128");
+ auto name4 = p4.makeName();
+ EXPECT_THAT(name4.toString(), ::testing::StrEq("b001:a:b:c:d:e:f:1|0"));
+}
+
+TEST_F(PrefixTest, MakeRandomName) {
+ Prefix p0(prefix_str0);
+ auto name0 = p0.makeRandomName();
+ auto name1 = p0.makeRandomName();
+ auto name2 = p0.makeRandomName();
+ auto name3 = p0.makeRandomName();
+
+ EXPECT_THAT(name0, ::testing::Not(::testing::Eq(name1)));
+ EXPECT_THAT(name0, ::testing::Not(::testing::Eq(name2)));
+ EXPECT_THAT(name0, ::testing::Not(::testing::Eq(name3)));
+ EXPECT_THAT(name1, ::testing::Not(::testing::Eq(name2)));
+ EXPECT_THAT(name1, ::testing::Not(::testing::Eq(name3)));
+ EXPECT_THAT(name2, ::testing::Not(::testing::Eq(name3)));
+
+ // Corner case
+ Prefix p2("b001:a:b:c:d:e:f:1/128");
+ name0 = p2.makeRandomName();
+ name1 = p2.makeRandomName();
+ name2 = p2.makeRandomName();
+ name3 = p2.makeRandomName();
+
+ EXPECT_THAT(name0, ::testing::Eq(name1));
+ EXPECT_THAT(name0, ::testing::Eq(name2));
+ EXPECT_THAT(name0, ::testing::Eq(name3));
+ EXPECT_THAT(name1, ::testing::Eq(name2));
+ EXPECT_THAT(name1, ::testing::Eq(name3));
+ EXPECT_THAT(name2, ::testing::Eq(name3));
+}
+
+TEST_F(PrefixTest, MakeNameWithIndex) {
+ Prefix p0(prefix_str0);
+ auto name0 = p0.makeNameWithIndex(0);
+ EXPECT_THAT(name0.toString(), ::testing::StrEq("2001:db8:1::|0"));
+ auto name1 = p0.makeNameWithIndex(1);
+ EXPECT_THAT(name1.toString(), ::testing::StrEq("2001:db8:1::1|0"));
+ auto name2 = p0.makeNameWithIndex(2);
+ EXPECT_THAT(name2.toString(), ::testing::StrEq("2001:db8:1::2|0"));
+ auto name3 = p0.makeNameWithIndex(3);
+ EXPECT_THAT(name3.toString(), ::testing::StrEq("2001:db8:1::3|0"));
+
+ Prefix p1(prefix_str1);
+ name0 = p1.makeNameWithIndex(0);
+ EXPECT_THAT(name0.toString(), ::testing::StrEq("10.11.12.0|0"));
+ name1 = p1.makeNameWithIndex(1);
+ EXPECT_THAT(name1.toString(), ::testing::StrEq("10.11.12.1|0"));
+ name2 = p1.makeNameWithIndex(2);
+ EXPECT_THAT(name2.toString(), ::testing::StrEq("10.11.12.2|0"));
+ name3 = p1.makeNameWithIndex(3);
+ EXPECT_THAT(name3.toString(), ::testing::StrEq("10.11.12.3|0"));
+
+ // Test truncation
+ Prefix p2("b001::/96");
+ name0 = p2.makeNameWithIndex(0xffffffffffffffff);
+ EXPECT_THAT(name0.toString(), ::testing::StrEq("b001::ffff:ffff|0"));
+}
+
+} // namespace
+
+} // namespace core
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/test/test_quadloop.cc b/libtransport/src/test/test_quadloop.cc
new file mode 100644
index 000000000..6a08033aa
--- /dev/null
+++ b/libtransport/src/test/test_quadloop.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 <glog/logging.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hicn/transport/portability/cache.h>
+
+#include <array>
+#include <cstring>
+#include <memory>
+#include <vector>
+
+namespace utils {
+
+class LoopTest : public ::testing::Test {
+ protected:
+ static inline const std::size_t size = 256;
+
+ LoopTest() = default;
+
+ ~LoopTest() override = default;
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ void SetUp() override {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ void TearDown() override {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+};
+
+// 1 cache line struct (64 bytes)
+struct Data {
+ std::array<uint64_t, 8> data;
+};
+
+TEST_F(LoopTest, QuadLoopTest) {
+ // Create 2 arrays of 256 elements
+ std::vector<std::unique_ptr<Data>> _from;
+ std::vector<std::unique_ptr<Data>> _to_next;
+ _from.reserve(size);
+ _to_next.reserve(size);
+
+ int n_left_from = size;
+ int n_left_to_next = size;
+
+ // Initialize the arrays
+ for (std::size_t i = 0; i < size; i++) {
+ _from.push_back(std::make_unique<Data>());
+ _to_next.push_back(std::make_unique<Data>());
+
+ for (int j = 0; j < 8; j++) {
+ _from[i]->data[j] = j;
+ _to_next[i]->data[j] = 0;
+ }
+ }
+
+ const std::unique_ptr<Data> *from = &_from[0];
+ const std::unique_ptr<Data> *to_next = &_to_next[0];
+
+ clock_t start;
+ clock_t end;
+ double clocks;
+
+ start = clock();
+ // Create a quad loop
+ while (n_left_from > 0) {
+ while (n_left_from >= 4 && n_left_to_next >= 4) {
+ {
+ using namespace transport::portability::cache;
+ Data *d2;
+ Data *d3;
+
+ d2 = from[2].get();
+ d3 = from[3].get();
+
+ prefetch<Data, READ>(d2, sizeof(Data));
+ prefetch<Data, READ>(d3, sizeof(Data));
+
+ d2 = to_next[2].get();
+ d3 = to_next[3].get();
+
+ prefetch<Data, WRITE>(d2, sizeof(Data));
+ prefetch<Data, WRITE>(d3, sizeof(Data));
+ }
+
+ // Do 4 iterations
+ std::memcpy(to_next[0].get()->data.data(), from[0].get()->data.data(),
+ sizeof(Data));
+ std::memcpy(to_next[1].get()->data.data(), from[1].get()->data.data(),
+ sizeof(Data));
+ n_left_from -= 2;
+ n_left_to_next -= 2;
+ from += 2;
+ to_next += 2;
+ }
+
+ while (n_left_from > 0 && n_left_to_next > 0) {
+ std::memcpy(to_next[0].get()->data.data(), from[0].get()->data.data(),
+ sizeof(Data));
+ n_left_from -= 1;
+ n_left_to_next -= 1;
+ from += 1;
+ to_next += 1;
+ }
+ }
+ end = clock();
+ clocks = (double)(end - start);
+
+ LOG(INFO) << "Time with quad loop: " << clocks << std::endl;
+}
+
+TEST_F(LoopTest, NormalLoopTest) {
+ // Create 2 arrays of 256 elements
+ std::vector<std::unique_ptr<Data>> _from;
+ std::vector<std::unique_ptr<Data>> _to_next;
+ _from.reserve(size);
+ _to_next.reserve(size);
+
+ int n_left_from = size;
+ int n_left_to_next = size;
+
+ // Initialize the arrays
+ for (std::size_t i = 0; i < size; i++) {
+ _from.push_back(std::make_unique<Data>());
+ _to_next.push_back(std::make_unique<Data>());
+
+ for (int j = 0; j < 8; j++) {
+ _from[i]->data[j] = j;
+ _to_next[i]->data[j] = 0;
+ }
+ }
+
+ const std::unique_ptr<Data> *from = &_from[0];
+ const std::unique_ptr<Data> *to_next = &_to_next[0];
+
+ clock_t start;
+ clock_t end;
+ double clocks;
+
+ start = clock();
+ while (n_left_from > 0) {
+ while (n_left_from > 0 && n_left_to_next > 0) {
+ std::memcpy(to_next[0].get()->data.data(), from[0].get()->data.data(),
+ sizeof(Data));
+ n_left_from -= 1;
+ n_left_to_next -= 1;
+ from += 1;
+ to_next += 1;
+ }
+ }
+ end = clock();
+ clocks = ((double)(end - start));
+
+ LOG(INFO) << "Time with normal loop: " << clocks << std::endl;
+}
+
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/src/utils/epoll_event_reactor.h b/libtransport/src/utils/epoll_event_reactor.h
index 8e7681c20..32d99c837 100644
--- a/libtransport/src/utils/epoll_event_reactor.h
+++ b/libtransport/src/utils/epoll_event_reactor.h
@@ -49,7 +49,7 @@ class EpollEventReactor : public EventReactor {
if (it == event_callback_map_.end()) {
{
utils::SpinLock::Acquire locked(event_callback_map_lock_);
- event_callback_map_[fd] = std::forward<EventHandler &&>(callback);
+ event_callback_map_[fd] = std::forward<EventHandler>(callback);
}
ret = addFileDescriptor(fd, events);
diff --git a/libtransport/src/utils/fd_deadline_timer.h b/libtransport/src/utils/fd_deadline_timer.h
index e15cd4d2a..cf0cde112 100644
--- a/libtransport/src/utils/fd_deadline_timer.h
+++ b/libtransport/src/utils/fd_deadline_timer.h
@@ -57,8 +57,8 @@ class FdDeadlineTimer : public DeadlineTimer<FdDeadlineTimer> {
reactor_.addFileDescriptor(
timer_fd_, events,
- [callback = std::forward<WaitHandler &&>(callback)](
- const Event &event) -> int {
+ [callback =
+ std::forward<WaitHandler>(callback)](const Event &event) -> int {
uint64_t s = 0;
std::error_code ec;
diff --git a/libtransport/src/utils/suffix_strategy.h b/libtransport/src/utils/suffix_strategy.h
index 96eaed662..4b3ddbc74 100644
--- a/libtransport/src/utils/suffix_strategy.h
+++ b/libtransport/src/utils/suffix_strategy.h
@@ -36,11 +36,11 @@ enum class NextSuffixStrategy : uint8_t {
class SuffixStrategy {
public:
static constexpr uint32_t MAX_SUFFIX = std::numeric_limits<uint32_t>::max();
- static constexpr uint8_t MAX_MANIFEST_CAPACITY =
+ static constexpr uint8_t MANIFEST_MAX_CAPACITY =
std::numeric_limits<uint8_t>::max();
SuffixStrategy(NextSuffixStrategy strategy, uint32_t offset = 0,
- uint32_t manifest_capacity = MAX_MANIFEST_CAPACITY)
+ uint32_t manifest_capacity = MANIFEST_MAX_CAPACITY)
: suffix_stragegy_(strategy),
next_suffix_(offset),
manifest_capacity_(manifest_capacity),
@@ -130,7 +130,7 @@ class SuffixStrategyFactory {
public:
static std::unique_ptr<SuffixStrategy> getSuffixStrategy(
NextSuffixStrategy strategy, uint32_t start_offset = 0,
- uint32_t manifest_capacity = SuffixStrategy::MAX_MANIFEST_CAPACITY) {
+ uint32_t manifest_capacity = SuffixStrategy::MANIFEST_MAX_CAPACITY) {
switch (strategy) {
case NextSuffixStrategy::INCREMENTAL:
return std::make_unique<IncrementalSuffixStrategy>(start_offset);
diff --git a/telemetry/.clang-format b/telemetry/.clang-format
new file mode 100644
index 000000000..0043ea3d0
--- /dev/null
+++ b/telemetry/.clang-format
@@ -0,0 +1,3 @@
+# Copyright (c) 2022 Cisco and/or its affiliates.
+
+BasedOnStyle: Google \ No newline at end of file
diff --git a/telemetry/CMakeLists.txt b/telemetry/CMakeLists.txt
index eff855646..181e726f1 100644
--- a/telemetry/CMakeLists.txt
+++ b/telemetry/CMakeLists.txt
@@ -11,19 +11,68 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-
+##############################################################
+# Project and cmake version
+##############################################################
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
+project(telemetry)
+
+
+##############################################################
+# C Standard
+##############################################################
+set(CMAKE_C_STANDARD 11)
+
+
+##############################################################
+# Cmake modules
+##############################################################
+include("${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake")
+set(CMAKE_MODULE_PATH
+ ${CMAKE_MODULE_PATH}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules
+)
+
+
+##############################################################
+# Libs and Bins names
+##############################################################
+set(COLLECTD_PLUGINS hicn-collectd-plugins CACHE INTERNAL "" FORCE)
+set(HICN_LIGHT_TELEMETRY hicn_light)
+set(KAFKA_TELEMETRY write_kafka_line_protocol)
+set(VPP_TELEMETRY vpp)
+set(VPP_HICN_TELEMETRY vpp_hicn)
+
##############################################################
-# Packaging and versioning
+# Dependencies and third party libs
##############################################################
+find_package(Collectd ${COLLECTD_DEFAULT_VERSION} REQUIRED)
+add_subdirectory(third-party)
+
+
+##############################################################
+# Check if building as subproject or as root project
+##############################################################
+if(NOT (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) AND
+ NOT (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux"))
+ return()
+endif()
+include(CommonSetup)
+
+# Include config.h in all collectd plugins
+set(COLLECTD_COMPILER_OPTIONS -include config.h)
+
+# ##############################################################
+# # Packaging and versioning
+# ##############################################################
include(${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake)
##############################################################
# Subdirectories
##############################################################
-if ((CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) OR
- (BUILD_HICNPLUGIN AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux"))
- add_subdirectory(vpp-collectd)
-endif ()
+add_subdirectory(hicn-light-collectd)
+add_subdirectory(kafka-collectd)
+add_subdirectory(vpp-collectd) \ No newline at end of file
diff --git a/telemetry/vpp-collectd/cmake/packaging.cmake b/telemetry/cmake/packaging.cmake
index 49a617342..d5d2264ce 100644
--- a/telemetry/vpp-collectd/cmake/packaging.cmake
+++ b/telemetry/cmake/packaging.cmake
@@ -21,11 +21,11 @@ set(${COLLECTD_PLUGINS}_DESCRIPTION
)
set(${COLLECTD_PLUGINS}_DEB_DEPENDENCIES
- "collectd, hicn-plugin-dev (= stable_version)"
+ "collectd, hicn-plugin-dev (= stable_version) libhicnctrl (= stable_version) libyajl-dev"
CACHE STRING "Dependencies for deb/rpm package."
)
set(${COLLECTD_PLUGINS}_RPM_DEPENDENCIES
- "collectd, hicn-plugin-dev = stable_version"
+ "collectd, hicn-plugin-dev (= stable_version) libhicnctrl (= stable_version) libyajl-dev"
CACHE STRING "Dependencies for deb/rpm package."
) \ No newline at end of file
diff --git a/telemetry/collectd.conf b/telemetry/collectd.conf
new file mode 100644
index 000000000..225c161c6
--- /dev/null
+++ b/telemetry/collectd.conf
@@ -0,0 +1,54 @@
+##############################################################################
+# Global #
+##############################################################################
+FQDNLookup true
+#Interval 10
+
+# Limit the size of the write queue. Default is no limit. Setting up a limit
+# is recommended for servers handling a high volume of traffic.
+#WriteQueueLimitHigh 1000000
+#WriteQueueLimitLow 800000
+
+##############################################################################
+# Logging #
+##############################################################################
+LoadPlugin logfile
+
+<Plugin logfile>
+ LogLevel "info"
+ File STDOUT
+ Timestamp true
+ PrintSeverity true
+</Plugin>
+
+##############################################################################
+# LoadPlugin section #
+##############################################################################
+LoadPlugin write_log
+
+<LoadPlugin hicn_light>
+ Globals true # Required to find libhicnctrl symbols
+ Interval 5
+</LoadPlugin>
+
+<LoadPlugin write_kafka_line_protocol>
+ Interval 10
+</LoadPlugin>
+
+##############################################################################
+# Plugin configuration #
+##############################################################################
+<Plugin write_kafka_line_protocol>
+ Property "bootstrap.servers" "localhost:8081"
+ Property "security.protocol" "sasl_plaintext"
+ Property "sasl.mechanism" "SCRAM-SHA-256"
+ Property "sasl.username" "eloparco"
+ Property "sasl.password" "password"
+
+ <Topic "stream">
+ Format InfluxDB
+ </Topic>
+ # <Topic "metadata">
+ # Format hicnJSON
+ # </Topic>
+</Plugin>
diff --git a/telemetry/data_model.h b/telemetry/data_model.h
new file mode 100644
index 000000000..b1c4ae7e5
--- /dev/null
+++ b/telemetry/data_model.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ */
+
+#include "utils/common/common.h"
+
+#define KAFKA_TOPIC_KEY "_TOPIC"
+#define KAFKA_STREAM_TOPIC "stream"
+#define KAFKA_METADATA_TOPIC "metadata"
+
+/************** DATA SOURCES ******************************/
+data_source_t packets_dsrc[1] = {
+ {"packets", DS_TYPE_GAUGE, 0, NAN},
+};
+
+data_source_t interests_dsrc[1] = {
+ {"interests", DS_TYPE_GAUGE, 0, NAN},
+};
+
+data_source_t data_dsrc[1] = {
+ {"data", DS_TYPE_GAUGE, 0, NAN},
+};
+
+data_source_t combined_dsrc[2] = {
+ {"packets", DS_TYPE_DERIVE, 0, NAN},
+ {"bytes", DS_TYPE_DERIVE, 0, NAN},
+};
+
+/************** DATA SETS NODE ****************************/
+data_set_t pkts_processed_ds = {
+ "pkts_processed",
+ STATIC_ARRAY_SIZE(packets_dsrc),
+ packets_dsrc,
+};
+
+data_set_t pkts_interest_count_ds = {
+ "pkts_interest_count",
+ STATIC_ARRAY_SIZE(packets_dsrc),
+ packets_dsrc,
+};
+
+data_set_t pkts_data_count_ds = {
+ "pkts_data_count",
+ STATIC_ARRAY_SIZE(packets_dsrc),
+ packets_dsrc,
+};
+
+data_set_t pkts_from_cache_count_ds = {
+ "pkts_from_cache_count",
+ STATIC_ARRAY_SIZE(packets_dsrc),
+ packets_dsrc,
+};
+
+data_set_t pkts_no_pit_count_ds = {
+ "pkts_no_pit_count",
+ STATIC_ARRAY_SIZE(packets_dsrc),
+ packets_dsrc,
+};
+
+data_set_t pit_expired_count_ds = {
+ "pit_expired_count",
+ STATIC_ARRAY_SIZE(interests_dsrc),
+ interests_dsrc,
+};
+
+data_set_t cs_expired_count_ds = {
+ "cs_expired_count",
+ STATIC_ARRAY_SIZE(data_dsrc),
+ data_dsrc,
+};
+
+data_set_t cs_lru_count_ds = {
+ "cs_lru_count",
+ STATIC_ARRAY_SIZE(data_dsrc),
+ data_dsrc,
+};
+
+data_set_t pkts_drop_no_buf_ds = {
+ "pkts_drop_no_buf",
+ STATIC_ARRAY_SIZE(packets_dsrc),
+ packets_dsrc,
+};
+
+data_set_t interests_aggregated_ds = {
+ "interests_aggregated",
+ STATIC_ARRAY_SIZE(interests_dsrc),
+ interests_dsrc,
+};
+
+data_set_t interests_retx_ds = {
+ "interests_retx",
+ STATIC_ARRAY_SIZE(interests_dsrc),
+ interests_dsrc,
+};
+
+data_set_t interests_hash_collision_ds = {
+ "interests_hash_collision",
+ STATIC_ARRAY_SIZE(interests_dsrc),
+ interests_dsrc,
+};
+
+data_set_t pit_entries_count_ds = {
+ "pit_entries_count",
+ STATIC_ARRAY_SIZE(interests_dsrc),
+ interests_dsrc,
+};
+
+data_set_t cs_entries_count_ds = {
+ "cs_entries_count",
+ STATIC_ARRAY_SIZE(data_dsrc),
+ data_dsrc,
+};
+
+data_set_t cs_entries_ntw_count_ds = {
+ "cs_entries_ntw_count",
+ STATIC_ARRAY_SIZE(data_dsrc),
+ data_dsrc,
+};
+
+/************** DATA SETS FACE ****************************/
+data_set_t irx_ds = {
+ "irx",
+ STATIC_ARRAY_SIZE(combined_dsrc),
+ combined_dsrc,
+};
+
+data_set_t itx_ds = {
+ "itx",
+ STATIC_ARRAY_SIZE(combined_dsrc),
+ combined_dsrc,
+};
+
+data_set_t drx_ds = {
+ "drx",
+ STATIC_ARRAY_SIZE(combined_dsrc),
+ combined_dsrc,
+};
+
+data_set_t dtx_ds = {
+ "dtx",
+ STATIC_ARRAY_SIZE(combined_dsrc),
+ combined_dsrc,
+};
diff --git a/telemetry/hicn-light-collectd/CMakeLists.txt b/telemetry/hicn-light-collectd/CMakeLists.txt
new file mode 100644
index 000000000..984d7076c
--- /dev/null
+++ b/telemetry/hicn-light-collectd/CMakeLists.txt
@@ -0,0 +1,65 @@
+# Copyright (c) 2022 Cisco and/or its affiliates.
+
+##############################################################
+# Source files
+##############################################################
+list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light.c
+)
+
+
+##############################################################
+# Include dirs
+##############################################################
+list(APPEND INCLUDE_DIRS
+ ${COLLECTD_INCLUDE_DIRS}
+ ${THIRD_PARTY_INCLUDE_DIRS}
+)
+
+
+##############################################################
+# Libraries
+##############################################################
+find_package(Libhicn ${CURRENT_VERSION} REQUIRED NO_MODULE)
+find_package(Libhicnctrl ${CURRENT_VERSION} REQUIRED NO_MODULE)
+
+if (DISABLE_SHARED_LIBRARIES)
+ set(LIBTYPE static)
+else()
+ set(LIBTYPE shared)
+endif()
+
+list(APPEND LIBHICN_LIBRARIES hicn::hicn.${LIBTYPE})
+list(APPEND LIBHICNCTRL_LIBRARIES hicn::hicnctrl.${LIBTYPE})
+
+list (APPEND LIBRARIES
+ PRIVATE ${LIBHICNCTRL_LIBRARIES}
+ PRIVATE ${LIBHICN_LIBRARIES}
+)
+
+
+##############################################################
+# Compiler options
+##############################################################
+list(APPEND COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+ ${COLLECTD_COMPILER_OPTIONS}
+)
+
+
+##############################################################
+# Build library
+##############################################################
+build_library(${HICN_LIGHT_TELEMETRY}
+ SHARED
+ EMPTY_PREFIX
+ SOURCES ${SOURCE_FILES}
+ LINK_LIBRARIES ${LIBRARIES}
+ INCLUDE_DIRS
+ PRIVATE ${INCLUDE_DIRS}
+ INSTALL_FULL_PATH_DIR ${COLLECTD_PLUGIN_DIR}
+ COMPONENT ${COLLECTD_PLUGINS}
+ DEPENDS ${DEPENDENCIES}
+ LINK_FLAGS ${LINK_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+) \ No newline at end of file
diff --git a/telemetry/hicn-light-collectd/hicn_light.c b/telemetry/hicn-light-collectd/hicn_light.c
new file mode 100644
index 000000000..bb4eb571c
--- /dev/null
+++ b/telemetry/hicn-light-collectd/hicn_light.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ */
+
+#define ntohll hicn_ntohll // Rename to avoid collision
+#include <hicn/ctrl/api.h>
+#include <hicn/ctrl/hicn-light-ng.h>
+#include <hicn/util/sstrncpy.h>
+#undef ntohll
+
+#include "../data_model.h"
+#include "collectd.h"
+#include "plugin.h"
+#include "utils/common/common.h"
+
+#define PLUGIN_NAME "hicn_light"
+
+static hc_sock_t *s = NULL;
+
+static void submit(const char *type, value_t *values, size_t values_len,
+ meta_data_t *meta) {
+ assert(type != NULL && values != NULL && values_len != 0);
+
+ value_list_t vl = {.values = values, .values_len = values_len};
+ if (meta) vl.meta = meta;
+
+ int rc = strcpy_s(vl.plugin, sizeof(vl.plugin), PLUGIN_NAME);
+ _ASSERT(rc == EOK);
+ rc = strcpy_s(vl.type, sizeof(vl.type), type);
+ _ASSERT(rc == EOK);
+ rc = strcpy_s(vl.host, sizeof(vl.host), hostname_g);
+ _ASSERT(rc == EOK);
+
+ plugin_dispatch_values(&vl);
+}
+
+static int read_forwarder_global_stats(hc_data_t **pdata, meta_data_t *meta) {
+ // Retrieve global stats from forwarder
+ int rc = hc_stats_get(s, pdata);
+ if (rc < 0) {
+ plugin_log(LOG_ERR, "Could not read global stats from forwarder");
+ return -1;
+ }
+ hicn_light_stats_t stats = *((hicn_light_stats_t *)(*pdata)->buffer);
+
+ // Submit values
+ value_t values[1];
+ values[0] = (value_t){.gauge = stats.forwarder.countReceived};
+ submit(pkts_processed_ds.type, values, 1, meta);
+ values[0] = (value_t){.gauge = stats.forwarder.countInterestsReceived};
+ submit(pkts_interest_count_ds.type, values, 1, meta);
+ values[0] = (value_t){.gauge = stats.forwarder.countObjectsReceived};
+ submit(pkts_data_count_ds.type, values, 1, meta);
+ values[0] =
+ (value_t){.gauge = stats.forwarder.countInterestsSatisfiedFromStore};
+ submit(pkts_from_cache_count_ds.type, values, 1, meta);
+ values[0] = (value_t){.gauge = stats.forwarder.countDroppedNoReversePath};
+ submit(pkts_no_pit_count_ds.type, values, 1, meta);
+ values[0] = (value_t){.gauge = stats.forwarder.countInterestsExpired};
+ submit(pit_expired_count_ds.type, values, 1, meta);
+ values[0] = (value_t){.gauge = stats.forwarder.countDataExpired};
+ submit(cs_expired_count_ds.type, values, 1, meta);
+ values[0] = (value_t){.gauge = stats.pkt_cache.n_lru_evictions};
+ submit(cs_lru_count_ds.type, values, 1, meta);
+ values[0] = (value_t){.gauge = stats.forwarder.countDropped};
+ submit(pkts_drop_no_buf_ds.type, values, 1, meta);
+ values[0] = (value_t){.gauge = stats.forwarder.countInterestsAggregated};
+ submit(interests_aggregated_ds.type, values, 1, meta);
+ values[0] = (value_t){.gauge = stats.forwarder.countInterestsRetransmitted};
+ submit(interests_retx_ds.type, values, 1, meta);
+ values[0] = (value_t){.gauge = stats.pkt_cache.n_pit_entries};
+ submit(pit_entries_count_ds.type, values, 1, meta);
+ values[0] = (value_t){.gauge = stats.pkt_cache.n_cs_entries};
+ submit(cs_entries_count_ds.type, values, 1, meta);
+
+ return 0;
+}
+
+static int read_forwarder_per_face_stats(hc_data_t **pdata, meta_data_t *meta) {
+ // Retrieve per-face stats from forwarder
+ int rc = hc_stats_list(s, pdata);
+ if (rc < 0) {
+ plugin_log(LOG_ERR, "Could not read face stats from forwarder");
+ return -1;
+ }
+ hc_data_t *data = *pdata;
+ cmd_stats_list_item_t *conn_stats = (cmd_stats_list_item_t *)data->buffer;
+ cmd_stats_list_item_t *end =
+ (cmd_stats_list_item_t *)(data->buffer +
+ data->size * data->out_element_size);
+
+ // Submit values
+ while (conn_stats < end) {
+ rc = meta_data_add_unsigned_int(meta, "face_id", conn_stats->id);
+ assert(rc == 0);
+
+ value_t values[2];
+ values[0] = (value_t){.derive = conn_stats->stats.interests.rx_pkts};
+ values[1] = (value_t){.derive = conn_stats->stats.interests.rx_bytes};
+ submit(irx_ds.type, values, 2, meta);
+ values[0] = (value_t){.derive = conn_stats->stats.interests.tx_pkts};
+ values[1] = (value_t){.derive = conn_stats->stats.interests.tx_bytes};
+ submit(itx_ds.type, values, 2, meta);
+ values[0] = (value_t){.derive = conn_stats->stats.data.rx_pkts};
+ values[1] = (value_t){.derive = conn_stats->stats.data.rx_bytes};
+ submit(drx_ds.type, values, 2, meta);
+ values[0] = (value_t){.derive = conn_stats->stats.data.tx_pkts};
+ values[1] = (value_t){.derive = conn_stats->stats.data.tx_bytes};
+ submit(dtx_ds.type, values, 2, meta);
+
+ conn_stats++;
+ }
+
+ return 0;
+}
+
+static int read_forwarder_stats() {
+ // Create metadata
+ meta_data_t *meta = meta_data_create();
+ int rc = meta_data_add_string(meta, KAFKA_TOPIC_KEY, KAFKA_STREAM_TOPIC);
+ assert(rc == 0);
+
+ hc_data_t *data = NULL;
+ rc = read_forwarder_global_stats(&data, meta);
+ if (rc < 0) goto READ_ERROR;
+ rc = read_forwarder_per_face_stats(&data, meta);
+
+READ_ERROR:
+ meta_data_destroy(meta);
+ hc_data_free(data);
+ return rc;
+}
+
+static int connect_to_forwarder() {
+ plugin_log(LOG_INFO, "Connecting to forwarder");
+ s = hc_sock_create_forwarder(HICNLIGHT_NG);
+ if (!s) {
+ plugin_log(LOG_ERR, "Could not create socket");
+ return -1;
+ }
+
+ int rc = hc_sock_connect(s);
+ if (rc < 0) {
+ plugin_log(LOG_ERR, "Could not establish connection to forwarder");
+ hc_sock_free(s);
+ s = NULL;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int disconnect_from_forwarder() {
+ plugin_log(LOG_INFO, "Disconnecting from forwarder");
+
+ if (s == NULL) {
+ plugin_log(LOG_ERR, "Forwarder not connected");
+ return -1;
+ }
+
+ hc_command_t command = {0};
+ command.object.connection.id = 0;
+ int rc = strcpy_s(command.object.connection.name,
+ sizeof(command.object.connection.name), "SELF");
+ if (rc != EOK || hc_connection_delete(s, &command.object.connection) < 0) {
+ rc = -1;
+ plugin_log(LOG_ERR, "Error removing local connection to forwarder");
+ }
+
+ hc_sock_free(s);
+ return rc;
+}
+
+void module_register() {
+ // Data sets
+ plugin_register_data_set(&pkts_processed_ds);
+ plugin_register_data_set(&pkts_interest_count_ds);
+ plugin_register_data_set(&pkts_data_count_ds);
+ plugin_register_data_set(&pkts_from_cache_count_ds);
+ plugin_register_data_set(&pkts_no_pit_count_ds);
+ plugin_register_data_set(&pit_expired_count_ds);
+ plugin_register_data_set(&cs_expired_count_ds);
+ plugin_register_data_set(&cs_lru_count_ds);
+ plugin_register_data_set(&pkts_drop_no_buf_ds);
+ plugin_register_data_set(&interests_aggregated_ds);
+ plugin_register_data_set(&interests_retx_ds);
+ plugin_register_data_set(&interests_hash_collision_ds);
+ plugin_register_data_set(&pit_entries_count_ds);
+ plugin_register_data_set(&cs_entries_count_ds);
+ plugin_register_data_set(&cs_entries_ntw_count_ds);
+ plugin_register_data_set(&irx_ds);
+ plugin_register_data_set(&itx_ds);
+ plugin_register_data_set(&drx_ds);
+ plugin_register_data_set(&dtx_ds);
+
+ // Callbacks
+ plugin_register_init(PLUGIN_NAME, connect_to_forwarder);
+ plugin_register_read(PLUGIN_NAME, read_forwarder_stats);
+ plugin_register_shutdown(PLUGIN_NAME, disconnect_from_forwarder);
+} \ No newline at end of file
diff --git a/telemetry/kafka-collectd/CMakeLists.txt b/telemetry/kafka-collectd/CMakeLists.txt
new file mode 100644
index 000000000..f1ff81117
--- /dev/null
+++ b/telemetry/kafka-collectd/CMakeLists.txt
@@ -0,0 +1,62 @@
+# Copyright (c) 2022 Cisco and/or its affiliates.
+
+##############################################################
+# Source files
+##############################################################
+file(GLOB_RECURSE COLLECTD_UTILS_SOURCES "${THIRD_PARTY_INCLUDE_DIRS}/utils/cmds/*.c")
+
+list(APPEND SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/write_kafka_line_protocol.c
+ ${THIRD_PARTY_INCLUDE_DIRS}/utils/format_json/format_json.c
+ ${THIRD_PARTY_INCLUDE_DIRS}/utils/format_graphite/format_graphite.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/format_influxdb.c
+ ${COLLECTD_UTILS_SOURCES}
+)
+
+
+##############################################################
+# Include dirs
+##############################################################
+list(APPEND INCLUDE_DIRS
+ PRIVATE ${COLLECTD_INCLUDE_DIRS}
+ PRIVATE ${THIRD_PARTY_INCLUDE_DIRS}
+)
+
+
+##############################################################
+# Libraries
+##############################################################
+find_package(RdKafka ${RDKAFKA_DEFAULT_VERSION} REQUIRED)
+find_library(YAJL_LIB libyajl.so REQUIRED)
+
+list (APPEND LIBRARIES
+ ${YAJL_LIB}
+ ${RdKafka_LIBRARY_PATH}
+)
+
+
+##############################################################
+# Compiler options
+##############################################################
+list(APPEND COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+ ${COLLECTD_COMPILER_OPTIONS}
+)
+
+
+##############################################################
+# Build library
+##############################################################
+build_library(${KAFKA_TELEMETRY}
+ SHARED
+ EMPTY_PREFIX
+ SOURCES ${SOURCE_FILES}
+ LINK_LIBRARIES ${LIBRARIES}
+ INCLUDE_DIRS
+ PRIVATE ${INCLUDE_DIRS}
+ INSTALL_FULL_PATH_DIR ${COLLECTD_PLUGIN_DIR}
+ COMPONENT ${COLLECTD_PLUGINS}
+ DEPENDS ${DEPENDENCIES}
+ LINK_FLAGS ${LINK_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+)
diff --git a/telemetry/kafka-collectd/format_influxdb.c b/telemetry/kafka-collectd/format_influxdb.c
new file mode 100644
index 000000000..f7ff29501
--- /dev/null
+++ b/telemetry/kafka-collectd/format_influxdb.c
@@ -0,0 +1,190 @@
+/**
+ * collectd - src/utils_format_influxdb.c
+ * Copyright (C) 2007-2009 Florian octo Forster
+ * Copyright (C) 2009 Aman Gupta
+ * Copyright (C) 2019 Carlos Peon Costa
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ * Aman Gupta <aman at tmm1.net>
+ * Carlos Peon Costa <carlospeon at gmail.com>
+ * multiple Server directives by:
+ * Paul (systemcrash) <newtwen thatfunny_at_symbol gmail.com>
+ **/
+
+#include "format_influxdb.h"
+
+#include "collectd.h"
+#include "plugin.h"
+#include "utils/common/common.h"
+#include "utils/metadata/meta_data.h"
+#include "utils_cache.h"
+
+static int format_influxdb_escape_string(char *buffer, size_t buffer_size,
+ const char *string) {
+ if ((buffer == NULL) || (string == NULL)) return -EINVAL;
+
+ if (buffer_size < 3) return -ENOMEM;
+
+ int dst_pos = 0;
+
+#define BUFFER_ADD(c) \
+ do { \
+ if (dst_pos >= (buffer_size - 1)) { \
+ buffer[buffer_size - 1] = '\0'; \
+ return -ENOMEM; \
+ } \
+ buffer[dst_pos] = (c); \
+ dst_pos++; \
+ } while (0)
+
+ /* Escape special characters */
+ for (int src_pos = 0; string[src_pos] != 0; src_pos++) {
+ if ((string[src_pos] == '\\') || (string[src_pos] == ' ') ||
+ (string[src_pos] == ',') || (string[src_pos] == '=') ||
+ (string[src_pos] == '"')) {
+ BUFFER_ADD('\\');
+ BUFFER_ADD(string[src_pos]);
+ } else
+ BUFFER_ADD(string[src_pos]);
+ } /* for */
+ buffer[dst_pos] = 0;
+
+#undef BUFFER_ADD
+
+ return dst_pos;
+} /* int format_influxdb_escape_string */
+
+int format_influxdb_value_list(
+ char *buffer, int buffer_len, const data_set_t *ds, const value_list_t *vl,
+ bool store_rates, format_influxdb_time_precision_t time_precision) {
+ int status;
+ int offset = 0;
+ gauge_t *rates = NULL;
+ bool have_values = false;
+
+ assert(0 == strcmp(ds->type, vl->type));
+
+#define BUFFER_ADD_ESCAPE(...) \
+ do { \
+ status = format_influxdb_escape_string(buffer + offset, \
+ buffer_len - offset, __VA_ARGS__); \
+ if (status < 0) return status; \
+ offset += status; \
+ } while (0)
+
+#define BUFFER_ADD(...) \
+ do { \
+ status = snprintf(buffer + offset, buffer_len - offset, __VA_ARGS__); \
+ if ((status < 0) || (status >= (buffer_len - offset))) { \
+ sfree(rates); \
+ return -ENOMEM; \
+ } \
+ offset += status; \
+ } while (0)
+
+ assert(vl->type);
+ BUFFER_ADD_ESCAPE(vl->type);
+ BUFFER_ADD(",host=");
+ BUFFER_ADD_ESCAPE(vl->host);
+ if (vl->meta) {
+ char **toc;
+ int n = meta_data_toc(vl->meta, &toc);
+
+ for (int i = 0; i < n; i++) {
+ char *key = toc[i];
+ char *value;
+
+ if (meta_data_as_string(vl->meta, key, &value) == 0) {
+ BUFFER_ADD(",");
+ BUFFER_ADD_ESCAPE(key);
+ BUFFER_ADD("=");
+ BUFFER_ADD_ESCAPE(value);
+ free(value);
+ }
+ free(toc[i]);
+ }
+
+ if (n != 0) free(toc);
+ }
+
+ BUFFER_ADD(" ");
+ for (size_t i = 0; i < ds->ds_num; i++) {
+ if ((ds->ds[i].type != DS_TYPE_COUNTER) &&
+ (ds->ds[i].type != DS_TYPE_GAUGE) &&
+ (ds->ds[i].type != DS_TYPE_DERIVE) &&
+ (ds->ds[i].type != DS_TYPE_ABSOLUTE)) {
+ sfree(rates);
+ return -EINVAL;
+ }
+
+ if (ds->ds[i].type == DS_TYPE_GAUGE) {
+ if (isnan(vl->values[i].gauge)) continue;
+ if (have_values) BUFFER_ADD(",");
+ BUFFER_ADD("%s=%lf", ds->ds[i].name, vl->values[i].gauge);
+ have_values = true;
+ } else if (store_rates) {
+ if (rates == NULL) rates = uc_get_rate(ds, vl);
+ if (rates == NULL) {
+ WARNING(
+ "format_influxdb: "
+ "uc_get_rate failed.");
+ return -EINVAL;
+ }
+ if (isnan(rates[i])) continue;
+ if (have_values) BUFFER_ADD(",");
+ BUFFER_ADD("%s=%lf", ds->ds[i].name, rates[i]);
+ have_values = true;
+ } else if (ds->ds[i].type == DS_TYPE_COUNTER) {
+ if (have_values) BUFFER_ADD(",");
+ BUFFER_ADD("%s=%" PRIu64 "i", ds->ds[i].name,
+ (uint64_t)vl->values[i].counter);
+ have_values = true;
+ } else if (ds->ds[i].type == DS_TYPE_DERIVE) {
+ if (have_values) BUFFER_ADD(",");
+ BUFFER_ADD("%s=%" PRIi64 "i", ds->ds[i].name, vl->values[i].derive);
+ have_values = true;
+ } else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) {
+ if (have_values) BUFFER_ADD(",");
+ BUFFER_ADD("%s=%" PRIu64 "i", ds->ds[i].name, vl->values[i].absolute);
+ have_values = true;
+ }
+
+ } /* for ds->ds_num */
+ sfree(rates);
+
+ if (!have_values) return 0;
+
+ uint64_t influxdb_time = 0;
+ switch (time_precision) {
+ case NS:
+ influxdb_time = CDTIME_T_TO_NS(vl->time);
+ break;
+ case US:
+ influxdb_time = CDTIME_T_TO_US(vl->time);
+ break;
+ case MS:
+ influxdb_time = CDTIME_T_TO_MS(vl->time);
+ break;
+ }
+
+ BUFFER_ADD(" %" PRIu64 "\n", influxdb_time);
+
+#undef BUFFER_ADD_ESCAPE
+#undef BUFFER_ADD
+
+ return offset;
+} /* int format_influxdb_value_list */
diff --git a/telemetry/kafka-collectd/format_influxdb.h b/telemetry/kafka-collectd/format_influxdb.h
new file mode 100644
index 000000000..fd298f11b
--- /dev/null
+++ b/telemetry/kafka-collectd/format_influxdb.h
@@ -0,0 +1,45 @@
+/**
+ * collectd - src/utils_format_influxdb.h
+ * Copyright (C) 2007-2009 Florian octo Forster
+ * Copyright (C) 2009 Aman Gupta
+ * Copyright (C) 2019 Carlos Peon Costa
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ * Aman Gupta <aman at tmm1.net>
+ * Carlos Peon Costa <carlospeon at gmail.com>
+ * multiple Server directives by:
+ * Paul (systemcrash) <newtwen thatfunny_at_symbol gmail.com>
+ **/
+
+#ifndef UTILS_FORMAT_INFLUXDB_H
+#define UTILS_FORMAT_INFLUXDB_H 1
+
+#include "collectd.h"
+#include "plugin.h"
+
+typedef enum {
+ NS,
+ US,
+ MS,
+} format_influxdb_time_precision_t;
+
+int format_influxdb_value_list(char *buffer, int buffer_len,
+ const data_set_t *ds, const value_list_t *vl,
+ bool store_rates,
+ format_influxdb_time_precision_t time_precision);
+
+#endif /* UTILS_FORMAT_INFLUXDB_H */
diff --git a/telemetry/kafka-collectd/write_kafka_line_protocol.c b/telemetry/kafka-collectd/write_kafka_line_protocol.c
new file mode 100644
index 000000000..5eb7b520d
--- /dev/null
+++ b/telemetry/kafka-collectd/write_kafka_line_protocol.c
@@ -0,0 +1,526 @@
+/**
+ * collectd - src/write_kafka.c
+ * Copyright (C) 2014 Pierre-Yves Ritschard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Pierre-Yves Ritschard <pyr at spootnik.org>
+ */
+
+#include <errno.h>
+#include <librdkafka/rdkafka.h>
+#include <stdint.h>
+
+#include "../data_model.h"
+#include "collectd.h"
+#include "format_influxdb.h"
+#include "plugin.h"
+#include "utils/cmds/putval.h"
+#include "utils/common/common.h"
+#include "utils/format_graphite/format_graphite.h"
+#include "utils/format_json/format_json.h"
+#include "utils_random.h"
+
+struct kafka_topic_context {
+#define KAFKA_FORMAT_JSON 0
+#define KAFKA_FORMAT_COMMAND 1
+#define KAFKA_FORMAT_GRAPHITE 2
+#define KAFKA_FORMAT_INFLUXDB 3
+ uint8_t format;
+ unsigned int graphite_flags;
+ bool store_rates;
+ rd_kafka_topic_conf_t *conf;
+ rd_kafka_topic_t *topic;
+ rd_kafka_conf_t *kafka_conf;
+ rd_kafka_t *kafka;
+ char *key;
+ char *prefix;
+ char *postfix;
+ char escape_char;
+ char *topic_name;
+ pthread_mutex_t lock;
+};
+
+static int kafka_handle(struct kafka_topic_context *);
+static int kafka_write(const data_set_t *, const value_list_t *, user_data_t *);
+static int32_t kafka_partition(const rd_kafka_topic_t *, const void *, size_t,
+ int32_t, void *, void *);
+
+/* Version 0.9.0 of librdkafka deprecates rd_kafka_set_logger() in favor of
+ * rd_kafka_conf_set_log_cb(). This is to make sure we're not using the
+ * deprecated function. */
+#ifdef HAVE_LIBRDKAFKA_LOG_CB
+#undef HAVE_LIBRDKAFKA_LOGGER
+#endif
+
+#if defined(HAVE_LIBRDKAFKA_LOGGER) || defined(HAVE_LIBRDKAFKA_LOG_CB)
+static void kafka_log(const rd_kafka_t *, int, const char *, const char *);
+
+static void kafka_log(const rd_kafka_t *rkt, int level, const char *fac,
+ const char *msg) {
+ plugin_log(level, "%s", msg);
+}
+#endif
+
+static rd_kafka_resp_err_t kafka_error() {
+#if RD_KAFKA_VERSION >= 0x000b00ff
+ return rd_kafka_last_error();
+#else
+ return rd_kafka_errno2err(errno);
+#endif
+}
+
+static uint32_t kafka_hash(const char *keydata, size_t keylen) {
+ uint32_t hash = 5381;
+ for (; keylen > 0; keylen--)
+ hash = ((hash << 5) + hash) + keydata[keylen - 1];
+ return hash;
+}
+
+/* 31 bit -> 4 byte -> 8 byte hex string + null byte */
+#define KAFKA_RANDOM_KEY_SIZE 9
+#define KAFKA_RANDOM_KEY_BUFFER \
+ (char[KAFKA_RANDOM_KEY_SIZE]) { "" }
+static char *kafka_random_key(char buffer[static KAFKA_RANDOM_KEY_SIZE]) {
+ ssnprintf(buffer, KAFKA_RANDOM_KEY_SIZE, "%08" PRIX32, cdrand_u());
+ return buffer;
+}
+
+static int32_t kafka_partition(const rd_kafka_topic_t *rkt, const void *keydata,
+ size_t keylen, int32_t partition_cnt, void *p,
+ void *m) {
+ uint32_t key = kafka_hash(keydata, keylen);
+ uint32_t target = key % partition_cnt;
+ int32_t i = partition_cnt;
+
+ while (--i > 0 && !rd_kafka_topic_partition_available(rkt, target)) {
+ target = (target + 1) % partition_cnt;
+ }
+ return target;
+}
+
+static int kafka_handle(struct kafka_topic_context *ctx) /* {{{ */
+{
+ char errbuf[1024];
+ rd_kafka_conf_t *conf;
+ rd_kafka_topic_conf_t *topic_conf;
+
+ if (ctx->kafka != NULL && ctx->topic != NULL) return 0;
+
+ if (ctx->kafka == NULL) {
+ if ((conf = rd_kafka_conf_dup(ctx->kafka_conf)) == NULL) {
+ ERROR("write_kafka plugin: cannot duplicate kafka config");
+ return 1;
+ }
+
+ if ((ctx->kafka = rd_kafka_new(RD_KAFKA_PRODUCER, conf, errbuf,
+ sizeof(errbuf))) == NULL) {
+ ERROR("write_kafka plugin: cannot create kafka handle.");
+ return 1;
+ }
+
+ rd_kafka_conf_destroy(ctx->kafka_conf);
+ ctx->kafka_conf = NULL;
+
+ INFO("write_kafka plugin: created KAFKA handle : %s",
+ rd_kafka_name(ctx->kafka));
+
+#if defined(HAVE_LIBRDKAFKA_LOGGER) && !defined(HAVE_LIBRDKAFKA_LOG_CB)
+ rd_kafka_set_logger(ctx->kafka, kafka_log);
+#endif
+ }
+
+ if (ctx->topic == NULL) {
+ if ((topic_conf = rd_kafka_topic_conf_dup(ctx->conf)) == NULL) {
+ ERROR("write_kafka plugin: cannot duplicate kafka topic config");
+ return 1;
+ }
+
+ if ((ctx->topic = rd_kafka_topic_new(ctx->kafka, ctx->topic_name,
+ topic_conf)) == NULL) {
+ ERROR("write_kafka plugin: cannot create topic : %s\n",
+ rd_kafka_err2str(kafka_error()));
+ return errno;
+ }
+
+ rd_kafka_topic_conf_destroy(ctx->conf);
+ ctx->conf = NULL;
+
+ INFO("write_kafka plugin: handle created for topic : %s",
+ rd_kafka_topic_name(ctx->topic));
+ }
+
+ return 0;
+
+} /* }}} int kafka_handle */
+
+static int kafka_write(const data_set_t *ds, /* {{{ */
+ const value_list_t *vl, user_data_t *ud) {
+ int status = 0;
+ void *key;
+ size_t keylen = 0;
+ char buffer[8192];
+ size_t bfree = sizeof(buffer);
+ size_t bfill = 0;
+ size_t blen = 0;
+ struct kafka_topic_context *ctx = ud->data;
+
+ if ((ds == NULL) || (vl == NULL) || (ctx == NULL)) return EINVAL;
+
+ pthread_mutex_lock(&ctx->lock);
+ status = kafka_handle(ctx);
+ pthread_mutex_unlock(&ctx->lock);
+ if (status != 0) return status;
+
+ bzero(buffer, sizeof(buffer));
+
+ switch (ctx->format) {
+ case KAFKA_FORMAT_COMMAND:
+ status = cmd_create_putval(buffer, sizeof(buffer), ds, vl);
+ if (status != 0) {
+ ERROR("write_kafka plugin: cmd_create_putval failed with status %i.",
+ status);
+ return status;
+ }
+ blen = strlen(buffer);
+ break;
+ case KAFKA_FORMAT_JSON:
+ format_json_initialize(buffer, &bfill, &bfree);
+ format_json_value_list(buffer, &bfill, &bfree, ds, vl, ctx->store_rates);
+ format_json_finalize(buffer, &bfill, &bfree);
+ blen = strlen(buffer);
+ break;
+ case KAFKA_FORMAT_GRAPHITE:
+ status =
+ format_graphite(buffer, sizeof(buffer), ds, vl, ctx->prefix,
+ ctx->postfix, ctx->escape_char, ctx->graphite_flags);
+ if (status != 0) {
+ ERROR("write_kafka plugin: format_graphite failed with status %i.",
+ status);
+ return status;
+ }
+ blen = strlen(buffer);
+ break;
+ case KAFKA_FORMAT_INFLUXDB: {
+ // Decide format depending on the topic
+ // (to handle multilple topics w/ different formats);
+ // Comment this part to use the stream topic as default for other
+ // collectd plugins (e.g. cpu, mem)
+ char *topic = NULL;
+ int rc = meta_data_get_string(vl->meta, KAFKA_TOPIC_KEY, &topic);
+ if (rc != 0 || topic == NULL) return 0;
+ if (strcasecmp(KAFKA_STREAM_TOPIC, topic) != 0) {
+ free(topic);
+ return 0;
+ }
+ meta_data_delete(vl->meta, KAFKA_TOPIC_KEY);
+
+ status =
+ format_influxdb_value_list(buffer, sizeof(buffer), ds, vl, false, NS);
+ if (status <= 0) {
+ ERROR("write_kafka plugin: format_influxdb failed with status %i.",
+ status);
+ return status;
+ }
+ blen = strlen(buffer);
+
+ // Print without newline
+ buffer[blen - 1] = 0;
+ INFO("%s", buffer);
+ buffer[blen - 1] = '\n';
+
+ break;
+ }
+ default:
+ ERROR("write_kafka plugin: invalid format %i.", ctx->format);
+ return -1;
+ }
+
+ key =
+ (ctx->key != NULL) ? ctx->key : kafka_random_key(KAFKA_RANDOM_KEY_BUFFER);
+ keylen = strlen(key);
+
+ rd_kafka_produce(ctx->topic, RD_KAFKA_PARTITION_UA, RD_KAFKA_MSG_F_COPY,
+ buffer, blen, key, keylen, NULL);
+
+ return status;
+} /* }}} int kafka_write */
+
+static void kafka_topic_context_free(void *p) /* {{{ */
+{
+ struct kafka_topic_context *ctx = p;
+
+ if (ctx == NULL) return;
+
+ if (ctx->topic_name != NULL) sfree(ctx->topic_name);
+ if (ctx->topic != NULL) rd_kafka_topic_destroy(ctx->topic);
+ if (ctx->conf != NULL) rd_kafka_topic_conf_destroy(ctx->conf);
+ if (ctx->kafka_conf != NULL) rd_kafka_conf_destroy(ctx->kafka_conf);
+ if (ctx->kafka != NULL) rd_kafka_destroy(ctx->kafka);
+
+ sfree(ctx);
+} /* }}} void kafka_topic_context_free */
+
+static void kafka_config_topic(rd_kafka_conf_t *conf,
+ oconfig_item_t *ci) /* {{{ */
+{
+ int status;
+ struct kafka_topic_context *tctx;
+ char *key = NULL;
+ char *val;
+ char callback_name[DATA_MAX_NAME_LEN];
+ char errbuf[1024];
+ oconfig_item_t *child;
+ rd_kafka_conf_res_t ret;
+
+ if ((tctx = calloc(1, sizeof(*tctx))) == NULL) {
+ ERROR("write_kafka plugin: calloc failed.");
+ return;
+ }
+
+ tctx->escape_char = '.';
+ tctx->store_rates = true;
+ tctx->format = KAFKA_FORMAT_JSON;
+ tctx->key = NULL;
+
+ if ((tctx->kafka_conf = rd_kafka_conf_dup(conf)) == NULL) {
+ sfree(tctx);
+ ERROR("write_kafka plugin: cannot allocate memory for kafka config");
+ return;
+ }
+
+#ifdef HAVE_LIBRDKAFKA_LOG_CB
+ rd_kafka_conf_set_log_cb(tctx->kafka_conf, kafka_log);
+#endif
+
+ if ((tctx->conf = rd_kafka_topic_conf_new()) == NULL) {
+ rd_kafka_conf_destroy(tctx->kafka_conf);
+ sfree(tctx);
+ ERROR("write_kafka plugin: cannot create topic configuration.");
+ return;
+ }
+
+ if (ci->values_num != 1) {
+ WARNING("kafka topic name needed.");
+ goto errout;
+ }
+
+ if (ci->values[0].type != OCONFIG_TYPE_STRING) {
+ WARNING("kafka topic needs a string argument.");
+ goto errout;
+ }
+
+ if ((tctx->topic_name = strdup(ci->values[0].value.string)) == NULL) {
+ ERROR("write_kafka plugin: cannot copy topic name.");
+ goto errout;
+ }
+
+ for (int i = 0; i < ci->children_num; i++) {
+ /*
+ * The code here could be simplified but makes room
+ * for easy adding of new options later on.
+ */
+ child = &ci->children[i];
+ status = 0;
+
+ if (strcasecmp("Property", child->key) == 0) {
+ if (child->values_num != 2) {
+ WARNING("kafka properties need both a key and a value.");
+ goto errout;
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("kafka properties needs string arguments.");
+ goto errout;
+ }
+ key = child->values[0].value.string;
+ val = child->values[1].value.string;
+ ret =
+ rd_kafka_topic_conf_set(tctx->conf, key, val, errbuf, sizeof(errbuf));
+ if (ret != RD_KAFKA_CONF_OK) {
+ WARNING("cannot set kafka topic property %s to %s: %s.", key, val,
+ errbuf);
+ goto errout;
+ }
+
+ } else if (strcasecmp("Key", child->key) == 0) {
+ if (cf_util_get_string(child, &tctx->key) != 0) continue;
+ if (strcasecmp("Random", tctx->key) == 0) {
+ sfree(tctx->key);
+ tctx->key = strdup(kafka_random_key(KAFKA_RANDOM_KEY_BUFFER));
+ }
+ } else if (strcasecmp("Format", child->key) == 0) {
+ status = cf_util_get_string(child, &key);
+ if (status != 0) goto errout;
+
+ assert(key != NULL);
+
+ if (strcasecmp(key, "Command") == 0) {
+ tctx->format = KAFKA_FORMAT_COMMAND;
+
+ } else if (strcasecmp(key, "Graphite") == 0) {
+ tctx->format = KAFKA_FORMAT_GRAPHITE;
+
+ } else if (strcasecmp(key, "Json") == 0) {
+ tctx->format = KAFKA_FORMAT_JSON;
+
+ } else if (strcasecmp(key, "InfluxDB") == 0) {
+ tctx->format = KAFKA_FORMAT_INFLUXDB;
+
+ } else {
+ WARNING("write_kafka plugin: Invalid format string: %s", key);
+ }
+
+ sfree(key);
+
+ } else if (strcasecmp("StoreRates", child->key) == 0) {
+ status = cf_util_get_boolean(child, &tctx->store_rates);
+ (void)cf_util_get_flag(child, &tctx->graphite_flags,
+ GRAPHITE_STORE_RATES);
+
+ } else if (strcasecmp("GraphiteSeparateInstances", child->key) == 0) {
+ status = cf_util_get_flag(child, &tctx->graphite_flags,
+ GRAPHITE_SEPARATE_INSTANCES);
+
+ } else if (strcasecmp("GraphiteAlwaysAppendDS", child->key) == 0) {
+ status = cf_util_get_flag(child, &tctx->graphite_flags,
+ GRAPHITE_ALWAYS_APPEND_DS);
+
+ } else if (strcasecmp("GraphitePreserveSeparator", child->key) == 0) {
+ status = cf_util_get_flag(child, &tctx->graphite_flags,
+ GRAPHITE_PRESERVE_SEPARATOR);
+
+ } else if (strcasecmp("GraphiteUseTags", child->key) == 0) {
+ status =
+ cf_util_get_flag(child, &tctx->graphite_flags, GRAPHITE_USE_TAGS);
+
+ } else if (strcasecmp("GraphitePrefix", child->key) == 0) {
+ status = cf_util_get_string(child, &tctx->prefix);
+ } else if (strcasecmp("GraphitePostfix", child->key) == 0) {
+ status = cf_util_get_string(child, &tctx->postfix);
+ } else if (strcasecmp("GraphiteEscapeChar", child->key) == 0) {
+ char *tmp_buff = NULL;
+ status = cf_util_get_string(child, &tmp_buff);
+ if (strlen(tmp_buff) > 1)
+ WARNING(
+ "write_kafka plugin: The option \"GraphiteEscapeChar\" handles "
+ "only one character. Others will be ignored.");
+ tctx->escape_char = tmp_buff[0];
+ sfree(tmp_buff);
+ } else {
+ WARNING("write_kafka plugin: Invalid directive: %s.", child->key);
+ }
+
+ if (status != 0) break;
+ }
+
+ rd_kafka_topic_conf_set_partitioner_cb(tctx->conf, kafka_partition);
+ rd_kafka_topic_conf_set_opaque(tctx->conf, tctx);
+
+ ssnprintf(callback_name, sizeof(callback_name), "write_kafka/%s",
+ tctx->topic_name);
+
+ status = plugin_register_write(callback_name, kafka_write,
+ &(user_data_t){
+ .data = tctx,
+ .free_func = kafka_topic_context_free,
+ });
+ if (status != 0) {
+ WARNING(
+ "write_kafka plugin: plugin_register_write (\"%s\") "
+ "failed with status %i.",
+ callback_name, status);
+ goto errout;
+ }
+
+ pthread_mutex_init(&tctx->lock, /* attr = */ NULL);
+
+ return;
+errout:
+ if (tctx->topic_name != NULL) free(tctx->topic_name);
+ if (tctx->conf != NULL) rd_kafka_topic_conf_destroy(tctx->conf);
+ if (tctx->kafka_conf != NULL) rd_kafka_conf_destroy(tctx->kafka_conf);
+ sfree(tctx);
+} /* }}} int kafka_config_topic */
+
+static int kafka_config(oconfig_item_t *ci) /* {{{ */
+{
+ oconfig_item_t *child;
+ rd_kafka_conf_t *conf;
+ rd_kafka_conf_res_t ret;
+ char errbuf[1024];
+
+ if ((conf = rd_kafka_conf_new()) == NULL) {
+ WARNING("cannot allocate kafka configuration.");
+ return -1;
+ }
+ for (int i = 0; i < ci->children_num; i++) {
+ child = &ci->children[i];
+
+ if (strcasecmp("Topic", child->key) == 0) {
+ kafka_config_topic(conf, child);
+ } else if (strcasecmp(child->key, "Property") == 0) {
+ char *key = NULL;
+ char *val = NULL;
+
+ if (child->values_num != 2) {
+ WARNING("kafka properties need both a key and a value.");
+ goto errout;
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("kafka properties needs string arguments.");
+ goto errout;
+ }
+ if ((key = strdup(child->values[0].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute key.");
+ goto errout;
+ }
+ if ((val = strdup(child->values[1].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute value.");
+ sfree(key);
+ goto errout;
+ }
+ ret = rd_kafka_conf_set(conf, key, val, errbuf, sizeof(errbuf));
+ if (ret != RD_KAFKA_CONF_OK) {
+ WARNING("cannot set kafka property %s to %s: %s", key, val, errbuf);
+ sfree(key);
+ sfree(val);
+ goto errout;
+ }
+ sfree(key);
+ sfree(val);
+ } else {
+ WARNING(
+ "write_kafka plugin: Ignoring unknown "
+ "configuration option \"%s\" at top level.",
+ child->key);
+ }
+ }
+ if (conf != NULL) rd_kafka_conf_destroy(conf);
+ return 0;
+errout:
+ if (conf != NULL) rd_kafka_conf_destroy(conf);
+ return -1;
+} /* }}} int kafka_config */
+
+void module_register(void) {
+ plugin_register_complex_config("write_kafka_line_protocol", kafka_config);
+}
diff --git a/telemetry/third-party/CMakeLists.txt b/telemetry/third-party/CMakeLists.txt
new file mode 100644
index 000000000..26d305d62
--- /dev/null
+++ b/telemetry/third-party/CMakeLists.txt
@@ -0,0 +1,18 @@
+# Copyright (c) 2022 Cisco and/or its affiliates.
+
+set(THIRD_PARTY_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR})
+
+include(FetchContent)
+set(FETCHCONTENT_QUIET off)
+FetchContent_Declare(collectd
+ URL https://github.com/collectd/collectd/archive/refs/tags/collectd-${COLLECTD_VERSION}.zip
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+)
+FetchContent_Populate(collectd)
+
+list(APPEND THIRD_PARTY_INCLUDE_DIRS
+ ${collectd_SOURCE_DIR}/src
+)
+set(THIRD_PARTY_INCLUDE_DIRS ${THIRD_PARTY_INCLUDE_DIRS} PARENT_SCOPE)
diff --git a/telemetry/vpp-collectd/CMakeLists.txt b/telemetry/vpp-collectd/CMakeLists.txt
index 54a1a4b76..4ce357f63 100644
--- a/telemetry/vpp-collectd/CMakeLists.txt
+++ b/telemetry/vpp-collectd/CMakeLists.txt
@@ -11,34 +11,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-project(hicn-collectd-plugins)
-
-
-##############################################################
-# CMake Modules
-##############################################################
-set(CMAKE_MODULE_PATH
- ${CMAKE_MODULE_PATH}
- ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/Modules/)
-
-
##############################################################
# Dependencies
##############################################################
find_package(Vpp ${VPP_DEFAULT_VERSION} REQUIRED)
-find_package(Collectd ${COLLECTD_DEFAULT_VERSION} REQUIRED)
-
-
-##############################################################
-# Libs and bins names
-##############################################################
-set(COLLECTD_PLUGINS hicn-collectd-plugins)
-
-
-##############################################################
-# Packaging
-##############################################################
-include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake)
##############################################################
diff --git a/telemetry/vpp-collectd/common/README.md b/telemetry/vpp-collectd/common/README.md
deleted file mode 100644
index e3b9c74f6..000000000
--- a/telemetry/vpp-collectd/common/README.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Headers for collectd plugins
-
-These headers are required for plugin development but are not shipped with the
-`collectd` Ubuntu 20.04 package (as of May 2021):
-
-* [common.h](https://github.com/collectd/collectd/blob/main/src/utils/common/common.h)
-* [plugin.h](https://github.com/collectd/collectd/blob/main/src/daemon/plugin.h)
-* [meta_data.h](https://github.com/collectd/collectd/blob/main/src/utils/metadata/meta_data.h)
-
-Related issues:
-* [GitHub](https://github.com/collectd/collectd/issues/3881)
-* [Ubuntu](https://bugs.launchpad.net/ubuntu/+source/collectd/+bug/1929079)
diff --git a/telemetry/vpp-collectd/common/common.h b/telemetry/vpp-collectd/common/common.h
deleted file mode 100644
index fce2d12bb..000000000
--- a/telemetry/vpp-collectd/common/common.h
+++ /dev/null
@@ -1,405 +0,0 @@
-/**
- * collectd - src/common.h
- * Copyright (C) 2005-2014 Florian octo Forster
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Florian octo Forster <octo at collectd.org>
- * Niki W. Waibel <niki.waibel@gmx.net>
- **/
-
-#ifndef COMMON_H
-#define COMMON_H
-
-#include "collectd.h"
-
-#include "plugin.h"
-
-#if HAVE_PWD_H
-#include <pwd.h>
-#endif
-
-#define sfree(ptr) \
- do { \
- free(ptr); \
- (ptr) = NULL; \
- } while (0)
-
-#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))
-
-struct rate_to_value_state_s {
- value_t last_value;
- cdtime_t last_time;
- gauge_t residual;
-};
-typedef struct rate_to_value_state_s rate_to_value_state_t;
-
-struct value_to_rate_state_s {
- value_t last_value;
- cdtime_t last_time;
-};
-typedef struct value_to_rate_state_s value_to_rate_state_t;
-
-char *sstrncpy(char *dest, const char *src, size_t n);
-
-__attribute__((format(printf, 3, 4))) int ssnprintf(char *str, size_t size,
- char const *format, ...);
-
-__attribute__((format(printf, 1, 2))) char *ssnprintf_alloc(char const *format,
- ...);
-
-char *sstrdup(const char *s);
-size_t sstrnlen(const char *s, size_t n);
-char *sstrndup(const char *s, size_t n);
-void *smalloc(size_t size);
-char *sstrerror(int errnum, char *buf, size_t buflen);
-
-#ifndef ERRBUF_SIZE
-#define ERRBUF_SIZE 256
-#endif
-
-#define STRERROR(e) sstrerror((e), (char[ERRBUF_SIZE]){0}, ERRBUF_SIZE)
-#define STRERRNO STRERROR(errno)
-
-/*
- * NAME
- * sread
- *
- * DESCRIPTION
- * Reads exactly `n' bytes or fails. Syntax and other behavior is analogous
- * to `read(2)'.
- *
- * PARAMETERS
- * `fd' File descriptor to write to.
- * `buf' Buffer that is to be written.
- * `count' Number of bytes in the buffer.
- *
- * RETURN VALUE
- * Zero upon success or non-zero if an error occurred. `errno' is set in this
- * case.
- */
-int sread(int fd, void *buf, size_t count);
-
-/*
- * NAME
- * swrite
- *
- * DESCRIPTION
- * Writes exactly `n' bytes or fails. Syntax and other behavior is analogous
- * to `write(2)'.
- *
- * PARAMETERS
- * `fd' File descriptor to write to.
- * `buf' Buffer that is to be written.
- * `count' Number of bytes in the buffer.
- *
- * RETURN VALUE
- * Zero upon success or non-zero if an error occurred. `errno' is set in this
- * case.
- */
-int swrite(int fd, const void *buf, size_t count);
-
-/*
- * NAME
- * strsplit
- *
- * DESCRIPTION
- * Splits a string into parts and stores pointers to the parts in `fields'.
- * The characters split at are: " ", "\t", "\r", and "\n".
- *
- * PARAMETERS
- * `string' String to split. This string will be modified. `fields' will
- * contain pointers to parts of this string, so free'ing it
- * will destroy `fields' as well.
- * `fields' Array of strings where pointers to the parts will be stored.
- * `size' Number of elements in the array. No more than `size'
- * pointers will be stored in `fields'.
- *
- * RETURN VALUE
- * Returns the number of parts stored in `fields'.
- */
-int strsplit(char *string, char **fields, size_t size);
-
-/*
- * NAME
- * strjoin
- *
- * DESCRIPTION
- * Joins together several parts of a string using `sep' as a separator. This
- * is equivalent to the Perl built-in `join'.
- *
- * PARAMETERS
- * `dst' Buffer where the result is stored. Can be NULL if you need to
- * determine the required buffer size only.
- * `dst_len' Length of the destination buffer. No more than this many
- * bytes will be written to the memory pointed to by `dst',
- * including the trailing null-byte. Must be zero if dst is
- * NULL.
- * `fields' Array of strings to be joined.
- * `fields_num' Number of elements in the `fields' array.
- * `sep' String to be inserted between any two elements of `fields'.
- * This string is neither prepended nor appended to the result.
- * Instead of passing "" (empty string) one can pass NULL.
- *
- * RETURN VALUE
- * Returns the number of characters in the resulting string, excluding a
- * tailing null byte. If this value is greater than or equal to "dst_len", the
- * result in "dst" is truncated (but still null terminated). On error a
- * negative value is returned.
- */
-int strjoin(char *dst, size_t dst_len, char **fields, size_t fields_num,
- const char *sep);
-
-/*
- * NAME
- * escape_slashes
- *
- * DESCRIPTION
- * Removes slashes ("/") from "buffer". If buffer contains a single slash,
- * the result will be "root". Leading slashes are removed. All other slashes
- * are replaced with underscores ("_").
- * This function is used by plugin_dispatch_values() to escape all parts of
- * the identifier.
- *
- * PARAMETERS
- * `buffer' String to be escaped.
- * `buffer_size' Size of the buffer. No more then this many bytes will be
- * written to `buffer', including the trailing null-byte.
- *
- * RETURN VALUE
- * Returns zero upon success and a value smaller than zero upon failure.
- */
-int escape_slashes(char *buffer, size_t buffer_size);
-
-/**
- * NAME
- * escape_string
- *
- * DESCRIPTION
- * escape_string quotes and escapes a string to be usable with collectd's
- * plain text protocol. "simple" strings are left as they are, for example if
- * buffer is 'simple' before the call, it will remain 'simple'. However, if
- * buffer contains 'more "complex"' before the call, the returned buffer will
- * contain '"more \"complex\""'.
- *
- * If the buffer is too small to contain the escaped string, the string will
- * be truncated. However, leading and trailing double quotes, as well as an
- * ending null byte are guaranteed.
- *
- * RETURN VALUE
- * Returns zero on success, even if the string was truncated. Non-zero on
- * failure.
- */
-int escape_string(char *buffer, size_t buffer_size);
-
-/*
- * NAME
- * replace_special
- *
- * DESCRIPTION
- * Replaces any special characters (anything that's not alpha-numeric or a
- * dash) with an underscore.
- *
- * E.g. "foo$bar&" would become "foo_bar_".
- *
- * PARAMETERS
- * `buffer' String to be handled.
- * `buffer_size' Length of the string. The function returns after
- * encountering a null-byte or reading this many bytes.
- */
-void replace_special(char *buffer, size_t buffer_size);
-
-/*
- * NAME
- * strunescape
- *
- * DESCRIPTION
- * Replaces any escaped characters in a string with the appropriate special
- * characters. The following escaped characters are recognized:
- *
- * \t -> <tab>
- * \n -> <newline>
- * \r -> <carriage return>
- *
- * For all other escacped characters only the backslash will be removed.
- *
- * PARAMETERS
- * `buf' String to be unescaped.
- * `buf_len' Length of the string, including the terminating null-byte.
- *
- * RETURN VALUE
- * Returns zero upon success, a value less than zero else.
- */
-int strunescape(char *buf, size_t buf_len);
-
-/**
- * Removed trailing newline characters (CR and LF) from buffer, which must be
- * null terminated. Returns the length of the resulting string.
- */
-__attribute__((nonnull(1))) size_t strstripnewline(char *buffer);
-
-/*
- * NAME
- * timeval_cmp
- *
- * DESCRIPTION
- * Compare the two time values `tv0' and `tv1' and store the absolut value
- * of the difference in the time value pointed to by `delta' if it does not
- * equal NULL.
- *
- * RETURN VALUE
- * Returns an integer less than, equal to, or greater than zero if `tv0' is
- * less than, equal to, or greater than `tv1' respectively.
- */
-int timeval_cmp(struct timeval tv0, struct timeval tv1, struct timeval *delta);
-
-/* make sure tv_usec stores less than a second */
-#define NORMALIZE_TIMEVAL(tv) \
- do { \
- (tv).tv_sec += (tv).tv_usec / 1000000; \
- (tv).tv_usec = (tv).tv_usec % 1000000; \
- } while (0)
-
-/* make sure tv_sec stores less than a second */
-#define NORMALIZE_TIMESPEC(tv) \
- do { \
- (tv).tv_sec += (tv).tv_nsec / 1000000000; \
- (tv).tv_nsec = (tv).tv_nsec % 1000000000; \
- } while (0)
-
-int check_create_dir(const char *file_orig);
-
-#ifdef HAVE_LIBKSTAT
-#if HAVE_KSTAT_H
-#include <kstat.h>
-#endif
-int get_kstat(kstat_t **ksp_ptr, char *module, int instance, char *name);
-long long get_kstat_value(kstat_t *ksp, char *name);
-#endif
-
-#ifndef HAVE_HTONLL
-unsigned long long ntohll(unsigned long long n);
-unsigned long long htonll(unsigned long long n);
-#endif
-
-#if FP_LAYOUT_NEED_NOTHING
-#define ntohd(d) (d)
-#define htond(d) (d)
-#elif FP_LAYOUT_NEED_ENDIANFLIP || FP_LAYOUT_NEED_INTSWAP
-double ntohd(double d);
-double htond(double d);
-#else
-#error \
- "Don't know how to convert between host and network representation of doubles."
-#endif
-
-int format_name(char *ret, int ret_len, const char *hostname,
- const char *plugin, const char *plugin_instance,
- const char *type, const char *type_instance);
-#define FORMAT_VL(ret, ret_len, vl) \
- format_name(ret, ret_len, (vl)->host, (vl)->plugin, (vl)->plugin_instance, \
- (vl)->type, (vl)->type_instance)
-int format_values(char *ret, size_t ret_len, const data_set_t *ds,
- const value_list_t *vl, bool store_rates);
-
-int parse_identifier(char *str, char **ret_host, char **ret_plugin,
- char **ret_plugin_instance, char **ret_type,
- char **ret_type_instance, char *default_host);
-int parse_identifier_vl(const char *str, value_list_t *vl);
-int parse_value(const char *value, value_t *ret_value, int ds_type);
-int parse_values(char *buffer, value_list_t *vl, const data_set_t *ds);
-
-/* parse_value_file reads "path" and parses its content as an integer or
- * floating point, depending on "ds_type". On success, the value is stored in
- * "ret_value" and zero is returned. On failure, a non-zero value is returned.
- */
-int parse_value_file(char const *path, value_t *ret_value, int ds_type);
-
-#if !HAVE_GETPWNAM_R
-struct passwd;
-int getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen,
- struct passwd **pwbufp);
-#endif
-
-int notification_init(notification_t *n, int severity, const char *message,
- const char *host, const char *plugin,
- const char *plugin_instance, const char *type,
- const char *type_instance);
-#define NOTIFICATION_INIT_VL(n, vl) \
- notification_init(n, NOTIF_FAILURE, NULL, (vl)->host, (vl)->plugin, \
- (vl)->plugin_instance, (vl)->type, (vl)->type_instance)
-
-typedef int (*dirwalk_callback_f)(const char *dirname, const char *filename,
- void *user_data);
-int walk_directory(const char *dir, dirwalk_callback_f callback,
- void *user_data, int hidden);
-/* Returns the number of bytes read or negative on error. */
-ssize_t read_file_contents(char const *filename, void *buf, size_t bufsize);
-/* Writes the contents of the file into the buffer with a trailing NUL.
- * Returns the number of bytes written to the buffer or negative on error. */
-ssize_t read_text_file_contents(char const *filename, char *buf,
- size_t bufsize);
-
-counter_t counter_diff(counter_t old_value, counter_t new_value);
-
-/* Convert a rate back to a value_t. When converting to a derive_t, counter_t
- * or absolute_t, take fractional residuals into account. This is important
- * when scaling counters, for example.
- * Returns zero on success. Returns EAGAIN when called for the first time; in
- * this case the value_t is invalid and the next call should succeed. Other
- * return values indicate an error. */
-int rate_to_value(value_t *ret_value, gauge_t rate,
- rate_to_value_state_t *state, int ds_type, cdtime_t t);
-
-int value_to_rate(gauge_t *ret_rate, value_t value, int ds_type, cdtime_t t,
- value_to_rate_state_t *state);
-
-/* Converts a service name (a string) to a port number
- * (in the range [1-65535]). Returns less than zero on error. */
-int service_name_to_port_number(const char *service_name);
-
-/* Sets various, non-default, socket options */
-void set_sock_opts(int sockfd);
-
-/** Parse a string to a derive_t value. Returns zero on success or non-zero on
- * failure. If failure is returned, ret_value is not touched. */
-int strtoderive(const char *string, derive_t *ret_value);
-
-/** Parse a string to a gauge_t value. Returns zero on success or non-zero on
- * failure. If failure is returned, ret_value is not touched. */
-int strtogauge(const char *string, gauge_t *ret_value);
-
-int strarray_add(char ***ret_array, size_t *ret_array_len, char const *str);
-void strarray_free(char **array, size_t array_len);
-
-/** Check if the current process benefits from the capability passed in
- * argument. Returns zero if it does, less than zero if it doesn't or on error.
- * See capabilities(7) for the list of possible capabilities.
- * */
-int check_capability(int arg);
-
-#endif /* COMMON_H */
diff --git a/telemetry/vpp-collectd/common/meta_data.h b/telemetry/vpp-collectd/common/meta_data.h
deleted file mode 100644
index 203b14607..000000000
--- a/telemetry/vpp-collectd/common/meta_data.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * collectd - src/meta_data.h
- * Copyright (C) 2008-2011 Florian octo Forster
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Florian octo Forster <octo at collectd.org>
- **/
-
-#ifndef META_DATA_H
-#define META_DATA_H
-
-#include "collectd.h"
-
-/*
- * Defines
- */
-#define MD_TYPE_STRING 1
-#define MD_TYPE_SIGNED_INT 2
-#define MD_TYPE_UNSIGNED_INT 3
-#define MD_TYPE_DOUBLE 4
-#define MD_TYPE_BOOLEAN 5
-
-struct meta_data_s;
-typedef struct meta_data_s meta_data_t;
-
-meta_data_t *meta_data_create(void);
-meta_data_t *meta_data_clone(meta_data_t *orig);
-int meta_data_clone_merge(meta_data_t **dest, meta_data_t *orig);
-void meta_data_destroy(meta_data_t *md);
-
-int meta_data_exists(meta_data_t *md, const char *key);
-int meta_data_type(meta_data_t *md, const char *key);
-int meta_data_toc(meta_data_t *md, char ***toc);
-int meta_data_delete(meta_data_t *md, const char *key);
-
-int meta_data_add_string(meta_data_t *md, const char *key, const char *value);
-int meta_data_add_signed_int(meta_data_t *md, const char *key, int64_t value);
-int meta_data_add_unsigned_int(meta_data_t *md, const char *key,
- uint64_t value);
-int meta_data_add_double(meta_data_t *md, const char *key, double value);
-int meta_data_add_boolean(meta_data_t *md, const char *key, bool value);
-
-int meta_data_get_string(meta_data_t *md, const char *key, char **value);
-int meta_data_get_signed_int(meta_data_t *md, const char *key, int64_t *value);
-int meta_data_get_unsigned_int(meta_data_t *md, const char *key,
- uint64_t *value);
-int meta_data_get_double(meta_data_t *md, const char *key, double *value);
-int meta_data_get_boolean(meta_data_t *md, const char *key, bool *value);
-
-/* Returns the value as a string, regardless of the type. */
-int meta_data_as_string(meta_data_t *md, const char *key, char **value);
-
-#endif /* META_DATA_H */
diff --git a/telemetry/vpp-collectd/common/plugin.h b/telemetry/vpp-collectd/common/plugin.h
deleted file mode 100644
index bbd69e003..000000000
--- a/telemetry/vpp-collectd/common/plugin.h
+++ /dev/null
@@ -1,483 +0,0 @@
-/**
- * collectd - src/daemon/plugin.h
- * Copyright (C) 2005-2014 Florian octo Forster
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Florian octo Forster <octo at collectd.org>
- * Sebastian Harl <sh at tokkee.org>
- **/
-
-#ifndef PLUGIN_H
-#define PLUGIN_H
-
-#include "collectd.h"
-
-#include "configfile.h"
-#include "meta_data.h"
-#include "utils_time.h"
-
-#include <inttypes.h>
-#include <pthread.h>
-
-#define DS_TYPE_COUNTER 0
-#define DS_TYPE_GAUGE 1
-#define DS_TYPE_DERIVE 2
-#define DS_TYPE_ABSOLUTE 3
-
-#define DS_TYPE_TO_STRING(t) \
- (t == DS_TYPE_COUNTER) ? "counter" \
- : (t == DS_TYPE_GAUGE) ? "gauge" \
- : (t == DS_TYPE_DERIVE) ? "derive" \
- : (t == DS_TYPE_ABSOLUTE) ? "absolute" \
- : "unknown"
-
-#ifndef LOG_ERR
-#define LOG_ERR 3
-#endif
-#ifndef LOG_WARNING
-#define LOG_WARNING 4
-#endif
-#ifndef LOG_NOTICE
-#define LOG_NOTICE 5
-#endif
-#ifndef LOG_INFO
-#define LOG_INFO 6
-#endif
-#ifndef LOG_DEBUG
-#define LOG_DEBUG 7
-#endif
-
-#define NOTIF_MAX_MSG_LEN 256
-
-#define NOTIF_FAILURE 1
-#define NOTIF_WARNING 2
-#define NOTIF_OKAY 4
-
-#define plugin_interval (plugin_get_ctx().interval)
-
-/*
- * Public data types
- */
-struct identifier_s {
- char *host;
- char *plugin;
- char *plugin_instance;
- char *type;
- char *type_instance;
-};
-typedef struct identifier_s identifier_t;
-
-typedef unsigned long long counter_t;
-typedef double gauge_t;
-typedef int64_t derive_t;
-typedef uint64_t absolute_t;
-
-union value_u {
- counter_t counter;
- gauge_t gauge;
- derive_t derive;
- absolute_t absolute;
-};
-typedef union value_u value_t;
-
-struct value_list_s {
- value_t *values;
- size_t values_len;
- cdtime_t time;
- cdtime_t interval;
- char host[DATA_MAX_NAME_LEN];
- char plugin[DATA_MAX_NAME_LEN];
- char plugin_instance[DATA_MAX_NAME_LEN];
- char type[DATA_MAX_NAME_LEN];
- char type_instance[DATA_MAX_NAME_LEN];
- meta_data_t *meta;
-};
-typedef struct value_list_s value_list_t;
-
-#define VALUE_LIST_INIT \
- { .values = NULL, .meta = NULL }
-
-struct data_source_s {
- char name[DATA_MAX_NAME_LEN];
- int type;
- double min;
- double max;
-};
-typedef struct data_source_s data_source_t;
-
-struct data_set_s {
- char type[DATA_MAX_NAME_LEN];
- size_t ds_num;
- data_source_t *ds;
-};
-typedef struct data_set_s data_set_t;
-
-enum notification_meta_type_e {
- NM_TYPE_STRING,
- NM_TYPE_SIGNED_INT,
- NM_TYPE_UNSIGNED_INT,
- NM_TYPE_DOUBLE,
- NM_TYPE_BOOLEAN
-};
-
-typedef struct notification_meta_s {
- char name[DATA_MAX_NAME_LEN];
- enum notification_meta_type_e type;
- union {
- const char *nm_string;
- int64_t nm_signed_int;
- uint64_t nm_unsigned_int;
- double nm_double;
- bool nm_boolean;
- } nm_value;
- struct notification_meta_s *next;
-} notification_meta_t;
-
-typedef struct notification_s {
- int severity;
- cdtime_t time;
- char message[NOTIF_MAX_MSG_LEN];
- char host[DATA_MAX_NAME_LEN];
- char plugin[DATA_MAX_NAME_LEN];
- char plugin_instance[DATA_MAX_NAME_LEN];
- char type[DATA_MAX_NAME_LEN];
- char type_instance[DATA_MAX_NAME_LEN];
- notification_meta_t *meta;
-} notification_t;
-
-struct user_data_s {
- void *data;
- void (*free_func)(void *);
-};
-typedef struct user_data_s user_data_t;
-
-enum cache_event_type_e { CE_VALUE_NEW, CE_VALUE_UPDATE, CE_VALUE_EXPIRED };
-
-typedef struct cache_event_s {
- enum cache_event_type_e type;
- const value_list_t *value_list;
- const char *value_list_name;
- int ret;
-} cache_event_t;
-
-struct plugin_ctx_s {
- char *name;
- cdtime_t interval;
- cdtime_t flush_interval;
- cdtime_t flush_timeout;
-};
-typedef struct plugin_ctx_s plugin_ctx_t;
-
-/*
- * Callback types
- */
-typedef int (*plugin_init_cb)(void);
-typedef int (*plugin_read_cb)(user_data_t *);
-typedef int (*plugin_write_cb)(const data_set_t *, const value_list_t *,
- user_data_t *);
-typedef int (*plugin_flush_cb)(cdtime_t timeout, const char *identifier,
- user_data_t *);
-/* "missing" callback. Returns less than zero on failure, zero if other
- * callbacks should be called, greater than zero if no more callbacks should be
- * called. */
-typedef int (*plugin_missing_cb)(const value_list_t *, user_data_t *);
-/* "cache event" callback. CE_VALUE_NEW events are sent to all registered
- * callbacks. Callback should check if it interested in further CE_VALUE_UPDATE
- * and CE_VALUE_EXPIRED events for metric and set event->ret = 1 if so.
- */
-typedef int (*plugin_cache_event_cb)(cache_event_t *, user_data_t *);
-typedef void (*plugin_log_cb)(int severity, const char *message, user_data_t *);
-typedef int (*plugin_shutdown_cb)(void);
-typedef int (*plugin_notification_cb)(const notification_t *, user_data_t *);
-/*
- * NAME
- * plugin_set_dir
- *
- * DESCRIPTION
- * Sets the current `plugindir'
- *
- * ARGUMENTS
- * `dir' Path to the plugin directory
- *
- * NOTES
- * If `dir' is NULL the compiled in default `PLUGINDIR' is used.
- */
-void plugin_set_dir(const char *dir);
-
-/*
- * NAME
- * plugin_load
- *
- * DESCRIPTION
- * Searches the current `plugindir' (see `plugin_set_dir') for the plugin
- * named $type and loads it. Afterwards the plugin's `module_register'
- * function is called, which then calls `plugin_register' to register callback
- * functions.
- *
- * ARGUMENTS
- * `name' Name of the plugin to load.
- * `global' Make this plugins symbols available for other shared libraries.
- *
- * RETURN VALUE
- * Returns zero upon success, a value greater than zero if no plugin was found
- * and a value below zero if an error occurs.
- *
- * NOTES
- * Re-loading an already loaded module is detected and zero is returned in
- * this case.
- */
-int plugin_load(const char *name, bool global);
-bool plugin_is_loaded(char const *name);
-
-int plugin_init_all(void);
-void plugin_read_all(void);
-int plugin_read_all_once(void);
-int plugin_shutdown_all(void);
-
-/*
- * NAME
- * plugin_write
- *
- * DESCRIPTION
- * Calls the write function of the given plugin with the provided data set and
- * value list. It differs from `plugin_dispatch_values' in that it does not
- * update the cache, does not do threshold checking, call the chain subsystem
- * and so on. It looks up the requested plugin and invokes the function, end
- * of story.
- *
- * ARGUMENTS
- * plugin Name of the plugin. If NULL, the value is sent to all registered
- * write functions.
- * ds Pointer to the data_set_t structure. If NULL, the data set is
- * looked up according to the `type' member in the `vl' argument.
- * vl The actual value to be processed. Must not be NULL.
- *
- * RETURN VALUE
- * Returns zero upon success or non-zero if an error occurred. If `plugin' is
- * NULL and more than one plugin is called, an error is only returned if *all*
- * plugins fail.
- *
- * NOTES
- * This is the function used by the `write' built-in target. May be used by
- * other target plugins.
- */
-int plugin_write(const char *plugin, const data_set_t *ds,
- const value_list_t *vl);
-
-int plugin_flush(const char *plugin, cdtime_t timeout, const char *identifier);
-
-/*
- * The `plugin_register_*' functions are used to make `config', `init',
- * `read', `write' and `shutdown' functions known to the plugin
- * infrastructure. Also, the data-formats are made public like this.
- */
-int plugin_register_config(const char *name,
- int (*callback)(const char *key, const char *val),
- const char **keys, int keys_num);
-int plugin_register_complex_config(const char *type,
- int (*callback)(oconfig_item_t *));
-int plugin_register_init(const char *name, plugin_init_cb callback);
-int plugin_register_read(const char *name, int (*callback)(void));
-/* "user_data" will be freed automatically, unless
- * "plugin_register_complex_read" returns an error (non-zero). */
-int plugin_register_complex_read(const char *group, const char *name,
- plugin_read_cb callback, cdtime_t interval,
- user_data_t const *user_data);
-int plugin_register_write(const char *name, plugin_write_cb callback,
- user_data_t const *user_data);
-int plugin_register_flush(const char *name, plugin_flush_cb callback,
- user_data_t const *user_data);
-int plugin_register_missing(const char *name, plugin_missing_cb callback,
- user_data_t const *user_data);
-int plugin_register_cache_event(const char *name,
- plugin_cache_event_cb callback,
- user_data_t const *ud);
-int plugin_register_shutdown(const char *name, plugin_shutdown_cb callback);
-int plugin_register_data_set(const data_set_t *ds);
-int plugin_register_log(const char *name, plugin_log_cb callback,
- user_data_t const *user_data);
-int plugin_register_notification(const char *name,
- plugin_notification_cb callback,
- user_data_t const *user_data);
-
-int plugin_unregister_config(const char *name);
-int plugin_unregister_complex_config(const char *name);
-int plugin_unregister_init(const char *name);
-int plugin_unregister_read(const char *name);
-int plugin_unregister_read_group(const char *group);
-int plugin_unregister_write(const char *name);
-int plugin_unregister_flush(const char *name);
-int plugin_unregister_missing(const char *name);
-int plugin_unregister_cache_event(const char *name);
-int plugin_unregister_shutdown(const char *name);
-int plugin_unregister_data_set(const char *name);
-int plugin_unregister_log(const char *name);
-int plugin_unregister_notification(const char *name);
-
-/*
- * NAME
- * plugin_log_available_writers
- *
- * DESCRIPTION
- * This function can be called to output a list of _all_ registered
- * writers to the logfacility.
- * Since some writers dynamically build their name it can be hard for
- * the configuring person to know it. This function will fill this gap.
- */
-void plugin_log_available_writers(void);
-
-/*
- * NAME
- * plugin_dispatch_values
- *
- * DESCRIPTION
- * This function is called by reading processes with the values they've
- * aquired. The function fetches the data-set definition (that has been
- * registered using `plugin_register_data_set') and calls _all_ registered
- * write-functions.
- *
- * ARGUMENTS
- * `vl' Value list of the values that have been read by a `read'
- * function.
- */
-int plugin_dispatch_values(value_list_t const *vl);
-
-/*
- * NAME
- * plugin_dispatch_multivalue
- *
- * SYNOPSIS
- * plugin_dispatch_multivalue (vl, true, DS_TYPE_GAUGE,
- * "free", 42.0,
- * "used", 58.0,
- * NULL);
- *
- * DESCRIPTION
- * Takes a list of type instances and values and dispatches that in a batch,
- * making sure that all values have the same time stamp. If "store_percentage"
- * is set to true, the "type" is set to "percent" and a percentage is
- * calculated and dispatched, rather than the absolute values. Values that are
- * NaN are dispatched as NaN and will not influence the total.
- *
- * The variadic arguments is a list of type_instance / type pairs, that are
- * interpreted as type "char const *" and type, encoded by their corresponding
- * "store_type":
- *
- * - "gauge_t" when "DS_TYPE_GAUGE"
- * - "absolute_t" when "DS_TYPE_ABSOLUTE"
- * - "derive_t" when "DS_TYPE_DERIVE"
- * - "counter_t" when "DS_TYPE_COUNTER"
- *
- * The last argument must be
- * a NULL pointer to signal end-of-list.
- *
- * RETURNS
- * The number of values it failed to dispatch (zero on success).
- */
-__attribute__((sentinel)) int plugin_dispatch_multivalue(value_list_t const *vl,
- bool store_percentage,
- int store_type, ...);
-
-int plugin_dispatch_missing(const value_list_t *vl);
-void plugin_dispatch_cache_event(enum cache_event_type_e event_type,
- unsigned long callbacks_mask, const char *name,
- const value_list_t *vl);
-
-int plugin_dispatch_notification(const notification_t *notif);
-
-void plugin_log(int level, const char *format, ...)
- __attribute__((format(printf, 2, 3)));
-
-/* These functions return the parsed severity or less than zero on failure. */
-int parse_log_severity(const char *severity);
-int parse_notif_severity(const char *severity);
-
-#define ERROR(...) plugin_log(LOG_ERR, __VA_ARGS__)
-#define WARNING(...) plugin_log(LOG_WARNING, __VA_ARGS__)
-#define NOTICE(...) plugin_log(LOG_NOTICE, __VA_ARGS__)
-#define INFO(...) plugin_log(LOG_INFO, __VA_ARGS__)
-#if COLLECT_DEBUG
-#define DEBUG(...) plugin_log(LOG_DEBUG, __VA_ARGS__)
-#else /* COLLECT_DEBUG */
-#define DEBUG(...) /* noop */
-#endif /* ! COLLECT_DEBUG */
-
-/* This will log messages, prefixed by plugin name */
-void daemon_log(int level, const char *format, ...)
- __attribute__((format(printf, 2, 3)));
-
-#define P_ERROR(...) daemon_log(LOG_ERR, __VA_ARGS__)
-#define P_WARNING(...) daemon_log(LOG_WARNING, __VA_ARGS__)
-#define P_NOTICE(...) daemon_log(LOG_NOTICE, __VA_ARGS__)
-#define P_INFO(...) daemon_log(LOG_INFO, __VA_ARGS__)
-
-const data_set_t *plugin_get_ds(const char *name);
-
-int plugin_notification_meta_add_string(notification_t *n, const char *name,
- const char *value);
-int plugin_notification_meta_add_signed_int(notification_t *n, const char *name,
- int64_t value);
-int plugin_notification_meta_add_unsigned_int(notification_t *n,
- const char *name, uint64_t value);
-int plugin_notification_meta_add_double(notification_t *n, const char *name,
- double value);
-int plugin_notification_meta_add_boolean(notification_t *n, const char *name,
- bool value);
-
-int plugin_notification_meta_copy(notification_t *dst,
- const notification_t *src);
-
-int plugin_notification_meta_free(notification_meta_t *n);
-
-/*
- * Plugin context management.
- */
-
-void plugin_init_ctx(void);
-
-plugin_ctx_t plugin_get_ctx(void);
-plugin_ctx_t plugin_set_ctx(plugin_ctx_t ctx);
-
-/*
- * NAME
- * plugin_get_interval
- *
- * DESCRIPTION
- * This function returns the current value of the plugin's interval. The
- * return value will be strictly greater than zero in all cases. If
- * everything else fails, it will fall back to 10 seconds.
- */
-cdtime_t plugin_get_interval(void);
-
-/*
- * Context-aware thread management.
- */
-
-int plugin_thread_create(pthread_t *thread, void *(*start_routine)(void *),
- void *arg, char const *name);
-
-/*
- * Plugins need to implement this
- */
-
-void module_register(void);
-
-#endif /* PLUGIN_H */
diff --git a/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt b/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt
index d55aede80..85dd51577 100644
--- a/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt
+++ b/telemetry/vpp-collectd/vpp-hicn/CMakeLists.txt
@@ -12,55 +12,62 @@
# limitations under the License.
##############################################################
-# Check if building as subproject or as root project
+# Dependencies
##############################################################
-if(${CMAKE_SOURCE_DIR}/vpp-collectd STREQUAL ${PROJECT_SOURCE_DIR})
- message (STATUS "not compiling in the same folder")
- find_package(HicnPlugin ${CURRENT_VERSION} REQUIRED)
- find_package(Vapisafe ${CURRENT_VERSION} REQUIRED)
-else()
- message (STATUS "compiling in the same folder")
- list(APPEND DEPENDENCIES
- ${HICNPLUGIN_SHARED}
- )
-endif()
+find_package(HicnPlugin ${CURRENT_VERSION} REQUIRED)
+find_package(Libsafevapi ${CURRENT_VERSION} REQUIRED NO_MODULE)
##############################################################
-# Sources
+# Source files
##############################################################
list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/vpp_hicn.c
)
+
+##############################################################
+# Include dirs
+##############################################################
list(APPEND INCLUDE_DIRS
${COLLECTD_INCLUDE_DIRS}
+ ${THIRD_PARTY_INCLUDE_DIRS}
${HICNPLUGIN_INCLUDE_DIRS}
- ${SAFE_VAPI_INCLUDE_DIRS}
+ ${Libsafe_vapi_INCLUDE_DIRS}
${VPP_INCLUDE_DIRS}
- ${CMAKE_CURRENT_SOURCE_DIR}
- "${CMAKE_CURRENT_SOURCE_DIR}/../common"
)
##############################################################
-# Libs
+# Libraries
##############################################################
list(APPEND LIBRARIES
${VPP_LIBRARY_VAPICLIENT}
- ${SAFE_VAPI_LIBRARIES}
+ hicn::safevapi.shared
+)
+
+
+##############################################################
+# Compiler options
+##############################################################
+list(APPEND COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+ ${COLLECTD_COMPILER_OPTIONS}
)
##############################################################
# Build library
##############################################################
-build_library(vpp_hicn
+build_library(${VPP_HICN_TELEMETRY}
+ SHARED
+ EMPTY_PREFIX
SOURCES ${SOURCE_FILES}
LINK_LIBRARIES ${LIBRARIES}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- INSTALL_FULL_PATH_DIR ${CMAKE_INSTALL_PREFIX}/lib/collectd
- COMPONENT "${COLLECTD_PLUGINS}"
+ INCLUDE_DIRS
+ PRIVATE ${INCLUDE_DIRS}
+ INSTALL_FULL_PATH_DIR ${COLLECTD_PLUGIN_DIR}
+ COMPONENT ${COLLECTD_PLUGINS}
DEPENDS ${DEPENDENCIES}
COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
diff --git a/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c b/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
index a724c1124..a20bcbcd0 100644
--- a/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
+++ b/telemetry/vpp-collectd/vpp-hicn/vpp_hicn.c
@@ -13,13 +13,14 @@
* limitations under the License.
*/
-/* Keep order as it is */
-#include "common.h"
-#include <config.h>
+#include "../../data_model.h"
+#include "collectd.h"
+#include "plugin.h"
+#include "utils/common/common.h"
#define counter_t vpp_counter_t
+#include <hicn/vapi/vapi_safe.h>
#include <vapi/hicn.api.vapi.h>
-#include <vapi/vapi_safe.h>
#undef counter_t
DEFINE_VAPI_MSG_IDS_HICN_API_JSON
@@ -34,140 +35,6 @@ static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
static bool verbose = false;
static char *tag = NULL;
-/************** DATA SOURCES ******************************/
-static data_source_t packets_dsrc[1] = {
- {"packets", DS_TYPE_GAUGE, 0, NAN},
-};
-
-static data_source_t interests_dsrc[1] = {
- {"interests", DS_TYPE_GAUGE, 0, NAN},
-};
-
-static data_source_t data_dsrc[1] = {
- {"data", DS_TYPE_GAUGE, 0, NAN},
-};
-
-static data_source_t combined_dsrc[2] = {
- {"packets", DS_TYPE_DERIVE, 0, NAN},
- {"bytes", DS_TYPE_DERIVE, 0, NAN},
-};
-
-/************** DATA SETS NODE ****************************/
-static data_set_t pkts_processed_ds = {
- "pkts_processed",
- STATIC_ARRAY_SIZE(packets_dsrc),
- packets_dsrc,
-};
-
-static data_set_t pkts_interest_count_ds = {
- "pkts_interest_count",
- STATIC_ARRAY_SIZE(packets_dsrc),
- packets_dsrc,
-};
-
-static data_set_t pkts_data_count_ds = {
- "pkts_data_count",
- STATIC_ARRAY_SIZE(packets_dsrc),
- packets_dsrc,
-};
-
-static data_set_t pkts_from_cache_count_ds = {
- "pkts_from_cache_count",
- STATIC_ARRAY_SIZE(packets_dsrc),
- packets_dsrc,
-};
-
-static data_set_t pkts_no_pit_count_ds = {
- "pkts_no_pit_count",
- STATIC_ARRAY_SIZE(packets_dsrc),
- packets_dsrc,
-};
-
-static data_set_t pit_expired_count_ds = {
- "pit_expired_count",
- STATIC_ARRAY_SIZE(interests_dsrc),
- interests_dsrc,
-};
-
-static data_set_t cs_expired_count_ds = {
- "cs_expired_count",
- STATIC_ARRAY_SIZE(data_dsrc),
- data_dsrc,
-};
-
-static data_set_t cs_lru_count_ds = {
- "cs_lru_count",
- STATIC_ARRAY_SIZE(data_dsrc),
- data_dsrc,
-};
-
-static data_set_t pkts_drop_no_buf_ds = {
- "pkts_drop_no_buf",
- STATIC_ARRAY_SIZE(packets_dsrc),
- packets_dsrc,
-};
-
-static data_set_t interests_aggregated_ds = {
- "interests_aggregated",
- STATIC_ARRAY_SIZE(interests_dsrc),
- interests_dsrc,
-};
-
-static data_set_t interests_retx_ds = {
- "interests_retx",
- STATIC_ARRAY_SIZE(interests_dsrc),
- interests_dsrc,
-};
-
-static data_set_t interests_hash_collision_ds = {
- "interests_hash_collision",
- STATIC_ARRAY_SIZE(interests_dsrc),
- interests_dsrc,
-};
-
-static data_set_t pit_entries_count_ds = {
- "pit_entries_count",
- STATIC_ARRAY_SIZE(interests_dsrc),
- interests_dsrc,
-};
-
-static data_set_t cs_entries_count_ds = {
- "cs_entries_count",
- STATIC_ARRAY_SIZE(data_dsrc),
- data_dsrc,
-};
-
-static data_set_t cs_entries_ntw_count_ds = {
- "cs_entries_ntw_count",
- STATIC_ARRAY_SIZE(data_dsrc),
- data_dsrc,
-};
-
-/************** DATA SETS FACE ****************************/
-static data_set_t irx_ds = {
- "irx",
- STATIC_ARRAY_SIZE(combined_dsrc),
- combined_dsrc,
-};
-
-static data_set_t itx_ds = {
- "itx",
- STATIC_ARRAY_SIZE(combined_dsrc),
- combined_dsrc,
-};
-
-static data_set_t drx_ds = {
- "drx",
- STATIC_ARRAY_SIZE(combined_dsrc),
- combined_dsrc,
-};
-
-static data_set_t dtx_ds = {
- "dtx",
- STATIC_ARRAY_SIZE(combined_dsrc),
- combined_dsrc,
-};
-
/**********************************************************/
/********** UTILITY FUNCTIONS *****************************/
/**********************************************************/
@@ -189,8 +56,7 @@ static int submit(const char *plugin_instance, const char *type,
sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance));
sstrncpy(vl.type, type, sizeof(vl.type));
- if (tag != NULL)
- sstrncpy(vl.type_instance, tag, sizeof(vl.type_instance));
+ if (tag != NULL) sstrncpy(vl.type_instance, tag, sizeof(vl.type_instance));
return plugin_dispatch_values(&vl);
}
@@ -223,15 +89,12 @@ static int vpp_hicn_config(const char *key, const char *value) {
/*
* Callback called by the hICN plugin API when node stats are ready.
*/
-static vapi_error_e
-parse_node_stats(vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_node_stats_get_reply *reply) {
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e parse_node_stats(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_node_stats_get_reply *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
- if (reply->retval != VAPI_OK)
- return reply->retval;
+ if (reply->retval != VAPI_OK) return reply->retval;
char *node_name = "node";
value_t values[1];
@@ -277,15 +140,12 @@ parse_node_stats(vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv,
/*
* Callback called by the hICN plugin API when face stats are ready.
*/
-static vapi_error_e
-parse_face_stats(vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv,
- bool is_last,
- vapi_payload_hicn_api_face_stats_details *reply) {
- if (reply == NULL || rv != VAPI_OK)
- return rv;
+static vapi_error_e parse_face_stats(
+ vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_hicn_api_face_stats_details *reply) {
+ if (reply == NULL || rv != VAPI_OK) return rv;
- if (reply->retval != VAPI_OK)
- return reply->retval;
+ if (reply->retval != VAPI_OK) return reply->retval;
char face_name[10];
snprintf(face_name, 10, "face%u", reply->faceid);
@@ -314,8 +174,7 @@ parse_face_stats(vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv,
static int vpp_hicn_init(void) {
int ret = vapi_connect_safe(&vapi_ctx, 0);
- if (ret)
- plugin_log(LOG_ERR, "vpp_hicn plugin: vapi_connect_safe failed");
+ if (ret) plugin_log(LOG_ERR, "vpp_hicn plugin: vapi_connect_safe failed");
return ret;
}
diff --git a/telemetry/vpp-collectd/vpp/CMakeLists.txt b/telemetry/vpp-collectd/vpp/CMakeLists.txt
index 41c19208a..e1cf55553 100644
--- a/telemetry/vpp-collectd/vpp/CMakeLists.txt
+++ b/telemetry/vpp-collectd/vpp/CMakeLists.txt
@@ -20,13 +20,12 @@ list(APPEND SOURCE_FILES
##############################################################
-# Include directories
+# Include dirs
##############################################################
list(APPEND INCLUDE_DIRS
${COLLECTD_INCLUDE_DIRS}
+ ${THIRD_PARTY_INCLUDE_DIRS}
${VPP_INCLUDE_DIRS}
- ${CMAKE_CURRENT_SOURCE_DIR}
- "${CMAKE_CURRENT_SOURCE_DIR}/../common"
)
@@ -39,11 +38,26 @@ list(APPEND LIBRARIES
)
-build_module(vpp
+##############################################################
+# Compiler options
+##############################################################
+list(APPEND COMPILER_OPTIONS
+ ${DEFAULT_COMPILER_OPTIONS}
+ ${COLLECTD_COMPILER_OPTIONS}
+)
+
+
+##############################################################
+# Build library
+##############################################################
+build_library(${VPP_TELEMETRY}
+ SHARED
+ EMPTY_PREFIX
SOURCES ${SOURCE_FILES}
LINK_LIBRARIES ${LIBRARIES}
- INCLUDE_DIRS ${INCLUDE_DIRS}
- INSTALL_FULL_PATH_DIR ${CMAKE_INSTALL_PREFIX}/lib/collectd
+ INCLUDE_DIRS
+ PRIVATE ${INCLUDE_DIRS}
+ INSTALL_FULL_PATH_DIR ${COLLECTD_PLUGIN_DIR}
COMPONENT ${COLLECTD_PLUGINS}
COMPILE_OPTIONS ${COMPILER_OPTIONS}
)
diff --git a/telemetry/vpp-collectd/vpp/vpp.c b/telemetry/vpp-collectd/vpp/vpp.c
index 85d0971d0..ff70f3503 100644
--- a/telemetry/vpp-collectd/vpp/vpp.c
+++ b/telemetry/vpp-collectd/vpp/vpp.c
@@ -13,9 +13,9 @@
* limitations under the License.
*/
-/* Keep order as it is */
-#include "common.h"
-#include <config.h>
+#include "collectd.h"
+#include "plugin.h"
+#include "utils/common/common.h"
#define counter_t vpp_counter_t
#include <vpp-api/client/stat_client.h>
@@ -165,8 +165,7 @@ static int submit(const char *plugin_instance, const char *type,
sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance));
sstrncpy(vl.type, type, sizeof(vl.type));
- if (tag != NULL)
- sstrncpy(vl.type_instance, tag, sizeof(vl.type_instance));
+ if (tag != NULL) sstrncpy(vl.type_instance, tag, sizeof(vl.type_instance));
return plugin_dispatch_values(&vl);
}
@@ -261,8 +260,7 @@ static int vpp_init(void) {
u8 *stat_segment_name = (u8 *)STAT_SEGMENT_SOCKET_FILE;
int ret = stat_segment_connect((char *)stat_segment_name);
- if (ret)
- plugin_log(LOG_ERR, "vpp plugin: connecting to segment failed");
+ if (ret) plugin_log(LOG_ERR, "vpp plugin: connecting to segment failed");
return ret;
}
@@ -296,66 +294,65 @@ static int vpp_read(void) {
/* Collect results for each interface and submit them */
for (int i = 0; i < vec_len(res); i++) {
switch (res[i].type) {
- 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++) {
- if (!interfaces[j]) {
- continue;
- }
+ 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++) {
+ if (!interfaces[j]) {
+ continue;
+ }
- if (get_data_set(res[i].name, &data_set)) {
- 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]}};
+ value_t values[1] = {
+ (value_t){.derive = res[i].simple_counter_vec[k][j]}};
- err = submit(interfaces[j], data_set.type, values, 1, &timestamp);
+ err = submit(interfaces[j], data_set.type, values, 1, &timestamp);
- if (err)
- goto END;
+ if (err) goto END;
+ }
}
- }
- break;
+ break;
- 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++) {
- if (!interfaces[j]) {
- continue;
- }
+ 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++) {
+ if (!interfaces[j]) {
+ continue;
+ }
- if (get_data_set(res[i].name, &data_set)) {
- 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},
- };
+ 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);
+ err = submit(interfaces[j], data_set.type, values, 2, &timestamp);
- if (err)
- goto END;
+ if (err) goto END;
+ }
}
- }
- break;
+ break;
- case STAT_DIR_TYPE_SCALAR_INDEX:
- plugin_log(LOG_INFO, "vpp plugin: %.2f %s", res[i].scalar_value,
- res[i].name);
- break;
+ case STAT_DIR_TYPE_SCALAR_INDEX:
+ plugin_log(LOG_INFO, "vpp plugin: %.2f %s", res[i].scalar_value,
+ res[i].name);
+ break;
- case STAT_DIR_TYPE_NAME_VECTOR:
- break;
+ case STAT_DIR_TYPE_NAME_VECTOR:
+ break;
- case STAT_DIR_TYPE_ERROR_INDEX:
- break;
+ case STAT_DIR_TYPE_ERROR_INDEX:
+ break;
- default:
- plugin_log(LOG_WARNING, "vpp plugin: unknown stat type %d", res[i].type);
- break;
+ default:
+ plugin_log(LOG_WARNING, "vpp plugin: unknown stat type %d",
+ res[i].type);
+ break;
}
}
diff --git a/tests/.env b/tests/.env
index 1d40e4dea..f36c66785 100644
--- a/tests/.env
+++ b/tests/.env
@@ -9,6 +9,6 @@ TEST_VPP_MEMIF=vpp-memif
TEST_VPP_MEMIF_REPLICATION=vpp-memif-replication
# names
-RTC_PRODUCER=b002::1
+RTC_PRODUCER=b002:0:0:0:abcd::/80
RAAQM_PRODUCER=b002::2
PING_PRODUCER=b002::3
diff --git a/tests/2-nodes-hicn-light.yml b/tests/2-nodes-hicn-light.yml
index 318a5ccbd..0aee8cf5e 100644
--- a/tests/2-nodes-hicn-light.yml
+++ b/tests/2-nodes-hicn-light.yml
@@ -58,8 +58,8 @@ services:
sleep 4
- hiperf -z hicnlightng_module -D -S -R -B 4000kbps ${RTC_PRODUCER}/128
- hiperf -z hicnlightng_module -D -S ${RAAQM_PRODUCER}/128
- hicn-ping-server -z hicnlightng_module -d -s 0 -n ${PING_PRODUCER}/128
+ hiperf -q -z hicnlightng_module -S -R -B 4000kbps ${RTC_PRODUCER} -P 2 &
+ hiperf -q -z hicnlightng_module -S ${RAAQM_PRODUCER}/128 &
+ hicn-ping-server -q -z hicnlightng_module -s 0 -n ${PING_PRODUCER}/128 &
tail -f /dev/null
diff --git a/tests/2-nodes-vpp-bridge.yml b/tests/2-nodes-vpp-bridge.yml
index d9426844f..db1fa6fdc 100644
--- a/tests/2-nodes-vpp-bridge.yml
+++ b/tests/2-nodes-vpp-bridge.yml
@@ -98,10 +98,10 @@ services:
sudo vpp -c /etc/vpp/startup.conf
sleep 5
- sudo hiperf -D -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER}/128
+ sudo hiperf -q -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER} -P 2 &
sleep 1
- sudo hiperf -D -S -z memif_module ${RAAQM_PRODUCER}/128
+ sudo hiperf -q -S -z memif_module ${RAAQM_PRODUCER}/128 &
sleep 1
- sudo hicn-ping-server -d -s 0 -n ${PING_PRODUCER}/128 -z memif_module
+ sudo hicn-ping-server -q -s 0 -n ${PING_PRODUCER}/128 -z memif_module &
tail -f /dev/null
diff --git a/tests/2-nodes-vpp-memif-replication.yml b/tests/2-nodes-vpp-memif-replication.yml
index 37f028dac..45de82400 100644
--- a/tests/2-nodes-vpp-memif-replication.yml
+++ b/tests/2-nodes-vpp-memif-replication.yml
@@ -134,10 +134,10 @@ services:
sudo vpp -c /etc/vpp/startup.conf
sleep 10
- sudo hiperf -D -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER}/128
+ sudo hiperf -q -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER} -P 2 &
sleep 5
- sudo hiperf -D -S -z memif_module ${RAAQM_PRODUCER}/128
+ sudo hiperf -q -S -z memif_module ${RAAQM_PRODUCER}/128 &
sleep 5
- sudo hicn-ping-server -d -s 0 -n ${PING_PRODUCER}/128 -z memif_module
+ sudo hicn-ping-server -q -s 0 -n ${PING_PRODUCER}/128 -z memif_module &
tail -f /dev/null
diff --git a/tests/2-nodes-vpp-memif.yml b/tests/2-nodes-vpp-memif.yml
index 034437dbc..48b4a1c1d 100644
--- a/tests/2-nodes-vpp-memif.yml
+++ b/tests/2-nodes-vpp-memif.yml
@@ -107,10 +107,10 @@ services:
sudo vpp -c /etc/vpp/startup.conf
sleep 10
- sudo hiperf -D -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER}/128
+ sudo hiperf -q -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER} -P 2 &
sleep 5
- sudo hiperf -D -S -z memif_module ${RAAQM_PRODUCER}/128
+ sudo hiperf -q -S -z memif_module ${RAAQM_PRODUCER}/128 &
sleep 5
- sudo hicn-ping-server -d -s 0 -n ${PING_PRODUCER}/128 -z memif_module
+ sudo hicn-ping-server -q -s 0 -n ${PING_PRODUCER}/128 -z memif_module &
tail -f /dev/null
diff --git a/tests/Makefile b/tests/Makefile
index 6e85a717e..0f30d6a42 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -30,6 +30,6 @@ down:
functional:
sleep 1 # Wait for the forwarder to be ready
- bash config.sh test_listeners
- bash config.sh test_connections
- bash config.sh test_routes \ No newline at end of file
+ bash config.sh ctrl listeners
+ bash config.sh ctrl connections
+ bash config.sh ctrl routes \ No newline at end of file
diff --git a/tests/config.sh b/tests/config.sh
index d504b1c97..654bad518 100755
--- a/tests/config.sh
+++ b/tests/config.sh
@@ -16,7 +16,7 @@ BASE_IMAGE=${BASE_IMAGE:-hicn}
BUILD_SOFTWARE=${BUILD_SOFTWARE:-1}
set +a
-HIPERF_CMD_RTC="hiperf -n 50 -C -H -R ${RTC_PRODUCER}"
+HIPERF_CMD_RTC="hiperf -q -n 50 -C -H -R ${RTC_PRODUCER} -P 2"
HIPERF_CMD_MEMIF_RTC="${HIPERF_CMD_RTC} -z memif_module"
POSTPROCESS_COMMAND_RAAQM_RTC='tail -n +3 | \
tr -s " " | \
@@ -34,7 +34,7 @@ POSTPROCESS_COMMAND_RAAQM_RTC='tail -n +3 | \
print int(a[0]), int(a[n-1]), int(s/n) \
}"'
-HIPERF_CMD_RAAQM="hiperf -n 50 -i 200 -C -H ${RAAQM_PRODUCER}"
+HIPERF_CMD_RAAQM="hiperf -q -n 50 -i 200 -C -H ${RAAQM_PRODUCER}"
HIPERF_CMD_CBR="${HIPERF_CMD_RAAQM} -W 350 -M 0"
HIPERF_CMD_MEMIF_RAAQM="${HIPERF_CMD_RAAQM} -z memif_module"
HIPERF_CMD_MEMIF_CBR="${HIPERF_CMD_CBR} -z memif_module"
diff --git a/tests/forwarder.robot b/tests/forwarder.robot
deleted file mode 100644
index 60345dbb0..000000000
--- a/tests/forwarder.robot
+++ /dev/null
@@ -1,45 +0,0 @@
-*** Settings ***
-Library Process
-Test Template Run Test
-Test Setup Setup
-Test Teardown Teardown
-Test Timeout 5 seconds
-
-*** Variables ***
-${cmd} bash test_forwarder.sh
-
-*** Test Cases ***
-# Commands
-Add listener test_add_listener
-Remove listener test_remove_listener
-Remove non-existing listener test_remove_non_existing_listener
-Add duplicated listener test_add_duplicated_listener
-List listeners test_list_listeners
-Commands from config file test_commands_from_config
-
-# Ping
-Ping one packet test_ping_one_packet
-Ping two packets test_ping_two_packets
-Ping using CS test_ping_using_cs
-Ping using CS different order test_ping_using_cs_different_order
-Ping timeout test_ping_timeout
-Ping aggregation test_ping_aggregation
-Ping with CS store disabled test_ping_with_cs_store_disabled
-Ping with CS serve disabled test_ping_with_cs_serve_disabled
-Ping with eviction test_ping_with_eviction
-Ping with zero data lifetime test_ping_with_zero_data_lifetime
-
-*** Keywords ***
-Setup
- ${result}= Run Process ${cmd} set_up shell=True
- Log Many stdout: ${result.stdout} stderr: ${result.stderr}
-
-Teardown
- ${result}= Run Process ${cmd} tear_down shell=True
- Log Many stdout: ${result.stdout} stderr: ${result.stderr}
-
-Run Test
- [Arguments] ${test_name}
- ${result}= Run Process ${cmd} ${test_name} shell=True
- Log Many stdout: ${result.stdout} stderr: ${result.stderr}
- Should Be Equal As Integers ${result.rc} 0 \ No newline at end of file
diff --git a/tests/hiperf-local.sh b/tests/hiperf-local.sh
new file mode 100644
index 000000000..1ef11eb72
--- /dev/null
+++ b/tests/hiperf-local.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+set -eo pipefail
+
+if [[ "$(basename $(pwd))" != build* ]]; then
+ echo "Error: launch script from build dir"
+ exit 1
+fi
+
+# Stop forwarder and hiperf if already running
+sudo killall -9 hicn-light-daemon hiperf 2>/dev/null || true
+
+# Start forwarder and hiperf server in background
+ninja && sudo ./build-root/bin/hicn-light-daemon --daemon --log-file /tmp/lite_client.log >/dev/null
+./build-root/bin/hiperf -z hicnlightng_module -S b001::/16 &
+
+# Run hiperf client for 20 seconds
+sleep 1
+./build-root/bin/hiperf -z hicnlightng_module -C b001:: -W 50 -n 20
+
+# Clean up
+sudo killall -9 hicn-light-daemon hiperf
diff --git a/tests/test_forwarder.sh b/tests/test_forwarder.sh
deleted file mode 100644
index aba85d8d8..000000000
--- a/tests/test_forwarder.sh
+++ /dev/null
@@ -1,437 +0,0 @@
-#!/bin/bash
-
-############################################################################
-# CONSTANTS
-############################################################################
-INTERFACE_CMD="ip route get 1 | grep -Po '(?<=(dev )).*(?= src| proto)'"
-ADDRESS_CMD="ip route get 1 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'"
-CTRL_CMD="docker exec test-hicn \
- /hicn-build/build/build-root/bin/hicn-light-control"
-PING_SERVER_CMD="docker exec -d test-hicn \
- /hicn-build/build/build-root/bin/hicn-ping-server \
- -z hicnlightng_module"
-PING_CLIENT_CMD="docker exec test-hicn \
- /hicn-build/build/build-root/bin/hicn-ping-client \
- -z hicnlightng_module"
-PING_CLIENT_DETACHED_CMD="docker exec -d test-hicn \
- /hicn-build/build/build-root/bin/hicn-ping-client \
- -z hicnlightng_module"
-LISTENER_NAME="udp0"
-CONN_NAME="conn0"
-PREFIX="c001::/64"
-COST=1
-FIVE_SECONDS=5000
-
-############################################################################
-# UTILS
-############################################################################
-set_up() {
- docker build -t hicn-dev .
- run_forwarder
-}
-
-tear_down() {
- docker stop --time 0 test-hicn
-}
-
-get_address() {
- echo $(docker exec test-hicn sh -c "${ADDRESS_CMD}")
-}
-
-get_interface() {
- echo $(docker exec test-hicn sh -c "${INTERFACE_CMD}")
-}
-
-#---------------------------------------------------------------------------
-# Exec
-#---------------------------------------------------------------------------
-run_forwarder() {
- capacity=${1:-"100000"}
- loglevel=${2:-"trace"}
- config=${3:-""}
-
- config_file_arg=""
- if [[ $config != "" ]]; then
- config_file_arg="--config ${config}"
- fi
-
- docker run --rm -d --name test-hicn \
- -v $(pwd)/..:/hicn-build \
- -e LD_LIBRARY_PATH=/hicn-build/build/build-root/lib \
- hicn-dev \
- /hicn-build/build/build-root/bin/hicn-light-daemon \
- --log ${loglevel} --capacity ${capacity} $config_file_arg
-}
-
-exec_controller() {
- command=$1
-
- # Redirect stderr to stdout
- output=$(${CTRL_CMD} ${command} 2>&1)
- assert_exit_code
- echo ${output}
-}
-
-exec_ping_server() {
- data_lifetime=${1:-""}
-
- lifetime_arg=""
- if [[ $data_lifetime != "" ]]; then
- lifetime_arg="-l ${data_lifetime}"
- fi
-
- ${PING_SERVER_CMD} ${lifetime_arg}
-}
-
-exec_ping_client() {
- num_packets=$1
-
- output=$(${PING_CLIENT_CMD} -m ${num_packets})
- assert_exit_code
- echo ${output}
-}
-
-exec_ping_client_detached() {
- num_packets=$1
- interest_lifetime=$2
-
- ${PING_CLIENT_DETACHED_CMD} -m ${num_packets} -l ${interest_lifetime}
-}
-
-#---------------------------------------------------------------------------
-# Asserts
-#---------------------------------------------------------------------------
-assert_exit_code() {
- if [[ $? -ne 0 ]]; then
- exit_with_failure
- fi
-}
-
-assert_forwarder() {
- # Print forwarder logs for debug info
- echo "******** Forwarder Logs ********"
- docker logs test-hicn
- echo "********************************"
-
- output=$(docker logs test-hicn)
- if [[ $output == "" ]]; then
- exit_with_failure
- fi
-
- if [[ "${output}" == *"ERROR"* ]]; then
- exit_with_failure
- fi
-
- if [[ "${output}" == *"Aborted (core dumped)"* ]]; then
- exit_with_failure
- fi
-}
-
-assert_ack() {
- # Print controller logs for debug info
- echo "******** Controller Logs ********"
- echo $1
- echo "********************************"
-
- output=$1
-
- if [[ "$output" == *"Error"* ]]; then
- exit_with_failure
- fi
-}
-
-assert_nack() {
- # Print controller logs for debug info
- echo "******** Controller Logs ********"
- echo $1
- echo "********************************"
-
- output=$1
-
- if [[ "$output" != *"Error"* ]]; then
- exit_with_failure
- fi
-}
-
-assert_ping_client() {
- # Print ping client logs for debug info
- echo "******** Ping Client Logs ********"
- echo $1
- echo "********************************"
-
- ping_client_output=$1
- pkts_sent=$2
- pkts_recv=$3
- pkts_timeout=$4
-
- match_str="Sent: ${pkts_sent} Received: ${pkts_recv} Timeouts: ${pkts_timeout}"
- if [[ ! ${ping_client_output} == *"${match_str}"* ]]; then
- exit_with_failure
- fi
-}
-
-assert_forwarder_stats() {
- satisfied_from_cs=${1:-""}
- no_route_in_fib=${2:-""}
- aggregated=${3:-""}
-
- fwder_stats=$(docker logs test-hicn | grep "Forwarder: received" | tail -n 1)
-
- if [[ $satisfied_from_cs != "" &&
- "${fwder_stats}" != *"satisfied_from_cs = ${satisfied_from_cs}"* ]]; then
- exit_with_failure
- fi
-
- if [[ $no_route_in_fib != "" &&
- "${fwder_stats}" != *"no_route_in_fib = ${no_route_in_fib}"* ]]; then
- exit_with_failure
- fi
-
- if [[ $aggregated != "" &&
- "${fwder_stats}" != *"aggregated = ${aggregated}"* ]]; then
- exit_with_failure
- fi
-}
-
-assert_pkt_cache_stats() {
- total_size=${1:-""}
- pit_size=${2:-""}
- cs_size=${3:-""}
-
- pkt_cache_stats=$(docker logs test-hicn | grep "Packet cache:" | tail -n 1)
-
- if [[ $total_size != "" &&
- "${pkt_cache_stats}" != *"total size = ${total_size}"* ]]; then
- exit_with_failure
- fi
-
- if [[ $pit_size != "" &&
- "${pkt_cache_stats}" != *"PIT size = ${pit_size}"* ]]; then
- exit_with_failure
- fi
-
- if [[ $cs_size != "" &&
- "${pkt_cache_stats}" != *"CS size = ${cs_size}"* ]]; then
- exit_with_failure
- fi
-}
-
-assert_cs_stats() {
- evictions=${1:-""}
-
- cs_stats=$(docker logs test-hicn | grep "Content store:" | tail -n 1)
-
- if [[ $evictions != "" &&
- "${cs_stats}" != *"evictions = ${evictions}"* ]]; then
- exit_with_failure
- fi
-}
-
-############################################################################
-# TEST SUITE
-############################################################################
-
-#---------------------------------------------------------------------------
-# Commands
-#---------------------------------------------------------------------------
-test_add_listener() {
- # Exec hicn-light-control command and capture its output
- INTERFACE=$(get_interface)
- ADDRESS=$(get_address)
- command="add listener udp ${LISTENER_NAME} ${ADDRESS} 9695 ${INTERFACE}"
- ctrl_output=$(exec_controller "${command}")
-
- # Check hicn-light-control and hicn-light-daemon outputs
- assert_ack "$ctrl_output"
- assert_forwarder
-}
-
-test_remove_listener() {
- INTERFACE=$(get_interface)
- ADDRESS=$(get_address)
- command="add listener udp ${LISTENER_NAME} ${ADDRESS} 9695 ${INTERFACE}"
- ctrl_output=$(exec_controller "${command}")
- assert_ack "$ctrl_output"
-
- command="remove listener udp0"
- ctrl_output=$(exec_controller "${command}")
-
- assert_ack "$ctrl_output"
- assert_forwarder
-}
-
-test_remove_non_existing_listener() {
- command="remove listener udp0"
- ctrl_output=$(exec_controller "${command}")
-
- assert_nack "$ctrl_output"
- assert_forwarder
-}
-
-test_add_duplicated_listener() {
- # Exec hicn-light-control command and capture its output
- INTERFACE=$(get_interface)
- ADDRESS=$(get_address)
- command="add listener udp ${LISTENER_NAME} ${ADDRESS} 9695 ${INTERFACE}"
- exec_controller "${command}"
- ctrl_output=$(exec_controller "${command}")
-
- # Check hicn-light-control and hicn-light-daemon outputs
- assert_nack "$ctrl_output"
- assert_forwarder
-}
-
-test_list_listeners() {
- # Exec hicn-light-control command and capture its output
- command="list listener"
- ctrl_output=$(exec_controller "${command}")
-
- # Check hicn-light-control and hicn-light-daemon outputs
- assert_forwarder
- # Only the local listener should be present
- [[ "${ctrl_output}" =~ "inet4://127.0.0.1:9695" ]] && return 0 || exit_with_failure
-}
-
-test_commands_from_config() {
- # Create config file
- INTERFACE=$(get_interface)
- ADDRESS=$(get_address)
- echo "# Teset config file
- add listener udp $LISTENER_NAME $ADDRESS 9695 ${INTERFACE}
- add connection udp $CONN_NAME $ADDRESS 12345 $ADDRESS 9695 ${INTERFACE}
- add route $CONN_NAME $PREFIX $COST
- set strategy c001::/64 random
- " >forwarder.conf
-
- # Restart the forwarder specifying the config file
- tear_down
- run_forwarder "" "" "/hicn-build/tests/forwarder.conf"
- rm forwarder.conf
-
- # Check for errors in the output
- assert_forwarder
-}
-
-#---------------------------------------------------------------------------
-# Ping
-#---------------------------------------------------------------------------
-test_ping_one_packet() {
- # Exec hicn-ping-server
- exec_ping_server
- # Exec hicn-ping-client (w/ 1 packet) and capture its output
- output=$(exec_ping_client 1)
-
- # Check hicn-ping-client (1 pkt sent, 1 pkt received, 0 timeouts)
- # and hicn-light-daemon outputs
- assert_ping_client "${output}" 1 1 0
- assert_forwarder
-}
-
-test_ping_two_packets() {
- exec_ping_server
- output=$(exec_ping_client 2)
-
- assert_ping_client "${output}" 2 2 0
- assert_forwarder
-}
-
-test_ping_using_cs() {
- exec_ping_server
- exec_ping_client 2
- output=$(exec_ping_client 1)
-
- assert_ping_client "${output}" 1 1 0
- assert_forwarder
- assert_forwarder_stats 1
-}
-
-test_ping_using_cs_different_order() {
- exec_ping_server
- exec_ping_client 1
- output=$(exec_ping_client 2)
-
- assert_ping_client "${output}" 2 2 0
- assert_forwarder
- assert_forwarder_stats 1
-}
-
-test_ping_timeout() {
- # Send ping without the ping server being run
- output=$(exec_ping_client 1)
-
- assert_ping_client "${output}" 1 0 1
- assert_forwarder
- assert_forwarder_stats 0 1
-}
-
-test_ping_aggregation() {
- # Send ping without server, waiting for a reply
- exec_ping_client_detached 1 ${FIVE_SECONDS}
- exec_ping_server
- # This new ping interest will be aggregated with the previous one
- # and the forwarder will reply to both ping clients
- output=$(exec_ping_client 1)
-
- assert_ping_client "${output}" 1 1 0
- assert_forwarder
- assert_forwarder_stats "" "" 1
-}
-
-test_ping_with_cs_store_disabled() {
- command="store cache off"
- exec_controller "${command}"
-
- exec_ping_server
- exec_ping_client 1
- output=$(exec_ping_client 1)
-
- assert_ping_client "${output}" 1 1 0
- assert_forwarder
- assert_forwarder_stats 0 "" ""
- # The packet is not stored in the CS
- assert_pkt_cache_stats "" "" 0
-}
-
-test_ping_with_cs_serve_disabled() {
- command="serve cache off"
- exec_controller "${command}"
-
- exec_ping_server
- exec_ping_client 1
- output=$(exec_ping_client 1)
-
- assert_ping_client "${output}" 1 1 0
- assert_forwarder
- assert_forwarder_stats 0 "" ""
- # The packet is stored in the CS, but CS is not used
- assert_pkt_cache_stats "" "" 1
-}
-
-test_ping_with_eviction() {
- # Restart the forwarder with CS capacity = 1
- tear_down
- run_forwarder 1
-
- exec_ping_server
- exec_ping_client 1
- output=$(exec_ping_client 2)
-
- assert_ping_client "${output}" 2 2 0
- assert_forwarder
- # Check if eviction happened
- assert_cs_stats 1
- assert_pkt_cache_stats "" "" 1
-}
-
-test_ping_with_zero_data_lifetime() {
- exec_ping_server 0
- exec_ping_client 1
- output=$(exec_ping_client 1)
-
- assert_ping_client "${output}" 1 1 0
- assert_forwarder
- # The data is not taken from the CS because expired
- assert_forwarder_stats 0 "" ""
-}
-
-"$@"
diff --git a/versions.cmake b/versions.cmake
index 3bce94504..97e843298 100644
--- a/versions.cmake
+++ b/versions.cmake
@@ -5,4 +5,6 @@ set(VPP_DEFAULT_VERSION "22.02.0" "EXACT")
set(LIBMEMIF_DEFAULT_VERSION "22.02" "EXACT")
set(LIBCONFIG_DEFAULT_VERSION "1.5.0")
set(COLLECTD_DEFAULT_VERSION "5.9.2" "EXACT")
+set(RDKAFKA_DEFAULT_VERSION "1.8.2" "EXACT")
set(ANDORID_SDK_DEP_DEFAULT_VERSION "2.1.1" "EXACT")
+set(IOS_TOOLCHAIN_DEP_DEFAULT_VERSION "1.0.1" "EXACT")